subport.c (357907B)
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 * File: subport.c 8 * Purpose: Katana2 SUBPORT functions 9 */ 10 11 #include <shared/bsl.h> 12 13 #include <soc/defs.h> 14 #include <sal/core/libc.h> 15 #if defined(BCM_KATANA2_SUPPORT) 16 17 #include <soc/drv.h> 18 #include <soc/mem.h> 19 #include <soc/util.h> 20 #include <soc/katana2.h> 21 #include <bcm/error.h> 22 #include <bcm/port.h> 23 #include <bcm/subport.h> 24 #include <bcm_int/esw/katana2.h> 25 #include <bcm_int/esw/subport.h> 26 #include <bcm_int/esw_dispatch.h> 27 #include <bcm_int/esw/triumph.h> 28 #include <bcm_int/esw/triumph2.h> 29 #include <bcm_int/esw/stack.h> 30 31 #if defined(BCM_SABER2_SUPPORT) 32 #include <soc/saber2.h> 33 #endif 34 35 #if defined(BCM_METROLITE_SUPPORT) 36 #include <soc/metrolite.h> 37 #endif 38 /***************************************** 39 * Subport common section - start 40 */ 41 42 /* 43 * Function Vector 44 */ 45 static bcm_esw_subport_drv_t bcmi_kt2_subport_drv = { 46 47 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 48 /* subport_init */ bcm_tr2_subport_init, 49 /* subport_group_create */ bcm_tr2_subport_group_create, 50 /* subport_group_get */ bcm_tr2_subport_group_get, 51 /* subport_group_traverse */ NULL, 52 /* subport_group_destroy */ bcm_tr2_subport_group_destroy, 53 /* subport_linkphy_config_set */ NULL, 54 /* subport_linkphy_config_get */ NULL, 55 /* subport_port_add */ bcm_tr2_subport_port_add, 56 /* subport_port_get */ bcm_tr2_subport_port_get, 57 /* subport_port_traverse */ bcm_tr2_subport_port_traverse, 58 /* subport_port_stat_set */ NULL, 59 /* subport_port_stat_get */ NULL, 60 /* subport_port_delete */ bcm_tr2_subport_port_delete, 61 /* subport_cleanup */ bcm_tr2_subport_cleanup, 62 #else 63 NULL, NULL, NULL, NULL, NULL, 64 NULL, NULL, NULL, NULL, NULL, 65 NULL, NULL, NULL, NULL, 66 #endif 67 68 /* coe_init */ bcm_kt2_subport_init, 69 /* coe_group_create */ bcm_kt2_subport_group_create, 70 /* coe_group_get */ bcm_kt2_subport_group_get, 71 /* coe_group_traverse */ bcm_kt2_subport_group_traverse, 72 /* coe_group_destroy */ bcm_kt2_subport_group_destroy, 73 /* coe_linkphy_config_set */ bcm_kt2_subport_group_linkphy_config_set, 74 /* coe_linkphy_config_get */ bcm_kt2_subport_group_linkphy_config_get, 75 /* coe_port_add */ bcm_kt2_subport_port_add, 76 /* coe_port_get */ bcm_kt2_subport_port_get, 77 /* coe_port_traverse */ bcm_kt2_subport_port_traverse, 78 /* coe_port_stat_set */ bcm_kt2_subport_port_stat_set, 79 /* coe_port_stat_get */ bcm_kt2_subport_port_stat_get, 80 /* coe_port_delete */ bcm_kt2_subport_port_delete, 81 /* coe_cleanup */ bcm_kt2_subport_cleanup, 82 /* subport_linkphy_rx_error_register */ bcm_kt2_subport_linkphy_rx_error_register, 83 /* subport_linkphy_rx_error_unregister */ bcm_kt2_subport_linkphy_rx_error_unregister, 84 /* subport_gport_modport_get */ bcmi_kt2_subport_gport_modport_get 85 }; 86 87 /***************************************** 88 * Subport common section - start 89 */ 90 91 /* Bitmap to manage PP_PORT indices for subport port addition*/ 92 STATIC SHR_BITDCL *_bcm_subport_pp_port_bitmap[BCM_MAX_NUM_UNITS] = { 0 }; 93 STATIC int _bcm_subport_pp_port_count[BCM_MAX_NUM_UNITS] = { 0 }; 94 95 /********************************* 96 * Subport common section - end 97 */ 98 99 100 /********************************* 101 * LinkPHY subport section -start 102 */ 103 104 /* Bitmap of LinkPHY subport group id */ 105 STATIC SHR_BITDCL *_bcm_linkphy_group_bitmap[BCM_MAX_NUM_UNITS] = { 0 }; 106 107 /* Count of all LinkPHY subport groups created */ 108 STATIC int _bcm_linkphy_subport_group_count[BCM_MAX_NUM_UNITS] = { 0 }; 109 110 /* 111 * Bitmap of device internal stream id usage.usage for Katana2 112 * Katana has 2 blocks and each block has 128 streams. 113 * External stream id is mapped to 256 device internal stream ids. 114 * Block 0 internal stream id base = 0 115 * Block 1 internal stream id base = 128 116 * device internal stream id = internal stream id + internal stream id base 117 */ 118 STATIC SHR_BITDCL *_bcm_dev_int_stream_id_bitmap[BCM_MAX_NUM_UNITS] = { 0 }; 119 120 /* Set the LinkPHY subport group gport */ 121 #define _BCM_KT2_LINKPHY_SUBPORT_GROUP_SET(_subport_group, \ 122 _port, _gid) \ 123 _BCM_COE_LINKPHY_SUBPORT_GROUP_SET(_subport_group, \ 124 _port, _gid) 125 126 127 #define _BCM_KT2_PORT_SUPPORTS_LINKPHY(_unit_, _port_) \ 128 (SOC_REG_PORT_VALID(_unit_, RXLP_PORT_ENABLEr, _port_)) 129 130 /* 131 * LinkPHY subport group usage bitmap operations 132 */ 133 #define _BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_GET(_u_, _group_) \ 134 SHR_BITGET(_bcm_linkphy_group_bitmap[_u_], (_group_)) 135 136 #define _BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_SET(_u_, _group_) \ 137 SHR_BITSET(_bcm_linkphy_group_bitmap[_u_], (_group_)) 138 139 #define _BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_CLR(_u_, _group_) \ 140 SHR_BITCLR(_bcm_linkphy_group_bitmap[_u_], (_group_)) 141 142 143 /* Katana2 LinkPHY device internal stream id usage bitmap */ 144 #define _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_GET(_u_, _stream_id_) \ 145 SHR_BITGET(_bcm_dev_int_stream_id_bitmap[_u_], (_stream_id_)) 146 147 #define _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_SET(_u_, _stream_id_) \ 148 SHR_BITSET(_bcm_dev_int_stream_id_bitmap[_u_], (_stream_id_)) 149 150 #define _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_CLR(_u_, _stream_id_) \ 151 SHR_BITCLR(_bcm_dev_int_stream_id_bitmap[_u_], (_stream_id_)) 152 153 /* LinkPHY subport port info structure */ 154 typedef struct { 155 bcm_gport_t group; /* Subport group gort*/ 156 int valid; 157 int num_streams; /* Number of sreams */ 158 uint16 ext_stream_idx[BCM_SUBPORT_CONFIG_MAX_STREAMS]; 159 } _bcm_linkphy_subport_port_info_t; 160 161 /* LinkPHY subport port array */ 162 _bcm_linkphy_subport_port_info_t 163 *(_bcm_linkphy_subport_port_info[BCM_MAX_NUM_UNITS]) = { 0 }; 164 165 #define _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port) \ 166 (_bcm_linkphy_subport_port_info[unit][pp_port].valid) 167 168 #define _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port) \ 169 (_bcm_linkphy_subport_port_info[unit][pp_port].group) 170 171 #define _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_NUM_STREAMS_GET(unit, pp_port) \ 172 (_bcm_linkphy_subport_port_info[unit][pp_port].num_streams) 173 174 #define _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_EXT_STREAM_ID_GET(unit, pp_port, \ 175 sp_stream_array_id) \ 176 (_bcm_linkphy_subport_port_info[unit] \ 177 [pp_port].ext_stream_idx[sp_stream_array_id]) 178 179 #define _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_SET(unit, \ 180 pp_port, sp_group, sp_num_streams, is_valid) \ 181 { \ 182 _bcm_linkphy_subport_port_info[unit][pp_port].group = sp_group; \ 183 _bcm_linkphy_subport_port_info[unit][pp_port].num_streams \ 184 = sp_num_streams; \ 185 _bcm_linkphy_subport_port_info[unit][pp_port].valid = is_valid; \ 186 } 187 188 #if defined(BCM_SABER2_SUPPORT) 189 /* SB2 Linkphy internal stream id allocation related structures 190 * There are only 32 internal stream ids possible for SB2 (0 to 31). 191 * This has to be divided to four ports as 8 stream ids per linkphy port. 192 * 193 * Note that this cannot be directly calculated from external stream id 194 * since external stream ids range from N to N+31 (where N is external stream 195 * id base) for that port. And these 32 external stream IDs have a 196 * limited pool range of 8 internal stream IDs. Hence we need an allocation 197 * procedure. 198 * 199 * Hence Internal stream id pool allocation is as follows. 200 * 201 * Port 1 - Pool contains Ids from 0 to 7 202 * Port 2 - Pool contains Ids from 8 to 15 203 * Port 3 - Pool contains Ids from 16 to 23 204 * Port 4 - Pool contains Ids from 24 to 31. 205 */ 206 shr_idxres_list_handle_t _bcm_sb2_int_stream_id_pool[BCM_MAX_NUM_UNITS][SOC_SB2_MAX_LINKPHY_PORTS]; 207 #endif 208 209 #if defined(BCM_METROLITE_SUPPORT) 210 /* Metrolite Linkphy internal stream id allocation related structures 211 * There are only 24 internal stream ids possible for Metrolite (0 to 23). 212 * This has to be divided to four ports as 6 stream ids per linkphy port. 213 * 214 * Note that this cannot be directly calculated from external stream id 215 * since external stream ids range from N to N+23 (where N is external stream 216 * id base) for that port. And these 24 external stream IDs have a 217 * limited pool range of 6 internal stream IDs. Hence we need an allocation 218 * procedure. 219 * 220 * Hence Internal stream id pool allocation is as follows. 221 * 222 * Port 1 - Pool contains Ids from 0 to 5 223 * Port 2 - Pool contains Ids from 6 to 11 224 * Port 3 - Pool contains Ids from 12 to 17 225 * Port 4 - Pool contains Ids from 18 to 23. 226 */ 227 shr_idxres_list_handle_t _bcm_ml_int_stream_id_pool[BCM_MAX_NUM_UNITS][_BCM_ML_MAX_LINKPHY_PORTS]; 228 #endif 229 230 /* 231 * KT2 - Pool of LinkPhy block per port internal stream Ids. 232 * Each LinkPhy block port has internal streams ids in the range of 233 * 0 to 127. Each LinkPhy block supports upto maximum 4 LinkPhy 234 * ports and the internal stream id allocation is done per port in LP block. 235 * Block 0 has LP ports 27,32,33,34 and Block 1 has LP ports 28,29,30,31. 236 */ 237 shr_idxres_list_handle_t 238 _bcm_kt2_blk_int_stream_id_pool[BCM_MAX_NUM_UNITS][SOC_KT2_LINKPHY_BLOCK_MAX] 239 [SOC_KT2_LINKPHY_BLOCK_PORT_IDX_MAX]; 240 /* LinkPHY counter related defines */ 241 242 #define _BCM_KT2_LINKPHY_DIRECTION_MAX 2 243 #define _BCM_KT2_LINKPHY_DIRECTION_RX 0 244 #define _BCM_KT2_LINKPHY_DIRECTION_TX 1 245 #define _BCM_KT2_LINKPHY_BLOCK_MAX 2 246 #define _BCM_KT2_LINKPHY_POOL_MAX 4 247 #define _BCM_KT2_LINKPHY_POOL_FRAG_BYTE 0 248 #define _BCM_KT2_LINKPHY_POOL_FRAG 1 249 #define _BCM_KT2_LINKPHY_POOL_FRAME_BYTE 2 250 #define _BCM_KT2_LINKPHY_POOL_FRAME 3 251 #define _BCM_KT2_LINKPHY_COUNTER_MIN(unit) \ 252 (soc_mem_index_min(unit, RXLP_DEBUG_COUNTER8m)) 253 #define _BCM_KT2_LINKPHY_COUNTER_MAX(unit) \ 254 (soc_mem_index_max(unit, RXLP_DEBUG_COUNTER8m) + 1) 255 256 #define _BCM_ML_LINKPHY_BLOCK_MAX 1 /* Only one RXLP/TXLP block */ 257 258 static sal_mutex_t linkphy_ctr_mutex[BCM_UNITS_MAX] = {NULL}; 259 260 261 static rxlp_debug_counter7_entry_t *linkphy_temp_ctr 262 [BCM_UNITS_MAX] = {NULL}; 263 264 static uint64 *linkphy_frag_byte_ctr 265 [BCM_UNITS_MAX][_BCM_KT2_LINKPHY_DIRECTION_MAX] 266 [_BCM_KT2_LINKPHY_BLOCK_MAX] = {{{NULL}}}; 267 static uint64 *linkphy_frag_ctr 268 [BCM_UNITS_MAX][_BCM_KT2_LINKPHY_DIRECTION_MAX] 269 [_BCM_KT2_LINKPHY_BLOCK_MAX] = {{{NULL}}}; 270 static uint64 *linkphy_frame_byte_ctr 271 [BCM_UNITS_MAX][_BCM_KT2_LINKPHY_DIRECTION_MAX] 272 [_BCM_KT2_LINKPHY_BLOCK_MAX] = {{{NULL}}}; 273 static uint64 *linkphy_frame_ctr 274 [BCM_UNITS_MAX][_BCM_KT2_LINKPHY_DIRECTION_MAX] 275 [_BCM_KT2_LINKPHY_BLOCK_MAX] = {{{NULL}}}; 276 277 278 #define BCM_LINKPHY_COUNTER_LOCK(unit) \ 279 sal_mutex_take(linkphy_ctr_mutex[unit], sal_mutex_FOREVER); 280 #define BCM_LINKPHY_COUNTER_UNLOCK(unit) \ 281 sal_mutex_give(linkphy_ctr_mutex[unit]); 282 283 static soc_mem_t linkphy_counter_table 284 [_BCM_KT2_LINKPHY_DIRECTION_MAX][_BCM_KT2_LINKPHY_POOL_MAX] = { 285 {RXLP_DEBUG_COUNTER8m, 286 RXLP_DEBUG_COUNTER9m, 287 RXLP_DEBUG_COUNTER10m, 288 RXLP_DEBUG_COUNTER11m}, 289 {TXLP_DEBUG_COUNTER8m, 290 TXLP_DEBUG_COUNTER9m, 291 TXLP_DEBUG_COUNTER10m, 292 TXLP_DEBUG_COUNTER11m} 293 }; 294 295 typedef struct _bcm_subport_linkphy_rx_error_cb_info_s{ 296 bcm_subport_linkphy_rx_error_reg_info_t reg_info; 297 void *user_data; 298 }_bcm_subport_linkphy_rx_error_cb_info_t; 299 300 _bcm_subport_linkphy_rx_error_cb_info_t _bcm_linkphy_rx_error_cb_info[bcmSubportLinkphyRxErrorCount] = {{{NULL, 0},NULL}}; 301 302 303 soc_field_t _bcm_kt2_subport_linkphy_rx_error_to_reg_field_map[bcmSubportLinkphyRxErrorCount] = { 304 MAX_FRAME_SIZE_ERROR_INT_ENABLEf, 305 RUNT_FRAME_INT_ENABLEf, 306 DFC_LENGTH_ERROR_INT_ENABLEf, 307 DFC_DROP_DUE_TO_PORT_PURGE_INT_ENABLEf, 308 DFC_TIME_ERROR_INT_ENABLEf, 309 DFC_OPCODE_ERROR_INT_ENABLEf, 310 LENGTH_ZERO_INT_ENABLEf, 311 LENGTH_LT_PAYLOAD_INT_ENABLEf, 312 LENGTH_GT_PAYLOAD_INT_ENABLEf, 313 FRAMING_ERROR_INT_ENABLEf, 314 FRAME_CRC_ERROR_INT_ENABLEf, 315 STREAM_ID_UNEXPECTED_INT_ENABLEf, 316 MACSA_ERROR_INT_ENABLEf, 317 MACDA_ERROR_INT_ENABLEf, 318 ETHERTYPE_ERROR_INT_ENABLEf, 319 }; 320 321 soc_field_t _bcm_kt2_subport_linkphy_rx_error_to_st_reg_field_map[bcmSubportLinkphyRxErrorCount] = { 322 MAX_FRAME_SIZE_ERROR_INT_STATUSf, 323 RUNT_FRAME_INT_STATUSf, 324 DFC_LENGTH_ERROR_INT_STATUSf, 325 DFC_DROP_DUE_TO_PORT_PURGE_INT_STATUSf, 326 DFC_TIME_ERROR_INT_STATUSf, 327 DFC_OPCODE_ERROR_INT_STATUSf, 328 LENGTH_ZERO_INT_STATUSf, 329 LENGTH_LT_PAYLOAD_INT_STATUSf, 330 LENGTH_GT_PAYLOAD_INT_STATUSf, 331 FRAMING_ERROR_INT_STATUSf, 332 FRAME_CRC_ERROR_INT_STATUSf, 333 STREAM_ID_UNEXPECTED_INT_STATUSf, 334 MACSA_ERROR_INT_STATUSf, 335 MACDA_ERROR_INT_STATUSf, 336 ETHERTYPE_ERROR_INT_STATUSf, 337 }; 338 339 soc_field_t _bcm_kt2_subport_linkphy_rx_error_to_dl_reg_field_map[bcmSubportLinkphyRxErrorCount] = { 340 MAX_FRAME_SIZE_ERROR_LOG_ENABLEf, 341 RUNT_FRAME_LOG_ENABLEf, 342 DFC_LENGTH_ERROR_LOG_ENABLEf, 343 DFC_DROP_DUE_TO_PORT_PURGE_LOG_ENABLEf, 344 DFC_TIME_ERROR_LOG_ENABLEf, 345 DFC_OPCODE_ERROR_LOG_ENABLEf, 346 LENGTH_ZERO_LOG_ENABLEf, 347 LENGTH_LT_PAYLOAD_LOG_ENABLEf, 348 LENGTH_GT_PAYLOAD_LOG_ENABLEf, 349 FRAMING_ERROR_LOG_ENABLEf, 350 INVALIDf, 351 STREAM_ID_UNEXPECTED_LOG_ENABLEf, 352 MACSA_ERROR_LOG_ENABLEf, 353 MACDA_ERROR_LOG_ENABLEf, 354 ETHERTYPE_ERROR_LOG_ENABLEf, 355 }; 356 357 soc_field_t _bcm_kt2_subport_linkphy_rx_error_to_dl_val_reg_field_map[bcmSubportLinkphyRxErrorCount] = { 358 MAX_FRAME_SIZE_ERROR_LOG_VALIDf, 359 RUNT_FRAME_INT_LOG_VALIDf, 360 DFC_LENGTH_ERROR_INT_LOG_VALIDf, 361 DFC_DROP_DUE_TO_PORT_PURGE_INT_LOG_VALIDf, 362 DFC_TIME_ERROR_INT_LOG_VALIDf, 363 DFC_OPCODE_ERROR_INT_LOG_VALIDf, 364 LENGTH_ZERO_INT_LOG_VALIDf, 365 LENGTH_LT_PAYLOAD_INT_LOG_VALIDf, 366 LENGTH_GT_PAYLOAD_INT_LOG_VALIDf, 367 FRAMING_ERROR_INT_LOG_VALIDf, 368 INVALIDf, 369 STREAM_ID_UNEXPECTED_INT_LOG_VALIDf, 370 MACSA_ERROR_INT_LOG_VALIDf, 371 MACDA_ERROR_INT_LOG_VALIDf, 372 ETHERTYPE_ERROR_INT_LOG_VALIDf, 373 }; 374 375 376 #define _BCM_KT2_SUBPORT_LINKPHY_RX_ERROR_VALID(lp_rx_error) ((lp_rx_error >= bcmSubportLinkphyRxErrorMaxFrameSize) &&\ 377 (lp_rx_error < bcmSubportLinkphyRxErrorCount)) 378 379 int _bcm_linkphy_port_int_stream_id_base_get(int unit, 380 bcm_port_t port, 381 uint16 *int_stream_id_base); 382 int _bcm_linkphy_port_ext_stream_id_base_get(int unit, 383 bcm_port_t port, 384 uint16 *ext_stream_id_base); 385 STATIC int 386 _bcm_linkphy_port_rx_int_stream_map_port_get(int unit, 387 int port, 388 uint16 ext_stream_id, 389 uint16 *int_stream_id); 390 391 int 392 soc_linkphy_port_blk_idx_get(int unit, int port, int *block, int *index); 393 394 int _bcm_kt2_subport_linkphy_rx_error_handler( 395 int unit, bcm_port_t port, uint32 rval); 396 /********************************* 397 * LinkPHY subport section -end 398 */ 399 400 401 402 /********************************* 403 * Subport common section - start 404 */ 405 406 407 /* Get port number/trunk id associated with subport_group gport*/ 408 #define _BCM_KT2_SUBPORT_GROUP_PORT_GET(_subport_group) \ 409 _BCM_SUBPORT_COE_GROUP_PORT_GET(_subport_group) 410 411 /* Get group id associated with subport_group gport*/ 412 #define _BCM_KT2_SUBPORT_GROUP_ID_GET(_subport_group) \ 413 _BCM_SUBPORT_COE_GROUP_ID_GET(_subport_group) 414 415 #define _BCM_KT2_SUBPORT_GROUP_TYPE_CASCADED_SET(_subport_group) \ 416 _BCM_SUBPORT_COE_GROUP_TYPE_CASCADED_SET(_subport_group) 417 418 #define _BCM_KT2_SUBPORT_LOCK(unit) \ 419 _BCM_SUBPORT_COE_LOCK(unit); 420 421 #define _BCM_KT2_SUBPORT_UNLOCK(unit) \ 422 _BCM_SUBPORT_COE_UNLOCK(unit); 423 424 #define _BCM_KT2_SUBPORT_CHECK_INIT(_unit_) \ 425 _BCM_SUBPORT_COE_CHECK_INIT(_unit_); 426 427 /* 428 * Subport group usage bitmap operations 429 */ 430 #define _BCM_KT2_SUBPORT_GROUP_USED_GET(_u_, _group_) \ 431 _BCM_SUBPORT_COE_GROUP_USED_GET(_u_, _group_) 432 433 #define _BCM_KT2_SUBPORT_GROUP_USED_SET(_u_, _group_) \ 434 _BCM_SUBPORT_COE_GROUP_USED_SET(_u_, _group_) 435 436 #define _BCM_KT2_SUBPORT_GROUP_USED_CLR(_u_, _group_) \ 437 _BCM_SUBPORT_COE_GROUP_USED_CLR(_u_, _group_) 438 439 #define _BCM_KT2_SUBPORT_PP_PORT_USED_GET(_u_, _pp_port_) \ 440 SHR_BITGET(_bcm_subport_pp_port_bitmap[_u_], (_pp_port_)) 441 442 #define _BCM_KT2_SUBPORT_PP_PORT_USED_SET(_u_, _pp_port_) \ 443 SHR_BITSET(_bcm_subport_pp_port_bitmap[_u_], (_pp_port_)) 444 445 #define _BCM_KT2_SUBPORT_PP_PORT_USED_CLR(_u_, _pp_port_) \ 446 SHR_BITCLR(_bcm_subport_pp_port_bitmap[_u_], (_pp_port_)) 447 448 449 /********************************* 450 * Subport common section - end 451 */ 452 453 /********************************* 454 * General subport section - start 455 */ 456 457 /* Set the general subport group gport */ 458 #define _BCM_KT2_GENERAL_SUBPORT_GROUP_SET(_subport_group, \ 459 _port, _gid) \ 460 _BCM_GENERAL_SUBPORT_GROUP_SET(_subport_group, \ 461 _port, _gid) 462 463 /* General subport group usage bitmap operations */ 464 #define _BCM_KT2_GENERAL_SUBPORT_GROUP_USED_GET(_u_, _group_) \ 465 _BCM_GENERAL_SUBPORT_GROUP_USED_GET(_u_, _group_) 466 467 #define _BCM_KT2_GENERAL_SUBPORT_GROUP_USED_SET(_u_, _group_) \ 468 _BCM_GENERAL_SUBPORT_GROUP_USED_SET(_u_, _group_) 469 470 #define _BCM_KT2_GENERAL_SUBPORT_GROUP_USED_CLR(_u_, _group_) \ 471 _BCM_GENERAL_SUBPORT_GROUP_USED_CLR(_u_, _group_) 472 473 #define _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port) \ 474 (_bcm_general_subport_port_info[unit][pp_port].valid) 475 476 #define _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port) \ 477 (_bcm_general_subport_port_info[unit][pp_port].group) 478 479 #define _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_SET(unit, pp_port,\ 480 sp_group, is_valid) \ 481 { \ 482 _bcm_general_subport_port_info[unit][pp_port].group = sp_group; \ 483 _bcm_general_subport_port_info[unit][pp_port].valid = is_valid; \ 484 } 485 486 /********************************* 487 * General subport section - end 488 */ 489 490 /********************************* 491 * SubTag subport section - start 492 */ 493 494 /* Set the SubTag subport group gport */ 495 #define _BCM_KT2_SUBTAG_SUBPORT_GROUP_SET(_subport_group, \ 496 _port, _gid) \ 497 _BCM_SUBPORT_COE_SUBTAG_GROUP_SET(_subport_group, \ 498 _port, _gid) 499 500 /* 501 * SubTag subport group usage bitmap operations 502 */ 503 #define _BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_GET(_u_, _group_) \ 504 _BCM_SUBPORT_COE_SUBTAG_GROUP_USED_GET(_u_, _group_) 505 506 #define _BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_SET(_u_, _group_) \ 507 _BCM_SUBPORT_COE_SUBTAG_GROUP_USED_SET(_u_, _group_) 508 509 #define _BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_CLR(_u_, _group_) \ 510 _BCM_SUBPORT_COE_SUBTAG_GROUP_USED_CLR(_u_, _group_) 511 512 /* Katana2 SubTag VLAN id usage bitmap for given port*/ 513 #define _BCM_KT2_SUBTAG_VLAN_ID_USED_GET(_u_, _p, _vlan_id_) \ 514 _BCM_COE_SUBTAG_VLAN_ID_USED_GET(_u_, _p, _vlan_id_) 515 516 #define _BCM_KT2_SUBTAG_VLAN_ID_USED_SET(_u_, _p, _vlan_id_) \ 517 _BCM_COE_SUBTAG_VLAN_ID_USED_SET(_u_, _p, _vlan_id_) 518 519 #define _BCM_KT2_SUBTAG_VLAN_ID_USED_CLR(_u_, _p, _vlan_id_) \ 520 _BCM_COE_SUBTAG_VLAN_ID_USED_CLR(_u_, _p, _vlan_id_) 521 522 523 #define _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port) \ 524 (_bcm_subtag_subport_port_info[unit][pp_port].valid) 525 526 #define _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port) \ 527 (_bcm_subtag_subport_port_info[unit][pp_port].group) 528 529 #define _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VLAN_GET(unit, pp_port) \ 530 (_bcm_subtag_subport_port_info[unit][pp_port].vlan) 531 532 #define _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_TCAM_HW_ID_GET(unit, pp_port) \ 533 (_bcm_subtag_subport_port_info[unit][pp_port].subtag_tcam_hw_idx) 534 535 #define _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_SET(unit, pp_port,\ 536 sp_group, vlan_id, tcam_hw_id, is_valid) \ 537 { \ 538 _bcm_subtag_subport_port_info[unit][pp_port].group = sp_group; \ 539 _bcm_subtag_subport_port_info[unit][pp_port].vlan = vlan_id; \ 540 _bcm_subtag_subport_port_info[unit] \ 541 [pp_port].subtag_tcam_hw_idx = tcam_hw_id; \ 542 _bcm_subtag_subport_port_info[unit][pp_port].valid = is_valid; \ 543 } 544 545 546 /********************************* 547 * SubTag subport section - end 548 */ 549 550 /* prototypes - start */ 551 STATIC int 552 _bcm_linkphy_subport_port_get(int unit, 553 bcm_gport_t subport_port_gport, 554 bcm_subport_config_t *config); 555 556 STATIC int 557 _bcm_linkphy_subport_port_delete(int unit, 558 bcm_gport_t subport_port_gport); 559 560 STATIC int 561 _bcm_subtag_subport_port_get(int unit, 562 bcm_gport_t subport_port_gport, 563 bcm_subport_config_t *config); 564 565 STATIC int 566 _bcm_subtag_subport_port_delete(int unit, 567 bcm_gport_t subport_port_gport); 568 569 STATIC int 570 _bcm_general_subport_port_get(int unit, 571 bcm_gport_t subport_port_gport, 572 bcm_subport_config_t *config); 573 574 STATIC int 575 _bcm_general_subport_port_delete(int unit, 576 bcm_gport_t subport_port_gport); 577 578 #ifdef BCM_WARM_BOOT_SUPPORT 579 580 #define SCACHE_ALLOC_SIZE_INIT(_var_) \ 581 do { \ 582 (_var_) = 0; (_scache_ofst_) = 0; \ 583 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, \ 584 (BSL_META_U(unit, \ 585 "WarmBoot: Scache offset initialized to 0\n"))); \ 586 } while (0); 587 588 #define SCACHE_ALLOC_SIZE_INCR(_var_, _count_) \ 589 do { \ 590 (_var_) += (_count_); (_scache_ofst_) += (_count_); \ 591 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, \ 592 (BSL_META_U(unit, \ 593 "WarmBoot: Scache offset incr by %d to %d\n"), \ 594 (int)(_count_), (_scache_ofst_) \ 595 )); \ 596 } while (0); 597 598 #define SCACHE_BYTE_INIT(_scache_ptr_) \ 599 do { \ 600 _scache_ofst_ = 0; \ 601 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, \ 602 (BSL_META_U(unit, \ 603 "WarmBoot: Scache offset initialized to 0\n") \ 604 )); \ 605 } while (0); 606 607 #define SCACHE_BYTE_COPY(_scache_ptr_, _local_var_, _size_) \ 608 do { \ 609 sal_memcpy(_scache_ptr_, _local_var_, _size_); \ 610 _scache_ptr_ += (_size_); \ 611 (_scache_ofst_) += (_size_); \ 612 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, \ 613 (BSL_META_U(unit, \ 614 "WarmBoot: Scache offset incr by %d to %d\n"),\ 615 (int)(_size_), (_scache_ofst_) \ 616 )); \ 617 } while (0); 618 619 #define SCACHE_BYTE_RESTORE(_scache_ptr_, _local_var_, _size_) \ 620 do { \ 621 sal_memcpy(_local_var_, _scache_ptr_, _size_); \ 622 _scache_ptr_ += (_size_); \ 623 (_scache_ofst_) += (_size_); \ 624 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, \ 625 (BSL_META_U(unit, \ 626 "WarmBoot: Scache offset incr by %d to %d\n"),\ 627 (int)(_size_), (_scache_ofst_) \ 628 )); \ 629 } while (0); 630 631 int 632 bcm_kt2_subport_wb_scache_alloc(int unit, uint16 version, int *alloc_sz) 633 { 634 int subport_group_max = SOC_INFO(unit).subport_group_max; 635 int pp_port_index_max = SOC_INFO(unit).pp_port_index_max; 636 uint32 _scache_ofst_ = 0; 637 638 SCACHE_ALLOC_SIZE_INIT(*alloc_sz); 639 640 /* Num subport groups */ 641 SCACHE_ALLOC_SIZE_INCR(*alloc_sz, sizeof(int)); 642 643 /* Num pp ports */ 644 SCACHE_ALLOC_SIZE_INCR(*alloc_sz, sizeof(int)); 645 646 /* Subport-group bitmap */ 647 SCACHE_ALLOC_SIZE_INCR(*alloc_sz, 648 SHR_BITALLOCSIZE(subport_group_max)); 649 650 /* Subport pp_port bitmap */ 651 SCACHE_ALLOC_SIZE_INCR(*alloc_sz, 652 SHR_BITALLOCSIZE(pp_port_index_max + 1)); 653 654 /* Num subtag groups */ 655 SCACHE_ALLOC_SIZE_INCR(*alloc_sz, sizeof(int)); 656 657 /* Subtag group bitmap */ 658 SCACHE_ALLOC_SIZE_INCR(*alloc_sz, 659 SHR_BITALLOCSIZE(subport_group_max)); 660 661 /* pp_port to subport group info */ 662 SCACHE_ALLOC_SIZE_INCR(*alloc_sz, 663 (sizeof(bcm_gport_t) * SOC_MAX_NUM_PP_PORTS)); 664 665 /* Num linkphy group */ 666 SCACHE_ALLOC_SIZE_INCR(*alloc_sz, sizeof(int)); 667 668 /* linkphy group bitmap */ 669 SCACHE_ALLOC_SIZE_INCR(*alloc_sz, 670 SHR_BITALLOCSIZE(subport_group_max)); 671 672 /* linkphy subports info */ 673 SCACHE_ALLOC_SIZE_INCR(*alloc_sz, 674 (sizeof(bcm_gport_t) * SOC_MAX_NUM_PP_PORTS)); /* group */ 675 SCACHE_ALLOC_SIZE_INCR(*alloc_sz, 676 (sizeof(uint16) * SOC_MAX_NUM_PP_PORTS)); /* valid */ 677 SCACHE_ALLOC_SIZE_INCR(*alloc_sz, 678 (sizeof(uint16) * SOC_MAX_NUM_PP_PORTS)); /* num_streams */ 679 SCACHE_ALLOC_SIZE_INCR(*alloc_sz, 680 (2 * sizeof(uint16) * SOC_MAX_NUM_PP_PORTS)); /* streams */ 681 682 if (version >= BCM_SUBPORT_WB_VERSION_1_1) { 683 /* Enabled_subtag pbm */ 684 SCACHE_ALLOC_SIZE_INCR(*alloc_sz, sizeof(pbmp_t)); 685 /* Enabled_linkphy pbm */ 686 SCACHE_ALLOC_SIZE_INCR(*alloc_sz, sizeof(pbmp_t)); 687 } 688 689 690 return BCM_E_NONE; 691 } 692 693 int 694 bcm_kt2_subport_wb_sync(int unit, uint16 version, uint8 **scache_ptr) 695 { 696 int index, value; 697 uint16 value16; 698 int subport_group_max = SOC_INFO(unit).subport_group_max; 699 int pp_port_index_max = SOC_INFO(unit).pp_port_index_max; 700 uint32 _scache_ofst_ = 0; 701 702 SCACHE_BYTE_INIT(*scache_ptr); 703 704 /* Num subport groups */ 705 value = _bcm_subport_group_count[unit]; 706 SCACHE_BYTE_COPY(*scache_ptr, &value, sizeof(int)); 707 708 /* Num pp ports */ 709 value = _bcm_subport_pp_port_count[unit]; 710 SCACHE_BYTE_COPY(*scache_ptr, &value, sizeof(int)); 711 712 /* Subport-group bitmap */ 713 SCACHE_BYTE_COPY(*scache_ptr, _bcm_subport_group_bitmap[unit], 714 SHR_BITALLOCSIZE(subport_group_max)); 715 716 /* Subport pp_port bitmap */ 717 SCACHE_BYTE_COPY(*scache_ptr, _bcm_subport_pp_port_bitmap[unit], 718 SHR_BITALLOCSIZE(pp_port_index_max + 1)); 719 720 if (BCM_PBMP_NOT_NULL(SOC_INFO(unit).subtag_allowed_pbm)) { 721 /* Num subtag groups */ 722 value = _bcm_subtag_subport_group_count[unit]; 723 SCACHE_BYTE_COPY(*scache_ptr, &value, sizeof(int)); 724 725 /* Subtag group bitmap */ 726 SCACHE_BYTE_COPY(*scache_ptr, _bcm_subtag_group_bitmap[unit], 727 SHR_BITALLOCSIZE(subport_group_max)); 728 729 /* pp_port to subport group info */ 730 for (index = 0; index < SOC_MAX_NUM_PP_PORTS; index++) { 731 SCACHE_BYTE_COPY(*scache_ptr, 732 &(_bcm_subtag_subport_port_info[unit][index].group), 733 sizeof(bcm_gport_t)); 734 } 735 } 736 737 if (BCM_PBMP_NOT_NULL(SOC_INFO(unit).linkphy_allowed_pbm)) { 738 /* Num linkphy group */ 739 value = _bcm_linkphy_subport_group_count[unit]; 740 SCACHE_BYTE_COPY(*scache_ptr, &value, sizeof(int)); 741 742 /* linkphy group bitmap */ 743 SCACHE_BYTE_COPY(*scache_ptr, _bcm_linkphy_group_bitmap[unit], 744 SHR_BITALLOCSIZE(subport_group_max)); 745 746 /* linkphy subports info */ 747 for (index = 0; index < SOC_MAX_NUM_PP_PORTS; index++) { 748 value = _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, index); 749 SCACHE_BYTE_COPY(*scache_ptr, &value, sizeof(bcm_gport_t)); 750 751 value16 = _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, index); 752 SCACHE_BYTE_COPY(*scache_ptr, &value16, sizeof(uint16)); 753 754 value16 = 755 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_NUM_STREAMS_GET(unit, index); 756 SCACHE_BYTE_COPY(*scache_ptr, &value16, sizeof(uint16)); 757 758 value16 = 759 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_EXT_STREAM_ID_GET(unit, 760 index, 0); 761 SCACHE_BYTE_COPY(*scache_ptr, &value16, sizeof(uint16)); 762 763 value16 = 764 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_EXT_STREAM_ID_GET(unit, 765 index, 1); 766 SCACHE_BYTE_COPY(*scache_ptr, &value16, sizeof(uint16)); 767 768 } 769 } 770 771 if (version >= BCM_SUBPORT_WB_VERSION_1_1) { 772 SCACHE_BYTE_COPY(*scache_ptr, &(SOC_INFO(unit).enabled_subtag_pp_port_pbm), 773 sizeof(pbmp_t)); 774 SCACHE_BYTE_COPY(*scache_ptr, &(SOC_INFO(unit).enabled_linkphy_pp_port_pbm), 775 sizeof(pbmp_t)); 776 } 777 778 return BCM_E_NONE; 779 } 780 781 /* Function: 782 * bcm_kt2_port_control_subtag_linkphy_pbm_recover 783 * Description: 784 * Retrieve the subtag_pbm from hw to SOC_INFO->subtag_pbm 785 * Parameters: 786 * unit - (IN) Device number 787 * Return Value: 788 * BCM_E_XXX 789 */ 790 791 int bcm_kt2_port_control_subtag_linkphy_pbm_recover(int unit) 792 { 793 int rv = BCM_E_NONE; 794 soc_mem_t mem; 795 soc_info_t *si = &SOC_INFO(unit); 796 ing_physical_port_table_entry_t ing_physical_port_entry; 797 bcm_port_t port; 798 799 if (!soc_feature(unit, soc_feature_subtag_coe)) { 800 return rv; 801 } 802 803 mem = ING_PHYSICAL_PORT_TABLEm; 804 805 _BCM_KT2_SUBPORT_LOCK(unit); 806 807 BCM_PBMP_ITER(PBMP_ALL(unit), port) { 808 809 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port, 810 &ing_physical_port_entry); 811 if (SOC_FAILURE(rv)) { 812 LOG_ERROR(BSL_LS_BCM_SUBPORT, 813 (BSL_META_U(unit, 814 "ERROR:ING_PHYSICAL_PORT_TABLEm read failed\n"))); 815 _BCM_KT2_SUBPORT_UNLOCK(unit); 816 return rv; 817 } 818 if (soc_mem_field32_get(unit, mem, &ing_physical_port_entry, 819 PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED) { 820 if (soc_mem_field32_get(unit, mem, &ing_physical_port_entry, 821 CASCADED_PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED_SUBTAG) { 822 BCM_PBMP_PORT_ADD(si->subtag_pbm, port); 823 BCM_PBMP_PORT_ADD(si->subtag.bitmap, port); 824 } else if (soc_mem_field32_get(unit, mem, &ing_physical_port_entry, 825 CASCADED_PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED_LINKPHY) { 826 BCM_PBMP_PORT_ADD(si->linkphy_pbm, port); 827 BCM_PBMP_PORT_ADD(si->lp.bitmap, port); 828 } 829 } 830 } 831 832 _BCM_KT2_SUBPORT_UNLOCK(unit); 833 834 return rv; 835 } 836 837 838 839 840 int 841 bcm_kt2_subport_wb_recover(int unit, uint16 version, uint8 **scache_ptr) 842 { 843 bcm_gport_t group; 844 int length, pp_port, index, rv = BCM_E_NONE; 845 int subport_group_max = SOC_INFO(unit).subport_group_max; 846 int pp_port_index_max = SOC_INFO(unit).pp_port_index_max; 847 uint32 _scache_ofst_ = 0; 848 soc_info_t *si = &SOC_INFO(unit); 849 850 SCACHE_BYTE_INIT(*scache_ptr); 851 852 /* Recover subtag_pbm from hw */ 853 rv = bcm_kt2_port_control_subtag_linkphy_pbm_recover(unit); 854 SOC_IF_ERROR_RETURN(rv); 855 856 /* Num subport groups */ 857 SCACHE_BYTE_RESTORE(*scache_ptr, 858 &_bcm_subport_group_count[unit], sizeof(int)); 859 860 /* Num pp ports */ 861 SCACHE_BYTE_RESTORE(*scache_ptr, 862 &_bcm_subport_pp_port_count[unit], sizeof(int)); 863 864 /* Subport group bitmap */ 865 SCACHE_BYTE_RESTORE(*scache_ptr, 866 _bcm_subport_group_bitmap[unit], 867 SHR_BITALLOCSIZE(subport_group_max)); 868 869 870 /* Subport pp_port bitmap */ 871 SCACHE_BYTE_RESTORE(*scache_ptr, 872 _bcm_subport_pp_port_bitmap[unit], 873 SHR_BITALLOCSIZE(pp_port_index_max + 1)); 874 875 876 if (BCM_PBMP_NOT_NULL(SOC_INFO(unit).subtag_allowed_pbm)) { 877 soc_mem_t mem; 878 int start, end; 879 subport_tag_to_pp_port_map_entry_t entry; 880 881 /* Num subtag groups */ 882 SCACHE_BYTE_RESTORE(*scache_ptr, 883 &_bcm_subtag_subport_group_count[unit], sizeof(int)); 884 885 /* Subtag group bitmap */ 886 SCACHE_BYTE_RESTORE(*scache_ptr, 887 _bcm_subtag_group_bitmap[unit], 888 SHR_BITALLOCSIZE(subport_group_max)); 889 890 mem = SUBPORT_TAG_TO_PP_PORT_MAPm; 891 start = soc_mem_index_min(unit, mem); 892 end = soc_mem_index_max(unit, mem); 893 894 length = sizeof(bcm_gport_t); 895 for (index = start; index <= end; index++) { 896 897 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, &entry); 898 SOC_IF_ERROR_RETURN(rv); 899 900 if (soc_mem_field32_get(unit, mem, &entry, VALIDf)) { 901 902 pp_port = soc_mem_field32_get(unit, mem, &entry, PP_PORTf); 903 sal_memcpy(&group, (*scache_ptr + (pp_port * length)), length); 904 905 _BCM_KT2_SUBPORT_PP_PORT_USED_SET(unit, pp_port); 906 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_SET(unit, pp_port, group, 907 soc_mem_field32_get(unit, mem, &entry, SUBPORT_TAGf), 908 index, TRUE); 909 910 _BCM_KT2_SUBTAG_VLAN_ID_USED_SET(unit, 911 soc_mem_field32_get(unit, mem, &entry, PHYSICAL_PORTf), 912 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VLAN_GET(unit, pp_port)); 913 914 _bcm_subport_group_subport_port_count[unit] 915 [_BCM_KT2_SUBPORT_GROUP_ID_GET(group)] += 1; 916 } 917 } 918 *scache_ptr += (length * SOC_MAX_NUM_PP_PORTS); 919 } 920 921 if (BCM_PBMP_NOT_NULL(SOC_INFO(unit).linkphy_allowed_pbm)) { 922 uint16 valid = 0, num_streams = 0; 923 uint16 stream_id_1 = 0, stream_id_2 = 0; 924 925 /* Num linkphy groups */ 926 SCACHE_BYTE_RESTORE(*scache_ptr, 927 &_bcm_linkphy_subport_group_count[unit], sizeof(int)); 928 929 /* linkphy group bitmap */ 930 SCACHE_BYTE_RESTORE(*scache_ptr, 931 _bcm_linkphy_group_bitmap[unit], 932 SHR_BITALLOCSIZE(subport_group_max)); 933 934 935 /* linkphy subport info */ 936 for (index = 0; index < SOC_MAX_NUM_PP_PORTS; index++) { 937 SCACHE_BYTE_RESTORE(*scache_ptr, 938 &group, sizeof(bcm_gport_t)); 939 940 SCACHE_BYTE_RESTORE(*scache_ptr, 941 &valid, sizeof(uint16)); 942 943 SCACHE_BYTE_RESTORE(*scache_ptr, 944 &num_streams, sizeof(uint16)); 945 946 SCACHE_BYTE_RESTORE(*scache_ptr, 947 &stream_id_1, sizeof(uint16)); 948 949 SCACHE_BYTE_RESTORE(*scache_ptr, 950 &stream_id_2, sizeof(uint16)); 951 952 953 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_SET(unit, index, group, 954 num_streams, valid); 955 _bcm_linkphy_subport_port_info[unit][index].ext_stream_idx[0] = 956 stream_id_1; 957 if (num_streams > 1) { 958 _bcm_linkphy_subport_port_info[unit][index].ext_stream_idx[1] = 959 stream_id_2; 960 } 961 962 if (valid) { 963 int rv; 964 bcm_port_t port; 965 uint16 dev_int_stream_id_1 = 0, dev_int_stream_id_2 = 0; 966 uint16 int_stream_id_base = 0, ext_stream_id_base = 0; 967 uint16 port_e_stream_id_base_adj_1 = 0; 968 uint16 port_e_stream_id_base_adj_2 = 0; 969 uint16 blk_i_stream_id_1 = 0; 970 uint16 blk_i_stream_id_2 = 0; 971 uint16 blk_port_idx_i_stream_id_1 = 0; 972 uint16 blk_port_idx_i_stream_id_2 = 0; 973 uint16 dev_int_stream_id_base = 0; 974 port = ((group >> _BCM_KT2_SUBPORT_GROUP_PORT_SHIFT) & 975 _BCM_KT2_SUBPORT_GROUP_PORT_MASK); 976 977 rv = _bcm_linkphy_port_int_stream_id_base_get(unit, port, 978 &int_stream_id_base); 979 BCM_IF_ERROR_RETURN(rv); 980 981 rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, port, 982 &ext_stream_id_base); 983 BCM_IF_ERROR_RETURN(rv); 984 985 port_e_stream_id_base_adj_1 = stream_id_1 - ext_stream_id_base; 986 987 if (num_streams > 1) { 988 port_e_stream_id_base_adj_2 = stream_id_2 - ext_stream_id_base; 989 } 990 991 BCM_IF_ERROR_RETURN( 992 _bcm_linkphy_port_rx_int_stream_map_port_get(unit, port, 993 port_e_stream_id_base_adj_1, 994 &blk_i_stream_id_1)); 995 if (num_streams > 1) { 996 BCM_IF_ERROR_RETURN( 997 _bcm_linkphy_port_rx_int_stream_map_port_get(unit, port, 998 port_e_stream_id_base_adj_2, 999 &blk_i_stream_id_2)); 1000 } 1001 1002 #if defined(BCM_METROLITE_SUPPORT) 1003 if (SOC_IS_METROLITE(unit)) { 1004 /* Index for _bcm_ml_int_stream_id_pool runs from 0 to 3, 1005 * whereas port runs from 1 to 4. Hence doing port -1 1006 * to index the pool 1007 */ 1008 /* Reserve those internal streams in that port's pool. */ 1009 BCM_IF_ERROR_RETURN(shr_idxres_list_reserve( 1010 _bcm_ml_int_stream_id_pool[unit][port-1], 1011 blk_i_stream_id_1, blk_i_stream_id_1)); 1012 if (num_streams > 1) { 1013 BCM_IF_ERROR_RETURN(shr_idxres_list_reserve( 1014 _bcm_ml_int_stream_id_pool[unit][port-1], 1015 blk_i_stream_id_2, blk_i_stream_id_2)); 1016 } 1017 } else 1018 #endif 1019 #if defined(BCM_SABER2_SUPPORT) 1020 if (SOC_IS_SABER2(unit)) { 1021 /* Index for _bcm_sb2_int_stream_id_pool runs from 0 to 3, 1022 * whereas port runs from 1 to 4. Hence doing port -1 1023 * to index the pool 1024 */ 1025 /* Reserve those internal streams in that port's pool. */ 1026 BCM_IF_ERROR_RETURN(shr_idxres_list_reserve( 1027 _bcm_sb2_int_stream_id_pool[unit][port-1], 1028 blk_i_stream_id_1, blk_i_stream_id_1)); 1029 if (num_streams > 1) { 1030 BCM_IF_ERROR_RETURN(shr_idxres_list_reserve( 1031 _bcm_sb2_int_stream_id_pool[unit][port-1], 1032 blk_i_stream_id_2, blk_i_stream_id_2)); 1033 } 1034 } else 1035 #endif 1036 { 1037 int lp_block, lp_index; 1038 /* get the block and index for the LinkPHY memory */ 1039 rv = soc_linkphy_port_blk_idx_get(unit, port, 1040 &lp_block, &lp_index); 1041 if (BCM_FAILURE(rv)) { 1042 LOG_ERROR(BSL_LS_BCM_SUBPORT, 1043 (BSL_META_U(unit, 1044 "ERROR: LinkPHY block, index get failed " 1045 "for port %d\n"), port)); 1046 return rv; 1047 } 1048 dev_int_stream_id_base = (lp_block)? 128: 0; 1049 blk_port_idx_i_stream_id_1 = blk_i_stream_id_1 - 1050 (si->port_linkphy_s1_base[port] 1051 - dev_int_stream_id_base); 1052 BCM_IF_ERROR_RETURN(shr_idxres_list_reserve( 1053 _bcm_kt2_blk_int_stream_id_pool[unit][lp_block] 1054 [lp_index], 1055 blk_port_idx_i_stream_id_1, blk_port_idx_i_stream_id_1)); 1056 if (num_streams > 1) { 1057 blk_port_idx_i_stream_id_2 = blk_i_stream_id_2 - 1058 (si->port_linkphy_s1_base[port] 1059 - dev_int_stream_id_base); 1060 BCM_IF_ERROR_RETURN(shr_idxres_list_reserve( 1061 _bcm_kt2_blk_int_stream_id_pool[unit][lp_block] 1062 [lp_index], 1063 blk_port_idx_i_stream_id_2, 1064 blk_port_idx_i_stream_id_2)); 1065 } 1066 } 1067 1068 dev_int_stream_id_1 = blk_i_stream_id_1 + int_stream_id_base; 1069 if (num_streams > 1) { 1070 dev_int_stream_id_2 = blk_i_stream_id_2 + 1071 int_stream_id_base; 1072 } 1073 1074 _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_SET(unit, 1075 dev_int_stream_id_1); 1076 if (num_streams > 1) { 1077 _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_SET(unit, 1078 dev_int_stream_id_2); 1079 } 1080 1081 _bcm_subport_group_subport_port_count[unit] 1082 [_BCM_KT2_SUBPORT_GROUP_ID_GET(group)] += 1; 1083 } 1084 } 1085 } 1086 1087 if (version >= BCM_SUBPORT_WB_VERSION_1_1) { 1088 SCACHE_BYTE_RESTORE(*scache_ptr, 1089 &(si->enabled_subtag_pp_port_pbm), sizeof(pbmp_t)); 1090 SCACHE_BYTE_RESTORE(*scache_ptr, 1091 &(si->enabled_linkphy_pp_port_pbm), sizeof(pbmp_t)); 1092 } 1093 return BCM_E_NONE; 1094 } 1095 1096 1097 #endif /* BCM_WARM_BOOT_SUPPORT */ 1098 1099 /* prototypes - end */ 1100 1101 1102 /*********************************** 1103 * LinkPHY helper functions - start * 1104 */ 1105 1106 STATIC int 1107 _bcm_linkphy_reg_mac_addr_set(int unit, bcm_port_t port, 1108 soc_reg_t reg, soc_field_t field, 1109 bcm_mac_t mac) 1110 { 1111 uint64 val, tmp, regval; 1112 int i; 1113 1114 COMPILER_64_ZERO(val); 1115 COMPILER_64_ZERO(tmp); 1116 COMPILER_64_ZERO(regval); 1117 1118 for (i = 0; i < 6; i++) { 1119 COMPILER_64_SET(tmp, 0, mac[i]); 1120 COMPILER_64_SHL(val, 8); 1121 COMPILER_64_OR(val, tmp); 1122 } 1123 BCM_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, ®val)); 1124 soc_reg64_field_set(unit, reg, ®val, field, val); 1125 return soc_reg_set(unit, reg, port, 0, regval); 1126 } 1127 1128 STATIC int 1129 _bcm_linkphy_reg_mac_addr_get(int unit, bcm_port_t port, 1130 soc_reg_t reg, soc_field_t field, 1131 bcm_mac_t mac) 1132 { 1133 uint64 regval, data; 1134 uint32 msw; 1135 uint32 lsw; 1136 1137 COMPILER_64_ZERO(data); 1138 COMPILER_64_ZERO(regval); 1139 1140 BCM_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, ®val)); 1141 data = soc_reg64_field_get(unit, reg, regval, field); 1142 COMPILER_64_TO_32_HI(msw, data); 1143 COMPILER_64_TO_32_LO(lsw, data); 1144 1145 mac[0] = (uint8) ( ( msw & 0x0000ff00 ) >> 8 ); 1146 mac[1] = (uint8) ( msw & 0x000000ff ); 1147 1148 mac[2] = (uint8) ( ( lsw & 0xff000000) >> 24 ); 1149 mac[3] = (uint8) ( ( lsw & 0x00ff0000) >> 16 ); 1150 mac[4] = (uint8) ( ( lsw & 0x0000ff00) >> 8 ); 1151 mac[5] = (uint8) ( lsw & 0x000000ff ); 1152 1153 return BCM_E_NONE; 1154 } 1155 1156 int 1157 _bcm_linkphy_port_ext_stream_id_base_get(int unit, 1158 bcm_port_t port, 1159 uint16 *ext_stream_id_base) 1160 { 1161 uint32 regval = 0; 1162 soc_reg_t reg = RXLP_PORT_STREAM_ID_BASEr; 1163 if (SOC_REG_PORT_VALID(unit, reg, port)) { 1164 SOC_IF_ERROR_RETURN( 1165 READ_RXLP_PORT_STREAM_ID_BASEr(unit, port, ®val)); 1166 *ext_stream_id_base = soc_reg_field_get(unit, reg, regval, BASEf); 1167 } 1168 return BCM_E_NONE; 1169 } 1170 1171 int 1172 _bcm_linkphy_port_int_stream_id_base_get(int unit, 1173 bcm_port_t port, 1174 uint16 *int_stream_id_base) 1175 { 1176 uint32 regval = 0; 1177 soc_reg_t reg = RXLP_INT_STREAM_ID_BASEr; 1178 if (SOC_REG_PORT_VALID(unit, reg, port)) { 1179 SOC_IF_ERROR_RETURN(READ_RXLP_INT_STREAM_ID_BASEr(unit, port, ®val)); 1180 *int_stream_id_base = soc_reg_field_get(unit, reg, regval, BASEf); 1181 } 1182 return BCM_E_NONE; 1183 } 1184 1185 int soc_linkphy_port_blk_idx_get( 1186 int unit, int port, int *block, int *index) { 1187 #if defined(BCM_METROLITE_SUPPORT) 1188 if (SOC_IS_METROLITE(unit)) { 1189 SOC_IF_ERROR_RETURN( 1190 soc_ml_linkphy_port_blk_idx_get(unit, port, block, index)); 1191 } else 1192 #endif 1193 #if defined(BCM_SABER2_SUPPORT) 1194 if(SOC_IS_SABER2(unit)) { 1195 SOC_IF_ERROR_RETURN( 1196 soc_sb2_linkphy_port_blk_idx_get(unit, port, block, index)); 1197 } else 1198 #endif 1199 if (SOC_IS_KATANA2(unit)) { 1200 SOC_IF_ERROR_RETURN( 1201 soc_kt2_linkphy_port_blk_idx_get(unit, port, block, index)); 1202 } 1203 return SOC_E_NONE; 1204 } 1205 1206 /* 1207 * Set or clear the valid streams on a sub-port of a port-interface 1208 * in a bitmap format. 1209 * Each bit set indicates that SID being part of that port. 1210 * Note that same stream cannot be enabled on more than one sub-port. 1211 * When the port is in LP-mode, then Stream-ID for that sub-port is 1212 * in Range [0-127] only. 1213 * Sub-ports cannot be dyncamically changed to LP->NonLP and vice-versa 1214 * without resetting the entire block. 1215 * However in LP-mode, streams could get added dynamically to a port. 1216 */ 1217 1218 STATIC int 1219 _bcm_linkphy_port_tx_active_stream_set(int unit, 1220 bcm_port_t port, 1221 uint16 int_stream_id, 1222 int enable) 1223 { 1224 soc_mem_t mem; 1225 int rv = BCM_E_NONE, lp_index = 0, lp_block = 0, copyno = 0; 1226 int field_word = 0, bit_pos = 0; 1227 uint32 fldbuf[4] = { 0 }; 1228 txlp_port_stream_bitmap_table_entry_t txlp_port_stream_bitmap; 1229 1230 /* Set Active Stream ID 1231 * Use TXLP_PORT_STREAM_BITMAP_TABLE 1232 * This is a per-LP block, per-LP port memory. 1233 * KT2 has 2 LP block and 4 LP ports per LP block 1234 */ 1235 1236 mem = TXLP_PORT_STREAM_BITMAP_TABLEm; 1237 if (SOC_MEM_FIELD_VALID(unit, mem, STREAM_BITMAPf)) { 1238 /* get the block and index for the LinkPHY memory */ 1239 rv = soc_linkphy_port_blk_idx_get(unit, port, &lp_block, &lp_index); 1240 if (SOC_FAILURE(rv)) { 1241 LOG_ERROR(BSL_LS_BCM_SUBPORT, 1242 (BSL_META_U(unit, 1243 1244 "ERROR: LinkPHY block, index get failed for port %d\n"), port)); 1245 return rv; 1246 } 1247 1248 copyno = SOC_MEM_BLOCK_ANY(unit, mem) + lp_block; 1249 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, copyno, lp_index, 1250 &txlp_port_stream_bitmap)); 1251 soc_mem_field_get(unit, mem, (uint32 *)&txlp_port_stream_bitmap, 1252 STREAM_BITMAPf, fldbuf); 1253 1254 field_word = int_stream_id / 32; 1255 bit_pos = int_stream_id % 32; 1256 if (enable) { 1257 fldbuf[field_word] |= (1 << bit_pos); 1258 } else { 1259 fldbuf[field_word] &= ~(1 << bit_pos); 1260 } 1261 soc_mem_field_set(unit, mem, (uint32 *)&txlp_port_stream_bitmap, 1262 STREAM_BITMAPf, fldbuf); 1263 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, copyno, 1264 lp_index, &txlp_port_stream_bitmap)); 1265 } 1266 1267 return rv; 1268 } 1269 1270 /* Map the Internal-SID(7b) to External-SID(10b) */ 1271 STATIC int 1272 _bcm_linkphy_port_tx_int_to_ext_stream_map_set(int unit, 1273 int port, 1274 uint16 ext_stream_id, 1275 uint16 int_stream_id, 1276 int enable) 1277 { 1278 int rv = BCM_E_NONE; 1279 soc_mem_t mem; 1280 int copyno = 0, lp_block = 0, lp_index = 0; 1281 txlp_int2ext_stream_map_table_entry_t txlp_int2ext_stream_map; 1282 1283 /* Map Internal Stream ID to External Stream ID 1284 * Use TXLP_INT2EXT_STREAM_MAP_TABLE table 1285 * This is a per-LP block memory 1286 */ 1287 mem = TXLP_INT2EXT_STREAM_MAP_TABLEm; 1288 if (SOC_MEM_FIELD_VALID(unit, mem, EXTERNAL_SIDf)) { 1289 /* get the block and index for the LinkPHY memory */ 1290 rv = soc_linkphy_port_blk_idx_get(unit,port, 1291 &lp_block, &lp_index); 1292 if (SOC_FAILURE(rv)) { 1293 LOG_ERROR(BSL_LS_BCM_SUBPORT, 1294 (BSL_META_U(unit, 1295 1296 "ERROR: LinkPHY block, index get failed for port %d\n"), port)); 1297 return rv; 1298 } 1299 sal_memset(&txlp_int2ext_stream_map, 0, 1300 sizeof(txlp_int2ext_stream_map_table_entry_t)); 1301 1302 copyno = SOC_MEM_BLOCK_ANY(unit, mem) + lp_block; 1303 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, copyno, int_stream_id, 1304 &txlp_int2ext_stream_map)); 1305 soc_mem_field32_set(unit, mem, (uint32 *)&txlp_int2ext_stream_map, 1306 VALIDf, (enable) ? 1 : 0); 1307 soc_mem_field32_set(unit, mem, (uint32 *)&txlp_int2ext_stream_map, 1308 EXTERNAL_SIDf, (enable) ? (uint32)ext_stream_id : 0); 1309 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, copyno, int_stream_id, 1310 &txlp_int2ext_stream_map)); 1311 } 1312 1313 return rv; 1314 } 1315 1316 STATIC int 1317 _bcm_linkphy_subport_index_to_phyport_get(int unit, 1318 bcm_port_t port, 1319 uint32 subport_index, 1320 uint32 *phy_port) 1321 { 1322 uint8 block; 1323 1324 /* Input Param Check */ 1325 if (phy_port == NULL) { 1326 return BCM_E_INTERNAL; 1327 } 1328 1329 /* Retreive physical port from subport index provided */ 1330 #if defined(BCM_METROLITE_SUPPORT) 1331 if (SOC_IS_METROLITE(unit)) { 1332 BCM_IF_ERROR_RETURN(soc_metrolite_get_port_block(unit, port, &block)); 1333 if (ml_block_ports[unit] == NULL) { 1334 return BCM_E_INTERNAL; 1335 } 1336 *phy_port = (*ml_block_ports[unit])[block][subport_index]; 1337 } else 1338 #endif 1339 #if defined(BCM_SABER2_SUPPORT) 1340 if (SOC_IS_SABER2(unit)) { 1341 BCM_IF_ERROR_RETURN(soc_saber2_get_port_block(unit, port, &block)); 1342 if (sb2_block_ports[unit] == NULL) { 1343 return BCM_E_INTERNAL; 1344 } 1345 *phy_port =(*sb2_block_ports[unit])[block][subport_index]; 1346 } else 1347 #endif 1348 { 1349 BCM_IF_ERROR_RETURN(soc_katana2_get_port_mxqblock(unit, port, &block)); 1350 if (kt2_mxqblock_ports[unit] == NULL) { 1351 return BCM_E_INTERNAL; 1352 } 1353 *phy_port = (*kt2_mxqblock_ports[unit])[block][subport_index]; 1354 } 1355 1356 return BCM_E_NONE; 1357 } 1358 1359 STATIC int 1360 _bcm_linkphy_port_tx_int_to_ext_stream_map_get(int unit, 1361 int port, 1362 uint16 int_stream_id, 1363 uint16 *ext_stream_id) 1364 { 1365 int rv = BCM_E_NONE; 1366 soc_mem_t mem; 1367 int copyno = 0, lp_block = 0, lp_index = 0; 1368 txlp_int2ext_stream_map_table_entry_t txlp_int2ext_stream_map; 1369 int valid = 0; 1370 1371 /* Map Internal Stream ID to External Stream ID 1372 * Use TXLP_INT2EXT_STREAM_MAP_TABLE table 1373 * This is a per-LP block memory 1374 */ 1375 mem = TXLP_INT2EXT_STREAM_MAP_TABLEm; 1376 if (SOC_MEM_FIELD_VALID(unit, mem, EXTERNAL_SIDf)) { 1377 /* get the block and index for the LinkPHY memory */ 1378 rv = soc_linkphy_port_blk_idx_get(unit,port, 1379 &lp_block, &lp_index); 1380 if (SOC_FAILURE(rv)) { 1381 LOG_ERROR(BSL_LS_BCM_SUBPORT, 1382 (BSL_META_U(unit, 1383 "ERROR: LinkPHY block, index get failed for port %d rv %d\n"), port, rv)); 1384 return rv; 1385 } 1386 sal_memset(&txlp_int2ext_stream_map, 0, 1387 sizeof(txlp_int2ext_stream_map_table_entry_t)); 1388 1389 copyno = SOC_MEM_BLOCK_ANY(unit, mem) + lp_block; 1390 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, copyno, int_stream_id, 1391 &txlp_int2ext_stream_map)); 1392 valid = soc_mem_field32_get(unit, mem, &txlp_int2ext_stream_map, 1393 VALIDf); 1394 if (valid) { 1395 *ext_stream_id = soc_mem_field32_get(unit, mem, 1396 &txlp_int2ext_stream_map, 1397 EXTERNAL_SIDf); 1398 } else { 1399 return BCM_E_NOT_FOUND; 1400 } 1401 } 1402 1403 return rv; 1404 } 1405 /* 1406 * Function for buffer allocation for the streams of LP-ENABLED ports. 1407 * 1408 * End address Range = [11-3423]. 1409 * Starting address Range = [0-3420]. 1410 * Note that [END-START+1] must be an integral multiple of "4". 1411 * 1412 * 856-cell worth of storage is available in the TXL-DATA-BUFFER. 1413 * 856 cells have to be distributed across: 1414 * 1. All the streams of LP-ENABLED ports, 1415 * 2. Non-LP ports. 1416 * 1417 * A cell=384B(4-lines of 96B). Hence Depth = 856 * 4 = 3424 lines. 1418 * Following are the rules of how to configure space for each STREAM:: 1419 * 1. Each active STREAM on an LP-PORT can be allocated utmost "N" cells, 1420 * 2. "N" is an integer and [2* <= N <= 64] 1421 * 3. Each STREAM is provided with a [start,end] pointer pairs. 1422 * 4. Space for each STREAM = [end-start+1] lines of buffer. 1423 * 5. As each cell-occupies "4" lines in buffer, 1424 * [end-start+1] must be a integral multiple of "4". 1425 * 6. The addresses must be configured linearly from "0" till "3423". 1426 * 7. Wrap-around not supported. 1427 * 8. END must be always greater than START. 1428 * 9. If a stream is INACTIVE start=end=0. 1429 * 10. This configuration has to be done before "enabling" the STREAM. 1430 * NOTE: There has to be a minimum of "2" cell allocation 1431 * for a stream to function. If we allocate only "1" cell, 1432 * there is potential that stream will be stuck. 1433 * 1434 * Following are the guidelines to configure number of cells/STREAM:: 1435 * The Line-rate is gaurenteed when below guidelines are adhered to. 1436 * 1437 * In LP-Mode: 1438 * =========== 1439 * Stream-Speed(Gbps) | Min Num.Cells 1440 * < 1G | 3 1441 * 1G | 6 1442 * 10G | 50 1443 * 1444 * In Non-LP-Mode: 1445 * =============== 1446 * DONOT PROGRAM. 1447 */ 1448 1449 STATIC int 1450 _bcm_linkphy_port_tx_stream_addr_map_set(int unit, 1451 int port, 1452 uint16 int_stream_id, 1453 uint32 start_addr, 1454 uint32 end_addr, 1455 int enable) 1456 { 1457 int rv = BCM_E_NONE; 1458 int copyno = 0, lp_block = 0, lp_index = 0; 1459 soc_mem_t mem; 1460 txlp_stream_addr_map_table_entry_t txlp_stream_addr_map; 1461 uint32 max_start_addr = SOC_INFO(unit).lp_tx_databuf_start_addr_max; 1462 uint32 min_end_addr = SOC_INFO(unit).lp_tx_databuf_end_addr_min; 1463 uint32 max_end_addr = SOC_INFO(unit).lp_tx_databuf_end_addr_max; 1464 1465 mem = TXLP_STREAM_ADDR_MAP_TABLEm; 1466 1467 if (SOC_MEM_FIELD_VALID(unit, mem, START_ADDRf)) { 1468 if (enable) { 1469 if ((start_addr > max_start_addr) || 1470 (end_addr < min_end_addr) || 1471 (end_addr > max_end_addr)) { 1472 return BCM_E_PARAM; 1473 } 1474 1475 if ((end_addr - start_addr + 1) % 4) { 1476 LOG_ERROR(BSL_LS_BCM_SUBPORT, 1477 (BSL_META_U(unit, 1478 "ERROR:for TX data buffer allocation [END-START+1] " 1479 "should be multiple of 4. \n(start =%d, end = %d)" 1480 "for port = %d, int_stream_id = %d\n"), 1481 start_addr, end_addr, 1482 port, int_stream_id)); 1483 return BCM_E_PARAM; 1484 } 1485 } else { 1486 start_addr = 0; 1487 end_addr = 0; 1488 } 1489 1490 /* get the block and index for the LinkPHY memory */ 1491 rv = soc_linkphy_port_blk_idx_get(unit,port, 1492 &lp_block, &lp_index); 1493 if (SOC_FAILURE(rv)) { 1494 LOG_ERROR(BSL_LS_BCM_SUBPORT, 1495 (BSL_META_U(unit, 1496 "ERROR: LinkPHY block, index get failed for port %d\n"), 1497 port)); 1498 return rv; 1499 } 1500 1501 sal_memset(&txlp_stream_addr_map, 0, 1502 sizeof(txlp_stream_addr_map_table_entry_t)); 1503 1504 copyno = SOC_MEM_BLOCK_ANY(unit, mem) + lp_block; 1505 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, copyno, int_stream_id, 1506 &txlp_stream_addr_map)); 1507 1508 soc_mem_field32_set(unit, mem, (uint32 *)&txlp_stream_addr_map, 1509 START_ADDRf, enable ? start_addr : 0); 1510 1511 soc_mem_field32_set(unit, mem, (uint32 *)&txlp_stream_addr_map, 1512 END_ADDRf, enable ? end_addr : 0); 1513 1514 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, copyno, int_stream_id, 1515 &txlp_stream_addr_map)); 1516 } 1517 1518 return rv; 1519 } 1520 1521 STATIC int 1522 _bcm_linkphy_port_rx_flow_control_set(int unit, 1523 int port, 1524 uint16 int_stream_id, 1525 int enable) 1526 { 1527 soc_reg_t reg; 1528 int rv = BCM_E_NONE, reg_hi = 0, stream_bit = 0; 1529 uint64 rval64, data, bit_pos; 1530 1531 COMPILER_64_ZERO(rval64); 1532 COMPILER_64_ZERO(data); 1533 COMPILER_64_ZERO(bit_pos); 1534 1535 reg_hi = int_stream_id / 64; 1536 stream_bit = int_stream_id % 64; 1537 1538 reg = (reg_hi) ? RXLP_DFC_STATUS_CPU_UPDATE_ENABLE_HIr : 1539 RXLP_DFC_STATUS_CPU_UPDATE_ENABLE_LOr; 1540 1541 if (SOC_REG_IS_VALID(unit, reg)) { 1542 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 1543 1544 data = soc_reg64_field_get(unit, reg, rval64, DFC_STATUS_CPU_WRITE_ENf); 1545 if (!enable) { 1546 if (!COMPILER_64_BITTEST(data, stream_bit)) { 1547 COMPILER_64_SET(bit_pos, 0, 1); 1548 COMPILER_64_SHL(bit_pos, stream_bit); 1549 COMPILER_64_OR(data, bit_pos); 1550 } 1551 } else { 1552 if (COMPILER_64_BITTEST(data, stream_bit)) { 1553 COMPILER_64_SET(bit_pos, 0, 1); 1554 COMPILER_64_SHL(bit_pos, stream_bit); 1555 COMPILER_64_NOT(bit_pos); 1556 COMPILER_64_AND(data,bit_pos); 1557 } 1558 } 1559 soc_reg64_field_set(unit, reg, &rval64, DFC_STATUS_CPU_WRITE_ENf, data); 1560 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 1561 } 1562 WRITE_RXLP_DFC_CPU_UPDATE_REFRESHr(unit, port, 1); 1563 reg = (reg_hi) ? RXLP_DFC_STATUS_HIr : RXLP_DFC_STATUS_LOr; 1564 1565 if (SOC_REG_IS_VALID(unit, reg)) { 1566 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 1567 1568 data = soc_reg64_field_get(unit, reg, rval64, DFC_STATUSf); 1569 1570 if (enable) { 1571 if (!COMPILER_64_BITTEST(data, stream_bit)) { 1572 COMPILER_64_SET(bit_pos, 0, 1); 1573 COMPILER_64_SHL(bit_pos, stream_bit); 1574 COMPILER_64_OR(data, bit_pos); 1575 1576 soc_reg64_field_set(unit, reg, &rval64, DFC_STATUSf, data); 1577 SOC_IF_ERROR_RETURN( 1578 soc_reg_set(unit, reg, port, 0, rval64)); 1579 } 1580 } else { 1581 if (COMPILER_64_BITTEST(data, stream_bit)) { 1582 COMPILER_64_SET(bit_pos, 0, 1); 1583 COMPILER_64_SHL(bit_pos, stream_bit); 1584 COMPILER_64_NOT(bit_pos); 1585 COMPILER_64_AND(data,bit_pos); 1586 1587 soc_reg64_field_set(unit, reg, &rval64, DFC_STATUSf, data); 1588 SOC_IF_ERROR_RETURN( 1589 soc_reg_set(unit, reg, port, 0, rval64)); 1590 } 1591 } 1592 } 1593 1594 return rv; 1595 } 1596 1597 /* Set and clear Bitmap(LSBs/MSBs) of active internal stream IDs 1598 * associated with a port. 1599 * The same internal stream ID should not be active on more than one ports 1600 */ 1601 STATIC int 1602 _bcm_linkphy_port_rx_active_stream_bitmap_set(int unit, 1603 int port, 1604 uint16 int_stream_id, 1605 int enable) 1606 { 1607 soc_reg_t reg; 1608 int rv = BCM_E_NONE, reg_hi = 0, stream_bit = 0; 1609 uint64 rval64, data, bit_pos; 1610 1611 COMPILER_64_ZERO(rval64); 1612 COMPILER_64_ZERO(data); 1613 COMPILER_64_ZERO(bit_pos); 1614 1615 reg_hi = int_stream_id / 64; 1616 stream_bit = int_stream_id % 64; 1617 1618 reg = (reg_hi) ? RXLP_PORT_ACTIVE_STREAM_BITMAP_HIr : 1619 RXLP_PORT_ACTIVE_STREAM_BITMAP_LOr; 1620 if (SOC_REG_PORT_VALID(unit, reg, port)) { 1621 1622 SOC_IF_ERROR_RETURN(soc_reg_get(unit, reg, port, 0, &rval64)); 1623 1624 data = soc_reg64_field_get(unit, reg, rval64,ACTIVE_STREAM_BITMAPf); 1625 1626 if (enable) { 1627 if (!COMPILER_64_BITTEST(data, stream_bit)) { 1628 COMPILER_64_SET(bit_pos, 0, 1); 1629 COMPILER_64_SHL(bit_pos, stream_bit); 1630 COMPILER_64_OR(data, bit_pos); 1631 1632 soc_reg64_field_set(unit, reg, &rval64, 1633 ACTIVE_STREAM_BITMAPf, data); 1634 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 1635 } 1636 } else { 1637 if (COMPILER_64_BITTEST(data, stream_bit)) { 1638 COMPILER_64_SET(bit_pos, 0, 1); 1639 COMPILER_64_SHL(bit_pos, stream_bit); 1640 COMPILER_64_NOT(bit_pos); 1641 COMPILER_64_AND(data, bit_pos); 1642 1643 soc_reg64_field_set(unit, reg, &rval64, 1644 ACTIVE_STREAM_BITMAPf, data); 1645 SOC_IF_ERROR_RETURN(soc_reg_set(unit, reg, port, 0, rval64)); 1646 } 1647 } 1648 } 1649 1650 return rv; 1651 } 1652 1653 /* Given the external stream id, 1654 * which is the (original external stream id - external stream id base), 1655 * This function will return the internal stream id mapped to it. 1656 * 1657 * 1658 * NOTE: 1659 * This internal stream id got can be added to internal stream id base 1660 * to get the device level internal stream id. 1661 */ 1662 STATIC int 1663 _bcm_linkphy_port_rx_int_stream_map_port_get(int unit, 1664 int port, 1665 uint16 ext_stream_id, 1666 uint16 *int_stream_id) 1667 { 1668 soc_mem_t mem; 1669 int rv = BCM_E_NONE, copyno = 0, lp_index = 0, lp_block = 0; 1670 rxlp_internal_stream_map_port_0_entry_t rxlp_int_stream_map_port; 1671 int rxlp_int_stream_map_port_idx = -1; 1672 int valid = 0; 1673 1674 mem = RXLP_INTERNAL_STREAM_MAP_PORT_0m; 1675 if (SOC_MEM_FIELD_VALID(unit, mem, INTERNAL_STREAM_IDf)) { 1676 /* get the block and index for the LinkPHY memory */ 1677 rv = soc_linkphy_port_blk_idx_get(unit,port, 1678 &lp_block, &lp_index); 1679 if (SOC_FAILURE(rv)) { 1680 LOG_ERROR(BSL_LS_BCM_SUBPORT, 1681 (BSL_META_U(unit, 1682 "ERROR: LinkPHY block, index get failed for port %d\n"), 1683 port)); 1684 return rv; 1685 } 1686 sal_memset(&rxlp_int_stream_map_port, 0, 1687 sizeof(rxlp_internal_stream_map_port_0_entry_t)); 1688 1689 /* 1690 * Internal stream id = 1691 * RXLP_INTERNAL_STREAM_MAP_PORTn.rxlp0/1 [Internal Stream ID]; 1692 */ 1693 switch (lp_index) { 1694 case 0: 1695 mem = RXLP_INTERNAL_STREAM_MAP_PORT_0m; 1696 break; 1697 case 1: 1698 mem = RXLP_INTERNAL_STREAM_MAP_PORT_1m; 1699 break; 1700 case 2: 1701 mem = RXLP_INTERNAL_STREAM_MAP_PORT_2m; 1702 break; 1703 case 3: 1704 mem = RXLP_INTERNAL_STREAM_MAP_PORT_3m; 1705 break; 1706 default: 1707 return SOC_E_PORT; 1708 }; 1709 copyno = SOC_MEM_BLOCK_ANY(unit, mem) + lp_block; 1710 /* The index into the rxlp_internal_stream_map_port table is 1711 * stream_id_array_value - external_stream_id_base which is 1712 * given by the passed ext_stream_id. 1713 */ 1714 rxlp_int_stream_map_port_idx = ext_stream_id; 1715 1716 1717 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, copyno, 1718 rxlp_int_stream_map_port_idx, 1719 &rxlp_int_stream_map_port)); 1720 valid = soc_mem_field32_get(unit, mem, 1721 (uint32 *)&rxlp_int_stream_map_port, VALIDf); 1722 if (valid) { 1723 *int_stream_id = soc_mem_field32_get(unit, mem, 1724 (uint32 *)&rxlp_int_stream_map_port, INTERNAL_STREAM_IDf); 1725 } 1726 else { 1727 return BCM_E_BADID; 1728 } 1729 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 1730 (BSL_META_U(unit, 1731 "rxlp_internal_stream_map_port index[%d] for port[%d] " 1732 "block_internal_stream_id[%d]\n"), 1733 rxlp_int_stream_map_port_idx, port, *int_stream_id)); 1734 } 1735 1736 return rv; 1737 } 1738 1739 1740 /* Map (External Stream ID - RXLP_PORT_STREAM_ID_BASE) 1741 * to internal stream ID in the range 0-127. 1742 * There is one copy of this table for each port. 1743 * The internal stream IDs configured in this table 1744 * should be unique across the four ports associated with the RXLP slice. 1745 */ 1746 STATIC int 1747 _bcm_linkphy_port_rx_int_stream_map_port_set(int unit, 1748 int port, 1749 uint16 ext_stream_id, 1750 uint16 int_stream_id, 1751 int enable) 1752 { 1753 soc_mem_t mem; 1754 int rv = BCM_E_NONE, copyno = 0, lp_index = 0, lp_block = 0; 1755 rxlp_internal_stream_map_port_0_entry_t rxlp_int_stream_map_port; 1756 int rxlp_int_stream_map_port_idx = -1; 1757 1758 mem = RXLP_INTERNAL_STREAM_MAP_PORT_0m; 1759 if (SOC_MEM_FIELD_VALID(unit, mem, INTERNAL_STREAM_IDf)) { 1760 /* get the block and index for the LinkPHY memory */ 1761 rv = soc_linkphy_port_blk_idx_get(unit,port, 1762 &lp_block, &lp_index); 1763 if (SOC_FAILURE(rv)) { 1764 LOG_ERROR(BSL_LS_BCM_SUBPORT, 1765 (BSL_META_U(unit, 1766 1767 "ERROR: LinkPHY block, index get failed for port %d\n"), port)); 1768 return rv; 1769 } 1770 sal_memset(&rxlp_int_stream_map_port, 0, 1771 sizeof(rxlp_internal_stream_map_port_0_entry_t)); 1772 1773 /* 1774 * Internal stream id = 1775 * RXLP_INTERNAL_STREAM_MAP_PORTn.rxlp0/1 [Internal Stream ID]; 1776 */ 1777 switch (lp_index) { 1778 case 0: 1779 mem = RXLP_INTERNAL_STREAM_MAP_PORT_0m; 1780 break; 1781 case 1: 1782 mem = RXLP_INTERNAL_STREAM_MAP_PORT_1m; 1783 break; 1784 case 2: 1785 mem = RXLP_INTERNAL_STREAM_MAP_PORT_2m; 1786 break; 1787 case 3: 1788 mem = RXLP_INTERNAL_STREAM_MAP_PORT_3m; 1789 break; 1790 default: 1791 return SOC_E_PORT; 1792 }; 1793 copyno = SOC_MEM_BLOCK_ANY(unit, mem) + lp_block; 1794 1795 /* The index into the rxlp_internal_stream_map_port table is 1796 * stream_id_array_value - external_stream_id_base which is 1797 * given by the passed ext_stream_id. 1798 */ 1799 rxlp_int_stream_map_port_idx = ext_stream_id; 1800 1801 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 1802 (BSL_META_U(unit, 1803 "rxlp_internal_stream_map_port index[%d] for port[%d] " 1804 "block_internal_stream_id[%d]\n"), 1805 rxlp_int_stream_map_port_idx, port, int_stream_id)); 1806 1807 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mem, copyno, 1808 rxlp_int_stream_map_port_idx, 1809 &rxlp_int_stream_map_port)); 1810 soc_mem_field32_set(unit, mem, 1811 (uint32 *)&rxlp_int_stream_map_port, VALIDf, 1812 (enable) ? 1 : 0); 1813 soc_mem_field32_set(unit, mem, 1814 (uint32 *)&rxlp_int_stream_map_port, INTERNAL_STREAM_IDf, 1815 (enable) ? int_stream_id : 0); 1816 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, copyno, 1817 rxlp_int_stream_map_port_idx, 1818 &rxlp_int_stream_map_port)); 1819 } 1820 1821 return rv; 1822 } 1823 1824 /* 1825 * Function: 1826 * _bcmi_linkphy_subport_ext_stream_id_in_use 1827 * Description: 1828 * Check if an external stream id is in use on 1829 * a subport group. 1830 * Parameters: 1831 * unit - (IN) Device Number 1832 * config - (IN) Subport config information 1833 * ext_stream_d - (IN) External stream id 1834 * Returns: 1835 * BCM_E_XXX 1836 */ 1837 STATIC int 1838 _bcmi_linkphy_subport_ext_stream_id_in_use(int unit, 1839 bcm_subport_config_t *config, 1840 int ext_stream_id) 1841 { 1842 int rv = BCM_E_NONE, group_id = 0, i; 1843 int pp_port = 0, subport_port; 1844 int linkphy_subport_count = 0; 1845 bcm_subport_config_t sp_config; 1846 1847 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(config->group); 1848 1849 if (!_BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_GET(unit, group_id)) { 1850 LOG_ERROR(BSL_LS_BCM_SUBPORT, 1851 (BSL_META_U(unit, 1852 "ERROR: LinkPHY subport group 0x%x not found.\n"), 1853 config->group)); 1854 return BCM_E_NOT_FOUND; 1855 } 1856 1857 linkphy_subport_count = 1858 *(_bcm_subport_group_subport_port_count[unit] + group_id); 1859 1860 /* 1861 * Iterate through all the linkphy ports in the subport group 1862 * to check if external stream id is already in use. 1863 */ 1864 BCM_PBMP_ITER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port) { 1865 1866 if (linkphy_subport_count == 0) { 1867 break; 1868 } 1869 1870 if (!_BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) { 1871 continue; 1872 } 1873 1874 if (config->group != 1875 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port)) { 1876 continue; 1877 } 1878 1879 _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port); 1880 1881 _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port, 1882 _BCM_KT2_SUBPORT_TYPE_LINKPHY); 1883 1884 rv = _bcm_linkphy_subport_port_get(unit, subport_port, &sp_config); 1885 if (SOC_FAILURE(rv)) { 1886 LOG_ERROR(BSL_LS_BCM_SUBPORT, 1887 (BSL_META_U(unit, 1888 "ERROR: LinkPHY subport group 0x%x \n" 1889 "to get subport port (group id %d, pp_port id %d)\n"), 1890 config->group, group_id, pp_port)); 1891 return rv; 1892 } 1893 1894 for (i = 0; i < sp_config.num_streams; i++) { 1895 if (ext_stream_id == sp_config.stream_id_array[i]) { 1896 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 1897 (BSL_META_U(unit, 1898 "*ERROR: External stream_id %d is in use!! port %d\n"), 1899 config->stream_id_array[i], 1900 _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group))); 1901 return BCM_E_EXISTS; 1902 } 1903 } 1904 1905 linkphy_subport_count--; 1906 } 1907 return BCM_E_NONE; 1908 } 1909 1910 STATIC void 1911 _bcm_linkphy_subport_stat_callback(int unit) 1912 { 1913 int pool_id = 0, direction = 0, index = 0, block_id = 0, copyno = 0; 1914 int width = 0; 1915 soc_mem_t mem; 1916 uint32 ctr_new = 0, ctr_prev = 0, ctr_diff = 0; 1917 volatile uint64 *vptr; 1918 int linkphy_counter_max = _BCM_KT2_LINKPHY_COUNTER_MAX(unit); 1919 int linkphy_block_max = SOC_INFO(unit).lp_block_max; 1920 1921 BCM_LINKPHY_COUNTER_LOCK(unit); 1922 if (linkphy_temp_ctr[unit] == NULL){ 1923 LOG_WARN(BSL_LS_BCM_SUBPORT, 1924 (BSL_META_U(unit, 1925 "Not Initilized or attached\n"))); 1926 } 1927 1928 for (direction = 0; 1929 direction < _BCM_KT2_LINKPHY_DIRECTION_MAX; direction++) { 1930 for (block_id = 0; block_id < linkphy_block_max; block_id++) { 1931 for (pool_id = 0; pool_id < _BCM_KT2_LINKPHY_POOL_MAX; pool_id++) { 1932 1933 mem = linkphy_counter_table[direction][pool_id]; 1934 copyno = SOC_MEM_BLOCK_ANY(unit, mem) + block_id; 1935 width = soc_mem_field_length(unit, mem, COUNTf); 1936 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) { 1937 continue; 1938 } 1939 1940 if (soc_mem_read_range(unit, mem, copyno, 0, 1941 (linkphy_counter_max - 1), 1942 linkphy_temp_ctr[unit]) != BCM_E_NONE) { 1943 BCM_LINKPHY_COUNTER_UNLOCK(unit); 1944 return; 1945 } 1946 for (index = 0; index <= (linkphy_counter_max - 1); 1947 index++) { 1948 switch (pool_id) { 1949 case 0: 1950 vptr = &linkphy_frag_byte_ctr[unit][direction] 1951 [block_id][index]; 1952 break; 1953 case 1: 1954 vptr = &linkphy_frag_ctr[unit][direction] 1955 [block_id][index]; 1956 break; 1957 case 2: 1958 vptr = &linkphy_frame_byte_ctr[unit][direction] 1959 [block_id][index]; 1960 break; 1961 case 3: 1962 default: 1963 vptr = &linkphy_frame_ctr[unit][direction] 1964 [block_id][index]; 1965 break; 1966 } 1967 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 1968 (BSL_META_U(unit, 1969 "%s_DEBUG_COUNTER%d.lp%d index:%d " 1970 "%s : old count:0x%08x%08x \n"), 1971 direction ? "TXLP" : "RXLP", 1972 ((pool_id == 3) ? 11 : 1973 ((pool_id == 2) ? 10 : 1974 ((pool_id == 1) ? 9 : 8))), 1975 block_id, index, 1976 ((pool_id == 3) ? "Frame " : 1977 ((pool_id == 2) ? "FrameByte" : 1978 ((pool_id == 1) ? "Frag " : "FragByte "))), 1979 COMPILER_64_HI(*vptr), 1980 COMPILER_64_LO(*vptr))); 1981 1982 ctr_prev = COMPILER_64_LO(*vptr); 1983 1984 if (width < 32) { 1985 ctr_prev &= ((1UL << width) - 1); 1986 } 1987 1988 soc_mem_field_get(unit, mem, 1989 (uint32 *)&linkphy_temp_ctr[unit][index], 1990 COUNTf, &ctr_new); 1991 1992 if (ctr_new == ctr_prev) { 1993 continue; 1994 } 1995 1996 ctr_diff = ctr_new; 1997 1998 if (ctr_diff < ctr_prev) { 1999 /* Counter has wrapped around. */ 2000 if (width < 32) { 2001 ctr_diff += (1UL << width); 2002 } 2003 } 2004 2005 ctr_diff -= ctr_prev; 2006 2007 COMPILER_64_ADD_32(*vptr, ctr_diff); 2008 2009 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 2010 (BSL_META_U(unit, 2011 "%s_DEBUG_COUNTER%d.lp%d index:%d " 2012 "%s : new_count:0x%08x%08x\n"), 2013 direction ? "TXLP" : "RXLP", 2014 ((pool_id == 3) ? 11 : 2015 ((pool_id == 2) ? 10 : 2016 ((pool_id == 1) ? 9 : 8))), 2017 block_id, index, 2018 ((pool_id == 3) ? "Frame " : 2019 ((pool_id == 2) ? "FrameByte" : 2020 ((pool_id == 1) ? "Frag " : "FragByte "))), 2021 COMPILER_64_HI(*vptr), 2022 COMPILER_64_LO(*vptr))); 2023 } /*end index */ 2024 }/* end pool */ 2025 } /* end block */ 2026 } /* end direction */ 2027 BCM_LINKPHY_COUNTER_UNLOCK(unit); 2028 return; 2029 } 2030 2031 STATIC int 2032 _bcm_linkphy_subport_counter_cleanup(int unit) 2033 { 2034 int direction = 0, block_id = 0; 2035 int linkphy_block_max = SOC_INFO(unit).lp_block_max; 2036 2037 if (linkphy_ctr_mutex[unit] != NULL) { 2038 BCM_LINKPHY_COUNTER_LOCK(unit); 2039 soc_counter_extra_unregister(unit, _bcm_linkphy_subport_stat_callback); 2040 BCM_LINKPHY_COUNTER_UNLOCK(unit); 2041 sal_mutex_destroy(linkphy_ctr_mutex[unit]); 2042 linkphy_ctr_mutex[unit] = NULL; 2043 } 2044 2045 if (linkphy_temp_ctr[unit] != NULL){ 2046 soc_cm_sfree(unit,linkphy_temp_ctr[unit]); 2047 linkphy_temp_ctr[unit] = NULL; 2048 } 2049 2050 for (direction = 0; 2051 direction < _BCM_KT2_LINKPHY_DIRECTION_MAX; direction++) { 2052 for (block_id = 0; block_id < linkphy_block_max; block_id++) { 2053 if (linkphy_frag_byte_ctr[unit][direction][block_id] != NULL) { 2054 soc_cm_sfree(unit, 2055 linkphy_frag_byte_ctr[unit][direction][block_id]); 2056 linkphy_frag_byte_ctr[unit][direction][block_id] = NULL; 2057 } 2058 if (linkphy_frag_ctr[unit][direction][block_id] != NULL) { 2059 soc_cm_sfree(unit, 2060 linkphy_frag_ctr[unit][direction][block_id]); 2061 linkphy_frag_ctr[unit][direction][block_id] = NULL; 2062 } 2063 if (linkphy_frame_byte_ctr[unit][direction][block_id] != NULL) { 2064 soc_cm_sfree(unit, 2065 linkphy_frame_byte_ctr[unit][direction][block_id]); 2066 linkphy_frame_byte_ctr[unit][direction][block_id] = NULL; 2067 } 2068 if (linkphy_frame_ctr[unit][direction][block_id] != NULL) { 2069 soc_cm_sfree(unit, 2070 linkphy_frame_ctr[unit][direction][block_id]); 2071 linkphy_frame_ctr[unit][direction][block_id] = NULL; 2072 } 2073 } 2074 } 2075 return BCM_E_NONE; 2076 } 2077 2078 STATIC int 2079 _bcm_linkphy_subport_counter_init(int unit) 2080 { 2081 int direction = 0, block_id = 0, pool_id = 0, copyno = 0, index = 0; 2082 uint32 temp_alloc_size = 0, block_alloc_size = 0; 2083 soc_mem_t mem; 2084 int linkphy_counter_max = _BCM_KT2_LINKPHY_COUNTER_MAX(unit); 2085 int linkphy_block_max = SOC_INFO(unit).lp_block_max; 2086 2087 _bcm_linkphy_subport_counter_cleanup(unit); 2088 2089 if (linkphy_ctr_mutex[unit] == NULL) { 2090 linkphy_ctr_mutex[unit] = sal_mutex_create("subport counter mutex"); 2091 if (linkphy_ctr_mutex[unit] == NULL) { 2092 return BCM_E_MEMORY; 2093 } 2094 } 2095 2096 if (linkphy_temp_ctr[unit] != NULL){ 2097 LOG_WARN(BSL_LS_BCM_SUBPORT, 2098 (BSL_META_U(unit, 2099 "WARN:Freeing linkphy_temp_ctr\n"))); 2100 soc_cm_sfree(unit,linkphy_temp_ctr[unit]); 2101 linkphy_temp_ctr[unit] = NULL; 2102 } 2103 2104 temp_alloc_size = 2105 sizeof(rxlp_debug_counter7_entry_t) * linkphy_counter_max; 2106 linkphy_temp_ctr[unit] = soc_cm_salloc(unit, 2107 temp_alloc_size, "linkphy temp counter"); 2108 2109 if (linkphy_temp_ctr[unit] == NULL) { 2110 LOG_WARN(BSL_LS_BCM_SUBPORT, 2111 (BSL_META_U(unit, 2112 "linkphy temp allocation for unit:%d failed\n"), 2113 unit)); 2114 _bcm_linkphy_subport_counter_cleanup(unit); 2115 return BCM_E_MEMORY; 2116 } 2117 sal_memset(linkphy_temp_ctr[unit], 0, temp_alloc_size); 2118 LOG_DEBUG(BSL_LS_BCM_SUBPORT, 2119 (BSL_META_U(unit, 2120 "linkphy temp counter size:%d \n"), 2121 temp_alloc_size)); 2122 2123 2124 for (direction = 0; 2125 direction < _BCM_KT2_LINKPHY_DIRECTION_MAX; direction++) { 2126 for (block_id = 0; block_id < linkphy_block_max; block_id++) { 2127 for (pool_id = 0; pool_id < _BCM_KT2_LINKPHY_POOL_MAX; pool_id++) { 2128 2129 mem = linkphy_counter_table[direction][pool_id]; 2130 copyno = SOC_MEM_BLOCK_ANY(unit, mem) + block_id; 2131 if (!SOC_MEM_BLOCK_VALID(unit, mem, copyno)) { 2132 continue; 2133 } 2134 if (soc_mem_write_range(unit, mem, copyno, 2135 0, 2136 (linkphy_counter_max - 1), 2137 linkphy_temp_ctr[unit])) { 2138 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2139 (BSL_META_U(unit, 2140 "ERROR: zeroing LinkPHY counter failed\n"))); 2141 soc_cm_sfree(unit,linkphy_temp_ctr[unit]); 2142 linkphy_temp_ctr[unit] = NULL; 2143 } 2144 } 2145 } 2146 } 2147 2148 block_alloc_size = sizeof(uint64) * linkphy_counter_max; 2149 2150 for (direction=0; direction < _BCM_KT2_LINKPHY_DIRECTION_MAX; direction++) { 2151 for (block_id = 0; block_id < linkphy_block_max; block_id++) { 2152 /* fragment byte */ 2153 if (linkphy_frag_byte_ctr[unit][direction][block_id] != NULL) { 2154 LOG_WARN(BSL_LS_BCM_SUBPORT, 2155 (BSL_META_U(unit, 2156 "WARN:Freeing linkphy_frag_byte_ctr\n"))); 2157 soc_cm_sfree(unit, 2158 linkphy_frag_byte_ctr[unit][direction][block_id]); 2159 linkphy_frag_byte_ctr[unit][direction][block_id] = NULL; 2160 } 2161 2162 linkphy_frag_byte_ctr[unit][direction][block_id] = 2163 soc_cm_salloc(unit, block_alloc_size, 2164 "linkphy_fragment_byte counter"); 2165 if (linkphy_frag_byte_ctr[unit][direction][block_id] == NULL) { 2166 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2167 (BSL_META_U(unit, 2168 "linkphy_frag_byte_ctr failed for " 2169 " unit:%d,dir:%d, block:%d \n"), unit, direction, block_id)); 2170 _bcm_linkphy_subport_counter_cleanup(unit); 2171 return BCM_E_MEMORY; 2172 } 2173 sal_memset(linkphy_frag_byte_ctr[unit][direction][block_id], 2174 0, block_alloc_size); 2175 2176 /* fragment */ 2177 if (linkphy_frag_ctr[unit][direction][block_id] != NULL) { 2178 LOG_WARN(BSL_LS_BCM_SUBPORT, 2179 (BSL_META_U(unit, 2180 "WARN:Freeing linkphy_frag_ctr\n"))); 2181 soc_cm_sfree(unit, 2182 linkphy_frag_ctr[unit][direction][block_id]); 2183 linkphy_frag_ctr[unit][direction][block_id] = NULL; 2184 } 2185 2186 linkphy_frag_ctr[unit][direction][block_id] = 2187 soc_cm_salloc(unit, block_alloc_size, 2188 "linkphy_fragment counter"); 2189 if (linkphy_frag_ctr[unit][direction][block_id] == NULL) { 2190 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2191 (BSL_META_U(unit, 2192 "linkphy_frag_ctr failed for " 2193 " unit:%d,dir:%d, block:%d \n"), unit, direction, block_id)); 2194 soc_cm_sfree(unit, 2195 linkphy_frag_byte_ctr[unit][direction][block_id]); 2196 linkphy_frag_byte_ctr[unit][direction][block_id] = NULL; 2197 _bcm_linkphy_subport_counter_cleanup(unit); 2198 return BCM_E_MEMORY; 2199 } 2200 sal_memset( 2201 linkphy_frag_ctr[unit][direction][block_id], 0, block_alloc_size); 2202 2203 /* frame byte */ 2204 if (linkphy_frame_byte_ctr[unit][direction][block_id] != NULL) { 2205 LOG_WARN(BSL_LS_BCM_SUBPORT, 2206 (BSL_META_U(unit, 2207 "WARN:Freeing linkphy_frame_byte_ctr\n"))); 2208 soc_cm_sfree(unit, 2209 linkphy_frame_byte_ctr[unit][direction][block_id]); 2210 } 2211 linkphy_frame_byte_ctr[unit][direction][block_id] = 2212 soc_cm_salloc(unit, block_alloc_size, 2213 "linkphy_frame_byte counter"); 2214 if (linkphy_frame_byte_ctr[unit][direction][block_id] == NULL) { 2215 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2216 (BSL_META_U(unit, 2217 "linkphy_frame_byte_ctr failed for " 2218 "unit:%d,dir:%d, block:%d \n"), unit, direction, block_id)); 2219 soc_cm_sfree(unit, 2220 linkphy_frag_byte_ctr[unit][direction][block_id]); 2221 soc_cm_sfree(unit, 2222 linkphy_frag_ctr[unit][direction][block_id]); 2223 linkphy_frag_byte_ctr[unit][direction][block_id] = NULL; 2224 linkphy_frag_ctr[unit][direction][block_id] = NULL; 2225 linkphy_frame_byte_ctr[unit][direction][block_id] = NULL; 2226 _bcm_linkphy_subport_counter_cleanup(unit); 2227 return BCM_E_MEMORY; 2228 } 2229 sal_memset(linkphy_frame_byte_ctr[unit][direction][block_id], 2230 0, block_alloc_size); 2231 2232 /* frame */ 2233 if (linkphy_frame_ctr[unit][direction][block_id] != NULL) { 2234 LOG_WARN(BSL_LS_BCM_SUBPORT, 2235 (BSL_META_U(unit, 2236 "WARN:Freeing linkphy_frame_ctr\n"))); 2237 soc_cm_sfree(unit, 2238 linkphy_frame_ctr[unit][direction][block_id]); 2239 } 2240 linkphy_frame_ctr[unit][direction][block_id] = 2241 soc_cm_salloc(unit, block_alloc_size, "linkphy_frame counter"); 2242 if (linkphy_frame_ctr[unit][direction][block_id] == NULL) { 2243 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2244 (BSL_META_U(unit, 2245 "linkphy_frame_ctr failed for " 2246 "unit:%d,dir:%d block:%d\n"), unit, direction, block_id)); 2247 soc_cm_sfree(unit, 2248 linkphy_frag_byte_ctr[unit][direction][block_id]); 2249 soc_cm_sfree(unit, 2250 linkphy_frag_ctr[unit][direction][block_id]); 2251 soc_cm_sfree(unit, 2252 linkphy_frame_byte_ctr[unit][direction][block_id]); 2253 linkphy_frag_byte_ctr[unit][direction][block_id] = NULL; 2254 linkphy_frag_ctr[unit][direction][block_id] = NULL; 2255 linkphy_frame_byte_ctr[unit][direction][block_id] = NULL; 2256 _bcm_linkphy_subport_counter_cleanup(unit); 2257 return BCM_E_MEMORY; 2258 } 2259 sal_memset(linkphy_frame_ctr[unit][direction][block_id], 2260 0, block_alloc_size); 2261 2262 for (index = 0; index < linkphy_counter_max; index++) { 2263 COMPILER_64_ZERO ( 2264 linkphy_frag_ctr[unit][direction][block_id][index]); 2265 COMPILER_64_ZERO ( 2266 linkphy_frag_byte_ctr[unit][direction][block_id][index]); 2267 COMPILER_64_ZERO ( 2268 linkphy_frame_ctr[unit][direction][block_id][index]); 2269 COMPILER_64_ZERO ( 2270 linkphy_frame_byte_ctr[unit][direction][block_id][index]); 2271 } 2272 } 2273 } 2274 2275 BCM_IF_ERROR_RETURN 2276 (soc_counter_extra_register(unit, _bcm_linkphy_subport_stat_callback)); 2277 return BCM_E_NONE; 2278 } 2279 2280 /* 2281 * Function: 2282 * _bcm_linkphy_subport_port_stat_set 2283 * Purpose: 2284 * Set the statistics value for LinkPHY subport port and statistics type 2285 * Parameters: 2286 * unit - (IN) Device Number 2287 * subport - (IN) subport port 2288 * stream_id - (IN) stream ID array index 2289 * stat_type - (IN) statistics type 2290 * val - (IN) value 2291 * Returns: 2292 * BCM_E_XXX 2293 */ 2294 STATIC int 2295 _bcm_linkphy_subport_port_stat_set( 2296 int unit, 2297 bcm_gport_t subport, 2298 int stream_id, 2299 bcm_subport_stat_t stat_type, 2300 uint64 val) 2301 { 2302 int direction = 0, block = 0, pool = 0, copyno = 0; 2303 int rv = BCM_E_NONE; 2304 uint16 counter_id = 0; 2305 uint16 port_e_stream_id_base_adj = 0; 2306 uint16 blk_i_stream_id = 0; 2307 int i = 0; 2308 uint16 ext_stream_id_base = 0; 2309 uint32 val32 = 0, count_mask = 0; 2310 bcm_port_t port; 2311 bcm_subport_config_t config; 2312 soc_mem_t mem; 2313 rxlp_debug_counter7_entry_t temp_counter; 2314 2315 /* get port from subport */ 2316 bcm_subport_config_t_init(&config); 2317 rv = _bcm_linkphy_subport_port_get(unit, subport, &config); 2318 if (BCM_FAILURE(rv)) { 2319 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2320 (BSL_META_U(unit, 2321 "ERROR: _bcm_linkphy_subport_port_get failed \n" 2322 "for subport 0x%x\n"), subport)); 2323 return rv; 2324 } 2325 2326 port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config.group); 2327 rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, port, 2328 &ext_stream_id_base); 2329 if (BCM_FAILURE(rv)) { 2330 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2331 (BSL_META_U(unit, 2332 "ERROR: Linkphy port %d external " 2333 "stream id base get failed\n"), port)); 2334 return rv; 2335 } 2336 2337 if ((stream_id != -1) && (stream_id >= config.num_streams)) { 2338 return BCM_E_PARAM; 2339 } 2340 2341 switch (stat_type) { 2342 case bcmSubportLinkPhyStatRxFragmentBytes: 2343 direction = _BCM_KT2_LINKPHY_DIRECTION_RX; 2344 pool = _BCM_KT2_LINKPHY_POOL_FRAG_BYTE; 2345 break; 2346 case bcmSubportLinkPhyStatRxFragments: 2347 direction = _BCM_KT2_LINKPHY_DIRECTION_RX; 2348 pool = _BCM_KT2_LINKPHY_POOL_FRAG; 2349 break; 2350 case bcmSubportLinkPhyStatRxFrameBytes: 2351 direction = _BCM_KT2_LINKPHY_DIRECTION_RX; 2352 pool = _BCM_KT2_LINKPHY_POOL_FRAME_BYTE; 2353 break; 2354 case bcmSubportLinkPhyStatRxFrames: 2355 direction = _BCM_KT2_LINKPHY_DIRECTION_RX; 2356 pool = _BCM_KT2_LINKPHY_POOL_FRAME; 2357 break; 2358 case bcmSubportLinkPhyStatTxFragmentBytes: 2359 direction = _BCM_KT2_LINKPHY_DIRECTION_TX; 2360 pool = _BCM_KT2_LINKPHY_POOL_FRAG_BYTE; 2361 break; 2362 case bcmSubportLinkPhyStatTxFragments: 2363 direction = _BCM_KT2_LINKPHY_DIRECTION_TX; 2364 pool = _BCM_KT2_LINKPHY_POOL_FRAG; 2365 break; 2366 case bcmSubportLinkPhyStatTxFrameBytes: 2367 direction = _BCM_KT2_LINKPHY_DIRECTION_TX; 2368 pool = _BCM_KT2_LINKPHY_POOL_FRAME_BYTE; 2369 break; 2370 case bcmSubportLinkPhyStatTxFrames: 2371 direction = _BCM_KT2_LINKPHY_DIRECTION_TX; 2372 pool = _BCM_KT2_LINKPHY_POOL_FRAME; 2373 break; 2374 default: 2375 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2376 (BSL_META_U(unit, 2377 "LinkPHY Statistic not supported: %d\n"), stat_type)); 2378 return BCM_E_PARAM; 2379 break; 2380 } 2381 2382 rv = soc_linkphy_port_blk_idx_get(unit, port, &block, NULL); 2383 if (SOC_FAILURE(rv)) { 2384 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2385 (BSL_META_U(unit, 2386 2387 "ERROR: LinkPHY block, index get failed for port %d\n"), port)); 2388 return rv; 2389 } 2390 2391 BCM_LINKPHY_COUNTER_LOCK(unit); 2392 mem = linkphy_counter_table[direction][pool]; 2393 copyno = SOC_MEM_BLOCK_ANY(unit, mem) + block; 2394 2395 for (i =0; i < config.num_streams; i++) { 2396 if (stream_id != i) { 2397 /* if stream_id == -1 then set the stats for all 2398 * streams associated with the LinkPHY subport */ 2399 if (stream_id != -1) { 2400 continue; 2401 } 2402 } 2403 2404 /* 2405 * Port external stream Id after adjusting the 2406 * port external stream id base. 2407 * Range from 0 - 127. 2408 */ 2409 port_e_stream_id_base_adj = config.stream_id_array[i] - 2410 ext_stream_id_base; 2411 2412 /* 2413 * get the rxlp block internal stream id(0 - 127) for the 2414 * external stream id. 2415 */ 2416 BCM_IF_ERROR_RETURN(_bcm_linkphy_port_rx_int_stream_map_port_get(unit, 2417 port, port_e_stream_id_base_adj, 2418 &blk_i_stream_id)); 2419 2420 /* counter index is same as rxlp block internal stream id */ 2421 counter_id = blk_i_stream_id; 2422 2423 2424 /* Read Hard copy */ 2425 if (soc_mem_read(unit, mem, copyno, counter_id, 2426 &temp_counter) != BCM_E_NONE) { 2427 BCM_LINKPHY_COUNTER_UNLOCK(unit); 2428 return BCM_E_INTERNAL; 2429 } 2430 2431 /* Update soft copy */ 2432 if ((stat_type == bcmSubportLinkPhyStatRxFragmentBytes) || 2433 (stat_type == bcmSubportLinkPhyStatTxFragmentBytes)) { 2434 COMPILER_64_SET (linkphy_frag_byte_ctr[unit][direction] 2435 [block][counter_id], 2436 COMPILER_64_HI(val), 2437 COMPILER_64_LO(val)); 2438 } else if ((stat_type == bcmSubportLinkPhyStatRxFragments) || 2439 (stat_type == bcmSubportLinkPhyStatTxFragments)) { 2440 COMPILER_64_SET (linkphy_frag_ctr[unit][direction] 2441 [block][counter_id], 2442 COMPILER_64_HI(val), 2443 COMPILER_64_LO(val)); 2444 } else if ((stat_type == bcmSubportLinkPhyStatRxFrameBytes) || 2445 (stat_type == bcmSubportLinkPhyStatTxFrameBytes)) { 2446 COMPILER_64_SET (linkphy_frame_byte_ctr[unit][direction] 2447 [block][counter_id], 2448 COMPILER_64_HI(val), 2449 COMPILER_64_LO(val)); 2450 } else { 2451 /* if ((stat_type == bcmSubportLinkPhyStatRxFrames) || 2452 (stat_type == bcmSubportLinkPhyStatTxFrames)) */ 2453 COMPILER_64_SET (linkphy_frame_ctr[unit][direction] 2454 [block][counter_id], 2455 COMPILER_64_HI(val), 2456 COMPILER_64_LO(val)); 2457 } 2458 2459 /* Modify Hard copy */ 2460 count_mask = (1 << soc_mem_field_length(unit, mem, COUNTf)) - 1; 2461 val32 = COMPILER_64_LO(val) & count_mask; 2462 2463 soc_mem_field_set(unit, mem, (uint32 *)&temp_counter, COUNTf, &val32); 2464 /* Update Hard Copy */ 2465 if (soc_mem_write(unit, mem, copyno, counter_id, 2466 &temp_counter) != BCM_E_NONE){ 2467 BCM_LINKPHY_COUNTER_UNLOCK(unit); 2468 return BCM_E_INTERNAL; 2469 } 2470 } 2471 2472 BCM_LINKPHY_COUNTER_UNLOCK(unit); 2473 return BCM_E_NONE; 2474 } 2475 2476 /* TXLP module is not aware of the Fragment FCS added by the MAC/PORT logic. 2477 * Hence the TXLP Fragment byte counters do not count the additional 2478 * 4 bytes added as FCS per fragment. Hence we need to add it in SW, 2479 * when those counters are retrieved by user. 2480 */ 2481 STATIC void 2482 _bcm_kt2_linkphy_add_FCS_bytes_count_to_frag_byte_ctr(uint64 *val, 2483 uint64 num_fragments) 2484 { 2485 /* Add the current frag byte counter with 2486 * 4 bytes of FCS per fragment * num of fragments 2487 */ 2488 COMPILER_64_UMUL_32(num_fragments, 4); 2489 COMPILER_64_ADD_64(*val, num_fragments); 2490 } 2491 2492 /* 2493 * Function: 2494 * _bcm_linkphy_subport_port_stat_get 2495 * Purpose: 2496 * Get the statistics value for LinkPHY subport port and statistics type 2497 * Parameters: 2498 * unit - (IN) Device Number 2499 * subport - (IN) subport port 2500 * stream_id - (IN) stream ID array index 2501 * stat_type - (IN) statistics type 2502 * val - (OUT) value 2503 * Returns: 2504 * BCM_E_XXX 2505 */ 2506 STATIC int 2507 _bcm_linkphy_subport_port_stat_get( 2508 int unit, 2509 bcm_gport_t subport, 2510 int stream_id, 2511 bcm_subport_stat_t stat_type, 2512 uint64 *val) 2513 { 2514 int direction = 0, block = 0; 2515 int rv = BCM_E_NONE, i = 0; 2516 uint16 counter_id = 0; 2517 uint16 ext_stream_id_base = 0; 2518 uint16 port_e_stream_id_base_adj = 0; 2519 uint16 blk_i_stream_id = 0; 2520 bcm_port_t port; 2521 bcm_subport_config_t config; 2522 2523 /* get port from subport */ 2524 bcm_subport_config_t_init(&config); 2525 rv = _bcm_linkphy_subport_port_get(unit, subport, &config); 2526 if (BCM_FAILURE(rv)) { 2527 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2528 (BSL_META_U(unit, 2529 "ERROR: _bcm_linkphy_subport_port_get failed \n" 2530 "for subport 0x%x\n"), subport)); 2531 return rv; 2532 } 2533 2534 port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config.group); 2535 2536 rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, port, 2537 &ext_stream_id_base); 2538 if (BCM_FAILURE(rv)) { 2539 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2540 (BSL_META_U(unit, 2541 "ERROR: Linkphy port %d external " 2542 "stream id base get failed\n"), port)); 2543 return rv; 2544 } 2545 2546 if ((stream_id != -1) && (stream_id >= config.num_streams)) { 2547 return BCM_E_PARAM; 2548 } 2549 2550 rv = soc_linkphy_port_blk_idx_get(unit, port, &block, NULL); 2551 if (SOC_FAILURE(rv)) { 2552 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2553 (BSL_META_U(unit, 2554 2555 "ERROR: LinkPHY block, index get failed for port %d\n"), port)); 2556 return rv; 2557 } 2558 2559 switch (stat_type) { 2560 case bcmSubportLinkPhyStatRxFragmentBytes: 2561 case bcmSubportLinkPhyStatRxFragments: 2562 case bcmSubportLinkPhyStatRxFrameBytes: 2563 case bcmSubportLinkPhyStatRxFrames: 2564 direction = _BCM_KT2_LINKPHY_DIRECTION_RX; 2565 break; 2566 case bcmSubportLinkPhyStatTxFragmentBytes: 2567 case bcmSubportLinkPhyStatTxFragments: 2568 case bcmSubportLinkPhyStatTxFrameBytes: 2569 case bcmSubportLinkPhyStatTxFrames: 2570 direction = _BCM_KT2_LINKPHY_DIRECTION_TX; 2571 break; 2572 default: 2573 LOG_VERBOSE(BSL_LS_SOC_COMMON, 2574 (BSL_META_U(unit, 2575 "LinkPHY Statistic not supported: %d\n"), stat_type)); 2576 return BCM_E_PARAM; 2577 break; 2578 } 2579 2580 BCM_LINKPHY_COUNTER_LOCK(unit); 2581 2582 COMPILER_64_ZERO(*val); 2583 2584 for (i =0; i < config.num_streams; i++) { 2585 if (stream_id != i) { 2586 /* if stream_id == -1 then get the stats for all 2587 * streams associated with the LinkPHY subport and add them*/ 2588 if (stream_id != -1) { 2589 continue; 2590 } 2591 } 2592 2593 /* 2594 * Port external stream Id after adjusting the 2595 * port external stream id base. 2596 * Range from 0 - 127. 2597 */ 2598 port_e_stream_id_base_adj = config.stream_id_array[i] - 2599 ext_stream_id_base; 2600 2601 /* 2602 * get the rxlp block internal stream id(0 - 127) for the 2603 * external stream id. 2604 */ 2605 BCM_IF_ERROR_RETURN(_bcm_linkphy_port_rx_int_stream_map_port_get(unit, 2606 port, port_e_stream_id_base_adj, 2607 &blk_i_stream_id)); 2608 2609 /* counter index is same as rxlp block internal stream id */ 2610 counter_id = blk_i_stream_id; 2611 2612 2613 if ((stat_type == bcmSubportLinkPhyStatRxFragmentBytes) || 2614 (stat_type == bcmSubportLinkPhyStatTxFragmentBytes)) { 2615 COMPILER_64_ADD_64(*val, linkphy_frag_byte_ctr[unit][direction] 2616 [block][counter_id]); 2617 /* On both RXLP and TXLP, fragment bytes counter does not 2618 * include FCS bytes. Hence we add it when we provide stats 2619 * to user. 2620 */ 2621 _bcm_kt2_linkphy_add_FCS_bytes_count_to_frag_byte_ctr(val, 2622 linkphy_frag_ctr[unit][direction] 2623 [block][counter_id]); 2624 } else if ((stat_type == bcmSubportLinkPhyStatRxFragments) || 2625 (stat_type == bcmSubportLinkPhyStatTxFragments)) { 2626 COMPILER_64_ADD_64(*val, linkphy_frag_ctr[unit][direction] 2627 [block][counter_id]); 2628 } else if ((stat_type == bcmSubportLinkPhyStatRxFrameBytes) || 2629 (stat_type == bcmSubportLinkPhyStatTxFrameBytes)) { 2630 COMPILER_64_ADD_64(*val, linkphy_frame_byte_ctr[unit][direction] 2631 [block][counter_id]); 2632 } else { 2633 /* if ((stat_type == bcmSubportLinkPhyStatRxFrames) || 2634 (stat_type == bcmSubportLinkPhyStatTxFrames)) */ 2635 COMPILER_64_ADD_64(*val, linkphy_frame_ctr[unit][direction] 2636 [block][counter_id]); 2637 } 2638 } 2639 BCM_LINKPHY_COUNTER_UNLOCK(unit); 2640 return BCM_E_NONE; 2641 } 2642 2643 2644 /* 2645 * Function: 2646 * _bcm_linkphy_subport_init 2647 * Purpose: 2648 * Initialize LinkPHY subport module. 2649 * Parameters: 2650 * unit - Device Number 2651 * Returns: 2652 * BCM_E_XXX 2653 */ 2654 STATIC int 2655 _bcm_linkphy_subport_init(int unit) 2656 { 2657 int dev_int_stream_max = 0; 2658 bcm_port_t port; 2659 soc_info_t *si = &SOC_INFO(unit); 2660 int subport_port_max = si->subport_port_max; 2661 int subport_group_max = si->subport_group_max; 2662 int index = 0; 2663 int block = 0; 2664 int linkphy_enable = 0; 2665 int rv = BCM_E_NONE; 2666 int start_index, end_index; 2667 2668 /* Clear TXLP_PORT_STREAM_BITMAP_TABLEm table */ 2669 BCM_IF_ERROR_RETURN 2670 (soc_mem_clear(unit, TXLP_PORT_STREAM_BITMAP_TABLEm, COPYNO_ALL, TRUE)); 2671 2672 /* 2673 * Check if pbmp_linkphy members are valid for supporting LinkPHY. 2674 * For Katana2(BCM56450) port 27 to 34 only support LinkPHY 2675 */ 2676 BCM_PBMP_ITER(si->linkphy_allowed_pbm, port) { 2677 if (!_BCM_KT2_PORT_SUPPORTS_LINKPHY(unit, port)) { 2678 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2679 (BSL_META_U(unit, 2680 "ERROR: config variable pbmp_linkphy " 2681 "member port %d is invalid for LinkPHY support\n"), 2682 port)); 2683 return BCM_E_PORT; 2684 } 2685 } 2686 2687 /* 2688 * If config variable linkphy_enable is enabled 2689 * initialize and setup the linkphy on ports 2690 * enabled in the config variable "pbmp_linkphy". 2691 * The config variable "linkphy_enable" is set 2692 * by default, meaning linkphy is enabled during 2693 * initialization. 2694 */ 2695 2696 linkphy_enable = soc_property_get(unit, spn_LINKPHY_ENABLE, 1); 2697 if (linkphy_enable) { 2698 port = 0; 2699 BCM_PBMP_ITER(si->linkphy_allowed_pbm, port) { 2700 if (BCM_PBMP_MEMBER(PBMP_PORT_ALL(unit), port)) { 2701 /* Disable the port before enabling LinkPhy */ 2702 BCM_IF_ERROR_RETURN (bcm_esw_port_enable_set(unit, port, 0)); 2703 rv = bcm_kt2_port_control_linkphy_status_set(unit, 2704 port, 2705 linkphy_enable); 2706 /* Enable the port */ 2707 BCM_IF_ERROR_RETURN (bcm_esw_port_enable_set(unit, port, 1)); 2708 2709 if (BCM_FAILURE(rv)) { 2710 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2711 (BSL_META_U(unit, 2712 "ERROR:Enabling LinkPhy on Port(%d) " 2713 "failed - %s\n"), 2714 port, bcm_errmsg(rv))); 2715 return rv; 2716 } 2717 } /* BCM_PBMP_MEMBER(PBMP_PORT_ALL(unit), port) */ 2718 } /* BCM_PBMP_ITER */ 2719 } /* linkphy_enable */ 2720 2721 /* LinkPHY group bitmap to keep track of used LinkPHY groups */ 2722 if (_bcm_linkphy_group_bitmap[unit] == NULL) { 2723 2724 _bcm_linkphy_group_bitmap[unit] = 2725 sal_alloc(SHR_BITALLOCSIZE(subport_group_max), 2726 "linkphy_subport_group_bitmap"); 2727 2728 if (_bcm_linkphy_group_bitmap[unit] == NULL) { 2729 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2730 (BSL_META_U(unit, 2731 "ERROR:subport_init: group bitmap alloc failed\n"))); 2732 2733 return BCM_E_MEMORY; 2734 } 2735 } 2736 2737 sal_memset(_bcm_linkphy_group_bitmap[unit], 0, 2738 SHR_BITALLOCSIZE(subport_group_max)); 2739 2740 /* LinkPHY device internal stream ID bitmap to keep track of the device 2741 * internal stream ID used. A device internal stream id can be active on 2742 * one port at a time. 2743 */ 2744 dev_int_stream_max = 2 * subport_port_max; 2745 if (_bcm_dev_int_stream_id_bitmap[unit] == NULL) { 2746 2747 _bcm_dev_int_stream_id_bitmap[unit] = 2748 sal_alloc(SHR_BITALLOCSIZE(dev_int_stream_max), 2749 "dev_int_stream_id_bitmap"); 2750 2751 if (_bcm_dev_int_stream_id_bitmap[unit] == NULL) { 2752 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2753 (BSL_META_U(unit, 2754 "ERROR:subport_init: dev_int_stream_id_bitmap " 2755 " alloc failed\n"))); 2756 2757 return BCM_E_MEMORY; 2758 } 2759 } 2760 sal_memset(_bcm_dev_int_stream_id_bitmap[unit], 0, 2761 SHR_BITALLOCSIZE(dev_int_stream_max)); 2762 2763 /* LinkPHY subport port info per pp_port */ 2764 if (_bcm_linkphy_subport_port_info[unit] == NULL) { 2765 _bcm_linkphy_subport_port_info[unit] = 2766 sal_alloc((SOC_MAX_NUM_PP_PORTS * 2767 sizeof(_bcm_linkphy_subport_port_info_t)), 2768 "linkphy_subport_port_info"); 2769 if (_bcm_linkphy_subport_port_info[unit] == NULL) { 2770 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2771 (BSL_META_U(unit, 2772 "ERROR: " 2773 " linkphy_subport_port_info alloc failed\n"))); 2774 2775 return BCM_E_MEMORY; 2776 } 2777 } 2778 2779 sal_memset(_bcm_linkphy_subport_port_info[unit], 0, 2780 (SOC_MAX_NUM_PP_PORTS * sizeof(_bcm_linkphy_subport_port_info_t))); 2781 2782 for (index = 0; index < SOC_MAX_NUM_PP_PORTS; index++) { 2783 _bcm_linkphy_subport_port_info[unit][index].group = -1; 2784 _bcm_linkphy_subport_port_info[unit][index].num_streams = -1; 2785 } 2786 2787 #if defined(BCM_METROLITE_SUPPORT) 2788 if (SOC_IS_METROLITE(unit)) { 2789 /* Allocate for _BCM_ML_MAX_LINKPHY_PORTS */ 2790 for (index = 0; index < _BCM_ML_MAX_LINKPHY_PORTS; index++) { 2791 start_index = si->port_subport_base[index+1]; 2792 end_index = si->port_subport_base[index+1] + si->port_num_subport[index+1] - 1; 2793 rv = shr_idxres_list_create(&(_bcm_ml_int_stream_id_pool[unit][index]), 2794 start_index, end_index, 2795 start_index, end_index, 2796 "ml_int_stream_id_pool"); 2797 } 2798 } else 2799 #endif 2800 #if defined(BCM_SABER2_SUPPORT) 2801 if (SOC_IS_SABER2(unit)) { 2802 /* Allocate for _BCM_SB2_MAX_LINKPHY_PORTS */ 2803 for (index = 0; index < SOC_INFO(unit).lp_ports_max; index++) { 2804 start_index = si->port_linkphy_s1_base[index+1]; 2805 end_index = start_index + (si->port_num_subport[index+1] * 2)- 1; 2806 rv = shr_idxres_list_create(&(_bcm_sb2_int_stream_id_pool[unit][index]), 2807 start_index, end_index, 2808 start_index, end_index, 2809 "sb2_int_stream_id_pool"); 2810 } 2811 } else 2812 #endif 2813 { 2814 for (block = 0; block < SOC_INFO(unit).lp_block_max; block++) { 2815 for (index =0; index < SOC_KT2_LINKPHY_BLOCK_PORT_IDX_MAX; 2816 index++) { 2817 start_index = 0; 2818 end_index = _BCM_KT2_LINKPHY_PER_BLK_STREAMS_MAX - 1; 2819 rv = shr_idxres_list_create( 2820 &(_bcm_kt2_blk_int_stream_id_pool[unit][block][index]), 2821 start_index, end_index, 2822 start_index, end_index, 2823 "kt2_blk_int_stream_id_pool"); 2824 } 2825 } 2826 } 2827 2828 /* Set the STP state of subports */ 2829 BCM_PBMP_ITER(SOC_INFO(unit).linkphy_pp_port_pbm, port) { 2830 bcm_esw_port_learn_set(unit, port, 2831 BCM_PORT_LEARN_ARL | BCM_PORT_LEARN_FWD); 2832 bcm_esw_port_stp_set(unit, port, BCM_STG_STP_FORWARD); 2833 } 2834 2835 /* Register for RXLP interrupts */ 2836 soc_kt2_linkphy_handler_register(unit, &_bcm_kt2_subport_linkphy_rx_error_handler); 2837 return BCM_E_NONE; 2838 } 2839 2840 /* 2841 * Function: 2842 * _bcm_linkphy_subport_group_create 2843 * Purpose: 2844 * Create a LinkPHY subport group 2845 * Parameters: 2846 * unit - (IN) Device Number 2847 * config - (IN) Subport group config information 2848 * group - (OUT) GPORT (generic port) identifier 2849 * Returns: 2850 * BCM_E_XXX 2851 */ 2852 STATIC int 2853 _bcm_linkphy_subport_group_create(int unit, 2854 int is_trunk, bcm_port_t port, 2855 int group_id, bcm_gport_t *group) 2856 { 2857 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 2858 2859 _BCM_KT2_LINKPHY_SUBPORT_GROUP_SET(*group, port, group_id); 2860 _BCM_KT2_SUBPORT_GROUP_TYPE_CASCADED_SET(*group); 2861 2862 _BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_SET(unit, group_id); 2863 _bcm_linkphy_subport_group_count[unit]++; 2864 2865 return BCM_E_NONE; 2866 } 2867 2868 /* 2869 * Function: 2870 * _bcm_linkphy_subport_group_destroy 2871 * Purpose: 2872 * Destroy the LinkPHY subport group and all subport ports attached to it. 2873 * Parameters: 2874 * unit - (IN) Device Number 2875 * group - (IN) GPORT (generic port) identifier for subport group 2876 * Returns: 2877 * BCM_E_XXX 2878 */ 2879 STATIC int 2880 _bcm_linkphy_subport_group_destroy(int unit, 2881 bcm_gport_t group) 2882 { 2883 int group_id = -1; 2884 int pp_port = 0, rv = BCM_E_NONE; 2885 int linkphy_subport_count = 0; 2886 bcm_gport_t subport_port_gport; 2887 2888 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 2889 2890 if (_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(group)) { 2891 2892 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group); 2893 2894 if (!_BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_GET(unit, group_id)) { 2895 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2896 (BSL_META_U(unit, 2897 "ERROR: LinkPHY subport group 0x%x not found.\n"), 2898 group)); 2899 return BCM_E_NOT_FOUND; 2900 } 2901 2902 linkphy_subport_count = 2903 *(_bcm_subport_group_subport_port_count[unit] + group_id); 2904 2905 /* delete all subport ports attached to the subport group */ 2906 BCM_PBMP_ITER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port) { 2907 if (linkphy_subport_count == 0) { 2908 break; 2909 } 2910 2911 if (!_BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) { 2912 continue; 2913 } 2914 2915 if (group != 2916 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port)) { 2917 continue; 2918 } 2919 2920 _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port_gport, pp_port); 2921 2922 _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port_gport, 2923 _BCM_KT2_SUBPORT_TYPE_LINKPHY); 2924 2925 rv = _bcm_linkphy_subport_port_delete(unit, subport_port_gport); 2926 if (SOC_FAILURE(rv)) { 2927 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2928 (BSL_META_U(unit, 2929 "ERROR: LinkPHY subport group 0x%x destroy failed \n" 2930 " to delete subport port (subport group id %d, " 2931 " pp_port id %d)\n"), 2932 group, group_id, pp_port)); 2933 return rv; 2934 } 2935 linkphy_subport_count--; 2936 } 2937 2938 *(_bcm_subport_group_subport_port_count[unit] + group_id) = 0; 2939 /* delete the subport group */ 2940 _bcm_subport_group_count[unit]--; 2941 _BCM_KT2_SUBPORT_GROUP_USED_CLR(unit, group_id); 2942 _bcm_linkphy_subport_group_count[unit]--; 2943 _BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_CLR(unit, group_id); 2944 } 2945 2946 return BCM_E_NONE; 2947 } 2948 2949 /* 2950 * Function: 2951 * _bcm_linkphy_subport_group_get 2952 * Purpose: 2953 * Get a subport group 2954 * Parameters: 2955 * unit - (IN) Device Number 2956 * group - (IN) GPORT (generic port) identifier 2957 * config - (OUT) Subport group config information 2958 * Returns: 2959 * BCM_E_XXX 2960 */ 2961 STATIC int 2962 _bcm_linkphy_subport_group_get(int unit, 2963 bcm_gport_t group, 2964 bcm_subport_group_config_t *config) 2965 { 2966 int group_id = -1; 2967 2968 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 2969 2970 if (config == NULL) { 2971 return BCM_E_PARAM; 2972 } 2973 2974 if (_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(group)) { 2975 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group); 2976 if (!_BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_GET(unit, group_id)) { 2977 LOG_ERROR(BSL_LS_BCM_SUBPORT, 2978 (BSL_META_U(unit, 2979 "ERROR: LinkPHY subport group 0x%x not found.\n"), 2980 group)); 2981 return BCM_E_NOT_FOUND;; 2982 } 2983 config->flags |= BCM_SUBPORT_GROUP_TYPE_LINKPHY; 2984 config->port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(group); 2985 } else { 2986 return BCM_E_PARAM; 2987 } 2988 2989 return BCM_E_NONE; 2990 } 2991 2992 /* 2993 * Function: 2994 * _bcm_linkphy_subport_group_traverse 2995 * Purpose: 2996 * Traverse all valid subports for given LinkPHY subport group 2997 * and call the user supplied callback routine. 2998 * Parameters: 2999 * unit - Device Number 3000 * group - Subport group GPORT identifier 3001 * cb - User callback function, called once per subport. 3002 * user_data - cookie 3003 */ 3004 3005 STATIC int 3006 _bcm_linkphy_subport_group_traverse(int unit, 3007 bcm_gport_t group, 3008 bcm_subport_port_traverse_cb cb, 3009 void *user_data) 3010 { 3011 int rv = BCM_E_NONE, group_id = 0; 3012 int pp_port = 0, subport_port; 3013 int linkphy_subport_count = 0; 3014 bcm_subport_config_t config; 3015 3016 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 3017 3018 bcm_subport_config_t_init(&config); 3019 3020 if (_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(group)) { 3021 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group); 3022 3023 if (!_BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_GET(unit, group_id)) { 3024 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3025 (BSL_META_U(unit, 3026 "ERROR: LinkPHY subport group 0x%x not found.\n"), 3027 group)); 3028 return BCM_E_NOT_FOUND; 3029 } 3030 3031 linkphy_subport_count = 3032 *(_bcm_subport_group_subport_port_count[unit] + group_id); 3033 3034 BCM_PBMP_ITER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port) { 3035 3036 if (linkphy_subport_count == 0) { 3037 break; 3038 } 3039 3040 if (!_BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) { 3041 continue; 3042 } 3043 3044 if (group != 3045 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port)) { 3046 continue; 3047 } 3048 3049 _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port); 3050 3051 _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port, 3052 _BCM_KT2_SUBPORT_TYPE_LINKPHY); 3053 3054 rv = _bcm_linkphy_subport_port_get(unit, subport_port, &config); 3055 if (SOC_FAILURE(rv)) { 3056 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3057 (BSL_META_U(unit, 3058 "ERROR: LinkPHY subport group 0x%x traverse failed \n" 3059 "to get subport port (group id %d, pp_port id %d)\n"), 3060 group, group_id, pp_port)); 3061 return rv; 3062 } 3063 3064 #ifdef BCM_CB_ABORT_ON_ERR 3065 rv = cb(unit, subport_port, &config, user_data); 3066 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 3067 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3068 (BSL_META_U(unit, 3069 "ERROR: subport group 0x%x traverse failed \n" 3070 "to callback for subport port (group id %d, " 3071 "subport id %d)\n"), group, group_id, pp_port)); 3072 return rv; 3073 } 3074 #else 3075 (void)cb(unit, subport_port, &config, user_data); 3076 #endif 3077 linkphy_subport_count--; 3078 } 3079 } else { 3080 return BCM_E_PARAM; 3081 } 3082 return BCM_E_NONE; 3083 } 3084 3085 3086 /* 3087 * Function: 3088 * _bcm_kt2_allocate_pp_port 3089 * Purpose: 3090 * Allocate a pp_port based on supplied info 3091 * Parameters: 3092 * unit - (IN) Device Number 3093 * config - (IN) Subport config information 3094 * pp_port_index - (OUT) pp_port allocated 3095 * Returns: 3096 * BCM_E_XXX 3097 */ 3098 STATIC int _bcm_kt2_allocate_pp_port(int unit, bcm_subport_config_t *config, 3099 int *pp_port_index) 3100 { 3101 soc_info_t *si = &SOC_INFO(unit); 3102 int port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group), i = 0; 3103 int mod_id = 0, port_id = 0; 3104 #if defined BCM_METROLITE_SUPPORT 3105 int found_flag = 0; 3106 #endif 3107 3108 /* If a valid gport is supplied use it, else allocate one */ 3109 if(BCM_GPORT_IS_MODPORT(config->subport_modport)) { 3110 3111 /* The user can use this field to set (mod,port) only if the 3112 coe-stacking mode is enabled */ 3113 if(!si->coe_stacking_mode) { 3114 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3115 (BSL_META_U(unit,"ERROR: CoE stacking mode not enabled\n"))); 3116 return BCM_E_PARAM; 3117 } 3118 3119 mod_id = BCM_GPORT_MODPORT_MODID_GET(config->subport_modport); 3120 port_id = BCM_GPORT_MODPORT_PORT_GET(config->subport_modport); 3121 /* Check if the supplied CoE-(mod,port) is valid */ 3122 if(_bcm_stk_aux_modport_valid(unit, BCM_MODID_TYPE_COE, 3123 mod_id, port_id) != BCM_E_NONE) { 3124 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3125 (BSL_META_U(unit,"ERROR: Supplied (mod,port) (%d,%d) " 3126 "not valid\n"), 3127 mod_id, port_id)); 3128 return BCM_E_PARAM; 3129 } 3130 3131 /* Also check that the corresponding pp_port is valid on this 3132 physical port */ 3133 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit, 3134 mod_id, port_id, pp_port_index)); 3135 3136 if((*pp_port_index >= si->port_subport_base[port]) && 3137 (*pp_port_index < (si->port_subport_base[port] + 3138 (si->port_num_subport[port]) - 1))) { 3139 /* This pp_port is valid, now check if it is already in use */ 3140 if(_BCM_KT2_SUBPORT_PP_PORT_USED_GET(unit, *pp_port_index)) { 3141 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3142 (BSL_META_U(unit,"ERROR: Supplied (mod,port)" 3143 "(%d,%d) mapped pp_port: %d " 3144 "in use already \n"), 3145 mod_id, port_id, *pp_port_index)); 3146 return BCM_E_PARAM; 3147 } 3148 } else { 3149 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3150 (BSL_META_U(unit,"ERROR: Supplied (mod,port)" 3151 "(%d,%d) mapped pp_port: %d not valid on " 3152 "physical port %d \n"), mod_id, port_id, 3153 *pp_port_index, port)); 3154 } 3155 } else { 3156 #if defined BCM_METROLITE_SUPPORT 3157 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 3158 SOC_PBMP_ITER(SOC_PORT_PP_BITMAP(unit, port), i) { 3159 if (!_BCM_KT2_SUBPORT_PP_PORT_USED_GET(unit, i)) { 3160 *pp_port_index = i; 3161 found_flag = 1; 3162 break; 3163 } 3164 } 3165 if (found_flag == 0) { 3166 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3167 (BSL_META_U(unit, 3168 "ERROR: All %d subport pp_port already used.\n"), 3169 (si->port_num_subport[port]))); 3170 return BCM_E_FULL; 3171 } 3172 } else 3173 #endif 3174 { 3175 /* Alocate a pp_port for use with this subport */ 3176 for (i = si->port_subport_base[port]; 3177 i < (si->port_subport_base[port] + si->port_num_subport[port]); 3178 i++) { 3179 if (!_BCM_KT2_SUBPORT_PP_PORT_USED_GET(unit, i)) { 3180 *pp_port_index = i; 3181 break; 3182 } 3183 } 3184 3185 if (i == (si->port_subport_base[port] + si->port_num_subport[port])) { 3186 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3187 (BSL_META_U(unit, 3188 "ERROR: All %d subport pp_port already used.\n"), 3189 (i - si->port_subport_base[port]))); 3190 return BCM_E_FULL; 3191 } 3192 } 3193 3194 /* If the user is running in an enhanced mode, get the mapped 3195 (module, port) associated with this pp_port and validate 3196 the same */ 3197 if(si->coe_stacking_mode) { 3198 3199 /* Get the mod-port that corresponds to this pp_port */ 3200 BCM_IF_ERROR_RETURN(_bcm_kt2_pp_port_to_modport_get(unit, 3201 *pp_port_index, &mod_id, &port_id)); 3202 3203 /* Check if the mapped CoE-(mod,port) is valid */ 3204 if(_bcm_stk_aux_modport_valid(unit, BCM_MODID_TYPE_COE, 3205 mod_id, port_id) != BCM_E_NONE) { 3206 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3207 (BSL_META_U(unit,"ERROR: pp_port (%d) Mapped (mod,port)" 3208 "(%d,%d) not created \n"), 3209 *pp_port_index, mod_id, port_id)); 3210 return BCM_E_CONFIG; 3211 } 3212 } 3213 } 3214 3215 /* Put together a CoE-MODPORT for subsequent use */ 3216 if(si->coe_stacking_mode) { 3217 BCM_GPORT_MODPORT_SET(config->subport_modport, mod_id, port_id); 3218 } 3219 3220 return BCM_E_NONE; 3221 } 3222 3223 /* 3224 * Function: 3225 * _bcmi_linkphy_subport_stream_int_stream_get 3226 * Purpose: 3227 * Return an internal stream id for a given external 3228 * stream id 3229 * Parameters: 3230 * unit - (IN) Device number. 3231 * config - (IN LInkphy port config info 3232 * ext_stream_id - (IN) External stream id value 3233 * blk_int_stream_id - (OUT) Internal stream id value 3234 * Returns: 3235 * BCM_E_XXX 3236 */ 3237 STATIC int 3238 _bcmi_linkphy_subport_stream_int_stream_get(int unit, 3239 bcm_subport_config_t *config, 3240 int ext_stream_id, 3241 uint16 *blk_int_stream_id) 3242 { 3243 uint16 ext_stream_id_base = 0; 3244 int phy_port = 0; 3245 uint16 port_e_stream_id_base_adj = 0; 3246 int lp_block, lp_index, rv = BCM_E_NONE; 3247 3248 /* Get the associated physical phy_port */ 3249 phy_port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group); 3250 3251 /* Get the stream id base for this physical phy_port */ 3252 rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, phy_port, 3253 &ext_stream_id_base); 3254 if (BCM_FAILURE(rv)) { 3255 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3256 (BSL_META_U(unit, 3257 "ERROR: Linkphy subport group external stream id " 3258 "base get failed for phy_port %d.\n"), phy_port)); 3259 return rv; 3260 } 3261 3262 rv = soc_linkphy_port_blk_idx_get(unit, phy_port, &lp_block, &lp_index); 3263 if (SOC_FAILURE(rv)) { 3264 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3265 (BSL_META_U(unit, 3266 "ERROR: LinkPHY block, index get failed for phy_port %d\n"), 3267 phy_port)); 3268 return rv; 3269 } 3270 3271 /* Compute the port stream id base */ 3272 port_e_stream_id_base_adj = ext_stream_id - ext_stream_id_base; 3273 3274 /* Get the associated internal stream id for this ext stream*/ 3275 BCM_IF_ERROR_RETURN( 3276 _bcm_linkphy_port_rx_int_stream_map_port_get(unit, phy_port, 3277 port_e_stream_id_base_adj, blk_int_stream_id)); 3278 3279 return BCM_E_NONE; 3280 } 3281 3282 /* 3283 * Function: 3284 * _bcmi_linkphy_subport_stream_dfc_update 3285 * Purpose: 3286 * Updates the DFC state for a given ext stream id 3287 * Parameters: 3288 * unit - (IN) Device number. 3289 * config - (IN LInkphy port config info 3290 * pp_port_index - (IN) pp_port this external stream is a part of 3291 * ext_stream_id - (IN) External stream id value 3292 * enable - (IN) Port enable/disable status. 3293 * Returns: 3294 * BCM_E_XXX 3295 */ 3296 extern int 3297 _bcmi_linkphy_subport_stream_dfc_update(int unit, 3298 bcm_subport_config_t *config, 3299 int pp_port_index, 3300 int ext_stream_id, 3301 int enable) 3302 { 3303 uint16 blk_int_stream_id = 0; 3304 int phy_port = 0; 3305 int rv = BCM_E_NONE; 3306 3307 /* Get the internal stream associated with this ext stream id */ 3308 BCM_IF_ERROR_RETURN(_bcmi_linkphy_subport_stream_int_stream_get(unit, config, 3309 ext_stream_id, &blk_int_stream_id)); 3310 3311 /* Get the associated physical phy_port */ 3312 phy_port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group); 3313 3314 /* RXLP */ 3315 /* Update the DFC state for this stream */ 3316 rv = _bcm_linkphy_port_rx_flow_control_set(unit, phy_port, 3317 blk_int_stream_id, enable); 3318 if (SOC_FAILURE(rv)) { 3319 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3320 (BSL_META_U(unit, 3321 "ERROR: RX flow control update failed\n" 3322 " for, internal ext_stream_id = %d.\n"), 3323 blk_int_stream_id)); 3324 return rv; 3325 } 3326 3327 return rv; 3328 } 3329 3330 /* 3331 * Function: 3332 * _bcmi_linkphy_subport_stream_flush 3333 * Purpose: 3334 * Performs a flushe for the given ext stream ids 3335 * Parameters: 3336 * unit - (IN) Device number. 3337 * config - (IN LInkphy port config info 3338 * pp_port_index - (IN) pp_port this external stream is a part of 3339 * ext_stream_id - (IN) External stream id value 3340 * Returns: 3341 * BCM_E_XXX 3342 */ 3343 extern int 3344 _bcmi_linkphy_subport_stream_flush(int unit, 3345 bcm_subport_config_t *config, 3346 int pp_port_index, 3347 int ext_stream_id) 3348 { 3349 uint16 blk_int_stream_id = 0; 3350 int phy_port = 0, poll_active = 0; 3351 int rv = BCM_E_NONE; 3352 uint32 timeoutval = 0, regval = 0; 3353 soc_timeout_t timeout; 3354 soc_reg_t reg; 3355 3356 /* Get the internal stream associated with this ext stream id */ 3357 BCM_IF_ERROR_RETURN(_bcmi_linkphy_subport_stream_int_stream_get(unit, config, 3358 ext_stream_id, &blk_int_stream_id)); 3359 3360 /* Get the associated physical phy_port */ 3361 phy_port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group); 3362 3363 /* Perform an RX flush */ 3364 reg = RXLP_SW_FLUSH_CONTROLr; 3365 if (SOC_REG_PORT_VALID(unit, reg, phy_port)) { 3366 3367 timeoutval = _BCM_KT2_LINKPHY_STREAM_ID_FLUSH_TIMEOUT; 3368 soc_timeout_init(&timeout, timeoutval, 0); 3369 3370 /* If warmboot is enabled, HW calls just get written in cache 3371 * and does not write into HW. So FLUSH timeouts are seen during 3372 * exit clean which enables warmboot mode. Hence checking for 3373 * SOC_WARM_BOOT. 3374 */ 3375 if (!(SAL_BOOT_SIMULATION || SOC_WARM_BOOT(unit))) { 3376 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, reg, 3377 phy_port, FLUSH_STREAM_IDf, blk_int_stream_id)); 3378 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, reg, 3379 phy_port, FLUSH_ACTIVEf, 1)); 3380 3381 poll_active = 1; 3382 3383 while (poll_active) { 3384 3385 if (soc_timeout_check(&timeout)) { 3386 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3387 (BSL_META_U(unit, 3388 "ERROR: RX stream id %d flush timeout :" 3389 "phy_port = %d, pp_port %d\n"), 3390 blk_int_stream_id, 3391 phy_port, pp_port_index)); 3392 return BCM_E_TIMEOUT; 3393 } 3394 3395 BCM_IF_ERROR_RETURN( 3396 READ_RXLP_SW_FLUSH_CONTROLr(unit, phy_port, ®val)); 3397 3398 poll_active = (soc_reg_field_get(unit, reg, regval, 3399 FLUSH_DONEf)) ? 0 :1; 3400 3401 } 3402 } 3403 } 3404 3405 return rv; 3406 } 3407 3408 /* 3409 * Function: 3410 * _bcm_linkphy_subport_port_add 3411 * Purpose: 3412 * Add a LinkPHY subport to a subport group 3413 * Parameters: 3414 * unit - (IN) Device Number 3415 * config - (IN) Subport config information 3416 * port - (OUT) Subport_port GPORT (generic port) identifier 3417 * Returns: 3418 * BCM_E_XXX 3419 */ 3420 STATIC int 3421 _bcm_linkphy_subport_port_add(int unit, 3422 bcm_subport_config_t *config, 3423 bcm_gport_t *gport) 3424 { 3425 int rv = BCM_E_NONE, port = 0, enable = 0, lp_index = 0, lp_block = 0; 3426 int sp_group_idx = -1, i = 0; 3427 int start_addr = 0, end_addr = 0; 3428 uint16 dev_int_stream_id_base = 0, ext_stream_id_base = 0; 3429 uint32 dev_int_stream_id[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0, 0}; 3430 uint16 ext_stream_id[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0, 0}; 3431 int pp_port_index = 0; 3432 soc_mem_t mem; 3433 soc_info_t *si = &SOC_INFO(unit); 3434 device_stream_id_to_pp_port_map_entry_t dev_sid_to_pp_entry; 3435 pp_port_to_physical_port_map_entry_t pp_to_port_entry; 3436 uint32 two_s1s_in_s0_config = 0; 3437 uint32 blk_int_stream_id[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0, 0}; 3438 int num_max_stream = si->lp_streams_per_subport; 3439 uint32 blk_port_idx_int_stream_id[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0, 0}; 3440 soc_pbmp_t pbmp_linkphy_one_stream_per_subport; 3441 3442 /* A. PARAMETER VALIDATION 3443 */ 3444 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 3445 3446 /* Make sure the group exists */ 3447 if (!_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(config->group)) { 3448 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3449 (BSL_META_U(unit, 3450 "ERROR: subport group 0x%x is not LinkPHY group\n"), 3451 config->group)); 3452 return BCM_E_PARAM; 3453 } 3454 3455 sp_group_idx = 3456 _BCM_KT2_SUBPORT_GROUP_ID_GET(config->group); 3457 if (!_BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_GET(unit, sp_group_idx)) { 3458 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3459 (BSL_META_U(unit, 3460 "ERROR: subport group 0x%x does not exist. group id =%d\n"), 3461 config->group, sp_group_idx)); 3462 return BCM_E_NOT_FOUND; 3463 } 3464 3465 port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group); 3466 rv = soc_linkphy_port_blk_idx_get(unit, port, &lp_block, &lp_index); 3467 if (SOC_FAILURE(rv)) { 3468 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3469 (BSL_META_U(unit, 3470 "ERROR: LinkPHY block, index get failed for port %d\n"), 3471 port)); 3472 return rv; 3473 } 3474 3475 /* Check if port is member of pbmp_linkphy */ 3476 if (!SOC_PBMP_MEMBER(si->linkphy_pbm, port)) { 3477 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3478 (BSL_META_U(unit, 3479 "ERROR: Port %d is not member of pbmp_linkphy\n"), 3480 port)); 3481 return BCM_E_PORT; 3482 } 3483 3484 if (si->port_num_subport[port] <= 0) { 3485 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3486 (BSL_META_U(unit, 3487 "ERROR: %d number of subports available for port %d\n"), 3488 si->port_num_subport[port], port)); 3489 return BCM_E_CONFIG; 3490 } 3491 SOC_PBMP_CLEAR(pbmp_linkphy_one_stream_per_subport); 3492 if (SOC_IS_SABER2(unit)) { 3493 pbmp_linkphy_one_stream_per_subport = 3494 soc_property_get_pbmp(unit, spn_PBMP_LINKPHY_ONE_STREAM_PER_SUBPORT, 0); 3495 } 3496 if (SOC_PBMP_MEMBER(pbmp_linkphy_one_stream_per_subport, port)) { 3497 num_max_stream = 1; 3498 } 3499 if (config->num_streams > num_max_stream) { 3500 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3501 (BSL_META_U(unit, 3502 "ERROR: num_streams %d cannot be greater than %d\n"), 3503 config->num_streams, num_max_stream)); 3504 return BCM_E_PARAM; 3505 } 3506 3507 if (config->prop_flags & BCM_SUBPORT_PROPERTY_PHB) { 3508 if ((config->int_pri < 0 || config->int_pri >= (1 << 4)) || 3509 ((config->color != bcmColorGreen) && 3510 (config->color != bcmColorYellow) && 3511 (config->color != bcmColorRed))) { 3512 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3513 (BSL_META_U(unit, 3514 "ERROR: int_pri %d or color %d is invalid\n"), 3515 config->int_pri, config->color)); 3516 return BCM_E_PARAM; 3517 } 3518 } 3519 3520 if (_bcm_subport_group_subport_port_count[unit][sp_group_idx] > 0) { 3521 /* This is not the first linkphy subport in the port. Hence 2_s1s_in_s0 3522 * config would have been already set. Check if it matches with the 3523 * config->num_streams passed. We cannot allow mix and match of 3524 * num_streams between different subports of same 3525 * subport_group(linkphy port). 3526 */ 3527 two_s1s_in_s0_config = soc_kt2_cosq_two_s1s_in_s0_config_get(unit, port); 3528 if (((config->num_streams == 1) && (two_s1s_in_s0_config)) || 3529 ((config->num_streams == 2) && (!two_s1s_in_s0_config))) { 3530 return BCM_E_PARAM; 3531 } 3532 } 3533 3534 rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, port, 3535 &ext_stream_id_base); 3536 if (BCM_FAILURE(rv)) { 3537 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3538 (BSL_META_U(unit, 3539 "ERROR: Linkphy port %d external " 3540 "stream id base get failed\n"), port)); 3541 return rv; 3542 } 3543 3544 dev_int_stream_id_base = (lp_block)? 128: 0; 3545 3546 for (i = 0; i < config->num_streams; i++) { 3547 /* Check stream_id range for the port */ 3548 3549 #if defined(BCM_SABER2_SUPPORT) 3550 if (SOC_IS_SABER2(unit)) { 3551 if (config->stream_id_array[i] >= 3552 (ext_stream_id_base + 3553 (SOC_INFO(unit).lp_streams_per_slice_max * (lp_block + 1)))) { 3554 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3555 (BSL_META_U(unit, 3556 "*ERROR: stream_id %d is out of range for port %d\n"), 3557 config->stream_id_array[i], port)); 3558 return BCM_E_PARAM; 3559 } 3560 } else 3561 #endif 3562 { 3563 if (config->stream_id_array[i] >= 3564 (ext_stream_id_base + si->port_num_subport[port] 3565 * _BCM_KT2_LINKPHY_MAX_STREAM_IDS_PER_PORT)) { 3566 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3567 (BSL_META_U(unit, 3568 "*ERROR: stream_id %d is out of range for port %d\n"), 3569 config->stream_id_array[i], port)); 3570 return BCM_E_PARAM; 3571 } 3572 } 3573 3574 /* check if external stream id is in use on the port */ 3575 rv = _bcmi_linkphy_subport_ext_stream_id_in_use(unit, config, 3576 config->stream_id_array[i]); 3577 if (BCM_FAILURE(rv)) { 3578 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3579 (BSL_META_U(unit, 3580 "*ERROR: External stream id %d is in use!! - %s\n"), 3581 config->stream_id_array[i], bcm_errmsg(rv))); 3582 return rv; 3583 } 3584 3585 /* 3586 * Check if the device internal stream_id is already active 3587 * Device Internal stream id can be active only on one port at a time. 3588 */ 3589 ext_stream_id[i] = config->stream_id_array[i] - ext_stream_id_base; 3590 3591 #if defined(BCM_METROLITE_SUPPORT) 3592 if (SOC_IS_METROLITE(unit)) { 3593 /* Allocate a internal stream id for the given external stream id. 3594 * Index will be 0 to 3 whereas Port numbers would be 1 to 4. Hence 3595 * using port - 1 as the index. 3596 * For Metrolite, dev internal stream id and internal stream id are same 3597 * since dev internal stream id base is 0. 3598 */ 3599 rv = shr_idxres_list_alloc(_bcm_ml_int_stream_id_pool[unit][port - 1], 3600 (shr_idxres_element_t *)(&(blk_int_stream_id[i]))); 3601 3602 } else 3603 #endif 3604 #if defined(BCM_SABER2_SUPPORT) 3605 if (SOC_IS_SABER2(unit)) { 3606 /* Allocate a internal stream id for the given external stream id. 3607 * Index will be 0 to 3 whereas Port numbers would be 1 to 4. Hence 3608 * using port - 1 as the index. 3609 * For SB2, dev internal stream id and internal stream id are same 3610 * since dev internal stream id base is 0. 3611 */ 3612 rv = shr_idxres_list_alloc(_bcm_sb2_int_stream_id_pool[unit][port -1], 3613 (shr_idxres_element_t *)(&(blk_int_stream_id[i]))); 3614 } else 3615 #endif 3616 { 3617 /* 3618 * Allocate a internal stream id for this linkphy block 3619 * for the given external stream id. 3620 * The internal stream id is in the range of 0 to 127 3621 * per linkphy block. 3622 */ 3623 rv = shr_idxres_list_alloc( 3624 _bcm_kt2_blk_int_stream_id_pool[unit][lp_block][lp_index], 3625 (shr_idxres_element_t *)(&(blk_port_idx_int_stream_id[i]))); 3626 } 3627 3628 if (BCM_FAILURE(rv)) { 3629 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3630 (BSL_META_U(unit, 3631 "*ERROR: Internal stream id alloc failed for " 3632 "External stream_id %d - %s\n"), 3633 config->stream_id_array[i], bcm_errmsg(rv))); 3634 return rv; 3635 } 3636 3637 if(!SOC_IS_SABER2(unit) && !SOC_IS_METROLITE(unit)) { 3638 blk_int_stream_id[i] = (si->port_linkphy_s1_base[port] 3639 - dev_int_stream_id_base) 3640 + blk_port_idx_int_stream_id[i]; 3641 } 3642 /* 3643 * Device Internal stream Id is in the range 0 to 255. 3644 * (Internal stream id of block) + (block stream id base) 3645 */ 3646 dev_int_stream_id[i] = blk_int_stream_id[i] + dev_int_stream_id_base; 3647 3648 if (dev_int_stream_id[i] > soc_mem_index_max(unit, 3649 DEVICE_STREAM_ID_TO_PP_PORT_MAPm)) { 3650 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3651 (BSL_META_U(unit, 3652 "ERROR: device internal stream_id %d is out of " 3653 "range for \nport %d. internal stream id base %d, " 3654 "internal stream id %d\n"), 3655 dev_int_stream_id[i], port, 3656 dev_int_stream_id_base, blk_int_stream_id[i])); 3657 3658 return BCM_E_PARAM; 3659 } 3660 3661 if (_BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_GET(unit, 3662 dev_int_stream_id[i])) { 3663 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3664 (BSL_META_U(unit, 3665 "ERROR: Device internal stream_id %d already used.\n"), 3666 dev_int_stream_id[i])); 3667 return BCM_E_EXISTS; 3668 } 3669 } 3670 3671 /* B. PP_PORT INDEX RESERVATION 3672 */ 3673 /* C. PP_PORT INDEX RESERVATION 3674 */ 3675 /* Reserve PP_PORT index */ 3676 BCM_IF_ERROR_RETURN(_bcm_kt2_allocate_pp_port(unit, config, &pp_port_index)); 3677 3678 3679 /* C. RXLP/TXLP PROGRAMMING 3680 */ 3681 for (i = 0; i < config->num_streams; i++) { 3682 3683 mem = DEVICE_STREAM_ID_TO_PP_PORT_MAPm; 3684 3685 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, dev_int_stream_id[i], 3686 &dev_sid_to_pp_entry); 3687 3688 soc_mem_field32_set(unit, mem, (uint32 *)&dev_sid_to_pp_entry, 3689 PP_PORTf, pp_port_index); 3690 3691 /* Set PHB for the subport */ 3692 if (config->prop_flags & BCM_SUBPORT_PROPERTY_PHB) { 3693 soc_mem_field32_set(unit, mem, (uint32 *)&dev_sid_to_pp_entry, 3694 PHB_VALIDf, 1); 3695 soc_mem_field32_set(unit, mem, (uint32 *)&dev_sid_to_pp_entry, 3696 INT_PRIf, config->int_pri); 3697 soc_mem_field32_set(unit, mem, (uint32 *)&dev_sid_to_pp_entry, 3698 CNGf, config->color); 3699 } 3700 3701 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, dev_int_stream_id[i], 3702 &dev_sid_to_pp_entry); 3703 3704 if (SOC_FAILURE(rv)) { 3705 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3706 (BSL_META_U(unit, 3707 "ERROR: device internal stream id %d to pp_port %d " 3708 "map failed.\n"), dev_int_stream_id[i], pp_port_index)); 3709 3710 return rv; 3711 } 3712 SOC_IF_ERROR_RETURN 3713 (soc_kt2_cosq_lp_repl_map_set(unit, dev_int_stream_id[i], pp_port_index, 1)); 3714 3715 /* 3716 * Steps to Enable New-Stream 3717 * while traffic is flowing on other streams of a Port.: 3718 * ======================================================== 3719 * TXLP: 3720 * 1.First program the active-stream-bitmap-table with this stream. 3721 * 2.Program the INTERNAL-2-EXTERNAL mapping table for the new-stream. 3722 * 3.Program the Address-Map-table for that stream. 3723 * 4.After Step-3, TXLP will send requests to MMU for this stream 3724 * and traffic will commence. 3725 * 3726 * RXLP: 3727 * 1.Reconfigure RXLP_PORT_ACTIVE_STREAM_BITMAP_LO/HI based on 3728 * the internal stream ID of the new stream. 3729 * 2.Configure mapping of external stream ID to internal space in the 3730 * table RXLP_INTERNAL_STREAM_MAP_PORT_<0/1/2/3> depending on 3731 * the port where the new stream is added. 3732 * 3.Configure table RXLP_MAX_FRAME_SIZE for the newly added stream ID. 3733 */ 3734 3735 /* TXLP */ 3736 3737 enable = 1; 3738 3739 rv = _bcm_linkphy_port_tx_active_stream_set(unit, 3740 port, blk_int_stream_id[i], enable); 3741 if (SOC_FAILURE(rv)) { 3742 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3743 (BSL_META_U(unit, 3744 "ERROR: TX active stream bitmap enable failed.\n" 3745 "port %d, internal stream_id = %d.\n"), 3746 port, blk_int_stream_id[i])); 3747 3748 return rv; 3749 } 3750 3751 rv = _bcm_linkphy_port_tx_int_to_ext_stream_map_set(unit, 3752 port, config->stream_id_array[i], 3753 blk_int_stream_id[i], enable); 3754 if (SOC_FAILURE(rv)) { 3755 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3756 (BSL_META_U(unit, 3757 "ERROR: TX internal to external stream mapping failed.\n" 3758 "port %d, blk internal stream_id = %d, " 3759 "external stream id = %d.\n"), 3760 port, blk_int_stream_id[i], config->stream_id_array[i])); 3761 3762 return rv; 3763 } 3764 3765 /* 3766 * Add start and end address management for TXL Data Buffer. 3767 * 856 cells have to be distributed across 128 internal streams. 3768 * Assuming that by default each stream speed is < 1G we will 3769 * reserve 6 cells for each stream by default (6 * 128 = 768). 3770 * Remainig cells can be used when stream speed is 3771 * set to 10G as per following scheme. 3772 * Stream-Speed(Gbps) | Min Num.Cells 3773 * < 1G | 3 3774 * 1G | 6 3775 * 10G | 50 3776 */ 3777 3778 /* 3779 * each cell occupies 4 lines of buffer. 3780 * Assume that by default each stream speed is 1G. 3781 * so 24 lines of buffer are needed. 3782 */ 3783 3784 start_addr = SOC_INFO(unit).lp_tx_stream_start_addr_offset + 3785 (SOC_INFO(unit).lp_tx_databuf_end_addr_min + 1) * 3786 blk_int_stream_id[i]; 3787 end_addr = start_addr + SOC_INFO(unit).lp_tx_databuf_end_addr_min; 3788 3789 rv = _bcm_linkphy_port_tx_stream_addr_map_set(unit, 3790 port, blk_int_stream_id[i], start_addr, end_addr, enable); 3791 if (SOC_FAILURE(rv)) { 3792 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3793 (BSL_META_U(unit, 3794 "ERROR: TX data buffer address set failed.\n" 3795 "port %d, internal stream_id = %d, start_addr = %d " 3796 "end_addr = %d.\n"), port, blk_int_stream_id[i], 3797 start_addr, end_addr)); 3798 return rv; 3799 } 3800 3801 /* RXLP */ 3802 3803 rv = _bcm_linkphy_port_rx_active_stream_bitmap_set(unit, 3804 port, blk_int_stream_id[i], enable); 3805 if (SOC_FAILURE(rv)) { 3806 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3807 (BSL_META_U(unit, 3808 "ERROR: RX active stream enable failed\n" 3809 " port %d, internal stream_id = %d.\n"), port, 3810 blk_int_stream_id[i])); 3811 return rv; 3812 } 3813 3814 rv = _bcm_linkphy_port_rx_int_stream_map_port_set(unit, 3815 port, ext_stream_id[i], blk_int_stream_id[i], enable); 3816 if (SOC_FAILURE(rv)) { 3817 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3818 (BSL_META_U(unit, 3819 "ERROR: RX stream map for port enable failed.\n" 3820 "port %d, external stream_id = %d, " 3821 "internal stream_id = %d.\n"), 3822 port, ext_stream_id[i], blk_int_stream_id[i])); 3823 3824 return rv; 3825 } 3826 3827 _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_SET(unit, dev_int_stream_id[i]); 3828 3829 _bcm_linkphy_subport_port_info[unit] 3830 [pp_port_index].ext_stream_idx[i] = config->stream_id_array[i]; 3831 } 3832 3833 rv = soc_kt2_cosq_two_s1s_in_s0_config_set(unit, port, 3834 (config->num_streams > 1)?1:0); 3835 if (SOC_FAILURE(rv)) { 3836 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3837 (BSL_META_U(unit, 3838 "ERROR: 2 s1s in s0 config failed %s for port %d" 3839 "\n"), bcm_errmsg(rv), port)); 3840 return rv; 3841 } 3842 3843 /* 3844 * Map PP_PORT to Physical port mapping (IP/ EP): 3845 * Use the PP_PORT_TO_PHYSICAL_PORT_MAP 3846 */ 3847 mem = PP_PORT_TO_PHYSICAL_PORT_MAPm; 3848 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, pp_port_index, 3849 &pp_to_port_entry); 3850 3851 soc_mem_field32_set(unit, mem, (uint32 *)&pp_to_port_entry, 3852 DESTINATIONf, port); 3853 soc_mem_field32_set(unit, mem, (uint32 *)&pp_to_port_entry, 3854 ISTRUNKf, 0); 3855 3856 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, pp_port_index, 3857 &pp_to_port_entry); 3858 3859 if (SOC_FAILURE(rv)) { 3860 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3861 (BSL_META_U(unit, 3862 "ERROR: pp_port id %d to physical port %d " 3863 "map failed.\n"), pp_port_index, port)); 3864 for (i = 0; i < config->num_streams; i++) { 3865 _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_CLR(unit, 3866 dev_int_stream_id[i]); 3867 } 3868 return rv; 3869 } 3870 3871 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_SET(unit, pp_port_index, 3872 config->group, config->num_streams, TRUE); 3873 3874 _BCM_KT2_SUBPORT_PORT_ID_SET(*gport, pp_port_index); 3875 3876 /* Reset the subport_modport */ 3877 config->subport_modport = 0; 3878 3879 _BCM_KT2_SUBPORT_PORT_TYPE_SET(*gport, _BCM_KT2_SUBPORT_TYPE_LINKPHY); 3880 3881 *(_bcm_subport_group_subport_port_count[unit]+ sp_group_idx) += 1; 3882 3883 _BCM_KT2_SUBPORT_PP_PORT_USED_SET(unit, pp_port_index); 3884 _bcm_subport_pp_port_count[unit]++; 3885 3886 /* Add to enabled_linkphy_pbm */ 3887 BCM_PBMP_PORT_ADD(si->enabled_linkphy_pp_port_pbm, pp_port_index); 3888 3889 #ifdef BCM_WARM_BOOT_SUPPORT 3890 SOC_CONTROL_LOCK(unit); 3891 SOC_CONTROL(unit)->scache_dirty = 1; 3892 SOC_CONTROL_UNLOCK(unit); 3893 #endif 3894 3895 return rv; 3896 } 3897 3898 /* 3899 * Function: 3900 * _bcm_linkphy_subport_port_delete 3901 * Purpose: 3902 * Delete a LinkPHY subport_port 3903 * Parameters: 3904 * unit - (IN) Device Number 3905 * port - (IN) Subport_port GPORT (generic port) identifier 3906 * Returns: 3907 * BCM_E_XXX 3908 */ 3909 STATIC int 3910 _bcm_linkphy_subport_port_delete(int unit, 3911 bcm_gport_t subport_port_gport) 3912 { 3913 int rv = BCM_E_NONE, group_id = 0; 3914 int port = 0, subport_group = -1, disable = 0, poll_active = 0; 3915 int dev_int_stream_id[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0, 0}; 3916 int num_streams = 0, i = 0; 3917 uint16 dev_int_stream_id_base = 0, ext_stream_id_base = 0; 3918 uint16 port_e_stream_id_base_adj[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0}; 3919 uint16 pp_port_index = 0; 3920 uint32 timeoutval = 0, regval = 0; 3921 soc_timeout_t timeout; 3922 soc_reg_t reg; 3923 soc_mem_t mem; 3924 int lp_block = 0, lp_index = 0; 3925 uint16 blk_int_stream_id[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0, 0}; 3926 uint16 blk_port_idx_int_stream_id[BCM_SUBPORT_CONFIG_MAX_STREAMS] = {0, 0}; 3927 soc_info_t *si = &SOC_INFO(unit); 3928 3929 if (!_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, subport_port_gport)) { 3930 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3931 (BSL_META_U(unit, 3932 "ERROR: gport 0x%x is not LinkPHY subport port type.\n"), 3933 subport_port_gport)); 3934 return BCM_E_PARAM; 3935 } 3936 3937 pp_port_index = _BCM_KT2_SUBPORT_PORT_ID_GET(subport_port_gport); 3938 3939 if (!_BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port_index)) { 3940 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3941 (BSL_META_U(unit, 3942 "ERROR: LinkPHY subport port gport 0x%x is invalid\n"), 3943 subport_port_gport)); 3944 return BCM_E_NOT_FOUND; 3945 } 3946 3947 num_streams = _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_NUM_STREAMS_GET(unit, 3948 pp_port_index); 3949 if (num_streams == -1) { 3950 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3951 (BSL_META_U(unit, 3952 "ERROR: Subport port 0x%x does not have any streams.\n"), 3953 subport_port_gport)); 3954 return BCM_E_NOT_FOUND; 3955 } 3956 3957 subport_group = 3958 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port_index); 3959 3960 port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(subport_group); 3961 3962 rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, port, 3963 &ext_stream_id_base); 3964 if (BCM_FAILURE(rv)) { 3965 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3966 (BSL_META_U(unit, 3967 "ERROR: Linkphy subport group external stream id " 3968 "base get failed for port %d.\n"), port)); 3969 return rv; 3970 } 3971 3972 rv = soc_linkphy_port_blk_idx_get(unit, port, &lp_block, &lp_index); 3973 if (SOC_FAILURE(rv)) { 3974 LOG_ERROR(BSL_LS_BCM_SUBPORT, 3975 (BSL_META_U(unit, 3976 "ERROR: LinkPHY block, index get failed for port %d\n"), 3977 port)); 3978 return rv; 3979 } 3980 dev_int_stream_id_base = (lp_block)? 128: 0; 3981 3982 /*Disable a Stream while traffic is flowing on other streams of a Port: 3983 * RXLP: 3984 * 1.Set the bit corresponding to the internal stream ID in the register 3985 * RXLP_DFC_STATUS_LO/HI to XON. 3986 * This is to enable flushing of the data egressing to that stream 3987 * from the TXLP. 3988 * 2.Ensure that the stream being disabled in not sending in data anymore 3989 * 3.Flush the left over data (partial cell, if any) for the stream 3990 * in the RXLP by writing to the register RXLP_SW_FLUSH_CONTROL. 3991 * 4.Poll the FLUSH_DONE bit in the register RXLP_SW_FLUSH_CONTROL. 3992 * Once this bit is read as 1, proceed to the next step. 3993 * 5.Write 0 to the bit corresponding to the internal stream ID 3994 * in the register RXLP_PORT_ACTIVE_STREAM_BITMAP_LO/HI. 3995 * 6.Clear the configuration corresponding to the stream in 3996 * the table RXLP_INTERNAL_STREAM_MAP_PORT_<0/1/2/3> depending 3997 * on the port where the stream being disabled resides. 3998 * 3999 * TXLP: 4000 * 1. Disabling a stream MUST be done after all the packets 4001 * for that stream have been drained from {MMU-TXLP} sub-system. 4002 * This is like Stream/Queue-flush initiated by MMU. 4003 * 2.Once it has been ascertained that {MMU, TXLP} have been drained, 4004 * only then can s/w disable the stream by removing the stream 4005 * from ACTIVE-STREAM-BITMAP for that port. 4006 * 3.ADDR-MAP for this stream should be programmed to ZEROS. 4007 * This will also RESET the outstanding MMU-Credit for that SID. 4008 * (The same must also be done in MMU). 4009 */ 4010 4011 for (i = 0; i < num_streams; i++) { 4012 4013 port_e_stream_id_base_adj[i] = 4014 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_EXT_STREAM_ID_GET( 4015 unit, pp_port_index, i) - ext_stream_id_base; 4016 4017 BCM_IF_ERROR_RETURN( 4018 _bcm_linkphy_port_rx_int_stream_map_port_get(unit, port, 4019 port_e_stream_id_base_adj[i], &(blk_int_stream_id[i]))); 4020 4021 dev_int_stream_id[i] = blk_int_stream_id[i] + dev_int_stream_id_base; 4022 4023 mem = DEVICE_STREAM_ID_TO_PP_PORT_MAPm; 4024 if (dev_int_stream_id[i] > soc_mem_index_max(unit,mem)) { 4025 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4026 (BSL_META_U(unit, 4027 "ERROR: device internal stream_id %d is out of range \n" 4028 "port %d, internal stream id base %d, " 4029 "internal stream id %d " 4030 "pp_port %d\n"), dev_int_stream_id[i], port, 4031 dev_int_stream_id_base, port_e_stream_id_base_adj[i], 4032 pp_port_index)); 4033 return BCM_E_PARAM; 4034 } 4035 4036 if (!_BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_GET(unit, 4037 dev_int_stream_id[i])) { 4038 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4039 (BSL_META_U(unit, 4040 "ERROR: LinkPHY subport port gport 0x%x is not found.\n" 4041 "Device internal stream_id = %d " 4042 "is not set for port %d\n"), 4043 subport_port_gport, dev_int_stream_id[i], port)); 4044 return BCM_E_NOT_FOUND; 4045 } 4046 4047 /* RXLP */ 4048 disable = 0; 4049 rv = _bcm_linkphy_port_rx_flow_control_set(unit, port, 4050 blk_int_stream_id[i], disable); 4051 if (SOC_FAILURE(rv)) { 4052 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4053 (BSL_META_U(unit, 4054 "ERROR: RX flow control disable failed\n" 4055 " for, internal stream_id = %d.\n"), 4056 blk_int_stream_id[i])); 4057 return rv; 4058 } 4059 4060 reg = RXLP_SW_FLUSH_CONTROLr; 4061 if (SOC_REG_PORT_VALID(unit, reg, port)) { 4062 4063 timeoutval = _BCM_KT2_LINKPHY_STREAM_ID_FLUSH_TIMEOUT; 4064 soc_timeout_init(&timeout, timeoutval, 0); 4065 4066 /* If warmboot is enabled, HW calls just get written in cache 4067 * and does not write into HW. So FLUSH timeouts are seen during 4068 * exit clean which enables warmboot mode. Hence checking for 4069 * SOC_WARM_BOOT. 4070 */ 4071 if (!(SAL_BOOT_SIMULATION || SOC_WARM_BOOT(unit))) { 4072 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, reg, 4073 port, FLUSH_STREAM_IDf, blk_int_stream_id[i])); 4074 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, reg, 4075 port, FLUSH_ACTIVEf, 1)); 4076 4077 poll_active = 1; 4078 4079 while (poll_active) { 4080 4081 if (soc_timeout_check(&timeout)) { 4082 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4083 (BSL_META_U(unit, 4084 "ERROR: RX stream id %d flush timeout :" 4085 "subport_port gport 0x%x, port = %d, " 4086 "pp_port %d\n"), 4087 blk_int_stream_id[i], subport_port_gport, 4088 port, pp_port_index)); 4089 return BCM_E_TIMEOUT; 4090 } 4091 4092 BCM_IF_ERROR_RETURN( 4093 READ_RXLP_SW_FLUSH_CONTROLr(unit, port, ®val)); 4094 4095 poll_active = (soc_reg_field_get(unit, reg, regval, 4096 FLUSH_DONEf)) ? 0 :1; 4097 4098 } 4099 } 4100 } 4101 4102 rv = _bcm_linkphy_port_rx_active_stream_bitmap_set(unit, 4103 port, blk_int_stream_id[i], disable); 4104 if (SOC_FAILURE(rv)) { 4105 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4106 (BSL_META_U(unit, 4107 "ERROR: RX active stream disable failed\n" 4108 " port %d, internal stream_id = %d.\n"), 4109 port, blk_int_stream_id[i])); 4110 return rv; 4111 } 4112 4113 rv = _bcm_linkphy_port_rx_int_stream_map_port_set(unit, port, 4114 port_e_stream_id_base_adj[i], 4115 blk_int_stream_id[i], disable); 4116 if (SOC_FAILURE(rv)) { 4117 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4118 (BSL_META_U(unit, 4119 "ERROR: RX stream map for port clear failed.\n" 4120 "port %d, internal stream_id = %d.\n"), 4121 port, port_e_stream_id_base_adj[i])); 4122 return rv; 4123 } 4124 4125 /* TXLP */ 4126 4127 4128 rv = _bcm_linkphy_port_tx_active_stream_set(unit, port, 4129 blk_int_stream_id[i], 4130 disable); 4131 if (SOC_FAILURE(rv)) { 4132 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4133 (BSL_META_U(unit, 4134 "ERROR: TX active stream bitmap disable failed.\n" 4135 "port %d, internal stream_id = %d.\n"), 4136 port, blk_int_stream_id[i])); 4137 return rv; 4138 } 4139 4140 rv = _bcm_linkphy_port_tx_int_to_ext_stream_map_set(unit, port, 0, 4141 blk_int_stream_id[i], 4142 disable); 4143 if (SOC_FAILURE(rv)) { 4144 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4145 (BSL_META_U(unit, 4146 "ERROR: TX int to ext stream map clear failed.\n" 4147 "port %d, int stream_id = %d, ext stream id = %d.\n"), 4148 port, blk_int_stream_id[i], 0)); 4149 return rv; 4150 } 4151 4152 rv = _bcm_linkphy_port_tx_stream_addr_map_set(unit, port, 4153 blk_int_stream_id[i], 4154 0, 0, disable); 4155 if (SOC_FAILURE(rv)) { 4156 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4157 (BSL_META_U(unit, 4158 "ERROR: TX data buffer address clear failed.\n" 4159 "port %d, internal stream_id = %d, start_addr = %d " 4160 "end_addr = %d.\n"), port, blk_int_stream_id[i], 0, 0)); 4161 return rv; 4162 } 4163 4164 /* 4165 * Clean Device Internal Stream ID to pp_port mapping 4166 */ 4167 mem = DEVICE_STREAM_ID_TO_PP_PORT_MAPm; 4168 rv = soc_mem_field32_modify(unit, mem, dev_int_stream_id[i], PP_PORTf, 0); 4169 if (SOC_FAILURE(rv)) { 4170 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4171 (BSL_META_U(unit, 4172 "ERROR: cleaning device internal stream id %d " 4173 "to pp_port map failed.\n"), 4174 dev_int_stream_id[i])); 4175 return rv; 4176 } 4177 /* Clean PHB for the subport */ 4178 BCM_IF_ERROR_RETURN(soc_mem_field32_modify( 4179 unit, mem, dev_int_stream_id[i], PHB_VALIDf, 0)); 4180 BCM_IF_ERROR_RETURN( 4181 soc_mem_field32_modify(unit, mem, dev_int_stream_id[i], 4182 INT_PRIf, 0)); 4183 BCM_IF_ERROR_RETURN( 4184 soc_mem_field32_modify(unit, mem, dev_int_stream_id[i], CNGf, 0)); 4185 SOC_IF_ERROR_RETURN 4186 (soc_kt2_cosq_lp_repl_map_set(unit, dev_int_stream_id[i], 0, 0)); 4187 4188 #if defined(BCM_METROLITE_SUPPORT) 4189 if (SOC_IS_METROLITE(unit)) { 4190 /* Remove the internal stream id from the port's pool */ 4191 BCM_IF_ERROR_RETURN(shr_idxres_list_free( 4192 _bcm_ml_int_stream_id_pool[unit][port-1], 4193 blk_int_stream_id[i])); 4194 } else 4195 #endif 4196 #if defined(BCM_SABER2_SUPPORT) 4197 if (SOC_IS_SABER2(unit)) { 4198 /* Remove the internal stream id from the port's pool */ 4199 BCM_IF_ERROR_RETURN(shr_idxres_list_free( 4200 _bcm_sb2_int_stream_id_pool[unit][port-1], 4201 blk_int_stream_id[i])); 4202 } else 4203 #endif 4204 { 4205 blk_port_idx_int_stream_id[i] = blk_int_stream_id[i] 4206 - (si->port_linkphy_s1_base[port] 4207 - dev_int_stream_id_base); 4208 /* Remove the internal stream id from the port's pool */ 4209 BCM_IF_ERROR_RETURN(shr_idxres_list_free( 4210 _bcm_kt2_blk_int_stream_id_pool[unit][lp_block][lp_index], 4211 blk_port_idx_int_stream_id[i])); 4212 } 4213 4214 _BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_CLR(unit, dev_int_stream_id[i]); 4215 4216 _bcm_linkphy_subport_port_info[unit] 4217 [pp_port_index].ext_stream_idx[i] = 0; 4218 } 4219 4220 /* 4221 * clean PP_PORT to Physical port mapping 4222 */ 4223 mem = PP_PORT_TO_PHYSICAL_PORT_MAPm; 4224 rv = soc_mem_field32_modify(unit,mem ,pp_port_index, DESTINATIONf, 0); 4225 if (SOC_FAILURE(rv)) { 4226 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4227 (BSL_META_U(unit, 4228 "ERROR: Cleaning pp_port id %d to physical port " 4229 "map failed.\n"), pp_port_index)); 4230 return rv; 4231 } 4232 4233 4234 _BCM_KT2_SUBPORT_PP_PORT_USED_CLR(unit, pp_port_index); 4235 _bcm_subport_pp_port_count[unit]--; 4236 4237 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(subport_group); 4238 *(_bcm_subport_group_subport_port_count[unit] + group_id) -= 1; 4239 4240 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_SET(unit, pp_port_index, 4241 BCM_GPORT_INVALID, -1, FALSE); 4242 4243 if (_bcm_subport_group_subport_port_count[unit][group_id] == 0) { 4244 /* This is the last subport deleted in this group. So reset the 4245 * 2_s1s_in_s0_config to 1 which is the default for the 4246 * linkphy port 4247 */ 4248 rv = soc_kt2_cosq_two_s1s_in_s0_config_set(unit, port, 1); 4249 if (SOC_FAILURE(rv)) { 4250 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4251 (BSL_META_U(unit, 4252 "ERROR: 2 s1s in s0 config failed %s for port %d\n"), 4253 bcm_errmsg(rv), port)); 4254 return rv; 4255 } 4256 } 4257 4258 /* Remove from enabled_linkphy_pbm */ 4259 BCM_PBMP_PORT_REMOVE(si->enabled_linkphy_pp_port_pbm, pp_port_index); 4260 4261 #ifdef BCM_WARM_BOOT_SUPPORT 4262 SOC_CONTROL_LOCK(unit); 4263 SOC_CONTROL(unit)->scache_dirty = 1; 4264 SOC_CONTROL_UNLOCK(unit); 4265 #endif 4266 4267 return rv; 4268 } 4269 4270 /* 4271 * Function: 4272 * _bcm_subport_physical_port_get 4273 * Purpose: 4274 * Get the local_port given subport pp_port 4275 * Parameters: 4276 * unit - (IN) Device Number 4277 * pp_port - (IN) Subport pp_port number 4278 * local_port - (OUT) Physical port number 4279 * Returns: 4280 * BCM_E_XXX 4281 */ 4282 int 4283 _bcm_subport_physical_port_get(int unit, int pp_port, 4284 int *local_port) 4285 { 4286 bcm_gport_t subport_group; 4287 if (local_port == NULL) { 4288 return BCM_E_PARAM; 4289 } 4290 4291 if (BCM_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) { 4292 subport_group = _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port); 4293 if (!BCM_GPORT_IS_SUBPORT_GROUP(subport_group)) { 4294 return BCM_E_PARAM; 4295 } 4296 } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) { 4297 subport_group = _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port); 4298 if (!BCM_GPORT_IS_SUBPORT_GROUP(subport_group)) { 4299 return BCM_E_PARAM; 4300 } 4301 } else { 4302 return BCM_E_PARAM; 4303 } 4304 *local_port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(subport_group); 4305 return BCM_E_NONE; 4306 } 4307 4308 /* 4309 * Function: 4310 * _bcm_linkphy_subport_port_get 4311 * Purpose: 4312 * Get the LinkPHY subport_port config (subport group gport and stream_id) 4313 * Parameters: 4314 * unit - (IN) Device Number 4315 * port - (IN) Subport_port GPORT (generic port) identifier 4316 * config - (OUT) Subport port config 4317 * Returns: 4318 * BCM_E_XXX 4319 */ 4320 STATIC int 4321 _bcm_linkphy_subport_port_get(int unit, 4322 bcm_gport_t subport_port_gport, 4323 bcm_subport_config_t *config) 4324 { 4325 int i = 0, port = 0, pp_port = 0; 4326 int rv = BCM_E_NONE; 4327 bcm_gport_t subport_group; 4328 uint16 dev_int_stream_id_base = 0, dev_int_stream_id = 0; 4329 uint16 port_e_stream_id_base_adj = 0; 4330 uint16 blk_int_stream_id = 0; 4331 uint16 ext_stream_id_base = 0; 4332 device_stream_id_to_pp_port_map_entry_t dev_sid_to_pp_entry; 4333 soc_mem_t mem; 4334 int lp_block = 0, lp_index = 0; 4335 4336 if (config == NULL) { 4337 return BCM_E_PARAM; 4338 } 4339 4340 pp_port = _BCM_KT2_SUBPORT_PORT_ID_GET(subport_port_gport); 4341 4342 subport_group = 4343 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port); 4344 4345 if (!BCM_GPORT_IS_SUBPORT_GROUP(subport_group)) { 4346 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4347 (BSL_META_U(unit, 4348 "ERROR:Invalid LinkPHY subport port gport 0x%x\n"), 4349 subport_port_gport)); 4350 return BCM_E_PARAM; 4351 } 4352 4353 if (!_BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) { 4354 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4355 (BSL_META_U(unit, 4356 "ERROR: LinkPHY subport port gport 0x%x is invalid\n"), 4357 subport_port_gport)); 4358 return BCM_E_NOT_FOUND; 4359 } 4360 4361 config->group = subport_group; 4362 4363 config->num_streams = 4364 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_NUM_STREAMS_GET(unit, pp_port); 4365 4366 port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group); 4367 4368 rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, port, 4369 &ext_stream_id_base); 4370 if (BCM_FAILURE(rv)) { 4371 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4372 (BSL_META_U(unit, 4373 "ERROR: Linkphy subport group external stream id " 4374 "base get failed for port %d.\n"), port)); 4375 return rv; 4376 } 4377 4378 rv = soc_linkphy_port_blk_idx_get(unit, port, &lp_block, &lp_index); 4379 if (SOC_FAILURE(rv)) { 4380 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4381 (BSL_META_U(unit, 4382 "ERROR: LinkPHY block, index get failed for port %d\n"), 4383 port)); 4384 return rv; 4385 } 4386 4387 dev_int_stream_id_base = (lp_block)? 128: 0; 4388 4389 for (i = 0; i < config->num_streams; i++) { 4390 port_e_stream_id_base_adj = 4391 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_EXT_STREAM_ID_GET( 4392 unit, pp_port, i) - ext_stream_id_base; 4393 4394 BCM_IF_ERROR_RETURN( 4395 _bcm_linkphy_port_rx_int_stream_map_port_get(unit, port, 4396 port_e_stream_id_base_adj, &(blk_int_stream_id))); 4397 4398 dev_int_stream_id = blk_int_stream_id + dev_int_stream_id_base; 4399 if (dev_int_stream_id > soc_mem_index_max(unit, 4400 DEVICE_STREAM_ID_TO_PP_PORT_MAPm)) { 4401 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4402 (BSL_META_U(unit, 4403 "ERROR: device internal stream_id %d is out of range \n" 4404 "port %d, internal stream id base %d\n"), 4405 dev_int_stream_id, port, dev_int_stream_id_base)); 4406 return BCM_E_PARAM; 4407 } 4408 4409 if (!_BCM_KT2_LINKPHY_DEV_INT_STREAM_ID_USED_GET(unit, 4410 dev_int_stream_id)) { 4411 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4412 (BSL_META_U(unit, 4413 "ERROR: LinkPHY subport port gport 0x%x is not found.\n" 4414 "Device internal stream_id = %d(%d) is not set " 4415 "for port %d\n"), 4416 subport_port_gport, dev_int_stream_id, 4417 blk_int_stream_id, port)); 4418 return BCM_E_NOT_FOUND; 4419 } 4420 4421 config->stream_id_array[i] = 4422 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_EXT_STREAM_ID_GET( 4423 unit, pp_port, i); 4424 } 4425 4426 mem = DEVICE_STREAM_ID_TO_PP_PORT_MAPm; 4427 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, dev_int_stream_id, 4428 &dev_sid_to_pp_entry); 4429 if (SOC_FAILURE(rv)) { 4430 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4431 (BSL_META_U(unit, 4432 "ERROR: DEVICE_STREAM_ID_TO_PP_PORT_MAPm read " 4433 "failed.for index %d\n"), dev_int_stream_id)); 4434 return rv; 4435 } 4436 4437 if (soc_mem_field32_get(unit, mem, 4438 (uint32 *)&dev_sid_to_pp_entry, PHB_VALIDf)) { 4439 config->prop_flags |= BCM_SUBPORT_PROPERTY_PHB; 4440 config->int_pri = soc_mem_field32_get(unit, mem, 4441 (uint32 *)&dev_sid_to_pp_entry, INT_PRIf); 4442 config->color = soc_mem_field32_get(unit, mem, 4443 (uint32 *)&dev_sid_to_pp_entry, CNGf); 4444 } else { 4445 config->prop_flags &= ~BCM_SUBPORT_PROPERTY_PHB; 4446 config->int_pri = 0; 4447 config->color = 0; 4448 } 4449 4450 return BCM_E_NONE; 4451 } 4452 4453 /* 4454 * Function: 4455 * _bcm_linkphy_subport_port_traverse 4456 * Purpose: 4457 * Add all valid LinkPHY subports under all valid LinkPHY subport groups 4458 * Parameters: 4459 * unit - Device Number 4460 * cb - User callback function, called once per subport. 4461 * user_data - cookie 4462 * Returns: 4463 * BCM_E_XXX 4464 */ 4465 STATIC int 4466 _bcm_linkphy_subport_port_traverse(int unit, 4467 bcm_subport_port_traverse_cb cb, 4468 void *user_data) 4469 { 4470 int rv = BCM_E_NONE; 4471 int pp_port_id = 0; 4472 bcm_subport_config_t config; 4473 bcm_gport_t linkphy_subport_port; 4474 4475 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 4476 4477 BCM_PBMP_ITER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port_id) { 4478 4479 if (!_BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port_id)) { 4480 continue; 4481 } 4482 4483 bcm_subport_config_t_init(&config); 4484 4485 _BCM_KT2_SUBPORT_PORT_ID_SET(linkphy_subport_port, pp_port_id); 4486 4487 _BCM_KT2_SUBPORT_PORT_TYPE_SET(linkphy_subport_port, 4488 _BCM_KT2_SUBPORT_TYPE_LINKPHY); 4489 4490 rv = _bcm_linkphy_subport_port_get(unit, linkphy_subport_port, &config); 4491 if (BCM_FAILURE(rv)) { 4492 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4493 (BSL_META_U(unit, 4494 "ERROR: subport port traverse failed \n" 4495 "to get LinkPHY subport id %d\n"), pp_port_id)); 4496 return rv; 4497 } 4498 4499 rv = cb(unit, linkphy_subport_port, &config, user_data); 4500 COMPILER_REFERENCE(rv); 4501 #ifdef BCM_CB_ABORT_ON_ERR 4502 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 4503 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4504 (BSL_META_U(unit, 4505 "ERROR: subport port traverse failed \n" 4506 "to callback for subport port (pp_port id %d)\n"), pp_port_id)); 4507 return rv; 4508 } 4509 #endif 4510 } 4511 4512 return BCM_E_NONE; 4513 } 4514 4515 /* 4516 * Function: 4517 * _bcm_linkphy_subport_cleanup 4518 * Purpose: 4519 * Delate all valid LinkPHY subport ports and 4520 * all valid LinkPHY subport groups. 4521 * Parameters: 4522 * unit - Device Number 4523 * Returns: 4524 * BCM_E_XXX 4525 */ 4526 STATIC int 4527 _bcm_linkphy_subport_cleanup(int unit) 4528 { 4529 int group_id = 0, rv = BCM_E_NONE, pp_port_id = 0; 4530 bcm_gport_t subport_group; 4531 bcm_gport_t subport_port; 4532 bcm_port_t port; 4533 soc_mem_t mem; 4534 int index; 4535 int block; 4536 4537 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 4538 4539 /* delete all LinkPHY subport ports */ 4540 BCM_PBMP_ITER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port_id) { 4541 4542 if (!_BCM_KT2_SUBPORT_PP_PORT_USED_GET(unit, pp_port_id)) { 4543 continue; 4544 } 4545 4546 _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port_id); 4547 4548 _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port, 4549 _BCM_KT2_SUBPORT_TYPE_LINKPHY); 4550 4551 subport_group = 4552 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port_id); 4553 4554 rv = _bcm_linkphy_subport_port_delete(unit, subport_port); 4555 if (SOC_FAILURE(rv)) { 4556 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4557 (BSL_META_U(unit, 4558 "ERROR: LinkPHY subport port delete " 4559 "failed (subport id %d)\n"), 4560 pp_port_id)); 4561 return rv; 4562 } 4563 4564 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(subport_group); 4565 4566 if (*(_bcm_subport_group_subport_port_count[unit] + group_id) == 0) { 4567 /* delete the subport group */ 4568 _bcm_subport_group_count[unit]--; 4569 _BCM_KT2_SUBPORT_GROUP_USED_CLR(unit, group_id); 4570 _bcm_linkphy_subport_group_count[unit]--; 4571 _BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_CLR(unit, group_id); 4572 } 4573 } 4574 4575 /* Cleanup SubTag VLAN id bit map */ 4576 BCM_PBMP_ITER(SOC_INFO(unit).linkphy_pbm, port) { 4577 mem = ING_PHYSICAL_PORT_TABLEm; 4578 if (SOC_MEM_FIELD_VALID(unit, mem, CASCADED_PORT_TYPEf)) { 4579 BCM_IF_ERROR_RETURN(soc_mem_field32_modify( 4580 unit, mem, port, CASCADED_PORT_TYPEf, 0)); 4581 } 4582 if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) { 4583 BCM_IF_ERROR_RETURN(soc_mem_field32_modify 4584 (unit, mem, port, PORT_TYPEf, _BCM_KT2_PORT_TYPE_ETHERNET)); 4585 } 4586 mem = EGR_PHYSICAL_PORTm; 4587 if (SOC_MEM_FIELD_VALID(unit, mem, CASCADED_PORT_TYPEf)) { 4588 BCM_IF_ERROR_RETURN(soc_mem_field32_modify( 4589 unit, mem, port, CASCADED_PORT_TYPEf, 0)); 4590 } 4591 if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) { 4592 BCM_IF_ERROR_RETURN(soc_mem_field32_modify( 4593 unit, mem, port, PORT_TYPEf, _BCM_KT2_PORT_TYPE_ETHERNET)); 4594 } 4595 } 4596 4597 BCM_PBMP_ITER(SOC_INFO(unit).linkphy_allowed_pbm, port) { 4598 /* check to fix coverity static overrun error */ 4599 if (port < SOC_MAX_NUM_PORTS) { 4600 sal_free(_bcm_subtag_vlan_id_bitmap[unit][port]); 4601 _bcm_subtag_vlan_id_bitmap[unit][port] = NULL; 4602 } 4603 } 4604 4605 #if defined(BCM_METROLITE_SUPPORT) 4606 if (SOC_IS_METROLITE(unit)) { 4607 for (index = 0; index < _BCM_ML_MAX_LINKPHY_PORTS; index++) { 4608 shr_idxres_list_destroy(_bcm_ml_int_stream_id_pool[unit][index]); 4609 } 4610 } else 4611 #endif 4612 #if defined(BCM_SABER2_SUPPORT) 4613 if (SOC_IS_SABER2(unit)) { 4614 for (index = 0; index < SOC_INFO(unit).lp_ports_max; index++) { 4615 shr_idxres_list_destroy(_bcm_sb2_int_stream_id_pool[unit][index]); 4616 } 4617 } else 4618 #endif 4619 { 4620 for (block = 0; block < SOC_INFO(unit).lp_block_max; block++) { 4621 for (index = 0; index < SOC_KT2_LINKPHY_BLOCK_PORT_IDX_MAX; 4622 index++) { 4623 shr_idxres_list_destroy( 4624 _bcm_kt2_blk_int_stream_id_pool[unit][block][index]); 4625 } 4626 } 4627 } 4628 4629 return BCM_E_NONE; 4630 } 4631 4632 4633 /********************************* 4634 * LinkPHY helper functions -end * 4635 */ 4636 4637 4638 /********************************** 4639 * SubTag helper functions -start * 4640 */ 4641 4642 /* 4643 * Function: 4644 * _bcm_subtag_subport_free_entry_find 4645 * Purpose: 4646 * Search for unused entry in the SUBPORT_TAG_TO_PP_PORT_MAP table 4647 * Parameters: 4648 * unit - Device unit number 4649 * index - (OUT) index where found 4650 * Returns: 4651 * BOC_E_NONE - free entry found 4652 * BOC_E_FULL - no free entries found 4653 */ 4654 STATIC int 4655 _bcm_subtag_subport_free_entry_find(int unit, int *free_index) 4656 { 4657 subport_tag_to_pp_port_map_entry_t entry; 4658 int index, rv, start, end; 4659 soc_mem_t mem = SUBPORT_TAG_TO_PP_PORT_MAPm; 4660 4661 start = soc_mem_index_min(unit, mem); 4662 end = soc_mem_index_max(unit, mem) + 1; 4663 4664 for (index = start; index != end; index++) { 4665 rv = READ_SUBPORT_TAG_TO_PP_PORT_MAPm(unit, 4666 MEM_BLOCK_ANY, index, &entry); 4667 if (SOC_SUCCESS(rv)) { 4668 if (!soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_get(unit, 4669 (uint32 *)&entry, VALIDf)) { 4670 *free_index = index; 4671 return BCM_E_NONE; 4672 } 4673 } 4674 } 4675 4676 return BCM_E_FULL; 4677 } 4678 4679 /* 4680 * Function: 4681 * _bcm_general_subport_init 4682 * Purpose: 4683 * Initialize general subport module. 4684 * Parameters: 4685 * unit - Device Number 4686 * Returns: 4687 * BCM_E_XXX 4688 */ 4689 STATIC int 4690 _bcm_general_subport_init(int unit) 4691 { 4692 int subport_group_max = SOC_INFO(unit).subport_group_max; 4693 int index = 0; 4694 4695 /* General subport group bitmap to keep track of used General groups */ 4696 if (_bcm_general_subport_group_bitmap[unit] == NULL) { 4697 4698 _bcm_general_subport_group_bitmap[unit] = 4699 sal_alloc(SHR_BITALLOCSIZE(subport_group_max), 4700 "general_subport_group_bitmap"); 4701 4702 if (_bcm_general_subport_group_bitmap[unit] == NULL) { 4703 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4704 (BSL_META_U(unit, 4705 "ERROR:general group bitmap alloc failed\n"))); 4706 4707 return BCM_E_MEMORY; 4708 } 4709 } 4710 4711 sal_memset(_bcm_general_subport_group_bitmap[unit], 0, 4712 SHR_BITALLOCSIZE(subport_group_max)); 4713 4714 _bcm_general_subport_group_count[unit] = 0; 4715 4716 /* general subport port info per subport group per subport port */ 4717 if (_bcm_general_subport_port_info[unit] == NULL) { 4718 _bcm_general_subport_port_info[unit] = 4719 sal_alloc((SOC_MAX_NUM_PP_PORTS * 4720 sizeof(_bcm_general_subport_port_info_t)), 4721 "general_subport_port_info"); 4722 if (_bcm_general_subport_port_info[unit] == NULL) { 4723 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4724 (BSL_META_U(unit, 4725 "ERROR: " 4726 " general_subport_port_info alloc failed\n"))); 4727 return BCM_E_MEMORY; 4728 } 4729 } 4730 4731 sal_memset(_bcm_general_subport_port_info[unit], 0, 4732 (SOC_MAX_NUM_PP_PORTS * sizeof(_bcm_general_subport_port_info_t))); 4733 4734 for (index = 0; index < SOC_MAX_NUM_PP_PORTS; index++) { 4735 _bcm_general_subport_port_info[unit][index].group = BCM_GPORT_INVALID; 4736 } 4737 4738 return BCM_E_NONE; 4739 } 4740 4741 /* 4742 * Function: 4743 * _bcm_subtag_subport_init 4744 * Purpose: 4745 * Initialize SubTag subport module. 4746 * Parameters: 4747 * unit - Device Number 4748 * Returns: 4749 * BCM_E_XXX 4750 */ 4751 STATIC int 4752 _bcm_subtag_subport_init(int unit) 4753 { 4754 bcm_port_t port; 4755 int num_vlan = 0, index = 0; 4756 soc_info_t *si = &SOC_INFO(unit); 4757 int subport_group_max = SOC_INFO(unit).subport_group_max; 4758 4759 /* Clear SUBPORT_TAG_TO_PP_PORT_MAP table */ 4760 BCM_IF_ERROR_RETURN 4761 (soc_mem_clear(unit, SUBPORT_TAG_TO_PP_PORT_MAPm, COPYNO_ALL, TRUE)); 4762 4763 num_vlan = soc_mem_index_count(unit, VLAN_TABm); 4764 4765 BCM_PBMP_ITER(si->subtag_allowed_pbm, port) { 4766 4767 /* check to fix coverity static overrun error */ 4768 if (port < SOC_MAX_NUM_PORTS) { 4769 4770 /* SubTag VLAN ID bitmap to keep track of the VLAN ID used per 4771 * SubTag enabled port. 4772 */ 4773 if (_bcm_subtag_vlan_id_bitmap[unit][port] == NULL) { 4774 4775 _bcm_subtag_vlan_id_bitmap[unit][port] = 4776 sal_alloc(SHR_BITALLOCSIZE(num_vlan), 4777 "_bcm_subtag_vlan_id_bitmap"); 4778 4779 if (_bcm_subtag_vlan_id_bitmap[unit][port] == NULL) { 4780 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4781 (BSL_META_U(unit, 4782 "ERROR:_bcm_subtag_vlan_id_bitmap " 4783 " alloc failed\n"))); 4784 4785 return BCM_E_MEMORY; 4786 } 4787 } 4788 sal_memset(_bcm_subtag_vlan_id_bitmap[unit][port], 0, 4789 SHR_BITALLOCSIZE(num_vlan)); 4790 } 4791 } 4792 4793 4794 /* SubTag subport group bitmap to keep track of used SubTag groups */ 4795 if (_bcm_subtag_group_bitmap[unit] == NULL) { 4796 4797 _bcm_subtag_group_bitmap[unit] = 4798 sal_alloc(SHR_BITALLOCSIZE(subport_group_max), 4799 "subtag_subport_group_bitmap"); 4800 4801 if (_bcm_subtag_group_bitmap[unit] == NULL) { 4802 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4803 (BSL_META_U(unit, 4804 "ERROR:subtag group bitmap alloc failed\n"))); 4805 4806 return BCM_E_MEMORY; 4807 } 4808 } 4809 4810 sal_memset(_bcm_subtag_group_bitmap[unit], 0, 4811 SHR_BITALLOCSIZE(subport_group_max)); 4812 4813 _bcm_subtag_subport_group_count[unit] = 0; 4814 4815 /* SubTag subport port info per subport group per subport port */ 4816 if (_bcm_subtag_subport_port_info[unit] == NULL) { 4817 _bcm_subtag_subport_port_info[unit] = 4818 sal_alloc((SOC_MAX_NUM_PP_PORTS * 4819 sizeof(_bcm_subtag_subport_port_info_t)), 4820 "subtag_subport_port_info"); 4821 if (_bcm_subtag_subport_port_info[unit] == NULL) { 4822 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4823 (BSL_META_U(unit, 4824 "ERROR: " 4825 " subtag_subport_port_info alloc failed\n"))); 4826 4827 return BCM_E_MEMORY; 4828 } 4829 } 4830 4831 sal_memset(_bcm_subtag_subport_port_info[unit], 0, 4832 (SOC_MAX_NUM_PP_PORTS * sizeof(_bcm_subtag_subport_port_info_t))); 4833 4834 for (index = 0; index < SOC_MAX_NUM_PP_PORTS; index++) { 4835 _bcm_subtag_subport_port_info[unit][index].group = BCM_GPORT_INVALID; 4836 _bcm_subtag_subport_port_info[unit][index].vlan = BCM_VLAN_INVALID; 4837 _bcm_subtag_subport_port_info[unit][index].subtag_tcam_hw_idx = -1; 4838 } 4839 4840 /* Set the STP state of subports */ 4841 BCM_PBMP_ITER(SOC_INFO(unit).subtag_pp_port_pbm, port) { 4842 bcm_esw_port_learn_set(unit, port, 4843 BCM_PORT_LEARN_ARL | BCM_PORT_LEARN_FWD); 4844 bcm_esw_port_stp_set(unit, port, BCM_STG_STP_FORWARD); 4845 } 4846 4847 return BCM_E_NONE; 4848 } 4849 4850 4851 /* 4852 * Function: 4853 * _bcm_subtag_subport_group_create 4854 * Purpose: 4855 * Create a SubTag subport group 4856 * Parameters: 4857 * unit - (IN) Device Number 4858 * config - (IN) Subport group config information 4859 * group - (OUT) GPORT (generic port) identifier 4860 * Returns: 4861 * BCM_E_XXX 4862 */ 4863 STATIC int 4864 _bcm_subtag_subport_group_create(int unit, 4865 int is_trunk, bcm_port_t port, 4866 int group_id, bcm_gport_t *group) 4867 { 4868 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 4869 4870 _BCM_KT2_SUBTAG_SUBPORT_GROUP_SET(*group, port, group_id); 4871 _BCM_KT2_SUBPORT_GROUP_TYPE_CASCADED_SET(*group); 4872 4873 _BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_SET(unit, group_id); 4874 _bcm_subtag_subport_group_count[unit]++; 4875 4876 return BCM_E_NONE; 4877 } 4878 4879 /* 4880 * Function: 4881 * _bcm_general_subport_group_create 4882 * Purpose: 4883 * Create a general subport group 4884 * Parameters: 4885 * unit - (IN) Device Number 4886 * is_trunk - (IN) Is a trunk port 4887 * port - (IN) Physical port identifier 4888 * group_id - (IN) Group id 4889 * group - (OUT) GPORT (generic port) identifier 4890 * Returns: 4891 * BCM_E_XXX 4892 */ 4893 STATIC int 4894 _bcm_general_subport_group_create(int unit, 4895 int is_trunk, bcm_port_t port, 4896 int group_id, bcm_gport_t *group) 4897 { 4898 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 4899 4900 /* Create general group based on subport property flags */ 4901 _BCM_KT2_GENERAL_SUBPORT_GROUP_SET(*group, port, group_id); 4902 _BCM_KT2_SUBPORT_GROUP_TYPE_CASCADED_SET(*group); 4903 4904 _BCM_KT2_GENERAL_SUBPORT_GROUP_USED_SET(unit, group_id); 4905 _bcm_general_subport_group_count[unit]++; 4906 4907 return BCM_E_NONE; 4908 } 4909 4910 4911 /* 4912 * Function: 4913 * _bcm_subtag_subport_group_destroy 4914 * Purpose: 4915 * Destroy the SubTag subport group and all subport ports attached to it. 4916 * Parameters: 4917 * unit - (IN) Device Number 4918 * group - (IN) GPORT (generic port) identifier for subport group 4919 * Returns: 4920 * BCM_E_XXX 4921 */ 4922 STATIC int 4923 _bcm_subtag_subport_group_destroy(int unit, 4924 bcm_gport_t group) 4925 { 4926 int group_id = -1; 4927 int pp_port = 0, rv = BCM_E_NONE; 4928 int subtag_subport_count = 0; 4929 bcm_gport_t subport_port_gport; 4930 4931 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 4932 4933 if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) { 4934 4935 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group); 4936 4937 if (!_BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_GET(unit, group_id)) { 4938 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4939 (BSL_META_U(unit, 4940 "ERROR: SubTag subport group 0x%x not found.\n"), 4941 group)); 4942 return BCM_E_NOT_FOUND; 4943 } 4944 4945 subtag_subport_count = 4946 *(_bcm_subport_group_subport_port_count[unit] + group_id); 4947 4948 /* delete all subport ports attached to the subport group */ 4949 BCM_PBMP_ITER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port) { 4950 if (subtag_subport_count == 0) { 4951 break; 4952 } 4953 4954 if (!_BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) { 4955 continue; 4956 } 4957 4958 if (group != 4959 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port)) { 4960 continue; 4961 } 4962 4963 _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port_gport, pp_port); 4964 4965 _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port_gport, 4966 _BCM_KT2_SUBPORT_TYPE_SUBTAG); 4967 4968 rv = _bcm_subtag_subport_port_delete(unit,subport_port_gport); 4969 if (SOC_FAILURE(rv)) { 4970 LOG_ERROR(BSL_LS_BCM_SUBPORT, 4971 (BSL_META_U(unit, 4972 "ERROR: SubTag subport group 0x%x destroy failed \n" 4973 " to delete subport port (subport group id %d, " 4974 " subport id %d)\n"), 4975 group, group_id, pp_port)); 4976 return rv; 4977 } 4978 subtag_subport_count--; 4979 } 4980 4981 *(_bcm_subport_group_subport_port_count[unit] + group_id) = 0; 4982 /* delete the subport group */ 4983 _bcm_subport_group_count[unit]--; 4984 _BCM_KT2_SUBPORT_GROUP_USED_CLR(unit, group_id); 4985 _bcm_subtag_subport_group_count[unit]--; 4986 _BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_CLR(unit, group_id); 4987 } 4988 4989 return BCM_E_NONE; 4990 } 4991 4992 /* 4993 * Function: 4994 * _bcm_general_subport_group_destroy 4995 * Purpose: 4996 * Destroy the general subport group and all subport ports attached to it. 4997 * Parameters: 4998 * unit - (IN) Device Number 4999 * group - (IN) GPORT (generic port) identifier for subport group 5000 * Returns: 5001 * BCM_E_XXX 5002 */ 5003 STATIC int 5004 _bcm_general_subport_group_destroy(int unit, 5005 bcm_gport_t group) 5006 { 5007 int group_id = -1; 5008 int pp_port = 0, rv = BCM_E_NONE; 5009 int general_subport_count = 0; 5010 bcm_gport_t subport_port_gport; 5011 5012 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 5013 5014 if (_BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(group)) { 5015 5016 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group); 5017 5018 if (!_BCM_KT2_GENERAL_SUBPORT_GROUP_USED_GET(unit, group_id)) { 5019 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5020 (BSL_META_U(unit, 5021 "ERROR: General subport group 0x%x not found.\n"), 5022 group)); 5023 return BCM_E_NOT_FOUND; 5024 } 5025 5026 general_subport_count = 5027 *(_bcm_subport_group_subport_port_count[unit] + group_id); 5028 5029 /* Delete all subport added in group */ 5030 BCM_PBMP_ITER(SOC_INFO(unit).general_pp_port_pbm, pp_port) { 5031 if (general_subport_count == 0) { 5032 break; 5033 } 5034 5035 if (!_BCM_KT2_GENERAL_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) { 5036 continue; 5037 } 5038 5039 if (group != 5040 _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port)) { 5041 continue; 5042 } 5043 5044 _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port_gport, pp_port); 5045 5046 _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port_gport, 5047 _BCM_KT2_SUBPORT_TYPE_GENERAL); 5048 5049 rv = _bcm_general_subport_port_delete(unit,subport_port_gport); 5050 if (SOC_FAILURE(rv)) { 5051 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5052 (BSL_META_U(unit, 5053 "ERROR: General subport group 0x%x destroy failed \n" 5054 " to delete subport port (subport group id %d, " 5055 " subport id %d)\n"), 5056 group, group_id, pp_port)); 5057 return rv; 5058 } 5059 general_subport_count--; 5060 } 5061 5062 *(_bcm_subport_group_subport_port_count[unit] + group_id) = 0; 5063 5064 /* Delete the subport group */ 5065 _bcm_subport_group_count[unit]--; 5066 _BCM_KT2_SUBPORT_GROUP_USED_CLR(unit, group_id); 5067 _bcm_general_subport_group_count[unit]--; 5068 _BCM_KT2_GENERAL_SUBPORT_GROUP_USED_CLR(unit, group_id); 5069 } 5070 5071 return BCM_E_NONE; 5072 } 5073 5074 /* 5075 * Function: 5076 * _bcm_subtag_subport_group_get 5077 * Purpose: 5078 * Get a subport group 5079 * Parameters: 5080 * unit - (IN) Device Number 5081 * group - (IN) GPORT (generic port) identifier 5082 * config - (OUT) Subport group config information 5083 * Returns: 5084 * BCM_E_XXX 5085 */ 5086 STATIC int 5087 _bcm_subtag_subport_group_get(int unit, 5088 bcm_gport_t group, 5089 bcm_subport_group_config_t *config) 5090 { 5091 int group_id = -1; 5092 5093 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 5094 5095 if (config == NULL) { 5096 return BCM_E_PARAM; 5097 } 5098 5099 if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) { 5100 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group); 5101 if (!_BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_GET(unit, group_id)) { 5102 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5103 (BSL_META_U(unit, 5104 "ERROR: SubTag subport group 0x%x not found.\n"), 5105 group)); 5106 return BCM_E_NOT_FOUND;; 5107 } 5108 config->flags |= BCM_SUBPORT_GROUP_TYPE_SUBPORT_TAG; 5109 config->port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(group); 5110 } else { 5111 return BCM_E_PARAM; 5112 } 5113 5114 return BCM_E_NONE; 5115 } 5116 5117 /* 5118 * Function: 5119 * _bcm_general_subport_group_get 5120 * Purpose: 5121 * Get a subport group 5122 * Parameters: 5123 * unit - (IN) Device Number 5124 * group - (IN) GPORT (generic port) identifier 5125 * config - (OUT) Subport group config information 5126 * Returns: 5127 * BCM_E_XXX 5128 */ 5129 STATIC int 5130 _bcm_general_subport_group_get(int unit, 5131 bcm_gport_t group, 5132 bcm_subport_group_config_t *config) 5133 { 5134 int group_id = -1; 5135 5136 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 5137 5138 if (config == NULL) { 5139 return BCM_E_PARAM; 5140 } 5141 5142 if (_BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(group)) { 5143 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group); 5144 if (!_BCM_KT2_GENERAL_SUBPORT_GROUP_USED_GET(unit, group_id)) { 5145 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5146 (BSL_META_U(unit, 5147 "ERROR: General subport group 0x%x not found.\n"), 5148 group)); 5149 return BCM_E_NOT_FOUND;; 5150 } 5151 config->flags |= BCM_SUBPORT_GROUP_TYPE_GENERAL; 5152 config->port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(group); 5153 } else { 5154 return BCM_E_PARAM; 5155 } 5156 5157 return BCM_E_NONE; 5158 } 5159 5160 /* 5161 * Function: 5162 * _bcm_subtag_subport_group_traverse 5163 * Purpose: 5164 * Traverse all valid subports for given SubTag subport group 5165 * and call the user supplied callback routine. 5166 * Parameters: 5167 * unit - Device Number 5168 * group - Subport group GPORT identifier 5169 * cb - User callback function, called once per subport. 5170 * user_data - cookie 5171 */ 5172 5173 STATIC int 5174 _bcm_subtag_subport_group_traverse(int unit, 5175 bcm_gport_t group, 5176 bcm_subport_port_traverse_cb cb, 5177 void *user_data) 5178 { 5179 int rv = BCM_E_NONE, group_id = 0; 5180 int pp_port = 0, subport_port; 5181 int subtag_subport_count = 0; 5182 bcm_subport_config_t config; 5183 5184 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 5185 5186 bcm_subport_config_t_init(&config); 5187 5188 if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) { 5189 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group); 5190 5191 if (!_BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_GET(unit, group_id)) { 5192 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5193 (BSL_META_U(unit, 5194 "ERROR: SubTag subport group 0x%x not found.\n"), 5195 group)); 5196 return BCM_E_NOT_FOUND; 5197 } 5198 5199 subtag_subport_count = 5200 *(_bcm_subport_group_subport_port_count[unit] + group_id); 5201 5202 5203 BCM_PBMP_ITER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port) { 5204 5205 if (subtag_subport_count == 0) { 5206 break; 5207 } 5208 5209 if (!_BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) { 5210 continue; 5211 } 5212 5213 if (group != 5214 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port)) { 5215 continue; 5216 } 5217 5218 _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port); 5219 5220 _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port, 5221 _BCM_KT2_SUBPORT_TYPE_SUBTAG); 5222 5223 rv = _bcm_subtag_subport_port_get(unit, subport_port, &config); 5224 if (SOC_FAILURE(rv)) { 5225 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5226 (BSL_META_U(unit, 5227 "ERROR: SubTag subport group 0x%x traverse failed \n" 5228 "to get subport port (group id %d, subport id %d)\n"), 5229 group, group_id, pp_port)); 5230 return rv; 5231 } 5232 5233 #ifdef BCM_CB_ABORT_ON_ERR 5234 rv = cb(unit, subport_port, &config, user_data); 5235 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 5236 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5237 (BSL_META_U(unit, 5238 "ERROR: subport group 0x%x traverse failed \n" 5239 "to callback for subport port (group id %d, " 5240 "subport id %d)\n"), group, group_id, pp_port)); 5241 return rv; 5242 } 5243 #else 5244 (void)cb(unit, subport_port, &config, user_data); 5245 #endif 5246 subtag_subport_count--; 5247 } 5248 } else { 5249 return BCM_E_PARAM; 5250 } 5251 return BCM_E_NONE; 5252 } 5253 5254 /* 5255 * Function: 5256 * _bcm_general_subport_group_traverse 5257 * Purpose: 5258 * Traverse all valid subports for given general subport group 5259 * and call the user supplied callback routine. 5260 * Parameters: 5261 * unit - Device Number 5262 * group - Subport group GPORT identifier 5263 * cb - User callback function, called once per subport. 5264 * user_data - cookie 5265 */ 5266 STATIC int 5267 _bcm_general_subport_group_traverse(int unit, 5268 bcm_gport_t group, 5269 bcm_subport_port_traverse_cb cb, 5270 void *user_data) 5271 { 5272 int rv = BCM_E_NONE, group_id = 0; 5273 int pp_port = 0, subport_port; 5274 int general_subport_count = 0; 5275 bcm_subport_config_t config; 5276 5277 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 5278 5279 bcm_subport_config_t_init(&config); 5280 5281 if (_BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(group)) { 5282 5283 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(group); 5284 5285 if (!_BCM_KT2_GENERAL_SUBPORT_GROUP_USED_GET(unit, group_id)) { 5286 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5287 (BSL_META_U(unit, 5288 "ERROR: General subport group 0x%x not found.\n"), 5289 group)); 5290 return BCM_E_NOT_FOUND; 5291 } 5292 5293 general_subport_count = 5294 *(_bcm_subport_group_subport_port_count[unit] + group_id); 5295 5296 5297 BCM_PBMP_ITER(SOC_INFO(unit).general_pp_port_pbm, pp_port) { 5298 5299 if (general_subport_count == 0) { 5300 break; 5301 } 5302 5303 if (!_BCM_KT2_GENERAL_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) { 5304 continue; 5305 } 5306 5307 if (group != 5308 _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port)) { 5309 continue; 5310 } 5311 _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port); 5312 5313 _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port, 5314 _BCM_KT2_SUBPORT_TYPE_GENERAL); 5315 5316 rv = _bcm_general_subport_port_get(unit, subport_port, &config); 5317 if (SOC_FAILURE(rv)) { 5318 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5319 (BSL_META_U(unit, 5320 "ERROR: general subport group 0x%x traverse failed \n" 5321 "to get subport port (group id %d, subport id %d)\n"), 5322 group, group_id, pp_port)); 5323 return rv; 5324 } 5325 5326 #ifdef BCM_CB_ABORT_ON_ERR 5327 rv = cb(unit, subport_port, &config, user_data); 5328 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 5329 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5330 (BSL_META_U(unit, 5331 "ERROR: subport group 0x%x traverse failed \n" 5332 "to callback for subport port (group id %d, " 5333 "subport id %d)\n"), group, group_id, pp_port)); 5334 return rv; 5335 } 5336 #else 5337 (void)cb(unit, subport_port, &config, user_data); 5338 #endif 5339 general_subport_count--; 5340 } 5341 } else { 5342 return BCM_E_PARAM; 5343 } 5344 5345 return BCM_E_NONE; 5346 } 5347 5348 /* 5349 * Function: 5350 * _bcm_subtag_subport_port_add 5351 * Purpose: 5352 * Add a SubTag subport to a subport group 5353 * Parameters: 5354 * unit - (IN) Device Number 5355 * config - (IN) Subport config information 5356 * port - (OUT) Subport_port GPORT (generic port) identifier 5357 * Returns: 5358 * BCM_E_XXX 5359 */ 5360 STATIC int 5361 _bcm_subtag_subport_port_add(int unit, 5362 bcm_subport_config_t *config, 5363 bcm_gport_t *gport) 5364 { 5365 int rv = BCM_E_NONE, port = -1; 5366 int subtag_index = -1; 5367 int sp_group_idx = -1; 5368 uint16 vlan_id = 0; 5369 int pp_port_index = 0; 5370 soc_mem_t mem; 5371 soc_info_t *si = &SOC_INFO(unit); 5372 subport_tag_to_pp_port_map_entry_t subtag_to_pp_entry; 5373 pp_port_to_physical_port_map_entry_t pp_to_port_entry; 5374 5375 /* A. PARAMETER VALIDATION 5376 */ 5377 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 5378 5379 if (!BCM_GPORT_IS_SUBPORT_GROUP(config->group)) { 5380 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5381 (BSL_META_U(unit, 5382 "ERROR: group 0x%x is not subport group gport\n"), 5383 config->group)); 5384 return BCM_E_PARAM; 5385 } 5386 5387 /* Make sure the group exists */ 5388 if (!_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(config->group)) { 5389 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5390 (BSL_META_U(unit, 5391 "ERROR: subport group 0x%x is not SubTag group\n"), 5392 config->group)); 5393 return BCM_E_PARAM; 5394 } 5395 5396 sp_group_idx = _BCM_KT2_SUBPORT_GROUP_ID_GET(config->group); 5397 5398 if (!_BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_GET(unit, sp_group_idx)) { 5399 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5400 (BSL_META_U(unit, 5401 "ERROR: group 0x%x does not exist. group id =%d\n"), 5402 config->group, sp_group_idx)); 5403 return BCM_E_NOT_FOUND; 5404 } 5405 5406 port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(config->group); 5407 5408 /* Check if port is member of pbmp_subtag */ 5409 if (!SOC_PBMP_MEMBER(si->subtag_pbm, port)) { 5410 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5411 (BSL_META_U(unit, 5412 "ERROR: Port %d is not member of pbmp_subport\n"), 5413 port)); 5414 return BCM_E_PORT; 5415 } 5416 5417 if (si->port_num_subport[port] <= 0) { 5418 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5419 (BSL_META_U(unit, 5420 "ERROR: %d number of subports available for port %d\n"), 5421 si->port_num_subport[port], port)); 5422 return BCM_E_CONFIG; 5423 } 5424 5425 if ((config->pkt_vlan & 0xFFF) <= BCM_VLAN_NONE) { 5426 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5427 (BSL_META_U(unit, 5428 "ERROR: (config->pkt_vlan & 0xFFF) %d is invalid\n"), 5429 (config->pkt_vlan & 0xFFF))); 5430 return BCM_E_PARAM; 5431 } 5432 5433 if (config->prop_flags & BCM_SUBPORT_PROPERTY_PHB) { 5434 if (config->int_pri < 0 || config->int_pri > 15) { 5435 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5436 (BSL_META_U(unit, 5437 "ERROR: int_pri %d is invalid\n"), 5438 config->int_pri)); 5439 return BCM_E_PARAM; 5440 } 5441 if ((config->color != bcmColorGreen) && 5442 (config->color != bcmColorYellow) && 5443 (config->color != bcmColorRed)) { 5444 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5445 (BSL_META_U(unit, 5446 "ERROR: color %d is invalid\n"), 5447 config->color)); 5448 return BCM_E_PARAM; 5449 } 5450 } 5451 5452 /* Check if VLAN id is alredy used for the port */ 5453 vlan_id = config->pkt_vlan & 0xFFF; 5454 5455 if (_BCM_KT2_SUBTAG_VLAN_ID_USED_GET(unit, port, vlan_id)) { 5456 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5457 (BSL_META_U(unit, 5458 "ERROR: VLAN id %d already used for port %d\n"), 5459 vlan_id, port)); 5460 return BCM_E_EXISTS; 5461 } 5462 5463 /* B. find free entry in subtag to pp_port Mapping table 5464 */ 5465 5466 mem = SUBPORT_TAG_TO_PP_PORT_MAPm; 5467 5468 rv = _bcm_subtag_subport_free_entry_find(unit, &subtag_index); 5469 if (SOC_FAILURE(rv)) { 5470 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5471 (BSL_META_U(unit, 5472 "ERROR: Free entry not found in " 5473 " subtag to pp_port map table\n"))); 5474 return rv; 5475 } 5476 5477 /* C. PP_PORT INDEX RESERVATION 5478 */ 5479 /* Reserve PP_PORT index */ 5480 BCM_IF_ERROR_RETURN(_bcm_kt2_allocate_pp_port(unit, config, &pp_port_index)); 5481 5482 /* D. Map VLAN ID, port to pp_port_index 5483 */ 5484 /* Use the SUBPORT_TAG_TO_PP_PORT_MAPm table */ 5485 5486 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, subtag_index, 5487 &subtag_to_pp_entry); 5488 if (BCM_FAILURE(rv)) { 5489 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5490 (BSL_META_U(unit, 5491 "SUBPORT_TAG_TO_PP_PORT_MAPm read failed at index %d\n"), 5492 subtag_index)); 5493 5494 return rv; 5495 } 5496 5497 /* Set the SUBPORT_TAG, PHYSICAL_PORT and VALID fields */ 5498 soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit, 5499 (uint32 *)&subtag_to_pp_entry, SUBPORT_TAGf, config->pkt_vlan); 5500 soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit, 5501 (uint32 *)&subtag_to_pp_entry, PHYSICAL_PORTf, port); 5502 5503 #if defined(BCM_METROLITE_SUPPORT) 5504 if (SOC_IS_METROLITE(unit)) { 5505 soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit, 5506 (uint32 *)&subtag_to_pp_entry, VALIDf, 0x1); 5507 } else 5508 #endif 5509 #if defined(BCM_SABER2_SUPPORT) 5510 if (SOC_IS_SABER2(unit)) { 5511 soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit, 5512 (uint32 *)&subtag_to_pp_entry, VALIDf, 0x3); 5513 } else 5514 #endif 5515 { 5516 soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit, 5517 (uint32 *)&subtag_to_pp_entry, VALIDf, 0x1); 5518 } 5519 5520 soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit, 5521 (uint32 *)&subtag_to_pp_entry, SUBPORT_TAG_MASKf, 0xFFF); 5522 soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit, 5523 (uint32 *)&subtag_to_pp_entry, PHYSICAL_PORT_MASKf, 5524 ((1 << soc_mem_field_length(unit, mem, PHYSICAL_PORT_MASKf)) - 1)); 5525 5526 /* Set the PP_PORT field */ 5527 soc_SUBPORT_TAG_TO_PP_PORT_MAPm_field32_set(unit, 5528 (uint32 *)&subtag_to_pp_entry, PP_PORTf, pp_port_index); 5529 5530 /* Set PHB for the subport */ 5531 if (config->prop_flags & BCM_SUBPORT_PROPERTY_PHB) { 5532 soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_pp_entry, 5533 PHB_VALIDf, 1); 5534 soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_pp_entry, 5535 INT_PRIf, config->int_pri); 5536 soc_mem_field32_set(unit, mem, (uint32 *)&subtag_to_pp_entry, 5537 CNGf, config->color); 5538 } 5539 5540 rv = WRITE_SUBPORT_TAG_TO_PP_PORT_MAPm(unit, MEM_BLOCK_ANY, subtag_index, 5541 &subtag_to_pp_entry); 5542 5543 if (SOC_FAILURE(rv)) { 5544 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5545 (BSL_META_U(unit, 5546 "ERROR: (VLAN id %d, port %d) to pp_port %d " 5547 "map failed.\n"), vlan_id, port, pp_port_index)); 5548 5549 return rv; 5550 } 5551 5552 /* E. Map PP_PORT to Physical port mapping (IP/ EP): 5553 */ 5554 /* Use the PP_PORT_TO_PHYSICAL_PORT_MAP */ 5555 mem = PP_PORT_TO_PHYSICAL_PORT_MAPm; 5556 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, pp_port_index, 5557 &pp_to_port_entry); 5558 5559 soc_mem_field32_set(unit, mem, (uint32 *)&pp_to_port_entry, 5560 DESTINATIONf, port); 5561 soc_mem_field32_set(unit, mem, (uint32 *)&pp_to_port_entry, 5562 ISTRUNKf, 0); 5563 5564 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, pp_port_index, 5565 &pp_to_port_entry); 5566 5567 if (SOC_FAILURE(rv)) { 5568 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5569 (BSL_META_U(unit, 5570 "ERROR: pp_port id %d to physical port %d " 5571 "map failed.\n"), pp_port_index, port)); 5572 5573 /* free/invalidate the SUBTAG_TO_PP_PORT_MAP table entry */ 5574 BCM_IF_ERROR_RETURN(soc_mem_field32_modify(unit, 5575 SUBPORT_TAG_TO_PP_PORT_MAPm, subtag_index, VALIDf, 0)); 5576 return rv; 5577 } 5578 5579 _BCM_KT2_SUBTAG_VLAN_ID_USED_SET(unit, port, vlan_id); 5580 5581 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_SET(unit, pp_port_index, 5582 config->group, config->pkt_vlan, subtag_index, TRUE); 5583 5584 _BCM_KT2_SUBPORT_PORT_ID_SET(*gport, pp_port_index); 5585 5586 /* Reset the subport_modport */ 5587 config->subport_modport = 0; 5588 5589 _BCM_KT2_SUBPORT_PORT_TYPE_SET(*gport, _BCM_KT2_SUBPORT_TYPE_SUBTAG); 5590 5591 *(_bcm_subport_group_subport_port_count[unit] + sp_group_idx) += 1; 5592 5593 _BCM_KT2_SUBPORT_PP_PORT_USED_SET(unit, pp_port_index); 5594 _bcm_subport_pp_port_count[unit]++; 5595 5596 /* Add to enabled_subtag_pbm */ 5597 BCM_PBMP_PORT_ADD(si->enabled_subtag_pp_port_pbm, pp_port_index); 5598 5599 /*LOG_FATAL(BSL_LS_BCM_SUBPORT, 5600 (BSL_META_U(unit, 5601 "Raghu: pp_port_id %d mod: %d port %d " 5602 "\n"), pp_port_index, mod_id, port_id)); 5603 */ 5604 #ifdef BCM_WARM_BOOT_SUPPORT 5605 SOC_CONTROL_LOCK(unit); 5606 SOC_CONTROL(unit)->scache_dirty = 1; 5607 SOC_CONTROL_UNLOCK(unit); 5608 #endif 5609 return rv; 5610 } 5611 5612 /* 5613 * Function: 5614 * _bcm_general_subport_port_add 5615 * Purpose: 5616 * Add a subport to a general subport group 5617 * Parameters: 5618 * unit - (IN) Device Number 5619 * config - (IN) Subport config information 5620 * gport - (OUT) Subport_port GPORT (generic port) identifier 5621 * Returns: 5622 * BCM_E_XXX 5623 */ 5624 STATIC int 5625 _bcm_general_subport_port_add(int unit, 5626 bcm_subport_config_t *config, 5627 bcm_gport_t *gport) 5628 { 5629 int sp_group_idx = -1; 5630 soc_port_t pp_port; 5631 soc_info_t *si = &SOC_INFO(unit); 5632 5633 /* A. PARAMETER VALIDATION 5634 */ 5635 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 5636 5637 if (!BCM_GPORT_IS_SUBPORT_GROUP(config->group)) { 5638 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5639 (BSL_META_U(unit, 5640 "ERROR: group 0x%x is not subport group gport\n"), 5641 config->group)); 5642 return BCM_E_PARAM; 5643 } 5644 5645 /* Make sure the group exists */ 5646 if (!_BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(config->group)) { 5647 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5648 (BSL_META_U(unit, 5649 "ERROR: subport group 0x%x is not general group\n"), 5650 config->group)); 5651 return BCM_E_PARAM; 5652 } 5653 5654 sp_group_idx = _BCM_KT2_SUBPORT_GROUP_ID_GET(config->group); 5655 5656 if (!_BCM_KT2_GENERAL_SUBPORT_GROUP_USED_GET(unit, sp_group_idx)) { 5657 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5658 (BSL_META_U(unit, 5659 "ERROR: group 0x%x does not exist. group id =%d\n"), 5660 config->group, sp_group_idx)); 5661 return BCM_E_NOT_FOUND; 5662 } 5663 5664 /* B. Allocate pp port */ 5665 SOC_PBMP_ITER(si->general_pp_port_pbm, pp_port) { 5666 if (SOC_PBMP_MEMBER(si->enabled_general_pp_port_pbm, pp_port)) { 5667 continue; 5668 } 5669 break; 5670 } 5671 5672 _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_SET(unit, pp_port, 5673 config->group, TRUE); 5674 5675 _BCM_KT2_SUBPORT_PORT_ID_SET(*gport, pp_port); 5676 5677 _BCM_KT2_SUBPORT_PORT_TYPE_SET(*gport, _BCM_KT2_SUBPORT_TYPE_GENERAL); 5678 5679 *(_bcm_subport_group_subport_port_count[unit] + sp_group_idx) += 1; 5680 5681 _BCM_KT2_SUBPORT_PP_PORT_USED_SET(unit, pp_port); 5682 5683 _bcm_subport_pp_port_count[unit]++; 5684 5685 SOC_PBMP_PORT_ADD(si->enabled_general_pp_port_pbm, pp_port); 5686 5687 #ifdef BCM_WARM_BOOT_SUPPORT 5688 SOC_CONTROL_LOCK(unit); 5689 SOC_CONTROL(unit)->scache_dirty = 1; 5690 SOC_CONTROL_UNLOCK(unit); 5691 #endif 5692 5693 return BCM_E_NONE; 5694 } 5695 5696 /* 5697 * Function: 5698 * _bcm_subtag_subport_port_delete 5699 * Purpose: 5700 * Delete a SubTag subport_port 5701 * Parameters: 5702 * unit - (IN) Device Number 5703 * port - (IN) Subport_port GPORT (generic port) identifier 5704 * Returns: 5705 * BCM_E_XXX 5706 */ 5707 STATIC int 5708 _bcm_subtag_subport_port_delete(int unit, 5709 bcm_gport_t subport_port_gport) 5710 { 5711 int rv = BCM_E_NONE, group_id = 0; 5712 int port = 0, subport_group = -1; 5713 int subtag_to_pp_port_tab_idx = -1; 5714 uint16 pp_port_index = 0; 5715 bcm_vlan_t vlan_id; 5716 soc_mem_t mem; 5717 soc_info_t *si = &SOC_INFO(unit); 5718 subport_tag_to_pp_port_map_entry_t subport_tag_to_pp_port_map_entry; 5719 5720 if (!_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_port_gport)) { 5721 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5722 (BSL_META_U(unit, 5723 "ERROR: gport 0x%x is not SubTag subport port type.\n"), 5724 subport_port_gport)); 5725 return BCM_E_PARAM; 5726 } 5727 5728 pp_port_index = 5729 _BCM_KT2_SUBPORT_PORT_ID_GET(subport_port_gport); 5730 5731 if (!_BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port_index)) { 5732 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5733 (BSL_META_U(unit, 5734 "ERROR: SubTag subport port gport 0x%x is invalid\n"), 5735 subport_port_gport)); 5736 return BCM_E_NOT_FOUND; 5737 } 5738 5739 subport_group = 5740 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port_index); 5741 5742 port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(subport_group); 5743 5744 subtag_to_pp_port_tab_idx = 5745 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_TCAM_HW_ID_GET(unit, pp_port_index); 5746 5747 mem = SUBPORT_TAG_TO_PP_PORT_MAPm; 5748 if (subtag_to_pp_port_tab_idx < 0 || 5749 subtag_to_pp_port_tab_idx > soc_mem_index_max(unit,mem)) { 5750 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5751 (BSL_META_U(unit, 5752 "ERROR: SubTag subport port gport 0x%x is not found.\n" 5753 "subtag_to_pp_port tcam idx = %d\n"), subport_port_gport, 5754 subtag_to_pp_port_tab_idx)); 5755 return BCM_E_NOT_FOUND; 5756 } 5757 5758 vlan_id = _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VLAN_GET(unit, pp_port_index) & 5759 0xFFF; 5760 5761 if (!_BCM_KT2_SUBTAG_VLAN_ID_USED_GET(unit, port, vlan_id)) { 5762 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5763 (BSL_META_U(unit, 5764 "ERROR: SubTag subport port gport 0x%x is not found.\n" 5765 "VLAN id = %d is not set for port %d\n"), 5766 subport_port_gport, vlan_id, port)); 5767 return BCM_E_NOT_FOUND; 5768 } 5769 5770 5771 5772 /* 5773 * Clean port, VLAN ID to pp_port mapping 5774 */ 5775 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, subtag_to_pp_port_tab_idx, 5776 &subport_tag_to_pp_port_map_entry); 5777 soc_mem_field32_set(unit, mem, (uint32 *)&subport_tag_to_pp_port_map_entry, 5778 SUBPORT_TAGf, 0); 5779 soc_mem_field32_set(unit, mem, (uint32 *)&subport_tag_to_pp_port_map_entry, 5780 PP_PORTf, 0); 5781 soc_mem_field32_set(unit, mem, (uint32 *)&subport_tag_to_pp_port_map_entry, 5782 VALIDf, 0); 5783 /* Clean PHB for the subport */ 5784 soc_mem_field32_set(unit, mem, (uint32 *)&subport_tag_to_pp_port_map_entry, 5785 PHB_VALIDf, 0); 5786 soc_mem_field32_set(unit, mem, (uint32 *)&subport_tag_to_pp_port_map_entry, 5787 INT_PRIf, 0); 5788 soc_mem_field32_set(unit, mem, (uint32 *)&subport_tag_to_pp_port_map_entry, 5789 CNGf, 0); 5790 rv = soc_mem_write(unit, mem, MEM_BLOCK_ANY, subtag_to_pp_port_tab_idx, 5791 &subport_tag_to_pp_port_map_entry); 5792 if (SOC_FAILURE(rv)) { 5793 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5794 (BSL_META_U(unit, 5795 "ERROR: subport_tag %d to pp_port %d " 5796 "map failed.\n"), vlan_id, pp_port_index)); 5797 return rv; 5798 } 5799 5800 /* 5801 * clean PP_PORT to Physical port mapping 5802 */ 5803 mem = PP_PORT_TO_PHYSICAL_PORT_MAPm; 5804 rv = soc_mem_field32_modify(unit,mem ,pp_port_index, DESTINATIONf, 0); 5805 if (SOC_FAILURE(rv)) { 5806 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5807 (BSL_META_U(unit, 5808 "ERROR: Cleaning pp_port id %d to physical port " 5809 "map failed.\n"), pp_port_index)); 5810 return rv; 5811 } 5812 5813 _BCM_KT2_SUBTAG_VLAN_ID_USED_CLR(unit, port, vlan_id); 5814 5815 _BCM_KT2_SUBPORT_PP_PORT_USED_CLR(unit, pp_port_index); 5816 _bcm_subport_pp_port_count[unit]--; 5817 5818 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(subport_group); 5819 *(_bcm_subport_group_subport_port_count[unit] + group_id) -= 1; 5820 5821 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_SET(unit, pp_port_index, 5822 BCM_GPORT_INVALID, BCM_VLAN_INVALID, -1, FALSE); 5823 5824 /* remove from enabled_subtag_pbm */ 5825 BCM_PBMP_PORT_REMOVE(si->enabled_subtag_pp_port_pbm, pp_port_index); 5826 5827 #ifdef BCM_WARM_BOOT_SUPPORT 5828 SOC_CONTROL_LOCK(unit); 5829 SOC_CONTROL(unit)->scache_dirty = 1; 5830 SOC_CONTROL_UNLOCK(unit); 5831 #endif 5832 5833 return rv; 5834 } 5835 5836 /* 5837 * Function: 5838 * _bcm_general_subport_port_delete 5839 * Purpose: 5840 * Delete a general subport_port 5841 * Parameters: 5842 * unit - (IN) Device Number 5843 * port - (IN) Subport_port GPORT (generic port) identifier 5844 * Returns: 5845 * BCM_E_XXX 5846 */ 5847 STATIC int 5848 _bcm_general_subport_port_delete(int unit, 5849 bcm_gport_t subport_port_gport) 5850 { 5851 int subport_group = -1; 5852 uint16 pp_port_index = 0; 5853 soc_info_t *si = &SOC_INFO(unit); 5854 int group_id = 0; 5855 5856 if (!_BCM_KT2_GPORT_IS_GENERAL_SUBPORT_PORT(unit, subport_port_gport)) { 5857 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5858 (BSL_META_U(unit, 5859 "ERROR: gport 0x%x is not general subport port type.\n"), 5860 subport_port_gport)); 5861 return BCM_E_PARAM; 5862 } 5863 5864 pp_port_index = 5865 _BCM_KT2_SUBPORT_PORT_ID_GET(subport_port_gport); 5866 5867 if (!_BCM_KT2_GENERAL_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port_index)) { 5868 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5869 (BSL_META_U(unit, 5870 "ERROR: general subport port gport 0x%x is invalid\n"), 5871 subport_port_gport)); 5872 return BCM_E_NOT_FOUND; 5873 } 5874 5875 subport_group = 5876 _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port_index); 5877 5878 _BCM_KT2_SUBPORT_PP_PORT_USED_CLR(unit, pp_port_index); 5879 5880 _bcm_subport_pp_port_count[unit]--; 5881 5882 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(subport_group); 5883 5884 *(_bcm_subport_group_subport_port_count[unit] + group_id) -= 1; 5885 5886 _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_SET(unit, pp_port_index, 5887 BCM_GPORT_INVALID, FALSE); 5888 5889 /* remove from enabled_general_pp_port_pbm */ 5890 BCM_PBMP_PORT_REMOVE(si->enabled_general_pp_port_pbm, pp_port_index); 5891 5892 #ifdef BCM_WARM_BOOT_SUPPORT 5893 SOC_CONTROL_LOCK(unit); 5894 SOC_CONTROL(unit)->scache_dirty = 1; 5895 SOC_CONTROL_UNLOCK(unit); 5896 #endif 5897 5898 return BCM_E_NONE; 5899 } 5900 5901 /* 5902 * Function: 5903 * _bcm_subtag_subport_port_get 5904 * Purpose: 5905 * Get the SubTag subport_port config (subport group gport and stream_id) 5906 * Parameters: 5907 * unit - (IN) Device Number 5908 * port - (IN) Subport_port GPORT (generic port) identifier 5909 * config - (OUT) Subport port config 5910 * Returns: 5911 * BCM_E_XXX 5912 */ 5913 STATIC int 5914 _bcm_subtag_subport_port_get(int unit, 5915 bcm_gport_t subport_port_gport, 5916 bcm_subport_config_t *config) 5917 { 5918 int pp_port = 0; 5919 int rv = BCM_E_NONE; 5920 bcm_gport_t subport_group; 5921 int subtag_to_pp_hw_id = -1; 5922 subport_tag_to_pp_port_map_entry_t subtag_pp_entry; 5923 soc_mem_t mem; 5924 5925 if (config == NULL) { 5926 return BCM_E_PARAM; 5927 } 5928 5929 if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_port_gport)) { 5930 5931 pp_port = _BCM_KT2_SUBPORT_PORT_ID_GET(subport_port_gport); 5932 5933 subport_group = 5934 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port); 5935 5936 if (!BCM_GPORT_IS_SUBPORT_GROUP(subport_group)) { 5937 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 5938 (BSL_META_U(unit, 5939 "ERROR:Invalid SubTag subport port gport 0x%x\n"), 5940 subport_port_gport)); 5941 return BCM_E_PARAM; 5942 } 5943 5944 if (!_BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) { 5945 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 5946 (BSL_META_U(unit, 5947 "ERROR: SubTag subport port gport 0x%x not found\n"), 5948 subport_port_gport)); 5949 return BCM_E_NOT_FOUND; 5950 } 5951 5952 config->group = subport_group; 5953 5954 config->pkt_vlan = 5955 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VLAN_GET(unit, pp_port); 5956 5957 subtag_to_pp_hw_id = 5958 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_TCAM_HW_ID_GET(unit, pp_port); 5959 5960 mem = SUBPORT_TAG_TO_PP_PORT_MAPm; 5961 if ((subtag_to_pp_hw_id < 0) || 5962 (subtag_to_pp_hw_id > soc_mem_index_max(unit, mem))) { 5963 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5964 (BSL_META_U(unit, 5965 "ERROR: SubTag subport port gport 0x%x is not found.\n" 5966 "subtag_to_pp_port_tab idx = %d\n"), subport_port_gport, 5967 subtag_to_pp_hw_id)); 5968 return BCM_E_NOT_FOUND; 5969 } 5970 5971 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, subtag_to_pp_hw_id, 5972 &subtag_pp_entry); 5973 if (SOC_FAILURE(rv)) { 5974 LOG_ERROR(BSL_LS_BCM_SUBPORT, 5975 (BSL_META_U(unit, 5976 "ERROR: DEVICE_STREAM_ID_TO_PP_PORT_MAPm read " 5977 "failed.for index %d\n"), subtag_to_pp_hw_id)); 5978 return rv; 5979 } 5980 5981 if (soc_mem_field32_get(unit, mem, 5982 (uint32 *)&subtag_pp_entry, PHB_VALIDf)) { 5983 config->prop_flags |= BCM_SUBPORT_PROPERTY_PHB; 5984 config->int_pri = soc_mem_field32_get(unit, mem, 5985 (uint32 *)&subtag_pp_entry, INT_PRIf); 5986 config->color = soc_mem_field32_get(unit, mem, 5987 (uint32 *)&subtag_pp_entry, CNGf); 5988 } else { 5989 config->prop_flags &= ~BCM_SUBPORT_PROPERTY_PHB; 5990 config->int_pri = 0; 5991 config->color = 0; 5992 } 5993 } else { 5994 return BCM_E_PARAM; 5995 } 5996 5997 return BCM_E_NONE; 5998 } 5999 6000 /* 6001 * Function: 6002 * _bcm_general_subport_port_get 6003 * Purpose: 6004 * Get the General subport_port config 6005 * Parameters: 6006 * unit - (IN) Device Number 6007 * port - (IN) Subport_port GPORT (generic port) identifier 6008 * config - (OUT) Subport port config 6009 * Returns: 6010 * BCM_E_XXX 6011 */ 6012 STATIC int 6013 _bcm_general_subport_port_get(int unit, 6014 bcm_gport_t subport_port_gport, 6015 bcm_subport_config_t *config) 6016 { 6017 int pp_port = 0; 6018 bcm_gport_t subport_group; 6019 6020 if (config == NULL) { 6021 return BCM_E_PARAM; 6022 } 6023 6024 if (_BCM_KT2_GPORT_IS_GENERAL_SUBPORT_PORT(unit, subport_port_gport)) { 6025 6026 pp_port = _BCM_KT2_SUBPORT_PORT_ID_GET(subport_port_gport); 6027 6028 subport_group = 6029 _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port); 6030 6031 if (!BCM_GPORT_IS_SUBPORT_GROUP(subport_group)) { 6032 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 6033 (BSL_META_U(unit, 6034 "ERROR:Invalid General subport port gport 0x%x\n"), 6035 subport_port_gport)); 6036 return BCM_E_PARAM; 6037 } 6038 6039 if (!_BCM_KT2_GENERAL_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) { 6040 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 6041 (BSL_META_U(unit, 6042 "ERROR: General subport port gport 0x%x not found\n"), 6043 subport_port_gport)); 6044 return BCM_E_NOT_FOUND; 6045 } 6046 6047 config->group = subport_group; 6048 6049 } else { 6050 return BCM_E_PARAM; 6051 } 6052 6053 return BCM_E_NONE; 6054 } 6055 6056 /* 6057 * Function: 6058 * _bcm_subtag_subport_port_traverse 6059 * Purpose: 6060 * Add all valid SubTag subports under all valid SubTag subport groups 6061 * Parameters: 6062 * unit - Device Number 6063 * cb - User callback function, called once per subport. 6064 * user_data - cookie 6065 * Returns: 6066 * BCM_E_XXX 6067 */ 6068 STATIC int 6069 _bcm_subtag_subport_port_traverse(int unit, 6070 bcm_subport_port_traverse_cb cb, 6071 void *user_data) 6072 { 6073 int rv = BCM_E_NONE; 6074 int pp_port_id = 0; 6075 bcm_subport_config_t config; 6076 bcm_gport_t subtag_subport_port; 6077 6078 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 6079 6080 BCM_PBMP_ITER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port_id) { 6081 6082 if (!_BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port_id)) { 6083 continue; 6084 } 6085 6086 bcm_subport_config_t_init(&config); 6087 6088 _BCM_KT2_SUBPORT_PORT_ID_SET(subtag_subport_port, pp_port_id); 6089 6090 _BCM_KT2_SUBPORT_PORT_TYPE_SET(subtag_subport_port, 6091 _BCM_KT2_SUBPORT_TYPE_SUBTAG); 6092 6093 rv = _bcm_subtag_subport_port_get(unit, subtag_subport_port, &config); 6094 if (BCM_FAILURE(rv)) { 6095 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6096 (BSL_META_U(unit, 6097 "ERROR: subport port traverse failed \n" 6098 "to get SubTag subport id %d\n"), pp_port_id)); 6099 return rv; 6100 } 6101 6102 rv = cb(unit, subtag_subport_port, &config, user_data); 6103 COMPILER_REFERENCE(rv); 6104 #ifdef BCM_CB_ABORT_ON_ERR 6105 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 6106 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6107 (BSL_META_U(unit, 6108 "ERROR: subport port traverse failed \n" 6109 "to callback for subport port (subport_port id %d)\n"), 6110 pp_port_id)); 6111 return rv; 6112 } 6113 #endif 6114 } 6115 return BCM_E_NONE; 6116 } 6117 6118 /* 6119 * Function: 6120 * _bcm_general_subport_port_traverse 6121 * Purpose: 6122 * Traverse all valid general subports under all valid general subport groups 6123 * Parameters: 6124 * unit - Device Number 6125 * cb - User callback function, called once per subport. 6126 * user_data - cookie 6127 * Returns: 6128 * BCM_E_XXX 6129 */ 6130 STATIC int 6131 _bcm_general_subport_port_traverse(int unit, 6132 bcm_subport_port_traverse_cb cb, 6133 void *user_data) 6134 { 6135 int rv = BCM_E_NONE; 6136 int pp_port_id = 0; 6137 bcm_subport_config_t config; 6138 bcm_gport_t general_subport_port; 6139 6140 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 6141 6142 BCM_PBMP_ITER(SOC_INFO(unit).general_pp_port_pbm, pp_port_id) { 6143 6144 if (!_BCM_KT2_GENERAL_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port_id)) { 6145 continue; 6146 } 6147 6148 bcm_subport_config_t_init(&config); 6149 6150 _BCM_KT2_SUBPORT_PORT_ID_SET(general_subport_port, pp_port_id); 6151 6152 _BCM_KT2_SUBPORT_PORT_TYPE_SET(general_subport_port, 6153 _BCM_KT2_SUBPORT_TYPE_GENERAL); 6154 6155 rv = _bcm_general_subport_port_get(unit, general_subport_port, &config); 6156 if (BCM_FAILURE(rv)) { 6157 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6158 (BSL_META_U(unit, 6159 "ERROR: subport port traverse failed \n" 6160 "to get general subport id %d\n"), pp_port_id)); 6161 return rv; 6162 } 6163 6164 rv = cb(unit, general_subport_port, &config, user_data); 6165 COMPILER_REFERENCE(rv); 6166 6167 #ifdef BCM_CB_ABORT_ON_ERR 6168 if (BCM_FAILURE(rv) && SOC_CB_ABORT_ON_ERR(unit)) { 6169 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6170 (BSL_META_U(unit, 6171 "ERROR: subport port traverse failed \n" 6172 "to callback for subport port (subport_port id %d)\n"), 6173 pp_port_id)); 6174 return rv; 6175 } 6176 #endif 6177 } 6178 6179 return BCM_E_NONE; 6180 } 6181 6182 /* 6183 * Function: 6184 * _bcm_subtag_subport_cleanup 6185 * Purpose: 6186 * Delate all valid SubTag subport ports and 6187 * all valid SubTag subport groups. 6188 * Parameters: 6189 * unit - Device Number 6190 * Returns: 6191 * BCM_E_XXX 6192 */ 6193 STATIC int 6194 _bcm_subtag_subport_cleanup(int unit) 6195 { 6196 int group_id = 0, rv = BCM_E_NONE, pp_port_id = 0; 6197 bcm_port_t port; 6198 bcm_gport_t subport_group; 6199 bcm_gport_t subport_port; 6200 soc_mem_t mem; 6201 6202 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 6203 6204 /* delete all SubTag subport ports */ 6205 BCM_PBMP_ITER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port_id) { 6206 6207 if (!_BCM_KT2_SUBPORT_PP_PORT_USED_GET(unit, pp_port_id)) { 6208 continue; 6209 } 6210 6211 _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port_id); 6212 6213 _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port, 6214 _BCM_KT2_SUBPORT_TYPE_SUBTAG); 6215 6216 subport_group = 6217 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port_id); 6218 6219 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(subport_group); 6220 6221 rv = _bcm_subtag_subport_port_delete(unit, subport_port); 6222 if (SOC_FAILURE(rv)) { 6223 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6224 (BSL_META_U(unit, 6225 "ERROR: SubTag subport port delete failed (subport id %d)\n"), 6226 pp_port_id)); 6227 return rv; 6228 } 6229 6230 if (*(_bcm_subport_group_subport_port_count[unit] + group_id) == 0) { 6231 /* delete the subport group */ 6232 _bcm_subport_group_count[unit]--; 6233 _BCM_KT2_SUBPORT_GROUP_USED_CLR(unit, group_id); 6234 _bcm_linkphy_subport_group_count[unit]--; 6235 _BCM_KT2_SUBTAG_SUBPORT_GROUP_USED_CLR(unit, group_id); 6236 } 6237 } 6238 6239 /* Cleanup SubTag VLAN id bit map */ 6240 BCM_PBMP_ITER(SOC_INFO(unit).subtag_pbm, port) { 6241 mem = ING_PHYSICAL_PORT_TABLEm; 6242 if (SOC_MEM_FIELD_VALID(unit, mem, CASCADED_PORT_TYPEf)) { 6243 BCM_IF_ERROR_RETURN(soc_mem_field32_modify( 6244 unit, mem, port, CASCADED_PORT_TYPEf, 0)); 6245 } 6246 if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) { 6247 BCM_IF_ERROR_RETURN(soc_mem_field32_modify 6248 (unit, mem, port, PORT_TYPEf, _BCM_KT2_PORT_TYPE_ETHERNET)); 6249 } 6250 mem = EGR_PHYSICAL_PORTm; 6251 if (SOC_MEM_FIELD_VALID(unit, mem, CASCADED_PORT_TYPEf)) { 6252 BCM_IF_ERROR_RETURN(soc_mem_field32_modify( 6253 unit, mem, port, CASCADED_PORT_TYPEf, 0)); 6254 } 6255 if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) { 6256 BCM_IF_ERROR_RETURN(soc_mem_field32_modify( 6257 unit, mem, port, PORT_TYPEf, _BCM_KT2_PORT_TYPE_ETHERNET)); 6258 } 6259 } 6260 6261 return BCM_E_NONE; 6262 6263 } 6264 6265 /* 6266 * Function: 6267 * _bcm_general_subport_cleanup 6268 * Purpose: 6269 * Delete all valid general purpose subport ports and 6270 * all valid general subport groups. 6271 * Parameters: 6272 * unit - Device Number 6273 * Returns: 6274 * BCM_E_XXX 6275 */ 6276 STATIC int 6277 _bcm_general_subport_cleanup(int unit) 6278 { 6279 6280 int group_id = 0, rv = BCM_E_NONE, pp_port_id = 0; 6281 bcm_gport_t subport_group; 6282 bcm_gport_t subport_port; 6283 6284 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 6285 6286 /* delete all general subport ports */ 6287 BCM_PBMP_ITER(SOC_INFO(unit).general_pp_port_pbm, pp_port_id) { 6288 6289 if (!_BCM_KT2_SUBPORT_PP_PORT_USED_GET(unit, pp_port_id)) { 6290 continue; 6291 } 6292 6293 _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port_id); 6294 6295 _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port, 6296 _BCM_KT2_SUBPORT_TYPE_GENERAL); 6297 6298 subport_group = 6299 _BCM_KT2_GENERAL_SUBPORT_PORT_INFO_GROUP_GET(unit, pp_port_id); 6300 6301 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(subport_group); 6302 6303 rv = _bcm_general_subport_port_delete(unit, subport_port); 6304 if (SOC_FAILURE(rv)) { 6305 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6306 (BSL_META_U(unit, 6307 "ERROR: General subport port delete failed (subport id %d)\n"), 6308 pp_port_id)); 6309 return rv; 6310 } 6311 6312 /* delete the subport group */ 6313 if (*(_bcm_subport_group_subport_port_count[unit] + group_id) == 0) { 6314 _bcm_subport_group_count[unit]--; 6315 _BCM_KT2_SUBPORT_GROUP_USED_CLR(unit, group_id); 6316 _bcm_general_subport_group_count[unit]--; 6317 _BCM_KT2_GENERAL_SUBPORT_GROUP_USED_CLR(unit, group_id); 6318 } 6319 } 6320 6321 return BCM_E_NONE; 6322 } 6323 6324 /********************************* 6325 * SubTag helper functions -end * 6326 */ 6327 6328 6329 STATIC void 6330 bcm_kt2_subport_free_resource(int unit) 6331 { 6332 if(_bcm_subport_group_bitmap[unit] != NULL) { 6333 sal_free(_bcm_subport_group_bitmap[unit]); 6334 _bcm_subport_group_bitmap[unit] = NULL; 6335 } 6336 6337 if(_bcm_subport_pp_port_bitmap[unit] != NULL) { 6338 sal_free(_bcm_subport_pp_port_bitmap[unit]); 6339 _bcm_subport_pp_port_bitmap[unit] = NULL; 6340 } 6341 6342 if (soc_feature(unit, soc_feature_linkphy_coe)) { 6343 6344 if(_bcm_linkphy_group_bitmap[unit] != NULL) { 6345 sal_free(_bcm_linkphy_group_bitmap[unit]); 6346 _bcm_linkphy_group_bitmap[unit] = NULL; 6347 } 6348 6349 if (_bcm_linkphy_subport_port_info[unit] != NULL) { 6350 sal_free(_bcm_linkphy_subport_port_info[unit]); 6351 _bcm_linkphy_subport_port_info[unit] = NULL; 6352 } 6353 6354 } /* end of soc_feature_linkphy_coe */ 6355 6356 if (soc_feature(unit, soc_feature_subtag_coe)) { 6357 6358 if(_bcm_subtag_group_bitmap[unit] != NULL) { 6359 sal_free(_bcm_subtag_group_bitmap[unit]); 6360 _bcm_subtag_group_bitmap[unit] = NULL; 6361 } 6362 6363 if (_bcm_subtag_subport_port_info[unit] != NULL) { 6364 sal_free(_bcm_subtag_subport_port_info[unit]); 6365 _bcm_subtag_subport_port_info[unit] = NULL; 6366 } 6367 6368 } /* end of soc_feature_subtag_coe */ 6369 6370 if (soc_feature(unit, soc_feature_general_cascade)) { 6371 6372 if(_bcm_general_subport_group_bitmap[unit] != NULL) { 6373 sal_free(_bcm_general_subport_group_bitmap[unit]); 6374 _bcm_general_subport_group_bitmap[unit] = NULL; 6375 } 6376 6377 if (_bcm_general_subport_port_info[unit] != NULL) { 6378 sal_free(_bcm_general_subport_port_info[unit]); 6379 _bcm_general_subport_port_info[unit] = NULL; 6380 } 6381 6382 } /* end of soc_feature_general_cascade */ 6383 6384 if (_bcm_subport_group_subport_port_count[unit] != NULL) { 6385 sal_free(_bcm_subport_group_subport_port_count[unit]); 6386 _bcm_subport_group_subport_port_count[unit] = NULL; 6387 } 6388 6389 if (_bcm_subport_mutex[unit] != NULL) { 6390 sal_mutex_destroy(_bcm_subport_mutex[unit]); 6391 _bcm_subport_mutex[unit] = NULL; 6392 } 6393 6394 } 6395 6396 /* 6397 * Function: 6398 * bcm_kt2_nhi_group_tc_profile_init 6399 * Purpose: 6400 * Initialize kt2 NHI_GROUP_TC_PROFILE table. KT2 provides a TC PROFILE table with 256 6401 * items which are used to store the NHI_OFFSET. The index of TC PROFILE derives from 6402 * concatenating the TC PROFILE INDEX and internal priority of the packet. 6403 * Parameters: 6404 * unit - Device Number 6405 * Returns: 6406 * BCM_E_XXX 6407 */ 6408 STATIC int 6409 bcm_kt2_nhi_group_tc_profile_init(int unit) 6410 { 6411 int rv = BCM_E_NONE; 6412 int nhi_group, int_pri; 6413 nhi_group_tc_profile_entry_t nhi_entry; 6414 6415 if (SOC_MEM_IS_VALID(unit, NHI_GROUP_TC_PROFILEm)) { 6416 for (nhi_group = 0; nhi_group <= 0xf; nhi_group++) { 6417 for (int_pri = 0; int_pri <= 0xf; int_pri++) { 6418 sal_memset(&nhi_entry, 0, sizeof(nhi_group_tc_profile_entry_t)); 6419 soc_mem_field32_set(unit, NHI_GROUP_TC_PROFILEm, &nhi_entry, 6420 NHI_OFFSETf, int_pri); 6421 rv = soc_mem_write(unit, NHI_GROUP_TC_PROFILEm, 6422 MEM_BLOCK_ALL, (nhi_group<<4)|int_pri, &nhi_entry); 6423 if (SOC_FAILURE(rv)) { 6424 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6425 (BSL_META_U(unit, 6426 "ERROR: NHI_GROUP_TC_PROFIE init failed\n"))); 6427 return rv; 6428 } 6429 } 6430 } 6431 } 6432 6433 return rv; 6434 } 6435 6436 6437 /* 6438 * Function: 6439 * bcm_kt2_subport_init 6440 * Purpose: 6441 * Initialize the SUBPORT software module 6442 * Parameters: 6443 * unit - Device Number 6444 * Returns: 6445 * BCM_E_XXX 6446 */ 6447 int 6448 bcm_kt2_subport_init(int unit) 6449 { 6450 int rv = BCM_E_NONE; 6451 soc_info_t *si = &SOC_INFO(unit); 6452 int pp_port_index_max = si->pp_port_index_max; 6453 int subport_group_max = si->subport_group_max; 6454 6455 /* Subport group bitmap to keep track of used subport groups */ 6456 if (_bcm_subport_group_bitmap[unit] == NULL) { 6457 6458 _bcm_subport_group_bitmap[unit] = 6459 sal_alloc(SHR_BITALLOCSIZE(subport_group_max), 6460 "subport_group_bitmap"); 6461 6462 if (_bcm_subport_group_bitmap[unit] == NULL) { 6463 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6464 (BSL_META_U(unit, 6465 "ERROR:subport_init: group bitmap alloc failed\n"))); 6466 6467 bcm_kt2_subport_free_resource(unit); 6468 6469 return BCM_E_MEMORY; 6470 } 6471 } 6472 6473 sal_memset(_bcm_subport_group_bitmap[unit], 0, 6474 SHR_BITALLOCSIZE(subport_group_max)); 6475 6476 _bcm_subport_group_count[unit] = 0; 6477 6478 /* Keep Count of subport port created per subport group */ 6479 if (_bcm_subport_group_subport_port_count[unit] == NULL) { 6480 _bcm_subport_group_subport_port_count[unit] = 6481 sal_alloc((subport_group_max * sizeof(int)), 6482 "subport_group_subport_port_count"); 6483 if (_bcm_subport_group_subport_port_count[unit] == NULL) { 6484 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6485 (BSL_META_U(unit, 6486 "ERROR: " 6487 "subport_group_subport_port_count alloc failed\n"))); 6488 6489 return BCM_E_MEMORY; 6490 } 6491 } 6492 6493 sal_memset(_bcm_subport_group_subport_port_count[unit], 0, 6494 (subport_group_max * sizeof(int))); 6495 6496 /* Create subport mutex */ 6497 if (NULL == _bcm_subport_mutex[unit]) { 6498 _bcm_subport_mutex[unit] = 6499 sal_mutex_create("linkphy_subtag subport mutex"); 6500 6501 if (_bcm_subport_mutex[unit] == NULL) { 6502 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6503 (BSL_META_U(unit, 6504 "ERROR:linkphy_subtag subport mutex create failed\n"))); 6505 6506 return BCM_E_MEMORY; 6507 } 6508 } 6509 6510 /* LinkPHY subport initialization */ 6511 if (soc_feature(unit, soc_feature_linkphy_coe) && 6512 BCM_PBMP_NOT_NULL(si->linkphy_allowed_pbm)) { 6513 rv = _bcm_linkphy_subport_init(unit); 6514 if (SOC_FAILURE(rv)) { 6515 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6516 (BSL_META_U(unit, 6517 "ERROR: LinkPHY init failed.\n"))); 6518 6519 bcm_kt2_subport_free_resource(unit); 6520 return rv; 6521 } 6522 } 6523 6524 /* Subtag CoE subport initialization */ 6525 if (soc_feature(unit, soc_feature_subtag_coe) && 6526 BCM_PBMP_NOT_NULL(si->subtag_allowed_pbm)) { 6527 rv = _bcm_subtag_subport_init(unit); 6528 if (SOC_FAILURE(rv)) { 6529 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6530 (BSL_META_U(unit, 6531 "ERROR: SubTag init failed.\n"))); 6532 6533 bcm_kt2_subport_free_resource(unit); 6534 return rv; 6535 } 6536 } 6537 6538 /* General subport initialization */ 6539 if (soc_feature(unit, soc_feature_general_cascade)) { 6540 rv = _bcm_general_subport_init(unit); 6541 if (SOC_FAILURE(rv)) { 6542 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6543 (BSL_META_U(unit, 6544 "ERROR: General subport init failed.\n"))); 6545 bcm_kt2_subport_free_resource(unit); 6546 return rv; 6547 } 6548 } 6549 6550 if (soc_feature(unit, soc_feature_lltag)) { 6551 rv = bcm_kt2_nhi_group_tc_profile_init(unit); 6552 if (SOC_FAILURE(rv)) { 6553 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6554 (BSL_META_U(unit, 6555 "ERROR: tc profile init failed.\n"))); 6556 6557 bcm_kt2_subport_free_resource(unit); 6558 return rv; 6559 } 6560 } 6561 6562 if (_bcm_subport_pp_port_bitmap[unit] == NULL) { 6563 6564 _bcm_subport_pp_port_bitmap[unit] = 6565 sal_alloc(SHR_BITALLOCSIZE(pp_port_index_max + 1), 6566 "subport_group_bitmap"); 6567 6568 if (_bcm_subport_pp_port_bitmap[unit] == NULL) { 6569 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6570 (BSL_META_U(unit, 6571 "ERROR:subport_init: pp_port bitmap alloc failed\n"))); 6572 6573 bcm_kt2_subport_free_resource(unit); 6574 6575 return BCM_E_MEMORY; 6576 } 6577 } 6578 6579 sal_memset(_bcm_subport_pp_port_bitmap[unit], 0, 6580 SHR_BITALLOCSIZE(pp_port_index_max + 1)); 6581 6582 _bcm_subport_pp_port_count[unit] = 0; 6583 6584 6585 /* Initialize common SUBPORT module */ 6586 6587 /* If the subport-feature is disabled, unset the relevant 6588 handlers in the vector, these would have been setup by 6589 default for all KT2 devices, the feature being disabled 6590 is an exception */ 6591 if(!soc_feature(unit, soc_feature_subport_enhanced)) { 6592 bcmi_kt2_subport_drv.subport_init = NULL; 6593 bcmi_kt2_subport_drv.subport_group_create = NULL; 6594 bcmi_kt2_subport_drv.subport_group_get = NULL; 6595 bcmi_kt2_subport_drv.subport_group_traverse = NULL; 6596 bcmi_kt2_subport_drv.subport_group_destroy = NULL; 6597 bcmi_kt2_subport_drv.subport_linkphy_config_set = NULL; 6598 bcmi_kt2_subport_drv.subport_linkphy_config_get = NULL; 6599 bcmi_kt2_subport_drv.subport_port_add = NULL; 6600 bcmi_kt2_subport_drv.subport_port_get = NULL; 6601 bcmi_kt2_subport_drv.subport_port_traverse = NULL; 6602 bcmi_kt2_subport_drv.subport_port_stat_set = NULL; 6603 bcmi_kt2_subport_drv.subport_port_stat_get = NULL; 6604 bcmi_kt2_subport_drv.subport_port_delete = NULL; 6605 bcmi_kt2_subport_drv.subport_cleanup = NULL; 6606 } 6607 6608 BCM_IF_ERROR_RETURN 6609 (bcmi_subport_common_init(unit, &bcmi_kt2_subport_drv)); 6610 6611 return rv; 6612 } 6613 6614 /* 6615 * Function: 6616 * bcm_kt2_subport_group_create 6617 * Purpose: 6618 * Create a subport group 6619 * Parameters: 6620 * unit - (IN) Device Number 6621 * config - (IN) Subport group config information 6622 * group - (OUT) GPORT (generic port) identifier 6623 * Returns: 6624 * BCM_E_XXX 6625 */ 6626 int 6627 bcm_kt2_subport_group_create(int unit, 6628 bcm_subport_group_config_t *config, 6629 bcm_gport_t *group) 6630 { 6631 int rv = BCM_E_NONE, group_id = -1, i = 0, is_trunk = 0; 6632 bcm_port_t port = 0; 6633 soc_info_t *si = &SOC_INFO(unit); 6634 int subport_group_max = si->subport_group_max; 6635 6636 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 6637 6638 if ((config == NULL) || (group == NULL)) { 6639 return BCM_E_PARAM; 6640 } 6641 6642 if ((config->flags & BCM_SUBPORT_GROUP_TYPE_LINKPHY) && 6643 (config->flags & BCM_SUBPORT_GROUP_TYPE_SUBPORT_TAG)) { 6644 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6645 (BSL_META_U(unit, 6646 "ERROR:Either LinkPHY or SubTag group can " 6647 "be created at a time\n"))); 6648 return BCM_E_PARAM; 6649 } 6650 6651 if (!(config->flags & BCM_SUBPORT_GROUP_TYPE_GENERAL)) { 6652 rv = _bcm_esw_port_gport_validate(unit, config->port, &port); 6653 if (SOC_FAILURE(rv)) { 6654 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6655 (BSL_META_U(unit, 6656 "ERROR: Invalid gport 0x%x for subport group create.\n"), 6657 config->port)); 6658 return BCM_E_PORT; 6659 } 6660 } 6661 6662 if ((config->flags & BCM_SUBPORT_GROUP_TYPE_LINKPHY) && 6663 !BCM_PBMP_MEMBER(si->linkphy_pbm, port)) { 6664 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6665 (BSL_META_U(unit, 6666 "ERROR: port %d is not member of pbmp_linkphy\n"), 6667 port)); 6668 return BCM_E_PORT; 6669 } 6670 6671 if ((config->flags & BCM_SUBPORT_GROUP_TYPE_SUBPORT_TAG) && 6672 !BCM_PBMP_MEMBER(si->subtag_pbm, port)) { 6673 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6674 (BSL_META_U(unit, 6675 "ERROR: SubportTag/CoE should be enabled" 6676 " for port %d\n"), port)); 6677 return BCM_E_PORT; 6678 } 6679 6680 if (config->flags & BCM_SUBPORT_GROUP_TYPE_GENERAL) { 6681 if ((config->flags & BCM_SUBPORT_GROUP_TYPE_LINKPHY) || 6682 (config->flags & BCM_SUBPORT_GROUP_TYPE_SUBPORT_TAG)) { 6683 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6684 (BSL_META_U(unit, 6685 "ERROR: General subport group not supported " 6686 "with Linkphy/Coe applications.\n"))); 6687 return BCM_E_CONFIG; 6688 } 6689 } 6690 6691 if (_bcm_subport_group_count[unit] == subport_group_max) { 6692 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6693 (BSL_META_U(unit, 6694 "ERROR: All %d subport groups already used.\n"), 6695 subport_group_max)); 6696 return BCM_E_FULL; 6697 } 6698 6699 if (config->flags & BCM_SUBPORT_GROUP_WITH_ID) { 6700 group_id = BCM_GPORT_SUBPORT_GROUP_GET(*group); 6701 /* Group id should be within 0 to 128. 6702 * BCM_GPORT_SUBPORT_GROUP_MASK is 0xffffff (for all chips) 6703 * but subtag/linkphy group id is only first 9 bits (8-0). 6704 * Check that only subtag/linkphy group id bits (8-0) are configured*/ 6705 if ((group_id >> _BCM_KT2_SUBPORT_GROUP_PORT_SHIFT) 6706 & _SHR_GPORT_SUBPORT_GROUP_MASK) { 6707 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6708 (BSL_META_U(unit, 6709 "ERROR: subport group id = %d should be within 0 to" 6710 " %d\n"), group_id, SOC_INFO(unit).subport_group_max-1)); 6711 return BCM_E_PARAM; 6712 } 6713 if (_BCM_KT2_SUBPORT_GROUP_USED_GET(unit, group_id)) { 6714 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6715 (BSL_META_U(unit, 6716 "ERROR: subport group id = %d is already used\n"), 6717 group_id)); 6718 return BCM_E_EXISTS; 6719 } 6720 } else { 6721 for (i =0; i < subport_group_max; i++) { 6722 if (!_BCM_KT2_SUBPORT_GROUP_USED_GET(unit, i)) { 6723 group_id = i; 6724 break; 6725 } 6726 } 6727 6728 if (i == subport_group_max) { 6729 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6730 (BSL_META_U(unit, 6731 "ERROR: All %d subport groups already used.\n"), 6732 i)); 6733 return BCM_E_FULL; 6734 } 6735 } 6736 6737 _BCM_KT2_SUBPORT_LOCK(unit); 6738 6739 if (soc_feature(unit, soc_feature_linkphy_coe) && 6740 (config->flags & BCM_SUBPORT_GROUP_TYPE_LINKPHY)) { 6741 6742 rv =_bcm_linkphy_subport_group_create(unit, 6743 is_trunk, port, group_id, group); 6744 if (SOC_FAILURE(rv)) { 6745 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6746 (BSL_META_U(unit, 6747 "ERROR: LinkPHY subport group create failed" 6748 " for port %d. rv = %d(%s)\n"), 6749 config->port, rv, soc_errmsg(rv))); 6750 _BCM_KT2_SUBPORT_UNLOCK(unit); 6751 return rv; 6752 } 6753 } else if (soc_feature(unit, soc_feature_subtag_coe) && 6754 (config->flags & BCM_SUBPORT_GROUP_TYPE_SUBPORT_TAG)) { 6755 rv =_bcm_subtag_subport_group_create(unit, 6756 is_trunk, port, group_id, group); 6757 if (SOC_FAILURE(rv)) { 6758 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6759 (BSL_META_U(unit, 6760 "ERROR: SubTag subport group create failed" 6761 " for port %d. rv = %d(%s)\n"), 6762 config->port, rv, soc_errmsg(rv))); 6763 _BCM_KT2_SUBPORT_UNLOCK(unit); 6764 return rv; 6765 } 6766 } else if (soc_feature(unit, soc_feature_general_cascade) && 6767 (config->flags & BCM_SUBPORT_GROUP_TYPE_GENERAL)) { 6768 rv =_bcm_general_subport_group_create(unit, 6769 is_trunk, port, 6770 group_id, group); 6771 if (SOC_FAILURE(rv)) { 6772 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6773 (BSL_META_U(unit, 6774 "ERROR: General subport group create failed" 6775 " for port %d. rv = %d(%s)\n"), 6776 config->port, rv, soc_errmsg(rv))); 6777 _BCM_KT2_SUBPORT_UNLOCK(unit); 6778 return rv; 6779 } 6780 } 6781 6782 /* defensive check for static analyzers */ 6783 if (group_id == -1) { 6784 _BCM_KT2_SUBPORT_UNLOCK(unit); 6785 return BCM_E_INTERNAL; 6786 } 6787 _BCM_KT2_SUBPORT_GROUP_USED_SET(unit, group_id); 6788 _bcm_subport_group_count[unit]++; 6789 6790 _BCM_KT2_SUBPORT_UNLOCK(unit); 6791 6792 #ifdef BCM_WARM_BOOT_SUPPORT 6793 SOC_CONTROL_LOCK(unit); 6794 SOC_CONTROL(unit)->scache_dirty = 1; 6795 SOC_CONTROL_UNLOCK(unit); 6796 #endif 6797 6798 return BCM_E_NONE; 6799 6800 } 6801 6802 6803 /* 6804 * Function: 6805 * bcm_kt2_subport_group_destroy 6806 * Purpose: 6807 * Destroy a subport group and all subport ports attached to it. 6808 * Parameters: 6809 * unit - (IN) Device Number 6810 * group - (IN) GPORT (generic port) identifier for subport group 6811 * Returns: 6812 * BCM_E_XXX 6813 */ 6814 int 6815 bcm_kt2_subport_group_destroy(int unit, 6816 bcm_gport_t group) 6817 { 6818 int rv = BCM_E_NONE; 6819 soc_info_t *si = &SOC_INFO(unit); 6820 6821 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 6822 6823 if (!BCM_GPORT_IS_SUBPORT_GROUP(group)) { 6824 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6825 (BSL_META_U(unit, 6826 "ERROR: group 0x%x is not subport group gport\n"), 6827 group)); 6828 return BCM_E_PARAM; 6829 } 6830 6831 _BCM_KT2_SUBPORT_LOCK(unit); 6832 6833 if (soc_feature(unit, soc_feature_linkphy_coe) && 6834 _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(group)) { 6835 if (BCM_PBMP_IS_NULL(si->linkphy_pbm)) { 6836 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6837 (BSL_META_U(unit, 6838 "ERROR: LinkPHY ports not configured\n"))); 6839 _BCM_KT2_SUBPORT_UNLOCK(unit); 6840 return BCM_E_PARAM; 6841 } 6842 rv = _bcm_linkphy_subport_group_destroy(unit, group); 6843 } else if (soc_feature(unit, soc_feature_subtag_coe) && 6844 _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) { 6845 if (BCM_PBMP_IS_NULL(si->subtag_pbm)) { 6846 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6847 (BSL_META_U(unit, 6848 "ERROR: SubTag ports not configured\n"))); 6849 _BCM_KT2_SUBPORT_UNLOCK(unit); 6850 return BCM_E_PARAM; 6851 } 6852 rv = _bcm_subtag_subport_group_destroy(unit, group); 6853 } else if (soc_feature(unit, soc_feature_general_cascade) && 6854 _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(group)) { 6855 rv = _bcm_general_subport_group_destroy(unit, group); 6856 } 6857 6858 if (SOC_FAILURE(rv)) { 6859 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6860 (BSL_META_U(unit, 6861 "ERROR: subport group 0x%x destroy failed. rv= %d(%s)\n"), 6862 group, rv, soc_errmsg(rv))); 6863 _BCM_KT2_SUBPORT_UNLOCK(unit); 6864 return rv; 6865 } 6866 6867 _BCM_KT2_SUBPORT_UNLOCK(unit); 6868 6869 #ifdef BCM_WARM_BOOT_SUPPORT 6870 SOC_CONTROL_LOCK(unit); 6871 SOC_CONTROL(unit)->scache_dirty = 1; 6872 SOC_CONTROL_UNLOCK(unit); 6873 #endif 6874 6875 return BCM_E_NONE; 6876 } 6877 6878 /* 6879 * Function: 6880 * bcm_kt2_subport_group_get 6881 * Purpose: 6882 * Get a subport group 6883 * Parameters: 6884 * unit - (IN) Device Number 6885 * group - (IN) GPORT (generic port) identifier 6886 * config - (OUT) Subport group config information 6887 * Returns: 6888 * BCM_E_XXX 6889 */ 6890 int 6891 bcm_kt2_subport_group_get(int unit, 6892 bcm_gport_t group, 6893 bcm_subport_group_config_t *config) 6894 { 6895 int rv = BCM_E_NONE; 6896 soc_info_t *si = &SOC_INFO(unit); 6897 6898 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 6899 6900 if (config == NULL) { 6901 return BCM_E_PARAM; 6902 } 6903 6904 if (!BCM_GPORT_IS_SUBPORT_GROUP(group)) { 6905 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6906 (BSL_META_U(unit, 6907 "ERROR: group 0x%x is not subport group gport\n"), 6908 group)); 6909 return BCM_E_PARAM; 6910 } 6911 6912 _BCM_KT2_SUBPORT_LOCK(unit); 6913 6914 if (soc_feature(unit, soc_feature_linkphy_coe) && 6915 _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(group)) { 6916 if (BCM_PBMP_IS_NULL(si->linkphy_pbm)) { 6917 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6918 (BSL_META_U(unit, 6919 "ERROR: LinkPHY ports not configured\n"))); 6920 _BCM_KT2_SUBPORT_UNLOCK(unit); 6921 return BCM_E_PARAM; 6922 } 6923 rv = _bcm_linkphy_subport_group_get(unit, group, config); 6924 } else if (soc_feature(unit, soc_feature_subtag_coe) && 6925 _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) { 6926 if (BCM_PBMP_IS_NULL(si->subtag_pbm)) { 6927 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6928 (BSL_META_U(unit, 6929 "ERROR: SubTag ports not configured\n"))); 6930 _BCM_KT2_SUBPORT_UNLOCK(unit); 6931 return BCM_E_PARAM; 6932 } 6933 rv = _bcm_subtag_subport_group_get(unit, group, config); 6934 } else if (soc_feature(unit, soc_feature_general_cascade) && 6935 _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(group)) { 6936 rv = _bcm_general_subport_group_get(unit, group, config); 6937 } 6938 6939 if (SOC_FAILURE(rv)) { 6940 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6941 (BSL_META_U(unit, 6942 "ERROR: subport group get failed for 0x%x, rv = %d(%s)\n"), 6943 group, rv, soc_errmsg(rv))); 6944 _BCM_KT2_SUBPORT_UNLOCK(unit); 6945 return rv; 6946 } 6947 6948 _BCM_KT2_SUBPORT_UNLOCK(unit); 6949 6950 return BCM_E_NONE; 6951 } 6952 6953 /* 6954 * Function: 6955 * bcm_kt2_subport_group_traverse 6956 * Purpose: 6957 * Traverse all valid subports for given subport group and call the user 6958 * supplied callback routine. 6959 * Parameters: 6960 * unit - Device Number 6961 * group - Subport group GPORT identifier 6962 * cb - User callback function, called once per subport. 6963 * user_data - cookie 6964 */ 6965 6966 int 6967 bcm_kt2_subport_group_traverse(int unit, 6968 bcm_gport_t group, 6969 bcm_subport_port_traverse_cb cb, 6970 void *user_data) 6971 { 6972 int rv = BCM_E_NONE; 6973 soc_info_t *si = &SOC_INFO(unit); 6974 6975 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 6976 6977 if (!BCM_GPORT_IS_SUBPORT_GROUP(group)) { 6978 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6979 (BSL_META_U(unit, 6980 "ERROR: group 0x%x is not subport group gport\n"), 6981 group)); 6982 return BCM_E_PARAM; 6983 } 6984 6985 _BCM_KT2_SUBPORT_LOCK(unit); 6986 6987 if (soc_feature(unit, soc_feature_linkphy_coe) && 6988 _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(group)) { 6989 if (BCM_PBMP_IS_NULL(si->linkphy_pbm)) { 6990 LOG_ERROR(BSL_LS_BCM_SUBPORT, 6991 (BSL_META_U(unit, 6992 "ERROR: LinkPHY ports not configured\n"))); 6993 _BCM_KT2_SUBPORT_UNLOCK(unit); 6994 return BCM_E_PARAM; 6995 } 6996 rv =_bcm_linkphy_subport_group_traverse(unit, group, cb, user_data); 6997 } else if (soc_feature(unit, soc_feature_subtag_coe) && 6998 _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(group)) { 6999 if (BCM_PBMP_IS_NULL(si->subtag_pbm)) { 7000 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7001 (BSL_META_U(unit, 7002 "ERROR: SubTag ports not configured\n"))); 7003 _BCM_KT2_SUBPORT_UNLOCK(unit); 7004 return BCM_E_PARAM; 7005 } 7006 rv =_bcm_subtag_subport_group_traverse(unit, group, cb, user_data); 7007 } else if (soc_feature(unit, soc_feature_general_cascade) && 7008 _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(group)) { 7009 rv =_bcm_general_subport_group_traverse(unit, group, cb, user_data); 7010 } 7011 7012 if (SOC_FAILURE(rv)) { 7013 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7014 (BSL_META_U(unit, 7015 "ERROR: subport group traverse failed for 0x%x, rv = %d(%s)\n"), 7016 group, rv, soc_errmsg(rv))); 7017 _BCM_KT2_SUBPORT_UNLOCK(unit); 7018 return rv; 7019 } 7020 7021 _BCM_KT2_SUBPORT_UNLOCK(unit); 7022 7023 return BCM_E_NONE; 7024 } 7025 7026 /* 7027 * Function: 7028 * bcm_kt2_subport_group_resolve 7029 * Purpose: 7030 * resolve physical port associated with the LinkPHy subport group 7031 */ 7032 int 7033 bcm_kt2_subport_group_resolve(int unit, 7034 bcm_gport_t subport_group_gport, 7035 bcm_module_t *modid, bcm_port_t *port, 7036 bcm_trunk_t *trunk_id, int *id) 7037 7038 { 7039 bcm_module_t my_modid; 7040 uint16 group_id; 7041 7042 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 7043 7044 *modid = -1; 7045 *port = -1; 7046 *id = -1; 7047 *trunk_id = BCM_TRUNK_INVALID; 7048 7049 if (!BCM_GPORT_IS_SUBPORT_GROUP(subport_group_gport)) { 7050 LOG_WARN(BSL_LS_BCM_SUBPORT, 7051 (BSL_META_U(unit, 7052 "gport 0x%x is not subport gport\n"), 7053 subport_group_gport)); 7054 return BCM_E_NONE; 7055 } 7056 7057 if ((soc_feature(unit, soc_feature_linkphy_coe) && 7058 _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(subport_group_gport)) || 7059 (soc_feature(unit, soc_feature_subtag_coe) && 7060 _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(subport_group_gport)) || 7061 (soc_feature(unit, soc_feature_general_cascade) && 7062 _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(subport_group_gport))) { 7063 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(subport_group_gport); 7064 if(!_BCM_KT2_SUBPORT_GROUP_USED_GET(unit, group_id)) { 7065 LOG_WARN(BSL_LS_BCM_SUBPORT, 7066 (BSL_META_U(unit, 7067 "subport gport 0x%x is not used\n"), 7068 subport_group_gport)); 7069 return BCM_E_NONE; 7070 } 7071 7072 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 7073 *modid = my_modid; 7074 *port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(subport_group_gport); 7075 } else if (soc_feature(unit, soc_feature_subport_enhanced)) { 7076 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 7077 return _bcm_tr2_subport_group_resolve(unit, subport_group_gport, 7078 modid, port, trunk_id,id); 7079 #endif 7080 } else if (soc_feature(unit, soc_feature_subport)) { 7081 #if defined (BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 7082 return _bcm_tr_subport_group_resolve(unit, subport_group_gport, 7083 modid, port, trunk_id, id); 7084 #endif 7085 } 7086 7087 return BCM_E_NONE; 7088 7089 } 7090 7091 /* 7092 * Function: 7093 * bcm_kt2_subport_port_add 7094 * Purpose: 7095 * Add a subport to a subport group 7096 * Parameters: 7097 * unit - (IN) Device Number 7098 * config - (IN) Subport config information 7099 * port - (OUT) Subport_port GPORT (generic port) identifier 7100 * Returns: 7101 * BCM_E_XXX 7102 */ 7103 int 7104 bcm_kt2_subport_port_add(int unit, 7105 bcm_subport_config_t *config, 7106 bcm_gport_t *gport) 7107 { 7108 int rv = BCM_E_NONE; 7109 uint16 group_id; 7110 soc_info_t *si = &SOC_INFO(unit); 7111 int subport_port_max = si->subport_port_max; 7112 7113 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 7114 7115 if (!BCM_GPORT_IS_SUBPORT_GROUP(config->group)) { 7116 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7117 (BSL_META_U(unit, 7118 "ERROR: config->group 0x%x is not subport group gport\n"), 7119 config->group)); 7120 return BCM_E_PARAM; 7121 } 7122 7123 group_id = _BCM_KT2_SUBPORT_GROUP_ID_GET(config->group); 7124 if(!_BCM_KT2_SUBPORT_GROUP_USED_GET(unit, group_id)) { 7125 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7126 (BSL_META_U(unit, 7127 "ERROR:config->group 0x%x is not found\n"), 7128 config->group)); 7129 return BCM_E_NOT_FOUND; 7130 } 7131 7132 if (_bcm_subport_pp_port_count[unit] == subport_port_max) { 7133 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7134 (BSL_META_U(unit, 7135 "ERROR:All %d subport pp_port used\n"), 7136 subport_port_max)); 7137 return BCM_E_FULL; 7138 } 7139 7140 _BCM_KT2_SUBPORT_LOCK(unit); 7141 7142 if (soc_feature(unit, soc_feature_linkphy_coe) && 7143 _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_GROUP(config->group)) { 7144 if (BCM_PBMP_IS_NULL(si->linkphy_pbm)) { 7145 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7146 (BSL_META_U(unit, 7147 "ERROR: LinkPHY ports not configured\n"))); 7148 _BCM_KT2_SUBPORT_UNLOCK(unit); 7149 return BCM_E_PARAM; 7150 } 7151 rv = _bcm_linkphy_subport_port_add(unit, config, gport); 7152 } else if (soc_feature(unit, soc_feature_subtag_coe) && 7153 _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(config->group)) { 7154 if (BCM_PBMP_IS_NULL(si->subtag_pbm)) { 7155 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7156 (BSL_META_U(unit, 7157 "ERROR: SubTag ports not configured\n"))); 7158 _BCM_KT2_SUBPORT_UNLOCK(unit); 7159 return BCM_E_PARAM; 7160 } 7161 rv = _bcm_subtag_subport_port_add(unit, config, gport); 7162 } else if (soc_feature(unit, soc_feature_general_cascade) && 7163 _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_GROUP(config->group)) { 7164 rv = _bcm_general_subport_port_add(unit, config, gport); 7165 } 7166 7167 if (SOC_FAILURE(rv)) { 7168 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7169 (BSL_META_U(unit, 7170 "ERROR: Subport port add failed. rv = %d(%s)\n"), 7171 rv, soc_errmsg(rv))); 7172 _BCM_KT2_SUBPORT_UNLOCK(unit); 7173 return rv; 7174 } 7175 7176 _BCM_KT2_SUBPORT_UNLOCK(unit); 7177 7178 #ifdef BCM_WARM_BOOT_SUPPORT 7179 SOC_CONTROL_LOCK(unit); 7180 SOC_CONTROL(unit)->scache_dirty = 1; 7181 SOC_CONTROL_UNLOCK(unit); 7182 #endif 7183 7184 return rv; 7185 } 7186 7187 /* 7188 * Function: 7189 * bcm_kt2_subport_port_delete 7190 * Purpose: 7191 * Delete a subport_port 7192 * Parameters: 7193 * unit - (IN) Device Number 7194 * port - (IN) Subport_port GPORT (generic port) identifier 7195 * Returns: 7196 * BCM_E_XXX 7197 */ 7198 int 7199 bcm_kt2_subport_port_delete(int unit, 7200 bcm_gport_t subport_port_gport) 7201 { 7202 int rv = BCM_E_NONE; 7203 7204 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 7205 7206 if (!BCM_GPORT_IS_SUBPORT_PORT(subport_port_gport)) { 7207 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7208 (BSL_META_U(unit, 7209 "ERROR: gport 0x%x is not subport port gport\n"), 7210 subport_port_gport)); 7211 return BCM_E_PARAM; 7212 } 7213 7214 _BCM_KT2_SUBPORT_LOCK(unit); 7215 7216 if (soc_feature(unit, soc_feature_linkphy_coe) && 7217 _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, subport_port_gport)) { 7218 rv = _bcm_linkphy_subport_port_delete(unit, subport_port_gport); 7219 } else if (soc_feature(unit, soc_feature_subtag_coe) && 7220 _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_port_gport)) { 7221 rv = _bcm_subtag_subport_port_delete(unit, subport_port_gport); 7222 } else if (soc_feature(unit, soc_feature_general_cascade) && 7223 _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_PORT(unit, subport_port_gport)) { 7224 rv = _bcm_general_subport_port_delete(unit, subport_port_gport); 7225 } 7226 7227 if (SOC_FAILURE(rv)) { 7228 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7229 (BSL_META_U(unit, 7230 "ERROR: Subport port 0x%x delete failed. rv = %d(%s)\n"), 7231 subport_port_gport, rv, soc_errmsg(rv))); 7232 _BCM_KT2_SUBPORT_UNLOCK(unit); 7233 return rv; 7234 } 7235 7236 _BCM_KT2_SUBPORT_UNLOCK(unit); 7237 7238 #ifdef BCM_WARM_BOOT_SUPPORT 7239 SOC_CONTROL_LOCK(unit); 7240 SOC_CONTROL(unit)->scache_dirty = 1; 7241 SOC_CONTROL_UNLOCK(unit); 7242 #endif 7243 7244 return rv; 7245 } 7246 7247 /* 7248 * Function: 7249 * bcm_kt2_subport_port_get 7250 * Purpose: 7251 * Get the subport_port config 7252 * Parameters: 7253 * unit - (IN) Device Number 7254 * port - (IN) Subport_port GPORT (generic port) identifier 7255 * config - (OUT) Subport port config 7256 * Returns: 7257 * BCM_E_XXX 7258 */ 7259 int 7260 bcm_kt2_subport_port_get(int unit, 7261 bcm_gport_t subport_port_gport, 7262 bcm_subport_config_t *config) 7263 { 7264 int rv = BCM_E_NONE; 7265 7266 if (config == NULL) { 7267 return BCM_E_PARAM; 7268 } 7269 7270 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 7271 7272 if (!BCM_GPORT_IS_SUBPORT_PORT(subport_port_gport)) { 7273 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7274 (BSL_META_U(unit, 7275 "ERROR: gport 0x%x is not subport port gport\n"), 7276 subport_port_gport)); 7277 return BCM_E_PARAM; 7278 } 7279 7280 _BCM_KT2_SUBPORT_LOCK(unit); 7281 7282 if (soc_feature(unit, soc_feature_linkphy_coe) && 7283 _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, subport_port_gport)) { 7284 rv = _bcm_linkphy_subport_port_get(unit, subport_port_gport, config); 7285 } else if (soc_feature(unit, soc_feature_subtag_coe) && 7286 _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_port_gport)) { 7287 rv = _bcm_subtag_subport_port_get(unit, subport_port_gport, config); 7288 } else if (soc_feature(unit, soc_feature_general_cascade) && 7289 _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_PORT(unit, subport_port_gport)) { 7290 rv = _bcm_general_subport_port_get(unit, subport_port_gport, config); 7291 } 7292 7293 if (SOC_FAILURE(rv)) { 7294 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 7295 (BSL_META_U(unit, 7296 "ERROR: Subport port 0x%x get failed. rv=%d(%s)\n"), 7297 subport_port_gport, rv, soc_errmsg(rv))); 7298 _BCM_KT2_SUBPORT_UNLOCK(unit); 7299 return rv; 7300 } 7301 7302 _BCM_KT2_SUBPORT_UNLOCK(unit); 7303 7304 return BCM_E_NONE; 7305 } 7306 7307 /* 7308 * Function: 7309 * bcm_kt2_subport_port_traverse 7310 * Purpose: 7311 * Add all valid subports under all valid subport groups 7312 * Parameters: 7313 * unit - Device Number 7314 * cb - User callback function, called once per subport. 7315 * user_data - cookie 7316 * Returns: 7317 * BCM_E_XXX 7318 */ 7319 7320 int 7321 bcm_kt2_subport_port_traverse(int unit, 7322 bcm_subport_port_traverse_cb cb, 7323 void *user_data) 7324 { 7325 int rv = BCM_E_NONE; 7326 soc_info_t *si = &SOC_INFO(unit); 7327 7328 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 7329 7330 _BCM_KT2_SUBPORT_LOCK(unit); 7331 7332 if(soc_feature(unit, soc_feature_linkphy_coe) && 7333 BCM_PBMP_NOT_NULL(si->linkphy_pbm)) { 7334 rv = _bcm_linkphy_subport_port_traverse(unit, cb, user_data); 7335 } 7336 if (soc_feature(unit, soc_feature_subtag_coe) && 7337 BCM_PBMP_NOT_NULL(si->subtag_pbm)) { 7338 rv = _bcm_subtag_subport_port_traverse(unit, cb, user_data); 7339 } 7340 if (soc_feature(unit, soc_feature_general_cascade)) { 7341 rv = _bcm_general_subport_port_traverse(unit, cb, user_data); 7342 } 7343 7344 if (SOC_FAILURE(rv)) { 7345 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7346 (BSL_META_U(unit, 7347 "ERROR:Subport port traverse failed. rv = %d(%s)\n"), 7348 rv,soc_errmsg(rv))); 7349 _BCM_KT2_SUBPORT_UNLOCK(unit); 7350 return rv; 7351 } 7352 7353 _BCM_KT2_SUBPORT_UNLOCK(unit); 7354 7355 return BCM_E_NONE; 7356 } 7357 7358 /* 7359 * Function: 7360 * bcm_kt2_subport_port_resolve 7361 * Purpose: 7362 * resolve pp_port associated with the LinkPHy subport port 7363 */ 7364 int 7365 bcm_kt2_subport_port_resolve(int unit, 7366 bcm_gport_t subport_port_gport, 7367 bcm_module_t *modid, bcm_port_t *port, 7368 bcm_trunk_t *trunk_id, int *id) 7369 { 7370 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 7371 7372 *modid = -1; 7373 *port = -1; 7374 *id = -1; 7375 *trunk_id = BCM_TRUNK_INVALID; 7376 7377 if (!BCM_GPORT_IS_SUBPORT_PORT(subport_port_gport)) { 7378 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7379 (BSL_META_U(unit, 7380 "ERROR: gport 0x%x is not subport gport\n"), 7381 subport_port_gport)); 7382 return BCM_E_PARAM; 7383 } 7384 7385 if ((soc_feature(unit, soc_feature_linkphy_coe) && 7386 _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, subport_port_gport)) || 7387 (soc_feature(unit, soc_feature_subtag_coe) && 7388 _BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_port_gport)) || 7389 (soc_feature(unit, soc_feature_general_cascade) && 7390 _BCM_KT2_GPORT_IS_GENERAL_SUBPORT_PORT(unit, subport_port_gport))) { 7391 BCM_IF_ERROR_RETURN(_bcm_kt2_pp_port_to_modport_get( 7392 unit, subport_port_gport, modid, port)); 7393 } else if (soc_feature(unit, soc_feature_subport_enhanced)) { 7394 #if defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) 7395 return _bcm_tr2_subport_port_resolve(unit,subport_port_gport, 7396 modid, port, trunk_id, id); 7397 #endif /* defined(BCM_TRIUMPH2_SUPPORT) && defined(INCLUDE_L3) */ 7398 } else if (soc_feature(unit, soc_feature_subport)) { 7399 #if defined (BCM_TRX_SUPPORT) && defined(INCLUDE_L3) 7400 return _bcm_tr_subport_port_resolve(unit, subport_port_gport, 7401 modid, port, trunk_id, id); 7402 #endif 7403 } 7404 return BCM_E_NONE; 7405 } 7406 7407 int bcm_kt2_subport_pp_port_s1_index_get(int unit, 7408 bcm_port_t pp_port, 7409 int *s1_index) 7410 { 7411 int rv = BCM_E_NONE; 7412 #if defined BCM_METROLITE_SUPPORT 7413 soc_info_t *si = &SOC_INFO(unit); 7414 soc_port_t port; 7415 int i = 0, index = 0, found = 0; 7416 7417 /* Retreive s1 index from provided pp port */ 7418 for (port = 0 ; port < ML_MAX_LOGICAL_PORTS; port ++) { 7419 index = 0; 7420 SOC_PBMP_ITER(SOC_PORT_PP_BITMAP(unit, port), i) { 7421 index++; 7422 if (pp_port == i) { 7423 found = 1; 7424 break; 7425 } 7426 } 7427 if (found) { 7428 break; 7429 } 7430 } 7431 7432 if (found) { 7433 *s1_index = si->port_subport_base[port] + (index -1); 7434 return rv; 7435 } else { 7436 rv = BCM_E_NOT_FOUND; 7437 } 7438 #endif 7439 7440 *s1_index = -1; 7441 return rv; 7442 } 7443 7444 /* 7445 * Function: 7446 * bcm_kt2_subport_pp_port_subport_info_get 7447 * Purpose: 7448 * Get physical port number and port_type (LinkPHY/SubTag/General), SubTag/Device internal 7449 * stream IDs for given pp_port. 7450 * If subport_port and group are not configured for the pp_port the port number 7451 * and type are returned as -1. 7452 * Returns 7453 * BCM_E_XXX 7454 */ 7455 7456 int bcm_kt2_subport_pp_port_subport_info_get(int unit, 7457 bcm_port_t pp_port, 7458 _bcm_kt2_subport_info_t *subport_info) 7459 { 7460 bcm_gport_t subport_port; 7461 int rv = BCM_E_NONE, i = 0; 7462 uint16 dev_int_stream_id_base = 0, ext_stream_id_base = 0, int_stream_id = 0; 7463 bcm_subport_config_t subport_port_config; 7464 int pp_port_index_min = SOC_INFO(unit).pp_port_index_min; 7465 int pp_port_index_max = SOC_INFO(unit).pp_port_index_max; 7466 int lp_block = 0, lp_index = 0; 7467 uint16 port_e_stream_id_base_adj = 0; 7468 uint16 blk_int_stream_id = 0; 7469 7470 if (subport_info == NULL) { 7471 return BCM_E_MEMORY; 7472 } 7473 7474 sal_memset(subport_info, 0, sizeof(_bcm_kt2_subport_info_t)); 7475 7476 if ((pp_port < pp_port_index_min) || 7477 (pp_port > pp_port_index_max)) { 7478 if (SOC_PORT_VALID(unit, pp_port)) { 7479 subport_info->port = pp_port; 7480 return BCM_E_NONE; 7481 } else { 7482 return BCM_E_PORT; 7483 } 7484 } 7485 7486 if (BCM_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) { 7487 subport_info->port_type = _BCM_KT2_SUBPORT_TYPE_LINKPHY; 7488 } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) { 7489 subport_info->port_type = _BCM_KT2_SUBPORT_TYPE_SUBTAG; 7490 } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).general_pp_port_pbm, pp_port)) { 7491 subport_info->port_type = _BCM_KT2_SUBPORT_TYPE_GENERAL; 7492 } else { 7493 return BCM_E_PORT; 7494 } 7495 7496 _BCM_KT2_SUBPORT_PORT_ID_SET(subport_port, pp_port); 7497 _BCM_KT2_SUBPORT_PORT_TYPE_SET(subport_port, subport_info->port_type); 7498 7499 rv = bcm_kt2_subport_port_get(unit, subport_port, &subport_port_config); 7500 if (BCM_FAILURE(rv)) { 7501 return rv; 7502 } 7503 7504 subport_info->port = 7505 _BCM_KT2_SUBPORT_GROUP_PORT_GET(subport_port_config.group); 7506 7507 7508 7509 if (subport_info->port_type == _BCM_KT2_SUBPORT_TYPE_SUBTAG) { 7510 subport_info->subtag = subport_port_config.pkt_vlan & 0xFFF; 7511 } else if (subport_info->port_type == _BCM_KT2_SUBPORT_TYPE_GENERAL) { 7512 /* Nothing to fill for general subport type */ 7513 } else { 7514 rv = soc_linkphy_port_blk_idx_get(unit, subport_info->port, 7515 &lp_block, &lp_index); 7516 if (SOC_FAILURE(rv)) { 7517 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7518 (BSL_META_U(unit, 7519 "ERROR: LinkPHY block, index get failed for port %d\n"), 7520 subport_info->port)); 7521 return rv; 7522 } 7523 dev_int_stream_id_base = (lp_block)? 128: 0; 7524 7525 subport_info->num_streams = subport_port_config.num_streams; 7526 7527 rv = _bcm_linkphy_port_ext_stream_id_base_get(unit, subport_info->port, 7528 &ext_stream_id_base); 7529 7530 if (BCM_FAILURE(rv)) { 7531 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7532 (BSL_META_U(unit, 7533 "ERROR: Linkphy subport group external stream id " 7534 "base get failed for port %d - %d.\n"), 7535 subport_info->port, ext_stream_id_base)); 7536 return rv; 7537 } 7538 7539 for (i = 0; i < subport_port_config.num_streams; i++) { 7540 port_e_stream_id_base_adj = 7541 subport_port_config.stream_id_array[i] - ext_stream_id_base; 7542 7543 BCM_IF_ERROR_RETURN( 7544 _bcm_linkphy_port_rx_int_stream_map_port_get(unit, 7545 subport_info->port, 7546 port_e_stream_id_base_adj, 7547 &blk_int_stream_id)); 7548 7549 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 7550 (BSL_META_U(unit, 7551 "Linkphy subport group external stream id " 7552 "base get failed for port %d - %d - int_stream_id(%d).\n"), 7553 subport_info->port, ext_stream_id_base, int_stream_id)); 7554 7555 subport_info->dev_int_stream_id[i] = 7556 blk_int_stream_id + dev_int_stream_id_base; 7557 } 7558 } 7559 7560 return BCM_E_NONE; 7561 7562 } 7563 7564 /* 7565 * Function: 7566 * bcm_kt2_subport_cleanup 7567 * Purpose: 7568 * Delate all valid subport ports and all valid subport groups. 7569 Also clean up software resources. 7570 * Parameters: 7571 * unit - Device Number 7572 * Returns: 7573 * BCM_E_XXX 7574 */ 7575 int 7576 bcm_kt2_subport_cleanup(int unit) 7577 { 7578 int rv = BCM_E_NONE; 7579 soc_info_t *si = &SOC_INFO(unit); 7580 7581 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 7582 7583 if (soc_feature(unit, soc_feature_linkphy_coe)) { 7584 if (BCM_PBMP_NOT_NULL(si->linkphy_pbm)) { 7585 rv = _bcm_linkphy_subport_cleanup(unit); 7586 if (SOC_FAILURE(rv)) { 7587 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7588 (BSL_META_U(unit, 7589 "ERROR: LinkPHY cleanup failed\n"))); 7590 return rv; 7591 } 7592 } 7593 } 7594 if (soc_feature(unit, soc_feature_subtag_coe)) { 7595 if (BCM_PBMP_NOT_NULL(si->subtag_allowed_pbm)) { 7596 rv = _bcm_subtag_subport_cleanup(unit); 7597 if (SOC_FAILURE(rv)) { 7598 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7599 (BSL_META_U(unit, 7600 "ERROR: SubTag cleanup failed\n"))); 7601 return rv; 7602 } 7603 } 7604 } 7605 if (soc_feature(unit, soc_feature_general_cascade)) { 7606 rv = _bcm_general_subport_cleanup(unit); 7607 if (SOC_FAILURE(rv)) { 7608 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7609 (BSL_META_U(unit, 7610 "ERROR: General subport cleanup failed\n"))); 7611 return rv; 7612 } 7613 } 7614 7615 bcm_kt2_subport_free_resource(unit); 7616 7617 return BCM_E_NONE; 7618 } 7619 7620 /** 7621 * Function: 7622 * bcm_kt2_subport_group_linkphy_config_get 7623 * Purpose: 7624 * Get ALL or selective LinkPHY configuration attributes 7625 * on a given port GPORT. 7626 * Parameters: 7627 * Parameters: 7628 * uint (IN) BCM device number 7629 * port (IN) port GPORT 7630 * linkphy_cfg (OUT) LinkPHY configuration 7631 * Returns: 7632 * BCM_E_xxx 7633 * Notes: 7634 * When retrieving, if an error is returned then the entire contents of the 7635 * linkphy_config structure are undefined. 7636 */ 7637 7638 int 7639 bcm_kt2_subport_group_linkphy_config_get(int unit, 7640 bcm_gport_t port, 7641 bcm_subport_group_linkphy_config_t *linkphy_config) 7642 { 7643 int rv = BCM_E_NONE; 7644 uint32 regval = 0; 7645 uint32 header_mode = 0; 7646 uint32 mac_addr[2] = {0, 0}; 7647 uint64 rval64, data; 7648 uint16 base_stream_id = 0; 7649 soc_reg_t reg; 7650 int base_stream_id_max = 0; 7651 int ne_mac_check = 0, fe_mac_check = 0, dfc_destmac_check = 0; 7652 int dfc_opcode_check = 0, dfc_time_check = 0; 7653 soc_info_t *si = &SOC_INFO(unit); 7654 int max_streams = si->lp_streams_per_slice_max; 7655 7656 if (!soc_feature(unit, soc_feature_linkphy_coe)) { 7657 return BCM_E_UNAVAIL; 7658 } 7659 7660 if (linkphy_config == NULL) { 7661 return BCM_E_PARAM; 7662 } 7663 7664 if (!BCM_PBMP_MEMBER(si->linkphy_pbm, port)) { 7665 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7666 (BSL_META_U(unit, 7667 "ERROR: Invalid port %d for LinkPHY config get\n"), 7668 port)); 7669 return BCM_E_PORT; 7670 } 7671 7672 sal_memset(linkphy_config, 0, sizeof(bcm_subport_group_linkphy_config_t)); 7673 7674 reg = RXLP_PORT_STREAM_ID_BASEr; 7675 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7676 base_stream_id_max = _BCM_KT2_LINKPHY_STREAMS_MAX - 7677 max_streams; 7678 7679 BCM_IF_ERROR_RETURN( 7680 READ_RXLP_PORT_STREAM_ID_BASEr(unit, port, ®val)); 7681 base_stream_id = soc_reg_field_get(unit, reg, regval, BASEf); 7682 if ((base_stream_id % 8) || (base_stream_id > base_stream_id_max)) { 7683 linkphy_config->action_mask &= ~BCM_SUBPORT_LINKPHY_BASE_STREAM_ID; 7684 } else { 7685 linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_BASE_STREAM_ID; 7686 linkphy_config->base_stream_id = base_stream_id; 7687 } 7688 } 7689 7690 reg = RXLP_PORT_LP_MODE_CONTROLr; 7691 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7692 BCM_IF_ERROR_RETURN( 7693 READ_RXLP_PORT_LP_MODE_CONTROLr(unit, port, ®val)); 7694 header_mode = soc_reg_field_get(unit, reg, regval, HEADER_MODEf); 7695 if ((header_mode == bcmSubportLinkphyHeaderModeEthAdapt) || 7696 (header_mode == bcmSubportLinkphyHeaderModeTciLength)) { 7697 linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_HEADER_MODE; 7698 linkphy_config->header_mode = header_mode; 7699 } 7700 } 7701 7702 COMPILER_64_ZERO(rval64); 7703 COMPILER_64_ZERO(data); 7704 reg = RXLP_PORT_NEAR_END_MAC_ADDRr; 7705 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7706 BCM_IF_ERROR_RETURN( 7707 READ_RXLP_PORT_NEAR_END_MAC_ADDRr(unit, port, &rval64)); 7708 data = soc_reg64_field_get(unit, reg, rval64, CHECK_ENABLEf); 7709 COMPILER_64_TO_32_LO(regval, data); 7710 if ((ne_mac_check = (regval & 0x1))) { 7711 linkphy_config->rx_check_flags |= 7712 BCM_SUBPORT_LINKPHY_RX_NEAREND_MAC_CHECK; 7713 } 7714 } 7715 7716 COMPILER_64_ZERO(rval64); 7717 COMPILER_64_ZERO(data); 7718 reg = RXLP_PORT_FAR_END_MAC_ADDRr; 7719 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7720 BCM_IF_ERROR_RETURN( 7721 READ_RXLP_PORT_FAR_END_MAC_ADDRr(unit, port, &rval64)); 7722 data = soc_reg64_field_get(unit, reg, rval64, CHECK_ENABLEf); 7723 COMPILER_64_TO_32_LO(regval, data); 7724 if ((fe_mac_check = (regval & 0x1))) { 7725 linkphy_config->rx_check_flags |= 7726 BCM_SUBPORT_LINKPHY_RX_FAREND_MAC_CHECK; 7727 } 7728 } 7729 7730 COMPILER_64_ZERO(rval64); 7731 COMPILER_64_ZERO(data); 7732 reg = RXLP_PORT_DFC_DESTINATION_MAC_ADDRr; 7733 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7734 BCM_IF_ERROR_RETURN( 7735 READ_RXLP_PORT_DFC_DESTINATION_MAC_ADDRr(unit, port, &rval64)); 7736 data = soc_reg64_field_get(unit, reg, rval64, CHECK_ENABLEf); 7737 COMPILER_64_TO_32_LO(regval, data); 7738 if ((dfc_destmac_check = (regval & 0x1))) { 7739 linkphy_config->rx_check_flags |= 7740 BCM_SUBPORT_LINKPHY_RX_DFC_DEST_MAC_CHECK; 7741 } 7742 } 7743 7744 reg = RXLP_PORT_DFC_OPCODEr; 7745 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7746 BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_OPCODEr(unit, port, ®val)); 7747 if ((dfc_opcode_check = 7748 soc_reg_field_get(unit, reg, regval, CHECK_ENABLEf))) { 7749 linkphy_config->rx_check_flags |= 7750 BCM_SUBPORT_LINKPHY_RX_DFC_OPCODE_CHECK; 7751 } 7752 } 7753 7754 reg = RXLP_PORT_DFC_TIMEr; 7755 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7756 BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_TIMEr(unit, port, ®val)); 7757 if ((dfc_time_check = 7758 soc_reg_field_get(unit, reg, regval, CHECK_ENABLEf))) { 7759 linkphy_config->rx_check_flags |= 7760 BCM_SUBPORT_LINKPHY_RX_DFC_TIME_CHECK; 7761 } 7762 } 7763 7764 if (ne_mac_check || fe_mac_check || dfc_destmac_check || 7765 dfc_opcode_check || dfc_time_check) { 7766 linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_CHECK_FLAGS; 7767 } 7768 7769 reg = RXLP_PORT_VLAN_TPIDr; 7770 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7771 BCM_IF_ERROR_RETURN(READ_RXLP_PORT_VLAN_TPIDr(unit, port, ®val)); 7772 if ((linkphy_config->rx_vlan_tpid = 7773 soc_reg_field_get(unit, reg, regval, VLAN_TPIDf))) { 7774 linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_VLAN_TPID; 7775 } 7776 } 7777 7778 reg = RXLP_PORT_NEAR_END_MAC_ADDRr; 7779 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7780 BCM_IF_ERROR_RETURN(_bcm_linkphy_reg_mac_addr_get(unit, port, 7781 RXLP_PORT_NEAR_END_MAC_ADDRr, MAC_ADDRf, 7782 linkphy_config->rx_nearend_mac)); 7783 SAL_MAC_ADDR_TO_UINT32(linkphy_config->rx_nearend_mac, mac_addr); 7784 if ((mac_addr[0] != 0) || (mac_addr[1] != 0)) { 7785 linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_NEAREND_MAC; 7786 } 7787 } 7788 7789 reg = RXLP_PORT_FAR_END_MAC_ADDRr; 7790 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7791 BCM_IF_ERROR_RETURN(_bcm_linkphy_reg_mac_addr_get(unit, port, 7792 RXLP_PORT_FAR_END_MAC_ADDRr, MAC_ADDRf, 7793 linkphy_config->rx_farend_mac)); 7794 SAL_MAC_ADDR_TO_UINT32(linkphy_config->rx_farend_mac, mac_addr); 7795 if ((mac_addr[0] != 0) || (mac_addr[1] != 0)) { 7796 linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_FAREND_MAC; 7797 } 7798 } 7799 7800 reg = RXLP_PORT_DFC_DESTINATION_MAC_ADDRr; 7801 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7802 BCM_IF_ERROR_RETURN(_bcm_linkphy_reg_mac_addr_get(unit, port, 7803 RXLP_PORT_DFC_DESTINATION_MAC_ADDRr, MAC_ADDRf, 7804 linkphy_config->rx_dfc_dest_mac)); 7805 SAL_MAC_ADDR_TO_UINT32(linkphy_config->rx_dfc_dest_mac, mac_addr); 7806 if ((mac_addr[0] != 0) || (mac_addr[1] != 0)) { 7807 linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_DFC_DEST_MAC; 7808 } 7809 } 7810 7811 reg = RXLP_PORT_DFC_OPCODEr; 7812 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7813 BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_OPCODEr(unit, port, ®val)); 7814 if ((linkphy_config->rx_dfc_opcode = 7815 soc_reg_field_get(unit, reg, regval, OPCODEf))) { 7816 linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_DFC_OPCODE; 7817 } 7818 } 7819 7820 reg = RXLP_PORT_DFC_TIMEr; 7821 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7822 BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_TIMEr(unit, port, ®val)); 7823 if ((linkphy_config->rx_dfc_time = 7824 soc_reg_field_get(unit, reg, regval, DFC_TIMEf))) { 7825 linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_DFC_TIME; 7826 } 7827 } 7828 7829 reg = RXLP_PORT_DFC_MAC_TYPEr; 7830 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7831 BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_MAC_TYPEr(unit, port, ®val)); 7832 if ((linkphy_config->rx_dfc_mac_type = 7833 soc_reg_field_get(unit, reg, regval, MAC_TYPEf))) { 7834 linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_RX_DFC_MAC_TYPE; 7835 } 7836 } 7837 7838 reg = TXLP_PORT_VLAN_TPIDr; 7839 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7840 BCM_IF_ERROR_RETURN(READ_TXLP_PORT_VLAN_TPIDr(unit, port, ®val)); 7841 if ((linkphy_config->tx_vlan_tpid = 7842 soc_reg_field_get(unit, reg, regval, VLAN_TPIDf))) { 7843 linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_TX_VLAN_TPID; 7844 } 7845 } 7846 7847 reg = TXLP_PORT_NEAR_END_MAC_ADDRr; 7848 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7849 BCM_IF_ERROR_RETURN(_bcm_linkphy_reg_mac_addr_get(unit, port, 7850 TXLP_PORT_NEAR_END_MAC_ADDRr, MAC_ADDRf, 7851 linkphy_config->tx_nearend_mac)); 7852 SAL_MAC_ADDR_TO_UINT32(linkphy_config->tx_nearend_mac, mac_addr); 7853 if ((mac_addr[0] != 0) || (mac_addr[1] != 0)) { 7854 linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_TX_NEAREND_MAC; 7855 } 7856 } 7857 7858 reg = TXLP_PORT_FAR_END_MAC_ADDRr; 7859 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7860 BCM_IF_ERROR_RETURN(_bcm_linkphy_reg_mac_addr_get(unit, port, 7861 TXLP_PORT_FAR_END_MAC_ADDRr, MAC_ADDRf, 7862 linkphy_config->tx_farend_mac)); 7863 SAL_MAC_ADDR_TO_UINT32(linkphy_config->tx_farend_mac, mac_addr); 7864 if ((mac_addr[0] != 0) || (mac_addr[1] != 0)) { 7865 linkphy_config->action_mask |= BCM_SUBPORT_LINKPHY_TX_FAREND_MAC; 7866 } 7867 } 7868 7869 7870 reg = TXLP_PORT_LP_MODE_CONTROLr; 7871 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7872 BCM_IF_ERROR_RETURN( 7873 READ_TXLP_PORT_LP_MODE_CONTROLr(unit, port, ®val)); 7874 if (soc_reg_field_get(unit, reg, regval, PENULTIMATE_MODEf)) { 7875 linkphy_config->action_mask |= 7876 BCM_SUBPORT_LINKPHY_TX_PENULTIMATE_MODE; 7877 } 7878 } 7879 7880 return rv; 7881 } 7882 7883 /** 7884 * Function: 7885 * bcm_kt2_subport_group_linkphy_config_set 7886 * Purpose: 7887 * Set ALL or selective LinkPHY configuration attributes 7888 * on a given port GPORT. 7889 * Parameters: 7890 * uint (IN) BCM device number 7891 * port (IN) port GPORT 7892 * linkphy_cfg (IN) LinkPHY configuration 7893 * Returns: 7894 * BCM_E_xxx 7895 * Notes: 7896 * The 'linkphy_config.action_mask' field is used to indicate if ALL or 7897 * selective attributes will be set or get. 7898 * While setting or restoring LinkPHY port configuration, if the call 7899 * returns an error then the port state is undefined. 7900 * Each field in linkphy_config structure has a corresponding mask bit 7901 * to set that value during the execution of this functions. 7902 * The OR of all BCM_SUBPORT_LINKPHY_xxx masks 7903 * should be stored in the linkphy_config.action_mask field. 7904 * The 'linkphy_config.base_stream_id' member should be a multiple 7905 * of 8 and <=896 for bcm5645x device. 7906 * LinkPHY fragment headers with stream ID range 7907 * {base_stream_id, base_stream_id+127} are valid for the gport. 7908 * Fragments with stream id outside this range will be dropped. 7909 * It is recommended to configure the 'base_stream_id' first 7910 * on a given port before adding LinkPHY subports to the port 7911 * using bcm_subport_port_add() API. 7912 * The 'linkphy_config.rx_check_flags' member is used to enable LinkPHY 7913 * fragment header parameter checks on received fragments. 7914 */ 7915 7916 int 7917 bcm_kt2_subport_group_linkphy_config_set(int unit, 7918 bcm_gport_t port, 7919 bcm_subport_group_linkphy_config_t *linkphy_config) 7920 { 7921 int rv = BCM_E_NONE; 7922 uint32 mask = 0, regval = 0, rx_check_flags = 0; 7923 uint64 rval64, data; 7924 uint16 base_stream_id = 0; 7925 soc_reg_t reg; 7926 int base_stream_id_max = 0; 7927 soc_info_t *si = &SOC_INFO(unit); 7928 int max_streams = si->lp_streams_per_slice_max; 7929 7930 COMPILER_64_ZERO(rval64); 7931 COMPILER_64_ZERO(data); 7932 7933 if (!soc_feature(unit, soc_feature_linkphy_coe)) { 7934 return BCM_E_UNAVAIL; 7935 } 7936 7937 if (!BCM_PBMP_MEMBER(si->linkphy_pbm, port)) { 7938 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7939 (BSL_META_U(unit, 7940 "ERROR: Invalid port %d for LinkPHY config set\n"), 7941 port)); 7942 return BCM_E_PORT; 7943 } 7944 7945 mask = linkphy_config->action_mask; 7946 7947 if (mask & BCM_SUBPORT_LINKPHY_BASE_STREAM_ID) { 7948 base_stream_id = linkphy_config->base_stream_id; 7949 7950 base_stream_id_max = _BCM_KT2_LINKPHY_STREAMS_MAX - 7951 max_streams; 7952 7953 if ((base_stream_id % 8) || (base_stream_id > base_stream_id_max)) { 7954 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7955 (BSL_META_U(unit, 7956 "ERROR:base stream id should be " 7957 "multiple of 8 and <= %d\n"), base_stream_id_max)); 7958 return BCM_E_PARAM; 7959 } 7960 7961 reg = RXLP_PORT_STREAM_ID_BASEr; 7962 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7963 regval = 0; 7964 BCM_IF_ERROR_RETURN( 7965 READ_RXLP_PORT_STREAM_ID_BASEr(unit, port, ®val)); 7966 soc_reg_field_set(unit, reg, ®val, BASEf, base_stream_id); 7967 BCM_IF_ERROR_RETURN( 7968 WRITE_RXLP_PORT_STREAM_ID_BASEr(unit, port, regval)); 7969 } 7970 7971 /* Write DFC MSG START OFFSET based on external stream ID base */ 7972 reg = RXLP_DFC_MSG_START_BYTE_OFFSETr; 7973 if (SOC_REG_PORT_VALID(unit, reg, port)) { 7974 regval = 0; 7975 BCM_IF_ERROR_RETURN( 7976 READ_RXLP_DFC_MSG_START_BYTE_OFFSETr(unit, port, ®val)); 7977 /* Byte offset. For example, if external stream id base is say 40, 7978 40th bit should be the offset. Since it is provided in bytes, 7979 40/8 will be equal to 5 bytes. */ 7980 soc_reg_field_set(unit, reg, ®val, OFFSETf, (base_stream_id/8)); 7981 BCM_IF_ERROR_RETURN( 7982 WRITE_RXLP_DFC_MSG_START_BYTE_OFFSETr(unit, port, regval)); 7983 } 7984 } 7985 7986 if (mask & BCM_SUBPORT_LINKPHY_HEADER_MODE) { 7987 if ((linkphy_config->header_mode != 7988 bcmSubportLinkphyHeaderModeEthAdapt) && 7989 (linkphy_config->header_mode != 7990 bcmSubportLinkphyHeaderModeTciLength)){ 7991 LOG_ERROR(BSL_LS_BCM_SUBPORT, 7992 (BSL_META_U(unit, 7993 "ERROR: invalid LinkPHY header mode %d\n"), 7994 linkphy_config->header_mode)); 7995 return BCM_E_PARAM; 7996 } 7997 #ifdef BCM_KATANA2_SUPPORT 7998 if (SOC_IS_KATANA2(unit) && 7999 (linkphy_config->header_mode == 8000 bcmSubportLinkphyHeaderModeTciLength)){ 8001 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8002 (BSL_META_U(unit, 8003 "ERROR: LinkPHY TCI+Length header mode is not supported.\n"))); 8004 return BCM_E_PARAM; 8005 } 8006 #endif 8007 8008 reg = RXLP_PORT_LP_MODE_CONTROLr; 8009 if (SOC_REG_PORT_VALID(unit, reg, port)) { 8010 regval = 0; 8011 BCM_IF_ERROR_RETURN( 8012 READ_RXLP_PORT_LP_MODE_CONTROLr(unit, port, ®val)); 8013 soc_reg_field_set(unit, reg, ®val, 8014 HEADER_MODEf, linkphy_config->header_mode); 8015 BCM_IF_ERROR_RETURN( 8016 WRITE_RXLP_PORT_LP_MODE_CONTROLr(unit, port, regval)); 8017 } 8018 } 8019 8020 if (mask & BCM_SUBPORT_LINKPHY_RX_CHECK_FLAGS) { 8021 rx_check_flags = linkphy_config->rx_check_flags; 8022 8023 reg = RXLP_PORT_NEAR_END_MAC_ADDRr; 8024 COMPILER_64_ZERO(rval64); 8025 BCM_IF_ERROR_RETURN( 8026 READ_RXLP_PORT_NEAR_END_MAC_ADDRr(unit, port, &rval64)); 8027 COMPILER_64_ZERO(data); 8028 COMPILER_64_SET(data, 0, 8029 ((rx_check_flags & BCM_SUBPORT_LINKPHY_RX_NEAREND_MAC_CHECK) ? 1: 0)); 8030 soc_reg64_field_set(unit, reg, &rval64, CHECK_ENABLEf, data); 8031 BCM_IF_ERROR_RETURN( 8032 WRITE_RXLP_PORT_NEAR_END_MAC_ADDRr(unit, port, rval64)); 8033 8034 reg = RXLP_PORT_FAR_END_MAC_ADDRr; 8035 COMPILER_64_ZERO(rval64); 8036 BCM_IF_ERROR_RETURN( 8037 READ_RXLP_PORT_FAR_END_MAC_ADDRr(unit, port, &rval64)); 8038 COMPILER_64_ZERO(data); 8039 COMPILER_64_SET(data, 0, 8040 ((rx_check_flags & BCM_SUBPORT_LINKPHY_RX_FAREND_MAC_CHECK) ? 1: 0)); 8041 soc_reg64_field_set(unit, reg, &rval64, CHECK_ENABLEf, data); 8042 BCM_IF_ERROR_RETURN( 8043 WRITE_RXLP_PORT_FAR_END_MAC_ADDRr(unit, port, rval64)); 8044 8045 reg = RXLP_PORT_DFC_DESTINATION_MAC_ADDRr; 8046 COMPILER_64_ZERO(rval64); 8047 BCM_IF_ERROR_RETURN( 8048 READ_RXLP_PORT_DFC_DESTINATION_MAC_ADDRr(unit, port, &rval64)); 8049 COMPILER_64_ZERO(data); 8050 COMPILER_64_SET(data, 0, ((rx_check_flags & 8051 BCM_SUBPORT_LINKPHY_RX_DFC_DEST_MAC_CHECK) ? 1: 0)); 8052 soc_reg64_field_set(unit, reg, &rval64, CHECK_ENABLEf, data); 8053 BCM_IF_ERROR_RETURN( 8054 WRITE_RXLP_PORT_DFC_DESTINATION_MAC_ADDRr(unit, port, rval64)); 8055 8056 reg = RXLP_PORT_DFC_OPCODEr; 8057 regval = 0; 8058 BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_OPCODEr(unit, port, ®val)); 8059 soc_reg_field_set(unit, reg, ®val, CHECK_ENABLEf, 8060 (rx_check_flags & BCM_SUBPORT_LINKPHY_RX_DFC_OPCODE_CHECK) ? 1 : 0); 8061 BCM_IF_ERROR_RETURN(WRITE_RXLP_PORT_DFC_OPCODEr(unit, port, regval)); 8062 8063 reg = RXLP_PORT_DFC_TIMEr; 8064 regval = 0; 8065 BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_TIMEr(unit, port, ®val)); 8066 soc_reg_field_set(unit, reg, ®val, CHECK_ENABLEf, 8067 (rx_check_flags & BCM_SUBPORT_LINKPHY_RX_DFC_TIME_CHECK) ? 1 : 0); 8068 BCM_IF_ERROR_RETURN(WRITE_RXLP_PORT_DFC_TIMEr(unit, port, regval)); 8069 } 8070 8071 if (mask & BCM_SUBPORT_LINKPHY_RX_VLAN_TPID) { 8072 reg = RXLP_PORT_VLAN_TPIDr; 8073 if (SOC_REG_PORT_VALID(unit, reg, port)) { 8074 regval = 0; 8075 BCM_IF_ERROR_RETURN(READ_RXLP_PORT_VLAN_TPIDr(unit, port, ®val)); 8076 soc_reg_field_set(unit, reg, ®val, VLAN_TPIDf, 8077 linkphy_config->rx_vlan_tpid); 8078 BCM_IF_ERROR_RETURN(WRITE_RXLP_PORT_VLAN_TPIDr(unit, port, regval)); 8079 } 8080 } 8081 8082 if (mask & BCM_SUBPORT_LINKPHY_RX_NEAREND_MAC) { 8083 rv = _bcm_linkphy_reg_mac_addr_set(unit, port, 8084 RXLP_PORT_NEAR_END_MAC_ADDRr, MAC_ADDRf, 8085 linkphy_config->rx_nearend_mac); 8086 if (BCM_FAILURE(rv)) { 8087 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8088 (BSL_META_U(unit, 8089 "ERROR: LinkPHY RX nearend MAC set failed\n"))); 8090 return rv; 8091 } 8092 } 8093 8094 if (mask & BCM_SUBPORT_LINKPHY_RX_FAREND_MAC) { 8095 rv = _bcm_linkphy_reg_mac_addr_set(unit, port, 8096 RXLP_PORT_FAR_END_MAC_ADDRr, MAC_ADDRf, 8097 linkphy_config->rx_farend_mac); 8098 if (BCM_FAILURE(rv)) { 8099 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8100 (BSL_META_U(unit, 8101 "ERROR: LinkPHY RX farend MAC set failed\n"))); 8102 return rv; 8103 } 8104 } 8105 8106 if (mask & BCM_SUBPORT_LINKPHY_RX_DFC_DEST_MAC) { 8107 rv = _bcm_linkphy_reg_mac_addr_set(unit, port, 8108 RXLP_PORT_DFC_DESTINATION_MAC_ADDRr, MAC_ADDRf, 8109 linkphy_config->rx_dfc_dest_mac); 8110 if (BCM_FAILURE(rv)) { 8111 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8112 (BSL_META_U(unit, 8113 "ERROR: LinkPHY RX DFC dest MAC set failed\n"))); 8114 return rv; 8115 } 8116 } 8117 8118 if (mask & BCM_SUBPORT_LINKPHY_RX_DFC_OPCODE) { 8119 reg = RXLP_PORT_DFC_OPCODEr; 8120 if (SOC_REG_PORT_VALID(unit, reg, port)) { 8121 regval = 0; 8122 BCM_IF_ERROR_RETURN( 8123 READ_RXLP_PORT_DFC_OPCODEr(unit, port, ®val)); 8124 soc_reg_field_set(unit, reg, ®val, OPCODEf, 8125 linkphy_config->rx_dfc_opcode); 8126 BCM_IF_ERROR_RETURN( 8127 WRITE_RXLP_PORT_DFC_OPCODEr(unit, port, regval)); 8128 } 8129 } 8130 8131 if (mask & BCM_SUBPORT_LINKPHY_RX_DFC_TIME) { 8132 reg = RXLP_PORT_DFC_TIMEr; 8133 if (SOC_REG_PORT_VALID(unit, reg, port)) { 8134 regval = 0; 8135 BCM_IF_ERROR_RETURN(READ_RXLP_PORT_DFC_TIMEr(unit, port, ®val)); 8136 soc_reg_field_set(unit, reg, ®val, DFC_TIMEf, 8137 linkphy_config->rx_dfc_time); 8138 BCM_IF_ERROR_RETURN(WRITE_RXLP_PORT_DFC_TIMEr(unit, port, regval)); 8139 } 8140 } 8141 8142 if (mask & BCM_SUBPORT_LINKPHY_RX_DFC_MAC_TYPE) { 8143 reg = RXLP_PORT_DFC_MAC_TYPEr; 8144 if (SOC_REG_PORT_VALID(unit, reg, port)) { 8145 regval = 0; 8146 BCM_IF_ERROR_RETURN( 8147 READ_RXLP_PORT_DFC_MAC_TYPEr(unit, port, ®val)); 8148 soc_reg_field_set(unit, reg, ®val, MAC_TYPEf, 8149 linkphy_config->rx_dfc_mac_type); 8150 BCM_IF_ERROR_RETURN( 8151 WRITE_RXLP_PORT_DFC_MAC_TYPEr(unit, port, regval)); 8152 } 8153 } 8154 8155 if (mask & BCM_SUBPORT_LINKPHY_TX_VLAN_TPID) { 8156 reg = TXLP_PORT_VLAN_TPIDr; 8157 if (SOC_REG_PORT_VALID(unit, reg, port)) { 8158 regval = 0; 8159 BCM_IF_ERROR_RETURN( 8160 READ_TXLP_PORT_VLAN_TPIDr(unit, port, ®val)); 8161 soc_reg_field_set(unit, reg, ®val, VLAN_TPIDf, 8162 linkphy_config->tx_vlan_tpid); 8163 BCM_IF_ERROR_RETURN( 8164 WRITE_TXLP_PORT_VLAN_TPIDr(unit, port, regval)); 8165 } 8166 } 8167 8168 if (mask & BCM_SUBPORT_LINKPHY_TX_NEAREND_MAC) { 8169 rv = _bcm_linkphy_reg_mac_addr_set(unit, port, 8170 TXLP_PORT_NEAR_END_MAC_ADDRr, MAC_ADDRf, 8171 linkphy_config->tx_nearend_mac); 8172 if (BCM_FAILURE(rv)) { 8173 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8174 (BSL_META_U(unit, 8175 "ERROR: LinkPHY TX nearend MAC set failed\n"))); 8176 return rv; 8177 } 8178 } 8179 8180 if (mask & BCM_SUBPORT_LINKPHY_TX_FAREND_MAC) { 8181 rv = _bcm_linkphy_reg_mac_addr_set(unit, port, 8182 TXLP_PORT_FAR_END_MAC_ADDRr, MAC_ADDRf, 8183 linkphy_config->tx_farend_mac); 8184 if (BCM_FAILURE(rv)) { 8185 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8186 (BSL_META_U(unit, 8187 "ERROR: LinkPHY TX farend MAC set failed\n"))); 8188 return rv; 8189 } 8190 } 8191 8192 reg = TXLP_PORT_LP_MODE_CONTROLr; 8193 if (SOC_REG_PORT_VALID(unit, reg, port)) { 8194 regval = 0; 8195 BCM_IF_ERROR_RETURN( 8196 READ_TXLP_PORT_LP_MODE_CONTROLr(unit, port, ®val)); 8197 soc_reg_field_set(unit, reg, ®val, PENULTIMATE_MODEf, 8198 (mask & BCM_SUBPORT_LINKPHY_TX_PENULTIMATE_MODE) ? 1 : 0); 8199 BCM_IF_ERROR_RETURN( 8200 WRITE_TXLP_PORT_LP_MODE_CONTROLr(unit, port, regval)); 8201 } 8202 8203 /* 8204 * If DFC dest mac is 0x0180c2000001 and DFC Mac Type is 0x8808 8205 * the enable RX_PASS_PAUSE in XMAC_PAUSE_CTR to enable 8206 * DFC frames to bypass the MAC. 8207 * On Saber2 enable PASS_PAUSE_FRAME in XPORT_CONFIG to enable 8208 * DFC frames to bypass the MAC. 8209 */ 8210 if ((mask & BCM_SUBPORT_LINKPHY_RX_DFC_MAC_TYPE) && 8211 (mask & BCM_SUBPORT_LINKPHY_RX_DFC_DEST_MAC)) { 8212 if ((linkphy_config->rx_dfc_mac_type == 0x8808) && 8213 (sal_strncmp((char *)linkphy_config->rx_dfc_dest_mac, 8214 "01:80:c2:00:00:01", 8215 sal_strlen((char *)linkphy_config->rx_dfc_dest_mac)))) { 8216 #if defined(BCM_SABER2_SUPPORT) 8217 if (SOC_IS_SABER2(unit)) { 8218 reg = XPORT_CONFIGr; 8219 if (SOC_REG_PORT_VALID(unit, reg, port)) { 8220 uint32 rval; 8221 8222 SOC_IF_ERROR_RETURN(READ_XPORT_CONFIGr(unit, port, &rval)); 8223 soc_reg_field_set(unit, reg, &rval, PASS_PAUSE_FRAMEf, 1); 8224 SOC_IF_ERROR_RETURN(WRITE_XPORT_CONFIGr(unit, port, rval)); 8225 } 8226 8227 } else 8228 #endif 8229 { 8230 reg = XMAC_PAUSE_CTRLr; 8231 if (SOC_REG_PORT_VALID(unit, reg, port)) { 8232 uint64 rval; 8233 8234 SOC_IF_ERROR_RETURN(READ_XMAC_PAUSE_CTRLr(unit, port, &rval)); 8235 soc_reg64_field32_set(unit, reg, &rval, RX_PASS_PAUSEf, 1); 8236 SOC_IF_ERROR_RETURN(WRITE_XMAC_PAUSE_CTRLr(unit, port, rval)); 8237 } 8238 } 8239 } 8240 } 8241 8242 return rv; 8243 } 8244 8245 /* 8246 * Function: 8247 * bcm_kt2_subport_counter_init 8248 * Purpose: 8249 * Initialize the subport counters 8250 * Parameters: 8251 * unit - Device Number 8252 * Returns: 8253 * BCM_E_XXX 8254 */ 8255 int 8256 bcm_kt2_subport_counter_init(int unit) 8257 { 8258 int rv = BCM_E_NONE; 8259 if (soc_feature(unit, soc_feature_linkphy_coe)) { 8260 rv = _bcm_linkphy_subport_counter_init(unit); 8261 if (SOC_FAILURE(rv)) { 8262 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8263 (BSL_META_U(unit, 8264 "ERROR: subport counter init failed\n"))); 8265 return rv; 8266 } 8267 } 8268 if (soc_feature(unit, soc_feature_subtag_coe)) { 8269 8270 } 8271 return rv; 8272 } 8273 8274 /* 8275 * Function: 8276 * bcm_kt2_subport_counter_cleanup 8277 * Purpose: 8278 * cleanup the subport counters 8279 * Parameters: 8280 * unit - Device Number 8281 * Returns: 8282 * BCM_E_XXX 8283 */ 8284 int 8285 bcm_kt2_subport_counter_cleanup(int unit) 8286 { 8287 int rv = BCM_E_NONE; 8288 if (soc_feature(unit, soc_feature_linkphy_coe)) { 8289 rv = _bcm_linkphy_subport_counter_cleanup(unit); 8290 if (SOC_FAILURE(rv)) { 8291 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8292 (BSL_META_U(unit, 8293 "ERROR: subport counter cleanup failed\n"))); 8294 return rv; 8295 } 8296 } 8297 if (soc_feature(unit, soc_feature_subtag_coe)) { 8298 8299 } 8300 return rv; 8301 } 8302 8303 /* 8304 * Function: 8305 * bcm_kt2_subport_port_stat_set 8306 * Purpose: 8307 * Set the statistics value for a given subport port and statistics type 8308 * Parameters: 8309 * unit - (IN) Device Number 8310 * port - (IN) subport port 8311 * stream_id - (IN) stream ID array index (if LinkPHY subport) 8312 * stat_type - (IN) statistics type 8313 * val - (IN) value 8314 * Returns: 8315 * BCM_E_XXX 8316 */ 8317 int 8318 bcm_kt2_subport_port_stat_set( 8319 int unit, 8320 bcm_gport_t port, 8321 int stream_id, 8322 bcm_subport_stat_t stat_type, 8323 uint64 val) 8324 { 8325 int rv = BCM_E_NONE; 8326 8327 /* Parameter validation */ 8328 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 8329 8330 if (!BCM_GPORT_IS_SUBPORT_PORT(port)) { 8331 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8332 (BSL_META_U(unit, 8333 "ERROR: gport 0x%x is not subport port gport\n"), 8334 port)); 8335 return BCM_E_PARAM; 8336 } 8337 8338 if (soc_feature(unit, soc_feature_linkphy_coe) && 8339 _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, port)) { 8340 _BCM_KT2_SUBPORT_LOCK(unit); 8341 rv = _bcm_linkphy_subport_port_stat_set(unit, 8342 port, stream_id, stat_type, val); 8343 if (SOC_FAILURE(rv)) { 8344 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8345 (BSL_META_U(unit, 8346 "ERROR: Subport 0x%x stat set failed. rv = %d(%s)\n"), 8347 port, rv, soc_errmsg(rv))); 8348 _BCM_KT2_SUBPORT_UNLOCK(unit); 8349 return rv; 8350 } 8351 _BCM_KT2_SUBPORT_UNLOCK(unit); 8352 } else { 8353 rv = BCM_E_UNAVAIL; 8354 } 8355 8356 return rv; 8357 8358 } 8359 8360 /* 8361 * Function: 8362 * bcm_kt2_subport_port_stat_get 8363 * Purpose: 8364 * Get the statistics value for a given subport port and statistics type 8365 * Parameters: 8366 * unit - (IN) Device Number 8367 * port - (IN) subport port 8368 * stream_id - (IN) stream ID array index (if LinkPHY subport) 8369 * stat_type - (IN) statistics type 8370 * val - (OUT) value 8371 * Returns: 8372 * BCM_E_XXX 8373 */ 8374 int 8375 bcm_kt2_subport_port_stat_get( 8376 int unit, 8377 bcm_gport_t port, 8378 int stream_id, 8379 bcm_subport_stat_t stat_type, 8380 uint64 *val) 8381 { 8382 int rv = BCM_E_NONE; 8383 8384 /* Parameter validation */ 8385 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 8386 8387 if (!BCM_GPORT_IS_SUBPORT_PORT(port)) { 8388 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8389 (BSL_META_U(unit, 8390 "ERROR: gport 0x%x is not subport port gport\n"), 8391 port)); 8392 return BCM_E_PARAM; 8393 } 8394 8395 if (soc_feature(unit, soc_feature_linkphy_coe) && 8396 _BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, port)) { 8397 8398 _BCM_KT2_SUBPORT_LOCK(unit); 8399 8400 rv = _bcm_linkphy_subport_port_stat_get(unit, 8401 port, stream_id, stat_type, val); 8402 if (SOC_FAILURE(rv)) { 8403 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8404 (BSL_META_U(unit, 8405 "ERROR: Subport 0x%x stat get failed. rv = %d(%s)\n"), 8406 port, rv, soc_errmsg(rv))); 8407 _BCM_KT2_SUBPORT_UNLOCK(unit); 8408 return rv; 8409 } 8410 _BCM_KT2_SUBPORT_UNLOCK(unit); 8411 } else { 8412 rv = BCM_E_UNAVAIL; 8413 } 8414 8415 return rv; 8416 8417 } 8418 8419 /* 8420 * Function: 8421 * bcm_kt2_subport_egr_subtag_dot1p_map_add 8422 * Purpose: 8423 * Map the egress SubTag CoE packet's PHB (internal priority and color) 8424 * to subport tag's Priority Code Point(PCP) and Drop Eligible(DE). 8425 * Parameters: 8426 * unit - (IN) Device Number 8427 * map - (IN) qos map 8428 * Returns: 8429 * BCM_E_XXX 8430 */ 8431 int 8432 bcm_kt2_subport_egr_subtag_dot1p_map_add(int unit, 8433 bcm_qos_map_t *map) 8434 { 8435 soc_mem_t mem; 8436 int index; 8437 egr_subport_tag_dot1p_map_entry_t egr_subtag_dot1p_map; 8438 8439 mem = EGR_SUBPORT_TAG_DOT1P_MAPm; 8440 8441 if (!soc_feature(unit, soc_feature_subtag_coe)) { 8442 return BCM_E_UNAVAIL; 8443 } 8444 8445 if (map->etag_pcp > 7 || 8446 map->etag_de > 1 || 8447 map->int_pri < 0 || map->int_pri > 15 || 8448 ((map->color != bcmColorGreen) && 8449 (map->color != bcmColorYellow) && 8450 (map->color != bcmColorRed))) { 8451 return BCM_E_PARAM; 8452 } 8453 8454 /* EGR_SUBPORT_TAG_DOT1P_MAPm table is indexed with 8455 * internal priority - 4 bits [5:2] and color - 2 bits[1:0] 8456 */ 8457 index = ((map->int_pri << 2) | map->color) & soc_mem_index_max(unit, mem); 8458 8459 sal_memset(&egr_subtag_dot1p_map, 0, sizeof(egr_subtag_dot1p_map)); 8460 soc_mem_field32_set(unit, mem, &egr_subtag_dot1p_map, SUBPORT_TAG_PCPf, 8461 map->etag_pcp); 8462 soc_mem_field32_set(unit, mem, &egr_subtag_dot1p_map, SUBPORT_TAG_DEf, 8463 map->etag_de); 8464 SOC_IF_ERROR_RETURN(WRITE_EGR_SUBPORT_TAG_DOT1P_MAPm(unit, 8465 MEM_BLOCK_ALL, index, &egr_subtag_dot1p_map)); 8466 return BCM_E_NONE; 8467 } 8468 8469 /* 8470 * Function: 8471 * bcm_kt2_subport_egr_subtag_dot1p_map_delete 8472 * Purpose: 8473 * Delete the map the egress SubTag CoE packet's 8474 * PHB (internal priority and color) 8475 * to subport tag's Priority Code Point(PCP) and Drop Eligible(DE). 8476 * Parameters: 8477 * unit - (IN) Device Number 8478 * map - (IN) qos map 8479 * Returns: 8480 * BCM_E_XXX 8481 */ 8482 int 8483 bcm_kt2_subport_egr_subtag_dot1p_map_delete(int unit, 8484 bcm_qos_map_t *map) 8485 { 8486 soc_mem_t mem; 8487 int index; 8488 egr_subport_tag_dot1p_map_entry_t egr_subtag_dot1p_map; 8489 8490 mem = EGR_SUBPORT_TAG_DOT1P_MAPm; 8491 8492 if (!soc_feature(unit, soc_feature_subtag_coe)) { 8493 return BCM_E_UNAVAIL; 8494 } 8495 8496 if (map->etag_pcp > 7 || 8497 map->etag_de > 1 || 8498 map->int_pri < 0 || map->int_pri > 15 || 8499 ((map->color != bcmColorGreen) && 8500 (map->color != bcmColorYellow) && 8501 (map->color != bcmColorRed))) { 8502 return BCM_E_PARAM; 8503 } 8504 8505 /* EGR_SUBPORT_TAG_DOT1P_MAPm table is indexed with 8506 * internal priority - 4 bits [5:2] and color - 2 bits[1:0] 8507 */ 8508 index = ((map->int_pri << 2) | map->color) & soc_mem_index_max(unit, mem); 8509 8510 sal_memset(&egr_subtag_dot1p_map, 0, sizeof(egr_subtag_dot1p_map)); 8511 soc_mem_field32_set(unit, mem, &egr_subtag_dot1p_map, SUBPORT_TAG_PCPf, 0); 8512 soc_mem_field32_set(unit, mem, &egr_subtag_dot1p_map, SUBPORT_TAG_DEf, 0); 8513 SOC_IF_ERROR_RETURN(WRITE_EGR_SUBPORT_TAG_DOT1P_MAPm(unit, 8514 MEM_BLOCK_ALL, index, &egr_subtag_dot1p_map)); 8515 return BCM_E_NONE; 8516 } 8517 8518 /* 8519 * Function: 8520 * bcm_kt2_subport_subtag_port_tpid_set 8521 * Description: 8522 * Set the default Tag Protocol ID for a SubTag port. 8523 * Parameters: 8524 * unit - (IN) Device number 8525 * gport - (IN) SubTag group gport 8526 * tpid - (IN) Tag Protocol ID 8527 * Return Value: 8528 * BCM_E_XXX 8529 */ 8530 8531 int 8532 bcm_kt2_subport_subtag_port_tpid_set(int unit, 8533 bcm_gport_t gport, 8534 uint16 tpid) 8535 { 8536 int rv = BCM_E_UNAVAIL; 8537 bcm_port_t port; 8538 soc_mem_t mem; 8539 ing_physical_port_table_entry_t ing_physical_port_entry; 8540 egr_physical_port_entry_t egr_physical_port_entry; 8541 8542 if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(gport)) { 8543 port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(gport); 8544 8545 mem = ING_PHYSICAL_PORT_TABLEm; 8546 if (port > soc_mem_index_max(unit, mem)) { 8547 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8548 (BSL_META_U(unit, 8549 "ERROR: Invalid port %d in subport group 0x%x\n"), 8550 port, gport)); 8551 } 8552 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port, 8553 &ing_physical_port_entry); 8554 if (SOC_FAILURE(rv)) { 8555 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8556 (BSL_META_U(unit, 8557 "ERROR:ING_PHYSICAL_PORT_TABLEm read failed\n"))); 8558 return rv; 8559 } 8560 if (soc_mem_field32_get(unit, mem, &ing_physical_port_entry, 8561 CASCADED_PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED_SUBTAG) { 8562 rv = soc_mem_field32_modify(unit, mem , port, SUBPORT_TAG_TPIDf, 8563 tpid); 8564 if (SOC_FAILURE(rv)) { 8565 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8566 (BSL_META_U(unit, 8567 "ERROR: SubTag TPID setting failed for port %d\n"), 8568 port)); 8569 return rv; 8570 } 8571 } else { 8572 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8573 (BSL_META_U(unit, 8574 "ERROR: Port %d is not SubTag Cascaded\n"), 8575 port)); 8576 return BCM_E_PORT; 8577 } 8578 mem = EGR_PHYSICAL_PORTm; 8579 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port, 8580 &egr_physical_port_entry); 8581 if (SOC_FAILURE(rv)) { 8582 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8583 (BSL_META_U(unit, 8584 "ERROR:EGR_PHYSICAL_PORTm read failed\n"))); 8585 return rv; 8586 } 8587 rv = soc_mem_field32_modify(unit, mem , port, SUBPORT_TAG_TPIDf, tpid); 8588 if (SOC_FAILURE(rv)) { 8589 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8590 (BSL_META_U(unit, 8591 "ERROR: SubTag TPID setting failed for egr_port %d\n"), 8592 port)); 8593 return rv; 8594 } 8595 } else { 8596 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8597 (BSL_META_U(unit, 8598 "ERROR: Invalid gport 0x%x for SubTag TPID set\n"), 8599 gport)); 8600 return BCM_E_PARAM; 8601 } 8602 return BCM_E_NONE; 8603 } 8604 8605 /* 8606 * Function: 8607 * bcm_kt2_subport_subtag_port_tpid_get 8608 * Description: 8609 * Retrieve the default Tag Protocol ID for a SubTag port. 8610 * Parameters: 8611 * unit - (IN) Device number 8612 * gport - (IN)SubTag group gport 8613 * tpid - (OUT) Tag Protocol ID 8614 * Return Value: 8615 * BCM_E_XXX 8616 */ 8617 8618 int 8619 bcm_kt2_subport_subtag_port_tpid_get(int unit, 8620 bcm_gport_t gport, 8621 uint16 *tpid) 8622 { 8623 int rv = BCM_E_UNAVAIL; 8624 bcm_port_t port; 8625 soc_mem_t mem; 8626 ing_physical_port_table_entry_t ing_physical_port_entry; 8627 8628 if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(gport)) { 8629 port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(gport); 8630 8631 mem = ING_PHYSICAL_PORT_TABLEm; 8632 if (port > soc_mem_index_max(unit, mem)) { 8633 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8634 (BSL_META_U(unit, 8635 "ERROR: Invalid port %d in subport group 0x%x\n"), 8636 port, gport)); 8637 } 8638 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port, 8639 &ing_physical_port_entry); 8640 if (SOC_FAILURE(rv)) { 8641 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8642 (BSL_META_U(unit, 8643 "ERROR:ING_PHYSICAL_PORT_TABLEm read failed\n"))); 8644 return rv; 8645 } 8646 if (soc_mem_field32_get(unit, mem, &ing_physical_port_entry, 8647 CASCADED_PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED_SUBTAG) { 8648 *tpid = soc_mem_field32_get(unit, mem, &ing_physical_port_entry, 8649 SUBPORT_TAG_TPIDf); 8650 } else { 8651 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8652 (BSL_META_U(unit, 8653 "ERROR: Port %d is not SubTag Cascaded\n"), 8654 port)); 8655 return BCM_E_PORT; 8656 } 8657 } else { 8658 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8659 (BSL_META_U(unit, 8660 "ERROR: Invalid gport 0x%x for SubTag TPID set\n"), 8661 gport)); 8662 return BCM_E_PARAM; 8663 } 8664 return BCM_E_NONE; 8665 } 8666 8667 8668 /* 8669 * Function: 8670 * bcm_kt2_subport_subtag_port_tpid_delete 8671 * Description: 8672 * Delete allowed TPID for a SubTag port. 8673 * Parameters: 8674 * unit - (IN) Device number 8675 * gport - (IN) SubTag group gport 8676 * tpid - (IN) Tag Protocol ID 8677 * Return Value: 8678 * BCM_E_XXX 8679 */ 8680 8681 int 8682 bcm_kt2_subport_subtag_port_tpid_delete(int unit, 8683 bcm_gport_t gport, 8684 uint16 tpid) 8685 { 8686 int rv = BCM_E_UNAVAIL; 8687 bcm_port_t port; 8688 soc_mem_t mem; 8689 ing_physical_port_table_entry_t ing_physical_port_entry; 8690 egr_physical_port_entry_t egr_physical_port_entry; 8691 8692 if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_GROUP(gport)) { 8693 port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(gport); 8694 8695 mem = ING_PHYSICAL_PORT_TABLEm; 8696 if (port > soc_mem_index_max(unit, mem)) { 8697 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8698 (BSL_META_U(unit, 8699 "ERROR: Invalid port %d in subport group 0x%x\n"), 8700 port, gport)); 8701 } 8702 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port, 8703 &ing_physical_port_entry); 8704 if (SOC_FAILURE(rv)) { 8705 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8706 (BSL_META_U(unit, 8707 "ERROR:ING_PHYSICAL_PORT_TABLEm read failed\n"))); 8708 return rv; 8709 } 8710 if (soc_mem_field32_get(unit, mem, &ing_physical_port_entry, 8711 CASCADED_PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED_SUBTAG) { 8712 rv = soc_mem_field32_modify(unit, mem , port, SUBPORT_TAG_TPIDf, 0); 8713 if (SOC_FAILURE(rv)) { 8714 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8715 (BSL_META_U(unit, 8716 "ERROR: SubTag TPID delete failed for port %d\n"), 8717 port)); 8718 return rv; 8719 } 8720 } else { 8721 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8722 (BSL_META_U(unit, 8723 "ERROR: Port %d is not SubTag Cascaded\n"), 8724 port)); 8725 return BCM_E_PORT; 8726 } 8727 mem = EGR_PHYSICAL_PORTm; 8728 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port, 8729 &egr_physical_port_entry); 8730 if (SOC_FAILURE(rv)) { 8731 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8732 (BSL_META_U(unit, 8733 "ERROR:EGR_PHYSICAL_PORTm read failed\n"))); 8734 return rv; 8735 } 8736 rv = soc_mem_field32_modify(unit, mem , port, SUBPORT_TAG_TPIDf, 0); 8737 if (SOC_FAILURE(rv)) { 8738 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8739 (BSL_META_U(unit, 8740 "ERROR: SubTag TPID delete failed for egr_port %d\n"), 8741 port)); 8742 return rv; 8743 } 8744 } else { 8745 LOG_ERROR(BSL_LS_BCM_SUBPORT, 8746 (BSL_META_U(unit, 8747 "ERROR: Invalid gport 0x%x for SubTag TPID set\n"), 8748 gport)); 8749 return BCM_E_PARAM; 8750 } 8751 return BCM_E_NONE; 8752 } 8753 8754 STATIC int 8755 _bcm_linkphy_subport_cb(int unit, 8756 bcm_gport_t subport_gport, 8757 bcm_subport_config_t *linkphy_config, 8758 void *user_data) 8759 { 8760 int stream_idx = 0; 8761 int rv = 0, stat = 0; 8762 uint64 val; 8763 int subport_group = -1, port = 0, done = 0; 8764 8765 char *stat_name[]= 8766 {"RxFragByte ","RxFrag ","RxFrameByte", 8767 "RxFrame ","TxFragByte ","TxFrag ", 8768 "TxFrameByte","TxFrame "}; 8769 bcm_subport_stat_t stat_type[]={ 8770 bcmSubportLinkPhyStatRxFragmentBytes, 8771 bcmSubportLinkPhyStatRxFragments, 8772 bcmSubportLinkPhyStatRxFrameBytes, 8773 bcmSubportLinkPhyStatRxFrames, 8774 bcmSubportLinkPhyStatTxFragmentBytes, 8775 bcmSubportLinkPhyStatTxFragments, 8776 bcmSubportLinkPhyStatTxFrameBytes, 8777 bcmSubportLinkPhyStatTxFrames 8778 }; 8779 8780 if (linkphy_config->num_streams > 0) { 8781 for(stream_idx = 0; 8782 stream_idx < linkphy_config->num_streams; stream_idx++) { 8783 done = 0; 8784 for(stat = 0; stat <= 7; stat++) { 8785 COMPILER_64_ZERO(val); 8786 rv = bcm_kt2_subport_port_stat_get(unit, subport_gport, 8787 stream_idx, stat_type[stat], &val); 8788 if (rv < 0) { 8789 LOG_CLI((BSL_META_U(unit, 8790 "Subport(0x%x) stat get failed\n"), 8791 subport_gport)); 8792 } else { 8793 if (!COMPILER_64_IS_ZERO(val)) { 8794 if (!done) { 8795 subport_group = _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, 8796 BCM_GPORT_SUBPORT_PORT_GET(subport_gport)); 8797 port = _BCM_KT2_SUBPORT_GROUP_PORT_GET(subport_group); 8798 LOG_CLI((BSL_META_U(unit, 8799 "\nSubport = 0x%x PP_Port = %02d " 8800 "ExtStreamId = %d Port = %s(%d)\n\n"), 8801 subport_gport, 8802 BCM_GPORT_SUBPORT_PORT_GET(subport_gport), 8803 linkphy_config->stream_id_array[stream_idx], 8804 SOC_PORT_NAME(unit, port), port)); 8805 done = 1; 8806 } 8807 if (COMPILER_64_HI(val) == 0) { 8808 LOG_CLI((BSL_META_U(unit, 8809 "\t%s %08u\n"), 8810 stat_name[stat], 8811 COMPILER_64_LO(val))); 8812 } else { 8813 LOG_CLI((BSL_META_U(unit, 8814 "\t%s 0x%08x%08x\n"), 8815 stat_name[stat], 8816 COMPILER_64_HI(val), 8817 COMPILER_64_LO(val))); 8818 } 8819 } 8820 } 8821 } 8822 } 8823 } 8824 return BCM_E_NONE; 8825 } 8826 8827 STATIC void 8828 _bcm_linkphy_ext_stream_id_port_get(int unit, 8829 int block_id, int index, int *ext_stream_id, int *port) 8830 { 8831 int copyno = 0, idx = 0, pp_port = 0; 8832 soc_mem_t mem = INVALIDm; 8833 txlp_int2ext_stream_map_table_entry_t txlp_int2ext_stream_map; 8834 device_stream_id_to_pp_port_map_entry_t dev_sid_to_pp_entry; 8835 pp_port_to_physical_port_map_entry_t pp_to_port_entry; 8836 int valid = 0; 8837 8838 8839 mem = TXLP_INT2EXT_STREAM_MAP_TABLEm; 8840 /* get the block and index for the LinkPHY memory */ 8841 sal_memset(&txlp_int2ext_stream_map, 0, 8842 sizeof(txlp_int2ext_stream_map_table_entry_t)); 8843 copyno = SOC_MEM_BLOCK_ANY(unit, mem) + block_id; 8844 (void) soc_mem_read(unit, mem, copyno, index, 8845 &txlp_int2ext_stream_map); 8846 valid = soc_mem_field32_get(unit, mem, 8847 (uint32 *)&txlp_int2ext_stream_map, 8848 VALIDf); 8849 if (!valid) { 8850 /* If not a valid internal stream id, do not 8851 * fill external stream id and port. 8852 */ 8853 return; 8854 } 8855 *ext_stream_id = soc_mem_field32_get(unit, mem, 8856 (uint32 *)&txlp_int2ext_stream_map, 8857 EXTERNAL_SIDf); 8858 8859 /* get the pp_port from dev stream id */ 8860 mem = DEVICE_STREAM_ID_TO_PP_PORT_MAPm; 8861 idx = ((block_id) ? (_BCM_KT2_LINKPHY_COUNTER_MAX(unit) + index) : index); 8862 sal_memset(&dev_sid_to_pp_entry, 0, 8863 sizeof(dev_sid_to_pp_entry)); 8864 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 8865 (void) soc_mem_read(unit, mem, copyno, idx, 8866 &dev_sid_to_pp_entry); 8867 pp_port = soc_mem_field32_get(unit, mem, 8868 (uint32 *)&dev_sid_to_pp_entry, 8869 PP_PORTf); 8870 8871 /* get the port id from pp_port */ 8872 mem = PP_PORT_TO_PHYSICAL_PORT_MAPm; 8873 sal_memset(&pp_to_port_entry, 0, 8874 sizeof(pp_to_port_entry)); 8875 copyno = SOC_MEM_BLOCK_ANY(unit, mem); 8876 (void) soc_mem_read(unit, mem, copyno, pp_port, 8877 &pp_to_port_entry); 8878 *port = soc_mem_field32_get(unit, mem, 8879 (uint32 *)&pp_to_port_entry, 8880 DESTINATIONf); 8881 return; 8882 } 8883 8884 STATIC void 8885 _bcm_kt2_linkphy_counter_show(int unit, 8886 int block_id, int index) 8887 { 8888 char *stat[] = {"RxFragByte ","RxFrag ","RxFrameByte", "RxFrame ", 8889 "TxFragByte ","TxFrag ","TxFrameByte", "TxFrame "}; 8890 int stat_type_id = 0; 8891 int direction = 0, pool_id = 0; 8892 volatile uint64 *vptr; 8893 int ext_stream_id = -1, port = -1, done = 0; 8894 8895 _bcm_linkphy_ext_stream_id_port_get(unit, block_id, index, 8896 &ext_stream_id, &port); 8897 if (ext_stream_id == -1 || port == -1) { 8898 /* Not a valid internal stream id. Return */ 8899 return; 8900 } 8901 8902 BCM_LINKPHY_COUNTER_LOCK(unit); 8903 for (direction = 0; direction < _BCM_KT2_LINKPHY_DIRECTION_MAX; 8904 direction++) { 8905 for (pool_id = 0; pool_id < _BCM_KT2_LINKPHY_POOL_MAX; pool_id++) { 8906 switch (pool_id) { 8907 case 0: 8908 vptr = &linkphy_frag_byte_ctr[unit] 8909 [direction][block_id][index]; 8910 break; 8911 case 1: 8912 vptr = &linkphy_frag_ctr[unit] 8913 [direction][block_id][index]; 8914 break; 8915 case 2: 8916 vptr = &linkphy_frame_byte_ctr[unit] 8917 [direction][block_id][index]; 8918 break; 8919 case 3: 8920 default: 8921 vptr = &linkphy_frame_ctr[unit] 8922 [direction][block_id][index]; 8923 break; 8924 } 8925 stat_type_id = 8926 (direction*_BCM_KT2_LINKPHY_POOL_MAX) + pool_id; 8927 if (!(COMPILER_64_IS_ZERO(*vptr))) { 8928 if (!done) { 8929 LOG_CLI((BSL_META_U(unit, 8930 "\nDevStreamID = %d " 8931 "ExtStreamID = %d " 8932 "Port = %s(%d) \n\n"), 8933 ((block_id) ? (_BCM_KT2_LINKPHY_COUNTER_MAX(unit) + 8934 index) : index), 8935 ext_stream_id, 8936 SOC_PORT_NAME(unit,port), 8937 port)); 8938 done = 1; 8939 } 8940 if (COMPILER_64_HI(*vptr) == 0) { 8941 LOG_CLI((BSL_META_U(unit, 8942 "\t%s %08u\n"), 8943 stat[stat_type_id], 8944 COMPILER_64_LO(*vptr))); 8945 } else { 8946 LOG_CLI((BSL_META_U(unit, 8947 "\t%s 0x%08x%08x\n"), 8948 stat[stat_type_id], 8949 COMPILER_64_HI(*vptr), 8950 COMPILER_64_LO(*vptr))); 8951 } 8952 } 8953 } 8954 } 8955 BCM_LINKPHY_COUNTER_UNLOCK(unit); 8956 return; 8957 } 8958 8959 int 8960 bcm_kt2_subport_port_stat_show(int unit, uint32 flag, int sid) 8961 { 8962 int block_id = 0, index = 0; 8963 int max_streams = SOC_INFO(unit).lp_streams_per_slice_max; 8964 int linkphy_block_max = SOC_INFO(unit).lp_block_max; 8965 8966 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 8967 8968 if(soc_feature(unit, soc_feature_linkphy_coe) && 8969 SOC_INFO(unit).linkphy_enabled) { 8970 if (flag == 0) { 8971 _bcm_linkphy_subport_port_traverse(unit, 8972 _bcm_linkphy_subport_cb, NULL); 8973 } else { /* flag == 1*/ 8974 if (sid != -1) { 8975 if (sid >= max_streams) { 8976 LOG_CLI((BSL_META_U(unit, 8977 "invalid stream ID\n"))); 8978 return BCM_E_PARAM; 8979 } else { 8980 for (block_id = 0; 8981 block_id < linkphy_block_max; block_id++) { 8982 _bcm_kt2_linkphy_counter_show(unit, block_id, sid); 8983 } 8984 } 8985 } else { 8986 for (index = 0; 8987 index < _BCM_KT2_LINKPHY_COUNTER_MAX(unit); index++) { 8988 for (block_id = 0; 8989 block_id < linkphy_block_max; block_id++) { 8990 _bcm_kt2_linkphy_counter_show(unit, block_id, index); 8991 } 8992 } 8993 } 8994 } 8995 } 8996 return BCM_E_NONE; 8997 } 8998 8999 /* 9000 * Function: 9001 * bcm_kt2_port_control_subtag_status_set 9002 * Description: 9003 * Set the SubTag status for a given port. 9004 * Parameters: 9005 * unit - (IN) Device number 9006 * port - (IN) port 9007 * value - (IN) Enable/Disable status 9008 * Return Value: 9009 * BCM_E_XXX 9010 * Note: The application need to delete all subport groups/ports, if any, 9011 * before disabling the SubTag CoE for given port. 9012 */ 9013 9014 int bcm_kt2_port_control_subtag_status_set(int unit, 9015 bcm_port_t port, int value) 9016 { 9017 int rv = BCM_E_NONE; 9018 int start = 0, end = 0; 9019 uint32 port_type, cascaded_port_type; 9020 soc_mem_t mem; 9021 soc_info_t *si = &SOC_INFO(unit); 9022 int min_subport_index = si->pp_port_index_min; 9023 ing_physical_port_table_entry_t ing_physical_port_entry; 9024 egr_physical_port_entry_t egr_physical_port_entry; 9025 9026 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 9027 9028 if (!soc_feature(unit, soc_feature_subtag_coe)) { 9029 return BCM_E_UNAVAIL; 9030 } 9031 if (!BCM_PBMP_MEMBER(si->subtag_allowed_pbm, port)) { 9032 return BCM_E_PORT; 9033 } 9034 9035 port_type = value ? _BCM_KT2_PORT_TYPE_CASCADED : 9036 _BCM_KT2_PORT_TYPE_ETHERNET; 9037 cascaded_port_type = value ? _BCM_KT2_PORT_TYPE_CASCADED_SUBTAG : 0; 9038 9039 _BCM_KT2_SUBPORT_LOCK(unit); 9040 mem = ING_PHYSICAL_PORT_TABLEm; 9041 if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) { 9042 rv = soc_mem_field32_modify( unit, mem, port, PORT_TYPEf, port_type); 9043 if (SOC_FAILURE(rv)) { 9044 _BCM_KT2_SUBPORT_UNLOCK(unit); 9045 return rv; 9046 } 9047 } 9048 if (SOC_MEM_FIELD_VALID(unit, mem, CASCADED_PORT_TYPEf)) { 9049 rv = soc_mem_field32_modify(unit, mem, port, 9050 CASCADED_PORT_TYPEf, cascaded_port_type); 9051 if (SOC_FAILURE(rv)) { 9052 _BCM_KT2_SUBPORT_UNLOCK(unit); 9053 return rv; 9054 } 9055 } 9056 9057 /* Add default TPID for the created cascaded port */ 9058 if (value) { 9059 if (SOC_MEM_FIELD_VALID(unit, mem, SUBPORT_TAG_TPIDf)) { 9060 9061 /* Lets not modify the field, if default tpid is already set */ 9062 if (soc_mem_field32_get(unit, mem, &ing_physical_port_entry, 9063 SUBPORT_TAG_TPIDf) != BCM_SUBPORT_COE_DEFAULT_ETHERTYPE) { 9064 rv = soc_mem_field32_modify(unit, mem, port, 9065 SUBPORT_TAG_TPIDf, BCM_SUBPORT_COE_DEFAULT_ETHERTYPE); 9066 if (SOC_FAILURE(rv)) { 9067 _BCM_KT2_SUBPORT_UNLOCK(unit); 9068 return rv; 9069 } 9070 } 9071 } 9072 } 9073 9074 mem = EGR_PHYSICAL_PORTm; 9075 if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) { 9076 rv = soc_mem_field32_modify(unit, mem, port, PORT_TYPEf, port_type); 9077 if (SOC_FAILURE(rv)) { 9078 _BCM_KT2_SUBPORT_UNLOCK(unit); 9079 return rv; 9080 } 9081 } 9082 if (SOC_MEM_FIELD_VALID(unit, mem, CASCADED_PORT_TYPEf)) { 9083 rv = soc_mem_field32_modify(unit, mem, port, 9084 CASCADED_PORT_TYPEf, cascaded_port_type); 9085 if (SOC_FAILURE(rv)) { 9086 _BCM_KT2_SUBPORT_UNLOCK(unit); 9087 return rv; 9088 } 9089 } 9090 9091 /* Update tpid in EGR_PHYSICAL_PORT if default tpid is not set */ 9092 if (value) { 9093 if (SOC_MEM_FIELD_VALID(unit, mem, SUBPORT_TAG_TPIDf)) { 9094 if (soc_mem_field32_get(unit, mem, &egr_physical_port_entry, 9095 SUBPORT_TAG_TPIDf) != BCM_SUBPORT_COE_DEFAULT_ETHERTYPE) { 9096 rv = soc_mem_field32_modify(unit, mem, port, 9097 SUBPORT_TAG_TPIDf, BCM_SUBPORT_COE_DEFAULT_ETHERTYPE); 9098 if (SOC_FAILURE(rv)) { 9099 _BCM_KT2_SUBPORT_UNLOCK(unit); 9100 return rv; 9101 } 9102 } 9103 } 9104 } 9105 9106 start = si->port_subport_base[port] - min_subport_index; 9107 end = start + si->port_num_subport[port] - 1; 9108 if (value) { 9109 BCM_PBMP_PORT_ADD(si->subtag_pbm, port); 9110 BCM_PBMP_PORT_ADD(si->subtag.bitmap, port); 9111 SOC_IF_ERROR_RETURN 9112 (soc_kt2_cosq_s1_range_set(unit, port, start, end, 0)); 9113 SOC_IF_ERROR_RETURN 9114 (soc_kt2_cosq_repl_map_set(unit, port, start, end, 1)); 9115 SOC_IF_ERROR_RETURN 9116 (soc_kt2_cosq_port_coe_linkphy_status_set(unit, port, 1)); 9117 } else { 9118 if (BCM_PBMP_MEMBER(si->subtag_pbm, port)) { 9119 BCM_PBMP_PORT_REMOVE(si->subtag_pbm, port); 9120 BCM_PBMP_PORT_REMOVE(si->subtag.bitmap, port); 9121 SOC_IF_ERROR_RETURN 9122 (soc_kt2_cosq_port_coe_linkphy_status_set(unit, port, 0)); 9123 SOC_IF_ERROR_RETURN 9124 (soc_kt2_cosq_s1_range_set(unit, port, 0, 0, 0)); 9125 SOC_IF_ERROR_RETURN 9126 (soc_kt2_cosq_repl_map_set(unit, port, start, end, 0)); 9127 } 9128 } 9129 _BCM_KT2_SUBPORT_UNLOCK(unit); 9130 return rv; 9131 } 9132 /* 9133 * Function: 9134 * bcm_kt2_port_control_subtag_status_get 9135 * Description: 9136 * Get the SubTag status for a given port. 9137 * Parameters: 9138 * unit - (IN) Device number 9139 * port - (IN) port 9140 * value - (OUT) Enable/Disable status 9141 * Return Value: 9142 * BCM_E_XXX 9143 */ 9144 9145 int bcm_kt2_port_control_subtag_status_get(int unit, 9146 bcm_port_t port, int *value) 9147 { 9148 int rv = BCM_E_NONE; 9149 soc_mem_t mem; 9150 soc_info_t *si = &SOC_INFO(unit); 9151 ing_physical_port_table_entry_t ing_physical_port_entry; 9152 9153 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 9154 9155 if (!soc_feature(unit, soc_feature_subtag_coe)) { 9156 return BCM_E_UNAVAIL; 9157 } 9158 if (!BCM_PBMP_MEMBER(si->subtag_allowed_pbm, port)) { 9159 return BCM_E_PORT; 9160 } 9161 9162 _BCM_KT2_SUBPORT_LOCK(unit); 9163 9164 *value = 0; 9165 mem = ING_PHYSICAL_PORT_TABLEm; 9166 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port, 9167 &ing_physical_port_entry); 9168 if (SOC_FAILURE(rv)) { 9169 LOG_ERROR(BSL_LS_BCM_SUBPORT, 9170 (BSL_META_U(unit, 9171 "ERROR:ING_PHYSICAL_PORT_TABLEm read failed\n"))); 9172 _BCM_KT2_SUBPORT_UNLOCK(unit); 9173 return rv; 9174 } 9175 if ((soc_mem_field32_get(unit, mem, &ing_physical_port_entry, 9176 CASCADED_PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED_SUBTAG) && 9177 (soc_mem_field32_get(unit, mem, &ing_physical_port_entry, 9178 PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED)) { 9179 *value = 1; 9180 } 9181 9182 _BCM_KT2_SUBPORT_UNLOCK(unit); 9183 9184 return rv; 9185 } 9186 9187 /* 9188 * Function: 9189 * bcm_kt2_port_control_linkphy_status_set 9190 * Description: 9191 * Set the LinkPHY status for a given port. 9192 * Parameters: 9193 * unit - (IN) Device number 9194 * port - (IN) port 9195 * value - (IN) Enable/Disable status 9196 * Return Value: 9197 * BCM_E_XXX 9198 * Note: The application need to delete all subport groups/ports, if any, 9199 * before disabling the LinkPHY CoE for given port. 9200 */ 9201 9202 int bcm_kt2_port_control_linkphy_status_set(int unit, 9203 bcm_port_t port, int value) 9204 { 9205 int rv = BCM_E_NONE; 9206 int start = 0, end = 0, index = 0, lp_block = 0, lp_index = 0; 9207 uint32 lp_enable, port_enable; 9208 uint32 port_type, cascaded_port_type; 9209 uint32 regval = 0; 9210 uint64 tx_ctrl, rx_ctrl; 9211 soc_reg_t reg; 9212 soc_mem_t mem; 9213 soc_info_t *si = &SOC_INFO(unit); 9214 int num_max_stream = si->lp_streams_per_subport; 9215 soc_pbmp_t pbmp_linkphy_one_stream_per_subport; 9216 9217 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 9218 9219 if (!soc_feature(unit, soc_feature_linkphy_coe)) { 9220 return BCM_E_UNAVAIL; 9221 } 9222 if (!BCM_PBMP_MEMBER(si->linkphy_allowed_pbm, port)) { 9223 return BCM_E_PORT; 9224 } 9225 port_type = value ? _BCM_KT2_PORT_TYPE_CASCADED : 9226 _BCM_KT2_PORT_TYPE_ETHERNET; 9227 cascaded_port_type = value ? _BCM_KT2_PORT_TYPE_CASCADED_LINKPHY : 0; 9228 9229 _BCM_KT2_SUBPORT_LOCK(unit); 9230 9231 /* Configures XMAC_TX_CTRL register to append CRC to the data */ 9232 if (SOC_REG_PORT_VALID(unit, XMAC_TX_CTRLr, port)) { 9233 SOC_IF_ERROR_RETURN(READ_XMAC_TX_CTRLr(unit, port, &tx_ctrl)); 9234 soc_reg64_field32_set(unit, XMAC_TX_CTRLr, &tx_ctrl, CRC_MODEf, 0x0); 9235 SOC_IF_ERROR_RETURN(WRITE_XMAC_TX_CTRLr(unit, port, tx_ctrl)); 9236 } else if (SOC_REG_PORT_VALID(unit, XLMAC_TX_CTRLr, port)) { 9237 /* For saber2 it is XLMAC */ 9238 SOC_IF_ERROR_RETURN(READ_XLMAC_TX_CTRLr(unit, port, &tx_ctrl)); 9239 soc_reg64_field32_set(unit, XLMAC_TX_CTRLr, &tx_ctrl, CRC_MODEf, 0x0); 9240 SOC_IF_ERROR_RETURN(WRITE_XLMAC_TX_CTRLr(unit, port, tx_ctrl)); 9241 } 9242 9243 if (SOC_REG_PORT_VALID(unit, XMAC_RX_CTRLr, port)) { 9244 SOC_IF_ERROR_RETURN(READ_XMAC_RX_CTRLr(unit, port, &rx_ctrl)); 9245 soc_reg64_field32_set(unit, XMAC_RX_CTRLr, &rx_ctrl, STRIP_CRCf, 1); 9246 SOC_IF_ERROR_RETURN(WRITE_XMAC_RX_CTRLr(unit, port, rx_ctrl)); 9247 } else if (SOC_REG_PORT_VALID(unit, XLMAC_RX_CTRLr, port)) { 9248 /* For saber2 it is XLMAC */ 9249 SOC_IF_ERROR_RETURN(READ_XLMAC_RX_CTRLr(unit, port, &rx_ctrl)); 9250 soc_reg64_field32_set(unit, XLMAC_RX_CTRLr, &rx_ctrl, STRIP_CRCf, 1); 9251 SOC_IF_ERROR_RETURN(WRITE_XLMAC_RX_CTRLr(unit, port, rx_ctrl)); 9252 } 9253 9254 /* 9255 * Set the RXLP/TXLP internal stream id base to 128 for 9256 * RXLP/TXLP block number 1. This is needed to support 9257 * 256 streams 9258 */ 9259 9260 rv = soc_linkphy_port_blk_idx_get(unit,port, 9261 &lp_block, &lp_index); 9262 if (SOC_FAILURE(rv)) { 9263 LOG_ERROR(BSL_LS_BCM_SUBPORT, 9264 (BSL_META_U(unit, 9265 "ERROR: LinkPHY block, index get failed for port %d\n"), port)); 9266 return rv; 9267 } 9268 9269 reg = RXLP_INT_STREAM_ID_BASEr; 9270 if (SOC_REG_PORT_VALID(unit, reg, port)) { 9271 soc_reg_field_set(unit, reg, ®val, BASEf, lp_block ? 128 : 0); 9272 BCM_IF_ERROR_RETURN( 9273 WRITE_RXLP_INT_STREAM_ID_BASEr(unit, port, regval)); 9274 } 9275 reg = TXLP_INT_STREAM_ID_BASEr; 9276 if (SOC_REG_PORT_VALID(unit, reg, port)) { 9277 soc_reg_field_set(unit, reg, ®val, BASEf, lp_block ? 128 : 0); 9278 BCM_IF_ERROR_RETURN( 9279 WRITE_TXLP_INT_STREAM_ID_BASEr(unit, port, regval)); 9280 } 9281 9282 SOC_PBMP_CLEAR(pbmp_linkphy_one_stream_per_subport); 9283 if (SOC_IS_SABER2(unit)) { 9284 pbmp_linkphy_one_stream_per_subport = 9285 soc_property_get_pbmp(unit, spn_PBMP_LINKPHY_ONE_STREAM_PER_SUBPORT, 0); 9286 } 9287 if (value) { 9288 BCM_PBMP_PORT_ADD(si->linkphy_pbm, port); 9289 BCM_PBMP_PORT_ADD(si->lp.bitmap, port); 9290 start = si->port_linkphy_s1_base[port]; 9291 end = start + 9292 si->port_num_subport[port] * 9293 (SOC_PBMP_MEMBER(pbmp_linkphy_one_stream_per_subport, port) ? 9294 1 : num_max_stream) - 1; 9295 9296 SOC_IF_ERROR_RETURN 9297 (soc_kt2_cosq_s1_range_set(unit, port, start, end, value)); 9298 SOC_IF_ERROR_RETURN 9299 (soc_kt2_cosq_port_coe_linkphy_status_set(unit, port, 1)); 9300 } else { 9301 if (BCM_PBMP_MEMBER(si->linkphy_pbm, port)) { 9302 BCM_PBMP_PORT_REMOVE(si->linkphy_pbm, port); 9303 BCM_PBMP_PORT_REMOVE(si->lp.bitmap, port); 9304 SOC_IF_ERROR_RETURN 9305 (soc_kt2_cosq_port_coe_linkphy_status_set(unit, port, 0)); 9306 SOC_IF_ERROR_RETURN 9307 (soc_kt2_cosq_s1_range_set(unit, port, 0, 0, 0)); 9308 } 9309 } 9310 9311 port_type = _BCM_KT2_PORT_TYPE_CASCADED; 9312 cascaded_port_type = _BCM_KT2_PORT_TYPE_CASCADED_LINKPHY; 9313 9314 mem = ING_PHYSICAL_PORT_TABLEm; 9315 if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) { 9316 BCM_IF_ERROR_RETURN(soc_mem_field32_modify 9317 (unit, mem, port, PORT_TYPEf, port_type)); 9318 BCM_IF_ERROR_RETURN(soc_mem_field32_modify( 9319 unit, mem, port, CASCADED_PORT_TYPEf, cascaded_port_type)); 9320 } 9321 9322 mem = EGR_PHYSICAL_PORTm; 9323 if (SOC_MEM_FIELD_VALID(unit, mem, PORT_TYPEf)) { 9324 BCM_IF_ERROR_RETURN(soc_mem_field32_modify( 9325 unit, mem, port, PORT_TYPEf, port_type)); 9326 } 9327 if (SOC_MEM_FIELD_VALID(unit, mem, CASCADED_PORT_TYPEf)) { 9328 BCM_IF_ERROR_RETURN(soc_mem_field32_modify( 9329 unit, mem, port, CASCADED_PORT_TYPEf, cascaded_port_type)); 9330 } 9331 9332 reg = RXLP_PORT_ENABLEr; 9333 if (SOC_REG_PORT_VALID(unit, reg, port)) { 9334 BCM_IF_ERROR_RETURN( 9335 READ_RXLP_PORT_ENABLEr(unit, port, ®val)); 9336 lp_enable = soc_reg_field_get(unit, reg, regval, LP_ENABLEf); 9337 9338 if (soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 9339 SOC_BLK_RXLP, NULL, &index) == SOC_E_NONE) { 9340 lp_enable |= ((1 << index) & 0xF); 9341 } 9342 9343 regval = 0; 9344 soc_reg_field_set(unit, reg, ®val, LP_ENABLEf, lp_enable); 9345 BCM_IF_ERROR_RETURN( WRITE_RXLP_PORT_ENABLEr(unit,port,regval)); 9346 } 9347 9348 reg = TXLP_PORT_ENABLEr; 9349 if (SOC_REG_PORT_VALID(unit, reg, port)) { 9350 BCM_IF_ERROR_RETURN( 9351 READ_TXLP_PORT_ENABLEr(unit, port, ®val)); 9352 lp_enable = soc_reg_field_get(unit, reg, regval, LP_ENABLEf); 9353 port_enable = soc_reg_field_get(unit, reg, regval,PORT_ENABLEf); 9354 9355 if (soc_kt2_linkphy_port_reg_blk_idx_get(unit, port, 9356 SOC_BLK_TXLP, NULL, &index) == SOC_E_NONE) { 9357 lp_enable |= ((1 << index) & 0xF); 9358 port_enable |= ((1 << index) & 0xF); 9359 } 9360 9361 regval = 0; 9362 soc_reg_field_set(unit, reg, ®val, LP_ENABLEf, lp_enable); 9363 soc_reg_field_set(unit, reg, ®val, PORT_ENABLEf,port_enable); 9364 BCM_IF_ERROR_RETURN(WRITE_TXLP_PORT_ENABLEr(unit, port,regval)); 9365 } 9366 9367 _BCM_KT2_SUBPORT_UNLOCK(unit); 9368 return rv; 9369 } 9370 /* 9371 * Function: 9372 * bcm_kt2_port_control_linkphy_status_get 9373 * Description: 9374 * Get the LinkPHY status for a given port. 9375 * Parameters: 9376 * unit - (IN) Device number 9377 * port - (IN) port 9378 * value - (OUT) Enable/Disable status 9379 * Return Value: 9380 * BCM_E_XXX 9381 */ 9382 9383 int bcm_kt2_port_control_linkphy_status_get(int unit, 9384 bcm_port_t port, int *value) 9385 { 9386 int rv = BCM_E_NONE; 9387 soc_mem_t mem; 9388 soc_info_t *si = &SOC_INFO(unit); 9389 ing_physical_port_table_entry_t ing_physical_port_entry; 9390 9391 _BCM_KT2_SUBPORT_CHECK_INIT(unit); 9392 9393 if (!soc_feature(unit, soc_feature_linkphy_coe)) { 9394 return BCM_E_UNAVAIL; 9395 } 9396 if (!BCM_PBMP_MEMBER(si->linkphy_allowed_pbm, port)) { 9397 return BCM_E_PORT; 9398 } 9399 9400 _BCM_KT2_SUBPORT_LOCK(unit); 9401 9402 *value = 0; 9403 mem = ING_PHYSICAL_PORT_TABLEm; 9404 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port, 9405 &ing_physical_port_entry); 9406 if (SOC_FAILURE(rv)) { 9407 LOG_ERROR(BSL_LS_BCM_SUBPORT, 9408 (BSL_META_U(unit, 9409 "ERROR:ING_PHYSICAL_PORT_TABLEm read failed\n"))); 9410 _BCM_KT2_SUBPORT_UNLOCK(unit); 9411 return rv; 9412 } 9413 if ((soc_mem_field32_get(unit, mem, &ing_physical_port_entry, 9414 CASCADED_PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED_LINKPHY) && 9415 (soc_mem_field32_get(unit, mem, &ing_physical_port_entry, 9416 PORT_TYPEf) == _BCM_KT2_PORT_TYPE_CASCADED)) { 9417 *value = 1; 9418 } 9419 9420 _BCM_KT2_SUBPORT_UNLOCK(unit); 9421 9422 return rv; 9423 } 9424 9425 int 9426 _bcm_kt2_modport_is_local_coe_subport(int unit, int mod, bcm_port_t port, 9427 int *is_local_subport) 9428 { 9429 int pp_port = 0; 9430 int pp_port_index_min = SOC_INFO(unit).pp_port_index_min; 9431 int pp_port_index_max = SOC_INFO(unit).pp_port_index_max; 9432 9433 *is_local_subport = 0; 9434 9435 if (soc_feature(unit, soc_feature_linkphy_coe) || 9436 soc_feature(unit, soc_feature_subtag_coe)) { 9437 /* For LinkPHY/SubportPktTag pp_ports, check if the mod is a valid one */ 9438 if (_bcm_kt2_mod_is_coe_mod_check(unit, mod) == BCM_E_NONE) { 9439 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit, 9440 mod, port, &pp_port)); 9441 #if defined BCM_METROLITE_SUPPORT 9442 if (soc_feature(unit, soc_feature_discontinuous_pp_port)) { 9443 if (_SOC_IS_PP_PORT_LINKPHY_SUBTAG(unit, pp_port)) { 9444 *is_local_subport = 1; 9445 } 9446 } else 9447 #endif 9448 { 9449 /* For KT2, pp_port 42 to 169 are used for LinkPHY/CoE subport.*/ 9450 if ((pp_port >= pp_port_index_min) && 9451 (pp_port <= pp_port_index_max)) { 9452 *is_local_subport = 1; 9453 } 9454 } 9455 } 9456 } 9457 return BCM_E_NONE; 9458 } 9459 9460 9461 int _bcm_kt2_subport_linkphy_rx_error_hw_set(int unit, 9462 bcm_subport_linkphy_rx_error_t error, 9463 soc_reg_t reg, 9464 uint32 value) 9465 { 9466 soc_field_t field = INVALIDf; 9467 soc_info_t *si = &SOC_INFO(unit); 9468 bcm_port_t port; 9469 9470 9471 /* Validate the error parameter */ 9472 if (!_BCM_KT2_SUBPORT_LINKPHY_RX_ERROR_VALID(error)) { 9473 return BCM_E_PARAM; 9474 } 9475 9476 /* Validate value parameter */ 9477 if (value > 1) { 9478 /* It is expected to be 0 or 1 only implying 9479 * enable/disable. 9480 */ 9481 return BCM_E_PARAM; 9482 } 9483 9484 switch (reg) { 9485 case RXLP_INTERRUPT_ENABLEr: 9486 /* Map the error to field in the register */ 9487 field = _bcm_kt2_subport_linkphy_rx_error_to_reg_field_map[error]; 9488 break; 9489 case RXLP_INTERRUPT_STATUSr: 9490 /* Map the error to field in the register */ 9491 field = _bcm_kt2_subport_linkphy_rx_error_to_st_reg_field_map[error]; 9492 break; 9493 case RXLP_INTERRUPT_DATA_LOG_ENABLEr: 9494 field = _bcm_kt2_subport_linkphy_rx_error_to_dl_reg_field_map[error]; 9495 break; 9496 case RXLP_INTERRUPT_DATA_LOG_VALIDr: 9497 field = _bcm_kt2_subport_linkphy_rx_error_to_dl_val_reg_field_map[error]; 9498 break; 9499 default: 9500 return BCM_E_PARAM; 9501 break; 9502 } 9503 9504 /* Enable/Disable the register's field. */ 9505 SOC_PBMP_ITER(si->linkphy_pbm, port) { 9506 if (SOC_REG_PORT_VALID(unit, reg, port)) { 9507 if (soc_reg_field_valid(unit, reg, field)) { 9508 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, reg, port, field, value)); 9509 } 9510 } 9511 } 9512 9513 return BCM_E_NONE; 9514 } 9515 9516 9517 int bcm_kt2_subport_linkphy_rx_error_register ( 9518 int unit, 9519 bcm_subport_linkphy_rx_errors_t errors, 9520 bcm_subport_linkphy_rx_error_reg_info_t *reg_info, 9521 void *user_data) 9522 { 9523 bcm_subport_linkphy_rx_error_t error; 9524 9525 /* Loop for the errors in the errors bitmap. */ 9526 for (error = 0; error < bcmSubportLinkphyRxErrorCount; error++) { 9527 /* For every error set in the bitmap */ 9528 if (BCM_SUBPORT_LINKPHY_RX_ERROR_GET(errors, error)) { 9529 /* Enable the interrupt */ 9530 BCM_IF_ERROR_RETURN(_bcm_kt2_subport_linkphy_rx_error_hw_set 9531 (unit, error, RXLP_INTERRUPT_ENABLEr, 1)); 9532 /* Assign the callback function to the handler for the error */ 9533 _bcm_linkphy_rx_error_cb_info[error].reg_info.cb = reg_info->cb; 9534 /* If Data log enable/disable, enable/disable data log in the register */ 9535 BCM_IF_ERROR_RETURN(_bcm_kt2_subport_linkphy_rx_error_hw_set 9536 (unit, error, RXLP_INTERRUPT_DATA_LOG_ENABLEr, reg_info->data_log_enable)); 9537 /* Update the data log information for the error */ 9538 _bcm_linkphy_rx_error_cb_info[error].reg_info.data_log_enable = reg_info->data_log_enable; 9539 _bcm_linkphy_rx_error_cb_info[error].user_data = user_data; 9540 } 9541 } 9542 9543 return BCM_E_NONE; 9544 } 9545 9546 int bcm_kt2_subport_linkphy_rx_error_unregister ( 9547 int unit, 9548 bcm_subport_linkphy_rx_errors_t errors) 9549 { 9550 bcm_subport_linkphy_rx_error_t error; 9551 9552 /* Loop for errors in the errors bitmap */ 9553 for (error = 0; error < bcmSubportLinkphyRxErrorCount; error++) { 9554 /* For every error set in the bitmap */ 9555 if (BCM_SUBPORT_LINKPHY_RX_ERROR_GET(errors, error)) { 9556 /* Disable the interrupt */ 9557 BCM_IF_ERROR_RETURN(_bcm_kt2_subport_linkphy_rx_error_hw_set 9558 (unit, error, RXLP_INTERRUPT_ENABLEr, 0)); 9559 /* Assign the callback function to NULL for the error */ 9560 _bcm_linkphy_rx_error_cb_info[error].reg_info.cb = NULL; 9561 /* Disable data log in the register */ 9562 BCM_IF_ERROR_RETURN(_bcm_kt2_subport_linkphy_rx_error_hw_set 9563 (unit, error, RXLP_INTERRUPT_DATA_LOG_ENABLEr, 0)); 9564 /* Set data log info to 0 (disabled) for the error */ 9565 _bcm_linkphy_rx_error_cb_info[error].reg_info.data_log_enable = 0; 9566 _bcm_linkphy_rx_error_cb_info[error].user_data = NULL; 9567 } 9568 } 9569 9570 return BCM_E_NONE; 9571 } 9572 9573 void _bcm_kt2_subport_linkphy_rx_error_get_from_interrupt_status(int unit, uint32 rval, 9574 bcm_subport_linkphy_rx_errors_t *errors) 9575 { 9576 bcm_subport_linkphy_rx_error_t error_type; 9577 soc_field_t field = INVALIDf; 9578 9579 BCM_SUBPORT_LINKPHY_RX_ERROR_CLEAR_ALL(*errors); 9580 9581 for (error_type = bcmSubportLinkphyRxErrorMaxFrameSize; 9582 error_type < bcmSubportLinkphyRxErrorCount; 9583 error_type++) { 9584 field = _bcm_kt2_subport_linkphy_rx_error_to_st_reg_field_map[error_type]; 9585 if (soc_reg_field_get(unit, RXLP_INTERRUPT_STATUSr, rval, field)) { 9586 BCM_SUBPORT_LINKPHY_RX_ERROR_SET(*errors, error_type); 9587 } 9588 } 9589 } 9590 9591 int _bcm_kt2_subport_linkphy_rx_error_handler( 9592 int unit, bcm_port_t port, uint32 rval) 9593 { 9594 uint32 rval1 = 0; 9595 uint32 rxlp_subport_index = 0, phy_port = 0, blk_int_stream_id = 0; 9596 uint8 intr_data_mem[BCM_SUBPORT_LINKPHY_MAX_FRAGMENT_SIZE] = {0}; 9597 int i, j; 9598 int rv = BCM_E_NONE; 9599 uint32 flags = 0; 9600 int data_log_valid = 0, data_log_enabled = 0; 9601 void *user_data = NULL; 9602 bcm_subport_linkphy_rx_error_t error_type = -1; 9603 bcm_subport_linkphy_rx_errors_t errors; 9604 bcm_subport_linkphy_rx_error_data_t error_data; 9605 uint32 *user_pkt_data = NULL; 9606 uint32 *user_frag_data = NULL; 9607 int entry_dw = 0; 9608 9609 BCM_SUBPORT_LINKPHY_RX_ERROR_CLEAR_ALL(errors); 9610 _bcm_kt2_subport_linkphy_rx_error_get_from_interrupt_status(unit, rval, &errors); 9611 9612 entry_dw = soc_mem_entry_words(unit, RXLP_INTR_DATA_MEMm); 9613 9614 rv = READ_RXLP_INTERRUPT_DATA_LOG_VALIDr(unit, port, &rval1); 9615 if (rv < BCM_E_NONE) { 9616 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 9617 (BSL_META_U(unit, 9618 "Linkphy error handler data log valid read failed " 9619 "%s\n"), 9620 bcm_errmsg(rv))); 9621 } 9622 if (rval1) { 9623 rval1 = 0; 9624 data_log_valid = 1; 9625 rv = READ_RXLP_INTERRUPT_DATA_SOURCEr(unit, port, &rval1); 9626 if (rv < BCM_E_NONE) { 9627 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 9628 (BSL_META_U(unit, 9629 "Linkphy error handler data source read failed " 9630 "%s\n"), 9631 bcm_errmsg(rv))); 9632 } 9633 rxlp_subport_index = soc_reg_field_get(unit, RXLP_INTERRUPT_DATA_SOURCEr, rval1, PORT_NUMBERf); 9634 blk_int_stream_id = soc_reg_field_get(unit, RXLP_INTERRUPT_DATA_SOURCEr, rval1, STREAM_IDf); 9635 j = 0; 9636 for (i = 0; i < 192; i=i+16) { 9637 rv = READ_RXLP_INTR_DATA_MEMm(unit, MEM_BLOCK_ANY, j, &(intr_data_mem[i])); 9638 if (rv < BCM_E_NONE) { 9639 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 9640 (BSL_META_U(unit, 9641 "Linkphy error handler intr data mem read failed " 9642 "%s\n"), 9643 bcm_errmsg(rv))); 9644 } 9645 j++; 9646 } 9647 } 9648 for (error_type = bcmSubportLinkphyRxErrorMaxFrameSize; 9649 error_type < bcmSubportLinkphyRxErrorCount; 9650 error_type++) { 9651 if (BCM_SUBPORT_LINKPHY_RX_ERROR_GET(errors, error_type)) { 9652 flags = 0; 9653 sal_memset(&error_data, 0, sizeof(error_data)); 9654 data_log_enabled = _bcm_linkphy_rx_error_cb_info[error_type].reg_info.data_log_enable; 9655 if (data_log_valid && data_log_enabled) { 9656 flags |= BCM_SUBPORT_LINKPHY_RX_ERROR_CB_DATA_VALID; 9657 9658 /* Retreive physical port from subport index returned by hardware */ 9659 rv = _bcm_linkphy_subport_index_to_phyport_get(unit, port, rxlp_subport_index, &phy_port); 9660 if (rv < BCM_E_NONE) { 9661 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 9662 (BSL_META_U(unit, 9663 "Linkphy error getting physical port failed " 9664 "%s\n"), 9665 bcm_errmsg(rv))); 9666 } 9667 error_data.port = phy_port; 9668 9669 /* Retreive ext stream id from int steam id returned by hardware */ 9670 rv = _bcm_linkphy_port_tx_int_to_ext_stream_map_get(unit, port, blk_int_stream_id, &(error_data.ext_stream_id)); 9671 if (rv < BCM_E_NONE) { 9672 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 9673 (BSL_META_U(unit, 9674 "Linkphy error handler stream mapping failed " 9675 "%s\n"), 9676 bcm_errmsg(rv))); 9677 } 9678 9679 /* Copy fragment data to user */ 9680 user_frag_data = (uint32 *)error_data.fragment_data; 9681 for (i = 0; i<12; i++) { 9682 user_pkt_data = (uint32 *)intr_data_mem + (((i+1)*entry_dw) - 1); 9683 for (j=0; j<entry_dw; j++) { 9684 *user_pkt_data = bcm_htonl(*user_pkt_data); 9685 sal_memcpy(user_frag_data, user_pkt_data, sizeof(uint32)); 9686 user_pkt_data--; 9687 user_frag_data++; 9688 } 9689 } 9690 } 9691 9692 /* Call the user registered handler */ 9693 user_data = _bcm_linkphy_rx_error_cb_info[error_type].user_data; 9694 if (_bcm_linkphy_rx_error_cb_info[error_type].reg_info.cb) { 9695 rv = _bcm_linkphy_rx_error_cb_info[error_type].reg_info.cb(unit, error_type, flags, &error_data, user_data); 9696 if (rv < BCM_E_NONE) { 9697 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 9698 (BSL_META_U(unit, 9699 "Linkphy error handler callback failed " 9700 "%s\n"), 9701 bcm_errmsg(rv))); 9702 } 9703 } 9704 } 9705 } 9706 9707 /* Clear the interrupt data source register */ 9708 rv = WRITE_RXLP_INTERRUPT_DATA_SOURCEr(unit, port, 0); 9709 if (rv < BCM_E_NONE) { 9710 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 9711 (BSL_META_U(unit, 9712 "Linkphy error handler data source write failed " 9713 "%s\n"), 9714 bcm_errmsg(rv))); 9715 } 9716 for (error_type = bcmSubportLinkphyRxErrorMaxFrameSize; 9717 error_type < bcmSubportLinkphyRxErrorCount; 9718 error_type++) { 9719 if (BCM_SUBPORT_LINKPHY_RX_ERROR_GET(errors, error_type)) { 9720 /* Clear the interrupt enable for that error_type */ 9721 _bcm_kt2_subport_linkphy_rx_error_hw_set(unit, error_type, RXLP_INTERRUPT_ENABLEr, 0); 9722 /* Clear the interrupt data log valid register for the given error type */ 9723 _bcm_kt2_subport_linkphy_rx_error_hw_set(unit, error_type, RXLP_INTERRUPT_DATA_LOG_VALIDr, 0); 9724 /* Clear the interrupt status register for the given error type */ 9725 _bcm_kt2_subport_linkphy_rx_error_hw_set(unit, error_type, RXLP_INTERRUPT_STATUSr, 0); 9726 /* Enable the interrupt enable for that error_type */ 9727 _bcm_kt2_subport_linkphy_rx_error_hw_set(unit, error_type, RXLP_INTERRUPT_ENABLEr, 1); 9728 } 9729 } 9730 9731 return BCM_E_NONE; 9732 } 9733 9734 /* 9735 * Function: 9736 * bcmi_kt2_subport_gport_modport_get 9737 * Purpose: 9738 * Given a subport-gport, return teh corresponding mod-port 9739 * Parameters: 9740 * unit - (IN) Device Number 9741 * subport_gport - (IN) GPORT (generic port) identifier 9742 * module - (OUT) Module associated with the subport 9743 * port - (OUT) Port associated with the subport 9744 * Returns: 9745 * BCM_E_XXX 9746 */ 9747 9748 int bcmi_kt2_subport_gport_modport_get(int unit, 9749 bcm_gport_t subport_gport, bcm_module_t *module, bcm_port_t *port) 9750 { 9751 int pp_port = 0; 9752 9753 if (!BCM_GPORT_IS_SUBPORT_PORT(subport_gport)) { 9754 LOG_ERROR(BSL_LS_BCM_SUBPORT, 9755 (BSL_META_U(unit, 9756 "ERROR: gport 0x%x is not subport port gport\n"), 9757 subport_gport)); 9758 return BCM_E_PARAM; 9759 } 9760 9761 /* Extract the pp_port from the encoded gport and make sure it is valid */ 9762 pp_port = _BCM_KT2_SUBPORT_PORT_ID_GET(subport_gport); 9763 9764 if (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, subport_gport)) { 9765 if (!_BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) { 9766 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 9767 (BSL_META_U(unit, 9768 "ERROR: SubTag subport port gport 0x%x not found\n"), 9769 subport_gport)); 9770 return BCM_E_NOT_FOUND; 9771 } 9772 } else if (_BCM_KT2_GPORT_IS_GENERAL_SUBPORT_PORT(unit, subport_gport)) { 9773 if (!_BCM_KT2_GENERAL_SUBPORT_PORT_INFO_VALID_GET(unit, pp_port)) { 9774 LOG_VERBOSE(BSL_LS_BCM_SUBPORT, 9775 (BSL_META_U(unit, 9776 "ERROR: General subport port gport 0x%x not found\n"), 9777 subport_gport)); 9778 return BCM_E_NOT_FOUND; 9779 } 9780 } 9781 9782 /* Get the mod-port that corresponds to this pp_port */ 9783 BCM_IF_ERROR_RETURN(_bcm_kt2_pp_port_to_modport_get(unit, 9784 pp_port, module, port)); 9785 9786 return BCM_E_NONE; 9787 } 9788 9789 9790 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 9791 /* 9792 * Function: 9793 * _bcm_kt2_subport_sw_dump 9794 * Purpose: 9795 * Print Subport module s/w state 9796 * Returns: 9797 * void 9798 */ 9799 void 9800 _bcm_kt2_subport_sw_dump(int unit) 9801 { 9802 int idx; 9803 int subport_group_max = SOC_INFO(unit).subport_group_max; 9804 9805 if (BCM_PBMP_NOT_NULL(SOC_INFO(unit).subtag_allowed_pbm)) { 9806 LOG_CLI((BSL_META_U(unit, 9807 "Subtag Subport Groups: total (%d)\n"), 9808 _bcm_subtag_subport_group_count[unit])); 9809 9810 for(idx = 0; idx < subport_group_max; idx++) { 9811 if(_BCM_KT2_SUBPORT_GROUP_USED_GET(unit, idx)) { 9812 LOG_CLI((BSL_META_U(unit, "%d "), idx)); 9813 } 9814 } 9815 LOG_CLI((BSL_META_U(unit, "\n"))); 9816 LOG_CLI((BSL_META_U(unit, "\n----\n"))); 9817 9818 LOG_CLI((BSL_META_U(unit, 9819 "Subtag Subport ids and pp_port used:\n"))); 9820 for (idx = 0; idx < SOC_MAX_NUM_PP_PORTS; idx++) { 9821 if (_BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VALID_GET(unit, idx)) { 9822 LOG_CLI((BSL_META_U(unit, 9823 "group_gport = 0x%x, vlan = %d tcam_idx = %d\n"), 9824 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_GROUP_GET(unit, idx), 9825 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_VLAN_GET(unit, idx), 9826 _BCM_KT2_SUBTAG_SUBPORT_PORT_INFO_TCAM_HW_ID_GET(unit, idx) 9827 )); 9828 } 9829 } 9830 } else { 9831 LOG_CLI((BSL_META_U(unit, 9832 "Subtag Subports not enabled!!\n"))); 9833 } 9834 9835 LOG_CLI((BSL_META_U(unit, 9836 "\n--**--\n"))); 9837 9838 9839 if (BCM_PBMP_NOT_NULL(SOC_INFO(unit).linkphy_allowed_pbm)) { 9840 LOG_CLI((BSL_META_U(unit, 9841 "Linkphy Subport Groups: total (%d)\n"), 9842 _bcm_linkphy_subport_group_count[unit])); 9843 for(idx = 0; idx < SOC_INFO(unit).subport_group_max; idx++) { 9844 if(_BCM_KT2_LINKPHY_SUBPORT_GROUP_USED_GET(unit, idx)) { 9845 LOG_CLI((BSL_META_U(unit, "%d "), idx)); 9846 } 9847 } 9848 LOG_CLI((BSL_META_U(unit, "\n"))); 9849 LOG_CLI((BSL_META_U(unit, "\n----\n"))); 9850 9851 LOG_CLI((BSL_META_U(unit, 9852 "Linkphy Subport ids and pp_port used:\n"))); 9853 for (idx = 0; idx < SOC_MAX_NUM_PP_PORTS; idx++) { 9854 if (_BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_VALID_GET(unit, idx)) { 9855 LOG_CLI((BSL_META_U(unit, 9856 "group_gport = 0x%x, streams(%d) = {%d, %d}\n"), 9857 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_GROUP_GET(unit, idx), 9858 _BCM_KT2_LINKPHY_SUBPORT_PORT_INFO_NUM_STREAMS_GET(unit, idx), 9859 _bcm_linkphy_subport_port_info[unit][idx].ext_stream_idx[0], 9860 _bcm_linkphy_subport_port_info[unit][idx].ext_stream_idx[1] 9861 )); 9862 } 9863 } 9864 } else { 9865 LOG_CLI((BSL_META_U(unit, 9866 "Linkphy Subports not enabled!!\n"))); 9867 } 9868 9869 return; 9870 } 9871 #endif /* BCM_WARM_BOOT_SUPPORT_SW_DUMP */ 9872 9873 #else /* BCM_KATANA2_SUPPORT */ 9874 int bcm_esw_kt2_subport_not_empty; 9875 #endif /* BCM_KATANA2_SUPPORT */ 9876 9877