alpm_tcam.c (52590B)
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_tcam.c 7 * Purpose: ALPM TCAM management. device independent 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/lpm.h> 20 #include <soc/trident2.h> 21 #include <soc/tomahawk.h> 22 #include <shared/bsl.h> 23 24 #include <shared/util.h> 25 #include <shared/l3.h> 26 27 #if defined(ALPM_ENABLE) 28 29 #include <bcm/l3.h> 30 31 #include <bcm_int/esw/l3.h> 32 #include <bcm_int/esw/firebolt.h> 33 #include <bcm_int/esw/alpm.h> 34 #include <bcm_int/esw/alpm_util.h> 35 36 /* Internal function declaration */ 37 38 #define _TCAM_ZONE_CNT 4 39 #define _TCAM_ZID_CNT 32 40 41 typedef struct _tcam_zone_state_s { 42 int start; /* start index for this prefix length */ 43 int end; /* End index for this prefix length */ 44 int prev; /* Prev (Lo to Hi) prefix length with non zero entry count */ 45 int next; /* Next (Hi to Lo) prefix length with non zero entry count */ 46 int vent; /* valid entries */ 47 int fent; /* free entries */ 48 } _tcam_zone_state_t; 49 50 typedef enum _tz_db_e { 51 _tcamZoneDBInvalid = 0, 52 _tcamZoneDBV4All = 1, 53 _tcamZoneDBV4Prv = 2, 54 _tcamZoneDBV4Glb = 3, 55 _tcamZoneDBV6All = 4, 56 _tcamZoneDBV6Prv = 5, 57 _tcamZoneDBV6Glb = 6, 58 _tcamZoneDBMixAll = 7, 59 _tcamZoneDBMixPrv = 8, 60 _tcamZoneDBMixGlb = 9, 61 _tcamZoneDBCnt = 10, 62 } _tz_db_t; 63 64 char *_tz_db_str[] = { 65 "Invalid", 66 "V4", 67 "V4 Private", 68 "V4 Global ", 69 "V6", 70 "V6 Private", 71 "V6 Global ", 72 "Mixed", 73 "Mixed Private", 74 "Mixed Global ", 75 "Count" 76 }; 77 78 typedef struct _tcam_zone_s { 79 _tcam_zone_state_t *state; 80 81 /* TCAM Zone management */ 82 _tz_db_t tz_db_type; 83 uint16 tz_num_inst; 84 uint16 tz_ent_per_inst; 85 uint16 tz_min_v6; 86 uint16 tz_base_idx; 87 uint16 tz_tbl_sz; 88 89 /* Calculated variables */ 90 uint16 _tz_ent_cnt; 91 uint16 _tz_max_idx; 92 } _tcam_zone_t; 93 94 typedef struct _tcam_ctrl_s { 95 _tcam_zone_t *tcam_zn[_TCAM_ZID_CNT]; 96 int tcam_zn_cnt; 97 } _tcam_ctrl_t; 98 99 typedef struct _tcam_zone_st_s { 100 int cnt_used; 101 int cnt_free; 102 } _tcam_zone_st_t; 103 104 _tcam_ctrl_t *_tcam_control[SOC_MAX_NUM_DEVICES]; 105 106 #define TCAMC(u) (_tcam_control[u]) 107 #define _TCAM_INIT_CHECK(u) (TCAMC(u) != NULL) 108 #define _TCAMZ_CNT(u) (TCAMC(u)->tcam_zn_cnt) 109 #define _TCAMZ(u, zid) (TCAMC(u)->tcam_zn[zid]) 110 #define _TCAM_STATE(u, zid) (_TCAMZ(u, zid)->state) 111 #define _TCAM_STATE_START(u, zid, pfx) (_TCAMZ(u, zid)->state[pfx].start) 112 #define _TCAM_STATE_END(u, zid, pfx) (_TCAMZ(u, zid)->state[pfx].end) 113 #define _TCAM_STATE_PREV(u, zid, pfx) (_TCAMZ(u, zid)->state[pfx].prev) 114 #define _TCAM_STATE_NEXT(u, zid, pfx) (_TCAMZ(u, zid)->state[pfx].next) 115 #define _TCAM_STATE_VENT(u, zid, pfx) (_TCAMZ(u, zid)->state[pfx].vent) 116 #define _TCAM_STATE_FENT(u, zid, pfx) (_TCAMZ(u, zid)->state[pfx].fent) 117 118 #define _TCAMZ_INITED(u, zid) (_TCAMZ(u, zid) && _TCAMZ(u, zid)->tz_num_inst != 0) 119 #define _TCAMZ_DB_TYPE(u, zid) (_TCAMZ(u, zid)->tz_db_type) 120 #define _TCAMZ_PFX_MIN_V6(u, zid) (_TCAMZ(u, zid)->tz_min_v6) 121 #define _TCAMZ_PFX_ENT_PER_INST(u, zid) (_TCAMZ(u, zid)->tz_ent_per_inst) 122 #define _TCAMZ_PFX_BASE_IDX(u, zid) (_TCAMZ(u, zid)->tz_base_idx) 123 #define _TCAMZ_PFX_TBL_SZ(u, zid) (_TCAMZ(u, zid)->tz_tbl_sz) 124 #define _TCAMZ_PFX_MAX_ENTS(u, zid) (_TCAMZ(u, zid)->_tz_ent_cnt) 125 #define _TCAMZ_PFX_MAX_IDX(u, zid) (_TCAMZ(u, zid)->_tz_max_idx) 126 127 #define _PFX_IS_PKM_64B(u, zid, pfx) ((pfx) % _TCAMZ_PFX_ENT_PER_INST(u, zid) \ 128 >= _TCAMZ_PFX_MIN_V6(u, zid) && \ 129 (pfx) != _TCAMZ_PFX_MAX_IDX(u, zid)) 130 /* 131 * P: Paired, Z: Zoned, MC: IPMC, VRF 0: Global. 132 * PKM: 32B(0) !32B(1) 133 * 134 * ------------------------------------------ 135 * | MC | P | Z | VRF | PKM | Zone | Inst | 136 * ------------------------------------------ 137 * | 0 | 0 | 0 | 0 | 32B | Mix | 0,2 | 0b00000 0 ZoneA 138 * | 0 | 0 | 0 | 0 | 64B | Mix | 0,2 | 0b00001 1 -->ZoneA 139 * | 0 | 0 | 0 | 1 | 32B | Mix | 1 | 0b00010 2 -->ZoneA 140 * | 0 | 0 | 0 | 1 | 64B | Mix | 1 | 0b00011 3 -->ZoneA 141 * | 0 | 0 | 1 | 0 | 32B | MxG | 0,1 | 0b00100 4 B 142 * | 0 | 0 | 1 | 0 | 64B | MxG | 0,1 | 0b00101 5 -->ZoneB 143 * | 0 | 0 | 1 | 1 | 32B | MxP | 0 | 0b00110 6 C 144 * | 0 | 0 | 1 | 1 | 64B | MxP | 0 | 0b00111 7 -->ZoneC 145 * | 0 | 1 | 0 | 0 | 32B | V4 | 0,2 | 0b01000 8 D 146 * | 0 | 1 | 0 | 0 | 128 | V6 | 0,2 | 0b01001 9 E 147 * | 0 | 1 | 0 | 1 | 32B | V4 | 1 | 0b01010 10 -->ZoneD 148 * | 0 | 1 | 0 | 1 | 128 | V6 | 1 | 0b01011 11 -->ZoneE 149 * | 0 | 1 | 1 | 0 | 32B | V4G | 0,1 | 0b01100 12 F 150 * | 0 | 1 | 1 | 0 | 128 | V6G | 0,1 | 0b01101 13 G 151 * | 0 | 1 | 1 | 1 | 32B | V4P | 0 | 0b01110 14 H 152 * | 0 | 1 | 1 | 1 | 128 | V6P | 0 | 0b01111 15 I 153 * ------------------------------------------ 154 * ------------------------------------------ 155 * | MC | P | Z | VRF | PKM | Zone | Inst | 156 * ------------------------------------------ 157 * | 1 | 0 | 0 | 0 | 32B | Mix | 3,5 | 0b10000 -->ZoneA 158 * | 1 | 0 | 0 | 0 | 64B | Mix | 3,5 | 0b10001 -->ZoneA 159 * | 1 | 0 | 0 | 1 | 32B | Mix | 4 | 0b10010 -->ZoneA 160 * | 1 | 0 | 0 | 1 | 64B | Mix | 4 | 0b10011 -->ZoneA 161 * | 1 | 0 | 1 | 0 | 32B | MxP | 1,3 | 0b10100 -->ZoneC 162 * | 1 | 0 | 1 | 0 | 64B | MxP | 1,3 | 0b10101 -->ZoneC 163 * | 1 | 0 | 1 | 1 | 32B | MxP | 2 | 0b10110 -->ZoneC 164 * | 1 | 0 | 1 | 1 | 64B | MxP | 2 | 0b10111 -->ZoneC 165 * | 1 | 1 | 0 | 0 | 32B | V4 | 3,5 | 0b11000 -->ZoneD 166 * | 1 | 1 | 0 | 0 | 128 | V6 | 3,5 | 0b11001 -->ZoneE 167 * | 1 | 1 | 0 | 1 | 32B | V4 | 4 | 0b11010 -->ZoneD 168 * | 1 | 1 | 0 | 1 | 128 | V6 | 4 | 0b11011 -->ZoneE 169 * | 1 | 1 | 1 | 0 | 32B | V4P | 1,3 | 0b11100 -->ZoneH 170 * | 1 | 1 | 1 | 0 | 128 | V6P | 1,3 | 0b11101 -->ZoneI 171 * | 1 | 1 | 1 | 1 | 32B | V4P | 2 | 0b11110 -->ZoneH 172 * | 1 | 1 | 1 | 1 | 128 | V6P | 2 | 0b11111 -->ZoneI 173 * ------------------------------------------ 174 */ 175 176 /* Zone combination count */ 177 typedef enum tz_comb_e { 178 tZoneInvalid, 179 tZoneAC64, /* 1 */ 180 tZoneBP64Glb, /* 2 */ 181 tZoneCP64Prv, /* 3 */ 182 tZoneDC128V4, /* 4 */ 183 tZoneEC128V6, /* 5 */ 184 tZoneFP128V4Glb, /* 6 */ 185 tZoneGP128V6Glb, /* 7 */ 186 tZoneHP128V4Prv, /* 8 */ 187 tZoneIP128V6Prv, /* 9 */ 188 tZone__Count 189 } tz_comb_t; 190 191 static _tz_db_t tcam_zone_type[tZone__Count] = { 192 _tcamZoneDBInvalid, 193 _tcamZoneDBMixAll, /* ZoneA, Combined-64 */ 194 _tcamZoneDBMixGlb, /* ZoneB, Parallel-64 (Global) */ 195 _tcamZoneDBMixPrv, /* ZoneC, Parallel-64 (Private) */ 196 _tcamZoneDBV4All, /* ZoneD, Combined-128 (V4) */ 197 _tcamZoneDBV6All, /* ZoneE, Combined-128 (V6) */ 198 _tcamZoneDBV4Glb, /* ZoneF, Parallel-128 (V4 Global) */ 199 _tcamZoneDBV6Glb, /* ZoneG, Parallel-128 (V6 Global) */ 200 _tcamZoneDBV4Prv, /* ZoneH, Parallel-128 (V4 Private) */ 201 _tcamZoneDBV6Prv, /* ZoneI, Parallel-128 (V6 Private) */ 202 }; 203 204 /* Number of instance in the zone */ 205 static uint16 tcam_zone_num_inst[tZone__Count] = { 206 0, 207 3, /* ZoneA */ 208 2, /* ZoneB */ 209 1, /* ZoneC */ 210 3, /* ZoneD */ 211 3, /* ZoneE */ 212 2, /* ZoneF */ 213 2, /* ZoneG */ 214 1, /* ZoneH */ 215 1, /* ZoneI */ 216 }; 217 218 static uint16 tcam_zone_num_inst_ipmc_war[tZone__Count] = { 219 0, 220 6, /* ZoneA */ 221 2, /* ZoneB */ 222 4, /* ZoneC */ 223 6, /* ZoneD */ 224 6, /* ZoneE */ 225 2, /* ZoneF */ 226 2, /* ZoneG */ 227 4, /* ZoneH */ 228 4, /* ZoneI */ 229 }; 230 231 /* 4 means 4 combinations for Pair_128_mode + alpm_mode 232 * _TCAM_ZONE_CNT: 233 * bit1 : 0 Glb, 1 Prv 234 * bit0 : 0 V4, 1 V6 235 */ 236 static tz_comb_t tz_conf[4][_TCAM_ZONE_CNT] = { 237 /* Combined-64 */ 238 {tZoneAC64, tZoneInvalid, tZoneInvalid, tZoneInvalid}, 239 /* Combined-128 bit0 V4|V6 */ 240 {tZoneDC128V4, tZoneEC128V6, tZoneInvalid, tZoneInvalid}, 241 /* Parallel-64 bit1 Glb|Prv */ 242 {tZoneBP64Glb, tZoneInvalid, tZoneCP64Prv, tZoneInvalid}, 243 /* Parallel-128 bit1 Glb|Prv bit0 V4|V6 */ 244 {tZoneFP128V4Glb, tZoneGP128V6Glb, tZoneHP128V4Prv, tZoneIP128V6Prv}, 245 }; 246 247 #define _TCAMZ_ZID_TO_ZN(zid) (zid & 0x3) 248 #define _TCAMZ_ZID_MAKE_FROM_ZN(mc, p, z, zn) \ 249 (!!(mc) << 4 | !!(p) << 3 | !!(z) << 2 | (zn & 0x3)) 250 #define _TCAMZ_ZID_MAKE(mc, p, z, vrf, pkm) \ 251 (!!(mc) << 4 | !!(p) << 3 | !!(z) << 2 | !!(vrf) << 1 | !!(pkm)) 252 #define _TCAMZ_ZID_IS_V6_ONLY(zid) ((zid) & 0x1) 253 254 static _tcam_zone_t tz_ctrl[SOC_MAX_NUM_DEVICES][_TCAM_ZONE_CNT]; 255 256 /* 257 * TCAM (1 Zone) >>>> Combined + 64B. 258 * --------------- index 0 259 * | | 260 * | Zone 0 | ---- _tcamZoneDBMixAll 261 * | | 262 * --------------- index size-1 263 * 264 * TCAM (2 Zones) >>>> Parallel + 64B. 265 * --------------- index 0 266 * | Zone 0 | ---- _tcamZoneDBMixPrv 267 * --------------- index size/2-1 268 * | Zone 1 | ---- _tcamZoneDBMixGlb 269 * --------------- index size-1 270 * 271 * TCAM (2 Zones) >>>> Combined + 128B. 272 * --------------- index 0 273 * | Zone 0 | ---- _tcamZoneDBV4All 274 * --------------- index size(L3_DEFIP_PAIR_128)-1 275 * --------------- index 0 276 * | Zone 1 | ---- _tcamZoneDBV6All 277 * --------------- index size(L3_DEFIP)-1 278 * 279 * TCAM (4 Zones) >>>> Parallel + 128B. 280 * --------------- index 0 281 * | Zone 0 | ---- _tcamZoneDBV4Prv 282 * --------------- index size(L3_DEFIP_PAIR_128)/2-1 283 * | Zone 1 | ---- _tcamZoneDBV4Glb 284 * --------------- index size(L3_DEFIP_PAIR_128)-1 285 * --------------- index 0 286 * | Zone 2 | ---- _tcamZoneDBV6Prv 287 * --------------- index size(L3_DEFIP)/2-1 288 * | Zone 3 | ---- _tcamZoneDBV6Glb 289 * --------------- index size(L3_DEFIP)-1 290 */ 291 void 292 _tcam_zone_ctrl_config(int u, int zn, _tz_db_t db_type, uint16 num_inst, 293 uint16 base_idx, uint16 tbl_sz) 294 { 295 uint16 ent_per_inst = 0, v6_min = 0; 296 _tcam_zone_t *tz; 297 298 tz = &tz_ctrl[u][zn]; 299 300 switch (db_type) { 301 case _tcamZoneDBV4All: 302 case _tcamZoneDBV4Prv: 303 case _tcamZoneDBV4Glb: 304 ent_per_inst = 32 + 2 + 1; 305 v6_min = ent_per_inst + 1; 306 break; 307 case _tcamZoneDBV6All: 308 case _tcamZoneDBV6Prv: 309 case _tcamZoneDBV6Glb: 310 ent_per_inst = 128 + 2 + 1; 311 v6_min = 0; 312 break; 313 case _tcamZoneDBMixAll: 314 case _tcamZoneDBMixPrv: 315 case _tcamZoneDBMixGlb: 316 ent_per_inst = 64 + 32 + 2 + 1; 317 v6_min = 32 + 1; 318 break; 319 default: 320 assert(0); 321 break; 322 } 323 324 tz->tz_db_type = db_type; 325 tz->tz_num_inst = num_inst; 326 tz->tz_ent_per_inst = ent_per_inst; 327 tz->tz_min_v6 = v6_min; 328 tz->tz_tbl_sz = tbl_sz; 329 tz->tz_base_idx = base_idx; 330 tz->_tz_ent_cnt = num_inst * ent_per_inst; 331 tz->_tz_max_idx = tz->_tz_ent_cnt - 1; 332 333 return ; 334 } 335 336 int 337 _tcam_zone_db_type_to_pkm(int u, _tz_db_t db_type) 338 { 339 int pkm = ALPM_PKM_32B; 340 switch (db_type) { 341 case _tcamZoneDBV6All: 342 case _tcamZoneDBV6Prv: 343 case _tcamZoneDBV6Glb: 344 pkm = ALPM_PKM_128; 345 break; 346 default: 347 break; 348 } 349 350 return pkm; 351 } 352 353 int 354 _tcam_zone_init(int u) 355 { 356 int rv = BCM_E_NONE, zn, zid, j, comb; 357 int max_pfx_len, pfx_st_sz, zone_cnt = 0; 358 359 int pkm; 360 _tz_db_t db_type; 361 uint16 num_inst; 362 uint16 base_idx; 363 int tbl_sz; 364 365 comb = !!ALPM_TCAM_ZONED(u) << 1 | !!ALPM_128B(u); 366 for (zn = 0; zn < _TCAM_ZONE_CNT; zn++) { 367 tz_comb_t tzc = tz_conf[comb][zn]; 368 if (tzc == tZoneInvalid) { 369 continue; 370 } 371 372 db_type = tcam_zone_type[tzc]; 373 pkm = _tcam_zone_db_type_to_pkm(u, db_type); 374 tbl_sz = tcam_table_size(u, pkm) >> !!ALPM_TCAM_ZONED(u); 375 if (db_type == _tcamZoneDBV6Glb || 376 db_type == _tcamZoneDBV4Glb || 377 db_type == _tcamZoneDBMixGlb) { 378 base_idx = tbl_sz; 379 } else { 380 base_idx = 0; 381 } 382 383 num_inst = (soc_feature(u, soc_feature_td3_lpm_ipmc_war)) ? 384 tcam_zone_num_inst_ipmc_war[tzc] : 385 tcam_zone_num_inst[tzc]; 386 _tcam_zone_ctrl_config(u, zn, db_type, num_inst, 387 base_idx, (uint16)tbl_sz); 388 zone_cnt ++; 389 } 390 391 TCAMC(u)->tcam_zn_cnt = zone_cnt; 392 393 /* Mapping to tz_ctrl(uc) */ 394 for (zn = 0; zn < _TCAM_ZONE_CNT; zn++) { 395 int zn2 = zn; 396 tz_comb_t tzc; 397 398 tzc = tz_conf[comb][zn]; 399 zid = _TCAMZ_ZID_MAKE_FROM_ZN(0, ALPM_128B(u), ALPM_TCAM_ZONED(u), zn); 400 if (tzc == tZoneInvalid) { 401 /* IP type don't care */ 402 if (!ALPM_128B(u) && (zn & 0x1)) { 403 zn2 = zn2 & 0x2; 404 } 405 /* VRF type don't care */ 406 if (!ALPM_TCAM_ZONED(u) && (zn & 0x2)) { 407 zn2 = zn2 & 0x1; 408 } 409 } 410 _TCAMZ(u, zid) = &tz_ctrl[u][zn2]; 411 ALPM_VERB(("uc zid %d -> zn %d\n", zid, zn2)); 412 } 413 414 if (soc_feature(u, soc_feature_td3_lpm_ipmc_war)) { 415 for (zn = 0; zn < _TCAM_ZONE_CNT; zn++) { 416 int zn2 = zn; 417 418 zid = _TCAMZ_ZID_MAKE_FROM_ZN(1, ALPM_128B(u), ALPM_TCAM_ZONED(u), zn); 419 420 /* IP type don't care */ 421 if (!ALPM_128B(u) && (zn & 0x1)) { 422 zn2 = zn2 & 0x2; 423 } 424 425 if (ALPM_TCAM_ZONED(u)) { 426 /* VRF type don't care */ 427 if (!(zn & 0x2)) { 428 zn2 = zn2 | 0x2; 429 } 430 } else { 431 /* VRF type don't care */ 432 if (zn & 0x2) { 433 zn2 = zn2 & 0x1; 434 } 435 } 436 _TCAMZ(u, zid) = &tz_ctrl[u][zn2]; 437 ALPM_VERB(("mc zid %d -> zn %d\n", zid, zn2)); 438 } 439 } 440 441 /* TCAM State init */ 442 for (zn = 0; zn < _TCAM_ZONE_CNT; zn++) { 443 int max_idx, zid; 444 445 zid = _TCAMZ_ZID_MAKE_FROM_ZN(0, ALPM_128B(u), ALPM_TCAM_ZONED(u), zn); 446 if (_TCAMZ(u, zid) == NULL) { 447 continue; 448 } 449 450 max_idx = _TCAMZ_PFX_MAX_IDX(u, zid); 451 max_pfx_len = _TCAMZ_PFX_MAX_ENTS(u, zid); 452 pfx_st_sz = sizeof(_tcam_zone_state_t) * max_pfx_len; 453 ALPM_REALLOC_EG(_TCAM_STATE(u, zid), pfx_st_sz, "LPM_pfx_info"); 454 for (j = 0; j < max_pfx_len; j++) { 455 _TCAM_STATE_START(u, zid, j) = -1; 456 _TCAM_STATE_END(u, zid, j) = -1; 457 _TCAM_STATE_PREV(u, zid, j) = -1; 458 _TCAM_STATE_NEXT(u, zid, j) = -1; 459 _TCAM_STATE_VENT(u, zid, j) = 0; 460 _TCAM_STATE_FENT(u, zid, j) = 0; 461 } 462 463 _TCAM_STATE_FENT(u, zid, max_idx) = _TCAMZ_PFX_TBL_SZ(u, zid); 464 _TCAM_STATE_END(u, zid, max_idx) = _TCAMZ_PFX_BASE_IDX(u, zid) - 1; 465 } 466 467 bad: 468 return rv; 469 } 470 471 static int 472 _tcam_zone_zid_get(int u, int vrf, int ipt, int in_pair_mode, int mc) 473 { 474 int zid; 475 mc = soc_feature(u, soc_feature_td3_lpm_ipmc_war) && mc; 476 zid = _TCAMZ_ZID_MAKE(mc, in_pair_mode, ALPM_TCAM_ZONED(u), 477 !ALPM_VRF_IS_GBL(u, vrf), ipt); 478 return zid; 479 } 480 481 int 482 _tcam_zone_inst_id_get(int u, int vrf, int mc) 483 { 484 int inst_id; 485 486 if (ALPM_TCAM_ZONED(u)) { 487 if (soc_feature(u, soc_feature_td3_lpm_ipmc_war) && mc) { 488 switch (vrf) { 489 case BCM_L3_VRF_GLOBAL: 490 inst_id = 1; 491 break; 492 case BCM_L3_VRF_OVERRIDE: 493 inst_id = 3; 494 break; 495 default: 496 inst_id = 2; 497 break; 498 } 499 } else { 500 switch (vrf) { 501 case BCM_L3_VRF_GLOBAL: 502 inst_id = 0; 503 break; 504 case BCM_L3_VRF_OVERRIDE: 505 inst_id = 1; 506 break; 507 default: 508 inst_id = 0; 509 break; 510 } 511 } 512 } else { 513 if (soc_feature(u, soc_feature_td3_lpm_ipmc_war) && mc) { 514 switch (vrf) { 515 case BCM_L3_VRF_GLOBAL: 516 inst_id = 3; 517 break; 518 case BCM_L3_VRF_OVERRIDE: 519 inst_id = 5; 520 break; 521 default: 522 inst_id = 4; 523 break; 524 } 525 } else { 526 switch (vrf) { 527 case BCM_L3_VRF_GLOBAL: 528 inst_id = 0; 529 break; 530 case BCM_L3_VRF_OVERRIDE: 531 inst_id = 2; 532 break; 533 default: 534 inst_id = 1; 535 break; 536 } 537 } 538 } 539 540 return inst_id; 541 } 542 543 static void 544 _tcam_zone_status(int u, int zid, _tcam_zone_st_t *tz_st) 545 { 546 int i, max_pfx_len; 547 548 sal_memset(tz_st, 0, sizeof(*tz_st)); 549 max_pfx_len = _TCAMZ_PFX_MAX_IDX(u, zid); 550 for (i = max_pfx_len; i >= 0 ; i--) { 551 if (i != _TCAMZ_PFX_MAX_IDX(u, zid) && (_TCAM_STATE_START(u, zid, i) == -1)) { 552 continue; 553 } 554 555 tz_st->cnt_free += _TCAM_STATE_FENT(u, zid, i); 556 tz_st->cnt_used += _TCAM_STATE_VENT(u, zid, i); 557 } 558 559 return ; 560 } 561 562 static int 563 _tcam_trie_lookup(int u, _bcm_defip_cfg_t *lpm_cfg, int *key_index) 564 { 565 int rv = BCM_E_NOT_FOUND; 566 alpm_lib_trie_t *pvt_trie; 567 _alpm_pvt_node_t *pvt_node; 568 569 int ipt = ALPM_LPM_IPT(u, lpm_cfg); 570 int vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg); 571 572 pvt_trie = ACB_PVT_TRIE(ACB_TOP(u), vrf_id, ipt); 573 if (pvt_trie != NULL) { 574 rv = alpm_lib_trie_search(pvt_trie, lpm_cfg->user_data, 575 lpm_cfg->defip_sub_len, 576 (alpm_lib_trie_node_t **)&pvt_node); 577 if (BCM_SUCCESS(rv)) { 578 *key_index = PVT_IDX(pvt_node); 579 } 580 } 581 return rv; 582 } 583 584 static int 585 _tcam_trie_update(int u, uint32 *key, int len, int vrf_id, int ipt, int key_idx) 586 { 587 int rv = BCM_E_NOT_FOUND; 588 alpm_lib_trie_t *pvt_trie; 589 _alpm_pvt_node_t *pvt_node; 590 591 pvt_trie = ACB_PVT_TRIE(ACB_TOP(u), vrf_id, ipt); 592 if (pvt_trie != NULL) { 593 rv = alpm_lib_trie_search(pvt_trie, key, len, (alpm_lib_trie_node_t **)&pvt_node); 594 if (BCM_SUCCESS(rv)) { 595 PVT_IDX(pvt_node) = key_idx; 596 } 597 } 598 599 return rv; 600 } 601 602 int 603 _tcam_trie_update_by_cfg(int u, _bcm_defip_cfg_t *lpm_cfg, int key_idx) 604 { 605 int rv; 606 int ipt = ALPM_LPM_IPT(u, lpm_cfg); 607 int vrf_id = ALPM_LPM_VRF_ID(u, lpm_cfg); 608 609 rv = _tcam_trie_update(u, lpm_cfg->user_data, lpm_cfg->defip_sub_len, 610 vrf_id, ipt, key_idx); 611 612 return rv; 613 } 614 615 int 616 tcam_entry_valid(int u, int pkm, void *e, int sub_idx) 617 { 618 int vld = 0; 619 620 vld = ALPM_DRV(u)->tcam_entry_valid(u, pkm, e, sub_idx); 621 622 return vld; 623 } 624 625 static int 626 _tcam_entry_valid_set(int u, int pkm, void *e, int sub_idx, int val) 627 { 628 int rv = BCM_E_NONE; 629 630 rv = ALPM_DRV(u)->tcam_entry_valid_set(u, pkm, e, sub_idx, val); 631 632 return rv; 633 } 634 635 static int 636 _tcam_trie_update_by_ent(int u, int pkm, void *e, int hw_idx) 637 { 638 int i, rv = BCM_E_NONE; 639 uint32 pfx[5]; 640 int pfx_len, vrf_id; 641 642 if (pkm == ALPM_PKM_32B) { 643 /* For IPv4(32B packing mode), check and update both 2 entries */ 644 for (i = 0; i < 2; i++) { 645 if (tcam_entry_valid(u, pkm, e, i)) { 646 ALPM_IER(tcam_entry_vrf_id_get(u, pkm, e, i, &vrf_id)); 647 ALPM_IER(tcam_entry_pfx_len_get(u, pkm, e, i, &pfx_len)); 648 ALPM_IER(alpm_trie_ent_to_pfx(u, pkm, e, i, pfx_len, pfx)); 649 rv = _tcam_trie_update(u, pfx, pfx_len, vrf_id, ALPM_PKM2IPT(pkm), 650 hw_idx << 1 | i); 651 } 652 } 653 } else { 654 if (tcam_entry_valid(u, pkm, e, 0)) { 655 ALPM_IER(tcam_entry_vrf_id_get(u, pkm, e, 0, &vrf_id)); 656 ALPM_IER(tcam_entry_pfx_len_get(u, pkm, e, 0, &pfx_len)); 657 ALPM_IER(alpm_trie_ent_to_pfx(u, pkm, e, 0, pfx_len, pfx)); 658 rv = _tcam_trie_update(u, pfx, pfx_len, vrf_id, ALPM_PKM2IPT(pkm), hw_idx); 659 } 660 } 661 662 return rv; 663 } 664 665 /********************************************** 666 * TCAM Management functions * 667 */ 668 669 /* 670 * TCAM based PIVOT implementation. Each table entry can hold two IPV4 PIVOTs or 671 * one IPV6 PIVOT entry. VRF independent routes placed at the beginning or 672 * at the end of table based on application provided entry vrf id 673 * (BCM_L3_VRF_OVERRIDE/BCM_L3_VRF_GLOBAL). 674 * 675 * _PFX_MAX_INDEX 676 * lpm_prefix_index[98].begin ---> =============================== 677 * == == 678 * == 0 == 679 * lpm_prefix_index[98].end ---> =============================== 680 * 681 * lpm_prefix_index[97].begin ---> =============================== 682 * == == 683 * == IPV6 Prefix Len = 64 == 684 * lpm_prefix_index[97].end ---> =============================== 685 * 686 * 687 * 688 * lpm_prefix_index[x].begin ---> =============================== 689 * == == 690 * == == 691 * lpm_prefix_index[x].end ---> =============================== 692 * 693 * 694 * _PFX_MIN_V6 695 * lpm_prefix_index[33].begin ---> =============================== 696 * == == 697 * == IPV6 Prefix Len = 0 == 698 * lpm_prefix_index[33].end ---> =============================== 699 * 700 * 701 * lpm_prefix_index[32].begin ---> =============================== 702 * == == 703 * == IPV4 Prefix Len = 32 == 704 * lpm_prefix_index[32].end ---> =============================== 705 * 706 * 707 * 708 * lpm_prefix_index[0].begin ---> =============================== 709 * == == 710 * == IPV4 Prefix Len = 0 == 711 * lpm_prefix_index[0].end ---> =============================== 712 */ 713 714 int 715 tcam_entry_vrf_id_get(int u, int pkm, void *e, int sub_idx, int *vrf_id) 716 { 717 int rv = BCM_E_UNAVAIL; 718 719 rv = ALPM_DRV(u)->tcam_entry_vrf_id_get(u, pkm, e, sub_idx, vrf_id); 720 721 return rv; 722 } 723 724 int 725 tcam_entry_pfx_len_get(int u, int pkm, void *e, int sub_idx, int *pfx_len) 726 { 727 int rv = BCM_E_UNAVAIL; 728 729 rv = ALPM_DRV(u)->tcam_entry_pfx_len_get(u, pkm, e, sub_idx, pfx_len); 730 731 return rv; 732 } 733 734 /* 735 * x | y 736 * -------------------- 737 * 0 | 0 : entry0_to_0 738 * 0 | 1 : entry0_to_1 739 * 1 | 0 : entry1_to_0 740 * 1 | 1 : entry1_to_1 741 * src and dst can be same 742 */ 743 static int 744 _tcam_entry_x_to_y(int u, int pkm, void *src, void *dst, 745 int copy_hit, int x, int y) 746 { 747 int rv = BCM_E_UNAVAIL; 748 rv = ALPM_DRV(u)->tcam_entry_x_to_y(u, pkm, src, dst, copy_hit, x, y); 749 750 return rv; 751 } 752 753 static int 754 _tcam_entry_from_cfg(int u, int pkm, _bcm_defip_cfg_t *lpm_cfg, void *e, int x, uint32 write_flags) 755 { 756 int rv = BCM_E_UNAVAIL; 757 758 rv = ALPM_DRV(u)->tcam_entry_from_cfg(u, pkm, lpm_cfg, e, x, write_flags); 759 return rv; 760 } 761 762 int 763 tcam_entry_to_cfg(int u, int pkm, void *e, int x, _bcm_defip_cfg_t *lpm_cfg) 764 { 765 int rv = BCM_E_UNAVAIL; 766 767 rv = ALPM_DRV(u)->tcam_entry_to_cfg(u, pkm, e, x, lpm_cfg); 768 return rv; 769 } 770 771 int 772 tcam_entry_read(int u, int pkm, void *e, int index, int s_index) 773 { 774 int rv = BCM_E_UNAVAIL; 775 _alpm_cb_t *acb; 776 777 acb = ACB_TOP(u); 778 rv = ALPM_DRV(u)->mem_entry_read(u, acb, acb->pvt_tbl[pkm], index, e, FALSE); 779 780 return rv; 781 } 782 783 int 784 tcam_entry_read_no_cache(int u, int pkm, void *e, int index, int s_index) 785 { 786 int rv = BCM_E_UNAVAIL; 787 _alpm_cb_t *acb; 788 789 acb = ACB_TOP(u); 790 rv = ALPM_DRV(u)->mem_entry_read(u, acb, acb->pvt_tbl[pkm], index, e, TRUE); 791 792 return rv; 793 } 794 795 int 796 _tcam_entry_write(int u, int pkm, void *e, int index, int s_index) 797 { 798 int rv = BCM_E_UNAVAIL; 799 _alpm_cb_t *acb; 800 801 acb = ACB_TOP(u); 802 rv = ALPM_DRV(u)->mem_entry_write(u, acb, NULL, acb->pvt_tbl[pkm], index, e); 803 804 return rv; 805 } 806 807 /* 808 * key[4] = {key[0], key[1], key[2], key[3]} 809 * ipv4: key[4] = 810 * {IP_ADDR0f, 0, 0, 0} 811 * ipv6-64: key[4] = 812 * {0, 0, IP_ADDR0f, IP_ADDR1f} 813 * ipv6-128: key[4] = 814 * {IP_ADDR0_LWRf, IP_ADDR1_LWRf, IP_ADDR0_UPRf, IP_ADDR1_UPRf} 815 */ 816 int 817 tcam_entry_to_key(int u, int pkm, void *e, int sub_idx, uint32 *key) 818 { 819 int rv = BCM_E_UNAVAIL; 820 821 rv = ALPM_DRV(u)->tcam_entry_to_key(u, pkm, e, sub_idx, key); 822 823 return rv; 824 } 825 826 /* 827 * Create a slot for the new entry rippling the entries if required 828 */ 829 static int 830 _tcam_entry_shift(int u, int pkm, int from_ent, int to_ent) 831 { 832 int rv; 833 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 834 835 ALPM_IER(tcam_entry_read(u, pkm, e, from_ent, from_ent)); 836 rv = _tcam_trie_update_by_ent(u, pkm, e, to_ent); 837 if (BCM_SUCCESS(rv)) { 838 rv = _tcam_entry_write(u, pkm, e, to_ent, from_ent); 839 } 840 841 return rv; 842 } 843 844 /* 845 * Lower index -> Higher index 846 * Higher priority -> Lower priority 847 * L3_DEFIP_PAIR_128 -> L3_DEFIP 848 * -------- 0 849 * | | 850 * | | | 851 * | | \|/ 852 * | | * 853 * | | 854 * -------- 1023 855 */ 856 static int 857 _tcam_shift_pfx_up(int u, int pfx, int zid) 858 { 859 int pkm; 860 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 861 int from_ent; 862 int to_ent; 863 uint32 v0, v1; 864 int rv = BCM_E_NONE; 865 866 to_ent = _TCAM_STATE_END(u, zid, pfx) + 1; 867 868 pkm = _tcam_zone_db_type_to_pkm(u, _TCAMZ_DB_TYPE(u, zid)); 869 if (pkm != ALPM_PKM_128) { 870 pkm = _PFX_IS_PKM_64B(u, zid, pfx); 871 } 872 873 if (pkm == ALPM_PKM_32B) { 874 from_ent = _TCAM_STATE_END(u, zid, pfx); 875 ALPM_IER(tcam_entry_read(u, pkm, e, from_ent, from_ent)); 876 v0 = tcam_entry_valid(u, pkm, e, 0); 877 v1 = tcam_entry_valid(u, pkm, e, 1); 878 879 if ((v0 == 0) || (v1 == 0)) { 880 /* Last entry is half full -> keep it last. */ 881 _tcam_trie_update_by_ent(u, pkm, e, to_ent); 882 ALPM_IER(_tcam_entry_write(u, pkm, e, to_ent, from_ent)); 883 to_ent--; 884 } 885 } 886 887 from_ent = _TCAM_STATE_START(u, zid, pfx); 888 if (from_ent != to_ent) { 889 ALPM_IER(_tcam_entry_shift(u, pkm, from_ent, to_ent)); 890 } 891 _TCAM_STATE_START(u, zid, pfx) += 1; 892 _TCAM_STATE_END(u, zid, pfx) += 1; 893 894 return rv; 895 } 896 897 /* 898 * Higher index -> Lower index 899 * Lower priority -> Higher priority 900 * L3_DEFIP -> L3_DEFIP_PAIR_128 901 * 902 * -------- 0 903 * | | 904 * | | * 905 * | | /|\ 906 * | | | 907 * | | 908 * -------- 1023 909 */ 910 static int 911 _tcam_shift_pfx_down(int u, int pfx, int zid) 912 { 913 int pkm; 914 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 915 int from_ent; 916 int to_ent; 917 int prev_ent; 918 uint32 v0, v1; 919 int rv = BCM_E_NONE; 920 921 to_ent = _TCAM_STATE_START(u, zid, pfx) - 1; 922 923 /* Don't move empty prefix . */ 924 if (_TCAM_STATE_VENT(u, zid, pfx) == 0) { 925 _TCAM_STATE_START(u, zid, pfx) = to_ent; 926 _TCAM_STATE_END(u, zid, pfx) = to_ent - 1; 927 return BCM_E_NONE; 928 } 929 930 pkm = _tcam_zone_db_type_to_pkm(u, _TCAMZ_DB_TYPE(u, zid)); 931 if (pkm != ALPM_PKM_128) { 932 pkm = _PFX_IS_PKM_64B(u, zid, pfx); 933 } 934 935 if (pkm == ALPM_PKM_32B && 936 _TCAM_STATE_END(u, zid, pfx) != _TCAM_STATE_START(u, zid, pfx)) { 937 938 from_ent = _TCAM_STATE_END(u, zid, pfx); 939 940 ALPM_IER(tcam_entry_read(u, pkm, e, from_ent, from_ent)); 941 v0 = tcam_entry_valid(u, pkm, e, 0); 942 v1 = tcam_entry_valid(u, pkm, e, 1); 943 944 if ((v0 == 0) || (v1 == 0)) { 945 /* Last entry is half full -> keep it last. */ 946 /* Shift entry before last to start - 1 position. */ 947 prev_ent = from_ent - 1; 948 ALPM_IER(_tcam_entry_shift(u, pkm, prev_ent, to_ent)); 949 950 _tcam_trie_update_by_ent(u, pkm, e, prev_ent); 951 ALPM_IER(_tcam_entry_write(u, pkm, e, prev_ent, from_ent)); 952 } else { 953 /* Last entry is full -> just shift it to start - 1 position. */ 954 _tcam_trie_update_by_ent(u, pkm, e, to_ent); 955 ALPM_IER(_tcam_entry_write(u, pkm, e, to_ent, from_ent)); 956 } 957 958 } else { 959 from_ent = _TCAM_STATE_END(u, zid, pfx); 960 ALPM_IER(_tcam_entry_shift(u, pkm, from_ent, to_ent)); 961 } 962 _TCAM_STATE_START(u, zid, pfx) -= 1; 963 _TCAM_STATE_END(u, zid, pfx) -= 1; 964 965 return rv; 966 } 967 968 /* 969 * Create a slot for the new entry rippling the entries if required 970 * returned update=1 if half-free entry, update=0 if full-free entry. 971 */ 972 static int 973 _tcam_free_slot_create(int u, int pkm, int zid, int pfx, int *free_slot, int *update) 974 { 975 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 976 int prev_pfx; 977 int next_pfx; 978 int free_pfx; 979 int curr_pfx; 980 int from_ent; 981 uint32 v0, v1; 982 983 if (_TCAM_STATE_VENT(u, zid, pfx) == 0) { 984 /* 985 * Find the prefix position. Only prefix with valid 986 * entries are in the list. 987 * next -> high to low prefix. low to high index 988 * prev -> low to high prefix. high to low index 989 * Unused prefix length _PFX_MAX_INDEX is the head of the 990 * list and is node corresponding to this is always 991 * present. 992 */ 993 curr_pfx = _TCAMZ_PFX_MAX_IDX(u, zid); 994 while (_TCAM_STATE_NEXT(u, zid, curr_pfx) > pfx) { 995 curr_pfx = _TCAM_STATE_NEXT(u, zid, curr_pfx); 996 } 997 /* Insert the new prefix */ 998 next_pfx = _TCAM_STATE_NEXT(u, zid, curr_pfx); 999 if (next_pfx != -1) { 1000 _TCAM_STATE_PREV(u, zid, next_pfx) = pfx; 1001 } 1002 _TCAM_STATE_NEXT(u, zid, pfx) = _TCAM_STATE_NEXT(u, zid, curr_pfx); 1003 _TCAM_STATE_PREV(u, zid, pfx) = curr_pfx; 1004 _TCAM_STATE_NEXT(u, zid, curr_pfx) = pfx; 1005 1006 _TCAM_STATE_FENT(u, zid, pfx) = 1007 (_TCAM_STATE_FENT(u, zid, curr_pfx) + 1) / 2; 1008 _TCAM_STATE_FENT(u, zid, curr_pfx) -= _TCAM_STATE_FENT(u, zid, pfx); 1009 _TCAM_STATE_START(u, zid, pfx) = _TCAM_STATE_END(u, zid, curr_pfx) + 1010 _TCAM_STATE_FENT(u, zid, curr_pfx) + 1; 1011 _TCAM_STATE_END(u, zid, pfx) = _TCAM_STATE_START(u, zid, pfx) - 1; 1012 _TCAM_STATE_VENT(u, zid, pfx) = 0; 1013 } else if (pkm == ALPM_PKM_32B) { 1014 /* For IPv4 Check if alternate entry is free */ 1015 from_ent = _TCAM_STATE_START(u, zid, pfx); 1016 ALPM_IER(tcam_entry_read(u, pkm, e, from_ent, from_ent)); 1017 v0 = tcam_entry_valid(u, pkm, e, 0); 1018 v1 = tcam_entry_valid(u, pkm, e, 1); 1019 1020 if ((v0 == 0) || (v1 == 0)) { 1021 *free_slot = (from_ent << 1) + ((v1 == 0) ? 1 : 0); 1022 *update = 1; /* half-free entry */ 1023 return BCM_E_NONE; 1024 } 1025 1026 from_ent = _TCAM_STATE_END(u, zid, pfx); 1027 ALPM_IER(tcam_entry_read(u, pkm, e, from_ent, from_ent)); 1028 v0 = tcam_entry_valid(u, pkm, e, 0); 1029 v1 = tcam_entry_valid(u, pkm, e, 1); 1030 1031 if ((v0 == 0) || (v1 == 0)) { 1032 *free_slot = (from_ent << 1) + ((v1 == 0) ? 1 : 0); 1033 *update = 1; /* half-free entry */ 1034 return BCM_E_NONE; 1035 } 1036 } 1037 1038 free_pfx = pfx; 1039 while (_TCAM_STATE_FENT(u, zid, free_pfx) == 0) { 1040 /* pkm <= ALPM_PKM_64B: starting from higher index. 1041 * else starting from lower index 1042 */ 1043 free_pfx = _TCAM_STATE_NEXT(u, zid, free_pfx); 1044 if (free_pfx == -1) { 1045 /* No free entries on this side try the other side */ 1046 free_pfx = pfx; 1047 break; 1048 } 1049 } 1050 1051 while (_TCAM_STATE_FENT(u, zid, free_pfx) == 0) { 1052 free_pfx = _TCAM_STATE_PREV(u, zid, free_pfx); 1053 if (free_pfx == -1) { 1054 if (_TCAM_STATE_VENT(u, zid, pfx) == 0) { 1055 /* We failed to allocate entries for a newly allocated prefix.*/ 1056 prev_pfx = _TCAM_STATE_PREV(u, zid, pfx); 1057 next_pfx = _TCAM_STATE_NEXT(u, zid, pfx); 1058 if (-1 != prev_pfx) { 1059 _TCAM_STATE_NEXT(u, zid, prev_pfx) = next_pfx; 1060 } 1061 if (-1 != next_pfx) { 1062 _TCAM_STATE_PREV(u, zid, next_pfx) = prev_pfx; 1063 } 1064 } 1065 return BCM_E_FULL; 1066 } 1067 } 1068 1069 /* 1070 * Ripple entries to create free space 1071 */ 1072 while (free_pfx > pfx) { 1073 next_pfx = _TCAM_STATE_NEXT(u, zid, free_pfx); 1074 ALPM_IER(_tcam_shift_pfx_down(u, next_pfx, zid)); 1075 _TCAM_STATE_FENT(u, zid, free_pfx) -= 1; 1076 _TCAM_STATE_FENT(u, zid, next_pfx) += 1; 1077 free_pfx = next_pfx; 1078 } 1079 1080 while (free_pfx < pfx) { 1081 ALPM_IER(_tcam_shift_pfx_up(u, free_pfx, zid)); 1082 _TCAM_STATE_FENT(u, zid, free_pfx) -= 1; 1083 prev_pfx = _TCAM_STATE_PREV(u, zid, free_pfx); 1084 _TCAM_STATE_FENT(u, zid, prev_pfx) += 1; 1085 free_pfx = prev_pfx; 1086 } 1087 1088 _TCAM_STATE_VENT(u, zid, pfx) += 1; 1089 _TCAM_STATE_FENT(u, zid, pfx) -= 1; 1090 _TCAM_STATE_END(u, zid, pfx) += 1; 1091 1092 *free_slot = _TCAM_STATE_END(u, zid, pfx) << ((pkm) ? 0 : 1); 1093 *update = 0; /* full-free entry */ 1094 1095 return BCM_E_NONE; 1096 } 1097 1098 /* 1099 * Delete a slot and adjust entry pointers if required. 1100 */ 1101 static int 1102 _tcam_free_slot_delete(int u, int pkm, int zid, int pfx, int slot) 1103 { 1104 int prev_pfx, next_pfx; 1105 int fidx, tidx; 1106 uint32 ef[SOC_MAX_MEM_FIELD_WORDS]; 1107 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 1108 void *et; 1109 int rv = BCM_E_NONE; 1110 1111 fidx = _TCAM_STATE_END(u, zid, pfx); 1112 tidx = slot; 1113 1114 if (pkm == ALPM_PKM_32B) { 1115 tidx >>= 1; 1116 ALPM_IER(tcam_entry_read(u, pkm, ef, fidx, fidx)); 1117 if (fidx != tidx) { 1118 ALPM_IER(tcam_entry_read(u, pkm, e, tidx, tidx)); 1119 et = e; 1120 } else { 1121 et = ef; 1122 } 1123 1124 if (tcam_entry_valid(u, pkm, ef, 1)) { 1125 rv = _tcam_entry_x_to_y(u, pkm, ef, et, TRUE, 1, slot & 1); 1126 (void)_tcam_entry_valid_set(u, pkm, ef, 1, 0); 1127 } else { 1128 rv = _tcam_entry_x_to_y(u, pkm, ef, et, TRUE, 0, slot & 1); 1129 (void)_tcam_entry_valid_set(u, pkm, ef, 0, 0); 1130 _TCAM_STATE_VENT(u, zid, pfx) -= 1; 1131 _TCAM_STATE_FENT(u, zid, pfx) += 1; 1132 _TCAM_STATE_END(u, zid, pfx) -= 1; 1133 } 1134 1135 /* not true for OVERRIDE routes */ 1136 if (tidx != fidx) { 1137 ALPM_IER(_tcam_trie_update_by_ent(u, pkm, et, tidx)); 1138 ALPM_IER(_tcam_entry_write(u, pkm, et, tidx, tidx)); 1139 } 1140 ALPM_IER(_tcam_trie_update_by_ent(u, pkm, ef, fidx)); 1141 ALPM_IER(_tcam_entry_write(u, pkm, ef, fidx, fidx)); 1142 } else { /* IPV6 */ 1143 _TCAM_STATE_VENT(u, zid, pfx) -= 1; 1144 _TCAM_STATE_FENT(u, zid, pfx) += 1; 1145 _TCAM_STATE_END(u, zid, pfx) -= 1; 1146 if (tidx != fidx) { 1147 ALPM_IER(tcam_entry_read(u, pkm, ef, fidx, fidx)); 1148 ALPM_IER(_tcam_trie_update_by_ent(u, pkm, ef, tidx)); 1149 ALPM_IER(_tcam_entry_write(u, pkm, ef, tidx, fidx)); 1150 } 1151 /* v6-64 indices are still raw in pivot tcam */ 1152 sal_memset(ef, 0, sizeof(ef)); 1153 ALPM_IER(_tcam_entry_write(u, pkm, ef, fidx, fidx)); 1154 } 1155 1156 if (_TCAM_STATE_VENT(u, zid, pfx) == 0) { 1157 /* remove from the list */ 1158 prev_pfx = _TCAM_STATE_PREV(u, zid, pfx); /* Always present */ 1159 assert(prev_pfx != -1); 1160 next_pfx = _TCAM_STATE_NEXT(u, zid, pfx); 1161 _TCAM_STATE_NEXT(u, zid, prev_pfx) = next_pfx; 1162 _TCAM_STATE_FENT(u, zid, prev_pfx) += _TCAM_STATE_FENT(u, zid, pfx); 1163 _TCAM_STATE_FENT(u, zid, pfx) = 0; 1164 if (next_pfx != -1) { 1165 _TCAM_STATE_PREV(u, zid, next_pfx) = prev_pfx; 1166 } 1167 _TCAM_STATE_NEXT(u, zid, pfx) = -1; 1168 _TCAM_STATE_PREV(u, zid, pfx) = -1; 1169 _TCAM_STATE_START(u, zid, pfx) = -1; 1170 _TCAM_STATE_END(u, zid, pfx) = -1; 1171 } 1172 1173 return rv; 1174 } 1175 1176 /* 1177 * Extract vrf weighted prefix lenght from vrf_id, pkm, key_len. 1178 */ 1179 static void 1180 tcam_pfx_len_get(int u, int ipv6, int zid, int inst_id, int key_len, int *pfx_len) 1181 { 1182 int ipv6_min; 1183 1184 ipv6_min = _TCAMZ_PFX_MIN_V6(u, zid); 1185 1186 if (ipv6) { 1187 key_len += ipv6_min; 1188 } 1189 1190 /* In ALPM the arragnement of VRF is at he begining followed by VRF 1191 override and global */ 1192 *pfx_len = key_len + inst_id * _TCAMZ_PFX_ENT_PER_INST(u, zid); 1193 return; 1194 } 1195 1196 static void 1197 _tcam_gpfx_len_get( 1198 int u, int defip_vrf, int ipv6, int zid, 1199 _bcm_defip_cfg_t *lpm_cfg, int *pfx_len) 1200 { 1201 int inst_id; 1202 1203 /* Calculate vrf weighted prefix lengh. */ 1204 inst_id = _tcam_zone_inst_id_get(u, defip_vrf, lpm_cfg->defip_flags & BCM_L3_IPMC); 1205 tcam_pfx_len_get(u, ipv6, zid, inst_id, lpm_cfg->defip_sub_len, pfx_len); 1206 1207 return; 1208 } 1209 1210 static int 1211 _tcam_cfg_write(int u, _bcm_defip_cfg_t *lpm_cfg, int index, int s_index, 1212 int update, uint32 write_flags) 1213 { 1214 int rv = BCM_E_NONE; 1215 int hw_idx; 1216 int pkm = ALPM_LPM_PKM(u, lpm_cfg); 1217 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 1218 _alpm_tcam_write_t *tcam_write = lpm_cfg->tcam_write; 1219 1220 hw_idx = (pkm == ALPM_PKM_32B) ? index >> 1 : index; 1221 1222 /* Entry already present. Update the entry */ 1223 if (pkm == ALPM_PKM_32B) { 1224 if (update) { 1225 ALPM_IER(tcam_entry_read(u, pkm, e, hw_idx, s_index)); 1226 } else { 1227 sal_memset(e, 0, sizeof(e)); 1228 } 1229 /* Need to clear entry if both entry0 & 1 are invalid? */ 1230 rv = _tcam_entry_from_cfg(u, pkm, lpm_cfg, e, index & 1, write_flags); 1231 } else { 1232 sal_memset(e, 0, sizeof(e)); 1233 rv = _tcam_entry_from_cfg(u, pkm, lpm_cfg, e, 0, write_flags); 1234 } 1235 1236 if (BCM_SUCCESS(rv)) { 1237 if (tcam_write != NULL) { /* case new L1 pvt add during L2 bkt split */ 1238 tcam_write->hw_idx = hw_idx; 1239 sal_memcpy(tcam_write->ent, e, sizeof(e)); 1240 } else { 1241 rv = _tcam_entry_write(u, pkm, e, hw_idx, s_index); 1242 } 1243 } 1244 1245 return rv; 1246 } 1247 1248 /* 1249 * _tcam_cfg_match (Exact match for the key. Will match both IP address 1250 * and mask) 1251 * 1252 * OUT index_ptr: return key location 1253 * OUT pfx_len: Key prefix length. vrf+32+pfx len for single wide(64b) 1254 */ 1255 static int 1256 _tcam_cfg_match(int u, _bcm_defip_cfg_t *lpm_cfg, int *index_ptr) 1257 { 1258 int key_index = 0; 1259 int rv = BCM_E_NONE; 1260 1261 if (_tcam_trie_lookup(u, lpm_cfg, &key_index) == BCM_E_NONE) { 1262 *index_ptr = key_index; 1263 } else { 1264 rv = BCM_E_NOT_FOUND; 1265 } 1266 1267 return rv; 1268 } 1269 1270 static int 1271 _tcam_cfg_insert(int u, int zid, _bcm_defip_cfg_t *lpm_cfg, uint32 write_flags) 1272 { 1273 int rv; 1274 int index, pfx, pkm, update = 0; /* for 32B only */ 1275 1276 pkm = ALPM_LPM_PKM(u, lpm_cfg); 1277 _tcam_gpfx_len_get(u, lpm_cfg->defip_vrf, !!pkm, zid, lpm_cfg, &pfx); 1278 rv = _tcam_free_slot_create(u, pkm, zid, pfx, &index, &update); 1279 if (BCM_SUCCESS(rv)) { 1280 lpm_cfg->defip_index = index; 1281 rv = _tcam_cfg_write(u, lpm_cfg, index, index, update, write_flags); 1282 } 1283 1284 return rv; 1285 } 1286 1287 int 1288 bcm_esw_alpm_tcam_avail(int u, int vrf_id, int ipt, int key_len, int mc) 1289 { 1290 int pfx, zid, fent, cnt = 0; 1291 1292 if (!TCAMC(u)) { 1293 return 0; 1294 } 1295 1296 zid = _tcam_zone_zid_get(u, ALPM_VRF_ID_TO_VRF(u, vrf_id), ipt, ALPM_128B(u), mc); 1297 pfx = _TCAMZ_PFX_MAX_IDX(u, zid); 1298 while (pfx >= 0) { 1299 fent = _TCAM_STATE_FENT(u, zid, pfx); 1300 if (fent > 0) { 1301 cnt += fent; 1302 } 1303 pfx = _TCAM_STATE_NEXT(u, zid, pfx); 1304 } 1305 1306 return cnt; 1307 } 1308 1309 int 1310 bcm_esw_alpm_tcam_state_free_get(int u, int zn, int *free_cnt, int *used_cnt) 1311 { 1312 int i, zn_min, zn_max; 1313 int fcnt = 0, vcnt = 0; 1314 1315 if (!TCAMC(u)) { 1316 return BCM_E_NONE; 1317 } 1318 1319 if (zn < 0 || zn >= _TCAM_ZONE_CNT) { 1320 zn_min = 0; 1321 zn_max = _TCAM_ZONE_CNT - 1; 1322 } else { 1323 zn_min = zn_max = zn; 1324 } 1325 1326 for (i = zn_min; i <= zn_max; i++) { 1327 int zid; 1328 _tcam_zone_st_t tz_st; 1329 1330 zid = _TCAMZ_ZID_MAKE_FROM_ZN(0, ALPM_128B(u), ALPM_TCAM_ZONED(u), i); 1331 if (!_TCAMZ_INITED(u, zid)) { 1332 continue; 1333 } 1334 _tcam_zone_status(u, zid, &tz_st); 1335 1336 fcnt += tz_st.cnt_free; 1337 vcnt += tz_st.cnt_used; 1338 } 1339 1340 if (free_cnt) { 1341 *free_cnt = fcnt; 1342 } 1343 if (used_cnt) { 1344 *used_cnt = vcnt; 1345 } 1346 1347 return BCM_E_NONE; 1348 } 1349 1350 void 1351 bcm_esw_alpm_tcam_zone_state_dump(int u) 1352 { 1353 int i, zn; 1354 int max_pfx_len; 1355 1356 for (zn = 0; zn < _TCAM_ZONE_CNT; zn++) { 1357 int zid; 1358 1359 if (tz_conf[!!ALPM_TCAM_ZONED(u) << 1 | !!ALPM_128B(u)][zn] == tZoneInvalid) { 1360 continue; 1361 } 1362 1363 zid = _TCAMZ_ZID_MAKE_FROM_ZN(0, ALPM_128B(u), ALPM_TCAM_ZONED(u), zn); 1364 if (!_TCAMZ_INITED(u, zid)) { 1365 continue; 1366 } 1367 1368 cli_out("Zone %d (%s) :\n", zn, _tz_db_str[_TCAMZ_DB_TYPE(u, zid)]); 1369 max_pfx_len = _TCAMZ_PFX_MAX_IDX(u, zid); 1370 for (i = max_pfx_len; i >= 0 ; i--) { 1371 if ((i != _TCAMZ_PFX_MAX_IDX(u, zid)) && 1372 _TCAM_STATE_START(u, zid, i) == -1 && 1373 _TCAM_STATE_FENT(u, zid, i) == 0) { 1374 continue; 1375 } 1376 1377 cli_out("\tPFX = %3d P = %3d N = %3d START = %5d END = %5d " 1378 "VENT = %5d FENT = %5d\n", i, 1379 _TCAM_STATE_PREV(u, zid, i), 1380 _TCAM_STATE_NEXT(u, zid, i), 1381 _TCAM_STATE_START(u, zid, i), 1382 _TCAM_STATE_END(u, zid, i), 1383 _TCAM_STATE_VENT(u, zid, i), 1384 _TCAM_STATE_FENT(u, zid, i)); 1385 } 1386 cli_out("\n"); 1387 } 1388 } 1389 1390 void 1391 bcm_esw_alpm_tcam_zone_dump(int u, char *pfx_str) 1392 { 1393 int zn; 1394 int free_tcam = 0, used_tcam = 0, tot_tcam; 1395 1396 for (zn = 0; zn < _TCAM_ZONE_CNT; zn++) { 1397 int zid; 1398 1399 if (tz_conf[!!ALPM_TCAM_ZONED(u) << 1 | !!ALPM_128B(u)][zn] == tZoneInvalid) { 1400 continue; 1401 } 1402 1403 zid = _TCAMZ_ZID_MAKE_FROM_ZN(0, ALPM_128B(u), ALPM_TCAM_ZONED(u), zn); 1404 if (!_TCAMZ_INITED(u, zid)) { 1405 continue; 1406 } 1407 1408 (void)bcm_esw_alpm_tcam_state_free_get(u, zn, &free_tcam, &used_tcam); 1409 tot_tcam = used_tcam + free_tcam; 1410 if (tot_tcam == 0) { 1411 tot_tcam = 1; /* avoid divide by 0 */ 1412 } 1413 cli_out("%sTCAM zone %d(%s): %4d (used), %4d (free), Usage: %d.%d%%\n", 1414 pfx_str, zn, _tz_db_str[_TCAMZ_DB_TYPE(u, zid)], 1415 used_tcam, free_tcam, 1416 used_tcam * 100 / tot_tcam, 1417 (used_tcam * 1000 / tot_tcam) % 10); 1418 } 1419 1420 return ; 1421 } 1422 1423 /* 1424 * De-initialize the start/end tracking pointers for each prefix length 1425 */ 1426 int 1427 bcm_esw_alpm_tcam_deinit(int u) 1428 { 1429 int i, zid; 1430 1431 if (!soc_feature(u, soc_feature_lpm_tcam)) { 1432 return BCM_E_UNAVAIL; 1433 } 1434 1435 for (zid = 0; zid < _TCAM_ZID_CNT; zid++) { 1436 if (_TCAMZ_INITED(u, zid) && 1437 _TCAM_STATE(u, zid) != NULL) { 1438 alpm_util_free(_TCAM_STATE(u, zid)); 1439 _TCAM_STATE(u, zid) = NULL; 1440 } 1441 } 1442 1443 for (i = 0; i < _TCAM_ZID_CNT; i++) { 1444 _TCAMZ(u, i) = NULL; 1445 } 1446 1447 if (_TCAM_INIT_CHECK(u)) { 1448 alpm_util_free(TCAMC(u)); 1449 TCAMC(u) = NULL; 1450 } 1451 1452 return BCM_E_NONE; 1453 } 1454 1455 /* 1456 * Initialize the start/end tracking pointers for each prefix length 1457 */ 1458 int 1459 bcm_esw_alpm_tcam_init(int u) 1460 { 1461 int rv = BCM_E_NONE; 1462 1463 if (!soc_feature(u, soc_feature_lpm_tcam)) { 1464 return BCM_E_UNAVAIL; 1465 } 1466 1467 if (_TCAM_INIT_CHECK(u)) { 1468 /* this is a reinit. clean up old state */ 1469 if (bcm_esw_alpm_tcam_deinit(u) < 0) { 1470 return BCM_E_UNAVAIL; 1471 } 1472 } 1473 1474 ALPM_ALLOC_EG(TCAMC(u), sizeof(_tcam_ctrl_t), "TCAMC"); 1475 ALPM_IEG(_tcam_zone_init(u)); 1476 1477 return rv; 1478 1479 bad: 1480 (void)bcm_esw_alpm_tcam_deinit(u); 1481 return rv; 1482 } 1483 1484 /* 1485 * ALPM TCAM cleanup 1486 */ 1487 int 1488 bcm_esw_alpm_tcam_cleanup(int u) 1489 { 1490 int rv = BCM_E_NONE; 1491 1492 if (!soc_feature(u, soc_feature_lpm_tcam)) { 1493 return BCM_E_UNAVAIL; 1494 } 1495 1496 ALPM_REALLOC_EG(TCAMC(u), sizeof(_tcam_ctrl_t), "TCAMC"); 1497 ALPM_IEG(_tcam_zone_init(u)); 1498 1499 bad: 1500 return rv; 1501 } 1502 1503 /* 1504 * Implementation using _mem_read/write using entry rippling technique 1505 * Advantage: A completely sorted table is not required. Lookups can be slow 1506 * as it will perform a linear search on the entries for a given prefix length. 1507 * No device access necessary for the search if the table is cached. Auxiliary 1508 * Small number of entries need to be moved around (97 worst case) 1509 * for performing insert/update/delete. However CPU needs to do all 1510 * the work to move the entries. 1511 */ 1512 1513 /* 1514 * bcm_esw_alpm_tcam_insert 1515 * For IPV4 assume only both IP_ADDR0 is valid 1516 * Moving multiple entries around in h/w vs doing a linear search in s/w 1517 */ 1518 int 1519 bcm_esw_alpm_tcam_insert(int u, _bcm_defip_cfg_t *lpm_cfg, uint32 write_flags) 1520 { 1521 int index; 1522 int rv = BCM_E_NONE; 1523 1524 rv = _tcam_cfg_match(u, lpm_cfg, &index); 1525 if (rv == BCM_E_NOT_FOUND) { 1526 int zid; 1527 zid = _tcam_zone_zid_get(u, lpm_cfg->defip_vrf, 1528 ALPM_LPM_IPT(u, lpm_cfg), ALPM_128B(u), 1529 lpm_cfg->defip_flags & BCM_L3_IPMC); 1530 rv = _tcam_cfg_insert(u, zid, lpm_cfg, write_flags); 1531 } else if (rv == BCM_E_NONE) { 1532 /* Found */ 1533 rv = _tcam_cfg_write(u, lpm_cfg, index, index, 1, write_flags); 1534 } 1535 1536 return rv; 1537 } 1538 1539 /* 1540 * bcm_esw_alpm_tcam_delete 1541 */ 1542 int 1543 bcm_esw_alpm_tcam_delete(int u, _bcm_defip_cfg_t *lpm_cfg) 1544 { 1545 int index, ipt; 1546 int rv = BCM_E_NONE; 1547 1548 rv = _tcam_cfg_match(u, lpm_cfg, &index); 1549 if (rv == BCM_E_NONE) { 1550 int zid, pkm, pfx, defip_vrf; 1551 defip_vrf = lpm_cfg->defip_vrf; 1552 1553 pkm = ALPM_LPM_PKM(u, lpm_cfg); 1554 ipt = ALPM_PKM2IPT(pkm); 1555 zid = _tcam_zone_zid_get(u, defip_vrf, ipt, ALPM_128B(u), 1556 lpm_cfg->defip_flags & BCM_L3_IPMC); 1557 lpm_cfg->defip_index = index; 1558 _tcam_gpfx_len_get(u, defip_vrf, ipt, zid, lpm_cfg, &pfx); 1559 rv = _tcam_free_slot_delete(u, pkm, zid, pfx, index); 1560 } 1561 1562 if (BCM_SUCCESS(rv)) { 1563 ; /* VRF_PIVOT_REF_DEC(u, vrf_id, vrf, pkm); */ 1564 } 1565 1566 return(rv); 1567 } 1568 1569 /* 1570 * bcm_esw_alpm_tcam_match 1571 * (Exact match for the key. Will match both IP address and mask) 1572 */ 1573 int 1574 bcm_esw_alpm_tcam_match(int u, _bcm_defip_cfg_t *lpm_cfg, int *index_ptr) 1575 { 1576 int rv; 1577 int hw_idx; 1578 int pkm = ALPM_LPM_PKM(u, lpm_cfg); 1579 uint32 e[SOC_MAX_MEM_FIELD_WORDS]; 1580 1581 rv = _tcam_cfg_match(u, lpm_cfg, index_ptr); 1582 if (BCM_SUCCESS(rv)) { 1583 /* 1584 * If entry is ipv4 copy to the "zero" half of the, 1585 * buffer, "zero" half of lpm_entry if the original entry 1586 * is in the "one" half. 1587 */ 1588 hw_idx = *index_ptr; 1589 if (pkm == ALPM_PKM_32B) { 1590 hw_idx >>= 1; 1591 } 1592 1593 ALPM_IER(tcam_entry_read(u, pkm, e, hw_idx, hw_idx)); 1594 1595 if (pkm == ALPM_PKM_32B) { 1596 rv = tcam_entry_to_cfg(u, pkm, e, (*index_ptr & 0x1), lpm_cfg); 1597 } else { 1598 rv = tcam_entry_to_cfg(u, pkm, e, 0, lpm_cfg); 1599 } 1600 } 1601 return rv; 1602 } 1603 1604 /* ********************* * 1605 * TCAM warmboot support * 1606 */ 1607 1608 /* 1609 * Function: 1610 * tcam_wb_reinit_done 1611 * Purpose: 1612 * Update all TCAM state once entry reinit done from warmboot. 1613 * Parameters: 1614 * u - (IN)Device unit number. 1615 * Returns: 1616 * BCM_E_XXX 1617 */ 1618 int 1619 tcam_wb_reinit_done(int u) 1620 { 1621 int idx; 1622 int prev_idx; 1623 int defip_table_size; 1624 int zn; 1625 1626 for (zn = 0; zn < _TCAM_ZONE_CNT; zn++) { 1627 int zid, pkm; 1628 1629 zid = _TCAMZ_ZID_MAKE_FROM_ZN(0, ALPM_128B(u), ALPM_TCAM_ZONED(u), zn); 1630 1631 if (!_TCAMZ_INITED(u, zid)) { 1632 continue; 1633 } 1634 1635 prev_idx = _TCAMZ_PFX_MAX_IDX(u, zid); 1636 pkm = _tcam_zone_db_type_to_pkm(u, _TCAMZ_DB_TYPE(u, zid)); 1637 defip_table_size = tcam_table_size(u, pkm); 1638 1639 if (ALPM_MODE_CHK(u, BCM_ALPM_MODE_COMBINED)) { 1640 /* Combined search mode */ 1641 _TCAM_STATE_PREV(u, zid, _TCAMZ_PFX_MAX_IDX(u, zid)) = -1; 1642 1643 for (idx = _TCAMZ_PFX_MAX_IDX(u, zid); idx > -1; idx--) { 1644 if (_TCAM_STATE_START(u, zid, idx) == -1) { 1645 continue; 1646 } 1647 1648 _TCAM_STATE_PREV(u, zid, idx) = prev_idx; 1649 _TCAM_STATE_NEXT(u, zid, prev_idx) = idx; 1650 1651 _TCAM_STATE_FENT(u, zid, prev_idx) = \ 1652 _TCAM_STATE_START(u, zid, idx) - \ 1653 _TCAM_STATE_END(u, zid, prev_idx) - 1; 1654 prev_idx = idx; 1655 1656 } 1657 1658 _TCAM_STATE_NEXT(u, zid, prev_idx) = -1; 1659 _TCAM_STATE_FENT(u, zid, prev_idx) = \ 1660 defip_table_size - \ 1661 _TCAM_STATE_END(u, zid, prev_idx) - 1; 1662 } else { 1663 int tab_idx_max = 0; 1664 /* Parallel search mode 1665 * 1666 * Configured VRF Range 1667 * {0 - (ALPM_MAX_PFX_INDEX/3)} 1668 * Global VRF Range 1669 * {((ALPM_MAX_PFX_INDEX/1) + 1) - (ALPM_MAX_PFX_INDEX/2) } 1670 * Override VRF Range 1671 * {((ALPM_MAX_PFX_INDEX/2) + 1) - (ALPM_MAX_PFX_INDEX) } 1672 */ 1673 1674 /* 1675 * Global and Overide VRF range are treated as single block and 1676 * both blocks will be linked 1677 */ 1678 _TCAM_STATE_PREV(u, zid, _TCAMZ_PFX_MAX_IDX(u, zid)) = -1; 1679 for (idx = _TCAMZ_PFX_MAX_IDX(u, zid); idx > -1; idx--) { 1680 if (-1 == _TCAM_STATE_START(u, zid, idx)) { 1681 continue; 1682 } 1683 1684 _TCAM_STATE_PREV(u, zid, idx) = prev_idx; 1685 _TCAM_STATE_NEXT(u, zid, prev_idx) = idx; 1686 1687 _TCAM_STATE_FENT(u, zid, prev_idx) = \ 1688 _TCAM_STATE_START(u, zid, idx) - \ 1689 _TCAM_STATE_END(u, zid, prev_idx) - 1; 1690 1691 prev_idx = idx; 1692 } 1693 /* 1694 * _TCAM_ZONE_CNT: 1695 * bit1 : 0 Glb, 1 Prv 1696 * bit0 : 0 V4, 1 V6 1697 */ 1698 if (zn & 0x2) { 1699 tab_idx_max = defip_table_size / 2; 1700 } else { 1701 tab_idx_max = defip_table_size; 1702 } 1703 1704 _TCAM_STATE_NEXT(u, zid, prev_idx) = -1; 1705 _TCAM_STATE_FENT(u, zid, prev_idx) = 1706 tab_idx_max - _TCAM_STATE_END(u, zid, prev_idx) - 1; 1707 } 1708 1709 } /* for zn */ 1710 1711 return (BCM_E_NONE); 1712 } 1713 1714 /* 1715 * Function: 1716 * tcam_wb_reinit 1717 * Purpose: 1718 * TCAM entry state reinit from warmboot. 1719 * Parameters: 1720 * u - (IN)Device unit number. 1721 * pkm - (In)Packing mode (32B, 64B, 128) 1722 * vrf_id - (In)VRF ID 1723 * idx - (In)Memory Index 1724 * key_len - (In)Key prefix length 1725 * Returns: 1726 * BCM_E_XXX 1727 */ 1728 int 1729 tcam_wb_reinit(int u, int vrf_id, int pkm, int idx, int key_len, int mc) 1730 { 1731 int zid, inst_id; 1732 int pfx_len, ipt; 1733 1734 ipt = ALPM_PKM2IPT(pkm); 1735 zid = _tcam_zone_zid_get(u, ALPM_VRF_ID_TO_VRF(u, vrf_id), ipt, ALPM_128B(u), mc); 1736 inst_id = _tcam_zone_inst_id_get(u, ALPM_VRF_ID_TO_VRF(u, vrf_id), mc); 1737 1738 tcam_pfx_len_get(u, pkm, zid, inst_id, key_len, &pfx_len); 1739 1740 if (_TCAM_STATE_VENT(u, zid, pfx_len) == 0) { 1741 _TCAM_STATE_START(u, zid, pfx_len) = idx; 1742 _TCAM_STATE_END(u, zid, pfx_len) = idx; 1743 } else { 1744 _TCAM_STATE_END(u, zid, pfx_len) = idx; 1745 } 1746 1747 _TCAM_STATE_VENT(u, zid, pfx_len)++; 1748 1749 return (BCM_E_NONE); 1750 } 1751 1752 #endif /* ALPM_ENABLE */ 1753