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

tsn.c (561400B)


      1  /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  */
      7 #include <shared/bsl.h>
      8 #include <soc/drv.h>
      9 #include <soc/scache.h>
     10 #include <soc/profile_mem.h>
     11 #include <bcm/tsn.h>
     12 #include <bcm/port.h>
     13 #include <bcm/error.h>
     14 #include <bcm/types.h>
     15 #include <bcm_int/common/multicast.h>
     16 #include <bcm_int/esw_dispatch.h>
     17 #include <bcm_int/esw/tsn.h>
     18 #include <bcm_int/esw/tsn_taf.h>
     19 #include <bcm_int/esw/tsn_stat.h>
     20 #include <bcm_int/esw_dispatch.h>
     21 #if defined(BCM_GREYHOUND2_SUPPORT)
     22 #include <bcm_int/esw/greyhound2.h>
     23 #endif /* BCM_GREYHOUND2_SUPPORT */
     24 #include <bcm_int/esw/tsn_stat.h>
     25 #include <bcm/module.h>
     26 #include <bcm_int/esw/switch.h>
     27 
     28 #if defined(BCM_TSN_SUPPORT)
     29 /* Function Enter/Leave Tracing */
     30 #define TSN_FUNCTION_TRACE(_u_, _str_)                                        \
     31     do {                                                                      \
     32         LOG_DEBUG(BSL_LS_BCM_TSN,                                             \
     33                   (BSL_META_U((_u_),                                          \
     34                               "%s: " _str_ "\n"), __FUNCTION__));             \
     35     } while (0)
     36 
     37 /* Device Information NULL error handling */
     38 #define TSN_CHECK_NULL_DEV_INSTANCE(_u_, _instance_)                          \
     39     do {                                                                      \
     40         if (NULL == (_instance_)) {                                           \
     41             LOG_ERROR(BSL_LS_BCM_TSN,                                         \
     42                       (BSL_META_U((_u_),                                      \
     43                                   "Error: NULL chip specific function \n"))); \
     44             return BCM_E_UNAVAIL;                                             \
     45         }                                                                     \
     46     } while (0)
     47 
     48 #if defined(BCM_TSN_SR_SUPPORT)
     49 
     50 /**************** TSN SR Mac Proxy ****************/
     51 /*
     52  * TSN SR Mac Proxy entry data structure
     53  */
     54 typedef struct bcmi_esw_tsn_sr_mac_proxy_entry_s {
     55     bcm_pbmp_t mp_pbmp;
     56     int ref_count;
     57 } bcmi_esw_tsn_sr_mac_proxy_entry_t;
     58 
     59 /*
     60  * TSN SR Mac Proxy bookkeeping info data structure
     61  */
     62 typedef struct bcmi_esw_tsn_sr_mac_proxy_bk_info_s {
     63     sal_mutex_t sr_mp_mutex;
     64     bcmi_esw_tsn_sr_mac_proxy_entry_t *sr_mp_entry;
     65     int sr_mp_num;
     66 } bcmi_esw_tsn_sr_mac_proxy_bk_info_t;
     67 
     68 /* TSN SR Mac Proxy bookkeeping instance lock/unlock */
     69 #define SR_MAC_PROXY_LOCK(sr_mp_bk_info) \
     70         sal_mutex_take(sr_mp_bk_info->sr_mp_mutex, sal_mutex_FOREVER)
     71 #define SR_MAC_PROXY_UNLOCK(sr_mp_bk_info) \
     72         sal_mutex_give(sr_mp_bk_info->sr_mp_mutex)
     73 /************** End of TSN SR Mac Proxy **************/
     74 
     75 /*
     76  *
     77  * Seamless Redundancy (SR) Flow Management
     78  */
     79 
     80 /*
     81  * SR flow index allocation entry:
     82  *   We need to minimize the time taken for picking a free flow index.
     83  *   To achieve this, we use linked list with pre-allocated entries so that
     84  *   we can do it in O(1).
     85  *   Flow index is a zero-based serial number which can be converted to
     86  *   SW flow ID (used by API) or HW flow ID (maintained by the platform).
     87  */
     88 typedef struct tsn_sr_flowidx_entry_s {
     89     int                             flow_idx;
     90     struct tsn_sr_flowidx_entry_s   *next;
     91 } tsn_sr_flowidx_entry_t;
     92 
     93 /* SR RX/TX flowset */
     94 typedef struct tsn_sr_flowset_s {
     95     bcm_tsn_pri_map_t               map_id;     /* priority map ID */
     96     tsn_sr_flowidx_entry_t          *flow_ide;  /* flow index entries */
     97     int                             ref_count;  /* reference count */
     98     int                             num_flows;  /* flow count (cache) */
     99     union {
    100         bcm_tsn_sr_rx_flow_config_t rx;
    101         bcm_tsn_sr_tx_flow_config_t tx;
    102     }                               config;     /* default flow config */
    103     sal_mutex_t                     mutex;      /* to protect flowset slot */
    104 } tsn_sr_flowset_t;
    105 
    106 /* SR flow direction constant used when accessing shared data structures */
    107 #define SR_FLOW_DIR_RX          (0)
    108 #define SR_FLOW_DIR_TX          (1)
    109 #define SR_FLOW_DIR_COUNT       (2)
    110 
    111 /* SR flow management book keeping */
    112 typedef struct tsn_sr_flows_bookkeeping_s {
    113     /* SR flow index quick allocation */
    114     tsn_sr_flowidx_entry_t          *flowids_avail[2];  /* RX/TX linked list */
    115     tsn_sr_flowidx_entry_t          *flowids_allocated; /* for freeing */
    116 
    117     /* SR flowset entries */
    118     tsn_sr_flowset_t                *flowsets[2];       /* RX/TX arrays */
    119 
    120     /* SR flow entries (not shared since the type is quite different) */
    121     bcmi_tsn_sr_rx_flow_t           *flows_rx;          /* indexed array */
    122     sal_mutex_t                     *flows_rx_mutex;    /* for RX flow slot */
    123     bcmi_tsn_sr_tx_flow_t           *flows_tx;          /* indexed array */
    124     sal_mutex_t                     *flows_tx_mutex;    /* for TX flow slot */
    125 
    126     /* for efficiency */
    127     int                             max_flows[2];       /* RX/TX */
    128 
    129     /* To protect flow list (allocate/free) */
    130     sal_mutex_t                     fmgmt_mutex;
    131 } tsn_sr_flows_bookkeeping_t;
    132 
    133 #ifdef BCM_WARM_BOOT_SUPPORT
    134 /* SR RX flowset for warmboot */
    135 typedef struct tsn_sr_rx_flowset_wb_s {
    136     int                             flow_idx;   /* Flow index */
    137     bcm_tsn_pri_map_t               map_id;     /* priority map ID */
    138     bcm_tsn_sr_rx_flow_config_t     config;     /* Flow default config */
    139 } tsn_sr_rx_flowset_wb_t;
    140 
    141 /* SR TX flowset for warmboot */
    142 typedef struct tsn_sr_tx_flowset_wb_s {
    143     int                             flow_idx;   /* Flow index */
    144     bcm_tsn_pri_map_t               map_id;     /* priority map ID */
    145     bcm_tsn_sr_tx_flow_config_t     config;     /* Flow default config */
    146 } tsn_sr_tx_flowset_wb_t;
    147 #endif /* BCM_WARM_BOOT_SUPPORT */
    148 
    149 /*
    150  *
    151  * Seamless Redundancy (SR) Auto Learn Management
    152  */
    153 
    154 /*
    155  * Structure definition for SR Auto Learn bookkeeping info
    156  */
    157 typedef struct bcmi_esw_tsn_sr_auto_learn_group_bk_data_s {
    158     int group_id;
    159     int redundant_pro_idx[bcmi_sr_auto_learn_group_count];
    160     int interlink_pro_idx;
    161     bcm_tsn_sr_auto_learn_group_config_t config;
    162 } bcmi_esw_tsn_sr_auto_learn_group_bk_data_t;
    163 
    164 typedef struct bcmi_esw_tsn_sr_auto_learn_bk_data_s {
    165     int enabled;
    166     bcm_tsn_sr_auto_learn_config_t config;
    167     uint32 flowsets_cnt[bcmi_sr_auto_learn_flow_count];
    168     bcm_tsn_sr_flowset_t *flowsets[bcmi_sr_auto_learn_flow_count];
    169 } bcmi_esw_tsn_sr_auto_learn_bk_data_t;
    170 
    171 typedef struct bcmi_esw_tsn_sr_auto_learn_bk_s {
    172     SHR_BITDCL *intf_bitmap;
    173     bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *group_data;
    174     uint32 valid_count;
    175     uint32 valid_sw_idx_start;
    176     uint32 valid_sw_idx_end;
    177     uint32 empty_sw_idx_start;
    178     uint32 empty_sw_idx_end;
    179     bcmi_esw_tsn_sr_auto_learn_bk_data_t data;
    180     sal_mutex_t bk_mutex;
    181     sal_mutex_t mutex;
    182     int initialized; /* for lazy initialization */
    183 } bcmi_esw_tsn_sr_auto_learn_bk_t;
    184 #endif /* BCM_TSN_SR_SUPPORT */
    185 
    186 /*
    187  *
    188  * TSN Flow (TSN Circuit ID) Management
    189  */
    190 
    191 /*
    192  * TSN flow index allocation entry (similar mechanism as SR flows)
    193  */
    194 typedef struct tsn_flowidx_entry_s {
    195     int                             flow_idx;
    196     struct tsn_flowidx_entry_s      *next;
    197 } tsn_flowidx_entry_t;
    198 
    199 /* TSN flowset */
    200 typedef struct tsn_flowset_s {
    201     bcm_tsn_pri_map_t               map_id;     /* priorty map ID */
    202     tsn_flowidx_entry_t             *flow_ide;  /* flow index entries */
    203     int                             ref_count;  /* reference count */
    204     int                             num_flows;  /* flow count (cache) */
    205     bcm_tsn_flow_config_t           config;     /* default flow config */
    206     sal_mutex_t                     mutex;      /* to protect flowset slot */
    207 } tsn_flowset_t;
    208 
    209 /* TSN flow management book keeping */
    210 typedef struct tsn_flows_bookkeeping_s {
    211     /* TSN flow index quick allocation */
    212     tsn_flowidx_entry_t             *flowids_avail;     /* linked list */
    213     tsn_flowidx_entry_t             *flowids_allocated; /* for freeing */
    214 
    215     /* TSN flowset entries */
    216     tsn_flowset_t                   *flowsets;          /* indexed arrays */
    217 
    218     /* TSN flow entries (not shared since the type is quite different) */
    219     bcm_tsn_flow_config_t           *flows;             /* indexed array */
    220     sal_mutex_t                     *flows_mutex;       /* for flow slot */
    221 
    222     /* for efficiency */
    223     int                             max_flows;
    224 
    225     /* To protect flow list (allocate/free) */
    226     sal_mutex_t                     fmgmt_mutex;
    227 } tsn_flows_bookkeeping_t;
    228 
    229 #ifdef BCM_WARM_BOOT_SUPPORT
    230 /* TSN flowset for warmboot */
    231 typedef struct tsn_flowset_wb_s {
    232     int                             flow_idx;   /* Flow index */
    233     bcm_tsn_pri_map_t               map_id;     /* priority map ID */
    234     bcm_tsn_flow_config_t           config;     /* Flow default config */
    235 } tsn_flowset_wb_t;
    236 #endif /* BCM_WARM_BOOT_SUPPORT */
    237 
    238 /* Initialization flag for TSN bookkeeping info structure */
    239 static int tsn_bk_info_initialized = 0;
    240 
    241 /* SW structure for storing the ingress & egress mtu priority map config ID */
    242 typedef struct bcmi_esw_tsn_mtu_bk_info_s {
    243     int *mtu_refcount[bcmTsnMtuProfileTypeCount];
    244     bcm_tsn_pri_map_t *pri_map_port;
    245     sal_mutex_t mutex;
    246 } bcmi_esw_tsn_mtu_bk_info_t;
    247 
    248 /* SW structure for storing the ingress & egress stu priority map config ID */
    249 typedef struct bcmi_esw_tsn_stu_bk_info_s {
    250     int *stu_refcount[bcmTsnStuProfileTypeCount];
    251     bcm_tsn_pri_map_t *pri_map_port;
    252     sal_mutex_t mutex;
    253 } bcmi_esw_tsn_stu_bk_info_t;
    254 
    255 /*
    256  * Structure definition for Priority Map bookkeeping info
    257  */
    258 typedef struct bcmi_esw_tsn_pri_map_bk_info_data_s {
    259     bcm_tsn_pri_map_t map_id;
    260     bcm_tsn_pri_map_config_t config;
    261     uint32 ref_cnt;
    262 } bcmi_esw_tsn_pri_map_bk_info_data_t;
    263 
    264 typedef struct bcmi_esw_tsn_pri_map_bk_info_s {
    265     SHR_BITDCL *intf_bitmap[bcmTsnPriMapTypeCount];
    266     bcmi_esw_tsn_pri_map_bk_info_data_t *data[bcmTsnPriMapTypeCount];
    267     uint32 valid_count[bcmTsnPriMapTypeCount];
    268     uint32 valid_sw_idx_start[bcmTsnPriMapTypeCount];
    269     uint32 valid_sw_idx_end[bcmTsnPriMapTypeCount];
    270     uint32 empty_sw_idx_start[bcmTsnPriMapTypeCount];
    271     uint32 empty_sw_idx_end[bcmTsnPriMapTypeCount];
    272     sal_mutex_t mutex, bk_mutex;
    273 } bcmi_esw_tsn_pri_map_bk_info_t;
    274 
    275 /*
    276  *
    277  * TSN Event Management
    278  */
    279 
    280 /*
    281  * Structure definition for event instance info
    282  * NOTE: event instance indicats the event with speficied source type
    283  */
    284 typedef struct tsn_evt_inst_s {
    285     struct tsn_evt_inst_s   *next;      /* next instance */
    286     bcm_tsn_event_cb        cb;         /* registered callback */
    287     void                    *user_data; /* registered user data */
    288     bcm_port_t              port;       /* specified port */
    289     bcm_tsn_sr_flow_t       sr_flow;    /* specified sr_flow */
    290 } tsn_evt_inst_t;
    291 
    292 /* event instance resource allocation info */
    293 typedef struct tsn_evt_inst_alloc_s {
    294     bcmi_tsn_evt_inst_type_t    inst_type;  /* event instance type */
    295     bcm_tsn_event_type_t        evt_type;   /* associated event type */
    296     int                         source_type;    /* associated source type */
    297     int                         inst_limits;    /* pre-allocated limits */
    298 } tsn_evt_inst_alloc_t;
    299 
    300 /* Structure definition for registered event instance info */
    301 typedef struct tsn_evt_regist_s {
    302     bcmi_tsn_evt_inst_type_t    inst_type;   /* event instance type */
    303     bcm_tsn_event_type_t        evt_type;    /* associated event type */
    304     int                         source_type; /* associated source type */
    305     tsn_evt_inst_t              *evt_inst;   /* event instance link list */
    306     sal_mutex_t                 mutex;  /* protect event instance link list */
    307 } tsn_evt_regist_t;
    308 
    309 /* Structure definition for registered event statistics info */
    310 typedef struct tsn_evt_stat_s {
    311     int         event_ref;  /* event reference count */
    312     int         *port_ref;  /* port basis event referece count */
    313     int         *flow_ref;  /* flow basis event referece count */
    314     SHR_BITDCL  *pbmp;  /* port bitmap on this event */
    315     SHR_BITDCL  *fbmp;  /* flow bitmap on this event */
    316     SHR_BITDCL  *ffbmp;  /* filter flow bitmap on this event */
    317 } tsn_evt_stat_t;
    318 
    319 /* Structure definition for event management bookkeeping info */
    320 typedef struct tsn_event_bk_s {
    321     /* Central event instance resource */
    322     tsn_evt_inst_t      *einst_avail[bcmiTsnEvtCount];  /* event linked list */
    323     tsn_evt_inst_t      *einst_allocated;    /* for freeing */
    324 
    325     /* Registered event arrays */
    326     tsn_evt_regist_t    eregist[bcmiTsnEvtCount];
    327     int                 max_flows; /* convenient to allocate flow database */
    328     int                 max_rx_flows; /* use to differentiate the flow dir */
    329     int                 max_ports; /* convenient to allocate port database */
    330 
    331     tsn_evt_stat_t      evt_stat[bcmTsnEventTypeCount];
    332     sal_mutex_t         evt_mutex;
    333 
    334     /* Kept the previous state used to enable age-out event poll */
    335     uint32              pre_enable;
    336     uint32              pre_interval;
    337     uint32              pre_rmode;
    338 
    339     /* Poll funtion information */
    340     VOL sal_thread_t    poll_tid;       /* thread id */
    341     VOL sal_usecs_t     poll_interval;  /* wakeup interval */
    342     sal_sem_t           poll_notify;    /* notify signal */
    343     int                 poll_enable;    /* poll thread is enable or not */
    344 } tsn_event_bk_t;
    345 
    346 /*
    347  * Structure definition for TSN bookkeeping info,
    348  * including bookkeeping and chip specific info
    349  */
    350 typedef struct bcmi_esw_tsn_bk_info_s {
    351     /* bookkeeping structure defined below */
    352 #if defined(BCM_TSN_SR_SUPPORT)
    353     /* TSN SR MAC Proxy bookkeeping info */
    354     bcmi_esw_tsn_sr_mac_proxy_bk_info_t         tsn_sr_mac_proxy_bk_info;
    355     /* TSN SR flow management */
    356     tsn_sr_flows_bookkeeping_t                  sr_flows;
    357     /* TSN SR Auto Learn management */
    358     bcmi_esw_tsn_sr_auto_learn_bk_t             tsn_sr_auto_learn_bk_info;
    359 #endif /* BCM_TSN_SR_SUPPORT */
    360     /* TSN flow management */
    361     tsn_flows_bookkeeping_t                     tsn_flows;
    362 
    363     bcmi_esw_tsn_pri_map_bk_info_t              tsn_pri_map_bk_info;
    364 
    365     /* MTU & STU management */
    366     bcmi_esw_tsn_mtu_bk_info_t                  tsn_mtu_bk_info;
    367     bcmi_esw_tsn_stu_bk_info_t                  tsn_stu_bk_info;
    368 
    369     /* Event management */
    370     tsn_event_bk_t                              tsn_events;
    371     /* device specific info */
    372     const bcmi_esw_tsn_dev_info_t               *tsn_dev_info;
    373 } bcmi_esw_tsn_bk_info_t;
    374 
    375 /* TSN bookkeeping info */
    376 STATIC bcmi_esw_tsn_bk_info_t *tsn_bk_info[BCM_MAX_NUM_UNITS] = { NULL };
    377 
    378 #if defined(BCM_TSN_SR_SUPPORT)
    379 
    380 /* SW SR Flow ID conversion: flow ID is 1-based (0 is invalid) */
    381 #define SR_FLOW_ID_TX_MASK       0x40000000
    382 #define SR_FLOW_ID_FROM_IDX(_dir, _idx)                                     \
    383     ((bcm_tsn_sr_flow_t)(                                                   \
    384         ((_idx) | ((_dir) == SR_FLOW_DIR_TX ? SR_FLOW_ID_TX_MASK : 0)) + 1))
    385 #define SR_FLOW_ID_TO_DIR(_id)                                              \
    386     ((((int)(_id)) & SR_FLOW_ID_TX_MASK) ? SR_FLOW_DIR_TX : SR_FLOW_DIR_RX)
    387 #define SR_FLOW_ID_TO_IDX(_id)                                              \
    388     ((((int)(_id)) & (~SR_FLOW_ID_TX_MASK)) - 1)
    389 
    390 /* SR Flowset ID conversion: use the same encoding as SW flow ID */
    391 #define SR_FLOWSET_ID_FROM_IDX(_dir, _idx)                                  \
    392     ((bcm_tsn_sr_flowset_t)SR_FLOW_ID_FROM_IDX((_dir), (_idx)))
    393 #define SR_FLOWSET_ID_TO_DIR(_id) SR_FLOW_ID_TO_DIR((bcm_tsn_sr_flow_t)(_id))
    394 #define SR_FLOWSET_ID_TO_IDX(_id) SR_FLOW_ID_TO_IDX((bcm_tsn_sr_flow_t)(_id))
    395 
    396 /* SR flow management bookkeeping info quick access */
    397 #define SR_FLOW_MGMT_BKINFO(_unit_)                                         \
    398     (&tsn_bk_info[_unit_]->sr_flows)
    399 #define SR_FLOW_MGMT_DEVINFO(_unit_)                                        \
    400     tsn_bk_info[_unit_]->tsn_dev_info->sr_flows_info
    401 
    402 /* Protecting the global SR flow management */
    403 #define SR_FLOW_MGMT_LOCK(_unit_)                                           \
    404     sal_mutex_take(SR_FLOW_MGMT_BKINFO(_unit_)->fmgmt_mutex, sal_mutex_FOREVER)
    405 #define SR_FLOW_MGMT_UNLOCK(_unit_)                                         \
    406     sal_mutex_give(SR_FLOW_MGMT_BKINFO(_unit_)->fmgmt_mutex)
    407 
    408 /* Protecting an SR flowset slot */
    409 #define SR_FLOWSET_LOCK(_fsp_)                                              \
    410     sal_mutex_take((_fsp_)->mutex, sal_mutex_FOREVER)
    411 #define SR_FLOWSET_UNLOCK(_fsp_)                                            \
    412     sal_mutex_give((_fsp_)->mutex)
    413 
    414 /* Protecting an SR flow slot */
    415 #define SR_FLOW_RX_LOCK(_unit_, _idx_)                                      \
    416     sal_mutex_take(SR_FLOW_MGMT_BKINFO(_unit_)->flows_rx_mutex[_idx_],      \
    417                    sal_mutex_FOREVER)
    418 #define SR_FLOW_RX_UNLOCK(_unit_, _idx_)                                    \
    419     sal_mutex_give(SR_FLOW_MGMT_BKINFO(_unit_)->flows_rx_mutex[_idx_])
    420 #define SR_FLOW_TX_LOCK(_unit_, _idx_)                                      \
    421     sal_mutex_take(SR_FLOW_MGMT_BKINFO(_unit_)->flows_tx_mutex[_idx_],      \
    422                    sal_mutex_FOREVER)
    423 #define SR_FLOW_TX_UNLOCK(_unit_, _idx_)                                    \
    424     sal_mutex_give(SR_FLOW_MGMT_BKINFO(_unit_)->flows_tx_mutex[_idx_])
    425 
    426 /* Valid flags for bcm_tsn_sr_auto_learn_group_config_t */
    427 #define BCMI_TSN_SR_AUTO_LEARN_GROUP_VALID_FLAGS                            \
    428     (BCM_TSN_SR_AUTO_LEARN_GROUP_PROXY_FILTERING)
    429 
    430 /*
    431  * SR Auto Learn Group id encoding:
    432  * 1-bit (reserved) + 1-bit'1 (Auto Learn Magic Bit) + 22-bit (reserved)
    433  * + 8-bit sw_idx
    434  */
    435 #define BCMI_SR_AUTO_LEARN_SW_IDX_MASK           (0xFF)
    436 #define BCMI_SR_AUTO_LEARN_SHIFT                 (30)
    437 #define BCMI_SR_AUTO_LEARN                       (1)
    438 
    439 /*
    440  * SR Auto Learn Group related define
    441  */
    442 #define BCMI_SR_AUTO_LEARN_GROUP_ID_INVALID (-1)
    443 #define BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID (-1)
    444 
    445 /*
    446  * Translate between SR Auto Learn Group id and SW_IDX
    447  * The sw_idx is not the hardware index of register/memory.
    448  * It just represents the array index of SW bookkeeping group_data[sw_idx]
    449  */
    450 #define GROUP_ID_TO_SW_IDX(_group_id_) \
    451     ((_group_id_) & BCMI_SR_AUTO_LEARN_SW_IDX_MASK)
    452 
    453 #define SW_IDX_TO_GROUP_ID(_sw_idx_) \
    454     ((_sw_idx_) | BCMI_SR_AUTO_LEARN << BCMI_SR_AUTO_LEARN_SHIFT)
    455 
    456 #define AUTO_LEARN_DEV_INIT(_u_)                                            \
    457     do {                                                                    \
    458         if (!soc_feature(unit, soc_feature_tsn_sr) ||                       \
    459             !soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {            \
    460             LOG_ERROR(BSL_LS_BCM_TSN,                                       \
    461                       (BSL_META_U(unit,                                     \
    462                                   "SR Auto Learn Error:"                    \
    463                                   " feature not enable \n")));              \
    464             return BCM_E_UNAVAIL;                                           \
    465         }                                                                   \
    466         if (!tsn_bk_info[(_u_)] ||                                          \
    467             !tsn_bk_info[(_u_)]->tsn_dev_info ||                            \
    468             !tsn_bk_info[(_u_)]->tsn_dev_info->tsn_sr_auto_learn_info) {    \
    469             LOG_ERROR(BSL_LS_BCM_TSN,                                       \
    470                       (BSL_META_U(unit,                                     \
    471                                   "SR Auto Learn Error:"                    \
    472                                   " dev not initialized\n")));              \
    473             return BCM_E_UNAVAIL;                                           \
    474         }                                                                   \
    475     } while (0)
    476 
    477 #define AUTO_LEARN_INIT(_u_)                                                \
    478     do {                                                                    \
    479         if (!soc_feature(unit, soc_feature_tsn_sr) ||                       \
    480             !soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {            \
    481             LOG_ERROR(BSL_LS_BCM_TSN,                                       \
    482                       (BSL_META_U(unit,                                     \
    483                                   "SR Auto Learn Error:"                    \
    484                                   " feature not enable \n")));              \
    485             return BCM_E_UNAVAIL;                                           \
    486         }                                                                   \
    487         if (!tsn_bk_info[(_u_)] ||                                          \
    488             !tsn_bk_info[(_u_)]->tsn_sr_auto_learn_bk_info.initialized) {   \
    489             LOG_WARN(BSL_LS_BCM_TSN,                                        \
    490                       (BSL_META_U(unit,                                     \
    491                                   "SR Auto Learn Warning:"                  \
    492                                   " not initialized\n")));                  \
    493             return BCM_E_INIT;                                              \
    494         }                                                                   \
    495         if (!tsn_bk_info[(_u_)] ||                                          \
    496             !tsn_bk_info[(_u_)]->tsn_dev_info ||                            \
    497             !tsn_bk_info[(_u_)]->tsn_dev_info->tsn_sr_auto_learn_info ||    \
    498             !tsn_bk_info[(_u_)]->tsn_sr_auto_learn_bk_info.intf_bitmap ||   \
    499             !tsn_bk_info[(_u_)]->tsn_sr_auto_learn_bk_info.group_data) {    \
    500             LOG_ERROR(BSL_LS_BCM_TSN,                                       \
    501                       (BSL_META_U(unit,                                     \
    502                                   "SR Auto Learn Error:"                    \
    503                                   " not allocated\n")));                    \
    504             return BCM_E_UNAVAIL;                                           \
    505         }                                                                   \
    506     } while (0)
    507 
    508 /* SR Auto Learn instance fetch/lock/unlock */
    509 #define AUTO_LEARN_BK_INFO(_u_) \
    510     (&tsn_bk_info[(_u_)]->tsn_sr_auto_learn_bk_info)
    511 
    512 /* Protect bcmi_esw_tsn_pri_map_bk_info_t */
    513 #define AUTO_LEARN_BK_LOCK(_u_) \
    514     (sal_mutex_take(AUTO_LEARN_BK_INFO((_u_))->bk_mutex, sal_mutex_FOREVER))
    515 
    516 #define AUTO_LEARN_BK_UNLOCK(_u_) \
    517     (sal_mutex_give(AUTO_LEARN_BK_INFO((_u_))->bk_mutex))
    518 
    519 /*
    520  * make bcmi_esw_tsn_sr_auto_learn_create/set/get/destroy/traverse
    521  * to be atomic executed
    522  */
    523 #define AUTO_LEARN_LOCK(_u_) \
    524     (sal_mutex_take(AUTO_LEARN_BK_INFO((_u_))->mutex, sal_mutex_FOREVER))
    525 
    526 #define AUTO_LEARN_UNLOCK(_u_) \
    527     (sal_mutex_give(AUTO_LEARN_BK_INFO((_u_))->mutex))
    528 
    529 /*
    530  * SR Auto Learn usage bitmap operations
    531  */
    532 #define AUTO_LEARN_INTF_USED_GET(_u_, _intf_) \
    533     ((AUTO_LEARN_BK_INFO(_u_)->intf_bitmap) ? \
    534         (SHR_BITGET(AUTO_LEARN_BK_INFO(_u_)->intf_bitmap, (_intf_))) : 0)
    535 #define AUTO_LEARN_INTF_USED_SET(_u_, _intf_) \
    536     (SHR_BITSET(AUTO_LEARN_BK_INFO(_u_)->intf_bitmap, (_intf_)))
    537 #define AUTO_LEARN_INTF_USED_CLR(_u_, _intf_) \
    538     (SHR_BITCLR(AUTO_LEARN_BK_INFO(_u_)->intf_bitmap, (_intf_)))
    539 
    540 #endif /* BCM_TSN_SR_SUPPORT */
    541 
    542 /* TSN SW Flow ID conversion: flow ID is 1-based (0 is invalid) */
    543 #define TSN_FLOW_ID_FROM_IDX(_idx)          ((bcm_tsn_flow_t)((_idx) + 1))
    544 #define TSN_FLOW_ID_TO_IDX(_id)             ((int)(_id) - 1)
    545 
    546 /* Flowset ID conversion: use the same encoding as SW flow ID */
    547 #define TSN_FLOWSET_ID_FROM_IDX(_idx)       \
    548         ((bcm_tsn_flowset_t)TSN_FLOW_ID_FROM_IDX(_idx))
    549 #define TSN_FLOWSET_ID_TO_IDX(_id)          \
    550         TSN_FLOW_ID_TO_IDX((bcm_tsn_flow_t)(_id))
    551 
    552 /* TSN flow management bookkeeping info quick access */
    553 #define TSN_FLOW_MGMT_BKINFO(_unit_)                                        \
    554     (&tsn_bk_info[_unit_]->tsn_flows)
    555 #define TSN_FLOW_MGMT_DEVINFO(_unit_)                                       \
    556     tsn_bk_info[_unit_]->tsn_dev_info->tsn_flows_info
    557 
    558 /* Protecting the global TSN flow management */
    559 #define TSN_FLOW_MGMT_LOCK(_unit_)                                          \
    560     sal_mutex_take(TSN_FLOW_MGMT_BKINFO(_unit_)->fmgmt_mutex, sal_mutex_FOREVER)
    561 #define TSN_FLOW_MGMT_UNLOCK(_unit_)                                        \
    562     sal_mutex_give(TSN_FLOW_MGMT_BKINFO(_unit_)->fmgmt_mutex)
    563 
    564 /* Protecting a TSN flowset slot */
    565 #define TSN_FLOWSET_LOCK(_fsp_)                                             \
    566     sal_mutex_take((_fsp_)->mutex, sal_mutex_FOREVER)
    567 #define TSN_FLOWSET_UNLOCK(_fsp_)                                           \
    568     sal_mutex_give((_fsp_)->mutex)
    569 
    570 /* Protecting a TSN flow slot */
    571 #define TSN_FLOW_LOCK(_unit_, _idx_)                                        \
    572     sal_mutex_take(TSN_FLOW_MGMT_BKINFO(_unit_)->flows_mutex[_idx_],        \
    573                    sal_mutex_FOREVER)
    574 #define TSN_FLOW_UNLOCK(_unit_, _idx_)                                      \
    575     sal_mutex_give(TSN_FLOW_MGMT_BKINFO(_unit_)->flows_mutex[_idx_])
    576 
    577 /*
    578  * Priority Map id encoding:
    579  * 1bit (valid) + 3-bit bcm_tsn_pri_map_type + 12-bit (reserved)
    580  * + 16-bit sw_idx
    581  */
    582 #define BCMI_TSN_PRI_MAP_SW_IDX_MASK          (0xFFFF)
    583 #define BCMI_TSN_PRI_MAP_TYPE_SHIFT           (28)
    584 #define BCMI_TSN_PRI_MAP_TYPE_MASK            (0x7)
    585 #define BCMI_TSN_PRI_MAP_VALID_SHIFT          (31)
    586 
    587 /*
    588  * Translate between Priority Map ID and SW_IDX & Priority Map Type
    589  * The sw_idx is not the hardware index of register/memory.
    590  * It just represents the array index of SW bookkeeping data[map_type][sw_idx]
    591  */
    592 #define MAP_ID_TO_SW_IDX(_id_) \
    593         ((_id_) & BCMI_TSN_PRI_MAP_SW_IDX_MASK)
    594 
    595 #define SW_IDX_TO_MAP_ID(_id_, _map_type_) \
    596         ((_id_) | \
    597          ((_map_type_) << BCMI_TSN_PRI_MAP_TYPE_SHIFT) | \
    598          (0x1 << BCMI_TSN_PRI_MAP_VALID_SHIFT))
    599 
    600 #define PRI_MAP_TYPE_GET(_id_) \
    601         (((_id_) >> BCMI_TSN_PRI_MAP_TYPE_SHIFT) & BCMI_TSN_PRI_MAP_TYPE_MASK)
    602 
    603 #define PRI_MAP_ID_IS_TYPE(_id_, _map_type_) \
    604         (PRI_MAP_TYPE_GET((_id_)) == (_map_type_))
    605 
    606 #define PRI_MAP_INIT(_u_, _map_type_)                                         \
    607     do {                                                                      \
    608         if (!soc_feature((_u_), soc_feature_tsn_sr) &&                        \
    609             (_map_type_) == bcmTsnPriMapTypeSrFlow) {                         \
    610             LOG_ERROR(BSL_LS_BCM_TSN,                                         \
    611                       (BSL_META_U((_u_),                                      \
    612                                   "TSN Priority Map Error:"                   \
    613                                   " feature not enable \n")));                \
    614             return BCM_E_UNAVAIL;                                             \
    615         }                                                                     \
    616         if (!soc_feature((_u_), soc_feature_tsn_mtu_stu) &&                   \
    617             ((_map_type_) == bcmTsnPriMapTypeEgressMtuProfile ||              \
    618              (_map_type_) == bcmTsnPriMapTypeEgressStuProfile)) {             \
    619             LOG_ERROR(BSL_LS_BCM_TSN,                                         \
    620                       (BSL_META_U((_u_),                                      \
    621                                   "TSN Priority Map Error:"                   \
    622                                   " feature not enable \n")));                \
    623             return BCM_E_UNAVAIL;                                             \
    624         }                                                                     \
    625         if (!soc_feature((_u_), soc_feature_tsn_taf) &&                       \
    626             (_map_type_) == bcmTsnPriMapTypeTafGate) {                        \
    627             LOG_ERROR(BSL_LS_BCM_TSN,                                         \
    628                       (BSL_META_U((_u_),                                      \
    629                                   "TSN Priority Map Error:"                   \
    630                                   " feature not enable \n")));                \
    631             return BCM_E_UNAVAIL;                                             \
    632         }                                                                     \
    633         if (!tsn_bk_info[_u_]->tsn_dev_info ||                                \
    634             !tsn_bk_info[_u_]->tsn_dev_info->tsn_pri_map_info[_map_type_] ||  \
    635             !tsn_bk_info[_u_]->tsn_pri_map_bk_info.data ||                    \
    636             !tsn_bk_info[_u_]->tsn_pri_map_bk_info.intf_bitmap) {             \
    637             LOG_ERROR(BSL_LS_BCM_TSN,                                         \
    638                       (BSL_META_U((_u_),                                      \
    639                                   "TSN Priority Map Error:"                   \
    640                                   " not allocated\n")));                      \
    641             return BCM_E_UNAVAIL;                                             \
    642         }                                                                     \
    643     } while (0)
    644 
    645 /* Priority Map instance fetch/lock/unlock */
    646 #define PRI_MAP_BK_INFO(_u_) \
    647         (&tsn_bk_info[(_u_)]->tsn_pri_map_bk_info)
    648 
    649 /* Protect bcmi_esw_tsn_pri_map_bk_info_t */
    650 #define PRI_MAP_BK_LOCK(_u_) \
    651         sal_mutex_take(PRI_MAP_BK_INFO((_u_))->bk_mutex, sal_mutex_FOREVER)
    652 
    653 #define PRI_MAP_BK_UNLOCK(_u_) \
    654         sal_mutex_give(PRI_MAP_BK_INFO((_u_))->bk_mutex)
    655 
    656 /*
    657  * make bcmi_esw_tsn_pri_map_create/set/get/destroy/traverse
    658  * to be atomic executed
    659  */
    660 #define PRI_MAP_LOCK(_u_) \
    661         sal_mutex_take(PRI_MAP_BK_INFO((_u_))->mutex, sal_mutex_FOREVER)
    662 
    663 #define PRI_MAP_UNLOCK(_u_) \
    664         sal_mutex_give(PRI_MAP_BK_INFO((_u_))->mutex)
    665 
    666 /* Priority Map usage bitmap operations */
    667 #define PRI_MAP_INTF_GET(_u_, _map_type_, _intf_) \
    668     ((PRI_MAP_BK_INFO(_u_)->intf_bitmap[(_map_type_)]) ? \
    669       (SHR_BITGET(PRI_MAP_BK_INFO(_u_)->intf_bitmap[_map_type_], (_intf_))) : 0)
    670 #define PRI_MAP_INTF_SET(_u_, _map_type_, _intf_) \
    671         SHR_BITSET(PRI_MAP_BK_INFO(_u_)->intf_bitmap[(_map_type_)], (_intf_))
    672 #define PRI_MAP_INTF_CLR(_u_, _map_type_, _intf_) \
    673         SHR_BITCLR(PRI_MAP_BK_INFO(_u_)->intf_bitmap[(_map_type_)], (_intf_))
    674 
    675 /* MTU Operation Check */
    676 #define MTU_BK_INIT(_u_, _t_)                                                 \
    677     do {                                                                      \
    678         if ((_t_) != bcmTsnMtuProfileTypeIngress &&                           \
    679             (_t_) != bcmTsnMtuProfileTypeEgress) {                            \
    680             return BCM_E_PARAM;                                               \
    681         }                                                                     \
    682         if ((NULL == tsn_bk_info[(_u_)]->tsn_mtu_bk_info.mtu_refcount[_t_])) {\
    683             LOG_ERROR(BSL_LS_BCM_TSN,                                         \
    684                       (BSL_META_U((_u_),                                      \
    685                                   "MTU Error:"                                \
    686                                   " bookeeping not allocated\n")));           \
    687             return BCM_E_UNAVAIL;                                             \
    688         }                                                                     \
    689     } while (0)
    690 
    691 #define MTU_DEV_INIT(_u_)                                                \
    692     do {                                                                 \
    693         const tsn_mtu_info_t *mtu_info;                                  \
    694         if (tsn_bk_info[(_u_)]->tsn_dev_info == NULL) {                  \
    695             LOG_ERROR(BSL_LS_BCM_TSN,                                    \
    696                       (BSL_META_U((_u_),                                 \
    697                                   "MTU Error:"                           \
    698                                   " tsn_dev_info not allocated\n")));    \
    699             return BCM_E_UNAVAIL;                                        \
    700         }                                                                \
    701         mtu_info = tsn_bk_info[(_u_)]->tsn_dev_info->tsn_mtu_info;       \
    702         if (mtu_info == NULL) {                                          \
    703             LOG_ERROR(BSL_LS_BCM_TSN,                                    \
    704                       (BSL_META_U((_u_),                                 \
    705                                   "MTU Error:"                           \
    706                                   " tsn_mtu_info not allocated\n")));    \
    707             return BCM_E_UNAVAIL;                                        \
    708         }                                                                \
    709         if ((NULL == mtu_info->mtu_profile_mem_idx_get) ||               \
    710             (NULL == mtu_info->mtu_profile_create) ||                    \
    711             (NULL == mtu_info->mtu_profile_set) ||                       \
    712             (NULL == mtu_info->mtu_profile_get) ||                       \
    713             (NULL == mtu_info->mtu_profile_destroy) ||                   \
    714             (NULL == mtu_info->ingress_mtu_config_set) ||                \
    715             (NULL == mtu_info->ingress_mtu_config_get) ||                \
    716             (NULL == mtu_info->egress_mtu_port_control_set) ||           \
    717             (NULL == mtu_info->mtu_profile_decode) ||                    \
    718             (NULL == mtu_info->mtu_profile_encode) ||                    \
    719             (NULL == mtu_info->mtu_profile_traverse) ||                  \
    720             (NULL == mtu_info->mtu_profile_mem_refcnt_get)) {            \
    721             LOG_ERROR(BSL_LS_BCM_TSN,                                    \
    722                       (BSL_META_U((_u_),                                 \
    723                                   "MTU Error:"                           \
    724                                   " dev info not allocated\n")));        \
    725             return BCM_E_UNAVAIL;                                        \
    726         }                                                                \
    727     } while (0)
    728 
    729 /* MTU instance fetch/lock/unlock */
    730 #define MTU_BK_INFO(_u_) \
    731         (&tsn_bk_info[(_u_)]->tsn_mtu_bk_info)
    732 
    733 #define MTU_BK_LOCK(_u_) \
    734         sal_mutex_take(MTU_BK_INFO((_u_))->mutex, sal_mutex_FOREVER)
    735 
    736 #define MTU_BK_UNLOCK(_u_) \
    737         sal_mutex_give(MTU_BK_INFO((_u_))->mutex)
    738 
    739 /* STU Operation Check */
    740 #define STU_BK_INIT(_u_, _t_)                                                 \
    741     do {                                                                      \
    742         if ((_t_) != bcmTsnStuProfileTypeIngress &&                           \
    743             (_t_) != bcmTsnStuProfileTypeEgress) {                            \
    744             return BCM_E_PARAM;                                               \
    745         }                                                                     \
    746         if ((NULL == tsn_bk_info[(_u_)]->tsn_stu_bk_info.stu_refcount[_t_])) {\
    747             LOG_ERROR(BSL_LS_BCM_TSN,                                         \
    748                       (BSL_META_U((_u_),                                      \
    749                                   "STU Error:"                                \
    750                                   " bookeeping not allocated\n")));           \
    751             return BCM_E_UNAVAIL;                                             \
    752         }                                                                     \
    753     } while (0)
    754 
    755 #define STU_DEV_INIT(_u_)                                                \
    756     do {                                                                 \
    757         const tsn_stu_info_t *stu_info;                                  \
    758         if (tsn_bk_info[(_u_)]->tsn_dev_info == NULL) {                  \
    759             LOG_ERROR(BSL_LS_BCM_TSN,                                    \
    760                       (BSL_META_U((_u_),                                 \
    761                                   "STU Error:"                           \
    762                                   " tsn_dev_info not allocated\n")));    \
    763             return BCM_E_UNAVAIL;                                        \
    764         }                                                                \
    765         stu_info = tsn_bk_info[(_u_)]->tsn_dev_info->tsn_stu_info;       \
    766         if (stu_info == NULL) {                                          \
    767             LOG_ERROR(BSL_LS_BCM_TSN,                                    \
    768                       (BSL_META_U((_u_),                                 \
    769                                   "STU Error:"                           \
    770                                   " tsn_stu_info not allocated\n")));    \
    771             return BCM_E_UNAVAIL;                                        \
    772         }                                                                \
    773         if ((NULL == stu_info->stu_profile_mem_idx_get) ||               \
    774             (NULL == stu_info->stu_profile_create) ||                    \
    775             (NULL == stu_info->stu_profile_set) ||                       \
    776             (NULL == stu_info->stu_profile_get) ||                       \
    777             (NULL == stu_info->stu_profile_destroy) ||                   \
    778             (NULL == stu_info->ingress_stu_config_set) ||                \
    779             (NULL == stu_info->ingress_stu_config_get) ||                \
    780             (NULL == stu_info->egress_stu_port_control_set) ||           \
    781             (NULL == stu_info->stu_profile_decode) ||                    \
    782             (NULL == stu_info->stu_profile_encode) ||                    \
    783             (NULL == stu_info->stu_profile_traverse) ||                  \
    784             (NULL == stu_info->stu_profile_mem_refcnt_get)) {            \
    785             LOG_ERROR(BSL_LS_BCM_TSN,                                    \
    786                       (BSL_META_U((_u_),                                 \
    787                                   "STU Error:"                           \
    788                                   " dev info not allocated\n")));        \
    789             return BCM_E_UNAVAIL;                                        \
    790         }                                                                \
    791     } while (0)
    792 
    793 /* STU instance fetch/lock/unlock */
    794 #define STU_BK_INFO(_u_) \
    795         (&tsn_bk_info[(_u_)]->tsn_stu_bk_info)
    796 
    797 #define STU_BK_LOCK(_u_) \
    798         sal_mutex_take(STU_BK_INFO((_u_))->mutex, sal_mutex_FOREVER)
    799 #define STU_BK_UNLOCK(_u_) \
    800         sal_mutex_give(STU_BK_INFO((_u_))->mutex)
    801 
    802 /* TSN event management bookkeeping info quick access */
    803 #define TSN_EVENT_BKINFO(_unit_)                                         \
    804     (&tsn_bk_info[_unit_]->tsn_events)
    805 #define TSN_EVENT_DEVINFO(_unit_)                                        \
    806     tsn_bk_info[_unit_]->tsn_dev_info->tsn_event_info
    807 
    808 #define TSN_EVENT_FLOW_CB_MAX           (1000)
    809 #define TSN_EVENT_PORT_CB_MAX           (1000)
    810 #define TSN_EVENT_SYSTEM_CB_MAX         (100)
    811 
    812 #define TSN_EVENT_POLL_INTERVAL_DEFAULT     (SECOND_USEC)
    813 
    814 /* Protecting the global TSN event management */
    815 #define TSN_EVENT_LOCK(_unit_)                                           \
    816     sal_mutex_take(TSN_EVENT_BKINFO(_unit_)->evt_mutex, sal_mutex_FOREVER)
    817 #define TSN_EVENT_UNLOCK(_unit_)                                         \
    818     sal_mutex_give(TSN_EVENT_BKINFO(_unit_)->evt_mutex)
    819 
    820 #if defined(BCM_TSN_SR_SUPPORT)
    821 /* Internal functions to update the active rx flow idx */
    822 STATIC int bcmi_esw_tsn_event_rx_flow_delete(int unit, int flow_idx);
    823 STATIC int bcmi_esw_tsn_event_rx_flow_add(int unit, int flow_idx);
    824 #endif /* BCM_TSN_SR_SUPPORT */
    825 
    826 /* Protecting registered event instance */
    827 #define TSN_REVT_LOCK(_erp_)                                    \
    828     sal_mutex_take((_erp_)->mutex, sal_mutex_FOREVER)
    829 #define TSN_REVT_UNLOCK(_erp_)                                         \
    830     sal_mutex_give((_erp_)->mutex)
    831 
    832 /* Get the tsn_bk_info[unit] pointer */
    833 STATIC int
    834 tsn_bk_info_instance_get(int unit, bcmi_esw_tsn_bk_info_t **bk_info)
    835 {
    836     /* Input parameters check. */
    837     if (NULL == bk_info) {
    838         return (BCM_E_PARAM);
    839     }
    840     if (!SOC_UNIT_VALID(unit)) {
    841         return BCM_E_UNIT;
    842     }
    843 
    844     /* Check if TSN feature supported and initialized */
    845     if (!soc_feature(unit, soc_feature_tsn)) {
    846         return (BCM_E_UNAVAIL);
    847     }
    848     if (tsn_bk_info[unit] == NULL) {
    849         LOG_ERROR(BSL_LS_BCM_TSN,
    850                   (BSL_META_U(unit,
    851                               "TSN Error: bookkeeping info not "
    852                               "initialized\n")));
    853         return (BCM_E_INIT);
    854     }
    855 
    856     /* Fill info structure. */
    857     *bk_info = tsn_bk_info[unit];
    858 
    859     return (BCM_E_NONE);
    860 }
    861 
    862 /*
    863  * Function:
    864  *     bcmi_esw_tsn_noninit_dev_info_get
    865  * Purpose:
    866  *     Internal function to get device sepcific info without tsn_bk initialized.
    867  * Parameters:
    868  *     unit - (IN) unit number
    869  *     devinfo-(OUT) device info
    870  * Returns:
    871  *     BCM_E_XXX
    872  */
    873 STATIC int
    874 bcmi_esw_tsn_noninit_dev_info_get(
    875     int unit,
    876     const bcmi_esw_tsn_dev_info_t **devinfo)
    877 {
    878     int rv = BCM_E_NONE;
    879 
    880     /* Input parameters check. */
    881     if (NULL == devinfo) {
    882         return (BCM_E_PARAM);
    883     }
    884     if (!SOC_UNIT_VALID(unit)) {
    885         return BCM_E_UNIT;
    886     }
    887 
    888     /* Check if TSN feature supported and initialized */
    889     if (!soc_feature(unit, soc_feature_tsn)) {
    890         return (BCM_E_UNAVAIL);
    891     }
    892 #ifdef BCM_GREYHOUND2_SUPPORT
    893     if (SOC_IS_GREYHOUND2(unit)) {
    894         /* Fill info structure. */
    895         rv = bcmi_gh2_tsn_noninit_dev_info_get(unit, devinfo);
    896     } else
    897 #endif /* BCM_GREYHOUND2_SUPPORT */
    898     {
    899         rv = BCM_E_UNAVAIL;
    900     }
    901 
    902     return rv;
    903 }
    904 
    905 #if defined(BCM_TSN_SR_SUPPORT)
    906 
    907 /*
    908  * Function:
    909  *    bcmi_esw_tsn_sr_mac_proxy_cleanup
    910  * Description:
    911  *    Clean and free all allocated resources for
    912  *    TSN SR Mac Proxy profile.
    913  * Parameters:
    914  *    unit - (IN) Unit number
    915  * Return Value:
    916  *    None
    917  */
    918 STATIC int
    919 bcmi_esw_tsn_sr_mac_proxy_cleanup(int unit)
    920 {
    921     bcmi_esw_tsn_sr_mac_proxy_bk_info_t *sr_mp_bk_info;
    922 
    923     LOG_VERBOSE(BSL_LS_BCM_TSN,
    924                 (BSL_META_U(unit,
    925                             "bcmi_esw_tsn_sr_mac_proxy_cleanup\n")));
    926 
    927     /* Free and clear the TSN SR MAC Proxy bookkeeping info structure */
    928     if (tsn_bk_info[unit] != NULL) {
    929         sr_mp_bk_info = &(tsn_bk_info[unit]->tsn_sr_mac_proxy_bk_info);
    930 
    931         if (sr_mp_bk_info->sr_mp_entry != NULL) {
    932             TSN_FREE(unit, sr_mp_bk_info->sr_mp_entry, 0);
    933             sr_mp_bk_info->sr_mp_entry = NULL;
    934         }
    935 
    936         if (sr_mp_bk_info->sr_mp_mutex != NULL) {
    937             sal_mutex_destroy(sr_mp_bk_info->sr_mp_mutex);
    938             sr_mp_bk_info->sr_mp_mutex = NULL;
    939         }
    940     }
    941 
    942     return BCM_E_NONE;
    943 }
    944 
    945 /*
    946  * Function:
    947  *    bcmi_esw_tsn_sr_mac_proxy_init
    948  * Description:
    949  *    Initialize and allocate all required resources for
    950  *    TSN SR Mac Proxy profile.
    951  * Parameters:
    952  *    unit - (IN) Unit number
    953  * Returns:
    954  *    BCM_E_XXX
    955  */
    956 STATIC int
    957 bcmi_esw_tsn_sr_mac_proxy_init(int unit)
    958 {
    959     int rv = BCM_E_NONE;
    960     bcmi_esw_tsn_bk_info_t *tsn_bk_info;
    961     const bcmi_esw_tsn_dev_info_t *tsn_dev_info;
    962     const tsn_sr_mac_proxy_info_t *sr_mp_dev_info;
    963     bcmi_esw_tsn_sr_mac_proxy_bk_info_t *sr_mp_bk_info;
    964 
    965     LOG_VERBOSE(BSL_LS_BCM_TSN,
    966                 (BSL_META_U(unit,
    967                             "bcmi_esw_tsn_sr_mac_proxy_init\n")));
    968 
    969     BCM_IF_ERROR_RETURN(
    970         tsn_bk_info_instance_get(unit, &tsn_bk_info));
    971 
    972     /* Set up the unit TSN SR Mac Proxy bookkeeping info structure. */
    973     sr_mp_bk_info = &(tsn_bk_info->tsn_sr_mac_proxy_bk_info);
    974 
    975     /* Create protection mutex. */
    976     sr_mp_bk_info->sr_mp_mutex = sal_mutex_create("sr_mp_bk_info.lock");
    977     if (NULL == sr_mp_bk_info->sr_mp_mutex) {
    978         return BCM_E_RESOURCE;
    979     }
    980 
    981     /* Get chip specific assignment */
    982     tsn_dev_info = tsn_bk_info->tsn_dev_info;
    983     sr_mp_dev_info = tsn_dev_info->tsn_sr_mac_proxy_info;
    984 
    985     if (sr_mp_dev_info == NULL) {
    986         LOG_ERROR(BSL_LS_BCM_TSN,
    987                   (BSL_META_U(unit,
    988                               "TSN Error: SR MAC Proxy device info not "
    989                               "initialized\n")));
    990         return BCM_E_INIT;
    991     }
    992 
    993     if (!soc_mem_field_valid(unit, sr_mp_dev_info->mem,
    994                              sr_mp_dev_info->field)) {
    995         LOG_ERROR(BSL_LS_BCM_TSN,
    996                   (BSL_META_U(unit,
    997                               "Memory %s or field is Not valid\n"),
    998                   SOC_MEM_UFNAME(unit, sr_mp_dev_info->mem)));
    999         return BCM_E_PARAM;
   1000     }
   1001 
   1002     /* Allocate TSN SR Mac Proxy entry memory by sr_mp_num */
   1003     sr_mp_bk_info->sr_mp_num = soc_mem_index_count(unit, sr_mp_dev_info->mem);
   1004     TSN_ALLOC(unit, sr_mp_bk_info->sr_mp_entry,
   1005               bcmi_esw_tsn_sr_mac_proxy_entry_t,
   1006               (sr_mp_bk_info->sr_mp_num *
   1007               sizeof(bcmi_esw_tsn_sr_mac_proxy_entry_t)),
   1008               "TSN SR Mac Proxy Entry", 0, rv);
   1009     if (BCM_FAILURE(rv)) {
   1010         LOG_VERBOSE(BSL_LS_BCM_TSN,
   1011                     (BSL_META_U(unit,
   1012                                 "bcmi_esw_tsn_sr_mac_proxy_init: "
   1013                                 "failed to allocate memory\n")));
   1014     }
   1015 
   1016     return rv;
   1017 }
   1018 
   1019 #ifdef BCM_WARM_BOOT_SUPPORT
   1020 /*
   1021  * Function:
   1022  *    bcmi_esw_tsn_sr_mac_proxy_reload
   1023  * Description:
   1024  *    Load TSN SR MAC Proxy info
   1025  *    from hardware into software data structures.
   1026  * Parameters:
   1027  *    unit - (IN) Unit number
   1028  */
   1029 STATIC int
   1030 bcmi_esw_tsn_sr_mac_proxy_reload(int unit)
   1031 {
   1032     int rv = BCM_E_NONE;
   1033     bcmi_esw_tsn_bk_info_t *tsn_bk_info;
   1034     bcmi_esw_tsn_sr_mac_proxy_bk_info_t *sr_mp_bk_info;
   1035     const bcmi_esw_tsn_dev_info_t *tsn_dev_info;
   1036     const tsn_sr_mac_proxy_info_t *sr_mp_dev_info;
   1037     bcmi_esw_tsn_sr_mac_proxy_entry_t *mp_entries;
   1038     uint32 entry[SOC_MAX_MEM_WORDS];
   1039     int cur_index;
   1040     bcm_pbmp_t mp_pbmp;
   1041     int index, l2x_size;
   1042     l2x_entry_t *l2x_entry, *l2x_table = NULL;
   1043 
   1044     LOG_DEBUG(BSL_LS_BCM_TSN,
   1045               (BSL_META_U(unit,
   1046                           "bcmi_esw_tsn_sr_mac_proxy_reload\n")));
   1047 
   1048     BCM_IF_ERROR_RETURN(
   1049         tsn_bk_info_instance_get(unit, &tsn_bk_info));
   1050 
   1051     /* Get chip specific assignment */
   1052     tsn_dev_info = tsn_bk_info->tsn_dev_info;
   1053     sr_mp_dev_info = tsn_dev_info->tsn_sr_mac_proxy_info;
   1054     if (sr_mp_dev_info == NULL) {
   1055         return BCM_E_UNAVAIL;
   1056     }
   1057 
   1058     /* Set up the unit TSN SR Mac Proxy bookkeeping info structure. */
   1059     sr_mp_bk_info = &(tsn_bk_info->tsn_sr_mac_proxy_bk_info);
   1060     mp_entries = sr_mp_bk_info->sr_mp_entry;
   1061     if (mp_entries == NULL) {
   1062         return BCM_E_UNAVAIL;
   1063     }
   1064 
   1065     SR_MAC_PROXY_LOCK(sr_mp_bk_info);
   1066     /*
   1067      * Refresh TSN SR MAC Proxy information from the hardware tables.
   1068      */
   1069     for (cur_index = 0; cur_index < sr_mp_bk_info->sr_mp_num; cur_index++) {
   1070         sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   1071         rv = soc_mem_read(unit, sr_mp_dev_info->mem, MEM_BLOCK_ANY,
   1072                           cur_index, entry);
   1073         if (BCM_FAILURE(rv)) {
   1074             SR_MAC_PROXY_UNLOCK(sr_mp_bk_info);
   1075             return rv;
   1076         }
   1077 
   1078         BCM_PBMP_CLEAR(mp_pbmp);
   1079         soc_mem_pbmp_field_get(unit, sr_mp_dev_info->mem, entry,
   1080                                sr_mp_dev_info->field, &mp_pbmp);
   1081 
   1082         BCM_PBMP_ASSIGN(mp_entries[cur_index].mp_pbmp, mp_pbmp);
   1083     }
   1084     SR_MAC_PROXY_UNLOCK(sr_mp_bk_info);
   1085 
   1086     /* Refresh ref_count for L2 usage */
   1087     if (soc_mem_field_valid(unit, L2Xm, SR_MAC_PROXY_PROFILE_PTRf)) {
   1088         l2x_size = sizeof(l2x_entry_t) * soc_mem_index_count(unit, L2Xm);
   1089         TSN_ALLOC(unit, l2x_table, l2x_entry_t, l2x_size,
   1090                   "tsn_sr_mac_proxy l2 reload", 1, rv);
   1091         if (BCM_FAILURE(rv)) {
   1092             LOG_VERBOSE(BSL_LS_BCM_TSN,
   1093                         (BSL_META_U(unit,
   1094                                     "bcmi_esw_tsn_sr_mac_proxy_reload: "
   1095                                     "failed to allocate memory\n")));
   1096             return rv;
   1097         }
   1098         if (soc_mem_read_range(unit, L2Xm, MEM_BLOCK_ANY,
   1099                                soc_mem_index_min(unit, L2Xm),
   1100                                soc_mem_index_max(unit, L2Xm),
   1101                                l2x_table) < 0) {
   1102             soc_cm_sfree(unit, l2x_table);
   1103             return SOC_E_INTERNAL;
   1104         }
   1105 
   1106         SR_MAC_PROXY_LOCK(sr_mp_bk_info);
   1107         for (index = soc_mem_index_min(unit, L2Xm);
   1108             index <= soc_mem_index_max(unit, L2Xm); index++) {
   1109             l2x_entry = soc_mem_table_idx_to_pointer(unit, L2Xm,
   1110                                                      l2x_entry_t *,
   1111                                                      l2x_table, index);
   1112              if (!soc_L2Xm_field32_get(unit, l2x_entry, VALIDf)) {
   1113                  continue;
   1114              }
   1115 
   1116              cur_index = soc_L2Xm_field32_get(unit, l2x_entry,
   1117                                               SR_MAC_PROXY_PROFILE_PTRf);
   1118              if ((cur_index > 0) && (cur_index < sr_mp_bk_info->sr_mp_num)) {
   1119                  mp_entries[cur_index].ref_count++;
   1120              }
   1121         }
   1122         SR_MAC_PROXY_UNLOCK(sr_mp_bk_info);
   1123 
   1124         soc_cm_sfree(unit, l2x_table);
   1125     } else {
   1126         return BCM_E_INTERNAL;
   1127     }
   1128 
   1129     return BCM_E_NONE;
   1130 }
   1131 
   1132 STATIC int
   1133 bcmi_esw_tsn_pri_map_existed_check(
   1134     int unit,
   1135     bcm_tsn_pri_map_config_t *config,
   1136     bcm_tsn_pri_map_t *map_id);
   1137 
   1138 /*
   1139  * Function:
   1140  *      bcmi_esw_tsn_egress_mtu_sync
   1141  * Purpose:
   1142  *      Synchronize the egr mtu sw data into scache
   1143  * Parameters:
   1144  *      unit - (IN) Unit number
   1145  * Returns:
   1146  *      BCM_E_xxx
   1147  */
   1148 STATIC int
   1149 bcmi_esw_tsn_egress_mtu_sync(int unit)
   1150 {
   1151     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   1152     const tsn_mtu_info_t *ctrl_info = NULL;
   1153 
   1154     soc_scache_handle_t scache_handle;
   1155     uint8 *map_id_scache;
   1156     int idx;
   1157     uint32 alloc;
   1158 
   1159     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   1160     /* Use this init macro after the bk info instance get */
   1161     MTU_DEV_INIT(unit);
   1162     ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
   1163 
   1164     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN,
   1165                           BCM_TSN_WB_SCACHE_PART_EGR_MTU);
   1166     /* allocate the scache pointer size */
   1167     alloc = sizeof(bcm_tsn_pri_map_t) * ctrl_info->logical_port_num;
   1168     BCM_IF_ERROR_RETURN(
   1169         _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
   1170                                 alloc, &map_id_scache,
   1171                                 BCM_TSN_WB_DEFAULT_VERSION, NULL));
   1172     if (map_id_scache == NULL ||
   1173         bk_info->tsn_mtu_bk_info.pri_map_port == NULL) {
   1174         return BCM_E_INTERNAL;
   1175     }
   1176 
   1177     MTU_BK_LOCK(unit);
   1178     for (idx = 0; idx < ctrl_info->logical_port_num; idx++) {
   1179         sal_memcpy(map_id_scache,
   1180                    &(bk_info->tsn_mtu_bk_info.pri_map_port[idx]),
   1181                    sizeof(bcm_tsn_pri_map_t));
   1182         map_id_scache += sizeof(bcm_tsn_pri_map_t);
   1183     }
   1184     MTU_BK_UNLOCK(unit);
   1185     return BCM_E_NONE;
   1186 }
   1187 
   1188 /*
   1189  * Function:
   1190  *      bcmi_esw_tsn_egress_mtu_reload
   1191  * Purpose:
   1192  *      Reload the scache data into egr mtu sw data structure
   1193  * Parameters:
   1194  *      unit - (IN) Unit number
   1195  * Returns:
   1196  *      BCM_E_xxx
   1197  */
   1198 STATIC int
   1199 bcmi_esw_tsn_egress_mtu_reload(int unit)
   1200 {
   1201     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   1202     const tsn_mtu_info_t *ctrl_info = NULL;
   1203 
   1204     bcm_tsn_pri_map_config_t config;
   1205     soc_scache_handle_t scache_handle;
   1206     uint8 *map_id_scache;
   1207     int idx, rv, rv1, i, prof_idx, prof_id;
   1208     bcm_tsn_pri_map_t map_id;
   1209     bcm_tsn_mtu_profile_type_t type;
   1210 
   1211     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   1212     /* Use this init macro after the bk info instance get */
   1213     MTU_DEV_INIT(unit);
   1214     ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
   1215 
   1216     LOG_DEBUG(BSL_LS_BCM_TSN,
   1217               (BSL_META_U(unit,
   1218                          "bcmi_esw_tsn_egress_mtu_reload\n")));
   1219 
   1220     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN,
   1221                           BCM_TSN_WB_SCACHE_PART_EGR_MTU);
   1222     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
   1223                                  0, &map_id_scache, BCM_TSN_WB_DEFAULT_VERSION,
   1224                                  NULL);
   1225     if (bk_info->tsn_mtu_bk_info.pri_map_port == NULL) {
   1226         return BCM_E_INTERNAL;
   1227     }
   1228 
   1229     if (rv == BCM_E_NOT_FOUND) {
   1230         rv1 = _bcm_esw_scache_ptr_get(
   1231                     unit, scache_handle, TRUE, sizeof(bcm_tsn_pri_map_t),
   1232                     &map_id_scache, BCM_TSN_WB_DEFAULT_VERSION, NULL);
   1233         if (BCM_E_NOT_FOUND == rv1) {
   1234             /* Proceed with Level 1 Warm Boot */
   1235             rv1 = BCM_E_NONE;
   1236         }
   1237         BCM_IF_ERROR_RETURN(rv1);
   1238         return BCM_E_NONE;
   1239     } else if (rv == BCM_E_NONE) {
   1240         if (map_id_scache == NULL) {
   1241             return BCM_E_INTERNAL;
   1242         }
   1243         MTU_BK_LOCK(unit);
   1244         for (idx = 0; idx < ctrl_info->logical_port_num; idx++) {
   1245             sal_memcpy(&(bk_info->tsn_mtu_bk_info.pri_map_port[idx]),
   1246                        map_id_scache,
   1247                        sizeof(bcm_tsn_pri_map_t));
   1248             map_id_scache += sizeof(bcm_tsn_pri_map_t);
   1249             rv1 = ctrl_info->egress_mtu_wb_reload(unit, idx, &config);
   1250             if (BCM_FAILURE(rv1)) {
   1251                 MTU_BK_UNLOCK(unit);
   1252                 return rv1;
   1253             }
   1254             /* Check whether the config has been added before */
   1255             rv1 = bcmi_esw_tsn_pri_map_existed_check(unit, &config, &map_id);
   1256             if (rv1 == BCM_E_NOT_FOUND) {
   1257                 /* MTU profile reference count update */
   1258                 for (i = 0; i < config.num_map_entries; i++) {
   1259                     prof_id = config.map_entries[i].profile_id;
   1260                     ctrl_info->mtu_profile_decode(
   1261                         unit, prof_id, &type, &prof_idx);
   1262                     /* MTU profile entry == 0 is invalid */
   1263                     if (prof_idx != 0) {
   1264                         bcmi_esw_tsn_mtu_profile_ref_inc(unit, prof_id);
   1265                     }
   1266                 }
   1267                 /* Provide priority map structure the related mtu wb information */
   1268                 bcmi_esw_tsn_pri_map_mtu_stu_wb_set(
   1269                     unit, bk_info->tsn_mtu_bk_info.pri_map_port[idx], &config);
   1270             }
   1271 
   1272         }
   1273 
   1274         MTU_BK_UNLOCK(unit);
   1275     }
   1276 
   1277     return rv;
   1278 }
   1279 
   1280 /*
   1281  * Function:
   1282  *      bcmi_esw_tsn_egress_stu_sync
   1283  * Purpose:
   1284  *      Synchronize the egr stu sw data into scache
   1285  * Parameters:
   1286  *      unit - (IN) Unit number
   1287  * Returns:
   1288  *      BCM_E_xxx
   1289  */
   1290 STATIC int
   1291 bcmi_esw_tsn_egress_stu_sync(int unit)
   1292 {
   1293     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   1294     const tsn_stu_info_t *ctrl_info = NULL;
   1295 
   1296     soc_scache_handle_t scache_handle;
   1297     uint8 *map_id_scache;
   1298     int idx;
   1299     uint32 alloc;
   1300 
   1301     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   1302     /* Use this init macro after the bk info instance get */
   1303     STU_DEV_INIT(unit);
   1304     ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
   1305 
   1306     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN,
   1307                           BCM_TSN_WB_SCACHE_PART_EGR_STU);
   1308     /* allocate the scache pointer size */
   1309     alloc = sizeof(bcm_tsn_pri_map_t) * ctrl_info->logical_port_num;
   1310     BCM_IF_ERROR_RETURN(
   1311         _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE,
   1312                                 alloc, &map_id_scache,
   1313                                 BCM_TSN_WB_DEFAULT_VERSION, NULL));
   1314     if (map_id_scache == NULL ||
   1315         bk_info->tsn_stu_bk_info.pri_map_port == NULL) {
   1316         return BCM_E_INTERNAL;
   1317     }
   1318 
   1319     STU_BK_LOCK(unit);
   1320     for (idx = 0; idx < ctrl_info->logical_port_num; idx++) {
   1321         sal_memcpy(map_id_scache,
   1322                    &(bk_info->tsn_stu_bk_info.pri_map_port[idx]),
   1323                    sizeof(bcm_tsn_pri_map_t));
   1324         map_id_scache += sizeof(bcm_tsn_pri_map_t);
   1325     }
   1326     STU_BK_UNLOCK(unit);
   1327     return BCM_E_NONE;
   1328 }
   1329 
   1330 /*
   1331  * Function:
   1332  *      bcmi_esw_tsn_egress_stu_reload
   1333  * Purpose:
   1334  *      Reload the scache data into egr stu sw data structure
   1335  * Parameters:
   1336  *      unit - (IN) Unit number
   1337  * Returns:
   1338  *      BCM_E_xxx
   1339  */
   1340 STATIC int
   1341 bcmi_esw_tsn_egress_stu_reload(int unit)
   1342 {
   1343     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   1344     const tsn_stu_info_t *ctrl_info = NULL;
   1345 
   1346     bcm_tsn_pri_map_config_t config;
   1347     soc_scache_handle_t scache_handle;
   1348     uint8 *map_id_scache;
   1349     int idx, rv, rv1, i, prof_idx, prof_id;
   1350     bcm_tsn_pri_map_t map_id;
   1351     bcm_tsn_stu_profile_type_t type;
   1352 
   1353     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   1354     /* Use this init macro after the bk info instance get */
   1355     STU_DEV_INIT(unit);
   1356     ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
   1357 
   1358     LOG_DEBUG(BSL_LS_BCM_TSN,
   1359               (BSL_META_U(unit,
   1360                          "bcmi_esw_tsn_egress_stu_reload\n")));
   1361 
   1362     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN,
   1363                           BCM_TSN_WB_SCACHE_PART_EGR_STU);
   1364     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE,
   1365                                  0, &map_id_scache, BCM_TSN_WB_DEFAULT_VERSION,
   1366                                  NULL);
   1367     if (bk_info->tsn_stu_bk_info.pri_map_port == NULL) {
   1368         return BCM_E_INTERNAL;
   1369     }
   1370     if (rv == BCM_E_NOT_FOUND) {
   1371         rv1 = _bcm_esw_scache_ptr_get(
   1372                     unit, scache_handle, TRUE, sizeof(bcm_tsn_pri_map_t),
   1373                     &map_id_scache, BCM_TSN_WB_DEFAULT_VERSION, NULL);
   1374         if (BCM_E_NOT_FOUND == rv1) {
   1375             /* Proceed with Level 1 Warm Boot */
   1376             rv1 = BCM_E_NONE;
   1377         }
   1378         BCM_IF_ERROR_RETURN(rv1);
   1379         return BCM_E_NONE;
   1380     } else if (rv == BCM_E_NONE) {
   1381         if (map_id_scache == NULL) {
   1382             return BCM_E_INTERNAL;
   1383         }
   1384         STU_BK_LOCK(unit);
   1385         for (idx = 0; idx < ctrl_info->logical_port_num; idx++) {
   1386             sal_memcpy(&(bk_info->tsn_stu_bk_info.pri_map_port[idx]),
   1387                        map_id_scache,
   1388                        sizeof(bcm_tsn_pri_map_t));
   1389             map_id_scache += sizeof(bcm_tsn_pri_map_t);
   1390             rv1 = ctrl_info->egress_stu_wb_reload(unit, idx, &config);
   1391             if (BCM_FAILURE(rv1)) {
   1392                 STU_BK_UNLOCK(unit);
   1393                 return rv1;
   1394             }
   1395             /* Check whether the config has been added before */
   1396             rv1 = bcmi_esw_tsn_pri_map_existed_check(unit, &config, &map_id);
   1397             if (rv1 == BCM_E_NOT_FOUND) {
   1398                 /* STU profile reference count update */
   1399                 for (i = 0; i < config.num_map_entries; i++) {
   1400                     prof_id = config.map_entries[i].profile_id;
   1401                     ctrl_info->stu_profile_decode(
   1402                         unit, prof_id, &type, &prof_idx);
   1403                     /* STU profile entry == 0 is invalid */
   1404                     if (prof_idx != 0) {
   1405                         bcmi_esw_tsn_stu_profile_ref_inc(unit, prof_id);
   1406                     }
   1407                 }
   1408                 /* Provide priority map structure the related stu wb information */
   1409                 bcmi_esw_tsn_pri_map_mtu_stu_wb_set(
   1410                     unit, bk_info->tsn_stu_bk_info.pri_map_port[idx], &config);
   1411             }
   1412         }
   1413 
   1414         STU_BK_UNLOCK(unit);
   1415     }
   1416     return rv;
   1417 }
   1418 
   1419 /*
   1420  * Function:
   1421  *     bcmi_esw_tsn_sr_port_prp_forwarding_sync
   1422  * Purpose:
   1423  *      Synchronize the prp-forwarding sw data into scache
   1424  * Parameters:
   1425  *      unit - (IN) Unit number
   1426 
   1427  * Returns:
   1428  *     BCM_E_XXX
   1429  * Notes:
   1430  */
   1431 STATIC int
   1432 bcmi_esw_tsn_sr_port_prp_forwarding_sync(
   1433     int unit)
   1434 {
   1435     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   1436     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   1437     const tsn_sr_port_dev_info_t *sr_port_config = NULL;
   1438     soc_scache_handle_t scache_handle;
   1439 
   1440     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   1441     dev_info = bk_info->tsn_dev_info;
   1442     if (dev_info == NULL) {
   1443         return BCM_E_UNAVAIL;
   1444     }
   1445     sr_port_config = dev_info->sr_port_info;
   1446     if ((sr_port_config == NULL) ||
   1447         (sr_port_config->sr_port_prp_forwarding_wb_sync == NULL)) {
   1448         return BCM_E_UNAVAIL;
   1449     }
   1450 
   1451     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN,
   1452                           BCM_TSN_WB_SCACHE_PART_PRP_FORWARDING);
   1453 
   1454     return sr_port_config->sr_port_prp_forwarding_wb_sync(unit, scache_handle);
   1455 }
   1456 
   1457 /*
   1458  * Function:
   1459  *     bcmi_esw_tsn_sr_port_prp_forwarding_reload
   1460  * Purpose:
   1461  *      Reload the scache data into prp-forwarding sw data
   1462  * Parameters:
   1463  *      unit - (IN) Unit number
   1464 
   1465  * Returns:
   1466  *     BCM_E_XXX
   1467  * Notes:
   1468  */
   1469 STATIC int
   1470 bcmi_esw_tsn_sr_port_prp_forwarding_reload(
   1471     int unit)
   1472 {
   1473     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   1474     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   1475     const tsn_sr_port_dev_info_t *sr_port_config = NULL;
   1476     soc_scache_handle_t scache_handle;
   1477 
   1478     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   1479     dev_info = bk_info->tsn_dev_info;
   1480     if (dev_info == NULL) {
   1481         return BCM_E_UNAVAIL;
   1482     }
   1483     sr_port_config = dev_info->sr_port_info;
   1484     if ((sr_port_config == NULL) ||
   1485         (sr_port_config->sr_port_prp_forwarding_wb_reload == NULL)) {
   1486         return BCM_E_UNAVAIL;
   1487     }
   1488 
   1489     SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN,
   1490                           BCM_TSN_WB_SCACHE_PART_PRP_FORWARDING);
   1491 
   1492     return
   1493         sr_port_config->sr_port_prp_forwarding_wb_reload(unit, scache_handle);
   1494 }
   1495 #endif /* BCM_WARM_BOOT_SUPPORT */
   1496 
   1497 /*
   1498  * Function:
   1499  *    bcmi_esw_tsn_sr_mac_proxy_insert
   1500  * Purpose:
   1501  *    Find or create a TSN SR MAC Proxy table entry
   1502  *    matching the given bitmap.
   1503  * Parameters:
   1504  *    unit - (IN) Unit number
   1505  *    mp_pbmp  - (IN) Port bitmap for SR source MAC Proxy
   1506  *    mp_index - (OUT) Index of TSN SR MAC Proxy table with bitmap
   1507  * Returns:
   1508  *    BCM_E_NONE - Success.
   1509  *    BCM_E_INTERNAL - Chip access failure.
   1510  *    BCM_E_RESOURCE - No more TSN SR MAC Proxy entries available.
   1511  *    BCM_E_PARAM - Illegal parameter.
   1512  */
   1513 int
   1514 bcmi_esw_tsn_sr_mac_proxy_insert(
   1515     int unit,
   1516     bcm_pbmp_t mp_pbmp,
   1517     int *mp_index)
   1518 {
   1519     int rv = BCM_E_NONE;
   1520     bcmi_esw_tsn_bk_info_t *tsn_bk_info;
   1521     const bcmi_esw_tsn_dev_info_t *tsn_dev_info;
   1522     const tsn_sr_mac_proxy_info_t *sr_mp_dev_info;
   1523     bcmi_esw_tsn_sr_mac_proxy_bk_info_t *sr_mp_bk_info;
   1524     bcmi_esw_tsn_sr_mac_proxy_entry_t *mp_entries;
   1525     uint32 entry[SOC_MAX_MEM_WORDS];
   1526     bcm_pbmp_t temp_pbmp;
   1527     int cur_index = 0;
   1528 
   1529     LOG_VERBOSE(BSL_LS_BCM_TSN,
   1530                 (BSL_META_U(unit,
   1531                             "bcmi_esw_tsn_sr_mac_proxy_insert\n")));
   1532 
   1533     /* Check if TSN SR feature supported */
   1534     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   1535         return BCM_E_UNAVAIL;
   1536     }
   1537 
   1538     /* Check for input parameter */
   1539     if (NULL == mp_index) {
   1540         return BCM_E_PARAM;
   1541     }
   1542 
   1543     /* Check for reasonable pbmp */
   1544     BCM_PBMP_ASSIGN(temp_pbmp, mp_pbmp);
   1545     BCM_PBMP_AND(temp_pbmp, PBMP_ALL(unit));
   1546     if (BCM_PBMP_NEQ(mp_pbmp, temp_pbmp)) {
   1547         return BCM_E_PARAM;
   1548     }
   1549 
   1550     BCM_IF_ERROR_RETURN(
   1551         tsn_bk_info_instance_get(unit, &tsn_bk_info));
   1552 
   1553     /* Get chip specific assignment */
   1554     tsn_dev_info = tsn_bk_info->tsn_dev_info;
   1555     sr_mp_dev_info = tsn_dev_info->tsn_sr_mac_proxy_info;
   1556     if (sr_mp_dev_info == NULL) {
   1557         return BCM_E_UNAVAIL;
   1558     }
   1559 
   1560     /* Set up the unit TSN SR Mac Proxy bookkeeping info structure. */
   1561     sr_mp_bk_info = &(tsn_bk_info->tsn_sr_mac_proxy_bk_info);
   1562     mp_entries = sr_mp_bk_info->sr_mp_entry;
   1563     if (mp_entries == NULL) {
   1564         return BCM_E_UNAVAIL;
   1565     }
   1566 
   1567     SR_MAC_PROXY_LOCK(sr_mp_bk_info);
   1568 
   1569     /* Compare the bitmap with existing entries */
   1570     for (cur_index = 0; cur_index < sr_mp_bk_info->sr_mp_num; cur_index++) {
   1571         if (mp_entries[cur_index].ref_count != 0) {
   1572             if (BCM_PBMP_EQ(mp_entries[cur_index].mp_pbmp, mp_pbmp)) {
   1573                 mp_entries[cur_index].ref_count++;
   1574                 *mp_index = cur_index;
   1575                 SR_MAC_PROXY_UNLOCK(sr_mp_bk_info);
   1576                 return BCM_E_NONE;
   1577             }
   1578         }
   1579     }
   1580 
   1581     /*
   1582      * Not in table already, see if any space free
   1583      * (index 0 is reserved by default)
   1584      */
   1585     for (cur_index = 1; cur_index < sr_mp_bk_info->sr_mp_num; cur_index++) {
   1586         if (mp_entries[cur_index].ref_count == 0) {
   1587             /* Attempt insert */
   1588             sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS);
   1589             rv = soc_mem_read(unit, sr_mp_dev_info->mem, MEM_BLOCK_ANY,
   1590                               cur_index, entry);
   1591             if (BCM_FAILURE(rv)) {
   1592                 SR_MAC_PROXY_UNLOCK(sr_mp_bk_info);
   1593                 return rv;
   1594             }
   1595 
   1596             soc_mem_pbmp_field_set(unit, sr_mp_dev_info->mem, entry,
   1597                                    sr_mp_dev_info->field, &mp_pbmp);
   1598 
   1599             rv = soc_mem_write(unit, sr_mp_dev_info->mem, MEM_BLOCK_ALL,
   1600                                cur_index, entry);
   1601             if (BCM_FAILURE(rv)) {
   1602                 SR_MAC_PROXY_UNLOCK(sr_mp_bk_info);
   1603                 return rv;
   1604             }
   1605 
   1606             mp_entries[cur_index].ref_count++;
   1607             BCM_PBMP_ASSIGN(mp_entries[cur_index].mp_pbmp, mp_pbmp);
   1608             *mp_index = cur_index;
   1609 
   1610             SR_MAC_PROXY_UNLOCK(sr_mp_bk_info);
   1611             return BCM_E_NONE;
   1612         }
   1613     }
   1614 
   1615     /* Didn't find a free slot, out of table space */
   1616     SR_MAC_PROXY_UNLOCK(sr_mp_bk_info);
   1617     return BCM_E_RESOURCE;
   1618 }
   1619 
   1620 /*
   1621  * Function:
   1622  *    bcmi_esw_tsn_sr_mac_proxy_delete
   1623  * Purpose:
   1624  *    Remove reference to TSN SR MAC Proxy table entry
   1625  *    matching the given bitmap.
   1626  * Parameters:
   1627  *    unit - (IN) Unit number
   1628  *    mp_index - (IN) Index of TSN SR MAC Proxy table with bitmap
   1629  * Returns:
   1630  *    BCM_E_XXX.
   1631  */
   1632 int
   1633 bcmi_esw_tsn_sr_mac_proxy_delete(int unit, int mp_index)
   1634 {
   1635     bcmi_esw_tsn_bk_info_t *tsn_bk_info;
   1636     bcmi_esw_tsn_sr_mac_proxy_bk_info_t *sr_mp_bk_info;
   1637     bcmi_esw_tsn_sr_mac_proxy_entry_t *mp_entries;
   1638 
   1639     LOG_VERBOSE(BSL_LS_BCM_TSN,
   1640                 (BSL_META_U(unit,
   1641                             "bcmi_esw_tsn_sr_mac_proxy_delete\n")));
   1642 
   1643     /* Check if TSN SR feature supported */
   1644     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   1645         return BCM_E_UNAVAIL;
   1646     }
   1647 
   1648     BCM_IF_ERROR_RETURN(
   1649         tsn_bk_info_instance_get(unit, &tsn_bk_info));
   1650 
   1651     /* Set up the unit TSN SR Mac Proxy bookkeeping info structure. */
   1652     sr_mp_bk_info = &(tsn_bk_info->tsn_sr_mac_proxy_bk_info);
   1653     mp_entries = sr_mp_bk_info->sr_mp_entry;
   1654 
   1655     /* Check for reasonable entry index (0 is reserved by default) */
   1656     if (mp_index <= 0 || mp_index >= sr_mp_bk_info->sr_mp_num) {
   1657         return BCM_E_PARAM;
   1658     }
   1659 
   1660     SR_MAC_PROXY_LOCK(sr_mp_bk_info);
   1661     if (mp_entries[mp_index].ref_count > 0) {
   1662         mp_entries[mp_index].ref_count--;
   1663     } else {
   1664         /* Check if the ref_count is zero: return BCM_E_NOT_FOUND */
   1665         SR_MAC_PROXY_UNLOCK(sr_mp_bk_info);
   1666         return BCM_E_NOT_FOUND;
   1667     }
   1668 
   1669     /* Clear software port bitmap if the ref_count is decreased to zero */
   1670     if (mp_entries[mp_index].ref_count == 0) {
   1671         BCM_PBMP_CLEAR(mp_entries[mp_index].mp_pbmp);
   1672     }
   1673 
   1674     SR_MAC_PROXY_UNLOCK(sr_mp_bk_info);
   1675     return BCM_E_NONE;
   1676 }
   1677 
   1678 /*
   1679  * Function:
   1680  *    bcmi_esw_tsn_sr_mac_proxy_get
   1681  * Purpose:
   1682  *    Get Port bitmap from software SR MAC Proxy table
   1683  *    with given index of TSN SR MAC Proxy table.
   1684  * Parameters:
   1685  *    unit - (IN) Unit number
   1686  *    mp_index - (IN) Index of TSN SR MAC Proxy table with bitmap
   1687  *    mp_pbmp  - (OUT) Port bitmap for SR source MAC Proxy
   1688  * Returns:
   1689  *    BCM_E_XXX.
   1690  */
   1691 int
   1692 bcmi_esw_tsn_sr_mac_proxy_get(int unit, int mp_index, bcm_pbmp_t *mp_pbmp)
   1693 {
   1694     bcmi_esw_tsn_bk_info_t *tsn_bk_info;
   1695     bcmi_esw_tsn_sr_mac_proxy_bk_info_t *sr_mp_bk_info;
   1696     bcmi_esw_tsn_sr_mac_proxy_entry_t *mp_entries;
   1697 
   1698     LOG_VERBOSE(BSL_LS_BCM_TSN,
   1699                 (BSL_META_U(unit,
   1700                             "bcmi_esw_tsn_sr_mac_proxy_get\n")));
   1701 
   1702     /* Check if TSN SR feature supported */
   1703     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   1704         return BCM_E_UNAVAIL;
   1705     }
   1706 
   1707     BCM_IF_ERROR_RETURN(
   1708         tsn_bk_info_instance_get(unit, &tsn_bk_info));
   1709 
   1710     /* Set up the unit TSN SR Mac Proxy bookkeeping info structure. */
   1711     sr_mp_bk_info = &(tsn_bk_info->tsn_sr_mac_proxy_bk_info);
   1712     mp_entries = sr_mp_bk_info->sr_mp_entry;
   1713 
   1714     /* Check for reasonable entry index (0 is reserved by default) */
   1715     if (mp_index <= 0 || mp_index >= sr_mp_bk_info->sr_mp_num) {
   1716         return BCM_E_PARAM;
   1717     }
   1718 
   1719     SR_MAC_PROXY_LOCK(sr_mp_bk_info);
   1720     BCM_PBMP_ASSIGN(*mp_pbmp, mp_entries[mp_index].mp_pbmp);
   1721     SR_MAC_PROXY_UNLOCK(sr_mp_bk_info);
   1722 
   1723     return BCM_E_NONE;
   1724 }
   1725 
   1726 /* SR flow: free a chain of one or more continuous flow indexes */
   1727 STATIC int
   1728 bcmi_esw_tsn_sr_flow_idx_free(int unit, int dir, tsn_sr_flowidx_entry_t *entry)
   1729 {
   1730     bcmi_esw_tsn_bk_info_t *tsn_bk;
   1731     tsn_sr_flows_bookkeeping_t *bkinfo;
   1732     tsn_sr_flowidx_entry_t *fid, *prev, *last;
   1733     int eidx;
   1734 
   1735     /* parameter check */
   1736     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   1737     if (dir < 0 || dir >= SR_FLOW_DIR_COUNT || entry == NULL) {
   1738         return BCM_E_PARAM;
   1739     }
   1740 
   1741     /* Protect access to the flow indexes */
   1742     SR_FLOW_MGMT_LOCK(unit);
   1743 
   1744     /* Traverse the list and insert the chain into the list */
   1745     bkinfo = &tsn_bk->sr_flows;
   1746     eidx = entry->flow_idx;
   1747     prev = NULL;
   1748     for (fid = bkinfo->flowids_avail[dir]; fid != NULL; fid = fid->next) {
   1749 
   1750         /* If the index is smaller than current, insert before current */
   1751         if (eidx < fid->flow_idx) {
   1752             /* Find the last item in the supplied chain */
   1753             for (last = entry; last->next != NULL; last = last->next);
   1754             /* Connect remaining items to the chain */
   1755             last->next = fid;
   1756             /* Insert the chain to the list */
   1757             if (NULL == prev) {
   1758                 bkinfo->flowids_avail[dir] = entry;
   1759             } else {
   1760                 prev->next = entry;
   1761             }
   1762             SR_FLOW_MGMT_UNLOCK(unit);
   1763             return BCM_E_NONE;
   1764         }
   1765 
   1766         /* all indexes should be different */
   1767         assert(eidx != fid->flow_idx);
   1768 
   1769         /* record the previous item */
   1770         prev = fid;
   1771     }
   1772 
   1773     /* The index is larger than all items in the list, append it at the end */
   1774     if (NULL == prev) {
   1775         bkinfo->flowids_avail[dir] = entry;
   1776     } else {
   1777         prev->next = entry;
   1778     }
   1779     SR_FLOW_MGMT_UNLOCK(unit);
   1780     return BCM_E_NONE;
   1781 }
   1782 
   1783 /* SR flow: allocate one or more continuous flow idx(s) */
   1784 STATIC int
   1785 bcmi_esw_tsn_sr_flow_idx_allocate(
   1786     int unit,
   1787     int dir,
   1788     int count,
   1789     tsn_sr_flowidx_entry_t **entry)
   1790 {
   1791     bcmi_esw_tsn_bk_info_t *tsn_bk;
   1792     tsn_sr_flows_bookkeeping_t *bkinfo;
   1793     tsn_sr_flowidx_entry_t *fid, *begin, *prev, *bprev;
   1794     int idx, bidx;
   1795 
   1796     /* parameter check */
   1797     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   1798     if (dir < 0 || dir >= SR_FLOW_DIR_COUNT || count <= 0 || entry == NULL) {
   1799         return BCM_E_PARAM;
   1800     }
   1801 
   1802     /* Protect access to the flow indexes */
   1803     SR_FLOW_MGMT_LOCK(unit);
   1804 
   1805     /* Check if any index is available */
   1806     bkinfo = &tsn_bk->sr_flows;
   1807     if (NULL == bkinfo->flowids_avail[dir]) {
   1808         SR_FLOW_MGMT_UNLOCK(unit);
   1809         return BCM_E_RESOURCE;
   1810     }
   1811 
   1812     /*
   1813      * Quick retrieval for typical case: count == 1.
   1814      * Dynamic software learning may be performed for HSR/PRP where the count
   1815      * should always be 1. We need to make this as quick as possible.
   1816      * Here we should be able to do it in O(1) using pre-allocated linked list.
   1817      */
   1818     if (1 == count) {
   1819         /* Get one entry from the head */
   1820         fid = bkinfo->flowids_avail[dir];
   1821         bkinfo->flowids_avail[dir] = fid->next;
   1822         fid->next = NULL;
   1823         *entry = fid;
   1824         SR_FLOW_MGMT_UNLOCK(unit);
   1825         return BCM_E_NONE;
   1826     }
   1827 
   1828     /* Traverse the list and search for enough continuous items to allocate */
   1829     idx = bidx = bkinfo->max_flows[dir]; /* invalid current index */
   1830     prev = bprev = begin = NULL;
   1831     for (fid = bkinfo->flowids_avail[dir]; fid != NULL; fid = fid->next) {
   1832 
   1833         /* Check if it's continuous */
   1834         if (idx + 1 != fid->flow_idx) {
   1835             /* Index not continuous, restart the searching */
   1836             idx = fid->flow_idx;
   1837             bidx = idx;
   1838             begin = fid;
   1839             bprev = prev;
   1840         } else if (fid->flow_idx - bidx + 1 == count) {
   1841 
   1842             /*
   1843              * Found enough continuous flow indexes: update and return
   1844              */
   1845 
   1846             /* Update the linked list by removing the chain from the list */
   1847             if (NULL == bprev) {
   1848                 /* The chain is the head */
   1849                 bkinfo->flowids_avail[dir] = fid->next;
   1850             } else {
   1851                 /* Connect previous one to the next of the chain */
   1852                 bprev->next = fid->next;
   1853             }
   1854 
   1855             /* Terminate this chain and return */
   1856             fid->next = NULL;
   1857             *entry = begin;
   1858             SR_FLOW_MGMT_UNLOCK(unit);
   1859             return BCM_E_NONE;
   1860 
   1861         } else {
   1862             /* continuous but not yet reached the count */
   1863             idx++;
   1864         }
   1865 
   1866         /* record the previous one */
   1867         prev = fid;
   1868     }
   1869 
   1870     /* Cannot find enough continuous entries */
   1871     SR_FLOW_MGMT_UNLOCK(unit);
   1872     return BCM_E_RESOURCE;
   1873 }
   1874 
   1875 /*
   1876  * De-allocate an SR flowset and underlying flows with flowset index
   1877  * This function should be called with flowset mutex locked (if made public)
   1878  * and ref_count = 0.
   1879  */
   1880 STATIC int
   1881 bcmi_esw_tsn_sr_flowset_free(int unit, int dir, int fsid)
   1882 {
   1883     bcmi_esw_tsn_bk_info_t *tsn_bk;
   1884     tsn_sr_flows_bookkeeping_t *bkinfo;
   1885     tsn_sr_flowset_t *fset;
   1886     int rv = BCM_E_NONE;
   1887 
   1888     /* parameter check */
   1889     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   1890     if (dir < 0 || dir >= SR_FLOW_DIR_COUNT) {
   1891         return BCM_E_PARAM;
   1892     }
   1893     bkinfo = &tsn_bk->sr_flows;
   1894     fset = &bkinfo->flowsets[dir][fsid];
   1895 
   1896     /* Free flow indexes */
   1897     rv = bcmi_esw_tsn_sr_flow_idx_free(unit, dir, fset->flow_ide);
   1898 
   1899     /* Clear flowset data */
   1900     fset->flow_ide = NULL;
   1901     fset->num_flows = 0;
   1902 
   1903     return rv;
   1904 }
   1905 
   1906 /*
   1907  * Function:
   1908  *     bcmi_esw_tsn_sr_flowset_destroy
   1909  * Purpose:
   1910  *     Destroy an SR (TX or RX) flowset.
   1911  * Parameters:
   1912  *     unit             - (IN) unit number
   1913  *     flowset          - (IN) flowset ID
   1914  * Returns:
   1915  *     BCM_E_XXX
   1916  * Notes:
   1917  */
   1918 STATIC int
   1919 bcmi_esw_tsn_sr_flowset_destroy(int unit, bcm_tsn_sr_flowset_t flowset)
   1920 {
   1921     bcmi_esw_tsn_bk_info_t *tsn_bk;
   1922     tsn_sr_flows_bookkeeping_t *bkinfo;
   1923     tsn_sr_flowset_t *fset;
   1924     int dir, fsid;
   1925     int rv = BCM_E_NONE;
   1926     int i;
   1927 
   1928     /* parameter check */
   1929     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   1930     bkinfo = &tsn_bk->sr_flows;
   1931     dir = SR_FLOWSET_ID_TO_DIR(flowset);
   1932     fsid = SR_FLOWSET_ID_TO_IDX(flowset);
   1933     if (fsid < 0 || fsid >= bkinfo->max_flows[dir]) {
   1934         return BCM_E_PARAM;
   1935     }
   1936     fset = &bkinfo->flowsets[dir][fsid];
   1937     if (fset->num_flows == 0) {
   1938         /* Not allocated */
   1939         return BCM_E_NOT_FOUND;
   1940     }
   1941 
   1942     /* Check if it's still in use */
   1943     SR_FLOWSET_LOCK(fset);
   1944     if (fset->ref_count != 0) {
   1945         SR_FLOWSET_UNLOCK(fset);
   1946         return BCM_E_BUSY;
   1947     }
   1948 
   1949     /* Handle per-flow RX/TX specific clean up */
   1950     for (i = 0; i < fset->num_flows; i++) {
   1951         if (dir == SR_FLOW_DIR_RX) {
   1952             /* RX: de-allocate SN history slice and clear HW */
   1953             SR_FLOW_RX_LOCK(unit, fsid + i);
   1954             if (SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_free) {
   1955                 (void)SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_free(
   1956                         unit, bkinfo->flows_rx[fsid + i].sn_slice);
   1957             }
   1958             bkinfo->flows_rx[fsid + i].sn_slice = NULL;
   1959             if (SR_FLOW_MGMT_DEVINFO(unit)->clear_rx_flow) {
   1960                 (void)SR_FLOW_MGMT_DEVINFO(unit)->clear_rx_flow(unit, fsid + i);
   1961             }
   1962             if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   1963                 (void)bcmi_esw_tsn_mtu_profile_ref_dec(
   1964                   unit, bkinfo->flows_rx[fsid + i].config.ingress_mtu_profile);
   1965             }
   1966             SR_FLOW_RX_UNLOCK(unit, fsid + i);
   1967         } else {
   1968             /* TX: simply clear HW */
   1969             SR_FLOW_TX_LOCK(unit, fsid + i);
   1970             if (SR_FLOW_MGMT_DEVINFO(unit)->clear_tx_flow) {
   1971                 (void)SR_FLOW_MGMT_DEVINFO(unit)->clear_tx_flow(unit, fsid + i);
   1972             }
   1973             if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   1974                 (void)bcmi_esw_tsn_mtu_profile_ref_dec(
   1975                   unit, bkinfo->flows_tx[fsid + i].config.ingress_mtu_profile);
   1976             }
   1977             SR_FLOW_TX_UNLOCK(unit, fsid + i);
   1978         }
   1979         /* update active flow information for event management */
   1980         (void)bcmi_esw_tsn_event_rx_flow_delete(unit, fsid + i);
   1981     }
   1982 
   1983     /* De-allocate the flowset (note that mutex is always there) */
   1984     rv = bcmi_esw_tsn_sr_flowset_free(unit, dir, fsid);
   1985     SR_FLOWSET_UNLOCK(fset);
   1986     return rv;
   1987 }
   1988 
   1989 /* Allocate an SR flowset with both TX and RX directions */
   1990 STATIC int
   1991 bcmi_esw_tsn_sr_flowset_alloc(
   1992     int unit,
   1993     int dir,
   1994     bcm_tsn_pri_map_t pri_map,
   1995     int *pfsid)
   1996 {
   1997     bcmi_esw_tsn_bk_info_t *tsn_bk;
   1998     tsn_sr_flows_bookkeeping_t *bkinfo;
   1999     bcm_tsn_pri_map_config_t pmcfg;
   2000     tsn_sr_flowidx_entry_t *fids;
   2001     tsn_sr_flowset_t *fset;
   2002     int fsid;
   2003     int num_flows;
   2004     int rv;
   2005     int i;
   2006 
   2007     /* parameter check */
   2008     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   2009     if (dir < 0 || dir >= SR_FLOW_DIR_COUNT || pfsid == NULL) {
   2010         return BCM_E_PARAM;
   2011     }
   2012     bkinfo = &tsn_bk->sr_flows;
   2013 
   2014     /* Get number of flows from this priority map */
   2015     num_flows = 1;
   2016     if (pri_map != BCM_TSN_PRI_MAP_INVALID) {
   2017         /* call API to get priority map configuration */
   2018         rv = bcm_esw_tsn_pri_map_get(unit, pri_map, &pmcfg);
   2019         if (BCM_FAILURE(rv) || pmcfg.map_type != bcmTsnPriMapTypeSrFlow) {
   2020             return BCM_E_PARAM;
   2021         }
   2022         /* Number of flows is max flow offset + 1 */
   2023         for (i = 0; i < pmcfg.num_map_entries; i++) {
   2024             if ((pmcfg.map_entries[i].flags &
   2025                  BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET) &&
   2026                 (pmcfg.map_entries[i].flow_offset > num_flows - 1)) {
   2027                 num_flows = pmcfg.map_entries[i].flow_offset + 1;
   2028             }
   2029         }
   2030     }
   2031 
   2032     /* Allocate flow indexes */
   2033     rv = bcmi_esw_tsn_sr_flow_idx_allocate(unit, dir, num_flows, &fids);
   2034     if (BCM_FAILURE(rv)) {
   2035         return rv;
   2036     }
   2037 
   2038     /*
   2039      * For efficiency and convenience, the flowset index is the base (first)
   2040      * flow index so that we don't need to have another set of flowset
   2041      * allocation/free mechanism which would take more time in this time
   2042      * critical operation.
   2043      */
   2044     fsid = fids->flow_idx;
   2045     assert(fsid >= 0 && fsid + num_flows <= bkinfo->max_flows[dir]);
   2046 
   2047     /* Write to the flowset */
   2048     fset = &bkinfo->flowsets[dir][fsid];
   2049     SR_FLOWSET_LOCK(fset);
   2050     assert(fset->num_flows == 0);
   2051     fset->map_id = pri_map;
   2052     fset->flow_ide = fids;
   2053     fset->ref_count = 0;
   2054     fset->num_flows = num_flows;
   2055     SR_FLOWSET_UNLOCK(fset);
   2056 
   2057     /* Return the allocated flowset index */
   2058     *pfsid = fsid;
   2059     return BCM_E_NONE;
   2060 }
   2061 
   2062 /*
   2063  * Function:
   2064  *     bcmi_esw_tsn_sr_rx_flowset_create
   2065  * Purpose:
   2066  *     Create an SR RX flowset.
   2067  * Parameters:
   2068  *     unit             - (IN) unit number
   2069  *     pri_map          - (IN) TSN priority map ID
   2070  *     def_cfg          - (IN) default flow configuration
   2071  *     flowset          - (OUT) flowset ID
   2072  * Returns:
   2073  *     BCM_E_XXX
   2074  * Notes:
   2075  */
   2076 STATIC int
   2077 bcmi_esw_tsn_sr_rx_flowset_create(
   2078     int unit,
   2079     bcm_tsn_pri_map_t pri_map,
   2080     bcm_tsn_sr_rx_flow_config_t *def_cfg,
   2081     bcm_tsn_sr_flowset_t *flowset)
   2082 {
   2083     bcmi_esw_tsn_bk_info_t *tsn_bk;
   2084     tsn_sr_flows_bookkeeping_t *bkinfo;
   2085     tsn_sr_flowset_t *fset;
   2086     bcm_tsn_sr_flowset_t flowset_id;
   2087     bcmi_tsn_sr_rx_flow_t *flow;
   2088     bcmi_tsn_sr_seqnum_slice_t slice;
   2089     int fsid;
   2090     uint32 reset_mode;
   2091     uint32 flags;
   2092     int rv = BCM_E_NONE;
   2093     int i;
   2094 
   2095     /* parameter check */
   2096     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   2097     if (def_cfg == NULL || flowset == NULL) {
   2098         return BCM_E_PARAM;
   2099     }
   2100     bkinfo = &tsn_bk->sr_flows;
   2101 
   2102     /* sanity check for platform specific routines */
   2103     if (!SR_FLOW_MGMT_DEVINFO(unit)->check_rx_flow_config ||
   2104         !SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_alloc ||
   2105         !SR_FLOW_MGMT_DEVINFO(unit)->write_rx_flow) {
   2106         return BCM_E_UNAVAIL;
   2107     }
   2108 
   2109     /* Validate flow configuration */
   2110     BCM_IF_ERROR_RETURN(
   2111         SR_FLOW_MGMT_DEVINFO(unit)->check_rx_flow_config(unit, def_cfg));
   2112 
   2113     /* Allocate flows and flowset. Basic init check is also done inside. */
   2114     BCM_IF_ERROR_RETURN(
   2115         bcmi_esw_tsn_sr_flowset_alloc(unit, SR_FLOW_DIR_RX, pri_map, &fsid));
   2116     flowset_id = SR_FLOWSET_ID_FROM_IDX(SR_FLOW_DIR_RX, fsid);
   2117 
   2118     /* Write to the flowset software copy */
   2119     bkinfo = &tsn_bk->sr_flows;
   2120     fset = &bkinfo->flowsets[SR_FLOW_DIR_RX][fsid];
   2121     SR_FLOWSET_LOCK(fset);
   2122     sal_memcpy(&fset->config.rx, def_cfg, sizeof(fset->config.rx));
   2123 
   2124     /* Write to individual flows */
   2125     for (i = 0; i < fset->num_flows; i++) {
   2126         SR_FLOW_RX_LOCK(unit, fsid + i);
   2127         flow = &bkinfo->flows_rx[fsid + i];
   2128 
   2129         /* Allocate sequence number history pool for this flow */
   2130         rv = SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_alloc(
   2131                 unit, def_cfg->seqnum_history_win_size, &slice);
   2132         if (BCM_FAILURE(rv)) {
   2133             (void)bcmi_esw_tsn_sr_flowset_destroy(unit, flowset_id);
   2134             SR_FLOW_RX_UNLOCK(unit, fsid + i);
   2135             SR_FLOWSET_UNLOCK(fset);
   2136             return rv;
   2137         }
   2138 
   2139         /* Store the flow configuration */
   2140         sal_memcpy(&flow->config, def_cfg, sizeof(flow->config));
   2141         flow->sn_slice = slice;
   2142 
   2143         /* Write to HW */
   2144         rv = SR_FLOW_MGMT_DEVINFO(unit)->write_rx_flow(unit, fsid + i, flow);
   2145         if (BCM_FAILURE(rv)) {
   2146             (void)bcmi_esw_tsn_sr_flowset_destroy(unit, flowset_id);
   2147             SR_FLOW_RX_UNLOCK(unit, fsid + i);
   2148             SR_FLOWSET_UNLOCK(fset);
   2149             return rv;
   2150         }
   2151         if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   2152             (void)bcmi_esw_tsn_mtu_profile_ref_inc(
   2153                         unit, def_cfg->ingress_mtu_profile);
   2154         }
   2155         /*
   2156          * Reset the flow as the initial state
   2157          */
   2158         flags = BCM_TSN_SR_RX_FLOW_RESET_ALL;
   2159         /* Get reset mode */
   2160         rv = bcm_esw_tsn_control_get(
   2161                 unit, bcmTsnControlSrSeqNumWindowResetMode, &reset_mode);
   2162         if (BCM_FAILURE(rv)) {
   2163             (void)bcmi_esw_tsn_sr_flowset_destroy(unit, flowset_id);
   2164             SR_FLOW_RX_UNLOCK(unit, fsid + i);
   2165             SR_FLOWSET_UNLOCK(fset);
   2166             return rv;
   2167         }
   2168         if (reset_mode != BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_HW1) {
   2169             /* Only need to set SN RESET bit for HW reset method 1 */
   2170             flags &= ~BCM_TSN_SR_RX_FLOW_RESET_SEQNUM_WIN_STATE;
   2171         }
   2172         /* Call flow reset function */
   2173         rv = bcm_esw_tsn_sr_rx_flow_reset(
   2174                 unit, flags, SR_FLOW_ID_FROM_IDX(SR_FLOW_DIR_RX, fsid + i));
   2175         if (BCM_FAILURE(rv)) {
   2176             (void)bcmi_esw_tsn_sr_flowset_destroy(unit, flowset_id);
   2177             SR_FLOW_RX_UNLOCK(unit, fsid + i);
   2178             SR_FLOWSET_UNLOCK(fset);
   2179             return rv;
   2180         }
   2181 
   2182         SR_FLOW_RX_UNLOCK(unit, fsid + i);
   2183 
   2184         /* provide active flow information for event management */
   2185         (void)bcmi_esw_tsn_event_rx_flow_add(unit, fsid + i);
   2186     }
   2187     SR_FLOWSET_UNLOCK(fset);
   2188 
   2189     /* Convert to user flowset ID */
   2190     *flowset = flowset_id;
   2191     return BCM_E_NONE;
   2192 }
   2193 
   2194 /*
   2195  * Function:
   2196  *     bcmi_esw_tsn_sr_tx_flowset_create
   2197  * Purpose:
   2198  *     Create an SR TX flowset.
   2199  * Parameters:
   2200  *     unit             - (IN) unit number
   2201  *     pri_map          - (IN) TSN priority map ID
   2202  *     def_cfg          - (IN) default flow configuration
   2203  *     flowset          - (OUT) flowset ID
   2204  * Returns:
   2205  *     BCM_E_XXX
   2206  * Notes:
   2207  */
   2208 STATIC int
   2209 bcmi_esw_tsn_sr_tx_flowset_create(
   2210     int unit,
   2211     bcm_tsn_pri_map_t pri_map,
   2212     bcm_tsn_sr_tx_flow_config_t *def_cfg,
   2213     bcm_tsn_sr_flowset_t *flowset)
   2214 {
   2215     bcmi_esw_tsn_bk_info_t *tsn_bk;
   2216     tsn_sr_flows_bookkeeping_t *bkinfo;
   2217     tsn_sr_flowset_t *fset;
   2218     bcm_tsn_sr_flowset_t flowset_id;
   2219     bcmi_tsn_sr_tx_flow_t *flow;
   2220     int fsid;
   2221     int rv = BCM_E_NONE;
   2222     int i;
   2223 
   2224     /* parameter check */
   2225     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   2226     if (def_cfg == NULL || flowset == NULL) {
   2227         return BCM_E_PARAM;
   2228     }
   2229     bkinfo = &tsn_bk->sr_flows;
   2230 
   2231     /* Validate flow configuration */
   2232     if (SR_FLOW_MGMT_DEVINFO(unit)->check_tx_flow_config) {
   2233         rv = SR_FLOW_MGMT_DEVINFO(unit)->check_tx_flow_config(unit, def_cfg);
   2234         if (BCM_FAILURE(rv)) {
   2235             return rv;
   2236         }
   2237     } else {
   2238         return BCM_E_UNAVAIL;
   2239     }
   2240 
   2241     /* Allocate flows and flowset. Basic init check is also done inside. */
   2242     rv = bcmi_esw_tsn_sr_flowset_alloc(unit, SR_FLOW_DIR_TX, pri_map, &fsid);
   2243     if (BCM_FAILURE(rv)) {
   2244         return rv;
   2245     }
   2246     flowset_id = SR_FLOWSET_ID_FROM_IDX(SR_FLOW_DIR_TX, fsid);
   2247 
   2248     /* Write to the flowset software copy */
   2249     bkinfo = &tsn_bk->sr_flows;
   2250     fset = &bkinfo->flowsets[SR_FLOW_DIR_TX][fsid];
   2251     SR_FLOWSET_LOCK(fset);
   2252     sal_memcpy(&fset->config.tx, def_cfg, sizeof(fset->config.tx));
   2253 
   2254     /* Write to individual flows */
   2255     for (i = 0; i < fset->num_flows; i++) {
   2256         SR_FLOW_TX_LOCK(unit, fsid + i);
   2257         flow = &bkinfo->flows_tx[fsid + i];
   2258 
   2259         /* Save a SW copy */
   2260         sal_memcpy(&flow->config, def_cfg, sizeof(flow->config));
   2261 
   2262         /* Write to HW */
   2263         if (SR_FLOW_MGMT_DEVINFO(unit)->write_tx_flow) {
   2264             rv = SR_FLOW_MGMT_DEVINFO(unit)->write_tx_flow(
   2265                     unit, fsid + i, flow);
   2266             if (BCM_FAILURE(rv)) {
   2267                 (void)bcmi_esw_tsn_sr_flowset_destroy(unit, flowset_id);
   2268                 SR_FLOW_TX_UNLOCK(unit, fsid + i);
   2269                 SR_FLOWSET_UNLOCK(fset);
   2270                 return rv;
   2271             }
   2272         } else {
   2273             (void)bcmi_esw_tsn_sr_flowset_destroy(unit, flowset_id);
   2274             SR_FLOW_TX_UNLOCK(unit, fsid + i);
   2275             SR_FLOWSET_UNLOCK(fset);
   2276             return BCM_E_UNAVAIL;
   2277         }
   2278         if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   2279             (void)bcmi_esw_tsn_mtu_profile_ref_inc(
   2280                         unit, def_cfg->ingress_mtu_profile);
   2281         }
   2282         SR_FLOW_TX_UNLOCK(unit, fsid + i);
   2283     }
   2284     SR_FLOWSET_UNLOCK(fset);
   2285 
   2286     /* Convert to user flowset ID */
   2287     *flowset = flowset_id;
   2288     return BCM_E_NONE;
   2289 }
   2290 
   2291 /*
   2292  * Function:
   2293  *     bcmi_esw_tsn_sr_tx_flowset_config_get
   2294  * Purpose:
   2295  *     Get default configuration for the specified SR flowset
   2296  * Parameters:
   2297  *     unit             - (IN) unit number
   2298  *     flowset          - (IN) flowset ID
   2299  *     pri_map          - (OUT) TSN priority map ID
   2300  *     default_config   - (OUT) default flow configuration
   2301  * Returns:
   2302  *     BCM_E_XXX
   2303  * Notes:
   2304  *     If it's called with a RX flowset, BCM_E_BADID is returned
   2305  */
   2306 STATIC int
   2307 bcmi_esw_tsn_sr_tx_flowset_config_get(
   2308     int unit,
   2309     bcm_tsn_sr_flowset_t flowset,
   2310     bcm_tsn_pri_map_t *pri_map,
   2311     bcm_tsn_sr_tx_flow_config_t *config)
   2312 {
   2313     bcmi_esw_tsn_bk_info_t *tsn_bk;
   2314     tsn_sr_flows_bookkeeping_t *bkinfo;
   2315     tsn_sr_flowset_t *fset;
   2316     int dir, fsid;
   2317 
   2318     /* parameter check */
   2319     if (pri_map == NULL || config == NULL) {
   2320         return BCM_E_PARAM;
   2321     }
   2322     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   2323     bkinfo = &tsn_bk->sr_flows;
   2324     dir = SR_FLOWSET_ID_TO_DIR(flowset);
   2325     fsid = SR_FLOWSET_ID_TO_IDX(flowset);
   2326     if (dir != SR_FLOW_DIR_TX) {
   2327         return BCM_E_BADID;
   2328     }
   2329     if (fsid < 0 || fsid >= bkinfo->max_flows[dir]) {
   2330         return BCM_E_PARAM;
   2331     }
   2332     fset = &bkinfo->flowsets[dir][fsid];
   2333     SR_FLOWSET_LOCK(fset);
   2334     if (fset->num_flows == 0) {
   2335         /* Not allocated */
   2336         SR_FLOWSET_UNLOCK(fset);
   2337         return BCM_E_NOT_FOUND;
   2338     }
   2339 
   2340     /* Return the value */
   2341     *pri_map = fset->map_id;
   2342     sal_memcpy(config, &fset->config.tx, sizeof(fset->config.tx));
   2343     SR_FLOWSET_UNLOCK(fset);
   2344     return BCM_E_NONE;
   2345 }
   2346 
   2347 /*
   2348  * Function:
   2349  *     bcmi_esw_tsn_sr_rx_flowset_config_get
   2350  * Purpose:
   2351  *     Get default configuration for the specified SR flowset
   2352  * Parameters:
   2353  *     unit             - (IN) unit number
   2354  *     flowset          - (IN) flowset ID
   2355  *     pri_map          - (OUT) TSN priority map ID
   2356  *     default_config   - (OUT) default flow configuration
   2357  * Returns:
   2358  *     BCM_E_XXX
   2359  * Notes:
   2360  *     If it's called with a TX flowset, BCM_E_BADID is returned
   2361  */
   2362 STATIC int
   2363 bcmi_esw_tsn_sr_rx_flowset_config_get(
   2364     int unit,
   2365     bcm_tsn_sr_flowset_t flowset,
   2366     bcm_tsn_pri_map_t *pri_map,
   2367     bcm_tsn_sr_rx_flow_config_t *config)
   2368 {
   2369     bcmi_esw_tsn_bk_info_t *tsn_bk;
   2370     tsn_sr_flows_bookkeeping_t *bkinfo;
   2371     tsn_sr_flowset_t *fset;
   2372     int dir, fsid;
   2373 
   2374     /* parameter check */
   2375     if (pri_map == NULL || config == NULL) {
   2376         return BCM_E_PARAM;
   2377     }
   2378     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   2379     bkinfo = &tsn_bk->sr_flows;
   2380     dir = SR_FLOWSET_ID_TO_DIR(flowset);
   2381     fsid = SR_FLOWSET_ID_TO_IDX(flowset);
   2382     if (dir != SR_FLOW_DIR_RX) {
   2383         return BCM_E_BADID;
   2384     }
   2385     if (fsid < 0 || fsid >= bkinfo->max_flows[dir]) {
   2386         return BCM_E_PARAM;
   2387     }
   2388     fset = &bkinfo->flowsets[dir][fsid];
   2389     SR_FLOWSET_LOCK(fset);
   2390     if (fset->num_flows == 0) {
   2391         /* Not allocated */
   2392         SR_FLOWSET_UNLOCK(fset);
   2393         return BCM_E_NOT_FOUND;
   2394     }
   2395 
   2396     /* Return the value */
   2397     *pri_map = fset->map_id;
   2398     sal_memcpy(config, &fset->config.rx, sizeof(fset->config.rx));
   2399     SR_FLOWSET_UNLOCK(fset);
   2400     return BCM_E_NONE;
   2401 }
   2402 
   2403 /*
   2404  * Function:
   2405  *     bcmi_esw_tsn_sr_flowset_status_get
   2406  * Purpose:
   2407  *     Get current status of specified SR flowset
   2408  * Parameters:
   2409  *     unit             - (IN) unit number
   2410  *     flowset          - (IN) flowset ID
   2411  *     status           - (OUT) status structure
   2412  * Returns:
   2413  *     BCM_E_XXX
   2414  * Notes:
   2415  */
   2416 STATIC int
   2417 bcmi_esw_tsn_sr_flowset_status_get(
   2418     int unit,
   2419     bcm_tsn_sr_flowset_t flowset,
   2420     bcm_tsn_sr_flowset_status_t *status)
   2421 {
   2422     bcmi_esw_tsn_bk_info_t *tsn_bk;
   2423     tsn_sr_flows_bookkeeping_t *bkinfo;
   2424     tsn_sr_flowset_t *fset;
   2425     int dir, fsid;
   2426 
   2427     /* parameter check */
   2428     if (status == NULL) {
   2429         return BCM_E_PARAM;
   2430     }
   2431     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   2432     bkinfo = &tsn_bk->sr_flows;
   2433     dir = SR_FLOWSET_ID_TO_DIR(flowset);
   2434     fsid = SR_FLOWSET_ID_TO_IDX(flowset);
   2435     if (fsid < 0 || fsid >= bkinfo->max_flows[dir]) {
   2436         return BCM_E_PARAM;
   2437     }
   2438     fset = &bkinfo->flowsets[dir][fsid];
   2439     SR_FLOWSET_LOCK(fset);
   2440     if (fset->num_flows == 0) {
   2441         /* Not allocated */
   2442         SR_FLOWSET_UNLOCK(fset);
   2443         return BCM_E_NOT_FOUND;
   2444     }
   2445 
   2446     /* Return the value */
   2447     status->active = fset->ref_count > 0 ?  1 : 0;
   2448     status->count = fset->num_flows;
   2449     SR_FLOWSET_UNLOCK(fset);
   2450     return BCM_E_NONE;
   2451 }
   2452 
   2453 /*
   2454  * Function:
   2455  *     bcmi_esw_tsn_sr_flowset_ref_inc
   2456  * Purpose:
   2457  *     Increase reference count for the specified SR flowset
   2458  * Parameters:
   2459  *     unit             - (IN) unit number
   2460  *     flowset          - (IN) flowset ID
   2461  * Returns:
   2462  *     BCM_E_XXX
   2463  * Notes:
   2464  */
   2465 int
   2466 bcmi_esw_tsn_sr_flowset_ref_inc(int unit, bcm_tsn_sr_flowset_t flowset)
   2467 {
   2468     bcmi_esw_tsn_bk_info_t *tsn_bk;
   2469     tsn_sr_flows_bookkeeping_t *bkinfo;
   2470     tsn_sr_flowset_t *fset;
   2471     int dir, fsid;
   2472 
   2473     /* parameter check */
   2474     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   2475     bkinfo = &tsn_bk->sr_flows;
   2476     dir = SR_FLOWSET_ID_TO_DIR(flowset);
   2477     fsid = SR_FLOWSET_ID_TO_IDX(flowset);
   2478     if (fsid < 0 || fsid >= bkinfo->max_flows[dir]) {
   2479         return BCM_E_PARAM;
   2480     }
   2481     fset = &bkinfo->flowsets[dir][fsid];
   2482     SR_FLOWSET_LOCK(fset);
   2483     if (fset->num_flows == 0) {
   2484         /* Not allocated */
   2485         SR_FLOWSET_UNLOCK(fset);
   2486         return BCM_E_NOT_FOUND;
   2487     }
   2488     /* Update the reference count */
   2489     fset->ref_count++;
   2490     SR_FLOWSET_UNLOCK(fset);
   2491     return BCM_E_NONE;
   2492 }
   2493 
   2494 /*
   2495  * Function:
   2496  *     bcmi_esw_tsn_sr_flowset_ref_dec
   2497  * Purpose:
   2498  *     Decrease reference count for the specified SR flowset
   2499  * Parameters:
   2500  *     unit             - (IN) unit number
   2501  *     flowset          - (IN) flowset ID
   2502  * Returns:
   2503  *     BCM_E_XXX
   2504  * Notes:
   2505  */
   2506 int
   2507 bcmi_esw_tsn_sr_flowset_ref_dec(int unit, bcm_tsn_sr_flowset_t flowset)
   2508 {
   2509     bcmi_esw_tsn_bk_info_t *tsn_bk;
   2510     tsn_sr_flows_bookkeeping_t *bkinfo;
   2511     tsn_sr_flowset_t *fset;
   2512     int dir, fsid;
   2513 
   2514     /* parameter check */
   2515     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   2516     bkinfo = &tsn_bk->sr_flows;
   2517     dir = SR_FLOWSET_ID_TO_DIR(flowset);
   2518     fsid = SR_FLOWSET_ID_TO_IDX(flowset);
   2519     if (fsid < 0 || fsid >= bkinfo->max_flows[dir]) {
   2520         return BCM_E_PARAM;
   2521     }
   2522     fset = &bkinfo->flowsets[dir][fsid];
   2523     SR_FLOWSET_LOCK(fset);
   2524     if (fset->num_flows == 0) {
   2525         /* Not allocated */
   2526         SR_FLOWSET_UNLOCK(fset);
   2527         return BCM_E_NOT_FOUND;
   2528     }
   2529     /* Update the reference count */
   2530     if (fset->ref_count > 0) {
   2531         fset->ref_count--;
   2532     }
   2533     SR_FLOWSET_UNLOCK(fset);
   2534     return BCM_E_NONE;
   2535 }
   2536 
   2537 /*
   2538  * Function:
   2539  *     bcmi_esw_tsn_sr_flowset_traverse
   2540  * Purpose:
   2541  *     Traverse all created SR flowsets
   2542  * Parameters:
   2543  *     unit             - (IN) unit number
   2544  *     is_rx            - (IN) 1 for RX flowsets; 0 for TX flowsets
   2545  *     cb               - (IN) callback function
   2546  *     user_data        - (IN) user data supplied to the callback function
   2547  * Returns:
   2548  *     BCM_E_XXX
   2549  * Notes:
   2550  */
   2551 STATIC int
   2552 bcmi_esw_tsn_sr_flowset_traverse(
   2553     int unit,
   2554     int is_rx,
   2555     bcm_tsn_sr_flowset_traverse_cb cb,
   2556     void *user_data)
   2557 {
   2558     bcmi_esw_tsn_bk_info_t *tsn_bk;
   2559     tsn_sr_flows_bookkeeping_t *bkinfo;
   2560     tsn_sr_flowset_t *fset;
   2561     int dir;
   2562     int rv = BCM_E_NONE;
   2563     int i;
   2564 
   2565     /* parameter check */
   2566     if (cb == NULL) {
   2567         return BCM_E_PARAM;
   2568     }
   2569     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   2570 
   2571     /* Loop through the flowset array */
   2572     bkinfo = &tsn_bk->sr_flows;
   2573     dir = is_rx ? SR_FLOW_DIR_RX : SR_FLOW_DIR_TX;
   2574     for (i = 0; i < bkinfo->max_flows[dir]; i++) {
   2575         fset = &bkinfo->flowsets[dir][i];
   2576         SR_FLOWSET_LOCK(fset);
   2577         if (fset->num_flows != 0) {
   2578             rv = cb(unit, SR_FLOWSET_ID_FROM_IDX(dir, i), user_data);
   2579         }
   2580         SR_FLOWSET_UNLOCK(fset);
   2581         BCM_IF_ERROR_RETURN(rv);
   2582     }
   2583 
   2584     return BCM_E_NONE;
   2585 }
   2586 
   2587 /*
   2588  * Function:
   2589  *     bcmi_esw_tsn_sr_flowset_flow_get
   2590  * Purpose:
   2591  *     Retrieve an individual SR flow based on the flow offset from a flow set.
   2592  * Parameters:
   2593  *     unit             - (IN) unit number
   2594  *     flowset          - (IN) flowset ID
   2595  *     index            - (IN) index of the flow
   2596  *     flow_id          - (OUT) flow ID
   2597  * Returns:
   2598  *     BCM_E_XXX
   2599  * Notes:
   2600  */
   2601 STATIC int
   2602 bcmi_esw_tsn_sr_flowset_flow_get(
   2603     int unit,
   2604     bcm_tsn_sr_flowset_t flowset,
   2605     int index,
   2606     bcm_tsn_sr_flow_t *flow_id)
   2607 {
   2608     bcmi_esw_tsn_bk_info_t *tsn_bk;
   2609     tsn_sr_flows_bookkeeping_t *bkinfo;
   2610     tsn_sr_flowset_t *fset;
   2611     int dir;
   2612     int fsid;
   2613 
   2614     /* parameter check */
   2615     if (flow_id == NULL) {
   2616         return BCM_E_PARAM;
   2617     }
   2618     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   2619     bkinfo = &tsn_bk->sr_flows;
   2620     dir = SR_FLOWSET_ID_TO_DIR(flowset);
   2621     fsid = SR_FLOWSET_ID_TO_IDX(flowset);
   2622     if (fsid < 0 || fsid >= bkinfo->max_flows[dir]) {
   2623         return BCM_E_PARAM;
   2624     }
   2625     fset = &bkinfo->flowsets[dir][fsid];
   2626     SR_FLOWSET_LOCK(fset);
   2627     if (fset->num_flows == 0) {
   2628         /* Not allocated */
   2629         SR_FLOWSET_UNLOCK(fset);
   2630         return BCM_E_NOT_FOUND;
   2631     }
   2632     if (index < 0 || index >= fset->num_flows) {
   2633         SR_FLOWSET_UNLOCK(fset);
   2634         return BCM_E_PARAM;
   2635     }
   2636     assert(fsid + index < bkinfo->max_flows[dir]);
   2637 
   2638     /* Got SW flow ID */
   2639     *flow_id = SR_FLOW_ID_FROM_IDX(dir, fsid + index);
   2640     SR_FLOWSET_UNLOCK(fset);
   2641     return BCM_E_NONE;
   2642 }
   2643 
   2644 /*
   2645  * Function:
   2646  *     bcmi_esw_tsn_sr_tx_flow_config_get
   2647  * Purpose:
   2648  *     Get configuration for the specified SR flow
   2649  * Parameters:
   2650  *     unit             - (IN) unit number
   2651  *     flow_id          - (IN) flow ID
   2652  *     config           - (OUT) flow configuration
   2653  * Returns:
   2654  *     BCM_E_XXX
   2655  * Notes:
   2656  *     If it's called with a RX flowset, BCM_E_BADID is returned
   2657  */
   2658 STATIC int
   2659 bcmi_esw_tsn_sr_tx_flow_config_get(
   2660     int unit,
   2661     bcm_tsn_sr_flow_t flow_id,
   2662     bcm_tsn_sr_tx_flow_config_t *config)
   2663 {
   2664     bcmi_esw_tsn_bk_info_t *tsn_bk;
   2665     tsn_sr_flows_bookkeeping_t *bkinfo;
   2666     int fidx;
   2667     int dir;
   2668     int i;
   2669 
   2670     /* parameter check */
   2671     if (config == NULL) {
   2672         return BCM_E_PARAM;
   2673     }
   2674     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   2675     bkinfo = &tsn_bk->sr_flows;
   2676     dir = SR_FLOW_ID_TO_DIR(flow_id);
   2677     fidx = SR_FLOW_ID_TO_IDX(flow_id);
   2678     if (dir != SR_FLOW_DIR_TX) {
   2679         return BCM_E_BADID;
   2680     }
   2681     if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) {
   2682         return BCM_E_PARAM;
   2683     }
   2684 
   2685     /* Validate if it's from a flowset */
   2686     for (i = fidx; i >= 0; i--) {
   2687         if (bkinfo->flowsets[dir][i].num_flows != 0) {
   2688             if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) {
   2689                 break;
   2690             } else {
   2691                 return BCM_E_NOT_FOUND;
   2692             }
   2693         }
   2694     }
   2695     if (i == -1) {
   2696         /* No valid flowsets */
   2697         return BCM_E_NOT_FOUND;
   2698     }
   2699 
   2700     /* Return the configuration */
   2701     SR_FLOW_TX_LOCK(unit, fidx);
   2702     sal_memcpy(config, &bkinfo->flows_tx[fidx].config, sizeof(*config));
   2703     SR_FLOW_TX_UNLOCK(unit, fidx);
   2704     return BCM_E_NONE;
   2705 }
   2706 
   2707 /*
   2708  * Function:
   2709  *     bcmi_esw_tsn_sr_rx_flow_config_get
   2710  * Purpose:
   2711  *     Get configuration for the specified SR flow
   2712  * Parameters:
   2713  *     unit             - (IN) unit number
   2714  *     flow_id          - (IN) flow ID
   2715  *     config           - (OUT) flow configuration
   2716  * Returns:
   2717  *     BCM_E_XXX
   2718  * Notes:
   2719  *     If it's called with a TX flowset, BCM_E_BADID is returned
   2720  */
   2721 STATIC int
   2722 bcmi_esw_tsn_sr_rx_flow_config_get(
   2723     int unit,
   2724     bcm_tsn_sr_flow_t flow_id,
   2725     bcm_tsn_sr_rx_flow_config_t *config)
   2726 {
   2727     bcmi_esw_tsn_bk_info_t *tsn_bk;
   2728     tsn_sr_flows_bookkeeping_t *bkinfo;
   2729     int fidx;
   2730     int dir;
   2731     int i;
   2732 
   2733     /* parameter check */
   2734     if (config == NULL) {
   2735         return BCM_E_PARAM;
   2736     }
   2737     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   2738     bkinfo = &tsn_bk->sr_flows;
   2739     dir = SR_FLOW_ID_TO_DIR(flow_id);
   2740     fidx = SR_FLOW_ID_TO_IDX(flow_id);
   2741     if (dir != SR_FLOW_DIR_RX) {
   2742         return BCM_E_BADID;
   2743     }
   2744     if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) {
   2745         return BCM_E_PARAM;
   2746     }
   2747 
   2748     /* Validate if it's from a flowset */
   2749     for (i = fidx; i >= 0; i--) {
   2750         if (bkinfo->flowsets[dir][i].num_flows != 0) {
   2751             if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) {
   2752                 break;
   2753             } else {
   2754                 return BCM_E_NOT_FOUND;
   2755             }
   2756         }
   2757     }
   2758     if (i == -1) {
   2759         /* No valid flowsets */
   2760         return BCM_E_NOT_FOUND;
   2761     }
   2762 
   2763     /* Return the configuration */
   2764     SR_FLOW_RX_LOCK(unit, fidx);
   2765     sal_memcpy(config, &bkinfo->flows_rx[fidx].config, sizeof(*config));
   2766     SR_FLOW_RX_UNLOCK(unit, fidx);
   2767     return BCM_E_NONE;
   2768 }
   2769 
   2770 /*
   2771  * Function:
   2772  *     bcmi_esw_tsn_sr_tx_flow_config_set
   2773  * Purpose:
   2774  *     Set configuration for the specified SR flow
   2775  * Parameters:
   2776  *     unit             - (IN) unit number
   2777  *     flow_id          - (IN) flow ID
   2778  *     config           - (IN) flow configuration
   2779  * Returns:
   2780  *     BCM_E_XXX
   2781  * Notes:
   2782  *     If it's called with a RX flow, BCM_E_BADID is returned
   2783  */
   2784 STATIC int
   2785 bcmi_esw_tsn_sr_tx_flow_config_set(
   2786     int unit,
   2787     bcm_tsn_sr_flow_t flow_id,
   2788     bcm_tsn_sr_tx_flow_config_t *config)
   2789 {
   2790     bcmi_esw_tsn_bk_info_t *tsn_bk;
   2791     tsn_sr_flows_bookkeeping_t *bkinfo;
   2792     int fidx;
   2793     int dir;
   2794     int rv;
   2795     int i;
   2796 
   2797     /* parameter check */
   2798     if (config == NULL) {
   2799         return BCM_E_PARAM;
   2800     }
   2801     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   2802     bkinfo = &tsn_bk->sr_flows;
   2803     dir = SR_FLOW_ID_TO_DIR(flow_id);
   2804     fidx = SR_FLOW_ID_TO_IDX(flow_id);
   2805     if (dir != SR_FLOW_DIR_TX) {
   2806         return BCM_E_BADID;
   2807     }
   2808     if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) {
   2809         return BCM_E_PARAM;
   2810     }
   2811 
   2812     /* Validate if it's from a flowset */
   2813     for (i = fidx; i >= 0; i--) {
   2814         if (bkinfo->flowsets[dir][i].num_flows != 0) {
   2815             if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) {
   2816                 break;
   2817             } else {
   2818                 return BCM_E_NOT_FOUND;
   2819             }
   2820         }
   2821     }
   2822     if (i == -1) {
   2823         /* No valid flowsets */
   2824         return BCM_E_NOT_FOUND;
   2825     }
   2826 
   2827     /* Validate flow configuration */
   2828     if (SR_FLOW_MGMT_DEVINFO(unit)->check_tx_flow_config) {
   2829         rv = SR_FLOW_MGMT_DEVINFO(unit)->check_tx_flow_config(unit, config);
   2830         if (BCM_FAILURE(rv)) {
   2831             return rv;
   2832         }
   2833     } else {
   2834         return BCM_E_UNAVAIL;
   2835     }
   2836 
   2837     /*
   2838      * Configure the flow using the supplied configuration
   2839      */
   2840     SR_FLOW_TX_LOCK(unit, fidx);
   2841     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   2842         /* Clear the old MTU profile id */
   2843         if (SR_FLOW_MGMT_DEVINFO(unit)->clear_tx_flow_mtu) {
   2844             rv = SR_FLOW_MGMT_DEVINFO(unit)->clear_tx_flow_mtu(unit, fidx);
   2845             if (BCM_FAILURE(rv)) {
   2846                 SR_FLOW_TX_UNLOCK(unit, fidx);
   2847                 return rv;
   2848             }
   2849         } else {
   2850             SR_FLOW_TX_UNLOCK(unit, fidx);
   2851             return BCM_E_UNAVAIL;
   2852         }
   2853         (void)bcmi_esw_tsn_mtu_profile_ref_dec(
   2854             unit, bkinfo->flows_tx[fidx].config.ingress_mtu_profile);
   2855     }
   2856     /* Copy to SW flow info */
   2857     sal_memcpy(&bkinfo->flows_tx[fidx].config, config, sizeof(*config));
   2858     /* Write to HW */
   2859     if (SR_FLOW_MGMT_DEVINFO(unit)->write_tx_flow) {
   2860         rv = SR_FLOW_MGMT_DEVINFO(unit)->write_tx_flow(
   2861                 unit, fidx, &bkinfo->flows_tx[fidx]);
   2862         if (BCM_FAILURE(rv)) {
   2863             SR_FLOW_TX_UNLOCK(unit, fidx);
   2864             return rv;
   2865         }
   2866     } else {
   2867         SR_FLOW_TX_UNLOCK(unit, fidx);
   2868         return BCM_E_UNAVAIL;
   2869     }
   2870     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   2871         (void)bcmi_esw_tsn_mtu_profile_ref_inc(
   2872             unit, bkinfo->flows_tx[fidx].config.ingress_mtu_profile);
   2873     }
   2874     SR_FLOW_TX_UNLOCK(unit, fidx);
   2875     return BCM_E_NONE;
   2876 }
   2877 
   2878 /*
   2879  * Function:
   2880  *     bcmi_esw_tsn_sr_rx_flow_config_set
   2881  * Purpose:
   2882  *     Set configuration for the specified SR flow
   2883  * Parameters:
   2884  *     unit             - (IN) unit number
   2885  *     flow_id          - (IN) flow ID
   2886  *     config           - (IN) flow configuration
   2887  * Returns:
   2888  *     BCM_E_XXX
   2889  * Notes:
   2890  *     If it's called with a TX flow, BCM_E_BADID is returned
   2891  */
   2892 STATIC int
   2893 bcmi_esw_tsn_sr_rx_flow_config_set(
   2894     int unit,
   2895     bcm_tsn_sr_flow_t flow_id,
   2896     bcm_tsn_sr_rx_flow_config_t *config)
   2897 {
   2898     bcmi_esw_tsn_bk_info_t *tsn_bk;
   2899     tsn_sr_flows_bookkeeping_t *bkinfo;
   2900     bcmi_tsn_sr_seqnum_slice_t slice;
   2901     tsn_sr_flowset_t *fset;
   2902     uint32 reset_mode;
   2903     uint32 flags;
   2904     int fidx;
   2905     int dir;
   2906     int rv;
   2907     int i;
   2908 
   2909     /* parameter check */
   2910     if (config == NULL) {
   2911         return BCM_E_PARAM;
   2912     }
   2913     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   2914     bkinfo = &tsn_bk->sr_flows;
   2915     dir = SR_FLOW_ID_TO_DIR(flow_id);
   2916     fidx = SR_FLOW_ID_TO_IDX(flow_id);
   2917     if (dir != SR_FLOW_DIR_RX) {
   2918         return BCM_E_BADID;
   2919     }
   2920     if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) {
   2921         return BCM_E_PARAM;
   2922     }
   2923 
   2924     /* Validate if it's from a flowset */
   2925     fset = NULL;
   2926     for (i = fidx; i >= 0; i--) {
   2927         if (bkinfo->flowsets[dir][i].num_flows != 0) {
   2928             fset = &bkinfo->flowsets[dir][i];
   2929             if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) {
   2930                 break;
   2931             } else {
   2932                 return BCM_E_NOT_FOUND;
   2933             }
   2934         }
   2935     }
   2936     if (fset == NULL) {
   2937         /* No valid flowsets */
   2938         return BCM_E_NOT_FOUND;
   2939     }
   2940 
   2941     /* Validate flow configuration */
   2942     if (SR_FLOW_MGMT_DEVINFO(unit)->check_rx_flow_config) {
   2943         rv = SR_FLOW_MGMT_DEVINFO(unit)->check_rx_flow_config(unit, config);
   2944         if (BCM_FAILURE(rv)) {
   2945             return rv;
   2946         }
   2947     } else {
   2948         return BCM_E_UNAVAIL;
   2949     }
   2950 
   2951     /* Get reset mode here before we modify anything */
   2952     rv = bcm_esw_tsn_control_get(
   2953             unit, bcmTsnControlSrSeqNumWindowResetMode, &reset_mode);
   2954     if (BCM_FAILURE(rv)) {
   2955         return rv;
   2956     }
   2957 
   2958     /* Can't change window size when its flowset is active */
   2959     SR_FLOWSET_LOCK(fset);
   2960     if (fset->ref_count != 0 &&
   2961         config->seqnum_history_win_size !=
   2962             bkinfo->flows_rx[fidx].config.seqnum_history_win_size) {
   2963         SR_FLOWSET_UNLOCK(fset);
   2964         return BCM_E_BUSY;
   2965     }
   2966 
   2967     /*
   2968      * Configure the flow using the supplied configuration
   2969      */
   2970     SR_FLOW_RX_LOCK(unit, fidx);
   2971     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   2972         /* Clear the old MTU profile id */
   2973         if (SR_FLOW_MGMT_DEVINFO(unit)->clear_rx_flow_mtu) {
   2974             rv = SR_FLOW_MGMT_DEVINFO(unit)->clear_rx_flow_mtu(unit, fidx);
   2975             if (BCM_FAILURE(rv)) {
   2976                 SR_FLOW_RX_UNLOCK(unit, fidx);
   2977                 return rv;
   2978             }
   2979         } else {
   2980             SR_FLOW_RX_UNLOCK(unit, fidx);
   2981             return BCM_E_UNAVAIL;
   2982         }
   2983         (void)bcmi_esw_tsn_mtu_profile_ref_dec(
   2984             unit, bkinfo->flows_rx[fidx].config.ingress_mtu_profile);
   2985     }
   2986     /* Re-allocate sequence number history pool if necessary */
   2987     if (config->seqnum_history_win_size !=
   2988         bkinfo->flows_rx[fidx].config.seqnum_history_win_size) {
   2989         if (!SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_alloc ||
   2990             !SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_free) {
   2991             SR_FLOW_RX_UNLOCK(unit, fidx);
   2992             SR_FLOWSET_UNLOCK(fset);
   2993             return BCM_E_UNAVAIL;
   2994         }
   2995         /* Try allocating first */
   2996         rv = SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_alloc(
   2997                 unit, config->seqnum_history_win_size, &slice);
   2998         if (BCM_FAILURE(rv)) {
   2999             SR_FLOW_RX_UNLOCK(unit, fidx);
   3000             SR_FLOWSET_UNLOCK(fset);
   3001             return rv;
   3002         }
   3003         /* Free the original */
   3004         (void)SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_free(
   3005                 unit, bkinfo->flows_rx[fidx].sn_slice);
   3006         /* Now we use the new slice */
   3007         bkinfo->flows_rx[fidx].sn_slice = slice;
   3008     }
   3009     /* Copy to SW flow info */
   3010     sal_memcpy(&bkinfo->flows_rx[fidx].config, config, sizeof(*config));
   3011     /* Write to HW */
   3012     if (SR_FLOW_MGMT_DEVINFO(unit)->write_rx_flow) {
   3013         rv = SR_FLOW_MGMT_DEVINFO(unit)->write_rx_flow(
   3014                 unit, fidx, &bkinfo->flows_rx[fidx]);
   3015         if (BCM_FAILURE(rv)) {
   3016             SR_FLOW_RX_UNLOCK(unit, fidx);
   3017             SR_FLOWSET_UNLOCK(fset);
   3018             return rv;
   3019         }
   3020     } else {
   3021         SR_FLOW_RX_UNLOCK(unit, fidx);
   3022         SR_FLOWSET_UNLOCK(fset);
   3023         return BCM_E_UNAVAIL;
   3024     }
   3025 
   3026     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   3027         (void)bcmi_esw_tsn_mtu_profile_ref_inc(
   3028             unit, bkinfo->flows_rx[fidx].config.ingress_mtu_profile);
   3029     }
   3030 
   3031     /*
   3032      * Reset the flow as the initial state
   3033      */
   3034     flags = BCM_TSN_SR_RX_FLOW_RESET_ALL;
   3035     /* Update flags based on reset mode */
   3036     if (reset_mode != BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_HW1) {
   3037         /* Only need to set SN RESET bit for HW reset method 1 */
   3038         flags &= ~BCM_TSN_SR_RX_FLOW_RESET_SEQNUM_WIN_STATE;
   3039     }
   3040     /* Call flow reset function */
   3041     rv = bcm_esw_tsn_sr_rx_flow_reset(
   3042             unit, flags, SR_FLOW_ID_FROM_IDX(SR_FLOW_DIR_RX, fidx));
   3043     if (BCM_FAILURE(rv)) {
   3044         SR_FLOW_RX_UNLOCK(unit, fidx);
   3045         SR_FLOWSET_UNLOCK(fset);
   3046         return rv;
   3047     }
   3048 
   3049     SR_FLOW_RX_UNLOCK(unit, fidx);
   3050     SR_FLOWSET_UNLOCK(fset);
   3051     return BCM_E_NONE;
   3052 }
   3053 
   3054 /*
   3055  * Function:
   3056  *     bcmi_esw_tsn_sr_tx_flow_status_get
   3057  * Purpose:
   3058  *     Get status for the specified flow
   3059  * Parameters:
   3060  *     unit             - (IN) unit number
   3061  *     flow_id          - (IN) flow ID
   3062  *     status           - (OUT) flow status
   3063  * Returns:
   3064  *     BCM_E_XXX
   3065  * Notes:
   3066  *     If it's called with a RX flow, BCM_E_BADID is returned
   3067  */
   3068 STATIC int
   3069 bcmi_esw_tsn_sr_tx_flow_status_get(
   3070     int unit,
   3071     bcm_tsn_sr_flow_t flow_id,
   3072     bcm_tsn_sr_tx_flow_status_t *status)
   3073 {
   3074     bcmi_esw_tsn_bk_info_t *tsn_bk;
   3075     tsn_sr_flows_bookkeeping_t *bkinfo;
   3076     int fidx;
   3077     int dir;
   3078     int rv;
   3079     int i;
   3080 
   3081     /* parameter check */
   3082     if (status == NULL) {
   3083         return BCM_E_PARAM;
   3084     }
   3085     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   3086     bkinfo = &tsn_bk->sr_flows;
   3087     dir = SR_FLOW_ID_TO_DIR(flow_id);
   3088     fidx = SR_FLOW_ID_TO_IDX(flow_id);
   3089     if (dir != SR_FLOW_DIR_TX) {
   3090         return BCM_E_BADID;
   3091     }
   3092     if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) {
   3093         return BCM_E_PARAM;
   3094     }
   3095 
   3096     /* Validate if it's from a flowset */
   3097     for (i = fidx; i >= 0; i--) {
   3098         if (bkinfo->flowsets[dir][i].num_flows != 0) {
   3099             if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) {
   3100                 break;
   3101             } else {
   3102                 return BCM_E_NOT_FOUND;
   3103             }
   3104         }
   3105     }
   3106     if (i == -1) {
   3107         /* No valid flowsets */
   3108         return BCM_E_NOT_FOUND;
   3109     }
   3110 
   3111     /* Get and return the status */
   3112     SR_FLOW_TX_LOCK(unit, fidx);
   3113     if (SR_FLOW_MGMT_DEVINFO(unit)->get_tx_flow_status) {
   3114         rv = SR_FLOW_MGMT_DEVINFO(unit)->get_tx_flow_status(unit, fidx, status);
   3115         if (BCM_FAILURE(rv)) {
   3116             SR_FLOW_TX_UNLOCK(unit, fidx);
   3117             return rv;
   3118         }
   3119     } else {
   3120         SR_FLOW_TX_UNLOCK(unit, fidx);
   3121         return BCM_E_UNAVAIL;
   3122     }
   3123     SR_FLOW_TX_UNLOCK(unit, fidx);
   3124     return BCM_E_NONE;
   3125 }
   3126 
   3127 /*
   3128  * Function:
   3129  *     bcmi_esw_tsn_sr_rx_flow_status_get
   3130  * Purpose:
   3131  *     Get status for the specified flow
   3132  * Parameters:
   3133  *     unit             - (IN) unit number
   3134  *     flow_id          - (IN) flow ID
   3135  *     status           - (OUT) flow status
   3136  * Returns:
   3137  *     BCM_E_XXX
   3138  * Notes:
   3139  *     If it's called with a TX flow, BCM_E_BADID is returned
   3140  */
   3141 STATIC int
   3142 bcmi_esw_tsn_sr_rx_flow_status_get(
   3143     int unit,
   3144     bcm_tsn_sr_flow_t flow_id,
   3145     bcm_tsn_sr_rx_flow_status_t *status)
   3146 {
   3147     bcmi_esw_tsn_bk_info_t *tsn_bk;
   3148     tsn_sr_flows_bookkeeping_t *bkinfo;
   3149     int fidx;
   3150     int dir;
   3151     int rv;
   3152     int i;
   3153 
   3154     /* parameter check */
   3155     if (status == NULL) {
   3156         return BCM_E_PARAM;
   3157     }
   3158     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   3159     bkinfo = &tsn_bk->sr_flows;
   3160     dir = SR_FLOW_ID_TO_DIR(flow_id);
   3161     fidx = SR_FLOW_ID_TO_IDX(flow_id);
   3162     if (dir != SR_FLOW_DIR_RX) {
   3163         return BCM_E_BADID;
   3164     }
   3165     if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) {
   3166         return BCM_E_PARAM;
   3167     }
   3168 
   3169     /* Validate if it's from a flowset */
   3170     for (i = fidx; i >= 0; i--) {
   3171         if (bkinfo->flowsets[dir][i].num_flows != 0) {
   3172             if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) {
   3173                 break;
   3174             } else {
   3175                 return BCM_E_NOT_FOUND;
   3176             }
   3177         }
   3178     }
   3179     if (i == -1) {
   3180         /* No valid flowsets */
   3181         return BCM_E_NOT_FOUND;
   3182     }
   3183 
   3184     /* Get and return the status */
   3185     SR_FLOW_RX_LOCK(unit, fidx);
   3186     if (SR_FLOW_MGMT_DEVINFO(unit)->get_rx_flow_status) {
   3187         rv = SR_FLOW_MGMT_DEVINFO(unit)->get_rx_flow_status(unit, fidx, status);
   3188         if (BCM_FAILURE(rv)) {
   3189             SR_FLOW_RX_UNLOCK(unit, fidx);
   3190             return rv;
   3191         }
   3192     } else {
   3193         SR_FLOW_RX_UNLOCK(unit, fidx);
   3194         return BCM_E_UNAVAIL;
   3195     }
   3196     SR_FLOW_RX_UNLOCK(unit, fidx);
   3197     return BCM_E_NONE;
   3198 }
   3199 
   3200 /*
   3201  * Function:
   3202  *     bcmi_esw_tsn_sr_rx_flow_reset
   3203  * Purpose:
   3204  *     Reset SR RX flow status
   3205  * Parameters:
   3206  *     unit             - (IN) unit number
   3207  *     flags            - (IN) flags to select items to reset
   3208  *     flow_id          - (IN) flow ID
   3209  * Returns:
   3210  *     BCM_E_XXX
   3211  * Notes:
   3212  *     If it's called with a TX flow, BCM_E_BADID is returned
   3213  */
   3214 STATIC int
   3215 bcmi_esw_tsn_sr_rx_flow_reset(int unit, uint32 flags, bcm_tsn_sr_flow_t flow_id)
   3216 {
   3217     bcmi_esw_tsn_bk_info_t *tsn_bk;
   3218     tsn_sr_flows_bookkeeping_t *bkinfo;
   3219     int fidx;
   3220     int dir;
   3221     uint32 reset_mode;
   3222     int rv;
   3223     int i;
   3224 
   3225     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   3226     if (flags & ~BCM_TSN_SR_RX_FLOW_RESET_ALL) {
   3227         return BCM_E_PARAM;
   3228     }
   3229     bkinfo = &tsn_bk->sr_flows;
   3230     dir = SR_FLOW_ID_TO_DIR(flow_id);
   3231     fidx = SR_FLOW_ID_TO_IDX(flow_id);
   3232     if (dir != SR_FLOW_DIR_RX) {
   3233         return BCM_E_BADID;
   3234     }
   3235     if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) {
   3236         return BCM_E_PARAM;
   3237     }
   3238 
   3239     /* Validate if it's from a flowset */
   3240     for (i = fidx; i >= 0; i--) {
   3241         if (bkinfo->flowsets[dir][i].num_flows != 0) {
   3242             if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) {
   3243                 break;
   3244             } else {
   3245                 return BCM_E_NOT_FOUND;
   3246             }
   3247         }
   3248     }
   3249     if (i == -1) {
   3250         /* No valid flowsets */
   3251         return BCM_E_NOT_FOUND;
   3252     }
   3253 
   3254     /* Call platform specific routine to do reset */
   3255     if (!SR_FLOW_MGMT_DEVINFO(unit)->reset_rx_flow ||
   3256         !SR_FLOW_MGMT_DEVINFO(unit)->seqnum_hist_reset) {
   3257         return BCM_E_UNAVAIL;
   3258     }
   3259     SR_FLOW_RX_LOCK(unit, fidx);
   3260     /* Seqnum history window reset requires special handling */
   3261     if (flags & BCM_TSN_SR_RX_FLOW_RESET_SEQNUM_WIN_HISTORY) {
   3262         /* Get reset mode first */
   3263         rv = bcm_esw_tsn_control_get(
   3264                 unit, bcmTsnControlSrSeqNumWindowResetMode, &reset_mode);
   3265         if (BCM_FAILURE(rv)) {
   3266             SR_FLOW_RX_UNLOCK(unit, fidx);
   3267             return rv;
   3268         }
   3269         /* Reset seqnum window using platform specific routine */
   3270         rv = SR_FLOW_MGMT_DEVINFO(unit)->seqnum_hist_reset(
   3271                 unit, fidx,
   3272                 bkinfo->flows_rx[fidx].config.seqnum_history_win_size,
   3273                 bkinfo->flows_rx[fidx].sn_slice, reset_mode);
   3274         if (BCM_FAILURE(rv)) {
   3275             SR_FLOW_RX_UNLOCK(unit, fidx);
   3276             return rv;
   3277         }
   3278     }
   3279     /* For other flags, call another plafform specific routine */
   3280     if (flags & (~BCM_TSN_SR_RX_FLOW_RESET_SEQNUM_WIN_HISTORY)) {
   3281         rv = SR_FLOW_MGMT_DEVINFO(unit)->reset_rx_flow(unit, fidx, flags);
   3282         if (BCM_FAILURE(rv)) {
   3283             SR_FLOW_RX_UNLOCK(unit, fidx);
   3284             return rv;
   3285         }
   3286     }
   3287     SR_FLOW_RX_UNLOCK(unit, fidx);
   3288     return BCM_E_NONE;
   3289 }
   3290 
   3291 /*
   3292  * Function:
   3293  *     bcmi_esw_tsn_sr_rx_flow_seqnum_history_get
   3294  * Purpose:
   3295  *     Get the sequence number history bits (one bit for one sequence number)
   3296  *     in the RX flow.
   3297  * Parameters:
   3298  *     unit             - (IN) unit number
   3299  *     flow_id          - (IN) flow ID
   3300  *     offset           - (IN) Offset (in bits) in the seqnum history window
   3301  *     max_size         - (IN) Size (in bits) of the buffer
   3302  *     history          - (OUT) Bit buffer to read
   3303  *     actual           - (OUT) Actual size (in bits) read to the buffer
   3304  * Returns:
   3305  *     BCM_E_XXX
   3306  * Notes:
   3307  *     If it's called with a TX flow, BCM_E_BADID is returned
   3308  */
   3309 STATIC int
   3310 bcmi_esw_tsn_sr_rx_flow_seqnum_history_get(
   3311     int unit,
   3312     bcm_tsn_sr_flow_t flow_id,
   3313     int offset,
   3314     int max_size,
   3315     uint8 *history,
   3316     int *actual)
   3317 {
   3318     bcmi_esw_tsn_bk_info_t *tsn_bk;
   3319     tsn_sr_flows_bookkeeping_t *bkinfo;
   3320     int fidx;
   3321     int dir;
   3322     int winsize;
   3323     int rv;
   3324     int i;
   3325 
   3326     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   3327     if (history == NULL || actual == NULL || offset < 0 || max_size <= 0) {
   3328         return BCM_E_PARAM;
   3329     }
   3330     bkinfo = &tsn_bk->sr_flows;
   3331     dir = SR_FLOW_ID_TO_DIR(flow_id);
   3332     fidx = SR_FLOW_ID_TO_IDX(flow_id);
   3333     if (dir != SR_FLOW_DIR_RX) {
   3334         return BCM_E_BADID;
   3335     }
   3336     if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) {
   3337         return BCM_E_PARAM;
   3338     }
   3339 
   3340     /* Validate if it's from a flowset */
   3341     for (i = fidx; i >= 0; i--) {
   3342         if (bkinfo->flowsets[dir][i].num_flows != 0) {
   3343             if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) {
   3344                 break;
   3345             } else {
   3346                 return BCM_E_NOT_FOUND;
   3347             }
   3348         }
   3349     }
   3350     if (i == -1) {
   3351         /* No valid flowsets */
   3352         return BCM_E_NOT_FOUND;
   3353     }
   3354 
   3355     /* Call platform specific routine to do it */
   3356     if (!SR_FLOW_MGMT_DEVINFO(unit)->seqnum_hist_read) {
   3357         return BCM_E_UNAVAIL;
   3358     }
   3359     SR_FLOW_RX_LOCK(unit, fidx);
   3360     /* Do advanced parameter check */
   3361     winsize = bkinfo->flows_rx[fidx].config.seqnum_history_win_size;
   3362     if (offset >= winsize) {
   3363         SR_FLOW_RX_UNLOCK(unit, fidx);
   3364         return BCM_E_PARAM;
   3365     }
   3366     max_size = (max_size > (winsize - offset) ? (winsize - offset) : max_size);
   3367     /* Call platform specific routine for seqnum operation */
   3368     rv = SR_FLOW_MGMT_DEVINFO(unit)->seqnum_hist_read(
   3369             unit, fidx,
   3370             bkinfo->flows_rx[fidx].config.seqnum_history_win_size,
   3371             bkinfo->flows_rx[fidx].sn_slice,
   3372             offset, max_size, history, actual);
   3373     SR_FLOW_RX_UNLOCK(unit, fidx);
   3374     return rv;
   3375 
   3376 }
   3377 
   3378 /*
   3379  * Function:
   3380  *     bcmi_esw_tsn_sr_rx_flow_seqnum_history_set
   3381  * Purpose:
   3382  *     Set the sequence number history bits (one bit for one sequence number)
   3383  *     in the RX flow.
   3384  * Parameters:
   3385  *     unit             - (IN) unit number
   3386  *     flow_id          - (IN) flow ID
   3387  *     offset           - (IN) Offset (in bits) in the seqnum history window
   3388  *     size             - (IN) Size (in bits) to write
   3389  *     history          - (IN) Bit buffer to write
   3390  * Returns:
   3391  *     BCM_E_XXX
   3392  * Notes:
   3393  *     If it's called with a TX flow, BCM_E_BADID is returned
   3394  */
   3395 STATIC int
   3396 bcmi_esw_tsn_sr_rx_flow_seqnum_history_set(
   3397     int unit,
   3398     bcm_tsn_sr_flow_t flow_id,
   3399     int offset,
   3400     int size,
   3401     uint8 *history)
   3402 {
   3403     bcmi_esw_tsn_bk_info_t *tsn_bk;
   3404     tsn_sr_flows_bookkeeping_t *bkinfo;
   3405     int fidx;
   3406     int dir;
   3407     int winsize;
   3408     int rv;
   3409     int i;
   3410 
   3411     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   3412     if (history == NULL || offset < 0 || size <= 0) {
   3413         return BCM_E_PARAM;
   3414     }
   3415     bkinfo = &tsn_bk->sr_flows;
   3416     dir = SR_FLOW_ID_TO_DIR(flow_id);
   3417     fidx = SR_FLOW_ID_TO_IDX(flow_id);
   3418     if (dir != SR_FLOW_DIR_RX) {
   3419         return BCM_E_BADID;
   3420     }
   3421     if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) {
   3422         return BCM_E_PARAM;
   3423     }
   3424 
   3425     /* Validate if it's from a flowset */
   3426     for (i = fidx; i >= 0; i--) {
   3427         if (bkinfo->flowsets[dir][i].num_flows != 0) {
   3428             if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) {
   3429                 break;
   3430             } else {
   3431                 return BCM_E_NOT_FOUND;
   3432             }
   3433         }
   3434     }
   3435     if (i == -1) {
   3436         /* No valid flowsets */
   3437         return BCM_E_NOT_FOUND;
   3438     }
   3439 
   3440     /* Call platform specific routine to do it */
   3441     if (!SR_FLOW_MGMT_DEVINFO(unit)->seqnum_hist_write) {
   3442         return BCM_E_UNAVAIL;
   3443     }
   3444 
   3445     SR_FLOW_RX_LOCK(unit, fidx);
   3446     /* Do advanced parameter check */
   3447     winsize = bkinfo->flows_rx[fidx].config.seqnum_history_win_size;
   3448     if (offset >= winsize || size > winsize) {
   3449         SR_FLOW_RX_UNLOCK(unit, fidx);
   3450         return BCM_E_PARAM;
   3451     }
   3452     /* Call platform specific routine for seqnum operation */
   3453     rv = SR_FLOW_MGMT_DEVINFO(unit)->seqnum_hist_write(
   3454             unit, fidx, winsize, bkinfo->flows_rx[fidx].sn_slice,
   3455             offset, size, history);
   3456     SR_FLOW_RX_UNLOCK(unit, fidx);
   3457     return rv;
   3458 }
   3459 
   3460 /*
   3461  * Function:
   3462  *     bcmi_esw_tsn_sr_hw_flow_id_get
   3463  * Purpose:
   3464  *     Convert software SR flow ID to hardware SR flow ID
   3465  * Parameters:
   3466  *     unit             - (IN) unit number
   3467  *     flow_id          - (IN) SW flow ID
   3468  *     hw_id            - (OUT) HW flow ID
   3469  * Returns:
   3470  *     BCM_E_XXX
   3471  * Notes:
   3472  */
   3473 int
   3474 bcmi_esw_tsn_sr_hw_flow_id_get(
   3475     int unit,
   3476     bcm_tsn_sr_flow_t flow_id,
   3477     uint32 *hw_id)
   3478 {
   3479     bcmi_esw_tsn_bk_info_t *tsn_bk;
   3480     tsn_sr_flows_bookkeeping_t *bkinfo;
   3481     int fidx;
   3482     int dir;
   3483 
   3484     /* parameter check */
   3485     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   3486         return BCM_E_UNAVAIL;
   3487     }
   3488     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   3489     if (hw_id == NULL) {
   3490         return BCM_E_PARAM;
   3491     }
   3492     bkinfo = &tsn_bk->sr_flows;
   3493     dir = SR_FLOW_ID_TO_DIR(flow_id);
   3494     fidx = SR_FLOW_ID_TO_IDX(flow_id);
   3495     if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) {
   3496         return BCM_E_PARAM;
   3497     }
   3498 
   3499     /* Call platform specific routine to convert */
   3500     if (!SR_FLOW_MGMT_DEVINFO(unit)->get_hw_flow_id) {
   3501         return BCM_E_UNAVAIL;
   3502     }
   3503     return SR_FLOW_MGMT_DEVINFO(unit)->get_hw_flow_id(
   3504                 unit, (dir == SR_FLOW_DIR_TX), fidx, hw_id);
   3505 }
   3506 
   3507 /*
   3508  * Function:
   3509  *     bcmi_esw_tsn_sr_sw_flow_id_get
   3510  * Purpose:
   3511  *     Convert hardware SR flow ID to software SR flow ID
   3512  * Parameters:
   3513  *     unit             - (IN) unit number
   3514  *     hw_id            - (IN) HW flow ID
   3515  *     flow_id          - (OUT) SW flow ID
   3516  * Returns:
   3517  *     BCM_E_XXX
   3518  * Notes:
   3519  */
   3520 int
   3521 bcmi_esw_tsn_sr_sw_flow_id_get(
   3522     int unit,
   3523     uint32 hw_id,
   3524     bcm_tsn_sr_flow_t *flow_id)
   3525 {
   3526     bcmi_esw_tsn_bk_info_t *tsn_bk;
   3527     tsn_sr_flows_bookkeeping_t *bkinfo;
   3528     const bcmi_esw_tsn_dev_info_t *dev_info;
   3529     int is_tx;
   3530     int dir;
   3531     int fidx;
   3532 
   3533     /* parameter check */
   3534     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   3535         return BCM_E_UNAVAIL;
   3536     }
   3537 
   3538     if (flow_id == NULL) {
   3539         return BCM_E_PARAM;
   3540     }
   3541 
   3542     if (tsn_bk_info[unit] == NULL) {
   3543         /* Using device specific info that need no bk_info */
   3544         BCM_IF_ERROR_RETURN(bcmi_esw_tsn_noninit_dev_info_get(unit, &dev_info));
   3545         if (!dev_info->sr_flows_info->get_sw_flow_idx) {
   3546             return BCM_E_UNAVAIL;
   3547         }
   3548         BCM_IF_ERROR_RETURN(
   3549             dev_info->sr_flows_info->get_sw_flow_idx(unit, hw_id,
   3550                                                      &is_tx, &fidx));
   3551         dir = is_tx ? SR_FLOW_DIR_TX : SR_FLOW_DIR_RX;
   3552         *flow_id = SR_FLOW_ID_FROM_IDX(dir, fidx);
   3553         return BCM_E_NONE;
   3554     }
   3555 
   3556     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   3557     bkinfo = &tsn_bk->sr_flows;
   3558 
   3559     /* Call platform specific routine to convert */
   3560     if (!SR_FLOW_MGMT_DEVINFO(unit)->get_sw_flow_idx) {
   3561         return BCM_E_UNAVAIL;
   3562     }
   3563     BCM_IF_ERROR_RETURN(
   3564         SR_FLOW_MGMT_DEVINFO(unit)->get_sw_flow_idx(
   3565             unit, hw_id, &is_tx, &fidx));
   3566     dir = is_tx ? SR_FLOW_DIR_TX : SR_FLOW_DIR_RX;
   3567 
   3568     /* Validate converted index */
   3569     if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) {
   3570         return BCM_E_PARAM;
   3571     }
   3572 
   3573     /* Done */
   3574     *flow_id = SR_FLOW_ID_FROM_IDX(dir, fidx);
   3575     return BCM_E_NONE;
   3576 }
   3577 
   3578 /*
   3579  * Function:
   3580  *     bcmi_esw_tsn_sr_flowset_identify
   3581  * Purpose:
   3582  *     SR flow to flowset converstion (identify the flowset based on a flow)
   3583  * Parameters:
   3584  *     unit             - (IN) unit number
   3585  *     flow_id          - (IN) flow ID
   3586  *     flowset          - (OUT) flowset ID
   3587  * Returns:
   3588  *     BCM_E_XXX
   3589  * Notes:
   3590  */
   3591 int
   3592 bcmi_esw_tsn_sr_flowset_identify(
   3593     int unit,
   3594     bcm_tsn_sr_flow_t flow_id,
   3595     bcm_tsn_sr_flowset_t *flowset)
   3596 {
   3597     bcmi_esw_tsn_bk_info_t *tsn_bk;
   3598     tsn_sr_flows_bookkeeping_t *bkinfo;
   3599     int fidx;
   3600     int dir;
   3601     int i;
   3602 
   3603     /* parameter check */
   3604     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   3605         return BCM_E_UNAVAIL;
   3606     }
   3607     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   3608     if (flowset == NULL) {
   3609         return BCM_E_PARAM;
   3610     }
   3611     bkinfo = &tsn_bk->sr_flows;
   3612     dir = SR_FLOW_ID_TO_DIR(flow_id);
   3613     fidx = SR_FLOW_ID_TO_IDX(flow_id);
   3614     if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) {
   3615         return BCM_E_PARAM;
   3616     }
   3617 
   3618     /* Find the flowset */
   3619     for (i = fidx; i >= 0; i--) {
   3620         if (bkinfo->flowsets[dir][i].num_flows != 0) {
   3621             if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) {
   3622                 /* Convert to user flowset ID */
   3623                 *flowset = SR_FLOWSET_ID_FROM_IDX(dir, i);
   3624                 return BCM_E_NONE;
   3625             } else {
   3626                 /* The flow is not within this flowset */
   3627                 return BCM_E_NOT_FOUND;
   3628             }
   3629         }
   3630     }
   3631 
   3632     /* No flowset found with index less than the flow */
   3633     return BCM_E_NOT_FOUND;
   3634 }
   3635 
   3636 #ifdef BCM_WARM_BOOT_SUPPORT
   3637 /* SR flow: allocate specified flow idx(s) for warmboot restore */
   3638 STATIC int
   3639 bcmi_esw_tsn_sr_flow_idx_restore(
   3640     int unit,
   3641     int dir,
   3642     int index,
   3643     int count,
   3644     tsn_sr_flowidx_entry_t **entry)
   3645 {
   3646     bcmi_esw_tsn_bk_info_t *tsn_bk;
   3647     tsn_sr_flows_bookkeeping_t *bkinfo;
   3648     tsn_sr_flowidx_entry_t *fid, *prev, *bprev, *begin;
   3649 
   3650     /* parameter check */
   3651     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   3652     if (dir < 0 || dir >= SR_FLOW_DIR_COUNT || count <= 0 || entry == NULL) {
   3653         return BCM_E_PARAM;
   3654     }
   3655     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   3656     bkinfo = &tsn_bk->sr_flows;
   3657 
   3658     /* Protect access to the flow indexes */
   3659     SR_FLOW_MGMT_LOCK(unit);
   3660 
   3661     /* Traverse the list and search for the specified items */
   3662     begin = NULL;
   3663     prev = bprev = NULL;
   3664     for (fid = bkinfo->flowids_avail[dir]; fid != NULL; fid = fid->next) {
   3665         if (fid->flow_idx == index) {
   3666             if (begin == NULL) {
   3667                 /* Found the head */
   3668                 begin = fid;
   3669                 bprev = prev;
   3670             }
   3671 
   3672             /* Check if we have got all the items */
   3673             count--;
   3674             if (count == 0) {
   3675                 /* Done. Removing the chain from the list */
   3676                 if (NULL == bprev) {
   3677                     /* The chain was the head */
   3678                     bkinfo->flowids_avail[dir] = fid->next;
   3679                 } else {
   3680                     /* Connect previous one to the next of the chain */
   3681                     bprev->next = fid->next;
   3682                 }
   3683 
   3684                 /* Terminate this chain and return */
   3685                 fid->next = NULL;
   3686                 *entry = begin;
   3687                 SR_FLOW_MGMT_UNLOCK(unit);
   3688                 return BCM_E_NONE;
   3689             }
   3690             index++;
   3691         } else if (fid->flow_idx > index) {
   3692             /* Not found in this sorted list */
   3693             break;
   3694         }
   3695 
   3696         /* record the previous one */
   3697         prev = fid;
   3698     }
   3699 
   3700     /* Cannot find the specified item or enough continuous entries */
   3701     SR_FLOW_MGMT_UNLOCK(unit);
   3702     return BCM_E_INTERNAL;
   3703 }
   3704 
   3705 /* SR flow management - warmboot scache size allocation */
   3706 STATIC int
   3707 bcmi_esw_tsn_sr_flow_mgmt_wb_alloc(int unit)
   3708 {
   3709     bcmi_esw_tsn_bk_info_t *tsn_bk;
   3710     tsn_sr_flows_bookkeeping_t *bkinfo;
   3711     soc_scache_handle_t scache_handle;
   3712     uint8 *scache_ptr = NULL;
   3713     int stable_size = 0;
   3714     int alloc_size;
   3715     int rv;
   3716 
   3717     /* parameter check */
   3718     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   3719         return BCM_E_UNAVAIL;
   3720     }
   3721     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   3722     bkinfo = &tsn_bk->sr_flows;
   3723 
   3724     /* Requires extended scache support level-2 warmboot */
   3725     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   3726     if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
   3727         return BCM_E_NONE;
   3728     }
   3729 
   3730     /* Calculate allocate size */
   3731     alloc_size = 0;
   3732     alloc_size += sizeof(uint16);       /* Number of actual RX flows */
   3733     alloc_size += sizeof(uint16);       /* Number of actual TX flows */
   3734     alloc_size +=                       /* RX flows */
   3735         sizeof(tsn_sr_rx_flowset_wb_t) * bkinfo->max_flows[SR_FLOW_DIR_RX];
   3736     alloc_size +=                       /* TX flows */
   3737         sizeof(tsn_sr_tx_flowset_wb_t) * bkinfo->max_flows[SR_FLOW_DIR_TX];
   3738 
   3739     /* Allocate scache for warmboot */
   3740     SOC_SCACHE_HANDLE_SET(scache_handle, unit,
   3741                           BCM_MODULE_TSN, BCM_TSN_WB_SCACHE_PART_SR_FLOWS);
   3742     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size,
   3743                                  &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL);
   3744     if (rv == BCM_E_NOT_FOUND) {
   3745         /* Proceed with level 1 warmboot */
   3746         rv = BCM_E_NONE;
   3747     }
   3748 
   3749     return rv;
   3750 }
   3751 
   3752 /* SR flow management - sync information to scache */
   3753 STATIC int
   3754 bcmi_esw_tsn_sr_flow_mgmt_sync(int unit)
   3755 {
   3756     bcmi_esw_tsn_bk_info_t *tsn_bk;
   3757     tsn_sr_flows_bookkeeping_t *bkinfo;
   3758     soc_scache_handle_t scache_handle;
   3759     uint8 *scache_ptr = NULL, *scache;
   3760     tsn_sr_rx_flowset_wb_t rxflow;
   3761     tsn_sr_tx_flowset_wb_t txflow;
   3762     int stable_size = 0;
   3763     tsn_sr_flowset_t *fset;
   3764     uint16 flows;
   3765     int rv;
   3766     int i;
   3767 
   3768     /* parameter check */
   3769     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   3770         return BCM_E_UNAVAIL;
   3771     }
   3772     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   3773     bkinfo = &tsn_bk->sr_flows;
   3774 
   3775     /* Requires extended scache support level-2 warmboot */
   3776     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   3777     if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
   3778         return BCM_E_NONE;
   3779     }
   3780     SOC_SCACHE_HANDLE_SET(scache_handle, unit,
   3781                           BCM_MODULE_TSN, BCM_TSN_WB_SCACHE_PART_SR_FLOWS);
   3782     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
   3783                                  &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL);
   3784     if (rv == BCM_E_NOT_FOUND) {
   3785         return BCM_E_NONE;
   3786     }
   3787     BCM_IF_ERROR_RETURN(rv);
   3788     assert(scache_ptr != NULL);
   3789 
   3790     /* Avoid flowsets to be created/destroyed at the same time */
   3791     SR_FLOW_MGMT_LOCK(unit);
   3792 
   3793     /* Loop through RX flowsets and save to scache */
   3794     flows = 0;
   3795     scache = scache_ptr + sizeof(uint16) * 2;
   3796     for (i = 0; i < bkinfo->max_flows[SR_FLOW_DIR_RX]; i++) {
   3797         fset = &bkinfo->flowsets[SR_FLOW_DIR_RX][i];
   3798         SR_FLOWSET_LOCK(fset);
   3799         if (fset->num_flows != 0) {
   3800             rxflow.flow_idx = i;
   3801             rxflow.map_id = fset->map_id;
   3802             sal_memcpy(&rxflow.config, &fset->config.rx, sizeof(rxflow.config));
   3803             flows++;
   3804             sal_memcpy(scache, &rxflow, sizeof(rxflow));
   3805             scache += sizeof(rxflow);
   3806         }
   3807         SR_FLOWSET_UNLOCK(fset);
   3808     }
   3809     sal_memcpy(scache_ptr, &flows, sizeof(uint16)); /* Actual RX flowsets */
   3810 
   3811     /* And TX flowsets */
   3812     flows = 0;
   3813     for (i = 0; i < bkinfo->max_flows[SR_FLOW_DIR_TX]; i++) {
   3814         fset = &bkinfo->flowsets[SR_FLOW_DIR_TX][i];
   3815         SR_FLOWSET_LOCK(fset);
   3816         if (fset->num_flows != 0) {
   3817             txflow.flow_idx = i;
   3818             txflow.map_id = fset->map_id;
   3819             sal_memcpy(&txflow.config, &fset->config.tx, sizeof(txflow.config));
   3820             flows++;
   3821             sal_memcpy(scache, &txflow, sizeof(txflow));
   3822             scache += sizeof(txflow);
   3823         }
   3824         SR_FLOWSET_UNLOCK(fset);
   3825     }
   3826     sal_memcpy(scache_ptr + sizeof(uint16), &flows, sizeof(uint16));
   3827 
   3828     /* Done */
   3829     SR_FLOW_MGMT_UNLOCK(unit);
   3830     return BCM_E_NONE;
   3831 }
   3832 
   3833 /* SR flow management - reload flow management information from scache */
   3834 STATIC int
   3835 bcmi_esw_tsn_sr_flow_mgmt_reload(int unit)
   3836 {
   3837     bcmi_esw_tsn_bk_info_t *tsn_bk;
   3838     tsn_sr_flows_bookkeeping_t *bkinfo;
   3839     soc_scache_handle_t scache_handle;
   3840     uint8 *scache_ptr = NULL;
   3841     tsn_sr_rx_flowset_wb_t rxflow;
   3842     tsn_sr_tx_flowset_wb_t txflow;
   3843     int stable_size = 0;
   3844     tsn_sr_flowset_t *fset;
   3845     tsn_sr_flowidx_entry_t *flow_ide;
   3846     bcm_tsn_pri_map_config_t pmcfg;
   3847     uint16 rxflows, txflows, i;
   3848     int num_flows;
   3849     int rv;
   3850     int j, idx;
   3851 
   3852     /* parameter check */
   3853     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   3854         return BCM_E_UNAVAIL;
   3855     }
   3856     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   3857     bkinfo = &tsn_bk->sr_flows;
   3858     if (!SR_FLOW_MGMT_DEVINFO(unit)->read_rx_flow ||
   3859         !SR_FLOW_MGMT_DEVINFO(unit)->read_tx_flow) {
   3860         return BCM_E_UNAVAIL;
   3861     }
   3862 
   3863     /* Requires extended scache support level-2 warmboot */
   3864     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
   3865     if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
   3866         return BCM_E_NONE;
   3867     }
   3868     SOC_SCACHE_HANDLE_SET(scache_handle, unit,
   3869                           BCM_MODULE_TSN, BCM_TSN_WB_SCACHE_PART_SR_FLOWS);
   3870     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
   3871                                  &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL);
   3872     if (rv == BCM_E_NOT_FOUND) {
   3873         return BCM_E_NONE;
   3874     }
   3875     BCM_IF_ERROR_RETURN(rv);
   3876     assert(scache_ptr != NULL);
   3877 
   3878     /* Avoid flowsets to be created/destroyed at the same time */
   3879     SR_FLOW_MGMT_LOCK(unit);
   3880 
   3881     /* Get number of saved RX/TX flowsets */
   3882     sal_memcpy(&rxflows, scache_ptr, sizeof(uint16));
   3883     scache_ptr += sizeof(uint16);
   3884     sal_memcpy(&txflows, scache_ptr, sizeof(uint16));
   3885     scache_ptr += sizeof(uint16);
   3886 
   3887     /* Restore RX flowsets */
   3888     for (i = 0; i < rxflows; i++) {
   3889         /* Read from scache */
   3890         sal_memcpy(&rxflow, scache_ptr, sizeof(rxflow));
   3891         scache_ptr += sizeof(rxflow);
   3892 
   3893         /* Validate flow index */
   3894         if (rxflow.flow_idx < 0 ||
   3895             rxflow.flow_idx >= bkinfo->max_flows[SR_FLOW_DIR_RX]) {
   3896             SR_FLOW_MGMT_UNLOCK(unit);
   3897             return BCM_E_INTERNAL;
   3898         }
   3899 
   3900         /* Validate priority map and get number of flows inside this flowset */
   3901         num_flows = 1;
   3902         if (rxflow.map_id != BCM_TSN_PRI_MAP_INVALID) {
   3903             /* call API to get priority map configuration */
   3904             rv = bcm_esw_tsn_pri_map_get(unit, rxflow.map_id, &pmcfg);
   3905             if (BCM_FAILURE(rv) || pmcfg.map_type != bcmTsnPriMapTypeSrFlow) {
   3906                 SR_FLOW_MGMT_UNLOCK(unit);
   3907                 return BCM_E_INTERNAL;
   3908             }
   3909             /* Number of flows is max flow offset + 1 */
   3910             for (j = 0; j < pmcfg.num_map_entries; j++) {
   3911                 if ((pmcfg.map_entries[j].flags &
   3912                      BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET) &&
   3913                     (pmcfg.map_entries[j].flow_offset > num_flows - 1)) {
   3914                     num_flows = pmcfg.map_entries[j].flow_offset + 1;
   3915                 }
   3916             }
   3917         }
   3918 
   3919         /* Restore flow index entries */
   3920         rv = bcmi_esw_tsn_sr_flow_idx_restore(
   3921                 unit, SR_FLOW_DIR_RX, rxflow.flow_idx, num_flows, &flow_ide);
   3922         if (BCM_FAILURE(rv)) {
   3923             SR_FLOW_MGMT_UNLOCK(unit);
   3924             return BCM_E_INTERNAL;
   3925         }
   3926 
   3927         /* Confirmed that this flowset can be restored */
   3928         fset = &bkinfo->flowsets[SR_FLOW_DIR_RX][rxflow.flow_idx];
   3929         SR_FLOWSET_LOCK(fset);
   3930 
   3931         /* Restore the flowset */
   3932         fset->flow_ide = flow_ide;
   3933         fset->map_id = rxflow.map_id;
   3934         fset->num_flows = num_flows;
   3935         fset->ref_count = 0;
   3936         sal_memcpy(&fset->config.rx, &rxflow.config, sizeof(rxflow.config));
   3937 
   3938         /* Restore the individual flows */
   3939         for (j = 0; j < num_flows; j++) {
   3940             idx = rxflow.flow_idx + j;
   3941             SR_FLOW_RX_LOCK(unit, idx);
   3942             rv = SR_FLOW_MGMT_DEVINFO(unit)->read_rx_flow(
   3943                     unit, idx, &bkinfo->flows_rx[idx]);
   3944             if (BCM_FAILURE(rv)) {
   3945                 SR_FLOW_RX_UNLOCK(unit, idx);
   3946                 SR_FLOWSET_UNLOCK(fset);
   3947                 SR_FLOW_MGMT_UNLOCK(unit);
   3948                 return rv;
   3949             }
   3950             SR_FLOW_RX_UNLOCK(unit, idx);
   3951         }
   3952 
   3953         /* Done restoring this flowset */
   3954         SR_FLOWSET_UNLOCK(fset);
   3955     }
   3956 
   3957     /* Restore TX flowsets */
   3958     for (i = 0; i < txflows; i++) {
   3959         /* Read from scache */
   3960         sal_memcpy(&txflow, scache_ptr, sizeof(txflow));
   3961         scache_ptr += sizeof(txflow);
   3962 
   3963         /* Validate flow index */
   3964         if (txflow.flow_idx < 0 ||
   3965             txflow.flow_idx >= bkinfo->max_flows[SR_FLOW_DIR_TX]) {
   3966             SR_FLOW_MGMT_UNLOCK(unit);
   3967             return BCM_E_INTERNAL;
   3968         }
   3969 
   3970         /* Validate priority map and get number of flows inside this flowset */
   3971         num_flows = 1;
   3972         if (txflow.map_id != BCM_TSN_PRI_MAP_INVALID) {
   3973             /* call API to get priority map configuration */
   3974             rv = bcm_esw_tsn_pri_map_get(unit, txflow.map_id, &pmcfg);
   3975             if (BCM_FAILURE(rv) || pmcfg.map_type != bcmTsnPriMapTypeSrFlow) {
   3976                 SR_FLOW_MGMT_UNLOCK(unit);
   3977                 return BCM_E_INTERNAL;
   3978             }
   3979             /* Number of flows is max flow offset + 1 */
   3980             for (j = 0; j < pmcfg.num_map_entries; j++) {
   3981                 if ((pmcfg.map_entries[j].flags &
   3982                      BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET) &&
   3983                     (pmcfg.map_entries[j].flow_offset > num_flows - 1)) {
   3984                     num_flows = pmcfg.map_entries[j].flow_offset + 1;
   3985                 }
   3986             }
   3987         }
   3988 
   3989         /* Restore flow index entries */
   3990         rv = bcmi_esw_tsn_sr_flow_idx_restore(
   3991                 unit, SR_FLOW_DIR_TX, txflow.flow_idx, num_flows, &flow_ide);
   3992         if (BCM_FAILURE(rv)) {
   3993             SR_FLOW_MGMT_UNLOCK(unit);
   3994             return BCM_E_INTERNAL;
   3995         }
   3996 
   3997         /* Confirmed that this flowset can be restored */
   3998         fset = &bkinfo->flowsets[SR_FLOW_DIR_TX][txflow.flow_idx];
   3999         SR_FLOWSET_LOCK(fset);
   4000 
   4001         /* Restore the flowset */
   4002         fset->flow_ide = flow_ide;
   4003         fset->map_id = txflow.map_id;
   4004         fset->num_flows = num_flows;
   4005         fset->ref_count = 0;
   4006         sal_memcpy(&fset->config.tx, &txflow.config, sizeof(txflow.config));
   4007 
   4008         /* Restore the individual flows */
   4009         for (j = 0; j < num_flows; j++) {
   4010             idx = txflow.flow_idx + j;
   4011             SR_FLOW_TX_LOCK(unit, idx);
   4012             rv = SR_FLOW_MGMT_DEVINFO(unit)->read_tx_flow(
   4013                     unit, idx, &bkinfo->flows_tx[idx]);
   4014             if (BCM_FAILURE(rv)) {
   4015                 SR_FLOW_TX_UNLOCK(unit, idx);
   4016                 SR_FLOWSET_UNLOCK(fset);
   4017                 SR_FLOW_MGMT_UNLOCK(unit);
   4018                 return rv;
   4019             }
   4020             SR_FLOW_TX_UNLOCK(unit, idx);
   4021         }
   4022 
   4023         /* Done restoring this flowset */
   4024         SR_FLOWSET_UNLOCK(fset);
   4025     }
   4026 
   4027     /* Done */
   4028     SR_FLOW_MGMT_UNLOCK(unit);
   4029     return BCM_E_NONE;
   4030 }
   4031 #endif /* BCM_WARM_BOOT_SUPPORT */
   4032 
   4033 /* SR flow management de-initialization */
   4034 STATIC int
   4035 bcmi_esw_tsn_sr_flow_mgmt_detach(int unit)
   4036 {
   4037     tsn_sr_flows_bookkeeping_t *bkinfo;
   4038     int dir, i;
   4039 
   4040     /* parameter check */
   4041     if (!SOC_UNIT_VALID(unit)) {
   4042         return BCM_E_UNIT;
   4043     }
   4044 
   4045     /* check if it's already cleared */
   4046     bkinfo = &tsn_bk_info[unit]->sr_flows;
   4047     if (NULL == bkinfo) {
   4048         return BCM_E_NONE;
   4049     }
   4050 
   4051     /* de-allocate flow index pool */
   4052     if (NULL != bkinfo->flowids_allocated) {
   4053         sal_free(bkinfo->flowids_allocated);
   4054         bkinfo->flowids_allocated = NULL;
   4055     }
   4056 
   4057     /* de-allocate flow instances */
   4058     if (NULL != bkinfo->flows_rx) {
   4059         sal_free(bkinfo->flows_rx);
   4060         bkinfo->flows_rx = NULL;
   4061     }
   4062     if (NULL != bkinfo->flows_tx) {
   4063         sal_free(bkinfo->flows_tx);
   4064         bkinfo->flows_tx = NULL;
   4065     }
   4066 
   4067     /* de-allocate flow mutexes */
   4068     if (NULL != bkinfo->flows_rx_mutex) {
   4069         for (i = 0; i < bkinfo->max_flows[SR_FLOW_DIR_RX]; i++) {
   4070             if (bkinfo->flows_rx_mutex[i] != NULL) {
   4071                 sal_mutex_destroy(bkinfo->flows_rx_mutex[i]);
   4072                 bkinfo->flows_rx_mutex[i] = NULL;
   4073             }
   4074         }
   4075         sal_free(bkinfo->flows_rx_mutex);
   4076         bkinfo->flows_rx_mutex = NULL;
   4077     }
   4078     if (NULL != bkinfo->flows_tx_mutex) {
   4079         for (i = 0; i < bkinfo->max_flows[SR_FLOW_DIR_TX]; i++) {
   4080             if (bkinfo->flows_tx_mutex[i] != NULL) {
   4081                 sal_mutex_destroy(bkinfo->flows_tx_mutex[i]);
   4082                 bkinfo->flows_tx_mutex[i] = NULL;
   4083             }
   4084         }
   4085         sal_free(bkinfo->flows_tx_mutex);
   4086         bkinfo->flows_tx_mutex = NULL;
   4087     }
   4088 
   4089     /* De-allocate per direction */
   4090     for (dir = SR_FLOW_DIR_RX; dir < SR_FLOW_DIR_COUNT; dir++) {
   4091 
   4092         /* clear flow index linked list */
   4093         bkinfo->flowids_avail[dir] = NULL;
   4094 
   4095         /* de-allocate flowset instances */
   4096         if (NULL != bkinfo->flowsets[dir]) {
   4097             for (i = 0; i < bkinfo->max_flows[dir]; i++) {
   4098                 if (NULL != bkinfo->flowsets[dir][i].mutex) {
   4099                     sal_mutex_destroy(bkinfo->flowsets[dir][i].mutex);
   4100                     bkinfo->flowsets[dir][i].mutex = NULL;
   4101                 }
   4102             }
   4103             sal_free(bkinfo->flowsets[dir]);
   4104             bkinfo->flowsets[dir] = NULL;
   4105         }
   4106     }
   4107 
   4108     /* destroy the flow management mutex */
   4109     if (NULL != bkinfo->fmgmt_mutex) {
   4110         sal_mutex_destroy(bkinfo->fmgmt_mutex);
   4111         bkinfo->fmgmt_mutex = NULL;
   4112     }
   4113 
   4114     return BCM_E_NONE;
   4115 }
   4116 
   4117 /* SR flow management initialization */
   4118 STATIC int
   4119 bcmi_esw_tsn_sr_flow_mgmt_init(int unit)
   4120 {
   4121     tsn_sr_flows_bookkeeping_t *bkinfo;
   4122     tsn_sr_flowidx_entry_t *fid;
   4123     int rxflows, txflows;
   4124     int rv;
   4125     int d, i;
   4126 
   4127     /* parameter check */
   4128     if (!SOC_UNIT_VALID(unit)) {
   4129         return BCM_E_UNIT;
   4130     }
   4131 
   4132     /* Retrieve number of TX/RX flows */
   4133     bkinfo = &tsn_bk_info[unit]->sr_flows;
   4134     if (SR_FLOW_MGMT_DEVINFO(unit) == NULL ||
   4135         SR_FLOW_MGMT_DEVINFO(unit)->get_num_flows == NULL) {
   4136         return BCM_E_UNAVAIL;
   4137     }
   4138     rv = SR_FLOW_MGMT_DEVINFO(unit)->get_num_flows(unit, &rxflows, &txflows);
   4139     if (BCM_FAILURE(rv)) {
   4140         return rv;
   4141     }
   4142     if (rxflows < 0) {
   4143         rxflows = 0; /* Reserve negative value for future extension */
   4144     }
   4145     if (txflows < 0) {
   4146         txflows = 0; /* Reserve negative value for future extension */
   4147     }
   4148     if (rxflows + txflows == 0) {
   4149         /* No supported flows */
   4150         return BCM_E_UNAVAIL;
   4151     }
   4152     bkinfo->max_flows[SR_FLOW_DIR_RX] = rxflows;
   4153     bkinfo->max_flows[SR_FLOW_DIR_TX] = txflows;
   4154 
   4155     /*
   4156      * We need to minimize the time taken for picking a free flow index.
   4157      * To achieve this, we use linked list with pre-allocated entries so that
   4158      * we can do it in O(1).
   4159      */
   4160 
   4161     /* Allocate flow index entry pool (one pool for TX and RX) */
   4162     bkinfo->flowids_allocated = (tsn_sr_flowidx_entry_t *)sal_alloc(
   4163             sizeof(tsn_sr_flowidx_entry_t) * (rxflows + txflows),
   4164             "tsn sr flow ids");
   4165     if (NULL == bkinfo->flowids_allocated) {
   4166         LOG_ERROR(BSL_LS_BCM_TSN,
   4167                   (BSL_META("TSN SR: failed to allocate flow IDs\n")));
   4168         (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit);
   4169         return BCM_E_MEMORY;
   4170     }
   4171 
   4172     /* For RX and TX directions */
   4173     fid = bkinfo->flowids_allocated;
   4174     for (d = SR_FLOW_DIR_RX; d < SR_FLOW_DIR_COUNT; d++) {
   4175 
   4176         /* Prepare flow index entry linked list for quick ID allocation */
   4177         for (i = 0; i < bkinfo->max_flows[d]; i++, fid++) {
   4178             /*
   4179              * Add an entry to the head of the linked list.
   4180              * The flow index is going backward so the final list can be in
   4181              * increasing order (some allocation requires continuous flows).
   4182              */
   4183             fid->flow_idx = bkinfo->max_flows[d] - i - 1;
   4184             fid->next = bkinfo->flowids_avail[d];
   4185             bkinfo->flowids_avail[d] = fid;
   4186         }
   4187 
   4188         /* Allocate array of RX/TX flowset instances */
   4189         if (bkinfo->max_flows[d] > 0) {
   4190             /* The max number of flowsets should be the same as flows */
   4191             bkinfo->flowsets[d] = (tsn_sr_flowset_t *)sal_alloc(
   4192                 sizeof(tsn_sr_flowset_t) * bkinfo->max_flows[d],
   4193                 "tsn sr rx flows");
   4194             if (NULL == bkinfo->flowsets[d]) {
   4195                 LOG_ERROR(BSL_LS_BCM_TSN,
   4196                           (BSL_META("TSN SR: failed to allocate flowsets\n")));
   4197                 (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit);
   4198                 return BCM_E_MEMORY;
   4199             }
   4200             sal_memset(bkinfo->flowsets[d], 0,
   4201                 sizeof(tsn_sr_flowset_t) * bkinfo->max_flows[d]);
   4202             /* Pre-create mutexes of all flowsets for performance */
   4203             for (i = 0; i < bkinfo->max_flows[d]; i++) {
   4204                 bkinfo->flowsets[d][i].mutex =
   4205                     sal_mutex_create("tsn sr flowset");
   4206                 if (NULL == bkinfo->flowsets[d][i].mutex) {
   4207                     LOG_ERROR(BSL_LS_BCM_TSN,
   4208                               (BSL_META(
   4209                                  "TSN SR: failed to create flowset mutex\n")));
   4210                     (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit);
   4211                     return BCM_E_MEMORY;
   4212                 }
   4213             }
   4214         }
   4215     }
   4216 
   4217     /* Allocate array of RX/TX flow instances and mutexes */
   4218     if (rxflows > 0) {
   4219         bkinfo->flows_rx = (bcmi_tsn_sr_rx_flow_t *)sal_alloc(
   4220             sizeof(bcmi_tsn_sr_rx_flow_t) * rxflows, "tsn sr rx flows");
   4221         if (NULL == bkinfo->flows_rx) {
   4222             LOG_ERROR(BSL_LS_BCM_TSN,
   4223                       (BSL_META("TSN SR: failed to allocate RX flows\n")));
   4224             (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit);
   4225             return BCM_E_MEMORY;
   4226         }
   4227         sal_memset(bkinfo->flows_rx, 0,
   4228             sizeof(bcmi_tsn_sr_rx_flow_t) * rxflows);
   4229         bkinfo->flows_rx_mutex = (sal_mutex_t *)sal_alloc(
   4230             sizeof(sal_mutex_t) * rxflows, "tsn sr rx flows mutex");
   4231         if (NULL == bkinfo->flows_rx_mutex) {
   4232             LOG_ERROR(BSL_LS_BCM_TSN,
   4233                       (BSL_META(
   4234                           "TSN SR: failed to allocate RX flow mutexes\n")));
   4235             (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit);
   4236             return BCM_E_MEMORY;
   4237         }
   4238         for (i = 0; i < rxflows; i++) {
   4239             bkinfo->flows_rx_mutex[i] = sal_mutex_create("tsn sr flow mutex");
   4240             if (NULL == bkinfo->flows_rx_mutex[i]) {
   4241                 LOG_ERROR(BSL_LS_BCM_TSN,
   4242                           (BSL_META(
   4243                               "TSN SR: failed to create flow mutex\n")));
   4244                 (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit);
   4245                 return BCM_E_MEMORY;
   4246             }
   4247         }
   4248     }
   4249     if (txflows > 0) {
   4250         bkinfo->flows_tx = (bcmi_tsn_sr_tx_flow_t *)sal_alloc(
   4251             sizeof(bcmi_tsn_sr_tx_flow_t) * txflows, "tsn sr tx flows");
   4252         if (NULL == bkinfo->flows_tx) {
   4253             LOG_ERROR(BSL_LS_BCM_TSN,
   4254                       (BSL_META("TSN SR: failed to allocate TX flows\n")));
   4255             (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit);
   4256             return BCM_E_MEMORY;
   4257         }
   4258         sal_memset(bkinfo->flows_tx, 0,
   4259             sizeof(bcmi_tsn_sr_tx_flow_t) * txflows);
   4260         bkinfo->flows_tx_mutex = (sal_mutex_t *)sal_alloc(
   4261             sizeof(sal_mutex_t) * txflows, "tsn sr tx flows mutex");
   4262         if (NULL == bkinfo->flows_tx_mutex) {
   4263             LOG_ERROR(BSL_LS_BCM_TSN,
   4264                       (BSL_META(
   4265                           "TSN SR: failed to allocate TX flow mutexes\n")));
   4266             (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit);
   4267             return BCM_E_MEMORY;
   4268         }
   4269         for (i = 0; i < txflows; i++) {
   4270             bkinfo->flows_tx_mutex[i] = sal_mutex_create("tsn sr flow mutex");
   4271             if (NULL == bkinfo->flows_tx_mutex[i]) {
   4272                 LOG_ERROR(BSL_LS_BCM_TSN,
   4273                           (BSL_META("TSN SR: failed to create flow mutex\n")));
   4274                 (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit);
   4275                 return BCM_E_MEMORY;
   4276             }
   4277         }
   4278     }
   4279 
   4280     /* Create mutex for protecting flow management (allocate/free) */
   4281     bkinfo->fmgmt_mutex = sal_mutex_create("tsn sr flow mgmt");
   4282     if (NULL == bkinfo->fmgmt_mutex) {
   4283         LOG_ERROR(BSL_LS_BCM_TSN,
   4284                   (BSL_META("TSN SR: failed to create flow mgmt mutex\n")));
   4285         (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit);
   4286         return BCM_E_MEMORY;
   4287     }
   4288 
   4289     return BCM_E_NONE;
   4290 }
   4291 
   4292  /*
   4293  * Function:
   4294  *   bcmi_esw_tsn_sr_auto_learn_config_dump
   4295  * Purpose:
   4296  *   dump content of bcm_tsn_sr_auto_learn_config_t
   4297  * Parameters:
   4298  *   unit   - (IN) Unit number
   4299  *   prefix - (IN) Character string to prefix output lines
   4300  *   config - (IN) Auto Learn configuration
   4301  * Returns:
   4302  *   none
   4303  */
   4304 STATIC void
   4305 bcmi_esw_tsn_sr_auto_learn_config_dump(
   4306     int unit,
   4307     char *prefix,
   4308     bcm_tsn_sr_auto_learn_config_t *config)
   4309 {
   4310     TSN_FUNCTION_TRACE(unit, "IN");
   4311 
   4312     /* Parameter NULL error handling */
   4313     if ((NULL == prefix) || (NULL == config)) {
   4314         return;
   4315     }
   4316 
   4317     if (bsl_check(bslLayerBcm, bslSourceTsn, bslSeverityDebug, unit)) {
   4318         LOG_DEBUG(BSL_LS_BCM_TSN,
   4319                   (BSL_META_U(unit,
   4320                               "bcm_tsn_sr_auto_learn_config_t:\n")));
   4321         /* num_tx_flows & num_rx_flows */
   4322         LOG_DEBUG(BSL_LS_BCM_TSN,
   4323                   (BSL_META_U(unit,
   4324                               "%s num_tx_flows %d num_rx_flows %d.\n"),
   4325                               prefix,
   4326                               config->num_tx_flows,
   4327                               config->num_rx_flows));
   4328 
   4329         /* tx_flow_config */
   4330         LOG_DEBUG(BSL_LS_BCM_TSN,
   4331                   (BSL_META_U(unit,
   4332                               "%s tx_flow_config:"
   4333                               "flags 0x%x, seq_num %d, "
   4334                               "ingress_mtu_profile %d.\n"),
   4335                               prefix,
   4336                               config->tx_flow_config.flags,
   4337                               config->tx_flow_config.seq_num,
   4338                               config->tx_flow_config.ingress_mtu_profile));
   4339         /* rx_flow_config */
   4340         LOG_DEBUG(BSL_LS_BCM_TSN,
   4341                   (BSL_META_U(unit,
   4342                               "%s rx_flow_config:"
   4343                               "flags 0x%x, seqnum_accept_win_size %d, "
   4344                               "seqnum_history_win_size %d, age_timeout %d, "
   4345                               "ingress_mtu_profile %d\n"),
   4346                               prefix,
   4347                               config->rx_flow_config.flags,
   4348                               config->rx_flow_config.seqnum_accept_win_size,
   4349                               config->rx_flow_config.seqnum_history_win_size,
   4350                               config->rx_flow_config.age_timeout,
   4351                               config->rx_flow_config.ingress_mtu_profile));
   4352     }
   4353 
   4354     TSN_FUNCTION_TRACE(unit, "OUT");
   4355 }
   4356 
   4357 /*
   4358  * Function:
   4359  *   bcmi_esw_tsn_sr_auto_learn_group_config_dump
   4360  * Purpose:
   4361  *   dump content of bcm_tsn_sr_auto_learn_group_config_t
   4362  * Parameters:
   4363  *   unit   - (IN) Unit number
   4364  *   prefix - (IN) Character string to prefix output lines
   4365  *   config - (IN) Auto Learn Group configuration
   4366  * Returns:
   4367  *   none
   4368  */
   4369 STATIC void
   4370 bcmi_esw_tsn_sr_auto_learn_group_config_dump(
   4371     int unit,
   4372     char *prefix,
   4373     bcm_tsn_sr_auto_learn_group_config_t *config)
   4374 {
   4375     bcm_port_t port;
   4376 
   4377     TSN_FUNCTION_TRACE(unit, "IN");
   4378 
   4379     /* Parameter NULL error handling */
   4380     if ((NULL == prefix) || (NULL == config)) {
   4381         assert((prefix) && (config));
   4382         return;
   4383     }
   4384 
   4385     if (bsl_check(bslLayerBcm, bslSourceTsn, bslSeverityDebug, unit)) {
   4386         LOG_DEBUG(BSL_LS_BCM_TSN,
   4387                   (BSL_META_U(unit,
   4388                               "bcm_tsn_sr_auto_learn_group_config_t:\n")));
   4389 
   4390         /* flags */
   4391         LOG_DEBUG(BSL_LS_BCM_TSN,
   4392                   (BSL_META_U(unit,
   4393                               "%s flags 0x%x\n"),
   4394                               prefix,
   4395                               config->flags));
   4396 
   4397         /* interlink_ports */
   4398         LOG_DEBUG(BSL_LS_BCM_TSN,
   4399                   (BSL_META_U(unit,
   4400                              "%s interlink_ports:"),
   4401                              prefix));
   4402 
   4403         PBMP_ITER(config->interlink_ports, port) {
   4404             LOG_DEBUG(BSL_LS_BCM_TSN,
   4405                       (BSL_META_U(unit,
   4406                                   "%2d "), port));
   4407         }
   4408 
   4409         LOG_DEBUG(BSL_LS_BCM_TSN,
   4410                   (BSL_META_U(unit, "\n")));
   4411 
   4412         /* redundant_ports */
   4413         LOG_DEBUG(BSL_LS_BCM_TSN,
   4414                   (BSL_META_U(unit,
   4415                               "%s redundant_ports:"),
   4416                               prefix));
   4417 
   4418         PBMP_ITER(config->redundant_ports, port) {
   4419             LOG_DEBUG(BSL_LS_BCM_TSN,
   4420                       (BSL_META_U(unit,
   4421                                   "%2d "), port));
   4422 
   4423         }
   4424 
   4425         LOG_DEBUG(BSL_LS_BCM_TSN,
   4426                   (BSL_META_U(unit, "\n")));
   4427     }
   4428     TSN_FUNCTION_TRACE(unit, "OUT");
   4429 }
   4430 
   4431 /*
   4432  * Function:
   4433  *   bcmi_esw_tsn_sr_auto_learn_group_config_cmp
   4434  * Purpose:
   4435  *   Check the Auto Learn entry is the same or not.
   4436  * Parameters:
   4437  *   unit           - (IN) Unit number
   4438  *   config1        - (IN) Auto Learn Group config
   4439  *   config2        - (IN) Auto Learn Group config
   4440  * Returns:
   4441  *   BCM_E_NONE     - not the same and no overlapped ports found
   4442  *   BCM_E_PARAM    - NULL parameter
   4443  *   BCM_E_EXISTS   - both config are the same
   4444  *   BCM_E_BUSY     - not the same but overlapped ports found
   4445  */
   4446 STATIC int
   4447 bcmi_esw_tsn_sr_auto_learn_group_config_cmp(
   4448     int unit,
   4449     bcm_tsn_sr_auto_learn_group_config_t *config1,
   4450     bcm_tsn_sr_auto_learn_group_config_t *config2)
   4451 {
   4452     int is_the_same = TRUE;
   4453     bcm_pbmp_t tmp_pbmp;
   4454 
   4455     TSN_FUNCTION_TRACE(unit, "IN");
   4456 
   4457     /* Parameter NULL error handling */
   4458     if ((NULL == config1) || (NULL == config2)) {
   4459         assert((config1) && ( config2));
   4460         return BCM_E_PARAM;
   4461     }
   4462 
   4463     /* Check if flags are different */
   4464     if (config1->flags != config2->flags) {
   4465         is_the_same = FALSE;
   4466     }
   4467 
   4468     /* Check if any different found */
   4469     if (BCM_PBMP_NEQ(config1->redundant_ports,
   4470                      config2->redundant_ports)) {
   4471         is_the_same = FALSE;
   4472     }
   4473 
   4474     /* Check if any different found */
   4475     if (BCM_PBMP_NEQ(config1->interlink_ports,
   4476                      config2->interlink_ports)) {
   4477         is_the_same = FALSE;
   4478     }
   4479 
   4480     if (FALSE == is_the_same) {
   4481         BCM_PBMP_ASSIGN(tmp_pbmp, config1->interlink_ports);
   4482         BCM_PBMP_AND(tmp_pbmp, config2->interlink_ports);
   4483         /* Check for overlapped ports found, return BCM_E_BUSY */
   4484         if (BCM_PBMP_NOT_NULL(tmp_pbmp)) {
   4485             return BCM_E_BUSY;
   4486         }
   4487 
   4488         BCM_PBMP_ASSIGN(tmp_pbmp, config1->redundant_ports);
   4489         BCM_PBMP_AND(tmp_pbmp, config2->redundant_ports);
   4490         /* Check for overlapped ports found, return BCM_E_BUSY */
   4491         if (BCM_PBMP_NOT_NULL(tmp_pbmp)) {
   4492             return BCM_E_BUSY;
   4493         }
   4494 
   4495         /* Not the same and no overlapped */
   4496         return BCM_E_NONE;
   4497     }
   4498 
   4499     TSN_FUNCTION_TRACE(unit, "OUT");
   4500     /* Both config are the same, return BCM_E_EXISTS */
   4501     return BCM_E_EXISTS;
   4502 }
   4503 
   4504 /*
   4505  * Function:
   4506  *   bcmi_esw_tsn_sr_auto_learn_group_id_existed_check
   4507  * Purpose:
   4508  *   Check the Auto Learn Group ID exited or not.
   4509  * Parameters:
   4510  *   unit     - (IN) Unit number
   4511  *   group_id - (IN) Group ID
   4512  * Returns:
   4513  *   BCM_E_NONE - Success.
   4514  */
   4515 STATIC int
   4516 bcmi_esw_tsn_sr_auto_learn_group_id_existed_check(
   4517     int unit,
   4518     int group_id)
   4519 {
   4520     bcm_error_t rv = BCM_E_UNAVAIL;
   4521     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   4522     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   4523     const tsn_sr_auto_learn_info_t *al_dev_info = NULL;
   4524     uint32 sw_idx = GROUP_ID_TO_SW_IDX(group_id);
   4525     uint32 table_size;
   4526 
   4527     TSN_FUNCTION_TRACE(unit, "IN");
   4528 
   4529     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   4530 
   4531     /* Initialization check */
   4532     AUTO_LEARN_INIT(unit);
   4533 
   4534     /* auto learn device info */
   4535     dev_info = bk_info->tsn_dev_info;
   4536     al_dev_info = dev_info->tsn_sr_auto_learn_info;
   4537 
   4538     rv = al_dev_info->table_size_get(unit, &table_size);
   4539     BCM_IF_ERROR_RETURN(rv);
   4540     assert(table_size > 0);
   4541 
   4542     /* Check if the map_id and sw_idx is in the reasonable range */
   4543     if (sw_idx >= table_size) {
   4544         return BCM_E_PARAM;
   4545     }
   4546 
   4547     if (AUTO_LEARN_INTF_USED_GET(unit, sw_idx)) {
   4548         return BCM_E_NONE;
   4549     }
   4550     TSN_FUNCTION_TRACE(unit, "OUT");
   4551     return BCM_E_NOT_FOUND;
   4552 }
   4553 
   4554 /*
   4555  * Function:
   4556  *   bcmi_esw_tsn_sr_auto_learn_group_existed_check
   4557  * Purpose:
   4558  *   Check the Auto Learn Group configuration exited or not.
   4559  * Parameters:
   4560  *   unit           - (IN) Unit number
   4561  *   config         - (IN) Current Group ID
   4562  *   config         - (IN) Auto Learn Group configuration
   4563  *   group_id       - (OUT) Group ID
   4564  * Returns:
   4565  *   BCM_E_NONE     - Success. Not the same and no overlapped ports found
   4566  *   BCM_E_PARAM    - Fail. NULL parameter
   4567  *   BCM_E_EXISTS   - Fail. Both configures are the same
   4568  *   BCM_E_BUSY     - Fail. Not the same but overlapped ports found
   4569  */
   4570 STATIC int
   4571 bcmi_esw_tsn_sr_auto_learn_group_existed_check(
   4572     int unit,
   4573     bcm_tsn_sr_auto_learn_group_config_t *config,
   4574     int current_group_id,
   4575     int *group_id)
   4576 {
   4577     bcm_error_t rv = BCM_E_UNAVAIL;
   4578     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   4579     bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL;
   4580     bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *bk_group_data;
   4581     bcm_tsn_sr_auto_learn_group_config_t *bk_config;
   4582     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   4583     const tsn_sr_auto_learn_info_t *al_dev_info = NULL;
   4584     uint32 sw_idx;
   4585     uint32 table_size;
   4586 
   4587     TSN_FUNCTION_TRACE(unit, "IN");
   4588 
   4589     /* Parameter NULL error handling */
   4590     if ((NULL == config) || (NULL == group_id)) {
   4591         return BCM_E_PARAM;
   4592     }
   4593 
   4594     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   4595 
   4596     /* Initialization check */
   4597     AUTO_LEARN_INIT(unit);
   4598 
   4599     /* auto learn bk info */
   4600     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   4601 
   4602     /* auto learn device info */
   4603     dev_info = bk_info->tsn_dev_info;
   4604     al_dev_info = dev_info->tsn_sr_auto_learn_info;
   4605 
   4606     rv = al_dev_info->table_size_get(unit, &table_size);
   4607     BCM_IF_ERROR_RETURN(rv);
   4608     assert(table_size > 0);
   4609     assert(table_size > al_bk_info->valid_sw_idx_end);
   4610 
   4611     AUTO_LEARN_BK_LOCK(unit);
   4612 
   4613     /* Check if there is any the same configure in bk */
   4614     for (sw_idx = (al_bk_info->valid_sw_idx_start);
   4615          sw_idx <= (al_bk_info->valid_sw_idx_end);
   4616          sw_idx++) {
   4617 
   4618         /* Not used, continue to check next one */
   4619         if (AUTO_LEARN_INTF_USED_GET(unit, sw_idx) == 0) {
   4620             continue;
   4621         }
   4622 
   4623         bk_group_data = &(al_bk_info->group_data[sw_idx]);
   4624         bk_config = &(bk_group_data->config);
   4625 
   4626         /* Compare if two configures are the same */
   4627         rv = bcmi_esw_tsn_sr_auto_learn_group_config_cmp(
   4628                 unit, bk_config, config);
   4629         if (BCM_SUCCESS(rv)) {
   4630             /* Not the same and no overlapped port found */
   4631             continue;
   4632         } else if (BCM_E_EXISTS == rv) {
   4633             /* The same configure found */
   4634             *group_id = bk_group_data->group_id;
   4635             AUTO_LEARN_BK_UNLOCK(unit);
   4636             return rv;
   4637         } else if (BCM_FAILURE(rv)) {
   4638             /* Overlapped ports found and Error handle for other */
   4639 
   4640             /* Change the config via set function, skip check itself */
   4641             if (current_group_id == bk_group_data->group_id) {
   4642                 continue;
   4643             }
   4644             AUTO_LEARN_BK_UNLOCK(unit);
   4645             return rv;
   4646         }
   4647     }
   4648     AUTO_LEARN_BK_UNLOCK(unit);
   4649 
   4650     TSN_FUNCTION_TRACE(unit, "OUT");
   4651     return BCM_E_NONE;
   4652 }
   4653 
   4654 
   4655 /*
   4656  * Function:
   4657  *   bcmi_esw_tsn_sr_auto_learn_get_empty_group_id
   4658  * Purpose:
   4659  *   Get a empty group_id
   4660  * Parameters:
   4661  *   unit       - (IN) Unit number
   4662  *   group_id   - (OUT) Group ID
   4663  * Returns:
   4664  *   BCM_E_NONE - Success. Find a empty groud_id successfully
   4665  */
   4666 STATIC int
   4667 bcmi_esw_tsn_sr_auto_learn_get_empty_group_id(
   4668     int unit,
   4669     int *group_id)
   4670 {
   4671     bcm_error_t rv = BCM_E_UNAVAIL;
   4672     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   4673     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   4674     const tsn_sr_auto_learn_info_t *al_dev_info = NULL;
   4675     bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL;
   4676     uint32 empty_sw_idx;
   4677     uint32 table_size;
   4678 
   4679     TSN_FUNCTION_TRACE(unit, "IN");
   4680 
   4681     /* Parameter NULL error handling */
   4682     if (NULL == group_id) {
   4683         return BCM_E_PARAM;
   4684     }
   4685 
   4686     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   4687 
   4688     /* Initialization check */
   4689     AUTO_LEARN_INIT(unit);
   4690 
   4691     /* auto learn bk info */
   4692     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   4693 
   4694     /* auto learn device info */
   4695     dev_info = bk_info->tsn_dev_info;
   4696     al_dev_info = dev_info->tsn_sr_auto_learn_info;
   4697 
   4698     rv = al_dev_info->table_size_get(unit, &table_size);
   4699     BCM_IF_ERROR_RETURN(rv);
   4700     assert(table_size > 0);
   4701 
   4702     /* Full check */
   4703     if (al_bk_info->valid_count == table_size) {
   4704         return BCM_E_NOT_FOUND;
   4705     }
   4706 
   4707     /* Check if it's in the reasonable range */
   4708     if (al_bk_info->empty_sw_idx_end >= table_size) {
   4709         return BCM_E_INTERNAL;
   4710     }
   4711 
   4712     AUTO_LEARN_BK_LOCK(unit);
   4713 
   4714     /* Find an empty id */
   4715     for (empty_sw_idx = al_bk_info->empty_sw_idx_start;
   4716          empty_sw_idx <= al_bk_info->empty_sw_idx_end;
   4717          empty_sw_idx++) {
   4718 
   4719         if (AUTO_LEARN_INTF_USED_GET(unit, empty_sw_idx) == 0) {
   4720             /* Set bit map as used */
   4721             AUTO_LEARN_INTF_USED_SET(unit, empty_sw_idx);
   4722 
   4723             /* Update valid start and end */
   4724             if (al_bk_info->valid_count == 0) {
   4725                 al_bk_info->valid_sw_idx_start = empty_sw_idx;
   4726                 al_bk_info->valid_sw_idx_end = empty_sw_idx;
   4727             } else if (empty_sw_idx < al_bk_info->valid_sw_idx_start) {
   4728                 al_bk_info->valid_sw_idx_start = empty_sw_idx;
   4729             } else if (empty_sw_idx > al_bk_info->valid_sw_idx_end) {
   4730                 al_bk_info->valid_sw_idx_end = empty_sw_idx;
   4731             }
   4732 
   4733             al_bk_info->valid_count++;
   4734             *group_id = SW_IDX_TO_GROUP_ID(empty_sw_idx);
   4735 
   4736             /* Update the empty start, assume next one is real empty */
   4737             al_bk_info->empty_sw_idx_start = empty_sw_idx + 1;
   4738             AUTO_LEARN_BK_UNLOCK(unit);
   4739             return BCM_E_NONE;
   4740         }
   4741         else {
   4742 
   4743             /* Update the empty start, assume next one is real empty */
   4744             al_bk_info->empty_sw_idx_start = empty_sw_idx + 1;
   4745         }
   4746     }
   4747     AUTO_LEARN_BK_UNLOCK(unit);
   4748     TSN_FUNCTION_TRACE(unit, "OUT");
   4749     return BCM_E_NOT_FOUND;
   4750 }
   4751 
   4752 /*
   4753  * Function:
   4754  *   bcmi_esw_tsn_sr_auto_learn_destroy_group_id
   4755  * Purpose:
   4756  *   Free the resource of group_id
   4757  * Parameters:
   4758  *   unit       - (IN) Unit number
   4759  *   group_id   - (IN) Group ID
   4760  * Returns:
   4761  *   BCM_E_NONE - Success. delete groud_id successfully
   4762  */
   4763 STATIC int
   4764 bcmi_esw_tsn_sr_auto_learn_destroy_group_id(
   4765     int unit,
   4766     int group_id)
   4767 {
   4768     bcm_error_t rv = BCM_E_UNAVAIL;
   4769     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   4770     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   4771     const tsn_sr_auto_learn_info_t *al_dev_info = NULL;
   4772     bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL;
   4773     uint32 destroy_sw_idx = GROUP_ID_TO_SW_IDX(group_id);
   4774     uint32 next_valid_sw_idx;
   4775     uint32 table_size;
   4776 
   4777     TSN_FUNCTION_TRACE(unit, "IN");
   4778 
   4779     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   4780 
   4781     /* Initialization check */
   4782     AUTO_LEARN_INIT(unit);
   4783 
   4784     /* auto learn bk info */
   4785     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   4786 
   4787     /* auto learn device info */
   4788     dev_info = bk_info->tsn_dev_info;
   4789     al_dev_info = dev_info->tsn_sr_auto_learn_info;
   4790 
   4791     rv = al_dev_info->table_size_get(unit, &table_size);
   4792     BCM_IF_ERROR_RETURN(rv);
   4793     assert(table_size > 0);
   4794 
   4795     /* Check if it's in the reasonable range */
   4796     if (destroy_sw_idx >= table_size) {
   4797         return BCM_E_INTERNAL;
   4798     }
   4799     AUTO_LEARN_BK_LOCK(unit);
   4800 
   4801     /* Destroy bitmap */
   4802     AUTO_LEARN_INTF_USED_CLR(unit, destroy_sw_idx);
   4803 
   4804     /* Update empty start and end */
   4805     if (destroy_sw_idx < (al_bk_info->empty_sw_idx_start)) {
   4806         al_bk_info->empty_sw_idx_start = destroy_sw_idx;
   4807     } else if (destroy_sw_idx > (al_bk_info->empty_sw_idx_end)) {
   4808         al_bk_info->empty_sw_idx_end = destroy_sw_idx;
   4809     }
   4810 
   4811     /* Update valid, find a next valid start or next valid end */
   4812     next_valid_sw_idx = destroy_sw_idx;
   4813     if ((al_bk_info->valid_count) > 1) {
   4814         if (next_valid_sw_idx == (al_bk_info->valid_sw_idx_start)) {
   4815             do {
   4816                 next_valid_sw_idx++;
   4817                 if (next_valid_sw_idx == table_size - 1) {
   4818                     /* table_size -1 is the last one */
   4819                     break;
   4820                 }
   4821             } while (AUTO_LEARN_INTF_USED_GET(unit, next_valid_sw_idx) == 0);
   4822             al_bk_info->valid_sw_idx_start = next_valid_sw_idx;
   4823         } else if (next_valid_sw_idx == (al_bk_info->valid_sw_idx_end)) {
   4824             do {
   4825                 next_valid_sw_idx--;
   4826                 if (next_valid_sw_idx == 0) {
   4827                     /* 0 is the first one */
   4828                     break;
   4829                 }
   4830             } while (AUTO_LEARN_INTF_USED_GET(unit, next_valid_sw_idx) == 0);
   4831             al_bk_info->valid_sw_idx_end = next_valid_sw_idx;
   4832         }
   4833     }
   4834 
   4835     if (0 < al_bk_info->valid_count) {
   4836         al_bk_info->valid_count--;
   4837     }
   4838 
   4839     if (0 == al_bk_info->valid_count) {
   4840         al_bk_info->valid_sw_idx_start = 0;
   4841         al_bk_info->valid_sw_idx_end = 0;
   4842         al_bk_info->empty_sw_idx_start = 0;
   4843         al_bk_info->empty_sw_idx_end = table_size - 1;
   4844     }
   4845     AUTO_LEARN_BK_UNLOCK(unit);
   4846 
   4847     TSN_FUNCTION_TRACE(unit, "OUT");
   4848     return BCM_E_NONE;
   4849 }
   4850 
   4851 /*
   4852  * Function:
   4853  *   bcmi_esw_tsn_sr_auto_learn_create_sr_multicast
   4854  * Purpose:
   4855  *   Create Multicast group for SR ports
   4856  * Parameters:
   4857  *   unit       - (IN) Unit
   4858  *   port_pbmp  - (IN) port bitmap
   4859  *   mcg_idx    - (OUT) multicast group index
   4860  * Returns:
   4861  *   BCM_E_NONE - Success.
   4862  */
   4863 STATIC int
   4864 bcmi_esw_tsn_sr_auto_learn_create_sr_multicast(
   4865     int unit,
   4866     bcm_pbmp_t port_pbmp,
   4867     int *mcg_idx)
   4868 {
   4869     bcm_error_t rv = BCM_E_UNAVAIL;
   4870     bcm_if_t encap_id;
   4871     bcm_port_t port;
   4872     bcm_gport_t gport;
   4873     bcm_vlan_t vid = BCM_VLAN_INVALID;
   4874     bcm_multicast_t mc_group;
   4875 
   4876     TSN_FUNCTION_TRACE(unit, "IN");
   4877 
   4878     /* Parameter NULL error handling */
   4879     if (NULL == mcg_idx) {
   4880         return BCM_E_PARAM;
   4881     }
   4882 
   4883     /* Initialization check */
   4884     AUTO_LEARN_INIT(unit);
   4885 
   4886     rv = bcm_esw_multicast_create(unit, BCM_MULTICAST_TYPE_L2, &mc_group);
   4887     if (BCM_FAILURE(rv)) {
   4888         LOG_ERROR(BSL_LS_BCM_TSN,
   4889                   (BSL_META_U(unit,
   4890                               "bcm_multicast_create failed(rv = %d)\n"),
   4891                               rv));
   4892         return rv;
   4893     }
   4894 
   4895     PBMP_ITER(port_pbmp, port) {
   4896         LOG_DEBUG(BSL_LS_BCM_TSN,
   4897                   (BSL_META_U(unit,
   4898                               "port: %d, "), port));
   4899         /* convert port to gport */
   4900         BCM_IF_ERROR_RETURN(
   4901             bcm_esw_port_gport_get(unit, port, &gport));
   4902 
   4903         /* Add HSR ports into the multicast group */
   4904         rv = bcm_esw_multicast_l2_encap_get(unit,
   4905                                             mc_group,
   4906                                             gport,
   4907                                             vid,
   4908                                             &encap_id);
   4909         if (BCM_FAILURE(rv)) {
   4910             LOG_ERROR(BSL_LS_BCM_TSN,
   4911                       (BSL_META_U(unit,
   4912                                   "bcm_esw_multicast_l2_encap_get"
   4913                                   " failed(rv = %d)\n"),
   4914                                   rv));
   4915             return rv;
   4916         }
   4917 
   4918         rv = bcm_esw_multicast_egress_add(unit,
   4919                                           mc_group,
   4920                                           gport,
   4921                                           encap_id);
   4922         if (BCM_FAILURE(rv)) {
   4923             LOG_ERROR(BSL_LS_BCM_TSN,
   4924                       (BSL_META_U(unit,
   4925                                   "bcm_esw_multicast_egress_add"
   4926                                   " failed(rv = %d)\n"),
   4927                                   rv));
   4928             return rv;
   4929         }
   4930 
   4931         LOG_DEBUG(BSL_LS_BCM_TSN,
   4932                   (BSL_META_U(unit,
   4933                               "mc_group(%d), port(%2d), "
   4934                               "vlan(%d), encap_id(%d)\n"),
   4935                               mc_group,
   4936                               port,
   4937                               vid,
   4938                               encap_id));
   4939     }
   4940     *mcg_idx = _BCM_MULTICAST_ID_GET(mc_group);
   4941 
   4942     TSN_FUNCTION_TRACE(unit, "OUT");
   4943     return BCM_E_NONE;
   4944 }
   4945 
   4946 /*
   4947  * Function:
   4948  *   bcmi_esw_tsn_sr_auto_learn_delete_sr_multicast
   4949  * Purpose:
   4950  *   Delete Multicast group for SR ports
   4951  * Parameters:
   4952  *   unit       - (IN) Unit being delete.
   4953  *   port_pbmp  - (IN) port bitmap being delete.
   4954  *   mcg_idx   - (IN) multicast group index
   4955  * Returns:
   4956  *   BCM_E_NONE - Success.
   4957  */
   4958 STATIC int
   4959 bcmi_esw_tsn_sr_auto_learn_delete_sr_multicast(
   4960     int unit,
   4961     bcm_pbmp_t port_pbmp,
   4962     int mcg_idx)
   4963 {
   4964     bcm_error_t rv = BCM_E_UNAVAIL;
   4965     bcm_if_t encap_id;
   4966     bcm_port_t port;
   4967     bcm_gport_t gport;
   4968     bcm_vlan_t vid = BCM_VLAN_INVALID;
   4969     bcm_multicast_t mc_group;
   4970 
   4971     TSN_FUNCTION_TRACE(unit, "IN");
   4972 
   4973     _BCM_MULTICAST_GROUP_SET(mc_group, _BCM_MULTICAST_TYPE_L2, mcg_idx);
   4974 
   4975     /* Initialization check */
   4976     AUTO_LEARN_INIT(unit);
   4977 
   4978     PBMP_ITER(port_pbmp, port) {
   4979         /* convert port to gport */
   4980         BCM_IF_ERROR_RETURN(
   4981             bcm_esw_port_gport_get(unit, port, &gport));
   4982 
   4983         /* Add HSR ports into the multicast group */
   4984         rv = bcm_esw_multicast_l2_encap_get(unit,
   4985                                             mc_group,
   4986                                             gport,
   4987                                             vid,
   4988                                             &encap_id);
   4989         if (BCM_FAILURE(rv)) {
   4990             LOG_ERROR(BSL_LS_BCM_TSN,
   4991                       (BSL_META_U(unit,
   4992                                   "bcm_multicast_l2_encap_get"
   4993                                   " failed(rv = %d)\n"),
   4994                                   rv));
   4995             return rv;
   4996         }
   4997 
   4998         rv = bcm_esw_multicast_egress_delete(unit,
   4999                                              mc_group,
   5000                                              gport,
   5001                                              encap_id);
   5002         if (BCM_FAILURE(rv)) {
   5003             LOG_ERROR(BSL_LS_BCM_TSN,
   5004                       (BSL_META_U(unit,
   5005                                   "bcm_esw_multicast_egress_delete"
   5006                                   " failed(rv = %d)\n"),
   5007                                   rv));
   5008             return rv;
   5009         }
   5010 
   5011         LOG_DEBUG(BSL_LS_BCM_TSN,
   5012                   (BSL_META_U(unit,
   5013                               "mc_group(%d), port(%2d), "
   5014                               "vlan(%d), encap_id(%d)"),
   5015                               mc_group,
   5016                               port,
   5017                               vid,
   5018                               encap_id));
   5019     }
   5020 
   5021     rv = bcm_esw_multicast_destroy(unit, mc_group);
   5022     if (BCM_FAILURE(rv)) {
   5023         LOG_ERROR(BSL_LS_BCM_TSN,
   5024                   (BSL_META_U(unit,
   5025                               "bcm_esw_multicast_destroy"
   5026                               " mc_group(%d), failed(rv = %d)\n"),
   5027                               mc_group,
   5028                               rv));
   5029         return rv;
   5030     }
   5031     TSN_FUNCTION_TRACE(unit, "OUT");
   5032     return BCM_E_NONE;
   5033 }
   5034 
   5035 /*
   5036  * Function:
   5037  *   bcmi_esw_tsn_sr_auto_learn_hw_delete_all
   5038  * Purpose:
   5039  *   Delete all HW resource. Back to default status.
   5040  * Parameters:
   5041  *   unit       - (IN) Unit being delete.
   5042  * Returns:
   5043  *   BCM_E_NONE - Success.
   5044  */
   5045 STATIC int
   5046 bcmi_esw_tsn_sr_auto_learn_hw_delete_all(int unit)
   5047 {
   5048     bcm_error_t rv = BCM_E_UNAVAIL;
   5049     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   5050     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   5051     const tsn_sr_auto_learn_info_t *al_dev_info = NULL;
   5052 
   5053     TSN_FUNCTION_TRACE(unit, "IN");
   5054 
   5055     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   5056 
   5057     /* Initialization check */
   5058     AUTO_LEARN_INIT(unit);
   5059 
   5060     /* auto learn device info */
   5061     dev_info = bk_info->tsn_dev_info;
   5062     al_dev_info = dev_info->tsn_sr_auto_learn_info;
   5063 
   5064     /* Check if the chip specific function existed */
   5065     TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->group_port_reset_all);
   5066 
   5067     /* Reset all ports */
   5068     rv = al_dev_info->group_port_reset_all(unit);
   5069     BCM_IF_ERROR_RETURN(rv);
   5070     TSN_FUNCTION_TRACE(unit, "OUT");
   5071     return BCM_E_NONE;
   5072 }
   5073 
   5074 STATIC int bcmi_esw_tsn_sr_auto_learn_lazy_init(int unit);
   5075 STATIC int bcmi_esw_tsn_sr_auto_learn_cleanup(int unit);
   5076 
   5077 /* free the allocate group_id/l2mc entry & mac proxy entry */
   5078 STATIC int
   5079 bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx(
   5080     int unit,
   5081     int *group_id,
   5082     int i_pro_idx,
   5083     int r_pro_idx[bcmi_sr_auto_learn_group_count],
   5084     bcm_tsn_sr_auto_learn_group_config_t *config)
   5085 {
   5086     bcm_error_t rv = BCM_E_NONE;
   5087 
   5088     /* Parameter NULL error handling */
   5089     if (NULL == config) {
   5090         return BCM_E_PARAM;
   5091     }
   5092     if (NULL != group_id) {
   5093         /* Need to free the empty group_id from above */
   5094         bcmi_esw_tsn_sr_auto_learn_destroy_group_id(unit, *group_id);
   5095     }
   5096 
   5097     if (BCM_PBMP_NOT_NULL(config->redundant_ports)) {
   5098         if (BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID !=
   5099             r_pro_idx[bcmi_sr_auto_learn_group_l2mc]) {
   5100             rv = bcmi_esw_tsn_sr_auto_learn_delete_sr_multicast(
   5101                     unit,
   5102                     config->redundant_ports,
   5103                     r_pro_idx[bcmi_sr_auto_learn_group_l2mc]);
   5104             if (BCM_FAILURE(rv)) {
   5105                 LOG_ERROR(BSL_LS_BCM_TSN,
   5106                           (BSL_META_U(unit,
   5107                                       "L2MC delete failed(rv = %d)\n"),
   5108                                       rv));
   5109                 return rv;
   5110             }
   5111         }
   5112         if (BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID !=
   5113             r_pro_idx[bcmi_sr_auto_learn_group_macp]) {
   5114             rv = bcmi_esw_tsn_sr_mac_proxy_delete(
   5115                     unit,
   5116                     r_pro_idx[bcmi_sr_auto_learn_group_macp]);
   5117             if (BCM_FAILURE(rv)) {
   5118                 LOG_ERROR(BSL_LS_BCM_TSN,
   5119                           (BSL_META_U(unit,
   5120                                       "sr mac proxy profile delete failed"
   5121                                       "(rv = %d)\n"),
   5122                                       rv));
   5123                 return rv;
   5124             }
   5125         }
   5126     }
   5127 
   5128     if (BCM_PBMP_NOT_NULL(config->interlink_ports)) {
   5129         if (BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID !=
   5130             i_pro_idx) {
   5131             rv = bcmi_esw_tsn_sr_mac_proxy_delete(
   5132                     unit,
   5133                     i_pro_idx);
   5134             if (BCM_FAILURE(rv)) {
   5135                 LOG_ERROR(BSL_LS_BCM_TSN,
   5136                           (BSL_META_U(unit,
   5137                                       "sr mac proxy profile delete failed"
   5138                                       "(rv = %d)\n"),
   5139                                       rv));
   5140                 return rv;
   5141             }
   5142         }
   5143     }
   5144     return rv;
   5145 }
   5146 
   5147 /*
   5148  * Function:
   5149  *   bcmi_esw_tsn_sr_auto_learn_group_create
   5150  * Purpose:
   5151  *   Add an Auto Learn config to hardware.
   5152  * Parameters:
   5153  *   unit       - (IN) Unit number
   5154  *   config     - (IN) Auto Learn Group configuration
   5155  *   group_id   - (OUT) Group ID
   5156  * Returns:
   5157  *   BCM_E_xxx
   5158  */
   5159 STATIC int
   5160 bcmi_esw_tsn_sr_auto_learn_group_create(
   5161     int unit,
   5162     bcm_tsn_sr_auto_learn_group_config_t *config,
   5163     int *group_id)
   5164 {
   5165     bcm_error_t rv = BCM_E_UNAVAIL;
   5166 #if defined(BCM_TSN_SR_SUPPORT)
   5167     uint32 sw_idx;
   5168     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   5169     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   5170     const tsn_sr_auto_learn_info_t *al_dev_info = NULL;
   5171     bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL;
   5172     bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *bk_group_data;
   5173     bcm_tsn_sr_auto_learn_group_config_t *bk_config;
   5174     int pro_idx = BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID;
   5175     bcmi_tsn_sr_auto_learn_group_port_type_t group_ports_type;
   5176     bcm_pbmp_t group_ports_pbmp;
   5177     int new_i_pro_idx = BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID;
   5178     int new_r_pro_idx[bcmi_sr_auto_learn_group_count] =
   5179         { BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID,
   5180           BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID};
   5181 
   5182     TSN_FUNCTION_TRACE(unit, "IN");
   5183 
   5184     /* Parameter NULL error handling */
   5185     if ((NULL == config) || (NULL == group_id) ||
   5186         ((BCM_PBMP_IS_NULL(config->redundant_ports)) &&
   5187          (BCM_PBMP_IS_NULL(config->interlink_ports))) ||
   5188         ((0 != config->flags) &&
   5189          ((~BCMI_TSN_SR_AUTO_LEARN_GROUP_VALID_FLAGS) & config->flags))) {
   5190         return BCM_E_PARAM;
   5191     }
   5192 
   5193     bcmi_esw_tsn_sr_auto_learn_group_config_dump(
   5194         unit, "auto_learn_group_create", config);
   5195 
   5196     /* SR Auto Learn management initialization */
   5197     rv = bcmi_esw_tsn_sr_auto_learn_lazy_init(unit);
   5198     if (BCM_FAILURE(rv)) {
   5199         bcmi_esw_tsn_sr_auto_learn_cleanup(unit);
   5200         return (rv);
   5201     }
   5202 
   5203     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   5204     /* auto learn bk info */
   5205     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   5206 
   5207     /* Initialization check */
   5208     AUTO_LEARN_INIT(unit);
   5209 
   5210     /* auto learn bk info */
   5211     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   5212 
   5213     /* auto learn device info */
   5214     dev_info = bk_info->tsn_dev_info;
   5215     al_dev_info = dev_info->tsn_sr_auto_learn_info;
   5216 
   5217     /* Check if the chip specific function existed */
   5218     TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->group_port_set);
   5219 
   5220     AUTO_LEARN_LOCK(unit);
   5221 
   5222     /* Check if the same configure and overlapped ports existed */
   5223     rv = bcmi_esw_tsn_sr_auto_learn_group_existed_check(unit,
   5224             config, BCMI_SR_AUTO_LEARN_GROUP_ID_INVALID, group_id);
   5225     if (BCM_E_EXISTS == rv) {
   5226         /* config is the same as config of existing group_id */
   5227         AUTO_LEARN_UNLOCK(unit);
   5228         LOG_WARN(BSL_LS_BCM_TSN,
   5229                  (BSL_META_U(unit,
   5230                              "config already existed, found group_id(%d)\n"),
   5231                              *group_id));
   5232         return BCM_E_EXISTS;
   5233     } else if (BCM_E_BUSY == rv) {
   5234         /* config is found on other group_id (overlapper ports) */
   5235         AUTO_LEARN_UNLOCK(unit);
   5236         LOG_WARN(BSL_LS_BCM_TSN,
   5237                  (BSL_META_U(unit,
   5238                              "find existed auto learn group failed"
   5239                              "(rv = %d)\n"),
   5240                              rv));
   5241         return rv;
   5242     } else if (BCM_FAILURE(rv)) {
   5243         AUTO_LEARN_UNLOCK(unit);
   5244         return rv;
   5245     }
   5246 
   5247     /* Get a SW empty group_id */
   5248     rv = bcmi_esw_tsn_sr_auto_learn_get_empty_group_id(unit, group_id);
   5249     if (BCM_FAILURE(rv)) {
   5250         AUTO_LEARN_UNLOCK(unit);
   5251         LOG_ERROR(BSL_LS_BCM_TSN,
   5252                   (BSL_META_U(unit,
   5253                               "no empty group_id(rv = %d)\n"),
   5254                               rv));
   5255         return rv;
   5256     }
   5257 
   5258     /* Set SW bookkeeping database pointers */
   5259     sw_idx = GROUP_ID_TO_SW_IDX(*group_id);
   5260     bk_group_data = &(al_bk_info->group_data[sw_idx]);
   5261     bk_config = &(bk_group_data->config);
   5262 
   5263     /* Check if overlapped */
   5264     BCM_PBMP_ASSIGN(group_ports_pbmp, config->redundant_ports);
   5265     BCM_PBMP_AND(group_ports_pbmp, config->interlink_ports);
   5266     if (BCM_PBMP_NOT_NULL(group_ports_pbmp)) {
   5267         (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx(
   5268                 unit, group_id, new_i_pro_idx, new_r_pro_idx, config);
   5269         return BCM_E_PARAM;
   5270     }
   5271     /*
   5272      * Create auto learn group for redundant and interlink
   5273      * 1. auto learn group bitmap with redundant ports
   5274      * 2. auto learn group proxy bitmap with interlink & redundant ports
   5275      */
   5276 
   5277     /* redundant ports */
   5278     if (BCM_PBMP_NOT_NULL(config->redundant_ports)) {
   5279         /* L2MC */
   5280         group_ports_type = bcmi_sr_auto_learn_group_l2mc;
   5281         BCM_PBMP_ASSIGN(group_ports_pbmp, config->redundant_ports);
   5282 
   5283         /* Set new auto learn group (config) */
   5284         rv = bcmi_esw_tsn_sr_auto_learn_create_sr_multicast(
   5285                 unit, group_ports_pbmp, &pro_idx);
   5286 
   5287         if (BCM_FAILURE(rv)) {
   5288             (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx(
   5289                     unit, group_id, new_i_pro_idx, new_r_pro_idx, config);
   5290             AUTO_LEARN_UNLOCK(unit);
   5291             LOG_ERROR(BSL_LS_BCM_TSN,
   5292                       (BSL_META_U(unit,
   5293                                   "L2MC create failed(rv = %d)\n"),
   5294                                   rv));
   5295             return rv;
   5296         }
   5297         new_r_pro_idx[group_ports_type] = pro_idx;
   5298         rv = al_dev_info->group_port_set(unit, group_ports_type,
   5299                             group_ports_pbmp, pro_idx);
   5300 
   5301         if (BCM_FAILURE(rv)) {
   5302             (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx(
   5303                     unit, group_id, new_i_pro_idx, new_r_pro_idx, config);
   5304             AUTO_LEARN_UNLOCK(unit);
   5305             LOG_ERROR(BSL_LS_BCM_TSN,
   5306                       (BSL_META_U(unit,
   5307                                   "write to HW failed(rv = %d)\n"),
   5308                                   rv));
   5309             return rv;
   5310         }
   5311 
   5312 
   5313         /* MAC PROXY */
   5314         group_ports_type = bcmi_sr_auto_learn_group_macp;
   5315 
   5316         /* Set new auto learn group (config) */
   5317         rv = bcmi_esw_tsn_sr_mac_proxy_insert(
   5318                 unit, group_ports_pbmp, &pro_idx);
   5319 
   5320         if (BCM_FAILURE(rv)) {
   5321             (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx(
   5322                     unit, group_id, new_i_pro_idx, new_r_pro_idx, config);
   5323             AUTO_LEARN_UNLOCK(unit);
   5324             LOG_ERROR(BSL_LS_BCM_TSN,
   5325                       (BSL_META_U(unit,
   5326                                   "sr mac proxy profile insert failed"
   5327                                   "(rv = %d)\n"),
   5328                                   rv));
   5329             return rv;
   5330         }
   5331         new_r_pro_idx[group_ports_type] = pro_idx;
   5332         rv = al_dev_info->group_port_set(unit, group_ports_type,
   5333                             group_ports_pbmp, pro_idx);
   5334 
   5335         if (BCM_FAILURE(rv)) {
   5336             (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx(
   5337                     unit, group_id, new_i_pro_idx, new_r_pro_idx, config);
   5338             AUTO_LEARN_UNLOCK(unit);
   5339             LOG_ERROR(BSL_LS_BCM_TSN,
   5340                       (BSL_META_U(unit,
   5341                                   "write to HW failed(rv = %d)\n"),
   5342                                   rv));
   5343             return rv;
   5344         }
   5345 
   5346     }
   5347 
   5348     /* interlink ports */
   5349     if (BCM_PBMP_NOT_NULL(config->interlink_ports)) {
   5350         /* MAC PROXY */
   5351         group_ports_type = bcmi_sr_auto_learn_group_macp;
   5352         BCM_PBMP_ASSIGN(group_ports_pbmp, config->interlink_ports);
   5353 
   5354         /* Set new auto learn group (config) */
   5355         rv = bcmi_esw_tsn_sr_mac_proxy_insert(
   5356                 unit, group_ports_pbmp, &pro_idx);
   5357 
   5358         if (BCM_FAILURE(rv)) {
   5359             (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx(
   5360                     unit, group_id, new_i_pro_idx, new_r_pro_idx, config);
   5361             AUTO_LEARN_UNLOCK(unit);
   5362             LOG_ERROR(BSL_LS_BCM_TSN,
   5363                       (BSL_META_U(unit,
   5364                                   "sr mac proxy profile insert failed"
   5365                                   "(rv = %d)\n"),
   5366                                   rv));
   5367             return rv;
   5368         }
   5369         new_i_pro_idx = pro_idx;
   5370         rv = al_dev_info->group_port_set(unit, group_ports_type,
   5371                             group_ports_pbmp, pro_idx);
   5372 
   5373         if (BCM_FAILURE(rv)) {
   5374             (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx(
   5375                     unit, group_id, new_i_pro_idx, new_r_pro_idx, config);
   5376             AUTO_LEARN_UNLOCK(unit);
   5377             LOG_ERROR(BSL_LS_BCM_TSN,
   5378                       (BSL_META_U(unit,
   5379                                   "write to HW failed(rv = %d)\n"),
   5380                                   rv));
   5381             return rv;
   5382         }
   5383 
   5384     }
   5385 
   5386     /* Update SW bookkeeping database */
   5387     AUTO_LEARN_BK_LOCK(unit);
   5388     bk_group_data->interlink_pro_idx = new_i_pro_idx;
   5389     bk_group_data->redundant_pro_idx[bcmi_sr_auto_learn_group_l2mc] =
   5390         new_r_pro_idx[bcmi_sr_auto_learn_group_l2mc];
   5391     bk_group_data->redundant_pro_idx[bcmi_sr_auto_learn_group_macp] =
   5392         new_r_pro_idx[bcmi_sr_auto_learn_group_macp];
   5393     bk_group_data->group_id = *group_id;
   5394     sal_memcpy(bk_config,
   5395                config,
   5396                sizeof(bcm_tsn_sr_auto_learn_group_config_t));
   5397     AUTO_LEARN_BK_UNLOCK(unit);
   5398 
   5399     AUTO_LEARN_UNLOCK(unit);
   5400 
   5401     rv = BCM_E_NONE;
   5402 #endif /* BCM_TSN_SR_SUPPORT */
   5403     TSN_FUNCTION_TRACE(unit, "OUT");
   5404     return rv;
   5405 }
   5406 
   5407 /*
   5408  * Function:
   5409  *   bcmi_esw_tsn_sr_auto_learn_group_set
   5410  * Purpose:
   5411  *   Set Auto Learn config with the given group_id.
   5412  * Parameters:
   5413  *   unit     - (IN) Unit number
   5414  *   group_id - (IN) Group ID
   5415  *   config   - (IN) Auto Learn Group configuration
   5416  * Returns:
   5417  *   BCM_E_xxx
   5418  */
   5419 STATIC int
   5420 bcmi_esw_tsn_sr_auto_learn_group_set(
   5421     int unit,
   5422     int group_id,
   5423     bcm_tsn_sr_auto_learn_group_config_t *config)
   5424 {
   5425     bcm_error_t rv = BCM_E_UNAVAIL;
   5426 #if defined(BCM_TSN_SR_SUPPORT)
   5427     uint32 sw_idx;
   5428     int exisited_group_id;
   5429     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   5430     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   5431     const tsn_sr_auto_learn_info_t *al_dev_info = NULL;
   5432     bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL;
   5433     bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *bk_group_data;
   5434     bcm_tsn_sr_auto_learn_group_config_t *bk_config;
   5435     int pro_idx = BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID;
   5436     int new_i_pro_idx = BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID;
   5437     int new_r_pro_idx[bcmi_sr_auto_learn_group_count] =
   5438         { BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID,
   5439           BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID};
   5440     bcmi_tsn_sr_auto_learn_group_port_type_t group_ports_type;
   5441     bcm_pbmp_t group_ports_pbmp;
   5442 
   5443     TSN_FUNCTION_TRACE(unit, "IN");
   5444 
   5445     /* Parameter NULL error handling */
   5446     if ((NULL == config) ||
   5447         (BCM_PBMP_IS_NULL(config->redundant_ports)) ||
   5448         (BCM_PBMP_IS_NULL(config->interlink_ports)) ||
   5449         ((0 != config->flags) &&
   5450          ((~BCMI_TSN_SR_AUTO_LEARN_GROUP_VALID_FLAGS) & config->flags))) {
   5451         return BCM_E_PARAM;
   5452     }
   5453 
   5454     bcmi_esw_tsn_sr_auto_learn_group_config_dump(
   5455         unit, "auto_learn_group_set", config);
   5456 
   5457     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   5458 
   5459     /* Initialization check */
   5460     AUTO_LEARN_INIT(unit);
   5461 
   5462     /* auto learn bk info */
   5463     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   5464 
   5465     /* auto learn device info */
   5466     dev_info = bk_info->tsn_dev_info;
   5467     al_dev_info = dev_info->tsn_sr_auto_learn_info;
   5468 
   5469     /* Check if the chip specific function existed */
   5470     TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->group_port_delete);
   5471     TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->group_port_set);
   5472 
   5473     AUTO_LEARN_LOCK(unit);
   5474 
   5475     /* Check if group id existed */
   5476     rv = bcmi_esw_tsn_sr_auto_learn_group_id_existed_check(unit, group_id);
   5477     if (BCM_FAILURE(rv)) {
   5478         AUTO_LEARN_UNLOCK(unit);
   5479         LOG_WARN(BSL_LS_BCM_TSN,
   5480                  (BSL_META_U(unit,
   5481                              "group_id(%d) doesn't exited\n"), group_id));
   5482         return rv;
   5483     }
   5484 
   5485     /* Check if the same configure existed or not */
   5486     rv = bcmi_esw_tsn_sr_auto_learn_group_existed_check(unit,
   5487             config, group_id, &exisited_group_id);
   5488     if (BCM_E_EXISTS == rv) {
   5489         if (exisited_group_id == group_id) {
   5490             /* config is the same as config of current group_id */
   5491             AUTO_LEARN_UNLOCK(unit);
   5492             LOG_WARN(BSL_LS_BCM_TSN,
   5493                      (BSL_META_U(unit,
   5494                                  "config is the same as the config "
   5495                                  "of current group_id(%d)\n"),
   5496                                  group_id));
   5497             /* config are the same, do nothing */
   5498             return BCM_E_NONE;
   5499         } else {
   5500             /* the config is found on other group_id */
   5501             AUTO_LEARN_UNLOCK(unit);
   5502             LOG_WARN(BSL_LS_BCM_TSN,
   5503                      (BSL_META_U(unit,
   5504                                  "config already existed, "
   5505                                  "found group_id(%d)\n"),
   5506                                  exisited_group_id));
   5507             return BCM_E_EXISTS;
   5508         }
   5509     } else if (BCM_E_BUSY == rv) {
   5510         /* config is found on other group_id (overlapper ports) */
   5511         AUTO_LEARN_UNLOCK(unit);
   5512         LOG_WARN(BSL_LS_BCM_TSN,
   5513                  (BSL_META_U(unit,
   5514                              "find existed auto learn group failed"
   5515                              "(rv = %d)\n"),
   5516                              rv));
   5517         return rv;
   5518     } else if (BCM_FAILURE(rv)) {
   5519         AUTO_LEARN_UNLOCK(unit);
   5520         return rv;
   5521     }
   5522 
   5523     /* Check if overlapped */
   5524     BCM_PBMP_ASSIGN(group_ports_pbmp, config->redundant_ports);
   5525     BCM_PBMP_AND(group_ports_pbmp, config->interlink_ports);
   5526     if (BCM_PBMP_NOT_NULL(group_ports_pbmp)) {
   5527         return BCM_E_PARAM;
   5528     }
   5529 
   5530     /* Set SW bookkeeping database pointers */
   5531     sw_idx = GROUP_ID_TO_SW_IDX(group_id);
   5532     bk_group_data = &(al_bk_info->group_data[sw_idx]);
   5533     bk_config = &(bk_group_data->config);
   5534 
   5535     /*
   5536      * Delete bk auto learn group and then set new one
   5537      * 1. auto learn group bitmap with redundant ports
   5538      * 2. auto learn group proxy bitmap with interlink & redundant ports
   5539      */
   5540 
   5541     /* Only add when new config is different from bookkeeping's */
   5542     if (BCM_PBMP_NOT_NULL(bk_config->redundant_ports) &&
   5543         BCM_PBMP_NEQ(bk_config->redundant_ports, config->redundant_ports)) {
   5544         /* Set new auto learn group (config) */
   5545 
   5546         /* L2MC */
   5547         group_ports_type = bcmi_sr_auto_learn_group_l2mc;
   5548         BCM_PBMP_ASSIGN(group_ports_pbmp, config->redundant_ports);
   5549         rv = bcmi_esw_tsn_sr_auto_learn_create_sr_multicast(
   5550                 unit, group_ports_pbmp, &pro_idx);
   5551 
   5552         if (BCM_FAILURE(rv)) {
   5553             AUTO_LEARN_UNLOCK(unit);
   5554             LOG_ERROR(BSL_LS_BCM_TSN,
   5555                       (BSL_META_U(unit,
   5556                                   "L2MC create failed(rv = %d)\n"),
   5557                                   rv));
   5558             return rv;
   5559         }
   5560         new_r_pro_idx[group_ports_type] = pro_idx;
   5561         rv = al_dev_info->group_port_set(unit, group_ports_type,
   5562                             group_ports_pbmp, pro_idx);
   5563 
   5564         if (BCM_FAILURE(rv)) {
   5565             (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx(
   5566                     unit, NULL, new_i_pro_idx, new_r_pro_idx, config);
   5567             AUTO_LEARN_UNLOCK(unit);
   5568             LOG_ERROR(BSL_LS_BCM_TSN,
   5569                       (BSL_META_U(unit,
   5570                                   "write to HW failed(rv = %d)\n"),
   5571                                   rv));
   5572             return rv;
   5573         }
   5574 
   5575 
   5576         /* MAC PROXY */
   5577         group_ports_type = bcmi_sr_auto_learn_group_macp;
   5578 
   5579         /* Set new auto learn group (config) */
   5580         rv = bcmi_esw_tsn_sr_mac_proxy_insert(
   5581                 unit, group_ports_pbmp, &pro_idx);
   5582 
   5583         if (BCM_FAILURE(rv)) {
   5584             (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx(
   5585                     unit, NULL, new_i_pro_idx, new_r_pro_idx, config);
   5586             AUTO_LEARN_UNLOCK(unit);
   5587             LOG_ERROR(BSL_LS_BCM_TSN,
   5588                       (BSL_META_U(unit,
   5589                                   "sr mac proxy profile insert failed"
   5590                                   "(rv = %d)\n"),
   5591                                   rv));
   5592             return rv;
   5593         }
   5594 
   5595         new_r_pro_idx[group_ports_type] = pro_idx;
   5596         rv = al_dev_info->group_port_set(unit, group_ports_type,
   5597                             group_ports_pbmp, pro_idx);
   5598 
   5599         if (BCM_FAILURE(rv)) {
   5600             (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx(
   5601                     unit, NULL, new_i_pro_idx, new_r_pro_idx, config);
   5602             AUTO_LEARN_UNLOCK(unit);
   5603             LOG_ERROR(BSL_LS_BCM_TSN,
   5604                       (BSL_META_U(unit,
   5605                                   "write to HW failed(rv = %d)\n"),
   5606                                   rv));
   5607             return rv;
   5608         }
   5609     }
   5610 
   5611     /* Only add when new config is different from bookkeeping's */
   5612     if (BCM_PBMP_NOT_NULL(bk_config->interlink_ports) &&
   5613         BCM_PBMP_NEQ(bk_config->interlink_ports, config->interlink_ports)) {
   5614         /* MAC PROXY */
   5615         group_ports_type = bcmi_sr_auto_learn_group_macp;
   5616 
   5617         /* Set new auto learn group (config) */
   5618         BCM_PBMP_ASSIGN(group_ports_pbmp, config->interlink_ports);
   5619         rv = bcmi_esw_tsn_sr_mac_proxy_insert(
   5620                 unit, group_ports_pbmp, &pro_idx);
   5621 
   5622         if (BCM_FAILURE(rv)) {
   5623             (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx(
   5624                     unit, NULL, new_i_pro_idx, new_r_pro_idx, config);
   5625             AUTO_LEARN_UNLOCK(unit);
   5626             LOG_ERROR(BSL_LS_BCM_TSN,
   5627                       (BSL_META_U(unit,
   5628                                   "sr mac proxy profile insert failed"
   5629                                   "(rv = %d)\n"),
   5630                                   rv));
   5631             return rv;
   5632         }
   5633         new_i_pro_idx = pro_idx;
   5634         rv = al_dev_info->group_port_set(unit, group_ports_type,
   5635                             group_ports_pbmp, pro_idx);
   5636 
   5637         if (BCM_FAILURE(rv)) {
   5638             (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx(
   5639                     unit, NULL, new_i_pro_idx, new_r_pro_idx, config);
   5640             AUTO_LEARN_UNLOCK(unit);
   5641             LOG_ERROR(BSL_LS_BCM_TSN,
   5642                       (BSL_META_U(unit,
   5643                                   "write to HW failed(rv = %d)\n"),
   5644                                   rv));
   5645             return rv;
   5646         }
   5647     }
   5648 
   5649     /* delete redundant ports */
   5650     if (BCM_PBMP_NOT_NULL(bk_config->redundant_ports) &&
   5651         BCM_PBMP_NEQ(bk_config->redundant_ports, config->redundant_ports)) {
   5652         /* L2MC */
   5653         group_ports_type = bcmi_sr_auto_learn_group_l2mc;
   5654         BCM_PBMP_ASSIGN(group_ports_pbmp, bk_config->redundant_ports);
   5655         if (BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID !=
   5656             bk_group_data->redundant_pro_idx[group_ports_type]) {
   5657 
   5658             rv = bcmi_esw_tsn_sr_auto_learn_delete_sr_multicast(
   5659                     unit, group_ports_pbmp,
   5660                     bk_group_data->redundant_pro_idx[group_ports_type]);
   5661             if (BCM_FAILURE(rv)) {
   5662                 LOG_ERROR(BSL_LS_BCM_TSN,
   5663                           (BSL_META_U(unit,
   5664                                       "L2MC delete failed(rv = %d)\n"),
   5665                                       rv));
   5666             }
   5667         }
   5668         /* Delete HW */
   5669 
   5670         /* should not delete the ports with new created */
   5671         BCM_PBMP_REMOVE(group_ports_pbmp, config->redundant_ports);
   5672         rv = al_dev_info->group_port_delete(unit, group_ports_type,
   5673                             group_ports_pbmp);
   5674 
   5675         if (BCM_FAILURE(rv)) {
   5676             LOG_ERROR(BSL_LS_BCM_TSN,
   5677                       (BSL_META_U(unit,
   5678                                   "write to HW failed(rv = %d)\n"),
   5679                                   rv));
   5680         }
   5681 
   5682         /* MAC PROXY */
   5683         group_ports_type = bcmi_sr_auto_learn_group_macp;
   5684         BCM_PBMP_ASSIGN(group_ports_pbmp, bk_config->redundant_ports);
   5685         if (BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID !=
   5686             bk_group_data->redundant_pro_idx[group_ports_type]) {
   5687             rv = bcmi_esw_tsn_sr_mac_proxy_delete(
   5688                     unit, bk_group_data->redundant_pro_idx[group_ports_type]);
   5689             if (BCM_FAILURE(rv)) {
   5690                 LOG_ERROR(BSL_LS_BCM_TSN,
   5691                           (BSL_META_U(unit,
   5692                                       "sr mac proxy profile delete failed"
   5693                                       "(rv = %d)\n"),
   5694                                       rv));
   5695             }
   5696         }
   5697         /* Delete HW */
   5698 
   5699         /* should not delete the ports overlapped with newly created */
   5700         BCM_PBMP_REMOVE(group_ports_pbmp, config->interlink_ports);
   5701         BCM_PBMP_REMOVE(group_ports_pbmp, config->redundant_ports);
   5702         rv = al_dev_info->group_port_delete(unit, group_ports_type,
   5703                             group_ports_pbmp);
   5704 
   5705         if (BCM_FAILURE(rv)) {
   5706             LOG_ERROR(BSL_LS_BCM_TSN,
   5707                       (BSL_META_U(unit,
   5708                                   "write to HW failed(rv = %d)\n"),
   5709                                   rv));
   5710         }
   5711     }
   5712 
   5713     /* delete interlink ports */
   5714     if (BCM_PBMP_NOT_NULL(bk_config->interlink_ports) &&
   5715         BCM_PBMP_NEQ(bk_config->interlink_ports, config->interlink_ports)) {
   5716 
   5717         /* MAC PROXY */
   5718         group_ports_type = bcmi_sr_auto_learn_group_macp;
   5719         BCM_PBMP_ASSIGN(group_ports_pbmp, bk_config->interlink_ports);
   5720         if (BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID !=
   5721             bk_group_data->redundant_pro_idx[group_ports_type]) {
   5722             rv = bcmi_esw_tsn_sr_mac_proxy_delete(
   5723                     unit, bk_group_data->interlink_pro_idx);
   5724             if (BCM_FAILURE(rv)) {
   5725                 LOG_ERROR(BSL_LS_BCM_TSN,
   5726                           (BSL_META_U(unit,
   5727                                       "sr mac proxy profile delete failed"
   5728                                       "(rv = %d)\n"),
   5729                                       rv));
   5730             }
   5731         }
   5732         /* Delete HW */
   5733 
   5734         /* should not delete the ports overlapped with newly created */
   5735         BCM_PBMP_REMOVE(group_ports_pbmp, config->interlink_ports);
   5736         BCM_PBMP_REMOVE(group_ports_pbmp, config->redundant_ports);
   5737         rv = al_dev_info->group_port_delete(unit, group_ports_type,
   5738                             group_ports_pbmp);
   5739 
   5740         if (BCM_FAILURE(rv)) {
   5741             LOG_ERROR(BSL_LS_BCM_TSN,
   5742                       (BSL_META_U(unit,
   5743                                   "write to HW failed(rv = %d)\n"),
   5744                                   rv));
   5745         }
   5746     }
   5747 
   5748     /* Update SW bookkeeping database */
   5749     AUTO_LEARN_BK_LOCK(unit);
   5750     if (BCM_PBMP_NOT_NULL(bk_config->interlink_ports) &&
   5751         BCM_PBMP_NEQ(bk_config->interlink_ports, config->interlink_ports)) {
   5752         bk_group_data->interlink_pro_idx = new_i_pro_idx;
   5753     }
   5754     if (BCM_PBMP_NOT_NULL(bk_config->redundant_ports) &&
   5755         BCM_PBMP_NEQ(bk_config->redundant_ports, config->redundant_ports)) {
   5756         bk_group_data->redundant_pro_idx[bcmi_sr_auto_learn_group_l2mc] =
   5757             new_r_pro_idx[bcmi_sr_auto_learn_group_l2mc];
   5758         bk_group_data->redundant_pro_idx[bcmi_sr_auto_learn_group_macp] =
   5759             new_r_pro_idx[bcmi_sr_auto_learn_group_macp];
   5760     }
   5761     sal_memcpy(bk_config,
   5762                config,
   5763                sizeof(bcm_tsn_sr_auto_learn_group_config_t));
   5764     AUTO_LEARN_BK_UNLOCK(unit);
   5765     AUTO_LEARN_UNLOCK(unit);
   5766 
   5767     rv = BCM_E_NONE;
   5768 #endif /* BCM_TSN_SR_SUPPORT */
   5769     TSN_FUNCTION_TRACE(unit, "OUT");
   5770     return rv;
   5771 }
   5772 
   5773 /*
   5774  * Function:
   5775  *   bcmi_esw_tsn_sr_auto_learn_group_get
   5776  * Purpose:
   5777  *   Get the Auto Learn config with the given group_id.
   5778  * Parameters:
   5779  *   unit     - (IN) Unit number
   5780  *   group_id - (IN) Group ID
   5781  *   config   - (OUT) Auto Learn Group configuration
   5782  * Returns:
   5783  *   BCM_E_xxx
   5784  */
   5785 STATIC int
   5786 bcmi_esw_tsn_sr_auto_learn_group_get(
   5787     int unit,
   5788     int group_id,
   5789     bcm_tsn_sr_auto_learn_group_config_t *config)
   5790 {
   5791     bcm_error_t rv = BCM_E_UNAVAIL;
   5792 #if defined(BCM_TSN_SR_SUPPORT)
   5793     uint32 sw_idx;
   5794     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   5795     bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL;
   5796     bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *bk_group_data;
   5797     bcm_tsn_sr_auto_learn_group_config_t *bk_config;
   5798 
   5799     TSN_FUNCTION_TRACE(unit, "IN");
   5800 
   5801     /* Parameter NULL error handling */
   5802     if (NULL == config) {
   5803         return BCM_E_PARAM;
   5804     }
   5805 
   5806     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   5807 
   5808     /* Initialization check */
   5809     AUTO_LEARN_INIT(unit);
   5810 
   5811     /* auto learn bk info */
   5812     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   5813 
   5814     AUTO_LEARN_LOCK(unit);
   5815 
   5816     /* Check if group id existed */
   5817     rv = bcmi_esw_tsn_sr_auto_learn_group_id_existed_check(unit, group_id);
   5818     if (BCM_FAILURE(rv)) {
   5819         AUTO_LEARN_UNLOCK(unit);
   5820         LOG_WARN(BSL_LS_BCM_TSN,
   5821                  (BSL_META_U(unit,
   5822                              "group_id(%d) doesn't exited\n"), group_id));
   5823         return rv;
   5824     }
   5825 
   5826     /* Get the configure from SW bookkeeping database */
   5827     sw_idx = GROUP_ID_TO_SW_IDX(group_id);
   5828     bk_group_data = &(al_bk_info->group_data[sw_idx]);
   5829     bk_config = &(bk_group_data->config);
   5830     sal_memcpy(config,
   5831                bk_config,
   5832                sizeof(bcm_tsn_sr_auto_learn_group_config_t));
   5833 
   5834     AUTO_LEARN_UNLOCK(unit);
   5835 
   5836     bcmi_esw_tsn_sr_auto_learn_group_config_dump(
   5837         unit, "auto_learn_group_get", config);
   5838 
   5839     rv = BCM_E_NONE;
   5840 #endif /* BCM_TSN_SR_SUPPORT */
   5841     TSN_FUNCTION_TRACE(unit, "OUT");
   5842     return rv;
   5843 }
   5844 
   5845 /*
   5846  * Function:
   5847  *   bcmi_esw_tsn_sr_auto_learn_group_destroy
   5848  * Purpose:
   5849  *   Destroy an Auto Learn config with the given group_id by removing it
   5850  *   from hardware and deleting the associated software state info.
   5851  * Parameters:
   5852  *   unit       - (IN) Unit number
   5853  *   group_id   - (IN) Group ID
   5854  * Returns:
   5855  *   BCM_E_NONE - destroy successfully
   5856  */
   5857 STATIC int
   5858 bcmi_esw_tsn_sr_auto_learn_group_destroy(
   5859     int unit,
   5860     int group_id)
   5861 {
   5862     bcm_error_t rv = BCM_E_UNAVAIL;
   5863 #if defined(BCM_TSN_SR_SUPPORT)
   5864     uint32 sw_idx;
   5865     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   5866     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   5867     const tsn_sr_auto_learn_info_t *al_dev_info = NULL;
   5868     bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL;
   5869     bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *bk_group_data;
   5870     bcm_tsn_sr_auto_learn_group_config_t *bk_config;
   5871     bcmi_tsn_sr_auto_learn_group_port_type_t group_ports_type;
   5872     bcm_pbmp_t group_ports_pbmp;
   5873 
   5874     TSN_FUNCTION_TRACE(unit, "IN");
   5875 
   5876     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   5877 
   5878     /* Initialization check */
   5879     AUTO_LEARN_INIT(unit);
   5880 
   5881     /* auto learn bk info */
   5882     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   5883 
   5884     /* auto learn device info */
   5885     dev_info = bk_info->tsn_dev_info;
   5886     al_dev_info = dev_info->tsn_sr_auto_learn_info;
   5887 
   5888     /* Check if the chip specific function existed */
   5889     TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->group_port_delete);
   5890 
   5891     /* Check if group id existed */
   5892     rv = bcmi_esw_tsn_sr_auto_learn_group_id_existed_check(unit, group_id);
   5893     if (BCM_FAILURE(rv)) {
   5894         LOG_WARN(BSL_LS_BCM_TSN,
   5895                  (BSL_META_U(unit,
   5896                              "group_id(%d) doesn't exited\n"), group_id));
   5897         return BCM_E_NOT_FOUND;
   5898     }
   5899     if (!SOC_UNIT_VALID(unit)) {
   5900         return BCM_E_UNIT;
   5901     }
   5902 
   5903     AUTO_LEARN_LOCK(unit);
   5904 
   5905     /* Delete HW */
   5906     if (BCM_FAILURE(rv)) {
   5907         AUTO_LEARN_UNLOCK(unit);
   5908         LOG_ERROR(BSL_LS_BCM_TSN,
   5909                   (BSL_META_U(unit,
   5910                               "delete HW failed(rv = %d)\n"),
   5911                               rv));
   5912 
   5913         return rv;
   5914     }
   5915 
   5916     /* Set SW bookkeeping database pointers */
   5917     sw_idx = GROUP_ID_TO_SW_IDX(group_id);
   5918     bk_group_data = &(al_bk_info->group_data[sw_idx]);
   5919     bk_config = &(bk_group_data->config);
   5920 
   5921     /*
   5922      * Delete auto learn group for redundant and interlink
   5923      * 1. auto learn group bitmap with redundant ports
   5924      * 2. auto learn group proxy bitmap with interlink & redundant ports
   5925      */
   5926     AUTO_LEARN_BK_LOCK(unit);
   5927     (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx(
   5928             unit, &group_id,
   5929             bk_group_data->interlink_pro_idx,
   5930             bk_group_data->redundant_pro_idx,
   5931             bk_config);
   5932     AUTO_LEARN_BK_UNLOCK(unit);
   5933 
   5934     /* redundant ports */
   5935     if (BCM_PBMP_NOT_NULL(bk_config->redundant_ports)) {
   5936         /* L2MC */
   5937         group_ports_type = bcmi_sr_auto_learn_group_l2mc;
   5938         BCM_PBMP_ASSIGN(group_ports_pbmp, bk_config->redundant_ports);
   5939 
   5940         /* Delete HW */
   5941         rv = al_dev_info->group_port_delete(unit, group_ports_type,
   5942                             group_ports_pbmp);
   5943 
   5944         if (BCM_FAILURE(rv)) {
   5945             AUTO_LEARN_UNLOCK(unit);
   5946             LOG_ERROR(BSL_LS_BCM_TSN,
   5947                       (BSL_META_U(unit,
   5948                                   "L2MC delete failed(rv = %d)\n"),
   5949                                   rv));
   5950             return rv;
   5951         }
   5952 
   5953         /* MAC PROXY */
   5954         group_ports_type = bcmi_sr_auto_learn_group_macp;
   5955         BCM_PBMP_ASSIGN(group_ports_pbmp, bk_config->redundant_ports);
   5956 
   5957         /* Delete HW */
   5958         rv = al_dev_info->group_port_delete(unit, group_ports_type,
   5959                             group_ports_pbmp);
   5960 
   5961         if (BCM_FAILURE(rv)) {
   5962             AUTO_LEARN_UNLOCK(unit);
   5963             LOG_ERROR(BSL_LS_BCM_TSN,
   5964                       (BSL_META_U(unit,
   5965                                   "MAC PROXY delete failed(rv = %d)\n"),
   5966                                   rv));
   5967             return rv;
   5968         }
   5969     }
   5970 
   5971     /* interlink ports */
   5972     if (BCM_PBMP_NOT_NULL(bk_config->interlink_ports)) {
   5973         /* MAC PROXY */
   5974         group_ports_type = bcmi_sr_auto_learn_group_macp;
   5975         BCM_PBMP_ASSIGN(group_ports_pbmp, bk_config->interlink_ports);
   5976 
   5977         /* Delete HW */
   5978         rv = al_dev_info->group_port_delete(unit, group_ports_type,
   5979                             group_ports_pbmp);
   5980 
   5981         if (BCM_FAILURE(rv)) {
   5982             AUTO_LEARN_UNLOCK(unit);
   5983             LOG_ERROR(BSL_LS_BCM_TSN,
   5984                       (BSL_META_U(unit,
   5985                                   "write to HW failed(rv = %d)\n"),
   5986                                   rv));
   5987             return rv;
   5988         }
   5989     }
   5990 
   5991     /* Clear SW bookkeeping database */
   5992     AUTO_LEARN_BK_LOCK(unit);
   5993     bk_group_data->redundant_pro_idx[bcmi_sr_auto_learn_group_l2mc] =
   5994         BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID;
   5995     bk_group_data->redundant_pro_idx[bcmi_sr_auto_learn_group_macp] =
   5996         BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID;
   5997     bk_group_data->interlink_pro_idx =
   5998         BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID;
   5999     bk_group_data->group_id = BCMI_SR_AUTO_LEARN_GROUP_ID_INVALID;
   6000     sal_memset(bk_config,
   6001                0,
   6002                sizeof(bcm_tsn_sr_auto_learn_group_config_t));
   6003     AUTO_LEARN_BK_UNLOCK(unit);
   6004 
   6005     /* Clear HW status if there is no valid one.*/
   6006     if (0 == al_bk_info->valid_count) {
   6007         rv = bcmi_esw_tsn_sr_auto_learn_hw_delete_all(unit);
   6008         if (BCM_FAILURE(rv)) {
   6009             AUTO_LEARN_UNLOCK(unit);
   6010             LOG_ERROR(BSL_LS_BCM_TSN,
   6011                       (BSL_META_U(unit,
   6012                                   "Delete all HW resource failed(rv = %d)\n"),
   6013                                   rv));
   6014 
   6015             return rv;
   6016         }
   6017     }
   6018     AUTO_LEARN_UNLOCK(unit);
   6019 
   6020     rv = BCM_E_NONE;
   6021 #endif /* BCM_TSN_SR_SUPPORT */
   6022 
   6023     TSN_FUNCTION_TRACE(unit, "OUT");
   6024     return rv;
   6025 }
   6026 
   6027 /*
   6028  * Function:
   6029  *   bcmi_esw_tsn_sr_auto_learn_group_traverse
   6030  * Purpose:
   6031  *   Traverse the Auto Learn config information.
   6032  * Parameters:
   6033  *   unit      - (IN) Unit number
   6034  *   cb        - (IN) Traverse call back function
   6035  *   user_data - (IN) User data
   6036  * Returns:
   6037  *   BCM_E_xxx
   6038  */
   6039 STATIC int
   6040 bcmi_esw_tsn_sr_auto_learn_group_traverse(
   6041     int unit,
   6042     bcm_tsn_sr_auto_learn_group_traverse_cb cb,
   6043     void *user_data)
   6044 {
   6045     bcm_error_t rv = BCM_E_UNAVAIL;
   6046 #if defined(BCM_TSN_SR_SUPPORT)
   6047     uint32 sw_idx;
   6048     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   6049     bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL;
   6050 
   6051     TSN_FUNCTION_TRACE(unit, "IN");
   6052 
   6053     /* Parameter NULL error handling */
   6054     if (NULL == cb) {
   6055         return BCM_E_PARAM;
   6056     }
   6057 
   6058     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   6059 
   6060     /* Initialization check */
   6061     AUTO_LEARN_INIT(unit);
   6062 
   6063     AUTO_LEARN_LOCK(unit);
   6064     /* auto learn bk info */
   6065     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   6066 
   6067     for (sw_idx = al_bk_info->valid_sw_idx_start;
   6068          sw_idx <= al_bk_info->valid_sw_idx_end;
   6069          sw_idx++) {
   6070         if (AUTO_LEARN_INTF_USED_GET(unit, sw_idx)) {
   6071             rv = cb(unit, SW_IDX_TO_GROUP_ID(sw_idx), user_data);
   6072             if (BCM_FAILURE(rv)) {
   6073                 AUTO_LEARN_UNLOCK(unit);
   6074                 return rv;
   6075             }
   6076         }
   6077     }
   6078 
   6079     AUTO_LEARN_UNLOCK(unit);
   6080 
   6081     rv = BCM_E_NONE;
   6082 #endif /* BCM_TSN_SR_SUPPORT */
   6083     TSN_FUNCTION_TRACE(unit, "OUT");
   6084     return rv;
   6085 }
   6086 
   6087 
   6088 /*
   6089  * De-allocate a flowset list and underlying flows with flowset index
   6090  */
   6091 STATIC void
   6092 bcmi_esw_tsn_sr_auto_learn_free_flowset(
   6093     int unit,
   6094     bcm_tsn_sr_flowset_t *flowset[bcmi_sr_auto_learn_flow_count],
   6095     uint32 *flowset_cnt,
   6096     int clear_hw)
   6097 {
   6098     int i;
   6099     bcmi_tsn_sr_auto_learn_flow_t flow_type;
   6100 
   6101     /* Parameter NULL error handling */
   6102     if ((NULL == flowset) || (NULL == flowset_cnt)) {
   6103         return;
   6104     }
   6105 
   6106     for (flow_type = bcmi_sr_auto_learn_flow_tx;
   6107          flow_type < bcmi_sr_auto_learn_flow_count;
   6108          flow_type++) {
   6109         if (TRUE == clear_hw) {
   6110             for (i = 0; i < flowset_cnt[flow_type]; i++) {
   6111                 if (0 != flowset[flow_type][i]) {
   6112                     (void)bcm_esw_tsn_sr_flowset_destroy(
   6113                             unit, flowset[flow_type][i]);
   6114                 }
   6115             }
   6116         }
   6117         if (flowset[flow_type] != NULL) {
   6118             TSN_FREE(unit, flowset[flow_type], 0);
   6119             flowset[flow_type] = NULL;
   6120         }
   6121         flowset_cnt[flow_type] = 0;
   6122     }
   6123 }
   6124 
   6125 /*
   6126  * Function:
   6127  *   bcmi_esw_tsn_sr_auto_learn_enable
   6128  * Purpose:
   6129  *   Enable/disable SR flow auto learn subsystem
   6130  * Parameters:
   6131  *   unit   - (IN) Unit number
   6132  *   enable - (IN) Enable/Disable
   6133  *   config - (IN) Auto Learn configuration
   6134  * Returns:
   6135  *   BCM_E_xxx
   6136  */
   6137 STATIC int
   6138 bcmi_esw_tsn_sr_auto_learn_enable(
   6139     int unit,
   6140     int enable,
   6141     bcm_tsn_sr_auto_learn_config_t *config)
   6142 {
   6143     bcm_error_t rv = BCM_E_UNAVAIL;
   6144 #if defined(BCM_TSN_SR_SUPPORT)
   6145     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   6146     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   6147     const tsn_sr_auto_learn_info_t *al_dev_info = NULL;
   6148     bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL;
   6149     bcmi_esw_tsn_sr_auto_learn_bk_data_t *bk_data = NULL;
   6150     bcmi_tsn_sr_auto_learn_flow_t flow_type;
   6151     bcm_tsn_sr_flowset_t flowset;
   6152     bcm_tsn_sr_flow_t fid;
   6153     uint32 hwfid;
   6154     int i, prev = 0;
   6155     uint32 ctrl_current_fid = 0, ctrl_last_fid = 0;
   6156     uint32 ctrl_id_size[bcmi_sr_auto_learn_flow_count];
   6157 
   6158     TSN_FUNCTION_TRACE(unit, "IN");
   6159 
   6160     /* Parameter NULL error handling */
   6161     if ((TRUE == enable) &&
   6162         ((NULL == config) ||
   6163          (NULL != config &&
   6164           (0 == config->num_tx_flows || 0 == config->num_rx_flows)))) {
   6165         return BCM_E_PARAM;
   6166     }
   6167 
   6168     /* SR Auto Learn management initialization */
   6169     rv = bcmi_esw_tsn_sr_auto_learn_lazy_init(unit);
   6170     if (BCM_FAILURE(rv)) {
   6171         bcmi_esw_tsn_sr_auto_learn_cleanup(unit);
   6172         return (rv);
   6173     }
   6174 
   6175     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   6176 
   6177     /* Initialization check */
   6178     AUTO_LEARN_INIT(unit);
   6179 
   6180     /* auto learn bk info */
   6181     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   6182 
   6183     /* auto learn device info */
   6184     dev_info = bk_info->tsn_dev_info;
   6185     al_dev_info = dev_info->tsn_sr_auto_learn_info;
   6186 
   6187     bcmi_esw_tsn_sr_auto_learn_config_dump(unit, "auto_learn_enable", config);
   6188 
   6189     /* Check if the chip specific function existed */
   6190     TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->flow_id_pool_set);
   6191     TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->flow_id_ctrl_set);
   6192     TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->enable);
   6193 
   6194     /* Check Auto Learn is already enabled and config to enable is the same */
   6195     if ((TRUE == enable) &&
   6196         (TRUE == al_bk_info->data.enabled) &&
   6197         (!sal_memcmp(config, &al_bk_info->data,
   6198                       sizeof(bcm_tsn_sr_auto_learn_config_t)))) {
   6199         LOG_ERROR(BSL_LS_BCM_TSN,
   6200                   (BSL_META_U(unit,
   6201                               "Auto Learn has already enabled, "
   6202                               "please disable auto learn first.\n")));
   6203         return BCM_E_BUSY;
   6204     }
   6205 
   6206     AUTO_LEARN_LOCK(unit);
   6207     AUTO_LEARN_BK_LOCK(unit);
   6208 
   6209     bk_data = &(al_bk_info->data);
   6210     /*
   6211      * Create N(num_tx/rx_flows) flows with tx/rx_flow_config for tx/rx flows
   6212      * Each tx/rx flow is a linked list, begin at ctrl_current_fid and end
   6213      * at ctrl_last_fid.
   6214      */
   6215     if (TRUE == enable) {
   6216         /* Check if id sizes excess the max flow number */
   6217         ctrl_id_size[bcmi_sr_auto_learn_flow_tx] = config->num_tx_flows;
   6218         ctrl_id_size[bcmi_sr_auto_learn_flow_rx] = config->num_rx_flows;
   6219 
   6220         for (flow_type = bcmi_sr_auto_learn_flow_tx;
   6221              flow_type < bcmi_sr_auto_learn_flow_count;
   6222              flow_type++) {
   6223             if (ctrl_id_size[flow_type] >
   6224                 (al_dev_info->max_flow_num[flow_type])) {
   6225                 AUTO_LEARN_BK_UNLOCK(unit);
   6226                 AUTO_LEARN_UNLOCK(unit);
   6227                 return BCM_E_PARAM;
   6228             }
   6229         }
   6230 
   6231         bcmi_esw_tsn_sr_auto_learn_free_flowset(
   6232             unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE);
   6233 
   6234         for (flow_type = bcmi_sr_auto_learn_flow_tx;
   6235              flow_type < bcmi_sr_auto_learn_flow_count;
   6236              flow_type++) {
   6237 
   6238             TSN_ALLOC(unit, bk_data->flowsets[flow_type],
   6239                       bcm_tsn_sr_flowset_t,
   6240                       sizeof(bcm_tsn_sr_flowset_t) * ctrl_id_size[flow_type],
   6241                       "bk record Rx/Tx Flowset", 0, rv);
   6242             if (BCM_FAILURE(rv)) {
   6243                 AUTO_LEARN_BK_UNLOCK(unit);
   6244                 AUTO_LEARN_UNLOCK(unit);
   6245                 LOG_VERBOSE(BSL_LS_BCM_TSN,
   6246                             (BSL_META_U(unit,
   6247                                         "failed to allocate"
   6248                                         "Rx/Tx Flowset memory\n")));
   6249                 return rv;
   6250             }
   6251             /* Create N flowsets with tx/rx flow config */
   6252             for (i = 0; i < ctrl_id_size[flow_type]; i++) {
   6253                 if (bcmi_sr_auto_learn_flow_tx == flow_type) {
   6254                     rv = bcm_esw_tsn_sr_tx_flowset_create(
   6255                             unit, BCM_TSN_PRI_MAP_INVALID,
   6256                             &config->tx_flow_config, &flowset);
   6257                 } else if (bcmi_sr_auto_learn_flow_rx == flow_type) {
   6258                     rv = bcm_esw_tsn_sr_rx_flowset_create(
   6259                             unit, BCM_TSN_PRI_MAP_INVALID,
   6260                             &config->rx_flow_config, &flowset);
   6261                 }
   6262 
   6263                 if (BCM_FAILURE(rv)) {
   6264                     bcmi_esw_tsn_sr_auto_learn_free_flowset(
   6265                         unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE);
   6266                     AUTO_LEARN_BK_UNLOCK(unit);
   6267                     AUTO_LEARN_UNLOCK(unit);
   6268                     return rv;
   6269                 }
   6270                 bk_data->flowsets[flow_type][i] = flowset;
   6271                 bk_data->flowsets_cnt[flow_type] = i + 1;
   6272                 /* Get the flow_id from created flowset */
   6273                 rv = bcm_esw_tsn_sr_flowset_flow_get(
   6274                         unit, flowset, 0, &fid);
   6275                 if (BCM_FAILURE(rv)) {
   6276                     bcmi_esw_tsn_sr_auto_learn_free_flowset(
   6277                         unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE);
   6278                     AUTO_LEARN_BK_UNLOCK(unit);
   6279                     AUTO_LEARN_UNLOCK(unit);
   6280                     return rv;
   6281                 }
   6282 
   6283                 /* Convert software SR flow ID to hardware SR flow ID */
   6284                 rv = bcmi_esw_tsn_sr_hw_flow_id_get(
   6285                         unit, fid, &hwfid);
   6286                 if (BCM_FAILURE(rv)) {
   6287                     bcmi_esw_tsn_sr_auto_learn_free_flowset(
   6288                         unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE);
   6289                     AUTO_LEARN_BK_UNLOCK(unit);
   6290                     AUTO_LEARN_UNLOCK(unit);
   6291                     return rv;
   6292                 }
   6293                 if (i == 0) {
   6294                     ctrl_current_fid = hwfid;
   6295                     prev = hwfid;
   6296                     continue;
   6297                 }
   6298 
   6299                 /* Write next fid (prev pointer to fid) */
   6300                 rv = al_dev_info->flow_id_pool_set(
   6301                                     unit, flow_type, prev, hwfid);
   6302                 if (BCM_FAILURE(rv)) {
   6303                     bcmi_esw_tsn_sr_auto_learn_free_flowset(
   6304                         unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE);
   6305                     AUTO_LEARN_BK_UNLOCK(unit);
   6306                     AUTO_LEARN_UNLOCK(unit);
   6307                     LOG_ERROR(BSL_LS_BCM_TSN,
   6308                               (BSL_META_U(unit,
   6309                                           "Write to HW failed(rv = %d)\n"),
   6310                                           rv));
   6311                     return rv;
   6312                 }
   6313                 prev = hwfid;
   6314             }
   6315             ctrl_last_fid = hwfid;
   6316 
   6317             /* Set the config to HW */
   6318             rv = al_dev_info->flow_id_ctrl_set(
   6319                      unit,
   6320                      flow_type,
   6321                      ctrl_current_fid,
   6322                      ctrl_last_fid,
   6323                      ctrl_id_size[flow_type]);
   6324 
   6325             if (BCM_FAILURE(rv)) {
   6326                 bcmi_esw_tsn_sr_auto_learn_free_flowset(
   6327                         unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE);
   6328                 AUTO_LEARN_BK_UNLOCK(unit);
   6329                 AUTO_LEARN_UNLOCK(unit);
   6330                 LOG_ERROR(BSL_LS_BCM_TSN,
   6331                           (BSL_META_U(unit,
   6332                                       "Write to HW failed(rv = %d)\n"),
   6333                                       rv));
   6334                 return rv;
   6335             }
   6336         }
   6337     }
   6338 
   6339     /* Turn ON / OFF HW learning */
   6340     rv = al_dev_info->enable(unit, enable);
   6341     if (BCM_FAILURE(rv)) {
   6342         bcmi_esw_tsn_sr_auto_learn_free_flowset(
   6343             unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE);
   6344         AUTO_LEARN_BK_UNLOCK(unit);
   6345         AUTO_LEARN_UNLOCK(unit);
   6346         LOG_ERROR(BSL_LS_BCM_TSN,
   6347                   (BSL_META_U(unit,
   6348                               "Write to HW failed(rv = %d)\n"),
   6349                               rv));
   6350         return rv;
   6351     }
   6352 
   6353     bk_data->enabled = enable;
   6354     if (TRUE == enable) {
   6355         sal_memcpy(&(bk_data->config),
   6356                    config,
   6357                    sizeof(bcm_tsn_sr_auto_learn_config_t));
   6358     } else {
   6359         /* Clear the config when disable */
   6360         bcm_tsn_sr_auto_learn_config_t_init(&(bk_data->config));
   6361         bcmi_esw_tsn_sr_auto_learn_free_flowset(
   6362             unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE);
   6363     }
   6364 
   6365     AUTO_LEARN_BK_UNLOCK(unit);
   6366     AUTO_LEARN_UNLOCK(unit);
   6367 
   6368     bcmi_esw_tsn_sr_auto_learn_config_dump(
   6369         unit, "SW bk config", &(bk_data->config));
   6370 
   6371     rv = BCM_E_NONE;
   6372 #endif /* BCM_TSN_SR_SUPPORT */
   6373     TSN_FUNCTION_TRACE(unit, "OUT");
   6374     return rv;
   6375 }
   6376 
   6377 /*
   6378  * Function:
   6379  *   bcmi_esw_tsn_sr_auto_learn_enable_get
   6380  * Purpose:
   6381  *   Get enable/disable SR flow auto learn subsystem
   6382  * Parameters:
   6383  *   unit   - (IN) Unit number
   6384  *   enable - (OUT) Enable/disable
   6385  *   config - (OUT) Auto Learn configuration
   6386  * Returns:
   6387  *   BCM_E_xxx
   6388  */
   6389 STATIC int
   6390 bcmi_esw_tsn_sr_auto_learn_enable_get(
   6391     int unit,
   6392     int *enabled,
   6393     bcm_tsn_sr_auto_learn_config_t *config)
   6394 {
   6395     bcm_error_t rv = BCM_E_UNAVAIL;
   6396 #if defined(BCM_TSN_SR_SUPPORT)
   6397     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   6398     bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL;
   6399     bcmi_esw_tsn_sr_auto_learn_bk_data_t *bk_data = NULL;
   6400 
   6401     TSN_FUNCTION_TRACE(unit, "IN");
   6402 
   6403     /* Parameter NULL error handling */
   6404     if ((NULL == enabled) || (NULL == config)) {
   6405         return BCM_E_PARAM;
   6406     }
   6407 
   6408     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   6409 
   6410     /* Initialization check */
   6411     AUTO_LEARN_INIT(unit);
   6412 
   6413     /* auto learn bk info */
   6414     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   6415 
   6416     /* Get enabled from SW BK */
   6417     bk_data = &(al_bk_info->data);
   6418     *enabled = bk_data->enabled;
   6419 
   6420     /* If it's enabled, copy bcm_tsn_sr_auto_learn_config_t */
   6421     if (*enabled) {
   6422         sal_memcpy(config,
   6423                    &(bk_data->config),
   6424                    sizeof(bcm_tsn_sr_auto_learn_config_t));
   6425 
   6426         bcmi_esw_tsn_sr_auto_learn_config_dump(
   6427             unit, "auto_learn_enable_get", config);
   6428     } else {
   6429         LOG_WARN(BSL_LS_BCM_TSN,
   6430                  (BSL_META_U(unit,
   6431                              "SR flow auto learn subsystem isn't enabled\n")));
   6432     }
   6433 
   6434     rv = BCM_E_NONE;
   6435 #endif /* BCM_TSN_SR_SUPPORT */
   6436     TSN_FUNCTION_TRACE(unit, "OUT");
   6437     return rv;
   6438 }
   6439 
   6440 #if defined(BCM_WARM_BOOT_SUPPORT)
   6441 /* Auto Learn management - warmboot scache size allocation */
   6442 STATIC int
   6443 bcmi_esw_tsn_sr_auto_learn_wb_alloc(int unit)
   6444 {
   6445     bcm_error_t rv = BCM_E_UNAVAIL;
   6446     soc_scache_handle_t scache_handle;
   6447     uint8 *auto_learn_scache = NULL;
   6448     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   6449     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   6450     const tsn_sr_auto_learn_info_t *al_dev_info = NULL;
   6451     tsn_sr_flows_bookkeeping_t *flow_bkinfo;
   6452     uint32 table_size;
   6453     int data_size = 0, group_data_size = 0;
   6454 
   6455     TSN_FUNCTION_TRACE(unit, "IN");
   6456 
   6457     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   6458 
   6459     /* 1. Size of bcmi_esw_tsn_sr_auto_learn_bk_t.initialized */
   6460     data_size = sizeof(int);
   6461 
   6462     /* Initialization check */
   6463     AUTO_LEARN_DEV_INIT(unit);
   6464 
   6465     /* auto learn device info */
   6466     dev_info = bk_info->tsn_dev_info;
   6467     al_dev_info = dev_info->tsn_sr_auto_learn_info;
   6468 
   6469     rv = al_dev_info->table_size_get(unit, &table_size);
   6470     BCM_IF_ERROR_RETURN(rv);
   6471     assert(table_size > 0);
   6472 
   6473     /* 2. Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.intf_bitmap */
   6474     data_size += SHR_BITALLOCSIZE(table_size);
   6475 
   6476     /* 3. Size of bcmi_esw_tsn_sr_auto_learn_bk_t.group_data */
   6477     group_data_size =
   6478         sizeof(bcmi_esw_tsn_sr_auto_learn_group_bk_data_t) * table_size;
   6479     data_size += group_data_size;
   6480 
   6481     /* 4. Size of bcmi_esw_tsn_sr_auto_learn_bk_t.data */
   6482     flow_bkinfo = &tsn_bk_info[unit]->sr_flows;
   6483     data_size += sizeof(uint32) * 2;   /* flowsets_cnt */
   6484     data_size +=                       /* Rx flowsets */
   6485         flow_bkinfo->max_flows[SR_FLOW_DIR_RX] * sizeof(bcm_tsn_sr_flowset_t);
   6486     data_size +=                       /* Tx flowsets */
   6487         flow_bkinfo->max_flows[SR_FLOW_DIR_TX] * sizeof(bcm_tsn_sr_flowset_t);
   6488 
   6489     SOC_SCACHE_HANDLE_SET(scache_handle,
   6490                           unit,
   6491                           BCM_MODULE_TSN,
   6492                           BCM_TSN_WB_SCACHE_PART_AUTO_LEARN);
   6493 
   6494     rv = _bcm_esw_scache_ptr_get(
   6495             unit, scache_handle, TRUE, data_size,
   6496             &auto_learn_scache, BCM_TSN_WB_DEFAULT_VERSION, NULL);
   6497 
   6498     if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) {
   6499         LOG_VERBOSE(BSL_LS_BCM_TSN,
   6500                     (BSL_META_U(unit,
   6501                                 "Auto Learn SCACHE Memory not available\n")));
   6502         return rv;
   6503     }
   6504     TSN_FUNCTION_TRACE(unit, "OUT");
   6505     return BCM_E_NONE;
   6506 }
   6507 
   6508 /*
   6509  * Function:
   6510  *   bcmi_esw_tsn_sr_auto_learn_sync
   6511  * Purpose:
   6512  *   Record bcmi_esw_tsn_sr_auto_learn_group_bk_data_t for Warm Boot
   6513  * Parameters:
   6514  *   unit       - (IN) Unit number
   6515  * Returns:
   6516  *   BCM_E_NONE - Success.
   6517  */
   6518 STATIC int
   6519 bcmi_esw_tsn_sr_auto_learn_sync(int unit)
   6520 {
   6521     bcm_error_t rv = BCM_E_UNAVAIL;
   6522     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   6523     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   6524     const tsn_sr_auto_learn_info_t *al_dev_info = NULL;
   6525     bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL;
   6526     bcmi_esw_tsn_sr_auto_learn_bk_data_t *bk_data = NULL;
   6527     bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *bk_group_data;
   6528     uint32 table_size;
   6529     int data_size = 0, group_data_size = 0;
   6530     uint8 *auto_learn_scache = NULL;
   6531     soc_scache_handle_t scache_handle;
   6532 
   6533     TSN_FUNCTION_TRACE(unit, "IN");
   6534 
   6535     SOC_SCACHE_HANDLE_SET(scache_handle,
   6536                           unit,
   6537                           BCM_MODULE_TSN,
   6538                           BCM_TSN_WB_SCACHE_PART_AUTO_LEARN);
   6539 
   6540     BCM_IF_ERROR_RETURN(
   6541         _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
   6542             &auto_learn_scache, BCM_TSN_WB_DEFAULT_VERSION, NULL));
   6543 
   6544     if (NULL == auto_learn_scache) {
   6545         LOG_VERBOSE(BSL_LS_BCM_TSN,
   6546                     (BSL_META_U(unit,
   6547                                 "Auto Learn SCACHE Memory not available\n")));
   6548         return BCM_E_MEMORY;
   6549     }
   6550     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   6551 
   6552     /* auto learn bk info */
   6553     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   6554 
   6555     /* 1. Sync bcmi_esw_tsn_sr_auto_learn_bk_t.initialized */
   6556     AUTO_LEARN_BK_LOCK(unit);
   6557     data_size = sizeof(int);
   6558     sal_memcpy(auto_learn_scache, &(al_bk_info->initialized), data_size);
   6559     auto_learn_scache += data_size;
   6560     AUTO_LEARN_BK_UNLOCK(unit);
   6561 
   6562     if (TRUE == al_bk_info->initialized) {
   6563         /* Initialization check */
   6564         AUTO_LEARN_INIT(unit);
   6565 
   6566         /* auto learn device info */
   6567         dev_info = bk_info->tsn_dev_info;
   6568         al_dev_info = dev_info->tsn_sr_auto_learn_info;
   6569 
   6570         /* Set SW bookkeeping database pointers */
   6571         bk_group_data = al_bk_info->group_data;
   6572         bk_data = &(al_bk_info->data);
   6573 
   6574         rv = al_dev_info->table_size_get(unit, &table_size);
   6575         BCM_IF_ERROR_RETURN(rv);
   6576         assert(table_size > 0);
   6577         group_data_size =
   6578             sizeof(bcmi_esw_tsn_sr_auto_learn_group_bk_data_t) * table_size;
   6579 
   6580         AUTO_LEARN_BK_LOCK(unit);
   6581         /* 2. Sync bcmi_esw_tsn_sr_auto_learn_bk_t.intf_bitmap */
   6582         data_size = SHR_BITALLOCSIZE(table_size);
   6583         sal_memcpy(auto_learn_scache, al_bk_info->intf_bitmap, data_size);
   6584         auto_learn_scache += data_size;
   6585 
   6586         /* 3. Sync bcmi_esw_tsn_sr_auto_learn_bk_t.group_data */
   6587         data_size = group_data_size;
   6588         sal_memcpy(auto_learn_scache, bk_group_data, data_size);
   6589         auto_learn_scache += data_size;
   6590         AUTO_LEARN_BK_UNLOCK(unit);
   6591 
   6592         if (TRUE == bk_data->enabled) {
   6593             /* 4. Sync bcmi_esw_tsn_sr_auto_learn_bk_t.data */
   6594 
   6595             /* flowset_cnt */
   6596             AUTO_LEARN_BK_LOCK(unit);
   6597             data_size = sizeof(uint32);
   6598             sal_memcpy(auto_learn_scache,
   6599                        &(bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_tx]),
   6600                        data_size);
   6601             auto_learn_scache += data_size;
   6602 
   6603             data_size = sizeof(uint32);
   6604             sal_memcpy(auto_learn_scache,
   6605                        &(bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_rx]),
   6606                        data_size);
   6607             auto_learn_scache += data_size;
   6608 
   6609             /* Tx flowsets */
   6610             data_size =
   6611                 bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_tx] *
   6612                 sizeof(bcm_tsn_sr_flowset_t);
   6613             sal_memcpy(auto_learn_scache,
   6614                        bk_data->flowsets[bcmi_sr_auto_learn_flow_tx],
   6615                        data_size);
   6616             auto_learn_scache += data_size;
   6617 
   6618             /* Rx flowsets */
   6619             data_size =
   6620                 bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_rx] *
   6621                 sizeof(bcm_tsn_sr_flowset_t);
   6622             sal_memcpy(auto_learn_scache,
   6623                        bk_data->flowsets[bcmi_sr_auto_learn_flow_rx],
   6624                        data_size);
   6625             auto_learn_scache += data_size;
   6626             AUTO_LEARN_BK_UNLOCK(unit);
   6627         }
   6628     }
   6629 
   6630     TSN_FUNCTION_TRACE(unit, "OUT");
   6631     return BCM_E_NONE;
   6632 }
   6633 
   6634 /*
   6635  * Function:
   6636  *   bcmi_esw_tsn_sr_auto_learn_reload
   6637  * Purpose:
   6638  *   Re-initialize the Auto Learn resource. Restore bookkeeping information.
   6639  * Parameters:
   6640  *   unit       - (IN) Unit number
   6641  * Returns:
   6642  *   BCM_E_NONE - Success. Warm boot successfully
   6643  */
   6644 STATIC int
   6645 bcmi_esw_tsn_sr_auto_learn_reload(int unit)
   6646 {
   6647     bcm_error_t rv = BCM_E_UNAVAIL;
   6648     int enabled;
   6649     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   6650     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   6651     const tsn_sr_auto_learn_info_t *al_dev_info = NULL;
   6652     bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL;
   6653     bcmi_esw_tsn_sr_auto_learn_bk_data_t *bk_data = NULL;
   6654     bcmi_esw_tsn_sr_mac_proxy_bk_info_t *mp_bk_info = NULL;
   6655     bcmi_esw_tsn_sr_mac_proxy_entry_t *mp_entries = NULL;
   6656     bcmi_tsn_sr_auto_learn_flow_t flow_type;
   6657     bcm_tsn_sr_flowset_t flowset;
   6658     uint32 fid;
   6659     bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *bk_group_data;
   6660     uint32 table_size;
   6661     int data_size = 0;
   6662     uint8 *auto_learn_scache = NULL;
   6663     soc_scache_handle_t scache_handle;
   6664     int i;
   6665     bcmi_tsn_sr_auto_learn_group_port_type_t group_ports_type;
   6666     int pro_idx = BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID;
   6667 
   6668     TSN_FUNCTION_TRACE(unit, "IN");
   6669 
   6670     SOC_SCACHE_HANDLE_SET(scache_handle,
   6671                           unit,
   6672                           BCM_MODULE_TSN,
   6673                           BCM_TSN_WB_SCACHE_PART_AUTO_LEARN);
   6674 
   6675     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
   6676             &auto_learn_scache, BCM_TSN_WB_DEFAULT_VERSION, NULL);
   6677     if (rv == BCM_E_NOT_FOUND) {
   6678         /* Proceed with level 1 warmboot */
   6679         return BCM_E_NONE;
   6680     }
   6681 
   6682     if (NULL == auto_learn_scache) {
   6683         LOG_VERBOSE(BSL_LS_BCM_TSN,
   6684                     (BSL_META_U(unit,
   6685                                 "SCACHE Memory not available \n")));
   6686         return BCM_E_MEMORY;
   6687     }
   6688 
   6689     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   6690 
   6691     /* auto learn device info */
   6692     dev_info = bk_info->tsn_dev_info;
   6693     al_dev_info = dev_info->tsn_sr_auto_learn_info;
   6694 
   6695     /* Check if the chip specific function existed */
   6696     TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->table_size_get);
   6697     TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->enable_get);
   6698     TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->flow_id_ctrl_get);
   6699 
   6700     /* auto learn bk info */
   6701     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   6702 
   6703     /* 1. Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.initialized */
   6704     AUTO_LEARN_BK_LOCK(unit);
   6705     data_size = sizeof(int);
   6706     sal_memcpy(&(al_bk_info->initialized), auto_learn_scache, data_size);
   6707     auto_learn_scache += data_size;
   6708     AUTO_LEARN_BK_UNLOCK(unit);
   6709 
   6710     if (FALSE == al_bk_info->initialized) {
   6711         /* 1st initialization hasn't been triggered */
   6712         TSN_FUNCTION_TRACE(unit, "OUT : not initialized");
   6713         return BCM_E_NONE;
   6714     }
   6715 
   6716     /* Force to re-init again */
   6717     al_bk_info->initialized = FALSE;
   6718 
   6719     /* SR Auto Learn management initialization */
   6720     rv = bcmi_esw_tsn_sr_auto_learn_lazy_init(unit);
   6721     if (BCM_FAILURE(rv)) {
   6722         bcmi_esw_tsn_sr_auto_learn_cleanup(unit);
   6723         return (rv);
   6724     }
   6725 
   6726     /* Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.group_data : Start */
   6727     rv = al_dev_info->table_size_get(unit, &table_size);
   6728     BCM_IF_ERROR_RETURN(rv);
   6729     assert(table_size > 0);
   6730 
   6731     /* Set SW bookkeeping database pointers */
   6732     bk_data = &(al_bk_info->data);
   6733     bk_group_data = al_bk_info->group_data;
   6734 
   6735 
   6736     AUTO_LEARN_BK_LOCK(unit);
   6737 
   6738     /* 2. Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.intf_bitmap */
   6739     data_size = SHR_BITALLOCSIZE(table_size);
   6740     sal_memcpy(al_bk_info->intf_bitmap, auto_learn_scache, data_size);
   6741     auto_learn_scache += data_size;
   6742 
   6743     /* Calculate the cnt/start/end */
   6744     al_bk_info->valid_count = 0;
   6745     al_bk_info->valid_sw_idx_start = 0;
   6746     al_bk_info->valid_sw_idx_end = 0;
   6747     al_bk_info->empty_sw_idx_start = 0;
   6748     al_bk_info->empty_sw_idx_end = 0;
   6749 
   6750     for (i = 0; i < table_size; i++) {
   6751         if (AUTO_LEARN_INTF_USED_GET(unit, i)) {
   6752             al_bk_info->valid_count++;
   6753         }
   6754 
   6755         if (AUTO_LEARN_INTF_USED_GET(unit, i) &&
   6756             !AUTO_LEARN_INTF_USED_GET(unit, al_bk_info->valid_sw_idx_start)) {
   6757             al_bk_info->valid_sw_idx_start = i;
   6758         }
   6759 
   6760         if (AUTO_LEARN_INTF_USED_GET(unit, i) &&
   6761             al_bk_info->valid_sw_idx_end < i) {
   6762             al_bk_info->valid_sw_idx_end = i;
   6763         }
   6764 
   6765         if (!AUTO_LEARN_INTF_USED_GET(unit, i) &&
   6766             AUTO_LEARN_INTF_USED_GET(unit, al_bk_info->empty_sw_idx_start)) {
   6767             al_bk_info->empty_sw_idx_start = i;
   6768         }
   6769 
   6770         if (!AUTO_LEARN_INTF_USED_GET(unit, i) &&
   6771             al_bk_info->empty_sw_idx_end < i) {
   6772             al_bk_info->empty_sw_idx_end = i;
   6773         }
   6774     }
   6775 
   6776     /* 3. Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.group_data */
   6777     data_size =
   6778         sizeof(bcmi_esw_tsn_sr_auto_learn_group_bk_data_t) * table_size;
   6779     sal_memcpy(bk_group_data, auto_learn_scache, data_size);
   6780     auto_learn_scache += data_size;
   6781     AUTO_LEARN_BK_UNLOCK(unit);
   6782 
   6783     /* Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.group_data : End */
   6784 
   6785     /* Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.data : Start */
   6786 
   6787     rv = al_dev_info->enable_get(unit, &enabled);
   6788     if (BCM_FAILURE(rv)) {
   6789         LOG_ERROR(BSL_LS_BCM_TSN,
   6790                   (BSL_META_U(unit,
   6791                               "Read from HW failed(rv = %d)\n"),
   6792                               rv));
   6793         return rv;
   6794     }
   6795     AUTO_LEARN_BK_LOCK(unit);
   6796     bk_data->enabled = enabled;
   6797     AUTO_LEARN_BK_UNLOCK(unit);
   6798 
   6799     if (TRUE == bk_data->enabled) {
   6800         /* 3. Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.data */
   6801         AUTO_LEARN_BK_LOCK(unit);
   6802         data_size = sizeof(uint32);
   6803         sal_memcpy(&(bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_tx]),
   6804                    auto_learn_scache, data_size);
   6805         auto_learn_scache += data_size;
   6806 
   6807         data_size = sizeof(uint32);
   6808         sal_memcpy(&(bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_rx]),
   6809                    auto_learn_scache, data_size);
   6810         auto_learn_scache += data_size;
   6811         AUTO_LEARN_BK_UNLOCK(unit);
   6812 
   6813         bcm_tsn_sr_auto_learn_config_t_init(&(bk_data->config));
   6814 
   6815         AUTO_LEARN_BK_LOCK(unit);
   6816         bk_data->config.num_tx_flows =
   6817             bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_tx];
   6818         bk_data->config.num_rx_flows =
   6819             bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_rx];
   6820         AUTO_LEARN_BK_UNLOCK(unit);
   6821 
   6822         for (flow_type = bcmi_sr_auto_learn_flow_tx;
   6823              flow_type <= bcmi_sr_auto_learn_flow_rx;
   6824              flow_type++) {
   6825 
   6826             AUTO_LEARN_BK_LOCK(unit);
   6827             data_size =
   6828                 bk_data->flowsets_cnt[flow_type] *
   6829                 sizeof(bcm_tsn_sr_flowset_t);
   6830             TSN_ALLOC(
   6831                 unit, bk_data->flowsets[flow_type], bcm_tsn_sr_flowset_t,
   6832                 data_size, "bk record Rx/Tx Flowset", 0, rv);
   6833             if (BCM_FAILURE(rv)) {
   6834                 AUTO_LEARN_BK_UNLOCK(unit);
   6835                 LOG_VERBOSE(BSL_LS_BCM_TSN,
   6836                             (BSL_META_U(unit,
   6837                                         "bcmi_esw_tsn_sr_auto_learn_reload: "
   6838                                         "failed to allocate memory\n")));
   6839                 return rv;
   6840             }
   6841             sal_memcpy(bk_data->flowsets[flow_type], auto_learn_scache,
   6842                        data_size);
   6843             auto_learn_scache += data_size;
   6844 
   6845             /* Take the 1st one for retrieving default flow config */
   6846             flowset = bk_data->flowsets[flow_type][0];
   6847 
   6848             /* Get the flow_id from created flowset */
   6849             rv = bcm_esw_tsn_sr_flowset_flow_get(
   6850                     unit, flowset, 0, &fid);
   6851 
   6852             /* Get tx/rx_flow_config & num_tx/rx_flows */
   6853             if (bcmi_sr_auto_learn_flow_tx == flow_type) {
   6854                 /* Get flow config with given software SR flow ID */
   6855                 rv = bcm_esw_tsn_sr_tx_flow_config_get(unit,
   6856                         fid, &(bk_data->config.tx_flow_config));
   6857                 if (BCM_FAILURE(rv)) {
   6858                     bcmi_esw_tsn_sr_auto_learn_free_flowset(
   6859                         unit, bk_data->flowsets, bk_data->flowsets_cnt, FALSE);
   6860                     bcm_tsn_sr_auto_learn_config_t_init(&(bk_data->config));
   6861                     AUTO_LEARN_BK_UNLOCK(unit);
   6862                     return rv;
   6863                 }
   6864             } else if (bcmi_sr_auto_learn_flow_rx == flow_type) {
   6865                 /* Get flow config with given software SR flow ID */
   6866                 rv = bcm_esw_tsn_sr_rx_flow_config_get(unit,
   6867                         fid, &(bk_data->config.rx_flow_config));
   6868                 if (BCM_FAILURE(rv)) {
   6869                     bcmi_esw_tsn_sr_auto_learn_free_flowset(
   6870                         unit, bk_data->flowsets, bk_data->flowsets_cnt, FALSE);
   6871                     bcm_tsn_sr_auto_learn_config_t_init(&(bk_data->config));
   6872                     AUTO_LEARN_BK_UNLOCK(unit);
   6873                     return rv;
   6874                 }
   6875             }
   6876             AUTO_LEARN_BK_UNLOCK(unit);
   6877         }
   6878 
   6879     }
   6880     /* Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.data : End */
   6881 
   6882     /* Refresh MAC proxy ref_count for auto learn group usage */
   6883     /* SR MAC Proxy bk info */
   6884     mp_bk_info = &(bk_info->tsn_sr_mac_proxy_bk_info);
   6885     mp_entries = mp_bk_info->sr_mp_entry;
   6886     if (mp_entries == NULL) {
   6887         return BCM_E_UNAVAIL;
   6888     }
   6889 
   6890     SR_MAC_PROXY_LOCK(mp_bk_info);
   6891     for (i = 0; i < table_size; i++) {
   6892         if (AUTO_LEARN_INTF_USED_GET(unit, i)) {
   6893             bk_group_data = &(al_bk_info->group_data[i]);
   6894 
   6895             /* Update ref_count for interlink ports */
   6896             pro_idx = bk_group_data->interlink_pro_idx;
   6897             mp_entries[pro_idx].ref_count++;
   6898 
   6899             /* Update ref_count for redundant ports */
   6900             group_ports_type = bcmi_sr_auto_learn_group_macp;
   6901             pro_idx = bk_group_data->redundant_pro_idx[group_ports_type];
   6902             mp_entries[pro_idx].ref_count++;
   6903         }
   6904     }
   6905     SR_MAC_PROXY_UNLOCK(mp_bk_info);
   6906 
   6907     TSN_FUNCTION_TRACE(unit, "OUT");
   6908     return BCM_E_NONE;
   6909 }
   6910 #endif /* BCM_WARM_BOOT_SUPPORT */
   6911 
   6912 
   6913 /*
   6914  * Function:
   6915  *     bcmi_esw_tsn_sr_auto_learn_cleanup
   6916  * Purpose:
   6917  *     Internal function to clear the resource of the TSN module.
   6918  * Parameters:
   6919  *     unit             - (IN) unit number
   6920  * Returns:
   6921  *     BCM_E_XXX
   6922  */
   6923 STATIC int
   6924 bcmi_esw_tsn_sr_auto_learn_cleanup(int unit)
   6925 {
   6926     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   6927     bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL;
   6928     bcmi_esw_tsn_sr_auto_learn_bk_data_t *bk_data = NULL;
   6929 
   6930     LOG_VERBOSE(BSL_LS_BCM_TSN,
   6931                 (BSL_META_U(unit,
   6932                             "bcmi_esw_tsn_bk_info_cleanup\n")));
   6933 
   6934     BCM_IF_ERROR_RETURN(
   6935         tsn_bk_info_instance_get(unit, &bk_info));
   6936 
   6937     /* Free and clear the SR Auto Learn bookkeeping info structure */
   6938     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   6939 
   6940     if (NULL != al_bk_info->intf_bitmap) {
   6941         TSN_FREE(unit, al_bk_info->intf_bitmap, 0);
   6942         al_bk_info->intf_bitmap = NULL;
   6943     }
   6944     if (NULL != al_bk_info->group_data) {
   6945         TSN_FREE(unit, al_bk_info->group_data, 0);
   6946         al_bk_info->group_data = NULL;
   6947     }
   6948 
   6949     bk_data = &(al_bk_info->data);
   6950 
   6951     bcmi_esw_tsn_sr_auto_learn_free_flowset(
   6952         unit, bk_data->flowsets, bk_data->flowsets_cnt, FALSE);
   6953 
   6954     /* Reset to default setting */
   6955     al_bk_info->valid_count = 0;
   6956     al_bk_info->valid_sw_idx_start = 0;
   6957     al_bk_info->valid_sw_idx_end = 0;
   6958     al_bk_info->empty_sw_idx_start = 0;
   6959     al_bk_info->empty_sw_idx_end = 0;
   6960 
   6961     if (al_bk_info->mutex != NULL) {
   6962         sal_mutex_destroy(al_bk_info->mutex);
   6963         al_bk_info->mutex = NULL;
   6964     }
   6965 
   6966     if (al_bk_info->bk_mutex != NULL) {
   6967         sal_mutex_destroy(al_bk_info->bk_mutex);
   6968         al_bk_info->bk_mutex = NULL;
   6969     }
   6970 
   6971     al_bk_info->initialized = FALSE;
   6972     return BCM_E_NONE;
   6973 }
   6974 
   6975 /*
   6976  * Function:
   6977  *   bcmi_esw_tsn_sr_auto_learn_init
   6978  * Purpose:
   6979  *   create a default profile setting
   6980  * Parameters:
   6981  *   unit - (IN) Unit number
   6982  * Returns:
   6983  *   BCM_E_xxx
   6984  */
   6985 STATIC int
   6986 bcmi_esw_tsn_sr_auto_learn_init(int unit)
   6987 {
   6988     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   6989     bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL;
   6990 
   6991     TSN_FUNCTION_TRACE(unit, "IN");
   6992 
   6993     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   6994 
   6995     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   6996 
   6997     /* Create mutex */
   6998     al_bk_info->mutex = sal_mutex_create("auto_learn_mutex");
   6999     if (al_bk_info->mutex == NULL) {
   7000         return BCM_E_MEMORY;
   7001     }
   7002 
   7003     /* Create mutex */
   7004     al_bk_info->bk_mutex = sal_mutex_create("auto_learn_bk_mutex");
   7005     if (al_bk_info->bk_mutex == NULL) {
   7006         return BCM_E_MEMORY;
   7007     }
   7008 
   7009     al_bk_info->initialized = FALSE;
   7010 
   7011     TSN_FUNCTION_TRACE(unit, "OUT");
   7012     return BCM_E_NONE;
   7013 }
   7014 
   7015 /*
   7016  * Function:
   7017  *   bcmi_esw_tsn_sr_auto_learn_lazy_init
   7018  * Purpose:
   7019  *   create a default profile setting
   7020  * Parameters:
   7021  *   unit - (IN) Unit number
   7022  * Returns:
   7023  *   BCM_E_xxx
   7024  */
   7025 STATIC int
   7026 bcmi_esw_tsn_sr_auto_learn_lazy_init(int unit)
   7027 {
   7028     bcm_error_t rv = BCM_E_NONE;
   7029     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   7030     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   7031     const tsn_sr_auto_learn_info_t *al_dev_info = NULL;
   7032     bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL;
   7033     uint32 table_size, shr_bitdcl_size, bk_data_size;
   7034     char *table_name;
   7035     int i;
   7036 
   7037     TSN_FUNCTION_TRACE(unit, "IN");
   7038 
   7039     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   7040 
   7041     dev_info = bk_info->tsn_dev_info;
   7042     al_dev_info = dev_info->tsn_sr_auto_learn_info;
   7043     al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info);
   7044 
   7045     /*
   7046      * Lazy initialization,
   7047      * 1st initializ should be performed in auto_learn_group_create
   7048      */
   7049     if (TRUE == al_bk_info->initialized) {
   7050         /* 1st initialization has been triggered */
   7051         TSN_FUNCTION_TRACE(unit, "OUT : initialized");
   7052         return BCM_E_NONE;
   7053     }
   7054 
   7055     /* Check chip device info instance is valid or not */
   7056     if (NULL == al_dev_info) {
   7057         return BCM_E_UNAVAIL;
   7058     }
   7059 
   7060     table_name = al_dev_info->table_name;
   7061     rv = al_dev_info->table_size_get(unit, &table_size);
   7062     BCM_IF_ERROR_RETURN(rv);
   7063     /* table_size should large than 0 */
   7064     assert(table_size > 0);
   7065 
   7066     /* Allocate usage bitmap */
   7067     shr_bitdcl_size = SHR_BITALLOCSIZE(table_size);
   7068     TSN_ALLOC(unit, al_bk_info->intf_bitmap, SHR_BITDCL,
   7069               shr_bitdcl_size,
   7070               "SR Auto Learn bookkeeping intf_bitmap", 0, rv);
   7071     if (BCM_FAILURE(rv)) {
   7072         LOG_VERBOSE(BSL_LS_BCM_TSN,
   7073                     (BSL_META_U(unit,
   7074                                 "bcmi_esw_tsn_init: failed to "
   7075                                 "allocate memory\n")));
   7076         return rv;
   7077     }
   7078     sal_memset(al_bk_info->intf_bitmap, 0, shr_bitdcl_size);
   7079 
   7080     /* Allocate bcmi_esw_tsn_sr_auto_learn_group_bk_data_t */
   7081     bk_data_size =
   7082         sizeof(bcmi_esw_tsn_sr_auto_learn_group_bk_data_t) * table_size;
   7083     TSN_ALLOC(unit, al_bk_info->group_data,
   7084               bcmi_esw_tsn_sr_auto_learn_group_bk_data_t,
   7085               bk_data_size,
   7086               table_name, 0, rv);
   7087     if (BCM_FAILURE(rv)) {
   7088         LOG_VERBOSE(BSL_LS_BCM_TSN,
   7089                     (BSL_META_U(unit,
   7090                                 "bcmi_esw_tsn_init: failed to "
   7091                                 "allocate memory\n")));
   7092         return rv;
   7093     }
   7094     sal_memset(al_bk_info->group_data, 0, bk_data_size);
   7095 
   7096     /* Initialize default value */
   7097     for (i = 0; i < table_size; i++) {
   7098         al_bk_info->group_data[i].group_id =
   7099             BCMI_SR_AUTO_LEARN_GROUP_ID_INVALID;
   7100     }
   7101 
   7102     /* Initialize default valid & empty pointer */
   7103     al_bk_info->valid_count = 0;
   7104     al_bk_info->valid_sw_idx_start = 0;
   7105     al_bk_info->valid_sw_idx_end = 0;
   7106     al_bk_info->empty_sw_idx_start = 0;
   7107     al_bk_info->empty_sw_idx_end = table_size - 1;
   7108 
   7109     al_bk_info->data.enabled = FALSE;
   7110     bcm_tsn_sr_auto_learn_config_t_init(&(al_bk_info->data.config));
   7111 
   7112     /* For Lazy initialization */
   7113     al_bk_info->initialized = TRUE;
   7114 
   7115     /* Clear HW status if there is no valid one.*/
   7116     if (0 == al_bk_info->valid_count) {
   7117         rv = bcmi_esw_tsn_sr_auto_learn_hw_delete_all(unit);
   7118         if (BCM_FAILURE(rv)) {
   7119             LOG_ERROR(BSL_LS_BCM_TSN,
   7120                       (BSL_META_U(unit,
   7121                                   "Delete all HW resource failed(rv = %d)\n"),
   7122                                   rv));
   7123             return rv;
   7124         }
   7125     }
   7126 
   7127     TSN_FUNCTION_TRACE(unit, "OUT");
   7128     return BCM_E_NONE;
   7129 }
   7130 
   7131 /*
   7132  * Function:
   7133  *     bcmi_esw_tsn_sr_port_config_set
   7134  * Purpose:
   7135  *     Set SR configuration on a port
   7136  * Parameters:
   7137  *     unit             - (IN) unit number
   7138  *     port             - (IN) port to configure
   7139  *     config           - (IN) port SR configuration
   7140  * Returns:
   7141  *     BCM_E_XXX
   7142  * Notes:
   7143  */
   7144 STATIC int
   7145 bcmi_esw_tsn_sr_port_config_set(
   7146     int unit,
   7147     bcm_gport_t port,
   7148     bcm_tsn_sr_port_config_t *config)
   7149 {
   7150     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   7151     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   7152     const tsn_sr_port_dev_info_t *sr_port_config = NULL;
   7153 
   7154     if (config == NULL) {
   7155         return BCM_E_PARAM;
   7156     }
   7157     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   7158     dev_info = bk_info->tsn_dev_info;
   7159     if (dev_info == NULL) {
   7160         return BCM_E_UNAVAIL;
   7161     }
   7162     sr_port_config = dev_info->sr_port_info;
   7163     if ((sr_port_config == NULL) ||
   7164         (sr_port_config->sr_port_config_set == NULL)) {
   7165         return BCM_E_UNAVAIL;
   7166     }
   7167 
   7168     return sr_port_config->sr_port_config_set(unit, port, config);
   7169 }
   7170 
   7171 /*
   7172  * Function:
   7173  *     bcmi_esw_tsn_sr_port_config_get
   7174  * Purpose:
   7175  *     Get SR configuration from a port
   7176  * Parameters:
   7177  *     unit             - (IN) unit number
   7178  *     port             - (IN) port
   7179  *     config           - (OUT) port SR configuration
   7180  * Returns:
   7181  *     BCM_E_XXX
   7182  * Notes:
   7183  */
   7184 STATIC int
   7185 bcmi_esw_tsn_sr_port_config_get(
   7186     int unit,
   7187     bcm_gport_t port,
   7188     bcm_tsn_sr_port_config_t *config)
   7189 {
   7190     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   7191     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   7192     const tsn_sr_port_dev_info_t *sr_port_config = NULL;
   7193 
   7194     if (config == NULL) {
   7195         return BCM_E_PARAM;
   7196     }
   7197     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   7198     dev_info = bk_info->tsn_dev_info;
   7199     if (dev_info == NULL) {
   7200         return BCM_E_UNAVAIL;
   7201     }
   7202     sr_port_config = dev_info->sr_port_info;
   7203     if ((sr_port_config == NULL) ||
   7204         (sr_port_config->sr_port_config_get == NULL)) {
   7205         return BCM_E_UNAVAIL;
   7206     }
   7207 
   7208     return sr_port_config->sr_port_config_get(unit, port, config);
   7209 }
   7210 
   7211 #endif /* BCM_TSN_SR_SUPPORT */
   7212 
   7213 /*
   7214  * Function:
   7215  *      bcmi_esw_tsn_pri_map_dump_config
   7216  * Purpose:
   7217  *      dump the config of priority map
   7218  * Parameters:
   7219  *      unit - (IN) Unit number
   7220  *      prefix - (IN) Prefix string for dump message
   7221  *      config - (IN) Priority map config
   7222  * Returns:
   7223  *      none
   7224  */
   7225 STATIC void
   7226 bcmi_esw_tsn_pri_map_dump_config(
   7227     int unit,
   7228     char *prefix,
   7229     bcm_tsn_pri_map_config_t *config)
   7230 {
   7231     int i;
   7232     uint32 flags;
   7233 
   7234     LOG_VERBOSE(BSL_LS_BCM_TSN,
   7235                 (BSL_META_U(unit,
   7236                             "bcmi_esw_tsn_pri_map_dump_config\n")));
   7237 
   7238     if ((NULL == prefix) || (NULL == config)) {
   7239         return;
   7240     }
   7241 
   7242     if (bsl_check(bslLayerBcm, bslSourceTsn, bslSeverityDebug, unit)) {
   7243         LOG_DEBUG(BSL_LS_BCM_TSN,
   7244                   (BSL_META_U(unit,
   7245                               "bcmi_esw_tsn_pri_map_dump_config:\n")));
   7246         LOG_DEBUG(BSL_LS_BCM_TSN,
   7247                   (BSL_META_U(unit,
   7248                              "%s map_type %d, num_map_entries %d.\n"),
   7249                              prefix,
   7250                              config->map_type,
   7251                              config->num_map_entries
   7252                              ));
   7253 
   7254         for (i = 0; i < (config->num_map_entries); i++) {
   7255             flags = (config->map_entries[i].flags);
   7256             if (flags & BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET) {
   7257                 LOG_DEBUG(BSL_LS_BCM_TSN,
   7258                           (BSL_META_U(unit,
   7259                                       "%s map_entries[%d]: flow_offset %d.\n"),
   7260                                       prefix,
   7261                                       i,
   7262                                       config->map_entries[i].flow_offset
   7263                                       ));
   7264             }
   7265 
   7266             if (flags & BCM_TSN_PRI_MAP_ENTRY_NEW_INT_PRI) {
   7267                 LOG_DEBUG(BSL_LS_BCM_TSN,
   7268                           (BSL_META_U(unit,
   7269                                       "%s map_entries[%d]: new_int_pri %d.\n"),
   7270                                       prefix,
   7271                                       i,
   7272                                       config->map_entries[i].new_int_pri
   7273                                       ));
   7274             }
   7275 
   7276             if (flags & BCM_TSN_PRI_MAP_ENTRY_PROFILE_ID) {
   7277                 LOG_DEBUG(BSL_LS_BCM_TSN,
   7278                           (BSL_META_U(unit,
   7279                                       "%s map_entries[%d]: profile_id %d.\n"),
   7280                                       prefix,
   7281                                       i,
   7282                                       config->map_entries[i].profile_id
   7283                                       ));
   7284             }
   7285         }
   7286     }
   7287 }
   7288 
   7289 /*
   7290  * Function:
   7291  *      bcmi_esw_tsn_pri_map_cmp
   7292  * Purpose:
   7293  *      Check the priority mapping entry is the same or not.
   7294  * Parameters:
   7295  *      unit - (IN) Unit number
   7296  *      ent1 - (IN) priority mapping entry 1
   7297  *      ent2 - (IN) priority mapping entry 2
   7298   *     equal  - (OUT) identical flag.
   7299  * Returns:
   7300  *      BCM_E_NONE - Success.
   7301  *      BCM_E_PARAM - Fail. Wrong parameter
   7302  */
   7303 STATIC int
   7304 bcmi_esw_tsn_pri_map_cmp(
   7305     int unit,
   7306     bcm_tsn_pri_map_entry_t *ent1,
   7307     bcm_tsn_pri_map_entry_t *ent2,
   7308     uint8 *equal)
   7309 {
   7310     int compare_flow, compare_prof, compare_intp, compare_egate, compare_pgate;
   7311 
   7312     LOG_VERBOSE(BSL_LS_BCM_TSN,
   7313                 (BSL_META_U(unit,
   7314                             "bcmi_esw_tsn_pri_map_cmp\n")));
   7315 
   7316     if ((NULL == ent1) || (NULL == ent2) ||
   7317         (NULL == equal)) {
   7318         return BCM_E_PARAM;
   7319     }
   7320 
   7321     *equal = TRUE;
   7322 
   7323     /* If flags are different */
   7324     if (ent1->flags != ent2->flags) {
   7325         *equal = FALSE;
   7326         return BCM_E_NONE;
   7327     }
   7328 
   7329     /* Check which flags need to be compared */
   7330     compare_flow =
   7331         (ent1->flags & BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET) ?
   7332          TRUE : FALSE;
   7333     compare_intp =
   7334         (ent1->flags & BCM_TSN_PRI_MAP_ENTRY_PROFILE_ID) ?
   7335          TRUE : FALSE;
   7336     compare_prof =
   7337         (ent1->flags & BCM_TSN_PRI_MAP_ENTRY_NEW_INT_PRI) ?
   7338          TRUE : FALSE;
   7339     compare_egate =
   7340         (ent1->flags & BCM_BCM_TSN_PRI_MAP_ENTRY_TAF_GATE_EXPRESS) ?
   7341          TRUE : FALSE;
   7342     compare_pgate =
   7343         (ent1->flags & BCM_BCM_TSN_PRI_MAP_ENTRY_TAF_GATE_PREEMPT) ?
   7344          TRUE : FALSE;
   7345 
   7346     /* If any different found */
   7347     if ((compare_flow && (ent1->flow_offset != ent2->flow_offset)) ||
   7348         (compare_intp && (ent1->new_int_pri != ent2->new_int_pri)) ||
   7349         (compare_prof && (ent1->profile_id != ent2->profile_id)) ||
   7350         (compare_egate && (ent1->taf_gate_express != ent2->taf_gate_express)) ||
   7351         (compare_pgate && (ent1->taf_gate_preempt != ent2->taf_gate_preempt)))
   7352     {
   7353         *equal = FALSE;
   7354     }
   7355     return BCM_E_NONE;
   7356 }
   7357 
   7358 /*
   7359  * Function:
   7360  *      bcmi_esw_tsn_pri_map_id_existed_check
   7361  * Purpose:
   7362  *      Check the Priority Map ID exited or not.
   7363  * Parameters:
   7364  *      unit - (IN) Unit number
   7365  *      map_id - (OUT) Map ID
   7366  * Returns:
   7367  *      BCM_E_xxx
   7368  */
   7369 STATIC int
   7370 bcmi_esw_tsn_pri_map_id_existed_check(
   7371     int unit,
   7372     bcm_tsn_pri_map_t map_id)
   7373 {
   7374     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   7375     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   7376     const tsn_pri_map_info_t *pm_dev_info = NULL;
   7377     bcm_tsn_pri_map_type_t map_type;
   7378     uint32 sw_idx = MAP_ID_TO_SW_IDX(map_id);
   7379 
   7380     LOG_VERBOSE(BSL_LS_BCM_TSN,
   7381                 (BSL_META_U(unit,
   7382                             "bcmi_esw_tsn_pri_map_id_existed_check\n")));
   7383 
   7384     if (BCM_TSN_PRI_MAP_INVALID == map_id) {
   7385         return BCM_E_CONFIG;
   7386     }
   7387     map_type = PRI_MAP_TYPE_GET(map_id);
   7388 
   7389     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   7390 
   7391     /* Initialization check */
   7392     PRI_MAP_INIT(unit, map_type);
   7393 
   7394     dev_info = bk_info->tsn_dev_info;
   7395     pm_dev_info = dev_info->tsn_pri_map_info[map_type];
   7396 
   7397     /* Check if the map_id and sw_idx is in the reasonable range */
   7398     assert(pm_dev_info->table_size > 0);
   7399     if ((map_type >= bcmTsnPriMapTypeCount) ||
   7400         (sw_idx >= pm_dev_info->table_size)) {
   7401         return BCM_E_PARAM;
   7402     }
   7403 
   7404     if (PRI_MAP_INTF_GET(unit, map_type, sw_idx)) {
   7405         return BCM_E_NONE;
   7406     }
   7407     return BCM_E_NOT_FOUND;
   7408 }
   7409 
   7410 /*
   7411  * Function:
   7412  *      bcmi_esw_tsn_pri_map_existed_check
   7413  * Purpose:
   7414  *      Check the Priority Map configuration exited or not.
   7415  * Parameters:
   7416  *      unit - (IN) Unit number
   7417  *      config - (IN) Priority Map configuration
   7418  *      map_id - (OUT) Map ID
   7419  * Returns:
   7420  *      BCM_E_xxx
   7421  */
   7422 STATIC int
   7423 bcmi_esw_tsn_pri_map_existed_check(
   7424     int unit,
   7425     bcm_tsn_pri_map_config_t *config,
   7426     bcm_tsn_pri_map_t *map_id)
   7427 {
   7428     bcm_error_t rv = BCM_E_UNAVAIL;
   7429     int ent_idx, is_the_same;
   7430     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   7431     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   7432     const tsn_pri_map_info_t *pm_dev_info = NULL;
   7433     bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL;
   7434     bcmi_esw_tsn_pri_map_bk_info_data_t *bk_data = NULL;
   7435     bcm_tsn_pri_map_config_t *bk_config = NULL;
   7436     bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount;
   7437     uint32 sw_idx;
   7438     uint8 equal;
   7439 
   7440     LOG_VERBOSE(BSL_LS_BCM_TSN,
   7441                 (BSL_META_U(unit,
   7442                             "bcmi_esw_tsn_pri_map_existed_check\n")));
   7443 
   7444     if ((NULL == config) || (NULL == map_id)) {
   7445         return BCM_E_PARAM;
   7446     }
   7447     map_type = config->map_type;
   7448 
   7449     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   7450 
   7451     /* Initialization check */
   7452     PRI_MAP_INIT(unit, map_type);
   7453 
   7454     pm_bk_info = &(bk_info->tsn_pri_map_bk_info);
   7455     dev_info = bk_info->tsn_dev_info;
   7456     pm_dev_info = dev_info->tsn_pri_map_info[map_type];
   7457 
   7458     if ((map_type >= bcmTsnPriMapTypeCount) ||
   7459         (config->num_map_entries == 0) ||
   7460         (config->num_map_entries >
   7461          pm_dev_info->entry_size)) {
   7462         return BCM_E_PARAM;
   7463     }
   7464 
   7465     PRI_MAP_BK_LOCK(unit);
   7466     for (sw_idx = 0;
   7467          sw_idx < pm_dev_info->entry_size;
   7468          sw_idx++) {
   7469         is_the_same = TRUE;
   7470 
   7471         /* Non-used entry, return and continue to check new one */
   7472         if (PRI_MAP_INTF_GET(unit, map_type, sw_idx) == 0) {
   7473             continue;
   7474         }
   7475 
   7476         bk_data = &(pm_bk_info->data[map_type][sw_idx]);
   7477         bk_config = &(bk_data->config);
   7478 
   7479         /* Check if map_type is the same */
   7480         if ((bk_config->num_map_entries == config->num_map_entries)) {
   7481             for (ent_idx = 0; ent_idx < (config->num_map_entries); ent_idx++) {
   7482 
   7483                 /* Compare two entries if they're the same */
   7484                 rv = bcmi_esw_tsn_pri_map_cmp(unit,
   7485                         &(bk_config->map_entries[ent_idx]),
   7486                         &(config->map_entries[ent_idx]),
   7487                         &equal);
   7488                 if (BCM_FAILURE(rv)) {
   7489                     PRI_MAP_BK_UNLOCK(unit);
   7490                     return rv;
   7491                 }
   7492 
   7493                 /* The two entries are different */
   7494                 if (FALSE == equal) {
   7495                     is_the_same = FALSE;
   7496                     break;
   7497                 }
   7498             }
   7499             if (TRUE == is_the_same) {
   7500                 *map_id = pm_bk_info->data[map_type][sw_idx].map_id;
   7501                 PRI_MAP_BK_UNLOCK(unit);
   7502                 return BCM_E_EXISTS;
   7503             }
   7504         }
   7505     }
   7506     PRI_MAP_BK_UNLOCK(unit);
   7507     return BCM_E_NOT_FOUND;
   7508 }
   7509 
   7510 /*
   7511  * Function:
   7512  *      bcmi_esw_tsn_pri_map_hw_index_get
   7513  * Purpose:
   7514  *      Get HW memory base index with given map_id
   7515  * Parameters:
   7516  *      unit     - (IN) Unit number
   7517  *      map_id   - (IN) Map ID
   7518  *      map_type - (OUT) Priority Map Type
   7519  *      hw_index - (OUT) HW memory base index
   7520  * Returns:
   7521  *      BCM_E_xxx
   7522  */
   7523 int
   7524 bcmi_esw_tsn_pri_map_hw_index_get(
   7525     int unit,
   7526     bcm_tsn_pri_map_t map_id,
   7527     bcm_tsn_pri_map_type_t *map_type,
   7528     uint32 *hw_index)
   7529 {
   7530     bcm_error_t rv = BCM_E_UNAVAIL;
   7531     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   7532     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   7533     const tsn_pri_map_info_t *pm_dev_info = NULL;
   7534     uint32 sw_idx = MAP_ID_TO_SW_IDX(map_id);
   7535 
   7536     LOG_VERBOSE(BSL_LS_BCM_TSN,
   7537                 (BSL_META_U(unit,
   7538                             "bcmi_esw_tsn_pri_map_hw_index_get\n")));
   7539 
   7540     /* Parameter NULL error handling */
   7541     if (NULL == hw_index || NULL == map_type) {
   7542         return BCM_E_PARAM;
   7543     }
   7544 
   7545     /* Check if pri_map id existed */
   7546     rv = bcmi_esw_tsn_pri_map_id_existed_check(unit, map_id);
   7547     if (BCM_FAILURE(rv)) {
   7548         LOG_WARN(BSL_LS_BCM_TSN,
   7549                  (BSL_META_U(unit,
   7550                              "map_id(%d) doesn't exited, rv(%d)\n"),
   7551                              map_id,
   7552                              rv));
   7553         return rv;
   7554     }
   7555     *map_type = PRI_MAP_TYPE_GET(map_id);
   7556 
   7557     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   7558 
   7559     /* Initialization check */
   7560     PRI_MAP_INIT(unit, *map_type);
   7561 
   7562     dev_info = bk_info->tsn_dev_info;
   7563     pm_dev_info = dev_info->tsn_pri_map_info[*map_type];
   7564     if (NULL == pm_dev_info->tsn_pri_map_hw_index_get) {
   7565         return BCM_E_UNAVAIL;
   7566     }
   7567 
   7568     rv = pm_dev_info->tsn_pri_map_hw_index_get(unit, sw_idx, hw_index);
   7569     if (BCM_FAILURE(rv)) {
   7570         LOG_ERROR(BSL_LS_BCM_TSN,
   7571                   (BSL_META_U(unit,
   7572                               "HW operation failed(rv = %d)\n"),
   7573                               rv));
   7574         return rv;
   7575     }
   7576     return BCM_E_NONE;
   7577 }
   7578 
   7579 /*
   7580  * Function:
   7581  *      bcmi_esw_tsn_pri_map_map_id_get
   7582  * Purpose:
   7583  *      Get map_id with given HW memory base index
   7584  * Parameters:
   7585  *      unit     - (IN) Unit number
   7586  *      map_type - (IN) Priority Map Type
   7587  *      hw_index - (IN) HW memory base index
   7588  *      map_id   - (OUT) Map ID
   7589  * Returns:
   7590  *      BCM_E_xxx
   7591  */
   7592 int
   7593 bcmi_esw_tsn_pri_map_map_id_get(
   7594     int unit,
   7595     bcm_tsn_pri_map_type_t map_type,
   7596     uint32 hw_index,
   7597     bcm_tsn_pri_map_t *map_id)
   7598 {
   7599     bcm_error_t rv = BCM_E_UNAVAIL;
   7600     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   7601     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   7602     const tsn_pri_map_info_t *pm_dev_info = NULL;
   7603     uint32 sw_idx;
   7604 
   7605     LOG_VERBOSE(BSL_LS_BCM_TSN,
   7606                 (BSL_META_U(unit,
   7607                             "bcmi_esw_tsn_pri_map_map_id_get\n")));
   7608     /* Input parameters check. */
   7609     if (NULL == map_id) {
   7610         return (BCM_E_PARAM);
   7611     }
   7612 
   7613     if (tsn_bk_info[unit] == NULL) {
   7614         /* Using device specific info that need no bk_info */
   7615         BCM_IF_ERROR_RETURN(bcmi_esw_tsn_noninit_dev_info_get(unit, &dev_info));
   7616         if (NULL ==
   7617                 dev_info->tsn_pri_map_info[map_type]->tsn_pri_map_sw_idx_get) {
   7618             return BCM_E_UNAVAIL;
   7619         }
   7620         rv = dev_info->tsn_pri_map_info[map_type]->tsn_pri_map_sw_idx_get(
   7621                                                      unit, hw_index, &sw_idx);
   7622         if (BCM_FAILURE(rv)) {
   7623             LOG_ERROR(BSL_LS_BCM_TSN,
   7624                       (BSL_META_U(unit,
   7625                                   "HW operation failed(rv = %d)\n"),
   7626                                   rv));
   7627             return rv;
   7628         }
   7629         *map_id = SW_IDX_TO_MAP_ID(sw_idx, map_type);
   7630         return BCM_E_NONE;
   7631     }
   7632 
   7633     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   7634     /* Initialization check */
   7635     PRI_MAP_INIT(unit, map_type);
   7636 
   7637     dev_info = bk_info->tsn_dev_info;
   7638     pm_dev_info = dev_info->tsn_pri_map_info[map_type];
   7639     if (NULL == pm_dev_info->tsn_pri_map_sw_idx_get) {
   7640         return BCM_E_UNAVAIL;
   7641     }
   7642 
   7643     rv = pm_dev_info->tsn_pri_map_sw_idx_get(unit, hw_index, &sw_idx);
   7644     if (BCM_FAILURE(rv)) {
   7645         LOG_ERROR(BSL_LS_BCM_TSN,
   7646                   (BSL_META_U(unit,
   7647                               "HW operation failed(rv = %d)\n"),
   7648                               rv));
   7649         return rv;
   7650     }
   7651     *map_id = SW_IDX_TO_MAP_ID(sw_idx, map_type);
   7652     return BCM_E_NONE;
   7653 }
   7654 
   7655 /*
   7656  * Function:
   7657  *      bcmi_esw_tsn_pri_map_ref_cnt_dec
   7658  * Purpose:
   7659  *      Decrease reference cnt by 1 with given map_id
   7660  * Parameters:
   7661  *      unit   - (IN) Unit number
   7662  *      map_id - (IN) Map ID
   7663  * Returns:
   7664  *      BCM_E_xxx
   7665  */
   7666 int
   7667 bcmi_esw_tsn_pri_map_ref_cnt_dec(
   7668     int unit,
   7669     bcm_tsn_pri_map_t map_id)
   7670 {
   7671     bcm_error_t rv = BCM_E_UNAVAIL;
   7672     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   7673     bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL;
   7674     bcmi_esw_tsn_pri_map_bk_info_data_t *bk_data = NULL;
   7675     bcm_tsn_pri_map_type_t map_type = PRI_MAP_TYPE_GET(map_id);
   7676     uint32 sw_idx = MAP_ID_TO_SW_IDX(map_id);
   7677 
   7678     LOG_VERBOSE(BSL_LS_BCM_TSN,
   7679                 (BSL_META_U(unit,
   7680                             "bcmi_esw_tsn_pri_map_ref_cnt_dec\n")));
   7681 
   7682     /* Check if pri_map id existed */
   7683     rv = bcmi_esw_tsn_pri_map_id_existed_check(unit, map_id);
   7684     if (BCM_FAILURE(rv)) {
   7685         LOG_WARN(BSL_LS_BCM_TSN,
   7686                  (BSL_META_U(unit,
   7687                              "map_id(%d) doesn't exited, rv(%d)\n"),
   7688                              map_id,
   7689                              rv));
   7690         return rv;
   7691     }
   7692 
   7693     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   7694 
   7695     /* Initialization check */
   7696     PRI_MAP_INIT(unit, map_type);
   7697 
   7698     pm_bk_info = &(bk_info->tsn_pri_map_bk_info);
   7699 
   7700     PRI_MAP_BK_LOCK(unit);
   7701 
   7702     bk_data = &(pm_bk_info->data[map_type][sw_idx]);
   7703     if (bk_data->ref_cnt == 0) {
   7704         PRI_MAP_BK_UNLOCK(unit);
   7705         return BCM_E_FAIL;
   7706     }
   7707     bk_data->ref_cnt -= 1;
   7708     PRI_MAP_BK_UNLOCK(unit);
   7709     return BCM_E_NONE;
   7710 }
   7711 
   7712 /*
   7713  * Function:
   7714  *      bcmi_esw_tsn_pri_map_ref_cnt_inc
   7715  * Purpose:
   7716  *      Increase reference cnt by 1 with given map_id
   7717  * Parameters:
   7718  *      unit   - (IN) Unit number
   7719  *      map_id - (IN) Map ID
   7720  * Returns:
   7721  *      BCM_E_xxx
   7722  */
   7723 int
   7724 bcmi_esw_tsn_pri_map_ref_cnt_inc(
   7725     int unit,
   7726     bcm_tsn_pri_map_t map_id)
   7727 {
   7728     bcm_error_t rv = BCM_E_UNAVAIL;
   7729     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   7730     bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL;
   7731     bcmi_esw_tsn_pri_map_bk_info_data_t *bk_data = NULL;
   7732     bcm_tsn_pri_map_type_t map_type = PRI_MAP_TYPE_GET(map_id);
   7733     uint32 sw_idx = MAP_ID_TO_SW_IDX(map_id);
   7734 
   7735     LOG_VERBOSE(BSL_LS_BCM_TSN,
   7736                 (BSL_META_U(unit,
   7737                             "bcmi_esw_tsn_pri_map_ref_cnt_inc\n")));
   7738 
   7739     /* Check if pri_map id existed */
   7740     rv = bcmi_esw_tsn_pri_map_id_existed_check(unit, map_id);
   7741     if (BCM_FAILURE(rv)) {
   7742         LOG_WARN(BSL_LS_BCM_TSN,
   7743                  (BSL_META_U(unit,
   7744                              "map_id(%d) doesn't exited, rv(%d)\n"),
   7745                              map_id,
   7746                              rv));
   7747         return rv;
   7748     }
   7749     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   7750 
   7751     /* Initialization check */
   7752     PRI_MAP_INIT(unit, map_type);
   7753 
   7754     pm_bk_info = &(bk_info->tsn_pri_map_bk_info);
   7755 
   7756     PRI_MAP_BK_LOCK(unit);
   7757 
   7758     bk_data = &(pm_bk_info->data[map_type][sw_idx]);
   7759     bk_data->ref_cnt += 1;
   7760 
   7761     PRI_MAP_BK_UNLOCK(unit);
   7762     return BCM_E_NONE;
   7763 }
   7764 
   7765 /*
   7766  * Function:
   7767  *      bcmi_esw_tsn_pri_map_ref_cnt_get
   7768  * Purpose:
   7769  *      Get current reference cnt with given map_id
   7770  * Parameters:
   7771  *      unit    - (IN) Unit number
   7772  *      map_id  - (IN) Map ID
   7773  *      ref_cnt - (OUT) Reference cnt
   7774  * Returns:
   7775  *      BCM_E_xxx
   7776  */
   7777 int
   7778 bcmi_esw_tsn_pri_map_ref_cnt_get(
   7779     int unit,
   7780     bcm_tsn_pri_map_t map_id,
   7781     uint32 *ref_cnt)
   7782 {
   7783     bcm_error_t rv = BCM_E_UNAVAIL;
   7784     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   7785     bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL;
   7786     bcm_tsn_pri_map_type_t map_type = PRI_MAP_TYPE_GET(map_id);
   7787     uint32 sw_idx = MAP_ID_TO_SW_IDX(map_id);
   7788 
   7789     LOG_VERBOSE(BSL_LS_BCM_TSN,
   7790                 (BSL_META_U(unit,
   7791                             "bcmi_esw_tsn_pri_map_ref_cnt_get\n")));
   7792 
   7793     /* Parameter NULL error handling */
   7794     if (NULL == ref_cnt) {
   7795         return BCM_E_PARAM;
   7796     }
   7797 
   7798     /* Check if pri_map id existed */
   7799     rv = bcmi_esw_tsn_pri_map_id_existed_check(unit, map_id);
   7800     if (BCM_FAILURE(rv)) {
   7801         LOG_WARN(BSL_LS_BCM_TSN,
   7802                  (BSL_META_U(unit,
   7803                              "map_id(%d) doesn't exited, rv(%d)\n"),
   7804                              map_id,
   7805                              rv));
   7806         return rv;
   7807     }
   7808 
   7809     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   7810 
   7811     /* Initialization check */
   7812     PRI_MAP_INIT(unit, map_type);
   7813 
   7814     pm_bk_info = &(bk_info->tsn_pri_map_bk_info);
   7815 
   7816     *ref_cnt = pm_bk_info->data[map_type][sw_idx].ref_cnt;
   7817     return BCM_E_NONE;
   7818 }
   7819 
   7820 /*
   7821  * Function:
   7822  *      bcmi_esw_tsn_pri_map_get_empty_map_id
   7823  * Purpose:
   7824  *      Get a empty map_id for specific map type
   7825  * Parameters:
   7826  *      unit - (IN) Unit number
   7827  *      map_type - (IN) Priority Map Type
   7828  *      map_id - (OUT) Map ID
   7829  * Returns:
   7830  *      BCM_E_NONE - Success on finding a empty map_id
   7831  */
   7832 STATIC int
   7833 bcmi_esw_tsn_pri_map_get_empty_map_id(
   7834     int unit,
   7835     bcm_tsn_pri_map_type_t map_type,
   7836     bcm_tsn_pri_map_t *map_id)
   7837 {
   7838     bcm_error_t rv = BCM_E_UNAVAIL;
   7839     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   7840     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   7841     const tsn_pri_map_info_t *pm_dev_info = NULL;
   7842     bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL;
   7843     /* Empty id */
   7844     uint32 e_sw_idx;
   7845 
   7846     LOG_VERBOSE(BSL_LS_BCM_TSN,
   7847                 (BSL_META_U(unit,
   7848                             "bcmi_esw_tsn_pri_map_get_empty_map_id\n")));
   7849 
   7850     if (NULL == map_id) {
   7851         return BCM_E_PARAM;
   7852     }
   7853 
   7854     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   7855 
   7856     /* Initialization check */
   7857     PRI_MAP_INIT(unit, map_type);
   7858 
   7859     pm_bk_info = &(bk_info->tsn_pri_map_bk_info);
   7860     dev_info = bk_info->tsn_dev_info;
   7861     pm_dev_info = dev_info->tsn_pri_map_info[map_type];
   7862 
   7863     PRI_MAP_BK_LOCK(unit);
   7864     /* Already full, return E_RESOURCE */
   7865     if (pm_bk_info->valid_count[map_type] == pm_dev_info->table_size) {
   7866         PRI_MAP_BK_UNLOCK(unit);
   7867         return BCM_E_RESOURCE;
   7868     }
   7869 
   7870     /* Try to find an empty id */
   7871     for (e_sw_idx = pm_bk_info->empty_sw_idx_start[map_type];
   7872          e_sw_idx <= pm_bk_info->empty_sw_idx_end[map_type];
   7873          e_sw_idx++) {
   7874 
   7875         if (PRI_MAP_INTF_GET(unit, map_type, e_sw_idx) == 0) {
   7876             /* An empty id found, set bit map as used */
   7877             PRI_MAP_INTF_SET(unit, map_type, e_sw_idx);
   7878 
   7879             /* Update valid start and end */
   7880             if (pm_bk_info->valid_count[map_type] == 0) {
   7881                 pm_bk_info->valid_sw_idx_start[map_type] = e_sw_idx;
   7882                 pm_bk_info->valid_sw_idx_end[map_type] = e_sw_idx;
   7883             } else if (e_sw_idx < pm_bk_info->valid_sw_idx_start[map_type]) {
   7884                 pm_bk_info->valid_sw_idx_start[map_type] = e_sw_idx;
   7885             } else if (e_sw_idx > pm_bk_info->valid_sw_idx_end[map_type]) {
   7886                 pm_bk_info->valid_sw_idx_end[map_type] = e_sw_idx;
   7887             }
   7888 
   7889             pm_bk_info->valid_count[map_type]++;
   7890             *map_id = SW_IDX_TO_MAP_ID(e_sw_idx, map_type);
   7891 
   7892             /* Update the empty start, assume next one is real empty */
   7893             pm_bk_info->empty_sw_idx_start[map_type] = e_sw_idx + 1;
   7894 
   7895             /* An empty id found, break and return BCM_E_NONE */
   7896             rv = BCM_E_NONE;
   7897             break;
   7898         } else {
   7899             /* Not empty id */
   7900 
   7901             /* Update the empty start, assume next one is real empty */
   7902             pm_bk_info->empty_sw_idx_start[map_type] = e_sw_idx + 1;
   7903         }
   7904     }
   7905     PRI_MAP_BK_UNLOCK(unit);
   7906     return rv;
   7907 }
   7908 
   7909 /*
   7910  * Function:
   7911  *      bcmi_esw_tsn_pri_map_destroy_map_id
   7912  * Purpose:
   7913  *      Free the resource of map_id
   7914  * Parameters:
   7915  *      unit - (IN) Unit number
   7916  *      map_id - (IN) Map ID
   7917  * Returns:
   7918  *      BCM_E_NONE - Success on destroying the given map_id
   7919  */
   7920 STATIC int
   7921 bcmi_esw_tsn_pri_map_destroy_map_id(
   7922     int unit,
   7923     bcm_tsn_pri_map_t map_id)
   7924 {
   7925     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   7926     bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL;
   7927     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   7928     const tsn_pri_map_info_t *pm_dev_info = NULL;
   7929     bcm_tsn_pri_map_type_t map_type = PRI_MAP_TYPE_GET(map_id);
   7930     uint32 destroy_sw_idx = MAP_ID_TO_SW_IDX(map_id);
   7931     uint32 n_valid_sw_idx;
   7932 
   7933     LOG_VERBOSE(BSL_LS_BCM_TSN,
   7934                 (BSL_META_U(unit,
   7935                             "bcmi_esw_tsn_pri_map_destroy_map_id\n")));
   7936 
   7937     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   7938 
   7939     /* Initialization check */
   7940     PRI_MAP_INIT(unit, map_type);
   7941 
   7942     pm_bk_info = &(bk_info->tsn_pri_map_bk_info);
   7943     dev_info = bk_info->tsn_dev_info;
   7944     pm_dev_info = dev_info->tsn_pri_map_info[map_type];
   7945 
   7946     assert(pm_dev_info->table_size > 0);
   7947 
   7948     PRI_MAP_BK_LOCK(unit);
   7949     /* Destroy bit map */
   7950     PRI_MAP_INTF_CLR(unit, map_type, destroy_sw_idx);
   7951 
   7952     /* Update empty start and end */
   7953     if (destroy_sw_idx < pm_bk_info->empty_sw_idx_start[map_type]) {
   7954         pm_bk_info->empty_sw_idx_start[map_type] = destroy_sw_idx;
   7955     } else if (destroy_sw_idx > pm_bk_info->empty_sw_idx_end[map_type]) {
   7956         pm_bk_info->empty_sw_idx_end[map_type] = destroy_sw_idx;
   7957     }
   7958 
   7959     /* Update valid, find a next valid start or next valid end */
   7960     n_valid_sw_idx = destroy_sw_idx;
   7961     if (pm_bk_info->valid_count[map_type] > 1) {
   7962         if (n_valid_sw_idx == pm_bk_info->valid_sw_idx_start[map_type]) {
   7963             do {
   7964                 n_valid_sw_idx++;
   7965             } while (PRI_MAP_INTF_GET(unit, map_type, n_valid_sw_idx) == 0);
   7966             pm_bk_info->valid_sw_idx_start[map_type] = n_valid_sw_idx;
   7967         } else if (n_valid_sw_idx == pm_bk_info->valid_sw_idx_end[map_type]) {
   7968             do {
   7969                 n_valid_sw_idx--;
   7970             } while (PRI_MAP_INTF_GET(unit, map_type, n_valid_sw_idx) == 0);
   7971             pm_bk_info->valid_sw_idx_end[map_type] = n_valid_sw_idx;
   7972         }
   7973     }
   7974     pm_bk_info->valid_count[map_type]--;
   7975 
   7976     if (0 == pm_bk_info->valid_count[map_type]) {
   7977         pm_bk_info->valid_sw_idx_start[map_type] = 0;
   7978         pm_bk_info->valid_sw_idx_end[map_type] = 0;
   7979         pm_bk_info->empty_sw_idx_start[map_type] = 0;
   7980         pm_bk_info->empty_sw_idx_end[map_type] = pm_dev_info->table_size - 1;
   7981     }
   7982     PRI_MAP_BK_UNLOCK(unit);
   7983     return BCM_E_NONE;
   7984 }
   7985 
   7986 /*
   7987  * Function:
   7988  *   bcmi_esw_tsn_pri_map_tsn_sr_coldboot_init
   7989  * Purpose:
   7990  *   Restore bookkeeping information of TSN & SR priority map resource.
   7991  * Parameters:
   7992  *   unit - (IN) unit number
   7993  * Returns:
   7994  *   BCM_E_XXX
   7995  */
   7996 STATIC int
   7997 bcmi_esw_tsn_pri_map_tsn_sr_coldboot_init(int unit)
   7998 {
   7999     bcm_error_t rv = BCM_E_UNAVAIL;
   8000     uint32 sw_idx;
   8001     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   8002     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   8003     const tsn_pri_map_info_t *pm_dev_info = NULL;
   8004     bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount;
   8005 
   8006     LOG_VERBOSE(BSL_LS_BCM_TSN,
   8007                 (BSL_META_U(unit,
   8008                             "bcmi_esw_tsn_pri_map_tsn_sr_coldboot_init\n")));
   8009 
   8010 #if defined(BCM_WARM_BOOT_SUPPORT)
   8011     /* Warm boot should be false in cold boot case */
   8012     if (SOC_WARM_BOOT(unit)) {
   8013         return BCM_E_UNAVAIL;
   8014     }
   8015 #endif /* BCM_WARM_BOOT_SUPPORT */
   8016 
   8017     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   8018 
   8019     dev_info = bk_info->tsn_dev_info;
   8020 
   8021     /* Only init TSN & SR since there is only TSN and SR HW */
   8022     for (map_type = bcmTsnPriMapTypeTsnFlow;
   8023          map_type <= bcmTsnPriMapTypeSrFlow;
   8024          map_type++) {
   8025 
   8026         pm_dev_info = dev_info->tsn_pri_map_info[map_type];
   8027         if (NULL == pm_dev_info ||
   8028             (map_type == bcmTsnPriMapTypeTsnFlow &&
   8029              !soc_feature(unit, soc_feature_tsn)) ||
   8030             (map_type == bcmTsnPriMapTypeSrFlow &&
   8031              !soc_feature(unit, soc_feature_tsn_sr))) {
   8032             /* Need to check all map_type */
   8033             continue;
   8034         }
   8035 
   8036         assert(pm_dev_info->table_size > 0);
   8037         /*
   8038          * Do not need to init 1st profile, thus sw_idx start from 1
   8039          * 1st profile is always initialized in bcmi_esw_tsn_pri_map_init
   8040          */
   8041         for (sw_idx = 1;
   8042              sw_idx < (pm_dev_info->table_size);
   8043              sw_idx++) {
   8044             if (NULL == pm_dev_info->tsn_pri_map_delete) {
   8045                 return BCM_E_UNAVAIL;
   8046             }
   8047             /* Use delete for reset HW to default value */
   8048             rv = pm_dev_info->tsn_pri_map_delete(unit, sw_idx);
   8049             if (BCM_FAILURE(rv)) {
   8050                 LOG_ERROR(BSL_LS_BCM_TSN,
   8051                           (BSL_META_U(unit,
   8052                                       "HW operation failed(rv = %d)\n"),
   8053                                       rv));
   8054                 return rv;
   8055             }
   8056         }
   8057     }
   8058     return BCM_E_NONE;
   8059 }
   8060 
   8061 #if defined(BCM_WARM_BOOT_SUPPORT)
   8062 /*
   8063  * Function:
   8064  *   bcmi_esw_tsn_pri_map_tsn_sr_reload
   8065  * Purpose:
   8066  *   Restore bookkeeping information of TSN & SR priority map resource.
   8067  * Parameters:
   8068  *   unit - (IN) unit number
   8069  * Returns:
   8070  *   BCM_E_XXX
   8071  */
   8072 STATIC int
   8073 bcmi_esw_tsn_pri_map_tsn_sr_reload(int unit)
   8074 {
   8075     bcm_error_t rv = BCM_E_UNAVAIL;
   8076     uint32 sw_idx;
   8077     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   8078     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   8079     const tsn_pri_map_info_t *pm_dev_info = NULL;
   8080     bcm_tsn_pri_map_t map_id;
   8081     bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount;
   8082     bcm_tsn_pri_map_config_t config;
   8083 
   8084     LOG_VERBOSE(BSL_LS_BCM_TSN,
   8085                 (BSL_META_U(unit,
   8086                             "bcmi_esw_tsn_pri_map_tsn_sr_reload\n")));
   8087 
   8088     if (!SOC_WARM_BOOT(unit)) {
   8089         return BCM_E_UNAVAIL;
   8090     }
   8091 
   8092     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   8093 
   8094     dev_info = bk_info->tsn_dev_info;
   8095 
   8096     /* only recovery TSN & SR & TAF
   8097      * since MTU/STU wb is done by MTU/STU module
   8098      */
   8099     for (map_type = 0; map_type < bcmTsnPriMapTypeCount; map_type++) {
   8100 
   8101         if (map_type == bcmTsnPriMapTypeEgressMtuProfile ||
   8102             map_type == bcmTsnPriMapTypeEgressStuProfile ) {
   8103             continue;
   8104         }
   8105 
   8106         pm_dev_info = dev_info->tsn_pri_map_info[map_type];
   8107         if (NULL == pm_dev_info ||
   8108             (map_type == bcmTsnPriMapTypeTsnFlow &&
   8109              !soc_feature(unit, soc_feature_tsn)) ||
   8110             (map_type == bcmTsnPriMapTypeSrFlow &&
   8111              !soc_feature(unit, soc_feature_tsn_sr)) ||
   8112             (map_type == bcmTsnPriMapTypeTafGate &&
   8113              !soc_feature(unit, soc_feature_tsn_taf))) {
   8114             /* Need to check all map_type */
   8115             continue;
   8116         }
   8117 
   8118         assert(pm_dev_info->table_size > 0);
   8119         /*
   8120          * Do not need to check 1st profile, thus sw_idx start from 1
   8121          * 1st profile is always initialized in bcmi_esw_tsn_pri_map_init
   8122          */
   8123         for (sw_idx = 1;
   8124              sw_idx < (pm_dev_info->table_size);
   8125              sw_idx++) {
   8126             PRI_MAP_BK_LOCK(unit);
   8127             PRI_MAP_INTF_CLR(unit, map_type, sw_idx);
   8128             PRI_MAP_BK_UNLOCK(unit);
   8129             if (NULL == pm_dev_info->tsn_pri_map_wb_hw_existed ||
   8130                 NULL == pm_dev_info->tsn_pri_map_get) {
   8131                 return BCM_E_UNAVAIL;
   8132             }
   8133 
   8134             PRI_MAP_LOCK(unit);
   8135             rv = pm_dev_info->tsn_pri_map_wb_hw_existed(unit, sw_idx);
   8136             PRI_MAP_UNLOCK(unit);
   8137             if (BCM_SUCCESS(rv)) {
   8138                 /* rv = BCM_E_NONE means HW existed */
   8139 
   8140                 /* Set bit map as used */
   8141                 map_id = SW_IDX_TO_MAP_ID(sw_idx, map_type);
   8142                 PRI_MAP_BK_LOCK(unit);
   8143                 PRI_MAP_INTF_SET(unit, map_type, sw_idx);
   8144                 PRI_MAP_BK_UNLOCK(unit);
   8145 
   8146                 /* Restore SW database from HW */
   8147                 rv = pm_dev_info->tsn_pri_map_get(unit, sw_idx, &config);
   8148                 if (BCM_FAILURE(rv)) {
   8149                     PRI_MAP_BK_LOCK(unit);
   8150                     /* Clear SW usage bitmap */
   8151                     PRI_MAP_INTF_CLR(unit, map_type, sw_idx);
   8152                     PRI_MAP_BK_UNLOCK(unit);
   8153 
   8154                     LOG_ERROR(BSL_LS_BCM_TSN,
   8155                               (BSL_META_U(unit,
   8156                                           "Read from HW failed(rv = %d)\n"),
   8157                                           rv));
   8158                     return rv;
   8159                 }
   8160 
   8161                 /* Write via bcm set API to make sure bk info is also updated */
   8162                 bcm_esw_tsn_pri_map_set(unit, map_id, &config);
   8163             }
   8164         }
   8165     }
   8166     return BCM_E_NONE;
   8167 }
   8168 
   8169 /*
   8170  * Function:
   8171  *      bcmi_esw_tsn_pri_map_mtu_stu_wb_set
   8172  * Purpose:
   8173  *      Warmboot function provided for mtu/stu module doing warmboot recovery
   8174  *      MTU/STU modules should have config and map_id when doing warmboot
   8175  *      and this API is for MTU/STU modules to do WB recovery.
   8176  * Parameters:
   8177  *      unit   - (IN) Unit number
   8178  *      map_id - (IN) Map ID
   8179  *      config - (IN) Priority Map configuration
   8180  * Returns:
   8181  *      BCM_E_xxx
   8182  */
   8183 int
   8184 bcmi_esw_tsn_pri_map_mtu_stu_wb_set(
   8185     int unit,
   8186     bcm_tsn_pri_map_t map_id,
   8187     bcm_tsn_pri_map_config_t *config)
   8188 {
   8189     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   8190     bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL;
   8191     bcm_tsn_pri_map_type_t map_type = PRI_MAP_TYPE_GET(map_id);
   8192     uint32 wb_sw_idx = MAP_ID_TO_SW_IDX(map_id);
   8193 
   8194     LOG_VERBOSE(BSL_LS_BCM_TSN,
   8195                 (BSL_META_U(unit,
   8196                             "bcmi_esw_tsn_pri_map_mtu_stu_wb_set\n")));
   8197 
   8198     if (!SOC_WARM_BOOT(unit)) {
   8199         return BCM_E_UNAVAIL;
   8200     }
   8201 
   8202     /* Parameter NULL error handling */
   8203     if (NULL == config) {
   8204         return BCM_E_PARAM;
   8205     }
   8206 
   8207     /* Parameter check */
   8208     if (BCM_TSN_PRI_MAP_INVALID == map_id) {
   8209         return BCM_E_CONFIG;
   8210     }
   8211 
   8212     /* Check if the map_id encoding is MTU/STU */
   8213     if (!(PRI_MAP_ID_IS_TYPE(map_id, bcmTsnPriMapTypeEgressMtuProfile) ||
   8214         PRI_MAP_ID_IS_TYPE(map_id, bcmTsnPriMapTypeEgressStuProfile))) {
   8215         LOG_ERROR(BSL_LS_BCM_TSN,
   8216                   (BSL_META_U(unit,
   8217                               "This WB recovery API is only for MTU & STU"
   8218                               "Error map_id(%d)\n"),
   8219                               map_id));
   8220         return BCM_E_PARAM;
   8221     }
   8222 
   8223     /* Check if the config map_type is MTU/STU */
   8224     if (!((config->map_type == bcmTsnPriMapTypeEgressMtuProfile) ||
   8225         (config->map_type == bcmTsnPriMapTypeEgressStuProfile))) {
   8226         LOG_ERROR(BSL_LS_BCM_TSN,
   8227                   (BSL_META_U(unit,
   8228                               "This WB recovery API is only for MTU & STU"
   8229                               "Error map_type(%d)\n"),
   8230                               config->map_type));
   8231         return BCM_E_PARAM;
   8232     }
   8233 
   8234     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   8235 
   8236     /* Initialization check */
   8237     PRI_MAP_INIT(unit, map_type);
   8238 
   8239     pm_bk_info = &(bk_info->tsn_pri_map_bk_info);
   8240 
   8241     PRI_MAP_BK_LOCK(unit);
   8242 
   8243     /* Set bit map as used */
   8244     PRI_MAP_INTF_SET(unit, map_type, wb_sw_idx);
   8245 
   8246     /* Update valid start and end */
   8247     if (pm_bk_info->valid_count[map_type] == 0) {
   8248         pm_bk_info->valid_sw_idx_start[map_type] = wb_sw_idx;
   8249         pm_bk_info->valid_sw_idx_end[map_type] = wb_sw_idx;
   8250     } else if (wb_sw_idx < pm_bk_info->valid_sw_idx_start[map_type]) {
   8251         pm_bk_info->valid_sw_idx_start[map_type] = wb_sw_idx;
   8252     } else if (wb_sw_idx > pm_bk_info->valid_sw_idx_end[map_type]) {
   8253         pm_bk_info->valid_sw_idx_end[map_type] = wb_sw_idx;
   8254     }
   8255     pm_bk_info->valid_count[map_type]++;
   8256 
   8257     /* Update empty start and end */
   8258     if (pm_bk_info->empty_sw_idx_start[map_type] ==
   8259         pm_bk_info->empty_sw_idx_end[map_type]) {
   8260         /* Do nothing */
   8261     } else if (wb_sw_idx == pm_bk_info->empty_sw_idx_start[map_type]) {
   8262         /* Assume next one is real empty */
   8263         pm_bk_info->empty_sw_idx_start[map_type]++;
   8264     } else if (wb_sw_idx == pm_bk_info->empty_sw_idx_end[map_type]) {
   8265         /* Assume previous one is real empty */
   8266         pm_bk_info->empty_sw_idx_end[map_type]--;
   8267     }
   8268     PRI_MAP_BK_UNLOCK(unit);
   8269 
   8270     /* Write via bcm set API to make sure bk info is also updated */
   8271     bcm_esw_tsn_pri_map_set(unit, map_id, config);
   8272 
   8273     return BCM_E_NONE;
   8274 }
   8275 
   8276 #endif /* BCM_WARM_BOOT_SUPPORT */
   8277 
   8278 /*
   8279  * Function:
   8280  *      bcmi_esw_tsn_pri_map_create
   8281  * Purpose:
   8282  *      Add a priority map config to hardware.
   8283  * Parameters:
   8284  *      unit - (IN) Unit number
   8285  *      config - (IN) Priority Map configuration
   8286  *      map_id - (OUT) Map ID
   8287  * Returns:
   8288  *      BCM_E_xxx
   8289  */
   8290 STATIC int
   8291 bcmi_esw_tsn_pri_map_create(
   8292     int unit,
   8293     bcm_tsn_pri_map_config_t *config,
   8294     bcm_tsn_pri_map_t *map_id)
   8295 {
   8296     bcm_error_t rv, rv2;
   8297     int i;
   8298     uint32 sw_idx;
   8299     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   8300     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   8301     const tsn_pri_map_info_t *pm_dev_info = NULL;
   8302     bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL;
   8303     bcmi_esw_tsn_pri_map_bk_info_data_t *bk_data = NULL;
   8304     bcm_tsn_pri_map_config_t *bk_config = NULL;
   8305 
   8306     LOG_VERBOSE(BSL_LS_BCM_TSN,
   8307                 (BSL_META_U(unit,
   8308                             "bcmi_esw_tsn_pri_map_create\n")));
   8309 
   8310     /* Parameter NULL error handling */
   8311     if ((NULL == config) || (NULL == map_id)) {
   8312         return BCM_E_PARAM;
   8313     }
   8314 
   8315     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   8316 
   8317     /* Initialization check */
   8318     PRI_MAP_INIT(unit, config->map_type);
   8319 
   8320     pm_bk_info = &(bk_info->tsn_pri_map_bk_info);
   8321     dev_info = bk_info->tsn_dev_info;
   8322     pm_dev_info = dev_info->tsn_pri_map_info[config->map_type];
   8323 
   8324     if ((config->map_type < bcmTsnPriMapTypeTsnFlow) ||
   8325         (config->map_type >= bcmTsnPriMapTypeCount) ||
   8326         (config->num_map_entries != (pm_dev_info->entry_size))) {
   8327         LOG_ERROR(BSL_LS_BCM_TSN,
   8328                   (BSL_META_U(unit,
   8329                               "Error map_type(%d), num_map_entries(%d)\n"),
   8330                               config->map_type,
   8331                               config->num_map_entries));
   8332         return BCM_E_PARAM;
   8333     }
   8334 
   8335     PRI_MAP_LOCK(unit);
   8336 
   8337     /* Check if the same pri_map existed or not, return EXISTS if yes. */
   8338     rv = bcmi_esw_tsn_pri_map_existed_check(unit, config, map_id);
   8339     if (BCM_E_EXISTS == rv) {
   8340         LOG_WARN(BSL_LS_BCM_TSN,
   8341                  (BSL_META_U(unit,
   8342                              "config already existed, found map_id(%d)\n"),
   8343                              *map_id));
   8344         PRI_MAP_UNLOCK(unit);
   8345         return BCM_E_EXISTS;
   8346     } else if (BCM_E_NOT_FOUND != rv) {
   8347         LOG_WARN(BSL_LS_BCM_TSN,
   8348                  (BSL_META_U(unit,
   8349                              "find existed Priority Map config failed"
   8350                              "(rv = %d)\n"),
   8351                              rv));
   8352         PRI_MAP_UNLOCK(unit);
   8353         return rv;
   8354     }
   8355 
   8356     /* Get a SW empty map_id */
   8357     rv = bcmi_esw_tsn_pri_map_get_empty_map_id(
   8358             unit,
   8359             config->map_type,
   8360             map_id);
   8361     if (BCM_FAILURE(rv)) {
   8362         LOG_ERROR(BSL_LS_BCM_TSN,
   8363                   (BSL_META_U(unit,
   8364                               "no empty map_id(rv = %d)\n"),
   8365                               rv));
   8366         PRI_MAP_UNLOCK(unit);
   8367         return rv;
   8368     }
   8369 
   8370     /* Set the config to HW */
   8371     sw_idx = MAP_ID_TO_SW_IDX(*map_id);
   8372     if ((config->map_type == bcmTsnPriMapTypeEgressMtuProfile) ||
   8373         (config->map_type == bcmTsnPriMapTypeEgressStuProfile)) {
   8374         /*
   8375          * There is no HW operations for MTU/STU
   8376          * MTU/STU are stored in bookkeeping bcmi_esw_tsn_pri_map_bk_info_t
   8377          */
   8378     } else if (NULL == pm_dev_info->tsn_pri_map_set) {
   8379         /* Besides MTU/STU, instance should not be NULL */
   8380         PRI_MAP_UNLOCK(unit);
   8381         return BCM_E_UNAVAIL;
   8382     } else {
   8383         rv = pm_dev_info->tsn_pri_map_set(unit, sw_idx, config);
   8384 
   8385         if (BCM_FAILURE(rv)) {
   8386             LOG_ERROR(BSL_LS_BCM_TSN,
   8387                       (BSL_META_U(unit,
   8388                                   "write to HW failed(rv = %d)\n"),
   8389                                   rv));
   8390 
   8391             /* Destroy the map_id got from above */
   8392             rv2 = bcmi_esw_tsn_pri_map_destroy_map_id(unit, *map_id);
   8393             if (BCM_FAILURE(rv2)) {
   8394                 LOG_ERROR(BSL_LS_BCM_TSN,
   8395                           (BSL_META_U(unit,
   8396                                       "clear usage bitmap failed(rv = %d)\n"),
   8397                                       rv2));
   8398                 PRI_MAP_UNLOCK(unit);
   8399                 return rv2;
   8400             }
   8401 
   8402             PRI_MAP_UNLOCK(unit);
   8403             return rv;
   8404         }
   8405     }
   8406 
   8407     /* Increase reference cnt of MTU/STU profile_id */
   8408     if (config->map_type == bcmTsnPriMapTypeEgressMtuProfile ||
   8409         config->map_type == bcmTsnPriMapTypeEgressStuProfile) {
   8410         for (i = 0;
   8411              i < config->num_map_entries;
   8412              i++) {
   8413             if ((config->map_type == bcmTsnPriMapTypeEgressMtuProfile) &&
   8414                 (config->map_entries[i].flags &
   8415                  BCM_TSN_PRI_MAP_ENTRY_PROFILE_ID)) {
   8416                 /* Increase reference cnt of MTU profile_id */
   8417                 rv = bcmi_esw_tsn_mtu_profile_ref_inc(
   8418                         unit, config->map_entries[i].profile_id);
   8419             } else if (
   8420                 (config->map_type == bcmTsnPriMapTypeEgressStuProfile) &&
   8421                 (config->map_entries[i].flags &
   8422                  BCM_TSN_PRI_MAP_ENTRY_PROFILE_ID)) {
   8423                 /* Increase reference cnt of STU profile_id */
   8424                 rv = bcmi_esw_tsn_stu_profile_ref_inc(
   8425                         unit, config->map_entries[i].profile_id);
   8426             }
   8427             if (BCM_FAILURE(rv)) {
   8428                 PRI_MAP_UNLOCK(unit);
   8429                 LOG_ERROR(BSL_LS_BCM_TSN,
   8430                           (BSL_META_U(unit,
   8431                                       "Increase MTU / STU reference cnt failed"
   8432                                       "(rv = %d)\n"),
   8433                                       rv));
   8434                 return rv;
   8435             }
   8436 
   8437         }
   8438     }
   8439 
   8440     PRI_MAP_BK_LOCK(unit);
   8441     /* Update SW bookkeeping database */
   8442     bk_data = &(pm_bk_info->data[config->map_type][sw_idx]);
   8443     bk_data->map_id = *map_id;
   8444     bk_data->ref_cnt = 0;
   8445     bk_config = &(bk_data->config);
   8446     sal_memcpy(bk_config,
   8447                config,
   8448                sizeof(bcm_tsn_pri_map_config_t));
   8449     PRI_MAP_BK_UNLOCK(unit);
   8450     PRI_MAP_UNLOCK(unit);
   8451     return BCM_E_NONE;
   8452 }
   8453 
   8454 /*
   8455  * Function:
   8456  *      bcmi_esw_tsn_pri_map_set
   8457  * Purpose:
   8458  *      Set priority map config with the given map_id.
   8459  * Parameters:
   8460  *      unit - (IN) Unit number
   8461  *      map_id - (IN) Map ID
   8462  *      config - (IN) Priority Map configuration
   8463  * Returns:
   8464  *      BCM_E_xxx
   8465  */
   8466 STATIC int
   8467 bcmi_esw_tsn_pri_map_set(
   8468     int unit,
   8469     bcm_tsn_pri_map_t map_id,
   8470     bcm_tsn_pri_map_config_t *config)
   8471 {
   8472     bcm_error_t rv = BCM_E_UNAVAIL;
   8473     uint32 ref_cnt;
   8474     uint32 sw_idx;
   8475     bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount;
   8476     bcm_tsn_pri_map_t exisited_map_id;
   8477     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   8478     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   8479     const tsn_pri_map_info_t *pm_dev_info = NULL;
   8480     bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL;
   8481     bcmi_esw_tsn_pri_map_bk_info_data_t *bk_data = NULL;
   8482     bcm_tsn_pri_map_config_t *bk_config = NULL;
   8483 
   8484     LOG_VERBOSE(BSL_LS_BCM_TSN,
   8485                 (BSL_META_U(unit,
   8486                             "bcmi_esw_tsn_pri_map_set\n")));
   8487 
   8488     /* Parameter NULL error handling */
   8489     if (NULL == config) {
   8490         return BCM_E_PARAM;
   8491     }
   8492 
   8493     /* Parameter check */
   8494     if (BCM_TSN_PRI_MAP_INVALID == map_id) {
   8495         return BCM_E_CONFIG;
   8496     }
   8497 
   8498     bcmi_esw_tsn_pri_map_dump_config(unit, "config set", config);
   8499 
   8500     /* If parameter config->map_type is the same as map_type of map_id. */
   8501     map_type = PRI_MAP_TYPE_GET(map_id);
   8502     if ((config->map_type != map_type)) {
   8503         LOG_WARN(BSL_LS_BCM_TSN,
   8504                  (BSL_META_U(unit,
   8505                              "set wrong config to map_id(%d)\n"
   8506                              "map_type doesn't match\n"), map_id));
   8507         return BCM_E_PARAM;
   8508     }
   8509 
   8510     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   8511 
   8512     /* Initialization check */
   8513     PRI_MAP_INIT(unit, map_type);
   8514 
   8515     pm_bk_info = &(bk_info->tsn_pri_map_bk_info);
   8516     dev_info = bk_info->tsn_dev_info;
   8517     pm_dev_info = dev_info->tsn_pri_map_info[map_type];
   8518 
   8519     if ((config->map_type < bcmTsnPriMapTypeTsnFlow) ||
   8520         (config->map_type >= bcmTsnPriMapTypeCount) ||
   8521         (config->num_map_entries != (pm_dev_info->entry_size))) {
   8522         LOG_ERROR(BSL_LS_BCM_TSN,
   8523                   (BSL_META_U(unit,
   8524                               "Error map_type(%d), num_map_entries(%d)\n"),
   8525                               config->map_type,
   8526                               config->num_map_entries));
   8527         return BCM_E_PARAM;
   8528     }
   8529 
   8530     PRI_MAP_LOCK(unit);
   8531 
   8532     /* Check if pri_map id existed */
   8533     rv = bcmi_esw_tsn_pri_map_id_existed_check(unit, map_id);
   8534     if (BCM_FAILURE(rv)) {
   8535         PRI_MAP_UNLOCK(unit);
   8536         LOG_WARN(BSL_LS_BCM_TSN,
   8537                  (BSL_META_U(unit,
   8538                              "map_id(%d) doesn't exited, rv(%d)\n"),
   8539                              map_id,
   8540                              rv));
   8541         return rv;
   8542     }
   8543 
   8544     /* Check if the same pri_map existed or not */
   8545     rv = bcmi_esw_tsn_pri_map_existed_check(unit, config, &exisited_map_id);
   8546     if (BCM_E_EXISTS == rv) {
   8547         if (exisited_map_id == map_id) {
   8548             /* config is the same as config of current map_id */
   8549             LOG_WARN(BSL_LS_BCM_TSN,
   8550                      (BSL_META_U(unit,
   8551                                  "config is the same as the config "
   8552                                  "of current map_id(%d)\n"),
   8553                                  map_id));
   8554             PRI_MAP_UNLOCK(unit);
   8555             return BCM_E_NONE;
   8556         } else {
   8557             /* config is found on other map_id */
   8558             LOG_WARN(BSL_LS_BCM_TSN,
   8559                      (BSL_META_U(unit,
   8560                                  "config already existed, found map_id(%d)\n"),
   8561                                  exisited_map_id));
   8562             PRI_MAP_UNLOCK(unit);
   8563             return BCM_E_EXISTS;
   8564         }
   8565     }
   8566 
   8567     /* Check if there is any module using this pri_map id. */
   8568     rv = bcmi_esw_tsn_pri_map_ref_cnt_get(unit, map_id, &ref_cnt);
   8569     if (BCM_FAILURE(rv)) {
   8570         LOG_ERROR(BSL_LS_BCM_TSN,
   8571                   (BSL_META_U(unit,
   8572                               "get reference count error(rv = %d)\n"),
   8573                               rv));
   8574         PRI_MAP_UNLOCK(unit);
   8575         return rv;
   8576     }
   8577 
   8578     /* There is still other module using the pri_map id, return E_BUSY. */
   8579     if (ref_cnt != 0) {
   8580         LOG_WARN(BSL_LS_BCM_TSN,
   8581                  (BSL_META_U(unit,
   8582                              "unable to change the config of map_id(%d)\n"
   8583                              "is still used by other (%d) component.\n"),
   8584                              map_id,
   8585                              ref_cnt));
   8586         PRI_MAP_UNLOCK(unit);
   8587         return BCM_E_BUSY;
   8588     }
   8589 
   8590     /* Set the config to HW */
   8591     sw_idx = MAP_ID_TO_SW_IDX(map_id);
   8592     if ((map_type == bcmTsnPriMapTypeEgressMtuProfile) ||
   8593         (map_type == bcmTsnPriMapTypeEgressStuProfile)) {
   8594         /*
   8595          * There is no HW operations for MTU/STU
   8596          * MTU/STU are stored in bookkeeping bcmi_esw_tsn_pri_map_bk_info_t
   8597          */
   8598     } else if (NULL == pm_dev_info->tsn_pri_map_set) {
   8599         /* Besides MTU/STU, instance should not be NULL */
   8600         PRI_MAP_UNLOCK(unit);
   8601         return BCM_E_UNAVAIL;
   8602     } else {
   8603         rv = pm_dev_info->tsn_pri_map_set(unit, sw_idx, config);
   8604         if (BCM_FAILURE(rv)) {
   8605             LOG_ERROR(BSL_LS_BCM_TSN,
   8606                       (BSL_META_U(unit,
   8607                                   "write to HW failed(rv = %d)\n"),
   8608                                   rv));
   8609             PRI_MAP_UNLOCK(unit);
   8610             return rv;
   8611         }
   8612     }
   8613 
   8614     PRI_MAP_BK_LOCK(unit);
   8615     /* Update SW bookkeeping database */
   8616     bk_data = &(pm_bk_info->data[map_type][sw_idx]);
   8617     bk_config = &(bk_data->config);
   8618     sal_memcpy(bk_config,
   8619                config,
   8620                sizeof(bcm_tsn_pri_map_config_t));
   8621     PRI_MAP_BK_UNLOCK(unit);
   8622     PRI_MAP_UNLOCK(unit);
   8623 
   8624     return BCM_E_NONE;
   8625 }
   8626 
   8627 /*
   8628  * Function:
   8629  *      bcmi_esw_tsn_pri_map_get
   8630  * Purpose:
   8631  *      Get the priority map config with the given map_id.
   8632  * Parameters:
   8633  *      unit - (IN) Unit number
   8634  *      map_id - (IN) Map ID
   8635  *      config - (OUT) Priority Map configuration
   8636  * Returns:
   8637  *      BCM_E_xxx
   8638  */
   8639 STATIC int
   8640 bcmi_esw_tsn_pri_map_get(
   8641     int unit,
   8642     bcm_tsn_pri_map_t map_id,
   8643     bcm_tsn_pri_map_config_t *config)
   8644 {
   8645     bcm_error_t rv = BCM_E_UNAVAIL;
   8646     uint32 sw_idx;
   8647     bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount;
   8648     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   8649     bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL;
   8650     bcmi_esw_tsn_pri_map_bk_info_data_t *bk_data = NULL;
   8651     bcm_tsn_pri_map_config_t *bk_config = NULL;
   8652 
   8653     LOG_VERBOSE(BSL_LS_BCM_TSN,
   8654                 (BSL_META_U(unit,
   8655                             "bcmi_esw_tsn_pri_map_get\n")));
   8656 
   8657     /* Parameter NULL error handling */
   8658     if (NULL == config) {
   8659         return BCM_E_PARAM;
   8660     }
   8661 
   8662     /* Parameter check */
   8663     if (BCM_TSN_PRI_MAP_INVALID == map_id) {
   8664         return BCM_E_CONFIG;
   8665     }
   8666 
   8667     PRI_MAP_LOCK(unit);
   8668 
   8669     /* Check if pri_map id existed */
   8670     rv = bcmi_esw_tsn_pri_map_id_existed_check(unit, map_id);
   8671     if (BCM_FAILURE(rv)) {
   8672         PRI_MAP_UNLOCK(unit);
   8673         LOG_WARN(BSL_LS_BCM_TSN,
   8674                  (BSL_META_U(unit,
   8675                              "map_id(%d) doesn't exited, rv(%d)\n"),
   8676                              map_id,
   8677                              rv));
   8678         return rv;
   8679     }
   8680     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   8681 
   8682     pm_bk_info = &(bk_info->tsn_pri_map_bk_info);
   8683 
   8684     /* Get the config from SW bookkeeping database */
   8685     sw_idx = MAP_ID_TO_SW_IDX(map_id);
   8686     map_type = PRI_MAP_TYPE_GET(map_id);
   8687 
   8688     /* Initialization check */
   8689     PRI_MAP_INIT(unit, map_type);
   8690 
   8691     PRI_MAP_BK_LOCK(unit);
   8692     bk_data = &(pm_bk_info->data[map_type][sw_idx]);
   8693     bk_config = &(bk_data->config);
   8694     sal_memcpy(config,
   8695                bk_config,
   8696                sizeof(bcm_tsn_pri_map_config_t));
   8697     PRI_MAP_BK_UNLOCK(unit);
   8698     PRI_MAP_UNLOCK(unit);
   8699 
   8700     bcmi_esw_tsn_pri_map_dump_config(unit, "config get", config);
   8701     return BCM_E_NONE;
   8702 }
   8703 
   8704 /*
   8705  * Function:
   8706  *      bcmi_esw_tsn_pri_map_destroy
   8707  * Purpose:
   8708  *      Free the resource of map_id
   8709  * Parameters:
   8710  *      unit - (IN) Unit number
   8711  *      map_id - (IN) Priority Map ID
   8712  * Returns:
   8713  *      BCM_E_xxx
   8714  */
   8715 STATIC int
   8716 bcmi_esw_tsn_pri_map_destroy(
   8717     int unit,
   8718     bcm_tsn_pri_map_t map_id)
   8719 {
   8720     bcm_error_t rv = BCM_E_UNAVAIL;
   8721     int i;
   8722     uint32 ref_cnt;
   8723     uint32 sw_idx;
   8724     bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount;
   8725     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   8726     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   8727     const tsn_pri_map_info_t *pm_dev_info = NULL;
   8728     bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL;
   8729     bcmi_esw_tsn_pri_map_bk_info_data_t *bk_data = NULL;
   8730     bcm_tsn_pri_map_config_t *bk_config = NULL;
   8731 
   8732     /* Parameter check */
   8733     if (BCM_TSN_PRI_MAP_INVALID == map_id) {
   8734         return BCM_E_CONFIG;
   8735     }
   8736 
   8737     LOG_VERBOSE(BSL_LS_BCM_TSN,
   8738                 (BSL_META_U(unit,
   8739                             "bcmi_esw_tsn_pri_map_destroy\n")));
   8740 
   8741     PRI_MAP_LOCK(unit);
   8742 
   8743     /* Check if pri_map id existed */
   8744     rv = bcmi_esw_tsn_pri_map_id_existed_check(unit, map_id);
   8745     if (BCM_FAILURE(rv)) {
   8746         PRI_MAP_UNLOCK(unit);
   8747         LOG_WARN(BSL_LS_BCM_TSN,
   8748                  (BSL_META_U(unit,
   8749                              "map_id(%d) doesn't exited, rv(%d)\n"),
   8750                              map_id,
   8751                              rv));
   8752         return rv;
   8753     }
   8754     map_type = PRI_MAP_TYPE_GET(map_id);
   8755 
   8756     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   8757 
   8758     /* Initialization check */
   8759     PRI_MAP_INIT(unit, map_type);
   8760 
   8761     pm_bk_info = &(bk_info->tsn_pri_map_bk_info);
   8762     dev_info = bk_info->tsn_dev_info;
   8763     pm_dev_info = dev_info->tsn_pri_map_info[map_type];
   8764 
   8765     /* Check if there is any module using this pri_map id. */
   8766     rv = bcmi_esw_tsn_pri_map_ref_cnt_get(unit, map_id, &ref_cnt);
   8767     if (BCM_FAILURE(rv)) {
   8768         LOG_ERROR(BSL_LS_BCM_TSN,
   8769                   (BSL_META_U(unit,
   8770                               "get reference count error(rv = %d)\n"),
   8771                               rv));
   8772         PRI_MAP_UNLOCK(unit);
   8773         return rv;
   8774     }
   8775 
   8776     /* There is still other module using the pri_map id, return E_BUSY. */
   8777     if (ref_cnt != 0) {
   8778         LOG_WARN(BSL_LS_BCM_TSN,
   8779                  (BSL_META_U(unit,
   8780                              "unable to delete map_id(%d)\n"
   8781                              "is still used by other (%d) component.\n"),
   8782                              map_id,
   8783                              ref_cnt));
   8784         PRI_MAP_UNLOCK(unit);
   8785         return BCM_E_BUSY;
   8786     }
   8787     sw_idx = MAP_ID_TO_SW_IDX(map_id);
   8788 
   8789     /* Delete HW */
   8790     if ((map_type == bcmTsnPriMapTypeEgressMtuProfile) ||
   8791         (map_type == bcmTsnPriMapTypeEgressStuProfile)) {
   8792         /*
   8793          * There is no HW operations for MTU/STU
   8794          * MTU/STU are stored in bookkeeping bcmi_esw_tsn_pri_map_bk_info_t
   8795          */
   8796     } else if (NULL == pm_dev_info->tsn_pri_map_delete) {
   8797         /* Besides MTU/STU, instance should not be NULL */
   8798         PRI_MAP_UNLOCK(unit);
   8799         return BCM_E_UNAVAIL;
   8800     } else {
   8801         if (sw_idx == 0) {
   8802             /* cannot delete 1st default setting */
   8803             return BCM_E_NONE;
   8804         }
   8805         rv = pm_dev_info->tsn_pri_map_delete(unit, sw_idx);
   8806         if (BCM_FAILURE(rv)) {
   8807             LOG_ERROR(BSL_LS_BCM_TSN,
   8808                       (BSL_META_U(unit,
   8809                                   "Delete HW failed(rv = %d)\n"),
   8810                                   rv));
   8811             PRI_MAP_UNLOCK(unit);
   8812             return rv;
   8813         }
   8814     }
   8815 
   8816     /* Clear SW usage bitmap */
   8817     rv = bcmi_esw_tsn_pri_map_destroy_map_id(unit, map_id);
   8818     if (BCM_FAILURE(rv)) {
   8819         LOG_ERROR(BSL_LS_BCM_TSN,
   8820                   (BSL_META_U(unit,
   8821                               "clear usage bitmap failed(rv = %d)\n"),
   8822                               rv));
   8823         PRI_MAP_UNLOCK(unit);
   8824         return rv;
   8825     }
   8826 
   8827     bk_data = &(pm_bk_info->data[map_type][sw_idx]);
   8828     bk_config = &(bk_data->config);
   8829     /* Decrease reference cnt of MTU/STU profile_id */
   8830     if (map_type == bcmTsnPriMapTypeEgressMtuProfile ||
   8831         map_type == bcmTsnPriMapTypeEgressStuProfile) {
   8832         for (i = 0;
   8833              i < bk_config->num_map_entries;
   8834              i++) {
   8835             if ((map_type == bcmTsnPriMapTypeEgressMtuProfile) &&
   8836                 (bk_config->map_entries[i].flags &
   8837                  BCM_TSN_PRI_MAP_ENTRY_PROFILE_ID)) {
   8838                 /* Decrease reference cnt of MTU profile_id */
   8839                 rv = bcmi_esw_tsn_mtu_profile_ref_dec(
   8840                         unit, bk_config->map_entries[i].profile_id);
   8841             } else if ((map_type == bcmTsnPriMapTypeEgressStuProfile) &&
   8842                        (bk_config->map_entries[i].flags &
   8843                         BCM_TSN_PRI_MAP_ENTRY_PROFILE_ID)) {
   8844                 /* Decrease reference cnt of STU profile_id */
   8845                 rv = bcmi_esw_tsn_stu_profile_ref_dec(
   8846                         unit, bk_config->map_entries[i].profile_id);
   8847             }
   8848             if (BCM_FAILURE(rv)) {
   8849                 PRI_MAP_UNLOCK(unit);
   8850                 LOG_ERROR(BSL_LS_BCM_TSN,
   8851                           (BSL_META_U(unit,
   8852                                       "Decrease MTU / STU reference cnt failed"
   8853                                       "(rv = %d)\n"),
   8854                                       rv));
   8855                 return rv;
   8856             }
   8857         }
   8858     }
   8859     PRI_MAP_BK_LOCK(unit);
   8860 
   8861     /* Update SW bookkeeping database */
   8862     bk_data->map_id = BCM_TSN_PRI_MAP_INVALID;
   8863     bk_data->ref_cnt = 0;
   8864     sal_memset(bk_config,
   8865                0,
   8866                sizeof(bcm_tsn_pri_map_config_t));
   8867     PRI_MAP_BK_UNLOCK(unit);
   8868     PRI_MAP_UNLOCK(unit);
   8869 
   8870     return BCM_E_NONE;
   8871 }
   8872 
   8873 /*
   8874  * Function:
   8875  *      bcmi_esw_tsn_pri_map_traverse
   8876  * Purpose:
   8877  *      Traverse the priority map config information.
   8878  * Parameters:
   8879  *      unit - (IN) Unit number
   8880  *      cb - (IN) Traverse call back function
   8881  *      user_data - (IN) User data
   8882  * Returns:
   8883  *      BCM_E_xxx
   8884  */
   8885 STATIC int
   8886 bcmi_esw_tsn_pri_map_traverse(
   8887     int unit,
   8888     bcm_tsn_pri_map_traverse_cb cb,
   8889     void *user_data)
   8890 {
   8891     bcm_error_t rv = BCM_E_UNAVAIL;
   8892     uint32 sw_idx;
   8893     bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount;
   8894 
   8895     LOG_VERBOSE(BSL_LS_BCM_TSN,
   8896                 (BSL_META_U(unit,
   8897                             "bcmi_esw_tsn_pri_map_traverse\n")));
   8898 
   8899     if (NULL == cb) {
   8900         return BCM_E_PARAM;
   8901     }
   8902 
   8903     for (map_type = bcmTsnPriMapTypeTsnFlow;
   8904          map_type < bcmTsnPriMapTypeCount;
   8905          map_type++) {
   8906 
   8907         /* Initialization check */
   8908         PRI_MAP_INIT(unit, map_type);
   8909         PRI_MAP_LOCK(unit);
   8910         for (sw_idx = PRI_MAP_BK_INFO(unit)->valid_sw_idx_start[map_type];
   8911              sw_idx <= PRI_MAP_BK_INFO(unit)->valid_sw_idx_end[map_type];
   8912              sw_idx++) {
   8913 
   8914             if (PRI_MAP_INTF_GET(unit, map_type, sw_idx)) {
   8915                 /* Doing the user cb function with config */
   8916                 rv = cb(unit, SW_IDX_TO_MAP_ID(sw_idx, map_type), user_data);
   8917                 if (BCM_FAILURE(rv)) {
   8918                     PRI_MAP_UNLOCK(unit);
   8919                     return rv;
   8920                 }
   8921             }
   8922         }
   8923         PRI_MAP_UNLOCK(unit);
   8924     }
   8925     return BCM_E_NONE;
   8926 }
   8927 
   8928 /*
   8929  * Function:
   8930  *     bcmi_esw_tsn_pri_map_cleanup
   8931  * Purpose:
   8932  *     Internal function to clear the resource of the TSN module.
   8933  * Parameters:
   8934  *     unit             - (IN) unit number
   8935  * Returns:
   8936  *     BCM_E_XXX
   8937  */
   8938 STATIC int
   8939 bcmi_esw_tsn_pri_map_cleanup(int unit)
   8940 {
   8941     bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount;
   8942     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   8943     bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL;
   8944 
   8945     LOG_VERBOSE(BSL_LS_BCM_TSN,
   8946                 (BSL_META_U(unit,
   8947                             "bcmi_esw_tsn_pri_map_cleanup\n")));
   8948 
   8949     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   8950 
   8951     /* Free and clear the priority map bookkeeping info structure */
   8952     pm_bk_info = &(bk_info->tsn_pri_map_bk_info);
   8953 
   8954     for (map_type = bcmTsnPriMapTypeTsnFlow;
   8955          map_type < bcmTsnPriMapTypeCount;
   8956          map_type++) {
   8957         if (pm_bk_info->intf_bitmap[map_type] != NULL) {
   8958             TSN_FREE(unit, pm_bk_info->intf_bitmap[map_type], 0);
   8959             pm_bk_info->intf_bitmap[map_type] = NULL;
   8960         }
   8961         if (pm_bk_info->data[map_type] != NULL) {
   8962             TSN_FREE(unit, pm_bk_info->data[map_type], 0);
   8963             pm_bk_info->data[map_type] = NULL;
   8964         }
   8965 
   8966         /* Reset to default setting */
   8967         pm_bk_info->valid_count[map_type] = 0;
   8968         pm_bk_info->valid_sw_idx_start[map_type] = 0;
   8969         pm_bk_info->valid_sw_idx_end[map_type] = 0;
   8970         pm_bk_info->empty_sw_idx_start[map_type] = 0;
   8971         pm_bk_info->empty_sw_idx_end[map_type] = 0;
   8972     }
   8973 
   8974     if (pm_bk_info->mutex != NULL) {
   8975         sal_mutex_destroy(pm_bk_info->mutex);
   8976         pm_bk_info->mutex = NULL;
   8977     }
   8978 
   8979     if (pm_bk_info->bk_mutex != NULL) {
   8980         sal_mutex_destroy(pm_bk_info->bk_mutex);
   8981         pm_bk_info->bk_mutex = NULL;
   8982     }
   8983 
   8984     return BCM_E_NONE;
   8985 }
   8986 
   8987 
   8988 /*
   8989  * Function:
   8990  *      bcmi_tsn_pri_map_init
   8991  * Purpose:
   8992  *      create a default profile setting
   8993  * Parameters:
   8994  *      unit - (IN) Unit number
   8995  * Returns:
   8996  *      BCM_E_xxx
   8997  */
   8998 STATIC int
   8999 bcmi_esw_tsn_pri_map_init(int unit)
   9000 {
   9001     bcm_error_t rv = BCM_E_UNAVAIL;
   9002     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
   9003     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
   9004     const tsn_pri_map_info_t *pm_dev_info = NULL;
   9005     bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL;
   9006     int i, pri_map_id;
   9007     bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount;
   9008     bcm_tsn_pri_map_config_t config;
   9009     uint32 table_size, shr_bitdcl_size, bk_data_size;
   9010 
   9011     LOG_VERBOSE(BSL_LS_BCM_TSN,
   9012                 (BSL_META_U(unit,
   9013                             "bcmi_esw_tsn_pri_map_init\n")));
   9014 
   9015     /* error check when bit is not enough for bcm_tsn_pri_map_type */
   9016     assert((1 << (32 - BCMI_TSN_PRI_MAP_TYPE_SHIFT - 1)) >=
   9017             bcmTsnPriMapTypeCount);
   9018 
   9019     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
   9020 
   9021     pm_bk_info = &(bk_info->tsn_pri_map_bk_info);
   9022     dev_info = bk_info->tsn_dev_info;
   9023 
   9024     /* Check if all device info instances of Priority Map are NULL */
   9025     for (map_type = bcmTsnPriMapTypeTsnFlow;
   9026          map_type < bcmTsnPriMapTypeCount;
   9027          map_type++) {
   9028         pm_dev_info = dev_info->tsn_pri_map_info[map_type];
   9029         if (NULL != pm_dev_info) {
   9030             break;
   9031         }
   9032     }
   9033 
   9034     /* All device info instances of Priority Map are NULL */
   9035     if (map_type == bcmTsnPriMapTypeCount) {
   9036         LOG_WARN(BSL_LS_BCM_SWITCH,
   9037                  (BSL_META_U(unit,
   9038                              "Priority Map not supported:\n"
   9039                              "platform initialized, but none"
   9040                              "Priority Map services are available.\n")));
   9041         return BCM_E_UNAVAIL;
   9042     }
   9043 
   9044     LOG_VERBOSE(BSL_LS_BCM_TSN,
   9045                 (BSL_META_U(unit,
   9046                             "bcmi_esw_tsn_pri_map_init: Priority Map\n")));
   9047 
   9048     /* Allocate Priority Map bookkeeping resource, also do initialization */
   9049     for (map_type = bcmTsnPriMapTypeTsnFlow;
   9050          map_type < bcmTsnPriMapTypeCount;
   9051          map_type++) {
   9052 
   9053         pm_dev_info = dev_info->tsn_pri_map_info[map_type];
   9054         if (NULL == pm_dev_info ||
   9055             (map_type == bcmTsnPriMapTypeSrFlow &&
   9056              !soc_feature(unit, soc_feature_tsn_sr)) ||
   9057             (map_type == bcmTsnPriMapTypeEgressMtuProfile &&
   9058              !soc_feature(unit, soc_feature_tsn_mtu_stu)) ||
   9059             (map_type == bcmTsnPriMapTypeEgressStuProfile &&
   9060              !soc_feature(unit, soc_feature_tsn_mtu_stu)) ||
   9061             (map_type == bcmTsnPriMapTypeTafGate &&
   9062              !soc_feature(unit, soc_feature_tsn_taf))) {
   9063             /* Some chips only have some PriMapType */
   9064             continue;
   9065         }
   9066 
   9067         /* table_size should large than 0 */
   9068         assert(pm_dev_info->table_size > 0);
   9069         table_size = pm_dev_info->table_size;
   9070 
   9071         /* Allocate usage bitmap */
   9072         shr_bitdcl_size = SHR_BITALLOCSIZE(table_size);
   9073         TSN_ALLOC(unit, pm_bk_info->intf_bitmap[map_type], SHR_BITDCL,
   9074                   shr_bitdcl_size,
   9075                   "Priority bookkeeping intf_bitmap", 0, rv);
   9076         if (BCM_FAILURE(rv)) {
   9077             LOG_VERBOSE(BSL_LS_BCM_TSN,
   9078                         (BSL_META_U(unit,
   9079                                     "bcmi_esw_tsn_pri_map_init: failed to "
   9080                                     "allocate memory\n")));
   9081             return rv;
   9082         }
   9083         sal_memset(pm_bk_info->intf_bitmap[map_type], 0, shr_bitdcl_size);
   9084 
   9085         /* Allocate data */
   9086         bk_data_size =
   9087             sizeof(bcmi_esw_tsn_pri_map_bk_info_data_t) * table_size;
   9088         TSN_ALLOC(unit, pm_bk_info->data[map_type],
   9089                   bcmi_esw_tsn_pri_map_bk_info_data_t,
   9090                   bk_data_size,
   9091                   pm_dev_info->table_name, 0, rv);
   9092         if (BCM_FAILURE(rv)) {
   9093             LOG_VERBOSE(BSL_LS_BCM_TSN,
   9094                         (BSL_META_U(unit,
   9095                                     "bcmi_esw_tsn_pri_map_init: failed to "
   9096                                     "allocate memory\n")));
   9097             return rv;
   9098         }
   9099         sal_memset(pm_bk_info->data[map_type], 0, bk_data_size);
   9100 
   9101         /* Initialize default value */
   9102         for (i = 0; i < table_size; i++) {
   9103             pm_bk_info->data[map_type][i].map_id = BCM_TSN_PRI_MAP_INVALID;
   9104         }
   9105 
   9106         /* Initialize default valid & empty pointer */
   9107         pm_bk_info->valid_count[map_type] = 0;
   9108         pm_bk_info->valid_sw_idx_start[map_type] = 0;
   9109         pm_bk_info->valid_sw_idx_end[map_type] = 0;
   9110         pm_bk_info->empty_sw_idx_start[map_type] = 0;
   9111         pm_bk_info->empty_sw_idx_end[map_type] = table_size - 1;
   9112     }
   9113 
   9114     /* Create mutex */
   9115     pm_bk_info->mutex = sal_mutex_create("priority_map_mutex");
   9116     if (pm_bk_info->mutex == NULL) {
   9117         return BCM_E_MEMORY;
   9118     }
   9119 
   9120     /* Create bk_mutex */
   9121     pm_bk_info->bk_mutex = sal_mutex_create("priority_map_bk_mutex");
   9122     if (pm_bk_info->bk_mutex == NULL) {
   9123         return BCM_E_MEMORY;
   9124     }
   9125 
   9126     /* Create 1st default TSN profile */
   9127     map_type = bcmTsnPriMapTypeTsnFlow;
   9128     pm_dev_info = dev_info->tsn_pri_map_info[map_type];
   9129     bcm_tsn_pri_map_config_t_init(&config);
   9130     config.map_type = map_type;
   9131     config.num_map_entries = pm_dev_info->entry_size;
   9132     for (i = 0; i < config.num_map_entries; i++) {
   9133         bcm_tsn_pri_map_entry_t_init(&config.map_entries[i]);
   9134         config.map_entries[i].flags = BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET;
   9135         config.map_entries[i].flags |= BCM_TSN_PRI_MAP_ENTRY_NEW_INT_PRI;
   9136         config.map_entries[i].flow_offset = 0;
   9137         config.map_entries[i].new_int_pri = i;
   9138     }
   9139 
   9140     rv = bcmi_esw_tsn_pri_map_create(unit, &config, &pri_map_id);
   9141     if (BCM_FAILURE(rv)) {
   9142         LOG_ERROR(BSL_LS_BCM_TSN,
   9143                   (BSL_META_U(unit,
   9144                               "create default TSN profile failed(rv = %d)\n"),
   9145                               rv));
   9146         return rv;
   9147     }
   9148 
   9149 #if defined(BCM_TSN_SR_SUPPORT)
   9150     if (soc_feature(unit, soc_feature_tsn_sr)) {
   9151         /* Create 1st default SR profile */
   9152         map_type = bcmTsnPriMapTypeSrFlow;
   9153         pm_dev_info = dev_info->tsn_pri_map_info[map_type];
   9154         bcm_tsn_pri_map_config_t_init(&config);
   9155         config.map_type = map_type;
   9156         config.num_map_entries = pm_dev_info->entry_size;
   9157         for (i = 0; i < config.num_map_entries; i++) {
   9158             bcm_tsn_pri_map_entry_t_init(&config.map_entries[i]);
   9159             config.map_entries[i].flags = BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET;
   9160             config.map_entries[i].flags |= BCM_TSN_PRI_MAP_ENTRY_NEW_INT_PRI;
   9161             config.map_entries[i].flow_offset = 0;
   9162             config.map_entries[i].new_int_pri = i;
   9163         }
   9164 
   9165         rv = bcmi_esw_tsn_pri_map_create(unit, &config, &pri_map_id);
   9166         if (BCM_FAILURE(rv)) {
   9167             LOG_ERROR(BSL_LS_BCM_TSN,
   9168                       (BSL_META_U(unit,
   9169                                   "create default SR profile failed"
   9170                                   "(rv = %d)\n"),
   9171                                   rv));
   9172             return rv;
   9173         }
   9174     }
   9175 #endif /* BCM_TSN_SR_SUPPORT */
   9176 
   9177     if (soc_feature(unit, soc_feature_tsn_taf)) {
   9178         /* reserve default taf profile at index 0 */
   9179         PRI_MAP_INTF_SET(unit, bcmTsnPriMapTypeTafGate, 0);
   9180     }
   9181     return BCM_E_NONE;
   9182 }
   9183 
   9184 /* TSN flow: free a chain of one or more continuous flow indexes */
   9185 STATIC int
   9186 bcmi_esw_tsn_flow_idx_free(int unit, tsn_flowidx_entry_t *entry)
   9187 {
   9188     bcmi_esw_tsn_bk_info_t *tsn_bk;
   9189     tsn_flows_bookkeeping_t *bkinfo;
   9190     tsn_flowidx_entry_t *fid, *prev, *last;
   9191     int eidx;
   9192 
   9193     /* parameter check */
   9194     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   9195     if (entry == NULL) {
   9196         return BCM_E_PARAM;
   9197     }
   9198 
   9199     /* Protect access to the flow indexes */
   9200     TSN_FLOW_MGMT_LOCK(unit);
   9201 
   9202     /* Traverse the list and insert the chain into the list */
   9203     bkinfo = &tsn_bk->tsn_flows;
   9204     eidx = entry->flow_idx;
   9205     prev = NULL;
   9206     for (fid = bkinfo->flowids_avail; fid != NULL; fid = fid->next) {
   9207 
   9208         /* If the index is smaller than current, insert before current */
   9209         if (eidx < fid->flow_idx) {
   9210             /* Find the last item in the supplied chain */
   9211             for (last = entry; last->next != NULL; last = last->next);
   9212             /* Connect remaining items to the chain */
   9213             last->next = fid;
   9214             /* Insert the chain to the list */
   9215             if (NULL == prev) {
   9216                 bkinfo->flowids_avail = entry;
   9217             } else {
   9218                 prev->next = entry;
   9219             }
   9220             TSN_FLOW_MGMT_UNLOCK(unit);
   9221             return BCM_E_NONE;
   9222         }
   9223 
   9224         /* all indexes should be different */
   9225         assert(eidx != fid->flow_idx);
   9226 
   9227         /* record the previous item */
   9228         prev = fid;
   9229     }
   9230 
   9231     /* The index is larger than all items in the list, append it at the end */
   9232     if (NULL == prev) {
   9233         bkinfo->flowids_avail = entry;
   9234     } else {
   9235         prev->next = entry;
   9236     }
   9237     TSN_FLOW_MGMT_UNLOCK(unit);
   9238     return BCM_E_NONE;
   9239 }
   9240 
   9241 /* TSN flow: allocate one or more continuous flow idx(s) */
   9242 STATIC int
   9243 bcmi_esw_tsn_flow_idx_allocate(
   9244     int unit,
   9245     int count,
   9246     tsn_flowidx_entry_t **entry)
   9247 {
   9248     bcmi_esw_tsn_bk_info_t *tsn_bk;
   9249     tsn_flows_bookkeeping_t *bkinfo;
   9250     tsn_flowidx_entry_t *fid, *begin, *prev, *bprev;
   9251     int idx, bidx;
   9252 
   9253     /* parameter check */
   9254     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   9255     if (count <= 0 || entry == NULL) {
   9256         return BCM_E_PARAM;
   9257     }
   9258 
   9259     /* Protect access to the flow indexes */
   9260     TSN_FLOW_MGMT_LOCK(unit);
   9261 
   9262     /* Check if any index is available */
   9263     bkinfo = &tsn_bk->tsn_flows;
   9264     if (NULL == bkinfo->flowids_avail) {
   9265         TSN_FLOW_MGMT_UNLOCK(unit);
   9266         return BCM_E_RESOURCE;
   9267     }
   9268 
   9269     /*
   9270      * Quick retrieval for typical case: count == 1.
   9271      */
   9272     if (1 == count) {
   9273         /* Get one entry from the head */
   9274         fid = bkinfo->flowids_avail;
   9275         bkinfo->flowids_avail = fid->next;
   9276         fid->next = NULL;
   9277         *entry = fid;
   9278         TSN_FLOW_MGMT_UNLOCK(unit);
   9279         return BCM_E_NONE;
   9280     }
   9281 
   9282     /* Traverse the list and search for enough continuous items to allocate */
   9283     idx = bidx = bkinfo->max_flows; /* invalid current index */
   9284     prev = bprev = begin = NULL;
   9285     for (fid = bkinfo->flowids_avail; fid != NULL; fid = fid->next) {
   9286 
   9287         /* Check if it's continuous */
   9288         if (idx + 1 != fid->flow_idx) {
   9289             /* Index not continuous, restart the searching */
   9290             idx = fid->flow_idx;
   9291             bidx = idx;
   9292             begin = fid;
   9293             bprev = prev;
   9294         } else if (fid->flow_idx - bidx + 1 == count) {
   9295 
   9296             /*
   9297              * Found enough continuous flow indexes: update and return
   9298              */
   9299 
   9300             /* Update the linked list by removing the chain from the list */
   9301             if (NULL == bprev) {
   9302                 /* The chain is the head */
   9303                 bkinfo->flowids_avail = fid->next;
   9304             } else {
   9305                 /* Connect previous one to the next of the chain */
   9306                 bprev->next = fid->next;
   9307             }
   9308 
   9309             /* Terminate this chain and return */
   9310             fid->next = NULL;
   9311             *entry = begin;
   9312             TSN_FLOW_MGMT_UNLOCK(unit);
   9313             return BCM_E_NONE;
   9314 
   9315         } else {
   9316             /* continuous but not yet reached the count */
   9317             idx++;
   9318         }
   9319 
   9320         /* record the previous one */
   9321         prev = fid;
   9322     }
   9323 
   9324     /* Cannot find enough continuous entries */
   9325     TSN_FLOW_MGMT_UNLOCK(unit);
   9326     return BCM_E_RESOURCE;
   9327 }
   9328 
   9329 /*
   9330  * De-allocate a TSN flowset and underlying flows with flowset index
   9331  * This function should be called with flowset mutex locked (if made public)
   9332  * and ref_count = 0.
   9333  */
   9334 STATIC int
   9335 bcmi_esw_tsn_flowset_free(int unit, int fsid)
   9336 {
   9337     bcmi_esw_tsn_bk_info_t *tsn_bk;
   9338     tsn_flows_bookkeeping_t *bkinfo;
   9339     tsn_flowset_t *fset;
   9340     int rv = BCM_E_NONE;
   9341 
   9342     /* parameter check */
   9343     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   9344     bkinfo = &tsn_bk->tsn_flows;
   9345     fset = &bkinfo->flowsets[fsid];
   9346 
   9347     /* Free flow indexes */
   9348     rv = bcmi_esw_tsn_flow_idx_free(unit, fset->flow_ide);
   9349 
   9350     /* Clear flowset data */
   9351     fset->flow_ide = NULL;
   9352     fset->num_flows = 0;
   9353 
   9354     return rv;
   9355 }
   9356 
   9357 /*
   9358  * Function:
   9359  *     bcmi_esw_tsn_flowset_destroy
   9360  * Purpose:
   9361  *     Destroy a TSN flowset.
   9362  * Parameters:
   9363  *     unit             - (IN) unit number
   9364  *     flowset          - (IN) flowset ID
   9365  * Returns:
   9366  *     BCM_E_XXX
   9367  * Notes:
   9368  */
   9369 STATIC int
   9370 bcmi_esw_tsn_flowset_destroy(int unit, bcm_tsn_flowset_t flowset)
   9371 {
   9372     bcmi_esw_tsn_bk_info_t *tsn_bk;
   9373     tsn_flows_bookkeeping_t *bkinfo;
   9374     tsn_flowset_t *fset;
   9375     int fsid;
   9376     int rv = BCM_E_NONE;
   9377     int i;
   9378 
   9379     /* parameter check */
   9380     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   9381     bkinfo = &tsn_bk->tsn_flows;
   9382     fsid = TSN_FLOWSET_ID_TO_IDX(flowset);
   9383     if (fsid < 0 || fsid >= bkinfo->max_flows) {
   9384         return BCM_E_PARAM;
   9385     }
   9386     fset = &bkinfo->flowsets[fsid];
   9387     if (fset->num_flows == 0) {
   9388         /* Not allocated */
   9389         return BCM_E_NOT_FOUND;
   9390     }
   9391 
   9392     /* Check if it's still in use */
   9393     TSN_FLOWSET_LOCK(fset);
   9394     if (fset->ref_count != 0) {
   9395         TSN_FLOWSET_UNLOCK(fset);
   9396         return BCM_E_BUSY;
   9397     }
   9398 
   9399     /* Handle per-flow specific clean up */
   9400     for (i = 0; i < fset->num_flows; i++) {
   9401         TSN_FLOW_LOCK(unit, fsid + i);
   9402         if (TSN_FLOW_MGMT_DEVINFO(unit)->clear_flow) {
   9403             (void)TSN_FLOW_MGMT_DEVINFO(unit)->clear_flow(unit, fsid + i);
   9404         }
   9405         if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   9406             (void)bcmi_esw_tsn_mtu_profile_ref_dec(
   9407                 unit, bkinfo->flows[fsid + i].ingress_mtu_profile);
   9408         }
   9409         TSN_FLOW_UNLOCK(unit, fsid + i);
   9410     }
   9411 
   9412     /* De-allocate the flowset (note that mutex is always there) */
   9413     rv = bcmi_esw_tsn_flowset_free(unit, fsid);
   9414     TSN_FLOWSET_UNLOCK(fset);
   9415     return rv;
   9416 }
   9417 
   9418 /* Allocate a TSN flowset */
   9419 STATIC int
   9420 bcmi_esw_tsn_flowset_alloc(
   9421     int unit,
   9422     bcm_tsn_pri_map_t pri_map,
   9423     int *pfsid)
   9424 {
   9425     bcmi_esw_tsn_bk_info_t *tsn_bk;
   9426     tsn_flows_bookkeeping_t *bkinfo;
   9427     bcm_tsn_pri_map_config_t pmcfg;
   9428     tsn_flowidx_entry_t *fids;
   9429     tsn_flowset_t *fset;
   9430     int fsid;
   9431     int num_flows;
   9432     int rv;
   9433     int i;
   9434 
   9435     /* parameter check */
   9436     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   9437     if (pfsid == NULL) {
   9438         return BCM_E_PARAM;
   9439     }
   9440     bkinfo = &tsn_bk->tsn_flows;
   9441 
   9442     /* Get number of flows from this priority map */
   9443     num_flows = 1;
   9444     if (pri_map != BCM_TSN_PRI_MAP_INVALID) {
   9445         /* call API to get priority map configuration */
   9446         rv = bcm_esw_tsn_pri_map_get(unit, pri_map, &pmcfg);
   9447         if (BCM_FAILURE(rv) || pmcfg.map_type != bcmTsnPriMapTypeTsnFlow) {
   9448             return BCM_E_PARAM;
   9449         }
   9450         /* Number of flows is max flow offset + 1 */
   9451         for (i = 0; i < pmcfg.num_map_entries; i++) {
   9452             if ((pmcfg.map_entries[i].flags &
   9453                  BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET) &&
   9454                 (pmcfg.map_entries[i].flow_offset > num_flows - 1)) {
   9455                 num_flows = pmcfg.map_entries[i].flow_offset + 1;
   9456             }
   9457         }
   9458     }
   9459 
   9460     /* Allocate flow indexes */
   9461     rv = bcmi_esw_tsn_flow_idx_allocate(unit, num_flows, &fids);
   9462     if (BCM_FAILURE(rv)) {
   9463         return rv;
   9464     }
   9465 
   9466     /*
   9467      * For efficiency and convenience, the flowset index is the base (first)
   9468      * flow index so that we don't need to have another set of flowset
   9469      * allocation/free mechanism which would take more time in this time
   9470      * critical operation.
   9471      */
   9472     fsid = fids->flow_idx;
   9473     assert(fsid >= 0 && fsid + num_flows <= bkinfo->max_flows);
   9474 
   9475     /* Write to the flowset */
   9476     fset = &bkinfo->flowsets[fsid];
   9477     TSN_FLOWSET_LOCK(fset);
   9478     assert(fset->num_flows == 0);
   9479     fset->map_id = pri_map;
   9480     fset->flow_ide = fids;
   9481     fset->ref_count = 0;
   9482     fset->num_flows = num_flows;
   9483     TSN_FLOWSET_UNLOCK(fset);
   9484 
   9485     /* Return the allocated flowset index */
   9486     *pfsid = fsid;
   9487     return BCM_E_NONE;
   9488 }
   9489 
   9490 /*
   9491  * Function:
   9492  *     bcmi_esw_tsn_flowset_create
   9493  * Purpose:
   9494  *     Create a TSN flowset.
   9495  * Parameters:
   9496  *     unit             - (IN) unit number
   9497  *     pri_map          - (IN) TSN priority map ID
   9498  *     def_cfg          - (IN) default flow configuration
   9499  *     flowset          - (OUT) flowset ID
   9500  * Returns:
   9501  *     BCM_E_XXX
   9502  * Notes:
   9503  */
   9504 STATIC int
   9505 bcmi_esw_tsn_flowset_create(
   9506     int unit,
   9507     bcm_tsn_pri_map_t pri_map,
   9508     bcm_tsn_flow_config_t *def_cfg,
   9509     bcm_tsn_flowset_t *flowset)
   9510 {
   9511     bcmi_esw_tsn_bk_info_t *tsn_bk;
   9512     tsn_flows_bookkeeping_t *bkinfo;
   9513     tsn_flowset_t *fset;
   9514     bcm_tsn_flowset_t flowset_id;
   9515     bcm_tsn_flow_config_t *flow;
   9516     int fsid;
   9517     int rv = BCM_E_NONE;
   9518     int i;
   9519 
   9520     /* parameter check */
   9521     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   9522     if (def_cfg == NULL || flowset == NULL) {
   9523         return BCM_E_PARAM;
   9524     }
   9525     bkinfo = &tsn_bk->tsn_flows;
   9526 
   9527     /* sanity check for platform specific routines */
   9528     if (!TSN_FLOW_MGMT_DEVINFO(unit)->check_flow_config ||
   9529         !TSN_FLOW_MGMT_DEVINFO(unit)->write_flow) {
   9530         return BCM_E_UNAVAIL;
   9531     }
   9532 
   9533     /* Validate flow configuration */
   9534     BCM_IF_ERROR_RETURN(
   9535         TSN_FLOW_MGMT_DEVINFO(unit)->check_flow_config(unit, def_cfg));
   9536 
   9537     /* Allocate flows and flowset. Basic init check is also done inside. */
   9538     BCM_IF_ERROR_RETURN(
   9539         bcmi_esw_tsn_flowset_alloc(unit, pri_map, &fsid));
   9540     flowset_id = TSN_FLOWSET_ID_FROM_IDX(fsid);
   9541 
   9542     /* Write to the flowset software copy */
   9543     fset = &bkinfo->flowsets[fsid];
   9544     TSN_FLOWSET_LOCK(fset);
   9545     sal_memcpy(&fset->config, def_cfg, sizeof(fset->config));
   9546 
   9547     /* Write to individual flows */
   9548     for (i = 0; i < fset->num_flows; i++) {
   9549         TSN_FLOW_LOCK(unit, fsid + i);
   9550         flow = &bkinfo->flows[fsid + i];
   9551 
   9552         /* Store the flow configuration */
   9553         sal_memcpy(flow, def_cfg, sizeof(*flow));
   9554 
   9555         /* Write to HW */
   9556         rv = TSN_FLOW_MGMT_DEVINFO(unit)->write_flow(unit, fsid + i, flow);
   9557         if (BCM_FAILURE(rv)) {
   9558             (void)bcmi_esw_tsn_flowset_destroy(unit, flowset_id);
   9559             TSN_FLOW_UNLOCK(unit, fsid + i);
   9560             TSN_FLOWSET_UNLOCK(fset);
   9561             return rv;
   9562         }
   9563         TSN_FLOW_UNLOCK(unit, fsid + i);
   9564     }
   9565     TSN_FLOWSET_UNLOCK(fset);
   9566 
   9567     /* Convert to user flowset ID */
   9568     *flowset = flowset_id;
   9569     return BCM_E_NONE;
   9570 }
   9571 
   9572 /*
   9573  * Function:
   9574  *     bcmi_esw_tsn_flowset_config_get
   9575  * Purpose:
   9576  *     Get default configuration for the specified TSN flowset
   9577  * Parameters:
   9578  *     unit             - (IN) unit number
   9579  *     flowset          - (IN) flowset ID
   9580  *     pri_map          - (OUT) TSN priority map ID
   9581  *     default_config   - (OUT) default flow configuration
   9582  * Returns:
   9583  *     BCM_E_XXX
   9584  * Notes:
   9585  */
   9586 STATIC int
   9587 bcmi_esw_tsn_flowset_config_get(
   9588     int unit,
   9589     bcm_tsn_flowset_t flowset,
   9590     bcm_tsn_pri_map_t *pri_map,
   9591     bcm_tsn_flow_config_t *config)
   9592 {
   9593     bcmi_esw_tsn_bk_info_t *tsn_bk;
   9594     tsn_flows_bookkeeping_t *bkinfo;
   9595     tsn_flowset_t *fset;
   9596     int fsid;
   9597 
   9598     /* parameter check */
   9599     if (pri_map == NULL || config == NULL) {
   9600         return BCM_E_PARAM;
   9601     }
   9602     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   9603     bkinfo = &tsn_bk->tsn_flows;
   9604     fsid = TSN_FLOWSET_ID_TO_IDX(flowset);
   9605     if (fsid < 0 || fsid >= bkinfo->max_flows) {
   9606         return BCM_E_PARAM;
   9607     }
   9608     fset = &bkinfo->flowsets[fsid];
   9609     TSN_FLOWSET_LOCK(fset);
   9610     if (fset->num_flows == 0) {
   9611         /* Not allocated */
   9612         TSN_FLOWSET_UNLOCK(fset);
   9613         return BCM_E_NOT_FOUND;
   9614     }
   9615 
   9616     /* Return the value */
   9617     *pri_map = fset->map_id;
   9618     sal_memcpy(config, &fset->config, sizeof(fset->config));
   9619     TSN_FLOWSET_UNLOCK(fset);
   9620     return BCM_E_NONE;
   9621 }
   9622 
   9623 /*
   9624  * Function:
   9625  *     bcmi_esw_tsn_flowset_status_get
   9626  * Purpose:
   9627  *     Get current status of specified TSN flowset
   9628  * Parameters:
   9629  *     unit             - (IN) unit number
   9630  *     flowset          - (IN) flowset ID
   9631  *     status           - (OUT) status structure
   9632  * Returns:
   9633  *     BCM_E_XXX
   9634  * Notes:
   9635  */
   9636 STATIC int
   9637 bcmi_esw_tsn_flowset_status_get(
   9638     int unit,
   9639     bcm_tsn_flowset_t flowset,
   9640     bcm_tsn_flowset_status_t *status)
   9641 {
   9642     bcmi_esw_tsn_bk_info_t *tsn_bk;
   9643     tsn_flows_bookkeeping_t *bkinfo;
   9644     tsn_flowset_t *fset;
   9645     int fsid;
   9646 
   9647     /* parameter check */
   9648     if (status == NULL) {
   9649         return BCM_E_PARAM;
   9650     }
   9651     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   9652     bkinfo = &tsn_bk->tsn_flows;
   9653     fsid = TSN_FLOWSET_ID_TO_IDX(flowset);
   9654     if (fsid < 0 || fsid >= bkinfo->max_flows) {
   9655         return BCM_E_PARAM;
   9656     }
   9657     fset = &bkinfo->flowsets[fsid];
   9658     TSN_FLOWSET_LOCK(fset);
   9659     if (fset->num_flows == 0) {
   9660         /* Not allocated */
   9661         TSN_FLOWSET_UNLOCK(fset);
   9662         return BCM_E_NOT_FOUND;
   9663     }
   9664 
   9665     /* Return the value */
   9666     status->active = fset->ref_count > 0 ?  1 : 0;
   9667     status->count = fset->num_flows;
   9668     TSN_FLOWSET_UNLOCK(fset);
   9669     return BCM_E_NONE;
   9670 }
   9671 
   9672 /*
   9673  * Function:
   9674  *     bcmi_esw_tsn_flowset_ref_inc
   9675  * Purpose:
   9676  *     Increase reference count for the specified TSN flowset
   9677  * Parameters:
   9678  *     unit             - (IN) unit number
   9679  *     flowset          - (IN) flowset ID
   9680  * Returns:
   9681  *     BCM_E_XXX
   9682  * Notes:
   9683  */
   9684 int
   9685 bcmi_esw_tsn_flowset_ref_inc(int unit, bcm_tsn_flowset_t flowset)
   9686 {
   9687     bcmi_esw_tsn_bk_info_t *tsn_bk;
   9688     tsn_flows_bookkeeping_t *bkinfo;
   9689     tsn_flowset_t *fset;
   9690     int fsid;
   9691 
   9692     /* parameter check */
   9693     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   9694     bkinfo = &tsn_bk->tsn_flows;
   9695     fsid = TSN_FLOWSET_ID_TO_IDX(flowset);
   9696     if (fsid < 0 || fsid >= bkinfo->max_flows) {
   9697         return BCM_E_PARAM;
   9698     }
   9699     fset = &bkinfo->flowsets[fsid];
   9700     TSN_FLOWSET_LOCK(fset);
   9701     if (fset->num_flows == 0) {
   9702         /* Not allocated */
   9703         TSN_FLOWSET_UNLOCK(fset);
   9704         return BCM_E_NOT_FOUND;
   9705     }
   9706 
   9707     /* Update the reference count */
   9708     fset->ref_count++;
   9709     TSN_FLOWSET_UNLOCK(fset);
   9710     return BCM_E_NONE;
   9711 }
   9712 
   9713 /*
   9714  * Function:
   9715  *     bcmi_esw_tsn_flowset_ref_dec
   9716  * Purpose:
   9717  *     Decrease reference count for the specified TSN flowset
   9718  * Parameters:
   9719  *     unit             - (IN) unit number
   9720  *     flowset          - (IN) flowset ID
   9721  * Returns:
   9722  *     BCM_E_XXX
   9723  * Notes:
   9724  */
   9725 int
   9726 bcmi_esw_tsn_flowset_ref_dec(int unit, bcm_tsn_flowset_t flowset)
   9727 {
   9728     bcmi_esw_tsn_bk_info_t *tsn_bk;
   9729     tsn_flows_bookkeeping_t *bkinfo;
   9730     tsn_flowset_t *fset;
   9731     int fsid;
   9732 
   9733     /* parameter check */
   9734     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   9735     bkinfo = &tsn_bk->tsn_flows;
   9736     fsid = TSN_FLOWSET_ID_TO_IDX(flowset);
   9737     if (fsid < 0 || fsid >= bkinfo->max_flows) {
   9738         return BCM_E_PARAM;
   9739     }
   9740     fset = &bkinfo->flowsets[fsid];
   9741     TSN_FLOWSET_LOCK(fset);
   9742     if (fset->num_flows == 0) {
   9743         /* Not allocated */
   9744         TSN_FLOWSET_UNLOCK(fset);
   9745         return BCM_E_NOT_FOUND;
   9746     }
   9747 
   9748     /* Update the reference count */
   9749     if (fset->ref_count > 0) {
   9750         fset->ref_count--;
   9751     }
   9752     TSN_FLOWSET_UNLOCK(fset);
   9753     return BCM_E_NONE;
   9754 }
   9755 
   9756 /*
   9757  * Function:
   9758  *     bcmi_esw_tsn_flowset_traverse
   9759  * Purpose:
   9760  *     Traverse all created TSN flowsets
   9761  * Parameters:
   9762  *     unit             - (IN) unit number
   9763  *     cb               - (IN) callback function
   9764  *     user_data        - (IN) user data supplied to the callback function
   9765  * Returns:
   9766  *     BCM_E_XXX
   9767  * Notes:
   9768  */
   9769 STATIC int
   9770 bcmi_esw_tsn_flowset_traverse(
   9771     int unit,
   9772     bcm_tsn_flowset_traverse_cb cb,
   9773     void *user_data)
   9774 {
   9775     bcmi_esw_tsn_bk_info_t *tsn_bk;
   9776     tsn_flows_bookkeeping_t *bkinfo;
   9777     tsn_flowset_t *fset;
   9778     int rv = BCM_E_NONE;
   9779     int i;
   9780 
   9781     /* parameter check */
   9782     if (cb == NULL) {
   9783         return BCM_E_PARAM;
   9784     }
   9785     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   9786 
   9787     /* Loop through the flowset array */
   9788     bkinfo = &tsn_bk->tsn_flows;
   9789     for (i = 0; i < bkinfo->max_flows; i++) {
   9790         fset = &bkinfo->flowsets[i];
   9791         TSN_FLOWSET_LOCK(fset);
   9792         if (fset->num_flows != 0) {
   9793             rv = cb(unit, TSN_FLOWSET_ID_FROM_IDX(i), user_data);
   9794         }
   9795         TSN_FLOWSET_UNLOCK(fset);
   9796         BCM_IF_ERROR_RETURN(rv);
   9797     }
   9798 
   9799     return BCM_E_NONE;
   9800 }
   9801 
   9802 /*
   9803  * Function:
   9804  *     bcmi_esw_tsn_flowset_flow_get
   9805  * Purpose:
   9806  *     Retrieve an individual TSN flow based on the flow offset from a flow set.
   9807  * Parameters:
   9808  *     unit             - (IN) unit number
   9809  *     flowset          - (IN) flowset ID
   9810  *     index            - (IN) index of the flow
   9811  *     flow_id          - (OUT) flow ID
   9812  * Returns:
   9813  *     BCM_E_XXX
   9814  * Notes:
   9815  */
   9816 STATIC int
   9817 bcmi_esw_tsn_flowset_flow_get(
   9818     int unit,
   9819     bcm_tsn_flowset_t flowset,
   9820     int index,
   9821     bcm_tsn_flow_t *flow_id)
   9822 {
   9823     bcmi_esw_tsn_bk_info_t *tsn_bk;
   9824     tsn_flows_bookkeeping_t *bkinfo;
   9825     tsn_flowset_t *fset;
   9826     int fsid;
   9827 
   9828     /* parameter check */
   9829     if (flow_id == NULL) {
   9830         return BCM_E_PARAM;
   9831     }
   9832     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   9833     bkinfo = &tsn_bk->tsn_flows;
   9834     fsid = TSN_FLOWSET_ID_TO_IDX(flowset);
   9835     if (fsid < 0 || fsid >= bkinfo->max_flows) {
   9836         return BCM_E_PARAM;
   9837     }
   9838     fset = &bkinfo->flowsets[fsid];
   9839     TSN_FLOWSET_LOCK(fset);
   9840     if (fset->num_flows == 0) {
   9841         /* Not allocated */
   9842         TSN_FLOWSET_UNLOCK(fset);
   9843         return BCM_E_NOT_FOUND;
   9844     }
   9845     if (index < 0 || index >= fset->num_flows) {
   9846         TSN_FLOWSET_UNLOCK(fset);
   9847         return BCM_E_PARAM;
   9848     }
   9849     assert(fsid + index < bkinfo->max_flows);
   9850 
   9851     /* Got SW flow ID */
   9852     *flow_id = (bcm_tsn_flow_t)TSN_FLOW_ID_FROM_IDX(fsid + index);
   9853     TSN_FLOWSET_UNLOCK(fset);
   9854     return BCM_E_NONE;
   9855 }
   9856 
   9857 /*
   9858  * Function:
   9859  *     bcmi_esw_tsn_flow_config_get
   9860  * Purpose:
   9861  *     Get configuration for the specified TSN flow
   9862  * Parameters:
   9863  *     unit             - (IN) unit number
   9864  *     flow_id          - (IN) flow ID
   9865  *     config           - (OUT) flow configuration
   9866  * Returns:
   9867  *     BCM_E_XXX
   9868  * Notes:
   9869  */
   9870 STATIC int
   9871 bcmi_esw_tsn_flow_config_get(
   9872     int unit,
   9873     bcm_tsn_flow_t flow_id,
   9874     bcm_tsn_flow_config_t *config)
   9875 {
   9876     bcmi_esw_tsn_bk_info_t *tsn_bk;
   9877     tsn_flows_bookkeeping_t *bkinfo;
   9878     int fidx;
   9879     int i;
   9880 
   9881     /* parameter check */
   9882     if (config == NULL) {
   9883         return BCM_E_PARAM;
   9884     }
   9885     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   9886     bkinfo = &tsn_bk->tsn_flows;
   9887     fidx = TSN_FLOW_ID_TO_IDX((int)flow_id);
   9888     if (fidx < 0 || fidx >= bkinfo->max_flows) {
   9889         return BCM_E_PARAM;
   9890     }
   9891 
   9892     /* Validate if it's from a flowset */
   9893     for (i = fidx; i >= 0; i--) {
   9894         if (bkinfo->flowsets[i].num_flows != 0) {
   9895             if (bkinfo->flowsets[i].num_flows > (fidx - i)) {
   9896                 break;
   9897             } else {
   9898                 return BCM_E_NOT_FOUND;
   9899             }
   9900         }
   9901     }
   9902     if (i == -1) {
   9903         /* No valid flowsets */
   9904         return BCM_E_NOT_FOUND;
   9905     }
   9906 
   9907     /* Return the configuration */
   9908     TSN_FLOW_LOCK(unit, fidx);
   9909     sal_memcpy(config, &bkinfo->flows[fidx], sizeof(*config));
   9910     TSN_FLOW_UNLOCK(unit, fidx);
   9911     return BCM_E_NONE;
   9912 }
   9913 
   9914 /*
   9915  * Function:
   9916  *     bcmi_esw_tsn_flow_config_set
   9917  * Purpose:
   9918  *     Set configuration for the specified TSN flow
   9919  * Parameters:
   9920  *     unit             - (IN) unit number
   9921  *     flow_id          - (IN) flow ID
   9922  *     config           - (IN) flow configuration
   9923  * Returns:
   9924  *     BCM_E_XXX
   9925  * Notes:
   9926  */
   9927 STATIC int
   9928 bcmi_esw_tsn_flow_config_set(
   9929     int unit,
   9930     bcm_tsn_flow_t flow_id,
   9931     bcm_tsn_flow_config_t *config)
   9932 {
   9933     bcmi_esw_tsn_bk_info_t *tsn_bk;
   9934     tsn_flows_bookkeeping_t *bkinfo;
   9935     tsn_flowset_t *fset;
   9936     int fidx;
   9937     int rv;
   9938     int i;
   9939 
   9940     /* parameter check */
   9941     if (config == NULL) {
   9942         return BCM_E_PARAM;
   9943     }
   9944     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
   9945     bkinfo = &tsn_bk->tsn_flows;
   9946     fidx = TSN_FLOW_ID_TO_IDX((int)flow_id);
   9947     if (fidx < 0 || fidx >= bkinfo->max_flows) {
   9948         return BCM_E_PARAM;
   9949     }
   9950 
   9951     /* Validate if it's from a flowset */
   9952     fset = NULL;
   9953     for (i = fidx; i >= 0; i--) {
   9954         if (bkinfo->flowsets[i].num_flows != 0) {
   9955             fset = &bkinfo->flowsets[i];
   9956             if (bkinfo->flowsets[i].num_flows > (fidx - i)) {
   9957                 break;
   9958             } else {
   9959                 return BCM_E_NOT_FOUND;
   9960             }
   9961         }
   9962     }
   9963     if (fset == NULL) {
   9964         /* No valid flowsets */
   9965         return BCM_E_NOT_FOUND;
   9966     }
   9967 
   9968     /* Validate flow configuration */
   9969     if (TSN_FLOW_MGMT_DEVINFO(unit)->check_flow_config) {
   9970         rv = TSN_FLOW_MGMT_DEVINFO(unit)->check_flow_config(unit, config);
   9971         if (BCM_FAILURE(rv)) {
   9972             return rv;
   9973         }
   9974     } else {
   9975         return BCM_E_UNAVAIL;
   9976     }
   9977 
   9978     /*
   9979      * Configure the flow using the supplied configuration
   9980      */
   9981     TSN_FLOWSET_LOCK(fset);
   9982     TSN_FLOW_LOCK(unit, fidx);
   9983     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   9984         /* Clear the old MTU profile id */
   9985         if (TSN_FLOW_MGMT_DEVINFO(unit)->clear_flow_mtu) {
   9986             rv = TSN_FLOW_MGMT_DEVINFO(unit)->clear_flow_mtu(
   9987                     unit, fidx);
   9988             if (BCM_FAILURE(rv)) {
   9989                 TSN_FLOW_UNLOCK(unit, fidx);
   9990                 TSN_FLOWSET_UNLOCK(fset);
   9991                 return rv;
   9992             }
   9993         } else {
   9994             TSN_FLOW_UNLOCK(unit, fidx);
   9995             TSN_FLOWSET_UNLOCK(fset);
   9996             return BCM_E_UNAVAIL;
   9997         }
   9998         (void)bcmi_esw_tsn_mtu_profile_ref_dec(
   9999             unit, bkinfo->flows[fidx].ingress_mtu_profile);
  10000     }
  10001     /* Copy to SW flow info */
  10002     sal_memcpy(&bkinfo->flows[fidx], config, sizeof(*config));
  10003     /* Write to HW */
  10004     if (TSN_FLOW_MGMT_DEVINFO(unit)->write_flow) {
  10005         rv = TSN_FLOW_MGMT_DEVINFO(unit)->write_flow(
  10006                 unit, fidx, &bkinfo->flows[fidx]);
  10007         if (BCM_FAILURE(rv)) {
  10008             TSN_FLOW_UNLOCK(unit, fidx);
  10009             TSN_FLOWSET_UNLOCK(fset);
  10010             return rv;
  10011         }
  10012     } else {
  10013         TSN_FLOW_UNLOCK(unit, fidx);
  10014         TSN_FLOWSET_UNLOCK(fset);
  10015         return BCM_E_UNAVAIL;
  10016     }
  10017     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  10018         (void)bcmi_esw_tsn_mtu_profile_ref_inc(
  10019             unit, bkinfo->flows[fidx].ingress_mtu_profile);
  10020     }
  10021     TSN_FLOW_UNLOCK(unit, fidx);
  10022     TSN_FLOWSET_UNLOCK(fset);
  10023     return BCM_E_NONE;
  10024 }
  10025 
  10026 
  10027 /*
  10028  * Function:
  10029  *     bcmi_esw_tsn_hw_flow_id_get
  10030  * Purpose:
  10031  *     Convert software TSN flow ID to hardware TSN flow ID
  10032  * Parameters:
  10033  *     unit             - (IN) unit number
  10034  *     flow_id          - (IN) SW flow ID
  10035  *     hw_id            - (OUT) HW flow ID
  10036  * Returns:
  10037  *     BCM_E_XXX
  10038  * Notes:
  10039  */
  10040 int
  10041 bcmi_esw_tsn_hw_flow_id_get(int unit, bcm_tsn_flow_t flow_id, uint32 *hw_id)
  10042 {
  10043     bcmi_esw_tsn_bk_info_t *tsn_bk;
  10044     tsn_flows_bookkeeping_t *bkinfo;
  10045     int fidx;
  10046 
  10047     /* parameter check */
  10048     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  10049     if (hw_id == NULL) {
  10050         return BCM_E_PARAM;
  10051     }
  10052     bkinfo = &tsn_bk->tsn_flows;
  10053     fidx = TSN_FLOW_ID_TO_IDX((int)flow_id);
  10054     if (fidx < 0 || fidx >= bkinfo->max_flows) {
  10055         return BCM_E_PARAM;
  10056     }
  10057 
  10058     /* Call platform specific routine to convert */
  10059     if (!TSN_FLOW_MGMT_DEVINFO(unit)->get_hw_flow_id) {
  10060         return BCM_E_UNAVAIL;
  10061     }
  10062     return TSN_FLOW_MGMT_DEVINFO(unit)->get_hw_flow_id(unit, fidx, hw_id);
  10063 }
  10064 
  10065 /*
  10066  * Function:
  10067  *     bcmi_esw_tsn_sw_flow_id_get
  10068  * Purpose:
  10069  *     Convert hardware TSN flow ID to software TSN flow ID
  10070  * Parameters:
  10071  *     unit             - (IN) unit number
  10072  *     hw_id            - (IN) HW flow ID
  10073  *     flow_id          - (OUT) SW flow ID
  10074  * Returns:
  10075  *     BCM_E_XXX
  10076  * Notes:
  10077  */
  10078 int
  10079 bcmi_esw_tsn_sw_flow_id_get(int unit, uint32 hw_id, bcm_tsn_flow_t *flow_id)
  10080 {
  10081     bcmi_esw_tsn_bk_info_t *tsn_bk;
  10082     tsn_flows_bookkeeping_t *bkinfo;
  10083     const bcmi_esw_tsn_dev_info_t *dev_info;
  10084     int fidx;
  10085 
  10086     /* parameter check */
  10087     if (flow_id == NULL) {
  10088         return BCM_E_PARAM;
  10089     }
  10090 
  10091     if (tsn_bk_info[unit] == NULL) {
  10092         /* Using device specific info that need no bk_info */
  10093         BCM_IF_ERROR_RETURN(bcmi_esw_tsn_noninit_dev_info_get(unit, &dev_info));
  10094         if (!dev_info->tsn_flows_info->get_sw_flow_idx) {
  10095             return BCM_E_UNAVAIL;
  10096         }
  10097         BCM_IF_ERROR_RETURN(dev_info->tsn_flows_info->get_sw_flow_idx(
  10098                                                         unit, hw_id, &fidx));
  10099         *flow_id = TSN_FLOW_ID_FROM_IDX(fidx);
  10100         return BCM_E_NONE;
  10101     }
  10102 
  10103     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  10104     bkinfo = &tsn_bk->tsn_flows;
  10105 
  10106     /* Call platform specific routine to convert */
  10107     if (!TSN_FLOW_MGMT_DEVINFO(unit)->get_sw_flow_idx) {
  10108         return BCM_E_UNAVAIL;
  10109     }
  10110     BCM_IF_ERROR_RETURN(
  10111         TSN_FLOW_MGMT_DEVINFO(unit)->get_sw_flow_idx(unit, hw_id, &fidx));
  10112 
  10113     /* Validate converted index */
  10114     if (fidx < 0 || fidx >= bkinfo->max_flows) {
  10115         return BCM_E_PARAM;
  10116     }
  10117 
  10118     /* Done */
  10119     *flow_id = TSN_FLOW_ID_FROM_IDX(fidx);
  10120     return BCM_E_NONE;
  10121 }
  10122 
  10123 /*
  10124  * Function:
  10125  *     bcmi_esw_tsn_flowset_identify
  10126  * Purpose:
  10127  *     TSN flow to flowset converstion (identify the flowset based on a flow)
  10128  * Parameters:
  10129  *     unit             - (IN) unit number
  10130  *     flow_id          - (IN) flow ID
  10131  *     flowset          - (OUT) flowset ID
  10132  * Returns:
  10133  *     BCM_E_XXX
  10134  * Notes:
  10135  */
  10136 int
  10137 bcmi_esw_tsn_flowset_identify(
  10138     int unit,
  10139     bcm_tsn_flow_t flow_id,
  10140     bcm_tsn_flowset_t *flowset)
  10141 {
  10142     bcmi_esw_tsn_bk_info_t *tsn_bk;
  10143     tsn_flows_bookkeeping_t *bkinfo;
  10144     int fidx;
  10145     int i;
  10146 
  10147     /* parameter check */
  10148     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  10149     if (flowset == NULL) {
  10150         return BCM_E_PARAM;
  10151     }
  10152     bkinfo = &tsn_bk->tsn_flows;
  10153     fidx = TSN_FLOW_ID_TO_IDX((int)flow_id);
  10154     if (fidx < 0 || fidx >= bkinfo->max_flows) {
  10155         return BCM_E_PARAM;
  10156     }
  10157 
  10158     /* Find the flowset */
  10159     for (i = fidx; i >= 0; i--) {
  10160         if (bkinfo->flowsets[i].num_flows != 0) {
  10161             if (bkinfo->flowsets[i].num_flows > (fidx - i)) {
  10162                 /* Convert to user flowset ID */
  10163                 *flowset = TSN_FLOWSET_ID_FROM_IDX(i);
  10164                 return BCM_E_NONE;
  10165             } else {
  10166                 /* The flow is not within this flowset */
  10167                 return BCM_E_NOT_FOUND;
  10168             }
  10169         }
  10170     }
  10171 
  10172     /* No flowset found with index less then the flow */
  10173     return BCM_E_NOT_FOUND;
  10174 }
  10175 
  10176 #ifdef BCM_WARM_BOOT_SUPPORT
  10177 /* TSN flow: allocate specified flow idx(s) for warmboot restore */
  10178 STATIC int
  10179 bcmi_esw_tsn_flow_idx_restore(
  10180     int unit,
  10181     int index,
  10182     int count,
  10183     tsn_flowidx_entry_t **entry)
  10184 {
  10185     bcmi_esw_tsn_bk_info_t *tsn_bk;
  10186     tsn_flows_bookkeeping_t *bkinfo;
  10187     tsn_flowidx_entry_t *fid, *prev, *bprev, *begin;
  10188 
  10189     /* parameter check */
  10190     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  10191     if (count <= 0 || entry == NULL) {
  10192         return BCM_E_PARAM;
  10193     }
  10194     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  10195     bkinfo = &tsn_bk->tsn_flows;
  10196 
  10197     /* Protect access to the flow indexes */
  10198     TSN_FLOW_MGMT_LOCK(unit);
  10199 
  10200     /* Traverse the list and search for the specified items */
  10201     begin = NULL;
  10202     prev = bprev = NULL;
  10203     for (fid = bkinfo->flowids_avail; fid != NULL; fid = fid->next) {
  10204         if (fid->flow_idx == index) {
  10205             if (begin == NULL) {
  10206                 /* Found the head */
  10207                 begin = fid;
  10208                 bprev = prev;
  10209             }
  10210 
  10211             /* Check if we have got all the items */
  10212             count--;
  10213             if (count == 0) {
  10214                 /* Done. Removing the chain from the list */
  10215                 if (NULL == bprev) {
  10216                     /* The chain was the head */
  10217                     bkinfo->flowids_avail = fid->next;
  10218                 } else {
  10219                     /* Connect previous one to the next of the chain */
  10220                     bprev->next = fid->next;
  10221                 }
  10222 
  10223                 /* Terminate this chain and return */
  10224                 fid->next = NULL;
  10225                 *entry = begin;
  10226                 TSN_FLOW_MGMT_UNLOCK(unit);
  10227                 return BCM_E_NONE;
  10228             }
  10229             index++;
  10230         } else if (fid->flow_idx > index) {
  10231             /* Not found in this sorted list */
  10232             break;
  10233         }
  10234 
  10235         /* record the previous one */
  10236         prev = fid;
  10237     }
  10238 
  10239     /* Cannot find the specified item or enough continuous entries */
  10240     TSN_FLOW_MGMT_UNLOCK(unit);
  10241     return BCM_E_INTERNAL;
  10242 }
  10243 
  10244 /* TSN flow management - warmboot scache size allocation */
  10245 STATIC int
  10246 bcmi_esw_tsn_flow_mgmt_wb_alloc(int unit)
  10247 {
  10248     bcmi_esw_tsn_bk_info_t *tsn_bk;
  10249     tsn_flows_bookkeeping_t *bkinfo;
  10250     soc_scache_handle_t scache_handle;
  10251     uint8 *scache_ptr = NULL;
  10252     int stable_size = 0;
  10253     int alloc_size;
  10254     int rv;
  10255 
  10256     /* parameter check */
  10257     if (!soc_feature(unit, soc_feature_tsn)) {
  10258         return BCM_E_UNAVAIL;
  10259     }
  10260     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  10261     bkinfo = &tsn_bk->tsn_flows;
  10262 
  10263     /* Requires extended scache support level-2 warmboot */
  10264     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
  10265     if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
  10266         return BCM_E_NONE;
  10267     }
  10268 
  10269     /* Calculate allocate size */
  10270     alloc_size = 0;
  10271     alloc_size += sizeof(uint16);       /* Number of actual flows */
  10272     alloc_size +=                       /* Allocated flows */
  10273         sizeof(tsn_flowset_wb_t) * bkinfo->max_flows;
  10274 
  10275     /* Allocate scache for warmboot */
  10276     SOC_SCACHE_HANDLE_SET(scache_handle, unit,
  10277                           BCM_MODULE_TSN, BCM_TSN_WB_SCACHE_PART_TSN_FLOWS);
  10278     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size,
  10279                                  &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL);
  10280     if (rv == BCM_E_NOT_FOUND) {
  10281         /* Proceed with level 1 warmboot */
  10282         rv = BCM_E_NONE;
  10283     }
  10284 
  10285     return rv;
  10286 }
  10287 
  10288 /* TSN flow management - sync information to scache */
  10289 STATIC int
  10290 bcmi_esw_tsn_flow_mgmt_sync(int unit)
  10291 {
  10292     bcmi_esw_tsn_bk_info_t *tsn_bk;
  10293     tsn_flows_bookkeeping_t *bkinfo;
  10294     soc_scache_handle_t scache_handle;
  10295     uint8 *scache_ptr = NULL, *scache;
  10296     tsn_flowset_wb_t tsnflow;
  10297     int stable_size = 0;
  10298     tsn_flowset_t *fset;
  10299     uint16 flows;
  10300     int rv;
  10301     int i;
  10302 
  10303     /* parameter check */
  10304     if (!soc_feature(unit, soc_feature_tsn)) {
  10305         return BCM_E_UNAVAIL;
  10306     }
  10307     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  10308     bkinfo = &tsn_bk->tsn_flows;
  10309 
  10310     /* Requires extended scache support level-2 warmboot */
  10311     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
  10312     if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
  10313         return BCM_E_NONE;
  10314     }
  10315     SOC_SCACHE_HANDLE_SET(scache_handle, unit,
  10316                           BCM_MODULE_TSN, BCM_TSN_WB_SCACHE_PART_TSN_FLOWS);
  10317     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
  10318                                  &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL);
  10319     if (rv == BCM_E_NOT_FOUND) {
  10320         return BCM_E_NONE;
  10321     }
  10322     BCM_IF_ERROR_RETURN(rv);
  10323     assert(scache_ptr != NULL);
  10324 
  10325     /* Avoid flowsets to be created/destroyed at the same time */
  10326     TSN_FLOW_MGMT_LOCK(unit);
  10327 
  10328     /* Loop through flowsets and save to scache */
  10329     flows = 0;
  10330     scache = scache_ptr + sizeof(uint16);
  10331     for (i = 0; i < bkinfo->max_flows; i++) {
  10332         fset = &bkinfo->flowsets[i];
  10333         TSN_FLOWSET_LOCK(fset);
  10334         if (fset->num_flows != 0) {
  10335             tsnflow.flow_idx = i;
  10336             tsnflow.map_id = fset->map_id;
  10337             sal_memcpy(&tsnflow.config, &fset->config, sizeof(tsnflow.config));
  10338             flows++;
  10339             sal_memcpy(scache, &tsnflow, sizeof(tsnflow));
  10340             scache += sizeof(tsnflow);
  10341         }
  10342         TSN_FLOWSET_UNLOCK(fset);
  10343     }
  10344     sal_memcpy(scache_ptr, &flows, sizeof(uint16)); /* Actual flowsets */
  10345 
  10346     /* Done */
  10347     TSN_FLOW_MGMT_UNLOCK(unit);
  10348     return BCM_E_NONE;
  10349 }
  10350 
  10351 /* TSN flow management - reload flow management information from scache */
  10352 STATIC int
  10353 bcmi_esw_tsn_flow_mgmt_reload(int unit)
  10354 {
  10355     bcmi_esw_tsn_bk_info_t *tsn_bk;
  10356     tsn_flows_bookkeeping_t *bkinfo;
  10357     soc_scache_handle_t scache_handle;
  10358     uint8 *scache_ptr = NULL;
  10359     tsn_flowset_wb_t tsnflow;
  10360     int stable_size = 0;
  10361     tsn_flowset_t *fset;
  10362     tsn_flowidx_entry_t *flow_ide;
  10363     bcm_tsn_pri_map_config_t pmcfg;
  10364     uint16 flows, i;
  10365     int num_flows;
  10366     int rv;
  10367     int j, idx;
  10368 
  10369     /* parameter check */
  10370     if (!soc_feature(unit, soc_feature_tsn)) {
  10371         return BCM_E_UNAVAIL;
  10372     }
  10373     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  10374     bkinfo = &tsn_bk->tsn_flows;
  10375     if (!TSN_FLOW_MGMT_DEVINFO(unit)->read_flow) {
  10376         return BCM_E_UNAVAIL;
  10377     }
  10378 
  10379     /* Requires extended scache support level-2 warmboot */
  10380     SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size));
  10381     if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) {
  10382         return BCM_E_NONE;
  10383     }
  10384     SOC_SCACHE_HANDLE_SET(scache_handle, unit,
  10385                           BCM_MODULE_TSN, BCM_TSN_WB_SCACHE_PART_TSN_FLOWS);
  10386     rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0,
  10387                                  &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL);
  10388     if (rv == BCM_E_NOT_FOUND) {
  10389         return BCM_E_NONE;
  10390     }
  10391     BCM_IF_ERROR_RETURN(rv);
  10392     assert(scache_ptr != NULL);
  10393 
  10394     /* Avoid flowsets to be created/destroyed at the same time */
  10395     TSN_FLOW_MGMT_LOCK(unit);
  10396 
  10397     /* Get number of saved flowsets */
  10398     sal_memcpy(&flows, scache_ptr, sizeof(uint16));
  10399     scache_ptr += sizeof(uint16);
  10400 
  10401     /* Restore flowsets */
  10402     for (i = 0; i < flows; i++) {
  10403         /* Read from scache */
  10404         sal_memcpy(&tsnflow, scache_ptr, sizeof(tsnflow));
  10405         scache_ptr += sizeof(tsnflow);
  10406 
  10407         /* Validate flow index */
  10408         if (tsnflow.flow_idx < 0 ||
  10409             tsnflow.flow_idx >= bkinfo->max_flows) {
  10410             TSN_FLOW_MGMT_UNLOCK(unit);
  10411             return BCM_E_INTERNAL;
  10412         }
  10413 
  10414         /* Validate priority map and get number of flows inside this flowset */
  10415         num_flows = 1;
  10416         if (tsnflow.map_id != BCM_TSN_PRI_MAP_INVALID) {
  10417             /* call API to get priority map configuration */
  10418             rv = bcm_esw_tsn_pri_map_get(unit, tsnflow.map_id, &pmcfg);
  10419             if (BCM_FAILURE(rv) || pmcfg.map_type != bcmTsnPriMapTypeTsnFlow) {
  10420                 TSN_FLOW_MGMT_UNLOCK(unit);
  10421                 return BCM_E_INTERNAL;
  10422             }
  10423             /* Number of flows is max flow offset + 1 */
  10424             for (j = 0; j < pmcfg.num_map_entries; j++) {
  10425                 if ((pmcfg.map_entries[j].flags &
  10426                      BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET) &&
  10427                     (pmcfg.map_entries[j].flow_offset > num_flows - 1)) {
  10428                     num_flows = pmcfg.map_entries[j].flow_offset + 1;
  10429                 }
  10430             }
  10431         }
  10432 
  10433         /* Restore flow index entries */
  10434         rv = bcmi_esw_tsn_flow_idx_restore(
  10435                 unit, tsnflow.flow_idx, num_flows, &flow_ide);
  10436         if (BCM_FAILURE(rv)) {
  10437             TSN_FLOW_MGMT_UNLOCK(unit);
  10438             return BCM_E_INTERNAL;
  10439         }
  10440 
  10441         /* Confirmed that this flowset can be restored */
  10442         fset = &bkinfo->flowsets[tsnflow.flow_idx];
  10443         TSN_FLOWSET_LOCK(fset);
  10444 
  10445         /* Restore the flowset */
  10446         fset->flow_ide = flow_ide;
  10447         fset->map_id = tsnflow.map_id;
  10448         fset->num_flows = num_flows;
  10449         fset->ref_count = 0;
  10450         sal_memcpy(&fset->config, &tsnflow.config, sizeof(tsnflow.config));
  10451 
  10452         /* Restore the individual flows */
  10453         for (j = 0; j < num_flows; j++) {
  10454             idx = tsnflow.flow_idx + j;
  10455             TSN_FLOW_LOCK(unit, idx);
  10456             rv = TSN_FLOW_MGMT_DEVINFO(unit)->read_flow(
  10457                     unit, idx, &bkinfo->flows[idx]);
  10458             if (BCM_FAILURE(rv)) {
  10459                 TSN_FLOW_UNLOCK(unit, idx);
  10460                 TSN_FLOWSET_UNLOCK(fset);
  10461                 TSN_FLOW_MGMT_UNLOCK(unit);
  10462                 return rv;
  10463             }
  10464             TSN_FLOW_UNLOCK(unit, idx);
  10465         }
  10466 
  10467         /* Done restoring this flowset */
  10468         TSN_FLOWSET_UNLOCK(fset);
  10469     }
  10470 
  10471     /* Done */
  10472     TSN_FLOW_MGMT_UNLOCK(unit);
  10473     return BCM_E_NONE;
  10474 }
  10475 #endif /* BCM_WARM_BOOT_SUPPORT */
  10476 
  10477 /* TSN flow management de-initialization */
  10478 STATIC int
  10479 bcmi_esw_tsn_flow_mgmt_detach(int unit)
  10480 {
  10481     tsn_flows_bookkeeping_t *bkinfo;
  10482     int i;
  10483 
  10484     /* parameter check */
  10485     if (!SOC_UNIT_VALID(unit)) {
  10486         return BCM_E_UNIT;
  10487     }
  10488 
  10489     /* check if it's already cleared */
  10490     bkinfo = &tsn_bk_info[unit]->tsn_flows;
  10491     if (NULL == bkinfo) {
  10492         return BCM_E_NONE;
  10493     }
  10494 
  10495     /* de-allocate flow index pool */
  10496     if (NULL != bkinfo->flowids_allocated) {
  10497         sal_free(bkinfo->flowids_allocated);
  10498         bkinfo->flowids_allocated = NULL;
  10499     }
  10500 
  10501     /* de-allocate flow instances */
  10502     if (NULL != bkinfo->flows) {
  10503         sal_free(bkinfo->flows);
  10504         bkinfo->flows = NULL;
  10505     }
  10506 
  10507     /* de-allocate flow mutexes */
  10508     if (NULL != bkinfo->flows_mutex) {
  10509         for (i = 0; i < bkinfo->max_flows; i++) {
  10510             if (bkinfo->flows_mutex[i] != NULL) {
  10511                 sal_mutex_destroy(bkinfo->flows_mutex[i]);
  10512                 bkinfo->flows_mutex[i] = NULL;
  10513             }
  10514         }
  10515         sal_free(bkinfo->flows_mutex);
  10516         bkinfo->flows_mutex = NULL;
  10517     }
  10518 
  10519     /* clear flow index linked list */
  10520     bkinfo->flowids_avail = NULL;
  10521 
  10522     /* de-allocate flowset instances */
  10523     if (NULL != bkinfo->flowsets) {
  10524         for (i = 0; i < bkinfo->max_flows; i++) {
  10525             if (NULL != bkinfo->flowsets[i].mutex) {
  10526                 sal_mutex_destroy(bkinfo->flowsets[i].mutex);
  10527                 bkinfo->flowsets[i].mutex = NULL;
  10528             }
  10529         }
  10530         sal_free(bkinfo->flowsets);
  10531         bkinfo->flowsets = NULL;
  10532     }
  10533 
  10534     /* destroy the flow management mutex */
  10535     if (NULL != bkinfo->fmgmt_mutex) {
  10536         sal_mutex_destroy(bkinfo->fmgmt_mutex);
  10537         bkinfo->fmgmt_mutex = NULL;
  10538     }
  10539 
  10540     return BCM_E_NONE;
  10541 }
  10542 
  10543 /* TSN flow management initialization */
  10544 STATIC int
  10545 bcmi_esw_tsn_flow_mgmt_init(int unit)
  10546 {
  10547     bcmi_esw_tsn_bk_info_t *tsn_bk;
  10548     tsn_flows_bookkeeping_t *bkinfo;
  10549     tsn_flowidx_entry_t *fid;
  10550     int maxflows;
  10551     int rv;
  10552     int i;
  10553 
  10554     /* parameter check */
  10555     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  10556 
  10557     /* Retrieve number of flows */
  10558     bkinfo = &tsn_bk->tsn_flows;
  10559     if (TSN_FLOW_MGMT_DEVINFO(unit) == NULL ||
  10560         TSN_FLOW_MGMT_DEVINFO(unit)->get_num_flows == NULL) {
  10561         return BCM_E_UNAVAIL;
  10562     }
  10563     rv = TSN_FLOW_MGMT_DEVINFO(unit)->get_num_flows(unit, &maxflows);
  10564     if (BCM_FAILURE(rv)) {
  10565         return rv;
  10566     }
  10567     if (maxflows <= 0) {
  10568         /* No supported flows */
  10569         return BCM_E_UNAVAIL;
  10570     }
  10571     bkinfo->max_flows = maxflows;
  10572 
  10573     /*
  10574      * We need to minimize the time taken for picking a free flow index.
  10575      * To achieve this, we use linked list with pre-allocated entries so that
  10576      * we can do it in O(1).
  10577      */
  10578 
  10579     /* Allocate flow index entry pool */
  10580     bkinfo->flowids_allocated = (tsn_flowidx_entry_t *)sal_alloc(
  10581             sizeof(tsn_flowidx_entry_t) * maxflows,
  10582             "tsn flow ids");
  10583     if (NULL == bkinfo->flowids_allocated) {
  10584         LOG_ERROR(BSL_LS_BCM_TSN,
  10585                   (BSL_META("TSN: failed to allocate flow IDs\n")));
  10586         (void)bcmi_esw_tsn_flow_mgmt_detach(unit);
  10587         return BCM_E_MEMORY;
  10588     }
  10589 
  10590     /* Initialize flow ID list */
  10591     fid = bkinfo->flowids_allocated;
  10592     /* Prepare flow index entry linked list for quick ID allocation */
  10593     for (i = 0; i < bkinfo->max_flows; i++, fid++) {
  10594         /*
  10595          * Add an entry to the head of the linked list.
  10596          * The flow index is going backward so the final list can be in
  10597          * increasing order (some allocation requires continuous flows).
  10598          */
  10599         fid->flow_idx = bkinfo->max_flows - i - 1;
  10600         fid->next = bkinfo->flowids_avail;
  10601         bkinfo->flowids_avail = fid;
  10602     }
  10603 
  10604     /* Allocate array of flowset and flow instances */
  10605     if (bkinfo->max_flows > 0) {
  10606         /* The max number of flowsets should be the same as flows */
  10607         bkinfo->flowsets = (tsn_flowset_t *)sal_alloc(
  10608             sizeof(tsn_flowset_t) * bkinfo->max_flows, "tsn flowsets");
  10609         if (NULL == bkinfo->flowsets) {
  10610             LOG_ERROR(BSL_LS_BCM_TSN,
  10611                       (BSL_META("TSN: failed to allocate flowsets\n")));
  10612             (void)bcmi_esw_tsn_flow_mgmt_detach(unit);
  10613             return BCM_E_MEMORY;
  10614         }
  10615         sal_memset(bkinfo->flowsets, 0,
  10616             sizeof(tsn_flowset_t) * bkinfo->max_flows);
  10617         /* Pre-create mutexes of all flowsets for performance */
  10618         for (i = 0; i < bkinfo->max_flows; i++) {
  10619             bkinfo->flowsets[i].mutex = sal_mutex_create("tsn flowset");
  10620             if (NULL == bkinfo->flowsets[i].mutex) {
  10621                 LOG_ERROR(BSL_LS_BCM_TSN,
  10622                           (BSL_META("TSN: failed to create flowset mutex\n")));
  10623                 (void)bcmi_esw_tsn_flow_mgmt_detach(unit);
  10624                 return BCM_E_MEMORY;
  10625             }
  10626         }
  10627 
  10628         /* Allocate array of flow instances and mutexes */
  10629         bkinfo->flows = (bcm_tsn_flow_config_t *)sal_alloc(
  10630             sizeof(bcm_tsn_flow_config_t) * maxflows, "tsn flows");
  10631         if (NULL == bkinfo->flows) {
  10632             LOG_ERROR(BSL_LS_BCM_TSN,
  10633                       (BSL_META("TSN: failed to allocate flows\n")));
  10634             (void)bcmi_esw_tsn_flow_mgmt_detach(unit);
  10635             return BCM_E_MEMORY;
  10636         }
  10637         sal_memset(bkinfo->flows, 0, sizeof(bcm_tsn_flow_config_t) * maxflows);
  10638         bkinfo->flows_mutex = (sal_mutex_t *)sal_alloc(
  10639             sizeof(sal_mutex_t) * maxflows, "tsn flows mutex");
  10640         if (NULL == bkinfo->flows_mutex) {
  10641             LOG_ERROR(BSL_LS_BCM_TSN,
  10642                       (BSL_META("TSN: failed to allocate flow mutexes\n")));
  10643             (void)bcmi_esw_tsn_flow_mgmt_detach(unit);
  10644             return BCM_E_MEMORY;
  10645         }
  10646         for (i = 0; i < maxflows; i++) {
  10647             bkinfo->flows_mutex[i] = sal_mutex_create("tsn flow mutex");
  10648             if (NULL == bkinfo->flows_mutex[i]) {
  10649                 LOG_ERROR(BSL_LS_BCM_TSN,
  10650                           (BSL_META("TSN: failed to create flow mutex\n")));
  10651                 (void)bcmi_esw_tsn_flow_mgmt_detach(unit);
  10652                 return BCM_E_MEMORY;
  10653             }
  10654         }
  10655     }
  10656 
  10657     /* Create mutex for protecting flow management (allocate/free) */
  10658     bkinfo->fmgmt_mutex = sal_mutex_create("tsn flow mgmt");
  10659     if (NULL == bkinfo->fmgmt_mutex) {
  10660         LOG_ERROR(BSL_LS_BCM_TSN,
  10661                   (BSL_META("TSN: failed to create flow mgmt mutex\n")));
  10662         (void)bcmi_esw_tsn_flow_mgmt_detach(unit);
  10663         return BCM_E_MEMORY;
  10664     }
  10665 
  10666     return BCM_E_NONE;
  10667 }
  10668 
  10669 /*
  10670  * Function:
  10671  *      bcmi_esw_tsn_mtu_profile_ref_inc
  10672  * Purpose:
  10673  *      Increase the reference count for the
  10674  *      specific mtu profile ID
  10675  * Parameters:
  10676  *      unit - (IN) Unit number
  10677  *      mtu_profile_id - (IN) profile ID
  10678  * Returns:
  10679  *      BCM_E_xxx
  10680  */
  10681 int
  10682 bcmi_esw_tsn_mtu_profile_ref_inc(
  10683     int unit,
  10684     int mtu_profile_id)
  10685 {
  10686     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  10687     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
  10688     const tsn_mtu_info_t *ctrl_info = NULL;
  10689 
  10690     int index, rv, min, max;
  10691     bcm_tsn_mtu_profile_type_t type;
  10692 
  10693     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  10694     dev_info = bk_info->tsn_dev_info;
  10695     /* Use this init macro after the bk info instance get */
  10696     MTU_DEV_INIT(unit);
  10697     ctrl_info = dev_info->tsn_mtu_info;
  10698 
  10699     /* this function also check the validity of parameter profile id */
  10700     MTU_BK_LOCK(unit);
  10701     rv = ctrl_info->mtu_profile_decode(unit, mtu_profile_id, &type, &index);
  10702     if (BCM_FAILURE(rv)) {
  10703         MTU_BK_UNLOCK(unit);
  10704         return rv;
  10705     }
  10706 
  10707     /* index 0 in profile memory is the default value */
  10708     if (index == 0) {
  10709         MTU_BK_UNLOCK(unit);
  10710         return BCM_E_NONE;
  10711     }
  10712 
  10713     MTU_BK_INIT(unit, type);
  10714     ctrl_info->mtu_profile_mem_idx_get(unit, type, &min, &max);
  10715     if (index < min || index > max) {
  10716         MTU_BK_UNLOCK(unit);
  10717         return BCM_E_PARAM;
  10718     }
  10719     bk_info->tsn_mtu_bk_info.mtu_refcount[type][index]++;
  10720     MTU_BK_UNLOCK(unit);
  10721     return BCM_E_NONE;
  10722 }
  10723 
  10724 /*
  10725  * Function:
  10726  *      bcmi_esw_tsn_mtu_profile_ref_dec
  10727  * Purpose:
  10728  *      Decrease the reference count of the
  10729  *      specific mtu profile ID
  10730  * Parameters:
  10731  *      unit - (IN) Unit number
  10732  *      mtu_profile_id - (IN) profile ID
  10733  * Returns:
  10734  *      BCM_E_xxx
  10735  */
  10736 int
  10737 bcmi_esw_tsn_mtu_profile_ref_dec(
  10738     int unit,
  10739     int mtu_profile_id)
  10740 {
  10741     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  10742     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
  10743     const tsn_mtu_info_t *ctrl_info = NULL;
  10744 
  10745     int index, rv, min, max;
  10746     bcm_tsn_mtu_profile_type_t type;
  10747 
  10748     /* Check whether the module is being detached */
  10749     if (tsn_bk_info[unit] == NULL && tsn_bk_info_initialized == 1) {
  10750         return BCM_E_NONE;
  10751     }
  10752 
  10753     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  10754     dev_info = bk_info->tsn_dev_info;
  10755     /* Use this init macro after the bk info instance get */
  10756     MTU_DEV_INIT(unit);
  10757     ctrl_info = dev_info->tsn_mtu_info;
  10758 
  10759     /* this function also check the validity of parameter profile id */
  10760     MTU_BK_LOCK(unit);
  10761     rv = ctrl_info->mtu_profile_decode(unit, mtu_profile_id, &type, &index);
  10762     if (BCM_FAILURE(rv)) {
  10763         MTU_BK_UNLOCK(unit);
  10764         return rv;
  10765     }
  10766 
  10767     /* index 0 in profile memory is the default value */
  10768     if (index == 0) {
  10769         MTU_BK_UNLOCK(unit);
  10770         return BCM_E_NONE;
  10771     }
  10772 
  10773     MTU_BK_INIT(unit, type);
  10774     /* Cannot minus the reference count that is already 0 */
  10775     ctrl_info->mtu_profile_mem_idx_get(unit, type, &min, &max);
  10776     if (index < min || index > max) {
  10777         MTU_BK_UNLOCK(unit);
  10778         return BCM_E_PARAM;
  10779     }
  10780     if (bk_info->tsn_mtu_bk_info.mtu_refcount[type][index] == 0) {
  10781         MTU_BK_UNLOCK(unit);
  10782         return BCM_E_PARAM;
  10783     }
  10784 
  10785     bk_info->tsn_mtu_bk_info.mtu_refcount[type][index]--;
  10786     MTU_BK_UNLOCK(unit);
  10787     return BCM_E_NONE;
  10788 }
  10789 
  10790 /*
  10791  * Function:
  10792  *      bcmi_esw_tsn_stu_profile_ref_inc
  10793  * Purpose:
  10794  *      Increase the reference count for the
  10795  *      specific stu profile ID
  10796  * Parameters:
  10797  *      unit - (IN) Unit number
  10798  *      stu_profile_id - (IN) profile ID
  10799  * Returns:
  10800  *      BCM_E_xxx
  10801  */
  10802 int
  10803 bcmi_esw_tsn_stu_profile_ref_inc(
  10804     int unit,
  10805     int stu_profile_id)
  10806 {
  10807     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  10808     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
  10809     const tsn_stu_info_t *ctrl_info = NULL;
  10810 
  10811     int index, rv, min, max;
  10812     bcm_tsn_stu_profile_type_t type;
  10813 
  10814     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  10815     dev_info = bk_info->tsn_dev_info;
  10816     /* Use this init macro after the bk info instance get */
  10817     STU_DEV_INIT(unit);
  10818     ctrl_info = dev_info->tsn_stu_info;
  10819 
  10820     /* this function also check the validity of parameter profile id */
  10821     STU_BK_LOCK(unit);
  10822     rv = ctrl_info->stu_profile_decode(unit, stu_profile_id, &type, &index);
  10823     if (BCM_FAILURE(rv)) {
  10824         STU_BK_UNLOCK(unit);
  10825         return rv;
  10826     }
  10827 
  10828     /* index 0 in profile memory is the default value */
  10829     if (index == 0) {
  10830         STU_BK_UNLOCK(unit);
  10831         return BCM_E_NONE;
  10832     }
  10833 
  10834     STU_BK_INIT(unit, type);
  10835     ctrl_info->stu_profile_mem_idx_get(unit, type, &min, &max);
  10836     if (index < min || index > max) {
  10837         STU_BK_UNLOCK(unit);
  10838         return BCM_E_PARAM;
  10839     }
  10840     bk_info->tsn_stu_bk_info.stu_refcount[type][index]++;
  10841     STU_BK_UNLOCK(unit);
  10842     return BCM_E_NONE;
  10843 }
  10844 
  10845 /*
  10846  * Function:
  10847  *      bcmi_esw_tsn_stu_profile_ref_dec
  10848  * Purpose:
  10849  *      Decrease the reference count for the
  10850  *      specific stu profile ID
  10851  * Parameters:
  10852  *      unit - (IN) Unit number
  10853  *      stu_profile_id - (IN) profile ID
  10854  * Returns:
  10855  *      BCM_E_xxx
  10856  */
  10857 int
  10858 bcmi_esw_tsn_stu_profile_ref_dec(
  10859     int unit,
  10860     int stu_profile_id)
  10861 {
  10862     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  10863     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
  10864     const tsn_stu_info_t *ctrl_info = NULL;
  10865 
  10866     int index, rv, min, max;
  10867     bcm_tsn_stu_profile_type_t type;
  10868 
  10869     /* Check whether the module is being detached */
  10870     if (tsn_bk_info[unit] == NULL && tsn_bk_info_initialized == 1) {
  10871         return BCM_E_NONE;
  10872     }
  10873 
  10874     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  10875     dev_info = bk_info->tsn_dev_info;
  10876     /* Use this init macro after the bk info instance get */
  10877     STU_DEV_INIT(unit);
  10878     ctrl_info = dev_info->tsn_stu_info;
  10879 
  10880     /* this function also check the validity of parameter profile id */
  10881     STU_BK_LOCK(unit);
  10882     rv = ctrl_info->stu_profile_decode(unit, stu_profile_id, &type, &index);
  10883     if (BCM_FAILURE(rv)) {
  10884         STU_BK_UNLOCK(unit);
  10885         return rv;
  10886     }
  10887 
  10888     /* index 0 in profile memory is the default value */
  10889     if (index == 0) {
  10890         STU_BK_UNLOCK(unit);
  10891         return BCM_E_NONE;
  10892     }
  10893 
  10894     STU_BK_INIT(unit, type);
  10895     /* Cannot minus the reference count that is already 0 */
  10896     ctrl_info->stu_profile_mem_idx_get(unit, type, &min, &max);
  10897     if (index < min || index > max) {
  10898         STU_BK_UNLOCK(unit);
  10899         return BCM_E_PARAM;
  10900     }
  10901     if (bk_info->tsn_stu_bk_info.stu_refcount[type][index] == 0) {
  10902         STU_BK_UNLOCK(unit);
  10903         return BCM_E_PARAM;
  10904     }
  10905 
  10906     bk_info->tsn_stu_bk_info.stu_refcount[type][index]--;
  10907     STU_BK_UNLOCK(unit);
  10908     return BCM_E_NONE;
  10909 }
  10910 
  10911 /*
  10912  * Function:
  10913  *     bcmi_esw_tsn_mtu_hw_profile_id_get
  10914  * Purpose:
  10915  *     Convert software mtu profile ID to hardware mtu profile ID
  10916  * Parameters:
  10917  *     unit - (IN) unit number
  10918  *     mtu_profile_id - (IN) SW profile ID
  10919  *     hw_profile_id - (OUT) HW profile ID
  10920  * Returns:
  10921  *     BCM_E_XXX
  10922  * Notes:
  10923  */
  10924 int
  10925 bcmi_esw_tsn_mtu_hw_profile_id_get(
  10926     int unit,
  10927     int mtu_profile_id,
  10928     bcm_tsn_mtu_profile_type_t *type,
  10929     int *hw_profile_id)
  10930 {
  10931     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  10932     const tsn_mtu_info_t *ctrl_info = NULL;
  10933     int rv;
  10934 
  10935     if (hw_profile_id == NULL || type == NULL) {
  10936         return BCM_E_UNAVAIL;
  10937     }
  10938 
  10939     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  10940     /* Use this init macro after the bk info instance get */
  10941     MTU_DEV_INIT(unit);
  10942     ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
  10943     MTU_BK_LOCK(unit);
  10944     rv = ctrl_info->mtu_profile_decode(unit, mtu_profile_id,
  10945                                        type, hw_profile_id);
  10946     if (BCM_FAILURE(rv)) {
  10947         MTU_BK_UNLOCK(unit);
  10948         return rv;
  10949     }
  10950     MTU_BK_UNLOCK(unit);
  10951 
  10952     return BCM_E_NONE;
  10953 
  10954 }
  10955 
  10956 /*
  10957  * Function:
  10958  *     bcmi_esw_tsn_mtu_sw_profile_id_get
  10959  * Purpose:
  10960  *     Convert hardware mtu profile ID to software mtu profile ID
  10961  * Parameters:
  10962  *     unit - (IN) unit number
  10963  *     hw_profile_id - (IN) HW profile ID
  10964  *     mtu_profile_id - (OUT) SW profile ID
  10965  * Returns:
  10966  *     BCM_E_XXX
  10967  * Notes:
  10968  */
  10969 int
  10970 bcmi_esw_tsn_mtu_sw_profile_id_get(
  10971     int unit,
  10972     bcm_tsn_mtu_profile_type_t type,
  10973     int hw_profile_id,
  10974     int *mtu_profile_id)
  10975 {
  10976     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  10977     const tsn_mtu_info_t *ctrl_info = NULL;
  10978     const bcmi_esw_tsn_dev_info_t *dev_info;
  10979     int rv;
  10980 
  10981     if (mtu_profile_id == NULL) {
  10982         return BCM_E_UNAVAIL;
  10983     }
  10984 
  10985     if (type != bcmTsnMtuProfileTypeIngress &&
  10986         type != bcmTsnMtuProfileTypeEgress) {
  10987         LOG_VERBOSE(BSL_LS_BCM_TSN,
  10988                     (BSL_META_U(unit, "Wrong Profile Type.\n")));
  10989         return BCM_E_UNAVAIL;
  10990     }
  10991 
  10992     if (tsn_bk_info[unit] == NULL) {
  10993         /* Using device specific info that need no bk_info */
  10994         BCM_IF_ERROR_RETURN(bcmi_esw_tsn_noninit_dev_info_get(unit, &dev_info));
  10995         if (NULL == dev_info->tsn_mtu_info->mtu_profile_encode) {
  10996             return BCM_E_UNAVAIL;
  10997         }
  10998         rv = dev_info->tsn_mtu_info->mtu_profile_encode(unit, hw_profile_id,
  10999                                                         type, mtu_profile_id);
  11000         return BCM_E_NONE;
  11001     }
  11002 
  11003     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11004     /* Use this init macro after the bk info instance get */
  11005     MTU_DEV_INIT(unit);
  11006     ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
  11007 
  11008     MTU_BK_LOCK(unit);
  11009     rv = ctrl_info->mtu_profile_encode(unit, hw_profile_id,
  11010                                        type, mtu_profile_id);
  11011     if (BCM_FAILURE(rv)) {
  11012         MTU_BK_UNLOCK(unit);
  11013         return rv;
  11014     }
  11015     MTU_BK_UNLOCK(unit);
  11016 
  11017     return BCM_E_NONE;
  11018 
  11019 }
  11020 
  11021 /*
  11022  * Function:
  11023  *     bcmi_esw_tsn_stu_hw_profile_id_get
  11024  * Purpose:
  11025  *     Convert software stu profile ID to hardware stu profile ID
  11026  * Parameters:
  11027  *     unit - (IN) unit number
  11028  *     stu_profile_id - (IN) SW profile ID
  11029  *     hw_profile_id - (OUT) HW profile ID
  11030  * Returns:
  11031  *     BCM_E_XXX
  11032  * Notes:
  11033  */
  11034 int
  11035 bcmi_esw_tsn_stu_hw_profile_id_get(
  11036     int unit,
  11037     int stu_profile_id,
  11038     bcm_tsn_stu_profile_type_t *type,
  11039     int *hw_profile_id)
  11040 
  11041 {
  11042     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11043     const tsn_stu_info_t *ctrl_info = NULL;
  11044     int rv;
  11045 
  11046     if (hw_profile_id == NULL || type == NULL) {
  11047         return BCM_E_UNAVAIL;
  11048     }
  11049 
  11050     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11051     /* Use this init macro after the bk info instance get */
  11052     STU_DEV_INIT(unit);
  11053     ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
  11054     STU_BK_LOCK(unit);
  11055     rv = ctrl_info->stu_profile_decode(unit, stu_profile_id,
  11056                                        type, hw_profile_id);
  11057     if (BCM_FAILURE(rv)) {
  11058         STU_BK_UNLOCK(unit);
  11059         return rv;
  11060     }
  11061     STU_BK_UNLOCK(unit);
  11062 
  11063     return BCM_E_NONE;
  11064 }
  11065 
  11066 /*
  11067  * Function:
  11068  *     bcmi_esw_tsn_stu_sw_profile_id_get
  11069  * Purpose:
  11070  *     Convert hardware stu profile ID to software stu profile ID
  11071  * Parameters:
  11072  *     unit - (IN) unit number
  11073  *     hw_profile_id - (IN) HW profile ID
  11074  *     stu_profile_id - (OUT) SW profile ID
  11075  * Returns:
  11076  *     BCM_E_XXX
  11077  * Notes:
  11078  */
  11079 int
  11080 bcmi_esw_tsn_stu_sw_profile_id_get(
  11081     int unit,
  11082     bcm_tsn_stu_profile_type_t type,
  11083     int hw_profile_id,
  11084     int *stu_profile_id)
  11085 {
  11086     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11087     const tsn_stu_info_t *ctrl_info = NULL;
  11088     const bcmi_esw_tsn_dev_info_t *dev_info;
  11089     int rv;
  11090 
  11091     if (stu_profile_id == NULL) {
  11092         return BCM_E_UNAVAIL;
  11093     }
  11094 
  11095     if (type != bcmTsnStuProfileTypeIngress &&
  11096         type != bcmTsnStuProfileTypeEgress) {
  11097         LOG_VERBOSE(BSL_LS_BCM_TSN,
  11098                     (BSL_META_U(unit, "Wrong Profile Type.\n")));
  11099         return BCM_E_UNAVAIL;
  11100     }
  11101 
  11102     if (tsn_bk_info[unit] == NULL) {
  11103         /* Using device specific info that need no nk_info */
  11104         BCM_IF_ERROR_RETURN(bcmi_esw_tsn_noninit_dev_info_get(unit, &dev_info));
  11105         if (NULL == dev_info->tsn_stu_info->stu_profile_encode) {
  11106             return BCM_E_UNAVAIL;
  11107         }
  11108         rv = dev_info->tsn_stu_info->stu_profile_encode(unit, hw_profile_id,
  11109                                                         type, stu_profile_id);
  11110         return BCM_E_NONE;
  11111     }
  11112 
  11113     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11114     /* Use this init macro after the bk info instance get */
  11115     STU_DEV_INIT(unit);
  11116     ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
  11117 
  11118     STU_BK_LOCK(unit);
  11119     rv = ctrl_info->stu_profile_encode(unit, hw_profile_id,
  11120                                        type, stu_profile_id);
  11121     if (BCM_FAILURE(rv)) {
  11122         STU_BK_UNLOCK(unit);
  11123         return rv;
  11124     }
  11125     STU_BK_UNLOCK(unit);
  11126 
  11127     return BCM_E_NONE;
  11128 }
  11129 
  11130 
  11131 /*
  11132  * Function:
  11133  *      bcmi_esw_tsn_mtu_profile_get
  11134  * Purpose:
  11135  *      Get mtu profile configuration
  11136  *      with the profile id.
  11137  * Parameters:
  11138  *      unit - (IN) Unit number
  11139  *      mtu_profile_id - (IN) Indicated the mtu profile entry
  11140  *      type - (OUT) Indicates ingress or egress mtu profile
  11141  *      config - (OUT) Configuration of the mtu profile
  11142  * Returns:
  11143  *      BCM_E_xxx
  11144  */
  11145 int
  11146 bcmi_esw_tsn_mtu_profile_get(
  11147     int unit,
  11148     int mtu_profile_id,
  11149     bcm_tsn_mtu_profile_type_t *type,
  11150     bcm_tsn_mtu_config_t *config)
  11151 {
  11152     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11153     const tsn_mtu_info_t *ctrl_info = NULL;
  11154 
  11155     int index, rv;
  11156 
  11157     if (type == NULL || config == NULL) {
  11158         return BCM_E_PARAM;
  11159     }
  11160 
  11161     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11162     /* Use this init macro after the bk info instance get */
  11163     MTU_DEV_INIT(unit);
  11164     ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
  11165     MTU_BK_LOCK(unit);
  11166     /* this function also check the validity of parameter profile id */
  11167     rv = ctrl_info->mtu_profile_decode(unit, mtu_profile_id, type, &index);
  11168     if (BCM_FAILURE(rv)) {
  11169         MTU_BK_UNLOCK(unit);
  11170         return rv;
  11171     }
  11172     rv = ctrl_info->mtu_profile_get(unit, index, *type, config);
  11173     if (BCM_FAILURE(rv)) {
  11174         MTU_BK_UNLOCK(unit);
  11175         return rv;
  11176     }
  11177     MTU_BK_UNLOCK(unit);
  11178     return BCM_E_NONE;
  11179 }
  11180 
  11181 /*
  11182  * Function:
  11183  *      bcmi_esw_tsn_mtu_profile_set
  11184  * Purpose:
  11185  *      Set mtu profile with the profile id
  11186  *      and config parameter.
  11187  * Parameters:
  11188  *      unit - (IN) Unit number
  11189  *      mtu_profile_id - (IN) Indicated the mtu profile entry
  11190  *      config - (IN) Configuration of the mtu profile
  11191  * Returns:
  11192  *      BCM_E_xxx
  11193  */
  11194 int
  11195 bcmi_esw_tsn_mtu_profile_set(
  11196     int unit,
  11197     int mtu_profile_id,
  11198     bcm_tsn_mtu_config_t *config)
  11199 {
  11200     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11201     const tsn_mtu_info_t *ctrl_info = NULL;
  11202 
  11203     int index, ref_count, rv, min, max;
  11204     bcm_tsn_mtu_profile_type_t type;
  11205 
  11206     if (config == NULL) {
  11207         return BCM_E_PARAM;
  11208     }
  11209 
  11210     if (config->size <= 0) {
  11211         LOG_ERROR(BSL_LS_BCM_TSN,
  11212                   (BSL_META_U(unit, "Invalid MTU size.\n")));
  11213         return BCM_E_PARAM;
  11214     }
  11215 
  11216     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11217     /* Use this init macro after the bk info instance get */
  11218     MTU_DEV_INIT(unit);
  11219     ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
  11220 
  11221     MTU_BK_LOCK(unit);
  11222     /* this function also check the validity of parameter profile id */
  11223     rv = ctrl_info->mtu_profile_decode(unit, mtu_profile_id, &type, &index);
  11224     if (BCM_FAILURE(rv)) {
  11225         MTU_BK_UNLOCK(unit);
  11226         return rv;
  11227     }
  11228 
  11229     /* index 0 in profile memory is the default value */
  11230     if (index == 0) {
  11231         MTU_BK_UNLOCK(unit);
  11232         LOG_WARN(BSL_LS_BCMAPI_TSN,
  11233                 (BSL_META_U(
  11234                   unit, "Profile ID 0 is the default, can't modify it.\n")));
  11235         return BCM_E_PARAM;
  11236     }
  11237 
  11238     rv = ctrl_info->mtu_profile_mem_refcnt_get(unit, type, index, &ref_count);
  11239     if (BCM_FAILURE(rv)) {
  11240         MTU_BK_UNLOCK(unit);
  11241         return rv;
  11242     }
  11243     /* ref_count > 0, then the entry is created */
  11244     if (ref_count <= 0) {
  11245         MTU_BK_UNLOCK(unit);
  11246         LOG_WARN(BSL_LS_BCMAPI_TSN,
  11247                 (BSL_META_U(unit,
  11248                             "NTU Profile entry is not created.\n")));
  11249         return BCM_E_PARAM;
  11250     }
  11251 
  11252     /* the profile entry is referenced by other flows */
  11253     MTU_BK_INIT(unit, type);
  11254     ctrl_info->mtu_profile_mem_idx_get(unit, type, &min, &max);
  11255     if (index < min || index > max) {
  11256         MTU_BK_UNLOCK(unit);
  11257         return BCM_E_PARAM;
  11258     }
  11259     if (bk_info->tsn_mtu_bk_info.mtu_refcount[type][index] > 0) {
  11260         MTU_BK_UNLOCK(unit);
  11261         LOG_WARN(BSL_LS_BCMAPI_TSN,
  11262                 (BSL_META_U(unit,
  11263                             "Flow is in use of Ingress MTU Profile\n")));
  11264         return BCM_E_BUSY;
  11265     }
  11266 
  11267     rv = ctrl_info->mtu_profile_set(unit, index, type, config);
  11268     if (BCM_FAILURE(rv)) {
  11269         MTU_BK_UNLOCK(unit);
  11270         return rv;
  11271     }
  11272     MTU_BK_UNLOCK(unit);
  11273     return BCM_E_NONE;
  11274 }
  11275 
  11276 /*
  11277  * Function:
  11278  *      bcmi_esw_tsn_mtu_profile_destroy
  11279  * Purpose:
  11280  *      Clear the mtu profile with the profile id
  11281  * Parameters:
  11282  *      unit - (IN) Unit number
  11283  *      mtu_profile_id - (IN) Indicated the mtu profile entry
  11284  * Returns:
  11285  *      BCM_E_xxx
  11286  */
  11287 int
  11288 bcmi_esw_tsn_mtu_profile_destroy(
  11289     int unit,
  11290     int mtu_profile_id)
  11291 {
  11292     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11293     const tsn_mtu_info_t *ctrl_info = NULL;
  11294 
  11295     bcm_tsn_mtu_profile_type_t type;
  11296     int index, rv, min, max;
  11297 
  11298     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11299     /* Use this init macro after the bk info instance get */
  11300     MTU_DEV_INIT(unit);
  11301     ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
  11302 
  11303     /* this function also check the validity of parameter profile id */
  11304     MTU_BK_LOCK(unit);
  11305     rv = ctrl_info->mtu_profile_decode(unit, mtu_profile_id, &type, &index);
  11306     if (BCM_FAILURE(rv)) {
  11307         MTU_BK_UNLOCK(unit);
  11308         return rv;
  11309     }
  11310 
  11311     /* index 0 in profile memory is the default value */
  11312     if (index == 0) {
  11313         MTU_BK_UNLOCK(unit);
  11314         LOG_WARN(BSL_LS_BCMAPI_TSN,
  11315                 (BSL_META_U(
  11316                   unit, "Profile ID 0 is the default, can't modify it.\n")));
  11317         return BCM_E_PARAM;
  11318     }
  11319 
  11320     rv = ctrl_info->mtu_profile_mem_idx_get(unit, type, &min, &max);
  11321     if (BCM_FAILURE(rv)) {
  11322         MTU_BK_UNLOCK(unit);
  11323         return rv;
  11324     }
  11325     MTU_BK_INIT(unit, type);
  11326     /* the profile entry is referenced bt other flows */
  11327     if (index < min || index > max) {
  11328         MTU_BK_UNLOCK(unit);
  11329         return BCM_E_PARAM;
  11330     }
  11331     if (bk_info->tsn_mtu_bk_info.mtu_refcount[type][index] != 0) {
  11332         MTU_BK_UNLOCK(unit);
  11333         LOG_WARN(BSL_LS_BCMAPI_TSN,
  11334                 (BSL_META_U(unit,
  11335                             "Flow is in use of Ingress MTU Profile\n")));
  11336         return BCM_E_EXISTS;
  11337     }
  11338 
  11339     rv = ctrl_info->mtu_profile_destroy(unit, type, index);
  11340     MTU_BK_UNLOCK(unit);
  11341 
  11342     return rv;
  11343 }
  11344 
  11345 /*
  11346  * Function:
  11347  *      bcmi_esw_tsn_mtu_profile_create
  11348  * Purpose:
  11349  *      Create mtu profile with the config pointer
  11350  *      and return the assigned profile id.
  11351  * Parameters:
  11352  *      unit - (IN) Unit number
  11353  *      type - (IN) Indicates ingress or egress mtu profile
  11354  *      config - (IN) configuration of the mtu profile
  11355  *      mtu_profile_id - (OUT) profile id
  11356  * Returns:
  11357  *      BCM_E_xxx
  11358  */
  11359 int
  11360 bcmi_esw_tsn_mtu_profile_create(
  11361     int unit,
  11362     bcm_tsn_mtu_profile_type_t type,
  11363     bcm_tsn_mtu_config_t *config,
  11364     int *mtu_profile_id)
  11365 {
  11366     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11367     const tsn_mtu_info_t *ctrl_info = NULL;
  11368 
  11369     int ref_count, rv, rv1;
  11370     uint32 index;
  11371 
  11372     if (config == NULL || mtu_profile_id == NULL) {
  11373         return BCM_E_PARAM;
  11374     }
  11375 
  11376     if (config->size <= 0) {
  11377         LOG_ERROR(BSL_LS_BCM_TSN,
  11378                   (BSL_META_U(unit, "Invalid MTU size.\n")));
  11379         return BCM_E_PARAM;
  11380     }
  11381     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11382     /* Use this init macro after the bk info instance get */
  11383     MTU_DEV_INIT(unit);
  11384     ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
  11385 
  11386     /* Check the validity of the type */
  11387     if (type != bcmTsnMtuProfileTypeIngress &&
  11388         type != bcmTsnMtuProfileTypeEgress) {
  11389         LOG_VERBOSE(BSL_LS_BCM_TSN,
  11390                     (BSL_META_U(unit, "Wrong Profile Type.\n")));
  11391         return BCM_E_PARAM;
  11392     }
  11393 
  11394     MTU_BK_LOCK(unit);
  11395     rv = ctrl_info->mtu_profile_create(unit, type, config, &index);
  11396     if (BCM_FAILURE(rv)) {
  11397         MTU_BK_UNLOCK(unit);
  11398         return rv;
  11399     }
  11400     rv = ctrl_info->mtu_profile_mem_refcnt_get(unit, type, index, &ref_count);
  11401     if (BCM_FAILURE(rv)) {
  11402         rv1 = ctrl_info->mtu_profile_destroy(unit, type, index);
  11403         if (BCM_FAILURE(rv1)) {
  11404             MTU_BK_UNLOCK(unit);
  11405             return rv1;
  11406         }
  11407         MTU_BK_UNLOCK(unit);
  11408         return rv;
  11409     }
  11410 
  11411     /* Encode the mtu profile id */
  11412     rv = ctrl_info->mtu_profile_encode(unit, index, type, mtu_profile_id);
  11413     if (BCM_FAILURE(rv)) {
  11414         rv1 = ctrl_info->mtu_profile_destroy(unit, type, index);
  11415         if (BCM_FAILURE(rv1)) {
  11416             MTU_BK_UNLOCK(unit);
  11417             return rv1;
  11418         }
  11419         MTU_BK_UNLOCK(unit);
  11420         return rv;
  11421     }
  11422 
  11423     /* ref_count > 1 indicates replicated mtu profile is created */
  11424     if (ref_count > 1) {
  11425         if (type == bcmTsnMtuProfileTypeIngress) {
  11426             LOG_WARN(BSL_LS_BCMAPI_TSN,
  11427                      (BSL_META_U(unit,
  11428                                  "config already existed, "
  11429                                  "found ingress mtu profile id(%d)\n"),
  11430                                  *mtu_profile_id));
  11431         } else {
  11432             LOG_WARN(BSL_LS_BCMAPI_TSN,
  11433                      (BSL_META_U(unit,
  11434                                  "config already existed, "
  11435                                  "found egress mtu profile id(%d)\n"),
  11436                                  *mtu_profile_id));
  11437         }
  11438     }
  11439 
  11440     MTU_BK_UNLOCK(unit);
  11441     return BCM_E_NONE;
  11442 }
  11443 /*
  11444  * Function:
  11445  *      bcmi_esw_tsn_mtu_profile_traverse
  11446  * Purpose:
  11447  *      Traverse the created match config.
  11448  * Parameters:
  11449  *      unit - (IN) Unit number
  11450  *      cb - (IN) Traverse call back function
  11451  *      user_data - (IN) User data
  11452  * Returns:
  11453  *      BCM_E_xxx
  11454  */
  11455 int
  11456 bcmi_esw_tsn_mtu_profile_traverse(
  11457     int unit,
  11458     bcm_tsn_mtu_profile_traverse_cb cb,
  11459     void *user_data)
  11460 {
  11461     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11462     const tsn_mtu_info_t *ctrl_info = NULL;
  11463     int rv;
  11464 
  11465     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11466     /* Use this init macro after the bk info instance get */
  11467     MTU_DEV_INIT(unit);
  11468     ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
  11469 
  11470     MTU_BK_LOCK(unit);
  11471     rv = ctrl_info->mtu_profile_traverse(unit, cb, user_data);
  11472     MTU_BK_UNLOCK(unit);
  11473 
  11474     return rv;
  11475 
  11476 }
  11477 
  11478 
  11479 /*
  11480  * Function:
  11481  *      bcmi_esw_tsn_ingress_mtu_config_set
  11482  * Purpose:
  11483  *      Set the priority of source ingress
  11484  *      mtu profile index.
  11485  * Parameters:
  11486  *      unit - (IN) Unit number
  11487  *      config - (IN) Configuration of the mtu profile priority
  11488  * Returns:
  11489  *      BCM_E_xxx
  11490  */
  11491 int
  11492 bcmi_esw_tsn_ingress_mtu_config_set(
  11493     int unit,
  11494     bcm_tsn_ingress_mtu_config_t *config)
  11495 {
  11496     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11497     const tsn_mtu_info_t *ctrl_info = NULL;
  11498     int rv;
  11499 
  11500     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11501     /* Use this init macro after the bk info instance get */
  11502     MTU_DEV_INIT(unit);
  11503     ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
  11504 
  11505     if (config == NULL) {
  11506         return BCM_E_PARAM;
  11507     }
  11508 
  11509     MTU_BK_LOCK(unit);
  11510     rv = ctrl_info->ingress_mtu_config_set(unit, config);
  11511     MTU_BK_UNLOCK(unit);
  11512 
  11513     return rv;
  11514 }
  11515 
  11516 /*
  11517  * Function:
  11518  *      bcmi_esw_tsn_ingress_mtu_config_get
  11519  * Purpose:
  11520  *      Get the priority of source ingress
  11521  *      mtu profile index.
  11522  * Parameters:
  11523  *      unit - (IN) Unit number
  11524  *      config - (OUT) Configuration of the mtu profile priority
  11525  * Returns:
  11526  *      BCM_E_xxx
  11527  */
  11528 int
  11529 bcmi_esw_tsn_ingress_mtu_config_get(
  11530     int unit,
  11531     bcm_tsn_ingress_mtu_config_t *config)
  11532 {
  11533     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11534     const tsn_mtu_info_t *ctrl_info = NULL;
  11535     int rv;
  11536 
  11537     if (NULL == config) {
  11538         return BCM_E_PARAM;
  11539     }
  11540 
  11541     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11542     /* Use this init macro after the bk info instance get */
  11543     MTU_DEV_INIT(unit);
  11544     ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
  11545 
  11546     MTU_BK_LOCK(unit);
  11547     rv = ctrl_info->ingress_mtu_config_get(unit, config);
  11548     MTU_BK_UNLOCK(unit);
  11549 
  11550     return rv;
  11551 }
  11552 
  11553 /*
  11554  * Function:
  11555  *      bcmi_tsn_port_control_egress_mtu_set
  11556  * Purpose:
  11557  *      Setup HW memory with pri_map_id and port information
  11558  * Parameters:
  11559  *      unit - (IN) Unit number
  11560  *      port - (IN) port number
  11561  *      pri_map_id - (IN) priority map id
  11562  * Returns:
  11563  *      BCM_E_xxx
  11564  */
  11565 int
  11566 bcmi_tsn_port_control_egress_mtu_set(
  11567     int unit,
  11568     bcm_gport_t gport,
  11569     bcm_tsn_pri_map_t pri_map_id)
  11570 {
  11571     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11572     const tsn_mtu_info_t *ctrl_info = NULL;
  11573 
  11574     bcm_tsn_pri_map_t pre_pri_map_id;
  11575     bcm_tsn_pri_map_config_t config;
  11576     int rv;
  11577     uint32 hw_index;
  11578     bcm_tsn_pri_map_type_t type;
  11579     bcm_port_t port;
  11580 
  11581     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11582     /* Use this init macro after the bk info instance get */
  11583     MTU_DEV_INIT(unit);
  11584     ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
  11585 
  11586     /* Validate and convert gport to local port */
  11587     BCM_IF_ERROR_RETURN(
  11588         _bcm_esw_port_gport_validate(unit, gport, &port));
  11589 
  11590     if (port < 0 || port >= ctrl_info->logical_port_num) {
  11591         LOG_VERBOSE(BSL_LS_BCM_TSN,
  11592                     (BSL_META_U(unit, "Invalid Port Range, should be"
  11593                                 " %d\n"), ctrl_info->logical_port_num));
  11594         return BCM_E_PARAM;
  11595     }
  11596 
  11597     /* use pri_map_invalid to detach the pri_map_id from port*/
  11598     if (pri_map_id == BCM_TSN_PRI_MAP_INVALID) {
  11599         MTU_BK_LOCK(unit);
  11600         pre_pri_map_id = bk_info->tsn_mtu_bk_info.pri_map_port[port];
  11601         if (pre_pri_map_id != BCM_TSN_PRI_MAP_INVALID) {
  11602             (void)bcmi_esw_tsn_pri_map_ref_cnt_dec(unit, pre_pri_map_id);
  11603         }
  11604         bk_info->tsn_mtu_bk_info.pri_map_port[port] = pri_map_id;
  11605         MTU_BK_UNLOCK(unit);
  11606         return BCM_E_NONE;
  11607     }
  11608     /* Check if map id match to the bcmTsnControlEgressMtuPriorityMap */
  11609     BCM_IF_ERROR_RETURN(
  11610         bcmi_esw_tsn_pri_map_hw_index_get(unit, pri_map_id, &type, &hw_index));
  11611     if (type != bcmTsnPriMapTypeEgressMtuProfile) {
  11612         return BCM_E_PARAM;
  11613     }
  11614     rv = bcm_esw_tsn_pri_map_get(unit, pri_map_id, &config);
  11615     BCM_IF_ERROR_RETURN(rv);
  11616 
  11617     if (bk_info->tsn_mtu_bk_info.pri_map_port == NULL) {
  11618         return BCM_E_INTERNAL;
  11619     }
  11620 
  11621     MTU_BK_LOCK(unit);
  11622     /*
  11623      * Store map id into SW egress_mtu_pri_map with the corresponding
  11624      * port number
  11625      */
  11626     /* Increase Priority Map Reference Count */
  11627     rv = bcmi_esw_tsn_pri_map_ref_cnt_inc(unit, pri_map_id);
  11628     if (BCM_FAILURE(rv)) {
  11629         MTU_BK_UNLOCK(unit);
  11630         return rv;
  11631     }
  11632     pre_pri_map_id = bk_info->tsn_mtu_bk_info.pri_map_port[port];
  11633     if (pre_pri_map_id != BCM_TSN_PRI_MAP_INVALID) {
  11634        (void)bcmi_esw_tsn_pri_map_ref_cnt_dec(unit, pre_pri_map_id);
  11635     }
  11636     bk_info->tsn_mtu_bk_info.pri_map_port[port] = pri_map_id;
  11637 
  11638     /*
  11639      * Write into HW memory to store config with the
  11640      * corresponding port number
  11641      */
  11642     rv = ctrl_info->egress_mtu_port_control_set(unit, gport, &config);
  11643     MTU_BK_UNLOCK(unit);
  11644     return rv;
  11645 }
  11646 
  11647 
  11648 /*
  11649  * Function:
  11650  *      bcmi_tsn_port_control_egress_mtu_get
  11651  * Purpose:
  11652  *      get pri_map_id from HW memory with port information
  11653  * Parameters:
  11654  *      unit - (IN) Unit number
  11655  *      port - (IN) port number
  11656  *      pri_map_id - (OUT) priority map id
  11657  * Returns:
  11658  *      BCM_E_xxx
  11659  */
  11660 int
  11661 bcmi_tsn_port_control_egress_mtu_get(
  11662     int unit,
  11663     bcm_gport_t gport,
  11664     bcm_tsn_pri_map_t *pri_map_id)
  11665 {
  11666     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11667     const tsn_mtu_info_t *ctrl_info = NULL;
  11668     bcm_port_t port;
  11669 
  11670     if (pri_map_id == NULL) {
  11671         return BCM_E_PARAM;
  11672     }
  11673 
  11674     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11675     /* Use this init macro after the bk info instance get */
  11676     MTU_DEV_INIT(unit);
  11677     ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
  11678 
  11679     /* Validate and convert gport to local port */
  11680     BCM_IF_ERROR_RETURN(
  11681         _bcm_esw_port_gport_validate(unit, gport, &port));
  11682 
  11683     if (port < 0 || port >= ctrl_info->logical_port_num) {
  11684         LOG_VERBOSE(BSL_LS_BCM_TSN,
  11685                     (BSL_META_U(unit, "Invalid Port Range, should be"
  11686                                 " %d\n"), ctrl_info->logical_port_num));
  11687         return BCM_E_PARAM;
  11688     }
  11689     if (bk_info->tsn_mtu_bk_info.pri_map_port == NULL) {
  11690         return BCM_E_INTERNAL;
  11691     }
  11692     /* retrieve priority map id from the prio_map_port sw data structure */
  11693     MTU_BK_LOCK(unit);
  11694     *pri_map_id = bk_info->tsn_mtu_bk_info.pri_map_port[port];
  11695     MTU_BK_UNLOCK(unit);
  11696     /* the priority map is not store in the specific port number */
  11697     if (*pri_map_id == BCM_TSN_PRI_MAP_INVALID) {
  11698         return BCM_E_EMPTY;
  11699     }
  11700 
  11701     return BCM_E_NONE;
  11702 }
  11703 
  11704 /*
  11705  * Function:
  11706  *      bcmi_tsn_port_control_ingress_mtu_set
  11707  * Purpose:
  11708  *      Setup HW memory with profile id and port information
  11709  * Parameters:
  11710  *      unit - (IN) Unit number
  11711  *      port - (IN) port number
  11712  *      profile_id - (IN) ingress mtu profile id
  11713  * Returns:
  11714  *      BCM_E_xxx
  11715  */
  11716 int
  11717 bcmi_tsn_port_control_ingress_mtu_set(
  11718     int unit,
  11719     bcm_gport_t gport,
  11720     int profile_id)
  11721 {
  11722     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11723     const tsn_mtu_info_t *ctrl_info = NULL;
  11724 
  11725     int rv, index;
  11726     bcm_tsn_mtu_profile_type_t type;
  11727     bcm_port_t port;
  11728     uint32 pre_profile_id;
  11729 
  11730     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11731     /* Use this init macro after the bk info instance get */
  11732     MTU_DEV_INIT(unit);
  11733     ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
  11734 
  11735     /* Validate and convert gport to local port */
  11736     BCM_IF_ERROR_RETURN(
  11737         _bcm_esw_port_gport_validate(unit, gport, &port));
  11738 
  11739     if (port < 0 || port >= ctrl_info->logical_port_num) {
  11740         LOG_VERBOSE(BSL_LS_BCM_TSN,
  11741                     (BSL_META_U(unit, "Invalid Port Range, should be"
  11742                                 " %d\n"), ctrl_info->logical_port_num));
  11743         return BCM_E_PARAM;
  11744     }
  11745     MTU_BK_LOCK(unit);
  11746     rv = ctrl_info->mtu_profile_decode(unit, profile_id, &type, &index);
  11747     if (BCM_FAILURE(rv)) {
  11748         MTU_BK_UNLOCK(unit);
  11749         return rv;
  11750     }
  11751 
  11752     if (type != bcmTsnMtuProfileTypeIngress) {
  11753         MTU_BK_UNLOCK(unit);
  11754         LOG_VERBOSE(BSL_LS_BCM_TSN,
  11755                     (BSL_META_U(unit, "Wrong Profile Type.\n")));
  11756         return BCM_E_PARAM;
  11757     }
  11758     /* detach the previous mtu_profile_id*/
  11759     if (profile_id == 0) {
  11760         rv = bcm_esw_tsn_port_control_get(unit, gport,
  11761                                           bcmTsnControlIngressMtuProfile,
  11762                                           &pre_profile_id);
  11763         if (BCM_FAILURE(rv)) {
  11764             MTU_BK_UNLOCK(unit);
  11765             return rv;
  11766         }
  11767         (void)bcmi_esw_tsn_mtu_profile_ref_dec(unit, pre_profile_id);
  11768         MTU_BK_UNLOCK(unit);
  11769         return BCM_E_NONE;
  11770     }
  11771     rv = ctrl_info->ingress_mtu_port_control_set(unit, gport, index);
  11772     if (BCM_FAILURE(rv)) {
  11773         MTU_BK_UNLOCK(unit);
  11774         return rv;
  11775     }
  11776     (void)bcmi_esw_tsn_mtu_profile_ref_inc(unit, profile_id);
  11777     MTU_BK_UNLOCK(unit);
  11778     return rv;
  11779 }
  11780 
  11781 
  11782 /*
  11783  * Function:
  11784  *      bcmi_tsn_port_control_ingress_mtu_get
  11785  * Purpose:
  11786  *      get profile id from HW memory with port information
  11787  * Parameters:
  11788  *      unit - (IN) Unit number
  11789  *      port - (IN) port number
  11790  *      profile id - (OUT) ingress mtu profile id
  11791  * Returns:
  11792  *      BCM_E_xxx
  11793  */
  11794 int
  11795 bcmi_tsn_port_control_ingress_mtu_get(
  11796     int unit,
  11797     bcm_gport_t gport,
  11798     int *profile_id)
  11799 {
  11800     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11801     const tsn_mtu_info_t *ctrl_info = NULL;
  11802     bcm_port_t port;
  11803 
  11804     int index, rv;
  11805     if (profile_id == NULL) {
  11806         return BCM_E_PARAM;
  11807     }
  11808     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11809     /* Use this init macro after the bk info instance get */
  11810     MTU_DEV_INIT(unit);
  11811     ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
  11812 
  11813     /* Validate and convert gport to local port */
  11814     BCM_IF_ERROR_RETURN(
  11815         _bcm_esw_port_gport_validate(unit, gport, &port));
  11816 
  11817     if (port < 0 || port >= ctrl_info->logical_port_num) {
  11818         LOG_VERBOSE(BSL_LS_BCM_TSN,
  11819                     (BSL_META_U(unit, "Invalid Port Range, should be"
  11820                                 " %d\n"), ctrl_info->logical_port_num));
  11821         return BCM_E_PARAM;
  11822     }
  11823     MTU_BK_LOCK(unit);
  11824     rv = ctrl_info->ingress_mtu_port_control_get(unit, gport, &index);
  11825     if (BCM_FAILURE(rv)) {
  11826         MTU_BK_UNLOCK(unit);
  11827         return rv;
  11828     }
  11829     rv = ctrl_info->mtu_profile_encode(
  11830             unit, index, bcmTsnMtuProfileTypeIngress, profile_id);
  11831     MTU_BK_UNLOCK(unit);
  11832     return rv;
  11833 }
  11834 
  11835 /*
  11836  * Function:
  11837  *      bcmi_esw_tsn_stu_profile_get
  11838  * Purpose:
  11839  *      Get stu profile configuration
  11840  *      with the profile id.
  11841  * Parameters:
  11842  *      unit - (IN) Unit number
  11843  *      stu_profile_id - (IN) Indicated the stu profile entry
  11844  *      type - (OUT) Indicates ingress or egress stu profile
  11845  *      config - (OUT) Configuration of the stu profile
  11846  * Returns:
  11847  *      BCM_E_xxx
  11848  */
  11849 int
  11850 bcmi_esw_tsn_stu_profile_get(
  11851     int unit,
  11852     int stu_profile_id,
  11853     bcm_tsn_stu_profile_type_t *type,
  11854     bcm_tsn_stu_config_t *config)
  11855 {
  11856     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11857     const tsn_stu_info_t *ctrl_info = NULL;
  11858 
  11859     int index, rv;
  11860 
  11861     if (type == NULL || config == NULL) {
  11862         return BCM_E_PARAM;
  11863     }
  11864 
  11865     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11866     /* Use this init macro after the bk info instance get */
  11867     STU_DEV_INIT(unit);
  11868     ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
  11869     STU_BK_LOCK(unit);
  11870     /* this function also check the validity of parameter profile id */
  11871     rv = ctrl_info->stu_profile_decode(unit, stu_profile_id, type, &index);
  11872     if (BCM_FAILURE(rv)) {
  11873         STU_BK_UNLOCK(unit);
  11874         return rv;
  11875     }
  11876     rv = ctrl_info->stu_profile_get(unit, index, *type, config);
  11877     if (BCM_FAILURE(rv)) {
  11878         STU_BK_UNLOCK(unit);
  11879         return rv;
  11880     }
  11881     STU_BK_UNLOCK(unit);
  11882     return BCM_E_NONE;
  11883 }
  11884 
  11885 /*
  11886  * Function:
  11887  *      bcmi_esw_tsn_stu_profile_set
  11888  * Purpose:
  11889  *      Set stu profile with the profile id
  11890  *      and config parameter.
  11891  * Parameters:
  11892  *      unit - (IN) Unit number
  11893  *      stu_profile_id - (IN) Indicated the stu profile entry
  11894  *      config - (IN) Configuration of the stu profile
  11895  * Returns:
  11896  *      BCM_E_xxx
  11897  */
  11898 int
  11899 bcmi_esw_tsn_stu_profile_set(
  11900     int unit,
  11901     int stu_profile_id,
  11902     bcm_tsn_stu_config_t *config)
  11903 {
  11904     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11905     const tsn_stu_info_t *ctrl_info = NULL;
  11906 
  11907     int index, ref_count, rv, min, max;
  11908     bcm_tsn_stu_profile_type_t type;
  11909 
  11910     if (config == NULL) {
  11911         return BCM_E_PARAM;
  11912     }
  11913 
  11914     if (config->size <= 0) {
  11915         LOG_ERROR(BSL_LS_BCM_TSN,
  11916                   (BSL_META_U(unit, "Invalid STU size.\n")));
  11917         return BCM_E_PARAM;
  11918     }
  11919 
  11920     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  11921     /* Use this init macro after the bk info instance get */
  11922     STU_DEV_INIT(unit);
  11923     ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
  11924 
  11925     STU_BK_LOCK(unit);
  11926     /* this function also check the validity of parameter profile id */
  11927     rv = ctrl_info->stu_profile_decode(unit, stu_profile_id, &type, &index);
  11928     if (BCM_FAILURE(rv)) {
  11929         STU_BK_UNLOCK(unit);
  11930         return rv;
  11931     }
  11932 
  11933     /* index 0 in profile memory is the default value */
  11934     if (index == 0) {
  11935         MTU_BK_UNLOCK(unit);
  11936         LOG_WARN(BSL_LS_BCMAPI_TSN,
  11937                 (BSL_META_U(
  11938                   unit, "Profile ID 0 is the default, can't modify it.\n")));
  11939         return BCM_E_PARAM;
  11940     }
  11941 
  11942     rv = ctrl_info->stu_profile_mem_refcnt_get(unit, type, index, &ref_count);
  11943     if (BCM_FAILURE(rv)) {
  11944         STU_BK_UNLOCK(unit);
  11945         return rv;
  11946     }
  11947     /* ref_count > 0, then the entry is created */
  11948     if (ref_count <= 0) {
  11949         STU_BK_UNLOCK(unit);
  11950         LOG_WARN(BSL_LS_BCMAPI_TSN,
  11951                 (BSL_META_U(unit,
  11952                             "MTU Profile entry is not created.\n")));
  11953         return BCM_E_PARAM;
  11954     }
  11955 
  11956     /* the profile entry is referenced by other flows */
  11957     STU_BK_INIT(unit, type);
  11958     ctrl_info->stu_profile_mem_idx_get(unit, type, &min, &max);
  11959     if (index < min || index > max) {
  11960         STU_BK_UNLOCK(unit);
  11961         return BCM_E_PARAM;
  11962     }
  11963     if (bk_info->tsn_stu_bk_info.stu_refcount[type][index] > 0) {
  11964         STU_BK_UNLOCK(unit);
  11965         LOG_WARN(BSL_LS_BCMAPI_TSN,
  11966                 (BSL_META_U(unit,
  11967                             "Flow is in use of Ingress STU Profile\n")));
  11968         return BCM_E_BUSY;
  11969     }
  11970 
  11971     rv = ctrl_info->stu_profile_set(unit, index, type, config);
  11972     if (BCM_FAILURE(rv)) {
  11973         STU_BK_UNLOCK(unit);
  11974         return rv;
  11975     }
  11976     STU_BK_UNLOCK(unit);
  11977     return BCM_E_NONE;
  11978 }
  11979 
  11980 /*
  11981  * Function:
  11982  *      bcmi_esw_tsn_stu_profile_destroy
  11983  * Purpose:
  11984  *      Clear the stu profile with the profile id
  11985  * Parameters:
  11986  *      unit - (IN) Unit number
  11987  *      stu_profile_id - (IN) Indicated the stu profile entry
  11988  * Returns:
  11989  *      BCM_E_xxx
  11990  */
  11991 int
  11992 bcmi_esw_tsn_stu_profile_destroy(
  11993     int unit,
  11994     int stu_profile_id)
  11995 {
  11996     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  11997     const tsn_stu_info_t *ctrl_info = NULL;
  11998 
  11999     bcm_tsn_stu_profile_type_t type;
  12000     int index, rv, min, max;
  12001 
  12002     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  12003     /* Use this init macro after the bk info instance get */
  12004     STU_DEV_INIT(unit);
  12005     ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
  12006 
  12007     /* this function also check the validity of parameter profile id */
  12008     STU_BK_LOCK(unit);
  12009     rv = ctrl_info->stu_profile_decode(unit, stu_profile_id, &type, &index);
  12010     if (BCM_FAILURE(rv)) {
  12011         STU_BK_UNLOCK(unit);
  12012         return rv;
  12013     }
  12014 
  12015     /* index 0 in profile memory is the default value */
  12016     if (index == 0) {
  12017         MTU_BK_UNLOCK(unit);
  12018         LOG_WARN(BSL_LS_BCMAPI_TSN,
  12019                 (BSL_META_U(
  12020                   unit, "Profile ID 0 is the default, can't modify it.\n")));
  12021         return BCM_E_PARAM;
  12022     }
  12023 
  12024     rv = ctrl_info->stu_profile_mem_idx_get(unit, type, &min, &max);
  12025     if (BCM_FAILURE(rv)) {
  12026         STU_BK_UNLOCK(unit);
  12027         return rv;
  12028     }
  12029     STU_BK_INIT(unit, type);
  12030     /* the profile entry is referenced bt other flows */
  12031     if (index < min || index > max) {
  12032         STU_BK_UNLOCK(unit);
  12033         return BCM_E_PARAM;
  12034     }
  12035     if (bk_info->tsn_stu_bk_info.stu_refcount[type][index] != 0) {
  12036         STU_BK_UNLOCK(unit);
  12037         LOG_WARN(BSL_LS_BCMAPI_TSN,
  12038                 (BSL_META_U(unit,
  12039                             "Flow is in use of Ingress STU Profile\n")));
  12040         return BCM_E_EXISTS;
  12041     }
  12042 
  12043     rv = ctrl_info->stu_profile_destroy(unit, type, index);
  12044     STU_BK_UNLOCK(unit);
  12045 
  12046     return rv;
  12047 }
  12048 
  12049 /*
  12050  * Function:
  12051  *      bcmi_esw_tsn_stu_profile_create
  12052  * Purpose:
  12053  *      Create stu profile with the config pointer
  12054  *      and return the assigned profile id.
  12055  * Parameters:
  12056  *      unit - (IN) Unit number
  12057  *      type - (IN) Indicates ingress or egress stu profile
  12058  *      config - (IN) configuration of the stu profile
  12059  *      stu_profile_id - (OUT) profile id
  12060  * Returns:
  12061  *      BCM_E_xxx
  12062  */
  12063 int
  12064 bcmi_esw_tsn_stu_profile_create(
  12065     int unit,
  12066     bcm_tsn_stu_profile_type_t type,
  12067     bcm_tsn_stu_config_t *config,
  12068     int *stu_profile_id)
  12069 {
  12070     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  12071     const tsn_stu_info_t *ctrl_info = NULL;
  12072 
  12073     int ref_count, rv, rv1;
  12074     uint32 index;
  12075 
  12076     if (config == NULL || stu_profile_id == NULL) {
  12077         return BCM_E_PARAM;
  12078     }
  12079 
  12080     if (config->size <= 0) {
  12081         LOG_ERROR(BSL_LS_BCM_TSN,
  12082                   (BSL_META_U(unit, "Invalid STU size.\n")));
  12083         return BCM_E_PARAM;
  12084     }
  12085 
  12086     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  12087     /* Use this init macro after the bk info instance get */
  12088     STU_DEV_INIT(unit);
  12089     ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
  12090 
  12091     /* Check the validity of the type */
  12092     if (type != bcmTsnStuProfileTypeIngress &&
  12093         type != bcmTsnStuProfileTypeEgress) {
  12094         LOG_VERBOSE(BSL_LS_BCM_TSN,
  12095                     (BSL_META_U(unit, "Wrong Profile Type.\n")));
  12096         return BCM_E_PARAM;
  12097     }
  12098 
  12099     STU_BK_LOCK(unit);
  12100     rv = ctrl_info->stu_profile_create(unit, type, config, &index);
  12101     if (BCM_FAILURE(rv)) {
  12102         STU_BK_UNLOCK(unit);
  12103         return rv;
  12104     }
  12105     rv = ctrl_info->stu_profile_mem_refcnt_get(unit, type, index, &ref_count);
  12106     if (BCM_FAILURE(rv)) {
  12107         rv1 = ctrl_info->stu_profile_destroy(unit, type, index);
  12108         if (BCM_FAILURE(rv1)) {
  12109             STU_BK_UNLOCK(unit);
  12110             return rv1;
  12111         }
  12112         STU_BK_UNLOCK(unit);
  12113         return rv;
  12114     }
  12115 
  12116     /* Encode the stu profile id */
  12117     rv = ctrl_info->stu_profile_encode(unit, index, type, stu_profile_id);
  12118     if (BCM_FAILURE(rv)) {
  12119         rv1 = ctrl_info->stu_profile_destroy(unit, type, index);
  12120         if (BCM_FAILURE(rv1)) {
  12121             STU_BK_UNLOCK(unit);
  12122             return rv1;
  12123         }
  12124         STU_BK_UNLOCK(unit);
  12125         return rv;
  12126     }
  12127 
  12128     /* ref_count > 1 indicates replicated stu profile is created */
  12129     if (ref_count > 1) {
  12130         if (type == bcmTsnStuProfileTypeIngress) {
  12131             LOG_WARN(BSL_LS_BCMAPI_TSN,
  12132                      (BSL_META_U(unit,
  12133                                  "config already existed, "
  12134                                  "found ingress stu profile id(%d)\n"),
  12135                                  *stu_profile_id));
  12136         } else {
  12137             LOG_WARN(BSL_LS_BCMAPI_TSN,
  12138                      (BSL_META_U(unit,
  12139                                  "config already existed, "
  12140                                  "found egress stu profile id(%d)\n"),
  12141                                  *stu_profile_id));
  12142         }
  12143     }
  12144 
  12145     STU_BK_UNLOCK(unit);
  12146     return BCM_E_NONE;
  12147 }
  12148 /*
  12149  * Function:
  12150  *      bcmi_esw_tsn_stu_profile_traverse
  12151  * Purpose:
  12152  *      Traverse the created match config.
  12153  * Parameters:
  12154  *      unit - (IN) Unit number
  12155  *      cb - (IN) Traverse call back function
  12156  *      user_data - (IN) User data
  12157  * Returns:
  12158  *      BCM_E_xxx
  12159  */
  12160 int
  12161 bcmi_esw_tsn_stu_profile_traverse(
  12162     int unit,
  12163     bcm_tsn_stu_profile_traverse_cb cb,
  12164     void *user_data)
  12165 {
  12166     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  12167     const tsn_stu_info_t *ctrl_info = NULL;
  12168     int rv;
  12169 
  12170     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  12171     /* Use this init macro after the bk info instance get */
  12172     STU_DEV_INIT(unit);
  12173     ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
  12174 
  12175     STU_BK_LOCK(unit);
  12176     rv = ctrl_info->stu_profile_traverse(unit, cb, user_data);
  12177     STU_BK_UNLOCK(unit);
  12178 
  12179     return rv;
  12180 
  12181 }
  12182 
  12183 
  12184 /*
  12185  * Function:
  12186  *      bcmi_esw_tsn_ingress_stu_config_set
  12187  * Purpose:
  12188  *      Set the priority of source ingress
  12189  *      stu profile index.
  12190  * Parameters:
  12191  *      unit - (IN) Unit number
  12192  *      config - (IN) Configuration of the stu profile priority
  12193  * Returns:
  12194  *      BCM_E_xxx
  12195  */
  12196 int
  12197 bcmi_esw_tsn_ingress_stu_config_set(
  12198     int unit,
  12199     bcm_tsn_ingress_stu_config_t *config)
  12200 {
  12201     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  12202     const tsn_stu_info_t *ctrl_info = NULL;
  12203     int rv;
  12204 
  12205     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  12206     /* Use this init macro after the bk info instance get */
  12207     STU_DEV_INIT(unit);
  12208     ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
  12209 
  12210     if (config == NULL) {
  12211         return BCM_E_PARAM;
  12212     }
  12213 
  12214     STU_BK_LOCK(unit);
  12215     rv = ctrl_info->ingress_stu_config_set(unit, config);
  12216     STU_BK_UNLOCK(unit);
  12217 
  12218     return rv;
  12219 }
  12220 
  12221 /*
  12222  * Function:
  12223  *      bcmi_esw_tsn_ingress_stu_config_get
  12224  * Purpose:
  12225  *      Get the priority of source ingress
  12226  *      stu profile index.
  12227  * Parameters:
  12228  *      unit - (IN) Unit number
  12229  *      config - (OUT) Configuration of the stu profile priority
  12230  * Returns:
  12231  *      BCM_E_xxx
  12232  */
  12233 int
  12234 bcmi_esw_tsn_ingress_stu_config_get(
  12235     int unit,
  12236     bcm_tsn_ingress_stu_config_t *config)
  12237 {
  12238     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  12239     const tsn_stu_info_t *ctrl_info = NULL;
  12240     int rv;
  12241 
  12242     if (NULL == config) {
  12243         return BCM_E_PARAM;
  12244     }
  12245 
  12246     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  12247     /* Use this init macro after the bk info instance get */
  12248     STU_DEV_INIT(unit);
  12249     ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
  12250 
  12251     STU_BK_LOCK(unit);
  12252     rv = ctrl_info->ingress_stu_config_get(unit, config);
  12253     STU_BK_UNLOCK(unit);
  12254 
  12255     return rv;
  12256 }
  12257 
  12258 /*
  12259  * Function:
  12260  *      bcmi_tsn_port_control_egress_stu_set
  12261  * Purpose:
  12262  *      Setup HW memory with pri_map_id and port information
  12263  * Parameters:
  12264  *      unit - (IN) Unit number
  12265  *      port - (IN) port number
  12266  *      pri_map_id - (IN) priority map id
  12267  * Returns:
  12268  *      BCM_E_xxx
  12269  */
  12270 int
  12271 bcmi_tsn_port_control_egress_stu_set(
  12272     int unit,
  12273     bcm_gport_t gport,
  12274     bcm_tsn_pri_map_t pri_map_id)
  12275 {
  12276     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  12277     const tsn_stu_info_t *ctrl_info = NULL;
  12278 
  12279     bcm_tsn_pri_map_t pre_pri_map_id;
  12280     bcm_tsn_pri_map_config_t config;
  12281     int rv;
  12282     uint32 hw_index;
  12283     bcm_tsn_pri_map_type_t type;
  12284     bcm_port_t port;
  12285 
  12286     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  12287     /* Use this init macro after the bk info instance get */
  12288     STU_DEV_INIT(unit);
  12289     ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
  12290 
  12291     /* Validate and convert gport to local port */
  12292     BCM_IF_ERROR_RETURN(
  12293         _bcm_esw_port_gport_validate(unit, gport, &port));
  12294 
  12295     if (port < 0 || port >= ctrl_info->logical_port_num) {
  12296         LOG_VERBOSE(BSL_LS_BCM_TSN,
  12297                     (BSL_META_U(unit, "Invalid Port Range, should be"
  12298                                 " %d\n"), ctrl_info->logical_port_num));
  12299         return BCM_E_PARAM;
  12300     }
  12301 
  12302     /* use pri_map_invalid to detach the pri_map_id from port*/
  12303     if (pri_map_id == BCM_TSN_PRI_MAP_INVALID) {
  12304         STU_BK_LOCK(unit);
  12305         pre_pri_map_id = bk_info->tsn_stu_bk_info.pri_map_port[port];
  12306         if (pre_pri_map_id != BCM_TSN_PRI_MAP_INVALID) {
  12307             (void)bcmi_esw_tsn_pri_map_ref_cnt_dec(unit, pre_pri_map_id);
  12308         }
  12309         bk_info->tsn_stu_bk_info.pri_map_port[port] = pri_map_id;
  12310         STU_BK_UNLOCK(unit);
  12311         return BCM_E_NONE;
  12312     }
  12313     /* Check if map id match to the bcmTsnControlEgressStuPriorityMap */
  12314     BCM_IF_ERROR_RETURN(
  12315         bcmi_esw_tsn_pri_map_hw_index_get(unit, pri_map_id, &type, &hw_index));
  12316     if (type != bcmTsnPriMapTypeEgressStuProfile) {
  12317         return BCM_E_PARAM;
  12318     }
  12319     rv = bcm_esw_tsn_pri_map_get(unit, pri_map_id, &config);
  12320     BCM_IF_ERROR_RETURN(rv);
  12321 
  12322     if (bk_info->tsn_stu_bk_info.pri_map_port == NULL) {
  12323         return BCM_E_INTERNAL;
  12324     }
  12325 
  12326     STU_BK_LOCK(unit);
  12327     /*
  12328      * Store map id into SW egress_stu_pri_map with the corresponding
  12329      * port number
  12330      */
  12331     /* Increase Priority Map Reference Count */
  12332     rv = bcmi_esw_tsn_pri_map_ref_cnt_inc(unit, pri_map_id);
  12333     if (BCM_FAILURE(rv)) {
  12334         STU_BK_UNLOCK(unit);
  12335         return rv;
  12336     }
  12337     pre_pri_map_id = bk_info->tsn_stu_bk_info.pri_map_port[port];
  12338     if (pre_pri_map_id != BCM_TSN_PRI_MAP_INVALID) {
  12339        (void)bcmi_esw_tsn_pri_map_ref_cnt_dec(unit, pre_pri_map_id);
  12340     }
  12341     bk_info->tsn_stu_bk_info.pri_map_port[port] = pri_map_id;
  12342 
  12343     /*
  12344      * Write into HW memory to store config with the
  12345      * corresponding port number
  12346      */
  12347     rv = ctrl_info->egress_stu_port_control_set(unit, port, &config);
  12348     STU_BK_UNLOCK(unit);
  12349     return rv;
  12350 }
  12351 
  12352 
  12353 /*
  12354  * Function:
  12355  *      bcmi_tsn_port_control_egress_stu_get
  12356  * Purpose:
  12357  *      get pri_map_id from HW memory with port information
  12358  * Parameters:
  12359  *      unit - (IN) Unit number
  12360  *      port - (IN) port number
  12361  *      pri_map_id - (OUT) priority map id
  12362  * Returns:
  12363  *      BCM_E_xxx
  12364  */
  12365 int
  12366 bcmi_tsn_port_control_egress_stu_get(
  12367     int unit,
  12368     bcm_gport_t gport,
  12369     bcm_tsn_pri_map_t *pri_map_id)
  12370 {
  12371     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  12372     const tsn_stu_info_t *ctrl_info = NULL;
  12373     bcm_port_t port;
  12374 
  12375     if (pri_map_id == NULL) {
  12376         return BCM_E_PARAM;
  12377     }
  12378 
  12379     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  12380     /* Use this init macro after the bk info instance get */
  12381     STU_DEV_INIT(unit);
  12382     ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
  12383 
  12384     /* Validate and convert gport to local port */
  12385     BCM_IF_ERROR_RETURN(
  12386         _bcm_esw_port_gport_validate(unit, gport, &port));
  12387 
  12388     if (port < 0 || port >= ctrl_info->logical_port_num) {
  12389         LOG_VERBOSE(BSL_LS_BCM_TSN,
  12390                     (BSL_META_U(unit, "Invalid Port Range, should be"
  12391                                 " %d\n"), ctrl_info->logical_port_num));
  12392 
  12393         return BCM_E_PARAM;
  12394     }
  12395     if (bk_info->tsn_stu_bk_info.pri_map_port == NULL) {
  12396         return BCM_E_INTERNAL;
  12397     }
  12398     /* retrieve priority map id from the prio_map_port sw data structure */
  12399     STU_BK_LOCK(unit);
  12400     *pri_map_id = bk_info->tsn_stu_bk_info.pri_map_port[port];
  12401     STU_BK_UNLOCK(unit);
  12402     /* the priority map is not store in the specific port number */
  12403     if (*pri_map_id == BCM_TSN_PRI_MAP_INVALID) {
  12404         return BCM_E_EMPTY;
  12405     }
  12406 
  12407     return BCM_E_NONE;
  12408 }
  12409 
  12410 /*
  12411  * Function:
  12412  *      bcmi_tsn_port_control_ingress_stu_set
  12413  * Purpose:
  12414  *      Setup HW memory with profile id and port information
  12415  * Parameters:
  12416  *      unit - (IN) Unit number
  12417  *      port - (IN) port number
  12418  *      profile_id - (IN) ingress stu profile id
  12419  * Returns:
  12420  *      BCM_E_xxx
  12421  */
  12422 int
  12423 bcmi_tsn_port_control_ingress_stu_set(
  12424     int unit,
  12425     bcm_gport_t gport,
  12426     int profile_id)
  12427 {
  12428     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  12429     const tsn_stu_info_t *ctrl_info = NULL;
  12430 
  12431     int rv, index;
  12432     bcm_tsn_stu_profile_type_t type;
  12433     bcm_port_t port;
  12434     uint32 pre_profile_id;
  12435 
  12436     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  12437     /* Use this init macro after the bk info instance get */
  12438     STU_DEV_INIT(unit);
  12439     ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
  12440 
  12441     /* Validate and convert gport to local port */
  12442     BCM_IF_ERROR_RETURN(
  12443         _bcm_esw_port_gport_validate(unit, gport, &port));
  12444 
  12445     if (port < 0 || port >= ctrl_info->logical_port_num) {
  12446         LOG_VERBOSE(BSL_LS_BCM_TSN,
  12447                     (BSL_META_U(unit, "Invalid Port Range, should be"
  12448                                 " %d\n"), ctrl_info->logical_port_num));
  12449         return BCM_E_PARAM;
  12450     }
  12451     STU_BK_LOCK(unit);
  12452     rv = ctrl_info->stu_profile_decode(unit, profile_id, &type, &index);
  12453     if (BCM_FAILURE(rv)) {
  12454         STU_BK_UNLOCK(unit);
  12455         return rv;
  12456     }
  12457 
  12458     if (type != bcmTsnStuProfileTypeIngress) {
  12459         STU_BK_UNLOCK(unit);
  12460         LOG_VERBOSE(BSL_LS_BCM_TSN,
  12461                     (BSL_META_U(unit, "Wrong Profile Type.\n")));
  12462         return BCM_E_PARAM;
  12463     }
  12464     /* detach the previous mtu_profile_id*/
  12465     if (profile_id == 0) {
  12466         rv = bcm_esw_tsn_port_control_get(unit, gport,
  12467                                           bcmTsnControlIngressStuProfile,
  12468                                           &pre_profile_id);
  12469         if (BCM_FAILURE(rv)) {
  12470             STU_BK_UNLOCK(unit);
  12471             return rv;
  12472         }
  12473         (void)bcmi_esw_tsn_stu_profile_ref_dec(unit, pre_profile_id);
  12474         STU_BK_UNLOCK(unit);
  12475         return BCM_E_NONE;
  12476     }
  12477     rv = ctrl_info->ingress_stu_port_control_set(unit, gport, index);
  12478     if (BCM_FAILURE(rv)) {
  12479         STU_BK_UNLOCK(unit);
  12480         return rv;
  12481     }
  12482     (void)bcmi_esw_tsn_stu_profile_ref_inc(unit, profile_id);
  12483     STU_BK_UNLOCK(unit);
  12484     return rv;
  12485 }
  12486 
  12487 
  12488 /*
  12489  * Function:
  12490  *      bcmi_tsn_port_control_ingress_stu_get
  12491  * Purpose:
  12492  *      get profile id from HW memory with port information
  12493  * Parameters:
  12494  *      unit - (IN) Unit number
  12495  *      port - (IN) port number
  12496  *      profile id - (OUT) ingress stu profile id
  12497  * Returns:
  12498  *      BCM_E_xxx
  12499  */
  12500 int
  12501 bcmi_tsn_port_control_ingress_stu_get(
  12502     int unit,
  12503     bcm_gport_t gport,
  12504     int *profile_id)
  12505 {
  12506     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  12507     const tsn_stu_info_t *ctrl_info = NULL;
  12508     bcm_port_t port;
  12509 
  12510     int index, rv;
  12511     if (profile_id == NULL) {
  12512         return BCM_E_PARAM;
  12513     }
  12514     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  12515     /* Use this init macro after the bk info instance get */
  12516     STU_DEV_INIT(unit);
  12517     ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
  12518 
  12519     /* Validate and convert gport to local port */
  12520     BCM_IF_ERROR_RETURN(
  12521         _bcm_esw_port_gport_validate(unit, gport, &port));
  12522 
  12523     if (port < 0 || port >= ctrl_info->logical_port_num) {
  12524         LOG_VERBOSE(BSL_LS_BCM_TSN,
  12525                     (BSL_META_U(unit, "Invalid Port Range, should be"
  12526                                 " %d\n"), ctrl_info->logical_port_num));
  12527         return BCM_E_PARAM;
  12528     }
  12529     STU_BK_LOCK(unit);
  12530     rv = ctrl_info->ingress_stu_port_control_get(unit, gport, &index);
  12531     if (BCM_FAILURE(rv)) {
  12532         STU_BK_UNLOCK(unit);
  12533         return rv;
  12534     }
  12535     rv = ctrl_info->stu_profile_encode(
  12536             unit, index, bcmTsnStuProfileTypeIngress, profile_id);
  12537     STU_BK_UNLOCK(unit);
  12538     return rv;
  12539 }
  12540 
  12541 /*
  12542  * Function:
  12543  *     bcmi_esw_tsn_port_control_set
  12544  * Description:
  12545  *     Internal function for configure port-based operation modes.
  12546  * Parameters:
  12547  *     unit - (IN) Unit number.
  12548  *     port - (IN) Port number.
  12549  *     type - (IN) Control type of bcm_tsn_control_t.
  12550  *     arg  - (IN) argument to be set
  12551  * Returns:
  12552  *     BCM_E_XXX
  12553  */
  12554 STATIC int
  12555 bcmi_esw_tsn_port_control_set(
  12556     int unit,
  12557     bcm_gport_t port,
  12558     bcm_tsn_control_t type,
  12559     uint32 arg)
  12560 {
  12561     if (type == bcmTsnControlEgressMtuPriorityMap) {
  12562         if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  12563             return bcmi_tsn_port_control_egress_mtu_set(unit, port, arg);
  12564         } else {
  12565             return BCM_E_UNAVAIL;
  12566         }
  12567     } else if (type == bcmTsnControlIngressMtuProfile) {
  12568         if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  12569             return bcmi_tsn_port_control_ingress_mtu_set(unit, port, arg);
  12570         } else {
  12571             return BCM_E_UNAVAIL;
  12572         }
  12573     } else if (type == bcmTsnControlEgressStuPriorityMap) {
  12574         if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  12575             return bcmi_tsn_port_control_egress_stu_set(unit, port, arg);
  12576         } else {
  12577             return BCM_E_UNAVAIL;
  12578         }
  12579     } else if (type == bcmTsnControlIngressStuProfile) {
  12580         if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  12581             return bcmi_tsn_port_control_ingress_stu_set(unit, port, arg);
  12582         } else {
  12583             return BCM_E_UNAVAIL;
  12584         }
  12585     } else if (type == bcmTsnControlTafGatePriMap) {
  12586         if (soc_feature(unit, soc_feature_tsn_taf)) {
  12587             uint32 hw_index;
  12588             bcm_tsn_pri_map_type_t map;
  12589 
  12590             if (arg == (uint32)BCM_TSN_PRI_MAP_INVALID) {
  12591                 hw_index = 0;
  12592             } else {
  12593                 BCM_IF_ERROR_RETURN(
  12594                     bcmi_esw_tsn_pri_map_hw_index_get(unit, arg, &map,
  12595                                                       &hw_index));
  12596                 if (map != bcmTsnPriMapTypeTafGate) {
  12597                     return BCM_E_PARAM;
  12598                 }
  12599             }
  12600             return bcmi_esw_tsn_taf_port_control_set(unit, port, type,
  12601                                                      hw_index);
  12602         } else {
  12603             return BCM_E_UNAVAIL;
  12604         }
  12605     } else if (type == bcmTsnControlTafEnable ||
  12606                type == bcmTsnControlTafGatePriMapL2Select) {
  12607         if (soc_feature(unit, soc_feature_tsn_taf)) {
  12608             return bcmi_esw_tsn_taf_port_control_set(unit, port, type, arg);
  12609         } else {
  12610             return BCM_E_UNAVAIL;
  12611         }
  12612     }
  12613     return BCM_E_UNAVAIL;
  12614 }
  12615 
  12616 /*
  12617  * Function:
  12618  *     bcmi_esw_tsn_port_control_get
  12619  * Description:
  12620  *     Internal function for get the configure of port-based operation modes.
  12621  * Parameters:
  12622  *     unit - (IN) Unit number.
  12623  *     port - (IN) Port number.
  12624  *     type - (IN) Control type of bcm_tsn_control_t.
  12625  *     arg  - (OUT) argument got
  12626  * Returns:
  12627  *     BCM_E_XXX
  12628  */
  12629 STATIC int
  12630 bcmi_esw_tsn_port_control_get(
  12631     int unit,
  12632     bcm_gport_t port,
  12633     bcm_tsn_control_t type,
  12634     uint32 *arg)
  12635 {
  12636     if (arg == NULL) {
  12637         return BCM_E_PARAM;
  12638     }
  12639 
  12640     if (type == bcmTsnControlEgressMtuPriorityMap) {
  12641         if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  12642             return bcmi_tsn_port_control_egress_mtu_get(
  12643                        unit, port, (bcm_tsn_pri_map_t *)arg);
  12644         } else {
  12645             return BCM_E_UNAVAIL;
  12646         }
  12647     } else if (type == bcmTsnControlIngressMtuProfile) {
  12648         if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  12649             return bcmi_tsn_port_control_ingress_mtu_get(
  12650                        unit, port, (int *)arg);
  12651         } else {
  12652             return BCM_E_UNAVAIL;
  12653         }
  12654     } else if (type == bcmTsnControlEgressStuPriorityMap) {
  12655         if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  12656             return bcmi_tsn_port_control_egress_stu_get(
  12657                        unit, port, (bcm_tsn_pri_map_t *)arg);
  12658         } else {
  12659             return BCM_E_UNAVAIL;
  12660         }
  12661     } else if (type == bcmTsnControlIngressStuProfile) {
  12662         if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  12663             return bcmi_tsn_port_control_ingress_stu_get(
  12664                        unit, port, (int *)arg);
  12665         } else {
  12666             return BCM_E_UNAVAIL;
  12667         }
  12668     } else if (type == bcmTsnControlTafGatePriMap) {
  12669         if (soc_feature(unit, soc_feature_tsn_taf)) {
  12670             uint32 hw_index;
  12671             bcm_tsn_pri_map_t sw_index;
  12672 
  12673             BCM_IF_ERROR_RETURN(
  12674                 bcmi_esw_tsn_taf_port_control_get(unit, port, type, &hw_index));
  12675 
  12676             if (0 == hw_index) {
  12677                 sw_index = BCM_TSN_PRI_MAP_INVALID;
  12678             } else {
  12679                 BCM_IF_ERROR_RETURN(
  12680                     bcmi_esw_tsn_pri_map_map_id_get(
  12681                         unit, bcmTsnPriMapTypeTafGate, hw_index, &sw_index));
  12682             }
  12683             *arg = (uint32)sw_index;
  12684             return BCM_E_NONE;
  12685         } else {
  12686             return BCM_E_UNAVAIL;
  12687         }
  12688     } else if (type == bcmTsnControlTafEnable ||
  12689                type == bcmTsnControlTafGatePriMapL2Select) {
  12690         if (soc_feature(unit, soc_feature_tsn_taf)) {
  12691             return bcmi_esw_tsn_taf_port_control_get(unit, port, type, arg);
  12692         } else {
  12693             return BCM_E_UNAVAIL;
  12694         }
  12695     }
  12696     return BCM_E_UNAVAIL;
  12697 }
  12698 
  12699 /*
  12700  * Function:
  12701  *     bcmi_esw_tsn_mtu_cleanup
  12702  * Purpose:
  12703  *     Internal function to clear the resource of the TSN module.
  12704  * Parameters:
  12705  *     unit             - (IN) unit number
  12706  * Returns:
  12707  *     BCM_E_XXX
  12708  */
  12709 STATIC int
  12710 bcmi_esw_tsn_mtu_cleanup(int unit)
  12711 {
  12712 
  12713     bcm_tsn_mtu_profile_type_t type;
  12714     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  12715 
  12716     LOG_VERBOSE(BSL_LS_BCM_TSN,
  12717                 (BSL_META_U(unit,
  12718                             "bcmi_esw_tsn_mtu_cleanup\n")));
  12719 
  12720     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  12721         BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  12722         /* Free and clear the mtu bookkeeping info structure */
  12723         if (bk_info->tsn_mtu_bk_info.mutex != NULL) {
  12724             sal_mutex_destroy(bk_info->tsn_mtu_bk_info.mutex);
  12725             bk_info->tsn_mtu_bk_info.mutex = NULL;
  12726         }
  12727         for (type = bcmTsnMtuProfileTypeIngress;
  12728              type < bcmTsnMtuProfileTypeCount; type++) {
  12729             if (bk_info->tsn_mtu_bk_info.mtu_refcount[type] != NULL) {
  12730                 TSN_FREE(unit,
  12731                          bk_info->tsn_mtu_bk_info.mtu_refcount[type], 0);
  12732                 bk_info->tsn_mtu_bk_info.mtu_refcount[type] = NULL;
  12733             }
  12734         }
  12735         if (bk_info->tsn_mtu_bk_info.pri_map_port != NULL) {
  12736             TSN_FREE(unit,
  12737                      bk_info->tsn_mtu_bk_info.pri_map_port, 0);
  12738             bk_info->tsn_mtu_bk_info.pri_map_port = NULL;
  12739         }
  12740     }
  12741     return BCM_E_NONE;
  12742 }
  12743 
  12744 
  12745 /*
  12746  * Function:
  12747  *      bcmi_esw_tsn_mtu_init
  12748  * Purpose:
  12749  *      create a default profile setting
  12750  * Parameters:
  12751  *      unit - (IN) Unit number
  12752  * Returns:
  12753  *      BCM_E_xxx
  12754  */
  12755 STATIC int
  12756 bcmi_esw_tsn_mtu_init(int unit)
  12757 {
  12758     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  12759     int rv = BCM_E_NONE;
  12760     int i, min, max, alloc_size;
  12761     const tsn_mtu_info_t *ctrl_info = NULL;
  12762     bcm_tsn_mtu_profile_type_t type;
  12763 
  12764     BCM_IF_ERROR_RETURN(
  12765         tsn_bk_info_instance_get(unit, &bk_info));
  12766     /* Allocate MTU bookkeeping structure */
  12767     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  12768         MTU_DEV_INIT(unit);
  12769         ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info;
  12770         for (type = bcmTsnMtuProfileTypeIngress;
  12771              type < bcmTsnMtuProfileTypeCount; type++) {
  12772             if (bk_info->tsn_mtu_bk_info.mtu_refcount[type] == NULL) {
  12773                 ctrl_info->mtu_profile_mem_idx_get(unit, type, &min, &max);
  12774                 alloc_size = (max - min + 1) * sizeof(int);
  12775                 TSN_ALLOC(unit, bk_info->tsn_mtu_bk_info.mtu_refcount[type],
  12776                           int, alloc_size, "Ingress MTU Reference Count",
  12777                           0, rv);
  12778             }
  12779             if (BCM_FAILURE(rv)) {
  12780                 LOG_VERBOSE(BSL_LS_BCM_TSN,
  12781                             (BSL_META_U(unit,
  12782                                         "bcmi_esw_tsn_init: failed to "
  12783                                         "allocate memory\n")));
  12784                 return rv;
  12785             }
  12786         }
  12787         if (bk_info->tsn_mtu_bk_info.pri_map_port == NULL) {
  12788             alloc_size =
  12789                 ctrl_info->logical_port_num * sizeof(bcm_tsn_pri_map_t);
  12790             TSN_ALLOC(unit, bk_info->tsn_mtu_bk_info.pri_map_port,
  12791                       bcm_tsn_pri_map_t, alloc_size,
  12792                       "MTU Priority Map Port Array", 0, rv);
  12793         }
  12794         if (BCM_FAILURE(rv)) {
  12795             LOG_VERBOSE(BSL_LS_BCM_TSN,
  12796                         (BSL_META_U(unit,
  12797                                     "bcmi_esw_tsn_init: failed to "
  12798                                     "allocate memory\n")));
  12799             return rv;
  12800         }
  12801         /* Initialize pri_map_port array */
  12802         for (i = 0; i < ctrl_info->logical_port_num; i++) {
  12803             bk_info->tsn_mtu_bk_info.pri_map_port[i] = BCM_TSN_PRI_MAP_INVALID;
  12804         }
  12805         /* Create MTU mutex */
  12806         bk_info->tsn_mtu_bk_info.mutex = sal_mutex_create("mtu_mutex");
  12807         if (bk_info->tsn_mtu_bk_info.mutex == NULL) {
  12808             return BCM_E_MEMORY;
  12809         }
  12810     }
  12811     return BCM_E_NONE;
  12812 }
  12813 
  12814 /*
  12815  * Function:
  12816  *     bcmi_esw_tsn_stu_cleanup
  12817  * Purpose:
  12818  *     Internal function to clear the resource of the TSN module.
  12819  * Parameters:
  12820  *     unit             - (IN) unit number
  12821  * Returns:
  12822  *     BCM_E_XXX
  12823  */
  12824 STATIC int
  12825 bcmi_esw_tsn_stu_cleanup(int unit)
  12826 {
  12827 
  12828     bcm_tsn_stu_profile_type_t type;
  12829     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  12830 
  12831     LOG_VERBOSE(BSL_LS_BCM_TSN,
  12832                 (BSL_META_U(unit,
  12833                             "bcmi_esw_tsn_stu_cleanup\n")));
  12834 
  12835     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  12836         BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  12837         /* Free and clear the stu bookkeeping info structure */
  12838         if (bk_info->tsn_stu_bk_info.mutex != NULL) {
  12839             sal_mutex_destroy(bk_info->tsn_stu_bk_info.mutex);
  12840             bk_info->tsn_stu_bk_info.mutex = NULL;
  12841         }
  12842         for (type = bcmTsnStuProfileTypeIngress;
  12843              type < bcmTsnStuProfileTypeCount; type++) {
  12844             if (bk_info->tsn_stu_bk_info.stu_refcount[type] != NULL) {
  12845                 TSN_FREE(unit,
  12846                          bk_info->tsn_stu_bk_info.stu_refcount[type], 0);
  12847                 bk_info->tsn_stu_bk_info.stu_refcount[type] = NULL;
  12848             }
  12849         }
  12850         if (bk_info->tsn_stu_bk_info.pri_map_port != NULL) {
  12851             TSN_FREE(unit,
  12852                      bk_info->tsn_stu_bk_info.pri_map_port, 0);
  12853             bk_info->tsn_stu_bk_info.pri_map_port = NULL;
  12854         }
  12855     }
  12856     return BCM_E_NONE;
  12857 }
  12858 
  12859 
  12860 /*
  12861  * Function:
  12862  *      bcmi_esw_tsn_stu_init
  12863  * Purpose:
  12864  *      create a default profile setting
  12865  * Parameters:
  12866  *      unit - (IN) Unit number
  12867  * Returns:
  12868  *      BCM_E_xxx
  12869  */
  12870 STATIC int
  12871 bcmi_esw_tsn_stu_init(int unit)
  12872 {
  12873     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  12874     int rv = BCM_E_NONE;
  12875     int i, min, max, alloc_size;
  12876     const tsn_stu_info_t *ctrl_info = NULL;
  12877     bcm_tsn_stu_profile_type_t type;
  12878 
  12879     BCM_IF_ERROR_RETURN(
  12880         tsn_bk_info_instance_get(unit, &bk_info));
  12881     /* Allocate STU bookkeeping structure */
  12882     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  12883         STU_DEV_INIT(unit);
  12884         ctrl_info = bk_info->tsn_dev_info->tsn_stu_info;
  12885         for (type = bcmTsnStuProfileTypeIngress;
  12886              type < bcmTsnStuProfileTypeCount; type++) {
  12887             if (bk_info->tsn_stu_bk_info.stu_refcount[type] == NULL) {
  12888                 ctrl_info->stu_profile_mem_idx_get(unit, type, &min, &max);
  12889                 alloc_size = (max - min + 1) * sizeof(int);
  12890                 TSN_ALLOC(unit, bk_info->tsn_stu_bk_info.stu_refcount[type],
  12891                           int, alloc_size, "Ingress STU Reference Count",
  12892                           0, rv);
  12893             }
  12894             if (BCM_FAILURE(rv)) {
  12895                 LOG_VERBOSE(BSL_LS_BCM_TSN,
  12896                             (BSL_META_U(unit,
  12897                                         "bcmi_esw_tsn_init: failed to "
  12898                                         "allocate memory\n")));
  12899                 return rv;
  12900             }
  12901         }
  12902         if (bk_info->tsn_stu_bk_info.pri_map_port == NULL) {
  12903             alloc_size =
  12904                 ctrl_info->logical_port_num * sizeof(bcm_tsn_pri_map_t);
  12905             TSN_ALLOC(unit, bk_info->tsn_stu_bk_info.pri_map_port,
  12906                       bcm_tsn_pri_map_t, alloc_size,
  12907                       "STU Priority Map Port Array", 0, rv);
  12908         }
  12909         if (BCM_FAILURE(rv)) {
  12910             LOG_VERBOSE(BSL_LS_BCM_TSN,
  12911                         (BSL_META_U(unit,
  12912                                     "bcmi_esw_tsn_init: failed to "
  12913                                     "allocate memory\n")));
  12914             return rv;
  12915         }
  12916         /* Initialize pri_map_port array */
  12917         for (i = 0; i < ctrl_info->logical_port_num; i++) {
  12918             bk_info->tsn_stu_bk_info.pri_map_port[i] = BCM_TSN_PRI_MAP_INVALID;
  12919         }
  12920         /* Create STU mutex */
  12921         bk_info->tsn_stu_bk_info.mutex = sal_mutex_create("stu_mutex");
  12922         if (bk_info->tsn_stu_bk_info.mutex == NULL) {
  12923             return BCM_E_MEMORY;
  12924         }
  12925     }
  12926     return BCM_E_NONE;
  12927 }
  12928 
  12929 
  12930 /* Start of tsn event functions */
  12931 /*
  12932  * Event instance information
  12933  * NOTE: index order should be the same with bcmi_tsn_evt_inst_type_t
  12934  */
  12935 STATIC const tsn_evt_inst_alloc_t tsn_evt_inst_info[bcmiTsnEvtCount] = {
  12936     {bcmiTsnEvtCESys,
  12937      bcmTsnEventTypeCounterExceeded, BCM_TSN_EVENT_SOURCE_TYPE_SYSTEM,
  12938      TSN_EVENT_SYSTEM_CB_MAX},
  12939     {bcmiTsnEvtCEFlow,
  12940      bcmTsnEventTypeCounterExceeded, BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW,
  12941      TSN_EVENT_FLOW_CB_MAX},
  12942     {bcmiTsnEvtCEPort,
  12943      bcmTsnEventTypeCounterExceeded, BCM_TSN_EVENT_SOURCE_TYPE_PORT,
  12944      TSN_EVENT_PORT_CB_MAX},
  12945     {bcmiTsnEvtWLASys,
  12946      bcmTsnEventTypeSrWrongLanA, BCM_TSN_EVENT_SOURCE_TYPE_SYSTEM,
  12947      TSN_EVENT_SYSTEM_CB_MAX},
  12948     {bcmiTsnEvtWLAFlow,
  12949      bcmTsnEventTypeSrWrongLanA, BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW,
  12950      TSN_EVENT_FLOW_CB_MAX},
  12951     {bcmiTsnEvtWLBSys,
  12952      bcmTsnEventTypeSrWrongLanB, BCM_TSN_EVENT_SOURCE_TYPE_SYSTEM,
  12953      TSN_EVENT_SYSTEM_CB_MAX},
  12954     {bcmiTsnEvtWLBFlow,
  12955      bcmTsnEventTypeSrWrongLanB, BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW,
  12956      TSN_EVENT_FLOW_CB_MAX},
  12957     {bcmiTsnEvtSNSys,
  12958      bcmTsnEventTypeSrSeqNumWindowAgeOut, BCM_TSN_EVENT_SOURCE_TYPE_SYSTEM,
  12959      TSN_EVENT_SYSTEM_CB_MAX},
  12960     {bcmiTsnEvtSNFlow,
  12961      bcmTsnEventTypeSrSeqNumWindowAgeOut, BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW,
  12962      TSN_EVENT_FLOW_CB_MAX}
  12963 };
  12964 
  12965 #if defined(BCM_TSN_SR_SUPPORT)
  12966 /*
  12967  * Invoked from bcmi_esw_tsn_sr_rx_flowset_create to maintain the active rx flow
  12968  * database in device.
  12969  */
  12970 STATIC int
  12971 bcmi_esw_tsn_event_rx_flow_add(int unit, int fidx)
  12972 {
  12973     uint32 hw_id;
  12974 
  12975     SR_FLOW_MGMT_DEVINFO(unit)->get_hw_flow_id(
  12976         unit, 0, fidx, &hw_id);
  12977     if (TSN_EVENT_DEVINFO(unit)->update_rx_flow) {
  12978         BCM_IF_ERROR_RETURN(
  12979             TSN_EVENT_DEVINFO(unit)->update_rx_flow(unit, -1, hw_id, 1));
  12980     }
  12981     return BCM_E_UNAVAIL;
  12982 }
  12983 
  12984 STATIC int
  12985 bcmi_esw_tsn_event_rx_flow_delete(int unit, int fidx)
  12986 {
  12987     uint32 hw_id;
  12988 
  12989     SR_FLOW_MGMT_DEVINFO(unit)->get_hw_flow_id(
  12990         unit, 0, fidx, &hw_id);
  12991     if (TSN_EVENT_DEVINFO(unit)->update_rx_flow) {
  12992         BCM_IF_ERROR_RETURN(
  12993             TSN_EVENT_DEVINFO(unit)->update_rx_flow(unit, -1, hw_id, 0));
  12994     }
  12995     return BCM_E_UNAVAIL;
  12996 }
  12997 
  12998 /*
  12999  * Handle flow based event
  13000  * bcmTsnEventTypeSrWrongLanA, bcmTsnEventTypeSrWrongLanB,
  13001  * bcmTsnEventTypeSrSeqNumWindowAgeOut
  13002  */
  13003 STATIC int
  13004 bcmi_esw_tsn_flow_event_notify(
  13005     int unit,
  13006     bcm_tsn_event_type_t event,
  13007     int multiple,
  13008     int hw_flow_id)
  13009 {
  13010     bcmi_esw_tsn_bk_info_t      *tsn_bk;
  13011     tsn_event_bk_t              *bkinfo;
  13012     int                         rv = BCM_E_NONE, i;
  13013     tsn_evt_stat_t              *evt_stat;
  13014     tsn_evt_regist_t            *er;
  13015     tsn_evt_inst_t              *einst;
  13016     bcm_tsn_event_source_t      src;
  13017     bcmi_tsn_evt_inst_type_t    evt_inst_type;
  13018     bcm_tsn_sr_flow_t           flow_id;
  13019 
  13020     /* parameter check */
  13021     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  13022     bkinfo = &tsn_bk->tsn_events;
  13023 
  13024     TSN_EVENT_LOCK(unit);
  13025     evt_stat = &bkinfo->evt_stat[event];
  13026     SHR_BITCLR_RANGE(evt_stat->fbmp, 0, _SHR_BITDCLSIZE(bkinfo->max_flows));
  13027     SHR_BITCLR_RANGE(evt_stat->ffbmp, 0, _SHR_BITDCLSIZE(bkinfo->max_flows));
  13028 
  13029     if ((event == bcmTsnEventTypeSrWrongLanA) ||
  13030         (event == bcmTsnEventTypeSrWrongLanB) ||
  13031         (event == bcmTsnEventTypeSrSeqNumWindowAgeOut)) {
  13032         if (TSN_EVENT_DEVINFO(unit)->event_flow_stat_get) {
  13033             rv = TSN_EVENT_DEVINFO(unit)->
  13034                  event_flow_stat_get(unit, event, evt_stat->fbmp,
  13035                                      evt_stat->ffbmp,
  13036                                      bkinfo->max_flows);
  13037             if (BCM_FAILURE(rv)) {
  13038                 TSN_EVENT_UNLOCK(unit);
  13039                 return rv;
  13040             }
  13041         }
  13042         if (!multiple) {
  13043             SHR_BITCLR_RANGE(evt_stat->fbmp, 0,
  13044                              _SHR_BITDCLSIZE(bkinfo->max_flows));
  13045             SHR_BITSET(evt_stat->fbmp, hw_flow_id);
  13046         }
  13047 
  13048         /* Iter the flow id which indicate the wrong lan */
  13049         SHR_BIT_ITER(evt_stat->fbmp, bkinfo->max_flows, i) {
  13050             BCM_IF_ERROR_RETURN(
  13051                 bcmi_esw_tsn_sr_sw_flow_id_get(unit, i, &flow_id));
  13052             if (SHR_BITGET(evt_stat->ffbmp, i)) {
  13053                 /* Wrong lan event, registered as per flow */
  13054                 if (event == bcmTsnEventTypeSrWrongLanA) {
  13055                     evt_inst_type = bcmiTsnEvtWLAFlow;
  13056                 } else if (event == bcmTsnEventTypeSrWrongLanB) {
  13057                     evt_inst_type = bcmiTsnEvtWLBFlow;
  13058                 } else {
  13059                     evt_inst_type = bcmiTsnEvtSNFlow;
  13060                 }
  13061 
  13062                 er = &bkinfo->eregist[evt_inst_type];
  13063                 TSN_REVT_LOCK(er);
  13064                 for (einst = er->evt_inst; einst != NULL; einst = einst->next) {
  13065                     /* matched the flow id with registerd source */
  13066                     if (einst->sr_flow == flow_id) {
  13067                         if (NULL != einst->cb) {
  13068                             /* invoke registerd callback */
  13069                             bcm_tsn_event_source_t_init(&src);
  13070                             src.source_type = BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW;
  13071                             src.sr_flow = einst->sr_flow;
  13072                             einst->cb(unit, event, &src, einst->user_data);
  13073                         }
  13074                     }
  13075                 }
  13076                 TSN_REVT_UNLOCK(er);
  13077             }
  13078 
  13079             /* Wrong lan event, registered as per system */
  13080             if (event == bcmTsnEventTypeSrWrongLanA) {
  13081                 evt_inst_type = bcmiTsnEvtWLASys;
  13082             } else if (event == bcmTsnEventTypeSrWrongLanB) {
  13083                 evt_inst_type = bcmiTsnEvtWLBSys;
  13084             } else {
  13085                 evt_inst_type = bcmiTsnEvtSNSys;
  13086             }
  13087             er = &bkinfo->eregist[evt_inst_type];
  13088             TSN_REVT_LOCK(er);
  13089             for (einst = er->evt_inst; einst != NULL; einst = einst->next) {
  13090                 /* For src == system, callback with flow_id information */
  13091                 if (NULL != einst->cb) {
  13092                     bcm_tsn_event_source_t_init(&src);
  13093                     src.source_type = BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW;
  13094                     src.sr_flow = flow_id;
  13095                     einst->cb(unit, event, &src, einst->user_data);
  13096                 }
  13097             }
  13098             TSN_REVT_UNLOCK(er);
  13099         }
  13100         /* Clear the event stat information */
  13101         if (TSN_EVENT_DEVINFO(unit)->event_flow_stat_clear) {
  13102                 rv = TSN_EVENT_DEVINFO(unit)->
  13103                      event_flow_stat_clear(unit, event, evt_stat->fbmp,
  13104                                            bkinfo->max_flows);
  13105         }
  13106     }
  13107     TSN_EVENT_UNLOCK(unit);
  13108     return rv;
  13109 }
  13110 #endif /* BCM_TSN_SR_SUPPORT */
  13111 
  13112 /*
  13113  * Handle counter exceed event
  13114  */
  13115 STATIC int
  13116 bcmi_esw_tsn_cnt_exceed_notify(
  13117     int unit,
  13118     bcm_tsn_stat_t stat,
  13119     bcm_tsn_stat_threshold_source_t th_src,
  13120     int multiple,
  13121     int index)
  13122 {
  13123     bcm_tsn_stat_threshold_config_t config;
  13124     bcm_pbmp_t                      pbmp;
  13125     bcm_port_t                      p;
  13126     bcm_gport_t                     gport;
  13127     uint64                          hw_value, sw_value, th_value;
  13128     bcmi_esw_tsn_bk_info_t          *tsn_bk;
  13129     tsn_event_bk_t                  *bkinfo;
  13130     tsn_evt_regist_t                *er;
  13131     tsn_evt_inst_t                  *einst;
  13132     bcm_tsn_event_source_t          src;
  13133 #if defined(BCM_TSN_SR_SUPPORT)
  13134     tsn_evt_stat_t                  *evt_stat;
  13135     int                             i;
  13136     bcm_tsn_sr_flow_t               flow_id;
  13137 #endif
  13138 
  13139 
  13140     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  13141     bkinfo = &tsn_bk->tsn_events;
  13142 
  13143     /* Get the threshold value */
  13144     bcm_tsn_stat_threshold_config_t_init(&config);
  13145     BCM_IF_ERROR_RETURN(
  13146         bcmi_esw_tsn_stat_threshold_get(unit, th_src, stat, &config));
  13147     COMPILER_64_SET(th_value, 0, config.threshold);
  13148 
  13149     if (th_src == bcmTsnStatThresholdSourcePort) {
  13150         BCM_PBMP_CLEAR(pbmp);
  13151         /* sync the port stat */
  13152         BCM_IF_ERROR_RETURN(
  13153             bcmi_esw_tsn_stat_portcnt_stat_sync(unit, stat));
  13154 
  13155         if (multiple) {
  13156             BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit));
  13157         } else {
  13158             BCM_PBMP_PORT_SET(pbmp, index);
  13159         }
  13160         /* Iterate valid port to compare the threshold value */
  13161         BCM_PBMP_ITER(pbmp, p) {
  13162             BCM_IF_ERROR_RETURN(
  13163                 bcmi_esw_tsn_stat_portcnt_hw_sw_get(unit, stat, p,
  13164                                                     &hw_value, &sw_value));
  13165             BCM_IF_ERROR_RETURN(bcm_esw_port_gport_get(unit, p, &gport));
  13166             if (COMPILER_64_GT(hw_value, th_value)) {
  13167                 /* event registered with src = port */
  13168                 er = &bkinfo->eregist[bcmiTsnEvtCEPort];
  13169                 TSN_REVT_LOCK(er);
  13170                 for (einst = er->evt_inst; einst != NULL; einst = einst->next) {
  13171                     if (einst->port == p) {
  13172                         if (NULL != einst->cb) {
  13173                             bcm_tsn_event_source_t_init(&src);
  13174                             src.source_type = BCM_TSN_EVENT_SOURCE_TYPE_PORT;
  13175                             src.port = gport;
  13176                             einst->cb(unit, bcmTsnEventTypeCounterExceeded,
  13177                                       &src, einst->user_data);
  13178                         }
  13179                     }
  13180                 }
  13181                 TSN_REVT_UNLOCK(er);
  13182                 /* event registered with src = system */
  13183                 er = &bkinfo->eregist[bcmiTsnEvtCESys];
  13184                 TSN_REVT_LOCK(er);
  13185                 for (einst = er->evt_inst; einst != NULL; einst = einst->next) {
  13186                     if (NULL != einst->cb) {
  13187                         bcm_tsn_event_source_t_init(&src);
  13188                         src.source_type = BCM_TSN_EVENT_SOURCE_TYPE_PORT;
  13189                         src.port = gport;
  13190                         einst->cb(unit, bcmTsnEventTypeCounterExceeded,
  13191                                   &src, einst->user_data);
  13192                     }
  13193                 }
  13194                 TSN_REVT_UNLOCK(er);
  13195 
  13196                 /* Clear the HW value to avoid continuous threshold event */
  13197                 COMPILER_64_ZERO(hw_value);
  13198                 BCM_IF_ERROR_RETURN(
  13199                     bcmi_esw_tsn_stat_portcnt_hw_set(unit, stat, p, hw_value));
  13200             } /* end of COMPILER_64_GT */
  13201         } /* end of valid port iter */
  13202     }
  13203     if (th_src == bcmTsnStatThresholdSourceSRFlow) {
  13204 #if defined(BCM_TSN_SR_SUPPORT)
  13205         if (soc_feature(unit, soc_feature_tsn_sr)) {
  13206             /* sync the flow stat */
  13207             BCM_IF_ERROR_RETURN(
  13208                 bcmi_esw_tsn_stat_flowcnt_stat_sync(unit, stat));
  13209 
  13210             evt_stat = &bkinfo->evt_stat[bcmTsnEventTypeCounterExceeded];
  13211             SHR_BITCLR_RANGE(evt_stat->fbmp, 0,
  13212                              _SHR_BITDCLSIZE(bkinfo->max_flows));
  13213             if (multiple) {
  13214                 BCM_IF_ERROR_RETURN(
  13215                     bcmi_esw_tsn_stat_flowcnt_fbmp_get(
  13216                         unit, stat, evt_stat->fbmp,
  13217                         _SHR_BITDCLSIZE(bkinfo->max_flows)));
  13218             } else {
  13219                 SHR_BITSET(evt_stat->fbmp, index);
  13220             }
  13221             /* Iter the flows which support the stat */
  13222             SHR_BIT_ITER(evt_stat->fbmp, bkinfo->max_flows, i) {
  13223                 BCM_IF_ERROR_RETURN(
  13224                     bcmi_esw_tsn_sr_sw_flow_id_get(unit, i, &flow_id));
  13225                 BCM_IF_ERROR_RETURN(
  13226                     bcmi_esw_tsn_stat_flowcnt_hw_sw_get(unit, stat, flow_id,
  13227                                                         &hw_value, &sw_value));
  13228                 if (COMPILER_64_GT(hw_value, th_value)) {
  13229                     er = &bkinfo->eregist[bcmiTsnEvtCEFlow];
  13230                     TSN_REVT_LOCK(er);
  13231                     for (einst = er->evt_inst; einst != NULL;
  13232                          einst = einst->next) {
  13233                         /* matched the flow id with registerd source */
  13234                         if (einst->sr_flow == flow_id) {
  13235                             if (NULL != einst->cb) {
  13236                                 /* invoke registerd callback */
  13237                                 bcm_tsn_event_source_t_init(&src);
  13238                                 src.source_type =
  13239                                     BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW;
  13240                                 src.sr_flow = einst->sr_flow;
  13241                                 einst->cb(unit, bcmTsnEventTypeCounterExceeded,
  13242                                           &src, einst->user_data);
  13243                             }
  13244                         }
  13245                     }
  13246                     TSN_REVT_UNLOCK(er);
  13247                     er = &bkinfo->eregist[bcmiTsnEvtCESys];
  13248                     TSN_REVT_LOCK(er);
  13249                     for (einst = er->evt_inst; einst != NULL;
  13250                          einst = einst->next) {
  13251                         /*
  13252                          * For src == system,
  13253                          * callback with flow_id information
  13254                          */
  13255                         if (NULL != einst->cb) {
  13256                             bcm_tsn_event_source_t_init(&src);
  13257                             src.source_type = BCM_TSN_EVENT_SOURCE_TYPE_SYSTEM;
  13258                             src.sr_flow = flow_id;
  13259                             einst->cb(unit, bcmTsnEventTypeCounterExceeded,
  13260                                       &src, einst->user_data);
  13261                         }
  13262                     }
  13263                     TSN_REVT_UNLOCK(er);
  13264                     /* Clear the HW value to avoid continuous threshold event */
  13265                     COMPILER_64_ZERO(hw_value);
  13266                     BCM_IF_ERROR_RETURN(
  13267                         bcmi_esw_tsn_stat_flowcnt_hw_set(unit, stat, flow_id,
  13268                                                          hw_value));
  13269                 }
  13270             }
  13271         } else
  13272 #endif /* BCM_TSN_SR_SUPPORT */
  13273         {
  13274             /* Do nothing */
  13275             return BCM_E_NONE;
  13276         }
  13277     }
  13278     return BCM_E_NONE;
  13279 }
  13280 
  13281 void bcmi_tsn_event_poll(void *unit_vp)
  13282 {
  13283     int                     unit = PTR_TO_INT(unit_vp);
  13284     bcmi_esw_tsn_bk_info_t  *tsn_bk;
  13285     tsn_event_bk_t          *bkinfo;
  13286     sal_usecs_t             interval;
  13287     int                     rv;
  13288 
  13289     /* parameter check */
  13290     rv = tsn_bk_info_instance_get(unit, &tsn_bk);
  13291     if (BCM_FAILURE(rv)) {
  13292         LOG_ERROR(BSL_LS_BCM_TSN,
  13293                   (BSL_META_U(unit,
  13294                               "TSN EVT: failed to get the tsn bkinfo\n")));
  13295         return;
  13296     }
  13297 
  13298     bkinfo = &tsn_bk->tsn_events;
  13299 
  13300     while (bkinfo->poll_enable) {
  13301         if (bkinfo->poll_interval != 0) {
  13302             interval = (bkinfo->poll_interval) * MILLISECOND_USEC;
  13303         } else {
  13304             interval = TSN_EVENT_POLL_INTERVAL_DEFAULT;
  13305         }
  13306 
  13307         (void)sal_sem_take(bkinfo->poll_notify, interval);
  13308 
  13309         if (bkinfo->poll_enable == 0) {
  13310             break;
  13311         }
  13312 
  13313         /* invoke device poll function */
  13314         if (TSN_EVENT_DEVINFO(unit)->poll) {
  13315             (void)TSN_EVENT_DEVINFO(unit)->poll(unit);
  13316         }
  13317 
  13318     }
  13319     bkinfo->poll_tid = SAL_THREAD_ERROR;
  13320     bkinfo->poll_interval = 0;
  13321     bkinfo->poll_enable = 0;
  13322 
  13323     sal_thread_exit(0);
  13324 }
  13325 
  13326 STATIC int
  13327 bcmi_esw_tsn_evt_poll_config(int unit, int enable)
  13328 {
  13329     bcmi_esw_tsn_bk_info_t  *tsn_bk;
  13330     tsn_event_bk_t          *bkinfo;
  13331     soc_timeout_t           to;
  13332     int                     rv = BCM_E_NONE;
  13333 
  13334     /* parameter check */
  13335     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  13336     bkinfo = &tsn_bk->tsn_events;
  13337 
  13338     if (enable) {
  13339         if (bkinfo->poll_tid && bkinfo->poll_tid != SAL_THREAD_ERROR) {
  13340             /* Thead existed and running. invoke poll function */
  13341             sal_sem_give(bkinfo->poll_notify);
  13342             return BCM_E_NONE;
  13343         }
  13344         TSN_EVENT_LOCK(unit);
  13345         if ((bkinfo->poll_tid == NULL) ||
  13346             (bkinfo->poll_tid == SAL_THREAD_ERROR)) {
  13347             bkinfo->poll_tid = sal_thread_create("bcmTSN", SAL_THREAD_STKSZ, 50,
  13348                                                  bcmi_tsn_event_poll,
  13349                                                  INT_TO_PTR(unit));
  13350             if (bkinfo->poll_tid == SAL_THREAD_ERROR) {
  13351                 LOG_ERROR(BSL_LS_BCM_TSN,
  13352                           (BSL_META_U(unit,
  13353                                       "TSN EVT: failed to create thread\n")));
  13354                 TSN_EVENT_UNLOCK(unit);
  13355                 return BCM_E_MEMORY;
  13356             }
  13357         }
  13358         TSN_EVENT_UNLOCK(unit);
  13359     } else {
  13360         TSN_EVENT_LOCK(unit);
  13361         bkinfo->poll_interval = 0;
  13362         bkinfo->poll_enable = 0;
  13363         TSN_EVENT_UNLOCK(unit);
  13364         if (bkinfo->poll_tid && bkinfo->poll_tid != SAL_THREAD_ERROR) {
  13365             sal_sem_give(bkinfo->poll_notify);
  13366             if (SAL_BOOT_SIMULATION) {
  13367                 soc_timeout_init(&to, 300 * 1000000, 0);
  13368             } else {
  13369                 soc_timeout_init(&to, 60 * 1000000, 0);
  13370             }
  13371 
  13372             while (bkinfo->poll_tid != SAL_THREAD_ERROR) {
  13373                 if (soc_timeout_check(&to)) {
  13374                     LOG_ERROR(BSL_LS_BCM_TSN,
  13375                               (BSL_META_U(unit,
  13376                                           "TSN thread will not exit\n")));
  13377                     rv = BCM_E_INTERNAL;
  13378                     break;
  13379                 }
  13380             }
  13381         }
  13382     }
  13383     return rv;
  13384 }
  13385 
  13386 /* Internal function invoke when  tsnControl change */
  13387 STATIC void
  13388 bcmi_esw_tsn_evt_ageout_config(int unit, bcm_tsn_control_t type, uint32 arg)
  13389 {
  13390     bcmi_esw_tsn_bk_info_t  *tsn_bk;
  13391     tsn_event_bk_t          *bkinfo;
  13392     uint32                  enable, interval = 0, rmode;
  13393     uint8                   change = 0, rmode_change = 0;
  13394 
  13395     /* parameter check */
  13396     if (BCM_FAILURE(tsn_bk_info_instance_get(unit, &tsn_bk))) {
  13397         return;
  13398     }
  13399     bkinfo = &tsn_bk->tsn_events;
  13400 
  13401     TSN_EVENT_LOCK(unit);
  13402 
  13403     /*
  13404      * Interested in bcmTsnControlSrAgeTickInterval,
  13405      * bcmTsnControlSrAgeOutEnable
  13406      * bcmTsnControlSrSeqNumWindowResetMode
  13407      */
  13408     enable = bkinfo->pre_enable;
  13409     if (type == bcmTsnControlSrAgeTickInterval) {
  13410         interval = arg;
  13411         if (bkinfo->pre_interval != interval) {
  13412             change = 1;
  13413         }
  13414         bkinfo->pre_interval = interval;
  13415     } else if (type == bcmTsnControlSrAgeOutEnable) {
  13416         enable = arg;
  13417         if (bkinfo->pre_enable != enable) {
  13418             change = 1;
  13419         }
  13420         bkinfo->pre_enable = enable;
  13421     } else if (type == bcmTsnControlSrSeqNumWindowResetMode) {
  13422         rmode = arg;
  13423         if ((bkinfo->pre_rmode != rmode) &&
  13424             (rmode == BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_SW ||
  13425              bkinfo->pre_rmode ==
  13426              BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_SW)) {
  13427             rmode_change = 1;
  13428         }
  13429         bkinfo->pre_rmode = rmode;
  13430     } else {
  13431         TSN_EVENT_UNLOCK(unit);
  13432         return;
  13433     }
  13434 
  13435     /* update the poll thread parameter */
  13436     bkinfo->poll_interval = bkinfo->pre_interval;
  13437 
  13438     bkinfo->poll_enable = enable;
  13439 
  13440     TSN_EVENT_UNLOCK(unit);
  13441 
  13442     if ((change) || (rmode_change)) {
  13443         bcmi_esw_tsn_evt_poll_config(unit, enable);
  13444     }
  13445     return;
  13446 }
  13447 
  13448 /* Free event instance resource */
  13449 STATIC int
  13450 bcmi_esw_tsn_evt_inst_free(
  13451     int unit,
  13452     bcmi_tsn_evt_inst_type_t inst_type,
  13453     tsn_evt_inst_t  *entry)
  13454 {
  13455     bcmi_esw_tsn_bk_info_t  *tsn_bk;
  13456     tsn_event_bk_t          *bkinfo;
  13457 
  13458     /* parameter check */
  13459     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  13460     if (inst_type < 0 || inst_type >= bcmiTsnEvtCount || entry == NULL) {
  13461         return BCM_E_PARAM;
  13462     }
  13463     bkinfo = &tsn_bk->tsn_events;
  13464     TSN_EVENT_LOCK(unit);
  13465     /* Put it back to the head */
  13466     entry->next = bkinfo->einst_avail[inst_type];
  13467     bkinfo->einst_avail[inst_type] = entry;
  13468     TSN_EVENT_UNLOCK(unit);
  13469 
  13470     return BCM_E_NONE;
  13471 }
  13472 
  13473 /* Allocate event instance */
  13474 STATIC int
  13475 bcmi_esw_tsn_evt_inst_allocate(
  13476     int unit,
  13477     bcmi_tsn_evt_inst_type_t inst_type,
  13478     tsn_evt_inst_t  **entry)
  13479 {
  13480     bcmi_esw_tsn_bk_info_t  *tsn_bk;
  13481     tsn_event_bk_t          *bkinfo;
  13482     tsn_evt_inst_t          *einst;
  13483 
  13484     /* parameter check */
  13485     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  13486     if (inst_type < 0 || inst_type >= bcmiTsnEvtCount || entry == NULL) {
  13487         return BCM_E_PARAM;
  13488     }
  13489     bkinfo = &tsn_bk->tsn_events;
  13490 
  13491     TSN_EVENT_LOCK(unit);
  13492     /* Get one entry from the head */
  13493     einst = bkinfo->einst_avail[inst_type];
  13494     if (einst == NULL) {
  13495         TSN_EVENT_UNLOCK(unit);
  13496         return BCM_E_RESOURCE;
  13497     }
  13498     bkinfo->einst_avail[inst_type] = einst->next;
  13499     einst->next = NULL;
  13500     *entry = einst;
  13501     TSN_EVENT_UNLOCK(unit);
  13502 
  13503     return BCM_E_NONE;
  13504 }
  13505 
  13506 STATIC int
  13507 bcmi_esw_tsn_event_mgmt_detach(int unit)
  13508 {
  13509     bcmi_esw_tsn_bk_info_t  *tsn_bk;
  13510     tsn_event_bk_t          *bkinfo;
  13511     tsn_evt_regist_t        *eregist;
  13512     int                     i;
  13513 
  13514     /* parameter check */
  13515     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  13516 
  13517     bkinfo = &tsn_bk->tsn_events;
  13518 
  13519     if (bkinfo->poll_notify) {
  13520         if (bkinfo->poll_enable) {
  13521             BCM_IF_ERROR_RETURN(bcmi_esw_tsn_evt_poll_config(unit, 0));
  13522         }
  13523         sal_sem_destroy(bkinfo->poll_notify);
  13524         bkinfo->poll_notify = NULL;
  13525     }
  13526     /* de-allocate event instance pool */
  13527     if (NULL != bkinfo->einst_allocated) {
  13528         sal_free(bkinfo->einst_allocated);
  13529         bkinfo->einst_allocated = NULL;
  13530     }
  13531     /* de-allocate event mgmt mutex */
  13532     if (NULL != bkinfo->evt_mutex) {
  13533         sal_mutex_destroy(bkinfo->evt_mutex);
  13534         bkinfo->evt_mutex = NULL;
  13535     }
  13536 
  13537     for (i = 0; i < bcmiTsnEvtCount; i++) {
  13538         /* clear linked list */
  13539         bkinfo->einst_avail[i] = NULL;
  13540         /* destroy mutex */
  13541         eregist = &bkinfo->eregist[i];
  13542         if (NULL != eregist->mutex) {
  13543             sal_mutex_destroy(eregist->mutex);
  13544             eregist->mutex = NULL;
  13545         }
  13546     }
  13547     for (i = 0; i < bcmTsnEventTypeCount; i++) {
  13548         /* de-allocate register event instance */
  13549         if (NULL != bkinfo->evt_stat[i].port_ref) {
  13550             sal_free(bkinfo->evt_stat[i].port_ref);
  13551             bkinfo->evt_stat[i].port_ref = NULL;
  13552         }
  13553         if (NULL != bkinfo->evt_stat[i].flow_ref) {
  13554             sal_free(bkinfo->evt_stat[i].flow_ref);
  13555             bkinfo->evt_stat[i].flow_ref = NULL;
  13556         }
  13557         if (NULL != bkinfo->evt_stat[i].pbmp) {
  13558             sal_free(bkinfo->evt_stat[i].pbmp);
  13559             bkinfo->evt_stat[i].pbmp = NULL;
  13560         }
  13561         if (NULL != bkinfo->evt_stat[i].fbmp) {
  13562             sal_free(bkinfo->evt_stat[i].fbmp);
  13563             bkinfo->evt_stat[i].fbmp = NULL;
  13564         }
  13565         if (NULL != bkinfo->evt_stat[i].ffbmp) {
  13566             sal_free(bkinfo->evt_stat[i].ffbmp);
  13567             bkinfo->evt_stat[i].ffbmp = NULL;
  13568         }
  13569     }
  13570     return BCM_E_NONE;
  13571 }
  13572 
  13573 /* event management initialization */
  13574 STATIC int
  13575 bcmi_esw_tsn_event_mgmt_init(int unit)
  13576 {
  13577     bcmi_esw_tsn_bk_info_t      *tsn_bk;
  13578     tsn_event_bk_t              *bkinfo;
  13579     tsn_evt_inst_t              *einst;
  13580     int                         i, j, total_insts, maxflows = 0, maxports;
  13581     tsn_evt_regist_t            *eregist;
  13582     tsn_evt_stat_t              *evt_stat;
  13583     bcm_pbmp_t                  all_pbmp;
  13584 #if defined(BCM_TSN_SR_SUPPORT)
  13585     tsn_sr_flows_bookkeeping_t  *sr_flow_bkinfo;
  13586 #endif
  13587 
  13588     /* parameter check */
  13589     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  13590 
  13591     bkinfo = &tsn_bk->tsn_events;
  13592     if (TSN_EVENT_DEVINFO(unit) == NULL) {
  13593         return BCM_E_UNAVAIL;
  13594     }
  13595 
  13596     /* Allocate event cb link list */
  13597     total_insts = 0;
  13598     for (i = 0; i < bcmiTsnEvtCount; i++) {
  13599         total_insts += tsn_evt_inst_info[i].inst_limits;
  13600     }
  13601 
  13602     bkinfo->einst_allocated = (tsn_evt_inst_t *)sal_alloc(
  13603         sizeof(tsn_evt_inst_t) * total_insts,
  13604         "tsn event instances");
  13605     if (NULL == bkinfo->einst_allocated) {
  13606         LOG_ERROR(BSL_LS_BCM_TSN,
  13607                   (BSL_META_U(unit,
  13608                               "TSN EVNT: failed to alloc event instance\n")));
  13609         (void)bcmi_esw_tsn_event_mgmt_detach(unit);
  13610         return BCM_E_MEMORY;
  13611     }
  13612     sal_memset(bkinfo->einst_allocated, 0,
  13613                sizeof(tsn_evt_inst_t) * total_insts);
  13614 
  13615      /* Retrieve number of flows */
  13616 #if defined(BCM_TSN_SR_SUPPORT)
  13617     if (soc_feature(unit, soc_feature_tsn_sr)) {
  13618          sr_flow_bkinfo = &tsn_bk->sr_flows;
  13619         if (sr_flow_bkinfo != NULL &&
  13620             sr_flow_bkinfo->max_flows[SR_FLOW_DIR_TX] != 0 &&
  13621             sr_flow_bkinfo->max_flows[SR_FLOW_DIR_RX] != 0) {
  13622             maxflows = sr_flow_bkinfo->max_flows[SR_FLOW_DIR_TX] +
  13623                        sr_flow_bkinfo->max_flows[SR_FLOW_DIR_RX];
  13624             bkinfo->max_rx_flows = sr_flow_bkinfo->max_flows[SR_FLOW_DIR_RX];
  13625         } else {
  13626             LOG_ERROR(BSL_LS_BCM_TSN,
  13627                       (BSL_META_U(unit,
  13628                           "TSN EVNT: failed to get sr flow information.\n")));
  13629             return BCM_E_INTERNAL;
  13630         }
  13631     }
  13632 #endif /* BCM_TSN_SR_SUPPORT */
  13633     bkinfo->max_flows = maxflows;
  13634 
  13635     einst = bkinfo->einst_allocated;
  13636     for (i = 0; i < bcmiTsnEvtCount; i++) {
  13637         for (j = 0; j < tsn_evt_inst_info[i].inst_limits; j++, einst++) {
  13638             /* Initialize available linked list */
  13639             einst->next = bkinfo->einst_avail[i];
  13640             bkinfo->einst_avail[i] = einst;
  13641         }
  13642 
  13643         /* Initialize registered events instance */
  13644         sal_memset(&bkinfo->eregist[i], 0, sizeof(tsn_evt_regist_t));
  13645         eregist = &bkinfo->eregist[i];
  13646         eregist->source_type = tsn_evt_inst_info[i].source_type;
  13647         eregist->inst_type = tsn_evt_inst_info[i].inst_type;
  13648         eregist->evt_type = tsn_evt_inst_info[i].evt_type;
  13649 
  13650         /* Create mutex */
  13651         eregist->mutex = sal_mutex_create("tsn evt register mutex");
  13652         if (NULL == eregist->mutex) {
  13653             LOG_ERROR(BSL_LS_BCM_TSN,
  13654                       (BSL_META_U(unit,
  13655                                   "TSN EVT: "
  13656                                   "failed to create register mutex\n")));
  13657             (void)bcmi_esw_tsn_event_mgmt_detach(unit);
  13658             return BCM_E_MEMORY;
  13659         }
  13660     }
  13661     /* Get the max port in the system */
  13662     maxports = 0;
  13663     BCM_PBMP_CLEAR(all_pbmp);
  13664     /* Get the all valid port map */
  13665     BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit));
  13666     /* Iterate the bitmap to get the maximum port number */
  13667     BCM_PBMP_ITER(all_pbmp, i) {
  13668         maxports = i;
  13669     }
  13670     /* Total port counts should be (maximum port number + 1) */
  13671     bkinfo->max_ports = maxports + 1;
  13672     for (i = 0; i < bcmTsnEventTypeCount; i++) {
  13673         /* Allocate and initialize the event stat  */
  13674         evt_stat = &bkinfo->evt_stat[i];
  13675         evt_stat->event_ref = 0;
  13676         evt_stat->port_ref = sal_alloc(bkinfo->max_ports * sizeof(int),
  13677                                        "alloc evt port basis stat");
  13678         if (NULL == evt_stat->port_ref) {
  13679             LOG_ERROR(BSL_LS_BCM_TSN,
  13680                       (BSL_META_U(unit,
  13681                                   "TSN EVT: failed to create evt stat \n")));
  13682             (void)bcmi_esw_tsn_event_mgmt_detach(unit);
  13683             return BCM_E_MEMORY;
  13684         }
  13685         sal_memset(evt_stat->port_ref, 0, bkinfo->max_ports * sizeof(int));
  13686 
  13687         evt_stat->flow_ref = sal_alloc(maxflows * sizeof(int),
  13688                                        "alloc evt flow basis stat");
  13689         if (NULL == evt_stat->flow_ref) {
  13690             LOG_ERROR(BSL_LS_BCM_TSN,
  13691                       (BSL_META_U(unit,
  13692                                   "TSN EVT: failed to create evt stat \n")));
  13693             (void)bcmi_esw_tsn_event_mgmt_detach(unit);
  13694             return BCM_E_MEMORY;
  13695         }
  13696         sal_memset(evt_stat->flow_ref, 0, bkinfo->max_ports * sizeof(int));
  13697 
  13698         evt_stat->pbmp = sal_alloc(SHR_BITALLOCSIZE(bkinfo->max_ports),
  13699                                    "alloc evt stat pbmp");
  13700         if (NULL == evt_stat->pbmp) {
  13701             LOG_ERROR(BSL_LS_BCM_TSN,
  13702                       (BSL_META_U(unit,
  13703                                   "TSN EVT: failed to alloc evt stat pbmp\n")));
  13704             (void)bcmi_esw_tsn_event_mgmt_detach(unit);
  13705             return BCM_E_MEMORY;
  13706         }
  13707         sal_memset(evt_stat->pbmp, 0, SHR_BITALLOCSIZE(bkinfo->max_ports));
  13708         evt_stat->fbmp = sal_alloc(SHR_BITALLOCSIZE(maxflows),
  13709                                     "alloc evt stat fbmp");
  13710         if (NULL == evt_stat->fbmp) {
  13711             LOG_ERROR(BSL_LS_BCM_TSN,
  13712                       (BSL_META_U(unit,
  13713                                   "TSN EVT: failed to alloc evt stat fbmp\n")));
  13714             (void)bcmi_esw_tsn_event_mgmt_detach(unit);
  13715             return BCM_E_MEMORY;
  13716         }
  13717         sal_memset(evt_stat->fbmp, 0, SHR_BITALLOCSIZE(maxflows));
  13718         evt_stat->ffbmp = sal_alloc(SHR_BITALLOCSIZE(maxflows),
  13719                                     "alloc evt stat ffbmp");
  13720         if (NULL == evt_stat->ffbmp) {
  13721             LOG_ERROR(BSL_LS_BCM_TSN,
  13722                       (BSL_META_U(unit,
  13723                                   "TSN EVT: "
  13724                                   "failed to alloc evt stat ffbmp\n")));
  13725             (void)bcmi_esw_tsn_event_mgmt_detach(unit);
  13726             return BCM_E_MEMORY;
  13727         }
  13728         sal_memset(evt_stat->ffbmp, 0, SHR_BITALLOCSIZE(maxflows));
  13729    }
  13730 
  13731     /* Create mutex for protecting event management (allocate/free) */
  13732     bkinfo->evt_mutex = sal_mutex_create("tsn evt mgmt mutex");
  13733     if (NULL == bkinfo->evt_mutex) {
  13734         LOG_ERROR(BSL_LS_BCM_TSN,
  13735                   (BSL_META_U(unit,
  13736                               "TSN EVT: failed to create event mgmt mutex\n")));
  13737         (void)bcmi_esw_tsn_event_mgmt_detach(unit);
  13738         return BCM_E_MEMORY;
  13739     }
  13740 
  13741     /* Create poll notify */
  13742     bkinfo->poll_notify = sal_sem_create("TSN EVT poll", sal_sem_BINARY, 0);
  13743     if (NULL == bkinfo->poll_notify) {
  13744         LOG_ERROR(BSL_LS_BCM_TSN,
  13745                   (BSL_META_U(unit,
  13746                               "TSN EVT: failed to create event poll "
  13747                               "notify\n")));
  13748         (void)bcmi_esw_tsn_event_mgmt_detach(unit);
  13749         return BCM_E_MEMORY;
  13750     }
  13751 #if defined(BCM_TSN_SR_SUPPORT)
  13752     if (soc_feature(unit, soc_feature_tsn_sr)) {
  13753         /* Register the event notify callback */
  13754         if (TSN_EVENT_DEVINFO(unit)->register_flow_event_cb) {
  13755             (void)TSN_EVENT_DEVINFO(unit)->register_flow_event_cb(
  13756                 unit, bcmi_esw_tsn_flow_event_notify);
  13757         }
  13758     }
  13759 #endif /* BCM_TSN_SR_SUPPORT */
  13760     if (TSN_EVENT_DEVINFO(unit)->register_cnt_exceed_cb) {
  13761         (void)TSN_EVENT_DEVINFO(unit)->register_cnt_exceed_cb(
  13762             unit, bcmi_esw_tsn_cnt_exceed_notify);
  13763     }
  13764 
  13765     return BCM_E_NONE;
  13766 }
  13767 
  13768 STATIC int
  13769 bcmi_esw_tsn_event_validate(
  13770     int unit,
  13771     bcmi_tsn_evt_inst_type_t inst_type,
  13772     bcm_tsn_event_source_t *src)
  13773 {
  13774     bcmi_esw_tsn_bk_info_t  *tsn_bk;
  13775     bcm_port_t              port;
  13776 #if defined(BCM_TSN_SR_SUPPORT)
  13777     tsn_sr_flows_bookkeeping_t *sr_flow_bkinfo;
  13778     bcm_tsn_sr_flow_t flow_id = src->sr_flow;
  13779     int fidx;
  13780     int dir;
  13781 #endif
  13782 
  13783     /* parameter check */
  13784     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  13785 
  13786     if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_PORT) {
  13787         if (BCM_GPORT_IS_SET(src->port)) {
  13788             BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, src->port, &port));
  13789         } else {
  13790             port = src->port;
  13791         }
  13792         if (!SOC_PORT_VALID(unit, port) ||
  13793             !SOC_PBMP_MEMBER(PBMP_ALL(unit), port)) {
  13794             return BCM_E_PARAM;
  13795         }
  13796     }
  13797     if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW) {
  13798 #if defined(BCM_TSN_SR_SUPPORT)
  13799         if (soc_feature(unit, soc_feature_tsn_sr)) {
  13800             sr_flow_bkinfo = &tsn_bk->sr_flows;
  13801             dir = SR_FLOW_ID_TO_DIR(flow_id);
  13802             fidx = SR_FLOW_ID_TO_IDX(flow_id);
  13803             if (fidx < 0 ||
  13804                 fidx >= sr_flow_bkinfo->max_flows[dir]) {
  13805                 return BCM_E_PARAM;
  13806             }
  13807         } else
  13808 #endif /* BCM_TSN_SR_SUPPORT */
  13809         {
  13810             return BCM_E_PARAM;
  13811         }
  13812     }
  13813 
  13814     if (TSN_EVENT_DEVINFO(unit) == NULL) {
  13815         return BCM_E_UNAVAIL;
  13816     }
  13817     if (TSN_EVENT_DEVINFO(unit)->validate_event) {
  13818         return TSN_EVENT_DEVINFO(unit)->validate_event(unit, inst_type);
  13819     }
  13820     return BCM_E_UNAVAIL;
  13821 }
  13822 
  13823 /* Enable /disable the event mask */
  13824 STATIC int
  13825 bcmi_esw_tsn_event_mask_set(int unit, bcm_tsn_event_type_t event, int enable)
  13826 {
  13827     if (TSN_EVENT_DEVINFO(unit) == NULL) {
  13828         return BCM_E_UNAVAIL;
  13829     }
  13830     if (TSN_EVENT_DEVINFO(unit)->event_mask_set) {
  13831         return TSN_EVENT_DEVINFO(unit)->event_mask_set(unit, event, enable);
  13832     }
  13833     return BCM_E_UNAVAIL;
  13834 }
  13835 
  13836 STATIC int
  13837 bcmi_esw_tsn_event_register(
  13838     int unit,
  13839     bcm_tsn_event_type_t event,
  13840     bcm_tsn_event_source_t *src,
  13841     bcm_tsn_event_cb cb,
  13842     void *user_data)
  13843 {
  13844     int                         i, rv = BCM_E_NONE, event_count;
  13845 #if defined(BCM_TSN_SR_SUPPORT)
  13846     uint32                      idx;
  13847 #endif
  13848     bcmi_tsn_evt_inst_type_t    inst_type;
  13849     tsn_evt_regist_t            *er;
  13850     tsn_evt_inst_t              *einst, *einst_alloc;
  13851     bcmi_esw_tsn_bk_info_t      *tsn_bk;
  13852     tsn_event_bk_t              *bkinfo;
  13853     tsn_evt_stat_t              *evt_stat;
  13854     bcm_port_t                  port;
  13855 
  13856     if ((cb == NULL) || (src == NULL)) {
  13857         return BCM_E_PARAM;
  13858     }
  13859 
  13860     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  13861 
  13862     bkinfo = &tsn_bk->tsn_events;
  13863     if (TSN_EVENT_DEVINFO(unit) == NULL) {
  13864         return BCM_E_UNAVAIL;
  13865     }
  13866 
  13867     /* get the internal instance type */
  13868     inst_type = bcmiTsnEvtCount;
  13869     for (i = 0; i < bcmiTsnEvtCount; i++) {
  13870         if ((tsn_evt_inst_info[i].source_type == src->source_type) &&
  13871             (tsn_evt_inst_info[i].evt_type == event)) {
  13872             inst_type = tsn_evt_inst_info[i].inst_type;
  13873             break;
  13874         }
  13875     }
  13876     if (inst_type == bcmiTsnEvtCount) {
  13877         return BCM_E_PARAM;
  13878     }
  13879     BCM_IF_ERROR_RETURN(bcmi_esw_tsn_event_validate(unit, inst_type, src));
  13880 
  13881     if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_PORT) {
  13882         if (BCM_GPORT_IS_SET(src->port)) {
  13883             BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, src->port, &port));
  13884         } else {
  13885             port = src->port;
  13886         }
  13887     } else {
  13888         port = 0;
  13889     }
  13890     TSN_EVENT_LOCK(unit);
  13891     er = &bkinfo->eregist[inst_type];
  13892     TSN_REVT_LOCK(er);
  13893     if (NULL == er->evt_inst) {
  13894         /* registered instance type array is empty */
  13895         /* allocate the event instance from pool */
  13896         rv = bcmi_esw_tsn_evt_inst_allocate(unit, inst_type, &einst_alloc);
  13897         if (BCM_FAILURE(rv)) {
  13898             TSN_REVT_UNLOCK(er);
  13899             TSN_EVENT_UNLOCK(unit);
  13900             return rv;
  13901         }
  13902         /* Put it on the head of registered event instance list */
  13903         einst_alloc->cb = cb;
  13904         einst_alloc->user_data = user_data;
  13905         einst_alloc->port = port;
  13906         einst_alloc->sr_flow = src->sr_flow;
  13907         einst_alloc->next = NULL;
  13908         er->evt_inst = einst_alloc;
  13909     } else {
  13910         /* registered instance type array is available */
  13911         for (einst = er->evt_inst; einst != NULL; einst = einst->next) {
  13912             if ((einst->cb == cb) && (einst->port == port) &&
  13913                 (einst->sr_flow == src->sr_flow)) {
  13914                 /* matched the callback and event source */
  13915                 TSN_REVT_UNLOCK(er);
  13916                 TSN_EVENT_UNLOCK(unit);
  13917                 return BCM_E_EXISTS;
  13918             } else {
  13919                 /* not exactly matched instance, allocate a new one */
  13920                 rv = bcmi_esw_tsn_evt_inst_allocate(unit, inst_type,
  13921                                                     &einst_alloc);
  13922                 if (BCM_FAILURE(rv)) {
  13923                     TSN_REVT_UNLOCK(er);
  13924                     TSN_EVENT_UNLOCK(unit);
  13925                     return rv;
  13926                 }
  13927                 /* Put it on the head of registered event instance list */
  13928                 einst_alloc->cb = cb;
  13929                 einst_alloc->user_data = user_data;
  13930                 einst_alloc->port = port;
  13931                 einst_alloc->sr_flow = src->sr_flow;
  13932                 einst_alloc->next = er->evt_inst;
  13933                 er->evt_inst = einst_alloc;
  13934             }
  13935         }
  13936     }
  13937 
  13938     /* update the event stat */
  13939     evt_stat = &bkinfo->evt_stat[event];
  13940     if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_PORT) {
  13941         evt_stat->port_ref[port]++;
  13942     } else if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW) {
  13943 #if defined(BCM_TSN_SR_SUPPORT)
  13944         if (soc_feature(unit, soc_feature_tsn_sr)) {
  13945             rv = bcmi_esw_tsn_sr_hw_flow_id_get(unit, src->sr_flow, &idx);
  13946             if (BCM_FAILURE(rv)) {
  13947                 einst = er->evt_inst;
  13948                 er->evt_inst = einst->next;
  13949                 (void)bcmi_esw_tsn_evt_inst_free(unit, inst_type, einst);
  13950                 TSN_REVT_UNLOCK(er);
  13951                 TSN_EVENT_UNLOCK(unit);
  13952                 return rv;
  13953             }
  13954             evt_stat->flow_ref[idx]++;
  13955             if ((SR_FLOW_ID_TO_DIR(src->sr_flow) == SR_FLOW_DIR_RX) &&
  13956                 (evt_stat->flow_ref[idx] == 1)) {
  13957                 if (TSN_EVENT_DEVINFO(unit)->update_rx_flow) {
  13958                     rv = TSN_EVENT_DEVINFO(unit)->update_rx_flow(unit,
  13959                                                                  (int)event,
  13960                                                                  idx,
  13961                                                                  1);
  13962                     if (BCM_FAILURE(rv)) {
  13963                         einst = er->evt_inst;
  13964                         er->evt_inst = einst->next;
  13965                         (void)bcmi_esw_tsn_evt_inst_free(unit,
  13966                                                          inst_type,
  13967                                                          einst);
  13968                         TSN_REVT_UNLOCK(er);
  13969                         TSN_EVENT_UNLOCK(unit);
  13970                         return rv;
  13971                     }
  13972                 }
  13973             }
  13974         } else
  13975 #endif /* BCM_TSN_SR_SUPPORT */
  13976         {
  13977             einst = er->evt_inst;
  13978             er->evt_inst = einst->next;
  13979             (void)bcmi_esw_tsn_evt_inst_free(unit,
  13980                                              inst_type,
  13981                                              einst);
  13982             TSN_REVT_UNLOCK(er);
  13983             TSN_EVENT_UNLOCK(unit);
  13984             return BCM_E_UNAVAIL;
  13985         }
  13986     }
  13987     event_count = evt_stat->event_ref;
  13988     evt_stat->event_ref++;
  13989 
  13990     if (event_count == 0) {
  13991         rv = bcmi_esw_tsn_event_mask_set(unit, event, 1);
  13992         if (BCM_FAILURE(rv)) {
  13993             einst = er->evt_inst;
  13994             er->evt_inst = einst->next;
  13995             (void)bcmi_esw_tsn_evt_inst_free(unit, inst_type, einst);
  13996         }
  13997     }
  13998     TSN_REVT_UNLOCK(er);
  13999     TSN_EVENT_UNLOCK(unit);
  14000     return BCM_E_NONE;
  14001 }
  14002 
  14003 STATIC int
  14004 bcmi_esw_tsn_event_unregister(
  14005     int unit,
  14006     bcm_tsn_event_type_t event,
  14007     bcm_tsn_event_source_t *src,
  14008     bcm_tsn_event_cb cb)
  14009 {
  14010     int                         i, rv = BCM_E_NOT_FOUND, event_count;
  14011 #if defined(BCM_TSN_SR_SUPPORT)
  14012     uint32                      idx;
  14013 #endif
  14014     bcmi_tsn_evt_inst_type_t    inst_type;
  14015     tsn_evt_regist_t            *er;
  14016     tsn_evt_inst_t              *einst, *prev;
  14017     bcmi_esw_tsn_bk_info_t      *tsn_bk;
  14018     tsn_event_bk_t              *bkinfo;
  14019     tsn_evt_stat_t              *evt_stat;
  14020     bcm_port_t                  port;
  14021 
  14022     if ((cb == NULL) || (src == NULL)) {
  14023         return BCM_E_PARAM;
  14024     }
  14025 
  14026     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  14027     bkinfo = &tsn_bk->tsn_events;
  14028 
  14029     /* get the internal instance type */
  14030     inst_type = bcmiTsnEvtCount;
  14031     for (i = 0; i < bcmiTsnEvtCount; i++) {
  14032         if ((tsn_evt_inst_info[i].source_type == src->source_type) &&
  14033             (tsn_evt_inst_info[i].evt_type == event)) {
  14034             inst_type = tsn_evt_inst_info[i].inst_type;
  14035             break;
  14036         }
  14037     }
  14038     if (inst_type == bcmiTsnEvtCount) {
  14039         return BCM_E_PARAM;
  14040     }
  14041     BCM_IF_ERROR_RETURN(bcmi_esw_tsn_event_validate(unit, inst_type, src));
  14042 
  14043     if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_PORT) {
  14044         if (BCM_GPORT_IS_SET(src->port)) {
  14045             BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, src->port, &port));
  14046         } else {
  14047             port = src->port;
  14048         }
  14049     } else {
  14050         port = 0;
  14051     }
  14052     TSN_EVENT_LOCK(unit);
  14053     er = &bkinfo->eregist[inst_type];
  14054     TSN_REVT_LOCK(er);
  14055     if (NULL == er->evt_inst) {
  14056         /* registered instance type array is empty. */
  14057         TSN_REVT_UNLOCK(er);
  14058         TSN_EVENT_UNLOCK(unit);
  14059         return BCM_E_NOT_FOUND;
  14060     } else {
  14061         /* registered instance type array is available */
  14062         prev = NULL;
  14063         for (einst = er->evt_inst; einst != NULL; einst = einst->next) {
  14064             if ((einst->cb == cb) && (einst->port == port) &&
  14065                 (einst->sr_flow == src->sr_flow)) {
  14066                 /* matched the callback and event source */
  14067                 /* remove it from the er list */
  14068                 if (prev == NULL) {
  14069                     er->evt_inst = einst->next;
  14070                 } else {
  14071                     prev->next = einst->next;
  14072                 }
  14073                 /* Free to inst pool */
  14074                 (void)bcmi_esw_tsn_evt_inst_free(unit, inst_type, einst);
  14075                 rv = BCM_E_NONE;
  14076                 break;
  14077             }
  14078             prev = einst;
  14079         }
  14080         TSN_REVT_UNLOCK(er);
  14081         if (BCM_SUCCESS(rv)) {
  14082             /* update the bkinfo->event_count */
  14083             evt_stat = &bkinfo->evt_stat[event];
  14084             if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_PORT) {
  14085                 if (evt_stat->port_ref[port] > 0) {
  14086                     evt_stat->port_ref[port]--;
  14087                 }
  14088             } else if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW) {
  14089 #if defined(BCM_TSN_SR_SUPPORT)
  14090                 if (soc_feature(unit, soc_feature_tsn_sr)) {
  14091                     rv = bcmi_esw_tsn_sr_hw_flow_id_get(unit, src->sr_flow,
  14092                                                         &idx);
  14093                     if (BCM_FAILURE(rv)) {
  14094                         TSN_EVENT_UNLOCK(unit);
  14095                         return rv;
  14096                     }
  14097                     if (evt_stat->flow_ref[idx] > 0) {
  14098                         evt_stat->flow_ref[idx]--;
  14099                     }
  14100                     if ((SR_FLOW_ID_TO_DIR(src->sr_flow) == SR_FLOW_DIR_RX) &&
  14101                         (evt_stat->flow_ref[idx] == 0)) {
  14102                         if (TSN_EVENT_DEVINFO(unit)->update_rx_flow) {
  14103                             rv = TSN_EVENT_DEVINFO(unit)->update_rx_flow(
  14104                                  unit, (int)event, idx, 0);
  14105                             if (BCM_FAILURE(rv)) {
  14106                                 TSN_EVENT_UNLOCK(unit);
  14107                                 return rv;
  14108                             }
  14109                         }
  14110                     }
  14111                 } else
  14112 #endif /* BCM_TSN_SR_SUPPORT */
  14113                 {
  14114                     TSN_EVENT_UNLOCK(unit);
  14115                     return BCM_E_UNAVAIL;
  14116                 }
  14117             }
  14118             evt_stat->event_ref--;
  14119             event_count = evt_stat->event_ref;
  14120             if (event_count == 0) {
  14121                 rv = bcmi_esw_tsn_event_mask_set(unit, event, 0);
  14122                 if (BCM_FAILURE(rv)) {
  14123                     TSN_EVENT_UNLOCK(unit);
  14124                     return rv;
  14125                 }
  14126             }
  14127         }
  14128     }
  14129     TSN_EVENT_UNLOCK(unit);
  14130     return rv;
  14131 }
  14132 
  14133 STATIC int
  14134 bcmi_esw_tsn_event_notification_traverse(
  14135     int unit,
  14136     bcm_tsn_event_notification_traverse_cb cb,
  14137     void *user_data)
  14138 {
  14139     bcm_tsn_event_type_t    event;
  14140     bcm_tsn_event_source_t  src;
  14141     bcm_tsn_event_cb        evt_cb;
  14142     void                    *evt_cb_user_data;
  14143     int                     i, rv;
  14144     tsn_evt_regist_t        *er;
  14145     tsn_evt_inst_t          *einst;
  14146     bcmi_esw_tsn_bk_info_t  *tsn_bk;
  14147     tsn_event_bk_t          *bkinfo;
  14148 
  14149     if (cb == NULL) {
  14150         return BCM_E_PARAM;
  14151     }
  14152 
  14153     /* parameter check */
  14154     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk));
  14155 
  14156     bkinfo = &tsn_bk->tsn_events;
  14157 
  14158     for (i = 0; i < bcmiTsnEvtCount; i++) {
  14159         er = &bkinfo->eregist[i];
  14160         TSN_REVT_LOCK(er);
  14161         for (einst = er->evt_inst; einst != NULL; einst = einst->next) {
  14162             event = er->evt_type;
  14163             bcm_tsn_event_source_t_init(&src);
  14164             src.source_type = er->source_type;
  14165             src.port = einst->port;
  14166             src.sr_flow = einst->sr_flow;
  14167             evt_cb = einst->cb;
  14168             evt_cb_user_data = einst->user_data;
  14169             rv = cb(unit, event, &src, evt_cb, evt_cb_user_data, user_data);
  14170             if (BCM_FAILURE(rv)) {
  14171                 TSN_REVT_UNLOCK(er);
  14172                 return rv;
  14173             }
  14174         }
  14175         TSN_REVT_UNLOCK(er);
  14176     }
  14177     return BCM_E_NONE;
  14178 }
  14179 
  14180 #ifdef BCM_WARM_BOOT_SUPPORT
  14181 /*
  14182  * Function:
  14183  *   bcmi_esw_tsn_reinit
  14184  * Purpose:
  14185  *   Restore bookkeeping information.
  14186  * Parameters:
  14187  *   unit - (IN) unit number
  14188  * Returns:
  14189  *   BCM_E_XXX
  14190  */
  14191 STATIC int
  14192 bcmi_esw_tsn_reinit(int unit)
  14193 {
  14194     bcm_error_t rv = BCM_E_UNAVAIL;
  14195 
  14196     if (!SOC_WARM_BOOT(unit)) {
  14197         return BCM_E_UNAVAIL;
  14198     }
  14199 
  14200     if (!soc_feature(unit, soc_feature_tsn)) {
  14201         return BCM_E_UNAVAIL;
  14202     }
  14203 
  14204 #if defined(BCM_TSN_SR_SUPPORT)
  14205     if (soc_feature(unit, soc_feature_tsn_sr)) {
  14206         /*
  14207          * Load TSN SR MAC Proxy info from hardware
  14208          * into software data structures.
  14209          */
  14210         rv = bcmi_esw_tsn_sr_mac_proxy_reload(unit);
  14211         if (BCM_FAILURE(rv)) {
  14212             return rv;
  14213         }
  14214     }
  14215 #endif /* BCM_TSN_SR_SUPPORT */
  14216 
  14217     /* Doing TSN TAF resource reinit */
  14218     if (soc_feature(unit, soc_feature_tsn_taf)) {
  14219         rv = bcmi_esw_tsn_taf_reload(unit);
  14220         if (BCM_FAILURE(rv)) {
  14221             LOG_ERROR(BSL_LS_BCM_TSN,
  14222                       (BSL_META_U(unit,
  14223                                   "TSN TAF Reload Warm boot failed"
  14224                                   "(rv = %d)\n"),
  14225                                   rv));
  14226             return rv;
  14227         }
  14228     }
  14229 
  14230     /* Doing TSN and SR priority map resource reinit */
  14231     rv = bcmi_esw_tsn_pri_map_tsn_sr_reload(unit);
  14232     if (BCM_FAILURE(rv)) {
  14233         LOG_ERROR(BSL_LS_BCM_TSN,
  14234                   (BSL_META_U(unit,
  14235                               "TSN Priority Map Warm boot failed"
  14236                               "(rv = %d)\n"),
  14237                               rv));
  14238         return rv;
  14239     }
  14240 
  14241 #if defined(BCM_TSN_SR_SUPPORT)
  14242     if (soc_feature(unit, soc_feature_tsn_sr)) {
  14243         /* Doing SR flows resource reinint */
  14244         rv = bcmi_esw_tsn_sr_flow_mgmt_reload(unit);
  14245         if (BCM_FAILURE(rv)) {
  14246             LOG_ERROR(BSL_LS_BCM_TSN,
  14247                       (BSL_META_U(unit,
  14248                                   "TSN SR flows warm boot reload failed"
  14249                                   "(rv = %d)\n"),
  14250                                   rv));
  14251             return rv;
  14252         }
  14253     }
  14254 #endif /* BCM_TSN_SR_SUPPORT */
  14255 
  14256     /* Doing TSN flows resource reinint */
  14257     rv = bcmi_esw_tsn_flow_mgmt_reload(unit);
  14258     if (BCM_FAILURE(rv)) {
  14259         LOG_ERROR(BSL_LS_BCM_TSN,
  14260                   (BSL_META_U(unit,
  14261                               "TSN flows warm boot reload failed"
  14262                               "(rv = %d)\n"),
  14263                               rv));
  14264         return rv;
  14265     }
  14266 
  14267 #if defined(BCM_TSN_SR_SUPPORT)
  14268     if (soc_feature(unit, soc_feature_tsn_sr) &&
  14269         soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
  14270         /*
  14271          * Load TSN SR Auto Learn info from hardware
  14272          * into software data structures.
  14273          */
  14274         rv = bcmi_esw_tsn_sr_auto_learn_reload(unit);
  14275         if (BCM_FAILURE(rv)) {
  14276             LOG_ERROR(BSL_LS_BCM_TSN,
  14277                       (BSL_META_U(unit,
  14278                                   "SR Auto Learn Warm boot failed(rv = %d)\n"),
  14279                                   rv));
  14280             return rv;
  14281         }
  14282     }
  14283 #endif /* BCM_TSN_SR_SUPPORT */
  14284 
  14285     /* Doing TSN MTU & STU resource reinit */
  14286     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  14287         rv = bcmi_esw_tsn_egress_mtu_reload(unit);
  14288         if (BCM_FAILURE(rv)) {
  14289             LOG_ERROR(BSL_LS_BCM_TSN,
  14290                       (BSL_META_U(unit,
  14291                                   "TSN MTU Reload Warm boot failed"
  14292                                   "(rv = %d)\n"),
  14293                                   rv));
  14294             return rv;
  14295         }
  14296         rv = bcmi_esw_tsn_egress_stu_reload(unit);
  14297         if (BCM_FAILURE(rv)) {
  14298             LOG_ERROR(BSL_LS_BCM_TSN,
  14299                       (BSL_META_U(unit,
  14300                                   "TSN STU Reload Warm boot failed"
  14301                                   "(rv = %d)\n"),
  14302                                   rv));
  14303             return rv;
  14304         }
  14305     }
  14306 
  14307     /* Doing TSN PRP-Forwarding resource reinit */
  14308     rv = bcmi_esw_tsn_sr_port_prp_forwarding_reload(unit);
  14309     if (BCM_FAILURE(rv)) {
  14310         LOG_ERROR(BSL_LS_BCM_TSN,
  14311                   (BSL_META_U(unit,
  14312                               "TSN PRP-Forwarding Reload Warm boot failed"
  14313                               "(rv = %d)\n"),
  14314                               rv));
  14315         return rv;
  14316     }
  14317 
  14318     /* Doing TSN Portcnt Stat/Port bitmap resource reinit */
  14319     rv = bcmi_esw_tsn_stat_portcnt_reload(unit);
  14320     if (BCM_FAILURE(rv)) {
  14321         LOG_ERROR(BSL_LS_BCM_TSN,
  14322                   (BSL_META_U(unit,
  14323                               "TSN Stat Portcnt Reload Warm boot failed"
  14324                               "(rv = %d)\n"),
  14325                               rv));
  14326         return rv;
  14327     }
  14328 
  14329     /* Doing TSN Flowcnt Stat resource reinit */
  14330     rv = bcmi_esw_tsn_stat_flowcnt_reload(unit);
  14331     if (BCM_FAILURE(rv)) {
  14332         LOG_ERROR(BSL_LS_BCM_TSN,
  14333                   (BSL_META_U(unit,
  14334                               "TSN Stat Flowcnt Reload Warm boot failed"
  14335                               "(rv = %d)\n"),
  14336                               rv));
  14337         return rv;
  14338     }
  14339 
  14340     return BCM_E_NONE;
  14341 }
  14342 
  14343 /*
  14344  * Function:
  14345  *   bcmi_esw_tsn_sync
  14346  * Purpose:
  14347  *   Store bookkeeping information for
  14348  *   Warmboot recovery.
  14349  * Parameters:
  14350  *   unit - (IN) unit number
  14351  * Returns:
  14352  *   BCM_E_XXX
  14353  */
  14354 STATIC int
  14355 bcmi_esw_tsn_sync(int unit)
  14356 {
  14357     bcm_error_t rv = BCM_E_UNAVAIL;
  14358 
  14359     if (!soc_feature(unit, soc_feature_tsn)) {
  14360         return BCM_E_UNAVAIL;
  14361     }
  14362 
  14363     /* Doing TSN MTU & STU resource sync */
  14364     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  14365         rv = bcmi_esw_tsn_egress_mtu_sync(unit);
  14366         if (BCM_FAILURE(rv)) {
  14367             LOG_ERROR(BSL_LS_BCM_TSN,
  14368                       (BSL_META_U(unit,
  14369                                   "TSN MTU Sync Warm boot failed"
  14370                                   "(rv = %d)\n"),
  14371                                   rv));
  14372             return rv;
  14373         }
  14374         rv = bcmi_esw_tsn_egress_stu_sync(unit);
  14375         if (BCM_FAILURE(rv)) {
  14376             LOG_ERROR(BSL_LS_BCM_TSN,
  14377                       (BSL_META_U(unit,
  14378                                   "TSN STU Sync Warm boot failed"
  14379                                   "(rv = %d)\n"),
  14380                                   rv));
  14381             return rv;
  14382         }
  14383     }
  14384 
  14385     /* Sync TSN flows to scache */
  14386     rv = bcmi_esw_tsn_flow_mgmt_sync(unit);
  14387     if (BCM_FAILURE(rv)) {
  14388         LOG_ERROR(BSL_LS_BCM_TSN,
  14389                   (BSL_META_U(unit,
  14390                               "TSN flows warm boot sync failed"
  14391                               "(rv = %d)\n"),
  14392                               rv));
  14393         return rv;
  14394     }
  14395 
  14396 #if defined(BCM_TSN_SR_SUPPORT)
  14397     if (soc_feature(unit, soc_feature_tsn_sr)) {
  14398         /* Sync SR flows to scache */
  14399         rv = bcmi_esw_tsn_sr_flow_mgmt_sync(unit);
  14400         if (BCM_FAILURE(rv)) {
  14401             LOG_ERROR(BSL_LS_BCM_TSN,
  14402                       (BSL_META_U(unit,
  14403                                   "TSN SR flows warm boot sync failed"
  14404                                   "(rv = %d)\n"),
  14405                                   rv));
  14406             return rv;
  14407         }
  14408 
  14409         rv = bcmi_esw_tsn_sr_port_prp_forwarding_sync(unit);
  14410         if (BCM_FAILURE(rv)) {
  14411             LOG_ERROR(BSL_LS_BCM_TSN,
  14412                       (BSL_META_U(unit,
  14413                                   "TSN PRP Forwarding Warm boot failed"
  14414                                   "(rv = %d)\n"),
  14415                                   rv));
  14416             return rv;
  14417         }
  14418     }
  14419     if (soc_feature(unit, soc_feature_tsn_sr) &&
  14420         soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
  14421         rv = bcmi_esw_tsn_sr_auto_learn_sync(unit);
  14422         if (BCM_FAILURE(rv)) {
  14423             LOG_ERROR(BSL_LS_BCM_TSN,
  14424                       (BSL_META_U(unit,
  14425                                   "TSN SR Auto Learn Sync Warm boot failed"
  14426                                   "(rv = %d)\n"),
  14427                                   rv));
  14428             return rv;
  14429         }
  14430     }
  14431 #endif /* BCM_TSN_SR_SUPPORT */
  14432 
  14433     /* Doing TSN Portcnt Stat/Port bitmap resource sync */
  14434     rv = bcmi_esw_tsn_stat_portcnt_sync(unit);
  14435     if (BCM_FAILURE(rv)) {
  14436         LOG_ERROR(BSL_LS_BCM_TSN,
  14437                   (BSL_META_U(unit,
  14438                               "TSN Stat Portcnt Sync Warm boot failed"
  14439                               "(rv = %d)\n"),
  14440                               rv));
  14441         return rv;
  14442     }
  14443 
  14444      /* Doing TSN Flowtcnt Stat resource sync */
  14445     rv = bcmi_esw_tsn_stat_flowcnt_sync(unit);
  14446     if (BCM_FAILURE(rv)) {
  14447         LOG_ERROR(BSL_LS_BCM_TSN,
  14448                   (BSL_META_U(unit,
  14449                               "TSN Stat Flowcnt Sync Warm boot failed"
  14450                               "(rv = %d)\n"),
  14451                               rv));
  14452         return rv;
  14453     }
  14454  
  14455     /* Doing TSN TAF resource sync */
  14456     if (soc_feature(unit, soc_feature_tsn_taf)) {
  14457         rv = bcmi_esw_tsn_taf_sync(unit);
  14458         if (BCM_FAILURE(rv)) {
  14459             LOG_ERROR(BSL_LS_BCM_TSN,
  14460                       (BSL_META_U(unit,
  14461                                   "TSN TAF Sync Warm boot failed"
  14462                                   "(rv = %d)\n"),
  14463                                   rv));
  14464             return rv;
  14465         }
  14466     }
  14467 
  14468     return BCM_E_NONE;
  14469 }
  14470 #endif /* BCM_WARM_BOOT_SUPPORT */
  14471 
  14472 /*
  14473  * Function:
  14474  *   bcmi_esw_tsn_coldboot_init
  14475  * Purpose:
  14476  *   Restore bookkeeping information.
  14477  * Parameters:
  14478  *   unit - (IN) unit number
  14479  * Returns:
  14480  *   BCM_E_XXX
  14481  */
  14482 STATIC int
  14483 bcmi_esw_tsn_coldboot_init(int unit)
  14484 {
  14485     bcm_error_t rv = BCM_E_UNAVAIL;
  14486 
  14487 #if defined(BCM_WARM_BOOT_SUPPORT)
  14488     /* Warm boot should be false in cold boot case */
  14489     if (SOC_WARM_BOOT(unit)) {
  14490         return BCM_E_UNAVAIL;
  14491     }
  14492 
  14493 #if defined(BCM_TSN_SR_SUPPORT)
  14494     if (soc_feature(unit, soc_feature_tsn_sr)) {
  14495         /* Allocate scache for SR flows */
  14496         BCM_IF_ERROR_RETURN(bcmi_esw_tsn_sr_flow_mgmt_wb_alloc(unit));
  14497     }
  14498     if (soc_feature(unit, soc_feature_tsn_sr) &&
  14499         soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
  14500         /* Allocate scache for SR Auto Learn management */
  14501         BCM_IF_ERROR_RETURN(bcmi_esw_tsn_sr_auto_learn_wb_alloc(unit));
  14502     }
  14503 #endif /* BCM_TSN_SR_SUPPORT */
  14504 
  14505     /* Allocate scache for TSN flows */
  14506     BCM_IF_ERROR_RETURN(bcmi_esw_tsn_flow_mgmt_wb_alloc(unit));
  14507 
  14508 #endif /* BCM_WARM_BOOT_SUPPORT */
  14509 
  14510     /* Doing TSN and SR priority map resource cold boot init */
  14511     rv = bcmi_esw_tsn_pri_map_tsn_sr_coldboot_init(unit);
  14512     if (BCM_FAILURE(rv)) {
  14513         LOG_ERROR(BSL_LS_BCM_TSN,
  14514                   (BSL_META_U(unit,
  14515                               "TSN Priority Map Cold boot failed"
  14516                               "(rv = %d)\n"),
  14517                               rv));
  14518         return rv;
  14519     }
  14520 
  14521     /* Doing TAF resource cold boot init */
  14522     if (soc_feature(unit, soc_feature_tsn_taf)) {
  14523         rv = bcmi_esw_tsn_taf_coldboot_init(unit);
  14524         if (BCM_FAILURE(rv)) {
  14525             LOG_ERROR(BSL_LS_BCM_TSN,
  14526                       (BSL_META_U(unit,
  14527                                   "TSN TAF Cold boot failed"
  14528                                   "(rv = %d)\n"),
  14529                                   rv));
  14530             return rv;
  14531         }
  14532     }
  14533 
  14534     return BCM_E_NONE;
  14535 }
  14536 
  14537 /*
  14538  * Function:
  14539  *     bcmi_esw_tsn_bk_info_cleanup
  14540  * Purpose:
  14541  *     Internal function to clear the resource of the TSN module.
  14542  * Parameters:
  14543  *     unit             - (IN) unit number
  14544  * Returns:
  14545  *     BCM_E_XXX
  14546  */
  14547 STATIC int
  14548 bcmi_esw_tsn_bk_info_cleanup(int unit)
  14549 {
  14550     LOG_VERBOSE(BSL_LS_BCM_TSN,
  14551                 (BSL_META_U(unit,
  14552                             "bcmi_esw_tsn_bk_info_cleanup\n")));
  14553 
  14554     /* Free and clear the bookkeeping info structure */
  14555     if (tsn_bk_info[unit] != NULL) {
  14556         /* Event management clean up */
  14557         bcmi_esw_tsn_event_mgmt_detach(unit);
  14558 
  14559 #if defined(BCM_TSN_SR_SUPPORT)
  14560         if (soc_feature(unit, soc_feature_tsn_sr)) {
  14561             /* SR Auto Learn management clean up */
  14562             bcmi_esw_tsn_sr_auto_learn_cleanup(unit);
  14563             /* SR MAC proxy management clean up */
  14564             bcmi_esw_tsn_sr_mac_proxy_cleanup(unit);
  14565             /* SR flow management clean up */
  14566             bcmi_esw_tsn_sr_flow_mgmt_detach(unit);
  14567         }
  14568 #endif /* BCM_TSN_SR_SUPPORT */
  14569 
  14570         /* TSN priority map management clean up */
  14571         bcmi_esw_tsn_pri_map_cleanup(unit);
  14572 
  14573         /* MTU & STU management clean up */
  14574         bcmi_esw_tsn_mtu_cleanup(unit);
  14575         bcmi_esw_tsn_stu_cleanup(unit);
  14576 
  14577         /* TSN flow management clean up */
  14578         bcmi_esw_tsn_flow_mgmt_detach(unit);
  14579 
  14580         TSN_FREE(unit, tsn_bk_info[unit], 0);
  14581         tsn_bk_info[unit] = NULL;
  14582     }
  14583 
  14584     return BCM_E_NONE;
  14585 }
  14586 
  14587 /*
  14588  * Function:
  14589  *     bcmi_esw_tsn_detach
  14590  * Purpose:
  14591  *     Clear the resource of the TSN module.
  14592  * Parameters:
  14593  *     unit - (IN) unit number
  14594  * Returns:
  14595  *     BCM_E_XXX
  14596  */
  14597 STATIC int
  14598 bcmi_esw_tsn_detach(int unit)
  14599 {
  14600     if (!soc_feature(unit, soc_feature_tsn)) {
  14601         return BCM_E_UNAVAIL;
  14602     }
  14603 
  14604     /* clean up TSN Stat counters info resource */
  14605     BCM_IF_ERROR_RETURN(
  14606         bcmi_esw_tsn_stat_cleanup(unit));
  14607 
  14608     /* clean up TAF resource */
  14609     if (soc_feature(unit, soc_feature_tsn_taf)) {
  14610         bcmi_esw_tsn_taf_cleanup(unit);
  14611     }
  14612 
  14613     /* clean up bookkeeping info resource */
  14614     BCM_IF_ERROR_RETURN(
  14615         bcmi_esw_tsn_bk_info_cleanup(unit));
  14616 
  14617 #ifdef BCM_GREYHOUND2_SUPPORT
  14618     /* chip specific detach */
  14619     if (SOC_IS_GREYHOUND2(unit)) {
  14620         BCM_IF_ERROR_RETURN(
  14621             bcmi_gh2_tsn_info_detach(unit));
  14622     }
  14623 #endif /* BCM_GREYHOUND2_SUPPORT */
  14624 
  14625     return BCM_E_NONE;
  14626 }
  14627 
  14628 /*
  14629  * Function:
  14630  *     bcmi_esw_tsn_init
  14631  * Purpose:
  14632  *     Internal function to initialize the resource and setup device info.
  14633  * Parameters:
  14634  *     unit - (IN) unit number
  14635  * Returns:
  14636  *     BCM_E_XXX
  14637  */
  14638 STATIC int
  14639 bcmi_esw_tsn_init(int unit)
  14640 {
  14641     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  14642     int rv = BCM_E_NONE;
  14643     int i;
  14644 
  14645     LOG_VERBOSE(BSL_LS_BCM_TSN,
  14646                 (BSL_META_U(unit,
  14647                             "bcmi_esw_tsn_init\n")));
  14648 
  14649     if (!soc_feature(unit, soc_feature_tsn)) {
  14650         return BCM_E_UNAVAIL;
  14651     }
  14652 
  14653     /* Initialize structure */
  14654     if (!tsn_bk_info_initialized) {
  14655         for (i = 0; i < BCM_MAX_NUM_UNITS; i++) {
  14656             tsn_bk_info[i] = NULL;
  14657         }
  14658         tsn_bk_info_initialized = 1;
  14659     }
  14660 
  14661     /* Clean up the bookkeeping resource */
  14662     if (tsn_bk_info[unit] != NULL) {
  14663         rv = bcmi_esw_tsn_bk_info_cleanup(unit);
  14664         if (BCM_FAILURE(rv)) {
  14665             return rv;
  14666         }
  14667     }
  14668 
  14669     /* Allocate TSN bookkeeping resource for this unit. */
  14670     TSN_ALLOC(unit, bk_info, bcmi_esw_tsn_bk_info_t,
  14671               sizeof(bcmi_esw_tsn_bk_info_t),
  14672               "TSN bookkeeping info", 0, rv);
  14673     if (BCM_FAILURE(rv)) {
  14674         LOG_VERBOSE(BSL_LS_BCM_TSN,
  14675                     (BSL_META_U(unit,
  14676                                 "bcmi_esw_tsn_init: failed to "
  14677                                 "allocate memory\n")));
  14678         return rv;
  14679     }
  14680 
  14681     /* Get the chip dev_info structure. */
  14682     tsn_bk_info[unit] = bk_info;
  14683 #ifdef BCM_GREYHOUND2_SUPPORT
  14684     if (SOC_IS_GREYHOUND2(unit)) {
  14685         rv = bcmi_gh2_tsn_info_init(unit, &bk_info->tsn_dev_info);
  14686     } else
  14687 #endif
  14688     {
  14689         rv = BCM_E_UNAVAIL;
  14690     }
  14691 
  14692     /* Release resource if any error occurred. */
  14693     if (BCM_FAILURE(rv) || bk_info->tsn_dev_info == NULL) {
  14694         bcmi_esw_tsn_bk_info_cleanup(unit);
  14695         if (BCM_SUCCESS(rv)) {
  14696             return BCM_E_UNAVAIL;
  14697         }
  14698         return (rv);
  14699     }
  14700 
  14701     /* Initialize TAF */
  14702     if (soc_feature(unit, soc_feature_tsn_taf)) {
  14703         rv = bcmi_esw_tsn_taf_init(unit);
  14704         /* Release resource if any error occurred. */
  14705         if (BCM_FAILURE(rv)) {
  14706             bcmi_esw_tsn_detach(unit);
  14707             return rv;
  14708         }
  14709     }
  14710 
  14711     /* Allocate TSN Priority Map bookkeeping resource for this unit */
  14712     rv = bcmi_esw_tsn_pri_map_init(unit);
  14713 
  14714     /* Release resource if any error occurred. */
  14715     if (BCM_FAILURE(rv)) {
  14716         bcmi_esw_tsn_bk_info_cleanup(unit);
  14717         return rv;
  14718     }
  14719 
  14720 #if defined(BCM_TSN_SR_SUPPORT)
  14721     if (soc_feature(unit, soc_feature_tsn_sr)) {
  14722         /* Allocate TSN SR Mac Proxy bookkeeping resource for this unit */
  14723         rv = bcmi_esw_tsn_sr_mac_proxy_init(unit);
  14724         if (BCM_FAILURE(rv)) {
  14725             bcmi_esw_tsn_detach(unit);
  14726             return rv;
  14727         }
  14728 
  14729         /* SR flow management initialization */
  14730         rv = bcmi_esw_tsn_sr_flow_mgmt_init(unit);
  14731         if (BCM_FAILURE(rv)) {
  14732             bcmi_esw_tsn_detach(unit);
  14733             return (rv);
  14734         }
  14735 
  14736     }
  14737     if (soc_feature(unit, soc_feature_tsn_sr) &&
  14738         soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
  14739         /* Initialize SR Auto Learn management */
  14740         rv = bcmi_esw_tsn_sr_auto_learn_init(unit);
  14741         /* Release resource if any error occurred. */
  14742         if (BCM_FAILURE(rv)) {
  14743             bcmi_esw_tsn_detach(unit);
  14744             return rv;
  14745         }
  14746     }
  14747 #endif /* BCM_TSN_SR_SUPPORT */
  14748 
  14749     /* TSN flow management initialization */
  14750     rv = bcmi_esw_tsn_flow_mgmt_init(unit);
  14751     if (BCM_FAILURE(rv)) {
  14752         bcmi_esw_tsn_detach(unit);
  14753         return (rv);
  14754     }
  14755 
  14756     /* Allocate MTU /STU bookkeeping resource for this unit */
  14757     rv = bcmi_esw_tsn_mtu_init(unit);
  14758     /* Release resource if any error occurred. */
  14759     if (BCM_FAILURE(rv)) {
  14760         bcmi_esw_tsn_bk_info_cleanup(unit);
  14761         return rv;
  14762     }
  14763 
  14764     rv = bcmi_esw_tsn_stu_init(unit);
  14765     /* Release resource if any error occurred. */
  14766     if (BCM_FAILURE(rv)) {
  14767         bcmi_esw_tsn_bk_info_cleanup(unit);
  14768         return rv;
  14769     }
  14770 
  14771     /* Initialize TSN Stat counters */
  14772     rv = bcmi_esw_tsn_stat_init(unit);
  14773     /* Release resource if any error occurred. */
  14774     if (BCM_FAILURE(rv)) {
  14775         bcmi_esw_tsn_detach(unit);
  14776         return rv;
  14777     }
  14778 
  14779     /* Initialize TSN event management */
  14780     rv = bcmi_esw_tsn_event_mgmt_init(unit);
  14781     /* Release resource if any error occurred. */
  14782     if (BCM_FAILURE(rv)) {
  14783         bcmi_esw_tsn_detach(unit);
  14784         return rv;
  14785     }
  14786 
  14787 #ifdef BCM_WARM_BOOT_SUPPORT
  14788     /* Warm Boot recovery */
  14789     if (SOC_WARM_BOOT(unit)) {
  14790         rv = bcmi_esw_tsn_reinit(unit);
  14791         if (BCM_FAILURE(rv)) {
  14792             bcmi_esw_tsn_detach(unit);
  14793             LOG_ERROR(BSL_LS_BCM_TSN,
  14794                       (BSL_META_U(unit,
  14795                                   "Warm boot failed"
  14796                                   "(rv = %d)\n"),
  14797                                   rv));
  14798             return rv;
  14799         }
  14800     } else
  14801 #endif /* BCM_WARM_BOOT_SUPPORT */
  14802     {
  14803         /* Cold Boot */
  14804         rv = bcmi_esw_tsn_coldboot_init(unit);
  14805         if (BCM_FAILURE(rv)) {
  14806             bcmi_esw_tsn_detach(unit);
  14807             LOG_ERROR(BSL_LS_BCM_TSN,
  14808                       (BSL_META_U(unit,
  14809                                   "Cold boot failed"
  14810                                   "(rv = %d)\n"),
  14811                                   rv));
  14812             return rv;
  14813         }
  14814     }
  14815 
  14816     return BCM_E_NONE;
  14817 }
  14818 
  14819 /*
  14820  * Function:
  14821  *     bcmi_esw_tsn_control_set
  14822  * Description:
  14823  *     Internal function for configure device-based operation modes.
  14824  * Parameters:
  14825  *     unit - (IN) Unit number.
  14826  *     type - (IN) Control type of bcm_tsn_control_t.
  14827  *     arg  - (IN) argument to be set
  14828  * Returns:
  14829  *     BCM_E_XXX
  14830  */
  14831 STATIC int
  14832 bcmi_esw_tsn_control_set(int unit, bcm_tsn_control_t type, uint32 arg)
  14833 {
  14834     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  14835     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
  14836     const tsn_chip_ctrl_info_t *ctrl_info = NULL;
  14837     int rv;
  14838 
  14839     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  14840     dev_info = bk_info->tsn_dev_info;
  14841 
  14842     ctrl_info = dev_info->tsn_chip_ctrl_info;
  14843     if ((ctrl_info != NULL) &&
  14844         (ctrl_info->tsn_chip_ctrl_set != NULL)) {
  14845         rv = ctrl_info->tsn_chip_ctrl_set(unit, type, arg);
  14846         if (BCM_SUCCESS(rv)) {
  14847             bcmi_esw_tsn_evt_ageout_config(unit, type, arg);
  14848         }
  14849         return rv;
  14850     }
  14851 
  14852     return BCM_E_UNAVAIL;
  14853 }
  14854 
  14855 /*
  14856  * Function:
  14857  *     bcmi_esw_tsn_control_get
  14858  * Description:
  14859  *     Internal function for get the configure of device-based operation modes.
  14860  * Parameters:
  14861  *     unit - (IN) Unit number.
  14862  *     type - (IN) Control type of bcm_tsn_control_t.
  14863  *     arg  - (OUT) argument got
  14864  * Returns:
  14865  *     BCM_E_XXX
  14866  */
  14867 STATIC int
  14868 bcmi_esw_tsn_control_get(int unit, bcm_tsn_control_t type, uint32 *arg)
  14869 {
  14870     bcmi_esw_tsn_bk_info_t *bk_info = NULL;
  14871     const bcmi_esw_tsn_dev_info_t *dev_info = NULL;
  14872     const tsn_chip_ctrl_info_t *ctrl_info = NULL;
  14873 
  14874     BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info));
  14875     dev_info = bk_info->tsn_dev_info;
  14876 
  14877     ctrl_info = dev_info->tsn_chip_ctrl_info;
  14878     if ((ctrl_info != NULL) &&
  14879         (ctrl_info->tsn_chip_ctrl_get != NULL)) {
  14880         return ctrl_info->tsn_chip_ctrl_get(unit, type, arg);
  14881     }
  14882 
  14883     return BCM_E_UNAVAIL;
  14884 }
  14885 
  14886 #endif /* BCM_TSN_SUPPORT */
  14887 
  14888 /*
  14889  * Function:
  14890  *     bcm_esw_tsn_init
  14891  * Purpose:
  14892  *     Initialize the TSN module.
  14893  * Parameters:
  14894  *     unit - (IN) unit number
  14895  * Returns:
  14896  *     BCM_E_XXX
  14897  */
  14898 int
  14899 bcm_esw_tsn_init(int unit)
  14900 {
  14901 #if defined(BCM_TSN_SUPPORT)
  14902     /* initialize TSN info */
  14903     BCM_IF_ERROR_RETURN(bcmi_esw_tsn_init(unit));
  14904 
  14905     return BCM_E_NONE;
  14906 #else /* BCM_TSN_SUPPORT */
  14907     return BCM_E_UNAVAIL;
  14908 #endif /* BCM_TSN_SUPPORT */
  14909 }
  14910 
  14911 /*
  14912  * Function:
  14913  *     bcm_esw_tsn_detach
  14914  * Purpose:
  14915  *     Clear the resource of the TSN module.
  14916  * Parameters:
  14917  *     unit - (IN) unit number
  14918  * Returns:
  14919  *     BCM_E_XXX
  14920  */
  14921 int
  14922 bcm_esw_tsn_detach(int unit)
  14923 {
  14924 #if defined(BCM_TSN_SUPPORT)
  14925     BCM_IF_ERROR_RETURN(bcmi_esw_tsn_detach(unit));
  14926 
  14927     return BCM_E_NONE;
  14928 #else /* BCM_TSN_SUPPORT */
  14929     return BCM_E_UNAVAIL;
  14930 #endif /* BCM_TSN_SUPPORT */
  14931 }
  14932 
  14933 #if defined(BCM_WARM_BOOT_SUPPORT)
  14934 /*
  14935  * Function:
  14936  *     bcm_esw_tsn_sync
  14937  * Purpose:
  14938  *   Store bookkeeping information for
  14939  *   Warmboot recovery.
  14940  * Parameters:
  14941  *     unit - (IN) unit number
  14942  * Returns:
  14943  *     BCM_E_XXX
  14944  */
  14945 int
  14946 bcm_esw_tsn_sync(int unit)
  14947 {
  14948 #if defined(BCM_TSN_SUPPORT)
  14949     /* Store bookkeeping information */
  14950     BCM_IF_ERROR_RETURN(bcmi_esw_tsn_sync(unit));
  14951 
  14952     return BCM_E_NONE;
  14953 #else /* BCM_TSN_SUPPORT */
  14954     return BCM_E_UNAVAIL;
  14955 #endif /* BCM_TSN_SUPPORT */
  14956 }
  14957 #endif /* BCM_WARM_BOOT_SUPPORT */
  14958 
  14959 /*
  14960  * Function:
  14961  *     bcm_esw_tsn_sr_port_config_set
  14962  * Purpose:
  14963  *     Set SR configuration on a port
  14964  * Parameters:
  14965  *     unit             - (IN) unit number
  14966  *     port             - (IN) port to configure
  14967  *     config           - (IN) port SR configuration
  14968  * Returns:
  14969  *     BCM_E_XXX
  14970  * Notes:
  14971  */
  14972 int
  14973 bcm_esw_tsn_sr_port_config_set(
  14974     int unit,
  14975     bcm_gport_t port,
  14976     bcm_tsn_sr_port_config_t *config)
  14977 {
  14978 #if defined(BCM_TSN_SR_SUPPORT)
  14979     if (soc_feature(unit, soc_feature_tsn_sr)) {
  14980         return bcmi_esw_tsn_sr_port_config_set(unit, port, config);
  14981     }
  14982 #endif /* BCM_TSN_SR_SUPPORT */
  14983     return BCM_E_UNAVAIL;
  14984 }
  14985 
  14986 /*
  14987  * Function:
  14988  *     bcm_esw_tsn_sr_port_config_get
  14989  * Purpose:
  14990  *     Get SR configuration from a port
  14991  * Parameters:
  14992  *     unit             - (IN) unit number
  14993  *     port             - (IN) port
  14994  *     config           - (OUT) port SR configuration
  14995  * Returns:
  14996  *     BCM_E_XXX
  14997  * Notes:
  14998  */
  14999 int
  15000 bcm_esw_tsn_sr_port_config_get(
  15001     int unit,
  15002     bcm_gport_t port,
  15003     bcm_tsn_sr_port_config_t *config)
  15004 {
  15005 #if defined(BCM_TSN_SR_SUPPORT)
  15006     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15007         return bcmi_esw_tsn_sr_port_config_get(unit, port, config);
  15008     }
  15009 #endif /* BCM_TSN_SR_SUPPORT */
  15010     return BCM_E_UNAVAIL;
  15011 }
  15012 
  15013 /*
  15014  * Function:
  15015  *      bcm_esw_tsn_pri_map_create
  15016  * Purpose:
  15017  *      Add a priority map config to hardware.
  15018  * Parameters:
  15019  *      unit - (IN) Unit number
  15020  *      config - (IN) Priority Map configuration
  15021  *      map_id - (OUT) Map ID
  15022  * Returns:
  15023  *      BCM_E_xxx
  15024  */
  15025 int
  15026 bcm_esw_tsn_pri_map_create(
  15027     int unit,
  15028     bcm_tsn_pri_map_config_t *config,
  15029     bcm_tsn_pri_map_t *map_id)
  15030 {
  15031 #if defined(BCM_TSN_SUPPORT)
  15032     if (soc_feature(unit, soc_feature_tsn)) {
  15033         return bcmi_esw_tsn_pri_map_create(unit, config, map_id);
  15034     }
  15035 #endif /* BCM_TSN_SUPPORT */
  15036     return BCM_E_UNAVAIL;
  15037 }
  15038 
  15039 /*
  15040  * Function:
  15041  *      bcm_esw_tsn_pri_map_set
  15042  * Purpose:
  15043  *      Set priority map config with the given map_id.
  15044  * Parameters:
  15045  *      unit - (IN) Unit number
  15046  *      map_id - (IN) Map ID
  15047  *      config - (IN) Priority Map configuration
  15048  * Returns:
  15049  *      BCM_E_xxx
  15050  */
  15051 int
  15052 bcm_esw_tsn_pri_map_set(
  15053     int unit,
  15054     bcm_tsn_pri_map_t map_id,
  15055     bcm_tsn_pri_map_config_t *config)
  15056 {
  15057 #if defined(BCM_TSN_SUPPORT)
  15058     if (soc_feature(unit, soc_feature_tsn)) {
  15059         return bcmi_esw_tsn_pri_map_set(unit, map_id, config);
  15060     }
  15061 #endif /* BCM_TSN_SUPPORT */
  15062     return BCM_E_UNAVAIL;
  15063 }
  15064 
  15065 /*
  15066  * Function:
  15067  *      bcm_esw_tsn_pri_map_get
  15068  * Purpose:
  15069  *      Get the priority map config with the given map_id.
  15070  * Parameters:
  15071  *      unit - (IN) Unit number
  15072  *      map_id - (IN) Map ID
  15073  *      config - (OUT) Priority Map configuration
  15074  * Returns:
  15075  *      BCM_E_xxx
  15076  */
  15077 int
  15078 bcm_esw_tsn_pri_map_get(
  15079     int unit,
  15080     bcm_tsn_pri_map_t map_id,
  15081     bcm_tsn_pri_map_config_t *config)
  15082 {
  15083 #if defined(BCM_TSN_SUPPORT)
  15084     if (soc_feature(unit, soc_feature_tsn)) {
  15085         return bcmi_esw_tsn_pri_map_get(unit, map_id, config);
  15086     }
  15087 #endif /* BCM_TSN_SUPPORT */
  15088     return BCM_E_UNAVAIL;
  15089 
  15090 }
  15091 
  15092 /*
  15093  * Function:
  15094  *      bcm_esw_tsn_pri_map_destroy
  15095  * Purpose:
  15096  *      Free the resource of map_id
  15097  * Parameters:
  15098  *      unit - (IN) Unit number
  15099  *      map_id - (IN) Priority Map ID
  15100  * Returns:
  15101  *      BCM_E_xxx
  15102  */
  15103 int
  15104 bcm_esw_tsn_pri_map_destroy(
  15105     int unit,
  15106     bcm_tsn_pri_map_t map_id)
  15107 {
  15108 #if defined(BCM_TSN_SUPPORT)
  15109     if (soc_feature(unit, soc_feature_tsn)) {
  15110         return bcmi_esw_tsn_pri_map_destroy(unit, map_id);
  15111     }
  15112 #endif /* BCM_TSN_SUPPORT */
  15113     return BCM_E_UNAVAIL;
  15114 }
  15115 
  15116 /*
  15117  * Function:
  15118  *      bcm_esw_tsn_pri_map_traverse
  15119  * Purpose:
  15120  *      Traverse the priority map config information.
  15121  * Parameters:
  15122  *      unit - (IN) Unit number
  15123  *      cb - (IN) Traverse call back function
  15124  *      user_data - (IN) User data
  15125  * Returns:
  15126  *      BCM_E_xxx
  15127  */
  15128 int
  15129 bcm_esw_tsn_pri_map_traverse(
  15130     int unit,
  15131     bcm_tsn_pri_map_traverse_cb cb,
  15132     void *user_data)
  15133 {
  15134 #if defined(BCM_TSN_SUPPORT)
  15135     if (soc_feature(unit, soc_feature_tsn)) {
  15136         return bcmi_esw_tsn_pri_map_traverse(unit, cb, user_data);
  15137     }
  15138 #endif /* BCM_TSN_SUPPORT */
  15139     return BCM_E_UNAVAIL;
  15140 }
  15141 
  15142 /*
  15143  * Function:
  15144  *     bcm_esw_tsn_sr_tx_flowset_create
  15145  * Purpose:
  15146  *     Create an SR TX flowset.
  15147  * Parameters:
  15148  *     unit             - (IN) unit number
  15149  *     pri_map          - (IN) TSN priority map ID
  15150  *     def_cfg          - (IN) default flow configuration
  15151  *     flowset          - (OUT) flowset ID
  15152  * Returns:
  15153  *     BCM_E_XXX
  15154  * Notes:
  15155  */
  15156 int
  15157 bcm_esw_tsn_sr_tx_flowset_create(
  15158     int unit,
  15159     bcm_tsn_pri_map_t pri_map,
  15160     bcm_tsn_sr_tx_flow_config_t *def_cfg,
  15161     bcm_tsn_sr_flowset_t *flowset)
  15162 {
  15163 #if defined(BCM_TSN_SR_SUPPORT)
  15164     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15165         return
  15166             bcmi_esw_tsn_sr_tx_flowset_create(unit, pri_map, def_cfg, flowset);
  15167     }
  15168 #endif /* BCM_TSN_SR_SUPPORT */
  15169     return BCM_E_UNAVAIL;
  15170 }
  15171 
  15172 /*
  15173  * Function:
  15174  *     bcm_esw_tsn_sr_tx_flowset_config_get
  15175  * Purpose:
  15176  *     Get default configuration for the specified SR flowset
  15177  * Parameters:
  15178  *     unit             - (IN) unit number
  15179  *     flowset          - (IN) flowset ID
  15180  *     pri_map          - (OUT) TSN priority map ID
  15181  *     default_config   - (OUT) default flow configuration
  15182  * Returns:
  15183  *     BCM_E_XXX
  15184  * Notes:
  15185  *     If it's called with a RX flowset, BCM_E_BADID is returned
  15186  */
  15187 int
  15188 bcm_esw_tsn_sr_tx_flowset_config_get(
  15189     int unit,
  15190     bcm_tsn_sr_flowset_t flowset,
  15191     bcm_tsn_pri_map_t *pri_map,
  15192     bcm_tsn_sr_tx_flow_config_t *default_config)
  15193 {
  15194 #if defined(BCM_TSN_SR_SUPPORT)
  15195     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15196         return bcmi_esw_tsn_sr_tx_flowset_config_get(
  15197                    unit, flowset, pri_map, default_config);
  15198     }
  15199 #endif /* BCM_TSN_SR_SUPPORT */
  15200     return BCM_E_UNAVAIL;
  15201 }
  15202 
  15203 /*
  15204  * Function:
  15205  *     bcm_esw_tsn_sr_rx_flowset_create
  15206  * Purpose:
  15207  *     Create an SR RX flowset.
  15208  * Parameters:
  15209  *     unit             - (IN) unit number
  15210  *     pri_map          - (IN) TSN priority map ID
  15211  *     def_cfg          - (IN) default flow configuration
  15212  *     flowset          - (OUT) flowset ID
  15213  * Returns:
  15214  *     BCM_E_XXX
  15215  * Notes:
  15216  */
  15217 int
  15218 bcm_esw_tsn_sr_rx_flowset_create(
  15219     int unit,
  15220     bcm_tsn_pri_map_t pri_map,
  15221     bcm_tsn_sr_rx_flow_config_t *def_cfg,
  15222     bcm_tsn_sr_flowset_t *flowset)
  15223 {
  15224 #if defined(BCM_TSN_SR_SUPPORT)
  15225     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15226         return
  15227             bcmi_esw_tsn_sr_rx_flowset_create(unit, pri_map, def_cfg, flowset);
  15228     }
  15229 #endif /* BCM_TSN_SR_SUPPORT */
  15230     return BCM_E_UNAVAIL;
  15231 }
  15232 
  15233 /*
  15234  * Function:
  15235  *     bcm_esw_tsn_sr_rx_flowset_config_get
  15236  * Purpose:
  15237  *     Get default configuration for the specified SR flowset
  15238  * Parameters:
  15239  *     unit             - (IN) unit number
  15240  *     flowset          - (IN) flowset ID
  15241  *     pri_map          - (OUT) TSN priority map ID
  15242  *     default_config   - (OUT) default flow configuration
  15243  * Returns:
  15244  *     BCM_E_XXX
  15245  * Notes:
  15246  *     If it's called with a TX flowset, BCM_E_BADID is returned
  15247  */
  15248 int
  15249 bcm_esw_tsn_sr_rx_flowset_config_get(
  15250     int unit,
  15251     bcm_tsn_sr_flowset_t flowset,
  15252     bcm_tsn_pri_map_t *pri_map,
  15253     bcm_tsn_sr_rx_flow_config_t *default_config)
  15254 {
  15255 #if defined(BCM_TSN_SR_SUPPORT)
  15256     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15257         return bcmi_esw_tsn_sr_rx_flowset_config_get(
  15258                    unit, flowset, pri_map, default_config);
  15259     }
  15260 #endif /* BCM_TSN_SR_SUPPORT */
  15261     return BCM_E_UNAVAIL;
  15262 }
  15263 
  15264 /*
  15265  * Function:
  15266  *     bcm_esw_tsn_sr_flowset_status_get
  15267  * Purpose:
  15268  *     Get current status of specified SR flowset
  15269  * Parameters:
  15270  *     unit             - (IN) unit number
  15271  *     flowset          - (IN) flowset ID
  15272  *     status           - (OUT) status structure
  15273  * Returns:
  15274  *     BCM_E_XXX
  15275  * Notes:
  15276  */
  15277 int
  15278 bcm_esw_tsn_sr_flowset_status_get(
  15279     int unit,
  15280     bcm_tsn_sr_flowset_t flowset,
  15281     bcm_tsn_sr_flowset_status_t *status)
  15282 {
  15283 #if defined(BCM_TSN_SR_SUPPORT)
  15284     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15285         return bcmi_esw_tsn_sr_flowset_status_get(unit, flowset, status);
  15286     }
  15287 #endif /* BCM_TSN_SR_SUPPORT */
  15288     return BCM_E_UNAVAIL;
  15289 }
  15290 
  15291 /*
  15292  * Function:
  15293  *     bcm_esw_tsn_sr_flowset_traverse
  15294  * Purpose:
  15295  *     Traverse all created SR flowsets
  15296  * Parameters:
  15297  *     unit             - (IN) unit number
  15298  *     is_rx            - (IN) 1 for RX flowsets; 0 for TX flowsets
  15299  *     cb               - (IN) callback function
  15300  *     user_data        - (IN) user data supplied to the callback function
  15301  * Returns:
  15302  *     BCM_E_XXX
  15303  * Notes:
  15304  */
  15305 int
  15306 bcm_esw_tsn_sr_flowset_traverse(
  15307     int unit,
  15308     int is_rx,
  15309     bcm_tsn_sr_flowset_traverse_cb cb,
  15310     void *user_data)
  15311 {
  15312 #if defined(BCM_TSN_SR_SUPPORT)
  15313     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15314         return bcmi_esw_tsn_sr_flowset_traverse(unit, is_rx, cb, user_data);
  15315     }
  15316 #endif /* BCM_TSN_SR_SUPPORT */
  15317     return BCM_E_UNAVAIL;
  15318 }
  15319 
  15320 /*
  15321  * Function:
  15322  *     bcm_esw_tsn_sr_flowset_destroy
  15323  * Purpose:
  15324  *     Destroy an SR (TX or RX) flowset.
  15325  * Parameters:
  15326  *     unit             - (IN) unit number
  15327  *     flowset          - (IN) flowset ID
  15328  * Returns:
  15329  *     BCM_E_XXX
  15330  * Notes:
  15331  */
  15332 int
  15333 bcm_esw_tsn_sr_flowset_destroy(int unit, bcm_tsn_sr_flowset_t flowset)
  15334 {
  15335 #if defined(BCM_TSN_SR_SUPPORT)
  15336     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15337         return bcmi_esw_tsn_sr_flowset_destroy(unit, flowset);
  15338     }
  15339 #endif /* BCM_TSN_SR_SUPPORT */
  15340     return BCM_E_UNAVAIL;
  15341 }
  15342 
  15343 /*
  15344  * Function:
  15345  *     bcm_esw_tsn_sr_flowset_flow_get
  15346  * Purpose:
  15347  *     Retrieve an individual SR flow based on the flow offset from a flow set.
  15348  * Parameters:
  15349  *     unit             - (IN) unit number
  15350  *     flowset          - (IN) flowset ID
  15351  *     index            - (IN) index of the flow
  15352  *     flow_id          - (OUT) flow ID
  15353  * Returns:
  15354  *     BCM_E_XXX
  15355  * Notes:
  15356  */
  15357 int
  15358 bcm_esw_tsn_sr_flowset_flow_get(
  15359     int unit,
  15360     bcm_tsn_sr_flowset_t flowset,
  15361     int index,
  15362     bcm_tsn_sr_flow_t *flow_id)
  15363 {
  15364 #if defined(BCM_TSN_SR_SUPPORT)
  15365     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15366         return bcmi_esw_tsn_sr_flowset_flow_get(unit, flowset, index, flow_id);
  15367     }
  15368 #endif /* BCM_TSN_SR_SUPPORT */
  15369     return BCM_E_UNAVAIL;
  15370 }
  15371 
  15372 /*
  15373  * Function:
  15374  *     bcm_esw_tsn_sr_tx_flow_config_get
  15375  * Purpose:
  15376  *     Get configuration for the specified SR flow
  15377  * Parameters:
  15378  *     unit             - (IN) unit number
  15379  *     flow_id          - (IN) flow ID
  15380  *     config           - (OUT) flow configuration
  15381  * Returns:
  15382  *     BCM_E_XXX
  15383  * Notes:
  15384  *     If it's called with a RX flow, BCM_E_BADID is returned
  15385  */
  15386 int
  15387 bcm_esw_tsn_sr_tx_flow_config_get(
  15388     int unit,
  15389     bcm_tsn_sr_flow_t flow_id,
  15390     bcm_tsn_sr_tx_flow_config_t *config)
  15391 {
  15392 #if defined(BCM_TSN_SR_SUPPORT)
  15393     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15394         return bcmi_esw_tsn_sr_tx_flow_config_get(unit, flow_id, config);
  15395     }
  15396 #endif /* BCM_TSN_SR_SUPPORT */
  15397     return BCM_E_UNAVAIL;
  15398 }
  15399 
  15400 /*
  15401  * Function:
  15402  *     bcm_esw_tsn_sr_tx_flow_config_set
  15403  * Purpose:
  15404  *     Set configuration for the specified SR flow
  15405  * Parameters:
  15406  *     unit             - (IN) unit number
  15407  *     flow_id          - (IN) flow ID
  15408  *     config           - (IN) flow configuration
  15409  * Returns:
  15410  *     BCM_E_XXX
  15411  * Notes:
  15412  *     If it's called with a RX flow, BCM_E_BADID is returned
  15413  */
  15414 int
  15415 bcm_esw_tsn_sr_tx_flow_config_set(
  15416     int unit,
  15417     bcm_tsn_sr_flow_t flow_id,
  15418     bcm_tsn_sr_tx_flow_config_t *config)
  15419 {
  15420 #if defined(BCM_TSN_SR_SUPPORT)
  15421     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15422         return bcmi_esw_tsn_sr_tx_flow_config_set(unit, flow_id, config);
  15423     }
  15424 #endif /* BCM_TSN_SR_SUPPORT */
  15425     return BCM_E_UNAVAIL;
  15426 }
  15427 
  15428 /*
  15429  * Function:
  15430  *     bcm_esw_tsn_sr_tx_flow_status_get
  15431  * Purpose:
  15432  *     Get status for the specified flow
  15433  * Parameters:
  15434  *     unit             - (IN) unit number
  15435  *     flow_id          - (IN) flow ID
  15436  *     status           - (OUT) flow status
  15437  * Returns:
  15438  *     BCM_E_XXX
  15439  * Notes:
  15440  *     If it's called with a RX flow, BCM_E_BADID is returned
  15441  */
  15442 int
  15443 bcm_esw_tsn_sr_tx_flow_status_get(
  15444     int unit,
  15445     bcm_tsn_sr_flow_t flow_id,
  15446     bcm_tsn_sr_tx_flow_status_t *status)
  15447 {
  15448 #if defined(BCM_TSN_SR_SUPPORT)
  15449     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15450         return bcmi_esw_tsn_sr_tx_flow_status_get(unit, flow_id, status);
  15451     }
  15452 #endif /* BCM_TSN_SR_SUPPORT */
  15453     return BCM_E_UNAVAIL;
  15454 }
  15455 
  15456 /*
  15457  * Function:
  15458  *     bcm_esw_tsn_sr_rx_flow_config_get
  15459  * Purpose:
  15460  *     Get configuration for the specified SR flow
  15461  * Parameters:
  15462  *     unit             - (IN) unit number
  15463  *     flow_id          - (IN) flow ID
  15464  *     config           - (OUT) flow configuration
  15465  * Returns:
  15466  *     BCM_E_XXX
  15467  * Notes:
  15468  *     If it's called with a TX flow, BCM_E_BADID is returned
  15469  */
  15470 int
  15471 bcm_esw_tsn_sr_rx_flow_config_get(
  15472     int unit,
  15473     bcm_tsn_sr_flow_t flow_id,
  15474     bcm_tsn_sr_rx_flow_config_t *config)
  15475 {
  15476 #if defined(BCM_TSN_SR_SUPPORT)
  15477     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15478         return bcmi_esw_tsn_sr_rx_flow_config_get(unit, flow_id, config);
  15479     }
  15480 #endif /* BCM_TSN_SR_SUPPORT */
  15481     return BCM_E_UNAVAIL;
  15482 }
  15483 
  15484 /*
  15485  * Function:
  15486  *     bcm_esw_tsn_sr_rx_flow_config_set
  15487  * Purpose:
  15488  *     Set configuration for the specified SR flow
  15489  * Parameters:
  15490  *     unit             - (IN) unit number
  15491  *     flow_id          - (IN) flow ID
  15492  *     config           - (IN) flow configuration
  15493  * Returns:
  15494  *     BCM_E_XXX
  15495  * Notes:
  15496  *     If it's called with a TX flow, BCM_E_BADID is returned
  15497  */
  15498 int
  15499 bcm_esw_tsn_sr_rx_flow_config_set(
  15500     int unit,
  15501     bcm_tsn_sr_flow_t flow_id,
  15502     bcm_tsn_sr_rx_flow_config_t *config)
  15503 {
  15504 #if defined(BCM_TSN_SR_SUPPORT)
  15505     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15506         return bcmi_esw_tsn_sr_rx_flow_config_set(unit, flow_id, config);
  15507     }
  15508 #endif /* BCM_TSN_SR_SUPPORT */
  15509     return BCM_E_UNAVAIL;
  15510 }
  15511 
  15512 /*
  15513  * Function:
  15514  *     bcm_esw_tsn_sr_rx_flow_status_get
  15515  * Purpose:
  15516  *     Get status for the specified flow
  15517  * Parameters:
  15518  *     unit             - (IN) unit number
  15519  *     flow_id          - (IN) flow ID
  15520  *     status           - (OUT) flow status
  15521  * Returns:
  15522  *     BCM_E_XXX
  15523  * Notes:
  15524  *     If it's called with a TX flow, BCM_E_BADID is returned
  15525  */
  15526 int
  15527 bcm_esw_tsn_sr_rx_flow_status_get(
  15528     int unit,
  15529     bcm_tsn_sr_flow_t flow_id,
  15530     bcm_tsn_sr_rx_flow_status_t *status)
  15531 {
  15532 #if defined(BCM_TSN_SR_SUPPORT)
  15533     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15534         return bcmi_esw_tsn_sr_rx_flow_status_get(unit, flow_id, status);
  15535     }
  15536 #endif /* BCM_TSN_SR_SUPPORT */
  15537     return BCM_E_UNAVAIL;
  15538 }
  15539 
  15540 /*
  15541  * Function:
  15542  *     bcm_esw_tsn_sr_rx_flow_reset
  15543  * Purpose:
  15544  *     Reset SR RX flow status
  15545  * Parameters:
  15546  *     unit             - (IN) unit number
  15547  *     flags            - (IN) flags to select items to reset
  15548  *     flow_id          - (IN) flow ID
  15549  * Returns:
  15550  *     BCM_E_XXX
  15551  * Notes:
  15552  *     If it's called with a TX flow, BCM_E_BADID is returned
  15553  */
  15554 int
  15555 bcm_esw_tsn_sr_rx_flow_reset(int unit, uint32 flags, bcm_tsn_sr_flow_t flow_id)
  15556 {
  15557 #if defined(BCM_TSN_SR_SUPPORT)
  15558     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15559         return bcmi_esw_tsn_sr_rx_flow_reset(unit, flags, flow_id);
  15560     }
  15561 #endif /* BCM_TSN_SR_SUPPORT */
  15562     return BCM_E_UNAVAIL;
  15563 }
  15564 
  15565 /*
  15566  * Function:
  15567  *     bcm_esw_tsn_sr_rx_flow_seqnum_history_set
  15568  * Purpose:
  15569  *     Set the sequence number history bits (one bit for one sequence number)
  15570  *     in the RX flow.
  15571  * Parameters:
  15572  *     unit             - (IN) unit number
  15573  *     flow_id          - (IN) flow ID
  15574  *     offset_in_bits   - (IN) Offset (in bits) in the seqnum history window
  15575  *     size_in_bits     - (IN) Size (in bits) to write
  15576  *     history_bits     - (IN) Bit buffer to write
  15577  * Returns:
  15578  *     BCM_E_XXX
  15579  * Notes:
  15580  *     If it's called with a TX flow, BCM_E_BADID is returned
  15581  */
  15582 int
  15583 bcm_esw_tsn_sr_rx_flow_seqnum_history_set(
  15584     int unit,
  15585     bcm_tsn_sr_flow_t flow_id,
  15586     int offset_in_bits,
  15587     int size_in_bits,
  15588     uint8 *history_bits)
  15589 {
  15590 #if defined(BCM_TSN_SR_SUPPORT)
  15591     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15592         return bcmi_esw_tsn_sr_rx_flow_seqnum_history_set(
  15593                 unit, flow_id, offset_in_bits, size_in_bits, history_bits);
  15594     }
  15595 #endif /* BCM_TSN_SR_SUPPORT */
  15596     return BCM_E_UNAVAIL;
  15597 }
  15598 
  15599 /*
  15600  * Function:
  15601  *     bcm_esw_tsn_sr_rx_flow_seqnum_history_get
  15602  * Purpose:
  15603  *     Get the sequence number history bits (one bit for one sequence number)
  15604  *     in the RX flow.
  15605  * Parameters:
  15606  *     unit             - (IN) unit number
  15607  *     flow_id          - (IN) flow ID
  15608  *     offset_in_bits   - (IN) Offset (in bits) in the seqnum history window
  15609  *     max_size_in_bits - (IN) Size (in bits) of the buffer
  15610  *     history_bits     - (OUT) Bit buffer to read
  15611  *     actual_size      - (OUT) Actual size (in bits) read to the buffer
  15612  * Returns:
  15613  *     BCM_E_XXX
  15614  * Notes:
  15615  *     If it's called with a TX flow, BCM_E_BADID is returned
  15616  */
  15617 int
  15618 bcm_esw_tsn_sr_rx_flow_seqnum_history_get(
  15619     int unit,
  15620     bcm_tsn_sr_flow_t flow_id,
  15621     int offset_in_bits,
  15622     int max_size_in_bits,
  15623     uint8 *history_bits,
  15624     int *actual_size)
  15625 {
  15626 #if defined(BCM_TSN_SR_SUPPORT)
  15627     if (soc_feature(unit, soc_feature_tsn_sr)) {
  15628         return bcmi_esw_tsn_sr_rx_flow_seqnum_history_get(
  15629             unit, flow_id, offset_in_bits, max_size_in_bits,
  15630             history_bits, actual_size);
  15631     }
  15632 #endif /* BCM_TSN_SR_SUPPORT */
  15633     return BCM_E_UNAVAIL;
  15634 }
  15635 
  15636 /*
  15637  * Function:
  15638  *     bcm_esw_tsn_flowset_create
  15639  * Purpose:
  15640  *     Create a TSN flowset.
  15641  * Parameters:
  15642  *     unit             - (IN) unit number
  15643  *     pri_map          - (IN) TSN priority map ID
  15644  *     def_cfg          - (IN) default flow configuration
  15645  *     flowset          - (OUT) flowset ID
  15646  * Returns:
  15647  *     BCM_E_XXX
  15648  * Notes:
  15649  */
  15650 int
  15651 bcm_esw_tsn_flowset_create(
  15652     int unit,
  15653     bcm_tsn_pri_map_t pri_map,
  15654     bcm_tsn_flow_config_t *def_cfg,
  15655     bcm_tsn_flowset_t *flowset)
  15656 {
  15657 #if defined(BCM_TSN_SUPPORT)
  15658     if (soc_feature(unit, soc_feature_tsn)) {
  15659         return bcmi_esw_tsn_flowset_create(unit, pri_map, def_cfg, flowset);
  15660     }
  15661 #endif /* BCM_TSN_SUPPORT */
  15662     return BCM_E_UNAVAIL;
  15663 }
  15664 
  15665 /*
  15666  * Function:
  15667  *     bcm_esw_tsn_flowset_status_get
  15668  * Purpose:
  15669  *     Get current status of specified TSN flowset
  15670  * Parameters:
  15671  *     unit             - (IN) unit number
  15672  *     flowset          - (IN) flowset ID
  15673  *     status           - (OUT) status structure
  15674  * Returns:
  15675  *     BCM_E_XXX
  15676  * Notes:
  15677  */
  15678 int
  15679 bcm_esw_tsn_flowset_status_get(
  15680     int unit,
  15681     bcm_tsn_flowset_t flowset,
  15682     bcm_tsn_flowset_status_t *status)
  15683 {
  15684 #if defined(BCM_TSN_SUPPORT)
  15685     if (soc_feature(unit, soc_feature_tsn)) {
  15686         return bcmi_esw_tsn_flowset_status_get(unit, flowset, status);
  15687     }
  15688 #endif /* BCM_TSN_SUPPORT */
  15689     return BCM_E_UNAVAIL;
  15690 }
  15691 
  15692 /*
  15693  * Function:
  15694  *     bcm_esw_tsn_flowset_flow_get
  15695  * Purpose:
  15696  *     Retrieve an individual TSN flow based on the flow offset from a flow set.
  15697  * Parameters:
  15698  *     unit             - (IN) unit number
  15699  *     flowset          - (IN) flowset ID
  15700  *     index            - (IN) index of the flow
  15701  *     flow_id          - (OUT) flow ID
  15702  * Returns:
  15703  *     BCM_E_XXX
  15704  * Notes:
  15705  */
  15706 int
  15707 bcm_esw_tsn_flowset_flow_get(
  15708     int unit,
  15709     bcm_tsn_flowset_t flowset,
  15710     int index,
  15711     bcm_tsn_flow_t *flow_id)
  15712 {
  15713 #if defined(BCM_TSN_SUPPORT)
  15714     if (soc_feature(unit, soc_feature_tsn)) {
  15715         return bcmi_esw_tsn_flowset_flow_get(unit, flowset, index, flow_id);
  15716     }
  15717 #endif /* BCM_TSN_SUPPORT */
  15718     return BCM_E_UNAVAIL;
  15719 }
  15720 
  15721 /*
  15722  * Function:
  15723  *     bcm_esw_tsn_flowset_config_get
  15724  * Purpose:
  15725  *     Get default configuration for the specified TSN flowset
  15726  * Parameters:
  15727  *     unit             - (IN) unit number
  15728  *     flowset          - (IN) flowset ID
  15729  *     pri_map          - (OUT) TSN priority map ID
  15730  *     default_config   - (OUT) default flow configuration
  15731  * Returns:
  15732  *     BCM_E_XXX
  15733  * Notes:
  15734  */
  15735 int
  15736 bcm_esw_tsn_flowset_config_get(
  15737     int unit,
  15738     bcm_tsn_flowset_t flowset,
  15739     bcm_tsn_pri_map_t *pri_map,
  15740     bcm_tsn_flow_config_t *default_config)
  15741 {
  15742 #if defined(BCM_TSN_SUPPORT)
  15743     if (soc_feature(unit, soc_feature_tsn)) {
  15744         return bcmi_esw_tsn_flowset_config_get(unit, flowset,
  15745                                                pri_map, default_config);
  15746     }
  15747 #endif /* BCM_TSN_SUPPORT */
  15748     return BCM_E_UNAVAIL;
  15749 }
  15750 
  15751 /*
  15752  * Function:
  15753  *     bcm_esw_tsn_flowset_traverse
  15754  * Purpose:
  15755  *     Traverse all created TSN flowsets
  15756  * Parameters:
  15757  *     unit             - (IN) unit number
  15758  *     cb               - (IN) callback function
  15759  *     user_data        - (IN) user data supplied to the callback function
  15760  * Returns:
  15761  *     BCM_E_XXX
  15762  * Notes:
  15763  */
  15764 int
  15765 bcm_esw_tsn_flowset_traverse(
  15766     int unit,
  15767     bcm_tsn_flowset_traverse_cb cb,
  15768     void *user_data)
  15769 {
  15770 #if defined(BCM_TSN_SUPPORT)
  15771     if (soc_feature(unit, soc_feature_tsn)) {
  15772         return bcmi_esw_tsn_flowset_traverse(unit, cb, user_data);
  15773     }
  15774 #endif /* BCM_TSN_SUPPORT */
  15775     return BCM_E_UNAVAIL;
  15776 
  15777 }
  15778 
  15779 /*
  15780  * Function:
  15781  *     bcm_esw_tsn_flowset_destroy
  15782  * Purpose:
  15783  *     Destroy a TSN flowset.
  15784  * Parameters:
  15785  *     unit             - (IN) unit number
  15786  *     flowset          - (IN) flowset ID
  15787  * Returns:
  15788  *     BCM_E_XXX
  15789  * Notes:
  15790  */
  15791 int
  15792 bcm_esw_tsn_flowset_destroy(int unit, bcm_tsn_flowset_t flowset)
  15793 {
  15794 #if defined(BCM_TSN_SUPPORT)
  15795     if (soc_feature(unit, soc_feature_tsn)) {
  15796         return bcmi_esw_tsn_flowset_destroy(unit, flowset);
  15797     }
  15798 #endif /* BCM_TSN_SUPPORT */
  15799     return BCM_E_UNAVAIL;
  15800 }
  15801 
  15802 /*
  15803  * Function:
  15804  *     bcm_esw_tsn_flow_config_get
  15805  * Purpose:
  15806  *     Get configuration for the specified TSN flow
  15807  * Parameters:
  15808  *     unit             - (IN) unit number
  15809  *     flow_id          - (IN) flow ID
  15810  *     config           - (OUT) flow configuration
  15811  * Returns:
  15812  *     BCM_E_XXX
  15813  * Notes:
  15814  */
  15815 int
  15816 bcm_esw_tsn_flow_config_get(
  15817     int unit,
  15818     bcm_tsn_flow_t flow_id,
  15819     bcm_tsn_flow_config_t *config)
  15820 {
  15821 #if defined(BCM_TSN_SUPPORT)
  15822     if (soc_feature(unit, soc_feature_tsn)) {
  15823         return bcmi_esw_tsn_flow_config_get(unit, flow_id, config);
  15824     }
  15825 #endif /* BCM_TSN_SUPPORT */
  15826     return BCM_E_UNAVAIL;
  15827 }
  15828 
  15829 /*
  15830  * Function:
  15831  *     bcm_esw_tsn_flow_config_set
  15832  * Purpose:
  15833  *     Set configuration for the specified TSN flow
  15834  * Parameters:
  15835  *     unit             - (IN) unit number
  15836  *     flow_id          - (IN) flow ID
  15837  *     config           - (IN) flow configuration
  15838  * Returns:
  15839  *     BCM_E_XXX
  15840  * Notes:
  15841  */
  15842 int
  15843 bcm_esw_tsn_flow_config_set(
  15844     int unit,
  15845     bcm_tsn_flow_t flow_id,
  15846     bcm_tsn_flow_config_t *config)
  15847 {
  15848 #if defined(BCM_TSN_SUPPORT)
  15849     if (soc_feature(unit, soc_feature_tsn)) {
  15850         return bcmi_esw_tsn_flow_config_set(unit, flow_id, config);
  15851     }
  15852 #endif /* BCM_TSN_SUPPORT */
  15853     return BCM_E_UNAVAIL;
  15854 }
  15855 
  15856 /*
  15857  * Function:
  15858  *   bcm_esw_tsn_sr_auto_learn_group_create
  15859  * Purpose:
  15860  *   Add an Auto Learn config to hardware.
  15861  * Parameters:
  15862  *   unit     - (IN) Unit number
  15863  *   config   - (IN) Auto Learn Group configuration
  15864  *   group_id - (OUT) Group ID
  15865  * Returns:
  15866  *   BCM_E_xxx
  15867  */
  15868 int
  15869 bcm_esw_tsn_sr_auto_learn_group_create(
  15870     int unit,
  15871     bcm_tsn_sr_auto_learn_group_config_t *config,
  15872     int *group_id)
  15873 {
  15874 #if defined(BCM_TSN_SR_SUPPORT)
  15875     if (soc_feature(unit, soc_feature_tsn_sr) &&
  15876         soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
  15877         return bcmi_esw_tsn_sr_auto_learn_group_create(unit, config, group_id);
  15878     }
  15879 #endif /* BCM_TSN_SR_SUPPORT */
  15880     return BCM_E_UNAVAIL;
  15881 }
  15882 
  15883 /*
  15884  * Function:
  15885  *   bcm_esw_tsn_sr_auto_learn_group_get
  15886  * Purpose:
  15887  *   Get the Auto Learn config with the given group_id.
  15888  * Parameters:
  15889  *   unit     - (IN) Unit number
  15890  *   group_id - (IN) Group ID
  15891  *   config   - (OUT) Auto Learn Group configuration
  15892  * Returns:
  15893  *   BCM_E_xxx
  15894  */
  15895 int
  15896 bcm_esw_tsn_sr_auto_learn_group_get(
  15897     int unit,
  15898     int group_id,
  15899     bcm_tsn_sr_auto_learn_group_config_t *config)
  15900 {
  15901 #if defined(BCM_TSN_SR_SUPPORT)
  15902     if (soc_feature(unit, soc_feature_tsn_sr) &&
  15903         soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
  15904         return bcmi_esw_tsn_sr_auto_learn_group_get(unit, group_id, config);
  15905     }
  15906 #endif /* BCM_TSN_SR_SUPPORT */
  15907     return BCM_E_UNAVAIL;
  15908 }
  15909 
  15910 /*
  15911  * Function:
  15912  *   bcm_esw_tsn_sr_auto_learn_group_set
  15913  * Purpose:
  15914  *   Set Auto Learn config with the given group_id.
  15915  * Parameters:
  15916  *   unit     - (IN) Unit number
  15917  *   group_id - (IN) Group ID
  15918  *   config   - (IN) Auto Learn Group configuration
  15919  * Returns:
  15920  *   BCM_E_xxx
  15921  */
  15922 int
  15923 bcm_esw_tsn_sr_auto_learn_group_set(
  15924     int unit,
  15925     int group_id,
  15926     bcm_tsn_sr_auto_learn_group_config_t *config)
  15927 {
  15928 #if defined(BCM_TSN_SR_SUPPORT)
  15929     if (soc_feature(unit, soc_feature_tsn_sr) &&
  15930         soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
  15931         return bcmi_esw_tsn_sr_auto_learn_group_set(unit, group_id, config);
  15932     }
  15933 #endif /* BCM_TSN_SR_SUPPORT */
  15934     return BCM_E_UNAVAIL;
  15935 }
  15936 
  15937 /*
  15938  * Function:
  15939  *   bcm_esw_tsn_sr_auto_learn_group_destroy
  15940  * Purpose:
  15941  *   Destroy an Auto Learn config with the given group_id by removing it
  15942  *   from hardware and deleting the associated software state info.
  15943  * Parameters:
  15944  *   unit     - (IN) Unit number
  15945  *   group_id - (IN) Group ID
  15946  * Returns:
  15947  *   BCM_E_xxx
  15948  */
  15949 int
  15950 bcm_esw_tsn_sr_auto_learn_group_destroy(
  15951     int unit,
  15952     int group_id)
  15953 {
  15954 #if defined(BCM_TSN_SR_SUPPORT)
  15955     if (soc_feature(unit, soc_feature_tsn_sr) &&
  15956         soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
  15957         return bcmi_esw_tsn_sr_auto_learn_group_destroy(unit, group_id);
  15958     }
  15959 #endif /* BCM_TSN_SR_SUPPORT */
  15960     return BCM_E_UNAVAIL;
  15961 }
  15962 
  15963 /*
  15964  * Function:
  15965  *   bcm_esw_tsn_sr_auto_learn_group_traverse
  15966  * Purpose:
  15967  *   Traverse the Auto Learn config information.
  15968  * Parameters:
  15969  *   unit      - (IN) Unit number
  15970  *   cb        - (IN) Traverse call back function
  15971  *   user_data - (IN) User data
  15972  * Returns:
  15973  *   BCM_E_xxx
  15974  */
  15975 int
  15976 bcm_esw_tsn_sr_auto_learn_group_traverse(
  15977     int unit,
  15978     bcm_tsn_sr_auto_learn_group_traverse_cb cb,
  15979     void *user_data)
  15980 {
  15981 #if defined(BCM_TSN_SR_SUPPORT)
  15982     if (soc_feature(unit, soc_feature_tsn_sr) &&
  15983         soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
  15984         return bcmi_esw_tsn_sr_auto_learn_group_traverse(unit, cb, user_data);
  15985     }
  15986 #endif /* BCM_TSN_SR_SUPPORT */
  15987     return BCM_E_UNAVAIL;
  15988 }
  15989 
  15990 /*
  15991  * Function:
  15992  *   bcm_esw_tsn_sr_auto_learn_enable
  15993  * Purpose:
  15994  *   Enable/disable SR flow auto learn subsystem
  15995  * Parameters:
  15996  *   unit   - (IN) Unit number
  15997  *   enable - (IN) Enable/Disable
  15998  *   config - (IN) Auto Learn configuration
  15999  * Returns:
  16000  *   BCM_E_xxx
  16001  */
  16002 int
  16003 bcm_esw_tsn_sr_auto_learn_enable(
  16004     int unit,
  16005     int enable,
  16006     bcm_tsn_sr_auto_learn_config_t *config)
  16007 {
  16008 #if defined(BCM_TSN_SR_SUPPORT)
  16009     if (soc_feature(unit, soc_feature_tsn_sr) &&
  16010         soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
  16011         return bcmi_esw_tsn_sr_auto_learn_enable(unit, enable, config);
  16012     }
  16013 #endif /* BCM_TSN_SR_SUPPORT */
  16014     return BCM_E_UNAVAIL;
  16015 }
  16016 
  16017 /*
  16018  * Function:
  16019  *   bcm_esw_tsn_sr_auto_learn_enable_get
  16020  * Purpose:
  16021  *   Get enable/disable SR flow auto learn subsystem
  16022  * Parameters:
  16023  *   unit   - (IN) Unit number
  16024  *   enable - (OUT) Enable/disable
  16025  *   config - (OUT) Auto Learn configuration
  16026  * Returns:
  16027  *   BCM_E_xxx
  16028  */
  16029 int
  16030 bcm_esw_tsn_sr_auto_learn_enable_get(
  16031     int unit,
  16032     int *enabled,
  16033     bcm_tsn_sr_auto_learn_config_t *config)
  16034 {
  16035 #if defined(BCM_TSN_SR_SUPPORT)
  16036     if (soc_feature(unit, soc_feature_tsn_sr) &&
  16037         soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
  16038         return bcmi_esw_tsn_sr_auto_learn_enable_get(unit, enabled, config);
  16039     }
  16040 #endif /* BCM_TSN_SR_SUPPORT */
  16041     return BCM_E_UNAVAIL;
  16042 }
  16043 
  16044 /*
  16045  * Function:
  16046  *     bcm_esw_tsn_control_set
  16047  * Description:
  16048  *     Configure device operation modes for TSN.
  16049  * Parameters:
  16050  *     unit - (IN) Unit number.
  16051  *     type - (IN) Control type of bcm_tsn_control_t.
  16052  *     arg  - (IN) argument to be set
  16053  * Returns:
  16054  *     BCM_E_XXX
  16055  */
  16056 int
  16057 bcm_esw_tsn_control_set(int unit, bcm_tsn_control_t type, uint32 arg)
  16058 {
  16059 #if defined(BCM_TSN_SUPPORT)
  16060     if (soc_feature(unit, soc_feature_tsn)) {
  16061         return bcmi_esw_tsn_control_set(unit, type, arg);
  16062     }
  16063 #endif /* BCM_TSN_SUPPORT */
  16064     return BCM_E_UNAVAIL;
  16065 }
  16066 
  16067 /*
  16068  * Function:
  16069  *     bcm_esw_tsn_control_get
  16070  * Description:
  16071  *     Get the configure of device TSN operation modes.
  16072  * Parameters:
  16073  *     unit - (IN) Unit number.
  16074  *     type - (IN) Control type of bcm_tsn_control_t.
  16075  *     arg  - (OUT) argument got
  16076  * Returns:
  16077  *     BCM_E_XXX
  16078  */
  16079 int
  16080 bcm_esw_tsn_control_get(int unit, bcm_tsn_control_t type, uint32 *arg)
  16081 {
  16082 #if defined(BCM_TSN_SUPPORT)
  16083     if (soc_feature(unit, soc_feature_tsn)) {
  16084         return bcmi_esw_tsn_control_get(unit, type, arg);
  16085     }
  16086 #endif /* BCM_TSN_SUPPORT */
  16087     return BCM_E_UNAVAIL;
  16088 }
  16089 
  16090 /*
  16091  * Function:
  16092  *     bcm_esw_tsn_port_control_set
  16093  * Description:
  16094  *     Configure port operation modes for TSN.
  16095  * Parameters:
  16096  *     unit - (IN) Unit number.
  16097  *     port - (IN) Port number.
  16098  *     type - (IN) Control type of bcm_tsn_control_t.
  16099  *     arg  - (IN) argument to be set
  16100  * Returns:
  16101  *     BCM_E_XXX
  16102  */
  16103 int
  16104 bcm_esw_tsn_port_control_set(
  16105     int unit,
  16106     bcm_gport_t port,
  16107     bcm_tsn_control_t type,
  16108     uint32 arg)
  16109 {
  16110 #if defined(BCM_TSN_SUPPORT)
  16111     if (soc_feature(unit, soc_feature_tsn)) {
  16112         return bcmi_esw_tsn_port_control_set(unit, port, type, arg);
  16113     }
  16114 #endif /* BCM_TSN_SUPPORT */
  16115     return BCM_E_UNAVAIL;
  16116 }
  16117 
  16118 
  16119 /*
  16120  * Function:
  16121  *     bcm_esw_tsn_port_control_get
  16122  * Description:
  16123  *     Get the configure of port TSN operation modes.
  16124  * Parameters:
  16125  *     unit - (IN) Unit number.
  16126  *     port - (IN) Port number.
  16127  *     type - (IN) Control type of bcm_tsn_control_t.
  16128  *     arg  - (OUT) argument got
  16129  * Returns:
  16130  *     BCM_E_XXX
  16131  */
  16132  int bcm_esw_tsn_port_control_get(
  16133     int unit,
  16134     bcm_gport_t port,
  16135     bcm_tsn_control_t type,
  16136     uint32 *arg)
  16137 {
  16138 #if defined(BCM_TSN_SUPPORT)
  16139     if (soc_feature(unit, soc_feature_tsn)) {
  16140         return bcmi_esw_tsn_port_control_get(unit, port, type, arg);
  16141     }
  16142 #endif /* BCM_TSN_SUPPORT */
  16143     return BCM_E_UNAVAIL;
  16144 }
  16145 
  16146 /*
  16147  * Function:
  16148  *    bcm_esw_tsn_port_stat_set
  16149  * Description:
  16150  *    Set 64-bit counter value for specified TSN statistic type.
  16151  * Parameters:
  16152  *    unit - (IN) Unit number
  16153  *    port - (IN) port number
  16154  *    stat - (IN) TSN statistics type (see tsn.h)
  16155  *     val - (IN) 64-bit counter value.
  16156  * Returns:
  16157  *    BCM_E_NONE - Success.
  16158  *    BCM_E_PARAM - Illegal parameter.
  16159  *    BCM_E_BADID - Illegal port number.
  16160  *    BCM_E_INTERNAL - Chip access failure.
  16161  *    BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip.
  16162  * Notes:
  16163  */
  16164 int
  16165 bcm_esw_tsn_port_stat_set(
  16166     int unit,
  16167     bcm_gport_t port,
  16168     bcm_tsn_stat_t stat,
  16169     uint64 val)
  16170 {
  16171     int rv = BCM_E_UNAVAIL;
  16172 
  16173 #if defined(BCM_TSN_SUPPORT)
  16174     /* Write hardware and software accumulated counters */
  16175     if (soc_feature(unit, soc_feature_tsn)) {
  16176         rv = bcmi_esw_tsn_stat_portcnt_set(unit, port, stat, val);
  16177     }
  16178 #endif /* BCM_TSN_SUPPORT */
  16179 
  16180     return rv;
  16181 }
  16182 
  16183 /*
  16184  * Function:
  16185  *    bcm_esw_tsn_port_stat_set32
  16186  * Description:
  16187  *    Set lower 32-bit counter value for specified TSN statistic type.
  16188  * Parameters:
  16189  *    unit - (IN) Unit number
  16190  *    port - (IN) port number
  16191  *    stat - (IN) TSN statistics type (see tsn.h)
  16192  *     val - (IN) 32-bit counter value.
  16193  * Returns:
  16194  *    BCM_E_NONE - Success.
  16195  *    BCM_E_PARAM - Illegal parameter.
  16196  *    BCM_E_BADID - Illegal port number.
  16197  *    BCM_E_INTERNAL - Chip access failure.
  16198  *    BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip.
  16199  * Notes:
  16200  *    Same as bcm_esw_tsn_port_stat_set, except the counter value is 32-bit.
  16201  */
  16202 int
  16203 bcm_esw_tsn_port_stat_set32(
  16204     int unit,
  16205     bcm_gport_t port,
  16206     bcm_tsn_stat_t stat,
  16207     uint32 val)
  16208 {
  16209     int rv = BCM_E_UNAVAIL;
  16210 #if defined(BCM_TSN_SUPPORT)
  16211     uint64 val64;
  16212 
  16213     if (soc_feature(unit, soc_feature_tsn)) {
  16214         COMPILER_64_SET(val64, 0, val);
  16215         rv = bcm_esw_tsn_port_stat_set(unit, port, stat, val64);
  16216     }
  16217 #endif /* BCM_TSN_SUPPORT */
  16218 
  16219     return rv;
  16220 }
  16221 
  16222 /*
  16223  * Function:
  16224  *    bcm_esw_tsn_port_stat_get
  16225  * Description:
  16226  *    Get 64-bit counter value for specified TSN statistic type.
  16227  * Parameters:
  16228  *    unit - (IN) Unit number
  16229  *    port - (IN) port number
  16230  *    stat - (IN) TSN statistics type (see tsn.h)
  16231  *     val - (OUT) 64-bit counter value.
  16232  * Returns:
  16233  *    BCM_E_NONE - Success.
  16234  *    BCM_E_PARAM - Illegal parameter.
  16235  *    BCM_E_BADID - Illegal port number.
  16236  *    BCM_E_INTERNAL - Chip access failure.
  16237  *    BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip.
  16238  * Notes:
  16239  */
  16240 int
  16241 bcm_esw_tsn_port_stat_get(
  16242     int unit,
  16243     bcm_gport_t port,
  16244     bcm_tsn_stat_t stat,
  16245     uint64 *val)
  16246 {
  16247     int rv = BCM_E_UNAVAIL;
  16248 
  16249     /* Input parameter check. */
  16250     if (NULL == val) {
  16251         return BCM_E_PARAM;
  16252     }
  16253 
  16254 #if defined(BCM_TSN_SUPPORT)
  16255     /* Read software accumulated counters */
  16256     if (soc_feature(unit, soc_feature_tsn)) {
  16257         rv = bcmi_esw_tsn_stat_portcnt_get(unit, port, 0, stat, val);
  16258     }
  16259 #endif /* BCM_TSN_SUPPORT */
  16260 
  16261     return rv;
  16262 }
  16263 
  16264 /*
  16265  * Function:
  16266  *    bcm_esw_tsn_port_stat_get32
  16267  * Description:
  16268  *    Get lower 32-bit counter value for specified TSN statistic type.
  16269  * Parameters:
  16270  *    unit - (IN) Unit number
  16271  *    port - (IN) port number
  16272  *    stat - (IN) TSN statistics type (see tsn.h)
  16273  *     val - (OUT) 32-bit counter value.
  16274  * Returns:
  16275  *    BCM_E_NONE - Success.
  16276  *    BCM_E_PARAM - Illegal parameter.
  16277  *    BCM_E_BADID - Illegal port number.
  16278  *    BCM_E_INTERNAL - Chip access failure.
  16279  *    BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip.
  16280  * Notes:
  16281  *    Same as bcm_esw_tsn_port_stat_get, except converts result to 32-bit.
  16282  */
  16283 int
  16284 bcm_esw_tsn_port_stat_get32(
  16285     int unit,
  16286     bcm_gport_t port,
  16287     bcm_tsn_stat_t stat,
  16288     uint32 *val)
  16289 {
  16290     int rv = BCM_E_UNAVAIL;
  16291 #if defined(BCM_TSN_SUPPORT)
  16292     uint64 val64;
  16293 #endif /* BCM_TSN_SUPPORT */
  16294 
  16295     /* Input parameter check. */
  16296     if (NULL == val) {
  16297         return BCM_E_PARAM;
  16298     }
  16299 
  16300 #if defined(BCM_TSN_SUPPORT)
  16301     if (soc_feature(unit, soc_feature_tsn)) {
  16302         COMPILER_64_ZERO(val64);
  16303         rv = bcm_esw_tsn_port_stat_get(unit, port, stat, &val64);
  16304         if (BCM_FAILURE(rv)) {
  16305             return rv;
  16306         }
  16307 
  16308         COMPILER_64_TO_32_LO(*val, val64);
  16309     }
  16310 #endif /* BCM_TSN_SUPPORT */
  16311 
  16312     return rv;
  16313 }
  16314 
  16315 /*
  16316  * Function:
  16317  *    bcm_esw_tsn_port_stat_multi_set
  16318  * Purpose:
  16319  *    Set 64-bit counter value for multiple TSN statistic types.
  16320  * Parameters:
  16321  *    unit - (IN) Unit number
  16322  *    port - (IN) port number
  16323  *    nstat - (IN) Number of elements in stat array
  16324  *    stat_arr - (IN) Array of TSN statistics types defined in bcm_tsn_stat_t
  16325  *    value_arr - (IN) Set statistics values
  16326  * Returns:
  16327  *    BCM_E_NONE - Success.
  16328  *    BCM_E_PARAM - Illegal parameter.
  16329  *    BCM_E_BADID - Illegal port number.
  16330  *    BCM_E_INTERNAL - Chip access failure.
  16331  *    BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip.
  16332  * Notes:
  16333  */
  16334 int
  16335 bcm_esw_tsn_port_stat_multi_set(
  16336     int unit,
  16337     bcm_gport_t port,
  16338     int nstat,
  16339     bcm_tsn_stat_t *stat_arr,
  16340     uint64 *value_arr)
  16341 {
  16342     int rv = BCM_E_UNAVAIL;
  16343 #if defined(BCM_TSN_SUPPORT)
  16344     int stix;
  16345 #endif /* BCM_TSN_SUPPORT */
  16346 
  16347     /* Input parameter check. */
  16348     if (nstat <= 0) {
  16349         return BCM_E_PARAM;
  16350     }
  16351     if ((NULL == stat_arr) || (NULL == value_arr)) {
  16352         return BCM_E_PARAM;
  16353     }
  16354 
  16355 #if defined(BCM_TSN_SUPPORT)
  16356     if (soc_feature(unit, soc_feature_tsn)) {
  16357         for (stix = 0; stix < nstat; stix++) {
  16358             rv = bcm_esw_tsn_port_stat_set(unit, port, stat_arr[stix],
  16359                                            value_arr[stix]);
  16360             if (BCM_FAILURE(rv)) {
  16361                 return rv;
  16362             }
  16363         }
  16364     }
  16365 #endif /* BCM_TSN_SUPPORT */
  16366 
  16367     return rv;
  16368 }
  16369 
  16370 /*
  16371  * Function:
  16372  *    bcm_esw_tsn_port_stat_multi_set32
  16373  * Purpose:
  16374  *    Set lower 32-bit counter value for multiple TSN statistic types.
  16375  * Parameters:
  16376  *    unit - (IN) Unit number
  16377  *    port - (IN) port number
  16378  *    nstat - (IN) Number of elements in stat array
  16379  *    stat_arr - (IN) Array of TSN statistics types defined in bcm_tsn_stat_t
  16380  *    value_arr - (IN) Set 32-bit statistics values
  16381  * Returns:
  16382  *    BCM_E_NONE - Success.
  16383  *    BCM_E_PARAM - Illegal parameter.
  16384  *    BCM_E_BADID - Illegal port number.
  16385  *    BCM_E_INTERNAL - Chip access failure.
  16386  *    BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip.
  16387  * Notes:
  16388  */
  16389 int
  16390 bcm_esw_tsn_port_stat_multi_set32(
  16391     int unit,
  16392     bcm_gport_t port,
  16393     int nstat,
  16394     bcm_tsn_stat_t *stat_arr,
  16395     uint32 *value_arr)
  16396 {
  16397     int rv = BCM_E_UNAVAIL;
  16398 #if defined(BCM_TSN_SUPPORT)
  16399     int stix;
  16400 #endif /* BCM_TSN_SUPPORT */
  16401 
  16402     /* Input parameter check. */
  16403     if (nstat <= 0) {
  16404         return BCM_E_PARAM;
  16405     }
  16406     if ((NULL == stat_arr) || (NULL == value_arr)) {
  16407         return BCM_E_PARAM;
  16408     }
  16409 
  16410 #if defined(BCM_TSN_SUPPORT)
  16411     if (soc_feature(unit, soc_feature_tsn)) {
  16412         for (stix = 0; stix < nstat; stix++) {
  16413             rv = bcm_esw_tsn_port_stat_set32(unit, port, stat_arr[stix],
  16414                                              value_arr[stix]);
  16415             if (BCM_FAILURE(rv)) {
  16416                 return rv;
  16417             }
  16418         }
  16419     }
  16420 #endif /* BCM_TSN_SUPPORT */
  16421 
  16422     return rv;
  16423 }
  16424 
  16425 /*
  16426  * Function:
  16427  *    bcm_esw_tsn_port_stat_multi_get
  16428  * Purpose:
  16429  *    Get 64-bit counter value for multiple TSN statistic types.
  16430  * Parameters:
  16431  *    unit - (IN) Unit number
  16432  *    port - (IN) port number
  16433  *    nstat - (IN) Number of elements in stat array
  16434  *    stat_arr - (IN) Array of TSN statistics types defined in bcm_tsn_stat_t
  16435  *    value_arr - (OUT) Collected statistics values
  16436  * Returns:
  16437  *    BCM_E_NONE - Success.
  16438  *    BCM_E_PARAM - Illegal parameter.
  16439  *    BCM_E_BADID - Illegal port number.
  16440  *    BCM_E_INTERNAL - Chip access failure.
  16441  *    BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip.
  16442  * Notes:
  16443  */
  16444 int
  16445 bcm_esw_tsn_port_stat_multi_get(
  16446     int unit,
  16447     bcm_gport_t port,
  16448     int nstat,
  16449     bcm_tsn_stat_t *stat_arr,
  16450     uint64 *value_arr)
  16451 {
  16452     int rv = BCM_E_UNAVAIL;
  16453 #if defined(BCM_TSN_SUPPORT)
  16454     int stix;
  16455 #endif /* BCM_TSN_SUPPORT */
  16456 
  16457     /* Input parameter check. */
  16458     if (nstat <= 0) {
  16459         return BCM_E_PARAM;
  16460     }
  16461     if ((NULL == stat_arr) || (NULL == value_arr)) {
  16462         return BCM_E_PARAM;
  16463     }
  16464 
  16465 #if defined(BCM_TSN_SUPPORT)
  16466     if (soc_feature(unit, soc_feature_tsn)) {
  16467         for (stix = 0; stix < nstat; stix++) {
  16468             rv = bcm_esw_tsn_port_stat_get(unit, port, stat_arr[stix],
  16469                                            &(value_arr[stix]));
  16470             if (BCM_FAILURE(rv)) {
  16471                 return rv;
  16472             }
  16473         }
  16474     }
  16475 #endif /* BCM_TSN_SUPPORT */
  16476 
  16477     return rv;
  16478 }
  16479 
  16480 /*
  16481  * Function:
  16482  *    bcm_esw_tsn_port_stat_multi_get32
  16483  * Purpose:
  16484  *    Get lower 32-bit counter value for multiple TSN statistic types.
  16485  * Parameters:
  16486  *    unit - (IN) Unit number
  16487  *    port - (IN) port number
  16488  *    nstat - (IN) Number of elements in stat array
  16489  *    stat_arr - (IN) Array of TSN statistics types defined in bcm_tsn_stat_t
  16490  *    value_arr - (OUT) Collected 32-bit statistics values
  16491  * Returns:
  16492  *    BCM_E_NONE - Success.
  16493  *    BCM_E_PARAM - Illegal parameter.
  16494  *    BCM_E_BADID - Illegal port number.
  16495  *    BCM_E_INTERNAL - Chip access failure.
  16496  *    BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip.
  16497  * Notes:
  16498  */
  16499 int
  16500 bcm_esw_tsn_port_stat_multi_get32(
  16501     int unit,
  16502     bcm_gport_t port,
  16503     int nstat,
  16504     bcm_tsn_stat_t *stat_arr,
  16505     uint32 *value_arr)
  16506 {
  16507     int rv = BCM_E_UNAVAIL;
  16508 #if defined(BCM_TSN_SUPPORT)
  16509     int stix;
  16510 #endif /* BCM_TSN_SUPPORT */
  16511 
  16512     /* Input parameter check. */
  16513     if (nstat <= 0) {
  16514         return BCM_E_PARAM;
  16515     }
  16516     if ((NULL == stat_arr) || (NULL == value_arr)) {
  16517         return BCM_E_PARAM;
  16518     }
  16519 
  16520 #if defined(BCM_TSN_SUPPORT)
  16521     if (soc_feature(unit, soc_feature_tsn)) {
  16522         for (stix = 0; stix < nstat; stix++) {
  16523             rv = bcm_esw_tsn_port_stat_get32(unit, port, stat_arr[stix],
  16524                                              &(value_arr[stix]));
  16525             if (BCM_FAILURE(rv)) {
  16526                 return rv;
  16527             }
  16528         }
  16529     }
  16530 #endif /* BCM_TSN_SUPPORT */
  16531 
  16532     return rv;
  16533 }
  16534 
  16535 /*
  16536  * Function:
  16537  *    bcm_esw_tsn_port_stat_sync_get
  16538  * Description:
  16539  *    Get the specified hardware statistics (64-bit) from the device.
  16540  * Parameters:
  16541  *    unit - (IN) Unit number
  16542  *    port - (IN) port number
  16543  *    stat - (IN) TSN statistics type (see tsn.h)
  16544  *     val - (OUT) 64-bit counter value.
  16545  * Returns:
  16546  *    BCM_E_NONE - Success.
  16547  *    BCM_E_PARAM - Illegal parameter.
  16548  *    BCM_E_BADID - Illegal port number.
  16549  *    BCM_E_INTERNAL - Chip access failure.
  16550  *    BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip.
  16551  * Notes:
  16552  */
  16553 int
  16554 bcm_esw_tsn_port_stat_sync_get(
  16555     int unit,
  16556     bcm_gport_t port,
  16557     bcm_tsn_stat_t stat,
  16558     uint64 *val)
  16559 {
  16560     int rv = BCM_E_UNAVAIL;
  16561 
  16562 #if defined(BCM_TSN_SUPPORT)
  16563     /* Read software accumulated counters */
  16564     if (soc_feature(unit, soc_feature_tsn)) {
  16565         rv = bcmi_esw_tsn_stat_portcnt_get(unit, port, 1, stat, val);
  16566     }
  16567 #endif /* BCM_TSN_SUPPORT */
  16568 
  16569     return rv;
  16570 }
  16571 
  16572 /*
  16573  * Function:
  16574  *    bcm_esw_tsn_port_stat_sync_get32
  16575  * Description:
  16576  *    Get the specified hardware statistics (32-bit) from the device.
  16577  * Parameters:
  16578  *    unit - (IN) Unit number
  16579  *    port - (IN) port number
  16580  *    stat - (IN) TSN statistics type (see tsn.h)
  16581  *    val  - (OUT) 32-bit counter value.
  16582  * Returns:
  16583  *    BCM_E_NONE - Success.
  16584  *    BCM_E_PARAM - Illegal parameter.
  16585  *    BCM_E_BADID - Illegal port number.
  16586  *    BCM_E_INTERNAL - Chip access failure.
  16587  *    BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip.
  16588  * Notes:
  16589  *    Same as bcm_esw_tsn_port_stat_sync_get, except converts result to 32-bit.
  16590  */
  16591 int
  16592 bcm_esw_tsn_port_stat_sync_get32(
  16593     int unit,
  16594     bcm_gport_t port,
  16595     bcm_tsn_stat_t stat,
  16596     uint32 *val)
  16597 {
  16598     int rv = BCM_E_UNAVAIL;
  16599 #if defined(BCM_TSN_SUPPORT)
  16600     uint64 val64;
  16601 #endif /* BCM_TSN_SUPPORT */
  16602 
  16603     /* Input parameter check. */
  16604     if (NULL == val) {
  16605         return BCM_E_PARAM;
  16606     }
  16607 
  16608 #if defined(BCM_TSN_SUPPORT)
  16609     if (soc_feature(unit, soc_feature_tsn)) {
  16610         COMPILER_64_ZERO(val64);
  16611         rv = bcm_esw_tsn_port_stat_sync_get(unit, port, stat, &val64);
  16612         if (BCM_FAILURE(rv)) {
  16613             return rv;
  16614         }
  16615 
  16616         COMPILER_64_TO_32_LO(*val, val64);
  16617     }
  16618 #endif /* BCM_TSN_SUPPORT */
  16619 
  16620     return rv;
  16621 }
  16622 
  16623 /*
  16624  * Function:
  16625  *    bcm_esw_tsn_port_stat_sync_multi_get
  16626  * Purpose:
  16627  *    Get multiple hardware statistics (64-bit) from the device.
  16628  * Parameters:
  16629  *    unit - (IN) Unit number
  16630  *    port - (IN) port number
  16631  *    nstat - (IN) Number of elements in stat array
  16632  *    stat_arr - (IN) Array of TSN statistics types defined in bcm_tsn_stat_t
  16633  *    value_arr - (OUT) Collected statistics values
  16634  * Returns:
  16635  *    BCM_E_NONE - Success.
  16636  *    BCM_E_PARAM - Illegal parameter.
  16637  *    BCM_E_BADID - Illegal port number.
  16638  *    BCM_E_INTERNAL - Chip access failure.
  16639  *    BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip.
  16640  * Notes:
  16641  */
  16642 int
  16643 bcm_esw_tsn_port_stat_sync_multi_get(
  16644     int unit,
  16645     bcm_gport_t port,
  16646     int nstat,
  16647     bcm_tsn_stat_t *stat_arr,
  16648     uint64 *value_arr)
  16649 {
  16650     int rv = BCM_E_UNAVAIL;
  16651 #if defined(BCM_TSN_SUPPORT)
  16652     int stix;
  16653 #endif /* BCM_TSN_SUPPORT */
  16654 
  16655     /* Input parameter check. */
  16656     if (nstat <= 0) {
  16657         return BCM_E_PARAM;
  16658     }
  16659     if ((NULL == stat_arr) || (NULL == value_arr)) {
  16660         return BCM_E_PARAM;
  16661     }
  16662 
  16663 #if defined(BCM_TSN_SUPPORT)
  16664     if (soc_feature(unit, soc_feature_tsn)) {
  16665         for (stix = 0; stix < nstat; stix++) {
  16666             rv = bcm_esw_tsn_port_stat_sync_get(unit, port, stat_arr[stix],
  16667                                                 &(value_arr[stix]));
  16668             if (BCM_FAILURE(rv)) {
  16669                 return rv;
  16670             }
  16671         }
  16672     }
  16673 #endif /* BCM_TSN_SUPPORT */
  16674 
  16675     return rv;
  16676 }
  16677 
  16678 /*
  16679  * Function:
  16680  *    bcm_esw_tsn_port_stat_sync_multi_get32
  16681  * Purpose:
  16682  *    Get multiple hardware statistics (32-bit) from the device.
  16683  * Parameters:
  16684  *    unit - (IN) Unit number
  16685  *    port - (IN) port number
  16686  *    nstat - (IN) Number of elements in stat array
  16687  *    stat_arr - (IN) Array of TSN statistics types defined in bcm_tsn_stat_t
  16688  *    value_arr - (OUT) Collected 32-bit statistics values
  16689  * Returns:
  16690  *    BCM_E_NONE - Success.
  16691  *    BCM_E_PARAM - Illegal parameter.
  16692  *    BCM_E_BADID - Illegal port number.
  16693  *    BCM_E_INTERNAL - Chip access failure.
  16694  *    BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip.
  16695  * Notes:
  16696  */
  16697 int
  16698 bcm_esw_tsn_port_stat_sync_multi_get32(
  16699     int unit,
  16700     bcm_gport_t port,
  16701     int nstat,
  16702     bcm_tsn_stat_t *stat_arr,
  16703     uint32 *value_arr)
  16704 {
  16705     int rv = BCM_E_UNAVAIL;
  16706 #if defined(BCM_TSN_SUPPORT)
  16707     int stix;
  16708 #endif /* BCM_TSN_SUPPORT */
  16709     /* Input parameter check. */
  16710     if (nstat <= 0) {
  16711         return BCM_E_PARAM;
  16712     }
  16713     if ((NULL == stat_arr) || (NULL == value_arr)) {
  16714         return BCM_E_PARAM;
  16715     }
  16716 
  16717 #if defined(BCM_TSN_SUPPORT)
  16718     if (soc_feature(unit, soc_feature_tsn)) {
  16719         for (stix = 0; stix < nstat; stix++) {
  16720             rv = bcm_esw_tsn_port_stat_sync_get32(unit, port, stat_arr[stix],
  16721                                                   &(value_arr[stix]));
  16722             if (BCM_FAILURE(rv)) {
  16723                 return rv;
  16724             }
  16725         }
  16726 
  16727     }
  16728 #endif /* BCM_TSN_SUPPORT */
  16729 
  16730     return rv;
  16731 }
  16732 
  16733 /*
  16734  * Function:
  16735  *      bcm_esw_tsn_stat_group_create
  16736  * Description:
  16737  *      Create a TSN stat group by picking stat types (in an array) to be
  16738  *      included for counting
  16739  * Parameters:
  16740  *      unit             - (IN) unit number
  16741  *      group_type       - (IN) TSN statistic group type
  16742  *      count            - (IN) the number of elements in stat_arr
  16743  *      stat_arr         - (IN) array for tsn stat types
  16744  *      id               - (OUT) tsn statistic group id
  16745  *
  16746  * Return Value:
  16747  *      BCM_E_XXX
  16748  * Notes:
  16749  */
  16750 int
  16751 bcm_esw_tsn_stat_group_create(
  16752     int unit,
  16753     bcm_tsn_stat_group_type_t group_type,
  16754     int count,
  16755     bcm_tsn_stat_t *stat_arr,
  16756     bcm_tsn_stat_group_t *id)
  16757 {
  16758 #if defined(BCM_TSN_SUPPORT)
  16759     if (soc_feature(unit, soc_feature_tsn)) {
  16760         return bcmi_esw_tsn_stat_flowcnt_group_create(unit, group_type, count,
  16761                                                       stat_arr, id);
  16762     } else
  16763 #endif
  16764     {
  16765         return BCM_E_UNAVAIL;
  16766     }
  16767 }
  16768 
  16769 /*
  16770  * Function:
  16771  *      bcm_esw_tsn_stat_group_get
  16772  * Description:
  16773  *      Get configuration of the TSN stat group
  16774  * Parameters:
  16775  *      unit             - (IN) unit number
  16776  *      id               - (IN) TSN statistic group id
  16777  *      group_type       - (OUT) TSN statistic group type
  16778  *      max              - (IN) the size of stat_arr
  16779  *      stat_arr         - (OUT) array for returned TSN stat types
  16780  *      count            - (OUT) actual number of TSN stat types
  16781  *
  16782  * Return Value:
  16783  *      BCM_E_XXX
  16784  * Notes:
  16785  */
  16786 int
  16787 bcm_esw_tsn_stat_group_get(
  16788     int unit,
  16789     bcm_tsn_stat_group_t id,
  16790     bcm_tsn_stat_group_type_t *group_type,
  16791     int max,
  16792     bcm_tsn_stat_t *stat_arr,
  16793     int *count)
  16794 {
  16795 #if defined(BCM_TSN_SUPPORT)
  16796     if (soc_feature(unit, soc_feature_tsn)) {
  16797         return bcmi_esw_tsn_stat_flowcnt_group_get(unit, id, group_type, max,
  16798                                                    stat_arr, count);
  16799     } else
  16800 #endif
  16801     {
  16802         return BCM_E_UNAVAIL;
  16803     }
  16804 }
  16805 
  16806 /*
  16807  * Function:
  16808  *      bcm_esw_tsn_stat_group_set
  16809  * Description:
  16810  *      Set configuration of the TSN stat group
  16811  * Parameters:
  16812  *      unit             - (IN) unit number
  16813  *      id               - (IN) TSN statistic group id
  16814  *      count            - (IN) the number of elements in stat_arr
  16815  *      stat_arr         - (IN) array for TSN stat types
  16816  *
  16817  * Return Value:
  16818  *      BCM_E_XXX
  16819  * Notes:
  16820  */
  16821 int
  16822 bcm_esw_tsn_stat_group_set(
  16823     int unit,
  16824     bcm_tsn_stat_group_t id,
  16825     int count,
  16826     bcm_tsn_stat_t *stat_arr)
  16827 {
  16828 #if defined(BCM_TSN_SUPPORT)
  16829     if (soc_feature(unit, soc_feature_tsn)) {
  16830         return bcmi_esw_tsn_stat_flowcnt_group_set(unit, id, count, stat_arr);
  16831     } else
  16832 #endif
  16833     {
  16834         return BCM_E_UNAVAIL;
  16835     }
  16836 }
  16837 
  16838 /*
  16839  * Function:
  16840  *      bcm_esw_tsn_stat_group_destroy
  16841  * Description:
  16842  *      Destroy a TSN stat group
  16843  * Parameters:
  16844  *      unit             - (IN) unit number
  16845  *      id               - (IN) TSN statistic group id
  16846  *
  16847  * Return Value:
  16848  *      BCM_E_XXX
  16849  * Notes:
  16850  */
  16851 int
  16852 bcm_esw_tsn_stat_group_destroy(int unit, bcm_tsn_stat_group_t id)
  16853 {
  16854 #if defined(BCM_TSN_SUPPORT)
  16855     if (soc_feature(unit, soc_feature_tsn)) {
  16856         return bcmi_esw_tsn_stat_flowcnt_group_destroy(unit, id);
  16857     } else
  16858 #endif
  16859     {
  16860         return BCM_E_UNAVAIL;
  16861     }
  16862 }
  16863 
  16864 /*
  16865  * Function:
  16866  *      bcm_esw_tsn_stat_group_traverse
  16867  * Description:
  16868  *      Traverse TSN stat groups
  16869  * Parameters:
  16870  *      unit             - (IN) unit number
  16871  *      cb               - (IN) User provided call back function
  16872  *      user_data        - (IN) User provided data
  16873  *
  16874  * Return Value:
  16875  *      BCM_E_XXX
  16876  * Notes:
  16877  */
  16878 int
  16879 bcm_esw_tsn_stat_group_traverse(
  16880     int unit,
  16881     bcm_tsn_stat_group_traverse_cb cb,
  16882     void *user_data)
  16883 {
  16884 #if defined(BCM_TSN_SUPPORT)
  16885     if (soc_feature(unit, soc_feature_tsn)) {
  16886         return bcmi_esw_tsn_stat_flowcnt_group_traverse(unit, cb, user_data);
  16887     } else
  16888 #endif
  16889     {
  16890         return BCM_E_UNAVAIL;
  16891     }
  16892 }
  16893 
  16894 /*
  16895  * Function:
  16896  *      bcm_esw_tsn_sr_flow_stat_group_set
  16897  * Description:
  16898  *      Attach ingress/egress stat group to this flow and enable counting for
  16899  *      the stat group. To disable counting for a specific group type, set
  16900  *      BCM_TSN_STAT_GROUP_INVALID as stat_group
  16901  * Parameters:
  16902  *      unit             - (IN) unit number
  16903  *      flow             - (IN) SR flow
  16904  *      group_type       - (IN) TSN statistic group type
  16905  *      stat_group       - (IN) TSN statistic group
  16906  *
  16907  * Return Value:
  16908  *      BCM_E_XXX
  16909  * Notes:
  16910  */
  16911 int
  16912 bcm_esw_tsn_sr_flow_stat_group_set(
  16913     int unit,
  16914     bcm_tsn_sr_flow_t flow,
  16915     bcm_tsn_stat_group_type_t group_type,
  16916     bcm_tsn_stat_group_t stat_group)
  16917 {
  16918 #if defined(BCM_TSN_SUPPORT)
  16919     if (soc_feature(unit, soc_feature_tsn)) {
  16920         return bcmi_esw_tsn_stat_flowcnt_flow_set(unit, flow, group_type,
  16921                                                   stat_group);
  16922     } else
  16923 #endif
  16924     {
  16925         return BCM_E_UNAVAIL;
  16926     }
  16927 }
  16928 
  16929 /*
  16930  * Function:
  16931  *      bcm_esw_tsn_sr_flow_stat_group_get
  16932  * Description:
  16933  *      Get the stat group for this flow with specified group type
  16934  * Parameters:
  16935  *      unit             - (IN) unit number
  16936  *      flow             - (IN) SR flow
  16937  *      group_type       - (IN) TSN statistic group type
  16938  *      stat_group       - (OUT)TSN statistic group
  16939  *
  16940  * Return Value:
  16941  *      BCM_E_XXX
  16942  * Notes:
  16943  */
  16944 int
  16945 bcm_esw_tsn_sr_flow_stat_group_get(
  16946     int unit,
  16947     bcm_tsn_sr_flow_t flow,
  16948     bcm_tsn_stat_group_type_t group_type,
  16949     bcm_tsn_stat_group_t *stat_group)
  16950 {
  16951 #if defined(BCM_TSN_SUPPORT)
  16952     if (soc_feature(unit, soc_feature_tsn)) {
  16953         return bcmi_esw_tsn_stat_flowcnt_flow_get(unit, flow, group_type,
  16954                                                   stat_group);
  16955     } else
  16956 #endif
  16957     {
  16958         return BCM_E_UNAVAIL;
  16959     }
  16960 }
  16961 
  16962 /*
  16963  * Function:
  16964  *      bcm_esw_tsn_sr_flow_stat_set
  16965  * Description:
  16966  *      Set 64-bit counter value for specified TSN statistic type
  16967  * Parameters:
  16968  *      unit             - (IN) unit number
  16969  *      flow             - (IN) SR flow
  16970  *      stat             - (IN) TSN stat types
  16971  *      val              - (IN) counter value
  16972  *
  16973  * Return Value:
  16974  *      BCM_E_XXX
  16975  * Notes:
  16976  */
  16977 int
  16978 bcm_esw_tsn_sr_flow_stat_set(
  16979     int unit,
  16980     bcm_tsn_sr_flow_t flow,
  16981     bcm_tsn_stat_t stat,
  16982     uint64 val)
  16983 {
  16984 #if defined(BCM_TSN_SR_SUPPORT)
  16985     if (soc_feature(unit, soc_feature_tsn_sr)) {
  16986         return bcmi_esw_tsn_stat_flowcnt_set(
  16987                    unit, flow, 1, &stat, &val);
  16988     } else
  16989 #endif
  16990     {
  16991         return BCM_E_UNAVAIL;
  16992     }
  16993 }
  16994 
  16995 /*
  16996  * Function:
  16997  *      bcm_esw_tsn_sr_flow_stat_set32
  16998  * Description:
  16999  *      Set lower 32-bit counter value for specified TSN statistic type
  17000  * Parameters:
  17001  *      unit             - (IN) unit number
  17002  *      flow             - (IN) SR flow
  17003  *      stat             - (IN) TSN stat types
  17004  *      val              - (IN) counter value
  17005  *
  17006  * Return Value:
  17007  *      BCM_E_XXX
  17008  * Notes:
  17009  */
  17010 int
  17011 bcm_esw_tsn_sr_flow_stat_set32(
  17012     int unit,
  17013     bcm_tsn_sr_flow_t flow,
  17014     bcm_tsn_stat_t stat,
  17015     uint32 val)
  17016 {
  17017 #if defined(BCM_TSN_SR_SUPPORT)
  17018     if (soc_feature(unit, soc_feature_tsn_sr)) {
  17019         uint64 value64;
  17020 
  17021         COMPILER_64_SET(value64, 0, val);
  17022         return bcmi_esw_tsn_stat_flowcnt_set(
  17023                    unit, flow, 1, &stat, &value64);
  17024     } else
  17025 #endif
  17026     {
  17027         return BCM_E_UNAVAIL;
  17028     }
  17029 }
  17030 
  17031 /*
  17032  * Function:
  17033  *      bcm_esw_tsn_sr_flow_stat_get
  17034  * Description:
  17035  *      Get 64-bit counter value for specified TSN statistic type
  17036  * Parameters:
  17037  *      unit             - (IN) unit number
  17038  *      flow             - (IN) SR flow
  17039  *      stat             - (IN) TSN stat types
  17040  *      val              - (OUT)counter value
  17041  *
  17042  * Return Value:
  17043  *      BCM_E_XXX
  17044  * Notes:
  17045  */
  17046 int
  17047 bcm_esw_tsn_sr_flow_stat_get(
  17048     int unit,
  17049     bcm_tsn_sr_flow_t flow,
  17050     bcm_tsn_stat_t stat,
  17051     uint64 *val)
  17052 {
  17053 #if defined(BCM_TSN_SR_SUPPORT)
  17054     if (soc_feature(unit, soc_feature_tsn_sr)) {
  17055         return bcmi_esw_tsn_stat_flowcnt_get(
  17056                    unit, flow, 0, 1, &stat, val);
  17057     } else
  17058 #endif
  17059     {
  17060         return BCM_E_UNAVAIL;
  17061     }
  17062 }
  17063 
  17064 /*
  17065  * Function:
  17066  *      bcm_esw_tsn_sr_flow_stat_get32
  17067  * Description:
  17068  *      Get lower 32-bit counter value for specified TSN statistic type
  17069  * Parameters:
  17070  *      unit             - (IN) unit number
  17071  *      flow             - (IN) SR flow
  17072  *      stat             - (IN) TSN stat types
  17073  *      val              - (OUT)counter value
  17074  *
  17075  * Return Value:
  17076  *      BCM_E_XXX
  17077  * Notes:
  17078  */
  17079 int
  17080 bcm_esw_tsn_sr_flow_stat_get32(
  17081     int unit,
  17082     bcm_tsn_sr_flow_t flow,
  17083     bcm_tsn_stat_t stat,
  17084     uint32 *val)
  17085 {
  17086 #if defined(BCM_TSN_SR_SUPPORT)
  17087     if (soc_feature(unit, soc_feature_tsn_sr)) {
  17088         uint64 value64;
  17089         int rv;
  17090 
  17091         if (NULL == val) {
  17092             return BCM_E_PARAM;
  17093         }
  17094         rv = bcmi_esw_tsn_stat_flowcnt_get(
  17095                  unit, flow, 0, 1, &stat, &value64);
  17096         if (BCM_SUCCESS(rv)) {
  17097             *val = COMPILER_64_LO(value64);
  17098         }
  17099         return rv;
  17100     } else
  17101 #endif
  17102     {
  17103         return BCM_E_UNAVAIL;
  17104     }
  17105 }
  17106 
  17107 /*
  17108  * Function:
  17109  *      bcm_esw_tsn_sr_flow_stat_multi_set
  17110  * Description:
  17111  *      Set 64-bit counter value for multiple TSN statistic types.
  17112  * Parameters:
  17113  *      unit             - (IN) unit number
  17114  *      flow             - (IN) SR flow
  17115  *      nstat            - (IN) number of element in stat_arr and value_arr
  17116  *      stat_arr         - (IN) TSN stat types
  17117  *      value_arr        - (IN) counter value
  17118  *
  17119  * Return Value:
  17120  *      BCM_E_XXX
  17121  * Notes:
  17122  */
  17123 int
  17124 bcm_esw_tsn_sr_flow_stat_multi_set(
  17125     int unit,
  17126     bcm_tsn_sr_flow_t flow,
  17127     int nstat,
  17128     bcm_tsn_stat_t *stat_arr,
  17129     uint64 *value_arr)
  17130 {
  17131 #if defined(BCM_TSN_SR_SUPPORT)
  17132     if (soc_feature(unit, soc_feature_tsn_sr)) {
  17133         return bcmi_esw_tsn_stat_flowcnt_set(
  17134                    unit, flow, nstat, stat_arr, value_arr);
  17135     } else
  17136 #endif
  17137     {
  17138         return BCM_E_UNAVAIL;
  17139     }
  17140 }
  17141 
  17142 /*
  17143  * Function:
  17144  *      bcm_esw_tsn_sr_flow_stat_multi_set32
  17145  * Description:
  17146  *      Set lower 32-bit counter value for multiple TSN statistic types.
  17147  * Parameters:
  17148  *      unit             - (IN) unit number
  17149  *      flow             - (IN) SR flow
  17150  *      nstat            - (IN) number of element in stat_arr and value_arr
  17151  *      stat_arr         - (IN) TSN stat types
  17152  *      value_arr        - (IN) counter value
  17153  *
  17154  * Return Value:
  17155  *      BCM_E_XXX
  17156  * Notes:
  17157  */
  17158 int
  17159 bcm_esw_tsn_sr_flow_stat_multi_set32(
  17160     int unit,
  17161     bcm_tsn_sr_flow_t flow,
  17162     int nstat,
  17163     bcm_tsn_stat_t *stat_arr,
  17164     uint32 *value_arr)
  17165 {
  17166 #if defined(BCM_TSN_SR_SUPPORT)
  17167     if (soc_feature(unit, soc_feature_tsn_sr)) {
  17168         uint64 *value64_arr = NULL;
  17169         int i, rv;
  17170 
  17171         if (NULL == value_arr) {
  17172             return BCM_E_PARAM;
  17173         }
  17174         value64_arr = sal_alloc(nstat * sizeof(uint64), "value64_arr");
  17175         if (NULL == value64_arr) {
  17176             return BCM_E_MEMORY;
  17177         }
  17178         for (i = 0; i < nstat ; i++) {
  17179             COMPILER_64_SET(value64_arr[i], 0, value_arr[i]);
  17180         }
  17181         rv = bcmi_esw_tsn_stat_flowcnt_set(
  17182                  unit, flow, nstat, stat_arr, value64_arr);
  17183         sal_free(value64_arr);
  17184         return rv;
  17185     } else
  17186 #endif
  17187     {
  17188         return BCM_E_UNAVAIL;
  17189     }
  17190 }
  17191 
  17192 /*
  17193  * Function:
  17194  *      bcm_esw_tsn_sr_flow_stat_multi_get
  17195  * Description:
  17196  *      Get 64-bit counter value for multiple TSN statistic types.
  17197  * Parameters:
  17198  *      unit             - (IN) unit number
  17199  *      flow             - (IN) SR flow
  17200  *      nstat            - (IN) size of stat_arr and value_arr
  17201  *      stat_arr         - (IN) TSN stat types
  17202  *      value_arr        - (OUT)counter value
  17203  *
  17204  * Return Value:
  17205  *      BCM_E_XXX
  17206  * Notes:
  17207  */
  17208 int
  17209 bcm_esw_tsn_sr_flow_stat_multi_get(
  17210     int unit,
  17211     bcm_tsn_sr_flow_t flow,
  17212     int nstat,
  17213     bcm_tsn_stat_t *stat_arr,
  17214     uint64 *value_arr)
  17215 {
  17216 #if defined(BCM_TSN_SR_SUPPORT)
  17217     if (soc_feature(unit, soc_feature_tsn_sr)) {
  17218         return bcmi_esw_tsn_stat_flowcnt_get(
  17219                    unit, flow, 0, nstat, stat_arr, value_arr);
  17220     } else
  17221 #endif
  17222     {
  17223         return BCM_E_UNAVAIL;
  17224     }
  17225 }
  17226 
  17227 /*
  17228  * Function:
  17229  *      bcm_esw_tsn_sr_flow_stat_multi_get32
  17230  * Description:
  17231  *      Get lower 32-bit counter value for multiple TSN statistic types.
  17232  * Parameters:
  17233  *      unit             - (IN) unit number
  17234  *      flow             - (IN) SR flow
  17235  *      nstat            - (IN) size of stat_arr and value_arr
  17236  *      stat_arr         - (IN) TSN stat types
  17237  *      value_arr        - (OUT)counter value
  17238  *
  17239  * Return Value:
  17240  *      BCM_E_XXX
  17241  * Notes:
  17242  */
  17243 int
  17244 bcm_esw_tsn_sr_flow_stat_multi_get32(
  17245     int unit,
  17246     bcm_tsn_sr_flow_t flow,
  17247     int nstat,
  17248     bcm_tsn_stat_t *stat_arr,
  17249     uint32 *value_arr)
  17250 {
  17251 #if defined(BCM_TSN_SR_SUPPORT)
  17252     if (soc_feature(unit, soc_feature_tsn_sr)) {
  17253         uint64 *value64_arr = NULL;
  17254         int i, rv;
  17255 
  17256         if (NULL == value_arr) {
  17257             return BCM_E_PARAM;
  17258         }
  17259         value64_arr = sal_alloc(nstat * sizeof(uint64), "value64_arr");
  17260         if (NULL == value64_arr) {
  17261             return BCM_E_MEMORY;
  17262         }
  17263         rv = bcmi_esw_tsn_stat_flowcnt_get(
  17264                  unit, flow, 0, nstat, stat_arr, value64_arr);
  17265         if (BCM_SUCCESS(rv)) {
  17266             for (i = 0; i < nstat ; i++) {
  17267                 value_arr[i] = COMPILER_64_LO(value64_arr[i]);
  17268             }
  17269         }
  17270         sal_free(value64_arr);
  17271         return rv;
  17272     } else
  17273 #endif
  17274     {
  17275         return BCM_E_UNAVAIL;
  17276     }
  17277 }
  17278 
  17279 /*
  17280  * Function:
  17281  *      bcm_esw_tsn_sr_flow_stat_sync_get
  17282  * Description:
  17283  *      Get the specified hardware statistics (64-bit) from the device.
  17284  * Parameters:
  17285  *      unit             - (IN) unit number
  17286  *      flow             - (IN) SR flow
  17287  *      stat             - (IN) TSN stat types
  17288  *      val              - (OUT)counter value
  17289  *
  17290  * Return Value:
  17291  *      BCM_E_XXX
  17292  * Notes:
  17293  */
  17294 int
  17295 bcm_esw_tsn_sr_flow_stat_sync_get(
  17296     int unit,
  17297     bcm_tsn_sr_flow_t flow,
  17298     bcm_tsn_stat_t stat,
  17299     uint64 *val)
  17300 {
  17301 #if defined(BCM_TSN_SR_SUPPORT)
  17302     if (soc_feature(unit, soc_feature_tsn_sr)) {
  17303         return bcmi_esw_tsn_stat_flowcnt_get(
  17304                    unit, flow, 1, 1, &stat, val);
  17305     } else
  17306 #endif
  17307     {
  17308         return BCM_E_UNAVAIL;
  17309     }
  17310 }
  17311 
  17312 /*
  17313  * Function:
  17314  *      bcm_esw_tsn_sr_flow_stat_sync_get32
  17315  * Description:
  17316  *      Get the specified hardware statistics (32-bit) from the device.
  17317  * Parameters:
  17318  *      unit             - (IN) unit number
  17319  *      flow             - (IN) SR flow
  17320  *      stat             - (IN) TSN stat types
  17321  *      val              - (OUT)counter value
  17322  *
  17323  * Return Value:
  17324  *      BCM_E_XXX
  17325  * Notes:
  17326  */
  17327 int
  17328 bcm_esw_tsn_sr_flow_stat_sync_get32(
  17329     int unit,
  17330     bcm_tsn_sr_flow_t flow,
  17331     bcm_tsn_stat_t stat,
  17332     uint32 *val)
  17333 {
  17334 #if defined(BCM_TSN_SR_SUPPORT)
  17335     if (soc_feature(unit, soc_feature_tsn_sr)) {
  17336         uint64 value64;
  17337         int rv;
  17338 
  17339         if (NULL == val) {
  17340             return BCM_E_PARAM;
  17341         }
  17342         rv = bcmi_esw_tsn_stat_flowcnt_get(
  17343                  unit, flow, 1, 1, &stat, &value64);
  17344         if (BCM_SUCCESS(rv)) {
  17345             *val = COMPILER_64_LO(value64);
  17346         }
  17347         return rv;
  17348     } else
  17349 #endif
  17350     {
  17351         return BCM_E_UNAVAIL;
  17352     }
  17353 }
  17354 
  17355 /*
  17356  * Function:
  17357  *      bcm_esw_tsn_sr_flow_stat_sync_multi_get
  17358  * Description:
  17359  *      Get multiple hardware statistics (64-bit) from the device
  17360  * Parameters:
  17361  *      unit             - (IN) unit number
  17362  *      flow             - (IN) SR flow
  17363  *      nstat            - (IN) size of stat_arr and value_arr
  17364  *      stat_arr         - (IN) TSN stat types
  17365  *      value_arr        - (OUT)counter value
  17366  *
  17367  * Return Value:
  17368  *      BCM_E_XXX
  17369  * Notes:
  17370  */
  17371 int
  17372 bcm_esw_tsn_sr_flow_stat_sync_multi_get(
  17373     int unit,
  17374     bcm_tsn_sr_flow_t flow,
  17375     int nstat,
  17376     bcm_tsn_stat_t *stat_arr,
  17377     uint64 *value_arr)
  17378 {
  17379 #if defined(BCM_TSN_SR_SUPPORT)
  17380     if (soc_feature(unit, soc_feature_tsn_sr)) {
  17381         return bcmi_esw_tsn_stat_flowcnt_get(
  17382                    unit, flow, 1, nstat, stat_arr, value_arr);
  17383     } else
  17384 #endif
  17385     {
  17386         return BCM_E_UNAVAIL;
  17387     }
  17388 }
  17389 
  17390 /*
  17391  * Function:
  17392  *      bcm_esw_tsn_sr_flow_stat_sync_multi_get32
  17393  * Description:
  17394  *      Get multiple hardware statistics (32-bit) from the device
  17395  * Parameters:
  17396  *      unit             - (IN) unit number
  17397  *      flow             - (IN) SR flow
  17398  *      nstat            - (IN) size of stat_arr and value_arr
  17399  *      stat_arr         - (IN) TSN stat types
  17400  *      value_arr        - (OUT)counter value
  17401  *
  17402  * Return Value:
  17403  *      BCM_E_XXX
  17404  * Notes:
  17405  */
  17406 int
  17407 bcm_esw_tsn_sr_flow_stat_sync_multi_get32(
  17408     int unit,
  17409     bcm_tsn_sr_flow_t flow,
  17410     int nstat,
  17411     bcm_tsn_stat_t *stat_arr,
  17412     uint32 *value_arr)
  17413 {
  17414 #if defined(BCM_TSN_SR_SUPPORT)
  17415     if (soc_feature(unit, soc_feature_tsn_sr)) {
  17416         uint64 *value64_arr = NULL;
  17417         int i, rv;
  17418 
  17419         if (NULL == value_arr) {
  17420             return BCM_E_PARAM;
  17421         }
  17422         value64_arr = sal_alloc(nstat * sizeof(uint64), "value64_arr");
  17423         if (NULL == value64_arr) {
  17424             return BCM_E_MEMORY;
  17425         }
  17426         rv = bcmi_esw_tsn_stat_flowcnt_get(
  17427                  unit, flow, 1, nstat, stat_arr, value64_arr);
  17428         if (BCM_SUCCESS(rv)) {
  17429             for (i = 0; i < nstat ; i++) {
  17430                 value_arr[i] = COMPILER_64_LO(value64_arr[i]);
  17431             }
  17432         }
  17433         sal_free(value64_arr);
  17434         return rv;
  17435     } else
  17436 #endif
  17437     {
  17438         return BCM_E_UNAVAIL;
  17439     }
  17440 }
  17441 
  17442 /*
  17443  * Function:
  17444  *    bcm_esw_tsn_stat_threshold_set
  17445  * Purpose:
  17446  *    Configure threshold for a specific stat type on
  17447  *    a specific source
  17448  * Parameters:
  17449  *    unit   - (IN) Unit number
  17450  *    source - (IN) Stat source for TSN stat threshold check
  17451  *    stat   - (IN) TSN statistics type (see tsn.h)
  17452  *    config - (IN) TSN stat threshold configuration structure
  17453  * Returns:
  17454  *    BCM_E_XXX
  17455  */
  17456 int
  17457 bcm_esw_tsn_stat_threshold_set(
  17458     int unit,
  17459     bcm_tsn_stat_threshold_source_t source,
  17460     bcm_tsn_stat_t stat,
  17461     bcm_tsn_stat_threshold_config_t *config)
  17462 {
  17463     int rv = BCM_E_UNAVAIL;
  17464 
  17465     /* Input parameter check */
  17466     if (NULL == config) {
  17467         return BCM_E_PARAM;
  17468     }
  17469 
  17470 #if defined(BCM_TSN_SUPPORT)
  17471     if (soc_feature(unit, soc_feature_tsn)) {
  17472         rv = bcmi_esw_tsn_stat_threshold_set(unit, source, stat, config);
  17473     }
  17474 #endif /* BCM_TSN_SUPPORT */
  17475 
  17476     return rv;
  17477 }
  17478 
  17479 /*
  17480  * Function:
  17481  *    bcm_esw_tsn_stat_threshold_get
  17482  * Purpose:
  17483  *    Get the threshold configuration for a specific stat type on
  17484  *    a specific source
  17485  * Parameters:
  17486  *    unit   - (IN) Unit number
  17487  *    source - (IN) Stat source for TSN stat threshold check
  17488  *    stat   - (IN) TSN statistics type (see tsn.h)
  17489  *    config - (OUT) TSN stat threshold configuration structure
  17490  * Returns:
  17491  *    BCM_E_XXX
  17492  */
  17493 int
  17494 bcm_esw_tsn_stat_threshold_get(
  17495     int unit,
  17496     bcm_tsn_stat_threshold_source_t source,
  17497     bcm_tsn_stat_t stat,
  17498     bcm_tsn_stat_threshold_config_t *config)
  17499 {
  17500     int rv = BCM_E_UNAVAIL;
  17501 
  17502     /* Input parameter check */
  17503     if (NULL == config) {
  17504         return BCM_E_PARAM;
  17505     }
  17506 
  17507 #if defined(BCM_TSN_SUPPORT)
  17508     if (soc_feature(unit, soc_feature_tsn)) {
  17509         rv = bcmi_esw_tsn_stat_threshold_get(unit, source, stat, config);
  17510     }
  17511 #endif /* BCM_TSN_SUPPORT */
  17512 
  17513     return rv;
  17514 }
  17515 
  17516 /*
  17517  * Function:
  17518  *     bcm_esw_tsn_event_register
  17519  * Purpose:
  17520  *     The callback function registration to handle the TSN event on
  17521  *     specified event source.
  17522  * Parameters:
  17523  *     unit             - (IN) unit number
  17524  *     event            - (IN) TSN event
  17525  *     src              - (IN) source triggeres the event
  17526  *     cb               - (IN) callback function
  17527  *     user_data        - (IN) Pointer to user data to supply in the callback.
  17528  * Returns:
  17529  *     BCM_E_XXX
  17530  * Notes:
  17531  */
  17532 int
  17533 bcm_esw_tsn_event_register(
  17534     int unit,
  17535     bcm_tsn_event_type_t event,
  17536     bcm_tsn_event_source_t *src,
  17537     bcm_tsn_event_cb cb,
  17538     void *user_data)
  17539 {
  17540 #if defined(BCM_TSN_SUPPORT)
  17541     if (soc_feature(unit, soc_feature_tsn)) {
  17542         return bcmi_esw_tsn_event_register(unit, event, src, cb, user_data);
  17543     }
  17544 #endif /* BCM_TSN_SUPPORT */
  17545     return BCM_E_UNAVAIL;
  17546 }
  17547 
  17548 /*
  17549  * Function:
  17550  *     bcm_esw_tsn_event_unregister
  17551  * Purpose:
  17552  *     The callback function unregistration of the TSN event on
  17553  *     specified event source.
  17554  * Parameters:
  17555  *     unit             - (IN) unit number
  17556  *     event            - (IN) TSN event
  17557  *     src              - (IN) source triggeres the event
  17558  *     cb               - (IN) callback function
  17559  * Returns:
  17560  *     BCM_E_XXX
  17561  * Notes:
  17562  */
  17563 int
  17564 bcm_esw_tsn_event_unregister(
  17565     int unit,
  17566     bcm_tsn_event_type_t event,
  17567     bcm_tsn_event_source_t *src,
  17568     bcm_tsn_event_cb cb)
  17569 {
  17570 #if defined(BCM_TSN_SUPPORT)
  17571     if (soc_feature(unit, soc_feature_tsn)) {
  17572         return bcmi_esw_tsn_event_unregister(unit, event, src, cb);
  17573     }
  17574 #endif /* BCM_TSN_SUPPORT */
  17575     return BCM_E_UNAVAIL;
  17576 }
  17577 
  17578 /*
  17579  * Function:
  17580  *     bcm_esw_tsn_event_notification_traverse
  17581  * Purpose:
  17582  *     Traverse all registered event notification callback
  17583  * Parameters:
  17584  *     unit             - (IN) unit number
  17585  *     cb               - (IN) callback function
  17586  *     user_data        - (IN) Pointer to user data to supply in the callback
  17587  * Returns:
  17588  *     BCM_E_XXX
  17589  * Notes:
  17590  */
  17591 int
  17592 bcm_esw_tsn_event_notification_traverse(
  17593     int unit,
  17594     bcm_tsn_event_notification_traverse_cb cb,
  17595     void *user_data)
  17596 {
  17597 #if defined(BCM_TSN_SUPPORT)
  17598     if (soc_feature(unit, soc_feature_tsn)) {
  17599         return bcmi_esw_tsn_event_notification_traverse(unit, cb, user_data);
  17600     }
  17601 #endif /* BCM_TSN_SUPPORT */
  17602     return BCM_E_UNAVAIL;
  17603 }
  17604 
  17605 /*
  17606  * Function:
  17607  *      bcm_esw_tsn_mtu_profile_create
  17608  * Purpose:
  17609  *      Create mtu profile with the config pointer
  17610  *      and return the assigned profile id.
  17611  * Parameters:
  17612  *      unit - (IN) Unit number
  17613  *      type - (IN) Indicates ingress or egress mtu profile
  17614  *      config - (IN) configuration of the mtu profile
  17615  *      mtu_profile_id - (OUT) profile id
  17616  * Returns:
  17617  *      BCM_E_xxx
  17618  */
  17619 int
  17620 bcm_esw_tsn_mtu_profile_create(
  17621     int unit,
  17622     bcm_tsn_mtu_profile_type_t type,
  17623     bcm_tsn_mtu_config_t *config,
  17624     int *mtu_profile_id)
  17625 {
  17626     if (config == NULL || mtu_profile_id == NULL) {
  17627         return BCM_E_PARAM;
  17628     }
  17629 #if defined(BCM_TSN_SUPPORT)
  17630     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  17631         return bcmi_esw_tsn_mtu_profile_create(unit, type, config,
  17632                                                mtu_profile_id);
  17633     }
  17634 #endif /* BCM_TSN_SUPPORT */
  17635     return BCM_E_UNAVAIL;
  17636 }
  17637 
  17638 /*
  17639  * Function:
  17640  *      bcm_esw_tsn_mtu_profile_get
  17641  * Purpose:
  17642  *      Get mtu profile configuration
  17643  *      with the profile id.
  17644  * Parameters:
  17645  *      unit - (IN) Unit number
  17646  *      mtu_profile_id - (IN) Indicated the mtu profile entry
  17647  *      type - (OUT) Indicates ingress or egress mtu profile
  17648  *      config - (OUT) Configuration of the mtu profile
  17649  * Returns:
  17650  *      BCM_E_xxx
  17651  */
  17652 int
  17653 bcm_esw_tsn_mtu_profile_get(
  17654     int unit,
  17655     int mtu_profile_id,
  17656     bcm_tsn_mtu_profile_type_t *type,
  17657     bcm_tsn_mtu_config_t *config)
  17658 {
  17659     if (config == NULL || type == NULL) {
  17660         return BCM_E_PARAM;
  17661     }
  17662 #if defined(BCM_TSN_SUPPORT)
  17663     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  17664         return bcmi_esw_tsn_mtu_profile_get(unit, mtu_profile_id,
  17665                                             type, config);
  17666     }
  17667 #endif /* BCM_TSN_SUPPORT */
  17668     return BCM_E_UNAVAIL;
  17669 
  17670 }
  17671 
  17672 /*
  17673  * Function:
  17674  *      bcm_esw_tsn_mtu_profile_set
  17675  * Purpose:
  17676  *      Set mtu profile with the profile id
  17677  *      and config parameter.
  17678  * Parameters:
  17679  *      unit - (IN) Unit number
  17680  *      mtu_profile_id - (IN) Indicated the mtu profile entry
  17681  *      config - (IN) Configuration of the mtu profile
  17682  * Returns:
  17683  *      BCM_E_xxx
  17684  */
  17685 int
  17686 bcm_esw_tsn_mtu_profile_set(
  17687     int unit,
  17688     int mtu_profile_id,
  17689     bcm_tsn_mtu_config_t *config)
  17690 {
  17691     if (config == NULL) {
  17692         return BCM_E_PARAM;
  17693     }
  17694 #if defined(BCM_TSN_SUPPORT)
  17695     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  17696         return bcmi_esw_tsn_mtu_profile_set(unit, mtu_profile_id, config);
  17697     }
  17698 #endif /* BCM_TSN_SUPPORT */
  17699     return BCM_E_UNAVAIL;
  17700 }
  17701 
  17702 /*
  17703  * Function:
  17704  *      bcm_esw_tsn_mtu_profile_destroy
  17705  * Purpose:
  17706  *      Clear the mtu profile with the profile id
  17707  * Parameters:
  17708  *      unit - (IN) Unit number
  17709  *      mtu_profile_id - (IN) Indicated the mtu profile entry
  17710  * Returns:
  17711  *      BCM_E_xxx
  17712  */
  17713 int
  17714 bcm_esw_tsn_mtu_profile_destroy(
  17715     int unit,
  17716     int mtu_profile_id)
  17717 {
  17718 #if defined(BCM_TSN_SUPPORT)
  17719     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  17720         return bcmi_esw_tsn_mtu_profile_destroy(unit, mtu_profile_id);
  17721     }
  17722 #endif /* BCM_TSN_SUPPORT */
  17723     return BCM_E_UNAVAIL;
  17724 }
  17725 
  17726 /*
  17727  * Function:
  17728  *      bcm_tsn_mtu_profile_traverse
  17729  * Purpose:
  17730  *      Traverse the created match config.
  17731  * Parameters:
  17732  *      unit - (IN) Unit number
  17733  *      cb - (IN) Traverse call back function
  17734  *      user_data - (IN) User data
  17735  * Returns:
  17736  *      BCM_E_xxx
  17737  */
  17738 int
  17739 bcm_esw_tsn_mtu_profile_traverse(
  17740     int unit,
  17741     bcm_tsn_mtu_profile_traverse_cb cb,
  17742     void *user_data)
  17743 {
  17744     if (user_data == NULL || cb == NULL) {
  17745         return BCM_E_PARAM;
  17746     }
  17747 #if defined(BCM_TSN_SUPPORT)
  17748     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  17749         return bcmi_esw_tsn_mtu_profile_traverse(unit, cb, user_data);
  17750     }
  17751 #endif /* BCM_TSN_SUPPORT */
  17752     return BCM_E_UNAVAIL;
  17753 }
  17754 
  17755 /*
  17756  * Function:
  17757  *      bcm_esw_tsn_ingress_mtu_config_set
  17758  * Purpose:
  17759  *      Set ingress mtu profile source priority
  17760  *      with the config parameter.
  17761  * Parameters:
  17762  *      unit - (IN) Unit number
  17763  *      config - (IN) Configuration of the mtu profile
  17764  * Returns:
  17765  *      BCM_E_xxx
  17766  */
  17767 int
  17768 bcm_esw_tsn_ingress_mtu_config_set(
  17769     int unit,
  17770     bcm_tsn_ingress_mtu_config_t *config)
  17771 {
  17772     if (config == NULL) {
  17773         return BCM_E_PARAM;
  17774     }
  17775 #if defined(BCM_TSN_SUPPORT)
  17776     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  17777         return bcmi_esw_tsn_ingress_mtu_config_set(unit, config);
  17778     }
  17779 #endif /* BCM_TSN_SUPPORT */
  17780     return BCM_E_UNAVAIL;
  17781 }
  17782 
  17783 /*
  17784  * Function:
  17785  *      bcm_esw_tsn_ingress_mtu_config_get
  17786  * Purpose:
  17787  *      Get ingress mtu profile source priority
  17788  *      with the config parameter.
  17789  * Parameters:
  17790  *      unit - (IN) Unit number
  17791  *      config - (OUT) Configuration of the mtu profile
  17792  * Returns:
  17793  *      BCM_E_xxx
  17794  */
  17795 int
  17796 bcm_esw_tsn_ingress_mtu_config_get(
  17797     int unit,
  17798     bcm_tsn_ingress_mtu_config_t *config)
  17799 {
  17800     if (config == NULL) {
  17801         return BCM_E_PARAM;
  17802     }
  17803 #if defined(BCM_TSN_SUPPORT)
  17804     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  17805         return bcmi_esw_tsn_ingress_mtu_config_get(unit, config);
  17806     }
  17807 #endif /* BCM_TSN_SUPPORT */
  17808     return BCM_E_UNAVAIL;
  17809 }
  17810 /*
  17811  * Function:
  17812  *      bcm_esw_tsn_stu_profile_create
  17813  * Purpose:
  17814  *      Create stu profile with the config pointer
  17815  *      and return the assigned profile id.
  17816  * Parameters:
  17817  *      unit - (IN) Unit number
  17818  *      type - (IN) Indicates ingress or egress stu profile
  17819  *      config - (IN) configuration of the stu profile
  17820  *      stu_profile_id - (OUT) profile id
  17821  * Returns:
  17822  *      BCM_E_xxx
  17823  */
  17824 int
  17825 bcm_esw_tsn_stu_profile_create(
  17826     int unit,
  17827     bcm_tsn_stu_profile_type_t type,
  17828     bcm_tsn_stu_config_t *config,
  17829     int *stu_profile_id)
  17830 {
  17831     if (config == NULL || stu_profile_id == NULL) {
  17832         return BCM_E_PARAM;
  17833     }
  17834 #if defined(BCM_TSN_SUPPORT)
  17835     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  17836         return bcmi_esw_tsn_stu_profile_create(unit, type, config,
  17837                                                stu_profile_id);
  17838     }
  17839 #endif /* BCM_TSN_SUPPORT */
  17840     return BCM_E_UNAVAIL;
  17841 }
  17842 
  17843 /*
  17844  * Function:
  17845  *      bcm_esw_tsn_stu_profile_get
  17846  * Purpose:
  17847  *      Get stu profile configuration
  17848  *      with the profile id.
  17849  * Parameters:
  17850  *      unit - (IN) Unit number
  17851  *      stu_profile_id - (IN) Indicated the stu profile entry
  17852  *      type - (OUT) Indicates ingress or egress stu profile
  17853  *      config - (OUT) Configuration of the stu profile
  17854  * Returns:
  17855  *      BCM_E_xxx
  17856  */
  17857 int
  17858 bcm_esw_tsn_stu_profile_get(
  17859     int unit,
  17860     int stu_profile_id,
  17861     bcm_tsn_stu_profile_type_t *type,
  17862     bcm_tsn_stu_config_t *config)
  17863 {
  17864     if (config == NULL || type == NULL) {
  17865         return BCM_E_PARAM;
  17866     }
  17867 #if defined(BCM_TSN_SUPPORT)
  17868     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  17869         return bcmi_esw_tsn_stu_profile_get(unit, stu_profile_id,
  17870                                             type, config);
  17871     }
  17872 #endif /* BCM_TSN_SUPPORT */
  17873     return BCM_E_UNAVAIL;
  17874 
  17875 }
  17876 
  17877 /*
  17878  * Function:
  17879  *      bcm_esw_tsn_stu_profile_set
  17880  * Purpose:
  17881  *      Set stu profile with the profile id
  17882  *      and config parameter.
  17883  * Parameters:
  17884  *      unit - (IN) Unit number
  17885  *      stu_profile_id - (IN) Indicated the stu profile entry
  17886  *      config - (IN) Configuration of the stu profile
  17887  * Returns:
  17888  *      BCM_E_xxx
  17889  */
  17890 int
  17891 bcm_esw_tsn_stu_profile_set(
  17892     int unit,
  17893     int stu_profile_id,
  17894     bcm_tsn_stu_config_t *config)
  17895 {
  17896     if (config == NULL) {
  17897         return BCM_E_PARAM;
  17898     }
  17899 #if defined(BCM_TSN_SUPPORT)
  17900     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  17901         return bcmi_esw_tsn_stu_profile_set(unit, stu_profile_id, config);
  17902     }
  17903 #endif /* BCM_TSN_SUPPORT */
  17904     return BCM_E_UNAVAIL;
  17905 }
  17906 
  17907 /*
  17908  * Function:
  17909  *      bcm_esw_tsn_stu_profile_destroy
  17910  * Purpose:
  17911  *      Clear the stu profile with the profile id
  17912  * Parameters:
  17913  *      unit - (IN) Unit number
  17914  *      stu_profile_id - (IN) Indicated the stu profile entry
  17915  * Returns:
  17916  *      BCM_E_xxx
  17917  */
  17918 int
  17919 bcm_esw_tsn_stu_profile_destroy(
  17920     int unit,
  17921     int stu_profile_id)
  17922 {
  17923 #if defined(BCM_TSN_SUPPORT)
  17924     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  17925         return bcmi_esw_tsn_stu_profile_destroy(unit, stu_profile_id);
  17926     }
  17927 #endif /* BCM_TSN_SUPPORT */
  17928     return BCM_E_UNAVAIL;
  17929 }
  17930 
  17931 /*
  17932  * Function:
  17933  *      bcm_tsn_stu_profile_traverse
  17934  * Purpose:
  17935  *      Traverse the created match config.
  17936  * Parameters:
  17937  *      unit - (IN) Unit number
  17938  *      cb - (IN) Traverse call back function
  17939  *      user_data - (IN) User data
  17940  * Returns:
  17941  *      BCM_E_xxx
  17942  */
  17943 int
  17944 bcm_esw_tsn_stu_profile_traverse(
  17945     int unit,
  17946     bcm_tsn_stu_profile_traverse_cb cb,
  17947     void *user_data)
  17948 {
  17949     if (user_data == NULL || cb == NULL) {
  17950         return BCM_E_PARAM;
  17951     }
  17952 #if defined(BCM_TSN_SUPPORT)
  17953     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  17954         return bcmi_esw_tsn_stu_profile_traverse(unit, cb, user_data);
  17955     }
  17956 #endif /* BCM_TSN_SUPPORT */
  17957     return BCM_E_UNAVAIL;
  17958 }
  17959 
  17960 /*
  17961  * Function:
  17962  *      bcm_esw_tsn_ingress_stu_config_set
  17963  * Purpose:
  17964  *      Set ingress stu profile source priority
  17965  *      with the config parameter.
  17966  * Parameters:
  17967  *      unit - (IN) Unit number
  17968  *      config - (IN) Configuration of the stu profile
  17969  * Returns:
  17970  *      BCM_E_xxx
  17971  */
  17972 int
  17973 bcm_esw_tsn_ingress_stu_config_set(
  17974     int unit,
  17975     bcm_tsn_ingress_stu_config_t *config)
  17976 {
  17977     if (config == NULL) {
  17978         return BCM_E_PARAM;
  17979     }
  17980 #if defined(BCM_TSN_SUPPORT)
  17981     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  17982         return bcmi_esw_tsn_ingress_stu_config_set(unit, config);
  17983     }
  17984 #endif /* BCM_TSN_SUPPORT */
  17985     return BCM_E_UNAVAIL;
  17986 }
  17987 
  17988 /*
  17989  * Function:
  17990  *      bcm_esw_tsn_ingress_stu_config_get
  17991  * Purpose:
  17992  *      Get ingress stu profile source priority
  17993  *      with the config parameter.
  17994  * Parameters:
  17995  *      unit - (IN) Unit number
  17996  *      config - (OUT) Configuration of the stu profile
  17997  * Returns:
  17998  *      BCM_E_xxx
  17999  */
  18000 int
  18001 bcm_esw_tsn_ingress_stu_config_get(
  18002     int unit,
  18003     bcm_tsn_ingress_stu_config_t *config)
  18004 {
  18005     if (config == NULL) {
  18006         return BCM_E_PARAM;
  18007     }
  18008 #if defined(BCM_TSN_SUPPORT)
  18009     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
  18010         return bcmi_esw_tsn_ingress_stu_config_get(unit, config);
  18011     }
  18012 #endif /* BCM_TSN_SUPPORT */
  18013     return BCM_E_UNAVAIL;
  18014 }
  18015