trident2p.c (236377B)
1 /* 2 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 * 8 * File: trident2p.c 9 * Purpose: 10 * Requires: 11 */ 12 #include <shared/bsl.h> 13 #include <sal/core/boot.h> 14 15 #include <soc/bradley.h> 16 #include <soc/drv.h> 17 #include <soc/error.h> 18 #include <soc/debug.h> 19 #include <soc/mem.h> 20 #include <soc/mspi.h> 21 #include <soc/l2x.h> 22 #include <soc/soc_ser_log.h> 23 #include <soc/devids.h> 24 25 26 #ifdef BCM_TRIDENT2PLUS_SUPPORT 27 #include <soc/trident2.h> 28 #include <soc/td2_td2p.h> 29 #include <soc/tdm/core/tdm_top.h> 30 #include <soc/esw/portctrl.h> 31 #include <soc/scache.h> 32 33 #define IS_OVERSUB_PORT(unit,port) \ 34 (SOC_PBMP_MEMBER(PBMP_OVERSUB(unit), port)) 35 36 37 #define BCM_TD2P_MAX_BANK_SIZE 128 38 #define BCM_TD2P_SMALL_BANK_SIZE 64 39 40 41 #define _TD2P_PROB_DROP_SOP_XOFF 80 42 #define _TD2P_PROB_DROP_SOP_XON_ABOVE_THR 65 43 #define _TD2P_PROB_DROP_SOP_XON_BELOW_THR 0 44 45 46 #define _SOC_TRIDENT2P_UPDATE_TDM_PRE (0) 47 #define _SOC_TRIDENT2P_UPDATE_TDM_POST (1) 48 49 static const soc_reg_t pvtmon_result_reg[] = { 50 TOP_PVTMON_RESULT_0r, TOP_PVTMON_RESULT_1r, 51 TOP_PVTMON_RESULT_2r, TOP_PVTMON_RESULT_3r, 52 TOP_PVTMON_RESULT_4r, TOP_PVTMON_RESULT_5r, 53 TOP_PVTMON_RESULT_6r, TOP_PVTMON_RESULT_7r, 54 TOP_PVTMON_RESULT_8r 55 }; 56 57 STATIC soc_reg_t mmu_ovs_group_wt_regs_td2p_local[2][_MMU_OVS_WT_GROUP_COUNT] = { 58 { 59 ES_PIPE0_OVR_SUB_GRP_WT0r, ES_PIPE0_OVR_SUB_GRP_WT1r, 60 ES_PIPE0_OVR_SUB_GRP_WT2r, ES_PIPE0_OVR_SUB_GRP_WT3r 61 }, 62 { 63 ES_PIPE1_OVR_SUB_GRP_WT0r, ES_PIPE1_OVR_SUB_GRP_WT1r, 64 ES_PIPE1_OVR_SUB_GRP_WT2r, ES_PIPE1_OVR_SUB_GRP_WT3r 65 } 66 }; 67 68 STATIC soc_reg_t mmu_3dbg_c_regs[2] = { 69 ES_PIPE0_MMU_3DBG_Cr, 70 ES_PIPE1_MMU_3DBG_Cr 71 }; 72 73 STATIC const soc_field_t mmu_ovr_group_wt_select_fields[] = { 74 GRP0f, GRP1f, GRP2f, GRP3f, 75 GRP4f, GRP5f, GRP6f, GRP7f 76 }; 77 78 typedef struct _soc_td2p_ovr_sub_mmu_tdm_s { 79 int grp_wt_sel[TD2P_PIPES_PER_DEV][MAX_MMU_OVS_GROUP_COUNT]; 80 int tdm_update[TD2P_PIPES_PER_DEV][MAX_MMU_OVS_GROUP_COUNT] 81 [_MMU_OVS_GROUP_TDM_LENGTH]; 82 int grp_wt[TD2P_PIPES_PER_DEV][MAX_MMU_OVS_GROUP_COUNT] 83 [_MMU_OVS_GROUP_TDM_LENGTH]; 84 int mmu_port[TD2P_PIPES_PER_DEV][MAX_MMU_OVS_GROUP_COUNT] 85 [_MMU_OVS_GROUP_TDM_LENGTH]; 86 } _soc_td2p_ovr_sub_mmu_tdm_t; 87 88 typedef struct _soc_td2p_ovr_sub_tdm_s { 89 _soc_td2p_ovr_sub_mmu_tdm_t mmu_tdm; 90 } _soc_td2p_ovr_sub_tdm_t; 91 92 enum _td2p_ovs_wt_speed_group { 93 td2p_ovs_wt_group_speed_10G, 94 td2p_ovs_wt_group_speed_20G, 95 td2p_ovs_wt_group_speed_40G, 96 td2p_ovs_wt_group_speed_NA 97 }; 98 99 static _soc_td2p_flexport_port_q_cb td2p_flexport_cb; 100 static _soc_td2p_ets_mode_q_cb td2p_ets_mode_cb; 101 102 103 #define NUM_TSC4_PORT_MACRO 32 104 static int 105 soc_td2p_pm_to_1st_port_tsc12[NUM_TSC4_PORT_MACRO] = 106 {1 , 1 , 1 , 13, /* X Pipe */ 107 17, 21, 21, 21, 108 33, 33, 33, 45, 109 49, 53, 53, 53, 110 65, 65, 65, 77, /* Y Pipe */ 111 81, 85, 85, 85, 112 97, 97, 97, 109, 113 113,117, 117, 117}; 114 115 static int 116 soc_td2p_pm_to_1st_port_tsc4[NUM_TSC4_PORT_MACRO] = 117 {1 , 5 , 9 , 13, /* X Pipe */ 118 17, 21, 25, 29, 119 33, 37, 41, 45, 120 49, 53, 57, 61, 121 65, 69, 73, 77, /* Y Pipe */ 122 81, 85, 89, 93, 123 97, 101, 105, 109, 124 113,117, 121, 125}; 125 126 /* index 0 is for X pipe, index 1 is for Y pipe */ 127 static int num_hsp_to_reserve[_TD2_PIPES_PER_DEV] = {0, 0}; 128 129 /* defines for Reserved Buffer for Flex Port Macro when new Flex Port is 130 enabled */ 131 /* lossless defines */ 132 #define _TD2P_RSVD_BUF_FLEX_HDRM_LOSSLESS 182 133 134 #define _TD2P_RSVD_BUF_FLEX_QGRP 16 135 #define _TD2P_RSVD_BUF_FLEX_ASF 4 136 137 /* defines for Reserved Buffer for Ports when Flex Port for the macro is NOT 138 enabled*/ 139 #define _TD2P_RSVD_BUF_NON_FLEX_100G_HDRM_LOSSLESS 558 140 #define _TD2P_RSVD_BUF_NON_FLEX_40G_HDRM_LOSSLESS 461 141 #define _TD2P_RSVD_BUF_NON_FLEX_20G_HDRM_LOSSLESS 262 142 #define _TD2P_RSVD_BUF_NON_FLEX_10G_HDRM_LOSSLESS 182 143 144 #define _TD2P_RSVD_BUF_NON_FLEX_PGMIN 8 145 #define _TD2P_RSVD_BUF_NON_FLEX_QGRP 16 146 #define _TD2P_RSVD_BUF_NON_FLEX_ASF 16 147 148 #define _TD2P_RSVD_BUF_NON_FLEX_10G_ASF 4 149 150 #define _TD2P_NUM_TSC4_PER_PIPE 16 151 #define _TD2P_NUM_PORTS_PER_TSC4 4 152 153 int get_mmu_mode (int unit) 154 { 155 int is16Mmode = 0; 156 char *str, *str_end; 157 int mmu_size = 0; 158 159 if (SAL_BOOT_QUICKTURN) { 160 if ((str = soc_property_get_str(unit, "mmu_mem_size")) != NULL) { 161 mmu_size = sal_ctoi(str, &str_end); 162 if (str != str_end) { 163 if ( mmu_size == 16 ) { 164 is16Mmode = 1; 165 } 166 } 167 } 168 } else { 169 is16Mmode = 1; 170 } 171 172 return is16Mmode; 173 } 174 175 mmu_ovs_group_wt_regs_t 176 get_mmu_ovs_group_wt_regs (int unit, mmu_ovs_group_wt_regs_t old) 177 { 178 if (SOC_IS_TD2P_TT2P(unit)) { 179 return mmu_ovs_group_wt_regs_td2p_local; 180 } 181 return old; 182 } 183 184 int soc_td2p_if_full_chip (int unit) 185 { 186 int full_chip = 1; 187 188 return full_chip; 189 } 190 191 int soc_td2p_show_voltage(int unit) 192 { 193 soc_reg_t reg; 194 int index; 195 uint32 rval, fval, avg; 196 197 SOC_IF_ERROR_RETURN(READ_TOP_PVTMON_CTRL_1r(unit, &rval)); 198 soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_ADC_RESETBf, 0); 199 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_1r(unit, rval)); 200 soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_ADC_RESETBf, 1); 201 soc_reg_field_set(unit, TOP_PVTMON_CTRL_1r, &rval, PVTMON_SELECTf, 4); 202 SOC_IF_ERROR_RETURN(WRITE_TOP_PVTMON_CTRL_1r(unit, rval)); 203 SOC_IF_ERROR_RETURN(READ_TOP_SOFT_RESET_REG_2r(unit, &rval)); 204 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_AVS_PVTMON_RST_Lf, 0); 205 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 206 soc_reg_field_set(unit, TOP_SOFT_RESET_REG_2r, &rval, TOP_AVS_PVTMON_RST_Lf, 1); 207 SOC_IF_ERROR_RETURN(WRITE_TOP_SOFT_RESET_REG_2r(unit, rval)); 208 209 sal_sleep(1); 210 avg = 0; 211 212 /* Read Voltages. Ignores result of PVTMON8 */ 213 for (index = 0; index < COUNTOF(pvtmon_result_reg) - 1; index++) { 214 reg = pvtmon_result_reg[index]; 215 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 216 fval = soc_reg_field_get(unit, reg, rval, PVT_DATAf); 217 /* (PVT_DATA * 880) / 1024 * 0.7 */ 218 fval = (fval * 880 * 10) / (1024 * 7); 219 avg += fval; 220 LOG_CLI((BSL_META_U(unit, 221 "Voltage monitor %d: voltage = %d.%03dV\n"), 222 index, (fval/1000), (fval %1000))); 223 } 224 225 avg /= (COUNTOF(pvtmon_result_reg) - 1); 226 LOG_CLI((BSL_META_U(unit, 227 "Average voltage is = %d.%03dV\n"), 228 (avg/1000), (avg %1000))); 229 230 return SOC_E_NONE; 231 } 232 233 int soc_td2p_set_obm_registers (int unit, soc_reg_t reg, int speed, int index, 234 int obm_inst, int lossless , int default_flag) 235 { 236 int xon, xoff; 237 uint64 ctrl_rval64; 238 int maxt, mint = 0; 239 int lowprit; 240 int div; 241 242 if (PGW_OBM_INIT_HW_DEFAULT == default_flag) { 243 maxt = 0; 244 xoff = 0; 245 xon = 0; 246 lowprit = 0; 247 } else { 248 if ( speed > 20000) { 249 div = 1; 250 xoff = 0x2C3; 251 xon = 0x2AB; 252 lowprit = 0x2AE; 253 } else if (speed > 10000) { 254 div = 2; 255 xoff = 0x13B; 256 xon = 0x12F; 257 lowprit = 0x132; 258 } else { 259 div = 4; 260 xoff = 0x4F; 261 xon = 0x49; 262 lowprit = 0x4c; 263 } 264 maxt = GET_NUM_CELLS_PER_OBM(unit) / div; 265 266 if ( !lossless ) { 267 xon = xoff = 0x7FF; 268 lowprit = maxt; 269 } 270 } 271 272 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, index, 273 &ctrl_rval64)); 274 soc_reg64_field32_set(unit, reg, &ctrl_rval64, 275 MIN_THRESHOLDf, mint); 276 soc_reg64_field32_set(unit, reg, &ctrl_rval64, 277 LOW_PRI_THRESHOLDf, lowprit); 278 soc_reg64_field32_set(unit, reg, &ctrl_rval64, 279 MAX_THRESHOLDf, maxt); 280 soc_reg64_field32_set(unit, reg, &ctrl_rval64, 281 FLOW_CTRL_XONf, xon); 282 soc_reg64_field32_set(unit, reg, &ctrl_rval64, 283 FLOW_CTRL_XOFFf, xoff); 284 285 SOC_IF_ERROR_RETURN 286 (soc_reg_set(unit, reg, obm_inst, index, ctrl_rval64)); 287 288 289 return SOC_E_NONE; 290 } 291 292 /* Probablistic Drop configuration for TD2PLUS: 293 * These settings cannot be changed dynamically, According to Architecture team 294 * these settings are optimized for all the OverSubscription ratios. Hence not 295 * giving any configuration options for these fields. 296 * OverSub feature is enabled by default for TD2PLUS. 297 */ 298 int soc_td2p_obm_prob_drop_default_set (int unit, int xlp, int index, 299 int obm_inst, int default_flag) 300 { 301 static const soc_reg_t pgw_obm_prob_drop_regs[] = { 302 PGW_OBM0_LOW_PRI_DROP_PROBr, PGW_OBM1_LOW_PRI_DROP_PROBr, 303 PGW_OBM2_LOW_PRI_DROP_PROBr, PGW_OBM3_LOW_PRI_DROP_PROBr 304 }; 305 soc_reg_t reg; 306 uint64 ctrl_rval64; 307 308 reg = pgw_obm_prob_drop_regs[xlp]; 309 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, index, 310 &ctrl_rval64)); 311 if (PGW_OBM_INIT_HW_DEFAULT == default_flag) { 312 soc_reg64_field32_set(unit, reg, &ctrl_rval64, EN_DROP_PROBf, 0); 313 soc_reg64_field32_set(unit, reg, &ctrl_rval64, SOP_XOFFf, 0); 314 soc_reg64_field32_set(unit, reg, &ctrl_rval64, SOP_XON_ABOVE_THRf, 0); 315 soc_reg64_field32_set(unit, reg, &ctrl_rval64, SOP_XON_BELOW_THRf, 0); 316 } else { 317 /* By default enable Probabilistic dropping */ 318 soc_reg64_field32_set(unit, reg, &ctrl_rval64, EN_DROP_PROBf, 1); 319 soc_reg64_field32_set(unit, reg, &ctrl_rval64, SOP_XOFFf, 320 _TD2P_PROB_DROP_SOP_XOFF); 321 soc_reg64_field32_set(unit, reg, &ctrl_rval64, SOP_XON_ABOVE_THRf, 322 _TD2P_PROB_DROP_SOP_XON_ABOVE_THR); 323 soc_reg64_field32_set(unit, reg, &ctrl_rval64, SOP_XON_BELOW_THRf, 324 _TD2P_PROB_DROP_SOP_XON_BELOW_THR); 325 } 326 SOC_IF_ERROR_RETURN 327 (soc_reg_set(unit, reg, obm_inst, index, ctrl_rval64)); 328 329 return SOC_E_NONE; 330 } 331 332 /* Cut through is allowed if usage is less than or equal to 333 * CUT_THROUGH_OKf threshold. Granularity is 16B cell. 334 */ 335 int soc_td2p_obm_cut_through_threshold_set (int unit, int xlp, int index, 336 int obm_inst, int default_flag) 337 { 338 static const soc_reg_t pgw_obm_threshold2_regs[] = { 339 PGW_OBM0_THRESHOLD2r, PGW_OBM1_THRESHOLD2r, 340 PGW_OBM2_THRESHOLD2r, PGW_OBM3_THRESHOLD2r 341 }; 342 soc_reg_t reg; 343 uint64 ctrl_rval64; 344 345 reg = pgw_obm_threshold2_regs[xlp]; 346 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, index, 347 &ctrl_rval64)); 348 if ( PGW_OBM_INIT_HW_DEFAULT == default_flag ) { 349 soc_reg64_field32_set(unit, reg, &ctrl_rval64, 350 CUT_THROUGH_OKf, 0); 351 } else { 352 soc_reg64_field32_set(unit, reg, &ctrl_rval64, 353 CUT_THROUGH_OKf, 2); 354 } 355 SOC_IF_ERROR_RETURN 356 (soc_reg_set(unit, reg, obm_inst, index, ctrl_rval64)); 357 return SOC_E_NONE; 358 } 359 360 STATIC int 361 soc_td2p_pgw_mib_reset_reg_default_set(int unit, int xlp, int port_index, 362 int obm_inst) 363 { 364 const soc_reg_t reg = PGW_MIB_RESETr; 365 const soc_field_t field = CLR_CNTf; 366 int port_index_pgw; 367 uint64 ctrl_rval64; 368 uint32 reg_val; 369 370 port_index_pgw = xlp * 4 + port_index; 371 372 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, port_index, 373 &ctrl_rval64)); 374 reg_val = soc_reg64_field32_get(unit, reg, ctrl_rval64, field); 375 /* coverity[ptr_arith] */ 376 SHR_BITSET(®_val, port_index_pgw); 377 soc_reg64_field32_set(unit, reg, &ctrl_rval64, 378 field, reg_val); 379 SOC_IF_ERROR_RETURN 380 (soc_reg_set(unit, reg, obm_inst, port_index, ctrl_rval64)); 381 382 /* coverity[ptr_arith] */ 383 SHR_BITCLR(®_val, port_index_pgw); 384 soc_reg64_field32_set(unit, reg, &ctrl_rval64, 385 field, reg_val); 386 SOC_IF_ERROR_RETURN 387 (soc_reg_set(unit, reg, obm_inst, port_index, ctrl_rval64)); 388 389 return SOC_E_NONE; 390 } 391 392 STATIC int 393 soc_td2p_obm_high_pri_byte_drop_default_set (int unit, int xlp, int index, 394 int obm_inst) 395 { 396 static const soc_reg_t pgw_obm_high_pri_byte_drop_regs[] = { 397 PGW_OBM0_HIGH_PRI_BYTE_DROPr, PGW_OBM1_HIGH_PRI_BYTE_DROPr, 398 PGW_OBM2_HIGH_PRI_BYTE_DROPr, PGW_OBM3_HIGH_PRI_BYTE_DROPr 399 }; 400 soc_reg_t reg; 401 uint64 ctrl_rval64; 402 reg = pgw_obm_high_pri_byte_drop_regs[xlp]; 403 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, index, 404 &ctrl_rval64)); 405 soc_reg64_field32_set(unit, reg, &ctrl_rval64, COUNTERf, 0); 406 SOC_IF_ERROR_RETURN 407 (soc_reg_set(unit, reg, obm_inst, index, ctrl_rval64)); 408 409 return SOC_E_NONE; 410 } 411 412 STATIC int 413 soc_td2p_obm_high_pri_pkt_drop_default_set (int unit, int xlp, int index, 414 int obm_inst) 415 { 416 static const soc_reg_t pgw_obm_high_pri_pkt_drop_regs[] = { 417 PGW_OBM0_HIGH_PRI_PKT_DROPr, PGW_OBM1_HIGH_PRI_PKT_DROPr, 418 PGW_OBM2_HIGH_PRI_PKT_DROPr, PGW_OBM3_HIGH_PRI_PKT_DROPr 419 }; 420 soc_reg_t reg; 421 uint64 ctrl_rval64; 422 reg = pgw_obm_high_pri_pkt_drop_regs[xlp]; 423 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, index, 424 &ctrl_rval64)); 425 soc_reg64_field32_set(unit, reg, &ctrl_rval64, COUNTERf, 0); 426 SOC_IF_ERROR_RETURN 427 (soc_reg_set(unit, reg, obm_inst, index, ctrl_rval64)); 428 429 return SOC_E_NONE; 430 } 431 432 STATIC int 433 soc_td2p_obm_low_pri_byte_drop_default_set (int unit, int xlp, int index, 434 int obm_inst) 435 { 436 static const soc_reg_t pgw_obm_low_pri_byte_drop_regs[] = { 437 PGW_OBM0_LOW_PRI_BYTE_DROPr, PGW_OBM1_LOW_PRI_BYTE_DROPr, 438 PGW_OBM2_LOW_PRI_BYTE_DROPr, PGW_OBM3_LOW_PRI_BYTE_DROPr 439 }; 440 soc_reg_t reg; 441 uint64 ctrl_rval64; 442 reg = pgw_obm_low_pri_byte_drop_regs[xlp]; 443 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, index, 444 &ctrl_rval64)); 445 soc_reg64_field32_set(unit, reg, &ctrl_rval64, COUNTERf, 0); 446 SOC_IF_ERROR_RETURN 447 (soc_reg_set(unit, reg, obm_inst, index, ctrl_rval64)); 448 449 return SOC_E_NONE; 450 } 451 452 STATIC int 453 soc_td2p_obm_low_pri_pkt_drop_default_set (int unit, int xlp, int index, 454 int obm_inst) 455 { 456 static const soc_reg_t pgw_obm_low_pri_pkt_drop_regs[] = { 457 PGW_OBM0_LOW_PRI_PKT_DROPr, PGW_OBM1_LOW_PRI_PKT_DROPr, 458 PGW_OBM2_LOW_PRI_PKT_DROPr, PGW_OBM3_LOW_PRI_PKT_DROPr 459 }; 460 soc_reg_t reg; 461 uint64 ctrl_rval64; 462 reg = pgw_obm_low_pri_pkt_drop_regs[xlp]; 463 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm_inst, index, 464 &ctrl_rval64)); 465 soc_reg64_field32_set(unit, reg, &ctrl_rval64, COUNTERf, 0); 466 SOC_IF_ERROR_RETURN 467 (soc_reg_set(unit, reg, obm_inst, index, ctrl_rval64)); 468 469 return SOC_E_NONE; 470 } 471 472 473 int soc_td2p_mmu_delay_insertion_set (int unit, int port, int speed) 474 { 475 int phy_port, mmu_port; 476 int pipe; 477 int val = 0; 478 uint32 rval; 479 soc_info_t *si; 480 481 si = &SOC_INFO(unit); 482 483 phy_port = si->port_l2p_mapping[port]; 484 mmu_port = si->port_p2m_mapping[phy_port] & 0x3F; 485 486 if ( mmu_port < SOC_TD2P_MAX_MMU_PORTS_PER_PIPE ) { 487 pipe = SOC_PBMP_MEMBER(si->ypipe_pbm, port) ? 1 : 0; 488 489 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, 490 mmu_3dbg_c_regs [ pipe ], REG_PORT_ANY, mmu_port, &rval)); 491 /* register format is the same for PIPE0 and PIPE1 */ 492 if (IS_OVERSUB_PORT(unit, port )) { 493 if ( speed <= 10000 ) { 494 val = 15; 495 } else if ( speed <= 20000 ) { 496 val = 30; 497 } else if ( speed <= 25000 ) { 498 val = 40; 499 } else if ( speed <= 40000 ) { 500 val = 60; 501 } else { 502 } 503 } else { 504 /* linerate port */ 505 } 506 soc_reg_field_set(unit, ES_PIPE0_MMU_3DBG_Cr, &rval, FIELD_Af, val); 507 508 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, 509 mmu_3dbg_c_regs [ pipe ], REG_PORT_ANY, mmu_port, rval)); 510 } 511 512 return SOC_E_NONE; 513 } 514 515 /* 516 * Function: 517 * soc_td2p_subport_init 518 * Purpose: 519 * Setup the pbm fields from config variables for the COE application 520 * Parameters: 521 * unit - (IN) Device number. 522 * Returns: 523 * NONE 524 */ 525 void soc_td2p_subport_init(int unit) 526 { 527 soc_port_t port; 528 soc_info_t *si=&SOC_INFO(unit); 529 soc_pbmp_t pbmp_subport; 530 int num_subport = 0; 531 532 SOC_PBMP_CLEAR(si->subtag_pbm); 533 SOC_PBMP_CLEAR(si->subtag_allowed_pbm); 534 SOC_PBMP_CLEAR(si->subtag.bitmap); 535 536 for (port = 0; port < SOC_MAX_NUM_PORTS; port++) { 537 si->port_num_subport[port] = 0; 538 } 539 540 pbmp_subport = soc_property_get_pbmp(unit, spn_PBMP_SUBPORT, 0); 541 542 SOC_PBMP_ASSIGN(si->subtag_allowed_pbm, pbmp_subport); 543 544 if (SOC_PBMP_NOT_NULL(si->subtag_allowed_pbm)) { 545 /* Iterate through SubTag ports and reserve subport indices */ 546 SOC_PBMP_ITER(si->subtag_allowed_pbm, port) { 547 548 549 num_subport = 550 soc_property_port_get(unit, port, spn_NUM_SUBPORTS, 0); 551 552 if (num_subport > TD2P_MAX_SUBPORT_COE_PORT_PER_CASPORT) { 553 LOG_ERROR(BSL_LS_SOC_COMMON, 554 (BSL_META_U(unit, 555 "\nCONFIG ERROR\n" 556 "num_subports_%d on port %d exceed max value," 557 "setting it to the max allowed value %d\n\n"), 558 num_subport, port, 559 TD2P_MAX_SUBPORT_COE_PORT_PER_CASPORT)); 560 num_subport = TD2P_MAX_SUBPORT_COE_PORT_PER_CASPORT; 561 } 562 563 if (port < SOC_MAX_NUM_PORTS) { 564 si->port_num_subport[port] = num_subport; 565 566 } 567 } 568 } 569 570 /* Initialize the number of COE modules */ 571 si->num_coe_modules = TD2P_MAX_COE_MODULES; 572 } 573 574 int 575 soc_td2p_mem_config(int unit, uint16 dev_id, uint8 rev_id) 576 { 577 soc_persist_t *sop; 578 sop_memstate_t *memState; 579 580 int index_max; 581 int ipmc_tbl [] = { L3_IPMC_1m, L3_IPMC_REMAPm, L3_IPMCm, 582 EGR_IPMCm}; 583 int ipmc_tindex; 584 585 586 sop = SOC_PERSIST(unit); 587 memState = sop->memState; 588 589 switch ( dev_id ) { 590 case BCM56832_DEVICE_ID : 591 index_max = 8 * 1024; 592 break; 593 default : 594 index_max = 16 * 1024; 595 break; 596 } 597 index_max--; /* index is a last element so = size - 1 */ 598 599 for (ipmc_tindex = 0; ipmc_tindex < sizeof(ipmc_tbl)/sizeof(ipmc_tbl[0]); 600 ipmc_tindex++ ) { 601 memState[ipmc_tbl[ipmc_tindex]].index_max = index_max; 602 } 603 604 if (dev_id == BCM56832_DEVICE_ID) { 605 index_max = 8 * 1024; 606 } else { 607 index_max = 12 * 1024; 608 } 609 index_max--; 610 memState[L3_IIFm].index_max = index_max; 611 612 /* Disable CoE related memories for appr. SKUs */ 613 if ((dev_id != BCM56866_DEVICE_ID) && (dev_id != BCM56867_DEVICE_ID)) { 614 memState[SUBPORT_TAG_SGPP_MAPm].index_max = -1; 615 memState[SUBPORT_TAG_SGPP_MAP_ONLYm].index_max = -1; 616 memState[SUBPORT_TAG_SGPP_MAP_DATA_ONLYm].index_max = -1; 617 memState[EGR_LPORT_PROFILEm].index_max = -1; 618 memState[EGR_SUBPORT_TAG_DOT1P_MAPm].index_max = -1; 619 } 620 621 switch (dev_id) { 622 case BCM56868_DEVICE_ID: 623 /* L3 Forwarding disabled */ 624 memState[L3_ECMPm].index_max = -1; 625 memState[L3_ECMP_COUNTm].index_max = -1; 626 memState[ING_L3_NEXT_HOPm].index_max = -1; 627 memState[INITIAL_L3_ECMPm].index_max = -1; 628 memState[INITIAL_L3_ECMP_GROUPm].index_max = -1; 629 memState[INITIAL_ING_L3_NEXT_HOPm].index_max = -1; 630 memState[L3_DEFIP_AUX_HITBIT_UPDATEm].index_max = -1; 631 memState[L3_DEFIP_AUX_SCRATCHm].index_max = -1; 632 memState[L3_DEFIP_AUX_TABLEm].index_max = -1; 633 memState[L3_TUNNELm].index_max = -1; 634 memState[L3_TUNNEL_DATA_ONLYm].index_max = -1; 635 memState[L3_TUNNEL_ONLYm].index_max = -1; 636 637 /* MPLS related memories */ 638 memState[ING_MPLS_EXP_MAPPINGm].index_max = -1; 639 memState[EGR_MPLS_EXP_PRI_MAPPINGm].index_max = -1; 640 memState[EGR_MPLS_VC_AND_SWAP_LABEL_TABLEm].index_max = -1; 641 memState[EGR_MPLS_EXP_PRI_MAPPINGm].index_max = -1; 642 memState[EGR_IP_TUNNEL_MPLSm].index_max = -1; 643 memState[MPLS_ENTROPY_LABEL_DATAm].index_max = -1; 644 memState[MPLS_ENTRYm].index_max = -1; 645 646 /* coverity[fallthrough:FALSE] */ 647 case BCM56832_DEVICE_ID: 648 case BCM56833_DEVICE_ID: 649 case BCM56836_DEVICE_ID: 650 case BCM56867_DEVICE_ID: 651 /* FCoE */ 652 memState[ING_FC_HEADER_TYPEm].index_max = -1; 653 memState[ING_VFT_PRI_MAPm].index_max = -1; 654 memState[ING_VSANm].index_max = -1; 655 memState[FC_MAP_PROFILEm].index_max = -1; 656 memState[FCOE_HOP_COUNT_FNm].index_max = -1; 657 memState[EGR_VSAN_INTPRI_MAPm].index_max = -1; 658 memState[EGR_FCOE_CONTROL_1m].index_max = -1; 659 memState[EGR_VFT_FIELDS_PROFILEm].index_max = -1; 660 memState[EGR_VFT_PRI_MAPm].index_max = -1; 661 memState[EGR_FC_HEADER_TYPEm].index_max = -1; 662 663 /* NAT */ 664 memState[ING_SNATm].index_max = -1; 665 memState[ING_SNAT_DATA_ONLYm].index_max = -1; 666 memState[ING_SNAT_HIT_ONLYm].index_max = -1; 667 memState[ING_SNAT_HIT_ONLY_Xm].index_max = -1; 668 memState[ING_SNAT_HIT_ONLY_Ym].index_max = -1; 669 memState[ING_SNAT_ONLYm].index_max = -1; 670 memState[ING_DNAT_ADDRESS_TYPEm].index_max = -1; 671 memState[EGR_NAT_PACKET_EDIT_INFOm].index_max = -1; 672 673 /* TRILL */ 674 memState[ING_TRILL_PARSE_CONTROLm].index_max = -1; 675 memState[ING_TRILL_PAYLOAD_PARSE_CONTROLm].index_max = -1; 676 memState[EGR_TRILL_PARSE_CONTROLm].index_max = -1; 677 memState[EGR_TRILL_PARSE_CONTROL_2m].index_max = -1; 678 memState[EGR_TRILL_RBRIDGE_NICKNAMESm].index_max = -1; 679 memState[EGR_TRILL_TREE_PROFILEm].index_max = -1; 680 break; 681 case BCM56860_DEVICE_ID: 682 if (SOC_SWITCH_BYPASS_MODE(unit) != SOC_SWITCH_BYPASS_MODE_NONE) { 683 if (SOC_SWITCH_BYPASS_MODE(unit) == 684 SOC_SWITCH_BYPASS_MODE_L3_AND_FP) { 685 686 /* IFP */ 687 memState[FP_RANGE_CHECKm].index_max = -1; 688 memState[FP_GLOBAL_MASK_TCAMm].index_max = -1; 689 memState[FP_GM_FIELDSm].index_max = -1; 690 memState[FP_TCAMm].index_max = -1; 691 memState[FP_SLICE_MAPm].index_max = -1; 692 memState[FP_POLICY_TABLEm].index_max = -1; 693 memState[FP_METER_TABLEm].index_max = -1; 694 memState[FP_COUNTER_TABLEm].index_max = -1; 695 memState[FP_COUNTER_TABLE_Xm].index_max = -1; 696 memState[FP_COUNTER_TABLE_Ym].index_max = -1; 697 memState[FP_STORM_CONTROL_METERSm].index_max = -1; 698 memState[FP_SLICE_KEY_CONTROLm].index_max = -1; 699 memState[FP_PORT_METER_MAPm].index_max = -1; 700 memState[FP_I2E_CLASSID_SELECTm].index_max = -1; 701 memState[FP_HG_CLASSID_SELECTm].index_max = -1; 702 703 /* EFP */ 704 memState[EFP_TCAMm].index_max = -1; 705 memState[EFP_POLICY_TABLEm].index_max = -1; 706 memState[EFP_METER_TABLEm].index_max = -1; 707 memState[EGR_PW_INIT_COUNTERSm].index_max = -1; 708 709 /* IVXLT */ 710 memState[VLAN_PROTOCOLm].index_max = -1; 711 memState[VLAN_PROTOCOL_DATAm].index_max = -1; 712 memState[VLAN_SUBNETm].index_max = -1; 713 memState[VLAN_SUBNET_ONLYm].index_max = -1; 714 memState[VLAN_SUBNET_DATA_ONLYm].index_max = -1; 715 memState[VLAN_MACm].index_max = -1; 716 memState[VLAN_XLATEm].index_max = -1; 717 memState[VFP_TCAMm].index_max = -1; 718 memState[VFP_POLICY_TABLEm].index_max = -1; 719 memState[ING_VLAN_TAG_ACTION_PROFILEm].index_max = -1; 720 memState[MPLS_ENTRYm].index_max = -1; 721 memState[UDF_CONDITIONAL_CHECK_TABLE_CAMm].index_max = -1; 722 memState[UDF_CONDITIONAL_CHECK_TABLE_RAMm].index_max = -1; 723 memState[ING_ETAG_PCP_MAPPINGm].index_max = -1; 724 memState[VLAN_XLATE_ECCm].index_max = -1; 725 memState[MPLS_ENTROPY_LABEL_DATAm].index_max = -1; 726 memState[ING_ETAG_PCP_MAPPINGm].index_max = -1; 727 } 728 } 729 break; 730 default: 731 ; 732 733 } 734 735 return SOC_E_NONE; 736 } 737 738 int 739 soc_td2p_get_shared_bank_size(int unit, uint16 dev_id, uint8 rev_id) 740 { 741 int bank_size = BCM_TD2P_SMALL_BANK_SIZE; 742 743 744 switch ( dev_id ) { 745 case BCM56867_DEVICE_ID : 746 bank_size = BCM_TD2P_MAX_BANK_SIZE; 747 break; 748 } 749 750 return bank_size; 751 } 752 753 uint32* soc_td2p_mmu_params_arr_get (uint16 dev_id, uint8 rev_id) 754 { 755 switch (dev_id) { 756 case BCM56860_DEVICE_ID: 757 case BCM56861_DEVICE_ID: 758 case BCM56862_DEVICE_ID: 759 case BCM56864_DEVICE_ID: 760 case BCM56865_DEVICE_ID: 761 case BCM56866_DEVICE_ID: 762 case BCM56867_DEVICE_ID: 763 case BCM56868_DEVICE_ID: 764 case BCM56836_DEVICE_ID: 765 return soc_mmu_pkt_buf_size_arr[_MMU_PKT_BUF_SIZE_16MB]; 766 break; 767 case BCM56832_DEVICE_ID: 768 return soc_mmu_pkt_buf_size_arr[_MMU_PKT_BUF_SIZE_9MB]; 769 break; 770 case BCM56833_DEVICE_ID: 771 return soc_mmu_pkt_buf_size_arr[_MMU_PKT_BUF_SIZE_12MB]; 772 break; 773 } 774 775 return NULL; 776 } 777 778 STATIC uint32 trident2p_write_data[] = { 779 0x1fffffc0, 0xbffffbfe, 0x1dfcbe80, 0xbffffbfe, 0x40000000, 0x40000200, 780 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 781 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 782 0x80000180, 0x1dfcfe80, 0xbffffbfe, 0x40000000, 0x40000200, 0x40000000, 783 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 784 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 785 0x1dfc7e80, 0xbffffbfe, 0x40000000, 0x40080000, 0x40000000, 0x40000000, 786 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 787 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 788 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 789 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 790 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 791 0x40000000, 0x80000180, 0x1dfc3e80, 0xbffffbfe, 0x40000000, 0x40080000, 792 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 793 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 794 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 795 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 796 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 797 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1dfcde80, 0xbffffbfe, 798 0x44000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 799 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 800 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 801 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 802 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 803 0x40000000, 0x80000180, 0x1dfc9e80, 0xbffffbfe, 0x44000000, 0x40000000, 804 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 805 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 806 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 807 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 808 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 809 0xbfcbe80, 0xbffffbfe, 0x40000000, 0x40001000, 0x40000000, 0x40000000, 810 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 811 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 812 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 813 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 814 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 815 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 816 0x40000000, 0x80000180, 0xbfc7e80, 0xbffffbfe, 0x40000000, 0x40001000, 817 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 818 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 819 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 820 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 821 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 822 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 823 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xbfc3e80, 0xbffffbfe, 824 0x40000000, 0x40080000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 825 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 826 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 827 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 828 0xbfcde80, 0xbffffbfe, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 829 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 830 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 831 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 832 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 833 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1bfc3e80, 834 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000, 835 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 836 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 837 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 838 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1bfcde80, 839 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000, 840 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 841 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 842 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 843 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x17fc7e80, 844 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000, 845 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 846 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 847 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 848 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x17fc3e80, 849 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000, 850 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 851 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 852 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 853 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x13fcbe80, 854 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000, 855 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 856 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 857 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 858 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x13fc7e80, 859 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000, 860 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 861 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 862 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 863 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xffcfe80, 864 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000, 865 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 866 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 867 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 868 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xffcbe80, 869 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000, 870 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 871 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 872 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 873 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1ffc5e80, 874 0xbffffbfe, 0x44000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 875 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 876 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 877 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1ffc1e80, 0xbffffbfe, 878 0x44000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 879 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 880 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 881 0x40000000, 0x40000000, 0x80000180, 0x1dfc5e80, 0xbffffbfe, 0x40000000, 882 0x40000002, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 883 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 884 0x40000000, 0x40000000, 0x80000180, 0x1dfc1e80, 0xbffffbfe, 0x40000000, 885 0x40000002, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 886 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 887 0x40000000, 0x40000000, 0x80000180, 0x1bfcfe80, 0xbffffbfe, 0x40000000, 888 0x48000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 889 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1bfcbe80, 890 0xbffffbfe, 0x40000000, 0x48000000, 0x40000000, 0x40000000, 0x40000000, 891 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 892 0x80000180, 0xdfc5e80, 0xbffffbfe, 0x40000000, 0x40000002, 0x40000000, 893 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 894 0xdfc1e80, 0xbffffbfe, 0x40000000, 0x40200000, 0x40000000, 0x40000000, 895 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 896 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 897 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 898 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 899 0x40000000, 0x40000000, 0x80000180, 0xbfcfe80, 0xbffffbfe, 0x40000000, 900 0x40200000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 901 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 902 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 903 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 904 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 905 0xbfc9e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 0x40000000, 906 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 907 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 908 0x80000180, 0x1dfcbe80, 0xbffffbfe, 0x40000000, 0x40000200, 0x40000000, 909 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 910 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 911 0x1dfcbe80, 0xbffffbfe, 0x40000000, 0x40000200, 0x40000000, 0x40000000, 912 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 913 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1dfcfe80, 914 0xbffffbfe, 0x40000000, 0x40000200, 0x40000000, 0x40000000, 0x40000000, 915 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000, 916 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1dfcfe80, 0xbffffbfe, 917 0x40000000, 0x40000200, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 918 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 919 0x40000000, 0x40000000, 0x80000180, 0x1dfc7e80, 0xbffffbfe, 0x40000000, 920 0x40080000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 921 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 922 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 923 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 924 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 925 0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1dfc7e80, 926 0xbffffbfe, 0x40000000, 0x40080000, 0x40000000, 0x40000000, 0x40000000, 927 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 928 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 929 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 930 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 931 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 932 0x80000180, 0x1dfc3e80, 0xbffffbfe, 0x40000000, 0x40080000, 0x40000000, 933 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 934 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 935 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 936 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 937 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000, 0x40000000, 938 0x40000000, 0x40000000, 0x80000180, 0x1dfc3e80, 0xbffffbfe, 0x40000000, 939 0x40080000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 940 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 941 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 942 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 943 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 944 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1dfcde80, 945 0xbffffbfe, 0x44000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 946 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 947 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 948 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 949 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000, 0x40000000, 950 0x40000000, 0x40000000, 0x80000180, 0x1dfcde80, 0xbffffbfe, 0x44000000, 951 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 952 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 953 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 954 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 955 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 956 0x80000180, 0x1dfc9e80, 0xbffffbfe, 0x44000000, 0x40000000, 0x40000000, 957 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 958 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 959 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 960 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 961 0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1dfc9e80, 962 0xbffffbfe, 0x44000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 963 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 964 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 965 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 966 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 967 0x40000000, 0x40000000, 0x80000180, 0xbfcbe80, 0xbffffbfe, 0x40000000, 968 0x40001000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 969 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 970 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 971 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 972 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 973 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 974 0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xbfcbe80, 975 0xbffffbfe, 0x40000000, 0x40001000, 0x40000000, 0x40000000, 0x40000000, 976 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 977 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 978 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 979 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 980 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 981 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 982 0x80000180, 0xbfc7e80, 0xbffffbfe, 0x40000000, 0x40001000, 0x40000000, 983 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 984 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 985 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 986 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 987 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 988 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000, 0x40000000, 989 0x40000000, 0x40000000, 0x80000180, 0xbfc7e80, 0xbffffbfe, 0x40000000, 990 0x40001000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 991 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 992 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 993 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 994 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 995 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 996 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xbfc3e80, 997 0xbffffbfe, 0x40000000, 0x40080000, 0x40000000, 0x40000000, 0x40000000, 998 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 999 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1000 0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 1001 0x80000180, 0xbfc3e80, 0xbffffbfe, 0x40000000, 0x40080000, 0x40000000, 1002 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1003 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1004 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1005 0x40000000, 0x40000000, 0x80000180, 0xbfcde80, 0xbffffbfe, 0x40000000, 1006 0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1007 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1008 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1009 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1010 0x40000000, 0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 1011 0x40000000, 0x80000180, 0xbfcde80, 0xbffffbfe, 0x40000000, 0x41000000, 1012 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1013 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1014 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1015 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1016 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1017 0x80000180, 0x1bfc3e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1018 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1019 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1020 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1021 0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 1022 0x80000180, 0x1bfc3e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1023 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1024 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1025 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1026 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1027 0x80000180, 0x1bfcde80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1028 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1029 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1030 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1031 0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 1032 0x80000180, 0x1bfcde80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1033 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1034 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1035 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1036 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1037 0x80000180, 0x17fc7e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1038 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1039 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1040 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1041 0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 1042 0x80000180, 0x17fc7e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1043 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1044 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1045 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1046 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1047 0x80000180, 0x17fc3e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1048 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1049 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1050 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1051 0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 1052 0x80000180, 0x17fc3e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1053 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1054 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1055 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1056 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1057 0x80000180, 0x13fcbe80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1058 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1059 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1060 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1061 0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 1062 0x80000180, 0x13fcbe80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1063 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1064 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1065 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1066 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1067 0x80000180, 0x13fc7e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1068 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1069 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1070 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1071 0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 1072 0x80000180, 0x13fc7e80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1073 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1074 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1075 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1076 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1077 0x80000180, 0xffcfe80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1078 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1079 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1080 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1081 0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 1082 0x80000180, 0xffcfe80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1083 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1084 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1085 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1086 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1087 0x80000180, 0xffcbe80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1088 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1089 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1090 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1091 0x40000000, 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 1092 0x80000180, 0xffcbe80, 0xbffffbfe, 0x40000000, 0x40000008, 0x40000000, 1093 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1094 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1095 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1096 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1097 0x80000180, 0x1ffc5e80, 0xbffffbfe, 0x44000000, 0x40000000, 0x40000000, 1098 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1099 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1100 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 1101 0x1ffc5e80, 0xbffffbfe, 0x44000000, 0x40000000, 0x40000000, 0x40000000, 1102 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1103 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1104 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1ffc1e80, 1105 0xbffffbfe, 0x44000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1106 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1107 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000, 1108 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1ffc1e80, 0xbffffbfe, 1109 0x44000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1110 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1111 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1112 0x40000000, 0x40000000, 0x80000180, 0x1dfc5e80, 0xbffffbfe, 0x40000000, 1113 0x40000002, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1114 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000, 0x40000000, 1115 0x40000000, 0x40000000, 0x80000180, 0x1dfc5e80, 0xbffffbfe, 0x40000000, 1116 0x40000002, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1117 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1118 0x40000000, 0x40000000, 0x80000180, 0x1dfc1e80, 0xbffffbfe, 0x40000000, 1119 0x40000002, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1120 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000, 0x40000000, 1121 0x40000000, 0x40000000, 0x80000180, 0x1dfc1e80, 0xbffffbfe, 0x40000000, 1122 0x40000002, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1123 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1124 0x40000000, 0x40000000, 0x80000180, 0x1bfcfe80, 0xbffffbfe, 0x40000000, 1125 0x48000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1126 0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0x1bfcfe80, 1127 0xbffffbfe, 0x40000000, 0x48000000, 0x40000000, 0x40000000, 0x40000000, 1128 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1129 0x80000180, 0x1bfcbe80, 0xbffffbfe, 0x40000000, 0x48000000, 0x40000000, 1130 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000, 0x40000000, 1131 0x40000000, 0x40000000, 0x80000180, 0x1bfcbe80, 0xbffffbfe, 0x40000000, 1132 0x48000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1133 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xdfc5e80, 1134 0xbffffbfe, 0x40000000, 0x40000002, 0x40000000, 0x40000000, 0x41000000, 1135 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xdfc5e80, 0xbffffbfe, 1136 0x40000000, 0x40000002, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1137 0x40000000, 0x40000000, 0x80000180, 0xdfc1e80, 0xbffffbfe, 0x40000000, 1138 0x40200000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1139 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1140 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1141 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1142 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 1143 0xdfc1e80, 0xbffffbfe, 0x40000000, 0x40200000, 0x40000000, 0x40000000, 1144 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1145 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1146 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1147 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1148 0x40000000, 0x40000000, 0x80000180, 0xbfcfe80, 0xbffffbfe, 0x40000000, 1149 0x40200000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1150 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1151 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1152 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1153 0x40000000, 0x41000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180, 1154 0xbfcfe80, 0xbffffbfe, 0x40000000, 0x40200000, 0x40000000, 0x40000000, 1155 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1156 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1157 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1158 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1159 0x40000000, 0x40000000, 0x80000180, 0xbfc9e80, 0xbffffbfe, 0x40000000, 1160 0x40000008, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1161 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x41000000, 1162 0x40000000, 0x40000000, 0x40000000, 0x80000180, 0xbfc9e80, 0xbffffbfe, 1163 0x40000000, 0x40000008, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1164 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x40000000, 1165 0x40000000, 0x40000000, 0x40000000, 0x40000000, 0x80000180 1166 }; 1167 1168 /* 1169 * Function: 1170 * trident2p_ovstb_toggle 1171 * Purpose: 1172 * Execute the OVST sequence for Trident2Plus_A0 devices 1173 * Parameters: 1174 * unit - StrataSwitch unit # 1175 */ 1176 void 1177 trident2p_ovstb_toggle(int unit) 1178 { 1179 int i = 0; 1180 int array_length = 0; 1181 int write_data_count = 0; 1182 uint32 read_data = 0; 1183 1184 array_length = sizeof(trident2p_write_data) / sizeof(uint32); 1185 WRITE_TOP_UC_TAP_CONTROLr(unit, 0x2e); 1186 WRITE_TOP_UC_TAP_CONTROLr(unit, 0x2e); 1187 WRITE_TOP_UC_TAP_CONTROLr(unit, 0x2f); 1188 READ_TOP_UC_TAP_CONTROLr(unit, &read_data); 1189 1190 for ( i=0; i < array_length; i++) 1191 { 1192 WRITE_TOP_UC_TAP_WRITE_DATAr(unit, trident2p_write_data[write_data_count]); 1193 WRITE_TOP_UC_TAP_CONTROLr(unit, 0x2f); 1194 READ_TOP_UC_TAP_READ_DATAr(unit, &read_data); 1195 write_data_count++; 1196 1197 } 1198 1199 WRITE_TOP_UC_TAP_CONTROLr(unit, 0x2f); 1200 WRITE_TOP_UC_TAP_CONTROLr(unit, 0x2e); 1201 WRITE_TOP_UC_TAP_CONTROLr(unit, 0x2c); 1202 1203 return; 1204 } 1205 1206 1207 /* 1208 * Function: 1209 * soc_td2p_idb_buf_reset 1210 * Purpose: 1211 * Poll until Cell Assembly and OBM buffers are empty. 1212 * Parameters: 1213 * unit - (IN) Unit number. 1214 * port - (IN) Logical SOC port number. 1215 * reset - (IN) Reset. 1216 * Returns: 1217 * SOC_E_XXX 1218 */ 1219 int 1220 soc_td2p_idb_buf_reset(int unit, soc_port_t port, int reset) 1221 { 1222 soc_info_t *si = &SOC_INFO(unit); 1223 soc_reg_t reg; 1224 soc_field_t field; 1225 uint64 rval64; 1226 int phy_port; 1227 int pgw; 1228 int xlp; 1229 int port_index; 1230 int obm; 1231 soc_timeout_t to; 1232 int use_count; 1233 int fifo_empty; 1234 static const soc_reg_t pgw_obm_use_counter_regs[] = { 1235 PGW_OBM0_USE_COUNTERr, PGW_OBM1_USE_COUNTERr, 1236 PGW_OBM2_USE_COUNTERr, PGW_OBM3_USE_COUNTERr 1237 }; 1238 static const soc_field_t pgw_obm_use_counter_fields[] = { 1239 PORT0_USE_COUNTf, PORT1_USE_COUNTf, 1240 PORT2_USE_COUNTf, PORT3_USE_COUNTf 1241 }; 1242 1243 /* If not reset, nothing to do */ 1244 if (!reset) { 1245 return SOC_E_NONE; 1246 } 1247 1248 /* Get physical port PGW information */ 1249 phy_port = si->port_l2p_mapping[port]; 1250 SOC_IF_ERROR_RETURN 1251 (soc_td2p_phy_port_pgw_info_get(unit, phy_port, 1252 &pgw, &xlp, &port_index)); 1253 1254 /* Assume values returned above are valid */ 1255 reg = pgw_obm_use_counter_regs[xlp]; 1256 field = pgw_obm_use_counter_fields[port_index]; 1257 obm = pgw | SOC_REG_ADDR_INSTANCE_MASK; 1258 1259 if (!SAL_BOOT_SIMULATION) { 1260 /* Poll until Cell Assembly and OBM buffers are empty */ 1261 soc_timeout_init(&to, 250000, 0); 1262 for (;;) { 1263 /* Get PGW use counter */ 1264 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, obm, port_index, 1265 &rval64)); 1266 use_count = soc_reg64_field32_get(unit, reg, rval64, field); 1267 1268 /* Get PGW fifo empty flag */ 1269 SOC_IF_ERROR_RETURN(READ_PGW_BOD_STATUS1r(unit, port, &rval64)); 1270 fifo_empty = soc_reg64_field32_get(unit, PGW_BOD_STATUS1r, 1271 rval64, PGW_BOD_FIFO_EMPTYf); 1272 1273 if ((use_count == 0) && (fifo_empty == 1)) { 1274 break; 1275 } 1276 1277 if (soc_timeout_check(&to)) { 1278 LOG_ERROR(BSL_LS_SOC_COMMON, 1279 (BSL_META_U(unit, 1280 "PGW buffer reset timeout: port %d, %s, " 1281 "timeout (use_count: %d) " 1282 "(pgw_bod_fifo_emty:%d)\n"), 1283 port, SOC_PORT_NAME(unit, port), 1284 use_count, fifo_empty)); 1285 return SOC_E_INTERNAL; 1286 } 1287 } 1288 } 1289 1290 return SOC_E_NONE; 1291 } 1292 1293 STATIC int 1294 _soc_td2p_port_credit_size_get(int unit, soc_port_t port, int *ep_credit_size) 1295 { 1296 int speed_max; 1297 1298 if (ep_credit_size == NULL) { 1299 return SOC_E_INTERNAL; 1300 } 1301 1302 SOC_IF_ERROR_RETURN( 1303 soc_td2p_port_speed_get(unit, port, &speed_max)); 1304 1305 if (IS_OVERSUB_PORT(unit, port)) { 1306 if (speed_max >= 100000) { 1307 return SOC_E_PARAM; 1308 } else if (speed_max >= 40000) { 1309 *ep_credit_size = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_OVERSUB(40G); 1310 } else if (speed_max >= 20000) { 1311 *ep_credit_size = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_OVERSUB(20G); 1312 } else { 1313 *ep_credit_size = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_OVERSUB(10G); 1314 } 1315 } else { 1316 if (speed_max >= 100000) { 1317 *ep_credit_size = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(100G); 1318 } else if (speed_max >= 40000) { 1319 *ep_credit_size = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(40G); 1320 } else if (speed_max >= 20000) { 1321 *ep_credit_size = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(20G); 1322 } else { 1323 *ep_credit_size = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(10G); 1324 } 1325 } 1326 1327 return SOC_E_NONE; 1328 } 1329 1330 /* 1331 * Function: 1332 * _soc_td2p_mmu_ep_credit_set 1333 * Purpose: 1334 * Initalize EP credits in MMU so EP is in charge 1335 * of distributing the correct number of credits. 1336 * Parameters: 1337 * unit - (IN) Unit number. 1338 * port - (IN) Logical SOC port number. 1339 * Returns: 1340 * SOC_E_XXX 1341 */ 1342 STATIC int 1343 _soc_td2p_mmu_ep_credit_set(int unit, soc_port_t port) 1344 { 1345 soc_info_t *si = &SOC_INFO(unit); 1346 int phy_port; 1347 int mmu_port; 1348 int ep_credit_size = 0; 1349 soc_reg_t reg; 1350 uint32 rval; 1351 1352 /* Get physical port */ 1353 phy_port = si->port_l2p_mapping[port]; 1354 if (phy_port == -1) { 1355 return SOC_E_INTERNAL; 1356 } 1357 1358 /* Get MMU port */ 1359 mmu_port = si->port_p2m_mapping[phy_port]; 1360 if (mmu_port == -1) { 1361 return SOC_E_INTERNAL; 1362 } 1363 mmu_port &= 0x3F; /* Convert mmu port number for pipe */ 1364 1365 /* Wait until credits are initialised at non-optimum value 1366 * EP passes MMU 1 credit per cycle, so worse case delay is 95 cycles after EGR_ENABLE is set. 1367 * @793.75MHz, this is ~120ns. 1368 */ 1369 sal_usleep(1); 1370 1371 if (SOC_PBMP_MEMBER(si->xpipe_pbm, port)) { 1372 reg = ES_PIPE0_MMU_PORT_CREDITr; 1373 } else { 1374 reg = ES_PIPE1_MMU_PORT_CREDITr; 1375 } 1376 1377 SOC_IF_ERROR_RETURN(_soc_td2p_port_credit_size_get(unit, port, &ep_credit_size)); 1378 SOC_IF_ERROR_RETURN 1379 (soc_reg32_get(unit, reg, REG_PORT_ANY, mmu_port, &rval)); 1380 soc_reg_field_set(unit, reg, &rval, INIT_CREDITf, ep_credit_size); 1381 SOC_IF_ERROR_RETURN 1382 (soc_reg32_set(unit, reg, REG_PORT_ANY, mmu_port, rval)); 1383 1384 return SOC_E_NONE; 1385 } 1386 1387 /* 1388 * Function: 1389 * _soc_td2p_mmu_ep_credit_reset 1390 * Purpose: 1391 * Reset EP credits 1392 * Parameters: 1393 * unit - (IN) Unit number. 1394 * port - (IN) Logical SOC port number. 1395 * Returns: 1396 * SOC_E_XXX 1397 */ 1398 STATIC int 1399 _soc_td2p_mmu_ep_credit_reset(int unit, soc_port_t port) 1400 { 1401 soc_info_t *si = &SOC_INFO(unit); 1402 int phy_port; 1403 int mmu_port; 1404 soc_reg_t reg; 1405 uint32 rval; 1406 1407 /* Get physical port */ 1408 phy_port = si->port_l2p_mapping[port]; 1409 if (phy_port == -1) { 1410 return SOC_E_INTERNAL; 1411 } 1412 1413 /* Get MMU port */ 1414 mmu_port = si->port_p2m_mapping[phy_port]; 1415 if (mmu_port == -1) { 1416 return SOC_E_INTERNAL; 1417 } 1418 mmu_port &= 0x3F; /* Convert mmu port number for pipe */ 1419 1420 if (SOC_PBMP_MEMBER(si->xpipe_pbm, port)) { 1421 reg = ES_PIPE0_MMU_PORT_CREDITr; 1422 } else { 1423 reg = ES_PIPE1_MMU_PORT_CREDITr; 1424 } 1425 1426 SOC_IF_ERROR_RETURN 1427 (soc_reg32_get(unit, reg, REG_PORT_ANY, mmu_port, &rval)); 1428 soc_reg_field_set(unit, reg, &rval, INIT_CREDITf, 0); 1429 SOC_IF_ERROR_RETURN 1430 (soc_reg32_set(unit, reg, REG_PORT_ANY, mmu_port, rval)); 1431 1432 return SOC_E_NONE; 1433 } 1434 1435 /* 1436 * Function: 1437 * soc_td2p_edb_buf_reset 1438 * Purpose: 1439 * Initialize EP credits in MMU, release EDB port buffer and 1440 * enable cell request in EP. 1441 * Parameters: 1442 * unit - (IN) Unit number. 1443 * port - (IN) Logical SOC port number. 1444 * reset - (IN) Reset. 1445 * Returns: 1446 * SOC_E_XXX 1447 */ 1448 int 1449 soc_td2p_edb_buf_reset(int unit, soc_port_t port, int reset) 1450 { 1451 soc_info_t *si = &SOC_INFO(unit); 1452 uint32 entry[SOC_MAX_MEM_WORDS]; 1453 int phy_port; 1454 int use_pfc_optimized_settings = FALSE; 1455 1456 /* Get physical port */ 1457 phy_port = si->port_l2p_mapping[port]; 1458 if (phy_port == -1) { 1459 return SOC_E_INTERNAL; 1460 } 1461 1462 if (reset) { 1463 /* 1464 * Hold EDB port buffer in reset state and disable cell 1465 * request generation in EP. 1466 */ 1467 SOC_IF_ERROR_RETURN 1468 (READ_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, entry)); 1469 soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, 0); 1470 SOC_IF_ERROR_RETURN 1471 (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, entry)); 1472 1473 SOC_IF_ERROR_RETURN 1474 (READ_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL, 1475 phy_port, entry)); 1476 soc_mem_field32_set(unit, EGR_PER_PORT_BUFFER_SFT_RESETm, 1477 entry, ENABLEf, 1); 1478 SOC_IF_ERROR_RETURN 1479 (WRITE_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL, 1480 phy_port, entry)); 1481 } else { 1482 1483 /* Initialize EP credits in MMU */ 1484 SOC_IF_ERROR_RETURN(_soc_td2p_mmu_ep_credit_reset(unit, port)); 1485 1486 /* If system is able to use optimized settings, set 1487 credit limit accordingly, else use default */ 1488 use_pfc_optimized_settings = soc_td2p_use_pfc_optimized_settings(unit); 1489 if (use_pfc_optimized_settings) { 1490 SOC_IF_ERROR_RETURN(soc_td2p_set_mmu_credit_limit(unit, port)); 1491 } 1492 1493 /* 1494 * Release EDB port buffer reset and 1495 * enable cell request generation in EP. 1496 */ 1497 SOC_IF_ERROR_RETURN 1498 (READ_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL, 1499 phy_port, entry)); 1500 soc_mem_field32_set(unit, EGR_PER_PORT_BUFFER_SFT_RESETm, 1501 entry, ENABLEf, 0); 1502 SOC_IF_ERROR_RETURN 1503 (WRITE_EGR_PER_PORT_BUFFER_SFT_RESETm(unit, MEM_BLOCK_ALL, 1504 phy_port, entry)); 1505 1506 SOC_IF_ERROR_RETURN 1507 (READ_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, entry)); 1508 soc_mem_field32_set(unit, EGR_ENABLEm, entry, PRT_ENABLEf, 1); 1509 SOC_IF_ERROR_RETURN 1510 (WRITE_EGR_ENABLEm(unit, MEM_BLOCK_ALL, phy_port, entry)); 1511 1512 /* If system is able to use optimized settings, set 1513 watermark thresh accordingly, else use default */ 1514 if (use_pfc_optimized_settings) { 1515 SOC_IF_ERROR_RETURN(_soc_td2p_mmu_ep_credit_set(unit, port)); 1516 SOC_IF_ERROR_RETURN( 1517 soc_td2p_set_edb_pfc_watermark_threshold(unit, port)); 1518 } 1519 } 1520 1521 return SOC_E_NONE; 1522 } 1523 1524 1525 STATIC int 1526 _soc_td2p_resource_data_check(int unit, int num_res, soc_port_resource_t *res) 1527 { 1528 int i, j; 1529 /* null check for all resource data before accessing register */ 1530 for (i = 0 ; i < num_res ; ++i) { 1531 soc_port_resource_t *p = &res[i]; 1532 if (NULL == p) { 1533 /* 1534 * COVERITY 1535 * It is kept intentionally as a defensive check. 1536 */ 1537 /* coverity[dead_error_line] */ 1538 return SOC_E_PARAM; 1539 } 1540 for (j = 0; j < p->num_lanes ; ++j) { 1541 soc_port_lane_info_t *p_lane_info = p->lane_info[j]; 1542 if (NULL == p_lane_info) { 1543 return SOC_E_PARAM; 1544 } 1545 } 1546 } 1547 return SOC_E_NONE; 1548 } 1549 1550 1551 /* 1552 * Function: 1553 * soc_td2p_pgw_obm_default_set 1554 * Purpose: 1555 * Reconfigure PGW registers in flex port sequence 1556 * In this function following registers will be initialized. 1557 * PGW_OBM[0-3]_CONTROL 1558 * PGW_OBM[0-3]_HIGH_PRI_BYTE_DROP[] 1559 * PGW_OBM[0-3]_HIGH_PRI_PKT_DROP[] 1560 * PGW_OBM[0-3]_LOW_PRI_BYTE_DROP[] 1561 * PGW_OBM[0-3]_LOW_PRI_DROP_PROB[] 1562 * PGW_OBM[0-3]_LOW_PRI_PKT_DROP[] 1563 * PGW_OBM[0-3]_USE_COUNTER 1564 * PGW_OBM[0-3]_SHARED_CONFIG 1565 * If default_flag is PGW_OBM_INIT_HW_DEFAULT, 1566 * register will be intialized by HW reset value 1567 * If default_flag is PGW_OBM_INIT_SW_DEFAULT, 1568 * register will be intialized by SW reset value 1569 * 1570 * Parameters: 1571 * unit - (IN) Unit number. 1572 * num_res - (IN) Number of resource 1573 * res - (IN) Resource data structure 1574 * default_flag - (IN) PGW_OBM_INIT_HW_DEFAULT 1575 * Use HW reset value for register value 1576 * - (IN) PGW_OBM_INIT_SW_DEFAULT 1577 * Use SW default value 1578 * 1579 * Assumption: 1580 * This function cannot access SOC_INFO data structure. 1581 * So assume followings condition should be checked 1582 * before calling this function. 1583 * 1584 * 1. master/slave pgw block is valid 1585 * si->block_valid[PGW_CL_BLOCK(unit, pgw)] is true 1586 * si->block_valid[PGW_CL_BLOCK(unit, pgw+1)] is true 1587 * 2. port block is used 1588 * block = PGW_CL_BLOCK(unit, pgw); 1589 * SOC_BLOCK_PORT(unit, block) < 0 1590 * 3. num_res should be correct number of resource data structure. 1591 * all resource data structure should be accessed by using 1592 * pointer offset by res_num. If the pointer of resource data is NULL, 1593 * returns SOC_E_PARAM. 1594 * 1595 * Returns: 1596 * SOC_E_XXX 1597 */ 1598 STATIC int 1599 soc_td2p_pgw_obm_default_set(int unit, int num_res, soc_port_resource_t *res, 1600 int default_flag) 1601 { 1602 int obm_inst; 1603 int xlp, port_index; 1604 int i, j; 1605 1606 for (i = 0 ; i < num_res ; ++i) { 1607 soc_port_resource_t *p = &res[i]; 1608 1609 for (j = 0; j < p->num_lanes ; ++j) { 1610 soc_port_lane_info_t *p_lane_info = p->lane_info[j]; 1611 1612 xlp = p_lane_info->xlp; 1613 port_index = p_lane_info->port_index; 1614 obm_inst = p_lane_info->pgw | SOC_REG_ADDR_INSTANCE_MASK; 1615 1616 /* PGW_OBM[0-3]_CONTROL */ 1617 SOC_IF_ERROR_RETURN 1618 (soc_td2_obm_ctrl_reg_default_set(unit, xlp, 1619 port_index, obm_inst, p->oversub, default_flag)); 1620 /* PGW_OBM[0-3]_LOW_PRI_DROP_PROB[] */ 1621 SOC_IF_ERROR_RETURN 1622 (soc_td2p_obm_prob_drop_default_set (unit, xlp, 1623 port_index, obm_inst, default_flag)); 1624 /* PGW_OBM[0-3]_HIGH_PRI_BYTE_DROP[] */ 1625 SOC_IF_ERROR_RETURN 1626 (soc_td2p_obm_high_pri_byte_drop_default_set(unit, xlp, 1627 port_index, obm_inst)); 1628 /* PGW_OBM[0-3]_HIGH_PRI_PKT_DROP[] */ 1629 SOC_IF_ERROR_RETURN 1630 (soc_td2p_obm_high_pri_pkt_drop_default_set(unit, xlp, 1631 port_index, obm_inst)); 1632 /* PGW_OBM[0-3]_LOW_PRI_BYTE_DROP[] */ 1633 SOC_IF_ERROR_RETURN 1634 (soc_td2p_obm_low_pri_byte_drop_default_set(unit, xlp, 1635 port_index, obm_inst)); 1636 /* PGW_OBM[0-3]_LOW_PRI_PKT_DROP[] */ 1637 SOC_IF_ERROR_RETURN 1638 (soc_td2p_obm_low_pri_pkt_drop_default_set(unit, xlp, 1639 port_index, obm_inst)); 1640 /* PGW_OBM[0-3]_USE_COUNTER */ 1641 SOC_IF_ERROR_RETURN 1642 (soc_td2_obm_use_counter_reg_default_set(unit, xlp, 1643 port_index, obm_inst)); 1644 /* PGW_OBM[0-3]_SHARED_CONFIG */ 1645 SOC_IF_ERROR_RETURN 1646 (soc_td2_obm_shared_config_reg_default_set(unit, xlp, 1647 port_index, obm_inst, default_flag)); 1648 } 1649 } 1650 return SOC_E_NONE; 1651 } 1652 1653 STATIC int 1654 soc_td2p_pgw_obm_hw_default_set(int unit, int num_res, soc_port_resource_t *res) 1655 { 1656 int rv; 1657 rv = soc_td2p_pgw_obm_default_set(unit, num_res, res, 1658 PGW_OBM_INIT_HW_DEFAULT); 1659 return rv; 1660 } 1661 1662 STATIC int 1663 soc_td2p_pgw_obm_sw_default_set(int unit, int num_res, soc_port_resource_t *res) 1664 { 1665 int rv; 1666 rv = soc_td2p_pgw_obm_default_set(unit, num_res, res, 1667 PGW_OBM_INIT_SW_DEFAULT); 1668 return rv; 1669 } 1670 1671 /* 1672 * Function: 1673 * soc_td2p_pgw_obm_set 1674 * Purpose: 1675 * Reconfigure PGW_OBM registers in flex port sequence 1676 * This function will do two things, 1677 * 1. clear all registers for old ports which exists in pre-Flex status 1678 * 2. initialize all registers for new ports which exists in post-Flex status 1679 * 1680 * Parameters: 1681 * unit - (IN) Unit number. 1682 * pre_num_res - (IN) Number of resource data which exist in pre-Flex status 1683 * post_num_res - (IN) Number of resource data which exist in post-Flex status 1684 * pre_res - (IN) Resource data structure pointer in pre-Flex status 1685 * post_res - (IN) Resource data structure pointer in post-Flex status 1686 * 1687 * Returns: 1688 * SOC_E_XXX 1689 */ 1690 int 1691 soc_td2p_pgw_obm_set(int unit, 1692 int pre_num_res, soc_port_resource_t *pre_res, 1693 int post_num_res, soc_port_resource_t *post_res) 1694 { 1695 SOC_IF_ERROR_RETURN( 1696 _soc_td2p_resource_data_check(unit, pre_num_res, pre_res)); 1697 SOC_IF_ERROR_RETURN( 1698 _soc_td2p_resource_data_check(unit, post_num_res, post_res)); 1699 1700 SOC_IF_ERROR_RETURN(soc_td2p_pgw_obm_hw_default_set(unit, 1701 pre_num_res, pre_res)); 1702 SOC_IF_ERROR_RETURN(soc_td2p_pgw_obm_sw_default_set(unit, 1703 post_num_res, post_res)); 1704 return SOC_E_NONE; 1705 } 1706 1707 1708 /* 1709 * Function: 1710 * soc_td2p_obm_threshold_default_set 1711 * Purpose: 1712 * Reconfigure PGW Threshold in flex port sequence 1713 * In this function following registers will be initialized. 1714 * PGW_OBM[0-3]_THRESHOLD 1715 * PGW_OBM[0-3]_THRESHOLD2 1716 * If default_flag is PGW_OBM_INIT_HW_DEFAULT, 1717 * register will be intialized by HW reset value 1718 * If default_flag is PGW_OBM_INIT_SW_DEFAULT, 1719 * register will be intialized by SW reset value 1720 * 1721 * Parameters: 1722 * unit - (IN) Unit number 1723 * num_res - (IN) Number of resource 1724 * res - (IN) Resource data structure 1725 * lossless - (IN) Lossless configuration of device 1726 * default_flag - (IN) PGW_OBM_INIT_HW_DEFAULT 1727 * Use HW reset value for register value 1728 * - (IN) PGW_OBM_INIT_SW_DEFAULT 1729 * Use SW default value 1730 * 1731 * Assumption: 1732 * This function cannot access SOC_INFO data structure. 1733 * So assume followings condition should be checked 1734 * before calling this function. 1735 * 1736 * 1. master/slave pgw block is valid 1737 * si->block_valid[PGW_CL_BLOCK(unit, pgw)] is true 1738 * si->block_valid[PGW_CL_BLOCK(unit, pgw+1)] is true 1739 * 2. port block is used 1740 * block = PGW_CL_BLOCK(unit, pgw); 1741 * SOC_BLOCK_PORT(unit, block) < 0 1742 * 3. num_res should be correct number of resource data structure. 1743 * all resource data structure should be accessed by using 1744 * pointer offset by res_num. If the pointer of resource data is NULL, 1745 * returns SOC_E_PARAM. 1746 * 1747 * Returns: 1748 * SOC_E_XXX 1749 */ 1750 STATIC 1751 soc_error_t soc_td2p_obm_threshold_default_set(int unit, 1752 int num_res, 1753 soc_port_resource_t *res, 1754 int lossless, 1755 int default_flag) 1756 { 1757 pgw_obm_threshold_regs_t pgw_obm_threshold_regs = 1758 soc_trident2_pgw_obm_threshold_regs_get(unit); 1759 soc_reg_t reg; 1760 int obm_inst; 1761 int xlp, port_index, speed; 1762 int i, j; 1763 1764 for (i = 0 ; i < num_res ; ++i) { 1765 soc_port_resource_t *p = &res[i]; 1766 1767 speed = p->speed; 1768 for (j = 0; j < p->num_lanes ; ++j) { 1769 soc_port_lane_info_t *p_lane_info = p->lane_info[j]; 1770 1771 xlp = p_lane_info->xlp; 1772 port_index = p_lane_info->port_index; 1773 obm_inst = p_lane_info->pgw | SOC_REG_ADDR_INSTANCE_MASK; 1774 1775 reg = pgw_obm_threshold_regs[xlp]; 1776 /* PGW_OBM[0-3]_THRESHOLD */ 1777 SOC_IF_ERROR_RETURN 1778 (soc_td2p_set_obm_registers(unit, reg, speed, port_index, 1779 obm_inst, lossless, default_flag)); 1780 1781 /* PGW_OBM[0-3]_THRESHOLD2 */ 1782 SOC_IF_ERROR_RETURN 1783 (soc_td2p_obm_cut_through_threshold_set(unit, xlp, port_index, 1784 obm_inst, default_flag)); 1785 } 1786 } 1787 1788 return SOC_E_NONE; 1789 } 1790 1791 STATIC int 1792 soc_td2p_obm_threshold_hw_default_set(int unit, int num_res, 1793 soc_port_resource_t *res, 1794 int lossless) 1795 { 1796 1797 SOC_IF_ERROR_RETURN(soc_td2p_obm_threshold_default_set(unit, num_res, res, 1798 lossless, 1799 PGW_OBM_INIT_HW_DEFAULT)); 1800 return SOC_E_NONE; 1801 } 1802 1803 STATIC int 1804 soc_td2p_obm_threshold_sw_default_set(int unit, int num_res, 1805 soc_port_resource_t *res, 1806 int lossless) 1807 { 1808 SOC_IF_ERROR_RETURN(soc_td2p_obm_threshold_default_set(unit, num_res, res, 1809 lossless, 1810 PGW_OBM_INIT_SW_DEFAULT)); 1811 return SOC_E_NONE; 1812 } 1813 1814 /* 1815 * Function: 1816 * soc_td2p_obm_threshold_set 1817 * Purpose: 1818 * Reconfigure PGW registers in flex port sequence 1819 * In this function PGW OBM threshold registers will be initialized. 1820 * This function will do two things, 1821 * 1. clear all registers for old ports which exists in pre-Flex status 1822 * 2. initialize all registers for new ports which exists in post-Flex status 1823 * 1824 * Parameters: 1825 * unit - (IN) Unit number. 1826 * pre_num_res - (IN) Number of resource data which exist in pre-Flex status 1827 * post_num_res - (IN) Number of resource data which exist in post-Flex status 1828 * pre_res - (IN) Resource data structure pointer in pre-Flex status 1829 * post_res - (IN) Resource data structure pointer in post-Flex status 1830 * lossless - (IN) mmu lossless information 1831 * 1832 * Returns: 1833 * SOC_E_XXX 1834 * 1835 * Note : For 100G port, this functions expects the ovsersub field to be 1836 * disabled. 1837 */ 1838 soc_error_t soc_td2p_obm_threshold_set(int unit, 1839 int pre_num_res, soc_port_resource_t *pre_res, 1840 int post_num_res, soc_port_resource_t *post_res, 1841 int lossless) 1842 { 1843 1844 SOC_IF_ERROR_RETURN(_soc_td2p_resource_data_check(unit, pre_num_res, 1845 pre_res)); 1846 SOC_IF_ERROR_RETURN(_soc_td2p_resource_data_check(unit, post_num_res, 1847 post_res)); 1848 SOC_IF_ERROR_RETURN(soc_td2p_obm_threshold_hw_default_set(unit, 1849 pre_num_res, pre_res, lossless)); 1850 1851 SOC_IF_ERROR_RETURN(soc_td2p_obm_threshold_sw_default_set(unit, 1852 post_num_res, post_res, lossless)); 1853 1854 return SOC_E_NONE; 1855 } 1856 1857 1858 /* 1859 * Function: 1860 * soc_td2p_pgw_port_default_set 1861 * Purpose: 1862 * Reconfigure PGW registers in flex port sequence 1863 * In this function following registers will be initialized. 1864 * PGW_OBM[0-3]_MAX_USAGE: 1865 * PGW_OBM_PORT[0-15]_FC_CONFIG 1866 * PGW_OBM[0-3]_PRIORITY_MAP[] 1867 * If default_flag is PGW_OBM_INIT_HW_DEFAULT, 1868 * register will be intialized by HW reset value 1869 * If default_flag is PGW_OBM_FLEXPORT_INIT_SW_DEFAULT, 1870 * register will be intialized by SW reset value 1871 * 1872 * Parameters: 1873 * unit - (IN) Unit number. 1874 * num_res - (IN) Number of resource 1875 * res - (IN) Resource data structure 1876 * default_flag - (IN) PGW_OBM_INIT_HW_DEFAULT 1877 * Use HW reset value for register value 1878 * - (IN) PGW_OBM_FLEXPORT_INIT_SW_DEFAULT 1879 * Use SW default value 1880 * lossless - (IN) mmu lossless information 1881 * 1882 * Assumption: 1883 * This function cannot access SOC_INFO data structure. 1884 * So assume followings condition should be checked 1885 * before calling this function. 1886 * 1887 * 1. master/slave pgw block is valid 1888 * si->block_valid[PGW_CL_BLOCK(unit, pgw)] is true 1889 * si->block_valid[PGW_CL_BLOCK(unit, pgw+1)] is true 1890 * 2. port block is used 1891 * block = PGW_CL_BLOCK(unit, pgw); 1892 * SOC_BLOCK_PORT(unit, block) < 0 1893 * 3. num_res should be correct number of resource data structure. 1894 * all resource data structure should be accessed by using 1895 * pointer offset by res_num. If the pointer of resource data is NULL, 1896 * returns SOC_E_PARAM. 1897 * 1898 * Returns: 1899 * SOC_E_XXX 1900 */ 1901 STATIC int 1902 soc_td2p_pgw_port_default_set(int unit, int num_res, soc_port_resource_t *res, 1903 int lossless, int default_flag) 1904 { 1905 int obm_inst; 1906 int xlp, port_index; 1907 int i, j; 1908 1909 for (i = 0 ; i < num_res ; ++i) { 1910 soc_port_resource_t *p = &res[i]; 1911 1912 for (j = 0; j < p->num_lanes ; ++j) { 1913 soc_port_lane_info_t *p_lane_info = p->lane_info[j]; 1914 1915 xlp = p_lane_info->xlp; 1916 port_index = p_lane_info->port_index; 1917 1918 obm_inst = p_lane_info->pgw | SOC_REG_ADDR_INSTANCE_MASK; 1919 1920 /* PGW_MIB_RESET */ 1921 SOC_IF_ERROR_RETURN(soc_td2p_pgw_mib_reset_reg_default_set( 1922 unit, xlp, port_index, obm_inst)); 1923 1924 /* PGW_OBM[0-3]_MAX_USAGE */ 1925 SOC_IF_ERROR_RETURN 1926 (soc_td2_obm_max_usage_reg_default_set(unit, xlp, 1927 port_index, obm_inst)); 1928 1929 if (!lossless) { 1930 continue; 1931 } 1932 1933 /* PGW_OBM_PORT[0-15]_FC_CONFIG */ 1934 SOC_IF_ERROR_RETURN 1935 (soc_td2_obm_fc_config_reg_default_set(unit, xlp, port_index, 1936 obm_inst, p->logical_port, p->oversub, 1937 default_flag)); 1938 } 1939 } 1940 1941 return SOC_E_NONE; 1942 } 1943 1944 STATIC int 1945 soc_td2p_pgw_port_hw_default_set(int unit, int num_res, soc_port_resource_t *res, 1946 int lossless) 1947 { 1948 int rv; 1949 rv = soc_td2p_pgw_port_default_set(unit, num_res, res, 1950 lossless, PGW_OBM_INIT_HW_DEFAULT); 1951 return rv; 1952 } 1953 1954 STATIC int 1955 soc_td2p_pgw_port_sw_default_set(int unit, int num_res, soc_port_resource_t *res, 1956 int lossless) 1957 { 1958 int rv; 1959 rv = soc_td2p_pgw_port_default_set(unit, num_res, res, 1960 lossless, PGW_OBM_INIT_SW_DEFAULT); 1961 return rv; 1962 } 1963 1964 1965 STATIC 1966 int soc_td2p_ovr_sub_tdm_config_get(int unit, 1967 _soc_td2p_ovr_sub_tdm_t *ovs_tdm) 1968 { 1969 int pipe; 1970 int group; 1971 int slot; 1972 uint32 wt_group_select; 1973 soc_reg_t reg; 1974 uint32 rval; 1975 int index; 1976 mmu_ovs_group_wt_regs_t mmu_ovs_group_wt_regs = 1977 mmu_ovs_group_wt_regs_td2p_local; 1978 _soc_td2p_ovr_sub_mmu_tdm_t *mmu_tdm = &ovs_tdm->mmu_tdm; 1979 mmu_ovs_group_regs_t mmu_ovs_group_regs = 1980 soc_trident2_mmu_ovs_group_regs_get(unit); 1981 mmu_ovs_group_wt_select_regs_t mmu_ovs_group_wt_select_regs = 1982 soc_trident2_mmu_ovs_group_wt_select_regs_get(unit); 1983 1984 /* Initialize MMU OverSub TDM Ports Database */ 1985 for (pipe = 0; pipe < TD2P_PIPES_PER_DEV; pipe++) { 1986 for (group = 0; group < GET_MMU_OVS_GCOUNT(unit); group++) { 1987 for (slot = 0; slot < _MMU_OVS_GROUP_TDM_LENGTH; slot++) { 1988 /* Invalid MMU Port 0x3f */ 1989 mmu_tdm->mmu_port[pipe][group][slot] = 0x3f; 1990 } 1991 } 1992 } 1993 1994 /* Extract MMU Over Subscription TDM */ 1995 for (pipe = 0; pipe < TD2P_PIPES_PER_DEV; pipe++) { 1996 wt_group_select = 0; 1997 SOC_IF_ERROR_RETURN 1998 (soc_reg32_get(unit, mmu_ovs_group_wt_select_regs[pipe], 1999 REG_PORT_ANY, 0, &wt_group_select)); 2000 2001 for (group = 0; group < GET_MMU_OVS_GCOUNT(unit); group++) { 2002 reg = mmu_ovs_group_regs[pipe][group]; 2003 for (slot = 0; slot < _MMU_OVS_GROUP_TDM_LENGTH; slot++) { 2004 SOC_IF_ERROR_RETURN 2005 (soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval)); 2006 mmu_tdm->mmu_port[pipe][group][slot] = 2007 soc_reg_field_get(unit, reg, rval, MMU_PORTf); 2008 } 2009 } 2010 /* TD2P supports 4 oversub speeds only 10/20 and 40*/ 2011 for (group = 0; group < _MMU_OVS_WT_GROUP_COUNT; group++) { 2012 reg = mmu_ovs_group_wt_regs[pipe][group]; 2013 for (index = 0; index < _MMU_OVS_GROUP_TDM_LENGTH; index++) { 2014 SOC_IF_ERROR_RETURN 2015 (soc_reg32_get(unit, reg, REG_PORT_ANY, index, &rval)); 2016 mmu_tdm->grp_wt[pipe][group][index] = 2017 soc_reg_field_get(unit, reg, rval, WEIGHTf); 2018 } 2019 } 2020 /*Read the Group Weight Sel fields, Used later while 2021 * configuring the MMU TDM. 2022 */ 2023 for (group = 0; group < MAX_MMU_OVS_GROUP_COUNT; group++) { 2024 mmu_tdm->grp_wt_sel[pipe][group] = 2025 soc_reg_field_get(unit, mmu_ovs_group_wt_select_regs[pipe], 2026 wt_group_select, 2027 mmu_ovr_group_wt_select_fields[group]); 2028 } 2029 } 2030 2031 return SOC_E_NONE; 2032 } 2033 2034 2035 /* TD2P OverSub Scheduler */ 2036 /* For Egress MMU OvrSub schedular configuration, we need to create weight 2037 * group for each port speed. 2038 * If we didn't have a Port speed setup in the config file and during flex 2039 * operation, if we want to setup a port with new speed(Eg:40) we need to 2040 * create a new group. This functions sets up the Weight configuration. 2041 */ 2042 STATIC 2043 int soc_td2p_ovr_sub_tdm_mmu_group_create(int unit, int pipe, int speed_max, 2044 _soc_td2p_ovr_sub_tdm_t *ovs_tdm, 2045 int *group_new) 2046 { 2047 mmu_ovs_group_regs_t mmu_ovs_group_regs = 2048 soc_trident2_mmu_ovs_group_regs_get(unit); 2049 mmu_ovs_group_wt_select_regs_t mmu_ovs_group_wt_select_regs = 2050 soc_trident2_mmu_ovs_group_wt_select_regs_get(unit); 2051 mmu_ovs_group_wt_regs_t mmu_ovs_group_wt_regs = 2052 mmu_ovs_group_wt_regs_td2p_local; 2053 _soc_td2p_ovr_sub_mmu_tdm_t *mmu_tdm = &ovs_tdm->mmu_tdm; 2054 int index; 2055 int group; 2056 int slot; 2057 int wt_group = 0; 2058 soc_reg_t reg; 2059 uint32 rval; 2060 int weight; 2061 2062 for (group = 0; group < GET_MMU_OVS_GCOUNT(unit); group++) { 2063 if (mmu_tdm->grp_wt_sel[pipe][group] == td2p_ovs_wt_group_speed_NA) { 2064 /* This is an empty group, Initialize the group */ 2065 break; 2066 } 2067 } 2068 2069 if (group == GET_MMU_OVS_GCOUNT(unit)) { 2070 /* No Groups Available, Hence return SOC_E_RESOURCE */ 2071 return SOC_E_RESOURCE; 2072 } 2073 reg = mmu_ovs_group_regs[pipe][group]; 2074 2075 /* Initialize the MMU port to 0x3f for all the slots */ 2076 for (slot = 0; slot < _MMU_OVS_GROUP_TDM_LENGTH; slot++) { 2077 rval = 0; 2078 soc_reg_field_set(unit, reg, &rval, MMU_PORTf, 0x3f); 2079 SOC_IF_ERROR_RETURN 2080 (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval)); 2081 } 2082 2083 if ( speed_max <= 11000 ) { 2084 wt_group = td2p_ovs_wt_group_speed_10G; 2085 } else if ( speed_max <= 21000 ) { 2086 wt_group = td2p_ovs_wt_group_speed_20G; 2087 } else if ( speed_max <= 42000 ) { 2088 wt_group = td2p_ovs_wt_group_speed_40G; 2089 } else { 2090 wt_group = td2p_ovs_wt_group_speed_NA; /* "not" valid group */ 2091 } 2092 /* use 2500M as weight unit */ 2093 weight = (speed_max > 2500 ? speed_max : 2500) / 2500; 2094 2095 /* Read the Current OverSub Group Select Register per pipe, and assign the 2096 * group_weight for this group*/ 2097 rval = 0; 2098 SOC_IF_ERROR_RETURN 2099 (soc_reg32_get(unit, mmu_ovs_group_wt_select_regs [pipe], 2100 REG_PORT_ANY, 0, &rval)); 2101 /* Clear the Existing Weight, and append the new weight */ 2102 soc_reg_field_set(unit, mmu_ovs_group_wt_select_regs [pipe], 2103 &rval, mmu_ovr_group_wt_select_fields[group], wt_group); 2104 SOC_IF_ERROR_RETURN 2105 (soc_reg32_set(unit, mmu_ovs_group_wt_select_regs [pipe], 2106 REG_PORT_ANY, 0, rval)); 2107 2108 /* For the new Group, set the weight for all it's entries */ 2109 rval = 0; 2110 reg = mmu_ovs_group_wt_regs[pipe][wt_group]; 2111 for (index = 0; index < _MMU_OVS_GROUP_TDM_LENGTH; index++) { 2112 soc_reg_field_set(unit, reg, &rval, WEIGHTf, 2113 weight * (index + 1)); 2114 SOC_IF_ERROR_RETURN 2115 (soc_reg32_set(unit, reg, REG_PORT_ANY, index, rval)); 2116 } 2117 *group_new = group; 2118 return SOC_E_NONE; 2119 } 2120 2121 2122 2123 2124 /* TD2P OverSub Scheduler */ 2125 /* This function expects the oversub field in port_resource_t structure to be 0 2126 * for 100G ports. Since oversub on 100G ports is not supported for TD2Plus. 2127 * 2128 * This function Updates the Over Sub TDM calender. 2129 */ 2130 STATIC 2131 int soc_td2p_ovr_sub_tdm_db_update(int unit, int num_port_res, 2132 soc_port_resource_t *port_res, 2133 _soc_td2p_ovr_sub_tdm_t *ovs_tdm, 2134 int db_type) 2135 { 2136 int pipe, res_count; 2137 int group; 2138 int slot = 0; 2139 int count; 2140 int speed_max; 2141 int group_wt; 2142 int mmu_port, mmu_port_update; 2143 _soc_td2p_ovr_sub_mmu_tdm_t *mmu_tdm = &ovs_tdm->mmu_tdm; 2144 2145 for ( res_count = 0; res_count < num_port_res; res_count++) { 2146 soc_port_resource_t *p = &port_res[res_count]; 2147 2148 /* If OBM is not enabled then continue */ 2149 if (!p->oversub) { 2150 continue; 2151 } 2152 2153 if (p->flags & SOC_PORT_RESOURCE_INACTIVE) { 2154 continue; 2155 } 2156 2157 speed_max = p->speed; 2158 pipe = p->pipe; 2159 2160 if (_SOC_TRIDENT2P_UPDATE_TDM_PRE == db_type) { 2161 mmu_port = p->mmu_port & 0x3f; 2162 mmu_port_update = 0x3f; /* Invalid MMU Port */ 2163 } else { 2164 mmu_port = 0x3f; 2165 mmu_port_update = p->mmu_port & 0x3f; /* Valid MMU Port */ 2166 } 2167 2168 if ( speed_max <= 11000 ) { 2169 group_wt = td2p_ovs_wt_group_speed_10G; 2170 } else if ( speed_max <= 21000 ) { 2171 group_wt = td2p_ovs_wt_group_speed_20G; 2172 } else if ( speed_max <= 42000 ) { 2173 group_wt = td2p_ovs_wt_group_speed_40G; 2174 } else { 2175 group_wt = td2p_ovs_wt_group_speed_NA; /* "not" valid group */ 2176 } 2177 2178 /* Update MMU OverSub TDM Ports Database */ 2179 count = 0; 2180 for (group = 0; group < GET_MMU_OVS_GCOUNT(unit); group++) { 2181 /* Identify the group that needs to be updated */ 2182 if (mmu_tdm->grp_wt_sel[pipe][group] != group_wt) { 2183 continue; 2184 } 2185 /* Update MMU OverSub TDM Ports Database */ 2186 for (slot = 0; slot < _MMU_OVS_GROUP_TDM_LENGTH; slot++) { 2187 /* Invalid MMU Port 0x3f */ 2188 if (mmu_tdm->mmu_port[pipe][group][slot] == mmu_port) { 2189 count++; 2190 break; 2191 } 2192 } 2193 if (count) { 2194 break; 2195 } 2196 } 2197 2198 if (group == GET_MMU_OVS_GCOUNT(unit) && 2199 (_SOC_TRIDENT2P_UPDATE_TDM_PRE != db_type)) { 2200 /* Group (or) Free slot not found. 2201 * Need to allocate a new group if available */ 2202 2203 SOC_IF_ERROR_RETURN( 2204 soc_td2p_ovr_sub_tdm_mmu_group_create(unit, pipe, 2205 speed_max, ovs_tdm, &group)); 2206 2207 /* Start from the begining slot */ 2208 mmu_tdm->grp_wt_sel[pipe][group] = group_wt; 2209 slot = 0; 2210 count = 1; 2211 2212 /* MMU Port should be configured only once */ 2213 if (1 != count) { 2214 LOG_ERROR(BSL_LS_SOC_PORT, 2215 (BSL_META_U(unit, 2216 "MMU port %d cannot be found in MMU OVS GROUP TABLE: " 2217 "ES_PIPE_OVR_SUB_GRP_TBL\n"), 2218 mmu_port)); 2219 return SOC_E_PARAM; 2220 } 2221 } 2222 2223 /* Update the MMU_PORT */ 2224 mmu_tdm->tdm_update[pipe][group][slot] = 1; 2225 mmu_tdm->mmu_port[pipe][group][slot] = mmu_port_update; 2226 } 2227 return SOC_E_NONE; 2228 } 2229 2230 STATIC 2231 int soc_td2p_ovr_sub_tdm_hw_update(int unit, 2232 _soc_td2p_ovr_sub_tdm_t *ovs_tdm) 2233 { 2234 int pgw_master; 2235 int pipe; 2236 int group; 2237 int slot; 2238 int index = 0; 2239 int pgw; 2240 int base; 2241 soc_reg_t reg; 2242 uint32 rval; 2243 uint64 rval64, ctrl_rval64; 2244 int obm_inst; 2245 int phy_port; 2246 int count = 0; 2247 _soc_td2p_ovr_sub_mmu_tdm_t *mmu_tdm = &ovs_tdm->mmu_tdm; 2248 mmu_ovs_group_regs_t mmu_ovs_group_regs = 2249 soc_trident2_mmu_ovs_group_regs_get(unit); 2250 pgw_ovs_tdm_regs_t pgw_ovs_tdm_regs = 2251 soc_trident2_pgw_ovs_tdm_regs_get(unit); 2252 pgw_tdm_fields_t pgw_tdm_fields = 2253 soc_trident2_pgw_tdm_fields_get(unit); 2254 pgw_ovs_spacing_regs_t pgw_ovs_spacing_regs = 2255 soc_trident2_pgw_ovs_spacing_regs_get(unit); 2256 pgw_spacing_fields_t pgw_spacing_fields = 2257 soc_trident2_pgw_spacing_fields_get(unit); 2258 _soc_trident2_tdm_t *tdm; 2259 2260 tdm = soc_td2_td2p_tdm_sched_info_get(unit, 0); 2261 if (tdm == NULL) { 2262 return SOC_E_INIT; 2263 } 2264 2265 2266 /* Initialize MMU OverSub TDM Ports Database */ 2267 for (pipe = 0; pipe < TD2P_PIPES_PER_DEV; pipe++) { 2268 for (group = 0; group < GET_MMU_OVS_GCOUNT(unit); group++) { 2269 for (slot = 0; slot < _MMU_OVS_GROUP_TDM_LENGTH; slot++) { 2270 if (mmu_tdm->tdm_update[pipe][group][slot]) { 2271 /* Invalid MMU Port 0x3f */ 2272 reg = mmu_ovs_group_regs[pipe][group]; 2273 2274 SOC_IF_ERROR_RETURN 2275 (soc_reg32_get(unit, reg, REG_PORT_ANY, slot, &rval)); 2276 2277 soc_reg_field_set(unit, reg, &rval, MMU_PORTf, 2278 mmu_tdm->mmu_port[pipe][group][slot] & 0x3f); 2279 SOC_IF_ERROR_RETURN 2280 (soc_reg32_set(unit, reg, REG_PORT_ANY, slot, rval)); 2281 } 2282 } 2283 } 2284 } 2285 2286 /* Extract PGW Over Subscription TDM */ 2287 for (pgw = 0; pgw < TD2P_PGWS_PER_DEV; pgw += TD2P_PGWS_PER_QUAD) { 2288 pgw_master = pgw; 2289 2290 if (( pgw == 2 ) || ( pgw == 6 )) { 2291 pgw_master = pgw + 1; 2292 } 2293 2294 obm_inst = pgw_master | SOC_REG_ADDR_INSTANCE_MASK; 2295 2296 /* Update PGW oversubscription ports TDM */ 2297 count = 0; 2298 SOC_IF_ERROR_RETURN(soc_reg_get(unit, PGW_TDM_CONTROLr, obm_inst, 0, 2299 &ctrl_rval64)); 2300 for (base = 0; base < _PGW_TDM_OVS_SIZE; 2301 base += _PGW_TDM_SLOTS_PER_REG) { 2302 reg = pgw_ovs_tdm_regs[base / _PGW_TDM_SLOTS_PER_REG]; 2303 COMPILER_64_ZERO(rval64); 2304 for (index = 0; index < _PGW_TDM_SLOTS_PER_REG; index++) { 2305 slot = base + index; 2306 phy_port = tdm->pgw_ovs_tdm[pgw_master / 2][slot]; 2307 if (phy_port == NUM_EXT_PORTS) { 2308 phy_port = 0xff; 2309 } else { 2310 count++; 2311 } 2312 soc_reg64_field32_set(unit, reg, &rval64, pgw_tdm_fields[slot], 2313 phy_port); 2314 } 2315 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, obm_inst, 0, 2316 rval64)); 2317 } 2318 soc_reg64_field32_set(unit, PGW_TDM_CONTROLr, &ctrl_rval64, 2319 OS_TDM_ENABLEf, count ? 1 : 0); 2320 SOC_IF_ERROR_RETURN 2321 (soc_reg_set(unit, PGW_TDM_CONTROLr, obm_inst, 0, ctrl_rval64)); 2322 2323 /* Configure PGW oversubscription port spacing */ 2324 for (base = 0; base < _PGW_TDM_OVS_SIZE; 2325 base += _PGW_TDM_SLOTS_PER_REG) { 2326 reg = pgw_ovs_spacing_regs[base / _PGW_TDM_SLOTS_PER_REG]; 2327 COMPILER_64_ZERO(rval64); 2328 for (index = 0; index < _PGW_TDM_SLOTS_PER_REG; index++) { 2329 slot = base + index; 2330 phy_port = tdm->pgw_ovs_spacing[pgw_master / 2][slot]; 2331 soc_reg64_field32_set(unit, reg, &rval64, 2332 pgw_spacing_fields[slot], phy_port); 2333 } 2334 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, obm_inst, 0, rval64)); 2335 } 2336 } 2337 return SOC_E_NONE; 2338 } 2339 2340 /* 2341 * Function: 2342 * soc_td2p_ovr_sub_tdm_update 2343 * Description: 2344 * Update PGW and MMU TDM Over subscription programming for flex port 2345 * Parameters: 2346 * unit - Device number 2347 * pre_num_res - Number of Previous resources 2348 * pre_res - Previous resource information. 2349 * post_num_res - Number of Current resource configured 2350 * post_res - Current port resource information. 2351 */ 2352 int 2353 soc_td2p_ovr_sub_tdm_update(int unit, 2354 int pre_num_res, soc_port_resource_t *pre_res, 2355 int post_num_res, soc_port_resource_t *post_res) 2356 { 2357 _soc_td2p_ovr_sub_tdm_t *ovr_sub_tdm; 2358 int rv; 2359 2360 2361 SOC_IF_ERROR_RETURN(_soc_td2p_resource_data_check(unit, pre_num_res, 2362 pre_res)); 2363 SOC_IF_ERROR_RETURN(_soc_td2p_resource_data_check(unit, post_num_res, 2364 post_res)); 2365 2366 ovr_sub_tdm = sal_alloc(sizeof(_soc_td2p_ovr_sub_tdm_t), "ovr_sub_tdm"); 2367 if (ovr_sub_tdm == NULL) { 2368 return SOC_E_MEMORY; 2369 } 2370 sal_memset(ovr_sub_tdm, 0, sizeof(_soc_td2p_ovr_sub_tdm_t)); 2371 2372 /* Recover the Over_Sub PGW and MMU TDM configuration from registers. 2373 * Construct software database. 2374 */ 2375 rv = soc_td2p_ovr_sub_tdm_config_get(unit, ovr_sub_tdm); 2376 if (SOC_FAILURE(rv)) { 2377 sal_free(ovr_sub_tdm); 2378 return rv; 2379 } 2380 2381 /* Update the Pre OBM TDM configuration 2382 * Free's the pre-occupied slots*/ 2383 rv = soc_td2p_ovr_sub_tdm_db_update(unit, pre_num_res, pre_res, ovr_sub_tdm, 2384 _SOC_TRIDENT2P_UPDATE_TDM_PRE); 2385 if (SOC_FAILURE(rv)) { 2386 sal_free(ovr_sub_tdm); 2387 return rv; 2388 } 2389 2390 /* Update the Post OBM TDM configuration 2391 * Updates the Empty slots*/ 2392 rv = soc_td2p_ovr_sub_tdm_db_update(unit, post_num_res, post_res, ovr_sub_tdm, 2393 _SOC_TRIDENT2P_UPDATE_TDM_POST); 2394 if (SOC_FAILURE(rv)) { 2395 sal_free(ovr_sub_tdm); 2396 return rv; 2397 } 2398 2399 /* Updates the OBM TDM configuration in the Hardware */ 2400 rv = soc_td2p_ovr_sub_tdm_hw_update(unit, ovr_sub_tdm); 2401 if (SOC_FAILURE(rv)) { 2402 sal_free(ovr_sub_tdm); 2403 return rv; 2404 } 2405 2406 sal_free(ovr_sub_tdm); 2407 return SOC_E_NONE; 2408 } 2409 2410 2411 /* 2412 * Function: 2413 * soc_td2p_egr_edb_xmit_ctrl_set 2414 * 2415 * Description: 2416 * Program EGR_EDB_XMIT_CTRL memory by considering 2417 * Oversub/Linerate mode and Cut-Through/SAF mode 2418 * 2419 * Parameters: 2420 * unit - Device number 2421 * phy_port - Physical port 2422 * speed - Port speed 2423 * oversub - Oversub is enabled or not 2424 * cut_thru_enable - Cut through mode is enabled or not 2425 */ 2426 int soc_td2p_egr_edb_xmit_ctrl_set(int unit, int phy_port, int speed, 2427 int oversub, int cut_thru_enable) 2428 { 2429 soc_info_t *si; 2430 uint32 entry[SOC_MAX_MEM_WORDS]; 2431 soc_field_t reg_field; 2432 int start_cnt_val = 0; 2433 2434 si = &SOC_INFO(unit); 2435 sal_memset(entry, 0, sizeof(egr_edb_xmit_ctrl_entry_t)); 2436 SOC_IF_ERROR_RETURN(soc_mem_read(unit, EGR_EDB_XMIT_CTRLm, MEM_BLOCK_ALL, 2437 phy_port, &entry)); 2438 if (!cut_thru_enable) { 2439 if (oversub) { 2440 reg_field = WAIT_FOR_2ND_MOPf; 2441 } else { 2442 reg_field = WAIT_FOR_MOPf; 2443 } 2444 soc_mem_field32_set(unit, EGR_EDB_XMIT_CTRLm, entry, START_CNTf, 0); 2445 soc_mem_field32_set(unit, EGR_EDB_XMIT_CTRLm, entry, reg_field, 1); 2446 } else { 2447 if (oversub) { 2448 start_cnt_val = _TD2_MMU_XMIT_START_CNT_OVERSUB; 2449 } else { 2450 start_cnt_val = _TD2_MMU_XMIT_START_CNT_LINERATE(speed); 2451 } 2452 soc_mem_field32_set(unit, EGR_EDB_XMIT_CTRLm, entry, START_CNTf, 2453 start_cnt_val); 2454 soc_mem_field32_set(unit, EGR_EDB_XMIT_CTRLm, entry, WAIT_FOR_MOPf, 0); 2455 soc_mem_field32_set(unit, EGR_EDB_XMIT_CTRLm, entry, WAIT_FOR_2ND_MOPf, 2456 0); 2457 } 2458 SOC_IF_ERROR_RETURN(soc_mem_write(unit, EGR_EDB_XMIT_CTRLm, 2459 MEM_BLOCK_ALL, 2460 phy_port, &entry)); 2461 return SOC_E_NONE; 2462 } 2463 2464 /* 2465 * This function is used to enable or disable cut through when a port is 2466 * operating in store and forward mode. 2467 * Caller must pass the correct port_info pointer, corresponding to the port 2468 * being configured (and sent by the BCM layer) 2469 * To enable cut-through, pass enable = 1 2470 * To disable cut-through, pass enable = 0 2471 */ 2472 STATIC int 2473 soc_td2p_cut_thru_enable_disable(int unit, 2474 soc_port_resource_t *port_info, 2475 int enable) 2476 { 2477 uint32 rval; 2478 uint32 speed; 2479 int use_pfc_optimized_settings = FALSE; 2480 egr_pfc_control_entry_t pfc_control; 2481 2482 /* Mask unnecessary bits */ 2483 enable &= 0x1; 2484 2485 SOC_IF_ERROR_RETURN(READ_ASF_PORT_CFGr(unit, port_info->logical_port, 2486 &rval)); 2487 2488 speed = soc_reg_field_get(unit, ASF_PORT_CFGr, rval, ASF_PORT_SPEEDf); 2489 2490 /* Set port speed to 0 */ 2491 soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, ASF_PORT_SPEEDf, 0); 2492 SOC_IF_ERROR_RETURN(WRITE_ASF_PORT_CFGr(unit, port_info->logical_port, 2493 rval)); 2494 2495 if (!enable) { 2496 /* Wait 8ms for draining all cells */ 2497 sal_usleep(8000); 2498 } 2499 2500 SOC_IF_ERROR_RETURN(soc_td2p_egr_edb_xmit_ctrl_set( 2501 unit, port_info->physical_port, port_info->speed, 2502 port_info->oversub, enable)); 2503 2504 /* Set UC_ASF_ENABLE, MC_ASF_ENABLE bits to 1 */ 2505 soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, UC_ASF_ENABLEf, enable); 2506 soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, MC_ASF_ENABLEf, enable); 2507 SOC_IF_ERROR_RETURN(WRITE_ASF_PORT_CFGr(unit, port_info->logical_port, 2508 rval)); 2509 2510 if (enable) { 2511 /* Wait 1 micro-sec */ 2512 sal_usleep(1); 2513 } 2514 2515 soc_reg_field_set(unit, ASF_PORT_CFGr, &rval, ASF_PORT_SPEEDf, speed); 2516 SOC_IF_ERROR_RETURN(WRITE_ASF_PORT_CFGr(unit, port_info->logical_port, 2517 rval)); 2518 2519 /* If system is able to use optimized settings, 2520 disable EDB watermark to avoid credit underrun. 2521 MMU mechanism will be used to optimize PFC response. */ 2522 use_pfc_optimized_settings = soc_td2p_use_pfc_optimized_settings(unit); 2523 if (use_pfc_optimized_settings) { 2524 SOC_IF_ERROR_RETURN(READ_EGR_PFC_CONTROLm(unit, MEM_BLOCK_ALL, 2525 port_info->physical_port, &pfc_control)); 2526 soc_mem_field32_set(unit, EGR_PFC_CONTROLm, &pfc_control, 2527 ENABLEf, enable ? 0 : 1); 2528 SOC_IF_ERROR_RETURN(WRITE_EGR_PFC_CONTROLm(unit, MEM_BLOCK_ALL, 2529 port_info->physical_port, &pfc_control)); 2530 } 2531 2532 return SOC_E_NONE; 2533 } 2534 2535 int soc_td2p_max_speed_port_find(int phy_port, 2536 soc_port_resource_t *port_info, 2537 int port_info_arr_size) 2538 { 2539 int idx, index, speed; 2540 2541 index = 0; 2542 speed = port_info[index].speed; 2543 2544 for (idx = 1; idx < port_info_arr_size; idx++) { 2545 /* If all speeds are equal, '>' will return the 1st index, 2546 * '>=' will return the last index 2547 */ 2548 if (port_info[idx].speed > speed) { 2549 speed = port_info[idx].speed; 2550 index = idx; 2551 } 2552 } 2553 2554 return index; 2555 } 2556 2557 /* This function fetches the current egress scheduler's TDM table number being 2558 * used by the hardware. This function will be used during flexing, but its use 2559 * is not restricted to flexing operations. 2560 */ 2561 STATIC int soc_td2p_curr_egr_tdm_table_get(int unit, int pipe, 2562 uint32 *table_num) 2563 { 2564 soc_reg_t reg; 2565 uint32 rval; 2566 2567 /* Return value of CURR_CALf in table_num */ 2568 2569 reg = (pipe == 0) ? ES_PIPE0_TDM_CONFIGr : ES_PIPE1_TDM_CONFIGr; 2570 2571 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 2572 2573 *table_num = soc_reg_field_get(unit, reg, rval, CURR_CALf); 2574 2575 return SOC_E_NONE; 2576 } 2577 2578 /* This function fetches the current ingress scheduler's TDM table number being 2579 * used by the hardware. This function will be used during flexing, but its use 2580 * is not restricted to flexing operations. 2581 */ 2582 STATIC int soc_td2p_curr_ingr_tdm_table_get(int unit, int pgw_inst, 2583 uint32 *table_num) 2584 { 2585 uint64 rval64; 2586 2587 SOC_IF_ERROR_RETURN(soc_reg_get(unit, PGW_TDM_CONTROLr, pgw_inst, 0, 2588 &rval64)); 2589 2590 /* Return value of LR_TDM_SEL in table_num */ 2591 *table_num = soc_reg64_field32_get(unit, PGW_TDM_CONTROLr, rval64, 2592 LR_TDM_SELf); 2593 2594 return SOC_E_NONE; 2595 } 2596 2597 /* This function sets the new egress scheduler's TDM table number which will be 2598 * used by the hardware. This function will be used during flexing, but its use 2599 * is not restricted to flexing operations. 2600 */ 2601 STATIC int soc_td2p_curr_egr_tdm_table_set(int unit, int pipe, 2602 uint32 table_num) 2603 { 2604 uint32 rval; 2605 soc_reg_t reg; 2606 2607 reg = (pipe == 0) ? ES_PIPE0_TDM_CONFIGr : ES_PIPE1_TDM_CONFIGr; 2608 2609 SOC_IF_ERROR_RETURN (soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 2610 2611 /* Mask unwanted bits */ 2612 table_num &= 0x1; 2613 2614 /* Set CURR_CALf */ 2615 soc_reg_field_set(unit, reg, &rval, CURR_CALf, table_num); 2616 2617 SOC_IF_ERROR_RETURN (soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 2618 2619 return SOC_E_NONE; 2620 } 2621 2622 /* This function fetches the current ingress scheduler's TDM table number being 2623 * used by the hardware. This function will be used during flexing, but its use 2624 * is not restricted to flexing operations. 2625 */ 2626 STATIC int soc_td2p_curr_ingr_tdm_table_set(int unit, int pgw_inst, 2627 int table_num) 2628 { 2629 uint64 rval64; 2630 2631 SOC_IF_ERROR_RETURN(soc_reg_get(unit, PGW_TDM_CONTROLr, pgw_inst, 0, 2632 &rval64)); 2633 2634 /* Mask unwanted bits */ 2635 table_num &= 0x1; 2636 2637 /* Set LR_TDM_SEL */ 2638 soc_reg64_field32_set(unit, PGW_TDM_CONTROLr, &rval64, LR_TDM_SELf, 2639 table_num); 2640 2641 SOC_IF_ERROR_RETURN (soc_reg_set(unit, PGW_TDM_CONTROLr, pgw_inst, 0, 2642 rval64)); 2643 2644 return SOC_E_NONE; 2645 } 2646 2647 /* 2648 * This function checks if cut-through is enabled for a given port. 2649 * If either unicast or multicast cut-through is enabled, the function 2650 * returns TRUE else FALSE is returned 2651 */ 2652 int soc_td2p_is_cut_thru_enabled(int unit, soc_port_t port, int *enable) 2653 { 2654 uint32 rval; 2655 uint32 uc_enable, mc_enable; 2656 2657 SOC_IF_ERROR_RETURN(READ_ASF_PORT_CFGr(unit, port, &rval)); 2658 2659 uc_enable = soc_reg_field_get(unit, ASF_PORT_CFGr, rval, UC_ASF_ENABLEf); 2660 mc_enable = soc_reg_field_get(unit, ASF_PORT_CFGr, rval, MC_ASF_ENABLEf); 2661 2662 /* This is for ensuring that the behavior of cut-through setting get is 2663 * same as in _bcm_td2_port_asf_enable_get called by application 2664 * (upper layer software), through bcm_esw_switch_control_port_get() 2665 */ 2666 if (uc_enable & mc_enable) { 2667 *enable = TRUE; 2668 } else { 2669 *enable = FALSE; 2670 } 2671 2672 return SOC_E_NONE; 2673 } 2674 2675 /* 2676 * This function is used to clear various counters in EP block. The 2677 * counters to clear are mentioned in 'Reconfigure EP' section of TD2+ Flexport 2678 */ 2679 STATIC int soc_td2p_ep_counters_clear(int unit, soc_port_resource_t *port_info) 2680 { 2681 uint64 val64; 2682 uint32 val = 0; 2683 2684 COMPILER_64_ZERO(val64); 2685 SOC_IF_ERROR_RETURN(WRITE_EGR_TRILL_TX_PKTSr(unit, port_info->logical_port, 2686 val)); 2687 SOC_IF_ERROR_RETURN(WRITE_EGR_TRILL_TX_ACCESS_PORT_TRILL_PKTS_DISCARDEDr(unit, port_info->logical_port, val)); 2688 SOC_IF_ERROR_RETURN(WRITE_EGR_FCOE_DELIMITER_ERROR_FRAMESr(unit, 2689 port_info->logical_port, val)); 2690 SOC_IF_ERROR_RETURN(WRITE_EGR_FCOE_INVALID_CRC_FRAMESr(unit, 2691 port_info->logical_port, val)); 2692 2693 SOC_IF_ERROR_RETURN(WRITE_TPCEr(unit, port_info->logical_port, val64)); 2694 2695 SOC_IF_ERROR_RETURN(WRITE_TDBGC0r(unit, port_info->logical_port, val64)); 2696 SOC_IF_ERROR_RETURN(WRITE_TDBGC1r(unit, port_info->logical_port, val64)); 2697 SOC_IF_ERROR_RETURN(WRITE_TDBGC2r(unit, port_info->logical_port, val64)); 2698 SOC_IF_ERROR_RETURN(WRITE_TDBGC3r(unit, port_info->logical_port, val64)); 2699 SOC_IF_ERROR_RETURN(WRITE_TDBGC4r(unit, port_info->logical_port, val64)); 2700 SOC_IF_ERROR_RETURN(WRITE_TDBGC5r(unit, port_info->logical_port, val64)); 2701 SOC_IF_ERROR_RETURN(WRITE_TDBGC6r(unit, port_info->logical_port, val64)); 2702 SOC_IF_ERROR_RETURN(WRITE_TDBGC7r(unit, port_info->logical_port, val64)); 2703 SOC_IF_ERROR_RETURN(WRITE_TDBGC8r(unit, port_info->logical_port, val64)); 2704 SOC_IF_ERROR_RETURN(WRITE_TDBGC9r(unit, port_info->logical_port, val64)); 2705 SOC_IF_ERROR_RETURN(WRITE_TDBGC10r(unit, port_info->logical_port, val64)); 2706 SOC_IF_ERROR_RETURN(WRITE_TDBGC11r(unit, port_info->logical_port, val64)); 2707 2708 return SOC_E_NONE; 2709 } 2710 2711 STATIC int soc_td2p_port_resource_tdm_calculate(int unit, 2712 int curr_port_info_size, 2713 soc_port_resource_t *curr_port_info, 2714 int new_port_info_size, 2715 soc_port_resource_t *new_port_info, 2716 soc_td2p_info_t *si_info) 2717 { 2718 #ifdef BCM_56860_A0 2719 int rv, i; 2720 int num_of_subport; 2721 soc_info_t *si; 2722 _soc_trident2_tdm_t *tdm; 2723 tdm_soc_t _chip_pkg; 2724 tdm_mod_t *_tdm_pkg; 2725 int phy_port; 2726 int port; 2727 int speed_max, index, slot; 2728 soc_pbmp_t pbmp; 2729 2730 /* soc info has new values */ 2731 si = &SOC_INFO(unit); 2732 2733 tdm = soc_td2_td2p_tdm_sched_info_get(unit, 1); 2734 if (tdm == NULL) { 2735 return SOC_E_MEMORY; 2736 } 2737 2738 PBMP_PORT_ITER(unit, port) { 2739 if (SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) { 2740 continue; 2741 } 2742 2743 /* Since soc info structure has been updated before this function is 2744 * called, we use the information provided by it 2745 */ 2746 phy_port = si->port_l2p_mapping[port]; 2747 2748 tdm->speed[phy_port] = si->port_speed_max[port]; 2749 if (si->port_speed_max[port] < 1000) { 2750 tdm->speed[phy_port] = 1000; 2751 } 2752 tdm->port_state[phy_port] = SOC_PBMP_MEMBER(si->oversub_pbm, port) ? 2753 PORT_STATE_OVERSUB : 2754 PORT_STATE_LINERATE; 2755 2756 num_of_subport = 0; 2757 if (tdm->speed[phy_port] >= 120000) { 2758 num_of_subport = 11; 2759 } else if (tdm->speed[phy_port] >= 100000) { 2760 num_of_subport = 9; 2761 } else if (tdm->speed[phy_port] >= 40000) { 2762 num_of_subport = 3; 2763 } else if (tdm->speed[phy_port] >= 20000) { 2764 num_of_subport = 1; 2765 } 2766 for (i = 0; i < num_of_subport; i++) { 2767 tdm->port_state[phy_port + i + 1] = PORT_STATE_SUBPORT; 2768 } 2769 } 2770 2771 tdm->speed[0] = 1000; 2772 tdm->speed[129] = 1000; 2773 tdm->tdm_bw = si->bandwidth / 1000; 2774 2775 SOC_PBMP_ASSIGN(pbmp, si->oversub_pbm); 2776 SOC_PBMP_AND(pbmp, si->xpipe_pbm); 2777 if (tdm->tdm_bw == 720) { /* 720g special handling */ 2778 /* tell tdm code the pipe is oversub only if all ports are oversub */ 2779 SOC_PBMP_PORT_ADD(pbmp, 0); /* cpu port */ 2780 tdm->pipe_ovs_state[0] = SOC_PBMP_EQ(pbmp, si->xpipe_pbm); 2781 } else { 2782 /* tell tdm code the pipe is oversub if any ports is oversub */ 2783 tdm->pipe_ovs_state[0] = SOC_PBMP_NOT_NULL(pbmp); 2784 } 2785 SOC_PBMP_ASSIGN(pbmp, si->oversub_pbm); 2786 SOC_PBMP_AND(pbmp, si->ypipe_pbm); 2787 if (tdm->tdm_bw == 720) { /* 720g special handling */ 2788 /* tell tdm code the pipe is oversub only if all ports are oversub */ 2789 SOC_PBMP_PORT_ADD(pbmp, 105); /* loopback port */ 2790 tdm->pipe_ovs_state[1] = SOC_PBMP_EQ(pbmp, si->ypipe_pbm); 2791 } else { 2792 /* tell tdm code the pipe is oversub if any ports is oversub */ 2793 tdm->pipe_ovs_state[1] = SOC_PBMP_NOT_NULL(pbmp); 2794 } 2795 2796 tdm->manage_port_type = 0; 2797 if (SOC_PBMP_NOT_NULL(si->management_pbm)) { 2798 speed_max = 0; 2799 for (phy_port = 13; phy_port <= 16; phy_port++) { 2800 port = si->port_p2l_mapping[phy_port]; 2801 if (port == -1) { 2802 continue; 2803 } 2804 if (speed_max < si->port_speed_max[port]) { 2805 speed_max = si->port_speed_max[port]; 2806 } 2807 } 2808 if (speed_max <= 1000) { 2809 tdm->manage_port_type = 1; /* 4 x 1g */ 2810 } else if (speed_max <= 2500) { 2811 tdm->manage_port_type = 2; /* 4 * 2.5g */ 2812 } else { 2813 tdm->manage_port_type = 3; /* 1 x 10g */ 2814 } 2815 if (tdm->manage_port_type > 0) { 2816 tdm->pgw_tdm[0][0] = 1234; /* magic number used by tdm code */ 2817 } 2818 } 2819 if (tdm->manage_port_type != 0) { 2820 _chip_pkg.soc_vars.td2p.tdm_mgmt_en = 1; 2821 } else { 2822 _chip_pkg.soc_vars.td2p.tdm_mgmt_en = 0; 2823 } 2824 2825 for (slot = 0; slot <= _MMU_TDM_LENGTH; slot++) { 2826 tdm->mmu_tdm[0][slot] = NUM_EXT_PORTS; 2827 tdm->mmu_tdm[1][slot] = NUM_EXT_PORTS; 2828 } 2829 2830 /* Configure ingress scheduler back up calendar */ 2831 _chip_pkg.unit = unit; 2832 _chip_pkg.num_ext_ports = TD2P_NUM_EXT_PORTS; 2833 _chip_pkg.state=sal_alloc((_chip_pkg.num_ext_ports)*sizeof(int *), "port state list"); 2834 _chip_pkg.speed=sal_alloc((_chip_pkg.num_ext_ports)*sizeof(int *), "port speed list"); 2835 for (index=1; index<(_chip_pkg.num_ext_ports); index++) { 2836 _chip_pkg.state[index] = tdm->port_state[index]; 2837 } 2838 _chip_pkg.state[0]=1; /* enable cpu port */ 2839 _chip_pkg.state[_chip_pkg.num_ext_ports-1]=1; /* enable loopback port */ 2840 2841 /* This pointer is used internally by set tdm table API, and is 2842 * initialized in tdm_td2p_init (src/soc/esw/tdm/set_tdm.c). 2843 * _soc_set_tdm_tbl calls functions in the array of function pointers 2844 * (_chip_exec) 2845 * This pointer is not used by SDK code. 2846 */ 2847 /* coverity[uninit_use_in_call] */ 2848 _chip_pkg.pmap = NULL; 2849 for (index=0; index<(_chip_pkg.num_ext_ports); index++) { 2850 _chip_pkg.speed[index] = tdm->speed[index]; 2851 } 2852 2853 /* 2854 * Map detected core clk frequency to TDM algorithm internal code 2855 * value. 2856 */ 2857 switch (si->frequency) { 2858 case 790: 2859 case 760: 2860 _chip_pkg.clk_freq = 760; 2861 break; 2862 case 635: 2863 _chip_pkg.clk_freq = 608; 2864 break; 2865 case 537: 2866 _chip_pkg.clk_freq = 518; 2867 break; 2868 case 421: 2869 _chip_pkg.clk_freq = 415; 2870 break; 2871 default: 2872 _chip_pkg.clk_freq = (si->frequency > 760) ? (760) 2873 : si->frequency; 2874 } 2875 2876 /* This function initializes only the fields which the caller of 2877 * _soc_set_tdm_tbl should fill. The remaining fields of _chip_pkg 2878 * structure are initialized and used internally within _soc_set_tdm_tbl 2879 * (and other tdm library functions) 2880 */ 2881 /* coverity[uninit_use_in_call] */ 2882 _tdm_pkg = _soc_set_tdm_tbl(SOC_SEL_TDM(&_chip_pkg)); 2883 if (!_tdm_pkg) { 2884 LOG_CLI((BSL_META_U(unit, 2885 "Unsupported config for TDM calendar generation\n"))); 2886 return SOC_E_FAIL; 2887 } 2888 2889 sal_memcpy(tdm->pgw_tdm[0], _tdm_pkg->_chip_data.cal_0.cal_main, sizeof(int)*MAX_PGW_TDM_LENGTH); 2890 sal_memcpy(tdm->pgw_ovs_tdm[0], _tdm_pkg->_chip_data.cal_0.cal_grp[0], sizeof(int)*_PGW_TDM_OVS_SIZE); 2891 sal_memcpy(tdm->pgw_ovs_spacing[0], _tdm_pkg->_chip_data.cal_0.cal_grp[1], sizeof(int)*_PGW_TDM_OVS_SIZE); 2892 sal_memcpy(tdm->pgw_tdm[1], _tdm_pkg->_chip_data.cal_1.cal_main, sizeof(int)*MAX_PGW_TDM_LENGTH); 2893 sal_memcpy(tdm->pgw_ovs_tdm[1], _tdm_pkg->_chip_data.cal_1.cal_grp[0], sizeof(int)*_PGW_TDM_OVS_SIZE); 2894 sal_memcpy(tdm->pgw_ovs_spacing[1], _tdm_pkg->_chip_data.cal_1.cal_grp[1], sizeof(int)*_PGW_TDM_OVS_SIZE); 2895 sal_memcpy(tdm->pgw_tdm[2], _tdm_pkg->_chip_data.cal_2.cal_main, sizeof(int)*MAX_PGW_TDM_LENGTH); 2896 sal_memcpy(tdm->pgw_ovs_tdm[2], _tdm_pkg->_chip_data.cal_2.cal_grp[0], sizeof(int)*_PGW_TDM_OVS_SIZE); 2897 sal_memcpy(tdm->pgw_ovs_spacing[2], _tdm_pkg->_chip_data.cal_2.cal_grp[1], sizeof(int)*_PGW_TDM_OVS_SIZE); 2898 sal_memcpy(tdm->pgw_tdm[3], _tdm_pkg->_chip_data.cal_3.cal_main, sizeof(int)*MAX_PGW_TDM_LENGTH); 2899 sal_memcpy(tdm->pgw_ovs_tdm[3], _tdm_pkg->_chip_data.cal_3.cal_grp[0], sizeof(int)*_PGW_TDM_OVS_SIZE); 2900 sal_memcpy(tdm->pgw_ovs_spacing[3], _tdm_pkg->_chip_data.cal_3.cal_grp[1], sizeof(int)*_PGW_TDM_OVS_SIZE); 2901 sal_memcpy(tdm->mmu_tdm[0], _tdm_pkg->_chip_data.cal_4.cal_main, sizeof(int)*_MMU_TDM_LENGTH); 2902 sal_memcpy(tdm->mmu_ovs_group_tdm[0][0], _tdm_pkg->_chip_data.cal_4.cal_grp[0], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2903 sal_memcpy(tdm->mmu_ovs_group_tdm[0][1], _tdm_pkg->_chip_data.cal_4.cal_grp[1], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2904 sal_memcpy(tdm->mmu_ovs_group_tdm[0][2], _tdm_pkg->_chip_data.cal_4.cal_grp[2], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2905 sal_memcpy(tdm->mmu_ovs_group_tdm[0][3], _tdm_pkg->_chip_data.cal_4.cal_grp[3], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2906 sal_memcpy(tdm->mmu_ovs_group_tdm[0][4], _tdm_pkg->_chip_data.cal_4.cal_grp[4], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2907 sal_memcpy(tdm->mmu_ovs_group_tdm[0][5], _tdm_pkg->_chip_data.cal_4.cal_grp[5], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2908 sal_memcpy(tdm->mmu_ovs_group_tdm[0][6], _tdm_pkg->_chip_data.cal_4.cal_grp[6], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2909 sal_memcpy(tdm->mmu_ovs_group_tdm[0][7], _tdm_pkg->_chip_data.cal_4.cal_grp[7], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2910 sal_memcpy(tdm->mmu_tdm[1], _tdm_pkg->_chip_data.cal_5.cal_main, sizeof(int)*_MMU_TDM_LENGTH); 2911 sal_memcpy(tdm->mmu_ovs_group_tdm[1][0], _tdm_pkg->_chip_data.cal_5.cal_grp[0], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2912 sal_memcpy(tdm->mmu_ovs_group_tdm[1][1], _tdm_pkg->_chip_data.cal_5.cal_grp[1], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2913 sal_memcpy(tdm->mmu_ovs_group_tdm[1][2], _tdm_pkg->_chip_data.cal_5.cal_grp[2], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2914 sal_memcpy(tdm->mmu_ovs_group_tdm[1][3], _tdm_pkg->_chip_data.cal_5.cal_grp[3], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2915 sal_memcpy(tdm->mmu_ovs_group_tdm[1][4], _tdm_pkg->_chip_data.cal_5.cal_grp[4], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2916 sal_memcpy(tdm->mmu_ovs_group_tdm[1][5], _tdm_pkg->_chip_data.cal_5.cal_grp[5], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2917 sal_memcpy(tdm->mmu_ovs_group_tdm[1][6], _tdm_pkg->_chip_data.cal_5.cal_grp[6], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2918 sal_memcpy(tdm->mmu_ovs_group_tdm[1][7], _tdm_pkg->_chip_data.cal_5.cal_grp[7], sizeof(int)*_MMU_OVS_GROUP_TDM_LENGTH); 2919 sal_free(_chip_pkg.state); 2920 sal_free(_chip_pkg.speed); 2921 _tdm_pkg->_chip_exec[TDM_CHIP_EXEC__FREE](_tdm_pkg); 2922 sal_free(_tdm_pkg); 2923 2924 rv = tdm_td2p_set_iarb_tdm_table(tdm->tdm_bw, 2925 tdm->pipe_ovs_state[0], 2926 tdm->pipe_ovs_state[1], 2927 tdm->manage_port_type == 1, 2928 tdm->manage_port_type == 2, 2929 tdm->manage_port_type == 3, 2930 &tdm->iarb_tdm_wrap_ptr[0], 2931 &tdm->iarb_tdm_wrap_ptr[1], 2932 tdm->iarb_tdm[0], 2933 tdm->iarb_tdm[1]); 2934 2935 if (rv == 0) { 2936 LOG_CLI((BSL_META_U(unit, 2937 "Unsupported config for TDM calendar generation\n"))); 2938 return SOC_E_FAIL; 2939 } 2940 #endif 2941 return SOC_E_NONE; 2942 } 2943 2944 /* 2945 * Function: 2946 * soc_td2p_use_pfc_optimized_settings 2947 * Purpose: 2948 * Determines whether to use pfc optimized settings or not. 2949 * PFC Optimized Settings can only be used at max clock frequency, 2950 * which enables bandwidth of 960G. Its use is also dependent on 2951 * the oversub ratio, which must be < 1.5. Configurations that are 2952 * all linerate or all oversub do not exceed this threshold. However, 2953 * mixed configurations of linerate and oversubbed ports can exceed 2954 * 1.5, so the oversub ratio is calculated at the bottom of the 2955 * function. 2956 * 2957 * Parameters: 2958 * unit - (IN) Unit number. 2959 * 2960 * Returns: 2961 * TRUE or FALSE 2962 */ 2963 int 2964 soc_td2p_use_pfc_optimized_settings(int unit) 2965 { 2966 soc_info_t *si; 2967 soc_pbmp_t pbmp; 2968 2969 int x_denominator = 0, y_denominator = 0; 2970 2971 int all_x_oversub = 0, any_x_oversub = 0; 2972 int all_y_oversub = 0, any_y_oversub = 0; 2973 2974 int x_linerate_bw = 0, x_oversub_bw = 0; 2975 int y_linerate_bw = 0, y_oversub_bw = 0; 2976 int x_core_bw = 0, y_core_bw = 0; 2977 int max_quad_core_bandwidth, quad_linerate_bandwidth, quad_oversub_bandwidth; 2978 2979 /* soc info has new values */ 2980 si = &SOC_INFO(unit); 2981 /* if not max frequency, use non-optimized settings */ 2982 if (si->bandwidth < 960000) { 2983 return FALSE; 2984 } 2985 2986 SOC_PBMP_CLEAR(pbmp); 2987 SOC_PBMP_ASSIGN(pbmp, si->oversub_pbm); 2988 SOC_PBMP_AND(pbmp, si->xpipe_pbm); 2989 2990 /* find if any X ports are oversub */ 2991 any_x_oversub = SOC_PBMP_NOT_NULL(pbmp); 2992 2993 /* find if all X ports are oversub */ 2994 SOC_PBMP_PORT_ADD(pbmp, 0); /* cpu port */ 2995 all_x_oversub = SOC_PBMP_EQ(pbmp, si->xpipe_pbm); 2996 2997 2998 2999 SOC_PBMP_CLEAR(pbmp); 3000 SOC_PBMP_ASSIGN(pbmp, si->oversub_pbm); 3001 SOC_PBMP_AND(pbmp, si->ypipe_pbm); 3002 3003 /* find if any Y ports are oversub */ 3004 any_y_oversub = SOC_PBMP_NOT_NULL(pbmp); 3005 3006 /* find if all Y ports are oversub */ 3007 SOC_PBMP_PORT_ADD(pbmp, 105); /* loopback port */ 3008 all_y_oversub = SOC_PBMP_EQ(pbmp, si->ypipe_pbm); 3009 3010 /* if all ports are oversub, use pfc optimized settings; 3011 oversub ratio < 1.5 */ 3012 if (all_x_oversub == 1 && all_y_oversub == 1) { 3013 return TRUE; 3014 } 3015 3016 /* if all the ports are linerate, use pfc optimized settings; 3017 oversub ratio < 1.5 */ 3018 if (any_x_oversub == 0 && any_y_oversub == 0) { 3019 return TRUE; 3020 } 3021 3022 /* in the mixed line rate/oversub case, we need to calculate 3023 the oversub ratio: 3024 3025 oversubbed port bandwidth / remaining bw after guaranteed linerate 3026 3027 Example: if 2 100G line rate ports, subtract 200 from core bandwidth 3028 of 480 (per pipe) because that's guaranteed, so you're left with 280. 3029 3030 Now if you have 8 40G ports, that's 320G of bandwidth, so you MUST 3031 use oversub for those since you only have 280G left. 3032 3033 Thus your Oversub ratio is 320/280. This value MUST be < 1.5 in order 3034 to use PFC Optimized Settings. 3035 */ 3036 3037 /* Calculate total linerate and oversub bandwidth for X Pipe */ 3038 _soc_trident2_quad_bandwidth_calculate(unit, 0, &max_quad_core_bandwidth, 3039 &quad_linerate_bandwidth, 3040 &quad_oversub_bandwidth); 3041 x_core_bw += max_quad_core_bandwidth; 3042 x_linerate_bw += quad_linerate_bandwidth; 3043 x_oversub_bw += quad_oversub_bandwidth; 3044 3045 _soc_trident2_quad_bandwidth_calculate(unit, 1, &max_quad_core_bandwidth, 3046 &quad_linerate_bandwidth, 3047 &quad_oversub_bandwidth); 3048 x_core_bw += max_quad_core_bandwidth; 3049 x_linerate_bw += quad_linerate_bandwidth; 3050 x_oversub_bw += quad_oversub_bandwidth; 3051 3052 /* Calculate total linerate and oversub bandwidth for Y Pipe */ 3053 _soc_trident2_quad_bandwidth_calculate(unit, 2, &max_quad_core_bandwidth, 3054 &quad_linerate_bandwidth, 3055 &quad_oversub_bandwidth); 3056 y_core_bw += max_quad_core_bandwidth; 3057 y_linerate_bw += quad_linerate_bandwidth; 3058 y_oversub_bw += quad_oversub_bandwidth; 3059 3060 _soc_trident2_quad_bandwidth_calculate(unit, 3, &max_quad_core_bandwidth, 3061 &quad_linerate_bandwidth, 3062 &quad_oversub_bandwidth); 3063 y_core_bw += max_quad_core_bandwidth; 3064 y_linerate_bw += quad_linerate_bandwidth; 3065 y_oversub_bw += quad_oversub_bandwidth; 3066 3067 /* Calculate Oversub Ratio per pipe. Oversub ratio must be < 1.5. 3068 Since we can't use floats, the math 3069 used here is to multiply the numerator by 2 and the denominator by 3 3070 and compare the results. 3071 numerator = oversub bandwidth 3072 denominator = core bandwidth - linerate bandwidth 3073 */ 3074 x_denominator = (x_core_bw - x_linerate_bw); 3075 y_denominator = (y_core_bw - y_linerate_bw); 3076 3077 /* If either pipe has an oversub ratio > 1.5, use normal settings. */ 3078 if ((2 * x_oversub_bw) >= (3 * x_denominator) || 3079 (2 * y_oversub_bw) >= (3 * y_denominator)) { 3080 return FALSE; 3081 } 3082 3083 /* Use PFC Optimized Settings */ 3084 return TRUE; 3085 } 3086 3087 3088 3089 /* 3090 * Function: 3091 * soc_td2p_set_mmu_credit_limit 3092 * Purpose: 3093 * Programs egress port credit size depending on port speed and whether 3094 * oversub is enabled. Programs it for the worst case scenario. 3095 * 3096 * EP credit sizing is used to reduce the usable size of Edatabuf (EDB) 3097 * to limit accumulation. 3098 * 3099 * Parameters: 3100 * unit - (IN) Unit number. 3101 * port - (IN) Logical Port 3102 * 3103 * Returns: 3104 * SOC_E_XXX 3105 */ 3106 int 3107 soc_td2p_set_mmu_credit_limit(int unit, soc_port_t port) 3108 { 3109 uint32 enable = 1; 3110 uint32 credit_limit = 0; 3111 uint32 entry[SOC_MAX_MEM_WORDS]; 3112 int phy_port, speed_max, hw_index; 3113 soc_mem_t mem; 3114 soc_info_t *si = &SOC_INFO(unit); 3115 3116 phy_port = si->port_l2p_mapping[port]; 3117 if (phy_port == -1) { 3118 return SOC_E_INTERNAL; 3119 } 3120 3121 SOC_IF_ERROR_RETURN( 3122 READ_EGR_MMU_CREDIT_LIMITm(unit, MEM_BLOCK_ALL, phy_port, entry)); 3123 3124 /* Get the maximum speed of the port */ 3125 speed_max = si->port_speed_max[port]; 3126 3127 /* There are different credit limits depending on if 3128 oversub is enabled, and the port speed. */ 3129 if (IS_OVERSUB_PORT(unit, port)) { 3130 if (speed_max >= 100000) { 3131 return SOC_E_PARAM; 3132 } else if (speed_max >= 40000) { 3133 credit_limit = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_OVERSUB(40G); 3134 } else if (speed_max >= 20000) { 3135 credit_limit = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_OVERSUB(20G); 3136 } else if (speed_max >= 10000) { 3137 credit_limit = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_OVERSUB(10G); 3138 } else { 3139 return SOC_E_NONE; 3140 } 3141 } else { 3142 if (speed_max >= 100000) { 3143 credit_limit = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(100G); 3144 } else if (speed_max >= 40000) { 3145 credit_limit = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(40G); 3146 } else if (speed_max >= 20000) { 3147 credit_limit = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(20G); 3148 } else if (speed_max >= 10000) { 3149 credit_limit = _TD2P_MMU_EGR_MMU_CREDIT_LIMIT_LINERATE(10G); 3150 } else { 3151 return SOC_E_NONE; 3152 } 3153 } 3154 3155 mem = SOC_TD2_PMEM(unit, port, EGR_MMU_CREDIT_LIMIT_Xm, EGR_MMU_CREDIT_LIMIT_Ym); 3156 if (mem == INVALIDm) { 3157 return SOC_E_INTERNAL; 3158 } 3159 3160 hw_index = phy_port; 3161 SOC_IF_ERROR_RETURN 3162 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, hw_index, &entry)); 3163 3164 soc_mem_field32_set(unit, mem, entry, ENABLEf, enable); 3165 soc_mem_field32_set(unit, mem, entry, CELL_COUNTSf, credit_limit); 3166 3167 SOC_IF_ERROR_RETURN 3168 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_index, entry)); 3169 3170 3171 return SOC_E_NONE; 3172 } 3173 3174 /* 3175 * Function: 3176 * soc_td2p_set_edb_pfc_watermark_threshold 3177 * Purpose: 3178 * Programs EDB PFC Watermark Threshold depending on port speed and whether 3179 * oversub is enabled. Programs it for the worst case scenario. 3180 * 3181 * PFC Watermark in EDB stalls EP credit return to the MMU in order 3182 * to limit outstanding credits. 3183 * 3184 * Parameters: 3185 * unit - (IN) Unit number. 3186 * port - (IN) Logical Port 3187 * 3188 * Returns: 3189 * SOC_E_XXX 3190 */ 3191 int 3192 soc_td2p_set_edb_pfc_watermark_threshold(int unit, soc_port_t port) 3193 { 3194 3195 uint32 enable = 1; 3196 uint32 pfc_watermark_thresh = 0; 3197 uint32 entry[SOC_MAX_MEM_WORDS]; 3198 int phy_port, speed_max, ct_enable = 0; 3199 soc_info_t *si = &SOC_INFO(unit); 3200 3201 phy_port = si->port_l2p_mapping[port]; 3202 if (phy_port == -1) { 3203 return SOC_E_INTERNAL; 3204 } 3205 3206 SOC_IF_ERROR_RETURN( 3207 READ_EGR_PFC_CONTROLm(unit, MEM_BLOCK_ALL, phy_port, entry)); 3208 3209 /* Get the maximum speed of the port */ 3210 speed_max = si->port_speed_max[port]; 3211 3212 /* There are different watermarks depending on if 3213 oversub is enabled, and the port speed. */ 3214 /* cut through is not supported */ 3215 if (IS_OVERSUB_PORT(unit, port)) { 3216 if (speed_max >= 100000) { 3217 return SOC_E_PARAM; 3218 } else if (speed_max >= 40000) { 3219 pfc_watermark_thresh = _TD2P_EGR_PFC_WATERMARK_THRESH_OVERSUB(40G); 3220 } else if (speed_max >= 20000) { 3221 pfc_watermark_thresh = _TD2P_EGR_PFC_WATERMARK_THRESH_OVERSUB(20G); 3222 } else if (speed_max >= 10000) { 3223 pfc_watermark_thresh = _TD2P_EGR_PFC_WATERMARK_THRESH_OVERSUB(10G); 3224 } else { 3225 return SOC_E_NONE; 3226 } 3227 } else { 3228 if (speed_max >= 100000) { 3229 pfc_watermark_thresh = _TD2P_EGR_PFC_WATERMARK_THRESH_LINERATE(100G); 3230 } else if (speed_max >= 40000) { 3231 pfc_watermark_thresh = _TD2P_EGR_PFC_WATERMARK_THRESH_LINERATE(40G); 3232 } else if (speed_max >= 20000) { 3233 pfc_watermark_thresh = _TD2P_EGR_PFC_WATERMARK_THRESH_LINERATE(20G); 3234 } else if (speed_max >= 10000) { 3235 pfc_watermark_thresh = _TD2P_EGR_PFC_WATERMARK_THRESH_LINERATE(10G); 3236 } else { 3237 return SOC_E_NONE; 3238 } 3239 } 3240 3241 SOC_IF_ERROR_RETURN( 3242 soc_td2p_is_cut_thru_enabled(unit, port, &ct_enable)); 3243 if (ct_enable) { 3244 enable = 0; 3245 } 3246 /* modify ENABLE and CELL_COUNTS in the EGR_MMU_CREDIT_LIMIT */ 3247 soc_EGR_PFC_CONTROLm_field_set(unit, entry, ENABLEf, &enable); 3248 soc_EGR_PFC_CONTROLm_field_set(unit, entry, WATERMARKf, &pfc_watermark_thresh); 3249 3250 SOC_IF_ERROR_RETURN( 3251 WRITE_EGR_PFC_CONTROLm(unit, MEM_BLOCK_ALL, phy_port, entry)); 3252 3253 return SOC_E_NONE; 3254 } 3255 3256 /* 3257 * Function: 3258 * soc_td2p_port_resource_tdm_set 3259 * Purpose: 3260 * Reconfigure the ingress and egress schedulers for 3261 * the new port configuration. 3262 * 3263 * This includes reconfiguration of: 3264 * - OBM Thresholds 3265 * - EDB Prebuffer 3266 * - Ingress Oversub Scheduler 3267 * - Egress Oversub Scheduler 3268 * - Line-Rate Scheduler 3269 * Parameters: 3270 * unit - (IN) Unit number. 3271 * curr_port_info_size - (IN) Size of current port information array 3272 * curr_port_info - (IN) Per-port array with current flexing info 3273 * new_port_info_size - (IN) Size of new port information array 3274 * new_port_info - (IN) Per-port array with new flexing info 3275 * si_info - (IN) Contains subset of fields from 3276 * soc_info_t structure 3277 * prior to the flexing operation 3278 * lossless - (IN) MMU lossless information 3279 * Returns: 3280 * SOC_E_XXX 3281 * Note: 3282 * Assumptions 3283 * - soc info structure members have been updated to reflect the latest 3284 * flexing operation 3285 * - There is no overlapping between logical or physical ports in the 3286 * arrays passed, that is, operations like 4x10->1x40->4x10 on the same 3287 * set of ports have been rejected at bcm layer itself, and do not reach 3288 * this function 3289 * - Pre-FlexPort array 3290 * Contains current information on ports to be modified after 3291 * the FlexPort operation. This should include ports whose 3292 * mappings are either deleted or remapped. 3293 * - Post-FlexPort array 3294 * Contains information on new configuration for 3295 * ports that are active (present) after the FlexPort operation. 3296 * This should include ports whose mappings that are remapped or new. 3297 */ 3298 int soc_td2p_port_resource_tdm_set(int unit, int curr_port_info_size, 3299 soc_port_resource_t *curr_port_info, 3300 int new_port_info_size, 3301 soc_port_resource_t *new_port_info, 3302 soc_td2p_info_t *si_info, 3303 int lossless) 3304 { 3305 soc_info_t *si; 3306 _soc_trident2_tdm_t *tdm; 3307 int pipe; 3308 int phy_port; 3309 int count; 3310 uint32 table_num = 0; 3311 uint64 rval64, ctrl_rval64; 3312 uint32 rval; 3313 int idx, mmu_port, length, profile_x, profile_y, port; 3314 int index, pgw, pgw_master, pgw_slave, obm_inst, base, slot; 3315 soc_mem_t mem; 3316 uint32 entry[SOC_MAX_MEM_WORDS]; 3317 soc_reg_t reg; 3318 soc_field_t fields[4]; 3319 uint32 values[4]; 3320 soc_pbmp_t pbmp; 3321 /* Used to store per-port cut-through setting */ 3322 int cut_thru_en[SOC_MAX_NUM_PORTS]; 3323 soc_port_resource_t res; 3324 3325 /* Egress scheduler calendar memories */ 3326 static const soc_mem_t mmu_tdm_mems_0[2] ={ 3327 ES_PIPE0_TDM_TABLE_0m, ES_PIPE1_TDM_TABLE_0m 3328 }; 3329 3330 static const soc_mem_t mmu_tdm_mems_1[2] ={ 3331 ES_PIPE0_TDM_TABLE_1m, ES_PIPE1_TDM_TABLE_1m 3332 }; 3333 3334 static const soc_mem_t mmu_tdm_regs[2] ={ 3335 ES_PIPE0_TDM_CONFIGr, ES_PIPE1_TDM_CONFIGr 3336 }; 3337 3338 static const soc_mem_t iarb_tdm_mems[2] ={ 3339 IARB_MAIN_TDM_Xm, IARB_MAIN_TDM_Ym 3340 }; 3341 3342 static soc_reg_t pgw_tdm_regs[] = { 3343 PGW_LR_TDM_REG_0r, PGW_LR_TDM_REG_1r, 3344 PGW_LR_TDM_REG_2r, PGW_LR_TDM_REG_3r, 3345 PGW_LR_TDM_REG_4r, PGW_LR_TDM_REG_5r, 3346 PGW_LR_TDM_REG_6r, PGW_LR_TDM_REG_7r, 3347 PGW_LR_TDM_REG_8r, PGW_LR_TDM_REG_9r, 3348 PGW_LR_TDM_REG_10r, PGW_LR_TDM_REG_11r, 3349 PGW_LR_TDM_REG_12r, PGW_LR_TDM_REG_13r, 3350 PGW_LR_TDM_REG_14r, PGW_LR_TDM_REG_15r 3351 }; 3352 3353 /* Used for programming back up calender */ 3354 static soc_reg_t pgw_tdm2_regs[] = { 3355 PGW_LR_TDM2_REG_0r, PGW_LR_TDM2_REG_1r, 3356 PGW_LR_TDM2_REG_2r, PGW_LR_TDM2_REG_3r, 3357 PGW_LR_TDM2_REG_4r, PGW_LR_TDM2_REG_5r, 3358 PGW_LR_TDM2_REG_6r, PGW_LR_TDM2_REG_7r, 3359 PGW_LR_TDM2_REG_8r, PGW_LR_TDM2_REG_9r, 3360 PGW_LR_TDM2_REG_10r, PGW_LR_TDM2_REG_11r, 3361 PGW_LR_TDM2_REG_12r, PGW_LR_TDM2_REG_13r, 3362 PGW_LR_TDM2_REG_14r, PGW_LR_TDM2_REG_15r 3363 }; 3364 3365 static const soc_field_t pgw_tdm_fields[] = { 3366 TDM_ENTRY0_PORT_IDf, TDM_ENTRY1_PORT_IDf, 3367 TDM_ENTRY2_PORT_IDf, TDM_ENTRY3_PORT_IDf, 3368 TDM_ENTRY4_PORT_IDf, TDM_ENTRY5_PORT_IDf, 3369 TDM_ENTRY6_PORT_IDf, TDM_ENTRY7_PORT_IDf, 3370 TDM_ENTRY8_PORT_IDf, TDM_ENTRY9_PORT_IDf, 3371 TDM_ENTRY10_PORT_IDf, TDM_ENTRY11_PORT_IDf, 3372 TDM_ENTRY12_PORT_IDf, TDM_ENTRY13_PORT_IDf, 3373 TDM_ENTRY14_PORT_IDf, TDM_ENTRY15_PORT_IDf, 3374 TDM_ENTRY16_PORT_IDf, TDM_ENTRY17_PORT_IDf, 3375 TDM_ENTRY18_PORT_IDf, TDM_ENTRY19_PORT_IDf, 3376 TDM_ENTRY20_PORT_IDf, TDM_ENTRY21_PORT_IDf, 3377 TDM_ENTRY22_PORT_IDf, TDM_ENTRY23_PORT_IDf, 3378 TDM_ENTRY24_PORT_IDf, TDM_ENTRY25_PORT_IDf, 3379 TDM_ENTRY26_PORT_IDf, TDM_ENTRY27_PORT_IDf, 3380 TDM_ENTRY28_PORT_IDf, TDM_ENTRY29_PORT_IDf, 3381 TDM_ENTRY30_PORT_IDf, TDM_ENTRY31_PORT_IDf, 3382 TDM_ENTRY32_PORT_IDf, TDM_ENTRY33_PORT_IDf, 3383 TDM_ENTRY34_PORT_IDf, TDM_ENTRY35_PORT_IDf, 3384 TDM_ENTRY36_PORT_IDf, TDM_ENTRY37_PORT_IDf, 3385 TDM_ENTRY38_PORT_IDf, TDM_ENTRY39_PORT_IDf, 3386 TDM_ENTRY40_PORT_IDf, TDM_ENTRY41_PORT_IDf, 3387 TDM_ENTRY42_PORT_IDf, TDM_ENTRY43_PORT_IDf, 3388 TDM_ENTRY44_PORT_IDf, TDM_ENTRY45_PORT_IDf, 3389 TDM_ENTRY46_PORT_IDf, TDM_ENTRY47_PORT_IDf, 3390 TDM_ENTRY48_PORT_IDf, TDM_ENTRY49_PORT_IDf, 3391 TDM_ENTRY50_PORT_IDf, TDM_ENTRY51_PORT_IDf, 3392 TDM_ENTRY52_PORT_IDf, TDM_ENTRY53_PORT_IDf, 3393 TDM_ENTRY54_PORT_IDf, TDM_ENTRY55_PORT_IDf, 3394 TDM_ENTRY56_PORT_IDf, TDM_ENTRY57_PORT_IDf, 3395 TDM_ENTRY58_PORT_IDf, TDM_ENTRY59_PORT_IDf, 3396 TDM_ENTRY60_PORT_IDf, TDM_ENTRY61_PORT_IDf, 3397 TDM_ENTRY62_PORT_IDf, TDM_ENTRY63_PORT_IDf 3398 }; 3399 3400 if ((!SOC_IS_TRIDENT2PLUS(unit) && !SOC_IS_TITAN2PLUS(unit))) { 3401 /* Do nothing */ 3402 return SOC_E_NONE; 3403 } 3404 3405 /* Reconfigure EDB prebuffer */ 3406 3407 /* Note both pipelines' registers are written by hardware internally */ 3408 SOC_IF_ERROR_RETURN(READ_EGR_FLEXPORT_EXTRA_HOLDINGr(unit, &rval)); 3409 soc_reg_field_set(unit, EGR_FLEXPORT_EXTRA_HOLDINGr, &rval, 3410 CLPORT_CELL_COUNTSf, 0x1); 3411 soc_reg_field_set(unit, EGR_FLEXPORT_EXTRA_HOLDINGr, &rval, 3412 XLPORT_CELL_COUNTSf, 0x3); 3413 soc_reg_field_set(unit, EGR_FLEXPORT_EXTRA_HOLDINGr, &rval, 3414 ENABLEf, 0x1); 3415 SOC_IF_ERROR_RETURN(WRITE_EGR_FLEXPORT_EXTRA_HOLDINGr(unit, rval)); 3416 3417 /* Reconfigure EDB prebuffer back up calendar, for line rate 3418 * TDM calendar. Oversub related portion will be added later 3419 */ 3420 SOC_IF_ERROR_RETURN(soc_td2p_port_resource_tdm_calculate(unit, 3421 curr_port_info_size, curr_port_info, 3422 new_port_info_size, new_port_info, si_info)); 3423 3424 /* Reconfigure oversub scheduler. 3425 * Function internally determines if oversub is enabled/disabled 3426 */ 3427 SOC_IF_ERROR_RETURN(soc_td2p_ovr_sub_tdm_update(unit, 3428 curr_port_info_size, curr_port_info, 3429 new_port_info_size, new_port_info)); 3430 3431 tdm = soc_td2_td2p_tdm_sched_info_get(unit, 0); 3432 if (tdm == NULL) { 3433 return SOC_E_INIT; 3434 } 3435 3436 /* soc info has new values */ 3437 si = &SOC_INFO(unit); 3438 3439 3440 /* Configure ingress scheduler back up calendar */ 3441 for (pgw = 0; pgw < _TD2_PGWS_PER_DEV; pgw += _TD2_PGWS_PER_QUAD) { 3442 pgw_master = pgw; 3443 pgw_slave = pgw + 1; 3444 if ((pgw == 2) || (pgw == 6)) { 3445 pgw_master = pgw + 1; 3446 pgw_slave = pgw; 3447 } 3448 3449 /* coverity[negative_returns : FALSE] */ 3450 if (!si->block_valid[PGW_CL_BLOCK(unit, pgw_master)] && 3451 !si->block_valid[PGW_CL_BLOCK(unit, pgw_slave)]) { 3452 /* Both master and slave are not in use */ 3453 continue; 3454 } 3455 3456 obm_inst = pgw_master | SOC_REG_ADDR_INSTANCE_MASK; 3457 3458 SOC_IF_ERROR_RETURN(soc_reg_get(unit, PGW_TDM_CONTROLr, obm_inst, 0, 3459 &ctrl_rval64)); 3460 3461 SOC_IF_ERROR_RETURN(soc_td2p_curr_ingr_tdm_table_get(unit, 3462 obm_inst, 3463 &table_num)); 3464 /* Configure PGW line rate TDM backup calendar */ 3465 count = 0; 3466 for (base = 0; base < GET_PGW_TDM_LENGTH(unit); 3467 base += _PGW_TDM_SLOTS_PER_REG) { 3468 3469 /* Point to back up calendar */ 3470 if (table_num == 0) { 3471 reg = pgw_tdm2_regs[base / _PGW_TDM_SLOTS_PER_REG]; 3472 } else { 3473 reg = pgw_tdm_regs[base / _PGW_TDM_SLOTS_PER_REG]; 3474 } 3475 3476 COMPILER_64_ZERO(rval64); 3477 for (index = 0; index < _PGW_TDM_SLOTS_PER_REG; index++) { 3478 slot = base + index; 3479 phy_port = tdm->pgw_tdm[pgw_master / 2][slot]; 3480 if (phy_port == NUM_EXT_PORTS) { 3481 break; 3482 } 3483 soc_reg64_field32_set(unit, reg, &rval64, pgw_tdm_fields[slot], 3484 phy_port); 3485 count++; 3486 } 3487 3488 if (index != 0) { 3489 SOC_IF_ERROR_RETURN 3490 (soc_reg_set(unit, reg, obm_inst, 0, rval64)); 3491 } 3492 if (index != _PGW_TDM_SLOTS_PER_REG) { 3493 /* Due to hardware limitation, line-rate TDM wrap pointer 3494 * must be larger than 0 3495 */ 3496 if (count == 1) { 3497 3498 count = 2; 3499 3500 soc_reg64_field32_set(unit, reg, &rval64, 3501 pgw_tdm_fields[slot], 3502 PGW_LR_UNUSED_SLOT); 3503 3504 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, obm_inst, 0, 3505 rval64)); 3506 } 3507 break; 3508 } 3509 } 3510 3511 LOG_VERBOSE(BSL_LS_SOC_PORT, 3512 (BSL_META_U(unit, 3513 "pgw_master %d, count %d\n"), pgw_master, count)); 3514 3515 /* 3516 * When switching from current calendar to new calendar, there is an 3517 * intermediate state where hardware waits until end of current calendar 3518 * to switch to the new celandar. This happens when a moving table 3519 * pointer (ptr) inside the hardware reaches the value LR_TDMx_WRAP_PTR. 3520 * In the case where was no port on this pgw before flexing, 3521 * the hardware pointer will not increment to reach LR_TDMx_WRAP_PTR 3522 * value. In this case we set the value of wrap pointer to 0, so that, 3523 * inside hardware, calendar switching happens. 3524 */ 3525 if (table_num == 0) { 3526 /* Program new calendar bits */ 3527 soc_reg64_field32_set(unit, PGW_TDM_CONTROLr, &ctrl_rval64, 3528 LR_TDM2_WRAP_PTRf, count ? (count - 1) : 0); 3529 3530 soc_reg64_field32_set(unit, PGW_TDM_CONTROLr, &ctrl_rval64, 3531 LR_TDM2_ENABLEf, count ? 1 : 0); 3532 } else { 3533 /* Program new calendar bits */ 3534 soc_reg64_field32_set(unit, PGW_TDM_CONTROLr, &ctrl_rval64, 3535 LR_TDM_WRAP_PTRf, count ? (count - 1) : 0); 3536 3537 soc_reg64_field32_set(unit, PGW_TDM_CONTROLr, &ctrl_rval64, 3538 LR_TDM_ENABLEf, count ? 1 : 0); 3539 } 3540 3541 SOC_IF_ERROR_RETURN 3542 (soc_reg_set(unit, PGW_TDM_CONTROLr, obm_inst, 0, ctrl_rval64)); 3543 } 3544 3545 /* Configure ingress scheduler back up calendar */ 3546 for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) { 3547 3548 SOC_IF_ERROR_RETURN(soc_td2p_curr_egr_tdm_table_get(unit, pipe, 3549 &table_num)); 3550 3551 reg = mmu_tdm_regs[pipe]; 3552 3553 /* Program the _other_ (back up) TDM table (not the one in use)*/ 3554 if (table_num == 0) { 3555 mem = mmu_tdm_mems_1[pipe]; 3556 } else { 3557 mem = mmu_tdm_mems_0[pipe]; 3558 } 3559 3560 length = _MMU_TDM_LENGTH; 3561 for (slot = _MMU_TDM_LENGTH - 1; slot >= 0; slot--) { 3562 if (tdm->mmu_tdm[pipe][slot] != NUM_EXT_PORTS) { 3563 length = slot + 1; 3564 break; 3565 } 3566 } 3567 3568 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval)); 3569 sal_memset(entry, 0, soc_mem_entry_words(unit, mem) * sizeof(uint32)); 3570 for (slot = 0; slot < length; slot += 2) { 3571 phy_port = tdm->mmu_tdm[pipe][slot]; 3572 if (phy_port == GET_OVS_TOKEN(unit)) { 3573 mmu_port = 57; /* oppurtunist port */ 3574 } else if (phy_port == GET_IDL_TOKEN(unit)) { 3575 mmu_port = 58; /* scheduler will not pick anything */ 3576 } else if (phy_port >= NUM_EXT_PORTS) { 3577 mmu_port = 0x3f; 3578 } else { 3579 /* The BCM layer has updated the p2m mapping before calling 3580 * tdm_set, so we use it. Other way may be to find mmu_port 3581 * from the subset of new ports in new_port_info. 3582 * For other ports, updated p2m mapping may be used 3583 */ 3584 mmu_port = si->port_p2m_mapping[phy_port]; 3585 } 3586 3587 soc_mem_field32_set(unit, mem, entry, PORT_NUM_EVENf, 3588 mmu_port & 0x3F); 3589 3590 phy_port = tdm->mmu_tdm[pipe][slot + 1]; 3591 if (phy_port == GET_OVS_TOKEN(unit)) { 3592 mmu_port = 57; /* oppurtunist port */ 3593 } else if (phy_port == GET_IDL_TOKEN(unit)) { 3594 mmu_port = 58; /* scheduler will not pick anything */ 3595 } else if (phy_port >= NUM_EXT_PORTS) { 3596 mmu_port = 0x3f; 3597 } else { 3598 /* See comment above for EVENf slots */ 3599 mmu_port = si->port_p2m_mapping[phy_port]; 3600 } 3601 soc_mem_field32_set(unit, mem, entry, PORT_NUM_ODDf, 3602 mmu_port & 0x3f); 3603 SOC_IF_ERROR_RETURN 3604 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, slot / 2, entry)); 3605 } 3606 3607 /* We are programming the back up table, so we set it's 3608 * 'end' field (that is, not the current table's end field) 3609 */ 3610 if (table_num == 0) { 3611 soc_reg_field_set(unit, reg, &rval, CAL1_ENDf, slot / 2); 3612 3613 if (length & 1) { 3614 soc_reg_field_set(unit, reg, &rval, CAL1_END_SINGLEf, 1); 3615 } 3616 } else { 3617 soc_reg_field_set(unit, reg, &rval, CAL0_ENDf, slot / 2); 3618 3619 if (length & 1) { 3620 soc_reg_field_set(unit, reg, &rval, CAL0_END_SINGLEf, 1); 3621 } 3622 } 3623 3624 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval)); 3625 } 3626 3627 /* Configure IARB TDM */ 3628 for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) { 3629 mem = iarb_tdm_mems[pipe]; 3630 sal_memset(entry, 0, soc_mem_entry_words(unit, mem) * sizeof(uint32)); 3631 for (slot = 0; slot < _IARB_TDM_LENGTH; slot++) { 3632 if (slot > tdm->iarb_tdm_wrap_ptr[pipe]) { 3633 break; 3634 } 3635 soc_mem_field32_set(unit, mem, entry, TDM_SLOTf, 3636 tdm->iarb_tdm[pipe][slot]); 3637 SOC_IF_ERROR_RETURN 3638 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, slot, entry)); 3639 } 3640 } 3641 3642 /* Both pipe are expected to have same IARB TDM table length */ 3643 fields[0] = TDM_WRAP_PTRf; 3644 values[0] = tdm->iarb_tdm_wrap_ptr[0]; 3645 fields[1] = DISABLEf; 3646 values[1] = 0; 3647 fields[2] = AUX_CMICM_SLOT_ENf; 3648 values[2] = 1; 3649 fields[3] = AUX_EP_LB_SLOT_ENf; 3650 values[3] = 1; 3651 SOC_IF_ERROR_RETURN 3652 (soc_reg_fields32_modify(unit, IARB_TDM_CONTROLr, REG_PORT_ANY, 4, 3653 fields, values)); 3654 3655 /* Find ports with speeds >= 100G in any or both of the pipes */ 3656 /* In the new flex config, check if we are adding >= 100G speeds in a pipe, 3657 * or removing >=100G speeds from a pipe. If we are removing, profile_ will 3658 * set to '1'. If we are adding, profile_ will be set to '0' in the code 3659 * below. If there's no change in the pipe as far as speeds >= 100G is 3660 * concerned, we will set the same value of profile_ again. 3661 */ 3662 3663 profile_x = 1; /* For enforcing a minimum of 11 cycle same-port spacing */ 3664 profile_y = 1; /* For enforcing a minimum of 11 cycle same-port spacing */ 3665 3666 for (idx = 0; idx < new_port_info_size; idx++) { 3667 if (new_port_info[idx].speed >= 100000) { 3668 /* Set profile_* value for enforcing a minimum of 4 cycle 3669 * same-port spacing for speeds >= 100G 3670 */ 3671 if (new_port_info[idx].pipe == 0) { 3672 /* Port belongs to x-pipe */ 3673 profile_x = 0; 3674 } else { 3675 /* Port belongs to y-pipe */ 3676 profile_y = 0; 3677 } 3678 } 3679 } 3680 3681 /* If there was any port >= 100G configured during a past flexing within a 3682 * pipe, then we need to retain the same-port spacing value for 100G (0) 3683 * Search in the bigger (whole) set of ports 3684 */ 3685 for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) { 3686 pbmp = pipe ? si->ypipe_pbm : si->xpipe_pbm; 3687 SOC_PBMP_ITER(pbmp, port) { 3688 3689 if (si->port_l2p_mapping[port] == -1) { 3690 continue; 3691 } 3692 3693 if (si->port_speed_max[port] >= 100000) { 3694 if (pipe == 0) { 3695 profile_x = 0; 3696 } else { 3697 profile_y = 0; 3698 } 3699 } 3700 } 3701 } 3702 3703 /* X-pipe */ 3704 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, ES_PIPE0_MIN_SPACINGr, 3705 REG_PORT_ANY, 0, &rval)); 3706 soc_reg_field_set(unit, ES_PIPE0_MIN_SPACINGr, &rval, PROFILEf, profile_x); 3707 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, ES_PIPE0_MIN_SPACINGr, 3708 REG_PORT_ANY, 0, rval)); 3709 3710 /* Y-pipe */ 3711 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, ES_PIPE1_MIN_SPACINGr, 3712 REG_PORT_ANY, 0, &rval)); 3713 soc_reg_field_set(unit, ES_PIPE1_MIN_SPACINGr, &rval, PROFILEf, profile_y); 3714 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, ES_PIPE1_MIN_SPACINGr, 3715 REG_PORT_ANY, 0, rval)); 3716 3717 /* Configure ingress scheduler back up calendar */ 3718 3719 /* Safety check to make sure the array bounds are not crossed. If the input 3720 * array size exceeds, then we can increase size of cut_thru_en[] 3721 */ 3722 if (new_port_info_size > SOC_MAX_NUM_PORTS) { 3723 LOG_ERROR(BSL_LS_SOC_PORT, 3724 (BSL_META_U(unit, 3725 "Input array size %d (new_port_info_size) exceeds" 3726 " SOC_MAX_NUM_PORTS\n"), 3727 new_port_info_size)); 3728 return SOC_E_INTERNAL; 3729 } 3730 3731 /* Initialize cut-through settings array */ 3732 sal_memset(cut_thru_en, 0, sizeof(cut_thru_en)); 3733 3734 sal_memset(&res, 0, sizeof(soc_port_resource_t)); 3735 PBMP_PORT_ITER(unit, port) { 3736 3737 if (IS_LB_PORT(unit, port) || IS_CPU_PORT (unit, port)) { 3738 continue; 3739 } 3740 3741 /* Skip inactive ports, and ports with no mapping */ 3742 if ((SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) || 3743 (si->port_l2p_mapping[port] == -1)) { 3744 continue; 3745 } 3746 3747 /* Cut-through setting should be manipulated for line rate ports only. 3748 * Also, only speeds <= 21000 need to be considered 3749 */ 3750 if ((SOC_PBMP_MEMBER(si->oversub_pbm, port)) || 3751 (si->port_speed_max[port] > 21000)) { 3752 continue; 3753 } 3754 3755 /* Manipulate cut-through settings for the ports */ 3756 SOC_IF_ERROR_RETURN(soc_td2p_is_cut_thru_enabled(unit, 3757 port, &cut_thru_en[port])); 3758 3759 /* If cut-through is enabled, then we disable it here and re-enable 3760 * it again later in this function. If cut-through is disabled, 3761 * we don't program anything related to cut-through, here 3762 */ 3763 if (cut_thru_en[port] == TRUE) { 3764 res.logical_port = port; 3765 res.physical_port = si->port_l2p_mapping[port]; 3766 res.speed = si->port_speed_max[port]; 3767 res.oversub = 0; 3768 /* Disable cut-through for this port */ 3769 SOC_IF_ERROR_RETURN(soc_td2p_cut_thru_enable_disable(unit, &res, 3770 0)); 3771 } 3772 3773 } 3774 3775 /* Configure ingress scheduler back up calendar */ 3776 /* Note we are providing 80Usec delay only once, not twice 3777 */ 3778 sal_usleep(80); 3779 idx = 0; 3780 3781 for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) { 3782 int masters[_TD2_PGWS_PER_DEV / 2] = {0, 3, 4, 7}; /* pgw masters */ 3783 int masters_per_pipe = (sizeof(masters) / sizeof(int)) / 3784 _TD2_PIPES_PER_DEV; 3785 int pgw_num; 3786 3787 /* Switch over egress calendar */ 3788 SOC_IF_ERROR_RETURN(soc_td2p_curr_egr_tdm_table_get(unit, pipe, 3789 &table_num)); 3790 table_num ^= 0x1; 3791 3792 SOC_IF_ERROR_RETURN(soc_td2p_curr_egr_tdm_table_set(unit, pipe, 3793 table_num)); 3794 3795 for (pgw_num = 0; pgw_num < masters_per_pipe; pgw_num++, idx++) { 3796 obm_inst = masters[idx] | SOC_REG_ADDR_INSTANCE_MASK; 3797 3798 /* Switch over ingress calendar */ 3799 3800 SOC_IF_ERROR_RETURN(soc_td2p_curr_ingr_tdm_table_get(unit, 3801 obm_inst, &table_num)); 3802 table_num ^= 0x1; 3803 3804 SOC_IF_ERROR_RETURN(soc_td2p_curr_ingr_tdm_table_set(unit, 3805 obm_inst, table_num)); 3806 } 3807 } 3808 3809 /* Configure ingress scheduler back up calendar */ 3810 sal_memset(&res, 0, sizeof(soc_port_resource_t)); 3811 PBMP_PORT_ITER(unit, port) { 3812 3813 if (IS_LB_PORT(unit, port) || IS_CPU_PORT(unit, port)) { 3814 continue; 3815 } 3816 3817 /* Skip inactive ports, and ports with no mapping */ 3818 if ((SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) || 3819 (si->port_l2p_mapping[port] == -1)) { 3820 continue; 3821 } 3822 3823 /* Cut-through setting should be manipulated for line rate ports only. 3824 * Also, only speeds <= 21000 need to be considered 3825 */ 3826 if ((SOC_PBMP_MEMBER(si->oversub_pbm, port)) || 3827 (si->port_speed_max[port] > 21000)) { 3828 continue; 3829 } 3830 3831 /* Cut-through was enabled before entering this function, so we 3832 * restore it. If cut-through was disabled before entering this 3833 * function, we don't perform any programming related to it. 3834 */ 3835 if (cut_thru_en[port] == TRUE) { 3836 res.logical_port = port; 3837 res.physical_port = si->port_l2p_mapping[port]; 3838 res.speed = si->port_speed_max[port]; 3839 res.oversub = 0; 3840 /* Re-enable cut-through for this port */ 3841 SOC_IF_ERROR_RETURN(soc_td2p_cut_thru_enable_disable(unit, &res, 3842 1)); 3843 } 3844 3845 } 3846 3847 /* Reconfigure OBM thresholds */ 3848 SOC_IF_ERROR_RETURN(soc_td2p_obm_threshold_set(unit, 3849 curr_port_info_size, curr_port_info, 3850 new_port_info_size, new_port_info, 3851 lossless)); 3852 3853 /* Reconfigure EDB prebuffer */ 3854 3855 sal_usleep(1); 3856 3857 /* Note both pipelines' registers are written by hardware internally */ 3858 SOC_IF_ERROR_RETURN(READ_EGR_FLEXPORT_EXTRA_HOLDINGr(unit, &rval)); 3859 soc_reg_field_set(unit, EGR_FLEXPORT_EXTRA_HOLDINGr, &rval, 3860 CLPORT_CELL_COUNTSf, 0x1); 3861 soc_reg_field_set(unit, EGR_FLEXPORT_EXTRA_HOLDINGr, &rval, 3862 XLPORT_CELL_COUNTSf, 0x3); 3863 soc_reg_field_set(unit, EGR_FLEXPORT_EXTRA_HOLDINGr, &rval, 3864 ENABLEf, 0x0); 3865 SOC_IF_ERROR_RETURN(WRITE_EGR_FLEXPORT_EXTRA_HOLDINGr(unit, rval)); 3866 3867 3868 return SOC_E_NONE; 3869 } 3870 3871 /* 3872 * Function: 3873 * soc_td2p_port_resource_pgw_set 3874 * Purpose: 3875 * Reconfigure PGW registers in flex port sequence 3876 * In this function following registers will be initialized. 3877 * This function will do two things, 3878 * 1. clear all registers for old ports which exists in pre-Flex status 3879 * 2. initialize all registers for new ports which exists in post-Flex 3880 * status 3881 * 3882 * Parameters: 3883 * unit - (IN) Unit number. 3884 * pre_num_res - (IN) Number of resource data which exist in pre-Flex 3885 * status 3886 * post_num_res - (IN) Number of resource data which exist in post-Flex 3887 * status 3888 * pre_res - (IN) Resource data structure pointer in pre-Flex status 3889 * post_res - (IN) Resource data structure pointer in post-Flex status 3890 * lossless - (IN) MMU lossless information 3891 * 3892 * Returns: 3893 * SOC_E_XXX 3894 * Note: 3895 * - Assumes FlexPort cases are valid. 3896 * - Pre-FlexPort array 3897 * Contains current information on ports to be modified after 3898 * the FlexPort operation. This should include ports whose 3899 * mappings are either deleted or remapped. 3900 * - Post-FlexPort array 3901 * Contains information on new configuration for 3902 * ports that are active (present) after the FlexPort operation. 3903 * This should include ports whose mappings that are remapped or new. 3904 */ 3905 int 3906 soc_td2p_port_resource_pgw_set(int unit, 3907 int pre_num_res, soc_port_resource_t *pre_res, 3908 int post_num_res, soc_port_resource_t *post_res, 3909 int lossless) 3910 { 3911 soc_esw_portctrl_pgw_t data; 3912 int i; 3913 3914 SOC_IF_ERROR_RETURN( 3915 _soc_td2p_resource_data_check(unit, pre_num_res, pre_res)); 3916 SOC_IF_ERROR_RETURN( 3917 _soc_td2p_resource_data_check(unit, post_num_res, post_res)); 3918 3919 /* 3920 * NOTE: Mode is set in a per-XLPORT register, so 3921 * we only need to update the mode in a port. 3922 */ 3923 for (i = 0; i < post_num_res; i++) { 3924 data.mode = post_res[i].mode; 3925 data.lanes = post_res[i].num_lanes; 3926 data.port_index = post_res[i].lane_info[0]->port_index; 3927 data.flags = 0x0; 3928 3929 SOC_IF_ERROR_RETURN(soc_esw_portctrl_pgw_reconfigure(unit, 3930 post_res[i].logical_port, 3931 post_res[i].physical_port, &data)); 3932 } 3933 3934 3935 SOC_IF_ERROR_RETURN 3936 (soc_td2p_pgw_obm_set(unit, 3937 pre_num_res, pre_res, 3938 post_num_res, post_res)); 3939 3940 SOC_IF_ERROR_RETURN(soc_td2p_pgw_port_hw_default_set(unit, 3941 pre_num_res, pre_res, 3942 lossless)); 3943 SOC_IF_ERROR_RETURN(soc_td2p_pgw_port_sw_default_set(unit, 3944 post_num_res, post_res, 3945 lossless)); 3946 return SOC_E_NONE; 3947 } 3948 3949 /* 3950 * Function: 3951 * soc_td2p_port_resource_ip_set 3952 * Purpose: 3953 * Reconfigure IP. 3954 * Parameters: 3955 * unit - (IN) Unit number. 3956 * curr_port_info_size - (IN) Size of current port information array 3957 * curr_port_info - (IN) Per-port array with current flexing info 3958 * new_port_info_size - (IN) Size of new port information array 3959 * new_port_info - (IN) Per-port array with new flexing info 3960 * si_info - (IN) Contains subset of fields from soc_info_t structure 3961 * prior to the flexing operation 3962 * Returns: 3963 * SOC_E_XXX 3964 * Note: 3965 * Assumptions 3966 * - soc info structure members have been updated to reflect the latest 3967 * flexing operation 3968 * - There is no overlapping between logical or physical ports in the 3969 * arrays passed, example, operations like 4x10->1x40->4x10 on the same 3970 * set of ports have been rejected at bcm layer itself, and do not reach 3971 * this function 3972 * - Pre-FlexPort array 3973 * Contains current information on ports to be modified after 3974 * the FlexPort operation. This should include ports whose 3975 * mappings are either deleted or remapped. 3976 * - Post-FlexPort array 3977 * Contains information on new configuration for 3978 * ports that are active (present) after the FlexPort operation. 3979 * This should include ports whose mappings that are remapped or new. 3980 */ 3981 int soc_td2p_port_resource_ip_set(int unit, int curr_port_info_size, 3982 soc_port_resource_t *curr_port_info, 3983 int new_port_info_size, 3984 soc_port_resource_t *new_port_info, 3985 soc_td2p_info_t *si_info) 3986 { 3987 soc_info_t *si; 3988 soc_mem_t mem; 3989 ing_physical_to_logical_port_number_mapping_table_entry_t entry; 3990 int port, phy_port; 3991 int num_phy_port; 3992 3993 si = &SOC_INFO(unit); 3994 3995 /* Ingress physical to logical port mapping */ 3996 mem = ING_PHYSICAL_TO_LOGICAL_PORT_NUMBER_MAPPING_TABLEm; 3997 num_phy_port = soc_mem_index_count(unit, mem); 3998 3999 for (phy_port = 0; phy_port < num_phy_port; phy_port++) { 4000 sal_memset(&entry, 0, sizeof(entry)); 4001 4002 /* The p2l mapping has been updated before this function is called */ 4003 port = si->port_p2l_mapping[phy_port]; 4004 4005 soc_mem_field32_set(unit, mem, &entry, LOGICAL_PORT_NUMBERf, 4006 port == -1 ? 0x7F : port); 4007 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ALL, phy_port, 4008 &entry)); 4009 } 4010 4011 return SOC_E_NONE; 4012 } 4013 4014 /* 4015 * Function: 4016 * soc_td2p_port_resource_ep_set 4017 * Purpose: 4018 * Reconfigure EP. 4019 * Parameters: 4020 * unit - (IN) Unit number. 4021 * curr_port_info_size - (IN) Size of current port information array 4022 * curr_port_info - (IN) Per-port array with current flexing info 4023 * new_port_info_size - (IN) Size of new port information array 4024 * new_port_info - (IN) Per-port array with new flexing info 4025 * si_info - (IN) Contains subset of fields from soc_info_t structure 4026 * prior to the flexing operation 4027 * Returns: 4028 * SOC_E_XXX 4029 * Note: 4030 * Assumptions 4031 * - soc info structure members have been updated to reflect the latest 4032 * flexing operation 4033 * - There is no overlapping between logical or physical ports in the 4034 * arrays passed, example, operations like 4x10->1x40->4x10 on the same 4035 * set of ports have been rejected at bcm layer itself, and do not reach 4036 * this function 4037 * - Pre-FlexPort array 4038 * Contains current information on ports to be modified after 4039 * the FlexPort operation. This should include ports whose 4040 * mappings are either deleted or remapped. 4041 * - Post-FlexPort array 4042 * Contains information on new configuration for 4043 * ports that are active (present) after the FlexPort operation. 4044 * This should include ports whose mappings that are remapped or new. 4045 */ 4046 int soc_td2p_port_resource_ep_set(int unit, int curr_port_info_size, 4047 soc_port_resource_t *curr_port_info, 4048 int new_port_info_size, 4049 soc_port_resource_t *new_port_info, 4050 soc_td2p_info_t *si_info) 4051 { 4052 soc_info_t *si; 4053 uint32 rval; 4054 int num_port, port, idx, phy_port; 4055 4056 si = &SOC_INFO(unit); 4057 4058 /* Ingress logical to physical port mapping */ 4059 num_port = soc_mem_index_count(unit, PORT_TABm) - 1; 4060 4061 /* Egress logical to physical port mapping */ 4062 for (port = 0; port < num_port; port++) { 4063 /* 4064 * Use logical to physical number mapping from soc info structure 4065 * since it has been updated before this function is called 4066 */ 4067 phy_port = si->port_l2p_mapping[port]; 4068 4069 rval = 0; 4070 soc_reg_field_set(unit, EGR_LOGICAL_TO_PHYSICAL_PORT_NUMBER_MAPPINGr, 4071 &rval, PHYSICAL_PORT_NUMBERf, 4072 phy_port == -1 ? 0xFF : phy_port); 4073 SOC_IF_ERROR_RETURN 4074 (WRITE_EGR_LOGICAL_TO_PHYSICAL_PORT_NUMBER_MAPPINGr(unit, port, 4075 rval)); 4076 } 4077 4078 /* Clear counters for the newly added ports */ 4079 for (idx = 0; idx < new_port_info_size; idx++) { 4080 SOC_IF_ERROR_RETURN(soc_td2p_ep_counters_clear(unit, 4081 &new_port_info[idx])); 4082 } 4083 4084 return SOC_E_NONE; 4085 } 4086 4087 /* 4088 * Function: 4089 * soc_td2p_port_resource_mmu_mapping_set 4090 * Purpose: 4091 * Set the HW MMU Port mappings. 4092 * Parameters: 4093 * unit - (IN) Unit number. 4094 * nport - (IN) Number of elements in array resource. 4095 * resource - (IN) Port Resource FlexPort configuration. 4096 * Returns: 4097 * SOC_E_XXX 4098 * Note: 4099 * Assumes FlexPort cases are valid. 4100 * Assumes SOC INFO data structure has been updated. 4101 */ 4102 int 4103 soc_td2p_port_resource_mmu_mapping_set(int unit, int nport, 4104 soc_port_resource_t *resource) 4105 { 4106 soc_info_t *si = &SOC_INFO(unit); 4107 soc_port_resource_t *pr; 4108 int i; 4109 int logic_port; 4110 int phy_port; 4111 uint32 rval; 4112 4113 LOG_VERBOSE(BSL_LS_SOC_PORT, 4114 (BSL_META_U(unit, 4115 "SOC MMU Port Mappings Set\n"))); 4116 4117 for (i = 0, pr = &resource[0]; i < nport; i++, pr++) { 4118 if (pr->physical_port == -1) { 4119 logic_port = 0x7F; 4120 phy_port = 0xFF; 4121 4122 /* Clear MMU port info */ 4123 SOC_IF_ERROR_RETURN( 4124 soc_td2p_mmu_port_resource_clear(unit, 4125 pr->logical_port)); 4126 } else { 4127 logic_port = pr->logical_port; 4128 phy_port = pr->physical_port; 4129 } 4130 4131 /* 4132 * Skip for legacy inactive configurations since 4133 * MMU mappings are kept the same. 4134 */ 4135 if (pr->flags & SOC_PORT_RESOURCE_I_MAP) { 4136 LOG_VERBOSE(BSL_LS_SOC_PORT, 4137 (BSL_META_U(unit, 4138 " Skip port with inactive configuration, " 4139 "mappings are kept the same, " 4140 "mmu=%d logical=%d physical=%d\n"), 4141 si->port_p2m_mapping 4142 [si->port_l2p_mapping[pr->logical_port]], 4143 pr->logical_port, 4144 si->port_l2p_mapping[pr->logical_port])); 4145 continue; 4146 } 4147 4148 4149 rval = 0; 4150 soc_reg_field_set(unit, MMU_PORT_TO_PHY_PORT_MAPPINGr, &rval, 4151 PHY_PORTf, phy_port); 4152 SOC_IF_ERROR_RETURN 4153 (soc_reg32_set(unit, MMU_PORT_TO_PHY_PORT_MAPPINGr, 4154 pr->logical_port, 0, rval)); 4155 4156 rval = 0; 4157 soc_reg_field_set(unit, MMU_PORT_TO_LOGIC_PORT_MAPPINGr, &rval, 4158 LOGIC_PORTf, logic_port); 4159 SOC_IF_ERROR_RETURN 4160 (soc_reg32_set(unit, MMU_PORT_TO_LOGIC_PORT_MAPPINGr, 4161 pr->logical_port, 0, rval)); 4162 4163 LOG_VERBOSE(BSL_LS_SOC_PORT, 4164 (BSL_META_U(unit, 4165 " MMU port mappings: " 4166 "mmu=%d logical=%d physical=%d\n"), 4167 si->port_p2m_mapping 4168 [si->port_l2p_mapping[pr->logical_port]], 4169 logic_port, phy_port)); 4170 } 4171 4172 return SOC_E_NONE; 4173 } 4174 4175 4176 /* 4177 * Function: 4178 * soc_td2p_port_resource_mmu_set 4179 * Purpose: 4180 * Called to reconfigure the MMU hardware. 4181 * Parameters: 4182 * unit - (IN) Device Number 4183 * nport - (IN) The number of port modifications in flexport_data 4184 * flexport_data - (IN) An array of port changes that are being done 4185 * Returns: 4186 * SOC_E_NONE if parameters are valid, an error otherwise. 4187 * Note: 4188 * Assumes FlexPort cases are valid. 4189 * Assumes SOC INFO data structure has been updated. 4190 */ 4191 int 4192 soc_td2p_port_resource_mmu_set(int unit, int nport, 4193 soc_port_resource_t *flexport_data) 4194 { 4195 int i, rv = SOC_E_NONE; 4196 int * ports; 4197 4198 /* Before we initialize LLS for the newly flexed ports, 4199 * let's take a moment to update _td2_invalid_ptr since 4200 * flex operation could have added new mmu ports. 4201 * And also update the LLS memories with INVALID PARENT 4202 * values 4203 */ 4204 SOC_IF_ERROR_RETURN(soc_td2p_lls_reinit_invalid_pointers(unit)); 4205 SOC_IF_ERROR_RETURN(soc_td2p_lls_reset_flex(unit)); 4206 4207 /* Update MMU Port Mappings */ 4208 SOC_IF_ERROR_RETURN 4209 (soc_td2p_port_resource_mmu_mapping_set(unit, nport, 4210 flexport_data)); 4211 4212 /* Configure all MMU registers for new ports */ 4213 for (i = 0; i < nport; i++) { 4214 if (flexport_data[i].physical_port != -1) { 4215 /* a physical port of -1 indicates it's being deleted, so here 4216 we're adding */ 4217 SOC_IF_ERROR_RETURN( 4218 soc_td2p_mmu_port_resource_set(unit, flexport_data[i].logical_port, 4219 flexport_data[i].speed, 4220 (flexport_data[i].flags & SOC_PORT_RESOURCE_I_MAP))); 4221 } 4222 } 4223 4224 /* Copy the logical ports into a bcm_ports_t array because 4225 bcm_td2p_update_base_queue_num in src/bcm/esw/trident2/cosq.c has no 4226 concept of what a soc_port_resource_t is. */ 4227 ports = sal_alloc(sizeof(int) * nport, "flexport_ports"); 4228 if (ports == NULL) { 4229 return SOC_E_MEMORY; 4230 } 4231 for (i = 0; i < nport; i++) { 4232 ports[i] = flexport_data[i].logical_port; 4233 } 4234 4235 /* Update the logical port and queue mappings in memory and registers */ 4236 if (td2p_flexport_cb) { 4237 rv = td2p_flexport_cb(unit, nport, ports); 4238 } 4239 4240 /* free up the ports array */ 4241 sal_free(ports); 4242 4243 return rv; 4244 } 4245 4246 void 4247 soc_td2p_num_hsp_reserved_reset(int unit) 4248 { 4249 num_hsp_to_reserve[0] = 0; 4250 num_hsp_to_reserve[1] = 0; 4251 return; 4252 } 4253 4254 /* 4255 * Function: 4256 * soc_td2p_num_hsp_reserved_per_pipe 4257 * Purpose: 4258 * This function calculates the number of HSP ports to reserve per pipe. 4259 * It does by using the following algorithm: 4260 * - device speed 4261 * - for High clock frequency systems ( > 760), it takes into consideration 4262 * the number of TSC-12's that are flex enabled 4263 * - for Lower clock frequency systems, it looks at the number of port macros 4264 * (TSC-4's) that are flex enabled * Parameters: 4265 * Parameters 4266 * unit - (IN) Device Number 4267 * pipe - (IN) The pipe that will be checked to see how many 4268 * HSP need to be reserved. 4269 * num_hsp - (OUT) The number of HSP that need to be reserved 4270 * for the specified pipe. 4271 * Returns: 4272 * SOC_E_NONE if parameters are valid, an error otherwise. 4273 * Note: 4274 */ 4275 int 4276 soc_td2p_num_hsp_reserved_per_pipe(int unit, int pipe, int *num_hsp) 4277 { 4278 int port_macro, pm_flex_enabled = 0, temp_num_hsp = 0, port = 0; 4279 int i, phy_port, skip_port; 4280 soc_info_t *si; 4281 soc_pbmp_t pbmp; 4282 int phy_ports_x[] = {1, 21, 33, 53}; 4283 int phy_ports_y[] = {65, 85, 97, 117}; 4284 int * phy_ports = NULL; 4285 4286 si = &SOC_INFO(unit); 4287 4288 if (num_hsp == NULL) { 4289 return SOC_E_PARAM; 4290 } 4291 4292 *num_hsp = 0; 4293 4294 /* If we're at a sufficiently high frequency, 4295 only check the first physical port of every TSC-12 PM: 4296 physical ports 1, 21, 33, 53, 65, 85, 97, 117. 4297 This is because only 100G+ ports are considered HSP. */ 4298 if (si->frequency >= 760) { 4299 if (pipe == 0) { 4300 phy_ports = phy_ports_x; 4301 } else { 4302 phy_ports = phy_ports_y; 4303 } 4304 /* If a PGW is flexport capable or if it's 100G but not flex capable, 4305 a HSP MMU Port needs to be saved for it; it may not be given 4306 to a non-hsp port. */ 4307 for(i = 0; i < _TD2_PGWS_PER_PIPE; i++) { 4308 if(soc_td2p_is_port_flex_enable(unit, phy_ports[i])) { 4309 port = si->port_p2l_mapping[phy_ports[i]]; 4310 temp_num_hsp++; 4311 } else { 4312 port = si->port_p2l_mapping[phy_ports[i]]; 4313 /* the PGW is NOT port flex enabled, but still requires a HSP 4314 so mark it as reserved. */ 4315 if (si->port_speed_max[port] >= 100000 || 4316 soc_property_port_get(unit, port, spn_PORT_SCHED_HSP, 0)) { 4317 temp_num_hsp++; 4318 } 4319 } 4320 } 4321 /* Go through all the logical ports, skipping the ones mapped to 4322 the first of the PGWs 4323 since they were checked above, and see if they are port_sched_hsp */ 4324 pbmp = pipe ? si->ypipe_pbm : si->xpipe_pbm; 4325 SOC_PBMP_ITER(pbmp, port) { 4326 phy_port = si->port_l2p_mapping[port]; 4327 skip_port = 0; 4328 4329 /* skip the port if it was already counted above */ 4330 for(i = 0; i < _TD2_PGWS_PER_PIPE; i++) { 4331 if(phy_port == phy_ports[i]) { 4332 skip_port = 1; 4333 break; 4334 } 4335 } 4336 if(skip_port == 0) { 4337 /* if the logical port was declared port_sched_hsp, 4338 reserve HSP */ 4339 if(soc_property_port_get(unit, port, spn_PORT_SCHED_HSP, 0)) { 4340 temp_num_hsp++; 4341 } 4342 } 4343 } 4344 } else { 4345 /* Otherwise, check each PM on the specified pipe because 4346 we'll need to at least reserve 1 HSP port per port macro. 4347 This function does NOT determine if a T2OQ needs to be 4348 reserved too. */ 4349 for (port_macro = pipe * _TD2P_NUM_TSC4_PER_PIPE; 4350 port_macro < (pipe * _TD2P_NUM_TSC4_PER_PIPE) + 4351 _TD2P_NUM_TSC4_PER_PIPE; port_macro++) { 4352 SOC_IF_ERROR_RETURN( 4353 soc_td2p_port_macro_flex_enabled(unit, port_macro, &pm_flex_enabled)); 4354 4355 /* If a PM is flexport capable or if it's 40G but not flex capable, 4356 a HSP MMU Port needs to be saved for it; it may not be given 4357 to a non-hsp port. */ 4358 if (pm_flex_enabled == 1) { 4359 temp_num_hsp++; 4360 } else { 4361 phy_port = soc_td2p_pm_to_1st_port_tsc4[port_macro]; 4362 port = si->port_p2l_mapping[phy_port]; 4363 /* the PM is NOT port flex enabled, but still requires a HSP 4364 so mark it as reserved. */ 4365 if (si->port_speed_max[port] >= 40000 || 4366 soc_property_port_get(unit, port, spn_PORT_SCHED_HSP, 0)) { 4367 temp_num_hsp++; 4368 } 4369 } 4370 } 4371 4372 /* Go through all the logical ports, skipping the ones mapped to 4373 the port macros 4374 since they were checked above, and see if they are port_sched_hsp */ 4375 pbmp = pipe ? si->ypipe_pbm : si->xpipe_pbm; 4376 SOC_PBMP_ITER(pbmp, port) { 4377 phy_port = si->port_l2p_mapping[port]; 4378 skip_port = 0; 4379 4380 /* skip the port if it was already counted above */ 4381 for (port_macro = pipe * _TD2P_NUM_TSC4_PER_PIPE; 4382 port_macro < (pipe * _TD2P_NUM_TSC4_PER_PIPE) + 4383 _TD2P_NUM_TSC4_PER_PIPE; port_macro++) { 4384 if(phy_port == 4385 soc_td2p_pm_to_1st_port_tsc4[port_macro]) { 4386 skip_port = 1; 4387 break; 4388 } 4389 } 4390 if(skip_port == 0) { 4391 /* if the logical port was declared port_sched_hsp, 4392 reserve HSP */ 4393 if(soc_property_port_get(unit, port, spn_PORT_SCHED_HSP, 0)) { 4394 temp_num_hsp++; 4395 } 4396 } 4397 } 4398 } 4399 /* Only allow 16 HSP maximum per pipe */ 4400 if(temp_num_hsp > SOC_TD2_NUM_HSP_MMU_PORTS_PER_PIPE) { 4401 *num_hsp = SOC_TD2_NUM_HSP_MMU_PORTS_PER_PIPE; 4402 } else { 4403 *num_hsp = temp_num_hsp; 4404 } 4405 4406 return SOC_E_NONE; 4407 } 4408 4409 4410 4411 /* Tells if a port macro (indexed by TSC4, not TSC12) is flex port enabled. 4412 * 4413 * Port macro flex on or off is determined by the first port in that macro. 4414 * For TSC12 it's the first port in the first TSC4. For a TSC4 that is NOT 4415 * part of a TSC12, it's also the first port of that port macro. For a TSC4 4416 * that is a part of a TSC12, refer to the first port of the first port macro 4417 * for that TSC12. 4418 * 4419 * Parameters: 4420 * unit - (IN) Unit number. 4421 * port_macro - (IN) port macro desired 4422 * flex_enabled - (OUT) whether the port macro is enabled or disabled 4423 * 4424 * Returns: 4425 * SOC_E_xxx 4426 */ 4427 int 4428 soc_td2p_port_macro_flex_enabled(int unit, int port_macro, int * flex_enabled) 4429 { 4430 soc_info_t *si; 4431 int port_num = -1; 4432 4433 si = &SOC_INFO(unit); 4434 4435 if ((port_macro < 0) || (port_macro > 31)) { 4436 return SOC_E_PARAM; 4437 } 4438 4439 /* If SKU is max frequency, check flexport for TSC-12 and then 4440 individual TSC-4. 4441 Else, check each individual TSC-4 (not grouped as TSC-12). */ 4442 if (si->frequency >= 760) { 4443 port_num = soc_td2p_pm_to_1st_port_tsc12[port_macro]; 4444 } else { 4445 port_num = soc_td2p_pm_to_1st_port_tsc4[port_macro]; 4446 } 4447 4448 *flex_enabled = soc_td2p_is_port_flex_enable(unit, port_num); 4449 4450 return SOC_E_NONE; 4451 } 4452 4453 /* Function to reserve cells for CutThru(CT) and Flex ports 4454 * Parameters: 4455 * unit - (IN) Unit number. 4456 * pipe - (IN) Pipe number 4457 * flex - (IN) Config has Flex ports or Not 4458 * rsvd_buffer - (OUT) Buffers reserved per resource (Ing/Egr/ASF) 4459 * Returns: 4460 * SOC_E_xxx 4461 */ 4462 int 4463 soc_td2p_mmu_additional_buffer_reserve(int unit, int pipe, int flex, 4464 _soc_mmu_rsvd_buffer_t *rsvd_buffer) 4465 { 4466 soc_info_t *si; 4467 int pg_min_cells = 0, qgrp_min_cells = 0, hdrm_cells = 0, asf_cells = 0; 4468 int total_reserve = 0; 4469 int lossless = 0; 4470 int mcq_entry = 0; 4471 4472 int i, j, start_port, logical_port, start_pm, end_pm; 4473 int pm_flex_enabled = 0; 4474 4475 COMPILER_REFERENCE(si); 4476 si = &SOC_INFO(unit); 4477 4478 if ((pipe >= NUM_PIPE(unit)) || (!rsvd_buffer)) { 4479 return SOC_E_PARAM; 4480 } 4481 4482 /* returning if flex is true. flex true indicates the legacy flexport ':i' case is 4483 enabled */ 4484 if (flex) { 4485 return SOC_E_NONE; 4486 } 4487 4488 lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 1); 4489 4490 /* if we're on pipe 1, start at the 2nd half of the macros. Otherwise, 4491 start at the 1st half */ 4492 if(pipe) { 4493 start_pm = _TD2P_NUM_TSC4_PER_PIPE; 4494 end_pm = 2*_TD2P_NUM_TSC4_PER_PIPE; 4495 } else { 4496 start_pm = 0; 4497 end_pm = _TD2P_NUM_TSC4_PER_PIPE; 4498 } 4499 4500 /* Per pipe, calculate the memory required on a per port macro (TSC4) basis */ 4501 for (i = start_pm; i < end_pm; i++) { 4502 SOC_IF_ERROR_RETURN( 4503 soc_td2p_port_macro_flex_enabled(unit, i, &pm_flex_enabled)); 4504 4505 /* if this port macro is flex enabled, allocate memory for it accordingly */ 4506 if (pm_flex_enabled == 1) { 4507 /* Reserved Buffer for Flex Port Macro when Flex Port is enabled in 4508 device */ 4509 if (lossless) { 4510 hdrm_cells = (_TD2P_RSVD_BUF_FLEX_HDRM_LOSSLESS 4511 * _TD2P_NUM_PORTS_PER_TSC4); 4512 pg_min_cells = (_TD2P_MMU_RSVD_BUF_FLEX_PGMIN_LOSSLESS 4513 * _TD2P_NUM_PORTS_PER_TSC4); 4514 qgrp_min_cells = 0; 4515 asf_cells = (_TD2P_RSVD_BUF_FLEX_ASF 4516 * _TD2P_NUM_PORTS_PER_TSC4); 4517 } else { 4518 hdrm_cells = 0; 4519 pg_min_cells = 0; 4520 qgrp_min_cells = (_TD2P_RSVD_BUF_FLEX_QGRP 4521 * _TD2P_NUM_PORTS_PER_TSC4); 4522 4523 asf_cells = (_TD2P_RSVD_BUF_FLEX_ASF 4524 * _TD2P_NUM_PORTS_PER_TSC4); 4525 } 4526 mcq_entry = _TD2P_MMU_NUM_MCQ_PORT_MACRO * 4527 _TD2P_MMU_PER_COSQ_EGRESS_QENTRY_RSVD * 4528 _TD2P_NUM_PORTS_PER_TSC4; 4529 } else { 4530 /*For port modules that are in non-flex mode, buffer is reserved 4531 per port (not port macro). 4532 4533 Here we are calculating the buffer requirements for this TSC4 on 4534 a per port basis. */ 4535 hdrm_cells = 0; 4536 pg_min_cells = 0; 4537 qgrp_min_cells = 0; 4538 asf_cells = 0; 4539 mcq_entry = 0; 4540 4541 start_port = (i * _TD2P_NUM_PORTS_PER_TSC4) + 1; 4542 for (j = start_port; j < start_port + _TD2P_NUM_PORTS_PER_TSC4; j++) { 4543 /* figure out from the logical port what the speed of this port is */ 4544 logical_port = si->port_p2l_mapping[j]; 4545 if (logical_port == -1) { 4546 continue; 4547 } 4548 4549 if (si->port_speed_max[logical_port] >= 100000) { 4550 if (lossless) { 4551 hdrm_cells += _TD2P_RSVD_BUF_NON_FLEX_100G_HDRM_LOSSLESS; 4552 pg_min_cells += _TD2P_RSVD_BUF_NON_FLEX_PGMIN; 4553 qgrp_min_cells += _TD2P_RSVD_BUF_NON_FLEX_QGRP; 4554 asf_cells += _TD2P_RSVD_BUF_NON_FLEX_ASF; 4555 } else { 4556 qgrp_min_cells += _TD2P_RSVD_BUF_NON_FLEX_QGRP; 4557 asf_cells += _TD2P_RSVD_BUF_NON_FLEX_ASF; 4558 } 4559 } else if (si->port_speed_max[logical_port] >= 40000) { 4560 if (lossless) { 4561 hdrm_cells += _TD2P_RSVD_BUF_NON_FLEX_40G_HDRM_LOSSLESS; 4562 pg_min_cells += _TD2P_RSVD_BUF_NON_FLEX_PGMIN; 4563 qgrp_min_cells += _TD2P_RSVD_BUF_NON_FLEX_QGRP; 4564 asf_cells += _TD2P_RSVD_BUF_NON_FLEX_ASF; 4565 } else { 4566 qgrp_min_cells += _TD2P_RSVD_BUF_NON_FLEX_QGRP; 4567 asf_cells += _TD2P_RSVD_BUF_NON_FLEX_ASF; 4568 } 4569 } else if (si->port_speed_max[logical_port] >= 20000) { 4570 if (lossless) { 4571 hdrm_cells += _TD2P_RSVD_BUF_NON_FLEX_20G_HDRM_LOSSLESS; 4572 pg_min_cells += _TD2P_RSVD_BUF_NON_FLEX_PGMIN; 4573 qgrp_min_cells += _TD2P_RSVD_BUF_NON_FLEX_QGRP; 4574 asf_cells += _TD2P_RSVD_BUF_NON_FLEX_ASF; 4575 } else { 4576 qgrp_min_cells += _TD2P_RSVD_BUF_NON_FLEX_QGRP; 4577 asf_cells += _TD2P_RSVD_BUF_NON_FLEX_ASF; 4578 } 4579 } else { 4580 if (lossless) { 4581 hdrm_cells += _TD2P_RSVD_BUF_NON_FLEX_10G_HDRM_LOSSLESS; 4582 pg_min_cells += _TD2P_RSVD_BUF_NON_FLEX_PGMIN; 4583 qgrp_min_cells += _TD2P_RSVD_BUF_NON_FLEX_QGRP; 4584 asf_cells += _TD2P_RSVD_BUF_NON_FLEX_10G_ASF; 4585 } else { 4586 qgrp_min_cells += _TD2P_RSVD_BUF_NON_FLEX_QGRP; 4587 asf_cells += _TD2P_RSVD_BUF_NON_FLEX_10G_ASF; 4588 } 4589 } 4590 mcq_entry += soc_td2p_mcq_entries_rsvd_port(unit, logical_port); 4591 } 4592 } 4593 4594 /* Add what was calculated for the port macro to the total */ 4595 rsvd_buffer->ing_rsvd_cells += (hdrm_cells + pg_min_cells); 4596 rsvd_buffer->egr_rsvd_cells += qgrp_min_cells; 4597 rsvd_buffer->asf_rsvd_cells += asf_cells; 4598 rsvd_buffer->mcq_entry_rsvd += mcq_entry; 4599 } 4600 4601 total_reserve = rsvd_buffer->ing_rsvd_cells; 4602 total_reserve += rsvd_buffer->egr_rsvd_cells; 4603 total_reserve += rsvd_buffer->asf_rsvd_cells; 4604 4605 LOG_VERBOSE(BSL_LS_SOC_MMU, 4606 (BSL_META_U(unit, 4607 "MMU config: Cells rsvd for Pipe %d," 4608 " Flex/ASF per pipe: %d, Ing: %d," 4609 " Egr: %d, ASF: %d MCQ %d\n"), 4610 pipe, total_reserve, rsvd_buffer->ing_rsvd_cells, 4611 rsvd_buffer->egr_rsvd_cells, 4612 rsvd_buffer->asf_rsvd_cells, 4613 rsvd_buffer->mcq_entry_rsvd)); 4614 4615 return SOC_E_NONE; 4616 } 4617 4618 STATIC int 4619 soc_td2p_mmu_config_init_port(int unit, int port) 4620 { 4621 int rv; 4622 int lossless; 4623 _soc_mmu_cfg_buf_t *buf; 4624 _soc_mmu_device_info_t devcfg; 4625 4626 buf = soc_mmu_cfg_alloc(unit); 4627 if (!buf) { 4628 return SOC_E_MEMORY; 4629 } 4630 4631 lossless = soc_property_get(unit, spn_MMU_LOSSLESS, 1); 4632 4633 _soc_td2_mmu_init_dev_config(unit, &devcfg, lossless); 4634 /* Calculate the buf - global as well as per port 4635 * but _soc_td2_mmu_config_buf_set_hw_port is only made 4636 * for that port - since it is flex operation - we don't 4637 * touch any other port */ 4638 _soc_td2_mmu_config_buf_default(unit, buf, &devcfg, lossless); 4639 if (soc_property_get(unit, spn_MMU_CONFIG_OVERRIDE, 1) == 0) { 4640 _soc_mmu_cfg_buf_read(unit, buf, &devcfg); 4641 } 4642 rv = _soc_mmu_cfg_buf_check(unit, buf, &devcfg); 4643 if (SOC_FAILURE(rv)) { 4644 LOG_VERBOSE(BSL_LS_SOC_COMMON, 4645 (BSL_META_U(unit, 4646 "MMU config: Use default setting\n"))); 4647 _soc_td2_mmu_config_buf_default_global(unit, buf, &devcfg, lossless); 4648 _soc_td2_mmu_config_buf_default_port(unit, port, buf, &devcfg, lossless); 4649 _soc_mmu_cfg_buf_calculate(unit, buf, &devcfg); 4650 } 4651 rv = _soc_td2_mmu_config_buf_set_hw_port(unit, port, buf, &devcfg, lossless); 4652 4653 soc_mmu_cfg_free(unit, buf); 4654 4655 LOG_VERBOSE(BSL_LS_SOC_COMMON, 4656 (BSL_META_U(unit, 4657 "MMU THDI/THDO init done\n"))); 4658 return rv; 4659 } 4660 4661 4662 /* 4663 * Function: 4664 * soc_td2p_mmu_flexport_map_validate 4665 * Purpose: 4666 * Validate and allocate/deallocate MMU port assignments. 4667 * New MMU port assignments are returned in argument. 4668 * Parameters: 4669 * unit - (IN) Device Number 4670 * nport - (IN) The number of port modifications in flexport_data 4671 * flexport_data - (IN/OUT) An array of port changes that are being done. 4672 * Returns MMU ports assignment. 4673 * Returns: 4674 * SOC_E_NONE if parameters are valid, an error otherwise. 4675 */ 4676 int 4677 soc_td2p_mmu_flexport_map_validate(int unit, int nport, 4678 soc_port_resource_t * flexport_data) 4679 { 4680 return soc_td2p_mmu_flexport_allocate_deallocate_ports(unit, nport, 4681 flexport_data); 4682 } 4683 4684 /* 4685 * Function: 4686 * soc_td2p_mmu_flexport_allocate_deallocate_ports 4687 * Purpose: 4688 * Allocate or deallocate ports in software. This function frees up 4689 * mmu ports or allocates them in software. When apply is 0, 4690 * flexport_data[x].mmu_port needs to be filled in. When apply is 1, 4691 * flexport_data[x].mmu_port is valid and needs to be assigned in the 4692 * port_p2m_mapping[]. 4693 * Parameters: 4694 * unit - (IN) Device Number 4695 * nport - (IN) The number of port modifications in flexport_data 4696 * flexport_data - (IN/OUT) An array of port changes that are being done 4697 * Returns: 4698 * SOC_E_NONE if parameters are valid, an error otherwise. 4699 */ 4700 int 4701 soc_td2p_mmu_flexport_allocate_deallocate_ports(int unit, int nport, 4702 soc_port_resource_t * flexport_data) 4703 { 4704 int i, j; 4705 int phy_port; 4706 int mmu_port; 4707 int pipe; 4708 int start_mmu_port; 4709 int end_mmu_port; 4710 int port_max_speed = 0; 4711 int mmu_ports_used[TD2P_PIPES_PER_DEV * _TD2_PORTS_PER_PIPE]; 4712 int flexport_max_speed = -1; 4713 int flexport_max_speed_pipe[_TD2_PIPES_PER_DEV]; 4714 int t2oq_reserved[2]; 4715 int port_sched_hsp_exists = 0; 4716 4717 soc_info_t *si = &SOC_INFO(unit); 4718 4719 t2oq_reserved[0] = 0; 4720 t2oq_reserved[1] = 0; 4721 4722 sal_memset(mmu_ports_used, 0, sizeof(int) * COUNTOF(mmu_ports_used)); 4723 4724 /* Iterate through all logical ports and see if any of them are marked 4725 with port_sched_hsp */ 4726 PBMP_ALL_ITER(unit, i) { 4727 if(soc_property_port_get(unit, i, spn_PORT_SCHED_HSP, 0)) { 4728 port_sched_hsp_exists = 1; 4729 } 4730 } 4731 4732 /* Iterate through all the MMU ports and mark the used mmu ports */ 4733 for (j = 1; j <= TD2P_PIPES_PER_DEV * _TD2_PORTS_PER_PIPE; j++) { 4734 4735 mmu_port = si->port_p2m_mapping[j]; 4736 4737 /* if the mmu port is assigned, mark it as used */ 4738 if(mmu_port != -1) { 4739 mmu_ports_used[mmu_port] = 1; 4740 } 4741 } 4742 4743 /* Find out how many port macros are capable of flexing per pipe. Only 4744 really needs to be called and set once. */ 4745 if(num_hsp_to_reserve[0] == 0 && num_hsp_to_reserve[1] == 0) { 4746 SOC_IF_ERROR_RETURN( 4747 soc_td2p_num_hsp_reserved_per_pipe(unit, 0, &num_hsp_to_reserve[0])); 4748 SOC_IF_ERROR_RETURN( 4749 soc_td2p_num_hsp_reserved_per_pipe(unit, 1, &num_hsp_to_reserve[1])); 4750 } 4751 4752 /* Iterate through the array to deallocate and allocate ports */ 4753 for (i = 0; i < nport; i++) { 4754 if ((flexport_data[i].flags & SOC_PORT_RESOURCE_I_MAP) || 4755 (flexport_data[i].physical_port == -1)) { 4756 4757 /* 4758 * Get the current physical port and MMU Port associated 4759 * with the logical port passed in */ 4760 phy_port = si->port_l2p_mapping[flexport_data[i].logical_port]; 4761 4762 if (phy_port == -1) { 4763 LOG_VERBOSE(BSL_LS_SOC_MMU, 4764 (BSL_META_U(unit, 4765 "MMU port deallocation failure: logical " 4766 "port %d is not mapped to a physical port\n"), 4767 flexport_data[i].logical_port)); 4768 4769 return SOC_E_PARAM; 4770 } 4771 4772 mmu_port = si->port_p2m_mapping[phy_port]; 4773 4774 /* Use current MMU port assignments for inactive mapping */ 4775 if (flexport_data[i].flags & SOC_PORT_RESOURCE_I_MAP) { 4776 if (mmu_port == -1) { 4777 LOG_ERROR(BSL_LS_SOC_MMU, 4778 (BSL_META_U(unit, 4779 "Invalid MMU port on inactive " 4780 "port configuration: " 4781 "port=%d mmu=%d\n"), 4782 flexport_data[i].logical_port, mmu_port)); 4783 return SOC_E_INTERNAL; 4784 } 4785 4786 flexport_data[i].mmu_port = mmu_port; 4787 LOG_VERBOSE(BSL_LS_SOC_MMU, 4788 (BSL_META_U(unit, 4789 "Inactive port configuration, " 4790 "keep same mapping: port=%d mmu=%d\n"), 4791 flexport_data[i].logical_port, mmu_port)); 4792 continue; 4793 } 4794 4795 /* 4796 * Continue with next case. 4797 * If the phy_port == -1, we're deallocating if we're told to 4798 */ 4799 4800 /* Check to make sure we aren't indexing into mmu_ports_used with 4801 a negative mmu port number. Skip this if p2m returns negative. */ 4802 if (mmu_port < 0) { 4803 continue; 4804 } 4805 /* Mark the MMU port unused so that it can be allocated again 4806 in this routine */ 4807 mmu_ports_used[si->port_p2m_mapping[phy_port]] = 0; 4808 4809 4810 } else { 4811 /* We're allocating a port. 4812 1. Find out if we need to allocate a HSP given the port speed 4813 and the clock frequency 4814 2. Assign a free MMU port appropriate to the pipe the physical 4815 port is on. A phy port on X 4816 pipe must have an MMU port on X pipe, Y on Y. */ 4817 4818 SOC_IF_ERROR_RETURN(soc_td2p_port_resource_speed_max_get(unit, &flexport_max_speed)); 4819 4820 4821 /* Find out what pipe we're going to assign to */ 4822 if (flexport_data[i].physical_port < si->phy_port_base[1]) { /* X-pipe */ 4823 pipe = 0; 4824 } else { 4825 pipe = 1; 4826 } 4827 4828 /* If a per pipe flex speed has been defined, use that instead. 4829 Must have been defined for both X and Y Pipe. */ 4830 flexport_max_speed_pipe[0] = 0; 4831 flexport_max_speed_pipe[1] = 0; 4832 4833 SOC_IF_ERROR_RETURN(soc_td2p_port_resource_speed_max_x_get(unit, &flexport_max_speed_pipe[0])); 4834 SOC_IF_ERROR_RETURN(soc_td2p_port_resource_speed_max_y_get(unit, &flexport_max_speed_pipe[1])); 4835 4836 /* If both X and Y pipes have had their flex speed specified, select 4837 the one from the appropriate pipe; it takes priority over the 4838 global flex speed. */ 4839 if ((flexport_max_speed_pipe[0] > 0) && (flexport_max_speed_pipe[1] > 0)) { 4840 flexport_max_speed = flexport_max_speed_pipe[pipe]; 4841 } 4842 4843 /* 1. Find the first unused mmu port and map it to our phy 4844 port. If we aren't allocating a HSP, skip MMU Ports 0-15 4845 (start at 16). If we are, start at 0 and end at 15. 4846 4847 We use SOC_TD2_NUM_MMU_PORTS_PER_PIPE instead of 4848 _TD2_PORTS_PER_PIPE because 4849 the last 11 MMU ports in each pipe are not used. 4850 4851 **** THIS IS PER PIPE!!! **** 4852 4853 */ 4854 if (si->bandwidth >= 960000) { 4855 if(flexport_data[i].speed >= 100000) { 4856 start_mmu_port = 0; 4857 end_mmu_port = num_hsp_to_reserve[pipe]; 4858 } else { 4859 /* If any port is capable of flexing above HG[42], 4860 then we've reserved HSP and T2OQ */ 4861 if(flexport_max_speed > 42000 || port_sched_hsp_exists == 1) { 4862 start_mmu_port = num_hsp_to_reserve[pipe]; 4863 /* 53 MMU ports per pipe, MMU port 52 is CPU port, 4864 MMU port 116 is Loopback port*/ 4865 end_mmu_port = SOC_TD2_NUM_MMU_PORTS_PER_PIPE - 1; 4866 4867 /* Reserving T2OQ per pipe to match with HSP */ 4868 t2oq_reserved[pipe] = num_hsp_to_reserve[pipe]; 4869 } else { 4870 /* No HSP. All ports are treated as normal */ 4871 start_mmu_port = 0; 4872 end_mmu_port = SOC_TD2_NUM_MMU_PORTS_PER_PIPE - 1; 4873 } 4874 } 4875 } else if (si->bandwidth >= 480000) { 4876 /* both 480G and 720G SKU need a HSP at 40Gb and above */ 4877 if (flexport_data[i].speed >= 40000) { 4878 start_mmu_port = 0; 4879 end_mmu_port = num_hsp_to_reserve[pipe]; 4880 } else { 4881 /* If any port is capable of flexing above 40G, 4882 then we've reserved HSP and T2OQ */ 4883 if(flexport_max_speed >= 40000 || port_sched_hsp_exists == 1) { 4884 start_mmu_port = num_hsp_to_reserve[pipe]; 4885 /* 53 MMU ports per pipe, MMU port 52 is CPU port, 4886 MMU port 116 is Loopback port */ 4887 end_mmu_port = SOC_TD2_NUM_MMU_PORTS_PER_PIPE - 1; 4888 4889 /* Reserving T2OQ per pipe to match with HSP */ 4890 t2oq_reserved[pipe] = num_hsp_to_reserve[pipe]; 4891 } else { 4892 start_mmu_port = 0; 4893 end_mmu_port = SOC_TD2_NUM_MMU_PORTS_PER_PIPE - 1; 4894 } 4895 } 4896 } else { 4897 LOG_VERBOSE(BSL_LS_SOC_MMU, 4898 (BSL_META_U(unit, 4899 "MMU port allocation failure: " 4900 "SKU %d is not supported\n"), 4901 si->bandwidth)); 4902 return SOC_E_INTERNAL; 4903 } 4904 4905 /* 2. check pipe for a free mmu port */ 4906 /* Add the necessary offset for the pipe we're in */ 4907 start_mmu_port += (pipe * _TD2_PORTS_PER_PIPE); 4908 end_mmu_port += (pipe * _TD2_PORTS_PER_PIPE); 4909 4910 /* loop from start mmu port to end mmu port to find 4911 a free mmu port 4912 0-51 is range for X Pipe 4913 52 is CPU port 4914 53-63 are NOT used 4915 64-115 is range for Y Pipe 4916 116 is Loopback port */ 4917 for(j = start_mmu_port; j < end_mmu_port; j++) { 4918 /* Case where SKU == 720G and 4919 40 Gig <= max flexed speed < 100 Gig doesn't 4920 require T2OQ to be reserved, so we 4921 can use mmu ports 36 - 51 in that case, 4922 but MUST skip for all others */ 4923 SOC_IF_ERROR_RETURN 4924 (soc_td2p_port_resource_speed_max_get(unit, 4925 &port_max_speed)); 4926 4927 /* Only want to skip the amount of T2OQ needed to match with 4928 HSP. If we reserved 4 HSP, need to reserve 4 T2OQ max. 4929 If we reserved 16 HSP, need to reserve 16 T2OQ. 4930 j < (36 + t2oq_reserved + (pipe * _TD2_PORTS_PER_PIPE)). 4931 sets the upper limit of T2OQ we reserve since j >= 36... . 4932 is the base. */ 4933 if (!((si->bandwidth == 720000) && 4934 (port_max_speed >= 40000) && 4935 (port_max_speed < 100000))){ 4936 if ((j >= 36 + (pipe * _TD2_PORTS_PER_PIPE)) && 4937 j < (36 + t2oq_reserved[pipe] + (pipe * _TD2_PORTS_PER_PIPE))) { 4938 continue; 4939 } 4940 } 4941 4942 /* We found an unused MMU port! Let's assign it to 4943 a phy port! */ 4944 if (mmu_ports_used[j] == 0) { 4945 /* Mark the port as used. This is done in case 4946 we're passed multiple ports 4947 to allocate to make sure we have enough ports. */ 4948 mmu_ports_used[j] = 1; 4949 flexport_data[i].mmu_port = j; 4950 break; 4951 } 4952 } 4953 4954 /* if we didn't find a free mmu port, return error. */ 4955 if (j == end_mmu_port) { 4956 return SOC_E_RESOURCE; 4957 } 4958 } 4959 } 4960 return SOC_E_NONE; 4961 } 4962 4963 /* 4964 * Function: 4965 * soc_td2p_port_asf_set 4966 * Purpose: 4967 * Enable/Disable CT/ASF sequence 4968 * Parameters: 4969 * unit - (IN) Unit number. 4970 * port - (IN) Logical SOC port number. 4971 * enable - (IN) Enable or Disable. 4972 * Returns: 4973 * SOC_E_XXX 4974 */ 4975 int 4976 soc_td2p_port_asf_set (int unit, soc_port_t port, int enable) 4977 { 4978 soc_port_resource_t res; 4979 soc_info_t *si; 4980 si = &SOC_INFO(unit); 4981 4982 sal_memset(&res, 0, sizeof(soc_port_resource_t)); 4983 res.logical_port = port; 4984 res.physical_port = si->port_l2p_mapping[port]; 4985 res.speed = si->port_speed_max[port]; 4986 res.oversub = IS_OVERSUB_PORT(unit, port); 4987 4988 /* Enable/disable cut-through for this port */ 4989 return soc_td2p_cut_thru_enable_disable(unit, &res, enable); 4990 } 4991 4992 /* 4993 * Function: 4994 * soc_td2p_port_icc_width_set 4995 * Purpose: 4996 * Program PORT_INITIAL_COPY_COUNT_WIDTHr 4997 * Parameters: 4998 * unit - (IN) Unit number. 4999 * port - (IN) Logical SOC port number. 5000 * Returns: 5001 * SOC_E_XXX 5002 */ 5003 STATIC int 5004 soc_td2p_port_icc_width_set(int unit, soc_port_t port) 5005 { 5006 int num_lanes; 5007 int count_width = 0; 5008 5009 if (SOC_REG_IS_VALID(unit, PORT_INITIAL_COPY_COUNT_WIDTHr)) { 5010 num_lanes = SOC_INFO(unit).port_num_lanes[port]; 5011 switch (num_lanes) { 5012 case 1: count_width = 1; 5013 break; 5014 case 2: count_width = 2; 5015 break; 5016 case 4: count_width = 3; 5017 break; 5018 default: count_width = 0; 5019 break; 5020 } 5021 if (SOC_REG_FIELD_VALID(unit, PORT_INITIAL_COPY_COUNT_WIDTHr, 5022 BIT_WIDTHf)) { 5023 SOC_IF_ERROR_RETURN( 5024 soc_reg_field32_modify(unit, PORT_INITIAL_COPY_COUNT_WIDTHr, 5025 port, BIT_WIDTHf, count_width ? (count_width - 1) : 0)); 5026 } 5027 } 5028 5029 return SOC_E_NONE; 5030 } 5031 5032 /* 5033 * Function: 5034 * soc_td2p_repl_port_agg_map_init 5035 * Purpose: 5036 * Initialize L3MC Port Agg Map. 5037 * Parameters: 5038 * unit - (IN) Unit number. 5039 * port - (IN) Logical SOC port number. 5040 * Returns: 5041 * SOC_E_xxx 5042 */ 5043 STATIC int 5044 soc_td2p_repl_port_agg_map_init(int unit, soc_port_t port) 5045 { 5046 soc_info_t *si; 5047 int phy_port, mmu_port; 5048 uint32 regval; 5049 5050 si = &SOC_INFO(unit); 5051 phy_port = si->port_l2p_mapping[port]; 5052 mmu_port = si->port_p2m_mapping[phy_port]; 5053 5054 /* configure mmu port to repl aggregateId map */ 5055 regval = 0; 5056 soc_reg_field_set(unit, MMU_TOQ_REPL_PORT_AGG_MAPr, ®val, 5057 L3MC_PORT_AGG_IDf, mmu_port % 64); 5058 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, MMU_TOQ_REPL_PORT_AGG_MAPr, 5059 port,0,regval)); 5060 5061 regval = 0; 5062 soc_reg_field_set(unit, MMU_ENQ_REPL_PORT_AGG_MAPr, ®val, 5063 L3MC_PORT_AGG_IDf, mmu_port); 5064 SOC_IF_ERROR_RETURN( 5065 soc_reg32_set(unit, MMU_ENQ_REPL_PORT_AGG_MAPr, port, 0, regval)); 5066 5067 regval = 0; 5068 soc_reg_field_set(unit, MMU_ENQ_LOGICAL_PORT_TO_PORT_AGG_MAPr, ®val, 5069 L3MC_PORT_AGG_IDf, mmu_port); 5070 SOC_IF_ERROR_RETURN(WRITE_MMU_ENQ_LOGICAL_PORT_TO_PORT_AGG_MAPr(unit, 5071 port, regval)); 5072 5073 return SOC_E_NONE; 5074 } 5075 5076 /* 5077 * Function: 5078 * soc_td2p_ipmc_repl_init 5079 * Purpose: 5080 * Initialize IPMC Replication settings 5081 * Parameters: 5082 * unit - (IN) Unit number. 5083 * port - (IN) Logical SOC port number. 5084 * Returns: 5085 * SOC_E_XXX 5086 */ 5087 STATIC int 5088 soc_td2p_ipmc_repl_init(int unit, soc_port_t port) 5089 { 5090 /* Program MMU_TOQ_REPL_PORT_AGG_MAP 5091 */ 5092 SOC_IF_ERROR_RETURN(soc_td2p_repl_port_agg_map_init(unit, port)); 5093 5094 return SOC_E_NONE; 5095 } 5096 /* 5097 * Function: 5098 * soc_trident2p_num_cosq_init_port 5099 * Purpose: 5100 * Assign the base queues and number of queues for the 5101 * specified port. These are based upon MMU Port number to avoid 5102 * reallocation or running into other queues during post device init 5103 * port init. This is modeled after soc_trident2_num_cosq_init 5104 * but only for individual ports. 5105 * Parameters: 5106 * unit - (IN) Unit number. 5107 * logical_port - (IN) logical port num 5108 * Returns: 5109 * SOC_E_XXX 5110 * 5111 * 5112 * cpu port (mmu port 0): 48 queues (2000-2047) 5113 * loopback port (mmu port 116): 8 queues (4048-4055) 5114 */ 5115 STATIC int 5116 soc_trident2p_num_cosq_init_port(int unit, int logical_port) 5117 { 5118 soc_info_t *si; 5119 int port, phy_port, mmu_port, mmu_port_offset, pipe; 5120 int uc_cosq_base, mc_cosq_base, uc_cosq_per_port; 5121 int apply = 0; 5122 5123 si = &SOC_INFO(unit); 5124 /* 5125 if (soc_feature(unit, soc_feature_cmic_reserved_queues)) { 5126 si->port_num_cosq[CMIC_PORT(unit)] = 44; 5127 } else { 5128 si->port_num_cosq[CMIC_PORT(unit)] = 48; 5129 } 5130 si->port_cosq_base[CMIC_PORT(unit)] = 520; */ 5131 /* 5132 si->port_num_cosq[LB_PORT(unit)] = 9; 5133 si->port_cosq_base[LB_PORT(unit)] = 1088;*/ 5134 5135 for (pipe = 0; pipe < _TD2_PIPES_PER_DEV; pipe++) { 5136 if (pipe) { /* Y-pipe */ 5137 uc_cosq_base = 1480; 5138 mc_cosq_base = 568; 5139 } else { /* X-pipe */ 5140 uc_cosq_base = 0; 5141 mc_cosq_base = 0; 5142 } 5143 for (mmu_port_offset = 0; mmu_port_offset < _TD2_MMU_PORTS_PER_PIPE; 5144 mmu_port_offset++) { 5145 mmu_port = si->mmu_port_base[pipe] + mmu_port_offset; 5146 phy_port = si->port_m2p_mapping[mmu_port]; 5147 if (phy_port == -1) { 5148 continue; 5149 } 5150 port = si->port_p2l_mapping[phy_port]; 5151 5152 if(port == logical_port) { 5153 apply = 1; 5154 } 5155 5156 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) { 5157 continue; 5158 } 5159 5160 if (SOC_PBMP_MEMBER(si->eq_pbm, port)) { /* VBS (HSP) port */ 5161 if(apply == 1) { 5162 si->port_num_cosq[port] = 10; 5163 si->port_cosq_base[port] = mc_cosq_base + (mmu_port_offset * si->port_num_cosq[port]); 5164 si->port_num_uc_cosq[port] = 10; 5165 /* Made port_uc_cosq_base a function of mmu_port number 5166 * rather than a running number (as calculated by 5167 * uc_cosq_base before). If it is a running number, & 5168 * the port numbers come & go dynamically (as in flex port) 5169 * uc_cosq_base overlap. With port_uc_cosq_base a function 5170 * of mmu_port, each port has a fixed offset 5171 */ 5172 si->port_uc_cosq_base[port] = uc_cosq_base + (mmu_port_offset * 10); 5173 } 5174 } else { 5175 uc_cosq_per_port = 5176 soc_property_port_get(unit, port, spn_LLS_NUM_L2UC, 10); 5177 if (uc_cosq_per_port < 10 || uc_cosq_per_port > 16) { 5178 uc_cosq_per_port = 10; 5179 } 5180 uc_cosq_per_port = (uc_cosq_per_port + 3) & ~3; 5181 5182 if (apply == 1) { 5183 si->port_num_cosq[port] = 10; 5184 si->port_cosq_base[port] = mc_cosq_base + (mmu_port_offset * si->port_num_cosq[port]); 5185 si->port_num_uc_cosq[port] = uc_cosq_per_port; 5186 } 5187 /* uc_cosq_base for LLS port must be 5188 * divisible by 4 for PFC to work */ 5189 uc_cosq_base = (uc_cosq_base + 3) & (~3); 5190 5191 if (apply == 1) { 5192 /* Made port_uc_cosq_base a function of mmu_port number 5193 * rather than a running number (as calculated by 5194 * uc_cosq_base before). If it is a running number, & 5195 * the port numbers come & go dynamically (as in flex port) 5196 * uc_cosq_base overlap. With port_uc_cosq_base a function 5197 * of mmu_port, each port has a fixed offset 5198 */ 5199 si->port_uc_cosq_base[port] = uc_cosq_base + (mmu_port_offset * uc_cosq_per_port); 5200 5201 return SOC_E_NONE; 5202 } 5203 } 5204 } 5205 } 5206 5207 return SOC_E_NONE; 5208 } 5209 5210 /* 5211 * Function: 5212 * soc_td2p_hsp_sched_global_config_set 5213 * Purpose: 5214 * Set HSP_SCHED_GLOBAL_CONFIG for the given port 5215 * Parameters: 5216 * unit - (IN) Unit number. 5217 * port - (IN) Logical SOC port number. 5218 * Returns: 5219 * SOC_E_XXX 5220 */ 5221 STATIC int soc_td2p_hsp_sched_global_config_set(int unit, soc_port_t port) 5222 { 5223 uint32 rval, fval; 5224 uint32 field; 5225 int mmu_port, pipe; 5226 int hsp_port_index; 5227 5228 /* Only set this register for the port if the port is HSP */ 5229 if(_soc_trident2_port_sched_type_get(unit, port) 5230 != SOC_TD2_SCHED_HSP) { 5231 return SOC_E_NONE; 5232 } 5233 5234 rval = fval = 0; 5235 5236 SOC_IF_ERROR_RETURN( 5237 soc_td2_port_common_attributes_get(unit, port, &pipe, &mmu_port, NULL)); 5238 5239 field = pipe ? IS_HSP_PORT_IN_YPIPEf : IS_HSP_PORT_IN_XPIPEf; 5240 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_GLOBAL_CONFIGr(unit, &rval)); 5241 fval = soc_reg_field_get(unit, HSP_SCHED_GLOBAL_CONFIGr, rval, field); 5242 hsp_port_index = mmu_port - pipe * _TD2_PORTS_PER_PIPE; 5243 fval |= (1 << hsp_port_index); 5244 soc_reg_field_set(unit, HSP_SCHED_GLOBAL_CONFIGr, &rval, field, fval); 5245 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, rval)); 5246 5247 return SOC_E_NONE; 5248 } 5249 5250 /* 5251 * Function: 5252 * soc_td2p_hsp_sched_global_config_clear 5253 * Purpose: 5254 * Clear HSP_SCHED_GLOBAL_CONFIG for the given port 5255 * Parameters: 5256 * unit - (IN) Unit number. 5257 * port - (IN) Logical SOC port number. 5258 * Returns: 5259 * SOC_E_XXX 5260 */ 5261 STATIC int soc_td2p_hsp_sched_global_config_clear(int unit, soc_port_t port) 5262 { 5263 uint32 rval, fval; 5264 uint32 field; 5265 int mmu_port, pipe; 5266 int hsp_port_index; 5267 5268 rval = fval = 0; 5269 5270 SOC_IF_ERROR_RETURN( 5271 soc_td2_port_common_attributes_get(unit, port, &pipe, &mmu_port, NULL)); 5272 5273 field = pipe ? IS_HSP_PORT_IN_YPIPEf : IS_HSP_PORT_IN_XPIPEf; 5274 SOC_IF_ERROR_RETURN(READ_HSP_SCHED_GLOBAL_CONFIGr(unit, &rval)); 5275 fval = soc_reg_field_get(unit, HSP_SCHED_GLOBAL_CONFIGr, rval, field); 5276 hsp_port_index = mmu_port - pipe * _TD2_PORTS_PER_PIPE; 5277 fval &= ~(1 << hsp_port_index); 5278 soc_reg_field_set(unit, HSP_SCHED_GLOBAL_CONFIGr, &rval, field, fval); 5279 SOC_IF_ERROR_RETURN(WRITE_HSP_SCHED_GLOBAL_CONFIGr(unit, rval)); 5280 5281 return SOC_E_NONE; 5282 } 5283 5284 /* 5285 * Function: 5286 * soc_td2p_mmu_port_resource_set 5287 * Purpose: 5288 * Reconfigure MMU for flexport operation 5289 * Parameters: 5290 * unit - (IN) Unit number. 5291 * port - (IN) Logical SOC port number. 5292 * speed - (IN) port speed. 5293 * legacyFlex - (IN) Whether this is a legacy flex or new flex 5294 * Returns: 5295 * SOC_E_XXX 5296 */ 5297 int soc_td2p_mmu_port_resource_set(int unit, soc_port_t port, int speed, int legacyFlex) 5298 { 5299 int ets_mode = 0; 5300 /* Flex port operation not allowed on CPU or loopback port 5301 */ 5302 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) { 5303 return SOC_E_PARAM; 5304 } 5305 5306 /* Update the logical port and queue mappings in memory and registers */ 5307 if (td2p_ets_mode_cb) { 5308 ets_mode = td2p_ets_mode_cb(unit, port); 5309 } 5310 5311 /* Alloc the bitmaps for L0, L1, L2 nodes for this port */ 5312 SOC_IF_ERROR_RETURN(soc_trident2_lls_bmap_alloc_port(unit, port, ets_mode)); 5313 5314 SOC_IF_ERROR_RETURN(soc_trident2p_num_cosq_init_port(unit, port)); 5315 5316 /* Configure all MMU registers for new ports whose setting is 5317 * based on port speed. 5318 */ 5319 SOC_IF_ERROR_RETURN(soc_trident2_port_speed_update(unit, port, speed)); 5320 5321 /* Program PORT_INITIAL_COPY_COUNT_WIDTH 5322 */ 5323 SOC_IF_ERROR_RETURN(soc_td2p_port_icc_width_set(unit, port)); 5324 5325 5326 if (!ets_mode) { 5327 /* Default Scheduling on the port. The function 5328 * below also sets HSP_SCHED_GLOBAL_CONFIG for high speed ports. 5329 * This needs to be done regardless of if it's default or 5330 * custom scheduling. Custom scheduling is handled below. 5331 */ 5332 SOC_IF_ERROR_RETURN(soc_trident2_port_sched_set(unit, port)); 5333 } else { 5334 /* Custom scheduling on the port. 5335 * If the port is HSP, set HSP_SCHED_GLOBAL_CONFIG so the 5336 * device knows to use HSP scheduling for that port. The 5337 * function below checks if the port is HSP internally. 5338 */ 5339 SOC_IF_ERROR_RETURN( 5340 soc_td2p_hsp_sched_global_config_set(unit, port)); 5341 } 5342 5343 /* Reconfigure IPMC replication 5344 */ 5345 SOC_IF_ERROR_RETURN(soc_td2p_ipmc_repl_init(unit, port)); 5346 5347 /* Reconfigure THDI, THDO settings 5348 */ 5349 /* legacy flex has already set up these pg and queue settings for the port 5350 on device init. Calling this will overwrite any settings with 5351 default settings. */ 5352 if(legacyFlex == 0) { 5353 SOC_IF_ERROR_RETURN(soc_td2p_mmu_config_init_port(unit, port)); 5354 } 5355 5356 return SOC_E_NONE; 5357 } 5358 5359 /* 5360 * Function: 5361 * soc_td2p_mmu_port_resource_clear 5362 * Purpose: 5363 * Reconfigure MMU for flexport operation 5364 * Parameters: 5365 * unit - (IN) Unit number. 5366 * port - (IN) Logical SOC port number. 5367 * Returns: 5368 * SOC_E_XXX 5369 */ 5370 int soc_td2p_mmu_port_resource_clear(int unit, soc_port_t port) 5371 { 5372 int ets_mode = 0; 5373 soc_trident2_sched_type_t sched_type; 5374 5375 if (td2p_ets_mode_cb) { 5376 ets_mode = td2p_ets_mode_cb(unit, port); 5377 } 5378 5379 sched_type = _soc_trident2_port_sched_type_get(unit, port); 5380 if (sched_type == SOC_TD2_SCHED_HSP) { 5381 SOC_IF_ERROR_RETURN(soc_td2p_hsp_sched_global_config_clear(unit, port)); 5382 } 5383 5384 /* In ETS mode, SDK does not initialize or deletes the default LLS hierarchy */ 5385 if (!ets_mode) { 5386 SOC_IF_ERROR_RETURN(soc_td2_lls_port_uninit(unit, port)); 5387 } 5388 SOC_IF_ERROR_RETURN(soc_td2_lls_reset_port(unit, port)); 5389 5390 SOC_IF_ERROR_RETURN(soc_td2p_port_sched_hsp_set(unit, port, 0)); 5391 return SOC_E_NONE; 5392 } 5393 5394 /* 5395 * Function: 5396 * soc_td2p_is_any_port_flex_enable 5397 * Purpose: 5398 * Find out if 5399 * port_flex_enable=1 OR 5400 * port_flex_enable{physical port num}=1 5401 * config is present in config.bcm 5402 * Parameters: 5403 * unit - (IN) Unit number. 5404 * Returns: 5405 * TRUE or FALSE 5406 * If such a config is present, this function 5407 * returns 1 - implying that flex is enable on 5408 * at least 1 port (port macro) in the system 5409 * This function returns 0, if flex is not enabled 5410 * on any port (port macro) in the system 5411 */ 5412 int soc_td2p_is_any_port_flex_enable(int unit) 5413 { 5414 int phy_port, num_phy_port; 5415 5416 num_phy_port = 130; 5417 5418 for (phy_port = 0; phy_port < num_phy_port; phy_port++) { 5419 if (soc_property_phys_port_get(unit, 5420 phy_port, 5421 spn_PORT_FLEX_ENABLE, 0)) { 5422 return TRUE; 5423 } 5424 } 5425 5426 return FALSE; 5427 } 5428 5429 /* 5430 * Function: 5431 * soc_td2p_is_port_flex_enable 5432 * Purpose: 5433 * Find out if port_flex_enable{physical port num} config 5434 * is present on the given physical port in config.bcm 5435 * Parameters: 5436 * unit - (IN) Unit number. 5437 * phy_port - (IN) physical port num 5438 * Returns: 5439 * TRUE or FALSE 5440 */ 5441 int soc_td2p_is_port_flex_enable(int unit, int phy_port) 5442 { 5443 int enable = 0; 5444 5445 /* This property does not apply to cpu port & 5446 * loopback port 5447 */ 5448 5449 if (phy_port > 0 && phy_port < 129) { 5450 enable = soc_property_phys_port_get(unit, 5451 phy_port, 5452 spn_PORT_FLEX_ENABLE, 0); 5453 } 5454 5455 return enable; 5456 } 5457 5458 /* 5459 * Function: 5460 * soc_td2p_set_flexport_port_q_callback 5461 * Purpose: 5462 * Register a callback for the bcm layer so that the soc layer can call it 5463 * to update logical port and queue associations 5464 * Parameters: 5465 * unit - (IN) Unit number. 5466 * cb - (IN) Function callback 5467 * Returns: 5468 * SOC_E_XXX 5469 */ 5470 int soc_td2p_set_flexport_port_q_callback(int unit, 5471 _soc_td2p_flexport_port_q_cb cb) 5472 { 5473 td2p_flexport_cb = cb; 5474 return SOC_E_NONE; 5475 } 5476 5477 /* 5478 * Function: 5479 * soc_td2p_set_ets_mode_q_callback 5480 * Purpose: 5481 * Register a callback for the bcm layer so that the soc layer can call it 5482 * and check if ets mode is enabled or not 5483 * Parameters: 5484 * unit - (IN) Unit number. 5485 * cb - (IN) Function callback 5486 * Returns: 5487 * SOC_E_XXX 5488 */ 5489 int soc_td2p_set_ets_mode_q_callback(int unit, 5490 _soc_td2p_ets_mode_q_cb cb) 5491 { 5492 td2p_ets_mode_cb = cb; 5493 return SOC_E_NONE; 5494 } 5495 5496 /* 5497 * Function: 5498 * soc_td2p_port_mode_get 5499 * Description: 5500 * Get port mode by giving first logical port of TSC4 5501 * Parameters: 5502 * unit - Device number 5503 * port - Logical port 5504 * int* - Port Mode 5505 * 5506 * Each TSC4 can be configured into following 5 mode: 5507 * Lane number 0 1 2 3 5508 * ------------ --- --- --- --- 5509 * quad port 10G 10G 10G 10G 5510 * tri_012 port 10G 10G 20G x 5511 * tri_023 port 20G x 10G 10G 5512 * dual port 20G x 20G x 5513 * single port 40G x x x 5514 */ 5515 int 5516 soc_td2p_port_mode_get(int unit, int logical_port, int *mode) 5517 { 5518 soc_info_t *si; 5519 int lane; 5520 int port, first_phyport, phy_port; 5521 int num_lanes[_TD2_PORTS_PER_XLP]; 5522 5523 si = &SOC_INFO(unit); 5524 first_phyport = si->port_l2p_mapping[logical_port]; 5525 5526 for (lane = 0; lane < _TD2_PORTS_PER_XLP; lane++) { 5527 phy_port = first_phyport + lane; 5528 port = si->port_p2l_mapping[phy_port]; 5529 if (port == -1 || SOC_PBMP_MEMBER(si->all.disabled_bitmap, port)) { 5530 num_lanes[lane] = -1; 5531 } else { 5532 num_lanes[lane] = si->port_num_lanes[port]; 5533 } 5534 } 5535 5536 if (num_lanes[0] == 4) { 5537 *mode = SOC_TD2_PORT_MODE_QUAD; 5538 } else if (num_lanes[0] == 2 && num_lanes[2] == 2) { 5539 *mode = SOC_TD2_PORT_MODE_DUAL; 5540 } else if (num_lanes[0] == 2 && num_lanes[2] == 1 && num_lanes[3] == 1) { 5541 *mode = SOC_TD2_PORT_MODE_TRI_023; 5542 } else if (num_lanes[0] == 1 && num_lanes[1] == 1 && num_lanes[2] == 2) { 5543 *mode = SOC_TD2_PORT_MODE_TRI_012; 5544 } else { 5545 *mode = SOC_TD2_PORT_MODE_SINGLE; 5546 } 5547 5548 return SOC_E_NONE; 5549 } 5550 5551 /* 5552 * Function: 5553 * soc_td2p_mcq_entries_rsvd_port 5554 * Purpose: 5555 * For a given port, soc_td2p_mcq_entries_rsvd_port calculates 5556 * the number of MC q entries (Reserved Egress Queue Entries). 5557 * This function only gives MC q entries for 5558 * for flex disabled ports. 5559 * For flex enabled port macros, this function is not used. 5560 * Parameters: 5561 * unit - (IN) Unit number. 5562 * port - (IN) logical port num 5563 * Returns: 5564 * Reserved Egress Queue Entries for a given port 5565 */ 5566 int soc_td2p_mcq_entries_rsvd_port(int unit, int port) 5567 { 5568 int port_num_cosq; 5569 soc_info_t *si; 5570 int mcq_entry = 0; 5571 5572 si = &SOC_INFO(unit); 5573 port_num_cosq = si->port_num_cosq[port]; 5574 5575 if (IS_LB_PORT(unit, port)) { 5576 /* Loopback port has 9 queues (including QCN) 5577 * For calculation of Egress queue entries, 5578 * loopback port is considered having 8 queues 5579 * (Why? :- ask Architecture) 5580 */ 5581 port_num_cosq = si->port_num_cosq[port] - 1; 5582 } 5583 5584 mcq_entry = port_num_cosq * _TD2P_MMU_PER_COSQ_EGRESS_QENTRY_RSVD; 5585 return mcq_entry; 5586 } 5587 5588 /* 5589 * Function: 5590 * soc_td2p_egr_buf_rsvd_port 5591 * Purpose: 5592 * For Cpu port or loopback port, 5593 * soc_td2p_egr_buf_rsvd_port calculates 5594 * the reserved queue min/guarantee. 5595 * This function only gives cumulative (for all queues) 5596 * queue guarantee for CPU port or Loopback port. 5597 * Parameters: 5598 * unit - (IN) Unit number. 5599 * port - (IN) logical port num for CPU port or LB port 5600 * Returns: 5601 * Reserved Cumulative (total for all queues) Queue Min/Guarantee value 5602 */ 5603 int soc_td2p_egr_buf_rsvd_port(int unit, int port, int default_mtu_cells) 5604 { 5605 int port_num_cosq; 5606 soc_info_t *si; 5607 int egr_rsvd = 0; 5608 int min_cell_per_mcq; 5609 5610 if (!IS_CPU_PORT(unit, port) && !IS_LB_PORT(unit, port)) { 5611 return 0; 5612 } 5613 5614 si = &SOC_INFO(unit); 5615 5616 port_num_cosq = si->port_num_cosq[port]; 5617 5618 if (IS_LB_PORT(unit, port)) { 5619 /* Loopback port has 9 queues (including QCN) 5620 * For calculation of Egress queue entries, 5621 * loopback port is considered having 8 queues 5622 * (Why? :- ask Architecture) 5623 */ 5624 port_num_cosq = si->port_num_cosq[port] - 1; 5625 } 5626 5627 if (soc_feature(unit, soc_feature_min_cell_per_queue)) { 5628 min_cell_per_mcq = _soc_td2_min_cell_rsvd_per_mcq(unit, port, default_mtu_cells); 5629 } else { 5630 min_cell_per_mcq = default_mtu_cells; 5631 } 5632 5633 egr_rsvd = port_num_cosq * min_cell_per_mcq; 5634 return egr_rsvd; 5635 } 5636 5637 /* 5638 * Function: 5639 * _soc_td2p_lb_port_flush 5640 * Purpose: 5641 * Poll until LB port gets back all the credits from EP 5642 * Parameters: 5643 * unit - (IN) Unit number. 5644 * Returns: 5645 * SOC_E_XXX 5646 */ 5647 STATIC int 5648 _soc_td2p_lb_port_flush(int unit) 5649 { 5650 #define MMU_LB_PORT_BOOT_TIME_CREDITS 36 5651 5652 soc_info_t *si = &SOC_INFO(unit); 5653 soc_timeout_t to; 5654 int lb_port_credits; 5655 uint32 lbval; 5656 int mmu_lb_port; 5657 5658 mmu_lb_port = si->port_p2m_mapping[si->port_l2p_mapping[si->lb_port]]; 5659 /* Adjust for pipe */ 5660 mmu_lb_port = mmu_lb_port &0x3f; 5661 5662 soc_timeout_init(&to, 250000, 0); 5663 5664 /* Poll until EDB buffer is empty */ 5665 for (;;) { 5666 SOC_IF_ERROR_RETURN 5667 (READ_ES_PIPE1_MMU_PORT_CURRENT_CREDITr(unit, mmu_lb_port, &lbval)); 5668 lb_port_credits = soc_reg_field_get(unit, ES_PIPE1_MMU_PORT_CURRENT_CREDITr, 5669 lbval, CREDITf); 5670 if (lb_port_credits >= MMU_LB_PORT_BOOT_TIME_CREDITS) { 5671 break; 5672 } 5673 if (soc_timeout_check(&to)) { 5674 LOG_ERROR(BSL_LS_SOC_COMMON, 5675 (BSL_META_U(unit, 5676 "EDB buffer drain timeout: " 5677 "port %d, %s, " 5678 "timeout port %d credit %d\n"), 5679 unit, SOC_PORT_NAME(unit, si->lb_port), mmu_lb_port, lb_port_credits)); 5680 return SOC_E_INTERNAL; 5681 } 5682 } 5683 5684 return SOC_E_NONE; 5685 } 5686 5687 #define _TD2P_XPIPE (0) 5688 #define _TD2P_YPIPE (1) 5689 /* 5690 * Function: 5691 * _soc_td2p_tdm_cpulb_port_indices_get 5692 * Purpose: 5693 * This function finds & returns the slot number (location of) 5694 * loopback port in the active TDM calendar 5695 * Parameters: 5696 * unit - (IN) Unit number. 5697 * pipe - (IN) pipe number. 0 - xpipe, 1 - ypipe. 5698 * table_num - (IN) Active TDM Table number - 0 or 1 5699 * slot_len - (IN) Current length of the Active TDM table 5700 * *arr - (OUT) contains location (slot num) of lb port in TDM Cal 5701 * count - (OUT) number(count) of locations of LB port in TDM Cal 5702 * - valid number of entries in *arr 5703 * Returns: 5704 * SOC_E_XXX 5705 * Note: 5706 * This function assumes that the output array (arr) being passed 5707 * is initialized & has sufficient memory (_MMU_TDM_LENGTH) to store all possible 5708 * locations of loopback port in the TDM Calendar. In short, 5709 * before calling this function, please allocate the memory 5710 * (uint32 * _MMU_TDM_LENGTH) for arr 5711 */ 5712 STATIC int 5713 _soc_td2p_tdm_cpulb_port_indices_get(int unit, int pipe, int table_num, 5714 int slot_len, uint32 *arr, uint32 *count) 5715 { 5716 static const soc_mem_t mmu_tdm_mems[2][2] = { 5717 {ES_PIPE0_TDM_TABLE_0m, ES_PIPE0_TDM_TABLE_1m}, 5718 {ES_PIPE1_TDM_TABLE_0m, ES_PIPE1_TDM_TABLE_1m} 5719 }; 5720 static const soc_mem_t mmu_tdm_fields[2] = { 5721 PORT_NUM_EVENf, PORT_NUM_ODDf}; 5722 5723 soc_info_t *si; 5724 uint32 entry[SOC_MAX_MEM_WORDS]; 5725 soc_field_t field; 5726 soc_mem_t mem; 5727 uint32 fval; 5728 int phy_port, log_port, mmu_port; 5729 int slot, index; 5730 int temp_count; 5731 5732 si = &SOC_INFO(unit); 5733 5734 if (!arr || !count) { 5735 return SOC_E_NONE; 5736 } 5737 if ((pipe != _TD2P_XPIPE) && (pipe != _TD2P_YPIPE)) { 5738 return SOC_E_PARAM; 5739 } 5740 5741 temp_count = 0; 5742 mem = mmu_tdm_mems[pipe][table_num]; 5743 LOG_VERBOSE(BSL_LS_SOC_MMU, 5744 (BSL_META_U(unit, 5745 "Cal GET Pipe %d table_num %d slot_len %d mem %d \n"), 5746 pipe, table_num, slot_len, mem)); 5747 5748 for (slot = 0; slot < slot_len; slot += 2) { 5749 SOC_IF_ERROR_RETURN 5750 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, slot / 2, entry)); 5751 for (index = 0; index < 2; index++) { 5752 if (slot + index >= slot_len){ 5753 break; 5754 } 5755 field = mmu_tdm_fields[index]; 5756 fval = soc_mem_field32_get(unit, mem, entry, field); 5757 mmu_port = fval + si->mmu_port_base[pipe]; 5758 phy_port = si->port_m2p_mapping[mmu_port]; 5759 if (phy_port != -1) { 5760 log_port = si->port_p2l_mapping[phy_port]; 5761 if (((pipe == _TD2P_XPIPE) && IS_CPU_PORT(unit, log_port)) || 5762 ((pipe == _TD2P_YPIPE) && IS_LB_PORT(unit, log_port))) { 5763 LOG_VERBOSE(BSL_LS_SOC_MMU, 5764 (BSL_META_U(unit, 5765 "Pipe %d TDM Calendar %d slot %d" 5766 " mmu %d phy %d log %d fval 0x%x\n"), 5767 pipe, table_num, 5768 slot+index, 5769 mmu_port, 5770 phy_port, log_port, fval)); 5771 arr[temp_count] = slot+index; 5772 temp_count++; 5773 } 5774 } 5775 } 5776 } 5777 *count = temp_count; 5778 5779 return SOC_E_NONE; 5780 } 5781 5782 /* 5783 * Function: 5784 * _soc_td2p_tdm_cpulb_port_indices_set 5785 * Purpose: 5786 * This function sets the given slot number (locations) 5787 * in active TDM calendar with the value passed in the arguments. 5788 * Parameters: 5789 * unit - (IN) Unit number. 5790 * pipe - (IN) pipe number. 0 - xpipe, 1 - ypipe. 5791 * table_num - (IN) Active TDM Table number - 0 or 1 5792 * slot_len - (IN) Current length of the Active TDM table 5793 * *arr - (IN) contains location (slot num) of TDM Cal 5794 * count - (IN) number(count) of valid locations of TDM Cal 5795 * - valid number of entries in *arr 5796 * value - (IN) value to be set 5797 * Returns: 5798 * SOC_E_XXX 5799 */ 5800 STATIC int 5801 _soc_td2p_tdm_cpulb_port_indices_set(int unit, int pipe, int table_num, int slot_len, 5802 uint32 *arr, uint32 count, int value) 5803 { 5804 5805 static const soc_mem_t mmu_tdm_mems[2][2] = { 5806 {ES_PIPE0_TDM_TABLE_0m, ES_PIPE0_TDM_TABLE_1m}, 5807 {ES_PIPE1_TDM_TABLE_0m, ES_PIPE1_TDM_TABLE_1m} 5808 }; 5809 static const soc_mem_t mmu_tdm_fields[2] ={ 5810 PORT_NUM_EVENf, PORT_NUM_ODDf 5811 }; 5812 5813 int i, offset; 5814 uint32 entry[SOC_MAX_MEM_WORDS]; 5815 soc_field_t field; 5816 soc_mem_t mem; 5817 int slot, index; 5818 5819 if (!arr) { 5820 return SOC_E_NONE; 5821 } 5822 if ((pipe != _TD2P_XPIPE) && (pipe != _TD2P_YPIPE)) { 5823 return SOC_E_PARAM; 5824 } 5825 5826 mem = mmu_tdm_mems[pipe][table_num]; 5827 LOG_VERBOSE(BSL_LS_SOC_MMU, 5828 (BSL_META_U(unit, 5829 "Cal SET Pipe %d table_num %d slot_len %d mem %d \n"), 5830 pipe, table_num, slot_len, mem)); 5831 5832 for (i = 0; i < count; i++) { 5833 if (arr[i] >= slot_len){ 5834 break; 5835 } 5836 index = arr[i]; 5837 offset = index % 2; 5838 slot = index - offset; 5839 LOG_VERBOSE(BSL_LS_SOC_MMU, 5840 (BSL_META_U(unit, 5841 "Writing TDM Cal %d slot %d value 0x%x\n"), 5842 table_num, slot+offset, value)); 5843 SOC_IF_ERROR_RETURN 5844 (soc_mem_read(unit, mem, MEM_BLOCK_ALL, slot/2, entry)); 5845 field = mmu_tdm_fields[offset]; 5846 soc_mem_field32_set(unit, mem, entry, field, value); 5847 SOC_IF_ERROR_RETURN 5848 (soc_mem_write(unit, mem, MEM_BLOCK_ALL, slot / 2, entry)); 5849 } 5850 5851 return SOC_E_NONE; 5852 } 5853 5854 /* 5855 * Function: 5856 * _soc_td2p_mmu_map_phy_port_to_cpulb 5857 * Purpose: 5858 * This function temporarily maps old physical port to 5859 * CPU/loopback port in the mmu port mapping registers 5860 * Parameters: 5861 * unit - (IN) Unit number. 5862 * pipe - (IN) Pipe number. 5863 * count - (IN) Number of ports to map. 5864 * pport - (IN) Physical port number list. 5865 * Returns: 5866 * SOC_E_XXX 5867 */ 5868 STATIC int 5869 _soc_td2p_mmu_map_phy_port_to_cpulb(int unit, int pipe, 5870 int count, int *pport) 5871 { 5872 int i; 5873 uint32 rval; 5874 int old_phy_port; 5875 int cpulb_port; 5876 soc_info_t *si = &SOC_INFO(unit); 5877 5878 cpulb_port = (pipe == _TD2P_XPIPE)? si->cmic_port : si->lb_port; 5879 for (i = 0; i < count; i++) { 5880 LOG_VERBOSE(BSL_LS_SOC_MMU, 5881 (BSL_META_U(unit, 5882 "MMU RQE Phy port remapping " 5883 "old physical_port=%d\n"), 5884 pport[i])); 5885 5886 /* MMU_PORT_TO_PHY_PORT_MAPPING [MMU CPU/LB port number] 5887 * = old physical port number 5888 */ 5889 old_phy_port = pport[i]; 5890 5891 rval = 0; 5892 soc_reg_field_set(unit, MMU_PORT_TO_PHY_PORT_MAPPINGr, &rval, 5893 PHY_PORTf, old_phy_port); 5894 SOC_IF_ERROR_RETURN 5895 (soc_reg32_set(unit, MMU_PORT_TO_PHY_PORT_MAPPINGr, 5896 cpulb_port, 0, rval)); 5897 5898 } 5899 5900 /* MMU_PORT_TO_PHY_PORT_MAPPING [MMU CPU/LB port number] 5901 * = physical CPU/LB port number */ 5902 rval = 0; 5903 soc_reg_field_set(unit, MMU_PORT_TO_PHY_PORT_MAPPINGr, &rval, 5904 PHY_PORTf, si->port_l2p_mapping[cpulb_port]); 5905 SOC_IF_ERROR_RETURN 5906 (soc_reg32_set(unit, MMU_PORT_TO_PHY_PORT_MAPPINGr, 5907 cpulb_port, 0, rval)); 5908 5909 return SOC_E_NONE; 5910 } 5911 5912 /* 5913 * Function: 5914 * soc_td2p_mmu_rqe_phy_port_mapping_update 5915 * Purpose: 5916 * This function maps the old physical ports 5917 * temporarily to the CPU/Loopback port 5918 * Parameters: 5919 * unit - (IN) Unit number. 5920 * pipe - (IN) pipe number of the ports. 0 - xpipe, 1 - ypipe. 5921 * count - (IN) number of ports. 5922 * phy_port - (IN) list of physical port number. 5923 * Returns: 5924 * SOC_E_XXX 5925 * Note: 5926 * - Ports in the list should be in the same pipe. 5927 * - The goal of this function is to minimize the time CPU/loopback port 5928 * is down. Hence, minimal operations are done between 5929 * Turning off Opportunistic Scheduling for the CPU/Loopback port 5930 * and 5931 * Turning ON Opportunistic Scheduling for the CPU/Loopback port 5932 */ 5933 STATIC int 5934 soc_td2p_mmu_rqe_phy_port_mapping_update(int unit, int pipe, 5935 int count, int *phy_port) 5936 { 5937 static const soc_reg_t mmu_tdm_regs[2] = { 5938 ES_PIPE0_TDM_CONFIGr, ES_PIPE1_TDM_CONFIGr}; 5939 static const soc_mem_t cal_end_field[2] = { 5940 CAL0_ENDf, CAL1_ENDf }; 5941 static const soc_mem_t cal_end_single_field[2] = { 5942 CAL0_END_SINGLEf, CAL1_END_SINGLEf}; 5943 soc_reg_t mmu_tdm_reg; 5944 uint32 cpulb_port_tdm_indices[_MMU_TDM_LENGTH]; 5945 uint32 mmu_tdm_reg_rval; 5946 soc_info_t *si; 5947 uint32 cnt = 0; 5948 int cpulb_lport; 5949 int mmu_cpulb_port; 5950 int table_num; 5951 int slot_len; 5952 5953 5954 LOG_VERBOSE(BSL_LS_SOC_MMU, 5955 (BSL_META_U(unit, 5956 "Start MMU RQE phy port remapping\n"))); 5957 5958 if ((pipe != _TD2P_XPIPE) && (pipe != _TD2P_YPIPE)) { 5959 return SOC_E_PARAM; 5960 } 5961 /* Get all the fields here from Pipe TDM CONFIG 5962 * to avoid SBUS access in every 5963 * subsequent function to essentially 5964 * get the same information */ 5965 mmu_tdm_reg = mmu_tdm_regs[pipe]; 5966 mmu_tdm_reg_rval = 0; 5967 SOC_IF_ERROR_RETURN( 5968 soc_reg32_get(unit, mmu_tdm_reg, REG_PORT_ANY, 0, &mmu_tdm_reg_rval)); 5969 table_num = soc_reg_field_get( 5970 unit, mmu_tdm_reg, mmu_tdm_reg_rval, CURR_CALf); 5971 slot_len = (soc_reg_field_get( 5972 unit, mmu_tdm_reg, 5973 mmu_tdm_reg_rval, cal_end_field[table_num]) + 1) * 2; 5974 slot_len -= soc_reg_field_get( 5975 unit, mmu_tdm_reg, 5976 mmu_tdm_reg_rval, cal_end_single_field[table_num]); 5977 5978 si = &SOC_INFO(unit); 5979 cpulb_lport = (pipe == _TD2P_XPIPE)? si->cmic_port : si->lb_port; 5980 mmu_cpulb_port = si->port_p2m_mapping[si->port_l2p_mapping[cpulb_lport]]; 5981 /* Adjust for pipe */ 5982 mmu_cpulb_port = mmu_cpulb_port &0x3f; 5983 5984 /* Get the location of (slot numbers) CPU/loopback port in the active TDM calendar */ 5985 SOC_IF_ERROR_RETURN( 5986 _soc_td2p_tdm_cpulb_port_indices_get(unit, pipe, table_num, 5987 slot_len, cpulb_port_tdm_indices, 5988 &cnt)); 5989 5990 /* Turn off Opportunistic Scheduling for the CPU/Loopback port */ 5991 soc_reg_field_set(unit, mmu_tdm_reg, &mmu_tdm_reg_rval, OPP_CPULB_ENf, 0); 5992 SOC_IF_ERROR_RETURN( 5993 soc_reg32_set(unit, mmu_tdm_reg, 5994 REG_PORT_ANY, 0, mmu_tdm_reg_rval)); 5995 5996 LOG_VERBOSE(BSL_LS_SOC_MMU, 5997 (BSL_META_U(unit, 5998 "Writing 0x3f to CPU/LB port locations\n"))); 5999 6000 /* Write to the active TDM calendar table, 6001 * changing all instances of the CPU/LB port to 0x3f */ 6002 SOC_IF_ERROR_RETURN( 6003 _soc_td2p_tdm_cpulb_port_indices_set(unit, pipe, table_num, slot_len, 6004 cpulb_port_tdm_indices, cnt, 0x3f)); 6005 6006 if (pipe == _TD2P_XPIPE) { 6007 /* Stop EDB drain to the CMIC */ 6008 (void) WRITE_CMIC_RXBUF_BLOCK_DATABUF_ALLOCr(unit, 1); 6009 } else { 6010 /* Waiting for LB port to be empty */ 6011 SOC_IF_ERROR_RETURN( 6012 _soc_td2p_lb_port_flush(unit)); 6013 } 6014 6015 /* Temporarily map each old physical port number to the CPU/Loopback Port MMU port */ 6016 SOC_IF_ERROR_RETURN( 6017 _soc_td2p_mmu_map_phy_port_to_cpulb(unit, pipe, count, phy_port)); 6018 6019 if (pipe == _TD2P_XPIPE) { 6020 /* Resume EDB drain to the CMIC */ 6021 (void) WRITE_CMIC_RXBUF_BLOCK_DATABUF_ALLOCr(unit, 0); 6022 } 6023 6024 LOG_VERBOSE(BSL_LS_SOC_MMU, 6025 (BSL_META_U(unit, 6026 "Restoring TDM Cal to original\n\n"))); 6027 /* Write to the active TDM calendar table, 6028 * changing all instances of the LB port to mmu port for LB port */ 6029 SOC_IF_ERROR_RETURN( 6030 _soc_td2p_tdm_cpulb_port_indices_set(unit, pipe, table_num, slot_len, 6031 cpulb_port_tdm_indices, cnt, mmu_cpulb_port)); 6032 6033 6034 /* Turn ON Opportunistic Scheduling for the Loopback port */ 6035 soc_reg_field_set(unit, mmu_tdm_reg, &mmu_tdm_reg_rval, OPP_CPULB_ENf, 1); 6036 SOC_IF_ERROR_RETURN( 6037 soc_reg32_set(unit, 6038 mmu_tdm_reg, REG_PORT_ANY, 0, mmu_tdm_reg_rval)); 6039 6040 6041 LOG_VERBOSE(BSL_LS_SOC_MMU, 6042 (BSL_META_U(unit, 6043 "End MMU RQE phy port remapping\n"))); 6044 6045 return SOC_E_NONE; 6046 } 6047 6048 /* 6049 * Function: 6050 * soc_td2p_mmu_rqe_phy_port_mapping_set 6051 * Purpose: 6052 * This function maps the old physical ports 6053 * (that are either being deleted or remapped 6054 * in the flexport sequence) 6055 * temporarily to the CPU/Loopback port 6056 * Parameters: 6057 * unit - (IN) Unit number. 6058 * pre_count - (IN) Array size for pre-FlexPort array. 6059 * pre_resource - (IN) Pre-FlexPort configuration array. 6060 * Returns: 6061 * SOC_E_XXX 6062 * Note: 6063 * - Assumes all data is Port Resource arrays has been validated. 6064 * - The goal of this function is to minimize the time loopback port 6065 * is down. Hence, minimal operations are done between 6066 * Turning off Opportunistic Scheduling for the CPU/Loopback port 6067 * and 6068 * Turning ON Opportunistic Scheduling for the CPU/Loopback port 6069 */ 6070 int 6071 soc_td2p_mmu_rqe_phy_port_mapping_set(int unit, 6072 int pre_count, 6073 soc_port_resource_t *pre_resource) 6074 { 6075 int *pport; 6076 int i, px_cnt = 0, py_cnt = 0; 6077 soc_port_resource_t *pr; 6078 int rv = SOC_E_NONE; 6079 6080 LOG_VERBOSE(BSL_LS_SOC_MMU, 6081 (BSL_META_U(unit, 6082 "Start MMU RQE phy port remapping\n"))); 6083 if (pre_count <= 0) { 6084 return SOC_E_NONE; 6085 } 6086 /* sort pre_resource based on port pipe. */ 6087 pport = sal_alloc(pre_count * sizeof(int), "phy port list"); 6088 if (!pport) { 6089 return SOC_E_MEMORY; 6090 } 6091 for (i = 0, pr = &pre_resource[0]; i < pre_count; i++, pr++) { 6092 if (pr->physical_port > _TD2_PORTS_PER_PIPE) { 6093 py_cnt++; 6094 pport[pre_count - py_cnt] = pr->physical_port; 6095 } else { 6096 pport[px_cnt] = pr->physical_port; 6097 px_cnt++; 6098 } 6099 } 6100 6101 /* Do remapping for ports in x-pipe and y-pipe respectively. */ 6102 if (px_cnt > 0) { 6103 rv = soc_td2p_mmu_rqe_phy_port_mapping_update(unit, _TD2P_XPIPE, 6104 px_cnt, pport); 6105 } 6106 if (SOC_FAILURE(rv)) { 6107 goto cleanup; 6108 } 6109 6110 if (py_cnt > 0) { 6111 rv = soc_td2p_mmu_rqe_phy_port_mapping_update(unit, _TD2P_YPIPE, 6112 py_cnt, pport + px_cnt); 6113 } 6114 6115 cleanup: 6116 sal_free(pport); 6117 6118 if (SOC_FAILURE(rv)) { 6119 LOG_VERBOSE(BSL_LS_SOC_MMU, 6120 (BSL_META_U(unit, 6121 "Error happen during MMU RQE phy port remapping\n"))); 6122 } else { 6123 LOG_VERBOSE(BSL_LS_SOC_MMU, 6124 (BSL_META_U(unit, 6125 "End MMU RQE phy port remapping\n"))); 6126 } 6127 6128 return rv; 6129 } 6130 6131 #endif /* BCM_TRIDENT2PLUS_SUPPORT */