mmu_config.c (53842B)
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 * CMAC driver 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <sal/core/libc.h> 13 #include <shared/alloc.h> 14 #include <sal/core/spl.h> 15 #include <sal/core/boot.h> 16 #include <shared/bsl.h> 17 #include <soc/drv.h> 18 #include <soc/error.h> 19 #include <soc/ll.h> 20 #include <soc/debug.h> 21 #include <soc/mmu_config.h> 22 23 /* 16 MB Packet Buffer Size */ 24 uint32 soc_mmu_pkt_buf_size_arr[_MMU_PKT_BUF_SIZE_MAX_COUNT][_MMU_MAX_PARAMS] = { 25 /* _TD2_MMU_PKT_BUF_SIZE_9MB */ 26 {9416, /* _TD2_MMU_MAX_PACKET_BYTES */ 27 53248, /* _TD2_MMU_PHYSICAL_CELLS : 13 banks * 4096 cells */ 28 45372, /* _TD2_MMU_TOTAL_CELLS (9Mbytes) */ 29 490}, /* _TD2_MMU_RSVD_CELLS_CFAP */ 30 31 /* _TD2_MMU_PKT_BUF_SIZE_12MB */ 32 {9416, /* _TD2_MMU_MAX_PACKET_BYTES */ 33 65536, /* _TD2_MMU_PHYSICAL_CELLS : 16 banks * 4096 cells */ 34 60495, /* _TD2_MMU_TOTAL_CELLS 60494.76 cells (12Mbytes) */ 35 595}, /* _TD2_MMU_RSVD_CELLS_CFAP */ 36 37 /* _TD2_MMU_PKT_BUF_SIZE_16MB */ 38 {9416, /* _TD2_MMU_MAX_PACKET_BYTES */ 39 86016, /* _TD2_MMU_PHYSICAL_CELLS : 21 banks * 4096 bytes*/ 40 80660, /* _TD2_MMU_TOTAL_CELLS : 16MB */ 41 735} /* _TD2_MMU_RSVD_CELLS_CFAP */ 42 }; 43 44 45 46 #if defined(BCM_TRIUMPH3_SUPPORT) 47 48 char soc_mmu_theshold_type[_MMU_MAX_THRESHOLD_TYPE][SOC_PROPERTY_NAME_MAX] = 49 { 50 "", 51 spn_PKT, 52 spn_EXTMEM 53 }; 54 55 56 STATIC void 57 _soc_mmu_cfg_property_get(int unit, soc_port_t port, const char *obj, 58 int index, const char *attr, int *setting, 59 soc_mmu_type_t threshold_type) 60 { 61 char suffix; 62 char attr1[SOC_PROPERTY_NAME_MAX]; 63 64 if (_MMU_DEFAULT_THRES_TYPE != threshold_type) { 65 sal_snprintf(attr1, SOC_PROPERTY_NAME_MAX, "%s.%s", 66 soc_mmu_theshold_type[threshold_type], attr); 67 } else { 68 sal_snprintf(attr1, SOC_PROPERTY_NAME_MAX, "%s", 69 attr); 70 } 71 72 73 if (port < 0) { 74 *setting = soc_property_obj_attr_get 75 (unit, spn_BUF, obj, index, attr1, 0, &suffix, *setting); 76 } else { 77 *setting = soc_property_port_obj_attr_get 78 (unit, port, spn_BUF, obj, index, attr1, 0, &suffix, *setting); 79 } 80 } 81 82 void 83 _soc_mmu_cfg_property_get_cells(int unit, soc_port_t port, const char *obj, 84 int index, const char *attr, int allow_dynamic, 85 int *setting, int byte_per_cell, 86 soc_mmu_type_t threshold_type) 87 { 88 int val; 89 char suffix; 90 91 char attr1[SOC_PROPERTY_NAME_MAX]; 92 93 if (_MMU_DEFAULT_THRES_TYPE != threshold_type) { 94 sal_snprintf(attr1, SOC_PROPERTY_NAME_MAX, "%s.%s", 95 soc_mmu_theshold_type[threshold_type], attr); 96 } else { 97 sal_snprintf(attr1, SOC_PROPERTY_NAME_MAX, "%s", 98 attr); 99 } 100 101 if (*setting & _MMU_CFG_BUF_DYNAMIC_FLAG) { 102 suffix = '%'; 103 val = *setting & ~_MMU_CFG_BUF_DYNAMIC_FLAG; 104 if (*setting & _MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1) { 105 /* 0:1000 (100%), 1:125 (12.5%), ... 7:875 (87.5%) */ 106 val = (val == 0) ? 1000 : val * 125; 107 } else { 108 /* 0:125 (12.5%), ... 7:1000 (100%) */ 109 val = (val + 1) * 125; 110 } 111 } else { 112 /* scale up by 10 during calculation */ 113 suffix = '\0'; 114 val = *setting * 10; 115 } 116 117 if (port < 0) { 118 val = soc_property_obj_attr_get 119 (unit, spn_BUF, obj, index, attr1, 1, &suffix, val); 120 } else { 121 val = soc_property_port_obj_attr_get 122 (unit, port, spn_BUF, obj, index, attr1, 1, &suffix, val); 123 } 124 125 if (val < 0) { /* treat negative number as zero */ 126 val = 0; 127 } 128 129 if (allow_dynamic && suffix == '%') { 130 if (*setting & _MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1) { 131 /* 0:1000 (100%), 1:125 (12.5%), ... 7:875 (87.5%) */ 132 val = (val > 875) ? 0 : ((val == 0) ? 1 : (val + 125 -1) / 125); 133 val |= _MMU_CFG_BUF_DYNAMIC_MAPPING_TYPE_1; 134 } else { 135 /* 0:125 (12.5%), ... 7:1000 (100%) */ 136 val = val > 1000 ? 7 : (val - 1) / 125; 137 } 138 val |= _MMU_CFG_BUF_DYNAMIC_FLAG; 139 } else { 140 /* scale down by 10 after calculation */ 141 val /= 10; 142 switch (suffix) { 143 case 'B': /* byte */ 144 case 'b': 145 val = _MMU_CFG_MMU_BYTES_TO_CELLS(val, byte_per_cell); 146 break; 147 case 'K': /* kilobyte */ 148 case 'k': 149 val = _MMU_CFG_MMU_BYTES_TO_CELLS(val * 1024, byte_per_cell); 150 break; 151 case 'M': /* megabyte */ 152 case 'm': 153 val = _MMU_CFG_MMU_BYTES_TO_CELLS(val * 1048576, byte_per_cell); 154 break; 155 default: 156 break; 157 } 158 } 159 160 *setting = val; 161 } 162 163 STATIC void 164 _soc_mmu_cfg_property_get_percentage_x100(int unit, soc_port_t port, 165 const char *obj, int index, 166 const char *attr, int *setting) 167 { 168 int val; 169 char suffix; 170 171 if (*setting & _MMU_CFG_BUF_PERCENT_FLAG) { 172 suffix = '%'; 173 val = *setting & ~_MMU_CFG_BUF_PERCENT_FLAG; 174 } else { 175 suffix = '\0'; 176 val = *setting; 177 } 178 179 if (port < 0) { 180 val = soc_property_obj_attr_get 181 (unit, spn_BUF, obj, index, attr, 2, &suffix, val); 182 } else { 183 val = soc_property_port_obj_attr_get 184 (unit, port, spn_BUF, obj, index, attr, 2, &suffix, val); 185 } 186 187 if (suffix == '%') { 188 if (val < 0) { /* treat negative number as zero */ 189 val = 0; 190 } else if (val > 10000) { /* treat number larger than 100% as 100% */ 191 val = 10000; 192 } 193 *setting = val | _MMU_CFG_BUF_PERCENT_FLAG; 194 } else { 195 *setting = val; 196 } 197 } 198 199 STATIC void 200 _soc_mmu_cfg_property_get_scale(int unit, soc_port_t port, 201 const char *obj, int index, 202 const char *attr, int *setting , 203 soc_mmu_type_t threshold_type) 204 { 205 int val, alpha, index_max = 9; 206 char suffix; 207 char attr1[SOC_PROPERTY_NAME_MAX]; 208 209 if (_MMU_DEFAULT_THRES_TYPE != threshold_type) { 210 sal_snprintf(attr1, SOC_PROPERTY_NAME_MAX, "%s.%s", 211 soc_mmu_theshold_type[threshold_type], attr); 212 } else { 213 sal_snprintf(attr1, SOC_PROPERTY_NAME_MAX, "%s", 214 attr); 215 } 216 217 218 alpha = 156250; /* 1/64 = 0.015625, scale up by 10000000 (2**7) */ 219 if (SOC_IS_TRIDENT2X(unit) || SOC_IS_TOMAHAWKX(unit)) { 220 alpha /= 2; /* start from 1/128. */ 221 index_max = 10; 222 } 223 val = *setting < 0 ? -1 : alpha << *setting; 224 225 if (port < 0) { 226 val = soc_property_obj_attr_get 227 (unit, spn_BUF, obj, index, attr1, 7, &suffix, val); 228 } else { 229 val = soc_property_port_obj_attr_get 230 (unit, port, spn_BUF, obj, index, attr1, 7, &suffix, val); 231 } 232 233 if (val < 0) { /* ignore negative number */ 234 *setting = -1; 235 } else { 236 for (*setting = 0; *setting < index_max; (*setting)++) { 237 if (val <= (alpha << *setting)) { 238 break; 239 } 240 } 241 } 242 } 243 244 void 245 _soc_mmu_cfg_buf_read(int unit, _soc_mmu_cfg_buf_t *buf, 246 _soc_mmu_device_info_t *devcfg) 247 { 248 soc_info_t *si; 249 _soc_mmu_cfg_buf_pool_t *buf_pool; 250 _soc_mmu_cfg_buf_port_t *buf_port; 251 _soc_mmu_cfg_buf_port_pool_t *buf_port_pool; 252 _soc_mmu_cfg_buf_prigroup_t *buf_prigroup; 253 _soc_mmu_cfg_buf_queue_t *buf_queue; 254 #if defined(BCM_TOMAHAWK3_SUPPORT) 255 _soc_mmu_cfg_buf_mapping_profile_t *buf_mapprofile; 256 #endif 257 #if defined(BCM_KATANA2_SUPPORT) 258 _soc_mmu_cfg_buf_mcengine_queue_t *buf_rqe_queue; 259 #endif 260 int port, idx, count; 261 _soc_mmu_cfg_buf_qgroup_t *queue_group; 262 char name[80]; 263 int values[64]; 264 265 si = &SOC_INFO(unit); 266 267 _soc_mmu_cfg_property_get_cells 268 (unit, -1, spn_DEVICE, -1, spn_HEADROOM, FALSE, &buf->headroom, 269 devcfg->mmu_cell_size, _MMU_DEFAULT_THRES_TYPE); 270 271 for (idx = 0; idx < _SOC_MMU_CFG_DEV_POOL_NUM(devcfg); idx++) { 272 buf_pool = &buf->pools[idx]; 273 274 _soc_mmu_cfg_property_get_percentage_x100 275 (unit, -1, spn_POOL, idx, spn_SIZE, &buf_pool->size); 276 277 _soc_mmu_cfg_property_get_percentage_x100 278 (unit, -1, spn_POOL, idx, spn_YELLOW_SIZE, &buf_pool->yellow_size); 279 280 _soc_mmu_cfg_property_get_percentage_x100 281 (unit, -1, spn_POOL, idx, spn_RED_SIZE, &buf_pool->red_size); 282 } 283 284 #if defined(BCM_TOMAHAWK3_SUPPORT) 285 for (idx = 0; idx < SOC_MMU_CFG_NUM_PROFILES_MAX; idx++) { 286 buf_mapprofile = &buf->mapprofiles[idx]; 287 288 _soc_mmu_cfg_property_get 289 (unit, -1, spn_MAPPROFILE, idx, spn_PROFILE_VALID, 290 &buf_mapprofile->valid, _MMU_DEFAULT_THRES_TYPE); 291 292 293 /* internal priority to priority group mapping for UC*/ 294 sal_sprintf(name, "%s.%s%d.%s", 295 spn_BUF, spn_MAPPROFILE, idx, spn_INPUT_PRI_TO_PRIORITY_GROUP_UC); 296 (void)soc_property_get_csv(unit, name, 16, 297 buf_mapprofile->inpri_to_prigroup_uc); 298 299 /* internal priority to priority group mapping for MC*/ 300 sal_sprintf(name, "%s.%s%d.%s", 301 spn_BUF, spn_MAPPROFILE, idx, spn_INPUT_PRI_TO_PRIORITY_GROUP_MC); 302 (void)soc_property_get_csv(unit, name, 16, 303 buf_mapprofile->inpri_to_prigroup_mc); 304 305 /* priority group to service pool mapping */ 306 sal_sprintf(name, "%s.%s%d.%s", 307 spn_BUF, spn_MAPPROFILE, idx, spn_PRIORITY_GROUP_TO_SERVICE_POOL); 308 (void)soc_property_get_csv(unit, name, 8, 309 buf_mapprofile->prigroup_to_servicepool); 310 311 /* priority group to headroom pool mapping */ 312 sal_sprintf(name, "%s.%s%d.%s", 313 spn_BUF, spn_MAPPROFILE, idx, spn_PRIORITY_GROUP_TO_HEADROOM_POOL); 314 (void)soc_property_get_csv(unit, name, 8, 315 buf_mapprofile->prigroup_to_headroompool); 316 317 /* pfc class to priority group mapping */ 318 sal_sprintf(name, "%s.%s%d.%s", 319 spn_BUF, spn_MAPPROFILE, idx, spn_PFCCLASS_TO_PRIORITY_GROUP); 320 (void)soc_property_get_csv(unit, name, 8, 321 buf_mapprofile->pfcpri_to_prigroup); 322 } 323 #endif 324 325 for (idx = 0; idx < SOC_MMU_CFG_QGROUP_MAX; idx++) { 326 queue_group = &buf->qgroups[idx]; 327 328 _soc_mmu_cfg_property_get_cells 329 (unit, -1, spn_QGROUP, idx, spn_GUARANTEE, FALSE, 330 &queue_group->guarantee, devcfg->mmu_cell_size, 331 _MMU_DEFAULT_THRES_TYPE); 332 333 #if defined(BCM_TOMAHAWK3_SUPPORT) 334 _soc_mmu_cfg_property_get_cells 335 (unit, -1, spn_QGROUP, idx, spn_GUARANTEE_MC, FALSE, 336 &queue_group->guarantee_mc, devcfg->mmu_cell_size, 337 _MMU_DEFAULT_THRES_TYPE); 338 #endif 339 340 _soc_mmu_cfg_property_get 341 (unit, -1, spn_QGROUP, idx, spn_DISCARD_ENABLE, 342 &queue_group->discard_enable, _MMU_DEFAULT_THRES_TYPE); 343 344 _soc_mmu_cfg_property_get_scale 345 (unit, -1, spn_QGROUP, idx, spn_POOL_SCALE, 346 &queue_group->pool_scale, _MMU_DEFAULT_THRES_TYPE); 347 348 _soc_mmu_cfg_property_get_cells 349 (unit, -1, spn_QGROUP, idx, spn_POOL_LIMIT, FALSE, 350 &queue_group->pool_limit, devcfg->mmu_cell_size, 351 _MMU_DEFAULT_THRES_TYPE); 352 353 _soc_mmu_cfg_property_get_cells 354 (unit, -1, spn_QGROUP, idx, spn_POOL_RESUME, FALSE, 355 &queue_group->pool_resume, devcfg->mmu_cell_size, 356 _MMU_DEFAULT_THRES_TYPE); 357 358 _soc_mmu_cfg_property_get_cells 359 (unit, -1, spn_QGROUP, idx, spn_YELLOW_LIMIT, TRUE, 360 &queue_group->yellow_limit, devcfg->mmu_cell_size, 361 _MMU_DEFAULT_THRES_TYPE); 362 363 _soc_mmu_cfg_property_get_cells 364 (unit, -1, spn_QGROUP, idx, spn_RED_LIMIT, TRUE, 365 &queue_group->red_limit, devcfg->mmu_cell_size, 366 _MMU_DEFAULT_THRES_TYPE); 367 368 _soc_mmu_cfg_property_get_cells 369 (unit, -1, spn_QGROUP, idx, spn_YELLOW_RESUME, FALSE, 370 &queue_group->yellow_resume, devcfg->mmu_cell_size, 371 _MMU_DEFAULT_THRES_TYPE); 372 373 _soc_mmu_cfg_property_get_cells 374 (unit, -1, spn_QGROUP, idx, spn_RED_RESUME, FALSE, 375 &queue_group->red_resume, devcfg->mmu_cell_size, 376 _MMU_DEFAULT_THRES_TYPE); 377 378 } 379 380 PBMP_ALL_ITER(unit, port) { 381 buf_port = &buf->ports[port]; 382 383 #if defined(BCM_TOMAHAWK3_SUPPORT) 384 _soc_mmu_cfg_property_get 385 (unit, -1, spn_PORT, port, spn_INPUT_PRI_TO_PRIORITY_GROUP_PROFILE_IDX, 386 &buf_port->pri_to_prigroup_profile_idx, _MMU_DEFAULT_THRES_TYPE); 387 388 _soc_mmu_cfg_property_get 389 (unit, -1, spn_PORT, port, spn_PRIORITY_GROUP_PROFILE_IDX, 390 &buf_port->prigroup_profile_idx, _MMU_DEFAULT_THRES_TYPE); 391 #endif 392 393 for (idx = 0; idx < _SOC_MMU_CFG_DEV_POOL_NUM(devcfg); idx++) { 394 buf_port_pool = &buf_port->pools[idx]; 395 _soc_mmu_cfg_property_get_cells 396 (unit, port, spn_INGPORTPOOL, idx, spn_GUARANTEE, FALSE, 397 &buf_port_pool->guarantee, devcfg->mmu_cell_size, 398 _MMU_DEFAULT_THRES_TYPE); 399 _soc_mmu_cfg_property_get_cells 400 (unit, port, spn_INGPORTPOOL, idx, spn_POOL_LIMIT, FALSE, 401 &buf_port_pool->pool_limit, devcfg->mmu_cell_size, 402 _MMU_DEFAULT_THRES_TYPE); 403 _soc_mmu_cfg_property_get_cells 404 (unit, port, spn_INGPORTPOOL, idx, spn_POOL_RESUME, FALSE, 405 &buf_port_pool->pool_resume, devcfg->mmu_cell_size, 406 _MMU_DEFAULT_THRES_TYPE); 407 } 408 409 /* priority group */ 410 for (idx = 0; idx < _SOC_MMU_CFG_DEV_PG_NUM(devcfg); idx++) { 411 buf_prigroup = &buf_port->prigroups[idx]; 412 413 _soc_mmu_cfg_property_get_cells 414 (unit, port, spn_PRIGROUP, idx, spn_GUARANTEE, FALSE, 415 &buf_prigroup->guarantee, devcfg->mmu_cell_size, 416 _MMU_DEFAULT_THRES_TYPE); 417 418 _soc_mmu_cfg_property_get_cells 419 (unit, port, spn_PRIGROUP, idx, spn_HEADROOM, FALSE, 420 &buf_prigroup->headroom, devcfg->mmu_cell_size, 421 _MMU_DEFAULT_THRES_TYPE); 422 423 #if defined(BCM_TOMAHAWK3_SUPPORT) 424 _soc_mmu_cfg_property_get 425 (unit, port, spn_PRIGROUP, idx, spn_PRIORITY_GROUP_LOSSLESS, 426 &buf_prigroup->lossless, 427 _MMU_DEFAULT_THRES_TYPE); 428 #endif 429 430 _soc_mmu_cfg_property_get 431 (unit, port, spn_PRIGROUP, idx, spn_USER_DELAY, 432 &buf_prigroup->user_delay, 433 _MMU_DEFAULT_THRES_TYPE); 434 435 _soc_mmu_cfg_property_get 436 (unit, port, spn_PRIGROUP, idx, spn_SWITCH_DELAY, 437 &buf_prigroup->switch_delay, 438 _MMU_DEFAULT_THRES_TYPE); 439 440 _soc_mmu_cfg_property_get 441 (unit, port, spn_PRIGROUP, idx, spn_PKT_SIZE, 442 &buf_prigroup->pkt_size, 1 ); 443 444 _soc_mmu_cfg_property_get 445 (unit, port, spn_PRIGROUP, idx, spn_DEVICE_HEADROOM_ENABLE, 446 &buf_prigroup->device_headroom_enable, 447 _MMU_DEFAULT_THRES_TYPE); 448 449 _soc_mmu_cfg_property_get_scale 450 (unit, port, spn_PRIGROUP, idx, spn_POOL_SCALE, 451 &buf_prigroup->pool_scale , 452 _MMU_DEFAULT_THRES_TYPE); 453 454 _soc_mmu_cfg_property_get_cells 455 (unit, port, spn_PRIGROUP, idx, spn_POOL_LIMIT, FALSE, 456 &buf_prigroup->pool_limit, devcfg->mmu_cell_size, 457 _MMU_DEFAULT_THRES_TYPE); 458 459 _soc_mmu_cfg_property_get_cells 460 (unit, port, spn_PRIGROUP, idx, spn_POOL_RESUME, FALSE, 461 &buf_prigroup->pool_resume, devcfg->mmu_cell_size, 462 _MMU_DEFAULT_THRES_TYPE); 463 464 _soc_mmu_cfg_property_get_cells 465 (unit, port, spn_PRIGROUP, idx, spn_POOL_FLOOR, FALSE, 466 &buf_prigroup->pool_floor, devcfg->mmu_cell_size, 467 _MMU_DEFAULT_THRES_TYPE); 468 469 _soc_mmu_cfg_property_get 470 (unit, port, spn_PRIGROUP, idx, spn_FLOW_CONTROL_ENABLE, 471 &buf_prigroup->flow_control_enable, 472 _MMU_DEFAULT_THRES_TYPE); 473 } 474 475 /* multicast queue */ 476 for (idx = 0; idx < si->port_num_cosq[port]; idx++) { 477 #if defined(BCM_TOMAHAWK3_SUPPORT) 478 /* In Tomahawk3, the per-port queues are organized as unicast 479 queues followed by multicast queues */ 480 if (SOC_IS_TOMAHAWK3(unit)) { 481 buf_queue = &buf_port->queues[si->port_num_uc_cosq[port] + idx]; 482 } else { 483 buf_queue = &buf_port->queues[idx]; 484 } 485 #else 486 buf_queue = &buf_port->queues[idx]; 487 #endif 488 489 _soc_mmu_cfg_property_get_cells 490 (unit, port, spn_MQUEUE, idx, spn_GUARANTEE, FALSE, 491 &buf_queue->guarantee, devcfg->mmu_cell_size, 492 _MMU_DEFAULT_THRES_TYPE); 493 494 _soc_mmu_cfg_property_get 495 (unit, port, spn_MQUEUE, idx, spn_DISCARD_ENABLE, 496 &buf_queue->discard_enable, _MMU_DEFAULT_THRES_TYPE); 497 498 _soc_mmu_cfg_property_get_scale 499 (unit, port, spn_MQUEUE, idx, spn_POOL_SCALE, 500 &buf_queue->pool_scale, 501 _MMU_DEFAULT_THRES_TYPE); 502 503 _soc_mmu_cfg_property_get_cells 504 (unit, port, spn_MQUEUE, idx, spn_POOL_LIMIT, FALSE, 505 &buf_queue->pool_limit, devcfg->mmu_cell_size, 506 _MMU_DEFAULT_THRES_TYPE); 507 508 _soc_mmu_cfg_property_get_cells 509 (unit, port, spn_MQUEUE, idx, spn_POOL_RESUME, FALSE, 510 &buf_queue->pool_resume, devcfg->mmu_cell_size, 511 _MMU_DEFAULT_THRES_TYPE); 512 513 _soc_mmu_cfg_property_get 514 (unit, port, spn_MQUEUE, idx, spn_COLOR_DISCARD_ENABLE, 515 &buf_queue->color_discard_enable, 516 _MMU_DEFAULT_THRES_TYPE); 517 518 _soc_mmu_cfg_property_get_cells 519 (unit, port, spn_MQUEUE, idx, spn_RED_LIMIT, TRUE, 520 &buf_queue->red_limit, devcfg->mmu_cell_size, 521 _MMU_DEFAULT_THRES_TYPE); 522 523 _soc_mmu_cfg_property_get_cells 524 (unit, port, spn_MQUEUE, idx, spn_YELLOW_LIMIT, TRUE, 525 &buf_queue->yellow_limit, devcfg->mmu_cell_size, 526 _MMU_DEFAULT_THRES_TYPE); 527 528 529 _soc_mmu_cfg_property_get_cells 530 (unit, port, spn_MQUEUE, idx, spn_RED_RESUME, TRUE, 531 &buf_queue->red_resume, devcfg->mmu_cell_size, 532 _MMU_DEFAULT_THRES_TYPE); 533 534 _soc_mmu_cfg_property_get_cells 535 (unit, port, spn_MQUEUE, idx, spn_YELLOW_RESUME, TRUE, 536 &buf_queue->yellow_resume, devcfg->mmu_cell_size, 537 _MMU_DEFAULT_THRES_TYPE); 538 539 540 _soc_mmu_cfg_property_get_cells 541 (unit, port, spn_MQUEUE, idx, spn_POOL, FALSE, 542 &buf_queue->pool_idx, devcfg->mmu_cell_size, 543 _MMU_DEFAULT_THRES_TYPE); 544 } 545 546 /* unicast queue */ 547 for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) { 548 #if defined(BCM_TOMAHAWK3_SUPPORT) 549 /* In Tomahawk3, the per-port queues are organized as unicast 550 queues followed by multicast queues */ 551 if (SOC_IS_TOMAHAWK3(unit)) { 552 buf_queue = &buf_port->queues[idx]; 553 } else { 554 buf_queue = &buf_port->queues[si->port_num_cosq[port] + idx]; 555 } 556 #else 557 buf_queue = &buf_port->queues[si->port_num_cosq[port] + idx]; 558 #endif 559 560 _soc_mmu_cfg_property_get_cells 561 (unit, port, spn_QUEUE, idx, spn_GUARANTEE, FALSE, 562 &buf_queue->guarantee, devcfg->mmu_cell_size, 563 _MMU_DEFAULT_THRES_TYPE); 564 565 if (SOC_IS_KATANA2(unit)) { 566 _soc_mmu_cfg_property_get_cells 567 (unit, port, spn_QUEUE, idx, spn_GUARANTEE, FALSE, 568 &buf_queue->pkt_guarantee, devcfg->mmu_cell_size, 569 _MMU_QENTRY_BASED); 570 } 571 572 573 _soc_mmu_cfg_property_get 574 (unit, port, spn_QUEUE, idx, spn_DISCARD_ENABLE, 575 &buf_queue->discard_enable, _MMU_DEFAULT_THRES_TYPE); 576 577 _soc_mmu_cfg_property_get_cells 578 (unit, port, spn_QUEUE, idx, spn_POOL, FALSE, 579 &buf_queue->pool_idx, devcfg->mmu_cell_size, 580 _MMU_DEFAULT_THRES_TYPE); 581 582 _soc_mmu_cfg_property_get_scale 583 (unit, port, spn_QUEUE, idx, spn_POOL_SCALE, 584 &buf_queue->pool_scale, 585 _MMU_DEFAULT_THRES_TYPE); 586 587 if (SOC_IS_KATANA2(unit)) { 588 _soc_mmu_cfg_property_get_scale 589 (unit, port, spn_QUEUE, idx, spn_POOL_SCALE, 590 &buf_queue->pkt_pool_scale, 591 _MMU_QENTRY_BASED); 592 } 593 594 595 596 _soc_mmu_cfg_property_get_cells 597 (unit, port, spn_QUEUE, idx, spn_POOL_LIMIT, FALSE, 598 &buf_queue->pool_limit, devcfg->mmu_cell_size, 599 _MMU_DEFAULT_THRES_TYPE); 600 601 _soc_mmu_cfg_property_get_cells 602 (unit, port, spn_QUEUE, idx, spn_POOL_RESUME, FALSE, 603 &buf_queue->pool_resume, devcfg->mmu_cell_size, 604 _MMU_DEFAULT_THRES_TYPE); 605 606 _soc_mmu_cfg_property_get 607 (unit, port, spn_QUEUE, idx, spn_COLOR_DISCARD_ENABLE, 608 &buf_queue->color_discard_enable, 609 _MMU_DEFAULT_THRES_TYPE); 610 611 _soc_mmu_cfg_property_get_cells 612 (unit, port, spn_QUEUE, idx, spn_YELLOW_LIMIT, TRUE, 613 &buf_queue->yellow_limit, devcfg->mmu_cell_size, 614 _MMU_DEFAULT_THRES_TYPE); 615 616 _soc_mmu_cfg_property_get_cells 617 (unit, port, spn_QUEUE, idx, spn_RED_LIMIT, TRUE, 618 &buf_queue->red_limit, devcfg->mmu_cell_size, 619 _MMU_DEFAULT_THRES_TYPE); 620 621 _soc_mmu_cfg_property_get_cells 622 (unit, port, spn_QUEUE, idx, spn_YELLOW_RESUME, FALSE, 623 &buf_queue->yellow_resume, devcfg->mmu_cell_size, 624 _MMU_DEFAULT_THRES_TYPE); 625 626 _soc_mmu_cfg_property_get_cells 627 (unit, port, spn_QUEUE, idx, spn_RED_RESUME, FALSE, 628 &buf_queue->red_resume, devcfg->mmu_cell_size, 629 _MMU_DEFAULT_THRES_TYPE); 630 631 _soc_mmu_cfg_property_get 632 (unit, port, spn_QUEUE, idx, spn_QGROUP_ID, 633 &buf_queue->qgroup_id, 634 _MMU_DEFAULT_THRES_TYPE); 635 636 _soc_mmu_cfg_property_get_cells 637 (unit, port, spn_QUEUE, idx, spn_QGROUP_GUARANTEE_ENABLE, FALSE, 638 &buf_queue->qgroup_min_enable, devcfg->mmu_cell_size, 639 _MMU_DEFAULT_THRES_TYPE); 640 } 641 642 /* internal priority to priority group mapping */ 643 sal_sprintf(name, "%s.%s.%s.%s", 644 spn_BUF, spn_MAP, spn_PRI, spn_PRIGROUP); 645 (void)soc_property_port_get_csv(unit, port, name, 16, 646 buf_port->pri_to_prigroup); 647 648 /* priority group to pool mapping */ 649 for (idx = 0; idx < _SOC_MMU_CFG_DEV_PG_NUM(devcfg); idx++) { 650 values[idx] = buf_port->prigroups[idx].pool_idx; 651 } 652 653 sal_sprintf(name, "%s.%s.%s.%s", 654 spn_BUF, spn_MAP, spn_PRIGROUP, spn_POOL); 655 count = soc_property_port_get_csv(unit, port, name, 656 _SOC_MMU_CFG_DEV_PG_NUM(devcfg), values); 657 for (idx = 0; idx < count; idx++) { 658 buf_port->prigroups[idx].pool_idx = values[idx]; 659 } 660 } 661 662 /* virtual queue profiles */ 663 for (idx = 0; idx < SOC_MMU_CFG_EQUEUE_MAX; idx++) { 664 buf_queue = &buf->equeues[idx]; 665 666 _soc_mmu_cfg_property_get 667 (unit, -1, spn_EQUEUE, idx, spn_NUMQ, &buf_queue->numq, 668 _MMU_DEFAULT_THRES_TYPE); 669 670 _soc_mmu_cfg_property_get_cells 671 (unit, -1, spn_EQUEUE, idx, spn_GUARANTEE, FALSE, 672 &buf_queue->guarantee, devcfg->mmu_cell_size, 673 _MMU_DEFAULT_THRES_TYPE); 674 675 _soc_mmu_cfg_property_get 676 (unit, -1, spn_EQUEUE, idx, spn_DISCARD_ENABLE, 677 &buf_queue->discard_enable, 678 _MMU_DEFAULT_THRES_TYPE); 679 680 _soc_mmu_cfg_property_get_cells 681 (unit, -1, spn_EQUEUE, idx, spn_POOL, FALSE, 682 &buf_queue->pool_idx, devcfg->mmu_cell_size, 683 _MMU_DEFAULT_THRES_TYPE); 684 685 _soc_mmu_cfg_property_get_scale 686 (unit, -1, spn_EQUEUE, idx, spn_POOL_SCALE, 687 &buf_queue->pool_scale, 688 _MMU_DEFAULT_THRES_TYPE); 689 690 _soc_mmu_cfg_property_get_cells 691 (unit, -1, spn_EQUEUE, idx, spn_POOL_LIMIT, FALSE, 692 &buf_queue->pool_limit, devcfg->mmu_cell_size, 693 _MMU_DEFAULT_THRES_TYPE); 694 695 _soc_mmu_cfg_property_get_cells 696 (unit, -1, spn_EQUEUE, idx, spn_POOL_RESUME, FALSE, 697 &buf_queue->pool_resume, devcfg->mmu_cell_size, 698 _MMU_DEFAULT_THRES_TYPE); 699 700 _soc_mmu_cfg_property_get 701 (unit, -1, spn_EQUEUE, idx, spn_COLOR_DISCARD_ENABLE, 702 &buf_queue->color_discard_enable, 703 _MMU_DEFAULT_THRES_TYPE); 704 705 _soc_mmu_cfg_property_get_cells 706 (unit, -1, spn_EQUEUE, idx, spn_YELLOW_LIMIT, TRUE, 707 &buf_queue->yellow_limit, devcfg->mmu_cell_size, 708 _MMU_DEFAULT_THRES_TYPE); 709 710 _soc_mmu_cfg_property_get_cells 711 (unit, -1, spn_EQUEUE, idx, spn_RED_LIMIT, TRUE, 712 &buf_queue->red_limit, devcfg->mmu_cell_size, 713 _MMU_DEFAULT_THRES_TYPE); 714 715 _soc_mmu_cfg_property_get_cells 716 (unit, -1, spn_EQUEUE, idx, spn_YELLOW_RESUME, FALSE, 717 &buf_queue->yellow_resume, devcfg->mmu_cell_size, 718 _MMU_DEFAULT_THRES_TYPE); 719 720 _soc_mmu_cfg_property_get_cells 721 (unit, -1, spn_EQUEUE, idx, spn_RED_RESUME, FALSE, 722 &buf_queue->red_resume, devcfg->mmu_cell_size, 723 _MMU_DEFAULT_THRES_TYPE); 724 725 _soc_mmu_cfg_property_get 726 (unit, -1, spn_EQUEUE, idx, spn_QGROUP_ID, 727 &buf_queue->qgroup_id, 728 _MMU_DEFAULT_THRES_TYPE); 729 730 _soc_mmu_cfg_property_get_cells 731 (unit, -1, spn_EQUEUE, idx, spn_QGROUP_GUARANTEE_ENABLE, FALSE, 732 &buf_queue->qgroup_min_enable, devcfg->mmu_cell_size, 733 _MMU_DEFAULT_THRES_TYPE); 734 } 735 736 #if defined(BCM_KATANA2_SUPPORT) 737 if (SOC_IS_KATANA2(unit)) { 738 /* RQE queue settings */ 739 for (idx = 0; idx < SOC_MMU_CFG_RQE_QUEUE_MAX; idx++) { 740 buf_rqe_queue = &buf->rqe_queues[idx]; 741 742 _soc_mmu_cfg_property_get_cells 743 (unit, -1, spn_RQEQUEUE, idx, spn_GUARANTEE, FALSE, 744 &buf_rqe_queue->guarantee, devcfg->mmu_cell_size, 745 _MMU_DEFAULT_THRES_TYPE); 746 747 _soc_mmu_cfg_property_get_scale 748 (unit, -1, spn_RQEQUEUE, idx, spn_POOL_SCALE, 749 &buf_rqe_queue->pool_scale, 750 _MMU_DEFAULT_THRES_TYPE); 751 752 _soc_mmu_cfg_property_get_cells 753 (unit, -1, spn_RQEQUEUE, idx, spn_GUARANTEE, FALSE, 754 &buf_rqe_queue->ext_guarantee, devcfg->mmu_cell_size, 755 _MMU_EXTMEM_BASED); 756 757 _soc_mmu_cfg_property_get_scale 758 (unit, -1, spn_RQEQUEUE, idx, spn_POOL_SCALE, 759 &buf_rqe_queue->ext_pool_scale, 760 _MMU_EXTMEM_BASED); 761 _soc_mmu_cfg_property_get_cells 762 (unit, -1, spn_RQEQUEUE, idx, spn_GUARANTEE, FALSE, 763 &buf_rqe_queue->pkt_guarantee, devcfg->mmu_cell_size, 764 _MMU_QENTRY_BASED); 765 766 _soc_mmu_cfg_property_get_scale 767 (unit, -1, spn_RQEQUEUE, idx, spn_POOL_SCALE, 768 &buf_rqe_queue->pkt_pool_scale, 769 _MMU_QENTRY_BASED); 770 771 772 } 773 } 774 #endif 775 } 776 777 STATIC int 778 _soc_mmu_cfg_cross_point_buf_calculate(int unit, _soc_mmu_cfg_buf_t *buf, 779 _soc_mmu_device_info_t *devcfg) 780 { 781 soc_info_t *si; 782 _soc_mmu_cfg_buf_pool_t *buf_pool; 783 _soc_mmu_cfg_buf_queue_t *buf_queue; 784 _soc_mmu_cfg_buf_port_t *buf_port; 785 _soc_mmu_cfg_buf_qgroup_t *queue_group; 786 _soc_mmu_cfg_buf_prigroup_t *buf_prigroup; 787 _soc_mmu_cfg_buf_port_pool_t *buf_port_pool; 788 _soc_mmu_cfg_buf_mcengine_queue_t *buf_rqe_queue; 789 int port, idx; 790 int pool, qgidx, total_usable_buffer; 791 uint8 *qgpid; 792 int xpe_map, xpe, pipe; 793 int headroom_xpe[SOC_MMU_CFG_XPE_MAX][SOC_MMU_CFG_SERVICE_POOL_MAX]; 794 int pg_min_xpe[SOC_MMU_CFG_XPE_MAX][SOC_MMU_CFG_SERVICE_POOL_MAX]; 795 int port_min_xpe[SOC_MMU_CFG_XPE_MAX][SOC_MMU_CFG_SERVICE_POOL_MAX]; 796 int queue_min_xpe[SOC_MMU_CFG_XPE_MAX][SOC_MMU_CFG_SERVICE_POOL_MAX]; 797 int mcq_entry_reserved_xpe[SOC_MMU_CFG_XPE_MAX][SOC_MMU_CFG_SERVICE_POOL_MAX]; 798 int qgpid_size = SOC_MMU_CFG_QGROUP_MAX; 799 800 si = &SOC_INFO(unit); 801 802 for (idx = 0; idx < SOC_MMU_CFG_SERVICE_POOL_MAX; idx++) { 803 for (xpe = 0; xpe < si->num_xpe; xpe ++) { 804 queue_min_xpe[xpe][idx] = 0; 805 pg_min_xpe[xpe][idx] = 0; 806 port_min_xpe[xpe][idx] = 0; 807 headroom_xpe[xpe][idx] = 0; 808 mcq_entry_reserved_xpe[xpe][idx] = 0; 809 } 810 } 811 812 total_usable_buffer = _SOC_MMU_CFG_MMU_TOTAL_CELLS(devcfg); 813 814 for (idx = 0; idx < _SOC_MMU_CFG_DEV_POOL_NUM(devcfg); idx++) { 815 for (xpe = 0; xpe < si->num_xpe; xpe ++) { 816 buf_pool = &buf->pools_xpe[xpe][idx]; 817 if ((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) { 818 continue; 819 } 820 821 if (buf_pool->size & _MMU_CFG_BUF_PERCENT_FLAG) { 822 buf_pool->total = ((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) * 823 total_usable_buffer) / 10000; 824 if (devcfg->flags & SOC_MMU_CFG_F_EGR_MCQ_ENTRY) { 825 buf_pool->total_mcq_entry = 826 ((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) * 827 devcfg->total_mcq_entry) / 10000; 828 } 829 } 830 } 831 } 832 833 PBMP_ALL_ITER(unit, port) { 834 buf_port = &buf->ports[port]; 835 pipe = si->port_pipe[port]; 836 837 xpe_map = ((pipe >= 0) && (pipe < si->num_pipe)) ? si->ipipe_xpe_map[pipe] : 0x0; 838 /* pg headroom and pg min */ 839 for (idx = 0; idx < _SOC_MMU_CFG_DEV_PG_NUM(devcfg); idx++) { 840 buf_prigroup = &buf_port->prigroups[idx]; 841 for (xpe = 0; xpe < si->num_xpe; xpe ++) { 842 if (xpe_map & (1 << xpe)) { 843 headroom_xpe[xpe][buf_prigroup->pool_idx] += buf_prigroup->headroom; 844 pg_min_xpe[xpe][buf_prigroup->pool_idx] += buf_prigroup->guarantee; 845 } 846 } 847 } 848 849 xpe_map = ((pipe >= 0) && (pipe < si->num_pipe)) ? si->epipe_xpe_map[pipe] : 0x0; 850 /* port min */ 851 for (idx = 0; idx < _SOC_MMU_CFG_DEV_POOL_NUM(devcfg); idx++) { 852 buf_port_pool = &buf_port->pools[idx]; 853 for (xpe = 0; xpe < si->num_xpe; xpe ++) { 854 if (xpe_map & (1 << xpe)) { 855 port_min_xpe[xpe][idx] += buf_port_pool->guarantee; 856 } 857 } 858 } 859 860 /* queue min */ 861 for (idx = 0; idx < si->port_num_cosq[port]; idx++) { 862 buf_queue = &buf_port->queues[idx]; 863 for (xpe = 0; xpe < si->num_xpe; xpe ++) { 864 if (xpe_map & (1 << xpe)) { 865 if ((buf_queue->qgroup_id == -1) || 866 (buf_queue->qgroup_min_enable == 0)) { 867 queue_min_xpe[xpe][buf_queue->pool_idx] += buf_queue->guarantee; 868 } 869 870 mcq_entry_reserved_xpe[xpe][buf_queue->pool_idx] += 871 (buf_queue->mcq_entry_guarantee + buf_queue->mcq_entry_reserved); 872 } 873 } 874 } 875 876 for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) { 877 buf_queue = &buf_port->queues[si->port_num_cosq[port] + idx]; 878 for (xpe = 0; xpe < si->num_xpe; xpe ++) { 879 if (xpe_map & (1 << xpe)) { 880 if ((buf_queue->qgroup_id == -1) || 881 (buf_queue->qgroup_min_enable == 0)) { 882 queue_min_xpe[xpe][buf_queue->pool_idx] += buf_queue->guarantee; 883 } 884 } 885 } 886 } 887 } 888 889 if (devcfg->flags & SOC_MMU_CFG_F_RQE) { 890 for (idx = 0; idx < 11; idx++) { 891 buf_rqe_queue = &buf->rqe_queues[idx]; 892 for (xpe = 0; xpe < si->num_xpe; xpe ++) { 893 queue_min_xpe[xpe][buf_rqe_queue->pool_idx] += buf_rqe_queue->guarantee; 894 } 895 } 896 } 897 898 if (SOC_IS_TD2P_TT2P(unit)) { 899 qgpid_size = SOC_MMU_CFG_QGROUP_MAX * si->num_pipe; 900 } 901 qgpid = sal_alloc(sizeof(uint8) * qgpid_size, "queue2grp"); 902 if (!qgpid) { 903 return SOC_E_MEMORY; 904 } 905 906 for (idx = 0; idx < SOC_MMU_CFG_QGROUP_MAX; idx++) { 907 qgpid[idx] = 0; 908 } 909 910 /* Check all the queues belonging to queue group use same service pool. */ 911 pool = -1; 912 913 PBMP_ALL_ITER(unit, port) { 914 pipe = si->port_pipe[port]; 915 xpe_map = ((pipe >= 0) && (pipe < si->num_pipe)) ? si->epipe_xpe_map[pipe] : 0x0; 916 buf_port = &buf->ports[port]; 917 918 for (idx = 0; idx < si->port_num_cosq[port]; idx++) { 919 buf_queue = &buf_port->queues[idx]; 920 921 if (buf_queue->qgroup_id == -1) { 922 continue; 923 } 924 925 qgidx = buf_queue->qgroup_id; 926 /* deduct qgroup guarantee if not done so far */ 927 if (qgpid[qgidx] == 0) { 928 queue_group = &buf->qgroups[qgidx]; 929 for (xpe = 0; xpe < si->num_xpe; xpe ++) { 930 if (xpe_map & (1 << xpe)) { 931 queue_min_xpe[xpe][buf_queue->pool_idx] += queue_group->guarantee; 932 } 933 } 934 } 935 qgpid[qgidx] |= 1 << buf_queue->pool_idx; 936 } 937 938 for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) { 939 buf_queue = &buf_port->queues[si->port_num_cosq[port] + idx]; 940 941 if (buf_queue->qgroup_id == -1) { 942 continue; 943 } 944 qgidx = buf_queue->qgroup_id; 945 946 /* On TD2/TD2+ QGrp is per pipe, port in different pipe may have same QGrp id. 947 * Thus add pipe offset here. 948 */ 949 if (SOC_IS_TD2P_TT2P(unit)) { 950 qgidx = qgidx + (SOC_MMU_CFG_QGROUP_MAX * pipe); 951 } 952 if (qgpid[qgidx] == 0) { 953 queue_group = &buf->qgroups[qgidx]; 954 for (xpe = 0; xpe < si->num_xpe; xpe ++) { 955 if (xpe_map & (1 << xpe)) { 956 queue_min_xpe[xpe][buf_queue->pool_idx] += queue_group->guarantee; 957 } 958 } 959 } 960 qgpid[qgidx] |= 1 << buf_queue->pool_idx; 961 } 962 } 963 964 for (idx = 0; idx < SOC_MMU_CFG_EQUEUE_MAX; idx++) { 965 buf_queue = &buf->equeues[idx]; 966 if (buf_queue->numq <= 0) { 967 continue; 968 } 969 970 pool = buf_queue->pool_idx; 971 if (buf_queue->qgroup_id == -1) { 972 for (xpe = 0; xpe < si->num_xpe; xpe ++) { 973 queue_min_xpe[xpe][pool] += buf_queue->guarantee * buf_queue->numq; 974 } 975 } else { 976 qgidx = buf_queue->qgroup_id; 977 if (qgpid[qgidx] == 0) { 978 queue_group = &buf->qgroups[qgidx]; 979 for (xpe = 0; xpe < si->num_xpe; xpe ++) { 980 queue_min_xpe[xpe][buf_queue->pool_idx] += queue_group->guarantee; 981 } 982 } 983 qgpid[qgidx] |= 1 << buf_queue->pool_idx; 984 } 985 } 986 987 for (idx = 0; idx < SOC_MMU_CFG_QGROUP_MAX; idx++) { 988 if (qgpid[idx] & (qgpid[idx] - 1)) { 989 LOG_CLI((BSL_META_U(unit, 990 "Queue belonging to same group use different Pools !!"))); 991 sal_free(qgpid); 992 return SOC_E_PARAM; 993 } 994 } 995 996 sal_free(qgpid); 997 998 for (idx = 0; idx < _SOC_MMU_CFG_DEV_POOL_NUM(devcfg); idx++) { 999 for (xpe = 0; xpe < si->num_xpe; xpe ++) { 1000 buf_pool = &buf->pools_xpe[xpe][idx]; 1001 buf_pool->queue_guarantee = queue_min_xpe[xpe][idx]; 1002 buf_pool->prigroup_headroom = headroom_xpe[xpe][idx]; 1003 buf_pool->prigroup_guarantee = pg_min_xpe[xpe][idx]; 1004 buf_pool->port_guarantee = port_min_xpe[xpe][idx]; 1005 buf_pool->mcq_entry_reserved = mcq_entry_reserved_xpe[xpe][idx]; 1006 } 1007 } 1008 1009 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 1010 LOG_CLI((BSL_META_U(unit, 1011 "MMU buffer usage:\n"))); 1012 LOG_CLI((BSL_META_U(unit, 1013 " Global headroom: %d\n"), buf->headroom)); 1014 for (idx = 0; idx < _SOC_MMU_CFG_DEV_POOL_NUM(devcfg); idx++) { 1015 for (xpe = 0; xpe < si->num_xpe; xpe ++) { 1016 buf_pool = &buf->pools_xpe[xpe][idx]; 1017 if ((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) { 1018 continue; 1019 } 1020 LOG_CLI((BSL_META_U(unit, 1021 " Xpe %d Pool %d total prigroup guarantee: %d\n"), 1022 xpe, idx, buf_pool->prigroup_guarantee)); 1023 LOG_CLI((BSL_META_U(unit, 1024 " Xpe %d Pool %d total prigroup headroom: %d\n"), 1025 xpe, idx, buf_pool->prigroup_headroom)); 1026 LOG_CLI((BSL_META_U(unit, 1027 " Xpe %d Pool %d total queue guarantee: %d\n"), 1028 xpe, idx, buf_pool->queue_guarantee)); 1029 LOG_CLI((BSL_META_U(unit, 1030 " Xpe %d Pool %d total mcq entry reserved: %d\n"), 1031 xpe, idx, buf_pool->mcq_entry_reserved)); 1032 } 1033 } 1034 } 1035 1036 return SOC_E_NONE; 1037 } 1038 1039 int 1040 _soc_mmu_cfg_buf_calculate(int unit, _soc_mmu_cfg_buf_t *buf, 1041 _soc_mmu_device_info_t *devcfg) 1042 { 1043 soc_info_t *si; 1044 _soc_mmu_cfg_buf_pool_t *buf_pool; 1045 _soc_mmu_cfg_buf_queue_t *buf_queue; 1046 _soc_mmu_cfg_buf_port_t *buf_port; 1047 _soc_mmu_cfg_buf_qgroup_t *queue_group; 1048 _soc_mmu_cfg_buf_prigroup_t *buf_prigroup; 1049 _soc_mmu_cfg_buf_port_pool_t *buf_port_pool; 1050 _soc_mmu_cfg_buf_mcengine_queue_t *buf_rqe_queue; 1051 int port, idx, headroom[SOC_MMU_CFG_SERVICE_POOL_MAX]; 1052 int min_guarentees[SOC_MMU_CFG_SERVICE_POOL_MAX]; 1053 int queue_min[SOC_MMU_CFG_SERVICE_POOL_MAX]; 1054 int pool, qgidx, total_usable_buffer; 1055 uint8 *qgpid; 1056 int mcq_entry_reserved[SOC_MMU_CFG_SERVICE_POOL_MAX]; 1057 1058 for (idx = 0; idx < SOC_MMU_CFG_SERVICE_POOL_MAX; idx++) { 1059 queue_min[idx] = 0; 1060 min_guarentees[idx] = 0; 1061 headroom[idx] = 0; 1062 mcq_entry_reserved[idx] = 0; 1063 } 1064 1065 si = &SOC_INFO(unit); 1066 1067 total_usable_buffer = _SOC_MMU_CFG_MMU_TOTAL_CELLS(devcfg); 1068 1069 for (idx = 0; idx < _SOC_MMU_CFG_DEV_POOL_NUM(devcfg); idx++) { 1070 buf_pool = &buf->pools[idx]; 1071 if ((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) { 1072 continue; 1073 } 1074 1075 if (buf_pool->size & _MMU_CFG_BUF_PERCENT_FLAG) { 1076 buf_pool->total = ((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) * 1077 total_usable_buffer) / 10000; 1078 if (devcfg->flags & SOC_MMU_CFG_F_EGR_MCQ_ENTRY) { 1079 buf_pool->total_mcq_entry = 1080 ((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) * 1081 devcfg->total_mcq_entry) / 10000; 1082 } 1083 } else { 1084 buf_pool->total = buf_pool->size ; 1085 } 1086 } 1087 1088 PBMP_ALL_ITER(unit, port) { 1089 buf_port = &buf->ports[port]; 1090 for (idx = 0; idx < _SOC_MMU_CFG_DEV_PG_NUM(devcfg); idx++) { 1091 buf_prigroup = &buf_port->prigroups[idx]; 1092 if (buf_prigroup->user_delay != -1 && 1093 buf_prigroup->switch_delay != -1) { 1094 /* 1095 * number of max leftever cells = 1096 * port speed (megabits per sec) * 10**6 (megabits to bit) * 1097 * delay (nsec) / 10**9 (nsecs to second) / 1098 * 8 (bits per byte) / 1099 * (IPG (12 bytes) + preamble (8 bytes) + 1100 * worse case packet size (145 bytes)) * 1101 * worse case packet size (2 cells) 1102 * heandroom = 1103 * mtu (cells) + number of leftover cells 1104 */ 1105 buf_prigroup->headroom = buf_prigroup->pkt_size + 1106 si->port_speed_max[port] * 1107 (buf_prigroup->user_delay + buf_prigroup->switch_delay) * 1108 2 / (8 * (12 + 8 + 145) * 1000); 1109 } 1110 } 1111 } 1112 1113 PBMP_ALL_ITER(unit, port) { 1114 buf_port = &buf->ports[port]; 1115 1116 for (idx = 0; idx < _SOC_MMU_CFG_DEV_PG_NUM(devcfg); idx++) { 1117 buf_prigroup = &buf_port->prigroups[idx]; 1118 headroom[buf_prigroup->pool_idx] += buf_prigroup->headroom; 1119 min_guarentees[buf_prigroup->pool_idx] += buf_prigroup->guarantee; 1120 } 1121 1122 /* port mins */ 1123 for (idx = 0; idx < _SOC_MMU_CFG_DEV_POOL_NUM(devcfg); idx++) { 1124 buf_port_pool = &buf_port->pools[idx]; 1125 min_guarentees[idx] += buf_port_pool->guarantee; 1126 } 1127 1128 for (idx = 0; idx < si->port_num_cosq[port]; idx++) { 1129 buf_queue = &buf_port->queues[idx]; 1130 if ((buf_queue->qgroup_id == -1) || 1131 (buf_queue->qgroup_min_enable == 0)) { 1132 queue_min[buf_queue->pool_idx] += buf_queue->guarantee; 1133 } 1134 1135 mcq_entry_reserved[buf_queue->pool_idx] += 1136 (buf_queue->mcq_entry_guarantee + buf_queue->mcq_entry_reserved); 1137 } 1138 1139 for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) { 1140 buf_queue = &buf_port->queues[si->port_num_cosq[port] + idx]; 1141 if ((buf_queue->qgroup_id == -1) || 1142 (buf_queue->qgroup_min_enable == 0)) { 1143 queue_min[buf_queue->pool_idx] += buf_queue->guarantee; 1144 } 1145 } 1146 } 1147 1148 if (devcfg->flags & SOC_MMU_CFG_F_RQE) { 1149 for (idx = 0; idx < 11; idx++) { 1150 buf_rqe_queue = &buf->rqe_queues[idx]; 1151 queue_min[buf_rqe_queue->pool_idx] += buf_rqe_queue->guarantee; 1152 } 1153 } 1154 1155 qgpid = sal_alloc(sizeof(uint8)*SOC_MMU_CFG_QGROUP_MAX, "queue2grp"); 1156 if (!qgpid) { 1157 return SOC_E_MEMORY; 1158 } 1159 1160 1161 /* Check all the queues belonging to queue group use same service pool. */ 1162 pool = -1; 1163 1164 PBMP_ALL_ITER(unit, port) { 1165 buf_port = &buf->ports[port]; 1166 1167 /* Give each port, a chance to add, 1168 * it's qgroup reservation to the total */ 1169 for (idx = 0; idx < SOC_MMU_CFG_QGROUP_MAX; idx++) { 1170 qgpid[idx] = 0; 1171 } 1172 for (idx = 0; idx < si->port_num_cosq[port]; idx++) { 1173 buf_queue = &buf_port->queues[idx]; 1174 1175 if (buf_queue->qgroup_id == -1) { 1176 continue; 1177 } 1178 1179 qgidx = buf_queue->qgroup_id; 1180 /* deduct qgroup guarantee if not done so far */ 1181 if (qgpid[qgidx] == 0) { 1182 queue_group = &buf->qgroups[qgidx]; 1183 queue_min[buf_queue->pool_idx] += queue_group->guarantee; 1184 } 1185 qgpid[qgidx] |= 1 << buf_queue->pool_idx; 1186 } 1187 1188 for (idx = 0; idx < si->port_num_uc_cosq[port]; idx++) { 1189 buf_queue = &buf_port->queues[si->port_num_cosq[port] + idx]; 1190 1191 if (buf_queue->qgroup_id == -1) { 1192 continue; 1193 } 1194 qgidx = buf_queue->qgroup_id; 1195 if (qgpid[qgidx] == 0) { 1196 queue_group = &buf->qgroups[qgidx]; 1197 queue_min[buf_queue->pool_idx] += queue_group->guarantee; 1198 } 1199 qgpid[qgidx] |= 1 << buf_queue->pool_idx; 1200 } 1201 } 1202 1203 for (idx = 0; idx < SOC_MMU_CFG_EQUEUE_MAX; idx++) { 1204 buf_queue = &buf->equeues[idx]; 1205 if (buf_queue->numq <= 0) { 1206 continue; 1207 } 1208 1209 pool = buf_queue->pool_idx; 1210 if (buf_queue->qgroup_id == -1) { 1211 queue_min[pool] += buf_queue->guarantee * buf_queue->numq; 1212 } else { 1213 qgidx = buf_queue->qgroup_id; 1214 if (qgpid[qgidx] == 0) { 1215 queue_group = &buf->qgroups[qgidx]; 1216 queue_min[buf_queue->pool_idx] += queue_group->guarantee; 1217 } 1218 qgpid[qgidx] |= 1 << buf_queue->pool_idx; 1219 } 1220 } 1221 1222 for (idx = 0; idx < SOC_MMU_CFG_QGROUP_MAX; idx++) { 1223 if (qgpid[idx] & (qgpid[idx] - 1)) { 1224 LOG_CLI((BSL_META_U(unit, 1225 "Queue belonging to same group use different Pools !!"))); 1226 sal_free(qgpid); 1227 return SOC_E_PARAM; 1228 } 1229 } 1230 1231 sal_free(qgpid); 1232 1233 for (idx = 0; idx < _SOC_MMU_CFG_DEV_POOL_NUM(devcfg); idx++) { 1234 buf_pool = &buf->pools[idx]; 1235 1236 buf_pool->queue_guarantee = queue_min[idx]; 1237 buf_pool->prigroup_headroom = headroom[idx]; 1238 buf_pool->prigroup_guarantee = min_guarentees[idx]; 1239 buf_pool->mcq_entry_reserved = mcq_entry_reserved[idx]; 1240 #if 0 1241 buf_pool->total -= (buf_pool->queue_guarantee + 1242 buf_pool->prigroup_headroom + 1243 buf_pool->prigroup_guarantee); 1244 #endif 1245 } 1246 1247 if (bsl_check(bslLayerSoc, bslSourceCommon, bslSeverityVerbose, unit)) { 1248 LOG_CLI((BSL_META_U(unit, 1249 "MMU buffer usage:\n"))); 1250 LOG_CLI((BSL_META_U(unit, 1251 " Global headroom: %d\n"), buf->headroom)); 1252 for (idx = 0; idx < _SOC_MMU_CFG_DEV_POOL_NUM(devcfg); idx++) { 1253 buf_pool = &buf->pools[idx]; 1254 if ((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) { 1255 continue; 1256 } 1257 LOG_CLI((BSL_META_U(unit, 1258 " Pool %d total prigroup guarantee: %d\n"), 1259 idx, buf_pool->prigroup_guarantee)); 1260 LOG_CLI((BSL_META_U(unit, 1261 " Pool %d total prigroup headroom: %d\n"), 1262 idx, buf_pool->prigroup_headroom)); 1263 LOG_CLI((BSL_META_U(unit, 1264 " Pool %d total queue guarantee: %d\n"), 1265 idx, buf_pool->queue_guarantee)); 1266 LOG_CLI((BSL_META_U(unit, 1267 " Pool %d total mcq entry reserved: %d\n"), 1268 idx, buf_pool->mcq_entry_reserved)); 1269 } 1270 } 1271 1272 SOC_IF_ERROR_RETURN( 1273 _soc_mmu_cfg_cross_point_buf_calculate(unit, buf, devcfg)); 1274 1275 return SOC_E_NONE; 1276 } 1277 1278 int 1279 _soc_mmu_cfg_buf_check(int unit, _soc_mmu_cfg_buf_t *buf, 1280 _soc_mmu_device_info_t *devcfg) 1281 { 1282 _soc_mmu_cfg_buf_pool_t *buf_pool; 1283 _soc_mmu_cfg_buf_port_t *buf_port; 1284 _soc_mmu_cfg_buf_prigroup_t *buf_prigroup; 1285 int yellow_cells, red_cells; 1286 int port, dft_pool, idx; 1287 uint32 pool_map; 1288 1289 SOC_IF_ERROR_RETURN(_soc_mmu_cfg_buf_calculate(unit, buf, devcfg)); 1290 1291 dft_pool =0; 1292 pool_map = 0; 1293 for (idx = 0; idx < _SOC_MMU_CFG_DEV_POOL_NUM(devcfg); idx++) { 1294 buf_pool = &buf->pools[idx]; 1295 if ((buf_pool->size & ~_MMU_CFG_BUF_PERCENT_FLAG) == 0) { 1296 continue; 1297 } 1298 1299 if (pool_map == 0) { 1300 dft_pool = idx; 1301 } 1302 pool_map |= 1 << idx; 1303 1304 if (buf_pool->total <= 0) { 1305 LOG_CLI((BSL_META_U(unit, 1306 "Pool %d has no shared space after " 1307 "deducting guaranteed !!"), idx)); 1308 return SOC_E_FAIL; 1309 } 1310 1311 if (buf_pool->yellow_size & _MMU_CFG_BUF_PERCENT_FLAG) { 1312 yellow_cells = (buf_pool->yellow_size & ~_MMU_CFG_BUF_PERCENT_FLAG) * 1313 buf_pool->total / 10000; 1314 } else { 1315 yellow_cells = buf_pool->yellow_size; 1316 } 1317 if (buf_pool->red_size & _MMU_CFG_BUF_PERCENT_FLAG) { 1318 red_cells = (buf_pool->red_size & ~_MMU_CFG_BUF_PERCENT_FLAG) * 1319 buf_pool->total / 10000; 1320 } else { 1321 red_cells = buf_pool->red_size; 1322 } 1323 1324 if (yellow_cells > red_cells) { 1325 LOG_CLI((BSL_META_U(unit, 1326 "MMU config pool %d: Yellow cells offset is higher " 1327 "than red cells\n"), idx)); 1328 } 1329 if (red_cells > buf_pool->total) { 1330 LOG_CLI((BSL_META_U(unit, 1331 "MMU config pool %d: Red cells offset is higher " 1332 "than pool shared cells\n"), idx)); 1333 } 1334 } 1335 1336 PBMP_ALL_ITER(unit, port) { 1337 buf_port = &buf->ports[port]; 1338 1339 /* internal priority to priority group mapping */ 1340 for (idx = 0; idx < 16; idx++) { 1341 if (buf_port->pri_to_prigroup[idx] < 0 || 1342 buf_port->pri_to_prigroup[idx] >= _SOC_MMU_CFG_DEV_PG_NUM(devcfg)) { 1343 LOG_CLI((BSL_META_U(unit, 1344 "MMU config port %d: Invalid prigroup value (%d) " 1345 "for internal priority %d\n"), 1346 port, buf_port->pri_to_prigroup[idx], idx)); 1347 buf_port->pri_to_prigroup[idx] = 0; /* use prigroup 0 */ 1348 } 1349 } 1350 1351 /* priority group to pool mapping */ 1352 for (idx = 0; idx < _SOC_MMU_CFG_DEV_PG_NUM(devcfg); idx++) { 1353 buf_prigroup = &buf_port->prigroups[idx]; 1354 if (buf_prigroup->pool_idx < 0 || 1355 buf_prigroup->pool_idx >= _SOC_MMU_CFG_DEV_POOL_NUM(devcfg)) { 1356 LOG_CLI((BSL_META_U(unit, 1357 "MMU config port %d prigroup %d: " 1358 "Invalid pool value (%d)\n"), 1359 port, idx, buf_prigroup->pool_idx)); 1360 /* use first non-empty pool */ 1361 buf_prigroup->pool_idx = dft_pool; 1362 } else if (!(pool_map & (1 << buf_prigroup->pool_idx))) { 1363 LOG_CLI((BSL_META_U(unit, 1364 "MMU config port %d prigroup %d: " 1365 "Pool %d is empty\n"), 1366 port, idx, buf_prigroup->pool_idx)); 1367 } 1368 } 1369 1370 #if 0 1371 /* queue to pool mapping */ 1372 count = (IS_LB_PORT(unit, port) ? 5 : si->port_num_cosq[port]) + 1373 si->port_num_uc_cosq[port] + 1374 si->port_num_ext_cosq[port]; 1375 for (idx = 0; idx < count; idx++) { 1376 buf_queue = &buf->ports[port].queues[idx]; 1377 1378 queue_idx = idx; 1379 if (queue_idx < si->port_num_cosq[port]) { 1380 sal_sprintf(queue_name, "mqueue %d", queue_idx); 1381 } else { 1382 queue_idx -= si->port_num_cosq[port]; 1383 if (queue_idx < si->port_num_uc_cosq[port]) { 1384 sal_sprintf(queue_name, "queue %d", queue_idx); 1385 } else { 1386 queue_idx -= si->port_num_uc_cosq[port]; 1387 sal_sprintf(queue_name, "equeue %d", queue_idx); 1388 } 1389 } 1390 1391 if (buf_queue->pool_idx < 0 || 1392 buf_queue->pool_idx >= _SOC_MMU_CFG_DEV_POOL_NUM(devcfg)) { 1393 LOG_CLI((BSL_META_U(unit, 1394 "MMU config port %d %s: " 1395 "Invalid pool value (%d)\n"), 1396 port, queue_name, buf_queue->pool_idx)); 1397 buf_queue->pool_idx = dft_pool; /* use first non-empty pool */ 1398 } else if (!(pool_map & (1 << buf_queue->pool_idx))) { 1399 LOG_CLI((BSL_META_U(unit, 1400 "MMU config port %d %s: Pool %d is empty\n"), 1401 port, queue_name, buf_queue->pool_idx)); 1402 } 1403 } 1404 #endif 1405 } 1406 1407 return SOC_E_NONE; 1408 } 1409 1410 _soc_mmu_cfg_buf_t* soc_mmu_cfg_alloc(int unit) 1411 { 1412 soc_info_t *si; 1413 _soc_mmu_cfg_buf_t *buf; 1414 _soc_mmu_cfg_buf_queue_t *buf_queue; 1415 int num_cosq, alloc_size=0; 1416 soc_port_t port; 1417 si = &SOC_INFO(unit); 1418 1419 alloc_size = sizeof(_soc_mmu_cfg_buf_t); 1420 PBMP_ALL_ITER(unit, port) { 1421 num_cosq = si->port_num_cosq[port] + si->port_num_uc_cosq[port]; 1422 if (SOC_IS_MONTEREY(unit) && !IS_CPU_PORT (unit, port) ) { 1423 num_cosq = 20; 1424 } 1425 alloc_size += (sizeof(_soc_mmu_cfg_buf_queue_t) * num_cosq); 1426 } 1427 1428 buf = sal_alloc(alloc_size, "MMU config buffer"); 1429 if (buf == NULL) { 1430 return NULL; 1431 } 1432 1433 sal_memset(buf, 0, alloc_size); 1434 buf_queue = (_soc_mmu_cfg_buf_queue_t *)&buf[1]; 1435 PBMP_ALL_ITER(unit, port) { 1436 num_cosq = si->port_num_cosq[port] + si->port_num_uc_cosq[port]; 1437 buf->ports[port].queues = buf_queue; 1438 buf_queue += num_cosq; 1439 } 1440 return buf; 1441 } 1442 1443 void 1444 soc_mmu_cfg_free(int unit, _soc_mmu_cfg_buf_t *cfg) 1445 { 1446 sal_free(cfg); 1447 } 1448 1449 #endif /* defined(BCM_TRIUMPH3_SUPPORT) */