alpm.c (152448B)
1 /* 2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 3 * 4 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 5 * 6 * File: alpm.c 7 * Purpose: ALPM + TCAM device dependent implementation 8 * Requires: 9 */ 10 11 /* Implementation notes: 12 */ 13 #include <shared/bsl.h> 14 15 #include <soc/mem.h> 16 #include <soc/drv.h> 17 #include <soc/debug.h> 18 #include <soc/error.h> 19 #include <soc/format.h> 20 #include <soc/lpm.h> 21 #include <soc/soc_mem_bulk.h> 22 #include <soc/trident2.h> 23 #include <soc/tomahawk.h> 24 #include <soc/tomahawk3.h> 25 #include <shared/bsl.h> 26 27 #include <shared/util.h> 28 #include <shared/l3.h> 29 30 #if defined(ALPM_ENABLE) 31 #include <soc/alpm.h> 32 33 #include <bcm/l3.h> 34 35 #include <bcm_int/esw/l3.h> 36 #include <bcm_int/esw/firebolt.h> 37 #include <bcm_int/esw/tomahawk3.h> 38 #include <bcm_int/esw/alpm.h> 39 #include <bcm_int/esw/alpm_util.h> 40 #include <bcm_int/esw/alpm_th3_acc.h> 41 42 43 #define TH3_FMT_DECLARE(fmt_name) \ 44 uint32 fmt_name##_fld = 0; \ 45 th3_fmt_##fmt_name##_t fmt_name##_fmt; 46 47 #define TH3_FMT_FIELD_CHECK(u, fmt_name, fld_name, fld_width) \ 48 do { \ 49 uint32 fld_value; \ 50 assert(fld_width <= 32); \ 51 sal_memset(&fmt_name##_fmt, 0, sizeof(fmt_name##_fmt)); \ 52 fld_value = ((sal_rand() & 0x3) << 30) | (sal_rand() << 15) | sal_rand(); \ 53 fld_value = (fld_width == 32) ? fld_value : (fld_value % (1 << fld_width)); \ 54 fmt_name##_fmt.fld_name = fld_value; \ 55 soc_format_field_get(u, fmt_name##fmt, (uint32 *)&fmt_name##_fmt, fld_name##f, &fmt_name##_fld); \ 56 if (bsl_check(bslLayerBcm, bslSourceAlpm, bslSeverityVerbose, u)) { \ 57 cli_out("FMT CHECK: %s.%s set 0x%x get 0x%x\n", SOC_FORMAT_NAME(u, fmt_name##fmt), SOC_FIELD_NAME(u, fld_name##f), fld_value, fmt_name##_fld); \ 58 } \ 59 if (fld_value != fmt_name##_fld) { \ 60 assert(0); \ 61 } \ 62 } while (0) 63 64 #define TH3_FMT_FIELD_SPLIT_CHECK(u, fmt_name, fld_name, fld_width, split_fld_name1, split_fld_width1, split_fld_name2, split_fld_width2) \ 65 do { \ 66 uint32 fld_value; \ 67 assert(fld_width == (split_fld_width1 + split_fld_width2)); \ 68 assert(fld_width <= 32); \ 69 sal_memset(&fmt_name##_fmt, 0, sizeof(fmt_name##_fmt)); \ 70 fld_value = ((sal_rand() & 0x3) << 30) | (sal_rand() << 15) | sal_rand(); \ 71 fld_value = (fld_width == 32) ? fld_value : (fld_value % (1 << fld_width)); \ 72 fmt_name##_fmt.split_fld_name1 = fld_value & ((1 << split_fld_width1) - 1); \ 73 fmt_name##_fmt.split_fld_name2 = (fld_value >> split_fld_width1) & ((1 << split_fld_width2) - 1); \ 74 soc_format_field_get(u, fmt_name##fmt, (uint32 *)&fmt_name##_fmt, fld_name##f, &fmt_name##_fld); \ 75 if (bsl_check(bslLayerBcm, bslSourceAlpm, bslSeverityVerbose, u)) { \ 76 cli_out("FMT SPLIT CHECK: %s.%s set 0x%x get 0x%x\n", SOC_FORMAT_NAME(u, fmt_name##fmt), SOC_FIELD_NAME(u, fld_name##f), fld_value, fmt_name##_fld); \ 77 } \ 78 if (fld_value != fmt_name##_fld) { \ 79 assert(0); \ 80 } \ 81 } while (0) 82 83 static void th3_fmt_test(int u) 84 { 85 sal_srand(sal_time()); 86 87 { 88 TH3_FMT_DECLARE(ASSOC_DATA_FULL); 89 TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, DEST_TYPE, 1); 90 TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, DESTINATION, 15); 91 TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, PRI, 4); 92 TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, RPE, 1); 93 TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, DST_DISCARD, 1); 94 TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, CLASS_ID, 6); 95 TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, FLEX_CTR_POOL_NUMBER, 4); 96 TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, FLEX_CTR_OFFSET_MODE, 2); 97 TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_FULL, FLEX_CTR_BASE_COUNTER_IDX, 12); 98 } 99 { 100 TH3_FMT_DECLARE(ASSOC_DATA_REDUCED); 101 TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_REDUCED, DEST_TYPE, 1); 102 TH3_FMT_FIELD_CHECK(u, ASSOC_DATA_REDUCED, DESTINATION, 15); 103 } 104 { 105 TH3_FMT_DECLARE(FIXED_DATA); 106 TH3_FMT_FIELD_CHECK(u, FIXED_DATA, SUB_DB_PRIORITY, 2); 107 } 108 { 109 TH3_FMT_DECLARE(L3_DEFIP_TCAM_KEY); 110 TH3_FMT_FIELD_CHECK(u, L3_DEFIP_TCAM_KEY, KEY_MODE, 2); 111 TH3_FMT_FIELD_CHECK(u, L3_DEFIP_TCAM_KEY, KEY_TYPE, 1); 112 TH3_FMT_FIELD_SPLIT_CHECK(u, L3_DEFIP_TCAM_KEY, IP_ADDR, 32, IP_ADDR_0_28, 29, IP_ADDR_29_31, 3); 113 TH3_FMT_FIELD_CHECK(u, L3_DEFIP_TCAM_KEY, VRF_ID, 12); 114 } 115 { 116 TH3_FMT_DECLARE(ALPM1_DATA); 117 TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, DEFAULT_MISS, 1); 118 TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, DIRECT_ROUTE, 1); 119 TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, BKT_PTR, 10); 120 TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, KSHIFT, 7); 121 TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, ROFS, 3); 122 TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, FMT0, 4); 123 TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, FMT1, 4); 124 TH3_FMT_FIELD_SPLIT_CHECK(u, ALPM1_DATA, FMT2, 4, FMT2_0_1, 2, FMT2_2_3, 2); 125 TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, FMT3, 4); 126 TH3_FMT_FIELD_CHECK(u, ALPM1_DATA, FMT4, 4); 127 } 128 { 129 TH3_FMT_DECLARE(ALPM2_DATA); 130 TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, DEFAULT_MISS, 1); 131 TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, BKT_PTR, 13); 132 TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, KSHIFT, 7); 133 TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, ROFS, 3); 134 TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT0, 4); 135 TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT1, 4); 136 TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT2, 4); 137 TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT3, 4); 138 TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT4, 4); 139 TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT5, 4); 140 TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT6, 4); 141 TH3_FMT_FIELD_CHECK(u, ALPM2_DATA, FMT7, 4); 142 } 143 } 144 145 #define TH3_MEM_DECLARE(mem_name) \ 146 uint32 mem_name##_fld = 0; \ 147 th3_mem_##mem_name##_t mem_name##_mem; 148 149 #define TH3_MEM_FIELD_CHECK(u, mem_name, fld_name, fld_width) \ 150 do { \ 151 uint32 fld_value; \ 152 assert(fld_width <= 32); \ 153 sal_memset(&mem_name##_mem, 0, sizeof(mem_name##_mem)); \ 154 fld_value = ((sal_rand() & 0x3) << 30) | (sal_rand() << 15) | sal_rand(); \ 155 fld_value = (fld_width == 32) ? fld_value : (fld_value % (1 << fld_width)); \ 156 mem_name##_mem.fld_name = fld_value; \ 157 soc_mem_field_get(u, mem_name##m, (uint32 *)&mem_name##_mem, fld_name##f, &mem_name##_fld); \ 158 if (bsl_check(bslLayerBcm, bslSourceAlpm, bslSeverityVerbose, u)) { \ 159 cli_out("MEM CHECK: %s.%s set 0x%x get 0x%x\n", SOC_MEM_NAME(u, mem_name##m), SOC_FIELD_NAME(u, fld_name##f), fld_value, mem_name##_fld); \ 160 } \ 161 if (fld_value != mem_name##_fld) { \ 162 assert(0); \ 163 } \ 164 } while (0) 165 166 #define TH3_MEM_FIELD_SPLIT_CHECK(u, mem_name, fld_name, fld_width, split_fld_name1, split_fld_width1, split_fld_name2, split_fld_width2) \ 167 do { \ 168 uint32 fld_value; \ 169 assert(fld_width == (split_fld_width1 + split_fld_width2)); \ 170 assert(fld_width <= 32); \ 171 sal_memset(&mem_name##_mem, 0, sizeof(mem_name##_mem)); \ 172 fld_value = ((sal_rand() & 0x3) << 30) | (sal_rand() << 15) | sal_rand(); \ 173 fld_value = (fld_width == 32) ? fld_value : (fld_value % (1 << fld_width)); \ 174 mem_name##_mem.split_fld_name1 = fld_value & ((1 << split_fld_width1) - 1); \ 175 mem_name##_mem.split_fld_name2 = (fld_value >> split_fld_width1) & ((1 << split_fld_width2) - 1); \ 176 soc_mem_field_get(u, mem_name##m, (uint32 *)&mem_name##_mem, fld_name##f, &mem_name##_fld); \ 177 if (bsl_check(bslLayerBcm, bslSourceAlpm, bslSeverityVerbose, u)) { \ 178 cli_out("MEM SPLIT CHECK: %s.%s set 0x%x get 0x%x\n", SOC_MEM_NAME(u, mem_name##m), SOC_FIELD_NAME(u, fld_name##f), fld_value, mem_name##_fld); \ 179 } \ 180 if (fld_value != mem_name##_fld) { \ 181 assert(0); \ 182 } \ 183 } while (0) 184 185 static void th3_mem_test(int u) 186 { 187 sal_srand(sal_time()); 188 189 { 190 TH3_MEM_DECLARE(ING_L3_NEXT_HOP); 191 TH3_MEM_FIELD_CHECK(u, ING_L3_NEXT_HOP, VLAN_ID, 12); 192 TH3_MEM_FIELD_CHECK(u, ING_L3_NEXT_HOP, PORT_NUM, 8); 193 TH3_MEM_FIELD_CHECK(u, ING_L3_NEXT_HOP, COPY_TO_CPU, 1); 194 TH3_MEM_FIELD_CHECK(u, ING_L3_NEXT_HOP, DROP, 1); 195 TH3_MEM_FIELD_CHECK(u, ING_L3_NEXT_HOP, ENTRY_TYPE, 2); 196 TH3_MEM_FIELD_CHECK(u, ING_L3_NEXT_HOP, T, 1); 197 } 198 { 199 TH3_MEM_DECLARE(EGR_L3_NEXT_HOP); 200 TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, ENTRY_TYPE, 2); 201 TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, L3__CLASS_ID, 7); 202 TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, IFP_ACTIONS__L3_UC_DA_DISABLE, 1); 203 TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, IFP_ACTIONS__L3_UC_SA_DISABLE, 1); 204 TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, IFP_ACTIONS__L3_UC_TTL_DISABLE, 1); 205 TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, IFP_ACTIONS__L3_UC_VLAN_DISABLE, 1); 206 207 TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, L3__L3_UC_DA_DISABLE, 1); 208 TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, L3__L3_UC_SA_DISABLE, 1); 209 TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, L3__L3_UC_TTL_DISABLE, 1); 210 TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, L3__L3_UC_VLAN_DISABLE, 1); 211 TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP, MPLS__MAC_DA_PROFILE_INDEX, 9); 212 TH3_MEM_FIELD_SPLIT_CHECK(u, EGR_L3_NEXT_HOP, MPLS__MPLS_LABEL, 20, MPLS__MPLS_LABEL_0_1, 2, MPLS__MPLS_LABEL_2_19, 18); 213 } 214 { 215 TH3_MEM_DECLARE(EGR_L3_NEXT_HOP_2); 216 TH3_MEM_FIELD_CHECK(u, EGR_L3_NEXT_HOP_2, INTF_NUM, 13); 217 } 218 } 219 220 /* Default FMT */ 221 #define ALPM_FMT_DEF_PVT_REDUCED (1) 222 #define ALPM_FMT_DEF_PVT_FULL (6) 223 #define ALPM_FMT_DEF_RTE_REDUCED (1) 224 #define ALPM_FMT_DEF_RTE_FULL (10) 225 226 static _alpm_fmt_info_t th3_fmt_info[ALPM_FMT_CNT + 1] = { 227 { 228 ALPM_FMT_PVT, 229 8, /* 8 different formats(PIVOT FORMAT) */ 230 { /* For fmt_ent_max */ 231 0, /* FMT=0, means we cannot put entry in this format */ 232 6, /* allow 6 entires in PIVOT FMT1 */ 233 5, 234 4, 235 3, 236 2, 237 4, 238 3, 239 2, /* allow 2 entries in PIVOT FMT8 */ 240 0, 241 0, 242 0, 243 0 244 }, 245 { /* For fmt_pfx_len */ 246 0, 247 7, /* PIVOT FMT1 */ 248 23, 249 47, 250 87, 251 128, 252 17, 253 57, 254 128,/* PIVOT FMT8 */ 255 0, 256 0, 257 0, 258 0 259 }, 260 { /* fmt_bnk */ 261 INVALIDfmt, 262 L3_DEFIP_ALPM_PIVOT_FMT1_FULLfmt, 263 L3_DEFIP_ALPM_PIVOT_FMT2_FULLfmt, 264 L3_DEFIP_ALPM_PIVOT_FMT3_FULLfmt, 265 L3_DEFIP_ALPM_PIVOT_FMT4_FULLfmt, 266 L3_DEFIP_ALPM_PIVOT_FMT5_FULLfmt, 267 L3_DEFIP_ALPM_PIVOT_FMT6_FULLfmt, 268 L3_DEFIP_ALPM_PIVOT_FMT7_FULLfmt, 269 L3_DEFIP_ALPM_PIVOT_FMT8_FULLfmt, 270 INVALIDfmt, 271 INVALIDfmt, 272 INVALIDfmt, 273 INVALIDfmt 274 }, 275 { /* fmt_ent */ 276 INVALIDfmt, 277 L3_DEFIP_ALPM_PIVOT_FMT1fmt, 278 L3_DEFIP_ALPM_PIVOT_FMT2fmt, 279 L3_DEFIP_ALPM_PIVOT_FMT3fmt, 280 L3_DEFIP_ALPM_PIVOT_FMT4fmt, 281 L3_DEFIP_ALPM_PIVOT_FMT5fmt, 282 L3_DEFIP_ALPM_PIVOT_FMT6fmt, 283 L3_DEFIP_ALPM_PIVOT_FMT7fmt, 284 L3_DEFIP_ALPM_PIVOT_FMT8fmt, 285 INVALIDfmt, 286 INVALIDfmt, 287 INVALIDfmt, 288 INVALIDfmt 289 }, 290 {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, 291 }, /* PIVOT fmt info */ 292 { 293 ALPM_FMT_RTE, 294 12, /* 12 different formats(ROUTE FORMAT) */ 295 { /* For fmt_ent_max */ 296 0, /* FMT=0, means we cannot put entry in this format */ 297 15, /* allow 15 entires in ROUTE FMT1 */ 298 12, 299 10, 300 8, 301 7, 302 6, 303 5, 304 4, 305 3, 306 6, 307 4, 308 2 /* allow 2 entries in ROUTE FMT12 */ 309 }, 310 { /* For fmt_pfx_len */ 311 0, 312 15, /* ROUTE FMT1 */ 313 23, 314 31, 315 39, 316 47, 317 63, 318 79, 319 103, 320 128, 321 33, 322 73, 323 128 /* ROUTE FMT12 */ 324 }, 325 { /* fmt_bnk */ 326 INVALIDfmt, 327 L3_DEFIP_ALPM_ROUTE_FMT1_FULLfmt, 328 L3_DEFIP_ALPM_ROUTE_FMT2_FULLfmt, 329 L3_DEFIP_ALPM_ROUTE_FMT3_FULLfmt, 330 L3_DEFIP_ALPM_ROUTE_FMT4_FULLfmt, 331 L3_DEFIP_ALPM_ROUTE_FMT5_FULLfmt, 332 L3_DEFIP_ALPM_ROUTE_FMT6_FULLfmt, 333 L3_DEFIP_ALPM_ROUTE_FMT7_FULLfmt, 334 L3_DEFIP_ALPM_ROUTE_FMT8_FULLfmt, 335 L3_DEFIP_ALPM_ROUTE_FMT9_FULLfmt, 336 L3_DEFIP_ALPM_ROUTE_FMT10_FULLfmt, 337 L3_DEFIP_ALPM_ROUTE_FMT11_FULLfmt, 338 L3_DEFIP_ALPM_ROUTE_FMT12_FULLfmt 339 }, 340 { /* fmt_ent */ 341 INVALIDfmt, 342 L3_DEFIP_ALPM_ROUTE_FMT1fmt, 343 L3_DEFIP_ALPM_ROUTE_FMT2fmt, 344 L3_DEFIP_ALPM_ROUTE_FMT3fmt, 345 L3_DEFIP_ALPM_ROUTE_FMT4fmt, 346 L3_DEFIP_ALPM_ROUTE_FMT5fmt, 347 L3_DEFIP_ALPM_ROUTE_FMT6fmt, 348 L3_DEFIP_ALPM_ROUTE_FMT7fmt, 349 L3_DEFIP_ALPM_ROUTE_FMT8fmt, 350 L3_DEFIP_ALPM_ROUTE_FMT9fmt, 351 L3_DEFIP_ALPM_ROUTE_FMT10fmt, 352 L3_DEFIP_ALPM_ROUTE_FMT11fmt, 353 L3_DEFIP_ALPM_ROUTE_FMT12fmt 354 }, 355 {0, 356 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1}, 357 }, /* ROUTE fmt info */ 358 { 359 ALPM_FMT_CNT, 360 0, /* 0 different formats */ 361 { /* For fmt_ent_max */ 362 0, /* FMT=0, means we cannot put entry in this format */ 363 0, 364 0, 365 0, 366 0, 367 0, 368 0, 369 0, 370 0, 371 0, 372 0, 373 0, 374 0 375 }, 376 { /* For fmt_pfx_len */ 377 0, 378 0, 379 0, 380 0, 381 0, 382 0, 383 0, 384 0, 385 0, 386 0, 387 0, 388 0, 389 0 390 }, 391 { /* fmt_bnk */ 392 INVALIDfmt, 393 INVALIDfmt, 394 INVALIDfmt, 395 INVALIDfmt, 396 INVALIDfmt, 397 INVALIDfmt, 398 INVALIDfmt, 399 INVALIDfmt, 400 INVALIDfmt, 401 INVALIDfmt, 402 INVALIDfmt, 403 INVALIDfmt, 404 INVALIDfmt 405 }, 406 { /* fmt_ent */ 407 INVALIDfmt, 408 INVALIDfmt, 409 INVALIDfmt, 410 INVALIDfmt, 411 INVALIDfmt, 412 INVALIDfmt, 413 INVALIDfmt, 414 INVALIDfmt, 415 INVALIDfmt, 416 INVALIDfmt, 417 INVALIDfmt, 418 INVALIDfmt, 419 INVALIDfmt 420 }, 421 {0, 422 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 423 }, 424 }; 425 426 soc_field_t th3_alpm_ent_fld[] = { 427 ENTRY_0f, ENTRY_1f, ENTRY_2f, ENTRY_3f, 428 ENTRY_4f, ENTRY_5f, ENTRY_6f, ENTRY_7f, 429 ENTRY_8f, ENTRY_9f, ENTRY_10f,ENTRY_11f, 430 ENTRY_12f,ENTRY_13f,ENTRY_14f,ENTRY_15f, 431 }; 432 433 soc_field_t th3_alpm_bnk_fld[] = { 434 FMT0f, FMT1f, FMT2f, FMT3f, 435 FMT4f, FMT5f, FMT6f, FMT7f 436 }; 437 438 static soc_mem_t th3_alpm_hit_tbl_mem[] = { 439 L3_DEFIP_ALPM_LEVEL2_HIT_ONLYm, 440 L3_DEFIP_ALPM_LEVEL3_HIT_ONLYm 441 }; 442 443 /* Should be the same order as _alpm_tbl_t */ 444 static soc_mem_t th3_alpm_tbl[] = { 445 INVALIDm, 446 L3_DEFIP_LEVEL1m, 447 L3_DEFIP_LEVEL1m, 448 L3_DEFIP_PAIR_LEVEL1m, 449 L3_DEFIP_PAIR_LEVEL1m, 450 L3_DEFIP_ALPM_LEVEL2m, 451 L3_DEFIP_ALPM_LEVEL2m, 452 L3_DEFIP_ALPM_LEVEL2m, 453 L3_DEFIP_ALPM_LEVEL2m, 454 L3_DEFIP_ALPM_LEVEL3m, 455 L3_DEFIP_ALPM_LEVEL3m, 456 L3_DEFIP_ALPM_LEVEL3m, 457 INVALIDm 458 }; 459 460 static soc_mem_t *alpm_tbl; 461 462 /* Combined mode Level2 Table */ 463 static _alpm_bkt_pool_conf_t th3_alpm_cmode_pool_l2 = { 464 {NULL, NULL}, /* bnk_info, to be allocated */ 465 5120, /* 5 Banks x 1K buckets */ 466 5, /* 5 Banks per bucket */ 467 alpmTblBktCmodeL2, 468 1, /* Wrap around bucket */ 469 0, /* Not Fixed FMT */ 470 NULL, 471 &th3_fmt_info[ALPM_FMT_PVT], 472 }; 473 474 /* Combined mode Level3 Table */ 475 static _alpm_bkt_pool_conf_t th3_alpm_cmode_pool_l3 = { 476 {NULL, NULL}, /* bnk_info, to be allocated */ 477 65536, /* 8 Banks x 8K buckets */ 478 8, /* 8 Banks per bucket */ 479 alpmTblBktCmodeL3, 480 1, 481 0, /* Not Fixed FMT */ 482 NULL, 483 &th3_fmt_info[ALPM_FMT_RTE], 484 }; 485 486 /* Parallel mode Level2 Table pool for Global Routes */ 487 static _alpm_bkt_pool_conf_t th3_alpm_pmode_pool_gbl_l2 = { 488 {NULL, NULL}, /* bnk_info, to be allocated */ 489 2048, /* 2 Banks x 1K buckets */ 490 2, /* 2 Banks per bucket */ 491 alpmTblBktPmodeGblL2, 492 1, 493 0, /* Not Fixed FMT */ 494 NULL, 495 &th3_fmt_info[ALPM_FMT_PVT], 496 }; 497 498 /* Parallel mode Level2 Table pool for Private Routes */ 499 static _alpm_bkt_pool_conf_t th3_alpm_pmode_pool_prt_l2 = { 500 {NULL, NULL}, /* bnk_info, to be allocated */ 501 3072, /* 3 Banks x 1K buckets */ 502 3, /* 3 Banks per bucket */ 503 alpmTblBktPmodePrtL2, 504 1, 505 0, /* Not Fixed FMT */ 506 NULL, 507 &th3_fmt_info[ALPM_FMT_PVT], 508 }; 509 510 /* Parallel mode Level3 Table pool for Global Routes */ 511 static _alpm_bkt_pool_conf_t th3_alpm_pmode_pool_gbl_l3 = { 512 {NULL, NULL}, /* bnk_info, to be allocated */ 513 32768, /* 4 Banks x 8K buckets */ 514 4, /* 4 Banks per bucket */ 515 alpmTblBktPmodeGblL3, 516 1, 517 0, /* Not Fixed FMT */ 518 NULL, 519 &th3_fmt_info[ALPM_FMT_RTE], 520 }; 521 522 /* Parallel mode Level3 Table pool for Private Routes */ 523 static _alpm_bkt_pool_conf_t th3_alpm_pmode_pool_prt_l3 = { 524 {NULL, NULL}, /* bnk_info, to be allocated */ 525 32768, /* 4 Banks x 8K buckets */ 526 4, /* 4 Banks per bucket */ 527 alpmTblBktPmodePrtL3, 528 1, 529 0, /* Not Fixed FMT */ 530 NULL, 531 &th3_fmt_info[ALPM_FMT_RTE], 532 }; 533 534 static _alpm_bkt_pool_conf_t *th3_alpm_pool0_l2[SOC_MAX_NUM_DEVICES] = {NULL}; 535 static _alpm_bkt_pool_conf_t *th3_alpm_pool1_l2[SOC_MAX_NUM_DEVICES] = {NULL}; 536 static _alpm_bkt_pool_conf_t *th3_alpm_pool0_l3[SOC_MAX_NUM_DEVICES] = {NULL}; 537 static _alpm_bkt_pool_conf_t *th3_alpm_pool1_l3[SOC_MAX_NUM_DEVICES] = {NULL}; 538 539 static _alpm_cb_t th3_alpm_1cb_template = { 540 0, /* Unit */ 541 { 542 NULL, /* pvt_ctl[V4] */ 543 NULL, /* pvt_ctl[V6] */ 544 }, 545 { /* Pivot Tables of this block */ 546 alpmTblPvtCmodeL1, 547 alpmTblPvtCmodeL1, 548 alpmTblInvalid 549 }, 550 { /* _alpm_bnk_conf_t */ 551 {NULL, NULL}, /* bnk_pool pointer */ 552 10, /* 1K buckets = 10 bits */ 553 0, /* Single Wide */ 554 5, /* 5 physical banks per bucket */ 555 3, /* 3 bits */ 556 }, 557 0 /* Block 0 */ 558 }; 559 560 static _alpm_cb_t th3_alpm_1cb_template_128b = { 561 0, /* Unit */ 562 { 563 NULL, /* pvt_ctl[V4] */ 564 NULL, /* pvt_ctl[V6] */ 565 }, 566 { /* Pivot Tables of this block */ 567 alpmTblPvtCmodeL1, 568 alpmTblPvtCmodeL1P128, 569 alpmTblPvtCmodeL1P128 570 }, 571 { /* _alpm_bnk_conf_t */ 572 {NULL, NULL}, /* bnk_pool pointer */ 573 10, /* 1K buckets = 10 bits */ 574 0, /* Single Wide */ 575 5, /* 5 physical banks per bucket */ 576 3, /* 3 bits */ 577 }, 578 0 /* Block 0 */ 579 }; 580 581 static _alpm_cb_t th3_alpm_2cb_template_p0 = { 582 0, /* Unit */ 583 { 584 NULL, /* pvt_ctl[V4] */ 585 NULL, /* pvt_ctl[V6] */ 586 }, 587 { /* Pivot Tables of this block */ 588 alpmTblPvtCmodeL1, 589 alpmTblPvtCmodeL1, 590 alpmTblInvalid 591 }, 592 { /* _alpm_bnk_conf_t */ 593 {NULL, NULL}, /* bnk_pool pointer */ 594 10, /* 1K buckets = 10 bits */ 595 0, /* Single Wide */ 596 5, /* 5 physical banks per bucket */ 597 3, /* 3 bits */ 598 }, 599 0 /* ALPM block 0 */ 600 }; 601 602 static _alpm_cb_t th3_alpm_2cb_template_p0_128b = { 603 0, /* Unit */ 604 { 605 NULL, /* pvt_ctl[V4] */ 606 NULL, /* pvt_ctl[V6] */ 607 }, 608 { /* Pivot Tables of this block */ 609 alpmTblPvtCmodeL1, 610 alpmTblPvtCmodeL1P128, 611 alpmTblPvtCmodeL1P128 612 }, 613 { /* _alpm_bnk_conf_t */ 614 {NULL, NULL}, /* bnk_pool pointer */ 615 10, /* 1K buckets = 10 bits */ 616 0, /* Single Wide */ 617 5, /* 5 physical banks per bucket */ 618 3, /* 3 bits */ 619 }, 620 0 /* Block 0 */ 621 }; 622 623 static _alpm_cb_t th3_alpm_2cb_template_p1 = { 624 0, /* Unit */ 625 { 626 NULL, /* pvt_ctl[V4] */ 627 NULL, /* pvt_ctl[V6] */ 628 }, 629 { /* Pivot Tables of this block */ 630 alpmTblInvalid, 631 alpmTblInvalid, 632 alpmTblInvalid 633 }, 634 { /* _alpm_bnk_conf_t */ 635 {NULL, NULL}, /* bnk_pool pointer */ 636 13, /* 8K buckets = 13 bits */ 637 0, /* Single Wide */ 638 8, /* 8 physical banks per bucket */ 639 3, /* 3 bits */ 640 }, 641 1 /* Block 1 */ 642 }; 643 644 /* local used functions */ 645 int th3_alpm_bkt_hit_write(int u, int vrf_id, _alpm_cb_t *acb, 646 _alpm_tbl_t tbl, int ent_idx, int hit_val); 647 int th3_alpm_ent_hit_move(int u, int vrf_id, _alpm_cb_t *acb, 648 int src_ent_idx, int dst_ent_idx); 649 int th3_alpm_bnk_hit_move(int u, int vrf_id, _alpm_cb_t *acb, 650 int src_idx, int dst_idx); 651 int th3_alpm_bnk_hit_clear(int u, int vrf_id, _alpm_cb_t *acb, int idx); 652 int8 th3_alpm_bnk_fmt_get(int u, _alpm_cb_t *acb, _alpm_bkt_info_t *bkt_info, 653 int ent_idx); 654 int th3_alpm_table_dump_3level(int u, soc_mem_t mem, int idx, int sub_idx, 655 int lvl_cnt, int flags); 656 657 /* TH3 ALPM mis-fowarding check for memory write */ 658 int 659 th3_mem_write_check(int u, soc_mem_t mem, int phy_index, void *entry) 660 { 661 static int tot_err = 0; /* 0 for invalid hw route check */ 662 int rv = BCM_E_NONE; 663 664 if (ALPMTR_SANITY_EN(u) && ALPMTR_CNT(u) == ALPMTR_SANITY_START(u)) { 665 if (mem == L3_DEFIP_ALPM_LEVEL2m || (mem == L3_DEFIP_ALPM_LEVEL3m)) { 666 cli_out("w %s %d 1 ", SOC_MEM_NAME(u, mem), phy_index); 667 soc_mem_entry_dump(u, mem, entry, BSL_LSS_CLI); 668 } else { 669 cli_out("mod %s %d 1 ", SOC_MEM_NAME(u, mem), phy_index); 670 soc_mem_entry_dump_if_changed(u, mem, entry, ""); 671 th3_alpm_table_dump_3level(u, mem, phy_index, 0, 3, 0); 672 } 673 if (!tot_err && mem != L3_DEFIP_ALPM_LEVEL3m) { 674 (void)alpm_pfx_hw_route_sanity(u, &tot_err); 675 } 676 } 677 return rv; 678 } 679 680 static int 681 th3_mem_phy_index_get(int u, _alpm_cb_t *acb, _alpm_tbl_t tbl, int index) 682 { 683 int phy_index; 684 /* Remapping index for actual memory in Parallel/Mixed mode */ 685 switch (tbl) { 686 case alpmTblBktPmodeGblL2: 687 case alpmTblBktPmodeGblL3: 688 phy_index = index + ACB_BNK_PER_BKT(acb, 1) * ACB_BKT_CNT(acb); 689 break; 690 default: 691 phy_index = index; 692 break; 693 } 694 695 if (ACB_HLF_BNK_MD(acb)) { 696 phy_index += (1 << ACB_BNK_BITS(acb)) * ACB_BKT_CNT(acb); 697 } 698 699 return phy_index; 700 } 701 702 int 703 th3_mem_read(int u, _alpm_cb_t *acb, _alpm_tbl_t tbl, 704 int index, void *entry_data, int no_cache) 705 { 706 int rv = BCM_E_NONE; 707 soc_mem_t mem; 708 709 mem = alpm_tbl[tbl]; 710 index = th3_mem_phy_index_get(u, acb, tbl, index); 711 if (no_cache && !(ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_WRITE_CACHE_ONLY)) { 712 rv = soc_mem_read_no_cache(u, 0, mem, 0, MEM_BLOCK_ANY, 713 index, entry_data); 714 } else { 715 rv = soc_mem_read(u, mem, MEM_BLOCK_ANY, index, entry_data); 716 } 717 if (BCM_SUCCESS(rv)) { 718 acb->acb_cnt.c_mem[tbl][0]++; 719 } 720 721 return rv; 722 } 723 724 int 725 th3_mem_write(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, 726 _alpm_tbl_t tbl, int index, void *entry_data) 727 { 728 int rv = BCM_E_NONE; 729 int phy_index; 730 soc_mem_t mem; 731 void *entry = entry_data; 732 733 mem = alpm_tbl[tbl]; 734 if (entry == NULL) { 735 entry = soc_mem_entry_null(u, mem); 736 } 737 738 phy_index = th3_mem_phy_index_get(u, acb, tbl, index); 739 if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_WRITE_CACHE_ONLY) { 740 _soc_mem_alpm_write_cache(u, mem, MEM_BLOCK_ALL, phy_index, entry); 741 } else { 742 rv = soc_mem_write(u, mem, MEM_BLOCK_ALL, phy_index, entry); 743 744 /* Mis-forwarding check 745 (void)th3_mem_write_check(u, mem, phy_index, entry); */ 746 } 747 748 if (BCM_SUCCESS(rv)) { 749 acb->acb_cnt.c_mem[tbl][1]++; 750 if (pvt_node != NULL) { 751 if (entry_data != NULL) { 752 ACB_PVT_PTR(acb, pvt_node, index) = pvt_node; 753 } else { 754 ACB_PVT_PTR(acb, pvt_node, index) = NULL; 755 } 756 } 757 } 758 759 return rv; 760 } 761 762 int 763 th3_mem_bulk_write(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, 764 _alpm_tbl_t tbl, int *index, uint32 **entry_data, int count) 765 { 766 int i; 767 int phy_index[20]; /* 20 = Local max count */ 768 int copyno[20]; 769 soc_mem_t mem; 770 soc_mem_t bulk_mem[20]; 771 int rv = BCM_E_NONE; 772 773 assert(count <= 20); 774 775 mem = alpm_tbl[tbl]; 776 for (i = 0; i < count; i++) { 777 phy_index[i] = th3_mem_phy_index_get(u, acb, tbl, index[i]); 778 copyno[i] = MEM_BLOCK_ALL; 779 bulk_mem[i] = mem; 780 } 781 782 if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_WRITE_CACHE_ONLY) { 783 for (i = 0; i < count; i++) { 784 _soc_mem_alpm_write_cache(u, mem, MEM_BLOCK_ALL, phy_index[i], 785 entry_data[i]); 786 } 787 } else { 788 if (count <= ALPMC(u)->_alpm_bulk_wr_threshold || 789 SAL_BOOT_PLISIM || SAL_BOOT_BCMSIM) { 790 for (i = 0; i < count; i++) { 791 rv = soc_mem_write(u, mem, MEM_BLOCK_ALL, phy_index[i], 792 entry_data[i]); 793 794 /* Mis-forwarding check 795 (void)th3_mem_write_check(u, mem, phy_index[i], entry_data[i]); */ 796 797 ALPM_IER(rv); 798 } 799 } else { 800 rv = soc_mem_bulk_write(u, bulk_mem, phy_index, copyno, 801 entry_data, count); 802 } 803 } 804 805 if (BCM_SUCCESS(rv)) { 806 for (i = 0; i < count; i++) { 807 acb->acb_cnt.c_mem[tbl][1]++; 808 if (pvt_node != NULL) { 809 ACB_PVT_PTR(acb, pvt_node, index[i]) = pvt_node; 810 } 811 } 812 } 813 814 return rv; 815 } 816 817 /* ALPM related functions */ 818 819 static int 820 th3_alpm_cb_cnt(int u) 821 { 822 int acb_cnt, alpm_enable, alpm_level; 823 alpm_enable = soc_property_get(u, spn_L3_ALPM_ENABLE, 2); 824 alpm_level = soc_property_get(u, "l3_alpm2_level", 3); 825 826 if (alpm_enable) { 827 acb_cnt = alpm_level - 1; /* 1 or 2 ALPM Control Blocks */ 828 if (acb_cnt < 1) { 829 acb_cnt = ALPM_CB_CNT; 830 } 831 } else { 832 acb_cnt = 0; /* 0 ALPM Control Block */ 833 } 834 835 if (acb_cnt > ALPM_CB_CNT) { 836 acb_cnt = ALPM_CB_CNT; 837 } 838 839 return acb_cnt; 840 } 841 842 void 843 th3_alpm_ctrl_deinit(int u) 844 { 845 int i, j, pid, ipt, acb_cnt; 846 _alpm_cb_t *acb; 847 848 acb_cnt = th3_alpm_cb_cnt(u); 849 for (i = 0; i < acb_cnt; i++) { 850 acb = ACB(u, i); 851 if (acb != NULL) { 852 /* Free Bucket pool */ 853 for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) { 854 _alpm_bkt_pool_conf_t *bp_conf; 855 856 bp_conf = ACB_BKT_POOL(acb, pid); 857 if (bp_conf->pvt_ptr != NULL) { 858 alpm_util_free(bp_conf->pvt_ptr); 859 bp_conf->pvt_ptr = NULL; 860 } 861 862 for (ipt = ALPM_IPT_V4; ipt < ALPM_IPT_CNT; ipt++) { 863 if (ipt > ALPM_IPT_V4 && 864 BPC_BNK_INFO(bp_conf, ipt) == 865 BPC_BNK_INFO(bp_conf, ipt - 1)) { 866 continue; 867 } 868 if (BPC_BNK_INFO(bp_conf, ipt) != NULL) { 869 alpm_util_free(BPC_BNK_INFO(bp_conf, ipt)); 870 } 871 } 872 for (ipt = ALPM_IPT_V4; ipt < ALPM_IPT_CNT; ipt++) { 873 BPC_BNK_INFO(bp_conf, ipt) = NULL; 874 } 875 } 876 877 for (j = 0; j < ALPM_IPT_CNT; j++) { 878 if (acb->pvt_ctl[j] != NULL) { 879 alpm_util_free(acb->pvt_ctl[j]); 880 acb->pvt_ctl[j] = NULL; 881 } 882 } 883 884 alpm_util_free(acb); 885 ACB(u, i) = NULL; 886 } 887 } 888 889 alpm_util_free(th3_alpm_pool0_l2[u]); 890 th3_alpm_pool0_l2[u] = NULL; 891 alpm_util_free(th3_alpm_pool1_l2[u]); 892 th3_alpm_pool1_l2[u] = NULL; 893 alpm_util_free(th3_alpm_pool0_l3[u]); 894 th3_alpm_pool0_l3[u] = NULL; 895 alpm_util_free(th3_alpm_pool1_l3[u]); 896 th3_alpm_pool1_l3[u] = NULL; 897 898 return ; 899 } 900 901 /* Adjust config based on dynamic configuration */ 902 /* 903 * Matrix of fmt_info usage: 904 * --------------------------------------------------------------- 905 * | Lvl_cnt | Banks | ALPM_mode | DB_type | Cur_lvl | fmt_type | 906 * --------------------------------------------------------------- 907 * | 2 | 5 | Combined | DB0(P,G)| 2 | RTE | 908 * | 2 | 5 | Parallel | DB0(P) | 2 | RTE | 909 * | 2 | 5 | Parallel | DB1(G) | 2 | RTE | 910 * | 2 | 5 | Mixed | DB0(G) | 2 | RTE | 911 * | 2 | 5 | Mixed | DB1(G) | N/A | N/A | 912 * --------------------------------------------------------------- 913 * | 3 | 4/8 | Combined | DB0(P,G)| 2 | PVT | 914 * | 3 | 4/8 | Combined | DB0(P,G)| 3 | RTE | 915 * | 3 | 4 | Parallel | DB0(P) | 2 | PVT | 916 * | 3 | 4 | Parallel | DB0(P) | 3 | RTE | 917 * | 3 | 4 | Parallel | DB1(G) | 2 | RTE* | 918 * | 3 | 8 | Parallel | DB0(P) | 2 | PVT | 919 * | 3 | 8 | Parallel | DB0(P) | 3 | RTE | 920 * | 3 | 8 | Parallel | DB1(G) | 2 | PVT | 921 * | 3 | 8 | Parallel | DB1(G) | 3 | RTE | 922 * | 3 | 4/8 | Mixed | DB0(P) | 2 | PVT | 923 * | 3 | 4/8 | Mixed | DB0(P) | 3 | RTE | 924 * | 3 | 4/8 | Mixed | DB1(G) | N/A | N/A | 925 * --------------------------------------------------------------- 926 * 927 * if (Cur_lvl == Lvl_cnt) { 928 * fmt_type = RTE; 929 * } else { 930 * if (levels(DB) == (Lvl_cnt - 1)) { 931 * e.g.: (Banks==4 && Parallel && DB1) 932 * fmt_type = RTE; 933 * } else { 934 * fmt_type = PVT; 935 * } 936 * } 937 */ 938 static int 939 th3_alpm_cfg_adjust(int u, int acb_cnt, _alpm_cb_t *acb) 940 { 941 int i, half_banks = 0; 942 int vrf_id = ALPM_VRF_ID_GLO(u); 943 944 if (soc_th3_get_alpm_banks(u) == 4) { 945 half_banks = 1; 946 ALPMC(u)->_alpm_half_banks = 1; 947 } 948 949 if (acb_cnt > 1 && acb->acb_idx > 0) { 950 /* Half banks mode */ 951 if (half_banks) { 952 int pid; 953 /* Adjust _alpm_cb_t */ 954 ACB_PHY_BNK_PER_BKT(acb) >>= 1; 955 ACB_BNK_BITS(acb) -= 1; 956 957 /* Adjust _alpm_bkt_pool_conf_t */ 958 /* For Parallel mode, Global Low routes go to Level 2 only */ 959 if (ALPM_MODE_CHK(u, BCM_ALPM_MODE_PARALLEL)) { 960 _alpm_bkt_pool_conf_t *bp_conf; 961 bp_conf = ACB_BKT_VRF_POOL(acb, ALPM_VRF_ID_GLO(u)); 962 BPC_BNK_CNT(bp_conf) = 0; 963 BPC_BNK_PER_BKT(bp_conf) = 1; 964 } else { 965 for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) { 966 _alpm_bkt_pool_conf_t *bp_conf; 967 bp_conf = ACB_BKT_POOL(acb, pid); 968 969 if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid-1)) { 970 continue; 971 } 972 BPC_BNK_CNT(bp_conf) >>= 1; 973 BPC_BNK_PER_BKT(bp_conf) >>= 1; 974 } 975 } 976 } 977 } 978 979 /* Adjust fmt_info */ 980 if (ACB_IDX(acb) == acb_cnt - 1) { 981 for (i = 0; i < ALPM_BKT_PID_CNT; i++) { 982 ACB_BKT_POOL(acb, i)->fmt_info = &th3_fmt_info[ALPM_FMT_RTE]; 983 if (acb_cnt < 2) { 984 ALPMC(u)->_alpm_btm_cb_idx[i] = acb_cnt - 1; 985 } 986 } 987 if (ALPM_GLO_VRF_IN_HLF_PMODE(u, vrf_id)) { 988 ACB_VRF_POOL_FMT_INFO(acb, vrf_id) = 989 &th3_fmt_info[ALPM_FMT_CNT]; 990 } 991 } else { 992 /* When reach here: more than 2 acbs, non-last acb */ 993 for (i = 0; i < ALPM_BKT_PID_CNT; i++) { 994 ACB_POOL_FMT_INFO(acb, i) = &th3_fmt_info[ALPM_FMT_PVT]; 995 ALPMC(u)->_alpm_btm_cb_idx[i] = acb_cnt - 1; 996 } 997 if (ALPM_GLO_VRF_IN_HLF_PMODE(u, vrf_id)) { 998 ACB_VRF_POOL_FMT_INFO(acb, vrf_id) = 999 &th3_fmt_info[ALPM_FMT_RTE]; 1000 ALPMC(u)->_alpm_btm_cb_idx[ALPM_VRF_ID_TO_BPC_PID(u, vrf_id)] = 1001 acb_cnt - 2; 1002 } 1003 } 1004 1005 return BCM_E_NONE; 1006 } 1007 1008 static void 1009 th3_alpm_hw_mem_clear(int u, soc_mem_t mem) 1010 { 1011 uint8 *mbuf; 1012 int size, offset = 0; 1013 1014 ALPM_INFO(("ALPM clearing mem %s\n", SOC_MEM_NAME(u, mem))); 1015 1016 size = SOC_MEM_TABLE_BYTES(u, mem); 1017 /* skip first 4 shared UFT banks for EM */ 1018 if ((soc_th3_get_alpm_banks(u) == 4) && 1019 (mem == L3_DEFIP_ALPM_LEVEL3m || 1020 mem == L3_DEFIP_ALPM_LEVEL3_HIT_ONLYm)) { 1021 offset = (soc_mem_index_count(u, mem) >> 1); 1022 size >>= 1; 1023 } 1024 mbuf = soc_cm_salloc(u, size, "alpm_mem"); 1025 if (mbuf != NULL) { 1026 sal_memset(mbuf, 0, size); 1027 (void)soc_mem_write_range(u, mem, MEM_BLOCK_ANY, 1028 soc_mem_index_min(u, mem) + offset, 1029 soc_mem_index_max(u, mem), mbuf); 1030 soc_cm_sfree(u, mbuf); 1031 } else { 1032 ALPM_ERR(("alpm_hw_mem_clear alloc DMA memory failed\n")); 1033 } 1034 1035 return ; 1036 } 1037 1038 static int 1039 th3_alpm_hw_init(int u) 1040 { 1041 1042 #define LVLS 3 1043 #define MODES 3 1044 #define PAIRS 5 1045 #define CNTOF(arr) (sizeof(arr)/sizeof(arr[0])) 1046 1047 int i, mde, lvl, prs, rv = BCM_E_NONE; 1048 soc_mem_t mem = LPM_IP_CONTROLm; 1049 lpm_ip_control_entry_t entry; 1050 1051 /* Field definitions */ 1052 soc_field_t db_sel_f[8] = { 1053 LEVEL1_DATABASE_SEL_BLOCK_0f, 1054 LEVEL1_DATABASE_SEL_BLOCK_1f, 1055 LEVEL1_DATABASE_SEL_BLOCK_2f, 1056 LEVEL1_DATABASE_SEL_BLOCK_3f, 1057 LEVEL2_DATABASE_SEL_BLOCK_0f, 1058 LEVEL2_DATABASE_SEL_BLOCK_1f, 1059 LEVEL3_DATABASE_SEL_BLOCK_0f, 1060 LEVEL3_DATABASE_SEL_BLOCK_1f 1061 }; 1062 1063 soc_field_t ki_sel_f[8] = { 1064 LEVEL1_KEY_INPUT_SEL_BLOCK_0f, 1065 LEVEL1_KEY_INPUT_SEL_BLOCK_1f, 1066 LEVEL1_KEY_INPUT_SEL_BLOCK_2f, 1067 LEVEL1_KEY_INPUT_SEL_BLOCK_3f, 1068 LEVEL2_KEY_INPUT_SEL_BLOCK_0f, 1069 LEVEL2_KEY_INPUT_SEL_BLOCK_1f, 1070 LEVEL3_KEY_INPUT_SEL_BLOCK_0f, 1071 LEVEL3_KEY_INPUT_SEL_BLOCK_1f 1072 }; 1073 1074 soc_field_t bnk_cf_f[4] = { 1075 LEVEL2_BANK_CONFIG_BLOCK_0f, 1076 LEVEL2_BANK_CONFIG_BLOCK_1f, 1077 LEVEL3_BANK_CONFIG_BLOCK_0f, 1078 LEVEL3_BANK_CONFIG_BLOCK_1f 1079 }; 1080 1081 soc_field_t db_mod_f[2] = { 1082 DB0_MODEf, 1083 DB1_MODEf 1084 }; 1085 1086 soc_field_t dt_sel_f[2] = { 1087 DATA0_SELf, 1088 DATA1_SELf 1089 }; 1090 1091 /* Value definitions */ 1092 /* DB0: 0, Disable: 4 */ 1093 uint32 db_sel_v[MODES][PAIRS][8] = { 1094 { /* Combined */ 1095 {0, 0, 0, 0, 0, 0, 0, 0}, /* 0 block paired */ 1096 {0, 0, 0, 0, 0, 0, 0, 0}, /* 1 block paired */ 1097 {0, 0, 0, 0, 0, 0, 0, 0}, /* 2 blocks paired */ 1098 {0, 0, 0, 0, 0, 0, 0, 0}, /* 3 blocks paired */ 1099 {0, 0, 0, 0, 0, 0, 0, 0} /* 4 blocks paired */ 1100 }, 1101 { /* Parallel */ 1102 {0, 0, 1, 1, 0, 1, 0, 1}, 1103 {0, 0, 1, 1, 0, 1, 0, 1}, 1104 {0, 0, 1, 1, 0, 1, 0, 1}, 1105 {0, 0, 1, 1, 0, 1, 0, 1}, 1106 {0, 0, 1, 1, 0, 1, 0, 1} 1107 }, 1108 { /* Mixed */ 1109 {0, 0, 1, 1, 0, 0, 0, 0}, 1110 {0, 0, 1, 1, 0, 0, 0, 0}, 1111 {0, 0, 1, 1, 0, 0, 0, 0}, 1112 {0, 0, 1, 1, 0, 0, 0, 0}, 1113 {0, 0, 1, 1, 0, 0, 0, 0} 1114 } 1115 }; 1116 1117 /* IPv6: K0(0), 128bits; K1(1), 64bits */ 1118 uint32 ki_sel_v[MODES][PAIRS][8] = { 1119 { /* Combined */ 1120 {1, 1, 1, 1, 0, 0, 0, 0}, /* 0 block paired */ 1121 {0, 1, 1, 1, 0, 0, 0, 0}, /* 1 block paired */ 1122 {0, 0, 1, 1, 0, 0, 0, 0}, /* 2 blocks paired */ 1123 {0, 0, 0, 1, 0, 0, 0, 0}, /* 3 blocks paired */ 1124 {0, 0, 0, 0, 0, 0, 0, 0} /* 4 blocks paired */ 1125 }, 1126 { /* Parallel */ 1127 {1, 1, 1, 1, 0, 0, 0, 0}, /* 0 block paired */ 1128 {0, 1, 0, 1, 0, 0, 0, 0}, /* 1 block paired (invalid, use 2 blk paired setting) */ 1129 {0, 1, 0, 1, 0, 0, 0, 0}, /* 2 block paired */ 1130 {0, 0, 0, 0, 0, 0, 0, 0}, /* 3 block paired (invalid, use 4 blk paired setting) */ 1131 {0, 0, 0, 0, 0, 0, 0, 0} /* 4 block paired */ 1132 }, 1133 { /* Mixed */ 1134 {1, 1, 1, 1, 0, 0, 0, 0}, /* 0 block paired */ 1135 {0, 1, 0, 1, 0, 0, 0, 0}, /* 1 block paired (invalid, use 2 blk paired setting) */ 1136 {0, 1, 0, 1, 0, 0, 0, 0}, /* 2 block paired */ 1137 {0, 0, 0, 0, 0, 0, 0, 0}, /* 3 block paired (invalid, use 4 blk paired setting) */ 1138 {0, 0, 0, 0, 0, 0, 0, 0} /* 4 block paired */ 1139 } 1140 }; 1141 1142 /* Bank Config: bitmap */ 1143 uint32 bnk_cf_v[MODES][LVLS][4] = { 1144 { /* Combined */ 1145 {0, 0, 0, 0}, /* 1Level */ 1146 {0x7, 0x18, 0, 0}, /* 2Level */ 1147 {0x7, 0x18, 0xf, 0xf0} /* 3Level */ 1148 }, 1149 { /* Parallel */ 1150 {0, 0, 0, 0}, 1151 {0x7, 0x18, 0, 0}, 1152 {0x7, 0x18, 0xf, 0xf0} 1153 }, 1154 { /* Mixed */ 1155 {0, 0, 0, 0}, 1156 {0x7, 0x18, 0, 0}, 1157 {0x7, 0x18, 0xf, 0xf0} 1158 } 1159 }; 1160 1161 /* DB_MODE: 1Level(1), 2Level(2), 3Level(3), Disable(0) */ 1162 uint32 db_mod_v[MODES][LVLS][2] = { 1163 { /* Combined */ 1164 {1, 0}, /* 1Level */ 1165 {2, 0}, /* 2Level */ 1166 {3, 0} /* 3Level */ 1167 }, 1168 { /* Parallel */ 1169 {1, 1}, 1170 {2, 2}, 1171 {3, 3} 1172 }, 1173 { /* Mixed */ 1174 {1, 1}, 1175 {2, 1}, 1176 {3, 1} 1177 } 1178 }; 1179 1180 /* DATA_SEL: DB0(0), DB1(1), Disable(4) */ 1181 uint32 dt_sel_v[MODES][2] = { 1182 {0, 4}, 1183 {0, 1}, 1184 {0, 1} 1185 }; 1186 1187 if (!soc_mem_is_valid(u, LPM_IP_CONTROLm)) { 1188 return rv; 1189 } 1190 1191 mde = ALPM_MODE(u); 1192 lvl = ACB_CNT(u); 1193 prs = ALPM_TCAM_PAIR_BLK_CNT(u); 1194 1195 sal_memset(&entry, 0, sizeof(entry)); 1196 1197 /* Adjust DATABASE_SEL values based on Level count */ 1198 for (i = 2; i > lvl; i--) { 1199 db_sel_v[mde][prs][2*i+2] = 4; /* 4: Disable */ 1200 db_sel_v[mde][prs][2*i+3] = 4; 1201 } 1202 1203 if (soc_th3_get_alpm_banks(u) == 4) { 1204 /* Set LEVEL3_DATABASE_SEL_BLOCK_0 to 4: Disable in half banks mode */ 1205 db_sel_v[mde][prs][6] = 4; 1206 db_sel_v[mde][prs][7] = 0; 1207 /* Set LEVEL3_BANK_CONFIG_BLOCK_0 to 0: UFT banks 0-3 for EM */ 1208 bnk_cf_v[mde][2][2] = 0; 1209 if (ALPM_MODE_CHK(u, BCM_ALPM_MODE_PARALLEL) && (lvl == 2)) { 1210 db_mod_v[mde][lvl][1] = 2; /* Public DB in Parallel mode goes to Level2 only */ 1211 } 1212 } 1213 1214 /* DATABASE_SEL fields */ 1215 for (i = 0; i < CNTOF(db_sel_f); i++) { 1216 soc_mem_field32_set(u, mem, &entry, db_sel_f[i], db_sel_v[mde][prs][i]); 1217 } 1218 1219 /* KEY_INPUT_SEL fields */ 1220 for (i = 0; i < CNTOF(ki_sel_f); i++) { 1221 soc_mem_field32_set(u, mem, &entry, ki_sel_f[i], ki_sel_v[mde][prs][i]); 1222 } 1223 1224 /* BANK_CONFIG fields */ 1225 for (i = 0; i < CNTOF(bnk_cf_f); i++) { 1226 soc_mem_field32_set(u, mem, &entry, bnk_cf_f[i], bnk_cf_v[mde][lvl][i]); 1227 } 1228 1229 /* DB_MODE fields */ 1230 for (i = 0; i < CNTOF(db_mod_f); i++) { 1231 soc_mem_field32_set(u, mem, &entry, db_mod_f[i], db_mod_v[mde][lvl][i]); 1232 } 1233 1234 /* DATA_SEL fields */ 1235 for (i = 0; i < CNTOF(dt_sel_f); i++) { 1236 soc_mem_field32_set(u, mem, &entry, dt_sel_f[i], dt_sel_v[mde][i]); 1237 } 1238 1239 soc_mem_write(u, mem, COPYNO_ALL, 0, &entry); 1240 1241 return rv; 1242 } 1243 1244 /* Initialize pivot and bkt bank mem and states. 1245 allocate: TRUE when th3_alpm_ctrl_init, 1246 FALSE when th3_alpm_ctrl_cleanup */ 1247 int 1248 th3_alpm_ctrl_mem_init(int u, int allocate) 1249 { 1250 int rv = BCM_E_NONE; 1251 int i, j, pid, acb_cnt, vrf_id, vrf_id_cnt; 1252 uint8 def_mode, db_type; 1253 int alloc_sz; 1254 int scale_factor = 1; 1255 int sf = 0; 1256 1257 soc_mem_t mem, allmems[20] = {INVALIDm}; 1258 int m, mem_cnt = 0; 1259 1260 1261 if (SOC_MEM_IS_VALID(u, L3_DEFIP_ALPM_LEVEL2m)) { 1262 alpm_tbl = &th3_alpm_tbl[0]; 1263 } 1264 1265 /* Default route data mode = Full (1) */ 1266 def_mode = soc_property_get(u, spn_L3_ALPM2_DEFAULT_ROUTE_DATA_MODE, 1); 1267 1268 if (allocate) { /* for cleanup only scale_factor=1, sf=0 */ 1269 /* Load scaling factor config 1270 * 8 means valid factors are 1,2,4,8...128 1271 */ 1272 scale_factor = soc_property_get(u, "l3_alpm2_scaling_factor", 1); 1273 for (sf = 0; sf < 8; sf++) { 1274 if (scale_factor == (1 << sf)) { 1275 break; 1276 } 1277 } 1278 if (sf >= 8) { 1279 scale_factor = 1; 1280 sf = 0; 1281 } 1282 } 1283 1284 vrf_id_cnt = ALPM_VRF_ID_CNT(u); 1285 acb_cnt = ACB_CNT(u); 1286 1287 for (i = 0; i < acb_cnt; i++) { 1288 _alpm_cb_t *acb = ACB(u, i); 1289 1290 #define _CHK_IF_CLEAR_MEM(mem) \ 1291 do { \ 1292 for (m = 0; m < mem_cnt; m++) { \ 1293 if (allmems[m] == (mem)) { \ 1294 break; \ 1295 } \ 1296 } \ 1297 if (m == mem_cnt && mem != INVALIDm && \ 1298 soc_mem_index_count(u, mem) > 0) { \ 1299 th3_alpm_hw_mem_clear(u, (mem)); \ 1300 allmems[mem_cnt++] = (mem); \ 1301 } \ 1302 } while (0) 1303 1304 for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) { 1305 _alpm_bkt_pool_conf_t *bp_conf = ACB_BKT_POOL(acb, pid); 1306 if (pid > 0 && ACB_BKT_POOL(acb, pid-1) == bp_conf) { 1307 continue; 1308 } 1309 1310 /* Adjust bucket count based on scaling factor */ 1311 BPC_BNK_CNT(bp_conf) /= scale_factor; 1312 alloc_sz = sizeof(_alpm_bnk_info_t); 1313 ALPM_REALLOC_EG(BPC_BNK_INFO(bp_conf, ALPM_IPT_V4), 1314 alloc_sz, "bnk_bmp"); 1315 if (ALPM_128B(u) && ALPM_BKT_RSVD(u)) { 1316 int rsvd_v6_bnks = 1317 BPC_BNK_CNT(bp_conf) * ALPM_BKT_RSVD_CNT(u) / 8192; 1318 ALPM_REALLOC_EG( 1319 BPC_BNK_INFO(bp_conf, ALPM_IPT_V6), alloc_sz, "bnk_bmp"); 1320 /* reserved v6 bnks in v4 bitmap */ 1321 SHR_BITSET_RANGE( 1322 BPC_BNK_BMP(bp_conf, ALPM_IPT_V4), 1323 BPC_BNK_CNT(bp_conf) - rsvd_v6_bnks, 1324 rsvd_v6_bnks); 1325 BPC_BNK_RSVD(bp_conf, ALPM_IPT_V4) = rsvd_v6_bnks; 1326 /* reserved v4 bnks in v6 bitmap */ 1327 SHR_BITSET_RANGE( 1328 BPC_BNK_BMP(bp_conf, ALPM_IPT_V6), 0, 1329 BPC_BNK_CNT(bp_conf) - rsvd_v6_bnks); 1330 BPC_BNK_RSVD(bp_conf, ALPM_IPT_V6) = 1331 BPC_BNK_CNT(bp_conf) - rsvd_v6_bnks; 1332 } else { 1333 BPC_BNK_INFO(bp_conf, ALPM_IPT_V6) = 1334 BPC_BNK_INFO(bp_conf, ALPM_IPT_V4); 1335 } 1336 1337 if (!SOC_WARM_BOOT(u)) { 1338 mem = alpm_tbl[BPC_BKT_TBL(bp_conf)]; 1339 _CHK_IF_CLEAR_MEM(mem); 1340 } 1341 1342 if (bp_conf->pvt_ptr == NULL) { 1343 alloc_sz = BPC_BNK_CNT(bp_conf); 1344 alloc_sz = sizeof(void *) * alloc_sz; 1345 ALPM_REALLOC_EG(bp_conf->pvt_ptr, alloc_sz, "pvt_ptr"); 1346 } 1347 } 1348 1349 /* Adjust bucket count based on scaling factor */ 1350 ALPM_IDX_BNK_SHIFT(acb) -= sf; 1351 1352 /* Per instance structure init */ 1353 alloc_sz = vrf_id_cnt * sizeof(_alpm_pvt_ctrl_t); 1354 for (j = 0; j < ALPM_IPT_CNT; j++) { 1355 ALPM_REALLOC_EG( 1356 acb->pvt_ctl[j], alloc_sz, "pvt_ctl"); 1357 /* Initialize all VRF db_type with default route data mode */ 1358 for (vrf_id = 0; vrf_id < vrf_id_cnt; vrf_id++) { 1359 if (ALPM_VRF_ID_HAS_BKT(u, vrf_id)) { 1360 db_type = def_mode; 1361 } else { 1362 db_type = 1; /* DIRECT_ROUTE is always Full mode */ 1363 } 1364 ACB_VRF_DB_TYPE_SET(u, acb, vrf_id, j, db_type); 1365 } 1366 } 1367 1368 for (j = 0; j < ALPM_PKM_CNT; j++) { 1369 if (!SOC_WARM_BOOT(u)) { 1370 mem = alpm_tbl[acb->pvt_tbl[j]]; 1371 _CHK_IF_CLEAR_MEM(mem); 1372 } 1373 } 1374 } 1375 1376 bad: 1377 return rv; 1378 } 1379 1380 int 1381 th3_alpm_ctrl_init(int u) 1382 { 1383 int rv = BCM_E_NONE; 1384 int i, j, pid, acb_cnt; 1385 int alloc_sz; 1386 1387 /* 1388 * b2(p1) b1(p0) bit0(128b) 1389 * --------------------------- 1390 * 0 0 0 -> 2-Level (64b) 1391 * 0 0 1 -> 2-Level (128b) 1392 * 0 1 0 -> 3-Level (p0-64b) 1393 * 0 1 1 -> 3-Level (p0-128b) 1394 * 1 0 0 -> 3-Level (p1-64b) 1395 * 1 0 1 -> 3-Level (p1-128b) 1396 */ 1397 _alpm_cb_t *acb_template[6] = { 1398 &th3_alpm_1cb_template, 1399 &th3_alpm_1cb_template_128b, 1400 &th3_alpm_2cb_template_p0, 1401 &th3_alpm_2cb_template_p0_128b, 1402 &th3_alpm_2cb_template_p1, 1403 &th3_alpm_2cb_template_p1 1404 }; 1405 1406 #define ACB_BP_CONF_NUM 8 1407 _alpm_bkt_pool_conf_t *acb_bp_conf[ACB_BP_CONF_NUM]; 1408 1409 _alpm_bkt_pool_conf_t *acb_bp_conf_template[ACB_BP_CONF_NUM] = { 1410 &th3_alpm_cmode_pool_l2, 1411 &th3_alpm_cmode_pool_l3, 1412 &th3_alpm_pmode_pool_prt_l2, 1413 &th3_alpm_pmode_pool_prt_l3, 1414 &th3_alpm_cmode_pool_l2, 1415 &th3_alpm_cmode_pool_l3, 1416 &th3_alpm_pmode_pool_gbl_l2, 1417 &th3_alpm_pmode_pool_gbl_l3 1418 }; 1419 1420 alloc_sz = sizeof(_alpm_bkt_pool_conf_t); 1421 ALPM_ALLOC_EG(th3_alpm_pool0_l2[u], alloc_sz, "th3_alpm_pool0_l2"); 1422 ALPM_ALLOC_EG(th3_alpm_pool1_l2[u], alloc_sz, "th3_alpm_pool1_l2"); 1423 ALPM_ALLOC_EG(th3_alpm_pool0_l3[u], alloc_sz, "th3_alpm_pool0_l3"); 1424 ALPM_ALLOC_EG(th3_alpm_pool1_l3[u], alloc_sz, "th3_alpm_pool1_l3"); 1425 1426 acb_bp_conf[0] = th3_alpm_pool0_l2[u]; 1427 acb_bp_conf[1] = th3_alpm_pool0_l3[u]; 1428 acb_bp_conf[2] = th3_alpm_pool0_l2[u]; 1429 acb_bp_conf[3] = th3_alpm_pool0_l3[u]; 1430 acb_bp_conf[4] = th3_alpm_pool0_l2[u]; 1431 acb_bp_conf[5] = th3_alpm_pool0_l3[u]; 1432 acb_bp_conf[6] = th3_alpm_pool1_l2[u]; 1433 acb_bp_conf[7] = th3_alpm_pool1_l3[u]; 1434 1435 /* assert ALPM_MEM_ENT_MAX for largest TCAM/ALPM memory entry */ 1436 assert(ALPM_MEM_ENT_MAX * sizeof(uint32) 1437 >= sizeof(defip_pair_level1_entry_t)); 1438 1439 if (SOC_MEM_IS_VALID(u, L3_DEFIP_ALPM_LEVEL2m)) { 1440 alpm_tbl = &th3_alpm_tbl[0]; 1441 } 1442 acb_cnt = th3_alpm_cb_cnt(u); 1443 assert((acb_cnt * ALPM_PKM_CNT) < 20); 1444 1445 if (acb_cnt > 1 && (soc_th3_get_alpm_banks(u) == 0)) { 1446 ALPM_ERR(("There is no UFT bank available for 3-Level ALPM\n")); 1447 ALPM_IEG(BCM_E_CONFIG); 1448 } 1449 1450 for (i = 0; i < acb_cnt; i++) { 1451 int idx; 1452 _alpm_cb_t *acb = NULL; 1453 1454 alloc_sz = sizeof(_alpm_cb_t); 1455 ALPM_ALLOC_EG(acb, alloc_sz, "alpm_cb"); 1456 idx = (i + acb_cnt - 1) << 1 | (ALPM_128B(u) & 1); 1457 sal_memcpy(acb, acb_template[idx], sizeof(_alpm_cb_t)); 1458 acb->unit = u; 1459 1460 /** 1461 * ------- 1462 * |2|1|0| 1463 * ------- 1464 * Bit 0: acb_idx: acb0, acb1 1465 * Bit 1: Parallel: 1, Mixed/Combined: 0 1466 * Bit 2: Private(Pid 0)/Global(Pid 1) 1467 * --------- 1468 */ 1469 for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) { 1470 idx = pid << 2 | (!!ALPM_MODE_CHK(u, BCM_ALPM_MODE_PARALLEL) << 1) | i; 1471 ACB_BKT_POOL(acb, pid) = acb_bp_conf[idx]; 1472 sal_memcpy(acb_bp_conf[idx], acb_bp_conf_template[idx], 1473 sizeof(_alpm_bkt_pool_conf_t)); 1474 } 1475 1476 /* Adjust ctrl bnk conf 1477 * BPC should NOT be adjusted because they point to 1478 * global storage 1479 */ 1480 ALPM_IEG(th3_alpm_cfg_adjust(u, acb_cnt, acb)); 1481 1482 ACB(u, i) = acb; 1483 } 1484 1485 ACB_CNT(u) = acb_cnt; 1486 1487 /* Init pvt/bkt bank mem and ctrl (with allocate=TRUE) */ 1488 ALPM_IEG(th3_alpm_ctrl_mem_init(u, TRUE)); 1489 1490 /* Obtain TCAM table skip (invalid or duplicated) per */ 1491 for (i = 0; i < ALPM_PKM_CNT; i++) { 1492 1493 if (alpm_tbl[ACB_TOP(u)->pvt_tbl[i]] == INVALIDm) { 1494 ALPM_TCAM_TBL_SKIP(u, i) = TRUE; /* invalid */ 1495 continue; 1496 } else { 1497 ALPM_TCAM_TBL_SKIP(u, i) = FALSE; 1498 } 1499 1500 for (j = 0; j < i; j++) { 1501 if (alpm_tbl[ACB_TOP(u)->pvt_tbl[i]] == 1502 alpm_tbl[ACB_TOP(u)->pvt_tbl[j]]) { 1503 ALPM_TCAM_TBL_SKIP(u, j) = TRUE; /* duplicated */ 1504 break; 1505 } 1506 } 1507 } 1508 1509 if (!SOC_WARM_BOOT(u)) { 1510 rv = th3_alpm_hw_init(u); 1511 } 1512 1513 th3_fmt_test(u); 1514 th3_mem_test(u); 1515 1516 return rv; 1517 1518 bad: 1519 th3_alpm_ctrl_deinit(u); 1520 return rv; 1521 } 1522 1523 /* TH3 ALPM ctrl cleanup (for faster delete_all) */ 1524 int 1525 th3_alpm_ctrl_cleanup(int u) 1526 { 1527 /* Cleanup only bank mem and ctrl state, 1528 but keep statistics (with allocate=FALSE) */ 1529 return (th3_alpm_ctrl_mem_init(u, FALSE)); 1530 } 1531 1532 /* L3_DEFIP_ALPM_ROUTE_BANK_FMT1fmt 1533 * -> ENTRY0f: L3_DEFIP_ALPM_ROUTE_FMT1fmt 1534 * -> PREFIXf 1535 * -> ASSOC_DATAf: ASSOC_DATA_REDUCEDfmt 1536 * -> DEST_TYPEf 1537 * -> DESTINATIONf 1538 * 1539 * -> ASSOC_DATAf: ASSOC_DATA_FULLfmt 1540 * -> DEST_TYPEf 1541 * -> DESTINATIONf 1542 * -> PRIf 1543 * -> RPEf 1544 * -> DST_DISCARDf 1545 * -> CLASS_IDf 1546 * -> FLEX_CTR_POOL_NUMBERf 1547 * -> FLEX_CTR_OFFSET_MODEf 1548 * -> FLEX_CTR_BASE_COUNTER_IDXf 1549 */ 1550 1551 int8 1552 th3_alpm_bnk_fmt_get(int u, _alpm_cb_t *acb, 1553 _alpm_bkt_info_t *bkt_info, int ent_idx) 1554 { 1555 int bnk_idx; 1556 1557 bnk_idx = ALPM_IDX_TO_BNK(acb, ent_idx); 1558 1559 return bkt_info->bnk_fmt[bnk_idx]; 1560 1561 } 1562 1563 static void 1564 th3_alpm_ent_1bit_encoding(int u, uint32 *pfx, int fmt_len, int pfx_len) 1565 { 1566 SHR_BITSET(pfx, fmt_len - pfx_len); 1567 } 1568 1569 static void 1570 th3_alpm_ent_1bit_decoding(int u, uint32 *pfx, int fmt_len, int *pfx_len) 1571 { 1572 int bp = 0; /* Bit pos */ 1573 #if 0 1574 for (bp = 0; bp <= fmt_len; bp++) { 1575 if (SHR_BITGET(pfx, bp)) { 1576 break; 1577 } 1578 } 1579 #else 1580 static int fbit[16] = { 1581 -1, /* 0b0000 */ 1582 0, /* 0b0001 */ 1583 1, /* 0b0010 */ 1584 0, /* 0b0011 */ 1585 2, /* 0b0100 */ 1586 0, /* 0b0101 */ 1587 1, /* 0b0110 */ 1588 0, /* 0b0111 */ 1589 3, /* 0b1000 */ 1590 0, /* 0b1001 */ 1591 1, /* 0b1010 */ 1592 0, /* 0b1011 */ 1593 2, /* 0b1100 */ 1594 0, /* 0b1101 */ 1595 1, /* 0b1110 */ 1596 0, /* 0b1111 */ 1597 }; 1598 1599 while (bp < fmt_len) { 1600 uint32 tmp; 1601 if (*pfx != 0) { 1602 tmp = *pfx; 1603 while (tmp > 0) { 1604 if (tmp & 0xf) { 1605 bp += fbit[tmp & 0xf]; 1606 break; 1607 } 1608 bp += 4; 1609 tmp = tmp >> 4; 1610 } 1611 break; 1612 } else { 1613 pfx ++; 1614 bp += 32; 1615 } 1616 } 1617 #endif 1618 *pfx_len = fmt_len - bp; 1619 } 1620 1621 static void 1622 th3_alpm_ent_assemble(int u, _alpm_cb_t *acb, 1623 _alpm_pvt_node_t *pvt_node, int ent_idx, 1624 _bcm_defip_cfg_t *lpm_cfg, uint32 *entry, uint32 write_flags) 1625 { 1626 int b, vrf_id, ipt; 1627 int ofst, key_len; 1628 int dst_sbit, src_sbit; /* Source start bit and Dest start bit */ 1629 int fmt_len, cpy_len, max_pfx_len[] = {32, 128}; 1630 int8 fmt_tp; 1631 1632 uint32 fmt[6] = {0}; 1633 uint32 key[8] = {0}; 1634 uint32 pfx[5] = {0}; 1635 uint32 fent[ALPM_ENT_WORDS_MAX] = {0}; 1636 soc_format_t ent_fmt, bnk_fmt; 1637 1638 _alpm_bkt_info_t *bkt_info = NULL; 1639 _alpm_bkt_pool_conf_t *bp_conf = NULL; 1640 1641 th3_fmt_ASSOC_DATA_FULL_t *fmt_adf = NULL; 1642 th3_fmt_ASSOC_DATA_REDUCED_t *fmt_adr = NULL; 1643 th3_fmt_ALPM2_DATA_t fmt_a2d; 1644 1645 vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg); 1646 ipt = ALPM_LPM_IPT(u, lpm_cfg); 1647 1648 fmt_tp = th3_alpm_bnk_fmt_get(u, acb, &PVT_BKT_INFO(pvt_node), ent_idx); 1649 ent_fmt = ACB_FMT_ENT(acb, vrf_id, fmt_tp); 1650 bnk_fmt = ACB_FMT_BNK(acb, vrf_id, fmt_tp); 1651 ofst = ALPM_IDX_TO_ENT(ent_idx); 1652 1653 if (write_flags != ALPM_PVT_UPDATE_ALL) { 1654 soc_format_field_get(u, bnk_fmt, entry, th3_alpm_ent_fld[ofst], fent); 1655 } 1656 1657 /* Assoc DATA update */ 1658 if (write_flags & ALPM_PVT_UPDATE_ASSOC_DATA) { 1659 if (ACB_VRF_DB_TYPE(u, acb, vrf_id, ipt)) { 1660 fmt_adf = (th3_fmt_ASSOC_DATA_FULL_t *)fmt; 1661 fmt_adf->DEST_TYPE = lpm_cfg->defip_flags & BCM_L3_MULTIPATH ? 1 : 0; 1662 fmt_adf->DESTINATION = lpm_cfg->defip_ecmp_index; 1663 fmt_adf->PRI = lpm_cfg->defip_prio; 1664 fmt_adf->RPE = lpm_cfg->defip_flags & BCM_L3_RPE ? 1 : 0; 1665 fmt_adf->DST_DISCARD = lpm_cfg->defip_flags & BCM_L3_DST_DISCARD ? 1 : 0; 1666 fmt_adf->CLASS_ID = lpm_cfg->defip_lookup_class; 1667 fmt_adf->FLEX_CTR_POOL_NUMBER = lpm_cfg->defip_flex_ctr_pool; 1668 fmt_adf->FLEX_CTR_OFFSET_MODE = lpm_cfg->defip_flex_ctr_mode; 1669 fmt_adf->FLEX_CTR_BASE_COUNTER_IDX = lpm_cfg->defip_flex_ctr_base_id; 1670 } else { 1671 fmt_adr = (th3_fmt_ASSOC_DATA_REDUCED_t *)fmt; 1672 fmt_adr->DEST_TYPE = lpm_cfg->defip_flags & BCM_L3_MULTIPATH ? 1 : 0; 1673 fmt_adr->DESTINATION = lpm_cfg->defip_ecmp_index; 1674 } 1675 soc_format_field_set(u, ent_fmt, fent, ASSOC_DATAf, fmt); 1676 } 1677 1678 if (write_flags & ALPM_PVT_UPDATE_PREFIX) { 1679 key_len = PVT_KEY_LEN(pvt_node); 1680 fmt_len = ACB_FMT_PFX_LEN(acb, vrf_id, fmt_tp); 1681 /* 1682 * 128B: 1683 * ip6[0] ---- ip6[15] 1684 * ffff:ffff:0000:0000:0000:0000:0000:0000 1685 * prefix[7] prefix[6] prefix[5] prefix[4] ... prefix[0] 1686 * 64B: 1687 * ip6[0] ---- ip6[7] 1688 * ffff:ffff:0000:0000 1689 * prefix[7] prefix[6] prefix[5] prefix[4] ... prefix[0] 1690 * 32B: 1691 * ip_addr 1692 * c0a80101 1693 * prefix[7] prefix[6] prefix[5] prefix[4] ... prefix[0] 1694 */ 1695 alpm_util_cfg_to_key(u, ipt, lpm_cfg, &key[4]); 1696 if (max_pfx_len[ipt] < fmt_len) { 1697 src_sbit = 128; 1698 cpy_len = max_pfx_len[ipt] - key_len; 1699 dst_sbit = 1 + fmt_len - cpy_len; 1700 } else { 1701 src_sbit = 128 + max_pfx_len[ipt] - key_len - fmt_len; 1702 cpy_len = fmt_len; 1703 dst_sbit = 1; 1704 } 1705 SHR_BITCOPY_RANGE(pfx, dst_sbit, key, src_sbit, cpy_len); 1706 /* 1bit Length Encoding */ 1707 th3_alpm_ent_1bit_encoding(u, pfx, fmt_len, 1708 lpm_cfg->defip_sub_len - key_len); 1709 soc_format_field_set(u, ent_fmt, fent, PREFIXf, pfx); 1710 } 1711 1712 if ((write_flags & ALPM_PVT_UPDATE_ALPM_DATA) && ACB_HAS_PVT(acb, vrf_id)) { 1713 /* Pivot level ALPM data update */ 1714 sal_memset(&fmt_a2d, 0, sizeof(fmt_a2d)); 1715 bkt_info = (_alpm_bkt_info_t *)lpm_cfg->bkt_info; 1716 if (bkt_info != NULL) { 1717 int offset = 0; 1718 _alpm_tbl_t tbl; 1719 1720 bp_conf = ACB_BKT_VRF_POOL(ACB_DWN(u, acb), PVT_BKT_VRF(pvt_node)); 1721 tbl = BPC_BKT_TBL(bp_conf); 1722 switch (tbl) { 1723 case alpmTblBktPmodeGblL2: 1724 case alpmTblBktPmodeGblL3: 1725 offset = ACB_BNK_PER_BKT(ACB_DWN(u, acb), 1); 1726 break; 1727 default: 1728 break; 1729 } 1730 1731 if (ALPM_HLF_BNKS(u)) { 1732 offset = 4; 1733 } 1734 1735 fmt_a2d.KSHIFT = lpm_cfg->bkt_kshift; 1736 fmt_a2d.ROFS = bkt_info->rofs + offset; 1737 fmt_a2d.BKT_PTR = bkt_info->bkt_idx; 1738 if (ALPM_TCAM_ZONED(u) && lpm_cfg->default_miss == 1) { 1739 /* TH3TBD, Parallel & Mixed ALPM need to set DEFAULT_MISS to 1 1740 * if assoc_data is NOT set, in case of missing default */ 1741 fmt_a2d.DEFAULT_MISS = 1; 1742 } 1743 for (b = 0; b < BPC_BNK_PER_BKT(bp_conf); b++) { 1744 soc_field_t bnk_fld; 1745 if (bkt_info->bnk_fmt[b] == 0) { 1746 continue; 1747 } 1748 1749 bnk_fld = th3_alpm_bnk_fld[b+offset]; 1750 switch (bnk_fld) { 1751 case FMT0f: 1752 fmt_a2d.FMT0 = bkt_info->bnk_fmt[b]; 1753 break; 1754 case FMT1f: 1755 fmt_a2d.FMT1 = bkt_info->bnk_fmt[b]; 1756 break; 1757 case FMT2f: 1758 fmt_a2d.FMT2 = bkt_info->bnk_fmt[b]; 1759 break; 1760 case FMT3f: 1761 fmt_a2d.FMT3 = bkt_info->bnk_fmt[b]; 1762 break; 1763 case FMT4f: 1764 fmt_a2d.FMT4 = bkt_info->bnk_fmt[b]; 1765 break; 1766 case FMT5f: 1767 fmt_a2d.FMT5 = bkt_info->bnk_fmt[b]; 1768 break; 1769 case FMT6f: 1770 fmt_a2d.FMT6 = bkt_info->bnk_fmt[b]; 1771 break; 1772 case FMT7f: 1773 fmt_a2d.FMT7 = bkt_info->bnk_fmt[b]; 1774 break; 1775 default: 1776 break; 1777 } 1778 } 1779 soc_format_field_set(u, ent_fmt, fent, ALPM2_DATAf, (uint32 *)&fmt_a2d); 1780 } 1781 } 1782 1783 soc_format_field_set(u, bnk_fmt, entry, th3_alpm_ent_fld[ofst], fent); 1784 1785 return ; 1786 1787 } 1788 1789 int 1790 th3_alpm_ent_pfx_len_get(int u, _alpm_cb_t *acb, 1791 _alpm_pvt_node_t *pvt_node, int ent_idx) 1792 { 1793 int rv; 1794 int ent_id, pfx_len = -1; 1795 int8 fmt_tp; 1796 int16 fmt_len; 1797 uint32 bnkb[17]; 1798 uint32 entb[17] = {0}; 1799 uint32 fldb[17] = {0}; 1800 soc_format_t bnk_fmt, ent_fmt; 1801 _alpm_bkt_pool_conf_t *bp_conf; 1802 1803 bp_conf = ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node)); 1804 /* Get Bank data: bnkb */ 1805 rv = th3_mem_read(u, acb, BPC_BKT_TBL(bp_conf), 1806 ALPM_TAB_IDX_GET(ent_idx), bnkb, FALSE); 1807 if (BCM_SUCCESS(rv)) { 1808 fmt_tp = th3_alpm_bnk_fmt_get(u, acb, &PVT_BKT_INFO(pvt_node), ent_idx); 1809 bnk_fmt = BPC_FMT_BNK(bp_conf, fmt_tp); 1810 ent_id = ALPM_IDX_TO_ENT(ent_idx); 1811 1812 /* Get Entry data: entb */ 1813 (void)soc_format_field_get(u, bnk_fmt, bnkb, 1814 th3_alpm_ent_fld[ent_id], entb); 1815 /* Get PREFIXf Field data: tmpf */ 1816 ent_fmt = BPC_FMT_ENT(bp_conf, fmt_tp); 1817 (void)soc_format_field_get(u, ent_fmt, entb, PREFIXf, fldb); 1818 1819 /* 1bit Length Decoding */ 1820 fmt_len = BPC_FMT_PFX_LEN(bp_conf, fmt_tp); 1821 th3_alpm_ent_1bit_decoding(u, fldb, fmt_len, &pfx_len); 1822 } 1823 1824 return pfx_len; 1825 } 1826 1827 void 1828 th3_alpm_ent_copy(int u, int vrf_id, _alpm_cb_t *acb, uint32 *sb_ent, uint32 *db_ent, 1829 _alpm_bkt_info_t *sbinfo, _alpm_bkt_info_t *dbinfo, 1830 uint32 src_pvt_len, uint32 dst_pvt_len, 1831 uint32 src_idx, uint32 dst_idx) 1832 { 1833 int src_pfx_len, dst_pfx_len; 1834 1835 int8 src_fid, dst_fid; 1836 int16 src_fmt_len, dst_fmt_len; 1837 uint32 src_eid, dst_eid; 1838 uint32 se_ent[17] = {0}; 1839 uint32 de_ent[17] = {0}; 1840 1841 uint32 tmpf[17] = {0}; 1842 uint32 dstf[17] = {0}; 1843 1844 soc_format_t sb_fmt, db_fmt; 1845 soc_format_t se_fmt, de_fmt; 1846 1847 assert(dst_pvt_len >= src_pvt_len); 1848 1849 /* Retrieve src entry */ 1850 src_fid = th3_alpm_bnk_fmt_get(u, acb, sbinfo, src_idx); 1851 src_eid = ALPM_IDX_TO_ENT(src_idx); 1852 sb_fmt = ACB_FMT_BNK(acb, vrf_id, src_fid); 1853 se_fmt = ACB_FMT_ENT(acb, vrf_id, src_fid); 1854 soc_format_field_get(u, sb_fmt, sb_ent, th3_alpm_ent_fld[src_eid], se_ent); 1855 1856 dst_fid = th3_alpm_bnk_fmt_get(u, acb, dbinfo, dst_idx); 1857 dst_eid = ALPM_IDX_TO_ENT(dst_idx); 1858 db_fmt = ACB_FMT_BNK(acb, vrf_id, dst_fid); 1859 de_fmt = ACB_FMT_ENT(acb, vrf_id, dst_fid); 1860 1861 /* Copy ASSOC_DATA and ALPM2_DATA field */ 1862 if (sb_fmt != db_fmt) { 1863 sal_memset(tmpf, 0, sizeof(tmpf)); 1864 soc_format_field_get(u, se_fmt, se_ent, ASSOC_DATAf, tmpf); 1865 soc_format_field_set(u, de_fmt, de_ent, ASSOC_DATAf, tmpf); 1866 if (ACB_HAS_PVT(acb, vrf_id)) { 1867 sal_memset(tmpf, 0, sizeof(tmpf)); 1868 soc_format_field_get(u, se_fmt, se_ent, ALPM2_DATAf, tmpf); 1869 soc_format_field_set(u, de_fmt, de_ent, ALPM2_DATAf, tmpf); 1870 } 1871 } else { 1872 sal_memcpy(de_ent, se_ent, sizeof(de_ent)); 1873 } 1874 1875 /* Copy PREFIX field */ 1876 sal_memset(tmpf, 0, sizeof(tmpf)); 1877 soc_format_field_get(u, se_fmt, se_ent, PREFIXf, tmpf); 1878 src_fmt_len = ACB_FMT_PFX_LEN(acb, vrf_id, src_fid); 1879 dst_fmt_len = ACB_FMT_PFX_LEN(acb, vrf_id, dst_fid); 1880 1881 /* 1bit Length Decoding */ 1882 th3_alpm_ent_1bit_decoding(u, tmpf, src_fmt_len, &src_pfx_len); 1883 dst_pfx_len = src_pfx_len - (dst_pvt_len - src_pvt_len); 1884 if (dst_pfx_len > dst_fmt_len) { 1885 assert(0); 1886 } else { 1887 /* Copy only prefix part, src/dst offsets need jump after 1888 1bit encoding and do 1bit encoding after copy */ 1889 SHR_BITCOPY_RANGE(dstf, dst_fmt_len - dst_pfx_len + 1, 1890 tmpf, src_fmt_len - src_pfx_len + 1, dst_pfx_len); 1891 } 1892 1893 /* 1bit Length Encoding */ 1894 th3_alpm_ent_1bit_encoding(u, dstf, dst_fmt_len, dst_pfx_len); 1895 1896 soc_format_field_set(u, de_fmt, de_ent, PREFIXf, dstf); 1897 1898 /* Write entry back to bank */ 1899 soc_format_field_set(u, db_fmt, db_ent, th3_alpm_ent_fld[dst_eid], de_ent); 1900 1901 return ; 1902 } 1903 1904 int 1905 th3_alpm_bkt_bnk_write(int u, _alpm_cb_t *acb, 1906 _alpm_pvt_node_t *pvt_node, 1907 _bcm_defip_cfg_t *lpm_cfg, int ent_idx, uint32 write_flags) 1908 { 1909 int rv = BCM_E_NONE, index, vrf_id; 1910 uint32 entry[ALPM_ENT_WORDS_MAX]; 1911 _alpm_tbl_t tbl; 1912 uint32 vet_bmp; 1913 1914 vrf_id = PVT_BKT_VRF(pvt_node); 1915 index = ALPM_TAB_IDX_GET(ent_idx); 1916 tbl = BPC_BKT_TBL(ACB_BKT_VRF_POOL(acb, vrf_id)); 1917 1918 vet_bmp = PVT_BKT_INFO(pvt_node).vet_bmp[ALPM_IDX_TO_BNK(acb, ent_idx)]; 1919 1920 if (vet_bmp & ~(1 << ALPM_IDX_TO_ENT(ent_idx))) { 1921 rv = th3_mem_read(u, acb, tbl, index, entry, FALSE); 1922 } else { 1923 /* If it was empty bank then there is no need to do read */ 1924 sal_memset(entry, 0, sizeof(entry)); 1925 } 1926 1927 if (BCM_SUCCESS(rv)) { 1928 th3_alpm_ent_assemble(u, acb, pvt_node, ent_idx, lpm_cfg, entry, write_flags); 1929 rv = th3_mem_write(u, acb, pvt_node, tbl, index, entry); 1930 1931 /* write route HITBIT to cache & Hw */ 1932 if (!ALPM_HIT_SKIP(u)) { 1933 if (BCM_SUCCESS(rv) && ACB_HAS_RTE(acb, vrf_id)) { 1934 th3_alpm_bkt_hit_write(u, PVT_BKT_VRF(pvt_node), acb, tbl, ent_idx, 1935 (lpm_cfg->defip_flags & BCM_L3_HIT ? 1 : 0)); 1936 } 1937 } 1938 } 1939 1940 return rv; 1941 } 1942 1943 static int 1944 th3_alpm_bkt_bnk_shrink(int u, _alpm_cb_t *acb, 1945 _alpm_pvt_node_t *pvt_node, uint8 sbnk, 1946 uint8 dbnk, _alpm_bkt_pfx_arr_t *pfx_arr) 1947 { 1948 int i, j, k, rv = 0; 1949 int sepb, depb; 1950 int vrf_id; 1951 int8 src_fid, dst_fid; 1952 1953 soc_format_t sb_fmt, db_fmt; 1954 1955 uint32 tmp_idx, stab_idx, dtab_idx; 1956 _alpm_bkt_info_t *bkt_info = NULL; 1957 1958 uint32 srcbnke[17]; 1959 uint32 nullent[17]; 1960 uint32 dstbnke[17]; 1961 uint32 tempent[17]; 1962 1963 /* Bulk Write */ 1964 int bulk_idx[2]; 1965 uint32 *bulk_ent[2]; 1966 int bulk_cnt; 1967 1968 _alpm_bkt_pool_conf_t *bp_conf; 1969 1970 vrf_id = PVT_BKT_VRF(pvt_node); 1971 bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id); 1972 1973 bkt_info = &PVT_BKT_INFO(pvt_node); 1974 src_fid = bkt_info->bnk_fmt[sbnk]; 1975 dst_fid = bkt_info->bnk_fmt[dbnk]; 1976 sepb = ACB_FMT_ENT_MAX(acb, vrf_id, src_fid); 1977 depb = ACB_FMT_ENT_MAX(acb, vrf_id, dst_fid); 1978 1979 if (bkt_info->vet_bmp[dbnk] == 0) { 1980 /* Copy from entire from_bnk to to_bnk and don't invalidate 1981 from_bnk until upper level pivot changed. Invalidate 1982 from_bnk is optional after pivot changed. */ 1983 stab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, sbnk); 1984 dtab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, dbnk); 1985 1986 rv = th3_mem_read(u, acb, BPC_BKT_TBL(bp_conf), 1987 stab_idx, srcbnke, FALSE); 1988 ALPM_IER(rv); 1989 1990 rv = th3_mem_write(u, acb, pvt_node, BPC_BKT_TBL(bp_conf), 1991 dtab_idx, srcbnke); 1992 1993 ALPM_IER(rv); 1994 1995 bkt_info->vet_bmp[dbnk] = bkt_info->vet_bmp[sbnk]; 1996 bkt_info->vet_bmp[sbnk] = 0; 1997 bkt_info->bnk_fmt[dbnk] = src_fid; 1998 1999 /* Update ent_idx of prefix */ 2000 for (i = 0; i < pfx_arr->pfx_cnt; i++) { 2001 tmp_idx = pfx_arr->pfx[i]->ent_idx; 2002 if (ALPM_IDX_TO_BNK(acb, tmp_idx) == sbnk) { 2003 pfx_arr->pfx[i]->ent_idx = 2004 ALPM_IDX_MAKE(acb, bkt_info, dbnk, 2005 ALPM_IDX_TO_ENT(tmp_idx)); 2006 } 2007 } 2008 2009 ALPM_INFO(("**ACB(%d).BNK.MRG: RBBE from(%d %d %d *) to(%d %d %d *)\n", 2010 ACB_IDX(acb), 2011 PVT_ROFS(pvt_node), 2012 PVT_BKT_IDX(pvt_node), sbnk, 2013 PVT_ROFS(pvt_node), 2014 PVT_BKT_IDX(pvt_node), dbnk)); 2015 2016 return rv; 2017 } 2018 2019 /* Merge */ 2020 stab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, sbnk); 2021 rv = th3_mem_read(u, acb, BPC_BKT_TBL(bp_conf), 2022 stab_idx, srcbnke, FALSE); 2023 ALPM_IER(rv); 2024 dtab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, dbnk); 2025 rv = th3_mem_read(u, acb, BPC_BKT_TBL(bp_conf), 2026 dtab_idx, dstbnke, FALSE); 2027 ALPM_IER(rv); 2028 2029 sb_fmt = ACB_FMT_BNK(acb, vrf_id, src_fid); 2030 db_fmt = ACB_FMT_BNK(acb, vrf_id, dst_fid); 2031 for (i = 0; i < depb; i++) { 2032 /* to entry i */ 2033 if (bkt_info->vet_bmp[dbnk] & (1 << i)) { 2034 continue; 2035 } 2036 for (j = 0; j < sepb; j++) { 2037 if (!(bkt_info->vet_bmp[sbnk] & (1 << j))) { 2038 continue; 2039 } 2040 /* from entry j */ 2041 if (sb_fmt != db_fmt) { 2042 uint32 src_idx, dst_idx; 2043 src_idx = ALPM_IDX_MAKE(acb, bkt_info, sbnk, j); 2044 dst_idx = ALPM_IDX_MAKE(acb, bkt_info, dbnk, i); 2045 th3_alpm_ent_copy(u, vrf_id, acb, srcbnke, dstbnke, 2046 &PVT_BKT_INFO(pvt_node), 2047 &PVT_BKT_INFO(pvt_node), 2048 PVT_KEY_LEN(pvt_node), 2049 PVT_KEY_LEN(pvt_node), 2050 src_idx, dst_idx); 2051 } else { 2052 sal_memset(tempent, 0, sizeof(tempent)); 2053 (void)soc_format_field_get(u, sb_fmt, srcbnke, 2054 th3_alpm_ent_fld[j], tempent); 2055 (void)soc_format_field_set(u, db_fmt, dstbnke, 2056 th3_alpm_ent_fld[i], tempent); 2057 } 2058 /* Invalidate entry j */ 2059 sal_memset(nullent, 0, sizeof(nullent)); 2060 (void)soc_format_field_set(u, sb_fmt, srcbnke, 2061 th3_alpm_ent_fld[j], nullent); 2062 2063 bkt_info->vet_bmp[sbnk] &= ~(1 << j); 2064 bkt_info->vet_bmp[dbnk] |= (1 << i); 2065 2066 ALPM_INFO(( 2067 "**ACB(%d).BNK.MRG: RBBE from(%d %d %d %d) to(%d %d %d %d)\n", 2068 ACB_IDX(acb), 2069 PVT_ROFS(pvt_node), PVT_BKT_IDX(pvt_node), sbnk, j, 2070 PVT_ROFS(pvt_node), PVT_BKT_IDX(pvt_node), dbnk, i)); 2071 2072 /* Update ent_idx of prefix */ 2073 for (k = 0; k < pfx_arr->pfx_cnt; k++) { 2074 tmp_idx = pfx_arr->pfx[k]->ent_idx; 2075 if (ALPM_IDX_TO_BNK(acb, tmp_idx) == sbnk && 2076 ALPM_IDX_TO_ENT(tmp_idx) == j) { 2077 pfx_arr->pfx[k]->ent_idx = 2078 ALPM_IDX_MAKE(acb, bkt_info, dbnk, i); 2079 } 2080 } 2081 break; 2082 } 2083 } 2084 2085 bulk_idx[0] = dtab_idx; 2086 bulk_ent[0] = dstbnke; 2087 bulk_cnt = 1; 2088 if (bkt_info->vet_bmp[sbnk]) { 2089 bulk_idx[1] = stab_idx; 2090 bulk_ent[1] = srcbnke; 2091 bulk_cnt ++; 2092 } 2093 rv = th3_mem_bulk_write(u, acb, pvt_node, BPC_BKT_TBL(bp_conf), 2094 bulk_idx, bulk_ent, bulk_cnt); 2095 2096 return rv; 2097 } 2098 2099 int 2100 th3_alpm_bkt_pfx_copy(int u, _alpm_cb_t *acb, 2101 _alpm_bkt_pfx_arr_t *pfx_arr, 2102 _alpm_pvt_node_t *opvt_node, 2103 _alpm_pvt_node_t *npvt_node) 2104 { 2105 int i, rv = BCM_E_NONE; 2106 int vrf_id; 2107 uint32 src_idx, dst_idx = 0; 2108 uint8 def_fmt; 2109 uint16 sb_cnt[ALPM_BPB_MAX] = {0}; 2110 uint16 db_cnt[ALPM_BPB_MAX] = {0}; 2111 uint32 srcbnke[ALPM_BPB_MAX][17]; 2112 uint32 dstbnke[ALPM_BPB_MAX][17]; 2113 2114 int bulk_idx[ALPM_BPB_MAX]; 2115 uint32 *bulk_ent[ALPM_BPB_MAX]; 2116 int bulk_ent_cnt = 0; 2117 2118 _alpm_bkt_info_t *src_bkt, *dst_bkt; 2119 _alpm_bkt_pool_conf_t *bp_conf; 2120 2121 vrf_id = PVT_BKT_VRF(opvt_node); 2122 src_bkt = &PVT_BKT_INFO(opvt_node); 2123 dst_bkt = &PVT_BKT_INFO(npvt_node); 2124 bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id); 2125 2126 for (i = 0; i < pfx_arr->pfx_cnt; i++) { 2127 sb_cnt[ALPM_IDX_TO_BNK(acb, pfx_arr->pfx[i]->ent_idx)]++; 2128 } 2129 2130 for (i = 0; i < ALPM_BPB_MAX; i++) { 2131 if (sb_cnt[i] == 0) { 2132 continue; 2133 } 2134 rv = th3_mem_read(u, acb, BPC_BKT_TBL(bp_conf), 2135 ALPM_TAB_IDX_GET_BI_BNK(acb, src_bkt, i), 2136 srcbnke[i], FALSE); 2137 ALPM_IER(rv); 2138 } 2139 2140 def_fmt = alpm_util_bkt_def_fmt_get(u, acb, vrf_id, PVT_BKT_IPT(opvt_node)); 2141 sal_memset(dstbnke, 0, sizeof(dstbnke)); 2142 for (i = 0; i < pfx_arr->pfx_cnt; i++) { 2143 src_idx = pfx_arr->pfx[i]->ent_idx; 2144 rv = alpm_bkt_ent_get_attempt(u, acb, 2145 ACB_BKT_VRF_POOL(acb, vrf_id), 2146 dst_bkt, def_fmt, 2147 pfx_arr->pfx[i]->key_len - PVT_KEY_LEN(npvt_node), 2148 &dst_idx, NULL, 0); 2149 /* We should not see a FULL here */ 2150 ALPM_IER(rv); 2151 2152 th3_alpm_ent_copy(u, vrf_id, acb, 2153 srcbnke[ALPM_IDX_TO_BNK(acb, src_idx)], 2154 dstbnke[ALPM_IDX_TO_BNK(acb, dst_idx)], 2155 src_bkt, dst_bkt, 2156 PVT_KEY_LEN(opvt_node), 2157 PVT_KEY_LEN(npvt_node), 2158 src_idx, dst_idx); 2159 2160 db_cnt[ALPM_IDX_TO_BNK(acb, dst_idx)]++; 2161 pfx_arr->pfx[i]->ent_idx = dst_idx; 2162 if (!ALPM_HIT_SKIP(u)) { 2163 th3_alpm_ent_hit_move(u, vrf_id, acb, src_idx, dst_idx); 2164 } 2165 } 2166 2167 for (i = 0; i < ALPM_BPB_MAX; i++) { 2168 if (db_cnt[i] == 0) { 2169 continue; 2170 } 2171 2172 bulk_idx[bulk_ent_cnt] = ALPM_TAB_IDX_GET_BI_BNK(acb, dst_bkt, i); 2173 bulk_ent[bulk_ent_cnt] = dstbnke[i]; 2174 bulk_ent_cnt ++; 2175 } 2176 2177 rv = th3_mem_bulk_write(u, acb, npvt_node, 2178 BPC_BKT_TBL(bp_conf), 2179 bulk_idx, bulk_ent, bulk_ent_cnt); 2180 2181 ALPM_IER(rv); 2182 2183 /* TH3TBD: rollback@err */ 2184 return rv; 2185 } 2186 2187 int 2188 th3_alpm_bkt_pfx_clean(int u, _alpm_cb_t *acb, 2189 _alpm_pvt_node_t *pvt_node, 2190 int count, uint32 *ent_idx) 2191 { 2192 int i, rv = BCM_E_NONE; 2193 int vrf_id; 2194 uint32 src_idx, ent_id; 2195 /* Bulk write */ 2196 int bulk_idx[ALPM_BPB_MAX]; 2197 uint32 *bulk_ent[ALPM_BPB_MAX]; 2198 int bulk_ent_cnt = 0; 2199 2200 soc_format_t bnk_fmt; 2201 2202 uint16 srcbnk[ALPM_BPB_MAX] = {0}; 2203 uint32 srcbnke[ALPM_BPB_MAX][17]; 2204 2205 _alpm_bkt_pool_conf_t *bp_conf; 2206 2207 vrf_id = PVT_BKT_VRF(pvt_node); 2208 bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id); 2209 2210 for (i = 0; i < count; i++) { 2211 srcbnk[ALPM_IDX_TO_BNK(acb, ent_idx[i])]++; 2212 } 2213 2214 for (i = 0; i < ALPM_BPB_MAX; i++) { 2215 if (srcbnk[i] == 0) { 2216 continue; 2217 } 2218 rv = th3_mem_read(u, acb, BPC_BKT_TBL(bp_conf), 2219 ALPM_TAB_IDX_GET_BI_BNK(acb, &PVT_BKT_INFO(pvt_node), i), 2220 srcbnke[i], FALSE); 2221 ALPM_IER(rv); 2222 } 2223 2224 /* Clear corresponding entry from bank */ 2225 for (i = 0; i < count; i++) { 2226 uint32 *vet_bmp; 2227 uint32 tmpe[17] = {0}; 2228 int8 fmt_tp; 2229 int bnk_idx; 2230 2231 src_idx = ent_idx[i]; 2232 bnk_idx = ALPM_IDX_TO_BNK(acb, src_idx); 2233 fmt_tp = th3_alpm_bnk_fmt_get(u, acb, &PVT_BKT_INFO(pvt_node), src_idx); 2234 bnk_fmt = BPC_FMT_BNK(bp_conf, fmt_tp); 2235 ent_id = ALPM_IDX_TO_ENT(src_idx); 2236 vet_bmp = &(PVT_BKT_INFO(pvt_node).vet_bmp[bnk_idx]); 2237 *vet_bmp = (*vet_bmp) & ~(1 << ent_id); 2238 if (*vet_bmp) { 2239 (void)soc_format_field_set(u, bnk_fmt, 2240 srcbnke[bnk_idx], 2241 th3_alpm_ent_fld[ent_id], tmpe); 2242 } else { 2243 srcbnk[bnk_idx] = 0; 2244 } 2245 } 2246 2247 for (i = 0; i < ALPM_BPB_MAX; i++) { 2248 if (srcbnk[i] == 0) { 2249 continue; 2250 } 2251 2252 bulk_idx[bulk_ent_cnt] = 2253 ALPM_TAB_IDX_GET_BI_BNK(acb, &PVT_BKT_INFO(pvt_node), i); 2254 bulk_ent[bulk_ent_cnt] = srcbnke[i]; 2255 bulk_ent_cnt ++; 2256 } 2257 2258 rv = th3_mem_bulk_write(u, acb, pvt_node, 2259 BPC_BKT_TBL(bp_conf), 2260 bulk_idx, bulk_ent, bulk_ent_cnt); 2261 2262 ALPM_IER(rv); 2263 2264 if (!ALPM_HIT_SKIP(u)) { 2265 for (i = 0; i < count; i++) { 2266 _alpm_tbl_t tbl = alpmTblInvalid; 2267 src_idx = ent_idx[i]; 2268 tbl = ACB_BKT_TBL(acb, vrf_id); 2269 th3_alpm_bkt_hit_write(u, vrf_id, acb, tbl, src_idx, 0); 2270 } 2271 } 2272 2273 return rv; 2274 } 2275 2276 /* Only do defrag inside a bucket */ 2277 int 2278 th3_alpm_bkt_pfx_shrink(int u, _alpm_cb_t *acb, 2279 _alpm_pvt_node_t *pvt_node, 2280 _alpm_bkt_pfx_arr_t *pfx_arr, 2281 int shrink_empty_only) 2282 { 2283 int tb, fb, tbnk, fbnk; 2284 int rv = BCM_E_NONE; 2285 int start, close, step; 2286 int bnkpb = ACB_BNK_PER_BKT(acb, PVT_BKT_VRF(pvt_node)); 2287 2288 _alpm_bkt_info_t *bkt_info = NULL; 2289 2290 bkt_info = &PVT_BKT_INFO(pvt_node); 2291 2292 #if 0 /* TH3TBD ??? */ 2293 if (bkt_info->bkt_idx == 0) { 2294 return rv; 2295 } 2296 #endif 2297 2298 if (bkt_info->reverse == 0) { 2299 start = BI_ROFS(bkt_info); 2300 close = BI_ROFS(bkt_info) + bnkpb; 2301 step = 1; 2302 } else { 2303 start = BI_ROFS(bkt_info) + bnkpb - 1; 2304 close = BI_ROFS(bkt_info) - 1; 2305 step = -1; 2306 } 2307 2308 for (tb = start; ABS(tb-close) > 0; tb += step) { 2309 tbnk = tb % bnkpb; 2310 /* Found a used tbnk */ 2311 if (!BI_BNK_IS_USED(bkt_info, tbnk)) { 2312 continue; 2313 } 2314 for (fb = (close - step); ABS(fb-tb) > 0; fb -= step) { 2315 fbnk = fb % bnkpb; 2316 /* Bank fb empty */ 2317 if (!BI_BNK_IS_USED(bkt_info, fbnk) || 2318 bkt_info->vet_bmp[fbnk] == 0) { 2319 continue; 2320 } 2321 2322 /* Bank tb empty, Bank fb occupied */ 2323 if (bkt_info->vet_bmp[tbnk] == 0) { 2324 rv = th3_alpm_bkt_bnk_shrink(u, acb, pvt_node, fbnk, tbnk, 2325 pfx_arr); 2326 ALPM_IER(rv); 2327 } else if (bkt_info->bnk_fmt[tbnk] >= bkt_info->bnk_fmt[fbnk]) { 2328 /* Bank tb & fb are same type and both occupied */ 2329 if (!shrink_empty_only) { 2330 rv = th3_alpm_bkt_bnk_shrink(u, acb, pvt_node, fbnk, 2331 tbnk, pfx_arr); 2332 ALPM_IER(rv); 2333 } 2334 } 2335 } 2336 } 2337 2338 return rv; 2339 } 2340 2341 int 2342 th3_alpm_bkt_bnk_copy(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, 2343 _alpm_bkt_info_t *src_bkt, _alpm_bkt_info_t *dst_bkt, 2344 int src_idx, int dst_idx) 2345 { 2346 int rv = BCM_E_NONE; 2347 uint32 ent[ALPM_ENT_WORDS_MAX] = {0}; 2348 2349 _alpm_tbl_t tbl = alpmTblInvalid; 2350 2351 if (pvt_node != NULL) { 2352 tbl = BPC_BKT_TBL(ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node))); 2353 } 2354 2355 if (tbl != alpmTblInvalid) { 2356 ALPM_IER( 2357 th3_mem_read(u, acb, tbl, src_idx, ent, FALSE)); 2358 ALPM_IER( 2359 th3_mem_write(u, acb, pvt_node, tbl, dst_idx, ent)); 2360 2361 if (!ALPM_HIT_SKIP(u)) { 2362 th3_alpm_bnk_hit_move(u, PVT_BKT_VRF(pvt_node), 2363 acb, src_idx, dst_idx); 2364 } 2365 } 2366 2367 return rv; 2368 } 2369 2370 int 2371 th3_alpm_bkt_bnk_clear(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, 2372 int tab_idx) 2373 { 2374 int rv = BCM_E_NONE; 2375 _alpm_tbl_t tbl = alpmTblInvalid; 2376 2377 if (pvt_node != NULL) { 2378 tbl = ACB_BKT_TBL(acb, PVT_BKT_VRF(pvt_node)); 2379 ALPM_IER(th3_mem_write(u, acb, pvt_node, tbl, tab_idx, NULL)); 2380 2381 if (!ALPM_HIT_SKIP(u)) { 2382 th3_alpm_bnk_hit_clear(u, PVT_BKT_VRF(pvt_node), acb, tab_idx); 2383 } 2384 } 2385 2386 return rv; 2387 } 2388 2389 /* TCAM related functions */ 2390 int 2391 th3_tcam_table_sz(int u, int pkm) 2392 { 2393 int sz = 0; 2394 soc_mem_t mem; 2395 mem = alpm_tbl[ACB_TOP(u)->pvt_tbl[pkm]]; 2396 2397 if (mem != INVALIDm) { 2398 sz = soc_mem_index_count(u, mem); 2399 2400 if (SOC_URPF_STATUS_GET(u)) { 2401 sz >>= 1; 2402 } 2403 } 2404 return sz; 2405 } 2406 2407 /* TCAM Hw table cleanup (fast delete_all) */ 2408 int 2409 th3_tcam_hw_cleanup(int u) 2410 { 2411 soc_mem_t mem; 2412 _alpm_cb_t *acb = ACB_TOP(u); 2413 int pkm, tbl_sz; 2414 int rv = BCM_E_NONE; 2415 2416 for (pkm = 0; pkm < ALPM_PKM_CNT; pkm++) { 2417 2418 if (ALPM_TCAM_TBL_SKIP(u, pkm)) { 2419 continue; /* skip duplicated or invalid TCAM table */ 2420 } 2421 2422 mem = alpm_tbl[acb->pvt_tbl[pkm]]; 2423 tbl_sz = th3_tcam_table_sz(u, pkm); 2424 if (tbl_sz) { 2425 th3_alpm_hw_mem_clear(u, mem); 2426 } 2427 } 2428 2429 return rv; 2430 } 2431 2432 /* 2433 * x | y 2434 * -------------------- 2435 * 0 | 0 : entry0_to_0 2436 * 0 | 1 : entry0_to_1 2437 * 1 | 0 : entry1_to_0 2438 * 1 | 1 : entry1_to_1 2439 * src and dst can be same 2440 */ 2441 int 2442 th3_tcam_entry_x_to_y(int u, int pkm, void *src, void *dst, 2443 int copy_hit, int x, int y) 2444 { 2445 int i; 2446 uint32 val[SOC_MAX_MEM_FIELD_WORDS] = {0}; 2447 soc_mem_t mem; 2448 _alpm_cb_t *acb = ACB_TOP(u); 2449 2450 #define _FLD_CNT 6 2451 soc_field_t fld[2][_FLD_CNT] = 2452 { 2453 { 2454 VALID0f, 2455 KEY0f, 2456 MASK0f, 2457 ASSOC_DATA0f, 2458 ALPM1_DATA0f, 2459 FIXED_DATA0f 2460 }, 2461 { 2462 VALID1f, 2463 KEY1f, 2464 MASK1f, 2465 ASSOC_DATA1f, 2466 ALPM1_DATA1f, 2467 FIXED_DATA1f 2468 } 2469 }; 2470 soc_field_t hit[2] = {HIT0f, HIT1f}; 2471 2472 mem = alpm_tbl[acb->pvt_tbl[pkm]]; 2473 for (i = 0; i < _FLD_CNT; i++) { 2474 soc_mem_field_get(u, mem, src, fld[x][i], val); 2475 soc_mem_field_set(u, mem, dst, fld[y][i], val); 2476 } 2477 2478 if (copy_hit) { 2479 soc_mem_field_get(u, mem, src, hit[x], val); 2480 soc_mem_field_set(u, mem, dst, hit[y], val); 2481 } 2482 2483 return BCM_E_NONE; 2484 } 2485 2486 /* 2487 * field mapping: 2488 * 2489 * defip_flags 2490 * BCM_L3_HIT -> HIT0f 2491 * BCM_L3_RPE -> ASSOC_DATA0 -> RPE 2492 * BCM_L3_MULTIPATH -> ASSOC_DATA0 -> DEST_TYPE 2493 * BCM_L3_DST_DISCARD -> ASSOC_DATA0 -> DST_DISCARD 2494 * BCM_L3_IP6 -> KEY0 -> KEY_MODE 2495 * -> KEY0 -> KEY_TYPE 2496 * defip_prio -> ASSOC_DATA0 -> PRI 2497 * defip_ecmp_index -> ASSOC_DATA0 -> DESTINATION 2498 * defip_lookup_class -> ASSOC_DATA0 -> CLASS_ID 2499 * defip_vrf 2500 * BCM_L3_VRF_GLOBAL -> ALPM1_DATA -> DIRECT_ROUTE 2501 * -> FIXED_DATA0 -> SUB_DB_PRIORITY 2502 * 2503 * BCM_L3_VRF_OVERRIDE -> ALPM1_DATA -> DIRECT_ROUTE 2504 * -> FIXED_DATA0 -> SUB_DB_PRIORITY 2505 * 2506 * other -> KEY0 -> VRF_ID 2507 * -> MASK0 -> VRF_ID 2508 * -> FIXED_DATA0 -> SUB_DB_PRIORITY 2509 * 2510 * defip_sub_len -> MASK0 -> IP_ADDR 2511 * defip_ip_addr -> KEY0 -> IP_ADDR 2512 * defip_ip6_addr -> KEY0 -> IP_ADDR 2513 * 2514 * defip_flex_ctr_base_id -> ASSOC_DATA0 -> FLEX_CTR_BASE_COUNTER_IDX 2515 * defip_flex_ctr_mode -> ASSOC_DATA0 -> FLEX_CTR_OFFSET_MODE 2516 * defip_flex_ctr_pool -> ASSOC_DATA0 -> FLEX_CTR_POOL_NUMBER 2517 */ 2518 int 2519 th3_tcam_entry_from_cfg(int u, int pkm, _bcm_defip_cfg_t *lpm_cfg, void *e, int x, uint32 write_flags) 2520 { 2521 int i, b, cnt = 2; 2522 uint32 key[4] = {0}; 2523 uint32 msk[4] = {0}; 2524 uint32 val; 2525 2526 soc_mem_t mem; 2527 _alpm_cb_t *acb = ACB_TOP(u); 2528 _alpm_pvt_node_t *pvt_node; 2529 _alpm_bkt_pool_conf_t *bp_conf; 2530 2531 soc_field_t hit_fld[] = {HIT0f, HIT1f}; 2532 soc_field_t asd_fld[] = {ASSOC_DATA0f, ASSOC_DATA1f}; 2533 soc_field_t fix_fld[] = {FIXED_DATA0f, FIXED_DATA1f}; 2534 soc_field_t bkt_fld[] = {ALPM1_DATA0f, ALPM1_DATA1f}; 2535 soc_field_t vld_fld[] = {VALID0f, VALID1f}; 2536 soc_field_t key_fld[] = {KEY0f, KEY1f, KEY0_UPRf, KEY1_UPRf}; 2537 soc_field_t msk_fld[] = {MASK0f, MASK1f, MASK0_UPRf, MASK1_UPRf}; 2538 2539 th3_fmt_FIXED_DATA_t fmt_fd; 2540 th3_fmt_ASSOC_DATA_FULL_t fmt_asf; 2541 th3_fmt_L3_DEFIP_TCAM_KEY_t fmt_tk; 2542 th3_fmt_ALPM1_DATA_t fmt_a1d; 2543 2544 mem = alpm_tbl[acb->pvt_tbl[pkm]]; 2545 if (SOC_MEM_FIELD_VALID(u, mem, ASSOC_DATA0f)) { 2546 if (pkm == ALPM_PKM_32B) { 2547 hit_fld[!x] = hit_fld[!!x]; 2548 asd_fld[!x] = asd_fld[!!x]; 2549 fix_fld[!x] = fix_fld[!!x]; 2550 bkt_fld[!x] = bkt_fld[!!x]; 2551 vld_fld[!x] = vld_fld[!!x]; 2552 key_fld[!x] = key_fld[!!x]; 2553 msk_fld[!x] = msk_fld[!!x]; 2554 cnt = 1; 2555 } 2556 } else { 2557 hit_fld[0] = LWR_HIT0f; 2558 hit_fld[1] = LWR_HIT1f; 2559 asd_fld[0] = LWR_ASSOC_DATA0f; 2560 asd_fld[1] = LWR_ASSOC_DATA1f; 2561 fix_fld[0] = LWR_FIXED_DATA0f; 2562 fix_fld[1] = LWR_FIXED_DATA1f; 2563 bkt_fld[0] = LWR_ALPM1_DATA0f; 2564 bkt_fld[1] = LWR_ALPM1_DATA1f; 2565 vld_fld[0] = LWR_VALID0f; 2566 vld_fld[1] = LWR_VALID1f; 2567 key_fld[0] = KEY0_LWRf; 2568 key_fld[1] = KEY1_LWRf; 2569 msk_fld[0] = MASK0_LWRf; 2570 msk_fld[1] = MASK1_LWRf; 2571 } 2572 2573 for (i = 0; i < cnt; i++) { 2574 if (write_flags & ALPM_PVT_UPDATE_PREFIX) { 2575 soc_mem_field32_set(u, mem, e, vld_fld[i], 1); 2576 if (lpm_cfg->defip_flags & BCM_L3_HIT) { 2577 soc_mem_field32_set(u, mem, e, hit_fld[i], 1); 2578 } 2579 } 2580 2581 /* ASSOC_DATAf format */ 2582 if (write_flags & ALPM_PVT_UPDATE_ASSOC_DATA) { 2583 sal_memset(&fmt_asf, 0, sizeof(fmt_asf)); 2584 fmt_asf.RPE = lpm_cfg->defip_flags & BCM_L3_RPE ? 1 : 0; 2585 fmt_asf.DEST_TYPE = lpm_cfg->defip_flags & BCM_L3_MULTIPATH ? 1 : 0; 2586 fmt_asf.DESTINATION = lpm_cfg->defip_ecmp_index; 2587 fmt_asf.DST_DISCARD = lpm_cfg->defip_flags & BCM_L3_DST_DISCARD ? 1 : 0; 2588 fmt_asf.PRI = lpm_cfg->defip_prio; 2589 fmt_asf.CLASS_ID = lpm_cfg->defip_lookup_class; 2590 fmt_asf.FLEX_CTR_BASE_COUNTER_IDX = lpm_cfg->defip_flex_ctr_base_id; 2591 fmt_asf.FLEX_CTR_OFFSET_MODE = lpm_cfg->defip_flex_ctr_mode; 2592 fmt_asf.FLEX_CTR_POOL_NUMBER = lpm_cfg->defip_flex_ctr_pool; 2593 soc_mem_field_set(u, mem, e, asd_fld[i], (uint32 *)&fmt_asf); 2594 } 2595 2596 /* FIXED_DATAf format */ 2597 if (write_flags & ALPM_PVT_UPDATE_PREFIX) { 2598 sal_memset(&fmt_fd, 0, sizeof(fmt_fd)); 2599 switch (lpm_cfg->defip_vrf) { 2600 case BCM_L3_VRF_GLOBAL: 2601 val = 2; 2602 break; 2603 case BCM_L3_VRF_OVERRIDE: 2604 val = 0; 2605 break; 2606 default: 2607 val = 1; 2608 break; 2609 } 2610 fmt_fd.SUB_DB_PRIORITY = val; 2611 soc_mem_field_set(u, mem, e, fix_fld[i], (uint32 *)&fmt_fd); 2612 } 2613 2614 /* ALPM1_DATAf format */ 2615 if (write_flags & ALPM_PVT_UPDATE_ALPM_DATA) { 2616 sal_memset(&fmt_a1d, 0, sizeof(fmt_a1d)); 2617 2618 fmt_a1d.DIRECT_ROUTE = ALPM_LPM_DIRECT_RTE(u, lpm_cfg); 2619 if (ALPM_TCAM_ZONED(u) && lpm_cfg->default_miss == 1) { 2620 /* TH3TBD, Parallel & Mixed ALPM need to set DEFAULT_MISS to 1 2621 * if assoc_data is NOT set, in case of missing default */ 2622 fmt_a1d.DEFAULT_MISS = 1; 2623 } 2624 pvt_node = (_alpm_pvt_node_t *)lpm_cfg->pvt_node; 2625 if (pvt_node != NULL) { 2626 int offset = 0; 2627 _alpm_tbl_t tbl; 2628 _alpm_bkt_info_t *bkt_info = &PVT_BKT_INFO(pvt_node); 2629 2630 bp_conf = ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node)); 2631 tbl = BPC_BKT_TBL(bp_conf); 2632 switch (tbl) { 2633 case alpmTblBktPmodeGblL2: 2634 case alpmTblBktPmodeGblL3: 2635 offset = ACB_BNK_PER_BKT(acb, 1); 2636 break; 2637 default: 2638 break; 2639 } 2640 fmt_a1d.KSHIFT = PVT_KEY_LEN(pvt_node); 2641 fmt_a1d.ROFS = PVT_ROFS(pvt_node) + offset; 2642 fmt_a1d.BKT_PTR = PVT_BKT_IDX(pvt_node); 2643 for (b = 0; b < BPC_BNK_PER_BKT(bp_conf); b++) { 2644 soc_field_t bnk_fld; 2645 if (!BI_BNK_IS_USED(bkt_info, b)) { 2646 continue; 2647 } 2648 bnk_fld = th3_alpm_bnk_fld[b+offset]; 2649 switch (bnk_fld) { 2650 case FMT0f: 2651 fmt_a1d.FMT0 = bkt_info->bnk_fmt[b]; 2652 break; 2653 case FMT1f: 2654 fmt_a1d.FMT1 = bkt_info->bnk_fmt[b]; 2655 break; 2656 case FMT2f: 2657 fmt_a1d.FMT2_0_1 = bkt_info->bnk_fmt[b] & 0x3; 2658 fmt_a1d.FMT2_2_3 = (bkt_info->bnk_fmt[b] >> 2) & 0x3; 2659 break; 2660 case FMT3f: 2661 fmt_a1d.FMT3 = bkt_info->bnk_fmt[b]; 2662 break; 2663 case FMT4f: 2664 fmt_a1d.FMT4 = bkt_info->bnk_fmt[b]; 2665 break; 2666 default: 2667 break; 2668 } 2669 } 2670 } 2671 soc_mem_field_set(u, mem, e, bkt_fld[i], (uint32 *)&fmt_a1d); 2672 } /* if (write_flags & ALPM_PVT_UPDATE_ASSOC_DATA) */ 2673 } 2674 2675 if (hit_fld[0] == LWR_HIT0f) { 2676 soc_mem_field32_set(u, mem, e, UPR_VALIDf, 3); 2677 } 2678 2679 if (write_flags & ALPM_PVT_UPDATE_PREFIX) { 2680 /* Program KEY & MASK 2681 * 2682 * key[4] = {key[0], key[1], key[2], key[3]} 2683 * ipv4: key[4] = 2684 * {IP_ADDR0f, 0, 0, 0} 2685 * ipv6-64: key[4] = 2686 * {IP_ADDR0f, IP_ADDR1f, 0, 0} 2687 * ipv6-128: key[4] = 2688 * {IP_ADDR0_LWRf, IP_ADDR1_LWRf, IP_ADDR0_UPRf, IP_ADDR1_UPRf} 2689 */ 2690 alpm_util_cfg_to_key(u, ALPM_PKM2IPT(pkm), lpm_cfg, key); 2691 alpm_util_cfg_to_msk(u, ALPM_PKM2IPT(pkm), lpm_cfg, msk); 2692 if (hit_fld[0] == LWR_HIT0f) { 2693 cnt = 4; 2694 } 2695 2696 switch (pkm) { 2697 case ALPM_PKM_32B: 2698 val = 0; 2699 break; 2700 case ALPM_PKM_64B: 2701 key[1] = key[3]; 2702 key[0] = key[2]; 2703 msk[1] = msk[3]; 2704 msk[0] = msk[2]; 2705 val = 1; 2706 break; 2707 case ALPM_PKM_128: 2708 val = 3; 2709 break; 2710 default: 2711 val = 0; 2712 break; 2713 } 2714 2715 for (i = 0; i < cnt; i++) { 2716 /* KEY */ 2717 sal_memset(&fmt_tk, 0, sizeof(fmt_tk)); 2718 fmt_tk.KEY_MODE = val; 2719 fmt_tk.KEY_TYPE = (lpm_cfg->defip_flags & BCM_L3_IP6) ? 1 : 0; 2720 fmt_tk.IP_ADDR_0_28 = key[i] & 0x1fffffff; 2721 fmt_tk.IP_ADDR_29_31 = (key[i] >> 29) & 0x7; 2722 fmt_tk.VRF_ID = lpm_cfg->defip_vrf >= 0 ? lpm_cfg->defip_vrf : 0; 2723 soc_mem_field_set(u, mem, e, key_fld[i], (uint32 *)&fmt_tk); 2724 2725 /* MASK */ 2726 sal_memset(&fmt_tk, 0, sizeof(fmt_tk)); 2727 fmt_tk.KEY_MODE = 0x3; 2728 fmt_tk.KEY_TYPE = 0x1; 2729 fmt_tk.IP_ADDR_0_28 = msk[i] & 0x1fffffff; 2730 fmt_tk.IP_ADDR_29_31 = (msk[i] >> 29) & 0x7; 2731 fmt_tk.VRF_ID = lpm_cfg->defip_vrf >= 0 ? 0xfff : 0; 2732 soc_mem_field_set(u, mem, e, msk_fld[i], (uint32 *)&fmt_tk); 2733 } 2734 } 2735 2736 return BCM_E_NONE; 2737 } 2738 2739 int 2740 th3_tcam_entry_to_cfg(int u, int pkm, void *e, int x, 2741 _bcm_defip_cfg_t *lpm_cfg) 2742 { 2743 uint32 val; 2744 soc_mem_t mem; 2745 th3_fmt_ASSOC_DATA_FULL_t fmte; 2746 _alpm_cb_t *acb = ACB_TOP(u); 2747 2748 soc_field_t hit_fld[] = {HIT0f, HIT1f}; 2749 soc_field_t asd_fld[] = {ASSOC_DATA0f, ASSOC_DATA1f}; 2750 soc_field_t fix_fld[] = {FIXED_DATA0f, FIXED_DATA1f}; 2751 soc_field_t bkt_fld[] = {ALPM1_DATA0f, ALPM1_DATA1f}; 2752 2753 mem = alpm_tbl[acb->pvt_tbl[pkm]]; 2754 if (SOC_MEM_FIELD_VALID(u, mem, ASSOC_DATA0f)) { 2755 if (pkm == ALPM_PKM_32B) { 2756 hit_fld[!x] = hit_fld[!!x]; 2757 asd_fld[!x] = asd_fld[!!x]; 2758 fix_fld[!x] = fix_fld[!!x]; 2759 bkt_fld[!x] = bkt_fld[!!x]; 2760 } 2761 } else { 2762 hit_fld[0] = LWR_HIT0f; 2763 asd_fld[0] = LWR_ASSOC_DATA0f; 2764 fix_fld[0] = LWR_FIXED_DATA0f; 2765 bkt_fld[0] = LWR_ALPM1_DATA0f; 2766 } 2767 2768 #define _LPM_DEFIP_FLAGS_SET(val, flag) \ 2769 do { \ 2770 if (val) { \ 2771 lpm_cfg->defip_flags |= flag; \ 2772 } else { \ 2773 lpm_cfg->defip_flags &= ~flag; \ 2774 } \ 2775 } while (0) 2776 2777 val = soc_mem_field32_get(u, mem, e, hit_fld[0]); 2778 _LPM_DEFIP_FLAGS_SET(val, BCM_L3_HIT); 2779 2780 /* ASSOC_DATAf format */ 2781 soc_mem_field_get(u, mem, e, asd_fld[0], (uint32 *)&fmte); 2782 val = fmte.RPE; 2783 _LPM_DEFIP_FLAGS_SET(val, BCM_L3_RPE); 2784 2785 val = fmte.DEST_TYPE; 2786 _LPM_DEFIP_FLAGS_SET(val, BCM_L3_MULTIPATH); 2787 if (val) { 2788 lpm_cfg->defip_ecmp = 1; 2789 } else { 2790 lpm_cfg->defip_ecmp = 0; 2791 lpm_cfg->defip_ecmp_count = 0; 2792 } 2793 2794 lpm_cfg->defip_ecmp_index = fmte.DESTINATION; 2795 2796 val = fmte.DST_DISCARD; 2797 _LPM_DEFIP_FLAGS_SET(val, BCM_L3_DST_DISCARD); 2798 2799 lpm_cfg->defip_prio = fmte.PRI; 2800 lpm_cfg->defip_lookup_class = fmte.CLASS_ID; 2801 lpm_cfg->defip_flex_ctr_base_id = fmte.FLEX_CTR_BASE_COUNTER_IDX; 2802 lpm_cfg->defip_flex_ctr_mode = fmte.FLEX_CTR_OFFSET_MODE; 2803 lpm_cfg->defip_flex_ctr_pool = fmte.FLEX_CTR_POOL_NUMBER; 2804 2805 /* No need to parse the rest field because there are already in the 2806 * lpm_cfg, part of key */ 2807 2808 return BCM_E_NONE; 2809 } 2810 2811 int 2812 th3_tcam_entry_valid(int u, int pkm, void *e, int sub_idx) 2813 { 2814 int vld_val; 2815 soc_mem_t mem; 2816 soc_field_t vld_fld = VALIDf; 2817 _alpm_cb_t *acb = ACB_TOP(u); 2818 2819 mem = alpm_tbl[acb->pvt_tbl[pkm]]; 2820 if (SOC_MEM_FIELD_VALID(u, mem, VALIDf)) { 2821 vld_fld = VALIDf; 2822 } else { 2823 vld_fld = LWR_VALIDf; 2824 } 2825 2826 vld_val = soc_mem_field32_get(u, mem, e, vld_fld); 2827 2828 return vld_val & (1 << sub_idx) ? 1 : 0; 2829 } 2830 2831 int 2832 th3_tcam_entry_valid_set(int u, int pkm, void *e, int sub_idx, int val) 2833 { 2834 soc_mem_t mem; 2835 soc_field_t vld_fld; 2836 _alpm_cb_t *acb = ACB_TOP(u); 2837 2838 mem = alpm_tbl[acb->pvt_tbl[pkm]]; 2839 switch (pkm) { 2840 case ALPM_PKM_32B: 2841 vld_fld = sub_idx ? VALID1f : VALID0f; 2842 soc_mem_field32_set(u, mem, e, vld_fld, val ? 1 : 0); 2843 break; 2844 case ALPM_PKM_64B: 2845 soc_mem_field32_set(u, mem, e, VALIDf, val ? 3 : 0); 2846 break; 2847 case ALPM_PKM_128: 2848 soc_mem_field32_set(u, mem, e, LWR_VALIDf, val ? 3 : 0); 2849 soc_mem_field32_set(u, mem, e, UPR_VALIDf, val ? 3 : 0); 2850 break; 2851 default: 2852 break; 2853 } 2854 2855 return BCM_E_NONE; 2856 } 2857 2858 static void 2859 th3_tcam_key_fields_get(int u, soc_mem_t mem, void *e, soc_field_t fmt, 2860 int fld_cnt, soc_field_t *flds, uint32 *vals) 2861 { 2862 int i; 2863 th3_fmt_L3_DEFIP_TCAM_KEY_t fmt_tk; 2864 2865 for (i = 0; i < fld_cnt; i++) { 2866 soc_mem_field_get(u, mem, e, fmt, (uint32 *)&fmt_tk); 2867 switch(flds[i]) { 2868 case KEY_MODEf: 2869 vals[i] = fmt_tk.KEY_MODE; 2870 break; 2871 case KEY_TYPEf: 2872 vals[i] = fmt_tk.KEY_TYPE; 2873 break; 2874 case VRF_IDf: 2875 vals[i] = fmt_tk.VRF_ID; 2876 break; 2877 case IP_ADDRf: 2878 vals[i] = (fmt_tk.IP_ADDR_29_31 << 29) | fmt_tk.IP_ADDR_0_28; 2879 break; 2880 default: 2881 break; 2882 } 2883 } 2884 2885 return ; 2886 } 2887 2888 static int 2889 th3_tcam_entry_to_mask_key(int u, int pkm, void *e, int sub_idx, 2890 uint32 *key, int is_mask) 2891 { 2892 int i, fld_cnt; 2893 soc_mem_t mem; 2894 soc_field_t _msk_fld[] = {MASK0f, MASK1f}; 2895 soc_field_t _key_fld[] = {KEY0f, KEY1f}; 2896 soc_field_t _msk_fld_p[] = {MASK0_LWRf, MASK1_LWRf, MASK0_UPRf, MASK1_UPRf}; 2897 soc_field_t _key_fld_p[] = {KEY0_LWRf, KEY1_LWRf, KEY0_UPRf, KEY1_UPRf}; 2898 soc_field_t key_fld = IP_ADDRf; 2899 2900 soc_field_t *_fld, *_fld_p, *fmt; 2901 _alpm_cb_t *acb = ACB_TOP(u); 2902 2903 if (is_mask) { 2904 _fld = _msk_fld; 2905 _fld_p = _msk_fld_p; 2906 } else { 2907 _fld = _key_fld; 2908 _fld_p = _key_fld_p; 2909 } 2910 2911 mem = alpm_tbl[acb->pvt_tbl[pkm]]; 2912 if (SOC_MEM_FIELD_VALID(u, mem, ASSOC_DATA0f)) { 2913 if (pkm == ALPM_PKM_32B) { 2914 fld_cnt = 1; 2915 _fld[0] = _fld[sub_idx]; 2916 } else { 2917 fld_cnt = 2; 2918 } 2919 fmt = _fld; 2920 } else { 2921 fld_cnt = 4; 2922 fmt = _fld_p; 2923 } 2924 2925 sal_memset(key, 0, 4 * sizeof(uint32)); 2926 for (i = 0; i < fld_cnt; i++) { 2927 th3_tcam_key_fields_get(u, mem, e, fmt[i], 1, &key_fld, &key[i]); 2928 } 2929 2930 if (pkm == ALPM_PKM_64B) { 2931 key[3] = key[1]; 2932 key[2] = key[0]; 2933 key[1] = key[0] = 0; 2934 } 2935 2936 return BCM_E_NONE; 2937 2938 } 2939 2940 /* 2941 * key[4] = {key[0], key[1], key[2], key[3]} 2942 * ipv4: key[4] = 2943 * {IP_ADDR0f, 0, 0, 0} 2944 * ipv6-64: key[4] = 2945 * {0, 0, IP_ADDR0f, IP_ADDR1f, } 2946 * ipv6-128: key[4] = 2947 * {IP_ADDR0_LWRf, IP_ADDR1_LWRf, IP_ADDR0_UPRf, IP_ADDR1_UPRf} 2948 */ 2949 int 2950 th3_tcam_entry_to_key(int u, int pkm, void *e, int sub_idx, uint32 *key) 2951 { 2952 return th3_tcam_entry_to_mask_key(u, pkm, e, sub_idx, key, FALSE); 2953 } 2954 2955 int 2956 th3_tcam_entry_vrf_id_get(int u, int pkm, void *e, int sub_idx, int *vrf_id) 2957 { 2958 uint32 fld_val; 2959 soc_mem_t mem; 2960 soc_field_t _glb_fld[] = {FIXED_DATA0f, FIXED_DATA1f}; 2961 soc_field_t _glb_fld_p[] = {LWR_FIXED_DATA0f, LWR_FIXED_DATA1f}; 2962 soc_field_t _vrf_fld[] = {KEY0f, KEY1f}; 2963 soc_field_t _vrf_fld_p[] = {KEY0_LWRf, KEY1_LWRf}; 2964 soc_field_t *glb_fmt, *vrf_fmt; 2965 soc_field_t key_fld = VRF_IDf; 2966 _alpm_cb_t *acb = ACB_TOP(u); 2967 2968 th3_fmt_FIXED_DATA_t fmt_fd; 2969 2970 mem = alpm_tbl[acb->pvt_tbl[pkm]]; 2971 if (SOC_MEM_FIELD_VALID(u, mem, ASSOC_DATA0f)) { 2972 if (pkm == ALPM_PKM_32B) { 2973 _glb_fld[0] = _glb_fld[sub_idx]; 2974 _vrf_fld[0] = _vrf_fld[sub_idx]; 2975 } 2976 glb_fmt = _glb_fld; 2977 vrf_fmt = _vrf_fld; 2978 } else { 2979 glb_fmt = _glb_fld_p; 2980 vrf_fmt = _vrf_fld_p; 2981 } 2982 2983 /* To distinguish Global/Private route */ 2984 soc_mem_field_get(u, mem, e, glb_fmt[0], (uint32 *)&fmt_fd); 2985 fld_val = fmt_fd.SUB_DB_PRIORITY; 2986 if (fld_val == 0) { 2987 /* Global High */ 2988 *vrf_id = ALPM_VRF_ID_GHI(u); 2989 } else if (fld_val == 2) { 2990 /* Global Low */ 2991 *vrf_id = ALPM_VRF_ID_GLO(u); 2992 } else { 2993 /* Private routes */ 2994 th3_tcam_key_fields_get(u, mem, e, vrf_fmt[0], 1, &key_fld, 2995 (uint32 *)vrf_id); 2996 } 2997 2998 2999 return BCM_E_NONE; 3000 } 3001 3002 int 3003 th3_tcam_entry_pfx_len_get(int u, int pkm, void *e, int sub_idx, int *pfx_len) 3004 { 3005 int i, rv = BCM_E_NONE; 3006 uint32 mask[4]; 3007 3008 /* Assuming each MASK field is correct, 3009 * Not my duty to validate MASK here */ 3010 rv = th3_tcam_entry_to_mask_key(u, pkm, e, sub_idx, mask, TRUE); 3011 *pfx_len = 0; 3012 for (i = 0; i < 4; i++) { 3013 *pfx_len += _shr_popcount(mask[i]); 3014 } 3015 3016 return rv; 3017 } 3018 3019 int 3020 th3_tcam_entry_mode_get_by_mem(int u, soc_mem_t mem, void *e, int *step_size, 3021 int *pkm, int *ipv6, int *key_mode, int sub_idx) 3022 { 3023 soc_field_t _key_fld[] = {KEY0f, KEY1f}; 3024 soc_field_t key_fld = KEY0f, vld_fld = VALIDf; 3025 int valid, v6, km; 3026 3027 th3_fmt_L3_DEFIP_TCAM_KEY_t fmt_tk; 3028 3029 if (SOC_MEM_FIELD_VALID(u, mem, VALIDf)) { 3030 key_fld = _key_fld[sub_idx]; 3031 vld_fld = VALIDf; 3032 if (step_size) { 3033 *step_size = 1; /* default step_size for un pair TCAM */ 3034 } 3035 } else { 3036 key_fld = KEY0_LWRf; 3037 vld_fld = LWR_VALIDf; 3038 if (step_size) { 3039 *step_size = 2; /* default step_size for pair TCAM*/ 3040 } 3041 } 3042 3043 valid = soc_mem_field32_get(u, mem, e, vld_fld); 3044 valid &= (1 << sub_idx); 3045 3046 if (!valid) { /* invalid entry */ 3047 return BCM_E_NOT_FOUND; 3048 } 3049 3050 soc_mem_field_get(u, mem, e, key_fld, (uint32 *)&fmt_tk); 3051 km = fmt_tk.KEY_MODE; 3052 if (key_mode) { 3053 *key_mode = km; 3054 } 3055 v6 = fmt_tk.KEY_TYPE; 3056 if (ipv6) { 3057 *ipv6 = v6; 3058 } 3059 3060 /* TH3TBD */ 3061 if (pkm) { 3062 *pkm = (key_fld == KEY0_LWRf) ? ALPM_PKM_128 : 3063 v6 ? ALPM_PKM_64B : ALPM_PKM_32B; 3064 } 3065 3066 /* Wrong key_mode or key_type */ 3067 if ((key_fld != KEY0_LWRf && (km > 1)) || 3068 (key_fld == KEY0_LWRf && (km != 3)) || 3069 (key_fld == KEY0_LWRf && (v6 == 0))) { 3070 return BCM_E_INTERNAL; 3071 } 3072 3073 /* step_size 2 only if full-wide in un pair TCAM */ 3074 if (step_size) { 3075 if (key_fld != KEY0_LWRf && (km == 1)) { 3076 *step_size = 2; 3077 } 3078 } 3079 return BCM_E_NONE; 3080 } 3081 3082 /* 3083 * Function: 3084 * th3_tcam_entry_mode_get 3085 * Purpose: 3086 * Get TCAM valid entry KEY mode and type. 3087 * Parameters: 3088 * u - (In)Device unit 3089 * pk - (In)Input TCAM packing mode table view 3090 * e - (In)TCAM lpm memory entry 3091 * step_size - (Out)Key mode step-size (un pair: 1 or 2, pair: 2) 3092 * p km - (Out)Detected packing mode 3093 * ipv6 - (Out)Key Type (0:IPv4, 1:IPv6) 3094 * key_mode - (Out)Key Mode (0:Half, 1:Full, 3:Double) 3095 * sub_idx - (In)TCAM sub_idx (0, 1) for half-wide entries in unpair 3096 * TCAM. Pair TCAM has only one sub_idx=0. 3097 * Notes: 3098 * The for-loop for sub_idx is using always as below: 3099 * for (sub_idx = 0; sub_idx < ALPM_TCAM_SUBCNT; sub_idx += step_size) 3100 * where 3101 * ALPM_TCAM_SUBCNT is defined as 2, and 3102 * step_size is variable, depending on the actual TCAM entry reading. 3103 * 3104 * Returns: 3105 * BCM_E_XXX 3106 */ 3107 int 3108 th3_tcam_entry_mode_get(int u, int pk, void *e, int *step_size, 3109 int *pkm, int *ipv6, int *key_mode, int sub_idx) 3110 { 3111 _alpm_cb_t *acb = ACB_TOP(u); 3112 soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pk]]; 3113 return th3_tcam_entry_mode_get_by_mem(u, mem, e, step_size, pkm, 3114 ipv6, key_mode, sub_idx); 3115 } 3116 3117 /* Get ASSOC_DATA from a TCAM entry */ 3118 int 3119 th3_tcam_entry_adata_get(int u, int pkm, void *e, int sub_idx, 3120 _alpm_bkt_adata_t *adata) 3121 { 3122 int rv = BCM_E_NONE; 3123 soc_field_t fldv; 3124 _alpm_cb_t *acb = ACB_TOP(u); 3125 soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]]; 3126 th3_fmt_ASSOC_DATA_FULL_t fmt_adf; 3127 3128 if (SOC_MEM_FIELD_VALID(u, mem, ASSOC_DATA0f)) { 3129 fldv = (sub_idx == 0 ? ASSOC_DATA0f : ASSOC_DATA1f); 3130 } else { 3131 fldv = (sub_idx == 0 ? LWR_ASSOC_DATA0f : LWR_ASSOC_DATA1f); 3132 } 3133 soc_mem_field_get(u, mem, e, fldv, (uint32 *)&fmt_adf); 3134 3135 adata->defip_flags = fmt_adf.DEST_TYPE ? BCM_L3_MULTIPATH : 0; 3136 adata->defip_ecmp_index = fmt_adf.DESTINATION; 3137 adata->defip_flags |= fmt_adf.RPE ? BCM_L3_RPE : 0; 3138 adata->defip_flags |= fmt_adf.DST_DISCARD ? BCM_L3_DST_DISCARD : 0; 3139 adata->defip_prio = fmt_adf.PRI; 3140 adata->defip_lookup_class = fmt_adf.CLASS_ID; 3141 adata->defip_flex_ctr_base_id = fmt_adf.FLEX_CTR_BASE_COUNTER_IDX; 3142 adata->defip_flex_ctr_mode = fmt_adf.FLEX_CTR_OFFSET_MODE; 3143 adata->defip_flex_ctr_pool = fmt_adf.FLEX_CTR_POOL_NUMBER; 3144 3145 return rv; 3146 } 3147 3148 /* Get ALPM_DATA entry from a TCAM entry */ 3149 int 3150 th3_tcam_entry_bdata_get(int u, int pkm, void *e, int sub_idx, void *fent) 3151 { 3152 int rv = BCM_E_NONE; 3153 soc_field_t fldv; 3154 _alpm_cb_t *acb = ACB_TOP(u); 3155 soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]]; 3156 3157 if (SOC_MEM_FIELD_VALID(u, mem, ALPM1_DATA0f)) { 3158 fldv = (sub_idx == 0 ? ALPM1_DATA0f : ALPM1_DATA1f); 3159 } else { 3160 fldv = (sub_idx == 0 ? LWR_ALPM1_DATA0f : LWR_ALPM1_DATA1f); 3161 } 3162 soc_mem_field_get(u, mem, e, fldv, fent); 3163 return rv; 3164 } 3165 3166 /***************** Bucket entry (Bank) starts from here *****************/ 3167 int 3168 th3_alpm_ent_ent_get(int u, int vrf_id, _alpm_cb_t *acb, void *e, uint32 fmt, 3169 int eid, void *ftmp) 3170 { 3171 int rv = BCM_E_NONE; 3172 3173 /* get bucket level bank format entry */ 3174 soc_format_field_get(u, ACB_FMT_BNK(acb, vrf_id, fmt), e, 3175 th3_alpm_ent_fld[eid], ftmp); 3176 return rv; 3177 } 3178 3179 /* Get ALPM_Data bucket info (logic table based): 3180 bkt_ptr, rofs, kshift, def_miss and bnkfmt[] */ 3181 static void 3182 th3_alpm_ent_binfo_get(int u, int vrf_id, _alpm_cb_t *acb, void *e, 3183 _alpm_ent_info_t *info) 3184 { 3185 int bnk, offset = 0; 3186 th3_fmt_ALPM1_DATA_t *fmt_a1d = NULL; 3187 th3_fmt_ALPM2_DATA_t *fmt_a2d = NULL; 3188 3189 uint8 bnk_fmt[ALPM_BPB_MAX] = {0}; 3190 uint16 bkt_idx; 3191 int kshift; 3192 int default_miss; 3193 uint8 rofs; 3194 3195 if (ACB_HAS_TCAM(acb)) { 3196 fmt_a1d = e; 3197 bkt_idx = fmt_a1d->BKT_PTR; 3198 kshift = fmt_a1d->KSHIFT; 3199 default_miss = fmt_a1d->DEFAULT_MISS; 3200 rofs = fmt_a1d->ROFS; 3201 bnk_fmt[0] = fmt_a1d->FMT0; 3202 bnk_fmt[1] = fmt_a1d->FMT1; 3203 bnk_fmt[2] = (fmt_a1d->FMT2_2_3 << 2) | fmt_a1d->FMT2_0_1; 3204 bnk_fmt[3] = fmt_a1d->FMT3; 3205 bnk_fmt[4] = fmt_a1d->FMT4; 3206 } else { 3207 fmt_a2d = e; 3208 bkt_idx = fmt_a2d->BKT_PTR; 3209 kshift = fmt_a2d->KSHIFT; 3210 default_miss = fmt_a2d->DEFAULT_MISS; 3211 rofs = fmt_a2d->ROFS; 3212 bnk_fmt[0] = fmt_a2d->FMT0; 3213 bnk_fmt[1] = fmt_a2d->FMT1; 3214 bnk_fmt[2] = fmt_a2d->FMT2; 3215 bnk_fmt[3] = fmt_a2d->FMT3; 3216 bnk_fmt[4] = fmt_a2d->FMT4; 3217 bnk_fmt[5] = fmt_a2d->FMT5; 3218 bnk_fmt[6] = fmt_a2d->FMT6; 3219 bnk_fmt[7] = fmt_a2d->FMT7; 3220 } 3221 3222 info->bkt_info.bkt_idx = bkt_idx; 3223 info->kshift = kshift; 3224 info->default_miss = default_miss; 3225 3226 switch (ACB_BKT_TBL(acb, vrf_id)) { 3227 case alpmTblBktPmodeGblL2: 3228 case alpmTblBktPmodeGblL3: 3229 offset = ACB_BNK_PER_BKT(acb, 1); 3230 break; 3231 default: 3232 break; 3233 } 3234 3235 if (ACB_HLF_BNK_MD(acb) && ALPM_HLF_BNKS(u)) { 3236 offset = 4; 3237 } 3238 3239 info->bkt_info.rofs = rofs - offset; 3240 for (bnk = 0; bnk < ACB_BNK_PER_BKT(acb, vrf_id); bnk++) { 3241 soc_field_t bnk_fld; 3242 bnk_fld = th3_alpm_bnk_fld[bnk+offset]; 3243 switch (bnk_fld) { 3244 case FMT0f: 3245 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[0]; 3246 break; 3247 case FMT1f: 3248 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[1]; 3249 break; 3250 case FMT2f: 3251 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[2]; 3252 break; 3253 case FMT3f: 3254 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[3]; 3255 break; 3256 case FMT4f: 3257 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[4]; 3258 break; 3259 case FMT5f: 3260 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[5]; 3261 break; 3262 case FMT6f: 3263 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[6]; 3264 break; 3265 case FMT7f: 3266 info->bkt_info.bnk_fmt[bnk] = bnk_fmt[7]; 3267 break; 3268 default: 3269 break; 3270 } 3271 } 3272 3273 return; 3274 } 3275 3276 /* Read and update ALPM prefix key using 1bit length decoding */ 3277 int 3278 th3_alpm_bkt_pfx_get(int u, int vrf_id, _alpm_cb_t *acb, void *e, uint32 fmt, uint32 *valid, 3279 uint32 *new_key, int *new_len) 3280 { 3281 int rv = BCM_E_NONE; 3282 int fmt_len = ACB_FMT_PFX_LEN(acb, vrf_id, fmt); 3283 uint32 pfx[5] = {0}; 3284 3285 /* process Bucket Level PREFIX */ 3286 soc_format_field_get(u, ACB_FMT_ENT(acb, vrf_id, fmt), 3287 e, PREFIXf, pfx); 3288 *valid = pfx[0] | pfx[1] | pfx[2] | pfx[3] | pfx[4]; 3289 3290 /* pfx with all zero is invalid */ 3291 if (*valid) { 3292 th3_alpm_ent_1bit_decoding(u, pfx, fmt_len, new_len); 3293 SHR_BITCOPY_RANGE(new_key, 0, pfx, fmt_len - (*new_len) + 1, *new_len); 3294 } 3295 3296 return rv; 3297 } 3298 3299 /* Read ALPM Assoc_Data */ 3300 static void 3301 th3_alpm_bkt_adata_get(int u, int vrf_id, int ipt, _alpm_cb_t *acb, 3302 void *e, int ent_fmt, _alpm_bkt_adata_t *adata) 3303 { 3304 uint32 fval[ALPM_MEM_ENT_MAX]; 3305 th3_fmt_ASSOC_DATA_REDUCED_t *fmt_adr = NULL; 3306 th3_fmt_ASSOC_DATA_FULL_t *fmt_adf = NULL; 3307 3308 soc_format_field_get(u, ACB_FMT_ENT(acb, vrf_id, ent_fmt), 3309 e, ASSOC_DATAf, fval); 3310 3311 adata->defip_flags = ALPM_IS_IPV4(ipt) ? 0 : BCM_L3_IP6; 3312 if (ACB_FMT_FULL_TYPE(acb, vrf_id, ent_fmt)) { 3313 fmt_adf = (th3_fmt_ASSOC_DATA_FULL_t *)fval; 3314 adata->defip_flags |= fmt_adf->DEST_TYPE ? BCM_L3_MULTIPATH : 0; 3315 adata->defip_ecmp_index = fmt_adf->DESTINATION; 3316 adata->defip_flags |= fmt_adf->RPE ? BCM_L3_RPE : 0; 3317 adata->defip_flags |= fmt_adf->DST_DISCARD ? BCM_L3_DST_DISCARD : 0; 3318 adata->defip_prio = fmt_adf->PRI; 3319 adata->defip_lookup_class = fmt_adf->CLASS_ID; 3320 adata->defip_flex_ctr_base_id = fmt_adf->FLEX_CTR_BASE_COUNTER_IDX; 3321 adata->defip_flex_ctr_mode = fmt_adf->FLEX_CTR_OFFSET_MODE; 3322 adata->defip_flex_ctr_pool = fmt_adf->FLEX_CTR_POOL_NUMBER; 3323 } else { 3324 fmt_adr = (th3_fmt_ASSOC_DATA_REDUCED_t *)fval; 3325 adata->defip_flags |= fmt_adr->DEST_TYPE ? BCM_L3_MULTIPATH : 0; 3326 adata->defip_ecmp_index = fmt_adr->DESTINATION; 3327 adata->defip_prio = 0; 3328 adata->defip_lookup_class = 0; 3329 adata->defip_flex_ctr_base_id = 0; 3330 adata->defip_flex_ctr_mode = 0; 3331 adata->defip_flex_ctr_pool = 0; 3332 } 3333 3334 return ; 3335 } 3336 3337 static void 3338 th3_alpm_ent_binfo_raw_get(int u, int vrf_id, _alpm_cb_t *acb, void *ent, 3339 int fmt, void *binfo_raw) 3340 { 3341 soc_format_field_get(u, ACB_FMT_ENT(acb, vrf_id, fmt), 3342 ent, ALPM2_DATAf, binfo_raw); 3343 } 3344 3345 /* Used for retrieving alpm info from given entry, 3346 * Entry 'e' can be a TCAM entry or a entry entry, not bank entry */ 3347 int 3348 th3_alpm_ent_selective_get(int u, _alpm_cb_t *acb, void *ent, _alpm_ent_info_t *info) 3349 { 3350 int rv = BCM_E_NONE; 3351 int ent_fmt, vrf_id, ipt; 3352 uint32 mask = info->action_mask; 3353 3354 ent_fmt = info->ent_fmt; 3355 vrf_id = info->vrf_id; 3356 ipt = info->ipt; 3357 3358 if (mask & (ALPM_INFO_MASK_VALID | ALPM_INFO_MASK_KEYLEN)) { 3359 th3_alpm_bkt_pfx_get(u, vrf_id, acb, ent, ent_fmt, &info->ent_valid, 3360 info->key, &info->key_len); 3361 } 3362 3363 if (mask & ALPM_INFO_MASK_ASSOC_DATA) { 3364 th3_alpm_bkt_adata_get(u, vrf_id, ipt, acb, ent, ent_fmt, &info->adata); 3365 } 3366 3367 if (mask & ALPM_INFO_MASK_ALPM_DATA) { 3368 /* Here ent is ALPM_DATA/ALPM2_DATA format */ 3369 th3_alpm_ent_binfo_get(u, vrf_id, acb, ent, info); 3370 } 3371 3372 if (mask & ALPM_INFO_MASK_ALPM_DATA_RAW) { 3373 th3_alpm_ent_binfo_raw_get(u, vrf_id, acb, ent, ent_fmt, 3374 info->alpm_data_raw); 3375 } 3376 3377 if (mask & ALPM_INFO_MASK_FIXED_DATA) { 3378 /* For TCAM entry only */; 3379 } 3380 3381 return rv; 3382 } 3383 3384 /* Return ALPM bucket bank default (minimum) format according to DB_Type */ 3385 uint8 3386 th3_alpm_bkt_def_fmt_get(int u, _alpm_cb_t *acb, int vrf_id, int ipt) 3387 { 3388 static uint8 def_fmt[ALPM_FMT_CNT][2] = { 3389 { ALPM_FMT_DEF_PVT_REDUCED, ALPM_FMT_DEF_PVT_FULL }, 3390 { ALPM_FMT_DEF_RTE_REDUCED, ALPM_FMT_DEF_RTE_FULL }, 3391 }; 3392 3393 return def_fmt[ACB_FMT_TYPE(acb, vrf_id)][ACB_VRF_DB_TYPE(u, acb, vrf_id, ipt)]; 3394 } 3395 3396 /* Return Reduced/Full format type for a given fmt */ 3397 int16 3398 th3_alpm_bkt_fmt_type_get(int u, int vrf_id, _alpm_cb_t *acb, uint8 fmt) 3399 { 3400 return ACB_FMT_FULL_TYPE(acb, vrf_id, fmt); 3401 } 3402 3403 static int 3404 th3_alpm_table_dump_3level_bkt(int u, int vrf_id, int ipt, _alpm_cb_t *acb, 3405 uint32 *key, int key_len, 3406 _alpm_bkt_info_t *bkt_info, 3407 int lvl_cnt, int flags, 3408 int *count) 3409 { 3410 int i, bnk; 3411 int idx1, eid; 3412 int has_next = 1; 3413 uint32 fmt, valid; 3414 3415 char ip_str[128] = {0}; 3416 uint32 bkt_ent[ALPM_MEM_ENT_MAX]; 3417 uint32 ftmp[ALPM_MEM_ENT_MAX]; 3418 uint32 fent1[ALPM_MEM_ENT_MAX]; 3419 3420 uint32 hw_key[4]; 3421 int hw_len; 3422 3423 _alpm_bkt_adata_t adata; 3424 _alpm_bkt_info_t bkt_info1; 3425 _bcm_defip_cfg_t lpm_cfg; 3426 3427 if (lvl_cnt < 1) { 3428 return BCM_E_NONE; 3429 } 3430 3431 for (bnk = 0; bnk < ACB_BNK_PER_BKT(acb, vrf_id); bnk++) { 3432 fmt = bkt_info->bnk_fmt[bnk]; 3433 if ((fmt == 0) || (fmt > ACB_FMT_CNT(acb, vrf_id))) { 3434 continue; 3435 } 3436 3437 /**** Bucket Level ****/ 3438 idx1 = ALPM_TAB_IDX_GET_BKT_BNK(acb, BI_ROFS(bkt_info), 3439 BI_BKT_IDX(bkt_info), bnk); 3440 if (flags & ALPM_DUMP_TABLE_NOCACHE) { 3441 ALPM_IER(alpm_bkt_entry_read_no_cache(u, 3442 ACB_BKT_TBL(acb, vrf_id), acb, bkt_ent, idx1)); 3443 } else { 3444 ALPM_IER(alpm_bkt_entry_read(u, 3445 ACB_BKT_TBL(acb, vrf_id), acb, bkt_ent, idx1)); 3446 } 3447 for (eid = 0; eid < ACB_FMT_ENT_MAX(acb, vrf_id, fmt); eid++) { 3448 uint32 key2[4] = {0}; 3449 int len2 = 0; 3450 int phy_idx; 3451 3452 /* process bucket entry Prefix */ 3453 alpm_util_ent_ent_get(u, vrf_id, acb, bkt_ent, fmt, eid, ftmp); 3454 alpm_util_bkt_pfx_get(u, vrf_id, acb, ftmp, fmt, key2, &len2, &valid); 3455 if (!valid) { 3456 continue; 3457 } 3458 alpm_util_bkt_adata_get(u, vrf_id, ipt, acb, ftmp, fmt, &adata, NULL); 3459 alpm_util_pfx_cat(u, ipt, key, key_len, key2, len2, hw_key, &hw_len); 3460 sal_memset(&lpm_cfg, 0, sizeof(lpm_cfg)); 3461 alpm_util_key_to_cfg(u, ipt, hw_key, &lpm_cfg); 3462 if (ALPM_IS_IPV6(ipt)) { 3463 alpm_util_fmt_ip6addr(ip_str, lpm_cfg.defip_ip6_addr); 3464 } else { 3465 alpm_util_fmt_ipaddr(ip_str, lpm_cfg.defip_ip_addr); 3466 } 3467 if (ACB_HAS_RTE(acb, vrf_id)) { 3468 has_next = 0; 3469 } 3470 for (i = 0; i <= acb->acb_idx; i++) { 3471 cli_out("\t"); 3472 } 3473 phy_idx = th3_mem_phy_index_get(u, acb, 3474 ACB_BKT_TBL(acb, vrf_id), idx1); 3475 cli_out("L%d-[%-5d] | f%-2db%de%-2d %-3d | %s/%d : %s %d %s\n", 3476 acb->acb_idx + 2, phy_idx, fmt, bnk, eid, 3477 has_next ? 0 : *count, ip_str, hw_len, 3478 (adata.defip_flags & BCM_L3_MULTIPATH) ? "ECMP" : "NH", 3479 adata.defip_ecmp_index, has_next ? "->" : "" ); 3480 if (!has_next) { 3481 *count += 1; 3482 continue; 3483 } 3484 alpm_util_ent_data_get(u, vrf_id, ipt, acb, ftmp, fmt, fent1); 3485 alpm_util_bkt_info_get(u, vrf_id, ipt, ipt, ACB_DWN(u, acb), fent1, 0, 3486 &bkt_info1, NULL, NULL); 3487 ALPM_IER(th3_alpm_table_dump_3level_bkt(u, vrf_id, 3488 ipt, ACB_DWN(u, acb), hw_key, hw_len, 3489 &bkt_info1, lvl_cnt - 1, flags, count)); 3490 } 3491 } 3492 3493 return BCM_E_NONE; 3494 } 3495 3496 static int 3497 th3_alpm_table_dump_3level_index(int u, soc_mem_t mem, 3498 int idx, int sub_idx, int lvl_cnt, int flags) 3499 { 3500 int rv; 3501 int ipt, pkm, ipv6, vrf_id; 3502 int use_alpm; 3503 int key_len; 3504 int count = 0; 3505 3506 char ip_str[128] = {0}; 3507 uint32 ent[ALPM_MEM_ENT_MAX] = {0}; 3508 uint32 bdata_ent[ALPM_MEM_ENT_MAX]; 3509 uint32 key[4]; 3510 3511 _alpm_bkt_adata_t adata0; 3512 _alpm_bkt_info_t bkt_info; 3513 _bcm_defip_cfg_t lpm_cfg; 3514 3515 if (mem == L3_DEFIP_PAIR_LEVEL1m) { 3516 pkm = ALPM_PKM_128; 3517 } else { 3518 pkm = ALPM_PKM_32B; 3519 } 3520 3521 if (flags & ALPM_DUMP_TABLE_NOCACHE) { 3522 ALPM_IER(tcam_entry_read_no_cache(u, pkm, ent, idx, idx)); 3523 } else { 3524 ALPM_IER(tcam_entry_read(u, pkm, ent, idx, idx)); 3525 } 3526 3527 rv = th3_tcam_entry_mode_get_by_mem(u, mem, ent, NULL, &pkm, 3528 &ipv6, NULL, sub_idx); 3529 if (BCM_FAILURE(rv)) { 3530 return rv; 3531 } 3532 3533 if (pkm == ALPM_PKM_64B && sub_idx == 1) { 3534 return BCM_E_NONE; 3535 } 3536 ipt = ALPM_PKM2IPT(pkm); 3537 3538 tcam_entry_vrf_id_get(u, pkm, ent, sub_idx, &vrf_id); 3539 /* Get Pre-pivot key IP_ADDR and prefix length (mask) */ 3540 sal_memset(key, 0, sizeof(key)); 3541 key_len = 0; 3542 tcam_entry_to_key(u, pkm, ent, sub_idx, key); 3543 tcam_entry_pfx_len_get(u, pkm, ent, sub_idx, &key_len); 3544 tcam_entry_adata_get(u, pkm, ent, sub_idx, &adata0); 3545 tcam_entry_bdata_get(u, pkm, ent, sub_idx, bdata_ent); 3546 3547 use_alpm = !(adata0.defip_flags & BCM_L3_IPMC) && 3548 ALPM_VRF_ID_HAS_BKT(u, vrf_id); 3549 sal_memset(&lpm_cfg, 0, sizeof(lpm_cfg)); 3550 alpm_util_key_to_cfg(u, ipt, key, &lpm_cfg); 3551 if (ipv6) { 3552 alpm_util_fmt_ip6addr(ip_str, lpm_cfg.defip_ip6_addr); 3553 } else { 3554 alpm_util_fmt_ipaddr(ip_str, lpm_cfg.defip_ip_addr); 3555 } 3556 3557 if (ALPM_VRF_ID_IS_GBL(u, vrf_id)) { 3558 cli_out("L1-[%4d.%d] | vrf-%-4s ", idx, sub_idx, 3559 vrf_id == ALPM_VRF_ID_GHI(u) ? "GHi" : "GLo"); 3560 } else { 3561 cli_out("L1-[%4d.%d] | vrf-%-4d ", idx, sub_idx, vrf_id); 3562 } 3563 cli_out("| %s/%d : %s %d %s\n", ip_str, key_len, 3564 (adata0.defip_flags & BCM_L3_MULTIPATH) ? "ECMP" : "NH", 3565 adata0.defip_ecmp_index, use_alpm ? "->" : "" ); 3566 if (!use_alpm) { 3567 rv = BCM_E_NONE; 3568 goto end; 3569 } 3570 3571 /* process ALPM_DATA level recursively from top to bottom */ 3572 alpm_util_bkt_info_get(u, vrf_id, ipt, pkm, ACB_TOP(u), bdata_ent, 3573 sub_idx, &bkt_info, NULL, NULL); 3574 th3_alpm_table_dump_3level_bkt(u, vrf_id, ipt, ACB_TOP(u), 3575 key, key_len, &bkt_info, 3576 lvl_cnt - 1, flags, &count); 3577 end: 3578 return rv; 3579 } 3580 3581 int 3582 th3_alpm_table_dump_3level(int u, soc_mem_t mem, 3583 int idx, int sub_idx, int lvl_cnt, int flags) 3584 { 3585 int rv = BCM_E_NONE; 3586 int i, j, idx_min, idx_max, sub_idx_min, sub_idx_max; 3587 int pkm; 3588 3589 if (idx < 0) { 3590 idx_min = 0; 3591 if (mem == L3_DEFIP_LEVEL1m) { 3592 pkm = ALPM_PKM_32B; 3593 } else { 3594 pkm = ALPM_PKM_128; 3595 } 3596 idx_max = tcam_table_size(u, pkm) - 1; 3597 sub_idx_min = 0; 3598 sub_idx_max = (pkm == ALPM_PKM_32B) ? 1 : 0; 3599 } else { 3600 idx_min = idx_max = idx; 3601 sub_idx_min = sub_idx_max = (sub_idx < 0) ? 0 : sub_idx; 3602 } 3603 3604 /* Levels are going to be printed */ 3605 if (lvl_cnt < 1 || lvl_cnt > 3) { 3606 lvl_cnt = 3; 3607 } 3608 3609 for (i = idx_min; i <= idx_max; i++) { 3610 for (j = sub_idx_min; j <= sub_idx_max; j++) { 3611 rv = th3_alpm_table_dump_3level_index(u, mem, i, j, lvl_cnt, flags); 3612 if (BCM_FAILURE(rv)) { 3613 if (rv == BCM_E_NOT_FOUND) { 3614 if (idx_min == idx_max) { 3615 cli_out("Entry %d.%d is invalid\n", i, j); 3616 } 3617 continue; 3618 } 3619 break; 3620 } 3621 } 3622 } 3623 3624 return rv; 3625 } 3626 3627 /* 3628 * Function: 3629 * th3_alpm_table_dump 3630 * Purpose: 3631 * Dump TH3 ALPM Level2 and Level3 memory tables: 3632 * "alpm table dump [raw|chg|all|nocache] <mem> <index> <format> [<ent>]" 3633 * Parameters: 3634 * u - Device unit # 3635 * mem - ALPM Level2 or Level3 memory table 3636 * copyno - mem table copy number 3637 * index - ALPM bucket level logic table index 3638 * fmt - Bank format (1-8 for Pivot formats, 1-12 for Route formats) 3639 * ent_idx - entry index (0-14), -1 for all entries. 3640 * flags - Dump flags (raw, chg, all, nocache) 3641 * Returns: 3642 * BCM_E_XXX 3643 */ 3644 int 3645 th3_alpm_table_dump(int u, int vrf_id, soc_mem_t mem, int copyno, int index, 3646 int fmt, int ent_idx, int flags) 3647 { 3648 int rv; 3649 int i, ent, ent_min, ent_max; 3650 int f, f1, entry_dw; 3651 int first_print_flag = 0; 3652 int vertical = 0; 3653 uint32 entry[ALPM_MEM_ENT_MAX]; 3654 uint32 fent[ALPM_MEM_ENT_MAX]; 3655 uint32 fval[ALPM_MEM_ENT_MAX]; 3656 uint32 fval1[ALPM_MEM_ENT_MAX]; 3657 uint32 nfval[ALPM_MEM_ENT_MAX]; 3658 char ctmp[ALPM_MEM_ENT_MAX * 8 + 3]; 3659 char mem_prefix[256]; 3660 _alpm_cb_t *acb = (mem == L3_DEFIP_ALPM_LEVEL2m ? 3661 ACB_TOP(u) : ACB_VRF_BTM(u, vrf_id)); 3662 soc_field_info_t *fieldp; 3663 soc_field_info_t *fieldp1; 3664 soc_format_info_t *fmtp; 3665 soc_format_info_t *fmtp1; 3666 soc_format_t tfmt; 3667 soc_format_t tfmt1; 3668 3669 if (mem == L3_DEFIP_LEVEL1m || mem == L3_DEFIP_PAIR_LEVEL1m) { 3670 /* Use fmt to store Level count */ 3671 return th3_alpm_table_dump_3level(u, mem, index, ent_idx, fmt, flags); 3672 } 3673 3674 if ((fmt <= 0) || (fmt > ACB_FMT_CNT(acb, vrf_id))) { 3675 cli_out("invalid or disabled bank format %d\n", fmt); 3676 return BCM_E_INTERNAL; 3677 } 3678 tfmt = ACB_FMT_ENT(acb, vrf_id, fmt); 3679 3680 if (ent_idx == -1) { /* all entries */ 3681 ent_min = 0; 3682 ent_max = ACB_FMT_ENT_MAX(acb, vrf_id, fmt); 3683 } else if (ent_idx >= ACB_FMT_ENT_MAX(acb, vrf_id, fmt)) { 3684 cli_out("invalid entry idx %d\n", ent_idx); 3685 return BCM_E_INTERNAL; 3686 } else { /* one specific entry */ 3687 ent_min = ent_idx; 3688 ent_max = ent_idx + 1; 3689 } 3690 3691 sal_memset(nfval, 0, sizeof(nfval)); 3692 3693 if (flags & ALPM_DUMP_TABLE_NOCACHE) { 3694 rv = soc_mem_read_no_cache(u, 0, mem, 0, MEM_BLOCK_ANY, index, entry); 3695 } else { 3696 rv = soc_mem_read(u, mem, MEM_BLOCK_ANY, index, entry); 3697 } 3698 3699 if (BCM_FAILURE(rv)) { 3700 cli_out("Read ERROR: table %s.%s[%d]: %s\n", 3701 SOC_MEM_UFNAME(u, mem), 3702 SOC_BLOCK_NAME(u, copyno), index, soc_errmsg(rv)); 3703 return BCM_E_INTERNAL; 3704 } 3705 3706 for (ent = ent_min; ent < ent_max; ent++) { 3707 soc_format_field_get(u, ACB_FMT_BNK(acb, vrf_id, fmt), entry, 3708 th3_alpm_ent_fld[ent], fent); 3709 fmtp = &SOC_FORMAT_INFO(u, tfmt); 3710 3711 sal_sprintf(mem_prefix, "%s.%s[%d.%d]: ", SOC_MEM_UFNAME(u, mem), 3712 SOC_BLOCK_NAME(u, copyno), index, ent); 3713 3714 if (flags & ALPM_DUMP_TABLE_RAW) { 3715 cli_out("%s", mem_prefix); 3716 entry_dw = BITS2WORDS(fmtp->bits); 3717 for (i = 0; i < entry_dw; i++) { 3718 cli_out("0x%08x ", fent[i]); 3719 } 3720 cli_out("\n"); 3721 } else { 3722 /* for fields in entry format */ 3723 for (f = fmtp->nFields - 1; f >= 0; f--) { 3724 fieldp = &fmtp->fields[f]; 3725 sal_memset(fval, 0, ALPM_MEM_ENT_MAX * sizeof(uint32)); 3726 soc_format_field_get(u, tfmt, fent, fieldp->field, fval); 3727 3728 if (flags & ALPM_DUMP_TABLE_CHANGED) { 3729 if (sal_memcmp(fval, nfval, ALPM_MEM_ENT_MAX * 3730 sizeof(uint32)) == 0) { 3731 continue; 3732 } 3733 } 3734 3735 /* for fields in format-in-format (ALPM2_DATA or ASSOC_DATA) */ 3736 tfmt1 = INVALIDfmt; 3737 if (fieldp->field == ALPM2_DATAf) { 3738 tfmt1 = ALPM2_DATAfmt; 3739 } else if (fieldp->field == ASSOC_DATAf) { 3740 tfmt1 = ACB_FMT_FULL_TYPE(acb, vrf_id, fmt) ? 3741 ASSOC_DATA_FULLfmt : ASSOC_DATA_REDUCEDfmt; 3742 } 3743 if (tfmt1 != INVALIDfmt) { 3744 fmtp1 = &SOC_FORMAT_INFO(u, tfmt1); 3745 for (f1 = fmtp1->nFields - 1; f1 >= 0; f1--) { 3746 fieldp1 = &fmtp1->fields[f1]; 3747 sal_memset(fval1, 0, ALPM_MEM_ENT_MAX * sizeof(uint32)); 3748 soc_format_field_get(u, tfmt1, fval, fieldp1->field, fval1); 3749 3750 if (flags & ALPM_DUMP_TABLE_CHANGED) { 3751 if (sal_memcmp(fval1, nfval, ALPM_MEM_ENT_MAX * 3752 sizeof(uint32)) == 0) { 3753 continue; 3754 } 3755 } 3756 _shr_format_long_integer(ctmp, fval1, BITS2BYTES(fieldp1->len)); 3757 3758 if (first_print_flag == 0) { 3759 cli_out("%s%s", mem_prefix, vertical ? "" : "<"); 3760 first_print_flag=1; 3761 } 3762 if (vertical) { 3763 cli_out("\n\t%30s: %s", SOC_FIELD_NAME(u, fieldp1->field), ctmp); 3764 } else { 3765 cli_out("%s=%s,", SOC_FIELD_NAME(u, fieldp1->field), ctmp); 3766 } 3767 } /* for f1 */ 3768 } 3769 3770 _shr_format_long_integer(ctmp, fval, BITS2BYTES(fieldp->len)); 3771 3772 if (first_print_flag == 0) { 3773 cli_out("%s%s", mem_prefix, vertical ? "" : "<"); 3774 first_print_flag=1; 3775 } 3776 if (vertical) { 3777 cli_out("\n\t%30s: %s", SOC_FIELD_NAME(u, fieldp->field), ctmp); 3778 } else { 3779 cli_out("%s=%s%s", SOC_FIELD_NAME(u, fieldp->field), 3780 ctmp, f > 0 ? "," : ""); 3781 } 3782 } /* for f */ 3783 3784 if (first_print_flag == 1) { 3785 cli_out("%s\n", vertical ? "" : ">"); 3786 first_print_flag = 0; 3787 } 3788 } 3789 } /* for ent */ 3790 3791 return BCM_E_NONE; 3792 } 3793 3794 /* 3795 * Function: 3796 * th3_alpm_cap_min 3797 * Purpose: 3798 * Get the min capacity for ALPM routes from PKM 3799 * Parameters: 3800 * u - Device unit 3801 * pkm - Packing mode 3802 */ 3803 int 3804 th3_alpm_cap_min(int u, int pkm) 3805 { 3806 int tcam_ent = 0; 3807 int min_bkt_cnt, min_bkt_ent; 3808 int i, fmt, vrf_id; 3809 _alpm_bkt_pool_conf_t *bp_conf; 3810 _alpm_cb_t *acb; 3811 3812 /* Start from TCAM restriction */ 3813 switch (pkm) { 3814 case ALPM_PKM_32B: 3815 tcam_ent = soc_mem_index_count(u, L3_DEFIP_LEVEL1m) * 2; 3816 break; 3817 case ALPM_PKM_64B: 3818 tcam_ent = soc_mem_index_count(u, L3_DEFIP_LEVEL1m); 3819 break; 3820 case ALPM_PKM_128: 3821 tcam_ent = soc_mem_index_count(u, L3_DEFIP_PAIR_LEVEL1m); 3822 break; 3823 default: 3824 return 0; 3825 } 3826 3827 min_bkt_ent = (ALPM_TCAM_ZONED(u) ? tcam_ent / 2 : tcam_ent); 3828 3829 /* Consider only for private DB */ 3830 vrf_id = 1; 3831 for (i = 0; i < ACB_CNT(u); i++) { 3832 int avl_bnks, min_bnks; 3833 acb = ACB(u, i); 3834 bp_conf = ACB_BKT_POOL(acb, ALPM_VRF_ID_TO_BPC_PID(u, vrf_id)); 3835 3836 /* avl_bnks starts with all, then check ALPM_BKT_RSVD */ 3837 avl_bnks = BPC_BNK_CNT(bp_conf); 3838 if (ALPM_128B(u) && ALPM_BKT_RSVD(u)) { 3839 int rsvd_v6_bnks = 3840 BPC_BNK_CNT(bp_conf) * ALPM_BKT_RSVD_CNT(u) / 8192; 3841 if (pkm == ALPM_PKM_128) { 3842 avl_bnks = rsvd_v6_bnks; 3843 } else { 3844 avl_bnks -= rsvd_v6_bnks; 3845 } 3846 } 3847 3848 /* compare upper min_bkt_ent and bkt_cnt at current level */ 3849 min_bkt_cnt = (ACB_BKT_CNT(acb) < min_bkt_ent ? ACB_BKT_CNT(acb) : min_bkt_ent); 3850 min_bnks = min_bkt_cnt * BPC_BNK_PER_BKT(bp_conf); 3851 3852 /* update avl_bnks comapring to min_bnks */ 3853 if (min_bnks < avl_bnks ) { 3854 avl_bnks = min_bnks; 3855 } 3856 3857 if (ACB_HAS_RTE(acb, vrf_id)) { 3858 /* Route (full) format whose prefix length fits almost the full PKM length */ 3859 fmt = (pkm == ALPM_PKM_32B ? 10 : /* FMT10 (33b) */ 3860 pkm == ALPM_PKM_64B ? 11 : 12); /* FMT11 (73b), FMT12 (128b) */ 3861 } else { 3862 /* Pivot (full) format whose prefix length 3863 fits almost the remaining pivot length */ 3864 fmt = 6; /* FMT6 (17b) */ 3865 } 3866 3867 /* considering 33% on bucket split utlization */ 3868 min_bkt_ent = avl_bnks * ACB_FMT_ENT_MAX(acb, vrf_id, fmt) / 3; 3869 } 3870 3871 return min_bkt_ent; 3872 } 3873 3874 /* 3875 * Function: 3876 * th3_alpm_cap_max 3877 * Purpose: 3878 * Get the max capacity for ALPM routes from PKM 3879 * Parameters: 3880 * u - Device unit 3881 * pkm - Packing mode 3882 */ 3883 int 3884 th3_alpm_cap_max(int u, int pkm) 3885 { 3886 int tcam_ent = 0; 3887 int min_bkt_cnt, max_bkt_ent; 3888 int i, fmt, vrf_id, pid; 3889 _alpm_bkt_pool_conf_t *bp_conf; 3890 _alpm_cb_t *acb; 3891 3892 /* Start from TCAM restriction */ 3893 switch (pkm) { 3894 case ALPM_PKM_32B: 3895 tcam_ent = soc_mem_index_count(u, L3_DEFIP_LEVEL1m) * 2; 3896 break; 3897 case ALPM_PKM_64B: 3898 tcam_ent = soc_mem_index_count(u, L3_DEFIP_LEVEL1m); 3899 break; 3900 case ALPM_PKM_128: 3901 tcam_ent = soc_mem_index_count(u, L3_DEFIP_PAIR_LEVEL1m); 3902 break; 3903 default: 3904 return 0; 3905 } 3906 3907 /* Include private/global ALPM routes (exclude TCAM direct routes) */ 3908 /* TCAM mode private VRF has half TCAM entries */ 3909 max_bkt_ent = (ALPM_MODE_CHK(u, BCM_ALPM_MODE_TCAM_ALPM) ? tcam_ent / 2 : tcam_ent); 3910 3911 /* Route or Pivot (reduced) FMT1 with maximum entries per bank */ 3912 fmt = 1; 3913 3914 for (i = 0; i < ACB_CNT(u); i++) { 3915 int avl_bnks, min_bnks; 3916 acb = ACB(u, i); 3917 /* compare upper max_bkt_ent and bkt_cnt at current level */ 3918 min_bkt_cnt = (ACB_BKT_CNT(acb) < max_bkt_ent ? ACB_BKT_CNT(acb) : max_bkt_ent); 3919 3920 max_bkt_ent = 0; 3921 /* consider both private and global routes */ 3922 for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) { 3923 bp_conf = ACB_BKT_POOL(acb, pid); 3924 vrf_id = ALPM_BPC_PID_TO_VRF_ID(u, pid); 3925 3926 if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid - 1)) { 3927 continue; /* Combined Mode uses PID=0 only */ 3928 } 3929 3930 /* avl_bnks starts with all, then check ALPM_BKT_RSVD */ 3931 avl_bnks = BPC_BNK_CNT(bp_conf); 3932 if (ALPM_128B(u) && ALPM_BKT_RSVD(u)) { 3933 int rsvd_v6_bnks = 3934 BPC_BNK_CNT(bp_conf) * ALPM_BKT_RSVD_CNT(u) / 8192; 3935 if (pkm == ALPM_PKM_128) { 3936 avl_bnks = rsvd_v6_bnks; 3937 } else { 3938 avl_bnks -= rsvd_v6_bnks; 3939 } 3940 } 3941 3942 min_bnks = min_bkt_cnt * BPC_BNK_PER_BKT(bp_conf); 3943 3944 /* update avl_bnks comapring to min_bnks */ 3945 if (min_bnks < avl_bnks ) { 3946 avl_bnks = min_bnks; 3947 } 3948 3949 max_bkt_ent += avl_bnks * ACB_FMT_ENT_MAX(acb, vrf_id, fmt); 3950 } 3951 } 3952 3953 return max_bkt_ent; 3954 } 3955 3956 /* 3957 * Function: 3958 * th3_alpm_cap_get 3959 * Purpose: 3960 * Get the min or max capacity for ALPM routes from legacy tables: 3961 * L3_DEFIP_ALPM_IPV4, L3_DEFIP_ALPM_IPV6_64, L3_DEFIP_ALPM_IPV6_128 3962 * 3963 * Parameters: 3964 * u - Device unit 3965 * mem - Legacy memory type 3966 * max_cnt - Maximum result returned. 3967 * min_cnt - Minimum result returned. 3968 */ 3969 int 3970 th3_alpm_cap_get(int u, soc_mem_t mem, int *max_cnt, int *min_cnt) 3971 { 3972 int pkm; 3973 switch (mem) { 3974 case L3_DEFIP_ALPM_IPV4m: 3975 case L3_DEFIP_ALPM_IPV4_1m: 3976 pkm = ALPM_PKM_32B; 3977 break; 3978 case L3_DEFIP_ALPM_IPV6_64m: 3979 case L3_DEFIP_ALPM_IPV6_64_1m: 3980 pkm = ALPM_PKM_64B; 3981 break; 3982 case L3_DEFIP_ALPM_IPV6_128m: 3983 pkm = ALPM_PKM_128; 3984 break; 3985 default: 3986 return BCM_E_UNAVAIL; 3987 } 3988 3989 if (min_cnt != NULL) { 3990 *min_cnt = th3_alpm_cap_min(u, pkm); 3991 } 3992 3993 if (max_cnt != NULL) { 3994 *max_cnt = th3_alpm_cap_max(u, pkm); 3995 } 3996 3997 return BCM_E_NONE; 3998 } 3999 4000 /* 4001 * Function: 4002 * th3_alpm_bkt_hit_get 4003 * Purpose: 4004 * Get ALPM bucket entry hitbit status from hitbit table cache 4005 * sync with Hw. Route hitbit status is gathered from pivots 4006 * whose BPM is the route. 4007 * Parameters: 4008 * u - Device unit # 4009 * vrf_id - VRF ID for logic hit table PID in Parallel/Mixed Mode 4010 * acb - ALPM control block where hit table located 4011 * idx - ALPM bucket level logic table index 4012 * ent - Bucket entry ID (0-15) 4013 * Returns: 4014 * Bucket entry hitbit (0 or 1) 4015 */ 4016 int 4017 th3_alpm_bkt_hit_get(int u, int vrf_id, _alpm_cb_t *acb, 4018 _alpm_tbl_t tbl, int idx, int ent) 4019 { 4020 int rv; 4021 uint32 *tbl_ent; /* bucket hit cache table entry pointer */ 4022 int i = ACB_IDX(acb); 4023 int pid = ACB_BKT_VRF_PID(acb, vrf_id); 4024 soc_mem_t mem = ALPM_HTBL_MEM(u, i, pid); 4025 soc_field_t hit_fld[16] = { 4026 HIT_0f, HIT_1f, HIT_2f, HIT_3f, HIT_4f, HIT_5f, HIT_6f, HIT_7f, 4027 HIT_8f, HIT_9f, HIT_10f, HIT_11f, HIT_12f, HIT_13f, HIT_14f, HIT_15f 4028 }; 4029 4030 tbl_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *, 4031 ALPM_HTBL_CACHE(u, i, pid), idx); 4032 rv = soc_mem_field32_get(u, mem, tbl_ent, hit_fld[ent]); 4033 4034 return rv; 4035 } 4036 4037 /* 4038 * Function: 4039 * th3_alpm_bkt_hit_set 4040 * Purpose: 4041 * Set ALPM bucket entry hitbit to cache table only 4042 * Parameters: 4043 * u - Device unit #. 4044 * vrf_id - VRF ID for logic hit table PID in Parallel/Mixed Mode 4045 * acb - ALPM control block where hit table located 4046 * idx - ALPM bucket level table index 4047 * ent - Bucket entry ID (0-15) 4048 * hit_val - Bucket entry hit value (0/1) 4049 * Returns: 4050 * BCM_E_XXX 4051 */ 4052 int 4053 th3_alpm_bkt_hit_set(int u, int vrf_id, _alpm_cb_t *acb, _alpm_tbl_t tbl, 4054 int idx, int ent, int hit_val) 4055 { 4056 int rv = BCM_E_NONE; 4057 uint32 *tbl_ent; /* bucket hit cache table entry pointer */ 4058 int i = ACB_IDX(acb); 4059 int pid = ACB_BKT_VRF_PID(acb, vrf_id); 4060 soc_mem_t mem = ALPM_HTBL_MEM(u, i, pid); 4061 soc_field_t hit_fld[16] = { 4062 HIT_0f, HIT_1f, HIT_2f, HIT_3f, HIT_4f, HIT_5f, HIT_6f, HIT_7f, 4063 HIT_8f, HIT_9f, HIT_10f, HIT_11f, HIT_12f, HIT_13f, HIT_14f, HIT_15f 4064 }; 4065 4066 tbl_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *, 4067 ALPM_HTBL_CACHE(u, i, pid), idx); 4068 soc_mem_field32_set(u, mem, tbl_ent, hit_fld[ent], hit_val); 4069 4070 return rv; 4071 } 4072 4073 /* 4074 * Function: 4075 * th3_alpm_bkt_hit_write 4076 * Purpose: 4077 * Set ALPM bucket entry hitbit status to hitbit table cache 4078 * and write to Hw (by setting Entry Move & Mask to trigger write to Hw 4079 * in next Dist Hitbit thread clycle). 4080 * Parameters: 4081 * u - Device unit # 4082 * vrf_id - VRF ID for logic hit table PID in Parallel/Mixed Mode 4083 * acb - ALPM control block where hit table located 4084 * ent_idx - ALPM bucket node ent_idx 4085 * hit_val - HITBIT value requested 4086 * Returns: 4087 * BCM_E_XXX 4088 */ 4089 int 4090 th3_alpm_bkt_hit_write(int u, int vrf_id, _alpm_cb_t *acb, 4091 _alpm_tbl_t tbl, int ent_idx, int hit_val) 4092 { 4093 int rv = BCM_E_NONE; 4094 int idx, ent; 4095 uint32 *dst_ent; /* bucket hit cache table entry pointer */ 4096 int i = ACB_IDX(acb); 4097 int pid = ACB_BKT_VRF_PID(acb, vrf_id); 4098 soc_mem_t mem = ALPM_HTBL_MEM(u, i, pid); 4099 soc_field_t hit_fld[16] = { 4100 HIT_0f, HIT_1f, HIT_2f, HIT_3f, HIT_4f, HIT_5f, HIT_6f, HIT_7f, 4101 HIT_8f, HIT_9f, HIT_10f, HIT_11f, HIT_12f, HIT_13f, HIT_14f, HIT_15f 4102 }; 4103 4104 ALPM_HIT_LOCK(u); 4105 4106 ent = ALPM_IDX_TO_ENT(ent_idx); 4107 idx = ALPM_TAB_IDX_GET(ent_idx); 4108 4109 /* Write hit_val to dst cache hit bit */ 4110 dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 4111 ALPM_HTBL_CACHE(u, i, pid), idx); 4112 soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val); 4113 4114 /* Write hit_val to dst move bit */ 4115 dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 4116 ALPM_HTBL_MOVE(u, i, pid), idx); 4117 soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val); 4118 4119 /* Set dst move mask bit */ 4120 dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 4121 ALPM_HTBL_MOVE_MASK(u, i, pid), idx); 4122 soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], 1); 4123 4124 /* declare finally hitbit entry_moved flag */ 4125 ALPM_HTBL_ENT_MOVED(u, i, pid) = TRUE; 4126 4127 ALPM_HIT_UNLOCK(u); 4128 4129 return rv; 4130 } 4131 4132 /* ALPM bucket hitbit entry move from bkt_node's src_ent_idx to dst_ent_idx. 4133 Copy hit bit cache, and set properly move, move_mask and ent_moved flag. 4134 */ 4135 int 4136 th3_alpm_ent_hit_move(int u, int vrf_id, _alpm_cb_t *acb, int src_ent_idx, int dst_ent_idx) 4137 { 4138 int rv = BCM_E_NONE; 4139 int i, hit_val, idx, ent; 4140 uint32 *src_ent, *dst_ent; 4141 int pid = ACB_BKT_VRF_PID(acb, vrf_id); 4142 soc_mem_t mem; 4143 soc_field_t hit_fld[16] = { 4144 HIT_0f, HIT_1f, HIT_2f, HIT_3f, HIT_4f, HIT_5f, HIT_6f, HIT_7f, 4145 HIT_8f, HIT_9f, HIT_10f, HIT_11f, HIT_12f, HIT_13f, HIT_14f, HIT_15f 4146 }; 4147 4148 ALPM_HIT_LOCK(u); 4149 4150 i = ACB_IDX(acb); 4151 mem = ALPM_HTBL_MEM(u, i, pid); 4152 4153 /* 1) Src */ 4154 ent = ALPM_IDX_TO_ENT(src_ent_idx); 4155 idx = ALPM_TAB_IDX_GET(src_ent_idx); 4156 4157 /* Save src cache hit_val and clear it */ 4158 src_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 4159 ALPM_HTBL_CACHE(u, i, pid), idx); 4160 hit_val = soc_mem_field32_get(u, mem, src_ent, hit_fld[ent]); 4161 soc_mem_field32_set(u, mem, src_ent, hit_fld[ent], 0); 4162 4163 /* Clear src move bit */ 4164 src_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 4165 ALPM_HTBL_MOVE(u, i, pid), idx); 4166 soc_mem_field32_set(u, mem, src_ent, hit_fld[ent], 0); 4167 4168 /* Set src move mask bit */ 4169 src_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 4170 ALPM_HTBL_MOVE_MASK(u, i, pid), idx); 4171 soc_mem_field32_set(u, mem, src_ent, hit_fld[ent], 1); 4172 4173 /* 2) Dst */ 4174 ent = ALPM_IDX_TO_ENT(dst_ent_idx); 4175 idx = ALPM_TAB_IDX_GET(dst_ent_idx); 4176 4177 /* Write hit_val to dst cache hit bit */ 4178 dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 4179 ALPM_HTBL_CACHE(u, i, pid), idx); 4180 soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val); 4181 4182 /* Write hit_val to dst move bit */ 4183 dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 4184 ALPM_HTBL_MOVE(u, i, pid), idx); 4185 soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val); 4186 4187 /* Set dst move mask bit */ 4188 dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 4189 ALPM_HTBL_MOVE_MASK(u, i, pid), idx); 4190 soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], 1); 4191 4192 /* declare finally hitbit entry_moved flag */ 4193 ALPM_HTBL_ENT_MOVED(u, i, pid) = TRUE; 4194 4195 ALPM_HIT_UNLOCK(u); 4196 4197 return rv; 4198 } 4199 4200 /* ALPM bucket bank hitbit move from src_idx to dst_idx. 4201 Copy hit bit cache, and set properly move, move_mask and ent_moved flag. 4202 */ 4203 int 4204 th3_alpm_bnk_hit_move(int u, int vrf_id, _alpm_cb_t *acb, int src_idx, int dst_idx) 4205 { 4206 int rv = BCM_E_NONE; 4207 int i; 4208 uint32 src_cache; 4209 uint32 *cache_ent, *move_ent, *move_mask_ent; 4210 int pid = ACB_BKT_VRF_PID(acb, vrf_id); 4211 soc_mem_t mem; 4212 4213 ALPM_HIT_LOCK(u); 4214 4215 i = ACB_IDX(acb); 4216 mem = ALPM_HTBL_MEM(u, i, pid); 4217 4218 /* 1) Src bank */ 4219 cache_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 4220 ALPM_HTBL_CACHE(u, i, pid), src_idx); 4221 move_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 4222 ALPM_HTBL_MOVE(u, i, pid), src_idx); 4223 move_mask_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 4224 ALPM_HTBL_MOVE_MASK(u, i, pid), src_idx); 4225 src_cache = *cache_ent; /* save src_cache value */ 4226 *cache_ent = 0; /* clear src cache */ 4227 *move_ent = 0; /* clear src move */ 4228 *move_mask_ent = ALPM_MAX_HIT_ENT_MASK; /* Set src mask for all 16 bits */ 4229 4230 /* 2) Dst bank */ 4231 cache_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 4232 ALPM_HTBL_CACHE(u, i, pid), dst_idx); 4233 move_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 4234 ALPM_HTBL_MOVE(u, i, pid), dst_idx); 4235 move_mask_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 4236 ALPM_HTBL_MOVE_MASK(u, i, pid), dst_idx); 4237 *cache_ent = src_cache; /* copy saved src_cache value to dst cache */ 4238 *move_ent = src_cache; /* copy same to dst move */ 4239 *move_mask_ent = ALPM_MAX_HIT_ENT_MASK; /* Set dst mask for all 16 bits */ 4240 4241 /* declare finally hitbit entry_moved flag */ 4242 ALPM_HTBL_ENT_MOVED(u, i, pid) = TRUE; 4243 4244 ALPM_HIT_UNLOCK(u); 4245 return rv; 4246 } 4247 4248 /* Clear ALPM bucket bank hitbit cache at idx. 4249 Set properly move, move_mask and ent_moved flag. 4250 */ 4251 int 4252 th3_alpm_bnk_hit_clear(int u, int vrf_id, _alpm_cb_t *acb, int idx) 4253 { 4254 int rv = BCM_E_NONE; 4255 int i; 4256 uint32 *entry; 4257 int pid = ACB_BKT_VRF_PID(acb, vrf_id); 4258 soc_mem_t mem; 4259 4260 ALPM_HIT_LOCK(u); 4261 4262 i = ACB_IDX(acb); 4263 mem = ALPM_HTBL_MEM(u, i, pid); 4264 4265 entry = soc_mem_table_idx_to_pointer(u, mem, void *, 4266 ALPM_HTBL_CACHE(u, i, pid), idx); 4267 *entry = 0; /* clear cache */ 4268 4269 entry = soc_mem_table_idx_to_pointer(u, mem, void *, 4270 ALPM_HTBL_MOVE(u, i, pid), idx); 4271 *entry = 0; /* clear move */ 4272 4273 entry = soc_mem_table_idx_to_pointer(u, mem, void *, 4274 ALPM_HTBL_MOVE_MASK(u, i, pid), idx); 4275 *entry = ALPM_MAX_HIT_ENT_MASK; /* set move mask */ 4276 4277 /* declare finally hitbit entry_moved flag */ 4278 ALPM_HTBL_ENT_MOVED(u, i, pid) = TRUE; 4279 4280 ALPM_HIT_UNLOCK(u); 4281 return rv; 4282 } 4283 4284 /* Update hitbit for entry move on level i by 4285 * hit_cache = (hit_cache & ~hit_move_mask) | (hit_move & hit_move_mask) 4286 */ 4287 int 4288 th3_alpm_hit_move_update(int u, int i, int pid) 4289 { 4290 int rv = BCM_E_NONE; 4291 int idx, index_cnt; 4292 uint32 hit_cache, hit_move, hit_move_mask; 4293 uint32 *cache_ent, *move_ent, *move_mask_ent; 4294 soc_mem_t mem; 4295 4296 if (!ALPM_HTBL_ENT_MOVED(u, i, pid)) { 4297 return rv; 4298 } 4299 4300 mem = ALPM_HTBL_MEM(u, i, pid); 4301 index_cnt = ALPM_HTBL_IDX_CNT(u, i, pid); 4302 4303 ALPM_HTBL_ENT_MOVED_CNT(u, i, pid) = 0; 4304 for (idx = 0; idx < index_cnt; idx++) { 4305 move_mask_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *, 4306 ALPM_HTBL_MOVE_MASK(u, i, pid), idx); 4307 hit_move_mask = *move_mask_ent; 4308 4309 if (hit_move_mask) { 4310 cache_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 * , 4311 ALPM_HTBL_CACHE(u, i, pid), idx); 4312 move_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *, 4313 ALPM_HTBL_MOVE(u, i, pid), idx); 4314 hit_cache = *cache_ent; 4315 hit_move = *move_ent; 4316 4317 /* update cache entry */ 4318 *cache_ent = (hit_cache & ~hit_move_mask) | 4319 (hit_move & hit_move_mask); 4320 4321 ALPM_HTBL_ENT_MOVED_CNT(u, i, pid)++; 4322 } 4323 } 4324 4325 return rv; 4326 } 4327 4328 /* Sync ALPM non-TCAM level (i:0/1 for level 2/3) hitbit cache with Hw */ 4329 int 4330 th3_alpm_hit_cache_sync(int u, int i, int pid) 4331 { 4332 soc_mem_t mem; 4333 int idx_max, offset = 0; 4334 int rv = BCM_E_NONE; 4335 _alpm_cb_t *acb = (i == 0 ? ACB_TOP(u) : ACB_BTM(u)); 4336 4337 if (ALPM_HTBL_IDX_CNT(u, i, pid) == 0) { 4338 return rv; 4339 } 4340 4341 mem = ALPM_HTBL_MEM(u, i, pid); 4342 idx_max = ALPM_HTBL_IDX_CNT(u, i, pid) - 1; 4343 4344 if (pid == ALPM_BKT_GLB_PID) { /* adjust physical mem table offset */ 4345 offset = ALPM_HTBL_IDX_CNT(u, i, ALPM_BKT_PRT_PID); 4346 } 4347 4348 if (ACB_HLF_BNK_MD(acb) && ALPM_HLF_BNKS(u)) { 4349 offset = ALPM_HTBL_IDX_CNT(u, i, ALPM_BKT_PRT_PID); 4350 } 4351 4352 rv = soc_mem_read_range(u, mem, MEM_BLOCK_ANY, offset, idx_max + offset, 4353 ALPM_HTBL_CACHE(u, i, pid)); 4354 4355 return rv; 4356 } 4357 4358 /* Write ALPM non-TCAM level (i:0/1 for level 2/3) hitbit cache to Hw */ 4359 int 4360 th3_alpm_hit_hw_write(int u, int i, int pid) 4361 { 4362 soc_mem_t mem; 4363 int idx, idx_max, index, offset = 0; 4364 uint32 hit_move, hit_move_mask, entry_data; 4365 uint32 *cache_ent, *move_ent, *move_mask_ent; 4366 int rv = BCM_E_NONE; 4367 _alpm_cb_t *acb = (i == 0 ? ACB_TOP(u) : ACB_BTM(u)); 4368 4369 if (ALPM_HTBL_IDX_CNT(u, i, pid) == 0) { 4370 return rv; 4371 } 4372 4373 mem = ALPM_HTBL_MEM(u, i, pid); 4374 idx_max = ALPM_HTBL_IDX_CNT(u, i, pid) - 1; 4375 4376 if (pid == ALPM_BKT_GLB_PID) { /* adjust physical mem table offset */ 4377 offset = ALPM_HTBL_IDX_CNT(u, i, ALPM_BKT_PRT_PID); 4378 } 4379 4380 if (ACB_HLF_BNK_MD(acb) && ALPM_HLF_BNKS(u)) { 4381 offset = ALPM_HTBL_IDX_CNT(u, i, ALPM_BKT_PRT_PID); 4382 } 4383 4384 /* use DMA write for whole HIT table */ 4385 if (ALPM_HTBL_ENT_MOVED_CNT(u, i, pid) >= ALPM_HIT_DMA_THRESHOLD) { 4386 4387 rv = soc_mem_write_range(u, mem, MEM_BLOCK_ALL, offset, idx_max + offset, 4388 ALPM_HTBL_CACHE(u, i, pid)); 4389 } else { /* use HIT mem_read and mem_write per moved entry */ 4390 4391 for (idx = 0; idx <= idx_max; idx++) { 4392 4393 move_mask_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *, 4394 ALPM_HTBL_MOVE_MASK(u, i, pid), idx); 4395 hit_move_mask = *move_mask_ent; 4396 4397 if (hit_move_mask) { 4398 move_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *, 4399 ALPM_HTBL_MOVE(u, i, pid), idx); 4400 hit_move = *move_ent; 4401 4402 index = idx + offset; /* HIT entry physical index */ 4403 /* read from Hw HIT entry data */ 4404 rv = soc_mem_read_no_cache(u, 0, mem, 0, MEM_BLOCK_ANY, 4405 index, (void *)&entry_data); 4406 entry_data = (entry_data & ~hit_move_mask) | 4407 (hit_move & hit_move_mask); 4408 /* write to cache & Hw updated HIT entry data */ 4409 rv = soc_mem_write(u, mem, MEM_BLOCK_ALL, index, (void *)&entry_data); 4410 4411 /* update again cache entry */ 4412 cache_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 * , 4413 ALPM_HTBL_CACHE(u, i, pid), idx); 4414 *cache_ent = entry_data; 4415 } 4416 } 4417 } 4418 4419 return rv; 4420 } 4421 4422 /* Get hitbit status from a TCAM entry 4423 (it sync to Hw periodically) */ 4424 int 4425 th3_tcam_ent_hit_get(int u, int pkm, void *e, int sub_idx) 4426 { 4427 int rv = BCM_E_NONE; 4428 soc_field_t hit_fld[2] = {HIT0f, HIT1f}; 4429 _alpm_cb_t *acb = ACB_TOP(u); 4430 soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]]; 4431 4432 if (SOC_MEM_FIELD_VALID(u, mem, LWR_HIT0f)) { 4433 hit_fld[0] = LWR_HIT0f; 4434 hit_fld[1] = LWR_HIT1f; 4435 } 4436 rv = soc_mem_field32_get(u, mem, e, hit_fld[sub_idx]); 4437 4438 return rv; 4439 } 4440 4441 /* Get TCAM cached hitbit status from pvt_node's tcam_idx 4442 (it sync to Hw periodically) */ 4443 int 4444 th3_tcam_cache_hit_get(int u, int pkm, int tcam_idx) 4445 { 4446 int rv = BCM_E_NONE; 4447 int idx, sub_idx; 4448 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 4449 soc_field_t hit_fld[2] = {HIT0f, HIT1f}; 4450 4451 _alpm_cb_t *acb = ACB_TOP(u); 4452 soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]]; 4453 4454 if (SOC_MEM_FIELD_VALID(u, mem, LWR_HIT0f)) { 4455 hit_fld[0] = LWR_HIT0f; 4456 hit_fld[1] = LWR_HIT1f; 4457 } 4458 4459 if (pkm == ALPM_PKM_32B) { 4460 /* tcam_idx = idx << 1 | sub_idx */ 4461 sub_idx = tcam_idx & 1; 4462 idx = tcam_idx >> 1; 4463 } else { 4464 sub_idx = 0; 4465 idx = tcam_idx; 4466 } 4467 4468 ALPM_IER(th3_mem_read(u, acb, acb->pvt_tbl[pkm], idx, e, FALSE)); 4469 rv = soc_mem_field32_get(u, mem, e, hit_fld[sub_idx]); 4470 return rv; 4471 } 4472 4473 /* Sync TCAM hitbit cache tables with Hw */ 4474 int 4475 th3_tcam_hit_cache_sync(int u) 4476 { 4477 soc_mem_t mem; 4478 _alpm_cb_t *acb = ACB_TOP(u); 4479 int pkm, tbl_sz; 4480 int rv = BCM_E_NONE; 4481 4482 for (pkm = 0; pkm < ALPM_PKM_CNT; pkm++) { 4483 4484 if (ALPM_TCAM_TBL_SKIP(u, pkm)) { 4485 continue; /* skip duplicated or invalid TCAM table */ 4486 } 4487 4488 mem = alpm_tbl[acb->pvt_tbl[pkm]]; 4489 tbl_sz = th3_tcam_table_sz(u, pkm); 4490 if (tbl_sz) { 4491 rv = soc_mem_cache_set(u, mem, MEM_BLOCK_ANY, TRUE); 4492 } 4493 } 4494 4495 return rv; 4496 } 4497 4498 void 4499 th3_alpm_hit_deinit(int u) 4500 { 4501 int i, pid; 4502 _alpm_cb_t *acb; 4503 4504 if (ALPM_HIT_SKIP(u)) { 4505 return; 4506 } 4507 4508 /* Dist hitbit tables deinit */ 4509 if (ALPMDH(u) != NULL) { 4510 for (i = 0; i < ACB_CNT(u); i++) { 4511 acb = ACB(u, i); 4512 for (pid = 0; pid < ACB_PID_CNT(acb); pid++) { 4513 if (ALPM_HTBL(u, i, pid)) { 4514 if (ALPM_HTBL_CACHE(u, i, pid)) { 4515 soc_cm_sfree(u, ALPM_HTBL_CACHE(u, i, pid)); 4516 ALPM_HTBL_CACHE(u, i, pid) = NULL; 4517 } 4518 if (ALPM_HTBL_MOVE(u, i, pid)) { 4519 soc_cm_sfree(u, ALPM_HTBL_MOVE(u, i, pid)); 4520 ALPM_HTBL_MOVE(u, i, pid) = NULL; 4521 } 4522 if (ALPM_HTBL_MOVE_MASK(u, i, pid)) { 4523 soc_cm_sfree(u, ALPM_HTBL_MOVE_MASK(u, i, pid)); 4524 ALPM_HTBL_MOVE_MASK(u, i, pid) = NULL; 4525 } 4526 alpm_util_free(ALPM_HTBL(u, i, pid)); 4527 ALPM_HTBL(u, i, pid) = NULL; 4528 } 4529 } 4530 } 4531 } 4532 4533 return; 4534 } 4535 4536 /* Initialize TH3 ALPM distributed hitbit */ 4537 int 4538 th3_alpm_hit_init(int u) 4539 { 4540 int rv = BCM_E_NONE; 4541 int i, pid, index_cnt; 4542 int alloc_sz; 4543 soc_mem_t mem; 4544 _alpm_cb_t *acb; 4545 4546 if (ALPM_HIT_SKIP(u)) { 4547 return rv; 4548 } 4549 4550 /* Initialize bucket Levels hitbit table ctrl */ 4551 for (i = 0; i < ACB_CNT(u); i++) { 4552 acb = ACB(u, i); 4553 mem = th3_alpm_hit_tbl_mem[i]; 4554 /* Current implementation is assuming that HIT table entry 4555 is not more than 32 bits (actaully we have as maximum 16 HITBITs). 4556 Otherwise code has to adjust (for multiple words per entry) */ 4557 assert(soc_mem_entry_words(u, mem) == 1); 4558 4559 if (!SOC_WARM_BOOT(u)) { 4560 th3_alpm_hw_mem_clear(u, mem); 4561 } 4562 4563 for (pid = 0; pid < ACB_PID_CNT(acb); pid++) { 4564 alloc_sz = sizeof(_alpm_hit_tbl_ctrl_t); 4565 ALPM_ALLOC_EG(ALPM_HTBL(u, i, pid), alloc_sz, "hit_tbl"); 4566 4567 /* logic table index counter (same for HIT table) */ 4568 index_cnt = ACB_PID_BNK_CNT(acb, pid); 4569 alloc_sz = WORDS2BYTES(soc_mem_entry_words(u, mem)) * index_cnt; 4570 ALPM_HTBL_MEM(u, i, pid) = mem; 4571 ALPM_HTBL_IDX_CNT(u, i, pid) = index_cnt; 4572 ALPM_HTBL_SIZE(u, i, pid) = alloc_sz; 4573 ALPM_HTBL_ENT_MOVED(u, i, pid) = FALSE; 4574 ALPM_DMA_ALLOC_EG(u, ALPM_HTBL_CACHE(u, i, pid), 4575 alloc_sz, "hit_cache"); 4576 ALPM_DMA_ALLOC_EG(u, ALPM_HTBL_MOVE(u, i, pid), 4577 alloc_sz, "hit_move"); 4578 ALPM_DMA_ALLOC_EG(u, ALPM_HTBL_MOVE_MASK(u, i, pid), 4579 alloc_sz, "hit_move_mask"); 4580 } 4581 } 4582 4583 return rv; 4584 4585 bad: 4586 th3_alpm_hit_deinit(u); 4587 return rv; 4588 } 4589 4590 /* TH3 ALPM hitbit cleanup */ 4591 int 4592 th3_alpm_hit_cleanup(int u) 4593 { 4594 int rv = BCM_E_NONE; 4595 int i, pid; 4596 int alloc_sz; 4597 soc_mem_t mem; 4598 _alpm_cb_t *acb; 4599 4600 if (ALPM_HIT_SKIP(u)) { 4601 return rv; 4602 } 4603 4604 for (i = 0; i < ACB_CNT(u); i++) { 4605 acb = ACB(u, i); 4606 mem = th3_alpm_hit_tbl_mem[i]; 4607 4608 if (!SOC_WARM_BOOT(u)) { 4609 th3_alpm_hw_mem_clear(u, mem); 4610 } 4611 4612 for (pid = 0; pid < ACB_PID_CNT(acb); pid++) { 4613 4614 alloc_sz = ALPM_HTBL_SIZE(u, i, pid); 4615 sal_memset(ALPM_HTBL_CACHE(u, i, pid), 0, alloc_sz); 4616 sal_memset(ALPM_HTBL_MOVE(u, i, pid), 0, alloc_sz); 4617 sal_memset(ALPM_HTBL_MOVE_MASK(u, i, pid), 0, alloc_sz); 4618 4619 ALPM_HTBL_ENT_MOVED(u, i, pid) = FALSE; 4620 ALPM_HTBL_ENT_MOVED_CNT(u, i, pid) = 0; 4621 } 4622 } 4623 4624 return rv; 4625 } 4626 4627 alpm_functions_t th3_alpm_driver = { 4628 th3_alpm_ctrl_init, 4629 th3_alpm_ctrl_deinit, 4630 th3_alpm_ctrl_cleanup, 4631 th3_alpm_bkt_bnk_copy, 4632 th3_alpm_bkt_bnk_clear, 4633 th3_alpm_bkt_pfx_copy, 4634 th3_alpm_bkt_pfx_clean, 4635 th3_alpm_bkt_pfx_shrink, 4636 th3_alpm_bkt_bnk_write, 4637 th3_alpm_bkt_def_fmt_get, 4638 th3_alpm_bkt_fmt_type_get, 4639 4640 th3_alpm_ent_ent_get, 4641 th3_alpm_ent_pfx_len_get, 4642 th3_alpm_ent_selective_get, 4643 4644 /* TCAM */ 4645 th3_tcam_table_sz, 4646 th3_tcam_hw_cleanup, 4647 th3_tcam_entry_x_to_y, 4648 th3_tcam_entry_from_cfg, 4649 th3_tcam_entry_to_cfg, 4650 th3_tcam_entry_valid, 4651 th3_tcam_entry_valid_set, 4652 th3_tcam_entry_vrf_id_get, 4653 th3_tcam_entry_pfx_len_get, 4654 th3_tcam_entry_to_key, 4655 4656 th3_tcam_entry_mode_get, 4657 th3_tcam_entry_adata_get, 4658 th3_tcam_entry_bdata_get, 4659 4660 /* TCAM/ALPM */ 4661 th3_mem_read, 4662 th3_mem_write, 4663 4664 /* HITBIT */ 4665 th3_alpm_hit_init, 4666 th3_alpm_hit_deinit, 4667 th3_alpm_hit_cleanup, 4668 th3_alpm_bkt_hit_get, 4669 th3_alpm_bkt_hit_set, 4670 th3_alpm_bkt_hit_write, 4671 th3_alpm_hit_move_update, 4672 th3_alpm_hit_cache_sync, 4673 th3_alpm_hit_hw_write, 4674 th3_tcam_ent_hit_get, 4675 th3_tcam_cache_hit_get, 4676 th3_tcam_hit_cache_sync, 4677 4678 /* dump table */ 4679 th3_alpm_table_dump, 4680 th3_alpm_cap_get, 4681 4682 /* index mapping */ 4683 th3_mem_phy_index_get, 4684 }; 4685 4686 #endif /* ALPM_ENABLE */ 4687