alpm.c (136929B)
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/trident2.h> 22 #include <soc/tomahawk.h> 23 #include <soc/trident3.h> 24 #include <shared/bsl.h> 25 26 #include <shared/util.h> 27 #include <shared/l3.h> 28 29 #if defined(ALPM_ENABLE) 30 31 #include <bcm/l3.h> 32 #include <soc/alpm.h> 33 #include <bcm_int/esw/l3.h> 34 #include <bcm_int/esw/firebolt.h> 35 #include <bcm_int/esw/alpm.h> 36 #include <bcm_int/esw/alpm_util.h> 37 38 #define TD3_ALPM_BKT_BITS 13 39 40 #define TH_ENT_VALID_GET(u) \ 41 soc_mem_field32_get(u, (mem), (ent), \ 42 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? VALID_LWRf : VALIDf) 43 #define TH_ENT_HIT_GET(u) \ 44 soc_mem_field32_get(u, (mem), (ent), \ 45 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? HITf : \ 46 x ? HIT1f : HIT0f) 47 #define TH_ENT_RPE_GET(u) \ 48 soc_mem_field32_get(u, (mem), (ent), \ 49 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? RPEf : \ 50 x ? RPE1f : RPE0f) 51 #define TH_ENT_DATA_TYPE_GET(u) \ 52 soc_mem_field32_get(u, (mem), (ent), \ 53 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? DATA_TYPEf : \ 54 x ? DATA_TYPE1f : DATA_TYPE0f) 55 #define TH_ENT_ENTRY_VIEW_GET(u) \ 56 soc_mem_field32_get(u, (mem), (ent), \ 57 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? ENTRY_VIEWf : \ 58 x ? ENTRY_VIEW1f : ENTRY_VIEW0f) 59 #define TH_ENT_DST_DISCARD_GET(u) \ 60 soc_mem_field32_get(u, (mem), (ent), \ 61 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? DST_DISCARDf :\ 62 x ? DST_DISCARD1f : DST_DISCARD0f) 63 #define TH_ENT_PRI_GET(u) \ 64 soc_mem_field32_get(u, (mem), (ent), \ 65 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? PRIf : \ 66 x ? PRI1f : PRI0f) 67 #define TH_ENT_CLASS_ID_GET(u) \ 68 soc_mem_field32_get(u, (mem), (ent), \ 69 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? CLASS_IDf : \ 70 x ? CLASS_ID1f : CLASS_ID0f) 71 72 /* Key & Mask */ 73 #define TH_ENT_KEY_IPADDR_GET(u, key) \ 74 do { \ 75 int i; \ 76 if (mem == alpm_tbl[alpmTblPvtCmodeL1P128]) { \ 77 soc_field_t _key_fld_p[] = \ 78 {IP_ADDR0_LWRf, IP_ADDR1_LWRf, \ 79 IP_ADDR0_UPRf, IP_ADDR1_UPRf}; \ 80 for (i = 0; i < 4; i++) { \ 81 key[i] = soc_mem_field32_get(u, mem, ent, \ 82 _key_fld_p[i]); \ 83 } \ 84 } else { \ 85 soc_field_t _key_fld[] = {IP_ADDR0f, IP_ADDR1f};\ 86 for (i = 0; i < 2-x; i++) { \ 87 if (pkm == ALPM_PKM_32B && \ 88 x == 0 && i == 1) { \ 89 continue; \ 90 } \ 91 key[i] = soc_mem_field32_get(u, mem, ent, \ 92 _key_fld[(i+x)%2]); \ 93 } \ 94 } \ 95 } while (0) 96 97 #define TH_ENT_KEY_VRF_ID_GET(u, vrf_id) \ 98 do { \ 99 int i; \ 100 uint32 key[3] = {0}; \ 101 if (mem == alpm_tbl[alpmTblPvtCmodeL1P128]) { \ 102 soc_field_t _key_fld_p[] = \ 103 {GLOBAL_HIGHf, GLOBAL_ROUTEf, \ 104 VRF_ID_0_LWRf}; \ 105 for (i = 0; i < 3; i++) { \ 106 key[i] = soc_mem_field32_get(u, mem, ent, \ 107 _key_fld_p[i]); \ 108 } \ 109 } else { \ 110 soc_field_t _key_fld_0[] = \ 111 {GLOBAL_HIGH0f, GLOBAL_ROUTE0f, \ 112 VRF_ID_0f}; \ 113 soc_field_t _key_fld_1[] = \ 114 {GLOBAL_HIGH1f, GLOBAL_ROUTE1f, \ 115 VRF_ID_1f}; \ 116 for (i = 0; i < 3; i++) { \ 117 key[i] = soc_mem_field32_get(u, mem, ent, \ 118 x ? _key_fld_1[i] : _key_fld_0[i]); \ 119 } \ 120 } \ 121 if (key[1]) { \ 122 (vrf_id) = key[0] ? ALPM_VRF_ID_GHI(u) : \ 123 ALPM_VRF_ID_GLO(u); \ 124 } else { \ 125 (vrf_id) = key[2]; \ 126 } \ 127 } while (0) 128 129 #define TH_ENT_KEY_KT_GET(u) \ 130 soc_mem_field32_get(u, (mem), (ent), \ 131 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? KEY_TYPE0_LWRf : \ 132 x ? KEY_TYPE1f : KEY_TYPE0f) 133 #define TH_ENT_KEY_KM_GET(u) \ 134 soc_mem_field32_get(u, (mem), (ent), \ 135 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? KEY_MODE0_LWRf : \ 136 x ? KEY_MODE1f : KEY_MODE0f) 137 138 #define TH_ENT_MASK_IPADDR_GET(u, mask) \ 139 do { \ 140 int i; \ 141 if (mem == alpm_tbl[alpmTblPvtCmodeL1P128]) { \ 142 soc_field_t _msk_fld_p[] = \ 143 {IP_ADDR_MASK0_LWRf, IP_ADDR_MASK1_LWRf, \ 144 IP_ADDR_MASK0_UPRf, IP_ADDR_MASK1_UPRf}; \ 145 for (i = 0; i < 4; i++) { \ 146 mask[i] = soc_mem_field32_get(u, mem, ent, \ 147 _msk_fld_p[i]); \ 148 } \ 149 } else { \ 150 soc_field_t _msk_fld[] = \ 151 {IP_ADDR_MASK0f, IP_ADDR_MASK1f}; \ 152 for (i = 0; i < 2-x; i++) { \ 153 if (pkm == ALPM_PKM_32B && \ 154 x == 0 && i == 1) { \ 155 continue; \ 156 } \ 157 mask[i] = soc_mem_field32_get(u, mem, ent, \ 158 _msk_fld[(i+x)%2]); \ 159 } \ 160 } \ 161 } while (0) 162 163 /* Destination */ 164 #define TH_ENT_DEST_GET(u, ecmp, ipmc, nh_idx) \ 165 do { \ 166 soc_format_t fmt = DESTINATION_FORMATfmt; \ 167 uint32 dt0, dt1, dv; \ 168 if ((mem) == alpm_tbl[alpmTblPvtCmodeL1P128]) { \ 169 dv = soc_mem_field32_get(u, (mem), (ent), DESTINATIONf); \ 170 } else { \ 171 dv = soc_mem_field32_get(u, (mem), (ent), \ 172 x ? DESTINATION1f : DESTINATION0f); \ 173 } \ 174 dt0 = soc_format_field32_get(u, fmt, &dv, DEST_TYPE0f); \ 175 dt1 = soc_format_field32_get(u, fmt, &dv, DEST_TYPE1f); \ 176 if (dt0 == 3) { /* Should check dt0 first */ \ 177 ecmp = 0; \ 178 ipmc = 0; \ 179 nh_idx = soc_format_field32_get(u, fmt, &dv, NEXT_HOP_INDEXf);\ 180 } else if (dt1 == 1) { \ 181 ecmp = 1; \ 182 ipmc = 0; \ 183 nh_idx = soc_format_field32_get(u, fmt, &dv, ECMP_GROUPf); \ 184 } else if (dt1 == 3) { \ 185 ecmp = 0; \ 186 ipmc = 1; \ 187 nh_idx = soc_format_field32_get(u, fmt, &dv, IPMC_GROUPf); \ 188 } \ 189 } while (0) 190 191 /* Bucket idx */ 192 #define TH_ENT_BKT_PTR_GET(u) \ 193 soc_mem_field32_get(u, (mem), (ent), \ 194 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? ALG_BKT_PTRf : \ 195 x ? ALG_BKT_PTR1f : ALG_BKT_PTR0f) 196 #define TH_ENT_SUB_BKT_PTR_GET(u) \ 197 soc_mem_field32_get(u, (mem), (ent), \ 198 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? ALG_SUB_BKT_PTRf : \ 199 x ? ALG_SUB_BKT_PTR1f : ALG_SUB_BKT_PTR0f) 200 #define TH_ENT_DEFAULT_MISS_GET(u) \ 201 soc_mem_field32_get(u, (mem), (ent), \ 202 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? DEFAULT_MISSf : \ 203 x ? DEFAULT_MISS1f : DEFAULT_MISS0f) 204 205 /* Flex counter */ 206 #define TH_ENT_FC_BASE_ID_GET(u) \ 207 soc_mem_field32_get(u, (mem), (ent), \ 208 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? FLEX_CTR_BASE_COUNTER_IDXf : \ 209 x ? FLEX_CTR_BASE_COUNTER_IDX1f : FLEX_CTR_BASE_COUNTER_IDX0f) 210 #define TH_ENT_FC_MODE_GET(u) \ 211 soc_mem_field32_get(u, (mem), (ent), \ 212 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? FLEX_CTR_OFFSET_MODEf : \ 213 x ? FLEX_CTR_OFFSET_MODE1f : FLEX_CTR_OFFSET_MODE0f) 214 #define TH_ENT_FC_POOL_GET(u) \ 215 soc_mem_field32_get(u, (mem), (ent), \ 216 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? FLEX_CTR_POOL_NUMBERf : \ 217 x ? FLEX_CTR_POOL_NUMBER1f : FLEX_CTR_POOL_NUMBER0f) 218 219 /* IPMC */ 220 #define TH_ENT_MC_CPU_GET(u) \ 221 soc_mem_field32_get(u, (mem), (ent), \ 222 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf : \ 223 x ? IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f : IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f) 224 #define TH_ENT_MC_DROP_GET(u) \ 225 soc_mem_field32_get(u, (mem), (ent), \ 226 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf : \ 227 x ? IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f : IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f) 228 #define TH_ENT_MC_IIF_GET(u) \ 229 soc_mem_field32_get(u, (mem), (ent), \ 230 (mem) == alpm_tbl[alpmTblPvtCmodeL1P128] ? EXPECTED_L3_IIFf : \ 231 x ? EXPECTED_L3_IIF1f : EXPECTED_L3_IIF0f) 232 233 /* ALPM bucket entry get */ 234 #define TH_BKT_VALID_GET(u) \ 235 soc_format_field32_get(u, (fmt), (ent), VALIDf) 236 #define TH_BKT_LENGTH_GET(u) \ 237 soc_format_field32_get(u, (fmt), (ent), LENGTHf) 238 #define TH_BKT_KEY_GET(u, key) \ 239 soc_format_field_get(u, (fmt), (ent), KEYf, key) 240 #define TH_BKT_SUB_BKT_PTR_GET(u) \ 241 soc_format_field32_get(u, (fmt), (ent), SUB_BKT_PTRf) 242 #define TH_BKT_CLASS_ID_GET(u) \ 243 soc_format_field32_get(u, (fmt), (ent), CLASS_IDf) 244 #define TH_BKT_DST_DISCARD_GET(u) \ 245 soc_format_field32_get(u, (fmt), (ent), DST_DISCARDf) 246 #define TH_BKT_RPE_GET(u) \ 247 soc_format_field32_get(u, (fmt), (ent), RPEf) 248 #define TH_BKT_PRI_GET(u) \ 249 soc_format_field32_get(u, (fmt), (ent), PRIf) 250 251 #define TH_BKT_DEST_GET(u, ecmp, ipmc, nh_idx) \ 252 do { \ 253 soc_format_t dfmt = DESTINATION_FORMATfmt; \ 254 uint32 dt0, dt1, dv; \ 255 dv = soc_format_field32_get(u, (fmt), (ent), DESTINATIONf); \ 256 dt0 = soc_format_field32_get(u, dfmt, &dv, DEST_TYPE0f); \ 257 dt1 = soc_format_field32_get(u, dfmt, &dv, DEST_TYPE1f); \ 258 if (dt0 == 3) { /* Should check dt0 first */ \ 259 ecmp = 0; \ 260 ipmc = 0; \ 261 nh_idx = soc_format_field32_get(u, dfmt, &dv, NEXT_HOP_INDEXf);\ 262 } else if (dt1 == 1) { \ 263 ecmp = 1; \ 264 ipmc = 0; \ 265 nh_idx = soc_format_field32_get(u, dfmt, &dv, ECMP_GROUPf); \ 266 } else if (dt1 == 3) { \ 267 ecmp = 0; \ 268 ipmc = 1; \ 269 nh_idx = soc_format_field32_get(u, dfmt, &dv, IPMC_GROUPf); \ 270 } \ 271 } while (0) 272 273 /* Flex counter */ 274 #define TH_BKT_FC_BASE_ID_GET(u) \ 275 soc_format_field32_get(u, (fmt), (ent), FLEX_CTR_BASE_COUNTER_IDXf) 276 #define TH_BKT_FC_MODE_GET(u) \ 277 soc_format_field32_get(u, (fmt), (ent), FLEX_CTR_OFFSET_MODEf) 278 #define TH_BKT_FC_POOL_GET(u) \ 279 soc_format_field32_get(u, (fmt), (ent), FLEX_CTR_POOL_NUMBERf) 280 281 /* Default FMT */ 282 #define ALPM_FMT_PKM_32B (1) 283 #define ALPM_FMT_PKM_64B (2) 284 #define ALPM_FMT_PKM_128 (3) 285 #define ALPM_FMT_PKM_FLEX_32B (4) 286 #define ALPM_FMT_PKM_FLEX_64B (5) 287 #define ALPM_FMT_PKM_FLEX_128 (6) 288 289 static _alpm_fmt_info_t th_fmt_info[ALPM_FMT_CNT] = { 290 { 291 ALPM_FMT_RTE, 292 6, /* 6 different formats(ROUTE FORMAT) */ 293 { /* For fmt_ent_max */ 294 0, /* FMT=0, means we cannot put entry in this format */ 295 6, /* IPV4 */ 296 4, /* IPV6_64 */ 297 2, /* IPV6_128 */ 298 4, /* IPV4_1 */ 299 3, /* IPV6_64_1 */ 300 2, /* IPV6_128 */ 301 0, 302 0, 303 0, 304 0, 305 0, 306 0, 307 }, 308 { /* For fmt_pfx_len */ 309 0, 310 32, /* ROUTE FMT1 */ 311 64, 312 128, 313 32, 314 64, 315 128, 316 0, 317 0, 318 0, 319 0, 320 0, 321 0, 322 }, 323 { /* fmt_bnk */ 324 INVALIDfmt, 325 L3_DEFIP_ALPM_ROUTE_FMT1_FULLfmt, 326 L3_DEFIP_ALPM_ROUTE_FMT2_FULLfmt, 327 L3_DEFIP_ALPM_ROUTE_FMT3_FULLfmt, 328 L3_DEFIP_ALPM_ROUTE_FMT4_FULLfmt, 329 L3_DEFIP_ALPM_ROUTE_FMT5_FULLfmt, 330 L3_DEFIP_ALPM_ROUTE_FMT3_FULLfmt, 331 INVALIDfmt, 332 INVALIDfmt, 333 INVALIDfmt, 334 INVALIDfmt, 335 INVALIDfmt, 336 INVALIDfmt 337 }, 338 { /* fmt_ent */ 339 INVALIDfmt, 340 L3_DEFIP_ALPM_ROUTE_FMT1fmt, 341 L3_DEFIP_ALPM_ROUTE_FMT2fmt, 342 L3_DEFIP_ALPM_ROUTE_FMT3fmt, 343 L3_DEFIP_ALPM_ROUTE_FMT4fmt, 344 L3_DEFIP_ALPM_ROUTE_FMT5fmt, 345 L3_DEFIP_ALPM_ROUTE_FMT3fmt, 346 INVALIDfmt, 347 INVALIDfmt, 348 INVALIDfmt, 349 INVALIDfmt, 350 INVALIDfmt, 351 INVALIDfmt 352 }, 353 {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, 354 }, /* ROUTE fmt info */ 355 { 356 ALPM_FMT_RTE, 357 6, /* 6 different formats(ROUTE FORMAT) */ 358 { /* For fmt_ent_max */ 359 0, /* FMT=0, means we cannot put entry in this format */ 360 6, /* IPV4 */ 361 4, /* IPV6_64 */ 362 2, /* IPV6_128 */ 363 4, /* IPV4_1 */ 364 3, /* IPV6_64_1 */ 365 2, /* IPV6_128 */ 366 0, 367 0, 368 0, 369 0, 370 0, 371 0, 372 }, 373 { /* For fmt_pfx_len */ 374 0, 375 32, /* ROUTE FMT1 */ 376 64, 377 128, 378 32, 379 64, 380 128, 381 0, 382 0, 383 0, 384 0, 385 0, 386 0, 387 }, 388 { /* fmt_bnk */ 389 INVALIDfmt, 390 L3_DEFIP_ALPM_ROUTE_FMT1_FULLfmt, 391 L3_DEFIP_ALPM_ROUTE_FMT2_FULLfmt, 392 L3_DEFIP_ALPM_ROUTE_FMT3_FULLfmt, 393 L3_DEFIP_ALPM_ROUTE_FMT4_FULLfmt, 394 L3_DEFIP_ALPM_ROUTE_FMT5_FULLfmt, 395 L3_DEFIP_ALPM_ROUTE_FMT3_FULLfmt, 396 INVALIDfmt, 397 INVALIDfmt, 398 INVALIDfmt, 399 INVALIDfmt, 400 INVALIDfmt, 401 INVALIDfmt 402 }, 403 { /* fmt_ent */ 404 INVALIDfmt, 405 L3_DEFIP_ALPM_ROUTE_FMT1fmt, 406 L3_DEFIP_ALPM_ROUTE_FMT2fmt, 407 L3_DEFIP_ALPM_ROUTE_FMT3fmt, 408 L3_DEFIP_ALPM_ROUTE_FMT4fmt, 409 L3_DEFIP_ALPM_ROUTE_FMT5fmt, 410 L3_DEFIP_ALPM_ROUTE_FMT3fmt, 411 INVALIDfmt, 412 INVALIDfmt, 413 INVALIDfmt, 414 INVALIDfmt, 415 INVALIDfmt, 416 INVALIDfmt 417 }, 418 {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0}, 419 }, /* ROUTE fmt info */ 420 }; 421 422 soc_field_t th_alpm_ent_fld[] = { 423 ENTRY_0f, ENTRY_1f, ENTRY_2f, ENTRY_3f, 424 ENTRY_4f, ENTRY_5f, ENTRY_6f 425 }; 426 427 static soc_mem_t th_alpm_hit_tbl_mem[] = { 428 L3_DEFIP_ALPM_HIT_ONLYm 429 }; 430 431 /* Should be the same order as _alpm_tbl_t */ 432 static soc_mem_t th_alpm_tbl[] = { 433 INVALIDm, 434 L3_DEFIPm, 435 L3_DEFIPm, 436 L3_DEFIP_PAIR_128m, 437 L3_DEFIP_PAIR_128m, 438 L3_DEFIP_ALPM_RAWm, 439 L3_DEFIP_ALPM_RAWm, 440 L3_DEFIP_ALPM_RAWm, 441 L3_DEFIP_ALPM_RAWm, 442 INVALIDm, 443 INVALIDm, 444 INVALIDm, 445 INVALIDm 446 }; 447 448 static soc_mem_t *alpm_tbl; 449 450 /* Combined mode Level2 Table */ 451 static _alpm_bkt_pool_conf_t th_alpm_cmode_pool_l2 = { 452 {NULL, NULL}, /* bnk_info, to be allocated */ 453 65536, /* 16 Banks x 4K buckets */ 454 16, /* 16 Banks per logical bucket */ 455 alpmTblBktCmodeL2, 456 0, 457 1, /* Fixed FMT */ 458 NULL, 459 &th_fmt_info[ALPM_FMT_RTE], 460 }; 461 462 /* Parallel mode Level2 Table pool for Global Routes */ 463 static _alpm_bkt_pool_conf_t th_alpm_pmode_pool_l2 = { 464 {NULL, NULL}, /* bnk_info, to be allocated */ 465 65536, /* 8 Banks x 8K buckets */ 466 8, /* 8 Banks per bucket */ 467 alpmTblBktPmodeL2, 468 0, 469 1, /* Fixed FMT */ 470 NULL, 471 &th_fmt_info[ALPM_FMT_RTE], 472 }; 473 474 /* uRPF configuration */ 475 static _alpm_bkt_pool_conf_t th_alpm_urpf_cmode_pool_l2 = { 476 {NULL, NULL}, /* bnk_info, to be allocated */ 477 32768, /* 8 Banks x 4K buckets */ 478 8, /* 8 Banks per logical bucket */ 479 alpmTblBktCmodeL2, 480 0, 481 1, /* Fixed FMT */ 482 NULL, 483 &th_fmt_info[ALPM_FMT_RTE], 484 }; 485 486 static _alpm_bkt_pool_conf_t th_alpm_urpf_pmode_pool_gbl_l2 = { 487 {NULL, NULL}, /* bnk_info, to be allocated */ 488 16384, /* 4 Banks x 4K buckets */ 489 4, /* 4 Banks per bucket */ 490 alpmTblBktPmodeGblL2, 491 0, 492 1, /* Fixed FMT */ 493 NULL, 494 &th_fmt_info[ALPM_FMT_RTE], 495 }; 496 497 static _alpm_bkt_pool_conf_t th_alpm_urpf_pmode_pool_prt_l2 = { 498 {NULL, NULL}, /* bnk_info, to be allocated */ 499 16384, /* 4 Banks x 4K buckets */ 500 4, /* 4 Banks per bucket */ 501 alpmTblBktPmodePrtL2, 502 0, 503 1, /* Fixed FMT */ 504 NULL, 505 &th_fmt_info[ALPM_FMT_RTE], 506 }; 507 508 #if defined(BCM_HELIX5_SUPPORT) 509 static _alpm_bkt_pool_conf_t hx5_alpm_cmode_pool_l2 = { 510 {NULL, NULL}, /* bnk_info, to be allocated */ 511 24576, /* 12 Banks x 2K buckets */ 512 12, /* 12 Banks per logical bucket */ 513 alpmTblBktCmodeL2, 514 0, 515 1, /* Fixed FMT */ 516 NULL, 517 &th_fmt_info[ALPM_FMT_RTE], 518 }; 519 520 /* Parallel mode Level2 Table pool for Global Routes */ 521 static _alpm_bkt_pool_conf_t hx5_alpm_pmode_pool_l2 = { 522 {NULL, NULL}, /* bnk_info, to be allocated */ 523 24576, /* 6 Banks x 4K buckets */ 524 6, /* 6 Banks per bucket */ 525 alpmTblBktPmodeL2, 526 0, 527 1, /* Fixed FMT */ 528 NULL, 529 &th_fmt_info[ALPM_FMT_RTE], 530 }; 531 532 /* uRPF configuration */ 533 static _alpm_bkt_pool_conf_t hx5_alpm_urpf_cmode_pool_l2 = { 534 {NULL, NULL}, /* bnk_info, to be allocated */ 535 12288, /* 6 Banks x 2K buckets */ 536 6, /* 6 Banks per logical bucket */ 537 alpmTblBktCmodeL2, 538 0, 539 1, /* Fixed FMT */ 540 NULL, 541 &th_fmt_info[ALPM_FMT_RTE], 542 }; 543 544 static _alpm_bkt_pool_conf_t hx5_alpm_urpf_pmode_pool_gbl_l2 = { 545 {NULL, NULL}, /* bnk_info, to be allocated */ 546 6144, /* 3 Banks x 2K buckets */ 547 3, /* 3 Banks per bucket */ 548 alpmTblBktPmodeGblL2, 549 0, 550 1, /* Fixed FMT */ 551 NULL, 552 &th_fmt_info[ALPM_FMT_RTE], 553 }; 554 555 static _alpm_bkt_pool_conf_t hx5_alpm_urpf_pmode_pool_prt_l2 = { 556 {NULL, NULL}, /* bnk_info, to be allocated */ 557 6144, /* 3 Banks x 2K buckets */ 558 3, /* 3 Banks per bucket */ 559 alpmTblBktPmodePrtL2, 560 0, 561 1, /* Fixed FMT */ 562 NULL, 563 &th_fmt_info[ALPM_FMT_RTE], 564 }; 565 #endif 566 567 static _alpm_bkt_pool_conf_t th_alpm_pool0[SOC_MAX_NUM_DEVICES]; 568 static _alpm_bkt_pool_conf_t th_alpm_pool1[SOC_MAX_NUM_DEVICES]; 569 570 static _alpm_cb_t th_alpm_1cb_template = { 571 0, /* Unit */ 572 { 573 NULL, /* pvt_ctl[V4] */ 574 NULL, /* pvt_ctl[V6] */ 575 }, 576 { /* Pivot Tables of this block */ 577 alpmTblPvtCmodeL1, 578 alpmTblPvtCmodeL1, 579 alpmTblInvalid 580 }, 581 { /* _alpm_bnk_conf_t */ 582 {NULL, NULL}, /* bnk_pool pointer */ 583 13, /* 8K buckets = 13 bits */ 584 1, /* Double Wide */ 585 8, /* 8 physical banks per bucket */ 586 3, /* 3 bits */ 587 }, 588 0 /* Block 0 */ 589 }; 590 591 static _alpm_cb_t th_alpm_1cb_template_128b = { 592 0, /* Unit */ 593 { 594 NULL, /* pvt_ctl[V4] */ 595 NULL, /* pvt_ctl[V6] */ 596 }, 597 { /* Pivot Tables of this block */ 598 alpmTblPvtCmodeL1, 599 alpmTblPvtCmodeL1P128, 600 alpmTblPvtCmodeL1P128 601 }, 602 { /* _alpm_bnk_conf_t */ 603 {NULL, NULL}, /* bnk_pool pointer */ 604 13, /* 8K buckets = 13 bits */ 605 1, /* Double Wide */ 606 8, /* 8 physical banks per bucket */ 607 3, /* 3 bits */ 608 }, 609 0 /* Block 0 */ 610 }; 611 612 #if defined(BCM_HELIX5_SUPPORT) 613 static _alpm_cb_t hx5_alpm_1cb_template = { 614 0, /* Unit */ 615 { 616 NULL, /* pvt_ctl[V4] */ 617 NULL, /* pvt_ctl[V6] */ 618 }, 619 { /* Pivot Tables of this block */ 620 alpmTblPvtCmodeL1, 621 alpmTblPvtCmodeL1, 622 alpmTblInvalid 623 }, 624 { /* bnk_conf */ 625 {NULL, NULL}, /* bnk_pool pointer */ 626 12, /* 4K buckets = 12 bits */ 627 1, /* Double Wide */ 628 6, /* 6 physical banks per bucket */ 629 3, /* 3 bits */ 630 }, 631 0 /* Block 0 */ 632 }; 633 634 static _alpm_cb_t hx5_alpm_1cb_template_128b = { 635 0, /* Unit */ 636 { 637 NULL, /* pvt_ctl[V4] */ 638 NULL, /* pvt_ctl[V6] */ 639 }, 640 { /* Pivot Tables of this block */ 641 alpmTblPvtCmodeL1, 642 alpmTblPvtCmodeL1P128, 643 alpmTblPvtCmodeL1P128 644 }, 645 { /* bnk_conf */ 646 {NULL, NULL}, /* bnk_pool pointer */ 647 12, /* 4K buckets = 12 bits */ 648 1, /* Double Wide */ 649 6, /* 6 physical banks per bucket */ 650 3, /* 3 bits */ 651 }, 652 0 /* Block 0 */ 653 }; 654 655 #endif 656 int th_alpm_bkt_hit_write(int u, int vrf_id, _alpm_cb_t *acb, 657 _alpm_tbl_t tbl, int ent_idx, int hit_val); 658 int th_alpm_ent_hit_move(int u, int vrf_id, _alpm_cb_t *acb, 659 _alpm_tbl_t tbl, int src_ent_idx, int dst_ent_idx); 660 int th_alpm_bnk_hit_move(int u, int vrf_id, _alpm_cb_t *acb, 661 _alpm_bkt_info_t *bkt_info, 662 _alpm_tbl_t tbl, int src_idx, int dst_idx); 663 int th_alpm_bnk_hit_clear(int u, int vrf_id, _alpm_cb_t *acb, 664 _alpm_bkt_info_t *bkt_info, _alpm_tbl_t tbl, int idx); 665 static int 666 th_alpm_hit_tbl_idx_get(int u, _alpm_cb_t *acb, _alpm_tbl_t tbl, int idx, int ent); 667 668 /* Adjust config based on dynamic configuration */ 669 static int 670 th_alpm_cfg_adjust(int u, _alpm_cb_t *acb) 671 { 672 int half_banks = 0; 673 674 if (SOC_URPF_STATUS_GET(u) || ALPM_MODE_CHK(u, BCM_ALPM_MODE_PARALLEL)) { 675 ACB_BKT_DW(acb) = 0; 676 } else { 677 ACB_BKT_DW(acb) = 1; 678 } 679 680 if (SOC_URPF_STATUS_GET(u) || ACB_BKT_DW(acb)) { 681 /* Adjust bucket bits for Double wide mode and uRPF */ 682 ACB_BKT_BITS(acb) -= 1; 683 } 684 #if defined(BCM_HELIX5_SUPPORT) 685 if (soc_feature(u, soc_feature_alpm_addr_xlate)) { 686 if (soc_alpm_cmn_banks_get(u) == 4) { 687 int pid; 688 ACB_PHY_BNK_PER_BKT(acb) = ACB_PHY_BNK_PER_BKT(acb) * 2 / 3; 689 ACB_BNK_BITS(acb) = ACB_BNK_BITS(acb) * 2 / 3; 690 for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) { 691 _alpm_bkt_pool_conf_t *bp_conf = NULL; 692 bp_conf = ACB_BKT_POOL(acb, pid); 693 694 if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid - 1)) { 695 continue; 696 } 697 BPC_BNK_CNT(bp_conf) = BPC_BNK_CNT(bp_conf) * 2 / 3; 698 BPC_BNK_PER_BKT(bp_conf) = BPC_BNK_PER_BKT(bp_conf) * 2 / 3; 699 } 700 } 701 return BCM_E_NONE; 702 } 703 #endif 704 if (SOC_IS_TRIDENT3X(u) && soc_alpm_cmn_banks_get(u) == 4) { 705 half_banks = 1; 706 } 707 708 /* Half banks mode */ 709 if (half_banks) { 710 int pid; 711 /* Adjust _alpm_cb_t */ 712 ACB_PHY_BNK_PER_BKT(acb) >>= 1; 713 ACB_BNK_BITS(acb) -= 1; 714 715 /* Adjust _alpm_bkt_pool_conf_t */ 716 for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) { 717 _alpm_bkt_pool_conf_t *bp_conf; 718 bp_conf = ACB_BKT_POOL(acb, pid); 719 720 if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid-1)) { 721 continue; 722 } 723 BPC_BNK_CNT(bp_conf) >>= 1; 724 BPC_BNK_PER_BKT(bp_conf) >>= 1; 725 } 726 ALPMC(u)->_alpm_half_banks = 1; 727 } 728 729 return BCM_E_NONE; 730 } 731 732 #define HX5_ALPM_BKT_ENT_MAX (6) 733 #define HX5_ALPM_PHY_BKT_BITS (12) 734 735 /* Convert <bnk>|<bkt> style index to TD3 style index */ 736 #define TH_MEM_TAB_IDX_CONVERT(u, acb, tbl, index) \ 737 do { \ 738 if (tbl >= alpmTblBktCmodeL2) { \ 739 int bkt, bnk; \ 740 bkt = ALPM_IDX_TO_BKT(acb, index); \ 741 bnk = ALPM_IDX_TO_BNK(acb, index); \ 742 bkt = (bkt << ACB_BKT_DW(acb)) + \ 743 bnk / ACB_PHY_BNK_PER_BKT(acb); \ 744 bnk = bnk % ACB_PHY_BNK_PER_BKT(acb); \ 745 index = !soc_feature(u, soc_feature_alpm_addr_xlate) ? \ 746 (bkt << ACB_BNK_BITS(acb) | bnk) : \ 747 (bnk << HX5_ALPM_PHY_BKT_BITS | bkt); \ 748 } \ 749 } while (0) 750 751 int 752 th_mem_phy_index_get(int u, _alpm_cb_t *acb, _alpm_tbl_t tbl, int index) 753 { 754 int phy_index; 755 756 /* Convert index to TD3 style as below 757 * ------------------------- 758 * | bkt | bnk | 759 * ------------------------- 760 */ 761 TH_MEM_TAB_IDX_CONVERT(u, acb, tbl, index); 762 763 phy_index = index; 764 if (SOC_URPF_STATUS_GET(u)) { 765 switch (tbl) { 766 case alpmTblBktPmodeGblL2: 767 case alpmTblBktPmodeGblL3: 768 /* Private(Pid 0)/Global(Pid 1), 769 * VRF=1 means Private(Pid 0) */ 770 if (!soc_feature(u, soc_feature_alpm_addr_xlate)) { 771 phy_index = index + ACB_BNK_PER_BKT(acb, 1); 772 } else { 773 int phy_bnk; 774 int phy_bkt; 775 phy_bnk = phy_index >> HX5_ALPM_PHY_BKT_BITS; 776 phy_bkt = phy_index & ((1 << HX5_ALPM_PHY_BKT_BITS) -1); 777 phy_bnk += ACB_BNK_PER_BKT(acb, 1); 778 phy_index = (phy_bnk << HX5_ALPM_PHY_BKT_BITS) + phy_bkt; 779 } 780 break; 781 default: 782 break; 783 } 784 } 785 return phy_index; 786 } 787 788 int 789 th_mem_read(int u, _alpm_cb_t *acb, _alpm_tbl_t tbl, 790 int index, void *entry_data, int no_cache) 791 { 792 int rv = BCM_E_NONE; 793 soc_mem_t mem; 794 795 mem = alpm_tbl[tbl]; 796 index = th_mem_phy_index_get(u, acb, tbl, index); 797 798 if (no_cache) { 799 rv = soc_mem_read_no_cache(u, 0, mem, 0, MEM_BLOCK_ANY, 800 index, entry_data); 801 } else { 802 rv = soc_mem_read(u, mem, MEM_BLOCK_ANY, index, entry_data); 803 } 804 if (BCM_SUCCESS(rv)) { 805 acb->acb_cnt.c_mem[tbl][0]++; 806 } 807 808 return rv; 809 } 810 811 /* WAR for TD3 only */ 812 void 813 th_mem_urpf_pvt_flexctr_set(int u, soc_mem_t mem, void *entry) 814 { 815 int i; 816 soc_field_t fc_flds[] = { 817 FLEX_CTR_POOL_NUMBER0f, 818 FLEX_CTR_OFFSET_MODE0f, 819 FLEX_CTR_BASE_COUNTER_IDX0f, 820 FLEX_CTR_POOL_NUMBER1f, 821 FLEX_CTR_OFFSET_MODE1f, 822 FLEX_CTR_BASE_COUNTER_IDX1f, 823 FLEX_CTR_POOL_NUMBERf, 824 FLEX_CTR_OFFSET_MODEf, 825 FLEX_CTR_BASE_COUNTER_IDXf 826 }; 827 for (i = 0; i < (sizeof(fc_flds)/sizeof(fc_flds[0])); i++) { 828 if (soc_mem_field_valid(u, mem, fc_flds[i])) { 829 soc_mem_field32_set(u, mem, entry, fc_flds[i], 0); 830 } 831 } 832 } 833 834 void 835 th_mem_urpf_pvt_def_rte_set(int u, soc_mem_t mem, void *entry) 836 { 837 int i; 838 uint32 mask; 839 soc_field_t msk_fld[] = { 840 IP_ADDR_MASK0f, 841 IP_ADDR_MASK1f, 842 IP_ADDR_MASK1_UPRf 843 }; 844 845 soc_field_t dft_fld[] = { 846 DEFAULTROUTE0f, 847 DEFAULTROUTE1f, 848 DEFAULTROUTEf 849 }; 850 851 for (i = 0; i < (sizeof(msk_fld)/sizeof(msk_fld[0])); i++) { 852 if (soc_mem_field_valid(u, mem, msk_fld[i])) { 853 mask = soc_mem_field32_get(u, mem, entry, msk_fld[i]); 854 if (!mask) { 855 soc_mem_field32_set(u, mem, entry, dft_fld[i], 1); 856 } 857 } 858 } 859 860 return; 861 } 862 863 void 864 th_mem_urpf_pvt_bkt_ptr_set(int u, soc_mem_t mem, void *entry) 865 { 866 int i; 867 uint32 bkt_ptr; 868 uint32 urpf_offset; 869 soc_field_t bkt_fld[] = { 870 ALG_BKT_PTR0f, 871 ALG_BKT_PTR1f, 872 ALG_BKT_PTRf 873 }; 874 urpf_offset = soc_feature(u, soc_feature_alpm_addr_xlate) ? 2048 : 4096; 875 for (i = 0; i < (sizeof(bkt_fld)/sizeof(bkt_fld[0])); i++) { 876 if (soc_mem_field_valid(u, mem, bkt_fld[i])) { 877 bkt_ptr = soc_mem_field32_get(u, mem, entry, bkt_fld[i]); 878 if (bkt_ptr != 0) { 879 soc_mem_field32_set(u, mem, entry, bkt_fld[i], bkt_ptr + urpf_offset); 880 } 881 } 882 } 883 884 return; 885 } 886 887 void 888 th_mem_urpf_bkt_flexctr_set(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, 889 int log_idx, void *entry) 890 { 891 int i, eid, bnk; 892 int vrf_id; 893 uint8 fid; 894 _alpm_bkt_info_t *bkt_info; 895 soc_format_t bfmt, efmt; 896 uint32 ent[17]; 897 soc_field_t fc_flds[] = { 898 FLEX_CTR_POOL_NUMBERf, 899 FLEX_CTR_OFFSET_MODEf, 900 FLEX_CTR_BASE_COUNTER_IDXf 901 }; 902 903 904 bkt_info = &PVT_BKT_INFO(pvt_node); 905 vrf_id = PVT_BKT_VRF(pvt_node); 906 bnk = ALPM_IDX_TO_BNK(acb, log_idx); 907 fid = bkt_info->bnk_fmt[bnk]; 908 909 bfmt = ACB_FMT_BNK(acb, vrf_id, fid); 910 efmt = ACB_FMT_ENT(acb, vrf_id, fid); 911 for (eid = 0; eid < ACB_FMT_ENT_MAX(acb, vrf_id, fid); eid++) { 912 soc_format_field_get(u, bfmt, entry, th_alpm_ent_fld[eid], ent); 913 for (i = 0; i < (sizeof(fc_flds)/sizeof(fc_flds[0])); i++) { 914 if (soc_format_field_valid(u, efmt, fc_flds[i])) { 915 soc_format_field32_set(u, efmt, ent, fc_flds[i], 0); 916 } 917 } 918 /* Write entry back to bank */ 919 soc_format_field_set(u, bfmt, entry, th_alpm_ent_fld[eid], ent); 920 } 921 } 922 923 void 924 th_mem_urpf_bkt_def_rte_set(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, 925 int log_idx, void *entry) 926 { 927 int eid, bnk; 928 int vrf_id; 929 uint8 fid; 930 _alpm_bkt_info_t *bkt_info; 931 soc_format_t bfmt, efmt; 932 uint32 ent[17]; 933 934 bkt_info = &PVT_BKT_INFO(pvt_node); 935 vrf_id = PVT_BKT_VRF(pvt_node); 936 bnk = ALPM_IDX_TO_BNK(acb, log_idx); 937 fid = bkt_info->bnk_fmt[bnk]; 938 939 bfmt = ACB_FMT_BNK(acb, vrf_id, fid); 940 efmt = ACB_FMT_ENT(acb, vrf_id, fid); 941 for (eid = 0; eid < ACB_FMT_ENT_MAX(acb, vrf_id, fid); eid++) { 942 soc_format_field_get(u, bfmt, entry, th_alpm_ent_fld[eid], ent); 943 if (soc_format_field32_get(u, efmt, ent, VALIDf) && 944 soc_format_field32_get(u, efmt, ent, LENGTHf) == 0) { 945 soc_format_field32_set(u, efmt, ent, DEFAULTROUTEf, 1); 946 } 947 /* Write entry back to bank */ 948 soc_format_field_set(u, bfmt, entry, th_alpm_ent_fld[eid], ent); 949 } 950 } 951 952 /* pvt_node is only used for writing pivot to bucket table */ 953 int 954 th_mem_write(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, 955 _alpm_tbl_t tbl, int index, void *entry_data) 956 { 957 int rv = BCM_E_NONE; 958 int phy_index; 959 soc_mem_t mem; 960 void *entry = entry_data; 961 962 mem = alpm_tbl[tbl]; 963 if (entry == NULL) { 964 entry = soc_mem_entry_null(u, mem); 965 } 966 phy_index = th_mem_phy_index_get(u, acb, tbl, index); 967 968 if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_WRITE_CACHE_ONLY) { 969 _soc_mem_alpm_write_cache(u, mem, MEM_BLOCK_ALL, phy_index, entry); 970 } else { 971 rv = soc_mem_write(u, mem, MEM_BLOCK_ALL, phy_index, entry); 972 #if defined (BCM_TRIDENT3_SUPPORT) 973 if (tbl >= alpmTblBktCmodeL2) { 974 int i; 975 int8 fmt = 0; 976 for (i = 0; i < ALPM_BPB_MAX; i++) { 977 fmt |= pvt_node->bkt_info.bnk_fmt[i]; 978 } 979 _soc_trident3_alpm2_bnk_fmt_set(u, phy_index, 980 entry_data == NULL ? 0 : fmt); 981 } 982 #endif 983 if (SOC_URPF_STATUS_GET(u)) { 984 int urpf_index; 985 urpf_index = phy_index + (soc_mem_index_count(u, mem) >> 1); 986 if (soc_feature(u, soc_feature_alpm_addr_xlate)) { 987 if (tbl >= alpmTblBktCmodeL2) { 988 int phy_bnk; 989 int phy_bkt; 990 phy_bnk = phy_index >> HX5_ALPM_PHY_BKT_BITS; 991 phy_bkt = phy_index & ((1 << HX5_ALPM_PHY_BKT_BITS) -1); 992 phy_bkt += 1 << (HX5_ALPM_PHY_BKT_BITS - 1); 993 urpf_index = (phy_bnk << HX5_ALPM_PHY_BKT_BITS) + phy_bkt; 994 } 995 } 996 /* Pvt Table */ 997 if (entry_data != NULL) { 998 if (tbl >= alpmTblBktCmodeL2) { 999 if (alpm_util_route_type_get(u, NULL)) { 1000 th_mem_urpf_bkt_flexctr_set(u, acb, pvt_node, 1001 index, entry_data); 1002 } 1003 th_mem_urpf_bkt_def_rte_set(u, acb, pvt_node, 1004 index, entry_data); 1005 } else { 1006 if (alpm_util_route_type_get(u, NULL)) { 1007 th_mem_urpf_pvt_flexctr_set(u, mem, entry_data); 1008 } 1009 th_mem_urpf_pvt_def_rte_set(u, mem, entry_data); 1010 th_mem_urpf_pvt_bkt_ptr_set(u, mem, entry_data); 1011 } 1012 } 1013 rv = soc_mem_write(u, mem, MEM_BLOCK_ALL, urpf_index, entry); 1014 #if defined (BCM_TRIDENT3_SUPPORT) 1015 if (tbl >= alpmTblBktCmodeL2) { 1016 int i; 1017 int8 fmt = 0; 1018 for (i = 0; i < ALPM_BPB_MAX; i++) { 1019 fmt |= pvt_node->bkt_info.bnk_fmt[i]; 1020 } 1021 _soc_trident3_alpm2_bnk_fmt_set(u, phy_index, 1022 entry_data == NULL ? 0 : fmt); 1023 } 1024 #endif 1025 } 1026 } 1027 1028 if (BCM_SUCCESS(rv)) { 1029 acb->acb_cnt.c_mem[tbl][1]++; 1030 if (tbl >= alpmTblBktCmodeL2) { 1031 if (pvt_node != NULL) { 1032 ACB_PVT_PTR(acb, pvt_node, index) = 1033 entry_data ? pvt_node : NULL; 1034 } 1035 } 1036 } 1037 1038 return rv; 1039 } 1040 1041 int 1042 th_mem_bulk_write(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, 1043 _alpm_tbl_t tbl, int *index, uint32 **entry_data, int count) 1044 { 1045 int i; 1046 int rv = BCM_E_NONE; 1047 1048 for (i = 0; i < count; i++) { 1049 rv = th_mem_write(u, acb, pvt_node, tbl, index[i], entry_data[i]); 1050 ALPM_IER(rv); 1051 } 1052 1053 return rv; 1054 } 1055 1056 /* 1057 int 1058 th_mem_bulk_write(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, 1059 _alpm_tbl_t tbl, int *index, uint32 **entry_data, int count) 1060 { 1061 int i; 1062 int phy_index[20]; 1063 int copyno[20]; 1064 soc_mem_t bulk_mem[20]; 1065 int rv = BCM_E_NONE; 1066 1067 assert(count <= 20); 1068 1069 for (i = 0; i < count; i++) { 1070 phy_index[i] = th_mem_phy_index_get(u, acb, tbl, index[i]); 1071 copyno[i] = MEM_BLOCK_ALL; 1072 bulk_mem[i] = alpm_tbl[tbl]; 1073 } 1074 1075 if (ALPMC(u)->_alpm_dbg_bmp & _ALPM_DBG_WRITE_CACHE_ONLY) { 1076 for (i = 0; i < count; i++) { 1077 _soc_mem_alpm_write_cache(u, bulk_mem[i], copyno[i], phy_index[i], 1078 entry_data[i]); 1079 } 1080 } else { 1081 if (count <= ALPMC(u)->_alpm_bulk_wr_threshold) { 1082 for (i = 0; i < count; i++) { 1083 rv = soc_mem_write(u, bulk_mem[i], copyno[i], phy_index[i], 1084 entry_data[i]); 1085 ALPM_IER(rv); 1086 } 1087 1088 if (SOC_URPF_STATUS_GET(u)) { 1089 for (i = 0; i < count; i++) { 1090 int urpf_index; 1091 urpf_index = phy_index[i] + 1092 (soc_mem_index_count(u, bulk_mem[i]) >> 1); 1093 rv = soc_mem_write(u, bulk_mem[i], copyno[i], urpf_index, 1094 entry_data[i]); 1095 ALPM_IER(rv); 1096 } 1097 } 1098 1099 } 1100 else { 1101 assert(0); 1102 rv = soc_mem_bulk_write(u, bulk_mem, phy_index, 1103 copyno, entry_data, count); 1104 } 1105 } 1106 1107 if (BCM_SUCCESS(rv)) { 1108 for (i = 0; i < count; i++) { 1109 acb->acb_cnt.c_mem[tbl][1]++; 1110 acb->acb_cnt.c_bulk_mem[tbl][1]++; 1111 1112 if (pvt_node != NULL) { 1113 ACB_PVT_PTR(acb, pvt_node, index[i]) = pvt_node; 1114 } 1115 } 1116 } 1117 1118 return rv; 1119 } 1120 */ 1121 1122 /* ALPM related functions */ 1123 1124 static int 1125 th_alpm_cb_cnt(int u) 1126 { 1127 int acb_cnt, alpm_enable; 1128 alpm_enable = soc_property_get(u, spn_L3_ALPM_ENABLE, 2); 1129 1130 if (alpm_enable) { 1131 acb_cnt = 1; /* 1 ALPM Control Block */ 1132 } else { 1133 acb_cnt = 0; 1134 } 1135 1136 return acb_cnt; 1137 } 1138 1139 void 1140 th_alpm_ctrl_deinit(int u) 1141 { 1142 int i, j, pid, ipt, acb_cnt; 1143 _alpm_cb_t *acb; 1144 1145 acb_cnt = th_alpm_cb_cnt(u); 1146 for (i = 0; i < acb_cnt; i++) { 1147 acb = ACB(u, i); 1148 if (acb != NULL) { 1149 /* Free Bucket pool */ 1150 for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) { 1151 _alpm_bkt_pool_conf_t *bp_conf; 1152 1153 bp_conf = ACB_BKT_POOL(acb, pid); 1154 if (bp_conf->pvt_ptr != NULL) { 1155 alpm_util_free(bp_conf->pvt_ptr); 1156 bp_conf->pvt_ptr = NULL; 1157 } 1158 for (ipt = ALPM_IPT_V4; ipt < ALPM_IPT_CNT; ipt++) { 1159 if (ipt > ALPM_IPT_V4 && 1160 BPC_BNK_INFO(bp_conf, ipt) == 1161 BPC_BNK_INFO(bp_conf, ipt - 1)) { 1162 continue; 1163 } 1164 if (BPC_BNK_INFO(bp_conf, ipt) != NULL) { 1165 alpm_util_free(BPC_BNK_INFO(bp_conf, ipt)); 1166 } 1167 } 1168 for (ipt = ALPM_IPT_V4; ipt < ALPM_IPT_CNT; ipt++) { 1169 BPC_BNK_INFO(bp_conf, ipt) = NULL; 1170 } 1171 } 1172 1173 for (j = 0; j < ALPM_IPT_CNT; j++) { 1174 if (acb->pvt_ctl[j] != NULL) { 1175 alpm_util_free(acb->pvt_ctl[j]); 1176 acb->pvt_ctl[j] = NULL; 1177 } 1178 } 1179 1180 alpm_util_free(acb); 1181 ACB(u, i) = NULL; 1182 } 1183 } 1184 1185 return ; 1186 } 1187 1188 static void 1189 th_alpm_hw_mem_clear(int u, soc_mem_t mem) 1190 { 1191 int i; 1192 uint8 *mbuf; 1193 int size; 1194 soc_mem_t clr_mem[2] = {INVALIDm, INVALIDm}; 1195 1196 /* Clear table with ECC view to make sure 1197 * both data & ecc get cleared 1198 * 1199 * Clear L3_DEFIP_ALPM_RAWm as well to make sure 1200 * memory cache gets cleared as well. 1201 */ 1202 clr_mem[0] = mem; 1203 if (mem == L3_DEFIP_ALPM_RAWm) { 1204 clr_mem[1] = L3_DEFIP_ALPM_ECCm; 1205 } 1206 1207 for (i = 0; i < 2; i++) { 1208 if (clr_mem[i] == INVALIDm) { 1209 continue; 1210 } 1211 1212 ALPM_INFO(("ALPM clearing mem %s\n", SOC_MEM_NAME(u, clr_mem[i]))); 1213 1214 size = SOC_MEM_TABLE_BYTES(u, clr_mem[i]); 1215 mbuf = soc_cm_salloc(u, size, "alpm_mem"); 1216 if (mbuf == NULL) { 1217 ALPM_ERR(("th_alpm_hw_mem_clear alloc DMA memory failed\n")); 1218 return ; 1219 } 1220 sal_memset(mbuf, 0, size); 1221 1222 (void)soc_mem_write_range(u, clr_mem[i], MEM_BLOCK_ALL, 1223 soc_mem_index_min(u, clr_mem[i]), 1224 soc_mem_index_max(u, clr_mem[i]), mbuf); 1225 soc_cm_sfree(u, mbuf); 1226 } 1227 1228 return ; 1229 } 1230 1231 static int 1232 th_alpm_rpf_ctrl_init(int u) 1233 { 1234 int i; 1235 uint32 rval; 1236 soc_reg_t reg = L3_DEFIP_RPF_CONTROLr; 1237 1238 #define FLDS_CNT 3 1239 soc_field_t flds[FLDS_CNT] = { 1240 LPM_MODEf, 1241 LOOKUP_MODEf, 1242 ENABLE_DOUBLE_WIDE_BUCKETS_FOR_IPV4f 1243 }; 1244 1245 uint32 vals[FLDS_CNT] = { 1246 1, 1247 0, 1248 1 1249 }; 1250 1251 /* Adjust LOOKUP_MODEf value */ 1252 vals[1] = ALPM_MODE(u); 1253 SOC_IF_ERROR_RETURN(READ_L3_DEFIP_RPF_CONTROLr(u, &rval)); 1254 for (i = 0; i < FLDS_CNT; i++) { 1255 if (SOC_REG_FIELD_VALID(u, reg, flds[i])) { 1256 soc_reg_field_set(u, reg, &rval, flds[i], vals[i]); 1257 } 1258 } 1259 SOC_IF_ERROR_RETURN(WRITE_L3_DEFIP_RPF_CONTROLr(u, rval)); 1260 1261 return BCM_E_NONE; 1262 } 1263 1264 static int 1265 th_alpm_key_sel_init(int u) 1266 { 1267 int i, urpf_enb, lpm_128b; 1268 uint32 rval = 0; 1269 soc_reg_t kselr = L3_DEFIP_KEY_SELr; 1270 1271 /* URPF[bit1], 128B[bit0] */ 1272 int key_sel[4] = { 1273 2, /* 0x00b non-URPF + lpm-64b */ 1274 0, /* 0x01b non-URPF + lpm-128b */ 1275 3, /* 0x10b uRPF + lpm-64b */ 1276 1 /* 0x11b uRPF + lpm-128b */ 1277 }; 1278 1279 urpf_enb = !!SOC_URPF_STATUS_GET(u); 1280 lpm_128b = !!SOC_ALPM_128B_ENABLE(u); 1281 1282 if (soc_reg_field_valid(u, kselr, KEY_SEL_CAM0_1f)) { 1283 i = lpm_128b; 1284 soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM0_1f, key_sel[i]); 1285 soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM2_3f, key_sel[i]); 1286 soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM4_5f, key_sel[i]); 1287 soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM6_7f, key_sel[i]); 1288 if (urpf_enb) { 1289 i = (urpf_enb << 1) | lpm_128b; 1290 soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM4_5f, key_sel[i]); 1291 soc_reg_field_set(u, kselr, &rval, KEY_SEL_CAM6_7f, key_sel[i]); 1292 } 1293 } else { 1294 if (urpf_enb) { 1295 soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM4f, 0x1); 1296 soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM5f, 0x1); 1297 soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM6f, 0x1); 1298 soc_reg_field_set(u, kselr, &rval, URPF_LOOKUP_CAM7f, 0x1); 1299 } 1300 } 1301 1302 BCM_IF_ERROR_RETURN(WRITE_L3_DEFIP_KEY_SELr(u, rval)); 1303 return BCM_E_NONE; 1304 } 1305 1306 static int 1307 th_alpm_cfg_init(int u) 1308 { 1309 soc_reg_t creg = L3_DEFIP_ALPM_CFGr; 1310 uint32 rval = 0; 1311 if (ALPM_TCAM_ZONED(u)) { 1312 if (SOC_URPF_STATUS_GET(u)) { 1313 /* 4 DIPs, 4 SIPs */ 1314 if (soc_reg_field_valid(u, creg, CAM0_1_SELf)) { 1315 /* *DIP */ 1316 soc_reg_field_set(u, creg, &rval, CAM2_3_SELf, 1); 1317 /* VRF SIP */ 1318 soc_reg_field_set(u, creg, &rval, CAM4_5_SELf, 2); 1319 /* *SIP */ 1320 soc_reg_field_set(u, creg, &rval, CAM6_7_SELf, 3); 1321 } else { 1322 /* *DIP */ 1323 soc_reg_field_set(u, creg, &rval, TCAM2_SELf, 1); 1324 soc_reg_field_set(u, creg, &rval, TCAM3_SELf, 1); 1325 /* VRF SIP */ 1326 soc_reg_field_set(u, creg, &rval, TCAM4_SELf, 2); 1327 soc_reg_field_set(u, creg, &rval, TCAM5_SELf, 2); 1328 /* *SIP */ 1329 soc_reg_field_set(u, creg, &rval, TCAM6_SELf, 3); 1330 soc_reg_field_set(u, creg, &rval, TCAM7_SELf, 3); 1331 } 1332 } else { 1333 if (soc_reg_field_valid(u, creg, CAM0_1_SELf)) { 1334 soc_reg_field_set(u, creg, &rval, CAM4_5_SELf, 1); 1335 soc_reg_field_set(u, creg, &rval, CAM6_7_SELf, 1); 1336 } else { 1337 soc_reg_field_set(u, creg, &rval, TCAM4_SELf, 1); 1338 soc_reg_field_set(u, creg, &rval, TCAM5_SELf, 1); 1339 soc_reg_field_set(u, creg, &rval, TCAM6_SELf, 1); 1340 soc_reg_field_set(u, creg, &rval, TCAM7_SELf, 1); 1341 } 1342 } 1343 } else { 1344 if (SOC_URPF_STATUS_GET(u)) { 1345 /* 4 DIPs, 4 SIPs */ 1346 if (soc_reg_field_valid(u, creg, CAM0_1_SELf)) { 1347 soc_reg_field_set(u, creg, &rval, CAM4_5_SELf, 2); 1348 soc_reg_field_set(u, creg, &rval, CAM6_7_SELf, 2); 1349 } else { 1350 /* DIP */ 1351 /* VRF SIP */ 1352 soc_reg_field_set(u, creg, &rval, TCAM4_SELf, 2); 1353 soc_reg_field_set(u, creg, &rval, TCAM5_SELf, 2); 1354 soc_reg_field_set(u, creg, &rval, TCAM6_SELf, 2); 1355 soc_reg_field_set(u, creg, &rval, TCAM7_SELf, 2); 1356 } 1357 } 1358 } 1359 BCM_IF_ERROR_RETURN(WRITE_L3_DEFIP_ALPM_CFGr(u, rval)); 1360 1361 return BCM_E_NONE; 1362 } 1363 1364 1365 static int 1366 th_alpm_hw_init(int u) 1367 { 1368 int rv = BCM_E_NONE; 1369 1370 BCM_IF_ERROR_RETURN(th_alpm_rpf_ctrl_init(u)); 1371 BCM_IF_ERROR_RETURN(th_alpm_key_sel_init(u)); 1372 BCM_IF_ERROR_RETURN(th_alpm_cfg_init(u)); 1373 1374 return rv; 1375 } 1376 1377 int 1378 th_alpm_ctrl_init(int u) 1379 { 1380 int rv = BCM_E_NONE; 1381 int i, j, pid, acb_cnt, vrf_id_cnt; 1382 1383 int alloc_sz; 1384 #if 0 1385 int sf, scale_factor = 1; 1386 #endif 1387 1388 soc_mem_t mem, allmems[20] = {INVALIDm}; 1389 int m, mem_cnt = 0; 1390 1391 /* 1392 * b2(p1) b1(p0) bit0(128b) 1393 * --------------------------- 1394 * 0 0 0 -> 2-Level (64b) 1395 * 0 0 1 -> 2-Level (128b) 1396 */ 1397 _alpm_cb_t *acb_template[2] = { 1398 &th_alpm_1cb_template, 1399 &th_alpm_1cb_template_128b, 1400 }; 1401 1402 _alpm_bkt_pool_conf_t *acb_bp_conf[8] = { 1403 &th_alpm_pool0[u], 1404 &th_alpm_pool0[u], 1405 &th_alpm_pool0[u], 1406 &th_alpm_pool0[u], 1407 }; 1408 1409 _alpm_bkt_pool_conf_t *acb_urpf_bp_conf[8] = { 1410 &th_alpm_pool0[u], 1411 &th_alpm_pool0[u], 1412 &th_alpm_pool0[u], 1413 &th_alpm_pool1[u], 1414 }; 1415 1416 _alpm_bkt_pool_conf_t *acb_bp_conf_template[8] = { 1417 &th_alpm_cmode_pool_l2, 1418 &th_alpm_pmode_pool_l2, 1419 &th_alpm_cmode_pool_l2, 1420 &th_alpm_pmode_pool_l2 1421 }; 1422 1423 _alpm_bkt_pool_conf_t *acb_urpf_bp_conf_template[8] = { 1424 &th_alpm_urpf_cmode_pool_l2, 1425 &th_alpm_urpf_pmode_pool_prt_l2, 1426 &th_alpm_urpf_cmode_pool_l2, 1427 &th_alpm_urpf_pmode_pool_gbl_l2 1428 }; 1429 1430 /* assert ALPM_MEM_ENT_MAX for largest TCAM/ALPM memory entry */ 1431 assert(ALPM_MEM_ENT_MAX * sizeof(uint32) 1432 >= sizeof(defip_pair_128_entry_t)); 1433 1434 if (SOC_MEM_IS_VALID(u, L3_DEFIP_ALPM_RAWm)) { 1435 alpm_tbl = &th_alpm_tbl[0]; 1436 } 1437 1438 #if defined(BCM_HELIX5_SUPPORT) 1439 if (soc_feature(u, soc_feature_alpm_addr_xlate)) { 1440 acb_bp_conf_template[0] = &hx5_alpm_cmode_pool_l2; 1441 acb_bp_conf_template[1] = &hx5_alpm_pmode_pool_l2; 1442 acb_bp_conf_template[2] = &hx5_alpm_cmode_pool_l2; 1443 acb_bp_conf_template[3] = &hx5_alpm_pmode_pool_l2; 1444 1445 acb_urpf_bp_conf_template[0] = &hx5_alpm_urpf_cmode_pool_l2; 1446 acb_urpf_bp_conf_template[1] = &hx5_alpm_urpf_pmode_pool_prt_l2; 1447 acb_urpf_bp_conf_template[2] = &hx5_alpm_urpf_cmode_pool_l2; 1448 acb_urpf_bp_conf_template[3] = &hx5_alpm_urpf_pmode_pool_gbl_l2; 1449 1450 acb_template[0] = &hx5_alpm_1cb_template; 1451 acb_template[1] = &hx5_alpm_1cb_template_128b; 1452 } 1453 #endif 1454 /* Load scaling factor config 1455 * 8 means valid factors are 1,2,4,8...128 1456 */ 1457 #if 0 1458 scale_factor = soc_property_get(u, "l3_alpm_scaling_factor", 1); 1459 for (sf = 0; sf < 8; sf++) { 1460 if (scale_factor == (1 << sf)) { 1461 break; 1462 } 1463 } 1464 if (sf >= 8) { 1465 scale_factor = 1; 1466 sf = 0; 1467 } 1468 #endif 1469 1470 vrf_id_cnt = ALPM_VRF_ID_CNT(u); 1471 acb_cnt = th_alpm_cb_cnt(u); 1472 assert((acb_cnt * ALPM_PKM_CNT) < 20); 1473 1474 for (i = 0; i < acb_cnt; i++) { 1475 int idx; 1476 _alpm_cb_t *acb = NULL; 1477 1478 alloc_sz = sizeof(_alpm_cb_t); 1479 ALPM_ALLOC_EG(acb, alloc_sz, "alpm_cb"); 1480 idx = (acb_cnt - 1) << 1 | (ALPM_128B(u) & 1); 1481 sal_memcpy(acb, acb_template[idx], sizeof(_alpm_cb_t)); 1482 acb->unit = u; 1483 1484 /** 1485 * ------- 1486 * |2|1|0| 1487 * ------- 1488 * Bit 0: Zoned: Parallel/Mixed: 1, Combined: 0 1489 * Bit 1: Private(Pid 0)/Global(Pid 1) 1490 * --------- 1491 */ 1492 for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) { 1493 idx = pid << 1 | !!ALPM_MODE_CHK(u, BCM_ALPM_MODE_PARALLEL); 1494 if (SOC_URPF_STATUS_GET(u)) { 1495 ACB_BKT_POOL(acb, pid) = acb_urpf_bp_conf[idx]; 1496 sal_memcpy(acb_urpf_bp_conf[idx], 1497 acb_urpf_bp_conf_template[idx], 1498 sizeof(_alpm_bkt_pool_conf_t)); 1499 } else { 1500 ACB_BKT_POOL(acb, pid) = acb_bp_conf[idx]; 1501 sal_memcpy(acb_bp_conf[idx], 1502 acb_bp_conf_template[idx], 1503 sizeof(_alpm_bkt_pool_conf_t)); 1504 } 1505 } 1506 1507 /* Adjust ctrl bnk conf 1508 * BPC should NOT be adjusted because they point to 1509 * global storage 1510 */ 1511 ALPM_IEG(th_alpm_cfg_adjust(u, acb)); 1512 1513 #define _CHK_IF_CLEAR_MEM(mem) \ 1514 do { \ 1515 for (m = 0; m < mem_cnt; m++) { \ 1516 if (allmems[m] == (mem)) { \ 1517 break; \ 1518 } \ 1519 } \ 1520 if (m == mem_cnt && mem != INVALIDm && \ 1521 soc_mem_index_count(u, mem) > 0) { \ 1522 th_alpm_hw_mem_clear(u, (mem)); \ 1523 allmems[mem_cnt++] = (mem); \ 1524 } \ 1525 } while (0) 1526 1527 for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) { 1528 _alpm_bkt_pool_conf_t *bp_conf = ACB_BKT_POOL(acb, pid); 1529 if (pid > 0 && ACB_BKT_POOL(acb, pid-1) == bp_conf) { 1530 continue; 1531 } 1532 1533 /* Adjust bucket count based on scaling factor */ 1534 /* BPC_BNK_CNT(bp_conf) /= scale_factor; */ 1535 alloc_sz = sizeof(_alpm_bnk_info_t); 1536 ALPM_ALLOC_EG(BPC_BNK_INFO(bp_conf, ALPM_IPT_V4), 1537 alloc_sz, "bnk_bmp"); 1538 if (ALPM_128B(u) && ALPM_BKT_RSVD(u) && 1539 ACB_IDX(acb) == acb_cnt - 1) { 1540 int rsvd_v6_bnks = 1541 BPC_BNK_CNT(bp_conf) * ALPM_BKT_RSVD_CNT(u) / 8192; 1542 ALPM_ALLOC_EG( 1543 BPC_BNK_INFO(bp_conf, ALPM_IPT_V6), alloc_sz, "bnk_bmp"); 1544 /* reserved v6 bnks in v4 bitmap */ 1545 SHR_BITSET_RANGE( 1546 BPC_BNK_BMP(bp_conf, ALPM_IPT_V4), 1547 BPC_BNK_CNT(bp_conf) - rsvd_v6_bnks, 1548 rsvd_v6_bnks); 1549 BPC_BNK_RSVD(bp_conf, ALPM_IPT_V4) = rsvd_v6_bnks; 1550 /* reserved v4 bnks in v6 bitmap */ 1551 SHR_BITSET_RANGE( 1552 BPC_BNK_BMP(bp_conf, ALPM_IPT_V6), 0, 1553 BPC_BNK_CNT(bp_conf) - rsvd_v6_bnks); 1554 BPC_BNK_RSVD(bp_conf, ALPM_IPT_V6) = 1555 BPC_BNK_CNT(bp_conf) - rsvd_v6_bnks; 1556 } else { 1557 BPC_BNK_INFO(bp_conf, ALPM_IPT_V6) = 1558 BPC_BNK_INFO(bp_conf, ALPM_IPT_V4); 1559 } 1560 1561 /* Reserve bucket 0 */ 1562 SHR_BITSET_RANGE( 1563 BPC_BNK_BMP(bp_conf, ALPM_IPT_V4), 0, 1564 BPC_BNK_PER_BKT(bp_conf)); 1565 1566 if (!SOC_WARM_BOOT(u)) { 1567 mem = alpm_tbl[BPC_BKT_TBL(bp_conf)]; 1568 _CHK_IF_CLEAR_MEM(mem); 1569 } 1570 1571 if (bp_conf->pvt_ptr == NULL) { 1572 alloc_sz = BPC_BNK_CNT(bp_conf); 1573 alloc_sz = sizeof(void *) * alloc_sz; 1574 ALPM_ALLOC_EG(bp_conf->pvt_ptr, alloc_sz, "pvt_ptr"); 1575 } 1576 } 1577 1578 /* Adjust bucket count based on scaling factor */ 1579 /* ALPM_IDX_BNK_SHIFT(acb) -= sf; */ 1580 1581 /* Per instance structure init */ 1582 alloc_sz = vrf_id_cnt * sizeof(_alpm_pvt_ctrl_t); 1583 for (j = 0; j < ALPM_IPT_CNT; j++) { 1584 ALPM_ALLOC_EG( 1585 acb->pvt_ctl[j], alloc_sz, "pvt_ctl"); 1586 } 1587 for (j = 0; j < ALPM_PKM_CNT; j++) { 1588 if (!SOC_WARM_BOOT(u)) { 1589 mem = alpm_tbl[acb->pvt_tbl[j]]; 1590 _CHK_IF_CLEAR_MEM(mem); 1591 } 1592 } 1593 1594 ACB(u, i) = acb; 1595 } 1596 1597 /* Obtain TCAM table skip (invalid or duplicated) per */ 1598 for (i = 0; i < ALPM_PKM_CNT; i++) { 1599 if (alpm_tbl[ACB_TOP(u)->pvt_tbl[i]] == INVALIDm) { 1600 ALPM_TCAM_TBL_SKIP(u, i) = TRUE; /* invalid */ 1601 continue; 1602 } else { 1603 ALPM_TCAM_TBL_SKIP(u, i) = FALSE; 1604 } 1605 1606 for (j = 0; j < i; j++) { 1607 if (alpm_tbl[ACB_TOP(u)->pvt_tbl[i]] == 1608 alpm_tbl[ACB_TOP(u)->pvt_tbl[j]]) { 1609 ALPM_TCAM_TBL_SKIP(u, j) = TRUE; /* duplicated */ 1610 break; 1611 } 1612 } 1613 } 1614 1615 ALPM_TCAM_HB_IS_PTR(u) = TRUE; 1616 1617 ACB_CNT(u) = acb_cnt; 1618 1619 if (!SOC_WARM_BOOT(u)) { 1620 rv = th_alpm_hw_init(u); 1621 } 1622 1623 return rv; 1624 1625 bad: 1626 th_alpm_ctrl_deinit(u); 1627 return rv; 1628 } 1629 1630 /* ALPM ctrl cleanup (UNAVAIL for faster delete_all) */ 1631 int 1632 th_alpm_ctrl_cleanup(int u) 1633 { 1634 return BCM_E_UNAVAIL; 1635 } 1636 1637 /* L3_DEFIP_ALPM_ROUTE_BANK_FMT1fmt 1638 * -> ENTRY0f: L3_DEFIP_ALPM_ROUTE_FMT1fmt 1639 * -> PREFIXf 1640 * -> ASSOC_DATAf: ASSOC_DATA_REDUCEDfmt 1641 * -> DEST_TYPEf 1642 * -> DESTINATIONf 1643 * 1644 * -> ASSOC_DATAf: ASSOC_DATA_FULLfmt 1645 * -> DEST_TYPEf 1646 * -> DESTINATIONf 1647 * -> PRIf 1648 * -> RPEf 1649 * -> DST_DISCARDf 1650 * -> CLASS_IDf 1651 * -> FLEX_CTR_POOL_NUMBERf 1652 * -> FLEX_CTR_OFFSET_MODEf 1653 * -> FLEX_CTR_BASE_COUNTER_IDXf 1654 */ 1655 1656 static int8 1657 th_alpm_bnk_fmt_get(int u, _alpm_cb_t *acb, 1658 _alpm_bkt_info_t *bkt_info, int ent_idx) 1659 { 1660 int bnk_idx; 1661 1662 bnk_idx = ALPM_IDX_TO_BNK(acb, ent_idx); 1663 return bkt_info->bnk_fmt[bnk_idx]; 1664 } 1665 1666 static void 1667 th_alpm_ent_assemble(int u, _alpm_cb_t *acb, 1668 _alpm_pvt_node_t *pvt_node, int ent_idx, 1669 _bcm_defip_cfg_t *lpm_cfg, uint32 *entry) 1670 { 1671 int vrf_id, ipt; 1672 int rmode, offset; 1673 int8 fmt_tp; 1674 1675 uint32 key[5] = {0}; 1676 uint32 fent[ALPM_ENT_WORDS_MAX] = {0}; 1677 soc_format_t ent_fmt, bnk_fmt; 1678 1679 vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg); 1680 ipt = ALPM_LPM_IPT(u, lpm_cfg); 1681 fmt_tp = th_alpm_bnk_fmt_get(u, acb, &PVT_BKT_INFO(pvt_node), ent_idx); 1682 ent_fmt = ACB_FMT_ENT(acb, vrf_id, fmt_tp); 1683 1684 #define _FMT32_SET(field, value) \ 1685 soc_format_field32_set(u, ent_fmt, fent, (field), (value)) 1686 1687 _FMT32_SET(VALIDf, 1); 1688 /* TD3TBD */ 1689 _FMT32_SET(SUB_BKT_PTRf, 0); 1690 /* Associated-Data */ 1691 if (soc_feature(u, soc_feature_generic_dest)) { 1692 soc_format_t dst_fmt = DESTINATION_FORMATfmt; 1693 uint32 dst_fmt_val = 0; 1694 if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) { 1695 soc_format_field32_set(u, dst_fmt, &dst_fmt_val, DEST_TYPE1f, 1); 1696 soc_format_field32_set(u, dst_fmt, &dst_fmt_val, ECMP_GROUPf, 1697 lpm_cfg->defip_ecmp_index); 1698 } else if (!(lpm_cfg->defip_flags & BCM_L3_IPMC)) { 1699 soc_format_field32_set(u, dst_fmt, &dst_fmt_val, DEST_TYPE0f, 3); 1700 soc_format_field32_set(u, dst_fmt, &dst_fmt_val, NEXT_HOP_INDEXf, 1701 lpm_cfg->defip_ecmp_index); 1702 } 1703 _FMT32_SET(DESTINATIONf, dst_fmt_val); 1704 } else { 1705 if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) { 1706 _FMT32_SET(ECMPf, 1); 1707 _FMT32_SET(ECMP_PTRf, lpm_cfg->defip_ecmp_index); 1708 } else if (!(lpm_cfg->defip_flags & BCM_L3_IPMC)) { 1709 _FMT32_SET(NEXT_HOP_INDEXf, lpm_cfg->defip_ecmp_index); 1710 } 1711 } 1712 _FMT32_SET(PRIf, lpm_cfg->defip_prio); 1713 _FMT32_SET(RPEf, lpm_cfg->defip_flags & BCM_L3_RPE ? 1 : 0); 1714 _FMT32_SET(DST_DISCARDf, lpm_cfg->defip_flags & BCM_L3_DST_DISCARD ? 1 : 0); 1715 _FMT32_SET(CLASS_IDf, lpm_cfg->defip_lookup_class); 1716 _FMT32_SET(SUB_BKT_PTRf, PVT_SUB_BKT_IDX(pvt_node)); 1717 1718 /* Flex Counter */ 1719 rmode = ACB_VRF_DB_TYPE(u, acb, vrf_id, ipt); 1720 if (rmode) { 1721 _FMT32_SET(FLEX_CTR_POOL_NUMBERf, lpm_cfg->defip_flex_ctr_pool); 1722 _FMT32_SET(FLEX_CTR_OFFSET_MODEf, lpm_cfg->defip_flex_ctr_mode); 1723 _FMT32_SET(FLEX_CTR_BASE_COUNTER_IDXf, lpm_cfg->defip_flex_ctr_base_id); 1724 } 1725 1726 /* Key & Length */ 1727 /* 1728 * 128B: 1729 * ip6[0] ---- ip6[15] 1730 * ffff:ffff:0000:0000:0000:0000:0000:0000 1731 * prefix[7] prefix[6] prefix[5] prefix[4] ... prefix[0] 1732 * 64B: 1733 * ip6[0] ---- ip6[7] 1734 * ffff:ffff:0000:0000 1735 * prefix[7] prefix[6] prefix[5] prefix[4] ... prefix[0] 1736 * 32B: 1737 * ip_addr 1738 * c0a80101 1739 * prefix[7] prefix[6] prefix[5] prefix[4] ... prefix[0] 1740 */ 1741 alpm_util_cfg_to_key(u, ipt, lpm_cfg, key); 1742 if (ALPM_IS_IPV6(ipt)) { 1743 if (fmt_tp == ALPM_FMT_PKM_64B || fmt_tp == ALPM_FMT_PKM_FLEX_64B) { 1744 key[0] = key[2]; 1745 key[1] = key[3]; 1746 key[2] = key[3] = 0; 1747 } 1748 } 1749 1750 soc_format_field_set(u, ent_fmt, fent, KEYf, key); 1751 _FMT32_SET(LENGTHf, lpm_cfg->defip_sub_len); 1752 1753 offset = ALPM_IDX_TO_ENT(ent_idx); 1754 bnk_fmt = ACB_FMT_BNK(acb, vrf_id, fmt_tp); 1755 soc_format_field_set(u, bnk_fmt, entry, th_alpm_ent_fld[offset], fent); 1756 1757 #undef _FMT32_SET 1758 1759 return ; 1760 1761 } 1762 1763 int 1764 th_alpm_ent_pfx_len_get(int u, _alpm_cb_t *acb, 1765 _alpm_pvt_node_t *pvt_node, int ent_idx) 1766 { 1767 int rv; 1768 int ent_id, pfx_len = -1; 1769 int8 fmt_tp; 1770 uint32 bnkb[17]; 1771 uint32 entb[17] = {0}; 1772 soc_format_t bnk_fmt, ent_fmt; 1773 _alpm_bkt_pool_conf_t *bp_conf; 1774 1775 bp_conf = ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node)); 1776 /* Get Bank data: bnkb */ 1777 rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf), 1778 ALPM_TAB_IDX_GET(ent_idx), bnkb, FALSE); 1779 if (BCM_SUCCESS(rv)) { 1780 fmt_tp = th_alpm_bnk_fmt_get(u, acb, &PVT_BKT_INFO(pvt_node), ent_idx); 1781 bnk_fmt = BPC_FMT_BNK(bp_conf, fmt_tp); 1782 ent_id = ALPM_IDX_TO_ENT(ent_idx); 1783 1784 /* Get Entry data: entb */ 1785 (void)soc_format_field_get(u, bnk_fmt, bnkb, 1786 th_alpm_ent_fld[ent_id], entb); 1787 /* Get PREFIXf Field data: tmpf */ 1788 ent_fmt = BPC_FMT_ENT(bp_conf, fmt_tp); 1789 pfx_len = soc_format_field32_get(u, ent_fmt, entb, LENGTHf); 1790 } 1791 1792 return pfx_len; 1793 } 1794 1795 void 1796 th_alpm_ent_copy(int u, int vrf_id, _alpm_cb_t *acb, uint32 *sb_ent, uint32 *db_ent, 1797 _alpm_bkt_info_t *sbinfo, _alpm_bkt_info_t *dbinfo, 1798 uint32 src_pvt_len, uint32 dst_pvt_len, 1799 uint32 src_idx, uint32 dst_idx) 1800 { 1801 int8 src_fid, dst_fid; 1802 uint32 src_eid, dst_eid; 1803 uint32 se_ent[17] = {0}; 1804 uint32 de_ent[17] = {0}; 1805 1806 soc_format_t sb_fmt, db_fmt; 1807 1808 /* Retrieve src entry */ 1809 src_fid = th_alpm_bnk_fmt_get(u, acb, sbinfo, src_idx); 1810 src_eid = ALPM_IDX_TO_ENT(src_idx); 1811 sb_fmt = ACB_FMT_BNK(acb, vrf_id, src_fid); 1812 soc_format_field_get(u, sb_fmt, sb_ent, th_alpm_ent_fld[src_eid], se_ent); 1813 1814 dst_fid = th_alpm_bnk_fmt_get(u, acb, dbinfo, dst_idx); 1815 dst_eid = ALPM_IDX_TO_ENT(dst_idx); 1816 db_fmt = ACB_FMT_BNK(acb, vrf_id, dst_fid); 1817 1818 /* Copy entry */ 1819 if (sb_fmt != db_fmt) { 1820 assert(0); 1821 } else { 1822 sal_memcpy(de_ent, se_ent, sizeof(de_ent)); 1823 if (BI_SUB_BKT_IDX(sbinfo) != BI_SUB_BKT_IDX(dbinfo)) { 1824 soc_format_field32_set(u, ACB_FMT_ENT(acb, vrf_id, dst_fid), de_ent, 1825 SUB_BKT_PTRf, BI_SUB_BKT_IDX(dbinfo)); 1826 } 1827 } 1828 1829 /* Write entry back to bank */ 1830 soc_format_field_set(u, db_fmt, db_ent, th_alpm_ent_fld[dst_eid], de_ent); 1831 1832 return ; 1833 } 1834 1835 int 1836 th_alpm_bkt_bnk_write(int u, _alpm_cb_t *acb, 1837 _alpm_pvt_node_t *pvt_node, 1838 _bcm_defip_cfg_t *lpm_cfg, int ent_idx, uint32 write_flags) 1839 { 1840 int rv, index; 1841 uint32 entry[ALPM_ENT_WORDS_MAX] = {0}; 1842 _alpm_bkt_pool_conf_t *bp_conf = ACB_BKT_VRF_POOL(acb, PVT_BKT_VRF(pvt_node)); 1843 1844 index = ALPM_TAB_IDX_GET(ent_idx); 1845 1846 rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf), index, entry, FALSE); 1847 if (BCM_SUCCESS(rv)) { 1848 th_alpm_ent_assemble(u, acb, pvt_node, ent_idx, lpm_cfg, entry); 1849 rv = th_mem_write(u, acb, pvt_node, BPC_BKT_TBL(bp_conf), index, entry); 1850 } 1851 1852 return rv; 1853 } 1854 1855 static int 1856 th_alpm_bkt_bnk_shrink(int u, _alpm_cb_t *acb, 1857 _alpm_pvt_node_t *pvt_node, uint8 sbnk, 1858 uint8 dbnk, _alpm_bkt_pfx_arr_t *pfx_arr) 1859 { 1860 int i, j, k, rv = 0; 1861 int sepb, depb; 1862 int vrf_id; 1863 int8 src_fid, dst_fid; 1864 1865 soc_format_t sb_fmt, db_fmt; 1866 1867 uint32 tmp_idx, stab_idx, dtab_idx; 1868 _alpm_bkt_info_t *bkt_info = NULL; 1869 1870 uint32 srcbnke[17]; 1871 uint32 nullent[17]; 1872 uint32 dstbnke[17]; 1873 uint32 tempent[17]; 1874 1875 /* Bulk Write */ 1876 int bulk_idx[2]; 1877 uint32 *bulk_ent[2]; 1878 1879 _alpm_bkt_pool_conf_t *bp_conf; 1880 1881 vrf_id = PVT_BKT_VRF(pvt_node); 1882 bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id); 1883 1884 bkt_info = &PVT_BKT_INFO(pvt_node); 1885 src_fid = bkt_info->bnk_fmt[sbnk]; 1886 dst_fid = bkt_info->bnk_fmt[dbnk]; 1887 sepb = ACB_FMT_ENT_MAX(acb, vrf_id, src_fid); 1888 depb = ACB_FMT_ENT_MAX(acb, vrf_id, dst_fid); 1889 1890 if (bkt_info->vet_bmp[dbnk] == 0) { 1891 /* Move from entire from_bnk to to_bnk */ 1892 stab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, sbnk); 1893 dtab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, dbnk); 1894 1895 rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf), 1896 stab_idx, srcbnke, FALSE); 1897 ALPM_IER(rv); 1898 1899 bulk_idx[0] = dtab_idx; 1900 bulk_idx[1] = stab_idx; 1901 bulk_ent[0] = srcbnke; 1902 bulk_ent[1] = nullent; 1903 1904 sal_memset(nullent, 0, sizeof(nullent)); 1905 rv = th_mem_bulk_write(u, acb, pvt_node, BPC_BKT_TBL(bp_conf), 1906 bulk_idx, bulk_ent, 2); 1907 ALPM_IER(rv); 1908 1909 sal_memset(srcbnke, 0, sizeof(srcbnke)); 1910 /* Invalidate bank from */ 1911 rv = th_mem_write(u, acb, pvt_node, BPC_BKT_TBL(bp_conf), 1912 stab_idx, srcbnke); 1913 ALPM_IER(rv); 1914 1915 bkt_info->vet_bmp[dbnk] = bkt_info->vet_bmp[sbnk]; 1916 bkt_info->vet_bmp[sbnk] = 0; 1917 bkt_info->bnk_fmt[dbnk] = src_fid; 1918 1919 /* Update ent_idx of prefix */ 1920 for (i = 0; i < pfx_arr->pfx_cnt; i++) { 1921 tmp_idx = pfx_arr->pfx[i]->ent_idx; 1922 if (ALPM_IDX_TO_BNK(acb, tmp_idx) == sbnk) { 1923 pfx_arr->pfx[i]->ent_idx = 1924 ALPM_IDX_MAKE(acb, bkt_info, dbnk, 1925 ALPM_IDX_TO_ENT(tmp_idx)); 1926 } 1927 } 1928 1929 ALPM_INFO(("**ACB(%d).BNK.MRG: RBBE from(%d %d %d *) to(%d %d %d *)\n", 1930 ACB_IDX(acb), 1931 PVT_ROFS(pvt_node), 1932 PVT_BKT_IDX(pvt_node), sbnk, 1933 PVT_ROFS(pvt_node), 1934 PVT_BKT_IDX(pvt_node), dbnk)); 1935 1936 return rv; 1937 } 1938 1939 /* Merge */ 1940 stab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, sbnk); 1941 rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf), 1942 stab_idx, srcbnke, FALSE); 1943 ALPM_IER(rv); 1944 dtab_idx = ALPM_TAB_IDX_GET_BI_BNK(acb, bkt_info, dbnk); 1945 rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf), 1946 dtab_idx, dstbnke, FALSE); 1947 ALPM_IER(rv); 1948 1949 sb_fmt = ACB_FMT_BNK(acb, vrf_id, src_fid); 1950 db_fmt = ACB_FMT_BNK(acb, vrf_id, dst_fid); 1951 for (i = 0; i < depb; i++) { 1952 /* to entry i */ 1953 if (bkt_info->vet_bmp[dbnk] & (1 << i)) { 1954 continue; 1955 } 1956 for (j = 0; j < sepb; j++) { 1957 if (!(bkt_info->vet_bmp[sbnk] & (1 << j))) { 1958 continue; 1959 } 1960 /* from entry j */ 1961 if (sb_fmt != db_fmt) { 1962 uint32 src_idx, dst_idx; 1963 src_idx = ALPM_IDX_MAKE(acb, bkt_info, sbnk, j); 1964 dst_idx = ALPM_IDX_MAKE(acb, bkt_info, dbnk, i); 1965 th_alpm_ent_copy(u, vrf_id, acb, srcbnke, dstbnke, 1966 &PVT_BKT_INFO(pvt_node), 1967 &PVT_BKT_INFO(pvt_node), 1968 PVT_KEY_LEN(pvt_node), 1969 PVT_KEY_LEN(pvt_node), 1970 src_idx, dst_idx); 1971 } else { 1972 sal_memset(tempent, 0, sizeof(tempent)); 1973 (void)soc_format_field_get(u, sb_fmt, srcbnke, 1974 th_alpm_ent_fld[j], tempent); 1975 (void)soc_format_field_set(u, db_fmt, dstbnke, 1976 th_alpm_ent_fld[i], tempent); 1977 } 1978 /* Invalidate entry j */ 1979 sal_memset(nullent, 0, sizeof(nullent)); 1980 (void)soc_format_field_set(u, sb_fmt, srcbnke, 1981 th_alpm_ent_fld[j], nullent); 1982 1983 bkt_info->vet_bmp[sbnk] &= ~(1 << j); 1984 bkt_info->vet_bmp[dbnk] |= (1 << i); 1985 1986 ALPM_INFO(( 1987 "**ACB(%d).BNK.MRG: RBBE from(%d %d %d %d) to(%d %d %d %d)\n", 1988 ACB_IDX(acb), 1989 PVT_ROFS(pvt_node), PVT_BKT_IDX(pvt_node), sbnk, j, 1990 PVT_ROFS(pvt_node), PVT_BKT_IDX(pvt_node), dbnk, i)); 1991 1992 /* Update ent_idx of prefix */ 1993 for (k = 0; k < pfx_arr->pfx_cnt; k++) { 1994 tmp_idx = pfx_arr->pfx[k]->ent_idx; 1995 if (ALPM_IDX_TO_BNK(acb, tmp_idx) == sbnk && 1996 ALPM_IDX_TO_ENT(tmp_idx) == j) { 1997 pfx_arr->pfx[k]->ent_idx = 1998 ALPM_IDX_MAKE(acb, bkt_info, dbnk, i); 1999 } 2000 } 2001 break; 2002 } 2003 } 2004 2005 bulk_idx[0] = dtab_idx; 2006 bulk_idx[1] = stab_idx; 2007 bulk_ent[0] = dstbnke; 2008 bulk_ent[1] = srcbnke; 2009 rv = th_mem_bulk_write(u, acb, pvt_node, BPC_BKT_TBL(bp_conf), 2010 bulk_idx, bulk_ent, 2); 2011 return rv; 2012 } 2013 2014 int 2015 th_alpm_bkt_pfx_copy(int u, _alpm_cb_t *acb, 2016 _alpm_bkt_pfx_arr_t *pfx_arr, 2017 _alpm_pvt_node_t *opvt_node, 2018 _alpm_pvt_node_t *npvt_node) 2019 { 2020 int i, rv = BCM_E_NONE; 2021 int vrf_id; 2022 uint32 src_idx, dst_idx = 0; 2023 uint8 def_fmt; 2024 uint16 sb_cnt[ALPM_BPB_MAX] = {0}; 2025 uint16 db_cnt[ALPM_BPB_MAX] = {0}; 2026 uint32 srcbnke[ALPM_BPB_MAX][17]; 2027 uint32 dstbnke[ALPM_BPB_MAX][17]; 2028 2029 int bulk_idx[ALPM_BPB_MAX]; 2030 uint32 *bulk_ent[ALPM_BPB_MAX]; 2031 int bulk_ent_cnt = 0; 2032 2033 _alpm_bkt_info_t *src_bkt, *dst_bkt; 2034 _alpm_bkt_pool_conf_t *bp_conf; 2035 2036 src_bkt = &PVT_BKT_INFO(opvt_node); 2037 dst_bkt = &PVT_BKT_INFO(npvt_node); 2038 vrf_id = PVT_BKT_VRF(opvt_node); 2039 bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id); 2040 2041 for (i = 0; i < pfx_arr->pfx_cnt; i++) { 2042 sb_cnt[ALPM_IDX_TO_BNK(acb, pfx_arr->pfx[i]->ent_idx)]++; 2043 } 2044 2045 for (i = 0; i < ALPM_BPB_MAX; i++) { 2046 if (sb_cnt[i] == 0) { 2047 continue; 2048 } 2049 rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf), 2050 ALPM_TAB_IDX_GET_BI_BNK(acb, src_bkt, i), 2051 srcbnke[i], FALSE); 2052 ALPM_IER(rv); 2053 } 2054 2055 def_fmt = alpm_util_bkt_def_fmt_get(u, acb, vrf_id, PVT_BKT_IPT(opvt_node)); 2056 sal_memset(dstbnke, 0, sizeof(dstbnke)); 2057 for (i = 0; i < pfx_arr->pfx_cnt; i++) { 2058 int dst_bnk; 2059 int offset = ACB_BKT_FIXED_FMT(acb, 1) ? 0 : PVT_KEY_LEN(npvt_node); 2060 src_idx = pfx_arr->pfx[i]->ent_idx; 2061 rv = alpm_bkt_ent_get_attempt(u, acb, 2062 ACB_BKT_VRF_POOL(acb, vrf_id), 2063 dst_bkt, def_fmt, pfx_arr->pfx[i]->key_len - offset, 2064 &dst_idx, NULL, 0); 2065 /* We should not see a FULL here */ 2066 ALPM_IER(rv); 2067 2068 dst_bnk = ALPM_IDX_TO_BNK(acb, dst_idx); 2069 if (db_cnt[dst_bnk] == 0 && npvt_node->bkt_info.vet_bmp[dst_bnk] != 0) { 2070 rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf), 2071 ALPM_TAB_IDX_GET_BI_BNK(acb, dst_bkt, dst_bnk), 2072 dstbnke[dst_bnk], FALSE); 2073 ALPM_IER(rv); 2074 } 2075 th_alpm_ent_copy(u, vrf_id, acb, 2076 srcbnke[ALPM_IDX_TO_BNK(acb, src_idx)], 2077 dstbnke[dst_bnk], 2078 src_bkt, dst_bkt, 2079 PVT_KEY_LEN(opvt_node), 2080 PVT_KEY_LEN(npvt_node), 2081 src_idx, dst_idx); 2082 2083 db_cnt[dst_bnk]++; 2084 pfx_arr->pfx[i]->ent_idx = dst_idx; 2085 if (!ALPM_HIT_SKIP(u)) { 2086 _alpm_tbl_t tbl = alpmTblInvalid; 2087 ALPM_HIT_LOCK(u); 2088 tbl = ACB_BKT_TBL(acb, vrf_id); 2089 th_alpm_ent_hit_move(u, vrf_id, acb, tbl, src_idx, dst_idx); 2090 ALPM_HIT_UNLOCK(u); 2091 } 2092 } 2093 2094 for (i = 0; i < ALPM_BPB_MAX; i++) { 2095 if (db_cnt[i] == 0) { 2096 continue; 2097 } 2098 2099 bulk_idx[bulk_ent_cnt] = ALPM_TAB_IDX_GET_BI_BNK(acb, dst_bkt, i); 2100 bulk_ent[bulk_ent_cnt] = dstbnke[i]; 2101 bulk_ent_cnt ++; 2102 } 2103 2104 rv = th_mem_bulk_write(u, acb, npvt_node, 2105 BPC_BKT_TBL(bp_conf), 2106 bulk_idx, bulk_ent, bulk_ent_cnt); 2107 2108 ALPM_IER(rv); 2109 2110 /* TD3ALPMTBD: rollback@err */ 2111 return rv; 2112 } 2113 2114 int 2115 th_alpm_bkt_pfx_clean(int u, _alpm_cb_t *acb, 2116 _alpm_pvt_node_t *pvt_node, 2117 int count, uint32 *ent_idx) 2118 { 2119 int i, rv = BCM_E_NONE; 2120 int vrf_id; 2121 uint32 src_idx, ent_id; 2122 2123 soc_format_t bnk_fmt; 2124 2125 uint16 srcbnk[ALPM_BPB_MAX] = {0}; 2126 uint32 srcbnke[ALPM_BPB_MAX][17]; 2127 /* Bulk write */ 2128 int bulk_idx[ALPM_BPB_MAX]; 2129 uint32 *bulk_ent[ALPM_BPB_MAX]; 2130 int bulk_ent_cnt = 0; 2131 2132 _alpm_bkt_pool_conf_t *bp_conf; 2133 vrf_id = PVT_BKT_VRF(pvt_node); 2134 bp_conf = ACB_BKT_VRF_POOL(acb, vrf_id); 2135 2136 for (i = 0; i < count; i++) { 2137 srcbnk[ALPM_IDX_TO_BNK(acb, ent_idx[i])]++; 2138 } 2139 2140 for (i = 0; i < ALPM_BPB_MAX; i++) { 2141 if (srcbnk[i] == 0) { 2142 continue; 2143 } 2144 rv = th_mem_read(u, acb, BPC_BKT_TBL(bp_conf), 2145 ALPM_TAB_IDX_GET_BI_BNK(acb, &PVT_BKT_INFO(pvt_node), i), 2146 srcbnke[i], FALSE); 2147 ALPM_IER(rv); 2148 } 2149 2150 /* Clear corresponding entry from bank */ 2151 for (i = 0; i < count; i++) { 2152 uint32 tmpe[17] = {0}; 2153 int8 fmt_tp; 2154 2155 src_idx = ent_idx[i]; 2156 fmt_tp = th_alpm_bnk_fmt_get(u, acb, &PVT_BKT_INFO(pvt_node), src_idx); 2157 bnk_fmt = ACB_FMT_BNK(acb, vrf_id, fmt_tp); 2158 ent_id = ALPM_IDX_TO_ENT(src_idx); 2159 (void)soc_format_field_set(u, bnk_fmt, 2160 srcbnke[ALPM_IDX_TO_BNK(acb, src_idx)], 2161 th_alpm_ent_fld[ent_id], tmpe); 2162 } 2163 2164 for (i = 0; i < ALPM_BPB_MAX; i++) { 2165 if (srcbnk[i] == 0) { 2166 continue; 2167 } 2168 2169 bulk_idx[bulk_ent_cnt] = 2170 ALPM_TAB_IDX_GET_BI_BNK(acb, &PVT_BKT_INFO(pvt_node), i); 2171 bulk_ent[bulk_ent_cnt] = srcbnke[i]; 2172 bulk_ent_cnt ++; 2173 } 2174 2175 rv = th_mem_bulk_write(u, acb, pvt_node, 2176 BPC_BKT_TBL(bp_conf), 2177 bulk_idx, bulk_ent, bulk_ent_cnt); 2178 2179 ALPM_IER(rv); 2180 2181 for (i = 0; i < count; i++) { 2182 uint32 bnk_idx; 2183 2184 src_idx = ent_idx[i]; 2185 bnk_idx = ALPM_IDX_TO_BNK(acb, src_idx); 2186 ent_id = ALPM_IDX_TO_ENT(src_idx); 2187 PVT_BKT_INFO(pvt_node).vet_bmp[bnk_idx] &= ~(1 << ent_id); 2188 if (!ALPM_HIT_SKIP(u)) { 2189 _alpm_tbl_t tbl = alpmTblInvalid; 2190 ALPM_HIT_LOCK(u); 2191 tbl = ACB_BKT_TBL(acb, vrf_id); 2192 th_alpm_bkt_hit_write(u, vrf_id, acb, tbl, src_idx, 0); 2193 ALPM_HIT_UNLOCK(u); 2194 } 2195 } 2196 2197 return rv; 2198 } 2199 2200 /* Only do defrag inside a bucket */ 2201 int 2202 th_alpm_bkt_pfx_shrink(int u, _alpm_cb_t *acb, 2203 _alpm_pvt_node_t *pvt_node, 2204 _alpm_bkt_pfx_arr_t *pfx_arr, 2205 int shrink_empty_only) 2206 { 2207 int tb, fb, tbnk, fbnk; 2208 int rv = BCM_E_NONE; 2209 int start, close, step; 2210 int bnkpb = ACB_BNK_PER_BKT(acb, PVT_BKT_VRF(pvt_node)); 2211 2212 _alpm_bkt_info_t *bkt_info = NULL; 2213 2214 bkt_info = &PVT_BKT_INFO(pvt_node); 2215 2216 if (!ACB_BKT_WRA(acb, PVT_BKT_VRF(pvt_node)) || 2217 PVT_BKT_IDX(pvt_node) & 1) { 2218 start = PVT_ROFS(pvt_node); 2219 close = PVT_ROFS(pvt_node) + bnkpb; 2220 step = 1; 2221 } else { 2222 start = PVT_ROFS(pvt_node) + bnkpb - 1; 2223 close = PVT_ROFS(pvt_node) - 1; 2224 step = -1; 2225 } 2226 2227 for (tb = start; ABS(tb-close) > 0; tb += step) { 2228 tbnk = tb % bnkpb; 2229 if (!BI_BNK_IS_USED(bkt_info, tbnk)) { 2230 continue; 2231 } 2232 for (fb = (close - step); ABS(fb-tb) > 0; fb -= step) { 2233 fbnk = fb % bnkpb; 2234 /* Bank fb empty */ 2235 if (!BI_BNK_IS_USED(bkt_info, fbnk) || 2236 bkt_info->vet_bmp[fbnk] == 0) { 2237 continue; 2238 } 2239 2240 /* Bank tb empty, Bank fb occupied */ 2241 if (bkt_info->vet_bmp[tbnk] == 0) { 2242 rv = th_alpm_bkt_bnk_shrink(u, acb, pvt_node, fbnk, tbnk, 2243 pfx_arr); 2244 ALPM_IER(rv); 2245 } else if (bkt_info->bnk_fmt[tbnk] >= bkt_info->bnk_fmt[fbnk]) { 2246 /* Bank tb & fb are same type and both occupied */ 2247 rv = th_alpm_bkt_bnk_shrink(u, acb, pvt_node, fbnk, 2248 tbnk, pfx_arr); 2249 ALPM_IER(rv); 2250 } 2251 } 2252 } 2253 2254 return rv; 2255 } 2256 2257 int 2258 th_alpm_bkt_bnk_copy(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, 2259 _alpm_bkt_info_t *src_bkt, _alpm_bkt_info_t *dst_bkt, 2260 int src_idx, int dst_idx) 2261 { 2262 int rv = BCM_E_NONE; 2263 int vrf_id = -1; 2264 uint32 ent[ALPM_ENT_WORDS_MAX] = {0}; 2265 2266 _alpm_tbl_t tbl = alpmTblInvalid; 2267 2268 if (pvt_node != NULL) { 2269 vrf_id = PVT_BKT_VRF(pvt_node); 2270 tbl = BPC_BKT_TBL(ACB_BKT_VRF_POOL(acb, vrf_id)); 2271 } 2272 2273 2274 if (tbl != alpmTblInvalid) { 2275 ALPM_IER(th_mem_read(u, acb, tbl, src_idx, ent, FALSE)); 2276 if (BI_SUB_BKT_IDX(src_bkt) != BI_SUB_BKT_IDX(dst_bkt)) { 2277 int eid, sbnk, dbnk, emax; 2278 sbnk = ALPM_IDX_TO_BNK(acb, src_idx); 2279 dbnk = ALPM_IDX_TO_BNK(acb, dst_idx); 2280 emax = ACB_FMT_ENT_MAX(acb, vrf_id, src_bkt->bnk_fmt[sbnk]); 2281 for (eid = 0; eid < emax; eid++) { 2282 if (!SHR_BITGET(&src_bkt->vet_bmp[sbnk], eid)) { 2283 continue; 2284 } 2285 2286 th_alpm_ent_copy(u, vrf_id, acb, ent, ent, src_bkt, dst_bkt, 0, 0, 2287 ALPM_IDX_MAKE(acb, src_bkt, sbnk, eid), 2288 ALPM_IDX_MAKE(acb, dst_bkt, dbnk, eid)); 2289 } 2290 } 2291 ALPM_IER(th_mem_write(u, acb, pvt_node, tbl, dst_idx, ent)); 2292 2293 if (!ALPM_HIT_SKIP(u)) { 2294 ALPM_HIT_LOCK(u); 2295 th_alpm_bnk_hit_move(u, vrf_id, 2296 acb, &PVT_BKT_INFO(pvt_node), 2297 tbl, 2298 src_idx, dst_idx); 2299 ALPM_HIT_UNLOCK(u); 2300 } 2301 } 2302 return rv; 2303 } 2304 2305 int 2306 th_alpm_bkt_bnk_clear(int u, _alpm_cb_t *acb, _alpm_pvt_node_t *pvt_node, 2307 int tab_idx) 2308 { 2309 int rv = BCM_E_NONE; 2310 _alpm_tbl_t tbl = alpmTblInvalid; 2311 2312 if (pvt_node != NULL) { 2313 tbl = ACB_BKT_TBL(acb, PVT_BKT_VRF(pvt_node)); 2314 ALPM_IER(th_mem_write(u, acb, pvt_node, tbl, tab_idx, NULL)); 2315 if (!ALPM_HIT_SKIP(u)) { 2316 th_alpm_bnk_hit_clear(u, PVT_BKT_VRF(pvt_node), acb, 2317 &PVT_BKT_INFO(pvt_node), tbl, tab_idx); 2318 } 2319 } 2320 2321 return rv; 2322 } 2323 2324 /* TCAM related functions */ 2325 int 2326 th_tcam_table_sz(int u, int pkm) 2327 { 2328 int sz = 0; 2329 soc_mem_t mem; 2330 mem = alpm_tbl[ACB_TOP(u)->pvt_tbl[pkm]]; 2331 2332 if (mem != INVALIDm) { 2333 sz = soc_mem_index_count(u, mem); 2334 2335 if (SOC_URPF_STATUS_GET(u)) { 2336 sz >>= 1; 2337 } 2338 } 2339 return sz; 2340 } 2341 2342 /* TCAM Hw table cleanup (UNAVAIL for fast delete_all) */ 2343 int 2344 th_tcam_hw_cleanup(int u) 2345 { 2346 return BCM_E_UNAVAIL; 2347 } 2348 2349 /* 2350 * x | y 2351 * -------------------- 2352 * 0 | 0 : entry0_to_0 2353 * 0 | 1 : entry0_to_1 2354 * 1 | 0 : entry1_to_0 2355 * 1 | 1 : entry1_to_1 2356 * src and dst can be same 2357 */ 2358 int 2359 th_tcam_entry_x_to_y(int u, int pkm, void *src, void *dst, 2360 int copy_hit, int x, int y) 2361 { 2362 int i; 2363 uint32 val[SOC_MAX_MEM_FIELD_WORDS] = {0}; 2364 soc_mem_t mem; 2365 _alpm_cb_t *acb = ACB_TOP(u); 2366 2367 #define _FLD_CNT 9 2368 soc_field_t fld[2][_FLD_CNT] = 2369 { 2370 { 2371 VALID0f, 2372 DATA_TYPE0f, 2373 ENTRY_VIEW0f, 2374 KEY0f, 2375 MASK0f, 2376 REPLACE_DATA0f, 2377 ALG_BKT_PTR0f, 2378 ALG_SUB_BKT_PTR0f, 2379 GLOBAL_HIGH0f 2380 }, 2381 { 2382 VALID1f, 2383 DATA_TYPE1f, 2384 ENTRY_VIEW1f, 2385 KEY1f, 2386 MASK1f, 2387 REPLACE_DATA1f, 2388 ALG_BKT_PTR1f, 2389 ALG_SUB_BKT_PTR1f, 2390 GLOBAL_HIGH1f 2391 } 2392 }; 2393 soc_field_t hit[2] = {HIT0f, HIT1f}; 2394 2395 mem = alpm_tbl[acb->pvt_tbl[pkm]]; 2396 for (i = 0; i < _FLD_CNT; i++) { 2397 soc_mem_field_get(u, mem, src, fld[x][i], val); 2398 soc_mem_field_set(u, mem, dst, fld[y][i], val); 2399 } 2400 2401 if (copy_hit) { 2402 soc_mem_field_get(u, mem, src, hit[x], val); 2403 soc_mem_field_set(u, mem, dst, hit[y], val); 2404 } 2405 2406 return BCM_E_NONE; 2407 } 2408 2409 /* db_type: flex, non-flex */ 2410 static int 2411 th_tcam_entry_view_get(int u, _alpm_bkt_info_t *bkt_info) 2412 { 2413 int i, entry_view; 2414 2415 for (i = 0; i < ALPM_BPB_MAX; i++) { 2416 if (bkt_info->bnk_fmt[i] != 0) { 2417 break; 2418 } 2419 } 2420 assert(i < ALPM_BPB_MAX); 2421 2422 switch (bkt_info->bnk_fmt[i]) { 2423 case ALPM_FMT_PKM_32B: 2424 entry_view = 4; 2425 break; 2426 case ALPM_FMT_PKM_FLEX_32B: 2427 entry_view = 3; 2428 break; 2429 case ALPM_FMT_PKM_64B: 2430 entry_view = 2; 2431 break; 2432 case ALPM_FMT_PKM_FLEX_64B: 2433 entry_view = 1; 2434 break; 2435 case ALPM_FMT_PKM_128: 2436 case ALPM_FMT_PKM_FLEX_128: 2437 entry_view = 0; 2438 break; 2439 default: 2440 entry_view = 4; 2441 break; 2442 } 2443 2444 return entry_view; 2445 } 2446 2447 /* 2448 * field mapping: 2449 * 2450 * defip_flags 2451 * BCM_L3_HIT -> HIT0f 2452 * BCM_L3_RPE -> ASSOC_DATA0 -> RPE 2453 * BCM_L3_MULTIPATH -> ASSOC_DATA0 -> DEST_TYPE 2454 * BCM_L3_DST_DISCARD -> ASSOC_DATA0 -> DST_DISCARD 2455 * BCM_L3_IP6 -> KEY0 -> KEY_MODE 2456 * -> KEY0 -> KEY_TYPE 2457 * defip_prio -> ASSOC_DATA0 -> PRI 2458 * defip_ecmp_index -> ASSOC_DATA0 -> DESTINATION 2459 * defip_lookup_class -> ASSOC_DATA0 -> CLASS_ID 2460 * defip_vrf 2461 * BCM_L3_VRF_GLOBAL -> ALPM1_DATA -> DIRECT_ROUTE 2462 * -> FIXED_DATA0 -> SUB_DB_PRIORITY 2463 * 2464 * BCM_L3_VRF_OVERRIDE -> ALPM1_DATA -> DIRECT_ROUTE 2465 * -> FIXED_DATA0 -> SUB_DB_PRIORITY 2466 * 2467 * other -> KEY0 -> VRF_ID 2468 * -> MASK0 -> VRF_ID 2469 * -> FIXED_DATA0 -> SUB_DB_PRIORITY 2470 * 2471 * defip_sub_len -> MASK0 -> IP_ADDR 2472 * defip_ip_addr -> KEY0 -> IP_ADDR 2473 * defip_ip6_addr -> KEY0 -> IP_ADDR 2474 * 2475 * defip_flex_ctr_base_id -> ASSOC_DATA0 -> FLEX_CTR_BASE_COUNTER_IDX 2476 * defip_flex_ctr_mode -> ASSOC_DATA0 -> FLEX_CTR_OFFSET_MODE 2477 * defip_flex_ctr_pool -> ASSOC_DATA0 -> FLEX_CTR_POOL_NUMBER 2478 */ 2479 int 2480 th_tcam_entry_from_cfg(int unit, int pkm, _bcm_defip_cfg_t *lpm_cfg, void *e, int x, uint32 write_flags) 2481 { 2482 int i, f, cnt = 1; 2483 int ipt; 2484 uint32 key[4] = {0}; 2485 uint32 msk[4] = {0}; 2486 uint32 val; 2487 2488 soc_mem_t mem; 2489 _alpm_cb_t *acb = ACB_TOP(unit); 2490 _alpm_pvt_node_t *pvt_node; 2491 _alpm_bkt_node_t *bkt_node; 2492 2493 /* Associated-Data */ 2494 soc_field_t fld_hit[] = {HIT0f, HIT1f, HITf}; 2495 soc_field_t fld_class_id[] = {CLASS_ID0f, CLASS_ID1f, CLASS_IDf}; 2496 soc_field_t fld_dst_disc[] = {DST_DISCARD0f, DST_DISCARD1f, DST_DISCARDf}; 2497 soc_field_t fld_pri[] = {PRI0f, PRI1f, PRIf}; 2498 soc_field_t fld_dest[] = {DESTINATION0f, DESTINATION1f, DESTINATIONf}; 2499 soc_field_t fld_hit_idx[] = {ALG_HIT_IDX0f, ALG_HIT_IDX1f, ALG_HIT_IDXf}; 2500 soc_field_t fld_glb_hi[] = {GLOBAL_HIGH0f, GLOBAL_HIGH1f, GLOBAL_HIGHf}; 2501 soc_field_t fld_glb_rt[] = {GLOBAL_ROUTE0f, GLOBAL_ROUTE1f, GLOBAL_ROUTEf}; 2502 soc_field_t fld_df_ms[] = {DEFAULT_MISS0f, DEFAULT_MISS1f, DEFAULT_MISSf}; 2503 soc_field_t fld_rpe[] = {RPE0f, RPE1f, RPEf}; 2504 soc_field_t fld_dt[] = {DATA_TYPE0f, DATA_TYPE1f, DATA_TYPEf}; 2505 2506 /* Flex Counter */ 2507 soc_field_t fld_fc_bci[] = { 2508 FLEX_CTR_BASE_COUNTER_IDX0f, 2509 FLEX_CTR_BASE_COUNTER_IDX1f, 2510 FLEX_CTR_BASE_COUNTER_IDXf 2511 }; 2512 soc_field_t fld_fc_om[] = { 2513 FLEX_CTR_OFFSET_MODE0f, 2514 FLEX_CTR_OFFSET_MODE1f, 2515 FLEX_CTR_OFFSET_MODEf 2516 }; 2517 soc_field_t fld_fc_pn[] = { 2518 FLEX_CTR_POOL_NUMBER0f, 2519 FLEX_CTR_POOL_NUMBER1f, 2520 FLEX_CTR_POOL_NUMBERf 2521 }; 2522 2523 /* IPMC */ 2524 soc_field_t fld_mc_cpu[] = { 2525 IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU0f, 2526 IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPU1f, 2527 IPMC_EXPECTED_L3_IIF_MISMATCH_TOCPUf 2528 }; 2529 soc_field_t fld_mc_drop[] = { 2530 IPMC_EXPECTED_L3_IIF_MISMATCH_DROP0f, 2531 IPMC_EXPECTED_L3_IIF_MISMATCH_DROP1f, 2532 IPMC_EXPECTED_L3_IIF_MISMATCH_DROPf 2533 }; 2534 soc_field_t fld_mc_iif[] = 2535 {EXPECTED_L3_IIF0f, EXPECTED_L3_IIF1f, EXPECTED_L3_IIFf}; 2536 2537 /* VALID */ 2538 soc_field_t fld_vld[] = {VALID0f, VALID1f, VALID_LWRf}; 2539 2540 /* ALPM_DATA */ 2541 soc_field_t fld_bkt[] = {ALG_BKT_PTR0f, ALG_BKT_PTR1f, ALG_BKT_PTRf}; 2542 soc_field_t fld_sbkt[] = 2543 {ALG_SUB_BKT_PTR0f, ALG_SUB_BKT_PTR1f, ALG_SUB_BKT_PTRf}; 2544 2545 soc_field_t fld_ent_vw[] = {ENTRY_VIEW0f, ENTRY_VIEW1f, ENTRY_VIEWf}; 2546 2547 /* Key & Mask */ 2548 soc_field_t fld_key_ip[] = 2549 {IP_ADDR0f, IP_ADDR1f, IP_ADDR0_UPRf, IP_ADDR1_UPRf}; 2550 soc_field_t fld_key_vf[] = 2551 {VRF_ID_0f, VRF_ID_1f, VRF_ID_0_UPRf, VRF_ID_1_UPRf}; 2552 soc_field_t fld_key_kt[] = 2553 {KEY_TYPE0f, KEY_TYPE1f, KEY_TYPE0_UPRf, KEY_TYPE1_UPRf}; 2554 soc_field_t fld_key_km[] = 2555 {KEY_MODE0f, KEY_MODE1f, KEY_MODE0_UPRf, KEY_MODE1_UPRf}; 2556 soc_field_t fld_msk_ip[] = 2557 {IP_ADDR_MASK0f, IP_ADDR_MASK1f, IP_ADDR_MASK0_UPRf, IP_ADDR_MASK1_UPRf}; 2558 soc_field_t fld_msk_vf[] = 2559 {VRF_ID_MASK0f, VRF_ID_MASK1f, VRF_ID_MASK0_UPRf, VRF_ID_MASK1_UPRf}; 2560 soc_field_t fld_msk_kt[] = 2561 {KEY_TYPE_MASK0f, KEY_TYPE_MASK1f, KEY_TYPE_MASK0_UPRf, KEY_TYPE_MASK1_UPRf}; 2562 soc_field_t fld_msk_km[] = 2563 {KEY_MODE_MASK0f, KEY_MODE_MASK1f, KEY_MODE_MASK0_UPRf, KEY_MODE_MASK1_UPRf}; 2564 2565 int _ent_view = 0; 2566 2567 /* Starting here */ 2568 2569 mem = alpm_tbl[acb->pvt_tbl[pkm]]; 2570 if (SOC_MEM_FIELD_VALID(unit, mem, VALIDf)) { 2571 if (pkm == ALPM_PKM_32B) { 2572 f = !!x; 2573 fld_key_ip[!x] = fld_key_ip[!!x]; 2574 fld_key_vf[!x] = fld_key_vf[!!x]; 2575 fld_key_kt[!x] = fld_key_kt[!!x]; 2576 fld_key_km[!x] = fld_key_km[!!x]; 2577 fld_msk_ip[!x] = fld_msk_ip[!!x]; 2578 fld_msk_vf[!x] = fld_msk_vf[!!x]; 2579 fld_msk_kt[!x] = fld_msk_kt[!!x]; 2580 fld_msk_km[!x] = fld_msk_km[!!x]; 2581 } else { 2582 f = 0; 2583 cnt = 2; 2584 } 2585 } else if (SOC_MEM_FIELD_VALID(unit, mem, VALID_LWRf)) { 2586 fld_key_ip[0] = IP_ADDR0_LWRf; 2587 fld_key_ip[1] = IP_ADDR1_LWRf; 2588 fld_key_vf[0] = VRF_ID_0_LWRf; 2589 fld_key_vf[1] = VRF_ID_1_LWRf; 2590 fld_key_kt[0] = KEY_TYPE0_LWRf; 2591 fld_key_kt[1] = KEY_TYPE1_LWRf; 2592 fld_key_km[0] = KEY_MODE0_LWRf; 2593 fld_key_km[1] = KEY_MODE1_LWRf; 2594 fld_msk_ip[0] = IP_ADDR_MASK0_LWRf; 2595 fld_msk_ip[1] = IP_ADDR_MASK1_LWRf; 2596 fld_msk_vf[0] = VRF_ID_MASK0_LWRf; 2597 fld_msk_vf[1] = VRF_ID_MASK1_LWRf; 2598 fld_msk_kt[0] = KEY_TYPE_MASK0_LWRf; 2599 fld_msk_kt[1] = KEY_TYPE_MASK1_LWRf; 2600 fld_msk_km[0] = KEY_MODE_MASK0_LWRf; 2601 fld_msk_km[1] = KEY_MODE_MASK1_LWRf; 2602 f = 2; 2603 } else { 2604 f = 0; 2605 } 2606 2607 #define _MEM32_SET(field, value) \ 2608 soc_mem_field32_set(unit, mem, e, (field), (value)) 2609 2610 _conf: 2611 _MEM32_SET(fld_vld[f], 1); 2612 if (SOC_MEM_FIELD_VALID(unit, mem, VALID_LWRf)) { 2613 _MEM32_SET(VALID_LWRf, 3); 2614 _MEM32_SET(VALID_UPRf, 3); 2615 } 2616 /* HIT bits */ 2617 _MEM32_SET(fld_hit[f], !!(lpm_cfg->defip_flags & BCM_L3_HIT)); 2618 _MEM32_SET(fld_rpe[f], !!(lpm_cfg->defip_flags & BCM_L3_RPE)); 2619 _MEM32_SET(fld_dst_disc[f], !!(lpm_cfg->defip_flags & BCM_L3_DST_DISCARD)); 2620 _MEM32_SET(fld_pri[f], lpm_cfg->defip_prio); 2621 _MEM32_SET(fld_class_id[f], lpm_cfg->defip_lookup_class); 2622 _MEM32_SET(fld_fc_bci[f], lpm_cfg->defip_flex_ctr_base_id); 2623 _MEM32_SET(fld_fc_om[f], lpm_cfg->defip_flex_ctr_mode); 2624 _MEM32_SET(fld_fc_pn[f], lpm_cfg->defip_flex_ctr_pool); 2625 2626 if (soc_feature(unit, soc_feature_generic_dest)) { 2627 soc_format_t dst_fmt = DESTINATION_FORMATfmt; 2628 uint32 dst_fmt_val = 0; 2629 if (lpm_cfg->defip_flags & BCM_L3_MULTIPATH) { 2630 soc_format_field32_set(unit, dst_fmt, &dst_fmt_val, DEST_TYPE1f, 1); 2631 soc_format_field32_set(unit, dst_fmt, &dst_fmt_val, ECMP_GROUPf, 2632 lpm_cfg->defip_ecmp_index); 2633 } else if (!(lpm_cfg->defip_flags & BCM_L3_IPMC)) { 2634 soc_format_field32_set(unit, dst_fmt, &dst_fmt_val, DEST_TYPE0f, 3); 2635 soc_format_field32_set(unit, dst_fmt, &dst_fmt_val, NEXT_HOP_INDEXf, 2636 lpm_cfg->defip_ecmp_index); 2637 } 2638 _MEM32_SET(fld_dest[f], dst_fmt_val); 2639 } 2640 2641 _MEM32_SET(fld_glb_hi[f], lpm_cfg->defip_vrf == BCM_L3_VRF_OVERRIDE); 2642 _MEM32_SET(fld_glb_rt[f], lpm_cfg->defip_vrf == BCM_L3_VRF_OVERRIDE || 2643 lpm_cfg->defip_vrf == BCM_L3_VRF_GLOBAL); 2644 _MEM32_SET(fld_df_ms[f], ALPM_TCAM_ZONED(unit) && 2645 lpm_cfg->default_miss == 1); 2646 _MEM32_SET(fld_dt[f], 0); 2647 2648 pvt_node = (_alpm_pvt_node_t *)lpm_cfg->pvt_node; 2649 if (pvt_node != NULL) { 2650 _ent_view = th_tcam_entry_view_get(unit, &PVT_BKT_INFO(pvt_node)); 2651 _MEM32_SET(fld_ent_vw[f], _ent_view); 2652 2653 _MEM32_SET(fld_bkt[f], PVT_BKT_IDX(pvt_node) << ACB_BKT_DW(acb)); 2654 _MEM32_SET(fld_sbkt[f], PVT_SUB_BKT_IDX(pvt_node)); 2655 2656 bkt_node = PVT_BKT_DEF(pvt_node); 2657 if (bkt_node != NULL) { 2658 int ent, hw_idx = 0; 2659 hw_idx = bkt_node->ent_idx; 2660 ent = ALPM_IDX_TO_ENT(bkt_node->ent_idx); 2661 hw_idx = th_alpm_hit_tbl_idx_get(unit, acb, alpmTblBktCmodeL2, hw_idx, ent); 2662 _MEM32_SET(fld_hit_idx[f], hw_idx); 2663 } 2664 } 2665 2666 if (soc_feature(unit, soc_feature_ipmc_defip) && 2667 (lpm_cfg->defip_flags & BCM_L3_IPMC)) { 2668 _MEM32_SET(fld_dt[f], 2); 2669 if (lpm_cfg->defip_mc_group > 0 && 2670 soc_feature(unit, soc_feature_generic_dest)) { 2671 soc_format_t dst_fmt = DESTINATION_FORMATfmt; 2672 uint32 dst_fmt_val = 0; 2673 soc_format_field32_set(unit, dst_fmt, &dst_fmt_val, DEST_TYPE1f, 3); 2674 soc_format_field32_set(unit, dst_fmt, &dst_fmt_val, IPMC_GROUPf, 2675 lpm_cfg->defip_mc_group); 2676 _MEM32_SET(fld_dest[f], dst_fmt_val); 2677 } 2678 2679 if (lpm_cfg->defip_l3a_rp != BCM_IPMC_RP_ID_INVALID) { 2680 _MEM32_SET(fld_mc_iif[f], 2681 _BCM_DEFIP_IPMC_RP_SET(lpm_cfg->defip_l3a_rp)); 2682 } else if (lpm_cfg->defip_ipmc_flags & BCM_IPMC_POST_LOOKUP_RPF_CHECK && 2683 lpm_cfg->defip_expected_intf != 0) { 2684 _MEM32_SET(fld_mc_iif[f], lpm_cfg->defip_expected_intf); 2685 _MEM32_SET(fld_mc_drop[f], 2686 !!(lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_DROP)); 2687 _MEM32_SET(fld_mc_cpu[f], 2688 !!(lpm_cfg->defip_ipmc_flags & BCM_IPMC_RPF_FAIL_TOCPU)); 2689 } 2690 2691 } 2692 2693 if (--cnt > 0) { 2694 f = 1; 2695 goto _conf; 2696 } 2697 2698 /* Program KEY & MASK 2699 * 2700 * key[4] = {key[0], key[1], key[2], key[3]} 2701 * ipv4: key[4] = {IP_ADDR0f, 0, 0, 0} 2702 * ipv6-64: key[4] = {0, 0, IP_ADDR0f, IP_ADDR1f, } 2703 * ipv6-128: key[4] = {IP_ADDR0_LWRf, IP_ADDR1_LWRf, IP_ADDR0_UPRf, IP_ADDR1_UPRf} 2704 */ 2705 ipt = ALPM_PKM2IPT(pkm); 2706 alpm_util_cfg_to_key(unit, ipt, lpm_cfg, key); 2707 alpm_util_cfg_to_msk(unit, ipt, lpm_cfg, msk); 2708 if (SOC_MEM_FIELD_VALID(unit, mem, VALID_LWRf)) { 2709 cnt = 4; 2710 } else if (pkm == ALPM_PKM_64B) { 2711 key[1] = key[3]; 2712 key[0] = key[2]; 2713 msk[1] = msk[3]; 2714 msk[0] = msk[2]; 2715 cnt = 2; 2716 } else { 2717 cnt = 1; 2718 } 2719 2720 switch (pkm) { 2721 case ALPM_PKM_32B: 2722 val = 0; 2723 break; 2724 case ALPM_PKM_64B: 2725 val = 1; 2726 break; 2727 case ALPM_PKM_128: 2728 val = 3; 2729 break; 2730 default: 2731 val = 0; 2732 break; 2733 } 2734 2735 for (i = 0; i < cnt; i++) { 2736 /* KEY & mask */ 2737 _MEM32_SET(fld_key_km[i], val); 2738 _MEM32_SET(fld_msk_km[i], 0x3); 2739 _MEM32_SET(fld_key_kt[i], 0); 2740 _MEM32_SET(fld_msk_kt[i], 0xf); 2741 _MEM32_SET(fld_key_ip[i], key[i]); 2742 _MEM32_SET(fld_msk_ip[i], msk[i]); 2743 if (lpm_cfg->defip_vrf >= 0) { 2744 _MEM32_SET(fld_key_vf[i], lpm_cfg->defip_vrf); 2745 _MEM32_SET(fld_msk_vf[i], 0xfff); 2746 } 2747 } 2748 #undef _MEM32_SET 2749 2750 return BCM_E_NONE; 2751 } 2752 2753 int 2754 th_tcam_entry_to_cfg(int unit, int pkm, void *ent, int x, 2755 _bcm_defip_cfg_t *lpm_cfg) 2756 { 2757 soc_mem_t mem; 2758 _alpm_cb_t *acb = ACB_TOP(unit); 2759 2760 x = !!x; 2761 mem = alpm_tbl[acb->pvt_tbl[pkm]]; 2762 2763 lpm_cfg->defip_flags &= BCM_L3_IP6 | BCM_L3_IPMC; 2764 if (TH_ENT_HIT_GET(unit)) { 2765 lpm_cfg->defip_flags |= BCM_L3_HIT; 2766 } else { 2767 lpm_cfg->defip_flags &= ~BCM_L3_HIT; 2768 } 2769 2770 /* ASSOC_DATAf format */ 2771 if (TH_ENT_RPE_GET(unit)) { 2772 lpm_cfg->defip_flags |= BCM_L3_RPE; 2773 } else { 2774 lpm_cfg->defip_flags &= ~BCM_L3_RPE; 2775 } 2776 2777 if (soc_feature(unit, soc_feature_generic_dest)) { 2778 int ecmp = 0, ipmc = 0; 2779 TH_ENT_DEST_GET(unit, ecmp, ipmc, lpm_cfg->defip_ecmp_index); 2780 if (ecmp) { 2781 lpm_cfg->defip_flags |= BCM_L3_MULTIPATH; 2782 lpm_cfg->defip_ecmp = 1; 2783 } else { 2784 lpm_cfg->defip_flags &= ~BCM_L3_MULTIPATH; 2785 lpm_cfg->defip_ecmp = 0; 2786 lpm_cfg->defip_ecmp_count = 0; 2787 } 2788 if (ipmc) { 2789 lpm_cfg->defip_flags |= BCM_L3_IPMC; 2790 lpm_cfg->defip_mc_group = lpm_cfg->defip_ecmp_index; 2791 } else { 2792 lpm_cfg->defip_flags &= ~BCM_L3_IPMC; 2793 lpm_cfg->defip_mc_group = 0; 2794 } 2795 } 2796 2797 if (TH_ENT_DST_DISCARD_GET(unit)) { 2798 lpm_cfg->defip_flags |= BCM_L3_DST_DISCARD; 2799 } else { 2800 lpm_cfg->defip_flags &= ~BCM_L3_DST_DISCARD; 2801 } 2802 lpm_cfg->defip_prio = TH_ENT_PRI_GET(unit); 2803 lpm_cfg->defip_lookup_class = TH_ENT_CLASS_ID_GET(unit); 2804 lpm_cfg->defip_flex_ctr_base_id = TH_ENT_FC_BASE_ID_GET(unit); 2805 lpm_cfg->defip_flex_ctr_mode = TH_ENT_FC_MODE_GET(unit); 2806 lpm_cfg->defip_flex_ctr_pool = TH_ENT_FC_POOL_GET(unit); 2807 2808 /* No need to parse the rest field because there are already in the 2809 * lpm_cfg, part of key */ 2810 2811 if (soc_feature(unit, soc_feature_ipmc_defip)) { 2812 int is_ipmc = 0; 2813 if (TH_ENT_DATA_TYPE_GET(unit) == 2) { 2814 is_ipmc = 1; 2815 } 2816 2817 if (is_ipmc) { 2818 uint32 val; 2819 lpm_cfg->defip_flags |= BCM_L3_IPMC; 2820 if (TH_ENT_MC_DROP_GET(unit)) { 2821 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RPF_FAIL_DROP; 2822 } 2823 if (TH_ENT_MC_CPU_GET(unit)) { 2824 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_RPF_FAIL_TOCPU; 2825 } 2826 val = TH_ENT_MC_IIF_GET(unit); 2827 if (_BCM_DEFIP_IPMC_RP_IS_SET(val)) { 2828 lpm_cfg->defip_l3a_rp = _BCM_DEFIP_IPMC_RP_GET(val); 2829 } else { 2830 lpm_cfg->defip_expected_intf = val; 2831 if (lpm_cfg->defip_expected_intf != 0) { 2832 lpm_cfg->defip_ipmc_flags |= BCM_IPMC_POST_LOOKUP_RPF_CHECK; 2833 } 2834 lpm_cfg->defip_l3a_rp = BCM_IPMC_RP_ID_INVALID; 2835 } 2836 } else { 2837 lpm_cfg->defip_flags &= ~BCM_L3_IPMC; 2838 } 2839 } 2840 2841 return BCM_E_NONE; 2842 } 2843 2844 int 2845 th_tcam_entry_valid(int u, int pkm, void *ent, int x) 2846 { 2847 _alpm_cb_t *acb = ACB_TOP(u); 2848 soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]]; 2849 2850 return TH_ENT_VALID_GET(u) & (1 << x) ? 1 : 0; 2851 } 2852 2853 int 2854 th_tcam_entry_valid_set(int u, int pkm, void *ent, int x, int val) 2855 { 2856 soc_mem_t mem; 2857 soc_field_t vld_fld; 2858 _alpm_cb_t *acb = ACB_TOP(u); 2859 2860 mem = alpm_tbl[acb->pvt_tbl[pkm]]; 2861 switch (pkm) { 2862 case ALPM_PKM_32B: 2863 vld_fld = x ? VALID1f : VALID0f; 2864 soc_mem_field32_set(u, mem, ent, vld_fld, val ? 1 : 0); 2865 break; 2866 case ALPM_PKM_64B: 2867 soc_mem_field32_set(u, mem, ent, VALIDf, val ? 3 : 0); 2868 break; 2869 case ALPM_PKM_128: 2870 soc_mem_field32_set(u, mem, ent, VALID_LWRf, val ? 3 : 0); 2871 soc_mem_field32_set(u, mem, ent, VALID_UPRf, val ? 3 : 0); 2872 break; 2873 default: 2874 break; 2875 } 2876 2877 return BCM_E_NONE; 2878 } 2879 2880 static int 2881 th_tcam_entry_to_mask_key(int u, int pkm, void *ent, int x, 2882 uint32 *key, int is_mask) 2883 { 2884 _alpm_cb_t *acb = ACB_TOP(u); 2885 soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]]; 2886 2887 sal_memset(key, 0, 4 * sizeof(uint32)); 2888 if (is_mask) { 2889 TH_ENT_MASK_IPADDR_GET(u, key); 2890 } else { 2891 TH_ENT_KEY_IPADDR_GET(u, key); 2892 } 2893 2894 if (pkm == ALPM_PKM_64B) { 2895 key[3] = key[1]; 2896 key[2] = key[0]; 2897 key[1] = key[0] = 0; 2898 } 2899 2900 return BCM_E_NONE; 2901 } 2902 2903 /* 2904 * key[4] = {key[0], key[1], key[2], key[3]} 2905 * ipv4: key[4] = 2906 * {IP_ADDR0f, 0, 0, 0} 2907 * ipv6-64: key[4] = 2908 * {0, 0, IP_ADDR0f, IP_ADDR1f, } 2909 * ipv6-128: key[4] = 2910 * {IP_ADDR0_LWRf, IP_ADDR1_LWRf, IP_ADDR0_UPRf, IP_ADDR1_UPRf} 2911 */ 2912 int 2913 th_tcam_entry_to_key(int u, int pkm, void *ent, int x, uint32 *key) 2914 { 2915 return th_tcam_entry_to_mask_key(u, pkm, ent, x, key, FALSE); 2916 } 2917 2918 int 2919 th_tcam_entry_vrf_id_get(int u, int pkm, void *ent, int x, int *vrf_id) 2920 { 2921 _alpm_cb_t *acb = ACB_TOP(u); 2922 soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]]; 2923 2924 TH_ENT_KEY_VRF_ID_GET(u, *vrf_id); 2925 2926 return BCM_E_NONE; 2927 } 2928 2929 int 2930 th_tcam_entry_pfx_len_get(int u, int pkm, void *ent, int x, int *pfx_len) 2931 { 2932 int i, rv = BCM_E_NONE; 2933 uint32 mask[4]; 2934 2935 *pfx_len = 0; 2936 2937 /* Assuming each MASK field is correct, 2938 * Not my duty to validate MASK here */ 2939 th_tcam_entry_to_mask_key(u, pkm, ent, x, mask, TRUE); 2940 for (i = 0; i < 4; i++) { 2941 *pfx_len += _shr_popcount(mask[i]); 2942 } 2943 2944 return rv; 2945 } 2946 2947 /* 2948 * Function: 2949 * th_tcam_entry_mode_get 2950 * Purpose: 2951 * Get TCAM valid entry KEY mode and type. 2952 * Parameters: 2953 * u - (In)Device unit 2954 * pk - (In)Input TCAM packing mode table view 2955 * e - (In)TCAM lpm memory entry 2956 * step_size - (Out)Key mode step-size (un pair: 1 or 2, pair: 2) 2957 * p km - (Out)Detected packing mode 2958 * ipv6 - (Out)Key Type (0:IPv4, 1:IPv6) 2959 * key_mode - (Out)Key Mode (0:Half, 1:Full, 3:Double) 2960 * sub_idx - (In)TCAM sub_idx (0, 1) for half-wide entries in unpair 2961 * TCAM. Pair TCAM has only one sub_idx=0. 2962 * Notes: 2963 * The for-loop for sub_idx is using always as below: 2964 * for (sub_idx = 0; sub_idx < ALPM_TCAM_SUBCNT; sub_idx += step_size) 2965 * where 2966 * ALPM_TCAM_SUBCNT is defined as 2, and 2967 * step_size is variable, depending on the actual TCAM entry reading. 2968 * 2969 * Returns: 2970 * BCM_E_XXX 2971 */ 2972 int 2973 th_tcam_entry_mode_get(int u, int pk, void *ent, int *step_size, 2974 int *pkm, int *ipv6, int *key_mode, int x) 2975 { 2976 int valid; 2977 int is_pair_tbl = 0; 2978 _alpm_cb_t *acb = ACB_TOP(u); 2979 soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pk]]; 2980 2981 if (mem == alpm_tbl[alpmTblPvtCmodeL1P128]) { 2982 is_pair_tbl = 1; 2983 } 2984 *step_size = is_pair_tbl ? 2 : 1; 2985 2986 valid = TH_ENT_VALID_GET(u); 2987 valid &= (1 << x); 2988 2989 if (!valid) { /* invalid entry */ 2990 return BCM_E_NOT_FOUND; 2991 } 2992 2993 *key_mode = TH_ENT_KEY_KM_GET(u); 2994 *ipv6 = *key_mode ? 1 : 0; 2995 /* TD3TBD */ 2996 *pkm = (mem == alpm_tbl[alpmTblPvtCmodeL1P128]) ? ALPM_PKM_128 : 2997 *ipv6 ? ALPM_PKM_64B : ALPM_PKM_32B ; 2998 2999 /* Wrong key_mode or key_type */ 3000 if ((!is_pair_tbl && (*key_mode > 1)) || 3001 (is_pair_tbl && (*key_mode != 3))) { 3002 return BCM_E_INTERNAL; 3003 } 3004 3005 /* step_size 2 only if full-wide in un pair TCAM */ 3006 if (!is_pair_tbl && (*key_mode == 1)) { 3007 *step_size = 2; 3008 } 3009 return BCM_E_NONE; 3010 } 3011 3012 /* Get ASSOC_DATA from a TCAM entry */ 3013 int 3014 th_tcam_entry_adata_get(int u, int pkm, void *ent, int x, 3015 _alpm_bkt_adata_t *adata) 3016 { 3017 int ecmp = 0, ipmc = 0, rv = BCM_E_NONE; 3018 _alpm_cb_t *acb = ACB_TOP(u); 3019 soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]]; 3020 3021 TH_ENT_DEST_GET(u, ecmp, ipmc, adata->defip_ecmp_index); 3022 ipmc |= (TH_ENT_DATA_TYPE_GET(u) == 2); 3023 adata->defip_flags = ecmp ? BCM_L3_MULTIPATH : 0; 3024 adata->defip_flags |= (pkm != ALPM_PKM_32B) ? BCM_L3_IP6 : 0; 3025 adata->defip_flags |= ipmc ? BCM_L3_IPMC : 0; 3026 adata->defip_flags |= TH_ENT_RPE_GET(u) ? BCM_L3_RPE : 0; 3027 adata->defip_flags |= TH_ENT_DST_DISCARD_GET(u) ? BCM_L3_DST_DISCARD : 0; 3028 adata->defip_prio = TH_ENT_PRI_GET(u); 3029 adata->defip_lookup_class = TH_ENT_CLASS_ID_GET(u); 3030 adata->defip_flex_ctr_base_id = TH_ENT_FC_BASE_ID_GET(u); 3031 adata->defip_flex_ctr_mode = TH_ENT_FC_MODE_GET(u); 3032 adata->defip_flex_ctr_pool = TH_ENT_FC_POOL_GET(u); 3033 3034 return rv; 3035 } 3036 3037 /* Get ALPM_DATA entry from a TCAM entry */ 3038 int 3039 th_tcam_entry_bdata_get(int u, int pkm, void *ent, int x, void *fent) 3040 { 3041 /* return entry itself */ 3042 sal_memcpy(fent, ent, 3043 sizeof(uint32) * 3044 soc_mem_entry_words(u, alpm_tbl[ACB_TOP(u)->pvt_tbl[pkm]])); 3045 3046 return BCM_E_NONE; 3047 } 3048 3049 /***************** Bucket entry (Bank) starts from here *****************/ 3050 int 3051 th_alpm_ent_ent_get(int u, int vrf_id, _alpm_cb_t *acb, void *ent, uint32 fmt, 3052 int eid, void *ftmp) 3053 { 3054 int rv = BCM_E_NONE; 3055 3056 /* get bucket level bank format entry */ 3057 soc_format_field_get(u, ACB_FMT_BNK(acb, vrf_id, fmt), ent, 3058 th_alpm_ent_fld[eid], ftmp); 3059 return rv; 3060 } 3061 3062 /* Get ALPM_Data bucket info (logic table based): 3063 bkt_ptr, rofs, kshift, def_miss and bnkfmt[] */ 3064 static void 3065 th_alpm_ent_binfo_get(int u, int vrf_id, int ipt, int pvt_pkm, _alpm_cb_t *acb, 3066 void *ent, int x, _alpm_ent_info_t *info) 3067 { 3068 int bnk; 3069 soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pvt_pkm]]; 3070 3071 info->kshift = 0; 3072 BI_ROFS(&info->bkt_info) = 0; 3073 BI_BKT_IDX(&info->bkt_info) = TH_ENT_BKT_PTR_GET(u) >> ACB_BKT_DW(acb); 3074 BI_SUB_BKT_IDX(&info->bkt_info) = TH_ENT_SUB_BKT_PTR_GET(u); 3075 info->default_miss = TH_ENT_DEFAULT_MISS_GET(u); 3076 for (bnk = 0; bnk < ACB_BNK_PER_BKT(acb, vrf_id); bnk++) { 3077 info->bkt_info.bnk_fmt[bnk] = 3078 alpm_util_bkt_def_fmt_get(u, acb, vrf_id, ipt); 3079 } 3080 3081 return; 3082 } 3083 3084 /* Read and update ALPM prefix key */ 3085 int 3086 th_alpm_bkt_pfx_get(int u, int vrf_id, _alpm_cb_t *acb, void *ent, int ent_fmt, 3087 uint32 *valid, uint32 *new_key, int *new_len) 3088 { 3089 int rv = BCM_E_NONE; 3090 soc_format_t fmt = ACB_FMT_ENT(acb, vrf_id, ent_fmt); 3091 3092 /* process Bucket Level PREFIX */ 3093 *valid = TH_BKT_VALID_GET(u); 3094 if (*valid) { 3095 TH_BKT_KEY_GET(u, new_key); 3096 if (ent_fmt == ALPM_FMT_PKM_64B || ent_fmt == ALPM_FMT_PKM_FLEX_64B) { 3097 new_key[3] = new_key[1]; 3098 new_key[2] = new_key[0]; 3099 new_key[1] = new_key[0] = 0; 3100 } 3101 *new_len = TH_BKT_LENGTH_GET(u); 3102 } 3103 3104 return rv; 3105 } 3106 3107 /* Read ALPM Assoc_Data */ 3108 static void 3109 th_alpm_bkt_adata_get(int u, int vrf_id, int ipt, _alpm_cb_t *acb, void *ent, 3110 int ent_fmt, _alpm_ent_info_t *info) 3111 { 3112 int ecmp = 0, ipmc = 0; 3113 soc_format_t fmt = ACB_FMT_ENT(acb, vrf_id, ent_fmt); 3114 _alpm_bkt_adata_t *adata = &info->adata; 3115 3116 TH_BKT_DEST_GET(u, ecmp, ipmc, adata->defip_ecmp_index); 3117 adata->defip_flags = ecmp ? BCM_L3_MULTIPATH : 0; 3118 adata->defip_flags = ALPM_IS_IPV6(ipt) ? BCM_L3_IP6 : 0; 3119 adata->defip_flags |= ipmc ? BCM_L3_IPMC : 0; 3120 adata->defip_flags |= TH_BKT_RPE_GET(u) ? BCM_L3_RPE : 0; 3121 adata->defip_flags |= TH_BKT_DST_DISCARD_GET(u) ? BCM_L3_DST_DISCARD : 0; 3122 adata->defip_prio = TH_BKT_PRI_GET(u); 3123 adata->defip_lookup_class = TH_BKT_CLASS_ID_GET(u); 3124 if (soc_format_field_valid(u, fmt, FLEX_CTR_BASE_COUNTER_IDXf)) { 3125 adata->defip_flex_ctr_base_id = TH_BKT_FC_BASE_ID_GET(u); 3126 adata->defip_flex_ctr_mode = TH_BKT_FC_MODE_GET(u); 3127 adata->defip_flex_ctr_pool = TH_BKT_FC_POOL_GET(u); 3128 } 3129 info->bkt_info.sub_bkt_idx = TH_BKT_SUB_BKT_PTR_GET(u); 3130 3131 return ; 3132 } 3133 3134 static void 3135 th_alpm_ent_binfo_raw_get(int u, int vrf_id, _alpm_cb_t *acb, void *ent, 3136 int fmt, void *binfo_raw) 3137 { 3138 soc_format_t bnk_fmt = ACB_FMT_BNK(acb, vrf_id, fmt); 3139 soc_field_t ent_fld = th_alpm_ent_fld[0]; 3140 uint32 ent_sz = BITS2BYTES(soc_format_field_length(u, bnk_fmt, ent_fld)); 3141 sal_memcpy(binfo_raw, ent, ent_sz); 3142 return; 3143 } 3144 3145 /* Used for retrieving alpm info from given entry, 3146 * Entry 'e' can be a TCAM entry or a entry entry, not bank entry */ 3147 int 3148 th_alpm_ent_selective_get(int u, _alpm_cb_t *acb, void *ent, _alpm_ent_info_t *info) 3149 { 3150 int rv = BCM_E_NONE; 3151 int ent_fmt, vrf_id, ipt, pvt_pkm; 3152 uint32 mask = info->action_mask; 3153 3154 /* ent_fmt or sub_idx */ 3155 ent_fmt = info->ent_fmt; 3156 vrf_id = info->vrf_id; 3157 ipt = info->ipt; 3158 pvt_pkm = info->pvt_pkm; 3159 3160 if (mask & (ALPM_INFO_MASK_VALID | ALPM_INFO_MASK_KEYLEN)) { 3161 th_alpm_bkt_pfx_get(u, vrf_id, acb, ent, ent_fmt, &info->ent_valid, 3162 info->key, &info->key_len); 3163 } 3164 3165 if (mask & ALPM_INFO_MASK_ASSOC_DATA) { 3166 th_alpm_bkt_adata_get(u, vrf_id, ipt, acb, ent, ent_fmt, info); 3167 } 3168 3169 if (mask & ALPM_INFO_MASK_ALPM_DATA) { 3170 /* Here ent is TCAM entry */ 3171 th_alpm_ent_binfo_get(u, vrf_id, ipt, pvt_pkm, acb, ent, ent_fmt, info); 3172 } 3173 3174 if (mask & ALPM_INFO_MASK_ALPM_DATA_RAW) { 3175 th_alpm_ent_binfo_raw_get(u, vrf_id, acb, ent, ent_fmt, info->alpm_data_raw); 3176 } 3177 3178 if (mask & ALPM_INFO_MASK_FIXED_DATA) { 3179 /* For TCAM entry only */; 3180 } 3181 3182 return rv; 3183 } 3184 3185 /* Return ALPM bucket bank default (minimum) format according to DB_Type */ 3186 uint8 3187 th_alpm_bkt_def_fmt_get(int u, _alpm_cb_t *acb, int vrf_id, int ipt) 3188 { 3189 int bkt_pkm; 3190 3191 static uint8 def_fmt[] = { 3192 ALPM_FMT_PKM_32B, 3193 ALPM_FMT_PKM_FLEX_32B, 3194 ALPM_FMT_PKM_64B, 3195 ALPM_FMT_PKM_FLEX_64B, 3196 ALPM_FMT_PKM_128, 3197 ALPM_FMT_PKM_FLEX_128 3198 }; 3199 3200 if (ALPM_IS_IPV6(ipt)) { 3201 if (ALPM_128B(u)) { 3202 bkt_pkm = ALPM_PKM_128; 3203 } else { 3204 bkt_pkm = ALPM_PKM_64B; 3205 } 3206 } else { 3207 bkt_pkm = ALPM_PKM_32B; 3208 } 3209 3210 return def_fmt[bkt_pkm << 1 | ACB_VRF_DB_TYPE(u, acb, vrf_id, ipt)]; 3211 } 3212 3213 /* Return Reduced/Full format type for a given fmt */ 3214 int16 3215 th_alpm_bkt_fmt_type_get(int u, int vrf_id, _alpm_cb_t *acb, uint8 fmt) 3216 { 3217 return ACB_FMT_FULL_TYPE(acb, vrf_id, fmt); 3218 } 3219 3220 /* 3221 * Function: 3222 * th_alpm_table_dump 3223 * Purpose: 3224 * Dump ALPM memory tables: 3225 * "alpm table dump [raw|chg|all|nocache] <mem> <index> <format> [<ent>]" 3226 * Parameters: 3227 * u - Device unit # 3228 * mem - ALPM Level2 or Level3 memory table 3229 * copyno - mem table copy number 3230 * index - ALPM bucket level logic table index 3231 * fmt - Bank format (1-8 for Pivot formats, 1-12 for Route formats) 3232 * ent_idx - entry index (0-14), -1 for all entries. 3233 * flags - Dump flags (raw, chg, all, nocache) 3234 * Returns: 3235 * BCM_E_XXX 3236 */ 3237 void 3238 th_alpm_table_ent_dump(int u, int vrf_id, soc_mem_t mem, void *entry, 3239 int copyno, int index, int fmt, int ent_idx, 3240 int flags, char *pfx) 3241 { 3242 int i, ent, ent_min, ent_max; 3243 int f, entry_dw; 3244 int first_print_flag = 0; 3245 int vertical = 0; 3246 uint32 fent[ALPM_MEM_ENT_MAX]; 3247 uint32 fval[ALPM_MEM_ENT_MAX]; 3248 uint32 nfval[ALPM_MEM_ENT_MAX]; 3249 char ctmp[ALPM_MEM_ENT_MAX * 8 + 3]; 3250 soc_field_info_t *fieldp; 3251 soc_format_info_t *fmtp; 3252 soc_format_t tfmt; 3253 int fmt_ent_max[] = {0, 6, 4, 2, 4, 3, 2}; 3254 3255 _alpm_cb_t *acb; 3256 3257 if (ent_idx >= fmt_ent_max[fmt]) { 3258 return; 3259 } 3260 3261 acb = ACB_TOP(u); 3262 tfmt = ACB_FMT_ENT(acb, vrf_id, fmt); 3263 3264 if (ent_idx == -1) { /* all entries */ 3265 ent_min = 0; 3266 ent_max = fmt_ent_max[fmt] - 1; 3267 } else { /* one specific entry */ 3268 ent_min = ent_idx; 3269 ent_max = ent_idx; 3270 } 3271 3272 sal_memset(nfval, 0, sizeof(nfval)); 3273 3274 for (ent = ent_min; ent <= ent_max; ent++) { 3275 soc_format_field_get(u, ACB_FMT_BNK(acb, vrf_id, fmt), entry, 3276 th_alpm_ent_fld[ent], fent); 3277 fmtp = &SOC_FORMAT_INFO(u, tfmt); 3278 3279 if (flags & ALPM_DUMP_TABLE_RAW) { 3280 cli_out("%s", pfx); 3281 entry_dw = BITS2WORDS(fmtp->bits); 3282 for (i = 0; i < entry_dw; i++) { 3283 cli_out("0x%08x ", fent[i]); 3284 } 3285 cli_out("\n"); 3286 } else { 3287 /* for fields in entry format */ 3288 for (f = fmtp->nFields - 1; f >= 0; f--) { 3289 fieldp = &fmtp->fields[f]; 3290 sal_memset(fval, 0, ALPM_MEM_ENT_MAX * sizeof(uint32)); 3291 soc_format_field_get(u, tfmt, fent, fieldp->field, fval); 3292 3293 if (flags & ALPM_DUMP_TABLE_CHANGED) { 3294 if (sal_memcmp(fval, nfval, ALPM_MEM_ENT_MAX * 3295 sizeof(uint32)) == 0) { 3296 continue; 3297 } 3298 } 3299 _shr_format_long_integer(ctmp, fval, BITS2BYTES(fieldp->len)); 3300 3301 if (first_print_flag == 0) { 3302 cli_out("%s%s", pfx, vertical ? "" : "<"); 3303 first_print_flag=1; 3304 } 3305 if (vertical) { 3306 cli_out("\n\t%30s: %s", SOC_FIELD_NAME(u, fieldp->field), ctmp); 3307 } else { 3308 cli_out("%s=%s%s", SOC_FIELD_NAME(u, fieldp->field), 3309 ctmp, f > 0 ? "," : ""); 3310 } 3311 } /* for f */ 3312 3313 if (first_print_flag == 1) { 3314 cli_out("%s\n", vertical ? "" : ">"); 3315 first_print_flag = 0; 3316 } 3317 } 3318 } /* for ent */ 3319 } 3320 3321 int 3322 th_alpm_table_dump(int u, int vrf_id, soc_mem_t mem, int copyno, int index, 3323 int fmt, int ent_idx, int flags) 3324 { 3325 int rv = BCM_E_NONE; 3326 uint32 entry[ALPM_MEM_ENT_MAX]; 3327 char mem_prefix[256] = {0}; 3328 3329 if ((fmt <= 0) || (fmt > 6)) { 3330 cli_out("invalid or disabled bank format %d\n", fmt); 3331 return BCM_E_INTERNAL; 3332 } 3333 3334 if (flags & ALPM_DUMP_TABLE_NOCACHE) { 3335 rv = soc_mem_read_no_cache(u, 0, mem, 0, MEM_BLOCK_ANY, index, entry); 3336 } else { 3337 rv = soc_mem_read(u, mem, MEM_BLOCK_ANY, index, entry); 3338 } 3339 3340 if (BCM_SUCCESS(rv)) { 3341 sal_sprintf(mem_prefix, "%s.%s[%d.%d]: ", SOC_MEM_UFNAME(u, mem), 3342 SOC_BLOCK_NAME(u, copyno), index, ent_idx); 3343 th_alpm_table_ent_dump(u, vrf_id, mem, entry, copyno, index, fmt, 3344 ent_idx, flags, mem_prefix); 3345 } 3346 3347 return rv; 3348 } 3349 3350 #define ALPM_PHY_BKT_CNT(u) (SOC_IS_HELIX5(u) ? 4096 : 8192) 3351 3352 /* 3353 * Function: 3354 * th_alpm_cap_min 3355 * Purpose: 3356 * Get the min capacity for ALPM routes from PKM 3357 * Parameters: 3358 * u - Device unit 3359 * mem - hardware memory 3360 */ 3361 int 3362 th_alpm_cap_min(int u, soc_mem_t mem) 3363 { 3364 #define UTIL_33(x) ((x) / 3) 3365 #define UTIL_66(x) ((x) * 2 / 3) 3366 #define UTIL_85(x) ((x) * 85 / 100) 3367 3368 int min_ent = 0, tcam_ent = 0, tot_rte = 0, tot_bkt = 0; 3369 int pkm; 3370 int urpf = SOC_URPF_STATUS_GET(u); 3371 int tcam_alpm = 0; 3372 int pid, fmt; 3373 _alpm_bkt_pool_conf_t *bp_conf; 3374 _alpm_cb_t *acb; 3375 3376 acb = ACB_BTM(u); 3377 3378 switch (ALPM_MODE(u)) { 3379 case BCM_ALPM_MODE_COMBINED: 3380 case BCM_ALPM_MODE_PARALLEL: 3381 break; 3382 case BCM_ALPM_MODE_TCAM_ALPM: 3383 tcam_alpm = 1; 3384 break; 3385 default: 3386 return 0; 3387 } 3388 3389 switch (mem) { 3390 case L3_DEFIP_ALPM_IPV4m: 3391 fmt = 1; 3392 pkm = ALPM_PKM_32B; 3393 break; 3394 case L3_DEFIP_ALPM_IPV4_1m: 3395 fmt = 4; 3396 pkm = ALPM_PKM_32B; 3397 break; 3398 case L3_DEFIP_ALPM_IPV6_64m: 3399 fmt = 2; 3400 pkm = ALPM_PKM_64B; 3401 break; 3402 case L3_DEFIP_ALPM_IPV6_64_1m: 3403 fmt = 5; 3404 pkm = ALPM_PKM_64B; 3405 break; 3406 case L3_DEFIP_ALPM_IPV6_128m: 3407 fmt = 3; 3408 pkm = ALPM_PKM_128; 3409 break; 3410 default: 3411 fmt = 1; 3412 pkm = ALPM_PKM_32B; 3413 break; 3414 } 3415 3416 /* include VRF private and global routes */ 3417 for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) { 3418 int avl_bnks; 3419 bp_conf = ACB_BKT_POOL(acb, pid); 3420 if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid - 1)) { 3421 continue; /* Combined Mode uses PID=0 only */ 3422 } 3423 3424 /* Exclude reserved bucket 0 */ 3425 avl_bnks = BPC_BNK_CNT(bp_conf) - BPC_BNK_PER_BKT(bp_conf); 3426 if (ALPM_128B(u) && ALPM_BKT_RSVD(u)) { 3427 int rsvd_v6_bnks = 3428 BPC_BNK_CNT(bp_conf) * ALPM_BKT_RSVD_CNT(u) / ALPM_PHY_BKT_CNT(u); 3429 if (pkm == ALPM_PKM_128) { 3430 avl_bnks = rsvd_v6_bnks; 3431 } else { 3432 avl_bnks -= rsvd_v6_bnks; 3433 } 3434 } 3435 3436 tot_rte += avl_bnks * BPC_FMT_ENT_MAX(bp_conf, fmt); 3437 tot_bkt += BPC_BNK_PER_BKT(bp_conf) ? 3438 (avl_bnks / BPC_BNK_PER_BKT(bp_conf)) : 0; 3439 } 3440 3441 switch (mem) { 3442 case L3_DEFIP_ALPM_IPV4m: 3443 case L3_DEFIP_ALPM_IPV4_1m: 3444 tcam_ent = soc_mem_index_count(u, L3_DEFIPm) * 2; 3445 break; 3446 3447 case L3_DEFIP_ALPM_IPV6_64m: 3448 case L3_DEFIP_ALPM_IPV6_64_1m: 3449 tcam_ent = soc_mem_index_count(u, L3_DEFIPm); 3450 break; 3451 3452 case L3_DEFIP_ALPM_IPV6_128m: 3453 tcam_ent = soc_mem_index_count(u, L3_DEFIP_PAIR_128m); 3454 break; 3455 3456 default: 3457 break; 3458 } 3459 3460 if (tcam_alpm) { 3461 tcam_ent /= 2; 3462 } 3463 3464 if (tcam_ent) { 3465 tcam_ent = tcam_ent >> urpf; 3466 3467 if (tcam_ent <= tot_bkt) { 3468 min_ent = UTIL_33(tot_rte / tot_bkt) * tcam_ent; 3469 } else { 3470 min_ent = UTIL_33(tot_rte / tot_bkt) * tot_bkt; 3471 } 3472 if (tcam_alpm) { 3473 min_ent += tcam_ent; 3474 } 3475 } else { 3476 min_ent = 0; 3477 } 3478 3479 return min_ent; 3480 3481 } 3482 3483 /* 3484 * Function: 3485 * th_alpm_cap_max 3486 * Purpose: 3487 * Get the max capacity for ALPM routes from PKM 3488 * Parameters: 3489 * u - Device unit 3490 * mem - hardware memory 3491 */ 3492 static int 3493 th_alpm_cap_max(int u, soc_mem_t mem) 3494 { 3495 int pkm; 3496 int tcam_ent = 0, tot_rte = 0, tot_bkt = 0; 3497 int urpf = SOC_URPF_STATUS_GET(u); 3498 int tcam_alpm = 0; 3499 int pid, fmt; 3500 _alpm_bkt_pool_conf_t *bp_conf; 3501 _alpm_cb_t *acb; 3502 3503 acb = ACB_BTM(u); 3504 3505 switch (ALPM_MODE(u)) { 3506 case BCM_ALPM_MODE_COMBINED: 3507 case BCM_ALPM_MODE_PARALLEL: 3508 break; 3509 case BCM_ALPM_MODE_TCAM_ALPM: 3510 tcam_alpm = 1; 3511 break; 3512 default: 3513 return 0; 3514 } 3515 3516 switch (mem) { 3517 case L3_DEFIP_ALPM_IPV4m: 3518 pkm = ALPM_PKM_32B; 3519 fmt = 1; 3520 break; 3521 case L3_DEFIP_ALPM_IPV4_1m: 3522 pkm = ALPM_PKM_32B; 3523 fmt = 4; 3524 break; 3525 case L3_DEFIP_ALPM_IPV6_64m: 3526 pkm = ALPM_PKM_64B; 3527 fmt = 2; 3528 break; 3529 case L3_DEFIP_ALPM_IPV6_64_1m: 3530 pkm = ALPM_PKM_64B; 3531 fmt = 5; 3532 break; 3533 case L3_DEFIP_ALPM_IPV6_128m: 3534 pkm = ALPM_PKM_128; 3535 fmt = 3; 3536 break; 3537 default: 3538 pkm = ALPM_PKM_32B; 3539 fmt = 1; 3540 break; 3541 } 3542 3543 /* include VRF private and global routes */ 3544 for (pid = 0; pid < ALPM_BKT_PID_CNT; pid++) { 3545 int avl_bnks; 3546 bp_conf = ACB_BKT_POOL(acb, pid); 3547 if (pid > 0 && bp_conf == ACB_BKT_POOL(acb, pid - 1)) { 3548 continue; /* Combined Mode uses PID=0 only */ 3549 } 3550 3551 /* Exclude reserved bucket 0 */ 3552 avl_bnks = BPC_BNK_CNT(bp_conf) - BPC_BNK_PER_BKT(bp_conf); 3553 3554 if (ALPM_128B(u) && ALPM_BKT_RSVD(u)) { 3555 int rsvd_v6_bnks = 3556 BPC_BNK_CNT(bp_conf) * ALPM_BKT_RSVD_CNT(u) / ALPM_PHY_BKT_CNT(u); 3557 if (pkm == ALPM_PKM_128) { 3558 avl_bnks = rsvd_v6_bnks; 3559 } else { 3560 avl_bnks -= rsvd_v6_bnks; 3561 } 3562 } 3563 3564 tot_rte += avl_bnks * BPC_FMT_ENT_MAX(bp_conf, fmt); 3565 tot_bkt += BPC_BNK_PER_BKT(bp_conf) ? 3566 (avl_bnks / BPC_BNK_PER_BKT(bp_conf)) : 0; 3567 } 3568 3569 switch (mem) { 3570 case L3_DEFIP_ALPM_IPV4m: 3571 case L3_DEFIP_ALPM_IPV4_1m: 3572 tcam_ent = soc_mem_index_count(u, L3_DEFIPm) * 2; 3573 break; 3574 3575 case L3_DEFIP_ALPM_IPV6_64m: 3576 case L3_DEFIP_ALPM_IPV6_64_1m: 3577 tcam_ent = soc_mem_index_count(u, L3_DEFIPm); 3578 break; 3579 3580 case L3_DEFIP_ALPM_IPV6_128m: 3581 tcam_ent = soc_mem_index_count(u, L3_DEFIP_PAIR_128m); 3582 break; 3583 3584 default: 3585 tot_rte = 0; 3586 break; 3587 } 3588 3589 if (tcam_alpm) { 3590 tcam_ent /= 2; 3591 } 3592 3593 if (tcam_ent) { 3594 tcam_ent = tcam_ent >> urpf; 3595 3596 if (tcam_ent <= tot_bkt) { 3597 tot_rte = (tot_rte / tot_bkt) * tcam_ent; 3598 } 3599 if (tcam_alpm) { 3600 tot_rte += tcam_ent; 3601 } 3602 } else { 3603 tot_rte = 0; 3604 } 3605 3606 return tot_rte; 3607 3608 } 3609 3610 /* 3611 * Function: 3612 * th_alpm_cap_get 3613 * Purpose: 3614 * Get the min or max capacity for ALPM routes from tables: 3615 * L3_DEFIP_ALPM_IPV4, L3_DEFIP_ALPM_IPV6_64, L3_DEFIP_ALPM_IPV6_128 3616 * 3617 * Parameters: 3618 * u - Device unit 3619 * mem - Legacy memory type 3620 * max_cnt - Maximum result returned. 3621 * min_cnt - Minimum result returned. 3622 */ 3623 int 3624 th_alpm_cap_get(int u, soc_mem_t mem, int *max_cnt, int *min_cnt) 3625 { 3626 3627 switch (mem) { 3628 case L3_DEFIP_ALPM_IPV4m: 3629 case L3_DEFIP_ALPM_IPV4_1m: 3630 case L3_DEFIP_ALPM_IPV6_64m: 3631 case L3_DEFIP_ALPM_IPV6_64_1m: 3632 case L3_DEFIP_ALPM_IPV6_128m: 3633 break; 3634 default: 3635 return BCM_E_UNAVAIL; 3636 } 3637 3638 if (min_cnt != NULL) { 3639 *min_cnt = th_alpm_cap_min(u, mem); 3640 } 3641 3642 if (max_cnt != NULL) { 3643 *max_cnt = th_alpm_cap_max(u, mem); 3644 } 3645 3646 return BCM_E_NONE; 3647 } 3648 3649 3650 static int 3651 th_alpm_hit_tbl_idx_get(int u, _alpm_cb_t *acb, _alpm_tbl_t tbl, int idx, int ent) 3652 { 3653 int phy_idx; 3654 phy_idx = th_mem_phy_index_get(u, acb, tbl, idx); 3655 #if defined(BCM_HELIX5_SUPPORT) 3656 #define HX5_ALPM_4_BANK_MODE_BANK_BITS 2 3657 if (soc_feature(u, soc_feature_alpm_addr_xlate)) { 3658 int phy_bnk; 3659 int phy_bkt; 3660 phy_bnk = phy_idx >> HX5_ALPM_PHY_BKT_BITS; 3661 phy_bkt = phy_idx & ((1 << HX5_ALPM_PHY_BKT_BITS) - 1); 3662 if (soc_alpm_cmn_banks_get(u) == 6) { 3663 phy_idx = ent * HX5_ALPM_BKT_ENT_MAX + phy_bnk; 3664 phy_idx = (phy_idx << HX5_ALPM_PHY_BKT_BITS) | phy_bkt; 3665 } else { 3666 phy_idx = (ent << HX5_ALPM_4_BANK_MODE_BANK_BITS) | phy_bnk; 3667 phy_idx = (phy_idx << HX5_ALPM_PHY_BKT_BITS) | phy_bkt; 3668 } 3669 } else 3670 #endif 3671 { 3672 phy_idx =(ent << (ACB_BNK_BITS(acb) + TD3_ALPM_BKT_BITS)) | phy_idx; 3673 } 3674 return phy_idx; 3675 } 3676 /* 3677 * Function: 3678 * th_alpm_bkt_hit_get 3679 * Purpose: 3680 * Get ALPM bucket entry hitbit status from hitbit table cache 3681 * sync with Hw. Route hitbit status is gathered from pivots 3682 * whose BPM is the route. 3683 * Parameters: 3684 * u - Device unit # 3685 * vrf_id - VRF ID for logic hit table PID in Parallel/Mixed Mode 3686 * acb - ALPM control block where hit table located 3687 * idx - ALPM bucket level logic table index 3688 * ent - Bucket entry ID (0-15) 3689 * Returns: 3690 * Bucket entry hitbit (0 or 1) 3691 */ 3692 int 3693 th_alpm_bkt_hit_get(int u, int vrf_id, _alpm_cb_t *acb, 3694 _alpm_tbl_t tbl, int idx, int ent) 3695 { 3696 int rv; 3697 int hit_hit_offset; 3698 int hit_tab_idx; 3699 uint32 *tbl_ent; /* bucket hit cache table entry pointer */ 3700 int i = ACB_IDX(acb); 3701 int pid = 0; 3702 soc_mem_t mem = ALPM_HTBL_MEM(u, i, pid); 3703 soc_field_t hit_fld[4] = { 3704 HIT_0f, HIT_1f, HIT_2f, HIT_3f 3705 }; 3706 3707 ALPM_HIT_LOCK(u); 3708 3709 hit_tab_idx = th_alpm_hit_tbl_idx_get(u ,acb, tbl, idx, ent); 3710 3711 hit_hit_offset = hit_tab_idx % 4; 3712 hit_tab_idx /= 4; 3713 3714 tbl_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *, 3715 ALPM_HTBL_CACHE(u, i, pid), hit_tab_idx); 3716 rv = soc_mem_field32_get(u, mem, tbl_ent, hit_fld[hit_hit_offset]); 3717 3718 ALPM_HIT_UNLOCK(u); 3719 return rv; 3720 } 3721 3722 /* 3723 * Function: 3724 * th_alpm_bkt_hit_set 3725 * Purpose: 3726 * Set ALPM bucket entry hitbit to cache table only 3727 * Parameters: 3728 * u - Device unit #. 3729 * vrf_id - VRF ID for logic hit table PID in Parallel/Mixed Mode 3730 * acb - ALPM control block where hit table located 3731 * idx - ALPM bucket level table index 3732 * ent - Bucket entry ID (0-15) 3733 * hit_val - Bucket entry hit value (0/1) 3734 * Returns: 3735 * BCM_E_XXX 3736 */ 3737 int 3738 th_alpm_bkt_hit_set(int u, int vrf_id, _alpm_cb_t *acb, _alpm_tbl_t tbl, 3739 int idx, int ent, int hit_val) 3740 { 3741 int rv = BCM_E_NONE; 3742 int hit_bit_offset; 3743 int hit_tab_idx; 3744 uint32 *tbl_ent; /* bucket hit cache table entry pointer */ 3745 int i = ACB_IDX(acb); 3746 int pid = 0; 3747 soc_mem_t mem = ALPM_HTBL_MEM(u, i, pid); 3748 soc_field_t hit_fld[4] = { 3749 HIT_0f, HIT_1f, HIT_2f, HIT_3f 3750 }; 3751 3752 ALPM_HIT_LOCK(u); 3753 3754 hit_tab_idx = th_alpm_hit_tbl_idx_get(u, acb, tbl, idx, ent); 3755 3756 hit_bit_offset = hit_tab_idx % 4; 3757 hit_tab_idx /= 4; 3758 3759 tbl_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *, 3760 ALPM_HTBL_CACHE(u, i, pid), hit_tab_idx); 3761 soc_mem_field32_set(u, mem, tbl_ent, hit_fld[hit_bit_offset], hit_val); 3762 3763 ALPM_HIT_UNLOCK(u); 3764 return rv; 3765 } 3766 3767 /* 3768 * Function: 3769 * th_alpm_bkt_hit_write 3770 * Purpose: 3771 * Set ALPM bucket entry hitbit status to hitbit table cache 3772 * and write to Hw (by setting Entry Move & Mask to trigger write to Hw 3773 * in next Dist Hitbit thread clycle). 3774 * Parameters: 3775 * u - Device unit # 3776 * vrf_id - VRF ID for logic hit table PID in Parallel/Mixed Mode 3777 * acb - ALPM control block where hit table located 3778 * ent_idx - ALPM bucket node ent_idx 3779 * hit_val - HITBIT value requested 3780 * Returns: 3781 * BCM_E_XXX 3782 */ 3783 int 3784 th_alpm_bkt_hit_write(int u, int vrf_id, _alpm_cb_t *acb, 3785 _alpm_tbl_t tbl, int ent_idx, int hit_val) 3786 { 3787 int rv = BCM_E_NONE; 3788 int idx, ent; 3789 int hit_tab_idx; 3790 uint32 *dst_ent; /* bucket hit cache table entry pointer */ 3791 int i = ACB_IDX(acb); 3792 int pid = 0; 3793 soc_mem_t mem = ALPM_HTBL_MEM(u, i, pid); 3794 soc_field_t hit_fld[4] = { 3795 HIT_0f, HIT_1f, HIT_2f, HIT_3f 3796 }; 3797 3798 ALPM_HIT_LOCK(u); 3799 3800 ent = ALPM_IDX_TO_ENT(ent_idx); 3801 hit_tab_idx = th_alpm_hit_tbl_idx_get(u, acb, tbl, ent_idx, ent); 3802 3803 ent = hit_tab_idx % 4; 3804 idx = hit_tab_idx / 4; 3805 3806 /* Write hit_val to dst cache hit bit */ 3807 dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 3808 ALPM_HTBL_CACHE(u, i, pid), idx); 3809 soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val); 3810 3811 /* Write hit_val to dst move bit */ 3812 dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 3813 ALPM_HTBL_MOVE(u, i, pid), idx); 3814 soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val); 3815 3816 /* Set dst move mask bit */ 3817 dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 3818 ALPM_HTBL_MOVE_MASK(u, i, pid), idx); 3819 soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], 1); 3820 3821 /* declare finally hitbit entry_moved flag */ 3822 ALPM_HTBL_ENT_MOVED(u, i, pid) = TRUE; 3823 3824 ALPM_HIT_UNLOCK(u); 3825 3826 return rv; 3827 } 3828 3829 /* ALPM bucket hitbit entry move from bkt_node's src_ent_idx to dst_ent_idx. 3830 Copy hit bit cache, and set properly move, move_mask and ent_moved flag. 3831 */ 3832 int 3833 th_alpm_ent_hit_move(int u, int vrf_id, _alpm_cb_t *acb, _alpm_tbl_t tbl, 3834 int src_ent_idx, int dst_ent_idx) 3835 { 3836 int rv = BCM_E_NONE; 3837 int i, hit_val, idx, ent; 3838 uint32 *src_ent, *dst_ent; 3839 int pid = 0; 3840 int hit_tab_idx; 3841 soc_mem_t mem; 3842 soc_field_t hit_fld[4] = { 3843 HIT_0f, HIT_1f, HIT_2f, HIT_3f 3844 }; 3845 3846 ALPM_HIT_LOCK(u); 3847 3848 i = ACB_IDX(acb); 3849 mem = ALPM_HTBL_MEM(u, i, pid); 3850 3851 ent = ALPM_IDX_TO_ENT(src_ent_idx); 3852 hit_tab_idx = th_alpm_hit_tbl_idx_get(u, acb, tbl, src_ent_idx, ent); 3853 3854 ent = hit_tab_idx % 4; 3855 idx = hit_tab_idx / 4; 3856 3857 3858 /* Save src cache hit_val and clear it */ 3859 src_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 3860 ALPM_HTBL_CACHE(u, i, pid), idx); 3861 hit_val = soc_mem_field32_get(u, mem, src_ent, hit_fld[ent]); 3862 soc_mem_field32_set(u, mem, src_ent, hit_fld[ent], 0); 3863 3864 /* Clear src move bit */ 3865 src_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 3866 ALPM_HTBL_MOVE(u, i, pid), idx); 3867 soc_mem_field32_set(u, mem, src_ent, hit_fld[ent], 0); 3868 3869 /* Set src move mask bit */ 3870 src_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 3871 ALPM_HTBL_MOVE_MASK(u, i, pid), idx); 3872 soc_mem_field32_set(u, mem, src_ent, hit_fld[ent], 1); 3873 3874 /* 2) Dst */ 3875 ent = ALPM_IDX_TO_ENT(dst_ent_idx); 3876 hit_tab_idx = th_alpm_hit_tbl_idx_get(u, acb, tbl, dst_ent_idx, ent); 3877 3878 ent = hit_tab_idx % 4; 3879 idx = hit_tab_idx / 4; 3880 3881 3882 /* Write hit_val to dst cache hit bit */ 3883 dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 3884 ALPM_HTBL_CACHE(u, i, pid), idx); 3885 soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val); 3886 3887 /* Write hit_val to dst move bit */ 3888 dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 3889 ALPM_HTBL_MOVE(u, i, pid), idx); 3890 soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], hit_val); 3891 3892 /* Set dst move mask bit */ 3893 dst_ent = soc_mem_table_idx_to_pointer(u, mem, void *, 3894 ALPM_HTBL_MOVE_MASK(u, i, pid), idx); 3895 soc_mem_field32_set(u, mem, dst_ent, hit_fld[ent], 1); 3896 3897 /* declare finally hitbit entry_moved flag */ 3898 ALPM_HTBL_ENT_MOVED(u, i, pid) = TRUE; 3899 3900 ALPM_HIT_UNLOCK(u); 3901 3902 return rv; 3903 } 3904 3905 /* ALPM bucket bank hitbit move from src_idx to dst_idx. 3906 Copy hit bit cache, and set properly move, move_mask and ent_moved flag. 3907 */ 3908 int 3909 th_alpm_bnk_hit_move(int u, int vrf_id, _alpm_cb_t *acb, 3910 _alpm_bkt_info_t *bkt_info, _alpm_tbl_t tbl, 3911 int src_idx, int dst_idx) 3912 { 3913 int i; 3914 int ent_max; 3915 int src_ent_idx; 3916 int dst_ent_idx; 3917 int sbnk; 3918 int rv = BCM_E_NONE; 3919 sbnk = ALPM_IDX_TO_BNK(acb, src_idx); 3920 ent_max = ACB_FMT_ENT_MAX(acb, vrf_id, bkt_info->bnk_fmt[sbnk]); 3921 for (i = 0; i < ent_max; i++) { 3922 src_ent_idx = (i << ALPM_IDX_ENT_SHIFT) | src_idx; 3923 dst_ent_idx = (i << ALPM_IDX_ENT_SHIFT) | dst_idx; 3924 rv = th_alpm_ent_hit_move(u, vrf_id, acb, tbl, src_ent_idx, dst_ent_idx); 3925 } 3926 3927 return rv; 3928 } 3929 3930 /* Clear ALPM bucket bank hitbit cache at idx. 3931 Set properly move, move_mask and ent_moved flag. 3932 */ 3933 int 3934 th_alpm_bnk_hit_clear(int u, int vrf_id, _alpm_cb_t *acb, 3935 _alpm_bkt_info_t *bkt_info, _alpm_tbl_t tbl, 3936 int idx) 3937 { 3938 int i; 3939 int ent_max; 3940 int rv = BCM_E_NONE; 3941 int ent_idx; 3942 int bnk; 3943 bnk = ALPM_IDX_TO_BNK(acb, idx); 3944 ent_max = ACB_FMT_ENT_MAX(acb, vrf_id, bkt_info->bnk_fmt[bnk]); 3945 for (i = 0; i < ent_max; i++) { 3946 ent_idx = (i << ALPM_IDX_ENT_SHIFT) | idx; 3947 rv = th_alpm_bkt_hit_write(u, vrf_id, acb, tbl, ent_idx, 0); 3948 } 3949 3950 return rv; 3951 } 3952 3953 /* Update hitbit for entry move on level i by 3954 * hit_cache = (hit_cache & ~hit_move_mask) | (hit_move & hit_move_mask) 3955 */ 3956 int 3957 th_alpm_hit_move_update(int u, int i, int pid) 3958 { 3959 int rv = BCM_E_NONE; 3960 int idx, index_cnt; 3961 uint32 hit_cache, hit_move, hit_move_mask; 3962 uint32 *cache_ent, *move_ent, *move_mask_ent; 3963 soc_mem_t mem; 3964 3965 if (!ALPM_HTBL_ENT_MOVED(u, i, pid)) { 3966 return rv; 3967 } 3968 3969 mem = ALPM_HTBL_MEM(u, i, pid); 3970 index_cnt = ALPM_HTBL_IDX_CNT(u, i, pid); 3971 3972 ALPM_HTBL_ENT_MOVED_CNT(u, i, pid) = 0; 3973 for (idx = 0; idx < index_cnt; idx++) { 3974 move_mask_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *, 3975 ALPM_HTBL_MOVE_MASK(u, i, pid), idx); 3976 hit_move_mask = *move_mask_ent; 3977 3978 if (hit_move_mask) { 3979 cache_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 * , 3980 ALPM_HTBL_CACHE(u, i, pid), idx); 3981 move_ent = soc_mem_table_idx_to_pointer(u, mem, uint32 *, 3982 ALPM_HTBL_MOVE(u, i, pid), idx); 3983 hit_cache = *cache_ent; 3984 hit_move = *move_ent; 3985 3986 /* update cache entry */ 3987 *cache_ent = (hit_cache & ~hit_move_mask) | 3988 (hit_move & hit_move_mask); 3989 3990 ALPM_HTBL_ENT_MOVED_CNT(u, i, pid)++; 3991 } 3992 } 3993 3994 return rv; 3995 } 3996 3997 /* Sync ALPM non-TCAM level (i:0/1 for level 2/3) hitbit cache with Hw */ 3998 int 3999 th_alpm_hit_cache_sync(int u, int i, int pid) 4000 { 4001 soc_mem_t mem; 4002 int idx_max, offset = 0; 4003 int rv = BCM_E_NONE; 4004 4005 mem = ALPM_HTBL_MEM(u, i, pid); 4006 idx_max = ALPM_HTBL_IDX_CNT(u, i, pid) - 1; 4007 4008 rv = soc_mem_read_range(u, mem, MEM_BLOCK_ANY, offset, idx_max + offset, 4009 ALPM_HTBL_CACHE(u, i, pid)); 4010 4011 return rv; 4012 } 4013 4014 /* Write ALPM non-TCAM level (i:0/1 for level 2/3) hitbit cache to Hw */ 4015 int 4016 th_alpm_hit_hw_write(int u, int i, int pid) 4017 { 4018 soc_mem_t mem; 4019 int idx_max, offset = 0; 4020 int rv = BCM_E_NONE; 4021 4022 mem = ALPM_HTBL_MEM(u, i, pid); 4023 idx_max = ALPM_HTBL_IDX_CNT(u, i, pid) - 1; 4024 4025 rv = soc_mem_write_range(u, mem, MEM_BLOCK_ALL, offset, idx_max + offset, 4026 ALPM_HTBL_CACHE(u, i, pid)); 4027 4028 return rv; 4029 } 4030 4031 /* Get hitbit status from a TCAM entry 4032 (it sync to Hw periodically) */ 4033 int 4034 th_tcam_ent_hit_get(int u, int pkm, void *e, int sub_idx) 4035 { 4036 int rv = BCM_E_NONE; 4037 soc_field_t hit_fld[2] = {HIT0f, HIT1f}; 4038 _alpm_cb_t *acb = ACB_TOP(u); 4039 soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]]; 4040 4041 if (SOC_MEM_FIELD_VALID(u, mem, HITf)) { 4042 hit_fld[0] = HITf; 4043 hit_fld[1] = HITf; 4044 } 4045 4046 rv = soc_mem_field32_get(u, mem, e, hit_fld[sub_idx]); 4047 4048 return rv; 4049 } 4050 4051 /* Get TCAM cached hitbit status from pvt_node's tcam_idx 4052 (it sync to Hw periodically) */ 4053 int 4054 th_tcam_cache_hit_get(int u, int pkm, int tcam_idx) 4055 { 4056 int rv = BCM_E_NONE; 4057 int idx, sub_idx; 4058 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 4059 soc_field_t hit_fld[2] = {HIT0f, HIT1f}; 4060 4061 _alpm_cb_t *acb = ACB_TOP(u); 4062 soc_mem_t mem = alpm_tbl[acb->pvt_tbl[pkm]]; 4063 4064 if (SOC_MEM_FIELD_VALID(u, mem, HITf)) { 4065 hit_fld[0] = HITf; 4066 hit_fld[1] = HITf; 4067 } 4068 4069 if (pkm == ALPM_PKM_32B) { 4070 /* tcam_idx = idx << 1 | sub_idx */ 4071 sub_idx = tcam_idx & 1; 4072 idx = tcam_idx >> 1; 4073 } else { 4074 sub_idx = 0; 4075 idx = tcam_idx; 4076 } 4077 4078 ALPM_IER(th_mem_read(u, acb, acb->pvt_tbl[pkm], idx, e, FALSE)); 4079 rv = soc_mem_field32_get(u, mem, e, hit_fld[sub_idx]); 4080 return rv; 4081 } 4082 4083 /* Sync TCAM hitbit cache tables with Hw */ 4084 int 4085 th_tcam_hit_cache_sync(int u) 4086 { 4087 soc_mem_t mem; 4088 _alpm_cb_t *acb = ACB_TOP(u); 4089 int pkm, tbl_sz; 4090 int rv = BCM_E_NONE; 4091 4092 for (pkm = 0; pkm < ALPM_PKM_CNT; pkm++) { 4093 4094 if (ALPM_TCAM_TBL_SKIP(u, pkm)) { 4095 continue; /* skip duplicated or invalid TCAM table */ 4096 } 4097 4098 mem = alpm_tbl[acb->pvt_tbl[pkm]]; 4099 tbl_sz = th_tcam_table_sz(u, pkm); 4100 if (tbl_sz) { 4101 rv = soc_mem_cache_set(u, mem, MEM_BLOCK_ANY, TRUE); 4102 } 4103 } 4104 4105 return rv; 4106 } 4107 4108 void 4109 th_alpm_hit_deinit(int u) 4110 { 4111 int i, pid; 4112 _alpm_cb_t *acb; 4113 4114 if (ALPM_HIT_SKIP(u)) { 4115 return; 4116 } 4117 4118 /* Dist hitbit tables deinit */ 4119 if (ALPMDH(u) != NULL) { 4120 for (i = 0; i < ACB_CNT(u); i++) { 4121 acb = ACB(u, i); 4122 for (pid = 0; pid < ACB_PID_CNT(acb); pid++) { 4123 if (ALPM_HTBL(u, i, pid)) { 4124 if (ALPM_HTBL_CACHE(u, i, pid)) { 4125 soc_cm_sfree(u, ALPM_HTBL_CACHE(u, i, pid)); 4126 ALPM_HTBL_CACHE(u, i, pid) = NULL; 4127 } 4128 if (ALPM_HTBL_MOVE(u, i, pid)) { 4129 soc_cm_sfree(u, ALPM_HTBL_MOVE(u, i, pid)); 4130 ALPM_HTBL_MOVE(u, i, pid) = NULL; 4131 } 4132 if (ALPM_HTBL_MOVE_MASK(u, i, pid)) { 4133 soc_cm_sfree(u, ALPM_HTBL_MOVE_MASK(u, i, pid)); 4134 ALPM_HTBL_MOVE_MASK(u, i, pid) = NULL; 4135 } 4136 alpm_util_free(ALPM_HTBL(u, i, pid)); 4137 ALPM_HTBL(u, i, pid) = NULL; 4138 } 4139 } 4140 } 4141 } 4142 4143 return; 4144 } 4145 4146 /* Initialize ALPM distributed hitbit */ 4147 int 4148 th_alpm_hit_init(int u) 4149 { 4150 int rv = BCM_E_NONE; 4151 int i, pid, index_cnt; 4152 int alloc_sz; 4153 soc_mem_t mem; 4154 _alpm_cb_t *acb; 4155 4156 if (ALPM_HIT_SKIP(u)) { 4157 return rv; 4158 } 4159 4160 /* Initialize bucket Levels hitbit table ctrl */ 4161 for (i = 0; i < ACB_CNT(u); i++) { 4162 acb = ACB(u, i); 4163 mem = th_alpm_hit_tbl_mem[i]; 4164 /* Current implementation is assuming that HIT table entry 4165 is not more than 32 bits (actaully we have as maximum 16 HITBITs). 4166 Otherwise code has to adjust (for multiple words per entry) */ 4167 assert(soc_mem_entry_words(u, mem) == 1); 4168 4169 if (!SOC_WARM_BOOT(u)) { 4170 th_alpm_hw_mem_clear(u, mem); 4171 } 4172 4173 for (pid = 0; pid < ACB_PID_CNT(acb); pid++) { 4174 alloc_sz = sizeof(_alpm_hit_tbl_ctrl_t); 4175 ALPM_ALLOC_EG(ALPM_HTBL(u, i, pid), alloc_sz, "hit_tbl"); 4176 4177 /* logic table index counter (same for HIT table) */ 4178 index_cnt = soc_mem_index_count(u, mem); 4179 alloc_sz = WORDS2BYTES(soc_mem_entry_words(u, mem)) * index_cnt; 4180 ALPM_HTBL_MEM(u, i, pid) = mem; 4181 ALPM_HTBL_IDX_CNT(u, i, pid) = index_cnt; 4182 ALPM_HTBL_SIZE(u, i, pid) = alloc_sz; 4183 ALPM_HTBL_ENT_MOVED(u, i, pid) = FALSE; 4184 ALPM_DMA_ALLOC_EG(u, ALPM_HTBL_CACHE(u, i, pid), 4185 alloc_sz, "hit_cache"); 4186 ALPM_DMA_ALLOC_EG(u, ALPM_HTBL_MOVE(u, i, pid), 4187 alloc_sz, "hit_move"); 4188 ALPM_DMA_ALLOC_EG(u, ALPM_HTBL_MOVE_MASK(u, i, pid), 4189 alloc_sz, "hit_move_mask"); 4190 } 4191 } 4192 4193 return rv; 4194 4195 bad: 4196 th_alpm_hit_deinit(u); 4197 return rv; 4198 } 4199 4200 /* ALPM hitbit cleanup (UNAVAIL for fast delete_all) */ 4201 int 4202 th_alpm_hit_cleanup(int u) 4203 { 4204 return BCM_E_UNAVAIL; 4205 } 4206 4207 4208 alpm_functions_t th_alpm_driver = { 4209 th_alpm_ctrl_init, 4210 th_alpm_ctrl_deinit, 4211 th_alpm_ctrl_cleanup, /* UNAVAIL */ 4212 th_alpm_bkt_bnk_copy, 4213 th_alpm_bkt_bnk_clear, 4214 th_alpm_bkt_pfx_copy, 4215 th_alpm_bkt_pfx_clean, 4216 th_alpm_bkt_pfx_shrink, 4217 th_alpm_bkt_bnk_write, 4218 th_alpm_bkt_def_fmt_get, 4219 th_alpm_bkt_fmt_type_get, 4220 4221 th_alpm_ent_ent_get, 4222 th_alpm_ent_pfx_len_get, 4223 th_alpm_ent_selective_get, 4224 4225 /* TCAM */ 4226 th_tcam_table_sz, 4227 th_tcam_hw_cleanup, /* UNAVAIL */ 4228 th_tcam_entry_x_to_y, 4229 th_tcam_entry_from_cfg, 4230 /* th_tcam_entry_selective_set, */ 4231 /* th_tcam_entry_selective_get, */ 4232 th_tcam_entry_to_cfg, 4233 th_tcam_entry_valid, 4234 th_tcam_entry_valid_set, 4235 th_tcam_entry_vrf_id_get, 4236 th_tcam_entry_pfx_len_get, 4237 th_tcam_entry_to_key, 4238 4239 th_tcam_entry_mode_get, 4240 th_tcam_entry_adata_get, 4241 th_tcam_entry_bdata_get, 4242 4243 /* TCAM/ALPM */ 4244 th_mem_read, 4245 th_mem_write, 4246 4247 /* HITBIT */ 4248 th_alpm_hit_init, 4249 th_alpm_hit_deinit, 4250 th_alpm_hit_cleanup, /* UNAVAIL */ 4251 th_alpm_bkt_hit_get, 4252 th_alpm_bkt_hit_set, 4253 th_alpm_bkt_hit_write, 4254 th_alpm_hit_move_update, 4255 th_alpm_hit_cache_sync, 4256 th_alpm_hit_hw_write, 4257 th_tcam_ent_hit_get, 4258 th_tcam_cache_hit_get, 4259 th_tcam_hit_cache_sync, 4260 4261 /* dump table */ 4262 th_alpm_table_dump, 4263 th_alpm_cap_get, 4264 4265 /* index mapping */ 4266 th_mem_phy_index_get, 4267 }; 4268 4269 #endif /* ALPM_ENABLE */ 4270