tsn.c (561400B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 */ 7 #include <shared/bsl.h> 8 #include <soc/drv.h> 9 #include <soc/scache.h> 10 #include <soc/profile_mem.h> 11 #include <bcm/tsn.h> 12 #include <bcm/port.h> 13 #include <bcm/error.h> 14 #include <bcm/types.h> 15 #include <bcm_int/common/multicast.h> 16 #include <bcm_int/esw_dispatch.h> 17 #include <bcm_int/esw/tsn.h> 18 #include <bcm_int/esw/tsn_taf.h> 19 #include <bcm_int/esw/tsn_stat.h> 20 #include <bcm_int/esw_dispatch.h> 21 #if defined(BCM_GREYHOUND2_SUPPORT) 22 #include <bcm_int/esw/greyhound2.h> 23 #endif /* BCM_GREYHOUND2_SUPPORT */ 24 #include <bcm_int/esw/tsn_stat.h> 25 #include <bcm/module.h> 26 #include <bcm_int/esw/switch.h> 27 28 #if defined(BCM_TSN_SUPPORT) 29 /* Function Enter/Leave Tracing */ 30 #define TSN_FUNCTION_TRACE(_u_, _str_) \ 31 do { \ 32 LOG_DEBUG(BSL_LS_BCM_TSN, \ 33 (BSL_META_U((_u_), \ 34 "%s: " _str_ "\n"), __FUNCTION__)); \ 35 } while (0) 36 37 /* Device Information NULL error handling */ 38 #define TSN_CHECK_NULL_DEV_INSTANCE(_u_, _instance_) \ 39 do { \ 40 if (NULL == (_instance_)) { \ 41 LOG_ERROR(BSL_LS_BCM_TSN, \ 42 (BSL_META_U((_u_), \ 43 "Error: NULL chip specific function \n"))); \ 44 return BCM_E_UNAVAIL; \ 45 } \ 46 } while (0) 47 48 #if defined(BCM_TSN_SR_SUPPORT) 49 50 /**************** TSN SR Mac Proxy ****************/ 51 /* 52 * TSN SR Mac Proxy entry data structure 53 */ 54 typedef struct bcmi_esw_tsn_sr_mac_proxy_entry_s { 55 bcm_pbmp_t mp_pbmp; 56 int ref_count; 57 } bcmi_esw_tsn_sr_mac_proxy_entry_t; 58 59 /* 60 * TSN SR Mac Proxy bookkeeping info data structure 61 */ 62 typedef struct bcmi_esw_tsn_sr_mac_proxy_bk_info_s { 63 sal_mutex_t sr_mp_mutex; 64 bcmi_esw_tsn_sr_mac_proxy_entry_t *sr_mp_entry; 65 int sr_mp_num; 66 } bcmi_esw_tsn_sr_mac_proxy_bk_info_t; 67 68 /* TSN SR Mac Proxy bookkeeping instance lock/unlock */ 69 #define SR_MAC_PROXY_LOCK(sr_mp_bk_info) \ 70 sal_mutex_take(sr_mp_bk_info->sr_mp_mutex, sal_mutex_FOREVER) 71 #define SR_MAC_PROXY_UNLOCK(sr_mp_bk_info) \ 72 sal_mutex_give(sr_mp_bk_info->sr_mp_mutex) 73 /************** End of TSN SR Mac Proxy **************/ 74 75 /* 76 * 77 * Seamless Redundancy (SR) Flow Management 78 */ 79 80 /* 81 * SR flow index allocation entry: 82 * We need to minimize the time taken for picking a free flow index. 83 * To achieve this, we use linked list with pre-allocated entries so that 84 * we can do it in O(1). 85 * Flow index is a zero-based serial number which can be converted to 86 * SW flow ID (used by API) or HW flow ID (maintained by the platform). 87 */ 88 typedef struct tsn_sr_flowidx_entry_s { 89 int flow_idx; 90 struct tsn_sr_flowidx_entry_s *next; 91 } tsn_sr_flowidx_entry_t; 92 93 /* SR RX/TX flowset */ 94 typedef struct tsn_sr_flowset_s { 95 bcm_tsn_pri_map_t map_id; /* priority map ID */ 96 tsn_sr_flowidx_entry_t *flow_ide; /* flow index entries */ 97 int ref_count; /* reference count */ 98 int num_flows; /* flow count (cache) */ 99 union { 100 bcm_tsn_sr_rx_flow_config_t rx; 101 bcm_tsn_sr_tx_flow_config_t tx; 102 } config; /* default flow config */ 103 sal_mutex_t mutex; /* to protect flowset slot */ 104 } tsn_sr_flowset_t; 105 106 /* SR flow direction constant used when accessing shared data structures */ 107 #define SR_FLOW_DIR_RX (0) 108 #define SR_FLOW_DIR_TX (1) 109 #define SR_FLOW_DIR_COUNT (2) 110 111 /* SR flow management book keeping */ 112 typedef struct tsn_sr_flows_bookkeeping_s { 113 /* SR flow index quick allocation */ 114 tsn_sr_flowidx_entry_t *flowids_avail[2]; /* RX/TX linked list */ 115 tsn_sr_flowidx_entry_t *flowids_allocated; /* for freeing */ 116 117 /* SR flowset entries */ 118 tsn_sr_flowset_t *flowsets[2]; /* RX/TX arrays */ 119 120 /* SR flow entries (not shared since the type is quite different) */ 121 bcmi_tsn_sr_rx_flow_t *flows_rx; /* indexed array */ 122 sal_mutex_t *flows_rx_mutex; /* for RX flow slot */ 123 bcmi_tsn_sr_tx_flow_t *flows_tx; /* indexed array */ 124 sal_mutex_t *flows_tx_mutex; /* for TX flow slot */ 125 126 /* for efficiency */ 127 int max_flows[2]; /* RX/TX */ 128 129 /* To protect flow list (allocate/free) */ 130 sal_mutex_t fmgmt_mutex; 131 } tsn_sr_flows_bookkeeping_t; 132 133 #ifdef BCM_WARM_BOOT_SUPPORT 134 /* SR RX flowset for warmboot */ 135 typedef struct tsn_sr_rx_flowset_wb_s { 136 int flow_idx; /* Flow index */ 137 bcm_tsn_pri_map_t map_id; /* priority map ID */ 138 bcm_tsn_sr_rx_flow_config_t config; /* Flow default config */ 139 } tsn_sr_rx_flowset_wb_t; 140 141 /* SR TX flowset for warmboot */ 142 typedef struct tsn_sr_tx_flowset_wb_s { 143 int flow_idx; /* Flow index */ 144 bcm_tsn_pri_map_t map_id; /* priority map ID */ 145 bcm_tsn_sr_tx_flow_config_t config; /* Flow default config */ 146 } tsn_sr_tx_flowset_wb_t; 147 #endif /* BCM_WARM_BOOT_SUPPORT */ 148 149 /* 150 * 151 * Seamless Redundancy (SR) Auto Learn Management 152 */ 153 154 /* 155 * Structure definition for SR Auto Learn bookkeeping info 156 */ 157 typedef struct bcmi_esw_tsn_sr_auto_learn_group_bk_data_s { 158 int group_id; 159 int redundant_pro_idx[bcmi_sr_auto_learn_group_count]; 160 int interlink_pro_idx; 161 bcm_tsn_sr_auto_learn_group_config_t config; 162 } bcmi_esw_tsn_sr_auto_learn_group_bk_data_t; 163 164 typedef struct bcmi_esw_tsn_sr_auto_learn_bk_data_s { 165 int enabled; 166 bcm_tsn_sr_auto_learn_config_t config; 167 uint32 flowsets_cnt[bcmi_sr_auto_learn_flow_count]; 168 bcm_tsn_sr_flowset_t *flowsets[bcmi_sr_auto_learn_flow_count]; 169 } bcmi_esw_tsn_sr_auto_learn_bk_data_t; 170 171 typedef struct bcmi_esw_tsn_sr_auto_learn_bk_s { 172 SHR_BITDCL *intf_bitmap; 173 bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *group_data; 174 uint32 valid_count; 175 uint32 valid_sw_idx_start; 176 uint32 valid_sw_idx_end; 177 uint32 empty_sw_idx_start; 178 uint32 empty_sw_idx_end; 179 bcmi_esw_tsn_sr_auto_learn_bk_data_t data; 180 sal_mutex_t bk_mutex; 181 sal_mutex_t mutex; 182 int initialized; /* for lazy initialization */ 183 } bcmi_esw_tsn_sr_auto_learn_bk_t; 184 #endif /* BCM_TSN_SR_SUPPORT */ 185 186 /* 187 * 188 * TSN Flow (TSN Circuit ID) Management 189 */ 190 191 /* 192 * TSN flow index allocation entry (similar mechanism as SR flows) 193 */ 194 typedef struct tsn_flowidx_entry_s { 195 int flow_idx; 196 struct tsn_flowidx_entry_s *next; 197 } tsn_flowidx_entry_t; 198 199 /* TSN flowset */ 200 typedef struct tsn_flowset_s { 201 bcm_tsn_pri_map_t map_id; /* priorty map ID */ 202 tsn_flowidx_entry_t *flow_ide; /* flow index entries */ 203 int ref_count; /* reference count */ 204 int num_flows; /* flow count (cache) */ 205 bcm_tsn_flow_config_t config; /* default flow config */ 206 sal_mutex_t mutex; /* to protect flowset slot */ 207 } tsn_flowset_t; 208 209 /* TSN flow management book keeping */ 210 typedef struct tsn_flows_bookkeeping_s { 211 /* TSN flow index quick allocation */ 212 tsn_flowidx_entry_t *flowids_avail; /* linked list */ 213 tsn_flowidx_entry_t *flowids_allocated; /* for freeing */ 214 215 /* TSN flowset entries */ 216 tsn_flowset_t *flowsets; /* indexed arrays */ 217 218 /* TSN flow entries (not shared since the type is quite different) */ 219 bcm_tsn_flow_config_t *flows; /* indexed array */ 220 sal_mutex_t *flows_mutex; /* for flow slot */ 221 222 /* for efficiency */ 223 int max_flows; 224 225 /* To protect flow list (allocate/free) */ 226 sal_mutex_t fmgmt_mutex; 227 } tsn_flows_bookkeeping_t; 228 229 #ifdef BCM_WARM_BOOT_SUPPORT 230 /* TSN flowset for warmboot */ 231 typedef struct tsn_flowset_wb_s { 232 int flow_idx; /* Flow index */ 233 bcm_tsn_pri_map_t map_id; /* priority map ID */ 234 bcm_tsn_flow_config_t config; /* Flow default config */ 235 } tsn_flowset_wb_t; 236 #endif /* BCM_WARM_BOOT_SUPPORT */ 237 238 /* Initialization flag for TSN bookkeeping info structure */ 239 static int tsn_bk_info_initialized = 0; 240 241 /* SW structure for storing the ingress & egress mtu priority map config ID */ 242 typedef struct bcmi_esw_tsn_mtu_bk_info_s { 243 int *mtu_refcount[bcmTsnMtuProfileTypeCount]; 244 bcm_tsn_pri_map_t *pri_map_port; 245 sal_mutex_t mutex; 246 } bcmi_esw_tsn_mtu_bk_info_t; 247 248 /* SW structure for storing the ingress & egress stu priority map config ID */ 249 typedef struct bcmi_esw_tsn_stu_bk_info_s { 250 int *stu_refcount[bcmTsnStuProfileTypeCount]; 251 bcm_tsn_pri_map_t *pri_map_port; 252 sal_mutex_t mutex; 253 } bcmi_esw_tsn_stu_bk_info_t; 254 255 /* 256 * Structure definition for Priority Map bookkeeping info 257 */ 258 typedef struct bcmi_esw_tsn_pri_map_bk_info_data_s { 259 bcm_tsn_pri_map_t map_id; 260 bcm_tsn_pri_map_config_t config; 261 uint32 ref_cnt; 262 } bcmi_esw_tsn_pri_map_bk_info_data_t; 263 264 typedef struct bcmi_esw_tsn_pri_map_bk_info_s { 265 SHR_BITDCL *intf_bitmap[bcmTsnPriMapTypeCount]; 266 bcmi_esw_tsn_pri_map_bk_info_data_t *data[bcmTsnPriMapTypeCount]; 267 uint32 valid_count[bcmTsnPriMapTypeCount]; 268 uint32 valid_sw_idx_start[bcmTsnPriMapTypeCount]; 269 uint32 valid_sw_idx_end[bcmTsnPriMapTypeCount]; 270 uint32 empty_sw_idx_start[bcmTsnPriMapTypeCount]; 271 uint32 empty_sw_idx_end[bcmTsnPriMapTypeCount]; 272 sal_mutex_t mutex, bk_mutex; 273 } bcmi_esw_tsn_pri_map_bk_info_t; 274 275 /* 276 * 277 * TSN Event Management 278 */ 279 280 /* 281 * Structure definition for event instance info 282 * NOTE: event instance indicats the event with speficied source type 283 */ 284 typedef struct tsn_evt_inst_s { 285 struct tsn_evt_inst_s *next; /* next instance */ 286 bcm_tsn_event_cb cb; /* registered callback */ 287 void *user_data; /* registered user data */ 288 bcm_port_t port; /* specified port */ 289 bcm_tsn_sr_flow_t sr_flow; /* specified sr_flow */ 290 } tsn_evt_inst_t; 291 292 /* event instance resource allocation info */ 293 typedef struct tsn_evt_inst_alloc_s { 294 bcmi_tsn_evt_inst_type_t inst_type; /* event instance type */ 295 bcm_tsn_event_type_t evt_type; /* associated event type */ 296 int source_type; /* associated source type */ 297 int inst_limits; /* pre-allocated limits */ 298 } tsn_evt_inst_alloc_t; 299 300 /* Structure definition for registered event instance info */ 301 typedef struct tsn_evt_regist_s { 302 bcmi_tsn_evt_inst_type_t inst_type; /* event instance type */ 303 bcm_tsn_event_type_t evt_type; /* associated event type */ 304 int source_type; /* associated source type */ 305 tsn_evt_inst_t *evt_inst; /* event instance link list */ 306 sal_mutex_t mutex; /* protect event instance link list */ 307 } tsn_evt_regist_t; 308 309 /* Structure definition for registered event statistics info */ 310 typedef struct tsn_evt_stat_s { 311 int event_ref; /* event reference count */ 312 int *port_ref; /* port basis event referece count */ 313 int *flow_ref; /* flow basis event referece count */ 314 SHR_BITDCL *pbmp; /* port bitmap on this event */ 315 SHR_BITDCL *fbmp; /* flow bitmap on this event */ 316 SHR_BITDCL *ffbmp; /* filter flow bitmap on this event */ 317 } tsn_evt_stat_t; 318 319 /* Structure definition for event management bookkeeping info */ 320 typedef struct tsn_event_bk_s { 321 /* Central event instance resource */ 322 tsn_evt_inst_t *einst_avail[bcmiTsnEvtCount]; /* event linked list */ 323 tsn_evt_inst_t *einst_allocated; /* for freeing */ 324 325 /* Registered event arrays */ 326 tsn_evt_regist_t eregist[bcmiTsnEvtCount]; 327 int max_flows; /* convenient to allocate flow database */ 328 int max_rx_flows; /* use to differentiate the flow dir */ 329 int max_ports; /* convenient to allocate port database */ 330 331 tsn_evt_stat_t evt_stat[bcmTsnEventTypeCount]; 332 sal_mutex_t evt_mutex; 333 334 /* Kept the previous state used to enable age-out event poll */ 335 uint32 pre_enable; 336 uint32 pre_interval; 337 uint32 pre_rmode; 338 339 /* Poll funtion information */ 340 VOL sal_thread_t poll_tid; /* thread id */ 341 VOL sal_usecs_t poll_interval; /* wakeup interval */ 342 sal_sem_t poll_notify; /* notify signal */ 343 int poll_enable; /* poll thread is enable or not */ 344 } tsn_event_bk_t; 345 346 /* 347 * Structure definition for TSN bookkeeping info, 348 * including bookkeeping and chip specific info 349 */ 350 typedef struct bcmi_esw_tsn_bk_info_s { 351 /* bookkeeping structure defined below */ 352 #if defined(BCM_TSN_SR_SUPPORT) 353 /* TSN SR MAC Proxy bookkeeping info */ 354 bcmi_esw_tsn_sr_mac_proxy_bk_info_t tsn_sr_mac_proxy_bk_info; 355 /* TSN SR flow management */ 356 tsn_sr_flows_bookkeeping_t sr_flows; 357 /* TSN SR Auto Learn management */ 358 bcmi_esw_tsn_sr_auto_learn_bk_t tsn_sr_auto_learn_bk_info; 359 #endif /* BCM_TSN_SR_SUPPORT */ 360 /* TSN flow management */ 361 tsn_flows_bookkeeping_t tsn_flows; 362 363 bcmi_esw_tsn_pri_map_bk_info_t tsn_pri_map_bk_info; 364 365 /* MTU & STU management */ 366 bcmi_esw_tsn_mtu_bk_info_t tsn_mtu_bk_info; 367 bcmi_esw_tsn_stu_bk_info_t tsn_stu_bk_info; 368 369 /* Event management */ 370 tsn_event_bk_t tsn_events; 371 /* device specific info */ 372 const bcmi_esw_tsn_dev_info_t *tsn_dev_info; 373 } bcmi_esw_tsn_bk_info_t; 374 375 /* TSN bookkeeping info */ 376 STATIC bcmi_esw_tsn_bk_info_t *tsn_bk_info[BCM_MAX_NUM_UNITS] = { NULL }; 377 378 #if defined(BCM_TSN_SR_SUPPORT) 379 380 /* SW SR Flow ID conversion: flow ID is 1-based (0 is invalid) */ 381 #define SR_FLOW_ID_TX_MASK 0x40000000 382 #define SR_FLOW_ID_FROM_IDX(_dir, _idx) \ 383 ((bcm_tsn_sr_flow_t)( \ 384 ((_idx) | ((_dir) == SR_FLOW_DIR_TX ? SR_FLOW_ID_TX_MASK : 0)) + 1)) 385 #define SR_FLOW_ID_TO_DIR(_id) \ 386 ((((int)(_id)) & SR_FLOW_ID_TX_MASK) ? SR_FLOW_DIR_TX : SR_FLOW_DIR_RX) 387 #define SR_FLOW_ID_TO_IDX(_id) \ 388 ((((int)(_id)) & (~SR_FLOW_ID_TX_MASK)) - 1) 389 390 /* SR Flowset ID conversion: use the same encoding as SW flow ID */ 391 #define SR_FLOWSET_ID_FROM_IDX(_dir, _idx) \ 392 ((bcm_tsn_sr_flowset_t)SR_FLOW_ID_FROM_IDX((_dir), (_idx))) 393 #define SR_FLOWSET_ID_TO_DIR(_id) SR_FLOW_ID_TO_DIR((bcm_tsn_sr_flow_t)(_id)) 394 #define SR_FLOWSET_ID_TO_IDX(_id) SR_FLOW_ID_TO_IDX((bcm_tsn_sr_flow_t)(_id)) 395 396 /* SR flow management bookkeeping info quick access */ 397 #define SR_FLOW_MGMT_BKINFO(_unit_) \ 398 (&tsn_bk_info[_unit_]->sr_flows) 399 #define SR_FLOW_MGMT_DEVINFO(_unit_) \ 400 tsn_bk_info[_unit_]->tsn_dev_info->sr_flows_info 401 402 /* Protecting the global SR flow management */ 403 #define SR_FLOW_MGMT_LOCK(_unit_) \ 404 sal_mutex_take(SR_FLOW_MGMT_BKINFO(_unit_)->fmgmt_mutex, sal_mutex_FOREVER) 405 #define SR_FLOW_MGMT_UNLOCK(_unit_) \ 406 sal_mutex_give(SR_FLOW_MGMT_BKINFO(_unit_)->fmgmt_mutex) 407 408 /* Protecting an SR flowset slot */ 409 #define SR_FLOWSET_LOCK(_fsp_) \ 410 sal_mutex_take((_fsp_)->mutex, sal_mutex_FOREVER) 411 #define SR_FLOWSET_UNLOCK(_fsp_) \ 412 sal_mutex_give((_fsp_)->mutex) 413 414 /* Protecting an SR flow slot */ 415 #define SR_FLOW_RX_LOCK(_unit_, _idx_) \ 416 sal_mutex_take(SR_FLOW_MGMT_BKINFO(_unit_)->flows_rx_mutex[_idx_], \ 417 sal_mutex_FOREVER) 418 #define SR_FLOW_RX_UNLOCK(_unit_, _idx_) \ 419 sal_mutex_give(SR_FLOW_MGMT_BKINFO(_unit_)->flows_rx_mutex[_idx_]) 420 #define SR_FLOW_TX_LOCK(_unit_, _idx_) \ 421 sal_mutex_take(SR_FLOW_MGMT_BKINFO(_unit_)->flows_tx_mutex[_idx_], \ 422 sal_mutex_FOREVER) 423 #define SR_FLOW_TX_UNLOCK(_unit_, _idx_) \ 424 sal_mutex_give(SR_FLOW_MGMT_BKINFO(_unit_)->flows_tx_mutex[_idx_]) 425 426 /* Valid flags for bcm_tsn_sr_auto_learn_group_config_t */ 427 #define BCMI_TSN_SR_AUTO_LEARN_GROUP_VALID_FLAGS \ 428 (BCM_TSN_SR_AUTO_LEARN_GROUP_PROXY_FILTERING) 429 430 /* 431 * SR Auto Learn Group id encoding: 432 * 1-bit (reserved) + 1-bit'1 (Auto Learn Magic Bit) + 22-bit (reserved) 433 * + 8-bit sw_idx 434 */ 435 #define BCMI_SR_AUTO_LEARN_SW_IDX_MASK (0xFF) 436 #define BCMI_SR_AUTO_LEARN_SHIFT (30) 437 #define BCMI_SR_AUTO_LEARN (1) 438 439 /* 440 * SR Auto Learn Group related define 441 */ 442 #define BCMI_SR_AUTO_LEARN_GROUP_ID_INVALID (-1) 443 #define BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID (-1) 444 445 /* 446 * Translate between SR Auto Learn Group id and SW_IDX 447 * The sw_idx is not the hardware index of register/memory. 448 * It just represents the array index of SW bookkeeping group_data[sw_idx] 449 */ 450 #define GROUP_ID_TO_SW_IDX(_group_id_) \ 451 ((_group_id_) & BCMI_SR_AUTO_LEARN_SW_IDX_MASK) 452 453 #define SW_IDX_TO_GROUP_ID(_sw_idx_) \ 454 ((_sw_idx_) | BCMI_SR_AUTO_LEARN << BCMI_SR_AUTO_LEARN_SHIFT) 455 456 #define AUTO_LEARN_DEV_INIT(_u_) \ 457 do { \ 458 if (!soc_feature(unit, soc_feature_tsn_sr) || \ 459 !soc_feature(unit, soc_feature_tsn_sr_auto_learn)) { \ 460 LOG_ERROR(BSL_LS_BCM_TSN, \ 461 (BSL_META_U(unit, \ 462 "SR Auto Learn Error:" \ 463 " feature not enable \n"))); \ 464 return BCM_E_UNAVAIL; \ 465 } \ 466 if (!tsn_bk_info[(_u_)] || \ 467 !tsn_bk_info[(_u_)]->tsn_dev_info || \ 468 !tsn_bk_info[(_u_)]->tsn_dev_info->tsn_sr_auto_learn_info) { \ 469 LOG_ERROR(BSL_LS_BCM_TSN, \ 470 (BSL_META_U(unit, \ 471 "SR Auto Learn Error:" \ 472 " dev not initialized\n"))); \ 473 return BCM_E_UNAVAIL; \ 474 } \ 475 } while (0) 476 477 #define AUTO_LEARN_INIT(_u_) \ 478 do { \ 479 if (!soc_feature(unit, soc_feature_tsn_sr) || \ 480 !soc_feature(unit, soc_feature_tsn_sr_auto_learn)) { \ 481 LOG_ERROR(BSL_LS_BCM_TSN, \ 482 (BSL_META_U(unit, \ 483 "SR Auto Learn Error:" \ 484 " feature not enable \n"))); \ 485 return BCM_E_UNAVAIL; \ 486 } \ 487 if (!tsn_bk_info[(_u_)] || \ 488 !tsn_bk_info[(_u_)]->tsn_sr_auto_learn_bk_info.initialized) { \ 489 LOG_WARN(BSL_LS_BCM_TSN, \ 490 (BSL_META_U(unit, \ 491 "SR Auto Learn Warning:" \ 492 " not initialized\n"))); \ 493 return BCM_E_INIT; \ 494 } \ 495 if (!tsn_bk_info[(_u_)] || \ 496 !tsn_bk_info[(_u_)]->tsn_dev_info || \ 497 !tsn_bk_info[(_u_)]->tsn_dev_info->tsn_sr_auto_learn_info || \ 498 !tsn_bk_info[(_u_)]->tsn_sr_auto_learn_bk_info.intf_bitmap || \ 499 !tsn_bk_info[(_u_)]->tsn_sr_auto_learn_bk_info.group_data) { \ 500 LOG_ERROR(BSL_LS_BCM_TSN, \ 501 (BSL_META_U(unit, \ 502 "SR Auto Learn Error:" \ 503 " not allocated\n"))); \ 504 return BCM_E_UNAVAIL; \ 505 } \ 506 } while (0) 507 508 /* SR Auto Learn instance fetch/lock/unlock */ 509 #define AUTO_LEARN_BK_INFO(_u_) \ 510 (&tsn_bk_info[(_u_)]->tsn_sr_auto_learn_bk_info) 511 512 /* Protect bcmi_esw_tsn_pri_map_bk_info_t */ 513 #define AUTO_LEARN_BK_LOCK(_u_) \ 514 (sal_mutex_take(AUTO_LEARN_BK_INFO((_u_))->bk_mutex, sal_mutex_FOREVER)) 515 516 #define AUTO_LEARN_BK_UNLOCK(_u_) \ 517 (sal_mutex_give(AUTO_LEARN_BK_INFO((_u_))->bk_mutex)) 518 519 /* 520 * make bcmi_esw_tsn_sr_auto_learn_create/set/get/destroy/traverse 521 * to be atomic executed 522 */ 523 #define AUTO_LEARN_LOCK(_u_) \ 524 (sal_mutex_take(AUTO_LEARN_BK_INFO((_u_))->mutex, sal_mutex_FOREVER)) 525 526 #define AUTO_LEARN_UNLOCK(_u_) \ 527 (sal_mutex_give(AUTO_LEARN_BK_INFO((_u_))->mutex)) 528 529 /* 530 * SR Auto Learn usage bitmap operations 531 */ 532 #define AUTO_LEARN_INTF_USED_GET(_u_, _intf_) \ 533 ((AUTO_LEARN_BK_INFO(_u_)->intf_bitmap) ? \ 534 (SHR_BITGET(AUTO_LEARN_BK_INFO(_u_)->intf_bitmap, (_intf_))) : 0) 535 #define AUTO_LEARN_INTF_USED_SET(_u_, _intf_) \ 536 (SHR_BITSET(AUTO_LEARN_BK_INFO(_u_)->intf_bitmap, (_intf_))) 537 #define AUTO_LEARN_INTF_USED_CLR(_u_, _intf_) \ 538 (SHR_BITCLR(AUTO_LEARN_BK_INFO(_u_)->intf_bitmap, (_intf_))) 539 540 #endif /* BCM_TSN_SR_SUPPORT */ 541 542 /* TSN SW Flow ID conversion: flow ID is 1-based (0 is invalid) */ 543 #define TSN_FLOW_ID_FROM_IDX(_idx) ((bcm_tsn_flow_t)((_idx) + 1)) 544 #define TSN_FLOW_ID_TO_IDX(_id) ((int)(_id) - 1) 545 546 /* Flowset ID conversion: use the same encoding as SW flow ID */ 547 #define TSN_FLOWSET_ID_FROM_IDX(_idx) \ 548 ((bcm_tsn_flowset_t)TSN_FLOW_ID_FROM_IDX(_idx)) 549 #define TSN_FLOWSET_ID_TO_IDX(_id) \ 550 TSN_FLOW_ID_TO_IDX((bcm_tsn_flow_t)(_id)) 551 552 /* TSN flow management bookkeeping info quick access */ 553 #define TSN_FLOW_MGMT_BKINFO(_unit_) \ 554 (&tsn_bk_info[_unit_]->tsn_flows) 555 #define TSN_FLOW_MGMT_DEVINFO(_unit_) \ 556 tsn_bk_info[_unit_]->tsn_dev_info->tsn_flows_info 557 558 /* Protecting the global TSN flow management */ 559 #define TSN_FLOW_MGMT_LOCK(_unit_) \ 560 sal_mutex_take(TSN_FLOW_MGMT_BKINFO(_unit_)->fmgmt_mutex, sal_mutex_FOREVER) 561 #define TSN_FLOW_MGMT_UNLOCK(_unit_) \ 562 sal_mutex_give(TSN_FLOW_MGMT_BKINFO(_unit_)->fmgmt_mutex) 563 564 /* Protecting a TSN flowset slot */ 565 #define TSN_FLOWSET_LOCK(_fsp_) \ 566 sal_mutex_take((_fsp_)->mutex, sal_mutex_FOREVER) 567 #define TSN_FLOWSET_UNLOCK(_fsp_) \ 568 sal_mutex_give((_fsp_)->mutex) 569 570 /* Protecting a TSN flow slot */ 571 #define TSN_FLOW_LOCK(_unit_, _idx_) \ 572 sal_mutex_take(TSN_FLOW_MGMT_BKINFO(_unit_)->flows_mutex[_idx_], \ 573 sal_mutex_FOREVER) 574 #define TSN_FLOW_UNLOCK(_unit_, _idx_) \ 575 sal_mutex_give(TSN_FLOW_MGMT_BKINFO(_unit_)->flows_mutex[_idx_]) 576 577 /* 578 * Priority Map id encoding: 579 * 1bit (valid) + 3-bit bcm_tsn_pri_map_type + 12-bit (reserved) 580 * + 16-bit sw_idx 581 */ 582 #define BCMI_TSN_PRI_MAP_SW_IDX_MASK (0xFFFF) 583 #define BCMI_TSN_PRI_MAP_TYPE_SHIFT (28) 584 #define BCMI_TSN_PRI_MAP_TYPE_MASK (0x7) 585 #define BCMI_TSN_PRI_MAP_VALID_SHIFT (31) 586 587 /* 588 * Translate between Priority Map ID and SW_IDX & Priority Map Type 589 * The sw_idx is not the hardware index of register/memory. 590 * It just represents the array index of SW bookkeeping data[map_type][sw_idx] 591 */ 592 #define MAP_ID_TO_SW_IDX(_id_) \ 593 ((_id_) & BCMI_TSN_PRI_MAP_SW_IDX_MASK) 594 595 #define SW_IDX_TO_MAP_ID(_id_, _map_type_) \ 596 ((_id_) | \ 597 ((_map_type_) << BCMI_TSN_PRI_MAP_TYPE_SHIFT) | \ 598 (0x1 << BCMI_TSN_PRI_MAP_VALID_SHIFT)) 599 600 #define PRI_MAP_TYPE_GET(_id_) \ 601 (((_id_) >> BCMI_TSN_PRI_MAP_TYPE_SHIFT) & BCMI_TSN_PRI_MAP_TYPE_MASK) 602 603 #define PRI_MAP_ID_IS_TYPE(_id_, _map_type_) \ 604 (PRI_MAP_TYPE_GET((_id_)) == (_map_type_)) 605 606 #define PRI_MAP_INIT(_u_, _map_type_) \ 607 do { \ 608 if (!soc_feature((_u_), soc_feature_tsn_sr) && \ 609 (_map_type_) == bcmTsnPriMapTypeSrFlow) { \ 610 LOG_ERROR(BSL_LS_BCM_TSN, \ 611 (BSL_META_U((_u_), \ 612 "TSN Priority Map Error:" \ 613 " feature not enable \n"))); \ 614 return BCM_E_UNAVAIL; \ 615 } \ 616 if (!soc_feature((_u_), soc_feature_tsn_mtu_stu) && \ 617 ((_map_type_) == bcmTsnPriMapTypeEgressMtuProfile || \ 618 (_map_type_) == bcmTsnPriMapTypeEgressStuProfile)) { \ 619 LOG_ERROR(BSL_LS_BCM_TSN, \ 620 (BSL_META_U((_u_), \ 621 "TSN Priority Map Error:" \ 622 " feature not enable \n"))); \ 623 return BCM_E_UNAVAIL; \ 624 } \ 625 if (!soc_feature((_u_), soc_feature_tsn_taf) && \ 626 (_map_type_) == bcmTsnPriMapTypeTafGate) { \ 627 LOG_ERROR(BSL_LS_BCM_TSN, \ 628 (BSL_META_U((_u_), \ 629 "TSN Priority Map Error:" \ 630 " feature not enable \n"))); \ 631 return BCM_E_UNAVAIL; \ 632 } \ 633 if (!tsn_bk_info[_u_]->tsn_dev_info || \ 634 !tsn_bk_info[_u_]->tsn_dev_info->tsn_pri_map_info[_map_type_] || \ 635 !tsn_bk_info[_u_]->tsn_pri_map_bk_info.data || \ 636 !tsn_bk_info[_u_]->tsn_pri_map_bk_info.intf_bitmap) { \ 637 LOG_ERROR(BSL_LS_BCM_TSN, \ 638 (BSL_META_U((_u_), \ 639 "TSN Priority Map Error:" \ 640 " not allocated\n"))); \ 641 return BCM_E_UNAVAIL; \ 642 } \ 643 } while (0) 644 645 /* Priority Map instance fetch/lock/unlock */ 646 #define PRI_MAP_BK_INFO(_u_) \ 647 (&tsn_bk_info[(_u_)]->tsn_pri_map_bk_info) 648 649 /* Protect bcmi_esw_tsn_pri_map_bk_info_t */ 650 #define PRI_MAP_BK_LOCK(_u_) \ 651 sal_mutex_take(PRI_MAP_BK_INFO((_u_))->bk_mutex, sal_mutex_FOREVER) 652 653 #define PRI_MAP_BK_UNLOCK(_u_) \ 654 sal_mutex_give(PRI_MAP_BK_INFO((_u_))->bk_mutex) 655 656 /* 657 * make bcmi_esw_tsn_pri_map_create/set/get/destroy/traverse 658 * to be atomic executed 659 */ 660 #define PRI_MAP_LOCK(_u_) \ 661 sal_mutex_take(PRI_MAP_BK_INFO((_u_))->mutex, sal_mutex_FOREVER) 662 663 #define PRI_MAP_UNLOCK(_u_) \ 664 sal_mutex_give(PRI_MAP_BK_INFO((_u_))->mutex) 665 666 /* Priority Map usage bitmap operations */ 667 #define PRI_MAP_INTF_GET(_u_, _map_type_, _intf_) \ 668 ((PRI_MAP_BK_INFO(_u_)->intf_bitmap[(_map_type_)]) ? \ 669 (SHR_BITGET(PRI_MAP_BK_INFO(_u_)->intf_bitmap[_map_type_], (_intf_))) : 0) 670 #define PRI_MAP_INTF_SET(_u_, _map_type_, _intf_) \ 671 SHR_BITSET(PRI_MAP_BK_INFO(_u_)->intf_bitmap[(_map_type_)], (_intf_)) 672 #define PRI_MAP_INTF_CLR(_u_, _map_type_, _intf_) \ 673 SHR_BITCLR(PRI_MAP_BK_INFO(_u_)->intf_bitmap[(_map_type_)], (_intf_)) 674 675 /* MTU Operation Check */ 676 #define MTU_BK_INIT(_u_, _t_) \ 677 do { \ 678 if ((_t_) != bcmTsnMtuProfileTypeIngress && \ 679 (_t_) != bcmTsnMtuProfileTypeEgress) { \ 680 return BCM_E_PARAM; \ 681 } \ 682 if ((NULL == tsn_bk_info[(_u_)]->tsn_mtu_bk_info.mtu_refcount[_t_])) {\ 683 LOG_ERROR(BSL_LS_BCM_TSN, \ 684 (BSL_META_U((_u_), \ 685 "MTU Error:" \ 686 " bookeeping not allocated\n"))); \ 687 return BCM_E_UNAVAIL; \ 688 } \ 689 } while (0) 690 691 #define MTU_DEV_INIT(_u_) \ 692 do { \ 693 const tsn_mtu_info_t *mtu_info; \ 694 if (tsn_bk_info[(_u_)]->tsn_dev_info == NULL) { \ 695 LOG_ERROR(BSL_LS_BCM_TSN, \ 696 (BSL_META_U((_u_), \ 697 "MTU Error:" \ 698 " tsn_dev_info not allocated\n"))); \ 699 return BCM_E_UNAVAIL; \ 700 } \ 701 mtu_info = tsn_bk_info[(_u_)]->tsn_dev_info->tsn_mtu_info; \ 702 if (mtu_info == NULL) { \ 703 LOG_ERROR(BSL_LS_BCM_TSN, \ 704 (BSL_META_U((_u_), \ 705 "MTU Error:" \ 706 " tsn_mtu_info not allocated\n"))); \ 707 return BCM_E_UNAVAIL; \ 708 } \ 709 if ((NULL == mtu_info->mtu_profile_mem_idx_get) || \ 710 (NULL == mtu_info->mtu_profile_create) || \ 711 (NULL == mtu_info->mtu_profile_set) || \ 712 (NULL == mtu_info->mtu_profile_get) || \ 713 (NULL == mtu_info->mtu_profile_destroy) || \ 714 (NULL == mtu_info->ingress_mtu_config_set) || \ 715 (NULL == mtu_info->ingress_mtu_config_get) || \ 716 (NULL == mtu_info->egress_mtu_port_control_set) || \ 717 (NULL == mtu_info->mtu_profile_decode) || \ 718 (NULL == mtu_info->mtu_profile_encode) || \ 719 (NULL == mtu_info->mtu_profile_traverse) || \ 720 (NULL == mtu_info->mtu_profile_mem_refcnt_get)) { \ 721 LOG_ERROR(BSL_LS_BCM_TSN, \ 722 (BSL_META_U((_u_), \ 723 "MTU Error:" \ 724 " dev info not allocated\n"))); \ 725 return BCM_E_UNAVAIL; \ 726 } \ 727 } while (0) 728 729 /* MTU instance fetch/lock/unlock */ 730 #define MTU_BK_INFO(_u_) \ 731 (&tsn_bk_info[(_u_)]->tsn_mtu_bk_info) 732 733 #define MTU_BK_LOCK(_u_) \ 734 sal_mutex_take(MTU_BK_INFO((_u_))->mutex, sal_mutex_FOREVER) 735 736 #define MTU_BK_UNLOCK(_u_) \ 737 sal_mutex_give(MTU_BK_INFO((_u_))->mutex) 738 739 /* STU Operation Check */ 740 #define STU_BK_INIT(_u_, _t_) \ 741 do { \ 742 if ((_t_) != bcmTsnStuProfileTypeIngress && \ 743 (_t_) != bcmTsnStuProfileTypeEgress) { \ 744 return BCM_E_PARAM; \ 745 } \ 746 if ((NULL == tsn_bk_info[(_u_)]->tsn_stu_bk_info.stu_refcount[_t_])) {\ 747 LOG_ERROR(BSL_LS_BCM_TSN, \ 748 (BSL_META_U((_u_), \ 749 "STU Error:" \ 750 " bookeeping not allocated\n"))); \ 751 return BCM_E_UNAVAIL; \ 752 } \ 753 } while (0) 754 755 #define STU_DEV_INIT(_u_) \ 756 do { \ 757 const tsn_stu_info_t *stu_info; \ 758 if (tsn_bk_info[(_u_)]->tsn_dev_info == NULL) { \ 759 LOG_ERROR(BSL_LS_BCM_TSN, \ 760 (BSL_META_U((_u_), \ 761 "STU Error:" \ 762 " tsn_dev_info not allocated\n"))); \ 763 return BCM_E_UNAVAIL; \ 764 } \ 765 stu_info = tsn_bk_info[(_u_)]->tsn_dev_info->tsn_stu_info; \ 766 if (stu_info == NULL) { \ 767 LOG_ERROR(BSL_LS_BCM_TSN, \ 768 (BSL_META_U((_u_), \ 769 "STU Error:" \ 770 " tsn_stu_info not allocated\n"))); \ 771 return BCM_E_UNAVAIL; \ 772 } \ 773 if ((NULL == stu_info->stu_profile_mem_idx_get) || \ 774 (NULL == stu_info->stu_profile_create) || \ 775 (NULL == stu_info->stu_profile_set) || \ 776 (NULL == stu_info->stu_profile_get) || \ 777 (NULL == stu_info->stu_profile_destroy) || \ 778 (NULL == stu_info->ingress_stu_config_set) || \ 779 (NULL == stu_info->ingress_stu_config_get) || \ 780 (NULL == stu_info->egress_stu_port_control_set) || \ 781 (NULL == stu_info->stu_profile_decode) || \ 782 (NULL == stu_info->stu_profile_encode) || \ 783 (NULL == stu_info->stu_profile_traverse) || \ 784 (NULL == stu_info->stu_profile_mem_refcnt_get)) { \ 785 LOG_ERROR(BSL_LS_BCM_TSN, \ 786 (BSL_META_U((_u_), \ 787 "STU Error:" \ 788 " dev info not allocated\n"))); \ 789 return BCM_E_UNAVAIL; \ 790 } \ 791 } while (0) 792 793 /* STU instance fetch/lock/unlock */ 794 #define STU_BK_INFO(_u_) \ 795 (&tsn_bk_info[(_u_)]->tsn_stu_bk_info) 796 797 #define STU_BK_LOCK(_u_) \ 798 sal_mutex_take(STU_BK_INFO((_u_))->mutex, sal_mutex_FOREVER) 799 #define STU_BK_UNLOCK(_u_) \ 800 sal_mutex_give(STU_BK_INFO((_u_))->mutex) 801 802 /* TSN event management bookkeeping info quick access */ 803 #define TSN_EVENT_BKINFO(_unit_) \ 804 (&tsn_bk_info[_unit_]->tsn_events) 805 #define TSN_EVENT_DEVINFO(_unit_) \ 806 tsn_bk_info[_unit_]->tsn_dev_info->tsn_event_info 807 808 #define TSN_EVENT_FLOW_CB_MAX (1000) 809 #define TSN_EVENT_PORT_CB_MAX (1000) 810 #define TSN_EVENT_SYSTEM_CB_MAX (100) 811 812 #define TSN_EVENT_POLL_INTERVAL_DEFAULT (SECOND_USEC) 813 814 /* Protecting the global TSN event management */ 815 #define TSN_EVENT_LOCK(_unit_) \ 816 sal_mutex_take(TSN_EVENT_BKINFO(_unit_)->evt_mutex, sal_mutex_FOREVER) 817 #define TSN_EVENT_UNLOCK(_unit_) \ 818 sal_mutex_give(TSN_EVENT_BKINFO(_unit_)->evt_mutex) 819 820 #if defined(BCM_TSN_SR_SUPPORT) 821 /* Internal functions to update the active rx flow idx */ 822 STATIC int bcmi_esw_tsn_event_rx_flow_delete(int unit, int flow_idx); 823 STATIC int bcmi_esw_tsn_event_rx_flow_add(int unit, int flow_idx); 824 #endif /* BCM_TSN_SR_SUPPORT */ 825 826 /* Protecting registered event instance */ 827 #define TSN_REVT_LOCK(_erp_) \ 828 sal_mutex_take((_erp_)->mutex, sal_mutex_FOREVER) 829 #define TSN_REVT_UNLOCK(_erp_) \ 830 sal_mutex_give((_erp_)->mutex) 831 832 /* Get the tsn_bk_info[unit] pointer */ 833 STATIC int 834 tsn_bk_info_instance_get(int unit, bcmi_esw_tsn_bk_info_t **bk_info) 835 { 836 /* Input parameters check. */ 837 if (NULL == bk_info) { 838 return (BCM_E_PARAM); 839 } 840 if (!SOC_UNIT_VALID(unit)) { 841 return BCM_E_UNIT; 842 } 843 844 /* Check if TSN feature supported and initialized */ 845 if (!soc_feature(unit, soc_feature_tsn)) { 846 return (BCM_E_UNAVAIL); 847 } 848 if (tsn_bk_info[unit] == NULL) { 849 LOG_ERROR(BSL_LS_BCM_TSN, 850 (BSL_META_U(unit, 851 "TSN Error: bookkeeping info not " 852 "initialized\n"))); 853 return (BCM_E_INIT); 854 } 855 856 /* Fill info structure. */ 857 *bk_info = tsn_bk_info[unit]; 858 859 return (BCM_E_NONE); 860 } 861 862 /* 863 * Function: 864 * bcmi_esw_tsn_noninit_dev_info_get 865 * Purpose: 866 * Internal function to get device sepcific info without tsn_bk initialized. 867 * Parameters: 868 * unit - (IN) unit number 869 * devinfo-(OUT) device info 870 * Returns: 871 * BCM_E_XXX 872 */ 873 STATIC int 874 bcmi_esw_tsn_noninit_dev_info_get( 875 int unit, 876 const bcmi_esw_tsn_dev_info_t **devinfo) 877 { 878 int rv = BCM_E_NONE; 879 880 /* Input parameters check. */ 881 if (NULL == devinfo) { 882 return (BCM_E_PARAM); 883 } 884 if (!SOC_UNIT_VALID(unit)) { 885 return BCM_E_UNIT; 886 } 887 888 /* Check if TSN feature supported and initialized */ 889 if (!soc_feature(unit, soc_feature_tsn)) { 890 return (BCM_E_UNAVAIL); 891 } 892 #ifdef BCM_GREYHOUND2_SUPPORT 893 if (SOC_IS_GREYHOUND2(unit)) { 894 /* Fill info structure. */ 895 rv = bcmi_gh2_tsn_noninit_dev_info_get(unit, devinfo); 896 } else 897 #endif /* BCM_GREYHOUND2_SUPPORT */ 898 { 899 rv = BCM_E_UNAVAIL; 900 } 901 902 return rv; 903 } 904 905 #if defined(BCM_TSN_SR_SUPPORT) 906 907 /* 908 * Function: 909 * bcmi_esw_tsn_sr_mac_proxy_cleanup 910 * Description: 911 * Clean and free all allocated resources for 912 * TSN SR Mac Proxy profile. 913 * Parameters: 914 * unit - (IN) Unit number 915 * Return Value: 916 * None 917 */ 918 STATIC int 919 bcmi_esw_tsn_sr_mac_proxy_cleanup(int unit) 920 { 921 bcmi_esw_tsn_sr_mac_proxy_bk_info_t *sr_mp_bk_info; 922 923 LOG_VERBOSE(BSL_LS_BCM_TSN, 924 (BSL_META_U(unit, 925 "bcmi_esw_tsn_sr_mac_proxy_cleanup\n"))); 926 927 /* Free and clear the TSN SR MAC Proxy bookkeeping info structure */ 928 if (tsn_bk_info[unit] != NULL) { 929 sr_mp_bk_info = &(tsn_bk_info[unit]->tsn_sr_mac_proxy_bk_info); 930 931 if (sr_mp_bk_info->sr_mp_entry != NULL) { 932 TSN_FREE(unit, sr_mp_bk_info->sr_mp_entry, 0); 933 sr_mp_bk_info->sr_mp_entry = NULL; 934 } 935 936 if (sr_mp_bk_info->sr_mp_mutex != NULL) { 937 sal_mutex_destroy(sr_mp_bk_info->sr_mp_mutex); 938 sr_mp_bk_info->sr_mp_mutex = NULL; 939 } 940 } 941 942 return BCM_E_NONE; 943 } 944 945 /* 946 * Function: 947 * bcmi_esw_tsn_sr_mac_proxy_init 948 * Description: 949 * Initialize and allocate all required resources for 950 * TSN SR Mac Proxy profile. 951 * Parameters: 952 * unit - (IN) Unit number 953 * Returns: 954 * BCM_E_XXX 955 */ 956 STATIC int 957 bcmi_esw_tsn_sr_mac_proxy_init(int unit) 958 { 959 int rv = BCM_E_NONE; 960 bcmi_esw_tsn_bk_info_t *tsn_bk_info; 961 const bcmi_esw_tsn_dev_info_t *tsn_dev_info; 962 const tsn_sr_mac_proxy_info_t *sr_mp_dev_info; 963 bcmi_esw_tsn_sr_mac_proxy_bk_info_t *sr_mp_bk_info; 964 965 LOG_VERBOSE(BSL_LS_BCM_TSN, 966 (BSL_META_U(unit, 967 "bcmi_esw_tsn_sr_mac_proxy_init\n"))); 968 969 BCM_IF_ERROR_RETURN( 970 tsn_bk_info_instance_get(unit, &tsn_bk_info)); 971 972 /* Set up the unit TSN SR Mac Proxy bookkeeping info structure. */ 973 sr_mp_bk_info = &(tsn_bk_info->tsn_sr_mac_proxy_bk_info); 974 975 /* Create protection mutex. */ 976 sr_mp_bk_info->sr_mp_mutex = sal_mutex_create("sr_mp_bk_info.lock"); 977 if (NULL == sr_mp_bk_info->sr_mp_mutex) { 978 return BCM_E_RESOURCE; 979 } 980 981 /* Get chip specific assignment */ 982 tsn_dev_info = tsn_bk_info->tsn_dev_info; 983 sr_mp_dev_info = tsn_dev_info->tsn_sr_mac_proxy_info; 984 985 if (sr_mp_dev_info == NULL) { 986 LOG_ERROR(BSL_LS_BCM_TSN, 987 (BSL_META_U(unit, 988 "TSN Error: SR MAC Proxy device info not " 989 "initialized\n"))); 990 return BCM_E_INIT; 991 } 992 993 if (!soc_mem_field_valid(unit, sr_mp_dev_info->mem, 994 sr_mp_dev_info->field)) { 995 LOG_ERROR(BSL_LS_BCM_TSN, 996 (BSL_META_U(unit, 997 "Memory %s or field is Not valid\n"), 998 SOC_MEM_UFNAME(unit, sr_mp_dev_info->mem))); 999 return BCM_E_PARAM; 1000 } 1001 1002 /* Allocate TSN SR Mac Proxy entry memory by sr_mp_num */ 1003 sr_mp_bk_info->sr_mp_num = soc_mem_index_count(unit, sr_mp_dev_info->mem); 1004 TSN_ALLOC(unit, sr_mp_bk_info->sr_mp_entry, 1005 bcmi_esw_tsn_sr_mac_proxy_entry_t, 1006 (sr_mp_bk_info->sr_mp_num * 1007 sizeof(bcmi_esw_tsn_sr_mac_proxy_entry_t)), 1008 "TSN SR Mac Proxy Entry", 0, rv); 1009 if (BCM_FAILURE(rv)) { 1010 LOG_VERBOSE(BSL_LS_BCM_TSN, 1011 (BSL_META_U(unit, 1012 "bcmi_esw_tsn_sr_mac_proxy_init: " 1013 "failed to allocate memory\n"))); 1014 } 1015 1016 return rv; 1017 } 1018 1019 #ifdef BCM_WARM_BOOT_SUPPORT 1020 /* 1021 * Function: 1022 * bcmi_esw_tsn_sr_mac_proxy_reload 1023 * Description: 1024 * Load TSN SR MAC Proxy info 1025 * from hardware into software data structures. 1026 * Parameters: 1027 * unit - (IN) Unit number 1028 */ 1029 STATIC int 1030 bcmi_esw_tsn_sr_mac_proxy_reload(int unit) 1031 { 1032 int rv = BCM_E_NONE; 1033 bcmi_esw_tsn_bk_info_t *tsn_bk_info; 1034 bcmi_esw_tsn_sr_mac_proxy_bk_info_t *sr_mp_bk_info; 1035 const bcmi_esw_tsn_dev_info_t *tsn_dev_info; 1036 const tsn_sr_mac_proxy_info_t *sr_mp_dev_info; 1037 bcmi_esw_tsn_sr_mac_proxy_entry_t *mp_entries; 1038 uint32 entry[SOC_MAX_MEM_WORDS]; 1039 int cur_index; 1040 bcm_pbmp_t mp_pbmp; 1041 int index, l2x_size; 1042 l2x_entry_t *l2x_entry, *l2x_table = NULL; 1043 1044 LOG_DEBUG(BSL_LS_BCM_TSN, 1045 (BSL_META_U(unit, 1046 "bcmi_esw_tsn_sr_mac_proxy_reload\n"))); 1047 1048 BCM_IF_ERROR_RETURN( 1049 tsn_bk_info_instance_get(unit, &tsn_bk_info)); 1050 1051 /* Get chip specific assignment */ 1052 tsn_dev_info = tsn_bk_info->tsn_dev_info; 1053 sr_mp_dev_info = tsn_dev_info->tsn_sr_mac_proxy_info; 1054 if (sr_mp_dev_info == NULL) { 1055 return BCM_E_UNAVAIL; 1056 } 1057 1058 /* Set up the unit TSN SR Mac Proxy bookkeeping info structure. */ 1059 sr_mp_bk_info = &(tsn_bk_info->tsn_sr_mac_proxy_bk_info); 1060 mp_entries = sr_mp_bk_info->sr_mp_entry; 1061 if (mp_entries == NULL) { 1062 return BCM_E_UNAVAIL; 1063 } 1064 1065 SR_MAC_PROXY_LOCK(sr_mp_bk_info); 1066 /* 1067 * Refresh TSN SR MAC Proxy information from the hardware tables. 1068 */ 1069 for (cur_index = 0; cur_index < sr_mp_bk_info->sr_mp_num; cur_index++) { 1070 sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 1071 rv = soc_mem_read(unit, sr_mp_dev_info->mem, MEM_BLOCK_ANY, 1072 cur_index, entry); 1073 if (BCM_FAILURE(rv)) { 1074 SR_MAC_PROXY_UNLOCK(sr_mp_bk_info); 1075 return rv; 1076 } 1077 1078 BCM_PBMP_CLEAR(mp_pbmp); 1079 soc_mem_pbmp_field_get(unit, sr_mp_dev_info->mem, entry, 1080 sr_mp_dev_info->field, &mp_pbmp); 1081 1082 BCM_PBMP_ASSIGN(mp_entries[cur_index].mp_pbmp, mp_pbmp); 1083 } 1084 SR_MAC_PROXY_UNLOCK(sr_mp_bk_info); 1085 1086 /* Refresh ref_count for L2 usage */ 1087 if (soc_mem_field_valid(unit, L2Xm, SR_MAC_PROXY_PROFILE_PTRf)) { 1088 l2x_size = sizeof(l2x_entry_t) * soc_mem_index_count(unit, L2Xm); 1089 TSN_ALLOC(unit, l2x_table, l2x_entry_t, l2x_size, 1090 "tsn_sr_mac_proxy l2 reload", 1, rv); 1091 if (BCM_FAILURE(rv)) { 1092 LOG_VERBOSE(BSL_LS_BCM_TSN, 1093 (BSL_META_U(unit, 1094 "bcmi_esw_tsn_sr_mac_proxy_reload: " 1095 "failed to allocate memory\n"))); 1096 return rv; 1097 } 1098 if (soc_mem_read_range(unit, L2Xm, MEM_BLOCK_ANY, 1099 soc_mem_index_min(unit, L2Xm), 1100 soc_mem_index_max(unit, L2Xm), 1101 l2x_table) < 0) { 1102 soc_cm_sfree(unit, l2x_table); 1103 return SOC_E_INTERNAL; 1104 } 1105 1106 SR_MAC_PROXY_LOCK(sr_mp_bk_info); 1107 for (index = soc_mem_index_min(unit, L2Xm); 1108 index <= soc_mem_index_max(unit, L2Xm); index++) { 1109 l2x_entry = soc_mem_table_idx_to_pointer(unit, L2Xm, 1110 l2x_entry_t *, 1111 l2x_table, index); 1112 if (!soc_L2Xm_field32_get(unit, l2x_entry, VALIDf)) { 1113 continue; 1114 } 1115 1116 cur_index = soc_L2Xm_field32_get(unit, l2x_entry, 1117 SR_MAC_PROXY_PROFILE_PTRf); 1118 if ((cur_index > 0) && (cur_index < sr_mp_bk_info->sr_mp_num)) { 1119 mp_entries[cur_index].ref_count++; 1120 } 1121 } 1122 SR_MAC_PROXY_UNLOCK(sr_mp_bk_info); 1123 1124 soc_cm_sfree(unit, l2x_table); 1125 } else { 1126 return BCM_E_INTERNAL; 1127 } 1128 1129 return BCM_E_NONE; 1130 } 1131 1132 STATIC int 1133 bcmi_esw_tsn_pri_map_existed_check( 1134 int unit, 1135 bcm_tsn_pri_map_config_t *config, 1136 bcm_tsn_pri_map_t *map_id); 1137 1138 /* 1139 * Function: 1140 * bcmi_esw_tsn_egress_mtu_sync 1141 * Purpose: 1142 * Synchronize the egr mtu sw data into scache 1143 * Parameters: 1144 * unit - (IN) Unit number 1145 * Returns: 1146 * BCM_E_xxx 1147 */ 1148 STATIC int 1149 bcmi_esw_tsn_egress_mtu_sync(int unit) 1150 { 1151 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 1152 const tsn_mtu_info_t *ctrl_info = NULL; 1153 1154 soc_scache_handle_t scache_handle; 1155 uint8 *map_id_scache; 1156 int idx; 1157 uint32 alloc; 1158 1159 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 1160 /* Use this init macro after the bk info instance get */ 1161 MTU_DEV_INIT(unit); 1162 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 1163 1164 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN, 1165 BCM_TSN_WB_SCACHE_PART_EGR_MTU); 1166 /* allocate the scache pointer size */ 1167 alloc = sizeof(bcm_tsn_pri_map_t) * ctrl_info->logical_port_num; 1168 BCM_IF_ERROR_RETURN( 1169 _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 1170 alloc, &map_id_scache, 1171 BCM_TSN_WB_DEFAULT_VERSION, NULL)); 1172 if (map_id_scache == NULL || 1173 bk_info->tsn_mtu_bk_info.pri_map_port == NULL) { 1174 return BCM_E_INTERNAL; 1175 } 1176 1177 MTU_BK_LOCK(unit); 1178 for (idx = 0; idx < ctrl_info->logical_port_num; idx++) { 1179 sal_memcpy(map_id_scache, 1180 &(bk_info->tsn_mtu_bk_info.pri_map_port[idx]), 1181 sizeof(bcm_tsn_pri_map_t)); 1182 map_id_scache += sizeof(bcm_tsn_pri_map_t); 1183 } 1184 MTU_BK_UNLOCK(unit); 1185 return BCM_E_NONE; 1186 } 1187 1188 /* 1189 * Function: 1190 * bcmi_esw_tsn_egress_mtu_reload 1191 * Purpose: 1192 * Reload the scache data into egr mtu sw data structure 1193 * Parameters: 1194 * unit - (IN) Unit number 1195 * Returns: 1196 * BCM_E_xxx 1197 */ 1198 STATIC int 1199 bcmi_esw_tsn_egress_mtu_reload(int unit) 1200 { 1201 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 1202 const tsn_mtu_info_t *ctrl_info = NULL; 1203 1204 bcm_tsn_pri_map_config_t config; 1205 soc_scache_handle_t scache_handle; 1206 uint8 *map_id_scache; 1207 int idx, rv, rv1, i, prof_idx, prof_id; 1208 bcm_tsn_pri_map_t map_id; 1209 bcm_tsn_mtu_profile_type_t type; 1210 1211 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 1212 /* Use this init macro after the bk info instance get */ 1213 MTU_DEV_INIT(unit); 1214 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 1215 1216 LOG_DEBUG(BSL_LS_BCM_TSN, 1217 (BSL_META_U(unit, 1218 "bcmi_esw_tsn_egress_mtu_reload\n"))); 1219 1220 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN, 1221 BCM_TSN_WB_SCACHE_PART_EGR_MTU); 1222 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 1223 0, &map_id_scache, BCM_TSN_WB_DEFAULT_VERSION, 1224 NULL); 1225 if (bk_info->tsn_mtu_bk_info.pri_map_port == NULL) { 1226 return BCM_E_INTERNAL; 1227 } 1228 1229 if (rv == BCM_E_NOT_FOUND) { 1230 rv1 = _bcm_esw_scache_ptr_get( 1231 unit, scache_handle, TRUE, sizeof(bcm_tsn_pri_map_t), 1232 &map_id_scache, BCM_TSN_WB_DEFAULT_VERSION, NULL); 1233 if (BCM_E_NOT_FOUND == rv1) { 1234 /* Proceed with Level 1 Warm Boot */ 1235 rv1 = BCM_E_NONE; 1236 } 1237 BCM_IF_ERROR_RETURN(rv1); 1238 return BCM_E_NONE; 1239 } else if (rv == BCM_E_NONE) { 1240 if (map_id_scache == NULL) { 1241 return BCM_E_INTERNAL; 1242 } 1243 MTU_BK_LOCK(unit); 1244 for (idx = 0; idx < ctrl_info->logical_port_num; idx++) { 1245 sal_memcpy(&(bk_info->tsn_mtu_bk_info.pri_map_port[idx]), 1246 map_id_scache, 1247 sizeof(bcm_tsn_pri_map_t)); 1248 map_id_scache += sizeof(bcm_tsn_pri_map_t); 1249 rv1 = ctrl_info->egress_mtu_wb_reload(unit, idx, &config); 1250 if (BCM_FAILURE(rv1)) { 1251 MTU_BK_UNLOCK(unit); 1252 return rv1; 1253 } 1254 /* Check whether the config has been added before */ 1255 rv1 = bcmi_esw_tsn_pri_map_existed_check(unit, &config, &map_id); 1256 if (rv1 == BCM_E_NOT_FOUND) { 1257 /* MTU profile reference count update */ 1258 for (i = 0; i < config.num_map_entries; i++) { 1259 prof_id = config.map_entries[i].profile_id; 1260 ctrl_info->mtu_profile_decode( 1261 unit, prof_id, &type, &prof_idx); 1262 /* MTU profile entry == 0 is invalid */ 1263 if (prof_idx != 0) { 1264 bcmi_esw_tsn_mtu_profile_ref_inc(unit, prof_id); 1265 } 1266 } 1267 /* Provide priority map structure the related mtu wb information */ 1268 bcmi_esw_tsn_pri_map_mtu_stu_wb_set( 1269 unit, bk_info->tsn_mtu_bk_info.pri_map_port[idx], &config); 1270 } 1271 1272 } 1273 1274 MTU_BK_UNLOCK(unit); 1275 } 1276 1277 return rv; 1278 } 1279 1280 /* 1281 * Function: 1282 * bcmi_esw_tsn_egress_stu_sync 1283 * Purpose: 1284 * Synchronize the egr stu sw data into scache 1285 * Parameters: 1286 * unit - (IN) Unit number 1287 * Returns: 1288 * BCM_E_xxx 1289 */ 1290 STATIC int 1291 bcmi_esw_tsn_egress_stu_sync(int unit) 1292 { 1293 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 1294 const tsn_stu_info_t *ctrl_info = NULL; 1295 1296 soc_scache_handle_t scache_handle; 1297 uint8 *map_id_scache; 1298 int idx; 1299 uint32 alloc; 1300 1301 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 1302 /* Use this init macro after the bk info instance get */ 1303 STU_DEV_INIT(unit); 1304 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 1305 1306 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN, 1307 BCM_TSN_WB_SCACHE_PART_EGR_STU); 1308 /* allocate the scache pointer size */ 1309 alloc = sizeof(bcm_tsn_pri_map_t) * ctrl_info->logical_port_num; 1310 BCM_IF_ERROR_RETURN( 1311 _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, 1312 alloc, &map_id_scache, 1313 BCM_TSN_WB_DEFAULT_VERSION, NULL)); 1314 if (map_id_scache == NULL || 1315 bk_info->tsn_stu_bk_info.pri_map_port == NULL) { 1316 return BCM_E_INTERNAL; 1317 } 1318 1319 STU_BK_LOCK(unit); 1320 for (idx = 0; idx < ctrl_info->logical_port_num; idx++) { 1321 sal_memcpy(map_id_scache, 1322 &(bk_info->tsn_stu_bk_info.pri_map_port[idx]), 1323 sizeof(bcm_tsn_pri_map_t)); 1324 map_id_scache += sizeof(bcm_tsn_pri_map_t); 1325 } 1326 STU_BK_UNLOCK(unit); 1327 return BCM_E_NONE; 1328 } 1329 1330 /* 1331 * Function: 1332 * bcmi_esw_tsn_egress_stu_reload 1333 * Purpose: 1334 * Reload the scache data into egr stu sw data structure 1335 * Parameters: 1336 * unit - (IN) Unit number 1337 * Returns: 1338 * BCM_E_xxx 1339 */ 1340 STATIC int 1341 bcmi_esw_tsn_egress_stu_reload(int unit) 1342 { 1343 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 1344 const tsn_stu_info_t *ctrl_info = NULL; 1345 1346 bcm_tsn_pri_map_config_t config; 1347 soc_scache_handle_t scache_handle; 1348 uint8 *map_id_scache; 1349 int idx, rv, rv1, i, prof_idx, prof_id; 1350 bcm_tsn_pri_map_t map_id; 1351 bcm_tsn_stu_profile_type_t type; 1352 1353 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 1354 /* Use this init macro after the bk info instance get */ 1355 STU_DEV_INIT(unit); 1356 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 1357 1358 LOG_DEBUG(BSL_LS_BCM_TSN, 1359 (BSL_META_U(unit, 1360 "bcmi_esw_tsn_egress_stu_reload\n"))); 1361 1362 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN, 1363 BCM_TSN_WB_SCACHE_PART_EGR_STU); 1364 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 1365 0, &map_id_scache, BCM_TSN_WB_DEFAULT_VERSION, 1366 NULL); 1367 if (bk_info->tsn_stu_bk_info.pri_map_port == NULL) { 1368 return BCM_E_INTERNAL; 1369 } 1370 if (rv == BCM_E_NOT_FOUND) { 1371 rv1 = _bcm_esw_scache_ptr_get( 1372 unit, scache_handle, TRUE, sizeof(bcm_tsn_pri_map_t), 1373 &map_id_scache, BCM_TSN_WB_DEFAULT_VERSION, NULL); 1374 if (BCM_E_NOT_FOUND == rv1) { 1375 /* Proceed with Level 1 Warm Boot */ 1376 rv1 = BCM_E_NONE; 1377 } 1378 BCM_IF_ERROR_RETURN(rv1); 1379 return BCM_E_NONE; 1380 } else if (rv == BCM_E_NONE) { 1381 if (map_id_scache == NULL) { 1382 return BCM_E_INTERNAL; 1383 } 1384 STU_BK_LOCK(unit); 1385 for (idx = 0; idx < ctrl_info->logical_port_num; idx++) { 1386 sal_memcpy(&(bk_info->tsn_stu_bk_info.pri_map_port[idx]), 1387 map_id_scache, 1388 sizeof(bcm_tsn_pri_map_t)); 1389 map_id_scache += sizeof(bcm_tsn_pri_map_t); 1390 rv1 = ctrl_info->egress_stu_wb_reload(unit, idx, &config); 1391 if (BCM_FAILURE(rv1)) { 1392 STU_BK_UNLOCK(unit); 1393 return rv1; 1394 } 1395 /* Check whether the config has been added before */ 1396 rv1 = bcmi_esw_tsn_pri_map_existed_check(unit, &config, &map_id); 1397 if (rv1 == BCM_E_NOT_FOUND) { 1398 /* STU profile reference count update */ 1399 for (i = 0; i < config.num_map_entries; i++) { 1400 prof_id = config.map_entries[i].profile_id; 1401 ctrl_info->stu_profile_decode( 1402 unit, prof_id, &type, &prof_idx); 1403 /* STU profile entry == 0 is invalid */ 1404 if (prof_idx != 0) { 1405 bcmi_esw_tsn_stu_profile_ref_inc(unit, prof_id); 1406 } 1407 } 1408 /* Provide priority map structure the related stu wb information */ 1409 bcmi_esw_tsn_pri_map_mtu_stu_wb_set( 1410 unit, bk_info->tsn_stu_bk_info.pri_map_port[idx], &config); 1411 } 1412 } 1413 1414 STU_BK_UNLOCK(unit); 1415 } 1416 return rv; 1417 } 1418 1419 /* 1420 * Function: 1421 * bcmi_esw_tsn_sr_port_prp_forwarding_sync 1422 * Purpose: 1423 * Synchronize the prp-forwarding sw data into scache 1424 * Parameters: 1425 * unit - (IN) Unit number 1426 1427 * Returns: 1428 * BCM_E_XXX 1429 * Notes: 1430 */ 1431 STATIC int 1432 bcmi_esw_tsn_sr_port_prp_forwarding_sync( 1433 int unit) 1434 { 1435 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 1436 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 1437 const tsn_sr_port_dev_info_t *sr_port_config = NULL; 1438 soc_scache_handle_t scache_handle; 1439 1440 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 1441 dev_info = bk_info->tsn_dev_info; 1442 if (dev_info == NULL) { 1443 return BCM_E_UNAVAIL; 1444 } 1445 sr_port_config = dev_info->sr_port_info; 1446 if ((sr_port_config == NULL) || 1447 (sr_port_config->sr_port_prp_forwarding_wb_sync == NULL)) { 1448 return BCM_E_UNAVAIL; 1449 } 1450 1451 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN, 1452 BCM_TSN_WB_SCACHE_PART_PRP_FORWARDING); 1453 1454 return sr_port_config->sr_port_prp_forwarding_wb_sync(unit, scache_handle); 1455 } 1456 1457 /* 1458 * Function: 1459 * bcmi_esw_tsn_sr_port_prp_forwarding_reload 1460 * Purpose: 1461 * Reload the scache data into prp-forwarding sw data 1462 * Parameters: 1463 * unit - (IN) Unit number 1464 1465 * Returns: 1466 * BCM_E_XXX 1467 * Notes: 1468 */ 1469 STATIC int 1470 bcmi_esw_tsn_sr_port_prp_forwarding_reload( 1471 int unit) 1472 { 1473 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 1474 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 1475 const tsn_sr_port_dev_info_t *sr_port_config = NULL; 1476 soc_scache_handle_t scache_handle; 1477 1478 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 1479 dev_info = bk_info->tsn_dev_info; 1480 if (dev_info == NULL) { 1481 return BCM_E_UNAVAIL; 1482 } 1483 sr_port_config = dev_info->sr_port_info; 1484 if ((sr_port_config == NULL) || 1485 (sr_port_config->sr_port_prp_forwarding_wb_reload == NULL)) { 1486 return BCM_E_UNAVAIL; 1487 } 1488 1489 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_TSN, 1490 BCM_TSN_WB_SCACHE_PART_PRP_FORWARDING); 1491 1492 return 1493 sr_port_config->sr_port_prp_forwarding_wb_reload(unit, scache_handle); 1494 } 1495 #endif /* BCM_WARM_BOOT_SUPPORT */ 1496 1497 /* 1498 * Function: 1499 * bcmi_esw_tsn_sr_mac_proxy_insert 1500 * Purpose: 1501 * Find or create a TSN SR MAC Proxy table entry 1502 * matching the given bitmap. 1503 * Parameters: 1504 * unit - (IN) Unit number 1505 * mp_pbmp - (IN) Port bitmap for SR source MAC Proxy 1506 * mp_index - (OUT) Index of TSN SR MAC Proxy table with bitmap 1507 * Returns: 1508 * BCM_E_NONE - Success. 1509 * BCM_E_INTERNAL - Chip access failure. 1510 * BCM_E_RESOURCE - No more TSN SR MAC Proxy entries available. 1511 * BCM_E_PARAM - Illegal parameter. 1512 */ 1513 int 1514 bcmi_esw_tsn_sr_mac_proxy_insert( 1515 int unit, 1516 bcm_pbmp_t mp_pbmp, 1517 int *mp_index) 1518 { 1519 int rv = BCM_E_NONE; 1520 bcmi_esw_tsn_bk_info_t *tsn_bk_info; 1521 const bcmi_esw_tsn_dev_info_t *tsn_dev_info; 1522 const tsn_sr_mac_proxy_info_t *sr_mp_dev_info; 1523 bcmi_esw_tsn_sr_mac_proxy_bk_info_t *sr_mp_bk_info; 1524 bcmi_esw_tsn_sr_mac_proxy_entry_t *mp_entries; 1525 uint32 entry[SOC_MAX_MEM_WORDS]; 1526 bcm_pbmp_t temp_pbmp; 1527 int cur_index = 0; 1528 1529 LOG_VERBOSE(BSL_LS_BCM_TSN, 1530 (BSL_META_U(unit, 1531 "bcmi_esw_tsn_sr_mac_proxy_insert\n"))); 1532 1533 /* Check if TSN SR feature supported */ 1534 if (!soc_feature(unit, soc_feature_tsn_sr)) { 1535 return BCM_E_UNAVAIL; 1536 } 1537 1538 /* Check for input parameter */ 1539 if (NULL == mp_index) { 1540 return BCM_E_PARAM; 1541 } 1542 1543 /* Check for reasonable pbmp */ 1544 BCM_PBMP_ASSIGN(temp_pbmp, mp_pbmp); 1545 BCM_PBMP_AND(temp_pbmp, PBMP_ALL(unit)); 1546 if (BCM_PBMP_NEQ(mp_pbmp, temp_pbmp)) { 1547 return BCM_E_PARAM; 1548 } 1549 1550 BCM_IF_ERROR_RETURN( 1551 tsn_bk_info_instance_get(unit, &tsn_bk_info)); 1552 1553 /* Get chip specific assignment */ 1554 tsn_dev_info = tsn_bk_info->tsn_dev_info; 1555 sr_mp_dev_info = tsn_dev_info->tsn_sr_mac_proxy_info; 1556 if (sr_mp_dev_info == NULL) { 1557 return BCM_E_UNAVAIL; 1558 } 1559 1560 /* Set up the unit TSN SR Mac Proxy bookkeeping info structure. */ 1561 sr_mp_bk_info = &(tsn_bk_info->tsn_sr_mac_proxy_bk_info); 1562 mp_entries = sr_mp_bk_info->sr_mp_entry; 1563 if (mp_entries == NULL) { 1564 return BCM_E_UNAVAIL; 1565 } 1566 1567 SR_MAC_PROXY_LOCK(sr_mp_bk_info); 1568 1569 /* Compare the bitmap with existing entries */ 1570 for (cur_index = 0; cur_index < sr_mp_bk_info->sr_mp_num; cur_index++) { 1571 if (mp_entries[cur_index].ref_count != 0) { 1572 if (BCM_PBMP_EQ(mp_entries[cur_index].mp_pbmp, mp_pbmp)) { 1573 mp_entries[cur_index].ref_count++; 1574 *mp_index = cur_index; 1575 SR_MAC_PROXY_UNLOCK(sr_mp_bk_info); 1576 return BCM_E_NONE; 1577 } 1578 } 1579 } 1580 1581 /* 1582 * Not in table already, see if any space free 1583 * (index 0 is reserved by default) 1584 */ 1585 for (cur_index = 1; cur_index < sr_mp_bk_info->sr_mp_num; cur_index++) { 1586 if (mp_entries[cur_index].ref_count == 0) { 1587 /* Attempt insert */ 1588 sal_memset(entry, 0, sizeof(uint32) * SOC_MAX_MEM_WORDS); 1589 rv = soc_mem_read(unit, sr_mp_dev_info->mem, MEM_BLOCK_ANY, 1590 cur_index, entry); 1591 if (BCM_FAILURE(rv)) { 1592 SR_MAC_PROXY_UNLOCK(sr_mp_bk_info); 1593 return rv; 1594 } 1595 1596 soc_mem_pbmp_field_set(unit, sr_mp_dev_info->mem, entry, 1597 sr_mp_dev_info->field, &mp_pbmp); 1598 1599 rv = soc_mem_write(unit, sr_mp_dev_info->mem, MEM_BLOCK_ALL, 1600 cur_index, entry); 1601 if (BCM_FAILURE(rv)) { 1602 SR_MAC_PROXY_UNLOCK(sr_mp_bk_info); 1603 return rv; 1604 } 1605 1606 mp_entries[cur_index].ref_count++; 1607 BCM_PBMP_ASSIGN(mp_entries[cur_index].mp_pbmp, mp_pbmp); 1608 *mp_index = cur_index; 1609 1610 SR_MAC_PROXY_UNLOCK(sr_mp_bk_info); 1611 return BCM_E_NONE; 1612 } 1613 } 1614 1615 /* Didn't find a free slot, out of table space */ 1616 SR_MAC_PROXY_UNLOCK(sr_mp_bk_info); 1617 return BCM_E_RESOURCE; 1618 } 1619 1620 /* 1621 * Function: 1622 * bcmi_esw_tsn_sr_mac_proxy_delete 1623 * Purpose: 1624 * Remove reference to TSN SR MAC Proxy table entry 1625 * matching the given bitmap. 1626 * Parameters: 1627 * unit - (IN) Unit number 1628 * mp_index - (IN) Index of TSN SR MAC Proxy table with bitmap 1629 * Returns: 1630 * BCM_E_XXX. 1631 */ 1632 int 1633 bcmi_esw_tsn_sr_mac_proxy_delete(int unit, int mp_index) 1634 { 1635 bcmi_esw_tsn_bk_info_t *tsn_bk_info; 1636 bcmi_esw_tsn_sr_mac_proxy_bk_info_t *sr_mp_bk_info; 1637 bcmi_esw_tsn_sr_mac_proxy_entry_t *mp_entries; 1638 1639 LOG_VERBOSE(BSL_LS_BCM_TSN, 1640 (BSL_META_U(unit, 1641 "bcmi_esw_tsn_sr_mac_proxy_delete\n"))); 1642 1643 /* Check if TSN SR feature supported */ 1644 if (!soc_feature(unit, soc_feature_tsn_sr)) { 1645 return BCM_E_UNAVAIL; 1646 } 1647 1648 BCM_IF_ERROR_RETURN( 1649 tsn_bk_info_instance_get(unit, &tsn_bk_info)); 1650 1651 /* Set up the unit TSN SR Mac Proxy bookkeeping info structure. */ 1652 sr_mp_bk_info = &(tsn_bk_info->tsn_sr_mac_proxy_bk_info); 1653 mp_entries = sr_mp_bk_info->sr_mp_entry; 1654 1655 /* Check for reasonable entry index (0 is reserved by default) */ 1656 if (mp_index <= 0 || mp_index >= sr_mp_bk_info->sr_mp_num) { 1657 return BCM_E_PARAM; 1658 } 1659 1660 SR_MAC_PROXY_LOCK(sr_mp_bk_info); 1661 if (mp_entries[mp_index].ref_count > 0) { 1662 mp_entries[mp_index].ref_count--; 1663 } else { 1664 /* Check if the ref_count is zero: return BCM_E_NOT_FOUND */ 1665 SR_MAC_PROXY_UNLOCK(sr_mp_bk_info); 1666 return BCM_E_NOT_FOUND; 1667 } 1668 1669 /* Clear software port bitmap if the ref_count is decreased to zero */ 1670 if (mp_entries[mp_index].ref_count == 0) { 1671 BCM_PBMP_CLEAR(mp_entries[mp_index].mp_pbmp); 1672 } 1673 1674 SR_MAC_PROXY_UNLOCK(sr_mp_bk_info); 1675 return BCM_E_NONE; 1676 } 1677 1678 /* 1679 * Function: 1680 * bcmi_esw_tsn_sr_mac_proxy_get 1681 * Purpose: 1682 * Get Port bitmap from software SR MAC Proxy table 1683 * with given index of TSN SR MAC Proxy table. 1684 * Parameters: 1685 * unit - (IN) Unit number 1686 * mp_index - (IN) Index of TSN SR MAC Proxy table with bitmap 1687 * mp_pbmp - (OUT) Port bitmap for SR source MAC Proxy 1688 * Returns: 1689 * BCM_E_XXX. 1690 */ 1691 int 1692 bcmi_esw_tsn_sr_mac_proxy_get(int unit, int mp_index, bcm_pbmp_t *mp_pbmp) 1693 { 1694 bcmi_esw_tsn_bk_info_t *tsn_bk_info; 1695 bcmi_esw_tsn_sr_mac_proxy_bk_info_t *sr_mp_bk_info; 1696 bcmi_esw_tsn_sr_mac_proxy_entry_t *mp_entries; 1697 1698 LOG_VERBOSE(BSL_LS_BCM_TSN, 1699 (BSL_META_U(unit, 1700 "bcmi_esw_tsn_sr_mac_proxy_get\n"))); 1701 1702 /* Check if TSN SR feature supported */ 1703 if (!soc_feature(unit, soc_feature_tsn_sr)) { 1704 return BCM_E_UNAVAIL; 1705 } 1706 1707 BCM_IF_ERROR_RETURN( 1708 tsn_bk_info_instance_get(unit, &tsn_bk_info)); 1709 1710 /* Set up the unit TSN SR Mac Proxy bookkeeping info structure. */ 1711 sr_mp_bk_info = &(tsn_bk_info->tsn_sr_mac_proxy_bk_info); 1712 mp_entries = sr_mp_bk_info->sr_mp_entry; 1713 1714 /* Check for reasonable entry index (0 is reserved by default) */ 1715 if (mp_index <= 0 || mp_index >= sr_mp_bk_info->sr_mp_num) { 1716 return BCM_E_PARAM; 1717 } 1718 1719 SR_MAC_PROXY_LOCK(sr_mp_bk_info); 1720 BCM_PBMP_ASSIGN(*mp_pbmp, mp_entries[mp_index].mp_pbmp); 1721 SR_MAC_PROXY_UNLOCK(sr_mp_bk_info); 1722 1723 return BCM_E_NONE; 1724 } 1725 1726 /* SR flow: free a chain of one or more continuous flow indexes */ 1727 STATIC int 1728 bcmi_esw_tsn_sr_flow_idx_free(int unit, int dir, tsn_sr_flowidx_entry_t *entry) 1729 { 1730 bcmi_esw_tsn_bk_info_t *tsn_bk; 1731 tsn_sr_flows_bookkeeping_t *bkinfo; 1732 tsn_sr_flowidx_entry_t *fid, *prev, *last; 1733 int eidx; 1734 1735 /* parameter check */ 1736 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 1737 if (dir < 0 || dir >= SR_FLOW_DIR_COUNT || entry == NULL) { 1738 return BCM_E_PARAM; 1739 } 1740 1741 /* Protect access to the flow indexes */ 1742 SR_FLOW_MGMT_LOCK(unit); 1743 1744 /* Traverse the list and insert the chain into the list */ 1745 bkinfo = &tsn_bk->sr_flows; 1746 eidx = entry->flow_idx; 1747 prev = NULL; 1748 for (fid = bkinfo->flowids_avail[dir]; fid != NULL; fid = fid->next) { 1749 1750 /* If the index is smaller than current, insert before current */ 1751 if (eidx < fid->flow_idx) { 1752 /* Find the last item in the supplied chain */ 1753 for (last = entry; last->next != NULL; last = last->next); 1754 /* Connect remaining items to the chain */ 1755 last->next = fid; 1756 /* Insert the chain to the list */ 1757 if (NULL == prev) { 1758 bkinfo->flowids_avail[dir] = entry; 1759 } else { 1760 prev->next = entry; 1761 } 1762 SR_FLOW_MGMT_UNLOCK(unit); 1763 return BCM_E_NONE; 1764 } 1765 1766 /* all indexes should be different */ 1767 assert(eidx != fid->flow_idx); 1768 1769 /* record the previous item */ 1770 prev = fid; 1771 } 1772 1773 /* The index is larger than all items in the list, append it at the end */ 1774 if (NULL == prev) { 1775 bkinfo->flowids_avail[dir] = entry; 1776 } else { 1777 prev->next = entry; 1778 } 1779 SR_FLOW_MGMT_UNLOCK(unit); 1780 return BCM_E_NONE; 1781 } 1782 1783 /* SR flow: allocate one or more continuous flow idx(s) */ 1784 STATIC int 1785 bcmi_esw_tsn_sr_flow_idx_allocate( 1786 int unit, 1787 int dir, 1788 int count, 1789 tsn_sr_flowidx_entry_t **entry) 1790 { 1791 bcmi_esw_tsn_bk_info_t *tsn_bk; 1792 tsn_sr_flows_bookkeeping_t *bkinfo; 1793 tsn_sr_flowidx_entry_t *fid, *begin, *prev, *bprev; 1794 int idx, bidx; 1795 1796 /* parameter check */ 1797 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 1798 if (dir < 0 || dir >= SR_FLOW_DIR_COUNT || count <= 0 || entry == NULL) { 1799 return BCM_E_PARAM; 1800 } 1801 1802 /* Protect access to the flow indexes */ 1803 SR_FLOW_MGMT_LOCK(unit); 1804 1805 /* Check if any index is available */ 1806 bkinfo = &tsn_bk->sr_flows; 1807 if (NULL == bkinfo->flowids_avail[dir]) { 1808 SR_FLOW_MGMT_UNLOCK(unit); 1809 return BCM_E_RESOURCE; 1810 } 1811 1812 /* 1813 * Quick retrieval for typical case: count == 1. 1814 * Dynamic software learning may be performed for HSR/PRP where the count 1815 * should always be 1. We need to make this as quick as possible. 1816 * Here we should be able to do it in O(1) using pre-allocated linked list. 1817 */ 1818 if (1 == count) { 1819 /* Get one entry from the head */ 1820 fid = bkinfo->flowids_avail[dir]; 1821 bkinfo->flowids_avail[dir] = fid->next; 1822 fid->next = NULL; 1823 *entry = fid; 1824 SR_FLOW_MGMT_UNLOCK(unit); 1825 return BCM_E_NONE; 1826 } 1827 1828 /* Traverse the list and search for enough continuous items to allocate */ 1829 idx = bidx = bkinfo->max_flows[dir]; /* invalid current index */ 1830 prev = bprev = begin = NULL; 1831 for (fid = bkinfo->flowids_avail[dir]; fid != NULL; fid = fid->next) { 1832 1833 /* Check if it's continuous */ 1834 if (idx + 1 != fid->flow_idx) { 1835 /* Index not continuous, restart the searching */ 1836 idx = fid->flow_idx; 1837 bidx = idx; 1838 begin = fid; 1839 bprev = prev; 1840 } else if (fid->flow_idx - bidx + 1 == count) { 1841 1842 /* 1843 * Found enough continuous flow indexes: update and return 1844 */ 1845 1846 /* Update the linked list by removing the chain from the list */ 1847 if (NULL == bprev) { 1848 /* The chain is the head */ 1849 bkinfo->flowids_avail[dir] = fid->next; 1850 } else { 1851 /* Connect previous one to the next of the chain */ 1852 bprev->next = fid->next; 1853 } 1854 1855 /* Terminate this chain and return */ 1856 fid->next = NULL; 1857 *entry = begin; 1858 SR_FLOW_MGMT_UNLOCK(unit); 1859 return BCM_E_NONE; 1860 1861 } else { 1862 /* continuous but not yet reached the count */ 1863 idx++; 1864 } 1865 1866 /* record the previous one */ 1867 prev = fid; 1868 } 1869 1870 /* Cannot find enough continuous entries */ 1871 SR_FLOW_MGMT_UNLOCK(unit); 1872 return BCM_E_RESOURCE; 1873 } 1874 1875 /* 1876 * De-allocate an SR flowset and underlying flows with flowset index 1877 * This function should be called with flowset mutex locked (if made public) 1878 * and ref_count = 0. 1879 */ 1880 STATIC int 1881 bcmi_esw_tsn_sr_flowset_free(int unit, int dir, int fsid) 1882 { 1883 bcmi_esw_tsn_bk_info_t *tsn_bk; 1884 tsn_sr_flows_bookkeeping_t *bkinfo; 1885 tsn_sr_flowset_t *fset; 1886 int rv = BCM_E_NONE; 1887 1888 /* parameter check */ 1889 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 1890 if (dir < 0 || dir >= SR_FLOW_DIR_COUNT) { 1891 return BCM_E_PARAM; 1892 } 1893 bkinfo = &tsn_bk->sr_flows; 1894 fset = &bkinfo->flowsets[dir][fsid]; 1895 1896 /* Free flow indexes */ 1897 rv = bcmi_esw_tsn_sr_flow_idx_free(unit, dir, fset->flow_ide); 1898 1899 /* Clear flowset data */ 1900 fset->flow_ide = NULL; 1901 fset->num_flows = 0; 1902 1903 return rv; 1904 } 1905 1906 /* 1907 * Function: 1908 * bcmi_esw_tsn_sr_flowset_destroy 1909 * Purpose: 1910 * Destroy an SR (TX or RX) flowset. 1911 * Parameters: 1912 * unit - (IN) unit number 1913 * flowset - (IN) flowset ID 1914 * Returns: 1915 * BCM_E_XXX 1916 * Notes: 1917 */ 1918 STATIC int 1919 bcmi_esw_tsn_sr_flowset_destroy(int unit, bcm_tsn_sr_flowset_t flowset) 1920 { 1921 bcmi_esw_tsn_bk_info_t *tsn_bk; 1922 tsn_sr_flows_bookkeeping_t *bkinfo; 1923 tsn_sr_flowset_t *fset; 1924 int dir, fsid; 1925 int rv = BCM_E_NONE; 1926 int i; 1927 1928 /* parameter check */ 1929 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 1930 bkinfo = &tsn_bk->sr_flows; 1931 dir = SR_FLOWSET_ID_TO_DIR(flowset); 1932 fsid = SR_FLOWSET_ID_TO_IDX(flowset); 1933 if (fsid < 0 || fsid >= bkinfo->max_flows[dir]) { 1934 return BCM_E_PARAM; 1935 } 1936 fset = &bkinfo->flowsets[dir][fsid]; 1937 if (fset->num_flows == 0) { 1938 /* Not allocated */ 1939 return BCM_E_NOT_FOUND; 1940 } 1941 1942 /* Check if it's still in use */ 1943 SR_FLOWSET_LOCK(fset); 1944 if (fset->ref_count != 0) { 1945 SR_FLOWSET_UNLOCK(fset); 1946 return BCM_E_BUSY; 1947 } 1948 1949 /* Handle per-flow RX/TX specific clean up */ 1950 for (i = 0; i < fset->num_flows; i++) { 1951 if (dir == SR_FLOW_DIR_RX) { 1952 /* RX: de-allocate SN history slice and clear HW */ 1953 SR_FLOW_RX_LOCK(unit, fsid + i); 1954 if (SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_free) { 1955 (void)SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_free( 1956 unit, bkinfo->flows_rx[fsid + i].sn_slice); 1957 } 1958 bkinfo->flows_rx[fsid + i].sn_slice = NULL; 1959 if (SR_FLOW_MGMT_DEVINFO(unit)->clear_rx_flow) { 1960 (void)SR_FLOW_MGMT_DEVINFO(unit)->clear_rx_flow(unit, fsid + i); 1961 } 1962 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 1963 (void)bcmi_esw_tsn_mtu_profile_ref_dec( 1964 unit, bkinfo->flows_rx[fsid + i].config.ingress_mtu_profile); 1965 } 1966 SR_FLOW_RX_UNLOCK(unit, fsid + i); 1967 } else { 1968 /* TX: simply clear HW */ 1969 SR_FLOW_TX_LOCK(unit, fsid + i); 1970 if (SR_FLOW_MGMT_DEVINFO(unit)->clear_tx_flow) { 1971 (void)SR_FLOW_MGMT_DEVINFO(unit)->clear_tx_flow(unit, fsid + i); 1972 } 1973 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 1974 (void)bcmi_esw_tsn_mtu_profile_ref_dec( 1975 unit, bkinfo->flows_tx[fsid + i].config.ingress_mtu_profile); 1976 } 1977 SR_FLOW_TX_UNLOCK(unit, fsid + i); 1978 } 1979 /* update active flow information for event management */ 1980 (void)bcmi_esw_tsn_event_rx_flow_delete(unit, fsid + i); 1981 } 1982 1983 /* De-allocate the flowset (note that mutex is always there) */ 1984 rv = bcmi_esw_tsn_sr_flowset_free(unit, dir, fsid); 1985 SR_FLOWSET_UNLOCK(fset); 1986 return rv; 1987 } 1988 1989 /* Allocate an SR flowset with both TX and RX directions */ 1990 STATIC int 1991 bcmi_esw_tsn_sr_flowset_alloc( 1992 int unit, 1993 int dir, 1994 bcm_tsn_pri_map_t pri_map, 1995 int *pfsid) 1996 { 1997 bcmi_esw_tsn_bk_info_t *tsn_bk; 1998 tsn_sr_flows_bookkeeping_t *bkinfo; 1999 bcm_tsn_pri_map_config_t pmcfg; 2000 tsn_sr_flowidx_entry_t *fids; 2001 tsn_sr_flowset_t *fset; 2002 int fsid; 2003 int num_flows; 2004 int rv; 2005 int i; 2006 2007 /* parameter check */ 2008 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 2009 if (dir < 0 || dir >= SR_FLOW_DIR_COUNT || pfsid == NULL) { 2010 return BCM_E_PARAM; 2011 } 2012 bkinfo = &tsn_bk->sr_flows; 2013 2014 /* Get number of flows from this priority map */ 2015 num_flows = 1; 2016 if (pri_map != BCM_TSN_PRI_MAP_INVALID) { 2017 /* call API to get priority map configuration */ 2018 rv = bcm_esw_tsn_pri_map_get(unit, pri_map, &pmcfg); 2019 if (BCM_FAILURE(rv) || pmcfg.map_type != bcmTsnPriMapTypeSrFlow) { 2020 return BCM_E_PARAM; 2021 } 2022 /* Number of flows is max flow offset + 1 */ 2023 for (i = 0; i < pmcfg.num_map_entries; i++) { 2024 if ((pmcfg.map_entries[i].flags & 2025 BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET) && 2026 (pmcfg.map_entries[i].flow_offset > num_flows - 1)) { 2027 num_flows = pmcfg.map_entries[i].flow_offset + 1; 2028 } 2029 } 2030 } 2031 2032 /* Allocate flow indexes */ 2033 rv = bcmi_esw_tsn_sr_flow_idx_allocate(unit, dir, num_flows, &fids); 2034 if (BCM_FAILURE(rv)) { 2035 return rv; 2036 } 2037 2038 /* 2039 * For efficiency and convenience, the flowset index is the base (first) 2040 * flow index so that we don't need to have another set of flowset 2041 * allocation/free mechanism which would take more time in this time 2042 * critical operation. 2043 */ 2044 fsid = fids->flow_idx; 2045 assert(fsid >= 0 && fsid + num_flows <= bkinfo->max_flows[dir]); 2046 2047 /* Write to the flowset */ 2048 fset = &bkinfo->flowsets[dir][fsid]; 2049 SR_FLOWSET_LOCK(fset); 2050 assert(fset->num_flows == 0); 2051 fset->map_id = pri_map; 2052 fset->flow_ide = fids; 2053 fset->ref_count = 0; 2054 fset->num_flows = num_flows; 2055 SR_FLOWSET_UNLOCK(fset); 2056 2057 /* Return the allocated flowset index */ 2058 *pfsid = fsid; 2059 return BCM_E_NONE; 2060 } 2061 2062 /* 2063 * Function: 2064 * bcmi_esw_tsn_sr_rx_flowset_create 2065 * Purpose: 2066 * Create an SR RX flowset. 2067 * Parameters: 2068 * unit - (IN) unit number 2069 * pri_map - (IN) TSN priority map ID 2070 * def_cfg - (IN) default flow configuration 2071 * flowset - (OUT) flowset ID 2072 * Returns: 2073 * BCM_E_XXX 2074 * Notes: 2075 */ 2076 STATIC int 2077 bcmi_esw_tsn_sr_rx_flowset_create( 2078 int unit, 2079 bcm_tsn_pri_map_t pri_map, 2080 bcm_tsn_sr_rx_flow_config_t *def_cfg, 2081 bcm_tsn_sr_flowset_t *flowset) 2082 { 2083 bcmi_esw_tsn_bk_info_t *tsn_bk; 2084 tsn_sr_flows_bookkeeping_t *bkinfo; 2085 tsn_sr_flowset_t *fset; 2086 bcm_tsn_sr_flowset_t flowset_id; 2087 bcmi_tsn_sr_rx_flow_t *flow; 2088 bcmi_tsn_sr_seqnum_slice_t slice; 2089 int fsid; 2090 uint32 reset_mode; 2091 uint32 flags; 2092 int rv = BCM_E_NONE; 2093 int i; 2094 2095 /* parameter check */ 2096 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 2097 if (def_cfg == NULL || flowset == NULL) { 2098 return BCM_E_PARAM; 2099 } 2100 bkinfo = &tsn_bk->sr_flows; 2101 2102 /* sanity check for platform specific routines */ 2103 if (!SR_FLOW_MGMT_DEVINFO(unit)->check_rx_flow_config || 2104 !SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_alloc || 2105 !SR_FLOW_MGMT_DEVINFO(unit)->write_rx_flow) { 2106 return BCM_E_UNAVAIL; 2107 } 2108 2109 /* Validate flow configuration */ 2110 BCM_IF_ERROR_RETURN( 2111 SR_FLOW_MGMT_DEVINFO(unit)->check_rx_flow_config(unit, def_cfg)); 2112 2113 /* Allocate flows and flowset. Basic init check is also done inside. */ 2114 BCM_IF_ERROR_RETURN( 2115 bcmi_esw_tsn_sr_flowset_alloc(unit, SR_FLOW_DIR_RX, pri_map, &fsid)); 2116 flowset_id = SR_FLOWSET_ID_FROM_IDX(SR_FLOW_DIR_RX, fsid); 2117 2118 /* Write to the flowset software copy */ 2119 bkinfo = &tsn_bk->sr_flows; 2120 fset = &bkinfo->flowsets[SR_FLOW_DIR_RX][fsid]; 2121 SR_FLOWSET_LOCK(fset); 2122 sal_memcpy(&fset->config.rx, def_cfg, sizeof(fset->config.rx)); 2123 2124 /* Write to individual flows */ 2125 for (i = 0; i < fset->num_flows; i++) { 2126 SR_FLOW_RX_LOCK(unit, fsid + i); 2127 flow = &bkinfo->flows_rx[fsid + i]; 2128 2129 /* Allocate sequence number history pool for this flow */ 2130 rv = SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_alloc( 2131 unit, def_cfg->seqnum_history_win_size, &slice); 2132 if (BCM_FAILURE(rv)) { 2133 (void)bcmi_esw_tsn_sr_flowset_destroy(unit, flowset_id); 2134 SR_FLOW_RX_UNLOCK(unit, fsid + i); 2135 SR_FLOWSET_UNLOCK(fset); 2136 return rv; 2137 } 2138 2139 /* Store the flow configuration */ 2140 sal_memcpy(&flow->config, def_cfg, sizeof(flow->config)); 2141 flow->sn_slice = slice; 2142 2143 /* Write to HW */ 2144 rv = SR_FLOW_MGMT_DEVINFO(unit)->write_rx_flow(unit, fsid + i, flow); 2145 if (BCM_FAILURE(rv)) { 2146 (void)bcmi_esw_tsn_sr_flowset_destroy(unit, flowset_id); 2147 SR_FLOW_RX_UNLOCK(unit, fsid + i); 2148 SR_FLOWSET_UNLOCK(fset); 2149 return rv; 2150 } 2151 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 2152 (void)bcmi_esw_tsn_mtu_profile_ref_inc( 2153 unit, def_cfg->ingress_mtu_profile); 2154 } 2155 /* 2156 * Reset the flow as the initial state 2157 */ 2158 flags = BCM_TSN_SR_RX_FLOW_RESET_ALL; 2159 /* Get reset mode */ 2160 rv = bcm_esw_tsn_control_get( 2161 unit, bcmTsnControlSrSeqNumWindowResetMode, &reset_mode); 2162 if (BCM_FAILURE(rv)) { 2163 (void)bcmi_esw_tsn_sr_flowset_destroy(unit, flowset_id); 2164 SR_FLOW_RX_UNLOCK(unit, fsid + i); 2165 SR_FLOWSET_UNLOCK(fset); 2166 return rv; 2167 } 2168 if (reset_mode != BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_HW1) { 2169 /* Only need to set SN RESET bit for HW reset method 1 */ 2170 flags &= ~BCM_TSN_SR_RX_FLOW_RESET_SEQNUM_WIN_STATE; 2171 } 2172 /* Call flow reset function */ 2173 rv = bcm_esw_tsn_sr_rx_flow_reset( 2174 unit, flags, SR_FLOW_ID_FROM_IDX(SR_FLOW_DIR_RX, fsid + i)); 2175 if (BCM_FAILURE(rv)) { 2176 (void)bcmi_esw_tsn_sr_flowset_destroy(unit, flowset_id); 2177 SR_FLOW_RX_UNLOCK(unit, fsid + i); 2178 SR_FLOWSET_UNLOCK(fset); 2179 return rv; 2180 } 2181 2182 SR_FLOW_RX_UNLOCK(unit, fsid + i); 2183 2184 /* provide active flow information for event management */ 2185 (void)bcmi_esw_tsn_event_rx_flow_add(unit, fsid + i); 2186 } 2187 SR_FLOWSET_UNLOCK(fset); 2188 2189 /* Convert to user flowset ID */ 2190 *flowset = flowset_id; 2191 return BCM_E_NONE; 2192 } 2193 2194 /* 2195 * Function: 2196 * bcmi_esw_tsn_sr_tx_flowset_create 2197 * Purpose: 2198 * Create an SR TX flowset. 2199 * Parameters: 2200 * unit - (IN) unit number 2201 * pri_map - (IN) TSN priority map ID 2202 * def_cfg - (IN) default flow configuration 2203 * flowset - (OUT) flowset ID 2204 * Returns: 2205 * BCM_E_XXX 2206 * Notes: 2207 */ 2208 STATIC int 2209 bcmi_esw_tsn_sr_tx_flowset_create( 2210 int unit, 2211 bcm_tsn_pri_map_t pri_map, 2212 bcm_tsn_sr_tx_flow_config_t *def_cfg, 2213 bcm_tsn_sr_flowset_t *flowset) 2214 { 2215 bcmi_esw_tsn_bk_info_t *tsn_bk; 2216 tsn_sr_flows_bookkeeping_t *bkinfo; 2217 tsn_sr_flowset_t *fset; 2218 bcm_tsn_sr_flowset_t flowset_id; 2219 bcmi_tsn_sr_tx_flow_t *flow; 2220 int fsid; 2221 int rv = BCM_E_NONE; 2222 int i; 2223 2224 /* parameter check */ 2225 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 2226 if (def_cfg == NULL || flowset == NULL) { 2227 return BCM_E_PARAM; 2228 } 2229 bkinfo = &tsn_bk->sr_flows; 2230 2231 /* Validate flow configuration */ 2232 if (SR_FLOW_MGMT_DEVINFO(unit)->check_tx_flow_config) { 2233 rv = SR_FLOW_MGMT_DEVINFO(unit)->check_tx_flow_config(unit, def_cfg); 2234 if (BCM_FAILURE(rv)) { 2235 return rv; 2236 } 2237 } else { 2238 return BCM_E_UNAVAIL; 2239 } 2240 2241 /* Allocate flows and flowset. Basic init check is also done inside. */ 2242 rv = bcmi_esw_tsn_sr_flowset_alloc(unit, SR_FLOW_DIR_TX, pri_map, &fsid); 2243 if (BCM_FAILURE(rv)) { 2244 return rv; 2245 } 2246 flowset_id = SR_FLOWSET_ID_FROM_IDX(SR_FLOW_DIR_TX, fsid); 2247 2248 /* Write to the flowset software copy */ 2249 bkinfo = &tsn_bk->sr_flows; 2250 fset = &bkinfo->flowsets[SR_FLOW_DIR_TX][fsid]; 2251 SR_FLOWSET_LOCK(fset); 2252 sal_memcpy(&fset->config.tx, def_cfg, sizeof(fset->config.tx)); 2253 2254 /* Write to individual flows */ 2255 for (i = 0; i < fset->num_flows; i++) { 2256 SR_FLOW_TX_LOCK(unit, fsid + i); 2257 flow = &bkinfo->flows_tx[fsid + i]; 2258 2259 /* Save a SW copy */ 2260 sal_memcpy(&flow->config, def_cfg, sizeof(flow->config)); 2261 2262 /* Write to HW */ 2263 if (SR_FLOW_MGMT_DEVINFO(unit)->write_tx_flow) { 2264 rv = SR_FLOW_MGMT_DEVINFO(unit)->write_tx_flow( 2265 unit, fsid + i, flow); 2266 if (BCM_FAILURE(rv)) { 2267 (void)bcmi_esw_tsn_sr_flowset_destroy(unit, flowset_id); 2268 SR_FLOW_TX_UNLOCK(unit, fsid + i); 2269 SR_FLOWSET_UNLOCK(fset); 2270 return rv; 2271 } 2272 } else { 2273 (void)bcmi_esw_tsn_sr_flowset_destroy(unit, flowset_id); 2274 SR_FLOW_TX_UNLOCK(unit, fsid + i); 2275 SR_FLOWSET_UNLOCK(fset); 2276 return BCM_E_UNAVAIL; 2277 } 2278 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 2279 (void)bcmi_esw_tsn_mtu_profile_ref_inc( 2280 unit, def_cfg->ingress_mtu_profile); 2281 } 2282 SR_FLOW_TX_UNLOCK(unit, fsid + i); 2283 } 2284 SR_FLOWSET_UNLOCK(fset); 2285 2286 /* Convert to user flowset ID */ 2287 *flowset = flowset_id; 2288 return BCM_E_NONE; 2289 } 2290 2291 /* 2292 * Function: 2293 * bcmi_esw_tsn_sr_tx_flowset_config_get 2294 * Purpose: 2295 * Get default configuration for the specified SR flowset 2296 * Parameters: 2297 * unit - (IN) unit number 2298 * flowset - (IN) flowset ID 2299 * pri_map - (OUT) TSN priority map ID 2300 * default_config - (OUT) default flow configuration 2301 * Returns: 2302 * BCM_E_XXX 2303 * Notes: 2304 * If it's called with a RX flowset, BCM_E_BADID is returned 2305 */ 2306 STATIC int 2307 bcmi_esw_tsn_sr_tx_flowset_config_get( 2308 int unit, 2309 bcm_tsn_sr_flowset_t flowset, 2310 bcm_tsn_pri_map_t *pri_map, 2311 bcm_tsn_sr_tx_flow_config_t *config) 2312 { 2313 bcmi_esw_tsn_bk_info_t *tsn_bk; 2314 tsn_sr_flows_bookkeeping_t *bkinfo; 2315 tsn_sr_flowset_t *fset; 2316 int dir, fsid; 2317 2318 /* parameter check */ 2319 if (pri_map == NULL || config == NULL) { 2320 return BCM_E_PARAM; 2321 } 2322 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 2323 bkinfo = &tsn_bk->sr_flows; 2324 dir = SR_FLOWSET_ID_TO_DIR(flowset); 2325 fsid = SR_FLOWSET_ID_TO_IDX(flowset); 2326 if (dir != SR_FLOW_DIR_TX) { 2327 return BCM_E_BADID; 2328 } 2329 if (fsid < 0 || fsid >= bkinfo->max_flows[dir]) { 2330 return BCM_E_PARAM; 2331 } 2332 fset = &bkinfo->flowsets[dir][fsid]; 2333 SR_FLOWSET_LOCK(fset); 2334 if (fset->num_flows == 0) { 2335 /* Not allocated */ 2336 SR_FLOWSET_UNLOCK(fset); 2337 return BCM_E_NOT_FOUND; 2338 } 2339 2340 /* Return the value */ 2341 *pri_map = fset->map_id; 2342 sal_memcpy(config, &fset->config.tx, sizeof(fset->config.tx)); 2343 SR_FLOWSET_UNLOCK(fset); 2344 return BCM_E_NONE; 2345 } 2346 2347 /* 2348 * Function: 2349 * bcmi_esw_tsn_sr_rx_flowset_config_get 2350 * Purpose: 2351 * Get default configuration for the specified SR flowset 2352 * Parameters: 2353 * unit - (IN) unit number 2354 * flowset - (IN) flowset ID 2355 * pri_map - (OUT) TSN priority map ID 2356 * default_config - (OUT) default flow configuration 2357 * Returns: 2358 * BCM_E_XXX 2359 * Notes: 2360 * If it's called with a TX flowset, BCM_E_BADID is returned 2361 */ 2362 STATIC int 2363 bcmi_esw_tsn_sr_rx_flowset_config_get( 2364 int unit, 2365 bcm_tsn_sr_flowset_t flowset, 2366 bcm_tsn_pri_map_t *pri_map, 2367 bcm_tsn_sr_rx_flow_config_t *config) 2368 { 2369 bcmi_esw_tsn_bk_info_t *tsn_bk; 2370 tsn_sr_flows_bookkeeping_t *bkinfo; 2371 tsn_sr_flowset_t *fset; 2372 int dir, fsid; 2373 2374 /* parameter check */ 2375 if (pri_map == NULL || config == NULL) { 2376 return BCM_E_PARAM; 2377 } 2378 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 2379 bkinfo = &tsn_bk->sr_flows; 2380 dir = SR_FLOWSET_ID_TO_DIR(flowset); 2381 fsid = SR_FLOWSET_ID_TO_IDX(flowset); 2382 if (dir != SR_FLOW_DIR_RX) { 2383 return BCM_E_BADID; 2384 } 2385 if (fsid < 0 || fsid >= bkinfo->max_flows[dir]) { 2386 return BCM_E_PARAM; 2387 } 2388 fset = &bkinfo->flowsets[dir][fsid]; 2389 SR_FLOWSET_LOCK(fset); 2390 if (fset->num_flows == 0) { 2391 /* Not allocated */ 2392 SR_FLOWSET_UNLOCK(fset); 2393 return BCM_E_NOT_FOUND; 2394 } 2395 2396 /* Return the value */ 2397 *pri_map = fset->map_id; 2398 sal_memcpy(config, &fset->config.rx, sizeof(fset->config.rx)); 2399 SR_FLOWSET_UNLOCK(fset); 2400 return BCM_E_NONE; 2401 } 2402 2403 /* 2404 * Function: 2405 * bcmi_esw_tsn_sr_flowset_status_get 2406 * Purpose: 2407 * Get current status of specified SR flowset 2408 * Parameters: 2409 * unit - (IN) unit number 2410 * flowset - (IN) flowset ID 2411 * status - (OUT) status structure 2412 * Returns: 2413 * BCM_E_XXX 2414 * Notes: 2415 */ 2416 STATIC int 2417 bcmi_esw_tsn_sr_flowset_status_get( 2418 int unit, 2419 bcm_tsn_sr_flowset_t flowset, 2420 bcm_tsn_sr_flowset_status_t *status) 2421 { 2422 bcmi_esw_tsn_bk_info_t *tsn_bk; 2423 tsn_sr_flows_bookkeeping_t *bkinfo; 2424 tsn_sr_flowset_t *fset; 2425 int dir, fsid; 2426 2427 /* parameter check */ 2428 if (status == NULL) { 2429 return BCM_E_PARAM; 2430 } 2431 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 2432 bkinfo = &tsn_bk->sr_flows; 2433 dir = SR_FLOWSET_ID_TO_DIR(flowset); 2434 fsid = SR_FLOWSET_ID_TO_IDX(flowset); 2435 if (fsid < 0 || fsid >= bkinfo->max_flows[dir]) { 2436 return BCM_E_PARAM; 2437 } 2438 fset = &bkinfo->flowsets[dir][fsid]; 2439 SR_FLOWSET_LOCK(fset); 2440 if (fset->num_flows == 0) { 2441 /* Not allocated */ 2442 SR_FLOWSET_UNLOCK(fset); 2443 return BCM_E_NOT_FOUND; 2444 } 2445 2446 /* Return the value */ 2447 status->active = fset->ref_count > 0 ? 1 : 0; 2448 status->count = fset->num_flows; 2449 SR_FLOWSET_UNLOCK(fset); 2450 return BCM_E_NONE; 2451 } 2452 2453 /* 2454 * Function: 2455 * bcmi_esw_tsn_sr_flowset_ref_inc 2456 * Purpose: 2457 * Increase reference count for the specified SR flowset 2458 * Parameters: 2459 * unit - (IN) unit number 2460 * flowset - (IN) flowset ID 2461 * Returns: 2462 * BCM_E_XXX 2463 * Notes: 2464 */ 2465 int 2466 bcmi_esw_tsn_sr_flowset_ref_inc(int unit, bcm_tsn_sr_flowset_t flowset) 2467 { 2468 bcmi_esw_tsn_bk_info_t *tsn_bk; 2469 tsn_sr_flows_bookkeeping_t *bkinfo; 2470 tsn_sr_flowset_t *fset; 2471 int dir, fsid; 2472 2473 /* parameter check */ 2474 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 2475 bkinfo = &tsn_bk->sr_flows; 2476 dir = SR_FLOWSET_ID_TO_DIR(flowset); 2477 fsid = SR_FLOWSET_ID_TO_IDX(flowset); 2478 if (fsid < 0 || fsid >= bkinfo->max_flows[dir]) { 2479 return BCM_E_PARAM; 2480 } 2481 fset = &bkinfo->flowsets[dir][fsid]; 2482 SR_FLOWSET_LOCK(fset); 2483 if (fset->num_flows == 0) { 2484 /* Not allocated */ 2485 SR_FLOWSET_UNLOCK(fset); 2486 return BCM_E_NOT_FOUND; 2487 } 2488 /* Update the reference count */ 2489 fset->ref_count++; 2490 SR_FLOWSET_UNLOCK(fset); 2491 return BCM_E_NONE; 2492 } 2493 2494 /* 2495 * Function: 2496 * bcmi_esw_tsn_sr_flowset_ref_dec 2497 * Purpose: 2498 * Decrease reference count for the specified SR flowset 2499 * Parameters: 2500 * unit - (IN) unit number 2501 * flowset - (IN) flowset ID 2502 * Returns: 2503 * BCM_E_XXX 2504 * Notes: 2505 */ 2506 int 2507 bcmi_esw_tsn_sr_flowset_ref_dec(int unit, bcm_tsn_sr_flowset_t flowset) 2508 { 2509 bcmi_esw_tsn_bk_info_t *tsn_bk; 2510 tsn_sr_flows_bookkeeping_t *bkinfo; 2511 tsn_sr_flowset_t *fset; 2512 int dir, fsid; 2513 2514 /* parameter check */ 2515 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 2516 bkinfo = &tsn_bk->sr_flows; 2517 dir = SR_FLOWSET_ID_TO_DIR(flowset); 2518 fsid = SR_FLOWSET_ID_TO_IDX(flowset); 2519 if (fsid < 0 || fsid >= bkinfo->max_flows[dir]) { 2520 return BCM_E_PARAM; 2521 } 2522 fset = &bkinfo->flowsets[dir][fsid]; 2523 SR_FLOWSET_LOCK(fset); 2524 if (fset->num_flows == 0) { 2525 /* Not allocated */ 2526 SR_FLOWSET_UNLOCK(fset); 2527 return BCM_E_NOT_FOUND; 2528 } 2529 /* Update the reference count */ 2530 if (fset->ref_count > 0) { 2531 fset->ref_count--; 2532 } 2533 SR_FLOWSET_UNLOCK(fset); 2534 return BCM_E_NONE; 2535 } 2536 2537 /* 2538 * Function: 2539 * bcmi_esw_tsn_sr_flowset_traverse 2540 * Purpose: 2541 * Traverse all created SR flowsets 2542 * Parameters: 2543 * unit - (IN) unit number 2544 * is_rx - (IN) 1 for RX flowsets; 0 for TX flowsets 2545 * cb - (IN) callback function 2546 * user_data - (IN) user data supplied to the callback function 2547 * Returns: 2548 * BCM_E_XXX 2549 * Notes: 2550 */ 2551 STATIC int 2552 bcmi_esw_tsn_sr_flowset_traverse( 2553 int unit, 2554 int is_rx, 2555 bcm_tsn_sr_flowset_traverse_cb cb, 2556 void *user_data) 2557 { 2558 bcmi_esw_tsn_bk_info_t *tsn_bk; 2559 tsn_sr_flows_bookkeeping_t *bkinfo; 2560 tsn_sr_flowset_t *fset; 2561 int dir; 2562 int rv = BCM_E_NONE; 2563 int i; 2564 2565 /* parameter check */ 2566 if (cb == NULL) { 2567 return BCM_E_PARAM; 2568 } 2569 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 2570 2571 /* Loop through the flowset array */ 2572 bkinfo = &tsn_bk->sr_flows; 2573 dir = is_rx ? SR_FLOW_DIR_RX : SR_FLOW_DIR_TX; 2574 for (i = 0; i < bkinfo->max_flows[dir]; i++) { 2575 fset = &bkinfo->flowsets[dir][i]; 2576 SR_FLOWSET_LOCK(fset); 2577 if (fset->num_flows != 0) { 2578 rv = cb(unit, SR_FLOWSET_ID_FROM_IDX(dir, i), user_data); 2579 } 2580 SR_FLOWSET_UNLOCK(fset); 2581 BCM_IF_ERROR_RETURN(rv); 2582 } 2583 2584 return BCM_E_NONE; 2585 } 2586 2587 /* 2588 * Function: 2589 * bcmi_esw_tsn_sr_flowset_flow_get 2590 * Purpose: 2591 * Retrieve an individual SR flow based on the flow offset from a flow set. 2592 * Parameters: 2593 * unit - (IN) unit number 2594 * flowset - (IN) flowset ID 2595 * index - (IN) index of the flow 2596 * flow_id - (OUT) flow ID 2597 * Returns: 2598 * BCM_E_XXX 2599 * Notes: 2600 */ 2601 STATIC int 2602 bcmi_esw_tsn_sr_flowset_flow_get( 2603 int unit, 2604 bcm_tsn_sr_flowset_t flowset, 2605 int index, 2606 bcm_tsn_sr_flow_t *flow_id) 2607 { 2608 bcmi_esw_tsn_bk_info_t *tsn_bk; 2609 tsn_sr_flows_bookkeeping_t *bkinfo; 2610 tsn_sr_flowset_t *fset; 2611 int dir; 2612 int fsid; 2613 2614 /* parameter check */ 2615 if (flow_id == NULL) { 2616 return BCM_E_PARAM; 2617 } 2618 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 2619 bkinfo = &tsn_bk->sr_flows; 2620 dir = SR_FLOWSET_ID_TO_DIR(flowset); 2621 fsid = SR_FLOWSET_ID_TO_IDX(flowset); 2622 if (fsid < 0 || fsid >= bkinfo->max_flows[dir]) { 2623 return BCM_E_PARAM; 2624 } 2625 fset = &bkinfo->flowsets[dir][fsid]; 2626 SR_FLOWSET_LOCK(fset); 2627 if (fset->num_flows == 0) { 2628 /* Not allocated */ 2629 SR_FLOWSET_UNLOCK(fset); 2630 return BCM_E_NOT_FOUND; 2631 } 2632 if (index < 0 || index >= fset->num_flows) { 2633 SR_FLOWSET_UNLOCK(fset); 2634 return BCM_E_PARAM; 2635 } 2636 assert(fsid + index < bkinfo->max_flows[dir]); 2637 2638 /* Got SW flow ID */ 2639 *flow_id = SR_FLOW_ID_FROM_IDX(dir, fsid + index); 2640 SR_FLOWSET_UNLOCK(fset); 2641 return BCM_E_NONE; 2642 } 2643 2644 /* 2645 * Function: 2646 * bcmi_esw_tsn_sr_tx_flow_config_get 2647 * Purpose: 2648 * Get configuration for the specified SR flow 2649 * Parameters: 2650 * unit - (IN) unit number 2651 * flow_id - (IN) flow ID 2652 * config - (OUT) flow configuration 2653 * Returns: 2654 * BCM_E_XXX 2655 * Notes: 2656 * If it's called with a RX flowset, BCM_E_BADID is returned 2657 */ 2658 STATIC int 2659 bcmi_esw_tsn_sr_tx_flow_config_get( 2660 int unit, 2661 bcm_tsn_sr_flow_t flow_id, 2662 bcm_tsn_sr_tx_flow_config_t *config) 2663 { 2664 bcmi_esw_tsn_bk_info_t *tsn_bk; 2665 tsn_sr_flows_bookkeeping_t *bkinfo; 2666 int fidx; 2667 int dir; 2668 int i; 2669 2670 /* parameter check */ 2671 if (config == NULL) { 2672 return BCM_E_PARAM; 2673 } 2674 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 2675 bkinfo = &tsn_bk->sr_flows; 2676 dir = SR_FLOW_ID_TO_DIR(flow_id); 2677 fidx = SR_FLOW_ID_TO_IDX(flow_id); 2678 if (dir != SR_FLOW_DIR_TX) { 2679 return BCM_E_BADID; 2680 } 2681 if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) { 2682 return BCM_E_PARAM; 2683 } 2684 2685 /* Validate if it's from a flowset */ 2686 for (i = fidx; i >= 0; i--) { 2687 if (bkinfo->flowsets[dir][i].num_flows != 0) { 2688 if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) { 2689 break; 2690 } else { 2691 return BCM_E_NOT_FOUND; 2692 } 2693 } 2694 } 2695 if (i == -1) { 2696 /* No valid flowsets */ 2697 return BCM_E_NOT_FOUND; 2698 } 2699 2700 /* Return the configuration */ 2701 SR_FLOW_TX_LOCK(unit, fidx); 2702 sal_memcpy(config, &bkinfo->flows_tx[fidx].config, sizeof(*config)); 2703 SR_FLOW_TX_UNLOCK(unit, fidx); 2704 return BCM_E_NONE; 2705 } 2706 2707 /* 2708 * Function: 2709 * bcmi_esw_tsn_sr_rx_flow_config_get 2710 * Purpose: 2711 * Get configuration for the specified SR flow 2712 * Parameters: 2713 * unit - (IN) unit number 2714 * flow_id - (IN) flow ID 2715 * config - (OUT) flow configuration 2716 * Returns: 2717 * BCM_E_XXX 2718 * Notes: 2719 * If it's called with a TX flowset, BCM_E_BADID is returned 2720 */ 2721 STATIC int 2722 bcmi_esw_tsn_sr_rx_flow_config_get( 2723 int unit, 2724 bcm_tsn_sr_flow_t flow_id, 2725 bcm_tsn_sr_rx_flow_config_t *config) 2726 { 2727 bcmi_esw_tsn_bk_info_t *tsn_bk; 2728 tsn_sr_flows_bookkeeping_t *bkinfo; 2729 int fidx; 2730 int dir; 2731 int i; 2732 2733 /* parameter check */ 2734 if (config == NULL) { 2735 return BCM_E_PARAM; 2736 } 2737 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 2738 bkinfo = &tsn_bk->sr_flows; 2739 dir = SR_FLOW_ID_TO_DIR(flow_id); 2740 fidx = SR_FLOW_ID_TO_IDX(flow_id); 2741 if (dir != SR_FLOW_DIR_RX) { 2742 return BCM_E_BADID; 2743 } 2744 if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) { 2745 return BCM_E_PARAM; 2746 } 2747 2748 /* Validate if it's from a flowset */ 2749 for (i = fidx; i >= 0; i--) { 2750 if (bkinfo->flowsets[dir][i].num_flows != 0) { 2751 if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) { 2752 break; 2753 } else { 2754 return BCM_E_NOT_FOUND; 2755 } 2756 } 2757 } 2758 if (i == -1) { 2759 /* No valid flowsets */ 2760 return BCM_E_NOT_FOUND; 2761 } 2762 2763 /* Return the configuration */ 2764 SR_FLOW_RX_LOCK(unit, fidx); 2765 sal_memcpy(config, &bkinfo->flows_rx[fidx].config, sizeof(*config)); 2766 SR_FLOW_RX_UNLOCK(unit, fidx); 2767 return BCM_E_NONE; 2768 } 2769 2770 /* 2771 * Function: 2772 * bcmi_esw_tsn_sr_tx_flow_config_set 2773 * Purpose: 2774 * Set configuration for the specified SR flow 2775 * Parameters: 2776 * unit - (IN) unit number 2777 * flow_id - (IN) flow ID 2778 * config - (IN) flow configuration 2779 * Returns: 2780 * BCM_E_XXX 2781 * Notes: 2782 * If it's called with a RX flow, BCM_E_BADID is returned 2783 */ 2784 STATIC int 2785 bcmi_esw_tsn_sr_tx_flow_config_set( 2786 int unit, 2787 bcm_tsn_sr_flow_t flow_id, 2788 bcm_tsn_sr_tx_flow_config_t *config) 2789 { 2790 bcmi_esw_tsn_bk_info_t *tsn_bk; 2791 tsn_sr_flows_bookkeeping_t *bkinfo; 2792 int fidx; 2793 int dir; 2794 int rv; 2795 int i; 2796 2797 /* parameter check */ 2798 if (config == NULL) { 2799 return BCM_E_PARAM; 2800 } 2801 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 2802 bkinfo = &tsn_bk->sr_flows; 2803 dir = SR_FLOW_ID_TO_DIR(flow_id); 2804 fidx = SR_FLOW_ID_TO_IDX(flow_id); 2805 if (dir != SR_FLOW_DIR_TX) { 2806 return BCM_E_BADID; 2807 } 2808 if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) { 2809 return BCM_E_PARAM; 2810 } 2811 2812 /* Validate if it's from a flowset */ 2813 for (i = fidx; i >= 0; i--) { 2814 if (bkinfo->flowsets[dir][i].num_flows != 0) { 2815 if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) { 2816 break; 2817 } else { 2818 return BCM_E_NOT_FOUND; 2819 } 2820 } 2821 } 2822 if (i == -1) { 2823 /* No valid flowsets */ 2824 return BCM_E_NOT_FOUND; 2825 } 2826 2827 /* Validate flow configuration */ 2828 if (SR_FLOW_MGMT_DEVINFO(unit)->check_tx_flow_config) { 2829 rv = SR_FLOW_MGMT_DEVINFO(unit)->check_tx_flow_config(unit, config); 2830 if (BCM_FAILURE(rv)) { 2831 return rv; 2832 } 2833 } else { 2834 return BCM_E_UNAVAIL; 2835 } 2836 2837 /* 2838 * Configure the flow using the supplied configuration 2839 */ 2840 SR_FLOW_TX_LOCK(unit, fidx); 2841 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 2842 /* Clear the old MTU profile id */ 2843 if (SR_FLOW_MGMT_DEVINFO(unit)->clear_tx_flow_mtu) { 2844 rv = SR_FLOW_MGMT_DEVINFO(unit)->clear_tx_flow_mtu(unit, fidx); 2845 if (BCM_FAILURE(rv)) { 2846 SR_FLOW_TX_UNLOCK(unit, fidx); 2847 return rv; 2848 } 2849 } else { 2850 SR_FLOW_TX_UNLOCK(unit, fidx); 2851 return BCM_E_UNAVAIL; 2852 } 2853 (void)bcmi_esw_tsn_mtu_profile_ref_dec( 2854 unit, bkinfo->flows_tx[fidx].config.ingress_mtu_profile); 2855 } 2856 /* Copy to SW flow info */ 2857 sal_memcpy(&bkinfo->flows_tx[fidx].config, config, sizeof(*config)); 2858 /* Write to HW */ 2859 if (SR_FLOW_MGMT_DEVINFO(unit)->write_tx_flow) { 2860 rv = SR_FLOW_MGMT_DEVINFO(unit)->write_tx_flow( 2861 unit, fidx, &bkinfo->flows_tx[fidx]); 2862 if (BCM_FAILURE(rv)) { 2863 SR_FLOW_TX_UNLOCK(unit, fidx); 2864 return rv; 2865 } 2866 } else { 2867 SR_FLOW_TX_UNLOCK(unit, fidx); 2868 return BCM_E_UNAVAIL; 2869 } 2870 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 2871 (void)bcmi_esw_tsn_mtu_profile_ref_inc( 2872 unit, bkinfo->flows_tx[fidx].config.ingress_mtu_profile); 2873 } 2874 SR_FLOW_TX_UNLOCK(unit, fidx); 2875 return BCM_E_NONE; 2876 } 2877 2878 /* 2879 * Function: 2880 * bcmi_esw_tsn_sr_rx_flow_config_set 2881 * Purpose: 2882 * Set configuration for the specified SR flow 2883 * Parameters: 2884 * unit - (IN) unit number 2885 * flow_id - (IN) flow ID 2886 * config - (IN) flow configuration 2887 * Returns: 2888 * BCM_E_XXX 2889 * Notes: 2890 * If it's called with a TX flow, BCM_E_BADID is returned 2891 */ 2892 STATIC int 2893 bcmi_esw_tsn_sr_rx_flow_config_set( 2894 int unit, 2895 bcm_tsn_sr_flow_t flow_id, 2896 bcm_tsn_sr_rx_flow_config_t *config) 2897 { 2898 bcmi_esw_tsn_bk_info_t *tsn_bk; 2899 tsn_sr_flows_bookkeeping_t *bkinfo; 2900 bcmi_tsn_sr_seqnum_slice_t slice; 2901 tsn_sr_flowset_t *fset; 2902 uint32 reset_mode; 2903 uint32 flags; 2904 int fidx; 2905 int dir; 2906 int rv; 2907 int i; 2908 2909 /* parameter check */ 2910 if (config == NULL) { 2911 return BCM_E_PARAM; 2912 } 2913 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 2914 bkinfo = &tsn_bk->sr_flows; 2915 dir = SR_FLOW_ID_TO_DIR(flow_id); 2916 fidx = SR_FLOW_ID_TO_IDX(flow_id); 2917 if (dir != SR_FLOW_DIR_RX) { 2918 return BCM_E_BADID; 2919 } 2920 if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) { 2921 return BCM_E_PARAM; 2922 } 2923 2924 /* Validate if it's from a flowset */ 2925 fset = NULL; 2926 for (i = fidx; i >= 0; i--) { 2927 if (bkinfo->flowsets[dir][i].num_flows != 0) { 2928 fset = &bkinfo->flowsets[dir][i]; 2929 if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) { 2930 break; 2931 } else { 2932 return BCM_E_NOT_FOUND; 2933 } 2934 } 2935 } 2936 if (fset == NULL) { 2937 /* No valid flowsets */ 2938 return BCM_E_NOT_FOUND; 2939 } 2940 2941 /* Validate flow configuration */ 2942 if (SR_FLOW_MGMT_DEVINFO(unit)->check_rx_flow_config) { 2943 rv = SR_FLOW_MGMT_DEVINFO(unit)->check_rx_flow_config(unit, config); 2944 if (BCM_FAILURE(rv)) { 2945 return rv; 2946 } 2947 } else { 2948 return BCM_E_UNAVAIL; 2949 } 2950 2951 /* Get reset mode here before we modify anything */ 2952 rv = bcm_esw_tsn_control_get( 2953 unit, bcmTsnControlSrSeqNumWindowResetMode, &reset_mode); 2954 if (BCM_FAILURE(rv)) { 2955 return rv; 2956 } 2957 2958 /* Can't change window size when its flowset is active */ 2959 SR_FLOWSET_LOCK(fset); 2960 if (fset->ref_count != 0 && 2961 config->seqnum_history_win_size != 2962 bkinfo->flows_rx[fidx].config.seqnum_history_win_size) { 2963 SR_FLOWSET_UNLOCK(fset); 2964 return BCM_E_BUSY; 2965 } 2966 2967 /* 2968 * Configure the flow using the supplied configuration 2969 */ 2970 SR_FLOW_RX_LOCK(unit, fidx); 2971 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 2972 /* Clear the old MTU profile id */ 2973 if (SR_FLOW_MGMT_DEVINFO(unit)->clear_rx_flow_mtu) { 2974 rv = SR_FLOW_MGMT_DEVINFO(unit)->clear_rx_flow_mtu(unit, fidx); 2975 if (BCM_FAILURE(rv)) { 2976 SR_FLOW_RX_UNLOCK(unit, fidx); 2977 return rv; 2978 } 2979 } else { 2980 SR_FLOW_RX_UNLOCK(unit, fidx); 2981 return BCM_E_UNAVAIL; 2982 } 2983 (void)bcmi_esw_tsn_mtu_profile_ref_dec( 2984 unit, bkinfo->flows_rx[fidx].config.ingress_mtu_profile); 2985 } 2986 /* Re-allocate sequence number history pool if necessary */ 2987 if (config->seqnum_history_win_size != 2988 bkinfo->flows_rx[fidx].config.seqnum_history_win_size) { 2989 if (!SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_alloc || 2990 !SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_free) { 2991 SR_FLOW_RX_UNLOCK(unit, fidx); 2992 SR_FLOWSET_UNLOCK(fset); 2993 return BCM_E_UNAVAIL; 2994 } 2995 /* Try allocating first */ 2996 rv = SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_alloc( 2997 unit, config->seqnum_history_win_size, &slice); 2998 if (BCM_FAILURE(rv)) { 2999 SR_FLOW_RX_UNLOCK(unit, fidx); 3000 SR_FLOWSET_UNLOCK(fset); 3001 return rv; 3002 } 3003 /* Free the original */ 3004 (void)SR_FLOW_MGMT_DEVINFO(unit)->seqnum_slice_free( 3005 unit, bkinfo->flows_rx[fidx].sn_slice); 3006 /* Now we use the new slice */ 3007 bkinfo->flows_rx[fidx].sn_slice = slice; 3008 } 3009 /* Copy to SW flow info */ 3010 sal_memcpy(&bkinfo->flows_rx[fidx].config, config, sizeof(*config)); 3011 /* Write to HW */ 3012 if (SR_FLOW_MGMT_DEVINFO(unit)->write_rx_flow) { 3013 rv = SR_FLOW_MGMT_DEVINFO(unit)->write_rx_flow( 3014 unit, fidx, &bkinfo->flows_rx[fidx]); 3015 if (BCM_FAILURE(rv)) { 3016 SR_FLOW_RX_UNLOCK(unit, fidx); 3017 SR_FLOWSET_UNLOCK(fset); 3018 return rv; 3019 } 3020 } else { 3021 SR_FLOW_RX_UNLOCK(unit, fidx); 3022 SR_FLOWSET_UNLOCK(fset); 3023 return BCM_E_UNAVAIL; 3024 } 3025 3026 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 3027 (void)bcmi_esw_tsn_mtu_profile_ref_inc( 3028 unit, bkinfo->flows_rx[fidx].config.ingress_mtu_profile); 3029 } 3030 3031 /* 3032 * Reset the flow as the initial state 3033 */ 3034 flags = BCM_TSN_SR_RX_FLOW_RESET_ALL; 3035 /* Update flags based on reset mode */ 3036 if (reset_mode != BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_HW1) { 3037 /* Only need to set SN RESET bit for HW reset method 1 */ 3038 flags &= ~BCM_TSN_SR_RX_FLOW_RESET_SEQNUM_WIN_STATE; 3039 } 3040 /* Call flow reset function */ 3041 rv = bcm_esw_tsn_sr_rx_flow_reset( 3042 unit, flags, SR_FLOW_ID_FROM_IDX(SR_FLOW_DIR_RX, fidx)); 3043 if (BCM_FAILURE(rv)) { 3044 SR_FLOW_RX_UNLOCK(unit, fidx); 3045 SR_FLOWSET_UNLOCK(fset); 3046 return rv; 3047 } 3048 3049 SR_FLOW_RX_UNLOCK(unit, fidx); 3050 SR_FLOWSET_UNLOCK(fset); 3051 return BCM_E_NONE; 3052 } 3053 3054 /* 3055 * Function: 3056 * bcmi_esw_tsn_sr_tx_flow_status_get 3057 * Purpose: 3058 * Get status for the specified flow 3059 * Parameters: 3060 * unit - (IN) unit number 3061 * flow_id - (IN) flow ID 3062 * status - (OUT) flow status 3063 * Returns: 3064 * BCM_E_XXX 3065 * Notes: 3066 * If it's called with a RX flow, BCM_E_BADID is returned 3067 */ 3068 STATIC int 3069 bcmi_esw_tsn_sr_tx_flow_status_get( 3070 int unit, 3071 bcm_tsn_sr_flow_t flow_id, 3072 bcm_tsn_sr_tx_flow_status_t *status) 3073 { 3074 bcmi_esw_tsn_bk_info_t *tsn_bk; 3075 tsn_sr_flows_bookkeeping_t *bkinfo; 3076 int fidx; 3077 int dir; 3078 int rv; 3079 int i; 3080 3081 /* parameter check */ 3082 if (status == NULL) { 3083 return BCM_E_PARAM; 3084 } 3085 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 3086 bkinfo = &tsn_bk->sr_flows; 3087 dir = SR_FLOW_ID_TO_DIR(flow_id); 3088 fidx = SR_FLOW_ID_TO_IDX(flow_id); 3089 if (dir != SR_FLOW_DIR_TX) { 3090 return BCM_E_BADID; 3091 } 3092 if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) { 3093 return BCM_E_PARAM; 3094 } 3095 3096 /* Validate if it's from a flowset */ 3097 for (i = fidx; i >= 0; i--) { 3098 if (bkinfo->flowsets[dir][i].num_flows != 0) { 3099 if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) { 3100 break; 3101 } else { 3102 return BCM_E_NOT_FOUND; 3103 } 3104 } 3105 } 3106 if (i == -1) { 3107 /* No valid flowsets */ 3108 return BCM_E_NOT_FOUND; 3109 } 3110 3111 /* Get and return the status */ 3112 SR_FLOW_TX_LOCK(unit, fidx); 3113 if (SR_FLOW_MGMT_DEVINFO(unit)->get_tx_flow_status) { 3114 rv = SR_FLOW_MGMT_DEVINFO(unit)->get_tx_flow_status(unit, fidx, status); 3115 if (BCM_FAILURE(rv)) { 3116 SR_FLOW_TX_UNLOCK(unit, fidx); 3117 return rv; 3118 } 3119 } else { 3120 SR_FLOW_TX_UNLOCK(unit, fidx); 3121 return BCM_E_UNAVAIL; 3122 } 3123 SR_FLOW_TX_UNLOCK(unit, fidx); 3124 return BCM_E_NONE; 3125 } 3126 3127 /* 3128 * Function: 3129 * bcmi_esw_tsn_sr_rx_flow_status_get 3130 * Purpose: 3131 * Get status for the specified flow 3132 * Parameters: 3133 * unit - (IN) unit number 3134 * flow_id - (IN) flow ID 3135 * status - (OUT) flow status 3136 * Returns: 3137 * BCM_E_XXX 3138 * Notes: 3139 * If it's called with a TX flow, BCM_E_BADID is returned 3140 */ 3141 STATIC int 3142 bcmi_esw_tsn_sr_rx_flow_status_get( 3143 int unit, 3144 bcm_tsn_sr_flow_t flow_id, 3145 bcm_tsn_sr_rx_flow_status_t *status) 3146 { 3147 bcmi_esw_tsn_bk_info_t *tsn_bk; 3148 tsn_sr_flows_bookkeeping_t *bkinfo; 3149 int fidx; 3150 int dir; 3151 int rv; 3152 int i; 3153 3154 /* parameter check */ 3155 if (status == NULL) { 3156 return BCM_E_PARAM; 3157 } 3158 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 3159 bkinfo = &tsn_bk->sr_flows; 3160 dir = SR_FLOW_ID_TO_DIR(flow_id); 3161 fidx = SR_FLOW_ID_TO_IDX(flow_id); 3162 if (dir != SR_FLOW_DIR_RX) { 3163 return BCM_E_BADID; 3164 } 3165 if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) { 3166 return BCM_E_PARAM; 3167 } 3168 3169 /* Validate if it's from a flowset */ 3170 for (i = fidx; i >= 0; i--) { 3171 if (bkinfo->flowsets[dir][i].num_flows != 0) { 3172 if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) { 3173 break; 3174 } else { 3175 return BCM_E_NOT_FOUND; 3176 } 3177 } 3178 } 3179 if (i == -1) { 3180 /* No valid flowsets */ 3181 return BCM_E_NOT_FOUND; 3182 } 3183 3184 /* Get and return the status */ 3185 SR_FLOW_RX_LOCK(unit, fidx); 3186 if (SR_FLOW_MGMT_DEVINFO(unit)->get_rx_flow_status) { 3187 rv = SR_FLOW_MGMT_DEVINFO(unit)->get_rx_flow_status(unit, fidx, status); 3188 if (BCM_FAILURE(rv)) { 3189 SR_FLOW_RX_UNLOCK(unit, fidx); 3190 return rv; 3191 } 3192 } else { 3193 SR_FLOW_RX_UNLOCK(unit, fidx); 3194 return BCM_E_UNAVAIL; 3195 } 3196 SR_FLOW_RX_UNLOCK(unit, fidx); 3197 return BCM_E_NONE; 3198 } 3199 3200 /* 3201 * Function: 3202 * bcmi_esw_tsn_sr_rx_flow_reset 3203 * Purpose: 3204 * Reset SR RX flow status 3205 * Parameters: 3206 * unit - (IN) unit number 3207 * flags - (IN) flags to select items to reset 3208 * flow_id - (IN) flow ID 3209 * Returns: 3210 * BCM_E_XXX 3211 * Notes: 3212 * If it's called with a TX flow, BCM_E_BADID is returned 3213 */ 3214 STATIC int 3215 bcmi_esw_tsn_sr_rx_flow_reset(int unit, uint32 flags, bcm_tsn_sr_flow_t flow_id) 3216 { 3217 bcmi_esw_tsn_bk_info_t *tsn_bk; 3218 tsn_sr_flows_bookkeeping_t *bkinfo; 3219 int fidx; 3220 int dir; 3221 uint32 reset_mode; 3222 int rv; 3223 int i; 3224 3225 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 3226 if (flags & ~BCM_TSN_SR_RX_FLOW_RESET_ALL) { 3227 return BCM_E_PARAM; 3228 } 3229 bkinfo = &tsn_bk->sr_flows; 3230 dir = SR_FLOW_ID_TO_DIR(flow_id); 3231 fidx = SR_FLOW_ID_TO_IDX(flow_id); 3232 if (dir != SR_FLOW_DIR_RX) { 3233 return BCM_E_BADID; 3234 } 3235 if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) { 3236 return BCM_E_PARAM; 3237 } 3238 3239 /* Validate if it's from a flowset */ 3240 for (i = fidx; i >= 0; i--) { 3241 if (bkinfo->flowsets[dir][i].num_flows != 0) { 3242 if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) { 3243 break; 3244 } else { 3245 return BCM_E_NOT_FOUND; 3246 } 3247 } 3248 } 3249 if (i == -1) { 3250 /* No valid flowsets */ 3251 return BCM_E_NOT_FOUND; 3252 } 3253 3254 /* Call platform specific routine to do reset */ 3255 if (!SR_FLOW_MGMT_DEVINFO(unit)->reset_rx_flow || 3256 !SR_FLOW_MGMT_DEVINFO(unit)->seqnum_hist_reset) { 3257 return BCM_E_UNAVAIL; 3258 } 3259 SR_FLOW_RX_LOCK(unit, fidx); 3260 /* Seqnum history window reset requires special handling */ 3261 if (flags & BCM_TSN_SR_RX_FLOW_RESET_SEQNUM_WIN_HISTORY) { 3262 /* Get reset mode first */ 3263 rv = bcm_esw_tsn_control_get( 3264 unit, bcmTsnControlSrSeqNumWindowResetMode, &reset_mode); 3265 if (BCM_FAILURE(rv)) { 3266 SR_FLOW_RX_UNLOCK(unit, fidx); 3267 return rv; 3268 } 3269 /* Reset seqnum window using platform specific routine */ 3270 rv = SR_FLOW_MGMT_DEVINFO(unit)->seqnum_hist_reset( 3271 unit, fidx, 3272 bkinfo->flows_rx[fidx].config.seqnum_history_win_size, 3273 bkinfo->flows_rx[fidx].sn_slice, reset_mode); 3274 if (BCM_FAILURE(rv)) { 3275 SR_FLOW_RX_UNLOCK(unit, fidx); 3276 return rv; 3277 } 3278 } 3279 /* For other flags, call another plafform specific routine */ 3280 if (flags & (~BCM_TSN_SR_RX_FLOW_RESET_SEQNUM_WIN_HISTORY)) { 3281 rv = SR_FLOW_MGMT_DEVINFO(unit)->reset_rx_flow(unit, fidx, flags); 3282 if (BCM_FAILURE(rv)) { 3283 SR_FLOW_RX_UNLOCK(unit, fidx); 3284 return rv; 3285 } 3286 } 3287 SR_FLOW_RX_UNLOCK(unit, fidx); 3288 return BCM_E_NONE; 3289 } 3290 3291 /* 3292 * Function: 3293 * bcmi_esw_tsn_sr_rx_flow_seqnum_history_get 3294 * Purpose: 3295 * Get the sequence number history bits (one bit for one sequence number) 3296 * in the RX flow. 3297 * Parameters: 3298 * unit - (IN) unit number 3299 * flow_id - (IN) flow ID 3300 * offset - (IN) Offset (in bits) in the seqnum history window 3301 * max_size - (IN) Size (in bits) of the buffer 3302 * history - (OUT) Bit buffer to read 3303 * actual - (OUT) Actual size (in bits) read to the buffer 3304 * Returns: 3305 * BCM_E_XXX 3306 * Notes: 3307 * If it's called with a TX flow, BCM_E_BADID is returned 3308 */ 3309 STATIC int 3310 bcmi_esw_tsn_sr_rx_flow_seqnum_history_get( 3311 int unit, 3312 bcm_tsn_sr_flow_t flow_id, 3313 int offset, 3314 int max_size, 3315 uint8 *history, 3316 int *actual) 3317 { 3318 bcmi_esw_tsn_bk_info_t *tsn_bk; 3319 tsn_sr_flows_bookkeeping_t *bkinfo; 3320 int fidx; 3321 int dir; 3322 int winsize; 3323 int rv; 3324 int i; 3325 3326 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 3327 if (history == NULL || actual == NULL || offset < 0 || max_size <= 0) { 3328 return BCM_E_PARAM; 3329 } 3330 bkinfo = &tsn_bk->sr_flows; 3331 dir = SR_FLOW_ID_TO_DIR(flow_id); 3332 fidx = SR_FLOW_ID_TO_IDX(flow_id); 3333 if (dir != SR_FLOW_DIR_RX) { 3334 return BCM_E_BADID; 3335 } 3336 if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) { 3337 return BCM_E_PARAM; 3338 } 3339 3340 /* Validate if it's from a flowset */ 3341 for (i = fidx; i >= 0; i--) { 3342 if (bkinfo->flowsets[dir][i].num_flows != 0) { 3343 if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) { 3344 break; 3345 } else { 3346 return BCM_E_NOT_FOUND; 3347 } 3348 } 3349 } 3350 if (i == -1) { 3351 /* No valid flowsets */ 3352 return BCM_E_NOT_FOUND; 3353 } 3354 3355 /* Call platform specific routine to do it */ 3356 if (!SR_FLOW_MGMT_DEVINFO(unit)->seqnum_hist_read) { 3357 return BCM_E_UNAVAIL; 3358 } 3359 SR_FLOW_RX_LOCK(unit, fidx); 3360 /* Do advanced parameter check */ 3361 winsize = bkinfo->flows_rx[fidx].config.seqnum_history_win_size; 3362 if (offset >= winsize) { 3363 SR_FLOW_RX_UNLOCK(unit, fidx); 3364 return BCM_E_PARAM; 3365 } 3366 max_size = (max_size > (winsize - offset) ? (winsize - offset) : max_size); 3367 /* Call platform specific routine for seqnum operation */ 3368 rv = SR_FLOW_MGMT_DEVINFO(unit)->seqnum_hist_read( 3369 unit, fidx, 3370 bkinfo->flows_rx[fidx].config.seqnum_history_win_size, 3371 bkinfo->flows_rx[fidx].sn_slice, 3372 offset, max_size, history, actual); 3373 SR_FLOW_RX_UNLOCK(unit, fidx); 3374 return rv; 3375 3376 } 3377 3378 /* 3379 * Function: 3380 * bcmi_esw_tsn_sr_rx_flow_seqnum_history_set 3381 * Purpose: 3382 * Set the sequence number history bits (one bit for one sequence number) 3383 * in the RX flow. 3384 * Parameters: 3385 * unit - (IN) unit number 3386 * flow_id - (IN) flow ID 3387 * offset - (IN) Offset (in bits) in the seqnum history window 3388 * size - (IN) Size (in bits) to write 3389 * history - (IN) Bit buffer to write 3390 * Returns: 3391 * BCM_E_XXX 3392 * Notes: 3393 * If it's called with a TX flow, BCM_E_BADID is returned 3394 */ 3395 STATIC int 3396 bcmi_esw_tsn_sr_rx_flow_seqnum_history_set( 3397 int unit, 3398 bcm_tsn_sr_flow_t flow_id, 3399 int offset, 3400 int size, 3401 uint8 *history) 3402 { 3403 bcmi_esw_tsn_bk_info_t *tsn_bk; 3404 tsn_sr_flows_bookkeeping_t *bkinfo; 3405 int fidx; 3406 int dir; 3407 int winsize; 3408 int rv; 3409 int i; 3410 3411 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 3412 if (history == NULL || offset < 0 || size <= 0) { 3413 return BCM_E_PARAM; 3414 } 3415 bkinfo = &tsn_bk->sr_flows; 3416 dir = SR_FLOW_ID_TO_DIR(flow_id); 3417 fidx = SR_FLOW_ID_TO_IDX(flow_id); 3418 if (dir != SR_FLOW_DIR_RX) { 3419 return BCM_E_BADID; 3420 } 3421 if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) { 3422 return BCM_E_PARAM; 3423 } 3424 3425 /* Validate if it's from a flowset */ 3426 for (i = fidx; i >= 0; i--) { 3427 if (bkinfo->flowsets[dir][i].num_flows != 0) { 3428 if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) { 3429 break; 3430 } else { 3431 return BCM_E_NOT_FOUND; 3432 } 3433 } 3434 } 3435 if (i == -1) { 3436 /* No valid flowsets */ 3437 return BCM_E_NOT_FOUND; 3438 } 3439 3440 /* Call platform specific routine to do it */ 3441 if (!SR_FLOW_MGMT_DEVINFO(unit)->seqnum_hist_write) { 3442 return BCM_E_UNAVAIL; 3443 } 3444 3445 SR_FLOW_RX_LOCK(unit, fidx); 3446 /* Do advanced parameter check */ 3447 winsize = bkinfo->flows_rx[fidx].config.seqnum_history_win_size; 3448 if (offset >= winsize || size > winsize) { 3449 SR_FLOW_RX_UNLOCK(unit, fidx); 3450 return BCM_E_PARAM; 3451 } 3452 /* Call platform specific routine for seqnum operation */ 3453 rv = SR_FLOW_MGMT_DEVINFO(unit)->seqnum_hist_write( 3454 unit, fidx, winsize, bkinfo->flows_rx[fidx].sn_slice, 3455 offset, size, history); 3456 SR_FLOW_RX_UNLOCK(unit, fidx); 3457 return rv; 3458 } 3459 3460 /* 3461 * Function: 3462 * bcmi_esw_tsn_sr_hw_flow_id_get 3463 * Purpose: 3464 * Convert software SR flow ID to hardware SR flow ID 3465 * Parameters: 3466 * unit - (IN) unit number 3467 * flow_id - (IN) SW flow ID 3468 * hw_id - (OUT) HW flow ID 3469 * Returns: 3470 * BCM_E_XXX 3471 * Notes: 3472 */ 3473 int 3474 bcmi_esw_tsn_sr_hw_flow_id_get( 3475 int unit, 3476 bcm_tsn_sr_flow_t flow_id, 3477 uint32 *hw_id) 3478 { 3479 bcmi_esw_tsn_bk_info_t *tsn_bk; 3480 tsn_sr_flows_bookkeeping_t *bkinfo; 3481 int fidx; 3482 int dir; 3483 3484 /* parameter check */ 3485 if (!soc_feature(unit, soc_feature_tsn_sr)) { 3486 return BCM_E_UNAVAIL; 3487 } 3488 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 3489 if (hw_id == NULL) { 3490 return BCM_E_PARAM; 3491 } 3492 bkinfo = &tsn_bk->sr_flows; 3493 dir = SR_FLOW_ID_TO_DIR(flow_id); 3494 fidx = SR_FLOW_ID_TO_IDX(flow_id); 3495 if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) { 3496 return BCM_E_PARAM; 3497 } 3498 3499 /* Call platform specific routine to convert */ 3500 if (!SR_FLOW_MGMT_DEVINFO(unit)->get_hw_flow_id) { 3501 return BCM_E_UNAVAIL; 3502 } 3503 return SR_FLOW_MGMT_DEVINFO(unit)->get_hw_flow_id( 3504 unit, (dir == SR_FLOW_DIR_TX), fidx, hw_id); 3505 } 3506 3507 /* 3508 * Function: 3509 * bcmi_esw_tsn_sr_sw_flow_id_get 3510 * Purpose: 3511 * Convert hardware SR flow ID to software SR flow ID 3512 * Parameters: 3513 * unit - (IN) unit number 3514 * hw_id - (IN) HW flow ID 3515 * flow_id - (OUT) SW flow ID 3516 * Returns: 3517 * BCM_E_XXX 3518 * Notes: 3519 */ 3520 int 3521 bcmi_esw_tsn_sr_sw_flow_id_get( 3522 int unit, 3523 uint32 hw_id, 3524 bcm_tsn_sr_flow_t *flow_id) 3525 { 3526 bcmi_esw_tsn_bk_info_t *tsn_bk; 3527 tsn_sr_flows_bookkeeping_t *bkinfo; 3528 const bcmi_esw_tsn_dev_info_t *dev_info; 3529 int is_tx; 3530 int dir; 3531 int fidx; 3532 3533 /* parameter check */ 3534 if (!soc_feature(unit, soc_feature_tsn_sr)) { 3535 return BCM_E_UNAVAIL; 3536 } 3537 3538 if (flow_id == NULL) { 3539 return BCM_E_PARAM; 3540 } 3541 3542 if (tsn_bk_info[unit] == NULL) { 3543 /* Using device specific info that need no bk_info */ 3544 BCM_IF_ERROR_RETURN(bcmi_esw_tsn_noninit_dev_info_get(unit, &dev_info)); 3545 if (!dev_info->sr_flows_info->get_sw_flow_idx) { 3546 return BCM_E_UNAVAIL; 3547 } 3548 BCM_IF_ERROR_RETURN( 3549 dev_info->sr_flows_info->get_sw_flow_idx(unit, hw_id, 3550 &is_tx, &fidx)); 3551 dir = is_tx ? SR_FLOW_DIR_TX : SR_FLOW_DIR_RX; 3552 *flow_id = SR_FLOW_ID_FROM_IDX(dir, fidx); 3553 return BCM_E_NONE; 3554 } 3555 3556 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 3557 bkinfo = &tsn_bk->sr_flows; 3558 3559 /* Call platform specific routine to convert */ 3560 if (!SR_FLOW_MGMT_DEVINFO(unit)->get_sw_flow_idx) { 3561 return BCM_E_UNAVAIL; 3562 } 3563 BCM_IF_ERROR_RETURN( 3564 SR_FLOW_MGMT_DEVINFO(unit)->get_sw_flow_idx( 3565 unit, hw_id, &is_tx, &fidx)); 3566 dir = is_tx ? SR_FLOW_DIR_TX : SR_FLOW_DIR_RX; 3567 3568 /* Validate converted index */ 3569 if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) { 3570 return BCM_E_PARAM; 3571 } 3572 3573 /* Done */ 3574 *flow_id = SR_FLOW_ID_FROM_IDX(dir, fidx); 3575 return BCM_E_NONE; 3576 } 3577 3578 /* 3579 * Function: 3580 * bcmi_esw_tsn_sr_flowset_identify 3581 * Purpose: 3582 * SR flow to flowset converstion (identify the flowset based on a flow) 3583 * Parameters: 3584 * unit - (IN) unit number 3585 * flow_id - (IN) flow ID 3586 * flowset - (OUT) flowset ID 3587 * Returns: 3588 * BCM_E_XXX 3589 * Notes: 3590 */ 3591 int 3592 bcmi_esw_tsn_sr_flowset_identify( 3593 int unit, 3594 bcm_tsn_sr_flow_t flow_id, 3595 bcm_tsn_sr_flowset_t *flowset) 3596 { 3597 bcmi_esw_tsn_bk_info_t *tsn_bk; 3598 tsn_sr_flows_bookkeeping_t *bkinfo; 3599 int fidx; 3600 int dir; 3601 int i; 3602 3603 /* parameter check */ 3604 if (!soc_feature(unit, soc_feature_tsn_sr)) { 3605 return BCM_E_UNAVAIL; 3606 } 3607 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 3608 if (flowset == NULL) { 3609 return BCM_E_PARAM; 3610 } 3611 bkinfo = &tsn_bk->sr_flows; 3612 dir = SR_FLOW_ID_TO_DIR(flow_id); 3613 fidx = SR_FLOW_ID_TO_IDX(flow_id); 3614 if (fidx < 0 || fidx >= bkinfo->max_flows[dir]) { 3615 return BCM_E_PARAM; 3616 } 3617 3618 /* Find the flowset */ 3619 for (i = fidx; i >= 0; i--) { 3620 if (bkinfo->flowsets[dir][i].num_flows != 0) { 3621 if (bkinfo->flowsets[dir][i].num_flows > (fidx - i)) { 3622 /* Convert to user flowset ID */ 3623 *flowset = SR_FLOWSET_ID_FROM_IDX(dir, i); 3624 return BCM_E_NONE; 3625 } else { 3626 /* The flow is not within this flowset */ 3627 return BCM_E_NOT_FOUND; 3628 } 3629 } 3630 } 3631 3632 /* No flowset found with index less than the flow */ 3633 return BCM_E_NOT_FOUND; 3634 } 3635 3636 #ifdef BCM_WARM_BOOT_SUPPORT 3637 /* SR flow: allocate specified flow idx(s) for warmboot restore */ 3638 STATIC int 3639 bcmi_esw_tsn_sr_flow_idx_restore( 3640 int unit, 3641 int dir, 3642 int index, 3643 int count, 3644 tsn_sr_flowidx_entry_t **entry) 3645 { 3646 bcmi_esw_tsn_bk_info_t *tsn_bk; 3647 tsn_sr_flows_bookkeeping_t *bkinfo; 3648 tsn_sr_flowidx_entry_t *fid, *prev, *bprev, *begin; 3649 3650 /* parameter check */ 3651 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 3652 if (dir < 0 || dir >= SR_FLOW_DIR_COUNT || count <= 0 || entry == NULL) { 3653 return BCM_E_PARAM; 3654 } 3655 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 3656 bkinfo = &tsn_bk->sr_flows; 3657 3658 /* Protect access to the flow indexes */ 3659 SR_FLOW_MGMT_LOCK(unit); 3660 3661 /* Traverse the list and search for the specified items */ 3662 begin = NULL; 3663 prev = bprev = NULL; 3664 for (fid = bkinfo->flowids_avail[dir]; fid != NULL; fid = fid->next) { 3665 if (fid->flow_idx == index) { 3666 if (begin == NULL) { 3667 /* Found the head */ 3668 begin = fid; 3669 bprev = prev; 3670 } 3671 3672 /* Check if we have got all the items */ 3673 count--; 3674 if (count == 0) { 3675 /* Done. Removing the chain from the list */ 3676 if (NULL == bprev) { 3677 /* The chain was the head */ 3678 bkinfo->flowids_avail[dir] = fid->next; 3679 } else { 3680 /* Connect previous one to the next of the chain */ 3681 bprev->next = fid->next; 3682 } 3683 3684 /* Terminate this chain and return */ 3685 fid->next = NULL; 3686 *entry = begin; 3687 SR_FLOW_MGMT_UNLOCK(unit); 3688 return BCM_E_NONE; 3689 } 3690 index++; 3691 } else if (fid->flow_idx > index) { 3692 /* Not found in this sorted list */ 3693 break; 3694 } 3695 3696 /* record the previous one */ 3697 prev = fid; 3698 } 3699 3700 /* Cannot find the specified item or enough continuous entries */ 3701 SR_FLOW_MGMT_UNLOCK(unit); 3702 return BCM_E_INTERNAL; 3703 } 3704 3705 /* SR flow management - warmboot scache size allocation */ 3706 STATIC int 3707 bcmi_esw_tsn_sr_flow_mgmt_wb_alloc(int unit) 3708 { 3709 bcmi_esw_tsn_bk_info_t *tsn_bk; 3710 tsn_sr_flows_bookkeeping_t *bkinfo; 3711 soc_scache_handle_t scache_handle; 3712 uint8 *scache_ptr = NULL; 3713 int stable_size = 0; 3714 int alloc_size; 3715 int rv; 3716 3717 /* parameter check */ 3718 if (!soc_feature(unit, soc_feature_tsn_sr)) { 3719 return BCM_E_UNAVAIL; 3720 } 3721 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 3722 bkinfo = &tsn_bk->sr_flows; 3723 3724 /* Requires extended scache support level-2 warmboot */ 3725 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 3726 if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 3727 return BCM_E_NONE; 3728 } 3729 3730 /* Calculate allocate size */ 3731 alloc_size = 0; 3732 alloc_size += sizeof(uint16); /* Number of actual RX flows */ 3733 alloc_size += sizeof(uint16); /* Number of actual TX flows */ 3734 alloc_size += /* RX flows */ 3735 sizeof(tsn_sr_rx_flowset_wb_t) * bkinfo->max_flows[SR_FLOW_DIR_RX]; 3736 alloc_size += /* TX flows */ 3737 sizeof(tsn_sr_tx_flowset_wb_t) * bkinfo->max_flows[SR_FLOW_DIR_TX]; 3738 3739 /* Allocate scache for warmboot */ 3740 SOC_SCACHE_HANDLE_SET(scache_handle, unit, 3741 BCM_MODULE_TSN, BCM_TSN_WB_SCACHE_PART_SR_FLOWS); 3742 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size, 3743 &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL); 3744 if (rv == BCM_E_NOT_FOUND) { 3745 /* Proceed with level 1 warmboot */ 3746 rv = BCM_E_NONE; 3747 } 3748 3749 return rv; 3750 } 3751 3752 /* SR flow management - sync information to scache */ 3753 STATIC int 3754 bcmi_esw_tsn_sr_flow_mgmt_sync(int unit) 3755 { 3756 bcmi_esw_tsn_bk_info_t *tsn_bk; 3757 tsn_sr_flows_bookkeeping_t *bkinfo; 3758 soc_scache_handle_t scache_handle; 3759 uint8 *scache_ptr = NULL, *scache; 3760 tsn_sr_rx_flowset_wb_t rxflow; 3761 tsn_sr_tx_flowset_wb_t txflow; 3762 int stable_size = 0; 3763 tsn_sr_flowset_t *fset; 3764 uint16 flows; 3765 int rv; 3766 int i; 3767 3768 /* parameter check */ 3769 if (!soc_feature(unit, soc_feature_tsn_sr)) { 3770 return BCM_E_UNAVAIL; 3771 } 3772 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 3773 bkinfo = &tsn_bk->sr_flows; 3774 3775 /* Requires extended scache support level-2 warmboot */ 3776 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 3777 if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 3778 return BCM_E_NONE; 3779 } 3780 SOC_SCACHE_HANDLE_SET(scache_handle, unit, 3781 BCM_MODULE_TSN, BCM_TSN_WB_SCACHE_PART_SR_FLOWS); 3782 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 3783 &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL); 3784 if (rv == BCM_E_NOT_FOUND) { 3785 return BCM_E_NONE; 3786 } 3787 BCM_IF_ERROR_RETURN(rv); 3788 assert(scache_ptr != NULL); 3789 3790 /* Avoid flowsets to be created/destroyed at the same time */ 3791 SR_FLOW_MGMT_LOCK(unit); 3792 3793 /* Loop through RX flowsets and save to scache */ 3794 flows = 0; 3795 scache = scache_ptr + sizeof(uint16) * 2; 3796 for (i = 0; i < bkinfo->max_flows[SR_FLOW_DIR_RX]; i++) { 3797 fset = &bkinfo->flowsets[SR_FLOW_DIR_RX][i]; 3798 SR_FLOWSET_LOCK(fset); 3799 if (fset->num_flows != 0) { 3800 rxflow.flow_idx = i; 3801 rxflow.map_id = fset->map_id; 3802 sal_memcpy(&rxflow.config, &fset->config.rx, sizeof(rxflow.config)); 3803 flows++; 3804 sal_memcpy(scache, &rxflow, sizeof(rxflow)); 3805 scache += sizeof(rxflow); 3806 } 3807 SR_FLOWSET_UNLOCK(fset); 3808 } 3809 sal_memcpy(scache_ptr, &flows, sizeof(uint16)); /* Actual RX flowsets */ 3810 3811 /* And TX flowsets */ 3812 flows = 0; 3813 for (i = 0; i < bkinfo->max_flows[SR_FLOW_DIR_TX]; i++) { 3814 fset = &bkinfo->flowsets[SR_FLOW_DIR_TX][i]; 3815 SR_FLOWSET_LOCK(fset); 3816 if (fset->num_flows != 0) { 3817 txflow.flow_idx = i; 3818 txflow.map_id = fset->map_id; 3819 sal_memcpy(&txflow.config, &fset->config.tx, sizeof(txflow.config)); 3820 flows++; 3821 sal_memcpy(scache, &txflow, sizeof(txflow)); 3822 scache += sizeof(txflow); 3823 } 3824 SR_FLOWSET_UNLOCK(fset); 3825 } 3826 sal_memcpy(scache_ptr + sizeof(uint16), &flows, sizeof(uint16)); 3827 3828 /* Done */ 3829 SR_FLOW_MGMT_UNLOCK(unit); 3830 return BCM_E_NONE; 3831 } 3832 3833 /* SR flow management - reload flow management information from scache */ 3834 STATIC int 3835 bcmi_esw_tsn_sr_flow_mgmt_reload(int unit) 3836 { 3837 bcmi_esw_tsn_bk_info_t *tsn_bk; 3838 tsn_sr_flows_bookkeeping_t *bkinfo; 3839 soc_scache_handle_t scache_handle; 3840 uint8 *scache_ptr = NULL; 3841 tsn_sr_rx_flowset_wb_t rxflow; 3842 tsn_sr_tx_flowset_wb_t txflow; 3843 int stable_size = 0; 3844 tsn_sr_flowset_t *fset; 3845 tsn_sr_flowidx_entry_t *flow_ide; 3846 bcm_tsn_pri_map_config_t pmcfg; 3847 uint16 rxflows, txflows, i; 3848 int num_flows; 3849 int rv; 3850 int j, idx; 3851 3852 /* parameter check */ 3853 if (!soc_feature(unit, soc_feature_tsn_sr)) { 3854 return BCM_E_UNAVAIL; 3855 } 3856 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 3857 bkinfo = &tsn_bk->sr_flows; 3858 if (!SR_FLOW_MGMT_DEVINFO(unit)->read_rx_flow || 3859 !SR_FLOW_MGMT_DEVINFO(unit)->read_tx_flow) { 3860 return BCM_E_UNAVAIL; 3861 } 3862 3863 /* Requires extended scache support level-2 warmboot */ 3864 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 3865 if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 3866 return BCM_E_NONE; 3867 } 3868 SOC_SCACHE_HANDLE_SET(scache_handle, unit, 3869 BCM_MODULE_TSN, BCM_TSN_WB_SCACHE_PART_SR_FLOWS); 3870 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 3871 &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL); 3872 if (rv == BCM_E_NOT_FOUND) { 3873 return BCM_E_NONE; 3874 } 3875 BCM_IF_ERROR_RETURN(rv); 3876 assert(scache_ptr != NULL); 3877 3878 /* Avoid flowsets to be created/destroyed at the same time */ 3879 SR_FLOW_MGMT_LOCK(unit); 3880 3881 /* Get number of saved RX/TX flowsets */ 3882 sal_memcpy(&rxflows, scache_ptr, sizeof(uint16)); 3883 scache_ptr += sizeof(uint16); 3884 sal_memcpy(&txflows, scache_ptr, sizeof(uint16)); 3885 scache_ptr += sizeof(uint16); 3886 3887 /* Restore RX flowsets */ 3888 for (i = 0; i < rxflows; i++) { 3889 /* Read from scache */ 3890 sal_memcpy(&rxflow, scache_ptr, sizeof(rxflow)); 3891 scache_ptr += sizeof(rxflow); 3892 3893 /* Validate flow index */ 3894 if (rxflow.flow_idx < 0 || 3895 rxflow.flow_idx >= bkinfo->max_flows[SR_FLOW_DIR_RX]) { 3896 SR_FLOW_MGMT_UNLOCK(unit); 3897 return BCM_E_INTERNAL; 3898 } 3899 3900 /* Validate priority map and get number of flows inside this flowset */ 3901 num_flows = 1; 3902 if (rxflow.map_id != BCM_TSN_PRI_MAP_INVALID) { 3903 /* call API to get priority map configuration */ 3904 rv = bcm_esw_tsn_pri_map_get(unit, rxflow.map_id, &pmcfg); 3905 if (BCM_FAILURE(rv) || pmcfg.map_type != bcmTsnPriMapTypeSrFlow) { 3906 SR_FLOW_MGMT_UNLOCK(unit); 3907 return BCM_E_INTERNAL; 3908 } 3909 /* Number of flows is max flow offset + 1 */ 3910 for (j = 0; j < pmcfg.num_map_entries; j++) { 3911 if ((pmcfg.map_entries[j].flags & 3912 BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET) && 3913 (pmcfg.map_entries[j].flow_offset > num_flows - 1)) { 3914 num_flows = pmcfg.map_entries[j].flow_offset + 1; 3915 } 3916 } 3917 } 3918 3919 /* Restore flow index entries */ 3920 rv = bcmi_esw_tsn_sr_flow_idx_restore( 3921 unit, SR_FLOW_DIR_RX, rxflow.flow_idx, num_flows, &flow_ide); 3922 if (BCM_FAILURE(rv)) { 3923 SR_FLOW_MGMT_UNLOCK(unit); 3924 return BCM_E_INTERNAL; 3925 } 3926 3927 /* Confirmed that this flowset can be restored */ 3928 fset = &bkinfo->flowsets[SR_FLOW_DIR_RX][rxflow.flow_idx]; 3929 SR_FLOWSET_LOCK(fset); 3930 3931 /* Restore the flowset */ 3932 fset->flow_ide = flow_ide; 3933 fset->map_id = rxflow.map_id; 3934 fset->num_flows = num_flows; 3935 fset->ref_count = 0; 3936 sal_memcpy(&fset->config.rx, &rxflow.config, sizeof(rxflow.config)); 3937 3938 /* Restore the individual flows */ 3939 for (j = 0; j < num_flows; j++) { 3940 idx = rxflow.flow_idx + j; 3941 SR_FLOW_RX_LOCK(unit, idx); 3942 rv = SR_FLOW_MGMT_DEVINFO(unit)->read_rx_flow( 3943 unit, idx, &bkinfo->flows_rx[idx]); 3944 if (BCM_FAILURE(rv)) { 3945 SR_FLOW_RX_UNLOCK(unit, idx); 3946 SR_FLOWSET_UNLOCK(fset); 3947 SR_FLOW_MGMT_UNLOCK(unit); 3948 return rv; 3949 } 3950 SR_FLOW_RX_UNLOCK(unit, idx); 3951 } 3952 3953 /* Done restoring this flowset */ 3954 SR_FLOWSET_UNLOCK(fset); 3955 } 3956 3957 /* Restore TX flowsets */ 3958 for (i = 0; i < txflows; i++) { 3959 /* Read from scache */ 3960 sal_memcpy(&txflow, scache_ptr, sizeof(txflow)); 3961 scache_ptr += sizeof(txflow); 3962 3963 /* Validate flow index */ 3964 if (txflow.flow_idx < 0 || 3965 txflow.flow_idx >= bkinfo->max_flows[SR_FLOW_DIR_TX]) { 3966 SR_FLOW_MGMT_UNLOCK(unit); 3967 return BCM_E_INTERNAL; 3968 } 3969 3970 /* Validate priority map and get number of flows inside this flowset */ 3971 num_flows = 1; 3972 if (txflow.map_id != BCM_TSN_PRI_MAP_INVALID) { 3973 /* call API to get priority map configuration */ 3974 rv = bcm_esw_tsn_pri_map_get(unit, txflow.map_id, &pmcfg); 3975 if (BCM_FAILURE(rv) || pmcfg.map_type != bcmTsnPriMapTypeSrFlow) { 3976 SR_FLOW_MGMT_UNLOCK(unit); 3977 return BCM_E_INTERNAL; 3978 } 3979 /* Number of flows is max flow offset + 1 */ 3980 for (j = 0; j < pmcfg.num_map_entries; j++) { 3981 if ((pmcfg.map_entries[j].flags & 3982 BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET) && 3983 (pmcfg.map_entries[j].flow_offset > num_flows - 1)) { 3984 num_flows = pmcfg.map_entries[j].flow_offset + 1; 3985 } 3986 } 3987 } 3988 3989 /* Restore flow index entries */ 3990 rv = bcmi_esw_tsn_sr_flow_idx_restore( 3991 unit, SR_FLOW_DIR_TX, txflow.flow_idx, num_flows, &flow_ide); 3992 if (BCM_FAILURE(rv)) { 3993 SR_FLOW_MGMT_UNLOCK(unit); 3994 return BCM_E_INTERNAL; 3995 } 3996 3997 /* Confirmed that this flowset can be restored */ 3998 fset = &bkinfo->flowsets[SR_FLOW_DIR_TX][txflow.flow_idx]; 3999 SR_FLOWSET_LOCK(fset); 4000 4001 /* Restore the flowset */ 4002 fset->flow_ide = flow_ide; 4003 fset->map_id = txflow.map_id; 4004 fset->num_flows = num_flows; 4005 fset->ref_count = 0; 4006 sal_memcpy(&fset->config.tx, &txflow.config, sizeof(txflow.config)); 4007 4008 /* Restore the individual flows */ 4009 for (j = 0; j < num_flows; j++) { 4010 idx = txflow.flow_idx + j; 4011 SR_FLOW_TX_LOCK(unit, idx); 4012 rv = SR_FLOW_MGMT_DEVINFO(unit)->read_tx_flow( 4013 unit, idx, &bkinfo->flows_tx[idx]); 4014 if (BCM_FAILURE(rv)) { 4015 SR_FLOW_TX_UNLOCK(unit, idx); 4016 SR_FLOWSET_UNLOCK(fset); 4017 SR_FLOW_MGMT_UNLOCK(unit); 4018 return rv; 4019 } 4020 SR_FLOW_TX_UNLOCK(unit, idx); 4021 } 4022 4023 /* Done restoring this flowset */ 4024 SR_FLOWSET_UNLOCK(fset); 4025 } 4026 4027 /* Done */ 4028 SR_FLOW_MGMT_UNLOCK(unit); 4029 return BCM_E_NONE; 4030 } 4031 #endif /* BCM_WARM_BOOT_SUPPORT */ 4032 4033 /* SR flow management de-initialization */ 4034 STATIC int 4035 bcmi_esw_tsn_sr_flow_mgmt_detach(int unit) 4036 { 4037 tsn_sr_flows_bookkeeping_t *bkinfo; 4038 int dir, i; 4039 4040 /* parameter check */ 4041 if (!SOC_UNIT_VALID(unit)) { 4042 return BCM_E_UNIT; 4043 } 4044 4045 /* check if it's already cleared */ 4046 bkinfo = &tsn_bk_info[unit]->sr_flows; 4047 if (NULL == bkinfo) { 4048 return BCM_E_NONE; 4049 } 4050 4051 /* de-allocate flow index pool */ 4052 if (NULL != bkinfo->flowids_allocated) { 4053 sal_free(bkinfo->flowids_allocated); 4054 bkinfo->flowids_allocated = NULL; 4055 } 4056 4057 /* de-allocate flow instances */ 4058 if (NULL != bkinfo->flows_rx) { 4059 sal_free(bkinfo->flows_rx); 4060 bkinfo->flows_rx = NULL; 4061 } 4062 if (NULL != bkinfo->flows_tx) { 4063 sal_free(bkinfo->flows_tx); 4064 bkinfo->flows_tx = NULL; 4065 } 4066 4067 /* de-allocate flow mutexes */ 4068 if (NULL != bkinfo->flows_rx_mutex) { 4069 for (i = 0; i < bkinfo->max_flows[SR_FLOW_DIR_RX]; i++) { 4070 if (bkinfo->flows_rx_mutex[i] != NULL) { 4071 sal_mutex_destroy(bkinfo->flows_rx_mutex[i]); 4072 bkinfo->flows_rx_mutex[i] = NULL; 4073 } 4074 } 4075 sal_free(bkinfo->flows_rx_mutex); 4076 bkinfo->flows_rx_mutex = NULL; 4077 } 4078 if (NULL != bkinfo->flows_tx_mutex) { 4079 for (i = 0; i < bkinfo->max_flows[SR_FLOW_DIR_TX]; i++) { 4080 if (bkinfo->flows_tx_mutex[i] != NULL) { 4081 sal_mutex_destroy(bkinfo->flows_tx_mutex[i]); 4082 bkinfo->flows_tx_mutex[i] = NULL; 4083 } 4084 } 4085 sal_free(bkinfo->flows_tx_mutex); 4086 bkinfo->flows_tx_mutex = NULL; 4087 } 4088 4089 /* De-allocate per direction */ 4090 for (dir = SR_FLOW_DIR_RX; dir < SR_FLOW_DIR_COUNT; dir++) { 4091 4092 /* clear flow index linked list */ 4093 bkinfo->flowids_avail[dir] = NULL; 4094 4095 /* de-allocate flowset instances */ 4096 if (NULL != bkinfo->flowsets[dir]) { 4097 for (i = 0; i < bkinfo->max_flows[dir]; i++) { 4098 if (NULL != bkinfo->flowsets[dir][i].mutex) { 4099 sal_mutex_destroy(bkinfo->flowsets[dir][i].mutex); 4100 bkinfo->flowsets[dir][i].mutex = NULL; 4101 } 4102 } 4103 sal_free(bkinfo->flowsets[dir]); 4104 bkinfo->flowsets[dir] = NULL; 4105 } 4106 } 4107 4108 /* destroy the flow management mutex */ 4109 if (NULL != bkinfo->fmgmt_mutex) { 4110 sal_mutex_destroy(bkinfo->fmgmt_mutex); 4111 bkinfo->fmgmt_mutex = NULL; 4112 } 4113 4114 return BCM_E_NONE; 4115 } 4116 4117 /* SR flow management initialization */ 4118 STATIC int 4119 bcmi_esw_tsn_sr_flow_mgmt_init(int unit) 4120 { 4121 tsn_sr_flows_bookkeeping_t *bkinfo; 4122 tsn_sr_flowidx_entry_t *fid; 4123 int rxflows, txflows; 4124 int rv; 4125 int d, i; 4126 4127 /* parameter check */ 4128 if (!SOC_UNIT_VALID(unit)) { 4129 return BCM_E_UNIT; 4130 } 4131 4132 /* Retrieve number of TX/RX flows */ 4133 bkinfo = &tsn_bk_info[unit]->sr_flows; 4134 if (SR_FLOW_MGMT_DEVINFO(unit) == NULL || 4135 SR_FLOW_MGMT_DEVINFO(unit)->get_num_flows == NULL) { 4136 return BCM_E_UNAVAIL; 4137 } 4138 rv = SR_FLOW_MGMT_DEVINFO(unit)->get_num_flows(unit, &rxflows, &txflows); 4139 if (BCM_FAILURE(rv)) { 4140 return rv; 4141 } 4142 if (rxflows < 0) { 4143 rxflows = 0; /* Reserve negative value for future extension */ 4144 } 4145 if (txflows < 0) { 4146 txflows = 0; /* Reserve negative value for future extension */ 4147 } 4148 if (rxflows + txflows == 0) { 4149 /* No supported flows */ 4150 return BCM_E_UNAVAIL; 4151 } 4152 bkinfo->max_flows[SR_FLOW_DIR_RX] = rxflows; 4153 bkinfo->max_flows[SR_FLOW_DIR_TX] = txflows; 4154 4155 /* 4156 * We need to minimize the time taken for picking a free flow index. 4157 * To achieve this, we use linked list with pre-allocated entries so that 4158 * we can do it in O(1). 4159 */ 4160 4161 /* Allocate flow index entry pool (one pool for TX and RX) */ 4162 bkinfo->flowids_allocated = (tsn_sr_flowidx_entry_t *)sal_alloc( 4163 sizeof(tsn_sr_flowidx_entry_t) * (rxflows + txflows), 4164 "tsn sr flow ids"); 4165 if (NULL == bkinfo->flowids_allocated) { 4166 LOG_ERROR(BSL_LS_BCM_TSN, 4167 (BSL_META("TSN SR: failed to allocate flow IDs\n"))); 4168 (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit); 4169 return BCM_E_MEMORY; 4170 } 4171 4172 /* For RX and TX directions */ 4173 fid = bkinfo->flowids_allocated; 4174 for (d = SR_FLOW_DIR_RX; d < SR_FLOW_DIR_COUNT; d++) { 4175 4176 /* Prepare flow index entry linked list for quick ID allocation */ 4177 for (i = 0; i < bkinfo->max_flows[d]; i++, fid++) { 4178 /* 4179 * Add an entry to the head of the linked list. 4180 * The flow index is going backward so the final list can be in 4181 * increasing order (some allocation requires continuous flows). 4182 */ 4183 fid->flow_idx = bkinfo->max_flows[d] - i - 1; 4184 fid->next = bkinfo->flowids_avail[d]; 4185 bkinfo->flowids_avail[d] = fid; 4186 } 4187 4188 /* Allocate array of RX/TX flowset instances */ 4189 if (bkinfo->max_flows[d] > 0) { 4190 /* The max number of flowsets should be the same as flows */ 4191 bkinfo->flowsets[d] = (tsn_sr_flowset_t *)sal_alloc( 4192 sizeof(tsn_sr_flowset_t) * bkinfo->max_flows[d], 4193 "tsn sr rx flows"); 4194 if (NULL == bkinfo->flowsets[d]) { 4195 LOG_ERROR(BSL_LS_BCM_TSN, 4196 (BSL_META("TSN SR: failed to allocate flowsets\n"))); 4197 (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit); 4198 return BCM_E_MEMORY; 4199 } 4200 sal_memset(bkinfo->flowsets[d], 0, 4201 sizeof(tsn_sr_flowset_t) * bkinfo->max_flows[d]); 4202 /* Pre-create mutexes of all flowsets for performance */ 4203 for (i = 0; i < bkinfo->max_flows[d]; i++) { 4204 bkinfo->flowsets[d][i].mutex = 4205 sal_mutex_create("tsn sr flowset"); 4206 if (NULL == bkinfo->flowsets[d][i].mutex) { 4207 LOG_ERROR(BSL_LS_BCM_TSN, 4208 (BSL_META( 4209 "TSN SR: failed to create flowset mutex\n"))); 4210 (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit); 4211 return BCM_E_MEMORY; 4212 } 4213 } 4214 } 4215 } 4216 4217 /* Allocate array of RX/TX flow instances and mutexes */ 4218 if (rxflows > 0) { 4219 bkinfo->flows_rx = (bcmi_tsn_sr_rx_flow_t *)sal_alloc( 4220 sizeof(bcmi_tsn_sr_rx_flow_t) * rxflows, "tsn sr rx flows"); 4221 if (NULL == bkinfo->flows_rx) { 4222 LOG_ERROR(BSL_LS_BCM_TSN, 4223 (BSL_META("TSN SR: failed to allocate RX flows\n"))); 4224 (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit); 4225 return BCM_E_MEMORY; 4226 } 4227 sal_memset(bkinfo->flows_rx, 0, 4228 sizeof(bcmi_tsn_sr_rx_flow_t) * rxflows); 4229 bkinfo->flows_rx_mutex = (sal_mutex_t *)sal_alloc( 4230 sizeof(sal_mutex_t) * rxflows, "tsn sr rx flows mutex"); 4231 if (NULL == bkinfo->flows_rx_mutex) { 4232 LOG_ERROR(BSL_LS_BCM_TSN, 4233 (BSL_META( 4234 "TSN SR: failed to allocate RX flow mutexes\n"))); 4235 (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit); 4236 return BCM_E_MEMORY; 4237 } 4238 for (i = 0; i < rxflows; i++) { 4239 bkinfo->flows_rx_mutex[i] = sal_mutex_create("tsn sr flow mutex"); 4240 if (NULL == bkinfo->flows_rx_mutex[i]) { 4241 LOG_ERROR(BSL_LS_BCM_TSN, 4242 (BSL_META( 4243 "TSN SR: failed to create flow mutex\n"))); 4244 (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit); 4245 return BCM_E_MEMORY; 4246 } 4247 } 4248 } 4249 if (txflows > 0) { 4250 bkinfo->flows_tx = (bcmi_tsn_sr_tx_flow_t *)sal_alloc( 4251 sizeof(bcmi_tsn_sr_tx_flow_t) * txflows, "tsn sr tx flows"); 4252 if (NULL == bkinfo->flows_tx) { 4253 LOG_ERROR(BSL_LS_BCM_TSN, 4254 (BSL_META("TSN SR: failed to allocate TX flows\n"))); 4255 (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit); 4256 return BCM_E_MEMORY; 4257 } 4258 sal_memset(bkinfo->flows_tx, 0, 4259 sizeof(bcmi_tsn_sr_tx_flow_t) * txflows); 4260 bkinfo->flows_tx_mutex = (sal_mutex_t *)sal_alloc( 4261 sizeof(sal_mutex_t) * txflows, "tsn sr tx flows mutex"); 4262 if (NULL == bkinfo->flows_tx_mutex) { 4263 LOG_ERROR(BSL_LS_BCM_TSN, 4264 (BSL_META( 4265 "TSN SR: failed to allocate TX flow mutexes\n"))); 4266 (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit); 4267 return BCM_E_MEMORY; 4268 } 4269 for (i = 0; i < txflows; i++) { 4270 bkinfo->flows_tx_mutex[i] = sal_mutex_create("tsn sr flow mutex"); 4271 if (NULL == bkinfo->flows_tx_mutex[i]) { 4272 LOG_ERROR(BSL_LS_BCM_TSN, 4273 (BSL_META("TSN SR: failed to create flow mutex\n"))); 4274 (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit); 4275 return BCM_E_MEMORY; 4276 } 4277 } 4278 } 4279 4280 /* Create mutex for protecting flow management (allocate/free) */ 4281 bkinfo->fmgmt_mutex = sal_mutex_create("tsn sr flow mgmt"); 4282 if (NULL == bkinfo->fmgmt_mutex) { 4283 LOG_ERROR(BSL_LS_BCM_TSN, 4284 (BSL_META("TSN SR: failed to create flow mgmt mutex\n"))); 4285 (void)bcmi_esw_tsn_sr_flow_mgmt_detach(unit); 4286 return BCM_E_MEMORY; 4287 } 4288 4289 return BCM_E_NONE; 4290 } 4291 4292 /* 4293 * Function: 4294 * bcmi_esw_tsn_sr_auto_learn_config_dump 4295 * Purpose: 4296 * dump content of bcm_tsn_sr_auto_learn_config_t 4297 * Parameters: 4298 * unit - (IN) Unit number 4299 * prefix - (IN) Character string to prefix output lines 4300 * config - (IN) Auto Learn configuration 4301 * Returns: 4302 * none 4303 */ 4304 STATIC void 4305 bcmi_esw_tsn_sr_auto_learn_config_dump( 4306 int unit, 4307 char *prefix, 4308 bcm_tsn_sr_auto_learn_config_t *config) 4309 { 4310 TSN_FUNCTION_TRACE(unit, "IN"); 4311 4312 /* Parameter NULL error handling */ 4313 if ((NULL == prefix) || (NULL == config)) { 4314 return; 4315 } 4316 4317 if (bsl_check(bslLayerBcm, bslSourceTsn, bslSeverityDebug, unit)) { 4318 LOG_DEBUG(BSL_LS_BCM_TSN, 4319 (BSL_META_U(unit, 4320 "bcm_tsn_sr_auto_learn_config_t:\n"))); 4321 /* num_tx_flows & num_rx_flows */ 4322 LOG_DEBUG(BSL_LS_BCM_TSN, 4323 (BSL_META_U(unit, 4324 "%s num_tx_flows %d num_rx_flows %d.\n"), 4325 prefix, 4326 config->num_tx_flows, 4327 config->num_rx_flows)); 4328 4329 /* tx_flow_config */ 4330 LOG_DEBUG(BSL_LS_BCM_TSN, 4331 (BSL_META_U(unit, 4332 "%s tx_flow_config:" 4333 "flags 0x%x, seq_num %d, " 4334 "ingress_mtu_profile %d.\n"), 4335 prefix, 4336 config->tx_flow_config.flags, 4337 config->tx_flow_config.seq_num, 4338 config->tx_flow_config.ingress_mtu_profile)); 4339 /* rx_flow_config */ 4340 LOG_DEBUG(BSL_LS_BCM_TSN, 4341 (BSL_META_U(unit, 4342 "%s rx_flow_config:" 4343 "flags 0x%x, seqnum_accept_win_size %d, " 4344 "seqnum_history_win_size %d, age_timeout %d, " 4345 "ingress_mtu_profile %d\n"), 4346 prefix, 4347 config->rx_flow_config.flags, 4348 config->rx_flow_config.seqnum_accept_win_size, 4349 config->rx_flow_config.seqnum_history_win_size, 4350 config->rx_flow_config.age_timeout, 4351 config->rx_flow_config.ingress_mtu_profile)); 4352 } 4353 4354 TSN_FUNCTION_TRACE(unit, "OUT"); 4355 } 4356 4357 /* 4358 * Function: 4359 * bcmi_esw_tsn_sr_auto_learn_group_config_dump 4360 * Purpose: 4361 * dump content of bcm_tsn_sr_auto_learn_group_config_t 4362 * Parameters: 4363 * unit - (IN) Unit number 4364 * prefix - (IN) Character string to prefix output lines 4365 * config - (IN) Auto Learn Group configuration 4366 * Returns: 4367 * none 4368 */ 4369 STATIC void 4370 bcmi_esw_tsn_sr_auto_learn_group_config_dump( 4371 int unit, 4372 char *prefix, 4373 bcm_tsn_sr_auto_learn_group_config_t *config) 4374 { 4375 bcm_port_t port; 4376 4377 TSN_FUNCTION_TRACE(unit, "IN"); 4378 4379 /* Parameter NULL error handling */ 4380 if ((NULL == prefix) || (NULL == config)) { 4381 assert((prefix) && (config)); 4382 return; 4383 } 4384 4385 if (bsl_check(bslLayerBcm, bslSourceTsn, bslSeverityDebug, unit)) { 4386 LOG_DEBUG(BSL_LS_BCM_TSN, 4387 (BSL_META_U(unit, 4388 "bcm_tsn_sr_auto_learn_group_config_t:\n"))); 4389 4390 /* flags */ 4391 LOG_DEBUG(BSL_LS_BCM_TSN, 4392 (BSL_META_U(unit, 4393 "%s flags 0x%x\n"), 4394 prefix, 4395 config->flags)); 4396 4397 /* interlink_ports */ 4398 LOG_DEBUG(BSL_LS_BCM_TSN, 4399 (BSL_META_U(unit, 4400 "%s interlink_ports:"), 4401 prefix)); 4402 4403 PBMP_ITER(config->interlink_ports, port) { 4404 LOG_DEBUG(BSL_LS_BCM_TSN, 4405 (BSL_META_U(unit, 4406 "%2d "), port)); 4407 } 4408 4409 LOG_DEBUG(BSL_LS_BCM_TSN, 4410 (BSL_META_U(unit, "\n"))); 4411 4412 /* redundant_ports */ 4413 LOG_DEBUG(BSL_LS_BCM_TSN, 4414 (BSL_META_U(unit, 4415 "%s redundant_ports:"), 4416 prefix)); 4417 4418 PBMP_ITER(config->redundant_ports, port) { 4419 LOG_DEBUG(BSL_LS_BCM_TSN, 4420 (BSL_META_U(unit, 4421 "%2d "), port)); 4422 4423 } 4424 4425 LOG_DEBUG(BSL_LS_BCM_TSN, 4426 (BSL_META_U(unit, "\n"))); 4427 } 4428 TSN_FUNCTION_TRACE(unit, "OUT"); 4429 } 4430 4431 /* 4432 * Function: 4433 * bcmi_esw_tsn_sr_auto_learn_group_config_cmp 4434 * Purpose: 4435 * Check the Auto Learn entry is the same or not. 4436 * Parameters: 4437 * unit - (IN) Unit number 4438 * config1 - (IN) Auto Learn Group config 4439 * config2 - (IN) Auto Learn Group config 4440 * Returns: 4441 * BCM_E_NONE - not the same and no overlapped ports found 4442 * BCM_E_PARAM - NULL parameter 4443 * BCM_E_EXISTS - both config are the same 4444 * BCM_E_BUSY - not the same but overlapped ports found 4445 */ 4446 STATIC int 4447 bcmi_esw_tsn_sr_auto_learn_group_config_cmp( 4448 int unit, 4449 bcm_tsn_sr_auto_learn_group_config_t *config1, 4450 bcm_tsn_sr_auto_learn_group_config_t *config2) 4451 { 4452 int is_the_same = TRUE; 4453 bcm_pbmp_t tmp_pbmp; 4454 4455 TSN_FUNCTION_TRACE(unit, "IN"); 4456 4457 /* Parameter NULL error handling */ 4458 if ((NULL == config1) || (NULL == config2)) { 4459 assert((config1) && ( config2)); 4460 return BCM_E_PARAM; 4461 } 4462 4463 /* Check if flags are different */ 4464 if (config1->flags != config2->flags) { 4465 is_the_same = FALSE; 4466 } 4467 4468 /* Check if any different found */ 4469 if (BCM_PBMP_NEQ(config1->redundant_ports, 4470 config2->redundant_ports)) { 4471 is_the_same = FALSE; 4472 } 4473 4474 /* Check if any different found */ 4475 if (BCM_PBMP_NEQ(config1->interlink_ports, 4476 config2->interlink_ports)) { 4477 is_the_same = FALSE; 4478 } 4479 4480 if (FALSE == is_the_same) { 4481 BCM_PBMP_ASSIGN(tmp_pbmp, config1->interlink_ports); 4482 BCM_PBMP_AND(tmp_pbmp, config2->interlink_ports); 4483 /* Check for overlapped ports found, return BCM_E_BUSY */ 4484 if (BCM_PBMP_NOT_NULL(tmp_pbmp)) { 4485 return BCM_E_BUSY; 4486 } 4487 4488 BCM_PBMP_ASSIGN(tmp_pbmp, config1->redundant_ports); 4489 BCM_PBMP_AND(tmp_pbmp, config2->redundant_ports); 4490 /* Check for overlapped ports found, return BCM_E_BUSY */ 4491 if (BCM_PBMP_NOT_NULL(tmp_pbmp)) { 4492 return BCM_E_BUSY; 4493 } 4494 4495 /* Not the same and no overlapped */ 4496 return BCM_E_NONE; 4497 } 4498 4499 TSN_FUNCTION_TRACE(unit, "OUT"); 4500 /* Both config are the same, return BCM_E_EXISTS */ 4501 return BCM_E_EXISTS; 4502 } 4503 4504 /* 4505 * Function: 4506 * bcmi_esw_tsn_sr_auto_learn_group_id_existed_check 4507 * Purpose: 4508 * Check the Auto Learn Group ID exited or not. 4509 * Parameters: 4510 * unit - (IN) Unit number 4511 * group_id - (IN) Group ID 4512 * Returns: 4513 * BCM_E_NONE - Success. 4514 */ 4515 STATIC int 4516 bcmi_esw_tsn_sr_auto_learn_group_id_existed_check( 4517 int unit, 4518 int group_id) 4519 { 4520 bcm_error_t rv = BCM_E_UNAVAIL; 4521 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 4522 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 4523 const tsn_sr_auto_learn_info_t *al_dev_info = NULL; 4524 uint32 sw_idx = GROUP_ID_TO_SW_IDX(group_id); 4525 uint32 table_size; 4526 4527 TSN_FUNCTION_TRACE(unit, "IN"); 4528 4529 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 4530 4531 /* Initialization check */ 4532 AUTO_LEARN_INIT(unit); 4533 4534 /* auto learn device info */ 4535 dev_info = bk_info->tsn_dev_info; 4536 al_dev_info = dev_info->tsn_sr_auto_learn_info; 4537 4538 rv = al_dev_info->table_size_get(unit, &table_size); 4539 BCM_IF_ERROR_RETURN(rv); 4540 assert(table_size > 0); 4541 4542 /* Check if the map_id and sw_idx is in the reasonable range */ 4543 if (sw_idx >= table_size) { 4544 return BCM_E_PARAM; 4545 } 4546 4547 if (AUTO_LEARN_INTF_USED_GET(unit, sw_idx)) { 4548 return BCM_E_NONE; 4549 } 4550 TSN_FUNCTION_TRACE(unit, "OUT"); 4551 return BCM_E_NOT_FOUND; 4552 } 4553 4554 /* 4555 * Function: 4556 * bcmi_esw_tsn_sr_auto_learn_group_existed_check 4557 * Purpose: 4558 * Check the Auto Learn Group configuration exited or not. 4559 * Parameters: 4560 * unit - (IN) Unit number 4561 * config - (IN) Current Group ID 4562 * config - (IN) Auto Learn Group configuration 4563 * group_id - (OUT) Group ID 4564 * Returns: 4565 * BCM_E_NONE - Success. Not the same and no overlapped ports found 4566 * BCM_E_PARAM - Fail. NULL parameter 4567 * BCM_E_EXISTS - Fail. Both configures are the same 4568 * BCM_E_BUSY - Fail. Not the same but overlapped ports found 4569 */ 4570 STATIC int 4571 bcmi_esw_tsn_sr_auto_learn_group_existed_check( 4572 int unit, 4573 bcm_tsn_sr_auto_learn_group_config_t *config, 4574 int current_group_id, 4575 int *group_id) 4576 { 4577 bcm_error_t rv = BCM_E_UNAVAIL; 4578 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 4579 bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL; 4580 bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *bk_group_data; 4581 bcm_tsn_sr_auto_learn_group_config_t *bk_config; 4582 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 4583 const tsn_sr_auto_learn_info_t *al_dev_info = NULL; 4584 uint32 sw_idx; 4585 uint32 table_size; 4586 4587 TSN_FUNCTION_TRACE(unit, "IN"); 4588 4589 /* Parameter NULL error handling */ 4590 if ((NULL == config) || (NULL == group_id)) { 4591 return BCM_E_PARAM; 4592 } 4593 4594 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 4595 4596 /* Initialization check */ 4597 AUTO_LEARN_INIT(unit); 4598 4599 /* auto learn bk info */ 4600 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 4601 4602 /* auto learn device info */ 4603 dev_info = bk_info->tsn_dev_info; 4604 al_dev_info = dev_info->tsn_sr_auto_learn_info; 4605 4606 rv = al_dev_info->table_size_get(unit, &table_size); 4607 BCM_IF_ERROR_RETURN(rv); 4608 assert(table_size > 0); 4609 assert(table_size > al_bk_info->valid_sw_idx_end); 4610 4611 AUTO_LEARN_BK_LOCK(unit); 4612 4613 /* Check if there is any the same configure in bk */ 4614 for (sw_idx = (al_bk_info->valid_sw_idx_start); 4615 sw_idx <= (al_bk_info->valid_sw_idx_end); 4616 sw_idx++) { 4617 4618 /* Not used, continue to check next one */ 4619 if (AUTO_LEARN_INTF_USED_GET(unit, sw_idx) == 0) { 4620 continue; 4621 } 4622 4623 bk_group_data = &(al_bk_info->group_data[sw_idx]); 4624 bk_config = &(bk_group_data->config); 4625 4626 /* Compare if two configures are the same */ 4627 rv = bcmi_esw_tsn_sr_auto_learn_group_config_cmp( 4628 unit, bk_config, config); 4629 if (BCM_SUCCESS(rv)) { 4630 /* Not the same and no overlapped port found */ 4631 continue; 4632 } else if (BCM_E_EXISTS == rv) { 4633 /* The same configure found */ 4634 *group_id = bk_group_data->group_id; 4635 AUTO_LEARN_BK_UNLOCK(unit); 4636 return rv; 4637 } else if (BCM_FAILURE(rv)) { 4638 /* Overlapped ports found and Error handle for other */ 4639 4640 /* Change the config via set function, skip check itself */ 4641 if (current_group_id == bk_group_data->group_id) { 4642 continue; 4643 } 4644 AUTO_LEARN_BK_UNLOCK(unit); 4645 return rv; 4646 } 4647 } 4648 AUTO_LEARN_BK_UNLOCK(unit); 4649 4650 TSN_FUNCTION_TRACE(unit, "OUT"); 4651 return BCM_E_NONE; 4652 } 4653 4654 4655 /* 4656 * Function: 4657 * bcmi_esw_tsn_sr_auto_learn_get_empty_group_id 4658 * Purpose: 4659 * Get a empty group_id 4660 * Parameters: 4661 * unit - (IN) Unit number 4662 * group_id - (OUT) Group ID 4663 * Returns: 4664 * BCM_E_NONE - Success. Find a empty groud_id successfully 4665 */ 4666 STATIC int 4667 bcmi_esw_tsn_sr_auto_learn_get_empty_group_id( 4668 int unit, 4669 int *group_id) 4670 { 4671 bcm_error_t rv = BCM_E_UNAVAIL; 4672 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 4673 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 4674 const tsn_sr_auto_learn_info_t *al_dev_info = NULL; 4675 bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL; 4676 uint32 empty_sw_idx; 4677 uint32 table_size; 4678 4679 TSN_FUNCTION_TRACE(unit, "IN"); 4680 4681 /* Parameter NULL error handling */ 4682 if (NULL == group_id) { 4683 return BCM_E_PARAM; 4684 } 4685 4686 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 4687 4688 /* Initialization check */ 4689 AUTO_LEARN_INIT(unit); 4690 4691 /* auto learn bk info */ 4692 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 4693 4694 /* auto learn device info */ 4695 dev_info = bk_info->tsn_dev_info; 4696 al_dev_info = dev_info->tsn_sr_auto_learn_info; 4697 4698 rv = al_dev_info->table_size_get(unit, &table_size); 4699 BCM_IF_ERROR_RETURN(rv); 4700 assert(table_size > 0); 4701 4702 /* Full check */ 4703 if (al_bk_info->valid_count == table_size) { 4704 return BCM_E_NOT_FOUND; 4705 } 4706 4707 /* Check if it's in the reasonable range */ 4708 if (al_bk_info->empty_sw_idx_end >= table_size) { 4709 return BCM_E_INTERNAL; 4710 } 4711 4712 AUTO_LEARN_BK_LOCK(unit); 4713 4714 /* Find an empty id */ 4715 for (empty_sw_idx = al_bk_info->empty_sw_idx_start; 4716 empty_sw_idx <= al_bk_info->empty_sw_idx_end; 4717 empty_sw_idx++) { 4718 4719 if (AUTO_LEARN_INTF_USED_GET(unit, empty_sw_idx) == 0) { 4720 /* Set bit map as used */ 4721 AUTO_LEARN_INTF_USED_SET(unit, empty_sw_idx); 4722 4723 /* Update valid start and end */ 4724 if (al_bk_info->valid_count == 0) { 4725 al_bk_info->valid_sw_idx_start = empty_sw_idx; 4726 al_bk_info->valid_sw_idx_end = empty_sw_idx; 4727 } else if (empty_sw_idx < al_bk_info->valid_sw_idx_start) { 4728 al_bk_info->valid_sw_idx_start = empty_sw_idx; 4729 } else if (empty_sw_idx > al_bk_info->valid_sw_idx_end) { 4730 al_bk_info->valid_sw_idx_end = empty_sw_idx; 4731 } 4732 4733 al_bk_info->valid_count++; 4734 *group_id = SW_IDX_TO_GROUP_ID(empty_sw_idx); 4735 4736 /* Update the empty start, assume next one is real empty */ 4737 al_bk_info->empty_sw_idx_start = empty_sw_idx + 1; 4738 AUTO_LEARN_BK_UNLOCK(unit); 4739 return BCM_E_NONE; 4740 } 4741 else { 4742 4743 /* Update the empty start, assume next one is real empty */ 4744 al_bk_info->empty_sw_idx_start = empty_sw_idx + 1; 4745 } 4746 } 4747 AUTO_LEARN_BK_UNLOCK(unit); 4748 TSN_FUNCTION_TRACE(unit, "OUT"); 4749 return BCM_E_NOT_FOUND; 4750 } 4751 4752 /* 4753 * Function: 4754 * bcmi_esw_tsn_sr_auto_learn_destroy_group_id 4755 * Purpose: 4756 * Free the resource of group_id 4757 * Parameters: 4758 * unit - (IN) Unit number 4759 * group_id - (IN) Group ID 4760 * Returns: 4761 * BCM_E_NONE - Success. delete groud_id successfully 4762 */ 4763 STATIC int 4764 bcmi_esw_tsn_sr_auto_learn_destroy_group_id( 4765 int unit, 4766 int group_id) 4767 { 4768 bcm_error_t rv = BCM_E_UNAVAIL; 4769 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 4770 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 4771 const tsn_sr_auto_learn_info_t *al_dev_info = NULL; 4772 bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL; 4773 uint32 destroy_sw_idx = GROUP_ID_TO_SW_IDX(group_id); 4774 uint32 next_valid_sw_idx; 4775 uint32 table_size; 4776 4777 TSN_FUNCTION_TRACE(unit, "IN"); 4778 4779 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 4780 4781 /* Initialization check */ 4782 AUTO_LEARN_INIT(unit); 4783 4784 /* auto learn bk info */ 4785 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 4786 4787 /* auto learn device info */ 4788 dev_info = bk_info->tsn_dev_info; 4789 al_dev_info = dev_info->tsn_sr_auto_learn_info; 4790 4791 rv = al_dev_info->table_size_get(unit, &table_size); 4792 BCM_IF_ERROR_RETURN(rv); 4793 assert(table_size > 0); 4794 4795 /* Check if it's in the reasonable range */ 4796 if (destroy_sw_idx >= table_size) { 4797 return BCM_E_INTERNAL; 4798 } 4799 AUTO_LEARN_BK_LOCK(unit); 4800 4801 /* Destroy bitmap */ 4802 AUTO_LEARN_INTF_USED_CLR(unit, destroy_sw_idx); 4803 4804 /* Update empty start and end */ 4805 if (destroy_sw_idx < (al_bk_info->empty_sw_idx_start)) { 4806 al_bk_info->empty_sw_idx_start = destroy_sw_idx; 4807 } else if (destroy_sw_idx > (al_bk_info->empty_sw_idx_end)) { 4808 al_bk_info->empty_sw_idx_end = destroy_sw_idx; 4809 } 4810 4811 /* Update valid, find a next valid start or next valid end */ 4812 next_valid_sw_idx = destroy_sw_idx; 4813 if ((al_bk_info->valid_count) > 1) { 4814 if (next_valid_sw_idx == (al_bk_info->valid_sw_idx_start)) { 4815 do { 4816 next_valid_sw_idx++; 4817 if (next_valid_sw_idx == table_size - 1) { 4818 /* table_size -1 is the last one */ 4819 break; 4820 } 4821 } while (AUTO_LEARN_INTF_USED_GET(unit, next_valid_sw_idx) == 0); 4822 al_bk_info->valid_sw_idx_start = next_valid_sw_idx; 4823 } else if (next_valid_sw_idx == (al_bk_info->valid_sw_idx_end)) { 4824 do { 4825 next_valid_sw_idx--; 4826 if (next_valid_sw_idx == 0) { 4827 /* 0 is the first one */ 4828 break; 4829 } 4830 } while (AUTO_LEARN_INTF_USED_GET(unit, next_valid_sw_idx) == 0); 4831 al_bk_info->valid_sw_idx_end = next_valid_sw_idx; 4832 } 4833 } 4834 4835 if (0 < al_bk_info->valid_count) { 4836 al_bk_info->valid_count--; 4837 } 4838 4839 if (0 == al_bk_info->valid_count) { 4840 al_bk_info->valid_sw_idx_start = 0; 4841 al_bk_info->valid_sw_idx_end = 0; 4842 al_bk_info->empty_sw_idx_start = 0; 4843 al_bk_info->empty_sw_idx_end = table_size - 1; 4844 } 4845 AUTO_LEARN_BK_UNLOCK(unit); 4846 4847 TSN_FUNCTION_TRACE(unit, "OUT"); 4848 return BCM_E_NONE; 4849 } 4850 4851 /* 4852 * Function: 4853 * bcmi_esw_tsn_sr_auto_learn_create_sr_multicast 4854 * Purpose: 4855 * Create Multicast group for SR ports 4856 * Parameters: 4857 * unit - (IN) Unit 4858 * port_pbmp - (IN) port bitmap 4859 * mcg_idx - (OUT) multicast group index 4860 * Returns: 4861 * BCM_E_NONE - Success. 4862 */ 4863 STATIC int 4864 bcmi_esw_tsn_sr_auto_learn_create_sr_multicast( 4865 int unit, 4866 bcm_pbmp_t port_pbmp, 4867 int *mcg_idx) 4868 { 4869 bcm_error_t rv = BCM_E_UNAVAIL; 4870 bcm_if_t encap_id; 4871 bcm_port_t port; 4872 bcm_gport_t gport; 4873 bcm_vlan_t vid = BCM_VLAN_INVALID; 4874 bcm_multicast_t mc_group; 4875 4876 TSN_FUNCTION_TRACE(unit, "IN"); 4877 4878 /* Parameter NULL error handling */ 4879 if (NULL == mcg_idx) { 4880 return BCM_E_PARAM; 4881 } 4882 4883 /* Initialization check */ 4884 AUTO_LEARN_INIT(unit); 4885 4886 rv = bcm_esw_multicast_create(unit, BCM_MULTICAST_TYPE_L2, &mc_group); 4887 if (BCM_FAILURE(rv)) { 4888 LOG_ERROR(BSL_LS_BCM_TSN, 4889 (BSL_META_U(unit, 4890 "bcm_multicast_create failed(rv = %d)\n"), 4891 rv)); 4892 return rv; 4893 } 4894 4895 PBMP_ITER(port_pbmp, port) { 4896 LOG_DEBUG(BSL_LS_BCM_TSN, 4897 (BSL_META_U(unit, 4898 "port: %d, "), port)); 4899 /* convert port to gport */ 4900 BCM_IF_ERROR_RETURN( 4901 bcm_esw_port_gport_get(unit, port, &gport)); 4902 4903 /* Add HSR ports into the multicast group */ 4904 rv = bcm_esw_multicast_l2_encap_get(unit, 4905 mc_group, 4906 gport, 4907 vid, 4908 &encap_id); 4909 if (BCM_FAILURE(rv)) { 4910 LOG_ERROR(BSL_LS_BCM_TSN, 4911 (BSL_META_U(unit, 4912 "bcm_esw_multicast_l2_encap_get" 4913 " failed(rv = %d)\n"), 4914 rv)); 4915 return rv; 4916 } 4917 4918 rv = bcm_esw_multicast_egress_add(unit, 4919 mc_group, 4920 gport, 4921 encap_id); 4922 if (BCM_FAILURE(rv)) { 4923 LOG_ERROR(BSL_LS_BCM_TSN, 4924 (BSL_META_U(unit, 4925 "bcm_esw_multicast_egress_add" 4926 " failed(rv = %d)\n"), 4927 rv)); 4928 return rv; 4929 } 4930 4931 LOG_DEBUG(BSL_LS_BCM_TSN, 4932 (BSL_META_U(unit, 4933 "mc_group(%d), port(%2d), " 4934 "vlan(%d), encap_id(%d)\n"), 4935 mc_group, 4936 port, 4937 vid, 4938 encap_id)); 4939 } 4940 *mcg_idx = _BCM_MULTICAST_ID_GET(mc_group); 4941 4942 TSN_FUNCTION_TRACE(unit, "OUT"); 4943 return BCM_E_NONE; 4944 } 4945 4946 /* 4947 * Function: 4948 * bcmi_esw_tsn_sr_auto_learn_delete_sr_multicast 4949 * Purpose: 4950 * Delete Multicast group for SR ports 4951 * Parameters: 4952 * unit - (IN) Unit being delete. 4953 * port_pbmp - (IN) port bitmap being delete. 4954 * mcg_idx - (IN) multicast group index 4955 * Returns: 4956 * BCM_E_NONE - Success. 4957 */ 4958 STATIC int 4959 bcmi_esw_tsn_sr_auto_learn_delete_sr_multicast( 4960 int unit, 4961 bcm_pbmp_t port_pbmp, 4962 int mcg_idx) 4963 { 4964 bcm_error_t rv = BCM_E_UNAVAIL; 4965 bcm_if_t encap_id; 4966 bcm_port_t port; 4967 bcm_gport_t gport; 4968 bcm_vlan_t vid = BCM_VLAN_INVALID; 4969 bcm_multicast_t mc_group; 4970 4971 TSN_FUNCTION_TRACE(unit, "IN"); 4972 4973 _BCM_MULTICAST_GROUP_SET(mc_group, _BCM_MULTICAST_TYPE_L2, mcg_idx); 4974 4975 /* Initialization check */ 4976 AUTO_LEARN_INIT(unit); 4977 4978 PBMP_ITER(port_pbmp, port) { 4979 /* convert port to gport */ 4980 BCM_IF_ERROR_RETURN( 4981 bcm_esw_port_gport_get(unit, port, &gport)); 4982 4983 /* Add HSR ports into the multicast group */ 4984 rv = bcm_esw_multicast_l2_encap_get(unit, 4985 mc_group, 4986 gport, 4987 vid, 4988 &encap_id); 4989 if (BCM_FAILURE(rv)) { 4990 LOG_ERROR(BSL_LS_BCM_TSN, 4991 (BSL_META_U(unit, 4992 "bcm_multicast_l2_encap_get" 4993 " failed(rv = %d)\n"), 4994 rv)); 4995 return rv; 4996 } 4997 4998 rv = bcm_esw_multicast_egress_delete(unit, 4999 mc_group, 5000 gport, 5001 encap_id); 5002 if (BCM_FAILURE(rv)) { 5003 LOG_ERROR(BSL_LS_BCM_TSN, 5004 (BSL_META_U(unit, 5005 "bcm_esw_multicast_egress_delete" 5006 " failed(rv = %d)\n"), 5007 rv)); 5008 return rv; 5009 } 5010 5011 LOG_DEBUG(BSL_LS_BCM_TSN, 5012 (BSL_META_U(unit, 5013 "mc_group(%d), port(%2d), " 5014 "vlan(%d), encap_id(%d)"), 5015 mc_group, 5016 port, 5017 vid, 5018 encap_id)); 5019 } 5020 5021 rv = bcm_esw_multicast_destroy(unit, mc_group); 5022 if (BCM_FAILURE(rv)) { 5023 LOG_ERROR(BSL_LS_BCM_TSN, 5024 (BSL_META_U(unit, 5025 "bcm_esw_multicast_destroy" 5026 " mc_group(%d), failed(rv = %d)\n"), 5027 mc_group, 5028 rv)); 5029 return rv; 5030 } 5031 TSN_FUNCTION_TRACE(unit, "OUT"); 5032 return BCM_E_NONE; 5033 } 5034 5035 /* 5036 * Function: 5037 * bcmi_esw_tsn_sr_auto_learn_hw_delete_all 5038 * Purpose: 5039 * Delete all HW resource. Back to default status. 5040 * Parameters: 5041 * unit - (IN) Unit being delete. 5042 * Returns: 5043 * BCM_E_NONE - Success. 5044 */ 5045 STATIC int 5046 bcmi_esw_tsn_sr_auto_learn_hw_delete_all(int unit) 5047 { 5048 bcm_error_t rv = BCM_E_UNAVAIL; 5049 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 5050 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 5051 const tsn_sr_auto_learn_info_t *al_dev_info = NULL; 5052 5053 TSN_FUNCTION_TRACE(unit, "IN"); 5054 5055 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 5056 5057 /* Initialization check */ 5058 AUTO_LEARN_INIT(unit); 5059 5060 /* auto learn device info */ 5061 dev_info = bk_info->tsn_dev_info; 5062 al_dev_info = dev_info->tsn_sr_auto_learn_info; 5063 5064 /* Check if the chip specific function existed */ 5065 TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->group_port_reset_all); 5066 5067 /* Reset all ports */ 5068 rv = al_dev_info->group_port_reset_all(unit); 5069 BCM_IF_ERROR_RETURN(rv); 5070 TSN_FUNCTION_TRACE(unit, "OUT"); 5071 return BCM_E_NONE; 5072 } 5073 5074 STATIC int bcmi_esw_tsn_sr_auto_learn_lazy_init(int unit); 5075 STATIC int bcmi_esw_tsn_sr_auto_learn_cleanup(int unit); 5076 5077 /* free the allocate group_id/l2mc entry & mac proxy entry */ 5078 STATIC int 5079 bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx( 5080 int unit, 5081 int *group_id, 5082 int i_pro_idx, 5083 int r_pro_idx[bcmi_sr_auto_learn_group_count], 5084 bcm_tsn_sr_auto_learn_group_config_t *config) 5085 { 5086 bcm_error_t rv = BCM_E_NONE; 5087 5088 /* Parameter NULL error handling */ 5089 if (NULL == config) { 5090 return BCM_E_PARAM; 5091 } 5092 if (NULL != group_id) { 5093 /* Need to free the empty group_id from above */ 5094 bcmi_esw_tsn_sr_auto_learn_destroy_group_id(unit, *group_id); 5095 } 5096 5097 if (BCM_PBMP_NOT_NULL(config->redundant_ports)) { 5098 if (BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID != 5099 r_pro_idx[bcmi_sr_auto_learn_group_l2mc]) { 5100 rv = bcmi_esw_tsn_sr_auto_learn_delete_sr_multicast( 5101 unit, 5102 config->redundant_ports, 5103 r_pro_idx[bcmi_sr_auto_learn_group_l2mc]); 5104 if (BCM_FAILURE(rv)) { 5105 LOG_ERROR(BSL_LS_BCM_TSN, 5106 (BSL_META_U(unit, 5107 "L2MC delete failed(rv = %d)\n"), 5108 rv)); 5109 return rv; 5110 } 5111 } 5112 if (BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID != 5113 r_pro_idx[bcmi_sr_auto_learn_group_macp]) { 5114 rv = bcmi_esw_tsn_sr_mac_proxy_delete( 5115 unit, 5116 r_pro_idx[bcmi_sr_auto_learn_group_macp]); 5117 if (BCM_FAILURE(rv)) { 5118 LOG_ERROR(BSL_LS_BCM_TSN, 5119 (BSL_META_U(unit, 5120 "sr mac proxy profile delete failed" 5121 "(rv = %d)\n"), 5122 rv)); 5123 return rv; 5124 } 5125 } 5126 } 5127 5128 if (BCM_PBMP_NOT_NULL(config->interlink_ports)) { 5129 if (BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID != 5130 i_pro_idx) { 5131 rv = bcmi_esw_tsn_sr_mac_proxy_delete( 5132 unit, 5133 i_pro_idx); 5134 if (BCM_FAILURE(rv)) { 5135 LOG_ERROR(BSL_LS_BCM_TSN, 5136 (BSL_META_U(unit, 5137 "sr mac proxy profile delete failed" 5138 "(rv = %d)\n"), 5139 rv)); 5140 return rv; 5141 } 5142 } 5143 } 5144 return rv; 5145 } 5146 5147 /* 5148 * Function: 5149 * bcmi_esw_tsn_sr_auto_learn_group_create 5150 * Purpose: 5151 * Add an Auto Learn config to hardware. 5152 * Parameters: 5153 * unit - (IN) Unit number 5154 * config - (IN) Auto Learn Group configuration 5155 * group_id - (OUT) Group ID 5156 * Returns: 5157 * BCM_E_xxx 5158 */ 5159 STATIC int 5160 bcmi_esw_tsn_sr_auto_learn_group_create( 5161 int unit, 5162 bcm_tsn_sr_auto_learn_group_config_t *config, 5163 int *group_id) 5164 { 5165 bcm_error_t rv = BCM_E_UNAVAIL; 5166 #if defined(BCM_TSN_SR_SUPPORT) 5167 uint32 sw_idx; 5168 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 5169 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 5170 const tsn_sr_auto_learn_info_t *al_dev_info = NULL; 5171 bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL; 5172 bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *bk_group_data; 5173 bcm_tsn_sr_auto_learn_group_config_t *bk_config; 5174 int pro_idx = BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID; 5175 bcmi_tsn_sr_auto_learn_group_port_type_t group_ports_type; 5176 bcm_pbmp_t group_ports_pbmp; 5177 int new_i_pro_idx = BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID; 5178 int new_r_pro_idx[bcmi_sr_auto_learn_group_count] = 5179 { BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID, 5180 BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID}; 5181 5182 TSN_FUNCTION_TRACE(unit, "IN"); 5183 5184 /* Parameter NULL error handling */ 5185 if ((NULL == config) || (NULL == group_id) || 5186 ((BCM_PBMP_IS_NULL(config->redundant_ports)) && 5187 (BCM_PBMP_IS_NULL(config->interlink_ports))) || 5188 ((0 != config->flags) && 5189 ((~BCMI_TSN_SR_AUTO_LEARN_GROUP_VALID_FLAGS) & config->flags))) { 5190 return BCM_E_PARAM; 5191 } 5192 5193 bcmi_esw_tsn_sr_auto_learn_group_config_dump( 5194 unit, "auto_learn_group_create", config); 5195 5196 /* SR Auto Learn management initialization */ 5197 rv = bcmi_esw_tsn_sr_auto_learn_lazy_init(unit); 5198 if (BCM_FAILURE(rv)) { 5199 bcmi_esw_tsn_sr_auto_learn_cleanup(unit); 5200 return (rv); 5201 } 5202 5203 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 5204 /* auto learn bk info */ 5205 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 5206 5207 /* Initialization check */ 5208 AUTO_LEARN_INIT(unit); 5209 5210 /* auto learn bk info */ 5211 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 5212 5213 /* auto learn device info */ 5214 dev_info = bk_info->tsn_dev_info; 5215 al_dev_info = dev_info->tsn_sr_auto_learn_info; 5216 5217 /* Check if the chip specific function existed */ 5218 TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->group_port_set); 5219 5220 AUTO_LEARN_LOCK(unit); 5221 5222 /* Check if the same configure and overlapped ports existed */ 5223 rv = bcmi_esw_tsn_sr_auto_learn_group_existed_check(unit, 5224 config, BCMI_SR_AUTO_LEARN_GROUP_ID_INVALID, group_id); 5225 if (BCM_E_EXISTS == rv) { 5226 /* config is the same as config of existing group_id */ 5227 AUTO_LEARN_UNLOCK(unit); 5228 LOG_WARN(BSL_LS_BCM_TSN, 5229 (BSL_META_U(unit, 5230 "config already existed, found group_id(%d)\n"), 5231 *group_id)); 5232 return BCM_E_EXISTS; 5233 } else if (BCM_E_BUSY == rv) { 5234 /* config is found on other group_id (overlapper ports) */ 5235 AUTO_LEARN_UNLOCK(unit); 5236 LOG_WARN(BSL_LS_BCM_TSN, 5237 (BSL_META_U(unit, 5238 "find existed auto learn group failed" 5239 "(rv = %d)\n"), 5240 rv)); 5241 return rv; 5242 } else if (BCM_FAILURE(rv)) { 5243 AUTO_LEARN_UNLOCK(unit); 5244 return rv; 5245 } 5246 5247 /* Get a SW empty group_id */ 5248 rv = bcmi_esw_tsn_sr_auto_learn_get_empty_group_id(unit, group_id); 5249 if (BCM_FAILURE(rv)) { 5250 AUTO_LEARN_UNLOCK(unit); 5251 LOG_ERROR(BSL_LS_BCM_TSN, 5252 (BSL_META_U(unit, 5253 "no empty group_id(rv = %d)\n"), 5254 rv)); 5255 return rv; 5256 } 5257 5258 /* Set SW bookkeeping database pointers */ 5259 sw_idx = GROUP_ID_TO_SW_IDX(*group_id); 5260 bk_group_data = &(al_bk_info->group_data[sw_idx]); 5261 bk_config = &(bk_group_data->config); 5262 5263 /* Check if overlapped */ 5264 BCM_PBMP_ASSIGN(group_ports_pbmp, config->redundant_ports); 5265 BCM_PBMP_AND(group_ports_pbmp, config->interlink_ports); 5266 if (BCM_PBMP_NOT_NULL(group_ports_pbmp)) { 5267 (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx( 5268 unit, group_id, new_i_pro_idx, new_r_pro_idx, config); 5269 return BCM_E_PARAM; 5270 } 5271 /* 5272 * Create auto learn group for redundant and interlink 5273 * 1. auto learn group bitmap with redundant ports 5274 * 2. auto learn group proxy bitmap with interlink & redundant ports 5275 */ 5276 5277 /* redundant ports */ 5278 if (BCM_PBMP_NOT_NULL(config->redundant_ports)) { 5279 /* L2MC */ 5280 group_ports_type = bcmi_sr_auto_learn_group_l2mc; 5281 BCM_PBMP_ASSIGN(group_ports_pbmp, config->redundant_ports); 5282 5283 /* Set new auto learn group (config) */ 5284 rv = bcmi_esw_tsn_sr_auto_learn_create_sr_multicast( 5285 unit, group_ports_pbmp, &pro_idx); 5286 5287 if (BCM_FAILURE(rv)) { 5288 (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx( 5289 unit, group_id, new_i_pro_idx, new_r_pro_idx, config); 5290 AUTO_LEARN_UNLOCK(unit); 5291 LOG_ERROR(BSL_LS_BCM_TSN, 5292 (BSL_META_U(unit, 5293 "L2MC create failed(rv = %d)\n"), 5294 rv)); 5295 return rv; 5296 } 5297 new_r_pro_idx[group_ports_type] = pro_idx; 5298 rv = al_dev_info->group_port_set(unit, group_ports_type, 5299 group_ports_pbmp, pro_idx); 5300 5301 if (BCM_FAILURE(rv)) { 5302 (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx( 5303 unit, group_id, new_i_pro_idx, new_r_pro_idx, config); 5304 AUTO_LEARN_UNLOCK(unit); 5305 LOG_ERROR(BSL_LS_BCM_TSN, 5306 (BSL_META_U(unit, 5307 "write to HW failed(rv = %d)\n"), 5308 rv)); 5309 return rv; 5310 } 5311 5312 5313 /* MAC PROXY */ 5314 group_ports_type = bcmi_sr_auto_learn_group_macp; 5315 5316 /* Set new auto learn group (config) */ 5317 rv = bcmi_esw_tsn_sr_mac_proxy_insert( 5318 unit, group_ports_pbmp, &pro_idx); 5319 5320 if (BCM_FAILURE(rv)) { 5321 (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx( 5322 unit, group_id, new_i_pro_idx, new_r_pro_idx, config); 5323 AUTO_LEARN_UNLOCK(unit); 5324 LOG_ERROR(BSL_LS_BCM_TSN, 5325 (BSL_META_U(unit, 5326 "sr mac proxy profile insert failed" 5327 "(rv = %d)\n"), 5328 rv)); 5329 return rv; 5330 } 5331 new_r_pro_idx[group_ports_type] = pro_idx; 5332 rv = al_dev_info->group_port_set(unit, group_ports_type, 5333 group_ports_pbmp, pro_idx); 5334 5335 if (BCM_FAILURE(rv)) { 5336 (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx( 5337 unit, group_id, new_i_pro_idx, new_r_pro_idx, config); 5338 AUTO_LEARN_UNLOCK(unit); 5339 LOG_ERROR(BSL_LS_BCM_TSN, 5340 (BSL_META_U(unit, 5341 "write to HW failed(rv = %d)\n"), 5342 rv)); 5343 return rv; 5344 } 5345 5346 } 5347 5348 /* interlink ports */ 5349 if (BCM_PBMP_NOT_NULL(config->interlink_ports)) { 5350 /* MAC PROXY */ 5351 group_ports_type = bcmi_sr_auto_learn_group_macp; 5352 BCM_PBMP_ASSIGN(group_ports_pbmp, config->interlink_ports); 5353 5354 /* Set new auto learn group (config) */ 5355 rv = bcmi_esw_tsn_sr_mac_proxy_insert( 5356 unit, group_ports_pbmp, &pro_idx); 5357 5358 if (BCM_FAILURE(rv)) { 5359 (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx( 5360 unit, group_id, new_i_pro_idx, new_r_pro_idx, config); 5361 AUTO_LEARN_UNLOCK(unit); 5362 LOG_ERROR(BSL_LS_BCM_TSN, 5363 (BSL_META_U(unit, 5364 "sr mac proxy profile insert failed" 5365 "(rv = %d)\n"), 5366 rv)); 5367 return rv; 5368 } 5369 new_i_pro_idx = pro_idx; 5370 rv = al_dev_info->group_port_set(unit, group_ports_type, 5371 group_ports_pbmp, pro_idx); 5372 5373 if (BCM_FAILURE(rv)) { 5374 (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx( 5375 unit, group_id, new_i_pro_idx, new_r_pro_idx, config); 5376 AUTO_LEARN_UNLOCK(unit); 5377 LOG_ERROR(BSL_LS_BCM_TSN, 5378 (BSL_META_U(unit, 5379 "write to HW failed(rv = %d)\n"), 5380 rv)); 5381 return rv; 5382 } 5383 5384 } 5385 5386 /* Update SW bookkeeping database */ 5387 AUTO_LEARN_BK_LOCK(unit); 5388 bk_group_data->interlink_pro_idx = new_i_pro_idx; 5389 bk_group_data->redundant_pro_idx[bcmi_sr_auto_learn_group_l2mc] = 5390 new_r_pro_idx[bcmi_sr_auto_learn_group_l2mc]; 5391 bk_group_data->redundant_pro_idx[bcmi_sr_auto_learn_group_macp] = 5392 new_r_pro_idx[bcmi_sr_auto_learn_group_macp]; 5393 bk_group_data->group_id = *group_id; 5394 sal_memcpy(bk_config, 5395 config, 5396 sizeof(bcm_tsn_sr_auto_learn_group_config_t)); 5397 AUTO_LEARN_BK_UNLOCK(unit); 5398 5399 AUTO_LEARN_UNLOCK(unit); 5400 5401 rv = BCM_E_NONE; 5402 #endif /* BCM_TSN_SR_SUPPORT */ 5403 TSN_FUNCTION_TRACE(unit, "OUT"); 5404 return rv; 5405 } 5406 5407 /* 5408 * Function: 5409 * bcmi_esw_tsn_sr_auto_learn_group_set 5410 * Purpose: 5411 * Set Auto Learn config with the given group_id. 5412 * Parameters: 5413 * unit - (IN) Unit number 5414 * group_id - (IN) Group ID 5415 * config - (IN) Auto Learn Group configuration 5416 * Returns: 5417 * BCM_E_xxx 5418 */ 5419 STATIC int 5420 bcmi_esw_tsn_sr_auto_learn_group_set( 5421 int unit, 5422 int group_id, 5423 bcm_tsn_sr_auto_learn_group_config_t *config) 5424 { 5425 bcm_error_t rv = BCM_E_UNAVAIL; 5426 #if defined(BCM_TSN_SR_SUPPORT) 5427 uint32 sw_idx; 5428 int exisited_group_id; 5429 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 5430 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 5431 const tsn_sr_auto_learn_info_t *al_dev_info = NULL; 5432 bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL; 5433 bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *bk_group_data; 5434 bcm_tsn_sr_auto_learn_group_config_t *bk_config; 5435 int pro_idx = BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID; 5436 int new_i_pro_idx = BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID; 5437 int new_r_pro_idx[bcmi_sr_auto_learn_group_count] = 5438 { BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID, 5439 BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID}; 5440 bcmi_tsn_sr_auto_learn_group_port_type_t group_ports_type; 5441 bcm_pbmp_t group_ports_pbmp; 5442 5443 TSN_FUNCTION_TRACE(unit, "IN"); 5444 5445 /* Parameter NULL error handling */ 5446 if ((NULL == config) || 5447 (BCM_PBMP_IS_NULL(config->redundant_ports)) || 5448 (BCM_PBMP_IS_NULL(config->interlink_ports)) || 5449 ((0 != config->flags) && 5450 ((~BCMI_TSN_SR_AUTO_LEARN_GROUP_VALID_FLAGS) & config->flags))) { 5451 return BCM_E_PARAM; 5452 } 5453 5454 bcmi_esw_tsn_sr_auto_learn_group_config_dump( 5455 unit, "auto_learn_group_set", config); 5456 5457 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 5458 5459 /* Initialization check */ 5460 AUTO_LEARN_INIT(unit); 5461 5462 /* auto learn bk info */ 5463 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 5464 5465 /* auto learn device info */ 5466 dev_info = bk_info->tsn_dev_info; 5467 al_dev_info = dev_info->tsn_sr_auto_learn_info; 5468 5469 /* Check if the chip specific function existed */ 5470 TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->group_port_delete); 5471 TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->group_port_set); 5472 5473 AUTO_LEARN_LOCK(unit); 5474 5475 /* Check if group id existed */ 5476 rv = bcmi_esw_tsn_sr_auto_learn_group_id_existed_check(unit, group_id); 5477 if (BCM_FAILURE(rv)) { 5478 AUTO_LEARN_UNLOCK(unit); 5479 LOG_WARN(BSL_LS_BCM_TSN, 5480 (BSL_META_U(unit, 5481 "group_id(%d) doesn't exited\n"), group_id)); 5482 return rv; 5483 } 5484 5485 /* Check if the same configure existed or not */ 5486 rv = bcmi_esw_tsn_sr_auto_learn_group_existed_check(unit, 5487 config, group_id, &exisited_group_id); 5488 if (BCM_E_EXISTS == rv) { 5489 if (exisited_group_id == group_id) { 5490 /* config is the same as config of current group_id */ 5491 AUTO_LEARN_UNLOCK(unit); 5492 LOG_WARN(BSL_LS_BCM_TSN, 5493 (BSL_META_U(unit, 5494 "config is the same as the config " 5495 "of current group_id(%d)\n"), 5496 group_id)); 5497 /* config are the same, do nothing */ 5498 return BCM_E_NONE; 5499 } else { 5500 /* the config is found on other group_id */ 5501 AUTO_LEARN_UNLOCK(unit); 5502 LOG_WARN(BSL_LS_BCM_TSN, 5503 (BSL_META_U(unit, 5504 "config already existed, " 5505 "found group_id(%d)\n"), 5506 exisited_group_id)); 5507 return BCM_E_EXISTS; 5508 } 5509 } else if (BCM_E_BUSY == rv) { 5510 /* config is found on other group_id (overlapper ports) */ 5511 AUTO_LEARN_UNLOCK(unit); 5512 LOG_WARN(BSL_LS_BCM_TSN, 5513 (BSL_META_U(unit, 5514 "find existed auto learn group failed" 5515 "(rv = %d)\n"), 5516 rv)); 5517 return rv; 5518 } else if (BCM_FAILURE(rv)) { 5519 AUTO_LEARN_UNLOCK(unit); 5520 return rv; 5521 } 5522 5523 /* Check if overlapped */ 5524 BCM_PBMP_ASSIGN(group_ports_pbmp, config->redundant_ports); 5525 BCM_PBMP_AND(group_ports_pbmp, config->interlink_ports); 5526 if (BCM_PBMP_NOT_NULL(group_ports_pbmp)) { 5527 return BCM_E_PARAM; 5528 } 5529 5530 /* Set SW bookkeeping database pointers */ 5531 sw_idx = GROUP_ID_TO_SW_IDX(group_id); 5532 bk_group_data = &(al_bk_info->group_data[sw_idx]); 5533 bk_config = &(bk_group_data->config); 5534 5535 /* 5536 * Delete bk auto learn group and then set new one 5537 * 1. auto learn group bitmap with redundant ports 5538 * 2. auto learn group proxy bitmap with interlink & redundant ports 5539 */ 5540 5541 /* Only add when new config is different from bookkeeping's */ 5542 if (BCM_PBMP_NOT_NULL(bk_config->redundant_ports) && 5543 BCM_PBMP_NEQ(bk_config->redundant_ports, config->redundant_ports)) { 5544 /* Set new auto learn group (config) */ 5545 5546 /* L2MC */ 5547 group_ports_type = bcmi_sr_auto_learn_group_l2mc; 5548 BCM_PBMP_ASSIGN(group_ports_pbmp, config->redundant_ports); 5549 rv = bcmi_esw_tsn_sr_auto_learn_create_sr_multicast( 5550 unit, group_ports_pbmp, &pro_idx); 5551 5552 if (BCM_FAILURE(rv)) { 5553 AUTO_LEARN_UNLOCK(unit); 5554 LOG_ERROR(BSL_LS_BCM_TSN, 5555 (BSL_META_U(unit, 5556 "L2MC create failed(rv = %d)\n"), 5557 rv)); 5558 return rv; 5559 } 5560 new_r_pro_idx[group_ports_type] = pro_idx; 5561 rv = al_dev_info->group_port_set(unit, group_ports_type, 5562 group_ports_pbmp, pro_idx); 5563 5564 if (BCM_FAILURE(rv)) { 5565 (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx( 5566 unit, NULL, new_i_pro_idx, new_r_pro_idx, config); 5567 AUTO_LEARN_UNLOCK(unit); 5568 LOG_ERROR(BSL_LS_BCM_TSN, 5569 (BSL_META_U(unit, 5570 "write to HW failed(rv = %d)\n"), 5571 rv)); 5572 return rv; 5573 } 5574 5575 5576 /* MAC PROXY */ 5577 group_ports_type = bcmi_sr_auto_learn_group_macp; 5578 5579 /* Set new auto learn group (config) */ 5580 rv = bcmi_esw_tsn_sr_mac_proxy_insert( 5581 unit, group_ports_pbmp, &pro_idx); 5582 5583 if (BCM_FAILURE(rv)) { 5584 (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx( 5585 unit, NULL, new_i_pro_idx, new_r_pro_idx, config); 5586 AUTO_LEARN_UNLOCK(unit); 5587 LOG_ERROR(BSL_LS_BCM_TSN, 5588 (BSL_META_U(unit, 5589 "sr mac proxy profile insert failed" 5590 "(rv = %d)\n"), 5591 rv)); 5592 return rv; 5593 } 5594 5595 new_r_pro_idx[group_ports_type] = pro_idx; 5596 rv = al_dev_info->group_port_set(unit, group_ports_type, 5597 group_ports_pbmp, pro_idx); 5598 5599 if (BCM_FAILURE(rv)) { 5600 (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx( 5601 unit, NULL, new_i_pro_idx, new_r_pro_idx, config); 5602 AUTO_LEARN_UNLOCK(unit); 5603 LOG_ERROR(BSL_LS_BCM_TSN, 5604 (BSL_META_U(unit, 5605 "write to HW failed(rv = %d)\n"), 5606 rv)); 5607 return rv; 5608 } 5609 } 5610 5611 /* Only add when new config is different from bookkeeping's */ 5612 if (BCM_PBMP_NOT_NULL(bk_config->interlink_ports) && 5613 BCM_PBMP_NEQ(bk_config->interlink_ports, config->interlink_ports)) { 5614 /* MAC PROXY */ 5615 group_ports_type = bcmi_sr_auto_learn_group_macp; 5616 5617 /* Set new auto learn group (config) */ 5618 BCM_PBMP_ASSIGN(group_ports_pbmp, config->interlink_ports); 5619 rv = bcmi_esw_tsn_sr_mac_proxy_insert( 5620 unit, group_ports_pbmp, &pro_idx); 5621 5622 if (BCM_FAILURE(rv)) { 5623 (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx( 5624 unit, NULL, new_i_pro_idx, new_r_pro_idx, config); 5625 AUTO_LEARN_UNLOCK(unit); 5626 LOG_ERROR(BSL_LS_BCM_TSN, 5627 (BSL_META_U(unit, 5628 "sr mac proxy profile insert failed" 5629 "(rv = %d)\n"), 5630 rv)); 5631 return rv; 5632 } 5633 new_i_pro_idx = pro_idx; 5634 rv = al_dev_info->group_port_set(unit, group_ports_type, 5635 group_ports_pbmp, pro_idx); 5636 5637 if (BCM_FAILURE(rv)) { 5638 (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx( 5639 unit, NULL, new_i_pro_idx, new_r_pro_idx, config); 5640 AUTO_LEARN_UNLOCK(unit); 5641 LOG_ERROR(BSL_LS_BCM_TSN, 5642 (BSL_META_U(unit, 5643 "write to HW failed(rv = %d)\n"), 5644 rv)); 5645 return rv; 5646 } 5647 } 5648 5649 /* delete redundant ports */ 5650 if (BCM_PBMP_NOT_NULL(bk_config->redundant_ports) && 5651 BCM_PBMP_NEQ(bk_config->redundant_ports, config->redundant_ports)) { 5652 /* L2MC */ 5653 group_ports_type = bcmi_sr_auto_learn_group_l2mc; 5654 BCM_PBMP_ASSIGN(group_ports_pbmp, bk_config->redundant_ports); 5655 if (BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID != 5656 bk_group_data->redundant_pro_idx[group_ports_type]) { 5657 5658 rv = bcmi_esw_tsn_sr_auto_learn_delete_sr_multicast( 5659 unit, group_ports_pbmp, 5660 bk_group_data->redundant_pro_idx[group_ports_type]); 5661 if (BCM_FAILURE(rv)) { 5662 LOG_ERROR(BSL_LS_BCM_TSN, 5663 (BSL_META_U(unit, 5664 "L2MC delete failed(rv = %d)\n"), 5665 rv)); 5666 } 5667 } 5668 /* Delete HW */ 5669 5670 /* should not delete the ports with new created */ 5671 BCM_PBMP_REMOVE(group_ports_pbmp, config->redundant_ports); 5672 rv = al_dev_info->group_port_delete(unit, group_ports_type, 5673 group_ports_pbmp); 5674 5675 if (BCM_FAILURE(rv)) { 5676 LOG_ERROR(BSL_LS_BCM_TSN, 5677 (BSL_META_U(unit, 5678 "write to HW failed(rv = %d)\n"), 5679 rv)); 5680 } 5681 5682 /* MAC PROXY */ 5683 group_ports_type = bcmi_sr_auto_learn_group_macp; 5684 BCM_PBMP_ASSIGN(group_ports_pbmp, bk_config->redundant_ports); 5685 if (BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID != 5686 bk_group_data->redundant_pro_idx[group_ports_type]) { 5687 rv = bcmi_esw_tsn_sr_mac_proxy_delete( 5688 unit, bk_group_data->redundant_pro_idx[group_ports_type]); 5689 if (BCM_FAILURE(rv)) { 5690 LOG_ERROR(BSL_LS_BCM_TSN, 5691 (BSL_META_U(unit, 5692 "sr mac proxy profile delete failed" 5693 "(rv = %d)\n"), 5694 rv)); 5695 } 5696 } 5697 /* Delete HW */ 5698 5699 /* should not delete the ports overlapped with newly created */ 5700 BCM_PBMP_REMOVE(group_ports_pbmp, config->interlink_ports); 5701 BCM_PBMP_REMOVE(group_ports_pbmp, config->redundant_ports); 5702 rv = al_dev_info->group_port_delete(unit, group_ports_type, 5703 group_ports_pbmp); 5704 5705 if (BCM_FAILURE(rv)) { 5706 LOG_ERROR(BSL_LS_BCM_TSN, 5707 (BSL_META_U(unit, 5708 "write to HW failed(rv = %d)\n"), 5709 rv)); 5710 } 5711 } 5712 5713 /* delete interlink ports */ 5714 if (BCM_PBMP_NOT_NULL(bk_config->interlink_ports) && 5715 BCM_PBMP_NEQ(bk_config->interlink_ports, config->interlink_ports)) { 5716 5717 /* MAC PROXY */ 5718 group_ports_type = bcmi_sr_auto_learn_group_macp; 5719 BCM_PBMP_ASSIGN(group_ports_pbmp, bk_config->interlink_ports); 5720 if (BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID != 5721 bk_group_data->redundant_pro_idx[group_ports_type]) { 5722 rv = bcmi_esw_tsn_sr_mac_proxy_delete( 5723 unit, bk_group_data->interlink_pro_idx); 5724 if (BCM_FAILURE(rv)) { 5725 LOG_ERROR(BSL_LS_BCM_TSN, 5726 (BSL_META_U(unit, 5727 "sr mac proxy profile delete failed" 5728 "(rv = %d)\n"), 5729 rv)); 5730 } 5731 } 5732 /* Delete HW */ 5733 5734 /* should not delete the ports overlapped with newly created */ 5735 BCM_PBMP_REMOVE(group_ports_pbmp, config->interlink_ports); 5736 BCM_PBMP_REMOVE(group_ports_pbmp, config->redundant_ports); 5737 rv = al_dev_info->group_port_delete(unit, group_ports_type, 5738 group_ports_pbmp); 5739 5740 if (BCM_FAILURE(rv)) { 5741 LOG_ERROR(BSL_LS_BCM_TSN, 5742 (BSL_META_U(unit, 5743 "write to HW failed(rv = %d)\n"), 5744 rv)); 5745 } 5746 } 5747 5748 /* Update SW bookkeeping database */ 5749 AUTO_LEARN_BK_LOCK(unit); 5750 if (BCM_PBMP_NOT_NULL(bk_config->interlink_ports) && 5751 BCM_PBMP_NEQ(bk_config->interlink_ports, config->interlink_ports)) { 5752 bk_group_data->interlink_pro_idx = new_i_pro_idx; 5753 } 5754 if (BCM_PBMP_NOT_NULL(bk_config->redundant_ports) && 5755 BCM_PBMP_NEQ(bk_config->redundant_ports, config->redundant_ports)) { 5756 bk_group_data->redundant_pro_idx[bcmi_sr_auto_learn_group_l2mc] = 5757 new_r_pro_idx[bcmi_sr_auto_learn_group_l2mc]; 5758 bk_group_data->redundant_pro_idx[bcmi_sr_auto_learn_group_macp] = 5759 new_r_pro_idx[bcmi_sr_auto_learn_group_macp]; 5760 } 5761 sal_memcpy(bk_config, 5762 config, 5763 sizeof(bcm_tsn_sr_auto_learn_group_config_t)); 5764 AUTO_LEARN_BK_UNLOCK(unit); 5765 AUTO_LEARN_UNLOCK(unit); 5766 5767 rv = BCM_E_NONE; 5768 #endif /* BCM_TSN_SR_SUPPORT */ 5769 TSN_FUNCTION_TRACE(unit, "OUT"); 5770 return rv; 5771 } 5772 5773 /* 5774 * Function: 5775 * bcmi_esw_tsn_sr_auto_learn_group_get 5776 * Purpose: 5777 * Get the Auto Learn config with the given group_id. 5778 * Parameters: 5779 * unit - (IN) Unit number 5780 * group_id - (IN) Group ID 5781 * config - (OUT) Auto Learn Group configuration 5782 * Returns: 5783 * BCM_E_xxx 5784 */ 5785 STATIC int 5786 bcmi_esw_tsn_sr_auto_learn_group_get( 5787 int unit, 5788 int group_id, 5789 bcm_tsn_sr_auto_learn_group_config_t *config) 5790 { 5791 bcm_error_t rv = BCM_E_UNAVAIL; 5792 #if defined(BCM_TSN_SR_SUPPORT) 5793 uint32 sw_idx; 5794 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 5795 bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL; 5796 bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *bk_group_data; 5797 bcm_tsn_sr_auto_learn_group_config_t *bk_config; 5798 5799 TSN_FUNCTION_TRACE(unit, "IN"); 5800 5801 /* Parameter NULL error handling */ 5802 if (NULL == config) { 5803 return BCM_E_PARAM; 5804 } 5805 5806 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 5807 5808 /* Initialization check */ 5809 AUTO_LEARN_INIT(unit); 5810 5811 /* auto learn bk info */ 5812 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 5813 5814 AUTO_LEARN_LOCK(unit); 5815 5816 /* Check if group id existed */ 5817 rv = bcmi_esw_tsn_sr_auto_learn_group_id_existed_check(unit, group_id); 5818 if (BCM_FAILURE(rv)) { 5819 AUTO_LEARN_UNLOCK(unit); 5820 LOG_WARN(BSL_LS_BCM_TSN, 5821 (BSL_META_U(unit, 5822 "group_id(%d) doesn't exited\n"), group_id)); 5823 return rv; 5824 } 5825 5826 /* Get the configure from SW bookkeeping database */ 5827 sw_idx = GROUP_ID_TO_SW_IDX(group_id); 5828 bk_group_data = &(al_bk_info->group_data[sw_idx]); 5829 bk_config = &(bk_group_data->config); 5830 sal_memcpy(config, 5831 bk_config, 5832 sizeof(bcm_tsn_sr_auto_learn_group_config_t)); 5833 5834 AUTO_LEARN_UNLOCK(unit); 5835 5836 bcmi_esw_tsn_sr_auto_learn_group_config_dump( 5837 unit, "auto_learn_group_get", config); 5838 5839 rv = BCM_E_NONE; 5840 #endif /* BCM_TSN_SR_SUPPORT */ 5841 TSN_FUNCTION_TRACE(unit, "OUT"); 5842 return rv; 5843 } 5844 5845 /* 5846 * Function: 5847 * bcmi_esw_tsn_sr_auto_learn_group_destroy 5848 * Purpose: 5849 * Destroy an Auto Learn config with the given group_id by removing it 5850 * from hardware and deleting the associated software state info. 5851 * Parameters: 5852 * unit - (IN) Unit number 5853 * group_id - (IN) Group ID 5854 * Returns: 5855 * BCM_E_NONE - destroy successfully 5856 */ 5857 STATIC int 5858 bcmi_esw_tsn_sr_auto_learn_group_destroy( 5859 int unit, 5860 int group_id) 5861 { 5862 bcm_error_t rv = BCM_E_UNAVAIL; 5863 #if defined(BCM_TSN_SR_SUPPORT) 5864 uint32 sw_idx; 5865 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 5866 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 5867 const tsn_sr_auto_learn_info_t *al_dev_info = NULL; 5868 bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL; 5869 bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *bk_group_data; 5870 bcm_tsn_sr_auto_learn_group_config_t *bk_config; 5871 bcmi_tsn_sr_auto_learn_group_port_type_t group_ports_type; 5872 bcm_pbmp_t group_ports_pbmp; 5873 5874 TSN_FUNCTION_TRACE(unit, "IN"); 5875 5876 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 5877 5878 /* Initialization check */ 5879 AUTO_LEARN_INIT(unit); 5880 5881 /* auto learn bk info */ 5882 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 5883 5884 /* auto learn device info */ 5885 dev_info = bk_info->tsn_dev_info; 5886 al_dev_info = dev_info->tsn_sr_auto_learn_info; 5887 5888 /* Check if the chip specific function existed */ 5889 TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->group_port_delete); 5890 5891 /* Check if group id existed */ 5892 rv = bcmi_esw_tsn_sr_auto_learn_group_id_existed_check(unit, group_id); 5893 if (BCM_FAILURE(rv)) { 5894 LOG_WARN(BSL_LS_BCM_TSN, 5895 (BSL_META_U(unit, 5896 "group_id(%d) doesn't exited\n"), group_id)); 5897 return BCM_E_NOT_FOUND; 5898 } 5899 if (!SOC_UNIT_VALID(unit)) { 5900 return BCM_E_UNIT; 5901 } 5902 5903 AUTO_LEARN_LOCK(unit); 5904 5905 /* Delete HW */ 5906 if (BCM_FAILURE(rv)) { 5907 AUTO_LEARN_UNLOCK(unit); 5908 LOG_ERROR(BSL_LS_BCM_TSN, 5909 (BSL_META_U(unit, 5910 "delete HW failed(rv = %d)\n"), 5911 rv)); 5912 5913 return rv; 5914 } 5915 5916 /* Set SW bookkeeping database pointers */ 5917 sw_idx = GROUP_ID_TO_SW_IDX(group_id); 5918 bk_group_data = &(al_bk_info->group_data[sw_idx]); 5919 bk_config = &(bk_group_data->config); 5920 5921 /* 5922 * Delete auto learn group for redundant and interlink 5923 * 1. auto learn group bitmap with redundant ports 5924 * 2. auto learn group proxy bitmap with interlink & redundant ports 5925 */ 5926 AUTO_LEARN_BK_LOCK(unit); 5927 (void)bcmi_esw_tsn_sr_auto_learn_group_free_pro_idx( 5928 unit, &group_id, 5929 bk_group_data->interlink_pro_idx, 5930 bk_group_data->redundant_pro_idx, 5931 bk_config); 5932 AUTO_LEARN_BK_UNLOCK(unit); 5933 5934 /* redundant ports */ 5935 if (BCM_PBMP_NOT_NULL(bk_config->redundant_ports)) { 5936 /* L2MC */ 5937 group_ports_type = bcmi_sr_auto_learn_group_l2mc; 5938 BCM_PBMP_ASSIGN(group_ports_pbmp, bk_config->redundant_ports); 5939 5940 /* Delete HW */ 5941 rv = al_dev_info->group_port_delete(unit, group_ports_type, 5942 group_ports_pbmp); 5943 5944 if (BCM_FAILURE(rv)) { 5945 AUTO_LEARN_UNLOCK(unit); 5946 LOG_ERROR(BSL_LS_BCM_TSN, 5947 (BSL_META_U(unit, 5948 "L2MC delete failed(rv = %d)\n"), 5949 rv)); 5950 return rv; 5951 } 5952 5953 /* MAC PROXY */ 5954 group_ports_type = bcmi_sr_auto_learn_group_macp; 5955 BCM_PBMP_ASSIGN(group_ports_pbmp, bk_config->redundant_ports); 5956 5957 /* Delete HW */ 5958 rv = al_dev_info->group_port_delete(unit, group_ports_type, 5959 group_ports_pbmp); 5960 5961 if (BCM_FAILURE(rv)) { 5962 AUTO_LEARN_UNLOCK(unit); 5963 LOG_ERROR(BSL_LS_BCM_TSN, 5964 (BSL_META_U(unit, 5965 "MAC PROXY delete failed(rv = %d)\n"), 5966 rv)); 5967 return rv; 5968 } 5969 } 5970 5971 /* interlink ports */ 5972 if (BCM_PBMP_NOT_NULL(bk_config->interlink_ports)) { 5973 /* MAC PROXY */ 5974 group_ports_type = bcmi_sr_auto_learn_group_macp; 5975 BCM_PBMP_ASSIGN(group_ports_pbmp, bk_config->interlink_ports); 5976 5977 /* Delete HW */ 5978 rv = al_dev_info->group_port_delete(unit, group_ports_type, 5979 group_ports_pbmp); 5980 5981 if (BCM_FAILURE(rv)) { 5982 AUTO_LEARN_UNLOCK(unit); 5983 LOG_ERROR(BSL_LS_BCM_TSN, 5984 (BSL_META_U(unit, 5985 "write to HW failed(rv = %d)\n"), 5986 rv)); 5987 return rv; 5988 } 5989 } 5990 5991 /* Clear SW bookkeeping database */ 5992 AUTO_LEARN_BK_LOCK(unit); 5993 bk_group_data->redundant_pro_idx[bcmi_sr_auto_learn_group_l2mc] = 5994 BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID; 5995 bk_group_data->redundant_pro_idx[bcmi_sr_auto_learn_group_macp] = 5996 BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID; 5997 bk_group_data->interlink_pro_idx = 5998 BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID; 5999 bk_group_data->group_id = BCMI_SR_AUTO_LEARN_GROUP_ID_INVALID; 6000 sal_memset(bk_config, 6001 0, 6002 sizeof(bcm_tsn_sr_auto_learn_group_config_t)); 6003 AUTO_LEARN_BK_UNLOCK(unit); 6004 6005 /* Clear HW status if there is no valid one.*/ 6006 if (0 == al_bk_info->valid_count) { 6007 rv = bcmi_esw_tsn_sr_auto_learn_hw_delete_all(unit); 6008 if (BCM_FAILURE(rv)) { 6009 AUTO_LEARN_UNLOCK(unit); 6010 LOG_ERROR(BSL_LS_BCM_TSN, 6011 (BSL_META_U(unit, 6012 "Delete all HW resource failed(rv = %d)\n"), 6013 rv)); 6014 6015 return rv; 6016 } 6017 } 6018 AUTO_LEARN_UNLOCK(unit); 6019 6020 rv = BCM_E_NONE; 6021 #endif /* BCM_TSN_SR_SUPPORT */ 6022 6023 TSN_FUNCTION_TRACE(unit, "OUT"); 6024 return rv; 6025 } 6026 6027 /* 6028 * Function: 6029 * bcmi_esw_tsn_sr_auto_learn_group_traverse 6030 * Purpose: 6031 * Traverse the Auto Learn config information. 6032 * Parameters: 6033 * unit - (IN) Unit number 6034 * cb - (IN) Traverse call back function 6035 * user_data - (IN) User data 6036 * Returns: 6037 * BCM_E_xxx 6038 */ 6039 STATIC int 6040 bcmi_esw_tsn_sr_auto_learn_group_traverse( 6041 int unit, 6042 bcm_tsn_sr_auto_learn_group_traverse_cb cb, 6043 void *user_data) 6044 { 6045 bcm_error_t rv = BCM_E_UNAVAIL; 6046 #if defined(BCM_TSN_SR_SUPPORT) 6047 uint32 sw_idx; 6048 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 6049 bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL; 6050 6051 TSN_FUNCTION_TRACE(unit, "IN"); 6052 6053 /* Parameter NULL error handling */ 6054 if (NULL == cb) { 6055 return BCM_E_PARAM; 6056 } 6057 6058 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 6059 6060 /* Initialization check */ 6061 AUTO_LEARN_INIT(unit); 6062 6063 AUTO_LEARN_LOCK(unit); 6064 /* auto learn bk info */ 6065 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 6066 6067 for (sw_idx = al_bk_info->valid_sw_idx_start; 6068 sw_idx <= al_bk_info->valid_sw_idx_end; 6069 sw_idx++) { 6070 if (AUTO_LEARN_INTF_USED_GET(unit, sw_idx)) { 6071 rv = cb(unit, SW_IDX_TO_GROUP_ID(sw_idx), user_data); 6072 if (BCM_FAILURE(rv)) { 6073 AUTO_LEARN_UNLOCK(unit); 6074 return rv; 6075 } 6076 } 6077 } 6078 6079 AUTO_LEARN_UNLOCK(unit); 6080 6081 rv = BCM_E_NONE; 6082 #endif /* BCM_TSN_SR_SUPPORT */ 6083 TSN_FUNCTION_TRACE(unit, "OUT"); 6084 return rv; 6085 } 6086 6087 6088 /* 6089 * De-allocate a flowset list and underlying flows with flowset index 6090 */ 6091 STATIC void 6092 bcmi_esw_tsn_sr_auto_learn_free_flowset( 6093 int unit, 6094 bcm_tsn_sr_flowset_t *flowset[bcmi_sr_auto_learn_flow_count], 6095 uint32 *flowset_cnt, 6096 int clear_hw) 6097 { 6098 int i; 6099 bcmi_tsn_sr_auto_learn_flow_t flow_type; 6100 6101 /* Parameter NULL error handling */ 6102 if ((NULL == flowset) || (NULL == flowset_cnt)) { 6103 return; 6104 } 6105 6106 for (flow_type = bcmi_sr_auto_learn_flow_tx; 6107 flow_type < bcmi_sr_auto_learn_flow_count; 6108 flow_type++) { 6109 if (TRUE == clear_hw) { 6110 for (i = 0; i < flowset_cnt[flow_type]; i++) { 6111 if (0 != flowset[flow_type][i]) { 6112 (void)bcm_esw_tsn_sr_flowset_destroy( 6113 unit, flowset[flow_type][i]); 6114 } 6115 } 6116 } 6117 if (flowset[flow_type] != NULL) { 6118 TSN_FREE(unit, flowset[flow_type], 0); 6119 flowset[flow_type] = NULL; 6120 } 6121 flowset_cnt[flow_type] = 0; 6122 } 6123 } 6124 6125 /* 6126 * Function: 6127 * bcmi_esw_tsn_sr_auto_learn_enable 6128 * Purpose: 6129 * Enable/disable SR flow auto learn subsystem 6130 * Parameters: 6131 * unit - (IN) Unit number 6132 * enable - (IN) Enable/Disable 6133 * config - (IN) Auto Learn configuration 6134 * Returns: 6135 * BCM_E_xxx 6136 */ 6137 STATIC int 6138 bcmi_esw_tsn_sr_auto_learn_enable( 6139 int unit, 6140 int enable, 6141 bcm_tsn_sr_auto_learn_config_t *config) 6142 { 6143 bcm_error_t rv = BCM_E_UNAVAIL; 6144 #if defined(BCM_TSN_SR_SUPPORT) 6145 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 6146 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 6147 const tsn_sr_auto_learn_info_t *al_dev_info = NULL; 6148 bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL; 6149 bcmi_esw_tsn_sr_auto_learn_bk_data_t *bk_data = NULL; 6150 bcmi_tsn_sr_auto_learn_flow_t flow_type; 6151 bcm_tsn_sr_flowset_t flowset; 6152 bcm_tsn_sr_flow_t fid; 6153 uint32 hwfid; 6154 int i, prev = 0; 6155 uint32 ctrl_current_fid = 0, ctrl_last_fid = 0; 6156 uint32 ctrl_id_size[bcmi_sr_auto_learn_flow_count]; 6157 6158 TSN_FUNCTION_TRACE(unit, "IN"); 6159 6160 /* Parameter NULL error handling */ 6161 if ((TRUE == enable) && 6162 ((NULL == config) || 6163 (NULL != config && 6164 (0 == config->num_tx_flows || 0 == config->num_rx_flows)))) { 6165 return BCM_E_PARAM; 6166 } 6167 6168 /* SR Auto Learn management initialization */ 6169 rv = bcmi_esw_tsn_sr_auto_learn_lazy_init(unit); 6170 if (BCM_FAILURE(rv)) { 6171 bcmi_esw_tsn_sr_auto_learn_cleanup(unit); 6172 return (rv); 6173 } 6174 6175 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 6176 6177 /* Initialization check */ 6178 AUTO_LEARN_INIT(unit); 6179 6180 /* auto learn bk info */ 6181 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 6182 6183 /* auto learn device info */ 6184 dev_info = bk_info->tsn_dev_info; 6185 al_dev_info = dev_info->tsn_sr_auto_learn_info; 6186 6187 bcmi_esw_tsn_sr_auto_learn_config_dump(unit, "auto_learn_enable", config); 6188 6189 /* Check if the chip specific function existed */ 6190 TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->flow_id_pool_set); 6191 TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->flow_id_ctrl_set); 6192 TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->enable); 6193 6194 /* Check Auto Learn is already enabled and config to enable is the same */ 6195 if ((TRUE == enable) && 6196 (TRUE == al_bk_info->data.enabled) && 6197 (!sal_memcmp(config, &al_bk_info->data, 6198 sizeof(bcm_tsn_sr_auto_learn_config_t)))) { 6199 LOG_ERROR(BSL_LS_BCM_TSN, 6200 (BSL_META_U(unit, 6201 "Auto Learn has already enabled, " 6202 "please disable auto learn first.\n"))); 6203 return BCM_E_BUSY; 6204 } 6205 6206 AUTO_LEARN_LOCK(unit); 6207 AUTO_LEARN_BK_LOCK(unit); 6208 6209 bk_data = &(al_bk_info->data); 6210 /* 6211 * Create N(num_tx/rx_flows) flows with tx/rx_flow_config for tx/rx flows 6212 * Each tx/rx flow is a linked list, begin at ctrl_current_fid and end 6213 * at ctrl_last_fid. 6214 */ 6215 if (TRUE == enable) { 6216 /* Check if id sizes excess the max flow number */ 6217 ctrl_id_size[bcmi_sr_auto_learn_flow_tx] = config->num_tx_flows; 6218 ctrl_id_size[bcmi_sr_auto_learn_flow_rx] = config->num_rx_flows; 6219 6220 for (flow_type = bcmi_sr_auto_learn_flow_tx; 6221 flow_type < bcmi_sr_auto_learn_flow_count; 6222 flow_type++) { 6223 if (ctrl_id_size[flow_type] > 6224 (al_dev_info->max_flow_num[flow_type])) { 6225 AUTO_LEARN_BK_UNLOCK(unit); 6226 AUTO_LEARN_UNLOCK(unit); 6227 return BCM_E_PARAM; 6228 } 6229 } 6230 6231 bcmi_esw_tsn_sr_auto_learn_free_flowset( 6232 unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE); 6233 6234 for (flow_type = bcmi_sr_auto_learn_flow_tx; 6235 flow_type < bcmi_sr_auto_learn_flow_count; 6236 flow_type++) { 6237 6238 TSN_ALLOC(unit, bk_data->flowsets[flow_type], 6239 bcm_tsn_sr_flowset_t, 6240 sizeof(bcm_tsn_sr_flowset_t) * ctrl_id_size[flow_type], 6241 "bk record Rx/Tx Flowset", 0, rv); 6242 if (BCM_FAILURE(rv)) { 6243 AUTO_LEARN_BK_UNLOCK(unit); 6244 AUTO_LEARN_UNLOCK(unit); 6245 LOG_VERBOSE(BSL_LS_BCM_TSN, 6246 (BSL_META_U(unit, 6247 "failed to allocate" 6248 "Rx/Tx Flowset memory\n"))); 6249 return rv; 6250 } 6251 /* Create N flowsets with tx/rx flow config */ 6252 for (i = 0; i < ctrl_id_size[flow_type]; i++) { 6253 if (bcmi_sr_auto_learn_flow_tx == flow_type) { 6254 rv = bcm_esw_tsn_sr_tx_flowset_create( 6255 unit, BCM_TSN_PRI_MAP_INVALID, 6256 &config->tx_flow_config, &flowset); 6257 } else if (bcmi_sr_auto_learn_flow_rx == flow_type) { 6258 rv = bcm_esw_tsn_sr_rx_flowset_create( 6259 unit, BCM_TSN_PRI_MAP_INVALID, 6260 &config->rx_flow_config, &flowset); 6261 } 6262 6263 if (BCM_FAILURE(rv)) { 6264 bcmi_esw_tsn_sr_auto_learn_free_flowset( 6265 unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE); 6266 AUTO_LEARN_BK_UNLOCK(unit); 6267 AUTO_LEARN_UNLOCK(unit); 6268 return rv; 6269 } 6270 bk_data->flowsets[flow_type][i] = flowset; 6271 bk_data->flowsets_cnt[flow_type] = i + 1; 6272 /* Get the flow_id from created flowset */ 6273 rv = bcm_esw_tsn_sr_flowset_flow_get( 6274 unit, flowset, 0, &fid); 6275 if (BCM_FAILURE(rv)) { 6276 bcmi_esw_tsn_sr_auto_learn_free_flowset( 6277 unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE); 6278 AUTO_LEARN_BK_UNLOCK(unit); 6279 AUTO_LEARN_UNLOCK(unit); 6280 return rv; 6281 } 6282 6283 /* Convert software SR flow ID to hardware SR flow ID */ 6284 rv = bcmi_esw_tsn_sr_hw_flow_id_get( 6285 unit, fid, &hwfid); 6286 if (BCM_FAILURE(rv)) { 6287 bcmi_esw_tsn_sr_auto_learn_free_flowset( 6288 unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE); 6289 AUTO_LEARN_BK_UNLOCK(unit); 6290 AUTO_LEARN_UNLOCK(unit); 6291 return rv; 6292 } 6293 if (i == 0) { 6294 ctrl_current_fid = hwfid; 6295 prev = hwfid; 6296 continue; 6297 } 6298 6299 /* Write next fid (prev pointer to fid) */ 6300 rv = al_dev_info->flow_id_pool_set( 6301 unit, flow_type, prev, hwfid); 6302 if (BCM_FAILURE(rv)) { 6303 bcmi_esw_tsn_sr_auto_learn_free_flowset( 6304 unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE); 6305 AUTO_LEARN_BK_UNLOCK(unit); 6306 AUTO_LEARN_UNLOCK(unit); 6307 LOG_ERROR(BSL_LS_BCM_TSN, 6308 (BSL_META_U(unit, 6309 "Write to HW failed(rv = %d)\n"), 6310 rv)); 6311 return rv; 6312 } 6313 prev = hwfid; 6314 } 6315 ctrl_last_fid = hwfid; 6316 6317 /* Set the config to HW */ 6318 rv = al_dev_info->flow_id_ctrl_set( 6319 unit, 6320 flow_type, 6321 ctrl_current_fid, 6322 ctrl_last_fid, 6323 ctrl_id_size[flow_type]); 6324 6325 if (BCM_FAILURE(rv)) { 6326 bcmi_esw_tsn_sr_auto_learn_free_flowset( 6327 unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE); 6328 AUTO_LEARN_BK_UNLOCK(unit); 6329 AUTO_LEARN_UNLOCK(unit); 6330 LOG_ERROR(BSL_LS_BCM_TSN, 6331 (BSL_META_U(unit, 6332 "Write to HW failed(rv = %d)\n"), 6333 rv)); 6334 return rv; 6335 } 6336 } 6337 } 6338 6339 /* Turn ON / OFF HW learning */ 6340 rv = al_dev_info->enable(unit, enable); 6341 if (BCM_FAILURE(rv)) { 6342 bcmi_esw_tsn_sr_auto_learn_free_flowset( 6343 unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE); 6344 AUTO_LEARN_BK_UNLOCK(unit); 6345 AUTO_LEARN_UNLOCK(unit); 6346 LOG_ERROR(BSL_LS_BCM_TSN, 6347 (BSL_META_U(unit, 6348 "Write to HW failed(rv = %d)\n"), 6349 rv)); 6350 return rv; 6351 } 6352 6353 bk_data->enabled = enable; 6354 if (TRUE == enable) { 6355 sal_memcpy(&(bk_data->config), 6356 config, 6357 sizeof(bcm_tsn_sr_auto_learn_config_t)); 6358 } else { 6359 /* Clear the config when disable */ 6360 bcm_tsn_sr_auto_learn_config_t_init(&(bk_data->config)); 6361 bcmi_esw_tsn_sr_auto_learn_free_flowset( 6362 unit, bk_data->flowsets, bk_data->flowsets_cnt, TRUE); 6363 } 6364 6365 AUTO_LEARN_BK_UNLOCK(unit); 6366 AUTO_LEARN_UNLOCK(unit); 6367 6368 bcmi_esw_tsn_sr_auto_learn_config_dump( 6369 unit, "SW bk config", &(bk_data->config)); 6370 6371 rv = BCM_E_NONE; 6372 #endif /* BCM_TSN_SR_SUPPORT */ 6373 TSN_FUNCTION_TRACE(unit, "OUT"); 6374 return rv; 6375 } 6376 6377 /* 6378 * Function: 6379 * bcmi_esw_tsn_sr_auto_learn_enable_get 6380 * Purpose: 6381 * Get enable/disable SR flow auto learn subsystem 6382 * Parameters: 6383 * unit - (IN) Unit number 6384 * enable - (OUT) Enable/disable 6385 * config - (OUT) Auto Learn configuration 6386 * Returns: 6387 * BCM_E_xxx 6388 */ 6389 STATIC int 6390 bcmi_esw_tsn_sr_auto_learn_enable_get( 6391 int unit, 6392 int *enabled, 6393 bcm_tsn_sr_auto_learn_config_t *config) 6394 { 6395 bcm_error_t rv = BCM_E_UNAVAIL; 6396 #if defined(BCM_TSN_SR_SUPPORT) 6397 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 6398 bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL; 6399 bcmi_esw_tsn_sr_auto_learn_bk_data_t *bk_data = NULL; 6400 6401 TSN_FUNCTION_TRACE(unit, "IN"); 6402 6403 /* Parameter NULL error handling */ 6404 if ((NULL == enabled) || (NULL == config)) { 6405 return BCM_E_PARAM; 6406 } 6407 6408 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 6409 6410 /* Initialization check */ 6411 AUTO_LEARN_INIT(unit); 6412 6413 /* auto learn bk info */ 6414 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 6415 6416 /* Get enabled from SW BK */ 6417 bk_data = &(al_bk_info->data); 6418 *enabled = bk_data->enabled; 6419 6420 /* If it's enabled, copy bcm_tsn_sr_auto_learn_config_t */ 6421 if (*enabled) { 6422 sal_memcpy(config, 6423 &(bk_data->config), 6424 sizeof(bcm_tsn_sr_auto_learn_config_t)); 6425 6426 bcmi_esw_tsn_sr_auto_learn_config_dump( 6427 unit, "auto_learn_enable_get", config); 6428 } else { 6429 LOG_WARN(BSL_LS_BCM_TSN, 6430 (BSL_META_U(unit, 6431 "SR flow auto learn subsystem isn't enabled\n"))); 6432 } 6433 6434 rv = BCM_E_NONE; 6435 #endif /* BCM_TSN_SR_SUPPORT */ 6436 TSN_FUNCTION_TRACE(unit, "OUT"); 6437 return rv; 6438 } 6439 6440 #if defined(BCM_WARM_BOOT_SUPPORT) 6441 /* Auto Learn management - warmboot scache size allocation */ 6442 STATIC int 6443 bcmi_esw_tsn_sr_auto_learn_wb_alloc(int unit) 6444 { 6445 bcm_error_t rv = BCM_E_UNAVAIL; 6446 soc_scache_handle_t scache_handle; 6447 uint8 *auto_learn_scache = NULL; 6448 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 6449 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 6450 const tsn_sr_auto_learn_info_t *al_dev_info = NULL; 6451 tsn_sr_flows_bookkeeping_t *flow_bkinfo; 6452 uint32 table_size; 6453 int data_size = 0, group_data_size = 0; 6454 6455 TSN_FUNCTION_TRACE(unit, "IN"); 6456 6457 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 6458 6459 /* 1. Size of bcmi_esw_tsn_sr_auto_learn_bk_t.initialized */ 6460 data_size = sizeof(int); 6461 6462 /* Initialization check */ 6463 AUTO_LEARN_DEV_INIT(unit); 6464 6465 /* auto learn device info */ 6466 dev_info = bk_info->tsn_dev_info; 6467 al_dev_info = dev_info->tsn_sr_auto_learn_info; 6468 6469 rv = al_dev_info->table_size_get(unit, &table_size); 6470 BCM_IF_ERROR_RETURN(rv); 6471 assert(table_size > 0); 6472 6473 /* 2. Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.intf_bitmap */ 6474 data_size += SHR_BITALLOCSIZE(table_size); 6475 6476 /* 3. Size of bcmi_esw_tsn_sr_auto_learn_bk_t.group_data */ 6477 group_data_size = 6478 sizeof(bcmi_esw_tsn_sr_auto_learn_group_bk_data_t) * table_size; 6479 data_size += group_data_size; 6480 6481 /* 4. Size of bcmi_esw_tsn_sr_auto_learn_bk_t.data */ 6482 flow_bkinfo = &tsn_bk_info[unit]->sr_flows; 6483 data_size += sizeof(uint32) * 2; /* flowsets_cnt */ 6484 data_size += /* Rx flowsets */ 6485 flow_bkinfo->max_flows[SR_FLOW_DIR_RX] * sizeof(bcm_tsn_sr_flowset_t); 6486 data_size += /* Tx flowsets */ 6487 flow_bkinfo->max_flows[SR_FLOW_DIR_TX] * sizeof(bcm_tsn_sr_flowset_t); 6488 6489 SOC_SCACHE_HANDLE_SET(scache_handle, 6490 unit, 6491 BCM_MODULE_TSN, 6492 BCM_TSN_WB_SCACHE_PART_AUTO_LEARN); 6493 6494 rv = _bcm_esw_scache_ptr_get( 6495 unit, scache_handle, TRUE, data_size, 6496 &auto_learn_scache, BCM_TSN_WB_DEFAULT_VERSION, NULL); 6497 6498 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 6499 LOG_VERBOSE(BSL_LS_BCM_TSN, 6500 (BSL_META_U(unit, 6501 "Auto Learn SCACHE Memory not available\n"))); 6502 return rv; 6503 } 6504 TSN_FUNCTION_TRACE(unit, "OUT"); 6505 return BCM_E_NONE; 6506 } 6507 6508 /* 6509 * Function: 6510 * bcmi_esw_tsn_sr_auto_learn_sync 6511 * Purpose: 6512 * Record bcmi_esw_tsn_sr_auto_learn_group_bk_data_t for Warm Boot 6513 * Parameters: 6514 * unit - (IN) Unit number 6515 * Returns: 6516 * BCM_E_NONE - Success. 6517 */ 6518 STATIC int 6519 bcmi_esw_tsn_sr_auto_learn_sync(int unit) 6520 { 6521 bcm_error_t rv = BCM_E_UNAVAIL; 6522 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 6523 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 6524 const tsn_sr_auto_learn_info_t *al_dev_info = NULL; 6525 bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL; 6526 bcmi_esw_tsn_sr_auto_learn_bk_data_t *bk_data = NULL; 6527 bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *bk_group_data; 6528 uint32 table_size; 6529 int data_size = 0, group_data_size = 0; 6530 uint8 *auto_learn_scache = NULL; 6531 soc_scache_handle_t scache_handle; 6532 6533 TSN_FUNCTION_TRACE(unit, "IN"); 6534 6535 SOC_SCACHE_HANDLE_SET(scache_handle, 6536 unit, 6537 BCM_MODULE_TSN, 6538 BCM_TSN_WB_SCACHE_PART_AUTO_LEARN); 6539 6540 BCM_IF_ERROR_RETURN( 6541 _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 6542 &auto_learn_scache, BCM_TSN_WB_DEFAULT_VERSION, NULL)); 6543 6544 if (NULL == auto_learn_scache) { 6545 LOG_VERBOSE(BSL_LS_BCM_TSN, 6546 (BSL_META_U(unit, 6547 "Auto Learn SCACHE Memory not available\n"))); 6548 return BCM_E_MEMORY; 6549 } 6550 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 6551 6552 /* auto learn bk info */ 6553 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 6554 6555 /* 1. Sync bcmi_esw_tsn_sr_auto_learn_bk_t.initialized */ 6556 AUTO_LEARN_BK_LOCK(unit); 6557 data_size = sizeof(int); 6558 sal_memcpy(auto_learn_scache, &(al_bk_info->initialized), data_size); 6559 auto_learn_scache += data_size; 6560 AUTO_LEARN_BK_UNLOCK(unit); 6561 6562 if (TRUE == al_bk_info->initialized) { 6563 /* Initialization check */ 6564 AUTO_LEARN_INIT(unit); 6565 6566 /* auto learn device info */ 6567 dev_info = bk_info->tsn_dev_info; 6568 al_dev_info = dev_info->tsn_sr_auto_learn_info; 6569 6570 /* Set SW bookkeeping database pointers */ 6571 bk_group_data = al_bk_info->group_data; 6572 bk_data = &(al_bk_info->data); 6573 6574 rv = al_dev_info->table_size_get(unit, &table_size); 6575 BCM_IF_ERROR_RETURN(rv); 6576 assert(table_size > 0); 6577 group_data_size = 6578 sizeof(bcmi_esw_tsn_sr_auto_learn_group_bk_data_t) * table_size; 6579 6580 AUTO_LEARN_BK_LOCK(unit); 6581 /* 2. Sync bcmi_esw_tsn_sr_auto_learn_bk_t.intf_bitmap */ 6582 data_size = SHR_BITALLOCSIZE(table_size); 6583 sal_memcpy(auto_learn_scache, al_bk_info->intf_bitmap, data_size); 6584 auto_learn_scache += data_size; 6585 6586 /* 3. Sync bcmi_esw_tsn_sr_auto_learn_bk_t.group_data */ 6587 data_size = group_data_size; 6588 sal_memcpy(auto_learn_scache, bk_group_data, data_size); 6589 auto_learn_scache += data_size; 6590 AUTO_LEARN_BK_UNLOCK(unit); 6591 6592 if (TRUE == bk_data->enabled) { 6593 /* 4. Sync bcmi_esw_tsn_sr_auto_learn_bk_t.data */ 6594 6595 /* flowset_cnt */ 6596 AUTO_LEARN_BK_LOCK(unit); 6597 data_size = sizeof(uint32); 6598 sal_memcpy(auto_learn_scache, 6599 &(bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_tx]), 6600 data_size); 6601 auto_learn_scache += data_size; 6602 6603 data_size = sizeof(uint32); 6604 sal_memcpy(auto_learn_scache, 6605 &(bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_rx]), 6606 data_size); 6607 auto_learn_scache += data_size; 6608 6609 /* Tx flowsets */ 6610 data_size = 6611 bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_tx] * 6612 sizeof(bcm_tsn_sr_flowset_t); 6613 sal_memcpy(auto_learn_scache, 6614 bk_data->flowsets[bcmi_sr_auto_learn_flow_tx], 6615 data_size); 6616 auto_learn_scache += data_size; 6617 6618 /* Rx flowsets */ 6619 data_size = 6620 bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_rx] * 6621 sizeof(bcm_tsn_sr_flowset_t); 6622 sal_memcpy(auto_learn_scache, 6623 bk_data->flowsets[bcmi_sr_auto_learn_flow_rx], 6624 data_size); 6625 auto_learn_scache += data_size; 6626 AUTO_LEARN_BK_UNLOCK(unit); 6627 } 6628 } 6629 6630 TSN_FUNCTION_TRACE(unit, "OUT"); 6631 return BCM_E_NONE; 6632 } 6633 6634 /* 6635 * Function: 6636 * bcmi_esw_tsn_sr_auto_learn_reload 6637 * Purpose: 6638 * Re-initialize the Auto Learn resource. Restore bookkeeping information. 6639 * Parameters: 6640 * unit - (IN) Unit number 6641 * Returns: 6642 * BCM_E_NONE - Success. Warm boot successfully 6643 */ 6644 STATIC int 6645 bcmi_esw_tsn_sr_auto_learn_reload(int unit) 6646 { 6647 bcm_error_t rv = BCM_E_UNAVAIL; 6648 int enabled; 6649 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 6650 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 6651 const tsn_sr_auto_learn_info_t *al_dev_info = NULL; 6652 bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL; 6653 bcmi_esw_tsn_sr_auto_learn_bk_data_t *bk_data = NULL; 6654 bcmi_esw_tsn_sr_mac_proxy_bk_info_t *mp_bk_info = NULL; 6655 bcmi_esw_tsn_sr_mac_proxy_entry_t *mp_entries = NULL; 6656 bcmi_tsn_sr_auto_learn_flow_t flow_type; 6657 bcm_tsn_sr_flowset_t flowset; 6658 uint32 fid; 6659 bcmi_esw_tsn_sr_auto_learn_group_bk_data_t *bk_group_data; 6660 uint32 table_size; 6661 int data_size = 0; 6662 uint8 *auto_learn_scache = NULL; 6663 soc_scache_handle_t scache_handle; 6664 int i; 6665 bcmi_tsn_sr_auto_learn_group_port_type_t group_ports_type; 6666 int pro_idx = BCMI_SR_AUTO_LEARN_MPP_IDX_INVALID; 6667 6668 TSN_FUNCTION_TRACE(unit, "IN"); 6669 6670 SOC_SCACHE_HANDLE_SET(scache_handle, 6671 unit, 6672 BCM_MODULE_TSN, 6673 BCM_TSN_WB_SCACHE_PART_AUTO_LEARN); 6674 6675 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 6676 &auto_learn_scache, BCM_TSN_WB_DEFAULT_VERSION, NULL); 6677 if (rv == BCM_E_NOT_FOUND) { 6678 /* Proceed with level 1 warmboot */ 6679 return BCM_E_NONE; 6680 } 6681 6682 if (NULL == auto_learn_scache) { 6683 LOG_VERBOSE(BSL_LS_BCM_TSN, 6684 (BSL_META_U(unit, 6685 "SCACHE Memory not available \n"))); 6686 return BCM_E_MEMORY; 6687 } 6688 6689 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 6690 6691 /* auto learn device info */ 6692 dev_info = bk_info->tsn_dev_info; 6693 al_dev_info = dev_info->tsn_sr_auto_learn_info; 6694 6695 /* Check if the chip specific function existed */ 6696 TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->table_size_get); 6697 TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->enable_get); 6698 TSN_CHECK_NULL_DEV_INSTANCE(unit, al_dev_info->flow_id_ctrl_get); 6699 6700 /* auto learn bk info */ 6701 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 6702 6703 /* 1. Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.initialized */ 6704 AUTO_LEARN_BK_LOCK(unit); 6705 data_size = sizeof(int); 6706 sal_memcpy(&(al_bk_info->initialized), auto_learn_scache, data_size); 6707 auto_learn_scache += data_size; 6708 AUTO_LEARN_BK_UNLOCK(unit); 6709 6710 if (FALSE == al_bk_info->initialized) { 6711 /* 1st initialization hasn't been triggered */ 6712 TSN_FUNCTION_TRACE(unit, "OUT : not initialized"); 6713 return BCM_E_NONE; 6714 } 6715 6716 /* Force to re-init again */ 6717 al_bk_info->initialized = FALSE; 6718 6719 /* SR Auto Learn management initialization */ 6720 rv = bcmi_esw_tsn_sr_auto_learn_lazy_init(unit); 6721 if (BCM_FAILURE(rv)) { 6722 bcmi_esw_tsn_sr_auto_learn_cleanup(unit); 6723 return (rv); 6724 } 6725 6726 /* Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.group_data : Start */ 6727 rv = al_dev_info->table_size_get(unit, &table_size); 6728 BCM_IF_ERROR_RETURN(rv); 6729 assert(table_size > 0); 6730 6731 /* Set SW bookkeeping database pointers */ 6732 bk_data = &(al_bk_info->data); 6733 bk_group_data = al_bk_info->group_data; 6734 6735 6736 AUTO_LEARN_BK_LOCK(unit); 6737 6738 /* 2. Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.intf_bitmap */ 6739 data_size = SHR_BITALLOCSIZE(table_size); 6740 sal_memcpy(al_bk_info->intf_bitmap, auto_learn_scache, data_size); 6741 auto_learn_scache += data_size; 6742 6743 /* Calculate the cnt/start/end */ 6744 al_bk_info->valid_count = 0; 6745 al_bk_info->valid_sw_idx_start = 0; 6746 al_bk_info->valid_sw_idx_end = 0; 6747 al_bk_info->empty_sw_idx_start = 0; 6748 al_bk_info->empty_sw_idx_end = 0; 6749 6750 for (i = 0; i < table_size; i++) { 6751 if (AUTO_LEARN_INTF_USED_GET(unit, i)) { 6752 al_bk_info->valid_count++; 6753 } 6754 6755 if (AUTO_LEARN_INTF_USED_GET(unit, i) && 6756 !AUTO_LEARN_INTF_USED_GET(unit, al_bk_info->valid_sw_idx_start)) { 6757 al_bk_info->valid_sw_idx_start = i; 6758 } 6759 6760 if (AUTO_LEARN_INTF_USED_GET(unit, i) && 6761 al_bk_info->valid_sw_idx_end < i) { 6762 al_bk_info->valid_sw_idx_end = i; 6763 } 6764 6765 if (!AUTO_LEARN_INTF_USED_GET(unit, i) && 6766 AUTO_LEARN_INTF_USED_GET(unit, al_bk_info->empty_sw_idx_start)) { 6767 al_bk_info->empty_sw_idx_start = i; 6768 } 6769 6770 if (!AUTO_LEARN_INTF_USED_GET(unit, i) && 6771 al_bk_info->empty_sw_idx_end < i) { 6772 al_bk_info->empty_sw_idx_end = i; 6773 } 6774 } 6775 6776 /* 3. Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.group_data */ 6777 data_size = 6778 sizeof(bcmi_esw_tsn_sr_auto_learn_group_bk_data_t) * table_size; 6779 sal_memcpy(bk_group_data, auto_learn_scache, data_size); 6780 auto_learn_scache += data_size; 6781 AUTO_LEARN_BK_UNLOCK(unit); 6782 6783 /* Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.group_data : End */ 6784 6785 /* Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.data : Start */ 6786 6787 rv = al_dev_info->enable_get(unit, &enabled); 6788 if (BCM_FAILURE(rv)) { 6789 LOG_ERROR(BSL_LS_BCM_TSN, 6790 (BSL_META_U(unit, 6791 "Read from HW failed(rv = %d)\n"), 6792 rv)); 6793 return rv; 6794 } 6795 AUTO_LEARN_BK_LOCK(unit); 6796 bk_data->enabled = enabled; 6797 AUTO_LEARN_BK_UNLOCK(unit); 6798 6799 if (TRUE == bk_data->enabled) { 6800 /* 3. Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.data */ 6801 AUTO_LEARN_BK_LOCK(unit); 6802 data_size = sizeof(uint32); 6803 sal_memcpy(&(bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_tx]), 6804 auto_learn_scache, data_size); 6805 auto_learn_scache += data_size; 6806 6807 data_size = sizeof(uint32); 6808 sal_memcpy(&(bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_rx]), 6809 auto_learn_scache, data_size); 6810 auto_learn_scache += data_size; 6811 AUTO_LEARN_BK_UNLOCK(unit); 6812 6813 bcm_tsn_sr_auto_learn_config_t_init(&(bk_data->config)); 6814 6815 AUTO_LEARN_BK_LOCK(unit); 6816 bk_data->config.num_tx_flows = 6817 bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_tx]; 6818 bk_data->config.num_rx_flows = 6819 bk_data->flowsets_cnt[bcmi_sr_auto_learn_flow_rx]; 6820 AUTO_LEARN_BK_UNLOCK(unit); 6821 6822 for (flow_type = bcmi_sr_auto_learn_flow_tx; 6823 flow_type <= bcmi_sr_auto_learn_flow_rx; 6824 flow_type++) { 6825 6826 AUTO_LEARN_BK_LOCK(unit); 6827 data_size = 6828 bk_data->flowsets_cnt[flow_type] * 6829 sizeof(bcm_tsn_sr_flowset_t); 6830 TSN_ALLOC( 6831 unit, bk_data->flowsets[flow_type], bcm_tsn_sr_flowset_t, 6832 data_size, "bk record Rx/Tx Flowset", 0, rv); 6833 if (BCM_FAILURE(rv)) { 6834 AUTO_LEARN_BK_UNLOCK(unit); 6835 LOG_VERBOSE(BSL_LS_BCM_TSN, 6836 (BSL_META_U(unit, 6837 "bcmi_esw_tsn_sr_auto_learn_reload: " 6838 "failed to allocate memory\n"))); 6839 return rv; 6840 } 6841 sal_memcpy(bk_data->flowsets[flow_type], auto_learn_scache, 6842 data_size); 6843 auto_learn_scache += data_size; 6844 6845 /* Take the 1st one for retrieving default flow config */ 6846 flowset = bk_data->flowsets[flow_type][0]; 6847 6848 /* Get the flow_id from created flowset */ 6849 rv = bcm_esw_tsn_sr_flowset_flow_get( 6850 unit, flowset, 0, &fid); 6851 6852 /* Get tx/rx_flow_config & num_tx/rx_flows */ 6853 if (bcmi_sr_auto_learn_flow_tx == flow_type) { 6854 /* Get flow config with given software SR flow ID */ 6855 rv = bcm_esw_tsn_sr_tx_flow_config_get(unit, 6856 fid, &(bk_data->config.tx_flow_config)); 6857 if (BCM_FAILURE(rv)) { 6858 bcmi_esw_tsn_sr_auto_learn_free_flowset( 6859 unit, bk_data->flowsets, bk_data->flowsets_cnt, FALSE); 6860 bcm_tsn_sr_auto_learn_config_t_init(&(bk_data->config)); 6861 AUTO_LEARN_BK_UNLOCK(unit); 6862 return rv; 6863 } 6864 } else if (bcmi_sr_auto_learn_flow_rx == flow_type) { 6865 /* Get flow config with given software SR flow ID */ 6866 rv = bcm_esw_tsn_sr_rx_flow_config_get(unit, 6867 fid, &(bk_data->config.rx_flow_config)); 6868 if (BCM_FAILURE(rv)) { 6869 bcmi_esw_tsn_sr_auto_learn_free_flowset( 6870 unit, bk_data->flowsets, bk_data->flowsets_cnt, FALSE); 6871 bcm_tsn_sr_auto_learn_config_t_init(&(bk_data->config)); 6872 AUTO_LEARN_BK_UNLOCK(unit); 6873 return rv; 6874 } 6875 } 6876 AUTO_LEARN_BK_UNLOCK(unit); 6877 } 6878 6879 } 6880 /* Recovery bcmi_esw_tsn_sr_auto_learn_bk_t.data : End */ 6881 6882 /* Refresh MAC proxy ref_count for auto learn group usage */ 6883 /* SR MAC Proxy bk info */ 6884 mp_bk_info = &(bk_info->tsn_sr_mac_proxy_bk_info); 6885 mp_entries = mp_bk_info->sr_mp_entry; 6886 if (mp_entries == NULL) { 6887 return BCM_E_UNAVAIL; 6888 } 6889 6890 SR_MAC_PROXY_LOCK(mp_bk_info); 6891 for (i = 0; i < table_size; i++) { 6892 if (AUTO_LEARN_INTF_USED_GET(unit, i)) { 6893 bk_group_data = &(al_bk_info->group_data[i]); 6894 6895 /* Update ref_count for interlink ports */ 6896 pro_idx = bk_group_data->interlink_pro_idx; 6897 mp_entries[pro_idx].ref_count++; 6898 6899 /* Update ref_count for redundant ports */ 6900 group_ports_type = bcmi_sr_auto_learn_group_macp; 6901 pro_idx = bk_group_data->redundant_pro_idx[group_ports_type]; 6902 mp_entries[pro_idx].ref_count++; 6903 } 6904 } 6905 SR_MAC_PROXY_UNLOCK(mp_bk_info); 6906 6907 TSN_FUNCTION_TRACE(unit, "OUT"); 6908 return BCM_E_NONE; 6909 } 6910 #endif /* BCM_WARM_BOOT_SUPPORT */ 6911 6912 6913 /* 6914 * Function: 6915 * bcmi_esw_tsn_sr_auto_learn_cleanup 6916 * Purpose: 6917 * Internal function to clear the resource of the TSN module. 6918 * Parameters: 6919 * unit - (IN) unit number 6920 * Returns: 6921 * BCM_E_XXX 6922 */ 6923 STATIC int 6924 bcmi_esw_tsn_sr_auto_learn_cleanup(int unit) 6925 { 6926 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 6927 bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL; 6928 bcmi_esw_tsn_sr_auto_learn_bk_data_t *bk_data = NULL; 6929 6930 LOG_VERBOSE(BSL_LS_BCM_TSN, 6931 (BSL_META_U(unit, 6932 "bcmi_esw_tsn_bk_info_cleanup\n"))); 6933 6934 BCM_IF_ERROR_RETURN( 6935 tsn_bk_info_instance_get(unit, &bk_info)); 6936 6937 /* Free and clear the SR Auto Learn bookkeeping info structure */ 6938 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 6939 6940 if (NULL != al_bk_info->intf_bitmap) { 6941 TSN_FREE(unit, al_bk_info->intf_bitmap, 0); 6942 al_bk_info->intf_bitmap = NULL; 6943 } 6944 if (NULL != al_bk_info->group_data) { 6945 TSN_FREE(unit, al_bk_info->group_data, 0); 6946 al_bk_info->group_data = NULL; 6947 } 6948 6949 bk_data = &(al_bk_info->data); 6950 6951 bcmi_esw_tsn_sr_auto_learn_free_flowset( 6952 unit, bk_data->flowsets, bk_data->flowsets_cnt, FALSE); 6953 6954 /* Reset to default setting */ 6955 al_bk_info->valid_count = 0; 6956 al_bk_info->valid_sw_idx_start = 0; 6957 al_bk_info->valid_sw_idx_end = 0; 6958 al_bk_info->empty_sw_idx_start = 0; 6959 al_bk_info->empty_sw_idx_end = 0; 6960 6961 if (al_bk_info->mutex != NULL) { 6962 sal_mutex_destroy(al_bk_info->mutex); 6963 al_bk_info->mutex = NULL; 6964 } 6965 6966 if (al_bk_info->bk_mutex != NULL) { 6967 sal_mutex_destroy(al_bk_info->bk_mutex); 6968 al_bk_info->bk_mutex = NULL; 6969 } 6970 6971 al_bk_info->initialized = FALSE; 6972 return BCM_E_NONE; 6973 } 6974 6975 /* 6976 * Function: 6977 * bcmi_esw_tsn_sr_auto_learn_init 6978 * Purpose: 6979 * create a default profile setting 6980 * Parameters: 6981 * unit - (IN) Unit number 6982 * Returns: 6983 * BCM_E_xxx 6984 */ 6985 STATIC int 6986 bcmi_esw_tsn_sr_auto_learn_init(int unit) 6987 { 6988 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 6989 bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL; 6990 6991 TSN_FUNCTION_TRACE(unit, "IN"); 6992 6993 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 6994 6995 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 6996 6997 /* Create mutex */ 6998 al_bk_info->mutex = sal_mutex_create("auto_learn_mutex"); 6999 if (al_bk_info->mutex == NULL) { 7000 return BCM_E_MEMORY; 7001 } 7002 7003 /* Create mutex */ 7004 al_bk_info->bk_mutex = sal_mutex_create("auto_learn_bk_mutex"); 7005 if (al_bk_info->bk_mutex == NULL) { 7006 return BCM_E_MEMORY; 7007 } 7008 7009 al_bk_info->initialized = FALSE; 7010 7011 TSN_FUNCTION_TRACE(unit, "OUT"); 7012 return BCM_E_NONE; 7013 } 7014 7015 /* 7016 * Function: 7017 * bcmi_esw_tsn_sr_auto_learn_lazy_init 7018 * Purpose: 7019 * create a default profile setting 7020 * Parameters: 7021 * unit - (IN) Unit number 7022 * Returns: 7023 * BCM_E_xxx 7024 */ 7025 STATIC int 7026 bcmi_esw_tsn_sr_auto_learn_lazy_init(int unit) 7027 { 7028 bcm_error_t rv = BCM_E_NONE; 7029 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 7030 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 7031 const tsn_sr_auto_learn_info_t *al_dev_info = NULL; 7032 bcmi_esw_tsn_sr_auto_learn_bk_t *al_bk_info = NULL; 7033 uint32 table_size, shr_bitdcl_size, bk_data_size; 7034 char *table_name; 7035 int i; 7036 7037 TSN_FUNCTION_TRACE(unit, "IN"); 7038 7039 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 7040 7041 dev_info = bk_info->tsn_dev_info; 7042 al_dev_info = dev_info->tsn_sr_auto_learn_info; 7043 al_bk_info = &(bk_info->tsn_sr_auto_learn_bk_info); 7044 7045 /* 7046 * Lazy initialization, 7047 * 1st initializ should be performed in auto_learn_group_create 7048 */ 7049 if (TRUE == al_bk_info->initialized) { 7050 /* 1st initialization has been triggered */ 7051 TSN_FUNCTION_TRACE(unit, "OUT : initialized"); 7052 return BCM_E_NONE; 7053 } 7054 7055 /* Check chip device info instance is valid or not */ 7056 if (NULL == al_dev_info) { 7057 return BCM_E_UNAVAIL; 7058 } 7059 7060 table_name = al_dev_info->table_name; 7061 rv = al_dev_info->table_size_get(unit, &table_size); 7062 BCM_IF_ERROR_RETURN(rv); 7063 /* table_size should large than 0 */ 7064 assert(table_size > 0); 7065 7066 /* Allocate usage bitmap */ 7067 shr_bitdcl_size = SHR_BITALLOCSIZE(table_size); 7068 TSN_ALLOC(unit, al_bk_info->intf_bitmap, SHR_BITDCL, 7069 shr_bitdcl_size, 7070 "SR Auto Learn bookkeeping intf_bitmap", 0, rv); 7071 if (BCM_FAILURE(rv)) { 7072 LOG_VERBOSE(BSL_LS_BCM_TSN, 7073 (BSL_META_U(unit, 7074 "bcmi_esw_tsn_init: failed to " 7075 "allocate memory\n"))); 7076 return rv; 7077 } 7078 sal_memset(al_bk_info->intf_bitmap, 0, shr_bitdcl_size); 7079 7080 /* Allocate bcmi_esw_tsn_sr_auto_learn_group_bk_data_t */ 7081 bk_data_size = 7082 sizeof(bcmi_esw_tsn_sr_auto_learn_group_bk_data_t) * table_size; 7083 TSN_ALLOC(unit, al_bk_info->group_data, 7084 bcmi_esw_tsn_sr_auto_learn_group_bk_data_t, 7085 bk_data_size, 7086 table_name, 0, rv); 7087 if (BCM_FAILURE(rv)) { 7088 LOG_VERBOSE(BSL_LS_BCM_TSN, 7089 (BSL_META_U(unit, 7090 "bcmi_esw_tsn_init: failed to " 7091 "allocate memory\n"))); 7092 return rv; 7093 } 7094 sal_memset(al_bk_info->group_data, 0, bk_data_size); 7095 7096 /* Initialize default value */ 7097 for (i = 0; i < table_size; i++) { 7098 al_bk_info->group_data[i].group_id = 7099 BCMI_SR_AUTO_LEARN_GROUP_ID_INVALID; 7100 } 7101 7102 /* Initialize default valid & empty pointer */ 7103 al_bk_info->valid_count = 0; 7104 al_bk_info->valid_sw_idx_start = 0; 7105 al_bk_info->valid_sw_idx_end = 0; 7106 al_bk_info->empty_sw_idx_start = 0; 7107 al_bk_info->empty_sw_idx_end = table_size - 1; 7108 7109 al_bk_info->data.enabled = FALSE; 7110 bcm_tsn_sr_auto_learn_config_t_init(&(al_bk_info->data.config)); 7111 7112 /* For Lazy initialization */ 7113 al_bk_info->initialized = TRUE; 7114 7115 /* Clear HW status if there is no valid one.*/ 7116 if (0 == al_bk_info->valid_count) { 7117 rv = bcmi_esw_tsn_sr_auto_learn_hw_delete_all(unit); 7118 if (BCM_FAILURE(rv)) { 7119 LOG_ERROR(BSL_LS_BCM_TSN, 7120 (BSL_META_U(unit, 7121 "Delete all HW resource failed(rv = %d)\n"), 7122 rv)); 7123 return rv; 7124 } 7125 } 7126 7127 TSN_FUNCTION_TRACE(unit, "OUT"); 7128 return BCM_E_NONE; 7129 } 7130 7131 /* 7132 * Function: 7133 * bcmi_esw_tsn_sr_port_config_set 7134 * Purpose: 7135 * Set SR configuration on a port 7136 * Parameters: 7137 * unit - (IN) unit number 7138 * port - (IN) port to configure 7139 * config - (IN) port SR configuration 7140 * Returns: 7141 * BCM_E_XXX 7142 * Notes: 7143 */ 7144 STATIC int 7145 bcmi_esw_tsn_sr_port_config_set( 7146 int unit, 7147 bcm_gport_t port, 7148 bcm_tsn_sr_port_config_t *config) 7149 { 7150 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 7151 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 7152 const tsn_sr_port_dev_info_t *sr_port_config = NULL; 7153 7154 if (config == NULL) { 7155 return BCM_E_PARAM; 7156 } 7157 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 7158 dev_info = bk_info->tsn_dev_info; 7159 if (dev_info == NULL) { 7160 return BCM_E_UNAVAIL; 7161 } 7162 sr_port_config = dev_info->sr_port_info; 7163 if ((sr_port_config == NULL) || 7164 (sr_port_config->sr_port_config_set == NULL)) { 7165 return BCM_E_UNAVAIL; 7166 } 7167 7168 return sr_port_config->sr_port_config_set(unit, port, config); 7169 } 7170 7171 /* 7172 * Function: 7173 * bcmi_esw_tsn_sr_port_config_get 7174 * Purpose: 7175 * Get SR configuration from a port 7176 * Parameters: 7177 * unit - (IN) unit number 7178 * port - (IN) port 7179 * config - (OUT) port SR configuration 7180 * Returns: 7181 * BCM_E_XXX 7182 * Notes: 7183 */ 7184 STATIC int 7185 bcmi_esw_tsn_sr_port_config_get( 7186 int unit, 7187 bcm_gport_t port, 7188 bcm_tsn_sr_port_config_t *config) 7189 { 7190 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 7191 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 7192 const tsn_sr_port_dev_info_t *sr_port_config = NULL; 7193 7194 if (config == NULL) { 7195 return BCM_E_PARAM; 7196 } 7197 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 7198 dev_info = bk_info->tsn_dev_info; 7199 if (dev_info == NULL) { 7200 return BCM_E_UNAVAIL; 7201 } 7202 sr_port_config = dev_info->sr_port_info; 7203 if ((sr_port_config == NULL) || 7204 (sr_port_config->sr_port_config_get == NULL)) { 7205 return BCM_E_UNAVAIL; 7206 } 7207 7208 return sr_port_config->sr_port_config_get(unit, port, config); 7209 } 7210 7211 #endif /* BCM_TSN_SR_SUPPORT */ 7212 7213 /* 7214 * Function: 7215 * bcmi_esw_tsn_pri_map_dump_config 7216 * Purpose: 7217 * dump the config of priority map 7218 * Parameters: 7219 * unit - (IN) Unit number 7220 * prefix - (IN) Prefix string for dump message 7221 * config - (IN) Priority map config 7222 * Returns: 7223 * none 7224 */ 7225 STATIC void 7226 bcmi_esw_tsn_pri_map_dump_config( 7227 int unit, 7228 char *prefix, 7229 bcm_tsn_pri_map_config_t *config) 7230 { 7231 int i; 7232 uint32 flags; 7233 7234 LOG_VERBOSE(BSL_LS_BCM_TSN, 7235 (BSL_META_U(unit, 7236 "bcmi_esw_tsn_pri_map_dump_config\n"))); 7237 7238 if ((NULL == prefix) || (NULL == config)) { 7239 return; 7240 } 7241 7242 if (bsl_check(bslLayerBcm, bslSourceTsn, bslSeverityDebug, unit)) { 7243 LOG_DEBUG(BSL_LS_BCM_TSN, 7244 (BSL_META_U(unit, 7245 "bcmi_esw_tsn_pri_map_dump_config:\n"))); 7246 LOG_DEBUG(BSL_LS_BCM_TSN, 7247 (BSL_META_U(unit, 7248 "%s map_type %d, num_map_entries %d.\n"), 7249 prefix, 7250 config->map_type, 7251 config->num_map_entries 7252 )); 7253 7254 for (i = 0; i < (config->num_map_entries); i++) { 7255 flags = (config->map_entries[i].flags); 7256 if (flags & BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET) { 7257 LOG_DEBUG(BSL_LS_BCM_TSN, 7258 (BSL_META_U(unit, 7259 "%s map_entries[%d]: flow_offset %d.\n"), 7260 prefix, 7261 i, 7262 config->map_entries[i].flow_offset 7263 )); 7264 } 7265 7266 if (flags & BCM_TSN_PRI_MAP_ENTRY_NEW_INT_PRI) { 7267 LOG_DEBUG(BSL_LS_BCM_TSN, 7268 (BSL_META_U(unit, 7269 "%s map_entries[%d]: new_int_pri %d.\n"), 7270 prefix, 7271 i, 7272 config->map_entries[i].new_int_pri 7273 )); 7274 } 7275 7276 if (flags & BCM_TSN_PRI_MAP_ENTRY_PROFILE_ID) { 7277 LOG_DEBUG(BSL_LS_BCM_TSN, 7278 (BSL_META_U(unit, 7279 "%s map_entries[%d]: profile_id %d.\n"), 7280 prefix, 7281 i, 7282 config->map_entries[i].profile_id 7283 )); 7284 } 7285 } 7286 } 7287 } 7288 7289 /* 7290 * Function: 7291 * bcmi_esw_tsn_pri_map_cmp 7292 * Purpose: 7293 * Check the priority mapping entry is the same or not. 7294 * Parameters: 7295 * unit - (IN) Unit number 7296 * ent1 - (IN) priority mapping entry 1 7297 * ent2 - (IN) priority mapping entry 2 7298 * equal - (OUT) identical flag. 7299 * Returns: 7300 * BCM_E_NONE - Success. 7301 * BCM_E_PARAM - Fail. Wrong parameter 7302 */ 7303 STATIC int 7304 bcmi_esw_tsn_pri_map_cmp( 7305 int unit, 7306 bcm_tsn_pri_map_entry_t *ent1, 7307 bcm_tsn_pri_map_entry_t *ent2, 7308 uint8 *equal) 7309 { 7310 int compare_flow, compare_prof, compare_intp, compare_egate, compare_pgate; 7311 7312 LOG_VERBOSE(BSL_LS_BCM_TSN, 7313 (BSL_META_U(unit, 7314 "bcmi_esw_tsn_pri_map_cmp\n"))); 7315 7316 if ((NULL == ent1) || (NULL == ent2) || 7317 (NULL == equal)) { 7318 return BCM_E_PARAM; 7319 } 7320 7321 *equal = TRUE; 7322 7323 /* If flags are different */ 7324 if (ent1->flags != ent2->flags) { 7325 *equal = FALSE; 7326 return BCM_E_NONE; 7327 } 7328 7329 /* Check which flags need to be compared */ 7330 compare_flow = 7331 (ent1->flags & BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET) ? 7332 TRUE : FALSE; 7333 compare_intp = 7334 (ent1->flags & BCM_TSN_PRI_MAP_ENTRY_PROFILE_ID) ? 7335 TRUE : FALSE; 7336 compare_prof = 7337 (ent1->flags & BCM_TSN_PRI_MAP_ENTRY_NEW_INT_PRI) ? 7338 TRUE : FALSE; 7339 compare_egate = 7340 (ent1->flags & BCM_BCM_TSN_PRI_MAP_ENTRY_TAF_GATE_EXPRESS) ? 7341 TRUE : FALSE; 7342 compare_pgate = 7343 (ent1->flags & BCM_BCM_TSN_PRI_MAP_ENTRY_TAF_GATE_PREEMPT) ? 7344 TRUE : FALSE; 7345 7346 /* If any different found */ 7347 if ((compare_flow && (ent1->flow_offset != ent2->flow_offset)) || 7348 (compare_intp && (ent1->new_int_pri != ent2->new_int_pri)) || 7349 (compare_prof && (ent1->profile_id != ent2->profile_id)) || 7350 (compare_egate && (ent1->taf_gate_express != ent2->taf_gate_express)) || 7351 (compare_pgate && (ent1->taf_gate_preempt != ent2->taf_gate_preempt))) 7352 { 7353 *equal = FALSE; 7354 } 7355 return BCM_E_NONE; 7356 } 7357 7358 /* 7359 * Function: 7360 * bcmi_esw_tsn_pri_map_id_existed_check 7361 * Purpose: 7362 * Check the Priority Map ID exited or not. 7363 * Parameters: 7364 * unit - (IN) Unit number 7365 * map_id - (OUT) Map ID 7366 * Returns: 7367 * BCM_E_xxx 7368 */ 7369 STATIC int 7370 bcmi_esw_tsn_pri_map_id_existed_check( 7371 int unit, 7372 bcm_tsn_pri_map_t map_id) 7373 { 7374 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 7375 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 7376 const tsn_pri_map_info_t *pm_dev_info = NULL; 7377 bcm_tsn_pri_map_type_t map_type; 7378 uint32 sw_idx = MAP_ID_TO_SW_IDX(map_id); 7379 7380 LOG_VERBOSE(BSL_LS_BCM_TSN, 7381 (BSL_META_U(unit, 7382 "bcmi_esw_tsn_pri_map_id_existed_check\n"))); 7383 7384 if (BCM_TSN_PRI_MAP_INVALID == map_id) { 7385 return BCM_E_CONFIG; 7386 } 7387 map_type = PRI_MAP_TYPE_GET(map_id); 7388 7389 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 7390 7391 /* Initialization check */ 7392 PRI_MAP_INIT(unit, map_type); 7393 7394 dev_info = bk_info->tsn_dev_info; 7395 pm_dev_info = dev_info->tsn_pri_map_info[map_type]; 7396 7397 /* Check if the map_id and sw_idx is in the reasonable range */ 7398 assert(pm_dev_info->table_size > 0); 7399 if ((map_type >= bcmTsnPriMapTypeCount) || 7400 (sw_idx >= pm_dev_info->table_size)) { 7401 return BCM_E_PARAM; 7402 } 7403 7404 if (PRI_MAP_INTF_GET(unit, map_type, sw_idx)) { 7405 return BCM_E_NONE; 7406 } 7407 return BCM_E_NOT_FOUND; 7408 } 7409 7410 /* 7411 * Function: 7412 * bcmi_esw_tsn_pri_map_existed_check 7413 * Purpose: 7414 * Check the Priority Map configuration exited or not. 7415 * Parameters: 7416 * unit - (IN) Unit number 7417 * config - (IN) Priority Map configuration 7418 * map_id - (OUT) Map ID 7419 * Returns: 7420 * BCM_E_xxx 7421 */ 7422 STATIC int 7423 bcmi_esw_tsn_pri_map_existed_check( 7424 int unit, 7425 bcm_tsn_pri_map_config_t *config, 7426 bcm_tsn_pri_map_t *map_id) 7427 { 7428 bcm_error_t rv = BCM_E_UNAVAIL; 7429 int ent_idx, is_the_same; 7430 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 7431 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 7432 const tsn_pri_map_info_t *pm_dev_info = NULL; 7433 bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL; 7434 bcmi_esw_tsn_pri_map_bk_info_data_t *bk_data = NULL; 7435 bcm_tsn_pri_map_config_t *bk_config = NULL; 7436 bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount; 7437 uint32 sw_idx; 7438 uint8 equal; 7439 7440 LOG_VERBOSE(BSL_LS_BCM_TSN, 7441 (BSL_META_U(unit, 7442 "bcmi_esw_tsn_pri_map_existed_check\n"))); 7443 7444 if ((NULL == config) || (NULL == map_id)) { 7445 return BCM_E_PARAM; 7446 } 7447 map_type = config->map_type; 7448 7449 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 7450 7451 /* Initialization check */ 7452 PRI_MAP_INIT(unit, map_type); 7453 7454 pm_bk_info = &(bk_info->tsn_pri_map_bk_info); 7455 dev_info = bk_info->tsn_dev_info; 7456 pm_dev_info = dev_info->tsn_pri_map_info[map_type]; 7457 7458 if ((map_type >= bcmTsnPriMapTypeCount) || 7459 (config->num_map_entries == 0) || 7460 (config->num_map_entries > 7461 pm_dev_info->entry_size)) { 7462 return BCM_E_PARAM; 7463 } 7464 7465 PRI_MAP_BK_LOCK(unit); 7466 for (sw_idx = 0; 7467 sw_idx < pm_dev_info->entry_size; 7468 sw_idx++) { 7469 is_the_same = TRUE; 7470 7471 /* Non-used entry, return and continue to check new one */ 7472 if (PRI_MAP_INTF_GET(unit, map_type, sw_idx) == 0) { 7473 continue; 7474 } 7475 7476 bk_data = &(pm_bk_info->data[map_type][sw_idx]); 7477 bk_config = &(bk_data->config); 7478 7479 /* Check if map_type is the same */ 7480 if ((bk_config->num_map_entries == config->num_map_entries)) { 7481 for (ent_idx = 0; ent_idx < (config->num_map_entries); ent_idx++) { 7482 7483 /* Compare two entries if they're the same */ 7484 rv = bcmi_esw_tsn_pri_map_cmp(unit, 7485 &(bk_config->map_entries[ent_idx]), 7486 &(config->map_entries[ent_idx]), 7487 &equal); 7488 if (BCM_FAILURE(rv)) { 7489 PRI_MAP_BK_UNLOCK(unit); 7490 return rv; 7491 } 7492 7493 /* The two entries are different */ 7494 if (FALSE == equal) { 7495 is_the_same = FALSE; 7496 break; 7497 } 7498 } 7499 if (TRUE == is_the_same) { 7500 *map_id = pm_bk_info->data[map_type][sw_idx].map_id; 7501 PRI_MAP_BK_UNLOCK(unit); 7502 return BCM_E_EXISTS; 7503 } 7504 } 7505 } 7506 PRI_MAP_BK_UNLOCK(unit); 7507 return BCM_E_NOT_FOUND; 7508 } 7509 7510 /* 7511 * Function: 7512 * bcmi_esw_tsn_pri_map_hw_index_get 7513 * Purpose: 7514 * Get HW memory base index with given map_id 7515 * Parameters: 7516 * unit - (IN) Unit number 7517 * map_id - (IN) Map ID 7518 * map_type - (OUT) Priority Map Type 7519 * hw_index - (OUT) HW memory base index 7520 * Returns: 7521 * BCM_E_xxx 7522 */ 7523 int 7524 bcmi_esw_tsn_pri_map_hw_index_get( 7525 int unit, 7526 bcm_tsn_pri_map_t map_id, 7527 bcm_tsn_pri_map_type_t *map_type, 7528 uint32 *hw_index) 7529 { 7530 bcm_error_t rv = BCM_E_UNAVAIL; 7531 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 7532 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 7533 const tsn_pri_map_info_t *pm_dev_info = NULL; 7534 uint32 sw_idx = MAP_ID_TO_SW_IDX(map_id); 7535 7536 LOG_VERBOSE(BSL_LS_BCM_TSN, 7537 (BSL_META_U(unit, 7538 "bcmi_esw_tsn_pri_map_hw_index_get\n"))); 7539 7540 /* Parameter NULL error handling */ 7541 if (NULL == hw_index || NULL == map_type) { 7542 return BCM_E_PARAM; 7543 } 7544 7545 /* Check if pri_map id existed */ 7546 rv = bcmi_esw_tsn_pri_map_id_existed_check(unit, map_id); 7547 if (BCM_FAILURE(rv)) { 7548 LOG_WARN(BSL_LS_BCM_TSN, 7549 (BSL_META_U(unit, 7550 "map_id(%d) doesn't exited, rv(%d)\n"), 7551 map_id, 7552 rv)); 7553 return rv; 7554 } 7555 *map_type = PRI_MAP_TYPE_GET(map_id); 7556 7557 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 7558 7559 /* Initialization check */ 7560 PRI_MAP_INIT(unit, *map_type); 7561 7562 dev_info = bk_info->tsn_dev_info; 7563 pm_dev_info = dev_info->tsn_pri_map_info[*map_type]; 7564 if (NULL == pm_dev_info->tsn_pri_map_hw_index_get) { 7565 return BCM_E_UNAVAIL; 7566 } 7567 7568 rv = pm_dev_info->tsn_pri_map_hw_index_get(unit, sw_idx, hw_index); 7569 if (BCM_FAILURE(rv)) { 7570 LOG_ERROR(BSL_LS_BCM_TSN, 7571 (BSL_META_U(unit, 7572 "HW operation failed(rv = %d)\n"), 7573 rv)); 7574 return rv; 7575 } 7576 return BCM_E_NONE; 7577 } 7578 7579 /* 7580 * Function: 7581 * bcmi_esw_tsn_pri_map_map_id_get 7582 * Purpose: 7583 * Get map_id with given HW memory base index 7584 * Parameters: 7585 * unit - (IN) Unit number 7586 * map_type - (IN) Priority Map Type 7587 * hw_index - (IN) HW memory base index 7588 * map_id - (OUT) Map ID 7589 * Returns: 7590 * BCM_E_xxx 7591 */ 7592 int 7593 bcmi_esw_tsn_pri_map_map_id_get( 7594 int unit, 7595 bcm_tsn_pri_map_type_t map_type, 7596 uint32 hw_index, 7597 bcm_tsn_pri_map_t *map_id) 7598 { 7599 bcm_error_t rv = BCM_E_UNAVAIL; 7600 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 7601 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 7602 const tsn_pri_map_info_t *pm_dev_info = NULL; 7603 uint32 sw_idx; 7604 7605 LOG_VERBOSE(BSL_LS_BCM_TSN, 7606 (BSL_META_U(unit, 7607 "bcmi_esw_tsn_pri_map_map_id_get\n"))); 7608 /* Input parameters check. */ 7609 if (NULL == map_id) { 7610 return (BCM_E_PARAM); 7611 } 7612 7613 if (tsn_bk_info[unit] == NULL) { 7614 /* Using device specific info that need no bk_info */ 7615 BCM_IF_ERROR_RETURN(bcmi_esw_tsn_noninit_dev_info_get(unit, &dev_info)); 7616 if (NULL == 7617 dev_info->tsn_pri_map_info[map_type]->tsn_pri_map_sw_idx_get) { 7618 return BCM_E_UNAVAIL; 7619 } 7620 rv = dev_info->tsn_pri_map_info[map_type]->tsn_pri_map_sw_idx_get( 7621 unit, hw_index, &sw_idx); 7622 if (BCM_FAILURE(rv)) { 7623 LOG_ERROR(BSL_LS_BCM_TSN, 7624 (BSL_META_U(unit, 7625 "HW operation failed(rv = %d)\n"), 7626 rv)); 7627 return rv; 7628 } 7629 *map_id = SW_IDX_TO_MAP_ID(sw_idx, map_type); 7630 return BCM_E_NONE; 7631 } 7632 7633 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 7634 /* Initialization check */ 7635 PRI_MAP_INIT(unit, map_type); 7636 7637 dev_info = bk_info->tsn_dev_info; 7638 pm_dev_info = dev_info->tsn_pri_map_info[map_type]; 7639 if (NULL == pm_dev_info->tsn_pri_map_sw_idx_get) { 7640 return BCM_E_UNAVAIL; 7641 } 7642 7643 rv = pm_dev_info->tsn_pri_map_sw_idx_get(unit, hw_index, &sw_idx); 7644 if (BCM_FAILURE(rv)) { 7645 LOG_ERROR(BSL_LS_BCM_TSN, 7646 (BSL_META_U(unit, 7647 "HW operation failed(rv = %d)\n"), 7648 rv)); 7649 return rv; 7650 } 7651 *map_id = SW_IDX_TO_MAP_ID(sw_idx, map_type); 7652 return BCM_E_NONE; 7653 } 7654 7655 /* 7656 * Function: 7657 * bcmi_esw_tsn_pri_map_ref_cnt_dec 7658 * Purpose: 7659 * Decrease reference cnt by 1 with given map_id 7660 * Parameters: 7661 * unit - (IN) Unit number 7662 * map_id - (IN) Map ID 7663 * Returns: 7664 * BCM_E_xxx 7665 */ 7666 int 7667 bcmi_esw_tsn_pri_map_ref_cnt_dec( 7668 int unit, 7669 bcm_tsn_pri_map_t map_id) 7670 { 7671 bcm_error_t rv = BCM_E_UNAVAIL; 7672 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 7673 bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL; 7674 bcmi_esw_tsn_pri_map_bk_info_data_t *bk_data = NULL; 7675 bcm_tsn_pri_map_type_t map_type = PRI_MAP_TYPE_GET(map_id); 7676 uint32 sw_idx = MAP_ID_TO_SW_IDX(map_id); 7677 7678 LOG_VERBOSE(BSL_LS_BCM_TSN, 7679 (BSL_META_U(unit, 7680 "bcmi_esw_tsn_pri_map_ref_cnt_dec\n"))); 7681 7682 /* Check if pri_map id existed */ 7683 rv = bcmi_esw_tsn_pri_map_id_existed_check(unit, map_id); 7684 if (BCM_FAILURE(rv)) { 7685 LOG_WARN(BSL_LS_BCM_TSN, 7686 (BSL_META_U(unit, 7687 "map_id(%d) doesn't exited, rv(%d)\n"), 7688 map_id, 7689 rv)); 7690 return rv; 7691 } 7692 7693 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 7694 7695 /* Initialization check */ 7696 PRI_MAP_INIT(unit, map_type); 7697 7698 pm_bk_info = &(bk_info->tsn_pri_map_bk_info); 7699 7700 PRI_MAP_BK_LOCK(unit); 7701 7702 bk_data = &(pm_bk_info->data[map_type][sw_idx]); 7703 if (bk_data->ref_cnt == 0) { 7704 PRI_MAP_BK_UNLOCK(unit); 7705 return BCM_E_FAIL; 7706 } 7707 bk_data->ref_cnt -= 1; 7708 PRI_MAP_BK_UNLOCK(unit); 7709 return BCM_E_NONE; 7710 } 7711 7712 /* 7713 * Function: 7714 * bcmi_esw_tsn_pri_map_ref_cnt_inc 7715 * Purpose: 7716 * Increase reference cnt by 1 with given map_id 7717 * Parameters: 7718 * unit - (IN) Unit number 7719 * map_id - (IN) Map ID 7720 * Returns: 7721 * BCM_E_xxx 7722 */ 7723 int 7724 bcmi_esw_tsn_pri_map_ref_cnt_inc( 7725 int unit, 7726 bcm_tsn_pri_map_t map_id) 7727 { 7728 bcm_error_t rv = BCM_E_UNAVAIL; 7729 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 7730 bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL; 7731 bcmi_esw_tsn_pri_map_bk_info_data_t *bk_data = NULL; 7732 bcm_tsn_pri_map_type_t map_type = PRI_MAP_TYPE_GET(map_id); 7733 uint32 sw_idx = MAP_ID_TO_SW_IDX(map_id); 7734 7735 LOG_VERBOSE(BSL_LS_BCM_TSN, 7736 (BSL_META_U(unit, 7737 "bcmi_esw_tsn_pri_map_ref_cnt_inc\n"))); 7738 7739 /* Check if pri_map id existed */ 7740 rv = bcmi_esw_tsn_pri_map_id_existed_check(unit, map_id); 7741 if (BCM_FAILURE(rv)) { 7742 LOG_WARN(BSL_LS_BCM_TSN, 7743 (BSL_META_U(unit, 7744 "map_id(%d) doesn't exited, rv(%d)\n"), 7745 map_id, 7746 rv)); 7747 return rv; 7748 } 7749 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 7750 7751 /* Initialization check */ 7752 PRI_MAP_INIT(unit, map_type); 7753 7754 pm_bk_info = &(bk_info->tsn_pri_map_bk_info); 7755 7756 PRI_MAP_BK_LOCK(unit); 7757 7758 bk_data = &(pm_bk_info->data[map_type][sw_idx]); 7759 bk_data->ref_cnt += 1; 7760 7761 PRI_MAP_BK_UNLOCK(unit); 7762 return BCM_E_NONE; 7763 } 7764 7765 /* 7766 * Function: 7767 * bcmi_esw_tsn_pri_map_ref_cnt_get 7768 * Purpose: 7769 * Get current reference cnt with given map_id 7770 * Parameters: 7771 * unit - (IN) Unit number 7772 * map_id - (IN) Map ID 7773 * ref_cnt - (OUT) Reference cnt 7774 * Returns: 7775 * BCM_E_xxx 7776 */ 7777 int 7778 bcmi_esw_tsn_pri_map_ref_cnt_get( 7779 int unit, 7780 bcm_tsn_pri_map_t map_id, 7781 uint32 *ref_cnt) 7782 { 7783 bcm_error_t rv = BCM_E_UNAVAIL; 7784 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 7785 bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL; 7786 bcm_tsn_pri_map_type_t map_type = PRI_MAP_TYPE_GET(map_id); 7787 uint32 sw_idx = MAP_ID_TO_SW_IDX(map_id); 7788 7789 LOG_VERBOSE(BSL_LS_BCM_TSN, 7790 (BSL_META_U(unit, 7791 "bcmi_esw_tsn_pri_map_ref_cnt_get\n"))); 7792 7793 /* Parameter NULL error handling */ 7794 if (NULL == ref_cnt) { 7795 return BCM_E_PARAM; 7796 } 7797 7798 /* Check if pri_map id existed */ 7799 rv = bcmi_esw_tsn_pri_map_id_existed_check(unit, map_id); 7800 if (BCM_FAILURE(rv)) { 7801 LOG_WARN(BSL_LS_BCM_TSN, 7802 (BSL_META_U(unit, 7803 "map_id(%d) doesn't exited, rv(%d)\n"), 7804 map_id, 7805 rv)); 7806 return rv; 7807 } 7808 7809 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 7810 7811 /* Initialization check */ 7812 PRI_MAP_INIT(unit, map_type); 7813 7814 pm_bk_info = &(bk_info->tsn_pri_map_bk_info); 7815 7816 *ref_cnt = pm_bk_info->data[map_type][sw_idx].ref_cnt; 7817 return BCM_E_NONE; 7818 } 7819 7820 /* 7821 * Function: 7822 * bcmi_esw_tsn_pri_map_get_empty_map_id 7823 * Purpose: 7824 * Get a empty map_id for specific map type 7825 * Parameters: 7826 * unit - (IN) Unit number 7827 * map_type - (IN) Priority Map Type 7828 * map_id - (OUT) Map ID 7829 * Returns: 7830 * BCM_E_NONE - Success on finding a empty map_id 7831 */ 7832 STATIC int 7833 bcmi_esw_tsn_pri_map_get_empty_map_id( 7834 int unit, 7835 bcm_tsn_pri_map_type_t map_type, 7836 bcm_tsn_pri_map_t *map_id) 7837 { 7838 bcm_error_t rv = BCM_E_UNAVAIL; 7839 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 7840 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 7841 const tsn_pri_map_info_t *pm_dev_info = NULL; 7842 bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL; 7843 /* Empty id */ 7844 uint32 e_sw_idx; 7845 7846 LOG_VERBOSE(BSL_LS_BCM_TSN, 7847 (BSL_META_U(unit, 7848 "bcmi_esw_tsn_pri_map_get_empty_map_id\n"))); 7849 7850 if (NULL == map_id) { 7851 return BCM_E_PARAM; 7852 } 7853 7854 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 7855 7856 /* Initialization check */ 7857 PRI_MAP_INIT(unit, map_type); 7858 7859 pm_bk_info = &(bk_info->tsn_pri_map_bk_info); 7860 dev_info = bk_info->tsn_dev_info; 7861 pm_dev_info = dev_info->tsn_pri_map_info[map_type]; 7862 7863 PRI_MAP_BK_LOCK(unit); 7864 /* Already full, return E_RESOURCE */ 7865 if (pm_bk_info->valid_count[map_type] == pm_dev_info->table_size) { 7866 PRI_MAP_BK_UNLOCK(unit); 7867 return BCM_E_RESOURCE; 7868 } 7869 7870 /* Try to find an empty id */ 7871 for (e_sw_idx = pm_bk_info->empty_sw_idx_start[map_type]; 7872 e_sw_idx <= pm_bk_info->empty_sw_idx_end[map_type]; 7873 e_sw_idx++) { 7874 7875 if (PRI_MAP_INTF_GET(unit, map_type, e_sw_idx) == 0) { 7876 /* An empty id found, set bit map as used */ 7877 PRI_MAP_INTF_SET(unit, map_type, e_sw_idx); 7878 7879 /* Update valid start and end */ 7880 if (pm_bk_info->valid_count[map_type] == 0) { 7881 pm_bk_info->valid_sw_idx_start[map_type] = e_sw_idx; 7882 pm_bk_info->valid_sw_idx_end[map_type] = e_sw_idx; 7883 } else if (e_sw_idx < pm_bk_info->valid_sw_idx_start[map_type]) { 7884 pm_bk_info->valid_sw_idx_start[map_type] = e_sw_idx; 7885 } else if (e_sw_idx > pm_bk_info->valid_sw_idx_end[map_type]) { 7886 pm_bk_info->valid_sw_idx_end[map_type] = e_sw_idx; 7887 } 7888 7889 pm_bk_info->valid_count[map_type]++; 7890 *map_id = SW_IDX_TO_MAP_ID(e_sw_idx, map_type); 7891 7892 /* Update the empty start, assume next one is real empty */ 7893 pm_bk_info->empty_sw_idx_start[map_type] = e_sw_idx + 1; 7894 7895 /* An empty id found, break and return BCM_E_NONE */ 7896 rv = BCM_E_NONE; 7897 break; 7898 } else { 7899 /* Not empty id */ 7900 7901 /* Update the empty start, assume next one is real empty */ 7902 pm_bk_info->empty_sw_idx_start[map_type] = e_sw_idx + 1; 7903 } 7904 } 7905 PRI_MAP_BK_UNLOCK(unit); 7906 return rv; 7907 } 7908 7909 /* 7910 * Function: 7911 * bcmi_esw_tsn_pri_map_destroy_map_id 7912 * Purpose: 7913 * Free the resource of map_id 7914 * Parameters: 7915 * unit - (IN) Unit number 7916 * map_id - (IN) Map ID 7917 * Returns: 7918 * BCM_E_NONE - Success on destroying the given map_id 7919 */ 7920 STATIC int 7921 bcmi_esw_tsn_pri_map_destroy_map_id( 7922 int unit, 7923 bcm_tsn_pri_map_t map_id) 7924 { 7925 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 7926 bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL; 7927 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 7928 const tsn_pri_map_info_t *pm_dev_info = NULL; 7929 bcm_tsn_pri_map_type_t map_type = PRI_MAP_TYPE_GET(map_id); 7930 uint32 destroy_sw_idx = MAP_ID_TO_SW_IDX(map_id); 7931 uint32 n_valid_sw_idx; 7932 7933 LOG_VERBOSE(BSL_LS_BCM_TSN, 7934 (BSL_META_U(unit, 7935 "bcmi_esw_tsn_pri_map_destroy_map_id\n"))); 7936 7937 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 7938 7939 /* Initialization check */ 7940 PRI_MAP_INIT(unit, map_type); 7941 7942 pm_bk_info = &(bk_info->tsn_pri_map_bk_info); 7943 dev_info = bk_info->tsn_dev_info; 7944 pm_dev_info = dev_info->tsn_pri_map_info[map_type]; 7945 7946 assert(pm_dev_info->table_size > 0); 7947 7948 PRI_MAP_BK_LOCK(unit); 7949 /* Destroy bit map */ 7950 PRI_MAP_INTF_CLR(unit, map_type, destroy_sw_idx); 7951 7952 /* Update empty start and end */ 7953 if (destroy_sw_idx < pm_bk_info->empty_sw_idx_start[map_type]) { 7954 pm_bk_info->empty_sw_idx_start[map_type] = destroy_sw_idx; 7955 } else if (destroy_sw_idx > pm_bk_info->empty_sw_idx_end[map_type]) { 7956 pm_bk_info->empty_sw_idx_end[map_type] = destroy_sw_idx; 7957 } 7958 7959 /* Update valid, find a next valid start or next valid end */ 7960 n_valid_sw_idx = destroy_sw_idx; 7961 if (pm_bk_info->valid_count[map_type] > 1) { 7962 if (n_valid_sw_idx == pm_bk_info->valid_sw_idx_start[map_type]) { 7963 do { 7964 n_valid_sw_idx++; 7965 } while (PRI_MAP_INTF_GET(unit, map_type, n_valid_sw_idx) == 0); 7966 pm_bk_info->valid_sw_idx_start[map_type] = n_valid_sw_idx; 7967 } else if (n_valid_sw_idx == pm_bk_info->valid_sw_idx_end[map_type]) { 7968 do { 7969 n_valid_sw_idx--; 7970 } while (PRI_MAP_INTF_GET(unit, map_type, n_valid_sw_idx) == 0); 7971 pm_bk_info->valid_sw_idx_end[map_type] = n_valid_sw_idx; 7972 } 7973 } 7974 pm_bk_info->valid_count[map_type]--; 7975 7976 if (0 == pm_bk_info->valid_count[map_type]) { 7977 pm_bk_info->valid_sw_idx_start[map_type] = 0; 7978 pm_bk_info->valid_sw_idx_end[map_type] = 0; 7979 pm_bk_info->empty_sw_idx_start[map_type] = 0; 7980 pm_bk_info->empty_sw_idx_end[map_type] = pm_dev_info->table_size - 1; 7981 } 7982 PRI_MAP_BK_UNLOCK(unit); 7983 return BCM_E_NONE; 7984 } 7985 7986 /* 7987 * Function: 7988 * bcmi_esw_tsn_pri_map_tsn_sr_coldboot_init 7989 * Purpose: 7990 * Restore bookkeeping information of TSN & SR priority map resource. 7991 * Parameters: 7992 * unit - (IN) unit number 7993 * Returns: 7994 * BCM_E_XXX 7995 */ 7996 STATIC int 7997 bcmi_esw_tsn_pri_map_tsn_sr_coldboot_init(int unit) 7998 { 7999 bcm_error_t rv = BCM_E_UNAVAIL; 8000 uint32 sw_idx; 8001 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 8002 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 8003 const tsn_pri_map_info_t *pm_dev_info = NULL; 8004 bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount; 8005 8006 LOG_VERBOSE(BSL_LS_BCM_TSN, 8007 (BSL_META_U(unit, 8008 "bcmi_esw_tsn_pri_map_tsn_sr_coldboot_init\n"))); 8009 8010 #if defined(BCM_WARM_BOOT_SUPPORT) 8011 /* Warm boot should be false in cold boot case */ 8012 if (SOC_WARM_BOOT(unit)) { 8013 return BCM_E_UNAVAIL; 8014 } 8015 #endif /* BCM_WARM_BOOT_SUPPORT */ 8016 8017 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 8018 8019 dev_info = bk_info->tsn_dev_info; 8020 8021 /* Only init TSN & SR since there is only TSN and SR HW */ 8022 for (map_type = bcmTsnPriMapTypeTsnFlow; 8023 map_type <= bcmTsnPriMapTypeSrFlow; 8024 map_type++) { 8025 8026 pm_dev_info = dev_info->tsn_pri_map_info[map_type]; 8027 if (NULL == pm_dev_info || 8028 (map_type == bcmTsnPriMapTypeTsnFlow && 8029 !soc_feature(unit, soc_feature_tsn)) || 8030 (map_type == bcmTsnPriMapTypeSrFlow && 8031 !soc_feature(unit, soc_feature_tsn_sr))) { 8032 /* Need to check all map_type */ 8033 continue; 8034 } 8035 8036 assert(pm_dev_info->table_size > 0); 8037 /* 8038 * Do not need to init 1st profile, thus sw_idx start from 1 8039 * 1st profile is always initialized in bcmi_esw_tsn_pri_map_init 8040 */ 8041 for (sw_idx = 1; 8042 sw_idx < (pm_dev_info->table_size); 8043 sw_idx++) { 8044 if (NULL == pm_dev_info->tsn_pri_map_delete) { 8045 return BCM_E_UNAVAIL; 8046 } 8047 /* Use delete for reset HW to default value */ 8048 rv = pm_dev_info->tsn_pri_map_delete(unit, sw_idx); 8049 if (BCM_FAILURE(rv)) { 8050 LOG_ERROR(BSL_LS_BCM_TSN, 8051 (BSL_META_U(unit, 8052 "HW operation failed(rv = %d)\n"), 8053 rv)); 8054 return rv; 8055 } 8056 } 8057 } 8058 return BCM_E_NONE; 8059 } 8060 8061 #if defined(BCM_WARM_BOOT_SUPPORT) 8062 /* 8063 * Function: 8064 * bcmi_esw_tsn_pri_map_tsn_sr_reload 8065 * Purpose: 8066 * Restore bookkeeping information of TSN & SR priority map resource. 8067 * Parameters: 8068 * unit - (IN) unit number 8069 * Returns: 8070 * BCM_E_XXX 8071 */ 8072 STATIC int 8073 bcmi_esw_tsn_pri_map_tsn_sr_reload(int unit) 8074 { 8075 bcm_error_t rv = BCM_E_UNAVAIL; 8076 uint32 sw_idx; 8077 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 8078 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 8079 const tsn_pri_map_info_t *pm_dev_info = NULL; 8080 bcm_tsn_pri_map_t map_id; 8081 bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount; 8082 bcm_tsn_pri_map_config_t config; 8083 8084 LOG_VERBOSE(BSL_LS_BCM_TSN, 8085 (BSL_META_U(unit, 8086 "bcmi_esw_tsn_pri_map_tsn_sr_reload\n"))); 8087 8088 if (!SOC_WARM_BOOT(unit)) { 8089 return BCM_E_UNAVAIL; 8090 } 8091 8092 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 8093 8094 dev_info = bk_info->tsn_dev_info; 8095 8096 /* only recovery TSN & SR & TAF 8097 * since MTU/STU wb is done by MTU/STU module 8098 */ 8099 for (map_type = 0; map_type < bcmTsnPriMapTypeCount; map_type++) { 8100 8101 if (map_type == bcmTsnPriMapTypeEgressMtuProfile || 8102 map_type == bcmTsnPriMapTypeEgressStuProfile ) { 8103 continue; 8104 } 8105 8106 pm_dev_info = dev_info->tsn_pri_map_info[map_type]; 8107 if (NULL == pm_dev_info || 8108 (map_type == bcmTsnPriMapTypeTsnFlow && 8109 !soc_feature(unit, soc_feature_tsn)) || 8110 (map_type == bcmTsnPriMapTypeSrFlow && 8111 !soc_feature(unit, soc_feature_tsn_sr)) || 8112 (map_type == bcmTsnPriMapTypeTafGate && 8113 !soc_feature(unit, soc_feature_tsn_taf))) { 8114 /* Need to check all map_type */ 8115 continue; 8116 } 8117 8118 assert(pm_dev_info->table_size > 0); 8119 /* 8120 * Do not need to check 1st profile, thus sw_idx start from 1 8121 * 1st profile is always initialized in bcmi_esw_tsn_pri_map_init 8122 */ 8123 for (sw_idx = 1; 8124 sw_idx < (pm_dev_info->table_size); 8125 sw_idx++) { 8126 PRI_MAP_BK_LOCK(unit); 8127 PRI_MAP_INTF_CLR(unit, map_type, sw_idx); 8128 PRI_MAP_BK_UNLOCK(unit); 8129 if (NULL == pm_dev_info->tsn_pri_map_wb_hw_existed || 8130 NULL == pm_dev_info->tsn_pri_map_get) { 8131 return BCM_E_UNAVAIL; 8132 } 8133 8134 PRI_MAP_LOCK(unit); 8135 rv = pm_dev_info->tsn_pri_map_wb_hw_existed(unit, sw_idx); 8136 PRI_MAP_UNLOCK(unit); 8137 if (BCM_SUCCESS(rv)) { 8138 /* rv = BCM_E_NONE means HW existed */ 8139 8140 /* Set bit map as used */ 8141 map_id = SW_IDX_TO_MAP_ID(sw_idx, map_type); 8142 PRI_MAP_BK_LOCK(unit); 8143 PRI_MAP_INTF_SET(unit, map_type, sw_idx); 8144 PRI_MAP_BK_UNLOCK(unit); 8145 8146 /* Restore SW database from HW */ 8147 rv = pm_dev_info->tsn_pri_map_get(unit, sw_idx, &config); 8148 if (BCM_FAILURE(rv)) { 8149 PRI_MAP_BK_LOCK(unit); 8150 /* Clear SW usage bitmap */ 8151 PRI_MAP_INTF_CLR(unit, map_type, sw_idx); 8152 PRI_MAP_BK_UNLOCK(unit); 8153 8154 LOG_ERROR(BSL_LS_BCM_TSN, 8155 (BSL_META_U(unit, 8156 "Read from HW failed(rv = %d)\n"), 8157 rv)); 8158 return rv; 8159 } 8160 8161 /* Write via bcm set API to make sure bk info is also updated */ 8162 bcm_esw_tsn_pri_map_set(unit, map_id, &config); 8163 } 8164 } 8165 } 8166 return BCM_E_NONE; 8167 } 8168 8169 /* 8170 * Function: 8171 * bcmi_esw_tsn_pri_map_mtu_stu_wb_set 8172 * Purpose: 8173 * Warmboot function provided for mtu/stu module doing warmboot recovery 8174 * MTU/STU modules should have config and map_id when doing warmboot 8175 * and this API is for MTU/STU modules to do WB recovery. 8176 * Parameters: 8177 * unit - (IN) Unit number 8178 * map_id - (IN) Map ID 8179 * config - (IN) Priority Map configuration 8180 * Returns: 8181 * BCM_E_xxx 8182 */ 8183 int 8184 bcmi_esw_tsn_pri_map_mtu_stu_wb_set( 8185 int unit, 8186 bcm_tsn_pri_map_t map_id, 8187 bcm_tsn_pri_map_config_t *config) 8188 { 8189 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 8190 bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL; 8191 bcm_tsn_pri_map_type_t map_type = PRI_MAP_TYPE_GET(map_id); 8192 uint32 wb_sw_idx = MAP_ID_TO_SW_IDX(map_id); 8193 8194 LOG_VERBOSE(BSL_LS_BCM_TSN, 8195 (BSL_META_U(unit, 8196 "bcmi_esw_tsn_pri_map_mtu_stu_wb_set\n"))); 8197 8198 if (!SOC_WARM_BOOT(unit)) { 8199 return BCM_E_UNAVAIL; 8200 } 8201 8202 /* Parameter NULL error handling */ 8203 if (NULL == config) { 8204 return BCM_E_PARAM; 8205 } 8206 8207 /* Parameter check */ 8208 if (BCM_TSN_PRI_MAP_INVALID == map_id) { 8209 return BCM_E_CONFIG; 8210 } 8211 8212 /* Check if the map_id encoding is MTU/STU */ 8213 if (!(PRI_MAP_ID_IS_TYPE(map_id, bcmTsnPriMapTypeEgressMtuProfile) || 8214 PRI_MAP_ID_IS_TYPE(map_id, bcmTsnPriMapTypeEgressStuProfile))) { 8215 LOG_ERROR(BSL_LS_BCM_TSN, 8216 (BSL_META_U(unit, 8217 "This WB recovery API is only for MTU & STU" 8218 "Error map_id(%d)\n"), 8219 map_id)); 8220 return BCM_E_PARAM; 8221 } 8222 8223 /* Check if the config map_type is MTU/STU */ 8224 if (!((config->map_type == bcmTsnPriMapTypeEgressMtuProfile) || 8225 (config->map_type == bcmTsnPriMapTypeEgressStuProfile))) { 8226 LOG_ERROR(BSL_LS_BCM_TSN, 8227 (BSL_META_U(unit, 8228 "This WB recovery API is only for MTU & STU" 8229 "Error map_type(%d)\n"), 8230 config->map_type)); 8231 return BCM_E_PARAM; 8232 } 8233 8234 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 8235 8236 /* Initialization check */ 8237 PRI_MAP_INIT(unit, map_type); 8238 8239 pm_bk_info = &(bk_info->tsn_pri_map_bk_info); 8240 8241 PRI_MAP_BK_LOCK(unit); 8242 8243 /* Set bit map as used */ 8244 PRI_MAP_INTF_SET(unit, map_type, wb_sw_idx); 8245 8246 /* Update valid start and end */ 8247 if (pm_bk_info->valid_count[map_type] == 0) { 8248 pm_bk_info->valid_sw_idx_start[map_type] = wb_sw_idx; 8249 pm_bk_info->valid_sw_idx_end[map_type] = wb_sw_idx; 8250 } else if (wb_sw_idx < pm_bk_info->valid_sw_idx_start[map_type]) { 8251 pm_bk_info->valid_sw_idx_start[map_type] = wb_sw_idx; 8252 } else if (wb_sw_idx > pm_bk_info->valid_sw_idx_end[map_type]) { 8253 pm_bk_info->valid_sw_idx_end[map_type] = wb_sw_idx; 8254 } 8255 pm_bk_info->valid_count[map_type]++; 8256 8257 /* Update empty start and end */ 8258 if (pm_bk_info->empty_sw_idx_start[map_type] == 8259 pm_bk_info->empty_sw_idx_end[map_type]) { 8260 /* Do nothing */ 8261 } else if (wb_sw_idx == pm_bk_info->empty_sw_idx_start[map_type]) { 8262 /* Assume next one is real empty */ 8263 pm_bk_info->empty_sw_idx_start[map_type]++; 8264 } else if (wb_sw_idx == pm_bk_info->empty_sw_idx_end[map_type]) { 8265 /* Assume previous one is real empty */ 8266 pm_bk_info->empty_sw_idx_end[map_type]--; 8267 } 8268 PRI_MAP_BK_UNLOCK(unit); 8269 8270 /* Write via bcm set API to make sure bk info is also updated */ 8271 bcm_esw_tsn_pri_map_set(unit, map_id, config); 8272 8273 return BCM_E_NONE; 8274 } 8275 8276 #endif /* BCM_WARM_BOOT_SUPPORT */ 8277 8278 /* 8279 * Function: 8280 * bcmi_esw_tsn_pri_map_create 8281 * Purpose: 8282 * Add a priority map config to hardware. 8283 * Parameters: 8284 * unit - (IN) Unit number 8285 * config - (IN) Priority Map configuration 8286 * map_id - (OUT) Map ID 8287 * Returns: 8288 * BCM_E_xxx 8289 */ 8290 STATIC int 8291 bcmi_esw_tsn_pri_map_create( 8292 int unit, 8293 bcm_tsn_pri_map_config_t *config, 8294 bcm_tsn_pri_map_t *map_id) 8295 { 8296 bcm_error_t rv, rv2; 8297 int i; 8298 uint32 sw_idx; 8299 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 8300 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 8301 const tsn_pri_map_info_t *pm_dev_info = NULL; 8302 bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL; 8303 bcmi_esw_tsn_pri_map_bk_info_data_t *bk_data = NULL; 8304 bcm_tsn_pri_map_config_t *bk_config = NULL; 8305 8306 LOG_VERBOSE(BSL_LS_BCM_TSN, 8307 (BSL_META_U(unit, 8308 "bcmi_esw_tsn_pri_map_create\n"))); 8309 8310 /* Parameter NULL error handling */ 8311 if ((NULL == config) || (NULL == map_id)) { 8312 return BCM_E_PARAM; 8313 } 8314 8315 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 8316 8317 /* Initialization check */ 8318 PRI_MAP_INIT(unit, config->map_type); 8319 8320 pm_bk_info = &(bk_info->tsn_pri_map_bk_info); 8321 dev_info = bk_info->tsn_dev_info; 8322 pm_dev_info = dev_info->tsn_pri_map_info[config->map_type]; 8323 8324 if ((config->map_type < bcmTsnPriMapTypeTsnFlow) || 8325 (config->map_type >= bcmTsnPriMapTypeCount) || 8326 (config->num_map_entries != (pm_dev_info->entry_size))) { 8327 LOG_ERROR(BSL_LS_BCM_TSN, 8328 (BSL_META_U(unit, 8329 "Error map_type(%d), num_map_entries(%d)\n"), 8330 config->map_type, 8331 config->num_map_entries)); 8332 return BCM_E_PARAM; 8333 } 8334 8335 PRI_MAP_LOCK(unit); 8336 8337 /* Check if the same pri_map existed or not, return EXISTS if yes. */ 8338 rv = bcmi_esw_tsn_pri_map_existed_check(unit, config, map_id); 8339 if (BCM_E_EXISTS == rv) { 8340 LOG_WARN(BSL_LS_BCM_TSN, 8341 (BSL_META_U(unit, 8342 "config already existed, found map_id(%d)\n"), 8343 *map_id)); 8344 PRI_MAP_UNLOCK(unit); 8345 return BCM_E_EXISTS; 8346 } else if (BCM_E_NOT_FOUND != rv) { 8347 LOG_WARN(BSL_LS_BCM_TSN, 8348 (BSL_META_U(unit, 8349 "find existed Priority Map config failed" 8350 "(rv = %d)\n"), 8351 rv)); 8352 PRI_MAP_UNLOCK(unit); 8353 return rv; 8354 } 8355 8356 /* Get a SW empty map_id */ 8357 rv = bcmi_esw_tsn_pri_map_get_empty_map_id( 8358 unit, 8359 config->map_type, 8360 map_id); 8361 if (BCM_FAILURE(rv)) { 8362 LOG_ERROR(BSL_LS_BCM_TSN, 8363 (BSL_META_U(unit, 8364 "no empty map_id(rv = %d)\n"), 8365 rv)); 8366 PRI_MAP_UNLOCK(unit); 8367 return rv; 8368 } 8369 8370 /* Set the config to HW */ 8371 sw_idx = MAP_ID_TO_SW_IDX(*map_id); 8372 if ((config->map_type == bcmTsnPriMapTypeEgressMtuProfile) || 8373 (config->map_type == bcmTsnPriMapTypeEgressStuProfile)) { 8374 /* 8375 * There is no HW operations for MTU/STU 8376 * MTU/STU are stored in bookkeeping bcmi_esw_tsn_pri_map_bk_info_t 8377 */ 8378 } else if (NULL == pm_dev_info->tsn_pri_map_set) { 8379 /* Besides MTU/STU, instance should not be NULL */ 8380 PRI_MAP_UNLOCK(unit); 8381 return BCM_E_UNAVAIL; 8382 } else { 8383 rv = pm_dev_info->tsn_pri_map_set(unit, sw_idx, config); 8384 8385 if (BCM_FAILURE(rv)) { 8386 LOG_ERROR(BSL_LS_BCM_TSN, 8387 (BSL_META_U(unit, 8388 "write to HW failed(rv = %d)\n"), 8389 rv)); 8390 8391 /* Destroy the map_id got from above */ 8392 rv2 = bcmi_esw_tsn_pri_map_destroy_map_id(unit, *map_id); 8393 if (BCM_FAILURE(rv2)) { 8394 LOG_ERROR(BSL_LS_BCM_TSN, 8395 (BSL_META_U(unit, 8396 "clear usage bitmap failed(rv = %d)\n"), 8397 rv2)); 8398 PRI_MAP_UNLOCK(unit); 8399 return rv2; 8400 } 8401 8402 PRI_MAP_UNLOCK(unit); 8403 return rv; 8404 } 8405 } 8406 8407 /* Increase reference cnt of MTU/STU profile_id */ 8408 if (config->map_type == bcmTsnPriMapTypeEgressMtuProfile || 8409 config->map_type == bcmTsnPriMapTypeEgressStuProfile) { 8410 for (i = 0; 8411 i < config->num_map_entries; 8412 i++) { 8413 if ((config->map_type == bcmTsnPriMapTypeEgressMtuProfile) && 8414 (config->map_entries[i].flags & 8415 BCM_TSN_PRI_MAP_ENTRY_PROFILE_ID)) { 8416 /* Increase reference cnt of MTU profile_id */ 8417 rv = bcmi_esw_tsn_mtu_profile_ref_inc( 8418 unit, config->map_entries[i].profile_id); 8419 } else if ( 8420 (config->map_type == bcmTsnPriMapTypeEgressStuProfile) && 8421 (config->map_entries[i].flags & 8422 BCM_TSN_PRI_MAP_ENTRY_PROFILE_ID)) { 8423 /* Increase reference cnt of STU profile_id */ 8424 rv = bcmi_esw_tsn_stu_profile_ref_inc( 8425 unit, config->map_entries[i].profile_id); 8426 } 8427 if (BCM_FAILURE(rv)) { 8428 PRI_MAP_UNLOCK(unit); 8429 LOG_ERROR(BSL_LS_BCM_TSN, 8430 (BSL_META_U(unit, 8431 "Increase MTU / STU reference cnt failed" 8432 "(rv = %d)\n"), 8433 rv)); 8434 return rv; 8435 } 8436 8437 } 8438 } 8439 8440 PRI_MAP_BK_LOCK(unit); 8441 /* Update SW bookkeeping database */ 8442 bk_data = &(pm_bk_info->data[config->map_type][sw_idx]); 8443 bk_data->map_id = *map_id; 8444 bk_data->ref_cnt = 0; 8445 bk_config = &(bk_data->config); 8446 sal_memcpy(bk_config, 8447 config, 8448 sizeof(bcm_tsn_pri_map_config_t)); 8449 PRI_MAP_BK_UNLOCK(unit); 8450 PRI_MAP_UNLOCK(unit); 8451 return BCM_E_NONE; 8452 } 8453 8454 /* 8455 * Function: 8456 * bcmi_esw_tsn_pri_map_set 8457 * Purpose: 8458 * Set priority map config with the given map_id. 8459 * Parameters: 8460 * unit - (IN) Unit number 8461 * map_id - (IN) Map ID 8462 * config - (IN) Priority Map configuration 8463 * Returns: 8464 * BCM_E_xxx 8465 */ 8466 STATIC int 8467 bcmi_esw_tsn_pri_map_set( 8468 int unit, 8469 bcm_tsn_pri_map_t map_id, 8470 bcm_tsn_pri_map_config_t *config) 8471 { 8472 bcm_error_t rv = BCM_E_UNAVAIL; 8473 uint32 ref_cnt; 8474 uint32 sw_idx; 8475 bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount; 8476 bcm_tsn_pri_map_t exisited_map_id; 8477 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 8478 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 8479 const tsn_pri_map_info_t *pm_dev_info = NULL; 8480 bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL; 8481 bcmi_esw_tsn_pri_map_bk_info_data_t *bk_data = NULL; 8482 bcm_tsn_pri_map_config_t *bk_config = NULL; 8483 8484 LOG_VERBOSE(BSL_LS_BCM_TSN, 8485 (BSL_META_U(unit, 8486 "bcmi_esw_tsn_pri_map_set\n"))); 8487 8488 /* Parameter NULL error handling */ 8489 if (NULL == config) { 8490 return BCM_E_PARAM; 8491 } 8492 8493 /* Parameter check */ 8494 if (BCM_TSN_PRI_MAP_INVALID == map_id) { 8495 return BCM_E_CONFIG; 8496 } 8497 8498 bcmi_esw_tsn_pri_map_dump_config(unit, "config set", config); 8499 8500 /* If parameter config->map_type is the same as map_type of map_id. */ 8501 map_type = PRI_MAP_TYPE_GET(map_id); 8502 if ((config->map_type != map_type)) { 8503 LOG_WARN(BSL_LS_BCM_TSN, 8504 (BSL_META_U(unit, 8505 "set wrong config to map_id(%d)\n" 8506 "map_type doesn't match\n"), map_id)); 8507 return BCM_E_PARAM; 8508 } 8509 8510 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 8511 8512 /* Initialization check */ 8513 PRI_MAP_INIT(unit, map_type); 8514 8515 pm_bk_info = &(bk_info->tsn_pri_map_bk_info); 8516 dev_info = bk_info->tsn_dev_info; 8517 pm_dev_info = dev_info->tsn_pri_map_info[map_type]; 8518 8519 if ((config->map_type < bcmTsnPriMapTypeTsnFlow) || 8520 (config->map_type >= bcmTsnPriMapTypeCount) || 8521 (config->num_map_entries != (pm_dev_info->entry_size))) { 8522 LOG_ERROR(BSL_LS_BCM_TSN, 8523 (BSL_META_U(unit, 8524 "Error map_type(%d), num_map_entries(%d)\n"), 8525 config->map_type, 8526 config->num_map_entries)); 8527 return BCM_E_PARAM; 8528 } 8529 8530 PRI_MAP_LOCK(unit); 8531 8532 /* Check if pri_map id existed */ 8533 rv = bcmi_esw_tsn_pri_map_id_existed_check(unit, map_id); 8534 if (BCM_FAILURE(rv)) { 8535 PRI_MAP_UNLOCK(unit); 8536 LOG_WARN(BSL_LS_BCM_TSN, 8537 (BSL_META_U(unit, 8538 "map_id(%d) doesn't exited, rv(%d)\n"), 8539 map_id, 8540 rv)); 8541 return rv; 8542 } 8543 8544 /* Check if the same pri_map existed or not */ 8545 rv = bcmi_esw_tsn_pri_map_existed_check(unit, config, &exisited_map_id); 8546 if (BCM_E_EXISTS == rv) { 8547 if (exisited_map_id == map_id) { 8548 /* config is the same as config of current map_id */ 8549 LOG_WARN(BSL_LS_BCM_TSN, 8550 (BSL_META_U(unit, 8551 "config is the same as the config " 8552 "of current map_id(%d)\n"), 8553 map_id)); 8554 PRI_MAP_UNLOCK(unit); 8555 return BCM_E_NONE; 8556 } else { 8557 /* config is found on other map_id */ 8558 LOG_WARN(BSL_LS_BCM_TSN, 8559 (BSL_META_U(unit, 8560 "config already existed, found map_id(%d)\n"), 8561 exisited_map_id)); 8562 PRI_MAP_UNLOCK(unit); 8563 return BCM_E_EXISTS; 8564 } 8565 } 8566 8567 /* Check if there is any module using this pri_map id. */ 8568 rv = bcmi_esw_tsn_pri_map_ref_cnt_get(unit, map_id, &ref_cnt); 8569 if (BCM_FAILURE(rv)) { 8570 LOG_ERROR(BSL_LS_BCM_TSN, 8571 (BSL_META_U(unit, 8572 "get reference count error(rv = %d)\n"), 8573 rv)); 8574 PRI_MAP_UNLOCK(unit); 8575 return rv; 8576 } 8577 8578 /* There is still other module using the pri_map id, return E_BUSY. */ 8579 if (ref_cnt != 0) { 8580 LOG_WARN(BSL_LS_BCM_TSN, 8581 (BSL_META_U(unit, 8582 "unable to change the config of map_id(%d)\n" 8583 "is still used by other (%d) component.\n"), 8584 map_id, 8585 ref_cnt)); 8586 PRI_MAP_UNLOCK(unit); 8587 return BCM_E_BUSY; 8588 } 8589 8590 /* Set the config to HW */ 8591 sw_idx = MAP_ID_TO_SW_IDX(map_id); 8592 if ((map_type == bcmTsnPriMapTypeEgressMtuProfile) || 8593 (map_type == bcmTsnPriMapTypeEgressStuProfile)) { 8594 /* 8595 * There is no HW operations for MTU/STU 8596 * MTU/STU are stored in bookkeeping bcmi_esw_tsn_pri_map_bk_info_t 8597 */ 8598 } else if (NULL == pm_dev_info->tsn_pri_map_set) { 8599 /* Besides MTU/STU, instance should not be NULL */ 8600 PRI_MAP_UNLOCK(unit); 8601 return BCM_E_UNAVAIL; 8602 } else { 8603 rv = pm_dev_info->tsn_pri_map_set(unit, sw_idx, config); 8604 if (BCM_FAILURE(rv)) { 8605 LOG_ERROR(BSL_LS_BCM_TSN, 8606 (BSL_META_U(unit, 8607 "write to HW failed(rv = %d)\n"), 8608 rv)); 8609 PRI_MAP_UNLOCK(unit); 8610 return rv; 8611 } 8612 } 8613 8614 PRI_MAP_BK_LOCK(unit); 8615 /* Update SW bookkeeping database */ 8616 bk_data = &(pm_bk_info->data[map_type][sw_idx]); 8617 bk_config = &(bk_data->config); 8618 sal_memcpy(bk_config, 8619 config, 8620 sizeof(bcm_tsn_pri_map_config_t)); 8621 PRI_MAP_BK_UNLOCK(unit); 8622 PRI_MAP_UNLOCK(unit); 8623 8624 return BCM_E_NONE; 8625 } 8626 8627 /* 8628 * Function: 8629 * bcmi_esw_tsn_pri_map_get 8630 * Purpose: 8631 * Get the priority map config with the given map_id. 8632 * Parameters: 8633 * unit - (IN) Unit number 8634 * map_id - (IN) Map ID 8635 * config - (OUT) Priority Map configuration 8636 * Returns: 8637 * BCM_E_xxx 8638 */ 8639 STATIC int 8640 bcmi_esw_tsn_pri_map_get( 8641 int unit, 8642 bcm_tsn_pri_map_t map_id, 8643 bcm_tsn_pri_map_config_t *config) 8644 { 8645 bcm_error_t rv = BCM_E_UNAVAIL; 8646 uint32 sw_idx; 8647 bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount; 8648 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 8649 bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL; 8650 bcmi_esw_tsn_pri_map_bk_info_data_t *bk_data = NULL; 8651 bcm_tsn_pri_map_config_t *bk_config = NULL; 8652 8653 LOG_VERBOSE(BSL_LS_BCM_TSN, 8654 (BSL_META_U(unit, 8655 "bcmi_esw_tsn_pri_map_get\n"))); 8656 8657 /* Parameter NULL error handling */ 8658 if (NULL == config) { 8659 return BCM_E_PARAM; 8660 } 8661 8662 /* Parameter check */ 8663 if (BCM_TSN_PRI_MAP_INVALID == map_id) { 8664 return BCM_E_CONFIG; 8665 } 8666 8667 PRI_MAP_LOCK(unit); 8668 8669 /* Check if pri_map id existed */ 8670 rv = bcmi_esw_tsn_pri_map_id_existed_check(unit, map_id); 8671 if (BCM_FAILURE(rv)) { 8672 PRI_MAP_UNLOCK(unit); 8673 LOG_WARN(BSL_LS_BCM_TSN, 8674 (BSL_META_U(unit, 8675 "map_id(%d) doesn't exited, rv(%d)\n"), 8676 map_id, 8677 rv)); 8678 return rv; 8679 } 8680 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 8681 8682 pm_bk_info = &(bk_info->tsn_pri_map_bk_info); 8683 8684 /* Get the config from SW bookkeeping database */ 8685 sw_idx = MAP_ID_TO_SW_IDX(map_id); 8686 map_type = PRI_MAP_TYPE_GET(map_id); 8687 8688 /* Initialization check */ 8689 PRI_MAP_INIT(unit, map_type); 8690 8691 PRI_MAP_BK_LOCK(unit); 8692 bk_data = &(pm_bk_info->data[map_type][sw_idx]); 8693 bk_config = &(bk_data->config); 8694 sal_memcpy(config, 8695 bk_config, 8696 sizeof(bcm_tsn_pri_map_config_t)); 8697 PRI_MAP_BK_UNLOCK(unit); 8698 PRI_MAP_UNLOCK(unit); 8699 8700 bcmi_esw_tsn_pri_map_dump_config(unit, "config get", config); 8701 return BCM_E_NONE; 8702 } 8703 8704 /* 8705 * Function: 8706 * bcmi_esw_tsn_pri_map_destroy 8707 * Purpose: 8708 * Free the resource of map_id 8709 * Parameters: 8710 * unit - (IN) Unit number 8711 * map_id - (IN) Priority Map ID 8712 * Returns: 8713 * BCM_E_xxx 8714 */ 8715 STATIC int 8716 bcmi_esw_tsn_pri_map_destroy( 8717 int unit, 8718 bcm_tsn_pri_map_t map_id) 8719 { 8720 bcm_error_t rv = BCM_E_UNAVAIL; 8721 int i; 8722 uint32 ref_cnt; 8723 uint32 sw_idx; 8724 bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount; 8725 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 8726 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 8727 const tsn_pri_map_info_t *pm_dev_info = NULL; 8728 bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL; 8729 bcmi_esw_tsn_pri_map_bk_info_data_t *bk_data = NULL; 8730 bcm_tsn_pri_map_config_t *bk_config = NULL; 8731 8732 /* Parameter check */ 8733 if (BCM_TSN_PRI_MAP_INVALID == map_id) { 8734 return BCM_E_CONFIG; 8735 } 8736 8737 LOG_VERBOSE(BSL_LS_BCM_TSN, 8738 (BSL_META_U(unit, 8739 "bcmi_esw_tsn_pri_map_destroy\n"))); 8740 8741 PRI_MAP_LOCK(unit); 8742 8743 /* Check if pri_map id existed */ 8744 rv = bcmi_esw_tsn_pri_map_id_existed_check(unit, map_id); 8745 if (BCM_FAILURE(rv)) { 8746 PRI_MAP_UNLOCK(unit); 8747 LOG_WARN(BSL_LS_BCM_TSN, 8748 (BSL_META_U(unit, 8749 "map_id(%d) doesn't exited, rv(%d)\n"), 8750 map_id, 8751 rv)); 8752 return rv; 8753 } 8754 map_type = PRI_MAP_TYPE_GET(map_id); 8755 8756 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 8757 8758 /* Initialization check */ 8759 PRI_MAP_INIT(unit, map_type); 8760 8761 pm_bk_info = &(bk_info->tsn_pri_map_bk_info); 8762 dev_info = bk_info->tsn_dev_info; 8763 pm_dev_info = dev_info->tsn_pri_map_info[map_type]; 8764 8765 /* Check if there is any module using this pri_map id. */ 8766 rv = bcmi_esw_tsn_pri_map_ref_cnt_get(unit, map_id, &ref_cnt); 8767 if (BCM_FAILURE(rv)) { 8768 LOG_ERROR(BSL_LS_BCM_TSN, 8769 (BSL_META_U(unit, 8770 "get reference count error(rv = %d)\n"), 8771 rv)); 8772 PRI_MAP_UNLOCK(unit); 8773 return rv; 8774 } 8775 8776 /* There is still other module using the pri_map id, return E_BUSY. */ 8777 if (ref_cnt != 0) { 8778 LOG_WARN(BSL_LS_BCM_TSN, 8779 (BSL_META_U(unit, 8780 "unable to delete map_id(%d)\n" 8781 "is still used by other (%d) component.\n"), 8782 map_id, 8783 ref_cnt)); 8784 PRI_MAP_UNLOCK(unit); 8785 return BCM_E_BUSY; 8786 } 8787 sw_idx = MAP_ID_TO_SW_IDX(map_id); 8788 8789 /* Delete HW */ 8790 if ((map_type == bcmTsnPriMapTypeEgressMtuProfile) || 8791 (map_type == bcmTsnPriMapTypeEgressStuProfile)) { 8792 /* 8793 * There is no HW operations for MTU/STU 8794 * MTU/STU are stored in bookkeeping bcmi_esw_tsn_pri_map_bk_info_t 8795 */ 8796 } else if (NULL == pm_dev_info->tsn_pri_map_delete) { 8797 /* Besides MTU/STU, instance should not be NULL */ 8798 PRI_MAP_UNLOCK(unit); 8799 return BCM_E_UNAVAIL; 8800 } else { 8801 if (sw_idx == 0) { 8802 /* cannot delete 1st default setting */ 8803 return BCM_E_NONE; 8804 } 8805 rv = pm_dev_info->tsn_pri_map_delete(unit, sw_idx); 8806 if (BCM_FAILURE(rv)) { 8807 LOG_ERROR(BSL_LS_BCM_TSN, 8808 (BSL_META_U(unit, 8809 "Delete HW failed(rv = %d)\n"), 8810 rv)); 8811 PRI_MAP_UNLOCK(unit); 8812 return rv; 8813 } 8814 } 8815 8816 /* Clear SW usage bitmap */ 8817 rv = bcmi_esw_tsn_pri_map_destroy_map_id(unit, map_id); 8818 if (BCM_FAILURE(rv)) { 8819 LOG_ERROR(BSL_LS_BCM_TSN, 8820 (BSL_META_U(unit, 8821 "clear usage bitmap failed(rv = %d)\n"), 8822 rv)); 8823 PRI_MAP_UNLOCK(unit); 8824 return rv; 8825 } 8826 8827 bk_data = &(pm_bk_info->data[map_type][sw_idx]); 8828 bk_config = &(bk_data->config); 8829 /* Decrease reference cnt of MTU/STU profile_id */ 8830 if (map_type == bcmTsnPriMapTypeEgressMtuProfile || 8831 map_type == bcmTsnPriMapTypeEgressStuProfile) { 8832 for (i = 0; 8833 i < bk_config->num_map_entries; 8834 i++) { 8835 if ((map_type == bcmTsnPriMapTypeEgressMtuProfile) && 8836 (bk_config->map_entries[i].flags & 8837 BCM_TSN_PRI_MAP_ENTRY_PROFILE_ID)) { 8838 /* Decrease reference cnt of MTU profile_id */ 8839 rv = bcmi_esw_tsn_mtu_profile_ref_dec( 8840 unit, bk_config->map_entries[i].profile_id); 8841 } else if ((map_type == bcmTsnPriMapTypeEgressStuProfile) && 8842 (bk_config->map_entries[i].flags & 8843 BCM_TSN_PRI_MAP_ENTRY_PROFILE_ID)) { 8844 /* Decrease reference cnt of STU profile_id */ 8845 rv = bcmi_esw_tsn_stu_profile_ref_dec( 8846 unit, bk_config->map_entries[i].profile_id); 8847 } 8848 if (BCM_FAILURE(rv)) { 8849 PRI_MAP_UNLOCK(unit); 8850 LOG_ERROR(BSL_LS_BCM_TSN, 8851 (BSL_META_U(unit, 8852 "Decrease MTU / STU reference cnt failed" 8853 "(rv = %d)\n"), 8854 rv)); 8855 return rv; 8856 } 8857 } 8858 } 8859 PRI_MAP_BK_LOCK(unit); 8860 8861 /* Update SW bookkeeping database */ 8862 bk_data->map_id = BCM_TSN_PRI_MAP_INVALID; 8863 bk_data->ref_cnt = 0; 8864 sal_memset(bk_config, 8865 0, 8866 sizeof(bcm_tsn_pri_map_config_t)); 8867 PRI_MAP_BK_UNLOCK(unit); 8868 PRI_MAP_UNLOCK(unit); 8869 8870 return BCM_E_NONE; 8871 } 8872 8873 /* 8874 * Function: 8875 * bcmi_esw_tsn_pri_map_traverse 8876 * Purpose: 8877 * Traverse the priority map config information. 8878 * Parameters: 8879 * unit - (IN) Unit number 8880 * cb - (IN) Traverse call back function 8881 * user_data - (IN) User data 8882 * Returns: 8883 * BCM_E_xxx 8884 */ 8885 STATIC int 8886 bcmi_esw_tsn_pri_map_traverse( 8887 int unit, 8888 bcm_tsn_pri_map_traverse_cb cb, 8889 void *user_data) 8890 { 8891 bcm_error_t rv = BCM_E_UNAVAIL; 8892 uint32 sw_idx; 8893 bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount; 8894 8895 LOG_VERBOSE(BSL_LS_BCM_TSN, 8896 (BSL_META_U(unit, 8897 "bcmi_esw_tsn_pri_map_traverse\n"))); 8898 8899 if (NULL == cb) { 8900 return BCM_E_PARAM; 8901 } 8902 8903 for (map_type = bcmTsnPriMapTypeTsnFlow; 8904 map_type < bcmTsnPriMapTypeCount; 8905 map_type++) { 8906 8907 /* Initialization check */ 8908 PRI_MAP_INIT(unit, map_type); 8909 PRI_MAP_LOCK(unit); 8910 for (sw_idx = PRI_MAP_BK_INFO(unit)->valid_sw_idx_start[map_type]; 8911 sw_idx <= PRI_MAP_BK_INFO(unit)->valid_sw_idx_end[map_type]; 8912 sw_idx++) { 8913 8914 if (PRI_MAP_INTF_GET(unit, map_type, sw_idx)) { 8915 /* Doing the user cb function with config */ 8916 rv = cb(unit, SW_IDX_TO_MAP_ID(sw_idx, map_type), user_data); 8917 if (BCM_FAILURE(rv)) { 8918 PRI_MAP_UNLOCK(unit); 8919 return rv; 8920 } 8921 } 8922 } 8923 PRI_MAP_UNLOCK(unit); 8924 } 8925 return BCM_E_NONE; 8926 } 8927 8928 /* 8929 * Function: 8930 * bcmi_esw_tsn_pri_map_cleanup 8931 * Purpose: 8932 * Internal function to clear the resource of the TSN module. 8933 * Parameters: 8934 * unit - (IN) unit number 8935 * Returns: 8936 * BCM_E_XXX 8937 */ 8938 STATIC int 8939 bcmi_esw_tsn_pri_map_cleanup(int unit) 8940 { 8941 bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount; 8942 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 8943 bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL; 8944 8945 LOG_VERBOSE(BSL_LS_BCM_TSN, 8946 (BSL_META_U(unit, 8947 "bcmi_esw_tsn_pri_map_cleanup\n"))); 8948 8949 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 8950 8951 /* Free and clear the priority map bookkeeping info structure */ 8952 pm_bk_info = &(bk_info->tsn_pri_map_bk_info); 8953 8954 for (map_type = bcmTsnPriMapTypeTsnFlow; 8955 map_type < bcmTsnPriMapTypeCount; 8956 map_type++) { 8957 if (pm_bk_info->intf_bitmap[map_type] != NULL) { 8958 TSN_FREE(unit, pm_bk_info->intf_bitmap[map_type], 0); 8959 pm_bk_info->intf_bitmap[map_type] = NULL; 8960 } 8961 if (pm_bk_info->data[map_type] != NULL) { 8962 TSN_FREE(unit, pm_bk_info->data[map_type], 0); 8963 pm_bk_info->data[map_type] = NULL; 8964 } 8965 8966 /* Reset to default setting */ 8967 pm_bk_info->valid_count[map_type] = 0; 8968 pm_bk_info->valid_sw_idx_start[map_type] = 0; 8969 pm_bk_info->valid_sw_idx_end[map_type] = 0; 8970 pm_bk_info->empty_sw_idx_start[map_type] = 0; 8971 pm_bk_info->empty_sw_idx_end[map_type] = 0; 8972 } 8973 8974 if (pm_bk_info->mutex != NULL) { 8975 sal_mutex_destroy(pm_bk_info->mutex); 8976 pm_bk_info->mutex = NULL; 8977 } 8978 8979 if (pm_bk_info->bk_mutex != NULL) { 8980 sal_mutex_destroy(pm_bk_info->bk_mutex); 8981 pm_bk_info->bk_mutex = NULL; 8982 } 8983 8984 return BCM_E_NONE; 8985 } 8986 8987 8988 /* 8989 * Function: 8990 * bcmi_tsn_pri_map_init 8991 * Purpose: 8992 * create a default profile setting 8993 * Parameters: 8994 * unit - (IN) Unit number 8995 * Returns: 8996 * BCM_E_xxx 8997 */ 8998 STATIC int 8999 bcmi_esw_tsn_pri_map_init(int unit) 9000 { 9001 bcm_error_t rv = BCM_E_UNAVAIL; 9002 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 9003 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 9004 const tsn_pri_map_info_t *pm_dev_info = NULL; 9005 bcmi_esw_tsn_pri_map_bk_info_t *pm_bk_info = NULL; 9006 int i, pri_map_id; 9007 bcm_tsn_pri_map_type_t map_type = bcmTsnPriMapTypeCount; 9008 bcm_tsn_pri_map_config_t config; 9009 uint32 table_size, shr_bitdcl_size, bk_data_size; 9010 9011 LOG_VERBOSE(BSL_LS_BCM_TSN, 9012 (BSL_META_U(unit, 9013 "bcmi_esw_tsn_pri_map_init\n"))); 9014 9015 /* error check when bit is not enough for bcm_tsn_pri_map_type */ 9016 assert((1 << (32 - BCMI_TSN_PRI_MAP_TYPE_SHIFT - 1)) >= 9017 bcmTsnPriMapTypeCount); 9018 9019 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 9020 9021 pm_bk_info = &(bk_info->tsn_pri_map_bk_info); 9022 dev_info = bk_info->tsn_dev_info; 9023 9024 /* Check if all device info instances of Priority Map are NULL */ 9025 for (map_type = bcmTsnPriMapTypeTsnFlow; 9026 map_type < bcmTsnPriMapTypeCount; 9027 map_type++) { 9028 pm_dev_info = dev_info->tsn_pri_map_info[map_type]; 9029 if (NULL != pm_dev_info) { 9030 break; 9031 } 9032 } 9033 9034 /* All device info instances of Priority Map are NULL */ 9035 if (map_type == bcmTsnPriMapTypeCount) { 9036 LOG_WARN(BSL_LS_BCM_SWITCH, 9037 (BSL_META_U(unit, 9038 "Priority Map not supported:\n" 9039 "platform initialized, but none" 9040 "Priority Map services are available.\n"))); 9041 return BCM_E_UNAVAIL; 9042 } 9043 9044 LOG_VERBOSE(BSL_LS_BCM_TSN, 9045 (BSL_META_U(unit, 9046 "bcmi_esw_tsn_pri_map_init: Priority Map\n"))); 9047 9048 /* Allocate Priority Map bookkeeping resource, also do initialization */ 9049 for (map_type = bcmTsnPriMapTypeTsnFlow; 9050 map_type < bcmTsnPriMapTypeCount; 9051 map_type++) { 9052 9053 pm_dev_info = dev_info->tsn_pri_map_info[map_type]; 9054 if (NULL == pm_dev_info || 9055 (map_type == bcmTsnPriMapTypeSrFlow && 9056 !soc_feature(unit, soc_feature_tsn_sr)) || 9057 (map_type == bcmTsnPriMapTypeEgressMtuProfile && 9058 !soc_feature(unit, soc_feature_tsn_mtu_stu)) || 9059 (map_type == bcmTsnPriMapTypeEgressStuProfile && 9060 !soc_feature(unit, soc_feature_tsn_mtu_stu)) || 9061 (map_type == bcmTsnPriMapTypeTafGate && 9062 !soc_feature(unit, soc_feature_tsn_taf))) { 9063 /* Some chips only have some PriMapType */ 9064 continue; 9065 } 9066 9067 /* table_size should large than 0 */ 9068 assert(pm_dev_info->table_size > 0); 9069 table_size = pm_dev_info->table_size; 9070 9071 /* Allocate usage bitmap */ 9072 shr_bitdcl_size = SHR_BITALLOCSIZE(table_size); 9073 TSN_ALLOC(unit, pm_bk_info->intf_bitmap[map_type], SHR_BITDCL, 9074 shr_bitdcl_size, 9075 "Priority bookkeeping intf_bitmap", 0, rv); 9076 if (BCM_FAILURE(rv)) { 9077 LOG_VERBOSE(BSL_LS_BCM_TSN, 9078 (BSL_META_U(unit, 9079 "bcmi_esw_tsn_pri_map_init: failed to " 9080 "allocate memory\n"))); 9081 return rv; 9082 } 9083 sal_memset(pm_bk_info->intf_bitmap[map_type], 0, shr_bitdcl_size); 9084 9085 /* Allocate data */ 9086 bk_data_size = 9087 sizeof(bcmi_esw_tsn_pri_map_bk_info_data_t) * table_size; 9088 TSN_ALLOC(unit, pm_bk_info->data[map_type], 9089 bcmi_esw_tsn_pri_map_bk_info_data_t, 9090 bk_data_size, 9091 pm_dev_info->table_name, 0, rv); 9092 if (BCM_FAILURE(rv)) { 9093 LOG_VERBOSE(BSL_LS_BCM_TSN, 9094 (BSL_META_U(unit, 9095 "bcmi_esw_tsn_pri_map_init: failed to " 9096 "allocate memory\n"))); 9097 return rv; 9098 } 9099 sal_memset(pm_bk_info->data[map_type], 0, bk_data_size); 9100 9101 /* Initialize default value */ 9102 for (i = 0; i < table_size; i++) { 9103 pm_bk_info->data[map_type][i].map_id = BCM_TSN_PRI_MAP_INVALID; 9104 } 9105 9106 /* Initialize default valid & empty pointer */ 9107 pm_bk_info->valid_count[map_type] = 0; 9108 pm_bk_info->valid_sw_idx_start[map_type] = 0; 9109 pm_bk_info->valid_sw_idx_end[map_type] = 0; 9110 pm_bk_info->empty_sw_idx_start[map_type] = 0; 9111 pm_bk_info->empty_sw_idx_end[map_type] = table_size - 1; 9112 } 9113 9114 /* Create mutex */ 9115 pm_bk_info->mutex = sal_mutex_create("priority_map_mutex"); 9116 if (pm_bk_info->mutex == NULL) { 9117 return BCM_E_MEMORY; 9118 } 9119 9120 /* Create bk_mutex */ 9121 pm_bk_info->bk_mutex = sal_mutex_create("priority_map_bk_mutex"); 9122 if (pm_bk_info->bk_mutex == NULL) { 9123 return BCM_E_MEMORY; 9124 } 9125 9126 /* Create 1st default TSN profile */ 9127 map_type = bcmTsnPriMapTypeTsnFlow; 9128 pm_dev_info = dev_info->tsn_pri_map_info[map_type]; 9129 bcm_tsn_pri_map_config_t_init(&config); 9130 config.map_type = map_type; 9131 config.num_map_entries = pm_dev_info->entry_size; 9132 for (i = 0; i < config.num_map_entries; i++) { 9133 bcm_tsn_pri_map_entry_t_init(&config.map_entries[i]); 9134 config.map_entries[i].flags = BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET; 9135 config.map_entries[i].flags |= BCM_TSN_PRI_MAP_ENTRY_NEW_INT_PRI; 9136 config.map_entries[i].flow_offset = 0; 9137 config.map_entries[i].new_int_pri = i; 9138 } 9139 9140 rv = bcmi_esw_tsn_pri_map_create(unit, &config, &pri_map_id); 9141 if (BCM_FAILURE(rv)) { 9142 LOG_ERROR(BSL_LS_BCM_TSN, 9143 (BSL_META_U(unit, 9144 "create default TSN profile failed(rv = %d)\n"), 9145 rv)); 9146 return rv; 9147 } 9148 9149 #if defined(BCM_TSN_SR_SUPPORT) 9150 if (soc_feature(unit, soc_feature_tsn_sr)) { 9151 /* Create 1st default SR profile */ 9152 map_type = bcmTsnPriMapTypeSrFlow; 9153 pm_dev_info = dev_info->tsn_pri_map_info[map_type]; 9154 bcm_tsn_pri_map_config_t_init(&config); 9155 config.map_type = map_type; 9156 config.num_map_entries = pm_dev_info->entry_size; 9157 for (i = 0; i < config.num_map_entries; i++) { 9158 bcm_tsn_pri_map_entry_t_init(&config.map_entries[i]); 9159 config.map_entries[i].flags = BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET; 9160 config.map_entries[i].flags |= BCM_TSN_PRI_MAP_ENTRY_NEW_INT_PRI; 9161 config.map_entries[i].flow_offset = 0; 9162 config.map_entries[i].new_int_pri = i; 9163 } 9164 9165 rv = bcmi_esw_tsn_pri_map_create(unit, &config, &pri_map_id); 9166 if (BCM_FAILURE(rv)) { 9167 LOG_ERROR(BSL_LS_BCM_TSN, 9168 (BSL_META_U(unit, 9169 "create default SR profile failed" 9170 "(rv = %d)\n"), 9171 rv)); 9172 return rv; 9173 } 9174 } 9175 #endif /* BCM_TSN_SR_SUPPORT */ 9176 9177 if (soc_feature(unit, soc_feature_tsn_taf)) { 9178 /* reserve default taf profile at index 0 */ 9179 PRI_MAP_INTF_SET(unit, bcmTsnPriMapTypeTafGate, 0); 9180 } 9181 return BCM_E_NONE; 9182 } 9183 9184 /* TSN flow: free a chain of one or more continuous flow indexes */ 9185 STATIC int 9186 bcmi_esw_tsn_flow_idx_free(int unit, tsn_flowidx_entry_t *entry) 9187 { 9188 bcmi_esw_tsn_bk_info_t *tsn_bk; 9189 tsn_flows_bookkeeping_t *bkinfo; 9190 tsn_flowidx_entry_t *fid, *prev, *last; 9191 int eidx; 9192 9193 /* parameter check */ 9194 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 9195 if (entry == NULL) { 9196 return BCM_E_PARAM; 9197 } 9198 9199 /* Protect access to the flow indexes */ 9200 TSN_FLOW_MGMT_LOCK(unit); 9201 9202 /* Traverse the list and insert the chain into the list */ 9203 bkinfo = &tsn_bk->tsn_flows; 9204 eidx = entry->flow_idx; 9205 prev = NULL; 9206 for (fid = bkinfo->flowids_avail; fid != NULL; fid = fid->next) { 9207 9208 /* If the index is smaller than current, insert before current */ 9209 if (eidx < fid->flow_idx) { 9210 /* Find the last item in the supplied chain */ 9211 for (last = entry; last->next != NULL; last = last->next); 9212 /* Connect remaining items to the chain */ 9213 last->next = fid; 9214 /* Insert the chain to the list */ 9215 if (NULL == prev) { 9216 bkinfo->flowids_avail = entry; 9217 } else { 9218 prev->next = entry; 9219 } 9220 TSN_FLOW_MGMT_UNLOCK(unit); 9221 return BCM_E_NONE; 9222 } 9223 9224 /* all indexes should be different */ 9225 assert(eidx != fid->flow_idx); 9226 9227 /* record the previous item */ 9228 prev = fid; 9229 } 9230 9231 /* The index is larger than all items in the list, append it at the end */ 9232 if (NULL == prev) { 9233 bkinfo->flowids_avail = entry; 9234 } else { 9235 prev->next = entry; 9236 } 9237 TSN_FLOW_MGMT_UNLOCK(unit); 9238 return BCM_E_NONE; 9239 } 9240 9241 /* TSN flow: allocate one or more continuous flow idx(s) */ 9242 STATIC int 9243 bcmi_esw_tsn_flow_idx_allocate( 9244 int unit, 9245 int count, 9246 tsn_flowidx_entry_t **entry) 9247 { 9248 bcmi_esw_tsn_bk_info_t *tsn_bk; 9249 tsn_flows_bookkeeping_t *bkinfo; 9250 tsn_flowidx_entry_t *fid, *begin, *prev, *bprev; 9251 int idx, bidx; 9252 9253 /* parameter check */ 9254 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 9255 if (count <= 0 || entry == NULL) { 9256 return BCM_E_PARAM; 9257 } 9258 9259 /* Protect access to the flow indexes */ 9260 TSN_FLOW_MGMT_LOCK(unit); 9261 9262 /* Check if any index is available */ 9263 bkinfo = &tsn_bk->tsn_flows; 9264 if (NULL == bkinfo->flowids_avail) { 9265 TSN_FLOW_MGMT_UNLOCK(unit); 9266 return BCM_E_RESOURCE; 9267 } 9268 9269 /* 9270 * Quick retrieval for typical case: count == 1. 9271 */ 9272 if (1 == count) { 9273 /* Get one entry from the head */ 9274 fid = bkinfo->flowids_avail; 9275 bkinfo->flowids_avail = fid->next; 9276 fid->next = NULL; 9277 *entry = fid; 9278 TSN_FLOW_MGMT_UNLOCK(unit); 9279 return BCM_E_NONE; 9280 } 9281 9282 /* Traverse the list and search for enough continuous items to allocate */ 9283 idx = bidx = bkinfo->max_flows; /* invalid current index */ 9284 prev = bprev = begin = NULL; 9285 for (fid = bkinfo->flowids_avail; fid != NULL; fid = fid->next) { 9286 9287 /* Check if it's continuous */ 9288 if (idx + 1 != fid->flow_idx) { 9289 /* Index not continuous, restart the searching */ 9290 idx = fid->flow_idx; 9291 bidx = idx; 9292 begin = fid; 9293 bprev = prev; 9294 } else if (fid->flow_idx - bidx + 1 == count) { 9295 9296 /* 9297 * Found enough continuous flow indexes: update and return 9298 */ 9299 9300 /* Update the linked list by removing the chain from the list */ 9301 if (NULL == bprev) { 9302 /* The chain is the head */ 9303 bkinfo->flowids_avail = fid->next; 9304 } else { 9305 /* Connect previous one to the next of the chain */ 9306 bprev->next = fid->next; 9307 } 9308 9309 /* Terminate this chain and return */ 9310 fid->next = NULL; 9311 *entry = begin; 9312 TSN_FLOW_MGMT_UNLOCK(unit); 9313 return BCM_E_NONE; 9314 9315 } else { 9316 /* continuous but not yet reached the count */ 9317 idx++; 9318 } 9319 9320 /* record the previous one */ 9321 prev = fid; 9322 } 9323 9324 /* Cannot find enough continuous entries */ 9325 TSN_FLOW_MGMT_UNLOCK(unit); 9326 return BCM_E_RESOURCE; 9327 } 9328 9329 /* 9330 * De-allocate a TSN flowset and underlying flows with flowset index 9331 * This function should be called with flowset mutex locked (if made public) 9332 * and ref_count = 0. 9333 */ 9334 STATIC int 9335 bcmi_esw_tsn_flowset_free(int unit, int fsid) 9336 { 9337 bcmi_esw_tsn_bk_info_t *tsn_bk; 9338 tsn_flows_bookkeeping_t *bkinfo; 9339 tsn_flowset_t *fset; 9340 int rv = BCM_E_NONE; 9341 9342 /* parameter check */ 9343 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 9344 bkinfo = &tsn_bk->tsn_flows; 9345 fset = &bkinfo->flowsets[fsid]; 9346 9347 /* Free flow indexes */ 9348 rv = bcmi_esw_tsn_flow_idx_free(unit, fset->flow_ide); 9349 9350 /* Clear flowset data */ 9351 fset->flow_ide = NULL; 9352 fset->num_flows = 0; 9353 9354 return rv; 9355 } 9356 9357 /* 9358 * Function: 9359 * bcmi_esw_tsn_flowset_destroy 9360 * Purpose: 9361 * Destroy a TSN flowset. 9362 * Parameters: 9363 * unit - (IN) unit number 9364 * flowset - (IN) flowset ID 9365 * Returns: 9366 * BCM_E_XXX 9367 * Notes: 9368 */ 9369 STATIC int 9370 bcmi_esw_tsn_flowset_destroy(int unit, bcm_tsn_flowset_t flowset) 9371 { 9372 bcmi_esw_tsn_bk_info_t *tsn_bk; 9373 tsn_flows_bookkeeping_t *bkinfo; 9374 tsn_flowset_t *fset; 9375 int fsid; 9376 int rv = BCM_E_NONE; 9377 int i; 9378 9379 /* parameter check */ 9380 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 9381 bkinfo = &tsn_bk->tsn_flows; 9382 fsid = TSN_FLOWSET_ID_TO_IDX(flowset); 9383 if (fsid < 0 || fsid >= bkinfo->max_flows) { 9384 return BCM_E_PARAM; 9385 } 9386 fset = &bkinfo->flowsets[fsid]; 9387 if (fset->num_flows == 0) { 9388 /* Not allocated */ 9389 return BCM_E_NOT_FOUND; 9390 } 9391 9392 /* Check if it's still in use */ 9393 TSN_FLOWSET_LOCK(fset); 9394 if (fset->ref_count != 0) { 9395 TSN_FLOWSET_UNLOCK(fset); 9396 return BCM_E_BUSY; 9397 } 9398 9399 /* Handle per-flow specific clean up */ 9400 for (i = 0; i < fset->num_flows; i++) { 9401 TSN_FLOW_LOCK(unit, fsid + i); 9402 if (TSN_FLOW_MGMT_DEVINFO(unit)->clear_flow) { 9403 (void)TSN_FLOW_MGMT_DEVINFO(unit)->clear_flow(unit, fsid + i); 9404 } 9405 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 9406 (void)bcmi_esw_tsn_mtu_profile_ref_dec( 9407 unit, bkinfo->flows[fsid + i].ingress_mtu_profile); 9408 } 9409 TSN_FLOW_UNLOCK(unit, fsid + i); 9410 } 9411 9412 /* De-allocate the flowset (note that mutex is always there) */ 9413 rv = bcmi_esw_tsn_flowset_free(unit, fsid); 9414 TSN_FLOWSET_UNLOCK(fset); 9415 return rv; 9416 } 9417 9418 /* Allocate a TSN flowset */ 9419 STATIC int 9420 bcmi_esw_tsn_flowset_alloc( 9421 int unit, 9422 bcm_tsn_pri_map_t pri_map, 9423 int *pfsid) 9424 { 9425 bcmi_esw_tsn_bk_info_t *tsn_bk; 9426 tsn_flows_bookkeeping_t *bkinfo; 9427 bcm_tsn_pri_map_config_t pmcfg; 9428 tsn_flowidx_entry_t *fids; 9429 tsn_flowset_t *fset; 9430 int fsid; 9431 int num_flows; 9432 int rv; 9433 int i; 9434 9435 /* parameter check */ 9436 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 9437 if (pfsid == NULL) { 9438 return BCM_E_PARAM; 9439 } 9440 bkinfo = &tsn_bk->tsn_flows; 9441 9442 /* Get number of flows from this priority map */ 9443 num_flows = 1; 9444 if (pri_map != BCM_TSN_PRI_MAP_INVALID) { 9445 /* call API to get priority map configuration */ 9446 rv = bcm_esw_tsn_pri_map_get(unit, pri_map, &pmcfg); 9447 if (BCM_FAILURE(rv) || pmcfg.map_type != bcmTsnPriMapTypeTsnFlow) { 9448 return BCM_E_PARAM; 9449 } 9450 /* Number of flows is max flow offset + 1 */ 9451 for (i = 0; i < pmcfg.num_map_entries; i++) { 9452 if ((pmcfg.map_entries[i].flags & 9453 BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET) && 9454 (pmcfg.map_entries[i].flow_offset > num_flows - 1)) { 9455 num_flows = pmcfg.map_entries[i].flow_offset + 1; 9456 } 9457 } 9458 } 9459 9460 /* Allocate flow indexes */ 9461 rv = bcmi_esw_tsn_flow_idx_allocate(unit, num_flows, &fids); 9462 if (BCM_FAILURE(rv)) { 9463 return rv; 9464 } 9465 9466 /* 9467 * For efficiency and convenience, the flowset index is the base (first) 9468 * flow index so that we don't need to have another set of flowset 9469 * allocation/free mechanism which would take more time in this time 9470 * critical operation. 9471 */ 9472 fsid = fids->flow_idx; 9473 assert(fsid >= 0 && fsid + num_flows <= bkinfo->max_flows); 9474 9475 /* Write to the flowset */ 9476 fset = &bkinfo->flowsets[fsid]; 9477 TSN_FLOWSET_LOCK(fset); 9478 assert(fset->num_flows == 0); 9479 fset->map_id = pri_map; 9480 fset->flow_ide = fids; 9481 fset->ref_count = 0; 9482 fset->num_flows = num_flows; 9483 TSN_FLOWSET_UNLOCK(fset); 9484 9485 /* Return the allocated flowset index */ 9486 *pfsid = fsid; 9487 return BCM_E_NONE; 9488 } 9489 9490 /* 9491 * Function: 9492 * bcmi_esw_tsn_flowset_create 9493 * Purpose: 9494 * Create a TSN flowset. 9495 * Parameters: 9496 * unit - (IN) unit number 9497 * pri_map - (IN) TSN priority map ID 9498 * def_cfg - (IN) default flow configuration 9499 * flowset - (OUT) flowset ID 9500 * Returns: 9501 * BCM_E_XXX 9502 * Notes: 9503 */ 9504 STATIC int 9505 bcmi_esw_tsn_flowset_create( 9506 int unit, 9507 bcm_tsn_pri_map_t pri_map, 9508 bcm_tsn_flow_config_t *def_cfg, 9509 bcm_tsn_flowset_t *flowset) 9510 { 9511 bcmi_esw_tsn_bk_info_t *tsn_bk; 9512 tsn_flows_bookkeeping_t *bkinfo; 9513 tsn_flowset_t *fset; 9514 bcm_tsn_flowset_t flowset_id; 9515 bcm_tsn_flow_config_t *flow; 9516 int fsid; 9517 int rv = BCM_E_NONE; 9518 int i; 9519 9520 /* parameter check */ 9521 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 9522 if (def_cfg == NULL || flowset == NULL) { 9523 return BCM_E_PARAM; 9524 } 9525 bkinfo = &tsn_bk->tsn_flows; 9526 9527 /* sanity check for platform specific routines */ 9528 if (!TSN_FLOW_MGMT_DEVINFO(unit)->check_flow_config || 9529 !TSN_FLOW_MGMT_DEVINFO(unit)->write_flow) { 9530 return BCM_E_UNAVAIL; 9531 } 9532 9533 /* Validate flow configuration */ 9534 BCM_IF_ERROR_RETURN( 9535 TSN_FLOW_MGMT_DEVINFO(unit)->check_flow_config(unit, def_cfg)); 9536 9537 /* Allocate flows and flowset. Basic init check is also done inside. */ 9538 BCM_IF_ERROR_RETURN( 9539 bcmi_esw_tsn_flowset_alloc(unit, pri_map, &fsid)); 9540 flowset_id = TSN_FLOWSET_ID_FROM_IDX(fsid); 9541 9542 /* Write to the flowset software copy */ 9543 fset = &bkinfo->flowsets[fsid]; 9544 TSN_FLOWSET_LOCK(fset); 9545 sal_memcpy(&fset->config, def_cfg, sizeof(fset->config)); 9546 9547 /* Write to individual flows */ 9548 for (i = 0; i < fset->num_flows; i++) { 9549 TSN_FLOW_LOCK(unit, fsid + i); 9550 flow = &bkinfo->flows[fsid + i]; 9551 9552 /* Store the flow configuration */ 9553 sal_memcpy(flow, def_cfg, sizeof(*flow)); 9554 9555 /* Write to HW */ 9556 rv = TSN_FLOW_MGMT_DEVINFO(unit)->write_flow(unit, fsid + i, flow); 9557 if (BCM_FAILURE(rv)) { 9558 (void)bcmi_esw_tsn_flowset_destroy(unit, flowset_id); 9559 TSN_FLOW_UNLOCK(unit, fsid + i); 9560 TSN_FLOWSET_UNLOCK(fset); 9561 return rv; 9562 } 9563 TSN_FLOW_UNLOCK(unit, fsid + i); 9564 } 9565 TSN_FLOWSET_UNLOCK(fset); 9566 9567 /* Convert to user flowset ID */ 9568 *flowset = flowset_id; 9569 return BCM_E_NONE; 9570 } 9571 9572 /* 9573 * Function: 9574 * bcmi_esw_tsn_flowset_config_get 9575 * Purpose: 9576 * Get default configuration for the specified TSN flowset 9577 * Parameters: 9578 * unit - (IN) unit number 9579 * flowset - (IN) flowset ID 9580 * pri_map - (OUT) TSN priority map ID 9581 * default_config - (OUT) default flow configuration 9582 * Returns: 9583 * BCM_E_XXX 9584 * Notes: 9585 */ 9586 STATIC int 9587 bcmi_esw_tsn_flowset_config_get( 9588 int unit, 9589 bcm_tsn_flowset_t flowset, 9590 bcm_tsn_pri_map_t *pri_map, 9591 bcm_tsn_flow_config_t *config) 9592 { 9593 bcmi_esw_tsn_bk_info_t *tsn_bk; 9594 tsn_flows_bookkeeping_t *bkinfo; 9595 tsn_flowset_t *fset; 9596 int fsid; 9597 9598 /* parameter check */ 9599 if (pri_map == NULL || config == NULL) { 9600 return BCM_E_PARAM; 9601 } 9602 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 9603 bkinfo = &tsn_bk->tsn_flows; 9604 fsid = TSN_FLOWSET_ID_TO_IDX(flowset); 9605 if (fsid < 0 || fsid >= bkinfo->max_flows) { 9606 return BCM_E_PARAM; 9607 } 9608 fset = &bkinfo->flowsets[fsid]; 9609 TSN_FLOWSET_LOCK(fset); 9610 if (fset->num_flows == 0) { 9611 /* Not allocated */ 9612 TSN_FLOWSET_UNLOCK(fset); 9613 return BCM_E_NOT_FOUND; 9614 } 9615 9616 /* Return the value */ 9617 *pri_map = fset->map_id; 9618 sal_memcpy(config, &fset->config, sizeof(fset->config)); 9619 TSN_FLOWSET_UNLOCK(fset); 9620 return BCM_E_NONE; 9621 } 9622 9623 /* 9624 * Function: 9625 * bcmi_esw_tsn_flowset_status_get 9626 * Purpose: 9627 * Get current status of specified TSN flowset 9628 * Parameters: 9629 * unit - (IN) unit number 9630 * flowset - (IN) flowset ID 9631 * status - (OUT) status structure 9632 * Returns: 9633 * BCM_E_XXX 9634 * Notes: 9635 */ 9636 STATIC int 9637 bcmi_esw_tsn_flowset_status_get( 9638 int unit, 9639 bcm_tsn_flowset_t flowset, 9640 bcm_tsn_flowset_status_t *status) 9641 { 9642 bcmi_esw_tsn_bk_info_t *tsn_bk; 9643 tsn_flows_bookkeeping_t *bkinfo; 9644 tsn_flowset_t *fset; 9645 int fsid; 9646 9647 /* parameter check */ 9648 if (status == NULL) { 9649 return BCM_E_PARAM; 9650 } 9651 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 9652 bkinfo = &tsn_bk->tsn_flows; 9653 fsid = TSN_FLOWSET_ID_TO_IDX(flowset); 9654 if (fsid < 0 || fsid >= bkinfo->max_flows) { 9655 return BCM_E_PARAM; 9656 } 9657 fset = &bkinfo->flowsets[fsid]; 9658 TSN_FLOWSET_LOCK(fset); 9659 if (fset->num_flows == 0) { 9660 /* Not allocated */ 9661 TSN_FLOWSET_UNLOCK(fset); 9662 return BCM_E_NOT_FOUND; 9663 } 9664 9665 /* Return the value */ 9666 status->active = fset->ref_count > 0 ? 1 : 0; 9667 status->count = fset->num_flows; 9668 TSN_FLOWSET_UNLOCK(fset); 9669 return BCM_E_NONE; 9670 } 9671 9672 /* 9673 * Function: 9674 * bcmi_esw_tsn_flowset_ref_inc 9675 * Purpose: 9676 * Increase reference count for the specified TSN flowset 9677 * Parameters: 9678 * unit - (IN) unit number 9679 * flowset - (IN) flowset ID 9680 * Returns: 9681 * BCM_E_XXX 9682 * Notes: 9683 */ 9684 int 9685 bcmi_esw_tsn_flowset_ref_inc(int unit, bcm_tsn_flowset_t flowset) 9686 { 9687 bcmi_esw_tsn_bk_info_t *tsn_bk; 9688 tsn_flows_bookkeeping_t *bkinfo; 9689 tsn_flowset_t *fset; 9690 int fsid; 9691 9692 /* parameter check */ 9693 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 9694 bkinfo = &tsn_bk->tsn_flows; 9695 fsid = TSN_FLOWSET_ID_TO_IDX(flowset); 9696 if (fsid < 0 || fsid >= bkinfo->max_flows) { 9697 return BCM_E_PARAM; 9698 } 9699 fset = &bkinfo->flowsets[fsid]; 9700 TSN_FLOWSET_LOCK(fset); 9701 if (fset->num_flows == 0) { 9702 /* Not allocated */ 9703 TSN_FLOWSET_UNLOCK(fset); 9704 return BCM_E_NOT_FOUND; 9705 } 9706 9707 /* Update the reference count */ 9708 fset->ref_count++; 9709 TSN_FLOWSET_UNLOCK(fset); 9710 return BCM_E_NONE; 9711 } 9712 9713 /* 9714 * Function: 9715 * bcmi_esw_tsn_flowset_ref_dec 9716 * Purpose: 9717 * Decrease reference count for the specified TSN flowset 9718 * Parameters: 9719 * unit - (IN) unit number 9720 * flowset - (IN) flowset ID 9721 * Returns: 9722 * BCM_E_XXX 9723 * Notes: 9724 */ 9725 int 9726 bcmi_esw_tsn_flowset_ref_dec(int unit, bcm_tsn_flowset_t flowset) 9727 { 9728 bcmi_esw_tsn_bk_info_t *tsn_bk; 9729 tsn_flows_bookkeeping_t *bkinfo; 9730 tsn_flowset_t *fset; 9731 int fsid; 9732 9733 /* parameter check */ 9734 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 9735 bkinfo = &tsn_bk->tsn_flows; 9736 fsid = TSN_FLOWSET_ID_TO_IDX(flowset); 9737 if (fsid < 0 || fsid >= bkinfo->max_flows) { 9738 return BCM_E_PARAM; 9739 } 9740 fset = &bkinfo->flowsets[fsid]; 9741 TSN_FLOWSET_LOCK(fset); 9742 if (fset->num_flows == 0) { 9743 /* Not allocated */ 9744 TSN_FLOWSET_UNLOCK(fset); 9745 return BCM_E_NOT_FOUND; 9746 } 9747 9748 /* Update the reference count */ 9749 if (fset->ref_count > 0) { 9750 fset->ref_count--; 9751 } 9752 TSN_FLOWSET_UNLOCK(fset); 9753 return BCM_E_NONE; 9754 } 9755 9756 /* 9757 * Function: 9758 * bcmi_esw_tsn_flowset_traverse 9759 * Purpose: 9760 * Traverse all created TSN flowsets 9761 * Parameters: 9762 * unit - (IN) unit number 9763 * cb - (IN) callback function 9764 * user_data - (IN) user data supplied to the callback function 9765 * Returns: 9766 * BCM_E_XXX 9767 * Notes: 9768 */ 9769 STATIC int 9770 bcmi_esw_tsn_flowset_traverse( 9771 int unit, 9772 bcm_tsn_flowset_traverse_cb cb, 9773 void *user_data) 9774 { 9775 bcmi_esw_tsn_bk_info_t *tsn_bk; 9776 tsn_flows_bookkeeping_t *bkinfo; 9777 tsn_flowset_t *fset; 9778 int rv = BCM_E_NONE; 9779 int i; 9780 9781 /* parameter check */ 9782 if (cb == NULL) { 9783 return BCM_E_PARAM; 9784 } 9785 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 9786 9787 /* Loop through the flowset array */ 9788 bkinfo = &tsn_bk->tsn_flows; 9789 for (i = 0; i < bkinfo->max_flows; i++) { 9790 fset = &bkinfo->flowsets[i]; 9791 TSN_FLOWSET_LOCK(fset); 9792 if (fset->num_flows != 0) { 9793 rv = cb(unit, TSN_FLOWSET_ID_FROM_IDX(i), user_data); 9794 } 9795 TSN_FLOWSET_UNLOCK(fset); 9796 BCM_IF_ERROR_RETURN(rv); 9797 } 9798 9799 return BCM_E_NONE; 9800 } 9801 9802 /* 9803 * Function: 9804 * bcmi_esw_tsn_flowset_flow_get 9805 * Purpose: 9806 * Retrieve an individual TSN flow based on the flow offset from a flow set. 9807 * Parameters: 9808 * unit - (IN) unit number 9809 * flowset - (IN) flowset ID 9810 * index - (IN) index of the flow 9811 * flow_id - (OUT) flow ID 9812 * Returns: 9813 * BCM_E_XXX 9814 * Notes: 9815 */ 9816 STATIC int 9817 bcmi_esw_tsn_flowset_flow_get( 9818 int unit, 9819 bcm_tsn_flowset_t flowset, 9820 int index, 9821 bcm_tsn_flow_t *flow_id) 9822 { 9823 bcmi_esw_tsn_bk_info_t *tsn_bk; 9824 tsn_flows_bookkeeping_t *bkinfo; 9825 tsn_flowset_t *fset; 9826 int fsid; 9827 9828 /* parameter check */ 9829 if (flow_id == NULL) { 9830 return BCM_E_PARAM; 9831 } 9832 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 9833 bkinfo = &tsn_bk->tsn_flows; 9834 fsid = TSN_FLOWSET_ID_TO_IDX(flowset); 9835 if (fsid < 0 || fsid >= bkinfo->max_flows) { 9836 return BCM_E_PARAM; 9837 } 9838 fset = &bkinfo->flowsets[fsid]; 9839 TSN_FLOWSET_LOCK(fset); 9840 if (fset->num_flows == 0) { 9841 /* Not allocated */ 9842 TSN_FLOWSET_UNLOCK(fset); 9843 return BCM_E_NOT_FOUND; 9844 } 9845 if (index < 0 || index >= fset->num_flows) { 9846 TSN_FLOWSET_UNLOCK(fset); 9847 return BCM_E_PARAM; 9848 } 9849 assert(fsid + index < bkinfo->max_flows); 9850 9851 /* Got SW flow ID */ 9852 *flow_id = (bcm_tsn_flow_t)TSN_FLOW_ID_FROM_IDX(fsid + index); 9853 TSN_FLOWSET_UNLOCK(fset); 9854 return BCM_E_NONE; 9855 } 9856 9857 /* 9858 * Function: 9859 * bcmi_esw_tsn_flow_config_get 9860 * Purpose: 9861 * Get configuration for the specified TSN flow 9862 * Parameters: 9863 * unit - (IN) unit number 9864 * flow_id - (IN) flow ID 9865 * config - (OUT) flow configuration 9866 * Returns: 9867 * BCM_E_XXX 9868 * Notes: 9869 */ 9870 STATIC int 9871 bcmi_esw_tsn_flow_config_get( 9872 int unit, 9873 bcm_tsn_flow_t flow_id, 9874 bcm_tsn_flow_config_t *config) 9875 { 9876 bcmi_esw_tsn_bk_info_t *tsn_bk; 9877 tsn_flows_bookkeeping_t *bkinfo; 9878 int fidx; 9879 int i; 9880 9881 /* parameter check */ 9882 if (config == NULL) { 9883 return BCM_E_PARAM; 9884 } 9885 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 9886 bkinfo = &tsn_bk->tsn_flows; 9887 fidx = TSN_FLOW_ID_TO_IDX((int)flow_id); 9888 if (fidx < 0 || fidx >= bkinfo->max_flows) { 9889 return BCM_E_PARAM; 9890 } 9891 9892 /* Validate if it's from a flowset */ 9893 for (i = fidx; i >= 0; i--) { 9894 if (bkinfo->flowsets[i].num_flows != 0) { 9895 if (bkinfo->flowsets[i].num_flows > (fidx - i)) { 9896 break; 9897 } else { 9898 return BCM_E_NOT_FOUND; 9899 } 9900 } 9901 } 9902 if (i == -1) { 9903 /* No valid flowsets */ 9904 return BCM_E_NOT_FOUND; 9905 } 9906 9907 /* Return the configuration */ 9908 TSN_FLOW_LOCK(unit, fidx); 9909 sal_memcpy(config, &bkinfo->flows[fidx], sizeof(*config)); 9910 TSN_FLOW_UNLOCK(unit, fidx); 9911 return BCM_E_NONE; 9912 } 9913 9914 /* 9915 * Function: 9916 * bcmi_esw_tsn_flow_config_set 9917 * Purpose: 9918 * Set configuration for the specified TSN flow 9919 * Parameters: 9920 * unit - (IN) unit number 9921 * flow_id - (IN) flow ID 9922 * config - (IN) flow configuration 9923 * Returns: 9924 * BCM_E_XXX 9925 * Notes: 9926 */ 9927 STATIC int 9928 bcmi_esw_tsn_flow_config_set( 9929 int unit, 9930 bcm_tsn_flow_t flow_id, 9931 bcm_tsn_flow_config_t *config) 9932 { 9933 bcmi_esw_tsn_bk_info_t *tsn_bk; 9934 tsn_flows_bookkeeping_t *bkinfo; 9935 tsn_flowset_t *fset; 9936 int fidx; 9937 int rv; 9938 int i; 9939 9940 /* parameter check */ 9941 if (config == NULL) { 9942 return BCM_E_PARAM; 9943 } 9944 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 9945 bkinfo = &tsn_bk->tsn_flows; 9946 fidx = TSN_FLOW_ID_TO_IDX((int)flow_id); 9947 if (fidx < 0 || fidx >= bkinfo->max_flows) { 9948 return BCM_E_PARAM; 9949 } 9950 9951 /* Validate if it's from a flowset */ 9952 fset = NULL; 9953 for (i = fidx; i >= 0; i--) { 9954 if (bkinfo->flowsets[i].num_flows != 0) { 9955 fset = &bkinfo->flowsets[i]; 9956 if (bkinfo->flowsets[i].num_flows > (fidx - i)) { 9957 break; 9958 } else { 9959 return BCM_E_NOT_FOUND; 9960 } 9961 } 9962 } 9963 if (fset == NULL) { 9964 /* No valid flowsets */ 9965 return BCM_E_NOT_FOUND; 9966 } 9967 9968 /* Validate flow configuration */ 9969 if (TSN_FLOW_MGMT_DEVINFO(unit)->check_flow_config) { 9970 rv = TSN_FLOW_MGMT_DEVINFO(unit)->check_flow_config(unit, config); 9971 if (BCM_FAILURE(rv)) { 9972 return rv; 9973 } 9974 } else { 9975 return BCM_E_UNAVAIL; 9976 } 9977 9978 /* 9979 * Configure the flow using the supplied configuration 9980 */ 9981 TSN_FLOWSET_LOCK(fset); 9982 TSN_FLOW_LOCK(unit, fidx); 9983 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 9984 /* Clear the old MTU profile id */ 9985 if (TSN_FLOW_MGMT_DEVINFO(unit)->clear_flow_mtu) { 9986 rv = TSN_FLOW_MGMT_DEVINFO(unit)->clear_flow_mtu( 9987 unit, fidx); 9988 if (BCM_FAILURE(rv)) { 9989 TSN_FLOW_UNLOCK(unit, fidx); 9990 TSN_FLOWSET_UNLOCK(fset); 9991 return rv; 9992 } 9993 } else { 9994 TSN_FLOW_UNLOCK(unit, fidx); 9995 TSN_FLOWSET_UNLOCK(fset); 9996 return BCM_E_UNAVAIL; 9997 } 9998 (void)bcmi_esw_tsn_mtu_profile_ref_dec( 9999 unit, bkinfo->flows[fidx].ingress_mtu_profile); 10000 } 10001 /* Copy to SW flow info */ 10002 sal_memcpy(&bkinfo->flows[fidx], config, sizeof(*config)); 10003 /* Write to HW */ 10004 if (TSN_FLOW_MGMT_DEVINFO(unit)->write_flow) { 10005 rv = TSN_FLOW_MGMT_DEVINFO(unit)->write_flow( 10006 unit, fidx, &bkinfo->flows[fidx]); 10007 if (BCM_FAILURE(rv)) { 10008 TSN_FLOW_UNLOCK(unit, fidx); 10009 TSN_FLOWSET_UNLOCK(fset); 10010 return rv; 10011 } 10012 } else { 10013 TSN_FLOW_UNLOCK(unit, fidx); 10014 TSN_FLOWSET_UNLOCK(fset); 10015 return BCM_E_UNAVAIL; 10016 } 10017 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 10018 (void)bcmi_esw_tsn_mtu_profile_ref_inc( 10019 unit, bkinfo->flows[fidx].ingress_mtu_profile); 10020 } 10021 TSN_FLOW_UNLOCK(unit, fidx); 10022 TSN_FLOWSET_UNLOCK(fset); 10023 return BCM_E_NONE; 10024 } 10025 10026 10027 /* 10028 * Function: 10029 * bcmi_esw_tsn_hw_flow_id_get 10030 * Purpose: 10031 * Convert software TSN flow ID to hardware TSN flow ID 10032 * Parameters: 10033 * unit - (IN) unit number 10034 * flow_id - (IN) SW flow ID 10035 * hw_id - (OUT) HW flow ID 10036 * Returns: 10037 * BCM_E_XXX 10038 * Notes: 10039 */ 10040 int 10041 bcmi_esw_tsn_hw_flow_id_get(int unit, bcm_tsn_flow_t flow_id, uint32 *hw_id) 10042 { 10043 bcmi_esw_tsn_bk_info_t *tsn_bk; 10044 tsn_flows_bookkeeping_t *bkinfo; 10045 int fidx; 10046 10047 /* parameter check */ 10048 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 10049 if (hw_id == NULL) { 10050 return BCM_E_PARAM; 10051 } 10052 bkinfo = &tsn_bk->tsn_flows; 10053 fidx = TSN_FLOW_ID_TO_IDX((int)flow_id); 10054 if (fidx < 0 || fidx >= bkinfo->max_flows) { 10055 return BCM_E_PARAM; 10056 } 10057 10058 /* Call platform specific routine to convert */ 10059 if (!TSN_FLOW_MGMT_DEVINFO(unit)->get_hw_flow_id) { 10060 return BCM_E_UNAVAIL; 10061 } 10062 return TSN_FLOW_MGMT_DEVINFO(unit)->get_hw_flow_id(unit, fidx, hw_id); 10063 } 10064 10065 /* 10066 * Function: 10067 * bcmi_esw_tsn_sw_flow_id_get 10068 * Purpose: 10069 * Convert hardware TSN flow ID to software TSN flow ID 10070 * Parameters: 10071 * unit - (IN) unit number 10072 * hw_id - (IN) HW flow ID 10073 * flow_id - (OUT) SW flow ID 10074 * Returns: 10075 * BCM_E_XXX 10076 * Notes: 10077 */ 10078 int 10079 bcmi_esw_tsn_sw_flow_id_get(int unit, uint32 hw_id, bcm_tsn_flow_t *flow_id) 10080 { 10081 bcmi_esw_tsn_bk_info_t *tsn_bk; 10082 tsn_flows_bookkeeping_t *bkinfo; 10083 const bcmi_esw_tsn_dev_info_t *dev_info; 10084 int fidx; 10085 10086 /* parameter check */ 10087 if (flow_id == NULL) { 10088 return BCM_E_PARAM; 10089 } 10090 10091 if (tsn_bk_info[unit] == NULL) { 10092 /* Using device specific info that need no bk_info */ 10093 BCM_IF_ERROR_RETURN(bcmi_esw_tsn_noninit_dev_info_get(unit, &dev_info)); 10094 if (!dev_info->tsn_flows_info->get_sw_flow_idx) { 10095 return BCM_E_UNAVAIL; 10096 } 10097 BCM_IF_ERROR_RETURN(dev_info->tsn_flows_info->get_sw_flow_idx( 10098 unit, hw_id, &fidx)); 10099 *flow_id = TSN_FLOW_ID_FROM_IDX(fidx); 10100 return BCM_E_NONE; 10101 } 10102 10103 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 10104 bkinfo = &tsn_bk->tsn_flows; 10105 10106 /* Call platform specific routine to convert */ 10107 if (!TSN_FLOW_MGMT_DEVINFO(unit)->get_sw_flow_idx) { 10108 return BCM_E_UNAVAIL; 10109 } 10110 BCM_IF_ERROR_RETURN( 10111 TSN_FLOW_MGMT_DEVINFO(unit)->get_sw_flow_idx(unit, hw_id, &fidx)); 10112 10113 /* Validate converted index */ 10114 if (fidx < 0 || fidx >= bkinfo->max_flows) { 10115 return BCM_E_PARAM; 10116 } 10117 10118 /* Done */ 10119 *flow_id = TSN_FLOW_ID_FROM_IDX(fidx); 10120 return BCM_E_NONE; 10121 } 10122 10123 /* 10124 * Function: 10125 * bcmi_esw_tsn_flowset_identify 10126 * Purpose: 10127 * TSN flow to flowset converstion (identify the flowset based on a flow) 10128 * Parameters: 10129 * unit - (IN) unit number 10130 * flow_id - (IN) flow ID 10131 * flowset - (OUT) flowset ID 10132 * Returns: 10133 * BCM_E_XXX 10134 * Notes: 10135 */ 10136 int 10137 bcmi_esw_tsn_flowset_identify( 10138 int unit, 10139 bcm_tsn_flow_t flow_id, 10140 bcm_tsn_flowset_t *flowset) 10141 { 10142 bcmi_esw_tsn_bk_info_t *tsn_bk; 10143 tsn_flows_bookkeeping_t *bkinfo; 10144 int fidx; 10145 int i; 10146 10147 /* parameter check */ 10148 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 10149 if (flowset == NULL) { 10150 return BCM_E_PARAM; 10151 } 10152 bkinfo = &tsn_bk->tsn_flows; 10153 fidx = TSN_FLOW_ID_TO_IDX((int)flow_id); 10154 if (fidx < 0 || fidx >= bkinfo->max_flows) { 10155 return BCM_E_PARAM; 10156 } 10157 10158 /* Find the flowset */ 10159 for (i = fidx; i >= 0; i--) { 10160 if (bkinfo->flowsets[i].num_flows != 0) { 10161 if (bkinfo->flowsets[i].num_flows > (fidx - i)) { 10162 /* Convert to user flowset ID */ 10163 *flowset = TSN_FLOWSET_ID_FROM_IDX(i); 10164 return BCM_E_NONE; 10165 } else { 10166 /* The flow is not within this flowset */ 10167 return BCM_E_NOT_FOUND; 10168 } 10169 } 10170 } 10171 10172 /* No flowset found with index less then the flow */ 10173 return BCM_E_NOT_FOUND; 10174 } 10175 10176 #ifdef BCM_WARM_BOOT_SUPPORT 10177 /* TSN flow: allocate specified flow idx(s) for warmboot restore */ 10178 STATIC int 10179 bcmi_esw_tsn_flow_idx_restore( 10180 int unit, 10181 int index, 10182 int count, 10183 tsn_flowidx_entry_t **entry) 10184 { 10185 bcmi_esw_tsn_bk_info_t *tsn_bk; 10186 tsn_flows_bookkeeping_t *bkinfo; 10187 tsn_flowidx_entry_t *fid, *prev, *bprev, *begin; 10188 10189 /* parameter check */ 10190 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 10191 if (count <= 0 || entry == NULL) { 10192 return BCM_E_PARAM; 10193 } 10194 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 10195 bkinfo = &tsn_bk->tsn_flows; 10196 10197 /* Protect access to the flow indexes */ 10198 TSN_FLOW_MGMT_LOCK(unit); 10199 10200 /* Traverse the list and search for the specified items */ 10201 begin = NULL; 10202 prev = bprev = NULL; 10203 for (fid = bkinfo->flowids_avail; fid != NULL; fid = fid->next) { 10204 if (fid->flow_idx == index) { 10205 if (begin == NULL) { 10206 /* Found the head */ 10207 begin = fid; 10208 bprev = prev; 10209 } 10210 10211 /* Check if we have got all the items */ 10212 count--; 10213 if (count == 0) { 10214 /* Done. Removing the chain from the list */ 10215 if (NULL == bprev) { 10216 /* The chain was the head */ 10217 bkinfo->flowids_avail = fid->next; 10218 } else { 10219 /* Connect previous one to the next of the chain */ 10220 bprev->next = fid->next; 10221 } 10222 10223 /* Terminate this chain and return */ 10224 fid->next = NULL; 10225 *entry = begin; 10226 TSN_FLOW_MGMT_UNLOCK(unit); 10227 return BCM_E_NONE; 10228 } 10229 index++; 10230 } else if (fid->flow_idx > index) { 10231 /* Not found in this sorted list */ 10232 break; 10233 } 10234 10235 /* record the previous one */ 10236 prev = fid; 10237 } 10238 10239 /* Cannot find the specified item or enough continuous entries */ 10240 TSN_FLOW_MGMT_UNLOCK(unit); 10241 return BCM_E_INTERNAL; 10242 } 10243 10244 /* TSN flow management - warmboot scache size allocation */ 10245 STATIC int 10246 bcmi_esw_tsn_flow_mgmt_wb_alloc(int unit) 10247 { 10248 bcmi_esw_tsn_bk_info_t *tsn_bk; 10249 tsn_flows_bookkeeping_t *bkinfo; 10250 soc_scache_handle_t scache_handle; 10251 uint8 *scache_ptr = NULL; 10252 int stable_size = 0; 10253 int alloc_size; 10254 int rv; 10255 10256 /* parameter check */ 10257 if (!soc_feature(unit, soc_feature_tsn)) { 10258 return BCM_E_UNAVAIL; 10259 } 10260 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 10261 bkinfo = &tsn_bk->tsn_flows; 10262 10263 /* Requires extended scache support level-2 warmboot */ 10264 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 10265 if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 10266 return BCM_E_NONE; 10267 } 10268 10269 /* Calculate allocate size */ 10270 alloc_size = 0; 10271 alloc_size += sizeof(uint16); /* Number of actual flows */ 10272 alloc_size += /* Allocated flows */ 10273 sizeof(tsn_flowset_wb_t) * bkinfo->max_flows; 10274 10275 /* Allocate scache for warmboot */ 10276 SOC_SCACHE_HANDLE_SET(scache_handle, unit, 10277 BCM_MODULE_TSN, BCM_TSN_WB_SCACHE_PART_TSN_FLOWS); 10278 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, TRUE, alloc_size, 10279 &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL); 10280 if (rv == BCM_E_NOT_FOUND) { 10281 /* Proceed with level 1 warmboot */ 10282 rv = BCM_E_NONE; 10283 } 10284 10285 return rv; 10286 } 10287 10288 /* TSN flow management - sync information to scache */ 10289 STATIC int 10290 bcmi_esw_tsn_flow_mgmt_sync(int unit) 10291 { 10292 bcmi_esw_tsn_bk_info_t *tsn_bk; 10293 tsn_flows_bookkeeping_t *bkinfo; 10294 soc_scache_handle_t scache_handle; 10295 uint8 *scache_ptr = NULL, *scache; 10296 tsn_flowset_wb_t tsnflow; 10297 int stable_size = 0; 10298 tsn_flowset_t *fset; 10299 uint16 flows; 10300 int rv; 10301 int i; 10302 10303 /* parameter check */ 10304 if (!soc_feature(unit, soc_feature_tsn)) { 10305 return BCM_E_UNAVAIL; 10306 } 10307 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 10308 bkinfo = &tsn_bk->tsn_flows; 10309 10310 /* Requires extended scache support level-2 warmboot */ 10311 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 10312 if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 10313 return BCM_E_NONE; 10314 } 10315 SOC_SCACHE_HANDLE_SET(scache_handle, unit, 10316 BCM_MODULE_TSN, BCM_TSN_WB_SCACHE_PART_TSN_FLOWS); 10317 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 10318 &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL); 10319 if (rv == BCM_E_NOT_FOUND) { 10320 return BCM_E_NONE; 10321 } 10322 BCM_IF_ERROR_RETURN(rv); 10323 assert(scache_ptr != NULL); 10324 10325 /* Avoid flowsets to be created/destroyed at the same time */ 10326 TSN_FLOW_MGMT_LOCK(unit); 10327 10328 /* Loop through flowsets and save to scache */ 10329 flows = 0; 10330 scache = scache_ptr + sizeof(uint16); 10331 for (i = 0; i < bkinfo->max_flows; i++) { 10332 fset = &bkinfo->flowsets[i]; 10333 TSN_FLOWSET_LOCK(fset); 10334 if (fset->num_flows != 0) { 10335 tsnflow.flow_idx = i; 10336 tsnflow.map_id = fset->map_id; 10337 sal_memcpy(&tsnflow.config, &fset->config, sizeof(tsnflow.config)); 10338 flows++; 10339 sal_memcpy(scache, &tsnflow, sizeof(tsnflow)); 10340 scache += sizeof(tsnflow); 10341 } 10342 TSN_FLOWSET_UNLOCK(fset); 10343 } 10344 sal_memcpy(scache_ptr, &flows, sizeof(uint16)); /* Actual flowsets */ 10345 10346 /* Done */ 10347 TSN_FLOW_MGMT_UNLOCK(unit); 10348 return BCM_E_NONE; 10349 } 10350 10351 /* TSN flow management - reload flow management information from scache */ 10352 STATIC int 10353 bcmi_esw_tsn_flow_mgmt_reload(int unit) 10354 { 10355 bcmi_esw_tsn_bk_info_t *tsn_bk; 10356 tsn_flows_bookkeeping_t *bkinfo; 10357 soc_scache_handle_t scache_handle; 10358 uint8 *scache_ptr = NULL; 10359 tsn_flowset_wb_t tsnflow; 10360 int stable_size = 0; 10361 tsn_flowset_t *fset; 10362 tsn_flowidx_entry_t *flow_ide; 10363 bcm_tsn_pri_map_config_t pmcfg; 10364 uint16 flows, i; 10365 int num_flows; 10366 int rv; 10367 int j, idx; 10368 10369 /* parameter check */ 10370 if (!soc_feature(unit, soc_feature_tsn)) { 10371 return BCM_E_UNAVAIL; 10372 } 10373 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 10374 bkinfo = &tsn_bk->tsn_flows; 10375 if (!TSN_FLOW_MGMT_DEVINFO(unit)->read_flow) { 10376 return BCM_E_UNAVAIL; 10377 } 10378 10379 /* Requires extended scache support level-2 warmboot */ 10380 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 10381 if ((SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit))) { 10382 return BCM_E_NONE; 10383 } 10384 SOC_SCACHE_HANDLE_SET(scache_handle, unit, 10385 BCM_MODULE_TSN, BCM_TSN_WB_SCACHE_PART_TSN_FLOWS); 10386 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, FALSE, 0, 10387 &scache_ptr, BCM_TSN_WB_DEFAULT_VERSION, NULL); 10388 if (rv == BCM_E_NOT_FOUND) { 10389 return BCM_E_NONE; 10390 } 10391 BCM_IF_ERROR_RETURN(rv); 10392 assert(scache_ptr != NULL); 10393 10394 /* Avoid flowsets to be created/destroyed at the same time */ 10395 TSN_FLOW_MGMT_LOCK(unit); 10396 10397 /* Get number of saved flowsets */ 10398 sal_memcpy(&flows, scache_ptr, sizeof(uint16)); 10399 scache_ptr += sizeof(uint16); 10400 10401 /* Restore flowsets */ 10402 for (i = 0; i < flows; i++) { 10403 /* Read from scache */ 10404 sal_memcpy(&tsnflow, scache_ptr, sizeof(tsnflow)); 10405 scache_ptr += sizeof(tsnflow); 10406 10407 /* Validate flow index */ 10408 if (tsnflow.flow_idx < 0 || 10409 tsnflow.flow_idx >= bkinfo->max_flows) { 10410 TSN_FLOW_MGMT_UNLOCK(unit); 10411 return BCM_E_INTERNAL; 10412 } 10413 10414 /* Validate priority map and get number of flows inside this flowset */ 10415 num_flows = 1; 10416 if (tsnflow.map_id != BCM_TSN_PRI_MAP_INVALID) { 10417 /* call API to get priority map configuration */ 10418 rv = bcm_esw_tsn_pri_map_get(unit, tsnflow.map_id, &pmcfg); 10419 if (BCM_FAILURE(rv) || pmcfg.map_type != bcmTsnPriMapTypeTsnFlow) { 10420 TSN_FLOW_MGMT_UNLOCK(unit); 10421 return BCM_E_INTERNAL; 10422 } 10423 /* Number of flows is max flow offset + 1 */ 10424 for (j = 0; j < pmcfg.num_map_entries; j++) { 10425 if ((pmcfg.map_entries[j].flags & 10426 BCM_TSN_PRI_MAP_ENTRY_FLOW_OFFSET) && 10427 (pmcfg.map_entries[j].flow_offset > num_flows - 1)) { 10428 num_flows = pmcfg.map_entries[j].flow_offset + 1; 10429 } 10430 } 10431 } 10432 10433 /* Restore flow index entries */ 10434 rv = bcmi_esw_tsn_flow_idx_restore( 10435 unit, tsnflow.flow_idx, num_flows, &flow_ide); 10436 if (BCM_FAILURE(rv)) { 10437 TSN_FLOW_MGMT_UNLOCK(unit); 10438 return BCM_E_INTERNAL; 10439 } 10440 10441 /* Confirmed that this flowset can be restored */ 10442 fset = &bkinfo->flowsets[tsnflow.flow_idx]; 10443 TSN_FLOWSET_LOCK(fset); 10444 10445 /* Restore the flowset */ 10446 fset->flow_ide = flow_ide; 10447 fset->map_id = tsnflow.map_id; 10448 fset->num_flows = num_flows; 10449 fset->ref_count = 0; 10450 sal_memcpy(&fset->config, &tsnflow.config, sizeof(tsnflow.config)); 10451 10452 /* Restore the individual flows */ 10453 for (j = 0; j < num_flows; j++) { 10454 idx = tsnflow.flow_idx + j; 10455 TSN_FLOW_LOCK(unit, idx); 10456 rv = TSN_FLOW_MGMT_DEVINFO(unit)->read_flow( 10457 unit, idx, &bkinfo->flows[idx]); 10458 if (BCM_FAILURE(rv)) { 10459 TSN_FLOW_UNLOCK(unit, idx); 10460 TSN_FLOWSET_UNLOCK(fset); 10461 TSN_FLOW_MGMT_UNLOCK(unit); 10462 return rv; 10463 } 10464 TSN_FLOW_UNLOCK(unit, idx); 10465 } 10466 10467 /* Done restoring this flowset */ 10468 TSN_FLOWSET_UNLOCK(fset); 10469 } 10470 10471 /* Done */ 10472 TSN_FLOW_MGMT_UNLOCK(unit); 10473 return BCM_E_NONE; 10474 } 10475 #endif /* BCM_WARM_BOOT_SUPPORT */ 10476 10477 /* TSN flow management de-initialization */ 10478 STATIC int 10479 bcmi_esw_tsn_flow_mgmt_detach(int unit) 10480 { 10481 tsn_flows_bookkeeping_t *bkinfo; 10482 int i; 10483 10484 /* parameter check */ 10485 if (!SOC_UNIT_VALID(unit)) { 10486 return BCM_E_UNIT; 10487 } 10488 10489 /* check if it's already cleared */ 10490 bkinfo = &tsn_bk_info[unit]->tsn_flows; 10491 if (NULL == bkinfo) { 10492 return BCM_E_NONE; 10493 } 10494 10495 /* de-allocate flow index pool */ 10496 if (NULL != bkinfo->flowids_allocated) { 10497 sal_free(bkinfo->flowids_allocated); 10498 bkinfo->flowids_allocated = NULL; 10499 } 10500 10501 /* de-allocate flow instances */ 10502 if (NULL != bkinfo->flows) { 10503 sal_free(bkinfo->flows); 10504 bkinfo->flows = NULL; 10505 } 10506 10507 /* de-allocate flow mutexes */ 10508 if (NULL != bkinfo->flows_mutex) { 10509 for (i = 0; i < bkinfo->max_flows; i++) { 10510 if (bkinfo->flows_mutex[i] != NULL) { 10511 sal_mutex_destroy(bkinfo->flows_mutex[i]); 10512 bkinfo->flows_mutex[i] = NULL; 10513 } 10514 } 10515 sal_free(bkinfo->flows_mutex); 10516 bkinfo->flows_mutex = NULL; 10517 } 10518 10519 /* clear flow index linked list */ 10520 bkinfo->flowids_avail = NULL; 10521 10522 /* de-allocate flowset instances */ 10523 if (NULL != bkinfo->flowsets) { 10524 for (i = 0; i < bkinfo->max_flows; i++) { 10525 if (NULL != bkinfo->flowsets[i].mutex) { 10526 sal_mutex_destroy(bkinfo->flowsets[i].mutex); 10527 bkinfo->flowsets[i].mutex = NULL; 10528 } 10529 } 10530 sal_free(bkinfo->flowsets); 10531 bkinfo->flowsets = NULL; 10532 } 10533 10534 /* destroy the flow management mutex */ 10535 if (NULL != bkinfo->fmgmt_mutex) { 10536 sal_mutex_destroy(bkinfo->fmgmt_mutex); 10537 bkinfo->fmgmt_mutex = NULL; 10538 } 10539 10540 return BCM_E_NONE; 10541 } 10542 10543 /* TSN flow management initialization */ 10544 STATIC int 10545 bcmi_esw_tsn_flow_mgmt_init(int unit) 10546 { 10547 bcmi_esw_tsn_bk_info_t *tsn_bk; 10548 tsn_flows_bookkeeping_t *bkinfo; 10549 tsn_flowidx_entry_t *fid; 10550 int maxflows; 10551 int rv; 10552 int i; 10553 10554 /* parameter check */ 10555 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 10556 10557 /* Retrieve number of flows */ 10558 bkinfo = &tsn_bk->tsn_flows; 10559 if (TSN_FLOW_MGMT_DEVINFO(unit) == NULL || 10560 TSN_FLOW_MGMT_DEVINFO(unit)->get_num_flows == NULL) { 10561 return BCM_E_UNAVAIL; 10562 } 10563 rv = TSN_FLOW_MGMT_DEVINFO(unit)->get_num_flows(unit, &maxflows); 10564 if (BCM_FAILURE(rv)) { 10565 return rv; 10566 } 10567 if (maxflows <= 0) { 10568 /* No supported flows */ 10569 return BCM_E_UNAVAIL; 10570 } 10571 bkinfo->max_flows = maxflows; 10572 10573 /* 10574 * We need to minimize the time taken for picking a free flow index. 10575 * To achieve this, we use linked list with pre-allocated entries so that 10576 * we can do it in O(1). 10577 */ 10578 10579 /* Allocate flow index entry pool */ 10580 bkinfo->flowids_allocated = (tsn_flowidx_entry_t *)sal_alloc( 10581 sizeof(tsn_flowidx_entry_t) * maxflows, 10582 "tsn flow ids"); 10583 if (NULL == bkinfo->flowids_allocated) { 10584 LOG_ERROR(BSL_LS_BCM_TSN, 10585 (BSL_META("TSN: failed to allocate flow IDs\n"))); 10586 (void)bcmi_esw_tsn_flow_mgmt_detach(unit); 10587 return BCM_E_MEMORY; 10588 } 10589 10590 /* Initialize flow ID list */ 10591 fid = bkinfo->flowids_allocated; 10592 /* Prepare flow index entry linked list for quick ID allocation */ 10593 for (i = 0; i < bkinfo->max_flows; i++, fid++) { 10594 /* 10595 * Add an entry to the head of the linked list. 10596 * The flow index is going backward so the final list can be in 10597 * increasing order (some allocation requires continuous flows). 10598 */ 10599 fid->flow_idx = bkinfo->max_flows - i - 1; 10600 fid->next = bkinfo->flowids_avail; 10601 bkinfo->flowids_avail = fid; 10602 } 10603 10604 /* Allocate array of flowset and flow instances */ 10605 if (bkinfo->max_flows > 0) { 10606 /* The max number of flowsets should be the same as flows */ 10607 bkinfo->flowsets = (tsn_flowset_t *)sal_alloc( 10608 sizeof(tsn_flowset_t) * bkinfo->max_flows, "tsn flowsets"); 10609 if (NULL == bkinfo->flowsets) { 10610 LOG_ERROR(BSL_LS_BCM_TSN, 10611 (BSL_META("TSN: failed to allocate flowsets\n"))); 10612 (void)bcmi_esw_tsn_flow_mgmt_detach(unit); 10613 return BCM_E_MEMORY; 10614 } 10615 sal_memset(bkinfo->flowsets, 0, 10616 sizeof(tsn_flowset_t) * bkinfo->max_flows); 10617 /* Pre-create mutexes of all flowsets for performance */ 10618 for (i = 0; i < bkinfo->max_flows; i++) { 10619 bkinfo->flowsets[i].mutex = sal_mutex_create("tsn flowset"); 10620 if (NULL == bkinfo->flowsets[i].mutex) { 10621 LOG_ERROR(BSL_LS_BCM_TSN, 10622 (BSL_META("TSN: failed to create flowset mutex\n"))); 10623 (void)bcmi_esw_tsn_flow_mgmt_detach(unit); 10624 return BCM_E_MEMORY; 10625 } 10626 } 10627 10628 /* Allocate array of flow instances and mutexes */ 10629 bkinfo->flows = (bcm_tsn_flow_config_t *)sal_alloc( 10630 sizeof(bcm_tsn_flow_config_t) * maxflows, "tsn flows"); 10631 if (NULL == bkinfo->flows) { 10632 LOG_ERROR(BSL_LS_BCM_TSN, 10633 (BSL_META("TSN: failed to allocate flows\n"))); 10634 (void)bcmi_esw_tsn_flow_mgmt_detach(unit); 10635 return BCM_E_MEMORY; 10636 } 10637 sal_memset(bkinfo->flows, 0, sizeof(bcm_tsn_flow_config_t) * maxflows); 10638 bkinfo->flows_mutex = (sal_mutex_t *)sal_alloc( 10639 sizeof(sal_mutex_t) * maxflows, "tsn flows mutex"); 10640 if (NULL == bkinfo->flows_mutex) { 10641 LOG_ERROR(BSL_LS_BCM_TSN, 10642 (BSL_META("TSN: failed to allocate flow mutexes\n"))); 10643 (void)bcmi_esw_tsn_flow_mgmt_detach(unit); 10644 return BCM_E_MEMORY; 10645 } 10646 for (i = 0; i < maxflows; i++) { 10647 bkinfo->flows_mutex[i] = sal_mutex_create("tsn flow mutex"); 10648 if (NULL == bkinfo->flows_mutex[i]) { 10649 LOG_ERROR(BSL_LS_BCM_TSN, 10650 (BSL_META("TSN: failed to create flow mutex\n"))); 10651 (void)bcmi_esw_tsn_flow_mgmt_detach(unit); 10652 return BCM_E_MEMORY; 10653 } 10654 } 10655 } 10656 10657 /* Create mutex for protecting flow management (allocate/free) */ 10658 bkinfo->fmgmt_mutex = sal_mutex_create("tsn flow mgmt"); 10659 if (NULL == bkinfo->fmgmt_mutex) { 10660 LOG_ERROR(BSL_LS_BCM_TSN, 10661 (BSL_META("TSN: failed to create flow mgmt mutex\n"))); 10662 (void)bcmi_esw_tsn_flow_mgmt_detach(unit); 10663 return BCM_E_MEMORY; 10664 } 10665 10666 return BCM_E_NONE; 10667 } 10668 10669 /* 10670 * Function: 10671 * bcmi_esw_tsn_mtu_profile_ref_inc 10672 * Purpose: 10673 * Increase the reference count for the 10674 * specific mtu profile ID 10675 * Parameters: 10676 * unit - (IN) Unit number 10677 * mtu_profile_id - (IN) profile ID 10678 * Returns: 10679 * BCM_E_xxx 10680 */ 10681 int 10682 bcmi_esw_tsn_mtu_profile_ref_inc( 10683 int unit, 10684 int mtu_profile_id) 10685 { 10686 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 10687 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 10688 const tsn_mtu_info_t *ctrl_info = NULL; 10689 10690 int index, rv, min, max; 10691 bcm_tsn_mtu_profile_type_t type; 10692 10693 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 10694 dev_info = bk_info->tsn_dev_info; 10695 /* Use this init macro after the bk info instance get */ 10696 MTU_DEV_INIT(unit); 10697 ctrl_info = dev_info->tsn_mtu_info; 10698 10699 /* this function also check the validity of parameter profile id */ 10700 MTU_BK_LOCK(unit); 10701 rv = ctrl_info->mtu_profile_decode(unit, mtu_profile_id, &type, &index); 10702 if (BCM_FAILURE(rv)) { 10703 MTU_BK_UNLOCK(unit); 10704 return rv; 10705 } 10706 10707 /* index 0 in profile memory is the default value */ 10708 if (index == 0) { 10709 MTU_BK_UNLOCK(unit); 10710 return BCM_E_NONE; 10711 } 10712 10713 MTU_BK_INIT(unit, type); 10714 ctrl_info->mtu_profile_mem_idx_get(unit, type, &min, &max); 10715 if (index < min || index > max) { 10716 MTU_BK_UNLOCK(unit); 10717 return BCM_E_PARAM; 10718 } 10719 bk_info->tsn_mtu_bk_info.mtu_refcount[type][index]++; 10720 MTU_BK_UNLOCK(unit); 10721 return BCM_E_NONE; 10722 } 10723 10724 /* 10725 * Function: 10726 * bcmi_esw_tsn_mtu_profile_ref_dec 10727 * Purpose: 10728 * Decrease the reference count of the 10729 * specific mtu profile ID 10730 * Parameters: 10731 * unit - (IN) Unit number 10732 * mtu_profile_id - (IN) profile ID 10733 * Returns: 10734 * BCM_E_xxx 10735 */ 10736 int 10737 bcmi_esw_tsn_mtu_profile_ref_dec( 10738 int unit, 10739 int mtu_profile_id) 10740 { 10741 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 10742 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 10743 const tsn_mtu_info_t *ctrl_info = NULL; 10744 10745 int index, rv, min, max; 10746 bcm_tsn_mtu_profile_type_t type; 10747 10748 /* Check whether the module is being detached */ 10749 if (tsn_bk_info[unit] == NULL && tsn_bk_info_initialized == 1) { 10750 return BCM_E_NONE; 10751 } 10752 10753 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 10754 dev_info = bk_info->tsn_dev_info; 10755 /* Use this init macro after the bk info instance get */ 10756 MTU_DEV_INIT(unit); 10757 ctrl_info = dev_info->tsn_mtu_info; 10758 10759 /* this function also check the validity of parameter profile id */ 10760 MTU_BK_LOCK(unit); 10761 rv = ctrl_info->mtu_profile_decode(unit, mtu_profile_id, &type, &index); 10762 if (BCM_FAILURE(rv)) { 10763 MTU_BK_UNLOCK(unit); 10764 return rv; 10765 } 10766 10767 /* index 0 in profile memory is the default value */ 10768 if (index == 0) { 10769 MTU_BK_UNLOCK(unit); 10770 return BCM_E_NONE; 10771 } 10772 10773 MTU_BK_INIT(unit, type); 10774 /* Cannot minus the reference count that is already 0 */ 10775 ctrl_info->mtu_profile_mem_idx_get(unit, type, &min, &max); 10776 if (index < min || index > max) { 10777 MTU_BK_UNLOCK(unit); 10778 return BCM_E_PARAM; 10779 } 10780 if (bk_info->tsn_mtu_bk_info.mtu_refcount[type][index] == 0) { 10781 MTU_BK_UNLOCK(unit); 10782 return BCM_E_PARAM; 10783 } 10784 10785 bk_info->tsn_mtu_bk_info.mtu_refcount[type][index]--; 10786 MTU_BK_UNLOCK(unit); 10787 return BCM_E_NONE; 10788 } 10789 10790 /* 10791 * Function: 10792 * bcmi_esw_tsn_stu_profile_ref_inc 10793 * Purpose: 10794 * Increase the reference count for the 10795 * specific stu profile ID 10796 * Parameters: 10797 * unit - (IN) Unit number 10798 * stu_profile_id - (IN) profile ID 10799 * Returns: 10800 * BCM_E_xxx 10801 */ 10802 int 10803 bcmi_esw_tsn_stu_profile_ref_inc( 10804 int unit, 10805 int stu_profile_id) 10806 { 10807 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 10808 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 10809 const tsn_stu_info_t *ctrl_info = NULL; 10810 10811 int index, rv, min, max; 10812 bcm_tsn_stu_profile_type_t type; 10813 10814 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 10815 dev_info = bk_info->tsn_dev_info; 10816 /* Use this init macro after the bk info instance get */ 10817 STU_DEV_INIT(unit); 10818 ctrl_info = dev_info->tsn_stu_info; 10819 10820 /* this function also check the validity of parameter profile id */ 10821 STU_BK_LOCK(unit); 10822 rv = ctrl_info->stu_profile_decode(unit, stu_profile_id, &type, &index); 10823 if (BCM_FAILURE(rv)) { 10824 STU_BK_UNLOCK(unit); 10825 return rv; 10826 } 10827 10828 /* index 0 in profile memory is the default value */ 10829 if (index == 0) { 10830 STU_BK_UNLOCK(unit); 10831 return BCM_E_NONE; 10832 } 10833 10834 STU_BK_INIT(unit, type); 10835 ctrl_info->stu_profile_mem_idx_get(unit, type, &min, &max); 10836 if (index < min || index > max) { 10837 STU_BK_UNLOCK(unit); 10838 return BCM_E_PARAM; 10839 } 10840 bk_info->tsn_stu_bk_info.stu_refcount[type][index]++; 10841 STU_BK_UNLOCK(unit); 10842 return BCM_E_NONE; 10843 } 10844 10845 /* 10846 * Function: 10847 * bcmi_esw_tsn_stu_profile_ref_dec 10848 * Purpose: 10849 * Decrease the reference count for the 10850 * specific stu profile ID 10851 * Parameters: 10852 * unit - (IN) Unit number 10853 * stu_profile_id - (IN) profile ID 10854 * Returns: 10855 * BCM_E_xxx 10856 */ 10857 int 10858 bcmi_esw_tsn_stu_profile_ref_dec( 10859 int unit, 10860 int stu_profile_id) 10861 { 10862 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 10863 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 10864 const tsn_stu_info_t *ctrl_info = NULL; 10865 10866 int index, rv, min, max; 10867 bcm_tsn_stu_profile_type_t type; 10868 10869 /* Check whether the module is being detached */ 10870 if (tsn_bk_info[unit] == NULL && tsn_bk_info_initialized == 1) { 10871 return BCM_E_NONE; 10872 } 10873 10874 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 10875 dev_info = bk_info->tsn_dev_info; 10876 /* Use this init macro after the bk info instance get */ 10877 STU_DEV_INIT(unit); 10878 ctrl_info = dev_info->tsn_stu_info; 10879 10880 /* this function also check the validity of parameter profile id */ 10881 STU_BK_LOCK(unit); 10882 rv = ctrl_info->stu_profile_decode(unit, stu_profile_id, &type, &index); 10883 if (BCM_FAILURE(rv)) { 10884 STU_BK_UNLOCK(unit); 10885 return rv; 10886 } 10887 10888 /* index 0 in profile memory is the default value */ 10889 if (index == 0) { 10890 STU_BK_UNLOCK(unit); 10891 return BCM_E_NONE; 10892 } 10893 10894 STU_BK_INIT(unit, type); 10895 /* Cannot minus the reference count that is already 0 */ 10896 ctrl_info->stu_profile_mem_idx_get(unit, type, &min, &max); 10897 if (index < min || index > max) { 10898 STU_BK_UNLOCK(unit); 10899 return BCM_E_PARAM; 10900 } 10901 if (bk_info->tsn_stu_bk_info.stu_refcount[type][index] == 0) { 10902 STU_BK_UNLOCK(unit); 10903 return BCM_E_PARAM; 10904 } 10905 10906 bk_info->tsn_stu_bk_info.stu_refcount[type][index]--; 10907 STU_BK_UNLOCK(unit); 10908 return BCM_E_NONE; 10909 } 10910 10911 /* 10912 * Function: 10913 * bcmi_esw_tsn_mtu_hw_profile_id_get 10914 * Purpose: 10915 * Convert software mtu profile ID to hardware mtu profile ID 10916 * Parameters: 10917 * unit - (IN) unit number 10918 * mtu_profile_id - (IN) SW profile ID 10919 * hw_profile_id - (OUT) HW profile ID 10920 * Returns: 10921 * BCM_E_XXX 10922 * Notes: 10923 */ 10924 int 10925 bcmi_esw_tsn_mtu_hw_profile_id_get( 10926 int unit, 10927 int mtu_profile_id, 10928 bcm_tsn_mtu_profile_type_t *type, 10929 int *hw_profile_id) 10930 { 10931 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 10932 const tsn_mtu_info_t *ctrl_info = NULL; 10933 int rv; 10934 10935 if (hw_profile_id == NULL || type == NULL) { 10936 return BCM_E_UNAVAIL; 10937 } 10938 10939 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 10940 /* Use this init macro after the bk info instance get */ 10941 MTU_DEV_INIT(unit); 10942 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 10943 MTU_BK_LOCK(unit); 10944 rv = ctrl_info->mtu_profile_decode(unit, mtu_profile_id, 10945 type, hw_profile_id); 10946 if (BCM_FAILURE(rv)) { 10947 MTU_BK_UNLOCK(unit); 10948 return rv; 10949 } 10950 MTU_BK_UNLOCK(unit); 10951 10952 return BCM_E_NONE; 10953 10954 } 10955 10956 /* 10957 * Function: 10958 * bcmi_esw_tsn_mtu_sw_profile_id_get 10959 * Purpose: 10960 * Convert hardware mtu profile ID to software mtu profile ID 10961 * Parameters: 10962 * unit - (IN) unit number 10963 * hw_profile_id - (IN) HW profile ID 10964 * mtu_profile_id - (OUT) SW profile ID 10965 * Returns: 10966 * BCM_E_XXX 10967 * Notes: 10968 */ 10969 int 10970 bcmi_esw_tsn_mtu_sw_profile_id_get( 10971 int unit, 10972 bcm_tsn_mtu_profile_type_t type, 10973 int hw_profile_id, 10974 int *mtu_profile_id) 10975 { 10976 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 10977 const tsn_mtu_info_t *ctrl_info = NULL; 10978 const bcmi_esw_tsn_dev_info_t *dev_info; 10979 int rv; 10980 10981 if (mtu_profile_id == NULL) { 10982 return BCM_E_UNAVAIL; 10983 } 10984 10985 if (type != bcmTsnMtuProfileTypeIngress && 10986 type != bcmTsnMtuProfileTypeEgress) { 10987 LOG_VERBOSE(BSL_LS_BCM_TSN, 10988 (BSL_META_U(unit, "Wrong Profile Type.\n"))); 10989 return BCM_E_UNAVAIL; 10990 } 10991 10992 if (tsn_bk_info[unit] == NULL) { 10993 /* Using device specific info that need no bk_info */ 10994 BCM_IF_ERROR_RETURN(bcmi_esw_tsn_noninit_dev_info_get(unit, &dev_info)); 10995 if (NULL == dev_info->tsn_mtu_info->mtu_profile_encode) { 10996 return BCM_E_UNAVAIL; 10997 } 10998 rv = dev_info->tsn_mtu_info->mtu_profile_encode(unit, hw_profile_id, 10999 type, mtu_profile_id); 11000 return BCM_E_NONE; 11001 } 11002 11003 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11004 /* Use this init macro after the bk info instance get */ 11005 MTU_DEV_INIT(unit); 11006 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 11007 11008 MTU_BK_LOCK(unit); 11009 rv = ctrl_info->mtu_profile_encode(unit, hw_profile_id, 11010 type, mtu_profile_id); 11011 if (BCM_FAILURE(rv)) { 11012 MTU_BK_UNLOCK(unit); 11013 return rv; 11014 } 11015 MTU_BK_UNLOCK(unit); 11016 11017 return BCM_E_NONE; 11018 11019 } 11020 11021 /* 11022 * Function: 11023 * bcmi_esw_tsn_stu_hw_profile_id_get 11024 * Purpose: 11025 * Convert software stu profile ID to hardware stu profile ID 11026 * Parameters: 11027 * unit - (IN) unit number 11028 * stu_profile_id - (IN) SW profile ID 11029 * hw_profile_id - (OUT) HW profile ID 11030 * Returns: 11031 * BCM_E_XXX 11032 * Notes: 11033 */ 11034 int 11035 bcmi_esw_tsn_stu_hw_profile_id_get( 11036 int unit, 11037 int stu_profile_id, 11038 bcm_tsn_stu_profile_type_t *type, 11039 int *hw_profile_id) 11040 11041 { 11042 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11043 const tsn_stu_info_t *ctrl_info = NULL; 11044 int rv; 11045 11046 if (hw_profile_id == NULL || type == NULL) { 11047 return BCM_E_UNAVAIL; 11048 } 11049 11050 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11051 /* Use this init macro after the bk info instance get */ 11052 STU_DEV_INIT(unit); 11053 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 11054 STU_BK_LOCK(unit); 11055 rv = ctrl_info->stu_profile_decode(unit, stu_profile_id, 11056 type, hw_profile_id); 11057 if (BCM_FAILURE(rv)) { 11058 STU_BK_UNLOCK(unit); 11059 return rv; 11060 } 11061 STU_BK_UNLOCK(unit); 11062 11063 return BCM_E_NONE; 11064 } 11065 11066 /* 11067 * Function: 11068 * bcmi_esw_tsn_stu_sw_profile_id_get 11069 * Purpose: 11070 * Convert hardware stu profile ID to software stu profile ID 11071 * Parameters: 11072 * unit - (IN) unit number 11073 * hw_profile_id - (IN) HW profile ID 11074 * stu_profile_id - (OUT) SW profile ID 11075 * Returns: 11076 * BCM_E_XXX 11077 * Notes: 11078 */ 11079 int 11080 bcmi_esw_tsn_stu_sw_profile_id_get( 11081 int unit, 11082 bcm_tsn_stu_profile_type_t type, 11083 int hw_profile_id, 11084 int *stu_profile_id) 11085 { 11086 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11087 const tsn_stu_info_t *ctrl_info = NULL; 11088 const bcmi_esw_tsn_dev_info_t *dev_info; 11089 int rv; 11090 11091 if (stu_profile_id == NULL) { 11092 return BCM_E_UNAVAIL; 11093 } 11094 11095 if (type != bcmTsnStuProfileTypeIngress && 11096 type != bcmTsnStuProfileTypeEgress) { 11097 LOG_VERBOSE(BSL_LS_BCM_TSN, 11098 (BSL_META_U(unit, "Wrong Profile Type.\n"))); 11099 return BCM_E_UNAVAIL; 11100 } 11101 11102 if (tsn_bk_info[unit] == NULL) { 11103 /* Using device specific info that need no nk_info */ 11104 BCM_IF_ERROR_RETURN(bcmi_esw_tsn_noninit_dev_info_get(unit, &dev_info)); 11105 if (NULL == dev_info->tsn_stu_info->stu_profile_encode) { 11106 return BCM_E_UNAVAIL; 11107 } 11108 rv = dev_info->tsn_stu_info->stu_profile_encode(unit, hw_profile_id, 11109 type, stu_profile_id); 11110 return BCM_E_NONE; 11111 } 11112 11113 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11114 /* Use this init macro after the bk info instance get */ 11115 STU_DEV_INIT(unit); 11116 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 11117 11118 STU_BK_LOCK(unit); 11119 rv = ctrl_info->stu_profile_encode(unit, hw_profile_id, 11120 type, stu_profile_id); 11121 if (BCM_FAILURE(rv)) { 11122 STU_BK_UNLOCK(unit); 11123 return rv; 11124 } 11125 STU_BK_UNLOCK(unit); 11126 11127 return BCM_E_NONE; 11128 } 11129 11130 11131 /* 11132 * Function: 11133 * bcmi_esw_tsn_mtu_profile_get 11134 * Purpose: 11135 * Get mtu profile configuration 11136 * with the profile id. 11137 * Parameters: 11138 * unit - (IN) Unit number 11139 * mtu_profile_id - (IN) Indicated the mtu profile entry 11140 * type - (OUT) Indicates ingress or egress mtu profile 11141 * config - (OUT) Configuration of the mtu profile 11142 * Returns: 11143 * BCM_E_xxx 11144 */ 11145 int 11146 bcmi_esw_tsn_mtu_profile_get( 11147 int unit, 11148 int mtu_profile_id, 11149 bcm_tsn_mtu_profile_type_t *type, 11150 bcm_tsn_mtu_config_t *config) 11151 { 11152 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11153 const tsn_mtu_info_t *ctrl_info = NULL; 11154 11155 int index, rv; 11156 11157 if (type == NULL || config == NULL) { 11158 return BCM_E_PARAM; 11159 } 11160 11161 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11162 /* Use this init macro after the bk info instance get */ 11163 MTU_DEV_INIT(unit); 11164 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 11165 MTU_BK_LOCK(unit); 11166 /* this function also check the validity of parameter profile id */ 11167 rv = ctrl_info->mtu_profile_decode(unit, mtu_profile_id, type, &index); 11168 if (BCM_FAILURE(rv)) { 11169 MTU_BK_UNLOCK(unit); 11170 return rv; 11171 } 11172 rv = ctrl_info->mtu_profile_get(unit, index, *type, config); 11173 if (BCM_FAILURE(rv)) { 11174 MTU_BK_UNLOCK(unit); 11175 return rv; 11176 } 11177 MTU_BK_UNLOCK(unit); 11178 return BCM_E_NONE; 11179 } 11180 11181 /* 11182 * Function: 11183 * bcmi_esw_tsn_mtu_profile_set 11184 * Purpose: 11185 * Set mtu profile with the profile id 11186 * and config parameter. 11187 * Parameters: 11188 * unit - (IN) Unit number 11189 * mtu_profile_id - (IN) Indicated the mtu profile entry 11190 * config - (IN) Configuration of the mtu profile 11191 * Returns: 11192 * BCM_E_xxx 11193 */ 11194 int 11195 bcmi_esw_tsn_mtu_profile_set( 11196 int unit, 11197 int mtu_profile_id, 11198 bcm_tsn_mtu_config_t *config) 11199 { 11200 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11201 const tsn_mtu_info_t *ctrl_info = NULL; 11202 11203 int index, ref_count, rv, min, max; 11204 bcm_tsn_mtu_profile_type_t type; 11205 11206 if (config == NULL) { 11207 return BCM_E_PARAM; 11208 } 11209 11210 if (config->size <= 0) { 11211 LOG_ERROR(BSL_LS_BCM_TSN, 11212 (BSL_META_U(unit, "Invalid MTU size.\n"))); 11213 return BCM_E_PARAM; 11214 } 11215 11216 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11217 /* Use this init macro after the bk info instance get */ 11218 MTU_DEV_INIT(unit); 11219 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 11220 11221 MTU_BK_LOCK(unit); 11222 /* this function also check the validity of parameter profile id */ 11223 rv = ctrl_info->mtu_profile_decode(unit, mtu_profile_id, &type, &index); 11224 if (BCM_FAILURE(rv)) { 11225 MTU_BK_UNLOCK(unit); 11226 return rv; 11227 } 11228 11229 /* index 0 in profile memory is the default value */ 11230 if (index == 0) { 11231 MTU_BK_UNLOCK(unit); 11232 LOG_WARN(BSL_LS_BCMAPI_TSN, 11233 (BSL_META_U( 11234 unit, "Profile ID 0 is the default, can't modify it.\n"))); 11235 return BCM_E_PARAM; 11236 } 11237 11238 rv = ctrl_info->mtu_profile_mem_refcnt_get(unit, type, index, &ref_count); 11239 if (BCM_FAILURE(rv)) { 11240 MTU_BK_UNLOCK(unit); 11241 return rv; 11242 } 11243 /* ref_count > 0, then the entry is created */ 11244 if (ref_count <= 0) { 11245 MTU_BK_UNLOCK(unit); 11246 LOG_WARN(BSL_LS_BCMAPI_TSN, 11247 (BSL_META_U(unit, 11248 "NTU Profile entry is not created.\n"))); 11249 return BCM_E_PARAM; 11250 } 11251 11252 /* the profile entry is referenced by other flows */ 11253 MTU_BK_INIT(unit, type); 11254 ctrl_info->mtu_profile_mem_idx_get(unit, type, &min, &max); 11255 if (index < min || index > max) { 11256 MTU_BK_UNLOCK(unit); 11257 return BCM_E_PARAM; 11258 } 11259 if (bk_info->tsn_mtu_bk_info.mtu_refcount[type][index] > 0) { 11260 MTU_BK_UNLOCK(unit); 11261 LOG_WARN(BSL_LS_BCMAPI_TSN, 11262 (BSL_META_U(unit, 11263 "Flow is in use of Ingress MTU Profile\n"))); 11264 return BCM_E_BUSY; 11265 } 11266 11267 rv = ctrl_info->mtu_profile_set(unit, index, type, config); 11268 if (BCM_FAILURE(rv)) { 11269 MTU_BK_UNLOCK(unit); 11270 return rv; 11271 } 11272 MTU_BK_UNLOCK(unit); 11273 return BCM_E_NONE; 11274 } 11275 11276 /* 11277 * Function: 11278 * bcmi_esw_tsn_mtu_profile_destroy 11279 * Purpose: 11280 * Clear the mtu profile with the profile id 11281 * Parameters: 11282 * unit - (IN) Unit number 11283 * mtu_profile_id - (IN) Indicated the mtu profile entry 11284 * Returns: 11285 * BCM_E_xxx 11286 */ 11287 int 11288 bcmi_esw_tsn_mtu_profile_destroy( 11289 int unit, 11290 int mtu_profile_id) 11291 { 11292 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11293 const tsn_mtu_info_t *ctrl_info = NULL; 11294 11295 bcm_tsn_mtu_profile_type_t type; 11296 int index, rv, min, max; 11297 11298 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11299 /* Use this init macro after the bk info instance get */ 11300 MTU_DEV_INIT(unit); 11301 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 11302 11303 /* this function also check the validity of parameter profile id */ 11304 MTU_BK_LOCK(unit); 11305 rv = ctrl_info->mtu_profile_decode(unit, mtu_profile_id, &type, &index); 11306 if (BCM_FAILURE(rv)) { 11307 MTU_BK_UNLOCK(unit); 11308 return rv; 11309 } 11310 11311 /* index 0 in profile memory is the default value */ 11312 if (index == 0) { 11313 MTU_BK_UNLOCK(unit); 11314 LOG_WARN(BSL_LS_BCMAPI_TSN, 11315 (BSL_META_U( 11316 unit, "Profile ID 0 is the default, can't modify it.\n"))); 11317 return BCM_E_PARAM; 11318 } 11319 11320 rv = ctrl_info->mtu_profile_mem_idx_get(unit, type, &min, &max); 11321 if (BCM_FAILURE(rv)) { 11322 MTU_BK_UNLOCK(unit); 11323 return rv; 11324 } 11325 MTU_BK_INIT(unit, type); 11326 /* the profile entry is referenced bt other flows */ 11327 if (index < min || index > max) { 11328 MTU_BK_UNLOCK(unit); 11329 return BCM_E_PARAM; 11330 } 11331 if (bk_info->tsn_mtu_bk_info.mtu_refcount[type][index] != 0) { 11332 MTU_BK_UNLOCK(unit); 11333 LOG_WARN(BSL_LS_BCMAPI_TSN, 11334 (BSL_META_U(unit, 11335 "Flow is in use of Ingress MTU Profile\n"))); 11336 return BCM_E_EXISTS; 11337 } 11338 11339 rv = ctrl_info->mtu_profile_destroy(unit, type, index); 11340 MTU_BK_UNLOCK(unit); 11341 11342 return rv; 11343 } 11344 11345 /* 11346 * Function: 11347 * bcmi_esw_tsn_mtu_profile_create 11348 * Purpose: 11349 * Create mtu profile with the config pointer 11350 * and return the assigned profile id. 11351 * Parameters: 11352 * unit - (IN) Unit number 11353 * type - (IN) Indicates ingress or egress mtu profile 11354 * config - (IN) configuration of the mtu profile 11355 * mtu_profile_id - (OUT) profile id 11356 * Returns: 11357 * BCM_E_xxx 11358 */ 11359 int 11360 bcmi_esw_tsn_mtu_profile_create( 11361 int unit, 11362 bcm_tsn_mtu_profile_type_t type, 11363 bcm_tsn_mtu_config_t *config, 11364 int *mtu_profile_id) 11365 { 11366 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11367 const tsn_mtu_info_t *ctrl_info = NULL; 11368 11369 int ref_count, rv, rv1; 11370 uint32 index; 11371 11372 if (config == NULL || mtu_profile_id == NULL) { 11373 return BCM_E_PARAM; 11374 } 11375 11376 if (config->size <= 0) { 11377 LOG_ERROR(BSL_LS_BCM_TSN, 11378 (BSL_META_U(unit, "Invalid MTU size.\n"))); 11379 return BCM_E_PARAM; 11380 } 11381 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11382 /* Use this init macro after the bk info instance get */ 11383 MTU_DEV_INIT(unit); 11384 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 11385 11386 /* Check the validity of the type */ 11387 if (type != bcmTsnMtuProfileTypeIngress && 11388 type != bcmTsnMtuProfileTypeEgress) { 11389 LOG_VERBOSE(BSL_LS_BCM_TSN, 11390 (BSL_META_U(unit, "Wrong Profile Type.\n"))); 11391 return BCM_E_PARAM; 11392 } 11393 11394 MTU_BK_LOCK(unit); 11395 rv = ctrl_info->mtu_profile_create(unit, type, config, &index); 11396 if (BCM_FAILURE(rv)) { 11397 MTU_BK_UNLOCK(unit); 11398 return rv; 11399 } 11400 rv = ctrl_info->mtu_profile_mem_refcnt_get(unit, type, index, &ref_count); 11401 if (BCM_FAILURE(rv)) { 11402 rv1 = ctrl_info->mtu_profile_destroy(unit, type, index); 11403 if (BCM_FAILURE(rv1)) { 11404 MTU_BK_UNLOCK(unit); 11405 return rv1; 11406 } 11407 MTU_BK_UNLOCK(unit); 11408 return rv; 11409 } 11410 11411 /* Encode the mtu profile id */ 11412 rv = ctrl_info->mtu_profile_encode(unit, index, type, mtu_profile_id); 11413 if (BCM_FAILURE(rv)) { 11414 rv1 = ctrl_info->mtu_profile_destroy(unit, type, index); 11415 if (BCM_FAILURE(rv1)) { 11416 MTU_BK_UNLOCK(unit); 11417 return rv1; 11418 } 11419 MTU_BK_UNLOCK(unit); 11420 return rv; 11421 } 11422 11423 /* ref_count > 1 indicates replicated mtu profile is created */ 11424 if (ref_count > 1) { 11425 if (type == bcmTsnMtuProfileTypeIngress) { 11426 LOG_WARN(BSL_LS_BCMAPI_TSN, 11427 (BSL_META_U(unit, 11428 "config already existed, " 11429 "found ingress mtu profile id(%d)\n"), 11430 *mtu_profile_id)); 11431 } else { 11432 LOG_WARN(BSL_LS_BCMAPI_TSN, 11433 (BSL_META_U(unit, 11434 "config already existed, " 11435 "found egress mtu profile id(%d)\n"), 11436 *mtu_profile_id)); 11437 } 11438 } 11439 11440 MTU_BK_UNLOCK(unit); 11441 return BCM_E_NONE; 11442 } 11443 /* 11444 * Function: 11445 * bcmi_esw_tsn_mtu_profile_traverse 11446 * Purpose: 11447 * Traverse the created match config. 11448 * Parameters: 11449 * unit - (IN) Unit number 11450 * cb - (IN) Traverse call back function 11451 * user_data - (IN) User data 11452 * Returns: 11453 * BCM_E_xxx 11454 */ 11455 int 11456 bcmi_esw_tsn_mtu_profile_traverse( 11457 int unit, 11458 bcm_tsn_mtu_profile_traverse_cb cb, 11459 void *user_data) 11460 { 11461 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11462 const tsn_mtu_info_t *ctrl_info = NULL; 11463 int rv; 11464 11465 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11466 /* Use this init macro after the bk info instance get */ 11467 MTU_DEV_INIT(unit); 11468 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 11469 11470 MTU_BK_LOCK(unit); 11471 rv = ctrl_info->mtu_profile_traverse(unit, cb, user_data); 11472 MTU_BK_UNLOCK(unit); 11473 11474 return rv; 11475 11476 } 11477 11478 11479 /* 11480 * Function: 11481 * bcmi_esw_tsn_ingress_mtu_config_set 11482 * Purpose: 11483 * Set the priority of source ingress 11484 * mtu profile index. 11485 * Parameters: 11486 * unit - (IN) Unit number 11487 * config - (IN) Configuration of the mtu profile priority 11488 * Returns: 11489 * BCM_E_xxx 11490 */ 11491 int 11492 bcmi_esw_tsn_ingress_mtu_config_set( 11493 int unit, 11494 bcm_tsn_ingress_mtu_config_t *config) 11495 { 11496 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11497 const tsn_mtu_info_t *ctrl_info = NULL; 11498 int rv; 11499 11500 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11501 /* Use this init macro after the bk info instance get */ 11502 MTU_DEV_INIT(unit); 11503 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 11504 11505 if (config == NULL) { 11506 return BCM_E_PARAM; 11507 } 11508 11509 MTU_BK_LOCK(unit); 11510 rv = ctrl_info->ingress_mtu_config_set(unit, config); 11511 MTU_BK_UNLOCK(unit); 11512 11513 return rv; 11514 } 11515 11516 /* 11517 * Function: 11518 * bcmi_esw_tsn_ingress_mtu_config_get 11519 * Purpose: 11520 * Get the priority of source ingress 11521 * mtu profile index. 11522 * Parameters: 11523 * unit - (IN) Unit number 11524 * config - (OUT) Configuration of the mtu profile priority 11525 * Returns: 11526 * BCM_E_xxx 11527 */ 11528 int 11529 bcmi_esw_tsn_ingress_mtu_config_get( 11530 int unit, 11531 bcm_tsn_ingress_mtu_config_t *config) 11532 { 11533 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11534 const tsn_mtu_info_t *ctrl_info = NULL; 11535 int rv; 11536 11537 if (NULL == config) { 11538 return BCM_E_PARAM; 11539 } 11540 11541 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11542 /* Use this init macro after the bk info instance get */ 11543 MTU_DEV_INIT(unit); 11544 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 11545 11546 MTU_BK_LOCK(unit); 11547 rv = ctrl_info->ingress_mtu_config_get(unit, config); 11548 MTU_BK_UNLOCK(unit); 11549 11550 return rv; 11551 } 11552 11553 /* 11554 * Function: 11555 * bcmi_tsn_port_control_egress_mtu_set 11556 * Purpose: 11557 * Setup HW memory with pri_map_id and port information 11558 * Parameters: 11559 * unit - (IN) Unit number 11560 * port - (IN) port number 11561 * pri_map_id - (IN) priority map id 11562 * Returns: 11563 * BCM_E_xxx 11564 */ 11565 int 11566 bcmi_tsn_port_control_egress_mtu_set( 11567 int unit, 11568 bcm_gport_t gport, 11569 bcm_tsn_pri_map_t pri_map_id) 11570 { 11571 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11572 const tsn_mtu_info_t *ctrl_info = NULL; 11573 11574 bcm_tsn_pri_map_t pre_pri_map_id; 11575 bcm_tsn_pri_map_config_t config; 11576 int rv; 11577 uint32 hw_index; 11578 bcm_tsn_pri_map_type_t type; 11579 bcm_port_t port; 11580 11581 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11582 /* Use this init macro after the bk info instance get */ 11583 MTU_DEV_INIT(unit); 11584 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 11585 11586 /* Validate and convert gport to local port */ 11587 BCM_IF_ERROR_RETURN( 11588 _bcm_esw_port_gport_validate(unit, gport, &port)); 11589 11590 if (port < 0 || port >= ctrl_info->logical_port_num) { 11591 LOG_VERBOSE(BSL_LS_BCM_TSN, 11592 (BSL_META_U(unit, "Invalid Port Range, should be" 11593 " %d\n"), ctrl_info->logical_port_num)); 11594 return BCM_E_PARAM; 11595 } 11596 11597 /* use pri_map_invalid to detach the pri_map_id from port*/ 11598 if (pri_map_id == BCM_TSN_PRI_MAP_INVALID) { 11599 MTU_BK_LOCK(unit); 11600 pre_pri_map_id = bk_info->tsn_mtu_bk_info.pri_map_port[port]; 11601 if (pre_pri_map_id != BCM_TSN_PRI_MAP_INVALID) { 11602 (void)bcmi_esw_tsn_pri_map_ref_cnt_dec(unit, pre_pri_map_id); 11603 } 11604 bk_info->tsn_mtu_bk_info.pri_map_port[port] = pri_map_id; 11605 MTU_BK_UNLOCK(unit); 11606 return BCM_E_NONE; 11607 } 11608 /* Check if map id match to the bcmTsnControlEgressMtuPriorityMap */ 11609 BCM_IF_ERROR_RETURN( 11610 bcmi_esw_tsn_pri_map_hw_index_get(unit, pri_map_id, &type, &hw_index)); 11611 if (type != bcmTsnPriMapTypeEgressMtuProfile) { 11612 return BCM_E_PARAM; 11613 } 11614 rv = bcm_esw_tsn_pri_map_get(unit, pri_map_id, &config); 11615 BCM_IF_ERROR_RETURN(rv); 11616 11617 if (bk_info->tsn_mtu_bk_info.pri_map_port == NULL) { 11618 return BCM_E_INTERNAL; 11619 } 11620 11621 MTU_BK_LOCK(unit); 11622 /* 11623 * Store map id into SW egress_mtu_pri_map with the corresponding 11624 * port number 11625 */ 11626 /* Increase Priority Map Reference Count */ 11627 rv = bcmi_esw_tsn_pri_map_ref_cnt_inc(unit, pri_map_id); 11628 if (BCM_FAILURE(rv)) { 11629 MTU_BK_UNLOCK(unit); 11630 return rv; 11631 } 11632 pre_pri_map_id = bk_info->tsn_mtu_bk_info.pri_map_port[port]; 11633 if (pre_pri_map_id != BCM_TSN_PRI_MAP_INVALID) { 11634 (void)bcmi_esw_tsn_pri_map_ref_cnt_dec(unit, pre_pri_map_id); 11635 } 11636 bk_info->tsn_mtu_bk_info.pri_map_port[port] = pri_map_id; 11637 11638 /* 11639 * Write into HW memory to store config with the 11640 * corresponding port number 11641 */ 11642 rv = ctrl_info->egress_mtu_port_control_set(unit, gport, &config); 11643 MTU_BK_UNLOCK(unit); 11644 return rv; 11645 } 11646 11647 11648 /* 11649 * Function: 11650 * bcmi_tsn_port_control_egress_mtu_get 11651 * Purpose: 11652 * get pri_map_id from HW memory with port information 11653 * Parameters: 11654 * unit - (IN) Unit number 11655 * port - (IN) port number 11656 * pri_map_id - (OUT) priority map id 11657 * Returns: 11658 * BCM_E_xxx 11659 */ 11660 int 11661 bcmi_tsn_port_control_egress_mtu_get( 11662 int unit, 11663 bcm_gport_t gport, 11664 bcm_tsn_pri_map_t *pri_map_id) 11665 { 11666 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11667 const tsn_mtu_info_t *ctrl_info = NULL; 11668 bcm_port_t port; 11669 11670 if (pri_map_id == NULL) { 11671 return BCM_E_PARAM; 11672 } 11673 11674 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11675 /* Use this init macro after the bk info instance get */ 11676 MTU_DEV_INIT(unit); 11677 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 11678 11679 /* Validate and convert gport to local port */ 11680 BCM_IF_ERROR_RETURN( 11681 _bcm_esw_port_gport_validate(unit, gport, &port)); 11682 11683 if (port < 0 || port >= ctrl_info->logical_port_num) { 11684 LOG_VERBOSE(BSL_LS_BCM_TSN, 11685 (BSL_META_U(unit, "Invalid Port Range, should be" 11686 " %d\n"), ctrl_info->logical_port_num)); 11687 return BCM_E_PARAM; 11688 } 11689 if (bk_info->tsn_mtu_bk_info.pri_map_port == NULL) { 11690 return BCM_E_INTERNAL; 11691 } 11692 /* retrieve priority map id from the prio_map_port sw data structure */ 11693 MTU_BK_LOCK(unit); 11694 *pri_map_id = bk_info->tsn_mtu_bk_info.pri_map_port[port]; 11695 MTU_BK_UNLOCK(unit); 11696 /* the priority map is not store in the specific port number */ 11697 if (*pri_map_id == BCM_TSN_PRI_MAP_INVALID) { 11698 return BCM_E_EMPTY; 11699 } 11700 11701 return BCM_E_NONE; 11702 } 11703 11704 /* 11705 * Function: 11706 * bcmi_tsn_port_control_ingress_mtu_set 11707 * Purpose: 11708 * Setup HW memory with profile id and port information 11709 * Parameters: 11710 * unit - (IN) Unit number 11711 * port - (IN) port number 11712 * profile_id - (IN) ingress mtu profile id 11713 * Returns: 11714 * BCM_E_xxx 11715 */ 11716 int 11717 bcmi_tsn_port_control_ingress_mtu_set( 11718 int unit, 11719 bcm_gport_t gport, 11720 int profile_id) 11721 { 11722 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11723 const tsn_mtu_info_t *ctrl_info = NULL; 11724 11725 int rv, index; 11726 bcm_tsn_mtu_profile_type_t type; 11727 bcm_port_t port; 11728 uint32 pre_profile_id; 11729 11730 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11731 /* Use this init macro after the bk info instance get */ 11732 MTU_DEV_INIT(unit); 11733 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 11734 11735 /* Validate and convert gport to local port */ 11736 BCM_IF_ERROR_RETURN( 11737 _bcm_esw_port_gport_validate(unit, gport, &port)); 11738 11739 if (port < 0 || port >= ctrl_info->logical_port_num) { 11740 LOG_VERBOSE(BSL_LS_BCM_TSN, 11741 (BSL_META_U(unit, "Invalid Port Range, should be" 11742 " %d\n"), ctrl_info->logical_port_num)); 11743 return BCM_E_PARAM; 11744 } 11745 MTU_BK_LOCK(unit); 11746 rv = ctrl_info->mtu_profile_decode(unit, profile_id, &type, &index); 11747 if (BCM_FAILURE(rv)) { 11748 MTU_BK_UNLOCK(unit); 11749 return rv; 11750 } 11751 11752 if (type != bcmTsnMtuProfileTypeIngress) { 11753 MTU_BK_UNLOCK(unit); 11754 LOG_VERBOSE(BSL_LS_BCM_TSN, 11755 (BSL_META_U(unit, "Wrong Profile Type.\n"))); 11756 return BCM_E_PARAM; 11757 } 11758 /* detach the previous mtu_profile_id*/ 11759 if (profile_id == 0) { 11760 rv = bcm_esw_tsn_port_control_get(unit, gport, 11761 bcmTsnControlIngressMtuProfile, 11762 &pre_profile_id); 11763 if (BCM_FAILURE(rv)) { 11764 MTU_BK_UNLOCK(unit); 11765 return rv; 11766 } 11767 (void)bcmi_esw_tsn_mtu_profile_ref_dec(unit, pre_profile_id); 11768 MTU_BK_UNLOCK(unit); 11769 return BCM_E_NONE; 11770 } 11771 rv = ctrl_info->ingress_mtu_port_control_set(unit, gport, index); 11772 if (BCM_FAILURE(rv)) { 11773 MTU_BK_UNLOCK(unit); 11774 return rv; 11775 } 11776 (void)bcmi_esw_tsn_mtu_profile_ref_inc(unit, profile_id); 11777 MTU_BK_UNLOCK(unit); 11778 return rv; 11779 } 11780 11781 11782 /* 11783 * Function: 11784 * bcmi_tsn_port_control_ingress_mtu_get 11785 * Purpose: 11786 * get profile id from HW memory with port information 11787 * Parameters: 11788 * unit - (IN) Unit number 11789 * port - (IN) port number 11790 * profile id - (OUT) ingress mtu profile id 11791 * Returns: 11792 * BCM_E_xxx 11793 */ 11794 int 11795 bcmi_tsn_port_control_ingress_mtu_get( 11796 int unit, 11797 bcm_gport_t gport, 11798 int *profile_id) 11799 { 11800 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11801 const tsn_mtu_info_t *ctrl_info = NULL; 11802 bcm_port_t port; 11803 11804 int index, rv; 11805 if (profile_id == NULL) { 11806 return BCM_E_PARAM; 11807 } 11808 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11809 /* Use this init macro after the bk info instance get */ 11810 MTU_DEV_INIT(unit); 11811 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 11812 11813 /* Validate and convert gport to local port */ 11814 BCM_IF_ERROR_RETURN( 11815 _bcm_esw_port_gport_validate(unit, gport, &port)); 11816 11817 if (port < 0 || port >= ctrl_info->logical_port_num) { 11818 LOG_VERBOSE(BSL_LS_BCM_TSN, 11819 (BSL_META_U(unit, "Invalid Port Range, should be" 11820 " %d\n"), ctrl_info->logical_port_num)); 11821 return BCM_E_PARAM; 11822 } 11823 MTU_BK_LOCK(unit); 11824 rv = ctrl_info->ingress_mtu_port_control_get(unit, gport, &index); 11825 if (BCM_FAILURE(rv)) { 11826 MTU_BK_UNLOCK(unit); 11827 return rv; 11828 } 11829 rv = ctrl_info->mtu_profile_encode( 11830 unit, index, bcmTsnMtuProfileTypeIngress, profile_id); 11831 MTU_BK_UNLOCK(unit); 11832 return rv; 11833 } 11834 11835 /* 11836 * Function: 11837 * bcmi_esw_tsn_stu_profile_get 11838 * Purpose: 11839 * Get stu profile configuration 11840 * with the profile id. 11841 * Parameters: 11842 * unit - (IN) Unit number 11843 * stu_profile_id - (IN) Indicated the stu profile entry 11844 * type - (OUT) Indicates ingress or egress stu profile 11845 * config - (OUT) Configuration of the stu profile 11846 * Returns: 11847 * BCM_E_xxx 11848 */ 11849 int 11850 bcmi_esw_tsn_stu_profile_get( 11851 int unit, 11852 int stu_profile_id, 11853 bcm_tsn_stu_profile_type_t *type, 11854 bcm_tsn_stu_config_t *config) 11855 { 11856 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11857 const tsn_stu_info_t *ctrl_info = NULL; 11858 11859 int index, rv; 11860 11861 if (type == NULL || config == NULL) { 11862 return BCM_E_PARAM; 11863 } 11864 11865 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11866 /* Use this init macro after the bk info instance get */ 11867 STU_DEV_INIT(unit); 11868 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 11869 STU_BK_LOCK(unit); 11870 /* this function also check the validity of parameter profile id */ 11871 rv = ctrl_info->stu_profile_decode(unit, stu_profile_id, type, &index); 11872 if (BCM_FAILURE(rv)) { 11873 STU_BK_UNLOCK(unit); 11874 return rv; 11875 } 11876 rv = ctrl_info->stu_profile_get(unit, index, *type, config); 11877 if (BCM_FAILURE(rv)) { 11878 STU_BK_UNLOCK(unit); 11879 return rv; 11880 } 11881 STU_BK_UNLOCK(unit); 11882 return BCM_E_NONE; 11883 } 11884 11885 /* 11886 * Function: 11887 * bcmi_esw_tsn_stu_profile_set 11888 * Purpose: 11889 * Set stu profile with the profile id 11890 * and config parameter. 11891 * Parameters: 11892 * unit - (IN) Unit number 11893 * stu_profile_id - (IN) Indicated the stu profile entry 11894 * config - (IN) Configuration of the stu profile 11895 * Returns: 11896 * BCM_E_xxx 11897 */ 11898 int 11899 bcmi_esw_tsn_stu_profile_set( 11900 int unit, 11901 int stu_profile_id, 11902 bcm_tsn_stu_config_t *config) 11903 { 11904 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11905 const tsn_stu_info_t *ctrl_info = NULL; 11906 11907 int index, ref_count, rv, min, max; 11908 bcm_tsn_stu_profile_type_t type; 11909 11910 if (config == NULL) { 11911 return BCM_E_PARAM; 11912 } 11913 11914 if (config->size <= 0) { 11915 LOG_ERROR(BSL_LS_BCM_TSN, 11916 (BSL_META_U(unit, "Invalid STU size.\n"))); 11917 return BCM_E_PARAM; 11918 } 11919 11920 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 11921 /* Use this init macro after the bk info instance get */ 11922 STU_DEV_INIT(unit); 11923 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 11924 11925 STU_BK_LOCK(unit); 11926 /* this function also check the validity of parameter profile id */ 11927 rv = ctrl_info->stu_profile_decode(unit, stu_profile_id, &type, &index); 11928 if (BCM_FAILURE(rv)) { 11929 STU_BK_UNLOCK(unit); 11930 return rv; 11931 } 11932 11933 /* index 0 in profile memory is the default value */ 11934 if (index == 0) { 11935 MTU_BK_UNLOCK(unit); 11936 LOG_WARN(BSL_LS_BCMAPI_TSN, 11937 (BSL_META_U( 11938 unit, "Profile ID 0 is the default, can't modify it.\n"))); 11939 return BCM_E_PARAM; 11940 } 11941 11942 rv = ctrl_info->stu_profile_mem_refcnt_get(unit, type, index, &ref_count); 11943 if (BCM_FAILURE(rv)) { 11944 STU_BK_UNLOCK(unit); 11945 return rv; 11946 } 11947 /* ref_count > 0, then the entry is created */ 11948 if (ref_count <= 0) { 11949 STU_BK_UNLOCK(unit); 11950 LOG_WARN(BSL_LS_BCMAPI_TSN, 11951 (BSL_META_U(unit, 11952 "MTU Profile entry is not created.\n"))); 11953 return BCM_E_PARAM; 11954 } 11955 11956 /* the profile entry is referenced by other flows */ 11957 STU_BK_INIT(unit, type); 11958 ctrl_info->stu_profile_mem_idx_get(unit, type, &min, &max); 11959 if (index < min || index > max) { 11960 STU_BK_UNLOCK(unit); 11961 return BCM_E_PARAM; 11962 } 11963 if (bk_info->tsn_stu_bk_info.stu_refcount[type][index] > 0) { 11964 STU_BK_UNLOCK(unit); 11965 LOG_WARN(BSL_LS_BCMAPI_TSN, 11966 (BSL_META_U(unit, 11967 "Flow is in use of Ingress STU Profile\n"))); 11968 return BCM_E_BUSY; 11969 } 11970 11971 rv = ctrl_info->stu_profile_set(unit, index, type, config); 11972 if (BCM_FAILURE(rv)) { 11973 STU_BK_UNLOCK(unit); 11974 return rv; 11975 } 11976 STU_BK_UNLOCK(unit); 11977 return BCM_E_NONE; 11978 } 11979 11980 /* 11981 * Function: 11982 * bcmi_esw_tsn_stu_profile_destroy 11983 * Purpose: 11984 * Clear the stu profile with the profile id 11985 * Parameters: 11986 * unit - (IN) Unit number 11987 * stu_profile_id - (IN) Indicated the stu profile entry 11988 * Returns: 11989 * BCM_E_xxx 11990 */ 11991 int 11992 bcmi_esw_tsn_stu_profile_destroy( 11993 int unit, 11994 int stu_profile_id) 11995 { 11996 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 11997 const tsn_stu_info_t *ctrl_info = NULL; 11998 11999 bcm_tsn_stu_profile_type_t type; 12000 int index, rv, min, max; 12001 12002 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 12003 /* Use this init macro after the bk info instance get */ 12004 STU_DEV_INIT(unit); 12005 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 12006 12007 /* this function also check the validity of parameter profile id */ 12008 STU_BK_LOCK(unit); 12009 rv = ctrl_info->stu_profile_decode(unit, stu_profile_id, &type, &index); 12010 if (BCM_FAILURE(rv)) { 12011 STU_BK_UNLOCK(unit); 12012 return rv; 12013 } 12014 12015 /* index 0 in profile memory is the default value */ 12016 if (index == 0) { 12017 MTU_BK_UNLOCK(unit); 12018 LOG_WARN(BSL_LS_BCMAPI_TSN, 12019 (BSL_META_U( 12020 unit, "Profile ID 0 is the default, can't modify it.\n"))); 12021 return BCM_E_PARAM; 12022 } 12023 12024 rv = ctrl_info->stu_profile_mem_idx_get(unit, type, &min, &max); 12025 if (BCM_FAILURE(rv)) { 12026 STU_BK_UNLOCK(unit); 12027 return rv; 12028 } 12029 STU_BK_INIT(unit, type); 12030 /* the profile entry is referenced bt other flows */ 12031 if (index < min || index > max) { 12032 STU_BK_UNLOCK(unit); 12033 return BCM_E_PARAM; 12034 } 12035 if (bk_info->tsn_stu_bk_info.stu_refcount[type][index] != 0) { 12036 STU_BK_UNLOCK(unit); 12037 LOG_WARN(BSL_LS_BCMAPI_TSN, 12038 (BSL_META_U(unit, 12039 "Flow is in use of Ingress STU Profile\n"))); 12040 return BCM_E_EXISTS; 12041 } 12042 12043 rv = ctrl_info->stu_profile_destroy(unit, type, index); 12044 STU_BK_UNLOCK(unit); 12045 12046 return rv; 12047 } 12048 12049 /* 12050 * Function: 12051 * bcmi_esw_tsn_stu_profile_create 12052 * Purpose: 12053 * Create stu profile with the config pointer 12054 * and return the assigned profile id. 12055 * Parameters: 12056 * unit - (IN) Unit number 12057 * type - (IN) Indicates ingress or egress stu profile 12058 * config - (IN) configuration of the stu profile 12059 * stu_profile_id - (OUT) profile id 12060 * Returns: 12061 * BCM_E_xxx 12062 */ 12063 int 12064 bcmi_esw_tsn_stu_profile_create( 12065 int unit, 12066 bcm_tsn_stu_profile_type_t type, 12067 bcm_tsn_stu_config_t *config, 12068 int *stu_profile_id) 12069 { 12070 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 12071 const tsn_stu_info_t *ctrl_info = NULL; 12072 12073 int ref_count, rv, rv1; 12074 uint32 index; 12075 12076 if (config == NULL || stu_profile_id == NULL) { 12077 return BCM_E_PARAM; 12078 } 12079 12080 if (config->size <= 0) { 12081 LOG_ERROR(BSL_LS_BCM_TSN, 12082 (BSL_META_U(unit, "Invalid STU size.\n"))); 12083 return BCM_E_PARAM; 12084 } 12085 12086 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 12087 /* Use this init macro after the bk info instance get */ 12088 STU_DEV_INIT(unit); 12089 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 12090 12091 /* Check the validity of the type */ 12092 if (type != bcmTsnStuProfileTypeIngress && 12093 type != bcmTsnStuProfileTypeEgress) { 12094 LOG_VERBOSE(BSL_LS_BCM_TSN, 12095 (BSL_META_U(unit, "Wrong Profile Type.\n"))); 12096 return BCM_E_PARAM; 12097 } 12098 12099 STU_BK_LOCK(unit); 12100 rv = ctrl_info->stu_profile_create(unit, type, config, &index); 12101 if (BCM_FAILURE(rv)) { 12102 STU_BK_UNLOCK(unit); 12103 return rv; 12104 } 12105 rv = ctrl_info->stu_profile_mem_refcnt_get(unit, type, index, &ref_count); 12106 if (BCM_FAILURE(rv)) { 12107 rv1 = ctrl_info->stu_profile_destroy(unit, type, index); 12108 if (BCM_FAILURE(rv1)) { 12109 STU_BK_UNLOCK(unit); 12110 return rv1; 12111 } 12112 STU_BK_UNLOCK(unit); 12113 return rv; 12114 } 12115 12116 /* Encode the stu profile id */ 12117 rv = ctrl_info->stu_profile_encode(unit, index, type, stu_profile_id); 12118 if (BCM_FAILURE(rv)) { 12119 rv1 = ctrl_info->stu_profile_destroy(unit, type, index); 12120 if (BCM_FAILURE(rv1)) { 12121 STU_BK_UNLOCK(unit); 12122 return rv1; 12123 } 12124 STU_BK_UNLOCK(unit); 12125 return rv; 12126 } 12127 12128 /* ref_count > 1 indicates replicated stu profile is created */ 12129 if (ref_count > 1) { 12130 if (type == bcmTsnStuProfileTypeIngress) { 12131 LOG_WARN(BSL_LS_BCMAPI_TSN, 12132 (BSL_META_U(unit, 12133 "config already existed, " 12134 "found ingress stu profile id(%d)\n"), 12135 *stu_profile_id)); 12136 } else { 12137 LOG_WARN(BSL_LS_BCMAPI_TSN, 12138 (BSL_META_U(unit, 12139 "config already existed, " 12140 "found egress stu profile id(%d)\n"), 12141 *stu_profile_id)); 12142 } 12143 } 12144 12145 STU_BK_UNLOCK(unit); 12146 return BCM_E_NONE; 12147 } 12148 /* 12149 * Function: 12150 * bcmi_esw_tsn_stu_profile_traverse 12151 * Purpose: 12152 * Traverse the created match config. 12153 * Parameters: 12154 * unit - (IN) Unit number 12155 * cb - (IN) Traverse call back function 12156 * user_data - (IN) User data 12157 * Returns: 12158 * BCM_E_xxx 12159 */ 12160 int 12161 bcmi_esw_tsn_stu_profile_traverse( 12162 int unit, 12163 bcm_tsn_stu_profile_traverse_cb cb, 12164 void *user_data) 12165 { 12166 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 12167 const tsn_stu_info_t *ctrl_info = NULL; 12168 int rv; 12169 12170 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 12171 /* Use this init macro after the bk info instance get */ 12172 STU_DEV_INIT(unit); 12173 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 12174 12175 STU_BK_LOCK(unit); 12176 rv = ctrl_info->stu_profile_traverse(unit, cb, user_data); 12177 STU_BK_UNLOCK(unit); 12178 12179 return rv; 12180 12181 } 12182 12183 12184 /* 12185 * Function: 12186 * bcmi_esw_tsn_ingress_stu_config_set 12187 * Purpose: 12188 * Set the priority of source ingress 12189 * stu profile index. 12190 * Parameters: 12191 * unit - (IN) Unit number 12192 * config - (IN) Configuration of the stu profile priority 12193 * Returns: 12194 * BCM_E_xxx 12195 */ 12196 int 12197 bcmi_esw_tsn_ingress_stu_config_set( 12198 int unit, 12199 bcm_tsn_ingress_stu_config_t *config) 12200 { 12201 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 12202 const tsn_stu_info_t *ctrl_info = NULL; 12203 int rv; 12204 12205 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 12206 /* Use this init macro after the bk info instance get */ 12207 STU_DEV_INIT(unit); 12208 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 12209 12210 if (config == NULL) { 12211 return BCM_E_PARAM; 12212 } 12213 12214 STU_BK_LOCK(unit); 12215 rv = ctrl_info->ingress_stu_config_set(unit, config); 12216 STU_BK_UNLOCK(unit); 12217 12218 return rv; 12219 } 12220 12221 /* 12222 * Function: 12223 * bcmi_esw_tsn_ingress_stu_config_get 12224 * Purpose: 12225 * Get the priority of source ingress 12226 * stu profile index. 12227 * Parameters: 12228 * unit - (IN) Unit number 12229 * config - (OUT) Configuration of the stu profile priority 12230 * Returns: 12231 * BCM_E_xxx 12232 */ 12233 int 12234 bcmi_esw_tsn_ingress_stu_config_get( 12235 int unit, 12236 bcm_tsn_ingress_stu_config_t *config) 12237 { 12238 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 12239 const tsn_stu_info_t *ctrl_info = NULL; 12240 int rv; 12241 12242 if (NULL == config) { 12243 return BCM_E_PARAM; 12244 } 12245 12246 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 12247 /* Use this init macro after the bk info instance get */ 12248 STU_DEV_INIT(unit); 12249 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 12250 12251 STU_BK_LOCK(unit); 12252 rv = ctrl_info->ingress_stu_config_get(unit, config); 12253 STU_BK_UNLOCK(unit); 12254 12255 return rv; 12256 } 12257 12258 /* 12259 * Function: 12260 * bcmi_tsn_port_control_egress_stu_set 12261 * Purpose: 12262 * Setup HW memory with pri_map_id and port information 12263 * Parameters: 12264 * unit - (IN) Unit number 12265 * port - (IN) port number 12266 * pri_map_id - (IN) priority map id 12267 * Returns: 12268 * BCM_E_xxx 12269 */ 12270 int 12271 bcmi_tsn_port_control_egress_stu_set( 12272 int unit, 12273 bcm_gport_t gport, 12274 bcm_tsn_pri_map_t pri_map_id) 12275 { 12276 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 12277 const tsn_stu_info_t *ctrl_info = NULL; 12278 12279 bcm_tsn_pri_map_t pre_pri_map_id; 12280 bcm_tsn_pri_map_config_t config; 12281 int rv; 12282 uint32 hw_index; 12283 bcm_tsn_pri_map_type_t type; 12284 bcm_port_t port; 12285 12286 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 12287 /* Use this init macro after the bk info instance get */ 12288 STU_DEV_INIT(unit); 12289 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 12290 12291 /* Validate and convert gport to local port */ 12292 BCM_IF_ERROR_RETURN( 12293 _bcm_esw_port_gport_validate(unit, gport, &port)); 12294 12295 if (port < 0 || port >= ctrl_info->logical_port_num) { 12296 LOG_VERBOSE(BSL_LS_BCM_TSN, 12297 (BSL_META_U(unit, "Invalid Port Range, should be" 12298 " %d\n"), ctrl_info->logical_port_num)); 12299 return BCM_E_PARAM; 12300 } 12301 12302 /* use pri_map_invalid to detach the pri_map_id from port*/ 12303 if (pri_map_id == BCM_TSN_PRI_MAP_INVALID) { 12304 STU_BK_LOCK(unit); 12305 pre_pri_map_id = bk_info->tsn_stu_bk_info.pri_map_port[port]; 12306 if (pre_pri_map_id != BCM_TSN_PRI_MAP_INVALID) { 12307 (void)bcmi_esw_tsn_pri_map_ref_cnt_dec(unit, pre_pri_map_id); 12308 } 12309 bk_info->tsn_stu_bk_info.pri_map_port[port] = pri_map_id; 12310 STU_BK_UNLOCK(unit); 12311 return BCM_E_NONE; 12312 } 12313 /* Check if map id match to the bcmTsnControlEgressStuPriorityMap */ 12314 BCM_IF_ERROR_RETURN( 12315 bcmi_esw_tsn_pri_map_hw_index_get(unit, pri_map_id, &type, &hw_index)); 12316 if (type != bcmTsnPriMapTypeEgressStuProfile) { 12317 return BCM_E_PARAM; 12318 } 12319 rv = bcm_esw_tsn_pri_map_get(unit, pri_map_id, &config); 12320 BCM_IF_ERROR_RETURN(rv); 12321 12322 if (bk_info->tsn_stu_bk_info.pri_map_port == NULL) { 12323 return BCM_E_INTERNAL; 12324 } 12325 12326 STU_BK_LOCK(unit); 12327 /* 12328 * Store map id into SW egress_stu_pri_map with the corresponding 12329 * port number 12330 */ 12331 /* Increase Priority Map Reference Count */ 12332 rv = bcmi_esw_tsn_pri_map_ref_cnt_inc(unit, pri_map_id); 12333 if (BCM_FAILURE(rv)) { 12334 STU_BK_UNLOCK(unit); 12335 return rv; 12336 } 12337 pre_pri_map_id = bk_info->tsn_stu_bk_info.pri_map_port[port]; 12338 if (pre_pri_map_id != BCM_TSN_PRI_MAP_INVALID) { 12339 (void)bcmi_esw_tsn_pri_map_ref_cnt_dec(unit, pre_pri_map_id); 12340 } 12341 bk_info->tsn_stu_bk_info.pri_map_port[port] = pri_map_id; 12342 12343 /* 12344 * Write into HW memory to store config with the 12345 * corresponding port number 12346 */ 12347 rv = ctrl_info->egress_stu_port_control_set(unit, port, &config); 12348 STU_BK_UNLOCK(unit); 12349 return rv; 12350 } 12351 12352 12353 /* 12354 * Function: 12355 * bcmi_tsn_port_control_egress_stu_get 12356 * Purpose: 12357 * get pri_map_id from HW memory with port information 12358 * Parameters: 12359 * unit - (IN) Unit number 12360 * port - (IN) port number 12361 * pri_map_id - (OUT) priority map id 12362 * Returns: 12363 * BCM_E_xxx 12364 */ 12365 int 12366 bcmi_tsn_port_control_egress_stu_get( 12367 int unit, 12368 bcm_gport_t gport, 12369 bcm_tsn_pri_map_t *pri_map_id) 12370 { 12371 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 12372 const tsn_stu_info_t *ctrl_info = NULL; 12373 bcm_port_t port; 12374 12375 if (pri_map_id == NULL) { 12376 return BCM_E_PARAM; 12377 } 12378 12379 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 12380 /* Use this init macro after the bk info instance get */ 12381 STU_DEV_INIT(unit); 12382 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 12383 12384 /* Validate and convert gport to local port */ 12385 BCM_IF_ERROR_RETURN( 12386 _bcm_esw_port_gport_validate(unit, gport, &port)); 12387 12388 if (port < 0 || port >= ctrl_info->logical_port_num) { 12389 LOG_VERBOSE(BSL_LS_BCM_TSN, 12390 (BSL_META_U(unit, "Invalid Port Range, should be" 12391 " %d\n"), ctrl_info->logical_port_num)); 12392 12393 return BCM_E_PARAM; 12394 } 12395 if (bk_info->tsn_stu_bk_info.pri_map_port == NULL) { 12396 return BCM_E_INTERNAL; 12397 } 12398 /* retrieve priority map id from the prio_map_port sw data structure */ 12399 STU_BK_LOCK(unit); 12400 *pri_map_id = bk_info->tsn_stu_bk_info.pri_map_port[port]; 12401 STU_BK_UNLOCK(unit); 12402 /* the priority map is not store in the specific port number */ 12403 if (*pri_map_id == BCM_TSN_PRI_MAP_INVALID) { 12404 return BCM_E_EMPTY; 12405 } 12406 12407 return BCM_E_NONE; 12408 } 12409 12410 /* 12411 * Function: 12412 * bcmi_tsn_port_control_ingress_stu_set 12413 * Purpose: 12414 * Setup HW memory with profile id and port information 12415 * Parameters: 12416 * unit - (IN) Unit number 12417 * port - (IN) port number 12418 * profile_id - (IN) ingress stu profile id 12419 * Returns: 12420 * BCM_E_xxx 12421 */ 12422 int 12423 bcmi_tsn_port_control_ingress_stu_set( 12424 int unit, 12425 bcm_gport_t gport, 12426 int profile_id) 12427 { 12428 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 12429 const tsn_stu_info_t *ctrl_info = NULL; 12430 12431 int rv, index; 12432 bcm_tsn_stu_profile_type_t type; 12433 bcm_port_t port; 12434 uint32 pre_profile_id; 12435 12436 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 12437 /* Use this init macro after the bk info instance get */ 12438 STU_DEV_INIT(unit); 12439 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 12440 12441 /* Validate and convert gport to local port */ 12442 BCM_IF_ERROR_RETURN( 12443 _bcm_esw_port_gport_validate(unit, gport, &port)); 12444 12445 if (port < 0 || port >= ctrl_info->logical_port_num) { 12446 LOG_VERBOSE(BSL_LS_BCM_TSN, 12447 (BSL_META_U(unit, "Invalid Port Range, should be" 12448 " %d\n"), ctrl_info->logical_port_num)); 12449 return BCM_E_PARAM; 12450 } 12451 STU_BK_LOCK(unit); 12452 rv = ctrl_info->stu_profile_decode(unit, profile_id, &type, &index); 12453 if (BCM_FAILURE(rv)) { 12454 STU_BK_UNLOCK(unit); 12455 return rv; 12456 } 12457 12458 if (type != bcmTsnStuProfileTypeIngress) { 12459 STU_BK_UNLOCK(unit); 12460 LOG_VERBOSE(BSL_LS_BCM_TSN, 12461 (BSL_META_U(unit, "Wrong Profile Type.\n"))); 12462 return BCM_E_PARAM; 12463 } 12464 /* detach the previous mtu_profile_id*/ 12465 if (profile_id == 0) { 12466 rv = bcm_esw_tsn_port_control_get(unit, gport, 12467 bcmTsnControlIngressStuProfile, 12468 &pre_profile_id); 12469 if (BCM_FAILURE(rv)) { 12470 STU_BK_UNLOCK(unit); 12471 return rv; 12472 } 12473 (void)bcmi_esw_tsn_stu_profile_ref_dec(unit, pre_profile_id); 12474 STU_BK_UNLOCK(unit); 12475 return BCM_E_NONE; 12476 } 12477 rv = ctrl_info->ingress_stu_port_control_set(unit, gport, index); 12478 if (BCM_FAILURE(rv)) { 12479 STU_BK_UNLOCK(unit); 12480 return rv; 12481 } 12482 (void)bcmi_esw_tsn_stu_profile_ref_inc(unit, profile_id); 12483 STU_BK_UNLOCK(unit); 12484 return rv; 12485 } 12486 12487 12488 /* 12489 * Function: 12490 * bcmi_tsn_port_control_ingress_stu_get 12491 * Purpose: 12492 * get profile id from HW memory with port information 12493 * Parameters: 12494 * unit - (IN) Unit number 12495 * port - (IN) port number 12496 * profile id - (OUT) ingress stu profile id 12497 * Returns: 12498 * BCM_E_xxx 12499 */ 12500 int 12501 bcmi_tsn_port_control_ingress_stu_get( 12502 int unit, 12503 bcm_gport_t gport, 12504 int *profile_id) 12505 { 12506 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 12507 const tsn_stu_info_t *ctrl_info = NULL; 12508 bcm_port_t port; 12509 12510 int index, rv; 12511 if (profile_id == NULL) { 12512 return BCM_E_PARAM; 12513 } 12514 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 12515 /* Use this init macro after the bk info instance get */ 12516 STU_DEV_INIT(unit); 12517 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 12518 12519 /* Validate and convert gport to local port */ 12520 BCM_IF_ERROR_RETURN( 12521 _bcm_esw_port_gport_validate(unit, gport, &port)); 12522 12523 if (port < 0 || port >= ctrl_info->logical_port_num) { 12524 LOG_VERBOSE(BSL_LS_BCM_TSN, 12525 (BSL_META_U(unit, "Invalid Port Range, should be" 12526 " %d\n"), ctrl_info->logical_port_num)); 12527 return BCM_E_PARAM; 12528 } 12529 STU_BK_LOCK(unit); 12530 rv = ctrl_info->ingress_stu_port_control_get(unit, gport, &index); 12531 if (BCM_FAILURE(rv)) { 12532 STU_BK_UNLOCK(unit); 12533 return rv; 12534 } 12535 rv = ctrl_info->stu_profile_encode( 12536 unit, index, bcmTsnStuProfileTypeIngress, profile_id); 12537 STU_BK_UNLOCK(unit); 12538 return rv; 12539 } 12540 12541 /* 12542 * Function: 12543 * bcmi_esw_tsn_port_control_set 12544 * Description: 12545 * Internal function for configure port-based operation modes. 12546 * Parameters: 12547 * unit - (IN) Unit number. 12548 * port - (IN) Port number. 12549 * type - (IN) Control type of bcm_tsn_control_t. 12550 * arg - (IN) argument to be set 12551 * Returns: 12552 * BCM_E_XXX 12553 */ 12554 STATIC int 12555 bcmi_esw_tsn_port_control_set( 12556 int unit, 12557 bcm_gport_t port, 12558 bcm_tsn_control_t type, 12559 uint32 arg) 12560 { 12561 if (type == bcmTsnControlEgressMtuPriorityMap) { 12562 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 12563 return bcmi_tsn_port_control_egress_mtu_set(unit, port, arg); 12564 } else { 12565 return BCM_E_UNAVAIL; 12566 } 12567 } else if (type == bcmTsnControlIngressMtuProfile) { 12568 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 12569 return bcmi_tsn_port_control_ingress_mtu_set(unit, port, arg); 12570 } else { 12571 return BCM_E_UNAVAIL; 12572 } 12573 } else if (type == bcmTsnControlEgressStuPriorityMap) { 12574 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 12575 return bcmi_tsn_port_control_egress_stu_set(unit, port, arg); 12576 } else { 12577 return BCM_E_UNAVAIL; 12578 } 12579 } else if (type == bcmTsnControlIngressStuProfile) { 12580 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 12581 return bcmi_tsn_port_control_ingress_stu_set(unit, port, arg); 12582 } else { 12583 return BCM_E_UNAVAIL; 12584 } 12585 } else if (type == bcmTsnControlTafGatePriMap) { 12586 if (soc_feature(unit, soc_feature_tsn_taf)) { 12587 uint32 hw_index; 12588 bcm_tsn_pri_map_type_t map; 12589 12590 if (arg == (uint32)BCM_TSN_PRI_MAP_INVALID) { 12591 hw_index = 0; 12592 } else { 12593 BCM_IF_ERROR_RETURN( 12594 bcmi_esw_tsn_pri_map_hw_index_get(unit, arg, &map, 12595 &hw_index)); 12596 if (map != bcmTsnPriMapTypeTafGate) { 12597 return BCM_E_PARAM; 12598 } 12599 } 12600 return bcmi_esw_tsn_taf_port_control_set(unit, port, type, 12601 hw_index); 12602 } else { 12603 return BCM_E_UNAVAIL; 12604 } 12605 } else if (type == bcmTsnControlTafEnable || 12606 type == bcmTsnControlTafGatePriMapL2Select) { 12607 if (soc_feature(unit, soc_feature_tsn_taf)) { 12608 return bcmi_esw_tsn_taf_port_control_set(unit, port, type, arg); 12609 } else { 12610 return BCM_E_UNAVAIL; 12611 } 12612 } 12613 return BCM_E_UNAVAIL; 12614 } 12615 12616 /* 12617 * Function: 12618 * bcmi_esw_tsn_port_control_get 12619 * Description: 12620 * Internal function for get the configure of port-based operation modes. 12621 * Parameters: 12622 * unit - (IN) Unit number. 12623 * port - (IN) Port number. 12624 * type - (IN) Control type of bcm_tsn_control_t. 12625 * arg - (OUT) argument got 12626 * Returns: 12627 * BCM_E_XXX 12628 */ 12629 STATIC int 12630 bcmi_esw_tsn_port_control_get( 12631 int unit, 12632 bcm_gport_t port, 12633 bcm_tsn_control_t type, 12634 uint32 *arg) 12635 { 12636 if (arg == NULL) { 12637 return BCM_E_PARAM; 12638 } 12639 12640 if (type == bcmTsnControlEgressMtuPriorityMap) { 12641 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 12642 return bcmi_tsn_port_control_egress_mtu_get( 12643 unit, port, (bcm_tsn_pri_map_t *)arg); 12644 } else { 12645 return BCM_E_UNAVAIL; 12646 } 12647 } else if (type == bcmTsnControlIngressMtuProfile) { 12648 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 12649 return bcmi_tsn_port_control_ingress_mtu_get( 12650 unit, port, (int *)arg); 12651 } else { 12652 return BCM_E_UNAVAIL; 12653 } 12654 } else if (type == bcmTsnControlEgressStuPriorityMap) { 12655 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 12656 return bcmi_tsn_port_control_egress_stu_get( 12657 unit, port, (bcm_tsn_pri_map_t *)arg); 12658 } else { 12659 return BCM_E_UNAVAIL; 12660 } 12661 } else if (type == bcmTsnControlIngressStuProfile) { 12662 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 12663 return bcmi_tsn_port_control_ingress_stu_get( 12664 unit, port, (int *)arg); 12665 } else { 12666 return BCM_E_UNAVAIL; 12667 } 12668 } else if (type == bcmTsnControlTafGatePriMap) { 12669 if (soc_feature(unit, soc_feature_tsn_taf)) { 12670 uint32 hw_index; 12671 bcm_tsn_pri_map_t sw_index; 12672 12673 BCM_IF_ERROR_RETURN( 12674 bcmi_esw_tsn_taf_port_control_get(unit, port, type, &hw_index)); 12675 12676 if (0 == hw_index) { 12677 sw_index = BCM_TSN_PRI_MAP_INVALID; 12678 } else { 12679 BCM_IF_ERROR_RETURN( 12680 bcmi_esw_tsn_pri_map_map_id_get( 12681 unit, bcmTsnPriMapTypeTafGate, hw_index, &sw_index)); 12682 } 12683 *arg = (uint32)sw_index; 12684 return BCM_E_NONE; 12685 } else { 12686 return BCM_E_UNAVAIL; 12687 } 12688 } else if (type == bcmTsnControlTafEnable || 12689 type == bcmTsnControlTafGatePriMapL2Select) { 12690 if (soc_feature(unit, soc_feature_tsn_taf)) { 12691 return bcmi_esw_tsn_taf_port_control_get(unit, port, type, arg); 12692 } else { 12693 return BCM_E_UNAVAIL; 12694 } 12695 } 12696 return BCM_E_UNAVAIL; 12697 } 12698 12699 /* 12700 * Function: 12701 * bcmi_esw_tsn_mtu_cleanup 12702 * Purpose: 12703 * Internal function to clear the resource of the TSN module. 12704 * Parameters: 12705 * unit - (IN) unit number 12706 * Returns: 12707 * BCM_E_XXX 12708 */ 12709 STATIC int 12710 bcmi_esw_tsn_mtu_cleanup(int unit) 12711 { 12712 12713 bcm_tsn_mtu_profile_type_t type; 12714 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 12715 12716 LOG_VERBOSE(BSL_LS_BCM_TSN, 12717 (BSL_META_U(unit, 12718 "bcmi_esw_tsn_mtu_cleanup\n"))); 12719 12720 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 12721 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 12722 /* Free and clear the mtu bookkeeping info structure */ 12723 if (bk_info->tsn_mtu_bk_info.mutex != NULL) { 12724 sal_mutex_destroy(bk_info->tsn_mtu_bk_info.mutex); 12725 bk_info->tsn_mtu_bk_info.mutex = NULL; 12726 } 12727 for (type = bcmTsnMtuProfileTypeIngress; 12728 type < bcmTsnMtuProfileTypeCount; type++) { 12729 if (bk_info->tsn_mtu_bk_info.mtu_refcount[type] != NULL) { 12730 TSN_FREE(unit, 12731 bk_info->tsn_mtu_bk_info.mtu_refcount[type], 0); 12732 bk_info->tsn_mtu_bk_info.mtu_refcount[type] = NULL; 12733 } 12734 } 12735 if (bk_info->tsn_mtu_bk_info.pri_map_port != NULL) { 12736 TSN_FREE(unit, 12737 bk_info->tsn_mtu_bk_info.pri_map_port, 0); 12738 bk_info->tsn_mtu_bk_info.pri_map_port = NULL; 12739 } 12740 } 12741 return BCM_E_NONE; 12742 } 12743 12744 12745 /* 12746 * Function: 12747 * bcmi_esw_tsn_mtu_init 12748 * Purpose: 12749 * create a default profile setting 12750 * Parameters: 12751 * unit - (IN) Unit number 12752 * Returns: 12753 * BCM_E_xxx 12754 */ 12755 STATIC int 12756 bcmi_esw_tsn_mtu_init(int unit) 12757 { 12758 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 12759 int rv = BCM_E_NONE; 12760 int i, min, max, alloc_size; 12761 const tsn_mtu_info_t *ctrl_info = NULL; 12762 bcm_tsn_mtu_profile_type_t type; 12763 12764 BCM_IF_ERROR_RETURN( 12765 tsn_bk_info_instance_get(unit, &bk_info)); 12766 /* Allocate MTU bookkeeping structure */ 12767 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 12768 MTU_DEV_INIT(unit); 12769 ctrl_info = bk_info->tsn_dev_info->tsn_mtu_info; 12770 for (type = bcmTsnMtuProfileTypeIngress; 12771 type < bcmTsnMtuProfileTypeCount; type++) { 12772 if (bk_info->tsn_mtu_bk_info.mtu_refcount[type] == NULL) { 12773 ctrl_info->mtu_profile_mem_idx_get(unit, type, &min, &max); 12774 alloc_size = (max - min + 1) * sizeof(int); 12775 TSN_ALLOC(unit, bk_info->tsn_mtu_bk_info.mtu_refcount[type], 12776 int, alloc_size, "Ingress MTU Reference Count", 12777 0, rv); 12778 } 12779 if (BCM_FAILURE(rv)) { 12780 LOG_VERBOSE(BSL_LS_BCM_TSN, 12781 (BSL_META_U(unit, 12782 "bcmi_esw_tsn_init: failed to " 12783 "allocate memory\n"))); 12784 return rv; 12785 } 12786 } 12787 if (bk_info->tsn_mtu_bk_info.pri_map_port == NULL) { 12788 alloc_size = 12789 ctrl_info->logical_port_num * sizeof(bcm_tsn_pri_map_t); 12790 TSN_ALLOC(unit, bk_info->tsn_mtu_bk_info.pri_map_port, 12791 bcm_tsn_pri_map_t, alloc_size, 12792 "MTU Priority Map Port Array", 0, rv); 12793 } 12794 if (BCM_FAILURE(rv)) { 12795 LOG_VERBOSE(BSL_LS_BCM_TSN, 12796 (BSL_META_U(unit, 12797 "bcmi_esw_tsn_init: failed to " 12798 "allocate memory\n"))); 12799 return rv; 12800 } 12801 /* Initialize pri_map_port array */ 12802 for (i = 0; i < ctrl_info->logical_port_num; i++) { 12803 bk_info->tsn_mtu_bk_info.pri_map_port[i] = BCM_TSN_PRI_MAP_INVALID; 12804 } 12805 /* Create MTU mutex */ 12806 bk_info->tsn_mtu_bk_info.mutex = sal_mutex_create("mtu_mutex"); 12807 if (bk_info->tsn_mtu_bk_info.mutex == NULL) { 12808 return BCM_E_MEMORY; 12809 } 12810 } 12811 return BCM_E_NONE; 12812 } 12813 12814 /* 12815 * Function: 12816 * bcmi_esw_tsn_stu_cleanup 12817 * Purpose: 12818 * Internal function to clear the resource of the TSN module. 12819 * Parameters: 12820 * unit - (IN) unit number 12821 * Returns: 12822 * BCM_E_XXX 12823 */ 12824 STATIC int 12825 bcmi_esw_tsn_stu_cleanup(int unit) 12826 { 12827 12828 bcm_tsn_stu_profile_type_t type; 12829 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 12830 12831 LOG_VERBOSE(BSL_LS_BCM_TSN, 12832 (BSL_META_U(unit, 12833 "bcmi_esw_tsn_stu_cleanup\n"))); 12834 12835 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 12836 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 12837 /* Free and clear the stu bookkeeping info structure */ 12838 if (bk_info->tsn_stu_bk_info.mutex != NULL) { 12839 sal_mutex_destroy(bk_info->tsn_stu_bk_info.mutex); 12840 bk_info->tsn_stu_bk_info.mutex = NULL; 12841 } 12842 for (type = bcmTsnStuProfileTypeIngress; 12843 type < bcmTsnStuProfileTypeCount; type++) { 12844 if (bk_info->tsn_stu_bk_info.stu_refcount[type] != NULL) { 12845 TSN_FREE(unit, 12846 bk_info->tsn_stu_bk_info.stu_refcount[type], 0); 12847 bk_info->tsn_stu_bk_info.stu_refcount[type] = NULL; 12848 } 12849 } 12850 if (bk_info->tsn_stu_bk_info.pri_map_port != NULL) { 12851 TSN_FREE(unit, 12852 bk_info->tsn_stu_bk_info.pri_map_port, 0); 12853 bk_info->tsn_stu_bk_info.pri_map_port = NULL; 12854 } 12855 } 12856 return BCM_E_NONE; 12857 } 12858 12859 12860 /* 12861 * Function: 12862 * bcmi_esw_tsn_stu_init 12863 * Purpose: 12864 * create a default profile setting 12865 * Parameters: 12866 * unit - (IN) Unit number 12867 * Returns: 12868 * BCM_E_xxx 12869 */ 12870 STATIC int 12871 bcmi_esw_tsn_stu_init(int unit) 12872 { 12873 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 12874 int rv = BCM_E_NONE; 12875 int i, min, max, alloc_size; 12876 const tsn_stu_info_t *ctrl_info = NULL; 12877 bcm_tsn_stu_profile_type_t type; 12878 12879 BCM_IF_ERROR_RETURN( 12880 tsn_bk_info_instance_get(unit, &bk_info)); 12881 /* Allocate STU bookkeeping structure */ 12882 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 12883 STU_DEV_INIT(unit); 12884 ctrl_info = bk_info->tsn_dev_info->tsn_stu_info; 12885 for (type = bcmTsnStuProfileTypeIngress; 12886 type < bcmTsnStuProfileTypeCount; type++) { 12887 if (bk_info->tsn_stu_bk_info.stu_refcount[type] == NULL) { 12888 ctrl_info->stu_profile_mem_idx_get(unit, type, &min, &max); 12889 alloc_size = (max - min + 1) * sizeof(int); 12890 TSN_ALLOC(unit, bk_info->tsn_stu_bk_info.stu_refcount[type], 12891 int, alloc_size, "Ingress STU Reference Count", 12892 0, rv); 12893 } 12894 if (BCM_FAILURE(rv)) { 12895 LOG_VERBOSE(BSL_LS_BCM_TSN, 12896 (BSL_META_U(unit, 12897 "bcmi_esw_tsn_init: failed to " 12898 "allocate memory\n"))); 12899 return rv; 12900 } 12901 } 12902 if (bk_info->tsn_stu_bk_info.pri_map_port == NULL) { 12903 alloc_size = 12904 ctrl_info->logical_port_num * sizeof(bcm_tsn_pri_map_t); 12905 TSN_ALLOC(unit, bk_info->tsn_stu_bk_info.pri_map_port, 12906 bcm_tsn_pri_map_t, alloc_size, 12907 "STU Priority Map Port Array", 0, rv); 12908 } 12909 if (BCM_FAILURE(rv)) { 12910 LOG_VERBOSE(BSL_LS_BCM_TSN, 12911 (BSL_META_U(unit, 12912 "bcmi_esw_tsn_init: failed to " 12913 "allocate memory\n"))); 12914 return rv; 12915 } 12916 /* Initialize pri_map_port array */ 12917 for (i = 0; i < ctrl_info->logical_port_num; i++) { 12918 bk_info->tsn_stu_bk_info.pri_map_port[i] = BCM_TSN_PRI_MAP_INVALID; 12919 } 12920 /* Create STU mutex */ 12921 bk_info->tsn_stu_bk_info.mutex = sal_mutex_create("stu_mutex"); 12922 if (bk_info->tsn_stu_bk_info.mutex == NULL) { 12923 return BCM_E_MEMORY; 12924 } 12925 } 12926 return BCM_E_NONE; 12927 } 12928 12929 12930 /* Start of tsn event functions */ 12931 /* 12932 * Event instance information 12933 * NOTE: index order should be the same with bcmi_tsn_evt_inst_type_t 12934 */ 12935 STATIC const tsn_evt_inst_alloc_t tsn_evt_inst_info[bcmiTsnEvtCount] = { 12936 {bcmiTsnEvtCESys, 12937 bcmTsnEventTypeCounterExceeded, BCM_TSN_EVENT_SOURCE_TYPE_SYSTEM, 12938 TSN_EVENT_SYSTEM_CB_MAX}, 12939 {bcmiTsnEvtCEFlow, 12940 bcmTsnEventTypeCounterExceeded, BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW, 12941 TSN_EVENT_FLOW_CB_MAX}, 12942 {bcmiTsnEvtCEPort, 12943 bcmTsnEventTypeCounterExceeded, BCM_TSN_EVENT_SOURCE_TYPE_PORT, 12944 TSN_EVENT_PORT_CB_MAX}, 12945 {bcmiTsnEvtWLASys, 12946 bcmTsnEventTypeSrWrongLanA, BCM_TSN_EVENT_SOURCE_TYPE_SYSTEM, 12947 TSN_EVENT_SYSTEM_CB_MAX}, 12948 {bcmiTsnEvtWLAFlow, 12949 bcmTsnEventTypeSrWrongLanA, BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW, 12950 TSN_EVENT_FLOW_CB_MAX}, 12951 {bcmiTsnEvtWLBSys, 12952 bcmTsnEventTypeSrWrongLanB, BCM_TSN_EVENT_SOURCE_TYPE_SYSTEM, 12953 TSN_EVENT_SYSTEM_CB_MAX}, 12954 {bcmiTsnEvtWLBFlow, 12955 bcmTsnEventTypeSrWrongLanB, BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW, 12956 TSN_EVENT_FLOW_CB_MAX}, 12957 {bcmiTsnEvtSNSys, 12958 bcmTsnEventTypeSrSeqNumWindowAgeOut, BCM_TSN_EVENT_SOURCE_TYPE_SYSTEM, 12959 TSN_EVENT_SYSTEM_CB_MAX}, 12960 {bcmiTsnEvtSNFlow, 12961 bcmTsnEventTypeSrSeqNumWindowAgeOut, BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW, 12962 TSN_EVENT_FLOW_CB_MAX} 12963 }; 12964 12965 #if defined(BCM_TSN_SR_SUPPORT) 12966 /* 12967 * Invoked from bcmi_esw_tsn_sr_rx_flowset_create to maintain the active rx flow 12968 * database in device. 12969 */ 12970 STATIC int 12971 bcmi_esw_tsn_event_rx_flow_add(int unit, int fidx) 12972 { 12973 uint32 hw_id; 12974 12975 SR_FLOW_MGMT_DEVINFO(unit)->get_hw_flow_id( 12976 unit, 0, fidx, &hw_id); 12977 if (TSN_EVENT_DEVINFO(unit)->update_rx_flow) { 12978 BCM_IF_ERROR_RETURN( 12979 TSN_EVENT_DEVINFO(unit)->update_rx_flow(unit, -1, hw_id, 1)); 12980 } 12981 return BCM_E_UNAVAIL; 12982 } 12983 12984 STATIC int 12985 bcmi_esw_tsn_event_rx_flow_delete(int unit, int fidx) 12986 { 12987 uint32 hw_id; 12988 12989 SR_FLOW_MGMT_DEVINFO(unit)->get_hw_flow_id( 12990 unit, 0, fidx, &hw_id); 12991 if (TSN_EVENT_DEVINFO(unit)->update_rx_flow) { 12992 BCM_IF_ERROR_RETURN( 12993 TSN_EVENT_DEVINFO(unit)->update_rx_flow(unit, -1, hw_id, 0)); 12994 } 12995 return BCM_E_UNAVAIL; 12996 } 12997 12998 /* 12999 * Handle flow based event 13000 * bcmTsnEventTypeSrWrongLanA, bcmTsnEventTypeSrWrongLanB, 13001 * bcmTsnEventTypeSrSeqNumWindowAgeOut 13002 */ 13003 STATIC int 13004 bcmi_esw_tsn_flow_event_notify( 13005 int unit, 13006 bcm_tsn_event_type_t event, 13007 int multiple, 13008 int hw_flow_id) 13009 { 13010 bcmi_esw_tsn_bk_info_t *tsn_bk; 13011 tsn_event_bk_t *bkinfo; 13012 int rv = BCM_E_NONE, i; 13013 tsn_evt_stat_t *evt_stat; 13014 tsn_evt_regist_t *er; 13015 tsn_evt_inst_t *einst; 13016 bcm_tsn_event_source_t src; 13017 bcmi_tsn_evt_inst_type_t evt_inst_type; 13018 bcm_tsn_sr_flow_t flow_id; 13019 13020 /* parameter check */ 13021 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 13022 bkinfo = &tsn_bk->tsn_events; 13023 13024 TSN_EVENT_LOCK(unit); 13025 evt_stat = &bkinfo->evt_stat[event]; 13026 SHR_BITCLR_RANGE(evt_stat->fbmp, 0, _SHR_BITDCLSIZE(bkinfo->max_flows)); 13027 SHR_BITCLR_RANGE(evt_stat->ffbmp, 0, _SHR_BITDCLSIZE(bkinfo->max_flows)); 13028 13029 if ((event == bcmTsnEventTypeSrWrongLanA) || 13030 (event == bcmTsnEventTypeSrWrongLanB) || 13031 (event == bcmTsnEventTypeSrSeqNumWindowAgeOut)) { 13032 if (TSN_EVENT_DEVINFO(unit)->event_flow_stat_get) { 13033 rv = TSN_EVENT_DEVINFO(unit)-> 13034 event_flow_stat_get(unit, event, evt_stat->fbmp, 13035 evt_stat->ffbmp, 13036 bkinfo->max_flows); 13037 if (BCM_FAILURE(rv)) { 13038 TSN_EVENT_UNLOCK(unit); 13039 return rv; 13040 } 13041 } 13042 if (!multiple) { 13043 SHR_BITCLR_RANGE(evt_stat->fbmp, 0, 13044 _SHR_BITDCLSIZE(bkinfo->max_flows)); 13045 SHR_BITSET(evt_stat->fbmp, hw_flow_id); 13046 } 13047 13048 /* Iter the flow id which indicate the wrong lan */ 13049 SHR_BIT_ITER(evt_stat->fbmp, bkinfo->max_flows, i) { 13050 BCM_IF_ERROR_RETURN( 13051 bcmi_esw_tsn_sr_sw_flow_id_get(unit, i, &flow_id)); 13052 if (SHR_BITGET(evt_stat->ffbmp, i)) { 13053 /* Wrong lan event, registered as per flow */ 13054 if (event == bcmTsnEventTypeSrWrongLanA) { 13055 evt_inst_type = bcmiTsnEvtWLAFlow; 13056 } else if (event == bcmTsnEventTypeSrWrongLanB) { 13057 evt_inst_type = bcmiTsnEvtWLBFlow; 13058 } else { 13059 evt_inst_type = bcmiTsnEvtSNFlow; 13060 } 13061 13062 er = &bkinfo->eregist[evt_inst_type]; 13063 TSN_REVT_LOCK(er); 13064 for (einst = er->evt_inst; einst != NULL; einst = einst->next) { 13065 /* matched the flow id with registerd source */ 13066 if (einst->sr_flow == flow_id) { 13067 if (NULL != einst->cb) { 13068 /* invoke registerd callback */ 13069 bcm_tsn_event_source_t_init(&src); 13070 src.source_type = BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW; 13071 src.sr_flow = einst->sr_flow; 13072 einst->cb(unit, event, &src, einst->user_data); 13073 } 13074 } 13075 } 13076 TSN_REVT_UNLOCK(er); 13077 } 13078 13079 /* Wrong lan event, registered as per system */ 13080 if (event == bcmTsnEventTypeSrWrongLanA) { 13081 evt_inst_type = bcmiTsnEvtWLASys; 13082 } else if (event == bcmTsnEventTypeSrWrongLanB) { 13083 evt_inst_type = bcmiTsnEvtWLBSys; 13084 } else { 13085 evt_inst_type = bcmiTsnEvtSNSys; 13086 } 13087 er = &bkinfo->eregist[evt_inst_type]; 13088 TSN_REVT_LOCK(er); 13089 for (einst = er->evt_inst; einst != NULL; einst = einst->next) { 13090 /* For src == system, callback with flow_id information */ 13091 if (NULL != einst->cb) { 13092 bcm_tsn_event_source_t_init(&src); 13093 src.source_type = BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW; 13094 src.sr_flow = flow_id; 13095 einst->cb(unit, event, &src, einst->user_data); 13096 } 13097 } 13098 TSN_REVT_UNLOCK(er); 13099 } 13100 /* Clear the event stat information */ 13101 if (TSN_EVENT_DEVINFO(unit)->event_flow_stat_clear) { 13102 rv = TSN_EVENT_DEVINFO(unit)-> 13103 event_flow_stat_clear(unit, event, evt_stat->fbmp, 13104 bkinfo->max_flows); 13105 } 13106 } 13107 TSN_EVENT_UNLOCK(unit); 13108 return rv; 13109 } 13110 #endif /* BCM_TSN_SR_SUPPORT */ 13111 13112 /* 13113 * Handle counter exceed event 13114 */ 13115 STATIC int 13116 bcmi_esw_tsn_cnt_exceed_notify( 13117 int unit, 13118 bcm_tsn_stat_t stat, 13119 bcm_tsn_stat_threshold_source_t th_src, 13120 int multiple, 13121 int index) 13122 { 13123 bcm_tsn_stat_threshold_config_t config; 13124 bcm_pbmp_t pbmp; 13125 bcm_port_t p; 13126 bcm_gport_t gport; 13127 uint64 hw_value, sw_value, th_value; 13128 bcmi_esw_tsn_bk_info_t *tsn_bk; 13129 tsn_event_bk_t *bkinfo; 13130 tsn_evt_regist_t *er; 13131 tsn_evt_inst_t *einst; 13132 bcm_tsn_event_source_t src; 13133 #if defined(BCM_TSN_SR_SUPPORT) 13134 tsn_evt_stat_t *evt_stat; 13135 int i; 13136 bcm_tsn_sr_flow_t flow_id; 13137 #endif 13138 13139 13140 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 13141 bkinfo = &tsn_bk->tsn_events; 13142 13143 /* Get the threshold value */ 13144 bcm_tsn_stat_threshold_config_t_init(&config); 13145 BCM_IF_ERROR_RETURN( 13146 bcmi_esw_tsn_stat_threshold_get(unit, th_src, stat, &config)); 13147 COMPILER_64_SET(th_value, 0, config.threshold); 13148 13149 if (th_src == bcmTsnStatThresholdSourcePort) { 13150 BCM_PBMP_CLEAR(pbmp); 13151 /* sync the port stat */ 13152 BCM_IF_ERROR_RETURN( 13153 bcmi_esw_tsn_stat_portcnt_stat_sync(unit, stat)); 13154 13155 if (multiple) { 13156 BCM_PBMP_ASSIGN(pbmp, PBMP_ALL(unit)); 13157 } else { 13158 BCM_PBMP_PORT_SET(pbmp, index); 13159 } 13160 /* Iterate valid port to compare the threshold value */ 13161 BCM_PBMP_ITER(pbmp, p) { 13162 BCM_IF_ERROR_RETURN( 13163 bcmi_esw_tsn_stat_portcnt_hw_sw_get(unit, stat, p, 13164 &hw_value, &sw_value)); 13165 BCM_IF_ERROR_RETURN(bcm_esw_port_gport_get(unit, p, &gport)); 13166 if (COMPILER_64_GT(hw_value, th_value)) { 13167 /* event registered with src = port */ 13168 er = &bkinfo->eregist[bcmiTsnEvtCEPort]; 13169 TSN_REVT_LOCK(er); 13170 for (einst = er->evt_inst; einst != NULL; einst = einst->next) { 13171 if (einst->port == p) { 13172 if (NULL != einst->cb) { 13173 bcm_tsn_event_source_t_init(&src); 13174 src.source_type = BCM_TSN_EVENT_SOURCE_TYPE_PORT; 13175 src.port = gport; 13176 einst->cb(unit, bcmTsnEventTypeCounterExceeded, 13177 &src, einst->user_data); 13178 } 13179 } 13180 } 13181 TSN_REVT_UNLOCK(er); 13182 /* event registered with src = system */ 13183 er = &bkinfo->eregist[bcmiTsnEvtCESys]; 13184 TSN_REVT_LOCK(er); 13185 for (einst = er->evt_inst; einst != NULL; einst = einst->next) { 13186 if (NULL != einst->cb) { 13187 bcm_tsn_event_source_t_init(&src); 13188 src.source_type = BCM_TSN_EVENT_SOURCE_TYPE_PORT; 13189 src.port = gport; 13190 einst->cb(unit, bcmTsnEventTypeCounterExceeded, 13191 &src, einst->user_data); 13192 } 13193 } 13194 TSN_REVT_UNLOCK(er); 13195 13196 /* Clear the HW value to avoid continuous threshold event */ 13197 COMPILER_64_ZERO(hw_value); 13198 BCM_IF_ERROR_RETURN( 13199 bcmi_esw_tsn_stat_portcnt_hw_set(unit, stat, p, hw_value)); 13200 } /* end of COMPILER_64_GT */ 13201 } /* end of valid port iter */ 13202 } 13203 if (th_src == bcmTsnStatThresholdSourceSRFlow) { 13204 #if defined(BCM_TSN_SR_SUPPORT) 13205 if (soc_feature(unit, soc_feature_tsn_sr)) { 13206 /* sync the flow stat */ 13207 BCM_IF_ERROR_RETURN( 13208 bcmi_esw_tsn_stat_flowcnt_stat_sync(unit, stat)); 13209 13210 evt_stat = &bkinfo->evt_stat[bcmTsnEventTypeCounterExceeded]; 13211 SHR_BITCLR_RANGE(evt_stat->fbmp, 0, 13212 _SHR_BITDCLSIZE(bkinfo->max_flows)); 13213 if (multiple) { 13214 BCM_IF_ERROR_RETURN( 13215 bcmi_esw_tsn_stat_flowcnt_fbmp_get( 13216 unit, stat, evt_stat->fbmp, 13217 _SHR_BITDCLSIZE(bkinfo->max_flows))); 13218 } else { 13219 SHR_BITSET(evt_stat->fbmp, index); 13220 } 13221 /* Iter the flows which support the stat */ 13222 SHR_BIT_ITER(evt_stat->fbmp, bkinfo->max_flows, i) { 13223 BCM_IF_ERROR_RETURN( 13224 bcmi_esw_tsn_sr_sw_flow_id_get(unit, i, &flow_id)); 13225 BCM_IF_ERROR_RETURN( 13226 bcmi_esw_tsn_stat_flowcnt_hw_sw_get(unit, stat, flow_id, 13227 &hw_value, &sw_value)); 13228 if (COMPILER_64_GT(hw_value, th_value)) { 13229 er = &bkinfo->eregist[bcmiTsnEvtCEFlow]; 13230 TSN_REVT_LOCK(er); 13231 for (einst = er->evt_inst; einst != NULL; 13232 einst = einst->next) { 13233 /* matched the flow id with registerd source */ 13234 if (einst->sr_flow == flow_id) { 13235 if (NULL != einst->cb) { 13236 /* invoke registerd callback */ 13237 bcm_tsn_event_source_t_init(&src); 13238 src.source_type = 13239 BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW; 13240 src.sr_flow = einst->sr_flow; 13241 einst->cb(unit, bcmTsnEventTypeCounterExceeded, 13242 &src, einst->user_data); 13243 } 13244 } 13245 } 13246 TSN_REVT_UNLOCK(er); 13247 er = &bkinfo->eregist[bcmiTsnEvtCESys]; 13248 TSN_REVT_LOCK(er); 13249 for (einst = er->evt_inst; einst != NULL; 13250 einst = einst->next) { 13251 /* 13252 * For src == system, 13253 * callback with flow_id information 13254 */ 13255 if (NULL != einst->cb) { 13256 bcm_tsn_event_source_t_init(&src); 13257 src.source_type = BCM_TSN_EVENT_SOURCE_TYPE_SYSTEM; 13258 src.sr_flow = flow_id; 13259 einst->cb(unit, bcmTsnEventTypeCounterExceeded, 13260 &src, einst->user_data); 13261 } 13262 } 13263 TSN_REVT_UNLOCK(er); 13264 /* Clear the HW value to avoid continuous threshold event */ 13265 COMPILER_64_ZERO(hw_value); 13266 BCM_IF_ERROR_RETURN( 13267 bcmi_esw_tsn_stat_flowcnt_hw_set(unit, stat, flow_id, 13268 hw_value)); 13269 } 13270 } 13271 } else 13272 #endif /* BCM_TSN_SR_SUPPORT */ 13273 { 13274 /* Do nothing */ 13275 return BCM_E_NONE; 13276 } 13277 } 13278 return BCM_E_NONE; 13279 } 13280 13281 void bcmi_tsn_event_poll(void *unit_vp) 13282 { 13283 int unit = PTR_TO_INT(unit_vp); 13284 bcmi_esw_tsn_bk_info_t *tsn_bk; 13285 tsn_event_bk_t *bkinfo; 13286 sal_usecs_t interval; 13287 int rv; 13288 13289 /* parameter check */ 13290 rv = tsn_bk_info_instance_get(unit, &tsn_bk); 13291 if (BCM_FAILURE(rv)) { 13292 LOG_ERROR(BSL_LS_BCM_TSN, 13293 (BSL_META_U(unit, 13294 "TSN EVT: failed to get the tsn bkinfo\n"))); 13295 return; 13296 } 13297 13298 bkinfo = &tsn_bk->tsn_events; 13299 13300 while (bkinfo->poll_enable) { 13301 if (bkinfo->poll_interval != 0) { 13302 interval = (bkinfo->poll_interval) * MILLISECOND_USEC; 13303 } else { 13304 interval = TSN_EVENT_POLL_INTERVAL_DEFAULT; 13305 } 13306 13307 (void)sal_sem_take(bkinfo->poll_notify, interval); 13308 13309 if (bkinfo->poll_enable == 0) { 13310 break; 13311 } 13312 13313 /* invoke device poll function */ 13314 if (TSN_EVENT_DEVINFO(unit)->poll) { 13315 (void)TSN_EVENT_DEVINFO(unit)->poll(unit); 13316 } 13317 13318 } 13319 bkinfo->poll_tid = SAL_THREAD_ERROR; 13320 bkinfo->poll_interval = 0; 13321 bkinfo->poll_enable = 0; 13322 13323 sal_thread_exit(0); 13324 } 13325 13326 STATIC int 13327 bcmi_esw_tsn_evt_poll_config(int unit, int enable) 13328 { 13329 bcmi_esw_tsn_bk_info_t *tsn_bk; 13330 tsn_event_bk_t *bkinfo; 13331 soc_timeout_t to; 13332 int rv = BCM_E_NONE; 13333 13334 /* parameter check */ 13335 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 13336 bkinfo = &tsn_bk->tsn_events; 13337 13338 if (enable) { 13339 if (bkinfo->poll_tid && bkinfo->poll_tid != SAL_THREAD_ERROR) { 13340 /* Thead existed and running. invoke poll function */ 13341 sal_sem_give(bkinfo->poll_notify); 13342 return BCM_E_NONE; 13343 } 13344 TSN_EVENT_LOCK(unit); 13345 if ((bkinfo->poll_tid == NULL) || 13346 (bkinfo->poll_tid == SAL_THREAD_ERROR)) { 13347 bkinfo->poll_tid = sal_thread_create("bcmTSN", SAL_THREAD_STKSZ, 50, 13348 bcmi_tsn_event_poll, 13349 INT_TO_PTR(unit)); 13350 if (bkinfo->poll_tid == SAL_THREAD_ERROR) { 13351 LOG_ERROR(BSL_LS_BCM_TSN, 13352 (BSL_META_U(unit, 13353 "TSN EVT: failed to create thread\n"))); 13354 TSN_EVENT_UNLOCK(unit); 13355 return BCM_E_MEMORY; 13356 } 13357 } 13358 TSN_EVENT_UNLOCK(unit); 13359 } else { 13360 TSN_EVENT_LOCK(unit); 13361 bkinfo->poll_interval = 0; 13362 bkinfo->poll_enable = 0; 13363 TSN_EVENT_UNLOCK(unit); 13364 if (bkinfo->poll_tid && bkinfo->poll_tid != SAL_THREAD_ERROR) { 13365 sal_sem_give(bkinfo->poll_notify); 13366 if (SAL_BOOT_SIMULATION) { 13367 soc_timeout_init(&to, 300 * 1000000, 0); 13368 } else { 13369 soc_timeout_init(&to, 60 * 1000000, 0); 13370 } 13371 13372 while (bkinfo->poll_tid != SAL_THREAD_ERROR) { 13373 if (soc_timeout_check(&to)) { 13374 LOG_ERROR(BSL_LS_BCM_TSN, 13375 (BSL_META_U(unit, 13376 "TSN thread will not exit\n"))); 13377 rv = BCM_E_INTERNAL; 13378 break; 13379 } 13380 } 13381 } 13382 } 13383 return rv; 13384 } 13385 13386 /* Internal function invoke when tsnControl change */ 13387 STATIC void 13388 bcmi_esw_tsn_evt_ageout_config(int unit, bcm_tsn_control_t type, uint32 arg) 13389 { 13390 bcmi_esw_tsn_bk_info_t *tsn_bk; 13391 tsn_event_bk_t *bkinfo; 13392 uint32 enable, interval = 0, rmode; 13393 uint8 change = 0, rmode_change = 0; 13394 13395 /* parameter check */ 13396 if (BCM_FAILURE(tsn_bk_info_instance_get(unit, &tsn_bk))) { 13397 return; 13398 } 13399 bkinfo = &tsn_bk->tsn_events; 13400 13401 TSN_EVENT_LOCK(unit); 13402 13403 /* 13404 * Interested in bcmTsnControlSrAgeTickInterval, 13405 * bcmTsnControlSrAgeOutEnable 13406 * bcmTsnControlSrSeqNumWindowResetMode 13407 */ 13408 enable = bkinfo->pre_enable; 13409 if (type == bcmTsnControlSrAgeTickInterval) { 13410 interval = arg; 13411 if (bkinfo->pre_interval != interval) { 13412 change = 1; 13413 } 13414 bkinfo->pre_interval = interval; 13415 } else if (type == bcmTsnControlSrAgeOutEnable) { 13416 enable = arg; 13417 if (bkinfo->pre_enable != enable) { 13418 change = 1; 13419 } 13420 bkinfo->pre_enable = enable; 13421 } else if (type == bcmTsnControlSrSeqNumWindowResetMode) { 13422 rmode = arg; 13423 if ((bkinfo->pre_rmode != rmode) && 13424 (rmode == BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_SW || 13425 bkinfo->pre_rmode == 13426 BCM_TSN_CONTROL_SR_SEQNUM_WINDOW_RESET_MODE_SW)) { 13427 rmode_change = 1; 13428 } 13429 bkinfo->pre_rmode = rmode; 13430 } else { 13431 TSN_EVENT_UNLOCK(unit); 13432 return; 13433 } 13434 13435 /* update the poll thread parameter */ 13436 bkinfo->poll_interval = bkinfo->pre_interval; 13437 13438 bkinfo->poll_enable = enable; 13439 13440 TSN_EVENT_UNLOCK(unit); 13441 13442 if ((change) || (rmode_change)) { 13443 bcmi_esw_tsn_evt_poll_config(unit, enable); 13444 } 13445 return; 13446 } 13447 13448 /* Free event instance resource */ 13449 STATIC int 13450 bcmi_esw_tsn_evt_inst_free( 13451 int unit, 13452 bcmi_tsn_evt_inst_type_t inst_type, 13453 tsn_evt_inst_t *entry) 13454 { 13455 bcmi_esw_tsn_bk_info_t *tsn_bk; 13456 tsn_event_bk_t *bkinfo; 13457 13458 /* parameter check */ 13459 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 13460 if (inst_type < 0 || inst_type >= bcmiTsnEvtCount || entry == NULL) { 13461 return BCM_E_PARAM; 13462 } 13463 bkinfo = &tsn_bk->tsn_events; 13464 TSN_EVENT_LOCK(unit); 13465 /* Put it back to the head */ 13466 entry->next = bkinfo->einst_avail[inst_type]; 13467 bkinfo->einst_avail[inst_type] = entry; 13468 TSN_EVENT_UNLOCK(unit); 13469 13470 return BCM_E_NONE; 13471 } 13472 13473 /* Allocate event instance */ 13474 STATIC int 13475 bcmi_esw_tsn_evt_inst_allocate( 13476 int unit, 13477 bcmi_tsn_evt_inst_type_t inst_type, 13478 tsn_evt_inst_t **entry) 13479 { 13480 bcmi_esw_tsn_bk_info_t *tsn_bk; 13481 tsn_event_bk_t *bkinfo; 13482 tsn_evt_inst_t *einst; 13483 13484 /* parameter check */ 13485 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 13486 if (inst_type < 0 || inst_type >= bcmiTsnEvtCount || entry == NULL) { 13487 return BCM_E_PARAM; 13488 } 13489 bkinfo = &tsn_bk->tsn_events; 13490 13491 TSN_EVENT_LOCK(unit); 13492 /* Get one entry from the head */ 13493 einst = bkinfo->einst_avail[inst_type]; 13494 if (einst == NULL) { 13495 TSN_EVENT_UNLOCK(unit); 13496 return BCM_E_RESOURCE; 13497 } 13498 bkinfo->einst_avail[inst_type] = einst->next; 13499 einst->next = NULL; 13500 *entry = einst; 13501 TSN_EVENT_UNLOCK(unit); 13502 13503 return BCM_E_NONE; 13504 } 13505 13506 STATIC int 13507 bcmi_esw_tsn_event_mgmt_detach(int unit) 13508 { 13509 bcmi_esw_tsn_bk_info_t *tsn_bk; 13510 tsn_event_bk_t *bkinfo; 13511 tsn_evt_regist_t *eregist; 13512 int i; 13513 13514 /* parameter check */ 13515 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 13516 13517 bkinfo = &tsn_bk->tsn_events; 13518 13519 if (bkinfo->poll_notify) { 13520 if (bkinfo->poll_enable) { 13521 BCM_IF_ERROR_RETURN(bcmi_esw_tsn_evt_poll_config(unit, 0)); 13522 } 13523 sal_sem_destroy(bkinfo->poll_notify); 13524 bkinfo->poll_notify = NULL; 13525 } 13526 /* de-allocate event instance pool */ 13527 if (NULL != bkinfo->einst_allocated) { 13528 sal_free(bkinfo->einst_allocated); 13529 bkinfo->einst_allocated = NULL; 13530 } 13531 /* de-allocate event mgmt mutex */ 13532 if (NULL != bkinfo->evt_mutex) { 13533 sal_mutex_destroy(bkinfo->evt_mutex); 13534 bkinfo->evt_mutex = NULL; 13535 } 13536 13537 for (i = 0; i < bcmiTsnEvtCount; i++) { 13538 /* clear linked list */ 13539 bkinfo->einst_avail[i] = NULL; 13540 /* destroy mutex */ 13541 eregist = &bkinfo->eregist[i]; 13542 if (NULL != eregist->mutex) { 13543 sal_mutex_destroy(eregist->mutex); 13544 eregist->mutex = NULL; 13545 } 13546 } 13547 for (i = 0; i < bcmTsnEventTypeCount; i++) { 13548 /* de-allocate register event instance */ 13549 if (NULL != bkinfo->evt_stat[i].port_ref) { 13550 sal_free(bkinfo->evt_stat[i].port_ref); 13551 bkinfo->evt_stat[i].port_ref = NULL; 13552 } 13553 if (NULL != bkinfo->evt_stat[i].flow_ref) { 13554 sal_free(bkinfo->evt_stat[i].flow_ref); 13555 bkinfo->evt_stat[i].flow_ref = NULL; 13556 } 13557 if (NULL != bkinfo->evt_stat[i].pbmp) { 13558 sal_free(bkinfo->evt_stat[i].pbmp); 13559 bkinfo->evt_stat[i].pbmp = NULL; 13560 } 13561 if (NULL != bkinfo->evt_stat[i].fbmp) { 13562 sal_free(bkinfo->evt_stat[i].fbmp); 13563 bkinfo->evt_stat[i].fbmp = NULL; 13564 } 13565 if (NULL != bkinfo->evt_stat[i].ffbmp) { 13566 sal_free(bkinfo->evt_stat[i].ffbmp); 13567 bkinfo->evt_stat[i].ffbmp = NULL; 13568 } 13569 } 13570 return BCM_E_NONE; 13571 } 13572 13573 /* event management initialization */ 13574 STATIC int 13575 bcmi_esw_tsn_event_mgmt_init(int unit) 13576 { 13577 bcmi_esw_tsn_bk_info_t *tsn_bk; 13578 tsn_event_bk_t *bkinfo; 13579 tsn_evt_inst_t *einst; 13580 int i, j, total_insts, maxflows = 0, maxports; 13581 tsn_evt_regist_t *eregist; 13582 tsn_evt_stat_t *evt_stat; 13583 bcm_pbmp_t all_pbmp; 13584 #if defined(BCM_TSN_SR_SUPPORT) 13585 tsn_sr_flows_bookkeeping_t *sr_flow_bkinfo; 13586 #endif 13587 13588 /* parameter check */ 13589 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 13590 13591 bkinfo = &tsn_bk->tsn_events; 13592 if (TSN_EVENT_DEVINFO(unit) == NULL) { 13593 return BCM_E_UNAVAIL; 13594 } 13595 13596 /* Allocate event cb link list */ 13597 total_insts = 0; 13598 for (i = 0; i < bcmiTsnEvtCount; i++) { 13599 total_insts += tsn_evt_inst_info[i].inst_limits; 13600 } 13601 13602 bkinfo->einst_allocated = (tsn_evt_inst_t *)sal_alloc( 13603 sizeof(tsn_evt_inst_t) * total_insts, 13604 "tsn event instances"); 13605 if (NULL == bkinfo->einst_allocated) { 13606 LOG_ERROR(BSL_LS_BCM_TSN, 13607 (BSL_META_U(unit, 13608 "TSN EVNT: failed to alloc event instance\n"))); 13609 (void)bcmi_esw_tsn_event_mgmt_detach(unit); 13610 return BCM_E_MEMORY; 13611 } 13612 sal_memset(bkinfo->einst_allocated, 0, 13613 sizeof(tsn_evt_inst_t) * total_insts); 13614 13615 /* Retrieve number of flows */ 13616 #if defined(BCM_TSN_SR_SUPPORT) 13617 if (soc_feature(unit, soc_feature_tsn_sr)) { 13618 sr_flow_bkinfo = &tsn_bk->sr_flows; 13619 if (sr_flow_bkinfo != NULL && 13620 sr_flow_bkinfo->max_flows[SR_FLOW_DIR_TX] != 0 && 13621 sr_flow_bkinfo->max_flows[SR_FLOW_DIR_RX] != 0) { 13622 maxflows = sr_flow_bkinfo->max_flows[SR_FLOW_DIR_TX] + 13623 sr_flow_bkinfo->max_flows[SR_FLOW_DIR_RX]; 13624 bkinfo->max_rx_flows = sr_flow_bkinfo->max_flows[SR_FLOW_DIR_RX]; 13625 } else { 13626 LOG_ERROR(BSL_LS_BCM_TSN, 13627 (BSL_META_U(unit, 13628 "TSN EVNT: failed to get sr flow information.\n"))); 13629 return BCM_E_INTERNAL; 13630 } 13631 } 13632 #endif /* BCM_TSN_SR_SUPPORT */ 13633 bkinfo->max_flows = maxflows; 13634 13635 einst = bkinfo->einst_allocated; 13636 for (i = 0; i < bcmiTsnEvtCount; i++) { 13637 for (j = 0; j < tsn_evt_inst_info[i].inst_limits; j++, einst++) { 13638 /* Initialize available linked list */ 13639 einst->next = bkinfo->einst_avail[i]; 13640 bkinfo->einst_avail[i] = einst; 13641 } 13642 13643 /* Initialize registered events instance */ 13644 sal_memset(&bkinfo->eregist[i], 0, sizeof(tsn_evt_regist_t)); 13645 eregist = &bkinfo->eregist[i]; 13646 eregist->source_type = tsn_evt_inst_info[i].source_type; 13647 eregist->inst_type = tsn_evt_inst_info[i].inst_type; 13648 eregist->evt_type = tsn_evt_inst_info[i].evt_type; 13649 13650 /* Create mutex */ 13651 eregist->mutex = sal_mutex_create("tsn evt register mutex"); 13652 if (NULL == eregist->mutex) { 13653 LOG_ERROR(BSL_LS_BCM_TSN, 13654 (BSL_META_U(unit, 13655 "TSN EVT: " 13656 "failed to create register mutex\n"))); 13657 (void)bcmi_esw_tsn_event_mgmt_detach(unit); 13658 return BCM_E_MEMORY; 13659 } 13660 } 13661 /* Get the max port in the system */ 13662 maxports = 0; 13663 BCM_PBMP_CLEAR(all_pbmp); 13664 /* Get the all valid port map */ 13665 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 13666 /* Iterate the bitmap to get the maximum port number */ 13667 BCM_PBMP_ITER(all_pbmp, i) { 13668 maxports = i; 13669 } 13670 /* Total port counts should be (maximum port number + 1) */ 13671 bkinfo->max_ports = maxports + 1; 13672 for (i = 0; i < bcmTsnEventTypeCount; i++) { 13673 /* Allocate and initialize the event stat */ 13674 evt_stat = &bkinfo->evt_stat[i]; 13675 evt_stat->event_ref = 0; 13676 evt_stat->port_ref = sal_alloc(bkinfo->max_ports * sizeof(int), 13677 "alloc evt port basis stat"); 13678 if (NULL == evt_stat->port_ref) { 13679 LOG_ERROR(BSL_LS_BCM_TSN, 13680 (BSL_META_U(unit, 13681 "TSN EVT: failed to create evt stat \n"))); 13682 (void)bcmi_esw_tsn_event_mgmt_detach(unit); 13683 return BCM_E_MEMORY; 13684 } 13685 sal_memset(evt_stat->port_ref, 0, bkinfo->max_ports * sizeof(int)); 13686 13687 evt_stat->flow_ref = sal_alloc(maxflows * sizeof(int), 13688 "alloc evt flow basis stat"); 13689 if (NULL == evt_stat->flow_ref) { 13690 LOG_ERROR(BSL_LS_BCM_TSN, 13691 (BSL_META_U(unit, 13692 "TSN EVT: failed to create evt stat \n"))); 13693 (void)bcmi_esw_tsn_event_mgmt_detach(unit); 13694 return BCM_E_MEMORY; 13695 } 13696 sal_memset(evt_stat->flow_ref, 0, bkinfo->max_ports * sizeof(int)); 13697 13698 evt_stat->pbmp = sal_alloc(SHR_BITALLOCSIZE(bkinfo->max_ports), 13699 "alloc evt stat pbmp"); 13700 if (NULL == evt_stat->pbmp) { 13701 LOG_ERROR(BSL_LS_BCM_TSN, 13702 (BSL_META_U(unit, 13703 "TSN EVT: failed to alloc evt stat pbmp\n"))); 13704 (void)bcmi_esw_tsn_event_mgmt_detach(unit); 13705 return BCM_E_MEMORY; 13706 } 13707 sal_memset(evt_stat->pbmp, 0, SHR_BITALLOCSIZE(bkinfo->max_ports)); 13708 evt_stat->fbmp = sal_alloc(SHR_BITALLOCSIZE(maxflows), 13709 "alloc evt stat fbmp"); 13710 if (NULL == evt_stat->fbmp) { 13711 LOG_ERROR(BSL_LS_BCM_TSN, 13712 (BSL_META_U(unit, 13713 "TSN EVT: failed to alloc evt stat fbmp\n"))); 13714 (void)bcmi_esw_tsn_event_mgmt_detach(unit); 13715 return BCM_E_MEMORY; 13716 } 13717 sal_memset(evt_stat->fbmp, 0, SHR_BITALLOCSIZE(maxflows)); 13718 evt_stat->ffbmp = sal_alloc(SHR_BITALLOCSIZE(maxflows), 13719 "alloc evt stat ffbmp"); 13720 if (NULL == evt_stat->ffbmp) { 13721 LOG_ERROR(BSL_LS_BCM_TSN, 13722 (BSL_META_U(unit, 13723 "TSN EVT: " 13724 "failed to alloc evt stat ffbmp\n"))); 13725 (void)bcmi_esw_tsn_event_mgmt_detach(unit); 13726 return BCM_E_MEMORY; 13727 } 13728 sal_memset(evt_stat->ffbmp, 0, SHR_BITALLOCSIZE(maxflows)); 13729 } 13730 13731 /* Create mutex for protecting event management (allocate/free) */ 13732 bkinfo->evt_mutex = sal_mutex_create("tsn evt mgmt mutex"); 13733 if (NULL == bkinfo->evt_mutex) { 13734 LOG_ERROR(BSL_LS_BCM_TSN, 13735 (BSL_META_U(unit, 13736 "TSN EVT: failed to create event mgmt mutex\n"))); 13737 (void)bcmi_esw_tsn_event_mgmt_detach(unit); 13738 return BCM_E_MEMORY; 13739 } 13740 13741 /* Create poll notify */ 13742 bkinfo->poll_notify = sal_sem_create("TSN EVT poll", sal_sem_BINARY, 0); 13743 if (NULL == bkinfo->poll_notify) { 13744 LOG_ERROR(BSL_LS_BCM_TSN, 13745 (BSL_META_U(unit, 13746 "TSN EVT: failed to create event poll " 13747 "notify\n"))); 13748 (void)bcmi_esw_tsn_event_mgmt_detach(unit); 13749 return BCM_E_MEMORY; 13750 } 13751 #if defined(BCM_TSN_SR_SUPPORT) 13752 if (soc_feature(unit, soc_feature_tsn_sr)) { 13753 /* Register the event notify callback */ 13754 if (TSN_EVENT_DEVINFO(unit)->register_flow_event_cb) { 13755 (void)TSN_EVENT_DEVINFO(unit)->register_flow_event_cb( 13756 unit, bcmi_esw_tsn_flow_event_notify); 13757 } 13758 } 13759 #endif /* BCM_TSN_SR_SUPPORT */ 13760 if (TSN_EVENT_DEVINFO(unit)->register_cnt_exceed_cb) { 13761 (void)TSN_EVENT_DEVINFO(unit)->register_cnt_exceed_cb( 13762 unit, bcmi_esw_tsn_cnt_exceed_notify); 13763 } 13764 13765 return BCM_E_NONE; 13766 } 13767 13768 STATIC int 13769 bcmi_esw_tsn_event_validate( 13770 int unit, 13771 bcmi_tsn_evt_inst_type_t inst_type, 13772 bcm_tsn_event_source_t *src) 13773 { 13774 bcmi_esw_tsn_bk_info_t *tsn_bk; 13775 bcm_port_t port; 13776 #if defined(BCM_TSN_SR_SUPPORT) 13777 tsn_sr_flows_bookkeeping_t *sr_flow_bkinfo; 13778 bcm_tsn_sr_flow_t flow_id = src->sr_flow; 13779 int fidx; 13780 int dir; 13781 #endif 13782 13783 /* parameter check */ 13784 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 13785 13786 if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_PORT) { 13787 if (BCM_GPORT_IS_SET(src->port)) { 13788 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, src->port, &port)); 13789 } else { 13790 port = src->port; 13791 } 13792 if (!SOC_PORT_VALID(unit, port) || 13793 !SOC_PBMP_MEMBER(PBMP_ALL(unit), port)) { 13794 return BCM_E_PARAM; 13795 } 13796 } 13797 if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW) { 13798 #if defined(BCM_TSN_SR_SUPPORT) 13799 if (soc_feature(unit, soc_feature_tsn_sr)) { 13800 sr_flow_bkinfo = &tsn_bk->sr_flows; 13801 dir = SR_FLOW_ID_TO_DIR(flow_id); 13802 fidx = SR_FLOW_ID_TO_IDX(flow_id); 13803 if (fidx < 0 || 13804 fidx >= sr_flow_bkinfo->max_flows[dir]) { 13805 return BCM_E_PARAM; 13806 } 13807 } else 13808 #endif /* BCM_TSN_SR_SUPPORT */ 13809 { 13810 return BCM_E_PARAM; 13811 } 13812 } 13813 13814 if (TSN_EVENT_DEVINFO(unit) == NULL) { 13815 return BCM_E_UNAVAIL; 13816 } 13817 if (TSN_EVENT_DEVINFO(unit)->validate_event) { 13818 return TSN_EVENT_DEVINFO(unit)->validate_event(unit, inst_type); 13819 } 13820 return BCM_E_UNAVAIL; 13821 } 13822 13823 /* Enable /disable the event mask */ 13824 STATIC int 13825 bcmi_esw_tsn_event_mask_set(int unit, bcm_tsn_event_type_t event, int enable) 13826 { 13827 if (TSN_EVENT_DEVINFO(unit) == NULL) { 13828 return BCM_E_UNAVAIL; 13829 } 13830 if (TSN_EVENT_DEVINFO(unit)->event_mask_set) { 13831 return TSN_EVENT_DEVINFO(unit)->event_mask_set(unit, event, enable); 13832 } 13833 return BCM_E_UNAVAIL; 13834 } 13835 13836 STATIC int 13837 bcmi_esw_tsn_event_register( 13838 int unit, 13839 bcm_tsn_event_type_t event, 13840 bcm_tsn_event_source_t *src, 13841 bcm_tsn_event_cb cb, 13842 void *user_data) 13843 { 13844 int i, rv = BCM_E_NONE, event_count; 13845 #if defined(BCM_TSN_SR_SUPPORT) 13846 uint32 idx; 13847 #endif 13848 bcmi_tsn_evt_inst_type_t inst_type; 13849 tsn_evt_regist_t *er; 13850 tsn_evt_inst_t *einst, *einst_alloc; 13851 bcmi_esw_tsn_bk_info_t *tsn_bk; 13852 tsn_event_bk_t *bkinfo; 13853 tsn_evt_stat_t *evt_stat; 13854 bcm_port_t port; 13855 13856 if ((cb == NULL) || (src == NULL)) { 13857 return BCM_E_PARAM; 13858 } 13859 13860 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 13861 13862 bkinfo = &tsn_bk->tsn_events; 13863 if (TSN_EVENT_DEVINFO(unit) == NULL) { 13864 return BCM_E_UNAVAIL; 13865 } 13866 13867 /* get the internal instance type */ 13868 inst_type = bcmiTsnEvtCount; 13869 for (i = 0; i < bcmiTsnEvtCount; i++) { 13870 if ((tsn_evt_inst_info[i].source_type == src->source_type) && 13871 (tsn_evt_inst_info[i].evt_type == event)) { 13872 inst_type = tsn_evt_inst_info[i].inst_type; 13873 break; 13874 } 13875 } 13876 if (inst_type == bcmiTsnEvtCount) { 13877 return BCM_E_PARAM; 13878 } 13879 BCM_IF_ERROR_RETURN(bcmi_esw_tsn_event_validate(unit, inst_type, src)); 13880 13881 if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_PORT) { 13882 if (BCM_GPORT_IS_SET(src->port)) { 13883 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, src->port, &port)); 13884 } else { 13885 port = src->port; 13886 } 13887 } else { 13888 port = 0; 13889 } 13890 TSN_EVENT_LOCK(unit); 13891 er = &bkinfo->eregist[inst_type]; 13892 TSN_REVT_LOCK(er); 13893 if (NULL == er->evt_inst) { 13894 /* registered instance type array is empty */ 13895 /* allocate the event instance from pool */ 13896 rv = bcmi_esw_tsn_evt_inst_allocate(unit, inst_type, &einst_alloc); 13897 if (BCM_FAILURE(rv)) { 13898 TSN_REVT_UNLOCK(er); 13899 TSN_EVENT_UNLOCK(unit); 13900 return rv; 13901 } 13902 /* Put it on the head of registered event instance list */ 13903 einst_alloc->cb = cb; 13904 einst_alloc->user_data = user_data; 13905 einst_alloc->port = port; 13906 einst_alloc->sr_flow = src->sr_flow; 13907 einst_alloc->next = NULL; 13908 er->evt_inst = einst_alloc; 13909 } else { 13910 /* registered instance type array is available */ 13911 for (einst = er->evt_inst; einst != NULL; einst = einst->next) { 13912 if ((einst->cb == cb) && (einst->port == port) && 13913 (einst->sr_flow == src->sr_flow)) { 13914 /* matched the callback and event source */ 13915 TSN_REVT_UNLOCK(er); 13916 TSN_EVENT_UNLOCK(unit); 13917 return BCM_E_EXISTS; 13918 } else { 13919 /* not exactly matched instance, allocate a new one */ 13920 rv = bcmi_esw_tsn_evt_inst_allocate(unit, inst_type, 13921 &einst_alloc); 13922 if (BCM_FAILURE(rv)) { 13923 TSN_REVT_UNLOCK(er); 13924 TSN_EVENT_UNLOCK(unit); 13925 return rv; 13926 } 13927 /* Put it on the head of registered event instance list */ 13928 einst_alloc->cb = cb; 13929 einst_alloc->user_data = user_data; 13930 einst_alloc->port = port; 13931 einst_alloc->sr_flow = src->sr_flow; 13932 einst_alloc->next = er->evt_inst; 13933 er->evt_inst = einst_alloc; 13934 } 13935 } 13936 } 13937 13938 /* update the event stat */ 13939 evt_stat = &bkinfo->evt_stat[event]; 13940 if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_PORT) { 13941 evt_stat->port_ref[port]++; 13942 } else if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW) { 13943 #if defined(BCM_TSN_SR_SUPPORT) 13944 if (soc_feature(unit, soc_feature_tsn_sr)) { 13945 rv = bcmi_esw_tsn_sr_hw_flow_id_get(unit, src->sr_flow, &idx); 13946 if (BCM_FAILURE(rv)) { 13947 einst = er->evt_inst; 13948 er->evt_inst = einst->next; 13949 (void)bcmi_esw_tsn_evt_inst_free(unit, inst_type, einst); 13950 TSN_REVT_UNLOCK(er); 13951 TSN_EVENT_UNLOCK(unit); 13952 return rv; 13953 } 13954 evt_stat->flow_ref[idx]++; 13955 if ((SR_FLOW_ID_TO_DIR(src->sr_flow) == SR_FLOW_DIR_RX) && 13956 (evt_stat->flow_ref[idx] == 1)) { 13957 if (TSN_EVENT_DEVINFO(unit)->update_rx_flow) { 13958 rv = TSN_EVENT_DEVINFO(unit)->update_rx_flow(unit, 13959 (int)event, 13960 idx, 13961 1); 13962 if (BCM_FAILURE(rv)) { 13963 einst = er->evt_inst; 13964 er->evt_inst = einst->next; 13965 (void)bcmi_esw_tsn_evt_inst_free(unit, 13966 inst_type, 13967 einst); 13968 TSN_REVT_UNLOCK(er); 13969 TSN_EVENT_UNLOCK(unit); 13970 return rv; 13971 } 13972 } 13973 } 13974 } else 13975 #endif /* BCM_TSN_SR_SUPPORT */ 13976 { 13977 einst = er->evt_inst; 13978 er->evt_inst = einst->next; 13979 (void)bcmi_esw_tsn_evt_inst_free(unit, 13980 inst_type, 13981 einst); 13982 TSN_REVT_UNLOCK(er); 13983 TSN_EVENT_UNLOCK(unit); 13984 return BCM_E_UNAVAIL; 13985 } 13986 } 13987 event_count = evt_stat->event_ref; 13988 evt_stat->event_ref++; 13989 13990 if (event_count == 0) { 13991 rv = bcmi_esw_tsn_event_mask_set(unit, event, 1); 13992 if (BCM_FAILURE(rv)) { 13993 einst = er->evt_inst; 13994 er->evt_inst = einst->next; 13995 (void)bcmi_esw_tsn_evt_inst_free(unit, inst_type, einst); 13996 } 13997 } 13998 TSN_REVT_UNLOCK(er); 13999 TSN_EVENT_UNLOCK(unit); 14000 return BCM_E_NONE; 14001 } 14002 14003 STATIC int 14004 bcmi_esw_tsn_event_unregister( 14005 int unit, 14006 bcm_tsn_event_type_t event, 14007 bcm_tsn_event_source_t *src, 14008 bcm_tsn_event_cb cb) 14009 { 14010 int i, rv = BCM_E_NOT_FOUND, event_count; 14011 #if defined(BCM_TSN_SR_SUPPORT) 14012 uint32 idx; 14013 #endif 14014 bcmi_tsn_evt_inst_type_t inst_type; 14015 tsn_evt_regist_t *er; 14016 tsn_evt_inst_t *einst, *prev; 14017 bcmi_esw_tsn_bk_info_t *tsn_bk; 14018 tsn_event_bk_t *bkinfo; 14019 tsn_evt_stat_t *evt_stat; 14020 bcm_port_t port; 14021 14022 if ((cb == NULL) || (src == NULL)) { 14023 return BCM_E_PARAM; 14024 } 14025 14026 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 14027 bkinfo = &tsn_bk->tsn_events; 14028 14029 /* get the internal instance type */ 14030 inst_type = bcmiTsnEvtCount; 14031 for (i = 0; i < bcmiTsnEvtCount; i++) { 14032 if ((tsn_evt_inst_info[i].source_type == src->source_type) && 14033 (tsn_evt_inst_info[i].evt_type == event)) { 14034 inst_type = tsn_evt_inst_info[i].inst_type; 14035 break; 14036 } 14037 } 14038 if (inst_type == bcmiTsnEvtCount) { 14039 return BCM_E_PARAM; 14040 } 14041 BCM_IF_ERROR_RETURN(bcmi_esw_tsn_event_validate(unit, inst_type, src)); 14042 14043 if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_PORT) { 14044 if (BCM_GPORT_IS_SET(src->port)) { 14045 BCM_IF_ERROR_RETURN(bcm_esw_port_local_get(unit, src->port, &port)); 14046 } else { 14047 port = src->port; 14048 } 14049 } else { 14050 port = 0; 14051 } 14052 TSN_EVENT_LOCK(unit); 14053 er = &bkinfo->eregist[inst_type]; 14054 TSN_REVT_LOCK(er); 14055 if (NULL == er->evt_inst) { 14056 /* registered instance type array is empty. */ 14057 TSN_REVT_UNLOCK(er); 14058 TSN_EVENT_UNLOCK(unit); 14059 return BCM_E_NOT_FOUND; 14060 } else { 14061 /* registered instance type array is available */ 14062 prev = NULL; 14063 for (einst = er->evt_inst; einst != NULL; einst = einst->next) { 14064 if ((einst->cb == cb) && (einst->port == port) && 14065 (einst->sr_flow == src->sr_flow)) { 14066 /* matched the callback and event source */ 14067 /* remove it from the er list */ 14068 if (prev == NULL) { 14069 er->evt_inst = einst->next; 14070 } else { 14071 prev->next = einst->next; 14072 } 14073 /* Free to inst pool */ 14074 (void)bcmi_esw_tsn_evt_inst_free(unit, inst_type, einst); 14075 rv = BCM_E_NONE; 14076 break; 14077 } 14078 prev = einst; 14079 } 14080 TSN_REVT_UNLOCK(er); 14081 if (BCM_SUCCESS(rv)) { 14082 /* update the bkinfo->event_count */ 14083 evt_stat = &bkinfo->evt_stat[event]; 14084 if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_PORT) { 14085 if (evt_stat->port_ref[port] > 0) { 14086 evt_stat->port_ref[port]--; 14087 } 14088 } else if (src->source_type == BCM_TSN_EVENT_SOURCE_TYPE_SR_FLOW) { 14089 #if defined(BCM_TSN_SR_SUPPORT) 14090 if (soc_feature(unit, soc_feature_tsn_sr)) { 14091 rv = bcmi_esw_tsn_sr_hw_flow_id_get(unit, src->sr_flow, 14092 &idx); 14093 if (BCM_FAILURE(rv)) { 14094 TSN_EVENT_UNLOCK(unit); 14095 return rv; 14096 } 14097 if (evt_stat->flow_ref[idx] > 0) { 14098 evt_stat->flow_ref[idx]--; 14099 } 14100 if ((SR_FLOW_ID_TO_DIR(src->sr_flow) == SR_FLOW_DIR_RX) && 14101 (evt_stat->flow_ref[idx] == 0)) { 14102 if (TSN_EVENT_DEVINFO(unit)->update_rx_flow) { 14103 rv = TSN_EVENT_DEVINFO(unit)->update_rx_flow( 14104 unit, (int)event, idx, 0); 14105 if (BCM_FAILURE(rv)) { 14106 TSN_EVENT_UNLOCK(unit); 14107 return rv; 14108 } 14109 } 14110 } 14111 } else 14112 #endif /* BCM_TSN_SR_SUPPORT */ 14113 { 14114 TSN_EVENT_UNLOCK(unit); 14115 return BCM_E_UNAVAIL; 14116 } 14117 } 14118 evt_stat->event_ref--; 14119 event_count = evt_stat->event_ref; 14120 if (event_count == 0) { 14121 rv = bcmi_esw_tsn_event_mask_set(unit, event, 0); 14122 if (BCM_FAILURE(rv)) { 14123 TSN_EVENT_UNLOCK(unit); 14124 return rv; 14125 } 14126 } 14127 } 14128 } 14129 TSN_EVENT_UNLOCK(unit); 14130 return rv; 14131 } 14132 14133 STATIC int 14134 bcmi_esw_tsn_event_notification_traverse( 14135 int unit, 14136 bcm_tsn_event_notification_traverse_cb cb, 14137 void *user_data) 14138 { 14139 bcm_tsn_event_type_t event; 14140 bcm_tsn_event_source_t src; 14141 bcm_tsn_event_cb evt_cb; 14142 void *evt_cb_user_data; 14143 int i, rv; 14144 tsn_evt_regist_t *er; 14145 tsn_evt_inst_t *einst; 14146 bcmi_esw_tsn_bk_info_t *tsn_bk; 14147 tsn_event_bk_t *bkinfo; 14148 14149 if (cb == NULL) { 14150 return BCM_E_PARAM; 14151 } 14152 14153 /* parameter check */ 14154 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &tsn_bk)); 14155 14156 bkinfo = &tsn_bk->tsn_events; 14157 14158 for (i = 0; i < bcmiTsnEvtCount; i++) { 14159 er = &bkinfo->eregist[i]; 14160 TSN_REVT_LOCK(er); 14161 for (einst = er->evt_inst; einst != NULL; einst = einst->next) { 14162 event = er->evt_type; 14163 bcm_tsn_event_source_t_init(&src); 14164 src.source_type = er->source_type; 14165 src.port = einst->port; 14166 src.sr_flow = einst->sr_flow; 14167 evt_cb = einst->cb; 14168 evt_cb_user_data = einst->user_data; 14169 rv = cb(unit, event, &src, evt_cb, evt_cb_user_data, user_data); 14170 if (BCM_FAILURE(rv)) { 14171 TSN_REVT_UNLOCK(er); 14172 return rv; 14173 } 14174 } 14175 TSN_REVT_UNLOCK(er); 14176 } 14177 return BCM_E_NONE; 14178 } 14179 14180 #ifdef BCM_WARM_BOOT_SUPPORT 14181 /* 14182 * Function: 14183 * bcmi_esw_tsn_reinit 14184 * Purpose: 14185 * Restore bookkeeping information. 14186 * Parameters: 14187 * unit - (IN) unit number 14188 * Returns: 14189 * BCM_E_XXX 14190 */ 14191 STATIC int 14192 bcmi_esw_tsn_reinit(int unit) 14193 { 14194 bcm_error_t rv = BCM_E_UNAVAIL; 14195 14196 if (!SOC_WARM_BOOT(unit)) { 14197 return BCM_E_UNAVAIL; 14198 } 14199 14200 if (!soc_feature(unit, soc_feature_tsn)) { 14201 return BCM_E_UNAVAIL; 14202 } 14203 14204 #if defined(BCM_TSN_SR_SUPPORT) 14205 if (soc_feature(unit, soc_feature_tsn_sr)) { 14206 /* 14207 * Load TSN SR MAC Proxy info from hardware 14208 * into software data structures. 14209 */ 14210 rv = bcmi_esw_tsn_sr_mac_proxy_reload(unit); 14211 if (BCM_FAILURE(rv)) { 14212 return rv; 14213 } 14214 } 14215 #endif /* BCM_TSN_SR_SUPPORT */ 14216 14217 /* Doing TSN TAF resource reinit */ 14218 if (soc_feature(unit, soc_feature_tsn_taf)) { 14219 rv = bcmi_esw_tsn_taf_reload(unit); 14220 if (BCM_FAILURE(rv)) { 14221 LOG_ERROR(BSL_LS_BCM_TSN, 14222 (BSL_META_U(unit, 14223 "TSN TAF Reload Warm boot failed" 14224 "(rv = %d)\n"), 14225 rv)); 14226 return rv; 14227 } 14228 } 14229 14230 /* Doing TSN and SR priority map resource reinit */ 14231 rv = bcmi_esw_tsn_pri_map_tsn_sr_reload(unit); 14232 if (BCM_FAILURE(rv)) { 14233 LOG_ERROR(BSL_LS_BCM_TSN, 14234 (BSL_META_U(unit, 14235 "TSN Priority Map Warm boot failed" 14236 "(rv = %d)\n"), 14237 rv)); 14238 return rv; 14239 } 14240 14241 #if defined(BCM_TSN_SR_SUPPORT) 14242 if (soc_feature(unit, soc_feature_tsn_sr)) { 14243 /* Doing SR flows resource reinint */ 14244 rv = bcmi_esw_tsn_sr_flow_mgmt_reload(unit); 14245 if (BCM_FAILURE(rv)) { 14246 LOG_ERROR(BSL_LS_BCM_TSN, 14247 (BSL_META_U(unit, 14248 "TSN SR flows warm boot reload failed" 14249 "(rv = %d)\n"), 14250 rv)); 14251 return rv; 14252 } 14253 } 14254 #endif /* BCM_TSN_SR_SUPPORT */ 14255 14256 /* Doing TSN flows resource reinint */ 14257 rv = bcmi_esw_tsn_flow_mgmt_reload(unit); 14258 if (BCM_FAILURE(rv)) { 14259 LOG_ERROR(BSL_LS_BCM_TSN, 14260 (BSL_META_U(unit, 14261 "TSN flows warm boot reload failed" 14262 "(rv = %d)\n"), 14263 rv)); 14264 return rv; 14265 } 14266 14267 #if defined(BCM_TSN_SR_SUPPORT) 14268 if (soc_feature(unit, soc_feature_tsn_sr) && 14269 soc_feature(unit, soc_feature_tsn_sr_auto_learn)) { 14270 /* 14271 * Load TSN SR Auto Learn info from hardware 14272 * into software data structures. 14273 */ 14274 rv = bcmi_esw_tsn_sr_auto_learn_reload(unit); 14275 if (BCM_FAILURE(rv)) { 14276 LOG_ERROR(BSL_LS_BCM_TSN, 14277 (BSL_META_U(unit, 14278 "SR Auto Learn Warm boot failed(rv = %d)\n"), 14279 rv)); 14280 return rv; 14281 } 14282 } 14283 #endif /* BCM_TSN_SR_SUPPORT */ 14284 14285 /* Doing TSN MTU & STU resource reinit */ 14286 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 14287 rv = bcmi_esw_tsn_egress_mtu_reload(unit); 14288 if (BCM_FAILURE(rv)) { 14289 LOG_ERROR(BSL_LS_BCM_TSN, 14290 (BSL_META_U(unit, 14291 "TSN MTU Reload Warm boot failed" 14292 "(rv = %d)\n"), 14293 rv)); 14294 return rv; 14295 } 14296 rv = bcmi_esw_tsn_egress_stu_reload(unit); 14297 if (BCM_FAILURE(rv)) { 14298 LOG_ERROR(BSL_LS_BCM_TSN, 14299 (BSL_META_U(unit, 14300 "TSN STU Reload Warm boot failed" 14301 "(rv = %d)\n"), 14302 rv)); 14303 return rv; 14304 } 14305 } 14306 14307 /* Doing TSN PRP-Forwarding resource reinit */ 14308 rv = bcmi_esw_tsn_sr_port_prp_forwarding_reload(unit); 14309 if (BCM_FAILURE(rv)) { 14310 LOG_ERROR(BSL_LS_BCM_TSN, 14311 (BSL_META_U(unit, 14312 "TSN PRP-Forwarding Reload Warm boot failed" 14313 "(rv = %d)\n"), 14314 rv)); 14315 return rv; 14316 } 14317 14318 /* Doing TSN Portcnt Stat/Port bitmap resource reinit */ 14319 rv = bcmi_esw_tsn_stat_portcnt_reload(unit); 14320 if (BCM_FAILURE(rv)) { 14321 LOG_ERROR(BSL_LS_BCM_TSN, 14322 (BSL_META_U(unit, 14323 "TSN Stat Portcnt Reload Warm boot failed" 14324 "(rv = %d)\n"), 14325 rv)); 14326 return rv; 14327 } 14328 14329 /* Doing TSN Flowcnt Stat resource reinit */ 14330 rv = bcmi_esw_tsn_stat_flowcnt_reload(unit); 14331 if (BCM_FAILURE(rv)) { 14332 LOG_ERROR(BSL_LS_BCM_TSN, 14333 (BSL_META_U(unit, 14334 "TSN Stat Flowcnt Reload Warm boot failed" 14335 "(rv = %d)\n"), 14336 rv)); 14337 return rv; 14338 } 14339 14340 return BCM_E_NONE; 14341 } 14342 14343 /* 14344 * Function: 14345 * bcmi_esw_tsn_sync 14346 * Purpose: 14347 * Store bookkeeping information for 14348 * Warmboot recovery. 14349 * Parameters: 14350 * unit - (IN) unit number 14351 * Returns: 14352 * BCM_E_XXX 14353 */ 14354 STATIC int 14355 bcmi_esw_tsn_sync(int unit) 14356 { 14357 bcm_error_t rv = BCM_E_UNAVAIL; 14358 14359 if (!soc_feature(unit, soc_feature_tsn)) { 14360 return BCM_E_UNAVAIL; 14361 } 14362 14363 /* Doing TSN MTU & STU resource sync */ 14364 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 14365 rv = bcmi_esw_tsn_egress_mtu_sync(unit); 14366 if (BCM_FAILURE(rv)) { 14367 LOG_ERROR(BSL_LS_BCM_TSN, 14368 (BSL_META_U(unit, 14369 "TSN MTU Sync Warm boot failed" 14370 "(rv = %d)\n"), 14371 rv)); 14372 return rv; 14373 } 14374 rv = bcmi_esw_tsn_egress_stu_sync(unit); 14375 if (BCM_FAILURE(rv)) { 14376 LOG_ERROR(BSL_LS_BCM_TSN, 14377 (BSL_META_U(unit, 14378 "TSN STU Sync Warm boot failed" 14379 "(rv = %d)\n"), 14380 rv)); 14381 return rv; 14382 } 14383 } 14384 14385 /* Sync TSN flows to scache */ 14386 rv = bcmi_esw_tsn_flow_mgmt_sync(unit); 14387 if (BCM_FAILURE(rv)) { 14388 LOG_ERROR(BSL_LS_BCM_TSN, 14389 (BSL_META_U(unit, 14390 "TSN flows warm boot sync failed" 14391 "(rv = %d)\n"), 14392 rv)); 14393 return rv; 14394 } 14395 14396 #if defined(BCM_TSN_SR_SUPPORT) 14397 if (soc_feature(unit, soc_feature_tsn_sr)) { 14398 /* Sync SR flows to scache */ 14399 rv = bcmi_esw_tsn_sr_flow_mgmt_sync(unit); 14400 if (BCM_FAILURE(rv)) { 14401 LOG_ERROR(BSL_LS_BCM_TSN, 14402 (BSL_META_U(unit, 14403 "TSN SR flows warm boot sync failed" 14404 "(rv = %d)\n"), 14405 rv)); 14406 return rv; 14407 } 14408 14409 rv = bcmi_esw_tsn_sr_port_prp_forwarding_sync(unit); 14410 if (BCM_FAILURE(rv)) { 14411 LOG_ERROR(BSL_LS_BCM_TSN, 14412 (BSL_META_U(unit, 14413 "TSN PRP Forwarding Warm boot failed" 14414 "(rv = %d)\n"), 14415 rv)); 14416 return rv; 14417 } 14418 } 14419 if (soc_feature(unit, soc_feature_tsn_sr) && 14420 soc_feature(unit, soc_feature_tsn_sr_auto_learn)) { 14421 rv = bcmi_esw_tsn_sr_auto_learn_sync(unit); 14422 if (BCM_FAILURE(rv)) { 14423 LOG_ERROR(BSL_LS_BCM_TSN, 14424 (BSL_META_U(unit, 14425 "TSN SR Auto Learn Sync Warm boot failed" 14426 "(rv = %d)\n"), 14427 rv)); 14428 return rv; 14429 } 14430 } 14431 #endif /* BCM_TSN_SR_SUPPORT */ 14432 14433 /* Doing TSN Portcnt Stat/Port bitmap resource sync */ 14434 rv = bcmi_esw_tsn_stat_portcnt_sync(unit); 14435 if (BCM_FAILURE(rv)) { 14436 LOG_ERROR(BSL_LS_BCM_TSN, 14437 (BSL_META_U(unit, 14438 "TSN Stat Portcnt Sync Warm boot failed" 14439 "(rv = %d)\n"), 14440 rv)); 14441 return rv; 14442 } 14443 14444 /* Doing TSN Flowtcnt Stat resource sync */ 14445 rv = bcmi_esw_tsn_stat_flowcnt_sync(unit); 14446 if (BCM_FAILURE(rv)) { 14447 LOG_ERROR(BSL_LS_BCM_TSN, 14448 (BSL_META_U(unit, 14449 "TSN Stat Flowcnt Sync Warm boot failed" 14450 "(rv = %d)\n"), 14451 rv)); 14452 return rv; 14453 } 14454 14455 /* Doing TSN TAF resource sync */ 14456 if (soc_feature(unit, soc_feature_tsn_taf)) { 14457 rv = bcmi_esw_tsn_taf_sync(unit); 14458 if (BCM_FAILURE(rv)) { 14459 LOG_ERROR(BSL_LS_BCM_TSN, 14460 (BSL_META_U(unit, 14461 "TSN TAF Sync Warm boot failed" 14462 "(rv = %d)\n"), 14463 rv)); 14464 return rv; 14465 } 14466 } 14467 14468 return BCM_E_NONE; 14469 } 14470 #endif /* BCM_WARM_BOOT_SUPPORT */ 14471 14472 /* 14473 * Function: 14474 * bcmi_esw_tsn_coldboot_init 14475 * Purpose: 14476 * Restore bookkeeping information. 14477 * Parameters: 14478 * unit - (IN) unit number 14479 * Returns: 14480 * BCM_E_XXX 14481 */ 14482 STATIC int 14483 bcmi_esw_tsn_coldboot_init(int unit) 14484 { 14485 bcm_error_t rv = BCM_E_UNAVAIL; 14486 14487 #if defined(BCM_WARM_BOOT_SUPPORT) 14488 /* Warm boot should be false in cold boot case */ 14489 if (SOC_WARM_BOOT(unit)) { 14490 return BCM_E_UNAVAIL; 14491 } 14492 14493 #if defined(BCM_TSN_SR_SUPPORT) 14494 if (soc_feature(unit, soc_feature_tsn_sr)) { 14495 /* Allocate scache for SR flows */ 14496 BCM_IF_ERROR_RETURN(bcmi_esw_tsn_sr_flow_mgmt_wb_alloc(unit)); 14497 } 14498 if (soc_feature(unit, soc_feature_tsn_sr) && 14499 soc_feature(unit, soc_feature_tsn_sr_auto_learn)) { 14500 /* Allocate scache for SR Auto Learn management */ 14501 BCM_IF_ERROR_RETURN(bcmi_esw_tsn_sr_auto_learn_wb_alloc(unit)); 14502 } 14503 #endif /* BCM_TSN_SR_SUPPORT */ 14504 14505 /* Allocate scache for TSN flows */ 14506 BCM_IF_ERROR_RETURN(bcmi_esw_tsn_flow_mgmt_wb_alloc(unit)); 14507 14508 #endif /* BCM_WARM_BOOT_SUPPORT */ 14509 14510 /* Doing TSN and SR priority map resource cold boot init */ 14511 rv = bcmi_esw_tsn_pri_map_tsn_sr_coldboot_init(unit); 14512 if (BCM_FAILURE(rv)) { 14513 LOG_ERROR(BSL_LS_BCM_TSN, 14514 (BSL_META_U(unit, 14515 "TSN Priority Map Cold boot failed" 14516 "(rv = %d)\n"), 14517 rv)); 14518 return rv; 14519 } 14520 14521 /* Doing TAF resource cold boot init */ 14522 if (soc_feature(unit, soc_feature_tsn_taf)) { 14523 rv = bcmi_esw_tsn_taf_coldboot_init(unit); 14524 if (BCM_FAILURE(rv)) { 14525 LOG_ERROR(BSL_LS_BCM_TSN, 14526 (BSL_META_U(unit, 14527 "TSN TAF Cold boot failed" 14528 "(rv = %d)\n"), 14529 rv)); 14530 return rv; 14531 } 14532 } 14533 14534 return BCM_E_NONE; 14535 } 14536 14537 /* 14538 * Function: 14539 * bcmi_esw_tsn_bk_info_cleanup 14540 * Purpose: 14541 * Internal function to clear the resource of the TSN module. 14542 * Parameters: 14543 * unit - (IN) unit number 14544 * Returns: 14545 * BCM_E_XXX 14546 */ 14547 STATIC int 14548 bcmi_esw_tsn_bk_info_cleanup(int unit) 14549 { 14550 LOG_VERBOSE(BSL_LS_BCM_TSN, 14551 (BSL_META_U(unit, 14552 "bcmi_esw_tsn_bk_info_cleanup\n"))); 14553 14554 /* Free and clear the bookkeeping info structure */ 14555 if (tsn_bk_info[unit] != NULL) { 14556 /* Event management clean up */ 14557 bcmi_esw_tsn_event_mgmt_detach(unit); 14558 14559 #if defined(BCM_TSN_SR_SUPPORT) 14560 if (soc_feature(unit, soc_feature_tsn_sr)) { 14561 /* SR Auto Learn management clean up */ 14562 bcmi_esw_tsn_sr_auto_learn_cleanup(unit); 14563 /* SR MAC proxy management clean up */ 14564 bcmi_esw_tsn_sr_mac_proxy_cleanup(unit); 14565 /* SR flow management clean up */ 14566 bcmi_esw_tsn_sr_flow_mgmt_detach(unit); 14567 } 14568 #endif /* BCM_TSN_SR_SUPPORT */ 14569 14570 /* TSN priority map management clean up */ 14571 bcmi_esw_tsn_pri_map_cleanup(unit); 14572 14573 /* MTU & STU management clean up */ 14574 bcmi_esw_tsn_mtu_cleanup(unit); 14575 bcmi_esw_tsn_stu_cleanup(unit); 14576 14577 /* TSN flow management clean up */ 14578 bcmi_esw_tsn_flow_mgmt_detach(unit); 14579 14580 TSN_FREE(unit, tsn_bk_info[unit], 0); 14581 tsn_bk_info[unit] = NULL; 14582 } 14583 14584 return BCM_E_NONE; 14585 } 14586 14587 /* 14588 * Function: 14589 * bcmi_esw_tsn_detach 14590 * Purpose: 14591 * Clear the resource of the TSN module. 14592 * Parameters: 14593 * unit - (IN) unit number 14594 * Returns: 14595 * BCM_E_XXX 14596 */ 14597 STATIC int 14598 bcmi_esw_tsn_detach(int unit) 14599 { 14600 if (!soc_feature(unit, soc_feature_tsn)) { 14601 return BCM_E_UNAVAIL; 14602 } 14603 14604 /* clean up TSN Stat counters info resource */ 14605 BCM_IF_ERROR_RETURN( 14606 bcmi_esw_tsn_stat_cleanup(unit)); 14607 14608 /* clean up TAF resource */ 14609 if (soc_feature(unit, soc_feature_tsn_taf)) { 14610 bcmi_esw_tsn_taf_cleanup(unit); 14611 } 14612 14613 /* clean up bookkeeping info resource */ 14614 BCM_IF_ERROR_RETURN( 14615 bcmi_esw_tsn_bk_info_cleanup(unit)); 14616 14617 #ifdef BCM_GREYHOUND2_SUPPORT 14618 /* chip specific detach */ 14619 if (SOC_IS_GREYHOUND2(unit)) { 14620 BCM_IF_ERROR_RETURN( 14621 bcmi_gh2_tsn_info_detach(unit)); 14622 } 14623 #endif /* BCM_GREYHOUND2_SUPPORT */ 14624 14625 return BCM_E_NONE; 14626 } 14627 14628 /* 14629 * Function: 14630 * bcmi_esw_tsn_init 14631 * Purpose: 14632 * Internal function to initialize the resource and setup device info. 14633 * Parameters: 14634 * unit - (IN) unit number 14635 * Returns: 14636 * BCM_E_XXX 14637 */ 14638 STATIC int 14639 bcmi_esw_tsn_init(int unit) 14640 { 14641 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 14642 int rv = BCM_E_NONE; 14643 int i; 14644 14645 LOG_VERBOSE(BSL_LS_BCM_TSN, 14646 (BSL_META_U(unit, 14647 "bcmi_esw_tsn_init\n"))); 14648 14649 if (!soc_feature(unit, soc_feature_tsn)) { 14650 return BCM_E_UNAVAIL; 14651 } 14652 14653 /* Initialize structure */ 14654 if (!tsn_bk_info_initialized) { 14655 for (i = 0; i < BCM_MAX_NUM_UNITS; i++) { 14656 tsn_bk_info[i] = NULL; 14657 } 14658 tsn_bk_info_initialized = 1; 14659 } 14660 14661 /* Clean up the bookkeeping resource */ 14662 if (tsn_bk_info[unit] != NULL) { 14663 rv = bcmi_esw_tsn_bk_info_cleanup(unit); 14664 if (BCM_FAILURE(rv)) { 14665 return rv; 14666 } 14667 } 14668 14669 /* Allocate TSN bookkeeping resource for this unit. */ 14670 TSN_ALLOC(unit, bk_info, bcmi_esw_tsn_bk_info_t, 14671 sizeof(bcmi_esw_tsn_bk_info_t), 14672 "TSN bookkeeping info", 0, rv); 14673 if (BCM_FAILURE(rv)) { 14674 LOG_VERBOSE(BSL_LS_BCM_TSN, 14675 (BSL_META_U(unit, 14676 "bcmi_esw_tsn_init: failed to " 14677 "allocate memory\n"))); 14678 return rv; 14679 } 14680 14681 /* Get the chip dev_info structure. */ 14682 tsn_bk_info[unit] = bk_info; 14683 #ifdef BCM_GREYHOUND2_SUPPORT 14684 if (SOC_IS_GREYHOUND2(unit)) { 14685 rv = bcmi_gh2_tsn_info_init(unit, &bk_info->tsn_dev_info); 14686 } else 14687 #endif 14688 { 14689 rv = BCM_E_UNAVAIL; 14690 } 14691 14692 /* Release resource if any error occurred. */ 14693 if (BCM_FAILURE(rv) || bk_info->tsn_dev_info == NULL) { 14694 bcmi_esw_tsn_bk_info_cleanup(unit); 14695 if (BCM_SUCCESS(rv)) { 14696 return BCM_E_UNAVAIL; 14697 } 14698 return (rv); 14699 } 14700 14701 /* Initialize TAF */ 14702 if (soc_feature(unit, soc_feature_tsn_taf)) { 14703 rv = bcmi_esw_tsn_taf_init(unit); 14704 /* Release resource if any error occurred. */ 14705 if (BCM_FAILURE(rv)) { 14706 bcmi_esw_tsn_detach(unit); 14707 return rv; 14708 } 14709 } 14710 14711 /* Allocate TSN Priority Map bookkeeping resource for this unit */ 14712 rv = bcmi_esw_tsn_pri_map_init(unit); 14713 14714 /* Release resource if any error occurred. */ 14715 if (BCM_FAILURE(rv)) { 14716 bcmi_esw_tsn_bk_info_cleanup(unit); 14717 return rv; 14718 } 14719 14720 #if defined(BCM_TSN_SR_SUPPORT) 14721 if (soc_feature(unit, soc_feature_tsn_sr)) { 14722 /* Allocate TSN SR Mac Proxy bookkeeping resource for this unit */ 14723 rv = bcmi_esw_tsn_sr_mac_proxy_init(unit); 14724 if (BCM_FAILURE(rv)) { 14725 bcmi_esw_tsn_detach(unit); 14726 return rv; 14727 } 14728 14729 /* SR flow management initialization */ 14730 rv = bcmi_esw_tsn_sr_flow_mgmt_init(unit); 14731 if (BCM_FAILURE(rv)) { 14732 bcmi_esw_tsn_detach(unit); 14733 return (rv); 14734 } 14735 14736 } 14737 if (soc_feature(unit, soc_feature_tsn_sr) && 14738 soc_feature(unit, soc_feature_tsn_sr_auto_learn)) { 14739 /* Initialize SR Auto Learn management */ 14740 rv = bcmi_esw_tsn_sr_auto_learn_init(unit); 14741 /* Release resource if any error occurred. */ 14742 if (BCM_FAILURE(rv)) { 14743 bcmi_esw_tsn_detach(unit); 14744 return rv; 14745 } 14746 } 14747 #endif /* BCM_TSN_SR_SUPPORT */ 14748 14749 /* TSN flow management initialization */ 14750 rv = bcmi_esw_tsn_flow_mgmt_init(unit); 14751 if (BCM_FAILURE(rv)) { 14752 bcmi_esw_tsn_detach(unit); 14753 return (rv); 14754 } 14755 14756 /* Allocate MTU /STU bookkeeping resource for this unit */ 14757 rv = bcmi_esw_tsn_mtu_init(unit); 14758 /* Release resource if any error occurred. */ 14759 if (BCM_FAILURE(rv)) { 14760 bcmi_esw_tsn_bk_info_cleanup(unit); 14761 return rv; 14762 } 14763 14764 rv = bcmi_esw_tsn_stu_init(unit); 14765 /* Release resource if any error occurred. */ 14766 if (BCM_FAILURE(rv)) { 14767 bcmi_esw_tsn_bk_info_cleanup(unit); 14768 return rv; 14769 } 14770 14771 /* Initialize TSN Stat counters */ 14772 rv = bcmi_esw_tsn_stat_init(unit); 14773 /* Release resource if any error occurred. */ 14774 if (BCM_FAILURE(rv)) { 14775 bcmi_esw_tsn_detach(unit); 14776 return rv; 14777 } 14778 14779 /* Initialize TSN event management */ 14780 rv = bcmi_esw_tsn_event_mgmt_init(unit); 14781 /* Release resource if any error occurred. */ 14782 if (BCM_FAILURE(rv)) { 14783 bcmi_esw_tsn_detach(unit); 14784 return rv; 14785 } 14786 14787 #ifdef BCM_WARM_BOOT_SUPPORT 14788 /* Warm Boot recovery */ 14789 if (SOC_WARM_BOOT(unit)) { 14790 rv = bcmi_esw_tsn_reinit(unit); 14791 if (BCM_FAILURE(rv)) { 14792 bcmi_esw_tsn_detach(unit); 14793 LOG_ERROR(BSL_LS_BCM_TSN, 14794 (BSL_META_U(unit, 14795 "Warm boot failed" 14796 "(rv = %d)\n"), 14797 rv)); 14798 return rv; 14799 } 14800 } else 14801 #endif /* BCM_WARM_BOOT_SUPPORT */ 14802 { 14803 /* Cold Boot */ 14804 rv = bcmi_esw_tsn_coldboot_init(unit); 14805 if (BCM_FAILURE(rv)) { 14806 bcmi_esw_tsn_detach(unit); 14807 LOG_ERROR(BSL_LS_BCM_TSN, 14808 (BSL_META_U(unit, 14809 "Cold boot failed" 14810 "(rv = %d)\n"), 14811 rv)); 14812 return rv; 14813 } 14814 } 14815 14816 return BCM_E_NONE; 14817 } 14818 14819 /* 14820 * Function: 14821 * bcmi_esw_tsn_control_set 14822 * Description: 14823 * Internal function for configure device-based operation modes. 14824 * Parameters: 14825 * unit - (IN) Unit number. 14826 * type - (IN) Control type of bcm_tsn_control_t. 14827 * arg - (IN) argument to be set 14828 * Returns: 14829 * BCM_E_XXX 14830 */ 14831 STATIC int 14832 bcmi_esw_tsn_control_set(int unit, bcm_tsn_control_t type, uint32 arg) 14833 { 14834 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 14835 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 14836 const tsn_chip_ctrl_info_t *ctrl_info = NULL; 14837 int rv; 14838 14839 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 14840 dev_info = bk_info->tsn_dev_info; 14841 14842 ctrl_info = dev_info->tsn_chip_ctrl_info; 14843 if ((ctrl_info != NULL) && 14844 (ctrl_info->tsn_chip_ctrl_set != NULL)) { 14845 rv = ctrl_info->tsn_chip_ctrl_set(unit, type, arg); 14846 if (BCM_SUCCESS(rv)) { 14847 bcmi_esw_tsn_evt_ageout_config(unit, type, arg); 14848 } 14849 return rv; 14850 } 14851 14852 return BCM_E_UNAVAIL; 14853 } 14854 14855 /* 14856 * Function: 14857 * bcmi_esw_tsn_control_get 14858 * Description: 14859 * Internal function for get the configure of device-based operation modes. 14860 * Parameters: 14861 * unit - (IN) Unit number. 14862 * type - (IN) Control type of bcm_tsn_control_t. 14863 * arg - (OUT) argument got 14864 * Returns: 14865 * BCM_E_XXX 14866 */ 14867 STATIC int 14868 bcmi_esw_tsn_control_get(int unit, bcm_tsn_control_t type, uint32 *arg) 14869 { 14870 bcmi_esw_tsn_bk_info_t *bk_info = NULL; 14871 const bcmi_esw_tsn_dev_info_t *dev_info = NULL; 14872 const tsn_chip_ctrl_info_t *ctrl_info = NULL; 14873 14874 BCM_IF_ERROR_RETURN(tsn_bk_info_instance_get(unit, &bk_info)); 14875 dev_info = bk_info->tsn_dev_info; 14876 14877 ctrl_info = dev_info->tsn_chip_ctrl_info; 14878 if ((ctrl_info != NULL) && 14879 (ctrl_info->tsn_chip_ctrl_get != NULL)) { 14880 return ctrl_info->tsn_chip_ctrl_get(unit, type, arg); 14881 } 14882 14883 return BCM_E_UNAVAIL; 14884 } 14885 14886 #endif /* BCM_TSN_SUPPORT */ 14887 14888 /* 14889 * Function: 14890 * bcm_esw_tsn_init 14891 * Purpose: 14892 * Initialize the TSN module. 14893 * Parameters: 14894 * unit - (IN) unit number 14895 * Returns: 14896 * BCM_E_XXX 14897 */ 14898 int 14899 bcm_esw_tsn_init(int unit) 14900 { 14901 #if defined(BCM_TSN_SUPPORT) 14902 /* initialize TSN info */ 14903 BCM_IF_ERROR_RETURN(bcmi_esw_tsn_init(unit)); 14904 14905 return BCM_E_NONE; 14906 #else /* BCM_TSN_SUPPORT */ 14907 return BCM_E_UNAVAIL; 14908 #endif /* BCM_TSN_SUPPORT */ 14909 } 14910 14911 /* 14912 * Function: 14913 * bcm_esw_tsn_detach 14914 * Purpose: 14915 * Clear the resource of the TSN module. 14916 * Parameters: 14917 * unit - (IN) unit number 14918 * Returns: 14919 * BCM_E_XXX 14920 */ 14921 int 14922 bcm_esw_tsn_detach(int unit) 14923 { 14924 #if defined(BCM_TSN_SUPPORT) 14925 BCM_IF_ERROR_RETURN(bcmi_esw_tsn_detach(unit)); 14926 14927 return BCM_E_NONE; 14928 #else /* BCM_TSN_SUPPORT */ 14929 return BCM_E_UNAVAIL; 14930 #endif /* BCM_TSN_SUPPORT */ 14931 } 14932 14933 #if defined(BCM_WARM_BOOT_SUPPORT) 14934 /* 14935 * Function: 14936 * bcm_esw_tsn_sync 14937 * Purpose: 14938 * Store bookkeeping information for 14939 * Warmboot recovery. 14940 * Parameters: 14941 * unit - (IN) unit number 14942 * Returns: 14943 * BCM_E_XXX 14944 */ 14945 int 14946 bcm_esw_tsn_sync(int unit) 14947 { 14948 #if defined(BCM_TSN_SUPPORT) 14949 /* Store bookkeeping information */ 14950 BCM_IF_ERROR_RETURN(bcmi_esw_tsn_sync(unit)); 14951 14952 return BCM_E_NONE; 14953 #else /* BCM_TSN_SUPPORT */ 14954 return BCM_E_UNAVAIL; 14955 #endif /* BCM_TSN_SUPPORT */ 14956 } 14957 #endif /* BCM_WARM_BOOT_SUPPORT */ 14958 14959 /* 14960 * Function: 14961 * bcm_esw_tsn_sr_port_config_set 14962 * Purpose: 14963 * Set SR configuration on a port 14964 * Parameters: 14965 * unit - (IN) unit number 14966 * port - (IN) port to configure 14967 * config - (IN) port SR configuration 14968 * Returns: 14969 * BCM_E_XXX 14970 * Notes: 14971 */ 14972 int 14973 bcm_esw_tsn_sr_port_config_set( 14974 int unit, 14975 bcm_gport_t port, 14976 bcm_tsn_sr_port_config_t *config) 14977 { 14978 #if defined(BCM_TSN_SR_SUPPORT) 14979 if (soc_feature(unit, soc_feature_tsn_sr)) { 14980 return bcmi_esw_tsn_sr_port_config_set(unit, port, config); 14981 } 14982 #endif /* BCM_TSN_SR_SUPPORT */ 14983 return BCM_E_UNAVAIL; 14984 } 14985 14986 /* 14987 * Function: 14988 * bcm_esw_tsn_sr_port_config_get 14989 * Purpose: 14990 * Get SR configuration from a port 14991 * Parameters: 14992 * unit - (IN) unit number 14993 * port - (IN) port 14994 * config - (OUT) port SR configuration 14995 * Returns: 14996 * BCM_E_XXX 14997 * Notes: 14998 */ 14999 int 15000 bcm_esw_tsn_sr_port_config_get( 15001 int unit, 15002 bcm_gport_t port, 15003 bcm_tsn_sr_port_config_t *config) 15004 { 15005 #if defined(BCM_TSN_SR_SUPPORT) 15006 if (soc_feature(unit, soc_feature_tsn_sr)) { 15007 return bcmi_esw_tsn_sr_port_config_get(unit, port, config); 15008 } 15009 #endif /* BCM_TSN_SR_SUPPORT */ 15010 return BCM_E_UNAVAIL; 15011 } 15012 15013 /* 15014 * Function: 15015 * bcm_esw_tsn_pri_map_create 15016 * Purpose: 15017 * Add a priority map config to hardware. 15018 * Parameters: 15019 * unit - (IN) Unit number 15020 * config - (IN) Priority Map configuration 15021 * map_id - (OUT) Map ID 15022 * Returns: 15023 * BCM_E_xxx 15024 */ 15025 int 15026 bcm_esw_tsn_pri_map_create( 15027 int unit, 15028 bcm_tsn_pri_map_config_t *config, 15029 bcm_tsn_pri_map_t *map_id) 15030 { 15031 #if defined(BCM_TSN_SUPPORT) 15032 if (soc_feature(unit, soc_feature_tsn)) { 15033 return bcmi_esw_tsn_pri_map_create(unit, config, map_id); 15034 } 15035 #endif /* BCM_TSN_SUPPORT */ 15036 return BCM_E_UNAVAIL; 15037 } 15038 15039 /* 15040 * Function: 15041 * bcm_esw_tsn_pri_map_set 15042 * Purpose: 15043 * Set priority map config with the given map_id. 15044 * Parameters: 15045 * unit - (IN) Unit number 15046 * map_id - (IN) Map ID 15047 * config - (IN) Priority Map configuration 15048 * Returns: 15049 * BCM_E_xxx 15050 */ 15051 int 15052 bcm_esw_tsn_pri_map_set( 15053 int unit, 15054 bcm_tsn_pri_map_t map_id, 15055 bcm_tsn_pri_map_config_t *config) 15056 { 15057 #if defined(BCM_TSN_SUPPORT) 15058 if (soc_feature(unit, soc_feature_tsn)) { 15059 return bcmi_esw_tsn_pri_map_set(unit, map_id, config); 15060 } 15061 #endif /* BCM_TSN_SUPPORT */ 15062 return BCM_E_UNAVAIL; 15063 } 15064 15065 /* 15066 * Function: 15067 * bcm_esw_tsn_pri_map_get 15068 * Purpose: 15069 * Get the priority map config with the given map_id. 15070 * Parameters: 15071 * unit - (IN) Unit number 15072 * map_id - (IN) Map ID 15073 * config - (OUT) Priority Map configuration 15074 * Returns: 15075 * BCM_E_xxx 15076 */ 15077 int 15078 bcm_esw_tsn_pri_map_get( 15079 int unit, 15080 bcm_tsn_pri_map_t map_id, 15081 bcm_tsn_pri_map_config_t *config) 15082 { 15083 #if defined(BCM_TSN_SUPPORT) 15084 if (soc_feature(unit, soc_feature_tsn)) { 15085 return bcmi_esw_tsn_pri_map_get(unit, map_id, config); 15086 } 15087 #endif /* BCM_TSN_SUPPORT */ 15088 return BCM_E_UNAVAIL; 15089 15090 } 15091 15092 /* 15093 * Function: 15094 * bcm_esw_tsn_pri_map_destroy 15095 * Purpose: 15096 * Free the resource of map_id 15097 * Parameters: 15098 * unit - (IN) Unit number 15099 * map_id - (IN) Priority Map ID 15100 * Returns: 15101 * BCM_E_xxx 15102 */ 15103 int 15104 bcm_esw_tsn_pri_map_destroy( 15105 int unit, 15106 bcm_tsn_pri_map_t map_id) 15107 { 15108 #if defined(BCM_TSN_SUPPORT) 15109 if (soc_feature(unit, soc_feature_tsn)) { 15110 return bcmi_esw_tsn_pri_map_destroy(unit, map_id); 15111 } 15112 #endif /* BCM_TSN_SUPPORT */ 15113 return BCM_E_UNAVAIL; 15114 } 15115 15116 /* 15117 * Function: 15118 * bcm_esw_tsn_pri_map_traverse 15119 * Purpose: 15120 * Traverse the priority map config information. 15121 * Parameters: 15122 * unit - (IN) Unit number 15123 * cb - (IN) Traverse call back function 15124 * user_data - (IN) User data 15125 * Returns: 15126 * BCM_E_xxx 15127 */ 15128 int 15129 bcm_esw_tsn_pri_map_traverse( 15130 int unit, 15131 bcm_tsn_pri_map_traverse_cb cb, 15132 void *user_data) 15133 { 15134 #if defined(BCM_TSN_SUPPORT) 15135 if (soc_feature(unit, soc_feature_tsn)) { 15136 return bcmi_esw_tsn_pri_map_traverse(unit, cb, user_data); 15137 } 15138 #endif /* BCM_TSN_SUPPORT */ 15139 return BCM_E_UNAVAIL; 15140 } 15141 15142 /* 15143 * Function: 15144 * bcm_esw_tsn_sr_tx_flowset_create 15145 * Purpose: 15146 * Create an SR TX flowset. 15147 * Parameters: 15148 * unit - (IN) unit number 15149 * pri_map - (IN) TSN priority map ID 15150 * def_cfg - (IN) default flow configuration 15151 * flowset - (OUT) flowset ID 15152 * Returns: 15153 * BCM_E_XXX 15154 * Notes: 15155 */ 15156 int 15157 bcm_esw_tsn_sr_tx_flowset_create( 15158 int unit, 15159 bcm_tsn_pri_map_t pri_map, 15160 bcm_tsn_sr_tx_flow_config_t *def_cfg, 15161 bcm_tsn_sr_flowset_t *flowset) 15162 { 15163 #if defined(BCM_TSN_SR_SUPPORT) 15164 if (soc_feature(unit, soc_feature_tsn_sr)) { 15165 return 15166 bcmi_esw_tsn_sr_tx_flowset_create(unit, pri_map, def_cfg, flowset); 15167 } 15168 #endif /* BCM_TSN_SR_SUPPORT */ 15169 return BCM_E_UNAVAIL; 15170 } 15171 15172 /* 15173 * Function: 15174 * bcm_esw_tsn_sr_tx_flowset_config_get 15175 * Purpose: 15176 * Get default configuration for the specified SR flowset 15177 * Parameters: 15178 * unit - (IN) unit number 15179 * flowset - (IN) flowset ID 15180 * pri_map - (OUT) TSN priority map ID 15181 * default_config - (OUT) default flow configuration 15182 * Returns: 15183 * BCM_E_XXX 15184 * Notes: 15185 * If it's called with a RX flowset, BCM_E_BADID is returned 15186 */ 15187 int 15188 bcm_esw_tsn_sr_tx_flowset_config_get( 15189 int unit, 15190 bcm_tsn_sr_flowset_t flowset, 15191 bcm_tsn_pri_map_t *pri_map, 15192 bcm_tsn_sr_tx_flow_config_t *default_config) 15193 { 15194 #if defined(BCM_TSN_SR_SUPPORT) 15195 if (soc_feature(unit, soc_feature_tsn_sr)) { 15196 return bcmi_esw_tsn_sr_tx_flowset_config_get( 15197 unit, flowset, pri_map, default_config); 15198 } 15199 #endif /* BCM_TSN_SR_SUPPORT */ 15200 return BCM_E_UNAVAIL; 15201 } 15202 15203 /* 15204 * Function: 15205 * bcm_esw_tsn_sr_rx_flowset_create 15206 * Purpose: 15207 * Create an SR RX flowset. 15208 * Parameters: 15209 * unit - (IN) unit number 15210 * pri_map - (IN) TSN priority map ID 15211 * def_cfg - (IN) default flow configuration 15212 * flowset - (OUT) flowset ID 15213 * Returns: 15214 * BCM_E_XXX 15215 * Notes: 15216 */ 15217 int 15218 bcm_esw_tsn_sr_rx_flowset_create( 15219 int unit, 15220 bcm_tsn_pri_map_t pri_map, 15221 bcm_tsn_sr_rx_flow_config_t *def_cfg, 15222 bcm_tsn_sr_flowset_t *flowset) 15223 { 15224 #if defined(BCM_TSN_SR_SUPPORT) 15225 if (soc_feature(unit, soc_feature_tsn_sr)) { 15226 return 15227 bcmi_esw_tsn_sr_rx_flowset_create(unit, pri_map, def_cfg, flowset); 15228 } 15229 #endif /* BCM_TSN_SR_SUPPORT */ 15230 return BCM_E_UNAVAIL; 15231 } 15232 15233 /* 15234 * Function: 15235 * bcm_esw_tsn_sr_rx_flowset_config_get 15236 * Purpose: 15237 * Get default configuration for the specified SR flowset 15238 * Parameters: 15239 * unit - (IN) unit number 15240 * flowset - (IN) flowset ID 15241 * pri_map - (OUT) TSN priority map ID 15242 * default_config - (OUT) default flow configuration 15243 * Returns: 15244 * BCM_E_XXX 15245 * Notes: 15246 * If it's called with a TX flowset, BCM_E_BADID is returned 15247 */ 15248 int 15249 bcm_esw_tsn_sr_rx_flowset_config_get( 15250 int unit, 15251 bcm_tsn_sr_flowset_t flowset, 15252 bcm_tsn_pri_map_t *pri_map, 15253 bcm_tsn_sr_rx_flow_config_t *default_config) 15254 { 15255 #if defined(BCM_TSN_SR_SUPPORT) 15256 if (soc_feature(unit, soc_feature_tsn_sr)) { 15257 return bcmi_esw_tsn_sr_rx_flowset_config_get( 15258 unit, flowset, pri_map, default_config); 15259 } 15260 #endif /* BCM_TSN_SR_SUPPORT */ 15261 return BCM_E_UNAVAIL; 15262 } 15263 15264 /* 15265 * Function: 15266 * bcm_esw_tsn_sr_flowset_status_get 15267 * Purpose: 15268 * Get current status of specified SR flowset 15269 * Parameters: 15270 * unit - (IN) unit number 15271 * flowset - (IN) flowset ID 15272 * status - (OUT) status structure 15273 * Returns: 15274 * BCM_E_XXX 15275 * Notes: 15276 */ 15277 int 15278 bcm_esw_tsn_sr_flowset_status_get( 15279 int unit, 15280 bcm_tsn_sr_flowset_t flowset, 15281 bcm_tsn_sr_flowset_status_t *status) 15282 { 15283 #if defined(BCM_TSN_SR_SUPPORT) 15284 if (soc_feature(unit, soc_feature_tsn_sr)) { 15285 return bcmi_esw_tsn_sr_flowset_status_get(unit, flowset, status); 15286 } 15287 #endif /* BCM_TSN_SR_SUPPORT */ 15288 return BCM_E_UNAVAIL; 15289 } 15290 15291 /* 15292 * Function: 15293 * bcm_esw_tsn_sr_flowset_traverse 15294 * Purpose: 15295 * Traverse all created SR flowsets 15296 * Parameters: 15297 * unit - (IN) unit number 15298 * is_rx - (IN) 1 for RX flowsets; 0 for TX flowsets 15299 * cb - (IN) callback function 15300 * user_data - (IN) user data supplied to the callback function 15301 * Returns: 15302 * BCM_E_XXX 15303 * Notes: 15304 */ 15305 int 15306 bcm_esw_tsn_sr_flowset_traverse( 15307 int unit, 15308 int is_rx, 15309 bcm_tsn_sr_flowset_traverse_cb cb, 15310 void *user_data) 15311 { 15312 #if defined(BCM_TSN_SR_SUPPORT) 15313 if (soc_feature(unit, soc_feature_tsn_sr)) { 15314 return bcmi_esw_tsn_sr_flowset_traverse(unit, is_rx, cb, user_data); 15315 } 15316 #endif /* BCM_TSN_SR_SUPPORT */ 15317 return BCM_E_UNAVAIL; 15318 } 15319 15320 /* 15321 * Function: 15322 * bcm_esw_tsn_sr_flowset_destroy 15323 * Purpose: 15324 * Destroy an SR (TX or RX) flowset. 15325 * Parameters: 15326 * unit - (IN) unit number 15327 * flowset - (IN) flowset ID 15328 * Returns: 15329 * BCM_E_XXX 15330 * Notes: 15331 */ 15332 int 15333 bcm_esw_tsn_sr_flowset_destroy(int unit, bcm_tsn_sr_flowset_t flowset) 15334 { 15335 #if defined(BCM_TSN_SR_SUPPORT) 15336 if (soc_feature(unit, soc_feature_tsn_sr)) { 15337 return bcmi_esw_tsn_sr_flowset_destroy(unit, flowset); 15338 } 15339 #endif /* BCM_TSN_SR_SUPPORT */ 15340 return BCM_E_UNAVAIL; 15341 } 15342 15343 /* 15344 * Function: 15345 * bcm_esw_tsn_sr_flowset_flow_get 15346 * Purpose: 15347 * Retrieve an individual SR flow based on the flow offset from a flow set. 15348 * Parameters: 15349 * unit - (IN) unit number 15350 * flowset - (IN) flowset ID 15351 * index - (IN) index of the flow 15352 * flow_id - (OUT) flow ID 15353 * Returns: 15354 * BCM_E_XXX 15355 * Notes: 15356 */ 15357 int 15358 bcm_esw_tsn_sr_flowset_flow_get( 15359 int unit, 15360 bcm_tsn_sr_flowset_t flowset, 15361 int index, 15362 bcm_tsn_sr_flow_t *flow_id) 15363 { 15364 #if defined(BCM_TSN_SR_SUPPORT) 15365 if (soc_feature(unit, soc_feature_tsn_sr)) { 15366 return bcmi_esw_tsn_sr_flowset_flow_get(unit, flowset, index, flow_id); 15367 } 15368 #endif /* BCM_TSN_SR_SUPPORT */ 15369 return BCM_E_UNAVAIL; 15370 } 15371 15372 /* 15373 * Function: 15374 * bcm_esw_tsn_sr_tx_flow_config_get 15375 * Purpose: 15376 * Get configuration for the specified SR flow 15377 * Parameters: 15378 * unit - (IN) unit number 15379 * flow_id - (IN) flow ID 15380 * config - (OUT) flow configuration 15381 * Returns: 15382 * BCM_E_XXX 15383 * Notes: 15384 * If it's called with a RX flow, BCM_E_BADID is returned 15385 */ 15386 int 15387 bcm_esw_tsn_sr_tx_flow_config_get( 15388 int unit, 15389 bcm_tsn_sr_flow_t flow_id, 15390 bcm_tsn_sr_tx_flow_config_t *config) 15391 { 15392 #if defined(BCM_TSN_SR_SUPPORT) 15393 if (soc_feature(unit, soc_feature_tsn_sr)) { 15394 return bcmi_esw_tsn_sr_tx_flow_config_get(unit, flow_id, config); 15395 } 15396 #endif /* BCM_TSN_SR_SUPPORT */ 15397 return BCM_E_UNAVAIL; 15398 } 15399 15400 /* 15401 * Function: 15402 * bcm_esw_tsn_sr_tx_flow_config_set 15403 * Purpose: 15404 * Set configuration for the specified SR flow 15405 * Parameters: 15406 * unit - (IN) unit number 15407 * flow_id - (IN) flow ID 15408 * config - (IN) flow configuration 15409 * Returns: 15410 * BCM_E_XXX 15411 * Notes: 15412 * If it's called with a RX flow, BCM_E_BADID is returned 15413 */ 15414 int 15415 bcm_esw_tsn_sr_tx_flow_config_set( 15416 int unit, 15417 bcm_tsn_sr_flow_t flow_id, 15418 bcm_tsn_sr_tx_flow_config_t *config) 15419 { 15420 #if defined(BCM_TSN_SR_SUPPORT) 15421 if (soc_feature(unit, soc_feature_tsn_sr)) { 15422 return bcmi_esw_tsn_sr_tx_flow_config_set(unit, flow_id, config); 15423 } 15424 #endif /* BCM_TSN_SR_SUPPORT */ 15425 return BCM_E_UNAVAIL; 15426 } 15427 15428 /* 15429 * Function: 15430 * bcm_esw_tsn_sr_tx_flow_status_get 15431 * Purpose: 15432 * Get status for the specified flow 15433 * Parameters: 15434 * unit - (IN) unit number 15435 * flow_id - (IN) flow ID 15436 * status - (OUT) flow status 15437 * Returns: 15438 * BCM_E_XXX 15439 * Notes: 15440 * If it's called with a RX flow, BCM_E_BADID is returned 15441 */ 15442 int 15443 bcm_esw_tsn_sr_tx_flow_status_get( 15444 int unit, 15445 bcm_tsn_sr_flow_t flow_id, 15446 bcm_tsn_sr_tx_flow_status_t *status) 15447 { 15448 #if defined(BCM_TSN_SR_SUPPORT) 15449 if (soc_feature(unit, soc_feature_tsn_sr)) { 15450 return bcmi_esw_tsn_sr_tx_flow_status_get(unit, flow_id, status); 15451 } 15452 #endif /* BCM_TSN_SR_SUPPORT */ 15453 return BCM_E_UNAVAIL; 15454 } 15455 15456 /* 15457 * Function: 15458 * bcm_esw_tsn_sr_rx_flow_config_get 15459 * Purpose: 15460 * Get configuration for the specified SR flow 15461 * Parameters: 15462 * unit - (IN) unit number 15463 * flow_id - (IN) flow ID 15464 * config - (OUT) flow configuration 15465 * Returns: 15466 * BCM_E_XXX 15467 * Notes: 15468 * If it's called with a TX flow, BCM_E_BADID is returned 15469 */ 15470 int 15471 bcm_esw_tsn_sr_rx_flow_config_get( 15472 int unit, 15473 bcm_tsn_sr_flow_t flow_id, 15474 bcm_tsn_sr_rx_flow_config_t *config) 15475 { 15476 #if defined(BCM_TSN_SR_SUPPORT) 15477 if (soc_feature(unit, soc_feature_tsn_sr)) { 15478 return bcmi_esw_tsn_sr_rx_flow_config_get(unit, flow_id, config); 15479 } 15480 #endif /* BCM_TSN_SR_SUPPORT */ 15481 return BCM_E_UNAVAIL; 15482 } 15483 15484 /* 15485 * Function: 15486 * bcm_esw_tsn_sr_rx_flow_config_set 15487 * Purpose: 15488 * Set configuration for the specified SR flow 15489 * Parameters: 15490 * unit - (IN) unit number 15491 * flow_id - (IN) flow ID 15492 * config - (IN) flow configuration 15493 * Returns: 15494 * BCM_E_XXX 15495 * Notes: 15496 * If it's called with a TX flow, BCM_E_BADID is returned 15497 */ 15498 int 15499 bcm_esw_tsn_sr_rx_flow_config_set( 15500 int unit, 15501 bcm_tsn_sr_flow_t flow_id, 15502 bcm_tsn_sr_rx_flow_config_t *config) 15503 { 15504 #if defined(BCM_TSN_SR_SUPPORT) 15505 if (soc_feature(unit, soc_feature_tsn_sr)) { 15506 return bcmi_esw_tsn_sr_rx_flow_config_set(unit, flow_id, config); 15507 } 15508 #endif /* BCM_TSN_SR_SUPPORT */ 15509 return BCM_E_UNAVAIL; 15510 } 15511 15512 /* 15513 * Function: 15514 * bcm_esw_tsn_sr_rx_flow_status_get 15515 * Purpose: 15516 * Get status for the specified flow 15517 * Parameters: 15518 * unit - (IN) unit number 15519 * flow_id - (IN) flow ID 15520 * status - (OUT) flow status 15521 * Returns: 15522 * BCM_E_XXX 15523 * Notes: 15524 * If it's called with a TX flow, BCM_E_BADID is returned 15525 */ 15526 int 15527 bcm_esw_tsn_sr_rx_flow_status_get( 15528 int unit, 15529 bcm_tsn_sr_flow_t flow_id, 15530 bcm_tsn_sr_rx_flow_status_t *status) 15531 { 15532 #if defined(BCM_TSN_SR_SUPPORT) 15533 if (soc_feature(unit, soc_feature_tsn_sr)) { 15534 return bcmi_esw_tsn_sr_rx_flow_status_get(unit, flow_id, status); 15535 } 15536 #endif /* BCM_TSN_SR_SUPPORT */ 15537 return BCM_E_UNAVAIL; 15538 } 15539 15540 /* 15541 * Function: 15542 * bcm_esw_tsn_sr_rx_flow_reset 15543 * Purpose: 15544 * Reset SR RX flow status 15545 * Parameters: 15546 * unit - (IN) unit number 15547 * flags - (IN) flags to select items to reset 15548 * flow_id - (IN) flow ID 15549 * Returns: 15550 * BCM_E_XXX 15551 * Notes: 15552 * If it's called with a TX flow, BCM_E_BADID is returned 15553 */ 15554 int 15555 bcm_esw_tsn_sr_rx_flow_reset(int unit, uint32 flags, bcm_tsn_sr_flow_t flow_id) 15556 { 15557 #if defined(BCM_TSN_SR_SUPPORT) 15558 if (soc_feature(unit, soc_feature_tsn_sr)) { 15559 return bcmi_esw_tsn_sr_rx_flow_reset(unit, flags, flow_id); 15560 } 15561 #endif /* BCM_TSN_SR_SUPPORT */ 15562 return BCM_E_UNAVAIL; 15563 } 15564 15565 /* 15566 * Function: 15567 * bcm_esw_tsn_sr_rx_flow_seqnum_history_set 15568 * Purpose: 15569 * Set the sequence number history bits (one bit for one sequence number) 15570 * in the RX flow. 15571 * Parameters: 15572 * unit - (IN) unit number 15573 * flow_id - (IN) flow ID 15574 * offset_in_bits - (IN) Offset (in bits) in the seqnum history window 15575 * size_in_bits - (IN) Size (in bits) to write 15576 * history_bits - (IN) Bit buffer to write 15577 * Returns: 15578 * BCM_E_XXX 15579 * Notes: 15580 * If it's called with a TX flow, BCM_E_BADID is returned 15581 */ 15582 int 15583 bcm_esw_tsn_sr_rx_flow_seqnum_history_set( 15584 int unit, 15585 bcm_tsn_sr_flow_t flow_id, 15586 int offset_in_bits, 15587 int size_in_bits, 15588 uint8 *history_bits) 15589 { 15590 #if defined(BCM_TSN_SR_SUPPORT) 15591 if (soc_feature(unit, soc_feature_tsn_sr)) { 15592 return bcmi_esw_tsn_sr_rx_flow_seqnum_history_set( 15593 unit, flow_id, offset_in_bits, size_in_bits, history_bits); 15594 } 15595 #endif /* BCM_TSN_SR_SUPPORT */ 15596 return BCM_E_UNAVAIL; 15597 } 15598 15599 /* 15600 * Function: 15601 * bcm_esw_tsn_sr_rx_flow_seqnum_history_get 15602 * Purpose: 15603 * Get the sequence number history bits (one bit for one sequence number) 15604 * in the RX flow. 15605 * Parameters: 15606 * unit - (IN) unit number 15607 * flow_id - (IN) flow ID 15608 * offset_in_bits - (IN) Offset (in bits) in the seqnum history window 15609 * max_size_in_bits - (IN) Size (in bits) of the buffer 15610 * history_bits - (OUT) Bit buffer to read 15611 * actual_size - (OUT) Actual size (in bits) read to the buffer 15612 * Returns: 15613 * BCM_E_XXX 15614 * Notes: 15615 * If it's called with a TX flow, BCM_E_BADID is returned 15616 */ 15617 int 15618 bcm_esw_tsn_sr_rx_flow_seqnum_history_get( 15619 int unit, 15620 bcm_tsn_sr_flow_t flow_id, 15621 int offset_in_bits, 15622 int max_size_in_bits, 15623 uint8 *history_bits, 15624 int *actual_size) 15625 { 15626 #if defined(BCM_TSN_SR_SUPPORT) 15627 if (soc_feature(unit, soc_feature_tsn_sr)) { 15628 return bcmi_esw_tsn_sr_rx_flow_seqnum_history_get( 15629 unit, flow_id, offset_in_bits, max_size_in_bits, 15630 history_bits, actual_size); 15631 } 15632 #endif /* BCM_TSN_SR_SUPPORT */ 15633 return BCM_E_UNAVAIL; 15634 } 15635 15636 /* 15637 * Function: 15638 * bcm_esw_tsn_flowset_create 15639 * Purpose: 15640 * Create a TSN flowset. 15641 * Parameters: 15642 * unit - (IN) unit number 15643 * pri_map - (IN) TSN priority map ID 15644 * def_cfg - (IN) default flow configuration 15645 * flowset - (OUT) flowset ID 15646 * Returns: 15647 * BCM_E_XXX 15648 * Notes: 15649 */ 15650 int 15651 bcm_esw_tsn_flowset_create( 15652 int unit, 15653 bcm_tsn_pri_map_t pri_map, 15654 bcm_tsn_flow_config_t *def_cfg, 15655 bcm_tsn_flowset_t *flowset) 15656 { 15657 #if defined(BCM_TSN_SUPPORT) 15658 if (soc_feature(unit, soc_feature_tsn)) { 15659 return bcmi_esw_tsn_flowset_create(unit, pri_map, def_cfg, flowset); 15660 } 15661 #endif /* BCM_TSN_SUPPORT */ 15662 return BCM_E_UNAVAIL; 15663 } 15664 15665 /* 15666 * Function: 15667 * bcm_esw_tsn_flowset_status_get 15668 * Purpose: 15669 * Get current status of specified TSN flowset 15670 * Parameters: 15671 * unit - (IN) unit number 15672 * flowset - (IN) flowset ID 15673 * status - (OUT) status structure 15674 * Returns: 15675 * BCM_E_XXX 15676 * Notes: 15677 */ 15678 int 15679 bcm_esw_tsn_flowset_status_get( 15680 int unit, 15681 bcm_tsn_flowset_t flowset, 15682 bcm_tsn_flowset_status_t *status) 15683 { 15684 #if defined(BCM_TSN_SUPPORT) 15685 if (soc_feature(unit, soc_feature_tsn)) { 15686 return bcmi_esw_tsn_flowset_status_get(unit, flowset, status); 15687 } 15688 #endif /* BCM_TSN_SUPPORT */ 15689 return BCM_E_UNAVAIL; 15690 } 15691 15692 /* 15693 * Function: 15694 * bcm_esw_tsn_flowset_flow_get 15695 * Purpose: 15696 * Retrieve an individual TSN flow based on the flow offset from a flow set. 15697 * Parameters: 15698 * unit - (IN) unit number 15699 * flowset - (IN) flowset ID 15700 * index - (IN) index of the flow 15701 * flow_id - (OUT) flow ID 15702 * Returns: 15703 * BCM_E_XXX 15704 * Notes: 15705 */ 15706 int 15707 bcm_esw_tsn_flowset_flow_get( 15708 int unit, 15709 bcm_tsn_flowset_t flowset, 15710 int index, 15711 bcm_tsn_flow_t *flow_id) 15712 { 15713 #if defined(BCM_TSN_SUPPORT) 15714 if (soc_feature(unit, soc_feature_tsn)) { 15715 return bcmi_esw_tsn_flowset_flow_get(unit, flowset, index, flow_id); 15716 } 15717 #endif /* BCM_TSN_SUPPORT */ 15718 return BCM_E_UNAVAIL; 15719 } 15720 15721 /* 15722 * Function: 15723 * bcm_esw_tsn_flowset_config_get 15724 * Purpose: 15725 * Get default configuration for the specified TSN flowset 15726 * Parameters: 15727 * unit - (IN) unit number 15728 * flowset - (IN) flowset ID 15729 * pri_map - (OUT) TSN priority map ID 15730 * default_config - (OUT) default flow configuration 15731 * Returns: 15732 * BCM_E_XXX 15733 * Notes: 15734 */ 15735 int 15736 bcm_esw_tsn_flowset_config_get( 15737 int unit, 15738 bcm_tsn_flowset_t flowset, 15739 bcm_tsn_pri_map_t *pri_map, 15740 bcm_tsn_flow_config_t *default_config) 15741 { 15742 #if defined(BCM_TSN_SUPPORT) 15743 if (soc_feature(unit, soc_feature_tsn)) { 15744 return bcmi_esw_tsn_flowset_config_get(unit, flowset, 15745 pri_map, default_config); 15746 } 15747 #endif /* BCM_TSN_SUPPORT */ 15748 return BCM_E_UNAVAIL; 15749 } 15750 15751 /* 15752 * Function: 15753 * bcm_esw_tsn_flowset_traverse 15754 * Purpose: 15755 * Traverse all created TSN flowsets 15756 * Parameters: 15757 * unit - (IN) unit number 15758 * cb - (IN) callback function 15759 * user_data - (IN) user data supplied to the callback function 15760 * Returns: 15761 * BCM_E_XXX 15762 * Notes: 15763 */ 15764 int 15765 bcm_esw_tsn_flowset_traverse( 15766 int unit, 15767 bcm_tsn_flowset_traverse_cb cb, 15768 void *user_data) 15769 { 15770 #if defined(BCM_TSN_SUPPORT) 15771 if (soc_feature(unit, soc_feature_tsn)) { 15772 return bcmi_esw_tsn_flowset_traverse(unit, cb, user_data); 15773 } 15774 #endif /* BCM_TSN_SUPPORT */ 15775 return BCM_E_UNAVAIL; 15776 15777 } 15778 15779 /* 15780 * Function: 15781 * bcm_esw_tsn_flowset_destroy 15782 * Purpose: 15783 * Destroy a TSN flowset. 15784 * Parameters: 15785 * unit - (IN) unit number 15786 * flowset - (IN) flowset ID 15787 * Returns: 15788 * BCM_E_XXX 15789 * Notes: 15790 */ 15791 int 15792 bcm_esw_tsn_flowset_destroy(int unit, bcm_tsn_flowset_t flowset) 15793 { 15794 #if defined(BCM_TSN_SUPPORT) 15795 if (soc_feature(unit, soc_feature_tsn)) { 15796 return bcmi_esw_tsn_flowset_destroy(unit, flowset); 15797 } 15798 #endif /* BCM_TSN_SUPPORT */ 15799 return BCM_E_UNAVAIL; 15800 } 15801 15802 /* 15803 * Function: 15804 * bcm_esw_tsn_flow_config_get 15805 * Purpose: 15806 * Get configuration for the specified TSN flow 15807 * Parameters: 15808 * unit - (IN) unit number 15809 * flow_id - (IN) flow ID 15810 * config - (OUT) flow configuration 15811 * Returns: 15812 * BCM_E_XXX 15813 * Notes: 15814 */ 15815 int 15816 bcm_esw_tsn_flow_config_get( 15817 int unit, 15818 bcm_tsn_flow_t flow_id, 15819 bcm_tsn_flow_config_t *config) 15820 { 15821 #if defined(BCM_TSN_SUPPORT) 15822 if (soc_feature(unit, soc_feature_tsn)) { 15823 return bcmi_esw_tsn_flow_config_get(unit, flow_id, config); 15824 } 15825 #endif /* BCM_TSN_SUPPORT */ 15826 return BCM_E_UNAVAIL; 15827 } 15828 15829 /* 15830 * Function: 15831 * bcm_esw_tsn_flow_config_set 15832 * Purpose: 15833 * Set configuration for the specified TSN flow 15834 * Parameters: 15835 * unit - (IN) unit number 15836 * flow_id - (IN) flow ID 15837 * config - (IN) flow configuration 15838 * Returns: 15839 * BCM_E_XXX 15840 * Notes: 15841 */ 15842 int 15843 bcm_esw_tsn_flow_config_set( 15844 int unit, 15845 bcm_tsn_flow_t flow_id, 15846 bcm_tsn_flow_config_t *config) 15847 { 15848 #if defined(BCM_TSN_SUPPORT) 15849 if (soc_feature(unit, soc_feature_tsn)) { 15850 return bcmi_esw_tsn_flow_config_set(unit, flow_id, config); 15851 } 15852 #endif /* BCM_TSN_SUPPORT */ 15853 return BCM_E_UNAVAIL; 15854 } 15855 15856 /* 15857 * Function: 15858 * bcm_esw_tsn_sr_auto_learn_group_create 15859 * Purpose: 15860 * Add an Auto Learn config to hardware. 15861 * Parameters: 15862 * unit - (IN) Unit number 15863 * config - (IN) Auto Learn Group configuration 15864 * group_id - (OUT) Group ID 15865 * Returns: 15866 * BCM_E_xxx 15867 */ 15868 int 15869 bcm_esw_tsn_sr_auto_learn_group_create( 15870 int unit, 15871 bcm_tsn_sr_auto_learn_group_config_t *config, 15872 int *group_id) 15873 { 15874 #if defined(BCM_TSN_SR_SUPPORT) 15875 if (soc_feature(unit, soc_feature_tsn_sr) && 15876 soc_feature(unit, soc_feature_tsn_sr_auto_learn)) { 15877 return bcmi_esw_tsn_sr_auto_learn_group_create(unit, config, group_id); 15878 } 15879 #endif /* BCM_TSN_SR_SUPPORT */ 15880 return BCM_E_UNAVAIL; 15881 } 15882 15883 /* 15884 * Function: 15885 * bcm_esw_tsn_sr_auto_learn_group_get 15886 * Purpose: 15887 * Get the Auto Learn config with the given group_id. 15888 * Parameters: 15889 * unit - (IN) Unit number 15890 * group_id - (IN) Group ID 15891 * config - (OUT) Auto Learn Group configuration 15892 * Returns: 15893 * BCM_E_xxx 15894 */ 15895 int 15896 bcm_esw_tsn_sr_auto_learn_group_get( 15897 int unit, 15898 int group_id, 15899 bcm_tsn_sr_auto_learn_group_config_t *config) 15900 { 15901 #if defined(BCM_TSN_SR_SUPPORT) 15902 if (soc_feature(unit, soc_feature_tsn_sr) && 15903 soc_feature(unit, soc_feature_tsn_sr_auto_learn)) { 15904 return bcmi_esw_tsn_sr_auto_learn_group_get(unit, group_id, config); 15905 } 15906 #endif /* BCM_TSN_SR_SUPPORT */ 15907 return BCM_E_UNAVAIL; 15908 } 15909 15910 /* 15911 * Function: 15912 * bcm_esw_tsn_sr_auto_learn_group_set 15913 * Purpose: 15914 * Set Auto Learn config with the given group_id. 15915 * Parameters: 15916 * unit - (IN) Unit number 15917 * group_id - (IN) Group ID 15918 * config - (IN) Auto Learn Group configuration 15919 * Returns: 15920 * BCM_E_xxx 15921 */ 15922 int 15923 bcm_esw_tsn_sr_auto_learn_group_set( 15924 int unit, 15925 int group_id, 15926 bcm_tsn_sr_auto_learn_group_config_t *config) 15927 { 15928 #if defined(BCM_TSN_SR_SUPPORT) 15929 if (soc_feature(unit, soc_feature_tsn_sr) && 15930 soc_feature(unit, soc_feature_tsn_sr_auto_learn)) { 15931 return bcmi_esw_tsn_sr_auto_learn_group_set(unit, group_id, config); 15932 } 15933 #endif /* BCM_TSN_SR_SUPPORT */ 15934 return BCM_E_UNAVAIL; 15935 } 15936 15937 /* 15938 * Function: 15939 * bcm_esw_tsn_sr_auto_learn_group_destroy 15940 * Purpose: 15941 * Destroy an Auto Learn config with the given group_id by removing it 15942 * from hardware and deleting the associated software state info. 15943 * Parameters: 15944 * unit - (IN) Unit number 15945 * group_id - (IN) Group ID 15946 * Returns: 15947 * BCM_E_xxx 15948 */ 15949 int 15950 bcm_esw_tsn_sr_auto_learn_group_destroy( 15951 int unit, 15952 int group_id) 15953 { 15954 #if defined(BCM_TSN_SR_SUPPORT) 15955 if (soc_feature(unit, soc_feature_tsn_sr) && 15956 soc_feature(unit, soc_feature_tsn_sr_auto_learn)) { 15957 return bcmi_esw_tsn_sr_auto_learn_group_destroy(unit, group_id); 15958 } 15959 #endif /* BCM_TSN_SR_SUPPORT */ 15960 return BCM_E_UNAVAIL; 15961 } 15962 15963 /* 15964 * Function: 15965 * bcm_esw_tsn_sr_auto_learn_group_traverse 15966 * Purpose: 15967 * Traverse the Auto Learn config information. 15968 * Parameters: 15969 * unit - (IN) Unit number 15970 * cb - (IN) Traverse call back function 15971 * user_data - (IN) User data 15972 * Returns: 15973 * BCM_E_xxx 15974 */ 15975 int 15976 bcm_esw_tsn_sr_auto_learn_group_traverse( 15977 int unit, 15978 bcm_tsn_sr_auto_learn_group_traverse_cb cb, 15979 void *user_data) 15980 { 15981 #if defined(BCM_TSN_SR_SUPPORT) 15982 if (soc_feature(unit, soc_feature_tsn_sr) && 15983 soc_feature(unit, soc_feature_tsn_sr_auto_learn)) { 15984 return bcmi_esw_tsn_sr_auto_learn_group_traverse(unit, cb, user_data); 15985 } 15986 #endif /* BCM_TSN_SR_SUPPORT */ 15987 return BCM_E_UNAVAIL; 15988 } 15989 15990 /* 15991 * Function: 15992 * bcm_esw_tsn_sr_auto_learn_enable 15993 * Purpose: 15994 * Enable/disable SR flow auto learn subsystem 15995 * Parameters: 15996 * unit - (IN) Unit number 15997 * enable - (IN) Enable/Disable 15998 * config - (IN) Auto Learn configuration 15999 * Returns: 16000 * BCM_E_xxx 16001 */ 16002 int 16003 bcm_esw_tsn_sr_auto_learn_enable( 16004 int unit, 16005 int enable, 16006 bcm_tsn_sr_auto_learn_config_t *config) 16007 { 16008 #if defined(BCM_TSN_SR_SUPPORT) 16009 if (soc_feature(unit, soc_feature_tsn_sr) && 16010 soc_feature(unit, soc_feature_tsn_sr_auto_learn)) { 16011 return bcmi_esw_tsn_sr_auto_learn_enable(unit, enable, config); 16012 } 16013 #endif /* BCM_TSN_SR_SUPPORT */ 16014 return BCM_E_UNAVAIL; 16015 } 16016 16017 /* 16018 * Function: 16019 * bcm_esw_tsn_sr_auto_learn_enable_get 16020 * Purpose: 16021 * Get enable/disable SR flow auto learn subsystem 16022 * Parameters: 16023 * unit - (IN) Unit number 16024 * enable - (OUT) Enable/disable 16025 * config - (OUT) Auto Learn configuration 16026 * Returns: 16027 * BCM_E_xxx 16028 */ 16029 int 16030 bcm_esw_tsn_sr_auto_learn_enable_get( 16031 int unit, 16032 int *enabled, 16033 bcm_tsn_sr_auto_learn_config_t *config) 16034 { 16035 #if defined(BCM_TSN_SR_SUPPORT) 16036 if (soc_feature(unit, soc_feature_tsn_sr) && 16037 soc_feature(unit, soc_feature_tsn_sr_auto_learn)) { 16038 return bcmi_esw_tsn_sr_auto_learn_enable_get(unit, enabled, config); 16039 } 16040 #endif /* BCM_TSN_SR_SUPPORT */ 16041 return BCM_E_UNAVAIL; 16042 } 16043 16044 /* 16045 * Function: 16046 * bcm_esw_tsn_control_set 16047 * Description: 16048 * Configure device operation modes for TSN. 16049 * Parameters: 16050 * unit - (IN) Unit number. 16051 * type - (IN) Control type of bcm_tsn_control_t. 16052 * arg - (IN) argument to be set 16053 * Returns: 16054 * BCM_E_XXX 16055 */ 16056 int 16057 bcm_esw_tsn_control_set(int unit, bcm_tsn_control_t type, uint32 arg) 16058 { 16059 #if defined(BCM_TSN_SUPPORT) 16060 if (soc_feature(unit, soc_feature_tsn)) { 16061 return bcmi_esw_tsn_control_set(unit, type, arg); 16062 } 16063 #endif /* BCM_TSN_SUPPORT */ 16064 return BCM_E_UNAVAIL; 16065 } 16066 16067 /* 16068 * Function: 16069 * bcm_esw_tsn_control_get 16070 * Description: 16071 * Get the configure of device TSN operation modes. 16072 * Parameters: 16073 * unit - (IN) Unit number. 16074 * type - (IN) Control type of bcm_tsn_control_t. 16075 * arg - (OUT) argument got 16076 * Returns: 16077 * BCM_E_XXX 16078 */ 16079 int 16080 bcm_esw_tsn_control_get(int unit, bcm_tsn_control_t type, uint32 *arg) 16081 { 16082 #if defined(BCM_TSN_SUPPORT) 16083 if (soc_feature(unit, soc_feature_tsn)) { 16084 return bcmi_esw_tsn_control_get(unit, type, arg); 16085 } 16086 #endif /* BCM_TSN_SUPPORT */ 16087 return BCM_E_UNAVAIL; 16088 } 16089 16090 /* 16091 * Function: 16092 * bcm_esw_tsn_port_control_set 16093 * Description: 16094 * Configure port operation modes for TSN. 16095 * Parameters: 16096 * unit - (IN) Unit number. 16097 * port - (IN) Port number. 16098 * type - (IN) Control type of bcm_tsn_control_t. 16099 * arg - (IN) argument to be set 16100 * Returns: 16101 * BCM_E_XXX 16102 */ 16103 int 16104 bcm_esw_tsn_port_control_set( 16105 int unit, 16106 bcm_gport_t port, 16107 bcm_tsn_control_t type, 16108 uint32 arg) 16109 { 16110 #if defined(BCM_TSN_SUPPORT) 16111 if (soc_feature(unit, soc_feature_tsn)) { 16112 return bcmi_esw_tsn_port_control_set(unit, port, type, arg); 16113 } 16114 #endif /* BCM_TSN_SUPPORT */ 16115 return BCM_E_UNAVAIL; 16116 } 16117 16118 16119 /* 16120 * Function: 16121 * bcm_esw_tsn_port_control_get 16122 * Description: 16123 * Get the configure of port TSN operation modes. 16124 * Parameters: 16125 * unit - (IN) Unit number. 16126 * port - (IN) Port number. 16127 * type - (IN) Control type of bcm_tsn_control_t. 16128 * arg - (OUT) argument got 16129 * Returns: 16130 * BCM_E_XXX 16131 */ 16132 int bcm_esw_tsn_port_control_get( 16133 int unit, 16134 bcm_gport_t port, 16135 bcm_tsn_control_t type, 16136 uint32 *arg) 16137 { 16138 #if defined(BCM_TSN_SUPPORT) 16139 if (soc_feature(unit, soc_feature_tsn)) { 16140 return bcmi_esw_tsn_port_control_get(unit, port, type, arg); 16141 } 16142 #endif /* BCM_TSN_SUPPORT */ 16143 return BCM_E_UNAVAIL; 16144 } 16145 16146 /* 16147 * Function: 16148 * bcm_esw_tsn_port_stat_set 16149 * Description: 16150 * Set 64-bit counter value for specified TSN statistic type. 16151 * Parameters: 16152 * unit - (IN) Unit number 16153 * port - (IN) port number 16154 * stat - (IN) TSN statistics type (see tsn.h) 16155 * val - (IN) 64-bit counter value. 16156 * Returns: 16157 * BCM_E_NONE - Success. 16158 * BCM_E_PARAM - Illegal parameter. 16159 * BCM_E_BADID - Illegal port number. 16160 * BCM_E_INTERNAL - Chip access failure. 16161 * BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip. 16162 * Notes: 16163 */ 16164 int 16165 bcm_esw_tsn_port_stat_set( 16166 int unit, 16167 bcm_gport_t port, 16168 bcm_tsn_stat_t stat, 16169 uint64 val) 16170 { 16171 int rv = BCM_E_UNAVAIL; 16172 16173 #if defined(BCM_TSN_SUPPORT) 16174 /* Write hardware and software accumulated counters */ 16175 if (soc_feature(unit, soc_feature_tsn)) { 16176 rv = bcmi_esw_tsn_stat_portcnt_set(unit, port, stat, val); 16177 } 16178 #endif /* BCM_TSN_SUPPORT */ 16179 16180 return rv; 16181 } 16182 16183 /* 16184 * Function: 16185 * bcm_esw_tsn_port_stat_set32 16186 * Description: 16187 * Set lower 32-bit counter value for specified TSN statistic type. 16188 * Parameters: 16189 * unit - (IN) Unit number 16190 * port - (IN) port number 16191 * stat - (IN) TSN statistics type (see tsn.h) 16192 * val - (IN) 32-bit counter value. 16193 * Returns: 16194 * BCM_E_NONE - Success. 16195 * BCM_E_PARAM - Illegal parameter. 16196 * BCM_E_BADID - Illegal port number. 16197 * BCM_E_INTERNAL - Chip access failure. 16198 * BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip. 16199 * Notes: 16200 * Same as bcm_esw_tsn_port_stat_set, except the counter value is 32-bit. 16201 */ 16202 int 16203 bcm_esw_tsn_port_stat_set32( 16204 int unit, 16205 bcm_gport_t port, 16206 bcm_tsn_stat_t stat, 16207 uint32 val) 16208 { 16209 int rv = BCM_E_UNAVAIL; 16210 #if defined(BCM_TSN_SUPPORT) 16211 uint64 val64; 16212 16213 if (soc_feature(unit, soc_feature_tsn)) { 16214 COMPILER_64_SET(val64, 0, val); 16215 rv = bcm_esw_tsn_port_stat_set(unit, port, stat, val64); 16216 } 16217 #endif /* BCM_TSN_SUPPORT */ 16218 16219 return rv; 16220 } 16221 16222 /* 16223 * Function: 16224 * bcm_esw_tsn_port_stat_get 16225 * Description: 16226 * Get 64-bit counter value for specified TSN statistic type. 16227 * Parameters: 16228 * unit - (IN) Unit number 16229 * port - (IN) port number 16230 * stat - (IN) TSN statistics type (see tsn.h) 16231 * val - (OUT) 64-bit counter value. 16232 * Returns: 16233 * BCM_E_NONE - Success. 16234 * BCM_E_PARAM - Illegal parameter. 16235 * BCM_E_BADID - Illegal port number. 16236 * BCM_E_INTERNAL - Chip access failure. 16237 * BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip. 16238 * Notes: 16239 */ 16240 int 16241 bcm_esw_tsn_port_stat_get( 16242 int unit, 16243 bcm_gport_t port, 16244 bcm_tsn_stat_t stat, 16245 uint64 *val) 16246 { 16247 int rv = BCM_E_UNAVAIL; 16248 16249 /* Input parameter check. */ 16250 if (NULL == val) { 16251 return BCM_E_PARAM; 16252 } 16253 16254 #if defined(BCM_TSN_SUPPORT) 16255 /* Read software accumulated counters */ 16256 if (soc_feature(unit, soc_feature_tsn)) { 16257 rv = bcmi_esw_tsn_stat_portcnt_get(unit, port, 0, stat, val); 16258 } 16259 #endif /* BCM_TSN_SUPPORT */ 16260 16261 return rv; 16262 } 16263 16264 /* 16265 * Function: 16266 * bcm_esw_tsn_port_stat_get32 16267 * Description: 16268 * Get lower 32-bit counter value for specified TSN statistic type. 16269 * Parameters: 16270 * unit - (IN) Unit number 16271 * port - (IN) port number 16272 * stat - (IN) TSN statistics type (see tsn.h) 16273 * val - (OUT) 32-bit counter value. 16274 * Returns: 16275 * BCM_E_NONE - Success. 16276 * BCM_E_PARAM - Illegal parameter. 16277 * BCM_E_BADID - Illegal port number. 16278 * BCM_E_INTERNAL - Chip access failure. 16279 * BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip. 16280 * Notes: 16281 * Same as bcm_esw_tsn_port_stat_get, except converts result to 32-bit. 16282 */ 16283 int 16284 bcm_esw_tsn_port_stat_get32( 16285 int unit, 16286 bcm_gport_t port, 16287 bcm_tsn_stat_t stat, 16288 uint32 *val) 16289 { 16290 int rv = BCM_E_UNAVAIL; 16291 #if defined(BCM_TSN_SUPPORT) 16292 uint64 val64; 16293 #endif /* BCM_TSN_SUPPORT */ 16294 16295 /* Input parameter check. */ 16296 if (NULL == val) { 16297 return BCM_E_PARAM; 16298 } 16299 16300 #if defined(BCM_TSN_SUPPORT) 16301 if (soc_feature(unit, soc_feature_tsn)) { 16302 COMPILER_64_ZERO(val64); 16303 rv = bcm_esw_tsn_port_stat_get(unit, port, stat, &val64); 16304 if (BCM_FAILURE(rv)) { 16305 return rv; 16306 } 16307 16308 COMPILER_64_TO_32_LO(*val, val64); 16309 } 16310 #endif /* BCM_TSN_SUPPORT */ 16311 16312 return rv; 16313 } 16314 16315 /* 16316 * Function: 16317 * bcm_esw_tsn_port_stat_multi_set 16318 * Purpose: 16319 * Set 64-bit counter value for multiple TSN statistic types. 16320 * Parameters: 16321 * unit - (IN) Unit number 16322 * port - (IN) port number 16323 * nstat - (IN) Number of elements in stat array 16324 * stat_arr - (IN) Array of TSN statistics types defined in bcm_tsn_stat_t 16325 * value_arr - (IN) Set statistics values 16326 * Returns: 16327 * BCM_E_NONE - Success. 16328 * BCM_E_PARAM - Illegal parameter. 16329 * BCM_E_BADID - Illegal port number. 16330 * BCM_E_INTERNAL - Chip access failure. 16331 * BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip. 16332 * Notes: 16333 */ 16334 int 16335 bcm_esw_tsn_port_stat_multi_set( 16336 int unit, 16337 bcm_gport_t port, 16338 int nstat, 16339 bcm_tsn_stat_t *stat_arr, 16340 uint64 *value_arr) 16341 { 16342 int rv = BCM_E_UNAVAIL; 16343 #if defined(BCM_TSN_SUPPORT) 16344 int stix; 16345 #endif /* BCM_TSN_SUPPORT */ 16346 16347 /* Input parameter check. */ 16348 if (nstat <= 0) { 16349 return BCM_E_PARAM; 16350 } 16351 if ((NULL == stat_arr) || (NULL == value_arr)) { 16352 return BCM_E_PARAM; 16353 } 16354 16355 #if defined(BCM_TSN_SUPPORT) 16356 if (soc_feature(unit, soc_feature_tsn)) { 16357 for (stix = 0; stix < nstat; stix++) { 16358 rv = bcm_esw_tsn_port_stat_set(unit, port, stat_arr[stix], 16359 value_arr[stix]); 16360 if (BCM_FAILURE(rv)) { 16361 return rv; 16362 } 16363 } 16364 } 16365 #endif /* BCM_TSN_SUPPORT */ 16366 16367 return rv; 16368 } 16369 16370 /* 16371 * Function: 16372 * bcm_esw_tsn_port_stat_multi_set32 16373 * Purpose: 16374 * Set lower 32-bit counter value for multiple TSN statistic types. 16375 * Parameters: 16376 * unit - (IN) Unit number 16377 * port - (IN) port number 16378 * nstat - (IN) Number of elements in stat array 16379 * stat_arr - (IN) Array of TSN statistics types defined in bcm_tsn_stat_t 16380 * value_arr - (IN) Set 32-bit statistics values 16381 * Returns: 16382 * BCM_E_NONE - Success. 16383 * BCM_E_PARAM - Illegal parameter. 16384 * BCM_E_BADID - Illegal port number. 16385 * BCM_E_INTERNAL - Chip access failure. 16386 * BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip. 16387 * Notes: 16388 */ 16389 int 16390 bcm_esw_tsn_port_stat_multi_set32( 16391 int unit, 16392 bcm_gport_t port, 16393 int nstat, 16394 bcm_tsn_stat_t *stat_arr, 16395 uint32 *value_arr) 16396 { 16397 int rv = BCM_E_UNAVAIL; 16398 #if defined(BCM_TSN_SUPPORT) 16399 int stix; 16400 #endif /* BCM_TSN_SUPPORT */ 16401 16402 /* Input parameter check. */ 16403 if (nstat <= 0) { 16404 return BCM_E_PARAM; 16405 } 16406 if ((NULL == stat_arr) || (NULL == value_arr)) { 16407 return BCM_E_PARAM; 16408 } 16409 16410 #if defined(BCM_TSN_SUPPORT) 16411 if (soc_feature(unit, soc_feature_tsn)) { 16412 for (stix = 0; stix < nstat; stix++) { 16413 rv = bcm_esw_tsn_port_stat_set32(unit, port, stat_arr[stix], 16414 value_arr[stix]); 16415 if (BCM_FAILURE(rv)) { 16416 return rv; 16417 } 16418 } 16419 } 16420 #endif /* BCM_TSN_SUPPORT */ 16421 16422 return rv; 16423 } 16424 16425 /* 16426 * Function: 16427 * bcm_esw_tsn_port_stat_multi_get 16428 * Purpose: 16429 * Get 64-bit counter value for multiple TSN statistic types. 16430 * Parameters: 16431 * unit - (IN) Unit number 16432 * port - (IN) port number 16433 * nstat - (IN) Number of elements in stat array 16434 * stat_arr - (IN) Array of TSN statistics types defined in bcm_tsn_stat_t 16435 * value_arr - (OUT) Collected statistics values 16436 * Returns: 16437 * BCM_E_NONE - Success. 16438 * BCM_E_PARAM - Illegal parameter. 16439 * BCM_E_BADID - Illegal port number. 16440 * BCM_E_INTERNAL - Chip access failure. 16441 * BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip. 16442 * Notes: 16443 */ 16444 int 16445 bcm_esw_tsn_port_stat_multi_get( 16446 int unit, 16447 bcm_gport_t port, 16448 int nstat, 16449 bcm_tsn_stat_t *stat_arr, 16450 uint64 *value_arr) 16451 { 16452 int rv = BCM_E_UNAVAIL; 16453 #if defined(BCM_TSN_SUPPORT) 16454 int stix; 16455 #endif /* BCM_TSN_SUPPORT */ 16456 16457 /* Input parameter check. */ 16458 if (nstat <= 0) { 16459 return BCM_E_PARAM; 16460 } 16461 if ((NULL == stat_arr) || (NULL == value_arr)) { 16462 return BCM_E_PARAM; 16463 } 16464 16465 #if defined(BCM_TSN_SUPPORT) 16466 if (soc_feature(unit, soc_feature_tsn)) { 16467 for (stix = 0; stix < nstat; stix++) { 16468 rv = bcm_esw_tsn_port_stat_get(unit, port, stat_arr[stix], 16469 &(value_arr[stix])); 16470 if (BCM_FAILURE(rv)) { 16471 return rv; 16472 } 16473 } 16474 } 16475 #endif /* BCM_TSN_SUPPORT */ 16476 16477 return rv; 16478 } 16479 16480 /* 16481 * Function: 16482 * bcm_esw_tsn_port_stat_multi_get32 16483 * Purpose: 16484 * Get lower 32-bit counter value for multiple TSN statistic types. 16485 * Parameters: 16486 * unit - (IN) Unit number 16487 * port - (IN) port number 16488 * nstat - (IN) Number of elements in stat array 16489 * stat_arr - (IN) Array of TSN statistics types defined in bcm_tsn_stat_t 16490 * value_arr - (OUT) Collected 32-bit statistics values 16491 * Returns: 16492 * BCM_E_NONE - Success. 16493 * BCM_E_PARAM - Illegal parameter. 16494 * BCM_E_BADID - Illegal port number. 16495 * BCM_E_INTERNAL - Chip access failure. 16496 * BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip. 16497 * Notes: 16498 */ 16499 int 16500 bcm_esw_tsn_port_stat_multi_get32( 16501 int unit, 16502 bcm_gport_t port, 16503 int nstat, 16504 bcm_tsn_stat_t *stat_arr, 16505 uint32 *value_arr) 16506 { 16507 int rv = BCM_E_UNAVAIL; 16508 #if defined(BCM_TSN_SUPPORT) 16509 int stix; 16510 #endif /* BCM_TSN_SUPPORT */ 16511 16512 /* Input parameter check. */ 16513 if (nstat <= 0) { 16514 return BCM_E_PARAM; 16515 } 16516 if ((NULL == stat_arr) || (NULL == value_arr)) { 16517 return BCM_E_PARAM; 16518 } 16519 16520 #if defined(BCM_TSN_SUPPORT) 16521 if (soc_feature(unit, soc_feature_tsn)) { 16522 for (stix = 0; stix < nstat; stix++) { 16523 rv = bcm_esw_tsn_port_stat_get32(unit, port, stat_arr[stix], 16524 &(value_arr[stix])); 16525 if (BCM_FAILURE(rv)) { 16526 return rv; 16527 } 16528 } 16529 } 16530 #endif /* BCM_TSN_SUPPORT */ 16531 16532 return rv; 16533 } 16534 16535 /* 16536 * Function: 16537 * bcm_esw_tsn_port_stat_sync_get 16538 * Description: 16539 * Get the specified hardware statistics (64-bit) from the device. 16540 * Parameters: 16541 * unit - (IN) Unit number 16542 * port - (IN) port number 16543 * stat - (IN) TSN statistics type (see tsn.h) 16544 * val - (OUT) 64-bit counter value. 16545 * Returns: 16546 * BCM_E_NONE - Success. 16547 * BCM_E_PARAM - Illegal parameter. 16548 * BCM_E_BADID - Illegal port number. 16549 * BCM_E_INTERNAL - Chip access failure. 16550 * BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip. 16551 * Notes: 16552 */ 16553 int 16554 bcm_esw_tsn_port_stat_sync_get( 16555 int unit, 16556 bcm_gport_t port, 16557 bcm_tsn_stat_t stat, 16558 uint64 *val) 16559 { 16560 int rv = BCM_E_UNAVAIL; 16561 16562 #if defined(BCM_TSN_SUPPORT) 16563 /* Read software accumulated counters */ 16564 if (soc_feature(unit, soc_feature_tsn)) { 16565 rv = bcmi_esw_tsn_stat_portcnt_get(unit, port, 1, stat, val); 16566 } 16567 #endif /* BCM_TSN_SUPPORT */ 16568 16569 return rv; 16570 } 16571 16572 /* 16573 * Function: 16574 * bcm_esw_tsn_port_stat_sync_get32 16575 * Description: 16576 * Get the specified hardware statistics (32-bit) from the device. 16577 * Parameters: 16578 * unit - (IN) Unit number 16579 * port - (IN) port number 16580 * stat - (IN) TSN statistics type (see tsn.h) 16581 * val - (OUT) 32-bit counter value. 16582 * Returns: 16583 * BCM_E_NONE - Success. 16584 * BCM_E_PARAM - Illegal parameter. 16585 * BCM_E_BADID - Illegal port number. 16586 * BCM_E_INTERNAL - Chip access failure. 16587 * BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip. 16588 * Notes: 16589 * Same as bcm_esw_tsn_port_stat_sync_get, except converts result to 32-bit. 16590 */ 16591 int 16592 bcm_esw_tsn_port_stat_sync_get32( 16593 int unit, 16594 bcm_gport_t port, 16595 bcm_tsn_stat_t stat, 16596 uint32 *val) 16597 { 16598 int rv = BCM_E_UNAVAIL; 16599 #if defined(BCM_TSN_SUPPORT) 16600 uint64 val64; 16601 #endif /* BCM_TSN_SUPPORT */ 16602 16603 /* Input parameter check. */ 16604 if (NULL == val) { 16605 return BCM_E_PARAM; 16606 } 16607 16608 #if defined(BCM_TSN_SUPPORT) 16609 if (soc_feature(unit, soc_feature_tsn)) { 16610 COMPILER_64_ZERO(val64); 16611 rv = bcm_esw_tsn_port_stat_sync_get(unit, port, stat, &val64); 16612 if (BCM_FAILURE(rv)) { 16613 return rv; 16614 } 16615 16616 COMPILER_64_TO_32_LO(*val, val64); 16617 } 16618 #endif /* BCM_TSN_SUPPORT */ 16619 16620 return rv; 16621 } 16622 16623 /* 16624 * Function: 16625 * bcm_esw_tsn_port_stat_sync_multi_get 16626 * Purpose: 16627 * Get multiple hardware statistics (64-bit) from the device. 16628 * Parameters: 16629 * unit - (IN) Unit number 16630 * port - (IN) port number 16631 * nstat - (IN) Number of elements in stat array 16632 * stat_arr - (IN) Array of TSN statistics types defined in bcm_tsn_stat_t 16633 * value_arr - (OUT) Collected statistics values 16634 * Returns: 16635 * BCM_E_NONE - Success. 16636 * BCM_E_PARAM - Illegal parameter. 16637 * BCM_E_BADID - Illegal port number. 16638 * BCM_E_INTERNAL - Chip access failure. 16639 * BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip. 16640 * Notes: 16641 */ 16642 int 16643 bcm_esw_tsn_port_stat_sync_multi_get( 16644 int unit, 16645 bcm_gport_t port, 16646 int nstat, 16647 bcm_tsn_stat_t *stat_arr, 16648 uint64 *value_arr) 16649 { 16650 int rv = BCM_E_UNAVAIL; 16651 #if defined(BCM_TSN_SUPPORT) 16652 int stix; 16653 #endif /* BCM_TSN_SUPPORT */ 16654 16655 /* Input parameter check. */ 16656 if (nstat <= 0) { 16657 return BCM_E_PARAM; 16658 } 16659 if ((NULL == stat_arr) || (NULL == value_arr)) { 16660 return BCM_E_PARAM; 16661 } 16662 16663 #if defined(BCM_TSN_SUPPORT) 16664 if (soc_feature(unit, soc_feature_tsn)) { 16665 for (stix = 0; stix < nstat; stix++) { 16666 rv = bcm_esw_tsn_port_stat_sync_get(unit, port, stat_arr[stix], 16667 &(value_arr[stix])); 16668 if (BCM_FAILURE(rv)) { 16669 return rv; 16670 } 16671 } 16672 } 16673 #endif /* BCM_TSN_SUPPORT */ 16674 16675 return rv; 16676 } 16677 16678 /* 16679 * Function: 16680 * bcm_esw_tsn_port_stat_sync_multi_get32 16681 * Purpose: 16682 * Get multiple hardware statistics (32-bit) from the device. 16683 * Parameters: 16684 * unit - (IN) Unit number 16685 * port - (IN) port number 16686 * nstat - (IN) Number of elements in stat array 16687 * stat_arr - (IN) Array of TSN statistics types defined in bcm_tsn_stat_t 16688 * value_arr - (OUT) Collected 32-bit statistics values 16689 * Returns: 16690 * BCM_E_NONE - Success. 16691 * BCM_E_PARAM - Illegal parameter. 16692 * BCM_E_BADID - Illegal port number. 16693 * BCM_E_INTERNAL - Chip access failure. 16694 * BCM_E_UNAVAIL - Counter/variable is not implemented on this current chip. 16695 * Notes: 16696 */ 16697 int 16698 bcm_esw_tsn_port_stat_sync_multi_get32( 16699 int unit, 16700 bcm_gport_t port, 16701 int nstat, 16702 bcm_tsn_stat_t *stat_arr, 16703 uint32 *value_arr) 16704 { 16705 int rv = BCM_E_UNAVAIL; 16706 #if defined(BCM_TSN_SUPPORT) 16707 int stix; 16708 #endif /* BCM_TSN_SUPPORT */ 16709 /* Input parameter check. */ 16710 if (nstat <= 0) { 16711 return BCM_E_PARAM; 16712 } 16713 if ((NULL == stat_arr) || (NULL == value_arr)) { 16714 return BCM_E_PARAM; 16715 } 16716 16717 #if defined(BCM_TSN_SUPPORT) 16718 if (soc_feature(unit, soc_feature_tsn)) { 16719 for (stix = 0; stix < nstat; stix++) { 16720 rv = bcm_esw_tsn_port_stat_sync_get32(unit, port, stat_arr[stix], 16721 &(value_arr[stix])); 16722 if (BCM_FAILURE(rv)) { 16723 return rv; 16724 } 16725 } 16726 16727 } 16728 #endif /* BCM_TSN_SUPPORT */ 16729 16730 return rv; 16731 } 16732 16733 /* 16734 * Function: 16735 * bcm_esw_tsn_stat_group_create 16736 * Description: 16737 * Create a TSN stat group by picking stat types (in an array) to be 16738 * included for counting 16739 * Parameters: 16740 * unit - (IN) unit number 16741 * group_type - (IN) TSN statistic group type 16742 * count - (IN) the number of elements in stat_arr 16743 * stat_arr - (IN) array for tsn stat types 16744 * id - (OUT) tsn statistic group id 16745 * 16746 * Return Value: 16747 * BCM_E_XXX 16748 * Notes: 16749 */ 16750 int 16751 bcm_esw_tsn_stat_group_create( 16752 int unit, 16753 bcm_tsn_stat_group_type_t group_type, 16754 int count, 16755 bcm_tsn_stat_t *stat_arr, 16756 bcm_tsn_stat_group_t *id) 16757 { 16758 #if defined(BCM_TSN_SUPPORT) 16759 if (soc_feature(unit, soc_feature_tsn)) { 16760 return bcmi_esw_tsn_stat_flowcnt_group_create(unit, group_type, count, 16761 stat_arr, id); 16762 } else 16763 #endif 16764 { 16765 return BCM_E_UNAVAIL; 16766 } 16767 } 16768 16769 /* 16770 * Function: 16771 * bcm_esw_tsn_stat_group_get 16772 * Description: 16773 * Get configuration of the TSN stat group 16774 * Parameters: 16775 * unit - (IN) unit number 16776 * id - (IN) TSN statistic group id 16777 * group_type - (OUT) TSN statistic group type 16778 * max - (IN) the size of stat_arr 16779 * stat_arr - (OUT) array for returned TSN stat types 16780 * count - (OUT) actual number of TSN stat types 16781 * 16782 * Return Value: 16783 * BCM_E_XXX 16784 * Notes: 16785 */ 16786 int 16787 bcm_esw_tsn_stat_group_get( 16788 int unit, 16789 bcm_tsn_stat_group_t id, 16790 bcm_tsn_stat_group_type_t *group_type, 16791 int max, 16792 bcm_tsn_stat_t *stat_arr, 16793 int *count) 16794 { 16795 #if defined(BCM_TSN_SUPPORT) 16796 if (soc_feature(unit, soc_feature_tsn)) { 16797 return bcmi_esw_tsn_stat_flowcnt_group_get(unit, id, group_type, max, 16798 stat_arr, count); 16799 } else 16800 #endif 16801 { 16802 return BCM_E_UNAVAIL; 16803 } 16804 } 16805 16806 /* 16807 * Function: 16808 * bcm_esw_tsn_stat_group_set 16809 * Description: 16810 * Set configuration of the TSN stat group 16811 * Parameters: 16812 * unit - (IN) unit number 16813 * id - (IN) TSN statistic group id 16814 * count - (IN) the number of elements in stat_arr 16815 * stat_arr - (IN) array for TSN stat types 16816 * 16817 * Return Value: 16818 * BCM_E_XXX 16819 * Notes: 16820 */ 16821 int 16822 bcm_esw_tsn_stat_group_set( 16823 int unit, 16824 bcm_tsn_stat_group_t id, 16825 int count, 16826 bcm_tsn_stat_t *stat_arr) 16827 { 16828 #if defined(BCM_TSN_SUPPORT) 16829 if (soc_feature(unit, soc_feature_tsn)) { 16830 return bcmi_esw_tsn_stat_flowcnt_group_set(unit, id, count, stat_arr); 16831 } else 16832 #endif 16833 { 16834 return BCM_E_UNAVAIL; 16835 } 16836 } 16837 16838 /* 16839 * Function: 16840 * bcm_esw_tsn_stat_group_destroy 16841 * Description: 16842 * Destroy a TSN stat group 16843 * Parameters: 16844 * unit - (IN) unit number 16845 * id - (IN) TSN statistic group id 16846 * 16847 * Return Value: 16848 * BCM_E_XXX 16849 * Notes: 16850 */ 16851 int 16852 bcm_esw_tsn_stat_group_destroy(int unit, bcm_tsn_stat_group_t id) 16853 { 16854 #if defined(BCM_TSN_SUPPORT) 16855 if (soc_feature(unit, soc_feature_tsn)) { 16856 return bcmi_esw_tsn_stat_flowcnt_group_destroy(unit, id); 16857 } else 16858 #endif 16859 { 16860 return BCM_E_UNAVAIL; 16861 } 16862 } 16863 16864 /* 16865 * Function: 16866 * bcm_esw_tsn_stat_group_traverse 16867 * Description: 16868 * Traverse TSN stat groups 16869 * Parameters: 16870 * unit - (IN) unit number 16871 * cb - (IN) User provided call back function 16872 * user_data - (IN) User provided data 16873 * 16874 * Return Value: 16875 * BCM_E_XXX 16876 * Notes: 16877 */ 16878 int 16879 bcm_esw_tsn_stat_group_traverse( 16880 int unit, 16881 bcm_tsn_stat_group_traverse_cb cb, 16882 void *user_data) 16883 { 16884 #if defined(BCM_TSN_SUPPORT) 16885 if (soc_feature(unit, soc_feature_tsn)) { 16886 return bcmi_esw_tsn_stat_flowcnt_group_traverse(unit, cb, user_data); 16887 } else 16888 #endif 16889 { 16890 return BCM_E_UNAVAIL; 16891 } 16892 } 16893 16894 /* 16895 * Function: 16896 * bcm_esw_tsn_sr_flow_stat_group_set 16897 * Description: 16898 * Attach ingress/egress stat group to this flow and enable counting for 16899 * the stat group. To disable counting for a specific group type, set 16900 * BCM_TSN_STAT_GROUP_INVALID as stat_group 16901 * Parameters: 16902 * unit - (IN) unit number 16903 * flow - (IN) SR flow 16904 * group_type - (IN) TSN statistic group type 16905 * stat_group - (IN) TSN statistic group 16906 * 16907 * Return Value: 16908 * BCM_E_XXX 16909 * Notes: 16910 */ 16911 int 16912 bcm_esw_tsn_sr_flow_stat_group_set( 16913 int unit, 16914 bcm_tsn_sr_flow_t flow, 16915 bcm_tsn_stat_group_type_t group_type, 16916 bcm_tsn_stat_group_t stat_group) 16917 { 16918 #if defined(BCM_TSN_SUPPORT) 16919 if (soc_feature(unit, soc_feature_tsn)) { 16920 return bcmi_esw_tsn_stat_flowcnt_flow_set(unit, flow, group_type, 16921 stat_group); 16922 } else 16923 #endif 16924 { 16925 return BCM_E_UNAVAIL; 16926 } 16927 } 16928 16929 /* 16930 * Function: 16931 * bcm_esw_tsn_sr_flow_stat_group_get 16932 * Description: 16933 * Get the stat group for this flow with specified group type 16934 * Parameters: 16935 * unit - (IN) unit number 16936 * flow - (IN) SR flow 16937 * group_type - (IN) TSN statistic group type 16938 * stat_group - (OUT)TSN statistic group 16939 * 16940 * Return Value: 16941 * BCM_E_XXX 16942 * Notes: 16943 */ 16944 int 16945 bcm_esw_tsn_sr_flow_stat_group_get( 16946 int unit, 16947 bcm_tsn_sr_flow_t flow, 16948 bcm_tsn_stat_group_type_t group_type, 16949 bcm_tsn_stat_group_t *stat_group) 16950 { 16951 #if defined(BCM_TSN_SUPPORT) 16952 if (soc_feature(unit, soc_feature_tsn)) { 16953 return bcmi_esw_tsn_stat_flowcnt_flow_get(unit, flow, group_type, 16954 stat_group); 16955 } else 16956 #endif 16957 { 16958 return BCM_E_UNAVAIL; 16959 } 16960 } 16961 16962 /* 16963 * Function: 16964 * bcm_esw_tsn_sr_flow_stat_set 16965 * Description: 16966 * Set 64-bit counter value for specified TSN statistic type 16967 * Parameters: 16968 * unit - (IN) unit number 16969 * flow - (IN) SR flow 16970 * stat - (IN) TSN stat types 16971 * val - (IN) counter value 16972 * 16973 * Return Value: 16974 * BCM_E_XXX 16975 * Notes: 16976 */ 16977 int 16978 bcm_esw_tsn_sr_flow_stat_set( 16979 int unit, 16980 bcm_tsn_sr_flow_t flow, 16981 bcm_tsn_stat_t stat, 16982 uint64 val) 16983 { 16984 #if defined(BCM_TSN_SR_SUPPORT) 16985 if (soc_feature(unit, soc_feature_tsn_sr)) { 16986 return bcmi_esw_tsn_stat_flowcnt_set( 16987 unit, flow, 1, &stat, &val); 16988 } else 16989 #endif 16990 { 16991 return BCM_E_UNAVAIL; 16992 } 16993 } 16994 16995 /* 16996 * Function: 16997 * bcm_esw_tsn_sr_flow_stat_set32 16998 * Description: 16999 * Set lower 32-bit counter value for specified TSN statistic type 17000 * Parameters: 17001 * unit - (IN) unit number 17002 * flow - (IN) SR flow 17003 * stat - (IN) TSN stat types 17004 * val - (IN) counter value 17005 * 17006 * Return Value: 17007 * BCM_E_XXX 17008 * Notes: 17009 */ 17010 int 17011 bcm_esw_tsn_sr_flow_stat_set32( 17012 int unit, 17013 bcm_tsn_sr_flow_t flow, 17014 bcm_tsn_stat_t stat, 17015 uint32 val) 17016 { 17017 #if defined(BCM_TSN_SR_SUPPORT) 17018 if (soc_feature(unit, soc_feature_tsn_sr)) { 17019 uint64 value64; 17020 17021 COMPILER_64_SET(value64, 0, val); 17022 return bcmi_esw_tsn_stat_flowcnt_set( 17023 unit, flow, 1, &stat, &value64); 17024 } else 17025 #endif 17026 { 17027 return BCM_E_UNAVAIL; 17028 } 17029 } 17030 17031 /* 17032 * Function: 17033 * bcm_esw_tsn_sr_flow_stat_get 17034 * Description: 17035 * Get 64-bit counter value for specified TSN statistic type 17036 * Parameters: 17037 * unit - (IN) unit number 17038 * flow - (IN) SR flow 17039 * stat - (IN) TSN stat types 17040 * val - (OUT)counter value 17041 * 17042 * Return Value: 17043 * BCM_E_XXX 17044 * Notes: 17045 */ 17046 int 17047 bcm_esw_tsn_sr_flow_stat_get( 17048 int unit, 17049 bcm_tsn_sr_flow_t flow, 17050 bcm_tsn_stat_t stat, 17051 uint64 *val) 17052 { 17053 #if defined(BCM_TSN_SR_SUPPORT) 17054 if (soc_feature(unit, soc_feature_tsn_sr)) { 17055 return bcmi_esw_tsn_stat_flowcnt_get( 17056 unit, flow, 0, 1, &stat, val); 17057 } else 17058 #endif 17059 { 17060 return BCM_E_UNAVAIL; 17061 } 17062 } 17063 17064 /* 17065 * Function: 17066 * bcm_esw_tsn_sr_flow_stat_get32 17067 * Description: 17068 * Get lower 32-bit counter value for specified TSN statistic type 17069 * Parameters: 17070 * unit - (IN) unit number 17071 * flow - (IN) SR flow 17072 * stat - (IN) TSN stat types 17073 * val - (OUT)counter value 17074 * 17075 * Return Value: 17076 * BCM_E_XXX 17077 * Notes: 17078 */ 17079 int 17080 bcm_esw_tsn_sr_flow_stat_get32( 17081 int unit, 17082 bcm_tsn_sr_flow_t flow, 17083 bcm_tsn_stat_t stat, 17084 uint32 *val) 17085 { 17086 #if defined(BCM_TSN_SR_SUPPORT) 17087 if (soc_feature(unit, soc_feature_tsn_sr)) { 17088 uint64 value64; 17089 int rv; 17090 17091 if (NULL == val) { 17092 return BCM_E_PARAM; 17093 } 17094 rv = bcmi_esw_tsn_stat_flowcnt_get( 17095 unit, flow, 0, 1, &stat, &value64); 17096 if (BCM_SUCCESS(rv)) { 17097 *val = COMPILER_64_LO(value64); 17098 } 17099 return rv; 17100 } else 17101 #endif 17102 { 17103 return BCM_E_UNAVAIL; 17104 } 17105 } 17106 17107 /* 17108 * Function: 17109 * bcm_esw_tsn_sr_flow_stat_multi_set 17110 * Description: 17111 * Set 64-bit counter value for multiple TSN statistic types. 17112 * Parameters: 17113 * unit - (IN) unit number 17114 * flow - (IN) SR flow 17115 * nstat - (IN) number of element in stat_arr and value_arr 17116 * stat_arr - (IN) TSN stat types 17117 * value_arr - (IN) counter value 17118 * 17119 * Return Value: 17120 * BCM_E_XXX 17121 * Notes: 17122 */ 17123 int 17124 bcm_esw_tsn_sr_flow_stat_multi_set( 17125 int unit, 17126 bcm_tsn_sr_flow_t flow, 17127 int nstat, 17128 bcm_tsn_stat_t *stat_arr, 17129 uint64 *value_arr) 17130 { 17131 #if defined(BCM_TSN_SR_SUPPORT) 17132 if (soc_feature(unit, soc_feature_tsn_sr)) { 17133 return bcmi_esw_tsn_stat_flowcnt_set( 17134 unit, flow, nstat, stat_arr, value_arr); 17135 } else 17136 #endif 17137 { 17138 return BCM_E_UNAVAIL; 17139 } 17140 } 17141 17142 /* 17143 * Function: 17144 * bcm_esw_tsn_sr_flow_stat_multi_set32 17145 * Description: 17146 * Set lower 32-bit counter value for multiple TSN statistic types. 17147 * Parameters: 17148 * unit - (IN) unit number 17149 * flow - (IN) SR flow 17150 * nstat - (IN) number of element in stat_arr and value_arr 17151 * stat_arr - (IN) TSN stat types 17152 * value_arr - (IN) counter value 17153 * 17154 * Return Value: 17155 * BCM_E_XXX 17156 * Notes: 17157 */ 17158 int 17159 bcm_esw_tsn_sr_flow_stat_multi_set32( 17160 int unit, 17161 bcm_tsn_sr_flow_t flow, 17162 int nstat, 17163 bcm_tsn_stat_t *stat_arr, 17164 uint32 *value_arr) 17165 { 17166 #if defined(BCM_TSN_SR_SUPPORT) 17167 if (soc_feature(unit, soc_feature_tsn_sr)) { 17168 uint64 *value64_arr = NULL; 17169 int i, rv; 17170 17171 if (NULL == value_arr) { 17172 return BCM_E_PARAM; 17173 } 17174 value64_arr = sal_alloc(nstat * sizeof(uint64), "value64_arr"); 17175 if (NULL == value64_arr) { 17176 return BCM_E_MEMORY; 17177 } 17178 for (i = 0; i < nstat ; i++) { 17179 COMPILER_64_SET(value64_arr[i], 0, value_arr[i]); 17180 } 17181 rv = bcmi_esw_tsn_stat_flowcnt_set( 17182 unit, flow, nstat, stat_arr, value64_arr); 17183 sal_free(value64_arr); 17184 return rv; 17185 } else 17186 #endif 17187 { 17188 return BCM_E_UNAVAIL; 17189 } 17190 } 17191 17192 /* 17193 * Function: 17194 * bcm_esw_tsn_sr_flow_stat_multi_get 17195 * Description: 17196 * Get 64-bit counter value for multiple TSN statistic types. 17197 * Parameters: 17198 * unit - (IN) unit number 17199 * flow - (IN) SR flow 17200 * nstat - (IN) size of stat_arr and value_arr 17201 * stat_arr - (IN) TSN stat types 17202 * value_arr - (OUT)counter value 17203 * 17204 * Return Value: 17205 * BCM_E_XXX 17206 * Notes: 17207 */ 17208 int 17209 bcm_esw_tsn_sr_flow_stat_multi_get( 17210 int unit, 17211 bcm_tsn_sr_flow_t flow, 17212 int nstat, 17213 bcm_tsn_stat_t *stat_arr, 17214 uint64 *value_arr) 17215 { 17216 #if defined(BCM_TSN_SR_SUPPORT) 17217 if (soc_feature(unit, soc_feature_tsn_sr)) { 17218 return bcmi_esw_tsn_stat_flowcnt_get( 17219 unit, flow, 0, nstat, stat_arr, value_arr); 17220 } else 17221 #endif 17222 { 17223 return BCM_E_UNAVAIL; 17224 } 17225 } 17226 17227 /* 17228 * Function: 17229 * bcm_esw_tsn_sr_flow_stat_multi_get32 17230 * Description: 17231 * Get lower 32-bit counter value for multiple TSN statistic types. 17232 * Parameters: 17233 * unit - (IN) unit number 17234 * flow - (IN) SR flow 17235 * nstat - (IN) size of stat_arr and value_arr 17236 * stat_arr - (IN) TSN stat types 17237 * value_arr - (OUT)counter value 17238 * 17239 * Return Value: 17240 * BCM_E_XXX 17241 * Notes: 17242 */ 17243 int 17244 bcm_esw_tsn_sr_flow_stat_multi_get32( 17245 int unit, 17246 bcm_tsn_sr_flow_t flow, 17247 int nstat, 17248 bcm_tsn_stat_t *stat_arr, 17249 uint32 *value_arr) 17250 { 17251 #if defined(BCM_TSN_SR_SUPPORT) 17252 if (soc_feature(unit, soc_feature_tsn_sr)) { 17253 uint64 *value64_arr = NULL; 17254 int i, rv; 17255 17256 if (NULL == value_arr) { 17257 return BCM_E_PARAM; 17258 } 17259 value64_arr = sal_alloc(nstat * sizeof(uint64), "value64_arr"); 17260 if (NULL == value64_arr) { 17261 return BCM_E_MEMORY; 17262 } 17263 rv = bcmi_esw_tsn_stat_flowcnt_get( 17264 unit, flow, 0, nstat, stat_arr, value64_arr); 17265 if (BCM_SUCCESS(rv)) { 17266 for (i = 0; i < nstat ; i++) { 17267 value_arr[i] = COMPILER_64_LO(value64_arr[i]); 17268 } 17269 } 17270 sal_free(value64_arr); 17271 return rv; 17272 } else 17273 #endif 17274 { 17275 return BCM_E_UNAVAIL; 17276 } 17277 } 17278 17279 /* 17280 * Function: 17281 * bcm_esw_tsn_sr_flow_stat_sync_get 17282 * Description: 17283 * Get the specified hardware statistics (64-bit) from the device. 17284 * Parameters: 17285 * unit - (IN) unit number 17286 * flow - (IN) SR flow 17287 * stat - (IN) TSN stat types 17288 * val - (OUT)counter value 17289 * 17290 * Return Value: 17291 * BCM_E_XXX 17292 * Notes: 17293 */ 17294 int 17295 bcm_esw_tsn_sr_flow_stat_sync_get( 17296 int unit, 17297 bcm_tsn_sr_flow_t flow, 17298 bcm_tsn_stat_t stat, 17299 uint64 *val) 17300 { 17301 #if defined(BCM_TSN_SR_SUPPORT) 17302 if (soc_feature(unit, soc_feature_tsn_sr)) { 17303 return bcmi_esw_tsn_stat_flowcnt_get( 17304 unit, flow, 1, 1, &stat, val); 17305 } else 17306 #endif 17307 { 17308 return BCM_E_UNAVAIL; 17309 } 17310 } 17311 17312 /* 17313 * Function: 17314 * bcm_esw_tsn_sr_flow_stat_sync_get32 17315 * Description: 17316 * Get the specified hardware statistics (32-bit) from the device. 17317 * Parameters: 17318 * unit - (IN) unit number 17319 * flow - (IN) SR flow 17320 * stat - (IN) TSN stat types 17321 * val - (OUT)counter value 17322 * 17323 * Return Value: 17324 * BCM_E_XXX 17325 * Notes: 17326 */ 17327 int 17328 bcm_esw_tsn_sr_flow_stat_sync_get32( 17329 int unit, 17330 bcm_tsn_sr_flow_t flow, 17331 bcm_tsn_stat_t stat, 17332 uint32 *val) 17333 { 17334 #if defined(BCM_TSN_SR_SUPPORT) 17335 if (soc_feature(unit, soc_feature_tsn_sr)) { 17336 uint64 value64; 17337 int rv; 17338 17339 if (NULL == val) { 17340 return BCM_E_PARAM; 17341 } 17342 rv = bcmi_esw_tsn_stat_flowcnt_get( 17343 unit, flow, 1, 1, &stat, &value64); 17344 if (BCM_SUCCESS(rv)) { 17345 *val = COMPILER_64_LO(value64); 17346 } 17347 return rv; 17348 } else 17349 #endif 17350 { 17351 return BCM_E_UNAVAIL; 17352 } 17353 } 17354 17355 /* 17356 * Function: 17357 * bcm_esw_tsn_sr_flow_stat_sync_multi_get 17358 * Description: 17359 * Get multiple hardware statistics (64-bit) from the device 17360 * Parameters: 17361 * unit - (IN) unit number 17362 * flow - (IN) SR flow 17363 * nstat - (IN) size of stat_arr and value_arr 17364 * stat_arr - (IN) TSN stat types 17365 * value_arr - (OUT)counter value 17366 * 17367 * Return Value: 17368 * BCM_E_XXX 17369 * Notes: 17370 */ 17371 int 17372 bcm_esw_tsn_sr_flow_stat_sync_multi_get( 17373 int unit, 17374 bcm_tsn_sr_flow_t flow, 17375 int nstat, 17376 bcm_tsn_stat_t *stat_arr, 17377 uint64 *value_arr) 17378 { 17379 #if defined(BCM_TSN_SR_SUPPORT) 17380 if (soc_feature(unit, soc_feature_tsn_sr)) { 17381 return bcmi_esw_tsn_stat_flowcnt_get( 17382 unit, flow, 1, nstat, stat_arr, value_arr); 17383 } else 17384 #endif 17385 { 17386 return BCM_E_UNAVAIL; 17387 } 17388 } 17389 17390 /* 17391 * Function: 17392 * bcm_esw_tsn_sr_flow_stat_sync_multi_get32 17393 * Description: 17394 * Get multiple hardware statistics (32-bit) from the device 17395 * Parameters: 17396 * unit - (IN) unit number 17397 * flow - (IN) SR flow 17398 * nstat - (IN) size of stat_arr and value_arr 17399 * stat_arr - (IN) TSN stat types 17400 * value_arr - (OUT)counter value 17401 * 17402 * Return Value: 17403 * BCM_E_XXX 17404 * Notes: 17405 */ 17406 int 17407 bcm_esw_tsn_sr_flow_stat_sync_multi_get32( 17408 int unit, 17409 bcm_tsn_sr_flow_t flow, 17410 int nstat, 17411 bcm_tsn_stat_t *stat_arr, 17412 uint32 *value_arr) 17413 { 17414 #if defined(BCM_TSN_SR_SUPPORT) 17415 if (soc_feature(unit, soc_feature_tsn_sr)) { 17416 uint64 *value64_arr = NULL; 17417 int i, rv; 17418 17419 if (NULL == value_arr) { 17420 return BCM_E_PARAM; 17421 } 17422 value64_arr = sal_alloc(nstat * sizeof(uint64), "value64_arr"); 17423 if (NULL == value64_arr) { 17424 return BCM_E_MEMORY; 17425 } 17426 rv = bcmi_esw_tsn_stat_flowcnt_get( 17427 unit, flow, 1, nstat, stat_arr, value64_arr); 17428 if (BCM_SUCCESS(rv)) { 17429 for (i = 0; i < nstat ; i++) { 17430 value_arr[i] = COMPILER_64_LO(value64_arr[i]); 17431 } 17432 } 17433 sal_free(value64_arr); 17434 return rv; 17435 } else 17436 #endif 17437 { 17438 return BCM_E_UNAVAIL; 17439 } 17440 } 17441 17442 /* 17443 * Function: 17444 * bcm_esw_tsn_stat_threshold_set 17445 * Purpose: 17446 * Configure threshold for a specific stat type on 17447 * a specific source 17448 * Parameters: 17449 * unit - (IN) Unit number 17450 * source - (IN) Stat source for TSN stat threshold check 17451 * stat - (IN) TSN statistics type (see tsn.h) 17452 * config - (IN) TSN stat threshold configuration structure 17453 * Returns: 17454 * BCM_E_XXX 17455 */ 17456 int 17457 bcm_esw_tsn_stat_threshold_set( 17458 int unit, 17459 bcm_tsn_stat_threshold_source_t source, 17460 bcm_tsn_stat_t stat, 17461 bcm_tsn_stat_threshold_config_t *config) 17462 { 17463 int rv = BCM_E_UNAVAIL; 17464 17465 /* Input parameter check */ 17466 if (NULL == config) { 17467 return BCM_E_PARAM; 17468 } 17469 17470 #if defined(BCM_TSN_SUPPORT) 17471 if (soc_feature(unit, soc_feature_tsn)) { 17472 rv = bcmi_esw_tsn_stat_threshold_set(unit, source, stat, config); 17473 } 17474 #endif /* BCM_TSN_SUPPORT */ 17475 17476 return rv; 17477 } 17478 17479 /* 17480 * Function: 17481 * bcm_esw_tsn_stat_threshold_get 17482 * Purpose: 17483 * Get the threshold configuration for a specific stat type on 17484 * a specific source 17485 * Parameters: 17486 * unit - (IN) Unit number 17487 * source - (IN) Stat source for TSN stat threshold check 17488 * stat - (IN) TSN statistics type (see tsn.h) 17489 * config - (OUT) TSN stat threshold configuration structure 17490 * Returns: 17491 * BCM_E_XXX 17492 */ 17493 int 17494 bcm_esw_tsn_stat_threshold_get( 17495 int unit, 17496 bcm_tsn_stat_threshold_source_t source, 17497 bcm_tsn_stat_t stat, 17498 bcm_tsn_stat_threshold_config_t *config) 17499 { 17500 int rv = BCM_E_UNAVAIL; 17501 17502 /* Input parameter check */ 17503 if (NULL == config) { 17504 return BCM_E_PARAM; 17505 } 17506 17507 #if defined(BCM_TSN_SUPPORT) 17508 if (soc_feature(unit, soc_feature_tsn)) { 17509 rv = bcmi_esw_tsn_stat_threshold_get(unit, source, stat, config); 17510 } 17511 #endif /* BCM_TSN_SUPPORT */ 17512 17513 return rv; 17514 } 17515 17516 /* 17517 * Function: 17518 * bcm_esw_tsn_event_register 17519 * Purpose: 17520 * The callback function registration to handle the TSN event on 17521 * specified event source. 17522 * Parameters: 17523 * unit - (IN) unit number 17524 * event - (IN) TSN event 17525 * src - (IN) source triggeres the event 17526 * cb - (IN) callback function 17527 * user_data - (IN) Pointer to user data to supply in the callback. 17528 * Returns: 17529 * BCM_E_XXX 17530 * Notes: 17531 */ 17532 int 17533 bcm_esw_tsn_event_register( 17534 int unit, 17535 bcm_tsn_event_type_t event, 17536 bcm_tsn_event_source_t *src, 17537 bcm_tsn_event_cb cb, 17538 void *user_data) 17539 { 17540 #if defined(BCM_TSN_SUPPORT) 17541 if (soc_feature(unit, soc_feature_tsn)) { 17542 return bcmi_esw_tsn_event_register(unit, event, src, cb, user_data); 17543 } 17544 #endif /* BCM_TSN_SUPPORT */ 17545 return BCM_E_UNAVAIL; 17546 } 17547 17548 /* 17549 * Function: 17550 * bcm_esw_tsn_event_unregister 17551 * Purpose: 17552 * The callback function unregistration of the TSN event on 17553 * specified event source. 17554 * Parameters: 17555 * unit - (IN) unit number 17556 * event - (IN) TSN event 17557 * src - (IN) source triggeres the event 17558 * cb - (IN) callback function 17559 * Returns: 17560 * BCM_E_XXX 17561 * Notes: 17562 */ 17563 int 17564 bcm_esw_tsn_event_unregister( 17565 int unit, 17566 bcm_tsn_event_type_t event, 17567 bcm_tsn_event_source_t *src, 17568 bcm_tsn_event_cb cb) 17569 { 17570 #if defined(BCM_TSN_SUPPORT) 17571 if (soc_feature(unit, soc_feature_tsn)) { 17572 return bcmi_esw_tsn_event_unregister(unit, event, src, cb); 17573 } 17574 #endif /* BCM_TSN_SUPPORT */ 17575 return BCM_E_UNAVAIL; 17576 } 17577 17578 /* 17579 * Function: 17580 * bcm_esw_tsn_event_notification_traverse 17581 * Purpose: 17582 * Traverse all registered event notification callback 17583 * Parameters: 17584 * unit - (IN) unit number 17585 * cb - (IN) callback function 17586 * user_data - (IN) Pointer to user data to supply in the callback 17587 * Returns: 17588 * BCM_E_XXX 17589 * Notes: 17590 */ 17591 int 17592 bcm_esw_tsn_event_notification_traverse( 17593 int unit, 17594 bcm_tsn_event_notification_traverse_cb cb, 17595 void *user_data) 17596 { 17597 #if defined(BCM_TSN_SUPPORT) 17598 if (soc_feature(unit, soc_feature_tsn)) { 17599 return bcmi_esw_tsn_event_notification_traverse(unit, cb, user_data); 17600 } 17601 #endif /* BCM_TSN_SUPPORT */ 17602 return BCM_E_UNAVAIL; 17603 } 17604 17605 /* 17606 * Function: 17607 * bcm_esw_tsn_mtu_profile_create 17608 * Purpose: 17609 * Create mtu profile with the config pointer 17610 * and return the assigned profile id. 17611 * Parameters: 17612 * unit - (IN) Unit number 17613 * type - (IN) Indicates ingress or egress mtu profile 17614 * config - (IN) configuration of the mtu profile 17615 * mtu_profile_id - (OUT) profile id 17616 * Returns: 17617 * BCM_E_xxx 17618 */ 17619 int 17620 bcm_esw_tsn_mtu_profile_create( 17621 int unit, 17622 bcm_tsn_mtu_profile_type_t type, 17623 bcm_tsn_mtu_config_t *config, 17624 int *mtu_profile_id) 17625 { 17626 if (config == NULL || mtu_profile_id == NULL) { 17627 return BCM_E_PARAM; 17628 } 17629 #if defined(BCM_TSN_SUPPORT) 17630 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 17631 return bcmi_esw_tsn_mtu_profile_create(unit, type, config, 17632 mtu_profile_id); 17633 } 17634 #endif /* BCM_TSN_SUPPORT */ 17635 return BCM_E_UNAVAIL; 17636 } 17637 17638 /* 17639 * Function: 17640 * bcm_esw_tsn_mtu_profile_get 17641 * Purpose: 17642 * Get mtu profile configuration 17643 * with the profile id. 17644 * Parameters: 17645 * unit - (IN) Unit number 17646 * mtu_profile_id - (IN) Indicated the mtu profile entry 17647 * type - (OUT) Indicates ingress or egress mtu profile 17648 * config - (OUT) Configuration of the mtu profile 17649 * Returns: 17650 * BCM_E_xxx 17651 */ 17652 int 17653 bcm_esw_tsn_mtu_profile_get( 17654 int unit, 17655 int mtu_profile_id, 17656 bcm_tsn_mtu_profile_type_t *type, 17657 bcm_tsn_mtu_config_t *config) 17658 { 17659 if (config == NULL || type == NULL) { 17660 return BCM_E_PARAM; 17661 } 17662 #if defined(BCM_TSN_SUPPORT) 17663 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 17664 return bcmi_esw_tsn_mtu_profile_get(unit, mtu_profile_id, 17665 type, config); 17666 } 17667 #endif /* BCM_TSN_SUPPORT */ 17668 return BCM_E_UNAVAIL; 17669 17670 } 17671 17672 /* 17673 * Function: 17674 * bcm_esw_tsn_mtu_profile_set 17675 * Purpose: 17676 * Set mtu profile with the profile id 17677 * and config parameter. 17678 * Parameters: 17679 * unit - (IN) Unit number 17680 * mtu_profile_id - (IN) Indicated the mtu profile entry 17681 * config - (IN) Configuration of the mtu profile 17682 * Returns: 17683 * BCM_E_xxx 17684 */ 17685 int 17686 bcm_esw_tsn_mtu_profile_set( 17687 int unit, 17688 int mtu_profile_id, 17689 bcm_tsn_mtu_config_t *config) 17690 { 17691 if (config == NULL) { 17692 return BCM_E_PARAM; 17693 } 17694 #if defined(BCM_TSN_SUPPORT) 17695 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 17696 return bcmi_esw_tsn_mtu_profile_set(unit, mtu_profile_id, config); 17697 } 17698 #endif /* BCM_TSN_SUPPORT */ 17699 return BCM_E_UNAVAIL; 17700 } 17701 17702 /* 17703 * Function: 17704 * bcm_esw_tsn_mtu_profile_destroy 17705 * Purpose: 17706 * Clear the mtu profile with the profile id 17707 * Parameters: 17708 * unit - (IN) Unit number 17709 * mtu_profile_id - (IN) Indicated the mtu profile entry 17710 * Returns: 17711 * BCM_E_xxx 17712 */ 17713 int 17714 bcm_esw_tsn_mtu_profile_destroy( 17715 int unit, 17716 int mtu_profile_id) 17717 { 17718 #if defined(BCM_TSN_SUPPORT) 17719 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 17720 return bcmi_esw_tsn_mtu_profile_destroy(unit, mtu_profile_id); 17721 } 17722 #endif /* BCM_TSN_SUPPORT */ 17723 return BCM_E_UNAVAIL; 17724 } 17725 17726 /* 17727 * Function: 17728 * bcm_tsn_mtu_profile_traverse 17729 * Purpose: 17730 * Traverse the created match config. 17731 * Parameters: 17732 * unit - (IN) Unit number 17733 * cb - (IN) Traverse call back function 17734 * user_data - (IN) User data 17735 * Returns: 17736 * BCM_E_xxx 17737 */ 17738 int 17739 bcm_esw_tsn_mtu_profile_traverse( 17740 int unit, 17741 bcm_tsn_mtu_profile_traverse_cb cb, 17742 void *user_data) 17743 { 17744 if (user_data == NULL || cb == NULL) { 17745 return BCM_E_PARAM; 17746 } 17747 #if defined(BCM_TSN_SUPPORT) 17748 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 17749 return bcmi_esw_tsn_mtu_profile_traverse(unit, cb, user_data); 17750 } 17751 #endif /* BCM_TSN_SUPPORT */ 17752 return BCM_E_UNAVAIL; 17753 } 17754 17755 /* 17756 * Function: 17757 * bcm_esw_tsn_ingress_mtu_config_set 17758 * Purpose: 17759 * Set ingress mtu profile source priority 17760 * with the config parameter. 17761 * Parameters: 17762 * unit - (IN) Unit number 17763 * config - (IN) Configuration of the mtu profile 17764 * Returns: 17765 * BCM_E_xxx 17766 */ 17767 int 17768 bcm_esw_tsn_ingress_mtu_config_set( 17769 int unit, 17770 bcm_tsn_ingress_mtu_config_t *config) 17771 { 17772 if (config == NULL) { 17773 return BCM_E_PARAM; 17774 } 17775 #if defined(BCM_TSN_SUPPORT) 17776 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 17777 return bcmi_esw_tsn_ingress_mtu_config_set(unit, config); 17778 } 17779 #endif /* BCM_TSN_SUPPORT */ 17780 return BCM_E_UNAVAIL; 17781 } 17782 17783 /* 17784 * Function: 17785 * bcm_esw_tsn_ingress_mtu_config_get 17786 * Purpose: 17787 * Get ingress mtu profile source priority 17788 * with the config parameter. 17789 * Parameters: 17790 * unit - (IN) Unit number 17791 * config - (OUT) Configuration of the mtu profile 17792 * Returns: 17793 * BCM_E_xxx 17794 */ 17795 int 17796 bcm_esw_tsn_ingress_mtu_config_get( 17797 int unit, 17798 bcm_tsn_ingress_mtu_config_t *config) 17799 { 17800 if (config == NULL) { 17801 return BCM_E_PARAM; 17802 } 17803 #if defined(BCM_TSN_SUPPORT) 17804 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 17805 return bcmi_esw_tsn_ingress_mtu_config_get(unit, config); 17806 } 17807 #endif /* BCM_TSN_SUPPORT */ 17808 return BCM_E_UNAVAIL; 17809 } 17810 /* 17811 * Function: 17812 * bcm_esw_tsn_stu_profile_create 17813 * Purpose: 17814 * Create stu profile with the config pointer 17815 * and return the assigned profile id. 17816 * Parameters: 17817 * unit - (IN) Unit number 17818 * type - (IN) Indicates ingress or egress stu profile 17819 * config - (IN) configuration of the stu profile 17820 * stu_profile_id - (OUT) profile id 17821 * Returns: 17822 * BCM_E_xxx 17823 */ 17824 int 17825 bcm_esw_tsn_stu_profile_create( 17826 int unit, 17827 bcm_tsn_stu_profile_type_t type, 17828 bcm_tsn_stu_config_t *config, 17829 int *stu_profile_id) 17830 { 17831 if (config == NULL || stu_profile_id == NULL) { 17832 return BCM_E_PARAM; 17833 } 17834 #if defined(BCM_TSN_SUPPORT) 17835 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 17836 return bcmi_esw_tsn_stu_profile_create(unit, type, config, 17837 stu_profile_id); 17838 } 17839 #endif /* BCM_TSN_SUPPORT */ 17840 return BCM_E_UNAVAIL; 17841 } 17842 17843 /* 17844 * Function: 17845 * bcm_esw_tsn_stu_profile_get 17846 * Purpose: 17847 * Get stu profile configuration 17848 * with the profile id. 17849 * Parameters: 17850 * unit - (IN) Unit number 17851 * stu_profile_id - (IN) Indicated the stu profile entry 17852 * type - (OUT) Indicates ingress or egress stu profile 17853 * config - (OUT) Configuration of the stu profile 17854 * Returns: 17855 * BCM_E_xxx 17856 */ 17857 int 17858 bcm_esw_tsn_stu_profile_get( 17859 int unit, 17860 int stu_profile_id, 17861 bcm_tsn_stu_profile_type_t *type, 17862 bcm_tsn_stu_config_t *config) 17863 { 17864 if (config == NULL || type == NULL) { 17865 return BCM_E_PARAM; 17866 } 17867 #if defined(BCM_TSN_SUPPORT) 17868 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 17869 return bcmi_esw_tsn_stu_profile_get(unit, stu_profile_id, 17870 type, config); 17871 } 17872 #endif /* BCM_TSN_SUPPORT */ 17873 return BCM_E_UNAVAIL; 17874 17875 } 17876 17877 /* 17878 * Function: 17879 * bcm_esw_tsn_stu_profile_set 17880 * Purpose: 17881 * Set stu profile with the profile id 17882 * and config parameter. 17883 * Parameters: 17884 * unit - (IN) Unit number 17885 * stu_profile_id - (IN) Indicated the stu profile entry 17886 * config - (IN) Configuration of the stu profile 17887 * Returns: 17888 * BCM_E_xxx 17889 */ 17890 int 17891 bcm_esw_tsn_stu_profile_set( 17892 int unit, 17893 int stu_profile_id, 17894 bcm_tsn_stu_config_t *config) 17895 { 17896 if (config == NULL) { 17897 return BCM_E_PARAM; 17898 } 17899 #if defined(BCM_TSN_SUPPORT) 17900 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 17901 return bcmi_esw_tsn_stu_profile_set(unit, stu_profile_id, config); 17902 } 17903 #endif /* BCM_TSN_SUPPORT */ 17904 return BCM_E_UNAVAIL; 17905 } 17906 17907 /* 17908 * Function: 17909 * bcm_esw_tsn_stu_profile_destroy 17910 * Purpose: 17911 * Clear the stu profile with the profile id 17912 * Parameters: 17913 * unit - (IN) Unit number 17914 * stu_profile_id - (IN) Indicated the stu profile entry 17915 * Returns: 17916 * BCM_E_xxx 17917 */ 17918 int 17919 bcm_esw_tsn_stu_profile_destroy( 17920 int unit, 17921 int stu_profile_id) 17922 { 17923 #if defined(BCM_TSN_SUPPORT) 17924 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 17925 return bcmi_esw_tsn_stu_profile_destroy(unit, stu_profile_id); 17926 } 17927 #endif /* BCM_TSN_SUPPORT */ 17928 return BCM_E_UNAVAIL; 17929 } 17930 17931 /* 17932 * Function: 17933 * bcm_tsn_stu_profile_traverse 17934 * Purpose: 17935 * Traverse the created match config. 17936 * Parameters: 17937 * unit - (IN) Unit number 17938 * cb - (IN) Traverse call back function 17939 * user_data - (IN) User data 17940 * Returns: 17941 * BCM_E_xxx 17942 */ 17943 int 17944 bcm_esw_tsn_stu_profile_traverse( 17945 int unit, 17946 bcm_tsn_stu_profile_traverse_cb cb, 17947 void *user_data) 17948 { 17949 if (user_data == NULL || cb == NULL) { 17950 return BCM_E_PARAM; 17951 } 17952 #if defined(BCM_TSN_SUPPORT) 17953 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 17954 return bcmi_esw_tsn_stu_profile_traverse(unit, cb, user_data); 17955 } 17956 #endif /* BCM_TSN_SUPPORT */ 17957 return BCM_E_UNAVAIL; 17958 } 17959 17960 /* 17961 * Function: 17962 * bcm_esw_tsn_ingress_stu_config_set 17963 * Purpose: 17964 * Set ingress stu profile source priority 17965 * with the config parameter. 17966 * Parameters: 17967 * unit - (IN) Unit number 17968 * config - (IN) Configuration of the stu profile 17969 * Returns: 17970 * BCM_E_xxx 17971 */ 17972 int 17973 bcm_esw_tsn_ingress_stu_config_set( 17974 int unit, 17975 bcm_tsn_ingress_stu_config_t *config) 17976 { 17977 if (config == NULL) { 17978 return BCM_E_PARAM; 17979 } 17980 #if defined(BCM_TSN_SUPPORT) 17981 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 17982 return bcmi_esw_tsn_ingress_stu_config_set(unit, config); 17983 } 17984 #endif /* BCM_TSN_SUPPORT */ 17985 return BCM_E_UNAVAIL; 17986 } 17987 17988 /* 17989 * Function: 17990 * bcm_esw_tsn_ingress_stu_config_get 17991 * Purpose: 17992 * Get ingress stu profile source priority 17993 * with the config parameter. 17994 * Parameters: 17995 * unit - (IN) Unit number 17996 * config - (OUT) Configuration of the stu profile 17997 * Returns: 17998 * BCM_E_xxx 17999 */ 18000 int 18001 bcm_esw_tsn_ingress_stu_config_get( 18002 int unit, 18003 bcm_tsn_ingress_stu_config_t *config) 18004 { 18005 if (config == NULL) { 18006 return BCM_E_PARAM; 18007 } 18008 #if defined(BCM_TSN_SUPPORT) 18009 if (soc_feature(unit, soc_feature_tsn_mtu_stu)) { 18010 return bcmi_esw_tsn_ingress_stu_config_get(unit, config); 18011 } 18012 #endif /* BCM_TSN_SUPPORT */ 18013 return BCM_E_UNAVAIL; 18014 } 18015