openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

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 *)&current_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 *)&current_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 *)&current_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 *)&current_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