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 (311708B)


      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  * Purpose: Manage chip specific functionality for TSN implementation on GH2.
      8  */
      9 
     10 #include <shared/bsl.h>
     11 #include <sal/core/time.h>
     12 #include <soc/drv.h>
     13 #include <soc/debug.h>
     14 #include <soc/mem.h>
     15 #include <soc/profile_mem.h>
     16 #include <soc/scache.h>
     17 #include <bcm/tsn.h>
     18 #include <bcm/port.h>
     19 #include <bcm/error.h>
     20 #include <bcm/types.h>
     21 #include <bcm_int/esw_dispatch.h>
     22 #include <bcm_int/esw/tsn.h>
     23 #include <bcm_int/esw/stack.h>
     24 #include <bcm_int/esw/hurricane3.h>
     25 #include <bcm_int/esw/greyhound2.h>
     26 #include <bcm_int/esw_dispatch.h>
     27 #ifdef BCM_WARM_BOOT_SUPPORT
     28 #include <soc/scache.h>
     29 #include <bcm_int/esw/switch.h>
     30 #endif /* BCM_WARM_BOOT_SUPPORT */
     31 
     32 #if defined(BCM_GREYHOUND2_SUPPORT) && defined(BCM_TSN_SUPPORT)
     33 
     34 #if defined(BCM_TSN_SR_SUPPORT)
     35 /*
     36  * SR Auto Learn management: HW platform specific constants
     37  */
     38 
     39 /* TX & RX flow index 0 is invalid, thus only 4095 are available */
     40 #define GH2_SR_AUTO_LEARN_TX_FLOW_SIZE        (4095)
     41 #define GH2_SR_AUTO_LEARN_RX_FLOW_SIZE        (4095)
     42 
     43 /*
     44  * Default value (reset value) for Auto Learn Group Ports
     45  * Note:
     46  * 0 is not a INVALID value of L2MC
     47  * but there are two HW fields ING_SR_ENABLE & ING_SR_PORT_ROLE to make
     48  * sure the port is SR redudant port.
     49  */
     50 #define GH2_SR_AUTO_LEARN_GROUP_PORTS_L2MC_DEFAULT_VALUE   (0)
     51 #define GH2_SR_AUTO_LEARN_GROUP_PORTS_MACP_DEFAULT_VALUE   (0)
     52 
     53 /*
     54  * SR flow management: HW platform specific constants
     55  */
     56 #define TSN_SRFLOWS_RX_ACCEPT_SIZE_MIN      512
     57 #define TSN_SRFLOWS_RX_ACCEPT_SIZE_MAX      65536
     58 #define TSN_SRFLOWS_RX_ACCEPT_POWER_MIN     9
     59 #define TSN_SRFLOWS_RX_ACCEPT_POWER_MAX     16
     60 #define TSN_SRFLOWS_RX_WINDOW_SIZE_MIN      64
     61 #define TSN_SRFLOWS_RX_WINDOW_SIZE_MAX      4096
     62 #define TSN_SRFLOWS_RX_WINDOW_POWER_MIN     6
     63 #define TSN_SRFLOWS_RX_WINDOW_POWER_MAX     12
     64 #define TSN_SRFLOWS_RX_SNPOOL_SIZE_MIN      64
     65 #define TSN_SRFLOWS_RX_SNPOOL_SIZE_MAX      1024
     66 #define TSN_SRFLOWS_RX_SNPOOL_POWER_MIN     6
     67 #define TSN_SRFLOWS_RX_SNPOOL_POWER_MAX     10
     68 #define TSN_SRFLOWS_RX_SNPOOL_SIZE_COUNT    \
     69     (TSN_SRFLOWS_RX_SNPOOL_POWER_MAX - TSN_SRFLOWS_RX_SNPOOL_POWER_MIN + 1)
     70 #define TSN_SRFLOWS_RX_SNPOOL_IDX_MAX       \
     71     (TSN_SRFLOWS_RX_SNPOOL_SIZE_COUNT - 1)
     72 #define TSN_SRFLOWS_RX_SN_HIST_POOLS        4
     73 #define TSN_SRFLOWS_RX_SN_HIST_POOL_SIZE    1024
     74 #define TSN_SRFLOWS_RX_SN_HIST_POOL_POWER   10
     75 #define TSN_SRFLOWS_RX_SN_HIST_MEM_SIZE     256
     76 #define TSN_SRFLOWS_RX_SN_HIST_MEM_POWER    8
     77 #define TSN_SRFLOWS_RX_SN_HIST_SUB_INDEX    \
     78     (TSN_SRFLOWS_RX_SN_HIST_POOL_POWER - TSN_SRFLOWS_RX_SN_HIST_MEM_POWER)
     79 #define TSN_SRFLOWS_RX_SN_HIST_SUB_POOLS    4
     80 #define TSN_SRFLOWS_RX_SN_HIST_BLOCK_SIZE   64
     81 #define TSN_SRFLOWS_RX_AGE_TIME_MAX         32768
     82 #define TSN_SRFLOWS_SEQNUM_VALUE_MAX        65535
     83 #define TSN_SRFLOWS_FLOWID_TX_MASK          0x1000
     84 #define TSN_SRFLOWS_DEFAULT_NEXT_SN         0
     85 
     86 /* SR flow management: sequence number slice entry */
     87 typedef struct tsn_sr_seqnum_slice_s {
     88     int index;                              /* Pool index */
     89     int entry;                              /* Entry in the pool */
     90     int offset;                             /* Offset in the entry */
     91     int power;                              /* size in power of bits */
     92     struct tsn_sr_seqnum_slice_s *next;
     93 } tsn_sr_seqnum_slice_t;
     94 
     95 /* SR flow management bookkeeping */
     96 typedef struct gh2_tsn_sr_flows_bkinfo_s {
     97     /* Max number of flows (for efficiency) */
     98     int max_flows_rx;
     99     int max_flows_tx;
    100 
    101     /* seqnum history slice pools */
    102     tsn_sr_seqnum_slice_t *sn_pools[TSN_SRFLOWS_RX_SN_HIST_POOLS]
    103                                    [TSN_SRFLOWS_RX_SNPOOL_SIZE_COUNT];
    104     tsn_sr_seqnum_slice_t *sn_entries_avail;
    105     tsn_sr_seqnum_slice_t *sn_entries_allocated;
    106     sal_mutex_t snpool_mutex;
    107 
    108 } gh2_tsn_sr_flows_bkinfo_t;
    109 
    110 #endif /* BCM_TSN_SR_SUPPORT */
    111 
    112 /* Structure definition for GH2 MTU profile memory bookkeeping information */
    113 typedef struct gh2_tsn_mtu_bk_info_s {
    114     soc_profile_mem_t *mtu_profile[bcmTsnMtuProfileTypeCount];
    115     sal_mutex_t mutex;
    116 } gh2_tsn_mtu_bk_info_t;
    117 
    118 /* Structure definition for GH2 STU profile memory bookkeeping information */
    119 typedef struct gh2_tsn_stu_bk_info_s {
    120     soc_profile_mem_t *stu_profile[bcmTsnStuProfileTypeCount];
    121     sal_mutex_t mutex;
    122 } gh2_tsn_stu_bk_info_t;
    123 
    124 /* Structure definition for GH2 PRP-forwarding bookkeeping information */
    125 typedef struct gh2_tsn_prp_forwarding_bk_info_s {
    126     int prp_forwarding_enable;
    127     bcm_field_group_t prp_redirect_group;
    128     bcm_port_t  prp_redirect_port;
    129     bcm_gport_t prp_redirect_gport;
    130     int switch_init;
    131     sal_mutex_t mutex;
    132 } gh2_tsn_prp_forwarding_bk_info_t;
    133 
    134 typedef struct gh2_tsn_events_bkinfo_s {
    135     bcmi_esw_tsn_flow_event_notify_cb  gh2_flow_event_notify;
    136     bcmi_esw_tsn_cnt_exceed_notify_cb  gh2_cnt_exceed_notify;
    137     sal_mutex_t event_mutex;
    138     int         max_rx_flows;
    139     SHR_BITDCL  *active_rx_fbmp;    /* Current active rx flows */
    140     int         active_rx_fbmp_min;
    141     int         active_rx_fbmp_max;
    142     SHR_BITDCL  *wrong_lana_fbmp;   /* Watched flows for wrong lan events */
    143     SHR_BITDCL  *wrong_lanb_fbmp;   /* Watched flows for wrong lan events */
    144     SHR_BITDCL  *sn_reset_fbmp;     /* Watched flows for sn window reset */
    145     int         wrong_lana_min_cd;  /* Min count down value of wrong lan a */
    146     int         wrong_lanb_min_cd; /* Min count down value of wrong lan b */
    147     int         sn_reset_min_cd; /* Min count down value of sn reset */
    148     uint32      window_reset_mode;
    149     uint32      ageout_tick_ms;
    150     uint32      age_enable;
    151     sal_usecs_t ptime; /* previous time */
    152     int         wla_tick;
    153     int         wlb_tick;
    154     int         reset_tick;
    155     int         wla_mask;
    156     int         wlb_mask;
    157 } gh2_tsn_events_bkinfo_t;
    158 
    159 /*
    160  * TSN flow management: HW platform specific constants
    161  */
    162 #define TSN_FLOWS_MAX_NUM_OF_FLOWS                  4095
    163 
    164 /* Initialization flag for GH2 TSN bookkeeping info structure */
    165 static int gh2_tsn_bkinfo_initialized = 0;
    166 
    167 /* Structure definition for GH2 TSN bookkeeping info */
    168 typedef struct gh2_tsn_bkinfo_s {
    169     gh2_tsn_mtu_bk_info_t gh2_mtu_bk_info;
    170     gh2_tsn_stu_bk_info_t gh2_stu_bk_info;
    171     gh2_tsn_prp_forwarding_bk_info_t gh2_prp_forwarding_bk_info;
    172 #if defined(BCM_TSN_SR_SUPPORT)
    173     gh2_tsn_sr_flows_bkinfo_t sr_flows;
    174 #endif /* BCM_TSN_SR_SUPPORT */
    175     gh2_tsn_events_bkinfo_t tsn_events;
    176 } gh2_tsn_bkinfo_t;
    177 
    178 /* GH2 TSN bookkeeping info */
    179 STATIC gh2_tsn_bkinfo_t *gh2_tsn_bkinfo[BCM_MAX_NUM_UNITS];
    180 
    181 /* Check if TSN bookkeeping info structure intialized */
    182 #define TSN_BKINFO_IS_INIT(_unit_)                                        \
    183     do {                                                                  \
    184         if (!SOC_UNIT_VALID(_unit_)) {                                    \
    185             return BCM_E_UNIT;                                            \
    186         }                                                                 \
    187         if (gh2_tsn_bkinfo[(_unit_)] == NULL) {                           \
    188             LOG_ERROR(BSL_LS_BCM_TSN,                                     \
    189                       (BSL_META_U((_unit_),                               \
    190                                   "TSN Error: chip bookkeeping info not " \
    191                                   "initialized\n")));                     \
    192             return (BCM_E_INIT);                                          \
    193         }                                                                 \
    194     } while (0)
    195 
    196 /* Function Enter/Leave Tracing */
    197 #define GH2_TSN_FUNCTION_TRACE(_u_, _str_)                                    \
    198     do {                                                                      \
    199         LOG_DEBUG(BSL_LS_BCM_TSN,                                             \
    200                     (BSL_META_U((_u_),                                        \
    201                                 "%s: " _str_ "\n"), __FUNCTION__));           \
    202     } while (0)
    203 
    204 /* For TSN bookkeeping access */
    205 #define TSN_BKINFO(_u_) gh2_tsn_bkinfo[_u_]
    206 
    207 /* Check if TSN MTU bookkeeping info structure initialized */
    208 #define TSN_MTU_BKINFO_IS_INIT(_unit_, _type_)                                \
    209     do {                                                                      \
    210         TSN_BKINFO_IS_INIT(_unit_);                                           \
    211         if ((_type_) != bcmTsnMtuProfileTypeIngress &&                        \
    212             (_type_) != bcmTsnMtuProfileTypeEgress) {                         \
    213             return BCM_E_PARAM;                                               \
    214         }                                                                     \
    215         if ((NULL ==                                                          \
    216             gh2_tsn_bkinfo[(_unit_)]->gh2_mtu_bk_info.mtu_profile[_type_])) { \
    217             LOG_ERROR(BSL_LS_BCM_TSN,                                         \
    218                       (BSL_META_U((_unit_),                                   \
    219                                   "TSN Error: MTU bookkeeping info not "      \
    220                                   "initialized\n")));                         \
    221             return BCM_E_INIT;                                                \
    222         }                                                                     \
    223     } while (0)
    224 
    225 
    226 /* TSN event management: bookkeeping access */
    227 #define EVENTS_BKINFO(_u_)         (&TSN_BKINFO(_u_)->tsn_events)
    228 
    229 /* TSN event management: mutex  */
    230 #define EVENT_MGMT_LOCK(_u_)                                            \
    231     sal_mutex_take(EVENTS_BKINFO(unit)->event_mutex, sal_mutex_FOREVER)
    232 #define EVENT_MGMT_UNLOCK(_u_)                                          \
    233     sal_mutex_give(EVENTS_BKINFO(unit)->event_mutex)
    234 
    235 /* MTU Bookkeeping Information lock/unlock */
    236 #define MTU_BKINFO_LOCK(_u_) \
    237                sal_mutex_take(gh2_tsn_bkinfo[(_u_)]->gh2_mtu_bk_info.mutex, \
    238                    sal_mutex_FOREVER)
    239 
    240 #define MTU_BKINFO_UNLOCK(_u_) \
    241                sal_mutex_give(gh2_tsn_bkinfo[(_u_)]->gh2_mtu_bk_info.mutex)
    242 
    243 /* Check if TSN STU bookkeeping info structure initialized */
    244 #define TSN_STU_BKINFO_IS_INIT(_unit_, _type_)                                \
    245     do {                                                                      \
    246         TSN_BKINFO_IS_INIT(_unit_);                                           \
    247         if ((_type_) != bcmTsnStuProfileTypeIngress &&                        \
    248             (_type_) != bcmTsnStuProfileTypeEgress) {                         \
    249             return BCM_E_PARAM;                                               \
    250         }                                                                     \
    251         if ((NULL ==                                                          \
    252             gh2_tsn_bkinfo[(_unit_)]->gh2_stu_bk_info.stu_profile[_type_])) { \
    253             LOG_ERROR(BSL_LS_BCM_TSN,                                         \
    254                       (BSL_META_U((_unit_),                                   \
    255                                   "TSN Error: STU bookkeeping info not "      \
    256                                   "initialized\n")));                         \
    257             return BCM_E_INIT;                                                \
    258         }                                                                     \
    259     } while (0)
    260 
    261 /* STU Bookkeeping Information lock/unlock */
    262 #define STU_BKINFO_LOCK(_u_) \
    263                sal_mutex_take(gh2_tsn_bkinfo[(_u_)]->gh2_stu_bk_info.mutex, \
    264                    sal_mutex_FOREVER)
    265 
    266 #define STU_BKINFO_UNLOCK(_u_) \
    267                sal_mutex_give(gh2_tsn_bkinfo[(_u_)]->gh2_stu_bk_info.mutex)
    268 
    269 /* GH2 support 8 internal priority for MTU/STU profile ID */
    270 #define EGRESS_MTU_STU_INT_PRI_NUM 8
    271 
    272 /* Egress MTU & STU profile ID encode value */
    273 #define EGR_MTU_STU_PROFILE_ID_ENCODE 0x01000000
    274 
    275 /* Refer to GH2 EGR_MTU_CHECK/EGR_STU_CHECK (66 ports) */
    276 #define GH2_LOGIC_PORT_MAX_NUM 66
    277 
    278 /* MTU profile memory information */
    279 STATIC const soc_mem_t gh2_mtu_profile_mem[bcmTsnMtuProfileTypeCount] =
    280                            {MTU_PROFILEm,
    281                             EGR_MTU_PROFILEm};
    282 /* STU profile memory information */
    283 STATIC const soc_mem_t gh2_stu_profile_mem[bcmTsnStuProfileTypeCount] =
    284                            {STU_PROFILEm,
    285                             EGR_STU_PROFILEm};
    286 
    287 /*
    288  * Definitions for Modified-PRP port's custom header(32 bits)
    289  *  +-------------------------------+
    290  *  |      Ethertype (16 bits)      |
    291  *  +--------------+----------------+
    292  *  | Non_PRP Flag | Port (15 bits) |
    293  *  +--------------+----------------+
    294  *
    295  *  Field location :
    296  *  - Port : b0~b14
    297  *  - Non_PRP Flag : b15
    298  *  - Ethertype : b16~b31
    299  *
    300  *  Note :
    301  *  - Macros defined below for the term of "CH" means "CustomHeader"
    302  */
    303 #define PRP_FORWARDING_CH_HEADER_MASK        0xffffffff
    304 #define PRP_FORWARDING_CH_ETHERTYPE_MASK     0xffff
    305 #define PRP_FORWARDING_CH_ETHERTYPE_OFFSET   16
    306 #define PRP_FORWARDING_CH_NON_PRP_OFFSET     15
    307 #define PRP_FORWARDING_CH_PORT_MASK          0x7fff
    308 #define PRP_FORWARDING_CH_PORT_OFFSET        0
    309 
    310 /* SW defined a non-common value for Modified-PRP(loopback) port */
    311 #define PRP_FORWARDING_CH_ETHERTYPE          0x10bc
    312 
    313 #define PRP_FORWARDING_CH_ENCAP_VALUE(_non_prp_, _port_)                      \
    314         ((PRP_FORWARDING_CH_ETHERTYPE << PRP_FORWARDING_CH_ETHERTYPE_OFFSET) |\
    315          (((_non_prp_) ? 1 : 0) << PRP_FORWARDING_CH_NON_PRP_OFFSET) |        \
    316          (((_port_) & PRP_FORWARDING_CH_PORT_MASK) <<                         \
    317           PRP_FORWARDING_CH_PORT_OFFSET))
    318 
    319 /* PRP-forwarding Bookkeeping Information lock/unlock */
    320 #define PRP_FORWARDING_BKINFO_LOCK(_u_)                             \
    321                sal_mutex_take(gh2_tsn_bkinfo[(_u_)]->               \
    322                gh2_prp_forwarding_bk_info.mutex, sal_mutex_FOREVER)
    323 
    324 #define PRP_FORWARDING_BKINFO_UNLOCK(_u_)                           \
    325                sal_mutex_give(gh2_tsn_bkinfo[(_u_)]->               \
    326                gh2_prp_forwarding_bk_info.mutex)
    327 
    328 #define PRP_FORWARDING_NEED_PRP_SETTING(_config_)           \
    329         (((bcmTsnSrPortTypeNone != (_config_).port_type) && \
    330           (bcmTsnSrPortTypePrp == (_config_).port_type ||   \
    331            bcmTsnSrPortModeInterworkingPrp == (_config_).port_mode)) ? 1 : 0)
    332 
    333 #define PRP_FORWARDING_NEED_EGRESS_MASK_SETTING(_config_)            \
    334         ((bcmTsnSrPortTypeNone != (_config_).port_type &&            \
    335           bcmTsnSrPortTypePrp != (_config_).port_type &&             \
    336           bcmTsnSrPortTypeDot1cb != (_config_).port_type &&          \
    337           bcmTsnSrPortModeInterworkingPrp != (_config_).port_mode && \
    338           0 == (_config_).mac_da_flows) ? 1 : 0)
    339 
    340 #define PRP_FORWARDING_REDIRECT_GROUP_INVALID    (0)
    341 
    342 #define PRP_FORWARDING_ENABLE(_u_)\
    343         (TSN_BKINFO(_u_)->gh2_prp_forwarding_bk_info.prp_forwarding_enable)
    344 #define PRP_FORWARDING_SWITCH_INIT(_u_)\
    345         (TSN_BKINFO(_u_)->gh2_prp_forwarding_bk_info.switch_init)
    346 #define PRP_FORWARDING_REDIRECT_GROUP(_u_)\
    347         (TSN_BKINFO(_u_)->gh2_prp_forwarding_bk_info.prp_redirect_group)
    348 #define PRP_FORWARDING_REDIRECT_PORT(_u_)\
    349         (TSN_BKINFO(_u_)->gh2_prp_forwarding_bk_info.prp_redirect_port)
    350 #define PRP_FORWARDING_REDIRECT_GPORT(_u_)\
    351         (TSN_BKINFO(_u_)->gh2_prp_forwarding_bk_info.prp_redirect_gport)
    352 
    353 #define PRP_FORWARDING_ERROR_RETURN(_op_)                      \
    354         do {                                                   \
    355             int _rv_ = (_op_);                                 \
    356             if (BCM_FAILURE(_rv_)) {                           \
    357                 return (_rv_);                                 \
    358             }                                                  \
    359         } while (0)
    360 
    361 #define PRP_FORWARDING_ERROR_RETURN_WITH_CLEAN(_op_, _extra_clean_)       \
    362         do {                                                              \
    363             int _rv_ = (_op_);                                            \
    364             if (BCM_FAILURE(_rv_)) {                                      \
    365                 (_extra_clean_);                                          \
    366                 return (_rv_);                                            \
    367             }                                                             \
    368         } while (0)
    369 
    370 #define PRP_FORWARDING_CLEAN_ERROR_RETURN(_op_)                           \
    371         do {                                                              \
    372             int _rv_ = (_op_);                                            \
    373             if (BCM_FAILURE(_rv_)) {                                      \
    374                 LOG_WARN(BSL_LS_BCMAPI_TSN,                               \
    375                          (BSL_META_U(                                     \
    376                               unit,                                       \
    377                               "prp_forwarding clean failed\n")));         \
    378                 return;                                                   \
    379             }                                                             \
    380         } while (0)
    381 
    382 #define PRP_FORWARDING_CREATE_ERROR_RETURN(_op_)                              \
    383         do {                                                                  \
    384             int _rv_ = (_op_);                                                \
    385             if (BCM_FAILURE(_rv_)) {                                          \
    386                 bcmi_gh2_tsn_sr_port_prp_forwarding_destroy(unit, prp_port);  \
    387                 return (_rv_);                                                \
    388             }                                                                 \
    389         } while (0)
    390 
    391 #define PRP_FORWARDING_DESTROY_ERROR_RETURN(_op_)                         \
    392         do {                                                              \
    393             int _rv_ = (_op_);                                            \
    394             if (BCM_FAILURE(_rv_)) {                                      \
    395                 LOG_WARN(BSL_LS_BCMAPI_TSN,                               \
    396                          (BSL_META_U(                                     \
    397                               unit,                                       \
    398                               "prp_forwarding destroy port %d failed\n"), \
    399                               prp_port));                                 \
    400                 return;                                                   \
    401             }                                                             \
    402         } while (0)
    403 
    404 #define PRP_FORWARDING_DESTROY_ERROR_RETURN_WITH_CLEAN(_op_, _extra_clean_) \
    405         do {                                                                \
    406             int _rv_ = (_op_);                                              \
    407             if (BCM_FAILURE(_rv_)) {                                        \
    408                 (_extra_clean_);                                            \
    409                 LOG_WARN(BSL_LS_BCMAPI_TSN,                                 \
    410                          (BSL_META_U(                                       \
    411                               unit,                                         \
    412                               "prp_forwarding destroy port %d failed\n"),   \
    413                               prp_port));                                   \
    414                 return;                                                     \
    415             }                                                               \
    416         } while (0)
    417 
    418 #if defined(BCM_TSN_SR_SUPPORT)
    419 
    420 /* SR flow management: quick array to get power of 2 */
    421 static const int tsn_math_powers[] = {
    422     1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096,
    423     8192, 16384, 32768, 65536
    424 };
    425 
    426 /* SR flow management: SR RX flow seqnum history field names */
    427 static const soc_field_t tsn_flow_sr_hist_indexs[] = {
    428     SN_HISTORY_INDEX_1f, SN_HISTORY_INDEX_2f,
    429     SN_HISTORY_INDEX_3f, SN_HISTORY_INDEX_4f
    430 };
    431 static const soc_field_t tsn_flow_sr_hist_offsets[] = {
    432     SN_HISTORY_OFFSET_1f, SN_HISTORY_OFFSET_2f,
    433     SN_HISTORY_OFFSET_3f, SN_HISTORY_OFFSET_4f
    434 };
    435 static const soc_field_t tsn_flow_sr_hist_sizes[] = {
    436     SN_HISTORY_SIZE_1f, SN_HISTORY_SIZE_2f,
    437     SN_HISTORY_SIZE_3f, SN_HISTORY_SIZE_4f
    438 };
    439 
    440 /* SR flow management: SR RX seqnum history pool table names */
    441 static const soc_mem_t tsn_flow_sr_hist_pools[] = {
    442     SR_SN_HISTORY_0m,
    443     SR_SN_HISTORY_1m,
    444     SR_SN_HISTORY_2m,
    445     SR_SN_HISTORY_3m,
    446     SR_SN_HISTORY_4m,
    447     SR_SN_HISTORY_5m,
    448     SR_SN_HISTORY_6m,
    449     SR_SN_HISTORY_7m,
    450     SR_SN_HISTORY_8m,
    451     SR_SN_HISTORY_9m,
    452     SR_SN_HISTORY_10m,
    453     SR_SN_HISTORY_11m,
    454     SR_SN_HISTORY_12m,
    455     SR_SN_HISTORY_13m,
    456     SR_SN_HISTORY_14m,
    457     SR_SN_HISTORY_15m
    458 };
    459 
    460 /* SR flow management: helper macros for flow ID conversion */
    461 #define TSN_SRFLOWS_IDX_TO_HW_ID(_tx_, _idx_)                               \
    462     (((_idx_) + 1) | ((_tx_) ? TSN_SRFLOWS_FLOWID_TX_MASK : 0))
    463 #define TSN_SRFLOWS_HW_ID_IS_TX(_id_)                                       \
    464     (((_id_) & TSN_SRFLOWS_FLOWID_TX_MASK) ? 1 : 0)
    465 #define TSN_SRFLOWS_HW_ID_TO_IDX(_id_)                                      \
    466     (((_id_) & (~TSN_SRFLOWS_FLOWID_TX_MASK)) - 1)
    467 
    468 /* SR flow management: bookkeeping access (for easier porting) */
    469 #define SRFLOWS_BKINFO(_u_)         (TSN_BKINFO(_u_)->sr_flows)
    470 
    471 /* SR flow management: convenient macro for seqnum pool protecting */
    472 #define SRFLOWS_SNPOOL_LOCK(_u_)                                            \
    473     sal_mutex_take(SRFLOWS_BKINFO(unit).snpool_mutex, sal_mutex_FOREVER)
    474 #define SRFLOWS_SNPOOL_UNLOCK(_u_)                                          \
    475     sal_mutex_give(SRFLOWS_BKINFO(unit).snpool_mutex)
    476 
    477 /* SR flow management: convenient macro to access seqnum slice pools */
    478 #define SR_SNPOOL(_idx, _pow)       SRFLOWS_BKINFO(unit).sn_pools[_idx][_pow]
    479 
    480 /* SR flow management: helper macro to get a slice from pool */
    481 #define TSN_SRFLOW_GET_SN_SLICE(_sn, _idx, _pow)                            \
    482     do {                                                                    \
    483         (_sn) = SR_SNPOOL((_idx), (_pow));                                  \
    484         if ((_sn) != NULL) {                                                \
    485             SR_SNPOOL((_idx), (_pow)) = (_sn)->next;                        \
    486             (_sn)->next = NULL;                                             \
    487         }                                                                   \
    488     } while (0)
    489 
    490 /* Convenient macro: check whether a number is power of 2 */
    491 #define TSN_IS_POWER_OF_2(_n_)              (!((_n_) & ((_n_) - 1)))
    492 
    493 /* Convenient macro: get log2 for a non-zero power-of-2 number */
    494 #define TSN_GET_LOG2(_n_, _power_)                                          \
    495     do {                                                                    \
    496         unsigned int _num = (unsigned int)(_n_);                            \
    497         for ((_power_) = -1; _num; (_power_)++) {                           \
    498             _num >>= 1;                                                     \
    499         }                                                                   \
    500     } while (0)
    501 
    502 /*
    503  * SR Auto Learn :
    504  * flow ID is 13-bit (1st lead bit is global for TX and RX)
    505  * Doing 12-bit mask for NEXT_FLOW_ID
    506  */
    507 #define AUTO_LEARN_FLOW_ID_TO_HW_FLOW_ID(_idx_)                        \
    508         ((_idx_) & 0x0FFF)
    509 #define AUTO_LEARN_HW_FLOW_ID_TO_FLOW_ID(_type_, _idx_)                \
    510         (((_type_) == bcmi_sr_auto_learn_flow_tx ? 0x1000 : 0x0) |     \
    511          ((_idx_) & 0x0FFF))
    512 
    513 #endif /* BCM_TSN_SR_SUPPORT */
    514 
    515 /* TSN flow management: helper macros for flow ID conversion */
    516 #define TSN_FLOWS_IDX_TO_HW_ID(_idx_)               ((_idx_) + 1)
    517 #define TSN_FLOWS_HW_ID_TO_IDX(_id_)                ((_id_) - 1)
    518 
    519 STATIC int
    520 bcmi_gh2_tsn_mtu_profile_decode(
    521     int unit,
    522     int mtu_profile_id,
    523     bcm_tsn_mtu_profile_type_t *type,
    524     int *index);
    525 
    526 STATIC int
    527 bcmi_gh2_tsn_mtu_profile_encode(
    528     int unit,
    529     int index,
    530     bcm_tsn_mtu_profile_type_t type,
    531     int *mtu_profile_id);
    532 
    533 #if defined(BCM_TSN_SR_SUPPORT)
    534 
    535 /* SR flow mgmt - free seqnum history pool */
    536 STATIC int
    537 bcmi_gh2_tsn_sr_flows_seqnum_slice_free(
    538     int unit,
    539     bcmi_tsn_sr_seqnum_slice_t slice)
    540 {
    541     tsn_sr_seqnum_slice_t *org = (tsn_sr_seqnum_slice_t *)slice;
    542     tsn_sr_seqnum_slice_t *sn, *sn2, *prev;
    543     int entries;
    544     int pow;
    545     int offset;
    546     int merged;
    547     int i;
    548 
    549     /* parameter check */
    550     TSN_BKINFO_IS_INIT(unit);
    551     if (!soc_feature(unit, soc_feature_tsn_sr)) {
    552         return (BCM_E_UNAVAIL);
    553     }
    554     if (NULL == slice) {
    555         return BCM_E_PARAM;
    556     }
    557 
    558     /* validate it first before putting back into the pools */
    559     i = 0;
    560     entries = soc_mem_index_count(unit, SR_SN_HISTORY_0m);
    561     for (sn = org; sn != NULL; sn = sn->next) {
    562         /* The total number of chained slices < number of pools */
    563         i++;
    564         if (i > TSN_SRFLOWS_RX_SN_HIST_POOLS) {
    565             return BCM_E_PARAM;
    566         }
    567 
    568         /* Validate item values */
    569         if (sn->index < 0 || sn->index >= TSN_SRFLOWS_RX_SN_HIST_POOLS) {
    570             return BCM_E_PARAM;
    571         }
    572         if (sn->power < TSN_SRFLOWS_RX_SNPOOL_POWER_MIN ||
    573             sn->power > TSN_SRFLOWS_RX_SNPOOL_POWER_MAX) {
    574             return BCM_E_PARAM;
    575         }
    576         if (sn->offset < 0 || sn->offset >= TSN_SRFLOWS_RX_SNPOOL_SIZE_MAX) {
    577             return BCM_E_PARAM;
    578         }
    579         if (sn->offset % tsn_math_powers[sn->power]) {
    580             /* offset should be multiples of the slice size */
    581             return BCM_E_PARAM;
    582         }
    583         if (sn->entry < 0 || sn->entry >= entries) {
    584             return BCM_E_PARAM;
    585         }
    586     }
    587 
    588     /* Put back to the pools one by one */
    589     while (org != NULL) {
    590         /* Handle one slice at a time */
    591         sn = org;
    592         org = sn->next;
    593         sn->next = NULL;
    594 
    595         /* Start putting back the slice */
    596         SRFLOWS_SNPOOL_LOCK(unit);
    597 
    598         /* See if we can find another half and merge into a bigger one */
    599         pow = sn->power - TSN_SRFLOWS_RX_SNPOOL_POWER_MIN;
    600         for (i = pow; i < TSN_SRFLOWS_RX_SNPOOL_IDX_MAX; i++) {
    601             /*
    602              * Calculate the offset value for the slice of another half
    603              * Another offset = this_offset XOR slice_size
    604              * (offset must be multiples of the slice_size)
    605              */
    606             offset = sn->offset ^ tsn_math_powers[sn->power];
    607 
    608             /* Find the slice with the offset within the same entry */
    609             merged = 0;
    610             prev = NULL;
    611             for (sn2 = SR_SNPOOL(sn->index, i); sn2 != NULL; sn2 = sn2->next) {
    612                 if (sn2->offset == offset) {
    613                     if (sn2->entry == sn->entry) {
    614 
    615                         /* Found. Remove it from the pool */
    616                         if (prev == NULL) {
    617                             SR_SNPOOL(sn->index, i) = sn2->next;
    618                         } else {
    619                             prev->next = sn2->next;
    620                         }
    621 
    622                         /* Change it to be next size with offset corrected */
    623                         sn2->power++;
    624                         sn2->offset &= ~tsn_math_powers[sn->power];
    625                         sn2->next = NULL;
    626 
    627                         /* Free the original one */
    628                         sn->next = SRFLOWS_BKINFO(unit).sn_entries_avail;
    629                         SRFLOWS_BKINFO(unit).sn_entries_avail = sn;
    630 
    631                         /* This becomes the one to return to the pool */
    632                         sn = sn2;
    633                         pow = sn2->power - TSN_SRFLOWS_RX_SNPOOL_POWER_MIN;
    634                         merged = 1;
    635                         break;
    636                     }
    637                 }
    638                 prev = sn2;
    639             }
    640             /*
    641              * If no merge happens, just return it to the pool.
    642              * Otherwise try to merge in the next size level.
    643              */
    644             if (!merged) {
    645                 break;
    646             }
    647         }
    648 
    649         /* Return the slice to the pool */
    650         sn->next = SR_SNPOOL(sn->index, pow);
    651         SR_SNPOOL(sn->index, pow) = sn;
    652 
    653         /* Done this one */
    654         SRFLOWS_SNPOOL_UNLOCK(unit);
    655     }
    656 
    657     return BCM_E_NONE;
    658 }
    659 
    660 /* SR flow mgmt - allocate seqnum history pool */
    661 STATIC int
    662 bcmi_gh2_tsn_sr_flows_seqnum_slice_alloc(
    663     int unit,
    664     int winsize,
    665     bcmi_tsn_sr_seqnum_slice_t *slice)
    666 {
    667     tsn_sr_seqnum_slice_t *sn, *sn2, *sn3, *sn4;
    668     int power, pow;
    669     int i, j, k, m;
    670 
    671     /* For convenience */
    672     static const int num_pools = TSN_SRFLOWS_RX_SN_HIST_POOLS;
    673 
    674     /* parameter check */
    675     TSN_BKINFO_IS_INIT(unit);
    676     if (!soc_feature(unit, soc_feature_tsn_sr)) {
    677         return (BCM_E_UNAVAIL);
    678     }
    679     if (NULL == slice || winsize <= 0 || !TSN_IS_POWER_OF_2(winsize)) {
    680         return BCM_E_PARAM;
    681     }
    682 
    683     /* Validate and correct size */
    684     TSN_GET_LOG2(winsize, power);
    685     if (power == 0) {
    686         /* Special case: use 64-bit slice for 1-bit window size */
    687         power = TSN_SRFLOWS_RX_WINDOW_POWER_MIN;
    688     }
    689     if (power < TSN_SRFLOWS_RX_WINDOW_POWER_MIN ||
    690         power > TSN_SRFLOWS_RX_WINDOW_POWER_MAX) {
    691         return BCM_E_PARAM;
    692     }
    693     pow = power - TSN_SRFLOWS_RX_WINDOW_POWER_MIN; /* pool slot index */
    694 
    695     /* Start finding matching slices */
    696     SRFLOWS_SNPOOL_LOCK(unit);
    697 
    698     /*
    699      * 1. Check for exact match
    700      *    Only applies when the window size is one of the slice size
    701      */
    702     if (pow <= TSN_SRFLOWS_RX_SNPOOL_IDX_MAX) {
    703         for (i = 0; i < num_pools; i++) {
    704             if (SR_SNPOOL(i, pow) != NULL) {
    705                 /* Got one exact match slice */
    706                 TSN_SRFLOW_GET_SN_SLICE(sn, i, pow);
    707                 *slice = (bcmi_tsn_sr_seqnum_slice_t)sn;
    708                 SRFLOWS_SNPOOL_UNLOCK(unit);
    709                 return BCM_E_NONE;
    710             }
    711         }
    712     }
    713 
    714     /*
    715      * 2. Check if the following conditions can meet
    716      *    - 1/2 + 1/2
    717      *    - 1/2 + 1/4 + 1/4
    718      *    - 1/2 + 1/4 + 1/8 + 1/8
    719      *    This only applies to
    720      *    - numbers that can be broken down to half (so power >= 1)
    721      *    - numbers that are at most twice of the max slice size
    722      *      (so pow <= TSN_SRFLOWS_RX_SNPOOL_IDX_MAX + 1)
    723      */
    724     if (pow >= 1 && pow <= TSN_SRFLOWS_RX_SNPOOL_IDX_MAX + 1) {
    725         /* Find the first 1/2 slice */
    726         for (i = 0; i < num_pools; i++) {
    727             if (SR_SNPOOL(i, pow - 1) != NULL) {
    728                 /* Found the first 1/2 slice, now find the 2nd 1/2 slice */
    729                 for (j = 0; j < num_pools; j++) {
    730                     if (j == i) {
    731                         continue;
    732                     }
    733                     if (SR_SNPOOL(j, pow - 1) != NULL) {
    734                         /* Found 1/2 + 1/2 slice, chain and return */
    735                         TSN_SRFLOW_GET_SN_SLICE(sn, i, pow - 1);
    736                         assert(sn != NULL);
    737                         TSN_SRFLOW_GET_SN_SLICE(sn2, j, pow - 1);
    738                         sn->next = sn2;
    739                         *slice = (bcmi_tsn_sr_seqnum_slice_t)sn;
    740                         SRFLOWS_SNPOOL_UNLOCK(unit);
    741                         return BCM_E_NONE;
    742                     }
    743                 }
    744 
    745                 /* Only one 1/2 slice available, so try to find 1/4 slices */
    746                 if (pow >= 2) {
    747                     for (j = 0; j < num_pools; j++) {
    748                         if (j == i) {
    749                             continue;
    750                         }
    751                         if (SR_SNPOOL(j, pow - 2) != NULL) {
    752                             /* Found first 1/4, now find another 1/4 slice */
    753                             for (k = 0; k < num_pools; k++) {
    754                                 if (k == i || k == j) {
    755                                     continue;
    756                                 }
    757                                 if (SR_SNPOOL(k, pow - 2) != NULL) {
    758                                     /* Found 1/2 + 1/4 + 1/4 */
    759                                     TSN_SRFLOW_GET_SN_SLICE(sn, i, pow - 1);
    760                                     assert(sn != NULL);
    761                                     TSN_SRFLOW_GET_SN_SLICE(sn2, j, pow - 2);
    762                                     assert(sn2 != NULL);
    763                                     TSN_SRFLOW_GET_SN_SLICE(sn3, k, pow - 2);
    764                                     sn2->next = sn3;
    765                                     sn->next = sn2;
    766                                     *slice = (bcmi_tsn_sr_seqnum_slice_t)sn;
    767                                     SRFLOWS_SNPOOL_UNLOCK(unit);
    768                                     return BCM_E_NONE;
    769                                 }
    770                             }
    771 
    772                             /* Try to find remaining 1/8 + 1/8 */
    773                             if (pow >= 3) {
    774                                 m = -1;
    775                                 for (k = 0; k < num_pools; k++) {
    776                                     if (k == i || k == j) {
    777                                         continue;
    778                                     }
    779                                     if (SR_SNPOOL(k, pow - 3) != NULL) {
    780                                         if (m == -1) {
    781                                             /* Found first 1/8, record it */
    782                                             m = k;
    783                                         } else {
    784                                             /* Found 1/2 + 1/4 + 1/8 x 2 */
    785                                             TSN_SRFLOW_GET_SN_SLICE(
    786                                                 sn, i, pow - 1);
    787                                             assert(sn != NULL);
    788                                             TSN_SRFLOW_GET_SN_SLICE(
    789                                                 sn2, j, pow - 2);
    790                                             assert(sn2 != NULL);
    791                                             TSN_SRFLOW_GET_SN_SLICE(
    792                                                 sn3, m, pow - 3);
    793                                             assert(sn3 != NULL);
    794                                             TSN_SRFLOW_GET_SN_SLICE(
    795                                                 sn4, k, pow - 3);
    796                                             sn3->next = sn4;
    797                                             sn2->next = sn3;
    798                                             sn->next = sn2;
    799                                             *slice =
    800                                                 (bcmi_tsn_sr_seqnum_slice_t)sn;
    801                                             SRFLOWS_SNPOOL_UNLOCK(unit);
    802                                             return BCM_E_NONE;
    803                                         }
    804                                     }
    805                                 }
    806                             }
    807                         }
    808                     }
    809                 }
    810             }
    811         }
    812     }
    813 
    814     /*
    815      * 3. Check if we can find 1/4 + 1/4 + 1/4 + 1/4
    816      *    - numbers that can be broken down to 1/4 (so power >= 2)
    817      *    - numbers that are at most 4 times of the max slice size
    818      *      (so pow <= TSN_SRFLOWS_RX_SNPOOL_IDX_MAX + 2)
    819      *    Note this algorithm is optimized for 4 pools.
    820      */
    821     if (pow >= 2 && pow <= TSN_SRFLOWS_RX_SNPOOL_IDX_MAX + 2) {
    822         /* Check if all pools have 1/4 slices */
    823         for (i = 0; i < num_pools; i++) {
    824             if (SR_SNPOOL(i, pow - 2) == NULL) {
    825                 break;
    826             }
    827         }
    828         if (i == num_pools) {
    829             /* All pools has 1/4 slices, chain them and return */
    830             sn = NULL;
    831             for (j = 0; j < num_pools; j++) {
    832                 TSN_SRFLOW_GET_SN_SLICE(sn2, j, pow - 2);
    833                 assert(sn2 != NULL);
    834                 if (sn == NULL) {
    835                     sn = sn2;
    836                 } else {
    837                     sn2->next = sn;
    838                     sn = sn2;
    839                 }
    840             }
    841             *slice = (bcmi_tsn_sr_seqnum_slice_t)sn;
    842             SRFLOWS_SNPOOL_UNLOCK(unit);
    843             return BCM_E_NONE;
    844         }
    845     }
    846 
    847     /*
    848      * 4. Cannot find smaller slices for combining.
    849      *    Try to break down bigger slices for it.
    850      */
    851     if (pow >= TSN_SRFLOWS_RX_SNPOOL_IDX_MAX) {
    852         /* No bigger slice than this */
    853         SRFLOWS_SNPOOL_UNLOCK(unit);
    854         return BCM_E_RESOURCE;
    855     }
    856     /* Find bigger slices to break, starting from next size */
    857     for (m = pow + 1; m <= TSN_SRFLOWS_RX_SNPOOL_IDX_MAX; m++) {
    858         /* Scan through all pools for this size */
    859         for (i = 0; i < num_pools; i++) {
    860             if (SR_SNPOOL(i, m) != NULL) {
    861                 /* break it until we get the required size */
    862                 for (j = m; j > pow; j--) {
    863 
    864                     /* Take this one out of the pool */
    865                     sn = SR_SNPOOL(i, j);
    866                     assert(sn != NULL);
    867                     SR_SNPOOL(i, j) = sn->next;
    868 
    869                     /* Break size into half */
    870                     sn->power--;
    871 
    872                     /* Get another slice instance */
    873                     sn2 = SRFLOWS_BKINFO(unit).sn_entries_avail;
    874                     if (sn2 == NULL) {
    875                         assert(0); /* shouldn't happen as we allocated max */
    876                         SRFLOWS_SNPOOL_UNLOCK(unit);
    877                         return BCM_E_RESOURCE;
    878                     }
    879                     SRFLOWS_BKINFO(unit).sn_entries_avail = sn2->next;
    880 
    881                     /* Fill the new slice */
    882                     sn2->index = sn->index;
    883                     sn2->entry = sn->entry;
    884                     sn2->power = sn->power;
    885                     sn2->next = NULL;
    886 
    887                     /* Calculate new offset */
    888                     assert(sn->power < sizeof(tsn_math_powers) / sizeof(int));
    889                     sn2->offset = sn->offset + tsn_math_powers[sn->power];
    890 
    891                     /* Chain them together */
    892                     sn->next = sn2;
    893 
    894                     /* Put into the pool of the new size */
    895                     sn2->next = SR_SNPOOL(i, j - 1);
    896                     SR_SNPOOL(i, j - 1) = sn;
    897                 }
    898 
    899                 /* Now we should have available slices */
    900                 sn = SR_SNPOOL(i, pow);
    901                 assert(sn != NULL);
    902                 SR_SNPOOL(i, pow) = sn->next;
    903                 sn->next = NULL;
    904                 *slice = (bcmi_tsn_sr_seqnum_slice_t)sn;
    905                 SRFLOWS_SNPOOL_UNLOCK(unit);
    906                 return BCM_E_NONE;
    907             }
    908         }
    909     }
    910 
    911     /* Cannot find slices to fulfill the request */
    912     SRFLOWS_SNPOOL_UNLOCK(unit);
    913     return BCM_E_RESOURCE;
    914 }
    915 
    916 #ifdef BCM_WARM_BOOT_SUPPORT
    917 /* SR flow mgmt - break slice until specified slice found (called with lock) */
    918 STATIC int
    919 bcmi_gh2_tsn_sr_flows_seqnum_slice_wb_break(
    920     int unit,
    921     tsn_sr_seqnum_slice_t *slice,
    922     int offset,
    923     int power,
    924     tsn_sr_seqnum_slice_t **pslice)
    925 {
    926     tsn_sr_seqnum_slice_t *sn, *sn2, *sn_break, *sn_put;
    927     int diff;
    928     int pow;
    929 
    930     /* parameter check */
    931     TSN_BKINFO_IS_INIT(unit);
    932     if (!soc_feature(unit, soc_feature_tsn_sr)) {
    933         return (BCM_E_UNAVAIL);
    934     }
    935     if (slice == NULL || pslice == NULL ||
    936         offset < 0 || offset >= TSN_SRFLOWS_RX_SNPOOL_SIZE_MAX ||
    937         power < TSN_SRFLOWS_RX_SNPOOL_POWER_MIN ||
    938         power > TSN_SRFLOWS_RX_SNPOOL_POWER_MAX) {
    939         return BCM_E_PARAM;
    940     }
    941 
    942     /* This routine is for warm boot only */
    943     if (!SOC_WARM_BOOT(unit)) {
    944         return BCM_E_UNAVAIL;
    945     }
    946 
    947     /* Validate supplied slice supplied by internal caller */
    948     assert(slice->entry >= 0);
    949     assert(slice->entry < (uint32)soc_mem_index_count(unit, SR_SN_HISTORY_0m));
    950     assert(slice->offset >= 0);
    951     assert(slice->offset < TSN_SRFLOWS_RX_SN_HIST_POOL_SIZE);
    952     assert(slice->power >= TSN_SRFLOWS_RX_SNPOOL_POWER_MIN);
    953     assert(slice->power <= TSN_SRFLOWS_RX_SNPOOL_POWER_MAX);
    954     assert(slice->power > power);
    955 
    956     /* break it until we get the specified slice */
    957     sn = slice;
    958     for (;;) {
    959 
    960         /* Break size into half */
    961         sn->power--;
    962         assert(sn->power >= power);
    963 
    964         /* Get another slice instance */
    965         sn2 = SRFLOWS_BKINFO(unit).sn_entries_avail;
    966         if (sn2 == NULL) {
    967             assert(0); /* shouldn't happen as we allocated max */
    968             SRFLOWS_SNPOOL_UNLOCK(unit);
    969             return BCM_E_RESOURCE;
    970         }
    971         SRFLOWS_BKINFO(unit).sn_entries_avail = sn2->next;
    972 
    973         /* Fill the new slice */
    974         sn2->index = sn->index;
    975         sn2->entry = sn->entry;
    976         sn2->power = sn->power;
    977         sn2->next = NULL;
    978 
    979         /* Calculate new offset */
    980         assert(sn->power < sizeof(tsn_math_powers) / sizeof(int));
    981         diff = tsn_math_powers[sn->power];
    982         sn2->offset = sn->offset + diff;
    983 
    984         /* Check which one to break and which one to put back */
    985         if (offset & diff) {
    986             sn_break = sn2;
    987             sn_put = sn;
    988         } else {
    989             sn_break = sn;
    990             sn_put = sn2;
    991         }
    992 
    993         /* Put back unused slice into the pool */
    994         pow = sn->power - TSN_SRFLOWS_RX_WINDOW_POWER_MIN;
    995         sn_put->next = SR_SNPOOL(sn->index, pow);
    996         SR_SNPOOL(sn->index, pow) = sn_put;
    997 
    998         /* Return if we have found it */
    999         if (sn_break->power == power) {
   1000             assert(sn_break->offset == offset);
   1001             *pslice = sn_break;
   1002             break;
   1003         }
   1004 
   1005         /* Not yet, break it further */
   1006         sn = sn_break;
   1007     }
   1008 
   1009     return BCM_E_NONE;
   1010 }
   1011 
   1012 /* SR flow mgmt - get specified SN slice from the pools */
   1013 STATIC int
   1014 bcmi_gh2_tsn_sr_flows_seqnum_slice_wb_restore(
   1015     int unit,
   1016     int index,
   1017     int entry,
   1018     int offset,
   1019     int power,
   1020     tsn_sr_seqnum_slice_t **pslice)
   1021 {
   1022     tsn_sr_seqnum_slice_t *sn, *prev;
   1023     int offset2;
   1024     int power2;
   1025     int pow;
   1026     int m;
   1027     int rv;
   1028 
   1029     /* parameter check */
   1030     TSN_BKINFO_IS_INIT(unit);
   1031     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   1032         return (BCM_E_UNAVAIL);
   1033     }
   1034     if (pslice == NULL ||
   1035         index < 0 || index >= TSN_SRFLOWS_RX_SN_HIST_POOLS ||
   1036         entry < 0 ||
   1037         entry >= (uint32)soc_mem_index_count(unit, SR_SN_HISTORY_0m) ||
   1038         offset < 0 || offset >= TSN_SRFLOWS_RX_SNPOOL_SIZE_MAX ||
   1039         power < TSN_SRFLOWS_RX_SNPOOL_POWER_MIN ||
   1040         power > TSN_SRFLOWS_RX_SNPOOL_POWER_MAX) {
   1041         return BCM_E_PARAM;
   1042     }
   1043 
   1044     /* This routine is for warm boot only */
   1045     if (!SOC_WARM_BOOT(unit)) {
   1046         return BCM_E_UNAVAIL;
   1047     }
   1048 
   1049     /* Start finding the specified slice */
   1050     pow = power - TSN_SRFLOWS_RX_WINDOW_POWER_MIN; /* pool slot index */
   1051     SRFLOWS_SNPOOL_LOCK(unit);
   1052 
   1053     /* Check if the exact slice exists */
   1054     prev = NULL;
   1055     for (sn = SR_SNPOOL(index, pow); sn != NULL; prev = sn, sn = sn->next) {
   1056         if (sn->entry == entry && sn->offset == offset) {
   1057             if (prev == NULL) {
   1058                 SR_SNPOOL(index, pow) = sn->next;
   1059             } else {
   1060                 prev->next = sn->next;
   1061             }
   1062             *pslice = sn;
   1063             SRFLOWS_SNPOOL_UNLOCK(unit);
   1064             return BCM_E_NONE;
   1065         }
   1066     }
   1067 
   1068     /* Need to break down bigger slice to get what we want */
   1069     if (pow >= TSN_SRFLOWS_RX_SNPOOL_IDX_MAX) {
   1070         /* No bigger slice than this */
   1071         SRFLOWS_SNPOOL_UNLOCK(unit);
   1072         return BCM_E_INTERNAL;
   1073     }
   1074     /* Find bigger slices to break, starting from next size */
   1075     for (m = pow + 1; m <= TSN_SRFLOWS_RX_SNPOOL_IDX_MAX; m++) {
   1076         /* Find the slice containing the specified window */
   1077         if (SR_SNPOOL(index, m) != NULL) {
   1078             power2 = m + TSN_SRFLOWS_RX_WINDOW_POWER_MIN;
   1079             offset2 = offset & (~(tsn_math_powers[power2] - 1));
   1080             prev = NULL;
   1081             for (sn = SR_SNPOOL(index, m); sn != NULL; sn = sn->next) {
   1082                 if (sn->entry == entry && sn->offset == offset2) {
   1083                     if (prev == NULL) {
   1084                         SR_SNPOOL(index, m) = sn->next;
   1085                     } else {
   1086                         prev->next = sn->next;
   1087                     }
   1088                     rv = bcmi_gh2_tsn_sr_flows_seqnum_slice_wb_break(
   1089                             unit, sn, offset, power, pslice);
   1090                     SRFLOWS_SNPOOL_UNLOCK(unit);
   1091                     return rv;
   1092                 }
   1093                 prev = sn;
   1094             }
   1095         }
   1096     }
   1097 
   1098     SRFLOWS_SNPOOL_UNLOCK(unit);
   1099     return BCM_E_RESOURCE;
   1100 }
   1101 #endif /* BCM_WARM_BOOT_SUPPORT */
   1102 
   1103 /* SR flow mgmt - read seqnum history pool for a flow */
   1104 STATIC int
   1105 bcmi_gh2_tsn_sr_flows_seqnum_hist_read(
   1106     int unit,
   1107     int idx,
   1108     int winsize,
   1109     bcmi_tsn_sr_seqnum_slice_t slice,
   1110     int offset,
   1111     int max_size,
   1112     uint8 *history,
   1113     int *actual)
   1114 {
   1115     tsn_sr_seqnum_slice_t *sn, *slices[TSN_SRFLOWS_RX_SN_HIST_POOLS];
   1116     int left;       /* bits left to read */
   1117     int off;        /* current offset to read for this flow */
   1118     int pos;        /* starting position within the flow for a slice */
   1119     int sz;         /* size of the slice */
   1120     int poff;       /* current offset within a pool */
   1121     int pbits;      /* bits to read within a pool */
   1122     int sidx;       /* sub pool (per memory access) index */
   1123     int soff;       /* current offset within a sub pool */
   1124     int sbits;      /* bits to read within a sub pool */
   1125     int boff;       /* buffer offset in bits */
   1126     soc_mem_t mem;
   1127     sr_sn_history_0_entry_t hist_entry;
   1128     uint32 fldbuf[TSN_SRFLOWS_RX_SN_HIST_MEM_SIZE / sizeof(uint32)];
   1129     int rv;
   1130     int i, j;
   1131 
   1132     /* parameter check */
   1133     TSN_BKINFO_IS_INIT(unit);
   1134     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   1135         return (BCM_E_UNAVAIL);
   1136     }
   1137     if (NULL == history || NULL == slice ||
   1138         idx < 0 || idx >= SRFLOWS_BKINFO(unit).max_flows_rx ||
   1139         (winsize < TSN_SRFLOWS_RX_WINDOW_SIZE_MIN && winsize != 1) ||
   1140         winsize > TSN_SRFLOWS_RX_WINDOW_SIZE_MAX) {
   1141         return BCM_E_PARAM;
   1142     }
   1143 
   1144     /* Put slice in the order of pool index and validate */
   1145     for (i = 0; i < TSN_SRFLOWS_RX_SN_HIST_POOLS; i++) {
   1146         slices[i] = NULL;
   1147     }
   1148     pos = 0;
   1149     for (sn = (tsn_sr_seqnum_slice_t *)slice; sn != NULL; sn = sn->next) {
   1150         if (sn->index < 0 || sn->index >= TSN_SRFLOWS_RX_SN_HIST_POOLS) {
   1151             return BCM_E_PARAM;
   1152         }
   1153         if (slices[sn->index] != NULL) {
   1154             return BCM_E_PARAM;
   1155         }
   1156         slices[sn->index] = sn;
   1157         if (sn->power < TSN_SRFLOWS_RX_SNPOOL_POWER_MIN ||
   1158             sn->power > TSN_SRFLOWS_RX_SNPOOL_POWER_MAX) {
   1159             return BCM_E_PARAM;
   1160         }
   1161         pos += tsn_math_powers[sn->power];
   1162     }
   1163     if (pos != winsize) {
   1164         if (pos != TSN_SRFLOWS_RX_SNPOOL_SIZE_MIN || winsize != 1) {
   1165             /* The only case that pos != winsize is that winsize = 1 */
   1166             return BCM_E_PARAM;
   1167         }
   1168     }
   1169 
   1170     /* Calculate bits to read */
   1171     max_size = (max_size > (winsize - offset)) ? (winsize - offset) : max_size;
   1172 
   1173     /* Try to read it pool by pool */
   1174     off = offset;           /* Offset of this flow */
   1175     left = max_size;        /* Remaining bits to read */
   1176     pos = 0;                /* Slice starting position of this flow */
   1177     boff = 0;               /* Buffer offset */
   1178     for (i = 0; i < TSN_SRFLOWS_RX_SN_HIST_POOLS; i++) {
   1179         if (slices[i] == NULL) {
   1180             continue;
   1181         }
   1182         sn = slices[i];
   1183         sz = tsn_math_powers[sn->power];    /* Size of this slice */
   1184 
   1185         /* Check if our target is within this slice */
   1186         if (off < pos || off >= pos + sz) {
   1187             pos += sz;
   1188             continue;
   1189         }
   1190 
   1191         /* Calculate starting offset within this pool */
   1192         poff = sn->offset + (off - pos);
   1193 
   1194         /* Calculate bits to read within this pool */
   1195         pbits = sz - (off - pos);
   1196         pbits = (pbits > left) ? left : pbits;
   1197 
   1198         /* Loop through sub pools */
   1199         for (j = 0; pbits > 0 && j < TSN_SRFLOWS_RX_SN_HIST_SUB_POOLS; j++) {
   1200             /* Check if we need to read this sub pool */
   1201             if (poff < j * TSN_SRFLOWS_RX_SN_HIST_MEM_SIZE ||
   1202                 poff >= (j + 1) * TSN_SRFLOWS_RX_SN_HIST_MEM_SIZE) {
   1203                 continue;
   1204             }
   1205 
   1206             /* Calculate actual HW sub pool index */
   1207             sidx = (i << TSN_SRFLOWS_RX_SN_HIST_SUB_INDEX) |
   1208                    (poff >> TSN_SRFLOWS_RX_SN_HIST_MEM_POWER);
   1209 
   1210             /* Read the entry and the field from the sub pool */
   1211             assert(sidx < sizeof(tsn_flow_sr_hist_pools) / sizeof(soc_mem_t));
   1212             mem = tsn_flow_sr_hist_pools[sidx];
   1213             sal_memset(&hist_entry, 0, sizeof(hist_entry));
   1214             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, sn->entry, &hist_entry);
   1215             if (SOC_FAILURE(rv)) {
   1216                 LOG_ERROR(BSL_LS_BCM_TSN,
   1217                           (BSL_META_U(unit, "Failed to read mem[%s]"),
   1218                                       SOC_MEM_NAME(unit, mem)));
   1219                 return rv;
   1220             }
   1221             soc_mem_field_get(
   1222                 unit, mem, (uint32 *)&hist_entry, SN_WINDOWf, fldbuf);
   1223 
   1224             /* Calculate starting offset within this sub pool */
   1225             soff = poff & (TSN_SRFLOWS_RX_SN_HIST_MEM_SIZE - 1);
   1226 
   1227             /* Calculate bits to read within this sub pool */
   1228             sbits = TSN_SRFLOWS_RX_SN_HIST_MEM_SIZE - soff;
   1229             sbits = (sbits > pbits) ? pbits : sbits;
   1230 
   1231             /* Copy bits from field to buffer */
   1232             SHR_BITCOPY_RANGE(
   1233                 (SHR_BITDCL *)history, boff, (SHR_BITDCL *)fldbuf, soff, sbits);
   1234 
   1235             /* Advance offsets and remaining bits */
   1236             poff += sbits;
   1237             off += sbits;
   1238             pbits -= sbits;
   1239             boff += sbits;
   1240             left -= sbits;
   1241         }
   1242 
   1243         /* Update position for next slice */
   1244         pos += sz;
   1245     }
   1246 
   1247     *actual = max_size;
   1248     return BCM_E_NONE;
   1249 }
   1250 
   1251 /* SR flow mgmt - write seqnum history pool for a flow */
   1252 STATIC int
   1253 bcmi_gh2_tsn_sr_flows_seqnum_hist_write(
   1254     int unit,
   1255     int idx,
   1256     int winsize,
   1257     bcmi_tsn_sr_seqnum_slice_t slice,
   1258     int offset,
   1259     int size,
   1260     uint8 *history)
   1261 {
   1262     tsn_sr_seqnum_slice_t *sn, *slices[TSN_SRFLOWS_RX_SN_HIST_POOLS];
   1263     int left;       /* bits left to write */
   1264     int off;        /* current offset to write for this flow */
   1265     int pos;        /* starting position within the flow for a slice */
   1266     int sz;         /* size of the slice */
   1267     int poff;       /* current offset within a pool */
   1268     int pbits;      /* bits to write within a pool */
   1269     int sidx;       /* sub pool (per memory access) index */
   1270     int soff;       /* current offset within a sub pool */
   1271     int sbits;      /* bits to write within a sub pool */
   1272     int boff;       /* buffer offset in bits */
   1273     uint32 bsel;    /* seqnum sub pool block select */
   1274     soc_mem_t mem;
   1275     sr_sn_history_0_entry_t hist_entry;
   1276     uint32 fldbuf[TSN_SRFLOWS_RX_SN_HIST_MEM_SIZE / sizeof(uint32)];
   1277     int rv;
   1278     int i, j, k;
   1279 
   1280     /* parameter check */
   1281     TSN_BKINFO_IS_INIT(unit);
   1282     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   1283         return (BCM_E_UNAVAIL);
   1284     }
   1285     if (NULL == history || NULL == slice ||
   1286         idx < 0 || idx >= SRFLOWS_BKINFO(unit).max_flows_rx ||
   1287         (winsize < TSN_SRFLOWS_RX_WINDOW_SIZE_MIN && winsize != 1) ||
   1288         winsize > TSN_SRFLOWS_RX_WINDOW_SIZE_MAX) {
   1289         return BCM_E_PARAM;
   1290     }
   1291 
   1292     /* Put slice in the order of pool index and validate */
   1293     for (i = 0; i < TSN_SRFLOWS_RX_SN_HIST_POOLS; i++) {
   1294         slices[i] = NULL;
   1295     }
   1296     pos = 0;
   1297     for (sn = (tsn_sr_seqnum_slice_t *)slice; sn != NULL; sn = sn->next) {
   1298         if (sn->index < 0 || sn->index >= TSN_SRFLOWS_RX_SN_HIST_POOLS) {
   1299             return BCM_E_PARAM;
   1300         }
   1301         if (slices[sn->index] != NULL) {
   1302             return BCM_E_PARAM;
   1303         }
   1304         slices[sn->index] = sn;
   1305         if (sn->power < TSN_SRFLOWS_RX_SNPOOL_POWER_MIN ||
   1306             sn->power > TSN_SRFLOWS_RX_SNPOOL_POWER_MAX) {
   1307             return BCM_E_PARAM;
   1308         }
   1309         pos += tsn_math_powers[sn->power];
   1310     }
   1311     if (pos != winsize) {
   1312         if (pos != TSN_SRFLOWS_RX_SNPOOL_SIZE_MIN || winsize != 1) {
   1313             /* The only case that pos != winsize is that winsize = 1 */
   1314             return BCM_E_PARAM;
   1315         }
   1316     }
   1317 
   1318     /* Writing across winsize is not allowed */
   1319     if (size > (winsize - offset)) {
   1320         return BCM_E_PARAM;
   1321     }
   1322 
   1323     /* Try to write it pool by pool */
   1324     off = offset;           /* Offset of this flow */
   1325     left = size;            /* Remaining bits to write */
   1326     pos = 0;                /* Slice starting position of this flow */
   1327     boff = 0;               /* Buffer offset */
   1328     for (i = 0; i < TSN_SRFLOWS_RX_SN_HIST_POOLS; i++) {
   1329         if (slices[i] == NULL) {
   1330             continue;
   1331         }
   1332         sn = slices[i];
   1333         sz = tsn_math_powers[sn->power];    /* Size of this slice */
   1334 
   1335         /* Check if our target is within this slice */
   1336         if (off < pos || off >= pos + sz) {
   1337             pos += sz;
   1338             continue;
   1339         }
   1340 
   1341         /* Calculate starting offset within this pool */
   1342         poff = sn->offset + (off - pos);
   1343 
   1344         /* Calculate bits to write within this pool */
   1345         pbits = sz - (off - pos);
   1346         pbits = (pbits > left) ? left : pbits;
   1347 
   1348         /* Loop through sub pools */
   1349         for (j = 0; pbits > 0 && j < TSN_SRFLOWS_RX_SN_HIST_SUB_POOLS; j++) {
   1350             /* Check if we need to write this sub pool */
   1351             if (poff < j * TSN_SRFLOWS_RX_SN_HIST_MEM_SIZE ||
   1352                 poff >= (j + 1) * TSN_SRFLOWS_RX_SN_HIST_MEM_SIZE) {
   1353                 continue;
   1354             }
   1355 
   1356             /* Calculate actual HW sub pool index */
   1357             sidx = (i << TSN_SRFLOWS_RX_SN_HIST_SUB_INDEX) |
   1358                    (poff >> TSN_SRFLOWS_RX_SN_HIST_MEM_POWER);
   1359 
   1360             /* read the entry and the field from the sub pool */
   1361             assert(sidx < sizeof(tsn_flow_sr_hist_pools) / sizeof(soc_mem_t));
   1362             mem = tsn_flow_sr_hist_pools[sidx];
   1363             sal_memset(&hist_entry, 0, sizeof(hist_entry));
   1364             MEM_LOCK(unit, mem);
   1365             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, sn->entry, &hist_entry);
   1366             if (SOC_FAILURE(rv)) {
   1367                 LOG_ERROR(BSL_LS_BCM_TSN,
   1368                           (BSL_META_U(unit, "Failed to read mem[%s]"),
   1369                                       SOC_MEM_NAME(unit, mem)));
   1370                 MEM_UNLOCK(unit, mem);
   1371                 return rv;
   1372             }
   1373             soc_mem_field_get(
   1374                 unit, mem, (uint32 *)&hist_entry, SN_WINDOWf, fldbuf);
   1375 
   1376             /* Calculate starting offset within this sub pool */
   1377             soff = poff & (TSN_SRFLOWS_RX_SN_HIST_MEM_SIZE - 1);
   1378 
   1379             /* Calculate bits to write within this sub pool */
   1380             sbits = TSN_SRFLOWS_RX_SN_HIST_MEM_SIZE - soff;
   1381             sbits = (sbits > pbits) ? pbits : sbits;
   1382 
   1383             /* Fill block selections */
   1384             bsel = 0;
   1385             for (k = 0;
   1386                  k < TSN_SRFLOWS_RX_SN_HIST_MEM_SIZE /
   1387                      TSN_SRFLOWS_RX_SN_HIST_BLOCK_SIZE;
   1388                  k++) {
   1389                 if (soff < (k + 1) * TSN_SRFLOWS_RX_SN_HIST_BLOCK_SIZE &&
   1390                     soff + sbits > k * TSN_SRFLOWS_RX_SN_HIST_BLOCK_SIZE) {
   1391                     bsel |= 1 << k;
   1392                 }
   1393             }
   1394             soc_mem_field32_set(unit, mem, &hist_entry, BLOCK_SELECTf, bsel);
   1395 
   1396             /* Copy bits from buffer to field */
   1397             SHR_BITCOPY_RANGE(
   1398                 (SHR_BITDCL *)fldbuf, soff, (SHR_BITDCL *)history, boff, sbits);
   1399             soc_mem_field_set(
   1400                 unit, mem, (uint32 *)&hist_entry, SN_WINDOWf, fldbuf);
   1401 
   1402             /* Write to HW */
   1403             rv = soc_mem_write(
   1404                 unit, mem, MEM_BLOCK_ALL, sn->entry, &hist_entry);
   1405             if (SOC_FAILURE(rv)) {
   1406                 LOG_ERROR(BSL_LS_BCM_TSN,
   1407                           (BSL_META_U(unit, "Failed to write mem[%s]"),
   1408                                       SOC_MEM_NAME(unit, mem)));
   1409                 MEM_UNLOCK(unit, mem);
   1410                 return rv;
   1411             }
   1412             MEM_UNLOCK(unit, mem);
   1413 
   1414             /* Advance offsets and remaining bits */
   1415             poff += sbits;
   1416             off += sbits;
   1417             pbits -= sbits;
   1418             boff += sbits;
   1419             left -= sbits;
   1420         }
   1421 
   1422         /* Update position for next slice */
   1423         pos += sz;
   1424     }
   1425 
   1426     return BCM_E_NONE;
   1427 }
   1428 
   1429 /* SR flow mgmt - reset seqnum history pool for a flow */
   1430 STATIC int
   1431 bcmi_gh2_tsn_sr_flows_seqnum_hist_reset(
   1432     int unit,
   1433     int idx,
   1434     int winsize,
   1435     bcmi_tsn_sr_seqnum_slice_t slice,
   1436     uint32 reset_mode)
   1437 {
   1438     uint8 history[BITS2BYTES(TSN_SRFLOWS_RX_WINDOW_SIZE_MAX)];
   1439 
   1440     /* parameter check */
   1441     TSN_BKINFO_IS_INIT(unit);
   1442     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   1443         return (BCM_E_UNAVAIL);
   1444     }
   1445     if (NULL == slice ||
   1446         idx < 0 || idx >= SRFLOWS_BKINFO(unit).max_flows_rx ||
   1447         (winsize < TSN_SRFLOWS_RX_WINDOW_SIZE_MIN && winsize != 1) ||
   1448         winsize > TSN_SRFLOWS_RX_WINDOW_SIZE_MAX) {
   1449         return BCM_E_PARAM;
   1450     }
   1451 
   1452     /* Prepare seqnum values */
   1453     if (reset_mode == BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_HW1 ||
   1454         reset_mode == BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_SW) {
   1455         /* All zeroes */
   1456         sal_memset(history, 0, BITS2BYTES(winsize));
   1457     } else if (reset_mode == BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_HW2) {
   1458         /* All 1's except the last bit */
   1459         if (winsize == 1) {
   1460             /* Special case: 1 bit (it's the first bit in this byte) */
   1461             history[0] = 0;
   1462         } else {
   1463             sal_memset(history, 0xff, BITS2BYTES(winsize));
   1464             history[BITS2BYTES(winsize) - 1] &= ~0x80;
   1465         }
   1466     } else {
   1467         /* Reset mode not supported */
   1468         return BCM_E_UNAVAIL;
   1469     }
   1470 
   1471     /* Call write routine to write the values */
   1472     return bcmi_gh2_tsn_sr_flows_seqnum_hist_write(
   1473                 unit, idx, winsize, slice, 0, winsize, history);
   1474 }
   1475 
   1476 /* SR flow mgmt - clean up seqnum history slice pools */
   1477 STATIC int
   1478 bcmi_gh2_tsn_sr_flows_seqnum_slices_cleanup(int unit)
   1479 {
   1480     int i, j;
   1481 
   1482     /* Free resources */
   1483     TSN_BKINFO_IS_INIT(unit);
   1484     if (SRFLOWS_BKINFO(unit).sn_entries_allocated != NULL) {
   1485         sal_free(SRFLOWS_BKINFO(unit).sn_entries_allocated);
   1486         SRFLOWS_BKINFO(unit).sn_entries_allocated = NULL;
   1487     }
   1488     if (SRFLOWS_BKINFO(unit).snpool_mutex != NULL) {
   1489         sal_mutex_destroy(SRFLOWS_BKINFO(unit).snpool_mutex);
   1490         SRFLOWS_BKINFO(unit).snpool_mutex = NULL;
   1491     }
   1492 
   1493     /* Clear values */
   1494     SRFLOWS_BKINFO(unit).sn_entries_avail = NULL;
   1495     for (i = 0; i < TSN_SRFLOWS_RX_SN_HIST_POOLS; i++) {
   1496         for (j = 0; j < TSN_SRFLOWS_RX_SNPOOL_SIZE_COUNT; j++) {
   1497             SR_SNPOOL(i, j) = NULL;
   1498         }
   1499     }
   1500 
   1501     return BCM_E_NONE;
   1502 }
   1503 
   1504 /* SR flow mgmt - intiailize seqnum history slice pools */
   1505 STATIC int
   1506 bcmi_gh2_tsn_sr_flows_seqnum_slices_init(int unit)
   1507 {
   1508     tsn_sr_seqnum_slice_t *slice;
   1509     uint32 entries;
   1510     uint32 i, j;
   1511 
   1512     TSN_BKINFO_IS_INIT(unit);
   1513 
   1514     /* Calculate max entries to be pre-allcoated */
   1515     entries = (uint32)soc_mem_index_count(unit, SR_SN_HISTORY_0m);
   1516     j = entries *                                       /* entries per pool */
   1517         TSN_SRFLOWS_RX_SN_HIST_POOL_SIZE *              /* size per entry */
   1518         TSN_SRFLOWS_RX_SN_HIST_POOLS                    /* pools */
   1519         / TSN_SRFLOWS_RX_SNPOOL_SIZE_MIN;               /* min slice size */
   1520 
   1521     /* Pre-allocate slice entries for efficiency */
   1522     SRFLOWS_BKINFO(unit).sn_entries_allocated = (tsn_sr_seqnum_slice_t *)
   1523         sal_alloc(sizeof(tsn_sr_seqnum_slice_t) * j, "tsn sr sn slices");
   1524     if (SRFLOWS_BKINFO(unit).sn_entries_allocated == NULL) {
   1525         LOG_ERROR(BSL_LS_BCM_TSN,
   1526                   (BSL_META("TSN SR: failed to allocate SN pool slices\n")));
   1527         return BCM_E_MEMORY;
   1528     }
   1529 
   1530     /* Initialize the free slice entries list by hooking them together */
   1531     slice = SRFLOWS_BKINFO(unit).sn_entries_allocated;
   1532     for (i = 0; i < j - 1; i++) {
   1533         slice[i].next = &slice[i + 1];
   1534     }
   1535     slice[j - 1].next = NULL;
   1536     SRFLOWS_BKINFO(unit).sn_entries_avail = &slice[0];
   1537 
   1538     /* Initialize slices linked list for all sizes */
   1539     for (i = 0; i < TSN_SRFLOWS_RX_SN_HIST_POOLS; i++) {
   1540         for (j = 0; j < TSN_SRFLOWS_RX_SNPOOL_SIZE_COUNT; j++) {
   1541             SR_SNPOOL(i, j) = NULL;
   1542         }
   1543     }
   1544 
   1545     /* Create mutex for protecting seqnum slices */
   1546     SRFLOWS_BKINFO(unit).snpool_mutex = sal_mutex_create("tsn sr sn pool");
   1547     if (NULL == SRFLOWS_BKINFO(unit).snpool_mutex) {
   1548         LOG_ERROR(BSL_LS_BCM_TSN,
   1549                   (BSL_META("TSN SR: failed to create SN pool mutex\n")));
   1550         (void)bcmi_gh2_tsn_sr_flows_seqnum_slices_cleanup(unit);
   1551         return BCM_E_MEMORY;
   1552     }
   1553 
   1554     /* Prepare the entries with max size for seqnum allocation */
   1555     for (i = 0; i < TSN_SRFLOWS_RX_SN_HIST_POOLS; i++) {
   1556         /* Add max-size slices */
   1557         for (j = 0; j < entries; j++) {
   1558 
   1559             /* Get one empty entry */
   1560             slice = SRFLOWS_BKINFO(unit).sn_entries_avail;
   1561             SRFLOWS_BKINFO(unit).sn_entries_avail = slice->next;
   1562 
   1563             /* Fill with entry info and max size */
   1564             slice->index = i;
   1565             slice->entry = entries - j - 1;
   1566             slice->offset = 0;
   1567             slice->power = TSN_SRFLOWS_RX_SNPOOL_POWER_MAX;
   1568 
   1569             /* Hook to it */
   1570             slice->next = SR_SNPOOL(i, TSN_SRFLOWS_RX_SNPOOL_IDX_MAX);
   1571             SR_SNPOOL(i, TSN_SRFLOWS_RX_SNPOOL_IDX_MAX) = slice;
   1572         }
   1573     }
   1574 
   1575     return BCM_E_NONE;
   1576 }
   1577 
   1578 /* SR flow mgmt - get number of RX/TX flows */
   1579 STATIC int
   1580 bcmi_gh2_tsn_sr_flows_get_num_flows(int unit, int *rx_flows, int *tx_flows)
   1581 {
   1582     /* parameter check */
   1583     TSN_BKINFO_IS_INIT(unit);
   1584     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   1585         return (BCM_E_UNAVAIL);
   1586     }
   1587     if (NULL == rx_flows || NULL == tx_flows) {
   1588         return BCM_E_PARAM;
   1589     }
   1590 
   1591     /* Get the flows based on number of entries in HW memory (if not yet) */
   1592     if (SRFLOWS_BKINFO(unit).max_flows_rx == 0) {
   1593 
   1594         /* The actual valid flow count - 1 since HW flow 0 is invalid */
   1595         SRFLOWS_BKINFO(unit).max_flows_rx =
   1596             soc_mem_index_count(unit, SR_RXm) - 1;
   1597         SRFLOWS_BKINFO(unit).max_flows_tx =
   1598             soc_mem_index_count(unit, SR_TXm) - 1;
   1599     }
   1600 
   1601     /* Return the cached values */
   1602     *rx_flows = SRFLOWS_BKINFO(unit).max_flows_rx;
   1603     *tx_flows = SRFLOWS_BKINFO(unit).max_flows_tx;
   1604 
   1605     return BCM_E_NONE;
   1606 }
   1607 
   1608 /* SR flow mgmt - convert flow index to HW flow ID */
   1609 STATIC int
   1610 bcmi_gh2_tsn_sr_flows_get_hw_flow_id(
   1611     int unit,
   1612     int is_tx,
   1613     int fidx,
   1614     uint32 *hw_id)
   1615 {
   1616     /* parameter check */
   1617     TSN_BKINFO_IS_INIT(unit);
   1618     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   1619         return (BCM_E_UNAVAIL);
   1620     }
   1621     if (NULL == hw_id || fidx < 0) {
   1622         return BCM_E_PARAM;
   1623     }
   1624 
   1625     /* Check if it's valid */
   1626     if (is_tx) {
   1627         if (fidx >= SRFLOWS_BKINFO(unit).max_flows_tx) {
   1628             return BCM_E_PARAM;
   1629         }
   1630     } else {
   1631         if (fidx >= SRFLOWS_BKINFO(unit).max_flows_rx) {
   1632             return BCM_E_PARAM;
   1633         }
   1634     }
   1635 
   1636     /* Convert it */
   1637     *hw_id = (uint32)TSN_SRFLOWS_IDX_TO_HW_ID(is_tx, fidx);
   1638     return BCM_E_NONE;
   1639 }
   1640 
   1641 /* SR flow mgmt - convert flow index to HW flow ID */
   1642 STATIC int
   1643 bcmi_gh2_tsn_sr_flows_get_sw_flow_idx(
   1644     int unit,
   1645     uint32 hw_id,
   1646     int *is_tx,
   1647     int *fidx)
   1648 {
   1649     int tx;
   1650     int idx;
   1651 
   1652     /* parameter check */
   1653     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   1654         return (BCM_E_UNAVAIL);
   1655     }
   1656     if (NULL == is_tx || NULL == fidx) {
   1657         return BCM_E_PARAM;
   1658     }
   1659 
   1660     /* Convert it */
   1661     tx = TSN_SRFLOWS_HW_ID_IS_TX((int)hw_id);
   1662     idx = TSN_SRFLOWS_HW_ID_TO_IDX((int)hw_id);
   1663 
   1664     /* Check if it's valid */
   1665     if (TSN_BKINFO(unit) != NULL) {
   1666         TSN_BKINFO_IS_INIT(unit);
   1667         if (tx) {
   1668             if (idx < 0 || idx >= SRFLOWS_BKINFO(unit).max_flows_tx) {
   1669                 return BCM_E_PARAM;
   1670             }
   1671         } else {
   1672             if (idx < 0 || idx >= SRFLOWS_BKINFO(unit).max_flows_rx) {
   1673                 return BCM_E_PARAM;
   1674             }
   1675         }
   1676     }
   1677 
   1678     *is_tx = tx;
   1679     *fidx = idx;
   1680     return BCM_E_NONE;
   1681 }
   1682 
   1683 /* SR flow mgmt - check flow config */
   1684 STATIC int
   1685 bcmi_gh2_tsn_sr_flows_check_rx_flow_config(
   1686     int unit,
   1687     bcm_tsn_sr_rx_flow_config_t *cfg)
   1688 {
   1689     int index;
   1690     bcm_tsn_mtu_profile_type_t type;
   1691 
   1692     /* parameter check */
   1693     TSN_BKINFO_IS_INIT(unit);
   1694     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   1695         return (BCM_E_UNAVAIL);
   1696     }
   1697     if (NULL == cfg) {
   1698         return BCM_E_PARAM;
   1699     }
   1700 
   1701     /* Check min/max window sizes (special case: history size can be 1) */
   1702     if ((cfg->seqnum_history_win_size != 1 &&
   1703          cfg->seqnum_history_win_size < TSN_SRFLOWS_RX_WINDOW_SIZE_MIN) ||
   1704          cfg->seqnum_history_win_size > TSN_SRFLOWS_RX_WINDOW_SIZE_MAX ||
   1705          cfg->seqnum_accept_win_size < TSN_SRFLOWS_RX_ACCEPT_SIZE_MIN ||
   1706          cfg->seqnum_accept_win_size > TSN_SRFLOWS_RX_ACCEPT_SIZE_MAX) {
   1707         return BCM_E_PARAM;
   1708     }
   1709 
   1710     /* Check if they're power of 2 */
   1711     if (!TSN_IS_POWER_OF_2(cfg->seqnum_accept_win_size) ||
   1712         !TSN_IS_POWER_OF_2(cfg->seqnum_history_win_size)) {
   1713         return BCM_E_PARAM;
   1714     }
   1715 
   1716     /* History window size should be smaller than acceptance window size */
   1717     if (cfg->seqnum_history_win_size >= cfg->seqnum_accept_win_size) {
   1718         return BCM_E_PARAM;
   1719     }
   1720 
   1721     /* Check age out time (for GH2, it must be power of 2) */
   1722     if (!TSN_IS_POWER_OF_2(cfg->age_timeout) ||
   1723         cfg->age_timeout > TSN_SRFLOWS_RX_AGE_TIME_MAX) {
   1724         return BCM_E_PARAM;
   1725     }
   1726 
   1727     /* Check flags */
   1728     if (cfg->flags &
   1729         ~(BCM_TSN_SR_RX_FLOW_CONFIG_ACCEPT_DUPLICATES |
   1730           BCM_TSN_SR_RX_FLOW_CONFIG_ACCEPT_PKT_IN_DROP_WINDOW |
   1731           BCM_TSN_SR_RX_FLOW_CONFIG_DROP_OUT_OF_ORDER |
   1732           BCM_TSN_SR_RX_FLOW_CONFIG_DO_NOT_CUT_THROUGH)) {
   1733           /* Found unsupported flags */
   1734           return BCM_E_UNAVAIL;
   1735     }
   1736 
   1737     /* Check MTU profile id */
   1738     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   1739         /* Using MTU decode function to do profile id validation */
   1740         BCM_IF_ERROR_RETURN(bcmi_gh2_tsn_mtu_profile_decode(
   1741                               unit, cfg->ingress_mtu_profile, &type, &index));
   1742         if (type == bcmTsnMtuProfileTypeEgress) {
   1743             return BCM_E_PARAM;
   1744         }
   1745     }
   1746 
   1747     return BCM_E_NONE;
   1748 }
   1749 
   1750 /* SR flow mgmt - check flow config */
   1751 STATIC int
   1752 bcmi_gh2_tsn_sr_flows_check_tx_flow_config(
   1753     int unit,
   1754     bcm_tsn_sr_tx_flow_config_t *cfg)
   1755 {
   1756     int index;
   1757     bcm_tsn_mtu_profile_type_t type;
   1758 
   1759     /* parameter check */
   1760     TSN_BKINFO_IS_INIT(unit);
   1761     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   1762         return (BCM_E_UNAVAIL);
   1763     }
   1764     if (NULL == cfg) {
   1765         return BCM_E_PARAM;
   1766     }
   1767 
   1768     /* check sequence number */
   1769     if (cfg->seq_num > TSN_SRFLOWS_SEQNUM_VALUE_MAX) {
   1770         return BCM_E_PARAM;
   1771     }
   1772 
   1773     /* Check MTU profile id */
   1774     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   1775         /* Using MTU decode function to do profile id validation */
   1776         BCM_IF_ERROR_RETURN(bcmi_gh2_tsn_mtu_profile_decode(
   1777                               unit, cfg->ingress_mtu_profile, &type, &index));
   1778         if (type == bcmTsnMtuProfileTypeEgress) {
   1779             return BCM_E_PARAM;
   1780         }
   1781 
   1782     }
   1783 
   1784     return BCM_E_NONE;
   1785 }
   1786 
   1787 /* SR flow mgmt - clear flow config - mtu */
   1788 STATIC int
   1789 bcmi_gh2_tsn_sr_flows_clear_rx_flow_mtu(int unit, int idx)
   1790 {
   1791     soc_mem_t mem;
   1792     ing_mtu_check_2_entry_t mtu_ent;
   1793     int rv;
   1794     int is_tx = 0;
   1795     uint32 hw_id;
   1796 
   1797     TSN_BKINFO_IS_INIT(unit);
   1798     if (!soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   1799         return BCM_E_UNAVAIL;
   1800     }
   1801 
   1802     hw_id = (uint32)TSN_SRFLOWS_IDX_TO_HW_ID(is_tx, idx);
   1803     mem = ING_MTU_CHECK_2m;
   1804     sal_memset(&mtu_ent, 0, sizeof(mtu_ent));
   1805     MEM_LOCK(unit, mem);
   1806     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_id, &mtu_ent);
   1807     if (SOC_FAILURE(rv)) {
   1808         LOG_ERROR(BSL_LS_BCM_TSN,
   1809                   (BSL_META_U(unit, "Failed to read mem[%s]"),
   1810                               SOC_MEM_NAME(unit, mem)));
   1811         MEM_UNLOCK(unit, mem);
   1812         return rv;
   1813     }
   1814     soc_mem_field32_set(unit, mem, &mtu_ent, MTU_PROFILE_INDEXf, 0);
   1815 
   1816     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_id, &mtu_ent);
   1817     if (SOC_FAILURE(rv)) {
   1818         LOG_ERROR(BSL_LS_BCM_TSN,
   1819                   (BSL_META_U(unit, "Failed to write mem[%s]"),
   1820                               SOC_MEM_NAME(unit, mem)));
   1821         MEM_UNLOCK(unit, mem);
   1822         return rv;
   1823     }
   1824     MEM_UNLOCK(unit, mem);
   1825     return BCM_E_NONE;
   1826 }
   1827 
   1828 /* SR flow mgmt - clear flow config */
   1829 STATIC int
   1830 bcmi_gh2_tsn_sr_flows_clear_rx_flow(int unit, int idx)
   1831 {
   1832     soc_mem_t mem;
   1833     sr_rx_entry_t entry;
   1834     int rv;
   1835 
   1836     /* parameter check */
   1837     TSN_BKINFO_IS_INIT(unit);
   1838     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   1839         return (BCM_E_UNAVAIL);
   1840     }
   1841     if (idx < 0 || idx >= SRFLOWS_BKINFO(unit).max_flows_rx) {
   1842         return BCM_E_PARAM;
   1843     }
   1844 
   1845     /* Clear the entry with HW index idx+1 since entry 0 is not visible */
   1846     mem = SR_RXm;
   1847     sal_memset(&entry, 0, sizeof(entry));
   1848     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx + 1, &entry);
   1849     if (SOC_FAILURE(rv)) {
   1850         LOG_ERROR(BSL_LS_BCM_TSN,
   1851                   (BSL_META_U(unit, "Failed to write mem[%s]"),
   1852                               SOC_MEM_NAME(unit, mem)));
   1853         return rv;
   1854     }
   1855 
   1856     /* Clear MTU profile id HW */
   1857     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   1858         rv = bcmi_gh2_tsn_sr_flows_clear_rx_flow_mtu(unit, idx);
   1859         if (SOC_FAILURE(rv)) {
   1860             LOG_ERROR(BSL_LS_BCM_TSN,
   1861                       (BSL_META_U(unit, "Failed to clear mem[%s]"),
   1862                                   SOC_MEM_NAME(unit, mem)));
   1863             return rv;
   1864         }
   1865     }
   1866 
   1867     return BCM_E_NONE;
   1868 }
   1869 
   1870 /* SR flow mgmt - clear flow config - mtu */
   1871 STATIC int
   1872 bcmi_gh2_tsn_sr_flows_clear_tx_flow_mtu(int unit, int idx)
   1873 {
   1874     soc_mem_t mem;
   1875     ing_mtu_check_2_entry_t mtu_ent;
   1876     int rv;
   1877     int is_tx = 1;
   1878     uint32 hw_id;
   1879 
   1880     TSN_BKINFO_IS_INIT(unit);
   1881     if (!soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   1882         return BCM_E_UNAVAIL;
   1883     }
   1884 
   1885     hw_id = (uint32)TSN_SRFLOWS_IDX_TO_HW_ID(is_tx, idx);
   1886     mem = ING_MTU_CHECK_2m;
   1887     sal_memset(&mtu_ent, 0, sizeof(mtu_ent));
   1888     MEM_LOCK(unit, mem);
   1889     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_id, &mtu_ent);
   1890     if (SOC_FAILURE(rv)) {
   1891         LOG_ERROR(BSL_LS_BCM_TSN,
   1892                   (BSL_META_U(unit, "Failed to read mem[%s]"),
   1893                               SOC_MEM_NAME(unit, mem)));
   1894         MEM_UNLOCK(unit, mem);
   1895         return rv;
   1896     }
   1897     soc_mem_field32_set(unit, mem, &mtu_ent, MTU_PROFILE_INDEXf, 0);
   1898 
   1899     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_id, &mtu_ent);
   1900     if (SOC_FAILURE(rv)) {
   1901         LOG_ERROR(BSL_LS_BCM_TSN,
   1902                   (BSL_META_U(unit, "Failed to write mem[%s]"),
   1903                               SOC_MEM_NAME(unit, mem)));
   1904         MEM_UNLOCK(unit, mem);
   1905         return rv;
   1906     }
   1907 
   1908     MEM_UNLOCK(unit, mem);
   1909     return BCM_E_NONE;
   1910 }
   1911 
   1912 /* SR flow mgmt - clear flow config */
   1913 STATIC int
   1914 bcmi_gh2_tsn_sr_flows_clear_tx_flow(int unit, int idx)
   1915 {
   1916     soc_mem_t mem;
   1917     sr_tx_entry_t entry;
   1918     int rv;
   1919 
   1920     /* parameter check */
   1921     TSN_BKINFO_IS_INIT(unit);
   1922     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   1923         return (BCM_E_UNAVAIL);
   1924     }
   1925     if (idx < 0 || idx >= SRFLOWS_BKINFO(unit).max_flows_tx) {
   1926         return BCM_E_PARAM;
   1927     }
   1928 
   1929     /* Write to HW with HW index idx+1 since entry 0 is not visible to SW */
   1930     mem = SR_TXm;
   1931     sal_memset(&entry, 0, sizeof(entry));
   1932     MEM_LOCK(unit, mem);
   1933     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx + 1, &entry);
   1934     if (SOC_FAILURE(rv)) {
   1935         LOG_ERROR(BSL_LS_BCM_TSN,
   1936                   (BSL_META_U(unit, "Failed to read mem[%s]"),
   1937                               SOC_MEM_NAME(unit, mem)));
   1938         MEM_UNLOCK(unit, mem);
   1939         return rv;
   1940     }
   1941     soc_mem_field32_set(
   1942         unit, mem, &entry, NEXT_SNf, TSN_SRFLOWS_DEFAULT_NEXT_SN);
   1943     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx + 1, &entry);
   1944     if (SOC_FAILURE(rv)) {
   1945         LOG_ERROR(BSL_LS_BCM_TSN,
   1946                   (BSL_META_U(unit, "Failed to write mem[%s]"),
   1947                               SOC_MEM_NAME(unit, mem)));
   1948         MEM_UNLOCK(unit, mem);
   1949         return rv;
   1950     }
   1951 
   1952     /* Clear MTU profile id HW */
   1953     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   1954         rv = bcmi_gh2_tsn_sr_flows_clear_tx_flow_mtu(unit, idx);
   1955         if (SOC_FAILURE(rv)) {
   1956             LOG_ERROR(BSL_LS_BCM_TSN,
   1957                       (BSL_META_U(unit, "Failed to clear mem[%s]"),
   1958                                   SOC_MEM_NAME(unit, mem)));
   1959             MEM_UNLOCK(unit, mem);
   1960             return rv;
   1961         }
   1962     }
   1963     MEM_UNLOCK(unit, mem);
   1964 
   1965     return BCM_E_NONE;
   1966 }
   1967 
   1968 /* SR flow mgmt - reset RX flow */
   1969 STATIC int
   1970 bcmi_gh2_tsn_sr_flows_reset_rx_flow(int unit, int idx, uint32 flags)
   1971 {
   1972     soc_mem_t mem;
   1973     sr_rx_entry_t entry;
   1974     uint32 v;
   1975     int rv;
   1976 
   1977     /* parameter check */
   1978     TSN_BKINFO_IS_INIT(unit);
   1979     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   1980         return (BCM_E_UNAVAIL);
   1981     }
   1982     if (idx < 0 || idx >= SRFLOWS_BKINFO(unit).max_flows_rx) {
   1983         return BCM_E_PARAM;
   1984     }
   1985 
   1986     /* Write to HW with HW index idx+1 since entry 0 is not visible to SW */
   1987     mem = SR_RXm;
   1988     sal_memset(&entry, 0, sizeof(entry));
   1989     MEM_LOCK(unit, mem);
   1990     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx + 1, &entry);
   1991     if (SOC_FAILURE(rv)) {
   1992         LOG_ERROR(BSL_LS_BCM_TSN,
   1993                   (BSL_META_U(unit, "Failed to read mem[%s]"),
   1994                               SOC_MEM_NAME(unit, mem)));
   1995         MEM_UNLOCK(unit, mem);
   1996         return rv;
   1997     }
   1998 
   1999     /* seqnum age count down and wrong LAN clear count down */
   2000     v = soc_mem_field32_get(unit, mem, &entry, SN_AGE_OUT_ENABLEf);
   2001     if (v) {
   2002         /* Calculate the countdown if aging enabled, otherwise fill with 0 */
   2003         v = 1 << soc_mem_field32_get(unit, mem, &entry, AGE_OUT_MULTIPLIERf);
   2004     }
   2005     if (flags & BCM_TSN_SR_RX_FLOW_RESET_SEQNUM_AGE_COUNTDOWN) {
   2006         soc_mem_field32_set(
   2007             unit, mem, &entry, SN_AGE_OUT_COUNT_DOWNf, v);
   2008     }
   2009     if (flags & BCM_TSN_SR_RX_FLOW_RESET_WRONGLAN_A_AGE_COUNTDOWN) {
   2010         /* Reset the value only if the indicator bit is set */
   2011         if (soc_mem_field32_get(unit, mem, &entry, WRONG_LAN_Af)) {
   2012             soc_mem_field32_set(
   2013                 unit, mem, &entry, WRONG_LAN_A_AGE_OUT_COUNT_DOWNf, v);
   2014         }
   2015     }
   2016     if (flags & BCM_TSN_SR_RX_FLOW_RESET_WRONGLAN_B_AGE_COUNTDOWN) {
   2017         /* Reset the value only if the indicator bit is set */
   2018         if (soc_mem_field32_get(unit, mem, &entry, WRONG_LAN_Bf)) {
   2019             soc_mem_field32_set(
   2020                 unit, mem, &entry, WRONG_LAN_B_AGE_OUT_COUNT_DOWNf, v);
   2021         }
   2022     }
   2023 
   2024     /* seqnum reset state */
   2025     if (flags & BCM_TSN_SR_RX_FLOW_RESET_SEQNUM_WIN_STATE) {
   2026         soc_mem_field32_set(unit, mem, &entry, SN_RESET_STATEf, 1);
   2027     }
   2028 
   2029     /* Do final writing */
   2030     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx + 1, &entry);
   2031     if (SOC_FAILURE(rv)) {
   2032         LOG_ERROR(BSL_LS_BCM_TSN,
   2033                   (BSL_META_U(unit, "Failed to write mem[%s]"),
   2034                               SOC_MEM_NAME(unit, mem)));
   2035         MEM_UNLOCK(unit, mem);
   2036         return rv;
   2037     }
   2038     MEM_UNLOCK(unit, mem);
   2039 
   2040     return BCM_E_NONE;
   2041 }
   2042 
   2043 /* SR flow mgmt - write flow config */
   2044 STATIC int
   2045 bcmi_gh2_tsn_sr_flows_write_rx_flow(
   2046     int unit,
   2047     int idx,
   2048     bcmi_tsn_sr_rx_flow_t *config)
   2049 {
   2050     soc_mem_t mem;
   2051     sr_rx_entry_t entry;
   2052     cut_through_attribute_entry_t ct_entry;
   2053     ing_mtu_check_2_entry_t mtu_ent;
   2054     bcm_tsn_sr_rx_flow_config_t *cfg;
   2055     tsn_sr_seqnum_slice_t *sn;
   2056     int entries;
   2057     uint32 v;
   2058     int power;
   2059     int rv;
   2060     int i;
   2061     int is_tx = 0;
   2062     uint32 hw_id;
   2063     int mtu_hw_index;
   2064     bcm_tsn_mtu_profile_type_t type;
   2065 
   2066     /* parameter check */
   2067     TSN_BKINFO_IS_INIT(unit);
   2068     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   2069         return (BCM_E_UNAVAIL);
   2070     }
   2071     if (NULL == config || idx < 0 ||
   2072         idx >= SRFLOWS_BKINFO(unit).max_flows_rx) {
   2073         return BCM_E_PARAM;
   2074     }
   2075 
   2076     /* Double check the configuration is correct */
   2077     cfg = &config->config;
   2078     BCM_IF_ERROR_RETURN(bcmi_gh2_tsn_sr_flows_check_rx_flow_config(unit, cfg));
   2079     if (config->sn_slice == NULL) {
   2080         return BCM_E_PARAM;
   2081     }
   2082 
   2083     /* Validate slice before doing anything */
   2084     i = 0;
   2085     entries = soc_mem_index_count(unit, SR_SN_HISTORY_0m);
   2086     sn = (tsn_sr_seqnum_slice_t *)config->sn_slice;
   2087     for (; sn != NULL; sn = sn->next) {
   2088         /* The total number of chained slices < number of pools */
   2089         i++;
   2090         if (i > TSN_SRFLOWS_RX_SN_HIST_POOLS) {
   2091             return BCM_E_PARAM;
   2092         }
   2093 
   2094         /* Validate item values */
   2095         if (sn->index < 0 || sn->index >= TSN_SRFLOWS_RX_SN_HIST_POOLS) {
   2096             return BCM_E_PARAM;
   2097         }
   2098         if (sn->power < TSN_SRFLOWS_RX_SNPOOL_POWER_MIN ||
   2099             sn->power > TSN_SRFLOWS_RX_SNPOOL_POWER_MAX) {
   2100             return BCM_E_PARAM;
   2101         }
   2102         if (sn->offset < 0 || sn->offset > TSN_SRFLOWS_RX_SNPOOL_SIZE_MAX) {
   2103             return BCM_E_PARAM;
   2104         }
   2105         if (sn->offset % tsn_math_powers[sn->power]) {
   2106             /* offset should be multiples of the slice size */
   2107             return BCM_E_PARAM;
   2108         }
   2109         if (sn->entry < 0 || sn->entry >= entries) {
   2110             return BCM_E_PARAM;
   2111         }
   2112     }
   2113 
   2114     /*
   2115      * Per flow disable cut-through
   2116      * Write to HW with HW index (idx+flow_type_offset)+1
   2117      * since entry 0 is not visible to SW
   2118      */
   2119     if (soc_feature(unit, soc_feature_tsn_sr_flow_no_asf_select)) {
   2120         mem = CUT_THROUGH_ATTRIBUTEm;
   2121         sal_memset(&ct_entry, 0, sizeof(ct_entry));
   2122         v = (cfg->flags & BCM_TSN_SR_RX_FLOW_CONFIG_DO_NOT_CUT_THROUGH) ? 1 : 0;
   2123         soc_mem_field32_set(unit, mem, &ct_entry, DO_NOT_CUT_THROUGHf, v);
   2124         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   2125                            TSN_SRFLOWS_IDX_TO_HW_ID(0, idx),
   2126                            &ct_entry);
   2127         if (SOC_FAILURE(rv)) {
   2128             LOG_ERROR(BSL_LS_BCM_TSN,
   2129                       (BSL_META_U(unit, "Failed to write mem[%s]"),
   2130                                   SOC_MEM_NAME(unit, mem)));
   2131             return rv;
   2132         }
   2133     } else {
   2134         if (cfg->flags & BCM_TSN_SR_RX_FLOW_CONFIG_DO_NOT_CUT_THROUGH) {
   2135             LOG_VERBOSE(BSL_LS_BCM_TSN,
   2136                         (BSL_META_U(unit,
   2137                                     "SR RX flow disable cut-through "
   2138                                     "is not configurable\n")));
   2139             return BCM_E_PARAM;
   2140         }
   2141     }
   2142 
   2143     /* Write to HW with HW index idx+1 since entry 0 is not visible to SW */
   2144     mem = SR_RXm;
   2145     sal_memset(&entry, 0, sizeof(entry));
   2146     MEM_LOCK(unit, mem);
   2147     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx + 1, &entry);
   2148     if (SOC_FAILURE(rv)) {
   2149         LOG_ERROR(BSL_LS_BCM_TSN,
   2150                   (BSL_META_U(unit, "Failed to read mem[%s]"),
   2151                               SOC_MEM_NAME(unit, mem)));
   2152         MEM_UNLOCK(unit, mem);
   2153         return rv;
   2154     }
   2155 
   2156     /* Flags */
   2157     v = (cfg->flags & BCM_TSN_SR_RX_FLOW_CONFIG_ACCEPT_DUPLICATES) ? 1 : 0;
   2158     soc_mem_field32_set(unit, mem, &entry, ACCEPT_DUPLICATE_PACKETf, v);
   2159     v = (cfg->flags & BCM_TSN_SR_RX_FLOW_CONFIG_ACCEPT_PKT_IN_DROP_WINDOW) ?
   2160         1 : 0;
   2161     soc_mem_field32_set(unit, mem, &entry, ACCEPT_IN_DROP_WINDOWf, v);
   2162     v = (cfg->flags & BCM_TSN_SR_RX_FLOW_CONFIG_DROP_OUT_OF_ORDER) ? 1 : 0;
   2163     soc_mem_field32_set(unit, mem, &entry, DROP_OUT_OF_ORDERf, v);
   2164 
   2165     /* Acceptance window (already validated as a valid power-of-2 number) */
   2166     TSN_GET_LOG2(cfg->seqnum_accept_win_size, power);
   2167     assert(power >= TSN_SRFLOWS_RX_ACCEPT_POWER_MIN &&
   2168            power <= TSN_SRFLOWS_RX_ACCEPT_POWER_MAX);
   2169     v = (uint32)TSN_SRFLOWS_RX_ACCEPT_POWER_MAX - power;
   2170     soc_mem_field32_set(unit, mem, &entry, ACCEPTANCE_WINDOW_SIZEf, v);
   2171 
   2172     /* Age out time interval */
   2173     if (cfg->age_timeout == 0) {
   2174         /* Disable aging */
   2175         soc_mem_field32_set(unit, mem, &entry, AGE_OUT_MULTIPLIERf, 0);
   2176         soc_mem_field32_set(unit, mem, &entry, SN_AGE_OUT_ENABLEf, 0);
   2177     } else {
   2178         /* The actual multiplier is 2^N */
   2179         TSN_GET_LOG2(cfg->age_timeout, v);
   2180         soc_mem_field32_set(unit, mem, &entry, AGE_OUT_MULTIPLIERf, v);
   2181         /* Enable aging */
   2182         soc_mem_field32_set(unit, mem, &entry, SN_AGE_OUT_ENABLEf, 1);
   2183     }
   2184 
   2185     /* Sequence number history window size (also already validated) */
   2186     if (cfg->seqnum_history_win_size == 1) {
   2187         /* Special case: 1-bit */
   2188         v = 0;
   2189     } else {
   2190         TSN_GET_LOG2(cfg->seqnum_history_win_size, power);
   2191         assert(power >= TSN_SRFLOWS_RX_WINDOW_POWER_MIN &&
   2192                power <= TSN_SRFLOWS_RX_WINDOW_POWER_MAX);
   2193         v = (uint32)power - TSN_SRFLOWS_RX_WINDOW_POWER_MIN + 1;
   2194     }
   2195     soc_mem_field32_set(unit, mem, &entry, SN_WINDOW_SIZEf, v);
   2196 
   2197     /* Clear seqnum pool sizes to 0 (disabled by default) */
   2198     for (i = 0; i < sizeof(tsn_flow_sr_hist_sizes) / sizeof(soc_field_t); i++) {
   2199         soc_mem_field32_set(unit, mem, &entry, tsn_flow_sr_hist_sizes[i], 0);
   2200     }
   2201 
   2202     /* Write indexes to the seqnum pools */
   2203     sn = (tsn_sr_seqnum_slice_t *)config->sn_slice;
   2204     for (; sn != NULL; sn = sn->next) {
   2205         soc_mem_field32_set(
   2206             unit, mem, &entry, tsn_flow_sr_hist_indexs[sn->index], sn->entry);
   2207         soc_mem_field32_set(
   2208             unit, mem, &entry, tsn_flow_sr_hist_offsets[sn->index],
   2209             sn->offset / TSN_SRFLOWS_RX_SN_HIST_BLOCK_SIZE);
   2210         soc_mem_field32_set(
   2211             unit, mem, &entry, tsn_flow_sr_hist_sizes[sn->index],
   2212             sn->power - TSN_SRFLOWS_RX_SNPOOL_POWER_MIN + 2);
   2213     }
   2214 
   2215     /* Do final writing */
   2216     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx + 1, &entry);
   2217     if (SOC_FAILURE(rv)) {
   2218         LOG_ERROR(BSL_LS_BCM_TSN,
   2219                   (BSL_META_U(unit, "Failed to write mem[%s]"),
   2220                               SOC_MEM_NAME(unit, mem)));
   2221         MEM_UNLOCK(unit, mem);
   2222         return rv;
   2223     }
   2224     /* Unlock memory  SR_RXm */
   2225     MEM_UNLOCK(unit, mem);
   2226 
   2227     /* MTU profile id HW writing */
   2228     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   2229         hw_id = (uint32)TSN_SRFLOWS_IDX_TO_HW_ID(is_tx, idx);
   2230         mem = ING_MTU_CHECK_2m;
   2231         sal_memset(&mtu_ent, 0, sizeof(mtu_ent));
   2232         MEM_LOCK(unit, mem);
   2233         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_id, &mtu_ent);
   2234         if (SOC_FAILURE(rv)) {
   2235             LOG_ERROR(BSL_LS_BCM_TSN,
   2236                       (BSL_META_U(unit, "Failed to read mem[%s]"),
   2237                                   SOC_MEM_NAME(unit, mem)));
   2238             MEM_UNLOCK(unit, mem);
   2239             return rv;
   2240         }
   2241         type = bcmTsnMtuProfileTypeIngress;
   2242         rv = bcmi_gh2_tsn_mtu_profile_decode(
   2243                               unit, cfg->ingress_mtu_profile,
   2244                               &type, &mtu_hw_index);
   2245         if (SOC_FAILURE(rv)) {
   2246             LOG_ERROR(BSL_LS_BCM_TSN,
   2247                       (BSL_META_U(unit, "Failed to decode profile id[%d]"),
   2248                                   cfg->ingress_mtu_profile));
   2249             MEM_UNLOCK(unit, mem);
   2250             return rv;
   2251         }
   2252         soc_mem_field32_set(unit, mem, &mtu_ent,
   2253                             MTU_PROFILE_INDEXf, mtu_hw_index);
   2254 
   2255         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_id, &mtu_ent);
   2256         if (SOC_FAILURE(rv)) {
   2257             LOG_ERROR(BSL_LS_BCM_TSN,
   2258                       (BSL_META_U(unit, "Failed to write mem[%s]"),
   2259                                   SOC_MEM_NAME(unit, mem)));
   2260             MEM_UNLOCK(unit, mem);
   2261             return rv;
   2262         }
   2263         MEM_UNLOCK(unit, mem);
   2264     }
   2265 
   2266     return BCM_E_NONE;
   2267 }
   2268 
   2269 /* SR flow mgmt - write flow config */
   2270 STATIC int
   2271 bcmi_gh2_tsn_sr_flows_write_tx_flow(
   2272     int unit,
   2273     int idx,
   2274     bcmi_tsn_sr_tx_flow_t *config)
   2275 {
   2276     soc_mem_t mem;
   2277     sr_tx_entry_t entry;
   2278     cut_through_attribute_entry_t ct_entry;
   2279     ing_mtu_check_2_entry_t mtu_ent;
   2280     int rv;
   2281     uint32 v = 0;
   2282     int is_tx = 1;
   2283     uint32 hw_id;
   2284     int mtu_hw_index;
   2285     bcm_tsn_mtu_profile_type_t type;
   2286     bcm_tsn_sr_tx_flow_config_t *cfg;
   2287 
   2288     /* parameter check */
   2289     TSN_BKINFO_IS_INIT(unit);
   2290     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   2291         return (BCM_E_UNAVAIL);
   2292     }
   2293     if (NULL == config || idx < 0 ||
   2294         idx >= SRFLOWS_BKINFO(unit).max_flows_tx) {
   2295         return BCM_E_PARAM;
   2296     }
   2297 
   2298     /* Double check the configuration is correct */
   2299     cfg = &config->config;
   2300     BCM_IF_ERROR_RETURN(bcmi_gh2_tsn_sr_flows_check_tx_flow_config(unit, cfg));
   2301 
   2302     /*
   2303      * Per flow disable cut-through
   2304      * Write to HW with HW index (idx+flow_type_offset)+1
   2305      * since entry 0 is not visible to SW
   2306      */
   2307     if (soc_feature(unit, soc_feature_tsn_sr_flow_no_asf_select)) {
   2308         mem = CUT_THROUGH_ATTRIBUTEm;
   2309         sal_memset(&ct_entry, 0, sizeof(ct_entry));
   2310         v = (cfg->flags & BCM_TSN_SR_TX_FLOW_CONFIG_DO_NOT_CUT_THROUGH) ?
   2311                 1 : 0;
   2312         soc_mem_field32_set(unit, mem, &ct_entry, DO_NOT_CUT_THROUGHf, v);
   2313         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   2314                            TSN_SRFLOWS_IDX_TO_HW_ID(1, idx),
   2315                            &ct_entry);
   2316         if (SOC_FAILURE(rv)) {
   2317             LOG_ERROR(BSL_LS_BCM_TSN,
   2318                       (BSL_META_U(unit, "Failed to write mem[%s]"),
   2319                                   SOC_MEM_NAME(unit, mem)));
   2320             return rv;
   2321         }
   2322     } else {
   2323         if (cfg->flags & BCM_TSN_SR_TX_FLOW_CONFIG_DO_NOT_CUT_THROUGH) {
   2324             LOG_VERBOSE(BSL_LS_BCM_TSN,
   2325                         (BSL_META_U(unit,
   2326                                     "SR TX flow disable cut-through "
   2327                                     "is not configurable\n")));
   2328             return BCM_E_PARAM;
   2329         }
   2330     }
   2331 
   2332     /* Write to HW with HW index idx+1 since entry 0 is not visible to SW */
   2333     mem = SR_TXm;
   2334     sal_memset(&entry, 0, sizeof(entry));
   2335     MEM_LOCK(unit, mem);
   2336     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx + 1, &entry);
   2337     if (SOC_FAILURE(rv)) {
   2338         LOG_ERROR(BSL_LS_BCM_TSN,
   2339                   (BSL_META_U(unit, "Failed to read mem[%s]"),
   2340                               SOC_MEM_NAME(unit, mem)));
   2341         MEM_UNLOCK(unit, mem);
   2342         return rv;
   2343     }
   2344     soc_mem_field32_set(unit, mem, &entry, NEXT_SNf, config->config.seq_num);
   2345     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, idx + 1, &entry);
   2346     if (SOC_FAILURE(rv)) {
   2347         LOG_ERROR(BSL_LS_BCM_TSN,
   2348                   (BSL_META_U(unit, "Failed to write mem[%s]"),
   2349                               SOC_MEM_NAME(unit, mem)));
   2350         MEM_UNLOCK(unit, mem);
   2351         return rv;
   2352     }
   2353     /* Unlock memory  SR_TXm */
   2354     MEM_UNLOCK(unit, mem);
   2355 
   2356     /* MTU profile id HW writing */
   2357     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   2358         hw_id = (uint32)TSN_SRFLOWS_IDX_TO_HW_ID(is_tx, idx);
   2359         mem = ING_MTU_CHECK_2m;
   2360         sal_memset(&mtu_ent, 0, sizeof(mtu_ent));
   2361         MEM_LOCK(unit, mem);
   2362         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_id, &mtu_ent);
   2363         if (SOC_FAILURE(rv)) {
   2364             LOG_ERROR(BSL_LS_BCM_TSN,
   2365                       (BSL_META_U(unit, "Failed to read mem[%s]"),
   2366                                   SOC_MEM_NAME(unit, mem)));
   2367             MEM_UNLOCK(unit, mem);
   2368             return rv;
   2369         }
   2370         type = bcmTsnMtuProfileTypeIngress;
   2371         rv = bcmi_gh2_tsn_mtu_profile_decode(
   2372                               unit, config->config.ingress_mtu_profile,
   2373                               &type, &mtu_hw_index);
   2374         if (SOC_FAILURE(rv)) {
   2375             LOG_ERROR(BSL_LS_BCM_TSN,
   2376                       (BSL_META_U(unit, "Failed to decode profile id[%d]"),
   2377                                   config->config.ingress_mtu_profile));
   2378             MEM_UNLOCK(unit, mem);
   2379             return rv;
   2380         }
   2381         soc_mem_field32_set(unit, mem, &mtu_ent, MTU_PROFILE_INDEXf,
   2382                             mtu_hw_index);
   2383         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_id, &mtu_ent);
   2384         if (SOC_FAILURE(rv)) {
   2385             LOG_ERROR(BSL_LS_BCM_TSN,
   2386                       (BSL_META_U(unit, "Failed to write mem[%s]"),
   2387                                   SOC_MEM_NAME(unit, mem)));
   2388             MEM_UNLOCK(unit, mem);
   2389             return rv;
   2390         }
   2391         /* Unlock memory  ING_MTU_CHECK_2m */
   2392         MEM_UNLOCK(unit, mem);
   2393     }
   2394 
   2395     return BCM_E_NONE;
   2396 }
   2397 
   2398 #ifdef BCM_WARM_BOOT_SUPPORT
   2399 /* SR flow mgmt - read flow config (for warm boot) */
   2400 STATIC int
   2401 bcmi_gh2_tsn_sr_flows_read_rx_flow(
   2402     int unit,
   2403     int idx,
   2404     bcmi_tsn_sr_rx_flow_t *config)
   2405 {
   2406     soc_mem_t mem;
   2407     sr_rx_entry_t entry;
   2408     cut_through_attribute_entry_t ct_entry;
   2409     ing_mtu_check_2_entry_t mtu_ent;
   2410     bcm_tsn_sr_rx_flow_config_t *cfg;
   2411     tsn_sr_seqnum_slice_t *slice, *sn;
   2412     uint32 power;
   2413     uint32 v;
   2414     int mtu_idx, mtu_id;
   2415     int eidx;
   2416     int offs;
   2417     int rv;
   2418     int i;
   2419 
   2420     /* parameter check */
   2421     TSN_BKINFO_IS_INIT(unit);
   2422     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   2423         return (BCM_E_UNAVAIL);
   2424     }
   2425     if (NULL == config ||
   2426         idx < 0 || idx >= SRFLOWS_BKINFO(unit).max_flows_rx) {
   2427         return BCM_E_PARAM;
   2428     }
   2429 
   2430     /* This routine is for warm boot only */
   2431     if (!SOC_WARM_BOOT(unit)) {
   2432         return BCM_E_UNAVAIL;
   2433     }
   2434 
   2435     /* Get config from HW with HW index idx+1 */
   2436     mem = SR_RXm;
   2437     sal_memset(&entry, 0, sizeof(entry));
   2438     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx + 1, &entry);
   2439     if (SOC_FAILURE(rv)) {
   2440         LOG_ERROR(BSL_LS_BCM_TSN,
   2441                   (BSL_META_U(unit, "Failed to read mem[%s]"),
   2442                               SOC_MEM_NAME(unit, mem)));
   2443         return rv;
   2444     }
   2445 
   2446     /* Start compiling the configuration from HW values */
   2447     cfg = &config->config;
   2448 
   2449     /* Flags */
   2450     cfg->flags = 0;
   2451     if (soc_mem_field32_get(unit, mem, &entry, ACCEPT_DUPLICATE_PACKETf)) {
   2452         cfg->flags |= BCM_TSN_SR_RX_FLOW_CONFIG_ACCEPT_DUPLICATES;
   2453     }
   2454     if (soc_mem_field32_get(unit, mem, &entry, ACCEPT_IN_DROP_WINDOWf)) {
   2455         cfg->flags |= BCM_TSN_SR_RX_FLOW_CONFIG_ACCEPT_PKT_IN_DROP_WINDOW;
   2456     }
   2457     if (soc_mem_field32_get(unit, mem, &entry, DROP_OUT_OF_ORDERf)) {
   2458         cfg->flags |= BCM_TSN_SR_RX_FLOW_CONFIG_DROP_OUT_OF_ORDER;
   2459     }
   2460 
   2461     /* Acceptance window */
   2462     v = soc_mem_field32_get(unit, mem, &entry, ACCEPTANCE_WINDOW_SIZEf);
   2463     power = TSN_SRFLOWS_RX_ACCEPT_POWER_MAX - v;
   2464     if (power < TSN_SRFLOWS_RX_ACCEPT_POWER_MIN ||
   2465         power > TSN_SRFLOWS_RX_ACCEPT_POWER_MAX) {
   2466         return BCM_E_INTERNAL;
   2467     }
   2468     assert(power < sizeof(tsn_math_powers) / sizeof(int));
   2469     cfg->seqnum_accept_win_size = (uint32)tsn_math_powers[power];
   2470 
   2471     /* Sequence number history window size */
   2472     v = soc_mem_field32_get(unit, mem, &entry, SN_WINDOW_SIZEf);
   2473     if (v == 0) {
   2474         cfg->seqnum_history_win_size = 1;
   2475     } else {
   2476         power = v + TSN_SRFLOWS_RX_WINDOW_POWER_MIN - 1;
   2477         if (power < TSN_SRFLOWS_RX_WINDOW_POWER_MIN ||
   2478             power > TSN_SRFLOWS_RX_WINDOW_POWER_MAX) {
   2479             return BCM_E_INTERNAL;
   2480         }
   2481         assert(power < sizeof(tsn_math_powers) / sizeof(int));
   2482         cfg->seqnum_history_win_size = (uint32)tsn_math_powers[power];
   2483     }
   2484 
   2485     /* Age out time interval */
   2486     v = soc_mem_field32_get(unit, mem, &entry, SN_AGE_OUT_ENABLEf);
   2487     if (v == 0) {
   2488         cfg->age_timeout = 0;
   2489     } else {
   2490         power = soc_mem_field32_get(unit, mem, &entry, AGE_OUT_MULTIPLIERf);
   2491         assert(power < sizeof(tsn_math_powers) / sizeof(int));
   2492         cfg->age_timeout = (uint32)tsn_math_powers[power];
   2493     }
   2494 
   2495     /* Re-build SN slices */
   2496     sn = NULL;
   2497     for (i = 0; i < TSN_SRFLOWS_RX_SN_HIST_POOLS; i++) {
   2498         v = soc_mem_field32_get(unit, mem, &entry, tsn_flow_sr_hist_sizes[i]);
   2499         if (v != 0 && v != 1) {
   2500             eidx = (int)soc_mem_field32_get(
   2501                             unit, mem, &entry, tsn_flow_sr_hist_indexs[i]);
   2502             offs = (int)soc_mem_field32_get(
   2503                             unit, mem, &entry, tsn_flow_sr_hist_offsets[i]);
   2504             rv = bcmi_gh2_tsn_sr_flows_seqnum_slice_wb_restore(
   2505                     unit,
   2506                     i,
   2507                     eidx,
   2508                     offs * TSN_SRFLOWS_RX_SN_HIST_BLOCK_SIZE,
   2509                     v - 2 + TSN_SRFLOWS_RX_SNPOOL_POWER_MIN,
   2510                     &slice
   2511                  );
   2512             if (rv != BCM_E_NONE) {
   2513                 if (sn != NULL) {
   2514                     (void)bcmi_gh2_tsn_sr_flows_seqnum_slice_free(
   2515                             unit, (bcmi_tsn_sr_seqnum_slice_t)sn);
   2516                 }
   2517                 return rv;
   2518             }
   2519             if (slice != NULL) {
   2520                 slice->next = sn;
   2521                 sn = slice;
   2522             } else {
   2523                 assert(0);
   2524                 return BCM_E_INTERNAL;
   2525             }
   2526         }
   2527     }
   2528     config->sn_slice = (bcmi_tsn_sr_seqnum_slice_t)sn;
   2529 
   2530     /* Get flag from hardware  */
   2531     mem = CUT_THROUGH_ATTRIBUTEm;
   2532     sal_memset(&ct_entry, 0, sizeof(ct_entry));
   2533     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   2534                       TSN_SRFLOWS_IDX_TO_HW_ID(0, idx), &ct_entry);
   2535     if (SOC_FAILURE(rv)) {
   2536         LOG_ERROR(BSL_LS_BCM_TSN,
   2537                   (BSL_META_U(unit, "Failed to read mem[%s]"),
   2538                               SOC_MEM_NAME(unit, mem)));
   2539         return rv;
   2540     }
   2541     if (soc_mem_field32_get(unit, mem, &ct_entry, DO_NOT_CUT_THROUGHf)) {
   2542         cfg->flags |= BCM_TSN_SR_RX_FLOW_CONFIG_DO_NOT_CUT_THROUGH;
   2543     }
   2544     /* MTU SR rx flow warm boot read */
   2545     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   2546         mem = ING_MTU_CHECK_2m;
   2547 
   2548         sal_memset(&mtu_ent, 0, sizeof(mtu_ent));
   2549         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   2550                           TSN_SRFLOWS_IDX_TO_HW_ID(0, idx), &mtu_ent);
   2551         if (SOC_FAILURE(rv)) {
   2552             LOG_ERROR(BSL_LS_BCM_TSN,
   2553                     (BSL_META_U(unit, "Failed to read mem[%s]"),
   2554                                 SOC_MEM_NAME(unit, mem)));
   2555             return rv;
   2556         }
   2557         mtu_idx = soc_mem_field32_get(unit, mem, &mtu_ent, MTU_PROFILE_INDEXf);
   2558         rv = bcmi_gh2_tsn_mtu_profile_encode(unit, mtu_idx,
   2559                                              bcmTsnMtuProfileTypeIngress,
   2560                                              &mtu_id);
   2561         if (SOC_FAILURE(rv)) {
   2562             LOG_ERROR(BSL_LS_BCM_TSN,
   2563                       (BSL_META_U(unit, "Failed to encode mtu profile"
   2564                                   " from idx = %d"), mtu_idx));
   2565             return rv;
   2566         }
   2567         cfg->ingress_mtu_profile = mtu_id;
   2568     }
   2569 
   2570     return BCM_E_NONE;
   2571 }
   2572 
   2573 /* SR flow mgmt - read flow config (for warm boot) */
   2574 STATIC int
   2575 bcmi_gh2_tsn_sr_flows_read_tx_flow(
   2576     int unit,
   2577     int idx,
   2578     bcmi_tsn_sr_tx_flow_t *config)
   2579 {
   2580     soc_mem_t mem;
   2581     sr_tx_entry_t entry;
   2582     cut_through_attribute_entry_t ct_entry;
   2583     ing_mtu_check_2_entry_t mtu_ent;
   2584     int mtu_idx, mtu_id;
   2585     int rv;
   2586 
   2587     /* parameter check */
   2588     TSN_BKINFO_IS_INIT(unit);
   2589     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   2590         return (BCM_E_UNAVAIL);
   2591     }
   2592     if (NULL == config ||
   2593         idx < 0 || idx >= SRFLOWS_BKINFO(unit).max_flows_tx) {
   2594         return BCM_E_PARAM;
   2595     }
   2596 
   2597     /* This routine is for warm boot only */
   2598     if (!SOC_WARM_BOOT(unit)) {
   2599         return BCM_E_UNAVAIL;
   2600     }
   2601 
   2602     /* Get config from HW with HW index idx+1 */
   2603     mem = SR_TXm;
   2604     sal_memset(&entry, 0, sizeof(entry));
   2605     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx + 1, &entry);
   2606     if (SOC_FAILURE(rv)) {
   2607         LOG_ERROR(BSL_LS_BCM_TSN,
   2608                   (BSL_META_U(unit, "Failed to read mem[%s]"),
   2609                               SOC_MEM_NAME(unit, mem)));
   2610         return rv;
   2611     }
   2612     config->config.seq_num = soc_mem_field32_get(unit, mem, &entry, NEXT_SNf);
   2613 
   2614     /* Get config from hardware */
   2615     mem = CUT_THROUGH_ATTRIBUTEm;
   2616     sal_memset(&ct_entry, 0, sizeof(ct_entry));
   2617     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   2618                       TSN_SRFLOWS_IDX_TO_HW_ID(1, idx), &ct_entry);
   2619     if (SOC_FAILURE(rv)) {
   2620         LOG_ERROR(BSL_LS_BCM_TSN,
   2621                   (BSL_META_U(unit, "Failed to read mem[%s]"),
   2622                               SOC_MEM_NAME(unit, mem)));
   2623         return rv;
   2624     }
   2625     if (soc_mem_field32_get(unit, mem, &ct_entry, DO_NOT_CUT_THROUGHf)) {
   2626         config->config.flags |= BCM_TSN_SR_TX_FLOW_CONFIG_DO_NOT_CUT_THROUGH;
   2627     }
   2628     /* MTU SR tx flow warm boot read */
   2629     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   2630         mem = ING_MTU_CHECK_2m;
   2631 
   2632         sal_memset(&mtu_ent, 0, sizeof(mtu_ent));
   2633         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   2634                           TSN_SRFLOWS_IDX_TO_HW_ID(1, idx), &mtu_ent);
   2635         if (SOC_FAILURE(rv)) {
   2636             LOG_ERROR(BSL_LS_BCM_TSN,
   2637                     (BSL_META_U(unit, "Failed to read mem[%s]"),
   2638                                 SOC_MEM_NAME(unit, mem)));
   2639             return rv;
   2640         }
   2641         mtu_idx = soc_mem_field32_get(unit, mem, &mtu_ent, MTU_PROFILE_INDEXf);
   2642         rv = bcmi_gh2_tsn_mtu_profile_encode(unit, mtu_idx,
   2643                                              bcmTsnMtuProfileTypeIngress,
   2644                                              &mtu_id);
   2645         if (SOC_FAILURE(rv)) {
   2646             LOG_ERROR(BSL_LS_BCM_TSN,
   2647                       (BSL_META_U(unit, "Failed to encode mtu profile"
   2648                                   " from idx = %d"), mtu_idx));
   2649             return rv;
   2650         }
   2651         config->config.ingress_mtu_profile = mtu_id;
   2652     }
   2653 
   2654     return BCM_E_NONE;
   2655 }
   2656 #endif /* BCM_WARM_BOOT_SUPPORT */
   2657 
   2658 /* SR flow mgmt - get flow status */
   2659 STATIC int
   2660 bcmi_gh2_tsn_sr_flows_get_tx_flow_status(
   2661     int unit,
   2662     int idx,
   2663     bcm_tsn_sr_tx_flow_status_t *status)
   2664 {
   2665     soc_mem_t mem;
   2666     sr_tx_entry_t entry;
   2667     int rv;
   2668 
   2669     /* parameter check */
   2670     TSN_BKINFO_IS_INIT(unit);
   2671     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   2672         return (BCM_E_UNAVAIL);
   2673     }
   2674     if (NULL == status ||
   2675         idx < 0 || idx >= SRFLOWS_BKINFO(unit).max_flows_tx) {
   2676         return BCM_E_PARAM;
   2677     }
   2678 
   2679     /* Get status from HW with HW index idx+1 */
   2680     mem = SR_TXm;
   2681     sal_memset(&entry, 0, sizeof(entry));
   2682     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx + 1, &entry);
   2683     if (SOC_FAILURE(rv)) {
   2684         LOG_ERROR(BSL_LS_BCM_TSN,
   2685                   (BSL_META_U(unit, "Failed to read mem[%s]"),
   2686                               SOC_MEM_NAME(unit, mem)));
   2687         return rv;
   2688     }
   2689     status->seq_num = soc_mem_field32_get(unit, mem, &entry, NEXT_SNf);
   2690 
   2691     return BCM_E_NONE;
   2692 }
   2693 
   2694 /* SR flow mgmt - get flow status */
   2695 STATIC int
   2696 bcmi_gh2_tsn_sr_flows_get_rx_flow_status(
   2697     int unit,
   2698     int idx,
   2699     bcm_tsn_sr_rx_flow_status_t *status)
   2700 {
   2701     soc_mem_t mem;
   2702     sr_rx_entry_t entry;
   2703     int rv;
   2704 
   2705     /* parameter check */
   2706     TSN_BKINFO_IS_INIT(unit);
   2707     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   2708         return (BCM_E_UNAVAIL);
   2709     }
   2710     if (NULL == status ||
   2711         idx < 0 || idx >= SRFLOWS_BKINFO(unit).max_flows_rx) {
   2712         return BCM_E_PARAM;
   2713     }
   2714 
   2715     /* Get status from HW with HW index idx+1 */
   2716     mem = SR_RXm;
   2717     sal_memset(&entry, 0, sizeof(entry));
   2718     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, idx + 1, &entry);
   2719     if (SOC_FAILURE(rv)) {
   2720         LOG_ERROR(BSL_LS_BCM_TSN,
   2721                   (BSL_META_U(unit, "Failed to read mem[%s]"),
   2722                               SOC_MEM_NAME(unit, mem)));
   2723         return rv;
   2724     }
   2725     status->seqnum_win_in_reset =
   2726         (int)soc_mem_field32_get(unit, mem, &entry, SN_RESET_STATEf);
   2727     status->seqnum_age_countdown =
   2728         (int)soc_mem_field32_get(unit, mem, &entry, SN_AGE_OUT_COUNT_DOWNf);
   2729     status->last_history_win_seqnum =
   2730         soc_mem_field32_get(unit, mem, &entry, LAST_WINDOW_SNf);
   2731     status->last_accepted_seqnum_lan[0] =
   2732         soc_mem_field32_get(unit, mem, &entry, LAST_RECEIVED_SN_LAN_Af);
   2733     status->last_accepted_seqnum_lan[1] =
   2734         soc_mem_field32_get(unit, mem, &entry, LAST_RECEIVED_SN_LAN_Bf);
   2735     status->wrong_lan[0] =
   2736         (int)soc_mem_field32_get(unit, mem, &entry, WRONG_LAN_Af);
   2737     status->wrong_lan[1] =
   2738         (int)soc_mem_field32_get(unit, mem, &entry, WRONG_LAN_Bf);
   2739     status->wrong_lan_age_countdown[0] = (int)soc_mem_field32_get(
   2740             unit, mem, &entry, WRONG_LAN_A_AGE_OUT_COUNT_DOWNf);
   2741     status->wrong_lan_age_countdown[1] = (int)soc_mem_field32_get(
   2742             unit, mem, &entry, WRONG_LAN_B_AGE_OUT_COUNT_DOWNf);
   2743 
   2744     return BCM_E_NONE;
   2745 }
   2746 
   2747 /*
   2748  * Function:
   2749  *     bcmi_gh2_tsn_sr_port_config_get
   2750  * Purpose:
   2751  *     Get SR configuration from a port
   2752  * Parameters:
   2753  *     unit             - (IN) unit number
   2754  *     port             - (IN) port
   2755  *     config           - (OUT) port SR configuration
   2756  * Returns:
   2757  *     BCM_E_XXX
   2758  * Notes:
   2759  */
   2760 STATIC int
   2761 bcmi_gh2_tsn_sr_port_config_get(
   2762     int unit,
   2763     bcm_gport_t gport,
   2764     bcm_tsn_sr_port_config_t *config)
   2765 {
   2766     bcm_port_t              port;
   2767     sr_port_table_entry_t   sr_port_ent;
   2768     soc_mem_t               mem;
   2769     int                     rv = BCM_E_NONE;
   2770     uint32                  val;
   2771 
   2772     /* Parameter check */
   2773     if (config == NULL) {
   2774         return BCM_E_PARAM;
   2775     }
   2776 
   2777     /* Validate and convert gport to local port */
   2778     BCM_IF_ERROR_RETURN(
   2779         _bcm_esw_port_gport_validate(unit, gport, &port));
   2780 
   2781     /* Initialize the data first */
   2782     bcm_tsn_sr_port_config_t_init(config);
   2783 
   2784     /* Use PORT_TAB as major reference since all others should be the same */
   2785     mem = SR_PORT_TABLEm;
   2786     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, port, &sr_port_ent);
   2787     if (BCM_FAILURE(rv)) {
   2788         return rv;
   2789     }
   2790 
   2791     /* Check if SR enabled */
   2792     val = soc_mem_field32_get(
   2793             unit, mem, &sr_port_ent, ING_SR_ENABLEf);
   2794     if (val) {
   2795         /* SR port type */
   2796         val = soc_mem_field32_get(unit, mem, &sr_port_ent, ING_SR_TYPEf);
   2797         config->port_type = (bcm_tsn_sr_port_type_t)(val + 1);
   2798 
   2799         /* Interlink role */
   2800         val = soc_mem_field32_get(unit, mem, &sr_port_ent, ING_SR_PORT_ROLEf);
   2801         config->interlink_role = val ? 0 : 1;
   2802 
   2803         /* sr mode */
   2804         config->port_mode = (bcm_tsn_sr_port_mode_t)
   2805             soc_mem_field32_get(unit, mem, &sr_port_ent, ING_SR_MODEf);
   2806 
   2807         /* LAN ID  */
   2808         config->lan_id = (uint8)
   2809             soc_mem_field32_get(unit, mem, &sr_port_ent, ING_SR_LAN_IDf);
   2810 
   2811         /* NET ID */
   2812         config->net_id = (uint8)
   2813             soc_mem_field32_get(unit, mem, &sr_port_ent, ING_SR_NET_IDf);
   2814 
   2815         /* mac_da_flows */
   2816         val = soc_mem_field32_get(
   2817                 unit, mem, &sr_port_ent, FLOW_ID_SOURCE_PRIORITYf);
   2818         config->mac_da_flows = val ? 1 : 0;
   2819     } else {
   2820         /* SR disabled */
   2821         config->port_type = bcmTsnSrPortTypeNone;
   2822     }
   2823 
   2824     return BCM_E_NONE;
   2825 }
   2826 
   2827 /*
   2828  * SR port stub for config set to support Modified-PRP configuration.
   2829  *    Note: Use port_type=bcmTsnSrPortTypeCount to configure Modified-PRP port
   2830  */
   2831 STATIC int
   2832 bcmi_gh2_tsn_sr_port_config_apply(
   2833     int unit,
   2834     bcm_port_t port,
   2835     bcm_tsn_sr_port_config_t *ori_config,
   2836     bcm_tsn_sr_port_config_t *new_config)
   2837 {
   2838     soc_mem_t mem;
   2839     uint32 entry[SOC_MAX_MEM_WORDS];
   2840     soc_field_t fld;
   2841     uint32 val;
   2842     int ptab;
   2843     bcm_trunk_t trunk_id;
   2844     int rv;
   2845 
   2846     /* Port tables to write */
   2847     const soc_mem_t mem_list[] = {
   2848         SR_PORT_TABLEm,
   2849         SR_LPORT_TABm,
   2850         SR_ING_EGR_PORTm,
   2851         SR_ING_EGR_TRUNKm,
   2852         SR_EGR_PORTm,
   2853         SR_EGR_ING_PORTm
   2854     };
   2855 
   2856     /* Fields for different port tables */
   2857     const soc_field_t fields_sr_enable[] = {
   2858         ING_SR_ENABLEf,
   2859         ING_SR_ENABLEf,
   2860         EGR_SR_ENABLEf,
   2861         EGR_SR_ENABLEf,
   2862         EGR_SR_ENABLEf,
   2863         ING_SR_ENABLEf
   2864     };
   2865     const soc_field_t fields_sr_type[] = {
   2866         ING_SR_TYPEf,
   2867         ING_SR_TYPEf,
   2868         EGR_SR_TYPEf,
   2869         EGR_SR_TYPEf,
   2870         EGR_SR_TYPEf,
   2871         ING_SR_TYPEf
   2872     };
   2873     const soc_field_t fields_sr_role[] = {
   2874         ING_SR_PORT_ROLEf,
   2875         ING_SR_PORT_ROLEf,
   2876         EGR_SR_PORT_ROLEf,
   2877         EGR_SR_PORT_ROLEf,
   2878         EGR_SR_PORT_ROLEf,
   2879         ING_SR_PORT_ROLEf
   2880     };
   2881     const soc_field_t fields_sr_mode[] = {
   2882         ING_SR_MODEf,
   2883         ING_SR_MODEf,
   2884         EGR_SR_MODEf,
   2885         EGR_SR_MODEf,
   2886         EGR_SR_MODEf,
   2887         ING_SR_MODEf
   2888     };
   2889     const soc_field_t fields_sr_lanid[] = {
   2890         ING_SR_LAN_IDf,
   2891         ING_SR_LAN_IDf,
   2892         EGR_SR_LAN_IDf,
   2893         EGR_SR_LAN_IDf,
   2894         EGR_SR_LAN_IDf,
   2895         ING_SR_LAN_IDf
   2896     };
   2897     const soc_field_t fields_sr_netid[] = {
   2898         ING_SR_NET_IDf,
   2899         ING_SR_NET_IDf,
   2900         EGR_SR_NET_IDf,
   2901         EGR_SR_NET_IDf,
   2902         EGR_SR_NET_IDf,
   2903         ING_SR_NET_IDf
   2904     };
   2905     const soc_field_t fields_sr_flowsrc[] = {
   2906         FLOW_ID_SOURCE_PRIORITYf,
   2907         FLOW_ID_SOURCE_PRIORITYf,
   2908         INVALIDf,
   2909         INVALIDf,
   2910         INVALIDf,
   2911         INVALIDf
   2912     };
   2913     int mem_idx;
   2914     bcm_module_t my_modid = -1;
   2915     int src_trk_idx = 0; /* Source Trunk table index.*/
   2916     uint32 mem_entry[SOC_MAX_MEM_WORDS];
   2917 
   2918     BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid));
   2919 
   2920     assert(NULL != ori_config && NULL != new_config);
   2921 
   2922     /* Update HW only if it's changed */
   2923     if (!sal_memcmp(ori_config, new_config, sizeof(*ori_config))) {
   2924         return BCM_E_NONE;
   2925     }
   2926 
   2927     /* Apply to all the port tables */
   2928     for (ptab = 0; ptab < COUNTOF(mem_list); ptab++) {
   2929         mem = mem_list[ptab];
   2930 
   2931         if (mem == SR_LPORT_TABm) {
   2932             BCM_IF_ERROR_RETURN(
   2933                 _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
   2934                                                       port, &src_trk_idx));
   2935 
   2936             BCM_IF_ERROR_RETURN(
   2937                 soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY,
   2938                              src_trk_idx, mem_entry));
   2939 
   2940             mem_idx = soc_mem_field32_get(unit, SOURCE_TRUNK_MAP_TABLEm,
   2941                                           mem_entry, LPORT_PROFILE_IDXf);
   2942         } else if (mem == SR_ING_EGR_TRUNKm) {
   2943             /* Check if the port belongs to a trunk */
   2944             rv = bcm_esw_trunk_find(unit, my_modid, port, &trunk_id);
   2945             if (BCM_SUCCESS(rv)) {
   2946                 /* Port is member of a valid trunk */
   2947                 mem_idx = trunk_id;
   2948             } else {
   2949                 /* Port is not member of any valid trunk */
   2950                 continue;
   2951             }
   2952         } else {
   2953             mem_idx = port;
   2954         }
   2955         /* Read the original entry for modification */
   2956         sal_memset(entry, 0, sizeof(entry));
   2957         BCM_IF_ERROR_RETURN(
   2958             soc_mem_read(unit, mem, MEM_BLOCK_ANY, mem_idx, entry));
   2959 
   2960         /* Check SR enable */
   2961         if (new_config->port_type == bcmTsnSrPortTypeNone) {
   2962             /*
   2963              * SR disabled: just write SR_ENABLE and all other fields are 0
   2964              */
   2965 
   2966             /* SR enable = 0 */
   2967             fld = fields_sr_enable[ptab];
   2968             val = 0;
   2969             soc_mem_field32_set(unit, mem, entry, fld, val);
   2970         } else {
   2971             /*
   2972              * SR enabled: write configuration and enable it at last
   2973              */
   2974 
   2975             /* SR type */
   2976             fld = fields_sr_type[ptab];
   2977             val = new_config->port_type - 1;
   2978             soc_mem_field32_set(unit, mem, entry, fld, val);
   2979 
   2980             /* SR role */
   2981             fld = fields_sr_role[ptab];
   2982             val = new_config->interlink_role ? 0 : 1;
   2983             soc_mem_field32_set(unit, mem, entry, fld, val);
   2984 
   2985             /* SR mode */
   2986             fld = fields_sr_mode[ptab];
   2987             val = new_config->port_mode;
   2988             soc_mem_field32_set(unit, mem, entry, fld, val);
   2989 
   2990             /* SR LAN ID */
   2991             fld = fields_sr_lanid[ptab];
   2992             val = new_config->lan_id;
   2993             soc_mem_field32_set(unit, mem, entry, fld, val);
   2994 
   2995             /* SR NET ID */
   2996             fld = fields_sr_netid[ptab];
   2997             val = new_config->net_id;
   2998             soc_mem_field32_set(unit, mem, entry, fld, val);
   2999 
   3000             /* SR flow ID source priority (not for all tables) */
   3001             fld = fields_sr_flowsrc[ptab];
   3002             if (fld != INVALIDf) {
   3003                 val = new_config->mac_da_flows ? 1 : 0;
   3004                 soc_mem_field32_set(unit, mem, entry, fld, val);
   3005             }
   3006 
   3007             /* Write SR enable at last */
   3008             fld = fields_sr_enable[ptab];
   3009             val = 1;
   3010             soc_mem_field32_set(unit, mem, entry, fld, val);
   3011         }
   3012 
   3013         /* Write the new configuration */
   3014         BCM_IF_ERROR_RETURN(
   3015             soc_mem_write(unit, mem, MEM_BLOCK_ALL, mem_idx, entry));
   3016     }
   3017 
   3018     return BCM_E_NONE;
   3019 }
   3020 
   3021 /* SR PRP port forwarding: callback for destroying customer header match */
   3022 STATIC int
   3023 bcmi_gh2_tsn_sr_port_prp_forwarding_destroy_switch_match(
   3024     int unit,
   3025     int match_id,
   3026     bcm_switch_match_config_info_t *config_info,
   3027     void *user_data)
   3028 {
   3029     bcm_port_t prp_port;
   3030 
   3031     if (NULL == user_data || NULL == config_info) {
   3032         return BCM_E_INTERNAL; /* should not happen */
   3033     }
   3034 
   3035     prp_port = *((bcm_port_t *)user_data);
   3036     if (config_info->value32 == PRP_FORWARDING_CH_ENCAP_VALUE(0, prp_port) ||
   3037         config_info->value32 == PRP_FORWARDING_CH_ENCAP_VALUE(1, prp_port)) {
   3038         uint32                      match_id_hw;
   3039         bcm_switch_match_service_t  match_service;
   3040 
   3041         /* need to clean PRP_PACKETf LPORT_PROFILE_IDXf by ourselves */
   3042         BCM_IF_ERROR_RETURN(
   3043             bcmi_switch_match_hw_id_get(
   3044                 unit, match_id, &match_service, &match_id_hw));
   3045         if (bcmSwitchMatchServiceCustomHeader != match_service) {
   3046             BCM_IF_ERROR_RETURN(BCM_E_INTERNAL);
   3047         }
   3048         BCM_IF_ERROR_RETURN(
   3049             soc_mem_field32_modify(
   3050                 unit, CUSTOM_HEADER_POLICY_TABLEm, match_id_hw,
   3051                 PRP_PACKETf, 0));
   3052         BCM_IF_ERROR_RETURN(
   3053             soc_mem_field32_modify(
   3054                 unit, CUSTOM_HEADER_POLICY_TABLEm, match_id_hw,
   3055                 LPORT_PROFILE_IDXf, 0));
   3056 
   3057         /* invoke API to delete switch_match */
   3058         BCM_IF_ERROR_RETURN(
   3059             bcm_esw_switch_match_config_delete(
   3060                 unit, bcmSwitchMatchServiceCustomHeader, match_id));
   3061     }
   3062 
   3063     return BCM_E_NONE;
   3064 }
   3065 
   3066 /* SR PRP port forwarding: callback for destroying customer header encap */
   3067 STATIC int
   3068 bcmi_gh2_tsn_sr_port_prp_forwarding_destroy_switch_encap(
   3069     int unit,
   3070     bcm_if_t encap_id,
   3071     bcm_switch_encap_info_t *encap_info,
   3072     void *user_data)
   3073 {
   3074     bcm_port_t prp_port;
   3075 
   3076     if (NULL == user_data || NULL == encap_info) {
   3077         return BCM_E_INTERNAL; /* should not happen */
   3078     }
   3079 
   3080     prp_port = *((bcm_port_t *)user_data);
   3081     if (encap_info->value32 == PRP_FORWARDING_CH_ENCAP_VALUE(0, prp_port) ||
   3082         encap_info->value32 == PRP_FORWARDING_CH_ENCAP_VALUE(1, prp_port)) {
   3083         BCM_IF_ERROR_RETURN(
   3084             bcm_esw_switch_encap_destroy(unit, encap_id));
   3085     }
   3086 
   3087     return BCM_E_NONE;
   3088 }
   3089 
   3090 
   3091 /* helper function to remove all ifp rules that created on this specific port */
   3092 STATIC int
   3093 bcmi_gh2_tsn_sr_remove_all_field_entries(
   3094     int unit,
   3095     bcm_field_group_t field_group,
   3096     bcm_port_t target_port)
   3097 {
   3098     int               ifp_group_entry_num;
   3099     bcm_field_entry_t *ifp_group_entry_array = NULL;
   3100     int               ifp_group_entry_array_size;
   3101     int               i;
   3102 
   3103     /* 1st time to get the array size that we need */
   3104     PRP_FORWARDING_ERROR_RETURN(
   3105         bcm_esw_field_entry_multi_get(
   3106             unit, PRP_FORWARDING_REDIRECT_GROUP(unit), 0,
   3107             NULL, &ifp_group_entry_num));
   3108 
   3109     ifp_group_entry_array_size = ifp_group_entry_num;
   3110     ifp_group_entry_array = (bcm_field_entry_t *)
   3111         sal_alloc(sizeof(bcm_field_entry_t) * ifp_group_entry_array_size,
   3112                   "ifp_group_entry_array");
   3113     if (NULL == ifp_group_entry_array) {
   3114         PRP_FORWARDING_ERROR_RETURN(BCM_E_MEMORY);
   3115     }
   3116 
   3117     /* 2nd time to get all entries to the array that we just allocated */
   3118     PRP_FORWARDING_ERROR_RETURN_WITH_CLEAN(
   3119         bcm_esw_field_entry_multi_get(
   3120             unit, PRP_FORWARDING_REDIRECT_GROUP(unit),
   3121             ifp_group_entry_array_size,
   3122             ifp_group_entry_array, &ifp_group_entry_num),
   3123         sal_free(ifp_group_entry_array));
   3124     assert(ifp_group_entry_num == ifp_group_entry_array_size);
   3125 
   3126     /* remove the entries that qulified on this specific target port */
   3127     for (i = 0; i < ifp_group_entry_array_size; i++) {
   3128         bcm_port_t data = 0, mask = 0;
   3129 
   3130         PRP_FORWARDING_ERROR_RETURN_WITH_CLEAN(
   3131             bcm_esw_field_qualify_InPort_get(
   3132                 unit, ifp_group_entry_array[i], &data, &mask),
   3133             sal_free(ifp_group_entry_array));
   3134         if (data == target_port) {
   3135             PRP_FORWARDING_ERROR_RETURN_WITH_CLEAN(
   3136                 bcm_esw_field_entry_remove(
   3137                     unit, ifp_group_entry_array[i]),
   3138                 sal_free(ifp_group_entry_array));
   3139             PRP_FORWARDING_ERROR_RETURN_WITH_CLEAN(
   3140                 bcm_esw_field_entry_destroy(
   3141                     unit, ifp_group_entry_array[i]),
   3142                 sal_free(ifp_group_entry_array));
   3143             break;
   3144         }
   3145     }
   3146     sal_free(ifp_group_entry_array);
   3147     ifp_group_entry_array = NULL;
   3148 
   3149     return BCM_E_NONE;
   3150 }
   3151 
   3152 
   3153 /* SR PRP port forwarding: cancel prp forwarding at specific port */
   3154 STATIC void
   3155 bcmi_gh2_tsn_sr_port_prp_forwarding_destroy(
   3156     int unit,
   3157     bcm_port_t  prp_port)
   3158 {
   3159     /* destroy IFP rule on this prp port
   3160      *  : we traverse each entry in IFP group
   3161      *    delete it if this entry qualify this specified prp_port
   3162      */
   3163     assert(PRP_FORWARDING_REDIRECT_GROUP_INVALID !=
   3164            PRP_FORWARDING_REDIRECT_GROUP(unit));
   3165     PRP_FORWARDING_DESTROY_ERROR_RETURN(
   3166         bcmi_gh2_tsn_sr_remove_all_field_entries(
   3167             unit, PRP_FORWARDING_REDIRECT_GROUP(unit), prp_port));
   3168 
   3169     /* cleanup CustomHeader match and policy */
   3170     PRP_FORWARDING_DESTROY_ERROR_RETURN(
   3171         bcm_esw_switch_match_config_traverse(
   3172             unit, bcmSwitchMatchServiceCustomHeader,
   3173             bcmi_gh2_tsn_sr_port_prp_forwarding_destroy_switch_match,
   3174             (void *)&prp_port));
   3175 
   3176     /* cleanup CustomHeader encap */
   3177     PRP_FORWARDING_DESTROY_ERROR_RETURN(
   3178         bcm_esw_switch_encap_traverse(
   3179             unit,
   3180             bcmi_gh2_tsn_sr_port_prp_forwarding_destroy_switch_encap,
   3181             (void *)&prp_port));
   3182 
   3183 }
   3184 
   3185 /*
   3186  * SR PRP port forwarding: setup prp forwarding at specific port
   3187  *
   3188  * Note
   3189  *  1. Two encacp entries(CH1 and CH2) for this PRP port
   3190  *      - CH1 is for Non-PRP CustomHeader and CH2 is for PRP CustomHeader.
   3191  *      - API returned encap_id for CH1 is N and CH2's encap_id must be N + 1
   3192  *          >> HW behavior assert CH1 and CH2 encacp entries is continued.
   3193  *  2. CustomHeader is expected will be engaged for PRP support only on the
   3194  *      GH2 device declared TSN-SR for PRP is supported.
   3195  *      - Thus two CustomHeader encap table entries directly mapped for
   3196  *         assigned PRP port.
   3197  *        >> CH1 entry : encacp_id = CustomHeader_type || prp_port * 2
   3198  *        >> CH2 entry : encacp_id = CustomHeader_type || prp_port * 2 + 1
   3199  *  3. One IFP rule for PRP-Port encacp on CH1(1st entry) and the HW
   3200  *      automatically select the 2nd entry for CH2.
   3201  *  4. two CustomHeader Match/Policy entries required for PRP_Port (no
   3202  *      assertion on continued entries in HW).
   3203  *      >> SW apply two entries as continued as well.
   3204  */
   3205 STATIC int
   3206 bcmi_gh2_tsn_sr_port_prp_forwarding_create(
   3207     int unit,
   3208     bcm_port_t  prp_port)
   3209 {
   3210     bcm_field_entry_t                   fp_entry;
   3211     bcm_if_t                            encap_id_prp, encap_id_non_prp;
   3212     bcm_switch_encap_info_t             encap_info;
   3213     int                                 match_id_prp, match_id_non_prp;
   3214     int                                 i;
   3215     int lport_profile_idx;
   3216     bcm_module_t my_modid = -1;
   3217     int src_trk_idx = 0; /* Source Trunk table index.*/
   3218     uint32 mem_entry[SOC_MAX_MEM_WORDS];
   3219 
   3220     BCM_IF_ERROR_RETURN(
   3221         bcm_esw_stk_my_modid_get(unit, &my_modid));
   3222 
   3223     /* setup switch_match on lb_port if 1st time to create prp port */
   3224     if (0 == PRP_FORWARDING_SWITCH_INIT(unit)) {
   3225         bcm_switch_match_control_info_t match_control_info;
   3226 
   3227         /* enable CustomHeader match/encap on loopbcak port
   3228          *   Note. because tsn module is inited before switch module
   3229          *         so we let switch_match_control setup at 1st prp-port create
   3230          */
   3231         bcm_switch_match_control_info_t_init(&match_control_info);
   3232         match_control_info.port_enable = TRUE;
   3233         match_control_info.mask32 = PRP_FORWARDING_CH_HEADER_MASK;
   3234         PRP_FORWARDING_CREATE_ERROR_RETURN(
   3235             bcm_esw_switch_match_control_set(
   3236                 unit, bcmSwitchMatchServiceCustomHeader,
   3237                 bcmSwitchMatchControlPortEnable,
   3238                 PRP_FORWARDING_REDIRECT_GPORT(unit), &match_control_info));
   3239 
   3240         PRP_FORWARDING_CREATE_ERROR_RETURN(
   3241             bcm_esw_switch_match_control_set(
   3242                 unit, bcmSwitchMatchServiceCustomHeader,
   3243                 bcmSwitchMatchControlMatchMask,
   3244                 PRP_FORWARDING_REDIRECT_GPORT(unit), &match_control_info));
   3245 
   3246         PRP_FORWARDING_CREATE_ERROR_RETURN(
   3247             bcm_esw_port_control_set(
   3248                 unit, PRP_FORWARDING_REDIRECT_PORT(unit),
   3249                 bcmPortControlCustomHeaderEncapEnable, TRUE));
   3250 
   3251         PRP_FORWARDING_SWITCH_INIT(unit) = 1;
   3252     }
   3253 
   3254     /* create two CustomHeader encap :
   3255      *   step 1. create two continuous encap id
   3256      *           (with the same encap value for non-prp at first)
   3257      *   step 2. set 2nd encap id as prp value
   3258      */
   3259     bcm_switch_encap_info_t_init(&encap_info);
   3260     encap_info.encap_service = BCM_SWITCH_ENCAP_SERVICE_CUSTOM_HEADER;
   3261     encap_info.value32 = PRP_FORWARDING_CH_ENCAP_VALUE(1, prp_port);
   3262     PRP_FORWARDING_CREATE_ERROR_RETURN(
   3263         _bcm_hr3_switch_encap_create(
   3264             unit, &encap_info, 2, &encap_id_non_prp));
   3265 
   3266     encap_id_prp = encap_id_non_prp + 1;
   3267     encap_info.value32 = PRP_FORWARDING_CH_ENCAP_VALUE(0, prp_port);
   3268     PRP_FORWARDING_CREATE_ERROR_RETURN(
   3269         bcm_esw_switch_encap_set(
   3270             unit, encap_id_prp, &encap_info));
   3271 
   3272     /* setup two CustomHeader match and policy :
   3273      *  ==> let packet get correct orignal prp port
   3274      */
   3275     for (i = 0; i < 2; i++) {
   3276         int is_prp = i;
   3277         int *match_id_ptr = is_prp ? &match_id_prp : &match_id_non_prp;
   3278         bcm_switch_match_config_info_t match_info;
   3279         bcm_switch_match_service_t     match_service;
   3280         uint32                         match_id_hw;
   3281 
   3282         bcm_switch_match_config_info_t_init(&match_info);
   3283         match_info.value32 = PRP_FORWARDING_CH_ENCAP_VALUE(is_prp ? 0 : 1,
   3284                                                            prp_port);
   3285         PRP_FORWARDING_CREATE_ERROR_RETURN(
   3286             bcm_esw_switch_match_config_add(
   3287                 unit, bcmSwitchMatchServiceCustomHeader,
   3288                 &match_info, match_id_ptr));
   3289         PRP_FORWARDING_CREATE_ERROR_RETURN(
   3290             bcmi_switch_match_hw_id_get(
   3291                 unit, *match_id_ptr, &match_service, &match_id_hw));
   3292         if (bcmSwitchMatchServiceCustomHeader != match_service) {
   3293             PRP_FORWARDING_CREATE_ERROR_RETURN(BCM_E_INTERNAL);
   3294         }
   3295 
   3296         PRP_FORWARDING_CREATE_ERROR_RETURN(
   3297             soc_mem_field32_modify(
   3298                 unit, CUSTOM_HEADER_POLICY_TABLEm, match_id_hw,
   3299                 PRP_PACKETf, is_prp ? 1 : 0));
   3300 
   3301         BCM_IF_ERROR_RETURN(
   3302             _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
   3303                                                   prp_port, &src_trk_idx));
   3304         BCM_IF_ERROR_RETURN(
   3305             soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY,
   3306                          src_trk_idx, mem_entry));
   3307 
   3308         lport_profile_idx = soc_mem_field32_get(unit, SOURCE_TRUNK_MAP_TABLEm,
   3309                                                 mem_entry, LPORT_PROFILE_IDXf);
   3310 
   3311         PRP_FORWARDING_CREATE_ERROR_RETURN(
   3312             soc_mem_field32_modify(
   3313                 unit, CUSTOM_HEADER_POLICY_TABLEm, match_id_hw,
   3314                 LPORT_PROFILE_IDXf, lport_profile_idx));
   3315     }
   3316 
   3317     /* add IFP rule that apply on the packet from this PRP port
   3318      *   1. change NET_ID source from packet (for validate the packet path ID)
   3319      *   2. encap customer header
   3320      *      (we use id "encap_id_non_prp"
   3321      *       , hw will auto select "encap_id_prp" if the packet is prp-packet)
   3322      *   3. redirect packet to loopback port
   3323      */
   3324     PRP_FORWARDING_CREATE_ERROR_RETURN(
   3325         bcm_esw_field_entry_create(
   3326             unit, PRP_FORWARDING_REDIRECT_GROUP(unit), &fp_entry));
   3327     PRP_FORWARDING_CREATE_ERROR_RETURN(
   3328         bcm_esw_field_qualify_InPort(unit, fp_entry,
   3329                                      prp_port, BCM_FIELD_EXACT_MATCH_MASK));
   3330     PRP_FORWARDING_CREATE_ERROR_RETURN(
   3331         bcm_esw_field_action_add(unit, fp_entry,
   3332                                  bcmFieldActionSRNetIdSource,
   3333                                  BCM_FIELD_SR_NET_ID_SOURCE_PACKET, 0));
   3334     PRP_FORWARDING_CREATE_ERROR_RETURN(
   3335         bcm_esw_field_action_add(unit, fp_entry,
   3336                                  bcmFieldActionSwitchEncap,
   3337                                  encap_id_non_prp, 0));
   3338     PRP_FORWARDING_CREATE_ERROR_RETURN(
   3339         bcm_esw_field_action_add(unit, fp_entry,
   3340                                  bcmFieldActionRedirectPort,
   3341                                  SOC_BASE_MODID(unit),
   3342                                  PRP_FORWARDING_REDIRECT_PORT(unit)));
   3343     PRP_FORWARDING_CREATE_ERROR_RETURN(
   3344         bcm_esw_field_entry_install(unit, fp_entry));
   3345 
   3346     return BCM_E_NONE;
   3347 }
   3348 
   3349 /* SR PRP port forwarding: cleanup all prp forwaring */
   3350 STATIC void
   3351 bcmi_gh2_tsn_sr_port_prp_forwarding_cleanup(
   3352     int unit,
   3353     int init_error)
   3354 {
   3355     bcm_tsn_sr_port_config_t        old_config;
   3356     bcm_tsn_sr_port_config_t        new_config;
   3357 
   3358     /* skip prp-init if sdk not enable this feature */
   3359     if (0 == PRP_FORWARDING_ENABLE(unit)) {
   3360         return;
   3361     }
   3362 
   3363     /* set loopback port back to prp disable */
   3364     PRP_FORWARDING_CLEAN_ERROR_RETURN(
   3365         bcmi_gh2_tsn_sr_port_config_get(
   3366             unit, PRP_FORWARDING_REDIRECT_GPORT(unit), &old_config));
   3367     new_config = old_config;
   3368     new_config.port_type = bcmTsnSrPortTypeNone;
   3369     new_config.interlink_role = 1;
   3370     PRP_FORWARDING_CLEAN_ERROR_RETURN(
   3371         bcmi_gh2_tsn_sr_port_config_apply(
   3372             unit, PRP_FORWARDING_REDIRECT_PORT(unit),
   3373             &old_config, &new_config));
   3374 
   3375     /* destroy IFP group for prp port */
   3376     if (PRP_FORWARDING_REDIRECT_GROUP_INVALID !=
   3377         PRP_FORWARDING_REDIRECT_GROUP(unit)) {
   3378 
   3379         /* if "init failed in tsn module" or
   3380          *    "only init tsn module" (SOC_F_ALL_MODULES_INITED flag is setup)
   3381          *   ==> need to clean IFP /customer header created by prp-forwarding
   3382          * if during "init all"
   3383          *   (all module would clean resource by themselves,
   3384          *    and SOC_F_ALL_MODULES_INITED flag would not be setup)
   3385          *   ==> need not clean IFP /customer header
   3386          */
   3387         if ((1 == init_error) ||
   3388             (SOC_CONTROL(unit)->soc_flags & SOC_F_ALL_MODULES_INITED)) {
   3389 
   3390             /* For each PRP-port been setup before,
   3391              * clean their CH encap and IFP entries
   3392              */
   3393             bcm_port_t                port;
   3394             bcm_tsn_sr_port_config_t  config;
   3395 
   3396             PBMP_ITER(PBMP_PORT_ALL(unit), port) {
   3397                 bcm_gport_t gport;
   3398 
   3399                 PRP_FORWARDING_CLEAN_ERROR_RETURN(
   3400                     bcm_esw_port_gport_get(unit, port, &gport));
   3401 
   3402                 PRP_FORWARDING_CLEAN_ERROR_RETURN(
   3403                     bcmi_gh2_tsn_sr_port_config_get(unit, gport, &config));
   3404 
   3405                 if (1 == PRP_FORWARDING_NEED_PRP_SETTING(config)) {
   3406                     bcmi_gh2_tsn_sr_port_prp_forwarding_destroy(unit, port);
   3407                 }
   3408             }
   3409 
   3410             /* delete ifp rule for loobpack port in the group */
   3411             PRP_FORWARDING_CLEAN_ERROR_RETURN(
   3412                 bcmi_gh2_tsn_sr_remove_all_field_entries(
   3413                     unit, PRP_FORWARDING_REDIRECT_GROUP(unit),
   3414                     PRP_FORWARDING_REDIRECT_PORT(unit)));
   3415 
   3416             /* destroy ifp group */
   3417             PRP_FORWARDING_CLEAN_ERROR_RETURN(
   3418                 bcm_esw_field_group_destroy(
   3419                     unit, PRP_FORWARDING_REDIRECT_GROUP(unit)));
   3420 
   3421         } else {
   3422             /* group_id should has been free by field module, do nothing */
   3423         }
   3424         PRP_FORWARDING_REDIRECT_GROUP(unit) =
   3425             PRP_FORWARDING_REDIRECT_GROUP_INVALID;
   3426     }
   3427 
   3428     /* destroy mutex */
   3429     if (gh2_tsn_bkinfo[unit]->gh2_prp_forwarding_bk_info.mutex != NULL) {
   3430         sal_mutex_destroy(
   3431             gh2_tsn_bkinfo[unit]->gh2_prp_forwarding_bk_info.mutex);
   3432         gh2_tsn_bkinfo[unit]->gh2_prp_forwarding_bk_info.mutex = NULL;
   3433     }
   3434 }
   3435 
   3436 /* SR PRP port forwarding: init prp forwaring feature */
   3437 STATIC int
   3438 bcmi_gh2_tsn_sr_port_prp_forwarding_init(
   3439     int unit)
   3440 {
   3441     uint32                          vlan_flags;
   3442     bcm_field_qset_t                qset;
   3443     bcm_field_entry_t               fp_entry;
   3444     bcm_tsn_sr_port_config_t        old_config;
   3445     bcm_tsn_sr_port_config_t        new_config;
   3446     pbmp_t                          pbmp;
   3447     bcm_vlan_data_t                 *vlan_list = NULL;
   3448     int                             vlan_cnt = 0;
   3449     int                             port;
   3450 
   3451     /*
   3452      *  INIT BOOKKEEPING
   3453      */
   3454 
   3455     /* skip prp-init if sdk not enable this feature */
   3456     port = soc_property_get(unit, spn_SR_PRP_ENABLE, 0);
   3457     PRP_FORWARDING_ENABLE(unit) = 0;
   3458     if (BCM_PBMP_MEMBER(PBMP_PORT_ALL(unit), port)) {
   3459         /* Check if belong to valid ports, except port 0 */
   3460         PRP_FORWARDING_ENABLE(unit) = 1;
   3461     } else {
   3462         /*
   3463          * port = 0 : feature disabled.
   3464          * other invalid port id : error configuration.
   3465          */
   3466         if (port != 0) {
   3467             LOG_ERROR(BSL_LS_BCM_TSN,
   3468                       (BSL_META_U(unit,
   3469                                   "PRP loopback port %d is an "
   3470                                   "invalid port.\n"), port));
   3471             return BCM_E_CONFIG;
   3472         }
   3473     }
   3474 
   3475     if (0 == PRP_FORWARDING_ENABLE(unit)) {
   3476         return BCM_E_NONE;
   3477     }
   3478 
   3479     /* config switch_match until 1st time to setup prp-port
   3480      *  (because switch module is inited after tsn module)
   3481      */
   3482     PRP_FORWARDING_SWITCH_INIT(unit) = 0;
   3483 
   3484     PRP_FORWARDING_REDIRECT_PORT(unit) = port;
   3485     BCM_GPORT_LOCAL_SET(PRP_FORWARDING_REDIRECT_GPORT(unit),
   3486                         PRP_FORWARDING_REDIRECT_PORT(unit));
   3487 
   3488     PRP_FORWARDING_ERROR_RETURN(
   3489         bcmi_gh2_tsn_sr_port_config_get(
   3490             unit, PRP_FORWARDING_REDIRECT_GPORT(unit), &old_config));
   3491 
   3492     /* Create mutex */
   3493     gh2_tsn_bkinfo[unit]->gh2_prp_forwarding_bk_info.mutex =
   3494         sal_mutex_create("prp_forwarding_mutex");
   3495     if (gh2_tsn_bkinfo[unit]->gh2_prp_forwarding_bk_info.mutex == NULL) {
   3496         PRP_FORWARDING_ERROR_RETURN(BCM_E_MEMORY);
   3497     }
   3498 
   3499     /*
   3500      *  SETUP HW-RELATED SETTING
   3501      *  (ex. port table / ifp / customer header / l2 / vlan )
   3502      *    1. skip these if it is in warmboot
   3503      *    2. prp_redirect_group of bookkeeping
   3504      *       would be recovered in reload()
   3505      */
   3506 #if defined(BCM_WARM_BOOT_SUPPORT)
   3507     if (SOC_WARM_BOOT(unit)) {
   3508         return BCM_E_NONE;
   3509     }
   3510 #endif /* BCM_WARM_BOOT_SUPPORT */
   3511 
   3512     /* setup loopback port as PRP-modified */
   3513     new_config = old_config;
   3514     new_config.port_type = bcmTsnSrPortTypeCount; /* for PRP-modified usage */
   3515     new_config.interlink_role = 0;
   3516     new_config.net_id = 5; /* For PathID to be b'1010 (A) or b'1011 (B) */
   3517     PRP_FORWARDING_ERROR_RETURN(
   3518         bcmi_gh2_tsn_sr_port_config_apply(
   3519             unit, PRP_FORWARDING_REDIRECT_PORT(unit),
   3520             &old_config, &new_config));
   3521     PRP_FORWARDING_ERROR_RETURN(
   3522         bcm_esw_port_encap_set(
   3523             unit, PRP_FORWARDING_REDIRECT_PORT(unit), BCM_PORT_ENCAP_IEEE));
   3524     PRP_FORWARDING_ERROR_RETURN(
   3525         bcm_esw_port_autoneg_set(
   3526             unit, PRP_FORWARDING_REDIRECT_PORT(unit), 0));
   3527     PRP_FORWARDING_ERROR_RETURN(
   3528         bcm_esw_port_loopback_set(
   3529             unit, PRP_FORWARDING_REDIRECT_PORT(unit), BCM_PORT_LOOPBACK_MAC));
   3530 
   3531     /* create a IFP group on prp-port for redirect to loopback-port
   3532      *  Note. we need to set this group as lowest-priority
   3533      *        (use BCM_FIELD_GROUP_PRIO_ANY,
   3534      *         it would use lowest-priority in default)
   3535      *        Becuase the user maybe want to setup another IFP rule on prp port
   3536      *        (ex. setup action DROP or PKT_NET_ID_SOURCE)
   3537      */
   3538     PRP_FORWARDING_REDIRECT_GROUP(unit) = PRP_FORWARDING_REDIRECT_GROUP_INVALID;
   3539     bcm_field_qset_t_init(&qset);
   3540     BCM_FIELD_QSET_ADD(qset, bcmFieldQualifyInPort);
   3541     PRP_FORWARDING_ERROR_RETURN(
   3542         bcm_esw_field_group_create(
   3543             unit, qset, BCM_FIELD_GROUP_PRIO_ANY,
   3544             &PRP_FORWARDING_REDIRECT_GROUP(unit)));
   3545     assert(PRP_FORWARDING_REDIRECT_GROUP(unit) !=
   3546            PRP_FORWARDING_REDIRECT_GROUP_INVALID);
   3547 
   3548     /* For this loopback-port
   3549      *   1. disable ingress/egress vlan check
   3550      *   2. disable L2 learning
   3551      *   3. disable L2 moving
   3552      *   4. clear egress mask first
   3553      *   5. remove this port from all VLANs
   3554      *   6. change net_id source to be from ingress port.
   3555      */
   3556     /* .1 */
   3557     PRP_FORWARDING_ERROR_RETURN(
   3558         bcm_esw_port_vlan_member_get(
   3559             unit, PRP_FORWARDING_REDIRECT_PORT(unit), &vlan_flags));
   3560     vlan_flags &= ~(BCM_PORT_VLAN_MEMBER_INGRESS);
   3561     vlan_flags &= ~(BCM_PORT_VLAN_MEMBER_EGRESS);
   3562     PRP_FORWARDING_ERROR_RETURN(
   3563         bcm_esw_port_vlan_member_set(
   3564             unit, PRP_FORWARDING_REDIRECT_PORT(unit), vlan_flags));
   3565     /* .2 */
   3566     PRP_FORWARDING_ERROR_RETURN(
   3567         bcm_esw_port_control_set(
   3568             unit, PRP_FORWARDING_REDIRECT_PORT(unit),
   3569             bcmPortControlL2Learn, BCM_PORT_LEARN_FWD));
   3570     /* .3 */
   3571     PRP_FORWARDING_ERROR_RETURN(
   3572         bcm_esw_port_control_set(
   3573             unit, PRP_FORWARDING_REDIRECT_PORT(unit),
   3574             bcmPortControlL2Move, BCM_PORT_LEARN_FWD));
   3575     /* .4 */
   3576     BCM_PBMP_CLEAR(pbmp);
   3577     PRP_FORWARDING_ERROR_RETURN(
   3578         bcm_esw_port_egress_set(
   3579             unit, PRP_FORWARDING_REDIRECT_PORT(unit),
   3580             SOC_BASE_MODID(unit), pbmp));
   3581     /* .5 */
   3582     BCM_PBMP_CLEAR(pbmp);
   3583     BCM_PBMP_PORT_ADD(pbmp, PRP_FORWARDING_REDIRECT_PORT(unit));
   3584     PRP_FORWARDING_ERROR_RETURN(
   3585         bcm_esw_vlan_list_by_pbmp(
   3586             unit, pbmp, &vlan_list, &vlan_cnt));
   3587     if (vlan_cnt != 0) {
   3588         int i;
   3589 
   3590         if (NULL == vlan_list) {
   3591             PRP_FORWARDING_ERROR_RETURN(BCM_E_INTERNAL);
   3592         }
   3593         for (i = 0; i < vlan_cnt; i++) {
   3594             PRP_FORWARDING_ERROR_RETURN_WITH_CLEAN(
   3595                 bcm_esw_vlan_port_remove(
   3596                     unit, vlan_list[i].vlan_tag, pbmp),
   3597                 bcm_esw_vlan_list_destroy(unit, vlan_list, vlan_cnt));
   3598         }
   3599     }
   3600     if (NULL != vlan_list) {
   3601         bcm_esw_vlan_list_destroy(unit, vlan_list, vlan_cnt);
   3602         vlan_list = NULL;
   3603     }
   3604     /* .6 */
   3605     PRP_FORWARDING_ERROR_RETURN(
   3606         bcm_esw_field_entry_create(
   3607             unit, PRP_FORWARDING_REDIRECT_GROUP(unit), &fp_entry));
   3608     PRP_FORWARDING_ERROR_RETURN(
   3609         bcm_esw_field_qualify_InPort(
   3610             unit, fp_entry, PRP_FORWARDING_REDIRECT_PORT(unit),
   3611             BCM_FIELD_EXACT_MATCH_MASK));
   3612     PRP_FORWARDING_ERROR_RETURN(
   3613         bcm_esw_field_action_add(
   3614             unit, fp_entry, bcmFieldActionSRNetIdSource,
   3615              BCM_FIELD_SR_NET_ID_SOURCE_SRC_PORT, 0));
   3616     PRP_FORWARDING_ERROR_RETURN(
   3617         bcm_esw_field_entry_install(unit, fp_entry));
   3618 
   3619     /* re-setup IFP/CustomerHeader
   3620      * for each PRP-port (according to hw port table)
   3621      */
   3622     {
   3623         bcm_port_t port;
   3624         bcm_tsn_sr_port_config_t  config;
   3625 
   3626         PBMP_ITER(PBMP_PORT_ALL(unit), port) {
   3627             bcm_gport_t gport;
   3628 
   3629             PRP_FORWARDING_ERROR_RETURN(
   3630                 bcm_esw_port_gport_get(unit, port, &gport));
   3631 
   3632             PRP_FORWARDING_ERROR_RETURN(
   3633                 bcmi_gh2_tsn_sr_port_config_get(unit, gport, &config));
   3634 
   3635             if (1 == PRP_FORWARDING_NEED_PRP_SETTING(config)) {
   3636                 PRP_FORWARDING_ERROR_RETURN(
   3637                     bcmi_gh2_tsn_sr_port_prp_forwarding_create(unit, port));
   3638             }
   3639         }
   3640     }
   3641 
   3642     return BCM_E_NONE;
   3643 }
   3644 
   3645 #ifdef BCM_WARM_BOOT_SUPPORT
   3646 /* sync prp-forwarding info to scache */
   3647 STATIC int
   3648 bcmi_gh2_tsn_sr_port_prp_forwarding_sync(
   3649     int unit,
   3650     soc_scache_handle_t scache_handle)
   3651 {
   3652     uint8 *scache_ptr = NULL;
   3653     int rv = BCM_E_NONE;
   3654 
   3655     if (0 == PRP_FORWARDING_ENABLE(unit)) {
   3656         return BCM_E_NONE;
   3657     }
   3658 
   3659     rv = _bcm_esw_scache_ptr_get(
   3660              unit, scache_handle, TRUE, sizeof(bcm_field_group_t),
   3661              &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL);
   3662 
   3663     if (BCM_SUCCESS(rv)) {
   3664         if (scache_ptr == NULL) {
   3665             rv = BCM_E_INTERNAL;
   3666         }
   3667     }
   3668 
   3669     PRP_FORWARDING_BKINFO_LOCK(unit);
   3670     if (BCM_SUCCESS(rv)) {
   3671         if (PRP_FORWARDING_REDIRECT_GROUP_INVALID ==
   3672             PRP_FORWARDING_REDIRECT_GROUP(unit)) {
   3673            rv = BCM_E_INTERNAL;
   3674         }
   3675     }
   3676 
   3677     if (BCM_SUCCESS(rv)) {
   3678         sal_memcpy(scache_ptr, &(PRP_FORWARDING_REDIRECT_GROUP(unit)),
   3679                    sizeof(bcm_field_group_t));
   3680     }
   3681     PRP_FORWARDING_BKINFO_UNLOCK(unit);
   3682 
   3683     return rv;
   3684 }
   3685 
   3686 /* recover prp-forwarding info from scache */
   3687 STATIC int
   3688 bcmi_gh2_tsn_sr_port_prp_forwarding_reload(
   3689     int unit,
   3690     soc_scache_handle_t scache_handle)
   3691 {
   3692     uint8 *scache_ptr = NULL;
   3693     int rv = BCM_E_NONE;
   3694 
   3695     rv = _bcm_esw_scache_ptr_get(
   3696              unit, scache_handle, FALSE, sizeof(bcm_field_group_t),
   3697              &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL);
   3698 
   3699     if (BCM_E_NOT_FOUND == rv) {
   3700         /* Maybe proceed with Level 1 Warm Boot */
   3701         return BCM_E_NONE;
   3702     } else if (BCM_E_NONE == rv) {
   3703         if (NULL == scache_ptr) {
   3704             rv = BCM_E_INTERNAL;
   3705         } else {
   3706             sal_memcpy(&(PRP_FORWARDING_REDIRECT_GROUP(unit)), scache_ptr,
   3707                        sizeof(bcm_field_group_t));
   3708         }
   3709     }
   3710 
   3711     return rv;
   3712 }
   3713 #endif /* BCM_WARM_BOOT_SUPPORT */
   3714 
   3715 /* add this port into egress mask of loopback port */
   3716 STATIC int
   3717 bcmi_gh2_tsn_sr_port_prp_forwarding_egress_add(
   3718     int unit,
   3719     bcm_port_t port)
   3720 {
   3721     bcm_pbmp_t pbmp;
   3722 
   3723     BCM_PBMP_CLEAR(pbmp);
   3724     BCM_IF_ERROR_RETURN(
   3725         bcm_esw_port_egress_get(
   3726             unit, PRP_FORWARDING_REDIRECT_PORT(unit),
   3727             SOC_BASE_MODID(unit), &pbmp));
   3728     BCM_PBMP_PORT_ADD(pbmp, port);
   3729     BCM_IF_ERROR_RETURN(
   3730         bcm_esw_port_egress_set(
   3731             unit, PRP_FORWARDING_REDIRECT_PORT(unit),
   3732             SOC_BASE_MODID(unit), pbmp));
   3733 
   3734     return BCM_E_NONE;
   3735 }
   3736 
   3737 /* delete this port from egress mask of loopback port */
   3738 STATIC int
   3739 bcmi_gh2_tsn_sr_port_prp_forwarding_egress_remove(
   3740     int unit,
   3741     bcm_port_t port)
   3742 {
   3743     bcm_pbmp_t pbmp;
   3744 
   3745     BCM_PBMP_CLEAR(pbmp);
   3746     BCM_IF_ERROR_RETURN(
   3747         bcm_esw_port_egress_get(
   3748             unit, PRP_FORWARDING_REDIRECT_PORT(unit),
   3749             SOC_BASE_MODID(unit), &pbmp));
   3750     BCM_PBMP_PORT_REMOVE(pbmp, port);
   3751     BCM_IF_ERROR_RETURN(
   3752         bcm_esw_port_egress_set(
   3753             unit, PRP_FORWARDING_REDIRECT_PORT(unit),
   3754             SOC_BASE_MODID(unit), pbmp));
   3755 
   3756     return BCM_E_NONE;
   3757 }
   3758 
   3759 /*
   3760  * Function:
   3761  *     bcmi_gh2_tsn_sr_port_config_set
   3762  * Purpose:
   3763  *     Set SR configuration on a port
   3764  * Parameters:
   3765  *     unit             - (IN) unit number
   3766  *     port             - (IN) port to configure
   3767  *     config           - (IN) port SR configuration
   3768  * Returns:
   3769  *     BCM_E_XXX
   3770  * Notes:
   3771  */
   3772 STATIC int
   3773 bcmi_gh2_tsn_sr_port_config_set(
   3774     int unit,
   3775     bcm_gport_t gport,
   3776     bcm_tsn_sr_port_config_t *config)
   3777 {
   3778     bcm_port_t               port;
   3779     bcm_tsn_sr_port_config_t old_config;
   3780     bcm_pbmp_t               netid_bmp;
   3781     netid_bitmap_entry_t     netid_bmp_entry;
   3782     uint8                    old_netid, new_netid;
   3783     int                      rv;
   3784 
   3785     /* Parameter check */
   3786     if (config == NULL) {
   3787         return BCM_E_PARAM;
   3788     }
   3789 
   3790     /* This API implementation doesn't accept bcmTsnSrPortTypeCount */
   3791     if (config->port_type < bcmTsnSrPortTypeNone ||
   3792         config->port_type >= bcmTsnSrPortTypeCount) {
   3793         return BCM_E_PARAM;
   3794     }
   3795     if (config->port_mode < bcmTsnSrPortModeDefault ||
   3796         config->port_mode >= bcmTsnSrPortModeCount) {
   3797         return BCM_E_PARAM;
   3798     }
   3799     if (config->lan_id > 1) {
   3800         return BCM_E_PARAM;
   3801     }
   3802     if (config->net_id > 7) {
   3803         return BCM_E_PARAM;
   3804     }
   3805 
   3806     /* Validate and convert gport to local port */
   3807     BCM_IF_ERROR_RETURN(
   3808         _bcm_esw_port_gport_validate(unit, gport, &port));
   3809 
   3810     /* get old previous config */
   3811     BCM_IF_ERROR_RETURN(
   3812         bcmi_gh2_tsn_sr_port_config_get(unit, gport, &old_config));
   3813 
   3814     /* handle prp forwarding */
   3815     if (0 == PRP_FORWARDING_NEED_PRP_SETTING(old_config) &&
   3816         1 == PRP_FORWARDING_NEED_PRP_SETTING(*config)) {
   3817         if (0 == PRP_FORWARDING_ENABLE(unit)) {
   3818             return BCM_E_UNAVAIL;
   3819         }
   3820         PRP_FORWARDING_BKINFO_LOCK(unit);
   3821         rv = bcmi_gh2_tsn_sr_port_prp_forwarding_create(unit, port);
   3822         PRP_FORWARDING_BKINFO_UNLOCK(unit);
   3823         BCM_IF_ERROR_RETURN(rv);
   3824     } else if (1 == PRP_FORWARDING_NEED_PRP_SETTING(old_config) &&
   3825                0 == PRP_FORWARDING_NEED_PRP_SETTING(*config)) {
   3826         if (0 == PRP_FORWARDING_ENABLE(unit)) {
   3827             return BCM_E_UNAVAIL;
   3828         }
   3829         PRP_FORWARDING_BKINFO_LOCK(unit);
   3830         bcmi_gh2_tsn_sr_port_prp_forwarding_destroy(unit, port);
   3831         PRP_FORWARDING_BKINFO_UNLOCK(unit);
   3832     }
   3833 
   3834     /* need handle egress mask on loopback port if PRP enable */
   3835     if (1 == PRP_FORWARDING_ENABLE(unit)) {
   3836         if (0 == PRP_FORWARDING_NEED_EGRESS_MASK_SETTING(old_config) &&
   3837             1 == PRP_FORWARDING_NEED_EGRESS_MASK_SETTING(*config)) {
   3838             BCM_IF_ERROR_RETURN(
   3839                 bcmi_gh2_tsn_sr_port_prp_forwarding_egress_add(unit, port));
   3840         } else if (1 == PRP_FORWARDING_NEED_EGRESS_MASK_SETTING(old_config) &&
   3841                    0 == PRP_FORWARDING_NEED_EGRESS_MASK_SETTING(*config)) {
   3842             BCM_IF_ERROR_RETURN(
   3843                 bcmi_gh2_tsn_sr_port_prp_forwarding_egress_remove(unit, port));
   3844         }
   3845     }
   3846 
   3847     /* Configure NET_ID bitmap for NET_ID filtering on mutlicast packets */
   3848     old_netid = 0;
   3849     new_netid = 0;
   3850     if (old_config.port_type == bcmTsnSrPortTypePrp ||
   3851         old_config.port_mode == bcmTsnSrPortModeInterworkingPrp) {
   3852         old_netid = old_config.net_id;
   3853     }
   3854     if (config->port_type == bcmTsnSrPortTypePrp ||
   3855         config->port_mode == bcmTsnSrPortModeInterworkingPrp) {
   3856         new_netid = config->net_id;
   3857     }
   3858     if (old_netid != new_netid) {
   3859         sal_memset(&netid_bmp_entry, 0, sizeof(netid_bmp_entry));
   3860         if (old_netid) {
   3861             /* Remove this port from old NET_ID bitmap if applicable */
   3862             BCM_IF_ERROR_RETURN(
   3863                 soc_mem_read(unit, NETID_BITMAPm, MEM_BLOCK_ANY,
   3864                              old_netid, &netid_bmp_entry));
   3865             soc_mem_pbmp_field_get(
   3866                 unit, NETID_BITMAPm, &netid_bmp_entry, BITMAPf, &netid_bmp);
   3867             BCM_PBMP_PORT_REMOVE(netid_bmp, port);
   3868             soc_mem_pbmp_field_set(
   3869                 unit, NETID_BITMAPm, &netid_bmp_entry, BITMAPf, &netid_bmp);
   3870             BCM_IF_ERROR_RETURN(
   3871                 soc_mem_write(unit, NETID_BITMAPm, MEM_BLOCK_ALL,
   3872                              old_netid, &netid_bmp_entry));
   3873         }
   3874         if (new_netid) {
   3875             /* Add this port to new NET_ID bitmap if applicable */
   3876             BCM_IF_ERROR_RETURN(
   3877                 soc_mem_read(unit, NETID_BITMAPm, MEM_BLOCK_ANY,
   3878                              new_netid, &netid_bmp_entry));
   3879             soc_mem_pbmp_field_get(
   3880                 unit, NETID_BITMAPm, &netid_bmp_entry, BITMAPf, &netid_bmp);
   3881             BCM_PBMP_PORT_ADD(netid_bmp, port);
   3882             soc_mem_pbmp_field_set(
   3883                 unit, NETID_BITMAPm, &netid_bmp_entry, BITMAPf, &netid_bmp);
   3884             BCM_IF_ERROR_RETURN(
   3885                 soc_mem_write(unit, NETID_BITMAPm, MEM_BLOCK_ALL,
   3886                              new_netid, &netid_bmp_entry));
   3887         }
   3888     }
   3889 
   3890     /* Call the shared configuration apply to configure */
   3891     BCM_IF_ERROR_RETURN(
   3892         bcmi_gh2_tsn_sr_port_config_apply(unit, port, &old_config, config));
   3893     return BCM_E_NONE;
   3894 }
   3895 #endif /* BCM_TSN_SR_SUPPORT */
   3896 
   3897 /* TSN flow mgmt - get number of flows */
   3898 STATIC int
   3899 bcmi_gh2_tsn_flows_get_num_flows(int unit, int *max_flows)
   3900 {
   3901     /* parameter check */
   3902     if (!SOC_UNIT_VALID(unit) || NULL == max_flows) {
   3903         return BCM_E_PARAM;
   3904     }
   3905 
   3906     *max_flows = TSN_FLOWS_MAX_NUM_OF_FLOWS;
   3907 
   3908     return BCM_E_NONE;
   3909 }
   3910 
   3911 /* TSN flow mgmt - convert flow index to HW flow ID */
   3912 STATIC int
   3913 bcmi_gh2_tsn_flows_get_hw_flow_id(int unit, int fidx, uint32 *hw_id)
   3914 {
   3915     /* parameter check */
   3916     if (!SOC_UNIT_VALID(unit) || NULL == hw_id || fidx < 0 ||
   3917         fidx >= TSN_FLOWS_MAX_NUM_OF_FLOWS) {
   3918         return BCM_E_PARAM;
   3919     }
   3920 
   3921     /* Convert it */
   3922     *hw_id = (uint32)TSN_FLOWS_IDX_TO_HW_ID(fidx);
   3923     return BCM_E_NONE;
   3924 }
   3925 
   3926 /* TSN flow mgmt - convert flow index to HW flow ID */
   3927 STATIC int
   3928 bcmi_gh2_tsn_flows_get_sw_flow_idx(int unit, uint32 hw_id, int *fidx)
   3929 {
   3930     int idx;
   3931 
   3932     /* parameter check */
   3933     if (!SOC_UNIT_VALID(unit) || NULL == fidx) {
   3934         return BCM_E_PARAM;
   3935     }
   3936 
   3937     /* Convert it */
   3938     idx = TSN_FLOWS_HW_ID_TO_IDX((int)hw_id);
   3939 
   3940     /* Check if it's valid */
   3941     if (idx < 0 || idx >= TSN_FLOWS_MAX_NUM_OF_FLOWS) {
   3942         return BCM_E_PARAM;
   3943     }
   3944 
   3945     *fidx = idx;
   3946     return BCM_E_NONE;
   3947 }
   3948 
   3949 /* TSN flow mgmt - check flow config */
   3950 STATIC int
   3951 bcmi_gh2_tsn_flows_check_flow_config(int unit, bcm_tsn_flow_config_t *cfg)
   3952 {
   3953     int index;
   3954     bcm_tsn_mtu_profile_type_t type;
   3955 
   3956     /* parameter check */
   3957     TSN_BKINFO_IS_INIT(unit);
   3958     if (NULL == cfg) {
   3959         return BCM_E_PARAM;
   3960     }
   3961 
   3962     /* Check MTU profile id */
   3963     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   3964         /* Using MTU decode function to do profile id validation */
   3965         BCM_IF_ERROR_RETURN(bcmi_gh2_tsn_mtu_profile_decode(
   3966                               unit, cfg->ingress_mtu_profile, &type, &index));
   3967         if (type == bcmTsnMtuProfileTypeEgress) {
   3968             return BCM_E_PARAM;
   3969         }
   3970     }
   3971 
   3972     return BCM_E_NONE;
   3973 }
   3974 
   3975 /* TSN flow mgmt - write flow config */
   3976 STATIC int
   3977 bcmi_gh2_tsn_flows_write_flow(
   3978     int unit,
   3979     int idx,
   3980     bcm_tsn_flow_config_t *config)
   3981 {
   3982     soc_mem_t mem;
   3983     uint32 v = 0;
   3984     cut_through_attribute_entry_t ct_entry;
   3985     ing_mtu_check_1_entry_t mtu_ent;
   3986     uint32 hw_id;
   3987     int mtu_hw_index;
   3988     bcm_tsn_mtu_profile_type_t type;
   3989     int rv;
   3990 
   3991     /* parameter check */
   3992     TSN_BKINFO_IS_INIT(unit);
   3993     if (NULL == config || idx < 0 || idx >= TSN_FLOWS_MAX_NUM_OF_FLOWS) {
   3994         return BCM_E_PARAM;
   3995     }
   3996 
   3997     /*
   3998      * Per flow disable cut-through
   3999      * Write to HW with HW index idx+1 since entry 0 is not visible to SW
   4000      */
   4001     if (soc_feature(unit, soc_feature_tsn_flow_no_asf_select)) {
   4002         mem = CUT_THROUGH_ATTRIBUTEm;
   4003         sal_memset(&ct_entry, 0, sizeof(ct_entry));
   4004         v = (config->flags & BCM_TSN_FLOW_CONFIG_DO_NOT_CUT_THROUGH) ? 1 : 0;
   4005         soc_mem_field32_set(unit, mem, &ct_entry, DO_NOT_CUT_THROUGHf, v);
   4006         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL,
   4007                            TSN_FLOWS_IDX_TO_HW_ID(idx),
   4008                            &ct_entry);
   4009         if (SOC_FAILURE(rv)) {
   4010             LOG_ERROR(BSL_LS_BCM_TSN,
   4011                       (BSL_META_U(unit, "Failed to write mem[%s]"),
   4012                                   SOC_MEM_NAME(unit, mem)));
   4013             return rv;
   4014         }
   4015     } else {
   4016         if (config->flags & BCM_TSN_FLOW_CONFIG_DO_NOT_CUT_THROUGH) {
   4017             LOG_VERBOSE(BSL_LS_BCM_TSN,
   4018                         (BSL_META_U(unit,
   4019                                     "TSN flow disable cut-through "
   4020                                     "is not configurable\n")));
   4021             return BCM_E_PARAM;
   4022         }
   4023     }
   4024     /* MTU profile id HW writing */
   4025     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   4026         hw_id = (uint32)TSN_FLOWS_IDX_TO_HW_ID(idx);
   4027         mem = ING_MTU_CHECK_1m;
   4028         MEM_LOCK(unit, mem);
   4029         sal_memset(&mtu_ent, 0, sizeof(mtu_ent));
   4030         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_id, &mtu_ent);
   4031         if (SOC_FAILURE(rv)) {
   4032             LOG_ERROR(BSL_LS_BCM_TSN,
   4033                       (BSL_META_U(unit, "Failed to read mem[%s]"),
   4034                                   SOC_MEM_NAME(unit, mem)));
   4035             MEM_UNLOCK(unit, mem);
   4036             return rv;
   4037         }
   4038         type = bcmTsnMtuProfileTypeIngress;
   4039         BCM_IF_ERROR_RETURN(bcmi_gh2_tsn_mtu_profile_decode(
   4040                               unit, config->ingress_mtu_profile,
   4041                               &type, &mtu_hw_index));
   4042         soc_mem_field32_set(unit, mem, &mtu_ent, MTU_PROFILE_INDEXf,
   4043                             mtu_hw_index);
   4044 
   4045         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_id, &mtu_ent);
   4046         if (SOC_FAILURE(rv)) {
   4047             LOG_ERROR(BSL_LS_BCM_TSN,
   4048                       (BSL_META_U(unit, "Failed to write mem[%s]"),
   4049                                   SOC_MEM_NAME(unit, mem)));
   4050             MEM_UNLOCK(unit, mem);
   4051             return rv;
   4052         }
   4053         MEM_UNLOCK(unit, mem);
   4054     }
   4055 
   4056     return BCM_E_NONE;
   4057 }
   4058 
   4059 #ifdef BCM_WARM_BOOT_SUPPORT
   4060 /* TSN flow mgmt - read flow config (for warm boot) */
   4061 STATIC int
   4062 bcmi_gh2_tsn_flows_read_flow(
   4063     int unit,
   4064     int idx,
   4065     bcm_tsn_flow_config_t *config)
   4066 {
   4067     soc_mem_t mem;
   4068     cut_through_attribute_entry_t ct_entry;
   4069     int rv = BCM_E_NONE;
   4070     ing_mtu_check_1_entry_t mtu_ent;
   4071     uint32 hw_id;
   4072     int mtu_idx, mtu_id;
   4073 
   4074     /* parameter check */
   4075     TSN_BKINFO_IS_INIT(unit);
   4076     if (!soc_feature(unit, soc_feature_tsn)) {
   4077         return (BCM_E_UNAVAIL);
   4078     }
   4079     if (NULL == config || idx < 0 || idx >= TSN_FLOWS_MAX_NUM_OF_FLOWS) {
   4080         return BCM_E_PARAM;
   4081     }
   4082 
   4083     /* This routine is for warm boot only */
   4084     if (!SOC_WARM_BOOT(unit)) {
   4085         return BCM_E_UNAVAIL;
   4086     }
   4087 
   4088     /* Get config from hardware */
   4089     mem = CUT_THROUGH_ATTRIBUTEm;
   4090     sal_memset(&ct_entry, 0, sizeof(ct_entry));
   4091     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY,
   4092                       TSN_FLOWS_IDX_TO_HW_ID(idx), &ct_entry);
   4093     if (SOC_FAILURE(rv)) {
   4094         LOG_ERROR(BSL_LS_BCM_TSN,
   4095                   (BSL_META_U(unit, "Failed to read mem[%s]"),
   4096                               SOC_MEM_NAME(unit, mem)));
   4097         return rv;
   4098     }
   4099     if (soc_mem_field32_get(unit, mem, &ct_entry, DO_NOT_CUT_THROUGHf)) {
   4100         config->flags |= BCM_TSN_FLOW_CONFIG_DO_NOT_CUT_THROUGH;
   4101     }
   4102 
   4103     /* MTU TSN flow warm boot read */
   4104     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   4105         mem = ING_MTU_CHECK_1m;
   4106         hw_id = (uint32)TSN_FLOWS_IDX_TO_HW_ID(idx);
   4107         sal_memset(&mtu_ent, 0, sizeof(mtu_ent));
   4108         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_id, &mtu_ent);
   4109         if (SOC_FAILURE(rv)) {
   4110             LOG_ERROR(BSL_LS_BCM_TSN,
   4111                     (BSL_META_U(unit, "Failed to read mem[%s]"),
   4112                                 SOC_MEM_NAME(unit, mem)));
   4113             return rv;
   4114         }
   4115         mtu_idx = soc_mem_field32_get(unit, mem, &mtu_ent, MTU_PROFILE_INDEXf);
   4116         rv = bcmi_gh2_tsn_mtu_profile_encode(unit, mtu_idx,
   4117                                              bcmTsnMtuProfileTypeIngress,
   4118                                              &mtu_id);
   4119         if (SOC_FAILURE(rv)) {
   4120             LOG_ERROR(BSL_LS_BCM_TSN,
   4121                       (BSL_META_U(unit, "Failed to encode mtu profile"
   4122                                   " from idx = %d"), mtu_idx));
   4123             return rv;
   4124         }
   4125         config->ingress_mtu_profile = mtu_id;
   4126     }
   4127     return BCM_E_NONE;
   4128 }
   4129 #endif /* BCM_WARM_BOOT_SUPPORT */
   4130 
   4131 /* TSN flow mgmt - clear flow config */
   4132 STATIC int
   4133 bcmi_gh2_tsn_flows_clear_flow_mtu(int unit, int idx)
   4134 {
   4135     soc_mem_t mem;
   4136     ing_mtu_check_1_entry_t mtu_ent;
   4137     int rv;
   4138     uint32 hw_id;
   4139 
   4140     TSN_BKINFO_IS_INIT(unit);
   4141     if (!soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   4142         return BCM_E_UNAVAIL;
   4143     }
   4144 
   4145     hw_id = (uint32)TSN_FLOWS_IDX_TO_HW_ID(idx);
   4146     mem = ING_MTU_CHECK_1m;
   4147     MEM_LOCK(unit, mem);
   4148     sal_memset(&mtu_ent, 0, sizeof(mtu_ent));
   4149     rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_id, &mtu_ent);
   4150     if (SOC_FAILURE(rv)) {
   4151         LOG_ERROR(BSL_LS_BCM_TSN,
   4152                   (BSL_META_U(unit, "Failed to read mem[%s]"),
   4153                               SOC_MEM_NAME(unit, mem)));
   4154         MEM_UNLOCK(unit, mem);
   4155         return rv;
   4156     }
   4157     soc_mem_field32_set(unit, mem, &mtu_ent, MTU_PROFILE_INDEXf, 0);
   4158 
   4159     rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_id, &mtu_ent);
   4160     if (SOC_FAILURE(rv)) {
   4161         LOG_ERROR(BSL_LS_BCM_TSN,
   4162                   (BSL_META_U(unit, "Failed to write mem[%s]"),
   4163                               SOC_MEM_NAME(unit, mem)));
   4164         MEM_UNLOCK(unit, mem);
   4165         return rv;
   4166     }
   4167     MEM_UNLOCK(unit, mem);
   4168 
   4169     return BCM_E_NONE;
   4170 }
   4171 
   4172 
   4173 /* TSN flow mgmt - clear flow config */
   4174 STATIC int
   4175 bcmi_gh2_tsn_flows_clear_flow(int unit, int idx)
   4176 {
   4177     /* parameter check */
   4178     if (!SOC_UNIT_VALID(unit) ||
   4179         idx < 0 || idx >= TSN_FLOWS_MAX_NUM_OF_FLOWS) {
   4180         return BCM_E_PARAM;
   4181     }
   4182 
   4183     /* Clear MTU profile id HW */
   4184     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   4185         return bcmi_gh2_tsn_flows_clear_flow_mtu(unit, idx);
   4186     }
   4187 
   4188     return BCM_E_NONE;
   4189 }
   4190 
   4191 /*
   4192  * TSN/SR table size is 8 * 16, sw_idx = 0 ~ 7
   4193  * each sw_idx represent a group of 16 new priority entries
   4194  */
   4195 #define GH2_PRI_MAP_TSN_SHIFT        (4)
   4196 #define GH2_PRI_MAP_TSN_MASK         (0xF)
   4197 #define GH2_PRI_MAP_TSN_TAB_SIZE     (8)
   4198 #define GH2_PRI_MAP_TSN_ENT_SIZE     (16)
   4199 #if defined(BCM_TSN_SR_SUPPORT)
   4200 #define GH2_PRI_MAP_SR_SHIFT         (4)
   4201 #define GH2_PRI_MAP_SR_MASK          (0xF)
   4202 #define GH2_PRI_MAP_SR_TAB_SIZE      (8)
   4203 #define GH2_PRI_MAP_SR_ENT_SIZE      (16)
   4204 #endif /* BCM_TSN_SR_SUPPORT */
   4205 
   4206 /*
   4207  * Egress STU/MTU table is 128x8, and the 128 is the max port count.
   4208  * However, it could be smaller in fact. The max actual number of ports is
   4209  * more reasonable.
   4210  * refer to GH2 EGR_MTU_CHECK/EGR_STU_CHECK (66 ports)
   4211  */
   4212 #define GH2_PRI_MAP_MTU_SHIFT        (3)
   4213 #define GH2_PRI_MAP_MTU_MASK         (0x7)
   4214 #define GH2_PRI_MAP_MTU_TAB_SIZE     (66)
   4215 #define GH2_PRI_MAP_MTU_ENT_SIZE     (8)
   4216 #define GH2_PRI_MAP_STU_SHIFT        (3)
   4217 #define GH2_PRI_MAP_STU_MASK         (0x7)
   4218 #define GH2_PRI_MAP_STU_TAB_SIZE     (66)
   4219 #define GH2_PRI_MAP_STU_ENT_SIZE     (8)
   4220 
   4221 /* OFFSET is only 3 bits and INT_PRI is only 4 bits */
   4222 #define GH2_PRI_MAP_TSN_MAX_FLOW_VALUE        (8)
   4223 #define GH2_PRI_MAP_SR_MAX_FLOW_VALUE         (8)
   4224 #define GH2_PRI_MAP_TSN_MAX_NEW_PRI_VALUE     (16)
   4225 #define GH2_PRI_MAP_SR_MAX_NEW_PRI_VALUE      (16)
   4226 /*
   4227  * The default setting is placed in the 1st profile (sw_idx = 0)
   4228  * of TSN/SR flow initially
   4229  * Note:
   4230  * 2rd to Nth profiles with values default_offset and default_new_pri
   4231  * are recognized as empty setting.
   4232  */
   4233 STATIC const uint32 default_offset[GH2_PRI_MAP_TSN_ENT_SIZE] =
   4234     {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
   4235 STATIC const uint32 default_new_pri[GH2_PRI_MAP_TSN_ENT_SIZE] =
   4236     {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
   4237 
   4238 /*
   4239  * Function:
   4240  *      bcmi_gh2_tsn_pri_map_tsn_set
   4241  * Purpose:
   4242  *      Set the Priority Map configuration to hardware
   4243  * Parameters:
   4244  *      unit   - (IN) Unit number
   4245  *      sw_idx - (IN) SW memory index
   4246  *      config - (OUT) Priority Map configuration
   4247  * Returns:
   4248  *      BCM_E_xxx
   4249  */
   4250 STATIC int
   4251 bcmi_gh2_tsn_pri_map_tsn_set(
   4252     int unit,
   4253     uint32 sw_idx,
   4254     bcm_tsn_pri_map_config_t *config)
   4255 {
   4256     uint32 hw_idx;
   4257     uint32 entry_idx;
   4258     soc_mem_t mem = TSN_PRI_OFFSETm;
   4259     tsn_pri_offset_entry_t data;
   4260     uint32 field_data;
   4261     int is_default_offset = TRUE, is_default_new_pri = TRUE;
   4262     bcm_tsn_pri_map_entry_t *map_entry;
   4263 
   4264     if (!soc_feature(unit, soc_feature_tsn)) {
   4265         return BCM_E_UNAVAIL;
   4266     }
   4267 
   4268     if (!(sw_idx < GH2_PRI_MAP_TSN_TAB_SIZE)) {
   4269         LOG_ERROR(BSL_LS_BCM_TSN,
   4270                   (BSL_META_U(unit,
   4271                               "Invalid sw_idx(%d).\n"),
   4272                               sw_idx));
   4273         assert(sw_idx < GH2_PRI_MAP_TSN_TAB_SIZE);
   4274         return BCM_E_PARAM;
   4275     }
   4276 
   4277     /* Parameter validation */
   4278     if (NULL == config) {
   4279         return BCM_E_PARAM;
   4280     }
   4281 
   4282     /* Set the flow_offset and new_int_pri to TSN_PRI_OFFSETm */
   4283     entry_idx = 0;
   4284     for (hw_idx = (sw_idx << GH2_PRI_MAP_TSN_SHIFT);
   4285          hw_idx < (sw_idx << GH2_PRI_MAP_TSN_SHIFT) + GH2_PRI_MAP_TSN_ENT_SIZE;
   4286          hw_idx++) {
   4287 
   4288         map_entry = &(config->map_entries[entry_idx]);
   4289         is_default_offset =
   4290             (BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET & (map_entry->flags)) ?
   4291             FALSE : TRUE;
   4292         is_default_new_pri =
   4293             (BCM_TSN_PRI_MAP_ENTRY_NEW_INT_PRI & (map_entry->flags)) ?
   4294             FALSE : TRUE;
   4295 
   4296         BCM_IF_ERROR_RETURN(
   4297             soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, &data));
   4298 
   4299         if (SOC_MEM_FIELD_VALID(unit, mem, OFFSETf)) {
   4300             if (TRUE == is_default_offset) {
   4301                 field_data = default_offset[entry_idx];
   4302             }
   4303             else {
   4304                 field_data = map_entry->flow_offset;
   4305             }
   4306 
   4307             /* Check if the value fit the target field range */
   4308             BCM_IF_ERROR_RETURN
   4309                 (soc_mem_field32_fit(
   4310                     unit, mem, OFFSETf,
   4311                     field_data));
   4312             soc_TSN_PRI_OFFSETm_field_set(unit, &data, OFFSETf, &field_data);
   4313         }
   4314         else {
   4315             return BCM_E_INTERNAL;
   4316         }
   4317 
   4318         if (SOC_MEM_FIELD_VALID(unit, mem, INT_PRIf)) {
   4319             if (TRUE == is_default_new_pri) {
   4320                 field_data = default_new_pri[entry_idx];
   4321             }
   4322             else {
   4323                 field_data = map_entry->new_int_pri;
   4324             }
   4325 
   4326             /* Check if the value fit the target field range */
   4327             BCM_IF_ERROR_RETURN
   4328                 (soc_mem_field32_fit(
   4329                     unit, mem, INT_PRIf,
   4330                     field_data));
   4331             soc_TSN_PRI_OFFSETm_field_set(unit, &data, INT_PRIf, &field_data);
   4332         }
   4333         else {
   4334             return BCM_E_INTERNAL;
   4335         }
   4336         BCM_IF_ERROR_RETURN(
   4337             soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_idx, &data));
   4338         entry_idx++;
   4339     }
   4340 
   4341     return BCM_E_NONE;
   4342 }
   4343 
   4344 /*
   4345  * Function:
   4346  *      bcmi_gh2_tsn_pri_map_tsn_get
   4347  * Purpose:
   4348  *      Get the Priority Map configuration from hardware
   4349  * Parameters:
   4350  *      unit   - (IN) Unit number
   4351  *      sw_idx - (IN) SW memory index
   4352  *      config - (OUT) Priority Map configuration
   4353  * Returns:
   4354  *      BCM_E_xxx
   4355  */
   4356 STATIC int
   4357 bcmi_gh2_tsn_pri_map_tsn_get(
   4358     int unit,
   4359     uint32 sw_idx,
   4360     bcm_tsn_pri_map_config_t *config)
   4361 {
   4362     uint32 hw_idx;
   4363     uint32 entry_idx;
   4364     soc_mem_t mem = TSN_PRI_OFFSETm;
   4365     tsn_pri_offset_entry_t data;
   4366     uint32 field_data;
   4367     int is_default_offset = TRUE, is_default_new_pri = TRUE;
   4368 
   4369     if (!soc_feature(unit, soc_feature_tsn)) {
   4370         return BCM_E_UNAVAIL;
   4371     }
   4372 
   4373     if (!(sw_idx < GH2_PRI_MAP_TSN_TAB_SIZE)) {
   4374         LOG_ERROR(BSL_LS_BCM_TSN,
   4375                   (BSL_META_U(unit,
   4376                               "Invalid sw_idx(%d).\n"),
   4377                               sw_idx));
   4378         assert(sw_idx < GH2_PRI_MAP_TSN_TAB_SIZE);
   4379         return BCM_E_PARAM;
   4380     }
   4381 
   4382     /* Parameter validation */
   4383     if (NULL == config) {
   4384         return BCM_E_PARAM;
   4385     }
   4386 
   4387     /* Get the flow_offset and new_int_pri from TSN_PRI_OFFSETm */
   4388     entry_idx = 0;
   4389     for (hw_idx = (sw_idx << GH2_PRI_MAP_TSN_SHIFT);
   4390          hw_idx < (sw_idx << GH2_PRI_MAP_TSN_SHIFT) + GH2_PRI_MAP_TSN_ENT_SIZE;
   4391          hw_idx++) {
   4392 
   4393         BCM_IF_ERROR_RETURN(
   4394             soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, &data));
   4395 
   4396         if (SOC_MEM_FIELD_VALID(unit, mem, OFFSETf)) {
   4397             soc_TSN_PRI_OFFSETm_field_get(unit, &data, OFFSETf, &field_data);
   4398             config->map_entries[entry_idx].flow_offset = field_data;
   4399 
   4400             /* check if the current setting from HW is default setting */
   4401             if (default_offset[entry_idx] != field_data) {
   4402                 is_default_offset = FALSE;
   4403             }
   4404         }
   4405         else {
   4406             return BCM_E_INTERNAL;
   4407         }
   4408 
   4409         if (SOC_MEM_FIELD_VALID(unit, mem, INT_PRIf)) {
   4410             soc_TSN_PRI_OFFSETm_field_get(unit, &data, INT_PRIf, &field_data);
   4411             config->map_entries[entry_idx].new_int_pri = field_data;
   4412 
   4413             /* check if the current setting from HW is default setting */
   4414             if (default_new_pri[entry_idx] != field_data) {
   4415                 is_default_new_pri = FALSE;
   4416             }
   4417         }
   4418         else {
   4419             return BCM_E_INTERNAL;
   4420         }
   4421         entry_idx++;
   4422     }
   4423 
   4424     /* Set TSN related setting */
   4425     config->map_type = bcmTsnPriMapTypeTsnFlow;
   4426     config->num_map_entries = GH2_PRI_MAP_TSN_ENT_SIZE;
   4427 
   4428     /* Check if the HW setting is default setting, and set valid flags. */
   4429     for (entry_idx = 0;
   4430          entry_idx < GH2_PRI_MAP_TSN_ENT_SIZE;
   4431          entry_idx++) {
   4432         config->map_entries[entry_idx].flags = 0;
   4433 
   4434         if (FALSE == is_default_offset) {
   4435             config->map_entries[entry_idx].flags |=
   4436                 BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET;
   4437         }
   4438         if (FALSE == is_default_new_pri) {
   4439             config->map_entries[entry_idx].flags |=
   4440                 BCM_TSN_PRI_MAP_ENTRY_NEW_INT_PRI;
   4441         }
   4442     }
   4443     return BCM_E_NONE;
   4444 }
   4445 
   4446 /*
   4447  * Function:
   4448  *      bcmi_gh2_tsn_pri_map_tsn_delete
   4449  * Purpose:
   4450  *      Delete the Priority Map configuration on hardware
   4451  * Parameters:
   4452  *      unit   - (IN) Unit number
   4453  *      sw_idx - (IN) SW memory index
   4454  * Returns:
   4455  *      BCM_E_xxx
   4456  */
   4457 STATIC int
   4458 bcmi_gh2_tsn_pri_map_tsn_delete(
   4459     int unit,
   4460     uint32 sw_idx)
   4461 {
   4462     uint32 hw_idx;
   4463     uint32 entry_idx;
   4464     soc_mem_t mem = TSN_PRI_OFFSETm;
   4465     tsn_pri_offset_entry_t data;
   4466     uint32 field_data;
   4467 
   4468     LOG_VERBOSE(BSL_LS_BCM_TSN,
   4469                 (BSL_META_U(unit,
   4470                             "bcmi_gh2_tsn_pri_map_tsn_delete:"
   4471                             "sw_idx %d\n"),
   4472                             sw_idx));
   4473 
   4474     if (!soc_feature(unit, soc_feature_tsn)) {
   4475         return BCM_E_UNAVAIL;
   4476     }
   4477 
   4478     /* 1st profile should exist all the time, cannot delete sw_idx 0 */
   4479     if (!((sw_idx > 0) && (sw_idx < GH2_PRI_MAP_TSN_TAB_SIZE))) {
   4480         LOG_ERROR(BSL_LS_BCM_TSN,
   4481                   (BSL_META_U(unit,
   4482                               "Invalid sw_idx(%d).\n"),
   4483                               sw_idx));
   4484         assert((sw_idx > 0) && (sw_idx < GH2_PRI_MAP_TSN_TAB_SIZE));
   4485         return BCM_E_PARAM;
   4486     }
   4487 
   4488     if (sw_idx == 0) {
   4489         LOG_WARN(BSL_LS_BCM_TSN,
   4490                  (BSL_META_U(unit,
   4491                              "cannot delete default profile(sw_idx = 0).\n")));
   4492         return BCM_E_NONE;
   4493     }
   4494 
   4495     /* Set the flow_offset and new_int_pri to TSN_PRI_OFFSETm */
   4496     entry_idx = 0;
   4497     for (hw_idx = (sw_idx << GH2_PRI_MAP_TSN_SHIFT);
   4498          hw_idx < (sw_idx << GH2_PRI_MAP_TSN_SHIFT) + GH2_PRI_MAP_TSN_ENT_SIZE;
   4499          hw_idx++) {
   4500 
   4501         BCM_IF_ERROR_RETURN(
   4502             soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, &data));
   4503 
   4504         if (SOC_MEM_FIELD_VALID(unit, mem, OFFSETf)) {
   4505             field_data = default_offset[entry_idx];
   4506             soc_TSN_PRI_OFFSETm_field_set(unit, &data, OFFSETf, &field_data);
   4507         }
   4508         else {
   4509             return BCM_E_INTERNAL;
   4510         }
   4511 
   4512         if (SOC_MEM_FIELD_VALID(unit, mem, INT_PRIf)) {
   4513             field_data = default_new_pri[entry_idx];
   4514             soc_TSN_PRI_OFFSETm_field_set(unit, &data, INT_PRIf, &field_data);
   4515         }
   4516         else {
   4517             return BCM_E_INTERNAL;
   4518         }
   4519         BCM_IF_ERROR_RETURN(
   4520             soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_idx, &data));
   4521         entry_idx++;
   4522     }
   4523     return BCM_E_NONE;
   4524 }
   4525 
   4526 /*
   4527  * Function:
   4528  *      bcmi_gh2_tsn_pri_map_tsn_hw_index_get
   4529  * Purpose:
   4530  *      Get HW memory base index
   4531  * Parameters:
   4532  *      unit     - (IN) Unit number
   4533  *      sw_idx   - (IN) SW memory index
   4534  *      hw_index - (OUT) HW memory base index
   4535  * Returns:
   4536  *      BCM_E_xxx
   4537  */
   4538 STATIC int
   4539 bcmi_gh2_tsn_pri_map_tsn_hw_index_get(
   4540     int unit,
   4541     uint32 sw_idx,
   4542     uint32 *hw_index)
   4543 {
   4544     if (!soc_feature(unit, soc_feature_tsn)) {
   4545         return BCM_E_UNAVAIL;
   4546     }
   4547 
   4548     /* Parameter validation */
   4549     if (NULL == hw_index ||
   4550         GH2_PRI_MAP_TSN_TAB_SIZE <= sw_idx) {
   4551         return BCM_E_PARAM;
   4552     }
   4553     *hw_index = sw_idx;
   4554 
   4555     LOG_VERBOSE(BSL_LS_BCM_TSN,
   4556                 (BSL_META_U(unit,
   4557                             "bcmi_gh2_tsn_pri_map_tsn_hw_index_get:"
   4558                             "sw_idx %d, hw_index %d\n"),
   4559                             sw_idx, *hw_index));
   4560     return BCM_E_NONE;
   4561 }
   4562 
   4563 /*
   4564  * Function:
   4565  *      bcmi_gh2_tsn_pri_map_tsn_sw_idx_get
   4566  * Purpose:
   4567  *      Get SW memory index
   4568  * Parameters:
   4569  *      unit     - (IN) Unit number
   4570  *      hw_index - (IN) HW memory base index
   4571  *      sw_idx   - (OUT) SW memory index
   4572  * Returns:
   4573  *      BCM_E_xxx
   4574  */
   4575 STATIC int
   4576 bcmi_gh2_tsn_pri_map_tsn_sw_idx_get(
   4577     int unit,
   4578     uint32 hw_index,
   4579     uint32 *sw_idx)
   4580 {
   4581     if (!soc_feature(unit, soc_feature_tsn)) {
   4582         return BCM_E_UNAVAIL;
   4583     }
   4584 
   4585     /* Parameter validation */
   4586     if (NULL == sw_idx ||
   4587         GH2_PRI_MAP_TSN_TAB_SIZE * GH2_PRI_MAP_TSN_ENT_SIZE <= hw_index) {
   4588         return BCM_E_PARAM;
   4589     }
   4590     *sw_idx = hw_index;
   4591 
   4592     LOG_VERBOSE(BSL_LS_BCM_TSN,
   4593                 (BSL_META_U(unit,
   4594                             "bcmi_gh2_tsn_pri_map_tsn_sw_idx_get:"
   4595                             "hw_index %d, sw_idx %d\n"),
   4596                             hw_index, *sw_idx));
   4597     return BCM_E_NONE;
   4598 }
   4599 
   4600 /*
   4601  * Function:
   4602  *   bcmi_gh2_tsn_pri_map_tsn_wb_hw_existed
   4603  * Purpose:
   4604  *   check if the HW existed value or not
   4605  * Parameters:
   4606  *   unit   - (IN) Unit being initialized
   4607  *   sw_idx - (IN) SW memory index
   4608  * Returns:
   4609  *   BCM_E_NOT_FOUND means HW doesn't exist
   4610  *   BCM_E_NONE means HW existed
   4611  */
   4612 STATIC int
   4613 bcmi_gh2_tsn_pri_map_tsn_wb_hw_existed(
   4614     int unit,
   4615     uint32 sw_idx)
   4616 {
   4617 #if defined(BCM_WARM_BOOT_SUPPORT)
   4618     uint32 hw_idx;
   4619     uint32 entry_idx;
   4620     uint32 field_data;
   4621     soc_mem_t mem = TSN_PRI_OFFSETm;
   4622     tsn_pri_offset_entry_t data;
   4623     int is_default_offset = TRUE, is_default_new_pri = TRUE;
   4624 
   4625     LOG_VERBOSE(BSL_LS_BCM_TSN,
   4626                 (BSL_META_U(unit,
   4627                             "bcmi_gh2_tsn_pri_map_tsn_wb_hw_existed:"
   4628                             "sw_idx %d\n"),
   4629                             sw_idx));
   4630 
   4631     if (!SOC_WARM_BOOT(unit) ||
   4632         !soc_feature(unit, soc_feature_tsn)) {
   4633         return BCM_E_UNAVAIL;
   4634     }
   4635 
   4636     /* 1st profile should exist all the time, dont need to do wb */
   4637     if (!((sw_idx > 0) && (sw_idx < GH2_PRI_MAP_TSN_TAB_SIZE))) {
   4638         LOG_ERROR(BSL_LS_BCM_TSN,
   4639                   (BSL_META_U(unit,
   4640                               "Invalid sw_idx(%d).\n"),
   4641                               sw_idx));
   4642         assert((sw_idx > 0) && (sw_idx < GH2_PRI_MAP_TSN_TAB_SIZE));
   4643         return BCM_E_PARAM;
   4644     }
   4645 
   4646     /* Get the flow_offset and new_int_pri from TSN_PRI_OFFSETm */
   4647     entry_idx = 0;
   4648     for (hw_idx = (sw_idx << GH2_PRI_MAP_TSN_SHIFT);
   4649          hw_idx < (sw_idx << GH2_PRI_MAP_TSN_SHIFT) + GH2_PRI_MAP_TSN_ENT_SIZE;
   4650          hw_idx++) {
   4651 
   4652         BCM_IF_ERROR_RETURN(
   4653             soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, &data));
   4654 
   4655         if (SOC_MEM_FIELD_VALID(unit, mem, OFFSETf)) {
   4656             soc_TSN_PRI_OFFSETm_field_get(unit, &data, OFFSETf, &field_data);
   4657 
   4658             /* Check if the current setting from HW is default setting */
   4659             if (default_offset[entry_idx] != field_data) {
   4660                 is_default_offset = FALSE;
   4661                 break;
   4662             }
   4663         }
   4664         else {
   4665             return BCM_E_INTERNAL;
   4666         }
   4667 
   4668         if (SOC_MEM_FIELD_VALID(unit, mem, INT_PRIf)) {
   4669             soc_TSN_PRI_OFFSETm_field_get(unit, &data, INT_PRIf, &field_data);
   4670 
   4671             /* Check if the current setting from HW is default setting */
   4672             if (default_new_pri[entry_idx] != field_data) {
   4673                 is_default_new_pri = FALSE;
   4674                 break;
   4675             }
   4676         }
   4677         else {
   4678             return BCM_E_INTERNAL;
   4679         }
   4680         entry_idx++;
   4681     }
   4682 
   4683     /* Return BCM_E_NOT_FOUND means HW doesn't exist */
   4684     if ((is_default_offset == TRUE) && (is_default_new_pri == TRUE)) {
   4685         return BCM_E_NOT_FOUND;
   4686     }
   4687 
   4688     /* Return BCM_E_NONE means HW existed */
   4689     return BCM_E_NONE;
   4690 #else /* BCM_WARM_BOOT_SUPPORT */
   4691     return BCM_E_UNAVAIL;
   4692 #endif /* BCM_WARM_BOOT_SUPPORT */
   4693 }
   4694 
   4695 #if defined(BCM_TSN_SR_SUPPORT)
   4696 /*
   4697  * Function:
   4698  *      bcmi_gh2_tsn_pri_map_sr_set
   4699  * Purpose:
   4700  *      Set the Priority Map configuration to hardware
   4701  * Parameters:
   4702  *      unit   - (IN) Unit number
   4703  *      sw_idx - (IN) SW memory index
   4704  *      config - (OUT) Priority Map configuration
   4705  * Returns:
   4706  *      BCM_E_xxx
   4707  */
   4708 STATIC int
   4709 bcmi_gh2_tsn_pri_map_sr_set(
   4710     int unit,
   4711     uint32 sw_idx,
   4712     bcm_tsn_pri_map_config_t *config)
   4713 {
   4714     uint32 hw_idx;
   4715     uint32 entry_idx;
   4716     soc_mem_t mem = SR_PRI_OFFSETm;
   4717     sr_pri_offset_entry_t data;
   4718     uint32 field_data;
   4719     int is_default_offset = TRUE, is_default_new_pri = TRUE;
   4720     bcm_tsn_pri_map_entry_t *map_entry;
   4721 
   4722     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   4723         return BCM_E_UNAVAIL;
   4724     }
   4725 
   4726     if (!(sw_idx < GH2_PRI_MAP_SR_TAB_SIZE)) {
   4727         LOG_ERROR(BSL_LS_BCM_TSN,
   4728                   (BSL_META_U(unit,
   4729                               "Invalid sw_idx(%d).\n"),
   4730                               sw_idx));
   4731         assert(sw_idx < GH2_PRI_MAP_SR_TAB_SIZE);
   4732         return BCM_E_PARAM;
   4733     }
   4734 
   4735     /* Parameter validation */
   4736     if (NULL == config) {
   4737         return BCM_E_PARAM;
   4738     }
   4739 
   4740     /* Set the flow_offset and new_int_pri to SR_PRI_OFFSETm */
   4741     entry_idx = 0;
   4742     for (hw_idx = (sw_idx << GH2_PRI_MAP_SR_SHIFT);
   4743          hw_idx < (sw_idx << GH2_PRI_MAP_SR_SHIFT) + GH2_PRI_MAP_SR_ENT_SIZE;
   4744          hw_idx++) {
   4745 
   4746         map_entry = &(config->map_entries[entry_idx]);
   4747         is_default_offset =
   4748             (BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET & (map_entry->flags)) ?
   4749             FALSE : TRUE;
   4750         is_default_new_pri =
   4751             (BCM_TSN_PRI_MAP_ENTRY_NEW_INT_PRI & (map_entry->flags)) ?
   4752             FALSE : TRUE;
   4753 
   4754         BCM_IF_ERROR_RETURN(
   4755             soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, &data));
   4756 
   4757         if (SOC_MEM_FIELD_VALID(unit, mem, OFFSETf)) {
   4758             if (TRUE == is_default_offset) {
   4759                 field_data = default_offset[entry_idx];
   4760             }
   4761             else {
   4762                 field_data = config->map_entries[entry_idx].flow_offset;
   4763             }
   4764 
   4765             /* Check if the value fit the target field range */
   4766             BCM_IF_ERROR_RETURN
   4767                 (soc_mem_field32_fit(
   4768                     unit, mem, OFFSETf,
   4769                     field_data));
   4770             soc_SR_PRI_OFFSETm_field_set(unit, &data, OFFSETf, &field_data);
   4771         }
   4772         else {
   4773             return BCM_E_INTERNAL;
   4774         }
   4775 
   4776         if (SOC_MEM_FIELD_VALID(unit, mem, INT_PRIf)) {
   4777             if (TRUE == is_default_new_pri) {
   4778                 field_data = default_new_pri[entry_idx];
   4779             }
   4780             else {
   4781                 field_data = config->map_entries[entry_idx].new_int_pri;
   4782             }
   4783             if (field_data >= GH2_PRI_MAP_SR_MAX_NEW_PRI_VALUE) {
   4784                 return BCM_E_PARAM;
   4785             }
   4786 
   4787             /* Check if the value fit the target field range */
   4788             BCM_IF_ERROR_RETURN
   4789                 (soc_mem_field32_fit(
   4790                     unit, mem, INT_PRIf,
   4791                     field_data));
   4792             soc_SR_PRI_OFFSETm_field_set(unit, &data, INT_PRIf, &field_data);
   4793         }
   4794         else {
   4795             return BCM_E_INTERNAL;
   4796         }
   4797         BCM_IF_ERROR_RETURN(
   4798             soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_idx, &data));
   4799         entry_idx++;
   4800     }
   4801     return BCM_E_NONE;
   4802 }
   4803 
   4804 /*
   4805  * Function:
   4806  *      bcmi_gh2_tsn_pri_map_sr_get
   4807  * Purpose:
   4808  *      Get the Priority Map configuration from hardware
   4809  * Parameters:
   4810  *      unit   - (IN) Unit number
   4811  *      sw_idx - (IN) SW memory index
   4812  *      config - (OUT) Priority Map configuration
   4813  * Returns:
   4814  *      BCM_E_xxx
   4815  */
   4816 STATIC int
   4817 bcmi_gh2_tsn_pri_map_sr_get(
   4818     int unit,
   4819     uint32 sw_idx,
   4820     bcm_tsn_pri_map_config_t *config)
   4821 {
   4822     uint32 hw_idx;
   4823     uint32 entry_idx;
   4824     soc_mem_t mem = SR_PRI_OFFSETm;
   4825     sr_pri_offset_entry_t data;
   4826     uint32 field_data;
   4827     int is_default_offset = TRUE, is_default_new_pri = TRUE;
   4828 
   4829     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   4830         return BCM_E_UNAVAIL;
   4831     }
   4832 
   4833     if (!(sw_idx < GH2_PRI_MAP_SR_TAB_SIZE)) {
   4834         LOG_ERROR(BSL_LS_BCM_TSN,
   4835                   (BSL_META_U(unit,
   4836                               "Invalid sw_idx(%d).\n"),
   4837                               sw_idx));
   4838         assert(sw_idx < GH2_PRI_MAP_SR_TAB_SIZE);
   4839         return BCM_E_PARAM;
   4840     }
   4841 
   4842     /* Parameter validation */
   4843     if (NULL == config) {
   4844         return BCM_E_PARAM;
   4845     }
   4846 
   4847     /* Get the flow_offset and new_int_pri from SR_PRI_OFFSETm */
   4848     entry_idx = 0;
   4849     for (hw_idx = (sw_idx << GH2_PRI_MAP_SR_SHIFT);
   4850          hw_idx < (sw_idx << GH2_PRI_MAP_SR_SHIFT) + GH2_PRI_MAP_SR_ENT_SIZE;
   4851          hw_idx++) {
   4852 
   4853         BCM_IF_ERROR_RETURN(
   4854             soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, &data));
   4855 
   4856         if (SOC_MEM_FIELD_VALID(unit, mem, OFFSETf)) {
   4857             soc_SR_PRI_OFFSETm_field_get(unit, &data, OFFSETf, &field_data);
   4858             config->map_entries[entry_idx].flow_offset = field_data;
   4859 
   4860             /* Check if the current setting from HW is default setting */
   4861             if (default_offset[entry_idx] != field_data) {
   4862                 is_default_offset = FALSE;
   4863             }
   4864         }
   4865         else {
   4866             return BCM_E_INTERNAL;
   4867         }
   4868 
   4869         if (SOC_MEM_FIELD_VALID(unit, mem, INT_PRIf)) {
   4870             soc_SR_PRI_OFFSETm_field_get(unit, &data, INT_PRIf, &field_data);
   4871             config->map_entries[entry_idx].new_int_pri = field_data;
   4872 
   4873             /* Check if the current setting from HW is default setting */
   4874             if (default_new_pri[entry_idx] != field_data) {
   4875                 is_default_new_pri = FALSE;
   4876             }
   4877         }
   4878         else {
   4879             return BCM_E_INTERNAL;
   4880         }
   4881         entry_idx++;
   4882     }
   4883 
   4884     /* Set SR related setting */
   4885     config->map_type = bcmTsnPriMapTypeSrFlow;
   4886     config->num_map_entries = GH2_PRI_MAP_SR_ENT_SIZE;
   4887 
   4888     /* Check if the HW setting is default setting, and set valid flags. */
   4889     for (entry_idx = 0;
   4890          entry_idx < GH2_PRI_MAP_SR_ENT_SIZE;
   4891          entry_idx++) {
   4892         config->map_entries[entry_idx].flags = 0;
   4893 
   4894         if (FALSE == is_default_offset) {
   4895             config->map_entries[entry_idx].flags |=
   4896                 BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET;
   4897         }
   4898         if (FALSE == is_default_new_pri) {
   4899             config->map_entries[entry_idx].flags |=
   4900                 BCM_TSN_PRI_MAP_ENTRY_NEW_INT_PRI;
   4901         }
   4902     }
   4903     return BCM_E_NONE;
   4904 }
   4905 
   4906 /*
   4907  * Function:
   4908  *      bcmi_gh2_tsn_pri_map_sr_delete
   4909  * Purpose:
   4910  *      Delete the Priority Map configuration on hardware
   4911  * Parameters:
   4912  *      unit   - (IN) Unit number
   4913  *      sw_idx - (IN) SW memory index
   4914  * Returns:
   4915  *      BCM_E_xxx
   4916  */
   4917 STATIC int
   4918 bcmi_gh2_tsn_pri_map_sr_delete(
   4919     int unit,
   4920     uint32 sw_idx)
   4921 {
   4922     uint32 hw_idx;
   4923     uint32 entry_idx;
   4924     soc_mem_t mem = SR_PRI_OFFSETm;
   4925     sr_pri_offset_entry_t data;
   4926     uint32 field_data;
   4927 
   4928     LOG_VERBOSE(BSL_LS_BCM_TSN,
   4929                 (BSL_META_U(unit,
   4930                             "bcmi_gh2_tsn_pri_map_sr_delete:"
   4931                             "sw_idx %d\n"),
   4932                             sw_idx));
   4933 
   4934     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   4935         return BCM_E_UNAVAIL;
   4936     }
   4937 
   4938     /* 1st profile should exist all the time, cannot delete sw_idx 0 */
   4939     if (!((sw_idx > 0) && (sw_idx < GH2_PRI_MAP_SR_TAB_SIZE))) {
   4940         LOG_ERROR(BSL_LS_BCM_TSN,
   4941                   (BSL_META_U(unit,
   4942                               "Invalid sw_idx(%d).\n"),
   4943                               sw_idx));
   4944         assert((sw_idx > 0) && (sw_idx < GH2_PRI_MAP_SR_TAB_SIZE));
   4945         return BCM_E_PARAM;
   4946     }
   4947 
   4948     if (sw_idx == 0) {
   4949         LOG_WARN(BSL_LS_BCM_TSN,
   4950                  (BSL_META_U(unit,
   4951                              "cannot delete default profile(sw_idx = 0).\n")));
   4952         return BCM_E_NONE;
   4953     }
   4954 
   4955     /* Set the flow_offset and new_int_pri to SR_PRI_OFFSETm */
   4956     entry_idx = 0;
   4957     for (hw_idx = (sw_idx << GH2_PRI_MAP_SR_SHIFT);
   4958          hw_idx < (sw_idx << GH2_PRI_MAP_SR_SHIFT) + GH2_PRI_MAP_SR_ENT_SIZE;
   4959          hw_idx++) {
   4960 
   4961         BCM_IF_ERROR_RETURN(
   4962             soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, &data));
   4963 
   4964         if (SOC_MEM_FIELD_VALID(unit, mem, OFFSETf)) {
   4965             field_data = default_offset[entry_idx];
   4966             soc_SR_PRI_OFFSETm_field_set(unit, &data, OFFSETf, &field_data);
   4967         }
   4968         else {
   4969             return BCM_E_INTERNAL;
   4970         }
   4971 
   4972         if (SOC_MEM_FIELD_VALID(unit, mem, INT_PRIf)) {
   4973             field_data = default_new_pri[entry_idx];
   4974             soc_SR_PRI_OFFSETm_field_set(unit, &data, INT_PRIf, &field_data);
   4975         }
   4976         else {
   4977             return BCM_E_INTERNAL;
   4978         }
   4979         BCM_IF_ERROR_RETURN(
   4980             soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_idx, &data));
   4981         entry_idx++;
   4982     }
   4983     return BCM_E_NONE;
   4984 }
   4985 
   4986 /*
   4987  * Function:
   4988  *      bcmi_gh2_tsn_pri_map_sr_hw_index_get
   4989  * Purpose:
   4990  *      Get HW memory base index
   4991  * Parameters:
   4992  *      unit     - (IN) Unit number
   4993  *      sw_idx   - (IN) SW memory index
   4994  *      hw_index - (OUT) HW memory base index
   4995  * Returns:
   4996  *      BCM_E_xxx
   4997  */
   4998 STATIC int
   4999 bcmi_gh2_tsn_pri_map_sr_hw_index_get(
   5000     int unit,
   5001     uint32 sw_idx,
   5002     uint32 *hw_index)
   5003 {
   5004     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   5005         return BCM_E_UNAVAIL;
   5006     }
   5007 
   5008     /* Parameter validation */
   5009     if (NULL == hw_index ||
   5010         GH2_PRI_MAP_SR_TAB_SIZE <= sw_idx) {
   5011         return BCM_E_PARAM;
   5012     }
   5013     *hw_index = sw_idx;
   5014     LOG_VERBOSE(BSL_LS_BCM_TSN,
   5015                 (BSL_META_U(unit,
   5016                             "bcmi_gh2_tsn_pri_map_sr_hw_index_get:"
   5017                             "sw_idx %d, hw_index %d\n"),
   5018                             sw_idx, *hw_index));
   5019     return BCM_E_NONE;
   5020 }
   5021 
   5022 /*
   5023  * Function:
   5024  *      bcmi_gh2_tsn_pri_map_sr_sw_idx_get
   5025  * Purpose:
   5026  *      Get SW memory index
   5027  * Parameters:
   5028  *      unit     - (IN) Unit number
   5029  *      hw_index - (IN) HW memory base index
   5030  *      sw_idx   - (OUT) SW memory index
   5031  * Returns:
   5032  *      BCM_E_xxx
   5033  */
   5034 STATIC int
   5035 bcmi_gh2_tsn_pri_map_sr_sw_idx_get(
   5036     int unit,
   5037     uint32 hw_index,
   5038     uint32 *sw_idx)
   5039 {
   5040     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   5041         return BCM_E_UNAVAIL;
   5042     }
   5043 
   5044     /* Parameter validation */
   5045     if (NULL == sw_idx ||
   5046         GH2_PRI_MAP_SR_TAB_SIZE <= hw_index) {
   5047         return BCM_E_PARAM;
   5048     }
   5049     *sw_idx = hw_index;
   5050 
   5051     LOG_VERBOSE(BSL_LS_BCM_TSN,
   5052                 (BSL_META_U(unit,
   5053                             "bcmi_gh2_tsn_pri_map_sr_sw_idx_get:"
   5054                             "hw_index %d, sw_idx %d\n"),
   5055                             hw_index, *sw_idx));
   5056     return BCM_E_NONE;
   5057 }
   5058 
   5059 /*
   5060  * Function:
   5061  *   bcmi_gh2_tsn_pri_map_sr_wb_hw_existed
   5062  * Purpose:
   5063  *   check if the HW existed value or not
   5064  * Parameters:
   5065  *   unit   - (IN) Unit being initialized
   5066  *   sw_idx - (IN) SW memory index
   5067  * Returns:
   5068  *   BCM_E_NOT_FOUND means HW doesn't exist
   5069  *   BCM_E_NONE means HW existed
   5070  */
   5071 STATIC int
   5072 bcmi_gh2_tsn_pri_map_sr_wb_hw_existed(
   5073     int unit,
   5074     uint32 sw_idx)
   5075 {
   5076 #if defined(BCM_WARM_BOOT_SUPPORT)
   5077     uint32 hw_idx;
   5078     uint32 entry_idx;
   5079     uint32 field_data;
   5080     soc_mem_t mem = SR_PRI_OFFSETm;
   5081     sr_pri_offset_entry_t data;
   5082     int is_default_offset = TRUE, is_default_new_pri = TRUE;
   5083 
   5084     LOG_VERBOSE(BSL_LS_BCM_TSN,
   5085                 (BSL_META_U(unit,
   5086                             "bcmi_gh2_tsn_pri_map_sr_wb_hw_existed:"
   5087                             "sw_idx %d\n"),
   5088                             sw_idx));
   5089 
   5090     if (!SOC_WARM_BOOT(unit) ||
   5091         !soc_feature(unit, soc_feature_tsn_sr)) {
   5092         return BCM_E_UNAVAIL;
   5093     }
   5094 
   5095     /* 1st profile should exist all the time, cannot delete sw_idx 0 */
   5096     if (!((sw_idx > 0) && (sw_idx < GH2_PRI_MAP_SR_TAB_SIZE))) {
   5097         LOG_ERROR(BSL_LS_BCM_TSN,
   5098                   (BSL_META_U(unit,
   5099                               "Invalid sw_idx(%d).\n"),
   5100                               sw_idx));
   5101         assert((sw_idx > 0) && (sw_idx < GH2_PRI_MAP_SR_TAB_SIZE));
   5102         return BCM_E_PARAM;
   5103     }
   5104 
   5105     /* Get the flow_offset and new_int_pri from SR_PRI_OFFSETm */
   5106     entry_idx = 0;
   5107     for (hw_idx = (sw_idx << GH2_PRI_MAP_SR_SHIFT);
   5108          hw_idx < (sw_idx << GH2_PRI_MAP_SR_SHIFT) + GH2_PRI_MAP_SR_ENT_SIZE;
   5109          hw_idx++) {
   5110 
   5111         BCM_IF_ERROR_RETURN(
   5112             soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, &data));
   5113 
   5114         if (SOC_MEM_FIELD_VALID(unit, mem, OFFSETf)) {
   5115             soc_SR_PRI_OFFSETm_field_get(unit, &data, OFFSETf, &field_data);
   5116 
   5117             /* check if the current setting from HW is default setting */
   5118             if (default_offset[entry_idx] != field_data) {
   5119                 is_default_offset = FALSE;
   5120                 break;
   5121             }
   5122         }
   5123         else {
   5124             return BCM_E_INTERNAL;
   5125         }
   5126 
   5127         if (SOC_MEM_FIELD_VALID(unit, mem, INT_PRIf)) {
   5128             soc_SR_PRI_OFFSETm_field_get(unit, &data, INT_PRIf, &field_data);
   5129 
   5130             /* Check if the current setting from HW is default setting */
   5131             if (default_new_pri[entry_idx] != field_data) {
   5132                 is_default_new_pri = FALSE;
   5133                 break;
   5134             }
   5135         }
   5136         else {
   5137             return BCM_E_INTERNAL;
   5138         }
   5139         entry_idx++;
   5140     }
   5141 
   5142     /* Return BCM_E_NOT_FOUND means HW doesn't exist */
   5143     if ((is_default_offset == TRUE) && (is_default_new_pri == TRUE)) {
   5144         return BCM_E_NOT_FOUND;
   5145     }
   5146 
   5147     /* Return BCM_E_NONE means HW existed */
   5148     return BCM_E_NONE;
   5149 #else /* BCM_WARM_BOOT_SUPPORT */
   5150     return BCM_E_UNAVAIL;
   5151 #endif /* BCM_WARM_BOOT_SUPPORT */
   5152 }
   5153 
   5154 #endif /* BCM_TSN_SR_SUPPORT */
   5155 
   5156 
   5157 /*
   5158  * Function:
   5159  *      bcmi_gh2_tsn_pri_map_mtu_hw_index_get
   5160  * Purpose:
   5161  *      Get HW memory base index
   5162  * Parameters:
   5163  *      unit     - (IN) Unit number
   5164  *      sw_idx   - (IN) SW memory index
   5165  *      hw_index - (OUT) HW memory base index
   5166  * Returns:
   5167  *      BCM_E_xxx
   5168  */
   5169 STATIC int
   5170 bcmi_gh2_tsn_pri_map_mtu_hw_index_get(
   5171     int unit,
   5172     uint32 sw_idx,
   5173     uint32 *hw_index)
   5174 {
   5175     if (!soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   5176         return BCM_E_UNAVAIL;
   5177     }
   5178 
   5179     /* Parameter validation */
   5180     if (NULL == hw_index ||
   5181         GH2_PRI_MAP_MTU_TAB_SIZE <= sw_idx) {
   5182         return BCM_E_PARAM;
   5183     }
   5184     *hw_index = sw_idx * GH2_PRI_MAP_MTU_ENT_SIZE;
   5185 
   5186     LOG_VERBOSE(BSL_LS_BCM_TSN,
   5187                 (BSL_META_U(unit,
   5188                             "bcmi_gh2_tsn_pri_map_mtu_hw_index_get:"
   5189                             "sw_idx = %d, hw_index = %d\n"),
   5190                             sw_idx, *hw_index));
   5191     return BCM_E_NONE;
   5192 }
   5193 
   5194 /*
   5195  * Function:
   5196  *      bcmi_gh2_tsn_pri_map_mtu_sw_idx_get
   5197  * Purpose:
   5198  *      Get SW memory index
   5199  * Parameters:
   5200  *      unit     - (IN) Unit number
   5201  *      hw_index - (IN) HW memory base index
   5202  *      sw_idx   - (OUT) SW memory index
   5203  * Returns:
   5204  *      BCM_E_xxx
   5205  */
   5206 STATIC int
   5207 bcmi_gh2_tsn_pri_map_mtu_sw_idx_get(
   5208     int unit,
   5209     uint32 hw_index,
   5210     uint32 *sw_idx)
   5211 {
   5212     if (!soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   5213         return BCM_E_UNAVAIL;
   5214     }
   5215 
   5216     /* Parameter validation */
   5217     if (NULL == sw_idx ||
   5218         GH2_PRI_MAP_MTU_MASK & hw_index ||
   5219         GH2_PRI_MAP_MTU_TAB_SIZE * GH2_PRI_MAP_MTU_ENT_SIZE <= hw_index) {
   5220         return BCM_E_PARAM;
   5221     }
   5222     *sw_idx = hw_index >> GH2_PRI_MAP_MTU_SHIFT;
   5223 
   5224     LOG_VERBOSE(BSL_LS_BCM_TSN,
   5225                 (BSL_META_U(unit,
   5226                             "bcmi_gh2_tsn_pri_map_mtu_sw_idx_get:"
   5227                             "hw_index %d, sw_idx %d\n"),
   5228                             hw_index, *sw_idx));
   5229     return BCM_E_NONE;
   5230 }
   5231 
   5232 /*
   5233  * Function:
   5234  *      bcmi_gh2_tsn_pri_map_stu_hw_index_get
   5235  * Purpose:
   5236  *      Get HW memory base index
   5237  * Parameters:
   5238  *      unit     - (IN) Unit number
   5239  *      sw_idx   - (IN) SW memory index
   5240  *      hw_index - (OUT) HW memory base index
   5241  * Returns:
   5242  *      BCM_E_xxx
   5243  */
   5244 STATIC int
   5245 bcmi_gh2_tsn_pri_map_stu_hw_index_get(
   5246     int unit,
   5247     uint32 sw_idx,
   5248     uint32 *hw_index)
   5249 {
   5250     if (!soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   5251         return BCM_E_UNAVAIL;
   5252     }
   5253 
   5254     /* Parameter validation */
   5255     if (NULL == hw_index ||
   5256         GH2_PRI_MAP_STU_TAB_SIZE <= sw_idx) {
   5257         return BCM_E_PARAM;
   5258     }
   5259     *hw_index = sw_idx * GH2_PRI_MAP_STU_ENT_SIZE;
   5260 
   5261     LOG_VERBOSE(BSL_LS_BCM_TSN,
   5262                 (BSL_META_U(unit,
   5263                             "bcmi_gh2_tsn_pri_map_stu_hw_index_get:"
   5264                             "sw_idx %d, hw_index %d\n"),
   5265                             sw_idx, *hw_index));
   5266     return BCM_E_NONE;
   5267 }
   5268 
   5269 /*
   5270  * Function:
   5271  *      bcmi_gh2_tsn_pri_map_stu_sw_idx_get
   5272  * Purpose:
   5273  *      Get SW memory index
   5274  * Parameters:
   5275  *      unit     - (IN) Unit number
   5276  *      hw_index - (IN) HW memory base index
   5277  *      sw_idx   - (OUT) SW memory index
   5278  * Returns:
   5279  *      BCM_E_xxx
   5280  */
   5281 STATIC int
   5282 bcmi_gh2_tsn_pri_map_stu_sw_idx_get(
   5283     int unit,
   5284     uint32 hw_index,
   5285     uint32 *sw_idx)
   5286 {
   5287     if (!soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   5288         return BCM_E_UNAVAIL;
   5289     }
   5290 
   5291     /* Parameter validation */
   5292     if (NULL == sw_idx ||
   5293         GH2_PRI_MAP_STU_MASK & hw_index ||
   5294         GH2_PRI_MAP_STU_TAB_SIZE * GH2_PRI_MAP_STU_ENT_SIZE <= hw_index) {
   5295         return BCM_E_PARAM;
   5296     }
   5297     *sw_idx = hw_index >> GH2_PRI_MAP_STU_SHIFT;
   5298 
   5299     LOG_VERBOSE(BSL_LS_BCM_TSN,
   5300                 (BSL_META_U(unit,
   5301                             "bcmi_gh2_tsn_pri_map_stu_sw_idx_get:"
   5302                             "hw_index %d, sw_idx %d\n"),
   5303                             hw_index, *sw_idx));
   5304     return BCM_E_NONE;
   5305 }
   5306 
   5307 /*
   5308  * Function:
   5309  *     bcmi_gh2_tsn_control_set
   5310  * Description:
   5311  *     Configure device-wide operation modes for TSN.
   5312  * Parameters:
   5313  *     unit - (IN) Unit number.
   5314  *     type - (IN) Control type of bcm_tsn_control_t.
   5315  *     arg  - (IN) argument to be set
   5316  * Returns:
   5317  *     BCM_E_XXX
   5318  */
   5319 STATIC int
   5320 bcmi_gh2_tsn_control_set(int unit, bcm_tsn_control_t type, uint32 arg)
   5321 {
   5322 #if defined(BCM_TSN_SR_SUPPORT)
   5323     soc_reg_t config_reg = INVALIDr;
   5324     soc_mem_t config_mem = INVALIDm;
   5325     soc_mem_t config_mem_egr = INVALIDm;
   5326     soc_field_t config_field = INVALIDf;
   5327     uint32 fldval = 0;
   5328     uint32 regval = 0;
   5329     int memidx = 0;
   5330     uint32 entry[SOC_MAX_MEM_WORDS];
   5331 #endif /* BCM_TSN_SR_SUPPORT */
   5332 
   5333     LOG_VERBOSE(BSL_LS_BCM_TSN,
   5334                 (BSL_META_U(unit,
   5335                             "bcmi_esw_tsn_control_set: type = %d arg = %d\n"),
   5336                             type, arg));
   5337 
   5338 #if defined(BCM_TSN_SR_SUPPORT)
   5339     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   5340         return (BCM_E_UNAVAIL);
   5341     }
   5342 #endif /* BCM_TSN_SR_SUPPORT */
   5343 
   5344     switch (type) {
   5345 #if defined(BCM_TSN_SR_SUPPORT)
   5346         case bcmTsnControlSrAgeTickInterval:
   5347             if (((int)arg < 0) || (arg > 0xffff)) {
   5348                 return BCM_E_PARAM;
   5349             }
   5350             config_reg = SR_AGING_TIMERr;
   5351             config_field = AGE_OUT_TIMEf;
   5352             fldval = arg;
   5353             if (EVENTS_BKINFO(unit) != NULL) {
   5354                 EVENTS_BKINFO(unit)->ageout_tick_ms = arg;
   5355             }
   5356             break;
   5357         case bcmTsnControlSrAgeOutEnable:
   5358             if (((int)arg < 0) || (arg > 1)) {
   5359                 return BCM_E_PARAM;
   5360             }
   5361             config_reg = SR_AGING_TIMERr;
   5362             config_field = AGE_ENAf;
   5363             fldval = arg;
   5364             if (EVENTS_BKINFO(unit) != NULL) {
   5365                 EVENTS_BKINFO(unit)->age_enable = arg;
   5366             }
   5367             break;
   5368         case bcmTsnControlSrSeqNumWindowResetMode:
   5369             config_reg = SR_AGING_TIMERr;
   5370             config_field = SN_WINDOW_RESET_TYPEf;
   5371             if (arg == BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_HW1) {
   5372                 fldval = 0;
   5373             } else if (arg == BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_HW2) {
   5374                 fldval = 1;
   5375             } else if (arg == BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_SW) {
   5376                 fldval = 2;
   5377             } else {
   5378                 return BCM_E_PARAM;
   5379             }
   5380 
   5381             if (EVENTS_BKINFO(unit) != NULL) {
   5382                 EVENTS_BKINFO(unit)->window_reset_mode = arg;
   5383             }
   5384             break;
   5385         case bcmTsnControlSrLooseOutOfOrder:
   5386             if (((int)arg < 0) || (arg > 1)) {
   5387                 return BCM_E_PARAM;
   5388             }
   5389             config_reg = SR_OUT_OF_ORDER_CONTROLr;
   5390             config_field = OUT_OF_ORDER_CONTROLf;
   5391             fldval = arg;
   5392             break;
   5393         case bcmTsnControlSrHsrEthertype:
   5394             if (arg > 0xffff) {
   5395                 return BCM_E_PARAM;
   5396             }
   5397             config_mem = SR_ETHERTYPESm;
   5398             config_mem_egr = EGR_SR_ETHERTYPESm;
   5399             config_field = HSR_ETHERTYPEf;
   5400             memidx = 0;
   5401             fldval = arg;
   5402             break;
   5403         case bcmTsnControlSrPrpEthertype:
   5404             if (arg > 0xffff) {
   5405                 return BCM_E_PARAM;
   5406             }
   5407             config_mem = SR_ETHERTYPESm;
   5408             config_mem_egr = EGR_SR_ETHERTYPESm;
   5409             config_field = PRP_SUFFIXf;
   5410             memidx = 0;
   5411             fldval = arg;
   5412             break;
   5413         case bcmTsnControlSrDot1cbEthertype:
   5414             if (arg > 0xffff) {
   5415                 return BCM_E_PARAM;
   5416             }
   5417             config_mem = SR_ETHERTYPESm;
   5418             config_mem_egr = EGR_SR_ETHERTYPESm;
   5419             config_field = DOT1CB_ETHERTYPEf;
   5420             memidx = 0;
   5421             fldval = arg;
   5422             break;
   5423 #endif /* BCM_TSN_SR_SUPPORT */
   5424         default:
   5425             return BCM_E_PARAM;
   5426     }
   5427 
   5428 #if defined(BCM_TSN_SR_SUPPORT)
   5429     if (config_reg != INVALIDr) {
   5430         BCM_IF_ERROR_RETURN
   5431             (soc_reg32_get(unit, config_reg, REG_PORT_ANY, 0, &regval));
   5432         soc_reg_field_set(unit, config_reg, &regval,
   5433                           config_field, fldval);
   5434         BCM_IF_ERROR_RETURN
   5435             (soc_reg32_set(unit, config_reg, REG_PORT_ANY, 0, regval));
   5436     }
   5437 
   5438     if (config_mem != INVALIDm) {
   5439         BCM_IF_ERROR_RETURN
   5440             (soc_mem_read(unit, config_mem, MEM_BLOCK_ANY, memidx, &entry));
   5441         soc_mem_field32_set(unit, config_mem, &entry, config_field, fldval);
   5442         BCM_IF_ERROR_RETURN
   5443             (soc_mem_write(unit, config_mem, MEM_BLOCK_ALL, memidx, &entry));
   5444     }
   5445 
   5446     if (config_mem_egr != INVALIDm) {
   5447         BCM_IF_ERROR_RETURN
   5448             (soc_mem_read(unit, config_mem_egr, MEM_BLOCK_ANY,
   5449                           memidx, &entry));
   5450         soc_mem_field32_set(unit, config_mem_egr, &entry, config_field, fldval);
   5451         BCM_IF_ERROR_RETURN
   5452             (soc_mem_write(unit, config_mem_egr, MEM_BLOCK_ALL,
   5453                            memidx, &entry));
   5454     }
   5455 #endif /* BCM_TSN_SR_SUPPORT */
   5456     return BCM_E_NONE;
   5457 }
   5458 
   5459 /*
   5460  * Function:
   5461  *     bcmi_gh2_tsn_control_get
   5462  * Description:
   5463  *     Get the configure of device-wide TSN operation modes.
   5464  * Parameters:
   5465  *     unit - (IN) Unit number.
   5466  *     type - (IN) Control type of bcm_tsn_control_t.
   5467  *     arg  - (OUT) argument got
   5468  * Returns:
   5469  *     BCM_E_XXX
   5470  */
   5471 STATIC int
   5472 bcmi_gh2_tsn_control_get(int unit, bcm_tsn_control_t type, uint32 *arg)
   5473 {
   5474 #if defined(BCM_TSN_SR_SUPPORT)
   5475     uint32 fldval = 0;
   5476     uint32 regval = 0;
   5477     uint32 entry[SOC_MAX_MEM_WORDS];
   5478 #endif /* BCM_TSN_SR_SUPPORT */
   5479 
   5480     LOG_VERBOSE(BSL_LS_BCM_TSN,
   5481                 (BSL_META_U(unit,
   5482                             "bcmi_esw_tsn_control_get: type = %d"),
   5483                             type));
   5484 
   5485 #if defined(BCM_TSN_SR_SUPPORT)
   5486     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   5487         return (BCM_E_UNAVAIL);
   5488     }
   5489 #endif /* BCM_TSN_SR_SUPPORT */
   5490 
   5491     /* Parameter validation */
   5492     if (NULL == arg) {
   5493         return BCM_E_PARAM;
   5494     }
   5495 
   5496     switch (type) {
   5497 #if defined(BCM_TSN_SR_SUPPORT)
   5498         case bcmTsnControlSrAgeTickInterval:
   5499             BCM_IF_ERROR_RETURN(READ_SR_AGING_TIMERr(unit, &regval));
   5500             fldval = soc_reg_field_get(unit, SR_AGING_TIMERr,
   5501                                        regval, AGE_OUT_TIMEf);
   5502             break;
   5503         case bcmTsnControlSrAgeOutEnable:
   5504             BCM_IF_ERROR_RETURN(READ_SR_AGING_TIMERr(unit, &regval));
   5505             fldval = soc_reg_field_get(unit, SR_AGING_TIMERr,
   5506                                        regval, AGE_ENAf);
   5507             break;
   5508         case bcmTsnControlSrSeqNumWindowResetMode:
   5509             BCM_IF_ERROR_RETURN(READ_SR_AGING_TIMERr(unit, &regval));
   5510             fldval = soc_reg_field_get(unit, SR_AGING_TIMERr,
   5511                                        regval, SN_WINDOW_RESET_TYPEf);
   5512             if (fldval == 0) {
   5513                 fldval = BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_HW1;
   5514             } else if (fldval == 1) {
   5515                 fldval = BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_HW2;
   5516             } else if (fldval == 2) {
   5517                 fldval = BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_SW;
   5518             } else {
   5519                 return BCM_E_FAIL;
   5520             }
   5521             break;
   5522         case bcmTsnControlSrLooseOutOfOrder:
   5523             BCM_IF_ERROR_RETURN(READ_SR_OUT_OF_ORDER_CONTROLr(unit, &regval));
   5524             fldval = soc_reg_field_get(unit, SR_OUT_OF_ORDER_CONTROLr,
   5525                                        regval, OUT_OF_ORDER_CONTROLf);
   5526             break;
   5527         case bcmTsnControlSrHsrEthertype:
   5528             BCM_IF_ERROR_RETURN
   5529                 (soc_mem_read(unit, SR_ETHERTYPESm, MEM_BLOCK_ANY, 0, &entry));
   5530             soc_mem_field_get(unit, SR_ETHERTYPESm,
   5531                               entry, HSR_ETHERTYPEf, &fldval);
   5532             break;
   5533         case bcmTsnControlSrPrpEthertype:
   5534             BCM_IF_ERROR_RETURN
   5535                 (soc_mem_read(unit, SR_ETHERTYPESm, MEM_BLOCK_ANY, 0, &entry));
   5536             soc_mem_field_get(unit, SR_ETHERTYPESm,
   5537                               entry, PRP_SUFFIXf, &fldval);
   5538             break;
   5539         case bcmTsnControlSrDot1cbEthertype:
   5540             BCM_IF_ERROR_RETURN
   5541                 (soc_mem_read(unit, SR_ETHERTYPESm, MEM_BLOCK_ANY, 0, &entry));
   5542             soc_mem_field_get(unit, SR_ETHERTYPESm,
   5543                               entry, DOT1CB_ETHERTYPEf, &fldval);
   5544             break;
   5545 #endif /* BCM_TSN_SR_SUPPORT */
   5546         default:
   5547             return BCM_E_PARAM;
   5548     }
   5549 
   5550 #if defined(BCM_TSN_SR_SUPPORT)
   5551     *arg = fldval;
   5552 
   5553     LOG_VERBOSE(BSL_LS_BCM_TSN,
   5554                 (BSL_META_U(unit,
   5555                             "arg = %d\n"),
   5556                             *arg));
   5557 #endif /* BCM_TSN_SR_SUPPORT */
   5558     return BCM_E_NONE;
   5559 }
   5560 
   5561 /* Helper function to get the reference count of the profile memory entry */
   5562 STATIC int
   5563 bcmi_gh2_tsn_mtu_profmem_refcnt_get(
   5564     int unit,
   5565     bcm_tsn_mtu_profile_type_t type,
   5566     int index,
   5567     int *ref_count)
   5568 {
   5569     soc_profile_mem_t *pmem;
   5570 
   5571     if (ref_count == NULL) {
   5572         return BCM_E_PARAM;
   5573     }
   5574     TSN_MTU_BKINFO_IS_INIT(unit, type);
   5575     MTU_BKINFO_LOCK(unit);
   5576     pmem = TSN_BKINFO(unit)->gh2_mtu_bk_info.mtu_profile[type];
   5577     MTU_BKINFO_UNLOCK(unit);
   5578     BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit, pmem,
   5579                                                       index, ref_count));
   5580     return BCM_E_NONE;
   5581 }
   5582 
   5583 /*
   5584  * Function:
   5585  *      bcmi_esw_tsn_mtu_profile_decode
   5586  * Purpose:
   5587  *      Decode the profile id into
   5588  *      HW memory index and mtu profile type
   5589  * Parameters:
   5590  *      unit - (IN) Unit number
   5591  *      mtu_profile_id - (IN) profile id
   5592  *      type - (OUT) Indicates ingress or egress mtu profile
   5593  *      index -(OUT) Indicates HW index of the mem
   5594  * Returns:
   5595  *      BCM_E_xxx
   5596  */
   5597 STATIC int
   5598 bcmi_gh2_tsn_mtu_profile_decode(
   5599     int unit,
   5600     int mtu_profile_id,
   5601     bcm_tsn_mtu_profile_type_t *type,
   5602     int *index)
   5603 {
   5604     soc_profile_mem_table_t *table;
   5605 
   5606     if (type == NULL || index == NULL) {
   5607         return BCM_E_PARAM;
   5608     }
   5609     /* If it is an ingress mtu profile id */
   5610     if ((mtu_profile_id & EGR_MTU_STU_PROFILE_ID_ENCODE) == 0) {
   5611         *type = bcmTsnMtuProfileTypeIngress;
   5612         TSN_MTU_BKINFO_IS_INIT(unit, *type);
   5613     } else {
   5614         /* If it is an egress mtu profile id */
   5615         *type = bcmTsnMtuProfileTypeEgress;
   5616         TSN_MTU_BKINFO_IS_INIT(unit, *type);
   5617         mtu_profile_id &= ~EGR_MTU_STU_PROFILE_ID_ENCODE;
   5618     }
   5619 
   5620     /* Check whether the memory index is valid */
   5621     MTU_BKINFO_LOCK(unit);
   5622     table = TSN_BKINFO(unit)->gh2_mtu_bk_info.mtu_profile[*type]->tables;
   5623     if (mtu_profile_id > table->index_max ||
   5624         mtu_profile_id < table->index_min) {
   5625         MTU_BKINFO_UNLOCK(unit);
   5626         return BCM_E_PARAM;
   5627     }
   5628     MTU_BKINFO_UNLOCK(unit);
   5629     *index = mtu_profile_id;
   5630 
   5631     return BCM_E_NONE;
   5632 }
   5633 
   5634 
   5635 /*
   5636  * Function:
   5637  *      bcmi_esw_tsn_mtu_profile_encode
   5638  * Purpose:
   5639  *      Encode the HW memory index and type
   5640  *      into profile id
   5641  * Parameters:
   5642  *      unit - (IN) Unit number
   5643  *      index - (IN) HW memory index
   5644  *      type - (IN) Indicates ingress or egress mtu profile
   5645  *      mtu_profile_id - (OUT) profile id
   5646  * Returns:
   5647  *      BCM_E_xxx
   5648  */
   5649 STATIC int
   5650 bcmi_gh2_tsn_mtu_profile_encode(
   5651     int unit,
   5652     int index,
   5653     bcm_tsn_mtu_profile_type_t type,
   5654     int *mtu_profile_id)
   5655 {
   5656     soc_profile_mem_table_t *table;
   5657 
   5658     /* The validity of the type is checked in the previous layer */
   5659     if (mtu_profile_id == NULL) {
   5660         return BCM_E_PARAM;
   5661     }
   5662     if (TSN_BKINFO(unit) != NULL) {
   5663         TSN_MTU_BKINFO_IS_INIT(unit, type);
   5664         /* Check whether the memory index is valid */
   5665         MTU_BKINFO_LOCK(unit);
   5666         table = TSN_BKINFO(unit)->gh2_mtu_bk_info.mtu_profile[type]->tables;
   5667         if (index > table->index_max || index < table->index_min) {
   5668             MTU_BKINFO_UNLOCK(unit);
   5669             return BCM_E_PARAM;
   5670         }
   5671         MTU_BKINFO_UNLOCK(unit);
   5672     }
   5673     if (type == bcmTsnMtuProfileTypeIngress) {
   5674         *mtu_profile_id = index;
   5675     } else {
   5676         *mtu_profile_id = index | EGR_MTU_STU_PROFILE_ID_ENCODE;
   5677     }
   5678 
   5679     return BCM_E_NONE;
   5680 }
   5681 
   5682 
   5683 /*
   5684  * Function:
   5685  *      bcmi_gh2_tsn_mtu_profile_traverse
   5686  * Purpose:
   5687  *      Traverse the created match config.
   5688  * Parameters:
   5689  *      unit - (IN) Unit number
   5690  *      cb - (IN) Traverse call back function
   5691  *      user_data - (IN) User data
   5692  * Returns:
   5693  *      BCM_E_xxx
   5694  */
   5695 STATIC int
   5696 bcmi_gh2_tsn_mtu_profile_traverse(
   5697     int unit,
   5698     bcm_tsn_mtu_profile_traverse_cb cb,
   5699     void *user_data)
   5700 {
   5701     int i, profile_id, rv;
   5702     soc_profile_mem_table_t *table;
   5703     bcm_tsn_mtu_profile_type_t type;
   5704 
   5705     if (user_data == NULL || cb == NULL) {
   5706         return BCM_E_PARAM;
   5707     }
   5708 
   5709     /* Traverse on Profile Mem */
   5710     MTU_BKINFO_LOCK(unit);
   5711     for (type = bcmTsnMtuProfileTypeIngress; type < bcmTsnMtuProfileTypeCount;
   5712          type++) {
   5713          TSN_MTU_BKINFO_IS_INIT(unit, type);
   5714          table = TSN_BKINFO(unit)->gh2_mtu_bk_info.mtu_profile[type]->tables;
   5715 
   5716          for (i = table->index_min; i <= table->index_max; i++) {
   5717             bcmi_gh2_tsn_mtu_profile_encode(unit, i, type, &profile_id);
   5718             /* profile id 0 is the default value, won't traverse it */
   5719             if (table->entries[i].ref_count > 0  && i != 0) {
   5720                 rv = cb(unit, profile_id, user_data);
   5721                 if (BCM_FAILURE(rv)) {
   5722                     MTU_BKINFO_UNLOCK(unit);
   5723                     return rv;
   5724                 }
   5725             }
   5726         }
   5727     }
   5728     MTU_BKINFO_UNLOCK(unit);
   5729 
   5730     return BCM_E_NONE;
   5731 }
   5732 
   5733 
   5734 /* helper function to get the profile memory index */
   5735 STATIC int
   5736 bcmi_gh2_tsn_mtu_profile_mem_idx_get(
   5737     int unit,
   5738     bcm_tsn_mtu_profile_type_t type,
   5739     int *min,
   5740     int *max)
   5741 {
   5742     if (min == NULL || max == NULL) {
   5743         return BCM_E_PARAM;
   5744     }
   5745     if (type != bcmTsnMtuProfileTypeIngress &&
   5746         type != bcmTsnMtuProfileTypeEgress) {
   5747         return BCM_E_PARAM;
   5748     }
   5749     *min = soc_mem_index_min(unit, gh2_mtu_profile_mem[type]);
   5750     *max = soc_mem_index_max(unit, gh2_mtu_profile_mem[type]);
   5751 
   5752     return BCM_E_NONE;
   5753 }
   5754 
   5755 /*
   5756  * Function:
   5757  *      bcmi_gh2_tsn_mtu_profile_mem_init
   5758  * Purpose:
   5759  *      Initiate mtu profile mem management structure
   5760  *      and set MTU_PROFILEm entries to zero.
   5761  * Parameters:
   5762  *      unit - (IN) Unit number
   5763  *      type - (IN) Indicates ingress or egress mtu profile
   5764  * Returns:
   5765  *      BCM_E_xxx
   5766  */
   5767 STATIC int
   5768 bcmi_gh2_tsn_mtu_profile_mem_init(
   5769     int unit,
   5770     bcm_tsn_mtu_profile_type_t type)
   5771 {
   5772     soc_mem_t mem;
   5773     soc_mem_t mems[1];
   5774     int mem_words[1];
   5775     soc_profile_mem_t *pmem;
   5776     int rv;
   5777 
   5778     TSN_MTU_BKINFO_IS_INIT(unit, type);
   5779 
   5780     /* Set ingress MTU profile memory HW table entries to zero */
   5781 #if defined(BCM_WARM_BOOT_SUPPORT)
   5782     if (!SOC_WARM_BOOT(unit))
   5783 #endif /* BCM_WARM_BOOT_SUPPORT */
   5784     {
   5785         SOC_IF_ERROR_RETURN
   5786             (soc_mem_clear(unit, gh2_mtu_profile_mem[type], MEM_BLOCK_ALL, 0));
   5787     }
   5788     MTU_BKINFO_LOCK(unit);
   5789     pmem = TSN_BKINFO(unit)->gh2_mtu_bk_info.mtu_profile[type];
   5790     soc_profile_mem_t_init(pmem);
   5791     mem = gh2_mtu_profile_mem[type];
   5792     if (SOC_MEM_IS_VALID(unit, mem)) {
   5793         mems[0] = mem;
   5794         if (type == bcmTsnMtuProfileTypeIngress) {
   5795             mem_words[0] = BYTES2WORDS(sizeof(mtu_profile_entry_t));
   5796         } else {
   5797             mem_words[0] = BYTES2WORDS(sizeof(egr_mtu_profile_entry_t));
   5798         }
   5799     } else {
   5800         MTU_BKINFO_UNLOCK(unit);
   5801         return BCM_E_INTERNAL;
   5802     }
   5803     rv = soc_profile_mem_create(unit, mems, mem_words, 1, pmem);
   5804 
   5805     MTU_BKINFO_UNLOCK(unit);
   5806     return rv;
   5807 }
   5808 
   5809 /*
   5810  * Function:
   5811  *      bcmi_gh2_tsn_mtu_profile_create
   5812  * Purpose:
   5813  *      Create mtu profile with the config pointer
   5814  *      and return the assigned profile id.
   5815  * Parameters:
   5816  *      unit - (IN) Unit number
   5817  *      type - (IN) Indicates ingress or egress mtu profile
   5818  *      config - (IN) configuration of the mtu profile
   5819  *      index - (OUT) HW index of ingress mtu profile
   5820  * Returns:
   5821  *      BCM_E_xxx
   5822  */
   5823 STATIC int
   5824 bcmi_gh2_tsn_mtu_profile_create(
   5825     int unit,
   5826     bcm_tsn_mtu_profile_type_t type,
   5827     bcm_tsn_mtu_config_t *config,
   5828     uint32 *index)
   5829 {
   5830     void *entries[1];
   5831     soc_profile_mem_t *pmem;
   5832     void *entry;
   5833     mtu_profile_entry_t entry_i;
   5834     egr_mtu_profile_entry_t entry_e;
   5835     int rv;
   5836 
   5837     if (index == NULL || config == NULL) {
   5838         return BCM_E_PARAM;
   5839     }
   5840     TSN_MTU_BKINFO_IS_INIT(unit, type);
   5841 
   5842     if (type == bcmTsnMtuProfileTypeIngress) {
   5843         entry = &entry_i;
   5844     } else {
   5845         entry = &entry_e;
   5846     }
   5847 
   5848     SOC_IF_ERROR_RETURN
   5849         (soc_mem_field32_fit(unit, gh2_mtu_profile_mem[type],
   5850                              MTU_SIZEf, config->size));
   5851     SOC_IF_ERROR_RETURN
   5852         (soc_mem_field32_fit(unit, gh2_mtu_profile_mem[type],
   5853                              MTU_ERROR_ACTIONf, config->drop));
   5854     soc_mem_field32_set(unit, gh2_mtu_profile_mem[type], (uint32 *)entry,
   5855                         MTU_SIZEf, config->size);
   5856     soc_mem_field32_set(unit, gh2_mtu_profile_mem[type], (uint32 *)entry,
   5857                         MTU_ERROR_ACTIONf, config->drop);
   5858     MTU_BKINFO_LOCK(unit);
   5859     pmem = TSN_BKINFO(unit)->gh2_mtu_bk_info.mtu_profile[type];
   5860     entries[0] = entry;
   5861     rv = soc_profile_mem_add(unit, pmem, entries, 1, index);
   5862     MTU_BKINFO_UNLOCK(unit);
   5863 
   5864     return rv;
   5865 }
   5866 
   5867 /*
   5868  * Function:
   5869  *      bcmi_gh2_tsn_mtu_profile_get
   5870  * Purpose:
   5871  *      Get mtu profile configuration
   5872  *      with the profile id.
   5873  * Parameters:
   5874  *      unit - (IN) Unit number
   5875  *      index - (IN) HW index of ingress mtu profile
   5876  *      type - (IN) Indicates ingress or egress mtu profile
   5877  *      config - (OUT) configuration of the mtu profile
   5878  * Returns:
   5879  *      BCM_E_xxx
   5880  */
   5881 STATIC int
   5882 bcmi_gh2_tsn_mtu_profile_get(
   5883     int unit,
   5884     int index,
   5885     bcm_tsn_mtu_profile_type_t type,
   5886     bcm_tsn_mtu_config_t *config)
   5887 {
   5888     void *entries[1];
   5889     soc_profile_mem_t *pmem;
   5890     void *entry;
   5891     mtu_profile_entry_t entry_i;
   5892     egr_mtu_profile_entry_t entry_e;
   5893 
   5894     if (config == NULL) {
   5895         return BCM_E_PARAM;
   5896     }
   5897     TSN_MTU_BKINFO_IS_INIT(unit, type);
   5898 
   5899     if (type == bcmTsnMtuProfileTypeIngress) {
   5900         entry = &entry_i;
   5901     } else {
   5902         entry = &entry_e;
   5903     }
   5904     MTU_BKINFO_LOCK(unit);
   5905     pmem = TSN_BKINFO(unit)->gh2_mtu_bk_info.mtu_profile[type];
   5906     entries[0] = entry;
   5907     BCM_IF_ERROR_RETURN(soc_profile_mem_get(unit, pmem, index, 1, entries));
   5908     if (SOC_MEM_FIELD_VALID(unit, gh2_mtu_profile_mem[type], MTU_SIZEf) &&
   5909         SOC_MEM_FIELD_VALID(unit, gh2_mtu_profile_mem[type],
   5910                             MTU_ERROR_ACTIONf)) {
   5911         config->size =
   5912             soc_mem_field32_get(unit, gh2_mtu_profile_mem[type],
   5913                                 (uint32 *)entry, MTU_SIZEf);
   5914         config->drop =
   5915             soc_mem_field32_get(unit, gh2_mtu_profile_mem[type],
   5916                                 (uint32 *)entry, MTU_ERROR_ACTIONf);
   5917     } else {
   5918         MTU_BKINFO_UNLOCK(unit);
   5919         return BCM_E_INTERNAL;
   5920     }
   5921     MTU_BKINFO_UNLOCK(unit);
   5922     return BCM_E_NONE;
   5923 }
   5924 
   5925 /*
   5926  * Function:
   5927  *      bcmi_gh2_tsn_ingress_mtu_profile_set
   5928  * Purpose:
   5929  *      Set mtu profile with the profile id
   5930  *      and config parameter.
   5931  * Parameters:
   5932  *      unit - (IN) Unit number
   5933  *      index - (IN) HW index of ingress mtu profile
   5934  *      type - (IN) Indicates ingress or egress mtu profile
   5935  *      config - (IN) configuration of the mtu profile
   5936  * Returns:
   5937  *      BCM_E_xxx
   5938  */
   5939 STATIC int
   5940 bcmi_gh2_tsn_mtu_profile_set(
   5941     int unit,
   5942     int index,
   5943     bcm_tsn_mtu_profile_type_t type,
   5944     bcm_tsn_mtu_config_t *config)
   5945 {
   5946     int idx, profile_idx, rv;
   5947     void *entries[1];
   5948     bcm_tsn_mtu_config_t config_repl;
   5949     soc_profile_mem_table_t *table;
   5950     soc_profile_mem_t *pmem;
   5951     void *entry;
   5952     mtu_profile_entry_t entry_i;
   5953     egr_mtu_profile_entry_t entry_e;
   5954 
   5955     if (config == NULL) {
   5956         return BCM_E_PARAM;
   5957     }
   5958     TSN_MTU_BKINFO_IS_INIT(unit, type);
   5959 
   5960     /*
   5961     * Search for whether replicated profile mem config exist,
   5962     * if existed return BCM_E_UNAVAIL
   5963     */
   5964     bcm_tsn_mtu_config_t_init(&config_repl);
   5965     MTU_BKINFO_LOCK(unit);
   5966     table = TSN_BKINFO(unit)->gh2_mtu_bk_info.mtu_profile[type]->tables;
   5967     for (idx = table->index_min; idx <= table->index_max; idx++) {
   5968         bcmi_gh2_tsn_mtu_profile_encode(unit, idx, type, &profile_idx);
   5969         bcmi_gh2_tsn_mtu_profile_get(unit, idx, type, &config_repl);
   5970         if ((config_repl.size == config->size) &&
   5971             (config_repl.drop == config->drop)) {
   5972             LOG_WARN(BSL_LS_BCMAPI_TSN,
   5973                     (BSL_META_U(unit,
   5974                                 "config already existed, found"
   5975                                 " mtu profile id(%d)\n"), profile_idx));
   5976             MTU_BKINFO_UNLOCK(unit);
   5977             return BCM_E_EXISTS;
   5978         }
   5979     }
   5980     MTU_BKINFO_UNLOCK(unit);
   5981 
   5982     SOC_IF_ERROR_RETURN
   5983         (soc_mem_field32_fit(unit, gh2_mtu_profile_mem[type],
   5984                              MTU_SIZEf, config->size));
   5985     SOC_IF_ERROR_RETURN
   5986         (soc_mem_field32_fit(unit, gh2_mtu_profile_mem[type], MTU_ERROR_ACTIONf,
   5987                              config->drop));
   5988 
   5989     if (type == bcmTsnMtuProfileTypeIngress) {
   5990         entry = &entry_i;
   5991     } else {
   5992         entry = &entry_e;
   5993     }
   5994 
   5995     if (SOC_MEM_FIELD_VALID(unit, gh2_mtu_profile_mem[type], MTU_SIZEf) &&
   5996         SOC_MEM_FIELD_VALID(unit, gh2_mtu_profile_mem[type],
   5997                             MTU_ERROR_ACTIONf)) {
   5998         soc_mem_field32_set(unit, gh2_mtu_profile_mem[type],
   5999                             entry, MTU_SIZEf, config->size);
   6000         soc_mem_field32_set(unit, gh2_mtu_profile_mem[type], entry,
   6001                             MTU_ERROR_ACTIONf, config->drop);
   6002     } else {
   6003         return BCM_E_INTERNAL;
   6004     }
   6005     MTU_BKINFO_LOCK(unit);
   6006     pmem = TSN_BKINFO(unit)->gh2_mtu_bk_info.mtu_profile[type];
   6007     entries[0] = entry;
   6008     rv = soc_profile_mem_set(unit, pmem, entries, index);
   6009     MTU_BKINFO_UNLOCK(unit);
   6010 
   6011     return rv;
   6012 }
   6013 
   6014 /*
   6015  * Function:
   6016  *      bcmi_gh2_tsn_mtu_profile_destroy
   6017  * Purpose:
   6018  *      Clear the mtu profile with the profile id
   6019  * Parameters:
   6020  *      unit - (IN) Unit number
   6021  *      type - (IN) Indicates ingress or egress mtu profile
   6022  *      index - (IN) Indicated the ingress mtu profile entry
   6023  * Returns:
   6024  *      BCM_E_xxx
   6025  */
   6026 STATIC int
   6027 bcmi_gh2_tsn_mtu_profile_destroy(
   6028     int unit,
   6029     bcm_tsn_mtu_profile_type_t type,
   6030     int index)
   6031 {
   6032     uint32 buf;
   6033     soc_profile_mem_t *pmem;
   6034     void *entry;
   6035     mtu_profile_entry_t entry_i;
   6036     egr_mtu_profile_entry_t entry_e;
   6037     int rv;
   6038 
   6039     TSN_MTU_BKINFO_IS_INIT(unit, type);
   6040     if (type == bcmTsnMtuProfileTypeIngress) {
   6041         entry = &entry_i;
   6042     } else {
   6043         entry = &entry_e;
   6044     }
   6045     MTU_BKINFO_LOCK(unit);
   6046     pmem = TSN_BKINFO(unit)->gh2_mtu_bk_info.mtu_profile[type];
   6047     rv = soc_profile_mem_delete(unit, pmem, index);
   6048     MTU_BKINFO_UNLOCK(unit);
   6049     BCM_IF_ERROR_RETURN(rv);
   6050 
   6051     /* clear the HW table to zero */
   6052     buf = 0x00000000;
   6053     SOC_IF_ERROR_RETURN(soc_mem_read(unit, gh2_mtu_profile_mem[type],
   6054                                      MEM_BLOCK_ANY, index, entry));
   6055     soc_mem_field_set(unit, gh2_mtu_profile_mem[type],
   6056                       (uint32 *)entry, MTU_SIZEf, &buf);
   6057     soc_mem_field_set(unit, gh2_mtu_profile_mem[type], (uint32 *)entry,
   6058                       MTU_ERROR_ACTIONf, &buf);
   6059     SOC_IF_ERROR_RETURN(
   6060         soc_mem_write(unit, gh2_mtu_profile_mem[type], MEM_BLOCK_ALL,
   6061                       index, entry));
   6062 
   6063     return BCM_E_NONE;
   6064 }
   6065 
   6066 /*
   6067  * Function:
   6068  *      bcmi_gh2_tsn_ingress_mtu_config_set
   6069  * Purpose:
   6070  *      Set the priority of source ingress
   6071  *      mtu profile index.
   6072  * Parameters:
   6073  *      unit - (IN) Unit number
   6074  *      config - (IN) Configuration of the mtu profile priority
   6075  * Returns:
   6076  *      BCM_E_xxx
   6077  */
   6078 STATIC int
   6079 bcmi_gh2_tsn_ingress_mtu_config_set(
   6080     int unit,
   6081     bcm_tsn_ingress_mtu_config_t *config)
   6082 {
   6083     uint32 i, reg_val, val;
   6084     int user_valid[bcmTsnMtuSourceCount];
   6085 
   6086     if (config == NULL) {
   6087         return BCM_E_PARAM;
   6088     }
   6089     /* source_order_count is mandatory to set as bcmTsnMtuSourceCount */
   6090     if (config->source_order_count != bcmTsnMtuSourceCount) {
   6091         return BCM_E_PARAM;
   6092     }
   6093     for (i = 0; i < config->source_order_count; i++) {
   6094         user_valid[i] = 0;
   6095     }
   6096     /* Check the user config is correct */
   6097     for (i = 0; i < config->source_order_count; i++) {
   6098         switch (config->source_order[i]) {
   6099             case bcmTsnMtuSourceTsnFlow:
   6100                 user_valid[bcmTsnMtuSourceTsnFlow]++;
   6101                 break;
   6102             case bcmTsnMtuSourceSrFlow:
   6103                 user_valid[bcmTsnMtuSourceSrFlow]++;
   6104                 break;
   6105             case bcmTsnMtuSourcePort:
   6106                 user_valid[bcmTsnMtuSourcePort]++;
   6107                 break;
   6108             case bcmTsnMtuSourceFieldLookup:
   6109                 user_valid[bcmTsnMtuSourceFieldLookup]++;
   6110                 break;
   6111             default:
   6112                 return BCM_E_PARAM;
   6113         }
   6114     }
   6115     for (i = 0; i < config->source_order_count; i++) {
   6116         if (user_valid[i] != 1) {
   6117             return BCM_E_PARAM;
   6118         }
   6119     }
   6120     /*
   6121      * higher value in the register field means higher priority, and less
   6122      * array index in the source_order means higher priority
   6123      */
   6124     BCM_IF_ERROR_RETURN(READ_MTU_PRIORITYr(unit, &reg_val));
   6125     for (i = 0; i < config->source_order_count; i++) {
   6126         val = bcmTsnMtuSourceCount - 1 - i;
   6127         switch (config->source_order[i]) {
   6128             case bcmTsnMtuSourceTsnFlow:
   6129                 soc_reg_field_set(unit, MTU_PRIORITYr, &reg_val,
   6130                                   L2_TSN_PRIORITYf, val);
   6131                 break;
   6132             case bcmTsnMtuSourceSrFlow:
   6133                 soc_reg_field_set(unit, MTU_PRIORITYr, &reg_val,
   6134                                   L2_SR_PRIORITYf, val);
   6135                 break;
   6136             case bcmTsnMtuSourcePort:
   6137                 soc_reg_field_set(unit, MTU_PRIORITYr, &reg_val,
   6138                                   PORT_PRIORITYf, val);
   6139                 break;
   6140             case bcmTsnMtuSourceFieldLookup:
   6141                 soc_reg_field_set(unit, MTU_PRIORITYr, &reg_val,
   6142                                   VFP_PRIORITYf, val);
   6143                 break;
   6144             default:
   6145                 return BCM_E_PARAM;
   6146         }
   6147     }
   6148     BCM_IF_ERROR_RETURN(WRITE_MTU_PRIORITYr(unit, reg_val));
   6149 
   6150     return BCM_E_NONE;
   6151 }
   6152 
   6153 /*
   6154  * Function:
   6155  *      bcmi_gh2_tsn_ingress_mtu_config_get
   6156  * Purpose:
   6157  *      Get the priority of source ingress
   6158  *      mtu profile index.
   6159  * Parameters:
   6160  *      unit - (IN) Unit number
   6161  *      config - (OUT) Configuration of the mtu profile priority
   6162  * Returns:
   6163  *      BCM_E_xxx
   6164  */
   6165 STATIC int
   6166 bcmi_gh2_tsn_ingress_mtu_config_get(
   6167     int unit,
   6168     bcm_tsn_ingress_mtu_config_t *config)
   6169 {
   6170     int i;
   6171     uint32 reg_val, val;
   6172     static const soc_field_t mtu_pri_field[] = {
   6173         L2_TSN_PRIORITYf, L2_SR_PRIORITYf,
   6174         PORT_PRIORITYf, VFP_PRIORITYf
   6175     };
   6176     static const bcm_tsn_mtu_source_t mtu_src[] = {
   6177         bcmTsnMtuSourceTsnFlow, bcmTsnMtuSourceSrFlow,
   6178         bcmTsnMtuSourcePort, bcmTsnMtuSourceFieldLookup
   6179     };
   6180 
   6181     if (config == NULL) {
   6182         return BCM_E_PARAM;
   6183     }
   6184     /*
   6185      * higher value in the register field means higher priority, and less
   6186      * array index in the source_order means higher priority
   6187      */
   6188 
   6189     config->source_order_count = bcmTsnMtuSourceCount;
   6190     BCM_IF_ERROR_RETURN(READ_MTU_PRIORITYr(unit, &reg_val));
   6191     for (i = 0; i < config->source_order_count; i++) {
   6192         if (SOC_REG_FIELD_VALID(unit, MTU_PRIORITYr, mtu_pri_field[i])) {
   6193             val = soc_reg_field_get(unit, MTU_PRIORITYr,
   6194                                     reg_val, mtu_pri_field[i]);
   6195         } else {
   6196             return BCM_E_INTERNAL;
   6197         }
   6198         if (val < bcmTsnMtuSourceCount) {
   6199             config->source_order[(bcmTsnMtuSourceCount - 1) - val] =
   6200                                                                 mtu_src[i];
   6201         } else {
   6202             return BCM_E_INTERNAL;
   6203         }
   6204     }
   6205     return BCM_E_NONE;
   6206 }
   6207 
   6208 /* Helper function to setup EGR_MTU_CHECKm */
   6209 STATIC int
   6210 bcmi_gh2_tsn_port_control_egress_mtu_set(
   6211     int unit,
   6212     bcm_gport_t gport,
   6213     bcm_tsn_pri_map_config_t *config)
   6214 {
   6215     bcm_port_t port;
   6216     int pri, index, index_base, egr_prof_index;
   6217     bcm_tsn_mtu_profile_type_t type;
   6218     egr_mtu_check_entry_t egr_mtu;
   6219 
   6220     if (config == NULL) {
   6221         return BCM_E_PARAM;
   6222     }
   6223 
   6224     if (config->map_type != bcmTsnPriMapTypeEgressMtuProfile) {
   6225         return BCM_E_PARAM;
   6226     }
   6227     /* Validate and convert gport to local port */
   6228     BCM_IF_ERROR_RETURN(
   6229         _bcm_esw_port_gport_validate(unit, gport, &port));
   6230 
   6231     if (port < 0 || port >= GH2_LOGIC_PORT_MAX_NUM) {
   6232         return BCM_E_PARAM;
   6233     }
   6234 
   6235     index_base = port * EGRESS_MTU_STU_INT_PRI_NUM;
   6236     sal_memset(&egr_mtu, 0, sizeof(egr_mtu));
   6237     for (pri = 0; pri < config->num_map_entries; pri++) {
   6238         index = index_base + pri;
   6239         SOC_IF_ERROR_RETURN(
   6240             soc_mem_read(unit, EGR_MTU_CHECKm, MEM_BLOCK_ANY, index,
   6241                          &egr_mtu));
   6242         BCM_IF_ERROR_RETURN(bcmi_gh2_tsn_mtu_profile_decode(
   6243                                 unit, config->map_entries[pri].profile_id,
   6244                                 &type, &egr_prof_index));
   6245         soc_mem_field32_set(unit, EGR_MTU_CHECKm, &egr_mtu,
   6246                             MTU_PROFILE_INDEXf, egr_prof_index);
   6247         SOC_IF_ERROR_RETURN(
   6248             soc_mem_write(unit, EGR_MTU_CHECKm, MEM_BLOCK_ALL, index,
   6249                           &egr_mtu));
   6250     }
   6251 
   6252     return BCM_E_NONE;
   6253 }
   6254 
   6255 /* Helper function to set PORT_TABm MTU_PROFILE_INDEXf */
   6256 STATIC int
   6257 bcmi_gh2_tsn_port_control_ingress_mtu_set(
   6258     int unit,
   6259     bcm_gport_t gport,
   6260     int index)
   6261 {
   6262     bcm_port_t port;
   6263     sr_port_table_entry_t mtu_profile;
   6264 
   6265     /* Validate and convert gport to local port */
   6266     BCM_IF_ERROR_RETURN(
   6267         _bcm_esw_port_gport_validate(unit, gport, &port));
   6268 
   6269     if (port < 0 || port >= GH2_LOGIC_PORT_MAX_NUM) {
   6270         return BCM_E_PARAM;
   6271     }
   6272     /* check whether index is in the valid range */
   6273     SOC_IF_ERROR_RETURN(
   6274         soc_mem_field32_fit(unit, SR_PORT_TABLEm, MTU_PROFILE_INDEXf, index));
   6275     SOC_IF_ERROR_RETURN(
   6276         soc_mem_read(unit, SR_PORT_TABLEm, MEM_BLOCK_ANY, port,
   6277                      &mtu_profile));
   6278     soc_mem_field32_set(unit, SR_PORT_TABLEm, &mtu_profile,
   6279                         MTU_PROFILE_INDEXf, index);
   6280     SOC_IF_ERROR_RETURN(
   6281         soc_mem_write(unit, SR_PORT_TABLEm, MEM_BLOCK_ALL, port,
   6282                       &mtu_profile));
   6283 
   6284     return BCM_E_NONE;
   6285 }
   6286 
   6287 /* Helper function to get PORT_TABm MTU_PROFILE_INDEXf */
   6288 STATIC int
   6289 bcmi_gh2_tsn_port_control_ingress_mtu_get(
   6290     int unit,
   6291     bcm_gport_t gport,
   6292     int *index)
   6293 {
   6294     bcm_port_t port;
   6295     sr_port_table_entry_t mtu_profile;
   6296 
   6297     /* Validate and convert gport to local port */
   6298     BCM_IF_ERROR_RETURN(
   6299         _bcm_esw_port_gport_validate(unit, gport, &port));
   6300 
   6301     if (port < 0 || port >= GH2_LOGIC_PORT_MAX_NUM || index == NULL) {
   6302         return BCM_E_PARAM;
   6303     }
   6304 
   6305     SOC_IF_ERROR_RETURN(
   6306         soc_mem_read(unit, SR_PORT_TABLEm, MEM_BLOCK_ANY, port,
   6307                      &mtu_profile));
   6308     *index = soc_mem_field32_get(unit, SR_PORT_TABLEm, &mtu_profile,
   6309                                  MTU_PROFILE_INDEXf);
   6310 
   6311     return BCM_E_NONE;
   6312 }
   6313 
   6314 /* Helper function to get the reference count of the profile memory entry */
   6315 STATIC int
   6316 bcmi_gh2_tsn_stu_profmem_refcnt_get(
   6317     int unit,
   6318     bcm_tsn_stu_profile_type_t type,
   6319     int index,
   6320     int *ref_count)
   6321 {
   6322     soc_profile_mem_t *pmem;
   6323 
   6324     if (ref_count == NULL) {
   6325         return BCM_E_PARAM;
   6326     }
   6327     TSN_STU_BKINFO_IS_INIT(unit, type);
   6328     STU_BKINFO_LOCK(unit);
   6329     pmem = TSN_BKINFO(unit)->gh2_stu_bk_info.stu_profile[type];
   6330     STU_BKINFO_UNLOCK(unit);
   6331     BCM_IF_ERROR_RETURN(soc_profile_mem_ref_count_get(unit, pmem,
   6332                                                       index, ref_count));
   6333     return BCM_E_NONE;
   6334 }
   6335 
   6336 /*
   6337  * Function:
   6338  *      bcmi_esw_tsn_stu_profile_decode
   6339  * Purpose:
   6340  *      Decode the profile id into
   6341  *      HW memory index and stu profile type
   6342  * Parameters:
   6343  *      unit - (IN) Unit number
   6344  *      stu_profile_id - (IN) profile id
   6345  *      type - (OUT) Indicates ingress or egress stu profile
   6346  *      index -(OUT) Indicates HW index of the mem
   6347  * Returns:
   6348  *      BCM_E_xxx
   6349  */
   6350 STATIC int
   6351 bcmi_gh2_tsn_stu_profile_decode(
   6352     int unit,
   6353     int stu_profile_id,
   6354     bcm_tsn_stu_profile_type_t *type,
   6355     int *index)
   6356 {
   6357     soc_profile_mem_table_t *table;
   6358 
   6359     if (type == NULL || index == NULL) {
   6360         return BCM_E_PARAM;
   6361     }
   6362     /* If it is an ingress stu profile id */
   6363     if ((stu_profile_id & EGR_MTU_STU_PROFILE_ID_ENCODE) == 0) {
   6364         *type = bcmTsnStuProfileTypeIngress;
   6365         TSN_STU_BKINFO_IS_INIT(unit, *type);
   6366     } else {
   6367         /* If it is an egress stu profile id */
   6368         *type = bcmTsnStuProfileTypeEgress;
   6369         TSN_STU_BKINFO_IS_INIT(unit, *type);
   6370         stu_profile_id &= ~EGR_MTU_STU_PROFILE_ID_ENCODE;
   6371     }
   6372 
   6373     /* Check whether the memory index is valid */
   6374     STU_BKINFO_LOCK(unit);
   6375     table = TSN_BKINFO(unit)->gh2_stu_bk_info.stu_profile[*type]->tables;
   6376     if (stu_profile_id > table->index_max ||
   6377         stu_profile_id < table->index_min) {
   6378         STU_BKINFO_UNLOCK(unit);
   6379         return BCM_E_PARAM;
   6380     }
   6381     STU_BKINFO_UNLOCK(unit);
   6382     *index = stu_profile_id;
   6383 
   6384     return BCM_E_NONE;
   6385 }
   6386 
   6387 #if defined(BCM_TSN_SR_SUPPORT)
   6388 
   6389 /*
   6390  * Function:
   6391  *   bcmi_gh2_tsn_sr_auto_learn_table_size_get
   6392  * Purpose:
   6393  *   Get the table size for auto learn
   6394  * Parameters:
   6395  *   unit - (IN) Unit number
   6396  *   table_size - (OUT) table size
   6397  * Returns:
   6398  *   BCM_E_xxx
   6399  */
   6400 STATIC int
   6401 bcmi_gh2_tsn_sr_auto_learn_table_size_get(
   6402     int unit,
   6403     uint32 *table_size)
   6404 {
   6405     /* Parameter NULL error handling */
   6406     if (NULL == table_size) {
   6407         return BCM_E_PARAM;
   6408     }
   6409 
   6410     /*
   6411       * SR Auto Learn table
   6412       * Since each SR group need 3 ports at least,
   6413       * divide with 3 is a reasonable total flow size
   6414       */
   6415     *table_size = NUM_PORT(unit) / 3;
   6416     return BCM_E_NONE;
   6417 }
   6418 
   6419 /* Per port check if SR is enabled and port role is correct matched. */
   6420 STATIC int
   6421 bcmi_gh2_tsn_sr_auto_learn_group_port_config_check(
   6422     int unit,
   6423     bcmi_tsn_sr_auto_learn_group_port_type_t group_port_type,
   6424     bcm_gport_t gport)
   6425 {
   6426     bcm_tsn_sr_port_config_t org_config;
   6427 
   6428     GH2_TSN_FUNCTION_TRACE(unit, "IN");
   6429 
   6430     LOG_VERBOSE(BSL_LS_BCM_TSN,
   6431                 (BSL_META_U(unit,
   6432                             "%2d "), gport));
   6433 
   6434     if (!soc_feature(unit, soc_feature_tsn_sr) ||
   6435         !soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
   6436         return BCM_E_UNAVAIL;
   6437     }
   6438 
   6439     BCM_IF_ERROR_RETURN(
   6440         bcmi_gh2_tsn_sr_port_config_get(unit, gport, &org_config));
   6441 
   6442     /* Port pre-configuration check */
   6443     if (bcmTsnSrPortTypeNone == org_config.port_type) {
   6444         return BCM_E_CONFIG;
   6445     } else if ((bcmi_sr_auto_learn_group_l2mc == group_port_type) &&
   6446                (org_config.interlink_role != 0)) {
   6447         return BCM_E_CONFIG;
   6448     }
   6449 
   6450     GH2_TSN_FUNCTION_TRACE(unit, "OUT");
   6451     return BCM_E_NONE;
   6452 }
   6453 
   6454 /*
   6455  * Function:
   6456  *   bcmi_gh2_tsn_sr_auto_learn_group_port_set
   6457  * Purpose:
   6458  *   Set value to the ports of given bitmap
   6459  * Parameters:
   6460  *   unit            - (IN) Unit number
   6461  *   group_port_type - (IN) SR Auto Learn Group port type
   6462  *   port_pbmp       - (IN) port bitmap
   6463  *   val             - (IN) value to write
   6464  * Returns:
   6465  *   BCM_E_XXX
   6466  */
   6467 STATIC int
   6468 bcmi_gh2_tsn_sr_auto_learn_group_port_set(
   6469     int unit,
   6470     bcmi_tsn_sr_auto_learn_group_port_type_t group_port_type,
   6471     bcm_pbmp_t port_pbmp,
   6472     int val)
   6473 {
   6474     sr_port_table_entry_t data;
   6475     soc_mem_t mem = INVALIDm;
   6476     soc_field_t port_field = INVALIDf;
   6477     bcm_port_t port;
   6478     bcm_gport_t gport;
   6479     int rv;
   6480     int ptab;
   6481     /* Port tables to write */
   6482     const soc_mem_t mem_list[] = {
   6483         SR_PORT_TABLEm,
   6484         SR_LPORT_TABm
   6485     };
   6486     int mem_idx;
   6487     bcm_module_t my_modid = -1;
   6488     int src_trk_idx = 0; /* Source Trunk table index.*/
   6489     uint32 mem_entry[SOC_MAX_MEM_WORDS];
   6490 
   6491     BCM_IF_ERROR_RETURN(
   6492         bcm_esw_stk_my_modid_get(unit, &my_modid));
   6493 
   6494     GH2_TSN_FUNCTION_TRACE(unit, "IN");
   6495 
   6496     LOG_VERBOSE(BSL_LS_BCM_TSN,
   6497                 (BSL_META_U(unit,
   6498                             "group_port_type %d , val %d\n"),
   6499                             group_port_type, val));
   6500 
   6501     if (!soc_feature(unit, soc_feature_tsn_sr) ||
   6502         !soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
   6503         return BCM_E_UNAVAIL;
   6504     }
   6505 
   6506     if (group_port_type == bcmi_sr_auto_learn_group_l2mc) {
   6507         port_field = L2MCf;
   6508     } else if (group_port_type == bcmi_sr_auto_learn_group_macp) {
   6509         port_field = SR_MAC_PROXY_PROFILE_PTRf;
   6510     } else {
   6511         return BCM_E_PARAM;
   6512     }
   6513 
   6514     for (ptab = 0; ptab < COUNTOF(mem_list); ptab++) {
   6515         mem = mem_list[ptab];
   6516         if (!SOC_MEM_IS_VALID(unit, mem) ||
   6517             !SOC_MEM_FIELD_VALID(unit, mem, port_field)) {
   6518             return BCM_E_INTERNAL;
   6519         }
   6520 
   6521         /* Check if the value fit the target field range */
   6522         BCM_IF_ERROR_RETURN
   6523             (soc_mem_field32_fit(
   6524                 unit, mem, port_field, (uint32)val));
   6525     }
   6526 
   6527     for (ptab = 0; ptab < COUNTOF(mem_list); ptab++) {
   6528         mem = mem_list[ptab];
   6529         PBMP_ITER(port_pbmp, port) {
   6530             LOG_VERBOSE(BSL_LS_BCM_TSN,
   6531                         (BSL_META_U(unit,
   6532                                     "port %2d: "), port));
   6533             /* convert port to gport */
   6534             BCM_IF_ERROR_RETURN(
   6535                 bcm_esw_port_gport_get(unit, port, &gport));
   6536 
   6537             /* Port SR related config check */
   6538             BCM_IF_ERROR_RETURN(
   6539                 bcmi_gh2_tsn_sr_auto_learn_group_port_config_check(
   6540                     unit, group_port_type, gport));
   6541 
   6542             if (mem == SR_LPORT_TABm) {
   6543                 BCM_IF_ERROR_RETURN(
   6544                     _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
   6545                                                           port, &src_trk_idx));
   6546                 BCM_IF_ERROR_RETURN(
   6547                     soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY,
   6548                                  src_trk_idx, mem_entry));
   6549 
   6550                 mem_idx = soc_mem_field32_get(unit, SOURCE_TRUNK_MAP_TABLEm,
   6551                                               mem_entry, LPORT_PROFILE_IDXf);
   6552             } else {
   6553                 mem_idx = port;
   6554             }
   6555             MEM_LOCK(unit, mem);
   6556             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, mem_idx, &data);
   6557             if (BCM_FAILURE(rv)) {
   6558                 LOG_ERROR(BSL_LS_BCM_TSN,
   6559                           (BSL_META_U(unit, "Failed to read mem[%s]"),
   6560                                       SOC_MEM_NAME(unit, mem)));
   6561                 MEM_UNLOCK(unit, mem);
   6562                 return rv;
   6563             }
   6564             soc_mem_field32_set(unit, mem, &data, port_field, (uint32)val);
   6565             rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, mem_idx, &data);
   6566             if (BCM_FAILURE(rv)) {
   6567                 LOG_ERROR(BSL_LS_BCM_TSN,
   6568                           (BSL_META_U(unit, "Failed to write mem[%s]"),
   6569                                       SOC_MEM_NAME(unit, mem)));
   6570                 MEM_UNLOCK(unit, mem);
   6571                 return rv;
   6572             }
   6573             MEM_UNLOCK(unit, mem);
   6574         }
   6575     }
   6576     GH2_TSN_FUNCTION_TRACE(unit, "OUT");
   6577     return BCM_E_NONE;
   6578 }
   6579 
   6580 /*
   6581  * Function:
   6582  *   bcmi_gh2_tsn_sr_auto_learn_group_port_delete
   6583  * Purpose:
   6584  *   Reset the value of the ports of given bitmap
   6585  * Parameters:
   6586  *   unit            - (IN) Unit number
   6587  *   group_port_type - (IN) SR Auto Learn Group port type
   6588  *   port_pbmp       - (IN) port bitmap
   6589  * Returns:
   6590  *   BCM_E_XXX
   6591  */
   6592 STATIC int
   6593 bcmi_gh2_tsn_sr_auto_learn_group_port_delete(
   6594     int unit,
   6595     bcmi_tsn_sr_auto_learn_group_port_type_t group_port_type,
   6596     bcm_pbmp_t port_pbmp)
   6597 {
   6598     bcm_port_t port;
   6599     int val;
   6600 
   6601     GH2_TSN_FUNCTION_TRACE(unit, "IN");
   6602 
   6603     LOG_VERBOSE(BSL_LS_BCM_TSN,
   6604                 (BSL_META_U(unit, "group_port_type %d "), group_port_type));
   6605 
   6606     PBMP_ITER(port_pbmp, port) {
   6607         LOG_VERBOSE(BSL_LS_BCM_TSN,
   6608                     (BSL_META_U(unit, "%2d "), port));
   6609     }
   6610 
   6611     if (!soc_feature(unit, soc_feature_tsn_sr) ||
   6612         !soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
   6613         return BCM_E_UNAVAIL;
   6614     }
   6615 
   6616     val = ((group_port_type == bcmi_sr_auto_learn_group_l2mc) ?
   6617         GH2_SR_AUTO_LEARN_GROUP_PORTS_L2MC_DEFAULT_VALUE :
   6618         GH2_SR_AUTO_LEARN_GROUP_PORTS_MACP_DEFAULT_VALUE);
   6619 
   6620     BCM_IF_ERROR_RETURN(
   6621         bcmi_gh2_tsn_sr_auto_learn_group_port_set(
   6622             unit, group_port_type, port_pbmp,
   6623             val));
   6624     GH2_TSN_FUNCTION_TRACE(unit, "OUT");
   6625     return BCM_E_NONE;
   6626 }
   6627 
   6628 /*
   6629  * Function:
   6630  *   bcmi_gh2_tsn_sr_auto_learn_group_port_reset_all
   6631  * Purpose:
   6632  *   Reset the port value for all ports
   6633  * Parameters:
   6634  *   unit            - (IN) Unit number
   6635  * Returns:
   6636  *   BCM_E_XXX
   6637  */
   6638 STATIC int
   6639 bcmi_gh2_tsn_sr_auto_learn_group_port_reset_all(
   6640     int unit)
   6641 {
   6642     sr_port_table_entry_t data;
   6643     soc_mem_t mem = INVALIDm;
   6644     bcm_port_t port;
   6645     bcm_pbmp_t ports_pbmp;
   6646     int rv;
   6647     int ptab;
   6648     /* Port tables to write */
   6649     const soc_mem_t mem_list[] = {
   6650         SR_PORT_TABLEm,
   6651         SR_LPORT_TABm
   6652     };
   6653     int mem_idx;
   6654     bcm_module_t my_modid = -1;
   6655     int src_trk_idx = 0; /* Source Trunk table index.*/
   6656     uint32 mem_entry[SOC_MAX_MEM_WORDS];
   6657 
   6658     BCM_IF_ERROR_RETURN(
   6659         bcm_esw_stk_my_modid_get(unit, &my_modid));
   6660 
   6661     GH2_TSN_FUNCTION_TRACE(unit, "IN");
   6662 
   6663     if (!soc_feature(unit, soc_feature_tsn_sr) ||
   6664         !soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
   6665         return BCM_E_UNAVAIL;
   6666     }
   6667 
   6668     for (ptab = 0; ptab < COUNTOF(mem_list); ptab++) {
   6669         mem = mem_list[ptab];
   6670         if (!SOC_MEM_IS_VALID(unit, mem) ||
   6671             !SOC_MEM_FIELD_VALID(unit, mem, L2MCf) ||
   6672             !SOC_MEM_FIELD_VALID(unit, mem, SR_MAC_PROXY_PROFILE_PTRf)) {
   6673             return BCM_E_INTERNAL;
   6674         }
   6675     }
   6676 
   6677     BCM_PBMP_ASSIGN(ports_pbmp, PBMP_PORT_ALL(unit));
   6678 
   6679     for (ptab = 0; ptab < COUNTOF(mem_list); ptab++) {
   6680         mem = mem_list[ptab];
   6681         PBMP_ITER(ports_pbmp, port) {
   6682             if (mem == SR_LPORT_TABm) {
   6683                 BCM_IF_ERROR_RETURN(
   6684                     _bcm_esw_src_mod_port_table_index_get(unit, my_modid,
   6685                                                           port, &src_trk_idx));
   6686                 BCM_IF_ERROR_RETURN(
   6687                     soc_mem_read(unit, SOURCE_TRUNK_MAP_TABLEm, MEM_BLOCK_ANY,
   6688                                  src_trk_idx, mem_entry));
   6689 
   6690                 mem_idx = soc_mem_field32_get(unit, SOURCE_TRUNK_MAP_TABLEm,
   6691                                               mem_entry, LPORT_PROFILE_IDXf);
   6692             } else {
   6693                 mem_idx = port;
   6694             }
   6695             MEM_LOCK(unit, mem);
   6696             rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, mem_idx, &data);
   6697             if (BCM_FAILURE(rv)) {
   6698                 LOG_ERROR(BSL_LS_BCM_TSN,
   6699                           (BSL_META_U(unit, "Failed to read mem[%s]"),
   6700                                       SOC_MEM_NAME(unit, mem)));
   6701                 MEM_UNLOCK(unit, mem);
   6702                 return rv;
   6703             }
   6704             soc_mem_field32_set(unit, mem, &data, L2MCf,
   6705                 GH2_SR_AUTO_LEARN_GROUP_PORTS_L2MC_DEFAULT_VALUE);
   6706             soc_mem_field32_set(unit, mem, &data, SR_MAC_PROXY_PROFILE_PTRf,
   6707                 GH2_SR_AUTO_LEARN_GROUP_PORTS_MACP_DEFAULT_VALUE);
   6708 
   6709             rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, mem_idx, &data);
   6710             if (BCM_FAILURE(rv)) {
   6711                 LOG_ERROR(BSL_LS_BCM_TSN,
   6712                           (BSL_META_U(unit, "Failed to write mem[%s]"),
   6713                                       SOC_MEM_NAME(unit, mem)));
   6714                 MEM_UNLOCK(unit, mem);
   6715                 return rv;
   6716             }
   6717             MEM_UNLOCK(unit, mem);
   6718         }
   6719     }
   6720 
   6721     GH2_TSN_FUNCTION_TRACE(unit, "OUT");
   6722     return BCM_E_NONE;
   6723 }
   6724 
   6725 /*
   6726  * Function:
   6727  *   bcmi_gh2_tsn_sr_auto_learn_flow_id_ctrl_set
   6728  * Purpose:
   6729  *   Set flow id control for auto learn subsystem
   6730  * Parameters:
   6731  *   unit        - (IN) Unit number
   6732  *   flow_type   - (IN) SR Auto learn TX/RX flow type
   6733  *   current_fid - (IN) current flow element
   6734  *   last_fid    - (IN) last flow element
   6735  *   id_size     - (IN) total flow elements for auto learn
   6736  * Returns:
   6737  *   BCM_E_XXX
   6738  */
   6739 STATIC int
   6740 bcmi_gh2_tsn_sr_auto_learn_flow_id_ctrl_set(
   6741     int unit,
   6742     bcmi_tsn_sr_auto_learn_flow_t flow_type,
   6743     uint32 current_fid,
   6744     uint32 last_fid,
   6745     uint32 id_size)
   6746 {
   6747     uint64 rval64 = COMPILER_64_INIT(0, 0);
   6748     soc_reg_t sr_flow_id_control_reg;
   6749 
   6750     GH2_TSN_FUNCTION_TRACE(unit, "IN");
   6751     LOG_VERBOSE(BSL_LS_BCM_TSN,
   6752                 (BSL_META_U(unit,
   6753                             "current_fid %d, last_fid %d, id_size %d\n"),
   6754                             current_fid, last_fid, id_size));
   6755 
   6756     if (!soc_feature(unit, soc_feature_tsn_sr) ||
   6757         !soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
   6758         return BCM_E_UNAVAIL;
   6759     }
   6760 
   6761     if (bcmi_sr_auto_learn_flow_tx == flow_type) {
   6762         sr_flow_id_control_reg = SR_TX_FLOW_ID_CONTROLr;
   6763     } else if (bcmi_sr_auto_learn_flow_rx == flow_type) {
   6764         sr_flow_id_control_reg = SR_RX_FLOW_ID_CONTROLr;
   6765     } else {
   6766         return BCM_E_PARAM;
   6767     }
   6768 
   6769     BCM_IF_ERROR_RETURN(
   6770         soc_reg64_get(unit, sr_flow_id_control_reg, REG_PORT_ANY, 0, &rval64));
   6771     soc_reg64_field32_set(
   6772         unit, sr_flow_id_control_reg, &rval64,
   6773         CURRENT_PTRf, current_fid);
   6774     soc_reg64_field32_set(
   6775         unit, sr_flow_id_control_reg, &rval64,
   6776         LAST_PTRf, last_fid);
   6777     soc_reg64_field32_set(unit, sr_flow_id_control_reg, &rval64,
   6778         ID_SIZEf, id_size);
   6779     BCM_IF_ERROR_RETURN(
   6780         soc_reg64_set(unit, sr_flow_id_control_reg, REG_PORT_ANY, 0, rval64));
   6781     GH2_TSN_FUNCTION_TRACE(unit, "OUT");
   6782     return BCM_E_NONE;
   6783 }
   6784 
   6785 /*
   6786  * Function:
   6787  *   bcmi_gh2_tsn_sr_auto_learn_flow_id_pool_get
   6788  * Purpose:
   6789  *   Get flow id pool for auto learn subsystem
   6790  * Parameters:
   6791  *   unit      - (IN) Unit number
   6792  *   flow_type - (IN) SR Auto learn TX/RX flow type
   6793  *   prev_fid  - (IN) previous HW flow ID
   6794  *   fid       - (OUT) HW flow ID
   6795  * Returns:
   6796  *   BCM_E_XXX
   6797  */
   6798 STATIC int
   6799 bcmi_gh2_tsn_sr_auto_learn_flow_id_pool_get(
   6800     int unit,
   6801     bcmi_tsn_sr_auto_learn_flow_t flow_type,
   6802     uint32 prev_fid,
   6803     uint32 *fid)
   6804 {
   6805     soc_mem_t mem = INVALIDm;
   6806     soc_field_t field = NEXT_FLOW_IDf;
   6807     sr_tx_flow_id_pool_entry_t tx_data;
   6808     sr_rx_flow_id_pool_entry_t rx_data;
   6809     void *data;
   6810     uint32 hw_idx;
   6811     int rx_flows, tx_flows;
   6812 
   6813     GH2_TSN_FUNCTION_TRACE(unit, "IN");
   6814     if (!soc_feature(unit, soc_feature_tsn_sr) ||
   6815         !soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
   6816         return BCM_E_UNAVAIL;
   6817     }
   6818 
   6819     /* Parameter validation */
   6820     if (NULL == fid) {
   6821         return BCM_E_PARAM;
   6822     }
   6823 
   6824     /* Get fid from POOL.NEXT_FLOW_ID[prev_fid] */
   6825     hw_idx = (uint32)AUTO_LEARN_FLOW_ID_TO_HW_FLOW_ID(prev_fid);
   6826     if (hw_idx >= soc_mem_index_count(unit, SR_SN_HISTORY_0m)) {
   6827         return BCM_E_PARAM;
   6828     }
   6829 
   6830     BCM_IF_ERROR_RETURN(
   6831         bcmi_gh2_tsn_sr_flows_get_num_flows(unit, &rx_flows, &tx_flows));
   6832 
   6833     if (bcmi_sr_auto_learn_flow_tx == flow_type) {
   6834         mem = SR_TX_FLOW_ID_POOLm;
   6835         sal_memset(&tx_data, 0, sizeof(sr_tx_flow_id_pool_entry_t));
   6836         data = (sr_tx_flow_id_pool_entry_t *)&tx_data;
   6837         if (hw_idx >= tx_flows) {
   6838             return BCM_E_PARAM;
   6839         }
   6840     } else if (bcmi_sr_auto_learn_flow_rx == flow_type) {
   6841         mem = SR_RX_FLOW_ID_POOLm;
   6842         sal_memset(&rx_data, 0, sizeof(sr_tx_flow_id_pool_entry_t));
   6843         data = (sr_rx_flow_id_pool_entry_t *)&rx_data;
   6844         if (hw_idx >= rx_flows) {
   6845             return BCM_E_PARAM;
   6846         }
   6847     } else {
   6848         return BCM_E_PARAM;
   6849     }
   6850 
   6851     if (SOC_MEM_IS_VALID(unit, mem) || SOC_MEM_FIELD_VALID(unit, mem, field)) {
   6852         BCM_IF_ERROR_RETURN(
   6853             soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, data));
   6854         soc_mem_field_get(unit, mem,
   6855                           data, field, fid);
   6856     } else {
   6857         return BCM_E_INTERNAL;
   6858     }
   6859     *fid = (uint32)AUTO_LEARN_HW_FLOW_ID_TO_FLOW_ID(flow_type, *fid);
   6860 
   6861     LOG_VERBOSE(BSL_LS_BCM_TSN,
   6862                 (BSL_META_U(unit,
   6863                             "flow_type %d, prev_fid %d, *fid %d\n"),
   6864                             flow_type, prev_fid, *fid));
   6865     GH2_TSN_FUNCTION_TRACE(unit, "OUT");
   6866     return BCM_E_NONE;
   6867 }
   6868 
   6869 /*
   6870  * Function:
   6871  *   bcmi_gh2_tsn_sr_auto_learn_flow_id_ctrl_get
   6872  * Purpose:
   6873  *   get flow id control for auto learn subsystem
   6874  * Parameters:
   6875  *   unit      - (IN) Unit number
   6876  *   flow_type - (IN) SR Auto learn TX/RX flow type
   6877  *   current   - (OUT) current flow element
   6878  *   last_fid  - (OUT) last flow element
   6879  *   id_size   - (OUT) total flow elements for auto learn
   6880  * Returns:
   6881  *   BCM_E_XXX
   6882  */
   6883 STATIC int
   6884 bcmi_gh2_tsn_sr_auto_learn_flow_id_ctrl_get(
   6885     int unit,
   6886     bcmi_tsn_sr_auto_learn_flow_t flow_type,
   6887     uint32 *current_fid,
   6888     uint32 *last_fid,
   6889     uint32 *id_size)
   6890 {
   6891     uint64 rval64 = COMPILER_64_INIT(0, 0);
   6892     soc_reg_t sr_flow_id_control_reg;
   6893 
   6894     GH2_TSN_FUNCTION_TRACE(unit, "IN");
   6895 
   6896     if (!soc_feature(unit, soc_feature_tsn_sr) ||
   6897         !soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
   6898         return BCM_E_UNAVAIL;
   6899     }
   6900 
   6901     /* Parameter validation */
   6902     if (NULL == current_fid ||
   6903         NULL == last_fid ||
   6904         NULL == id_size) {
   6905         return BCM_E_PARAM;
   6906     }
   6907 
   6908     if (bcmi_sr_auto_learn_flow_tx == flow_type) {
   6909         sr_flow_id_control_reg = SR_TX_FLOW_ID_CONTROLr;
   6910     } else if (bcmi_sr_auto_learn_flow_rx == flow_type) {
   6911         sr_flow_id_control_reg = SR_RX_FLOW_ID_CONTROLr;
   6912     } else {
   6913         return BCM_E_PARAM;
   6914     }
   6915 
   6916     BCM_IF_ERROR_RETURN(
   6917         soc_reg64_get(unit, sr_flow_id_control_reg, REG_PORT_ANY, 0, &rval64));
   6918     *current_fid =
   6919         soc_reg64_field32_get(unit, sr_flow_id_control_reg, rval64,
   6920             CURRENT_PTRf);
   6921     *last_fid =
   6922         soc_reg64_field32_get(unit, sr_flow_id_control_reg, rval64,
   6923             LAST_PTRf);
   6924     *id_size =
   6925         soc_reg64_field32_get(unit, sr_flow_id_control_reg, rval64,
   6926             ID_SIZEf);
   6927 
   6928     LOG_VERBOSE(BSL_LS_BCM_TSN,
   6929                 (BSL_META_U(unit,
   6930                             "*current_fid %d, *last_fid %d, *id_size %d\n"),
   6931                             *current_fid, *last_fid, *id_size));
   6932     GH2_TSN_FUNCTION_TRACE(unit, "OUT");
   6933     return BCM_E_NONE;
   6934 }
   6935 
   6936 /*
   6937  * Function:
   6938  *   bcmi_gh2_tsn_sr_auto_learn_flow_id_pool_set
   6939  * Purpose:
   6940  *   Set flow id pool for auto learn subsystem
   6941  * Parameters:
   6942  *   unit      - (IN) Unit number
   6943  *   flow_type - (IN) SR Auto learn TX/RX flow type
   6944  *   prev_fid  - (IN) previous HW flow ID
   6945  *   fid       - (IN) HW flow ID
   6946  * Returns:
   6947  *   BCM_E_XXX
   6948  */
   6949 STATIC int
   6950 bcmi_gh2_tsn_sr_auto_learn_flow_id_pool_set(
   6951     int unit,
   6952     bcmi_tsn_sr_auto_learn_flow_t flow_type,
   6953     uint32 prev_fid,
   6954     uint32 fid)
   6955 {
   6956     soc_mem_t mem = INVALIDm;
   6957     soc_field_t field = NEXT_FLOW_IDf;
   6958     sr_tx_flow_id_pool_entry_t tx_data;
   6959     sr_rx_flow_id_pool_entry_t rx_data;
   6960     void *data;
   6961     uint32 hw_idx;
   6962     uint32 next_fid;
   6963     int rx_flows, tx_flows;
   6964 
   6965     GH2_TSN_FUNCTION_TRACE(unit, "IN");
   6966     LOG_VERBOSE(BSL_LS_BCM_TSN,
   6967                 (BSL_META_U(unit,
   6968                             "flow_type %d, prev_fid %d, fid %d\n"),
   6969                             flow_type, prev_fid, fid));
   6970 
   6971     if (!soc_feature(unit, soc_feature_tsn_sr) ||
   6972         !soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
   6973         return BCM_E_UNAVAIL;
   6974     }
   6975 
   6976     /* Covert it to next_fflow ID */
   6977     next_fid = (uint32)AUTO_LEARN_FLOW_ID_TO_HW_FLOW_ID(fid);
   6978 
   6979     /* POOL.NEXT_FLOW_ID[prev_fid] = fid; */
   6980     hw_idx = (uint32)AUTO_LEARN_FLOW_ID_TO_HW_FLOW_ID(prev_fid);
   6981 
   6982     BCM_IF_ERROR_RETURN(
   6983         bcmi_gh2_tsn_sr_flows_get_num_flows(unit, &rx_flows, &tx_flows));
   6984 
   6985     if (bcmi_sr_auto_learn_flow_tx == flow_type) {
   6986         mem = SR_TX_FLOW_ID_POOLm;
   6987         sal_memset(&tx_data, 0, sizeof(sr_tx_flow_id_pool_entry_t));
   6988         data = (sr_tx_flow_id_pool_entry_t *)&tx_data;
   6989         if (hw_idx >= tx_flows) {
   6990             return BCM_E_PARAM;
   6991         }
   6992     } else if (bcmi_sr_auto_learn_flow_rx == flow_type) {
   6993         mem = SR_RX_FLOW_ID_POOLm;
   6994         sal_memset(&rx_data, 0, sizeof(sr_tx_flow_id_pool_entry_t));
   6995         data = (sr_rx_flow_id_pool_entry_t *)&rx_data;
   6996         if (hw_idx >= rx_flows) {
   6997             return BCM_E_PARAM;
   6998         }
   6999     } else {
   7000         return BCM_E_PARAM;
   7001     }
   7002 
   7003     if (SOC_MEM_IS_VALID(unit, mem) && SOC_MEM_FIELD_VALID(unit, mem, field)) {
   7004         BCM_IF_ERROR_RETURN(
   7005             soc_mem_read(unit, mem, MEM_BLOCK_ANY, hw_idx, data));
   7006         soc_mem_field32_set(unit, mem, data, field, next_fid);
   7007         BCM_IF_ERROR_RETURN(
   7008             soc_mem_write(unit, mem, MEM_BLOCK_ALL, hw_idx, data));
   7009     } else {
   7010         return BCM_E_INTERNAL;
   7011     }
   7012     GH2_TSN_FUNCTION_TRACE(unit, "OUT");
   7013     return BCM_E_NONE;
   7014 }
   7015 
   7016 /*
   7017  * Function:
   7018  *   bcmi_gh2_tsn_sr_auto_learn_enable
   7019  * Purpose:
   7020  *   Enable/disable SR flow auto learn subsystem
   7021  * Parameters:
   7022  *   unit   - (IN) Unit number
   7023  *   enable - (IN) Enable/disable auto learn
   7024  * Returns:
   7025  *   BCM_E_XXX
   7026  */
   7027 STATIC int
   7028 bcmi_gh2_tsn_sr_auto_learn_enable(
   7029     int unit,
   7030     int enable)
   7031 {
   7032     uint32 rval = 0, val = 0;
   7033 
   7034     GH2_TSN_FUNCTION_TRACE(unit, "IN");
   7035     LOG_VERBOSE(BSL_LS_BCM_TSN,
   7036                 (BSL_META_U(unit,
   7037                             "enable %d\n"), enable));
   7038 
   7039     if (!soc_feature(unit, soc_feature_tsn_sr) ||
   7040         !soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
   7041         return BCM_E_UNAVAIL;
   7042     }
   7043 
   7044     BCM_IF_ERROR_RETURN(READ_HW_MAC_LEARNINGr(unit, &rval));
   7045     if (enable) {
   7046         val = 1;
   7047     } else {
   7048         val = 0;
   7049     }
   7050     soc_reg_field_set(unit,
   7051                       HW_MAC_LEARNINGr,
   7052                       &rval,
   7053                       HW_MAC_LEARNING_ENABLEf,
   7054                       val);
   7055     BCM_IF_ERROR_RETURN(WRITE_HW_MAC_LEARNINGr(unit, rval));
   7056     GH2_TSN_FUNCTION_TRACE(unit, "OUT");
   7057     return BCM_E_NONE;
   7058 }
   7059 
   7060 /*
   7061  * Function:
   7062  *   bcmi_gh2_tsn_sr_auto_learn_enable_get
   7063  * Purpose:
   7064  *   Get enable/disable status of SR flow auto learn subsystem
   7065  * Parameters:
   7066  *   unit    - (IN) Unit number
   7067  *   enabled - (OUT) enable/disable of SR flow auto learn
   7068  * Returns:
   7069  *   BCM_E_XXX
   7070  */
   7071 STATIC int
   7072 bcmi_gh2_tsn_sr_auto_learn_enable_get(
   7073     int unit,
   7074     int *enabled)
   7075 {
   7076     uint32 rval = 0;
   7077 
   7078     GH2_TSN_FUNCTION_TRACE(unit, "IN");
   7079 
   7080     if (!soc_feature(unit, soc_feature_tsn_sr) ||
   7081         !soc_feature(unit, soc_feature_tsn_sr_auto_learn)) {
   7082         return BCM_E_UNAVAIL;
   7083     }
   7084 
   7085     /* Parameter validation */
   7086     if (NULL == enabled) {
   7087         return BCM_E_PARAM;
   7088     }
   7089 
   7090     BCM_IF_ERROR_RETURN(READ_HW_MAC_LEARNINGr(unit, &rval));
   7091     *enabled = soc_reg_field_get(unit,
   7092                                  HW_MAC_LEARNINGr,
   7093                                  rval,
   7094                                  HW_MAC_LEARNING_ENABLEf);
   7095     LOG_VERBOSE(BSL_LS_BCM_TSN,
   7096                 (BSL_META_U(unit,
   7097                             "enabled %d\n"), *enabled));
   7098 
   7099     GH2_TSN_FUNCTION_TRACE(unit, "OUT");
   7100     return BCM_E_NONE;
   7101 }
   7102 #endif /* BCM_TSN_SR_SUPPORT */
   7103 
   7104 /*
   7105  * Function:
   7106  *      bcmi_esw_tsn_stu_profile_encode
   7107  * Purpose:
   7108  *      Encode the HW memory index and type
   7109  *      into profile id
   7110  * Parameters:
   7111  *      unit - (IN) Unit number
   7112  *      index - (IN) HW memory index
   7113  *      type - (IN) Indicates ingress or egress stu profile
   7114  *      stu_profile_id - (OUT) profile id
   7115  * Returns:
   7116  *      BCM_E_xxx
   7117  */
   7118 STATIC int
   7119 bcmi_gh2_tsn_stu_profile_encode(
   7120     int unit,
   7121     int index,
   7122     bcm_tsn_stu_profile_type_t type,
   7123     int *stu_profile_id)
   7124 {
   7125     soc_profile_mem_table_t *table;
   7126 
   7127     /* The validity of the type is checked in the previous layer */
   7128     if (stu_profile_id == NULL) {
   7129         return BCM_E_PARAM;
   7130     }
   7131     if (TSN_BKINFO(unit) != NULL) {
   7132         TSN_STU_BKINFO_IS_INIT(unit, type);
   7133         /* Check whether the memory index is valid */
   7134         STU_BKINFO_LOCK(unit);
   7135         table = TSN_BKINFO(unit)->gh2_stu_bk_info.stu_profile[type]->tables;
   7136         if (index > table->index_max || index < table->index_min) {
   7137             STU_BKINFO_UNLOCK(unit);
   7138             return BCM_E_PARAM;
   7139         }
   7140         STU_BKINFO_UNLOCK(unit);
   7141     }
   7142     if (type == bcmTsnStuProfileTypeIngress) {
   7143         *stu_profile_id = index;
   7144     } else {
   7145         *stu_profile_id = index | EGR_MTU_STU_PROFILE_ID_ENCODE;
   7146     }
   7147 
   7148     return BCM_E_NONE;
   7149 }
   7150 
   7151 
   7152 /*
   7153  * Function:
   7154  *      bcmi_gh2_tsn_stu_profile_traverse
   7155  * Purpose:
   7156  *      Traverse the created match config.
   7157  * Parameters:
   7158  *      unit - (IN) Unit number
   7159  *      cb - (IN) Traverse call back function
   7160  *      user_data - (IN) User data
   7161  * Returns:
   7162  *      BCM_E_xxx
   7163  */
   7164 STATIC int
   7165 bcmi_gh2_tsn_stu_profile_traverse(
   7166     int unit,
   7167     bcm_tsn_stu_profile_traverse_cb cb,
   7168     void *user_data)
   7169 {
   7170     int i, profile_id, rv;
   7171     soc_profile_mem_table_t *table;
   7172     bcm_tsn_stu_profile_type_t type;
   7173 
   7174     if (user_data == NULL || cb == NULL) {
   7175         return BCM_E_PARAM;
   7176     }
   7177 
   7178     /* Traverse on Profile Mem */
   7179     STU_BKINFO_LOCK(unit);
   7180     for (type = bcmTsnStuProfileTypeIngress; type < bcmTsnStuProfileTypeCount;
   7181          type++) {
   7182          TSN_STU_BKINFO_IS_INIT(unit, type);
   7183          table = TSN_BKINFO(unit)->gh2_stu_bk_info.stu_profile[type]->tables;
   7184 
   7185          for (i = table->index_min; i <= table->index_max; i++) {
   7186             bcmi_gh2_tsn_stu_profile_encode(unit, i, type, &profile_id);
   7187             /* profile id 0 is the default value, won't traverse it */
   7188             if (table->entries[i].ref_count > 0 && i != 0) {
   7189                 rv = cb(unit, profile_id, user_data);
   7190                 if (BCM_FAILURE(rv)) {
   7191                     STU_BKINFO_UNLOCK(unit);
   7192                     return rv;
   7193                 }
   7194             }
   7195         }
   7196     }
   7197     STU_BKINFO_UNLOCK(unit);
   7198 
   7199     return BCM_E_NONE;
   7200 }
   7201 
   7202 /* helper function to get the profile memory index */
   7203 STATIC int
   7204 bcmi_gh2_tsn_stu_profile_mem_idx_get(
   7205     int unit,
   7206     bcm_tsn_stu_profile_type_t type,
   7207     int *min,
   7208     int *max)
   7209 {
   7210     if (min == NULL || max == NULL) {
   7211         return BCM_E_PARAM;
   7212     }
   7213     if (type != bcmTsnStuProfileTypeIngress &&
   7214         type != bcmTsnStuProfileTypeEgress) {
   7215         return BCM_E_PARAM;
   7216     }
   7217     *min = soc_mem_index_min(unit, gh2_stu_profile_mem[type]);
   7218     *max = soc_mem_index_max(unit, gh2_stu_profile_mem[type]);
   7219 
   7220     return BCM_E_NONE;
   7221 }
   7222 
   7223 /*
   7224  * Function:
   7225  *      bcmi_gh2_tsn_stu_profile_mem_init
   7226  * Purpose:
   7227  *      Initiate stu profile mem management structure
   7228  *      and set STU_PROFILEm entries to zero.
   7229  * Parameters:
   7230  *      unit - (IN) Unit number
   7231  *      type - (IN) Indicates ingress or egress stu profile
   7232  * Returns:
   7233  *      BCM_E_xxx
   7234  */
   7235 STATIC int
   7236 bcmi_gh2_tsn_stu_profile_mem_init(
   7237     int unit,
   7238     bcm_tsn_stu_profile_type_t type)
   7239 {
   7240     soc_mem_t mem;
   7241     soc_mem_t mems[1];
   7242     int mem_words[1];
   7243     soc_profile_mem_t *pmem;
   7244     int rv;
   7245 
   7246     TSN_STU_BKINFO_IS_INIT(unit, type);
   7247 
   7248     /* Set ingress STU profile memory HW table entries to zero */
   7249 #if defined(BCM_WARM_BOOT_SUPPORT)
   7250     if (!SOC_WARM_BOOT(unit))
   7251 #endif /* BCM_WARM_BOOT_SUPPORT */
   7252     {
   7253         SOC_IF_ERROR_RETURN
   7254             (soc_mem_clear(unit, gh2_stu_profile_mem[type], MEM_BLOCK_ALL, 0));
   7255     }
   7256     STU_BKINFO_LOCK(unit);
   7257     pmem = TSN_BKINFO(unit)->gh2_stu_bk_info.stu_profile[type];
   7258     soc_profile_mem_t_init(pmem);
   7259     mem = gh2_stu_profile_mem[type];
   7260     if (SOC_MEM_IS_VALID(unit, mem)) {
   7261         mems[0] = mem;
   7262         if (type == bcmTsnStuProfileTypeIngress) {
   7263             mem_words[0] = BYTES2WORDS(sizeof(stu_profile_entry_t));
   7264         } else {
   7265             mem_words[0] = BYTES2WORDS(sizeof(egr_stu_profile_entry_t));
   7266         }
   7267     } else {
   7268         STU_BKINFO_UNLOCK(unit);
   7269         return BCM_E_INTERNAL;
   7270     }
   7271     rv = soc_profile_mem_create(unit, mems, mem_words, 1, pmem);
   7272 
   7273     STU_BKINFO_UNLOCK(unit);
   7274     return rv;
   7275 }
   7276 
   7277 /*
   7278  * Function:
   7279  *      bcmi_gh2_tsn_stu_profile_create
   7280  * Purpose:
   7281  *      Create stu profile with the config pointer
   7282  *      and return the assigned profile id.
   7283  * Parameters:
   7284  *      unit - (IN) Unit number
   7285  *      type - (IN) Indicates ingress or egress stu profile
   7286  *      config - (IN) configuration of the stu profile
   7287  *      index - (OUT) HW index of ingress stu profile
   7288  * Returns:
   7289  *      BCM_E_xxx
   7290  */
   7291 STATIC int
   7292 bcmi_gh2_tsn_stu_profile_create(
   7293     int unit,
   7294     bcm_tsn_stu_profile_type_t type,
   7295     bcm_tsn_stu_config_t *config,
   7296     uint32 *index)
   7297 {
   7298     void *entries[1];
   7299     soc_profile_mem_t *pmem;
   7300     void *entry;
   7301     stu_profile_entry_t entry_i;
   7302     egr_stu_profile_entry_t entry_e;
   7303     int rv;
   7304 
   7305     if (index == NULL || config == NULL) {
   7306         return BCM_E_PARAM;
   7307     }
   7308     TSN_STU_BKINFO_IS_INIT(unit, type);
   7309 
   7310     if (type == bcmTsnStuProfileTypeIngress) {
   7311         entry = &entry_i;
   7312     } else {
   7313         entry = &entry_e;
   7314     }
   7315 
   7316     SOC_IF_ERROR_RETURN
   7317         (soc_mem_field32_fit(unit, gh2_stu_profile_mem[type],
   7318                              STU_SIZEf, config->size));
   7319     SOC_IF_ERROR_RETURN
   7320         (soc_mem_field32_fit(unit, gh2_stu_profile_mem[type],
   7321                              STU_ERROR_ACTIONf, config->drop));
   7322     soc_mem_field32_set(unit, gh2_stu_profile_mem[type], (uint32 *)entry,
   7323                         STU_SIZEf, config->size);
   7324     soc_mem_field32_set(unit, gh2_stu_profile_mem[type], (uint32 *)entry,
   7325                         STU_ERROR_ACTIONf, config->drop);
   7326     STU_BKINFO_LOCK(unit);
   7327     pmem = TSN_BKINFO(unit)->gh2_stu_bk_info.stu_profile[type];
   7328     entries[0] = entry;
   7329     rv = soc_profile_mem_add(unit, pmem, entries, 1, index);
   7330     STU_BKINFO_UNLOCK(unit);
   7331 
   7332     return rv;
   7333 }
   7334 
   7335 /*
   7336  * Function:
   7337  *      bcmi_gh2_tsn_stu_profile_get
   7338  * Purpose:
   7339  *      Get stu profile configuration
   7340  *      with the profile id.
   7341  * Parameters:
   7342  *      unit - (IN) Unit number
   7343  *      index - (IN) HW index of ingress stu profile
   7344  *      type - (IN) Indicates ingress or egress stu profile
   7345  *      config - (OUT) configuration of the stu profile
   7346  * Returns:
   7347  *      BCM_E_xxx
   7348  */
   7349 STATIC int
   7350 bcmi_gh2_tsn_stu_profile_get(
   7351     int unit,
   7352     int index,
   7353     bcm_tsn_stu_profile_type_t type,
   7354     bcm_tsn_stu_config_t *config)
   7355 {
   7356     void *entries[1];
   7357     soc_profile_mem_t *pmem;
   7358     void *entry;
   7359     stu_profile_entry_t entry_i;
   7360     egr_stu_profile_entry_t entry_e;
   7361 
   7362     if (config == NULL) {
   7363         return BCM_E_PARAM;
   7364     }
   7365     TSN_STU_BKINFO_IS_INIT(unit, type);
   7366 
   7367     if (type == bcmTsnStuProfileTypeIngress) {
   7368         entry = &entry_i;
   7369     } else {
   7370         entry = &entry_e;
   7371     }
   7372     STU_BKINFO_LOCK(unit);
   7373     pmem = TSN_BKINFO(unit)->gh2_stu_bk_info.stu_profile[type];
   7374     entries[0] = entry;
   7375     BCM_IF_ERROR_RETURN(soc_profile_mem_get(unit, pmem, index, 1, entries));
   7376     if (SOC_MEM_FIELD_VALID(unit, gh2_stu_profile_mem[type], STU_SIZEf) &&
   7377         SOC_MEM_FIELD_VALID(unit, gh2_stu_profile_mem[type],
   7378                             STU_ERROR_ACTIONf)) {
   7379         config->size =
   7380             soc_mem_field32_get(unit, gh2_stu_profile_mem[type],
   7381                                 (uint32 *)entry, STU_SIZEf);
   7382         config->drop =
   7383             soc_mem_field32_get(unit, gh2_stu_profile_mem[type],
   7384                                 (uint32 *)entry, STU_ERROR_ACTIONf);
   7385     } else {
   7386         STU_BKINFO_UNLOCK(unit);
   7387         return BCM_E_INTERNAL;
   7388     }
   7389     STU_BKINFO_UNLOCK(unit);
   7390     return BCM_E_NONE;
   7391 }
   7392 
   7393 /*
   7394  * Function:
   7395  *      bcmi_gh2_tsn_ingress_stu_profile_set
   7396  * Purpose:
   7397  *      Set stu profile with the profile id
   7398  *      and config parameter.
   7399  * Parameters:
   7400  *      unit - (IN) Unit number
   7401  *      index - (IN) HW index of ingress stu profile
   7402  *      type - (IN) Indicates ingress or egress stu profile
   7403  *      config - (IN) configuration of the stu profile
   7404  * Returns:
   7405  *      BCM_E_xxx
   7406  */
   7407 STATIC int
   7408 bcmi_gh2_tsn_stu_profile_set(
   7409     int unit,
   7410     int index,
   7411     bcm_tsn_stu_profile_type_t type,
   7412     bcm_tsn_stu_config_t *config)
   7413 {
   7414     int idx, profile_idx, rv;
   7415     void *entries[1];
   7416     bcm_tsn_stu_config_t config_repl;
   7417     soc_profile_mem_table_t *table;
   7418     soc_profile_mem_t *pmem;
   7419     void *entry;
   7420     stu_profile_entry_t entry_i;
   7421     egr_stu_profile_entry_t entry_e;
   7422 
   7423     if (config == NULL) {
   7424         return BCM_E_PARAM;
   7425     }
   7426     TSN_STU_BKINFO_IS_INIT(unit, type);
   7427 
   7428     /*
   7429     * Search for whether replicated profile mem config exist,
   7430     * if existed return BCM_E_UNAVAIL
   7431     */
   7432     bcm_tsn_stu_config_t_init(&config_repl);
   7433     STU_BKINFO_LOCK(unit);
   7434     table = TSN_BKINFO(unit)->gh2_stu_bk_info.stu_profile[type]->tables;
   7435     for (idx = table->index_min; idx <= table->index_max; idx++) {
   7436         bcmi_gh2_tsn_stu_profile_encode(unit, idx, type, &profile_idx);
   7437         bcmi_gh2_tsn_stu_profile_get(unit, idx, type, &config_repl);
   7438         if ((config_repl.size == config->size) &&
   7439             (config_repl.drop == config->drop)) {
   7440             LOG_WARN(BSL_LS_BCMAPI_TSN,
   7441                     (BSL_META_U(unit,
   7442                                 "config already existed, found"
   7443                                 " stu profile id(%d)\n"), profile_idx));
   7444             STU_BKINFO_UNLOCK(unit);
   7445             return BCM_E_EXISTS;
   7446         }
   7447     }
   7448     STU_BKINFO_UNLOCK(unit);
   7449 
   7450     SOC_IF_ERROR_RETURN
   7451         (soc_mem_field32_fit(unit, gh2_stu_profile_mem[type],
   7452                              STU_SIZEf, config->size));
   7453     SOC_IF_ERROR_RETURN
   7454         (soc_mem_field32_fit(unit, gh2_stu_profile_mem[type], STU_ERROR_ACTIONf,
   7455                              config->drop));
   7456 
   7457     if (type == bcmTsnStuProfileTypeIngress) {
   7458         entry = &entry_i;
   7459     } else {
   7460         entry = &entry_e;
   7461     }
   7462 
   7463     if (SOC_MEM_FIELD_VALID(unit, gh2_stu_profile_mem[type], STU_SIZEf) &&
   7464         SOC_MEM_FIELD_VALID(unit, gh2_stu_profile_mem[type],
   7465                             STU_ERROR_ACTIONf)) {
   7466         soc_mem_field32_set(unit, gh2_stu_profile_mem[type],
   7467                             entry, STU_SIZEf, config->size);
   7468         soc_mem_field32_set(unit, gh2_stu_profile_mem[type], entry,
   7469                             STU_ERROR_ACTIONf, config->drop);
   7470     } else {
   7471         return BCM_E_INTERNAL;
   7472     }
   7473     STU_BKINFO_LOCK(unit);
   7474     pmem = TSN_BKINFO(unit)->gh2_stu_bk_info.stu_profile[type];
   7475     entries[0] = entry;
   7476     rv = soc_profile_mem_set(unit, pmem, entries, index);
   7477     STU_BKINFO_UNLOCK(unit);
   7478 
   7479     return rv;
   7480 }
   7481 
   7482 /*
   7483  * Function:
   7484  *      bcmi_gh2_tsn_stu_profile_destroy
   7485  * Purpose:
   7486  *      Clear the stu profile with the profile id
   7487  * Parameters:
   7488  *      unit - (IN) Unit number
   7489  *      type - (IN) Indicates ingress or egress stu profile
   7490  *      index - (IN) Indicated the ingress stu profile entry
   7491  * Returns:
   7492  *      BCM_E_xxx
   7493  */
   7494 STATIC int
   7495 bcmi_gh2_tsn_stu_profile_destroy(
   7496     int unit,
   7497     bcm_tsn_stu_profile_type_t type,
   7498     int index)
   7499 {
   7500     uint32 buf;
   7501     soc_profile_mem_t *pmem;
   7502     void *entry;
   7503     stu_profile_entry_t entry_i;
   7504     egr_stu_profile_entry_t entry_e;
   7505     int rv;
   7506 
   7507     TSN_STU_BKINFO_IS_INIT(unit, type);
   7508     if (type == bcmTsnStuProfileTypeIngress) {
   7509         entry = &entry_i;
   7510     } else {
   7511         entry = &entry_e;
   7512     }
   7513     STU_BKINFO_LOCK(unit);
   7514     pmem = TSN_BKINFO(unit)->gh2_stu_bk_info.stu_profile[type];
   7515     rv = soc_profile_mem_delete(unit, pmem, index);
   7516     STU_BKINFO_UNLOCK(unit);
   7517     BCM_IF_ERROR_RETURN(rv);
   7518 
   7519     /* clear the HW table to zero */
   7520     buf = 0x00000000;
   7521     SOC_IF_ERROR_RETURN(soc_mem_read(unit, gh2_stu_profile_mem[type],
   7522                                      MEM_BLOCK_ANY, index, entry));
   7523     soc_mem_field_set(unit, gh2_stu_profile_mem[type],
   7524                       (uint32 *)entry, STU_SIZEf, &buf);
   7525     soc_mem_field_set(unit, gh2_stu_profile_mem[type], (uint32 *)entry,
   7526                       STU_ERROR_ACTIONf, &buf);
   7527     SOC_IF_ERROR_RETURN(
   7528         soc_mem_write(unit, gh2_stu_profile_mem[type], MEM_BLOCK_ALL,
   7529                       index, entry));
   7530 
   7531     return BCM_E_NONE;
   7532 }
   7533 
   7534 /*
   7535  * Function:
   7536  *      bcmi_gh2_tsn_ingress_stu_config_set
   7537  * Purpose:
   7538  *      Set the priority of source ingress
   7539  *      stu profile index.
   7540  * Parameters:
   7541  *      unit - (IN) Unit number
   7542  *      config - (IN) Configuration of the stu profile priority
   7543  * Returns:
   7544  *      BCM_E_xxx
   7545  */
   7546 STATIC int
   7547 bcmi_gh2_tsn_ingress_stu_config_set(
   7548     int unit,
   7549     bcm_tsn_ingress_stu_config_t *config)
   7550 {
   7551     uint32 i, reg_val, val;
   7552     int user_valid[bcmTsnStuSourceCount];
   7553 
   7554     if (config == NULL) {
   7555         return BCM_E_PARAM;
   7556     }
   7557     /* source_order_count is mandatory to set as bcmTsnStuSourceCount */
   7558     if (config->source_order_count != bcmTsnStuSourceCount) {
   7559         return BCM_E_PARAM;
   7560     }
   7561     for (i = 0; i < config->source_order_count; i++) {
   7562         user_valid[i] = 0;
   7563     }
   7564     /* Check the user config is correct */
   7565     for (i = 0; i < config->source_order_count; i++) {
   7566         switch (config->source_order[i]) {
   7567             case bcmTsnStuSourceFieldLookup:
   7568                 user_valid[bcmTsnStuSourceFieldLookup]++;
   7569                 break;
   7570             case bcmTsnStuSourcePort:
   7571                 user_valid[bcmTsnStuSourcePort]++;
   7572                 break;
   7573             default:
   7574                 return BCM_E_PARAM;
   7575         }
   7576     }
   7577     for (i = 0; i < config->source_order_count; i++) {
   7578         if (user_valid[i] != 1) {
   7579             return BCM_E_PARAM;
   7580         }
   7581     }
   7582     /*
   7583      * higher value in the register field means higher priority, and less
   7584      * array index in the source_order means higher priority
   7585      */
   7586     BCM_IF_ERROR_RETURN(READ_STU_PRIORITYr(unit, &reg_val));
   7587     for (i = 0; i < config->source_order_count; i++) {
   7588         val = bcmTsnStuSourceCount - 1 - i;
   7589         switch (config->source_order[i]) {
   7590             case bcmTsnStuSourceFieldLookup:
   7591                 soc_reg_field_set(unit, STU_PRIORITYr, &reg_val,
   7592                                   VFP_PRIORITYf, val);
   7593                 break;
   7594             case bcmTsnStuSourcePort:
   7595                 soc_reg_field_set(unit, STU_PRIORITYr, &reg_val,
   7596                                   PORT_PRIORITYf, val);
   7597                 break;
   7598             default:
   7599                 return BCM_E_PARAM;
   7600         }
   7601     }
   7602     BCM_IF_ERROR_RETURN(WRITE_STU_PRIORITYr(unit, reg_val));
   7603 
   7604     return BCM_E_NONE;
   7605 }
   7606 
   7607 /*
   7608  * Function:
   7609  *      bcmi_gh2_tsn_ingress_stu_config_get
   7610  * Purpose:
   7611  *      Get the priority of source ingress
   7612  *      stu profile index.
   7613  * Parameters:
   7614  *      unit - (IN) Unit number
   7615  *      config - (OUT) Configuration of the stu profile priority
   7616  * Returns:
   7617  *      BCM_E_xxx
   7618  */
   7619 STATIC int
   7620 bcmi_gh2_tsn_ingress_stu_config_get(
   7621     int unit,
   7622     bcm_tsn_ingress_stu_config_t *config)
   7623 {
   7624     int i;
   7625     uint32 reg_val, val;
   7626     static const soc_field_t stu_pri_field[] = {
   7627         VFP_PRIORITYf, PORT_PRIORITYf
   7628     };
   7629     static const bcm_tsn_stu_source_t stu_src[] = {
   7630         bcmTsnStuSourceFieldLookup, bcmTsnStuSourcePort
   7631     };
   7632 
   7633     if (config == NULL) {
   7634         return BCM_E_PARAM;
   7635     }
   7636     /*
   7637      * higher value in the register field means higher priority, and less
   7638      * array index in the source_order means higher priority
   7639      */
   7640     config->source_order_count = bcmTsnStuSourceCount;
   7641     BCM_IF_ERROR_RETURN(READ_STU_PRIORITYr(unit, &reg_val));
   7642     for (i = 0; i < config->source_order_count; i++) {
   7643         if (SOC_REG_FIELD_VALID(unit, STU_PRIORITYr, stu_pri_field[i])) {
   7644             val = soc_reg_field_get(unit, STU_PRIORITYr,
   7645                                     reg_val, stu_pri_field[i]);
   7646         } else {
   7647             return BCM_E_INTERNAL;
   7648         }
   7649         if (val < bcmTsnStuSourceCount) {
   7650             config->source_order[(bcmTsnStuSourceCount - 1) - val] =
   7651                                                                 stu_src[i];
   7652         } else {
   7653             return BCM_E_INTERNAL;
   7654         }
   7655     }
   7656     return BCM_E_NONE;
   7657 }
   7658 
   7659 /* Helper function to setup EGR_STU_CHECKm */
   7660 STATIC int
   7661 bcmi_gh2_tsn_port_control_egress_stu_set(
   7662     int unit,
   7663     bcm_gport_t gport,
   7664     bcm_tsn_pri_map_config_t *config)
   7665 {
   7666     bcm_port_t port;
   7667     int pri, index, index_base, egr_prof_index;
   7668     bcm_tsn_stu_profile_type_t type;
   7669     egr_stu_check_entry_t egr_stu;
   7670 
   7671     if (config == NULL) {
   7672         return BCM_E_PARAM;
   7673     }
   7674 
   7675     if (config->map_type != bcmTsnPriMapTypeEgressStuProfile) {
   7676         return BCM_E_PARAM;
   7677     }
   7678 
   7679     /* Validate and convert gport to local port */
   7680     BCM_IF_ERROR_RETURN(
   7681         _bcm_esw_port_gport_validate(unit, gport, &port));
   7682 
   7683     if (port < 0 || port >= GH2_LOGIC_PORT_MAX_NUM) {
   7684         return BCM_E_PARAM;
   7685     }
   7686 
   7687     index_base = port * EGRESS_MTU_STU_INT_PRI_NUM;
   7688     sal_memset(&egr_stu, 0, sizeof(egr_stu));
   7689     for (pri = 0; pri < config->num_map_entries; pri++) {
   7690         index = index_base + pri;
   7691         SOC_IF_ERROR_RETURN(
   7692             soc_mem_read(unit, EGR_STU_CHECKm, MEM_BLOCK_ANY, index,
   7693                          &egr_stu));
   7694         BCM_IF_ERROR_RETURN(bcmi_gh2_tsn_stu_profile_decode(
   7695                                 unit, config->map_entries[pri].profile_id,
   7696                                 &type, &egr_prof_index));
   7697         soc_mem_field32_set(unit, EGR_STU_CHECKm, &egr_stu,
   7698                             STU_PROFILE_INDEXf, egr_prof_index);
   7699         SOC_IF_ERROR_RETURN(
   7700             soc_mem_write(unit, EGR_STU_CHECKm, MEM_BLOCK_ALL, index,
   7701                           &egr_stu));
   7702     }
   7703 
   7704     return BCM_E_NONE;
   7705 }
   7706 
   7707 /* Helper function to set PORT_TABm STU_PROFILE_INDEXf */
   7708 STATIC int
   7709 bcmi_gh2_tsn_port_control_ingress_stu_set(
   7710     int unit,
   7711     bcm_gport_t gport,
   7712     int index)
   7713 {
   7714     bcm_port_t port;
   7715     sr_port_table_entry_t stu_profile;
   7716 
   7717     /* Validate and convert gport to local port */
   7718     BCM_IF_ERROR_RETURN(
   7719         _bcm_esw_port_gport_validate(unit, gport, &port));
   7720 
   7721     if (port < 0 || port >= GH2_LOGIC_PORT_MAX_NUM) {
   7722         return BCM_E_PARAM;
   7723     }
   7724     /* check whether index is in the valid range */
   7725     SOC_IF_ERROR_RETURN(
   7726         soc_mem_field32_fit(unit, SR_PORT_TABLEm, STU_PROFILE_INDEXf, index));
   7727     SOC_IF_ERROR_RETURN(
   7728         soc_mem_read(unit, SR_PORT_TABLEm, MEM_BLOCK_ANY, port,
   7729                      &stu_profile));
   7730     soc_mem_field32_set(unit, SR_PORT_TABLEm, &stu_profile,
   7731                         STU_PROFILE_INDEXf, index);
   7732     SOC_IF_ERROR_RETURN(
   7733         soc_mem_write(unit, SR_PORT_TABLEm, MEM_BLOCK_ALL, port,
   7734                       &stu_profile));
   7735 
   7736     return BCM_E_NONE;
   7737 }
   7738 
   7739 /* Helper function to get PORT_TABm STU_PROFILE_INDEXf */
   7740 STATIC int
   7741 bcmi_gh2_tsn_port_control_ingress_stu_get(
   7742     int unit,
   7743     bcm_gport_t gport,
   7744     int *index)
   7745 {
   7746     bcm_port_t port;
   7747     sr_port_table_entry_t stu_profile;
   7748 
   7749     /* Validate and convert gport to local port */
   7750     BCM_IF_ERROR_RETURN(
   7751         _bcm_esw_port_gport_validate(unit, gport, &port));
   7752 
   7753     if (port < 0 || port >= GH2_LOGIC_PORT_MAX_NUM || index == NULL) {
   7754         return BCM_E_PARAM;
   7755     }
   7756 
   7757     SOC_IF_ERROR_RETURN(
   7758         soc_mem_read(unit, SR_PORT_TABLEm, MEM_BLOCK_ANY, port,
   7759                      &stu_profile));
   7760     *index = soc_mem_field32_get(unit, SR_PORT_TABLEm, &stu_profile,
   7761                                  STU_PROFILE_INDEXf);
   7762 
   7763     return BCM_E_NONE;
   7764 }
   7765 
   7766 /* Free and clear the  MTU bookkeeping info structure */
   7767 STATIC int
   7768 bcmi_gh2_tsn_mtu_cleanup(int unit)
   7769 {
   7770     bcm_tsn_mtu_profile_type_t type;
   7771 
   7772     TSN_BKINFO_IS_INIT(unit);
   7773     for (type = bcmTsnMtuProfileTypeIngress; type < bcmTsnMtuProfileTypeCount;
   7774          type++) {
   7775         if (gh2_tsn_bkinfo[unit]->gh2_mtu_bk_info.mtu_profile[type] != NULL) {
   7776             soc_profile_mem_destroy(
   7777                 unit, gh2_tsn_bkinfo[unit]->gh2_mtu_bk_info.mtu_profile[type]);
   7778             TSN_FREE(unit,
   7779                     gh2_tsn_bkinfo[unit]->gh2_mtu_bk_info.mtu_profile[type],
   7780                     0);
   7781             gh2_tsn_bkinfo[unit]->gh2_mtu_bk_info.mtu_profile[type] = NULL;
   7782         }
   7783     }
   7784     if (gh2_tsn_bkinfo[unit]->gh2_mtu_bk_info.mutex != NULL) {
   7785         sal_mutex_destroy(gh2_tsn_bkinfo[unit]->gh2_mtu_bk_info.mutex);
   7786         gh2_tsn_bkinfo[unit]->gh2_mtu_bk_info.mutex = NULL;
   7787     }
   7788 
   7789     return BCM_E_NONE;
   7790 }
   7791 
   7792 /* Allocate MTU bookkeeping info resource */
   7793 STATIC int
   7794 bcmi_gh2_tsn_mtu_init(int unit)
   7795 {
   7796     bcm_tsn_mtu_profile_type_t type;
   7797     bcm_tsn_mtu_config_t config;
   7798     uint32 idx;
   7799     int rv;
   7800 #if defined(BCM_WARM_BOOT_SUPPORT)
   7801     int min, max, i;
   7802     void *entry;
   7803     mtu_profile_entry_t entry_i;
   7804     egr_mtu_profile_entry_t entry_e;
   7805     uint32 buff;
   7806     soc_mem_t mem;
   7807     soc_profile_mem_t *pmem;
   7808 #endif /* BCM_WARM_BOOT_SUPPORT */
   7809 
   7810     /*
   7811      * The mtu config is not used, but to occupy profile memory id 0 as invalid
   7812      */
   7813     config.size = 0;
   7814     config.drop = 0;
   7815 
   7816     /* Create MTU mutex */
   7817     gh2_tsn_bkinfo[unit]->gh2_mtu_bk_info.mutex =
   7818         sal_mutex_create("mtu_mutex");
   7819     if (gh2_tsn_bkinfo[unit]->gh2_mtu_bk_info.mutex == NULL) {
   7820         bcmi_gh2_tsn_mtu_cleanup(unit);
   7821         return BCM_E_MEMORY;
   7822     }
   7823 
   7824     for (type = bcmTsnMtuProfileTypeIngress; type < bcmTsnMtuProfileTypeCount;
   7825          type++) {
   7826         TSN_ALLOC(
   7827             unit, gh2_tsn_bkinfo[unit]->gh2_mtu_bk_info.mtu_profile[type],
   7828             soc_profile_mem_t, sizeof(soc_profile_mem_t),
   7829             "GH2 TSN MTU Ingress bookkeeping info", 0, rv);
   7830         if (BCM_FAILURE(rv)) {
   7831             bcmi_gh2_tsn_mtu_cleanup(unit);
   7832             return rv;
   7833         }
   7834 
   7835         /* Initialize and Create ingress mtu profile memory */
   7836         rv = bcmi_gh2_tsn_mtu_profile_mem_init(unit, type);
   7837         if (BCM_FAILURE(rv)) {
   7838             bcmi_gh2_tsn_mtu_cleanup(unit);
   7839             return rv;
   7840         }
   7841         /* Profile memory id 0 as default/invalid */
   7842         rv = bcmi_gh2_tsn_mtu_profile_create(unit, type, &config, &idx);
   7843         if (BCM_FAILURE(rv) || idx != 0) {
   7844             bcmi_gh2_tsn_mtu_cleanup(unit);
   7845             return rv;
   7846         }
   7847 #if defined(BCM_WARM_BOOT_SUPPORT)
   7848         if (SOC_WARM_BOOT(unit)) {
   7849             pmem = TSN_BKINFO(unit)->gh2_mtu_bk_info.mtu_profile[type];
   7850             mem = gh2_mtu_profile_mem[type];
   7851 
   7852             if (type == bcmTsnMtuProfileTypeIngress) {
   7853                 entry = &entry_i;
   7854             } else {
   7855                 entry = &entry_e;
   7856             }
   7857             MTU_BKINFO_LOCK(unit);
   7858             rv = bcmi_gh2_tsn_mtu_profile_mem_idx_get(unit, type, &min, &max);
   7859             if (BCM_FAILURE(rv)) {
   7860                 MTU_BKINFO_UNLOCK(unit);
   7861                 return rv;
   7862             }
   7863             /* Recovering SW soc_profile_mem management */
   7864             for (i = min; i <= max; i++) {
   7865                 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, i, entry);
   7866                 if (SOC_FAILURE(rv)) {
   7867                     MTU_BKINFO_UNLOCK(unit);
   7868                     return rv;
   7869                 }
   7870                 soc_mem_field_get(unit, mem, (uint32 *)entry, MTU_SIZEf, &buff);
   7871                 if (buff > 0) {
   7872                     rv = soc_profile_mem_reference(unit, pmem, i, 1);
   7873                     if (SOC_FAILURE(rv)) {
   7874                         MTU_BKINFO_UNLOCK(unit);
   7875                         return rv;
   7876                     }
   7877                 }
   7878             }
   7879             MTU_BKINFO_UNLOCK(unit);
   7880         }
   7881 #endif /* BCM_WARM_BOOT_SUPPORT */
   7882     }
   7883      return BCM_E_NONE;
   7884 }
   7885 
   7886 /* Free and clear the  STU bookkeeping info structure */
   7887 STATIC int
   7888 bcmi_gh2_tsn_stu_cleanup(int unit)
   7889 {
   7890     bcm_tsn_stu_profile_type_t type;
   7891 
   7892     TSN_BKINFO_IS_INIT(unit);
   7893     for (type = bcmTsnStuProfileTypeIngress; type < bcmTsnStuProfileTypeCount;
   7894          type++) {
   7895         if (gh2_tsn_bkinfo[unit]->gh2_stu_bk_info.stu_profile[type] != NULL) {
   7896             soc_profile_mem_destroy(
   7897                 unit, gh2_tsn_bkinfo[unit]->gh2_stu_bk_info.stu_profile[type]);
   7898             TSN_FREE(unit,
   7899                     gh2_tsn_bkinfo[unit]->gh2_stu_bk_info.stu_profile[type],
   7900                     0);
   7901             gh2_tsn_bkinfo[unit]->gh2_stu_bk_info.stu_profile[type] = NULL;
   7902         }
   7903     }
   7904     if (gh2_tsn_bkinfo[unit]->gh2_stu_bk_info.mutex != NULL) {
   7905         sal_mutex_destroy(gh2_tsn_bkinfo[unit]->gh2_stu_bk_info.mutex);
   7906         gh2_tsn_bkinfo[unit]->gh2_stu_bk_info.mutex = NULL;
   7907     }
   7908 
   7909     return BCM_E_NONE;
   7910 }
   7911 
   7912 /* Allocate STU bookkeeping info resource */
   7913 STATIC int
   7914 bcmi_gh2_tsn_stu_init(int unit)
   7915 {
   7916     bcm_tsn_stu_profile_type_t type;
   7917     bcm_tsn_stu_config_t config;
   7918     uint32 idx;
   7919     int rv;
   7920 #if defined(BCM_WARM_BOOT_SUPPORT)
   7921     int min, max, i;
   7922     void *entry;
   7923     stu_profile_entry_t entry_i;
   7924     egr_stu_profile_entry_t entry_e;
   7925     uint32 buff;
   7926     soc_mem_t mem;
   7927     soc_profile_mem_t *pmem;
   7928 #endif /*BCM_WARM_BOOT_SUPPORT*/
   7929 
   7930 
   7931     /*
   7932      * The stu config is not used, but to occupy profile memory id 0 as invalid
   7933      */
   7934     config.size = 0;
   7935     config.drop = 0;
   7936 
   7937     /* Create STU mutex */
   7938     gh2_tsn_bkinfo[unit]->gh2_stu_bk_info.mutex =
   7939         sal_mutex_create("stu_mutex");
   7940     if (gh2_tsn_bkinfo[unit]->gh2_stu_bk_info.mutex == NULL) {
   7941         bcmi_gh2_tsn_stu_cleanup(unit);
   7942         return BCM_E_MEMORY;
   7943     }
   7944 
   7945     for (type = bcmTsnStuProfileTypeIngress; type < bcmTsnStuProfileTypeCount;
   7946          type++) {
   7947         TSN_ALLOC(
   7948             unit, gh2_tsn_bkinfo[unit]->gh2_stu_bk_info.stu_profile[type],
   7949             soc_profile_mem_t, sizeof(soc_profile_mem_t),
   7950             "GH2 TSN STU Ingress bookkeeping info", 0, rv);
   7951         if (BCM_FAILURE(rv)) {
   7952             bcmi_gh2_tsn_stu_cleanup(unit);
   7953             return rv;
   7954         }
   7955 
   7956         /* Initialize and Create ingress stu profile memory */
   7957         rv = bcmi_gh2_tsn_stu_profile_mem_init(unit, type);
   7958         if (BCM_FAILURE(rv)) {
   7959             bcmi_gh2_tsn_stu_cleanup(unit);
   7960             return rv;
   7961         }
   7962 
   7963         /* Profile memory id 0 as default/invalid */
   7964         rv = bcmi_gh2_tsn_stu_profile_create(unit, type, &config, &idx);
   7965         if (BCM_FAILURE(rv) || idx != 0) {
   7966             bcmi_gh2_tsn_stu_cleanup(unit);
   7967             return rv;
   7968         }
   7969 
   7970 #if defined(BCM_WARM_BOOT_SUPPORT)
   7971         if (SOC_WARM_BOOT(unit)) {
   7972             pmem = TSN_BKINFO(unit)->gh2_stu_bk_info.stu_profile[type];
   7973             mem = gh2_stu_profile_mem[type];
   7974 
   7975             if (type == bcmTsnStuProfileTypeIngress) {
   7976                 entry = &entry_i;
   7977             } else {
   7978                 entry = &entry_e;
   7979             }
   7980 
   7981             STU_BKINFO_LOCK(unit);
   7982             rv = bcmi_gh2_tsn_stu_profile_mem_idx_get(unit, type, &min, &max);
   7983             if (BCM_FAILURE(rv)) {
   7984                 STU_BKINFO_UNLOCK(unit);
   7985                 return rv;
   7986             }
   7987             /* Recovering SW soc_profile_mem management */
   7988             for (i = min; i <= max; i++) {
   7989                 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, i, entry);
   7990                 if (SOC_FAILURE(rv)) {
   7991                     STU_BKINFO_UNLOCK(unit);
   7992                     return rv;
   7993                 }
   7994                 soc_mem_field_get(unit, mem, (uint32 *)entry, STU_SIZEf, &buff);
   7995                 if (buff > 0) {
   7996                     rv = soc_profile_mem_reference(unit, pmem, i, 1);
   7997                     if (SOC_FAILURE(rv)) {
   7998                         STU_BKINFO_UNLOCK(unit);
   7999                         return rv;
   8000                     }
   8001                 }
   8002             }
   8003             STU_BKINFO_UNLOCK(unit);
   8004         }
   8005 #endif /* BCM_WARM_BOOT_SUPPORT */
   8006     }
   8007      return BCM_E_NONE;
   8008 }
   8009 
   8010 #ifdef BCM_WARM_BOOT_SUPPORT
   8011 /*
   8012  * Function:
   8013  *      bcmi_gh2_tsn_egress_mtu_wb_reload
   8014  * Purpose:
   8015  *      Reload the scache data into egr mtu sw data structure
   8016  * Parameters:
   8017  *      unit - (IN) Unit number
   8018  *      idx - (IN) HW index
   8019  *      config - (OUT) pri_map_cofig
   8020  * Returns:
   8021  *      BCM_E_xxx
   8022  */
   8023 STATIC int
   8024 bcmi_gh2_tsn_egress_mtu_wb_reload(
   8025     int unit,
   8026     int idx,
   8027     bcm_tsn_pri_map_config_t *config)
   8028 {
   8029     int i, mem_idx, profile_id, mtu_idx;
   8030     egr_mtu_check_entry_t egr_entry;
   8031 
   8032     if (config == NULL) {
   8033         return BCM_E_PARAM;
   8034     }
   8035 
   8036     if (idx < 0 || idx >= GH2_LOGIC_PORT_MAX_NUM) {
   8037         return BCM_E_PARAM;
   8038     }
   8039 
   8040     /* Recovered the SW priority map data structure */
   8041     config->map_type = bcmTsnPriMapTypeEgressMtuProfile;
   8042     config->num_map_entries = EGRESS_MTU_STU_INT_PRI_NUM;
   8043     for (i = 0; i < config->num_map_entries; i++) {
   8044         bcm_tsn_pri_map_entry_t_init(&config->map_entries[i]);
   8045         config->map_entries[i].flags = BCM_TSN_PRI_MAP_ENTRY_PROFILE_ID;
   8046         mem_idx = idx * EGRESS_MTU_STU_INT_PRI_NUM + i;
   8047         SOC_IF_ERROR_RETURN
   8048             (soc_mem_read(unit, EGR_MTU_CHECKm, MEM_BLOCK_ANY, mem_idx,
   8049                           &egr_entry));
   8050         if (SOC_MEM_FIELD_VALID(unit, EGR_MTU_CHECKm,
   8051                                 MTU_PROFILE_INDEXf)) {
   8052             mtu_idx = soc_mem_field32_get(unit, EGR_MTU_CHECKm, &egr_entry,
   8053                                      MTU_PROFILE_INDEXf);
   8054         } else {
   8055             return BCM_E_INTERNAL;
   8056         }
   8057         bcmi_gh2_tsn_mtu_profile_encode(
   8058             unit, mtu_idx, bcmTsnMtuProfileTypeEgress, &profile_id);
   8059         config->map_entries[i].profile_id = profile_id;
   8060     }
   8061     return BCM_E_NONE;
   8062 }
   8063 
   8064 /*
   8065  * Function:
   8066  *      bcmi_gh2_tsn_egress_stu_wb_reload
   8067  * Purpose:
   8068  *      Reload the scache data into egr stu sw data structure
   8069  * Parameters:
   8070  *      unit - (IN) Unit number
   8071  *      idx - (IN) HW index
   8072  *      config - (OUT) pri_map_cofig
   8073  * Returns:
   8074  *      BCM_E_xxx
   8075  */
   8076 STATIC int
   8077 bcmi_gh2_tsn_egress_stu_wb_reload(
   8078     int unit,
   8079     int idx,
   8080     bcm_tsn_pri_map_config_t *config)
   8081 {
   8082     int i, mem_idx, profile_id, stu_idx;
   8083     egr_stu_check_entry_t egr_entry;
   8084 
   8085     if (config == NULL) {
   8086         return BCM_E_PARAM;
   8087     }
   8088 
   8089     if (idx < 0 || idx >= GH2_LOGIC_PORT_MAX_NUM) {
   8090         return BCM_E_PARAM;
   8091     }
   8092 
   8093     /* Recovered the SW priority map data structure */
   8094     config->map_type = bcmTsnPriMapTypeEgressStuProfile;
   8095     config->num_map_entries = EGRESS_MTU_STU_INT_PRI_NUM;
   8096     for (i = 0; i < config->num_map_entries; i++) {
   8097         bcm_tsn_pri_map_entry_t_init(&config->map_entries[i]);
   8098         config->map_entries[i].flags = BCM_TSN_PRI_MAP_ENTRY_PROFILE_ID;
   8099         mem_idx = idx * EGRESS_MTU_STU_INT_PRI_NUM + i;
   8100         SOC_IF_ERROR_RETURN
   8101             (soc_mem_read(unit, EGR_STU_CHECKm, MEM_BLOCK_ANY, mem_idx,
   8102                           &egr_entry));
   8103         if (SOC_MEM_FIELD_VALID(unit, EGR_STU_CHECKm,
   8104                                 STU_PROFILE_INDEXf)) {
   8105             stu_idx = soc_mem_field32_get(unit, EGR_STU_CHECKm, &egr_entry,
   8106                                      STU_PROFILE_INDEXf);
   8107         } else {
   8108             return BCM_E_INTERNAL;
   8109         }
   8110         bcmi_gh2_tsn_stu_profile_encode(
   8111             unit, stu_idx, bcmTsnStuProfileTypeEgress, &profile_id);
   8112         config->map_entries[i].profile_id = profile_id;
   8113     }
   8114     return BCM_E_NONE;
   8115 }
   8116 
   8117 #endif /* BCM_WARM_BOOT_SUPPORT */
   8118 
   8119 #if defined(BCM_TSN_SR_SUPPORT)
   8120 /* Per-chip SR MAC Proxy info */
   8121 STATIC const tsn_sr_mac_proxy_info_t gh2_sr_mac_proxy_info = {
   8122     SR_MAC_PROXY_PROFILEm, /* soc_mem_t mem */
   8123     SR_PROXY_BITMAPf       /* soc_field_t field */
   8124 };
   8125 
   8126 /* SR flow management platform specific data */
   8127 STATIC const bcmi_tsn_sr_flows_dev_info_t gh2_tsn_sr_flows_dev_info = {
   8128     bcmi_gh2_tsn_sr_flows_get_num_flows,        /* get_num_flows */
   8129     bcmi_gh2_tsn_sr_flows_get_hw_flow_id,       /* get_hw_flow_id */
   8130     bcmi_gh2_tsn_sr_flows_get_sw_flow_idx,      /* get_sw_flow_idx */
   8131     bcmi_gh2_tsn_sr_flows_check_rx_flow_config, /* check_rx_flow_config */
   8132     bcmi_gh2_tsn_sr_flows_check_tx_flow_config, /* check_tx_flow_config */
   8133     bcmi_gh2_tsn_sr_flows_clear_rx_flow,        /* clear_rx_flow */
   8134     bcmi_gh2_tsn_sr_flows_clear_tx_flow,        /* clear_tx_flow */
   8135     bcmi_gh2_tsn_sr_flows_write_rx_flow,        /* write_rx_flow */
   8136     bcmi_gh2_tsn_sr_flows_write_tx_flow,        /* write_tx_flow */
   8137 #ifdef BCM_WARM_BOOT_SUPPORT
   8138     bcmi_gh2_tsn_sr_flows_read_rx_flow,         /* read_rx_flow */
   8139     bcmi_gh2_tsn_sr_flows_read_tx_flow,         /* read_tx_flow */
   8140 #endif /* BCM_WARM_BOOT_SUPPORT */
   8141     bcmi_gh2_tsn_sr_flows_get_rx_flow_status,   /* get_rx_flow_status */
   8142     bcmi_gh2_tsn_sr_flows_get_tx_flow_status,   /* get_tx_flow_status */
   8143     bcmi_gh2_tsn_sr_flows_reset_rx_flow,        /* reset_rx_flow */
   8144     bcmi_gh2_tsn_sr_flows_seqnum_slice_alloc,   /* seqnum_slice_alloc */
   8145     bcmi_gh2_tsn_sr_flows_seqnum_slice_free,    /* seqnum_slice_free */
   8146     bcmi_gh2_tsn_sr_flows_seqnum_hist_read,     /* seqnum_hist_read */
   8147     bcmi_gh2_tsn_sr_flows_seqnum_hist_write,    /* seqnum_hist_write */
   8148     bcmi_gh2_tsn_sr_flows_seqnum_hist_reset,    /* seqnum_hist_reset */
   8149     bcmi_gh2_tsn_sr_flows_clear_rx_flow_mtu,    /* clear_rx_flow_mtu */
   8150     bcmi_gh2_tsn_sr_flows_clear_tx_flow_mtu     /* clear_tx_flow_mtu */
   8151 };
   8152 
   8153 /* TSN-SR Port config set/get */
   8154 STATIC const tsn_sr_port_dev_info_t gh2_sr_port_dev_info = {
   8155 #ifdef BCM_WARM_BOOT_SUPPORT
   8156     bcmi_gh2_tsn_sr_port_prp_forwarding_sync,   /* prp_forwarding_sync */
   8157     bcmi_gh2_tsn_sr_port_prp_forwarding_reload, /* prp_forwarding_reload */
   8158 #endif /* BCM_WARM_BOOT_SUPPORT */
   8159     bcmi_gh2_tsn_sr_port_config_set,            /* sr_port_config_set */
   8160     bcmi_gh2_tsn_sr_port_config_get             /* sr_port_config_get */
   8161 };
   8162 
   8163 #endif /* BCM_TSN_SR_SUPPORT */
   8164 
   8165 /* TSN event management structures */
   8166 /* device wrong lan interrupt register/field information */
   8167 typedef struct gh2_event_wrong_lan_info_s {
   8168     bcm_tsn_event_type_t event_type;
   8169     soc_field_t enable_status_field;
   8170     soc_reg_t   sts_reg;
   8171     soc_field_t idx_field;
   8172     soc_field_t mul_err_field;
   8173     soc_field_t err_field;
   8174 } gh2_event_wrong_lan_info_t;
   8175 
   8176 STATIC const gh2_event_wrong_lan_info_t gh2_event_lan_err[] = {
   8177     {bcmTsnEventTypeSrWrongLanA,
   8178      IFP_WRONG_LAN_A_INTRf,
   8179      IFP_WRONG_LAN_A_STATUS_INTRr, ENTRY_IDXf, MULTIPLE_WRONG_LAN_A_ERRf,
   8180      WRONG_LAN_A_ERRf},
   8181     {bcmTsnEventTypeSrWrongLanB,
   8182      IFP_WRONG_LAN_B_INTRf,
   8183      IFP_WRONG_LAN_B_STATUS_INTRr, ENTRY_IDXf, MULTIPLE_WRONG_LAN_B_ERRf,
   8184      WRONG_LAN_B_ERRf}
   8185 };
   8186 
   8187 /* device counter threshold register/field information */
   8188 typedef struct gh2_event_cnt_threshold_s {
   8189     soc_field_t sts_field;
   8190     bcm_tsn_stat_t  stat_type;
   8191     bcm_tsn_stat_threshold_source_t th_src;
   8192 } gh2_event_cnt_threshold_t;
   8193 
   8194 /* Information from IP2_SR_TH_INTR_STATUSr */
   8195 STATIC const gh2_event_cnt_threshold_t gh2_event_cnt_thr_ip[] = {
   8196     {SR_FLOW_INTR_RX_TAGGEDf,
   8197      bcmTsnStatIngressSrTaggedPackets, bcmTsnStatThresholdSourceSRFlow},
   8198     {SR_FLOW_INTR_RXf,
   8199      bcmTsnStatIngressNonLinkLocalPackets, bcmTsnStatThresholdSourceSRFlow},
   8200     {SR_FLOW_INTR_RX_WRONG_LANf,
   8201      bcmTsnStatIngressSrWrongLanPackets, bcmTsnStatThresholdSourceSRFlow},
   8202     {SR_FLOW_INTR_RX_ERRORf,
   8203      bcmTsnStatIngressSrRxErrorPackets, bcmTsnStatThresholdSourceSRFlow},
   8204     {SR_FLOW_INTR_RX_TAG_ERRORf,
   8205      bcmTsnStatIngressSrTagErrorPackets, bcmTsnStatThresholdSourceSRFlow},
   8206     {SR_FLOW_INTR_RX_DUPLICATESf,
   8207      bcmTsnStatIngressSrDuplicatePackets, bcmTsnStatThresholdSourceSRFlow},
   8208     {SR_FLOW_INTR_RX_OUTOFORDERf,
   8209      bcmTsnStatIngressSrOutOfOrderSrPackets, bcmTsnStatThresholdSourceSRFlow},
   8210     {SR_FLOW_INTR_OWN_RXf,
   8211      bcmTsnStatIngressSrOwnRxPackets, bcmTsnStatThresholdSourceSRFlow},
   8212     {SR_FLOW_INTR_UNEXPECTED_FRAMEf,
   8213      bcmTsnStatIngressSrUnexpectedPackets, bcmTsnStatThresholdSourceSRFlow},
   8214     {SR_FLOW_INTR_MTU_ERRORf,
   8215      bcmTsnStatIngressMtuErrorPackets, bcmTsnStatThresholdSourceSRFlow},
   8216     {SR_FLOW_INTR_STU_ERRORf,
   8217      bcmTsnStatIngressStuErrorPackets, bcmTsnStatThresholdSourceSRFlow},
   8218     {SR_FLOW_INTR_RX_PASSEDf,
   8219      bcmTsnStatIngressSrAcceptedSrPackets, bcmTsnStatThresholdSourceSRFlow},
   8220     {SR_FLOW_INTR_PROXY_MAC_ERRORf,
   8221      bcmTsnStatIngressSrSaSrcFilteredPackets, bcmTsnStatThresholdSourceSRFlow},
   8222     {SR_PORT_INTR_RX_TAGGEDf,
   8223      bcmTsnStatIngressSrTaggedPackets, bcmTsnStatThresholdSourcePort},
   8224     {SR_PORT_INTR_RXf,
   8225      bcmTsnStatIngressNonLinkLocalPackets, bcmTsnStatThresholdSourcePort},
   8226     {SR_PORT_INTR_RX_WRONG_LANf,
   8227      bcmTsnStatIngressSrWrongLanPackets, bcmTsnStatThresholdSourcePort},
   8228     {SR_PORT_INTR_RX_ERRORf,
   8229      bcmTsnStatIngressSrRxErrorPackets, bcmTsnStatThresholdSourcePort},
   8230     {SR_PORT_INTR_RX_TAG_ERRORf,
   8231      bcmTsnStatIngressSrTagErrorPackets, bcmTsnStatThresholdSourcePort},
   8232     {SR_PORT_INTR_RX_DUPLICATESf,
   8233      bcmTsnStatIngressSrDuplicatePackets, bcmTsnStatThresholdSourcePort},
   8234     {SR_PORT_INTR_RX_OUTOFORDERf,
   8235      bcmTsnStatIngressSrOutOfOrderSrPackets, bcmTsnStatThresholdSourcePort},
   8236     {SR_PORT_INTR_OWN_RXf,
   8237      bcmTsnStatIngressSrOwnRxPackets, bcmTsnStatThresholdSourcePort},
   8238     {SR_PORT_INTR_UNEXPECTED_FRAMEf,
   8239      bcmTsnStatIngressSrUnexpectedPackets, bcmTsnStatThresholdSourcePort},
   8240     {SR_PORT_INTR_MTU_ERRORf,
   8241      bcmTsnStatIngressMtuErrorPackets, bcmTsnStatThresholdSourcePort},
   8242     {SR_PORT_INTR_STU_ERRORf,
   8243      bcmTsnStatIngressStuErrorPackets, bcmTsnStatThresholdSourcePort},
   8244     {SR_PORT_INTR_RX_PASSEDf,
   8245      bcmTsnStatIngressSrAcceptedSrPackets, bcmTsnStatThresholdSourcePort},
   8246     {SR_PORT_INTR_PROXY_MAC_ERRORf,
   8247      bcmTsnStatIngressSrSaSrcFilteredPackets, bcmTsnStatThresholdSourcePort}
   8248 };
   8249 
   8250 /* Information from EGR_MISC_INTR_STATUSr */
   8251 STATIC const gh2_event_cnt_threshold_t gh2_event_cnt_thr_ep[] = {
   8252     {SR_FLOW_COUNT_THRESHOLD_TX_TAGGEDf,
   8253      bcmTsnStatEgressSrTaggedPackets, bcmTsnStatThresholdSourceSRFlow},
   8254     {SR_FLOW_COUNT_THRESHOLD_TXf,
   8255      bcmTsnStatEgressNonLinkLocalPackets, bcmTsnStatThresholdSourceSRFlow},
   8256     {SR_FLOW_THRESHOLD_TX_MTU_ERRORf,
   8257      bcmTsnStatEgressMtuErrorPackets, bcmTsnStatThresholdSourceSRFlow},
   8258     {SR_FLOW_THRESHOLD_TX_STU_ERRORf,
   8259      bcmTsnStatEgressStuErrorPackets, bcmTsnStatThresholdSourceSRFlow},
   8260     {SR_PORT_COUNT_THRESHOLD_TX_TAGGEDf,
   8261      bcmTsnStatEgressSrTaggedPackets, bcmTsnStatThresholdSourcePort},
   8262     {SR_PORT_COUNT_THRESHOLD_TXf,
   8263      bcmTsnStatEgressNonLinkLocalPackets, bcmTsnStatThresholdSourcePort},
   8264     {SR_PORT_THRESHOLD_TX_MTU_ERRORf,
   8265      bcmTsnStatEgressMtuErrorPackets, bcmTsnStatThresholdSourcePort},
   8266     {SR_PORT_THRESHOLD_TX_STU_ERRORf,
   8267      bcmTsnStatEgressStuErrorPackets, bcmTsnStatThresholdSourcePort}
   8268 };
   8269 
   8270 STATIC int
   8271 bcmi_gh2_tsn_event_mask(int unit, bcm_tsn_event_type_t event, uint32 enable)
   8272 {
   8273     uint64 val;
   8274 
   8275     if (event == bcmTsnEventTypeSrWrongLanA) {
   8276         BCM_IF_ERROR_RETURN(READ_IP2_INTR_ENABLEr(unit, &val));
   8277         soc_reg64_field32_set(unit, IP2_INTR_ENABLEr, &val,
   8278                               IFP_WRONG_LAN_A_INTRf, enable);
   8279         BCM_IF_ERROR_RETURN(WRITE_IP2_INTR_ENABLEr(unit, val));
   8280     }
   8281     if (event == bcmTsnEventTypeSrWrongLanB) {
   8282         BCM_IF_ERROR_RETURN(READ_IP2_INTR_ENABLEr(unit, &val));
   8283         soc_reg64_field32_set(unit, IP2_INTR_ENABLEr, &val,
   8284                               IFP_WRONG_LAN_B_INTRf, enable);
   8285         BCM_IF_ERROR_RETURN(WRITE_IP2_INTR_ENABLEr(unit, val));
   8286     }
   8287     LOG_DEBUG(BSL_LS_BCM_TSN,
   8288               (BSL_META("TSN EVT: event(%d) mask enable = %d\n"),
   8289               event, enable));
   8290     return BCM_E_NONE;
   8291 }
   8292 
   8293 /*
   8294  * Update the flow bitmap by specifying the event and hw flow id
   8295  * when event == -1, update the active rx flow bitmap
   8296  */
   8297 STATIC int
   8298 bcmi_gh2_tsn_event_rx_flow_update(
   8299     int unit,
   8300     int event,
   8301     int idx,
   8302     int val)
   8303 {
   8304     int                     rv = BCM_E_NONE, fid, max;
   8305     gh2_tsn_events_bkinfo_t *bkinfo = EVENTS_BKINFO(unit);
   8306 
   8307     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   8308         return BCM_E_UNAVAIL;
   8309     }
   8310     EVENT_MGMT_LOCK(unit);
   8311     if ((bcm_tsn_event_type_t)event == bcmTsnEventTypeSrWrongLanA) {
   8312         if (val) {
   8313             SHR_BITSET(bkinfo->wrong_lana_fbmp, idx);
   8314         } else {
   8315             SHR_BITCLR(bkinfo->wrong_lana_fbmp, idx);
   8316         }
   8317     } else if ((bcm_tsn_event_type_t)event == bcmTsnEventTypeSrWrongLanB) {
   8318         if (val) {
   8319             SHR_BITSET(bkinfo->wrong_lanb_fbmp, idx);
   8320         } else {
   8321             SHR_BITCLR(bkinfo->wrong_lanb_fbmp, idx);
   8322         }
   8323     } else if ((bcm_tsn_event_type_t)event ==
   8324                bcmTsnEventTypeSrSeqNumWindowAgeOut) {
   8325         if (val) {
   8326             SHR_BITSET(bkinfo->sn_reset_fbmp, idx);
   8327         } else {
   8328             SHR_BITCLR(bkinfo->sn_reset_fbmp, idx);
   8329         }
   8330     } else if (event == -1) {
   8331         /* update the valid rx flow bmp */
   8332         if (val) {
   8333             SHR_BITSET(bkinfo->active_rx_fbmp, idx);
   8334             if (bkinfo->active_rx_fbmp_min == -1) {
   8335                 bkinfo->active_rx_fbmp_min = idx;
   8336                 bkinfo->active_rx_fbmp_max = idx;
   8337             }
   8338             if (idx < bkinfo->active_rx_fbmp_min) {
   8339                 bkinfo->active_rx_fbmp_min = idx;
   8340             }
   8341             if (idx > bkinfo->active_rx_fbmp_max) {
   8342                 bkinfo->active_rx_fbmp_max = idx;
   8343             }
   8344         } else {
   8345             SHR_BITCLR(bkinfo->active_rx_fbmp, idx);
   8346             if (SHR_BITNULL_RANGE(bkinfo->active_rx_fbmp, 0,
   8347                                   bkinfo->max_rx_flows)) {
   8348                 /* active_rx_fbmp is empty */
   8349                 bkinfo->active_rx_fbmp_min = bkinfo->active_rx_fbmp_max = -1;
   8350             } else {
   8351                 if (idx == bkinfo->active_rx_fbmp_min) {
   8352                     /* need to get new min */
   8353                     SHR_BIT_ITER(bkinfo->active_rx_fbmp,
   8354                                  bkinfo->active_rx_fbmp_max, fid) {
   8355                         bkinfo->active_rx_fbmp_min = fid;
   8356                         break;
   8357                     }
   8358                 }
   8359                 if (idx == bkinfo->active_rx_fbmp_max) {
   8360                     max = bkinfo->active_rx_fbmp_max;
   8361                     /* need to get new max */
   8362                     SHR_BIT_ITER(bkinfo->active_rx_fbmp,
   8363                                  bkinfo->active_rx_fbmp_max, fid) {
   8364                         max = fid;
   8365                     }
   8366                     bkinfo->active_rx_fbmp_max = max;
   8367                 }
   8368             }
   8369         }
   8370     } else {
   8371         /* don't care the other types for GH2 */
   8372         rv = BCM_E_NONE;
   8373     }
   8374     EVENT_MGMT_UNLOCK(unit);
   8375     return rv;
   8376 }
   8377 
   8378 STATIC int
   8379 bcmi_gh2_tsn_event_flow_stat_get(
   8380     int unit,
   8381     bcm_tsn_event_type_t event,
   8382     SHR_BITDCL *flowstate,
   8383     SHR_BITDCL *filterflowstate,
   8384     uint32 flow_number)
   8385 {
   8386     int             min, max, rv, fidx, min_cd_val, cd_val;
   8387     sr_rx_entry_t   *rx_entries, *sr_rx;
   8388     soc_mem_t       mem;
   8389     soc_field_t     field, cd_field;
   8390     int             rx_flows, min_age_val, age_val;
   8391     gh2_tsn_events_bkinfo_t *bkinfo = EVENTS_BKINFO(unit);
   8392 
   8393     if ((bkinfo->active_rx_fbmp_min == -1) ||
   8394         (bkinfo->active_rx_fbmp_max == -1)) {
   8395         LOG_ERROR(BSL_LS_BCM_TSN,
   8396                   (BSL_META_U(unit, "No active rx flow.\n")));
   8397         return BCM_E_INTERNAL;
   8398     }
   8399     if (flowstate != NULL && filterflowstate != NULL &&
   8400         (flow_number < bkinfo->max_rx_flows)) {
   8401         return BCM_E_PARAM;
   8402     }
   8403     if ((filterflowstate == NULL) ^ (flowstate == NULL)) {
   8404         return BCM_E_PARAM;
   8405     }
   8406     rx_flows = bkinfo->max_rx_flows;
   8407     /* flowstate could be null when try to update the min count down value */
   8408     EVENT_MGMT_LOCK(unit);
   8409     if (event == bcmTsnEventTypeSrWrongLanA) {
   8410         field = WRONG_LAN_Af;
   8411         cd_field = WRONG_LAN_A_AGE_OUT_COUNT_DOWNf;
   8412     } else if (event == bcmTsnEventTypeSrWrongLanB) {
   8413         field = WRONG_LAN_Bf;
   8414         cd_field = WRONG_LAN_B_AGE_OUT_COUNT_DOWNf;
   8415     } else if (event == bcmTsnEventTypeSrSeqNumWindowAgeOut) {
   8416         field = AGE_OUT_INDICATORf;
   8417         cd_field = SN_AGE_OUT_COUNT_DOWNf;
   8418     } else {
   8419         EVENT_MGMT_UNLOCK(unit);
   8420         return BCM_E_PARAM;
   8421     }
   8422 
   8423     min = bkinfo->active_rx_fbmp_min;
   8424     max = bkinfo->active_rx_fbmp_max;
   8425 
   8426     rx_entries = soc_cm_salloc(unit, (max - min + 1) * sizeof(*rx_entries),
   8427                                "rx flow dma");
   8428     if (rx_entries == NULL) {
   8429         EVENT_MGMT_UNLOCK(unit);
   8430         return BCM_E_MEMORY;
   8431     }
   8432     mem = SR_RXm;
   8433     rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ANY, min, max, rx_entries);
   8434     if (BCM_FAILURE(rv)) {
   8435         soc_cm_sfree(unit, rx_entries);
   8436         EVENT_MGMT_UNLOCK(unit);
   8437         return rv;
   8438     }
   8439     min_cd_val = 0;
   8440     min_age_val = 0;
   8441     for (fidx = min; fidx <= max; fidx++) {
   8442         sr_rx = soc_mem_table_idx_to_pointer(unit, mem, sr_rx_entry_t *,
   8443                                              rx_entries, (fidx - min));
   8444         if (soc_mem_field32_get(unit, mem, sr_rx, field)) {
   8445             if (flowstate != NULL) {
   8446                 SHR_BITSET(flowstate, fidx);
   8447             }
   8448         }
   8449         age_val = soc_mem_field32_get(unit, mem, sr_rx, AGE_OUT_MULTIPLIERf);
   8450         if (age_val) {
   8451             if ((min_age_val == 0) || (age_val < min_age_val)) {
   8452                 min_age_val = age_val;
   8453             }
   8454         }
   8455         cd_val = soc_mem_field32_get(unit, mem, sr_rx, cd_field);
   8456         /* when count down value > age tick, assign count down value = 0 */
   8457         if (cd_val >= (1 << age_val)) {
   8458             cd_val = 0;
   8459         }
   8460         if (cd_val) {
   8461             if ((min_cd_val == 0) || (cd_val < min_cd_val)) {
   8462                 min_cd_val = cd_val;
   8463             }
   8464         }
   8465     }
   8466     soc_cm_sfree(unit, rx_entries);
   8467 
   8468     if (min_cd_val > (1 << min_age_val)) {
   8469         min_cd_val = (1 << min_age_val) - 1;
   8470     }
   8471     LOG_DEBUG(BSL_LS_BCM_TSN,
   8472               (BSL_META_U(unit, "TSN EVT (%d): Min. count downtick %d\n"),
   8473               event, min_cd_val));
   8474 
   8475     if (event == bcmTsnEventTypeSrWrongLanA) {
   8476         bkinfo->wrong_lana_min_cd = min_cd_val;
   8477         if (flowstate != NULL) {
   8478             SHR_BITAND_RANGE(flowstate, bkinfo->wrong_lana_fbmp, 0, rx_flows,
   8479                              filterflowstate);
   8480         }
   8481     } else if (event == bcmTsnEventTypeSrWrongLanB) {
   8482         bkinfo->wrong_lanb_min_cd = min_cd_val;
   8483         if (flowstate != NULL) {
   8484             SHR_BITAND_RANGE(flowstate, bkinfo->wrong_lanb_fbmp, 0, rx_flows,
   8485                              filterflowstate);
   8486         }
   8487     } else if (event == bcmTsnEventTypeSrSeqNumWindowAgeOut) {
   8488         bkinfo->sn_reset_min_cd = min_cd_val;
   8489         if (flowstate != NULL) {
   8490             SHR_BITAND_RANGE(flowstate, bkinfo->sn_reset_fbmp, 0, rx_flows,
   8491                              filterflowstate);
   8492         }
   8493     }
   8494 
   8495     EVENT_MGMT_UNLOCK(unit);
   8496     return BCM_E_NONE;
   8497 }
   8498 
   8499 STATIC int
   8500 bcmi_gh2_tsn_event_flow_stat_clear(
   8501     int unit,
   8502     bcm_tsn_event_type_t event,
   8503     SHR_BITDCL *flowstate,
   8504     uint32 flow_number)
   8505 {
   8506     gh2_tsn_events_bkinfo_t *bkinfo = EVENTS_BKINFO(unit);
   8507     sr_rx_entry_t   entry;
   8508     soc_mem_t       mem;
   8509     soc_field_t     field;
   8510     int             rx_flows, fidx, rv;
   8511 
   8512     /* Parameter check */
   8513     if (flowstate == NULL) {
   8514         return BCM_E_PARAM;
   8515     }
   8516     if (flow_number < bkinfo->max_rx_flows) {
   8517         return BCM_E_PARAM;
   8518     }
   8519 
   8520     rx_flows = bkinfo->max_rx_flows;
   8521     EVENT_MGMT_LOCK(unit);
   8522     if (event == bcmTsnEventTypeSrWrongLanA) {
   8523         field = WRONG_LAN_Af;
   8524     } else if (event == bcmTsnEventTypeSrWrongLanB) {
   8525         field = WRONG_LAN_Bf;
   8526     } else if (event == bcmTsnEventTypeSrSeqNumWindowAgeOut) {
   8527         field = AGE_OUT_INDICATORf;
   8528     } else {
   8529         EVENT_MGMT_UNLOCK(unit);
   8530         return BCM_E_PARAM;
   8531     }
   8532 
   8533     mem = SR_RXm;
   8534     MEM_LOCK(unit, mem);
   8535     SHR_BIT_ITER(flowstate, rx_flows, fidx) {
   8536         sal_memset(&entry, 0, sizeof(entry));
   8537         rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, fidx, &entry);
   8538         if (BCM_FAILURE(rv)) {
   8539             LOG_ERROR(BSL_LS_BCM_TSN,
   8540                       (BSL_META_U(unit, "Failed to read mem[%s]"),
   8541                                   SOC_MEM_NAME(unit, mem)));
   8542             MEM_UNLOCK(unit, mem);
   8543             return rv;
   8544         }
   8545         soc_mem_field32_set(unit, mem, &entry, field, 0);
   8546         rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, fidx, &entry);
   8547         if (SOC_FAILURE(rv)) {
   8548             LOG_ERROR(BSL_LS_BCM_TSN,
   8549                       (BSL_META_U(unit, "Failed to write mem[%s]"),
   8550                                   SOC_MEM_NAME(unit, mem)));
   8551             MEM_UNLOCK(unit, mem);
   8552             return rv;
   8553         }
   8554     }
   8555     MEM_UNLOCK(unit, mem);
   8556     EVENT_MGMT_UNLOCK(unit);
   8557     return BCM_E_NONE;
   8558 }
   8559 
   8560 STATIC int
   8561 bcmi_gh2_tsn_event_poll(int unit)
   8562 {
   8563     gh2_tsn_events_bkinfo_t *bkinfo = EVENTS_BKINFO(unit);
   8564     sal_usecs_t             ctime; /* current time */
   8565     int                     diff, dtick = 0;
   8566 
   8567     if (!soc_feature(unit, soc_feature_tsn_sr)) {
   8568         /* Do nothing */
   8569         return BCM_E_NONE;
   8570     }
   8571 
   8572     if ((bkinfo->ageout_tick_ms == 0) || (bkinfo->age_enable == 0)) {
   8573         return BCM_E_NONE;
   8574     }
   8575 
   8576     /* Check any active rx flow */
   8577     if ((bkinfo->active_rx_fbmp_min == -1) ||
   8578         (bkinfo->active_rx_fbmp_max == -1)) {
   8579         /* Do nothing */
   8580         return BCM_E_NONE;
   8581     }
   8582 
   8583     EVENT_MGMT_LOCK(unit);
   8584 
   8585     ctime = sal_time_usecs();
   8586     if (bkinfo->ptime != 0) {
   8587         diff = SAL_USECS_SUB(ctime, bkinfo->ptime);
   8588         bkinfo->ptime = ctime;
   8589         dtick = diff / (bkinfo->ageout_tick_ms * MILLISECOND_USEC);
   8590     } else {
   8591         bkinfo->ptime = ctime;
   8592     }
   8593 
   8594     if ((bkinfo->wla_mask == 0) && (bkinfo->wla_tick == 0)) {
   8595         /*
   8596          * Get the updated min count down value
   8597          * when interrupt mask is disabled and tick count down to 0.
   8598          */
   8599         (void)bcmi_gh2_tsn_event_flow_stat_get(
   8600                 unit, bcmTsnEventTypeSrWrongLanA, NULL, NULL, 0);
   8601         bkinfo->wla_tick = bkinfo->wrong_lana_min_cd;
   8602         LOG_DEBUG(BSL_LS_BCM_TSN,
   8603                   (BSL_META_U(unit, "TSN EVT: WrongLanA tick %d\n"),
   8604                   bkinfo->wla_tick));
   8605     }
   8606     bkinfo->wla_tick -= dtick;
   8607 
   8608     if ((bkinfo->wlb_mask == 0) && (bkinfo->wlb_tick == 0)) {
   8609         /*
   8610          * Get the updated min count down value
   8611          * when interrupt mask is disabled and tick count down to 0.
   8612          */
   8613         (void)bcmi_gh2_tsn_event_flow_stat_get(
   8614                 unit, bcmTsnEventTypeSrWrongLanB, NULL, NULL, 0);
   8615         bkinfo->wlb_tick = bkinfo->wrong_lanb_min_cd;
   8616         LOG_DEBUG(BSL_LS_BCM_TSN,
   8617                   (BSL_META_U(unit, "TSN EVT: WrongLanB tick %d\n"),
   8618                   bkinfo->wlb_tick));
   8619     }
   8620     bkinfo->wlb_tick -= dtick;
   8621 
   8622     if (bkinfo->window_reset_mode ==
   8623         BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_SW) {
   8624         if (bkinfo->sn_reset_min_cd == 0) {
   8625             /* Update sn_reset_min_cd */
   8626             (void)bcmi_gh2_tsn_event_flow_stat_get(
   8627                 unit, bcmTsnEventTypeSrSeqNumWindowAgeOut, NULL, NULL, 0);
   8628         }
   8629         if (bkinfo->sn_reset_min_cd > 0) {
   8630             if (bkinfo->reset_tick == 0) {
   8631                 bkinfo->reset_tick = bkinfo->sn_reset_min_cd;
   8632                 LOG_DEBUG(BSL_LS_BCM_TSN,
   8633                           (BSL_META_U(unit, "TSN EVT: sn reset tick %d\n"),
   8634                           bkinfo->sn_reset_min_cd));
   8635             }
   8636             bkinfo->reset_tick -= dtick;
   8637 
   8638             /* notify callback to check the age-out indicator */
   8639             if (bkinfo->reset_tick <= 0) {
   8640                 if (bkinfo->gh2_flow_event_notify) {
   8641                     bkinfo->gh2_flow_event_notify(
   8642                         unit, bcmTsnEventTypeSrSeqNumWindowAgeOut, 1, 0);
   8643                 }
   8644                 bkinfo->reset_tick = 0;
   8645             }
   8646         }
   8647     }
   8648     if (!SHR_BITNULL_RANGE(bkinfo->wrong_lana_fbmp, 0, bkinfo->max_rx_flows)) {
   8649         /* check the wrong LanA ageout ticks to enable the interrupt mask */
   8650         if (bkinfo->wla_tick <= 0) {
   8651             if (bkinfo->wla_mask == 0) {
   8652                 (void)bcmi_gh2_tsn_event_mask(unit,
   8653                                               bcmTsnEventTypeSrWrongLanA, 1);
   8654                 bkinfo->wla_mask = 1;
   8655             }
   8656             bkinfo->wla_tick = 0;
   8657         }
   8658     }
   8659     if (!SHR_BITNULL_RANGE(bkinfo->wrong_lanb_fbmp, 0, bkinfo->max_rx_flows)) {
   8660         /* check the wrong LanB ageout ticks to enable the interrupt mask */
   8661         if (bkinfo->wlb_tick <= 0) {
   8662             if (bkinfo->wlb_mask == 0) {
   8663                 (void)bcmi_gh2_tsn_event_mask(unit,
   8664                                               bcmTsnEventTypeSrWrongLanB, 1);
   8665                 bkinfo->wlb_mask = 1;
   8666             }
   8667             bkinfo->wlb_tick = 0;
   8668         }
   8669     }
   8670 
   8671     EVENT_MGMT_UNLOCK(unit);
   8672 
   8673     return BCM_E_NONE;
   8674 }
   8675 
   8676 STATIC int
   8677 bcmi_gh2_tsn_flow_event_notify_register(
   8678     int unit,
   8679     bcmi_esw_tsn_flow_event_notify_cb cb)
   8680 {
   8681     gh2_tsn_events_bkinfo_t *bkinfo = EVENTS_BKINFO(unit);
   8682 
   8683     bkinfo->gh2_flow_event_notify = cb;
   8684     return BCM_E_NONE;
   8685 }
   8686 
   8687 STATIC int
   8688 bcmi_gh2_tsn_cnt_excceed_notify_register(
   8689     int unit,
   8690     bcmi_esw_tsn_cnt_exceed_notify_cb cb)
   8691 {
   8692     gh2_tsn_events_bkinfo_t *bkinfo = EVENTS_BKINFO(unit);
   8693 
   8694     bkinfo->gh2_cnt_exceed_notify = cb;
   8695     return BCM_E_NONE;
   8696 }
   8697 
   8698 STATIC int
   8699 bcmi_gh2_tsn_event_interrupt_handler(
   8700     int unit,
   8701     uint8 lan_err,
   8702     uint8 ip_cnt_err,
   8703     uint8 ep_cnt_err)
   8704 {
   8705     const gh2_event_wrong_lan_info_t    *lan_err_info;
   8706     const gh2_event_cnt_threshold_t     *cnt_th_info;
   8707     uint64                              rval64, clear_field_64;
   8708     uint32                              rval32, multiple, clear_field;
   8709     soc_reg_t                           sts_reg;
   8710     bcmi_esw_tsn_flow_event_notify_cb   fe_cb = NULL;
   8711     bcmi_esw_tsn_cnt_exceed_notify_cb   ce_cb = NULL;
   8712     int                                 idx, i;
   8713     gh2_tsn_events_bkinfo_t *bkinfo = EVENTS_BKINFO(unit);
   8714 
   8715     if (bkinfo->gh2_flow_event_notify) {
   8716         fe_cb = bkinfo->gh2_flow_event_notify;
   8717     }
   8718     if (bkinfo->gh2_cnt_exceed_notify) {
   8719         ce_cb = bkinfo->gh2_cnt_exceed_notify;
   8720     }
   8721 
   8722     if (ip_cnt_err) {
   8723         multiple = 1;
   8724         idx = -1;
   8725         BCM_IF_ERROR_RETURN(
   8726             soc_reg_get(unit, IP2_SR_TH_INTR_STATUSr, REG_PORT_ANY, 0,
   8727                         &rval64));
   8728         COMPILER_64_COPY(clear_field_64, rval64);
   8729 
   8730         for (i = 0; i < COUNTOF(gh2_event_cnt_thr_ip); i++) {
   8731             cnt_th_info = &gh2_event_cnt_thr_ip[i];
   8732             if (soc_reg64_field32_get(unit, IP2_SR_TH_INTR_STATUSr, rval64,
   8733                                       cnt_th_info->sts_field)) {
   8734                 if (ce_cb) {
   8735                     (void)ce_cb(unit, cnt_th_info->stat_type,
   8736                                 cnt_th_info->th_src, multiple, idx);
   8737                 }
   8738                 soc_reg64_field32_set(unit, IP2_SR_TH_INTR_STATUSr,
   8739                                       &clear_field_64,
   8740                                       cnt_th_info->sts_field, 0);
   8741             }
   8742         }
   8743         /* Clear status */
   8744         BCM_IF_ERROR_RETURN(
   8745             soc_reg_set(unit, IP2_SR_TH_INTR_STATUSr, REG_PORT_ANY, 0,
   8746                         clear_field_64));
   8747     }
   8748     if (ep_cnt_err) {
   8749         multiple = 1;
   8750         idx = -1;
   8751         BCM_IF_ERROR_RETURN(READ_EGR_MISC_INTR_STATUSr(unit, &rval32));
   8752         clear_field = rval32;
   8753         for (i = 0; i < COUNTOF(gh2_event_cnt_thr_ep); i++) {
   8754             cnt_th_info = &gh2_event_cnt_thr_ep[i];
   8755             if (soc_reg_field_get(unit, EGR_MISC_INTR_STATUSr, rval32,
   8756                                   cnt_th_info->sts_field)) {
   8757                 if (ce_cb) {
   8758                     (void)ce_cb(unit, cnt_th_info->stat_type,
   8759                                 cnt_th_info->th_src, multiple, idx);
   8760                 }
   8761                 soc_reg_field_set(unit, EGR_MISC_INTR_STATUSr, &clear_field,
   8762                                   cnt_th_info->sts_field, 0);
   8763             }
   8764         }
   8765         /* Clear status */
   8766         BCM_IF_ERROR_RETURN(WRITE_EGR_MISC_INTR_STATUSr(unit, clear_field));
   8767     }
   8768     if (lan_err) {
   8769         /* which lan error */
   8770         idx = -1;
   8771         BCM_IF_ERROR_RETURN(READ_IP2_INTR_STATUSr(unit, &rval64));
   8772         for (i = 0; i < COUNTOF(gh2_event_lan_err); i++) {
   8773             lan_err_info = &gh2_event_lan_err[i];
   8774             if (soc_reg64_field32_get(unit, IP2_INTR_STATUSr, rval64,
   8775                                     lan_err_info->enable_status_field)) {
   8776                 sts_reg = lan_err_info->sts_reg;
   8777                 BCM_IF_ERROR_RETURN(
   8778                     soc_reg32_get(unit, sts_reg,
   8779                                   REG_PORT_ANY, 0, &rval32));
   8780                 if (soc_reg_field_get(unit, sts_reg, rval32,
   8781                                       lan_err_info->err_field)) {
   8782                     multiple = soc_reg_field_get(unit, sts_reg, rval32,
   8783                                                  lan_err_info->mul_err_field);
   8784                     idx = soc_reg_field_get(unit, sts_reg, rval32,
   8785                                             lan_err_info->idx_field);
   8786 
   8787                     if (fe_cb) {
   8788                         (void)fe_cb(unit, lan_err_info->event_type,
   8789                                     multiple, idx);
   8790                     }
   8791                     /*
   8792                      * Disable the event mask to avoid
   8793                      * continuous wrong lan interrupt
   8794                      */
   8795                     if (bkinfo->age_enable) {
   8796                         (void)bcmi_gh2_tsn_event_mask(unit,
   8797                                                       lan_err_info->event_type,
   8798                                                       0);
   8799                         if (lan_err_info->event_type ==
   8800                             bcmTsnEventTypeSrWrongLanA) {
   8801                             bkinfo->wla_mask = 0;
   8802                         }
   8803                         if (lan_err_info->event_type ==
   8804                             bcmTsnEventTypeSrWrongLanB) {
   8805                             bkinfo->wlb_mask = 0;
   8806                         }
   8807 
   8808                     }
   8809 
   8810                     /* Clear status */
   8811                     BCM_IF_ERROR_RETURN(
   8812                         soc_reg32_set(unit, sts_reg, REG_PORT_ANY, 0, 0));
   8813                 }
   8814             }
   8815         }
   8816     }
   8817     return BCM_E_NONE;
   8818 }
   8819 
   8820 /* Check if the device supports tsn event or not */
   8821 STATIC int
   8822 bcmi_gh2_tsn_event_validate(int unit, bcmi_tsn_evt_inst_type_t inst_type)
   8823 {
   8824     switch (inst_type) {
   8825         case bcmiTsnEvtCESys:
   8826         case bcmiTsnEvtCEPort:
   8827             return BCM_E_NONE;
   8828         case bcmiTsnEvtCEFlow:
   8829         case bcmiTsnEvtWLASys:
   8830         case bcmiTsnEvtWLAFlow:
   8831         case bcmiTsnEvtWLBSys:
   8832         case bcmiTsnEvtWLBFlow:
   8833         case bcmiTsnEvtSNSys:
   8834         case bcmiTsnEvtSNFlow:
   8835             if (!soc_feature(unit, soc_feature_tsn_sr)) {
   8836                 return BCM_E_UNAVAIL;
   8837             }
   8838             return BCM_E_NONE;
   8839         default :
   8840             return BCM_E_UNAVAIL;
   8841     }
   8842 }
   8843 
   8844 STATIC int
   8845 bcmi_gh2_tsn_event_mgmt_cleanup(int unit)
   8846 {
   8847     gh2_tsn_events_bkinfo_t *bkinfo = EVENTS_BKINFO(unit);
   8848 
   8849     /* Free resource */
   8850     if (bkinfo->active_rx_fbmp != NULL) {
   8851         sal_free(bkinfo->active_rx_fbmp);
   8852         bkinfo->active_rx_fbmp = NULL;
   8853     }
   8854     if (bkinfo->wrong_lana_fbmp != NULL) {
   8855         sal_free(bkinfo->wrong_lana_fbmp);
   8856         bkinfo->wrong_lana_fbmp = NULL;
   8857     }
   8858     if (bkinfo->wrong_lanb_fbmp != NULL) {
   8859         sal_free(bkinfo->wrong_lanb_fbmp);
   8860         bkinfo->wrong_lanb_fbmp = NULL;
   8861     }
   8862     if (bkinfo->sn_reset_fbmp != NULL) {
   8863         sal_free(bkinfo->sn_reset_fbmp);
   8864         bkinfo->sn_reset_fbmp = NULL;
   8865     }
   8866 
   8867     if (bkinfo->event_mutex != NULL) {
   8868         sal_mutex_destroy(bkinfo->event_mutex);
   8869         bkinfo->event_mutex = NULL;
   8870     }
   8871 
   8872     /* Unregister event handler */
   8873     soc_gh2_tsn_event_handler_register(unit, NULL);
   8874 
   8875     return BCM_E_NONE;
   8876 }
   8877 
   8878 STATIC int
   8879 bcmi_gh2_tsn_event_mgmt_init(int unit)
   8880 {
   8881 #if defined(BCM_TSN_SR_SUPPORT)
   8882     int rx_flows, tx_flows;
   8883 #endif /* BCM_TSN_SR_SUPPORT */
   8884     gh2_tsn_events_bkinfo_t *bkinfo = EVENTS_BKINFO(unit);
   8885 
   8886     sal_memset(bkinfo, 0, sizeof(gh2_tsn_events_bkinfo_t));
   8887 #if defined(BCM_TSN_SR_SUPPORT)
   8888     /* Allocate resource */
   8889     if (soc_feature(unit, soc_feature_tsn_sr)) {
   8890         /* Get # of flows and create the flow bmp */
   8891         BCM_IF_ERROR_RETURN(
   8892             bcmi_gh2_tsn_sr_flows_get_num_flows(unit, &rx_flows, &tx_flows));
   8893         bkinfo->max_rx_flows = rx_flows;
   8894         /* Allocate flows bitmap */
   8895         bkinfo->active_rx_fbmp = (SHR_BITDCL *)
   8896             sal_alloc(SHR_BITALLOCSIZE(rx_flows), "gh2 event rx flow bmp");
   8897         if (bkinfo->active_rx_fbmp == NULL) {
   8898             LOG_ERROR(BSL_LS_BCM_TSN,
   8899                       (BSL_META("EVENT: failed to allocate flow bmp\n")));
   8900             (void)bcmi_gh2_tsn_event_mgmt_cleanup(unit);
   8901             return BCM_E_MEMORY;
   8902         }
   8903         sal_memset(bkinfo->active_rx_fbmp, 0, SHR_BITALLOCSIZE(rx_flows));
   8904         bkinfo->active_rx_fbmp_min = -1;
   8905         bkinfo->active_rx_fbmp_max = -1;
   8906 
   8907         bkinfo->wrong_lana_fbmp = (SHR_BITDCL *)
   8908             sal_alloc(SHR_BITALLOCSIZE(rx_flows),
   8909                       "gh2 event wrong lan flow bmp");
   8910         if (bkinfo->wrong_lana_fbmp == NULL) {
   8911             LOG_ERROR(BSL_LS_BCM_TSN,
   8912                       (BSL_META("EVENT: failed to allocate wrong lan fbmp\n")));
   8913             (void)bcmi_gh2_tsn_event_mgmt_cleanup(unit);
   8914             return BCM_E_MEMORY;
   8915         }
   8916         sal_memset(bkinfo->wrong_lana_fbmp, 0, SHR_BITALLOCSIZE(rx_flows));
   8917         bkinfo->wrong_lanb_fbmp = (SHR_BITDCL *)
   8918             sal_alloc(SHR_BITALLOCSIZE(rx_flows),
   8919                       "gh2 event wrong lan flow bmp");
   8920         if (bkinfo->wrong_lanb_fbmp == NULL) {
   8921             LOG_ERROR(BSL_LS_BCM_TSN,
   8922                       (BSL_META("EVENT: failed to allocate wrong lan fbmp\n")));
   8923             (void)bcmi_gh2_tsn_event_mgmt_cleanup(unit);
   8924             return BCM_E_MEMORY;
   8925         }
   8926         sal_memset(bkinfo->wrong_lanb_fbmp, 0, SHR_BITALLOCSIZE(rx_flows));
   8927         bkinfo->sn_reset_fbmp = (SHR_BITDCL *)
   8928             sal_alloc(SHR_BITALLOCSIZE(rx_flows),
   8929                       "gh2 event sn reset flow bmp");
   8930         if (bkinfo->sn_reset_fbmp == NULL) {
   8931             LOG_ERROR(BSL_LS_BCM_TSN,
   8932                       (BSL_META("EVENT: failed to allocate sn reset fbmp\n")));
   8933             (void)bcmi_gh2_tsn_event_mgmt_cleanup(unit);
   8934             return BCM_E_MEMORY;
   8935         }
   8936         sal_memset(bkinfo->sn_reset_fbmp, 0, SHR_BITALLOCSIZE(rx_flows));
   8937         /* Get the inital value of the window reset mode */
   8938         (void)bcmi_gh2_tsn_control_get(unit,
   8939                                        bcmTsnControlSrSeqNumWindowResetMode,
   8940                                        &bkinfo->window_reset_mode);
   8941         (void)bcmi_gh2_tsn_control_get(unit, bcmTsnControlSrAgeOutEnable,
   8942                                        &bkinfo->age_enable);
   8943         (void)bcmi_gh2_tsn_control_get(unit, bcmTsnControlSrAgeTickInterval,
   8944                                        &bkinfo->ageout_tick_ms);
   8945     }
   8946 #endif
   8947 
   8948     /* Create mutex for protecting event management */
   8949     bkinfo->event_mutex = sal_mutex_create("gh2 event mgmt");
   8950     if (NULL == bkinfo->event_mutex) {
   8951         LOG_ERROR(BSL_LS_BCM_TSN,
   8952                   (BSL_META("EVENT: failed to create gh2 mgmt mutex\n")));
   8953         (void)bcmi_gh2_tsn_event_mgmt_cleanup(unit);
   8954         return BCM_E_MEMORY;
   8955     }
   8956 
   8957     /* Register the event interrupt handler */
   8958     soc_gh2_tsn_event_handler_register(unit,
   8959                                        bcmi_gh2_tsn_event_interrupt_handler);
   8960 
   8961     return BCM_E_NONE;
   8962 }
   8963 
   8964 /* TSN event management platform specific data */
   8965 STATIC const bcmi_tsn_events_dev_info_t gh2_tsn_events_dev_info = {
   8966     bcmi_gh2_tsn_flow_event_notify_register,    /* register_flow_event_cb */
   8967     bcmi_gh2_tsn_cnt_excceed_notify_register,   /* register_cnt_exceed_cb */
   8968     bcmi_gh2_tsn_event_validate,                /* event validate */
   8969     bcmi_gh2_tsn_event_mask,                    /* Enable/disable event mask */
   8970     bcmi_gh2_tsn_event_rx_flow_update,          /* update_rx_flow */
   8971     bcmi_gh2_tsn_event_flow_stat_get,           /* Get the flow event state */
   8972     bcmi_gh2_tsn_event_flow_stat_clear,         /* Clear the flow event state */
   8973     bcmi_gh2_tsn_event_poll                     /* poll function */
   8974 };
   8975 
   8976 /* MTU platform specific data */
   8977 STATIC const tsn_mtu_info_t gh2_mtu_ctrl_info = {
   8978     /* per-chip control drivers */
   8979 #ifdef BCM_WARM_BOOT_SUPPORT
   8980     bcmi_gh2_tsn_egress_mtu_wb_reload,
   8981 #endif /* BCM_WARM_BOOT_SUPPORT */
   8982     GH2_LOGIC_PORT_MAX_NUM,
   8983     bcmi_gh2_tsn_mtu_profile_mem_idx_get,
   8984     bcmi_gh2_tsn_mtu_profile_create,
   8985     bcmi_gh2_tsn_mtu_profile_set,
   8986     bcmi_gh2_tsn_mtu_profile_get,
   8987     bcmi_gh2_tsn_mtu_profile_destroy,
   8988     bcmi_gh2_tsn_ingress_mtu_config_set,
   8989     bcmi_gh2_tsn_ingress_mtu_config_get,
   8990     bcmi_gh2_tsn_port_control_egress_mtu_set,
   8991     bcmi_gh2_tsn_mtu_profile_decode,
   8992     bcmi_gh2_tsn_mtu_profile_encode,
   8993     bcmi_gh2_tsn_mtu_profile_traverse,
   8994     bcmi_gh2_tsn_mtu_profmem_refcnt_get,
   8995     bcmi_gh2_tsn_port_control_ingress_mtu_set,
   8996     bcmi_gh2_tsn_port_control_ingress_mtu_get
   8997 };
   8998 
   8999 /* STU platform specific data */
   9000 STATIC const tsn_stu_info_t gh2_stu_ctrl_info = {
   9001     /* per-chip control drivers */
   9002 #ifdef BCM_WARM_BOOT_SUPPORT
   9003     bcmi_gh2_tsn_egress_stu_wb_reload,
   9004 #endif /* BCM_WARM_BOOT_SUPPORT */
   9005     GH2_LOGIC_PORT_MAX_NUM,
   9006     bcmi_gh2_tsn_stu_profile_mem_idx_get,
   9007     bcmi_gh2_tsn_stu_profile_create,
   9008     bcmi_gh2_tsn_stu_profile_set,
   9009     bcmi_gh2_tsn_stu_profile_get,
   9010     bcmi_gh2_tsn_stu_profile_destroy,
   9011     bcmi_gh2_tsn_ingress_stu_config_set,
   9012     bcmi_gh2_tsn_ingress_stu_config_get,
   9013     bcmi_gh2_tsn_port_control_egress_stu_set,
   9014     bcmi_gh2_tsn_stu_profile_decode,
   9015     bcmi_gh2_tsn_stu_profile_encode,
   9016     bcmi_gh2_tsn_stu_profile_traverse,
   9017     bcmi_gh2_tsn_stu_profmem_refcnt_get,
   9018     bcmi_gh2_tsn_port_control_ingress_stu_set,
   9019     bcmi_gh2_tsn_port_control_ingress_stu_get
   9020 };
   9021 
   9022 /* TSN flow management platform specific data */
   9023 STATIC const bcmi_tsn_flows_dev_info_t gh2_tsn_flows_dev_info = {
   9024     bcmi_gh2_tsn_flows_get_num_flows,       /* get_num_flows */
   9025     bcmi_gh2_tsn_flows_get_hw_flow_id,      /* get_hw_flow_id */
   9026     bcmi_gh2_tsn_flows_get_sw_flow_idx,     /* get_sw_flow_idx */
   9027     bcmi_gh2_tsn_flows_check_flow_config,   /* check_flow_config */
   9028     bcmi_gh2_tsn_flows_write_flow,          /* write_flow */
   9029 #ifdef BCM_WARM_BOOT_SUPPORT
   9030     bcmi_gh2_tsn_flows_read_flow,           /* read_flow */
   9031 #endif /* BCM_WARM_BOOT_SUPPORT */
   9032     bcmi_gh2_tsn_flows_clear_flow,          /* clear_flow */
   9033     bcmi_gh2_tsn_flows_clear_flow_mtu       /* clear_flow_mtu */
   9034 };
   9035 
   9036 /* per-chip TSN Priority Map driver set */
   9037 STATIC const tsn_pri_map_info_t bcmi_gh2_tsn_pri_map_info = {
   9038     "gh2_tsn_priority_map",                /* table_name */
   9039     GH2_PRI_MAP_TSN_TAB_SIZE,              /* table_size */
   9040     GH2_PRI_MAP_TSN_ENT_SIZE,              /* entry_size */
   9041     bcmi_gh2_tsn_pri_map_tsn_set,          /* tsn_pri_map_set */
   9042     bcmi_gh2_tsn_pri_map_tsn_get,          /* tsn_pri_map_get */
   9043     bcmi_gh2_tsn_pri_map_tsn_delete,       /* tsn_pri_map_delete */
   9044     bcmi_gh2_tsn_pri_map_tsn_hw_index_get, /* tsn_pri_map_hw_index_get */
   9045     bcmi_gh2_tsn_pri_map_tsn_sw_idx_get,   /* tsn_pri_map_sw_idx_get */
   9046     bcmi_gh2_tsn_pri_map_tsn_wb_hw_existed /* tsn_pri_map_wb_hw_existed */
   9047 };
   9048 
   9049 #if defined(BCM_TSN_SR_SUPPORT)
   9050 /* per-chip SR Priority Map driver set */
   9051 STATIC const tsn_pri_map_info_t bcmi_gh2_sr_pri_map_info = {
   9052     "gh2_tsn_priority_map",                /* table_name */
   9053     GH2_PRI_MAP_SR_TAB_SIZE,               /* table_size */
   9054     GH2_PRI_MAP_SR_ENT_SIZE,               /* entry_size */
   9055     bcmi_gh2_tsn_pri_map_sr_set,           /* tsn_pri_map_set */
   9056     bcmi_gh2_tsn_pri_map_sr_get,           /* tsn_pri_map_get */
   9057     bcmi_gh2_tsn_pri_map_sr_delete,        /* tsn_pri_map_delete */
   9058     bcmi_gh2_tsn_pri_map_sr_hw_index_get,  /* tsn_pri_map_hw_index_get */
   9059     bcmi_gh2_tsn_pri_map_sr_sw_idx_get,    /* tsn_pri_map_sw_idx_get */
   9060     bcmi_gh2_tsn_pri_map_sr_wb_hw_existed  /* tsn_pri_map_wb_hw_existed */
   9061 };
   9062 
   9063 /* Per-chip SR Auto Learn driver set */
   9064 STATIC const tsn_sr_auto_learn_info_t gh2_sr_auto_learn_info = {
   9065     "gh2_tsn_sr_auto_learn_platform_info",        /* table_name */
   9066     bcmi_gh2_tsn_sr_auto_learn_table_size_get,    /* table_size */
   9067     {   /* max_flow_num[bcmi_sr_auto_learn_flow_count] */
   9068         GH2_SR_AUTO_LEARN_TX_FLOW_SIZE,
   9069         GH2_SR_AUTO_LEARN_RX_FLOW_SIZE
   9070     },
   9071     bcmi_gh2_tsn_sr_auto_learn_group_port_set,    /* group_port_set */
   9072     bcmi_gh2_tsn_sr_auto_learn_group_port_delete, /* group_port_delete */
   9073     bcmi_gh2_tsn_sr_auto_learn_group_port_reset_all, /* group_port_reset_all */
   9074     bcmi_gh2_tsn_sr_auto_learn_flow_id_ctrl_set,  /* flow_id_ctrl_set */
   9075     bcmi_gh2_tsn_sr_auto_learn_flow_id_ctrl_get,  /* flow_id_ctrl_get */
   9076     bcmi_gh2_tsn_sr_auto_learn_flow_id_pool_set,  /* flow_id_pool_set */
   9077     bcmi_gh2_tsn_sr_auto_learn_flow_id_pool_get,  /* flow_id_pool_get */
   9078     bcmi_gh2_tsn_sr_auto_learn_enable,            /* enable */
   9079     bcmi_gh2_tsn_sr_auto_learn_enable_get         /* enable_get */
   9080 };
   9081 #endif /* BCM_TSN_SR_SUPPORT */
   9082 
   9083 /* per-chip MTU Priority Map driver set */
   9084 STATIC const tsn_pri_map_info_t bcmi_gh2_mtu_pri_map_info = {
   9085     "gh2_mtu_priority_map",                /* table_name */
   9086     GH2_PRI_MAP_MTU_TAB_SIZE,              /* table_size */
   9087     GH2_PRI_MAP_MTU_ENT_SIZE,              /* entry_size */
   9088     NULL,                                  /* tsn_pri_map_set */
   9089     NULL,                                  /* tsn_pri_map_get */
   9090     NULL,                                  /* tsn_pri_map_delete */
   9091     bcmi_gh2_tsn_pri_map_mtu_hw_index_get, /* tsn_pri_map_hw_index_get */
   9092     bcmi_gh2_tsn_pri_map_mtu_sw_idx_get,   /* tsn_pri_map_sw_idx_get */
   9093     NULL                                   /* tsn_pri_map_wb_hw_existed */
   9094 };
   9095 
   9096 /* per-chip STU Priority Map driver set */
   9097 STATIC const tsn_pri_map_info_t bcmi_gh2_stu_pri_map_info = {
   9098     "gh2_stu_priority_map",                /* table_name */
   9099     GH2_PRI_MAP_STU_TAB_SIZE,              /* table_size */
   9100     GH2_PRI_MAP_STU_ENT_SIZE,              /* entry_size */
   9101     NULL,                                  /* tsn_pri_map_set */
   9102     NULL,                                  /* tsn_pri_map_get */
   9103     NULL,                                  /* tsn_pri_map_delete */
   9104     bcmi_gh2_tsn_pri_map_stu_hw_index_get, /* tsn_pri_map_hw_index_get */
   9105     bcmi_gh2_tsn_pri_map_stu_sw_idx_get,   /* tsn_pri_map_sw_idx_get */
   9106     NULL                                   /* tsn_pri_map_wb_hw_existed */
   9107 };
   9108 
   9109 /* Per-chip control driver set */
   9110 STATIC const tsn_chip_ctrl_info_t gh2_chip_ctrl_info = {
   9111     /* per-chip control drivers */
   9112     bcmi_gh2_tsn_control_set,
   9113     bcmi_gh2_tsn_control_get
   9114 };
   9115 
   9116 /* GH2 TSN device info */
   9117 STATIC const bcmi_esw_tsn_dev_info_t gh2_tsn_devinfo = {
   9118 #if defined(BCM_TSN_SR_SUPPORT)
   9119     &gh2_sr_mac_proxy_info,
   9120     &gh2_tsn_sr_flows_dev_info,
   9121     &gh2_sr_port_dev_info,
   9122     &gh2_sr_auto_learn_info,
   9123 #endif /* BCM_TSN_SR_SUPPORT */
   9124     &gh2_tsn_flows_dev_info,
   9125 
   9126     {   /* tsn_pri_map_info[bcmTsnPriMapTypeCount] */
   9127         &bcmi_gh2_tsn_pri_map_info,
   9128 #if defined(BCM_TSN_SR_SUPPORT)
   9129         &bcmi_gh2_sr_pri_map_info,
   9130 #else
   9131         NULL,
   9132 #endif
   9133         &bcmi_gh2_mtu_pri_map_info,
   9134         &bcmi_gh2_stu_pri_map_info,
   9135         &bcmi_taf_gate_pri_map_info
   9136     },
   9137     &gh2_mtu_ctrl_info,
   9138     &gh2_stu_ctrl_info,
   9139     &gh2_tsn_events_dev_info,
   9140     &gh2_chip_ctrl_info
   9141 };
   9142 
   9143 /*
   9144  * Function:
   9145  *     bcmi_gh2_bkinfo_cleanup
   9146  * Purpose:
   9147  *     Clear bookkeeping.
   9148  * Parameters:
   9149  *     unit             - (IN) unit number
   9150  *     init_error       - (IN) 1 : init gh2_bkinfo failed so need cleanup
   9151  *                             0 : others
   9152  * Returns:
   9153  *     BCM_E_XXX
   9154  */
   9155 STATIC int
   9156 bcmi_gh2_bkinfo_cleanup(int unit, int init_error)
   9157 {
   9158     (void)bcmi_gh2_tsn_event_mgmt_cleanup(unit);
   9159 #if defined(BCM_TSN_SR_SUPPORT)
   9160     if (soc_feature(unit, soc_feature_tsn_sr)) {
   9161         /* SR flow management clean up */
   9162         SRFLOWS_BKINFO(unit).max_flows_rx = 0;
   9163         SRFLOWS_BKINFO(unit).max_flows_tx = 0;
   9164         (void)bcmi_gh2_tsn_sr_flows_seqnum_slices_cleanup(unit);
   9165         (void)bcmi_gh2_tsn_sr_port_prp_forwarding_cleanup(unit, init_error);
   9166     }
   9167 #endif /* BCM_TSN_SR_SUPPORT */
   9168 
   9169     /* Free and clear the  MTU & STU bookkeeping info structure */
   9170     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   9171         (void)bcmi_gh2_tsn_mtu_cleanup(unit);
   9172         (void)bcmi_gh2_tsn_stu_cleanup(unit);
   9173     }
   9174 
   9175     /* Free and clear the bookkeeping info structure */
   9176     if (gh2_tsn_bkinfo[unit] != NULL) {
   9177         TSN_FREE(unit, gh2_tsn_bkinfo[unit], 0);
   9178         gh2_tsn_bkinfo[unit] = NULL;
   9179     }
   9180 
   9181     return BCM_E_NONE;
   9182 }
   9183 
   9184 /*
   9185  * Function:
   9186  *     bcmi_gh2_tsn_info_init
   9187  * Description:
   9188  *     Setup the chip specific info.
   9189  * Parameters:
   9190  *     unit    - (IN) Unit number.
   9191  *     devinfo - (OUT) device info structure.
   9192  * Returns:
   9193  *     BCM_E_XXX
   9194  */
   9195 int
   9196 bcmi_gh2_tsn_info_init(
   9197     int unit,
   9198     const bcmi_esw_tsn_dev_info_t **devinfo)
   9199 {
   9200     gh2_tsn_bkinfo_t *bkinfo = NULL;
   9201     int rv = BCM_E_NONE;
   9202     int i;
   9203 
   9204     if (!SOC_UNIT_VALID(unit)) {
   9205         return BCM_E_UNIT;
   9206     }
   9207 
   9208     if (devinfo == NULL) {
   9209         return BCM_E_PARAM;
   9210     }
   9211 
   9212     /* GH2 TSN bookkeeping info initialization */
   9213     if (!gh2_tsn_bkinfo_initialized) {
   9214         for (i = 0; i < BCM_MAX_NUM_UNITS; i++) {
   9215             gh2_tsn_bkinfo[i] = NULL;
   9216         }
   9217         gh2_tsn_bkinfo_initialized = 1;
   9218     }
   9219 
   9220     /* Clean up the resource */
   9221     if (gh2_tsn_bkinfo[unit] != NULL) {
   9222         rv = bcmi_gh2_bkinfo_cleanup(unit, 0);
   9223         if (BCM_FAILURE(rv)) {
   9224             return rv;
   9225         }
   9226     }
   9227 
   9228     /* Allocate bookkeeping info resource */
   9229     /* coverity[bad_memset] */
   9230     TSN_ALLOC(unit, bkinfo, gh2_tsn_bkinfo_t,
   9231               sizeof(gh2_tsn_bkinfo_t),
   9232               "GH2 TSN bookkeeping info", 0, rv);
   9233     if (BCM_FAILURE(rv)) {
   9234         return rv;
   9235     }
   9236     gh2_tsn_bkinfo[unit] = bkinfo;
   9237 
   9238     /* Allocate MTU & STU bookkeeping info resource */
   9239     if (soc_feature(unit, soc_feature_tsn_mtu_stu)) {
   9240         rv = bcmi_gh2_tsn_mtu_init(unit);
   9241         if (BCM_FAILURE(rv)) {
   9242             (void)bcmi_gh2_bkinfo_cleanup(unit, 1);
   9243             return rv;
   9244         }
   9245 
   9246         rv = bcmi_gh2_tsn_stu_init(unit);
   9247         if (BCM_FAILURE(rv)) {
   9248             (void)bcmi_gh2_bkinfo_cleanup(unit, 1);
   9249             return rv;
   9250         }
   9251     }
   9252 
   9253 #if defined(BCM_TSN_SR_SUPPORT)
   9254     if (soc_feature(unit, soc_feature_tsn_sr)) {
   9255         /* SR flow management - RX seqnum slice management initialization */
   9256         rv = bcmi_gh2_tsn_sr_flows_seqnum_slices_init(unit);
   9257         if (BCM_FAILURE(rv)) {
   9258             (void)bcmi_gh2_bkinfo_cleanup(unit, 1);
   9259             return rv;
   9260         }
   9261 
   9262         /* SR PRP port forwarding initialization */
   9263         rv = bcmi_gh2_tsn_sr_port_prp_forwarding_init(unit);
   9264         if (BCM_FAILURE(rv)) {
   9265             (void)bcmi_gh2_bkinfo_cleanup(unit, 1);
   9266             return rv;
   9267         }
   9268     }
   9269 #endif /* BCM_TSN_SR_SUPPORT */
   9270 
   9271     rv = bcmi_gh2_tsn_event_mgmt_init(unit);
   9272     if (BCM_FAILURE(rv)) {
   9273         (void)bcmi_gh2_bkinfo_cleanup(unit, 1);
   9274         return rv;
   9275     }
   9276     /* Return the chip info structure */
   9277     *devinfo = &gh2_tsn_devinfo;
   9278 
   9279     return BCM_E_NONE;
   9280 }
   9281 
   9282 /*
   9283  * Function:
   9284  *     bcmi_gh2_tsn_noninit_dev_info_get
   9285  * Description:
   9286  *     Get the chip specific info without TSN module initialized.
   9287  * Parameters:
   9288  *     unit    - (IN) Unit number.
   9289  *     devinfo - (OUT) device info structure.
   9290  * Returns:
   9291  *     BCM_E_XXX
   9292  */
   9293 int
   9294 bcmi_gh2_tsn_noninit_dev_info_get(
   9295     int unit,
   9296     const bcmi_esw_tsn_dev_info_t **devinfo)
   9297 {
   9298     if (devinfo == NULL) {
   9299         return (BCM_E_PARAM);
   9300     }
   9301 
   9302     if (!SOC_UNIT_VALID(unit)) {
   9303         return BCM_E_UNIT;
   9304     }
   9305 
   9306     /* Return the chip info structure */
   9307     *devinfo = &gh2_tsn_devinfo;
   9308 
   9309     return BCM_E_NONE;
   9310 }
   9311 
   9312 /*
   9313  * Function:
   9314  *     bcmi_gh2_tsn_info_detach
   9315  * Description:
   9316  *     Detach the chip specific info.
   9317  * Parameters:
   9318  *     unit    - (IN) Unit number.
   9319  * Returns:
   9320  *     BCM_E_XXX
   9321  */
   9322 int
   9323 bcmi_gh2_tsn_info_detach(int unit)
   9324 {
   9325     /* Detach bookkeeping info */
   9326     BCM_IF_ERROR_RETURN(bcmi_gh2_bkinfo_cleanup(unit, 0));
   9327 
   9328     return BCM_E_NONE;
   9329 }
   9330 
   9331 #endif /* BCM_GREYHOUND2_SUPPORT && BCM_TSN_SUPPORT */