portmod.c (112334B)
1 /* 2 * 3 * 4 * 5 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 6 * 7 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 8 */ 9 10 #include <shared/bsl.h> 11 12 #include <soc/types.h> 13 #include <soc/error.h> 14 #include <soc/portmod/portmod.h> 15 #include <soc/portmod/portmod_common.h> 16 #include <soc/portmod/portmod_internal.h> 17 #include <soc/portmod/portmod_dispatch.h> 18 #include <soc/portmod/group_member_list.h> 19 #include <soc/portmod/portmod_chain.h> 20 #include <soc/wb_engine.h> 21 #include <soc/drv.h> 22 #include <shared/periodic_event.h> 23 24 25 #ifdef _ERR_MSG_MODULE_NAME 26 #error "_ERR_MSG_MODULE_NAME redefined" 27 #endif 28 #define _ERR_MSG_MODULE_NAME BSL_LS_SOC_PORT 29 30 /* Terminology: 31 ------------ 32 * Phy - represent a physical lane (serdes) 33 * Logical Port (a.k.a just "port") - a phy or group of phys creating a physical interface (e.g. Network Interface) 34 providing Data Link and Physical connectivity between devices 35 * PM - Port Macro 36 * PM id - each HW PM is represented by SW PM entity, this id is used to identify specific PM 37 (This number is internal to the PortMod. 38 * PMM - Port Macros Manager 39 */ 40 41 /* Buffer ID for the high level portmod databases*/ 42 #define PMM_WB_BUFFER_ID (0) 43 44 /* number to represent invalid PM id*/ 45 #define INVALID_PM_ID (-1) 46 47 /* number to represent invalid logical port*/ 48 #define INVALID_PORT (-1) 49 50 /* SUB_PHYS_NUM is used for QSGMII where each phy can contain up to 4 logical lanes. 51 The way it's handled is by expending each phy to have slots for 4 logical ports 52 (for simplicity of the mapping phys which are candidate to be QSGMII aren't handled separately, 53 therefore all the phy are extended by factor 4, regardless in whether QSGMII is valid for this phy*/ 54 #define SUB_PHYS_NUM (4) 55 56 /* Max number of phys (lanes) in single logical port (currently derived from ILKN-24)*/ 57 #define MAX_PHYS_PER_PORT (24) 58 59 #define MAX_ILKN_BLOCKS_NUM (8) 60 61 62 /* 63 PortMod High Level DataBases: 64 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 65 66 The PortMod high level is called PMM (Port Macros Manager). 67 This entity holds the requried information for PortMod managment for specific unit. 68 69 The PMM contain 2 types of databases: 70 * Dynamic information (pmm_wb_var_ids)- WB protected 71 - this information is expected to be automatically restored in case of WB 72 * Static infortmation (pmm_info_t)- not WB protected 73 - this information is expected to be provided by the user in WB initalization 74 (this contain information like: HW description (which port macros exist), function pointers, etc). 75 76 77 The Flow: 78 ~~~~~~~~~ 79 80 1. When portmod API is called it's first translated to "real" port. 81 (when channalized interfaces aren't used it'll be 1-to-1 mapping). 82 2. From the port PM id is fetched 83 3. Using the PM id the PM info is extracted (from pms array) and sent as input to internal PM. 84 85 Other mappings in the draw: 86 --------------------------- 87 1. Logical port to interface type 88 2. Phy to list of PMs (details in the draw) 89 3. phy to logical port bi-directional mapping. 90 91 92 +-------------------------------+ 93 |PMM_WB_PORT_INTERFACE_TYPE_MAP | 94 | | 95 | Map | 96 +--------> Logical Port | 97 | | --> | 98 | | Interface Type | 99 | +-------------------------------+ 100 | 101 +----------------------+ +----------------------+ +--------------------------------------------+ 102 |PMM_WB_PORT_ALIAS_MAP | |PMM_WB_PORT_PM_ID_MAP | | | 103 | | | | | | 104 | Map | | Map | | | 105 | Aliased Port | | Logical Port | | +---------------+ | When accessing with specific port 106 | --> +--> | --> +------> | PM 1 | +---------------> 107 | Real Port | | PM id | | | | | The result is specific PM id 108 | | | | | | | | (the specific PM id depend on phy + interface type) 109 | (See aliasd ports | | | | | +--------------+ | 110 | section below) | | | | | | | | | 111 +------+-------^-------+ +---------^------------+ | | | | | | 112 | | | | | | | | 113 | | | +---------------+ | | 114 | | | | PM 2 | | 115 +------v-------+-------+ | | +----------------+ | 116 |PMM_WB_PORT_DB_PHYS | | | | | | | 117 |PMM_WB_PORT_DB_PORTS | | +--------------+ | | 118 | | | | | | 119 | Map | | | | | 120 | Aliased Port | | | PM n | | 121 | --> | | | | | 122 | Real Port | | | | | 123 | | +------------------+ | +----------------+ | 124 +------+-------^-------+ |PMM_WB_PHY_PM_MAP | | | 125 | | | | | | 126 | | | MAP | | | When accessing with phy 127 | -------------+ Phy +----------> Device Port Macros (pms) +----------------> 128 | | --> | | --- | the result is list of PM ids 129 ---------------------> PM ids | | | (there might be several PMs over same phy, 130 | | | | and the selction depened on specific interface type) 131 +------------------+ +--------------------------------------------+ 132 133 134 135 Aliased Ports: 136 ~~~~~~~~~~~~~ 137 Channalized interfaces requires the ability of having several logical ports which are mapped to same physical interface. 138 139 How does it work: 140 1. When port is added on exisiting physical interface with same properties (interface type and phys) it'll be stored as alias port, 141 and will point to the "real" port. In this case the internal PM won't be notified at all. 142 2. Each port which is passed to portmod API will be translated first to "real" port. 143 For non channalied interfaces the mapping is always 1-to-1. 144 3. When "real" port is deleted one of his aliased will be selected as the new "real" port. 145 The databases will be updated accordinly and PM will be notied about port number change. 146 (HW configuration should bot be affected). 147 4. When all the ports related to an interface are removed, the port will be detached. 148 149 Group Member List: 150 ~~~~~~~~~~~~~~~~~ 151 Manage many to one bi-directional mapping. 152 In PortMod case the group is the port and the members are the phys. 153 (See details in group_member_list.c) 154 155 156 WarmBoot: 157 ~~~~~~~~~ 158 PortMod is using WB engine to save and restore dynamic variables. 159 160 WB engine use the folowing entities: 161 - "Variable" is a single WB protected data unit 162 Variables of same buffer must be kept in order to be restored correctly. 163 Set \ Get variables is done using WB engine macros. 164 165 - "Buffer" is a container for WB protected variables 166 Buffers must stay in order so they can be restored correctly 167 In Portmod buffer id is derived from PM id. 168 169 - "Engine" - is a container for buffers. 170 PortMod is using SOC_WB_ENGINE_PORTMOD static engine id. 171 */ 172 173 static int portmod_periodic_event(int unit, void* user_data); 174 175 static int portmod_pm_aggregated_update_internal(int unit, pm_info_t pm_info, const portmod_port_add_info_t *port_add_info); 176 177 178 typedef enum pmm_wb_var_ids_e{ 179 PMM_WB_PORT_PM_ID_MAP, /* See description above */ 180 PMM_WB_PORT_ALIAS_MAP, /* See description above */ 181 PMM_WB_PHY_PM_MAP_OLD, /* See description above */ 182 PMM_WB_PORT_INTERFACE_TYPE_MAP, /* See description above */ 183 PMM_WB_PORT_DB_PHYS_OLD, /* See description above */ 184 PMM_WB_PORT_DB_PORTS, /* See description above */ 185 PMM_WB_XPHY_DB_ADDR, 186 PMM_WB_XPHY_DB_VALID_PHYS, 187 PMM_WB_PHY_PM_MAP, 188 PMM_WB_PORT_DB_PHYS, 189 PMM_WB_ILKN_PM_MAP, 190 PMM_WB_VARS_COUNT 191 }pmm_wb_var_ids; 192 193 #define PMM_WB_BUFFER_VERSION (6) 194 195 #define PMM_XPHY_VALID_PHYS_SET(unit, valid_phys) \ 196 SOC_WB_ENGINE_SET_VAR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_XPHY_DB_VALID_PHYS, &valid_phys); 197 #define PMM_XPHY_VALID_PHYS_GET(unit, valid_phys) \ 198 SOC_WB_ENGINE_GET_VAR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_XPHY_DB_VALID_PHYS, valid_phys); 199 200 typedef struct pmm_periodic_per_port_info_s { 201 portmod_periodic_event_f ports_callback; 202 int interval; 203 } pmm_periodic_per_port_info_t; 204 205 /* This structure contain information required for periodic event managment */ 206 typedef struct pmm_periodic_data_s { 207 /* callback for ports */ 208 pmm_periodic_per_port_info_t *ports_periodic; 209 /* Handler for periodic events - see periodic_event.h for details */ 210 periodic_event_handler_t periodic_handler; 211 /* Mutex for interval calculation */ 212 sal_mutex_t periodic_lock; 213 /* current working port */ 214 int current_working_port; 215 } pmm_periodic_data_t; 216 217 typedef struct pmm_info_s{ 218 /* the unit number of this PMM. */ 219 int unit; 220 /* this is a feature which allow to map ports to dummy PM which doesn't represent HW entity (PM NULL). 221 If the feature is enabled then ports with interface portmodDispatchTypePmNull will be allocated 222 in the dummy PM. (when feature is disabled adding such ports will retrun an error). 223 pm_null_support is a boolean indication whether this feature is activated. 224 Note that activating \ deactivating this feature between versions isn't Warmboot safe.*/ 225 int pm_null_support; 226 /* number of PMs added so far to the PMM. */ 227 uint32 pms_in_use; 228 /* Array of PMs, accessed by PM id (see drawing above)*/ 229 pm_info_t pms; 230 /* var IDs are uniqe numbers used for WB 231 This number is used to allocate next free WB variable ID 232 (See comments about WB above)*/ 233 uint32 wb_vars_in_use; 234 /* the number of phys controlled by this PMM */ 235 uint32 max_phys; 236 /* max number of logical ports allowed in this PMM */ 237 uint32 max_ports; 238 /* phy to logical port bi-directional mapping 239 (see sepcific comment about group member list data structure)*/ 240 group_member_list_t ports_phys_mapping; 241 /* number of port macros added to this PMM*/ 242 uint32 max_pms; 243 /* priodic events */ 244 pmm_periodic_data_t periodic; 245 }pmm_info_t; 246 247 248 pmm_info_t *_pmm_info[SOC_MAX_NUM_DEVICES] = {NULL}; 249 250 STATIC 251 int portmod_pmm_free(int unit, pmm_info_t *pmm){ 252 int i = 0; 253 SOC_INIT_FUNC_DEFS; 254 255 SOC_NULL_CHECK(pmm); 256 if(pmm->pms != NULL){ 257 for(i = 0; i< pmm->pms_in_use; i++){ 258 if(pmm->pms[i].pm_data.pm4x25_db != NULL){ /*all members of the union are pointers*/ 259 LOG_WARN(BSL_LS_SOC_PORT, 260 (BSL_META_U(unit, 261 "potential memory leak: pm %d wasn't NULL at pmm free\n"), 262 i)); 263 } 264 } 265 sal_free(pmm->pms); 266 } 267 sal_free(pmm); 268 exit: 269 SOC_FUNC_RETURN; 270 } 271 272 273 STATIC 274 int port_db_port_set(void *user_data, group_entry_id_t group_id, group_entry_t* group){ 275 pmm_info_t *pmm; 276 277 if(user_data == NULL){ 278 return SOC_E_PARAM; 279 } 280 pmm = (pmm_info_t *)user_data; 281 return SOC_WB_ENGINE_SET_ARR(pmm->unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_DB_PORTS, group, group_id); 282 } 283 284 STATIC 285 int port_db_port_get(void *user_data, group_entry_id_t group_id, group_entry_t* group){ 286 pmm_info_t *pmm; 287 288 if(user_data == NULL){ 289 return SOC_E_PARAM; 290 } 291 pmm = (pmm_info_t *)user_data; 292 return SOC_WB_ENGINE_GET_ARR(pmm->unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_DB_PORTS, group, group_id); 293 } 294 295 STATIC 296 int port_db_phy_set(void *user_data, member_entry_id_t member_id, member_entry_t* member){ 297 pmm_info_t *pmm; 298 299 if(user_data == NULL){ 300 return SOC_E_PARAM; 301 } 302 pmm = (pmm_info_t *)user_data; 303 return SOC_WB_ENGINE_SET_ARR(pmm->unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_DB_PHYS, member, member_id); 304 } 305 306 STATIC 307 int port_db_phy_get(void *user_data, member_entry_id_t member_id, member_entry_t* member){ 308 pmm_info_t *pmm; 309 310 if(user_data == NULL){ 311 return SOC_E_PARAM; 312 } 313 pmm = (pmm_info_t *)user_data; 314 return SOC_WB_ENGINE_GET_ARR(pmm->unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_DB_PHYS, member, member_id); 315 } 316 317 318 int portmod_xphy_db_addr_set(int unit, int idx, int xphy_addr) 319 { 320 int rv; 321 322 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_XPHY_DB_ADDR, &xphy_addr, idx); 323 return rv; 324 } 325 326 int portmod_xphy_db_addr_get(int unit, int idx, int* xphy_addr) 327 { 328 int rv; 329 330 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_XPHY_DB_ADDR, xphy_addr, idx); 331 return rv; 332 } 333 334 /* 335 * Function: 336 * portmod_xphy_all_valid_phys_get 337 * Purpose: 338 * To get the list of valid external phys in db. 339 * Parameters: 340 * unit - (IN) Unit number. 341 * active_phys - (OUT)Bit map list of valid phy 342 * Returns: 343 * SOC_E_XXX 344 */ 345 346 int portmod_xphy_all_valid_phys_get(int unit, xphy_pbmp_t *active_phys) 347 { 348 int rv; 349 350 rv = PMM_XPHY_VALID_PHYS_GET(unit, active_phys); 351 return rv; 352 } 353 354 /* 355 * Function: 356 * portmod_xphy_valid_phy_set 357 * Purpose: 358 * Record the validity of a particular external phy. 359 * Parameters: 360 * unit - (IN) Unit number. 361 * xphy_idx - (IN) index to db. 362 * valid - (IN) validity information. TRUE/FALSE 363 * Returns: 364 * SOC_E_XXX 365 */ 366 int portmod_xphy_valid_phy_set (int unit, int xphy_idx, int valid) 367 { 368 xphy_pbmp_t active_phys; 369 int rv; 370 SOC_INIT_FUNC_DEFS; 371 372 rv = PMM_XPHY_VALID_PHYS_GET(unit, &active_phys); 373 _SOC_IF_ERR_EXIT(rv); 374 375 if( valid ) { 376 XPHY_PBMP_IDX_ADD(active_phys, xphy_idx); 377 } else { 378 XPHY_PBMP_IDX_REMOVE(active_phys, xphy_idx); 379 } 380 _SOC_IF_ERR_EXIT(PMM_XPHY_VALID_PHYS_SET(unit, active_phys)); 381 exit: 382 SOC_FUNC_RETURN; 383 } 384 385 /* 386 * Function: 387 * portmod_xphy_valid_phy_get 388 * Purpose: 389 * Retrieve the validity of a particular external phy. 390 * Parameters: 391 * unit - (IN) Unit number. 392 * xphy_idx - (IN) index to db. 393 * valid - (OUT) validity information. TRUE/FALSE 394 * Returns: 395 * SOC_E_XXX 396 */ 397 int portmod_xphy_valid_phy_get (int unit, int xphy_idx, int *is_valid) 398 { 399 xphy_pbmp_t active_phys; 400 int rv; 401 SOC_INIT_FUNC_DEFS; 402 403 rv = PMM_XPHY_VALID_PHYS_GET(unit, &active_phys); 404 _SOC_IF_ERR_EXIT(rv); 405 406 *is_valid = 0; 407 408 if( XPHY_PBMP_MEMBER(active_phys, xphy_idx)){ 409 *is_valid =1; 410 } 411 exit: 412 SOC_FUNC_RETURN; 413 } 414 415 /* 416 * Function: 417 * portmod_xphy_add 418 * Purpose: 419 * Add exteranl phy to the db. 420 * Parameters: 421 * unit - (IN) Unit number. 422 * xphy_addr - (IN) External phy address 423 * core_access - (IN) Access information for exteranl phy being added. 424 * xphy_idx - (OUT) Indicate location of new entry. 425 * Returns: 426 * SOC_E_XXX 427 */ 428 int portmod_xphy_add(int unit, int xphy_addr, const phymod_core_access_t* core_access, int* xphy_idx) 429 { 430 431 SOC_INIT_FUNC_DEFS; 432 433 434 _SOC_IF_ERR_EXIT(portmod_chain_xphy_add(unit, xphy_addr, core_access, xphy_idx)); 435 if (*xphy_idx != PORTMOD_XPHY_EXISTING_IDX) { 436 _SOC_IF_ERR_EXIT(portmod_xphy_valid_phy_set (unit, *xphy_idx, TRUE)); 437 } 438 exit: 439 SOC_FUNC_RETURN; 440 441 } 442 443 /* 444 * Function: 445 * portmod_xphy_delete 446 * Purpose: 447 * Delete exteranl phy from the db. 448 * Parameters: 449 * unit - (IN) Unit number. 450 * xphy_addr - (IN) External phy address 451 * Returns: 452 * SOC_E_XXX 453 */ 454 455 int portmod_xphy_delete(int unit, int xphy_addr) 456 { 457 458 SOC_INIT_FUNC_DEFS; 459 _SOC_IF_ERR_EXIT(portmod_chain_xphy_delete(unit, xphy_addr)); 460 /* portmod_xphy_valid_phy_set() was called as part of 461 portmod_chain_xphy_delete. */ 462 463 exit: 464 SOC_FUNC_RETURN; 465 466 } 467 468 /* 469 * Function: 470 * portmod_xphy_wb_db_restore 471 * Purpose: 472 * Add exteranl phy to the db. 473 * Parameters: 474 * unit - (IN) Unit number. 475 * xphy_idx - (IN) External Db index 476 * xphy_addr - (IN) External phy address 477 * core_access - (IN) Access information for exteranl phy to be restored. 478 * Returns: 479 * SOC_E_XXX 480 */ 481 int portmod_xphy_wb_db_restore(int unit, int xphy_idx, int xphy_addr, const phymod_core_access_t *core_access) 482 { 483 phymod_core_access_t xphy_core_access; 484 SOC_INIT_FUNC_DEFS; 485 486 _SOC_IF_ERR_EXIT(portmod_xphy_db_addr_get(unit, xphy_idx, &xphy_addr)); 487 sal_memcpy(&xphy_core_access, core_access, sizeof(phymod_core_access_t)); 488 _SOC_IF_ERR_EXIT(portmod_chain_xphy_add_by_index(unit, xphy_idx, xphy_addr, &xphy_core_access)); 489 490 exit: 491 SOC_FUNC_RETURN; 492 } 493 494 495 int portmod_pm_create_info_internal_t_init(int unit, portmod_pm_create_info_internal_t *create_info_internal) 496 { 497 sal_memset(create_info_internal, 0 , sizeof(*create_info_internal)); 498 return SOC_E_NONE; 499 } 500 501 /*calculate how many PMs objects are required for each PM type*/ 502 STATIC 503 int _portmod_pm_type_to_nof_pms(int unit, portmod_dispatch_type_t pm_type, int *nof_pms) 504 { 505 SOC_INIT_FUNC_DEFS; 506 507 switch(pm_type){ 508 #ifdef PORTMOD_PM4X25_SUPPORT 509 case portmodDispatchTypePm4x25: 510 #ifdef PORTMOD_PM4X25TD_SUPPORT 511 case portmodDispatchTypePm4x25td: 512 #endif /* PORTMOD_PM4X25TD_SUPPORT */ 513 #ifdef PORTMOD_CPM4X25_SUPPORT 514 case portmodDispatchTypeCpm4x25: 515 #endif /* PORTMOD_CPM4X25TD_SUPPORT */ 516 *nof_pms = 1; 517 break; 518 #endif /*PORTMOD_PM4X25_SUPPORT */ 519 #ifdef PORTMOD_PM4X10_SUPPORT 520 case portmodDispatchTypePm4x10: 521 #ifdef PORTMOD_PM4X10TD_SUPPORT 522 case portmodDispatchTypePm4x10td: 523 #endif /*PORTMOD_PM4X10TD_SUPPORT */ 524 *nof_pms = 1; 525 break; 526 #endif /*PORTMOD_PM4X10_SUPPORT */ 527 #ifdef PORTMOD_PM12X10_SUPPORT 528 case portmodDispatchTypePm12x10: 529 #ifdef PORTMOD_PM12X10_XGS_SUPPORT 530 case portmodDispatchTypePm12x10_xgs: 531 #endif /*PORTMOD_PM12X10_XGS_SUPPORT */ 532 *nof_pms = 5; /*Top, 3 times 4x10, 4X25 */ 533 break; 534 #endif /*PORTMOD_PM12X10_SUPPORT */ 535 #ifdef PORTMOD_PM4x10Q_SUPPORT 536 case portmodDispatchTypePm4x10Q: 537 *nof_pms = 2; /*Top, 4X10Q */ 538 break; 539 #endif /*PORTMOD_PM4x10Q_SUPPORT */ 540 #ifdef PORTMOD_PM_QTC_SUPPORT 541 case portmodDispatchTypePm_qtc: 542 *nof_pms = 1; /*Top, QTCs */ 543 break; 544 #endif /*PORTMOD_PM_QTC_SUPPORT */ 545 #ifdef PORTMOD_PM_OS_ILKN_SUPPORT 546 case portmodDispatchTypePmOsILKN: 547 #ifdef PORTMOD_PM_OS_ILKN_50G_SUPPORT 548 case portmodDispatchTypePmOsILKN_50G: 549 #endif /*PORTMOD_PM_OS_ILKN_50G_SUPPORT */ 550 *nof_pms = 1; 551 break; 552 #endif /*PORTMOD_PM_OS_ILKN_SUPPORT */ 553 #ifdef PORTMOD_DNX_FABRIC_SUPPORT 554 case portmodDispatchTypeDnx_fabric: 555 *nof_pms = 1; 556 break; 557 #endif /*PORTMOD_DNX_FABRIC_SUPPORT*/ 558 #ifdef PORTMOD_DNX_FABRIC_O_NIF_SUPPORT 559 case portmodDispatchTypeDnx_fabric_o_nif: 560 *nof_pms = 1; 561 break; 562 #endif /*PORTMOD_DNX_FABRIC_O_NIF_SUPPORT */ 563 #ifdef PORTMOD_PM8X50_FABRIC_SUPPORT 564 case portmodDispatchTypePm8x50_fabric: 565 *nof_pms = 1; 566 break; 567 #endif /*PORTMOD_PM8X50_FABRIC_SUPPORT*/ 568 #ifdef PORTMOD_PM4X2P5_SUPPORT 569 case portmodDispatchTypePm4x2p5: 570 *nof_pms = 1; 571 break; 572 #endif /*PORTMOD_PM4X2P5_SUPPORT */ 573 #ifdef PORTMOD_PM8X50_SUPPORT 574 case portmodDispatchTypePm8x50: 575 *nof_pms = 1; 576 break; 577 #endif /*PORTMOD_PM8X50_SUPPORT*/ 578 #ifdef PORTMOD_PM4X10_QTC_SUPPORT 579 case portmodDispatchTypePm4x10_qtc: 580 *nof_pms = 2; 581 break; 582 #endif /*PORTMOD_PM4X10_QTC_SUPPORT*/ 583 default: 584 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Can't retrieve number of warmboot buffers for the specified PM type %d"), pm_type)); 585 } 586 exit: 587 SOC_FUNC_RETURN; 588 } 589 590 STATIC 591 int _portmod_max_pms_get(int unit, int nof_pm_instances, const portmod_pm_instances_t* pm_instances, int *max_pms) 592 { 593 int i = 0; 594 int nof_pms = 0; 595 SOC_INIT_FUNC_DEFS; 596 597 *max_pms = 0; 598 599 for( i = 0 ; i < nof_pm_instances; i++){ 600 _SOC_IF_ERR_EXIT(_portmod_pm_type_to_nof_pms(unit, pm_instances[i].type, &nof_pms)); 601 *max_pms += nof_pms* pm_instances[i].instances; 602 } 603 exit: 604 SOC_FUNC_RETURN; 605 } 606 607 int portmod_wb_upgrade_func(int unit, void* arg, int recovered_version, int new_version) 608 { 609 int port, phy, pm_id, rv, i; 610 xphy_pbmp_t active_phys; 611 int xphy_idx; 612 int xphy_addr; 613 uint32 invalid_pm_id = INVALID_PM_ID; 614 member_entry_id_t member_id; 615 member_entry_t member, member_end; 616 SOC_INIT_FUNC_DEFS; 617 618 /* 619 * Change from version 1 to version 2: 620 * pmNull was added as pm_id 0 (optionaly) 621 * once it's done it pushes all other pm ids +1. 622 */ 623 if (recovered_version == 1 && 624 new_version >= 2 && 625 _pmm_info[unit]->pm_null_support) { 626 627 for (port=0 ; port<_pmm_info[unit]->max_ports ; port++) { 628 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_PM_ID_MAP, &pm_id, port); 629 _SOC_IF_ERR_EXIT(rv); 630 if(pm_id != INVALID_PM_ID){ 631 pm_id++; 632 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_PM_ID_MAP, &pm_id, port); 633 _SOC_IF_ERR_EXIT(rv); 634 } 635 } 636 for(phy=0;phy<(_pmm_info[unit]->max_phys - 1);phy++){ 637 for(i=0;i<MAX_PMS_PER_PHY;i++){ 638 _SOC_IF_ERR_EXIT(soc_wb_engine_var_get(unit,SOC_WB_ENGINE_PORTMOD,PMM_WB_PHY_PM_MAP_OLD,phy,i, (uint8*)&pm_id)); 639 if(pm_id!=INVALID_PM_ID){ 640 pm_id++; 641 _SOC_IF_ERR_EXIT(soc_wb_engine_var_set(unit,SOC_WB_ENGINE_PORTMOD,PMM_WB_PHY_PM_MAP_OLD,phy,i, (uint8*)&pm_id)); 642 } 643 } 644 } 645 } 646 647 if (recovered_version <= 3 && 648 new_version >= 4) { 649 650 /* 651 * if upgrading from older version which do not have valid_phys, 652 * it need to get cleared. 653 */ 654 sal_memset(&active_phys,0, sizeof(xphy_pbmp_t)); 655 rv = PMM_XPHY_VALID_PHYS_SET(unit, active_phys); 656 _SOC_IF_ERR_EXIT(rv); 657 658 /* 659 * if xphy_addr has valid address, that mean that phy is valid. 660 */ 661 for (xphy_idx=0; xphy_idx < PORTMOD_MAX_NUM_XPHY_SUPPORTED; xphy_idx++) { 662 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_XPHY_DB_ADDR, &xphy_addr, xphy_idx); 663 _SOC_IF_ERR_EXIT(rv); 664 665 if(xphy_addr != INVALID_PM_ID){ 666 rv = portmod_xphy_valid_phy_set (unit, xphy_idx, TRUE); 667 } 668 } 669 } 670 671 if (recovered_version <= 4 && 672 new_version >= 5) { 673 for(phy = 0; phy < (_pmm_info[unit]->max_phys - 1); phy++){ 674 for(i = 0; i < MAX_PMS_PER_PHY; i++){ 675 _SOC_IF_ERR_EXIT(soc_wb_engine_var_get(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP_OLD, phy, i, (uint8*)&pm_id)); 676 _SOC_IF_ERR_EXIT(soc_wb_engine_var_set(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, phy, i, (uint8*)&pm_id)); 677 } 678 } 679 /* init as INVALID_PM_ID for the last phy id */ 680 for(i = 0; i < MAX_PMS_PER_PHY; i++){ 681 _SOC_IF_ERR_EXIT(soc_wb_engine_var_set(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, _pmm_info[unit]->max_phys - 1, i, (uint8*)&invalid_pm_id)); 682 } 683 684 for(member_id = 0; member_id < (_pmm_info[unit]->ports_phys_mapping.members_count - SUB_PHYS_NUM); member_id++){ 685 _SOC_IF_ERR_EXIT(SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_DB_PHYS_OLD, &member, member_id)); 686 _SOC_IF_ERR_EXIT(SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_DB_PHYS, &member, member_id)); 687 } 688 /* init the last phy member */ 689 member_end.group = GROUP_MEM_LIST_END; 690 member_end.next = GROUP_MEM_LIST_END; 691 member_end.prev = GROUP_MEM_LIST_END; 692 for(member_id = (_pmm_info[unit]->ports_phys_mapping.members_count - SUB_PHYS_NUM); 693 member_id < _pmm_info[unit]->ports_phys_mapping.members_count; member_id++){ 694 _SOC_IF_ERR_EXIT(SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_DB_PHYS, &member_end, member_id)); 695 } 696 } 697 698 exit: 699 SOC_FUNC_RETURN; 700 } 701 702 int portmod_create(int unit, int flags, int max_ports, int max_phys, int nof_pm_instances, const portmod_pm_instances_t* pm_instances) 703 { 704 WB_ENGINE_INIT_TABLES_DEFS; 705 int buffer_id; 706 int rv; 707 int max_pms = 0; 708 int pm_inst = 0; 709 pmm_info_t *pmm = NULL; 710 portmod_pm_create_info_t pm_null_create_info; 711 int max_wb_buffer_ids = 0; 712 int max_wb_var_ids = 0 ; 713 int max_wb_buffer_ids_pm = 0; 714 int max_wb_buffer_ids_xphy = 0; 715 SOC_INIT_FUNC_DEFS; 716 717 COMPILER_REFERENCE(buffer_is_dynamic); 718 719 _SOC_IF_ERR_EXIT(portmod_pm_create_info_t_init(unit, &pm_null_create_info)); 720 721 _SOC_IF_ERR_EXIT(portmod_pm_instances_t_validate(unit, pm_instances)); 722 723 if(nof_pm_instances <= 0){ 724 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("nof_pm_instances must be > 0"))); 725 } 726 727 for(pm_inst = 0; pm_inst < nof_pm_instances; pm_inst++) { 728 _SOC_IF_ERR_EXIT(portmod_pm_instances_t_validate(unit, &pm_instances[pm_inst])); 729 } 730 731 if(_pmm_info[unit] != NULL){ 732 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod already created for the unit"))); 733 } 734 735 _SOC_IF_ERR_EXIT(_portmod_max_pms_get(unit, nof_pm_instances, pm_instances, &max_pms)); 736 737 if (PORTMOD_CREATE_F_PM_NULL_GET(flags)) { 738 max_pms++; 739 } 740 741 pmm = sal_alloc(sizeof(pmm_info_t), "unit pmm"); 742 SOC_NULL_CHECK(pmm); 743 _pmm_info[unit] = pmm; 744 pmm->pm_null_support = 0; 745 #ifdef PORTMOD_PMNULL_SUPPORT 746 if (PORTMOD_CREATE_F_PM_NULL_GET(flags)) { 747 pmm->pm_null_support = 1; 748 } 749 #endif /* PORTMOD_PMNULL_SUPPORT */ 750 pmm->pms = NULL; 751 752 /*the pms are not saved in WB*/ 753 pmm->pms = sal_alloc(sizeof(struct pm_info_s)*max_pms, "port_macros"); 754 SOC_NULL_CHECK(pmm->pms); 755 sal_memset(pmm->pms, 0, sizeof(struct pm_info_s)*max_pms); 756 757 /*callback allocation*/ 758 pmm->periodic.ports_periodic = sal_alloc(sizeof(pmm_periodic_per_port_info_t)*max_ports, "ports_periodic"); 759 SOC_NULL_CHECK(pmm->periodic.ports_periodic); 760 sal_memset(pmm->periodic.ports_periodic, 0, sizeof(pmm_periodic_per_port_info_t)*max_ports); 761 762 /* periodic mutex allocation */ 763 _pmm_info[unit]->periodic.periodic_lock = sal_mutex_create("ports_periodic lock"); 764 SOC_NULL_CHECK(_pmm_info[unit]->periodic.periodic_lock); 765 766 /* mark not currently working port */ 767 _pmm_info[unit]->periodic.current_working_port = -1; 768 769 770 pmm->pms_in_use = 0; 771 pmm->ports_phys_mapping.groups_count = max_ports; 772 pmm->ports_phys_mapping.members_count = (max_phys + 1)* SUB_PHYS_NUM; 773 pmm->ports_phys_mapping.user_data = pmm; 774 pmm->ports_phys_mapping.group_set = port_db_port_set; 775 pmm->ports_phys_mapping.group_get = port_db_port_get; 776 pmm->ports_phys_mapping.member_set = port_db_phy_set; 777 pmm->ports_phys_mapping.member_get = port_db_phy_get; 778 pmm->max_phys = max_phys + 1; 779 pmm->max_ports = max_ports; 780 pmm->max_pms = max_pms; 781 pmm->unit = unit; 782 pmm->wb_vars_in_use = PMM_WB_VARS_COUNT; 783 784 buffer_id = PMM_WB_BUFFER_ID; 785 786 max_wb_buffer_ids_pm = max_pms + 1; 787 max_wb_buffer_ids_xphy = PORTMOD_MAX_NUM_XPHY_SUPPORTED; 788 max_wb_var_ids = (max_wb_buffer_ids_pm * MAX_VARS_PER_BUFFER) + 789 (max_wb_buffer_ids_xphy * MAX_VARS_PER_XPHY_BUFFER); 790 max_wb_buffer_ids = max_wb_buffer_ids_pm + max_wb_buffer_ids_xphy; 791 792 _SOC_IF_ERR_EXIT(soc_wb_engine_init_tables(unit, SOC_WB_ENGINE_PORTMOD, max_wb_buffer_ids, max_wb_var_ids )); 793 794 /* 795 * Buffer version number need to be bumped up ever time there is a change in buffer content. This version will keep track of 796 * what content are in the buffer. Since we are adding xphy_db_valid_phys, need to bump the number. 797 */ 798 SOC_WB_ENGINE_ADD_BUFF(SOC_WB_ENGINE_PORTMOD, PMM_WB_BUFFER_ID, "pmm_buffer", portmod_wb_upgrade_func, NULL, PMM_WB_BUFFER_VERSION, 1, SOC_WB_ENGINE_PRE_RELEASE); 799 _SOC_IF_ERR_EXIT(rv); 800 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_PM_ID_MAP, "ports_to_pm_id_mapping", PMM_WB_BUFFER_ID, sizeof(int), NULL, max_ports, VERSION(1)); 801 _SOC_IF_ERR_EXIT(rv); 802 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_INTERFACE_TYPE_MAP, "ports_interface_type", PMM_WB_BUFFER_ID, sizeof(soc_port_if_t), NULL, max_ports, VERSION(1)); 803 _SOC_IF_ERR_EXIT(rv); 804 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_ALIAS_MAP, "ports_alias", PMM_WB_BUFFER_ID, sizeof(int), NULL, max_ports, VERSION(1)); 805 _SOC_IF_ERR_EXIT(rv); 806 SOC_WB_ENGINE_ADD_2D_ARR(SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP_OLD, "phys_to_pm_ids", PMM_WB_BUFFER_ID, sizeof(int), NULL, max_phys, MAX_PMS_PER_PHY, VERSION(1)); 807 _SOC_IF_ERR_EXIT(rv); 808 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_DB_PHYS_OLD, "port_db_phys", PMM_WB_BUFFER_ID, group_member_list_member_entry_size_get(), NULL, max_phys*SUB_PHYS_NUM, VERSION(1)); 809 _SOC_IF_ERR_EXIT(rv); 810 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_DB_PORTS, "port_db_ports", PMM_WB_BUFFER_ID, group_member_list_group_entry_size_get(), NULL, max_ports, VERSION(1)); 811 _SOC_IF_ERR_EXIT(rv); 812 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, PMM_WB_XPHY_DB_ADDR, "xphy_db_addr", PMM_WB_BUFFER_ID, sizeof(int), NULL, PORTMOD_MAX_NUM_XPHY_SUPPORTED, VERSION(3)); 813 _SOC_IF_ERR_EXIT(rv); 814 SOC_WB_ENGINE_ADD_2D_ARR(SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, "phys_to_pm_ids_new", PMM_WB_BUFFER_ID, sizeof(int), NULL, pmm->max_phys, MAX_PMS_PER_PHY, VERSION(5)); 815 _SOC_IF_ERR_EXIT(rv); 816 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_DB_PHYS, "port_db_phys_new", PMM_WB_BUFFER_ID, group_member_list_member_entry_size_get(), NULL, pmm->ports_phys_mapping.members_count, VERSION(5)); 817 _SOC_IF_ERR_EXIT(rv); 818 819 /* 820 * When new warmboot content is added, it need to identify which version of the buffer is added. So that warmboot engine can keep track of 821 * when to look for this content based on Buffer version. 822 */ 823 SOC_WB_ENGINE_ADD_VAR(SOC_WB_ENGINE_PORTMOD, PMM_WB_XPHY_DB_VALID_PHYS, "xphy_db_valid_phys", PMM_WB_BUFFER_ID, sizeof(xphy_pbmp_t), NULL,VERSION(4)); 824 _SOC_IF_ERR_EXIT(rv); 825 826 SOC_WB_ENGINE_ADD_ARR(SOC_WB_ENGINE_PORTMOD, PMM_WB_ILKN_PM_MAP, "ilkn_cores_to_pm_ids", PMM_WB_BUFFER_ID, sizeof(int), NULL, MAX_ILKN_BLOCKS_NUM, VERSION(6)); 827 _SOC_IF_ERR_EXIT(rv); 828 829 _SOC_IF_ERR_EXIT(soc_wb_engine_init_buffer(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_BUFFER_ID, FALSE)); 830 831 if(!SOC_WARM_BOOT(unit)){ /*Cold boot*/ 832 int phy_id, pm, core; 833 uint32 invalid_pm_id = INVALID_PM_ID; 834 xphy_pbmp_t xphy_valid_pbmp ; 835 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_PM_ID_MAP, INVALID_PM_ID); 836 _SOC_IF_ERR_EXIT(rv); 837 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_INTERFACE_TYPE_MAP, SOC_PORT_IF_NULL); 838 _SOC_IF_ERR_EXIT(rv); 839 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_ALIAS_MAP, INVALID_PORT); 840 _SOC_IF_ERR_EXIT(rv); 841 rv = SOC_WB_ENGINE_MEMSET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_XPHY_DB_ADDR, INVALID_PM_ID); 842 _SOC_IF_ERR_EXIT(rv); 843 sal_memset(&xphy_valid_pbmp,0, sizeof(xphy_pbmp_t)); 844 rv = PMM_XPHY_VALID_PHYS_SET(unit,xphy_valid_pbmp); 845 846 /* Set all PM ids in PMM_WB_PHY_PM_MAP to invalid */ 847 for(phy_id = 0 ; phy_id < pmm->max_phys ; phy_id++){ 848 for(pm = 0 ; pm < MAX_PMS_PER_PHY ; pm++){ 849 _SOC_IF_ERR_EXIT(soc_wb_engine_var_set(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, phy_id, pm, (uint8 *)&invalid_pm_id)); 850 } 851 } 852 /* Set all PM ids in PMM_WB_ILKN_PM_MAP to invalid */ 853 for(core = 0 ; core < MAX_ILKN_BLOCKS_NUM ; core++){ 854 _SOC_IF_ERR_EXIT(SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_ILKN_PM_MAP, &invalid_pm_id, core)); 855 } 856 _SOC_IF_ERR_EXIT(group_member_list_init(&pmm->ports_phys_mapping)); 857 } 858 859 if (SOC_WARM_BOOT(unit)) { 860 int xphy_id, xphy_addr; 861 for (xphy_id=0; xphy_id<PORTMOD_MAX_NUM_XPHY_SUPPORTED; xphy_id++) { 862 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_XPHY_DB_ADDR, &xphy_addr, xphy_id); 863 _SOC_IF_ERR_EXIT(rv); 864 portmod_xphy_addr_set(unit, xphy_id, xphy_addr); 865 } 866 } 867 868 _pmm_info[unit] = pmm; 869 870 #ifdef PORTMOD_PMNULL_SUPPORT 871 if (PORTMOD_CREATE_F_PM_NULL_GET(flags)) { 872 pm_null_create_info.type = portmodDispatchTypePmNull; 873 rv = portmod_port_macro_add(unit, &pm_null_create_info); 874 _SOC_IF_ERR_EXIT(rv); 875 } 876 #endif /* PORTMOD_PMNULL_SUPPORT */ 877 878 879 /* register periodic event */ 880 { 881 #define _PORTMOD_PE_NAME_MAX 30 882 883 char pe_name[_PORTMOD_PE_NAME_MAX]; 884 periodic_event_config_t pe_config; 885 int name_size; 886 periodic_event_config_t_init(&pe_config); 887 888 name_size = sal_snprintf(pe_name, _PORTMOD_PE_NAME_MAX, "Portmod Periodic.%d", unit); 889 if(name_size >= _PORTMOD_PE_NAME_MAX){ 890 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, (_SOC_MSG("Failed to create periodic name"))); 891 } 892 893 pe_config.name = pe_name; 894 pe_config.bsl_module = _ERR_MSG_MODULE_NAME; 895 pe_config.interval = 1000000; /* 1 sec - doesn't really matter */ 896 pe_config.callback = &portmod_periodic_event; 897 pe_config.start_operation = 0; 898 pe_config.error_threshold = 10; /* exit if too much failures */ 899 900 _SOC_IF_ERR_EXIT(periodic_event_create(unit, &pe_config, &(pmm->periodic.periodic_handler))); 901 } 902 903 904 905 exit: 906 /*free memories in case of error*/ 907 if (SOC_FUNC_ERROR){ 908 if(pmm != NULL){ 909 portmod_pmm_free(unit, pmm); 910 } 911 } 912 SOC_FUNC_RETURN; 913 } 914 915 916 917 int portmod_destroy(int unit) 918 { 919 int i; 920 pm_info_t pm_info = NULL; 921 SOC_INIT_FUNC_DEFS; 922 923 if(_pmm_info[unit] == NULL){ 924 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 925 } 926 927 _SOC_IF_ERR_EXIT(periodic_event_destroy(&(_pmm_info[unit]->periodic.periodic_handler))); 928 929 _pmm_info[unit]->periodic.current_working_port = -1; 930 931 if (_pmm_info[unit]->periodic.periodic_lock != NULL) { 932 sal_mutex_destroy(_pmm_info[unit]->periodic.periodic_lock); 933 } 934 935 if (_pmm_info[unit]->periodic.ports_periodic != NULL) { 936 sal_free(_pmm_info[unit]->periodic.ports_periodic); 937 _pmm_info[unit]->periodic.ports_periodic = NULL; 938 } 939 940 if(_pmm_info[unit]->pms != NULL){ 941 for(i = 0; i< _pmm_info[unit]->pms_in_use; i++){ 942 _SOC_IF_ERR_EXIT(portmod_pm_info_from_pm_id_get(unit, i, &pm_info)); 943 _SOC_IF_ERR_EXIT(portmod_pm_destroy(unit, pm_info)); 944 } 945 } 946 947 #ifdef CPRIMOD_SUPPORT 948 _SOC_IF_ERR_EXIT 949 (cprimod_cpri_cpm_interrupt_data_init(unit)); 950 #endif 951 952 portmod_chain_xphy_user_access_release(unit); 953 _SOC_IF_ERR_EXIT(portmod_chain_xphy_delete_all(unit)); 954 955 _SOC_IF_ERR_EXIT(soc_wb_engine_deinit_tables(unit, SOC_WB_ENGINE_PORTMOD)); 956 portmod_pmm_free(unit, _pmm_info[unit]); 957 _pmm_info[unit] = NULL; 958 959 exit: 960 SOC_FUNC_RETURN; 961 } 962 963 #if defined(PORTMOD_PM4X25_SUPPORT) || defined(PORTMOD_PM4X10_SUPPORT) || defined(PORTMOD_DNX_FABRIC_SUPPORT) || defined(PORTMOD_PM12X10_SUPPORT) || defined(PORTMOD_PM4x10Q_SUPPORT) || defined(PORTMOD_PM_OS_ILKN_SUPPORT) || defined(PORTMOD_PM8X50_FABRIC_SUPPORT) || defined(PORTMOD_PM8X50_SUPPORT) \ 964 || defined(PORTMOD_PM4X10_QTC_SUPPORT) 965 STATIC 966 int _portmod_port_macro_internal_add(int unit , const portmod_pm_create_info_internal_t* pm_add_info, int *pm_created_id) 967 { 968 int pm_id, free_slot_found, current_val, i, phy; 969 uint32 invalid_pm_id = INVALID_PM_ID; 970 int pm_initialized = FALSE; 971 int should_add_to_map = TRUE; 972 int wb_buffer_id; 973 SOC_INIT_FUNC_DEFS; 974 975 pm_id = _pmm_info[unit]->pms_in_use; 976 977 /*in case of ilkn interface the PM map sw-state is updated per ilkn block id */ 978 #if defined(PORTMOD_PM_OS_ILKN_50G_SUPPORT) 979 if (pm_add_info->type == portmodDispatchTypePmOsILKN_50G ) 980 { 981 /* Store the newly created Pm-ID in the Ilkn-core to PM-ID Sw-state */ 982 _SOC_IF_ERR_EXIT(SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_ILKN_PM_MAP, &pm_id, pm_add_info->pm_specific_info.os_ilkn.ilkn_block_index)); 983 } 984 #endif /* defined(PORTMOD_PM_OS_ILKN_50G_SUPPORT) */ 985 #if defined(PORTMOD_PM_OS_ILKN_SUPPORT) 986 if (pm_add_info->type == portmodDispatchTypePmOsILKN ) 987 { 988 /* Store the newly created Pm-ID in the Ilkn-core to PM-ID Sw-state */ 989 _SOC_IF_ERR_EXIT(SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_ILKN_PM_MAP, &pm_id, pm_add_info->pm_specific_info.os_ilkn.ilkn_block_index)); 990 } 991 #endif /* defined(PORTMOD_PM_OS_ILKN_SUPPORT) */ 992 993 994 /* WB buffer ID is used to identify the specific PM database 995 WB buffer order must be kept to insure WB and ISSU works. 996 Buffers order: 997 0 - Global Portmod DB 998 1..n-1 - PMs buffers. 999 when PmNull present it takes pm_id 0, so wb_buffer_id==pm_id 1000 when it's not present wb_buffer_id==pm_id+1 1001 The PmNull always tales last buffer 1002 */ 1003 if (_pmm_info[unit]->pm_null_support) { 1004 #ifdef PORTMOD_PMNULL_SUPPORT 1005 if (pm_add_info->type == portmodDispatchTypePmNull) { 1006 wb_buffer_id = _pmm_info[unit]->max_pms; 1007 } else 1008 #endif 1009 { 1010 wb_buffer_id = pm_id; 1011 } 1012 } else { 1013 wb_buffer_id = pm_id + 1; 1014 } 1015 1016 _SOC_IF_ERR_EXIT(portmod_pm_init(unit, pm_add_info, wb_buffer_id, &_pmm_info[unit]->pms[pm_id])); 1017 pm_initialized = TRUE; 1018 if(!SOC_WARM_BOOT(unit)){ 1019 /*add to map just in case of cold boot*/ 1020 PORTMOD_PBMP_ITER(pm_add_info->phys, phy){ 1021 free_slot_found = FALSE; 1022 for(i = 0 ; i < MAX_PMS_PER_PHY; i++){ 1023 _SOC_IF_ERR_EXIT(soc_wb_engine_var_get(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, phy, i, (uint8 *)¤t_val)); 1024 if(current_val == INVALID_PM_ID && pm_add_info->type == _pmm_info[unit]->pms[pm_id].type){ 1025 _SOC_IF_ERR_EXIT(soc_wb_engine_var_set(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, phy, i, (uint8 *)&pm_id)); 1026 free_slot_found = TRUE; 1027 break; 1028 } 1029 } 1030 if(!free_slot_found){ 1031 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, (_SOC_MSG("phy (%d) already used by the maximum number of pms %d"), phy, MAX_PMS_PER_PHY)); 1032 } 1033 } 1034 } 1035 1036 #ifdef PORTMOD_PM4X10_QTC_SUPPORT 1037 /*pm4x10_qtc dirver includes pm4x10_qtc and pm4x10 init.*/ 1038 if (pm_add_info->type == portmodDispatchTypePm4x10_qtc) { 1039 _pmm_info[unit]->pms_in_use += 2; 1040 } else 1041 #endif 1042 { 1043 _pmm_info[unit]->pms_in_use++; 1044 } 1045 *pm_created_id = pm_id; 1046 exit: 1047 if (SOC_FUNC_ERROR){ 1048 if(pm_initialized){ 1049 1050 portmod_pm_destroy(unit, &_pmm_info[unit]->pms[pm_id]); 1051 } 1052 /*clean the map*/ 1053 if(should_add_to_map){ 1054 PORTMOD_PBMP_ITER(pm_add_info->phys, phy){ 1055 /* coverity[dead_error_line] */ 1056 for(i = 0 ; !_rv && (i < MAX_PMS_PER_PHY); i++){ 1057 _rv = soc_wb_engine_var_get(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, phy, i, (uint8 *)¤t_val); 1058 if(!_rv && (current_val == pm_id)){ 1059 _SOC_IF_ERR_EXIT(soc_wb_engine_var_set(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, phy, i, (uint8 *)&invalid_pm_id)); 1060 break; 1061 } 1062 } 1063 } 1064 } 1065 } 1066 SOC_FUNC_RETURN; 1067 } 1068 #endif /* defined(PORTMOD_PM4X25_SUPPORT) || defined(PORTMOD_PM4X10_SUPPORT) || defined(PORTMOD_DNX_FABRIC_SUPPORT) || defined(PORTMOD_PM12X10_SUPPORT) || defined(PORTMOD_PM4x10Q_SUPPORT) || defined(PORTMOD_PM_OS_ILKN_SUPPORT) || defined(PORTMOD_PM8X50_FABRIC_SUPPORT) */ 1069 1070 1071 #if defined(PORTMOD_PM4X25_SUPPORT) || \ 1072 defined(PORTMOD_PM4X10_SUPPORT) || \ 1073 defined(PORTMOD_DNX_FABRIC_SUPPORT) || \ 1074 defined(PORTMOD_PM8X50_FABRIC_SUPPORT) || \ 1075 defined(PORTMOD_PM8X50_SUPPORT) || \ 1076 defined(PORTMOD_PM4X10_QTC_SUPPORT) 1077 STATIC 1078 int _portmod_simple_pm_add(int unit, const portmod_pm_create_info_t *pm_add_info) 1079 { 1080 portmod_pm_create_info_internal_t create_info; 1081 int specific_info_size = 0; 1082 int pm_id = 0; 1083 SOC_INIT_FUNC_DEFS; 1084 1085 PORTMOD_PBMP_ASSIGN(create_info.phys, pm_add_info->phys); 1086 create_info.type = pm_add_info->type; 1087 1088 switch(pm_add_info->type){ 1089 #ifdef PORTMOD_PM4X25_SUPPORT 1090 case portmodDispatchTypePm4x25: 1091 #ifdef PORTMOD_PM4X25TD_SUPPORT 1092 case portmodDispatchTypePm4x25td: 1093 #endif /* PORTMOD_PM4X25TD_SUPPORT */ 1094 #ifdef PORTMOD_CPM4X25_SUPPORT 1095 case portmodDispatchTypeCpm4x25: 1096 #endif /* PORTMOD_CPM4X25TD_SUPPORT */ 1097 specific_info_size = sizeof(pm_add_info->pm_specific_info.pm4x25); 1098 break; 1099 #endif /*PORTMOD_PM4X25_SUPPORT */ 1100 #ifdef PORTMOD_PM4X10_SUPPORT 1101 case portmodDispatchTypePm4x10: 1102 #ifdef PORTMOD_PM4X10TD_SUPPORT 1103 case portmodDispatchTypePm4x10td: 1104 #endif /*PORTMOD_PM4X10TD_SUPPORT */ 1105 specific_info_size = sizeof(pm_add_info->pm_specific_info.pm4x10); 1106 break; 1107 #endif /*PORTMOD_PM4X10_SUPPORT */ 1108 #ifdef PORTMOD_DNX_FABRIC_SUPPORT 1109 case portmodDispatchTypeDnx_fabric: 1110 specific_info_size = sizeof(pm_add_info->pm_specific_info.dnx_fabric); 1111 break; 1112 #endif /*PORTMOD_DNX_FABRIC_SUPPORT */ 1113 #ifdef PORTMOD_DNX_FABRIC_O_NIF_SUPPORT 1114 case portmodDispatchTypeDnx_fabric_o_nif: 1115 specific_info_size = sizeof(pm_add_info->pm_specific_info.dnx_fabric); 1116 break; 1117 #endif /*PORTMOD_DNX_FABRIC_O_NIF_SUPPORT */ 1118 #ifdef PORTMOD_PM8X50_FABRIC_SUPPORT 1119 case portmodDispatchTypePm8x50_fabric: 1120 specific_info_size = sizeof(pm_add_info->pm_specific_info.pm8x50_fabric); 1121 break; 1122 #endif /*PORTMOD_PM8X50_FABRIC_SUPPORT */ 1123 #ifdef PORTMOD_PMNULL_SUPPORT 1124 case portmodDispatchTypePmNull: 1125 specific_info_size = 0; 1126 break; 1127 #endif /*PORTMOD_PMNULL_SUPPORT */ 1128 #ifdef PORTMOD_PM_QTC_SUPPORT 1129 case portmodDispatchTypePm_qtc: 1130 specific_info_size = sizeof(pm_add_info->pm_specific_info.pm_qtc); 1131 break; 1132 #endif /*PORTMOD_PM_QTC_SUPPORT */ 1133 #ifdef PORTMOD_PM4X2P5_SUPPORT 1134 case portmodDispatchTypePm4x2p5: 1135 specific_info_size = sizeof(pm_add_info->pm_specific_info.pm4x2p5); 1136 break; 1137 #endif /*PORTMOD_PM4X2P5_SUPPORT */ 1138 #ifdef PORTMOD_PM8X50_SUPPORT 1139 case portmodDispatchTypePm8x50: 1140 specific_info_size = sizeof(pm_add_info->pm_specific_info.pm8x50); 1141 break; 1142 #endif /*PORTMOD_PM8X50_SUPPORT */ 1143 #ifdef PORTMOD_PM4X10_QTC_SUPPORT 1144 case portmodDispatchTypePm4x10_qtc: 1145 specific_info_size = sizeof(pm_add_info->pm_specific_info.pm4x10_qtc); 1146 break; 1147 #endif /*PORTMOD_PM4X10_QTC_SUPPORT */ 1148 default: 1149 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Unknown PM type %d"), pm_add_info->type)); 1150 } 1151 sal_memcpy(&create_info.pm_specific_info, &pm_add_info->pm_specific_info, specific_info_size); 1152 _SOC_IF_ERR_EXIT(_portmod_port_macro_internal_add(unit, &create_info, &pm_id)); 1153 exit: 1154 SOC_FUNC_RETURN; 1155 } 1156 #endif 1157 1158 1159 1160 #ifdef PORTMOD_PM12X10_SUPPORT 1161 STATIC 1162 int _portmod_pm12x10_add(int unit, const portmod_pm_create_info_t *pm_add_info) 1163 { 1164 int i = 0; 1165 int phy; 1166 int nof_phys = 0; 1167 int pm4x10_index = 0; 1168 portmod_pm_create_info_internal_t pm4x10_create_info; 1169 portmod_pm_create_info_internal_t pm4x25_create_info; 1170 portmod_pm_create_info_internal_t pm12x10_create_info; 1171 int pm_ids[] = {INVALID_PM_ID, INVALID_PM_ID, INVALID_PM_ID, INVALID_PM_ID, INVALID_PM_ID}; 1172 SOC_INIT_FUNC_DEFS; 1173 1174 PORTMOD_PBMP_COUNT(pm_add_info->phys, nof_phys); 1175 if(nof_phys != 12){ 1176 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("number of phys should be 12"))); 1177 } 1178 1179 /*PM4x10*/ 1180 PORTMOD_PBMP_ITER(pm_add_info->phys, phy){ 1181 if( i % 4 == 0){ 1182 if(i != 0){ 1183 _SOC_IF_ERR_EXIT(_portmod_port_macro_internal_add(unit, &pm4x10_create_info, &pm_ids[pm4x10_index])); 1184 pm4x10_index ++; 1185 } 1186 portmod_pm_create_info_internal_t_init(unit, &pm4x10_create_info); 1187 sal_memcpy(&pm4x10_create_info.pm_specific_info.pm4x10,&pm_add_info->pm_specific_info.pm12x10.pm4x10_infos[pm4x10_index], sizeof(pm4x10_create_info.pm_specific_info.pm4x10)); 1188 #ifdef PORTMOD_PM4X10TD_SUPPORT 1189 if (PORTMOD_PM12x10_F_USE_PM_TD_GET(pm_add_info->pm_specific_info.pm12x10.flags)) { 1190 pm4x10_create_info.type = portmodDispatchTypePm4x10td; 1191 } else 1192 #endif /* PORTMOD_PM4X10TD_SUPPORT */ 1193 { 1194 pm4x10_create_info.type = portmodDispatchTypePm4x10; 1195 } 1196 pm4x10_create_info.pm_specific_info.pm4x10.in_pm_12x10 = TRUE; 1197 } 1198 PORTMOD_PBMP_PORT_ADD(pm4x10_create_info.phys, phy); 1199 i++; 1200 } 1201 /*add the last one*/ 1202 _SOC_IF_ERR_EXIT(_portmod_port_macro_internal_add(unit, &pm4x10_create_info, &pm_ids[pm4x10_index])); 1203 1204 /*PM4x25*/ 1205 i = 0; 1206 portmod_pm_create_info_internal_t_init(unit, &pm4x25_create_info); 1207 #ifdef PORTMOD_PM4X25TD_SUPPORT 1208 if (PORTMOD_PM12x10_F_USE_PM_TD_GET(pm_add_info->pm_specific_info.pm12x10.flags)) { 1209 pm4x25_create_info.type = portmodDispatchTypePm4x25td; 1210 } else 1211 #endif /* PORTMOD_PM4X25TD_SUPPORT */ 1212 { 1213 pm4x25_create_info.type = portmodDispatchTypePm4x25; 1214 } 1215 pm4x25_create_info.pm_specific_info.pm4x25.in_pm_12x10 = TRUE; 1216 PORTMOD_PBMP_ITER(pm_add_info->phys, phy){ 1217 if( i == 4){ 1218 break; 1219 } 1220 PORTMOD_PBMP_PORT_ADD(pm4x25_create_info.phys, phy); 1221 i++; 1222 } 1223 _SOC_IF_ERR_EXIT(_portmod_port_macro_internal_add(unit, &pm4x25_create_info, &pm_ids[3])); 1224 /*PM12x10*/ 1225 portmod_pm_create_info_internal_t_init(unit, &pm12x10_create_info); 1226 PORTMOD_PBMP_ASSIGN(pm12x10_create_info.phys, pm_add_info->phys); 1227 pm12x10_create_info.pm_specific_info.pm12x10.flags = pm_add_info->pm_specific_info.pm12x10.flags; 1228 pm12x10_create_info.type = pm_add_info->type; 1229 pm12x10_create_info.pm_specific_info.pm12x10.blk_id = pm_add_info->pm_specific_info.pm12x10.blk_id; 1230 pm12x10_create_info.pm_specific_info.pm12x10.pm4x25 = &_pmm_info[unit]->pms[pm_ids[3]]; 1231 for(i = 0 ; i < 3 ; i++) 1232 { 1233 pm12x10_create_info.pm_specific_info.pm12x10.pm4x10[i] = &_pmm_info[unit]->pms[pm_ids[i]]; 1234 } 1235 _SOC_IF_ERR_EXIT(_portmod_port_macro_internal_add(unit, &pm12x10_create_info, &pm_ids[4])); 1236 1237 exit: 1238 if (SOC_FUNC_ERROR){ 1239 1240 } 1241 SOC_FUNC_RETURN; 1242 } 1243 #endif /*PORTMOD_PM12X10_SUPPORT*/ 1244 1245 1246 1247 1248 #ifdef PORTMOD_PM4x10Q_SUPPORT 1249 STATIC 1250 int _portmod_pm4x10q_add(int unit, const portmod_pm_create_info_t *pm_add_info) 1251 { 1252 portmod_pm_create_info_internal_t pm4x10_create_info; 1253 portmod_pm_create_info_internal_t pm4x10q_create_info; 1254 int pm4x10_id = INVALID_PM_ID; 1255 int pm4x10q_id = INVALID_PM_ID; 1256 SOC_INIT_FUNC_DEFS; 1257 1258 portmod_pm_create_info_internal_t_init(unit, &pm4x10_create_info); 1259 sal_memcpy(&pm4x10_create_info.pm_specific_info.pm4x10, &pm_add_info->pm_specific_info.pm4x10q.pm4x10_info, sizeof(pm4x10_create_info.pm_specific_info.pm4x10)); 1260 pm4x10_create_info.type = portmodDispatchTypePm4x10; 1261 PORTMOD_PBMP_ASSIGN(pm4x10_create_info.phys, pm_add_info->phys); 1262 _SOC_IF_ERR_EXIT(_portmod_port_macro_internal_add(unit, &pm4x10_create_info, &pm4x10_id)); 1263 1264 portmod_pm_create_info_internal_t_init(unit, &pm4x10q_create_info); 1265 pm4x10q_create_info.type = portmodDispatchTypePm4x10Q; 1266 PORTMOD_PBMP_ASSIGN(pm4x10q_create_info.phys, pm_add_info->phys); 1267 pm4x10q_create_info.pm_specific_info.pm4x10q.pm4x10 = &_pmm_info[unit]->pms[pm4x10_id]; 1268 pm4x10q_create_info.pm_specific_info.pm4x10q.blk_id = pm_add_info->pm_specific_info.pm4x10q.blk_id; 1269 pm4x10q_create_info.pm_specific_info.pm4x10q.core_clock_khz = pm_add_info->pm_specific_info.pm4x10q.core_clock_khz; 1270 pm4x10q_create_info.pm_specific_info.pm4x10q.qsgmii_user_acc = pm_add_info->pm_specific_info.pm4x10q.qsgmii_user_acc; 1271 pm4x10q_create_info.pm_specific_info.pm4x10q.pm4x10_user_acc = pm_add_info->pm_specific_info.pm4x10q.pm4x10_info.access.user_acc; 1272 _SOC_IF_ERR_EXIT(_portmod_port_macro_internal_add(unit, &pm4x10q_create_info, &pm4x10q_id)); 1273 1274 exit: 1275 if (SOC_FUNC_ERROR){ 1276 1277 } 1278 SOC_FUNC_RETURN; 1279 } 1280 #endif /*PORTMOD_PM4x10Q_SUPPORT*/ 1281 1282 1283 #ifdef PORTMOD_PM_OS_ILKN_SUPPORT 1284 STATIC 1285 int _portmod_os_ilkn_add(int unit, const portmod_pm_create_info_t *pm_add_info) 1286 { 1287 portmod_pm_create_info_internal_t os_ilkn_create_info; 1288 int i, j, phy, tmp_pm_id, rv = 0; 1289 pm_info_t tmp_pm_info, ilkn_pms[PORTMOD_MAX_ILKN_AGGREGATED_PMS] = {NULL}; 1290 int pm_ids[PORTMOD_MAX_ILKN_AGGREGATED_PMS] = {0}; 1291 portmod_dispatch_type_t pm_type; 1292 int pm_id= INVALID_PM_ID; 1293 SOC_INIT_FUNC_DEFS; 1294 1295 if(pm_add_info->pm_specific_info.os_ilkn.nof_aggregated_pms > PORTMOD_MAX_ILKN_AGGREGATED_PMS) 1296 { 1297 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Number of PMs(%d) should be less the %d"), pm_add_info->pm_specific_info.os_ilkn.nof_aggregated_pms, PORTMOD_MAX_ILKN_AGGREGATED_PMS)); 1298 } 1299 portmod_pm_create_info_internal_t_init(unit, &os_ilkn_create_info); 1300 os_ilkn_create_info.type = pm_add_info->type; 1301 PORTMOD_PBMP_ASSIGN(os_ilkn_create_info.phys, pm_add_info->phys); 1302 1303 for(i = 0 ; i < PORTMOD_MAX_ILKN_PORTS_PER_ILKN_PM; i++) { 1304 os_ilkn_create_info.pm_specific_info.os_ilkn.wm_high[i] = pm_add_info->pm_specific_info.os_ilkn.wm_high[i]; 1305 os_ilkn_create_info.pm_specific_info.os_ilkn.wm_low[i] = pm_add_info->pm_specific_info.os_ilkn.wm_low[i]; 1306 } 1307 os_ilkn_create_info.pm_specific_info.os_ilkn.nof_aggregated_pms = pm_add_info->pm_specific_info.os_ilkn.nof_aggregated_pms; 1308 os_ilkn_create_info.pm_specific_info.os_ilkn.pms = ilkn_pms; 1309 os_ilkn_create_info.pm_specific_info.os_ilkn.pm_ids = pm_ids; 1310 os_ilkn_create_info.pm_specific_info.os_ilkn.core_clock_khz = pm_add_info->pm_specific_info.os_ilkn.core_clock_khz; 1311 os_ilkn_create_info.pm_specific_info.os_ilkn.is_over_fabric = pm_add_info->pm_specific_info.os_ilkn.is_over_fabric; 1312 os_ilkn_create_info.pm_specific_info.os_ilkn.ilkn_core_lane_map_get = pm_add_info->pm_specific_info.os_ilkn.ilkn_core_lane_map_get; 1313 os_ilkn_create_info.pm_specific_info.os_ilkn.ilkn_pm_lane_map_get = pm_add_info->pm_specific_info.os_ilkn.ilkn_pm_lane_map_get; 1314 os_ilkn_create_info.pm_specific_info.os_ilkn.ilkn_block_index = pm_add_info->pm_specific_info.os_ilkn.ilkn_block_index; 1315 for(i = 0 ; i < pm_add_info->pm_specific_info.os_ilkn.nof_aggregated_pms; i++) 1316 { 1317 for( j = 0 ; j < MAX_PMS_PER_PHY ; j++){ 1318 phy = pm_add_info->pm_specific_info.os_ilkn.controlled_pms[i].phy; 1319 pm_type = pm_add_info->pm_specific_info.os_ilkn.controlled_pms[i].type; 1320 rv = SOC_WB_ENGINE_GET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, &tmp_pm_id, phy, j); 1321 _SOC_IF_ERR_EXIT(rv); 1322 if(tmp_pm_id == INVALID_PM_ID){ 1323 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("PM of type %d not found in PHY %d"), pm_type, phy)); 1324 } 1325 1326 rv = portmod_pm_info_from_pm_id_get(unit, tmp_pm_id, &tmp_pm_info); 1327 _SOC_IF_ERR_EXIT(rv); 1328 if(tmp_pm_info->type == pm_type){ 1329 ilkn_pms[i] = tmp_pm_info; 1330 pm_ids[i] = tmp_pm_id; 1331 break; 1332 } 1333 1334 } 1335 } 1336 _SOC_IF_ERR_EXIT(_portmod_port_macro_internal_add(unit, &os_ilkn_create_info, &pm_id)); 1337 exit: 1338 if (SOC_FUNC_ERROR){ 1339 1340 } 1341 SOC_FUNC_RETURN; 1342 } 1343 #endif /*PORTMOD_PM_OS_ILKN_SUPPORT*/ 1344 1345 #ifdef PORTMOD_DNX_FABRIC_O_NIF_SUPPORT 1346 STATIC 1347 int _portmod_dnx_fabric_add(int unit, const portmod_pm_create_info_t *pm_add_info) 1348 { 1349 portmod_pm_create_info_internal_t dnx_fabric_create_info; 1350 int j, phy, tmp_pm_id, rv = 0; 1351 pm_info_t tmp_pm_info, fabric_o_nif_pm[1] = {NULL}; 1352 portmod_dispatch_type_t pm_type; 1353 int pm_id= 0; 1354 SOC_INIT_FUNC_DEFS; 1355 1356 portmod_pm_create_info_internal_t_init(unit, &dnx_fabric_create_info); 1357 dnx_fabric_create_info.type = pm_add_info->type; 1358 SOC_PBMP_ASSIGN(dnx_fabric_create_info.phys, pm_add_info->phys); 1359 1360 dnx_fabric_create_info.pm_specific_info.dnx_fabric.pms = fabric_o_nif_pm; 1361 dnx_fabric_create_info.pm_specific_info.dnx_fabric.ref_clk = pm_add_info->pm_specific_info.dnx_fabric.ref_clk; 1362 dnx_fabric_create_info.pm_specific_info.dnx_fabric.com_clk = pm_add_info->pm_specific_info.dnx_fabric.com_clk; 1363 dnx_fabric_create_info.pm_specific_info.dnx_fabric.access = pm_add_info->pm_specific_info.dnx_fabric.access; 1364 dnx_fabric_create_info.pm_specific_info.dnx_fabric.lane_map = pm_add_info->pm_specific_info.dnx_fabric.lane_map; 1365 dnx_fabric_create_info.pm_specific_info.dnx_fabric.fw_load_method = pm_add_info->pm_specific_info.dnx_fabric.fw_load_method; 1366 dnx_fabric_create_info.pm_specific_info.dnx_fabric.external_fw_loader = pm_add_info->pm_specific_info.dnx_fabric.external_fw_loader; 1367 dnx_fabric_create_info.pm_specific_info.dnx_fabric.polarity = pm_add_info->pm_specific_info.dnx_fabric.polarity; 1368 dnx_fabric_create_info.pm_specific_info.dnx_fabric.fmac_schan_id = pm_add_info->pm_specific_info.dnx_fabric.fmac_schan_id; 1369 dnx_fabric_create_info.pm_specific_info.dnx_fabric.fsrd_schan_id = pm_add_info->pm_specific_info.dnx_fabric.fsrd_schan_id; 1370 dnx_fabric_create_info.pm_specific_info.dnx_fabric.fsrd_internal_quad = pm_add_info->pm_specific_info.dnx_fabric.fsrd_internal_quad; 1371 dnx_fabric_create_info.pm_specific_info.dnx_fabric.first_phy_offset = pm_add_info->pm_specific_info.dnx_fabric.first_phy_offset; 1372 dnx_fabric_create_info.pm_specific_info.dnx_fabric.core_index = pm_add_info->pm_specific_info.dnx_fabric.core_index; 1373 dnx_fabric_create_info.pm_specific_info.dnx_fabric.is_over_nif = pm_add_info->pm_specific_info.dnx_fabric.is_over_nif; 1374 1375 for( j = 0 ; j < MAX_PMS_PER_PHY ; j++){ 1376 phy = pm_add_info->pm_specific_info.dnx_fabric.fabric_o_nif_pm.phy; 1377 pm_type = pm_add_info->pm_specific_info.dnx_fabric.fabric_o_nif_pm.type; 1378 rv = SOC_WB_ENGINE_GET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, &tmp_pm_id, phy, j); 1379 _SOC_IF_ERR_EXIT(rv); 1380 if(tmp_pm_id == INVALID_PM_ID){ 1381 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("PM of type %d not found in PHY %d"), pm_type, phy)); 1382 } 1383 1384 rv = portmod_pm_info_from_pm_id_get(unit, tmp_pm_id, &tmp_pm_info); 1385 _SOC_IF_ERR_EXIT(rv); 1386 if(tmp_pm_info->type == pm_type){ 1387 fabric_o_nif_pm[0] = tmp_pm_info; 1388 break; 1389 } 1390 1391 } 1392 1393 dnx_fabric_create_info.pm_specific_info.dnx_fabric.pms[0] = fabric_o_nif_pm[0]; 1394 1395 1396 _SOC_IF_ERR_EXIT(_portmod_port_macro_internal_add(unit, &dnx_fabric_create_info, &pm_id)); 1397 exit: 1398 if (SOC_FUNC_ERROR){ 1399 1400 } 1401 SOC_FUNC_RETURN; 1402 } 1403 #endif /*PORTMOD_DNX_FABRIC_O_NIF_SUPPORT*/ 1404 1405 1406 int portmod_port_macro_add(int unit, const portmod_pm_create_info_t* pm_add_info) 1407 { 1408 SOC_INIT_FUNC_DEFS; 1409 1410 if(_pmm_info[unit] == NULL){ 1411 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 1412 } 1413 if(pm_add_info == NULL) { 1414 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("pm_add_info NULL parameter"))); 1415 } 1416 switch(pm_add_info->type){ 1417 #ifdef PORTMOD_PMNULL_SUPPORT 1418 case portmodDispatchTypePmNull: 1419 _SOC_IF_ERR_EXIT(_portmod_simple_pm_add(unit, pm_add_info)); 1420 break; 1421 #endif /*PORTMOD_PMNULL_SUPPORT */ 1422 #ifdef PORTMOD_PM12X10_SUPPORT 1423 case portmodDispatchTypePm12x10: 1424 #ifdef PORTMOD_PM12X10_XGS_SUPPORT 1425 case portmodDispatchTypePm12x10_xgs: 1426 #endif /*PORTMOD_PM12X10_XGS_SUPPORT */ 1427 _SOC_IF_ERR_EXIT(_portmod_pm12x10_add(unit, pm_add_info)); 1428 break; 1429 #endif /*PORTMOD_PM12X10_SUPPORT */ 1430 #ifdef PORTMOD_PM4X25_SUPPORT 1431 case portmodDispatchTypePm4x25: 1432 #ifdef PORTMOD_PM4X25TD_SUPPORT 1433 case portmodDispatchTypePm4x25td: 1434 #endif /* PORTMOD_PM4X25TD_SUPPORT */ 1435 #ifdef PORTMOD_CPM4X25_SUPPORT 1436 case portmodDispatchTypeCpm4x25: 1437 #endif /* PORTMOD_CPM4X25TD_SUPPORT */ 1438 _SOC_IF_ERR_EXIT(_portmod_simple_pm_add(unit, pm_add_info)); 1439 break; 1440 #endif /*PORTMOD_PM4X25_SUPPORT */ 1441 #ifdef PORTMOD_PM4X10_SUPPORT 1442 case portmodDispatchTypePm4x10: 1443 #ifdef PORTMOD_PM4X10TD_SUPPORT 1444 case portmodDispatchTypePm4x10td: 1445 #endif /*PORTMOD_PM4X10TD_SUPPORT */ 1446 _SOC_IF_ERR_EXIT(_portmod_simple_pm_add(unit, pm_add_info)); 1447 break; 1448 #endif /*PORTMOD_PM4X10_SUPPORT */ 1449 #ifdef PORTMOD_DNX_FABRIC_SUPPORT 1450 case portmodDispatchTypeDnx_fabric: 1451 _SOC_IF_ERR_EXIT(_portmod_simple_pm_add(unit, pm_add_info)); 1452 break; 1453 #endif /*PORTMOD_DNX_FABRIC_SUPPORT*/ 1454 #ifdef PORTMOD_DNX_FABRIC_O_NIF_SUPPORT 1455 case portmodDispatchTypeDnx_fabric_o_nif: 1456 _SOC_IF_ERR_EXIT(_portmod_dnx_fabric_add(unit, pm_add_info)); 1457 break; 1458 #endif /*PORTMOD_DNX_FABRIC_O_NIF_SUPPORT */ 1459 #ifdef PORTMOD_PM8X50_FABRIC_SUPPORT 1460 case portmodDispatchTypePm8x50_fabric: 1461 _SOC_IF_ERR_EXIT(_portmod_simple_pm_add(unit, pm_add_info)); 1462 break; 1463 #endif /*PORTMOD_PM8X50_FABRIC_SUPPORT*/ 1464 #ifdef PORTMOD_PM4x10Q_SUPPORT 1465 case portmodDispatchTypePm4x10Q: 1466 _SOC_IF_ERR_EXIT(_portmod_pm4x10q_add(unit, pm_add_info)); 1467 break; 1468 #endif /*PORTMOD_PM4x10Q_SUPPORT */ 1469 #ifdef PORTMOD_PM_QTC_SUPPORT 1470 case portmodDispatchTypePm_qtc: 1471 _SOC_IF_ERR_EXIT(_portmod_simple_pm_add(unit, pm_add_info)); 1472 break; 1473 #endif /*PORTMOD_PM_QTC_SUPPORT */ 1474 #ifdef PORTMOD_PM_OS_ILKN_SUPPORT 1475 case portmodDispatchTypePmOsILKN: 1476 #ifdef PORTMOD_PM_OS_ILKN_50G_SUPPORT 1477 case portmodDispatchTypePmOsILKN_50G: 1478 #endif /*PORTMOD_PM_OS_ILKN_50G_SUPPORT */ 1479 _SOC_IF_ERR_EXIT(_portmod_os_ilkn_add(unit, pm_add_info)); 1480 break; 1481 #endif /*PORTMOD_PM_OS_ILKN_SUPPORT */ 1482 #ifdef PORTMOD_PM4X2P5_SUPPORT 1483 case portmodDispatchTypePm4x2p5: 1484 _SOC_IF_ERR_EXIT(_portmod_simple_pm_add(unit, pm_add_info)); 1485 break; 1486 #endif /*PORTMOD_PM4X2P5_SUPPORT */ 1487 #ifdef PORTMOD_PM8X50_SUPPORT 1488 case portmodDispatchTypePm8x50: 1489 _SOC_IF_ERR_EXIT(_portmod_simple_pm_add(unit, pm_add_info)); 1490 break; 1491 #endif /*PORTMOD_PM8X50_SUPPORT*/ 1492 #ifdef PORTMOD_PM4X10_QTC_SUPPORT 1493 case portmodDispatchTypePm4x10_qtc: 1494 _SOC_IF_ERR_EXIT(_portmod_simple_pm_add(unit, pm_add_info)); 1495 break; 1496 #endif /*PORTMOD_PM4X10_QTC_SUPPORT */ 1497 default: 1498 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid PM type %d"), pm_add_info->type)); 1499 } 1500 exit: 1501 SOC_FUNC_RETURN; 1502 } 1503 1504 STATIC 1505 int portmod_validate_all_phys_in_pm(int unit, int pm_id, portmod_pbmp_t *phys, int *all_phys_in_pm){ 1506 int i, phy, other_pm_id, belongs_to_pm, rv; 1507 SOC_INIT_FUNC_DEFS; 1508 1509 *all_phys_in_pm = TRUE; 1510 PORTMOD_PBMP_ITER(*phys, phy){ 1511 belongs_to_pm = FALSE; 1512 for( i = 0 ; i < MAX_PMS_PER_PHY ; i++){ 1513 rv = SOC_WB_ENGINE_GET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, &other_pm_id, phy, i); 1514 _SOC_IF_ERR_EXIT(rv); 1515 if(pm_id == other_pm_id){ 1516 belongs_to_pm = TRUE; 1517 break; 1518 }else if(other_pm_id == INVALID_PM_ID){ 1519 /*end of list*/ 1520 break; 1521 } 1522 } 1523 if(!belongs_to_pm){ 1524 *all_phys_in_pm = FALSE; 1525 break; 1526 } 1527 } 1528 exit: 1529 SOC_FUNC_RETURN; 1530 } 1531 1532 1533 int portmod_port_add(int unit, int port, const portmod_port_add_info_t *port_add_info) 1534 { 1535 group_entry_id_t port_num; 1536 pm_info_t pm_info = NULL; 1537 int pm_id, rv, phy, phys_count = 0, sub_phy = 0, i, is_interface_supported, all_phys_in_pm = FALSE; 1538 int is_alias = 0, init_all = 0; 1539 #ifdef PORTMOD_PM4X10_SUPPORT 1540 int is_qsgmii = 0; 1541 #endif 1542 #ifdef PORTMOD_PM8X50_SUPPORT 1543 int is_init_pass1 = FALSE; 1544 #endif 1545 soc_port_if_t interface; 1546 int master_port; 1547 int add_port = FALSE; 1548 portmod_pbmp_t pm_phys; 1549 SOC_INIT_FUNC_DEFS; 1550 1551 if(_pmm_info[unit] == NULL){ 1552 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 1553 } 1554 SOC_NULL_CHECK(port_add_info); 1555 1556 init_all = (!PORTMOD_PORT_ADD_F_INIT_CORE_PROBE_GET(port_add_info) && 1557 !PORTMOD_PORT_ADD_F_INIT_PASS1_GET(port_add_info) && 1558 !PORTMOD_PORT_ADD_F_INIT_PASS2_GET(port_add_info)) ? 1 : 0; 1559 1560 #ifdef PORTMOD_PM8X50_SUPPORT 1561 PORTMOD_PBMP_ITER(port_add_info->phys, phy){ 1562 portmod_dispatch_type_t pm_type = portmodDispatchTypeCount; 1563 1564 /* coverity[check_return] */ 1565 portmod_phy_pm_type_get(unit, phy, &pm_type); 1566 /* For PM8x50 port add is done as part of init pass1 */ 1567 if (pm_type == portmodDispatchTypePm8x50) { 1568 is_init_pass1 = PORTMOD_PORT_ADD_F_INIT_PASS1_GET(port_add_info); 1569 if (is_init_pass1) { 1570 add_port = TRUE; 1571 } 1572 } 1573 } 1574 #endif /* PORTMOD_PM8X50_SUPPORT */ 1575 1576 /* do this only once (first time) per port */ 1577 if((PORTMOD_PORT_ADD_F_INIT_CORE_PROBE_GET(port_add_info)) || (init_all) || 1578 (add_port)) { 1579 /*check that port is not already in use*/ 1580 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_PM_ID_MAP, &pm_id, port); 1581 _SOC_IF_ERR_EXIT(rv); 1582 if(pm_id != INVALID_PM_ID){ 1583 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Port %d already in use"), port)); 1584 } 1585 1586 /*check for overlaps*/ 1587 if (port_add_info->interface_config.interface != SOC_PORT_IF_NULL) { 1588 if(port_add_info->interface_config.interface == SOC_PORT_IF_QSGMII){ 1589 PORTMOD_PBMP_COUNT(port_add_info->phys, phys_count); 1590 if(phys_count != 1){ 1591 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("QSGMII must has one lane"))); 1592 } 1593 #ifdef PORTMOD_PM4X10_SUPPORT 1594 is_qsgmii = 1; 1595 #endif 1596 sub_phy = port_add_info->sub_phy; 1597 } else { 1598 sub_phy = 0; /* sub phy is zero for non QSGMII */ 1599 PORTMOD_PBMP_ITER(port_add_info->phys, phy){ 1600 rv = group_member_list_group_get(&_pmm_info[unit]->ports_phys_mapping, phy*SUB_PHYS_NUM + sub_phy, &port_num); 1601 _SOC_IF_ERR_EXIT(rv); 1602 if(port_num != GROUP_MEM_LIST_END){ 1603 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_INTERFACE_TYPE_MAP, &interface, port_num); 1604 _SOC_IF_ERR_EXIT(rv); 1605 if(port_add_info->interface_config.interface == interface) { 1606 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_ALIAS_MAP, &port_num, port); 1607 _SOC_IF_ERR_EXIT(rv); 1608 is_alias = 1; 1609 break; 1610 } else { 1611 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("port %d overlap with port %d"), port, port_num)); 1612 } 1613 } 1614 } 1615 } 1616 } 1617 1618 if (!is_alias) { 1619 /*find the PM to add the port to*/ 1620 PORTMOD_PBMP_ITER(port_add_info->phys, phy){ 1621 break; 1622 } 1623 1624 if (port_add_info->interface_config.interface == SOC_PORT_IF_NULL) { 1625 pm_id = 0; /* pmNull is always added first, so it's pm_id will be always 0 */ 1626 } else { 1627 is_interface_supported = FALSE; 1628 for( i = 0 ; i < MAX_PMS_PER_PHY ; i++){ 1629 rv = SOC_WB_ENGINE_GET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, &pm_id, phy, i); 1630 _SOC_IF_ERR_EXIT(rv); 1631 if(pm_id == INVALID_PM_ID){ 1632 break; 1633 } else { 1634 rv = portmod_pm_info_from_pm_id_get(unit, pm_id, &pm_info); 1635 _SOC_IF_ERR_EXIT(rv); 1636 #ifdef PORTMOD_PM4X10_SUPPORT 1637 if (is_qsgmii) { 1638 if (pm_info->type == portmodDispatchTypePm4x10) continue; 1639 #ifdef PORTMOD_PM4X10TD_SUPPORT 1640 if (pm_info->type == portmodDispatchTypePm4x10td) continue; 1641 #endif 1642 } 1643 #endif 1644 rv = portmod_pm_interface_type_is_supported(unit, pm_info, port_add_info->interface_config.interface, &is_interface_supported); 1645 #if defined(PORTMOD_DNX_FABRIC_SUPPORT) && defined(PORTMOD_PM4X25_SUPPORT) 1646 if (pm_info->type == portmodDispatchTypePm4x25 && port_add_info->is_fabric_o_nif) 1647 { 1648 is_interface_supported = FALSE; 1649 } 1650 #endif 1651 _SOC_IF_ERR_EXIT(rv); 1652 if(is_interface_supported){ 1653 sal_memcpy(&pm_phys, &(port_add_info->phys), sizeof(pm_phys)); 1654 rv = portmod_validate_all_phys_in_pm(unit, pm_id, &pm_phys, &all_phys_in_pm); 1655 _SOC_IF_ERR_EXIT(rv); 1656 if(all_phys_in_pm){ 1657 break; 1658 } 1659 } 1660 } 1661 } 1662 if((!is_interface_supported) || (!all_phys_in_pm)){ 1663 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, (_SOC_MSG("No PM found for the specified phy %d and interface_type %d"), phy, port_add_info->interface_config.interface)); 1664 } 1665 1666 /*adding the new port to the PMM*/ 1667 PORTMOD_PBMP_ITER(port_add_info->phys, phy){ 1668 rv = group_member_list_member_add(&_pmm_info[unit]->ports_phys_mapping, port, phy*SUB_PHYS_NUM + sub_phy); 1669 _SOC_IF_ERR_EXIT(rv); 1670 } 1671 } 1672 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_PM_ID_MAP, &pm_id, port); 1673 _SOC_IF_ERR_EXIT(rv); 1674 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_INTERFACE_TYPE_MAP, &(port_add_info->interface_config.interface), port); 1675 _SOC_IF_ERR_EXIT(rv); 1676 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_ALIAS_MAP, &port, port); 1677 _SOC_IF_ERR_EXIT(rv); 1678 } else { 1679 1680 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_ALIAS_MAP, &master_port, port); 1681 _SOC_IF_ERR_EXIT(rv); 1682 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_INTERFACE_TYPE_MAP, &interface, master_port); 1683 _SOC_IF_ERR_EXIT(rv); 1684 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_PM_ID_MAP, &pm_id, master_port); 1685 _SOC_IF_ERR_EXIT(rv); 1686 1687 1688 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_INTERFACE_TYPE_MAP, &interface, port); 1689 _SOC_IF_ERR_EXIT(rv); 1690 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_PM_ID_MAP, &pm_id, port); 1691 _SOC_IF_ERR_EXIT(rv); 1692 } 1693 } else { 1694 /* all other calls to this function besides the first - check if this port is an alias */ 1695 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_ALIAS_MAP, &master_port, port); 1696 _SOC_IF_ERR_EXIT(rv); 1697 is_alias = (master_port == port) ? 0 : 1; 1698 } 1699 1700 if (!is_alias) { 1701 1702 if (port_add_info->interface_config.interface == SOC_PORT_IF_ILKN) 1703 { 1704 _SOC_IF_ERR_EXIT(portmod_pm_aggregated_update_internal(unit, pm_info, port_add_info)); 1705 } 1706 1707 /*add port in PM level */ 1708 rv = portmod_port_attach(unit, port, port_add_info); 1709 if(SOC_FAILURE(rv)){ 1710 int invalid_pm = INVALID_PM_ID, rv_warn; 1711 soc_port_if_t invalid_interface = SOC_PORT_IF_NULL; 1712 soc_port_if_t invalid_port = -1; 1713 /*remove from PMM*/ 1714 group_member_list_group_remove(&_pmm_info[unit]->ports_phys_mapping, port); 1715 rv_warn = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_PM_ID_MAP, &invalid_pm, port); 1716 if(SOC_FAILURE(rv_warn)) { 1717 LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit, "fail remove port %d from PMM_WB_PORT_PM_ID_MAP\n"), port)); 1718 } 1719 rv_warn = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_INTERFACE_TYPE_MAP, &invalid_interface, port); 1720 if(SOC_FAILURE(rv_warn)) { 1721 LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit, "fail remove port %d from PMM_WB_PORT_INTERFACE_TYPE_MAP\n"), port)); 1722 } 1723 rv_warn = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_ALIAS_MAP, &invalid_port, port); 1724 if(SOC_FAILURE(rv_warn)) { 1725 LOG_ERROR(BSL_LS_SOC_PORT, (BSL_META_U(unit, "fail remove port %d from PMM_WB_PORT_ALIAS_MAP\n"), port)); 1726 } 1727 _SOC_IF_ERR_EXIT(rv); 1728 } 1729 } 1730 1731 exit: 1732 SOC_FUNC_RETURN; 1733 } 1734 1735 1736 int portmod_port_remove(int unit, int port){ 1737 int rv; 1738 int invalid_pm = INVALID_PM_ID; 1739 int is_master = 0, is_channelized = 0, master_port = 0, new_master_port = 0, port_i = 0, master_port_i = 0, i; 1740 soc_port_if_t invalid_interface = SOC_PORT_IF_NULL; 1741 soc_port_if_t invalid_port = -1, port_interface; 1742 uint32 phys[MAX_PHYS_PER_PORT]; 1743 uint32 phys_count; 1744 1745 SOC_INIT_FUNC_DEFS; 1746 1747 rv = SOC_WB_ENGINE_GET_ARR (unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_INTERFACE_TYPE_MAP, 1748 &port_interface, port); 1749 if(rv != SOC_E_NONE){ 1750 LOG_ERROR(BSL_LS_SOC_PORT, 1751 (BSL_META_U(unit, 1752 "fail port %d interface get"), port)); 1753 } 1754 1755 /* check if master port */ 1756 _SOC_IF_ERR_EXIT(SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_ALIAS_MAP, &master_port, port)); 1757 if (port == master_port) { 1758 is_master = 1; 1759 } 1760 1761 if (is_master) { 1762 1763 /* check if channelized (if other ports exist on the same interface) and find new master port*/ 1764 for (port_i = 0; port_i < _pmm_info[unit]->max_ports; port_i++){ 1765 if (port == port_i) { 1766 continue; 1767 } 1768 _SOC_IF_ERR_EXIT(SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_ALIAS_MAP, &master_port_i, port_i)); 1769 if (master_port_i == port) { 1770 is_channelized = 1; 1771 new_master_port = port_i; 1772 break; 1773 } 1774 } 1775 if (!is_channelized) { 1776 _SOC_IF_ERR_EXIT(portmod_port_detach(unit, port)); 1777 1778 if (port_interface != SOC_PORT_IF_NULL) { 1779 /*remove from PMM*/ 1780 rv = group_member_list_group_remove(&_pmm_info[unit]->ports_phys_mapping, port); 1781 if(rv != SOC_E_NONE){ 1782 LOG_ERROR(BSL_LS_SOC_PORT, 1783 (BSL_META_U(unit, 1784 "fail remove port %d from port to phys map\n"), port)); 1785 } 1786 } 1787 } else { /* channelized interface */ 1788 1789 /* replace port mapping */ 1790 _SOC_IF_ERR_EXIT(portmod_port_replace(unit, port, new_master_port)); 1791 1792 /* update ALIAS map*/ 1793 for (port_i = 0; port_i < _pmm_info[unit]->max_ports; port_i++){ 1794 _SOC_IF_ERR_EXIT(SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_ALIAS_MAP, &master_port_i, port_i)); 1795 if (master_port_i == port) { 1796 _SOC_IF_ERR_EXIT(SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_ALIAS_MAP, &new_master_port, port_i)); 1797 } 1798 } 1799 1800 1801 /* start - update phys mapping */ 1802 rv = group_member_list_group_members_get(&_pmm_info[unit]->ports_phys_mapping, port, MAX_PHYS_PER_PORT, phys, &phys_count); 1803 _SOC_IF_ERR_EXIT(rv); 1804 if(phys_count < 1) { 1805 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("No Phys attached to port"))); 1806 } 1807 1808 /* remove old master from PMM */ 1809 if (port_interface != SOC_PORT_IF_NULL) { 1810 rv = group_member_list_group_remove(&_pmm_info[unit]->ports_phys_mapping, port); 1811 if(rv != SOC_E_NONE){ 1812 LOG_ERROR(BSL_LS_SOC_PORT, 1813 (BSL_META_U(unit, 1814 "fail remove port %d from port to phys map\n"), port)); 1815 } 1816 } 1817 1818 /*adding the new master port to the PMM*/ 1819 for(i = 0; i < phys_count; i++){ 1820 rv = group_member_list_member_add(&_pmm_info[unit]->ports_phys_mapping, new_master_port, phys[i]); 1821 _SOC_IF_ERR_EXIT(rv); 1822 } 1823 1824 /* end - update phys mapping */ 1825 } 1826 } 1827 1828 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_ALIAS_MAP, &invalid_port, port); 1829 if(rv != SOC_E_NONE){ 1830 LOG_ERROR(BSL_LS_SOC_PORT, 1831 (BSL_META_U(unit, 1832 "fail remove port %d from port alias map"), port)); 1833 } 1834 1835 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_PM_ID_MAP, &invalid_pm, port); 1836 if(rv != SOC_E_NONE){ 1837 LOG_ERROR(BSL_LS_SOC_PORT, 1838 (BSL_META_U(unit, 1839 "fail remove port %d from port to pm map\n"), port)); 1840 } 1841 rv = SOC_WB_ENGINE_SET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_INTERFACE_TYPE_MAP, &invalid_interface, port); 1842 if(rv != SOC_E_NONE){ 1843 LOG_ERROR(BSL_LS_SOC_PORT, 1844 (BSL_META_U(unit, 1845 "fail remove port %d from port to interface type map"), port)); 1846 } 1847 1848 1849 exit: 1850 SOC_FUNC_RETURN; 1851 } 1852 1853 1854 int portmod_next_wb_var_id_get(int unit, int *var_id){ 1855 SOC_INIT_FUNC_DEFS; 1856 1857 if(_pmm_info[unit] == NULL){ 1858 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 1859 } 1860 *var_id = _pmm_info[unit]->wb_vars_in_use; 1861 _pmm_info[unit]->wb_vars_in_use++; 1862 1863 exit: 1864 SOC_FUNC_RETURN; 1865 } 1866 1867 /*! 1868 * portmod_port_is_valid 1869 * 1870 * @brief Get the specific port has valid pm. 1871 * 1872 * @param [in] unit - unit id 1873 * @param [in] port - logical port 1874 * @param [out] valid - TRUE if port has valid pm_id 1875 */ 1876 int portmod_port_is_valid(int unit, int port, int* valid) { 1877 int rv, pm_id; 1878 SOC_INIT_FUNC_DEFS; 1879 1880 if(_pmm_info[unit] == NULL){ 1881 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 1882 } 1883 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_PM_ID_MAP, &pm_id, port); 1884 _SOC_IF_ERR_EXIT(rv); 1885 1886 *valid = ((pm_id >= _pmm_info[unit]->pms_in_use) || (pm_id == INVALID_PM_ID)) ? 1887 FALSE : TRUE; 1888 exit: 1889 SOC_FUNC_RETURN; 1890 } 1891 1892 /*PM info retreive*/ 1893 int portmod_port_pm_id_get(int unit, int port, int *pm_id){ 1894 int rv; 1895 SOC_INIT_FUNC_DEFS; 1896 1897 if(_pmm_info[unit] == NULL){ 1898 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 1899 } 1900 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_PM_ID_MAP, pm_id, port); 1901 _SOC_IF_ERR_EXIT(rv); 1902 if((*pm_id >= _pmm_info[unit]->pms_in_use) || (*pm_id == INVALID_PM_ID)){ 1903 _SOC_EXIT_WITH_ERR(SOC_E_NOT_FOUND, (_SOC_MSG("Valid PM Not found."))); 1904 } 1905 exit: 1906 SOC_FUNC_RETURN; 1907 } 1908 1909 int portmod_pm_id_pm_type_get(int unit, int pm_id, portmod_dispatch_type_t *type){ 1910 pm_info_t pm_info; 1911 SOC_INIT_FUNC_DEFS; 1912 _SOC_IF_ERR_EXIT(portmod_pm_info_from_pm_id_get(unit, pm_id, &pm_info)); 1913 *type = pm_info->type; 1914 exit: 1915 SOC_FUNC_RETURN; 1916 } 1917 1918 1919 int portmod_pm_info_get(int unit, int port, pm_info_t* pm_info){ 1920 int pm_id; 1921 SOC_INIT_FUNC_DEFS; 1922 1923 if(_pmm_info[unit] == NULL){ 1924 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 1925 } 1926 _SOC_IF_ERR_EXIT(portmod_port_pm_id_get(unit, port, &pm_id)); 1927 *pm_info = &_pmm_info[unit]->pms[pm_id]; 1928 if(*pm_info == NULL){ 1929 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, (_SOC_MSG("pm_info null not as expected"))); 1930 } 1931 exit: 1932 SOC_FUNC_RETURN; 1933 } 1934 1935 int portmod_pm_info_type_get(int unit, int port, portmod_dispatch_type_t type, pm_info_t* pm_info) 1936 { 1937 int pm_id, i, rv, actual_phy; 1938 uint32 phys[MAX_PHYS_PER_PORT]; 1939 uint32 phys_count; 1940 SOC_INIT_FUNC_DEFS; 1941 1942 *pm_info = NULL; 1943 1944 if(_pmm_info[unit] == NULL){ 1945 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 1946 } 1947 1948 rv = group_member_list_group_members_get(&_pmm_info[unit]->ports_phys_mapping, port, MAX_PHYS_PER_PORT, phys, &phys_count); 1949 _SOC_IF_ERR_EXIT(rv); 1950 1951 if(phys_count < 1) { 1952 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("No Phys attached to port"))); 1953 } 1954 1955 actual_phy = phys[0]/SUB_PHYS_NUM; 1956 1957 for(i = 0 ; i < MAX_PMS_PER_PHY; i++){ 1958 _SOC_IF_ERR_EXIT(soc_wb_engine_var_get(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, actual_phy, i, (uint8 *)&pm_id)); 1959 if(pm_id == INVALID_PM_ID){ 1960 break; 1961 } 1962 1963 if(type == _pmm_info[unit]->pms[pm_id].type) { 1964 *pm_info = &_pmm_info[unit]->pms[pm_id]; 1965 break; 1966 } 1967 } 1968 1969 if(*pm_info == NULL){ 1970 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, (_SOC_MSG("pm_info null not found"))); 1971 } 1972 1973 exit: 1974 SOC_FUNC_RETURN; 1975 } 1976 1977 int portmod_pm_info_from_pm_id_get(int unit, int pm_id, pm_info_t* pm_info){ 1978 SOC_INIT_FUNC_DEFS; 1979 1980 if(_pmm_info[unit] == NULL){ 1981 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 1982 } 1983 if((pm_id >= _pmm_info[unit]->pms_in_use)){ 1984 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Invalid pm"))); 1985 } 1986 *pm_info = &_pmm_info[unit]->pms[pm_id]; 1987 if(*pm_info == NULL){ 1988 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, (_SOC_MSG("pm_info null not as expected"))); 1989 } 1990 exit: 1991 SOC_FUNC_RETURN; 1992 } 1993 1994 1995 1996 1997 int portmod_port_pm_type_get(int unit, int port, int *real_port, portmod_dispatch_type_t* type){ 1998 pm_info_t pm_info; 1999 int rv; 2000 SOC_INIT_FUNC_DEFS; 2001 2002 if(_pmm_info[unit] == NULL){ 2003 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 2004 } 2005 2006 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_ALIAS_MAP, real_port, port); 2007 if (SOC_FAILURE(rv)) { 2008 _SOC_EXIT_WITH_ERR(SOC_E_PORT, ("port %d doesn't exist", port)); 2009 } 2010 2011 /* if real_port is invalid, it should not call portmod_pm_info_get with invalid port.*/ 2012 if(*real_port == INVALID_PORT) { 2013 _SOC_EXIT_WITH_ERR(SOC_E_PORT, ("port %d is not valid.", port)); 2014 } 2015 2016 _SOC_IF_ERR_EXIT(portmod_pm_info_get(unit, *real_port, &pm_info)); 2017 *type = pm_info->type; 2018 exit: 2019 SOC_FUNC_RETURN; 2020 } 2021 2022 2023 2024 int portmod_pms_num_get(int unit, int *pms_num){ 2025 SOC_INIT_FUNC_DEFS; 2026 SOC_NULL_CHECK(pms_num); 2027 if(_pmm_info[unit] == NULL){ 2028 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 2029 } 2030 *pms_num = _pmm_info[unit]->pms_in_use; 2031 exit: 2032 SOC_FUNC_RETURN; 2033 } 2034 2035 int portmod_port_interface_type_get(int unit, int port, soc_port_if_t *interface){ 2036 int rv; 2037 SOC_INIT_FUNC_DEFS; 2038 2039 if(_pmm_info[unit] == NULL){ 2040 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 2041 } 2042 2043 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_INTERFACE_TYPE_MAP, interface, port); 2044 _SOC_IF_ERR_EXIT(rv); 2045 2046 exit: 2047 SOC_FUNC_RETURN; 2048 } 2049 2050 int portmod_pm_diag_info_get(int unit, int pm_id, portmod_pm_diag_info_t *diag_info){ 2051 int i, phy, port, pm; 2052 #ifdef PORTMOD_PM4X25_SUPPORT 2053 int in_pm12x10; 2054 #endif /* PORTMOD_PM4X25_SUPPORT */ 2055 int skip = 0; 2056 SOC_INIT_FUNC_DEFS; 2057 2058 if(_pmm_info[unit] == NULL){ 2059 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 2060 } 2061 SOC_NULL_CHECK(diag_info); 2062 2063 if(pm_id >= _pmm_info[unit]->pms_in_use){ 2064 diag_info->type = portmodDispatchTypeCount; 2065 SOC_EXIT; 2066 } 2067 2068 #ifdef PORTMOD_PM4X10_QTC_SUPPORT 2069 #ifdef PORTMOD_PMNULL_SUPPORT 2070 if (_pmm_info[unit]->pms[pm_id].type == portmodDispatchTypePmNull) { 2071 } else 2072 #endif /* PORTMOD_PMNULL_SUPPORT */ 2073 { 2074 if(_pmm_info[unit]->pms[pm_id].pm_data.pm4x10_qtc_db == NULL){ 2075 diag_info->type = portmodDispatchTypeCount; 2076 SOC_EXIT; 2077 } 2078 } 2079 #endif /* PORTMOD_PM4X10_QTC_SUPPORT */ 2080 2081 PORTMOD_PBMP_CLEAR(diag_info->phys); 2082 diag_info->type = _pmm_info[unit]->pms[pm_id].type; 2083 for( phy = 0 ; phy < _pmm_info[unit]->max_phys; phy++){ 2084 for(i = 0 ; i < MAX_PMS_PER_PHY; i++){ 2085 _SOC_IF_ERR_EXIT(soc_wb_engine_var_get(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, phy, i, (uint8 *)&pm)); 2086 if(pm == INVALID_PM_ID){ 2087 break; 2088 }else if (pm == pm_id){ 2089 PORTMOD_PBMP_PORT_ADD(diag_info->phys, phy); 2090 break; 2091 } 2092 } 2093 2094 } 2095 SOC_PBMP_CLEAR(diag_info->ports); 2096 for( port = 1 ; port < _pmm_info[unit]->max_ports; port++){ 2097 _SOC_IF_ERR_EXIT(SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_PM_ID_MAP, &pm, port)); 2098 /*bsl_printf("portmod_pm_diag_info_get: unit=%d,port=%d,pm=%d,pmid=%d\r\n", unit, port, pm, pm_id);*/ 2099 if(pm == INVALID_PM_ID){ 2100 continue; 2101 }else if (pm == pm_id){ 2102 SOC_PBMP_PORT_ADD(diag_info->ports, port); 2103 continue; 2104 } 2105 } 2106 2107 /* Core info for pm4x25 when in pm12x10 not present, skip the call */ 2108 #ifdef PORTMOD_PM4X25_SUPPORT 2109 if ( 2110 #ifdef PORTMOD_PM4X25TD_SUPPORT 2111 (diag_info->type == portmodDispatchTypePm4x25td) || 2112 #endif /* PORTMOD_PM4X25TD_SUPPORT */ 2113 (diag_info->type == portmodDispatchTypePm4x25)) { 2114 _SOC_IF_ERR_EXIT(portmod_pm_is_in_pm12x10(unit, 2115 &(_pmm_info[unit]->pms[pm_id]), 2116 &in_pm12x10)); 2117 if (in_pm12x10) { 2118 skip = 1; 2119 } 2120 } 2121 #endif /* PORTMOD_PM4X25_SUPPORT */ 2122 2123 if (!skip) { 2124 _SOC_IF_ERR_EXIT(portmod_pm_core_info_get(unit, 2125 &_pmm_info[unit]->pms[pm_id], 2126 -1, &diag_info->core_info)); 2127 } 2128 2129 exit: 2130 SOC_FUNC_RETURN; 2131 } 2132 2133 /* Combo port control/status values. */ 2134 typedef enum _portmod_port_medium_e { 2135 PORTMOD_PORT_MEDIUM_NONE, /* _SHR_PORT_MEDIUM_NONE */ 2136 PORTMOD_PORT_MEDIUM_COPPER, /* _SHR_PORT_MEDIUM_COPPER */ 2137 PORTMOD_PORT_MEDIUM_FIBER, /* _SHR_PORT_MEDIUM_FIBER */ 2138 PORTMOD_PORT_MEDIUM_COUNT /* _SHR_PORT_MEDIUM_COUNT */ 2139 } _portmod_port_medium_t; 2140 2141 int portmod_port_diag_info_get(int unit, int port, portmod_port_diag_info_t *diag_info){ 2142 member_entry_id_t phys[MAX_PHYS_PER_PORT]; 2143 uint32 phys_count = 0; 2144 int rv; 2145 int i, nof_phys; 2146 #ifdef PORTMOD_CPM4X25_SUPPORT 2147 int real_port; 2148 int flags; 2149 portmod_encap_t encap; 2150 portmod_dispatch_type_t type; 2151 #endif 2152 portmod_access_get_params_t access_param; 2153 phymod_phy_access_t phy_access[6]; 2154 #ifdef PORTMOD_PM8X50_SUPPORT 2155 phymod_firmware_lane_config_t fw_lane_config; 2156 portmod_speed_config_t speed_config; 2157 #endif 2158 #if defined(PORTMOD_PM8X50_SUPPORT) || defined(PORTMOD_PM4X10_SUPPORT) 2159 uint32_t fec_enable = 0; 2160 #endif 2161 #if defined(PORTMOD_CPM4X25_SUPPORT) || defined(PORTMOD_PM8X50_SUPPORT) || defined(PORTMOD_PM4X10_SUPPORT) 2162 pm_info_t pm_info; 2163 #endif 2164 SOC_INIT_FUNC_DEFS; 2165 2166 if(_pmm_info[unit] == NULL){ 2167 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 2168 } 2169 SOC_NULL_CHECK(diag_info); 2170 rv = portmod_port_diag_info_t_init(unit, diag_info); 2171 _SOC_IF_ERR_EXIT(rv); 2172 if(port >= _pmm_info[unit]->max_ports){ 2173 diag_info->pm_id = INVALID_PM_ID; 2174 SOC_EXIT; 2175 } 2176 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_ALIAS_MAP, &diag_info->original_port, port); 2177 _SOC_IF_ERR_EXIT(rv); 2178 if(diag_info->original_port == INVALID_PORT){ 2179 diag_info->pm_id = INVALID_PM_ID; 2180 SOC_EXIT; 2181 } 2182 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_INTERFACE_TYPE_MAP, &diag_info->interface, port); 2183 _SOC_IF_ERR_EXIT(rv); 2184 rv = SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PORT_PM_ID_MAP, &diag_info->pm_id, port); 2185 _SOC_IF_ERR_EXIT(rv); 2186 rv = group_member_list_group_members_get(&_pmm_info[unit]->ports_phys_mapping, port, MAX_PHYS_PER_PORT, phys, &phys_count); 2187 _SOC_IF_ERR_EXIT(rv); 2188 PORTMOD_PBMP_CLEAR(diag_info->phys); 2189 if(phys_count != 0){ 2190 diag_info->sub_phy = phys[phys_count-1] % SUB_PHYS_NUM; 2191 for(i = 0; i < phys_count ;i++){ 2192 PORTMOD_PBMP_PORT_ADD(diag_info->phys, phys[i] / SUB_PHYS_NUM); 2193 } 2194 } 2195 2196 if (diag_info->interface == SOC_PORT_IF_NULL) 2197 return (SOC_E_NONE); 2198 2199 /* get phy polority */ 2200 rv = portmod_access_get_params_t_init(unit, &access_param); 2201 _SOC_IF_ERR_EXIT(rv); 2202 if (IS_C_PORT(unit, port)) { 2203 2204 access_param.phyn = 0; 2205 rv = portmod_port_phy_lane_access_get(unit, port, &access_param, 2206 3, &phy_access[0], &nof_phys, NULL); 2207 } else { 2208 2209 access_param.phyn = 0; 2210 rv = portmod_port_phy_lane_access_get(unit, port, &access_param, 2211 PORTMOD_MAX_ILKN_AGGREGATED_PMS, &phy_access[0], &nof_phys, NULL); 2212 } 2213 _SOC_IF_ERR_EXIT(rv); 2214 if (!SAL_BOOT_SIMULATION) 2215 #ifdef PORTMOD_CPM4X25_SUPPORT 2216 { 2217 rv = portmod_port_pm_type_get(unit, port, &real_port, &type); 2218 if(type == portmodDispatchTypeCpm4x25) { 2219 _SOC_IF_ERR_EXIT(portmod_pm_info_get(unit, real_port, &pm_info)); 2220 _SOC_IF_ERR_EXIT(portmod_port_encap_get(unit, port, &flags, &encap)); 2221 if(encap == _SHR_PORT_ENCAP_CPRI) { 2222 rv = 0; 2223 diag_info->polarity.rx_polarity = 0; 2224 diag_info->polarity.tx_polarity = 0; 2225 } else { 2226 rv = phymod_phy_polarity_get(&phy_access[0], &diag_info->polarity); 2227 _SOC_IF_ERR_EXIT(rv); 2228 } 2229 } else 2230 #else 2231 { 2232 #endif /*PORTMOD_CPM4X25_SUPPORT */ 2233 { 2234 rv = phymod_phy_polarity_get(&phy_access[0], &diag_info->polarity); 2235 _SOC_IF_ERR_EXIT(rv); 2236 } 2237 } 2238 2239 _SOC_IF_ERROR_NOT_UNAVAIL_RETURN(portmod_port_mode_get(unit, port, &diag_info->core_mode)); 2240 2241 #ifdef PORTMOD_PM8X50_SUPPORT 2242 _SOC_IF_ERR_EXIT(portmod_pm_info_from_pm_id_get(unit, diag_info->pm_id, &pm_info)); 2243 if (pm_info->type == portmodDispatchTypePm8x50) { 2244 rv = phymod_phy_firmware_lane_config_get(&phy_access[0], &fw_lane_config); 2245 _SOC_IF_ERR_EXIT(rv); 2246 diag_info->medium = fw_lane_config.MediaType; 2247 rv = portmod_port_speed_config_get(unit, port, &speed_config); 2248 _SOC_IF_ERR_EXIT(rv); 2249 diag_info->fec = speed_config.fec; 2250 } else 2251 #endif 2252 { 2253 /* CHECK CHECK WITH DORON */ 2254 diag_info->medium = PORTMOD_PORT_MEDIUM_NONE; 2255 } 2256 #ifdef PORTMOD_PM4X10_SUPPORT 2257 _SOC_IF_ERR_EXIT(portmod_pm_info_from_pm_id_get(unit, diag_info->pm_id, &pm_info)); 2258 if (pm_info->type == portmodDispatchTypePm4x10) { 2259 rv = portmod_port_fec_enable_get(unit, port, PORTMOD_INIT_F_INTERNAL_SERDES_ONLY, &fec_enable); 2260 diag_info->fec = fec_enable? PORTMOD_PORT_PHY_FEC_BASE_R : PORTMOD_PORT_PHY_FEC_NONE; 2261 } 2262 #endif 2263 exit: 2264 SOC_FUNC_RETURN; 2265 } 2266 2267 int portmod_port_first_phy_get(int unit, int port, int *first_phy, int *sub_phy){ 2268 member_entry_id_t phys[MAX_PHYS_PER_PORT]; 2269 uint32 phys_count = 0; 2270 int i; 2271 int min_phy; 2272 int rv; 2273 SOC_INIT_FUNC_DEFS; 2274 2275 if(_pmm_info[unit] == NULL){ 2276 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 2277 } 2278 2279 rv = group_member_list_group_members_get(&_pmm_info[unit]->ports_phys_mapping, port, MAX_PHYS_PER_PORT, phys, &phys_count); 2280 _SOC_IF_ERR_EXIT(rv); 2281 2282 min_phy = _pmm_info[unit]->max_phys * SUB_PHYS_NUM; 2283 /*git the minimal one*/ 2284 for(i = 0; i < phys_count ;i++){ 2285 if(phys[i] < min_phy){ 2286 min_phy = phys[i]; 2287 } 2288 } 2289 *first_phy = min_phy / SUB_PHYS_NUM; 2290 *sub_phy = min_phy % SUB_PHYS_NUM; 2291 exit: 2292 SOC_FUNC_RETURN; 2293 } 2294 2295 /*get all the PMS ids of specific phy*/ 2296 int portmod_phy_pms_ids_get(int unit, int phy, int max_pms, int *nof_pms, portmod_dispatch_type_t *pms_type, int *pms_ids){ 2297 pm_info_t pms_info[MAX_PMS_PER_PHY]; 2298 int i = 0; 2299 SOC_INIT_FUNC_DEFS; 2300 2301 _SOC_IF_ERR_EXIT(portmod_phy_pms_info_get(unit, phy, max_pms, pms_info, nof_pms, pms_ids)); 2302 for( i = 0 ; i < *nof_pms ; i++){ 2303 pms_type[i] = pms_info[i]->type ; 2304 } 2305 2306 exit: 2307 SOC_FUNC_RETURN; 2308 } 2309 2310 /*get all the PMS of specific phy*/ 2311 int portmod_phy_pms_info_get(int unit, int phy, int max_pms, pm_info_t *pms_info, int *nof_pms, int *pms_ids){ 2312 int pm_id = 0; 2313 int i = 0; 2314 SOC_INIT_FUNC_DEFS; 2315 2316 *nof_pms = 0; 2317 for( i = 0 ; i < MAX_PMS_PER_PHY ; i++){ 2318 _SOC_IF_ERR_EXIT(soc_wb_engine_var_get(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, phy, i, (uint8 *)&pm_id)); 2319 if(pm_id == INVALID_PM_ID){ 2320 break; 2321 } 2322 if (max_pms == *nof_pms){ 2323 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("Array supplied has less entries than needed"))); 2324 } 2325 _SOC_IF_ERR_EXIT(portmod_pm_info_from_pm_id_get(unit, pm_id, &pms_info[*nof_pms])); 2326 pms_ids[*nof_pms] = pm_id; 2327 *nof_pms += 1; 2328 } 2329 exit: 2330 SOC_FUNC_RETURN; 2331 } 2332 2333 int portmod_ext_phy_lane_attach(int unit, int iphy, int phyn, const portmod_lane_connection_t* lane_connection) 2334 { 2335 int i = 0, nof_pms = 0; 2336 pm_info_t pms_info[MAX_PMS_PER_PHY] = {NULL,}; 2337 int pms_ids[MAX_PMS_PER_PHY] = {0}; 2338 SOC_INIT_FUNC_DEFS; 2339 2340 /* Validate input parameters */ 2341 _SOC_IF_ERR_EXIT(portmod_phy_pms_info_get(unit, iphy, MAX_PMS_PER_PHY, pms_info, &nof_pms,pms_ids)); 2342 if (0 == nof_pms){ 2343 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("The input phy is not attached to any port macros"))); 2344 } 2345 2346 /* Attach the external phy to the phy chain of each port macro which uses the input phy */ 2347 for( i = 0 ; i < nof_pms ; i++){ 2348 _SOC_IF_ERR_EXIT(portmod_ext_phy_lane_attach_to_pm(unit, pms_info[i], iphy, phyn, lane_connection)); 2349 } 2350 SOC_FUNC_RETURN; 2351 exit: 2352 /* Rollingback the attach operations because of an error */ 2353 --i; 2354 for( ; i >= 0 ; --i) { 2355 portmod_ext_phy_lane_detach_from_pm(unit, pms_info[i], iphy, phyn, NULL); 2356 } 2357 SOC_FUNC_RETURN; 2358 } 2359 2360 int portmod_ext_phy_lane_detach(int unit, int iphy, int phyn) 2361 { 2362 int i = 0, nof_pms = 0; 2363 pm_info_t pms_info[MAX_PMS_PER_PHY] = {NULL,}; 2364 int pms_ids[MAX_PMS_PER_PHY] = {0}; 2365 portmod_lane_connection_t lane_connection[MAX_PMS_PER_PHY]; 2366 2367 SOC_INIT_FUNC_DEFS; 2368 2369 /* Validate input parameters */ 2370 _SOC_IF_ERR_EXIT(portmod_phy_pms_info_get(unit, iphy, MAX_PMS_PER_PHY, pms_info, &nof_pms,pms_ids)); 2371 if (0 == nof_pms){ 2372 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("The input phy is not attached to any port macros"))); 2373 } 2374 /* Detach the last external phy in the phy chain from each port macro which uses the input phy */ 2375 for( i = 0 ; i < nof_pms ; i++){ 2376 _SOC_IF_ERR_EXIT(portmod_ext_phy_lane_detach_from_pm(unit, pms_info[i], iphy, phyn, &lane_connection[i])); 2377 } 2378 SOC_FUNC_RETURN; 2379 exit: 2380 SOC_FUNC_RETURN; 2381 } 2382 2383 int portmod_xphy_lane_attach(int unit, int iphy, int phyn, const portmod_xphy_lane_connection_t* lane_conn) 2384 { 2385 int i = 0, nof_pms = 0; 2386 pm_info_t pms_info[MAX_PMS_PER_PHY] = {NULL,}; 2387 int pms_ids[MAX_PMS_PER_PHY] = {0}; 2388 SOC_INIT_FUNC_DEFS; 2389 2390 /* Validate input parameters */ 2391 _SOC_IF_ERR_EXIT(portmod_phy_pms_info_get(unit, iphy, MAX_PMS_PER_PHY, pms_info, &nof_pms,pms_ids)); 2392 if (0 == nof_pms){ 2393 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("The input phy is not attached to any port macros"))); 2394 } 2395 2396 /* Attach the external phy to the phy chain of each port macro which uses the input phy */ 2397 for( i = 0 ; i < nof_pms ; i++){ 2398 _SOC_IF_ERR_EXIT(portmod_xphy_lane_attach_to_pm(unit, pms_info[i], iphy, phyn, lane_conn)); 2399 } 2400 SOC_FUNC_RETURN; 2401 exit: 2402 /* Rollingback the attach operations because of an error */ 2403 --i; 2404 for( ; i >= 0 ; --i) { 2405 portmod_xphy_lane_detach_from_pm(unit, pms_info[i], iphy, phyn, NULL); 2406 } 2407 SOC_FUNC_RETURN; 2408 } 2409 2410 int portmod_xphy_lane_detach(int unit, int iphy, int phyn) 2411 { 2412 int i = 0, nof_pms = 0; 2413 pm_info_t pms_info[MAX_PMS_PER_PHY] = {NULL,}; 2414 int pms_ids[MAX_PMS_PER_PHY] = {0}; 2415 portmod_xphy_lane_connection_t lane_conn[MAX_PMS_PER_PHY]; 2416 2417 SOC_INIT_FUNC_DEFS; 2418 2419 /* Validate input parameters */ 2420 _SOC_IF_ERR_EXIT(portmod_phy_pms_info_get(unit, iphy, MAX_PMS_PER_PHY, pms_info, &nof_pms,pms_ids)); 2421 if (0 == nof_pms){ 2422 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, (_SOC_MSG("The input phy is not attached to any port macros"))); 2423 } 2424 /* Detach the last external phy in the phy chain from each port macro which uses the input phy */ 2425 for( i = 0 ; i < nof_pms ; i++){ 2426 _SOC_IF_ERR_EXIT(portmod_xphy_lane_detach_from_pm(unit, pms_info[i], iphy, phyn, &lane_conn[i])); 2427 } 2428 SOC_FUNC_RETURN; 2429 exit: 2430 SOC_FUNC_RETURN; 2431 } 2432 2433 int portmod_max_pms_get(int unit, int* max_pms) 2434 { 2435 SOC_INIT_FUNC_DEFS; 2436 if(_pmm_info[unit] == NULL){ 2437 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 2438 } 2439 *max_pms = _pmm_info[unit]->max_pms; 2440 exit: 2441 SOC_FUNC_RETURN; 2442 } 2443 2444 int portmod_phy_pm_type_get(int unit, int phy, portmod_dispatch_type_t *type) 2445 { 2446 int nof_pms = 0; 2447 pm_info_t pms_info[MAX_PMS_PER_PHY]; 2448 int pms_ids[MAX_PMS_PER_PHY] = {0}; 2449 2450 SOC_INIT_FUNC_DEFS; 2451 2452 _SOC_IF_ERR_EXIT(portmod_phy_pms_info_get(unit, phy, MAX_PMS_PER_PHY, pms_info, &nof_pms,pms_ids)); 2453 2454 if (0 == nof_pms){ 2455 _SOC_EXIT_WITH_ERR(SOC_E_PORT, (_SOC_MSG("The input phy is not attached to any port macros"))); 2456 } 2457 2458 *type = pms_info[nof_pms-1]->type; 2459 2460 exit: 2461 SOC_FUNC_RETURN; 2462 } 2463 2464 /* 2465 * Function: 2466 * portmod_pm_port_pll_div_get 2467 * Purpose: 2468 * This function will be called during speed is changed or flexport. 2469 * This function returns pll_div value by looking up the static 2470 * table in pm4x10 and pm4x25. But this funciton might be called 2471 * before port is attached (in flexport scenario). In that case, 2472 * port number may be invalid(-1), then the pll_div only can be 2473 * gotten from static table, and this function can't access registers 2474 * or Warmboot DB. In speed change scenario, there is no this limitation. 2475 * 2476 * portmod_port_pll_div_get is added just for the purpose to add 2477 * function pointer [pm_type]_port_pll_div_get to each portmod_dispatch_t 2478 * driver, such as portmod_pm4x10_driver, portmod_pm4x25_driver. 2479 * 2480 * Parameters: 2481 * unit - (IN) Unit number 2482 * port - (IN) logical port 2483 * phy_port - (IN) physical port 2484 * pll_div - (OUT) pll div 2485 * 2486 * Returns: 2487 * Note: 2488 */ 2489 int portmod_pm_port_pll_div_get(int unit, int port, int phy_port, 2490 const portmod_port_resources_t* port_resource, 2491 uint32_t* pll_div) 2492 { 2493 portmod_dispatch_type_t __type__ = portmodDispatchTypeCount; 2494 int __rv__; 2495 int i, pm_id, rv; 2496 pm_info_t pm_info; 2497 2498 SOC_INIT_FUNC_DEFS; 2499 2500 for (i = 0; i < MAX_PMS_PER_PHY; i++) { 2501 rv = SOC_WB_ENGINE_GET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, &pm_id, phy_port, i); 2502 _SOC_IF_ERR_EXIT(rv); 2503 if (pm_id != INVALID_PM_ID) { 2504 rv = portmod_pm_info_from_pm_id_get(unit, pm_id, &pm_info); 2505 _SOC_IF_ERR_EXIT(rv); 2506 break; 2507 } 2508 } 2509 if (pm_id == INVALID_PM_ID) { 2510 __rv__ = SOC_E_PARAM; 2511 _SOC_IF_ERR_EXIT(__rv__); 2512 } 2513 2514 __type__ = (pm_info)->type; 2515 if(NULL != __portmod__dispatch__[__type__]->f_portmod_port_pll_div_get) { 2516 __rv__ = __portmod__dispatch__[__type__]->f_portmod_port_pll_div_get(unit, port, pm_info, port_resource, pll_div); 2517 _SOC_IF_ERR_EXIT(__rv__); 2518 } else { 2519 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, ("portmod_port_pll_div_get isn't implemented for driver type")); 2520 } 2521 2522 exit: 2523 SOC_FUNC_RETURN; 2524 } 2525 2526 /*! 2527 * portmod_phy_pm_id_get 2528 * 2529 * @brief Geven the physical port ID, return the associated PM ID 2530 * 2531 * @param [in] unit - unit id 2532 * @param [in] pport - physical port 2533 * @param [out] pm_id - PM ID associated with the physical port 2534 */ 2535 int portmod_phy_pm_id_get(int unit, int pport, int *pm_id) 2536 { 2537 int i; 2538 SOC_INIT_FUNC_DEFS; 2539 2540 /* get the PM id from PHY->PM map */ 2541 for(i = 0 ; i < MAX_PMS_PER_PHY; i++){ 2542 _SOC_IF_ERR_EXIT(soc_wb_engine_var_get(unit, SOC_WB_ENGINE_PORTMOD, 2543 PMM_WB_PHY_PM_MAP, pport, i, 2544 (uint8 *)pm_id)); 2545 if ((*pm_id) != INVALID_PM_ID) 2546 break; 2547 } 2548 exit: 2549 SOC_FUNC_RETURN; 2550 } 2551 2552 int portmod_pm_supported_vcos_get(int unit, int port, portmod_dispatch_type_t pm_type, 2553 const portmod_vcos_speed_config_t* speed_config_list, 2554 int size, portmod_dual_vcos_t* dual_vco) 2555 { 2556 portmod_dispatch_type_t __type__ = portmodDispatchTypeCount; 2557 pm_info_t pm_info; 2558 int __rv__; 2559 2560 SOC_INIT_FUNC_DEFS; 2561 __type__ = pm_type; 2562 if(__type__ >= portmodDispatchTypeCount) { 2563 _SOC_EXIT_WITH_ERR(SOC_E_PARAM, ("Driver is out of range")); 2564 } 2565 pm_info = NULL; 2566 2567 if(NULL != __portmod__dispatch__[__type__]->f_portmod_port_vcos_get) { 2568 __rv__ = __portmod__dispatch__[__type__]->f_portmod_port_vcos_get(unit, port, pm_info, speed_config_list, size, dual_vco); 2569 _SOC_IF_ERR_EXIT(__rv__); 2570 } else { 2571 _SOC_EXIT_WITH_ERR(SOC_E_UNAVAIL, ("portmod_port_vcos_get isn't implemented for driver type")); 2572 } 2573 2574 exit: 2575 SOC_FUNC_RETURN; 2576 } 2577 2578 static int portmod_periodic_event(int unit, void* user_data) 2579 { 2580 int port_i, rv, rv_failure, is_quit_signaled; 2581 portmod_periodic_event_f port_callback; 2582 SOC_INIT_FUNC_DEFS; 2583 2584 /* Lock in case ports_callback DB is update while executing port operation */ 2585 rv_failure = SOC_E_NONE; 2586 2587 for (port_i=0 ; port_i<_pmm_info[unit]->max_ports ; port_i++) { 2588 2589 _pmm_info[unit]->periodic.current_working_port = port_i; 2590 2591 _SOC_IF_ERR_EXIT(periodic_event_is_quit_signaled_get(_pmm_info[unit]->periodic.periodic_handler, &is_quit_signaled)); 2592 2593 if (is_quit_signaled) { 2594 break; 2595 } 2596 2597 port_callback = _pmm_info[unit]->periodic.ports_periodic[port_i].ports_callback; 2598 2599 if(port_callback != NULL) { 2600 rv = port_callback(unit, port_i); 2601 2602 /* iterate over all port - but rememebr if there was a failrue */ 2603 if (SOC_FAILURE(rv)) { 2604 LOG_ERROR(BSL_LS_SOC_PORT, 2605 (BSL_META_U(unit, 2606 "portmod_periodic_event failed for port %d"), port_i)); 2607 rv_failure = rv; 2608 } 2609 } 2610 2611 2612 } 2613 2614 _SOC_IF_ERR_EXIT(rv_failure); 2615 2616 exit: 2617 _pmm_info[unit]->periodic.current_working_port = -1; 2618 SOC_FUNC_RETURN; 2619 } 2620 2621 /*! 2622 * portmod_port_callback_update_internal 2623 * 2624 * @brief add or remove per port periodic callback 2625 * 2626 * @param unit - unit # 2627 * @param port - port to register or remove callback 2628 * @param callback - periodi callback, use NULL for remove 2629 * @param interval - expected period (actual period will be 2630 * equal or smaller from given value). Use 0 for 2631 * remove. 2632 * 2633 * @return int 2634 */ 2635 #define _PORTMOD_MIN_INTERVAL_NOT_FOUND -2 2636 2637 static int portmod_port_callback_update_internal(int unit, int port, portmod_periodic_event_f callback, int interval) 2638 { 2639 int port_i; 2640 int min_interval=_PORTMOD_MIN_INTERVAL_NOT_FOUND; /*-2 indicates first value*/ 2641 SOC_INIT_FUNC_DEFS; 2642 2643 /* Update DB*/ 2644 _pmm_info[unit]->periodic.ports_periodic[port].ports_callback = callback; 2645 _pmm_info[unit]->periodic.ports_periodic[port].interval = interval; 2646 2647 2648 /* calc min interval and num of callbacks */ 2649 for (port_i=0 ; port_i<_pmm_info[unit]->max_ports ; port_i++) { 2650 2651 if (_pmm_info[unit]->periodic.ports_periodic[port_i].ports_callback != NULL) { 2652 2653 /* get minimum interval */ 2654 if (_pmm_info[unit]->periodic.ports_periodic[port_i].interval != sal_sem_FOREVER) { /*ignore forever as it's -1 and will always be the minimum...*/ 2655 if (min_interval == _PORTMOD_MIN_INTERVAL_NOT_FOUND) { 2656 min_interval = _pmm_info[unit]->periodic.ports_periodic[port_i].interval; 2657 } 2658 2659 if (_pmm_info[unit]->periodic.ports_periodic[port_i].interval < min_interval) { 2660 min_interval = _pmm_info[unit]->periodic.ports_periodic[port_i].interval; 2661 } 2662 } 2663 } 2664 } 2665 2666 /* if didn't found ant minimum but there is FOREVER interval - use the FOREVER */ 2667 if (min_interval == _PORTMOD_MIN_INTERVAL_NOT_FOUND) { 2668 min_interval = sal_sem_FOREVER; 2669 } 2670 2671 /* Update the interval anyway - if no callback the period should be set to forever*/ 2672 _SOC_IF_ERR_EXIT(periodic_event_interval_set(_pmm_info[unit]->periodic.periodic_handler, min_interval)); 2673 2674 exit: 2675 SOC_FUNC_RETURN; 2676 2677 } 2678 2679 /* see .h file */ 2680 int portmod_port_periodic_callback_unregister(int unit, int port) 2681 { 2682 soc_timeout_t to; 2683 int is_callback_conetxt; 2684 SOC_INIT_FUNC_DEFS; 2685 2686 sal_mutex_take(_pmm_info[unit]->periodic.periodic_lock, sal_mutex_FOREVER); 2687 2688 _SOC_IF_ERR_EXIT(portmod_port_callback_update_internal(unit, port, NULL, 0)); 2689 2690 /* make sure current port isn't in work currently 2691 - for the case callback for current port is already running before unregister was called*/ 2692 _SOC_IF_ERR_EXIT(periodic_event_is_periodic_context_get(_pmm_info[unit]->periodic.periodic_handler, &is_callback_conetxt)); 2693 if (!is_callback_conetxt) { 2694 2695 soc_timeout_init(&to, SECOND_USEC /*1 sec*/, 100); 2696 2697 while (_pmm_info[unit]->periodic.current_working_port == port) { 2698 if (soc_timeout_check(&to)) { 2699 _SOC_EXIT_WITH_ERR(SOC_E_TIMEOUT,(_SOC_MSG("Failed to unregister port %d"), port)); 2700 break; 2701 } 2702 } 2703 } 2704 2705 exit: 2706 sal_mutex_give(_pmm_info[unit]->periodic.periodic_lock); 2707 SOC_FUNC_RETURN; 2708 2709 } 2710 2711 /* see .h file */ 2712 int portmod_port_periodic_callback_register(int unit, int port, portmod_periodic_event_f callback, int interval) 2713 { 2714 int is_active; 2715 SOC_INIT_FUNC_DEFS; 2716 2717 sal_mutex_take(_pmm_info[unit]->periodic.periodic_lock, sal_mutex_FOREVER); 2718 2719 /* first unregister previous callback to allow safe exit before moving to bew callback */ 2720 _SOC_IF_ERR_EXIT(portmod_port_periodic_callback_unregister(unit, port)); 2721 2722 /* Update new callback */ 2723 _SOC_IF_ERR_EXIT(portmod_port_callback_update_internal(unit, port, callback, interval)); 2724 2725 /* If thread never started - start it now */ 2726 _SOC_IF_ERR_EXIT(periodic_event_is_active_get(_pmm_info[unit]->periodic.periodic_handler, &is_active)); 2727 2728 if (!is_active) { 2729 _SOC_IF_ERR_EXIT(periodic_event_start(_pmm_info[unit]->periodic.periodic_handler)); 2730 } 2731 2732 exit: 2733 sal_mutex_give(_pmm_info[unit]->periodic.periodic_lock); 2734 SOC_FUNC_RETURN; 2735 } 2736 2737 /* see .h file */ 2738 int portmod_port_periodic_interval_get(int unit, int* interval) 2739 { 2740 SOC_INIT_FUNC_DEFS; 2741 2742 _SOC_IF_ERR_EXIT(periodic_event_interval_get(_pmm_info[unit]->periodic.periodic_handler, interval)); 2743 2744 exit: 2745 SOC_FUNC_RETURN; 2746 } 2747 2748 2749 #ifdef CPRIMOD_SUPPORT 2750 int portmod_cpri_port_interrupt_callback_register(int unit, 2751 portmod_cpri_port_intr_type_t cpri_intr_type, 2752 portmod_cpri_port_interrupt_callback_t callback, 2753 void* cb_data) 2754 { 2755 SOC_INIT_FUNC_DEFS; 2756 2757 _SOC_IF_ERR_EXIT(cprimod_cpri_port_interrupt_callback_register(unit, 2758 cpri_intr_type, callback, cb_data)); 2759 2760 2761 exit: 2762 SOC_FUNC_RETURN; 2763 2764 } 2765 #endif /* CPRIMOD_SUPPORT */ 2766 2767 #ifdef CPRIMOD_SUPPORT 2768 int portmod_cpri_port_interrupt_callback_unregister(int unit, 2769 portmod_cpri_port_intr_type_t cpri_intr_type, 2770 cprimod_cpri_port_interrupt_callback_t callback) 2771 { 2772 SOC_INIT_FUNC_DEFS; 2773 2774 _SOC_IF_ERR_EXIT 2775 (cprimod_cpri_port_interrupt_callback_unregister(unit, 2776 cpri_intr_type, callback)); 2777 exit: 2778 SOC_FUNC_RETURN; 2779 2780 } 2781 #endif /* CPRIMOD_SUPPORT */ 2782 2783 2784 /* 2785 * This functions takes the actual hardware PM Id core_num as input and 2786 * returns the sw PM id mapped in the PortMod library. The function does 2787 * not return error and the function caller should initialize pm_id to -1. 2788 */ 2789 int portmod_core_pm_id_get(int unit, int core_num, int *pm_id) 2790 { 2791 int i = 0; 2792 pm_info_t pm_info; 2793 int pm_core_num = 0; 2794 2795 SOC_INIT_FUNC_DEFS; 2796 2797 if(_pmm_info[unit] == NULL){ 2798 _SOC_EXIT_WITH_ERR(SOC_E_INIT, 2799 (_SOC_MSG("Portmod was not initialized for the unit"))); 2800 } 2801 2802 for (i = 0; i < _pmm_info[unit]->pms_in_use; i++) { 2803 2804 _SOC_IF_ERR_EXIT(portmod_pm_info_from_pm_id_get(unit, i, &pm_info)); 2805 2806 if (NULL == __portmod__dispatch__[pm_info->type]-> 2807 f_portmod_pm_core_num_get) { 2808 continue; 2809 } 2810 2811 _SOC_IF_ERR_EXIT(portmod_pm_core_num_get(unit, pm_info, &pm_core_num)); 2812 2813 if (core_num == pm_core_num) { 2814 *pm_id = i; 2815 break; 2816 } 2817 } 2818 2819 if (i == _pmm_info[unit]->pms_in_use) { 2820 _SOC_EXIT_WITH_ERR(SOC_E_INIT, 2821 (_SOC_MSG("SW PM Id not for HW PM Id[%d] found!!"), core_num)); 2822 } 2823 2824 exit: 2825 SOC_FUNC_RETURN; 2826 } 2827 2828 /* see .h file */ 2829 int 2830 portmod_ilkn_block_phys_set(int unit, int ilkn_block_id, portmod_pbmp_t phys, int enable) 2831 { 2832 int i = 0; 2833 int phy, pm_id, current_val; 2834 uint8 free_slot_found; 2835 uint32 invalid_pm_id = INVALID_PM_ID; 2836 SOC_INIT_FUNC_DEFS; 2837 2838 2839 /*The PM-ID is taken from the WB-SW state */ 2840 _SOC_IF_ERR_EXIT(SOC_WB_ENGINE_GET_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_ILKN_PM_MAP, &pm_id, ilkn_block_id)); 2841 2842 if(!SOC_WARM_BOOT(unit)){ 2843 /*add to map just in case of cold boot*/ 2844 if (enable) 2845 { 2846 PORTMOD_PBMP_ITER(phys, phy){ 2847 free_slot_found = FALSE; 2848 for(i = 0 ; i < MAX_PMS_PER_PHY; i++){ 2849 _SOC_IF_ERR_EXIT(soc_wb_engine_var_get(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, phy, i, (uint8 *)¤t_val)); 2850 if(current_val == INVALID_PM_ID ){ 2851 _SOC_IF_ERR_EXIT(soc_wb_engine_var_set(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, phy, i, (uint8 *)&pm_id)); 2852 free_slot_found = TRUE; 2853 break; 2854 } 2855 } 2856 if(!free_slot_found){ 2857 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, (_SOC_MSG("phy (%d) already used by the maximum number of pms %d"), phy, MAX_PMS_PER_PHY)); 2858 } 2859 } 2860 } 2861 else 2862 { 2863 /*clean the map*/ 2864 PORTMOD_PBMP_ITER(phys, phy){ 2865 /* coverity[dead_error_line] */ 2866 for(i = 0 ; !_rv && (i < MAX_PMS_PER_PHY); i++){ 2867 _rv = soc_wb_engine_var_get(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, phy, i, (uint8 *)¤t_val); 2868 if(!_rv && (current_val == pm_id)){ 2869 _SOC_IF_ERR_EXIT(soc_wb_engine_var_set(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, phy, i, (uint8 *)&invalid_pm_id)); 2870 break; 2871 } 2872 } 2873 } 2874 } 2875 } 2876 exit: 2877 SOC_FUNC_RETURN; 2878 } 2879 2880 /*! 2881 * portmod_pm_aggregated_update_internal 2882 * 2883 * @brief update the aggregated PM info for ilkn port 2884 * Holds an array of portmacros assigned to this port (used by ilkn) 2885 * Each element describes the type of the PM, and the first phy. 2886 * 2887 * @param unit - unit # 2888 * @param pm_info - port macro info needed to be update 2889 * @param port_add_info - pointer to port add info, contains information about port macros (type and phys) 2890 * @return int 2891 */ 2892 static int portmod_pm_aggregated_update_internal(int unit, pm_info_t pm_info, const portmod_port_add_info_t *port_add_info) 2893 { 2894 pm_info_t tmp_pm_info = NULL; 2895 pm_info_t ilkn_pms[PORTMOD_MAX_ILKN_AGGREGATED_PMS] = {NULL}; 2896 int pm_ids[PORTMOD_MAX_ILKN_AGGREGATED_PMS] = {0}; 2897 int tmp_pm_id, phy, i, j; 2898 portmod_dispatch_type_t pm_type; 2899 2900 SOC_INIT_FUNC_DEFS; 2901 2902 if (port_add_info == NULL) 2903 { 2904 _SOC_EXIT_WITH_ERR(SOC_E_INTERNAL, (_SOC_MSG("port_add_info is NULL"))); 2905 } 2906 2907 for(i = 0 ; i < port_add_info->nof_aggregated_pms; i++) 2908 { 2909 for( j = 0 ; j < MAX_PMS_PER_PHY ; j++){ 2910 phy = port_add_info->controlled_pms[i].phy; 2911 pm_type = port_add_info->controlled_pms[i].type; 2912 _SOC_IF_ERR_EXIT(SOC_WB_ENGINE_GET_DBL_ARR(unit, SOC_WB_ENGINE_PORTMOD, PMM_WB_PHY_PM_MAP, &tmp_pm_id, phy, j)); 2913 if(tmp_pm_id == INVALID_PM_ID) 2914 { 2915 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("PM of type %d not found in PHY %d"), pm_type, phy)); 2916 } 2917 _SOC_IF_ERR_EXIT(portmod_pm_info_from_pm_id_get(unit, tmp_pm_id, &tmp_pm_info)); 2918 if(tmp_pm_info->type == pm_type){ 2919 ilkn_pms[i] = tmp_pm_info; 2920 pm_ids[i] = tmp_pm_id; 2921 break; 2922 } 2923 2924 } 2925 } 2926 _SOC_IF_ERR_EXIT(portmod_pm_aggregated_update(unit, pm_info, port_add_info->ilkn_core_id, port_add_info->nof_aggregated_pms, ilkn_pms, pm_ids)); 2927 2928 exit: 2929 SOC_FUNC_RETURN; 2930 2931 } 2932 2933 int portmod_port_phys_get(int unit, int port,portmod_pbmp_t *phys){ 2934 2935 member_entry_id_t phys_internal[MAX_PHYS_PER_PORT]; 2936 uint32 phys_count = 0; 2937 int i; 2938 int phy; 2939 int rv; 2940 SOC_INIT_FUNC_DEFS; 2941 2942 if(_pmm_info[unit] == NULL){ 2943 _SOC_EXIT_WITH_ERR(SOC_E_INIT, (_SOC_MSG("Portmod was not initialized for the unit"))); 2944 } 2945 2946 rv = group_member_list_group_members_get(&_pmm_info[unit]->ports_phys_mapping, port, MAX_PHYS_PER_PORT, phys_internal, &phys_count); 2947 _SOC_IF_ERR_EXIT(rv); 2948 2949 PORTMOD_PBMP_CLEAR(*phys); 2950 2951 for(i = 0; i < phys_count ;i++){ 2952 phy = phys_internal[i] / SUB_PHYS_NUM; 2953 PORTMOD_PBMP_PORT_ADD(*phys, phy); 2954 } 2955 exit: 2956 SOC_FUNC_RETURN; 2957 2958 } 2959 2960 2961 #undef _ERR_MSG_MODULE_NAME