asf.c (77146B)
1 /**************************************************************************** 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 */ 8 9 #include <soc/maverick2.h> 10 11 #if defined(BCM_MAVERICK2_SUPPORT) 12 13 #include <appl/diag/system.h> 14 #include <soc/drv.h> 15 #include <soc/ll.h> 16 #include <soc/property.h> 17 #include <shared/bsl.h> 18 #ifdef BCM_WARM_BOOT_SUPPORT 19 #include <soc/scache.h> 20 #endif 21 22 23 #define _SOC_MV2_ASF_CLASS_CNT 13 /* 0 for SAF, 13-15 are reserved. */ 24 #define _SOC_MV2_ASF_QUERY 0xfe 25 #define _SOC_MV2_ASF_RETRV 0xff 26 27 #define _SOC_MV2_CT_CLASS_TO_SPEED_MAP(ct_class) \ 28 _soc_mv2_asf_cfg_tbl[(ct_class)].speed 29 30 #define MIN(x, y) (((x) < (y)) ? (x) : (y)) 31 32 #define _SOC_MV2_ASF_SPEED_CLASS_VALIDATE(ct_class, floor) \ 33 do { \ 34 if (!(((ct_class) >= (floor)) && \ 35 ((ct_class) < _SOC_MV2_ASF_CLASS_CNT))) \ 36 return SOC_E_PARAM; \ 37 } while (0) 38 39 #define _SOC_MV2_ASF_PORT_VALIDATE(unit, port) \ 40 do { \ 41 if (IS_CPU_PORT(((unit)), (port)) || \ 42 IS_LB_PORT(((unit)), (port)) || \ 43 SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), (port))) \ 44 return SOC_E_UNAVAIL; \ 45 } while (0) 46 47 /* EP Credits Outstanding */ 48 typedef struct _soc_mv2_ep_credit_s { 49 uint8 base_cells; /* Baseline cells */ 50 uint8 pfc_op_cells; /* PFC Optimized cells */ 51 } _soc_mv2_ep_credit_t; 52 53 /* CT FIFO Threshold and Depth */ 54 typedef struct _soc_mv2_ct_fifo_s { 55 uint8 line_rate; /* Line-rate profile */ 56 uint8 oversub; /* General profile */ 57 } _soc_mv2_ct_fifo_t; 58 59 /* Bubble MOP */ 60 typedef struct _soc_mv2_mop_s { 61 uint8 line_rate; /* Line-rate profile */ 62 uint8 oversub; /* Oversub profile */ 63 } _soc_mv2_mop_t; 64 65 /* EDB Prebuffer */ 66 typedef struct _soc_mv2_edb_prebuf_profile_s { 67 uint8 saf; /* prebuffer for store-and-forward. 16B granularity. */ 68 uint8 ct; /* prebuffer for cut-through. 16B granularity. */ 69 } _soc_mv2_edb_prebuf_profile_t; 70 typedef struct _soc_mv2_edb_prebuf_s { 71 _soc_mv2_edb_prebuf_profile_t line_rate; 72 _soc_mv2_edb_prebuf_profile_t oversub_161; /* 1.61 Oversub */ 73 _soc_mv2_edb_prebuf_profile_t oversub_2_1; /* 2:1 Oversub */ 74 _soc_mv2_edb_prebuf_profile_t oversub_21_1; /* 2.155:1 Oversub */ 75 } _soc_mv2_edb_prebuf_t; 76 77 /* MMU Credit Thresholds */ 78 typedef struct _soc_mv2_mmu_credit_threshold_profile_s { 79 uint8 lo; /* MMU High Credit Threshold */ 80 uint8 hi; /* MMU Low Credit Threshold */ 81 } _soc_mv2_mmu_credit_threshold_profile_t; 82 typedef struct _soc_mv2_mmu_credit_threshold_s { 83 _soc_mv2_mmu_credit_threshold_profile_t lr_os_161; /* line-rate and os ratio <= 1.61 */ 84 _soc_mv2_mmu_credit_threshold_profile_t os_2_1; /* os ratio > 1.61 */ 85 } _soc_mv2_mmu_credit_threshold_t; 86 87 /* ASF core config */ 88 typedef struct _soc_mv2_asf_core_cfg_s { 89 int speed; 90 uint8 min_sp; /* Min. Src. Port Speed */ 91 uint8 max_sp; /* Max. Src. Port Speed */ 92 uint8 mmu_prebuffer; /* MMU prebuffer */ 93 _soc_mv2_ct_fifo_t ct_fifo_threshold; /* Same-speed CT FIFO Threshold */ 94 _soc_mv2_ct_fifo_t ct_fifo_depth; /* Same-speed CT FIFO Depth */ 95 uint8 fast_to_slow_acc; /* Fast to slow CT Accumulation */ 96 _soc_mv2_mop_t mop_enable; /* Bubble MOP enable */ 97 _soc_mv2_edb_prebuf_t edb_prebuffer; /* EDB prebuffer */ 98 _soc_mv2_mmu_credit_threshold_t mmu_credit_threshold; /* MMU Credit Threshold */ 99 _soc_mv2_ep_credit_t ep_credit; /* EP Credit */ 100 /* NOTE: DON'T ALTER FIELD ORDER */ 101 } _soc_mv2_asf_core_cfg_t; 102 103 /* ASF ctrl */ 104 typedef struct _soc_mv2_asf_ctrl_s { 105 uint8 init; 106 pbmp_t asf_ports; 107 pbmp_t pause_restore; 108 pbmp_t asf_ss; 109 pbmp_t asf_sf; 110 pbmp_t asf_fs; 111 soc_mv2_asf_mem_profile_e asf_mem_profile; 112 } _soc_mv2_asf_ctrl_t; 113 114 #ifdef BCM_WARM_BOOT_SUPPORT 115 /* ASF Warmboot */ 116 typedef struct _soc_mv2_asf_wb_s { 117 int unit; 118 _soc_mv2_asf_ctrl_t asf_ctrl; 119 } _soc_mv2_asf_wb_t; 120 #endif 121 122 /* ASF Core Config Table */ 123 static const _soc_mv2_asf_core_cfg_t 124 _soc_mv2_asf_cfg_tbl[_SOC_MV2_ASF_CLASS_CNT] = { 125 { -1, 0, 0, 0, {0, 0}, {0, 0}, 0, {0, 0}, {{0, 0}, { 0, 0}, { 0, 0}, {0, 0}}, {{0, 0}, {0, 0}}, { 0, 0}}, /* SAF */ 126 { 10000, 1, 10, 0, {3, 10}, {8, 18}, 31, {0, 0}, {{7, 29}, {15, 49}, {19, 56}, {20, 59}}, {{2, 4}, {2, 6}}, {11, 11}}, /* 10GE */ 127 { 11000, 1, 10, 6, {3, 10}, {8, 18}, 31, {0, 0}, {{7, 29}, {15, 49}, {19, 56}, {20, 59}}, {{2, 4}, {2, 6}}, {11, 11}}, /* HG[11] */ 128 { 20000, 3, 10, 0, {3, 10}, {8, 24}, 24, {1, 1}, {{7, 13}, {15, 59}, {19, 68}, {20, 72}}, {{2, 7}, {2, 11}}, {16, 13}}, /* 20GE */ 129 { 21000, 3, 10, 6, {3, 10}, {8, 24}, 24, {1, 1}, {{7, 13}, {15, 59}, {19, 68}, {20, 72}}, {{2, 7}, {2, 11}}, {16, 13}}, /* HG[21] */ 130 { 25000, 5, 10, 0, {3, 12}, {8, 30}, 21, {1, 1}, {{7, 13}, {15, 92}, {19, 101}, {20, 105}},{{3, 7}, {3, 11}}, {20, 18}}, /* 25GE */ 131 { 27000, 5, 10, 7, {3, 12}, {8, 30}, 21, {1, 1}, {{7, 13}, {15, 92}, {19, 101}, {20, 105}},{{3, 7}, {3, 11}}, {20, 18}}, /* HG[27] */ 132 { 40000, 7, 12, 0, {3, 10}, {8, 29}, 24, {1, 1}, {{7, 13}, {15, 30}, {19, 37}, {20, 40}}, {{4, 13}, {4, 21}}, {25, 19}}, /* 40GE */ 133 { 42000, 7, 12, 4, {3, 10}, {8, 29}, 24, {1, 1}, {{7, 13}, {15, 30}, {19, 37}, {20, 40}}, {{4, 13}, {4, 21}}, {25, 19}}, /* HG[42] */ 134 { 50000, 9, 12, 0, {3, 12}, {8, 36}, 21, {1, 1}, {{7, 13}, {15, 30}, {19, 37}, {20, 40}}, {{4, 15}, {4, 21}}, {26, 22}}, /* 50GE */ 135 { 53000, 9, 12, 4, {3, 12}, {8, 36}, 21, {1, 1}, {{7, 13}, {15, 30}, {19, 37}, {20, 40}}, {{4, 15}, {4, 21}}, {26, 22}}, /* HG[53] */ 136 {100000, 11, 12, 0, {3, 10}, {8, 45}, 3, {1, 1}, {{7, 13}, {15, 30}, {19, 37}, {20, 40}}, {{8, 27}, {8, 29}}, {41, 38}}, /* 100GE */ 137 {106000, 11, 12, 4, {3, 10}, {8, 45}, 0, {1, 1}, {{7, 13}, {15, 30}, {19, 37}, {20, 40}}, {{8, 27}, {8, 29}}, {41, 38}} /* HG[106] */ 138 }; 139 140 /* ASF Control */ 141 static _soc_mv2_asf_ctrl_t* 142 _soc_mv2_asf_ctrl[SOC_MAX_NUM_DEVICES] = {NULL}; 143 144 /* ASF profile billboard */ 145 static const char *asf_profile_str[3] = 146 {"removed of cut-thru capability", 147 "capable of limited speed range cut-thru", 148 "capable of extended speed range cut-thru"}; 149 150 151 /* 152 * Cut-through class encoding: 153 * 0 - SAF 154 * 1 - 10GE 155 * 2 - HG[11] 156 * 3 - 20GE 157 * 4 - 21[HG} 158 * 5 - 25GE 159 * 6 - HG[27] 160 * 7 - 40GE 161 * 8 - HG[42] 162 * 9 - 50GE 163 * 10 - HG[53] 164 * 11 - 100GE 165 * 12 - HG[106] 166 */ 167 STATIC int 168 _soc_mv2_speed_to_ct_class_map(int speed) 169 { 170 int ct_class; 171 172 if (1000 == speed) { /* 1G ports always in SAF, use same setting as 10G ports */ 173 speed = 10000; 174 } 175 176 for (ct_class = 0; ct_class < _SOC_MV2_ASF_CLASS_CNT; ct_class++) { 177 if (_soc_mv2_asf_cfg_tbl[ct_class].speed == speed) { 178 return ct_class; 179 } 180 } 181 182 return SOC_E_PARAM; 183 } 184 185 /****************************************************************************** 186 * Name: _soc_mv2_port_asf_class_get * 187 * Description: * 188 * Get Cut-through class configured for the specified port * 189 * IN params: * 190 * - Unit * 191 * - Logical Port * 192 * - Port Speed * 193 * OUT params: * 194 * - CT class * 195 * Returns: * 196 * - SOC_E_NONE on success * 197 * - SOC_E_PARAM on invalid parameter * 198 */ 199 STATIC int 200 _soc_mv2_port_asf_class_get( 201 int unit, 202 soc_port_t port, 203 OUT int* const ct_class) 204 { 205 egr_ip_cut_thru_class_entry_t entry; 206 207 if (!ct_class) { 208 return SOC_E_PARAM; 209 } 210 211 sal_memset(&entry, 0, sizeof(egr_ip_cut_thru_class_entry_t)); 212 SOC_IF_ERROR_RETURN 213 (READ_EGR_IP_CUT_THRU_CLASSm(unit, MEM_BLOCK_ALL, port, &entry)); 214 *ct_class = soc_mem_field32_get(unit, EGR_IP_CUT_THRU_CLASSm, &entry, 215 CUT_THRU_CLASSf); 216 217 return SOC_E_NONE; 218 } 219 220 /****************************************************************************** 221 * Name: _soc_mv2_port_asf_class_init * 222 * Description: * 223 * Initialize Cut-through class for the specified port * 224 * IN params: * 225 * - Unit * 226 * - Logical Port * 227 * - CT class * 228 * Returns: * 229 * - SOC_E_NONE on success * 230 * - SOC_E_PARAM on invalid parameter * 231 */ 232 STATIC int 233 _soc_mv2_port_asf_class_init( 234 int unit, 235 soc_port_t port, 236 int ct_class) 237 { 238 egr_ip_cut_thru_class_entry_t entry; 239 240 sal_memset(&entry, 0, sizeof(egr_ip_cut_thru_class_entry_t)); 241 soc_mem_field32_set(unit, EGR_IP_CUT_THRU_CLASSm, &entry, 242 CUT_THRU_CLASSf, ct_class); 243 SOC_IF_ERROR_RETURN 244 (WRITE_EGR_IP_CUT_THRU_CLASSm(unit, MEM_BLOCK_ALL, port, &entry)); 245 246 return SOC_E_NONE; 247 } 248 249 /****************************************************************************** 250 * Name: _soc_mv2_port_asf_xmit_start_count_get * 251 * Description: * 252 * Query or retrieve the XMIT Start Count for the specified source class * 253 * of the port depending on the magic number passed in xmit_cnt * 254 * IN params: * 255 * - Unit * 256 * - Logical Port * 257 * - Source Port's Class * 258 * - Destination Port's CT Class * 259 * - ASF Mode * 260 * IN/OUT params: * 261 * - xmit_cnt : IN: carries magic number for query / retrieve * 262 * - xmit_cnt : OUT: contains a valid XMIT START COUNT for the * 263 * source port class, on success * 264 * Returns: * 265 * - SOC_E_NONE on success * 266 * - SOC_E_PARAM on invalid parameter * 267 * - SOC_E_INTERNAL on init/soc errors * 268 */ 269 STATIC int 270 _soc_mv2_port_asf_xmit_start_count_get( 271 int unit, 272 soc_port_t port, 273 int sc, 274 int dc, 275 soc_mv2_asf_mode_e mode, 276 IN_OUT uint8* const xmit_cnt) 277 { 278 soc_info_t *si; 279 egr_xmit_start_count_entry_t entry; 280 int ovs_ratio, port_idx; 281 soc_pbmp_t mv2_ports, line_rate_ports, ovs_161_ports, ovs_21_ports; 282 soc_port_t mv2_port; 283 int speed; 284 int ct_class; 285 int pipe; 286 soc_mem_t config_mem = INVALIDm; 287 288 if (!(si = &SOC_INFO(unit))) { 289 return SOC_E_INTERNAL; 290 } 291 292 pipe = si->port_pipe[port]; 293 config_mem = SOC_MEM_UNIQUE_ACC(unit, EGR_XMIT_START_COUNTm)[pipe]; 294 295 if (_SOC_MV2_ASF_MODE_CFG_UPDATE == mode) { /* translate to valid mode */ 296 /* reverse map speed class to speed, to surmount speed deficit */ 297 SOC_IF_ERROR_RETURN(_soc_mv2_port_asf_class_get(unit, port, &ct_class)); 298 _SOC_MV2_ASF_SPEED_CLASS_VALIDATE(ct_class, 0); 299 speed = _SOC_MV2_CT_CLASS_TO_SPEED_MAP(ct_class); 300 SOC_IF_ERROR_RETURN(soc_mv2_port_asf_mode_get(unit, port, speed, &mode)); 301 } 302 if (!xmit_cnt || 303 !((mode >= _SOC_MV2_ASF_MODE_SAF) && 304 (mode <= _SOC_MV2_ASF_MODE_FAST_TO_SLOW))) { 305 return SOC_E_PARAM; 306 } 307 _SOC_MV2_ASF_SPEED_CLASS_VALIDATE(sc, 0); 308 _SOC_MV2_ASF_SPEED_CLASS_VALIDATE(dc, 0); 309 310 if (_SOC_MV2_ASF_RETRV == *xmit_cnt) { 311 *xmit_cnt = 0; 312 port_idx = ((port % _MV2_TDM_DEV_PORTS_PER_PIPE) * 16) + sc; 313 314 sal_memset(&entry, 0, sizeof(egr_xmit_start_count_entry_t)); 315 SOC_IF_ERROR_RETURN(soc_mem_read(unit, config_mem, MEM_BLOCK_ALL, 316 port_idx, &entry)); 317 *xmit_cnt = soc_mem_field32_get(unit, config_mem, 318 &entry, THRESHOLDf); 319 } else if (_SOC_MV2_ASF_QUERY == *xmit_cnt) { 320 *xmit_cnt = 0; 321 SOC_PBMP_CLEAR(mv2_ports); 322 SOC_PBMP_ASSIGN(mv2_ports, PBMP_E_ALL(unit)); 323 SOC_PBMP_OR(mv2_ports, PBMP_HG_ALL(unit)); 324 SOC_PBMP_REMOVE(mv2_ports, PBMP_MANAGEMENT(unit)); 325 SOC_PBMP_CLEAR(line_rate_ports); 326 SOC_PBMP_CLEAR(ovs_161_ports); 327 SOC_PBMP_CLEAR(ovs_21_ports); 328 329 PBMP_ITER(mv2_ports, mv2_port) { 330 if (SOC_PBMP_MEMBER(si->oversub_pbm, mv2_port)) { 331 SOC_IF_ERROR_RETURN( 332 soc_td3_port_oversub_ratio_get(unit, mv2_port, &ovs_ratio)); 333 if (ovs_ratio < 1620) { /* oversub ratio <= 1.61 */ 334 SOC_PBMP_PORT_ADD(ovs_161_ports, mv2_port); 335 } else if (ovs_ratio >= 1620 && ovs_ratio <= 2000) { /* oversub ratio <= 2.0 */ 336 SOC_PBMP_PORT_ADD(ovs_21_ports, mv2_port); 337 } 338 339 } else { /* Line-rate */ 340 SOC_PBMP_PORT_ADD(line_rate_ports, mv2_port); 341 } 342 } 343 344 /* if sc < dc, use SAF setting; else, use CT setting */ 345 if (SOC_PBMP_EQ(mv2_ports, line_rate_ports)) { 346 *xmit_cnt = (sc < dc) ? 347 _soc_mv2_asf_cfg_tbl[dc].edb_prebuffer.line_rate.saf : 348 _soc_mv2_asf_cfg_tbl[dc].edb_prebuffer.line_rate.ct; 349 } else if (SOC_PBMP_EQ(mv2_ports, ovs_161_ports)) { 350 *xmit_cnt = (sc < dc) ? 351 _soc_mv2_asf_cfg_tbl[dc].edb_prebuffer.oversub_161.saf : 352 _soc_mv2_asf_cfg_tbl[dc].edb_prebuffer.oversub_161.ct; 353 } else if (SOC_PBMP_EQ(mv2_ports, ovs_21_ports)){ 354 *xmit_cnt = (sc < dc) ? 355 _soc_mv2_asf_cfg_tbl[dc].edb_prebuffer.oversub_2_1.saf : 356 _soc_mv2_asf_cfg_tbl[dc].edb_prebuffer.oversub_2_1.ct; 357 } else { 358 *xmit_cnt = (sc < dc) ? 359 _soc_mv2_asf_cfg_tbl[dc].edb_prebuffer.oversub_21_1.saf : 360 _soc_mv2_asf_cfg_tbl[dc].edb_prebuffer.oversub_21_1.ct; 361 } 362 363 } 364 365 return SOC_E_NONE; 366 } 367 368 /****************************************************************************** 369 * Name: _soc_mv2_port_asf_mmu_prebuf_get * 370 * Description: * 371 * Query or retrieve MMU Prebuffer (Min Source Port XMIT Count) for the * 372 * specified port depending on the magic number passed in mmu_prebuf * 373 * IN params: * 374 * - Unit * 375 * - Logical Port * 376 * - Port Speed * 377 * IN/OUT params: * 378 * - mmu_prebuf : IN: carries magic number for query / retrieve * 379 * - mmu_prebuf : OUT: contains a valid Min Source Port XMIT Count on * 380 * success * 381 * Returns: * 382 * - SOC_E_NONE on success * 383 * - SOC_E_PARAM on invalid parameter * 384 * - SOC_E_INTERNAL on init/soc errors * 385 */ 386 STATIC int 387 _soc_mv2_port_asf_mmu_prebuf_get( 388 int unit, 389 soc_port_t port, 390 int port_speed, 391 IN_OUT uint8* const mmu_prebuf) 392 { 393 uint32 rval; 394 int speed_encoding; 395 396 _SOC_MV2_ASF_PORT_VALIDATE(unit, port); 397 if (!mmu_prebuf) { 398 return SOC_E_PARAM; 399 } 400 401 if (_SOC_MV2_ASF_RETRV == *mmu_prebuf) { 402 *mmu_prebuf = 0; 403 404 if (!_soc_mv2_asf_ctrl[unit]->init) { 405 return SOC_E_INTERNAL; 406 } 407 408 SOC_IF_ERROR_RETURN(READ_ASF_EPORT_CFGr(unit, port, &rval)); 409 *mmu_prebuf = soc_reg_field_get(unit, ASF_EPORT_CFGr, rval, 410 MIN_SRC_PORT_XMIT_CNTf); 411 } else if (_SOC_MV2_ASF_QUERY == *mmu_prebuf) { 412 *mmu_prebuf = 0; 413 speed_encoding = _soc_mv2_speed_to_ct_class_map(port_speed); 414 _SOC_MV2_ASF_SPEED_CLASS_VALIDATE(speed_encoding, 1); 415 416 *mmu_prebuf = 417 _soc_mv2_asf_cfg_tbl[speed_encoding].mmu_prebuffer; 418 } 419 420 return SOC_E_NONE; 421 } 422 423 /****************************************************************************** 424 * Name: _soc_mv2_port_asf_fifo_threshold_get * 425 * Description: * 426 * Query or retrieve FIFO Threshold for the specified port depending on * 427 * the magic number passed in fifo_threshold * 428 * IN params: * 429 * - Unit * 430 * - Logical Port * 431 * - Port Speed * 432 * - ASF Mode * 433 * IN/OUT params: * 434 * - fifo_threshold : IN: carries magic number for query / retrieve * 435 * - fifo_threshold : OUT: contains a valid FIFO Threshold on success * 436 * Returns: * 437 * - SOC_E_NONE on success * 438 * - SOC_E_PARAM on invalid parameter * 439 * - SOC_E_INTERNAL on init/soc errors * 440 */ 441 STATIC int 442 _soc_mv2_port_asf_fifo_threshold_get( 443 int unit, 444 soc_port_t port, 445 int port_speed, 446 soc_mv2_asf_mode_e mode, 447 IN_OUT uint8* const fifo_threshold) 448 { 449 uint32 rval; 450 int speed_encoding; 451 uint8 mmu_prebuf = 0, oversub; 452 453 _SOC_MV2_ASF_PORT_VALIDATE(unit, port); 454 if (!fifo_threshold) { 455 return SOC_E_PARAM; 456 } 457 458 if (_SOC_MV2_ASF_RETRV == *fifo_threshold) { 459 *fifo_threshold = 0; 460 461 if (!_soc_mv2_asf_ctrl[unit]->init) { 462 return SOC_E_INTERNAL; 463 } 464 465 SOC_IF_ERROR_RETURN(READ_ASF_EPORT_CFGr(unit, port, &rval)); 466 *fifo_threshold = soc_reg_field_get(unit, ASF_EPORT_CFGr, rval, 467 FIFO_THRESHOLDf); 468 } else if (_SOC_MV2_ASF_QUERY == *fifo_threshold) { 469 *fifo_threshold = 0; 470 speed_encoding = _soc_mv2_speed_to_ct_class_map(port_speed); 471 _SOC_MV2_ASF_SPEED_CLASS_VALIDATE(speed_encoding, 1); 472 oversub = (SOC_PBMP_MEMBER(SOC_INFO(unit).oversub_pbm, port) ? 1 : 0); 473 474 /* CT Type | CT FIFO Thre 475 ----------------+----------------------------- 476 Same-Speed | Same-speed CT Thre 477 Slow-to-Fast | Same-speed CT Thre + MMU Prebuffer 478 Fast-to-Slow | Same-speed CT Thre */ 479 480 *fifo_threshold = (oversub ? 481 _soc_mv2_asf_cfg_tbl[speed_encoding].ct_fifo_threshold.oversub : 482 _soc_mv2_asf_cfg_tbl[speed_encoding].ct_fifo_threshold.line_rate); 483 484 switch(mode) { 485 case _SOC_MV2_ASF_MODE_SAME_SPEED: 486 case _SOC_MV2_ASF_MODE_FAST_TO_SLOW: 487 break; 488 489 case _SOC_MV2_ASF_MODE_SLOW_TO_FAST: 490 /* Extra MMU prebuffer threshold */ 491 mmu_prebuf = _SOC_MV2_ASF_QUERY; 492 SOC_IF_ERROR_RETURN( 493 _soc_mv2_port_asf_mmu_prebuf_get(unit, port, port_speed, 494 &mmu_prebuf)); 495 496 *fifo_threshold += mmu_prebuf; 497 break; 498 499 default: 500 return SOC_E_PARAM; 501 } 502 } 503 504 return SOC_E_NONE; 505 } 506 507 /****************************************************************************** 508 * Name: _soc_mv2_port_asf_fifo_depth_get * 509 * Description: * 510 * Query or retrieve FIFO Depth for the specified port depending on the * 511 * magic number passed in buf_sz * 512 * IN params: * 513 * - Unit * 514 * - Logical Port * 515 * - Port Speed * 516 * - ASF Mode * 517 * IN/OUT params: * 518 * - fifo_depth : IN: carries magic number for query/retrieve * 519 * - fifo_depth : OUT: contains a valid FIFO Depth on success * 520 * Returns: * 521 * - SOC_E_NONE on success * 522 * - SOC_E_PARAM on invalid parameter * 523 * - SOC_E_INTERNAL on init/soc errors * 524 */ 525 STATIC int 526 _soc_mv2_port_asf_fifo_depth_get( 527 int unit, 528 soc_port_t port, 529 int port_speed, 530 soc_mv2_asf_mode_e mode, 531 IN_OUT uint8* const fifo_depth) 532 { 533 uint32 rval; 534 int speed_encoding; 535 uint8 oversub, mmu_prebuf = 0; 536 uint8 same_speed_ct_threshold = 0; 537 538 _SOC_MV2_ASF_PORT_VALIDATE(unit, port); 539 if (!fifo_depth) { 540 return SOC_E_PARAM; 541 } 542 543 if (_SOC_MV2_ASF_RETRV == *fifo_depth) { 544 if (!_soc_mv2_asf_ctrl[unit]->init) { 545 return SOC_E_INTERNAL; 546 } 547 548 *fifo_depth = 0; 549 SOC_IF_ERROR_RETURN(READ_ASF_EPORT_CFGr(unit, port, &rval)); 550 *fifo_depth = soc_reg_field_get(unit, ASF_EPORT_CFGr, rval, 551 FIFO_DEPTHf); 552 } else if (_SOC_MV2_ASF_QUERY == *fifo_depth) { 553 *fifo_depth = 0; 554 speed_encoding = _soc_mv2_speed_to_ct_class_map(port_speed); 555 _SOC_MV2_ASF_SPEED_CLASS_VALIDATE(speed_encoding, 1); 556 oversub = (SOC_PBMP_MEMBER(SOC_INFO(unit).oversub_pbm, port) ? 1 : 0); 557 558 /* CT Type | CT FIFO Dept 559 ----------------+----------------------------- 560 Same-Speed | Same-speed CT Dept 561 Slow-to-Fast | Same-speed CT Dept + MMU Prebuffer 562 Fast-to-Slow | Min (Same-speed CT Dept + Fast-to-slow Accumulation, 563 | Same-speed CT Thres + 38) */ 564 565 *fifo_depth = (oversub ? 566 _soc_mv2_asf_cfg_tbl[speed_encoding].ct_fifo_depth.oversub : 567 _soc_mv2_asf_cfg_tbl[speed_encoding].ct_fifo_depth.line_rate); 568 569 switch(mode) { 570 case _SOC_MV2_ASF_MODE_SAME_SPEED: 571 break; 572 573 case _SOC_MV2_ASF_MODE_SLOW_TO_FAST: 574 /* Extra MMU prebuffer depth */ 575 mmu_prebuf = _SOC_MV2_ASF_QUERY; 576 SOC_IF_ERROR_RETURN( 577 _soc_mv2_port_asf_mmu_prebuf_get(unit, port, port_speed, 578 &mmu_prebuf)); 579 580 *fifo_depth += mmu_prebuf; 581 break; 582 583 case _SOC_MV2_ASF_MODE_FAST_TO_SLOW: 584 *fifo_depth += 585 _soc_mv2_asf_cfg_tbl[speed_encoding].fast_to_slow_acc; 586 587 same_speed_ct_threshold = _SOC_MV2_ASF_QUERY; 588 SOC_IF_ERROR_RETURN( 589 _soc_mv2_port_asf_fifo_threshold_get(unit, port, port_speed, 590 _SOC_MV2_ASF_MODE_SAME_SPEED, 591 &same_speed_ct_threshold)); 592 593 *fifo_depth = 594 MIN((*fifo_depth), (same_speed_ct_threshold + 38)); 595 break; 596 597 default: 598 return SOC_E_PARAM; 599 } 600 } 601 602 return SOC_E_NONE; 603 } 604 605 /****************************************************************************** 606 * Name: _soc_mv2_port_asf_speed_limits_get * 607 * Description: * 608 * Query or retrieve min & max source port speeds for the specified port * 609 * depending on the magic number passed in min_sp & * 610 * max_sp * 611 * IN params: * 612 * - Unit * 613 * - Logical Port * 614 * - Port Speed * 615 * - ASF Mode * 616 * IN/OUT params: * 617 * - min_sp : IN: carries magic number for query / retrieve * 618 * - min_sp : OUT: contains a valid min source port speed * 619 * on success * 620 * - max_sp : IN: carries magic number for query / retrieve * 621 * - max_sp : OUT: contains a valid max source port speed * 622 * on success * 623 * Returns: * 624 * - SOC_E_NONE on success * 625 * - SOC_E_PARAM on invalid parameter * 626 * - SOC_E_INTERNAL on init/soc errors * 627 */ 628 STATIC int 629 _soc_mv2_port_asf_speed_limits_get( 630 int unit, 631 soc_port_t port, 632 int port_speed, 633 soc_mv2_asf_mode_e mode, 634 IN_OUT uint8* const min_sp, 635 IN_OUT uint8* const max_sp) 636 { 637 uint32 rval; 638 int speed_encoding; 639 640 _SOC_MV2_ASF_PORT_VALIDATE(unit, port); 641 if (!min_sp || !max_sp) { 642 return SOC_E_PARAM; 643 } 644 645 if ((_SOC_MV2_ASF_RETRV == *min_sp) && 646 (_SOC_MV2_ASF_RETRV == *max_sp)) { 647 *min_sp = *max_sp = 0; 648 if (!_soc_mv2_asf_ctrl[unit]->init) { 649 return SOC_E_INTERNAL; 650 } 651 652 SOC_IF_ERROR_RETURN(READ_ASF_EPORT_CFGr(unit, port, &rval)); 653 654 /* MIN_SRC_PORT_SPEED */ 655 *min_sp = soc_reg_field_get(unit, ASF_EPORT_CFGr, rval, 656 MIN_SRC_PORT_SPEEDf); 657 /* MAX_SRC_PORT_SPEED */ 658 *max_sp = soc_reg_field_get(unit, ASF_EPORT_CFGr, rval, 659 MAX_SRC_PORT_SPEEDf); 660 } else if ((_SOC_MV2_ASF_QUERY == *min_sp) && 661 (_SOC_MV2_ASF_QUERY == *max_sp)) { 662 *min_sp = *max_sp = 0; 663 speed_encoding = _soc_mv2_speed_to_ct_class_map(port_speed); 664 _SOC_MV2_ASF_SPEED_CLASS_VALIDATE(speed_encoding, 0); 665 666 switch(mode) { 667 case _SOC_MV2_ASF_MODE_SAF: 668 return SOC_E_NONE; 669 670 case _SOC_MV2_ASF_MODE_SAME_SPEED: 671 *min_sp = *max_sp = speed_encoding; 672 break; 673 674 case _SOC_MV2_ASF_MODE_SLOW_TO_FAST: 675 *min_sp = _soc_mv2_asf_cfg_tbl[speed_encoding].min_sp; 676 *max_sp = speed_encoding; 677 break; 678 679 case _SOC_MV2_ASF_MODE_FAST_TO_SLOW: 680 if (_SOC_MV2_ASF_MEM_PROFILE_SIMILAR == 681 _soc_mv2_asf_ctrl[unit]->asf_mem_profile) { 682 if (speed_encoding % 2) { /* IEEE */ 683 /* HG counterpart */ 684 *max_sp = speed_encoding + 1; 685 } else { /* HG */ 686 *max_sp = speed_encoding; 687 } 688 } else if (_SOC_MV2_ASF_MEM_PROFILE_EXTREME == 689 _soc_mv2_asf_ctrl[unit]->asf_mem_profile) { 690 *max_sp = _soc_mv2_asf_cfg_tbl[speed_encoding].max_sp; 691 } 692 *min_sp = speed_encoding; 693 break; 694 695 default: 696 return SOC_E_PARAM; 697 } 698 } 699 700 return SOC_E_NONE; 701 } 702 703 /****************************************************************************** 704 * Name: _soc_mv2_asf_obm_ca_fifo_thresh_set * 705 * Description: * 706 * Configure Cell Assembly CT FIFO threshold for all OBM and Pipe * 707 * instances. * 708 * IN params: * 709 * - Unit * 710 * - Logical Port * 711 * - Cell Assembly CT Threshold * 712 * Returns: * 713 * - SOC_E_NONE on success * 714 * - SOC_E_* on internal errors * 715 */ 716 STATIC int 717 _soc_mv2_asf_obm_ca_fifo_thresh_set( 718 int unit, 719 soc_port_t port, 720 uint8 ca_thresh) 721 { 722 int obm, pipe, clport; 723 int port_block_base, phy_port, lane; 724 uint32 rval; 725 soc_info_t *si = &SOC_INFO(unit); 726 uint32 thresh_field[4] = { THRESHOLD0f, THRESHOLD1f, 727 THRESHOLD2f, THRESHOLD3f }; 728 uint32 port_ct_sel_field[4] = { PORT0_CT_SELf, PORT1_CT_SELf, 729 PORT2_CT_SELf, PORT3_CT_SELf }; 730 uint32 idb_obm_ca_ct_ctrl_reg[][1] = { 731 {IDB_OBM0_CA_CT_CONTROL_PIPE0r}, 732 {IDB_OBM1_CA_CT_CONTROL_PIPE0r}, 733 {IDB_OBM2_CA_CT_CONTROL_PIPE0r}, 734 {IDB_OBM3_CA_CT_CONTROL_PIPE0r}, 735 {IDB_OBM4_CA_CT_CONTROL_PIPE0r}, 736 {IDB_OBM5_CA_CT_CONTROL_PIPE0r}, 737 {IDB_OBM6_CA_CT_CONTROL_PIPE0r}, 738 {IDB_OBM7_CA_CT_CONTROL_PIPE0r}, 739 {IDB_OBM8_CA_CT_CONTROL_PIPE0r}, 740 {IDB_OBM9_CA_CT_CONTROL_PIPE0r}, 741 {IDB_OBM10_CA_CT_CONTROL_PIPE0r}, 742 {IDB_OBM11_CA_CT_CONTROL_PIPE0r}, 743 {IDB_OBM12_CA_CT_CONTROL_PIPE0r}, 744 {IDB_OBM13_CA_CT_CONTROL_PIPE0r}, 745 {IDB_OBM14_CA_CT_CONTROL_PIPE0r}, 746 {IDB_OBM15_CA_CT_CONTROL_PIPE0r}, 747 {IDB_OBM16_CA_CT_CONTROL_PIPE0r}, 748 {IDB_OBM17_CA_CT_CONTROL_PIPE0r}, 749 {IDB_OBM18_CA_CT_CONTROL_PIPE0r}, 750 {IDB_OBM19_CA_CT_CONTROL_PIPE0r}, 751 }; 752 753 /* Get lane, pipe & obm */ 754 phy_port = si->port_l2p_mapping[port]; 755 port_block_base = PORT_BLOCK_BASE_PORT(port); 756 lane = phy_port - port_block_base; 757 pipe = si->port_pipe[port]; 758 clport = si->port_serdes[port]; 759 obm = clport; 760 761 SOC_IF_ERROR_RETURN( 762 soc_reg32_get(unit, idb_obm_ca_ct_ctrl_reg[obm][pipe], 763 REG_PORT_ANY, 0, &rval)); 764 765 soc_reg_field_set(unit, idb_obm_ca_ct_ctrl_reg[obm][pipe], &rval, 766 port_ct_sel_field[lane], lane); 767 soc_reg_field_set(unit, idb_obm_ca_ct_ctrl_reg[obm][pipe], &rval, 768 thresh_field[lane], ca_thresh); 769 770 SOC_IF_ERROR_RETURN( 771 soc_reg32_set(unit, idb_obm_ca_ct_ctrl_reg[obm][pipe], 772 REG_PORT_ANY, 0, rval)); 773 774 return SOC_E_NONE; 775 } 776 777 /****************************************************************************** 778 * Name: _soc_mv2_asf_obm_bubble_mop_set * 779 * Description: * 780 * Configure Bubble MOP for all OBM and Pipe Instances * 781 * IN params: * 782 * - Unit * 783 * - Logical Port * 784 * - Bubble MOP Flag * 785 * Returns: * 786 * - SOC_E_NONE on success * 787 * - SOC_E_* on internal errors * 788 */ 789 STATIC int 790 _soc_mv2_asf_obm_bubble_mop_set( 791 int unit, 792 soc_port_t port, 793 uint8 bubble_mop_disable) 794 { 795 int obm, pipe, clport; 796 int port_block_base, phy_port, lane; 797 uint32 rval; 798 soc_info_t *si = &SOC_INFO(unit); 799 uint32 port_field[4] = { 800 PORT0_BUBBLE_MOP_DISABLEf, PORT1_BUBBLE_MOP_DISABLEf, 801 PORT2_BUBBLE_MOP_DISABLEf, PORT3_BUBBLE_MOP_DISABLEf }; 802 uint32 idb_obm_ctrl_reg[][2] = { 803 {IDB_OBM0_CONTROL_PIPE0r}, 804 {IDB_OBM1_CONTROL_PIPE0r}, 805 {IDB_OBM2_CONTROL_PIPE0r}, 806 {IDB_OBM3_CONTROL_PIPE0r}, 807 {IDB_OBM4_CONTROL_PIPE0r}, 808 {IDB_OBM5_CONTROL_PIPE0r}, 809 {IDB_OBM6_CONTROL_PIPE0r}, 810 {IDB_OBM7_CONTROL_PIPE0r}, 811 {IDB_OBM8_CONTROL_PIPE0r}, 812 {IDB_OBM9_CONTROL_PIPE0r}, 813 {IDB_OBM10_CONTROL_PIPE0r}, 814 {IDB_OBM11_CONTROL_PIPE0r}, 815 {IDB_OBM12_CONTROL_PIPE0r}, 816 {IDB_OBM13_CONTROL_PIPE0r}, 817 {IDB_OBM14_CONTROL_PIPE0r}, 818 {IDB_OBM15_CONTROL_PIPE0r}, 819 {IDB_OBM16_CONTROL_PIPE0r}, 820 {IDB_OBM17_CONTROL_PIPE0r}, 821 {IDB_OBM18_CONTROL_PIPE0r}, 822 {IDB_OBM19_CONTROL_PIPE0r}, 823 }; 824 825 /* Get lane, pipe & obm */ 826 phy_port = si->port_l2p_mapping[port]; 827 port_block_base = PORT_BLOCK_BASE_PORT(port); 828 lane = phy_port - port_block_base; 829 pipe = si->port_pipe[port]; 830 clport = si->port_serdes[port]; 831 obm = clport; 832 833 /* BubbleMOP */ 834 SOC_IF_ERROR_RETURN( 835 soc_reg32_get(unit, idb_obm_ctrl_reg[obm][pipe], 836 REG_PORT_ANY, 0, &rval)); 837 838 soc_reg_field_set(unit, idb_obm_ctrl_reg[obm][pipe], &rval, 839 port_field[lane], bubble_mop_disable); 840 841 SOC_IF_ERROR_RETURN( 842 soc_reg32_set(unit, idb_obm_ctrl_reg[obm][pipe], REG_PORT_ANY, 843 0, rval)); 844 845 return SOC_E_NONE; 846 } 847 848 int 849 soc_mv2_port_asf_valid( 850 int unit, 851 soc_port_t port) 852 { 853 if (IS_CPU_PORT(((unit)), (port)) || IS_LB_PORT(((unit)), (port)) || \ 854 SOC_PBMP_MEMBER(PBMP_MANAGEMENT(unit), (port))) { 855 return FALSE; 856 } else { 857 return TRUE; 858 } 859 } 860 861 /************************************* 862 * Init Start Routine * 863 * - Allocates ASF Ctrl structure * 864 * for the given unit * 865 */ 866 int 867 soc_mv2_asf_init_start(int unit) 868 { 869 if (!(_soc_mv2_asf_ctrl[unit] = 870 sal_alloc(sizeof(_soc_mv2_asf_ctrl_t), "MV2 ASF Ctrl Area"))) { 871 return SOC_E_MEMORY; 872 } 873 sal_memset(_soc_mv2_asf_ctrl[unit], 0, sizeof(_soc_mv2_asf_ctrl_t)); 874 875 /* ASF_MEM_PROFILE */ 876 _soc_mv2_asf_ctrl[unit]->asf_mem_profile = 877 soc_property_get(unit, spn_ASF_MEM_PROFILE, 878 _SOC_MV2_ASF_MEM_PROFILE_SIMILAR); 879 if (!((_soc_mv2_asf_ctrl[unit]->asf_mem_profile >= 0) && 880 (_soc_mv2_asf_ctrl[unit]->asf_mem_profile < 3))) { 881 _soc_mv2_asf_ctrl[unit]->asf_mem_profile = 2; 882 } 883 884 return SOC_E_NONE; 885 } 886 887 /************************ 888 * Init Complete Marker * 889 */ 890 int 891 soc_mv2_asf_init_done(int unit) 892 { 893 if (_soc_mv2_asf_ctrl[unit]) { 894 _soc_mv2_asf_ctrl[unit]->init = 1; 895 LOG_CLI((BSL_META_U(unit, "*** unit %d: ports %s\n"), unit, 896 asf_profile_str[_soc_mv2_asf_ctrl[unit]->asf_mem_profile])); 897 return SOC_E_NONE; 898 } else { 899 return SOC_E_INTERNAL; 900 } 901 } 902 903 /****************************************************************************** 904 * Name: soc_mv2_port_asf_init * 905 * Description: * 906 * Initialize ASF primitives for the specified port * 907 * IN params: * 908 * - Unit * 909 * - Logical Port * 910 * - Port Speed * 911 * - ASF Mode * 912 * Returns: * 913 * - SOC_E_NONE on success * 914 * - SOC_E_PARAM on invalid parameter * 915 * - SOC_E_INIT on init/soc errors * 916 */ 917 int 918 soc_mv2_port_asf_init( 919 int unit, 920 soc_port_t port, 921 int speed, 922 soc_mv2_asf_mode_e mode) 923 { 924 SOC_IF_ERROR_RETURN(soc_mv2_port_asf_mode_set(unit, port, speed, mode)); 925 926 return SOC_E_NONE; 927 } 928 929 /************************ 930 * Init Start Routine * 931 */ 932 int 933 soc_mv2_asf_deinit(int unit) 934 { 935 if (_soc_mv2_asf_ctrl[unit]) { 936 sal_free(_soc_mv2_asf_ctrl[unit]); 937 _soc_mv2_asf_ctrl[unit] = NULL; 938 } 939 940 return SOC_E_NONE; 941 } 942 943 /****************************************************************************** 944 * Name: _soc_mv2_port_asf_xmit_start_count_set * 945 * Description: * 946 * Initialize XMIT START COUNT memory for all the source class for the * 947 * specified port * 948 * Support CPU and LB ports for init setting. * 949 * IN params: * 950 * - Unit * 951 * - Logical Port * 952 * - Port Speed * 953 * - ASF Mode * 954 * - Extra cells (if any, to be added to xmit start count) * 955 * Returns: * 956 * - SOC_E_NONE on success * 957 * - SOC_E_PARAM on invalid parameter * 958 */ 959 int 960 soc_mv2_port_asf_xmit_start_count_set( 961 int unit, 962 soc_port_t port, 963 int port_speed, 964 soc_mv2_asf_mode_e mode, 965 uint8 extra_cells) 966 { 967 egr_xmit_start_count_entry_t entry; 968 soc_info_t *si = &SOC_INFO(unit); 969 uint8 xmit_cnt = 0; 970 int rv, src_class, dst_class = 0, port_idx; 971 int pipe; 972 soc_mem_t config_mem = INVALIDm; 973 974 if (!((mode >= _SOC_MV2_ASF_MODE_SAF) && 975 (mode <= _SOC_MV2_ASF_MODE_CFG_UPDATE))) { 976 return SOC_E_PARAM; 977 } 978 979 if (IS_CPU_PORT(unit, port)) { 980 port_speed = 20000; 981 } 982 if (IS_LB_PORT(unit, port)) { 983 port_speed = 100000; 984 } 985 986 if (_SOC_MV2_ASF_MODE_CFG_UPDATE != mode) { 987 if (SOC_E_PARAM == (dst_class = _soc_mv2_speed_to_ct_class_map(port_speed))) { 988 /* port on a speed unsupported by CT - will resort to SAF */ 989 dst_class = 0; 990 } 991 } 992 993 sal_memset(&entry, 0, sizeof(egr_xmit_start_count_entry_t)); 994 995 pipe = si->port_pipe[port]; 996 config_mem = SOC_MEM_UNIQUE_ACC(unit, EGR_XMIT_START_COUNTm)[pipe]; 997 998 for (src_class = 0; src_class < _SOC_MV2_ASF_CLASS_CNT; src_class++) { 999 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) { 1000 xmit_cnt = _soc_mv2_asf_cfg_tbl[dst_class].edb_prebuffer.line_rate.saf; 1001 } else { 1002 if (_SOC_MV2_ASF_MODE_CFG_UPDATE == mode) { 1003 xmit_cnt = _SOC_MV2_ASF_RETRV; 1004 } else { 1005 xmit_cnt = _SOC_MV2_ASF_QUERY; 1006 } 1007 1008 rv = _soc_mv2_port_asf_xmit_start_count_get(unit, port, src_class, 1009 dst_class, mode, &xmit_cnt); 1010 1011 if (SOC_FAILURE(rv)) { 1012 if (SOC_E_UNAVAIL == rv) { 1013 xmit_cnt = _soc_mv2_asf_cfg_tbl[dst_class].edb_prebuffer.oversub_2_1.saf; 1014 } else { 1015 return rv; 1016 } 1017 } 1018 1019 xmit_cnt += extra_cells; 1020 } 1021 1022 port_idx = ((port % _MV2_TDM_DEV_PORTS_PER_PIPE) * 16) + src_class; 1023 1024 soc_mem_field32_set(unit, config_mem, &entry, 1025 THRESHOLDf, xmit_cnt); 1026 SOC_IF_ERROR_RETURN(soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, 1027 port_idx, &entry)); 1028 } 1029 1030 return SOC_E_NONE; 1031 } 1032 1033 /****************************************************************************** 1034 * Name: soc_mv2_port_asf_mode_get * 1035 * Description: * 1036 * Retrieve the ASF/SAF mode configured on the specified port * 1037 * IN params: * 1038 * - Unit * 1039 * - Logical Port * 1040 * - Port Speed * 1041 * OUT params: * 1042 * - mode : OUT: contains the ASF/SAF mode confiugred on the specified * 1043 * port on success * 1044 * Returns: * 1045 * - SOC_E_NONE on success * 1046 * - SOC_E_PARAM on invalid parameter * 1047 * - SOC_E_INTERNAL on init/soc errors * 1048 */ 1049 int 1050 soc_mv2_port_asf_mode_get( 1051 int unit, 1052 soc_port_t port, 1053 int port_speed, 1054 OUT soc_mv2_asf_mode_e* const mode) 1055 { 1056 uint32 rval; 1057 int speed_encoding; 1058 uint8 max_sp, min_sp, enable; 1059 1060 if (!mode) { 1061 return SOC_E_INTERNAL; 1062 } 1063 1064 if (soc_mv2_port_asf_valid(unit, port)) { 1065 SOC_IF_ERROR_RETURN(READ_ASF_EPORT_CFGr(unit, port, &rval)); 1066 enable = soc_reg_field_get(unit, ASF_EPORT_CFGr, rval, ENABLEf); 1067 if (!enable) { 1068 *mode = _SOC_MV2_ASF_MODE_SAF; 1069 return SOC_E_NONE; 1070 } 1071 } else { 1072 *mode = _SOC_MV2_ASF_MODE_SAF; 1073 return SOC_E_NONE; 1074 } 1075 1076 if (!_soc_mv2_asf_ctrl[unit] || !_soc_mv2_asf_ctrl[unit]->init) { 1077 return SOC_E_INTERNAL; 1078 } 1079 1080 max_sp = soc_reg_field_get(unit, ASF_EPORT_CFGr, rval, MAX_SRC_PORT_SPEEDf); 1081 min_sp = soc_reg_field_get(unit, ASF_EPORT_CFGr, rval, MIN_SRC_PORT_SPEEDf); 1082 1083 speed_encoding = _soc_mv2_speed_to_ct_class_map(port_speed); 1084 _SOC_MV2_ASF_SPEED_CLASS_VALIDATE(speed_encoding, 1); 1085 1086 if (max_sp && min_sp) { 1087 if (max_sp == min_sp) { 1088 if (SOC_PBMP_MEMBER(_soc_mv2_asf_ctrl[unit]->asf_sf, port)) { 1089 *mode = _SOC_MV2_ASF_MODE_SLOW_TO_FAST; 1090 } else if (SOC_PBMP_MEMBER(_soc_mv2_asf_ctrl[unit]->asf_fs, port)) { 1091 *mode = _SOC_MV2_ASF_MODE_FAST_TO_SLOW; 1092 } else { 1093 *mode = _SOC_MV2_ASF_MODE_SAME_SPEED; 1094 } 1095 } else if (max_sp == speed_encoding) { 1096 *mode = _SOC_MV2_ASF_MODE_SLOW_TO_FAST; 1097 } else if (min_sp == speed_encoding) { 1098 *mode = _SOC_MV2_ASF_MODE_FAST_TO_SLOW; 1099 } else { 1100 *mode = _SOC_MV2_ASF_MODE_UNSUPPORTED; 1101 return SOC_E_UNAVAIL; 1102 } 1103 } else { 1104 *mode = _SOC_MV2_ASF_MODE_UNSUPPORTED; 1105 return SOC_E_UNAVAIL; 1106 } 1107 1108 return SOC_E_NONE; 1109 } 1110 1111 /****************************************************************************** 1112 * Name: soc_mv2_port_asf_mode_set * 1113 * Description: * 1114 * Configure specified ASF/SAF modes on the specified port * 1115 * IN params: * 1116 * - Unit * 1117 * - Logical Port * 1118 * - Port Speed * 1119 * - ASF Mode * 1120 * OUT params: * 1121 * - None * 1122 * Returns: * 1123 * - SOC_E_NONE on success * 1124 * - SOC_E_PARAM on invalid parameter * 1125 * - SOC_E_INTERNAL on init/soc errors * 1126 */ 1127 int 1128 soc_mv2_port_asf_mode_set( 1129 int unit, 1130 soc_port_t port, 1131 int port_speed, 1132 soc_mv2_asf_mode_e mode) 1133 { 1134 int ret, speed_encoding = 0; 1135 uint8 min_sp = 0, max_sp = 0; 1136 uint8 fifo_threshold = 0, fifo_depth = 0, mmu_prebuf = 0; 1137 uint8 oversub = 0, ca_thresh = 0; 1138 uint8 bubble_mop_disable = 0; 1139 uint32 rval; 1140 soc_info_t *si = NULL; 1141 int init = 0; 1142 1143 if (_SOC_MV2_ASF_MODE_INIT == mode) { 1144 init = 1; 1145 mode = _SOC_MV2_ASF_MODE_SAF; 1146 } 1147 if ((!init) && (!_soc_mv2_asf_ctrl[unit] || 1148 !_soc_mv2_asf_ctrl[unit]->init || !(si = &SOC_INFO(unit)))) { 1149 return SOC_E_INTERNAL; 1150 } 1151 if (!_soc_mv2_asf_ctrl[unit]->asf_mem_profile) { /* no cut-thru profile */ 1152 if ((_SOC_MV2_ASF_MODE_SAF != mode) && 1153 (_SOC_MV2_ASF_MODE_CFG_UPDATE != mode)) { 1154 return SOC_E_UNAVAIL; 1155 } 1156 } 1157 if (!soc_mv2_port_asf_valid(unit, port)) { 1158 if ((_SOC_MV2_ASF_MODE_SAF != mode) && 1159 (_SOC_MV2_ASF_MODE_CFG_UPDATE != mode)) { 1160 return SOC_E_UNAVAIL; 1161 } 1162 SOC_IF_ERROR_RETURN( 1163 soc_mv2_port_asf_xmit_start_count_set(unit, port, port_speed, 1164 mode, 0)); 1165 return SOC_E_NONE; 1166 } 1167 1168 speed_encoding = _soc_mv2_speed_to_ct_class_map(port_speed); 1169 _SOC_MV2_ASF_SPEED_CLASS_VALIDATE(speed_encoding, 0); 1170 1171 /* min. and max. src port speeds */ 1172 if (_SOC_MV2_ASF_MODE_CFG_UPDATE != mode) { 1173 min_sp = max_sp = _SOC_MV2_ASF_QUERY; 1174 SOC_IF_ERROR_RETURN( 1175 _soc_mv2_port_asf_speed_limits_get(unit, port, port_speed, mode, 1176 &min_sp, &max_sp)); 1177 } 1178 1179 /* mode specific configurations */ 1180 switch(mode) { 1181 case _SOC_MV2_ASF_MODE_SAF: 1182 break; 1183 1184 case _SOC_MV2_ASF_MODE_SAME_SPEED: 1185 /* Cannot set cut-through mode for 1G ports */ 1186 if (1000 == port_speed) { 1187 return SOC_E_UNAVAIL; 1188 } 1189 /* verify mode specific conformance */ 1190 if (min_sp != max_sp) { 1191 return SOC_E_PARAM; 1192 } 1193 break; 1194 1195 case _SOC_MV2_ASF_MODE_SLOW_TO_FAST: 1196 /* Cannot set cut-through mode for 1G ports */ 1197 if (1000 == port_speed) { 1198 return SOC_E_UNAVAIL; 1199 } 1200 /* verify mode specific conformance */ 1201 if ( !((min_sp >= 1202 _soc_mv2_asf_cfg_tbl[speed_encoding].min_sp) && 1203 (max_sp == speed_encoding)) ) { 1204 return SOC_E_PARAM; 1205 } 1206 break; 1207 1208 case _SOC_MV2_ASF_MODE_FAST_TO_SLOW: 1209 /* Cannot set cut-through mode for 1G ports */ 1210 if (1000 == port_speed) { 1211 return SOC_E_UNAVAIL; 1212 } 1213 /* verify mode specific conformance */ 1214 if ( !((max_sp <= 1215 _soc_mv2_asf_cfg_tbl[speed_encoding].max_sp) && 1216 (min_sp == speed_encoding)) ) { 1217 return SOC_E_PARAM; 1218 } 1219 break; 1220 1221 case _SOC_MV2_ASF_MODE_CFG_UPDATE: 1222 mode = _SOC_MV2_ASF_MODE_SAF; 1223 1224 /* disable CT first */ 1225 SOC_IF_ERROR_RETURN(READ_ASF_EPORT_CFGr(unit, port, &rval)); 1226 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, 1227 FIFO_THRESHOLDf, 0); 1228 SOC_IF_ERROR_RETURN(WRITE_ASF_EPORT_CFGr(unit, port, rval)); 1229 sal_usleep(1); 1230 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, ENABLEf, 0); 1231 SOC_IF_ERROR_RETURN(WRITE_ASF_EPORT_CFGr(unit, port, rval)); 1232 1233 /* update new settings & re-enable */ 1234 ret = soc_mv2_port_asf_mode_set(unit, port, port_speed, mode); 1235 return ret; 1236 1237 default: 1238 return SOC_E_PARAM; 1239 } 1240 1241 /* ASF_IPORT_CFG */ 1242 SOC_IF_ERROR_RETURN(READ_ASF_IPORT_CFGr(unit, port, &rval)); 1243 soc_reg_field_set(unit, ASF_IPORT_CFGr, &rval, ASF_PORT_SPEEDf, 1244 port_speed == 1000? 0: speed_encoding); 1245 SOC_IF_ERROR_RETURN(WRITE_ASF_IPORT_CFGr(unit, port, rval)); 1246 1247 /* init CT class */ 1248 SOC_IF_ERROR_RETURN(_soc_mv2_port_asf_class_init(unit, port, speed_encoding)); 1249 1250 if (_SOC_MV2_ASF_MODE_SAF != mode) { 1251 /* Oversub */ 1252 oversub = (SOC_PBMP_MEMBER(si->oversub_pbm, port) ? 1 : 0); 1253 1254 /* FIFO threshold */ 1255 fifo_threshold = _SOC_MV2_ASF_QUERY; 1256 SOC_IF_ERROR_RETURN( 1257 _soc_mv2_port_asf_fifo_threshold_get(unit, port, port_speed, mode, 1258 &fifo_threshold)); 1259 1260 /* FIFO depth */ 1261 fifo_depth = _SOC_MV2_ASF_QUERY; 1262 SOC_IF_ERROR_RETURN( 1263 _soc_mv2_port_asf_fifo_depth_get(unit, port, port_speed, mode, 1264 &fifo_depth)); 1265 1266 /* MMU Prebuffer */ 1267 mmu_prebuf = _SOC_MV2_ASF_QUERY; 1268 SOC_IF_ERROR_RETURN( 1269 _soc_mv2_port_asf_mmu_prebuf_get(unit, port, port_speed, 1270 &mmu_prebuf)); 1271 1272 /* BubbleMOP */ 1273 bubble_mop_disable = oversub ? 1274 !(_soc_mv2_asf_cfg_tbl[speed_encoding].mop_enable.oversub) : 1275 !(_soc_mv2_asf_cfg_tbl[speed_encoding].mop_enable.line_rate); 1276 1277 ca_thresh = 4; 1278 1279 SOC_IF_ERROR_RETURN( 1280 soc_mv2_port_asf_params_set(unit, port, port_speed, mode, 1281 bubble_mop_disable, ca_thresh, 1282 speed_encoding)); 1283 1284 /* drain the port CT FIFO */ 1285 SOC_IF_ERROR_RETURN(READ_ASF_EPORT_CFGr(unit, port, &rval)); 1286 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, ENABLEf, 1); 1287 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, FIFO_THRESHOLDf, 0); 1288 SOC_IF_ERROR_RETURN(WRITE_ASF_EPORT_CFGr(unit, port, rval)); 1289 1290 sal_usleep(1); 1291 1292 /* enable cut-through */ 1293 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, OVERSUBf, oversub); 1294 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, 1295 MAX_SRC_PORT_SPEEDf, max_sp); 1296 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, 1297 MIN_SRC_PORT_SPEEDf, min_sp); 1298 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, 1299 MIN_SRC_PORT_XMIT_CNTf, mmu_prebuf); 1300 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, 1301 FIFO_THRESHOLDf, fifo_threshold); 1302 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, FIFO_DEPTHf, 1303 fifo_depth); 1304 SOC_IF_ERROR_RETURN(WRITE_ASF_EPORT_CFGr(unit, port, rval)); 1305 1306 /* bookkeeping */ 1307 if (SOC_PBMP_MEMBER(_soc_mv2_asf_ctrl[unit]->asf_ss, port)) { 1308 SOC_PBMP_PORT_REMOVE(_soc_mv2_asf_ctrl[unit]->asf_ss, port); 1309 } else if (SOC_PBMP_MEMBER(_soc_mv2_asf_ctrl[unit]->asf_sf, port)) { 1310 SOC_PBMP_PORT_REMOVE(_soc_mv2_asf_ctrl[unit]->asf_sf, port); 1311 } else if (SOC_PBMP_MEMBER(_soc_mv2_asf_ctrl[unit]->asf_fs, port)) { 1312 SOC_PBMP_PORT_REMOVE(_soc_mv2_asf_ctrl[unit]->asf_fs, port); 1313 } 1314 SOC_PBMP_PORT_ADD(_soc_mv2_asf_ctrl[unit]->asf_ports, port); 1315 if (_SOC_MV2_ASF_MODE_SAME_SPEED == mode) { 1316 SOC_PBMP_PORT_ADD(_soc_mv2_asf_ctrl[unit]->asf_ss, port); 1317 } else if (_SOC_MV2_ASF_MODE_SLOW_TO_FAST== mode) { 1318 SOC_PBMP_PORT_ADD(_soc_mv2_asf_ctrl[unit]->asf_sf, port); 1319 } else if (_SOC_MV2_ASF_MODE_FAST_TO_SLOW== mode) { 1320 SOC_PBMP_PORT_ADD(_soc_mv2_asf_ctrl[unit]->asf_fs, port); 1321 } 1322 } else { /* Store and Forward */ 1323 fifo_depth = 0x40; 1324 fifo_threshold = 0x20; 1325 mmu_prebuf = 0; 1326 min_sp = 0; 1327 max_sp = 0; 1328 oversub = 0; 1329 ca_thresh = 4; 1330 bubble_mop_disable = 0; 1331 1332 SOC_IF_ERROR_RETURN( 1333 soc_mv2_port_asf_params_set(unit, port, port_speed, mode, 1334 bubble_mop_disable, ca_thresh, 1335 speed_encoding)); 1336 1337 /* ASF_EPORT_CFG */ 1338 SOC_IF_ERROR_RETURN(READ_ASF_EPORT_CFGr(unit, port, &rval)); 1339 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, FIFO_THRESHOLDf, 0); 1340 SOC_IF_ERROR_RETURN(WRITE_ASF_EPORT_CFGr(unit, port, rval)); 1341 1342 sal_usleep(1); 1343 1344 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, ENABLEf, 0); 1345 SOC_IF_ERROR_RETURN(WRITE_ASF_EPORT_CFGr(unit, port, rval)); 1346 1347 /* update SAF configs */ 1348 SOC_IF_ERROR_RETURN(READ_ASF_EPORT_CFGr(unit, port, &rval)); 1349 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, OVERSUBf, oversub); 1350 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, 1351 MAX_SRC_PORT_SPEEDf, max_sp); 1352 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, 1353 MIN_SRC_PORT_SPEEDf, min_sp); 1354 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, 1355 MIN_SRC_PORT_XMIT_CNTf, mmu_prebuf); 1356 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, 1357 FIFO_THRESHOLDf, fifo_threshold); 1358 soc_reg_field_set(unit, ASF_EPORT_CFGr, &rval, FIFO_DEPTHf, 1359 fifo_depth); 1360 SOC_IF_ERROR_RETURN(WRITE_ASF_EPORT_CFGr(unit, port, rval)); 1361 1362 /* bookkeeping */ 1363 SOC_PBMP_PORT_REMOVE(_soc_mv2_asf_ctrl[unit]->asf_ports, port); 1364 if (SOC_PBMP_MEMBER(_soc_mv2_asf_ctrl[unit]->asf_ss, port)) { 1365 SOC_PBMP_PORT_REMOVE(_soc_mv2_asf_ctrl[unit]->asf_ss, port); 1366 } else if (SOC_PBMP_MEMBER(_soc_mv2_asf_ctrl[unit]->asf_sf, port)) { 1367 SOC_PBMP_PORT_REMOVE(_soc_mv2_asf_ctrl[unit]->asf_sf, port); 1368 } else if (SOC_PBMP_MEMBER(_soc_mv2_asf_ctrl[unit]->asf_fs, port)) { 1369 SOC_PBMP_PORT_REMOVE(_soc_mv2_asf_ctrl[unit]->asf_fs, port); 1370 } 1371 } 1372 1373 return SOC_E_NONE; 1374 } 1375 1376 /****************************************************************************** 1377 * Name: soc_mv2_port_asf_params_set * 1378 * Description: * 1379 * Configure ASF/SAF mode params on the specified port * 1380 * IN params: * 1381 * - Unit * 1382 * - Logical Port * 1383 * - Port Speed * 1384 * - ASF Mode * 1385 * - Bubble MOP disable flag * 1386 * - CA Threshold * 1387 * - Speed Encoding * 1388 * OUT params: * 1389 * - None * 1390 * Returns: * 1391 * - SOC_E_NONE on success * 1392 * - SOC_E_PARAM on invalid parameter * 1393 * - SOC_E_INTERNAL on init/soc errors * 1394 */ 1395 int 1396 soc_mv2_port_asf_params_set( 1397 int unit, 1398 soc_port_t port, 1399 int port_speed, 1400 soc_mv2_asf_mode_e mode, 1401 uint8 bubble_mop_disable, 1402 uint8 ca_thresh, 1403 int speed_encoding) 1404 { 1405 uint32 mmu_ep_credits_hi = 0, mmu_ep_credits_lo = 0; 1406 uint32 egr_mmu_cell_credits = 0; 1407 uint32 rval; 1408 int ovs_ratio = 0; 1409 soc_info_t *si = NULL; 1410 egr_mmu_cell_credit_entry_t credit_entry; 1411 1412 if (!(si = &SOC_INFO(unit))) { 1413 return SOC_E_INTERNAL; 1414 } 1415 1416 /* EDB Prebuffer */ 1417 SOC_IF_ERROR_RETURN( 1418 soc_mv2_port_asf_xmit_start_count_set(unit, port, port_speed, 1419 mode, 0)); 1420 /* OBM Cell Assembly FIFO threshold */ 1421 SOC_IF_ERROR_RETURN( 1422 _soc_mv2_asf_obm_ca_fifo_thresh_set(unit, port, ca_thresh)); 1423 1424 /* BubbleMOP */ 1425 SOC_IF_ERROR_RETURN( 1426 _soc_mv2_asf_obm_bubble_mop_set(unit, port, bubble_mop_disable)); 1427 1428 /* MMU EP Credit Threshold */ 1429 SOC_IF_ERROR_RETURN( 1430 soc_td3_port_oversub_ratio_get(unit, port, &ovs_ratio)); 1431 if ((CCLK_FREQ_1525MHZ == si->frequency) && (ovs_ratio < 1620)) { 1432 mmu_ep_credits_lo = 1433 _soc_mv2_asf_cfg_tbl[speed_encoding].mmu_credit_threshold.lr_os_161.lo; 1434 mmu_ep_credits_hi = 1435 _soc_mv2_asf_cfg_tbl[speed_encoding].mmu_credit_threshold.lr_os_161.hi; 1436 } else { 1437 mmu_ep_credits_lo = 1438 _soc_mv2_asf_cfg_tbl[speed_encoding].mmu_credit_threshold.os_2_1.lo; 1439 mmu_ep_credits_hi = 1440 _soc_mv2_asf_cfg_tbl[speed_encoding].mmu_credit_threshold.os_2_1.hi; 1441 } 1442 1443 /* ASF_CREDIT_THRESH_LO */ 1444 SOC_IF_ERROR_RETURN(READ_ASF_CREDIT_THRESH_LOr(unit, port, &rval)); 1445 soc_reg_field_set(unit, ASF_CREDIT_THRESH_LOr, &rval, THRESHf, 1446 mmu_ep_credits_lo); 1447 SOC_IF_ERROR_RETURN(WRITE_ASF_CREDIT_THRESH_LOr(unit, port, rval)); 1448 1449 /* ASF_CREDIT_THRESH_HI */ 1450 SOC_IF_ERROR_RETURN(READ_ASF_CREDIT_THRESH_HIr(unit, port, &rval)); 1451 soc_reg_field_set(unit, ASF_CREDIT_THRESH_HIr, &rval, THRESHf, 1452 mmu_ep_credits_hi); 1453 SOC_IF_ERROR_RETURN(WRITE_ASF_CREDIT_THRESH_HIr(unit, port, rval)); 1454 1455 /* EP credits outstanding */ 1456 SOC_IF_ERROR_RETURN( 1457 soc_mv2_port_asf_speed_to_mmu_cell_credit(unit, port, port_speed, 1458 &egr_mmu_cell_credits)); 1459 1460 /* EGR_MMU_CELL_CREDIT */ 1461 SOC_IF_ERROR_RETURN(READ_EGR_MMU_CELL_CREDITm(unit, MEM_BLOCK_ANY, 1462 si->port_l2p_mapping[port], &credit_entry)); 1463 soc_EGR_MMU_CELL_CREDITm_field32_set(unit, &credit_entry, CREDITf, 1464 egr_mmu_cell_credits); 1465 SOC_IF_ERROR_RETURN(WRITE_EGR_MMU_CELL_CREDITm(unit, MEM_BLOCK_ALL, 1466 si->port_l2p_mapping[port], &credit_entry)); 1467 1468 return SOC_E_NONE; 1469 } 1470 1471 /****************************************************************************** 1472 * Name: soc_mv2_port_asf_speed_to_mmu_cell_credit * 1473 * Description: * 1474 * Retrieve mmu_cell_credit based on port speed configured. * 1475 * Helper function for misc init. * 1476 * Support CPU and LB ports. * 1477 * IN params: * 1478 * - Unit * 1479 * - Logical Port * 1480 * - Port Speed * 1481 * OUT params: * 1482 * - MMU Cell credit * 1483 * Returns: * 1484 * - SOC_E_XXX on success * 1485 */ 1486 int 1487 soc_mv2_port_asf_speed_to_mmu_cell_credit( 1488 int unit, 1489 soc_port_t port, 1490 int port_speed, 1491 OUT uint32 *mmu_cell_credit) 1492 { 1493 int speed_encoding = 0, ovs_ratio = 0; 1494 soc_info_t *si = NULL; 1495 1496 if (NULL == mmu_cell_credit) { 1497 return SOC_E_PARAM; 1498 } 1499 1500 if (!(si = &SOC_INFO(unit))) { 1501 return SOC_E_INTERNAL; 1502 } 1503 1504 if (IS_CPU_PORT(unit, port)) { 1505 port_speed = 20000; 1506 } 1507 if (IS_LB_PORT(unit, port)) { 1508 port_speed = 100000; 1509 } 1510 1511 speed_encoding = _soc_mv2_speed_to_ct_class_map(port_speed); 1512 _SOC_MV2_ASF_SPEED_CLASS_VALIDATE(speed_encoding, 0); 1513 1514 SOC_IF_ERROR_RETURN( 1515 soc_td3_port_oversub_ratio_get(unit, port, &ovs_ratio)); 1516 1517 if ((CCLK_FREQ_1525MHZ == si->frequency) && (ovs_ratio < 1620)) { 1518 *mmu_cell_credit = 1519 _soc_mv2_asf_cfg_tbl[speed_encoding].ep_credit.pfc_op_cells; 1520 } else { 1521 *mmu_cell_credit = 1522 _soc_mv2_asf_cfg_tbl[speed_encoding].ep_credit.base_cells; 1523 } 1524 1525 1526 return SOC_E_NONE; 1527 } 1528 1529 /****************************************************************************** 1530 * Name: soc_mv2_port_asf_mmu_cell_credit_to_port_speed * 1531 * Description: * 1532 * Retrieve port speed based on mmu_cell_credit configured. * 1533 * Helper function for MAC driver speed get. * 1534 * IN params: * 1535 * - Unit * 1536 * - Logical Port * 1537 * - MMU Cell credit * 1538 * OUT params: * 1539 * - Port speed * 1540 * Returns: * 1541 * - SOC_E_XXX on success * 1542 */ 1543 int 1544 soc_mv2_port_asf_mmu_cell_credit_to_speed( 1545 int unit, 1546 soc_port_t port, 1547 uint8 mmu_cell_credit, 1548 OUT int *port_speed) 1549 { 1550 int i, freq; 1551 uint8 cell_credit; 1552 int speed; 1553 soc_info_t *si = NULL; 1554 1555 if (NULL == port_speed) { 1556 return SOC_E_PARAM; 1557 } 1558 1559 if (!(si = &SOC_INFO(unit))) { 1560 return SOC_E_INTERNAL; 1561 } 1562 1563 /* Special case for 1G ports since 1G ports use same setting as 10G port */ 1564 if (1000 == (speed = si->port_init_speed[port])) { /* Use cached speed instead */ 1565 *port_speed = speed; 1566 return SOC_E_NONE; 1567 } 1568 1569 freq = si->frequency; 1570 for (i = 1; i < (COUNTOF(_soc_mv2_asf_cfg_tbl) - 1); i++) { 1571 int ovs_ratio = 0; 1572 SOC_IF_ERROR_RETURN( 1573 soc_td3_port_oversub_ratio_get(unit, port, &ovs_ratio)); 1574 1575 cell_credit = ((CCLK_FREQ_1525MHZ == freq) && (ovs_ratio < 1620))? 1576 _soc_mv2_asf_cfg_tbl[i].ep_credit.pfc_op_cells : 1577 _soc_mv2_asf_cfg_tbl[i].ep_credit.base_cells; 1578 1579 if (mmu_cell_credit == cell_credit) { 1580 if (IS_HG_PORT(unit, port)) { 1581 *port_speed = _soc_mv2_asf_cfg_tbl[i + 1].speed; 1582 } else { 1583 *port_speed = _soc_mv2_asf_cfg_tbl[i].speed; 1584 } 1585 return SOC_E_NONE; 1586 } 1587 } 1588 1589 return SOC_E_NOT_FOUND; 1590 } 1591 1592 /****************************************************************************** 1593 * Name: soc_mv2_port_asf_pause_bpmp_get * 1594 * Description: * 1595 * Get pointer of pause_restore bitmap for update * 1596 * IN params: * 1597 * - Unit * 1598 * OUT params: * 1599 * * 1600 * Returns: * 1601 * - Pointer of pause_restore bitmap * 1602 */ 1603 pbmp_t * 1604 soc_mv2_port_asf_pause_bpmp_get(int unit) 1605 { 1606 if (_soc_mv2_asf_ctrl[unit] == NULL) { 1607 return NULL; 1608 } 1609 return &_soc_mv2_asf_ctrl[unit]->pause_restore; 1610 } 1611 1612 /************************ 1613 * ASF Warmboot Support * 1614 */ 1615 #ifdef BCM_WARM_BOOT_SUPPORT 1616 /* 1617 * ASF Warmboot is a part of Port module Warmboot. 1618 * Check Port module for scache_ver evolution. 1619 */ 1620 /* 1621 #define BCM_WB_VERSION_1_8 SOC_SCACHE_VERSION(1,8) 1622 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_8 1623 */ 1624 int 1625 soc_mv2_asf_wb_memsz_get( 1626 int unit, 1627 OUT uint32* const mem_sz, 1628 uint16 scache_ver) 1629 { 1630 if (!mem_sz) { 1631 return SOC_E_PARAM; 1632 } 1633 *mem_sz = 0; 1634 1635 if (!SOC_WARM_BOOT(unit)) { 1636 if (!_soc_mv2_asf_ctrl[unit] || !_soc_mv2_asf_ctrl[unit]->asf_mem_profile) { 1637 return SOC_E_UNAVAIL; 1638 } 1639 if (!_soc_mv2_asf_ctrl[unit]->init) { 1640 return SOC_E_INTERNAL; 1641 } 1642 } 1643 1644 *mem_sz = sizeof(_soc_mv2_asf_wb_t); 1645 1646 return SOC_E_NONE; 1647 } 1648 1649 int 1650 soc_mv2_asf_wb_sync( 1651 int unit, 1652 IN_OUT uint8* const wb_data) 1653 { 1654 _soc_mv2_asf_wb_t *wbd; 1655 1656 if (!_soc_mv2_asf_ctrl[unit] || !_soc_mv2_asf_ctrl[unit]->asf_mem_profile) { 1657 return SOC_E_UNAVAIL; 1658 } 1659 if (!_soc_mv2_asf_ctrl[unit]->init) { 1660 return SOC_E_INTERNAL; 1661 } 1662 if (!wb_data) { 1663 return SOC_E_PARAM; 1664 } 1665 1666 wbd = (_soc_mv2_asf_wb_t *) wb_data; 1667 wbd->unit = unit; 1668 sal_memcpy(&wbd->asf_ctrl, _soc_mv2_asf_ctrl[unit], 1669 sizeof(_soc_mv2_asf_ctrl_t)); 1670 1671 return SOC_E_NONE; 1672 } 1673 1674 int 1675 soc_mv2_asf_wb_recover( 1676 int unit, 1677 uint8* const wb_data, 1678 uint16 scache_ver) 1679 { 1680 _soc_mv2_asf_wb_t *wbd; 1681 1682 if (!SOC_WARM_BOOT(unit)) { 1683 return SOC_E_INTERNAL; 1684 } 1685 if (!wb_data) { 1686 return SOC_E_PARAM; 1687 } 1688 1689 wbd = (_soc_mv2_asf_wb_t *) wb_data; 1690 if (wbd->unit == unit) { 1691 if (!(_soc_mv2_asf_ctrl[unit] = 1692 sal_alloc(sizeof(_soc_mv2_asf_ctrl_t), "MV2 ASF Ctrl Area"))) { 1693 return SOC_E_MEMORY; 1694 } 1695 1696 sal_memcpy(_soc_mv2_asf_ctrl[unit], &wbd->asf_ctrl, 1697 sizeof(_soc_mv2_asf_ctrl_t)); 1698 } 1699 1700 LOG_CLI((BSL_META_U(unit, "*** unit %d: MMU-ASF subsystem warmbooted: " 1701 "ports %s\n"), unit, 1702 asf_profile_str[_soc_mv2_asf_ctrl[unit]->asf_mem_profile])); 1703 1704 return SOC_E_NONE; 1705 } 1706 #endif /* BCM_WARM_BOOT_SUPPORT */ 1707 1708 /********************** 1709 * ASF Debug Support * 1710 */ 1711 int 1712 soc_mv2_asf_pbmp_get(int unit) 1713 { 1714 char pfmt[SOC_PBMP_FMT_LEN]; 1715 1716 if (!_soc_mv2_asf_ctrl[unit]->init) { 1717 return SOC_E_INTERNAL; 1718 } 1719 1720 LOG_CLI(("ASF PBMP: %s\n", 1721 SOC_PBMP_FMT(_soc_mv2_asf_ctrl[unit]->asf_ports, pfmt))); 1722 1723 return SOC_E_NONE; 1724 } 1725 1726 int 1727 soc_mv2_port_asf_show( 1728 int unit, 1729 soc_port_t port, 1730 int port_speed) 1731 { 1732 int ret; 1733 char mode_str[4][15] = {"SAF", "Same speed ", "Slow to Fast", 1734 "Fast to Slow"}; 1735 char speed_str[_SOC_MV2_ASF_CLASS_CNT][10] = {"SAF", "10G", "HG[11]", "20G", 1736 "HG[21]", "25G", "HG[27]", "40G", "HG[42]", 1737 "50G", "HG[53]", "100G", "HG[106]"}; 1738 soc_mv2_asf_mode_e mode = _SOC_MV2_ASF_RETRV; 1739 uint8 min_speed, max_speed; 1740 1741 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) { 1742 return BCM_E_NONE; 1743 } 1744 1745 min_speed = max_speed = _SOC_MV2_ASF_RETRV; 1746 ret = soc_mv2_port_asf_mode_get(unit, port, port_speed, &mode); 1747 if (SOC_E_UNAVAIL == ret) { 1748 mode = _SOC_MV2_ASF_MODE_SAF; 1749 } else if (SOC_E_NONE != ret) { 1750 return ret; 1751 } 1752 1753 LOG_CLI(("%-5s %-11s ", SOC_PORT_NAME(unit, port), mode_str[mode])); 1754 1755 if (_SOC_MV2_ASF_MODE_SAF == mode) { 1756 LOG_CLI((" .. NA ..\n")); 1757 } else if (_SOC_MV2_ASF_MODE_FAST_TO_SLOW == mode) { 1758 ret = _soc_mv2_port_asf_speed_limits_get(unit, port, port_speed, mode, 1759 &min_speed, &max_speed); 1760 LOG_CLI(("%s / %s\n", speed_str[max_speed], speed_str[min_speed])); 1761 } else { 1762 ret = _soc_mv2_port_asf_speed_limits_get(unit, port, port_speed, mode, 1763 &min_speed, &max_speed); 1764 LOG_CLI(("%s / %s\n", speed_str[min_speed], speed_str[max_speed])); 1765 } 1766 1767 return SOC_E_NONE; 1768 } 1769 1770 int soc_mv2_asf_config_dump(int unit) 1771 { 1772 char asf_profile_str[3][25] = {"No cut-thru support", 1773 "Similar speed cut-thru", 1774 "Extreme speed cut-thru"}; 1775 1776 if (!_soc_mv2_asf_ctrl[unit] || !_soc_mv2_asf_ctrl[unit]->init) { 1777 return SOC_E_INTERNAL; 1778 } 1779 1780 LOG_CLI(("ASF Profile: %s\n\n", 1781 asf_profile_str[_soc_mv2_asf_ctrl[unit]->asf_mem_profile])); 1782 1783 return SOC_E_NONE; 1784 } 1785 1786 int 1787 soc_mv2_port_asf_config_dump( 1788 int unit, 1789 soc_port_t port, 1790 int port_speed) 1791 { 1792 int txp = 0, rxp = 0, ct_class = 0; 1793 uint8 src_class = 0, dst_class = 0; 1794 uint8 min_sp = 0, max_sp = 0; 1795 uint8 fifo_threshold = 0, fifo_depth = 0, mmu_prebuf = 0; 1796 uint8 xmit_start_cnt[13] = {0}; 1797 uint32 rval, mmu_ep_credits = 0, egr_mmu_cell_credits = 0; 1798 mac_driver_t *macd; 1799 soc_mv2_asf_mode_e mode = _SOC_MV2_ASF_RETRV; 1800 egr_mmu_cell_credit_entry_t credit_entry; 1801 1802 if (IS_CPU_PORT(unit, port) || IS_LB_PORT(unit, port)) { 1803 return BCM_E_NONE; 1804 } 1805 1806 if (!_soc_mv2_asf_ctrl[unit] || !_soc_mv2_asf_ctrl[unit]->init) { 1807 return SOC_E_INTERNAL; 1808 } 1809 1810 SOC_IF_ERROR_RETURN( 1811 soc_mv2_port_asf_mode_get(unit, port, port_speed, &mode)); 1812 1813 if (soc_mv2_port_asf_valid(unit, port)) { 1814 min_sp = max_sp = fifo_threshold = _SOC_MV2_ASF_RETRV; 1815 fifo_depth = mmu_prebuf = _SOC_MV2_ASF_RETRV; 1816 1817 SOC_IF_ERROR_RETURN( 1818 _soc_mv2_port_asf_class_get(unit, port, &ct_class)); 1819 SOC_IF_ERROR_RETURN( 1820 _soc_mv2_port_asf_speed_limits_get(unit, port, port_speed, mode, 1821 &min_sp, &max_sp)); 1822 SOC_IF_ERROR_RETURN( 1823 _soc_mv2_port_asf_fifo_threshold_get(unit, port, port_speed, mode, 1824 &fifo_threshold)); 1825 1826 SOC_IF_ERROR_RETURN( 1827 _soc_mv2_port_asf_fifo_depth_get(unit, port, port_speed, mode, 1828 &fifo_depth)); 1829 1830 SOC_IF_ERROR_RETURN( 1831 _soc_mv2_port_asf_mmu_prebuf_get(unit, port, port_speed, 1832 &mmu_prebuf)); 1833 1834 SOC_IF_ERROR_RETURN(READ_ASF_CREDIT_THRESH_HIr(unit, port, &rval)); 1835 mmu_ep_credits = soc_reg_field_get(unit, ASF_CREDIT_THRESH_HIr, 1836 rval, THRESHf); 1837 } 1838 1839 dst_class = _soc_mv2_speed_to_ct_class_map(port_speed); 1840 for (src_class = 0; src_class < _SOC_MV2_ASF_CLASS_CNT; src_class++) { 1841 xmit_start_cnt[src_class] = _SOC_MV2_ASF_RETRV; 1842 SOC_IF_ERROR_RETURN( 1843 _soc_mv2_port_asf_xmit_start_count_get(unit, port, src_class, 1844 dst_class, mode, 1845 &xmit_start_cnt[src_class])); 1846 } 1847 1848 /* 1849 * COVERITY 1850 * 1851 * min_sp and max_sp will be updated in _soc_mv2_port_asf_speed_limits_get. 1852 * So they won't overrun _soc_mv2_asf_cfg_tbl. 1853 */ 1854 /* coverity[overrun-local : FALSE] */ 1855 LOG_CLI(("%-5s %-3d %-3d %-6d %-6d %-3d %-3d ", SOC_PORT_NAME(unit, port), 1856 mode, ct_class, _SOC_MV2_CT_CLASS_TO_SPEED_MAP(min_sp), 1857 _SOC_MV2_CT_CLASS_TO_SPEED_MAP(max_sp), fifo_threshold, 1858 fifo_depth)); 1859 for (src_class = 0; src_class < _SOC_MV2_ASF_CLASS_CNT; src_class++) { 1860 LOG_CLI(("%-3d ", xmit_start_cnt[src_class])); 1861 } 1862 1863 SOC_IF_ERROR_RETURN(READ_EGR_MMU_CELL_CREDITm(unit, MEM_BLOCK_ANY, 1864 SOC_INFO(unit).port_l2p_mapping[port], &credit_entry)); 1865 egr_mmu_cell_credits = soc_EGR_MMU_CELL_CREDITm_field32_get(unit, 1866 &credit_entry, CREDITf); 1867 1868 SOC_IF_ERROR_RETURN(soc_mac_probe(unit, port, &macd)); 1869 SOC_IF_ERROR_RETURN(MAC_PAUSE_GET(macd, unit, port, &txp, &rxp)); 1870 1871 LOG_CLI((" %-3d %-3d %-3d %-3d\n", mmu_prebuf, mmu_ep_credits, 1872 egr_mmu_cell_credits, rxp)); 1873 1874 return SOC_E_NONE; 1875 } 1876 1877 /****************************************************************************** 1878 * Name: soc_mv2_port_asf_detach * 1879 * Description: * 1880 * Update ASF when port deleted during Flexport operation * 1881 * IN params: * 1882 * - Unit * 1883 * - Logical Port * 1884 * Returns: * 1885 * - SOC_E_NONE on success * 1886 * - SOC_E_PARAM on invalid parameter * 1887 */ 1888 int 1889 soc_mv2_port_asf_detach(int unit, soc_port_t port) 1890 { 1891 if (_soc_mv2_asf_ctrl[unit] == NULL) { 1892 return SOC_E_INIT; 1893 } 1894 1895 if (soc_mv2_port_asf_valid(unit, port)) { 1896 SOC_PBMP_PORT_REMOVE(_soc_mv2_asf_ctrl[unit]->asf_ports, port); 1897 SOC_PBMP_PORT_REMOVE(_soc_mv2_asf_ctrl[unit]->pause_restore, port); 1898 if (SOC_PBMP_MEMBER(_soc_mv2_asf_ctrl[unit]->asf_ss, port)) { 1899 SOC_PBMP_PORT_REMOVE(_soc_mv2_asf_ctrl[unit]->asf_ss, port); 1900 } else if (SOC_PBMP_MEMBER(_soc_mv2_asf_ctrl[unit]->asf_sf, port)) { 1901 SOC_PBMP_PORT_REMOVE(_soc_mv2_asf_ctrl[unit]->asf_sf, port); 1902 } else if (SOC_PBMP_MEMBER(_soc_mv2_asf_ctrl[unit]->asf_fs, port)) { 1903 SOC_PBMP_PORT_REMOVE(_soc_mv2_asf_ctrl[unit]->asf_fs, port); 1904 } 1905 } 1906 return SOC_E_NONE; 1907 } 1908 1909 #endif /* BCM_MAVERICK2_SUPPORT */ 1910