ism.c (133225B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * ISM management routines 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <assert.h> 13 14 #include <sal/types.h> 15 16 #include <soc/drv.h> 17 #include <soc/error.h> 18 #include <soc/util.h> 19 #include <soc/mem.h> 20 #include <soc/debug.h> 21 #include <soc/cm.h> 22 23 #ifdef BCM_ISM_SUPPORT 24 25 typedef struct { 26 uint8 index; 27 uint8 bank; 28 } _soc_ism_bank_trace_t; 29 30 _soc_ism_t _soc_ism_info[SOC_MAX_NUM_DEVICES]; 31 _soc_ism_hash_t _soc_ism_hash_info[SOC_MAX_NUM_DEVICES]; 32 /* track bank usage by mem, set dynamically - used by pcid as well */ 33 uint32 _soc_ism_bank_avail[SOC_MAX_NUM_DEVICES][_SOC_ISM_MAX_BANKS]; 34 35 /* Physical stage/bank constructs */ 36 uint32 _soc_ism_bank_raw_sizes[] = { 37 _SOC_ISM_BANK0_SIZE, _SOC_ISM_BANK1_SIZE, 38 _SOC_ISM_BANK2_SIZE, _SOC_ISM_BANK3_SIZE, 39 _SOC_ISM_BANK4_SIZE, 40 _SOC_ISM_BANK0_SIZE, _SOC_ISM_BANK1_SIZE, 41 _SOC_ISM_BANK2_SIZE, _SOC_ISM_BANK3_SIZE, 42 _SOC_ISM_BANK4_SIZE, 43 _SOC_ISM_BANK0_SIZE, _SOC_ISM_BANK1_SIZE, 44 _SOC_ISM_BANK2_SIZE, _SOC_ISM_BANK3_SIZE, 45 _SOC_ISM_BANK4_SIZE, 46 _SOC_ISM_BANK0_SIZE, _SOC_ISM_BANK1_SIZE, 47 _SOC_ISM_BANK2_SIZE, _SOC_ISM_BANK3_SIZE, 48 _SOC_ISM_BANK4_SIZE 49 }; 50 51 uint32 _soc_ism_bank_raw_sizes_256[] = { 52 _SOC_ISM_256_BANK0_SIZE, _SOC_ISM_256_BANK1_SIZE, 53 _SOC_ISM_256_BANK2_SIZE, _SOC_ISM_256_BANK3_SIZE, 54 _SOC_ISM_256_BANK4_SIZE, 55 _SOC_ISM_256_BANK0_SIZE, _SOC_ISM_256_BANK1_SIZE, 56 _SOC_ISM_256_BANK2_SIZE, _SOC_ISM_256_BANK3_SIZE, 57 _SOC_ISM_256_BANK4_SIZE, 58 _SOC_ISM_256_BANK0_SIZE, _SOC_ISM_256_BANK1_SIZE, 59 _SOC_ISM_256_BANK2_SIZE, _SOC_ISM_256_BANK3_SIZE, 60 _SOC_ISM_256_BANK4_SIZE, 61 _SOC_ISM_256_BANK0_SIZE, _SOC_ISM_256_BANK1_SIZE, 62 _SOC_ISM_256_BANK2_SIZE, _SOC_ISM_256_BANK3_SIZE, 63 _SOC_ISM_256_BANK4_SIZE 64 }; 65 66 uint32 _soc_ism_bank_raw_sizes_256_176[] = { 67 _SOC_ISM_256_176_BANK0_SIZE, _SOC_ISM_256_176_BANK1_SIZE, 68 _SOC_ISM_256_176_BANK2_SIZE, _SOC_ISM_256_176_BANK3_SIZE, 69 _SOC_ISM_256_176_BANK0_SIZE, _SOC_ISM_256_176_BANK1_SIZE, 70 _SOC_ISM_256_176_BANK2_SIZE, _SOC_ISM_256_176_BANK3_SIZE, 71 _SOC_ISM_256_176_BANK0_SIZE, _SOC_ISM_256_176_BANK1_SIZE, 72 _SOC_ISM_256_176_BANK2_SIZE, _SOC_ISM_256_176_BANK3_SIZE, 73 _SOC_ISM_256_176_BANK0_SIZE, _SOC_ISM_256_176_BANK1_SIZE, 74 _SOC_ISM_256_176_BANK2_SIZE, _SOC_ISM_256_176_BANK3_SIZE 75 }; 76 77 uint32 _soc_ism_bank_raw_sizes_256_96[] = { 78 _SOC_ISM_256_96_BANK1_SIZE, _SOC_ISM_256_96_BANK2_SIZE, 79 _SOC_ISM_256_96_BANK3_SIZE, _SOC_ISM_256_96_BANK4_SIZE, 80 _SOC_ISM_256_96_BANK1_SIZE, _SOC_ISM_256_96_BANK2_SIZE, 81 _SOC_ISM_256_96_BANK3_SIZE, _SOC_ISM_256_96_BANK4_SIZE, 82 _SOC_ISM_256_96_BANK1_SIZE, _SOC_ISM_256_96_BANK2_SIZE, 83 _SOC_ISM_256_96_BANK3_SIZE, _SOC_ISM_256_96_BANK4_SIZE, 84 _SOC_ISM_256_96_BANK1_SIZE, _SOC_ISM_256_96_BANK2_SIZE, 85 _SOC_ISM_256_96_BANK3_SIZE, _SOC_ISM_256_96_BANK4_SIZE 86 }; 87 88 uint32 _soc_ism_bank_raw_sizes_256_80[] = { 89 _SOC_ISM_256_80_BANK1_SIZE, _SOC_ISM_256_80_BANK2_SIZE, 90 _SOC_ISM_256_80_BANK3_SIZE, _SOC_ISM_256_80_BANK4_SIZE, 91 _SOC_ISM_256_80_BANK1_SIZE, _SOC_ISM_256_80_BANK2_SIZE, 92 _SOC_ISM_256_80_BANK3_SIZE, _SOC_ISM_256_80_BANK4_SIZE, 93 _SOC_ISM_256_80_BANK1_SIZE, _SOC_ISM_256_80_BANK2_SIZE, 94 _SOC_ISM_256_80_BANK3_SIZE, _SOC_ISM_256_80_BANK4_SIZE, 95 _SOC_ISM_256_80_BANK1_SIZE, _SOC_ISM_256_80_BANK2_SIZE, 96 _SOC_ISM_256_80_BANK3_SIZE, _SOC_ISM_256_80_BANK4_SIZE 97 }; 98 99 /* raw to real bank map */ 100 _soc_ism_real_bank_map_t _soc_ism_real_bank_map[] = { 101 {8, {0, 1, 2, 3, 4, 5, 6, 7}}, 102 {4, {8, 9, 10, 11}}, 103 {2, {12, 13}}, 104 {1, {14}}, 105 {1, {15}}, 106 {8, {16, 17, 18, 19, 20, 21, 22, 23}}, 107 {4, {24, 25, 26, 27}}, 108 {2, {28, 29}}, 109 {1, {30}}, 110 {1, {31}}, 111 {8, {32, 33, 34, 35, 36, 37, 38, 39}}, 112 {4, {40, 41, 42, 43}}, 113 {2, {44, 45}}, 114 {1, {46}}, 115 {1, {47}}, 116 {8, {48, 49, 50, 51, 52, 53, 54, 55}}, 117 {4, {56, 57, 58, 59}}, 118 {2, {60, 61}}, 119 {1, {62}}, 120 {1, {63}} 121 }; 122 123 _soc_ism_real_bank_map_t _soc_ism_real_bank_map_176[] = { 124 {4, {0, 1, 2, 3}}, 125 {4, {8, 9, 10, 11}}, 126 {2, {12, 13}}, 127 {1, {14}}, 128 {4, {16, 17, 18, 19}}, 129 {4, {24, 25, 26, 27}}, 130 {2, {28, 29}}, 131 {1, {30}}, 132 {4, {32, 33, 34, 35}}, 133 {4, {40, 41, 42, 43}}, 134 {2, {44, 45}}, 135 {1, {46}}, 136 {4, {48, 49, 50, 51}}, 137 {4, {56, 57, 58, 59}}, 138 {2, {60, 61}}, 139 {1, {62}} 140 }; 141 142 _soc_ism_real_bank_map_t _soc_ism_real_bank_map_96[] = { 143 {2, {8, 9}}, 144 {2, {12, 13}}, 145 {1, {14}}, 146 {1, {15}}, 147 {2, {24, 25}}, 148 {2, {28, 29}}, 149 {1, {30}}, 150 {1, {31}}, 151 {2, {40, 41}}, 152 {2, {44, 45}}, 153 {1, {46}}, 154 {1, {47}}, 155 {2, {56, 57}}, 156 {2, {60, 61}}, 157 {1, {62}}, 158 {1, {63}} 159 }; 160 161 _soc_ism_real_bank_map_t _soc_ism_real_bank_map_80[] = { 162 {2, {8, 9}}, 163 {1, {12}}, 164 {1, {14}}, 165 {1, {15}}, 166 {2, {24, 25}}, 167 {1, {28}}, 168 {1, {30}}, 169 {1, {31}}, 170 {2, {40, 41}}, 171 {1, {44}}, 172 {1, {46}}, 173 {1, {47}}, 174 {2, {56, 57}}, 175 {1, {60}}, 176 {1, {62}}, 177 {1, {63}} 178 }; 179 180 STATIC _soc_ism_table_index_t mem_info_entry[] = { 181 { "VLAN_XLATE", SOC_ISM_MEM_VLAN_XLATE, 0, 2 }, 182 { "L2_ENTRY", SOC_ISM_MEM_L2_ENTRY, 1, 2 }, 183 { "L3_ENTRY", SOC_ISM_MEM_L3_ENTRY, 2, 1 }, 184 { "EP_VLAN_XLATE", SOC_ISM_MEM_EP_VLAN_XLATE, 3, 4 }, 185 { "MPLS", SOC_ISM_MEM_MPLS, 4, 2 }, 186 { "ESM_L2", SOC_ISM_MEM_ESM_L2, 5, 1 }, 187 { "ESM_L3", SOC_ISM_MEM_ESM_L3, 6, 1 }, 188 { "ESM_ACL", SOC_ISM_MEM_ESM_ACL, 7, 1 } 189 }; 190 191 /* Populated dynamically */ 192 STATIC uint32 _soc_ism_table_bank_count[SOC_MAX_NUM_DEVICES] 193 [_SOC_ISM_MAX_TABLES]; 194 195 /* Populated dynamically */ 196 STATIC uint8 _soc_ism_table_bank_config[SOC_MAX_NUM_DEVICES] 197 [_SOC_ISM_MAX_TABLES][_SOC_ISM_MAX_BANKS]; 198 199 /* Populated dynamically */ 200 STATIC uint32 _soc_ism_table_raw_bank_count[SOC_MAX_NUM_DEVICES] 201 [_SOC_ISM_MAX_TABLES]; 202 203 /* Populated dynamically */ 204 STATIC uint32 _soc_ism_log_to_phy_map[SOC_MAX_NUM_DEVICES] 205 [_SOC_ISM_MAX_TABLES][_SOC_ISM_TOTAL_BANKS]; 206 207 /* Power Down structures */ 208 _soc_ism_pd_t _soc_ism_pd[_SOC_ISM_MAX_STAGES][_SOC_ISM_BANKS_PER_STAGE] = { 209 { 210 { 211 { 212 { STAGE0_MEMORY_CONTROL_0r, { BANK0_PDA0f, BANK0_PDA1f, INVALIDf } }, 213 { STAGE0_MEMORY_CONTROL_1r, { BANK0_PDA2f, BANK0_PDA3f, INVALIDf } }, 214 { STAGE0_MEMORY_CONTROL_2r, { BANK0_PDA4f, BANK0_PDA5f, INVALIDf } }, 215 { STAGE0_MEMORY_CONTROL_3r, { BANK0_PDA6f, BANK0_PDA7f, INVALIDf } }, 216 { STAGE0_MEMORY_CONTROL_4r, { BANK0_PDA8f, BANK0_PDA9f, INVALIDf } }, 217 { STAGE0_MEMORY_CONTROL_5r, { BANK0_PDA10f, BANK0_PDA11f, INVALIDf } }, 218 { INVALIDr } 219 }, 220 { 221 { STAGE0_MEMORY_CONTROL_23r, { BANK0_HIT_PDA0f, BANK0_HIT_PDA1f, INVALIDf } }, 222 { INVALIDr } 223 } 224 }, 225 { 226 { 227 { STAGE0_MEMORY_CONTROL_10r, { BANK1_PDA0f, BANK1_PDA1f, INVALIDf } }, 228 { STAGE0_MEMORY_CONTROL_11r, { BANK1_PDA2f, BANK1_PDA3f, INVALIDf } }, 229 { STAGE0_MEMORY_CONTROL_12r, { BANK1_PDA4f, BANK1_PDA5f, INVALIDf } }, 230 { INVALIDr } 231 }, 232 { 233 { STAGE0_MEMORY_CONTROL_25r, { BANK1_HIT_PDA0f, INVALIDf } }, 234 { INVALIDr } 235 } 236 }, 237 { 238 { 239 { STAGE0_MEMORY_CONTROL_15r, { BANK2_PDA0f, BANK2_PDA1f, BANK2_PDA2f, 240 BANK2_PDA3f, INVALIDf } }, 241 { STAGE0_MEMORY_CONTROL_16r, { BANK2_PDA4f, BANK2_PDA5f, INVALIDf } }, 242 { INVALIDr } 243 }, 244 { 245 { STAGE0_MEMORY_CONTROL_26r, { BANK2_HIT_PDA0f, INVALIDf } }, 246 { INVALIDr } 247 } 248 }, 249 { 250 { 251 { STAGE0_MEMORY_CONTROL_19r, { BANK3_PDA0f, BANK3_PDA1f, INVALIDf } }, 252 { INVALIDr } 253 }, 254 { 255 { STAGE0_MEMORY_CONTROL_27r, { BANK3_HIT_PDA0f, INVALIDf } }, 256 { INVALIDr } 257 } 258 }, 259 { 260 { 261 { STAGE0_MEMORY_CONTROL_21r, { BANK4_PDA0f, BANK4_PDA1f, INVALIDf } }, 262 { INVALIDr } 263 }, 264 { 265 { STAGE0_MEMORY_CONTROL_27r, { BANK4_HIT_PDA0f, INVALIDf } }, 266 { INVALIDr } 267 } 268 } 269 }, 270 { 271 { 272 { 273 { STAGE1_MEMORY_CONTROL_0r, { BANK0_PDA0f, BANK0_PDA1f, INVALIDf } }, 274 { STAGE1_MEMORY_CONTROL_1r, { BANK0_PDA2f, BANK0_PDA3f, INVALIDf } }, 275 { STAGE1_MEMORY_CONTROL_2r, { BANK0_PDA4f, BANK0_PDA5f, INVALIDf } }, 276 { STAGE1_MEMORY_CONTROL_3r, { BANK0_PDA6f, BANK0_PDA7f, INVALIDf } }, 277 { STAGE1_MEMORY_CONTROL_4r, { BANK0_PDA8f, BANK0_PDA9f, INVALIDf } }, 278 { STAGE1_MEMORY_CONTROL_5r, { BANK0_PDA10f, BANK0_PDA11f, INVALIDf } }, 279 { INVALIDr } 280 }, 281 { 282 { STAGE1_MEMORY_CONTROL_23r, { BANK0_HIT_PDA0f, BANK0_HIT_PDA1f, INVALIDf } }, 283 { INVALIDr } 284 } 285 }, 286 { 287 { 288 { STAGE1_MEMORY_CONTROL_10r, { BANK1_PDA0f, BANK1_PDA1f, INVALIDf } }, 289 { STAGE1_MEMORY_CONTROL_11r, { BANK1_PDA2f, BANK1_PDA3f, INVALIDf } }, 290 { STAGE1_MEMORY_CONTROL_12r, { BANK1_PDA4f, BANK1_PDA5f, INVALIDf } }, 291 { INVALIDr } 292 }, 293 { 294 { STAGE1_MEMORY_CONTROL_25r, { BANK1_HIT_PDA0f, INVALIDf } }, 295 { INVALIDr } 296 } 297 }, 298 { 299 { 300 { STAGE1_MEMORY_CONTROL_15r, { BANK2_PDA0f, BANK2_PDA1f, BANK2_PDA2f, 301 BANK2_PDA3f, INVALIDf } }, 302 { STAGE1_MEMORY_CONTROL_16r, { BANK2_PDA4f, BANK2_PDA5f, INVALIDf } }, 303 { INVALIDr } 304 }, 305 { 306 { STAGE1_MEMORY_CONTROL_26r, { BANK2_HIT_PDA0f, INVALIDf } }, 307 { INVALIDr } 308 } 309 }, 310 { 311 { 312 { STAGE1_MEMORY_CONTROL_19r, { BANK3_PDA0f, BANK3_PDA1f, INVALIDf } }, 313 { INVALIDr } 314 }, 315 { 316 { STAGE1_MEMORY_CONTROL_27r, { BANK3_HIT_PDA0f, INVALIDf } }, 317 { INVALIDr } 318 } 319 }, 320 { 321 { 322 { STAGE1_MEMORY_CONTROL_21r, { BANK4_PDA0f, BANK4_PDA1f, INVALIDf } }, 323 { INVALIDr } 324 }, 325 { 326 { STAGE1_MEMORY_CONTROL_27r, { BANK4_HIT_PDA0f, INVALIDf } }, 327 { INVALIDr } 328 } 329 } 330 }, 331 { 332 { 333 { 334 { STAGE2_MEMORY_CONTROL_0r, { BANK0_PDA0f, BANK0_PDA1f, INVALIDf } }, 335 { STAGE2_MEMORY_CONTROL_1r, { BANK0_PDA2f, BANK0_PDA3f, INVALIDf } }, 336 { STAGE2_MEMORY_CONTROL_2r, { BANK0_PDA4f, BANK0_PDA5f, INVALIDf } }, 337 { STAGE2_MEMORY_CONTROL_3r, { BANK0_PDA6f, BANK0_PDA7f, INVALIDf } }, 338 { STAGE2_MEMORY_CONTROL_4r, { BANK0_PDA8f, BANK0_PDA9f, INVALIDf } }, 339 { STAGE2_MEMORY_CONTROL_5r, { BANK0_PDA10f, BANK0_PDA11f, INVALIDf } }, 340 { INVALIDr } 341 }, 342 { 343 { STAGE2_MEMORY_CONTROL_23r, { BANK0_HIT_PDA0f, BANK0_HIT_PDA1f, INVALIDf } }, 344 { INVALIDr } 345 } 346 }, 347 { 348 { 349 { STAGE2_MEMORY_CONTROL_10r, { BANK1_PDA0f, BANK1_PDA1f, INVALIDf } }, 350 { STAGE2_MEMORY_CONTROL_11r, { BANK1_PDA2f, BANK1_PDA3f, INVALIDf } }, 351 { STAGE2_MEMORY_CONTROL_12r, { BANK1_PDA4f, BANK1_PDA5f, INVALIDf } }, 352 { INVALIDr } 353 }, 354 { 355 { STAGE2_MEMORY_CONTROL_25r, { BANK1_HIT_PDA0f, INVALIDf } }, 356 { INVALIDr } 357 } 358 }, 359 { 360 { 361 { STAGE2_MEMORY_CONTROL_15r, { BANK2_PDA0f, BANK2_PDA1f, BANK2_PDA2f, 362 BANK2_PDA3f, INVALIDf } }, 363 { STAGE2_MEMORY_CONTROL_16r, { BANK2_PDA4f, BANK2_PDA5f, INVALIDf } }, 364 { INVALIDr } 365 }, 366 { 367 { STAGE2_MEMORY_CONTROL_26r, { BANK2_HIT_PDA0f, INVALIDf } }, 368 { INVALIDr } 369 } 370 }, 371 { 372 { 373 { STAGE2_MEMORY_CONTROL_19r, { BANK3_PDA0f, BANK3_PDA1f, INVALIDf } }, 374 { INVALIDr } 375 }, 376 { 377 { STAGE2_MEMORY_CONTROL_27r, { BANK3_HIT_PDA0f, INVALIDf } }, 378 { INVALIDr } 379 } 380 }, 381 { 382 { 383 { STAGE2_MEMORY_CONTROL_21r, { BANK4_PDA0f, BANK4_PDA1f, INVALIDf } }, 384 { INVALIDr } 385 }, 386 { 387 { STAGE2_MEMORY_CONTROL_27r, { BANK4_HIT_PDA0f, INVALIDf } }, 388 { INVALIDr } 389 } 390 } 391 }, 392 { 393 { 394 { 395 { STAGE3_MEMORY_CONTROL_0r, { BANK0_PDA0f, BANK0_PDA1f, INVALIDf } }, 396 { STAGE3_MEMORY_CONTROL_1r, { BANK0_PDA2f, BANK0_PDA3f, INVALIDf } }, 397 { STAGE3_MEMORY_CONTROL_2r, { BANK0_PDA4f, BANK0_PDA5f, INVALIDf } }, 398 { STAGE3_MEMORY_CONTROL_3r, { BANK0_PDA6f, BANK0_PDA7f, INVALIDf } }, 399 { STAGE3_MEMORY_CONTROL_4r, { BANK0_PDA8f, BANK0_PDA9f, INVALIDf } }, 400 { STAGE3_MEMORY_CONTROL_5r, { BANK0_PDA10f, BANK0_PDA11f, INVALIDf } }, 401 { INVALIDr } 402 }, 403 { 404 { STAGE3_MEMORY_CONTROL_23r, { BANK0_HIT_PDA0f, BANK0_HIT_PDA1f, INVALIDf } }, 405 { INVALIDr } 406 } 407 }, 408 { 409 { 410 { STAGE3_MEMORY_CONTROL_10r, { BANK1_PDA0f, BANK1_PDA1f, INVALIDf } }, 411 { STAGE3_MEMORY_CONTROL_11r, { BANK1_PDA2f, BANK1_PDA3f, INVALIDf } }, 412 { STAGE3_MEMORY_CONTROL_12r, { BANK1_PDA4f, BANK1_PDA5f, INVALIDf } }, 413 { INVALIDr } 414 }, 415 { 416 { STAGE3_MEMORY_CONTROL_25r, { BANK1_HIT_PDA0f, INVALIDf } }, 417 { INVALIDr } 418 } 419 }, 420 { 421 { 422 { STAGE3_MEMORY_CONTROL_15r, { BANK2_PDA0f, BANK2_PDA1f, BANK2_PDA2f, 423 BANK2_PDA3f, INVALIDf } }, 424 { STAGE3_MEMORY_CONTROL_16r, { BANK2_PDA4f, BANK2_PDA5f, INVALIDf } }, 425 { INVALIDr } 426 }, 427 { 428 { STAGE3_MEMORY_CONTROL_26r, { BANK2_HIT_PDA0f, INVALIDf } }, 429 { INVALIDr } 430 } 431 }, 432 { 433 { 434 { STAGE3_MEMORY_CONTROL_19r, { BANK3_PDA0f, BANK3_PDA1f, INVALIDf } }, 435 { INVALIDr } 436 }, 437 { 438 { STAGE3_MEMORY_CONTROL_27r, { BANK3_HIT_PDA0f, INVALIDf } }, 439 { INVALIDr } 440 } 441 }, 442 { 443 { 444 { STAGE3_MEMORY_CONTROL_21r, { BANK4_PDA0f, BANK4_PDA1f, INVALIDf } }, 445 { INVALIDr } 446 }, 447 { 448 { STAGE3_MEMORY_CONTROL_27r, { BANK4_HIT_PDA0f, INVALIDf } }, 449 { INVALIDr } 450 } 451 } 452 } 453 }; 454 455 /* 456 * Macro used by memory accessor functions to fix order 457 */ 458 #define FIX_MEM_ORDER_E(v,m) (((m)->flags & SOC_MEM_FLAG_BE) ? \ 459 BYTES2WORDS((m)->bytes)-1-(v) : \ 460 (v)) 461 462 /* helper routine */ 463 int 464 soc_ism_get_hash_mem_idx(int unit, soc_mem_t mem) 465 { 466 int8 i; 467 for (i = 0; i < _SOC_ISM_MAX_ISM_MEMS; i++) { 468 if (mem == _SOC_ISM_MEMS(unit)[i].mem) { 469 return i; 470 } 471 } 472 return SOC_E_PARAM; 473 } 474 475 /* helper routine */ 476 int 477 soc_ism_table_to_index(uint32 mem) 478 { 479 int i, idx = -1; 480 for (i = 0; i < COUNTOF(mem_info_entry); i++) { 481 if (mem == mem_info_entry[i].mem) { 482 idx = mem_info_entry[i].index; 483 break; 484 } 485 } 486 return idx; 487 } 488 489 /* helper routine */ 490 char * 491 soc_ism_table_to_name(uint32 mem) 492 { 493 int i; 494 for (i = 0; i < COUNTOF(mem_info_entry); i++) { 495 if (mem == mem_info_entry[i].mem) { 496 return mem_info_entry[i].name; 497 break; 498 } 499 } 500 return NULL; 501 } 502 503 /* Fill _soc_ism_log_to_phy_map based upon _soc_ism_table_bank_config */ 504 STATIC int 505 soc_ism_log_to_phy_fill(int unit) 506 { 507 int32 tab, b, c, r; 508 int8 bank; 509 for (tab = 0; tab < _SOC_ISM_MAX_TABLES; tab++) { 510 r = 0; 511 for (b = 0; b < SOC_ISM_INFO(unit)->max_banks; b++) { 512 bank = ((b%_SOC_ISM_MAX_STAGES) * 513 SOC_ISM_INFO(unit)->banks_per_stage) + 514 (b/_SOC_ISM_MAX_STAGES); 515 if (_soc_ism_table_bank_config[unit][tab][bank]) { 516 for (c = 0; c < 517 SOC_ISM_INFO(unit)->real_bank_map[bank].count; c++) { 518 _soc_ism_log_to_phy_map[unit][tab][r] = 519 SOC_ISM_INFO(unit)->real_bank_map[bank].index[c]; 520 r++; 521 } 522 _soc_ism_table_raw_bank_count[unit][tab] += 523 SOC_ISM_INFO(unit)->real_bank_map[bank].count; 524 if (_soc_ism_table_raw_bank_count[unit][tab] > 525 SOC_ISM_INFO(unit)->total_banks) { 526 return SOC_E_PARAM; 527 } 528 } 529 } 530 } 531 return SOC_E_NONE; 532 } 533 534 STATIC soc_mem_t _ism_log_to_phy_mem[] = { 535 TABLE0_LOG_TO_PHY_MAPm, TABLE1_LOG_TO_PHY_MAPm, 536 TABLE2_LOG_TO_PHY_MAPm, TABLE3_LOG_TO_PHY_MAPm, 537 TABLE4_LOG_TO_PHY_MAPm 538 }; 539 540 /* Write _soc_ism_log_to_phy_map to TABLEx_LOG_TO_PHY_MAPm */ 541 STATIC int 542 soc_ism_log_to_phy_set(int unit) 543 { 544 int tab, bank; 545 uint32 entry[SOC_MAX_MEM_WORDS]; 546 for (tab = 0; tab < _SOC_ISM_MAX_TABLES; tab++) { 547 LOG_INFO(BSL_LS_SOC_SOCMEM, 548 (BSL_META_U(unit, 549 "Table: %d\n"), tab)); 550 for (bank = 0; bank < SOC_ISM_INFO(unit)->total_banks; bank++) { 551 LOG_INFO(BSL_LS_SOC_SOCMEM, 552 (BSL_META_U(unit, 553 "[%d]-%d "), bank, 554 _soc_ism_log_to_phy_map[unit][tab][bank])); 555 sal_memset(&entry, 0, sizeof(entry)); 556 soc_mem_field32_set(unit, _ism_log_to_phy_mem[tab], entry, 557 LOG_TO_PHY_MAPf, 558 _soc_ism_log_to_phy_map[unit][tab][bank]); 559 /* Write to TABLEx_LOG_TO_PHY_MAPm memory */ 560 SOC_IF_ERROR_RETURN 561 (soc_mem_write(unit, _ism_log_to_phy_mem[tab], 562 MEM_BLOCK_ALL, bank, &entry)); 563 } 564 LOG_INFO(BSL_LS_SOC_SOCMEM, 565 (BSL_META_U(unit, 566 "\n"))); 567 } 568 return SOC_E_NONE; 569 } 570 571 soc_reg_t _ism_table_bank_cfg_reg[] = { 572 TABLE0_BANK_CONFIGr, TABLE1_BANK_CONFIGr, 573 TABLE2_BANK_CONFIGr, TABLE3_BANK_CONFIGr, 574 TABLE4_BANK_CONFIGr 575 }; 576 577 soc_field_t _ism_table_bank_cfg_fld[] = { 578 STAGE0_BANKSf, STAGE1_BANKSf, 579 STAGE2_BANKSf, STAGE3_BANKSf 580 }; 581 582 /* Write _soc_ism_table_bank_config to TABLEx_BANK_CONFIG registers */ 583 STATIC int 584 soc_ism_table_bank_set(int unit) 585 { 586 int tab, stg, bank, offset; 587 uint32 rval, val; 588 for (tab = 0; tab < _SOC_ISM_MAX_TABLES; tab++) { 589 if (!_soc_ism_table_bank_count[unit][tab]) { 590 continue; 591 } 592 LOG_INFO(BSL_LS_SOC_SOCMEM, 593 (BSL_META_U(unit, 594 "Table: %d\n"), tab)); 595 SOC_IF_ERROR_RETURN 596 (soc_reg32_get(unit, _ism_table_bank_cfg_reg[tab], REG_PORT_ANY, 597 0, &rval)); 598 for (stg = 0; stg < _SOC_ISM_MAX_STAGES; stg++) { 599 val = 0; 600 /* Take disabled bank into account */ 601 offset = ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_96) || 602 (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_80)) ? 603 ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_64) ? 2 : 1) : 0; 604 for (bank = 0; bank < SOC_ISM_INFO(unit)->banks_per_stage; bank++) { 605 val |= _soc_ism_table_bank_config[unit][tab] 606 [(stg*SOC_ISM_INFO(unit)->banks_per_stage)+bank] << (bank + offset); 607 } 608 LOG_INFO(BSL_LS_SOC_SOCMEM, 609 (BSL_META_U(unit, 610 "stage: %d - bmask: %x "), stg, val)); 611 612 soc_reg_field_set(unit, _ism_table_bank_cfg_reg[tab], 613 &rval, _ism_table_bank_cfg_fld[stg], 614 val); 615 } 616 if (SOC_ISM_INFO(unit)->ism_mode != _ISM_SIZE_MODE_512) { 617 soc_reg_field_set(unit, _ism_table_bank_cfg_reg[tab], 618 &rval, MAPPING_MODEf, 1); 619 } 620 /* Write to TABLEx_BANK_CONFIG register */ 621 SOC_IF_ERROR_RETURN 622 (soc_reg32_set(unit, _ism_table_bank_cfg_reg[tab], 623 REG_PORT_ANY, 0, rval)); 624 LOG_INFO(BSL_LS_SOC_SOCMEM, 625 (BSL_META_U(unit, 626 "\n"))); 627 } 628 return SOC_E_NONE; 629 } 630 631 /* helper routine to sort and prioritize mem types based upon allocation rules */ 632 STATIC void 633 _soc_ism_sort_mems(soc_ism_mem_size_config_t *i_mem_cfg, int count, 634 soc_ism_mem_size_config_t *o_mem_cfg) 635 { 636 int i, j, esm = 0, ism = 0; 637 soc_ism_mem_size_config_t tmp; 638 soc_ism_mem_size_config_t arr[SOC_ISM_MEM_TOTAL]; 639 640 sal_memset(o_mem_cfg, 0, 641 sizeof(soc_ism_mem_size_config_t) * SOC_ISM_MEM_TOTAL); 642 sal_memcpy(o_mem_cfg, i_mem_cfg, 643 sizeof(soc_ism_mem_size_config_t) * count); 644 if (count == 1) { 645 return; 646 } 647 /* Search for and fetch ESM mems */ 648 for (i = 0; i < count; i++) { 649 if (i_mem_cfg[i].mem >= SOC_ISM_MEM_MAX) { 650 arr[esm] = i_mem_cfg[i]; 651 esm++; 652 } 653 } 654 if (esm) { 655 /* sort esm mems */ 656 for (i = 0; i < esm; i++) { 657 for (j = 0; j < esm - i - 1; j++) { 658 if (arr[j].size < arr[j+1].size) { 659 sal_memcpy(&tmp, &arr[j], 660 sizeof(soc_ism_mem_size_config_t)); 661 sal_memcpy(&arr[j], &arr[j+1], 662 sizeof(soc_ism_mem_size_config_t)); 663 sal_memcpy(&arr[j+1], &tmp, 664 sizeof(soc_ism_mem_size_config_t)); 665 } 666 } 667 } 668 /* copy back sorted esm mems */ 669 sal_memcpy(o_mem_cfg, arr, 670 sizeof(soc_ism_mem_size_config_t) * esm); 671 if ((count - esm) == 0) { 672 return; 673 } 674 } 675 /* Search for and fetch ISM mems */ 676 for (i = 0; i < count; i++) { 677 if (i_mem_cfg[i].mem < SOC_ISM_MEM_MAX) { 678 arr[ism] = i_mem_cfg[i]; 679 ism++; 680 } 681 } 682 if (ism) { 683 /* sort ism mems */ 684 for (i = 0; i < ism; i++) { 685 for (j = 0; j < ism - i - 1; j++) { 686 if (arr[j].size < arr[j+1].size) { 687 sal_memcpy(&tmp, &arr[j], 688 sizeof(soc_ism_mem_size_config_t)); 689 sal_memcpy(&arr[j], &arr[j+1], 690 sizeof(soc_ism_mem_size_config_t)); 691 sal_memcpy(&arr[j+1], &tmp, 692 sizeof(soc_ism_mem_size_config_t)); 693 } 694 } 695 } 696 /* copy back sorted esm mems */ 697 sal_memcpy(&o_mem_cfg[esm], arr, 698 sizeof(soc_ism_mem_size_config_t) * ism); 699 } 700 } 701 702 uint32 703 _soc_ism_bank_total(int unit) 704 { 705 uint8 i; 706 uint32 total = 0; 707 for (i = 0; i < SOC_ISM_INFO(unit)->max_banks; i++) { 708 total += SOC_ISM_INFO(unit)->bank_raw_sizes[i]; 709 } 710 return total; 711 } 712 713 /* helper routine to sort and prioritize mem types based upon allocation rules */ 714 STATIC void 715 _soc_ism_sort_mems_with_banks(int unit, soc_ism_mem_size_config_t *i_mem_cfg, int count, 716 soc_ism_mem_size_config_t *o_mem_cfg) 717 { 718 int i, j, esm = 0, ism = 0, ism_banks = 0; 719 soc_ism_mem_size_config_t tmp; 720 soc_ism_mem_size_config_t arr[SOC_ISM_MEM_TOTAL]; 721 int c_midx = -1, n_midx = -1; 722 int c_epb, n_epb; 723 724 sal_memset(o_mem_cfg, 0, 725 sizeof(soc_ism_mem_size_config_t) * SOC_ISM_MEM_TOTAL); 726 if (count == 1) { 727 sal_memcpy(o_mem_cfg, i_mem_cfg, 728 sizeof(soc_ism_mem_size_config_t) * count); 729 return; 730 } 731 /* Search for and fetch ESM mems */ 732 for (i = 0; i < count; i++) { 733 if (i_mem_cfg[i].mem >= SOC_ISM_MEM_MAX) { 734 arr[esm] = i_mem_cfg[i]; 735 esm++; 736 } 737 } 738 if (esm) { 739 /* sort esm mems */ 740 for (i = 0; i < esm; i++) { 741 for (j = 0; j < esm - i - 1; j++) { 742 if (arr[j].size < arr[j+1].size) { 743 sal_memcpy(&tmp, &arr[j], 744 sizeof(soc_ism_mem_size_config_t)); 745 sal_memcpy(&arr[j], &arr[j+1], 746 sizeof(soc_ism_mem_size_config_t)); 747 sal_memcpy(&arr[j+1], &tmp, 748 sizeof(soc_ism_mem_size_config_t)); 749 } 750 } 751 } 752 /* copy back sorted esm mems */ 753 sal_memcpy(o_mem_cfg, arr, 754 sizeof(soc_ism_mem_size_config_t) * esm); 755 if ((count - esm) == 0) { 756 return; 757 } 758 } 759 /* Search for and fetch ISM mems with banks */ 760 for (i = 0; i < count; i++) { 761 if ((i_mem_cfg[i].mem < SOC_ISM_MEM_MAX) && 762 i_mem_cfg[i].banks) { 763 arr[ism_banks] = i_mem_cfg[i]; 764 ism_banks++; 765 } 766 } 767 if (ism_banks) { 768 /* sort ism mems with banks */ 769 for (i = 0; i < ism_banks; i++) { 770 for (j = 0; j < ism_banks - i - 1; j++) { 771 c_midx = soc_ism_table_to_index(arr[j].mem); 772 n_midx = soc_ism_table_to_index(arr[j + 1].mem); 773 if ((c_midx >= 0) && (n_midx >= 0)) { 774 c_epb = mem_info_entry[c_midx].epb; 775 n_epb = mem_info_entry[n_midx].epb; 776 } else { 777 c_epb = n_epb = 1; 778 } 779 if ((arr[j].size / c_epb) < (arr[j+1].size / n_epb)) { 780 sal_memcpy(&tmp, &arr[j], 781 sizeof(soc_ism_mem_size_config_t)); 782 sal_memcpy(&arr[j], &arr[j+1], 783 sizeof(soc_ism_mem_size_config_t)); 784 sal_memcpy(&arr[j+1], &tmp, 785 sizeof(soc_ism_mem_size_config_t)); 786 } 787 } 788 } 789 /* copy back sorted ism mems with banks */ 790 sal_memcpy(&o_mem_cfg[esm], arr, 791 sizeof(soc_ism_mem_size_config_t) * ism_banks); 792 if ((count - esm - ism_banks) == 0) { 793 return; 794 } 795 } 796 /* Search for and fetch ISM mems */ 797 for (i = 0; i < count; i++) { 798 if ((i_mem_cfg[i].mem < SOC_ISM_MEM_MAX) && 799 !i_mem_cfg[i].banks) { 800 arr[ism] = i_mem_cfg[i]; 801 ism++; 802 } 803 } 804 if (ism) { 805 /* sort ism mems */ 806 for (i = 0; i < ism; i++) { 807 for (j = 0; j < ism - i - 1; j++) { 808 c_midx = soc_ism_table_to_index(arr[j].mem); 809 n_midx = soc_ism_table_to_index(arr[j + 1].mem); 810 if ((c_midx >= 0) && (n_midx >= 0)) { 811 c_epb = mem_info_entry[c_midx].epb; 812 n_epb = mem_info_entry[n_midx].epb; 813 } else { 814 c_epb = n_epb = 1; 815 } 816 if ((arr[j].size / c_epb) < (arr[j+1].size / n_epb)) { 817 sal_memcpy(&tmp, &arr[j], 818 sizeof(soc_ism_mem_size_config_t)); 819 sal_memcpy(&arr[j], &arr[j+1], 820 sizeof(soc_ism_mem_size_config_t)); 821 sal_memcpy(&arr[j+1], &tmp, 822 sizeof(soc_ism_mem_size_config_t)); 823 } 824 } 825 } 826 /* copy back sorted ism mems */ 827 sal_memcpy(&o_mem_cfg[esm + ism_banks], arr, 828 sizeof(soc_ism_mem_size_config_t) * ism); 829 } 830 } 831 832 STATIC int 833 _soc_ism_mem_allocation_log(int unit, soc_ism_mem_size_config_t *ism_hash_tables, int count) 834 { 835 int tab, idx, bank = 0; 836 int midx; 837 uint32 mem; 838 for (tab = 0; tab < count && tab < SOC_ISM_MEM_TOTAL; tab++) { 839 mem = ism_hash_tables[tab].mem; 840 midx = soc_ism_table_to_index(mem); 841 if (midx == -1) { 842 return SOC_E_PARAM; 843 } 844 for (idx = 0; idx < SOC_ISM_INFO(unit)->max_banks; idx++) { 845 bank = ((idx%_SOC_ISM_MAX_STAGES) * 846 SOC_ISM_INFO(unit)->banks_per_stage) + 847 (idx/_SOC_ISM_MAX_STAGES); 848 if (mem == _soc_ism_bank_avail[unit][bank]) { 849 LOG_VERBOSE(BSL_LS_SOC_COMMON, 850 (BSL_META_U(unit, 851 "Allocated bank %d for ISM mem:[%s], size:%d banksize :%d\n"), 852 bank, 853 soc_ism_table_to_name(ism_hash_tables[tab].mem), 854 ism_hash_tables[tab].size, 855 SOC_ISM_INFO(unit)->bank_raw_sizes[bank])); 856 } 857 } 858 } 859 return SOC_E_NONE; 860 861 } 862 863 int 864 soc_ism_mem_config_with_banks(int unit, soc_ism_mem_size_config_t *mem_cfg, int count) 865 { 866 int tab, idx, bank = 0, next_bank; 867 int midx, size, rem; 868 uint32 mem; 869 uint8 avail, undo_flag = FALSE, i; 870 soc_ism_mem_size_config_t ism_hash_tables[SOC_ISM_MEM_TOTAL]; 871 soc_persist_t *sop = SOC_PERSIST(unit); 872 uint32 total_size = 0, min_bank_size; 873 uint32 total_banks = 0; 874 _soc_ism_bank_trace_t bank_trace[SOC_ISM_MEM_TOTAL][_SOC_ISM_MAX_BANKS]; 875 uint32 orig_mem_size[SOC_ISM_MEM_TOTAL]; 876 877 total_banks = soc_property_get(unit, spn_VLAN_XLATE_MEM_BANKS, 0) + 878 soc_property_get(unit, spn_L2_MEM_BANKS, 0) + 879 soc_property_get(unit, spn_L3_MEM_BANKS, 0) + 880 soc_property_get(unit, spn_EGR_VLAN_XLATE_MEM_BANKS, 0) + 881 soc_property_get(unit, spn_MPLS_MEM_BANKS, 0); 882 if (total_banks > SOC_ISM_INFO(unit)->max_banks) { 883 LOG_ERROR(BSL_LS_SOC_COMMON, 884 (BSL_META_U(unit, 885 "Total requested banks[R:%d A:%d]\n"), 886 total_banks, SOC_ISM_INFO(unit)->max_banks)); 887 return SOC_E_PARAM; 888 } 889 890 891 _soc_ism_sort_mems_with_banks(unit, mem_cfg, count, ism_hash_tables); 892 893 /* Get the min bank size available 894 * Last bank is the smallest bank 895 */ 896 bank = SOC_ISM_INFO(unit)->max_banks - 1; 897 min_bank_size = SOC_ISM_INFO(unit)->bank_raw_sizes[bank]; 898 899 for (tab = 0; tab < count && tab < SOC_ISM_MEM_TOTAL; tab++) { 900 mem = ism_hash_tables[tab].mem; 901 midx = soc_ism_table_to_index(mem); 902 if (midx == -1) { 903 return SOC_E_PARAM; 904 } 905 /* Normalize mem entries */ 906 size = ism_hash_tables[tab].size / mem_info_entry[midx].epb; 907 rem = size % _SOC_ISM_ENTRY_SIZE_QUANTA; 908 if (rem) { 909 size = size + (_SOC_ISM_ENTRY_SIZE_QUANTA - rem); 910 LOG_VERBOSE(BSL_LS_SOC_COMMON, 911 (BSL_META_U(unit, 912 "Updated size %s: %d\n"), 913 soc_ism_table_to_name(mem), size * mem_info_entry[midx].epb)); 914 } 915 ism_hash_tables[tab].size = size * mem_info_entry[midx].epb; 916 /* Requested avg bank size should be atleast min bank size */ 917 if (ism_hash_tables[tab].banks && 918 ((size / ism_hash_tables[tab].banks) < min_bank_size)) { 919 LOG_ERROR(BSL_LS_SOC_COMMON, 920 (BSL_META_U(unit, 921 "Avg size bank[%d] should be atleast min bank size[%d] for mem: %s\n"), 922 (size / ism_hash_tables[tab].banks), min_bank_size, 923 soc_ism_table_to_name(mem))); 924 return SOC_E_PARAM; 925 } 926 total_size += size; 927 orig_mem_size[tab] = ism_hash_tables[tab].size; 928 LOG_VERBOSE(BSL_LS_SOC_COMMON, 929 (BSL_META_U(unit, 930 "ISM Normalized mem: [%s], size: %d\n"), 931 soc_ism_table_to_name(ism_hash_tables[tab].mem), 932 ism_hash_tables[tab].size)); 933 } 934 935 /* Sanity check */ 936 if (total_size > _soc_ism_bank_total(unit)) { 937 LOG_ERROR(BSL_LS_SOC_COMMON, 938 (BSL_META_U(unit, 939 "Total requested size is more than available[R:%d A:%d\n"), 940 total_size, _soc_ism_bank_total(unit))); 941 return SOC_E_PARAM; 942 } 943 944 avail = SOC_ISM_INFO(unit)->max_banks; 945 tab = 0; 946 idx = 0; 947 sal_memset(bank_trace, 0, sizeof(_soc_ism_bank_trace_t) * SOC_ISM_MEM_TOTAL *_SOC_ISM_MAX_BANKS); 948 949 while (tab < count && tab < SOC_ISM_MEM_TOTAL) { 950 mem = ism_hash_tables[tab].mem; 951 midx = soc_ism_table_to_index(mem); 952 if (midx == -1) { 953 return SOC_E_PARAM; 954 } 955 956 if (!ism_hash_tables[tab].size) { 957 tab++; 958 continue; 959 } 960 961 size = ism_hash_tables[tab].size / mem_info_entry[midx].epb; 962 if (undo_flag && ism_hash_tables[tab].allocated_banks) { 963 /* Update remaining size based on previous allocation */ 964 for (i = 0; i < ism_hash_tables[tab].allocated_banks ; i++) { 965 bank = bank_trace[tab][i].bank; 966 size -= SOC_ISM_INFO(unit)->bank_raw_sizes[bank]; 967 } 968 undo_flag = FALSE; 969 idx = bank_trace[tab][ism_hash_tables[tab].allocated_banks - 1].index; 970 bank = bank_trace[tab][ism_hash_tables[tab].allocated_banks - 1].bank; 971 ism_hash_tables[tab].allocated_banks--; 972 _soc_ism_bank_avail[unit][bank] = 0; 973 /* ISM mem only */ 974 if (mem < SOC_ISM_MEM_MAX) { 975 _soc_ism_table_bank_count[unit][midx]--; 976 _soc_ism_table_bank_config[unit][midx][bank] = 0; 977 } 978 size += SOC_ISM_INFO(unit)->bank_raw_sizes[bank]; 979 idx++; 980 avail++; 981 /* Find next bank size is other than rolled back value */ 982 while( idx < SOC_ISM_INFO(unit)->max_banks) { 983 next_bank = ((idx%_SOC_ISM_MAX_STAGES) * 984 SOC_ISM_INFO(unit)->banks_per_stage) + (idx/_SOC_ISM_MAX_STAGES); 985 986 if (!(_soc_ism_bank_avail[unit][next_bank] || 987 (SOC_ISM_INFO(unit)->bank_raw_sizes[bank] == SOC_ISM_INFO(unit)->bank_raw_sizes[next_bank]))) { 988 break; 989 } 990 idx++; 991 } 992 } 993 do { 994 for (; idx < SOC_ISM_INFO(unit)->max_banks; idx++) { 995 bank = ((idx%_SOC_ISM_MAX_STAGES) * 996 SOC_ISM_INFO(unit)->banks_per_stage) + (idx/_SOC_ISM_MAX_STAGES); 997 998 if (_soc_ism_bank_avail[unit][bank]) { 999 continue; 1000 } 1001 1002 /* Rule: ESM stuff can only be in banks >= 4k in size */ 1003 if (mem >= SOC_ISM_MEM_MAX && 1004 SOC_ISM_INFO(unit)->bank_raw_sizes[bank] < 1024*4) { 1005 continue; 1006 } 1007 1008 /* Skip if size and required banks criteria NOT meet */ 1009 if ((size == SOC_ISM_INFO(unit)->bank_raw_sizes[bank]) && 1010 (ism_hash_tables[tab].banks > 1011 (ism_hash_tables[tab].allocated_banks + 1))) { 1012 continue; 1013 } 1014 1015 /* Free bank found */ 1016 if (size >= SOC_ISM_INFO(unit)->bank_raw_sizes[bank]) { 1017 /* populate trace info */ 1018 bank_trace[tab][ism_hash_tables[tab].allocated_banks].index = idx; 1019 bank_trace[tab][ism_hash_tables[tab].allocated_banks].bank = bank; 1020 1021 size -= SOC_ISM_INFO(unit)->bank_raw_sizes[bank]; 1022 ism_hash_tables[tab].allocated_banks++; 1023 _soc_ism_bank_avail[unit][bank] = mem; 1024 1025 /* ISM mem only */ 1026 if (mem < SOC_ISM_MEM_MAX) { 1027 _soc_ism_table_bank_count[unit][midx]++; 1028 if (_soc_ism_table_bank_count[unit][midx] > 1029 SOC_ISM_INFO(unit)->max_banks) { 1030 return SOC_E_PARAM; 1031 } 1032 _soc_ism_table_bank_config[unit][midx][bank] = 1; 1033 } 1034 avail--; 1035 } 1036 1037 /* When required size is allocated check and 1038 * required number of banks are also allocated 1039 */ 1040 if (!size && (!ism_hash_tables[tab].banks || 1041 (ism_hash_tables[tab].banks <= 1042 ism_hash_tables[tab].allocated_banks))) { 1043 break; 1044 } 1045 } 1046 1047 /* Either required banks or size certiera not meet 1048 * using trace roll bank and go for next best fit bank 1049 */ 1050 if (size && ism_hash_tables[tab].allocated_banks) { 1051 /* No Free banks remaining. 1052 * Reordering can't be done for this memory 1053 */ 1054 if (!avail) { 1055 break; 1056 } 1057 idx = bank_trace[tab][ism_hash_tables[tab].allocated_banks - 1].index; 1058 bank = bank_trace[tab][ism_hash_tables[tab].allocated_banks - 1].bank; 1059 ism_hash_tables[tab].allocated_banks--; 1060 _soc_ism_bank_avail[unit][bank] = 0; 1061 /* ISM mem only */ 1062 if (mem < SOC_ISM_MEM_MAX) { 1063 _soc_ism_table_bank_count[unit][midx]--; 1064 _soc_ism_table_bank_config[unit][midx][bank] = 0; 1065 } 1066 size += SOC_ISM_INFO(unit)->bank_raw_sizes[bank]; 1067 idx++; 1068 avail++; 1069 /* Find next bank size is other than rolled back value */ 1070 while( idx < SOC_ISM_INFO(unit)->max_banks) { 1071 next_bank = ((idx%_SOC_ISM_MAX_STAGES) * 1072 SOC_ISM_INFO(unit)->banks_per_stage) + (idx/_SOC_ISM_MAX_STAGES); 1073 1074 if (!(_soc_ism_bank_avail[unit][next_bank] || 1075 (SOC_ISM_INFO(unit)->bank_raw_sizes[bank] == SOC_ISM_INFO(unit)->bank_raw_sizes[next_bank]))) { 1076 break; 1077 } 1078 idx++; 1079 } 1080 } else if (size && 1081 (idx >= SOC_ISM_INFO(unit)->max_banks)) { 1082 /* Bump up num of entries to allocate the next bigger bank 1083 * At this point all previsously allocated banks 1084 * have been rolled back 1085 */ 1086 size += _SOC_ISM_ENTRY_SIZE_QUANTA; 1087 ism_hash_tables[tab].size += (_SOC_ISM_ENTRY_SIZE_QUANTA * mem_info_entry[midx].epb); 1088 idx = 0; 1089 if (size > _soc_ism_bank_total(unit)) { 1090 break; 1091 } 1092 } 1093 } while (size && avail); 1094 1095 if (size) { 1096 /* Roll back if any previous table was allocated */ 1097 if (tab) { 1098 /* Roll back all the allocations in the current table and 1099 * last allocation in previous table 1100 */ 1101 for (i = ism_hash_tables[tab].allocated_banks ; i > 0 ; i--) { 1102 bank = bank_trace[tab][ism_hash_tables[tab].allocated_banks - 1].bank; 1103 _soc_ism_bank_avail[unit][bank] = 0; 1104 /* ISM mem only */ 1105 if (mem < SOC_ISM_MEM_MAX) { 1106 _soc_ism_table_bank_count[unit][midx]--; 1107 _soc_ism_table_bank_config[unit][midx][bank] = 0; 1108 } 1109 avail++; 1110 ism_hash_tables[tab].allocated_banks--; 1111 } 1112 /* Restore orignial mem size to undo size bump for this memory */ 1113 ism_hash_tables[tab].size = orig_mem_size[tab]; 1114 tab--; 1115 /* Skip ESM memories or zero size memories */ 1116 while((tab >= 0) && (!ism_hash_tables[tab].size || 1117 (ism_hash_tables[tab].mem >= SOC_ISM_MEM_MAX))) { 1118 tab--; 1119 } 1120 if (tab < 0) { 1121 return SOC_E_PARAM; 1122 } 1123 idx = 0; 1124 /* Set flag, so that last allocated bank will be undo 1125 * at the start of the next loop 1126 */ 1127 if (ism_hash_tables[tab].allocated_banks) { 1128 undo_flag = TRUE; 1129 } 1130 } else { 1131 LOG_ERROR(BSL_LS_SOC_COMMON, 1132 (BSL_META_U(unit, 1133 "Could not allocate banks for mem: %s\n"), 1134 soc_ism_table_to_name(mem))); 1135 return SOC_E_PARAM; 1136 } 1137 } else { 1138 idx = 0; 1139 size = ism_hash_tables[tab].size; 1140 switch (mem) { 1141 case SOC_ISM_MEM_VLAN_XLATE: 1142 sop->memState[VLAN_XLATEm].index_max += (size * 2); 1143 sop->memState[VLAN_XLATE_1m].index_max += (size * 2); 1144 sop->memState[VLAN_XLATE_1_HIT_ONLYm].index_max += (size * 2); 1145 sop->memState[VLAN_XLATE_EXTDm].index_max += size; 1146 sop->memState[VLAN_XLATE_2_HIT_ONLYm].index_max += size; 1147 break; 1148 case SOC_ISM_MEM_L2_ENTRY: 1149 sop->memState[L2_ENTRY_1m].index_max += (size * 2) ; 1150 sop->memState[L2_ENTRY_1_HIT_ONLYm].index_max += (size * 2) ; 1151 sop->memState[L2_ENTRY_2m].index_max += size ; 1152 sop->memState[L2_ENTRY_2_HIT_ONLYm].index_max += size ; 1153 break; 1154 case SOC_ISM_MEM_L3_ENTRY: 1155 sop->memState[L3_ENTRY_1m].index_max += (size * 4); 1156 sop->memState[L3_ENTRY_1_HIT_ONLYm].index_max += (size * 4); 1157 sop->memState[L3_ENTRY_2m].index_max += (size * 2); 1158 sop->memState[L3_ENTRY_2_HIT_ONLYm].index_max += (size * 2); 1159 sop->memState[L3_ENTRY_4m].index_max += size; 1160 sop->memState[L3_ENTRY_4_HIT_ONLYm].index_max += size; 1161 break; 1162 case SOC_ISM_MEM_EP_VLAN_XLATE: 1163 sop->memState[EGR_VLAN_XLATEm].index_max += size; 1164 sop->memState[EP_VLAN_XLATE_1m].index_max += size; 1165 sop->memState[EP_VLAN_XLATE_1_HIT_ONLYm].index_max += size; 1166 break; 1167 case SOC_ISM_MEM_MPLS: 1168 sop->memState[MPLS_ENTRYm].index_max += (size * 2); 1169 sop->memState[MPLS_ENTRY_1m].index_max += (size * 2); 1170 sop->memState[MPLS_ENTRY_1_HIT_ONLYm].index_max += (size * 2); 1171 sop->memState[MPLS_ENTRY_EXTDm].index_max += size; 1172 sop->memState[MPLS_ENTRY_2_HIT_ONLYm].index_max += size; 1173 break; 1174 case SOC_ISM_MEM_ESM_L2: 1175 case SOC_ISM_MEM_ESM_L3: 1176 case SOC_ISM_MEM_ESM_ACL: 1177 break; 1178 default: return SOC_E_PARAM; 1179 } 1180 tab++; 1181 } 1182 } 1183 _soc_ism_mem_allocation_log(unit, ism_hash_tables, count); 1184 1185 return SOC_E_NONE; 1186 } 1187 1188 /* Support simple, sequential configuration for now and 1189 fill _soc_ism_table_bank_config based upon driver memory config */ 1190 int 1191 soc_ism_mem_config(int unit, soc_ism_mem_size_config_t *mem_cfg, int count) 1192 { 1193 int rv, tab, idx, bank; 1194 int midx, size; 1195 uint16 dev_id; 1196 uint8 rev_id; 1197 uint32 mem, _ism_total = 0; 1198 soc_ism_mem_size_config_t ism_hash_tables[SOC_ISM_MEM_TOTAL]; 1199 soc_persist_t *sop = SOC_PERSIST(unit); 1200 SOC_ISM_INFO(unit) = &_soc_ism_info[unit]; 1201 SOC_ISM_HASH_INFO(unit) = &_soc_ism_hash_info[unit]; 1202 1203 sal_memset(&_soc_ism_bank_avail[unit], 0, 1204 sizeof(uint32) * _SOC_ISM_MAX_BANKS); 1205 sal_memset(&_soc_ism_table_bank_count[unit], 0, 1206 sizeof(uint32) * _SOC_ISM_MAX_TABLES); 1207 sal_memset(&_soc_ism_table_bank_config[unit], 0, 1208 sizeof(uint8) * _SOC_ISM_MAX_TABLES * _SOC_ISM_MAX_BANKS); 1209 sal_memset(&_soc_ism_table_raw_bank_count[unit], 0, 1210 sizeof(uint32) * _SOC_ISM_MAX_TABLES); 1211 sal_memset(&_soc_ism_log_to_phy_map[unit], 0, 1212 sizeof(uint32) * _SOC_ISM_MAX_TABLES * _SOC_ISM_TOTAL_BANKS); 1213 1214 soc_cm_get_id(unit, &dev_id, &rev_id); 1215 switch (dev_id) { 1216 case BCM56640_DEVICE_ID: 1217 case BCM56643_DEVICE_ID: 1218 case BCM56644_DEVICE_ID: 1219 SOC_ISM_INFO(unit)->ism_mode = _ISM_SIZE_MODE_512; 1220 break; 1221 case BCM56648_DEVICE_ID: 1222 case BCM56649_DEVICE_ID: 1223 case BCM56540_DEVICE_ID: 1224 case BCM56541_DEVICE_ID: 1225 case BCM56542_DEVICE_ID: 1226 case BCM56544_DEVICE_ID: 1227 case BCM56545_DEVICE_ID: 1228 case BCM56546_DEVICE_ID: 1229 SOC_ISM_INFO(unit)->ism_mode = _ISM_SIZE_MODE_176; 1230 break; 1231 case BCM56543_DEVICE_ID: 1232 SOC_ISM_INFO(unit)->ism_mode = _ISM_SIZE_MODE_256; 1233 break; 1234 case BCM56044_DEVICE_ID: 1235 case BCM56045_DEVICE_ID: 1236 case BCM56046_DEVICE_ID: 1237 SOC_ISM_INFO(unit)->ism_mode = _ISM_SIZE_MODE_80; 1238 break; 1239 #ifdef BCM_HELIX4_SUPPORT 1240 case BCM56548H_DEVICE_ID: 1241 case BCM56548_DEVICE_ID: 1242 case BCM56547_DEVICE_ID: 1243 case BCM56344_DEVICE_ID: 1244 case BCM56342_DEVICE_ID: 1245 case BCM56340_DEVICE_ID: 1246 SOC_ISM_INFO(unit)->ism_mode = _ISM_SIZE_MODE_96; 1247 break; 1248 case BCM56042_DEVICE_ID: 1249 case BCM56041_DEVICE_ID: 1250 case BCM56040_DEVICE_ID: 1251 case BCM56049_DEVICE_ID: 1252 case BCM56048_DEVICE_ID: 1253 case BCM56047_DEVICE_ID: 1254 case BCM56346_DEVICE_ID: 1255 case BCM56345_DEVICE_ID: 1256 SOC_ISM_INFO(unit)->ism_mode = _ISM_SIZE_MODE_80; 1257 break; 1258 #endif 1259 default: 1260 return SOC_E_PARAM; 1261 } 1262 1263 switch (SOC_ISM_INFO(unit)->ism_mode) { 1264 case _ISM_SIZE_MODE_512: 1265 SOC_ISM_INFO(unit)->bank_raw_sizes = _soc_ism_bank_raw_sizes; 1266 SOC_ISM_INFO(unit)->banks_per_stage = _SOC_ISM_BANKS_PER_STAGE; 1267 SOC_ISM_INFO(unit)->max_banks = _SOC_ISM_MAX_BANKS; 1268 SOC_ISM_INFO(unit)->total_banks = _SOC_ISM_TOTAL_BANKS; 1269 SOC_ISM_INFO(unit)->total_entries = _SOC_ISM_ENTRIES_PER_BKT * 1270 _soc_ism_bank_total(unit); 1271 SOC_ISM_INFO(unit)->max_raw_banks = _SOC_ISM_MAX_RAW_BANKS; 1272 SOC_ISM_INFO(unit)->real_bank_map = _soc_ism_real_bank_map; 1273 break; 1274 case _ISM_SIZE_MODE_256: 1275 SOC_ISM_INFO(unit)->bank_raw_sizes = _soc_ism_bank_raw_sizes_256; 1276 SOC_ISM_INFO(unit)->banks_per_stage = _SOC_ISM_BANKS_PER_STAGE; 1277 SOC_ISM_INFO(unit)->max_banks = _SOC_ISM_MAX_BANKS; 1278 SOC_ISM_INFO(unit)->total_banks = _SOC_ISM_TOTAL_BANKS; 1279 SOC_ISM_INFO(unit)->total_entries = _SOC_ISM_ENTRIES_PER_BKT * 1280 _soc_ism_bank_total(unit); 1281 SOC_ISM_INFO(unit)->max_raw_banks = _SOC_ISM_MAX_RAW_BANKS; 1282 SOC_ISM_INFO(unit)->real_bank_map = _soc_ism_real_bank_map; 1283 break; 1284 case _ISM_SIZE_MODE_176: 1285 SOC_ISM_INFO(unit)->bank_raw_sizes = _soc_ism_bank_raw_sizes_256_176; 1286 SOC_ISM_INFO(unit)->banks_per_stage = _SOC_ISM_BANKS_PER_STAGE_176; 1287 SOC_ISM_INFO(unit)->max_banks = _SOC_ISM_MAX_BANKS_176; 1288 SOC_ISM_INFO(unit)->total_banks = _SOC_ISM_TOTAL_BANKS_176; 1289 SOC_ISM_INFO(unit)->total_entries = _SOC_ISM_ENTRIES_PER_BKT * 1290 _soc_ism_bank_total(unit); 1291 SOC_ISM_INFO(unit)->max_raw_banks = _SOC_ISM_MAX_RAW_BANKS; 1292 SOC_ISM_INFO(unit)->real_bank_map = _soc_ism_real_bank_map_176; 1293 break; 1294 case _ISM_SIZE_MODE_96: 1295 SOC_ISM_INFO(unit)->bank_raw_sizes = _soc_ism_bank_raw_sizes_256_96; 1296 SOC_ISM_INFO(unit)->banks_per_stage = _SOC_ISM_BANKS_PER_STAGE_96; 1297 SOC_ISM_INFO(unit)->max_banks = _SOC_ISM_MAX_BANKS_96; 1298 SOC_ISM_INFO(unit)->total_banks = _SOC_ISM_TOTAL_BANKS_96; 1299 SOC_ISM_INFO(unit)->total_entries = _SOC_ISM_ENTRIES_PER_BKT * 1300 _soc_ism_bank_total(unit); 1301 SOC_ISM_INFO(unit)->max_raw_banks = _SOC_ISM_MAX_RAW_BANKS; 1302 SOC_ISM_INFO(unit)->real_bank_map = _soc_ism_real_bank_map_96; 1303 break; 1304 case _ISM_SIZE_MODE_80: 1305 SOC_ISM_INFO(unit)->bank_raw_sizes = _soc_ism_bank_raw_sizes_256_80; 1306 SOC_ISM_INFO(unit)->banks_per_stage = _SOC_ISM_BANKS_PER_STAGE_80; 1307 SOC_ISM_INFO(unit)->max_banks = _SOC_ISM_MAX_BANKS_80; 1308 SOC_ISM_INFO(unit)->total_banks = _SOC_ISM_TOTAL_BANKS_80; 1309 SOC_ISM_INFO(unit)->total_entries = _SOC_ISM_ENTRIES_PER_BKT * 1310 _soc_ism_bank_total(unit); 1311 SOC_ISM_INFO(unit)->max_raw_banks = _SOC_ISM_MAX_RAW_BANKS; 1312 SOC_ISM_INFO(unit)->real_bank_map = _soc_ism_real_bank_map_80; 1313 break; 1314 default: 1315 return SOC_E_PARAM; 1316 } 1317 1318 /* Attach the hash cfg structures based upon chip type 1319 (currently only one type; will change to use if-else in the future) */ 1320 _SOC_ISM_BANKS(unit) = _soc_ism_shb[unit]; 1321 _SOC_ISM_SETS(unit) = _soc_ism_shms; 1322 _SOC_ISM_MEMS(unit) = _soc_ism_shm; 1323 _SOC_ISM_VIEWS(unit) = _soc_ism_shmv; 1324 _SOC_ISM_KEYS(unit) = _soc_ism_shk; 1325 1326 sop->memState[VLAN_XLATEm].index_max = -1; 1327 sop->memState[VLAN_XLATE_1m].index_max = -1; 1328 sop->memState[VLAN_XLATE_1_HIT_ONLYm].index_max = -1; 1329 sop->memState[VLAN_XLATE_EXTDm].index_max = -1; 1330 sop->memState[VLAN_XLATE_2_HIT_ONLYm].index_max = -1; 1331 sop->memState[L2_ENTRY_1m].index_max = -1; 1332 sop->memState[L2_ENTRY_1_HIT_ONLYm].index_max = -1; 1333 sop->memState[L2_ENTRY_2m].index_max = -1; 1334 sop->memState[L2_ENTRY_2_HIT_ONLYm].index_max = -1; 1335 sop->memState[L3_ENTRY_1m].index_max = -1; 1336 sop->memState[L3_ENTRY_1_HIT_ONLYm].index_max = -1; 1337 sop->memState[L3_ENTRY_2m].index_max = -1; 1338 sop->memState[L3_ENTRY_2_HIT_ONLYm].index_max = -1; 1339 sop->memState[L3_ENTRY_4m].index_max = -1; 1340 sop->memState[L3_ENTRY_4_HIT_ONLYm].index_max = -1; 1341 sop->memState[EGR_VLAN_XLATEm].index_max = -1; 1342 sop->memState[EP_VLAN_XLATE_1m].index_max = -1; 1343 sop->memState[EP_VLAN_XLATE_1_HIT_ONLYm].index_max = -1; 1344 sop->memState[MPLS_ENTRYm].index_max = -1; 1345 sop->memState[MPLS_ENTRY_1m].index_max = -1; 1346 sop->memState[MPLS_ENTRY_1_HIT_ONLYm].index_max = -1; 1347 sop->memState[MPLS_ENTRY_EXTDm].index_max = -1; 1348 sop->memState[MPLS_ENTRY_2_HIT_ONLYm].index_max = -1; 1349 if (soc_property_get(unit, spn_VLAN_XLATE_MEM_BANKS, 0) || 1350 soc_property_get(unit, spn_L2_MEM_BANKS, 0) || 1351 soc_property_get(unit, spn_L3_MEM_BANKS, 0) || 1352 soc_property_get(unit, spn_EGR_VLAN_XLATE_MEM_BANKS, 0) || 1353 soc_property_get(unit, spn_MPLS_MEM_BANKS, 0)) { 1354 rv = soc_ism_mem_config_with_banks(unit, mem_cfg, count); 1355 if (SOC_FAILURE(rv)) { 1356 return rv; 1357 } 1358 } else { 1359 /* Sort the memories in decreasing order of sizes and allocation priority */ 1360 _soc_ism_sort_mems(mem_cfg, count, ism_hash_tables); 1361 1362 for (tab = 0; tab < count && tab < SOC_ISM_MEM_TOTAL; tab++) { 1363 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1364 (BSL_META_U(unit, 1365 "ISM mem: [%s], size: %d\n"), 1366 soc_ism_table_to_name(ism_hash_tables[tab].mem), 1367 ism_hash_tables[tab].size)); 1368 } 1369 for (tab = 0; tab < count && tab < SOC_ISM_MEM_TOTAL; tab++) { 1370 uint8 avail; 1371 int rem; 1372 mem = ism_hash_tables[tab].mem; 1373 midx = soc_ism_table_to_index(mem); 1374 if (midx == -1) { 1375 return SOC_E_PARAM; 1376 } 1377 if (ism_hash_tables[tab].size <= 0 ) { 1378 continue; 1379 } 1380 size = ism_hash_tables[tab].size; 1381 rem = size % _SOC_ISM_ENTRY_SIZE_QUANTA; 1382 if (rem) { 1383 size = size + (_SOC_ISM_ENTRY_SIZE_QUANTA - rem); 1384 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1385 (BSL_META_U(unit, 1386 "Updated size %s: %d\n"), 1387 soc_ism_table_to_name(mem), size)); 1388 } 1389 ism_hash_tables[tab].size = size; 1390 do { 1391 /* convert to num of buckets */ 1392 size = size / mem_info_entry[midx].epb; 1393 avail = 0; 1394 for (idx = 0; idx < SOC_ISM_INFO(unit)->max_banks; idx++) { 1395 bank = ((idx%_SOC_ISM_MAX_STAGES) * 1396 SOC_ISM_INFO(unit)->banks_per_stage) + 1397 (idx/_SOC_ISM_MAX_STAGES); 1398 if (_soc_ism_bank_avail[unit][bank]) { 1399 continue; 1400 } 1401 avail++; 1402 /* Rule: ESM stuff can only be in banks >= 4k in size */ 1403 if (mem >= SOC_ISM_MEM_MAX && 1404 SOC_ISM_INFO(unit)->bank_raw_sizes[bank] < 1024*4) { 1405 continue; 1406 } 1407 if (size >= SOC_ISM_INFO(unit)->bank_raw_sizes[bank]) { 1408 _ism_total += SOC_ISM_INFO(unit)->bank_raw_sizes[bank] * \ 1409 _SOC_ISM_ENTRIES_PER_BKT; 1410 size -= SOC_ISM_INFO(unit)->bank_raw_sizes[bank]; 1411 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1412 (BSL_META_U(unit, 1413 "bank: %d\n"), bank)); 1414 _soc_ism_bank_avail[unit][bank] = mem; 1415 if (mem < SOC_ISM_MEM_MAX) { 1416 _soc_ism_table_bank_count[unit][midx]++; 1417 if (_soc_ism_table_bank_count[unit][midx] > 1418 SOC_ISM_INFO(unit)->max_banks) { 1419 return SOC_E_PARAM; 1420 } 1421 _soc_ism_table_bank_config[unit][midx][bank] = 1; 1422 } 1423 } 1424 if (!size) { 1425 goto next_mem; 1426 } 1427 } 1428 if (size) { 1429 /* Bump up num of entries to allocate the next bigger bank */ 1430 size = size * mem_info_entry[midx].epb + _SOC_ISM_ENTRY_SIZE_QUANTA; 1431 ism_hash_tables[tab].size += _SOC_ISM_ENTRY_SIZE_QUANTA; 1432 } 1433 } while (size && avail); /* Keep trying */ 1434 if (size) { 1435 LOG_ERROR(BSL_LS_SOC_COMMON, 1436 (BSL_META_U(unit, 1437 "Could not allocate banks for mem: %s\n"), 1438 soc_ism_table_to_name(mem))); 1439 return SOC_E_PARAM; 1440 } 1441 next_mem: 1442 size = ism_hash_tables[tab].size; 1443 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1444 (BSL_META_U(unit, 1445 "Final size %s: %d\n"), 1446 soc_ism_table_to_name(mem), size)); 1447 switch (mem) { 1448 case SOC_ISM_MEM_VLAN_XLATE: 1449 sop->memState[VLAN_XLATEm].index_max += (size * 2); 1450 sop->memState[VLAN_XLATE_1m].index_max += (size * 2); 1451 sop->memState[VLAN_XLATE_1_HIT_ONLYm].index_max += (size * 2); 1452 sop->memState[VLAN_XLATE_EXTDm].index_max += size; 1453 sop->memState[VLAN_XLATE_2_HIT_ONLYm].index_max += size; 1454 break; 1455 case SOC_ISM_MEM_L2_ENTRY: 1456 sop->memState[L2_ENTRY_1m].index_max += (size * 2) ; 1457 sop->memState[L2_ENTRY_1_HIT_ONLYm].index_max += (size * 2) ; 1458 sop->memState[L2_ENTRY_2m].index_max += size ; 1459 sop->memState[L2_ENTRY_2_HIT_ONLYm].index_max += size ; 1460 break; 1461 case SOC_ISM_MEM_L3_ENTRY: 1462 sop->memState[L3_ENTRY_1m].index_max += (size * 4); 1463 sop->memState[L3_ENTRY_1_HIT_ONLYm].index_max += (size * 4); 1464 sop->memState[L3_ENTRY_2m].index_max += (size * 2); 1465 sop->memState[L3_ENTRY_2_HIT_ONLYm].index_max += (size * 2); 1466 sop->memState[L3_ENTRY_4m].index_max += size; 1467 sop->memState[L3_ENTRY_4_HIT_ONLYm].index_max += size; 1468 break; 1469 case SOC_ISM_MEM_EP_VLAN_XLATE: 1470 sop->memState[EGR_VLAN_XLATEm].index_max += size; 1471 sop->memState[EP_VLAN_XLATE_1m].index_max += size; 1472 sop->memState[EP_VLAN_XLATE_1_HIT_ONLYm].index_max += size; 1473 break; 1474 case SOC_ISM_MEM_MPLS: 1475 sop->memState[MPLS_ENTRYm].index_max += (size * 2); 1476 sop->memState[MPLS_ENTRY_1m].index_max += (size * 2); 1477 sop->memState[MPLS_ENTRY_1_HIT_ONLYm].index_max += (size * 2); 1478 sop->memState[MPLS_ENTRY_EXTDm].index_max += size; 1479 sop->memState[MPLS_ENTRY_2_HIT_ONLYm].index_max += size; 1480 break; 1481 case SOC_ISM_MEM_ESM_L2: 1482 case SOC_ISM_MEM_ESM_L3: 1483 case SOC_ISM_MEM_ESM_ACL: 1484 break; 1485 default: return SOC_E_PARAM; 1486 } 1487 continue; 1488 } 1489 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1490 (BSL_META_U(unit, 1491 "ISM used total: %d k of %d k\n"), 1492 _ism_total/_SOC_ISM_ENTRY_SIZE_QUANTA, 1493 SOC_ISM_INFO(unit)->total_entries/_SOC_ISM_ENTRY_SIZE_QUANTA)); 1494 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1495 (BSL_META_U(unit, 1496 "ISM remaining : %d k\n"), 1497 SOC_ISM_INFO(unit)->total_entries/_SOC_ISM_ENTRY_SIZE_QUANTA - 1498 (_ism_total/_SOC_ISM_ENTRY_SIZE_QUANTA))); 1499 1500 if (_ism_total/_SOC_ISM_ENTRY_SIZE_QUANTA > 1501 SOC_ISM_INFO(unit)->total_entries/_SOC_ISM_ENTRY_SIZE_QUANTA) { 1502 LOG_ERROR(BSL_LS_SOC_COMMON, 1503 (BSL_META_U(unit, 1504 "Over-allocation of ISM resources !!\n"))); 1505 return SOC_E_PARAM; 1506 } 1507 _soc_ism_mem_allocation_log(unit, ism_hash_tables, count); 1508 } 1509 1510 rv = soc_ism_log_to_phy_fill(unit); 1511 if (SOC_FAILURE(rv)) { 1512 return rv; 1513 } 1514 rv = soc_ism_hash_init(unit); 1515 if (SOC_FAILURE(rv)) { 1516 return rv; 1517 } 1518 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1519 (BSL_META_U(unit, 1520 "ISM configured.\n"))); 1521 return SOC_E_NONE; 1522 } 1523 1524 /* Internel helper routine */ 1525 STATIC int 1526 _soc_ism_get_sorted_bank_list(int unit, soc_mem_t *mems, int *banks) 1527 { 1528 int32 i, j, count = 0; 1529 uint8 done, bank, tmp; 1530 /* go through banks to get sorted base_entry's */ 1531 for (i = 0; i < SOC_ISM_INFO(unit)->max_banks; i++) { 1532 bank = ((i%_SOC_ISM_MAX_STAGES) * SOC_ISM_INFO(unit)->banks_per_stage) + 1533 (i/_SOC_ISM_MAX_STAGES); 1534 if (!_soc_ism_bank_avail[unit][bank]) { 1535 continue; 1536 } 1537 done = 0; 1538 for (j = 0; j < count; j++) { 1539 if (mems[j] == _soc_ism_bank_avail[unit][bank]) { 1540 done = 1; 1541 break; 1542 } 1543 } 1544 if (done) { 1545 continue; 1546 } else { 1547 banks[count] = bank; 1548 mems[count++] = _soc_ism_bank_avail[unit][bank]; 1549 } 1550 for (j = i+1; j < SOC_ISM_INFO(unit)->max_banks; j++) { 1551 tmp = ((j%_SOC_ISM_MAX_STAGES) * 1552 SOC_ISM_INFO(unit)->banks_per_stage) + 1553 (j/_SOC_ISM_MAX_STAGES); 1554 if (_soc_ism_bank_avail[unit][bank] == 1555 _soc_ism_bank_avail[unit][tmp]) { 1556 banks[count] = tmp; 1557 mems[count++] = _soc_ism_bank_avail[unit][tmp]; 1558 } 1559 } 1560 } 1561 return count; 1562 } 1563 1564 /* Initializes and links various hash structures */ 1565 int 1566 soc_ism_hash_init(int unit) 1567 { 1568 int i, j, k, count = 0; 1569 soc_mem_t mems[_SOC_ISM_MAX_BANKS]; 1570 int banks[_SOC_ISM_MAX_BANKS]; 1571 int bits_aligned; 1572 1573 1574 sal_memset(_SOC_ISM_BANKS(unit), 0, sizeof(soc_hash_bank_t)); 1575 sal_memset(mems, 0, COUNTOF(mems) * sizeof(soc_mem_t)); 1576 for (i = 0; i < SOC_MEM_SET_MAX; i++) { 1577 _SOC_ISM_SETS(unit)[i].num_banks = 0; 1578 } 1579 count = _soc_ism_get_sorted_bank_list(unit, mems, banks); 1580 LOG_INFO(BSL_LS_SOC_SOCMEM, 1581 (BSL_META_U(unit, 1582 "Used banks: %d\n"), count)); 1583 for (i = 0; i < count; i++) { 1584 if (mems[i] >= SOC_ISM_MEM_MAX) { 1585 continue; 1586 } 1587 _SOC_ISM_BANKS(unit)[i].num_bkts = 1588 SOC_ISM_INFO(unit)->bank_raw_sizes[banks[i]]; 1589 _SOC_ISM_BANKS(unit)[i].bkt_size = 4; /* could be configurable */ 1590 _SOC_ISM_BANKS(unit)[i].num_entries = _SOC_ISM_BANKS(unit)[i].num_bkts * 1591 _SOC_ISM_BANKS(unit)[i].bkt_size; 1592 _SOC_ISM_BANKS(unit)[i].my_id = banks[i]; 1593 for (j = 0; j < SOC_MEM_SET_MAX; j++) { 1594 if (mems[i] == _SOC_ISM_SETS(unit)[j].mem_set) { 1595 _SOC_ISM_BANKS(unit)[i].hms = &_SOC_ISM_SETS(unit)[j]; 1596 if (_SOC_ISM_SETS(unit)[j].num_banks == 0) { 1597 _SOC_ISM_SETS(unit)[j].shb = &_SOC_ISM_BANKS(unit)[i]; 1598 _SOC_ISM_BANKS(unit)[i].base_entry = 0; 1599 } else { 1600 _SOC_ISM_BANKS(unit)[i].base_entry = 1601 _SOC_ISM_SETS(unit)[j].shb[_SOC_ISM_SETS(unit)[j].num_banks-1].base_entry 1602 + _SOC_ISM_SETS(unit)[j].shb[_SOC_ISM_SETS(unit)[j].num_banks-1].num_entries; 1603 } 1604 _SOC_ISM_SETS(unit)[j].num_banks++; 1605 break; 1606 } 1607 } 1608 LOG_INFO(BSL_LS_SOC_SOCMEM, 1609 (BSL_META_U(unit, 1610 "Bank: %d, base: %d, mem: [%s], buckets: %d, entries: %d " 1611 "hash offset: %d\n"), banks[i], 1612 _SOC_ISM_BANKS(unit)[i].base_entry, 1613 soc_ism_table_to_name(_SOC_ISM_BANKS(unit)[i].hms->mem_set), 1614 _SOC_ISM_BANKS(unit)[i].num_bkts, 1615 _SOC_ISM_BANKS(unit)[i].num_entries, 1616 _SOC_ISM_BANKS(unit)[i].hash_offset)); 1617 } 1618 /* Just for sanity */ 1619 for (i = 0; i < SOC_MEM_SET_MAX; i++) { 1620 LOG_INFO(BSL_LS_SOC_SOCMEM, 1621 (BSL_META_U(unit, 1622 "Set: %s, num mems: %d, banks: %d, zero_lsb: %d, \n"), 1623 soc_ism_table_to_name(_SOC_ISM_SETS(unit)[i].mem_set), 1624 _SOC_ISM_SETS(unit)[i].num_mems, 1625 _SOC_ISM_SETS(unit)[i].num_banks, 1626 _SOC_ISM_SETS(unit)[i].zero_lsb)); 1627 for (j = 0; j < _SOC_ISM_SETS(unit)[i].num_mems; j++) { 1628 LOG_INFO(BSL_LS_SOC_SOCMEM, 1629 (BSL_META_U(unit, 1630 "Num views: %d\n"), 1631 _SOC_ISM_SETS(unit)[i].shm[j].num_views)); 1632 for (k = 0; k < _SOC_ISM_SETS(unit)[i].shm[j].num_views; k++) { 1633 LOG_INFO(BSL_LS_SOC_SOCMEM, 1634 (BSL_META_U(unit, 1635 "key width: %d\n"), 1636 _SOC_ISM_SETS(unit)[i].shm[j].hmv[k].key_size)); 1637 } 1638 } 1639 1640 /* the key bufer size is related to max_key_bits (which is defined in _soc_ism_shms array), need to check it */ 1641 bits_aligned = (_SOC_ISM_SETS(unit)[i].max_key_bits + 7) & (~0x7); 1642 if ((bits_aligned/8) > SOC_HASH_MEM_MAX_KEY_BUFFER_SIZE_BYTES) 1643 { 1644 LOG_ERROR(BSL_LS_SOC_COMMON, 1645 (BSL_META_U(unit, 1646 "The key buffer is two small, please adjust SOC_HASH_MEM_MAX_KEY_BUFFER_SIZE_BYTES!!\n"))); 1647 return SOC_E_CONFIG; 1648 } 1649 } 1650 return SOC_E_NONE; 1651 } 1652 1653 /* write to h/w */ 1654 int 1655 soc_ism_hw_config(int unit) 1656 { 1657 int i, r, f, stg, bank, len; 1658 int j, offset = 0, lbpd = 0, rv = SOC_E_NONE; 1659 uint32 pd_val, rval; 1660 _soc_ism_pd_t *pd; 1661 1662 assert(SOC_ISM_INFO(unit)); 1663 if (SAL_BOOT_SIMULATION) { 1664 uint32 rval = 0; 1665 if (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_176) { 1666 soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK0_SIZE_LIMITf, 1667 _ISM_BANK_SIZE_QUARTER); 1668 soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK1_SIZE_LIMITf, 1669 _ISM_BANK_SIZE_HALF); 1670 soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK2_SIZE_LIMITf, 1671 _ISM_BANK_SIZE_HALF); 1672 soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK3_SIZE_LIMITf, 1673 _ISM_BANK_SIZE_HALF); 1674 soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK4_SIZE_LIMITf, 1675 _ISM_BANK_SIZE_DISABLED); 1676 SOC_IF_ERROR_RETURN(WRITE_STAGE0_BANK_SIZEr(unit, rval)); 1677 SOC_IF_ERROR_RETURN(WRITE_STAGE1_BANK_SIZEr(unit, rval)); 1678 SOC_IF_ERROR_RETURN(WRITE_STAGE2_BANK_SIZEr(unit, rval)); 1679 SOC_IF_ERROR_RETURN(WRITE_STAGE3_BANK_SIZEr(unit, rval)); 1680 } else if (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_96) { 1681 soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK0_SIZE_LIMITf, 1682 _ISM_BANK_SIZE_DISABLED); 1683 soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK1_SIZE_LIMITf, 1684 _ISM_BANK_SIZE_QUARTER); 1685 soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK2_SIZE_LIMITf, 1686 _ISM_BANK_SIZE_HALF); 1687 soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK3_SIZE_LIMITf, 1688 _ISM_BANK_SIZE_HALF); 1689 soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK4_SIZE_LIMITf, 1690 _ISM_BANK_SIZE_HALF); 1691 SOC_IF_ERROR_RETURN(WRITE_STAGE0_BANK_SIZEr(unit, rval)); 1692 SOC_IF_ERROR_RETURN(WRITE_STAGE1_BANK_SIZEr(unit, rval)); 1693 SOC_IF_ERROR_RETURN(WRITE_STAGE2_BANK_SIZEr(unit, rval)); 1694 SOC_IF_ERROR_RETURN(WRITE_STAGE3_BANK_SIZEr(unit, rval)); 1695 } else if (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_80) { 1696 soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK0_SIZE_LIMITf, 1697 _ISM_BANK_SIZE_DISABLED); 1698 soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK1_SIZE_LIMITf, 1699 _ISM_BANK_SIZE_QUARTER); 1700 soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK2_SIZE_LIMITf, 1701 _ISM_BANK_SIZE_QUARTER); 1702 soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK3_SIZE_LIMITf, 1703 _ISM_BANK_SIZE_HALF); 1704 soc_reg_field_set(unit, STAGE0_BANK_SIZEr, &rval, BANK4_SIZE_LIMITf, 1705 _ISM_BANK_SIZE_HALF); 1706 SOC_IF_ERROR_RETURN(WRITE_STAGE0_BANK_SIZEr(unit, rval)); 1707 SOC_IF_ERROR_RETURN(WRITE_STAGE1_BANK_SIZEr(unit, rval)); 1708 SOC_IF_ERROR_RETURN(WRITE_STAGE2_BANK_SIZEr(unit, rval)); 1709 SOC_IF_ERROR_RETURN(WRITE_STAGE3_BANK_SIZEr(unit, rval)); 1710 } 1711 /* Note: handle other modes as needed in the future */ 1712 } 1713 rv = soc_ism_table_bank_set(unit); 1714 if (SOC_FAILURE(rv)) { 1715 return rv; 1716 } 1717 rv = soc_ism_log_to_phy_set(unit); 1718 if (SOC_FAILURE(rv)) { 1719 return rv; 1720 } 1721 if ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_96) || 1722 (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_80)) { 1723 offset = 1; /* First bank is not available */ 1724 } else if (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_176) { 1725 lbpd = 1; /* Last bank is not available */ 1726 } 1727 /* Power down unused banks. 1728 * Note: This works on the actual banks of the base device not the banks 1729 * based upon the ISM mode. 1730 */ 1731 for (i = 0; i < _SOC_ISM_MAX_BANKS; i++) { 1732 if (!_soc_ism_bank_avail[unit][i]) { 1733 if (offset || lbpd) { 1734 j = i + offset + i/4; 1735 if (j >= _SOC_ISM_MAX_BANKS) { 1736 return SOC_E_NONE; 1737 } 1738 } else { 1739 j = i; 1740 } 1741 stg = j / _SOC_ISM_BANKS_PER_STAGE; 1742 bank = j % _SOC_ISM_BANKS_PER_STAGE; 1743 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1744 (BSL_META_U(unit, 1745 "Powering down stage[%d] bank[%d]\n"), 1746 stg, bank)); 1747 pd = &_soc_ism_pd[stg][bank]; 1748 r = 0; 1749 while (pd->reg_field[r].pdr != INVALIDr) { 1750 SOC_IF_ERROR_RETURN 1751 (soc_reg32_get(unit, pd->reg_field[r].pdr, REG_PORT_ANY, 1752 0, &rval)); 1753 f = 0; 1754 while (pd->reg_field[r].pdf[f] != INVALIDf) { 1755 len = soc_reg_field_length(unit, pd->reg_field[r].pdr, 1756 pd->reg_field[r].pdf[f]); 1757 pd_val = ((1 << len) - 1); 1758 soc_reg_field_set(unit, pd->reg_field[r].pdr, &rval, 1759 pd->reg_field[r].pdf[f], pd_val); 1760 f++; 1761 } 1762 SOC_IF_ERROR_RETURN 1763 (soc_reg32_set(unit, pd->reg_field[r].pdr, REG_PORT_ANY, 1764 0, rval)); 1765 r++; 1766 } 1767 } else if (_soc_ism_bank_avail[unit][i] >= SOC_ISM_MEM_ESM_L2) { 1768 if (offset || lbpd) { 1769 j = i + offset + i/4; 1770 if (j >= _SOC_ISM_MAX_BANKS) { 1771 return SOC_E_NONE; 1772 } 1773 } else { 1774 j = i; 1775 } 1776 stg = j / _SOC_ISM_BANKS_PER_STAGE; 1777 bank = j % _SOC_ISM_BANKS_PER_STAGE; 1778 LOG_VERBOSE(BSL_LS_SOC_COMMON, 1779 (BSL_META_U(unit, 1780 "Powering down hit-bit rams for stage[%d] bank[%d]\n"), 1781 stg, bank)); 1782 pd = &_soc_ism_pd[stg][bank]; 1783 r = 0; 1784 while (pd->hit_reg_field[r].pdr != INVALIDr) { 1785 SOC_IF_ERROR_RETURN 1786 (soc_reg32_get(unit, pd->hit_reg_field[r].pdr, REG_PORT_ANY, 1787 0, &rval)); 1788 f = 0; 1789 while (pd->hit_reg_field[r].pdf[f] != INVALIDf) { 1790 len = soc_reg_field_length(unit, pd->hit_reg_field[r].pdr, 1791 pd->hit_reg_field[r].pdf[f]); 1792 pd_val = ((1 << len) - 1); 1793 soc_reg_field_set(unit, pd->hit_reg_field[r].pdr, &rval, 1794 pd->hit_reg_field[r].pdf[f], pd_val); 1795 f++; 1796 } 1797 SOC_IF_ERROR_RETURN 1798 (soc_reg32_set(unit, pd->hit_reg_field[r].pdr, REG_PORT_ANY, 1799 0, rval)); 1800 r++; 1801 } 1802 } 1803 } 1804 return SOC_E_NONE; 1805 } 1806 1807 soc_reg_t _ism_stage_hash_cfg_reg[] = { 1808 STAGE0_HASH_OFFSETr, STAGE1_HASH_OFFSETr, 1809 STAGE2_HASH_OFFSETr, STAGE3_HASH_OFFSETr 1810 }; 1811 1812 soc_field_t _ism_stage_hash_cfg_fld[] = { 1813 BANK0_HASH_OFFSETf, BANK1_HASH_OFFSETf, 1814 BANK2_HASH_OFFSETf, BANK3_HASH_OFFSETf, 1815 BANK4_HASH_OFFSETf 1816 }; 1817 1818 /* Configure hash offset per bank */ 1819 int 1820 soc_ism_hash_offset_config(int unit, uint8 bank, uint8 offset) 1821 { 1822 uint8 i, b, stage, set_idx, found = 0; 1823 uint32 rval; 1824 int disabled_banks = 0; 1825 1826 if ((bank >= SOC_ISM_INFO(unit)->max_banks) || (offset > 63)) { 1827 return SOC_E_PARAM; 1828 } 1829 if ((!_soc_ism_bank_avail[unit][bank]) || 1830 (_soc_ism_bank_avail[unit][bank] >= SOC_ISM_MEM_MAX)) { 1831 return SOC_E_PARAM; 1832 } 1833 stage = bank/SOC_ISM_INFO(unit)->banks_per_stage; 1834 disabled_banks = ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_96) || 1835 (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_80)) ? 1836 ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_64) ? 2 : 1) : 0; 1837 b = (bank%SOC_ISM_INFO(unit)->banks_per_stage) + disabled_banks; 1838 1839 SOC_IF_ERROR_RETURN 1840 (soc_reg32_get(unit, _ism_stage_hash_cfg_reg[stage], REG_PORT_ANY, 1841 0, &rval)); 1842 soc_reg_field_set(unit, _ism_stage_hash_cfg_reg[stage], 1843 &rval, _ism_stage_hash_cfg_fld[b], offset); 1844 SOC_IF_ERROR_RETURN 1845 (soc_reg32_set(unit, _ism_stage_hash_cfg_reg[stage], REG_PORT_ANY, 1846 0, rval)); 1847 set_idx = _soc_ism_bank_avail[unit][bank] - 1; 1848 for (i = 0; i < _SOC_ISM_SETS(unit)[set_idx].num_banks; i++) { 1849 if (_SOC_ISM_SETS(unit)[set_idx].shb[i].my_id == bank) { 1850 _SOC_ISM_SETS(unit)[set_idx].shb[i].hash_offset = offset; 1851 found = 1; 1852 break; 1853 } 1854 } 1855 if (!found) { 1856 LOG_ERROR(BSL_LS_SOC_COMMON, 1857 (BSL_META_U(unit, 1858 "No memory mapped to bank: %d\n"), bank)); 1859 return SOC_E_INTERNAL; 1860 } 1861 return SOC_E_NONE; 1862 } 1863 1864 /* Get max allowed offset value that can be used for any bank */ 1865 int 1866 soc_ism_hash_max_offset_get(int unit, int *offset) 1867 { 1868 if (offset) { 1869 *offset = 64; 1870 } 1871 return SOC_E_NONE; 1872 } 1873 1874 /* Configure hash offset per mem */ 1875 int 1876 soc_ism_hash_mem_offset_config(int unit, soc_mem_t mem, uint8 count, 1877 uint8 *offset) 1878 { 1879 return SOC_E_NONE; 1880 } 1881 1882 /* Get hash offset per bank */ 1883 int 1884 soc_ism_hash_offset_config_get(int unit, uint8 bank, uint8 *offset) 1885 { 1886 uint8 i, set_idx, found = 0; 1887 1888 if (bank >= SOC_ISM_INFO(unit)->max_banks) { 1889 return SOC_E_PARAM; 1890 } 1891 set_idx = _soc_ism_bank_avail[unit][bank] - 1; 1892 1893 #ifdef BCM_WARM_BOOT_SUPPORT 1894 if (SOC_WARM_BOOT(unit)) { 1895 uint8 b, stage; 1896 uint32 rval, val; 1897 int disabled_banks = 0; 1898 1899 if (bank >= SOC_ISM_INFO(unit)->max_banks) { 1900 return SOC_E_PARAM; 1901 } 1902 if ((!_soc_ism_bank_avail[unit][bank]) || 1903 (_soc_ism_bank_avail[unit][bank] >= SOC_ISM_MEM_MAX)) { 1904 return SOC_E_PARAM; 1905 } 1906 stage = bank/SOC_ISM_INFO(unit)->banks_per_stage; 1907 disabled_banks = ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_96) || 1908 (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_80)) ? 1909 ((SOC_ISM_INFO(unit)->ism_mode == 1910 _ISM_SIZE_MODE_64) ? 2 : 1) : 0; 1911 b = (bank%SOC_ISM_INFO(unit)->banks_per_stage) + disabled_banks; 1912 1913 SOC_IF_ERROR_RETURN 1914 (soc_reg32_get(unit, _ism_stage_hash_cfg_reg[stage], REG_PORT_ANY, 1915 0, &rval)); 1916 val = soc_reg_field_get(unit, _ism_stage_hash_cfg_reg[stage], 1917 rval, _ism_stage_hash_cfg_fld[b]); 1918 for (i = 0; i < _SOC_ISM_SETS(unit)[set_idx].num_banks; i++) { 1919 if (_SOC_ISM_SETS(unit)[set_idx].shb[i].my_id == bank) { 1920 *offset = val; 1921 _SOC_ISM_SETS(unit)[set_idx].shb[i].hash_offset = val; 1922 found = 1; 1923 break; 1924 } 1925 } 1926 } else 1927 #endif /* BCM_WARM_BOOT_SUPPORT */ 1928 { 1929 for (i = 0; i < _SOC_ISM_SETS(unit)[set_idx].num_banks; i++) { 1930 if (_SOC_ISM_SETS(unit)[set_idx].shb[i].my_id == bank) { 1931 *offset = _SOC_ISM_SETS(unit)[set_idx].shb[i].hash_offset; 1932 found = 1; 1933 break; 1934 } 1935 } 1936 } 1937 if (!found) { 1938 LOG_ERROR(BSL_LS_SOC_COMMON, 1939 (BSL_META_U(unit, 1940 "No memory mapped to bank: %d\n"), bank)); 1941 return SOC_E_INTERNAL; 1942 } 1943 return SOC_E_NONE; 1944 } 1945 1946 /* Get hash offset per table */ 1947 int 1948 soc_ism_hash_table_offset_config_get(int unit, soc_ism_mem_type_t table, 1949 uint8 *offset, uint8 *count) 1950 { 1951 int i, rv; 1952 uint8 banks[_SOC_ISM_MAX_BANKS]; 1953 uint32 bank_size[_SOC_ISM_MAX_BANKS]; 1954 1955 rv = soc_ism_get_banks(unit, table, banks, bank_size, count); 1956 for (i = 0; i < *count; i++) { 1957 rv |= soc_ism_hash_offset_config_get(unit, banks[i], &offset[i]); 1958 } 1959 return SOC_E_NONE; 1960 } 1961 1962 /* Get hash offset per mem */ 1963 int 1964 soc_ism_hash_mem_offset_config_get(int unit, soc_mem_t mem, uint8 *offset, 1965 uint8 *count) 1966 { 1967 int8 memidx; 1968 1969 if ((memidx = soc_ism_get_hash_mem_idx(unit, mem)) < 0) { 1970 return SOC_E_PARAM; 1971 } 1972 return soc_ism_hash_table_offset_config_get(unit, _SOC_ISM_MEMS(unit)[memidx].shms->mem_set, 1973 offset, count); 1974 } 1975 1976 /* Configure hash type per table */ 1977 int 1978 soc_ism_table_hash_config(int unit, soc_ism_mem_type_t table, uint8 zero_lsb) 1979 { 1980 uint32 rval; 1981 if (!table || table >= SOC_ISM_MEM_MAX) { 1982 return SOC_E_PARAM; 1983 } 1984 SOC_IF_ERROR_RETURN 1985 (soc_reg32_get(unit, _ism_table_bank_cfg_reg[table-1], REG_PORT_ANY, 1986 0, &rval)); 1987 soc_reg_field_set(unit, _ism_table_bank_cfg_reg[table-1], 1988 &rval, HASH_ZERO_OR_LSBf, zero_lsb); 1989 SOC_IF_ERROR_RETURN 1990 (soc_reg32_set(unit, _ism_table_bank_cfg_reg[table-1], REG_PORT_ANY, 1991 0, rval)); 1992 _SOC_ISM_SETS(unit)[table-1].zero_lsb = zero_lsb; 1993 return SOC_E_NONE; 1994 } 1995 1996 /* Configure hash type per mem */ 1997 int 1998 soc_ism_mem_hash_config(int unit, soc_mem_t mem, uint8 zero_lsb) 1999 { 2000 int8 memidx; 2001 if ((memidx = soc_ism_get_hash_mem_idx(unit, mem)) < 0) { 2002 return SOC_E_PARAM; 2003 } 2004 return soc_ism_table_hash_config(unit, _SOC_ISM_MEMS(unit)[memidx].shms->mem_set, 2005 zero_lsb); 2006 } 2007 2008 /* Get hash type per table */ 2009 int 2010 soc_ism_table_hash_config_get(int unit, soc_ism_mem_type_t table, uint8 *zero_lsb) 2011 { 2012 if (!table || table >= SOC_ISM_MEM_MAX) { 2013 return SOC_E_PARAM; 2014 } 2015 #ifdef BCM_WARM_BOOT_SUPPORT 2016 if (SOC_WARM_BOOT(unit)) { 2017 uint32 rval, val; 2018 SOC_IF_ERROR_RETURN 2019 (soc_reg32_get(unit, _ism_table_bank_cfg_reg[table-1], REG_PORT_ANY, 2020 0, &rval)); 2021 val = soc_reg_field_get(unit, _ism_table_bank_cfg_reg[table-1], 2022 rval, HASH_ZERO_OR_LSBf); 2023 *zero_lsb = val; 2024 _SOC_ISM_SETS(unit)[table-1].zero_lsb = val; 2025 } else 2026 #endif /* BCM_WARM_BOOT_SUPPORT */ 2027 { 2028 *zero_lsb = _SOC_ISM_SETS(unit)[table-1].zero_lsb; 2029 } 2030 return SOC_E_NONE; 2031 } 2032 2033 /* Get hash type per mem */ 2034 int 2035 soc_ism_mem_hash_config_get(int unit, soc_mem_t mem, uint8 *zero_lsb) 2036 { 2037 int8 memidx; 2038 if ((memidx = soc_ism_get_hash_mem_idx(unit, mem)) < 0) { 2039 return SOC_E_PARAM; 2040 } 2041 return soc_ism_table_hash_config_get(unit, _SOC_ISM_MEMS(unit)[memidx].shms->mem_set, 2042 zero_lsb); 2043 } 2044 2045 /* Get key length per mem */ 2046 int 2047 soc_ism_mem_max_key_bits_get(int unit, soc_mem_t mem) 2048 { 2049 int8 memidx; 2050 if ((memidx = soc_ism_get_hash_mem_idx(unit, mem)) < 0) { 2051 return SOC_E_PARAM; 2052 } 2053 return _SOC_ISM_MEMS(unit)[memidx].shms->max_key_bits; 2054 } 2055 2056 int 2057 soc_ism_get_total_banks(int unit, int *count) 2058 { 2059 if (count) { 2060 *count = SOC_ISM_INFO(unit)->max_banks; 2061 } 2062 return SOC_E_NONE; 2063 } 2064 2065 /* Get configured banks and count per table */ 2066 int 2067 soc_ism_get_banks(int unit, soc_ism_mem_type_t table, uint8 *banks, 2068 uint32 *bank_size, uint8 *count) 2069 { 2070 uint8 i; 2071 if (count) { 2072 *count = 0; 2073 } else { 2074 return SOC_E_PARAM; 2075 } 2076 for (i = 0; i < SOC_ISM_INFO(unit)->max_banks; i++) { 2077 if (_soc_ism_bank_avail[unit][i] == table) { 2078 if (banks) { 2079 banks[*count] = i; 2080 } 2081 if (bank_size) { 2082 bank_size[*count] = SOC_ISM_INFO(unit)->bank_raw_sizes[i]; 2083 } 2084 (*count)++; 2085 } 2086 } 2087 return SOC_E_NONE; 2088 } 2089 2090 /* Get configured banks and count per mem */ 2091 int 2092 soc_ism_get_banks_for_mem(int unit, soc_mem_t mem, uint8 *banks, 2093 uint32 *bank_size, uint8 *count) 2094 { 2095 int8 memidx; 2096 if ((memidx = soc_ism_get_hash_mem_idx(unit, mem)) < 0) { 2097 return SOC_E_PARAM; 2098 } 2099 if (_SOC_ISM_MEMS(unit)[memidx].shms->num_banks) { 2100 return soc_ism_get_banks(unit, _SOC_ISM_MEMS(unit)[memidx].shms->mem_set, 2101 banks, bank_size, count); 2102 } else { 2103 *count = 0; 2104 return SOC_E_NONE; 2105 } 2106 } 2107 2108 uint32 2109 soc_ism_get_phy_bank_mask(int unit, uint32 bank_mask) 2110 { 2111 uint32 offset = 1, bank = 0; 2112 if (-1 == bank_mask || 0 == bank_mask) { 2113 return bank_mask; 2114 } 2115 2116 if ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_96) || 2117 (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_80) || 2118 (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_176)) { 2119 int i; 2120 2121 for (i=0; i<32; i++) { 2122 if (bank_mask & (1<<i)) { 2123 bank = i; 2124 break; 2125 } 2126 } 2127 if ((SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_96) || 2128 (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_80)) { 2129 /* First bank is not available */ 2130 } else if (SOC_ISM_INFO(unit)->ism_mode == _ISM_SIZE_MODE_176) { 2131 /* Last bank is not available */ 2132 offset = 0; 2133 } 2134 /* Coverity 2135 * Number of ism banks do not exceed 16. 2136 */ 2137 /* coverity[large_shift : FALSE] */ 2138 return 1 << (bank + offset + bank/4); 2139 } else { 2140 return bank_mask; 2141 } 2142 } 2143 2144 /* Get key and lsb fields and count from a mem entry */ 2145 int 2146 soc_generic_get_hash_key(int unit, soc_mem_t mem, void *entry, 2147 soc_field_t *keyf, soc_field_t *lsbf, uint8 *num_flds) 2148 { 2149 int i, j, f = 0, found; 2150 int key_type; 2151 if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) { 2152 key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf); 2153 } else { 2154 key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPE_0f); 2155 } 2156 i = soc_ism_get_hash_mem_idx(unit, mem); 2157 if (i < 0) { 2158 LOG_ERROR(BSL_LS_SOC_COMMON, 2159 (BSL_META_U(unit, 2160 "Invalid hash memory !!\n"))); 2161 return SOC_E_PARAM; 2162 } 2163 found = 0; 2164 for (j = 0; j < _SOC_ISM_MEMS(unit)[i].shms->num_keys; j++) { 2165 if (key_type == _SOC_ISM_MEMS(unit)[i].shms->shk[j].key_type) { 2166 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2167 (BSL_META_U(unit, 2168 "Retreived key_type: %d for mem: %s\n"), 2169 key_type, SOC_MEM_NAME(unit, mem))); 2170 found = 1; 2171 break; 2172 } 2173 } 2174 if (!found) { 2175 return SOC_E_INTERNAL; 2176 } 2177 while (_SOC_ISM_MEMS(unit)[i].shms->shk[j].hmv->key_fields[f] != -1) { 2178 keyf[f] = _SOC_ISM_MEMS(unit)[i].shms->shk[j].hmv->key_fields[f]; 2179 f++; 2180 *num_flds = f; 2181 } 2182 *lsbf = _SOC_ISM_MEMS(unit)[i].shms->shk[j].hmv->lsb_field; 2183 return SOC_E_NONE; 2184 } 2185 2186 /* helper routine */ 2187 STATIC uint32 2188 _soc_crc32b(uint8 *data, int data_nbits) 2189 { 2190 uint32 rv; 2191 rv = _shr_crc32b(0, data, data_nbits); 2192 rv = _shr_bit_rev_by_byte_word32(rv); 2193 return rv; 2194 } 2195 2196 /* helper routine */ 2197 STATIC uint16 2198 _soc_crc16b(uint8 *data, int data_nbits) 2199 { 2200 uint16 rv; 2201 rv = _shr_crc16b(0, data, data_nbits); 2202 rv = _shr_bit_rev16(rv); 2203 return rv; 2204 } 2205 2206 /* Generate hash value from key using lsb or crc based upon config and offset */ 2207 int 2208 soc_generic_gen_hash(int unit, uint32 zero_lsb, uint32 num_bits, 2209 uint32 offset, uint32 mask, uint8 *key, uint16 lsb) 2210 { 2211 uint64 val, tmp; 2212 uint32 crc_lo; 2213 uint16 crc_hi; 2214 int32 i, j = 0; 2215 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2216 (BSL_META_U(unit, 2217 "Num bits: %d, zero_lsb: %d, lsb: %x, offset: %d, " 2218 "mask: %x\n"), num_bits, zero_lsb, lsb, offset, mask)); 2219 /* mask bit 0 of key */ 2220 key[0] &= 0xfe; 2221 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2222 (BSL_META_U(unit, 2223 "Key: ["))); 2224 for (i = num_bits; i > 0; i-=8) { 2225 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2226 (BSL_META_U(unit, 2227 "%0x"), key[j++])); 2228 } 2229 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2230 (BSL_META_U(unit, 2231 "]\n"))); 2232 if (offset >= 48) { 2233 if (!zero_lsb) { 2234 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2235 (BSL_META_U(unit, 2236 "Hash(zero)\n"))); 2237 return 0; 2238 } else { 2239 if (offset > 48) { 2240 lsb = lsb >> (offset-48); 2241 } 2242 lsb &= mask; 2243 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2244 (BSL_META_U(unit, 2245 "Hash(lsb): %d\n"), lsb)); 2246 return lsb & mask; 2247 } 2248 } else { 2249 crc_lo = _soc_crc32b(key, num_bits); 2250 crc_hi = _soc_crc16b(key, num_bits); 2251 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2252 (BSL_META_U(unit, 2253 "crc32: %x\n"), crc_lo)); 2254 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2255 (BSL_META_U(unit, 2256 "crc16: %x\n"), crc_hi)); 2257 COMPILER_64_SET(val, crc_hi, crc_lo); 2258 if (offset) { 2259 COMPILER_64_SHR(val, offset); 2260 } 2261 COMPILER_64_SET(tmp, 0, mask); 2262 COMPILER_64_AND(val, tmp); 2263 COMPILER_64_TO_32_LO(crc_lo, val); 2264 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2265 (BSL_META_U(unit, 2266 "Hash(crc): %d\n"), crc_lo)); 2267 return crc_lo & mask; 2268 } 2269 return SOC_E_NONE; 2270 } 2271 2272 /* return mask based upon bank size */ 2273 int 2274 soc_ism_get_hash_bucket_mask(int buckets) 2275 { 2276 switch (buckets) { 2277 case 1024: return 0x3ff; 2278 case 2048: return 0x7ff; 2279 case 4096: return 0xfff; 2280 case 8192: return 0x1fff; 2281 case 16384: return 0x3fff; 2282 default: return SOC_E_PARAM; 2283 } 2284 } 2285 2286 /* return num of bits based upon bank size */ 2287 int 2288 soc_ism_get_hash_bits(int buckets) 2289 { 2290 switch (buckets) { 2291 case 1024: return 10; 2292 case 2048: return 11; 2293 case 4096: return 12; 2294 case 8192: return 13; 2295 case 16384: return 14; 2296 default: return SOC_E_PARAM; 2297 } 2298 } 2299 2300 /* helper routine */ 2301 STATIC void 2302 _soc_hash_check_and_swap(_soc_ism_sbo_t *lx, _soc_ism_sbo_t *ly, int x, int y) 2303 { 2304 _soc_ism_sbo_t t; 2305 if (x > y) { 2306 t = *lx; 2307 *lx = *ly; 2308 *ly = t; 2309 } 2310 } 2311 2312 /* helper routine */ 2313 STATIC void 2314 _soc_sort_bank_on_criteria(_soc_ism_sbo_t *list, uint8 size, uint8 criteria) 2315 { 2316 uint8 x, y; 2317 for (x=0; x < size-1; x++) { 2318 for (y=0; y < size-x-1; y++) { 2319 switch (criteria) { 2320 case _CRITERIA_ENTRY: _soc_hash_check_and_swap(&list[y], &list[y+1], 2321 list[y].entry, 2322 list[y+1].entry); 2323 break; 2324 case _CRITERIA_STAGE: _soc_hash_check_and_swap(&list[y], &list[y+1], 2325 list[y].stage, 2326 list[y+1].stage); 2327 break; 2328 case _CRITERIA_BANK: _soc_hash_check_and_swap(&list[y], &list[y+1], 2329 list[y].bank, 2330 list[y+1].bank); 2331 break; 2332 } 2333 } 2334 } 2335 } 2336 2337 /* determine the best entry index from multiple banks using various criterias */ 2338 void 2339 soc_ism_resolve_entry_index(_soc_ism_sbo_t *sbo, uint8 num_banks) 2340 { 2341 uint8 b, tie=0; 2342 _soc_sort_bank_on_criteria(sbo, num_banks, _CRITERIA_ENTRY); 2343 /* determine if there is a tie and sort further */ 2344 for (b = 0; b < num_banks - 1; b++) { 2345 if (sbo[b].entry == sbo[b+1].entry) { 2346 tie++; 2347 } else { 2348 break; 2349 } 2350 } 2351 if (!tie) { 2352 return; 2353 } 2354 _soc_sort_bank_on_criteria(sbo, tie, _CRITERIA_BANK); 2355 num_banks = tie; 2356 tie=0; 2357 /* determine if there is a tie and sort further */ 2358 for (b = 0; b < num_banks - 1; b++) { 2359 if (sbo[b].bank == sbo[b+1].bank) { 2360 tie++; 2361 } else { 2362 break; 2363 } 2364 } 2365 if (!tie) { 2366 return; 2367 } 2368 num_banks = tie; 2369 tie=0; 2370 /* determine if there is a tie and sort further */ 2371 _soc_sort_bank_on_criteria(sbo, num_banks, _CRITERIA_STAGE); 2372 } 2373 2374 /* helper function: It has specific memory names and logic but that is only to 2375 make it work as fast as possible */ 2376 uint8 2377 soc_ism_get_bucket_offset(int unit, soc_mem_t mem, int8 midx, void *new_entry, 2378 void *existing_entry) 2379 { 2380 uint8 i, incr = 1, kts; 2381 uint32 new_kt, existing_kt; 2382 soc_hash_mem_set_t *shms; 2383 soc_hash_mem_t *shm; 2384 2385 if (midx < 0) { 2386 midx = soc_ism_get_hash_mem_idx(unit, mem); 2387 } 2388 shms = _SOC_ISM_MEMS(unit)[midx].shms; 2389 if (shms->num_mems == 1) { 2390 return incr; 2391 } 2392 if ((mem == L2_ENTRY_1m) || (mem == L2_ENTRY_2m)) { 2393 if (soc_mem_field32_get(unit, L2_ENTRY_1m, existing_entry, WIDEf)) { 2394 return 2; 2395 } else { 2396 if (soc_mem_field32_get(unit, L2_ENTRY_1m, new_entry, WIDEf)) { 2397 return 2; 2398 } 2399 return incr; 2400 } 2401 } 2402 if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) { 2403 new_kt = soc_mem_field32_get(unit, mem, new_entry, KEY_TYPEf); 2404 } else { 2405 new_kt = soc_mem_field32_get(unit, mem, new_entry, KEY_TYPE_0f); 2406 } 2407 if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) { 2408 existing_kt = soc_mem_field32_get(unit, mem, existing_entry, KEY_TYPEf); 2409 } else { 2410 existing_kt = soc_mem_field32_get(unit, mem, existing_entry, KEY_TYPE_0f); 2411 } 2412 kts = shms->num_keys; 2413 for (i=0; i<kts; i++) { 2414 if (shms->shk[i].key_type == existing_kt) { 2415 shm = shms->shk[i].hmv->shm; 2416 if (shm->mem == VLAN_XLATEm || shm->mem == L3_ENTRY_1m || 2417 shm->mem == MPLS_ENTRYm) { 2418 break; 2419 } else if (shm->mem == VLAN_XLATE_EXTDm || shm->mem == L3_ENTRY_2m || 2420 shm->mem == MPLS_ENTRY_EXTDm) { 2421 incr = 2; 2422 break; 2423 } else { 2424 return 4; 2425 } 2426 } 2427 } 2428 /* Need to check new entry's size and return index increment appropriately */ 2429 for (i=0; i<kts; i++) { 2430 if (shms->shk[i].key_type == new_kt) { 2431 shm = shms->shk[i].hmv->shm; 2432 if (shm->mem == VLAN_XLATEm || shm->mem == L3_ENTRY_1m || 2433 shm->mem == MPLS_ENTRYm) { 2434 return (incr > 1) ? incr : 1; 2435 } else if (shm->mem == VLAN_XLATE_EXTDm || shm->mem == L3_ENTRY_2m || 2436 shm->mem == MPLS_ENTRY_EXTDm) { 2437 return 2; 2438 } else { 2439 return 4; 2440 } 2441 } 2442 } 2443 return incr; 2444 } 2445 2446 /* helper function */ 2447 STATIC void 2448 _soc_append_mem_field_to_data(soc_mem_info_t *meminfo, uint8 *key, uint16 offset, 2449 uint32 *fldbuf, uint16 size, uint8 lendian) 2450 { 2451 int32 len; 2452 uint32 mask, i, wp, bp; 2453 uint32 *entbuf = (uint32 *)key; 2454 2455 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2456 (BSL_META("offset: %d, size: %d\n"), offset, size)); 2457 if (lendian) { 2458 wp = offset / 32; 2459 bp = offset & (32 - 1); 2460 i = 0; 2461 for (len = size; len > 0; len -= 32) { 2462 if (bp) { 2463 if (len < 32) { 2464 mask = (1 << len) - 1; 2465 } else { 2466 mask = -1; 2467 } 2468 2469 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~(mask << bp); 2470 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |= fldbuf[i] << bp; 2471 if (len > (32 - bp)) { 2472 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~(mask >> (32 - bp)); 2473 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] |= 2474 fldbuf[i] >> (32 - bp) & ((1 << bp) - 1); 2475 } 2476 } else { 2477 if (len < 32) { 2478 mask = (1 << len) - 1; 2479 entbuf[FIX_MEM_ORDER_E(wp, meminfo)] &= ~mask; 2480 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] |= fldbuf[i] << bp; 2481 } else { 2482 entbuf[FIX_MEM_ORDER_E(wp++, meminfo)] = fldbuf[i]; 2483 } 2484 } 2485 i++; 2486 } 2487 } else { 2488 bp = offset; 2489 len = size; 2490 while (len > 0) { 2491 len--; 2492 entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] &= ~(1 << (bp & (32-1))); 2493 entbuf[FIX_MEM_ORDER_E(bp / 32, meminfo)] |= 2494 (fldbuf[len / 32] >> (len & (32-1)) & 1) << (bp & (32-1)); 2495 bp++; 2496 } 2497 } 2498 } 2499 2500 /* Create final key by concatenating various key fields from a mem entry */ 2501 void 2502 soc_ism_gen_key_from_keyfields(int unit, soc_mem_t mem, void *entry, 2503 soc_field_t *keyflds, uint8 *key, uint8 num_flds) 2504 { 2505 int16 i; 2506 uint8 j = 0; 2507 uint32 val[SOC_MAX_MEM_WORDS]; 2508 uint16 offset = 0, len; 2509 soc_mem_info_t *meminfo; 2510 soc_field_info_t *fieldinfo; 2511 meminfo = &SOC_MEM_INFO(unit, mem); 2512 2513 for (i = 0; i < num_flds; i++) { 2514 SOC_FIND_FIELD(keyflds[i], meminfo->fields, meminfo->nFields, 2515 fieldinfo); 2516 if (NULL == fieldinfo) { 2517 LOG_CLI((BSL_META_U(unit, 2518 "mem %s field %s is invalid\n"), 2519 SOC_MEM_NAME(unit, mem), SOC_FIELD_NAME(unit, keyflds[i]))); 2520 assert(fieldinfo); 2521 } 2522 soc_mem_field_get(unit, mem, entry, keyflds[i], val); 2523 len = soc_mem_field_length(unit, mem, keyflds[i]); 2524 _soc_append_mem_field_to_data(meminfo, key, offset, val, len, 2525 fieldinfo->flags & SOCF_LE); 2526 offset += len; 2527 } 2528 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2529 (BSL_META_U(unit, 2530 "Combined Key: "))); 2531 for (i = offset; i > 0; i-=8) { 2532 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2533 (BSL_META_U(unit, 2534 "%0x "), key[j++])); 2535 } 2536 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2537 (BSL_META_U(unit, 2538 "\n"))); 2539 } 2540 2541 /* Create key to be used in crc calculation by concatenating various key fields 2542 from a mem entry and taking care of padding, alignment etc */ 2543 void 2544 soc_ism_gen_crc_key_from_keyfields(int unit, soc_mem_t mem, void *entry, 2545 soc_field_t *keyflds, uint8 *key, 2546 uint8 num_flds, uint16 *bit_count) 2547 { 2548 uint8 i; 2549 soc_field_t field; 2550 uint16 key_index, val_index, fval_index; 2551 uint16 right_shift_count, left_shift_count; 2552 uint32 val[SOC_MAX_MEM_WORDS], fval[SOC_MAX_MEM_WORDS]; 2553 int16 val_bits = *bit_count, fval_bits; 2554 uint16 bits, field_length[16]; 2555 int key_type; 2556 2557 for (i = 0; i < num_flds; i++) { 2558 field = keyflds[i]; 2559 field_length[i] = soc_mem_field_length(unit, mem, field); 2560 } 2561 2562 bits = (val_bits + 7) & ~0x7; 2563 sal_memset(val, 0, sizeof(val)); 2564 val_bits = bits - val_bits; 2565 for (i = 0; i < num_flds; i++) { 2566 field = keyflds[i]; 2567 soc_mem_field_get(unit, mem, entry, field, fval); 2568 2569 /* For TR3, only key_types that support regular/extended entries should 2570 force key_type[0] to 0 for the hash calculation. These memories are 2571 handled below */ 2572 2573 if(SOC_IS_TRIUMPH3(unit)) { 2574 2575 if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) { 2576 key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf); 2577 } else { 2578 key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPE_0f); 2579 } 2580 2581 if (mem == L2_ENTRY_1m) { 2582 if ((key_type == SOC_MEM_KEY_L2_ENTRY_1_L2_BRIDGE) || 2583 (key_type == SOC_MEM_KEY_L2_ENTRY_1_L2_VFI)) { 2584 fval[0] &= ~1; 2585 } 2586 } else if (mem == L2_ENTRY_2m) { 2587 if ((key_type == SOC_MEM_KEY_L2_ENTRY_2_L2_BRIDGE) || 2588 (key_type == SOC_MEM_KEY_L2_ENTRY_2_L2_VFI)) { 2589 fval[0] &= ~1; 2590 } 2591 } else if (mem == VLAN_XLATE_EXTDm) { 2592 if ((key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_IVID_OVID) || 2593 (key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_OVID) || 2594 (key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_IVID) || 2595 (key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_OTAG) || 2596 (key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_ITAG) || 2597 (key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_PRI_CFI) || 2598 (key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_IVID_OVID_SVP) || 2599 (key_type == SOC_MEM_KEY_VLAN_XLATE_2_XLATE_OVID_SVP)) { 2600 fval[0] &= ~1; 2601 } 2602 } else if (mem == L3_ENTRY_2m) { 2603 if (key_type == SOC_MEM_KEY_L3_ENTRY_2_IPV4UC_IPV4_UNICAST) { 2604 fval[0] &= ~1; 2605 } 2606 } else if (mem == L3_ENTRY_4m) { 2607 if(key_type == SOC_MEM_KEY_L3_ENTRY_4_IPV6UC_IPV6_UNICAST) { 2608 fval[0] &= ~1; 2609 } 2610 } else if (mem == MPLS_ENTRY_EXTDm) { 2611 if ((key_type == SOC_MEM_KEY_MPLS_ENTRY_2_MPLS_MPLS_FIRST_PASS) || 2612 (key_type == SOC_MEM_KEY_MPLS_ENTRY_2_MPLS_MPLS_SECOND_PASS)) { 2613 fval[0] &= ~1; 2614 } 2615 } 2616 } else { 2617 fval[0] &= ~1; 2618 } 2619 2620 fval_bits = field_length[i]; 2621 2622 val_index = val_bits >> 5; 2623 fval_index = 0; 2624 left_shift_count = val_bits & 0x1f; 2625 right_shift_count = 32 - left_shift_count; 2626 val_bits += fval_bits; 2627 2628 if (left_shift_count) { 2629 for (; fval_bits > 0; fval_bits -= 32) { 2630 val[val_index++] |= fval[fval_index] << left_shift_count; 2631 val[val_index] |= fval[fval_index++] >> right_shift_count; 2632 } 2633 } else { 2634 for (; fval_bits > 0; fval_bits -= 32) { 2635 val[val_index++] = fval[fval_index++]; 2636 } 2637 } 2638 } 2639 2640 key_index = 0; 2641 for (val_index = 0; val_bits > 0; val_index++) { 2642 for (right_shift_count = 0; right_shift_count < 32; 2643 right_shift_count += 8) { 2644 if (val_bits <= 0) { 2645 break; 2646 } 2647 key[key_index++] = (val[val_index] >> right_shift_count) & 0xff; 2648 val_bits -= 8; 2649 } 2650 } 2651 2652 if ((bits + 7) / 8 > key_index) { 2653 sal_memset(&key[key_index], 0, (bits + 7) / 8 - key_index); 2654 } 2655 *bit_count = bits; 2656 } 2657 2658 /* Create a valid memory entry from a compacted key */ 2659 int 2660 soc_gen_entry_from_key(int unit, soc_mem_t mem, uint8 *key, void *entry) 2661 { 2662 int8 i, j, f = 0, found = 0; 2663 uint16 len, num_flds = 0; 2664 uint32 keyf[4] = {0}; 2665 uint16 minb = 0, maxb; 2666 uint32 fvalue[SOC_MAX_MEM_WORDS] = {0}; 2667 int key_type; 2668 2669 if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) { 2670 len = soc_mem_field_length(unit, mem, KEY_TYPEf); 2671 soc_bits_get((uint32*)&key[0], 0, len-1, fvalue); 2672 key_type = fvalue[0]; 2673 } else { 2674 len = soc_mem_field_length(unit, mem, KEY_TYPE_0f); 2675 soc_bits_get((uint32*)&key[0], 0, len-1, fvalue); 2676 key_type = fvalue[0]; 2677 } 2678 i = soc_ism_get_hash_mem_idx(unit, mem); 2679 if (i < 0) { 2680 LOG_ERROR(BSL_LS_SOC_COMMON, 2681 (BSL_META_U(unit, 2682 "Invalid hash memory !!\n"))); 2683 return SOC_E_PARAM; 2684 } 2685 for (j = 0; j < _SOC_ISM_MEMS(unit)[i].shms->num_keys; j++) { 2686 if (_SOC_ISM_MEMS(unit)[i].shms->shk[j].hmv->shm->mem == mem) { 2687 if (key_type == _SOC_ISM_MEMS(unit)[i].shms->shk[j].key_type) { 2688 found = 1; 2689 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2690 (BSL_META_U(unit, 2691 "Input key_type: %d found for mem: %s\n"), 2692 key_type, SOC_MEM_NAME(unit, mem))); 2693 break; 2694 } 2695 } 2696 } 2697 if (!found) { 2698 LOG_CLI((BSL_META_U(unit, 2699 "Key type not found for this memory !!\n"))); 2700 return SOC_E_INTERNAL; 2701 } 2702 while (_SOC_ISM_MEMS(unit)[i].shms->shk[j].hmv->key_fields[f] != -1) { 2703 keyf[f] = _SOC_ISM_MEMS(unit)[i].shms->shk[j].hmv->key_fields[f]; 2704 f++; 2705 num_flds = f; 2706 } 2707 for (i=0; i<num_flds; i++) { 2708 len = soc_mem_field_length(unit, mem, keyf[i]); 2709 maxb = minb+len-1; 2710 /*LOG_CLI((BSL_META_U(unit, 2711 "Min: %d, Max: %d\n"), minb, maxb));*/ 2712 soc_bits_get((uint32*)&key[0], minb, maxb, fvalue); 2713 soc_mem_field_set(unit, mem, entry, keyf[i], fvalue); 2714 minb = maxb+1; 2715 } 2716 /* Make the entry valid and properly sized */ 2717 if (SOC_MEM_FIELD_VALID(unit, mem, VALIDf)) { 2718 soc_mem_field32_set(unit, mem, entry, VALIDf, 1); 2719 } else { 2720 soc_mem_field32_set(unit, mem, entry, VALID_0f, 1); 2721 soc_mem_field32_set(unit, mem, entry, VALID_1f, 1); 2722 if (SOC_MEM_FIELD_VALID(unit, mem, VALID_2f)) { 2723 soc_mem_field32_set(unit, mem, entry, VALID_2f, 1); 2724 soc_mem_field32_set(unit, mem, entry, VALID_3f, 1); 2725 } 2726 } 2727 if (SOC_MEM_FIELD_VALID(unit, mem, WIDE_0f)) { 2728 soc_mem_field32_set(unit, mem, entry, WIDE_0f, 1); 2729 soc_mem_field32_set(unit, mem, entry, WIDE_1f, 1); 2730 } 2731 return SOC_E_NONE; 2732 } 2733 2734 /* Generate entry with key fields set, used for direct comparision */ 2735 int 2736 soc_gen_key_from_entry(int unit, soc_mem_t mem, void *entry, void *key) 2737 { 2738 uint8 i, num_flds; 2739 uint32 val[SOC_MAX_MEM_WORDS]; 2740 soc_field_t keyflds[MAX_FIELDS], lsbfld; 2741 soc_mem_info_t *meminfo; 2742 soc_field_info_t *fieldinfo; 2743 int32 memidx = soc_ism_get_hash_mem_idx(unit, mem); 2744 2745 if (memidx < 0) { 2746 LOG_ERROR(BSL_LS_SOC_COMMON, 2747 (BSL_META_U(unit, 2748 "Invalid hash memory: %s !!\n"), 2749 SOC_MEM_NAME(unit, mem))); 2750 return SOC_E_PARAM; 2751 } 2752 meminfo = &SOC_MEM_INFO(unit, mem); 2753 2754 if (soc_generic_get_hash_key(unit, mem, entry, keyflds, &lsbfld, 2755 &num_flds) == SOC_E_NONE) { 2756 for (i = 0; i < num_flds; i++) { 2757 SOC_FIND_FIELD(keyflds[i], meminfo->fields, meminfo->nFields, 2758 fieldinfo); 2759 if (NULL == fieldinfo) { 2760 LOG_CLI((BSL_META_U(unit, 2761 "mem %s field %s is invalid\n"), 2762 SOC_MEM_NAME(unit, mem), SOC_FIELD_NAME(unit, keyflds[i]))); 2763 assert(fieldinfo); 2764 } 2765 soc_mem_field_get(unit, mem, entry, keyflds[i], val); 2766 soc_mem_field_set(unit, mem, key, keyflds[i], val); 2767 /* Make the entry valid and properly sized */ 2768 if (SOC_MEM_FIELD_VALID(unit, mem, VALIDf)) { 2769 soc_mem_field32_set(unit, mem, key, VALIDf, 1); 2770 } else { 2771 soc_mem_field32_set(unit, mem, key, VALID_0f, 1); 2772 soc_mem_field32_set(unit, mem, key, VALID_1f, 1); 2773 if (SOC_MEM_FIELD_VALID(unit, mem, VALID_2f)) { 2774 soc_mem_field32_set(unit, mem, key, VALID_2f, 1); 2775 soc_mem_field32_set(unit, mem, key, VALID_3f, 1); 2776 } 2777 } 2778 if (SOC_MEM_FIELD_VALID(unit, mem, WIDE_0f)) { 2779 soc_mem_field32_set(unit, mem, key, WIDE_0f, 1); 2780 soc_mem_field32_set(unit, mem, key, WIDE_1f, 1); 2781 } 2782 } 2783 return SOC_E_NONE; 2784 } 2785 return SOC_E_INTERNAL; 2786 } 2787 2788 /* 2789 * Main hash execution routine. 2790 * NOTE: Heavily overloaded, modify with care. 2791 * Returns index, result and optionally the last accessed bucket, 2792 * number of entries in a bucket for the memory. 2793 */ 2794 int 2795 soc_generic_hash(int unit, soc_mem_t mem, void *entry, int32 banks, 2796 uint8 op, int *index, uint32 *result, uint32 *base_idx, 2797 uint8 *num_entries) 2798 { 2799 int rv; 2800 soc_hash_bank_t *shbank; 2801 uint16 lsb, midx, num_bits; 2802 int32 bits, memidx, bucket = 0; 2803 uint32 tmp_hs[SOC_MAX_MEM_WORDS]; 2804 uint32 idx, bidx = 0, zero_lsb, offset, mask; 2805 uint8 idxinc = 1, num_flds, num_banks = 0; 2806 uint8 found = 0, key[SOC_HASH_MEM_MAX_KEY_BUFFER_SIZE_BYTES], tmp_key[SOC_HASH_MEM_MAX_KEY_BUFFER_SIZE_BYTES], crc_key[SOC_HASH_MEM_MAX_KEY_BUFFER_SIZE_BYTES]; 2807 _soc_ism_sbo_t sbo[_SOC_ISM_MAX_BANKS]; /* Dynamically created bank info based upon 2808 requested banks used for final 2809 bucket/index calculation */ 2810 soc_field_t keyflds[MAX_FIELDS], lsbfld, vf = VALIDf; 2811 2812 memidx = soc_ism_get_hash_mem_idx(unit, mem); 2813 if (memidx < 0) { 2814 LOG_ERROR(BSL_LS_SOC_COMMON, 2815 (BSL_META_U(unit, 2816 "Invalid hash memory !!\n"))); 2817 return SOC_E_PARAM; 2818 } 2819 if (!_SOC_ISM_MEMS(unit)[memidx].shms->num_banks) { 2820 return SOC_E_PARAM; 2821 } 2822 if (soc_generic_get_hash_key(unit, mem, entry, keyflds, &lsbfld, 2823 &num_flds) == SOC_E_NONE) { 2824 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2825 (BSL_META_U(unit, 2826 "Key field(s): "))); 2827 for (idx = 0; idx < num_flds; idx++) { 2828 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2829 (BSL_META_U(unit, 2830 "%d, "), keyflds[idx])); 2831 } 2832 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2833 (BSL_META_U(unit, 2834 "\nLsb field: %d\n"), lsbfld)); 2835 sal_memset(key, 0, sizeof(key)); 2836 sal_memset(crc_key, 0, sizeof(crc_key)); 2837 soc_ism_gen_key_from_keyfields(unit, mem, entry, keyflds, key, num_flds); 2838 num_bits = _SOC_ISM_MEMS(unit)[memidx].shms->max_key_bits; 2839 soc_ism_gen_crc_key_from_keyfields(unit, mem, entry, keyflds, crc_key, 2840 num_flds, &num_bits); 2841 lsb = soc_mem_field32_get(unit, mem, entry, lsbfld); 2842 } else { 2843 LOG_CLI((BSL_META_U(unit, 2844 "Key field not found !!\n"))); 2845 return -1; 2846 } 2847 shbank = _SOC_ISM_MEMS(unit)[memidx].shms->shb; 2848 bits = soc_mem_entry_bits(unit, mem); 2849 if (bits > (_SOC_ISM_ENTRY_BITS * 2)) { 2850 idxinc = 4; 2851 } else if (bits > _SOC_ISM_ENTRY_BITS) { 2852 idxinc = 2; 2853 } 2854 zero_lsb = _SOC_ISM_SETS(unit)[_SOC_ISM_MEMS(unit)[memidx].shms->mem_set-1].zero_lsb; 2855 sal_memset(sbo, 0, sizeof(sbo)); 2856 for (idx = 0; idx < _SOC_ISM_MEMS(unit)[memidx].shms->num_banks; idx++) { 2857 if (banks != -1) { 2858 /* only use the indicated bank */ 2859 if (!((((int32)1) << shbank[idx].my_id) & banks)) { 2860 continue; 2861 } 2862 num_banks++; 2863 } else { 2864 num_banks++; 2865 } 2866 sbo[bidx].mode = -1; 2867 sbo[bidx].bidx = bidx; 2868 mask = soc_ism_get_hash_bucket_mask(shbank[idx].num_bkts); 2869 offset = shbank[idx].hash_offset; 2870 bucket = soc_generic_gen_hash(unit, zero_lsb, num_bits, offset, 2871 mask, crc_key, lsb); 2872 sbo[bidx].index = bucket; 2873 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2874 (BSL_META_U(unit, 2875 "Bank[%d]: bucket:%d\n"), bidx, bucket)); 2876 if (base_idx) { 2877 *base_idx = sbo[bidx].index; 2878 } 2879 if (num_entries) { 2880 *num_entries = shbank[idx].bkt_size/idxinc; 2881 } 2882 sbo[bidx].index = (shbank[idx].base_entry/idxinc) + 2883 (sbo[bidx].index * (shbank[idx].bkt_size/idxinc)); 2884 if (op == 0) { /* Special bucket seek op */ 2885 *index = sbo[bidx].index; 2886 return SOC_E_NONE; 2887 } 2888 for (midx = 0; midx < shbank[idx].bkt_size/idxinc;) { 2889 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, sbo[bidx].index+midx, 2890 tmp_hs); 2891 if (SOC_FAILURE(rv)) { 2892 return rv; 2893 } 2894 if (!SOC_MEM_FIELD_VALID(unit, mem, VALIDf)) { 2895 vf = VALID_0f; 2896 } 2897 if (soc_mem_field32_get(unit, mem, tmp_hs, vf)) { 2898 sal_memset(tmp_key, 0, sizeof(tmp_key)); 2899 /* compare key */ 2900 soc_ism_gen_key_from_keyfields(unit, mem, tmp_hs, keyflds, 2901 tmp_key, num_flds); 2902 if (!sal_memcmp(key, tmp_key, sizeof(key))) { 2903 found++; 2904 sbo[bidx].entry = midx; 2905 sbo[bidx].stage = shbank[idx].my_id / SOC_ISM_INFO(unit)->banks_per_stage; 2906 sbo[bidx].bank = shbank[idx].my_id % SOC_ISM_INFO(unit)->banks_per_stage; 2907 sbo[bidx].mode = 1; 2908 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2909 (BSL_META_U(unit, 2910 "Existing mem index: %d\n"), 2911 sbo[bidx].index+sbo[bidx].entry)); 2912 if (op != TABLE_INSERT_CMD_MSG) { 2913 *index = sbo[bidx].index + midx; 2914 if (op == TABLE_LOOKUP_CMD_MSG) { 2915 *result = SCHAN_GEN_RESP_TYPE_FOUND; 2916 } else { 2917 *result = SCHAN_GEN_RESP_TYPE_DELETED; 2918 } 2919 return SOC_E_NONE; 2920 } 2921 break; 2922 } 2923 } else if (op == TABLE_INSERT_CMD_MSG) { 2924 found++; 2925 sbo[bidx].entry = midx; 2926 sbo[bidx].stage = shbank[idx].my_id / SOC_ISM_INFO(unit)->banks_per_stage; 2927 sbo[bidx].bank = shbank[idx].my_id % SOC_ISM_INFO(unit)->banks_per_stage; 2928 sbo[bidx].mode = 0; 2929 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2930 (BSL_META_U(unit, 2931 "New mem index: %d\n"), 2932 sbo[bidx].index+sbo[bidx].entry)); 2933 break; 2934 } 2935 /* Determine bucket offset increment based upon existing entry type/size */ 2936 midx += soc_ism_get_bucket_offset(unit, mem, memidx, entry, tmp_hs); 2937 } 2938 bidx++; 2939 } 2940 if (!found) { 2941 if (op == TABLE_INSERT_CMD_MSG) { 2942 *result = SCHAN_GEN_RESP_TYPE_FULL; 2943 } else { 2944 *result = SCHAN_GEN_RESP_TYPE_NOT_FOUND; 2945 return SOC_E_NONE; 2946 } 2947 } 2948 /* Get the lowest valid/empty index of the lowest bank-id of the lowest stage-id */ 2949 if (found > 1) { 2950 soc_ism_resolve_entry_index(sbo, num_banks); 2951 } 2952 for (idx = 0; idx < num_banks; idx++) { 2953 if (sbo[idx].mode >= 0) { 2954 *index = sbo[idx].index + sbo[idx].entry; 2955 if (sbo[idx].mode) { 2956 *result = SCHAN_GEN_RESP_TYPE_REPLACED; 2957 } else { 2958 *result = SCHAN_GEN_RESP_TYPE_INSERTED; 2959 } 2960 break; 2961 } 2962 } 2963 return SOC_E_NONE; 2964 } 2965 2966 /* 2967 * Normalize memory based on the key type: 2968 * 2969 * Move entry may be of different Key type and may have been inserted with 2970 * different memory view. Hence the need to normalize the memory view name 2971 * with respect to move_entry. The mem field is not the view used to insert 2972 * the entry, to make space for the incoming entry, existing entries are moved. 2973 * The move need to happen with respect to the memory view used to insert the 2974 * the already existing entry. 2975 */ 2976 STATIC void 2977 soc_mem_multi_hash_norm_mem(int unit, soc_mem_t mem, void *entry, soc_mem_t *norm_mem) 2978 { 2979 int s, k, key_type; 2980 *norm_mem = mem; 2981 2982 if (SOC_MEM_FIELD_VALID(unit, mem, KEY_TYPEf)) { 2983 key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPEf); 2984 } else { 2985 key_type = soc_mem_field32_get(unit, mem, entry, KEY_TYPE_0f); 2986 } 2987 s = soc_ism_get_hash_mem_idx(unit, mem); 2988 for (k = 0; k < _SOC_ISM_MEMS(unit)[s].shms->num_keys; k++) { 2989 if (key_type == _SOC_ISM_MEMS(unit)[s].shms->shk[k].key_type) { 2990 *norm_mem = _SOC_ISM_MEMS(unit)[s].shms->shk[k].hmv->shm->mem; 2991 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 2992 (BSL_META_U(unit, 2993 "Normalized for key_type: %d mem: %s\n"), 2994 key_type, SOC_MEM_NAME(unit, *norm_mem))); 2995 break; 2996 } 2997 } 2998 } 2999 3000 /* 3001 * Function: 3002 * _soc_mem_multi_hash_big_to_small_move_chk 3003 * Purpose: 3004 * Checks if bigger entry can be moved into 3005 * smaller entry. 3006 * Parameters: 3007 * v0, v1, v2, v3 - (IN) valid bits for entry. 3008 * mem - (IN/OUT) memory. 3009 * index - (IN/OUT) index of entry 3010 * offset - (IN) offset of entry 3011 * old_mem - (IN) the old memory type 3012 * Returns: 3013 * 1 = moe allowed, 0 = move not allowed 3014 */ 3015 STATIC int 3016 _soc_mem_multi_hash_big_to_small_move_chk(int v0, int v1, int v2, int v3, 3017 soc_mem_t *mem, int *index, int offset, soc_mem_t old_mem) 3018 { 3019 int entry_num = v0 + v1 + v2 + v3; 3020 int double_wide_upper_num = v0 + v1; 3021 int double_wide_lower_num = v2 + v3; 3022 soc_mem_t orig_mem = *mem; 3023 int orig_idx = *index + offset; 3024 int index_offset = 0; 3025 3026 switch (orig_mem) { 3027 case L3_ENTRY_4m: 3028 if (entry_num == 1) { 3029 index_offset = v0 ? 0 : (v1 ? 1 : (v2 ? 2 : (v3 ? 3 : 0))); 3030 *mem = L3_ENTRY_1m; 3031 *index = orig_idx * 4 + index_offset; 3032 return 1; 3033 } else if (entry_num == 2) { 3034 if ((double_wide_upper_num == 2 || double_wide_lower_num == 2) && 3035 (old_mem == L3_ENTRY_2m)) { 3036 index_offset = double_wide_upper_num ? 0 : 1; 3037 *mem = L3_ENTRY_2m; 3038 *index = orig_idx * 2 + index_offset; 3039 return 1; 3040 } 3041 } 3042 break; 3043 case L3_ENTRY_2m: 3044 if (entry_num == 1) { 3045 index_offset = v0 ? 0 : 1; 3046 *mem = L3_ENTRY_1m; 3047 *index = orig_idx * 2 + index_offset; 3048 return 1; 3049 } 3050 break; 3051 case L2_ENTRY_2m: 3052 if (entry_num == 1) { 3053 index_offset = v0 ? 0 : 1; 3054 *mem = L2_ENTRY_1m; 3055 *index = orig_idx * 2 + index_offset; 3056 return 1; 3057 } 3058 break; 3059 default: 3060 /* no entry narrower than L3_ENTRY_1m/L2_ENTRY_1m */ 3061 return 0; 3062 } 3063 return 0; 3064 } 3065 3066 /* 3067 * Function: 3068 * _soc_mem_multi_hash_entry_cmp 3069 * Purpose: 3070 * Compares various entry types and return size diffs. 3071 * Parameters: 3072 * unit - (IN)SOC unit number. 3073 * new_mem - (IN) memory to compare 3074 * old_mem - (IN) other memory to compare 3075 * Returns: 3076 * compare result 3077 */ 3078 STATIC int 3079 _soc_mem_multi_hash_entry_cmp(int unit, soc_mem_t new_mem, soc_mem_t old_mem) 3080 { 3081 int o_sz = 1; 3082 int n_sz = 1; 3083 /* 3084 * Different memories may require different size entries. 3085 * When moving the entries we need to see the width of 3086 * entries in the process of movement to make sure we dont 3087 * corrupt different sized entry. 3088 * e.g. L3_ENTRY_4 takes 4 h/w entries and L3_ENTRY_2 takes 2. 3089 */ 3090 /* L3 memories */ 3091 o_sz = (old_mem == L3_ENTRY_4m) ? 4 : ((old_mem == L3_ENTRY_2m) ? 2 : o_sz); 3092 n_sz = (new_mem == L3_ENTRY_4m) ? 4 : ((new_mem == L3_ENTRY_2m) ? 2 : n_sz); 3093 3094 /* L2 memories */ 3095 o_sz = (old_mem == L2_ENTRY_2m) ? 2 : ((old_mem == L2_ENTRY_1m) ? 1 : o_sz); 3096 n_sz = (new_mem == L2_ENTRY_2m) ? 2 : ((new_mem == L2_ENTRY_1m) ? 1 : n_sz); 3097 3098 /* return width differences */ 3099 if (o_sz < n_sz) { 3100 return -1; 3101 } else if (o_sz > n_sz) { 3102 return o_sz / n_sz; 3103 } 3104 return 0; 3105 } 3106 3107 /* 3108 * Function: 3109 * _soc_mem_multi_hash_get_valid_entries 3110 * Purpose: 3111 * Gets the valid entries based on a memory. 3112 * Parameters: 3113 * unit - (IN) SOC unit number. 3114 * mem - (IN) memory type 3115 * move_entry - (IN) memory to read 3116 * vo,v1,v2,v3 - (OUT) valid bits 3117 * Returns: 3118 * valid bit count 3119 */ 3120 STATIC int 3121 _soc_mem_multi_hash_get_valid_entries(int unit, soc_mem_t mem, uint32 *move_entry, 3122 uint32 *v0, uint32 *v1, 3123 uint32 *v2, uint32 *v3) 3124 { 3125 /* Initialize all of these to 0.*/ 3126 *v0 = *v1 = *v2 = *v3 = 0; 3127 switch (mem) { 3128 case L3_ENTRY_4m: 3129 /* Get v2,v3 and fall through to next case to get v0,v1.*/ 3130 /* coverity[fallthrough] */ 3131 *v3 = soc_mem_field32_get(unit, mem, move_entry, VALID_3f); 3132 *v2 = soc_mem_field32_get(unit, mem, move_entry, VALID_2f); 3133 case L3_ENTRY_2m: 3134 case L2_ENTRY_2m: 3135 *v1 = soc_mem_field32_get(unit, mem, move_entry, VALID_1f); 3136 *v0 = soc_mem_field32_get(unit, mem, move_entry, VALID_0f); 3137 break; 3138 case L3_ENTRY_1m: 3139 case L2_ENTRY_1m: 3140 *v0 = soc_mem_field32_get(unit, mem, move_entry, VALIDf); 3141 break; 3142 default: 3143 *v0 = *v1 = *v2 = *v3 = 1; 3144 break; 3145 } 3146 return (*v0 + *v1 + *v2 + *v3); 3147 } 3148 3149 int 3150 soc_mem_multi_hash_move(int unit, soc_mem_t mem, int32 banks, int copyno, 3151 void *entry, SHR_BITDCL *bucket_trace, 3152 _soc_ism_mem_banks_t *banks_info, int recurse_depth) 3153 { 3154 SHR_BITDCL *trace; 3155 int32 nbix; 3156 int rv = SOC_E_NONE, cmp_rv, index, orig_index; 3157 _soc_ism_mem_banks_t *mem_banks; 3158 uint8 i, bix, num_ent, found = 0; 3159 uint32 cb=0, db, dest_bucket_index, result, trace_size = 0; 3160 uint32 bucket_index, move_entry[SOC_MAX_MEM_WORDS]; 3161 soc_mem_t orig_mem = mem; 3162 soc_mem_t norm_mem = INVALIDm; 3163 static uint32 numb = 0; 3164 uint32 v0, v1, v2, v3; 3165 uint8 orig_mem_offset, norm_mem_offset; 3166 uint8 banks_count, max_banks_count; 3167 3168 if (recurse_depth < 0) { 3169 return SOC_E_FULL; 3170 } 3171 /* Stack variables initialization & memory allocations */ 3172 if (NULL == bucket_trace) { 3173 /* For simplicity, allocate same/max number of bits for buckets for all banks */ 3174 numb = _SOC_ISM_BANK0_SIZE; 3175 /* Keep back trace of all buckets affected by recursion. */ 3176 trace_size = SHR_BITALLOCSIZE(numb * _SOC_ISM_MAX_BANKS); 3177 trace = sal_alloc(trace_size, "N hash"); 3178 if (NULL == trace) { 3179 return (SOC_E_MEMORY); 3180 } 3181 sal_memset(trace, 0, trace_size); 3182 mem_banks = sal_alloc(sizeof(_soc_ism_mem_banks_t), "N hash banks"); 3183 if (NULL == mem_banks) { 3184 sal_free(trace); 3185 return (SOC_E_MEMORY); 3186 } 3187 sal_memset(mem_banks, 0, sizeof(_soc_ism_mem_banks_t)); 3188 /* Get mems bank info */ 3189 rv = soc_ism_get_banks_for_mem(unit, mem, mem_banks->banks, 3190 mem_banks->bank_size, &mem_banks->count); 3191 if (SOC_FAILURE(rv)) { 3192 sal_free(trace); 3193 sal_free(mem_banks); 3194 return rv; 3195 } 3196 if (mem_banks->count == 1) { 3197 sal_free(trace); 3198 sal_free(mem_banks); 3199 return SOC_E_FULL; 3200 } 3201 } else { 3202 trace = bucket_trace; 3203 mem_banks = banks_info; 3204 } 3205 3206 if (banks != SOC_MEM_HASH_BANK_ALL) { 3207 /* current should be selected same as banks */ 3208 for (bix = 0; bix < mem_banks->count; bix++) { 3209 cb = (uint32)1 << mem_banks->banks[bix]; 3210 if (cb == banks) { 3211 break; 3212 } 3213 } 3214 if (mem_banks->count == bix) { 3215 rv = SOC_E_FULL; 3216 goto cleanup; 3217 } 3218 max_banks_count = 1; 3219 } else { 3220 bix = 0; 3221 max_banks_count = mem_banks->count; 3222 } 3223 3224 /* Iterate over banks. */ 3225 for (banks_count = 0; banks_count < max_banks_count; banks_count++) { 3226 3227 if (banks_count > 0) { 3228 bix++; 3229 if (bix >= mem_banks->count) { 3230 bix = 0; 3231 } 3232 } 3233 3234 cb = (uint32)1 << mem_banks->banks[bix]; /* current bank */ 3235 3236 rv = soc_generic_hash(unit, mem, entry, cb, 0, &index, &result, 3237 &bucket_index, &num_ent); 3238 if (SOC_FAILURE(rv)) { 3239 break; 3240 } 3241 3242 /* Skip if bucket was previous visited */ 3243 if (SHR_BITGET(trace, (numb * bix) + bucket_index)) { 3244 continue; 3245 } 3246 3247 SHR_BITSET(trace, (numb * bix) + bucket_index); 3248 /* keep bcakup for fall back */ 3249 orig_index = index; 3250 orig_mem = mem; 3251 3252 /* For each current bank iterate over other possible destination banks. */ 3253 for (nbix = 0; nbix < mem_banks->count; nbix++) { 3254 if (bix == nbix) { 3255 continue; 3256 } 3257 3258 db = (uint32)1 << mem_banks->banks[nbix]; /* next destination bank */ 3259 3260 index = orig_index; 3261 mem = orig_mem; 3262 3263 /* Iterate over un-visited entries in the bucket */ 3264 for (i = 0; i < num_ent;) { 3265 rv = soc_mem_read(unit, mem, copyno, index+i, 3266 move_entry); 3267 if (SOC_FAILURE(rv)) { 3268 rv = SOC_E_MEMORY; 3269 break; 3270 } 3271 /* check if we have have found a free entry */ 3272 if(!(_soc_mem_multi_hash_get_valid_entries(unit, mem, move_entry, 3273 &v0, &v1, &v2, &v3))){ 3274 found = TRUE; 3275 break; 3276 } 3277 3278 /* Normalize memory based on the key type */ 3279 soc_mem_multi_hash_norm_mem(unit, mem, move_entry, &norm_mem); 3280 /* Compare memories to see width differences */ 3281 cmp_rv = _soc_mem_multi_hash_entry_cmp(unit, mem, norm_mem); 3282 if (cmp_rv == 0) { 3283 /* Calculate destination entry hash value. */ 3284 rv = soc_generic_hash(unit, mem, move_entry, db, 3285 0, &index, &result, 3286 &dest_bucket_index, NULL); 3287 if (SOC_FAILURE(rv)) { 3288 mem = orig_mem; 3289 break; 3290 } 3291 3292 if (SHR_BITGET(trace, (numb * nbix) + dest_bucket_index)) { 3293 /* Try next entry in the same bucket */ 3294 mem = orig_mem; 3295 index = orig_index; 3296 /* Mem and norm_mem has same entry wide 3297 * Try next entry in the same bucket by incrementing i */ 3298 i++; 3299 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3300 (BSL_META_U(unit, 3301 "Skip(1) bank %d bucket %d, go to bank %d index %d\n"), 3302 db, dest_bucket_index, cb, index+i)); 3303 continue; 3304 } 3305 } else if (cmp_rv < 0) { 3306 if (_soc_mem_multi_hash_big_to_small_move_chk(v0, v1, v2, v3, 3307 &mem, &index, i, norm_mem)) { 3308 if (SOC_FAILURE(soc_mem_read(unit, mem, copyno, index, 3309 move_entry))) { 3310 rv = SOC_E_MEMORY; 3311 mem = orig_mem; 3312 break; 3313 } 3314 /* Calculate destination entry hash value. */ 3315 rv = soc_generic_hash(unit, mem, move_entry, db, 3316 0, &index, &result, 3317 &dest_bucket_index, NULL); 3318 if (SOC_FAILURE(rv)) { 3319 mem = orig_mem; 3320 break; 3321 } 3322 if (SHR_BITGET(trace, (numb * nbix) + dest_bucket_index)) { 3323 /* Try next entry in the same bucket in original 3324 * memory view */ 3325 mem = orig_mem; 3326 index = orig_index; 3327 /* Mem is wider than norm_mem. 3328 * Try next entry in the same bucket by incrementing i */ 3329 i++; 3330 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3331 (BSL_META_U(unit, 3332 "Skip(2) bank %d bucket %d, go to mem %d " \ 3333 "bank %d index %d \n"), 3334 db, dest_bucket_index, mem, i >= num_ent ? db : cb, 3335 i >= num_ent ? -1 : (index+i))); 3336 continue; 3337 } 3338 } else { 3339 i++; 3340 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3341 (BSL_META_U(unit, 3342 "Depth %d, Existing entry width is narrower, but can't move." \ 3343 "Trying other entry in the bucket \n"), 3344 recurse_depth)); 3345 rv = SOC_E_NONE; 3346 continue; 3347 } 3348 } else { 3349 /* wider entry */ 3350 mem = norm_mem; 3351 index = (index + i) / cmp_rv; 3352 rv = soc_mem_read(unit, mem, copyno, index, move_entry); 3353 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3354 (BSL_META_U(unit, 3355 "Depth %d, G-2nd read %d index %d from bank %d bucket %d\n"), 3356 recurse_depth, mem, index, cb, bucket_index)); 3357 if (SOC_FAILURE(rv)) { 3358 rv = SOC_E_MEMORY; 3359 mem = orig_mem; 3360 break; 3361 } 3362 /* Calculate destination entry hash value. */ 3363 rv = soc_generic_hash(unit, mem, move_entry, db, 3364 0, &index, &result, 3365 &dest_bucket_index, NULL); 3366 if (SOC_FAILURE(rv)) { 3367 mem = orig_mem; 3368 break; 3369 } 3370 3371 if (SHR_BITGET(trace, (numb * nbix) + dest_bucket_index)) { 3372 mem = orig_mem; 3373 index = orig_index; 3374 /* Determine bucket offset increment based upon existing 3375 * entry type/size when orig_mem is single/double wide mode and 3376 * norm_mem is double/quad mode, 3377 * otherwise increment by 1 is sufficent */ 3378 orig_mem_offset = soc_ism_get_bucket_offset(unit, mem, -1, 3379 entry, move_entry); 3380 norm_mem_offset = soc_ism_get_bucket_offset(unit, norm_mem, -1, 3381 entry, move_entry); 3382 if (orig_mem_offset >= norm_mem_offset) { 3383 i++; 3384 } else { 3385 /* coverity[divide_by_zero] */ 3386 i += (norm_mem_offset / orig_mem_offset); 3387 } 3388 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3389 (BSL_META_U(unit, 3390 "Skip(3) bank %d bucket %d, go to bank %d index %d\n"), 3391 db, dest_bucket_index, cb, index+i)); 3392 continue; 3393 } 3394 } 3395 3396 /* Attempt to insert it into the other bank. */ 3397 rv = soc_mem_bank_insert(unit, mem, db, copyno, move_entry, NULL); 3398 if (SOC_FAILURE(rv)) { 3399 if (rv != SOC_E_FULL) { 3400 mem = orig_mem; 3401 break; 3402 } 3403 /* Recursive call - attempt to create a slot 3404 in another bank's bucket. */ 3405 rv = soc_mem_multi_hash_move(unit, mem, db, copyno, 3406 move_entry, trace, mem_banks, 3407 recurse_depth - 1); 3408 if (SOC_FAILURE(rv)) { 3409 mem = orig_mem; 3410 if (rv != SOC_E_FULL) { 3411 break; 3412 } 3413 index = orig_index; 3414 /* Determine bucket offset increment based upon existing 3415 * entry type/size when orig_mem is single/double wide mode and 3416 * norm_mem is double/quad mode, 3417 * otherwise increment by 1 is sufficent */ 3418 orig_mem_offset = soc_ism_get_bucket_offset(unit, mem, -1, 3419 entry, move_entry); 3420 norm_mem_offset = soc_ism_get_bucket_offset(unit, norm_mem, -1, 3421 entry, move_entry); 3422 if (orig_mem_offset >= norm_mem_offset) { 3423 i++; 3424 } else { 3425 /* coverity[divide_by_zero] */ 3426 i += (norm_mem_offset / orig_mem_offset); 3427 } 3428 continue; 3429 } 3430 } 3431 /* Entry was moved successfully. */ 3432 found = TRUE; 3433 /* Delete old entry from original location */ 3434 rv = soc_mem_generic_delete(unit, mem, MEM_BLOCK_ANY, cb, move_entry, 3435 NULL, NULL); 3436 mem = orig_mem; 3437 break; 3438 } /* Bucket iteration loop. */ 3439 if (found || ((rv < 0) && (rv != SOC_E_FULL))) { 3440 break; 3441 } 3442 } /* Destination Bank iteration loop. */ 3443 if (found || ((rv < 0) && (rv != SOC_E_FULL))) { 3444 break; 3445 } 3446 } /* Bank iteration loop. */ 3447 if ((rv < 0) && (rv != SOC_E_FULL)) { 3448 if (NULL == bucket_trace) { 3449 sal_free(trace); 3450 sal_free(mem_banks); 3451 } 3452 return rv; 3453 } 3454 if (!found) { 3455 if (NULL == bucket_trace) { 3456 sal_free(trace); 3457 sal_free(mem_banks); 3458 } 3459 return SOC_E_FULL; 3460 } 3461 rv = soc_mem_generic_insert(unit, mem, copyno, cb, entry, entry, NULL); 3462 if (rv) { 3463 LOG_VERBOSE(BSL_LS_SOC_SOCMEM, 3464 (BSL_META_U(unit, 3465 "Insert entry: %d\n"), rv)); 3466 } 3467 cleanup: 3468 if (NULL == bucket_trace) { 3469 sal_free(trace); 3470 sal_free(mem_banks); 3471 } 3472 return rv; 3473 } 3474 3475 #endif /* BCM_ISM_SUPPORT */ 3476