oam.c (851668B)
1 /* 2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 3 * 4 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 5 * 6 * File: 7 * oam.c 8 * 9 * Purpose: 10 * OAM implementation for Triumph3 family of devices. 11 */ 12 #include <shared/bsl.h> 13 14 #include <sal/core/libc.h> 15 #include <soc/defs.h> 16 #include <soc/drv.h> 17 #include <soc/scache.h> 18 #include <soc/profile_mem.h> 19 #include <soc/hash.h> 20 #include <soc/l3x.h> 21 #include <soc/katana2.h> 22 #include <soc/ism_hash.h> 23 24 #include <bcm/l3.h> 25 #include <bcm/oam.h> 26 #include <bcm/cosq.h> 27 28 #include <bcm_int/esw/oam.h> 29 #include <bcm_int/esw/port.h> 30 #include <bcm_int/esw/l3.h> 31 #include <bcm_int/esw/switch.h> 32 #include <bcm_int/esw/katana2.h> 33 #include <bcm_int/esw/virtual.h> 34 #include <bcm_int/esw_dispatch.h> 35 36 #if defined(BCM_KATANA2_SUPPORT) 37 #include <bcm_int/esw/stack.h> 38 #include <bcm_int/esw/subport.h> 39 40 #if defined(INCLUDE_BHH) 41 #include <bcm_int/esw/bhh.h> 42 #include <bcm_int/esw/bhh_sdk_pack.h> 43 #include <soc/uc.h> 44 #include <soc/shared/oam_pm_shared.h> 45 #include <soc/shared/oam_pm_pack.h> 46 #endif /* INCLUDE_BHH */ 47 /* 48 * Device OAM control structure. 49 */ 50 _bcm_oam_control_t *_kt2_oam_control[SOC_MAX_NUM_DEVICES]; 51 52 /* * * * * * * * * * * * * * * * * * * 53 * OAM MACROS * 54 */ 55 /* 56 * Macro: 57 * _BCM_OAM_IS_INIT (internal) 58 * Purpose: 59 * Check that the unit is valid and confirm that the oam functions 60 * are initialized. 61 * Parameters: 62 * unit - BCM device number 63 * Notes: 64 * Results in return(BCM_E_UNIT), return(BCM_E_UNAVAIL), or 65 * return(BCM_E_INIT) if fails. 66 */ 67 #define _BCM_OAM_IS_INIT(unit) \ 68 do { \ 69 if (!soc_feature(unit, soc_feature_oam)) { \ 70 return (BCM_E_UNAVAIL); \ 71 } \ 72 if (_kt2_oam_control[unit] == NULL) { \ 73 LOG_ERROR(BSL_LS_BCM_OAM, \ 74 (BSL_META_U(unit, \ 75 "OAM Error: Module not initialized\n"))); \ 76 return (BCM_E_INIT); \ 77 } \ 78 } while (0) 79 80 /* 81 *Macro: 82 * _BCM_OAM_LOCK 83 * Purpose: 84 * Lock take the OAM control mutex 85 * Parameters: 86 * control - Pointer to OAM control structure. 87 */ 88 #define _BCM_OAM_LOCK(control) \ 89 sal_mutex_take((control)->oc_lock, sal_mutex_FOREVER) 90 91 /* 92 * Macro: 93 * _BCM_OAM_UNLOCK 94 * Purpose: 95 * Lock take the OAM control mutex 96 * Parameters: 97 * control - Pointer to OAM control structure. 98 */ 99 #define _BCM_OAM_UNLOCK(control) \ 100 sal_mutex_give((control)->oc_lock); 101 /* 102 * Macro: 103 * _BCM_OAM_HASH_DATA_CLEAR 104 * Purpose: 105 * Clear hash data memory occupied by one endpoint. 106 * Parameters: 107 * _ptr_ - Pointer to endpoint hash data memory. 108 */ 109 #define _BCM_OAM_HASH_DATA_CLEAR(_ptr_) \ 110 sal_memset(_ptr_, 0, sizeof(_bcm_oam_hash_data_t)); 111 112 /* 113 * Macro: 114 * _BCM_OAM_HASH_DATA_HW_IDX_INIT 115 * Purpose: 116 * Initialize hardware indices to invalid index for an endpoint hash data. 117 * Parameters: 118 * _ptr_ - Pointer to endpoint hash data memory. 119 */ 120 #define _BCM_OAM_HASH_DATA_HW_IDX_INIT(_ptr_) \ 121 do { \ 122 (_ptr_)->group_index = (_BCM_OAM_INVALID_INDEX); \ 123 (_ptr_)->remote_index = (_BCM_OAM_INVALID_INDEX); \ 124 (_ptr_)->profile_index = (_BCM_OAM_INVALID_INDEX); \ 125 (_ptr_)->pri_map_index = (_BCM_OAM_INVALID_INDEX); \ 126 (_ptr_)->lm_counter_index = (_BCM_OAM_INVALID_INDEX); \ 127 (_ptr_)->local_tx_index = (_BCM_OAM_INVALID_INDEX); \ 128 (_ptr_)->local_rx_index = (_BCM_OAM_INVALID_INDEX); \ 129 } while (0) 130 /* 131 * Macro: 132 * _BCM_OAM_ALLOC 133 * Purpose: 134 * Generic memory allocation routine. 135 * Parameters: 136 * _ptr_ - Pointer to allocated memory. 137 * _ptype_ - Pointer type. 138 * _size_ - Size of heap memory to be allocated. 139 * _descr_ - Information about this memory allocation. 140 */ 141 #define _BCM_OAM_ALLOC(_ptr_,_ptype_,_size_,_descr_) \ 142 do { \ 143 if (NULL == (_ptr_)) { \ 144 (_ptr_) = (_ptype_ *) sal_alloc((_size_), (_descr_)); \ 145 } \ 146 if((_ptr_) != NULL) { \ 147 sal_memset((_ptr_), 0, (_size_)); \ 148 } else { \ 149 LOG_ERROR(BSL_LS_BCM_OAM, \ 150 (BSL_META("OAM Error: Allocation failure %s\n"), \ 151 (_descr_))); \ 152 } \ 153 } while (0) 154 155 /* 156 * Macro: 157 * _BCM_OAM_GROUP_INDEX_VALIDATE 158 * Purpose: 159 * Validate OAM Group ID value. 160 * Parameters: 161 * _group_ - Group ID value. 162 */ 163 #define _BCM_OAM_GROUP_INDEX_VALIDATE(_group_) \ 164 do { \ 165 if ((_group_) < 0 || (_group_) >= oc->group_count) { \ 166 LOG_ERROR(BSL_LS_BCM_OAM, \ 167 (BSL_META("OAM Error: Invalid Group ID = %d.\n"), \ 168 _group_)); \ 169 return (BCM_E_PARAM); \ 170 } \ 171 } while (0); 172 173 /* 174 * Macro: 175 * _BCM_OAM_EP_INDEX_VALIDATE 176 * Purpose: 177 * Validate OAM Endpoint ID value. 178 * Parameters: 179 * _ep_ - Endpoint ID value. 180 */ 181 #define _BCM_OAM_EP_INDEX_VALIDATE(_ep_) \ 182 do { \ 183 if ((_ep_) < 0 || (_ep_) >= oc->ep_count) { \ 184 LOG_ERROR(BSL_LS_BCM_OAM, \ 185 (BSL_META("OAM Error: Invalid Endpoint ID" \ 186 " = %d.\n"), _ep_)); \ 187 return (BCM_E_PARAM); \ 188 } \ 189 } while (0); 190 191 192 /* 193 * Macro: 194 * _BCM_OAM_RMEP_INDEX_VALIDATE 195 * Purpose: 196 * Validate OAM Endpoint ID value. 197 * Parameters: 198 * _ep_ - Endpoint ID value. 199 */ 200 #define _BCM_OAM_RMEP_INDEX_VALIDATE(_ep_) \ 201 do { \ 202 if ((_ep_) < 0 || (_ep_) >= oc->rmep_count) { \ 203 LOG_ERROR(BSL_LS_BCM_OAM, \ 204 (BSL_META("OAM Error: Invalid RMEP Index" \ 205 " = %d.\n"), _ep_)); \ 206 return (BCM_E_PARAM); \ 207 } \ 208 } while (0); 209 210 211 /* 212 * Macro: 213 * _BCM_OAM_KEY_PACK 214 * Purpose: 215 * Pack the hash table look up key fields. 216 * Parameters: 217 * _dest_ - Hash key buffer. 218 * _src_ - Hash key field to be packed. 219 * _size_ - Hash key field size in bytes. 220 */ 221 #define _BCM_OAM_KEY_PACK(_dest_,_src_,_size_) \ 222 do { \ 223 sal_memcpy((_dest_), (_src_), (_size_)); \ 224 (_dest_) += (_size_); \ 225 } while (0) 226 /* 227 * Macro: 228 * _BCM_KT2_OAM_MOD_PORT_TO_GLP 229 * Purpose: 230 * Construct hadware GLP value from module ID, port ID and Trunk ID value. 231 * Parameters: 232 * _modid_ - Module ID. 233 * _port_ - Port ID. 234 * _trunk_ - Trunk (1 - TRUE/0 - FALSE). 235 * _tgid_ - Trunk ID. 236 */ 237 #define _BCM_KT2_OAM_MOD_PORT_TO_GLP(_u_, _m_, _p_, _t_, _tgid_, _glp_) \ 238 do { \ 239 if ((_tgid_) != -1) { \ 240 (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_)) \ 241 | ((soc_mem_index_count((_u_), TRUNK_GROUPm) - 1) \ 242 & (_tgid_))); \ 243 } else { \ 244 (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_)) \ 245 | ((SOC_MODID_MAX(_u_) & (_m_)) \ 246 << (_shr_popcount((unsigned int) SOC_PORT_ADDR_MAX(_u_))) \ 247 | (SOC_PORT_ADDR_MAX(_u_) & (_p_)))); \ 248 } \ 249 LOG_DEBUG(BSL_LS_BCM_OAM, \ 250 (BSL_META("u:%d m:%d p:%d t:%d tgid:%d glp:%x\n"), \ 251 _u_, _m_, _p_, _t_, _tgid_, _glp_)); \ 252 } while (0) 253 254 /* 255 * Macro: 256 * _BCM_OAM_GLP_XXX 257 * Purpose: 258 * Get components of generic logical port value. 259 * Parameters: 260 * _glp_ - Generic logical port. 261 */ 262 #define _BCM_OAM_GLP_TRUNK_BIT_GET(_glp_) (0x1 & ((_glp_) >> 15)) 263 #define _BCM_OAM_GLP_TRUNK_ID_GET(_glp_) (0xFF & (_glp_)) 264 #define _BCM_OAM_GLP_MODULE_ID_GET(_glp_) (0xFF & ((_glp_) >> 7)) 265 #define _BCM_OAM_GLP_PORT_GET(_glp_) (0x7F & (_glp_)) 266 267 /* 268 * Macro: 269 * _BCM_OAM_EP_LEVEL_XXX 270 * Purpose: 271 * Maintenance domain level bit count and level max value. 272 * Parameters: 273 * _glp_ - Generic logical port. 274 */ 275 #define _BCM_OAM_EP_LEVEL_COUNT (1 << (_BCM_OAM_EP_LEVEL_BIT_COUNT)) 276 #define _BCM_OAM_EP_LEVEL_MAX (_BCM_OAM_EP_LEVEL_COUNT - 1) 277 #define BHH_EP_TYPE(ep) ( (ep->type == bcmOAMEndpointTypeBHHMPLS) || \ 278 (ep->type == bcmOAMEndpointTypeBHHMPLSVccv) || \ 279 (ep->type == bcmOAMEndpointTypeBhhSection)||\ 280 (ep->type == bcmOAMEndpointTypeBhhSectionInnervlan)||\ 281 (ep->type == bcmOAMEndpointTypeBhhSectionOuterVlan)||\ 282 (ep->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)\ 283 ) 284 285 #define BHH_EP_MPLS_SECTION_TYPE(ep) (\ 286 (ep->type == bcmOAMEndpointTypeBhhSection)||\ 287 (ep->type == bcmOAMEndpointTypeBhhSectionInnervlan)||\ 288 (ep->type == bcmOAMEndpointTypeBhhSectionOuterVlan)||\ 289 (ep->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)\ 290 ) 291 292 293 #define ETH_TYPE(type) (type == bcmOAMEndpointTypeEthernet) 294 295 /* Checks hash_data pointer's int_flags field */ 296 #define _BCM_OAM_EP_IS_VP_TYPE(h_data_p) (h_data_p->int_flags &\ 297 _BCM_OAM_ENDPOINT_IS_VP_BASED) 298 #define _BCM_OAM_EP_IS_MIP(info) (info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) 299 300 /* 301 * Macro: 302 * BCM_WB_XXX 303 * Purpose: 304 * OAM module scache version information. 305 * Parameters: 306 * (major number, minor number) 307 */ 308 #ifdef BCM_WARM_BOOT_SUPPORT 309 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 310 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 311 /* This new version incorporates new MA_INDEX allocation scheme. 312 * Recovery of Endpoints allocated in new scheme will be 313 * done for this version or higher only */ 314 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 315 316 /* This new version saves the SW endpoint ids for OAM. 317 * Recovery of Endpoints allocated in new scheme will be 318 * done for this version or higher only */ 319 320 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 321 #define BCM_WB_VERSION_1_4 SOC_SCACHE_VERSION(1,4) 322 #define BCM_WB_VERSION_1_5 SOC_SCACHE_VERSION(1,5) 323 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_5 324 #endif 325 326 #define _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_TBL_SIZE \ 327 (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + oc->egr_ma_idx_count)) 328 329 #define _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_DOWNMEP_IDX(ma_base_index, ma_offset)\ 330 (ma_base_index + ma_offset) 331 #define _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_UPMEP_IDX(ma_base_index, ma_offset)\ 332 (oc->ma_idx_count + ma_base_index + ma_offset) 333 334 #define _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX(ma_base_index, ma_offset, is_upmep)\ 335 ((is_upmep)?\ 336 _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_UPMEP_IDX(ma_base_index, ma_offset)\ 337 :_BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_DOWNMEP_IDX(ma_base_index, ma_offset)) 338 339 /* Macros for endpoint id locations for different endpoint types. */ 340 #define _BCM_KT2_OAM_ENDPOINT_ID_SCACHE_SIZE \ 341 (sizeof(bcm_oam_endpoint_t) * (oc->rmep_count + oc->lmep_count + oc->ma_idx_count + oc->egr_ma_idx_count)) 342 343 #define _BCM_KT2_OAM_RX_DOWNMEP_SCACHE_LOCATION(mep_index) \ 344 (sizeof(bcm_oam_endpoint_t) * mep_index) 345 #define _BCM_KT2_OAM_RX_UPMEP_SCACHE_LOCATION(mep_index) \ 346 (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + mep_index)) 347 #define _BCM_KT2_OAM_RMEP_SCACHE_LOCATION(rmep_index) \ 348 (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + oc->egr_ma_idx_count + rmep_index)) 349 #define _BCM_KT2_OAM_TX_MEP_SCACHE_LOCATION(mep_index) \ 350 (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + oc->egr_ma_idx_count + oc->rmep_count + mep_index)) 351 352 /* Vlans will be programmed in ING/EGR MP_GROUP table depending on MEP_TYPE */ 353 #define _BCM_KT2_ETH_OAM_MP_GROUP_KEY_DOMAIN_SPECIFIC 0 354 /* Inner & Outer Vlan will be always programmed in ING/EGR MP_GROUP table */ 355 #define _BCM_KT2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT 1 356 357 /* Defined for OAM opcode group 1 and 2 */ 358 #define _BCM_OAM_OTHER_OPCODE_GROUP_1 0x1 359 #define _BCM_OAM_OTHER_OPCODE_GROUP_2 0x2 360 /* Define the port used in OLP-XGS communication */ 361 #define _BCM_OAM_OLP_COMMUNICATION_PORT 0x7f 362 363 /* 364 * Device OAM control structure. 365 */ 366 _bcm_oam_control_t *_kt2_oam_control[SOC_MAX_NUM_DEVICES]; 367 368 #if defined (INCLUDE_BHH) 369 370 typedef struct _bcm_oam_pm_profile_int_info_s { 371 int id_status; 372 bcm_oam_pm_profile_info_t pm_profile; 373 }_bcm_oam_pm_profile_int_info_t; 374 typedef struct _bcm_oam_pm_profile_control_s { 375 _bcm_oam_pm_profile_int_info_t profile_info[_BCM_OAM_MAX_PM_PROFILES]; 376 }_bcm_oam_pm_profile_control_t; 377 378 379 _bcm_oam_pm_profile_control_t *kt2_pm_profile_control[SOC_MAX_NUM_DEVICES]; 380 381 #define _BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, id) (pmc->profile_info[id].id_status == 1) 382 #define _BCM_KT2_PM_CTRL_PROFILE_PTR(pmc, id) (&(pmc->profile_info[id].pm_profile)) 383 #define _BCM_KT2_SET_PM_CTRL_PROFILE_IN_USE(pmc, id) (pmc->profile_info[id].id_status = 1) 384 #define _BCM_KT2_SET_PM_CTRL_PROFILE_NOT_IN_USE(pmc, id) (pmc->profile_info[id].id_status = 0) 385 386 #define _BCM_KT2_PM_PROFILE_REPLACE_FLAG_SET(profile) (profile->flags & BCM_OAM_PM_PROFILE_REPLACE) 387 388 #define _BCM_KT2_PM_PROFILE_WITH_ID_FLAG_SET(profile) (profile->flags & BCM_OAM_PM_PROFILE_WITH_ID) 389 390 #define _BCM_KT2_PM_PROFILE_ID_VALID(profile_id) \ 391 ((profile_id >= 0) && (profile_id < _BCM_OAM_MAX_PM_PROFILES)) 392 393 #define _BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc) \ 394 (oc->pm_bhh_lmdm_data_collection_mode != \ 395 _BCM_OAM_PM_COLLECTION_MODE_NONE) 396 #define _BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) \ 397 (oc->pm_bhh_lmdm_data_collection_mode == \ 398 _BCM_OAM_PM_COLLECTION_MODE_RAW_DATA) 399 #define _BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc) \ 400 (oc->pm_bhh_lmdm_data_collection_mode == \ 401 _BCM_OAM_PM_COLLECTION_MODE_PROCESSED_STATS) 402 static int kt2_oam_mpls_tp_ach_channel_type = SHR_BHH_ACH_CHANNEL_TYPE; 403 #else 404 #define _BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc) 0 405 #define _BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) 0 406 #define _BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc) 0 407 #endif 408 409 410 typedef struct _oam_tpid_s { 411 uint32 tpid; 412 uint32 ref_count; 413 } _oam_tpid_t; 414 415 #define BCM_MAX_TPID_ENTRIES 4 416 #define BCM_MAX_INNER_TPID_ENTRIES 1 417 418 419 #define BCM_OAM_TPID_TYPE_OUTER 0 420 #define BCM_OAM_TPID_TYPE_INNER 1 421 #define BCM_OAM_TPID_TYPE_SUBPORT 2 422 #define BCM_OAM_TPID_VALUE_ZERO 0 423 #define BCM_OAM_DEFAULT_TPID 0x8100 424 #define BCM_OAM_TPID_9100 0x9100 425 #define BCM_OAM_TPID_88A8 0x88A8 426 #define DGLP_LAG_ID_INDICATOR_SHIFT_BITS 15 427 #define DGLP_MODULE_ID_SHIFT_BITS 7 428 #define _BCM_OAM_OPCODE_TYPE_CCM 0x1 429 #define _BCM_OAM_OPCODE_TYPE_LBR 0x2 430 #define _BCM_OAM_OPCODE_TYPE_LBM 0x3 431 #define _BCM_OAM_OPCODE_TYPE_LTR 0x4 432 #define _BCM_OAM_OPCODE_TYPE_LTM 0x5 433 #define _BCM_OAM_OPCODE_TYPE_NON_CFM_FIRST 0x6 434 #define _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST 0xFF 435 #define _BCM_OAM_OPCODE_TYPE_CFM_MASK 0x3E 436 #define _BCM_OAM_OPCODE_TYPE_NON_CFM_MASK 0xFFFFFFFF 437 #define _BCM_OAM_DGLP1_PROFILE_PTR 0x1 438 #define _BCM_OAM_DGLP2_PROFILE_PTR 0x2 439 #define _BCM_OAM_LOW_MDL_DROP_PACKET 0x2 440 #define _BCM_OAM_FWD_AS_DATA 0x0 441 #define _BCM_OAM_DROP_REDIRECT_T0_DGLP1 0x2 442 #define _BCM_OAM_DROP_REDIRECT_T0_DGLP2 0x3 443 #define _BCM_OAM_SERVICE_PRI_MAX_OFFSET 0x7 444 445 STATIC _oam_tpid_t 446 (*_oam_outer_tpid_tab[BCM_MAX_NUM_UNITS])[BCM_MAX_TPID_ENTRIES]; 447 448 STATIC _oam_tpid_t 449 (*_oam_inner_tpid_tab[BCM_MAX_NUM_UNITS])[BCM_MAX_INNER_TPID_ENTRIES]; 450 451 STATIC _oam_tpid_t 452 (*_oam_subport_tpid_tab[BCM_MAX_NUM_UNITS])[BCM_MAX_TPID_ENTRIES]; 453 454 STATIC sal_mutex_t _kt2_outer_tpid_lock[BCM_MAX_NUM_UNITS]; 455 STATIC sal_mutex_t _kt2_inner_tpid_lock[BCM_MAX_NUM_UNITS]; 456 STATIC sal_mutex_t _kt2_subport_tpid_lock[BCM_MAX_NUM_UNITS]; 457 458 /* OAM TPID registers and default values */ 459 STATIC int outer_tpid[4] = { OUTER_TPID_0r, OUTER_TPID_1r, 460 OUTER_TPID_2r, OUTER_TPID_3r }; 461 462 STATIC int default_outer_tpid[4] = { BCM_OAM_DEFAULT_TPID, BCM_OAM_TPID_9100, 463 BCM_OAM_TPID_88A8, BCM_OAM_TPID_VALUE_ZERO}; 464 465 STATIC int subport_tpid[4] = { SUBPORT_TAG_TPID_0r, SUBPORT_TAG_TPID_1r, 466 SUBPORT_TAG_TPID_2r, SUBPORT_TAG_TPID_3r }; 467 468 #define KT2_OAM_OUTER_TPID_TAB(unit) _oam_outer_tpid_tab[unit] 469 #define KT2_OAM_INNER_TPID_TAB(unit) _oam_inner_tpid_tab[unit] 470 #define KT2_OAM_SUBPORT_TPID_TAB(unit) _oam_subport_tpid_tab[unit] 471 472 #define KT2_OAM_OUTER_TPID_ENTRY(unit, index) \ 473 ((*_oam_outer_tpid_tab[unit])[index].tpid) 474 475 #define KT2_OAM_INNER_TPID_ENTRY(unit, index) \ 476 ((*_oam_inner_tpid_tab[unit])[index].tpid) 477 478 #define KT2_OAM_SUBPORT_TPID_ENTRY(unit, index) \ 479 ((*_oam_subport_tpid_tab[unit])[index].tpid) 480 481 #define KT2_OAM_OUTER_TPID_REF_COUNT(unit, index) \ 482 ((*_oam_outer_tpid_tab[unit])[index].ref_count) 483 484 #define KT2_OAM_INNER_TPID_REF_COUNT(unit, index) \ 485 ((*_oam_inner_tpid_tab[unit])[index].ref_count) 486 487 #define KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, index) \ 488 ((*_oam_subport_tpid_tab[unit])[index].ref_count) 489 490 #define KT2_OAM_OUTER_TPID_TAB_INIT_CHECK(unit) \ 491 if (KT2_OAM_OUTER_TPID_TAB(unit) == NULL) { return BCM_E_INIT; } 492 493 #define KT2_OAM_INNER_TPID_TAB_INIT_CHECK(unit) \ 494 if (KT2_OAM_INNER_TPID_TAB(unit) == NULL) { return BCM_E_INIT; } 495 496 #define KT2_OAM_SUBPORT_TPID_TAB_INIT_CHECK(unit) \ 497 if (KT2_OAM_SUBPORT_TPID_TAB(unit) == NULL) { return BCM_E_INIT; } 498 499 #define BCM_KT2_OUTER_TPID_MUTEX(_u_) _kt2_outer_tpid_lock[_u_] 500 #define BCM_KT2_INNER_TPID_MUTEX(_u_) _kt2_inner_tpid_lock[_u_] 501 #define BCM_KT2_SUBPORT_TPID_MUTEX(_u_) _kt2_subport_tpid_lock[_u_] 502 503 #define BCM_KT2_OUTER_TPID_LOCK(_u_) \ 504 ((_kt2_outer_tpid_lock[_u_]) ? \ 505 sal_mutex_take(_kt2_outer_tpid_lock[_u_], sal_mutex_FOREVER) : \ 506 (BCM_E_INTERNAL)) 507 508 #define BCM_KT2_INNER_TPID_LOCK(_u_) \ 509 ((_kt2_inner_tpid_lock[_u_]) ? \ 510 sal_mutex_take(_kt2_inner_tpid_lock[_u_], sal_mutex_FOREVER) : \ 511 (BCM_E_INTERNAL)) 512 513 #define BCM_KT2_SUBPORT_TPID_LOCK(_u_) \ 514 ((_kt2_subport_tpid_lock[_u_]) ? \ 515 sal_mutex_take(_kt2_subport_tpid_lock[_u_], sal_mutex_FOREVER) : \ 516 (BCM_E_INTERNAL)) 517 518 #define BCM_KT2_OUTER_TPID_UNLOCK(_u_) \ 519 ((_kt2_outer_tpid_lock[_u_]) ? \ 520 sal_mutex_give(_kt2_outer_tpid_lock[_u_]) : \ 521 (BCM_E_INTERNAL)) 522 523 #define BCM_KT2_INNER_TPID_UNLOCK(_u_) \ 524 ((_kt2_inner_tpid_lock[_u_]) ? \ 525 sal_mutex_give(_kt2_inner_tpid_lock[_u_]) : \ 526 (BCM_E_INTERNAL)) 527 528 #define BCM_KT2_SUBPORT_TPID_UNLOCK(_u_) \ 529 ((_kt2_subport_tpid_lock[_u_]) ? \ 530 sal_mutex_give(_kt2_subport_tpid_lock[_u_]) : \ 531 (BCM_E_INTERNAL)) 532 533 534 /* 535 * ========================================================================== 536 * Downmep/IFP 3'b000 8'd1(L2_HDR) 8'd0(NULL) 537 * Downmep/IFP 3'b001 8'd0(OAM_HDR) 8'd2(CCM/BHH-CCM) 538 * Downmep/IFP 3'b010 8'd0(OAM_HDR) 8'd3(BFD) 539 * Downmep/IFP 3'b011 8'd0(OAM_HDR) 8'd4(LM/DM) 540 * Upmep 3'b000 N/A N/A 541 * Upmep 3'b001 8'd0(OAM_HDR) 8'd5(CCM) 542 * Upmep 3'b010 N/A N/A 543 * Upmep 3'b011 8'd0(OAM_HDR) 8'd6(LM/DM) 544 */ 545 #define _BCM_KT2_OLP_HDR_SUBTYPE_CCM 0x2 546 #define _BCM_KT2_OLP_HDR_SUBTYPE_BFD 0x3 547 #define _BCM_KT2_OLP_HDR_SUBTYPE_LM_DM 0x4 548 #define _BCM_KT2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_CCM 0x5 549 #define _BCM_KT2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_LM_DM 0x6 550 551 #define _BCM_KT2_NO_OF_BITS_COMP_HDR 3 552 #define _BCM_KT2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET(comp_hdr) \ 553 ((1 << _BCM_KT2_NO_OF_BITS_COMP_HDR) | comp_hdr) 554 555 556 #define _BCM_KT2_CCM_OLP_HDR_TYPE_COMPRESSED 0x1 557 #define _BCM_KT2_BFD_OLP_HDR_TYPE_COMPRESSED 0x2 558 #define _BCM_KT2_LM_DM_OLP_HDR_TYPE_COMPRESSED 0x3 559 560 #define _BCM_KT2_ETH_OAM_UP_MEP_CCM_OLP_HDR_TYPE_COMPRESSED \ 561 _BCM_KT2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET( \ 562 _BCM_KT2_CCM_OLP_HDR_TYPE_COMPRESSED) 563 564 #define _BCM_KT2_ETH_OAM_UP_MEP_LM_DM_OLP_HDR_TYPE_COMPRESSED \ 565 _BCM_KT2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET( \ 566 _BCM_KT2_LM_DM_OLP_HDR_TYPE_COMPRESSED) 567 568 #define _BCM_KT2_OLP_OAM_HDR 0 569 #define _BCM_KT2_OLP_L2_HDR 1 570 571 /* No. of counter pool that can be programmed per endpoint */ 572 #define _KT2_OAM_COUNTER_SIZE 2 573 574 /* * * * * * * * * * * * * * * * * * * * * * * * * 575 * OAM function prototypes * 576 */ 577 578 int _bcm_kt2_oam_convert_action_to_opcode_entry( 579 int unit, 580 bcm_oam_endpoint_action_t *action, 581 bcm_oam_endpoint_t ep_id, 582 void *profile, 583 uint8 *opcode_profile_changed); 584 STATIC int 585 _bcm_kt2_oam_ma_idx_num_entries_and_pool_get(int unit, 586 _bcm_oam_hash_data_t *h_data_p, 587 int *num_ma_idx_entries, 588 shr_idxres_list_handle_t *pool); 589 STATIC int 590 _bcm_kt2_oam_ma_idx_pool_create(_bcm_oam_control_t *oc); 591 STATIC int 592 _bcm_kt2_oam_ma_idx_pool_destroy(_bcm_oam_control_t *oc); 593 594 STATIC int 595 _bcm_kt2_oam_control_get(int unit, _bcm_oam_control_t **oc); 596 597 STATIC INLINE bcm_oam_endpoint_t 598 _bcm_kt2_oam_ma_idx_to_ep_id_mapping_get (_bcm_oam_control_t *oc, int ma_idx); 599 600 601 602 /* * * * * * * * * * * * * * * * * * * * * * * * * 603 * OAM global data initialization * 604 */ 605 #if defined(INCLUDE_BHH) 606 607 #define BHH_COSQ_INVALID 0xFFFF 608 609 /* 610 * Macro: 611 * _BCM_OAM_BHH_IS_VALID (internal) 612 * Purpose: 613 * Check that the BHH feature is available on this unit 614 * Parameters: 615 * unit - BCM device number 616 * Notes: 617 * Results in return(BCM_E_UNAVAIL), 618 */ 619 #define _BCM_OAM_BHH_IS_VALID(unit) \ 620 do { \ 621 if (!soc_feature(unit, soc_feature_bhh)) { \ 622 return (BCM_E_UNAVAIL); \ 623 } \ 624 } while (0) 625 626 #define BCM_OAM_BHH_GET_UKERNEL_EP(ep) \ 627 (ep - _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET) 628 629 #define BCM_OAM_BHH_GET_SDK_EP(ep) \ 630 (ep + _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET) 631 632 #define BCM_OAM_BHH_VALIDATE_EP(_ep_) \ 633 do { \ 634 if (((_ep_) < _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET) || \ 635 ((_ep_) >= (_BCM_OAM_BHH_KT2_ENDPOINT_OFFSET \ 636 + oc->bhh_endpoint_count))) { \ 637 LOG_ERROR(BSL_LS_BCM_OAM, \ 638 (BSL_META_U(unit, \ 639 "OAM Error: Invalid Endpoint ID" \ 640 " = %d.\n"), _ep_)); \ 641 _BCM_OAM_UNLOCK(oc); \ 642 return (BCM_E_PARAM); \ 643 } \ 644 } while (0); 645 646 #define BCM_OAM_BHH_ABS(x) (((x) < 0) ? (-(x)) : (x)) 647 648 649 STATIC int 650 _bcm_kt2_oam_bhh_session_hw_delete(int unit, _bcm_oam_hash_data_t *h_data_p); 651 STATIC int 652 _bcm_kt2_oam_bhh_msg_send_receive(int unit, uint8 s_subclass, 653 uint16 s_len, uint32 s_data, 654 uint8 r_subclass, uint16 *r_len); 655 STATIC int 656 _bcm_kt2_oam_bhh_hw_init(int unit); 657 STATIC void 658 _bcm_kt2_oam_bhh_callback_thread(void *param); 659 STATIC int 660 _bcm_kt2_oam_bhh_event_mask_set(int unit); 661 STATIC int 662 bcm_kt2_oam_bhh_endpoint_create(int unit, 663 bcm_oam_endpoint_info_t *endpoint_info, 664 _bcm_oam_hash_key_t *hash_key); 665 STATIC int 666 _bcm_kt2_oam_bhh_sec_mep_alloc_counter(int unit, shr_idxres_element_t *ctr_index); 667 668 STATIC int 669 _bcm_kt2_oam_pm_msg_send_receive(int unit, uint8 s_class, uint8 s_subclass, 670 uint16 s_len, uint32 s_data, 671 uint8 r_subclass, uint16 *r_len); 672 673 STATIC void _bcm_kt2_oam_pm_event_msg_handle(_bcm_oam_control_t *oc, 674 mos_msg_data_t *event_msg); 675 int _bcm_kt2_oam_pm_init(int unit); 676 #endif /* INCLUDE_BHH */ 677 678 STATIC int 679 bcm_kt2_oam_hw_ccm_tx_ctr_update(int unit, 680 bcm_oam_endpoint_info_t *ep_info); 681 /* 682 * Katana2 device OAM CCM intervals array initialization.. 683 */ 684 STATIC uint32 _kt2_ccm_intervals[] = 685 { 686 BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED, 687 BCM_OAM_ENDPOINT_CCM_PERIOD_3MS, 688 BCM_OAM_ENDPOINT_CCM_PERIOD_10MS, 689 BCM_OAM_ENDPOINT_CCM_PERIOD_100MS, 690 BCM_OAM_ENDPOINT_CCM_PERIOD_1S, 691 BCM_OAM_ENDPOINT_CCM_PERIOD_10S, 692 BCM_OAM_ENDPOINT_CCM_PERIOD_1M, 693 BCM_OAM_ENDPOINT_CCM_PERIOD_10M, 694 _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED 695 }; 696 697 /* 698 * OAM hardware interrupts to software events mapping array initialization. 699 * _kt2_oam_interrupts[] = 700 * {Interrupt status register, Remote MEP index field, MA index field, 701 * CCM_INTERRUPT_CONTROLr - Interrupt status Field, 702 * OAM event type}. 703 */ 704 STATIC _bcm_oam_interrupt_t _kt2_oam_interrupts[] = 705 { 706 /* 1. Port down interrupt. */ 707 {ANY_RMEP_TLV_PORT_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 708 ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf, 709 bcmOAMEventEndpointPortDown}, 710 711 /* 2. Port up interrupt. */ 712 {ANY_RMEP_TLV_PORT_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 713 ANY_RMEP_TLV_PORT_UP_INT_ENABLEf, 714 bcmOAMEventEndpointPortUp}, 715 716 /* 3. Interface down interrupt. */ 717 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 718 ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf, 719 bcmOAMEventEndpointInterfaceDown}, 720 721 /* 4. Interface up interrupt. */ 722 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 723 ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf, 724 bcmOAMEventEndpointInterfaceUp}, 725 726 /* 5. Interface TLV Testing to Up interrupt. */ 727 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 728 ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf, 729 bcmOAMEventEndpointInterfaceTestingToUp}, 730 731 /* 6. Interface TLV Unknown to Up interrupt. */ 732 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 733 ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf, 734 bcmOAMEventEndpointInterfaceUnknownToUp}, 735 736 /* 7. Interface TLV Dormant to Up interrupt. */ 737 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 738 ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf, 739 bcmOAMEventEndpointInterfaceDormantToUp}, 740 741 /* 8. Interface TLV Not present to Up interrupt. */ 742 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 743 ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf, 744 bcmOAMEventEndpointInterfaceNotPresentToUp}, 745 746 /* 9. Interface Link Layer Down to Up interrupt. */ 747 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 748 ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf, 749 bcmOAMEventEndpointInterfaceLLDownToUp}, 750 751 /* 10. Interface up to testing transition interrupt. */ 752 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 753 ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf, 754 bcmOAMEventEndpointInterfaceTesting}, 755 756 /* 11. Interface up to unknown transition interrupt. */ 757 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 758 ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf, 759 bcmOAMEventEndpointInterfaceUnkonwn}, 760 761 /* 11. Interface up to dormant transition interrupt. */ 762 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 763 ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf, 764 bcmOAMEventEndpointInterfaceDormant}, 765 766 /* 11. Interface up to not present transition interrupt. */ 767 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 768 ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf, 769 bcmOAMEventEndpointInterfaceNotPresent}, 770 771 /* 11. Interface up to Link Layer Down transition interrupt. */ 772 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 773 ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf, 774 bcmOAMEventEndpointInterfaceLLDown}, 775 776 /* 12. Low MDL or unexpected MAID interrupt. */ 777 {XCON_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf, 778 XCON_CCM_DEFECT_INT_ENABLEf, 779 bcmOAMEventGroupCCMxcon}, 780 781 /* 782 * 13. Remote MEP lookup failed or CCM interval mismatch during Remote MEP 783 * lookup interrupt. 784 */ 785 {ERROR_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf, 786 ERROR_CCM_DEFECT_INT_ENABLEf, 787 bcmOAMEventGroupCCMError}, 788 789 /* 790 * 14. Some Remote defect indicator interrupt - aggregated health of remote 791 * MEPs. 792 */ 793 {SOME_RDI_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf, 794 SOME_RDI_DEFECT_INT_ENABLEf, 795 bcmOAMEventGroupRemote}, 796 797 /* 15. Aggregate health of remote MEP state machines interrupt. */ 798 {SOME_RMEP_CCM_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf, 799 SOME_RMEP_CCM_DEFECT_INT_ENABLEf, 800 bcmOAMEventGroupCCMTimeout}, 801 802 /* Invalid Interrupt - Always Last */ 803 {INVALIDr, INVALIDf, 0, bcmOAMEventCount} 804 }; 805 806 /* 807 * 0AM Group faults array initialization. 808 */ 809 STATIC _bcm_oam_fault_t _kt2_oam_group_faults[] = 810 { 811 {CURRENT_XCON_CCM_DEFECTf, STICKY_XCON_CCM_DEFECTf, 812 BCM_OAM_GROUP_FAULT_CCM_XCON, 0x08}, 813 814 {CURRENT_ERROR_CCM_DEFECTf, STICKY_ERROR_CCM_DEFECTf, 815 BCM_OAM_GROUP_FAULT_CCM_ERROR, 0x04}, 816 817 {CURRENT_SOME_RMEP_CCM_DEFECTf, STICKY_SOME_RMEP_CCM_DEFECTf, 818 BCM_OAM_GROUP_FAULT_CCM_TIMEOUT, 0x02}, 819 820 {CURRENT_SOME_RDI_DEFECTf, STICKY_SOME_RDI_DEFECTf, 821 BCM_OAM_GROUP_FAULT_REMOTE, 0x01}, 822 823 {0, 0, 0, 0} 824 }; 825 826 /* 827 * 0AM Endpoint faults array initialization. 828 */ 829 STATIC _bcm_oam_fault_t _kt2_oam_endpoint_faults[] = 830 { 831 {CURRENT_RMEP_PORT_STATUS_DEFECTf, 832 STICKY_RMEP_PORT_STATUS_DEFECTf, 833 BCM_OAM_ENDPOINT_FAULT_PORT_DOWN, 0x08}, 834 835 {CURRENT_RMEP_INTERFACE_STATUS_DEFECTf, 836 STICKY_RMEP_INTERFACE_STATUS_DEFECTf, 837 BCM_OAM_ENDPOINT_FAULT_INTERFACE_DOWN, 0x04}, 838 839 {CURRENT_RMEP_CCM_DEFECTf, 840 STICKY_RMEP_CCM_DEFECTf, 841 BCM_OAM_ENDPOINT_FAULT_CCM_TIMEOUT, 0x20}, 842 843 {CURRENT_RMEP_LAST_RDIf, 844 STICKY_RMEP_LAST_RDIf, 845 BCM_OAM_ENDPOINT_FAULT_REMOTE, 0x10}, 846 847 {0, 0, 0, 0} 848 }; 849 850 typedef struct _bcm_kt2_oam_intr_en_fields_s { 851 soc_field_t field; 852 uint32 value; 853 } _bcm_kt2_oam_intr_en_fields_t; 854 855 STATIC _bcm_kt2_oam_intr_en_fields_t _kt2_oam_intr_en_fields[bcmOAMEventCount] = 856 { 857 /* 858 * Note: 859 * The order of hardware field names in the below initialization 860 * code must match the event enum order in bcm_oam_event_type_t. 861 */ 862 { ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf, 1}, 863 { ANY_RMEP_TLV_PORT_UP_INT_ENABLEf, 1}, 864 { ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf, 1}, 865 { ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf, 1}, 866 { ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf, 1}, 867 { ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf, 1}, 868 { ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf, 1}, 869 { ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf, 1}, 870 { ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf, 1}, 871 { ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf, 1}, 872 { ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf, 1}, 873 { ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf, 1}, 874 { ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf, 1}, 875 { ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf, 1}, 876 { XCON_CCM_DEFECT_INT_ENABLEf, 1}, 877 { ERROR_CCM_DEFECT_INT_ENABLEf, 1}, 878 { SOME_RDI_DEFECT_INT_ENABLEf, 1}, 879 { SOME_RMEP_CCM_DEFECT_INT_ENABLEf, 1}, 880 { INVALIDf, 0}, 881 { INVALIDf, 0}, 882 { INVALIDf, 0}, 883 { INVALIDf, 0}, 884 { INVALIDf, 0}, 885 { INVALIDf, 0}, 886 { INVALIDf, 0}, 887 { INVALIDf, 0}, 888 { INVALIDf, 0}, 889 { INVALIDf, 0}, 890 { INVALIDf, 0} 891 }; 892 893 /* LM counter related fields - Ingress */ 894 STATIC mep_ctr_info_t mep_ctr_info[] = { 895 { LMEP__CTR1_VALIDf, LMEP__CTR1_BASE_PTRf, 896 LMEP__CTR1_MEP_TYPEf, LMEP__CTR1_MEP_MDLf, 897 LMEP__CTR1_SERVICE_PRI_MAP_PROFILE_PTRf 898 }, 899 { LMEP__CTR2_VALIDf, LMEP__CTR2_BASE_PTRf, 900 LMEP__CTR2_MEP_TYPEf, LMEP__CTR2_MEP_MDLf, 901 LMEP__CTR2_SERVICE_PRI_MAP_PROFILE_PTRf 902 } 903 }; 904 905 /* LM counter related fields - Egress */ 906 STATIC mep_ctr_info_t egr_mep_ctr_info[] = { 907 { CTR1_VALIDf, CTR1_BASE_PTRf, 908 CTR1_MEP_TYPEf, CTR1_MEP_MDLf, 909 CTR1_SERVICE_PRI_MAP_PROFILE_PTRf 910 }, 911 { CTR2_VALIDf, CTR2_BASE_PTRf, 912 CTR2_MEP_TYPEf, CTR2_MEP_MDLf, 913 CTR2_SERVICE_PRI_MAP_PROFILE_PTRf 914 } 915 }; 916 917 typedef struct _bcm_kt2_oam_olp_hdr_type_map_s { 918 bcm_field_olp_header_type_t field_olp_hdr_type; 919 uint8 mem_index; 920 uint8 subtype; 921 uint8 reuse; 922 } _bcm_kt2_oam_olp_hdr_type_map_t; 923 924 STATIC _bcm_kt2_oam_olp_hdr_type_map_t kt2_olp_hdr_type_mapping[] = { 925 /* Down MEP CCM */ 926 {bcmFieldOlpHeaderTypeEthOamCcm, _BCM_KT2_CCM_OLP_HDR_TYPE_COMPRESSED, 927 _BCM_KT2_OLP_HDR_SUBTYPE_CCM, 0}, 928 929 {bcmFieldOlpHeaderTypeBhhOamCcm, _BCM_KT2_CCM_OLP_HDR_TYPE_COMPRESSED, 930 _BCM_KT2_OLP_HDR_SUBTYPE_CCM, 1}, 931 932 /* BFD */ 933 {bcmFieldOlpHeaderTypeBfdOam, _BCM_KT2_BFD_OLP_HDR_TYPE_COMPRESSED, 934 _BCM_KT2_OLP_HDR_SUBTYPE_BFD, 0}, 935 936 /* Down MEP LM/DM */ 937 {bcmFieldOlpHeaderTypeEthOamLmDm, _BCM_KT2_LM_DM_OLP_HDR_TYPE_COMPRESSED, 938 _BCM_KT2_OLP_HDR_SUBTYPE_LM_DM, 0}, 939 940 {bcmFieldOlpHeaderTypeEthOamLm, _BCM_KT2_LM_DM_OLP_HDR_TYPE_COMPRESSED, 941 _BCM_KT2_OLP_HDR_SUBTYPE_LM_DM, 1}, 942 943 {bcmFieldOlpHeaderTypeEthOamDm, _BCM_KT2_LM_DM_OLP_HDR_TYPE_COMPRESSED, 944 _BCM_KT2_OLP_HDR_SUBTYPE_LM_DM, 1}, 945 946 {bcmFieldOlpHeaderTypeBhhOamLm, _BCM_KT2_LM_DM_OLP_HDR_TYPE_COMPRESSED, 947 _BCM_KT2_OLP_HDR_SUBTYPE_LM_DM, 1}, 948 949 {bcmFieldOlpHeaderTypeBhhOamDm, _BCM_KT2_LM_DM_OLP_HDR_TYPE_COMPRESSED, 950 _BCM_KT2_OLP_HDR_SUBTYPE_LM_DM, 1}, 951 952 /* 953 * UpMEP header types are not programmable by FP, but OAM pipeline lookup 954 * can assign UpMEP subtypes. 955 */ 956 957 /* UpMEP CCM*/ 958 {bcmFieldOlpHeaderTypeEthOamUpMepCcm, _BCM_KT2_ETH_OAM_UP_MEP_CCM_OLP_HDR_TYPE_COMPRESSED, 959 _BCM_KT2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_CCM, 0}, 960 961 {bcmFieldOlpHeaderTypeEthOamUpMepLm, _BCM_KT2_ETH_OAM_UP_MEP_LM_DM_OLP_HDR_TYPE_COMPRESSED, 962 _BCM_KT2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_LM_DM, 0}, 963 964 {bcmFieldOlpHeaderTypeEthOamUpMepDm, _BCM_KT2_ETH_OAM_UP_MEP_LM_DM_OLP_HDR_TYPE_COMPRESSED, 965 _BCM_KT2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_LM_DM, 1}, 966 }; 967 968 static uint8 kt2_olp_hdr_type_count = sizeof(kt2_olp_hdr_type_mapping) / 969 sizeof(kt2_olp_hdr_type_mapping[0]); 970 971 972 /* * * * * * * * * * * * * * * * * * * * * * * * * 973 * Static local functions * 974 */ 975 /* 976 * Function: 977 * _bcm_kt2_outer_tpid_init 978 * Purpose: 979 * Allocate and initialize memory to cache oam outer tpid entries. 980 * Initialize lock for cached tpid entries. 981 * Parameters: 982 * unit - (IN)SOC unit number. 983 * Returns: 984 * BCM_E_XXX 985 * Notes: 986 */ 987 int 988 _bcm_kt2_outer_tpid_init(int unit) { 989 int index; 990 int alloc_size; 991 uint32 reg32; 992 int rv = BCM_E_NONE; 993 994 /* Allocate memory to cache OUTER_TPID entries. */ 995 alloc_size = sizeof(_oam_tpid_t) * BCM_MAX_TPID_ENTRIES; 996 if (KT2_OAM_OUTER_TPID_TAB(unit) == NULL) { 997 KT2_OAM_OUTER_TPID_TAB(unit) = sal_alloc(alloc_size, 998 "Cached OAM Outer TPIDs"); 999 if (KT2_OAM_OUTER_TPID_TAB(unit) == NULL) { 1000 return BCM_E_MEMORY; 1001 } 1002 } 1003 sal_memset(KT2_OAM_OUTER_TPID_TAB(unit), 0, alloc_size); 1004 1005 /* Cache outer TPID table */ 1006 for (index = 0; index < BCM_MAX_TPID_ENTRIES; index++) { 1007 rv = soc_reg32_get(unit, outer_tpid[index], REG_PORT_ANY, 0, ®32); 1008 if (BCM_FAILURE(rv)) { 1009 sal_free(KT2_OAM_OUTER_TPID_TAB(unit)); 1010 KT2_OAM_OUTER_TPID_TAB(unit) = NULL; 1011 } 1012 KT2_OAM_OUTER_TPID_ENTRY(unit, index) = soc_reg_field_get(unit, 1013 outer_tpid[index], reg32, TPIDf); 1014 } 1015 1016 if (NULL == BCM_KT2_OUTER_TPID_MUTEX(unit)) { 1017 /* Create protection mutex. */ 1018 BCM_KT2_OUTER_TPID_MUTEX(unit) = sal_mutex_create("oamouter_tpid_lock"); 1019 if (NULL == BCM_KT2_OUTER_TPID_MUTEX(unit)) { 1020 return (BCM_E_MEMORY); 1021 } 1022 } 1023 return (BCM_E_NONE); 1024 } 1025 1026 /* 1027 * Function: 1028 * _bcm_kt2_inner_tpid_init 1029 * Purpose: 1030 * Allocate and initialize memory to cache oam inner tpid entries. 1031 * Initialize lock for cached tpid entries. 1032 * Parameters: 1033 * unit - (IN)SOC unit number. 1034 * Returns: 1035 * BCM_E_XXX 1036 * Notes: 1037 */ 1038 int 1039 _bcm_kt2_inner_tpid_init(int unit) { 1040 int alloc_size; 1041 uint32 reg32; 1042 int rv = BCM_E_NONE; 1043 1044 /* Allocate memory to cache INNER_TPID entries. */ 1045 alloc_size = sizeof(_oam_tpid_t) * BCM_MAX_INNER_TPID_ENTRIES; 1046 if (KT2_OAM_INNER_TPID_TAB(unit) == NULL) { 1047 KT2_OAM_INNER_TPID_TAB(unit) = sal_alloc(alloc_size, 1048 "Cached OAM Inner TPIDs"); 1049 if (KT2_OAM_INNER_TPID_TAB(unit) == NULL) { 1050 return BCM_E_MEMORY; 1051 } 1052 } 1053 sal_memset(KT2_OAM_INNER_TPID_TAB(unit), 0, alloc_size); 1054 1055 /* Cache Inner TPID table */ 1056 rv = soc_reg32_get(unit, INNER_TPIDr, REG_PORT_ANY, 0, ®32); 1057 if (BCM_FAILURE(rv)) { 1058 sal_free(KT2_OAM_INNER_TPID_TAB(unit)); 1059 KT2_OAM_INNER_TPID_TAB(unit) = NULL; 1060 } 1061 /* Inner TPID has only 1 entry. So, index is always 0 */ 1062 KT2_OAM_INNER_TPID_ENTRY(unit, 0) = soc_reg_field_get(unit, INNER_TPIDr, 1063 reg32, TPIDf); 1064 1065 if (NULL == BCM_KT2_INNER_TPID_MUTEX(unit)) { 1066 /* Create protection mutex. */ 1067 BCM_KT2_INNER_TPID_MUTEX(unit) = sal_mutex_create("oam inner_tpid_lock"); 1068 if (NULL == BCM_KT2_INNER_TPID_MUTEX(unit)) { 1069 return (BCM_E_MEMORY); 1070 } 1071 } 1072 return (BCM_E_NONE); 1073 } 1074 1075 /* 1076 * Function: 1077 * _bcm_kt2_subport_tpid_init 1078 * Purpose: 1079 * Allocate and initialize memory to cache oam subport tpid entries. 1080 * Initialize lock for cached tpid entries. 1081 * Parameters: 1082 * unit - (IN)SOC unit number. 1083 * Returns: 1084 * BCM_E_XXX 1085 * Notes: 1086 */ 1087 int 1088 _bcm_kt2_subport_tpid_init(int unit) { 1089 int index; 1090 int alloc_size; 1091 uint32 reg32; 1092 int rv = BCM_E_NONE; 1093 1094 /* Allocate memory to cache OUTER_TPID entries. */ 1095 alloc_size = sizeof(_oam_tpid_t) * BCM_MAX_TPID_ENTRIES; 1096 if (KT2_OAM_SUBPORT_TPID_TAB(unit) == NULL) { 1097 KT2_OAM_SUBPORT_TPID_TAB(unit) = sal_alloc(alloc_size, 1098 "Cached OAM Subport TPIDs"); 1099 if (KT2_OAM_SUBPORT_TPID_TAB(unit) == NULL) { 1100 return BCM_E_MEMORY; 1101 } 1102 } 1103 sal_memset(KT2_OAM_SUBPORT_TPID_TAB(unit), 0, alloc_size); 1104 1105 /* Cache Subport TPID table */ 1106 for (index = 0; index < BCM_MAX_TPID_ENTRIES; index++) { 1107 rv = soc_reg32_get(unit, subport_tpid[index], REG_PORT_ANY, 0, ®32); 1108 if (BCM_FAILURE(rv)) { 1109 sal_free(KT2_OAM_SUBPORT_TPID_TAB(unit)); 1110 KT2_OAM_SUBPORT_TPID_TAB(unit) = NULL; 1111 } 1112 KT2_OAM_SUBPORT_TPID_ENTRY(unit, index) = soc_reg_field_get(unit, 1113 subport_tpid[index], reg32, TPIDf); 1114 } 1115 1116 if (NULL == BCM_KT2_SUBPORT_TPID_MUTEX(unit)) { 1117 /* Create protection mutex. */ 1118 BCM_KT2_SUBPORT_TPID_MUTEX(unit) = sal_mutex_create("oam subport_tpid_lock"); 1119 if (NULL == BCM_KT2_SUBPORT_TPID_MUTEX(unit)) { 1120 return (BCM_E_MEMORY); 1121 } 1122 } 1123 return (BCM_E_NONE); 1124 } 1125 /* 1126 * Function : 1127 * _bcm_kt2_oam_tpid_get 1128 * 1129 * Purpose : 1130 * Get tpid value for tpid entry index in the HW. 1131 * 1132 * Parameters : 1133 * unit - (IN) BCM device number. 1134 * tpid_type -(IN) - outer/inner/subport 1135 * index - (IN) Entry index. 1136 * value - (OUT) TPID value 1137 * Return : 1138 * BCM_E_XXX 1139 */ 1140 int 1141 _bcm_kt2_oam_tpid_get(int unit, int tpid_type, int index, int *value) 1142 { 1143 int rv = BCM_E_NONE; 1144 uint32 rval = 0; 1145 1146 if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 1147 if (index >= BCM_MAX_TPID_ENTRIES) { 1148 return (BCM_E_PARAM); 1149 } 1150 rv = soc_reg32_get(unit, outer_tpid[index], REG_PORT_ANY, 0, &rval); 1151 if (BCM_FAILURE(rv)) { 1152 return (BCM_E_PARAM); 1153 } 1154 *value = soc_reg_field_get(unit, outer_tpid[index], rval, TPIDf); 1155 } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 1156 if (index >= BCM_MAX_INNER_TPID_ENTRIES) { 1157 return (BCM_E_PARAM); 1158 } 1159 rv = soc_reg32_get(unit, INNER_TPIDr, REG_PORT_ANY, 0, &rval); 1160 if (BCM_FAILURE(rv)) { 1161 return (BCM_E_PARAM); 1162 } 1163 *value = soc_reg_field_get(unit, INNER_TPIDr, rval, TPIDf); 1164 } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 1165 if (index >= BCM_MAX_TPID_ENTRIES) { 1166 return (BCM_E_PARAM); 1167 } 1168 rv = soc_reg32_get(unit, subport_tpid[index], REG_PORT_ANY, 0, &rval); 1169 if (BCM_FAILURE(rv)) { 1170 return (BCM_E_PARAM); 1171 } 1172 *value = soc_reg_field_get(unit, subport_tpid[index], rval, TPIDf); 1173 } else { 1174 return (BCM_E_PARAM); 1175 } 1176 return (rv); 1177 } 1178 1179 /* 1180 * Function : 1181 * _bcm_kt2_oam_tpid_set 1182 * 1183 * Purpose : 1184 * Set tpid value for tpid entry index in the HW. 1185 * 1186 * Parameters : 1187 * unit - (IN) BCM device number. 1188 * tpid_type -(IN) - outer/inner/subport 1189 * index - (IN) Entry index. 1190 * value - (IN) Value to be set as tpid 1191 * Return : 1192 * BCM_E_XXX 1193 */ 1194 int 1195 _bcm_kt2_oam_tpid_set(int unit, int tpid_type, int index, int value) 1196 { 1197 int rv = BCM_E_NONE; 1198 uint32 rval = 0; 1199 1200 if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 1201 if (index >= BCM_MAX_TPID_ENTRIES) { 1202 return (BCM_E_PARAM); 1203 } 1204 soc_reg_field_set(unit, outer_tpid[index], &rval, TPIDf, value); 1205 rv = soc_reg32_set(unit, outer_tpid[index], REG_PORT_ANY, 0, rval); 1206 if (BCM_FAILURE(rv)) { 1207 return (BCM_E_PARAM); 1208 } 1209 } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 1210 if (index >= BCM_MAX_INNER_TPID_ENTRIES) { 1211 return (BCM_E_PARAM); 1212 } 1213 soc_reg_field_set(unit, INNER_TPIDr, &rval, TPIDf, value); 1214 rv = soc_reg32_set(unit, INNER_TPIDr, REG_PORT_ANY, 0, rval); 1215 if (BCM_FAILURE(rv)) { 1216 return (BCM_E_PARAM); 1217 } 1218 } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 1219 if (index >= BCM_MAX_TPID_ENTRIES) { 1220 return (BCM_E_PARAM); 1221 } 1222 soc_reg_field_set(unit, subport_tpid[index], &rval, TPIDf, value); 1223 rv = soc_reg32_set(unit, subport_tpid[index], REG_PORT_ANY, 0, rval); 1224 if (BCM_FAILURE(rv)) { 1225 return (BCM_E_PARAM); 1226 } 1227 } else { 1228 return (BCM_E_PARAM); 1229 } 1230 return (rv); 1231 } 1232 1233 /* 1234 * Function : 1235 * _bcm_kt2_oam_tpid_entry_get 1236 * 1237 * Purpose : 1238 * Get tpid value for tpid entry index . 1239 * 1240 * Parameters : 1241 * unit - (IN) BCM device number. 1242 * tpid - (OUT) TPID value. 1243 * index - (IN) Entry index. 1244 * 1245 * Return : 1246 * BCM_E_XXX 1247 */ 1248 int 1249 _bcm_kt2_oam_tpid_entry_get(int unit, uint16 *tpid, int index, int tpid_type) 1250 { 1251 if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 1252 if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) || 1253 (KT2_OAM_OUTER_TPID_REF_COUNT(unit, index) <= 0)) { 1254 return (BCM_E_PARAM); 1255 } 1256 *tpid = KT2_OAM_OUTER_TPID_ENTRY(unit, index); 1257 } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 1258 if ((index < 0) || (index >= BCM_MAX_INNER_TPID_ENTRIES) || 1259 (KT2_OAM_INNER_TPID_REF_COUNT(unit, index) <= 0)) { 1260 return (BCM_E_PARAM); 1261 } 1262 *tpid = KT2_OAM_INNER_TPID_ENTRY(unit, index); 1263 } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 1264 if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) || 1265 (KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, index) <= 0)) { 1266 return (BCM_E_PARAM); 1267 } 1268 *tpid = KT2_OAM_SUBPORT_TPID_ENTRY(unit, index); 1269 } else { 1270 return (BCM_E_PARAM); 1271 } 1272 return (BCM_E_NONE); 1273 } 1274 1275 /* 1276 * Function : 1277 * _bcm_kt2_oam_tpid_entry_delete 1278 * 1279 * Purpose : 1280 * Delete tpid entry by index. 1281 * 1282 * Parameters : 1283 * unit - (IN) BCM device number. 1284 * index - (IN) Entry index. 1285 * 1286 * Return : 1287 * BCM_E_XXX 1288 */ 1289 int 1290 _bcm_kt2_tpid_entry_delete(int unit, int index, int tpid_type) 1291 { 1292 int rv = BCM_E_NONE; 1293 if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 1294 BCM_KT2_OUTER_TPID_LOCK(unit); 1295 if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) || 1296 (KT2_OAM_OUTER_TPID_REF_COUNT(unit, index) <= 0)) { 1297 rv = BCM_E_PARAM; 1298 BCM_KT2_OUTER_TPID_UNLOCK(unit); 1299 return rv; 1300 } 1301 KT2_OAM_OUTER_TPID_REF_COUNT(unit, index)--; 1302 if (0 == KT2_OAM_OUTER_TPID_REF_COUNT(unit, index)) { 1303 KT2_OAM_OUTER_TPID_ENTRY(unit, index) = default_outer_tpid[index]; 1304 rv = _bcm_kt2_oam_tpid_set(unit, tpid_type, index, 1305 default_outer_tpid[index]); 1306 } 1307 BCM_KT2_OUTER_TPID_UNLOCK(unit); 1308 } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 1309 BCM_KT2_INNER_TPID_LOCK(unit); 1310 if ((index < 0) || (index >= BCM_MAX_INNER_TPID_ENTRIES) || 1311 (KT2_OAM_INNER_TPID_REF_COUNT(unit, index) <= 0)) { 1312 rv = BCM_E_PARAM; 1313 BCM_KT2_INNER_TPID_UNLOCK(unit); 1314 return rv; 1315 } 1316 KT2_OAM_INNER_TPID_REF_COUNT(unit, index)--; 1317 if (0 == KT2_OAM_INNER_TPID_REF_COUNT(unit, index)) { 1318 KT2_OAM_INNER_TPID_ENTRY(unit, index) = BCM_OAM_DEFAULT_TPID; 1319 rv = _bcm_kt2_oam_tpid_set(unit, tpid_type, index, 1320 BCM_OAM_DEFAULT_TPID); 1321 } 1322 BCM_KT2_INNER_TPID_UNLOCK(unit); 1323 } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 1324 BCM_KT2_SUBPORT_TPID_LOCK(unit); 1325 if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) || 1326 (KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, index) <= 0)) { 1327 rv = BCM_E_PARAM; 1328 BCM_KT2_SUBPORT_TPID_UNLOCK(unit); 1329 return rv; 1330 } 1331 KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, index)--; 1332 if (0 == KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, index)) { 1333 KT2_OAM_SUBPORT_TPID_ENTRY(unit, index) = BCM_OAM_DEFAULT_TPID; 1334 rv = _bcm_kt2_oam_tpid_set(unit, tpid_type, index, 1335 BCM_OAM_DEFAULT_TPID); 1336 } 1337 BCM_KT2_SUBPORT_TPID_UNLOCK(unit); 1338 } else { 1339 return (BCM_E_PARAM); 1340 } 1341 return (rv); 1342 } 1343 1344 1345 /* 1346 * Function : 1347 * _bcm_kt2_tpid_lkup 1348 * 1349 * Purpose : 1350 * Get tpid entry index for specific tpid value. 1351 * 1352 * Parameters : 1353 * unit - (IN) BCM device number. 1354 * tpid - (IN) TPID value. 1355 * tpid_type - (IN) Type of the tpid - inner/outer/subport 1356 * index - (OUT) Entry index. 1357 * 1358 * Return : 1359 * BCM_E_XXX 1360 */ 1361 int 1362 _bcm_kt2_tpid_lkup(int unit, uint16 tpid, int tpid_type, int *index) 1363 { 1364 int i; 1365 if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 1366 for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) { 1367 if (KT2_OAM_OUTER_TPID_ENTRY(unit, i) == tpid) { 1368 *index = i; 1369 return BCM_E_NONE; 1370 } 1371 } 1372 } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 1373 for (i = 0; i < BCM_MAX_INNER_TPID_ENTRIES; i++) { 1374 if (KT2_OAM_INNER_TPID_ENTRY(unit, i) == tpid) { 1375 *index = i; 1376 return BCM_E_NONE; 1377 } 1378 } 1379 } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 1380 for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) { 1381 if (KT2_OAM_SUBPORT_TPID_ENTRY(unit, i) == tpid) { 1382 *index = i; 1383 return BCM_E_NONE; 1384 } 1385 } 1386 } 1387 return BCM_E_NOT_FOUND; 1388 } 1389 1390 /* 1391 * Function: 1392 * _bcm_kt2_tpid_entry_add 1393 * Purpose: 1394 * Add a new TPID entry. 1395 * Allocate and initialize memory to cache tpid entries. 1396 * Initialize lock for cached tpid entries. 1397 * Parameters: 1398 * unit - (IN) SOC unit number. 1399 * tpid - (IN) TPID to be added. 1400 * tpid_type - (IN) Type of the tpid - inner/outer/subport 1401 * index - (OUT) Index where the the new TPID is added. 1402 * Returns: 1403 * BCM_E_XXX 1404 * Notes: 1405 * If the same TPID already exists, simply increase the 1406 * reference count of the cached entry. Otherwise, add the entry 1407 * to the cached table and write the new entry to hardware. 1408 * Only four distinct TPID values are currently supported for 1409 * outer and subport TPID and only one value is supported for 1410 * inner tpid. 1411 */ 1412 1413 int 1414 _bcm_kt2_tpid_entry_add(int unit, uint16 tpid, int tpid_type, int *index) 1415 { 1416 int rv = BCM_E_NONE; 1417 int i, free_index; 1418 1419 free_index = -1; 1420 if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 1421 BCM_KT2_OUTER_TPID_LOCK(unit); 1422 /* Search for an existing entry. */ 1423 for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) { 1424 if (KT2_OAM_OUTER_TPID_ENTRY(unit, i) == tpid) { 1425 KT2_OAM_OUTER_TPID_REF_COUNT(unit, i)++; 1426 *index = i; 1427 BCM_KT2_OUTER_TPID_UNLOCK(unit); 1428 return rv; 1429 } 1430 } 1431 for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) { 1432 if (KT2_OAM_OUTER_TPID_REF_COUNT(unit, i) == 0) { 1433 free_index = i; 1434 break; 1435 } 1436 } 1437 if (free_index < 0) { 1438 rv = BCM_E_RESOURCE; 1439 BCM_KT2_OUTER_TPID_UNLOCK(unit); 1440 return rv; 1441 } 1442 /* Insert the new configuration into tpid table as free 1443 entry is available */ 1444 rv = _bcm_kt2_oam_tpid_set(unit, tpid_type, free_index, tpid); 1445 if (BCM_FAILURE(rv)) { 1446 BCM_KT2_OUTER_TPID_UNLOCK(unit); 1447 return rv; 1448 } 1449 KT2_OAM_OUTER_TPID_ENTRY(unit, free_index) = tpid; 1450 KT2_OAM_OUTER_TPID_REF_COUNT(unit, free_index)++; 1451 *index = free_index; 1452 BCM_KT2_OUTER_TPID_UNLOCK(unit); 1453 } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 1454 BCM_KT2_INNER_TPID_LOCK(unit); 1455 /* Search for an existing entry */ 1456 for (i = 0; i < BCM_MAX_INNER_TPID_ENTRIES; i++) { 1457 if (KT2_OAM_INNER_TPID_ENTRY(unit, i) == tpid) { 1458 KT2_OAM_INNER_TPID_REF_COUNT(unit, i)++; 1459 *index = i; 1460 BCM_KT2_INNER_TPID_UNLOCK(unit); 1461 return rv; 1462 } 1463 } 1464 for (i = 0; i < BCM_MAX_INNER_TPID_ENTRIES; i++) { 1465 if (KT2_OAM_INNER_TPID_REF_COUNT(unit, i) == 0) { 1466 free_index = i; 1467 break; 1468 } 1469 } 1470 if (free_index < 0) { 1471 rv = BCM_E_RESOURCE; 1472 BCM_KT2_INNER_TPID_UNLOCK(unit); 1473 return rv; 1474 } 1475 /* Insert the new configuration into tpid table as free 1476 entry is available */ 1477 rv = _bcm_kt2_oam_tpid_set(unit, tpid_type, free_index, tpid); 1478 if (BCM_FAILURE(rv)) { 1479 BCM_KT2_INNER_TPID_UNLOCK(unit); 1480 return rv; 1481 } 1482 KT2_OAM_INNER_TPID_ENTRY(unit, free_index) = tpid; 1483 KT2_OAM_INNER_TPID_REF_COUNT(unit, free_index)++; 1484 *index = free_index; 1485 BCM_KT2_INNER_TPID_UNLOCK(unit); 1486 } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 1487 BCM_KT2_SUBPORT_TPID_LOCK(unit); 1488 /* Search for an existing entry */ 1489 for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) { 1490 if (KT2_OAM_SUBPORT_TPID_ENTRY(unit, i) == tpid) { 1491 KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, i)++; 1492 *index = i; 1493 BCM_KT2_SUBPORT_TPID_UNLOCK(unit); 1494 return rv; 1495 } 1496 } 1497 for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) { 1498 if (KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, i) == 0) { 1499 free_index = i; 1500 break; 1501 } 1502 } 1503 if (free_index < 0) { 1504 rv = BCM_E_RESOURCE; 1505 BCM_KT2_SUBPORT_TPID_UNLOCK(unit); 1506 return rv; 1507 } 1508 /* Insert the new configuration into tpid table as free 1509 entry is available. */ 1510 rv = _bcm_kt2_oam_tpid_set(unit, tpid_type, free_index, tpid); 1511 if (BCM_FAILURE(rv)) { 1512 BCM_KT2_SUBPORT_TPID_UNLOCK(unit); 1513 return rv; 1514 } 1515 KT2_OAM_SUBPORT_TPID_ENTRY(unit, free_index) = tpid; 1516 KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, free_index)++; 1517 *index = free_index; 1518 BCM_KT2_SUBPORT_TPID_UNLOCK(unit); 1519 } else { 1520 rv = BCM_E_PARAM; 1521 } 1522 return rv; 1523 } 1524 1525 /* 1526 * Function: 1527 * _bcm_kt2_oam_ccm_msecs_to_hw_encode 1528 * Purpose: 1529 * Quanitze CCM interval from msecs to hardware encoding. 1530 * Parameters: 1531 * period - (IN) CCM interval in milli seconds. 1532 * Retruns: 1533 * Hardware encoding for the specified CCM interval value. 1534 */ 1535 STATIC int 1536 _bcm_kt2_oam_ccm_msecs_to_hw_encode(int period) 1537 { 1538 int q_period = 0; /* Quantized CCM period value. */ 1539 1540 if (0 == period) { 1541 return (q_period); 1542 } 1543 1544 /* Find closest supported period */ 1545 for (q_period = 1; _kt2_ccm_intervals[q_period] 1546 != _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED; ++q_period) { 1547 if (period < _kt2_ccm_intervals[q_period]) { 1548 break; 1549 } 1550 } 1551 1552 if (_kt2_ccm_intervals[q_period] 1553 == _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED) { 1554 /* Use the highest defined value */ 1555 --q_period; 1556 } else { 1557 if ((period - _kt2_ccm_intervals[q_period - 1]) 1558 < (_kt2_ccm_intervals[q_period] - period)) { 1559 /* Closer to the lower value */ 1560 --q_period; 1561 } 1562 } 1563 1564 return q_period; 1565 } 1566 1567 #if defined(BCM_WARM_BOOT_SUPPORT) 1568 /* 1569 * Function: 1570 * _bcm_kt2_oam_ccm_hw_encode_to_msecs 1571 * Purpose: 1572 * Get CCM interval in msecs for a given hardware encoded value. 1573 * Parameters: 1574 * encode - (IN) CCM interval hardware encoding. 1575 * Retruns: 1576 * CCM interval in msecs. 1577 */ 1578 STATIC int 1579 _bcm_kt2_oam_ccm_hw_encode_to_msecs(int encode) 1580 { 1581 return (_kt2_ccm_intervals[encode]); 1582 } 1583 #endif 1584 1585 /* 1586 * Function: 1587 * _bcm_kt2_oam_opcode_profile_entry_set 1588 * Purpose: 1589 * Program the OAM opcode control profile fields. 1590 * Parameters: 1591 * unit - (IN) BCM device number 1592 * mem - (IN) Opcode profile memory - ingress/egress 1593 * flags - (IN) Bitmap of opcode control settings. 1594 * entry - (IN/OUT) Pointer to opcode control profile table entry buffer. 1595 * Retruns: 1596 * BCM_E_XXX 1597 */ 1598 STATIC int 1599 _bcm_kt2_oam_opcode_profile_entry_set(int unit, _bcm_oam_hash_data_t *h_data_p, 1600 soc_mem_t mem, 1601 uint32 flags, 1602 void *entry) 1603 { 1604 uint32 ep_opcode; /* Endpoint opcode flag bits. */ 1605 uint32 opcode_count = 0; /* Number of bits set. */ 1606 int bp; /* bit position. */ 1607 int rv = BCM_E_NONE; /* Opreation return status. */ 1608 1609 /* Validate opcode flag bits. */ 1610 if (flags & ~(_BCM_KT2_OAM_OPCODE_MASK)) { 1611 return (BCM_E_PARAM); 1612 } 1613 1614 /* Get number of valid opcodes supported. */ 1615 opcode_count = _shr_popcount(_BCM_KT2_OAM_OPCODE_MASK); 1616 1617 /* 1618 * Iterate over opcode flag bits and set corresponding fields 1619 * in entry buffer. 1620 */ 1621 for (bp = 0; bp < opcode_count; bp++) { 1622 ep_opcode = (flags & (1 << bp)); 1623 1624 switch (ep_opcode) { 1625 case BCM_OAM_OPCODE_CCM_COPY_TO_CPU: 1626 soc_mem_field32_set(unit, mem, entry, CCM_COPYTO_CPUf, 1); 1627 break; 1628 1629 case BCM_OAM_OPCODE_CCM_IN_HW: 1630 soc_mem_field32_set(unit, mem, entry, CCM_PROCESS_IN_HWf, 1); 1631 break; 1632 1633 case BCM_OAM_OPCODE_CCM_DROP: 1634 soc_mem_field32_set(unit, mem, entry, CCM_DROPf, 1); 1635 break; 1636 1637 case BCM_OAM_OPCODE_LBM_IN_HW: 1638 soc_mem_field32_set(unit, mem, entry, LBM_ACTIONf, 1); 1639 break; 1640 1641 case BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU: 1642 soc_mem_field32_set(unit, mem, entry, LBM_UC_COPYTO_CPUf, 1); 1643 break; 1644 1645 case BCM_OAM_OPCODE_LBM_UC_DROP: 1646 soc_mem_field32_set(unit, mem, entry, LBM_UC_DROPf, 1); 1647 break; 1648 1649 case BCM_OAM_OPCODE_LBM_MC_DROP: 1650 soc_mem_field32_set(unit, mem, entry, LBM_MC_DROPf, 1); 1651 break; 1652 1653 case BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU: 1654 soc_mem_field32_set(unit, mem, entry, LBM_MC_COPYTO_CPUf, 1); 1655 break; 1656 1657 case BCM_OAM_OPCODE_LBR_COPY_TO_CPU: 1658 soc_mem_field32_set(unit, mem, entry, LBR_COPYTO_CPUf, 1); 1659 break; 1660 1661 case BCM_OAM_OPCODE_LBR_DROP: 1662 soc_mem_field32_set(unit, mem, entry, LBR_DROPf, 1); 1663 break; 1664 1665 case BCM_OAM_OPCODE_LTM_COPY_TO_CPU: 1666 soc_mem_field32_set(unit, mem, entry, LTM_COPYTO_CPUf, 1); 1667 break; 1668 1669 case BCM_OAM_OPCODE_LTM_DROP: 1670 soc_mem_field32_set(unit, mem, entry, LTM_DROPf, 1); 1671 break; 1672 1673 case BCM_OAM_OPCODE_LTR_COPY_TO_CPU: 1674 soc_mem_field32_set(unit, mem, entry, LTR_COPYTO_CPUf, 1); 1675 break; 1676 1677 case BCM_OAM_OPCODE_LTR_DROP: 1678 soc_mem_field32_set(unit, mem, entry, LTR_DROPf, 1); 1679 break; 1680 1681 case BCM_OAM_OPCODE_LMEP_PKT_FWD: 1682 soc_mem_field32_set(unit, mem, entry, FWD_LMEP_PKTf, 1); 1683 break; 1684 1685 case BCM_OAM_OPCODE_OTHER_COPY_TO_CPU: 1686 soc_mem_field32_set(unit, mem, entry, 1687 OTHER_OPCODE_GROUP_1_UC_MY_STATION_MISS_COPYTO_CPUf, 1); 1688 soc_mem_field32_set (unit, mem, entry, 1689 OTHER_OPCODE_GROUP_1_UC_MY_STATION_HIT_COPYTO_CPUf, 1); 1690 soc_mem_field32_set (unit, mem, entry, 1691 OTHER_OPCODE_GROUP_1_LOW_MDL_COPYTO_CPUf, 1); 1692 soc_mem_field32_set (unit, mem, entry, 1693 OTHER_OPCODE_GROUP_1_MC_COPYTO_CPUf, 1); 1694 soc_mem_field32_set(unit, mem, entry, 1695 OTHER_OPCODE_GROUP_2_UC_MY_STATION_MISS_COPYTO_CPUf, 1); 1696 soc_mem_field32_set (unit, mem, entry, 1697 OTHER_OPCODE_GROUP_2_UC_MY_STATION_HIT_COPYTO_CPUf, 1); 1698 soc_mem_field32_set (unit, mem, entry, 1699 OTHER_OPCODE_GROUP_2_LOW_MDL_COPYTO_CPUf, 1); 1700 soc_mem_field32_set (unit, mem, entry, 1701 OTHER_OPCODE_GROUP_2_MC_COPYTO_CPUf, 1); 1702 break; 1703 1704 case BCM_OAM_OPCODE_OTHER_DROP: 1705 soc_mem_field32_set(unit, mem, entry, 1706 OTHER_OPCODE_GROUP_1_UC_MY_STATION_MISS_ACTIONf, 1); 1707 soc_mem_field32_set(unit, mem, entry, 1708 OTHER_OPCODE_GROUP_1_UC_MY_STATION_HIT_ACTIONf, 1); 1709 soc_mem_field32_set(unit, mem, entry, 1710 OTHER_OPCODE_GROUP_1_LOW_MDL_ACTIONf, 1); 1711 soc_mem_field32_set(unit, mem, entry, 1712 OTHER_OPCODE_GROUP_1_MC_ACTIONf, 1); 1713 soc_mem_field32_set(unit, mem, entry, 1714 OTHER_OPCODE_GROUP_2_UC_MY_STATION_MISS_ACTIONf, 1); 1715 soc_mem_field32_set(unit, mem, entry, 1716 OTHER_OPCODE_GROUP_2_UC_MY_STATION_HIT_ACTIONf, 1); 1717 soc_mem_field32_set(unit, mem, entry, 1718 OTHER_OPCODE_GROUP_2_LOW_MDL_ACTIONf, 1); 1719 soc_mem_field32_set(unit, mem, entry, 1720 OTHER_OPCODE_GROUP_2_MC_ACTIONf, 1); 1721 break; 1722 1723 default: 1724 break; 1725 } 1726 } 1727 if (_BCM_OAM_EP_IS_MIP(h_data_p)) { 1728 soc_mem_field32_set(unit, mem, entry, LOW_MDL_CCM_FWD_ACTIONf, 0); 1729 soc_mem_field32_set(unit, mem, entry, LOW_MDL_LB_LT_DROPf, 0); 1730 soc_mem_field32_set(unit, mem, entry, LB_LT_UC_MY_STATION_MISS_DROPf, 0); 1731 } else { 1732 /* Set the opcode action values of the newly introduced CFM opcode actions 1733 to values that match with the legacy behavior for these opcodes */ 1734 /* LOW MDL CCM / LB/LT drop and LB/LT my station miss drop */ 1735 soc_mem_field32_set(unit, mem, entry, LOW_MDL_CCM_FWD_ACTIONf, 2); 1736 soc_mem_field32_set(unit, mem, entry, LOW_MDL_LB_LT_DROPf, 1); 1737 soc_mem_field32_set(unit, mem, entry, LB_LT_UC_MY_STATION_MISS_DROPf, 1); 1738 } 1739 return rv; 1740 } 1741 1742 1743 /* 1744 * Function: 1745 * _bcm_kt2_oam_opcode_profile_entry_init 1746 * Purpose: 1747 * Setup default OAM opcode control profile settings for MEP. 1748 * Parameters: 1749 * unit - (IN) BCM device number 1750 * mem - (IN) Opcode profile memory - ingress/egress 1751 * entry - (IN/OUT) Pointer to opcode control profile table entry buffer. 1752 * Retruns: 1753 * BCM_E_XXX 1754 */ 1755 int 1756 _bcm_kt2_oam_opcode_profile_entry_init(int unit, soc_mem_t mem, 1757 void *entry) 1758 { 1759 uint32 opcode; /* Opcode flag bits. */ 1760 int rv; /* Operation return status. */ 1761 1762 _bcm_oam_hash_data_t h_data; 1763 sal_memset(&h_data, 0, sizeof(_bcm_oam_hash_data_t)); 1764 1765 h_data.type = bcmOAMEndpointTypeEthernet; 1766 1767 opcode = (BCM_OAM_OPCODE_CCM_COPY_TO_CPU | 1768 BCM_OAM_OPCODE_CCM_DROP | 1769 BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU | 1770 BCM_OAM_OPCODE_LBM_UC_DROP | 1771 BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU | 1772 BCM_OAM_OPCODE_LBM_MC_DROP | 1773 BCM_OAM_OPCODE_LBR_COPY_TO_CPU | 1774 BCM_OAM_OPCODE_LBR_DROP | 1775 BCM_OAM_OPCODE_LTM_COPY_TO_CPU | 1776 BCM_OAM_OPCODE_LTM_DROP | 1777 BCM_OAM_OPCODE_LTR_COPY_TO_CPU | 1778 BCM_OAM_OPCODE_LTR_DROP | 1779 BCM_OAM_OPCODE_OTHER_COPY_TO_CPU | 1780 BCM_OAM_OPCODE_OTHER_DROP 1781 ); 1782 1783 rv = _bcm_kt2_oam_opcode_profile_entry_set(unit, &h_data, mem, opcode, entry); 1784 return rv; 1785 } 1786 1787 /* 1788 * Function: 1789 * _bcm_kt2_oam_mip_opcode_profile_entry_init 1790 * Purpose: 1791 * Setup default OAM opcode control profile settings for MIP. 1792 * Parameters: 1793 * unit - (IN) BCM device number 1794 * mem - (IN) Opcode profile memory - ingress/egress 1795 * entry - (IN/OUT) Pointer to opcode control profile table entry buffer. 1796 * Retruns: 1797 * BCM_E_XXX 1798 */ 1799 int 1800 _bcm_kt2_oam_mip_opcode_profile_entry_init(int unit, soc_mem_t mem, 1801 void *entry) 1802 { 1803 uint32 opcode; /* Opcode flag bits. */ 1804 int rv; /* Operation return status. */ 1805 1806 _bcm_oam_hash_data_t h_data; 1807 sal_memset(&h_data, 0, sizeof(_bcm_oam_hash_data_t)); 1808 1809 h_data.flags |= BCM_OAM_ENDPOINT_INTERMEDIATE; 1810 h_data.type = bcmOAMEndpointTypeEthernet; 1811 opcode = (BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU | 1812 BCM_OAM_OPCODE_LBM_UC_DROP | 1813 BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU | 1814 BCM_OAM_OPCODE_LBM_MC_DROP | 1815 BCM_OAM_OPCODE_LTM_COPY_TO_CPU | 1816 BCM_OAM_OPCODE_LTM_DROP); 1817 1818 rv = _bcm_kt2_oam_opcode_profile_entry_set(unit, &h_data, mem, opcode, entry); 1819 return rv; 1820 } 1821 1822 /* 1823 * Function: 1824 * _bcm_kt2_oam_opcode_group_init 1825 * Purpose: 1826 * Init ingress and egress OAM opcode groups. 1827 * Parameters: 1828 * unit - (IN) BCM device number 1829 * Retruns: 1830 * BCM_E_XXX 1831 */ 1832 int 1833 _bcm_kt2_oam_opcode_group_init(int unit) 1834 { 1835 int rv = BCM_E_NONE; 1836 ingress_oam_opcode_group_entry_t *opcode_grp_buf; 1837 ingress_oam_opcode_group_entry_t *opcode_grp_entry; 1838 int entry_mem_size; /* Size of table entry. */ 1839 int index_max = 0; 1840 int index = 0; 1841 bcm_oam_endpoint_action_t action; 1842 BCM_OAM_ACTION_CLEAR_ALL(action); 1843 BCM_OAM_OPCODE_CLEAR_ALL(action); 1844 1845 /* Set ingress and egress OAM opcode group */ 1846 entry_mem_size = sizeof(ingress_oam_opcode_group_entry_t); 1847 /* Allocate buffer to store the DMAed table entries. */ 1848 index_max = soc_mem_index_max(unit, INGRESS_OAM_OPCODE_GROUPm); 1849 opcode_grp_buf = soc_cm_salloc(unit, entry_mem_size * (index_max + 1), 1850 "Opcode group entry buffer"); 1851 if (NULL == opcode_grp_buf) { 1852 return (BCM_E_MEMORY); 1853 } 1854 /* Initialize the entry buffer. */ 1855 sal_memset(opcode_grp_buf, 0, sizeof(entry_mem_size) * (index_max + 1)); 1856 1857 for (index = 0; index <= index_max; index++) { 1858 opcode_grp_entry = soc_mem_table_idx_to_pointer 1859 (unit, INGRESS_OAM_OPCODE_GROUPm, 1860 ingress_oam_opcode_group_entry_t *, 1861 opcode_grp_buf, index); 1862 if (index <= _BCM_OAM_OPCODE_TYPE_LTM) { 1863 /* For CFM packets group valid = 0 */ 1864 soc_mem_field32_set(unit, INGRESS_OAM_OPCODE_GROUPm, 1865 (uint32 *)opcode_grp_entry, OPCODE_GROUP_VALIDf, 0); 1866 } else { 1867 /* For Non-CFM packets group valid = 1 and group is opcode group 1*/ 1868 soc_mem_field32_set(unit, INGRESS_OAM_OPCODE_GROUPm, 1869 (uint32 *)opcode_grp_entry, OPCODE_GROUP_VALIDf, 1); 1870 soc_mem_field32_set(unit, INGRESS_OAM_OPCODE_GROUPm, 1871 (uint32 *)opcode_grp_entry, OPCODE_GROUPf, 0); 1872 } 1873 } 1874 rv = soc_mem_write_range(unit, INGRESS_OAM_OPCODE_GROUPm, 1875 MEM_BLOCK_ALL, 0, index_max, opcode_grp_buf); 1876 if (BCM_FAILURE(rv)) { 1877 if (opcode_grp_buf) { 1878 soc_cm_sfree(unit, opcode_grp_buf); 1879 } 1880 return rv; 1881 } 1882 rv = soc_mem_write_range(unit, EGR_OAM_OPCODE_GROUPm, 1883 MEM_BLOCK_ALL, 0, index_max, opcode_grp_buf); 1884 if (BCM_FAILURE(rv)) { 1885 if (opcode_grp_buf) { 1886 soc_cm_sfree(unit, opcode_grp_buf); 1887 } 1888 return rv; 1889 } 1890 if (opcode_grp_buf) { 1891 soc_cm_sfree(unit, opcode_grp_buf); 1892 } 1893 return (rv); 1894 } 1895 1896 STATIC void 1897 _bcm_kt2_oam_get_passive_mdl_from_active_mdl(int unit, uint8 active_mdl, 1898 int ma_base_index, 1899 uint8 *passive_mdl, 1900 int is_upmep) 1901 { 1902 uint32 mdl_value[1] = { 0 }; 1903 int ma_offset = 0; 1904 int mdl = 0; 1905 bcm_oam_endpoint_t ep_id_at_mdl = _BCM_OAM_INVALID_INDEX; 1906 _bcm_oam_control_t *oc = NULL; 1907 _bcm_oam_hash_data_t *h_data_p = NULL; 1908 1909 /* coverity[check_return] */ 1910 _bcm_kt2_oam_control_get(unit, &oc); 1911 1912 if (oc == NULL) { 1913 /* Not expected */ 1914 return; 1915 } 1916 1917 /* Initialize passive_mdl to 0 */ 1918 *passive_mdl = 0; 1919 mdl_value[0] = active_mdl; 1920 1921 for (mdl = 0; mdl <= 7; mdl++) { 1922 if (SHR_BITGET(mdl_value, mdl)) { 1923 ep_id_at_mdl = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_get(oc, 1924 _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX 1925 (ma_base_index, ma_offset, is_upmep)); 1926 if (ep_id_at_mdl != _BCM_OAM_INVALID_INDEX) { 1927 h_data_p = &(oc->oam_hash_data[ep_id_at_mdl]); 1928 /* Set the passive bitmap only if it is not a MIP */ 1929 if (!_BCM_OAM_EP_IS_MIP(h_data_p)) { 1930 *passive_mdl = (1 << mdl) | ((1 << mdl) -1); 1931 } 1932 } else { 1933 /* Log an error. Ideally should not happen. */ 1934 LOG_ERROR(BSL_LS_BCM_OAM, 1935 (BSL_META_U(unit, 1936 "OAM(unit %d) Error: EP ID mapping get failed (MA_IDX=%d) -" 1937 "\n"), unit, ma_base_index+ma_offset)); 1938 } 1939 ma_offset++; 1940 } 1941 } 1942 } 1943 1944 1945 1946 /* 1947 * Function: 1948 * _bcm_kt2_oam_ep_hash_key_construct 1949 * Purpose: 1950 * Construct hash table key for a given endpoint information. 1951 * Parameters: 1952 * unit - (IN) BCM device number 1953 * oc - (IN) Pointer to OAM control structure. 1954 * ep_info - (IN) Pointer to endpoint information structure. 1955 * key - (IN/OUT) Pointer to hash key buffer. 1956 * Retruns: 1957 * None 1958 */ 1959 STATIC void 1960 _bcm_kt2_oam_ep_hash_key_construct(int unit, 1961 _bcm_oam_control_t *oc, 1962 bcm_oam_endpoint_info_t *ep_info, 1963 _bcm_oam_hash_key_t *key) 1964 { 1965 uint8 *loc = *key; 1966 uint32 direction = 0; 1967 1968 sal_memset(key, 0, sizeof(_bcm_oam_hash_key_t)); 1969 1970 if (NULL != ep_info) { 1971 if ((ep_info->flags & BCM_OAM_ENDPOINT_UP_FACING)) { 1972 direction = 1; 1973 } 1974 1975 _BCM_OAM_KEY_PACK(loc, &ep_info->group, sizeof(ep_info->group)); 1976 1977 _BCM_OAM_KEY_PACK(loc, &ep_info->name, sizeof(ep_info->name)); 1978 1979 _BCM_OAM_KEY_PACK(loc, &ep_info->gport, sizeof(ep_info->gport)); 1980 1981 _BCM_OAM_KEY_PACK(loc, &ep_info->level, sizeof(ep_info->level)); 1982 1983 _BCM_OAM_KEY_PACK(loc, &ep_info->vlan, sizeof(ep_info->vlan)); 1984 1985 _BCM_OAM_KEY_PACK(loc, &ep_info->inner_vlan, 1986 sizeof(ep_info->inner_vlan)); 1987 _BCM_OAM_KEY_PACK(loc, &direction, sizeof(direction)); 1988 } 1989 1990 /* End address should not exceed size of _bcm_oam_hash_key_t. */ 1991 assert ((int) (loc - *key) <= sizeof(_bcm_oam_hash_key_t)); 1992 } 1993 1994 /* 1995 * Function: 1996 * _bcm_oam_egr_lmep_key_construct 1997 * Purpose: 1998 * Construct egress MP group table lookup key for a given endpoint. 1999 * Parameters: 2000 * unit - (IN) BCM device number 2001 * h_data_p - (IN) Pointer to endpoint hash data memory. 2002 * egr_mp_grp_key_p - (IN/OUT) Pointer to entry buffer. 2003 * Retruns: 2004 * None 2005 */ 2006 STATIC void 2007 _bcm_oam_egr_lmep_key_construct(int unit, 2008 const _bcm_oam_hash_data_t *h_data_p, 2009 egr_mp_group_entry_t *egr_mp_grp_key_p) 2010 { 2011 _bcm_oam_control_t *oc = NULL; 2012 2013 /* coverity[check_return] */ 2014 _bcm_kt2_oam_control_get(unit, &oc); 2015 2016 /* Set the valid bit. */ 2017 soc_EGR_MP_GROUPm_field32_set 2018 (unit, egr_mp_grp_key_p, VALIDf, 1); 2019 /* Set the search key type. */ 2020 soc_EGR_MP_GROUPm_field32_set 2021 (unit, egr_mp_grp_key_p, KEY_TYPEf, h_data_p->oam_domain); 2022 2023 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_BHH) { 2024 2025 /* Set port type status in the search key. */ 2026 if (_BCM_OAM_EP_IS_VP_TYPE(h_data_p)) { 2027 2028 /* DGLP field contains virtual port. */ 2029 soc_EGR_MP_GROUPm_field32_set 2030 (unit, egr_mp_grp_key_p, DGLPf, h_data_p->vp); 2031 2032 } else { 2033 if (oc->eth_oam_mp_group_vlan_key == 2034 _BCM_KT2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT) { 2035 /* In earlier versions of the SDK, both inner & outer vlan was 2036 * always programmed in the MP_GROUP irrespective of the MEP 2037 * type, this has been changed to program only CVLAN for CVLAN 2038 * MEPs and SVLAN for SVLAN MEPs. To avoid breaking warm-upgrade 2039 * the old scheme is still supported. 2040 */ 2041 soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p, 2042 SVIDf, h_data_p->vlan); 2043 2044 soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p, 2045 CVIDf, h_data_p->inner_vlan); 2046 } else { 2047 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_CVLAN) { 2048 /* SVLAN/C+SVLAN */ 2049 soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p, 2050 SVIDf, h_data_p->vlan); 2051 } 2052 2053 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_SVLAN) { 2054 /* CLVAN/C+SVLAN */ 2055 soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p, 2056 CVIDf, h_data_p->inner_vlan); 2057 } 2058 } 2059 /* DGLP contains generic logical port. */ 2060 soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p, 2061 DGLPf, h_data_p->dglp); 2062 } 2063 } 2064 #if defined(INCLUDE_BHH) 2065 else { 2066 2067 /* BHH Domain, Key = Next Hop Index 2068 BHH API have been using L3_EGRESS type in 2069 bcm_oam_endpoint_info_t.intf field. 2070 However for supporting LM/DM on Katana2 this should be DVP_EGRESS type, 2071 only CCM will work with L3_EGRESS type, retaining the old type for 2072 backward compatibility */ 2073 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, h_data_p->egress_if)) { 2074 soc_EGR_MP_GROUPm_field32_set (unit, egr_mp_grp_key_p, NHIf, 2075 h_data_p->egress_if - BCM_XGS3_EGRESS_IDX_MIN(unit)); 2076 } else { 2077 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, h_data_p->egress_if)) { 2078 soc_EGR_MP_GROUPm_field32_set (unit, egr_mp_grp_key_p, NHIf, 2079 h_data_p->egress_if - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit)); 2080 } 2081 } 2082 } 2083 #endif 2084 2085 } 2086 2087 /* 2088 * Function: 2089 * _bcm_kt2_oam_lmep_key_construct 2090 * Purpose: 2091 * Construct LMEP view lookup key for a given endpoint. 2092 * Parameters: 2093 * unit - (IN) BCM device number 2094 * h_data_p - (IN) Pointer to endpoint hash data memory. 2095 * l3_key_p - (IN/OUT) Pointer to entry buffer. 2096 * Retruns: 2097 * None 2098 */ 2099 STATIC void 2100 _bcm_kt2_oam_lmep_key_construct(int unit, 2101 const _bcm_oam_hash_data_t *h_data_p, 2102 l3_entry_1_entry_t *l3_key_p) 2103 { 2104 _bcm_oam_control_t *oc = NULL; 2105 2106 /* coverity[check_return] */ 2107 _bcm_kt2_oam_control_get(unit, &oc); 2108 2109 /* Set the search key type. */ 2110 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 2111 (unit, l3_key_p, KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_LMEP); 2112 2113 /* Set the search key sub type. */ 2114 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 2115 (unit, l3_key_p, LMEP__OAM_LMEP_KEY_SUBTYPEf, 2116 h_data_p->oam_domain); 2117 2118 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_BHH) { 2119 2120 /* Set port type status in the search key. */ 2121 if (_BCM_OAM_EP_IS_VP_TYPE(h_data_p)) { 2122 /* SGLP field contains virtual port. */ 2123 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 2124 (unit, l3_key_p, LMEP__SGLPf, h_data_p->vp); 2125 2126 } else { 2127 if (oc->eth_oam_mp_group_vlan_key == 2128 _BCM_KT2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT) { 2129 /* In earlier versions of the SDK, both inner & outer vlan was 2130 * always programmed in the MP_GROUP irrespective of the MEP 2131 * type, this has been changed to program only CVLAN for CVLAN 2132 * MEPs and SVLAN for SVLAN MEPs. To avoid breaking warm-upgrade 2133 * the old scheme is still supported. 2134 */ 2135 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, LMEP__SVIDf, 2136 h_data_p->vlan); 2137 2138 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, LMEP__CVIDf, 2139 h_data_p->inner_vlan); 2140 } else { 2141 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_CVLAN) { 2142 /* SVLAN/C+SVLAN */ 2143 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, 2144 LMEP__SVIDf, 2145 h_data_p->vlan); 2146 } 2147 2148 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_SVLAN) { 2149 /* CLVAN/C+SVLAN */ 2150 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, 2151 LMEP__CVIDf, 2152 h_data_p->inner_vlan); 2153 } 2154 } 2155 /* SGLP contains generic logical port. */ 2156 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, LMEP__SGLPf, 2157 h_data_p->sglp); 2158 2159 } 2160 } 2161 #if defined(INCLUDE_BHH) 2162 else { 2163 2164 /* If the label is not global, set port */ 2165 if (bcm_tr_mpls_port_independent_range(unit, h_data_p->label, 2166 BCM_GPORT_INVALID) != BCM_E_NONE) { 2167 /* SGLP contains generic logical port. */ 2168 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 2169 (unit, l3_key_p, LMEP__SGLPf, h_data_p->sglp); 2170 } else { 2171 /* SGLP contains generic logical port. */ 2172 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 2173 (unit, l3_key_p, LMEP__SGLPf, 0xFFFF); 2174 2175 } 2176 2177 /* Set incoming MPLS Label */ 2178 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 2179 (unit, l3_key_p, LMEP__MPLS_LABELf, h_data_p->label); 2180 2181 } 2182 #endif 2183 } 2184 2185 /* 2186 * Function: 2187 * _bcm_kt2_oam_rmep_key_construct 2188 * Purpose: 2189 * Construct RMEP view lookup key for a given endpoint. 2190 * Parameters: 2191 * unit - (IN) BCM device number 2192 * h_data_p - (IN) Pointer to endpoint hash data memory. 2193 * l3_key_p - (IN/OUT) Pointer to entry buffer. 2194 * Retruns: 2195 * None 2196 */ 2197 STATIC void 2198 _bcm_kt2_oam_rmep_key_construct(int unit, 2199 const _bcm_oam_hash_data_t *h_data_p, 2200 l3_entry_1_entry_t *l3_key_p) 2201 { 2202 2203 /* Set the search key type. */ 2204 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 2205 (unit, l3_key_p, KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_RMEP); 2206 2207 /* Set endpoint name. */ 2208 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 2209 (unit, l3_key_p, RMEP__MEPIDf, h_data_p->name); 2210 2211 /* Set MA_PTR */ 2212 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 2213 (unit, l3_key_p, RMEP__MA_PTRf, h_data_p->group_index); 2214 2215 } 2216 2217 #if defined(KEY_PRINT) 2218 /* 2219 * Function: 2220 * _bcm_oam_hash_key_print 2221 * Purpose: 2222 * Print the contents of a hash key buffer. 2223 * Parameters: 2224 * hash_key - (IN) Pointer to hash key buffer. 2225 * Retruns: 2226 * None 2227 */ 2228 STATIC void 2229 _bcm_oam_hash_key_print(_bcm_oam_hash_key_t *hash_key) 2230 { 2231 int i; 2232 LOG_CLI((BSL_META_U(unit, 2233 "HASH KEY:"))); 2234 for(i = 0; i < _OAM_HASH_KEY_SIZE; i++) { 2235 LOG_CLI((BSL_META_U(unit, 2236 ":%u"), *(hash_key[i]))); 2237 } 2238 LOG_CLI((BSL_META_U(unit, 2239 "\n"))); 2240 } 2241 #endif 2242 2243 /* 2244 * Function: 2245 * _bcm_kt2_oam_control_get 2246 * Purpose: 2247 * Lookup a OAM control config from a bcm device id. 2248 * Parameters: 2249 * unit - (IN)BCM unit number. 2250 * oc - (OUT) OAM control structure. 2251 * Retruns: 2252 * BCM_E_XXX 2253 */ 2254 STATIC int 2255 _bcm_kt2_oam_control_get(int unit, _bcm_oam_control_t **oc) 2256 { 2257 if (NULL == oc) { 2258 return (BCM_E_PARAM); 2259 } 2260 2261 /* Ensure oam module is initialized. */ 2262 _BCM_OAM_IS_INIT(unit); 2263 2264 *oc = _kt2_oam_control[unit]; 2265 2266 return (BCM_E_NONE); 2267 } 2268 2269 /* 2270 * Function: 2271 * _bcm_kt2_oam_group_endpoint_count_init 2272 * Purpose: 2273 * Retrieves and initializes endpoint count information for this device. 2274 * Parameters: 2275 * unit - (IN) BCM unit number. 2276 * oc - (IN) Pointer to device OAM control structure. 2277 * Retruns: 2278 * BCM_E_XXX 2279 */ 2280 STATIC int 2281 _bcm_kt2_oam_group_endpoint_count_init(int unit, _bcm_oam_control_t *oc) 2282 { 2283 /* Input parameter check. */ 2284 if (NULL == oc) { 2285 return (BCM_E_PARAM); 2286 } 2287 2288 /* 2289 * Get endpoint hardware table index count values and 2290 * initialize device OAM control structure members variables. 2291 */ 2292 oc->rmep_count = soc_mem_index_count(unit, RMEPm); 2293 oc->lmep_count = soc_mem_index_count(unit, LMEPm); 2294 oc->ma_idx_count = soc_mem_index_count(unit, MA_INDEXm); 2295 oc->egr_ma_idx_count = soc_mem_index_count(unit, EGR_MA_INDEXm); 2296 2297 /* Max number of endpoints supported by the device. */ 2298 oc->ep_count = (oc->rmep_count + oc->lmep_count + oc->ma_idx_count + 2299 oc->egr_ma_idx_count); 2300 2301 LOG_VERBOSE(BSL_LS_BCM_OAM, 2302 (BSL_META_U(unit, 2303 "OAM Info: Total No. endpoint Count = %d.\n"), 2304 oc->ep_count)); 2305 2306 /* Max number of MA Groups supported by device. */ 2307 oc->group_count = soc_mem_index_count(unit, MA_STATEm); 2308 LOG_VERBOSE(BSL_LS_BCM_OAM, 2309 (BSL_META_U(unit, 2310 "OAM Info: Total No. Group Count = %d.\n"), 2311 oc->group_count)); 2312 2313 oc->lm_counter_cnt = soc_mem_index_count(unit, OAM_LM_COUNTERS_0m); 2314 return (BCM_E_NONE); 2315 } 2316 2317 /* 2318 * Function: 2319 * _bcm_kt2_oam_ccm_rx_timeout_enable 2320 * Purpose: 2321 * Enable CCM Timer operations for endpoint state table. 2322 * Parameters: 2323 * unit - (IN) BCM unit number. 2324 * state - (IN) Enable/Disable. 2325 * Retruns: 2326 * BCM_E_XXX 2327 * Note: 2328 * RMEP_MA_STATE_REFRESH_INDEXr - CPU access for debug only. 2329 */ 2330 STATIC int 2331 _bcm_kt2_oam_ccm_rx_timeout_set(int unit, uint8 state) 2332 { 2333 int rv; /* Opreation return status. */ 2334 uint32 rval = 0; /* Register value. */ 2335 2336 /* Enable timer instructions to RMEP/MA_STATE Table. */ 2337 soc_reg_field_set(unit, OAM_TIMER_CONTROLr, &rval, 2338 TIMER_ENABLEf, state ? 1 : 0); 2339 2340 /* Set Clock granularity to 250us ticks - 1. */ 2341 soc_reg_field_set(unit, OAM_TIMER_CONTROLr, &rval, 2342 CLK_GRANf, 1); 2343 2344 rv = WRITE_OAM_TIMER_CONTROLr(unit, rval); 2345 if (BCM_FAILURE(rv)) { 2346 LOG_ERROR(BSL_LS_BCM_OAM, 2347 (BSL_META_U(unit, 2348 "OAM Error: Timer enable - Failed.\n"))); 2349 return (rv); 2350 } 2351 2352 return (rv); 2353 } 2354 2355 /* 2356 * Function: 2357 * _bcm_kt2_oam_ccm_tx_config_enable 2358 * Purpose: 2359 * Enable transmission of OAM PDUs on local endpoint. 2360 * Parameters: 2361 * unit - (IN) BCM unit number. 2362 * state - (IN) Enable/Disable 2363 * Retruns: 2364 * BCM_E_XXX 2365 */ 2366 STATIC int 2367 _bcm_kt2_oam_ccm_tx_config_set(int unit, uint8 state) 2368 { 2369 int rv; /* Opreation return status. */ 2370 uint32 rval = 0; /* Register value. */ 2371 2372 /* Enable OAM LMEP Tx. */ 2373 soc_reg_field_set(unit, OAM_TX_CONTROLr, &rval, 2374 TX_ENABLEf, state ? 1 : 0); 2375 2376 /* Enable CMIC buffer. */ 2377 soc_reg_field_set(unit, OAM_TX_CONTROLr, &rval, 2378 CMIC_BUF_ENABLEf, state ? 1 : 0); 2379 2380 rv = WRITE_OAM_TX_CONTROLr(unit, rval); 2381 if (BCM_FAILURE(rv)) { 2382 LOG_ERROR(BSL_LS_BCM_OAM, 2383 (BSL_META_U(unit, 2384 "OAM Error: Tx config enable - Failed.\n"))); 2385 } 2386 return (rv); 2387 } 2388 2389 /* 2390 * Function: 2391 * _bcm_kt2_oam_misc_config 2392 * Purpose: 2393 * Miscellaneous OAM configurations: 2394 * 1. Enable IFP lookup on the CPU port. 2395 * Parameters: 2396 * unit - (IN) BCM unit number. 2397 * Retruns: 2398 * BCM_E_XXX 2399 */ 2400 STATIC int 2401 _bcm_kt2_oam_misc_config(int unit) 2402 { 2403 int rv; /* Opreation return status. */ 2404 2405 /* 2406 * Enable ingress FP for CPU port so LM/DM packets sent from CPU 2407 * can be processed. 2408 */ 2409 rv = bcm_esw_port_control_set(unit, CMIC_PORT(unit), 2410 bcmPortControlFilterIngress, 1); 2411 if (BCM_FAILURE(rv)) { 2412 LOG_ERROR(BSL_LS_BCM_OAM, 2413 (BSL_META_U(unit, 2414 "OAM Error: bcm_esw_port_control_set" 2415 " - Failed.\n"))); 2416 return (rv); 2417 } 2418 return (rv); 2419 2420 } 2421 2422 /* 2423 * Function: 2424 * _bcm_kt2_oam_profile_tables_init 2425 * Purpose: 2426 * Create ingress and egress service priority mapping profile table and 2427 * setup a default profile. Create Ingress and egress OAM opcode control 2428 * profile table, dglp profile 2429 * Parameters: 2430 * unit - (IN) BCM unit number. 2431 * oc - (IN) Pointer to OAM control structure. 2432 * Retruns: 2433 * BCM_E_XXX 2434 */ 2435 STATIC int 2436 _bcm_kt2_oam_profile_tables_init(int unit, _bcm_oam_control_t *oc) 2437 { 2438 int rv = BCM_E_NONE;/* Opreation return status. */ 2439 soc_mem_t mem; /* Profiled table memory. */ 2440 int entry_words; /* Profile table word size. */ 2441 int pri; /* Priority */ 2442 void *entries[1]; /* Profile entry. */ 2443 uint32 profile_index; /* Profile table index. */ 2444 ing_service_pri_map_entry_t pri_ent[BCM_OAM_INTPRI_MAX]; /* ing profile */ 2445 /* entry */ 2446 egr_service_pri_map_entry_t egr_pri_ent[BCM_OAM_INTPRI_MAX]; /*egr profile*/ 2447 /* entry */ 2448 bcm_module_t modid; 2449 uint32 dglp = 0; 2450 egr_oam_dglp_profile_entry_t egr_dglp_profile_entry; 2451 ing_oam_dglp_profile_entry_t ing_dglp_profile_entry; 2452 oam_opcode_control_profile_entry_t opcode_entry; /* Opcode control 2453 profile entry. */ 2454 egr_oam_opcode_control_profile_entry_t egr_opcode_entry; 2455 2456 /* Ingress Service Priority Map profile table initialization. */ 2457 soc_profile_mem_t_init(&oc->ing_service_pri_map); 2458 2459 entry_words = (sizeof(ing_service_pri_map_entry_t) / sizeof(uint32)); 2460 2461 mem = ING_SERVICE_PRI_MAPm; 2462 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 2463 &oc->ing_service_pri_map); 2464 if (BCM_FAILURE(rv)) { 2465 LOG_ERROR(BSL_LS_BCM_OAM, 2466 (BSL_META_U(unit, 2467 "OAM Error: service map profile - Failed.\n"))); 2468 return (rv); 2469 } 2470 if (!SOC_WARM_BOOT(unit)) { 2471 /* 2472 * Initialize ingress priority map profile table. 2473 * All priorities priorities map to priority:'0'. 2474 */ 2475 for (pri = 0; pri < BCM_OAM_INTPRI_MAX; pri++) 2476 { 2477 /* Clear ingress service pri map profile entry. */ 2478 sal_memcpy(&pri_ent[pri], soc_mem_entry_null(unit, mem), 2479 soc_mem_entry_words(unit, mem) * sizeof(uint32)); 2480 2481 if (SOC_MEM_FIELD_VALID(unit, mem, OFFSET_VALIDf)) { 2482 soc_mem_field32_set(unit, mem, &pri_ent[pri], OFFSET_VALIDf, 1); 2483 } 2484 } 2485 2486 2487 entries[0] = &pri_ent; 2488 rv = soc_profile_mem_add(unit, &oc->ing_service_pri_map, 2489 (void *)entries, BCM_OAM_INTPRI_MAX, 2490 &profile_index); 2491 if (BCM_FAILURE(rv)) { 2492 LOG_ERROR(BSL_LS_BCM_OAM, 2493 (BSL_META_U(unit, 2494 "OAM Error: service map init - Failed.\n"))); 2495 return (rv); 2496 } 2497 } 2498 2499 /* Egress Service Priority Map profile table initialization. */ 2500 soc_profile_mem_t_init(&oc->egr_service_pri_map); 2501 2502 entry_words = (sizeof(egr_service_pri_map_entry_t) / sizeof(uint32)); 2503 2504 mem = EGR_SERVICE_PRI_MAPm; 2505 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 2506 &oc->egr_service_pri_map); 2507 if (BCM_FAILURE(rv)) { 2508 LOG_ERROR(BSL_LS_BCM_OAM, 2509 (BSL_META_U(unit, 2510 "OAM Error: Egr service map profile - Failed.\n"))); 2511 return (rv); 2512 } 2513 2514 if (!SOC_WARM_BOOT(unit)) { 2515 2516 /* 2517 * Initialize Egress priority map profile table. 2518 * All priorities priorities map to priority:'0'. 2519 */ 2520 for (pri = 0; pri < BCM_OAM_INTPRI_MAX; pri++) 2521 { 2522 /* Clear ingress service pri map profile entry. */ 2523 sal_memcpy(&egr_pri_ent[pri], soc_mem_entry_null(unit, mem), 2524 soc_mem_entry_words(unit, mem) * sizeof(uint32)); 2525 2526 if (SOC_MEM_FIELD_VALID(unit, mem, OFFSET_VALIDf)) { 2527 soc_mem_field32_set(unit, mem, 2528 &egr_pri_ent[pri], OFFSET_VALIDf, 1); 2529 } 2530 } 2531 2532 2533 entries[0] = &egr_pri_ent; 2534 rv = soc_profile_mem_add(unit, &oc->egr_service_pri_map, 2535 (void *)entries, BCM_OAM_INTPRI_MAX, 2536 &profile_index); 2537 if (BCM_FAILURE(rv)) { 2538 LOG_ERROR(BSL_LS_BCM_OAM, 2539 (BSL_META_U(unit, 2540 "OAM Error: Egress service map init - Failed.\n"))); 2541 return (rv); 2542 } 2543 } 2544 2545 /* OAM Opcode Control profile table initialization. */ 2546 soc_profile_mem_t_init(&oc->oam_opcode_control_profile); 2547 2548 entry_words = sizeof(oam_opcode_control_profile_entry_t) 2549 / sizeof(uint32); 2550 2551 mem = OAM_OPCODE_CONTROL_PROFILEm; 2552 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 2553 &oc->oam_opcode_control_profile); 2554 if (BCM_FAILURE(rv)) { 2555 LOG_ERROR(BSL_LS_BCM_OAM, 2556 (BSL_META_U(unit, 2557 "OAM Error: opcode control profile - Failed.\n"))); 2558 return (rv); 2559 } 2560 if (!SOC_WARM_BOOT(unit)) { 2561 /* Create default opcode control profile */ 2562 sal_memset(&opcode_entry, 0, sizeof(oam_opcode_control_profile_entry_t)); 2563 rv = _bcm_kt2_oam_opcode_profile_entry_init(unit, mem, &opcode_entry); 2564 if (BCM_FAILURE(rv)) { 2565 LOG_ERROR(BSL_LS_BCM_OAM, 2566 (BSL_META_U(unit, 2567 "OAM Error: Opcode profile init failed " 2568 " %s.\n"), bcm_errmsg(rv))); 2569 return (rv); 2570 } 2571 /* Add entry to profile table. */ 2572 entries[0] = &opcode_entry; 2573 rv = soc_profile_mem_add(unit, &oc->oam_opcode_control_profile, 2574 (void *)entries, 1, &profile_index); 2575 if (BCM_FAILURE(rv)) { 2576 LOG_ERROR(BSL_LS_BCM_OAM, 2577 (BSL_META_U(unit, 2578 "OAM Opcode profile table is full - %s.\n"), 2579 bcm_errmsg(rv))); 2580 return rv; 2581 } 2582 } 2583 2584 /* Egress OAM Opcode Control profile table initialization. */ 2585 soc_profile_mem_t_init(&oc->egr_oam_opcode_control_profile); 2586 entry_words = sizeof(egr_oam_opcode_control_profile_entry_t) 2587 / sizeof(uint32); 2588 mem = EGR_OAM_OPCODE_CONTROL_PROFILEm; 2589 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 2590 &oc->egr_oam_opcode_control_profile); 2591 if (BCM_FAILURE(rv)) { 2592 LOG_ERROR(BSL_LS_BCM_OAM, 2593 (BSL_META_U(unit, 2594 "OAM Error: Egress opcode control profile- Failed.\n"))); 2595 return (rv); 2596 } 2597 if (!SOC_WARM_BOOT(unit)) { 2598 /* Create default opcode control profile */ 2599 sal_memset(&egr_opcode_entry, 0, 2600 sizeof(egr_oam_opcode_control_profile_entry_t)); 2601 rv = _bcm_kt2_oam_opcode_profile_entry_init(unit, mem, &egr_opcode_entry); 2602 if (BCM_FAILURE(rv)) { 2603 LOG_ERROR(BSL_LS_BCM_OAM, 2604 (BSL_META_U(unit, 2605 "OAM Error: Opcode profile init failed " 2606 " %s.\n"), bcm_errmsg(rv))); 2607 return (rv); 2608 } 2609 /* Add entry to profile table. */ 2610 entries[0] = &egr_opcode_entry; 2611 rv = soc_profile_mem_add(unit, &oc->egr_oam_opcode_control_profile, 2612 (void *)entries, 1, &profile_index); 2613 if (BCM_FAILURE(rv)) { 2614 LOG_ERROR(BSL_LS_BCM_OAM, 2615 (BSL_META_U(unit, 2616 "OAM Egr Opcode profile table is full - %s.\n"), 2617 bcm_errmsg(rv))); 2618 return rv; 2619 } 2620 } 2621 2622 /* Ingress OAM dglp profile table initialisation */ 2623 soc_profile_mem_t_init(&oc->ing_oam_dglp_profile); 2624 2625 entry_words = sizeof(ing_oam_dglp_profile_entry_t) / sizeof(uint32); 2626 2627 mem = ING_OAM_DGLP_PROFILEm; 2628 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 2629 &oc->ing_oam_dglp_profile); 2630 if (BCM_FAILURE(rv)) { 2631 LOG_ERROR(BSL_LS_BCM_OAM, 2632 (BSL_META_U(unit, 2633 "OAM Error: ING OAM DGLP profile create - Failed.\n"))); 2634 return (rv); 2635 } 2636 if (!SOC_WARM_BOOT(unit)) { 2637 /* Add default profile */ 2638 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 2639 /* put local CPU as default dglp */ 2640 dglp = CMIC_PORT(unit); 2641 dglp |= ((modid << DGLP_MODULE_ID_SHIFT_BITS)); 2642 2643 soc_mem_field32_set(unit, ING_OAM_DGLP_PROFILEm, 2644 &ing_dglp_profile_entry, DGLPf, dglp); 2645 entries[0] = &ing_dglp_profile_entry; 2646 2647 rv = soc_profile_mem_add(unit, &oc->ing_oam_dglp_profile, 2648 (void *)entries, 1, &profile_index); 2649 if (BCM_FAILURE(rv)) { 2650 LOG_ERROR(BSL_LS_BCM_OAM, 2651 (BSL_META_U(unit, 2652 "OAM DGLP profile table is full - %s.\n"), 2653 bcm_errmsg(rv))); 2654 return rv; 2655 } 2656 } 2657 2658 2659 /* Egress OAM dglp profile table initialisation */ 2660 soc_profile_mem_t_init(&oc->egr_oam_dglp_profile); 2661 2662 entry_words = sizeof(egr_oam_dglp_profile_entry_t) / sizeof(uint32); 2663 2664 mem = EGR_OAM_DGLP_PROFILEm; 2665 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 2666 &oc->egr_oam_dglp_profile); 2667 if (BCM_FAILURE(rv)) { 2668 LOG_ERROR(BSL_LS_BCM_OAM, 2669 (BSL_META_U(unit, 2670 "OAM Error: EGR OAM DGLP profile create - Failed.\n"))); 2671 return (rv); 2672 } 2673 if (!SOC_WARM_BOOT(unit)) { 2674 profile_index = 0; 2675 soc_mem_field32_set(unit, EGR_OAM_DGLP_PROFILEm, 2676 &egr_dglp_profile_entry, DGLPf, dglp); 2677 entries[0] = &egr_dglp_profile_entry; 2678 2679 rv = soc_profile_mem_add(unit, &oc->egr_oam_dglp_profile, 2680 (void *)entries, 1, &profile_index); 2681 if (BCM_FAILURE(rv)) { 2682 LOG_ERROR(BSL_LS_BCM_OAM, 2683 (BSL_META_U(unit, 2684 "OAM DGLP profile table is full - %s.\n"), 2685 bcm_errmsg(rv))); 2686 return rv; 2687 } 2688 } 2689 return (rv); 2690 } 2691 2692 /* 2693 * Function: 2694 * _bcm_kt2_oam_control_free 2695 * Purpose: 2696 * Free OAM control structure resources allocated by this unit. 2697 * Parameters: 2698 * unit - (IN) BCM unit number. 2699 * oc - (IN) Pointer to OAM control structure. 2700 * Retruns: 2701 * BCM_E_XXX 2702 */ 2703 STATIC int 2704 _bcm_kt2_oam_control_free(int unit, _bcm_oam_control_t *oc) 2705 { 2706 int status = 0; 2707 _kt2_oam_control[unit] = NULL; 2708 2709 if (NULL == oc) { 2710 /* Module already un-initialized. */ 2711 return (BCM_E_NONE); 2712 } 2713 2714 /* Free protection mutex. */ 2715 if (NULL != oc->oc_lock) { 2716 sal_mutex_destroy(oc->oc_lock); 2717 } 2718 2719 /* Free hash data storage memory. */ 2720 if (NULL != oc->oam_hash_data) { 2721 sal_free(oc->oam_hash_data); 2722 } 2723 2724 /* Destory endpoint hash table. */ 2725 if (NULL != oc->ma_mep_htbl) { 2726 status = shr_htb_destroy(&oc->ma_mep_htbl, NULL); 2727 if (BCM_FAILURE(status)) { 2728 LOG_ERROR(BSL_LS_BCM_OAM, 2729 (BSL_META_U(unit, 2730 "Freeing ma_mep_htbl failed\n"))); 2731 } 2732 } 2733 2734 /* Destory group indices list. */ 2735 if (NULL != oc->group_pool) { 2736 shr_idxres_list_destroy(oc->group_pool); 2737 oc->group_pool = NULL; 2738 } 2739 2740 /* Destroy endpoint indices list. */ 2741 if (NULL != oc->mep_pool) { 2742 shr_idxres_list_destroy(oc->mep_pool); 2743 oc->mep_pool = NULL; 2744 } 2745 2746 /* Destroy local endpoint indices list. */ 2747 if (NULL != oc->lmep_pool) { 2748 shr_idxres_list_destroy(oc->lmep_pool); 2749 oc->lmep_pool = NULL; 2750 } 2751 2752 /* Destroy remote endpoint indices list. */ 2753 if (NULL != oc->rmep_pool) { 2754 shr_idxres_list_destroy(oc->rmep_pool); 2755 oc->rmep_pool = NULL; 2756 } 2757 2758 /* Destroy ingress and egress group indices list. */ 2759 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_pool_destroy(oc)); 2760 2761 if (NULL != oc->egr_ma_idx_pool) { 2762 shr_idxres_list_destroy(oc->egr_ma_idx_pool); 2763 oc->egr_ma_idx_pool = NULL; 2764 } 2765 2766 /* Destroy LM counter indices list. */ 2767 if (NULL != oc->ing_lm_ctr_pool[0]) { 2768 shr_aidxres_list_destroy(oc->ing_lm_ctr_pool[0]); 2769 oc->ing_lm_ctr_pool[0] = NULL; 2770 } 2771 if (NULL != oc->ing_lm_ctr_pool[1]) { 2772 shr_aidxres_list_destroy(oc->ing_lm_ctr_pool[1]); 2773 oc->ing_lm_ctr_pool[1] = NULL; 2774 } 2775 if (soc_feature(unit, soc_feature_bhh)) { 2776 #if defined(INCLUDE_BHH) 2777 /* Destroy bhh indices list. */ 2778 if (NULL != oc->bhh_pool) { 2779 shr_idxres_list_destroy(oc->bhh_pool); 2780 oc->bhh_pool = NULL; 2781 } 2782 if (NULL != oc->dma_buffer){ 2783 soc_cm_sfree(oc->unit, oc->dma_buffer); 2784 oc->dma_buffer = NULL; 2785 } 2786 if (NULL != oc->dmabuf_reply){ 2787 soc_cm_sfree(oc->unit, oc->dmabuf_reply); 2788 oc->dmabuf_reply = NULL; 2789 } 2790 2791 if (NULL != oc->ing_lm_sec_mep_ctr_pool) { 2792 shr_aidxres_list_destroy(oc->ing_lm_sec_mep_ctr_pool); 2793 oc->ing_lm_sec_mep_ctr_pool = NULL; 2794 } 2795 #endif 2796 } 2797 if (soc_feature(unit, soc_feature_oam_pm)) { 2798 #if defined (INCLUDE_BHH) 2799 if (_BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc)) { 2800 soc_cm_sfree(oc->unit, oc->pm_bhh_dma_buffer); 2801 } 2802 #endif 2803 } 2804 /* Free group memory. */ 2805 if (NULL != oc->group_info) { 2806 sal_free(oc->group_info); 2807 } 2808 2809 /* Free RMEP H/w to logical index mapping memory. */ 2810 if (NULL != oc->remote_endpoints) { 2811 sal_free(oc->remote_endpoints); 2812 } 2813 2814 /* Destroy ingress serivce priority mapping profile. */ 2815 if (NULL != oc->ing_service_pri_map.tables) { 2816 soc_profile_mem_destroy(unit, &oc->ing_service_pri_map); 2817 } 2818 /* Destroy Egress serivce priority mapping profile. */ 2819 if (NULL != oc->egr_service_pri_map.tables) { 2820 soc_profile_mem_destroy(unit, &oc->egr_service_pri_map); 2821 } 2822 /* Destroy Ingress OAM opcode control profile. */ 2823 if (NULL != oc->oam_opcode_control_profile.tables) { 2824 soc_profile_mem_destroy(unit, &oc->oam_opcode_control_profile); 2825 } 2826 /* Destroy Egress OAM opcode control profile. */ 2827 if (NULL != oc->egr_oam_opcode_control_profile.tables) { 2828 soc_profile_mem_destroy(unit, &oc->egr_oam_opcode_control_profile); 2829 } 2830 /* Destroy Ingress DGLP profile */ 2831 if (NULL != oc->ing_oam_dglp_profile.tables) { 2832 soc_profile_mem_destroy(unit, &oc->ing_oam_dglp_profile); 2833 } 2834 /* Destroy Egress DGLP profile */ 2835 if (NULL != oc->egr_oam_dglp_profile.tables) { 2836 soc_profile_mem_destroy(unit, &oc->egr_oam_dglp_profile); 2837 } 2838 2839 #if defined(INCLUDE_BHH) 2840 if (soc_feature(unit, soc_feature_oam_pm)) { 2841 if (kt2_pm_profile_control[unit]) { 2842 sal_free(kt2_pm_profile_control[unit]); 2843 kt2_pm_profile_control[unit] = NULL; 2844 } 2845 } 2846 #endif /* INCLUDE_BHH */ 2847 2848 2849 /* Free OAM control structure memory. */ 2850 sal_free(oc); 2851 oc = NULL; 2852 2853 return (BCM_E_NONE); 2854 } 2855 2856 /* 2857 * Function: 2858 * _bcm_kt2_oam_handle_interrupt 2859 * Purpose: 2860 * Process OAM interrupts generated by endpoints. 2861 * Parameters: 2862 * unit - (IN) BCM unit number. 2863 * field - (IN) fault field. 2864 * Retruns: 2865 * BCM_E_XXX 2866 */ 2867 STATIC int 2868 _bcm_kt2_oam_handle_interrupt(int unit, soc_field_t field) 2869 { 2870 _bcm_oam_interrupt_t *intr; /* OAM interrupt. */ 2871 _bcm_oam_control_t *oc; /* OAM control structure. */ 2872 uint32 intr_rval; /* Interrupt register value. */ 2873 uint32 intr_cur_status; /* Interrupt status. */ 2874 uint32 flags; /* Interrupt flags. */ 2875 bcm_oam_group_t grp_index; /* MA group index. */ 2876 bcm_oam_endpoint_t remote_ep_index; /* Remote Endpoint index. */ 2877 int intr_multi; /* Event occured multiple times. */ 2878 int intr_count; /* No. of times event detected. */ 2879 int rv; /* Operation return status */ 2880 _bcm_oam_event_handler_t *e_handler; /* Pointer to Event handler. */ 2881 2882 2883 /* Get OAM control structure. */ 2884 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 2885 2886 _BCM_OAM_LOCK(oc); 2887 2888 /* Loop through the supported interrupts for this device. */ 2889 for (intr = _kt2_oam_interrupts; intr->status_register != INVALIDr; 2890 intr++) { 2891 2892 rv = soc_reg32_get(unit, intr->status_register, 2893 REG_PORT_ANY, 0, &intr_rval); 2894 if (BCM_FAILURE(rv)) { 2895 2896 continue; 2897 } 2898 2899 rv = soc_reg32_set(unit, intr->status_register, 2900 REG_PORT_ANY, 0, 0); 2901 if (BCM_FAILURE(rv)) { 2902 continue; 2903 } 2904 2905 /* Get status of interrupt from hardware. */ 2906 intr_cur_status = soc_reg_field_get(unit, intr->status_register, 2907 intr_rval, VALIDf); 2908 if (0 == intr_cur_status) { 2909 /* This interrupt event is not valid, so continue. */ 2910 continue; 2911 } 2912 2913 /* Get this interrupt event counter value. */ 2914 intr_count = oc->event_handler_cnt[intr->event_type]; 2915 2916 /* Check if the interrupt is set. */ 2917 if ((1 == intr_cur_status) && (intr_count > 0)) { 2918 flags = 0; 2919 2920 /* Get MA group index for this interrupt. */ 2921 if (INVALIDf != intr->group_index_field ) { 2922 grp_index = soc_reg_field_get(unit, intr->status_register, 2923 intr_rval, 2924 intr->group_index_field); 2925 } else { 2926 /* Group not valid for this interrupt. */ 2927 grp_index = BCM_OAM_GROUP_INVALID; 2928 } 2929 2930 /* Get H/w index of RMEP for this interrupt. */ 2931 if (INVALIDf != intr->endpoint_index_field ) { 2932 remote_ep_index = soc_reg_field_get(unit, intr->status_register, 2933 intr_rval, 2934 intr->endpoint_index_field); 2935 2936 /* Get Logical index from H/w index for this RMEP. */ 2937 remote_ep_index = oc->remote_endpoints[remote_ep_index]; 2938 } else { 2939 /* Endpoint not valid for this interrupt. */ 2940 remote_ep_index = BCM_OAM_ENDPOINT_INVALID; 2941 } 2942 2943 /* Get interrupt MULTIf status. */ 2944 intr_multi = soc_reg_field_get(unit, intr->status_register, 2945 intr_rval, MULTIf); 2946 if (1 == intr_multi) { 2947 /* 2948 * Interrupt event asserted more than once. 2949 * Set flags status bit to indicate event multiple occurance. 2950 */ 2951 flags |= BCM_OAM_EVENT_FLAGS_MULTIPLE; 2952 } 2953 2954 /* Check and call all the handlers registerd for this event. */ 2955 for (e_handler = oc->event_handler_list_p; e_handler != NULL; 2956 e_handler = e_handler->next_p) { 2957 2958 /* Check if an event handler is register for this event type. */ 2959 if (SHR_BITGET(e_handler->event_types.w, intr->event_type)) { 2960 2961 /* Call the event handler with the call back parameters. */ 2962 e_handler->cb(unit, flags, intr->event_type, grp_index, 2963 remote_ep_index, e_handler->user_data); 2964 } 2965 } 2966 } 2967 } 2968 2969 _BCM_OAM_UNLOCK(oc); 2970 2971 return (BCM_E_NONE); 2972 } 2973 2974 /* 2975 * Function: 2976 * _bcm_kt2_oam_events_unregister 2977 * Purpose: 2978 * Unregister all OAM events for this unit. 2979 * Parameters: 2980 * unit - (IN) BCM unit number. 2981 * oc - (IN) Pointer to OAM control structure. 2982 * Retruns: 2983 * BCM_E_NONE 2984 */ 2985 STATIC int 2986 _bcm_kt2_oam_events_unregister(int unit, _bcm_oam_control_t *oc) 2987 { 2988 _bcm_oam_event_handler_t *e_handler; /* Pointer to event handler list. */ 2989 _bcm_oam_event_handler_t *e_delete; /* Event handler to be freed. */ 2990 2991 /* Control lock taken by the calling routine. */ 2992 2993 e_handler = oc->event_handler_list_p; 2994 2995 while (e_handler != NULL) { 2996 e_delete = e_handler; 2997 e_handler = e_handler->next_p; 2998 sal_free(e_delete); 2999 } 3000 3001 oc->event_handler_list_p = NULL; 3002 3003 return (BCM_E_NONE); 3004 } 3005 3006 3007 /* 3008 * Function: 3009 * _bcm_kt2_oam_clear_rmep 3010 * Purpose: 3011 * Delete RMEP entry or Install fresh RMEP entry in the Hardware, clearing 3012 * the faults. 3013 * 3014 * Parameters: 3015 * unit - (IN) BCM device number 3016 * h_data_p - (IN) Pointer to Endpoint info associated with RMEP entry 3017 * being cleared. 3018 * valid - (IN) 0 => Delete the H/w entry 3019 * 1 => Install fresh entry with faults cleared. 3020 * Returns: 3021 * BCM_E_XXX 3022 */ 3023 STATIC int 3024 _bcm_kt2_oam_clear_rmep (int unit, _bcm_oam_hash_data_t *h_data_p, int valid) 3025 { 3026 3027 rmep_entry_t rmep_entry; /* RMEP table entry. */ 3028 int rv = BCM_E_INTERNAL; /* Operation return status entry */ 3029 uint32 oam_cur_time; /* Current time in H/w state machine */ 3030 3031 LOG_VERBOSE(BSL_LS_BCM_OAM, 3032 (BSL_META_U(unit, 3033 "OAM: EP id %d, valid %d\n"), 3034 h_data_p->remote_index, valid)); 3035 3036 if (h_data_p == NULL) { 3037 LOG_ERROR(BSL_LS_BCM_OAM, 3038 (BSL_META_U(unit, 3039 "OAM ERR: Arg h_data_p NULL check failed\n"))); 3040 return BCM_E_INTERNAL; 3041 } 3042 3043 /* RMEP table programming. */ 3044 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 3045 3046 /* if valid==0 delete RMEP entry, else create a clean RMEP entry */ 3047 if (!(valid)) { 3048 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index, 3049 &rmep_entry); 3050 if (rv != BCM_E_NONE) { 3051 LOG_ERROR(BSL_LS_BCM_OAM, 3052 (BSL_META_U(unit, 3053 "OAM ERR: Deleting RMEP entry failied\n"))); 3054 } 3055 return (rv); 3056 } 3057 3058 /* Set the MA group index. */ 3059 soc_RMEPm_field32_set(unit, &rmep_entry, MAID_INDEXf, 3060 h_data_p->group_index); 3061 3062 /* 3063 * The following steps are necessary to enable CCM timeout events 3064 * without having received any CCMs. 3065 */ 3066 soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMP_VALIDf, 1); 3067 3068 BCM_IF_ERROR_RETURN(READ_OAM_CURRENT_TIMEr(unit, &oam_cur_time)); 3069 3070 soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMPf, oam_cur_time); 3071 3072 soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_RECEIVED_CCMf, 3073 _bcm_kt2_oam_ccm_msecs_to_hw_encode(h_data_p->period)); 3074 /* End of timeout setup */ 3075 3076 3077 soc_RMEPm_field32_set(unit, &rmep_entry, VALIDf, 1); 3078 3079 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index, 3080 &rmep_entry); 3081 if (rv != BCM_E_NONE) { 3082 LOG_ERROR(BSL_LS_BCM_OAM, 3083 (BSL_META_U(unit, 3084 "OAM ERR: Clearing RMEP entry failied\n"))); 3085 return (rv); 3086 } 3087 3088 return BCM_E_NONE; 3089 } 3090 3091 3092 /* 3093 * Function: 3094 * _bcm_kt2_oam_clear_ma_state 3095 * Purpose: 3096 * Delete MA_STATE entry or Install fresh MA_STATE entry in the Hardware, 3097 * Clearing the faults. 3098 * Parameters: 3099 * unit - (IN) BCM device number 3100 * group_info - (IN) Group info associated with MA_STATE entry being 3101 * cleared. 3102 * index - (IN) H/w index of MA_STATE entry to be modified. 3103 * valid - (IN) 0 => Delete the H/w entry 3104 * 1 => Install fresh entry with faults cleared. 3105 * Returns: 3106 * BCM_E_XXX 3107 */ 3108 STATIC int 3109 _bcm_kt2_oam_clear_ma_state(int unit, _bcm_oam_group_data_t *group_info, 3110 int index, int valid) 3111 { 3112 3113 ma_state_entry_t ma_state_entry; /* MA State table entry. */ 3114 3115 LOG_VERBOSE(BSL_LS_BCM_OAM, 3116 (BSL_META_U(unit, 3117 "OAM *group_info %p, index %d, valid %d\n"), 3118 group_info, index, valid)); 3119 3120 if (group_info == NULL) { 3121 LOG_ERROR(BSL_LS_BCM_OAM, 3122 (BSL_META_U(unit, 3123 "OAM ERR: Arg group_info NULL check failed\n"))); 3124 return BCM_E_INTERNAL; 3125 } 3126 3127 sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t)); 3128 3129 /* Mark the entry as valid. */ 3130 soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, valid); 3131 3132 /* Set the lowest alarm priority info. */ 3133 if (valid) { 3134 soc_MA_STATEm_field32_set(unit, &ma_state_entry, LOWESTALARMPRIf, 3135 group_info->lowest_alarm_priority); 3136 } 3137 3138 /* Write group information to hardware table. */ 3139 SOC_IF_ERROR_RETURN(WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, index, 3140 &ma_state_entry)); 3141 return BCM_E_NONE; 3142 } 3143 3144 3145 /* 3146 * Function: 3147 * _bcm_kt2_oam_group_recreate 3148 * Purpose: 3149 * Recreate MA_STATE and RMEP entries, due to current H/w limitation 3150 * Currently there is a race condition between H/w and Software 3151 * When RMEP is deleted and if it has any faults then, 3152 * MA_STATE remote fault counters need to be decremented by software. 3153 * However it may so happen that after reading RMEP faults and just 3154 * before RMEP deletion, the fault gets cleared and H/w already decremented 3155 * the MA_STATE table, now when software decrements the MA_STATE it would 3156 * get MA_STATE table into an inconsistent state. 3157 * As a solution we always recreate the entire group on a RMEP deletion. 3158 * Parameters: 3159 * unit - (IN) BCM device number 3160 * group_id - (IN) Group Index, 3161 * as per current implementation this is same as MA_STATE index. 3162 * Returns: 3163 * BCM_E_XXX 3164 * Expects: 3165 * OAM LOCK 3166 */ 3167 STATIC int 3168 _bcm_kt2_oam_group_recreate(int unit, int index) 3169 { 3170 _bcm_oam_control_t *oc; /* OAM control structure. */ 3171 _bcm_oam_group_data_t *group_info; /* OAM group info */ 3172 _bcm_oam_ep_list_t *cur_ep_ptr = NULL; /* Pointer to group's EP list */ 3173 /* entry. */ 3174 int rv = BCM_E_NONE; /* Operation return status. */ 3175 3176 /* Get OAM control structure handle. */ 3177 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 3178 3179 /* Get the handle to group info */ 3180 group_info = &(oc->group_info[index]); 3181 3182 /*if unused Group, just clear the MA_STATE index, including the valid bit*/ 3183 if (!(group_info->in_use)) { 3184 LOG_WARN(BSL_LS_BCM_OAM, 3185 (BSL_META_U(unit, 3186 "OAM, WARN: Recieved group recreate request for " 3187 "unused Group Id %d\n"), index)); 3188 3189 rv = _bcm_kt2_oam_clear_ma_state(unit, group_info, index, 0); 3190 if (BCM_FAILURE(rv)) { 3191 LOG_ERROR(BSL_LS_BCM_OAM, 3192 (BSL_META_U(unit, 3193 "OAM Error: MA_STATE clear failed group id %d - " 3194 "%s.\n"), index, bcm_errmsg(rv))); 3195 return rv; 3196 } 3197 3198 } 3199 3200 /* 1. Traverse and delete the RMEPs in the group */ 3201 if (group_info->ep_list != NULL) { 3202 cur_ep_ptr = *(group_info->ep_list); 3203 } 3204 while (cur_ep_ptr) { 3205 if (cur_ep_ptr->ep_data_p->is_remote && cur_ep_ptr->ep_data_p->in_use) { 3206 rv = _bcm_kt2_oam_clear_rmep(unit, cur_ep_ptr->ep_data_p, 0); 3207 if (BCM_FAILURE(rv)) { 3208 LOG_ERROR(BSL_LS_BCM_OAM, 3209 (BSL_META_U(unit, 3210 "OAM Error: RMEP delete failed Ep id %d - " 3211 "%s.\n"), cur_ep_ptr->ep_data_p->ep_id, bcm_errmsg(rv))); 3212 return rv; 3213 } 3214 } 3215 cur_ep_ptr = cur_ep_ptr->next; 3216 } 3217 3218 /* 2. Clear the MA_STATE table faults */ 3219 rv = _bcm_kt2_oam_clear_ma_state(unit, group_info, index, 1); 3220 if (BCM_FAILURE(rv)) { 3221 LOG_ERROR(BSL_LS_BCM_OAM, 3222 (BSL_META_U(unit, 3223 "OAM Error: MA_STATE clear failed group id %d - " 3224 "%s.\n"), index, bcm_errmsg(rv))); 3225 return rv; 3226 } 3227 3228 /* 3. Recreate the RMEP table entries. Clearing the faults. */ 3229 if (group_info->ep_list != NULL) { 3230 cur_ep_ptr = *(group_info->ep_list); 3231 } 3232 while (cur_ep_ptr) { 3233 if (cur_ep_ptr->ep_data_p->is_remote && cur_ep_ptr->ep_data_p->in_use) { 3234 rv = _bcm_kt2_oam_clear_rmep(unit, cur_ep_ptr->ep_data_p, 1); 3235 if (BCM_FAILURE(rv)) { 3236 LOG_ERROR(BSL_LS_BCM_OAM, 3237 (BSL_META_U(unit, 3238 "OAM Error: RMEP clear failed EP id %d - " 3239 "%s.\n"), cur_ep_ptr->ep_data_p->ep_id, bcm_errmsg(rv))); 3240 return rv; 3241 } 3242 } 3243 cur_ep_ptr = cur_ep_ptr->next; 3244 } 3245 3246 return rv; 3247 } 3248 3249 3250 /* 3251 * Function: 3252 * _bcm_kt2_oam_ser_handler 3253 * Purpose: 3254 * Soft Error Correction routine for MA_STATE and RMEP tables. 3255 * Parameters: 3256 * unit - (IN) BCM device number 3257 * mem - (IN) Memory MA_STATE or RMEP. 3258 * index - (IN) Memory Index. 3259 * Returns: 3260 * BCM_E_XXX 3261 */ 3262 STATIC int 3263 _bcm_kt2_oam_ser_handler(int unit, soc_mem_t mem, int index) 3264 { 3265 int rv = BCM_E_NONE; /* Operation return status. */ 3266 _bcm_oam_control_t *oc = NULL; /* OAM control structure. */ 3267 bcm_oam_endpoint_t remote_ep_index; /* Remote Endpoint index. */ 3268 _bcm_oam_hash_data_t *ep_data = NULL; /* Remote Endpoint hash data */ 3269 3270 LOG_VERBOSE(BSL_LS_BCM_OAM, 3271 (BSL_META_U(unit, 3272 "OAM SER on mem %s, index %d\n"), 3273 SOC_MEM_NAME(unit, mem), index)); 3274 3275 /* Get OAM control structure handle. */ 3276 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 3277 3278 switch(mem){ 3279 case MA_STATEm: 3280 _BCM_OAM_GROUP_INDEX_VALIDATE(index); 3281 _BCM_OAM_LOCK(oc); 3282 rv = _bcm_kt2_oam_group_recreate(unit, index); 3283 _BCM_OAM_UNLOCK(oc); 3284 break; 3285 3286 case RMEPm: 3287 _BCM_OAM_RMEP_INDEX_VALIDATE(index); 3288 _BCM_OAM_LOCK(oc); 3289 /* Get the logical index from H/w RMEP index */ 3290 remote_ep_index = oc->remote_endpoints[index]; 3291 if(remote_ep_index == BCM_OAM_ENDPOINT_INVALID) { 3292 /* If endpoint not in use, just clear the RMEP entry in memory */ 3293 rmep_entry_t rmep_entry; 3294 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 3295 3296 LOG_WARN(BSL_LS_BCM_OAM, 3297 (BSL_META_U(unit, 3298 "OAM(unit %d), WARN: Recieved Parity Error on" 3299 "index %d & invalid Remote Id\n"), unit, index)); 3300 /* Just clear this entry including valid bit */ 3301 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, index, 3302 &rmep_entry); 3303 } else { 3304 3305 /* Get handle to Hash data */ 3306 ep_data = &(oc->oam_hash_data[remote_ep_index]); 3307 3308 if (!(ep_data->in_use)) { 3309 /* If endpoint not in use, just clear the RMEP entry in memory */ 3310 LOG_WARN(BSL_LS_BCM_OAM, 3311 (BSL_META_U(unit, 3312 "OAM, WARN: Recieved Parity Error on" 3313 "unused Remote Id %d\n"), remote_ep_index)); 3314 /* Just clear this entry including valid bit */ 3315 rv = _bcm_kt2_oam_clear_rmep(unit, ep_data, 0); 3316 } else { 3317 /* Get the group Id from EP data, call group recreate routine */ 3318 rv = _bcm_kt2_oam_group_recreate(unit, ep_data->group_index); 3319 } 3320 } 3321 _BCM_OAM_UNLOCK(oc); 3322 break; 3323 3324 default: 3325 LOG_ERROR(BSL_LS_BCM_OAM, 3326 (BSL_META_U(unit, 3327 "OAM, ERR: Invalid mem in OAM SER correction " 3328 "routine %s\n"), SOC_MEM_NAME(unit, mem))); 3329 return BCM_E_INTERNAL; 3330 } 3331 3332 LOG_VERBOSE(BSL_LS_BCM_OAM, 3333 (BSL_META_U(unit, 3334 "OAM SER completed on mem %s, index %d, rv %d\n"), 3335 SOC_MEM_NAME(unit, mem), index, rv)); 3336 3337 return rv; 3338 3339 } 3340 3341 /* 3342 * Function: 3343 * _bcm_kt2_oam_group_name_mangle 3344 * Purpose: 3345 * Build tbe group name for hardware table write. 3346 * Parameters: 3347 * name_p - (IN) OAM group name. 3348 * mangled_name_p - (IN/OUT) Buffer to write the group name in hardware 3349 * format. 3350 * Retruns: 3351 * None 3352 */ 3353 STATIC void 3354 _bcm_kt2_oam_group_name_mangle(uint8 *name_p, 3355 uint8 *mangled_name_p) 3356 { 3357 uint8 *byte_p; /* Pointer to group name buffer. */ 3358 int bytes_left; /* Number of bytes left in group name. */ 3359 3360 bytes_left = BCM_OAM_GROUP_NAME_LENGTH; 3361 byte_p = (name_p + BCM_OAM_GROUP_NAME_LENGTH - 1); 3362 3363 while (bytes_left > 0) { 3364 *mangled_name_p = *byte_p; 3365 ++mangled_name_p; 3366 --byte_p; 3367 --bytes_left; 3368 } 3369 } 3370 3371 /* 3372 * Function: 3373 * _bcm_kt2_oam_read_clear_faults 3374 * Purpose: 3375 * Clear OAM group and endpoint faults on hardware table read operation. 3376 * Parameters: 3377 * unit - (IN) BCM device number 3378 * index - (IN) Group/Endpoint hardware table index 3379 * mem - (IN) Memory/table value 3380 * entry - (IN) Pointer to group/endpoint entry 3381 * ma_mep - (IN) Pointer to group/endpoint info structure 3382 * Returns: 3383 * BCM_E_NONE - No errors. 3384 * BCM_E_XXX - Otherwise. 3385 */ 3386 STATIC int 3387 _bcm_kt2_oam_read_clear_faults(int unit, int index, soc_mem_t mem, 3388 uint32 *entry, void *ma_rmep) 3389 { 3390 bcm_oam_group_info_t *group_info_p; /* Pointer to group info */ 3391 /* structure. */ 3392 bcm_oam_endpoint_info_t *ep_info_p; /* Pointer to endpoint info */ 3393 /* structure. */ 3394 _bcm_oam_fault_t *faults_list; /* Pointer to faults list. */ 3395 uint32 *faults; /* Faults flag bits. */ 3396 uint32 *p_faults; /* Persistent faults bits. */ 3397 uint32 clear_p_faults; /* Clear persistent faults bits. */ 3398 uint32 rval = 0; /* Hardware register value. */ 3399 uint32 clear_mask = 0; /* Mask to clear persistent faults*/ 3400 3401 LOG_DEBUG(BSL_LS_BCM_OAM, 3402 (BSL_META_U(unit, 3403 "OAM Info: _bcm_kt2_oam_read_clear_faults index=%d " 3404 "Table=%d.\n"), index, mem)); 3405 3406 /* Switch on memory name. */ 3407 switch (mem) { 3408 /* OAM group state table. */ 3409 case MA_STATEm: 3410 /* Set the pointer to the start of the group faults array. */ 3411 faults_list = _kt2_oam_group_faults; 3412 3413 /* Typecast to group information structure pointer. */ 3414 group_info_p = (bcm_oam_group_info_t *) ma_rmep; 3415 3416 /* Get group faults information. */ 3417 faults = &group_info_p->faults; 3418 p_faults = &group_info_p->persistent_faults; 3419 clear_p_faults = group_info_p->clear_persistent_faults; 3420 break; 3421 3422 /* OAM remote endpoint table. */ 3423 case RMEPm: 3424 faults_list = _kt2_oam_endpoint_faults; 3425 ep_info_p = (bcm_oam_endpoint_info_t *) ma_rmep; 3426 faults = &ep_info_p->faults; 3427 p_faults = &ep_info_p->persistent_faults; 3428 clear_p_faults = ep_info_p->clear_persistent_faults; 3429 break; 3430 3431 default: 3432 return (BCM_E_NONE); 3433 } 3434 3435 /* Loop on list of valid faults. */ 3436 for (;faults_list->mask != 0; ++faults_list) { 3437 3438 /* Get faults status. */ 3439 if (0 != soc_mem_field32_get(unit, mem, entry, 3440 faults_list->current_field)) { 3441 *faults |= faults_list->mask; 3442 } 3443 3444 /* Get sticky faults status. */ 3445 if (0 != soc_mem_field32_get(unit, mem, entry, 3446 faults_list->sticky_field)) { 3447 3448 *p_faults |= faults_list->mask; 3449 3450 /* 3451 * If user has request to clear persistent faults, 3452 * then set BITS_TO_CLEARf field in the register buffer. 3453 */ 3454 if (clear_p_faults) { 3455 clear_mask |= faults_list->clear_sticky_mask; 3456 } 3457 } 3458 } 3459 3460 /* Check if faults need to be cleared. */ 3461 if (clear_mask && clear_p_faults) { 3462 3463 LOG_VERBOSE(BSL_LS_BCM_OAM, 3464 (BSL_META_U(unit, 3465 "OAM: clear_mask %d.\n"), 3466 clear_mask)); 3467 3468 soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, BITS_TO_CLEARf, 3469 clear_mask); 3470 3471 /* Enable clearing of faults. */ 3472 soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, ENABLE_CLEARf, 1); 3473 3474 3475 if (MA_STATEm == mem) { 3476 soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, MEMORYf, 0); 3477 } else { 3478 soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, MEMORYf, 1); 3479 } 3480 3481 soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, INDEXf, index); 3482 3483 /* Update read control register. */ 3484 BCM_IF_ERROR_RETURN(WRITE_CCM_READ_CONTROLr(unit, rval)); 3485 } 3486 3487 return (BCM_E_NONE); 3488 } 3489 3490 /* 3491 * Function: 3492 * _bcm_kt2_oam_get_group 3493 * Purpose: 3494 * Get OAM group information. 3495 * Parameters: 3496 * unit - (IN) BCM device number 3497 * group_index - (IN) Group hardware table index 3498 * group - (IN) Pointer to group array list 3499 * group_info - (IN/OUT) Pointer to group info structure 3500 * Returns: 3501 * BCM_E_NONE - No errors. 3502 * BCM_E_XXX - Otherwise. 3503 */ 3504 STATIC int 3505 _bcm_kt2_oam_get_group(int unit, bcm_oam_group_t group_index, 3506 _bcm_oam_group_data_t *group_p, 3507 bcm_oam_group_info_t *group_info) 3508 { 3509 maid_reduction_entry_t maid_reduction_entry; /* MAID reduction entry. */ 3510 ma_state_entry_t ma_state_entry; /* MA_STATE table entry. */ 3511 int rv; /* Operation return status. */ 3512 3513 group_info->id = group_index; 3514 3515 BCM_IF_ERROR_RETURN(READ_MA_STATEm(unit, MEM_BLOCK_ANY, 3516 group_index, 3517 &ma_state_entry)); 3518 3519 group_info->lowest_alarm_priority = soc_MA_STATEm_field32_get 3520 (unit, &ma_state_entry, 3521 LOWESTALARMPRIf); 3522 3523 rv = _bcm_kt2_oam_read_clear_faults(unit, group_index, 3524 MA_STATEm, 3525 (uint32 *) &ma_state_entry, 3526 group_info); 3527 if (BCM_FAILURE(rv)) { 3528 LOG_ERROR(BSL_LS_BCM_OAM, 3529 (BSL_META_U(unit, 3530 "OAM Error: Clean Faults Group ID=%d- Failed.\n"), 3531 group_index)); 3532 return (rv); 3533 } 3534 if (group_info->flags & BCM_OAM_GROUP_GET_FAULTS_ONLY) { 3535 group_info->flags &= ~BCM_OAM_GROUP_GET_FAULTS_ONLY; 3536 return BCM_E_NONE; 3537 } 3538 sal_memcpy(group_info->name, group_p[group_index].name, 3539 BCM_OAM_GROUP_NAME_LENGTH); 3540 3541 BCM_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, 3542 group_index, 3543 &maid_reduction_entry)); 3544 3545 if (1 == soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry, 3546 SW_RDIf)) { 3547 group_info->flags |= BCM_OAM_GROUP_REMOTE_DEFECT_TX; 3548 } 3549 3550 return (BCM_E_NONE); 3551 } 3552 3553 /* 3554 * Function: 3555 * _bcm_kt2_oam_group_ep_list_add 3556 * Purpose: 3557 * Add an endpoint to a group endpoint linked list. 3558 * Parameters: 3559 * unit - (IN) BCM device number 3560 * group_id - (IN) OAM group ID. 3561 * ep_id - (IN) OAM endpoint ID. 3562 * Retruns: 3563 * BCM_E_XXX 3564 */ 3565 STATIC int 3566 _bcm_kt2_oam_group_ep_list_add(int unit, 3567 bcm_oam_group_t group_id, 3568 bcm_oam_endpoint_t ep_id) 3569 { 3570 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 3571 _bcm_oam_group_data_t *group_p; /* Pointer to group data. */ 3572 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 3573 _bcm_oam_ep_list_t *ep_list_p = NULL; /* Pointer to endpoint list. */ 3574 3575 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 3576 3577 group_p = &oc->group_info[group_id]; 3578 /* coverity[dead_error_condition] */ 3579 if (NULL == group_p) { 3580 LOG_ERROR(BSL_LS_BCM_OAM, 3581 (BSL_META_U(unit, 3582 "OAM Error: Group data access for GID=%d failed" 3583 /* coverity[dead_error_begin] */ 3584 " %s.\n"), group_id, bcm_errmsg(BCM_E_INTERNAL))); 3585 return (BCM_E_INTERNAL); 3586 } 3587 3588 h_data_p = &oc->oam_hash_data[ep_id]; 3589 /* coverity[dead_error_condition] */ 3590 if (NULL == h_data_p) { 3591 LOG_ERROR(BSL_LS_BCM_OAM, 3592 (BSL_META_U(unit, 3593 "OAM Error: Endpoint data access for EP=%d failed" 3594 /* coverity[dead_error_begin] */ 3595 " %s.\n"), ep_id, bcm_errmsg(BCM_E_INTERNAL))); 3596 return (BCM_E_INTERNAL); 3597 } 3598 3599 _BCM_OAM_ALLOC(ep_list_p, _bcm_oam_ep_list_t, sizeof(_bcm_oam_ep_list_t), 3600 "EP list"); 3601 if (NULL == ep_list_p) { 3602 LOG_ERROR(BSL_LS_BCM_OAM, 3603 (BSL_META_U(unit, 3604 "OAM Error: Endpoint list alloc for EP=%d failed" 3605 " %s.\n"), ep_id, bcm_errmsg(BCM_E_MEMORY))); 3606 return (BCM_E_MEMORY); 3607 } 3608 3609 ep_list_p->prev = NULL; 3610 ep_list_p->ep_data_p = h_data_p; 3611 if (NULL == (*group_p->ep_list)) { 3612 /* Add endpoint as head node. */ 3613 ep_list_p->next = NULL; 3614 *group_p->ep_list = ep_list_p; 3615 } else { 3616 /* Add the endpoint to the linked list. */ 3617 ep_list_p->next = *group_p->ep_list; 3618 (*group_p->ep_list)->prev = ep_list_p; 3619 *group_p->ep_list = ep_list_p; 3620 } 3621 LOG_DEBUG(BSL_LS_BCM_OAM, 3622 (BSL_META_U(unit, 3623 "OAM Info: _bcm_kt2_oam_group_ep_list_add" 3624 " (GID=%d) (EP=%d).\n"), group_id, ep_id)); 3625 return (BCM_E_NONE); 3626 } 3627 3628 /* 3629 * Function: 3630 * _bcm_kt2_oam_group_ep_list_remove 3631 * Purpose: 3632 * Remove an endpoint to a group endpoint linked list. 3633 * Parameters: 3634 * unit - (IN) BCM device number 3635 * group_id - (IN) OAM group ID. 3636 * ep_id - (IN) OAM endpoint ID. 3637 * Retruns: 3638 * BCM_E_XXX 3639 */ 3640 STATIC int 3641 _bcm_kt2_oam_group_ep_list_remove(int unit, 3642 bcm_oam_group_t group_id, 3643 bcm_oam_endpoint_t ep_id) 3644 { 3645 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 3646 _bcm_oam_group_data_t *group_p; /* Pointer to group data. */ 3647 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 3648 _bcm_oam_ep_list_t *cur; /* Current endpoint node pointer. */ 3649 _bcm_oam_ep_list_t *del_node; /* Pointer to a node to be deleted. */ 3650 3651 /* Control lock already taken by calling routine. */ 3652 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 3653 3654 group_p = &oc->group_info[group_id]; 3655 cur = *group_p->ep_list; 3656 if (NULL == cur) { 3657 /* No endpoints to remove from this group. */ 3658 LOG_DEBUG(BSL_LS_BCM_OAM, 3659 (BSL_META_U(unit, 3660 "OAM Info: No endpoints to delete in group" 3661 " GID:%d.\n"), group_id)); 3662 return (BCM_E_NONE); 3663 } 3664 3665 /* Check if head node needs to be deleated. */ 3666 if (ep_id == cur->ep_data_p->ep_id) { 3667 /* Delete head node. */ 3668 del_node = *group_p->ep_list; 3669 if ((*group_p->ep_list)->next) { 3670 *group_p->ep_list = (*group_p->ep_list)->next; 3671 (*group_p->ep_list)->prev = NULL; 3672 } else { 3673 *group_p->ep_list = NULL; 3674 } 3675 sal_free(del_node); 3676 LOG_DEBUG(BSL_LS_BCM_OAM, 3677 (BSL_META_U(unit, 3678 "OAM Info: Head node delete GID=%d - Success\n"), 3679 group_id)); 3680 return (BCM_E_NONE); 3681 } 3682 3683 /* Traverse the list and delete the matching node. */ 3684 while (NULL != cur->next->next) { 3685 h_data_p = cur->next->ep_data_p; 3686 if (NULL == h_data_p) { 3687 LOG_ERROR(BSL_LS_BCM_OAM, 3688 (BSL_META_U(unit, 3689 "OAM Error: Group=%d endpoints access failed -" 3690 " %s.\n"), group_id, bcm_errmsg(BCM_E_INTERNAL))); 3691 return (BCM_E_INTERNAL); 3692 } 3693 3694 if (ep_id == h_data_p->ep_id) { 3695 del_node = cur->next; 3696 cur->next = del_node->next; 3697 del_node->next->prev = cur; 3698 sal_free(del_node); 3699 LOG_DEBUG(BSL_LS_BCM_OAM, 3700 (BSL_META_U(unit, 3701 "OAM Info: Node delete GID=%d - Success\n"), 3702 group_id)); 3703 return (BCM_E_NONE); 3704 } 3705 cur = cur->next; 3706 } 3707 3708 /* Check if tail node needs to be deleted. */ 3709 h_data_p = cur->next->ep_data_p; 3710 if (ep_id == h_data_p->ep_id) { 3711 /* Delete tail node. */ 3712 del_node = cur->next; 3713 cur->next = NULL; 3714 sal_free(del_node); 3715 LOG_DEBUG(BSL_LS_BCM_OAM, 3716 (BSL_META_U(unit, 3717 "OAM Info: Tail node delete GID=%d - Success\n"), 3718 group_id)); 3719 return (BCM_E_NONE); 3720 } 3721 3722 return (BCM_E_NOT_FOUND); 3723 } 3724 3725 /* 3726 * Function: 3727 * _bcm_oam_kt2_remote_mep_hw_set 3728 * Purpose: 3729 * Configure hardware tables for a remote endpoint. 3730 * Parameters: 3731 * unit - (IN) BCM device number 3732 * ep_info_p - (IN) Pointer to remote endpoint information. 3733 * Retruns: 3734 * BCM_E_XXX 3735 */ 3736 STATIC int 3737 _bcm_oam_kt2_remote_mep_hw_set(int unit, 3738 const bcm_oam_endpoint_info_t *ep_info_p) 3739 { 3740 l3_entry_1_entry_t l3_entry; /* Remote view entry. */ 3741 rmep_entry_t rmep_entry; /* Remote MEP entry. */ 3742 uint32 oam_cur_time; /* Current time. */ 3743 _bcm_oam_hash_data_t *h_data_p = NULL; /* Hash data pointer. */ 3744 int rv; /* Operation return status. */ 3745 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 3746 const bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint info. */ 3747 3748 if (NULL == ep_info_p) { 3749 return (BCM_E_INTERNAL); 3750 } 3751 3752 /* Initialize local endpoint info pointer. */ 3753 ep_p = ep_info_p; 3754 3755 /* Lock already taken by the calling routine. */ 3756 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 3757 3758 /* Get endpoint hash data pointer. */ 3759 h_data_p = &oc->oam_hash_data[ep_p->id]; 3760 if (0 == h_data_p->in_use) { 3761 return (BCM_E_INTERNAL); 3762 } 3763 3764 /* RMEP table programming. */ 3765 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 3766 3767 /* Set the MA group index. */ 3768 soc_RMEPm_field32_set(unit, &rmep_entry, MAID_INDEXf, 3769 ep_p->group); 3770 3771 /* 3772 * The following steps are necessary to enable CCM timeout events 3773 * without having received any CCMs. 3774 */ 3775 soc_RMEPm_field32_set(unit, &rmep_entry, 3776 RMEP_TIMESTAMP_VALIDf, 1); 3777 3778 BCM_IF_ERROR_RETURN 3779 (READ_OAM_CURRENT_TIMEr(unit, &oam_cur_time)); 3780 3781 soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMPf, 3782 oam_cur_time); 3783 3784 soc_RMEPm_field32_set(unit, &rmep_entry, 3785 RMEP_RECEIVED_CCMf, 3786 _bcm_kt2_oam_ccm_msecs_to_hw_encode(h_data_p->period)); 3787 /* End of timeout setup */ 3788 3789 soc_RMEPm_field32_set(unit, &rmep_entry, VALIDf, 1); 3790 3791 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index, 3792 &rmep_entry); 3793 if (BCM_FAILURE(rv)) { 3794 LOG_ERROR(BSL_LS_BCM_OAM, 3795 (BSL_META_U(unit, 3796 "OAM Error: RMEP table write failed EP=%d %s.\n"), 3797 ep_info_p->id, bcm_errmsg(rv))); 3798 return (rv); 3799 } 3800 3801 /* L3 unicast table programming. */ 3802 sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t)); 3803 3804 /* Set the CCM interval. */ 3805 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 3806 (unit, &l3_entry, RMEP__CCMf, 3807 _bcm_kt2_oam_ccm_msecs_to_hw_encode(h_data_p->period)); 3808 3809 /* Set the entry hardware index. */ 3810 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__RMEP_PTRf, 3811 h_data_p->remote_index); 3812 3813 /* 3814 * Construct endpoint RMEP view key for L3 Table entry 3815 * insert operation. 3816 */ 3817 _bcm_kt2_oam_rmep_key_construct(unit, h_data_p, &l3_entry); 3818 3819 /* Mark the entry as valid. */ 3820 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, VALIDf, 1); 3821 3822 /* Install entry in hardware. */ 3823 rv = soc_mem_insert(unit, L3_ENTRY_IPV4_UNICASTm, 3824 MEM_BLOCK_ALL, &l3_entry); 3825 if (BCM_FAILURE(rv)) { 3826 LOG_ERROR(BSL_LS_BCM_OAM, 3827 (BSL_META_U(unit, 3828 "OAM Error: L3 table insert failed EP=%d %s.\n"), 3829 ep_p->id, bcm_errmsg(rv))); 3830 return (rv); 3831 } 3832 /* Add the H/w index to logical index mapping for RMEP */ 3833 oc->remote_endpoints[h_data_p->remote_index] = ep_p->id; 3834 3835 return (BCM_E_NONE); 3836 } 3837 /* 3838 * Function: 3839 * _bcm_kt2_oam_find_egr_lmep 3840 * Purpose: 3841 * Search EGR_MP_GROUP table and return the match entry hardware index and 3842 * match entry data. 3843 * Parameters: 3844 * unit - (IN) BCM device number 3845 * h_data_p - (IN) Pointer to endpoint hash data. 3846 * entry_idx - (OUT) Pointer to match entry hardware index. 3847 * mp_group_entry_p - (OUT) Pointer to match entry data. 3848 * Retruns: 3849 * BCM_E_XXX 3850 */ 3851 STATIC int 3852 _bcm_kt2_oam_find_egr_lmep(int unit, const _bcm_oam_hash_data_t *h_data_p, 3853 int *entry_idx, 3854 egr_mp_group_entry_t *mp_group_entry_p) 3855 { 3856 egr_mp_group_entry_t mp_group_entry; /* MP group table 3857 entry to search. */ 3858 int rv; /* Operation return status. */ 3859 3860 if (NULL == h_data_p || NULL == entry_idx || NULL == mp_group_entry_p) { 3861 return (BCM_E_INTERNAL); 3862 } 3863 3864 sal_memset(&mp_group_entry, 0, sizeof(egr_mp_group_entry_t)); 3865 3866 /* Construct endpoint egress MP group Table entry search operation. */ 3867 _bcm_oam_egr_lmep_key_construct(unit, h_data_p, &mp_group_entry); 3868 3869 soc_mem_lock(unit, EGR_MP_GROUPm); 3870 /* Perform the search in EGR_MP_GROUP table. */ 3871 rv = soc_mem_search(unit, EGR_MP_GROUPm, MEM_BLOCK_ANY, entry_idx, 3872 &mp_group_entry, mp_group_entry_p, 0); 3873 soc_mem_unlock(unit, EGR_MP_GROUPm); 3874 if (BCM_FAILURE(rv)) { 3875 LOG_VERBOSE(BSL_LS_BCM_OAM, 3876 (BSL_META_U(unit, 3877 "OAM Error: Egr MP group entry lookup " 3878 "failed vlan=%d port =%x %s.\n"), 3879 h_data_p->vlan, h_data_p->dglp, bcm_errmsg(rv))); 3880 } 3881 3882 return (rv); 3883 } 3884 3885 /* 3886 * Function: 3887 * _bcm_kt2_oam_find_lmep 3888 * Purpose: 3889 * Search LMEP view table and return the match entry hardware index and 3890 * match entry data. 3891 * Parameters: 3892 * unit - (IN) BCM device number 3893 * h_data_p - (IN) Pointer to endpoint hash data. 3894 * entry_idx - (OUT) Pointer to match entry hardware index. 3895 * l3_entry_p - (OUT) Pointer to match entry data. 3896 * Retruns: 3897 * BCM_E_XXX 3898 */ 3899 STATIC int 3900 _bcm_kt2_oam_find_lmep(int unit, const _bcm_oam_hash_data_t *h_data_p, 3901 int *entry_idx, 3902 l3_entry_1_entry_t *l3_entry_p) 3903 { 3904 l3_entry_1_entry_t l3_entry; /* L3 entry to search. */ 3905 int rv; /* Operation return status. */ 3906 3907 if (NULL == h_data_p || NULL == entry_idx || NULL == l3_entry_p) { 3908 return (BCM_E_INTERNAL); 3909 } 3910 3911 sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t)); 3912 3913 /* Construct endpoint LMEP view key for L3 Table entry search operation. */ 3914 _bcm_kt2_oam_lmep_key_construct(unit, h_data_p, &l3_entry); 3915 3916 /* Take L3 module protection mutex to block any updates. */ 3917 L3_LOCK(unit); 3918 3919 /* Perform the search in L3_ENTRY table. */ 3920 rv = soc_mem_search(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ANY, entry_idx, 3921 &l3_entry, l3_entry_p, 0); 3922 if (BCM_FAILURE(rv)) { 3923 LOG_VERBOSE(BSL_LS_BCM_OAM, 3924 (BSL_META_U(unit, 3925 "OAM Error: L3 entry lookup vlan=%d port=%x %s.\n"), 3926 h_data_p->vlan, h_data_p->sglp, bcm_errmsg(rv))); 3927 } 3928 3929 /* Release L3 module protection mutex. */ 3930 L3_UNLOCK(unit); 3931 3932 return (rv); 3933 } 3934 3935 STATIC int 3936 _bcm_kt2_oam_find_port_lmep(int unit, const _bcm_oam_hash_data_t *h_data_p, 3937 int *stm_index, source_trunk_map_table_entry_t *stm_entry, 3938 uint8 *mdl) 3939 { 3940 port_tab_entry_t port_entry; 3941 int rv = BCM_E_NONE; 3942 int port_id, mod_id; 3943 3944 rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, 3945 h_data_p->src_pp_port, &port_entry); 3946 3947 if (BCM_FAILURE(rv)) { 3948 return rv; 3949 } 3950 3951 *mdl = soc_PORT_TABm_field32_get(unit, &port_entry, MDL_BITMAPf); 3952 3953 if (*mdl == 0) { 3954 /* No port mep enabled already on this port */ 3955 return BCM_E_NOT_FOUND; 3956 } 3957 3958 port_id = _BCM_OAM_GLP_PORT_GET(h_data_p->sglp); 3959 mod_id = _BCM_OAM_GLP_MODULE_ID_GET(h_data_p->sglp); 3960 3961 /* Derive index to SOURCE_TRUNK_MAP tbl based on module ID and port*/ 3962 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, mod_id, 3963 port_id, stm_index)); 3964 BCM_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY, 3965 *stm_index, stm_entry)); 3966 return BCM_E_NONE; 3967 } 3968 3969 STATIC 3970 int _bcm_kt2_oam_lm_counters_mems_from_pool_get(int pool_id, soc_mem_t *mems) 3971 { 3972 switch(pool_id) { 3973 case 0: 3974 mems[0] = OAM_LM_COUNTERS_0m; 3975 mems[1] = EGR_OAM_LM_COUNTERS_0m; 3976 break; 3977 case 1: 3978 mems[0] = OAM_LM_COUNTERS_1m; 3979 mems[1] = EGR_OAM_LM_COUNTERS_1m; 3980 break; 3981 default: 3982 /* should not happen */ 3983 return BCM_E_INTERNAL; 3984 break; 3985 } 3986 return BCM_E_NONE; 3987 } 3988 3989 3990 STATIC int 3991 _bcm_kt2_oam_lm_counters_hw_values_init(int unit, int pool_id, int ctr_index) 3992 { 3993 oam_lm_counters_0_entry_t entry; 3994 /* Ingress and egress. 2 memories */ 3995 soc_mem_t mems[2] = {INVALIDm, INVALIDm}; 3996 int index, entry_offset; 3997 3998 BCM_IF_ERROR_RETURN( 3999 _bcm_kt2_oam_lm_counters_mems_from_pool_get(pool_id, mems)); 4000 4001 for (index = 0; index < 2; index++) { 4002 sal_memset(&entry, 0, sizeof(entry)); 4003 4004 /* 8 entries allocated per endpoint */ 4005 for(entry_offset = 0; entry_offset < 8; entry_offset++) { 4006 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mems[index], MEM_BLOCK_ALL, 4007 ctr_index + entry_offset, &entry)); 4008 } 4009 } 4010 4011 return BCM_E_NONE; 4012 } 4013 4014 STATIC int 4015 _bcm_kt2_oam_lm_counters_hw_values_reset(int unit, int pool_id, int index) 4016 { 4017 4018 return _bcm_kt2_oam_lm_counters_hw_values_init(unit, pool_id, index); 4019 } 4020 4021 /* 4022 * Function: 4023 * _bcm_kt2_oam_free_counter 4024 * Purpose: 4025 * Free counter from counter pool. 4026 * Parameters: 4027 * unit - (IN) BCM device number 4028 * Retruns: 4029 * BCM_E_XXX 4030 */ 4031 STATIC int 4032 _bcm_kt2_oam_free_counter(int unit, 4033 _bcm_oam_hash_data_t *hash_data) 4034 { 4035 int rv = BCM_E_NONE;/* Operation return status. */ 4036 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 4037 int pool_id = 0; 4038 4039 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 4040 4041 if (hash_data->rx_ctr != _BCM_OAM_INVALID_INDEX) { 4042 pool_id = (hash_data->rx_ctr >> 24); 4043 rv = shr_aidxres_list_free(oc->ing_lm_ctr_pool[pool_id], 4044 (hash_data->rx_ctr & 0xffffff)); 4045 4046 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_lm_counters_hw_values_reset(unit, pool_id, 4047 hash_data->rx_ctr & 0xffffff)); 4048 if (BCM_FAILURE(rv)) { 4049 LOG_ERROR(BSL_LS_BCM_OAM, 4050 (BSL_META_U(unit, 4051 "OAM Error: LM counter block " 4052 "free failed (EP=%d) - %s.\n"), 4053 hash_data->ep_id, bcm_errmsg(rv))); 4054 return (rv); 4055 } 4056 hash_data->rx_ctr = _BCM_OAM_INVALID_INDEX; 4057 } 4058 return (rv); 4059 } 4060 4061 /* 4062 * Function: 4063 * _bcm_kt2_oam_alloc_counter 4064 * Purpose: 4065 * Allocate counter from counter pool. 4066 * Parameters: 4067 * unit - (IN) BCM device number 4068 * Retruns: 4069 * BCM_E_XXX 4070 */ 4071 STATIC int 4072 _bcm_kt2_oam_alloc_counter(int unit, int pool_id, 4073 shr_idxres_element_t *ctr_index) 4074 { 4075 int rv; /* Operation return status. */ 4076 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 4077 4078 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 4079 4080 /* Allocate 8 consecutive couters from the pool */ 4081 rv = shr_aidxres_list_alloc_block(oc->ing_lm_ctr_pool[pool_id], 4082 8, ctr_index); 4083 if (BCM_FAILURE(rv)) { 4084 LOG_ERROR(BSL_LS_BCM_OAM, 4085 (BSL_META_U(unit, 4086 "OAM Error: LM counter block alloic failed " 4087 "- %s.\n"), bcm_errmsg(rv))); 4088 return (rv); 4089 } 4090 return (BCM_E_NONE); 4091 } 4092 4093 #if defined(INCLUDE_BHH) 4094 /* 4095 * Function: 4096 * _bcm_kt2_oam_bhh_sec_mep_alloc_counter 4097 * Purpose: 4098 * Allocate counter from counter pool. 4099 * Parameters: 4100 * unit - (IN) BCM device number 4101 * Retruns: 4102 * BCM_E_XXX 4103 */ 4104 STATIC int 4105 _bcm_kt2_oam_bhh_sec_mep_alloc_counter(int unit, shr_idxres_element_t *ctr_index) 4106 { 4107 int rv; /* Operation return status. */ 4108 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 4109 4110 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 4111 4112 /* Allocate 8 consecutive couters from the pool */ 4113 rv = shr_aidxres_list_alloc_block(oc->ing_lm_sec_mep_ctr_pool, 4114 8, ctr_index); 4115 if (BCM_FAILURE(rv)) { 4116 LOG_ERROR(BSL_LS_BCM_OAM, 4117 (BSL_META_U(unit, 4118 "OAM Error: LM counter block alloc failed " 4119 "- %s.\n"), bcm_errmsg(rv))); 4120 return (rv); 4121 } 4122 4123 return (BCM_E_NONE); 4124 } 4125 #endif 4126 /* 4127 * Function: 4128 * _bcm_kt2_oam_counter_set 4129 * Purpose: 4130 * Set Rx counter for MEP 4131 * Parameters: 4132 * unit - (IN) BCM device number 4133 * Retruns: 4134 * BCM_E_XXX 4135 */ 4136 STATIC int 4137 _bcm_kt2_oam_counter_set(int unit, soc_mem_t mem, 4138 uint32 *entry, 4139 shr_idxres_element_t *ctr_index, 4140 int *pool_id) 4141 { 4142 4143 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 4144 soc_field_t ctr1_field; 4145 soc_field_t ctr2_field; 4146 int ctr1_valid = 0; 4147 int ctr2_valid = 0; 4148 int rv = BCM_E_NONE;/* Operation return status. */ 4149 4150 /* Lock already taken by the calling routine. */ 4151 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 4152 4153 if (mem == L3_ENTRY_IPV4_UNICASTm) { 4154 ctr1_field = LMEP__CTR1_VALIDf; 4155 ctr2_field = LMEP__CTR2_VALIDf; 4156 } else { 4157 ctr1_field = CTR1_VALIDf; 4158 ctr2_field = CTR2_VALIDf; 4159 } 4160 4161 ctr1_valid = soc_mem_field32_get(unit, mem, 4162 (uint32 *)entry, ctr1_field); 4163 ctr2_valid = soc_mem_field32_get(unit, mem, 4164 (uint32 *)entry, ctr2_field); 4165 4166 /* if both counters are already used, we can't enable LM on this endpoint */ 4167 if ((1 == ctr1_valid) && (1 == ctr2_valid)) { 4168 rv = BCM_E_RESOURCE; 4169 LOG_ERROR(BSL_LS_BCM_OAM, 4170 (BSL_META_U(unit, 4171 "OAM Error: 2 counters are already " 4172 "allocated for EP on this service interface" 4173 "%s.\n"), bcm_errmsg(rv))); 4174 return (rv); 4175 } else if ((0 == ctr1_valid) && (1 == ctr2_valid)) { 4176 *pool_id = 0; 4177 rv = _bcm_kt2_oam_alloc_counter(unit, *pool_id, ctr_index); 4178 if (BCM_FAILURE(rv)) { 4179 LOG_ERROR(BSL_LS_BCM_OAM, 4180 (BSL_META_U(unit, 4181 "OAM Error: LM counter block alloc - %s.\n"), 4182 bcm_errmsg(rv))); 4183 return (rv); 4184 } 4185 ctr1_valid = 1; 4186 } else if ((0 == ctr2_valid) && (1 == ctr1_valid)) { 4187 *pool_id = 1; 4188 rv = _bcm_kt2_oam_alloc_counter(unit, *pool_id, ctr_index); 4189 if (BCM_FAILURE(rv)) { 4190 LOG_ERROR(BSL_LS_BCM_OAM, 4191 (BSL_META_U(unit, 4192 "OAM Error: LM counter block alloc - %s.\n"), 4193 bcm_errmsg(rv))); 4194 return (rv); 4195 } 4196 ctr2_valid = 1; 4197 } else { 4198 *pool_id = 0; 4199 rv = _bcm_kt2_oam_alloc_counter(unit, *pool_id, ctr_index); 4200 if (BCM_FAILURE(rv)) { 4201 *pool_id = 1; 4202 rv = _bcm_kt2_oam_alloc_counter(unit, *pool_id, ctr_index); 4203 if (BCM_FAILURE(rv)) { 4204 LOG_ERROR(BSL_LS_BCM_OAM, 4205 (BSL_META_U(unit, 4206 "OAM Error: LM counter block alloc - %s.\n"), 4207 bcm_errmsg(rv))); 4208 return (rv); 4209 } 4210 } 4211 ctr1_valid = 1; 4212 } 4213 return (rv); 4214 } 4215 /* 4216 * Function: 4217 * _bcm_kt2_oam_service_pri_profile_add 4218 * Purpose: 4219 * Create ING_SERVICE_PRI_MAP or EGR_SERVICE_PRI_MAP profile entry 4220 * Parameters: 4221 * unit - (IN) BCM device number 4222 * egr - (IN) Ingress/egess profile 4223 * ep_info_p - (IN) Pointer to remote endpoint information. 4224 * profile_index - (IN) Index of the profile entry created 4225 * Retruns: 4226 * BCM_E_XXX 4227 */ 4228 int 4229 _bcm_kt2_oam_service_pri_profile_add(int unit, int egr, 4230 bcm_oam_endpoint_info_t *endpoint_info, 4231 uint32 *profile_index) 4232 { 4233 int rv = BCM_E_NONE; 4234 int i = 0; 4235 void *entries[1]; 4236 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 4237 soc_mem_t mem = ING_SERVICE_PRI_MAPm; 4238 uint32 mem_entries[BCM_OAM_INTPRI_MAX]; 4239 soc_profile_mem_t *profile; /* profile to be used ingress or egress */ 4240 4241 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 4242 if (egr) { 4243 mem = EGR_SERVICE_PRI_MAPm; 4244 profile = &oc->egr_service_pri_map; 4245 } else { 4246 profile = &oc->ing_service_pri_map; 4247 } 4248 for (i = 0; i < BCM_OAM_INTPRI_MAX; i++) { 4249 if (endpoint_info->pri_map[i] > _BCM_OAM_SERVICE_PRI_MAX_OFFSET) { 4250 return BCM_E_PARAM; 4251 } 4252 mem_entries[i] = endpoint_info->pri_map[i]; 4253 if (SOC_MEM_FIELD_VALID(unit, mem, OFFSET_VALIDf)) { 4254 soc_mem_field32_set(unit, mem, &mem_entries[i], OFFSET_VALIDf, 1); 4255 } 4256 } 4257 soc_mem_lock(unit, mem); 4258 entries[0] = &mem_entries; 4259 rv = soc_profile_mem_add(unit, profile, (void *) &entries, 4260 BCM_OAM_INTPRI_MAX, profile_index); 4261 if (BCM_FAILURE(rv)) { 4262 soc_mem_unlock(unit, mem); 4263 return rv; 4264 } 4265 *profile_index = ((*profile_index)/BCM_OAM_INTPRI_MAX); 4266 soc_mem_unlock(unit, mem); 4267 return rv; 4268 } 4269 4270 /* 4271 * Function: 4272 * _bcm_kt2_oam_lmep_counters_set 4273 * Purpose: 4274 * Get Tx counters for LMEP 4275 * Parameters: 4276 * unit - (IN) BCM device number 4277 * ep_info_p - (IN) Pointer to remote endpoint information. 4278 * Retruns: 4279 * BCM_E_XXX 4280 */ 4281 STATIC int 4282 _bcm_kt2_oam_lmep_counters_set(int unit, 4283 bcm_oam_endpoint_info_t *ep_info_p) 4284 { 4285 _bcm_oam_hash_data_t *hash_data; /* Pointer to endpoint hash data. */ 4286 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 4287 l3_entry_1_entry_t l3_entry; /* L3 entry buffer. */ 4288 int l3_index = -1; /* L3 entry hardware index. */ 4289 shr_idxres_element_t ctr_index = 0; 4290 int pool_id = 0; 4291 egr_mp_group_entry_t egr_mp_group; /* Egress MP group tbl entry buffer */ 4292 int mp_grp_index = 0; 4293 int rv = BCM_E_NONE;/* Operation return status. */ 4294 uint32 profile_index = 0; 4295 uint32 direction = 0; /* Up MEP or Down MEP */ 4296 4297 /* Lock already taken by the calling routine. */ 4298 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 4299 4300 /* Get the stored endpoint information from hash table. */ 4301 hash_data = &oc->oam_hash_data[ep_info_p->id]; 4302 if (0 == hash_data->in_use) { 4303 return (BCM_E_INTERNAL); 4304 } 4305 4306 if (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 4307 direction = 1; 4308 } 4309 4310 /*For downMEP Rx counters are in Ing Mp group table and for UpMEP 4311 it is in egr mp group table */ 4312 if (BCM_SUCCESS 4313 (_bcm_kt2_oam_find_lmep(unit, hash_data, &l3_index, &l3_entry))) { 4314 if (hash_data->tx_ctr == _BCM_OAM_INVALID_INDEX) { 4315 /* Allocate counters and configure the same in L3 entry */ 4316 rv = _bcm_kt2_oam_counter_set(unit, 4317 L3_ENTRY_IPV4_UNICASTm, 4318 (uint32 *)&l3_entry, 4319 &ctr_index, &pool_id); 4320 if (BCM_FAILURE(rv)) { 4321 LOG_ERROR(BSL_LS_BCM_OAM, 4322 (BSL_META_U(unit, 4323 "OAM Error: L3_ENTRY table update failed " 4324 "for EP=%d due to counter allocation failure " 4325 "%s.\n"), ep_info_p->id, bcm_errmsg(rv))); 4326 return (rv); 4327 } 4328 /* MS 8 bits of counter Id is pool id. LS 24 bits are index */ 4329 hash_data->tx_ctr = pool_id << 24 | (ctr_index); 4330 hash_data->rx_ctr = hash_data->tx_ctr; 4331 } else { 4332 pool_id = hash_data->tx_ctr >> 24; 4333 } 4334 ep_info_p->lm_counter_base_id = hash_data->tx_ctr; 4335 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, 4336 mep_ctr_info[pool_id].ctr_valid, 1); 4337 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, 4338 mep_ctr_info[pool_id].ctr_base_ptr, 4339 (hash_data->tx_ctr & 0xFFFFFF)); 4340 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, 4341 mep_ctr_info[pool_id].ctr_mep_type, direction); 4342 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, 4343 mep_ctr_info[pool_id].ctr_mep_mdl, ep_info_p->level); 4344 /* Create SERVICE_PRI_MAP profile */ 4345 rv = _bcm_kt2_oam_service_pri_profile_add(unit, 0, ep_info_p, 4346 &profile_index); 4347 if (BCM_FAILURE(rv)) { 4348 LOG_ERROR(BSL_LS_BCM_OAM, \ 4349 (BSL_META_U(unit, \ 4350 "OAM Error: L3_ENTRY table update failed " 4351 "for EP=%d due to service pri map profile allocation " 4352 "failure %s.\n"), 4353 ep_info_p->id, bcm_errmsg(rv))); 4354 return (rv); 4355 } 4356 hash_data->pri_map_index = profile_index; 4357 4358 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, 4359 mep_ctr_info[pool_id].ctr_profile, profile_index); 4360 4361 rv = soc_mem_write(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ALL, 4362 l3_index, &l3_entry); 4363 if (BCM_FAILURE(rv)) { 4364 LOG_ERROR(BSL_LS_BCM_OAM, 4365 (BSL_META_U(unit, 4366 "OAM Error: L3_ENTRY table write failed " 4367 "for EP=%d %s.\n"), 4368 ep_info_p->id, bcm_errmsg(rv))); 4369 return (rv); 4370 } 4371 4372 } else { 4373 LOG_ERROR(BSL_LS_BCM_OAM, 4374 (BSL_META_U(unit, 4375 "OAM Error: MP group tbl entry not found-%s.\n"), 4376 bcm_errmsg(rv))); 4377 return rv; 4378 } 4379 4380 /*For downMEP Tx counters are in Egr Mp group table and for UpMEP it 4381 is in ING MP group table */ 4382 if (BCM_SUCCESS(_bcm_kt2_oam_find_egr_lmep(unit, hash_data, 4383 &mp_grp_index, &egr_mp_group))) { 4384 if (hash_data->tx_ctr == _BCM_OAM_INVALID_INDEX) { 4385 rv = _bcm_kt2_oam_counter_set(unit, EGR_MP_GROUPm, 4386 (uint32 *)&egr_mp_group, &ctr_index, &pool_id); 4387 if (BCM_FAILURE(rv)) { 4388 LOG_ERROR(BSL_LS_BCM_OAM, 4389 (BSL_META_U(unit, 4390 "OAM Error: EGR_MP_GROUP table update " 4391 "failed for EP=%d due to counter allocation " 4392 "failure %s.\n"), 4393 ep_info_p->id, bcm_errmsg(rv))); 4394 return (rv); 4395 } 4396 /* MS 8 bits of counter Id is pool id. LS 24 bits are index */ 4397 hash_data->tx_ctr = pool_id << 24 | (ctr_index); 4398 hash_data->rx_ctr = hash_data->tx_ctr; 4399 } else { 4400 pool_id = hash_data->tx_ctr >> 24; 4401 } 4402 ep_info_p->lm_counter_base_id = hash_data->tx_ctr; 4403 if (SAL_BOOT_BCMSIM) { 4404 /* Added as WAR for Cmodel issue */ 4405 /* Construct endpoint egress MP group Table entry key part */ 4406 _bcm_oam_egr_lmep_key_construct(unit, hash_data, &egr_mp_group); 4407 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, VALIDf, 1); 4408 } 4409 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 4410 egr_mep_ctr_info[pool_id].ctr_valid, 1); 4411 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 4412 egr_mep_ctr_info[pool_id].ctr_base_ptr, 4413 (hash_data->tx_ctr & 0xFFFFFF)); 4414 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 4415 egr_mep_ctr_info[pool_id].ctr_mep_type, direction); 4416 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 4417 egr_mep_ctr_info[pool_id].ctr_mep_mdl, ep_info_p->level); 4418 4419 /* Create SERVICE_PRI_MAP profile */ 4420 rv = _bcm_kt2_oam_service_pri_profile_add(unit, 1, ep_info_p, 4421 &profile_index); 4422 if (BCM_FAILURE(rv)) { 4423 LOG_ERROR(BSL_LS_BCM_OAM, 4424 (BSL_META_U(unit, 4425 "OAM Error: EGR_MP_GROUP table update failed " 4426 "for EP=%d due to service pri map profile allocation " 4427 "failure %s.\n"), 4428 ep_info_p->id, bcm_errmsg(rv))); 4429 return (rv); 4430 } 4431 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 4432 egr_mep_ctr_info[pool_id].ctr_profile, profile_index); 4433 hash_data->egr_pri_map_index = profile_index; 4434 4435 rv = soc_mem_write(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL, 4436 mp_grp_index, &egr_mp_group); 4437 if (BCM_FAILURE(rv)) { 4438 LOG_ERROR(BSL_LS_BCM_OAM, 4439 (BSL_META_U(unit, 4440 "OAM Error: EGR_MP_GROUP table update failed " 4441 "for EP=%d %s.\n"), 4442 ep_info_p->id, bcm_errmsg(rv))); 4443 return (rv); 4444 } 4445 } else { 4446 LOG_ERROR(BSL_LS_BCM_OAM, 4447 (BSL_META_U(unit, 4448 "OAM Error: EGR MP group tbl entry not found-%s.\n"), 4449 bcm_errmsg(rv))); 4450 return rv; 4451 } 4452 4453 return (rv); 4454 } 4455 4456 /* 4457 * Function: 4458 * bcm_kt2_oam_hw_ccm_tx_ctr_update 4459 * Purpose: 4460 * Update CCM CTR params 4461 * Parameters: 4462 * unit - (IN) Unit number. 4463 * ep_info - (IN) Pointer to endpoint parameters 4464 * Returns: 4465 * BCM_E_XXX 4466 * Notes: 4467 */ 4468 STATIC int 4469 bcm_kt2_oam_hw_ccm_tx_ctr_update(int unit, 4470 bcm_oam_endpoint_info_t *ep_info) 4471 { 4472 4473 _bcm_oam_hash_data_t *h_data_p; 4474 _bcm_oam_control_t *oc; 4475 int rv=BCM_E_NONE; 4476 lmep_1_entry_t lmep_1_entry; /* LMEP_1 table entry.*/ 4477 uint8 num_counter; 4478 uint32 counter_id; 4479 uint32 pool; 4480 lmep_entry_t lmep_entry; /* LMEP_1 table entry.*/ 4481 4482 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 4483 4484 h_data_p = &oc->oam_hash_data[ep_info->id]; 4485 4486 /* Get the LMEP_1 table entry. for the endpoint*/ 4487 rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, &lmep_1_entry); 4488 if (BCM_FAILURE(rv)) { 4489 LOG_ERROR(BSL_LS_BCM_OAM, 4490 (BSL_META_U(unit, 4491 "OAM(unit %d) Error: LMEP_1 table read (index=%d) failed " 4492 "- %s.\n"), unit, h_data_p->local_tx_index, bcm_errmsg(rv))); 4493 return rv; 4494 } 4495 4496 /* Get the LMEP_1 table entry. for the endpoint*/ 4497 rv = READ_LMEPm(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, &lmep_entry); 4498 if (BCM_FAILURE(rv)) { 4499 LOG_ERROR(BSL_LS_BCM_OAM, 4500 (BSL_META_U(unit, 4501 "OAM(unit %d) Error: LMEP table read (index=%d) failed " 4502 "- %s.\n"), unit, h_data_p->local_tx_index, bcm_errmsg(rv))); 4503 return rv; 4504 } 4505 4506 if (_KT2_OAM_COUNTER_SIZE < ep_info->ccm_tx_update_lm_counter_size) { 4507 return BCM_E_PARAM; 4508 } 4509 4510 for(num_counter = 0; num_counter < ep_info->ccm_tx_update_lm_counter_size; 4511 num_counter++) { 4512 4513 /* Get the counter pool id */ 4514 counter_id = ep_info->ccm_tx_update_lm_counter_base_id[num_counter] + 4515 ep_info->ccm_tx_update_lm_counter_offset[num_counter]; 4516 pool = counter_id >> 24; 4517 4518 switch(pool){ 4519 case 0: 4520 /* Set Counter 1 ID and action */ 4521 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_1_IDf, 4522 (counter_id & 0xFFFF)); 4523 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_1_ACTIONf, 1); 4524 break; 4525 case 1: 4526 /* Set Counter 2 ID and action */ 4527 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_2_IDf, 4528 (counter_id & 0xFFFF)); 4529 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_2_ACTIONf, 1); 4530 break; 4531 default: 4532 return BCM_E_PARAM; 4533 } 4534 } 4535 4536 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 4537 /* TX counter is located in IP (0) */ 4538 soc_LMEPm_field32_set(unit, &lmep_entry, COUNTER_1_LOCATIONf, 0); 4539 soc_LMEPm_field32_set(unit, &lmep_entry, COUNTER_2_LOCATIONf, 0); 4540 } else { 4541 /* TX counter is located in EP (1) */ 4542 soc_LMEPm_field32_set(unit, &lmep_entry, COUNTER_1_LOCATIONf, 1); 4543 soc_LMEPm_field32_set(unit, &lmep_entry, COUNTER_2_LOCATIONf, 1); 4544 } 4545 4546 rv = WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index, 4547 &lmep_1_entry); 4548 if (BCM_FAILURE(rv)) { 4549 LOG_ERROR(BSL_LS_BCM_OAM, 4550 (BSL_META_U(unit, 4551 "OAM(unit %d) Error: LMEP_1 table write (EP=%d)" 4552 " failed - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 4553 return rv; 4554 } 4555 4556 rv = WRITE_LMEPm(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index, 4557 &lmep_entry); 4558 if (BCM_FAILURE(rv)) { 4559 LOG_ERROR(BSL_LS_BCM_OAM, 4560 (BSL_META_U(unit, 4561 "OAM(unit %d) Error: LMEP table write (EP=%d)" 4562 " failed - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 4563 return rv; 4564 } 4565 return rv; 4566 } 4567 4568 STATIC int 4569 _bcm_kt2_oam_lmep_down_modify_new_dest_port(int unit, _bcm_oam_hash_data_t *h_data_p) 4570 { 4571 4572 lmep_1_entry_t lmep_1_entry; /* LMEP_1 table entry.*/ 4573 4574 /* Get the LMEP_1 table entry. */ 4575 BCM_IF_ERROR_RETURN(READ_LMEP_1m(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, &lmep_1_entry)); 4576 4577 4578 /* Set the queue number */ 4579 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, QUEUE_NUMf, 4580 SOC_INFO(unit).port_uc_cosq_base[h_data_p->dst_pp_port] + 4581 h_data_p->int_pri); 4582 4583 /* Set the PP port */ 4584 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, PP_PORTf, h_data_p->dst_pp_port); 4585 4586 SOC_IF_ERROR_RETURN 4587 (WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index, 4588 &lmep_1_entry)); 4589 4590 4591 return (BCM_E_NONE); 4592 } 4593 /* 4594 * Function: 4595 * _bcm_oam_kt2_local_tx_mep_hw_set 4596 * Purpose: 4597 * Configure hardware tables for a local CCM Tx enabled endpoint. 4598 * Parameters: 4599 * unit - (IN) BCM device number 4600 * ep_info_p - (IN) Pointer to remote endpoint information. 4601 * Retruns: 4602 * BCM_E_XXX 4603 */ 4604 STATIC int 4605 _bcm_oam_kt2_local_tx_mep_hw_set(int unit, 4606 bcm_oam_endpoint_info_t *ep_info_p) 4607 { 4608 int rv = BCM_E_NONE;/* Operation return status. */ 4609 _bcm_oam_hash_data_t *hash_data; /* Pointer to endpoint hash data. */ 4610 lmep_entry_t entry; /* LMEP table entry. */ 4611 lmep_1_entry_t entry_1; /* LMEP_1 table entry. */ 4612 int word; /* Word index. */ 4613 uint32 reversed_maid[BCM_OAM_GROUP_NAME_LENGTH / 4]; 4614 /* Group name in Hw format. */ 4615 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 4616 const bcm_oam_endpoint_info_t *ep_p;/* Pointer to endpoint info. */ 4617 int subport = 0; 4618 int oam_replacement_offset = 0; 4619 int tpid_index = 0; 4620 _bcm_kt2_subport_info_t subport_info; 4621 int up_mep = 0; 4622 int pp_port = 0; 4623 int vlan_tag_control = 0; 4624 uint32 tag_type = 0; 4625 bcm_port_t up_mep_tx_port = 0; 4626 bcm_gport_t gport = 0; 4627 4628 if (NULL == ep_info_p) { 4629 return (BCM_E_INTERNAL); 4630 } 4631 4632 /* Initialize local endpoint info pointer. */ 4633 ep_p = ep_info_p; 4634 4635 /* Lock already taken by the calling routine. */ 4636 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 4637 4638 /* Get the stored endpoint information from hash table. */ 4639 hash_data = &oc->oam_hash_data[ep_p->id]; 4640 if (0 == hash_data->in_use) { 4641 return(BCM_E_INTERNAL); 4642 } 4643 4644 sal_memset(&entry, 0, sizeof(lmep_entry_t)); 4645 sal_memset(&entry_1, 0, sizeof(lmep_1_entry_t)); 4646 4647 /* Set the Group base index. */ 4648 soc_LMEPm_field32_set(unit, &entry, MAID_INDEXf, ep_p->group); 4649 4650 /* Set source MAC address to be used on transmitted packets. */ 4651 soc_LMEPm_mac_addr_set(unit, &entry, SAf, ep_p->src_mac_address); 4652 4653 /* Set the Maintenance Domain Level. */ 4654 soc_LMEPm_field32_set(unit, &entry, MDLf, ep_p->level); 4655 4656 /* Set endpoint name. */ 4657 soc_LMEPm_field32_set(unit, &entry, MEPIDf, ep_p->name); 4658 4659 /* 4660 * Set VLAN ID to be used in the transmitted packet. 4661 * For link level MEPs, this VLAN_ID == 0. 4662 */ 4663 soc_LMEPm_field32_set(unit, &entry, SVLAN_TAGf, ep_p->vlan); 4664 4665 /* Set packet priority value to be used in transmitted packet. */ 4666 soc_LMEPm_field32_set(unit, &entry, PRIORITYf, ep_p->pkt_pri); 4667 4668 /* Set CVLAN Id */ 4669 soc_LMEPm_field32_set(unit, &entry, CVLAN_TAGf, ((ep_p->inner_pkt_pri << 13) | ep_p->inner_vlan)); 4670 4671 /* Set interval between CCM packet transmissions. */ 4672 soc_LMEPm_field32_set 4673 (unit, &entry, CCM_INTERVALf, 4674 _bcm_kt2_oam_ccm_msecs_to_hw_encode(ep_p->ccm_period)); 4675 4676 /* Set Port status TLV in CCM Tx packets. */ 4677 if (ep_p->flags & BCM_OAM_ENDPOINT_PORT_STATE_UPDATE) { 4678 if (ep_p->port_state > BCM_OAM_PORT_TLV_UP) { 4679 return BCM_E_PARAM; 4680 } 4681 soc_LMEPm_field32_set(unit, &entry, PORT_TLVf, 4682 (ep_p->port_state == BCM_OAM_PORT_TLV_UP) 4683 ? 1 : 0); 4684 } 4685 4686 4687 /* Set the MEP type - up/down */ 4688 soc_LMEPm_field32_set(unit, &entry, MEP_TYPEf, 4689 ((ep_p->flags & BCM_OAM_ENDPOINT_UP_FACING) ? 1 : 0)); 4690 /* 4691 * Construct group name for hardware. 4692 * i.e Word-reverse the MAID bytes for hardware. 4693 */ 4694 for (word = 0; word < (BCM_OAM_GROUP_NAME_LENGTH / 4); ++word) { 4695 reversed_maid[word] 4696 = bcm_htonl(((uint32 *) oc->group_info[ep_p->group].name) 4697 [((BCM_OAM_GROUP_NAME_LENGTH / 4) - 1) - word]); 4698 } 4699 4700 /* Set the group name. */ 4701 soc_LMEPm_field_set(unit, &entry, MAIDf, reversed_maid); 4702 4703 /* Set OAM replacement offset & default TPID */ 4704 if (_BCM_OAM_EP_IS_VP_TYPE(hash_data)) { 4705 oam_replacement_offset = 1; 4706 if(hash_data->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) { 4707 oam_replacement_offset = 5; 4708 vlan_tag_control = 3; 4709 tag_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN; 4710 }else if (hash_data->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) { 4711 oam_replacement_offset = 3; 4712 vlan_tag_control = 1; 4713 tag_type =_BCM_OAM_DOMAIN_CVLAN; 4714 } else if (hash_data->vlan > 0) { 4715 oam_replacement_offset = 3; 4716 vlan_tag_control = 2; 4717 tag_type =_BCM_OAM_DOMAIN_SVLAN; 4718 } 4719 } 4720 4721 switch (hash_data->oam_domain) { 4722 case _BCM_OAM_DOMAIN_PORT: 4723 oam_replacement_offset = 1; 4724 vlan_tag_control = 0; 4725 break; 4726 4727 case _BCM_OAM_DOMAIN_CVLAN: 4728 vlan_tag_control = 1; 4729 oam_replacement_offset = 3; 4730 tag_type =_BCM_OAM_DOMAIN_CVLAN; 4731 break; 4732 4733 case _BCM_OAM_DOMAIN_SVLAN: 4734 oam_replacement_offset = 3; 4735 vlan_tag_control = 2; 4736 tag_type =_BCM_OAM_DOMAIN_SVLAN; 4737 break; 4738 4739 case _BCM_OAM_DOMAIN_S_PLUS_CVLAN: 4740 oam_replacement_offset = 5; 4741 vlan_tag_control = 3; 4742 tag_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN; 4743 break; 4744 4745 default: 4746 break; 4747 } 4748 4749 4750 /* if S or S+C vlan - set outer tpid index */ 4751 if ((tag_type == _BCM_OAM_DOMAIN_SVLAN) || 4752 (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN)) { 4753 rv = _bcm_kt2_tpid_entry_add(unit, 4754 (ep_p->outer_tpid ? ep_p->outer_tpid : 4755 BCM_OAM_DEFAULT_TPID), 4756 BCM_OAM_TPID_TYPE_OUTER, &tpid_index); 4757 if (BCM_FAILURE(rv)) { 4758 LOG_ERROR(BSL_LS_BCM_OAM, 4759 (BSL_META_U(unit, 4760 "OAM Error: L3 entry config failed in TPID set " 4761 "for EP=%d %s.\n"), 4762 ep_p->id, bcm_errmsg(rv))); 4763 return (rv); 4764 } 4765 hash_data->outer_tpid_profile_index = tpid_index; 4766 soc_LMEPm_field32_set(unit, &entry, SVLAN_TPID_INDEXf, tpid_index); 4767 } 4768 if ((tag_type == _BCM_OAM_DOMAIN_CVLAN) || 4769 /* C or S+C */ 4770 (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN)) { 4771 rv = _bcm_kt2_tpid_entry_add(unit, 4772 (ep_p->inner_tpid ? ep_p->inner_tpid : 4773 BCM_OAM_DEFAULT_TPID), 4774 BCM_OAM_TPID_TYPE_INNER, &tpid_index); 4775 if (BCM_FAILURE(rv)) { 4776 LOG_ERROR(BSL_LS_BCM_OAM, 4777 (BSL_META_U(unit, 4778 "OAM Error: L3 entry config failed in TPID set " 4779 "for EP=%d"" %s.\n"), ep_p->id, bcm_errmsg(rv))); 4780 return (rv); 4781 } 4782 hash_data->inner_tpid_profile_index = tpid_index; 4783 } 4784 4785 gport = hash_data->gport; 4786 if (BCM_GPORT_IS_TRUNK(ep_p->gport)) { 4787 gport = hash_data->resolved_trunk_gport; 4788 } 4789 4790 if ((BCM_GPORT_IS_SUBPORT_PORT(gport)) && 4791 (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport))) { 4792 /* CoE port */ 4793 rv = _bcm_kt2_tpid_entry_add(unit, 4794 (ep_p->subport_tpid ? ep_p->subport_tpid : 4795 BCM_OAM_DEFAULT_TPID), 4796 BCM_OAM_TPID_TYPE_SUBPORT, &tpid_index); 4797 if (BCM_FAILURE(rv)) { 4798 LOG_ERROR(BSL_LS_BCM_OAM, 4799 (BSL_META_U(unit, 4800 "OAM Error: L3 entry config failed in TPID set " 4801 "for EP=%d %s.\n"), ep_p->id, bcm_errmsg(rv))); 4802 return (rv); 4803 } 4804 soc_LMEPm_field32_set(unit, &entry, 4805 SUBPORT_TAG_TPID_INDEXf, tpid_index); 4806 hash_data->subport_tpid_profile_index = tpid_index; 4807 } 4808 4809 /* Set LMEP_1 table entry */ 4810 4811 /* If COE or LINKPHY port replacement offset should be increased 4812 by 2 to accomodate - stream_id/subport tag */ 4813 if (BCM_GPORT_IS_SUBPORT_PORT(gport)) { 4814 if ((_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)) || 4815 (_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, gport))) { 4816 oam_replacement_offset += 2; 4817 subport = 1 << 2; 4818 } 4819 } 4820 4821 soc_LMEP_1m_field32_set(unit, &entry_1, OAM_REPLACEMENT_OFFSETf, 4822 oam_replacement_offset); 4823 4824 4825 /* Set Tag status of the generated CCM packet 4826 we can set it based on incoming packet tag info 4827 if SUBPORT - vlan tag control = 1 << 2 | hash_data->oam_domain & 0x3 */ 4828 if (subport) { 4829 soc_LMEP_1m_field32_set(unit, &entry_1, VLAN_TAG_CONTROLf, 4830 (subport | (vlan_tag_control & 0x3))); 4831 } else { 4832 soc_LMEP_1m_field32_set(unit, &entry_1, VLAN_TAG_CONTROLf, 4833 (vlan_tag_control & 0x3)); 4834 4835 } 4836 /* allocate TX counters */ 4837 /* allocate TX counters */ 4838 if(ep_info_p->type == bcmOAMEndpointTypeEthernet) { 4839 if((ep_info_p->ccm_tx_update_lm_counter_size) && 4840 (_BCM_OAM_INVALID_INDEX != hash_data->local_tx_index)) { 4841 BCM_IF_ERROR_RETURN(bcm_kt2_oam_hw_ccm_tx_ctr_update(unit, ep_info_p)); 4842 } 4843 } 4844 4845 if (ep_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 4846 up_mep = 1; 4847 } 4848 /* For DownMEP, set Queue number to which this packet must be enqueued */ 4849 if (!up_mep) { 4850 soc_LMEP_1m_field32_set(unit, &entry_1, QUEUE_NUMf, 4851 SOC_INFO(unit).port_uc_cosq_base[hash_data->dst_pp_port] + 4852 ep_p->int_pri); 4853 /* Set the destination portt on which packet needs to Tx. */ 4854 pp_port = hash_data->dst_pp_port; 4855 } else { 4856 soc_LMEP_1m_field32_set(unit, &entry_1, INT_PRIf, 4857 ep_p->int_pri); 4858 /* Set the source on which packet is received */ 4859 pp_port = hash_data->src_pp_port; 4860 } 4861 4862 if (ep_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW) { 4863 4864 up_mep_tx_port = _BCM_KT2_SUBPORT_PORT_ID_GET(ep_p->tx_gport); 4865 hash_data->src_pp_port = up_mep_tx_port; 4866 pp_port = hash_data->src_pp_port; 4867 } 4868 4869 /* Set the PP port */ 4870 soc_LMEP_1m_field32_set(unit, &entry_1, PP_PORTf, pp_port); 4871 4872 /* Set Outgoing Subport tag to be inserted into CCM packet */ 4873 if ((BCM_GPORT_IS_SUBPORT_PORT(gport)) && 4874 (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport))) { 4875 /* Get the subport tag */ 4876 rv = bcm_kt2_subport_pp_port_subport_info_get(unit, pp_port, 4877 &subport_info); 4878 if (BCM_FAILURE(rv)) { 4879 LOG_ERROR(BSL_LS_BCM_OAM, 4880 (BSL_META_U(unit, 4881 "OAM Error: failed to get subport tag EP=%d" 4882 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 4883 return (rv); 4884 } 4885 if (subport_info.port_type == _BCM_KT2_SUBPORT_TYPE_SUBTAG) { 4886 soc_LMEP_1m_field32_set(unit, &entry_1, SUBPORT_TAGf, 4887 subport_info.subtag); 4888 } 4889 } 4890 4891 /* Set Interface status TLV in CCM Tx packets - 3-bits wide. */ 4892 if (ep_p->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_UPDATE) { 4893 if ((ep_p->interface_state < BCM_OAM_INTERFACE_TLV_UP) 4894 || (ep_p->interface_state > BCM_OAM_INTERFACE_TLV_LLDOWN)) { 4895 return BCM_E_PARAM; 4896 } 4897 soc_LMEP_1m_field32_set(unit, &entry_1, INTERFACE_TLVf, 4898 ep_p->interface_state); 4899 } 4900 /* 4901 * When this bit is '1', both port and interface TLV values are set in 4902 * CCM Tx packets - set in LMEP table. 4903 */ 4904 if ((ep_p->flags & BCM_OAM_ENDPOINT_PORT_STATE_TX) 4905 || (ep_p->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_TX)) { 4906 soc_LMEPm_field32_set(unit, &entry, INSERT_TLVf, 1); 4907 } 4908 4909 /* Set CCM packet Destination MAC address value. */ 4910 soc_mem_mac_addr_set(unit, LMEP_1m, &entry_1, DAf, 4911 ep_p->dst_mac_address); 4912 4913 4914 /* Write entry to hardware LMEP table. */ 4915 SOC_IF_ERROR_RETURN 4916 (WRITE_LMEPm(unit, MEM_BLOCK_ALL, hash_data->local_tx_index, 4917 &entry)); 4918 4919 /* Write entry to hardware LMEP_1 table. */ 4920 SOC_IF_ERROR_RETURN 4921 (WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, hash_data->local_tx_index, 4922 &entry_1)); 4923 4924 4925 return (BCM_E_NONE); 4926 } 4927 4928 /* 4929 * Function: 4930 * _bcm_kt2_oam_stm_table_update 4931 * Purpose: 4932 * Update MA_BASE_PTR in source trunk MAP table 4933 * Parameters: 4934 * unit - (IN) BCM device number 4935 * mod_id - (IN) module id 4936 * port_id - (IN) port id 4937 * h_data_p - (IN) endpoint hash data 4938 * Retruns: 4939 * BCM_E_XXX 4940 */ 4941 STATIC int 4942 _bcm_kt2_oam_stm_table_update(int unit, bcm_module_t mod_id, 4943 bcm_port_t port_id, 4944 _bcm_oam_hash_data_t *h_data_p) 4945 { 4946 int stm_index = 0; 4947 int rv; 4948 source_trunk_map_table_entry_t stm_entry; 4949 4950 soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm); 4951 4952 /* Derive index to SOURCE_TRUNK_MAP tbl based on module ID and port*/ 4953 rv = _bcm_esw_src_mod_port_table_index_get(unit, mod_id, 4954 port_id, &stm_index); 4955 4956 if(BCM_FAILURE(rv)) { 4957 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 4958 return rv; 4959 } 4960 4961 rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY, 4962 stm_index, &stm_entry); 4963 4964 if(BCM_FAILURE(rv)) { 4965 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 4966 return rv; 4967 } 4968 4969 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry, MA_BASE_PTRf, 4970 h_data_p->ma_base_index); 4971 rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ALL, stm_index, 4972 &stm_entry); 4973 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 4974 4975 return rv; 4976 } 4977 4978 4979 /* 4980 * Function: 4981 * _bcm_kt2_oam_port_mdl_update 4982 * Purpose: 4983 * Update MDL bitmap in port table 4984 * Parameters: 4985 * unit - (IN) BCM device number 4986 * pp_port - (IN) pp port id 4987 * reset - (IN) Reset MDL bitmap or not 4988 * h_data_p - (IN) endpoint hash data 4989 * mdl - (OUT) Maintenance domain level 4990 * Retruns: 4991 * BCM_E_XXX 4992 */ 4993 STATIC int 4994 _bcm_kt2_oam_port_mdl_update(int unit, uint32 pp_port, int reset, 4995 _bcm_oam_hash_data_t *h_data_p, uint8 *mdl) 4996 { 4997 port_tab_entry_t port_entry; 4998 4999 if (NULL == h_data_p) { 5000 return (BCM_E_INTERNAL); 5001 } 5002 BCM_IF_ERROR_RETURN 5003 (soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, pp_port, &port_entry)); 5004 5005 /* read and update MDL bitmap */ 5006 *mdl = soc_PORT_TABm_field32_get(unit, &port_entry, MDL_BITMAPf); 5007 if (reset) { 5008 /* Clear the MDL bit for this endpoint. */ 5009 *mdl &= ~(1 << h_data_p->level); 5010 5011 } else { 5012 *mdl |= (1 << h_data_p->level); 5013 } 5014 soc_PORT_TABm_field32_set(unit, &port_entry, MDL_BITMAPf, *mdl); 5015 BCM_IF_ERROR_RETURN 5016 (soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, pp_port, &port_entry)); 5017 5018 return BCM_E_NONE; 5019 } 5020 5021 /* 5022 * Function: 5023 * _bcm_kt2_oam_port_mdl_passive_update 5024 * Purpose: 5025 * Update passive MDL bitmap in egress port table 5026 * Parameters: 5027 * unit - (IN) BCM device number 5028 * reset - (IN) Reset MDL bitmap 5029 * h_data_p - (IN) endpoint hash data 5030 * Retruns: 5031 * BCM_E_XXX 5032 */ 5033 STATIC int 5034 _bcm_kt2_oam_port_mdl_passive_update(int unit, int reset, 5035 _bcm_oam_hash_data_t *h_data_p, uint8 mdl) 5036 { 5037 egr_port_entry_t egr_port_entry; 5038 uint8 passive_mdl = 0; /* Maintenance domain level-passive */ 5039 5040 if (NULL == h_data_p) { 5041 return (BCM_E_INTERNAL); 5042 } 5043 5044 /* Passive demux should not be done for MIP */ 5045 if (_BCM_OAM_EP_IS_MIP(h_data_p)) { 5046 return BCM_E_NONE; 5047 } 5048 5049 /* Set MDL passive bitmap in EGR_PORT table */ 5050 BCM_IF_ERROR_RETURN 5051 (soc_mem_read(unit, EGR_PORTm, MEM_BLOCK_ANY, h_data_p->dst_pp_port, 5052 &egr_port_entry)); 5053 5054 if (reset) { 5055 if (mdl > 0) { 5056 /* Passive MDL bitmap */ 5057 _bcm_kt2_oam_get_passive_mdl_from_active_mdl(unit, mdl, 5058 h_data_p->ma_base_index, &passive_mdl, 0); 5059 } else { 5060 passive_mdl = 0; 5061 } 5062 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 5063 MDL_BITMAP_PASSIVEf, passive_mdl); 5064 } else { 5065 /* read and update MDL bitmap */ 5066 mdl = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, 5067 MDL_BITMAP_PASSIVEf); 5068 mdl |= (1 << h_data_p->level); 5069 5070 /* Set all the bits till the highest configured MDL, so that there are 5071 no holes in the bitmap */ 5072 mdl |= ((1 << h_data_p->level) - 1); 5073 5074 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 5075 MDL_BITMAP_PASSIVEf, mdl); 5076 } 5077 BCM_IF_ERROR_RETURN 5078 (soc_mem_write(unit, EGR_PORTm, MEM_BLOCK_ALL, 5079 h_data_p->dst_pp_port, &egr_port_entry)); 5080 return BCM_E_NONE; 5081 } 5082 5083 /* 5084 * Function: 5085 * _bcm_kt2_oam_trunk_port_mdl_config 5086 * Purpose: 5087 * Update port mdl and stm table for OAM on trunk case 5088 * Parameters: 5089 * unit - (IN) BCM device number 5090 * h_data_p - (IN) Pointer to hash data 5091 * Retruns: 5092 * BCM_E_XXX 5093 */ 5094 STATIC int 5095 _bcm_kt2_oam_trunk_port_mdl_config(int unit, 5096 _bcm_oam_hash_data_t *h_data_p) 5097 { 5098 int rv = BCM_E_NONE;/* Operation return status. */ 5099 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 5100 int member_count = 0; 5101 bcm_port_t *member_array = NULL; /* Trunk member port array. */ 5102 int local_member_count = 0; 5103 int i = 0; 5104 bcm_port_t port = 0; 5105 bcm_module_t module_id; /* Module ID */ 5106 uint8 mdl = 0; 5107 5108 /* Lock already taken by the calling routine. */ 5109 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 5110 5111 if(h_data_p->trunk_id == BCM_TRUNK_INVALID) { 5112 return BCM_E_PARAM; 5113 } 5114 5115 /* Get all the local member ports belonging to this trunk */ 5116 BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, h_data_p->trunk_id, 5117 NULL, 0, NULL, &member_count)); 5118 if (0 == member_count) { 5119 /* No members have been added to the trunk group yet */ 5120 LOG_ERROR(BSL_LS_BCM_OAM, 5121 (BSL_META_U(unit, 5122 "OAM Error: No local members have been added to " 5123 "the trunk group yet - %s.\n"), bcm_errmsg(rv))); 5124 return BCM_E_PARAM; 5125 } 5126 5127 _BCM_OAM_ALLOC(member_array, bcm_port_t, 5128 sizeof(bcm_port_t) * member_count, "Trunk info"); 5129 if (NULL == member_array) { 5130 return (BCM_E_MEMORY); 5131 } 5132 5133 /* Get members of the trunk belonging to this module */ 5134 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 5135 h_data_p->trunk_id, 5136 member_count, member_array, 5137 &local_member_count))) { 5138 if (local_member_count > 0) { 5139 for(i = 0; i < local_member_count; i++) { 5140 rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i], 5141 &module_id, &port); 5142 if (BCM_FAILURE(rv)) { 5143 sal_free(member_array); 5144 return (rv); 5145 } 5146 rv = _bcm_kt2_oam_stm_table_update(unit, module_id, 5147 member_array[i], h_data_p); 5148 if (BCM_FAILURE(rv)) { 5149 sal_free(member_array); 5150 return (rv); 5151 } 5152 rv =_bcm_kt2_oam_port_mdl_update(unit, member_array[i], 0, 5153 h_data_p, &mdl); 5154 if (BCM_FAILURE(rv)) { 5155 sal_free(member_array); 5156 return (rv); 5157 } 5158 } 5159 } 5160 h_data_p->active_mdl_bitmap = mdl; 5161 } 5162 sal_free(member_array); 5163 return BCM_E_NONE; 5164 } 5165 5166 /* 5167 * Function: 5168 * _bcm_port_domain_oam_hw_set 5169 * Purpose: 5170 * Configure port table and stm table entries for port based MEP. 5171 * Parameters: 5172 * unit - (IN) BCM device number 5173 * ep_info_p - (IN) Pointer to remote endpoint information. 5174 * Retruns: 5175 * BCM_E_XXX 5176 */ 5177 STATIC int 5178 _bcm_port_domain_oam_hw_set(int unit, 5179 const bcm_oam_endpoint_info_t *ep_info_p) 5180 { 5181 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 5182 int rv = BCM_E_NONE;/* Operation return status. */ 5183 uint8 mdl = 0; /* Maintenance domain level. */ 5184 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 5185 const bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint info. */ 5186 bcm_module_t mod_id = 0; 5187 bcm_port_t port_id = 0; 5188 5189 if (NULL == ep_info_p) { 5190 return (BCM_E_INTERNAL); 5191 } 5192 5193 /* Initialize local endpoint info pointer. */ 5194 ep_p = ep_info_p; 5195 5196 /* Lock already taken by the calling routine. */ 5197 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 5198 5199 /* Get endpoint hash data pointer. */ 5200 h_data_p = &oc->oam_hash_data[ep_p->id]; 5201 5202 /* Set port table and source trunk map table */ 5203 if (0 == ep_info_p->vlan) { 5204 if(h_data_p->trunk_id != BCM_TRUNK_INVALID) { 5205 rv = _bcm_kt2_oam_trunk_port_mdl_config(unit, h_data_p); 5206 } else { 5207 port_id = _BCM_OAM_GLP_PORT_GET(h_data_p->sglp); 5208 mod_id = _BCM_OAM_GLP_MODULE_ID_GET(h_data_p->sglp); 5209 BCM_IF_ERROR_RETURN 5210 (_bcm_kt2_oam_stm_table_update(unit, mod_id, 5211 port_id, h_data_p)); 5212 BCM_IF_ERROR_RETURN 5213 (_bcm_kt2_oam_port_mdl_update(unit, h_data_p->src_pp_port, 0, 5214 h_data_p, &mdl)); 5215 h_data_p->active_mdl_bitmap = mdl; 5216 } 5217 BCM_IF_ERROR_RETURN 5218 (_bcm_kt2_oam_port_mdl_passive_update(unit, 0, h_data_p, mdl)); 5219 } 5220 return (rv); 5221 } 5222 5223 5224 /* 5225 * Function: 5226 * _bcm_kt2_oam_l3_entry_set 5227 * Purpose: 5228 * Configure l3 entry tables entry for a local CCM Rx enabled endpoint. 5229 * Parameters: 5230 * unit - (IN) BCM device number 5231 * ep_info_p - (IN) Pointer to remote endpoint information. 5232 * Retruns: 5233 * BCM_E_XXX 5234 */ 5235 STATIC int 5236 _bcm_kt2_oam_l3_entry_set(int unit, 5237 bcm_oam_endpoint_info_t *ep_info_p) 5238 { 5239 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 5240 l3_entry_1_entry_t l3_entry; /* L3 entry buffer. */ 5241 int l3_index = -1; /* L3 entry hardware index. */ 5242 int rv; /* Operation return status. */ 5243 uint8 mdl = 0; /* Maintenance domain level. */ 5244 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 5245 bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint info. */ 5246 soc_field_t mdl_field = 0; 5247 int up_mep = 0; /* Endpoint is an upMep */ 5248 5249 if (NULL == ep_info_p) { 5250 return (BCM_E_INTERNAL); 5251 } 5252 5253 /* Initialize local endpoint info pointer. */ 5254 ep_p = ep_info_p; 5255 5256 /* Lock already taken by the calling routine. */ 5257 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 5258 5259 /* Get endpoint hash data pointer. */ 5260 h_data_p = &oc->oam_hash_data[ep_p->id]; 5261 5262 if (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 5263 up_mep = 1 ; 5264 mdl_field = LMEP__MDL_BITMAP_PASSIVEf; 5265 } else { 5266 mdl_field = LMEP__MDL_BITMAP_ACTIVEf; 5267 } 5268 /* L3 entry */ 5269 L3_LOCK(unit); 5270 if (BCM_SUCCESS 5271 (_bcm_kt2_oam_find_lmep(unit, h_data_p, &l3_index, &l3_entry))) { 5272 if ((mdl_field == LMEP__MDL_BITMAP_PASSIVEf) && 5273 (_BCM_OAM_EP_IS_MIP(h_data_p))) { 5274 /* Passive demultiplexing should not be done on a MIP */ 5275 L3_UNLOCK(unit); 5276 return BCM_E_NONE; 5277 } 5278 5279 /* There's already an entry for this */ 5280 mdl = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, mdl_field); 5281 5282 /* If active bitmap is 0, so for first active endppoint in the mp_group 5283 * need to programme ma_base_ptr field during down_mep creation */ 5284 if((mdl == 0) && (up_mep == 0)) { 5285 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, LMEP__MA_BASE_PTRf, 5286 h_data_p->ma_base_index); 5287 } 5288 5289 mdl |= (1 << ep_p->level); 5290 5291 /* Set all the bits till the highest configured MDL, so that there are 5292 no holes in the passive bitmap */ 5293 if (up_mep) { 5294 mdl |= ((1 << ep_p->level) - 1); 5295 } 5296 /* set MDL bitmap passive or active depending on up or down mep */ 5297 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, mdl_field, mdl); 5298 5299 rv = soc_mem_write(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ALL, 5300 l3_index, &l3_entry); 5301 if (BCM_FAILURE(rv)) { 5302 L3_UNLOCK(unit); 5303 LOG_ERROR(BSL_LS_BCM_OAM, 5304 (BSL_META_U(unit, 5305 "OAM Error: L3_ENTRY table update failed for " 5306 "EP=%d" " %s.\n"), ep_p->id, bcm_errmsg(rv))); 5307 return (rv); 5308 } 5309 } else { 5310 5311 /* This is the first entry at this */ 5312 sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t)); 5313 5314 /* Passive demultiplexing should not be done on a MIP */ 5315 if (!((mdl_field == LMEP__MDL_BITMAP_PASSIVEf) 5316 && (_BCM_OAM_EP_IS_MIP(h_data_p)))) { 5317 mdl |= (1 << ep_p->level); 5318 5319 /* Set all the bits till the highest configured MDL, so that there are 5320 no holes in the passive bitmap */ 5321 if (up_mep) { 5322 mdl |= ((1 << ep_p->level) - 1); 5323 } 5324 } 5325 /* set MDL bitmap passive or active depending on up or down mep */ 5326 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, mdl_field, mdl); 5327 5328 if (mdl == 0) { 5329 /* MDL = 0 for case of MIP. Dont make the entry valid by 5330 programming other fields. */ 5331 return BCM_E_NONE; 5332 } 5333 5334 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, 5335 LMEP__MA_BASE_PTRf, 5336 h_data_p->ma_base_index); 5337 5338 /* Configure time stamp type 1588(PTP)/NTP */ 5339 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, 5340 LMEP__TIMESTAMP_TYPEf, 5341 ((ep_p->timestamp_format == bcmOAMTimestampFormatNTP) ? 1 : 0)); 5342 5343 h_data_p->ts_format = ep_p->timestamp_format; 5344 5345 /* Construct LMEP view key for L3 Table insert operation. */ 5346 _bcm_kt2_oam_lmep_key_construct(unit, h_data_p, &l3_entry); 5347 5348 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, VALIDf, 1); 5349 5350 rv = soc_mem_insert(unit, L3_ENTRY_IPV4_UNICASTm, 5351 MEM_BLOCK_ALL, &l3_entry); 5352 if (BCM_FAILURE(rv)) { 5353 LOG_ERROR(BSL_LS_BCM_OAM, 5354 (BSL_META_U(unit, 5355 "OAM Error: L3_ENTRY table insert failed for " 5356 "EP=%d" " %s.\n"), ep_p->id, bcm_errmsg(rv))); 5357 L3_UNLOCK(unit); 5358 return (rv); 5359 } 5360 } 5361 if (up_mep == 0) { 5362 h_data_p->active_mdl_bitmap = mdl; 5363 } 5364 L3_UNLOCK(unit); 5365 return (BCM_E_NONE); 5366 } 5367 5368 /* 5369 * Function: 5370 * _bcm_kt2_oam_egr_mp_group_entry_set 5371 * Purpose: 5372 * Configure Egress MP group tables entry for local CCM Rx enabled endpoint. 5373 * Parameters: 5374 * unit - (IN) BCM device number 5375 * ep_info_p - (IN) Pointer to remote endpoint information. 5376 * ctr_index - (OUT) LM counter index 5377 * Retruns: 5378 * BCM_E_XXX 5379 */ 5380 STATIC int 5381 _bcm_kt2_oam_egr_mp_group_entry_set(int unit, 5382 bcm_oam_endpoint_info_t *ep_info_p, 5383 shr_idxres_element_t *ctr_index) 5384 { 5385 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 5386 int rv; /* Operation return status. */ 5387 uint8 mdl = 0; /* Maintenance domain level. */ 5388 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 5389 bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint info. */ 5390 soc_field_t mdl_field = 0; 5391 egr_mp_group_entry_t egr_mp_group; /* Egress MP group tbl entry buffer */ 5392 int up_mep = 0; /* Endpoint is an upMep */ 5393 int mp_grp_index = 0; 5394 5395 if (NULL == ep_info_p) { 5396 return (BCM_E_INTERNAL); 5397 } 5398 5399 /* Initialize local endpoint info pointer. */ 5400 ep_p = ep_info_p; 5401 5402 /* Lock already taken by the calling routine. */ 5403 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 5404 5405 /* Get endpoint hash data pointer. */ 5406 h_data_p = &oc->oam_hash_data[ep_p->id]; 5407 5408 if (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 5409 up_mep = 1; 5410 mdl_field = MDL_BITMAP_ACTIVEf; 5411 } else { 5412 mdl_field = MDL_BITMAP_PASSIVEf; 5413 } 5414 5415 /* form the key to search EGR_MP_GRUP table */ 5416 if (BCM_SUCCESS 5417 (_bcm_kt2_oam_find_egr_lmep(unit, h_data_p, 5418 &mp_grp_index, &egr_mp_group))) { 5419 5420 /* There's already an entry for this */ 5421 if (SAL_BOOT_BCMSIM) { 5422 /* Added as WAR for Cmodel issue */ 5423 /* Construct endpoint egress MP group Table entry search operation. */ 5424 _bcm_oam_egr_lmep_key_construct(unit, h_data_p, &egr_mp_group); 5425 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, VALIDf, 1); 5426 } 5427 mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, mdl_field); 5428 /* If active bitmap is 0, so for first active endppoint in the mp_group 5429 * need to programme ma_base_ptr field during up_mep creation */ 5430 if((mdl == 0) && up_mep) { 5431 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, MA_BASE_PTRf, 5432 h_data_p->ma_base_index); 5433 } 5434 5435 /* Passive demultiplexing should not be done on a MIP */ 5436 if (!((mdl_field == MDL_BITMAP_PASSIVEf) 5437 && (_BCM_OAM_EP_IS_MIP(h_data_p)))) { 5438 mdl |= (1 << ep_p->level); 5439 5440 /* Set all the bits till the highest configured MDL, so that there are 5441 no holes in the passive bitmap */ 5442 if (mdl_field == MDL_BITMAP_PASSIVEf) { 5443 mdl |= ((1 << ep_p->level) - 1); 5444 } 5445 } 5446 /* set MDL bitmap passive or active depending on up or down mep */ 5447 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, mdl_field, mdl); 5448 5449 soc_mem_lock(unit, EGR_MP_GROUPm); 5450 5451 rv = soc_mem_write(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL, 5452 mp_grp_index, &egr_mp_group); 5453 if (BCM_FAILURE(rv)) { 5454 soc_mem_unlock(unit, EGR_MP_GROUPm); 5455 return (rv); 5456 } 5457 soc_mem_unlock(unit, EGR_MP_GROUPm); 5458 } else { 5459 5460 /* This is the first entry at this */ 5461 sal_memset(&egr_mp_group, 0, sizeof(egr_mp_group_entry_t)); 5462 5463 /* Passive demultiplexing should not be done on a MIP */ 5464 if (!((mdl_field == MDL_BITMAP_PASSIVEf) 5465 && (_BCM_OAM_EP_IS_MIP(h_data_p)))) { 5466 mdl = (1 << ep_p->level); 5467 /* Set all the bits till the highest configured MDL, so that there are 5468 no holes in the passive bitmap */ 5469 if ( mdl_field == MDL_BITMAP_PASSIVEf && !(BHH_EP_TYPE(ep_info_p)) ) { 5470 mdl |= ((1 << ep_p->level) - 1); 5471 } 5472 } 5473 5474 if (mdl == 0) { 5475 /* MDL = 0 for case of MIP. Dont make the entry valid by 5476 programming other fields. */ 5477 return BCM_E_NONE; 5478 } 5479 5480 /* set MDL bitmap passive or active depending on up or down mep */ 5481 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, mdl_field, mdl); 5482 5483 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, MA_BASE_PTRf, 5484 h_data_p->ma_base_index); 5485 5486 /* Configure time stamp type 1588(PTP)/NTP */ 5487 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 5488 TIMESTAMP_TYPEf, 5489 ((ep_p->timestamp_format == bcmOAMTimestampFormatNTP) ? 1 : 0)); 5490 5491 h_data_p->ts_format = ep_p->timestamp_format; 5492 5493 /* Construct LMEP view key for L3 Table insert operation. */ 5494 _bcm_oam_egr_lmep_key_construct(unit, h_data_p, &egr_mp_group); 5495 5496 soc_mem_lock(unit, EGR_MP_GROUPm); 5497 5498 rv = soc_mem_insert(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL, &egr_mp_group); 5499 if (BCM_FAILURE(rv)) { 5500 soc_mem_unlock(unit, EGR_MP_GROUPm); 5501 return (rv); 5502 } 5503 soc_mem_unlock(unit, EGR_MP_GROUPm); 5504 } 5505 if (up_mep == 1) { 5506 h_data_p->active_mdl_bitmap = mdl; 5507 } 5508 return (BCM_E_NONE); 5509 } 5510 5511 STATIC int 5512 _bcm_kt2_oam_ma_idx_to_ep_id_mapping_op (int unit, 5513 _bcm_oam_hash_data_t *h_data_p, 5514 soc_mem_t mem, 5515 int delete) 5516 { 5517 uint32 mdl_value[1] = { 0 }; 5518 int bit_pos = 0; 5519 int current_offset = 0; 5520 int new_offset = 0; 5521 int entry_count = 0; 5522 shr_idxres_list_handle_t pool; 5523 bcm_oam_endpoint_t *temp_array = NULL; 5524 _bcm_oam_control_t *oc = NULL; 5525 int ma_base_index = _BCM_OAM_INVALID_INDEX; 5526 int is_upmep = 0; 5527 l3_entry_1_entry_t l3_entry; /* LMEP view table entry. */ 5528 int l3_index = -1; /* L3 table hardware index. */ 5529 egr_mp_group_entry_t egr_mp_group; /* Egress MP group tbl entry buffer */ 5530 int mp_grp_index = -1; 5531 int stm_index = 0; 5532 source_trunk_map_table_entry_t stm_entry; 5533 uint8 port_mdl = 0; 5534 int rv = BCM_E_NONE; 5535 5536 if (NULL == h_data_p) { 5537 return (BCM_E_INTERNAL); 5538 } 5539 5540 /* Lock already taken by the calling routine. */ 5541 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 5542 5543 if (mem == MA_INDEXm) { 5544 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit, 5545 h_data_p, &entry_count, &pool)); 5546 } else { 5547 entry_count = 8; 5548 } 5549 5550 if (entry_count <= 0) { 5551 return BCM_E_INTERNAL; 5552 } 5553 5554 5555 ma_base_index = h_data_p->ma_base_index; 5556 is_upmep = (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING)?1:0; 5557 5558 if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) { 5559 rv = _bcm_kt2_oam_find_port_lmep(unit, h_data_p, &stm_index, &stm_entry, &port_mdl); 5560 if (BCM_SUCCESS(rv)) { 5561 mdl_value[0] = port_mdl; 5562 } else { 5563 /* If app is not initialized (say rc), then during detach (delete) 5564 * we will not find the entry. simply return without error */ 5565 if ((delete) && (rv == BCM_E_NOT_FOUND) && !(oc->init)) { 5566 return BCM_E_NONE; 5567 } else { 5568 return BCM_E_INTERNAL; 5569 } 5570 } 5571 } else if (is_upmep) { 5572 rv = _bcm_kt2_oam_find_egr_lmep(unit, h_data_p, 5573 &mp_grp_index, &egr_mp_group); 5574 if (BCM_SUCCESS(rv)) { 5575 mdl_value[0] = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, 5576 MDL_BITMAP_ACTIVEf); 5577 } else { 5578 /* If app is not initialized (say rc), then during detach (delete) 5579 * we will not find the entry. simply return without error */ 5580 if ((delete) && (rv == BCM_E_NOT_FOUND) && !(oc->init)) { 5581 return BCM_E_NONE; 5582 } else { 5583 return BCM_E_INTERNAL; 5584 } 5585 } 5586 } else { 5587 rv = _bcm_kt2_oam_find_lmep(unit, h_data_p, &l3_index, &l3_entry); 5588 if (BCM_SUCCESS(rv)) { 5589 mdl_value[0] = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, 5590 LMEP__MDL_BITMAP_ACTIVEf); 5591 } else { 5592 /* If app is not initialized (say rc), then during detach (delete) 5593 * we will not find the entry. simply return without error */ 5594 if ((delete) && (rv == BCM_E_NOT_FOUND) && !(oc->init)) { 5595 return BCM_E_NONE; 5596 } else { 5597 return BCM_E_INTERNAL; 5598 } 5599 } 5600 } 5601 5602 _BCM_OAM_ALLOC(temp_array, bcm_oam_endpoint_t, 5603 sizeof(bcm_oam_endpoint_t) * entry_count, "endpoint id array"); 5604 if (NULL == temp_array) { 5605 return (BCM_E_MEMORY); 5606 } 5607 /* Initialize the entry buffer. */ 5608 sal_memset(temp_array, _BCM_OAM_INVALID_INDEX, sizeof(bcm_oam_endpoint_t) * entry_count); 5609 5610 5611 if (delete) { 5612 for (bit_pos = 0; bit_pos <= 7; bit_pos++) { 5613 if (SHR_BITGET(mdl_value, bit_pos)) { 5614 if (bit_pos == h_data_p->level) { 5615 current_offset++; 5616 } else { 5617 temp_array[new_offset] = 5618 oc->_bcm_oam_ma_idx_to_ep_id_map 5619 [_BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX 5620 (ma_base_index, current_offset, is_upmep)]; 5621 new_offset++; 5622 current_offset++; 5623 } 5624 } 5625 } 5626 } else { 5627 for (bit_pos = 0; bit_pos <= 7; bit_pos++) { 5628 if (SHR_BITGET(mdl_value, bit_pos)) { 5629 if (bit_pos == h_data_p->level) { 5630 temp_array[new_offset] = h_data_p->ep_id; 5631 new_offset++; 5632 } else { 5633 temp_array[new_offset] = 5634 oc->_bcm_oam_ma_idx_to_ep_id_map[ 5635 _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX(ma_base_index, 5636 current_offset, is_upmep)]; 5637 new_offset++; 5638 current_offset++; 5639 } 5640 } 5641 } 5642 } 5643 5644 sal_memcpy(&(oc->_bcm_oam_ma_idx_to_ep_id_map[ 5645 _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX 5646 (ma_base_index, 0, is_upmep)]), 5647 temp_array, sizeof(bcm_oam_endpoint_t) * entry_count); 5648 5649 sal_free(temp_array); 5650 return (BCM_E_NONE); 5651 } 5652 5653 STATIC int 5654 _bcm_kt2_oam_ma_idx_to_ep_id_mapping_add (int unit, 5655 _bcm_oam_hash_data_t *h_data_p) 5656 { 5657 int is_upmep = 0; 5658 int is_remote = 0; 5659 int is_rx_enabled = 0; 5660 soc_mem_t mem = MA_INDEXm; 5661 int rv = BCM_E_NONE; 5662 5663 /* h_data_p being NULL could already be some other error 5664 * scenario. Lets not return error for such a scenario. 5665 */ 5666 if (h_data_p == NULL) { 5667 return BCM_E_NONE; 5668 } 5669 5670 is_upmep = (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING)?1:0; 5671 if (is_upmep) { 5672 mem = EGR_MA_INDEXm; 5673 } 5674 is_remote = (h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE)?1:0; 5675 is_rx_enabled = (h_data_p->local_rx_enabled == 1) && (h_data_p->ma_base_index != _BCM_OAM_INVALID_INDEX); 5676 if (is_remote || !is_rx_enabled) { 5677 /* Dont touch anything for remote endpoints or only tx enabled */ 5678 return BCM_E_NONE; 5679 } 5680 rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_op(unit, h_data_p, mem, 0); 5681 5682 return rv; 5683 } 5684 5685 STATIC int 5686 _bcm_kt2_oam_ma_idx_to_ep_id_mapping_delete (int unit, 5687 _bcm_oam_hash_data_t *h_data_p) 5688 { 5689 int is_upmep = 0; 5690 int is_remote = 0; 5691 int is_rx_enabled = 0; 5692 soc_mem_t mem = MA_INDEXm; 5693 int rv = BCM_E_NONE; 5694 5695 /* h_data_p being NULL could already be some other error 5696 * scenario. Lets not return error for such a scenario. 5697 */ 5698 if (h_data_p == NULL) { 5699 return BCM_E_NONE; 5700 } 5701 5702 is_upmep = (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING)?1:0; 5703 if (is_upmep) { 5704 mem = EGR_MA_INDEXm; 5705 } 5706 is_remote = (h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE)?1:0; 5707 is_rx_enabled = (h_data_p->local_rx_enabled == 1) && (h_data_p->ma_base_index != _BCM_OAM_INVALID_INDEX); 5708 if (is_remote || !is_rx_enabled) { 5709 /* Dont touch anything for remote endpoints or only tx enabled */ 5710 return BCM_E_NONE; 5711 } 5712 rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_op(unit, h_data_p, mem, 1); 5713 5714 return rv; 5715 } 5716 5717 STATIC INLINE bcm_oam_endpoint_t 5718 _bcm_kt2_oam_ma_idx_to_ep_id_mapping_get (_bcm_oam_control_t *oc, int ma_idx) 5719 { 5720 return oc->_bcm_oam_ma_idx_to_ep_id_map[ma_idx]; 5721 } 5722 5723 STATIC int _bcm_kt2_oam_ma_idx_to_ep_id_mapping_init (int unit) 5724 { 5725 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 5726 5727 /* Lock already taken by the calling routine. */ 5728 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 5729 5730 _BCM_OAM_ALLOC(oc->_bcm_oam_ma_idx_to_ep_id_map, bcm_oam_endpoint_t, 5731 _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_TBL_SIZE , "MA_IDX_TO_EP_ID map"); 5732 5733 if (oc->_bcm_oam_ma_idx_to_ep_id_map == NULL) { 5734 return BCM_E_MEMORY; 5735 } 5736 5737 /* Init it to all invalid */ 5738 sal_memset(oc->_bcm_oam_ma_idx_to_ep_id_map, _BCM_OAM_INVALID_INDEX, 5739 _BCM_KT2_OAM_MA_IDX_TO_EP_ID_MAPPING_TBL_SIZE); 5740 return BCM_E_NONE; 5741 } 5742 5743 STATIC int _bcm_kt2_oam_ma_idx_to_ep_id_mapping_destroy (int unit) 5744 { 5745 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 5746 5747 /* Lock already taken by the calling routine. */ 5748 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 5749 5750 if (oc->_bcm_oam_ma_idx_to_ep_id_map != NULL) { 5751 sal_free(oc->_bcm_oam_ma_idx_to_ep_id_map); 5752 oc->_bcm_oam_ma_idx_to_ep_id_map = NULL; 5753 } 5754 5755 return BCM_E_NONE; 5756 } 5757 5758 5759 STATIC int 5760 _bcm_kt2_oam_ma_index_entry_set(int unit, 5761 _bcm_oam_hash_data_t *h_data_p, 5762 soc_mem_t mem, 5763 void *ma_idx_ptr, int delete) 5764 { 5765 int rv = BCM_E_NONE; 5766 uint32 mdl_value[1] = { 0 }; 5767 int bit_pos = 0; 5768 int current_offset = 0; 5769 int new_offset = 0; 5770 int entry_count = 0; 5771 int entry_mem_size = 0; 5772 ma_index_entry_t *entry_buf; 5773 ma_index_entry_t *entry; 5774 ma_index_entry_t *entry_current; 5775 shr_idxres_list_handle_t pool = NULL; 5776 5777 if (NULL == h_data_p) { 5778 return (BCM_E_INTERNAL); 5779 } 5780 5781 if (mem == MA_INDEXm) { 5782 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit, 5783 h_data_p, &entry_count, &pool)); 5784 new_offset = entry_count; 5785 entry_mem_size = sizeof(ma_index_entry_t); 5786 } else { 5787 entry_mem_size = sizeof(egr_ma_index_entry_t); 5788 new_offset = entry_count = 8; 5789 } 5790 if(entry_count <= 0) { 5791 return BCM_E_INTERNAL; 5792 } 5793 /* Allocate buffer to store the DMAed table entries. */ 5794 entry_buf = soc_cm_salloc(unit, entry_mem_size * entry_count * 2, 5795 "MA index table entry buffer"); 5796 if (NULL == entry_buf) { 5797 return (BCM_E_MEMORY); 5798 } 5799 /* Initialize the entry buffer. */ 5800 sal_memset(entry_buf, 0, entry_mem_size * entry_count * 2); 5801 5802 /* Read the table entries into the buffer. */ 5803 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL, h_data_p->ma_base_index, 5804 (h_data_p->ma_base_index + entry_count - 1), 5805 entry_buf); 5806 if (BCM_FAILURE(rv)) { 5807 if (entry_buf) { 5808 soc_cm_sfree(unit, entry_buf); 5809 } 5810 return rv; 5811 } 5812 5813 mdl_value[0] = h_data_p->active_mdl_bitmap; 5814 5815 if (delete) { 5816 for (bit_pos = 0; bit_pos <= 7; bit_pos++) { 5817 if (SHR_BITGET(mdl_value, bit_pos)) { 5818 if (bit_pos == h_data_p->level) { 5819 current_offset++; 5820 } else { 5821 entry = soc_mem_table_idx_to_pointer(unit, mem, 5822 ma_index_entry_t *, 5823 entry_buf, new_offset); 5824 entry_current = soc_mem_table_idx_to_pointer(unit, mem, 5825 ma_index_entry_t *, 5826 entry_buf, current_offset); 5827 sal_memcpy(entry, entry_current, entry_mem_size); 5828 new_offset++; 5829 current_offset++; 5830 } 5831 } 5832 } 5833 } else { 5834 for (bit_pos = 0; bit_pos <= 7; bit_pos++) { 5835 if (SHR_BITGET(mdl_value, bit_pos)) { 5836 if (bit_pos == h_data_p->level) { 5837 entry = soc_mem_table_idx_to_pointer(unit, mem, 5838 ma_index_entry_t *, 5839 entry_buf, new_offset); 5840 sal_memcpy(entry, ma_idx_ptr, entry_mem_size); 5841 /* Doing Mod entry_count since new_offset starts 5842 from entry_count */ 5843 h_data_p->local_rx_index = h_data_p->ma_base_index + 5844 (new_offset % entry_count); 5845 new_offset++; 5846 } else { 5847 entry = soc_mem_table_idx_to_pointer(unit, mem, 5848 ma_index_entry_t *, 5849 entry_buf, new_offset); 5850 entry_current = soc_mem_table_idx_to_pointer(unit, mem, 5851 ma_index_entry_t *, 5852 entry_buf, current_offset); 5853 sal_memcpy(entry, entry_current, entry_mem_size); 5854 new_offset++; 5855 current_offset++; 5856 } 5857 } 5858 } 5859 } 5860 /* Move to the entry_count index since from there the newly programmed 5861 * ma_index table memory is present */ 5862 entry = soc_mem_table_idx_to_pointer(unit, mem, ma_index_entry_t *, 5863 entry_buf, entry_count); 5864 rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL, h_data_p->ma_base_index, 5865 (h_data_p->ma_base_index + entry_count - 1), 5866 entry); 5867 if (BCM_FAILURE(rv)) { 5868 if (entry_buf) { 5869 soc_cm_sfree(unit, entry_buf); 5870 } 5871 return rv; 5872 } 5873 if (entry_buf) { 5874 soc_cm_sfree(unit, entry_buf); 5875 } 5876 return (BCM_E_NONE); 5877 } 5878 5879 STATIC int 5880 _bcm_kt2_oam_port_table_ma_index_offset_get(int unit, 5881 _bcm_oam_hash_data_t *h_data_p, 5882 int *ma_offset) 5883 { 5884 int rv = BCM_E_NONE; 5885 uint32 mdl_value[1] = { 0 }; 5886 int bit_pos = 0; 5887 bcm_port_t port_id; /* Port ID. */ 5888 int local_member_count = 0; 5889 port_tab_entry_t port_entry; 5890 int offset_found = 0; 5891 5892 if (NULL == h_data_p) { 5893 return (BCM_E_INTERNAL); 5894 } 5895 if(h_data_p->trunk_id != BCM_TRUNK_INVALID) { 5896 rv = _bcm_kt2_oam_trunk_port_mdl_config(unit, h_data_p); 5897 5898 /* Get a member of the trunk belonging to this module */ 5899 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 5900 h_data_p->trunk_id, 1, 5901 &port_id, 5902 &local_member_count))) { 5903 } else { 5904 return (BCM_E_INTERNAL); 5905 } 5906 BCM_IF_ERROR_RETURN 5907 (soc_mem_read(unit, PORT_TABm, 5908 MEM_BLOCK_ANY, port_id, &port_entry)); 5909 } else { 5910 BCM_IF_ERROR_RETURN 5911 (soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, 5912 h_data_p->src_pp_port, &port_entry)); 5913 } 5914 mdl_value[0] = soc_PORT_TABm_field32_get(unit, &port_entry, MDL_BITMAPf); 5915 for (bit_pos = 0; bit_pos <= 7; bit_pos++) { 5916 if (SHR_BITGET(mdl_value, bit_pos)) { 5917 if (bit_pos == h_data_p->level) { 5918 offset_found = 1; 5919 break; 5920 } else { 5921 *ma_offset += 1; 5922 } 5923 } 5924 } 5925 h_data_p->active_mdl_bitmap = mdl_value[0]; 5926 /* Added the line below to avoid compiler warning - unused variable */ 5927 mdl_value[0] = *ma_offset; 5928 if (offset_found == 0) { 5929 return (BCM_E_INTERNAL); 5930 } 5931 return rv; 5932 } 5933 5934 5935 STATIC int 5936 _bcm_kt2_oam_mp_grp_table_ma_index_offset_get(int unit, 5937 _bcm_oam_hash_data_t *h_data_p, 5938 int *ma_offset) 5939 { 5940 int rv = BCM_E_NONE; 5941 uint32 mdl_value[1] = { 0 }; 5942 int bit_pos = 0; 5943 soc_mem_t mem = 0; 5944 l3_entry_1_entry_t l3_entry; /* L3 entry buffer. */ 5945 int entry_index = 0; 5946 egr_mp_group_entry_t egr_mp_group; /* Egress MP group tbl entry buffer */ 5947 void *entry; 5948 soc_field_t mdl_field = 0; 5949 int offset_found = 0; 5950 5951 if (NULL == h_data_p) { 5952 return (BCM_E_INTERNAL); 5953 } 5954 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 5955 mem = EGR_MP_GROUPm; 5956 mdl_field = MDL_BITMAP_ACTIVEf; 5957 entry = &egr_mp_group; 5958 if (BCM_FAILURE(_bcm_kt2_oam_find_egr_lmep(unit, h_data_p, 5959 &entry_index, 5960 &egr_mp_group))) { 5961 LOG_ERROR(BSL_LS_BCM_OAM, 5962 (BSL_META_U(unit, 5963 "OAM Error: EGR MP group tbl entry not found-%s.\n"), 5964 bcm_errmsg(rv))); 5965 return rv; 5966 } 5967 } else { 5968 mem = L3_ENTRY_IPV4_UNICASTm; 5969 mdl_field = LMEP__MDL_BITMAP_ACTIVEf; 5970 entry = &l3_entry; 5971 if (BCM_FAILURE 5972 (_bcm_kt2_oam_find_lmep(unit, h_data_p, &entry_index, &l3_entry))) { 5973 5974 LOG_ERROR(BSL_LS_BCM_OAM, 5975 (BSL_META_U(unit, 5976 "OAM Error: MP group tbl entry not found - %s.\n"), 5977 bcm_errmsg(rv))); 5978 return rv; 5979 } 5980 } 5981 mdl_value[0] = soc_mem_field32_get(unit, mem, entry, mdl_field); 5982 for (bit_pos = 0; bit_pos <= 7; bit_pos++) { 5983 if (SHR_BITGET(mdl_value, bit_pos)) { 5984 if (bit_pos == h_data_p->level) { 5985 offset_found = 1; 5986 break; 5987 } else { 5988 *ma_offset += 1; 5989 } 5990 } 5991 } 5992 h_data_p->active_mdl_bitmap = mdl_value[0]; 5993 if (offset_found == 0) { 5994 return (BCM_E_INTERNAL); 5995 } 5996 return rv; 5997 } 5998 5999 6000 STATIC int 6001 _bcm_kt2_oam_ma_index_offset_get(int unit, _bcm_oam_hash_data_t *h_data_p, 6002 int *ma_offset) 6003 { 6004 int rv = BCM_E_NONE; 6005 if (NULL == h_data_p) { 6006 return (BCM_E_INTERNAL); 6007 } 6008 6009 /* setting this to 0 is necessary as in the below functions this variable 6010 * passed as a pointer is just incremented based upon the level. 6011 * setting it to zero avoids any junk value that might have come in 6012 * by the caller function. */ 6013 *ma_offset = 0; 6014 6015 if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) { 6016 rv = _bcm_kt2_oam_port_table_ma_index_offset_get(unit, h_data_p, 6017 ma_offset); 6018 /* BCM_E_NOT_FOUND is not an error when switch is re-initializing 6019 as entry would have been already deleted by port module init */ 6020 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 6021 LOG_ERROR(BSL_LS_BCM_OAM, 6022 (BSL_META_U(unit, 6023 "OAM Error: Port table read failed - %s.\n"), 6024 bcm_errmsg(rv))); 6025 return rv; 6026 } 6027 } else { 6028 rv = _bcm_kt2_oam_mp_grp_table_ma_index_offset_get(unit, h_data_p, 6029 ma_offset); 6030 if (BCM_FAILURE(rv)) { 6031 LOG_ERROR(BSL_LS_BCM_OAM, 6032 (BSL_META_U(unit, 6033 "OAM Error: MP group table read failed - %s.\n"), 6034 bcm_errmsg(rv))); 6035 return rv; 6036 } 6037 } 6038 return (BCM_E_NONE); 6039 } 6040 /* 6041 * Function: 6042 * _bcm_kt2_oam_local_rx_mep_hw_set 6043 * Purpose: 6044 * Configure hardware tables for a local CCM Rx enabled endpoint. 6045 * Parameters: 6046 * unit - (IN) BCM device number 6047 * ep_info_p - (IN) Pointer to remote endpoint information. 6048 * Retruns: 6049 * BCM_E_XXX 6050 */ 6051 STATIC int 6052 _bcm_kt2_oam_local_rx_mep_hw_set(int unit, 6053 bcm_oam_endpoint_info_t *ep_info_p) 6054 { 6055 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 6056 ma_index_entry_t ma_idx_entry; /* MA_INDEX table entry buffer. */ 6057 egr_ma_index_entry_t egr_ma_idx_entry; /* EGR_MA_INDEX table entry buffer*/ 6058 oam_opcode_control_profile_entry_t opcode_entry; /* Opcode control 6059 profile entry. */ 6060 egr_oam_opcode_control_profile_entry_t egr_opcode_entry; /* Egress 6061 Opcode control profile entry*/ 6062 void *entries[1]; /* Pointer to opcode control entry. */ 6063 uint32 profile_index; /* opcode control profile index. */ 6064 int rv; /* Operation return status. */ 6065 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 6066 bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint info. */ 6067 soc_mem_t opcode_profile_mem = 0; 6068 soc_mem_t ma_index_mem = 0; 6069 shr_idxres_element_t egr_ctr_index = 0; 6070 soc_profile_mem_t *opcode_control_profile; /* profile to be used 6071 ingress or egress */ 6072 void *ma_idx_ptr; 6073 void *opcode_profile_entry; 6074 6075 if (NULL == ep_info_p) { 6076 return (BCM_E_INTERNAL); 6077 } 6078 6079 /* Initialize local endpoint info pointer. */ 6080 ep_p = ep_info_p; 6081 6082 /* Lock already taken by the calling routine. */ 6083 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 6084 6085 /* Get endpoint hash data pointer. */ 6086 h_data_p = &oc->oam_hash_data[ep_p->id]; 6087 if ( 0 == h_data_p->in_use) { 6088 return (BCM_E_INTERNAL); 6089 } 6090 6091 if (ep_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 6092 opcode_profile_mem = EGR_OAM_OPCODE_CONTROL_PROFILEm; 6093 opcode_control_profile = &oc->egr_oam_opcode_control_profile; 6094 ma_index_mem = EGR_MA_INDEXm; 6095 ma_idx_ptr = &egr_ma_idx_entry; 6096 opcode_profile_entry = &egr_opcode_entry; 6097 /* Clear the entry data. */ 6098 sal_memset(&egr_opcode_entry, 0, 6099 sizeof(egr_oam_opcode_control_profile_entry_t)); 6100 sal_memset(&egr_ma_idx_entry, 0, sizeof(egr_ma_index_entry_t)); 6101 } else { 6102 opcode_profile_mem = OAM_OPCODE_CONTROL_PROFILEm; 6103 opcode_control_profile = &oc->oam_opcode_control_profile; 6104 ma_index_mem = MA_INDEXm; 6105 ma_idx_ptr = &ma_idx_entry; 6106 opcode_profile_entry = &opcode_entry; 6107 /* Clear the entry data. */ 6108 sal_memset(&opcode_entry, 0, 6109 sizeof(oam_opcode_control_profile_entry_t)); 6110 sal_memset(&ma_idx_entry, 0, sizeof(ma_index_entry_t)); 6111 } 6112 6113 /* Construct the opcode control profile table entry. */ 6114 if (ep_p->opcode_flags & _BCM_KT2_OAM_OPCODE_MASK) { 6115 /* Use application specified opcode control settings. */ 6116 rv = _bcm_kt2_oam_opcode_profile_entry_set(unit, h_data_p, 6117 opcode_profile_mem, 6118 ep_p->opcode_flags, 6119 opcode_profile_entry); 6120 if (BCM_FAILURE(rv)) { 6121 LOG_ERROR(BSL_LS_BCM_OAM, 6122 (BSL_META_U(unit, 6123 "OAM Error: Opcode profile set failed for EP=%d" 6124 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 6125 return (rv); 6126 } 6127 } else { 6128 /* Use default opcode control profile settings. */ 6129 if (_BCM_OAM_EP_IS_MIP(h_data_p)) { 6130 rv = _bcm_kt2_oam_mip_opcode_profile_entry_init(unit, opcode_profile_mem, 6131 opcode_profile_entry); 6132 } else { 6133 rv = _bcm_kt2_oam_opcode_profile_entry_init(unit, opcode_profile_mem, 6134 opcode_profile_entry); 6135 } 6136 if (BCM_FAILURE(rv)) { 6137 LOG_ERROR(BSL_LS_BCM_OAM, 6138 (BSL_META_U(unit, 6139 "OAM Error: Opcode profile init failed for EP=%d" 6140 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 6141 return (rv); 6142 } 6143 } 6144 6145 soc_mem_lock(unit, opcode_profile_mem); 6146 /* Add entry to profile table. */ 6147 entries[0] = opcode_profile_entry; 6148 6149 rv = soc_profile_mem_add(unit, opcode_control_profile, 6150 (void *)entries, 1, &profile_index); 6151 if (BCM_FAILURE(rv)) { 6152 LOG_ERROR(BSL_LS_BCM_OAM, 6153 (BSL_META_U(unit, 6154 "OAM Error: Opcode profile add failed for EP=%d" 6155 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 6156 /* Release opcode control profile table lock. */ 6157 soc_mem_unlock(unit, opcode_profile_mem); 6158 return (rv); 6159 } 6160 6161 /* Store endpoint OAM opcode profile table index value. */ 6162 h_data_p->profile_index = profile_index; 6163 6164 /* Release opcode control profile table lock. */ 6165 soc_mem_unlock(unit, opcode_profile_mem); 6166 6167 /* 6168 * MA_INDEX table programming. 6169 */ 6170 6171 6172 /* Set group index value. */ 6173 /* In case of BHH this needs to be the session Index */ 6174 #if defined(INCLUDE_BHH) 6175 if ( BHH_EP_TYPE(ep_p) ) { 6176 soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr, MA_PTRf, 6177 BCM_OAM_BHH_GET_UKERNEL_EP(ep_p->id)); 6178 } else 6179 #endif 6180 { 6181 soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr, MA_PTRf, 6182 ep_p->group); 6183 } 6184 6185 6186 6187 /* Set OAM opcode control profile table index. */ 6188 soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr, 6189 OAM_OPCODE_CONTROL_PROFILE_PTRf, 6190 h_data_p->profile_index); 6191 6192 soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr, 6193 INT_PRIf, 6194 ep_p->int_pri); 6195 6196 6197 /* If the OAM domain is port, set source trunk map table */ 6198 if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) { 6199 rv = _bcm_port_domain_oam_hw_set(unit, ep_info_p); 6200 if (BCM_FAILURE(rv)) { 6201 LOG_ERROR(BSL_LS_BCM_OAM, 6202 (BSL_META_U(unit, 6203 "OAM Error: port OAM config failed for EP=%d" 6204 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 6205 return (rv); 6206 } 6207 } else { 6208 rv = _bcm_kt2_oam_l3_entry_set(unit, ep_info_p); 6209 if (BCM_FAILURE(rv)) { 6210 LOG_ERROR(BSL_LS_BCM_OAM, 6211 (BSL_META_U(unit, 6212 "OAM Error: L3 entry config failed for EP=%d" 6213 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 6214 return (rv); 6215 } 6216 rv = _bcm_kt2_oam_egr_mp_group_entry_set(unit, ep_info_p, 6217 &egr_ctr_index); 6218 if (BCM_FAILURE(rv)) { 6219 LOG_ERROR(BSL_LS_BCM_OAM, 6220 (BSL_META_U(unit, 6221 "OAM Error: Egress MP group entry config " 6222 "failed for EP=%d %s.\n"), ep_p->id, bcm_errmsg(rv))); 6223 return (rv); 6224 } 6225 6226 if ((ep_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) { 6227 rv = _bcm_kt2_oam_lmep_counters_set(unit, ep_info_p); 6228 if (BCM_FAILURE(rv)) { 6229 LOG_ERROR(BSL_LS_BCM_OAM, 6230 (BSL_META_U(unit, 6231 "OAM Error: Counter config failed for EP=%d" 6232 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 6233 if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) { 6234 rv = shr_aidxres_list_free(oc->ing_lm_ctr_pool[ 6235 (h_data_p->rx_ctr >> 24)], 6236 (h_data_p->rx_ctr & 0xffffff)); 6237 if (BCM_FAILURE(rv)) { 6238 LOG_ERROR(BSL_LS_BCM_OAM, 6239 (BSL_META_U(unit, 6240 "OAM Error: Ing LM counter block " 6241 "free failed (EP=%d) - %s.\n"), 6242 ep_info_p->id, bcm_errmsg(rv))); 6243 return (rv); 6244 } 6245 } 6246 return (rv); 6247 } 6248 } 6249 } 6250 rv = _bcm_kt2_oam_ma_index_entry_set(unit, h_data_p, 6251 ma_index_mem, ma_idx_ptr, 0); 6252 if (BCM_FAILURE(rv)) { 6253 LOG_ERROR(BSL_LS_BCM_OAM, 6254 (BSL_META_U(unit, 6255 "OAM Error: MA_INDEX table write failed for EP=%d" 6256 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 6257 return (rv); 6258 } 6259 return rv; 6260 } 6261 6262 /* 6263 * Function: 6264 * _bcm_kt2_oam_upmep_rx_endpoint_reserve 6265 * Purpose: 6266 * Reserve an hardware index in the group state table to maintain the state 6267 * for a CCM Rx enabled endpoint. 6268 * Parameters: 6269 * unit - (IN) BCM device number 6270 * ep_info_p - (IN) Pointer to remote endpoint information. 6271 * Retruns: 6272 * BCM_E_XXX 6273 */ 6274 STATIC int 6275 _bcm_kt2_oam_upmep_rx_endpoint_reserve(int unit, 6276 const bcm_oam_endpoint_info_t *ep_info_p) 6277 { 6278 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 6279 int rv; /* Operation return status. */ 6280 egr_mp_group_entry_t egr_mp_grp_entry; /* egress mp group entry buffer. */ 6281 int mp_group_index = -1;/*MP group entry hardware index*/ 6282 int count = 0; /* Successful Hw indices allocated. */ 6283 uint8 mdl = 0; /* Maintenance domain level. */ 6284 int rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0}; 6285 /* Endpoint Rx hardware index. */ 6286 uint16 ma_base_idx; /* Base pointer to endpoint state */ 6287 /* table [MA_INDEX = (BASE + MDL)]. */ 6288 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 6289 const bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint information. */ 6290 6291 if (NULL == ep_info_p) { 6292 return (BCM_E_INTERNAL); 6293 } 6294 6295 /* Lock already taken by the calling routine. */ 6296 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 6297 6298 /* Initialize local endpoint information pointer. */ 6299 ep_p = ep_info_p; 6300 6301 /* Get endpoint hash data pointer. */ 6302 h_data_p = &oc->oam_hash_data[ep_p->id]; 6303 if (0 == h_data_p->in_use) { 6304 return(BCM_E_INTERNAL); 6305 } 6306 6307 /* Initialize egress MP group table entry buffer. */ 6308 sal_memset(&egr_mp_grp_entry, 0, sizeof(egr_mp_group_entry_t)); 6309 6310 /* Find out if a matching entry already installed in hardware table. */ 6311 rv = _bcm_kt2_oam_find_egr_lmep(unit, h_data_p, &mp_group_index, 6312 &egr_mp_grp_entry); 6313 if (BCM_FAILURE(rv)) { 6314 /* 6315 * If NO match found, allocate a new hardware index from EGR_MA_INDEX 6316 * pool. 6317 */ 6318 6319 /* 6320 * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA 6321 * group endpoints. While allocating the base index, next 7 hardware 6322 * indices are also reserved. 6323 */ 6324 rv = shr_idxres_list_alloc_set(oc->egr_ma_idx_pool, 8, 6325 (shr_idxres_element_t *) rx_index, 6326 (shr_idxres_element_t *) &count); 6327 if (BCM_FAILURE(rv)) { 6328 LOG_ERROR(BSL_LS_BCM_OAM, 6329 (BSL_META_U(unit, 6330 "OAM Error: EGR MA_INDEX index alloc failed EP:%d" 6331 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 6332 return (rv); 6333 } else { 6334 LOG_DEBUG(BSL_LS_BCM_OAM, 6335 (BSL_META_U(unit, 6336 "OAM Info: Egr MA_INDEX alloc for EP:%d success" 6337 " rx_idx_base:%d alloc-count:%d.\n"), ep_p->id, 6338 rx_index[0], count)); 6339 h_data_p->ma_base_index = rx_index[0]; 6340 } 6341 6342 } else if (BCM_SUCCESS(rv)) { 6343 6344 /* Matching entry found, get installed entry MDL value. */ 6345 mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_grp_entry, 6346 MDL_BITMAP_ACTIVEf); 6347 6348 if (mdl == 0) { 6349 /* This is the first one in the active bitmap. 6350 Allocate the hw indexes. */ 6351 /* 6352 * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA 6353 * group endpoints. While allocating the base index, next 7 hardware 6354 * indices are also reserved. 6355 */ 6356 rv = shr_idxres_list_alloc_set(oc->egr_ma_idx_pool, 8, 6357 (shr_idxres_element_t *) rx_index, 6358 (shr_idxres_element_t *) &count); 6359 if (BCM_FAILURE(rv)) { 6360 LOG_ERROR(BSL_LS_BCM_OAM, 6361 (BSL_META_U(unit, 6362 "OAM(unit %d) Error: EGR MA_INDEX index alloc failed EP:%d" 6363 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 6364 return (rv); 6365 } else { 6366 LOG_DEBUG(BSL_LS_BCM_OAM, 6367 (BSL_META_U(unit, 6368 "OAM(unit %d) Info: Egr MA_INDEX alloc for EP:%d success" 6369 " rx_idx_base:%d alloc-count:%d.\n"), unit, ep_p->id, 6370 rx_index[0], count)); 6371 h_data_p->ma_base_index = rx_index[0]; 6372 } 6373 } else if (0 == (mdl & (1 << ep_p->level))) { /* Findout if MDLs are same. */ 6374 ma_base_idx = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_grp_entry, 6375 MA_BASE_PTRf); 6376 h_data_p->ma_base_index = ma_base_idx; 6377 } else { 6378 /* Rx index already taken return error. */ 6379 LOG_ERROR(BSL_LS_BCM_OAM, 6380 (BSL_META_U(unit, 6381 "OAM Error: No free Rx index found for EP:%d" 6382 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 6383 return (BCM_E_RESOURCE); 6384 } 6385 } 6386 return (rv); 6387 } 6388 6389 /* 6390 * Function: 6391 * _bcm_kt2_oam_downmep_rx_endpoint_reserve 6392 * Purpose: 6393 * Reserve an hardware index in the group state table to maintain the state 6394 * for a CCM Rx enabled endpoint. 6395 * Parameters: 6396 * unit - (IN) BCM device number 6397 * ep_info_p - (IN) Pointer to remote endpoint information. 6398 * Retruns: 6399 * BCM_E_XXX 6400 */ 6401 STATIC int 6402 _bcm_kt2_oam_downmep_rx_endpoint_reserve(int unit, 6403 const bcm_oam_endpoint_info_t *ep_info_p) 6404 { 6405 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 6406 int rv; /* Operation return status. */ 6407 l3_entry_1_entry_t l3_entry; /* L3 entry buffer. */ 6408 int l3_index = -1; /* L3 entry hardware index. */ 6409 int count = 0; /* Successful Hw indices allocated. */ 6410 uint8 mdl = 0; /* Maintenance domain level. */ 6411 int rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0}; 6412 /* Endpoint Rx hardware index. */ 6413 uint16 ma_base_idx; /* Base pointer to endpoint state */ 6414 /* table [MA_INDEX = (BASE + MDL)]. */ 6415 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 6416 const bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint information. */ 6417 int stm_index = 0; 6418 source_trunk_map_table_entry_t stm_entry; 6419 int ma_idx_entry_count = 0; 6420 shr_idxres_list_handle_t pool = NULL; 6421 6422 6423 if (NULL == ep_info_p) { 6424 return (BCM_E_INTERNAL); 6425 } 6426 6427 /* Lock already taken by the calling routine. */ 6428 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 6429 6430 /* Initialize local endpoint information pointer. */ 6431 ep_p = ep_info_p; 6432 6433 /* Get endpoint hash data pointer. */ 6434 h_data_p = &oc->oam_hash_data[ep_p->id]; 6435 if ( 0 == h_data_p->in_use) { 6436 return (BCM_E_INTERNAL); 6437 } 6438 6439 /* Initialize L3 entry buffer. */ 6440 sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t)); 6441 sal_memset(&stm_entry, 0, sizeof(source_trunk_map_table_entry_t)); 6442 6443 if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) { 6444 rv = _bcm_kt2_oam_find_port_lmep(unit, h_data_p, &stm_index, &stm_entry, &mdl); 6445 } else { 6446 /* Find out if a matching entry already installed in hardware table. */ 6447 rv = _bcm_kt2_oam_find_lmep(unit, h_data_p, &l3_index, &l3_entry); 6448 } 6449 if (BCM_FAILURE(rv)) { 6450 /* 6451 * If NO match found, allocate a new hardware index from MA_INDEX 6452 * pool. 6453 */ 6454 6455 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p, 6456 &ma_idx_entry_count, &pool)); 6457 /* 6458 * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA 6459 * group endpoints. While allocating the base index, next 7 hardware 6460 * indices are also reserved. 6461 */ 6462 rv = shr_idxres_list_alloc_set(pool, ma_idx_entry_count, 6463 (shr_idxres_element_t *) rx_index, 6464 (shr_idxres_element_t *) &count); 6465 6466 if (BCM_FAILURE(rv)) { 6467 LOG_ERROR(BSL_LS_BCM_OAM, 6468 (BSL_META_U(unit, 6469 "OAM Error: MA_INDEX index alloc failed EP:%d" 6470 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 6471 return (rv); 6472 } else { 6473 LOG_DEBUG(BSL_LS_BCM_OAM, 6474 (BSL_META_U(unit, 6475 "OAM Info: MA_INDEX alloc for EP:%d success." 6476 " rx_idx_base:%d alloc-count:%d.\n"), ep_p->id, 6477 rx_index[0], count)); 6478 } 6479 6480 h_data_p->ma_base_index = rx_index[0]; 6481 } else if (BCM_SUCCESS(rv)) { 6482 if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) { 6483 /* MDL already found.*/ 6484 /* Findout if MDLs are same. */ 6485 if (0 == (mdl & (1 << ep_p->level))) { 6486 ma_base_idx = 6487 soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm_entry, 6488 MA_BASE_PTRf); 6489 h_data_p->ma_base_index = ma_base_idx; 6490 } else { 6491 /* Rx index already taken return error. */ 6492 LOG_ERROR(BSL_LS_BCM_OAM, 6493 (BSL_META_U(unit, 6494 "OAM Error: No free Rx index found for EP:%d" 6495 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 6496 return (BCM_E_RESOURCE); 6497 } 6498 } else { 6499 /* Matching entry found, get installed entry MDL value. */ 6500 mdl = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, 6501 LMEP__MDL_BITMAP_ACTIVEf); 6502 6503 if (mdl == 0) { 6504 /* This is the first one in the active bitmap. 6505 Allocate the hw indexes. */ 6506 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p, 6507 &ma_idx_entry_count, &pool)); 6508 /* 6509 * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA 6510 * group endpoints. While allocating the base index, next 7 hardware 6511 * indices are also reserved. 6512 */ 6513 rv = shr_idxres_list_alloc_set(pool, ma_idx_entry_count, 6514 (shr_idxres_element_t *) rx_index, 6515 (shr_idxres_element_t *) &count); 6516 6517 if (BCM_FAILURE(rv)) { 6518 LOG_ERROR(BSL_LS_BCM_OAM, 6519 (BSL_META_U(unit, 6520 "OAM(unit %d) Error: MA_INDEX index alloc failed EP:%d" 6521 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 6522 return (rv); 6523 } else { 6524 LOG_DEBUG(BSL_LS_BCM_OAM, 6525 (BSL_META_U(unit, 6526 "OAM(unit %d) Info: MA_INDEX alloc for EP:%d success." 6527 " rx_idx_base:%d alloc-count:%d.\n"), unit, ep_p->id, 6528 rx_index[0], count)); 6529 } 6530 6531 h_data_p->ma_base_index = rx_index[0]; 6532 } else if (0 == (mdl & (1 << ep_p->level))) { /* Findout if MDLs are same. */ 6533 ma_base_idx = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, 6534 LMEP__MA_BASE_PTRf); 6535 h_data_p->ma_base_index = ma_base_idx; 6536 } else { 6537 /* Rx index already taken return error. */ 6538 LOG_ERROR(BSL_LS_BCM_OAM, 6539 (BSL_META_U(unit, 6540 "OAM Error: No free Rx index found for EP:%d" 6541 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 6542 return (BCM_E_RESOURCE); 6543 } 6544 } 6545 } 6546 6547 return (rv); 6548 } 6549 6550 /* 6551 * Function: 6552 * _bcm_kt2_oam_remote_endpoint_delete 6553 * Purpose: 6554 * Delete a remote endpoint. 6555 * Parameters: 6556 * unit - (IN) BCM device number 6557 * h_data_p - (IN) Pointer to endpoint hash data 6558 * Retruns: 6559 * BCM_E_XXX 6560 */ 6561 STATIC int 6562 _bcm_kt2_oam_remote_endpoint_delete(int unit, 6563 _bcm_oam_hash_data_t *h_data_p) 6564 { 6565 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 6566 l3_entry_1_entry_t l3_entry; /* RMEP view table entry. */ 6567 ma_state_entry_t ma_state_entry; /* Group state machine table entry. */ 6568 rmep_entry_t rmep_entry; /* Remote endpoint table entry. */ 6569 int rv; /* Operation return status. */ 6570 uint32 some_rmep_ccm_defect_counter = 0; /* No. of RMEPs in MA with CCM */ 6571 /* defects. */ 6572 uint32 some_rdi_defect_counter = 0; /* No. of RMEPs in MA with RDI */ 6573 /* defects. */ 6574 uint32 cur_some_rdi_defect = 0; /* Any RMEP in MA with RDI defect. */ 6575 uint32 cur_some_rmep_ccm_defect = 0; /* Any RMEP in MA with CCM defect. */ 6576 uint32 cur_rmep_ccm_defect = 0; /* RMEP lookup failed or CCM */ 6577 /* interval mismatch. */ 6578 uint32 cur_rmep_last_rdi = 0; /* Last CCM RDI Rx from this RMEP. */ 6579 uint32 first, last, validLow, validHigh, freeCount, allocCount; 6580 6581 /* Lock already taken by the calling routine. */ 6582 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 6583 6584 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 6585 6586 /* Get remote endpoint entry value from hardware. */ 6587 rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index, &rmep_entry); 6588 if (BCM_FAILURE(rv)) { 6589 LOG_ERROR(BSL_LS_BCM_OAM, 6590 (BSL_META_U(unit, 6591 "OAM Error: RMEP table read failed for EP=%d" 6592 "%s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 6593 return (rv); 6594 } 6595 6596 cur_rmep_ccm_defect 6597 = soc_RMEPm_field32_get(unit, &rmep_entry, 6598 CURRENT_RMEP_CCM_DEFECTf); 6599 6600 cur_rmep_last_rdi 6601 = soc_RMEPm_field32_get(unit, &rmep_entry, 6602 CURRENT_RMEP_LAST_RDIf); 6603 6604 sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry)); 6605 rv = READ_MA_STATEm(unit, MEM_BLOCK_ANY, h_data_p->group_index, 6606 &ma_state_entry); 6607 if (BCM_FAILURE(rv)) { 6608 LOG_ERROR(BSL_LS_BCM_OAM, 6609 (BSL_META_U(unit, 6610 "OAM Error: Group state (GID=%d) table read" 6611 " failed - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 6612 return (rv); 6613 } 6614 6615 if ((0 != cur_rmep_ccm_defect) || (0 != cur_rmep_last_rdi)) { 6616 some_rmep_ccm_defect_counter 6617 = soc_MA_STATEm_field32_get(unit, &ma_state_entry, 6618 SOME_RMEP_CCM_DEFECT_COUNTERf); 6619 cur_some_rmep_ccm_defect 6620 = soc_MA_STATEm_field32_get(unit, &ma_state_entry, 6621 CURRENT_SOME_RMEP_CCM_DEFECTf); 6622 6623 if ((0 != cur_rmep_ccm_defect) 6624 && (some_rmep_ccm_defect_counter > 0)) { 6625 --some_rmep_ccm_defect_counter; 6626 soc_MA_STATEm_field32_set 6627 (unit, &ma_state_entry, SOME_RMEP_CCM_DEFECT_COUNTERf, 6628 some_rmep_ccm_defect_counter); 6629 6630 if (0 == some_rmep_ccm_defect_counter) { 6631 cur_some_rmep_ccm_defect = 0; 6632 soc_MA_STATEm_field32_set 6633 (unit, &ma_state_entry, CURRENT_SOME_RMEP_CCM_DEFECTf, 6634 cur_some_rmep_ccm_defect); 6635 } 6636 } 6637 6638 some_rdi_defect_counter 6639 = soc_MA_STATEm_field32_get(unit, &ma_state_entry, 6640 SOME_RDI_DEFECT_COUNTERf); 6641 cur_some_rdi_defect 6642 = soc_MA_STATEm_field32_get(unit, &ma_state_entry, 6643 CURRENT_SOME_RDI_DEFECTf); 6644 6645 if ((0 != cur_rmep_last_rdi) 6646 && (some_rdi_defect_counter > 0)) { 6647 --some_rdi_defect_counter; 6648 soc_MA_STATEm_field32_set 6649 (unit, &ma_state_entry, SOME_RDI_DEFECT_COUNTERf, 6650 some_rdi_defect_counter); 6651 6652 if (0 == some_rdi_defect_counter) { 6653 cur_some_rdi_defect = 0; 6654 soc_MA_STATEm_field32_set 6655 (unit, &ma_state_entry, CURRENT_SOME_RDI_DEFECTf, 6656 cur_some_rdi_defect); 6657 } 6658 } 6659 6660 rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, h_data_p->group_index, 6661 &ma_state_entry); 6662 if (BCM_FAILURE(rv)) { 6663 LOG_ERROR(BSL_LS_BCM_OAM, 6664 (BSL_META_U(unit, 6665 "OAM Error: Group state (GID=%d) table write" 6666 " failed - %s.\n"), h_data_p->group_index, 6667 bcm_errmsg(rv))); 6668 return (rv); 6669 } 6670 } 6671 6672 /* Clear RMEP table entry for this endpoint index. */ 6673 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 6674 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index, 6675 &rmep_entry); 6676 if (BCM_FAILURE(rv)) { 6677 LOG_ERROR(BSL_LS_BCM_OAM, 6678 (BSL_META_U(unit, 6679 "OAM Error: RMEP table write index=%x (EP=%d)" 6680 " - %s.\n"), h_data_p->remote_index, 6681 h_data_p->ep_id, bcm_errmsg(rv))); 6682 return (rv); 6683 } 6684 6685 sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t)); 6686 6687 /* Construct endpoint RMEP view key for L3 Table entry delete operation. */ 6688 _bcm_kt2_oam_rmep_key_construct(unit, h_data_p, &l3_entry); 6689 6690 rv = soc_mem_delete(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ALL, &l3_entry); 6691 if (BCM_FAILURE(rv) && (oc->init)) { 6692 LOG_ERROR(BSL_LS_BCM_OAM, 6693 (BSL_META_U(unit, 6694 "OAM Error: RMEP view update (EP=%d)" 6695 " - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 6696 return (rv); 6697 } 6698 6699 /* Return ID back to free RMEP ID pool. */ 6700 BCM_IF_ERROR_RETURN 6701 (shr_idxres_list_free(oc->rmep_pool, h_data_p->remote_index)); 6702 6703 rv = shr_idxres_list_state(oc->rmep_pool, 6704 &first, &last, 6705 &validLow, &validHigh, 6706 &freeCount, &allocCount); 6707 if (BCM_FAILURE(rv)) { 6708 LOG_ERROR(BSL_LS_BCM_OAM, 6709 (BSL_META_U(unit, 6710 "OAM Error: RMEP pool state get failed " 6711 " - %s.\n"), bcm_errmsg(rv))); 6712 return (rv); 6713 } 6714 6715 if(allocCount == 0) 6716 { 6717 soc_MA_STATEm_field32_set 6718 (unit, &ma_state_entry, CURRENT_XCON_CCM_DEFECTf, 6719 0); 6720 soc_MA_STATEm_field32_set 6721 (unit, &ma_state_entry, CURRENT_ERROR_CCM_DEFECTf, 6722 0); 6723 soc_MA_STATEm_field32_set 6724 (unit, &ma_state_entry, STICKY_ERROR_CCM_DEFECTf, 6725 0); 6726 soc_MA_STATEm_field32_set 6727 (unit, &ma_state_entry, ERROR_CCM_DEFECT_TIMESTAMPf, 6728 0); 6729 soc_MA_STATEm_field32_set 6730 (unit, &ma_state_entry, ERROR_CCM_DEFECT_RECEIVE_CCMf, 6731 0); 6732 rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, h_data_p->group_index, 6733 &ma_state_entry); 6734 if (BCM_FAILURE(rv)) { 6735 LOG_ERROR(BSL_LS_BCM_OAM, 6736 (BSL_META_U(unit, 6737 "OAM Error: Group state (GID=%d) table write" 6738 " failed - %s.\n"), h_data_p->group_index, 6739 bcm_errmsg(rv))); 6740 return (rv); 6741 } 6742 } 6743 6744 /* Clear the H/w index to logical index Mapping for RMEP */ 6745 oc->remote_endpoints[h_data_p->remote_index] = BCM_OAM_ENDPOINT_INVALID; 6746 6747 6748 return (BCM_E_NONE); 6749 } 6750 6751 /* 6752 * Function: 6753 * _bcm_kt2_oam_clear_counter 6754 * Purpose: 6755 * Remove the counter associated with the endpoint being deleted 6756 * Parameters: 6757 * unit - (IN) BCM device number 6758 * mem - (IN) L3_ENTRY_IPV4_UNICAST/EGR_MP_GROUP 6759 * index - (IN) Index of the table entry to be modified 6760 * h_data_p - (IN) Pointer to endpoint hash data 6761 * entry - (IN) pointer to table entry 6762 * Retruns: 6763 * BCM_E_XXX 6764 */ 6765 STATIC int 6766 _bcm_kt2_oam_clear_counter(int unit, soc_mem_t mem, 6767 int index, 6768 _bcm_oam_hash_data_t *h_data_p, 6769 void *entry) 6770 { 6771 int rv = BCM_E_NONE; 6772 mep_ctr_info_t *ctr_info; 6773 int ctr_type = 0; 6774 int ctr1_valid = 0; 6775 int ctr2_valid = 0; 6776 int ctr_mdl = 0; 6777 int up_mep = 0; 6778 6779 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 6780 up_mep = 1; 6781 } 6782 if (mem == L3_ENTRY_IPV4_UNICASTm) { 6783 ctr_info = mep_ctr_info; 6784 } else { 6785 ctr_info = egr_mep_ctr_info; 6786 } 6787 ctr1_valid = soc_mem_field32_get(unit, mem, 6788 (uint32 *)entry, ctr_info[0].ctr_valid); 6789 if (ctr1_valid) { 6790 ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry, 6791 ctr_info[0].ctr_mep_type); 6792 ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry, 6793 ctr_info[0].ctr_mep_mdl); 6794 if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) { 6795 ctr1_valid = 0; 6796 rv = soc_mem_field32_modify(unit, mem, index, 6797 ctr_info[0].ctr_valid, 0); 6798 } 6799 } 6800 ctr2_valid = soc_mem_field32_get(unit, mem, 6801 (uint32 *)entry, ctr_info[1].ctr_valid); 6802 if (ctr2_valid) { 6803 ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry, 6804 ctr_info[1].ctr_mep_type); 6805 ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry, 6806 ctr_info[1].ctr_mep_mdl); 6807 if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) { 6808 rv = soc_mem_field32_modify(unit, mem, index, 6809 ctr_info[1].ctr_valid, 0); 6810 ctr2_valid = 0; 6811 } 6812 } 6813 6814 /* return rx & tx counters allocated if any */ 6815 rv =_bcm_kt2_oam_free_counter(unit, h_data_p); 6816 if (BCM_FAILURE(rv)) { 6817 LOG_ERROR(BSL_LS_BCM_OAM, 6818 (BSL_META_U(unit, 6819 "OAM Error: LM counter block " 6820 "free failed (EP=%d) - %s.\n"), 6821 h_data_p->ep_id, bcm_errmsg(rv))); 6822 return (rv); 6823 } 6824 return rv; 6825 } 6826 6827 /* 6828 * Function: 6829 * _bcm_kt2_oam_stm_table_clear 6830 * Purpose: 6831 * Clear MA base ptr and return MA index to the pool 6832 * Parameters: 6833 * unit - (IN) BCM device number 6834 * mod_id - (IN) Module Id 6835 * index - (IN) stm member index 6836 * port_id - (IN) port number 6837 * h_data_p - (IN) Pointer to hash data 6838 * Retruns: 6839 * BCM_E_XXX 6840 */ 6841 STATIC int 6842 _bcm_kt2_oam_stm_table_clear(int unit, bcm_module_t mod_id, int index, 6843 bcm_port_t port_id, 6844 _bcm_oam_hash_data_t *h_data_p) 6845 { 6846 int rv = BCM_E_NONE;/* Operation return status. */ 6847 int stm_index = 0; 6848 source_trunk_map_table_entry_t stm_entry; 6849 uint16 ma_base_idx; /* Base pointer to endpoint state */ 6850 /* table [MA_INDEX = (BASE + MDL)]. */ 6851 int idx = 0; 6852 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 6853 int count = 0; 6854 int ma_idx_entry_count = 0; 6855 shr_idxres_list_handle_t pool = NULL; 6856 6857 uint32 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0}; 6858 6859 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 6860 6861 soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm); 6862 6863 rv = _bcm_esw_src_mod_port_table_index_get(unit, 6864 mod_id, port_id, &stm_index); 6865 if(BCM_FAILURE(rv)) { 6866 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 6867 return rv; 6868 } 6869 6870 rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY, 6871 stm_index, &stm_entry); 6872 6873 if(BCM_FAILURE(rv)) { 6874 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 6875 return rv; 6876 } 6877 6878 ma_base_idx = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, 6879 &stm_entry, MA_BASE_PTRf); 6880 if (index == 0) { 6881 /* Return Rx indices to free pool. */ 6882 for (idx = 0; idx < (1 << _BCM_OAM_EP_LEVEL_BIT_COUNT); idx++) { 6883 rx_index[idx] = ma_base_idx + idx; 6884 } 6885 6886 rv = _bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p, 6887 &ma_idx_entry_count, &pool); 6888 if(BCM_FAILURE(rv)) { 6889 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 6890 return rv; 6891 } 6892 6893 rv = shr_idxres_list_free_set(pool, ma_idx_entry_count, 6894 (shr_idxres_element_t *) rx_index, 6895 (shr_idxres_element_t *) &count); 6896 if (BCM_FAILURE(rv) || (8 != count)) { 6897 LOG_ERROR(BSL_LS_BCM_OAM, 6898 (BSL_META_U(unit, 6899 "OAM Error: Rx index list free (EP=%d)" 6900 " (count=%d).\n"), h_data_p->ep_id, count)); 6901 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 6902 return (rv); 6903 } 6904 } 6905 6906 /* Set MA_BASE_PTR to 0 */ 6907 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry, MA_BASE_PTRf, 0); 6908 6909 rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ALL, stm_index, 6910 &stm_entry); 6911 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 6912 return rv; 6913 } 6914 6915 /* 6916 * Function: 6917 * _bcm_kt2_oam_trunk_port_mdl_update 6918 * Purpose: 6919 * Modify port, egr port and stm table entry 6920 * Parameters: 6921 * unit - (IN) BCM device number 6922 * h_data_p - (IN) Pointer to hash data 6923 * Retruns: 6924 * BCM_E_XXX 6925 */ 6926 STATIC int 6927 _bcm_kt2_oam_trunk_port_mdl_update(int unit, 6928 _bcm_oam_hash_data_t *h_data_p) 6929 { 6930 int rv = BCM_E_NONE; /* Operation return status. */ 6931 _bcm_oam_control_t *oc; /* Pointer to control structure*/ 6932 int member_count = 0; 6933 bcm_port_t *member_array = NULL; /* Trunk member port array. */ 6934 int local_member_count = 0; 6935 int i = 0; 6936 bcm_port_t pp_port = 0; 6937 bcm_module_t module_id; /* Module ID */ 6938 uint8 mdl = 0; 6939 6940 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 6941 6942 if(h_data_p->trunk_id == BCM_TRUNK_INVALID) { 6943 return BCM_E_PARAM; 6944 } 6945 6946 /* Get all the local member ports belonging to this trunk */ 6947 BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, h_data_p->trunk_id, 6948 NULL, 0, NULL, &member_count)); 6949 if (0 == member_count) { 6950 /* No members have been added to the trunk group yet */ 6951 LOG_ERROR(BSL_LS_BCM_OAM, 6952 (BSL_META_U(unit, 6953 "OAM Error: No local members have been added to " 6954 "the trunk group yet - %s.\n"), bcm_errmsg(rv))); 6955 return BCM_E_PARAM; 6956 } 6957 6958 _BCM_OAM_ALLOC(member_array, bcm_port_t, 6959 sizeof(bcm_port_t) * member_count, "Trunk info"); 6960 if (NULL == member_array) { 6961 return (BCM_E_MEMORY); 6962 } 6963 6964 /* Get members of the trunk belonging to this module */ 6965 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 6966 h_data_p->trunk_id, 6967 member_count, member_array, 6968 &local_member_count))) { 6969 if (local_member_count > 0) { 6970 for(i = 0; i < local_member_count; i++) { 6971 rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i], 6972 &module_id, &pp_port); 6973 if (BCM_FAILURE(rv)) { 6974 sal_free(member_array); 6975 return (rv); 6976 } 6977 rv =_bcm_kt2_oam_port_mdl_update(unit, pp_port, 1, 6978 h_data_p, &mdl); 6979 if (BCM_FAILURE(rv)) { 6980 sal_free(member_array); 6981 return (rv); 6982 } 6983 } 6984 if (mdl == 0) { 6985 for(i = 0; i < local_member_count; i++) { 6986 rv = _bcm_kt2_oam_stm_table_clear(unit, module_id, i, 6987 member_array[i], h_data_p); 6988 if (BCM_FAILURE(rv)) { 6989 sal_free(member_array); 6990 return (rv); 6991 } 6992 } 6993 } 6994 rv = _bcm_kt2_oam_port_mdl_passive_update(unit, 1, h_data_p, mdl); 6995 if (BCM_FAILURE(rv)) { 6996 sal_free(member_array); 6997 return (rv); 6998 } 6999 7000 } 7001 } 7002 sal_free(member_array); 7003 return BCM_E_NONE; 7004 } 7005 /* 7006 * Function: 7007 * _bcm_port_domain_mdl_bitmap_update 7008 * Purpose: 7009 * Update Port table MDL bitmap and STM table MA_BASE_PTR. 7010 * Parameters: 7011 * unit - (IN) BCM device number 7012 * h_data_p - (IN) Pointer to endpoint hash data 7013 * Retruns: 7014 * BCM_E_XXX 7015 */ 7016 STATIC int 7017 _bcm_port_domain_mdl_bitmap_update(int unit, _bcm_oam_hash_data_t *h_data_p) 7018 { 7019 int rv = BCM_E_NONE;/* Operation return status. */ 7020 uint8 mdl; /* Maintenance domain level. */ 7021 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 7022 bcm_module_t mod_id = 0; 7023 bcm_port_t port_id = 0; 7024 7025 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 7026 7027 /* If the OAM domain is port */ 7028 if (_BCM_OAM_DOMAIN_PORT != h_data_p->oam_domain) { 7029 return (BCM_E_INTERNAL); 7030 } 7031 7032 if(h_data_p->trunk_id != BCM_TRUNK_INVALID) { 7033 rv = _bcm_kt2_oam_trunk_port_mdl_update(unit, h_data_p); 7034 } else { 7035 port_id = _BCM_OAM_GLP_PORT_GET(h_data_p->sglp); 7036 mod_id = _BCM_OAM_GLP_MODULE_ID_GET(h_data_p->sglp); 7037 BCM_IF_ERROR_RETURN 7038 (_bcm_kt2_oam_port_mdl_update(unit, h_data_p->src_pp_port, 7039 1, h_data_p, &mdl)); 7040 BCM_IF_ERROR_RETURN 7041 (_bcm_kt2_oam_port_mdl_passive_update(unit, 1, h_data_p, mdl)); 7042 if (mdl == 0) { 7043 BCM_IF_ERROR_RETURN 7044 (_bcm_kt2_oam_stm_table_clear(unit, mod_id, 0, 7045 port_id, h_data_p)); 7046 } 7047 } 7048 return (rv); 7049 } 7050 7051 /* 7052 * Function: 7053 * _bcm_kt2_oam_l3_entry_destroy 7054 * Purpose: 7055 * Update Ingress MP group table(L3 Entry- LMEP view)entry. 7056 * Parameters: 7057 * unit - (IN) BCM device number 7058 * h_data_p - (IN) Pointer to endpoint hash data 7059 * active_mdl -(IN) Active MDL bitmap value 7060 * Retruns: 7061 * BCM_E_XXX 7062 */ 7063 STATIC int 7064 _bcm_kt2_oam_l3_entry_destroy(int unit, _bcm_oam_hash_data_t *h_data_p, 7065 uint8 *active_mdl) 7066 { 7067 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 7068 l3_entry_1_entry_t l3_entry; /* LMEP view table entry. */ 7069 int l3_index = -1; /* L3 table hardware index. */ 7070 int rv; /* Operation return status. */ 7071 uint8 mdl; /* Maintenance domain level. */ 7072 uint8 other_mdl = 0; /* Maintenance domain level. */ 7073 uint32 ma_base_index; /* Endpoint tbl base index. */ 7074 uint32 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0}; 7075 /* Endpoint Rx hardware index. */ 7076 uint32 count; /* No. of Rx indices freed */ 7077 /* successfully. */ 7078 int idx; /* Iterator variable. */ 7079 soc_field_t mdl_field = 0; 7080 soc_field_t other_mdl_field = 0; 7081 int upmep = 0; 7082 int ma_idx_entry_count = 0; 7083 shr_idxres_list_handle_t pool = NULL; 7084 7085 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 7086 /* Check whether up/down MEP */ 7087 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 7088 mdl_field = LMEP__MDL_BITMAP_PASSIVEf; 7089 other_mdl_field = LMEP__MDL_BITMAP_ACTIVEf; 7090 upmep = 1; 7091 } else { 7092 mdl_field = LMEP__MDL_BITMAP_ACTIVEf; 7093 other_mdl_field = LMEP__MDL_BITMAP_PASSIVEf; 7094 } 7095 rv = _bcm_kt2_oam_find_lmep(unit, h_data_p, &l3_index, &l3_entry); 7096 if (BCM_SUCCESS(rv)) { 7097 /* Endpoint found, get MDL bitmap value. */ 7098 mdl = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, 7099 mdl_field); 7100 7101 /* Passive demultiplexing should not be done on a MIP. 7102 * Hence do not touch PASSIVE bitmap when destroying 7103 * also. 7104 */ 7105 if (!((mdl_field == LMEP__MDL_BITMAP_PASSIVEf) && 7106 (_BCM_OAM_EP_IS_MIP(h_data_p)))) { 7107 /* Clear the MDL bit for this endpoint. */ 7108 mdl &= ~(1 << h_data_p->level); 7109 7110 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 7111 /* Passive MDL bitmap */ 7112 _bcm_kt2_oam_get_passive_mdl_from_active_mdl(unit, *active_mdl, 7113 h_data_p->ma_base_index, &mdl, 1); 7114 } else { 7115 *active_mdl = mdl; 7116 } 7117 } 7118 /* Take L3 module protection mutex to block any updates. */ 7119 L3_LOCK(unit); 7120 if (0 != mdl) { 7121 /* Valid endpoints exist for other MDLs at this index. */ 7122 rv = soc_mem_field32_modify(unit, L3_ENTRY_IPV4_UNICASTm, l3_index, 7123 mdl_field, mdl); 7124 if (BCM_FAILURE(rv)) { 7125 LOG_ERROR(BSL_LS_BCM_OAM, 7126 (BSL_META_U(unit, 7127 "OAM Error:L3 entry LMEP view update(EP=%d) -" 7128 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7129 L3_UNLOCK(unit); 7130 return (rv); 7131 } 7132 /* Clear the counter, if any */ 7133 rv = _bcm_kt2_oam_clear_counter(unit, L3_ENTRY_IPV4_UNICASTm, 7134 l3_index, h_data_p, 7135 (void *)&l3_entry); 7136 if (BCM_FAILURE(rv)) { 7137 /* coverity[copy_paste_error] */ 7138 LOG_ERROR(BSL_LS_BCM_OAM, 7139 (BSL_META_U(unit, 7140 "OAM Error: Clear counter failed (EP=%d) -" 7141 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7142 L3_UNLOCK(unit); 7143 return (rv); 7144 } 7145 7146 } else { 7147 /* check if other MDL bitmap is also zero (passive bitmap incase 7148 of downmep and active bitmap in case of upmep), if so delete the 7149 entry completely */ 7150 other_mdl = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, 7151 other_mdl_field); 7152 if (0 == other_mdl) { 7153 rv = soc_mem_delete_index(unit, L3_ENTRY_IPV4_UNICASTm, 7154 MEM_BLOCK_ALL, l3_index); 7155 rv =_bcm_kt2_oam_free_counter(unit, h_data_p); 7156 if (BCM_FAILURE(rv)) { 7157 LOG_ERROR(BSL_LS_BCM_OAM, 7158 (BSL_META_U(unit, 7159 "OAM Error: LM counter block " 7160 "free failed (EP=%d) - %s.\n"), 7161 h_data_p->ep_id, bcm_errmsg(rv))); 7162 L3_UNLOCK(unit); 7163 return (rv); 7164 } 7165 } else { 7166 /* Valid endpoints exist for other MDLs at this index. */ 7167 rv = soc_mem_field32_modify(unit, L3_ENTRY_IPV4_UNICASTm, 7168 l3_index, mdl_field, mdl); 7169 if (BCM_FAILURE(rv)) { 7170 LOG_ERROR(BSL_LS_BCM_OAM, 7171 (BSL_META_U(unit, 7172 "OAM Error: LMEP view update (EP=%d) -" 7173 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7174 L3_UNLOCK(unit); 7175 return (rv); 7176 } 7177 /* Clear the counter, if any */ 7178 rv = _bcm_kt2_oam_clear_counter(unit, L3_ENTRY_IPV4_UNICASTm, 7179 l3_index, h_data_p, 7180 (void *)&l3_entry); 7181 if (BCM_FAILURE(rv)) { 7182 LOG_ERROR(BSL_LS_BCM_OAM, 7183 (BSL_META_U(unit, 7184 "OAM Error: Clear counter failed (EP=%d) -" 7185 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7186 L3_UNLOCK(unit); 7187 return (rv); 7188 } 7189 7190 } 7191 } 7192 L3_UNLOCK(unit); 7193 7194 /* This is the last Rx endpoint in this OAM group. */ 7195 if ((0 == mdl) && (upmep == 0)) { 7196 ma_base_index = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 7197 &l3_entry, 7198 LMEP__MA_BASE_PTRf); 7199 /* Return Rx indices to free pool. */ 7200 for (idx = 0; idx < (1 << _BCM_OAM_EP_LEVEL_BIT_COUNT); idx++) { 7201 rx_index[idx] = ma_base_index + idx; 7202 } 7203 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p, 7204 &ma_idx_entry_count, &pool)); 7205 rv = shr_idxres_list_free_set(pool, ma_idx_entry_count, 7206 (shr_idxres_element_t *) rx_index, 7207 (shr_idxres_element_t *) &count); 7208 if (BCM_FAILURE(rv) || (8 != count)) { 7209 LOG_ERROR(BSL_LS_BCM_OAM, 7210 (BSL_META_U(unit, 7211 "OAM Error: Rx index list free (EP=%d)" 7212 " (count=%d).\n"), h_data_p->ep_id, count)); 7213 return (rv); 7214 } 7215 } 7216 /* Delete ING_SERVICE pri map profile entry for this endpoint. */ 7217 if (h_data_p->pri_map_index != _BCM_OAM_INVALID_INDEX) { 7218 rv = soc_profile_mem_delete(unit, &oc->ing_service_pri_map, 7219 (h_data_p->pri_map_index * BCM_OAM_INTPRI_MAX)); 7220 if (BCM_FAILURE(rv)) { 7221 LOG_ERROR(BSL_LS_BCM_OAM, 7222 (BSL_META_U(unit, 7223 "OAM Error: Profile table update error (idx=%d)" 7224 "- %s.\n"), h_data_p->pri_map_index, bcm_errmsg(rv))); 7225 return (rv); 7226 } 7227 h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX; 7228 } 7229 } else if (BCM_FAILURE(rv) && (oc->init)) { 7230 /* We do not program passive bitmap for MIP. So dont throw error 7231 * if you don't find an entry, since we might not have created 7232 * such an entry at all. */ 7233 if (!((mdl_field == LMEP__MDL_BITMAP_PASSIVEf) && 7234 (_BCM_OAM_EP_IS_MIP(h_data_p)))) { 7235 LOG_ERROR(BSL_LS_BCM_OAM, 7236 (BSL_META_U(unit, 7237 "OAM(unit %d) Error: L3 entry table lookup (EP=%d) -" 7238 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 7239 return (rv); 7240 } 7241 } 7242 return (BCM_E_NONE); 7243 } 7244 7245 /* 7246 * Function: 7247 * _bcm_kt2_oam_egr_mp_group_entry_destroy 7248 * Purpose: 7249 * Update Egress MP group table entry. 7250 * Parameters: 7251 * unit - (IN) BCM device number 7252 * h_data_p - (IN) Pointer to endpoint hash data 7253 * Retruns: 7254 * BCM_E_XXX 7255 */ 7256 STATIC int 7257 _bcm_kt2_oam_egr_mp_group_entry_destroy(int unit, 7258 _bcm_oam_hash_data_t *h_data_p, 7259 uint8 *active_mdl) 7260 { 7261 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 7262 uint8 mdl; /* Maintenance domain level. */ 7263 uint8 other_mdl = 0; /* Maintenance domain level. */ 7264 int rv; /* Operation return status. */ 7265 uint32 ma_base_index; /* Endpoint tbl base index. */ 7266 uint32 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0}; 7267 /* Endpoint Rx hardware index. */ 7268 uint32 count; /* No. of Rx indices freed */ 7269 /* successfully. */ 7270 int idx; /* Iterator variable. */ 7271 soc_field_t mdl_field = 0; 7272 soc_field_t other_mdl_field = 0; 7273 egr_mp_group_entry_t egr_mp_group; /* Egress MP group tbl entry buffer */ 7274 int mp_grp_index = 0; 7275 int upmep = 0; 7276 #if defined(INCLUDE_BHH) 7277 _bcm_oam_hash_data_t *hash_data; 7278 bcm_oam_endpoint_t ep_id; 7279 int key1 = 0, key2 = 0; 7280 #endif /* INCLUDE_BHH */ 7281 7282 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 7283 7284 /* Check whether up/down MEP */ 7285 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 7286 mdl_field = MDL_BITMAP_ACTIVEf; 7287 other_mdl_field = MDL_BITMAP_PASSIVEf; 7288 upmep = 1; 7289 } else { 7290 mdl_field = MDL_BITMAP_PASSIVEf; 7291 other_mdl_field = MDL_BITMAP_ACTIVEf; 7292 } 7293 rv = _bcm_kt2_oam_find_egr_lmep(unit, h_data_p, 7294 &mp_grp_index, &egr_mp_group); 7295 if (BCM_SUCCESS(rv)) { 7296 7297 #if defined(INCLUDE_BHH) 7298 if (BHH_EP_TYPE(h_data_p)) { 7299 7300 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, h_data_p->egress_if)) { 7301 key1 = h_data_p->egress_if - BCM_XGS3_EGRESS_IDX_MIN(unit); 7302 } else { 7303 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, h_data_p->egress_if)) { 7304 key1 = h_data_p->egress_if - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 7305 } 7306 } 7307 7308 for (ep_id = _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET; 7309 ep_id < (_BCM_OAM_BHH_KT2_ENDPOINT_OFFSET + oc->bhh_endpoint_count); 7310 ep_id++) { 7311 7312 hash_data = &(oc->oam_hash_data[ep_id]); 7313 if ((!hash_data->in_use) || (hash_data->ep_id == h_data_p->ep_id)) { 7314 continue; 7315 } 7316 7317 if (BCM_XGS3_L3_EGRESS_IDX_VALID(unit, hash_data->egress_if)) { 7318 key2 = hash_data->egress_if - BCM_XGS3_EGRESS_IDX_MIN(unit); 7319 } else { 7320 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, hash_data->egress_if)) { 7321 key2 = h_data_p->egress_if - 7322 BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 7323 } 7324 } 7325 7326 if (key1 == key2) { 7327 /* There are other EPs using the same NHI */ 7328 return BCM_E_NONE; 7329 } 7330 } 7331 } 7332 7333 #endif /* INCLUDE_BHH */ 7334 7335 /* Endpoint found, get MDL bitmap value. */ 7336 mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, 7337 mdl_field); 7338 7339 /* Passive demultiplexing should not be done on a MIP. 7340 * Hence do not touch PASSIVE bitmap when destroying 7341 * also. 7342 */ 7343 if (!((mdl_field == MDL_BITMAP_PASSIVEf) && 7344 (_BCM_OAM_EP_IS_MIP(h_data_p)))) { 7345 /* Clear the MDL bit for this endpoint. */ 7346 mdl &= ~(1 << h_data_p->level); 7347 7348 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 7349 *active_mdl = mdl; 7350 } else{ 7351 /* Passive MDL bitmap */ 7352 _bcm_kt2_oam_get_passive_mdl_from_active_mdl(unit, *active_mdl, 7353 h_data_p->ma_base_index, &mdl, 0); 7354 } 7355 } 7356 7357 /* Take L3 module protection mutex to block any updates. */ 7358 soc_mem_lock(unit, EGR_MP_GROUPm); 7359 if (0 != mdl) { 7360 /* Valid endpoints exist for other MDLs at this index. */ 7361 rv = soc_mem_field32_modify(unit, EGR_MP_GROUPm, mp_grp_index, 7362 mdl_field, mdl); 7363 if (BCM_FAILURE(rv)) { 7364 LOG_ERROR(BSL_LS_BCM_OAM, 7365 (BSL_META_U(unit, 7366 "OAM Error: EGR MP group table update (EP=%d) -" 7367 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7368 soc_mem_unlock(unit, EGR_MP_GROUPm); 7369 return (rv); 7370 } 7371 /* Clear the counter, if any */ 7372 rv = _bcm_kt2_oam_clear_counter(unit, EGR_MP_GROUPm, mp_grp_index, 7373 h_data_p, (void *)&egr_mp_group); 7374 if (BCM_FAILURE(rv)) { 7375 LOG_ERROR(BSL_LS_BCM_OAM, 7376 (BSL_META_U(unit, 7377 "OAM Error:EGR MP group table update(EP=%d) -" 7378 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7379 soc_mem_unlock(unit, EGR_MP_GROUPm); 7380 return (rv); 7381 } 7382 } else { 7383 /* check if other MDL bitmap is also zero (passive bitmap in case 7384 of downmep and active bitmap in case of upmep), if so delete the 7385 entry completely */ 7386 other_mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, 7387 other_mdl_field); 7388 if (0 == other_mdl) { 7389 rv = soc_mem_delete_index(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL, 7390 mp_grp_index); 7391 rv =_bcm_kt2_oam_free_counter(unit, h_data_p); 7392 if (BCM_FAILURE(rv)) { 7393 LOG_ERROR(BSL_LS_BCM_OAM, 7394 (BSL_META_U(unit, 7395 "OAM Error: LM counter block " 7396 "free failed (EP=%d) - %s.\n"), 7397 h_data_p->ep_id, bcm_errmsg(rv))); 7398 soc_mem_unlock(unit, EGR_MP_GROUPm); 7399 return (rv); 7400 } 7401 } else { 7402 rv = soc_mem_field32_modify(unit, EGR_MP_GROUPm, mp_grp_index, 7403 mdl_field, mdl); 7404 if (BCM_FAILURE(rv)) { 7405 LOG_ERROR(BSL_LS_BCM_OAM, 7406 (BSL_META_U(unit, 7407 "OAM Error: EGR MP group table update " 7408 "(EP=%d) -" " %s.\n"), 7409 h_data_p->ep_id, bcm_errmsg(rv))); 7410 soc_mem_unlock(unit, EGR_MP_GROUPm); 7411 return (rv); 7412 } 7413 /* Clear the counter, if any */ 7414 rv = _bcm_kt2_oam_clear_counter(unit, EGR_MP_GROUPm, mp_grp_index, 7415 h_data_p, (void *)&egr_mp_group); 7416 if (BCM_FAILURE(rv)) { 7417 LOG_ERROR(BSL_LS_BCM_OAM, 7418 (BSL_META_U(unit, 7419 "OAM Error:EGR MP group tbl update(EP=%d)-" 7420 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7421 soc_mem_unlock(unit, EGR_MP_GROUPm); 7422 return (rv); 7423 } 7424 } 7425 } 7426 soc_mem_unlock(unit, EGR_MP_GROUPm); 7427 7428 /* This is the last Rx endpoint in this OAM group. */ 7429 if ((0 == mdl) && (upmep)) { 7430 ma_base_index = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, 7431 MA_BASE_PTRf); 7432 /* Return Rx indices to free pool. */ 7433 for (idx = 0; idx < (1 << _BCM_OAM_EP_LEVEL_BIT_COUNT); idx++) { 7434 rx_index[idx] = ma_base_index + idx; 7435 } 7436 7437 rv = shr_idxres_list_free_set(oc->egr_ma_idx_pool, 8, 7438 (shr_idxres_element_t *) rx_index, 7439 (shr_idxres_element_t *) &count); 7440 if (BCM_FAILURE(rv) || (8 != count)) { 7441 LOG_ERROR(BSL_LS_BCM_OAM, 7442 (BSL_META_U(unit, 7443 "OAM Error: Egr Rx index list free (EP=%d)" 7444 " (count=%d).\n"), h_data_p->ep_id, count)); 7445 return (rv); 7446 } 7447 } 7448 /* Delete EGR_SERVICE pri map profile entry for this endpoint. */ 7449 if (h_data_p->egr_pri_map_index != _BCM_OAM_INVALID_INDEX) { 7450 rv = soc_profile_mem_delete(unit, &oc->egr_service_pri_map, 7451 (h_data_p->egr_pri_map_index * BCM_OAM_INTPRI_MAX)); 7452 if (BCM_FAILURE(rv)) { 7453 LOG_ERROR(BSL_LS_BCM_OAM, 7454 (BSL_META_U(unit, 7455 "OAMError:Profile table update error (idx=%d)" 7456 "- %s.\n"), h_data_p->egr_pri_map_index, bcm_errmsg(rv))); 7457 return (rv); 7458 } 7459 h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 7460 } 7461 } else if (BCM_FAILURE(rv) && (oc->init)) { 7462 /* We do not program passive bitmap for MIP. So dont throw error 7463 * if you don't find an entry, since we might not have created 7464 * such an entry at all. */ 7465 if (!((mdl_field == MDL_BITMAP_PASSIVEf) && 7466 (_BCM_OAM_EP_IS_MIP(h_data_p)))) { 7467 LOG_ERROR(BSL_LS_BCM_OAM, 7468 (BSL_META_U(unit, 7469 "OAM(unit %d) Error: LMEP table write (EP=%d) -" 7470 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 7471 return (rv); 7472 } 7473 } 7474 return (BCM_E_NONE); 7475 } 7476 7477 /* 7478 * Function: 7479 * _bcm_kt2_oam_local_endpoint_delete 7480 * Purpose: 7481 * Delete a local endpoint. 7482 * Parameters: 7483 * unit - (IN) BCM device number 7484 * h_data_p - (IN) Pointer to endpoint hash data 7485 * Retruns: 7486 * BCM_E_XXX 7487 */ 7488 STATIC int 7489 _bcm_kt2_oam_local_endpoint_delete(int unit, _bcm_oam_hash_data_t *h_data_p) 7490 { 7491 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 7492 lmep_entry_t lmep_entry; /* Local endpoint table entry. */ 7493 int rv; /* Operation return status. */ 7494 lmep_1_entry_t lmep_1_entry; /* LMEP_1 table entry. */ 7495 soc_profile_mem_t *opcode_control_profile; /* profile used - 7496 ingress or egress */ 7497 soc_profile_mem_t *dglp_profile; /* dglp profile used - 7498 ingress or egress */ 7499 ma_index_entry_t ma_idx_entry; /* MA_INDEX table entry buffer. */ 7500 ma_index_entry_t egr_ma_idx_entry;/* MA_INDEX table entry buffer. */ 7501 void *ma_idx_ptr; 7502 soc_mem_t ma_index_mem = 0; 7503 uint8 active_mdl = 0; 7504 int ma_offset = 0; 7505 7506 /* Lock already taken by the calling routine. */ 7507 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 7508 7509 if (1 == h_data_p->local_tx_enabled) { 7510 7511 /* Clear endpoint Tx config in hardware. */ 7512 sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t)); 7513 sal_memset(&lmep_1_entry, 0, sizeof(lmep_1_entry_t)); 7514 rv = WRITE_LMEPm(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index, 7515 &lmep_entry); 7516 7517 if (BCM_FAILURE(rv)) { 7518 LOG_ERROR(BSL_LS_BCM_OAM, 7519 (BSL_META_U(unit, 7520 "OAM Error: LMEP table write (EP=%d)" 7521 " failed - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7522 return (rv); 7523 } 7524 rv = WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index, 7525 &lmep_1_entry); 7526 if (BCM_FAILURE(rv)) { 7527 LOG_ERROR(BSL_LS_BCM_OAM, 7528 (BSL_META_U(unit, 7529 "OAM Error: LMEP_1 table write (EP=%d)" 7530 " failed - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7531 return (rv); 7532 } 7533 7534 /* Return ID back to free LMEP ID pool. */ 7535 BCM_IF_ERROR_RETURN 7536 (shr_idxres_list_free(oc->lmep_pool, h_data_p->local_tx_index)); 7537 } 7538 7539 if (1 == h_data_p->local_rx_enabled) { 7540 /* Check whether up/down MEP */ 7541 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 7542 opcode_control_profile = &oc->egr_oam_opcode_control_profile; 7543 dglp_profile = &oc->egr_oam_dglp_profile; 7544 ma_index_mem = EGR_MA_INDEXm; 7545 sal_memset(&egr_ma_idx_entry, 0, sizeof(egr_ma_index_entry_t)); 7546 ma_idx_ptr = &egr_ma_idx_entry; 7547 } else { 7548 opcode_control_profile = &oc->oam_opcode_control_profile; 7549 dglp_profile = &oc->ing_oam_dglp_profile; 7550 ma_index_mem = MA_INDEXm; 7551 sal_memset(&ma_idx_entry, 0, sizeof(ma_index_entry_t)); 7552 ma_idx_ptr = &ma_idx_entry; 7553 } 7554 7555 /* Delete OAM opcode profile entry for this endpoint. */ 7556 rv = soc_profile_mem_delete(unit, opcode_control_profile, 7557 h_data_p->profile_index); 7558 if (BCM_FAILURE(rv)) { 7559 LOG_ERROR(BSL_LS_BCM_OAM, 7560 (BSL_META_U(unit, 7561 "OAM Error: Profile table update error (idx=%d)" 7562 "- %s.\n"), h_data_p->profile_index, bcm_errmsg(rv))); 7563 return (rv); 7564 } 7565 /* Delete DGLP profile entry for this endpoint. */ 7566 if (h_data_p->dglp1_profile_index != _BCM_OAM_INVALID_INDEX) { 7567 rv = soc_profile_mem_delete(unit, dglp_profile, 7568 h_data_p->dglp1_profile_index); 7569 if (BCM_FAILURE(rv)) { 7570 LOG_ERROR(BSL_LS_BCM_OAM, 7571 (BSL_META_U(unit, 7572 "OAM Error: Profile table update " 7573 "error (idx=%d)" "- %s.\n"), 7574 h_data_p->dglp1_profile_index, bcm_errmsg(rv))); 7575 return (rv); 7576 } 7577 } 7578 if (h_data_p->dglp2_profile_index != _BCM_OAM_INVALID_INDEX) { 7579 rv = soc_profile_mem_delete(unit, dglp_profile, 7580 h_data_p->dglp2_profile_index); 7581 if (BCM_FAILURE(rv)) { 7582 LOG_ERROR(BSL_LS_BCM_OAM, 7583 (BSL_META_U(unit, 7584 "OAM Error: Profile table update " 7585 "error (idx=%d)" "- %s.\n"), 7586 h_data_p->dglp2_profile_index, bcm_errmsg(rv))); 7587 return (rv); 7588 } 7589 } 7590 /* Get MA_INDEX offset */ 7591 rv = _bcm_kt2_oam_ma_index_offset_get(unit, h_data_p, &ma_offset); 7592 if (BCM_FAILURE(rv)) { 7593 LOG_ERROR(BSL_LS_BCM_OAM, 7594 (BSL_META_U(unit, 7595 "OAM Error: MA INDEX table offset get failed EP=%d" 7596 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7597 return (rv); 7598 } 7599 7600 h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset; 7601 7602 /* Delete MA INDEX entry */ 7603 rv = _bcm_kt2_oam_ma_index_entry_set(unit, h_data_p, 7604 ma_index_mem, ma_idx_ptr, 1); 7605 if (BCM_FAILURE(rv)) { 7606 LOG_ERROR(BSL_LS_BCM_OAM, 7607 (BSL_META_U(unit, 7608 "OAM Error: MA INDEX table delete failed EP=%d" 7609 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7610 return (rv); 7611 } 7612 if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) { 7613 rv = _bcm_port_domain_mdl_bitmap_update(unit, h_data_p); 7614 if (BCM_FAILURE(rv)) { 7615 LOG_ERROR(BSL_LS_BCM_OAM, 7616 (BSL_META_U(unit, 7617 "OAM Error: port OAM MDL update failed EP=%d" 7618 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7619 return (rv); 7620 } 7621 } else if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 7622 rv = _bcm_kt2_oam_egr_mp_group_entry_destroy(unit, h_data_p, 7623 &active_mdl); 7624 if (BCM_FAILURE(rv)) { 7625 LOG_ERROR(BSL_LS_BCM_OAM, 7626 (BSL_META_U(unit, 7627 "OAM Error: Egr MP Group update (EP=%d) -" 7628 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7629 return (rv); 7630 } 7631 7632 7633 /* Update Ingress MP group table(L3_ENTRY) */ 7634 rv = _bcm_kt2_oam_l3_entry_destroy(unit, h_data_p, &active_mdl); 7635 if (BCM_FAILURE(rv)) { 7636 LOG_ERROR(BSL_LS_BCM_OAM, 7637 (BSL_META_U(unit, 7638 "OAM Error: LMEP view update (EP=%d) -" 7639 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7640 return (rv); 7641 } 7642 } else { 7643 /* Update Ingress MP group table(L3_ENTRY) */ 7644 rv = _bcm_kt2_oam_l3_entry_destroy(unit, h_data_p, &active_mdl); 7645 if (BCM_FAILURE(rv)) { 7646 LOG_ERROR(BSL_LS_BCM_OAM, 7647 (BSL_META_U(unit, 7648 "OAM Error: LMEP view update (EP=%d) -" 7649 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7650 return (rv); 7651 7652 } 7653 rv = _bcm_kt2_oam_egr_mp_group_entry_destroy(unit, h_data_p, 7654 &active_mdl); 7655 if (BCM_FAILURE(rv)) { 7656 LOG_ERROR(BSL_LS_BCM_OAM, 7657 (BSL_META_U(unit, 7658 "OAM Error: Egr MP Group update (EP=%d) -" 7659 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 7660 return (rv); 7661 } 7662 } 7663 } 7664 return (BCM_E_NONE); 7665 } 7666 7667 7668 /* 7669 * Function: 7670 * _bcm_kt2_oam_port_table_key_update1 7671 * Purpose: 7672 * Update OAM_KEY1 and OAM_KEY2 in port table 7673 * Parameters: 7674 * unit - (IN) BCM device number 7675 * mem - (IN) PORT_TAB/EGR_PORT 7676 * pp_port - (IN) PP port 7677 * h_data_p - (IN/OUT) Pointer to endpoint hash data 7678 * Returns: 7679 * BCM_E_XXX 7680 */ 7681 int 7682 _bcm_kt2_oam_port_table_key_update1(int unit, soc_mem_t mem, int pp_port, 7683 _bcm_oam_hash_data_t *h_data_p) 7684 { 7685 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 7686 int rv = BCM_E_NONE; /* Operation return status. */ 7687 port_tab_entry_t port_entry; 7688 egr_port_entry_t egr_port_entry; 7689 uint32 key_type = 0; 7690 uint32 oam_key1 = 0; 7691 uint32 oam_key2 = 0; 7692 void *port_entry_ptr; 7693 uint16 *key1_ref_count = NULL; 7694 uint16 *key2_ref_count = NULL; 7695 7696 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 7697 7698 /* Set the search key type. */ 7699 if (_BCM_OAM_EP_IS_VP_TYPE(h_data_p)) { 7700 key_type = _BCM_OAM_DOMAIN_VP; 7701 } else if(h_data_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) { 7702 key_type = _BCM_OAM_DOMAIN_CVLAN; 7703 } else if(h_data_p->flags & 7704 BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) { 7705 key_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN; 7706 } else if((h_data_p->vlan == 0) && (h_data_p->inner_vlan == 0)) { 7707 key_type = _BCM_OAM_DOMAIN_PORT; 7708 } else { 7709 key_type = _BCM_OAM_DOMAIN_SVLAN; 7710 } 7711 7712 if (mem == PORT_TABm) { 7713 port_entry_ptr = &port_entry; 7714 key1_ref_count = &oc->oam_key1_ref_count[0]; 7715 key2_ref_count = &oc->oam_key2_ref_count[0]; 7716 } else { 7717 port_entry_ptr = &egr_port_entry; 7718 key1_ref_count = &oc->egr_oam_key1_ref_count[0]; 7719 key2_ref_count = &oc->egr_oam_key2_ref_count[0]; 7720 } 7721 7722 /* 7723 We need to set the OAM_KEY1 and OAM_KEY2 fields of the PORT_TABLE and 7724 EGR_PORT_TABLE based on the key_type of OAM */ 7725 7726 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, pp_port, port_entry_ptr); 7727 if (BCM_FAILURE(rv)) { 7728 LOG_ERROR(BSL_LS_BCM_OAM, 7729 (BSL_META_U(unit, 7730 "OAM Error: Port table read - %s.\n"), 7731 bcm_errmsg(rv))); 7732 return (rv); 7733 } 7734 oam_key1 = soc_mem_field32_get(unit, mem, port_entry_ptr, OAM_KEY1f); 7735 oam_key2 = soc_mem_field32_get(unit, mem, port_entry_ptr, OAM_KEY2f); 7736 7737 if (key_type != _BCM_OAM_DOMAIN_PORT) { 7738 if ((oam_key1 > 0) && (oam_key2 > 0)) { 7739 if ((oam_key1 == key_type) || (oam_key2 == key_type)) { 7740 } else { 7741 LOG_ERROR(BSL_LS_BCM_OAM, 7742 (BSL_META_U(unit, 7743 "OAM Error: Invalid OAM domain to resolve " 7744 "(EP=%d) - %s.\n"), 7745 h_data_p->ep_id, bcm_errmsg(rv))); 7746 return (BCM_E_PARAM); 7747 } 7748 } 7749 } 7750 7751 if (key_type != _BCM_OAM_DOMAIN_PORT) { 7752 if ((oam_key1 == 0) && (oam_key2 == 0)) { 7753 soc_mem_field32_set(unit, mem, port_entry_ptr, OAM_KEY1f, key_type); 7754 key1_ref_count[pp_port]++; 7755 } else if ((oam_key1 != key_type) && (oam_key2 == 0)) { 7756 if (key_type > oam_key1) { 7757 soc_mem_field32_set(unit, mem, port_entry_ptr, OAM_KEY2f, 7758 key_type); 7759 key2_ref_count[pp_port]++; 7760 } else { 7761 key2_ref_count[pp_port] = key1_ref_count[pp_port]; 7762 soc_mem_field32_set(unit, mem, port_entry_ptr, 7763 OAM_KEY1f, key_type); 7764 key1_ref_count[pp_port] = 1; 7765 soc_mem_field32_set(unit, mem, port_entry_ptr, 7766 OAM_KEY2f, oam_key1); 7767 } 7768 } else if ((oam_key2 != key_type) && (oam_key1 == 0)) { 7769 if (key_type < oam_key2) { 7770 soc_mem_field32_set(unit, mem, port_entry_ptr, OAM_KEY1f, 7771 key_type); 7772 key1_ref_count[pp_port]++; 7773 } else { 7774 key1_ref_count[pp_port] = key2_ref_count[pp_port]; 7775 soc_mem_field32_set(unit, mem, port_entry_ptr, 7776 OAM_KEY1f, oam_key2); 7777 soc_mem_field32_set(unit, mem, port_entry_ptr, 7778 OAM_KEY2f, key_type); 7779 key2_ref_count[pp_port] = 1; 7780 } 7781 } else if (oam_key1 == key_type) { 7782 key1_ref_count[pp_port]++; 7783 } else if (oam_key2 == key_type) { 7784 key2_ref_count[pp_port]++ ; 7785 } 7786 if (SOC_WARM_BOOT(unit)) { 7787 return rv; 7788 } 7789 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, pp_port, port_entry_ptr); 7790 if (BCM_FAILURE(rv)) { 7791 LOG_ERROR(BSL_LS_BCM_OAM, 7792 (BSL_META_U(unit, 7793 "OAM Error: Port table update failed " 7794 "%s.\n"), bcm_errmsg(rv))); 7795 return (rv); 7796 } 7797 } 7798 return rv; 7799 } 7800 7801 /* 7802 * Function: 7803 * _bcm_kt2_oam_port_table_key_update 7804 * Purpose: 7805 * Update port table OAM key fields. 7806 * Parameters: 7807 * unit - (IN) BCM device number 7808 * mem - (IN) PORT_TAB/EGR_PORT 7809 * h_data_p - (IN/OUT) Pointer to endpoint hash data 7810 * Returns: 7811 * BCM_E_XXX 7812 */ 7813 int 7814 _bcm_kt2_oam_port_table_key_update(int unit, soc_mem_t mem, 7815 _bcm_oam_hash_data_t *h_data_p) 7816 { 7817 int rv = BCM_E_NONE; /* Operation return status. */ 7818 bcm_port_t *member_array = NULL; /* Trunk member port array. */ 7819 bcm_module_t module_id; /* Module ID */ 7820 bcm_port_t pp_port = 0; 7821 int member_count = 0; 7822 int local_member_count = 0; 7823 int i = 0; 7824 7825 if ((h_data_p->trunk_id != BCM_TRUNK_INVALID)) { 7826 /* Get count of ports in this trunk. */ 7827 BCM_IF_ERROR_RETURN 7828 (bcm_esw_trunk_get(unit, h_data_p->trunk_id, 7829 NULL, 0, NULL, &member_count)); 7830 if (0 == member_count) { 7831 /* No members have been added to the trunk group yet */ 7832 LOG_ERROR(BSL_LS_BCM_OAM, 7833 (BSL_META_U(unit, 7834 "OAM Error: No local members have been added to " 7835 "the trunk group yet - %s.\n"), bcm_errmsg(rv))); 7836 return BCM_E_PARAM; 7837 } 7838 7839 _BCM_OAM_ALLOC(member_array, bcm_port_t, 7840 sizeof(bcm_port_t) * member_count, "Trunk info"); 7841 if (NULL == member_array) { 7842 return (BCM_E_MEMORY); 7843 7844 } 7845 7846 /* Get a member of the trunk belonging to this module */ 7847 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 7848 h_data_p->trunk_id, 7849 member_count, member_array, 7850 &local_member_count))) { 7851 if (local_member_count > 0) { 7852 for(i = 0; i < local_member_count; i++) { 7853 rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i], 7854 &module_id, &pp_port); 7855 if (BCM_FAILURE(rv)) { 7856 sal_free(member_array); 7857 return (rv); 7858 } 7859 rv = _bcm_kt2_oam_port_table_key_update1(unit, mem, 7860 pp_port, h_data_p); 7861 if (BCM_FAILURE(rv)) { 7862 sal_free(member_array); 7863 return (rv); 7864 } 7865 } 7866 7867 } 7868 } 7869 sal_free(member_array); 7870 } else { 7871 if (mem == PORT_TABm) { 7872 pp_port = h_data_p->src_pp_port; 7873 } else { 7874 pp_port = h_data_p->dst_pp_port; 7875 } 7876 rv = _bcm_kt2_oam_port_table_key_update1(unit, mem, pp_port, h_data_p); 7877 } 7878 return rv; 7879 } 7880 7881 /* 7882 * Function: 7883 * _bcm_kt2_oam_decrement_key_ref_count1 7884 * Purpose: 7885 * Decrement PORT tab key1/key2 usage ref count. 7886 * Parameters: 7887 * unit - (IN) BCM device number 7888 * src_pp_port - (IN) Source PP port 7889 * dst_pp_port - (IN) destination PP port 7890 * h_data_p - (IN) Endpoint hash data. 7891 * Retruns: 7892 * BCM_E_XXX 7893 */ 7894 int 7895 _bcm_kt2_oam_decrement_key_ref_count1(int unit, uint32 src_pp_port, 7896 uint32 dst_pp_port, 7897 _bcm_oam_hash_data_t *h_data_p) 7898 { 7899 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 7900 int rv = BCM_E_NONE; /* Operation return status. */ 7901 port_tab_entry_t port_entry; 7902 egr_port_entry_t egr_port_entry; 7903 uint32 key_type = 0; 7904 uint32 oam_key1 = 0; 7905 uint32 oam_key2 = 0; 7906 int update_entry = 0; 7907 7908 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 7909 7910 /* Set the search key type. */ 7911 if (_BCM_OAM_EP_IS_VP_TYPE(h_data_p)) { 7912 key_type = _BCM_OAM_DOMAIN_VP; 7913 } else if(h_data_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) { 7914 key_type = _BCM_OAM_DOMAIN_CVLAN; 7915 } else if(h_data_p->flags & 7916 BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) { 7917 key_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN; 7918 } else if((h_data_p->vlan == 0) && (h_data_p->inner_vlan == 0)) { 7919 key_type = _BCM_OAM_DOMAIN_PORT; 7920 } else { 7921 key_type = _BCM_OAM_DOMAIN_SVLAN; 7922 } 7923 7924 rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, src_pp_port, &port_entry); 7925 if (BCM_FAILURE(rv)) { 7926 LOG_ERROR(BSL_LS_BCM_OAM, 7927 (BSL_META_U(unit, 7928 "OAM Error: Port table entry read failed - %s.\n"), 7929 bcm_errmsg(rv))); 7930 return (rv); 7931 } 7932 rv = soc_mem_read(unit, EGR_PORTm, MEM_BLOCK_ANY, 7933 dst_pp_port, &egr_port_entry); 7934 if (BCM_FAILURE(rv)) { 7935 LOG_ERROR(BSL_LS_BCM_OAM, 7936 (BSL_META_U(unit, 7937 "OAM Error: Port table entry read failed - %s.\n"), 7938 bcm_errmsg(rv))); 7939 return (rv); 7940 } 7941 7942 oam_key1 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY1f); 7943 oam_key2 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY2f); 7944 7945 if (key_type != _BCM_OAM_DOMAIN_PORT) { 7946 if (key_type == oam_key1) { 7947 oc->oam_key1_ref_count[src_pp_port]--; 7948 if (oc->oam_key1_ref_count[src_pp_port] == 0) { 7949 soc_PORT_TABm_field32_set(unit, &port_entry, OAM_KEY1f, 0); 7950 update_entry = 1; 7951 } 7952 } else if (key_type == oam_key2) { 7953 oc->oam_key2_ref_count[src_pp_port]--; 7954 if (oc->oam_key2_ref_count[src_pp_port] == 0) { 7955 soc_PORT_TABm_field32_set(unit, &port_entry, OAM_KEY2f, 0); 7956 update_entry = 1; 7957 } 7958 } 7959 if (update_entry) { 7960 rv = soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, 7961 src_pp_port, &port_entry); 7962 update_entry = 0; 7963 } 7964 7965 oam_key1 = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, OAM_KEY1f); 7966 oam_key2 = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, OAM_KEY2f); 7967 7968 if (key_type == oam_key1) { 7969 oc->egr_oam_key1_ref_count[dst_pp_port]--; 7970 if (oc->egr_oam_key1_ref_count[dst_pp_port] == 0) { 7971 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, OAM_KEY1f, 0); 7972 update_entry = 1; 7973 } 7974 } else if (key_type == oam_key2) { 7975 oc->egr_oam_key2_ref_count[dst_pp_port]--; 7976 if (oc->egr_oam_key2_ref_count[dst_pp_port] == 0) { 7977 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, OAM_KEY2f, 0); 7978 update_entry = 1; 7979 } 7980 } 7981 if (update_entry) { 7982 rv = soc_mem_write(unit, EGR_PORTm, MEM_BLOCK_ALL, 7983 dst_pp_port, &egr_port_entry); 7984 update_entry = 0; 7985 } 7986 } 7987 return rv; 7988 } 7989 7990 /* 7991 * Function: 7992 * _bcm_kt2_oam_decrement_key_ref_count 7993 * Purpose: 7994 * Decrement PORT tab key1/key2 usage ref count. 7995 * Parameters: 7996 * unit - (IN) BCM device number 7997 * h_data_p - (IN) Endpoint hash data. 7998 * Retruns: 7999 * BCM_E_XXX 8000 */ 8001 int 8002 _bcm_kt2_oam_decrement_key_ref_count(int unit, 8003 _bcm_oam_hash_data_t *h_data_p) 8004 { 8005 int rv = BCM_E_NONE; /* Operation return status. */ 8006 bcm_port_t *member_array = NULL; /* Trunk member port array. */ 8007 bcm_module_t module_id; /* Module ID */ 8008 bcm_port_t src_pp_port = 0; 8009 int member_count = 0; 8010 int local_member_count = 0; 8011 int i = 0; 8012 8013 if (h_data_p->trunk_id != BCM_TRUNK_INVALID) { 8014 /* Get count of ports in this trunk. */ 8015 BCM_IF_ERROR_RETURN 8016 (bcm_esw_trunk_get(unit, h_data_p->trunk_id, 8017 NULL, 0, NULL, &member_count)); 8018 if (0 == member_count) { 8019 /* No members have been added to the trunk group yet */ 8020 LOG_ERROR(BSL_LS_BCM_OAM, 8021 (BSL_META_U(unit, 8022 "OAM Error: No local members have been added to " 8023 "the trunk group yet - %s.\n"), bcm_errmsg(rv))); 8024 return BCM_E_PARAM; 8025 } 8026 8027 _BCM_OAM_ALLOC(member_array, bcm_port_t, 8028 sizeof(bcm_port_t) * member_count, "Trunk info"); 8029 if (NULL == member_array) { 8030 return (BCM_E_MEMORY); 8031 8032 } 8033 8034 /* Get a member of the trunk belonging to this module */ 8035 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 8036 h_data_p->trunk_id, 8037 member_count, member_array, 8038 &local_member_count))) { 8039 if (local_member_count > 0) { 8040 for(i = 0; i < local_member_count; i++) { 8041 rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i], 8042 &module_id, &src_pp_port); 8043 if (BCM_FAILURE(rv)) { 8044 sal_free(member_array); 8045 return (rv); 8046 } 8047 rv = _bcm_kt2_oam_decrement_key_ref_count1(unit, src_pp_port, 8048 h_data_p->dst_pp_port, h_data_p); 8049 if (BCM_FAILURE(rv)) { 8050 sal_free(member_array); 8051 return (rv); 8052 } 8053 } 8054 8055 } 8056 } 8057 sal_free(member_array); 8058 } else { 8059 rv = _bcm_kt2_oam_decrement_key_ref_count1(unit, h_data_p->src_pp_port, 8060 h_data_p->dst_pp_port, h_data_p); 8061 } 8062 return rv; 8063 } 8064 8065 8066 8067 /* 8068 * Function: _bcm_kt2_oam_tpid_decrement_ref_count 8069 * 8070 * Purpose: 8071 * Decrement TPID reference count. 8072 * Parameters: 8073 * unit - (IN) BCM device number 8074 * h_data_p - (IN) Endpoint hash data. 8075 * Retruns: 8076 * BCM_E_XXX 8077 */ 8078 STATIC int 8079 _bcm_kt2_oam_tpid_decrement_ref_count(int unit, _bcm_oam_hash_data_t *h_data_p) 8080 { 8081 int rv = BCM_E_NONE; 8082 uint32 tag_type = 0; 8083 8084 /* If local CCM tx generation was not enabled, then the tpid entries 8085 * would not have been set. So do not try to delete them even though the 8086 * h_data_p->outer/inner/subport_tpid has a non zero value */ 8087 if (!h_data_p->local_tx_enabled) { 8088 return BCM_E_NONE; 8089 } 8090 8091 if (_BCM_OAM_EP_IS_VP_TYPE(h_data_p)) { 8092 if(h_data_p->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) { 8093 tag_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN; 8094 } else if (h_data_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) { 8095 tag_type =_BCM_OAM_DOMAIN_CVLAN; 8096 } else if (h_data_p->vlan > 0) { 8097 tag_type =_BCM_OAM_DOMAIN_SVLAN; 8098 } 8099 } else { 8100 tag_type =h_data_p->oam_domain; 8101 } 8102 8103 /* if S or S+C vlan - set outer tpid index */ 8104 if (((tag_type == _BCM_OAM_DOMAIN_SVLAN) || 8105 (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN)) && 8106 (h_data_p->outer_tpid > 0)) { 8107 if (BCM_SUCCESS(rv)) { 8108 rv = _bcm_kt2_tpid_entry_delete(unit, 8109 h_data_p->outer_tpid_profile_index, 8110 BCM_OAM_TPID_TYPE_OUTER); 8111 if (BCM_FAILURE(rv)) { 8112 LOG_ERROR(BSL_LS_BCM_OAM, 8113 (BSL_META_U(unit, 8114 "OAM Error: L3 entry config failed in Outer TPID " 8115 "decrement ref count"" %s.\n"), bcm_errmsg(rv))); 8116 return (rv); 8117 } 8118 } 8119 } 8120 if (((tag_type == _BCM_OAM_DOMAIN_CVLAN) || 8121 (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN)) && 8122 (h_data_p->inner_tpid > 0)) { 8123 /* C or S+C */ 8124 if (BCM_SUCCESS(rv)) { 8125 rv = _bcm_kt2_tpid_entry_delete(unit, 8126 h_data_p->inner_tpid_profile_index, 8127 BCM_OAM_TPID_TYPE_INNER); 8128 if (BCM_FAILURE(rv)) { 8129 LOG_ERROR(BSL_LS_BCM_OAM, 8130 (BSL_META_U(unit, 8131 "OAM Error: L3 entry config failed in Inner TPID " 8132 "decrement ref count"" %s.\n"), bcm_errmsg(rv))); 8133 return (rv); 8134 } 8135 } 8136 } 8137 if ((BCM_GPORT_IS_SUBPORT_PORT(h_data_p->gport)) && 8138 (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, h_data_p->gport)) && 8139 (h_data_p->subport_tpid > 0)) { 8140 /* CoE port */ 8141 if (BCM_SUCCESS(rv)) { 8142 rv = _bcm_kt2_tpid_entry_delete(unit, 8143 h_data_p->subport_tpid_profile_index, 8144 BCM_OAM_TPID_TYPE_SUBPORT); 8145 if (BCM_FAILURE(rv)) { 8146 LOG_ERROR(BSL_LS_BCM_OAM, 8147 (BSL_META_U(unit, 8148 "OAM Error: L3 entry config failed in Subport TPID " 8149 "decrement ref count"" %s.\n"), bcm_errmsg(rv))); 8150 return (rv); 8151 } 8152 } 8153 } 8154 return rv; 8155 } 8156 8157 /* 8158 * Function: 8159 * _bcm_kt2_oam_endpoint_destroy 8160 * Purpose: 8161 * Delete an endpoint and free all its allocated resources. 8162 * Parameters: 8163 * unit - (IN) BCM device number 8164 * ep_id - (IN) Endpoint ID value. 8165 * Retruns: 8166 * BCM_E_XXX 8167 */ 8168 STATIC int 8169 _bcm_kt2_oam_endpoint_destroy(int unit, 8170 bcm_oam_endpoint_t ep_id) 8171 { 8172 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 8173 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint data. */ 8174 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 8175 bcm_oam_endpoint_info_t ep_info; /* Endpoint information. */ 8176 _bcm_oam_hash_data_t h_data; /* Pointer to endpoint data. */ 8177 int rv; /* Operation return status. */ 8178 #if defined(INCLUDE_BHH) 8179 uint16 reply_len; 8180 bcm_oam_endpoint_t bhh_pool_ep_id; 8181 #endif 8182 8183 /* Lock already taken by the calling routine. */ 8184 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 8185 8186 /* Get the hash data pointer. */ 8187 h_data_p = &oc->oam_hash_data[ep_id]; 8188 if(0 == h_data_p->in_use){ 8189 return BCM_E_NOT_FOUND; 8190 } 8191 8192 rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p); 8193 if (BCM_FAILURE(rv)) { 8194 LOG_ERROR(BSL_LS_BCM_OAM, 8195 (BSL_META_U(unit, 8196 "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) -" 8197 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 8198 return (rv); 8199 } 8200 8201 if(bcmOAMEndpointTypeEthernet == h_data_p->type) 8202 { 8203 8204 if (h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE) { 8205 BCM_IF_ERROR_RETURN 8206 (_bcm_kt2_oam_remote_endpoint_delete(unit, h_data_p)); 8207 8208 } else { 8209 BCM_IF_ERROR_RETURN 8210 (_bcm_kt2_oam_local_endpoint_delete(unit, h_data_p)); 8211 /* decrement TPID ref count */ 8212 BCM_IF_ERROR_RETURN 8213 (_bcm_kt2_oam_tpid_decrement_ref_count(unit, h_data_p)); 8214 } 8215 8216 /* Remove endpoint for group's endpoint list. */ 8217 rv = _bcm_kt2_oam_group_ep_list_remove(unit, h_data_p->group_index, 8218 h_data_p->ep_id); 8219 if (BCM_FAILURE(rv)) { 8220 LOG_ERROR(BSL_LS_BCM_OAM, 8221 (BSL_META_U(unit, 8222 "OAM Error: Remove from group list (EP=%d) -" 8223 " %s.\n"), ep_id, bcm_errmsg(rv))); 8224 return (rv); 8225 } 8226 8227 8228 /* Return ID back to free MEP ID pool.*/ 8229 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->mep_pool, ep_id)); 8230 8231 /* Decrement PORT tab key1/key2 usage ref count */ 8232 if (!(h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE)) { 8233 BCM_IF_ERROR_RETURN 8234 (_bcm_kt2_oam_decrement_key_ref_count(unit, h_data_p)); 8235 } 8236 /* Initialize endpoint info structure. */ 8237 bcm_oam_endpoint_info_t_init(&ep_info); 8238 8239 /* Set up endpoint information for key construction. */ 8240 ep_info.group = h_data_p->group_index; 8241 ep_info.name = h_data_p->name; 8242 ep_info.gport = h_data_p->gport; 8243 ep_info.level = h_data_p->level; 8244 ep_info.vlan = h_data_p->vlan; 8245 ep_info.inner_vlan = h_data_p->inner_vlan; 8246 ep_info.flags = h_data_p->flags; 8247 8248 /* Construct hash key for lookup + delete operation. */ 8249 _bcm_kt2_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key); 8250 8251 /* Remove entry from hash table. */ 8252 BCM_IF_ERROR_RETURN(shr_htb_find(oc->ma_mep_htbl, hash_key, 8253 (shr_htb_data_t *)&h_data, 8254 1)); 8255 8256 /* Clear the hash data memory previously occupied by this endpoint. */ 8257 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 8258 } 8259 /* 8260 * BHH specific 8261 */ 8262 else if (soc_feature(unit, soc_feature_bhh) 8263 && BHH_EP_TYPE(h_data_p)) { 8264 #if defined(INCLUDE_BHH) 8265 8266 if (h_data_p->is_remote) { 8267 /* 8268 * BHH uses same index for local and remote. So, delete always goes through 8269 * local endpoint destory 8270 */ 8271 return (BCM_E_NONE); 8272 } else { 8273 8274 bhh_pool_ep_id = BCM_OAM_BHH_GET_UKERNEL_EP(ep_id); 8275 8276 /* Delete BHH Session in HW. BCM_E_NOT_FOUND is not an error when 8277 switch is re-initializing as entry would have been already 8278 deleted by respective module init. */ 8279 rv = _bcm_kt2_oam_bhh_session_hw_delete(unit, h_data_p); 8280 if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) { 8281 LOG_ERROR(BSL_LS_BCM_OAM, 8282 (BSL_META_U(unit, 8283 "OAM Error: bhh_session_hw_delete failled " 8284 "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv))); 8285 return (rv); 8286 } 8287 8288 if (!(h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) { 8289 /* Send BHH Session Delete message to uC. Error response is not an 8290 during switch re-init as uKernel is reloaded and its state is 8291 cleared before oam init. As such endpoint wont exist during oam init*/ 8292 8293 _bcm_kt2_oam_bhh_msg_send_receive(unit, 8294 MOS_MSG_SUBCLASS_BHH_SESS_DELETE, 8295 (int)bhh_pool_ep_id, 0, 8296 MOS_MSG_SUBCLASS_BHH_SESS_DELETE_REPLY, 8297 &reply_len); 8298 } 8299 if (!BHH_EP_MPLS_SECTION_TYPE(h_data_p)) { 8300 rv = _bcm_kt2_oam_local_endpoint_delete(unit, h_data_p); 8301 if (BCM_FAILURE(rv)) { 8302 LOG_ERROR(BSL_LS_BCM_OAM, 8303 (BSL_META_U(unit, 8304 "OAM Error:BHH local_endpoint_delete failled " 8305 "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv))); 8306 return (rv); 8307 } 8308 } 8309 h_data_p->in_use = 0; 8310 8311 8312 /* Remove endpoint for group's endpoint list. */ 8313 rv = _bcm_kt2_oam_group_ep_list_remove(unit, h_data_p->group_index, 8314 h_data_p->ep_id); 8315 if (BCM_FAILURE(rv)) { 8316 LOG_ERROR(BSL_LS_BCM_OAM, 8317 (BSL_META_U(unit, 8318 "OAM Error: Remove from group list (EP=%d) -" 8319 " %s.\n"), ep_id, bcm_errmsg(rv))); 8320 return (rv); 8321 } 8322 8323 8324 /* Return ID back to free MEP ID pool.*/ 8325 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_id)); 8326 8327 /* Set up endpoint information for key construction. */ 8328 ep_info.group = h_data_p->group_index; 8329 ep_info.name = h_data_p->name; 8330 ep_info.gport = h_data_p->gport; 8331 ep_info.level = h_data_p->level; 8332 ep_info.vlan = h_data_p->vlan; 8333 ep_info.inner_vlan = h_data_p->inner_vlan; 8334 ep_info.flags = h_data_p->flags; 8335 8336 /* Construct hash key for lookup + delete operation. */ 8337 _bcm_kt2_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key); 8338 8339 /* Remove entry from hash table. */ 8340 BCM_IF_ERROR_RETURN(shr_htb_find(oc->ma_mep_htbl, hash_key, 8341 (shr_htb_data_t *)&h_data, 8342 1)); 8343 8344 /* Clear the hash data memory previously occupied by this endpoint. */ 8345 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 8346 8347 } 8348 #else 8349 return (BCM_E_UNAVAIL); 8350 #endif /* INCLUDE_BHH */ 8351 } 8352 else { 8353 return (BCM_E_PARAM); 8354 } 8355 return (BCM_E_NONE); 8356 } 8357 8358 /* 8359 * Function: 8360 * _bcm_kt2_oam_group_endpoints_destroy 8361 * Purpose: 8362 * Delete all endpoints associated with a group and free all 8363 * resources allocated by these endpoints. 8364 * Parameters: 8365 * unit - (IN) BCM device number 8366 * g_info_p - (IN) Pointer to group information 8367 * Retruns: 8368 * BCM_E_XXX 8369 */ 8370 STATIC int 8371 _bcm_kt2_oam_group_endpoints_destroy(int unit, 8372 _bcm_oam_group_data_t *g_info_p) 8373 { 8374 bcm_oam_endpoint_t ep_id; /* Endpoint ID. */ 8375 _bcm_oam_ep_list_t *cur; /* Pointer to endpoint list node. */ 8376 int rv; /* Operation return status. */ 8377 8378 if (NULL == g_info_p) { 8379 return (BCM_E_INTERNAL); 8380 } 8381 8382 /* Get the endpoint list head pointer. */ 8383 cur = *(g_info_p->ep_list); 8384 if (NULL == cur) { 8385 LOG_DEBUG(BSL_LS_BCM_OAM, 8386 (BSL_META_U(unit, 8387 "OAM Info: No endpoints in group.\n"))); 8388 return (BCM_E_NONE); 8389 } 8390 8391 while (NULL != cur) { 8392 ep_id = cur->ep_data_p->ep_id; 8393 8394 LOG_DEBUG(BSL_LS_BCM_OAM, 8395 (BSL_META_U(unit, 8396 "OAM Info: GID=%d EP:%d.\n"), 8397 cur->ep_data_p->group_index, ep_id)); 8398 8399 cur = cur->next; 8400 8401 rv = _bcm_kt2_oam_endpoint_destroy(unit, ep_id); 8402 if (BCM_FAILURE(rv)) { 8403 LOG_ERROR(BSL_LS_BCM_OAM, 8404 (BSL_META_U(unit, 8405 "OAM Error: Endpoint destroy (EP=%d) - " 8406 "%s.\n"), ep_id, bcm_errmsg(rv))); 8407 return (rv); 8408 } 8409 } 8410 8411 return (BCM_E_NONE); 8412 } 8413 8414 /* 8415 * Function: 8416 * _bcm_kt2_oam_trunk_resolve 8417 * Purpose: 8418 * Resolve a trunk value to SGLP, DGLP value and Tx gport. 8419 * Parameters: 8420 * unit - (IN) BCM device number 8421 * trunk_id - (IN) Pointer to trunk id 8422 * trunk_index - (IN) Index in the trunk array to Tx pkts 8423 * src_glp - (IN/OUT) Pointer to source generic logical port value. 8424 * dst_glp - (IN/OUT) Pointer to destination generic logical port value. 8425 * src_pp_port - (IN/OUT) Pointer to source pp port value. 8426 * dst_pp_port - (IN/OUT) Pointer to destination pp port value. 8427 * tx_gport - (OUT) Gport on which PDUs need to be sent 8428 * Retruns: 8429 * BCM_E_XXX 8430 */ 8431 STATIC int 8432 _bcm_kt2_oam_trunk_resolve(int unit, bcm_trunk_t trunk_id, int trunk_index, 8433 bcm_port_t *src_pp_port, bcm_port_t *dst_pp_port, 8434 uint32 *src_glp, uint32 *dst_glp, bcm_gport_t *tx_gport) 8435 { 8436 bcm_port_t port_id = 0; 8437 bcm_port_t port = 0; 8438 bcm_module_t module_id = 0; 8439 int local_id; 8440 bcm_trunk_member_t *member_array = NULL; 8441 int member_count = 0; 8442 int local_member_count = 0; 8443 bcm_trunk_info_t trunk_info; 8444 bcm_trunk_t tid = BCM_TRUNK_INVALID; 8445 int rv = BCM_E_NONE; 8446 8447 8448 if (BCM_TRUNK_INVALID == trunk_id) { 8449 /* Has to be a valid Trunk. */ 8450 return (BCM_E_PARAM); 8451 } 8452 8453 /* Construct Hw SGLP value. */ 8454 _BCM_KT2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 1, 8455 trunk_id, *src_glp); 8456 8457 /* Get a member of the trunk belonging to this module */ 8458 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, trunk_id, 1, 8459 &port_id, 8460 &local_member_count))) { 8461 8462 BCM_IF_ERROR_RETURN(_bcm_kt2_pp_port_to_modport_get(unit, port_id, 8463 &module_id, &port)); 8464 *src_pp_port = port_id; 8465 } 8466 8467 /* Get count of ports in this trunk. */ 8468 BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, trunk_id, NULL, 0, 8469 NULL, &member_count)); 8470 if (0 == member_count) { 8471 /* No members have been added to the trunk group yet */ 8472 return BCM_E_PARAM; 8473 } 8474 8475 _BCM_OAM_ALLOC(member_array, bcm_trunk_member_t, 8476 sizeof(bcm_trunk_member_t) * member_count, "Trunk info"); 8477 if (NULL == member_array) { 8478 return (BCM_E_MEMORY); 8479 } 8480 8481 /* Get Trunk Info for the Trunk ID. */ 8482 rv = bcm_esw_trunk_get(unit, trunk_id, &trunk_info, 8483 member_count, member_array, &member_count); 8484 if (BCM_FAILURE(rv)) { 8485 sal_free(member_array); 8486 return (rv); 8487 } 8488 8489 /* Check if the input trunk_index is valid. */ 8490 if (trunk_index >= member_count) { 8491 sal_free(member_array); 8492 return BCM_E_PARAM; 8493 } 8494 8495 8496 /* Get the Modid and Port value using Trunk Index value. */ 8497 rv = _bcm_esw_gport_resolve(unit, member_array[trunk_index].gport, 8498 &module_id, &port_id, &tid, &local_id); 8499 if (BCM_FAILURE(rv)) { 8500 sal_free(member_array); 8501 return (rv); 8502 } 8503 sal_free(member_array); 8504 8505 /* Construct Hw DGLP value. */ 8506 _BCM_KT2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1, *dst_glp); 8507 8508 /* Get HW PP port */ 8509 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit, module_id, 8510 port_id, dst_pp_port)); 8511 *dst_glp = *src_glp; 8512 *tx_gport = member_array[trunk_index].gport; 8513 8514 return BCM_E_NONE; 8515 8516 } 8517 /* 8518 * Function: 8519 * _bcm_kt2_oam_endpoint_gport_resolve 8520 * Purpose: 8521 * Resolve an endpoint GPORT value to SGLP and DGLP value. 8522 * Parameters: 8523 * unit - (IN) BCM device number 8524 * ep_info_p - (IN/OUT) Pointer to endpoint information. 8525 * src_glp - (IN/OUT) Pointer to source generic logical port value. 8526 * dst_glp - (IN/OUT) Pointer to destination generic logical port value. 8527 * src_pp_port- (IN/OUT) Pointer to source pp port value. 8528 * dst_pp_port- (IN/OUT) Pointer to destination pp port value. 8529 * svp - (IN/OUT) Pointer to VP value 8530 * trunk_id - (IN/OUT) Pointer to trunk id 8531 * tx_gport - (OUT) Gport on which PDUs need to be sent 8532 * Retruns: 8533 * BCM_E_XXX 8534 */ 8535 STATIC int 8536 _bcm_kt2_oam_endpoint_gport_resolve(int unit, bcm_oam_endpoint_info_t *ep_info_p, 8537 uint32 *src_glp, uint32 *dst_glp, 8538 bcm_port_t *src_pp_port, 8539 bcm_port_t *dst_pp_port, uint32 *svp, 8540 bcm_trunk_t *trunk_id, int *is_vp_valid, 8541 bcm_gport_t *tx_gport) 8542 { 8543 bcm_module_t module_id; /* Module ID */ 8544 bcm_port_t port_id; /* Port ID. */ 8545 bcm_port_t port; /* Port ID. */ 8546 int local_id; /* Hardware ID. */ 8547 int tx_enabled = 0; /* CCM Tx enabled. */ 8548 int local_member_count = 0; 8549 int rv = BCM_E_NONE; /* Return status. */ 8550 uint8 glp_valid = 0; /* Logical port valid. */ 8551 int is_local = 0; 8552 uint8 is_port_mep = 0; 8553 8554 is_port_mep = ((ep_info_p->vlan == 0) && (ep_info_p->inner_vlan == 0)); 8555 /* Get Trunk ID or (Modid + Port) value from Gport */ 8556 BCM_IF_ERROR_RETURN 8557 (_bcm_esw_gport_resolve(unit, ep_info_p->gport, &module_id, 8558 &port_id, trunk_id, &local_id)); 8559 8560 /* Set CCM endpoint Tx status only for local endpoints. */ 8561 if (!(ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE)) { 8562 tx_enabled 8563 = (ep_info_p->ccm_period 8564 != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) ? 1 : 0; 8565 } 8566 8567 /* 8568 * If Gport is Trunk type, _bcm_esw_gport_resolve() 8569 * sets trunk_id. Using Trunk ID, get Dst Modid and Port value. 8570 */ 8571 if (BCM_GPORT_IS_TRUNK(ep_info_p->gport)) { 8572 8573 /* 8574 * CCM Tx is enabled on a trunk member port. 8575 * trunk_index value is required to derive the Modid and Port info. 8576 */ 8577 if (1 == tx_enabled && _BCM_OAM_INVALID_INDEX == ep_info_p->trunk_index) { 8578 /* Invalid Trunk member index passed. */ 8579 return (BCM_E_PORT); 8580 } 8581 8582 BCM_IF_ERROR_RETURN( 8583 _bcm_kt2_oam_trunk_resolve(unit, *trunk_id, ep_info_p->trunk_index, 8584 src_pp_port, dst_pp_port, 8585 src_glp, dst_glp, tx_gport)); 8586 glp_valid = 1; 8587 } 8588 8589 /* 8590 * Application can resolve the trunk and pass the desginated 8591 * port as Gport value. Check if the Gport belongs to a trunk. 8592 */ 8593 if ((BCM_TRUNK_INVALID == (*trunk_id)) 8594 && (BCM_GPORT_IS_MODPORT(ep_info_p->gport) 8595 || BCM_GPORT_IS_LOCAL(ep_info_p->gport))) { 8596 8597 /* When Gport is ModPort or Port type, _bcm_esw_gport_resolve() 8598 * returns Modid and Port value. Use these values to make the DGLP 8599 * value. 8600 */ 8601 _BCM_KT2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1, 8602 *dst_glp); 8603 /* get destination PP port */ 8604 BCM_IF_ERROR_RETURN 8605 (_bcm_kt2_modport_to_pp_port_get(unit, module_id, port_id, 8606 dst_pp_port)); 8607 8608 /* Use the Modid, Port value and determine if the port 8609 * belongs to a Trunk. 8610 */ 8611 if (!is_port_mep) { 8612 /* Dont find all other trunk members if it is a port mep */ 8613 rv = bcm_esw_trunk_find(unit, module_id, port_id, trunk_id); 8614 } 8615 if (BCM_SUCCESS(rv) && !is_port_mep) { 8616 /* 8617 * Port is member of a valid trunk. 8618 * Now create the SGLP value from Trunk ID. 8619 */ 8620 /* Get a member of the trunk belonging to this module */ 8621 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, *trunk_id, 1, 8622 &port_id, 8623 &local_member_count))) { 8624 BCM_IF_ERROR_RETURN 8625 (_bcm_kt2_pp_port_to_modport_get(unit, port_id, 8626 &module_id, &port)); 8627 /* Get HW PP port */ 8628 *src_pp_port = port_id; 8629 8630 _BCM_KT2_OAM_MOD_PORT_TO_GLP(unit, module_id, port, 1, 8631 *trunk_id, *src_glp); 8632 *dst_glp = *src_glp; 8633 } else { 8634 *src_pp_port = *dst_pp_port; 8635 } 8636 } else { 8637 /* Port not a member of trunk. DGLP and SGLP are the same. */ 8638 *src_glp = *dst_glp; 8639 *src_pp_port = *dst_pp_port; 8640 } 8641 glp_valid = 1; 8642 *tx_gport = ep_info_p->gport; 8643 } 8644 if ((SOC_GPORT_IS_MIM_PORT(ep_info_p->gport)) || 8645 (SOC_GPORT_IS_MPLS_PORT(ep_info_p->gport)) || 8646 (SOC_GPORT_IS_VLAN_PORT(ep_info_p->gport))) { 8647 *svp = local_id; 8648 8649 if(BCM_TRUNK_INVALID == (*trunk_id)){ 8650 rv = _bcm_esw_modid_is_local(unit, module_id, &is_local); 8651 if(BCM_SUCCESS(rv) && (is_local)) { 8652 _BCM_KT2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, 8653 -1, *dst_glp); 8654 /* get destination PP port */ 8655 BCM_IF_ERROR_RETURN( 8656 _bcm_kt2_modport_to_pp_port_get(unit, 8657 module_id, port_id, 8658 dst_pp_port)); 8659 *src_glp = *dst_glp; 8660 *src_pp_port = *dst_pp_port; 8661 } 8662 *tx_gport = ep_info_p->gport; 8663 } else { 8664 /* 8665 * CCM Tx is enabled on a trunk member port. 8666 * trunk_index value is required to derive the Modid and Port info. 8667 */ 8668 if ((1 == tx_enabled) && 8669 (_BCM_OAM_INVALID_INDEX == ep_info_p->trunk_index)) { 8670 /* Invalid Trunk member index passed. */ 8671 return (BCM_E_PORT); 8672 } 8673 BCM_IF_ERROR_RETURN( 8674 _bcm_kt2_oam_trunk_resolve(unit, *trunk_id, ep_info_p->trunk_index, 8675 src_pp_port, dst_pp_port, 8676 src_glp, dst_glp, tx_gport)); 8677 } 8678 glp_valid = 1; 8679 *is_vp_valid = 1; 8680 } 8681 8682 /* LinkPhy/CoE case */ 8683 if ((BCM_GPORT_IS_SUBPORT_PORT(ep_info_p->gport))) { 8684 if ((_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, ep_info_p->gport)) || 8685 (_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, ep_info_p->gport))) { 8686 BCM_IF_ERROR_RETURN 8687 (_bcm_kt2_modport_to_pp_port_get(unit, module_id, port_id, 8688 dst_pp_port)); 8689 *src_pp_port = *dst_pp_port; 8690 _BCM_KT2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1, 8691 *dst_glp); 8692 /* Use the Modid, Port value and determine if the port 8693 * belongs to a Trunk. 8694 */ 8695 if (!is_port_mep) { 8696 rv = bcm_esw_trunk_find(unit, module_id, port_id, trunk_id); 8697 } 8698 if (BCM_SUCCESS(rv) && !is_port_mep) { 8699 /* 8700 * Port is member of a valid trunk. 8701 * Now create the SGLP value from Trunk ID. 8702 */ 8703 /* Get a member of the trunk belonging to this module */ 8704 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 8705 *trunk_id, 1, 8706 &port_id, 8707 &local_member_count))) { 8708 BCM_IF_ERROR_RETURN 8709 (_bcm_kt2_pp_port_to_modport_get(unit, port_id, 8710 &module_id, &port)); 8711 /* Get HW PP port */ 8712 *src_pp_port = port_id; 8713 8714 _BCM_KT2_OAM_MOD_PORT_TO_GLP(unit, module_id, port, 1, 8715 *trunk_id, *src_glp); 8716 *dst_glp = *src_glp; 8717 } 8718 } else { 8719 *src_glp = *dst_glp; 8720 } 8721 glp_valid = 1; 8722 BCM_GPORT_MODPORT_SET(*tx_gport, module_id, port_id); 8723 } 8724 } 8725 8726 /* 8727 * At this point, both src_glp and dst_glp should be valid. 8728 * Gport types other than TRUNK, MODPORT or LOCAL are not valid. 8729 */ 8730 if (0 == glp_valid) { 8731 return (BCM_E_PORT); 8732 } 8733 return (BCM_E_NONE); 8734 } 8735 8736 /* 8737 * Function: 8738 * _bcm_kt2_oam_mepid_validate 8739 * Purpose: 8740 * Validate an endpoint MEP id. 8741 * Parameters: 8742 * unit - (IN) BCM device number 8743 * ep_info_p - (IN) Pointer to endpoint information. 8744 * Retruns: 8745 * BCM_E_XXX 8746 */ 8747 STATIC int 8748 _bcm_kt2_oam_mepid_validate(int unit, 8749 bcm_oam_endpoint_info_t *ep_info_p) 8750 { 8751 _bcm_oam_control_t *oc; 8752 _bcm_oam_group_data_t *group_p; /* Pointer to group list. */ 8753 _bcm_oam_ep_list_t *cur; /* Current head node pointer. */ 8754 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 8755 8756 /* Get OAM control structure. */ 8757 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 8758 8759 /* Get the group memory pointer. */ 8760 group_p = &oc->group_info[ep_info_p->group]; 8761 8762 if (1 != group_p->in_use) { 8763 return BCM_E_NONE; 8764 } 8765 cur = *group_p->ep_list; 8766 8767 /* Traverse the list and delete the matching node. */ 8768 while (NULL != cur) { 8769 h_data_p = cur->ep_data_p; 8770 if (NULL == h_data_p) { 8771 LOG_ERROR(BSL_LS_BCM_OAM, 8772 (BSL_META_U(unit, 8773 "OAM Error: Hash data is empty\n"))); 8774 return (BCM_E_INTERNAL); 8775 } 8776 if (ep_info_p->name == h_data_p->name) { 8777 if (((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE) && 8778 (cur->ep_data_p->ep_id == ep_info_p->id)) || 8779 ((h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE) != 8780 (ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE))) { 8781 } else { 8782 return BCM_E_PARAM; 8783 } 8784 } 8785 cur = cur->next; 8786 } 8787 return (BCM_E_NONE); 8788 } 8789 8790 /* 8791 * Function: 8792 * _bcm_kt2_oam_endpoint_params_validate 8793 * Purpose: 8794 * Validate an endpoint parameters. 8795 * Parameters: 8796 * unit - (IN) BCM device number 8797 * oc - (IN) Pointer to OAM control structure. 8798 * hash_key - (IN) Pointer to endpoint hash key value. 8799 * ep_info_p - (IN) Pointer to endpoint information. 8800 * Retruns: 8801 * BCM_E_XXX 8802 */ 8803 STATIC int 8804 _bcm_kt2_oam_endpoint_params_validate(int unit, 8805 _bcm_oam_control_t *oc, 8806 _bcm_oam_hash_key_t *hash_key, 8807 bcm_oam_endpoint_info_t *ep_info_p) 8808 { 8809 int rv; /* Operation return status. */ 8810 _bcm_oam_hash_data_t h_stored_data; 8811 int remote = 0; 8812 8813 8814 /* Get MEP remote endpoint status. */ 8815 remote = (ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0; 8816 8817 LOG_DEBUG(BSL_LS_BCM_OAM, 8818 (BSL_META_U(unit, 8819 "OAM Info: " 8820 "_bcm_kt2_oam_endpoint_params_validate.\n"))); 8821 8822 /* Endpoint must be 802.1ag/Ethernet OAM type. */ 8823 if ((bcmOAMEndpointTypeEthernet != ep_info_p->type) 8824 #if defined(INCLUDE_BHH) 8825 && /* BHH/Y.1731 OAM type */ 8826 (!BHH_EP_TYPE(ep_info_p)) 8827 #endif /* INCLUDE_BHH */ 8828 ) 8829 { 8830 /* Other OAM types are not supported, return error. */ 8831 return BCM_E_UNAVAIL; 8832 } 8833 8834 /* Supported MDL level is 0 - 7. */ 8835 if ((!remote) && 8836 ((ep_info_p->level < 0) || (ep_info_p->level > _BCM_OAM_EP_LEVEL_MAX))) { 8837 LOG_ERROR(BSL_LS_BCM_OAM, 8838 (BSL_META_U(unit, 8839 "OAM Error: EP Level should be in the range(0-%d).\n"), 8840 _BCM_OAM_EP_LEVEL_MAX)); 8841 return (BCM_E_PARAM); 8842 } 8843 8844 /* Supported MEPID EP Name range is 1 - 8191, Skipping range check for MIP */ 8845 if (((ep_info_p->name < _BCM_OAM_EP_NAME_MIN) 8846 || (ep_info_p->name > _BCM_OAM_EP_NAME_MAX)) && 8847 !(ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE)) { 8848 LOG_ERROR(BSL_LS_BCM_OAM, 8849 (BSL_META_U(unit, 8850 "OAM Error: MEP Name should be in the range(%d-%d).\n"), 8851 _BCM_OAM_EP_NAME_MIN, _BCM_OAM_EP_NAME_MAX)); 8852 return (BCM_E_PARAM); 8853 } 8854 8855 /* 8856 * Check and return error if invalid flag bits are set for remote 8857 * endpoint. 8858 */ 8859 if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE) 8860 && (ep_info_p->flags & _BCM_OAM_REMOTE_EP_INVALID_FLAGS_MASK)) { 8861 8862 return (BCM_E_PARAM); 8863 8864 } 8865 8866 /* 8867 * Check and return error if MEPID is not unique within the group 8868 */ 8869 if(_bcm_kt2_oam_mepid_validate(unit, ep_info_p)) { 8870 LOG_ERROR(BSL_LS_BCM_OAM, 8871 (BSL_META_U(unit, 8872 "OAM Error: MEPID:%x passed is not unique in group %x\n"), 8873 ep_info_p->name, ep_info_p->group)); 8874 8875 return (BCM_E_EXISTS); 8876 } 8877 8878 /* For replace operation, endpoint ID is required. */ 8879 if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE) 8880 && !(ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID)) { 8881 8882 return (BCM_E_PARAM); 8883 8884 } 8885 /* Port based MEP is supported only for down MEP */ 8886 if ((0 == ep_info_p->vlan) && (0 == ep_info_p->inner_vlan) && 8887 (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) && (!remote)) { 8888 return (BCM_E_PARAM); 8889 } 8890 8891 /* If it is a Port + CVlan based MEP and the 8892 * CVlan (inner_vlan) is 0, return E_PARAM 8893 */ 8894 if ((0 == ep_info_p->inner_vlan) && 8895 (ep_info_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN)) { 8896 return (BCM_E_PARAM); 8897 } 8898 8899 /* If it is a Port + S + CVlan based MEP and one of SVlan(vlan) 8900 * or CVlan (inner_vlan) is 0, return E_PARAM 8901 */ 8902 if (((0 == ep_info_p->inner_vlan) || (0 == ep_info_p->vlan)) && 8903 (ep_info_p->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN)) { 8904 return (BCM_E_PARAM); 8905 } 8906 8907 /* Validate endpoint index value. */ 8908 if (ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID) { 8909 _BCM_OAM_EP_INDEX_VALIDATE(ep_info_p->id); 8910 } 8911 8912 /* MIP's are not created with non-zero ccm period */ 8913 if ((ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) && 8914 (ep_info_p->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED)) { 8915 return (BCM_E_PARAM); 8916 } 8917 8918 /* Validate endpoint group id. */ 8919 _BCM_OAM_GROUP_INDEX_VALIDATE(ep_info_p->group); 8920 8921 rv = shr_idxres_list_elem_state(oc->group_pool, ep_info_p->group); 8922 if (BCM_E_EXISTS != rv) { 8923 LOG_ERROR(BSL_LS_BCM_OAM, 8924 (BSL_META_U(unit, 8925 "OAM Error: Group (GID:%d) does not exist.\n"), 8926 ep_info_p->group)); 8927 return (BCM_E_PARAM); 8928 } 8929 8930 if(soc_feature(unit, soc_feature_bhh)) { 8931 #if defined(INCLUDE_BHH) 8932 /* 8933 * BHH can have multiple LSPs/endpoint on same port/MDL 8934 * BHH does not have h/w support. So, return here 8935 */ 8936 if ((bcmOAMEndpointTypeBHHMPLS == ep_info_p->type) || 8937 (bcmOAMEndpointTypeBHHMPLSVccv == ep_info_p->type)) { 8938 return (BCM_E_NONE); 8939 } 8940 #endif 8941 } 8942 8943 #if defined(KEY_PRINT) 8944 _bcm_oam_hash_key_print(hash_key); 8945 #endif 8946 8947 /* 8948 * Lookup using hash key value. 8949 * Last param value '0' specifies keep the match entry. 8950 * Value '1' would mean remove the entry from the table. 8951 * Matched Params: 8952 * Group Name + Group ID + Endpoint Name + VLAN + MDL + Gport. 8953 */ 8954 rv = shr_htb_find(oc->ma_mep_htbl, *hash_key, 8955 (shr_htb_data_t *)&h_stored_data, 0); 8956 if (BCM_SUCCESS(rv) 8957 && !(ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE)) { 8958 8959 LOG_ERROR(BSL_LS_BCM_OAM, 8960 (BSL_META_U(unit, 8961 "OAM Error: Endpoint ID=%d %s.\n"), 8962 ep_info_p->id, bcm_errmsg(BCM_E_EXISTS))); 8963 8964 /* Endpoint must not be in use expect for Replace operation. */ 8965 return (BCM_E_EXISTS); 8966 8967 } else { 8968 8969 LOG_DEBUG(BSL_LS_BCM_OAM, 8970 (BSL_META_U(unit, 8971 "OAM Info: Endpoint ID=%d Available. %s.\n"), 8972 ep_info_p->id, bcm_errmsg(rv))); 8973 8974 } 8975 8976 8977 8978 return (BCM_E_NONE); 8979 } 8980 8981 typedef struct _bcm_oam_flexible_oam_domain_vlan_ctrl_type1_s { 8982 uint32 start_index; 8983 uint32 end_index; 8984 soc_field_t tag_source; 8985 soc_field_t data_processing; 8986 soc_field_t oam_processing; 8987 } _bcm_oam_flexible_oam_domain_c_vlan_ctrl_type1_t; 8988 8989 typedef struct _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_s { 8990 uint32 start_index; 8991 uint32 no_entries; 8992 uint32 increment; 8993 soc_field_t tag_source_1; 8994 soc_field_t tag_source_2; 8995 soc_field_t data_processing; 8996 soc_field_t oam_processing; 8997 } _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t; 8998 8999 /* 9000 * Function: 9001 * _bcm_kt2_oam_ing_flexible_oam_domain_ctrl_set 9002 * Purpose: 9003 * Set the default values for ingress flexible oam domain control 9004 * Parameters: 9005 * unit - (IN) BCM device number 9006 * Retruns: 9007 * BCM_E_XXX 9008 * Index to the ing flexible domain control table is 9009 * index[5] = pars_inner_pri_tagged; 9010 * index[4] = pars_inner_tagged; 9011 * index[3] = pars_outer_tagged; 9012 * index[2] = vxlt_inner_tagged; 9013 * index[1] = vxlt_outer_tagged; 9014 * index[0] = svp_valid; 9015 */ 9016 STATIC int 9017 _bcm_kt2_oam_ing_flexible_oam_domain_ctrl_set(int unit) 9018 { 9019 int rv = BCM_E_NONE; 9020 ing_oam_flexible_domain_control_entry_t *ent_buf; 9021 ing_oam_flexible_domain_control_entry_t *ent; 9022 int max_index = 0; 9023 int index = 0; 9024 int end_index = 0; 9025 int loop_index = 0; 9026 int entry_mem_size = 0; 9027 int entry_index = 0; 9028 uint32 action_set = 1; 9029 9030 9031 _bcm_oam_flexible_oam_domain_c_vlan_ctrl_type1_t c_vlan_ctrl_info[] = { 9032 /* Set values for C VLAN MEP pre-VXLT actions */ 9033 /* Action for incoming untagged packets */ 9034 { 4, 7, CVLAN_DOMAIN_PRE_VXLT_CVLAN_TAG_SOURCEf, 9035 CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 9036 CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf }, 9037 /* Action for incoming single inner tagged but not 9038 priority tagged packets */ 9039 { 16, 23, CVLAN_DOMAIN_PRE_VXLT_CVLAN_TAG_SOURCEf, 9040 CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 9041 CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf }, 9042 /* Action for incoming single inner priority tagged packets */ 9043 { 52, 55, CVLAN_DOMAIN_PRE_VXLT_CVLAN_TAG_SOURCEf, 9044 CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 9045 CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf }, 9046 /* Set values for C VLAN MEP post-VXLT actions */ 9047 /* Action for incoming untagged packets */ 9048 { 4, 7, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 9049 CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 9050 CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf }, 9051 /* Action for incoming single inner tagged but not 9052 priority tagged packets */ 9053 { 20, 23, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 9054 CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 9055 CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf }, 9056 /* Action for incoming single inner priority tagged packets */ 9057 { 52, 55, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 9058 CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 9059 CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf }, 9060 { 0 } /* table terminator */ 9061 }; 9062 9063 _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t s_vlan_ctrl_info[] = { 9064 9065 /* Set values for S VLAN MEP actions */ 9066 /* Action for incoming packet with single outer tagged after 9067 VXLT */ 9068 { 2, 2, 8, SVLAN_DOMAIN_SVLAN_TAG_SOURCEf, 0, 9069 SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 9070 SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf}, 9071 /* Action for incoming packet with double tag after VXLT */ 9072 { 6, 2, 8, SVLAN_DOMAIN_SVLAN_TAG_SOURCEf, 0, 9073 SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 9074 SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 9075 9076 /* Set values for S+C VLAN MEP actions */ 9077 /* Action for incoming packet with double tag after VXLT */ 9078 { 6, 2, 8, SVLAN_CVLAN_DOMAIN_SVLAN_TAG_SOURCEf, 9079 SVLAN_CVLAN_DOMAIN_CVLAN_TAG_SOURCEf, 9080 SVLAN_CVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 9081 SVLAN_CVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 9082 { 6, 2, 8, 0, 0, 9083 SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 9084 SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 9085 { 6, 2, 8, 0, 0, 9086 CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf, 9087 CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf }, 9088 { 6, 2, 8, 0, 9089 0, 9090 CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf, 9091 CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf }, 9092 { 0, 0 } /* table terminator */ 9093 }; 9094 9095 _bcm_oam_flexible_oam_domain_c_vlan_ctrl_type1_t *ctrl_info; 9096 _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t *s_ctrl_info; 9097 9098 9099 /* Read the table entries into the buffer. */ 9100 max_index = soc_mem_index_max(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm); 9101 9102 entry_mem_size = sizeof(ing_oam_flexible_domain_control_entry_t); 9103 /* Allocate buffer to store the DMAed table entries. */ 9104 ent_buf = soc_cm_salloc(unit, entry_mem_size * (max_index + 1), 9105 "OAM flexible domain control table entry buffer"); 9106 if (NULL == ent_buf) { 9107 return (BCM_E_MEMORY); 9108 } 9109 /* Initialize the entry buffer. */ 9110 sal_memset(ent_buf, 0, sizeof(entry_mem_size) * (max_index + 1)); 9111 9112 /* Set action for C vlan */ 9113 for (index = 0; ;index++) { 9114 ctrl_info = &c_vlan_ctrl_info[index]; 9115 if(ctrl_info->start_index == 0) { 9116 /* End of table */ 9117 break; 9118 } 9119 for (entry_index = ctrl_info->start_index; 9120 entry_index <= ctrl_info->end_index; entry_index++) { 9121 ent = soc_mem_table_idx_to_pointer 9122 (unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9123 ing_oam_flexible_domain_control_entry_t *, 9124 ent_buf, entry_index); 9125 9126 soc_mem_field_set(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9127 (uint32 *)ent, ctrl_info->tag_source, &action_set); 9128 soc_mem_field_set(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9129 (uint32 *)ent, ctrl_info->data_processing, &action_set); 9130 soc_mem_field_set(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9131 (uint32 *)ent, ctrl_info->oam_processing, &action_set); 9132 } 9133 } 9134 /* Set action for S and S+C vlan */ 9135 for (index = 0; ;index++) { 9136 s_ctrl_info = &s_vlan_ctrl_info[index]; 9137 if(s_ctrl_info->start_index == 0) { 9138 /* End of table */ 9139 break; 9140 } 9141 entry_index = s_ctrl_info->start_index; 9142 loop_index = s_ctrl_info->start_index; 9143 end_index = entry_index + s_ctrl_info->no_entries; 9144 while (entry_index <= max_index) { 9145 for (; loop_index < end_index; loop_index++) { 9146 ent = soc_mem_table_idx_to_pointer(unit, 9147 ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9148 ing_oam_flexible_domain_control_entry_t *, 9149 ent_buf, loop_index); 9150 if (s_ctrl_info->tag_source_1 != 0) { 9151 soc_mem_field_set(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9152 (uint32 *)ent, s_ctrl_info->tag_source_1, &action_set); 9153 } 9154 if (s_ctrl_info->tag_source_2 != 0) { 9155 soc_mem_field_set(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9156 (uint32 *)ent, s_ctrl_info->tag_source_2, &action_set); 9157 } 9158 soc_mem_field_set(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9159 (uint32 *)ent, s_ctrl_info->data_processing, &action_set); 9160 soc_mem_field_set(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9161 (uint32 *)ent, s_ctrl_info->oam_processing, &action_set); 9162 } 9163 entry_index += s_ctrl_info->increment; 9164 loop_index = entry_index; 9165 end_index = (entry_index + s_ctrl_info->no_entries); 9166 } 9167 } 9168 9169 rv = soc_mem_write_range(unit, ING_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9170 MEM_BLOCK_ALL, 0, max_index, ent_buf); 9171 if (BCM_FAILURE(rv)) { 9172 if (ent_buf) { 9173 soc_cm_sfree(unit, ent_buf); 9174 } 9175 return rv; 9176 } 9177 if (ent_buf) { 9178 soc_cm_sfree(unit, ent_buf); 9179 } 9180 9181 return rv; 9182 } 9183 /* 9184 * Function: 9185 * _bcm_kt2_oam_egr_flexible_oam_domain_ctrl_set 9186 * Purpose: 9187 * Set the default values for egress flexible oam domain control 9188 * Parameters: 9189 * unit - (IN) BCM device number 9190 * Retruns: 9191 * BCM_E_XXX 9192 */ 9193 9194 STATIC int 9195 _bcm_kt2_oam_egr_flexible_oam_domain_ctrl_set(int unit) 9196 { 9197 int rv = BCM_E_NONE; 9198 egr_oam_flexible_domain_control_entry_t *egr_ent_buf; 9199 egr_oam_flexible_domain_control_entry_t *ent; 9200 int max_index = 0; 9201 int index = 0; 9202 int end_index = 0; 9203 int loop_index = 0; 9204 int entry_mem_size = 0; 9205 int entry_index = 0; 9206 uint32 action_set = 1; 9207 9208 _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t vlan_ctrl_info[] = { 9209 9210 /* CVLAN MEP before VXLT */ 9211 { 16, 2, 4, 0, 0, 9212 CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 9213 CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf }, 9214 /* CVLAN MEP after VXLT */ 9215 { 4, 2, 8, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 0, 9216 CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 9217 CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf }, 9218 /* SVLAN MEP */ 9219 { 8, 8, 16, 0, 0, 9220 SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 9221 SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 9222 /* S+C VLAN MEP */ 9223 { 14, 2, 18, SVLAN_CVLAN_DOMAIN_CVLAN_TAG_SOURCEf, 0, 9224 SVLAN_CVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 9225 SVLAN_CVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 9226 9227 { 24, 8, 8, 0, 0, 9228 SVLAN_CVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 9229 SVLAN_CVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 9230 { 24, 8, 8, 0, 0, 9231 CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 9232 CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf }, 9233 { 26, 2, 2, 0, 0, 9234 SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 9235 SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 9236 { 30, 2, 2, 0, 0, 9237 SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 9238 SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 9239 { 30, 2, 2, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 0, 9240 CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 9241 CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf }, 9242 { 0, 0 } /* table terminator */ 9243 }; 9244 9245 _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t *ctrl_info; 9246 9247 9248 /* Read the table entries into the buffer. */ 9249 max_index = soc_mem_index_max(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm); 9250 9251 entry_mem_size = sizeof(egr_oam_flexible_domain_control_entry_t); 9252 /* Allocate buffer to store the DMAed table entries. */ 9253 egr_ent_buf = soc_cm_salloc(unit, entry_mem_size * (max_index + 1), 9254 "OAM flexible domain control table entry buffer"); 9255 if (NULL == egr_ent_buf) { 9256 return (BCM_E_MEMORY); 9257 } 9258 /* Initialize the entry buffer. */ 9259 sal_memset(egr_ent_buf, 0, sizeof(entry_mem_size) * (max_index + 1)); 9260 9261 /* Set action for C, S and S+C vlan */ 9262 for (index = 0; ;index++) { 9263 ctrl_info = &vlan_ctrl_info[index]; 9264 if(ctrl_info->start_index == 0) { 9265 /* End of table */ 9266 break; 9267 } 9268 entry_index = ctrl_info->start_index; 9269 loop_index = ctrl_info->start_index; 9270 end_index = entry_index + ctrl_info->no_entries; 9271 while (entry_index <= max_index) { 9272 for (; loop_index < end_index; loop_index++) { 9273 ent = soc_mem_table_idx_to_pointer 9274 (unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9275 egr_oam_flexible_domain_control_entry_t *, 9276 egr_ent_buf, loop_index); 9277 9278 if (ctrl_info->tag_source_1 != 0) { 9279 soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9280 (uint32 *)ent, ctrl_info->tag_source_1, &action_set); 9281 } 9282 if (ctrl_info->tag_source_2 != 0) { 9283 soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9284 (uint32 *)ent, ctrl_info->tag_source_2, &action_set); 9285 } 9286 soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9287 (uint32 *)ent, ctrl_info->data_processing, &action_set); 9288 soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9289 (uint32 *)ent, ctrl_info->oam_processing, &action_set); 9290 } 9291 entry_index += ctrl_info->increment; 9292 loop_index = entry_index; 9293 end_index = (entry_index + ctrl_info->no_entries); 9294 } 9295 } 9296 9297 rv = soc_mem_write_range(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 9298 MEM_BLOCK_ALL, 0, max_index, egr_ent_buf); 9299 if (BCM_FAILURE(rv)) { 9300 if (egr_ent_buf) { 9301 soc_cm_sfree(unit, egr_ent_buf); 9302 } 9303 return rv; 9304 } 9305 if (egr_ent_buf) { 9306 soc_cm_sfree(unit, egr_ent_buf); 9307 } 9308 return rv; 9309 } 9310 9311 9312 /* 9313 * Function: 9314 * _bcm_kt2_oam_flexible_oam_domain_ctrl_set 9315 * Purpose: 9316 * Set the default values for flexible oam domain control 9317 * Parameters: 9318 * unit - (IN) BCM device number 9319 * Retruns: 9320 * BCM_E_XXX 9321 */ 9322 STATIC int 9323 _bcm_kt2_oam_flexible_oam_domain_ctrl_set(int unit) 9324 { 9325 int rv = BCM_E_NONE; 9326 /* Set ingress flexible domain control */ 9327 rv = _bcm_kt2_oam_ing_flexible_oam_domain_ctrl_set(unit); 9328 if (BCM_FAILURE(rv)) { 9329 return (rv); 9330 } 9331 9332 /* Set egress flexible domain control */ 9333 rv = _bcm_kt2_oam_egr_flexible_oam_domain_ctrl_set(unit); 9334 if (BCM_FAILURE(rv)) { 9335 return (rv); 9336 } 9337 return rv; 9338 } 9339 9340 9341 typedef struct _bcm_oam_ing_flexible_drop_ctrl_s { 9342 soc_reg_t drop_ctrl_reg; 9343 uint32 vfp_drop_ctrl; 9344 uint32 olp_drop_ctrl; 9345 uint32 spst_drop_ctrl; 9346 uint32 tag_drop_ctrl; 9347 uint32 cvlan_bfr_vxlt_drop_ctrl; 9348 uint32 cvlan_after_vxlt_drop_ctrl; 9349 uint32 e2e_drop_ctrl; 9350 uint32 vlan_drop_ctrl; 9351 uint32 disc_drop_ctrl; 9352 } _bcm_oam_ing_flexible_drop_ctrl_t; 9353 9354 typedef struct _bcm_oam_egr_flexible_drop_ctrl_s { 9355 soc_reg_t drop_ctrl_reg; 9356 uint32 egr_drop_ctrl; 9357 uint32 evxlt_payload_drop_ctrl; 9358 uint32 cvlan_after_vxlt_drop_ctrl; 9359 uint32 cvlan_before_vxlt_drop_ctrl; 9360 } _bcm_oam_egr_flexible_drop_ctrl_t; 9361 9362 /* 9363 * Function: 9364 * _bcm_kt2_oam_ing_flexible_drop_ctrl_set 9365 * Purpose: 9366 * Set the default values for flexible ingress drop control 9367 * Parameters: 9368 * unit - (IN) BCM device number 9369 * Retruns: 9370 * BCM_E_XXX 9371 */ 9372 STATIC int 9373 _bcm_kt2_oam_ing_flexible_drop_ctrl_set(int unit) 9374 { 9375 uint32 en_rval = 0; 9376 int index = 0; 9377 _bcm_oam_ing_flexible_drop_ctrl_t *flex_drop_info; 9378 _bcm_oam_ing_flexible_drop_ctrl_t ing_flex_drop[] = { 9379 { OAM_PORT_INTERFACE_DROP_CONTROLr, 0, 1, 0, 0, 0, 0, 1, 0, 0xe01c1 }, 9380 { OAM_C_INTERFACE_DROP_CONTROLr, 1, 1, 0, 0, 0, 1, 1, 0, 0xe01fd }, 9381 { OAM_S_INTERFACE_DROP_CONTROLr, 1, 1, 0, 1, 1, 1, 1, 5, 0xe01fd }, 9382 { OAM_S_C_INTERFACE_DROP_CONTROLr, 1, 1, 1, 1, 1, 1, 1, 7, 0xe01fd }, 9383 { OAM_SVP_INTERFACE_DROP_CONTROLr, 1, 1, 1, 1, 1, 1, 1, 7, 0xe01fd }, 9384 { 0 }, /* End of table */ 9385 }; 9386 9387 for (index = 0; ;index++) { 9388 flex_drop_info = &ing_flex_drop[index]; 9389 if(flex_drop_info->drop_ctrl_reg == 0) { 9390 /* End of table */ 9391 break; 9392 } 9393 9394 SOC_IF_ERROR_RETURN(soc_reg32_get(unit, flex_drop_info->drop_ctrl_reg, 9395 REG_PORT_ANY, 0, &en_rval)); 9396 soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 9397 &en_rval, VFP_DROP_CTRLf, 9398 flex_drop_info->vfp_drop_ctrl); 9399 soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 9400 &en_rval, OLP_ERROR_DROP_CTRLf, 9401 flex_drop_info->olp_drop_ctrl); 9402 soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 9403 &en_rval, SPST_NOT_IN_FORWARDING_STATE_DROP_CTRLf, 9404 flex_drop_info->spst_drop_ctrl); 9405 soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 9406 &en_rval, DISCARD_TAG_UNTAG_CTRLf, 9407 flex_drop_info->tag_drop_ctrl); 9408 soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 9409 &en_rval, 9410 CVLAN_INTF_BEFORE_VXLT_VXLT_MISS_DROP_CTRLf, 9411 flex_drop_info->cvlan_bfr_vxlt_drop_ctrl); 9412 soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 9413 &en_rval, 9414 CVLAN_INTF_AFTER_VXLT_VXLT_MISS_DROP_CTRLf, 9415 flex_drop_info->cvlan_after_vxlt_drop_ctrl); 9416 soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 9417 &en_rval, ERRORED_E2E_PKT_DROP_CTRLf, 9418 flex_drop_info->e2e_drop_ctrl); 9419 soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 9420 &en_rval, VLAN_DROP_VECTOR_CTRLf, 9421 flex_drop_info->vlan_drop_ctrl); 9422 soc_reg_field_set(unit, flex_drop_info->drop_ctrl_reg, 9423 &en_rval, DISC_DROP_VECTOR_CTRLf, 9424 flex_drop_info->disc_drop_ctrl); 9425 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, flex_drop_info->drop_ctrl_reg, 9426 REG_PORT_ANY, 0, en_rval)); 9427 } 9428 return (BCM_E_NONE); 9429 } 9430 9431 /* 9432 * Function: 9433 * _bcm_kt2_oam_egr_flexible_drop_ctrl_set 9434 * Purpose: 9435 * Set the default values for flexible egress drop control 9436 * Parameters: 9437 * unit - (IN) BCM device number 9438 * Retruns: 9439 * BCM_E_XXX 9440 */ 9441 STATIC int 9442 _bcm_kt2_oam_egr_flexible_drop_ctrl_set(int unit) 9443 { 9444 uint64 en_rval, set_val; 9445 int index = 0; 9446 9447 _bcm_oam_egr_flexible_drop_ctrl_t *flex_drop_info; 9448 _bcm_oam_egr_flexible_drop_ctrl_t egr_flex_drop[] = { 9449 { EGR_OAM_PORT_INTERFACE_DROP_CONTROL_64r, 0x1e0787d, 1, 1, 1 }, 9450 { EGR_OAM_C_INTERFACE_DROP_CONTROL_64r, 0x1e0787c, 1, 1, 0 }, 9451 { EGR_OAM_S_INTERFACE_DROP_CONTROL_64r, 0x1e06848, 1, 0, 0 }, 9452 { EGR_OAM_S_C_INTERFACE_DROP_CONTROL_64r, 0x1e06048, 1, 0, 0 }, 9453 { EGR_OAM_DVP_INTERFACE_DROP_CONTROL_64r, 0x1e06048, 1, 0, 0 }, 9454 { 0 }, /* End of table */ 9455 }; 9456 9457 COMPILER_64_ZERO(en_rval); 9458 9459 for (index = 0; ;index++) { 9460 flex_drop_info = &egr_flex_drop[index]; 9461 if(flex_drop_info->drop_ctrl_reg == 0) { 9462 /* End of table */ 9463 break; 9464 } 9465 9466 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, flex_drop_info->drop_ctrl_reg, 9467 REG_PORT_ANY, 0, &en_rval)); 9468 9469 COMPILER_64_SET(set_val, 0, flex_drop_info->egr_drop_ctrl); 9470 9471 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 9472 &en_rval, EGR_DROP_VECTOR_CTRLf, 9473 set_val); 9474 9475 COMPILER_64_SET(set_val, 0, flex_drop_info->evxlt_payload_drop_ctrl); 9476 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 9477 &en_rval, 9478 EVXLT_APPLIED_TO_PAYLOAD_VXLT_MISS_DROP_CTRLf, 9479 set_val); 9480 9481 COMPILER_64_SET(set_val, 0, flex_drop_info->cvlan_after_vxlt_drop_ctrl); 9482 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 9483 &en_rval, 9484 EVXLT_APPLIED_TO_OUTER_L2_CVLAN_INTF_AFTER_VXLT_VXLT_MISS_DROP_CTRLf, 9485 set_val); 9486 9487 COMPILER_64_SET(set_val, 0, flex_drop_info->cvlan_before_vxlt_drop_ctrl); 9488 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 9489 &en_rval, 9490 EVXLT_APPLIED_TO_OUTER_L2_CVLAN_INTF_BEFORE_VXLT_VXLT_MISS_DROP_CTRLf, 9491 set_val); 9492 9493 SOC_IF_ERROR_RETURN(soc_reg64_set(unit, flex_drop_info->drop_ctrl_reg, 9494 REG_PORT_ANY, 0, en_rval)); 9495 } 9496 return (BCM_E_NONE); 9497 } 9498 9499 /* 9500 * Function: 9501 * _bcm_kt2_oam_flexible_drop_ctrl_set 9502 * Purpose: 9503 * Set the default values for flexible ingress and egress drop control 9504 * Parameters: 9505 * unit - (IN) BCM device number 9506 * Retruns: 9507 * BCM_E_XXX 9508 */ 9509 STATIC int 9510 _bcm_kt2_oam_flexible_drop_ctrl_set(int unit) 9511 { 9512 int rv = BCM_E_NONE; 9513 /* Set ingress flexible drop control */ 9514 rv = _bcm_kt2_oam_ing_flexible_drop_ctrl_set(unit); 9515 if (BCM_FAILURE(rv)) { 9516 return (rv); 9517 } 9518 9519 /* Set egress flexible drop control */ 9520 rv = _bcm_kt2_oam_egr_flexible_drop_ctrl_set(unit); 9521 if (BCM_FAILURE(rv)) { 9522 return (rv); 9523 } 9524 return rv; 9525 } 9526 9527 /* 9528 * Function: 9529 * _bcm_kt2_oam_s_intf_passive_proc_ctrl_set 9530 * Purpose: 9531 * Set the default values for s-interface passive processing control 9532 * Parameters: 9533 * unit - (IN) BCM device number 9534 * Retruns: 9535 * BCM_E_XXX 9536 */ 9537 STATIC int 9538 _bcm_kt2_oam_s_intf_passive_proc_ctrl_set(int unit) 9539 { 9540 uint32 en_rval = 0; 9541 /* Set ingress s_intf passive processing control */ 9542 SOC_IF_ERROR_RETURN( 9543 soc_reg32_get(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 9544 REG_PORT_ANY, 0, &en_rval)); 9545 9546 soc_reg_field_set(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 9547 &en_rval, SPST_NOT_IN_FORWARDING_STATE_DROP_CTRLf, 9548 0x1); 9549 /* Set ENIFILTER_DROP, INVALID_TPID_DROP and INVALID_VLAN_DROP */ 9550 soc_reg_field_set(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 9551 &en_rval, VLAN_DROP_VECTOR_CTRLf, 9552 0x7); 9553 SOC_IF_ERROR_RETURN( 9554 soc_reg32_set(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 9555 REG_PORT_ANY, 0, en_rval)); 9556 9557 en_rval = 0; 9558 /* Set egress s_intf passive processing control */ 9559 SOC_IF_ERROR_RETURN( 9560 soc_reg32_get(unit, EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 9561 REG_PORT_ANY, 0, &en_rval)); 9562 9563 9564 /* Set NOT_VLAN_MEMBER_DROP, STG_BLOCK_DROP, STG_DISABLE_DROP 9565 For details - refer to EGR_DROP_VECTOR */ 9566 soc_reg_field_set(unit, EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 9567 &en_rval, EGR_DROP_VECTOR_CTRLf, 9568 0x1030); 9569 9570 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, 9571 EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 9572 REG_PORT_ANY, 0, en_rval)); 9573 return (BCM_E_NONE); 9574 } 9575 9576 /* 9577 * Function: 9578 * _bcm_kt2_oam_hg_olp_enable 9579 * Purpose: 9580 * Enable OLP handling on HG ports 9581 * Parameters: 9582 * unit - (IN) BCM device number 9583 * Retruns: 9584 * BCM_E_XXX 9585 */ 9586 STATIC int 9587 _bcm_kt2_oam_hg_olp_enable(int unit) 9588 { 9589 bcm_pbmp_t ports; 9590 bcm_port_t port; 9591 iarb_ing_physical_port_entry_t entry; 9592 9593 BCM_PBMP_ASSIGN(ports, PBMP_PORT_ALL(unit)); 9594 PBMP_ITER(ports, port) { 9595 if (IS_HG_PORT(unit, port)) { 9596 SOC_IF_ERROR_RETURN(soc_mem_read(unit, IARB_ING_PHYSICAL_PORTm, 9597 MEM_BLOCK_ANY, port, &entry)); 9598 soc_IARB_ING_PHYSICAL_PORTm_field32_set(unit, &entry, 9599 OLP_ENABLEf, 1); 9600 SOC_IF_ERROR_RETURN(soc_mem_write(unit, IARB_ING_PHYSICAL_PORTm, 9601 MEM_BLOCK_ALL, port, &entry)); 9602 } else { 9603 soc_IARB_ING_PHYSICAL_PORTm_field32_set(unit, &entry, 9604 OLP_ENABLEf, 0); 9605 } 9606 SOC_IF_ERROR_RETURN(soc_mem_write(unit, IARB_ING_PHYSICAL_PORTm, 9607 MEM_BLOCK_ALL, port, &entry)); 9608 } 9609 return (BCM_E_NONE); 9610 } 9611 9612 /* 9613 * Function: 9614 * _bcm_kt2_oam_olp_header_type_mapping_set 9615 * Purpose: 9616 * Set default olp header type mapping 9617 * Parameters: 9618 * unit - (IN) BCM device number 9619 * Retruns: 9620 * BCM_E_XXX 9621 * MEP_TYPE COMPRESSED_HDR_TYPE HDR_TYPE HDR_SUBTYPE 9622 * 9623 * ========================================================================== 9624 * Downmep/IFP 3'b000 8'd1(L2_HDR) 8'd0(NULL) 9625 * Downmep/IFP 3'b001 8'd0(OAM_HDR) 8'd2(CCM/BHH-CCM) 9626 * Downmep/IFP 3'b010 8'd0(OAM_HDR) 8'd3(BFD) 9627 * Downmep/IFP 3'b011 8'd0(OAM_HDR) 8'd4(LM/DM) 9628 * Upmep 3'b000 N/A N/A 9629 * Upmep 3'b001 8'd0(OAM_HDR) 8'd5(CCM) 9630 * Upmep 3'b010 N/A N/A 9631 * Upmep 3'b011 8'd0(OAM_HDR) 8'd6(LM/DM) 9632 */ 9633 STATIC int 9634 _bcm_kt2_oam_olp_header_type_mapping_set(int unit) 9635 { 9636 int index = 0; 9637 egr_olp_header_type_mapping_entry_t entry; 9638 9639 for (index = 0; index < kt2_olp_hdr_type_count; index++) { 9640 9641 if (kt2_olp_hdr_type_mapping[index].reuse) { 9642 continue; 9643 } 9644 9645 soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set(unit, 9646 &entry, 9647 HDR_TYPEf, 9648 _BCM_KT2_OLP_OAM_HDR); 9649 9650 soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set( 9651 unit, 9652 &entry, 9653 HDR_SUBTYPEf, 9654 kt2_olp_hdr_type_mapping[index].subtype); 9655 9656 SOC_IF_ERROR_RETURN( 9657 WRITE_EGR_OLP_HEADER_TYPE_MAPPINGm( 9658 unit, 9659 MEM_BLOCK_ALL, 9660 kt2_olp_hdr_type_mapping[index].mem_index, 9661 &entry)); 9662 } 9663 9664 /* Program L2 HDR at the first entry */ 9665 memset(&entry, 0, sizeof(entry)); 9666 soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set(unit, 9667 &entry, 9668 HDR_TYPEf, 9669 _BCM_KT2_OLP_L2_HDR); 9670 SOC_IF_ERROR_RETURN( 9671 WRITE_EGR_OLP_HEADER_TYPE_MAPPINGm(unit, 9672 MEM_BLOCK_ALL, 9673 0, 9674 &entry)); 9675 return BCM_E_NONE; 9676 } 9677 9678 /* 9679 * Function: _bcm_kt2_oam_olp_fp_hw_index_get 9680 * 9681 * Purpose: 9682 * Get OLP_HDR_TYPE_COMPRESSED corresponding to subtype 9683 * Parameters: 9684 * unit - (IN) BCM device number 9685 * Returns: 9686 * BCM_E_XXX 9687 */ 9688 int 9689 _bcm_kt2_oam_olp_fp_hw_index_get(int unit, 9690 bcm_field_olp_header_type_t olp_hdr_type, 9691 int *hwindex) 9692 { 9693 int index; 9694 9695 switch (olp_hdr_type) { 9696 /* KT2 does not allow IFP to program UpMEP header type for 9697 * ADD_OLP_HEADER action, as the OLP_HDR_TYPE_COMPRESSED in 9698 * FP_POLICY_TABLE is not wide enough to index Up MEP subtypes 9699 * in EGR_OLP_HEADER_TYPE_MAPPING 9700 */ 9701 9702 case bcmFieldOlpHeaderTypeEthOamUpMepCcm: 9703 case bcmFieldOlpHeaderTypeEthOamUpMepLm: 9704 case bcmFieldOlpHeaderTypeEthOamUpMepDm: 9705 return BCM_E_PARAM; 9706 9707 default: 9708 break; 9709 } 9710 9711 for (index = 0; index < kt2_olp_hdr_type_count; index++) { 9712 if (kt2_olp_hdr_type_mapping[index].field_olp_hdr_type == olp_hdr_type) { 9713 *hwindex = kt2_olp_hdr_type_mapping[index].mem_index; 9714 return BCM_E_NONE; 9715 } 9716 } 9717 9718 return BCM_E_NOT_FOUND; 9719 } 9720 9721 /* 9722 * Function: _bcm_kt2_oam_olp_hw_index_olp_type_get 9723 * 9724 * Purpose: 9725 * Get subtype corresponding to OLP_HDR_TYPE_COMPRESSED 9726 * Parameters: 9727 * unit - (IN) BCM device number 9728 * Returns: 9729 * BCM_E_XXX 9730 */ 9731 int 9732 _bcm_kt2_oam_olp_hw_index_olp_type_get(int unit, 9733 int hwindex, 9734 bcm_field_olp_header_type_t *olp_hdr_type) 9735 { 9736 int index; 9737 9738 for (index = 0; index < kt2_olp_hdr_type_count; index++) { 9739 if (kt2_olp_hdr_type_mapping[index].mem_index == hwindex) { 9740 9741 *olp_hdr_type = 9742 kt2_olp_hdr_type_mapping[hwindex].field_olp_hdr_type; 9743 9744 return BCM_E_NONE; 9745 } 9746 } 9747 return BCM_E_PARAM; 9748 } 9749 9750 /* 9751 * Function: 9752 * _bcm_kt2_oam_drop_ctrl_set 9753 * Purpose: 9754 * Set OAM drop control to not to drop wrong version OAM packets 9755 * Parameters: 9756 * unit - (IN) BCM device number 9757 * Retruns: 9758 * BCM_E_XXX 9759 */ 9760 STATIC int 9761 _bcm_kt2_oam_drop_ctrl_set(int unit) 9762 { 9763 uint32 drop_ctrl = 0; 9764 soc_reg_field_set(unit, OAM_DROP_CONTROLr, &drop_ctrl, 9765 IFP_OAM_UNKNOWN_OPCODE_VERSION_DROPf, 0); 9766 9767 SOC_IF_ERROR_RETURN(WRITE_OAM_DROP_CONTROLr(unit, drop_ctrl)); 9768 return (BCM_E_NONE); 9769 } 9770 9771 /* 9772 * Function: 9773 * _bcm_kt2_oam_lm_cng_cpu_ctrl_set_default 9774 * Purpose: 9775 * Set OAM LM cng and cpu data control 9776 * Parameters: 9777 * unit - (IN) BCM device number 9778 * Retruns: 9779 * BCM_E_XXX 9780 */ 9781 STATIC int 9782 _bcm_kt2_oam_lm_cng_cpu_ctrl_set_default(int unit) 9783 { 9784 uint32 rval = 0; 9785 /* Set OAM LM CNG control such that 9786 1. All colored packets are counted, 9787 2. Use LM_COLOR_MODE bit to qualify pre FP CNG for UPMEP TX 9788 counters in IP 9789 3. Use LM_COLOR_MODE bit to qualify post FP CNG for DOWNMEP RX 9790 counters in IP 9791 */ 9792 soc_reg_field_set(unit, OAM_LM_CNG_CONTROLr, &rval, 9793 LM_COLOR_MODEf, 1); 9794 soc_reg_field_set(unit, OAM_LM_CNG_CONTROLr, &rval, 9795 UPMEP_TX_CNG_SOURCEf, 1); 9796 soc_reg_field_set(unit, OAM_LM_CNG_CONTROLr, &rval, 9797 DOWNMEP_RX_CNG_SOURCEf, 0); 9798 SOC_IF_ERROR_RETURN(WRITE_OAM_LM_CNG_CONTROLr(unit, rval)); 9799 9800 rval = 0; 9801 /* include all colored packets for LM accounting on egress side */ 9802 soc_reg_field_set(unit, EGR_OAM_LM_CNG_CONTROLr, &rval, 9803 LM_COLOR_MODEf, 1); 9804 SOC_IF_ERROR_RETURN(WRITE_EGR_OAM_LM_CNG_CONTROLr(unit, rval)); 9805 9806 rval = 0; 9807 9808 /* Set OAM_LM_CPU_DATA_CONTROL to not to count 9809 CPU generated data packets for loss measurement */ 9810 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 9811 OAM_LCPU_TX_CNT_DISABLEf, 1); 9812 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 9813 OAM_LCPU_RX_CNT_DISABLEf, 1); 9814 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 9815 OAM_SRCPORT0_TX_CNT_DISABLEf, 1); 9816 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 9817 OAM_SRCPORT0_RX_CNT_DISABLEf, 1); 9818 SOC_IF_ERROR_RETURN(WRITE_OAM_LM_CPU_DATA_CONTROLr(unit, rval)); 9819 9820 return (BCM_E_NONE); 9821 } 9822 /* 9823 * Function: 9824 * _bcm_kt2_oam_lm_cng_cpu_ctrl_set 9825 * Purpose: 9826 * Set OAM LM cng and cpu data control 9827 * Parameters: 9828 * unit - (IN) BCM device number 9829 * Retruns: 9830 * BCM_E_XXX 9831 */ 9832 STATIC int 9833 _bcm_kt2_oam_lm_cng_cpu_ctrl_set (int unit, bcm_oam_endpoint_info_t *ep) 9834 { 9835 uint32 rval = 0; 9836 uint32 egr_rval = 0; 9837 int up_mep = 0; 9838 int color_mode = 0; 9839 int cng_source = 0; 9840 int count_pkt = 1; 9841 if (ep->lm_flags) { 9842 /* read LM CNG register */ 9843 SOC_IF_ERROR_RETURN(READ_OAM_LM_CNG_CONTROLr(unit, &rval)); 9844 SOC_IF_ERROR_RETURN(READ_EGR_OAM_LM_CNG_CONTROLr(unit, &egr_rval)); 9845 9846 if (ep->lm_flags & BCM_OAM_LOSS_COUNT_GREEN_AND_YELLOW) { 9847 color_mode = 1; 9848 } 9849 soc_reg_field_set(unit, OAM_LM_CNG_CONTROLr, &rval, 9850 LM_COLOR_MODEf, color_mode); 9851 soc_reg_field_set(unit, EGR_OAM_LM_CNG_CONTROLr, &egr_rval, 9852 LM_COLOR_MODEf, color_mode); 9853 9854 if (ep->flags & BCM_OAM_ENDPOINT_UP_FACING) { 9855 up_mep = 1; 9856 } 9857 if (ep->lm_flags & BCM_OAM_LOSS_COUNT_POST_TRAFFIC_CONDITIONING) { 9858 cng_source = 1; 9859 } 9860 if (up_mep) { 9861 soc_reg_field_set(unit, OAM_LM_CNG_CONTROLr, &rval, 9862 UPMEP_TX_CNG_SOURCEf, cng_source); 9863 } else { 9864 soc_reg_field_set(unit, OAM_LM_CNG_CONTROLr, &rval, 9865 DOWNMEP_RX_CNG_SOURCEf, cng_source); 9866 } 9867 /* write back the registrs */ 9868 SOC_IF_ERROR_RETURN(WRITE_OAM_LM_CNG_CONTROLr(unit, rval)); 9869 SOC_IF_ERROR_RETURN(WRITE_EGR_OAM_LM_CNG_CONTROLr(unit, egr_rval)); 9870 /* Read LM CPU data control */ 9871 SOC_IF_ERROR_RETURN(READ_OAM_LM_CPU_DATA_CONTROLr(unit, &rval)); 9872 if (ep->lm_flags & BCM_OAM_LOSS_COUNT_CPU_RX_PKT) { 9873 count_pkt = 0; 9874 } 9875 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 9876 OAM_LCPU_RX_CNT_DISABLEf, count_pkt); 9877 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 9878 OAM_SRCPORT0_RX_CNT_DISABLEf, count_pkt); 9879 9880 if (ep->lm_flags & BCM_OAM_LOSS_COUNT_CPU_TX_PKT) { 9881 count_pkt = 0; 9882 } else { 9883 count_pkt = 1; 9884 } 9885 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 9886 OAM_LCPU_TX_CNT_DISABLEf, count_pkt); 9887 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 9888 OAM_SRCPORT0_TX_CNT_DISABLEf, count_pkt); 9889 SOC_IF_ERROR_RETURN(WRITE_OAM_LM_CPU_DATA_CONTROLr(unit, rval)); 9890 } 9891 return (BCM_E_NONE); 9892 } 9893 9894 /* 9895 * Function: 9896 * _bcm_kt2_oam_olp_magic_port_set 9897 * Purpose: 9898 * Set Magic port used in OLP-XGS communication 9899 * Parameters: 9900 * unit - (IN) BCM device number 9901 * Retruns: 9902 * BCM_E_XXX 9903 */ 9904 STATIC int 9905 _bcm_kt2_oam_olp_magic_port_set(int unit) 9906 { 9907 uint64 rval, set_val; 9908 int modid; 9909 COMPILER_64_ZERO(rval); 9910 /* configure modid and the magic port */ 9911 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 9912 SOC_IF_ERROR_RETURN(READ_IARB_OLP_CONFIG_1r(unit, &rval)); 9913 9914 COMPILER_64_SET(set_val, 0, modid); 9915 soc_reg64_field_set(unit, IARB_OLP_CONFIG_1r, &rval, MY_MODIDf, set_val); 9916 COMPILER_64_SET(set_val, 0, _BCM_OAM_OLP_COMMUNICATION_PORT); 9917 soc_reg64_field_set(unit, IARB_OLP_CONFIG_1r, &rval, MY_PORT_NUMf, set_val); 9918 9919 SOC_IF_ERROR_RETURN(WRITE_IARB_OLP_CONFIG_1r(unit, rval)); 9920 return (BCM_E_NONE); 9921 } 9922 9923 /* 9924 * Function: 9925 * _bcm_kt2_oam_macsa_zero_check_disable 9926 * Purpose: 9927 * Disable MACSA Zero check 9928 * Parameters: 9929 * unit - (IN) BCM device number 9930 * Retruns: 9931 * BCM_E_XXX 9932 */ 9933 STATIC int 9934 _bcm_kt2_oam_macsa_zero_check_disable(int unit) 9935 { 9936 uint32 rval = 0; 9937 soc_reg_field_set(unit, OAM_CONTROLr, &rval, 9938 MACSA_ZERO_CHECK_ENABLEf, 0); 9939 SOC_IF_ERROR_RETURN(WRITE_OAM_CONTROLr(unit, rval)); 9940 soc_reg_field_set(unit, EGR_OAM_CONTROLr, &rval, 9941 MACSA_ZERO_CHECK_ENABLEf, 0); 9942 SOC_IF_ERROR_RETURN(WRITE_EGR_OAM_CONTROLr(unit, rval)); 9943 return (BCM_E_NONE); 9944 } 9945 9946 /* 9947 * Function: 9948 * _bcm_kt2_oam_endpoint_cleanup 9949 * Purpose: 9950 * Free all the counters and the indexes allocated on endpoint create 9951 * failure 9952 * Parameters: 9953 * unit - (IN) BCM device number 9954 * upmep- (IN) UpMep/DownMep 9955 * hash_key (IN) 9956 * hash_data (IN) Pointer to endpoint hash data 9957 * Retruns: 9958 * BCM_E_XXX 9959 */ 9960 void 9961 _bcm_kt2_oam_endpoint_cleanup(int unit, int upmep, 9962 _bcm_oam_hash_key_t hash_key, 9963 _bcm_oam_hash_data_t *hash_data) 9964 { 9965 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 9966 int rv = BCM_E_NONE; 9967 _bcm_oam_hash_data_t h_data_stored; /* Stored hash data. */ 9968 uint8 active_mdl = 0; 9969 9970 rv = _bcm_kt2_oam_control_get(unit, &oc); 9971 if (BCM_FAILURE(rv)) { 9972 return; 9973 } 9974 if (upmep) { 9975 /* Delete l3_entry, if already added */ 9976 rv = _bcm_kt2_oam_egr_mp_group_entry_destroy(unit, hash_data, 9977 &active_mdl); 9978 /* Update Ingress MP group table(L3_ENTRY) */ 9979 rv = _bcm_kt2_oam_l3_entry_destroy(unit, hash_data, &active_mdl); 9980 } else { 9981 /* Update Ingress MP group table(L3_ENTRY) */ 9982 rv = _bcm_kt2_oam_l3_entry_destroy(unit, hash_data, &active_mdl); 9983 /* Delete l3_entry, if already added */ 9984 rv = _bcm_kt2_oam_egr_mp_group_entry_destroy(unit, hash_data, 9985 &active_mdl); 9986 } 9987 /* return rx & tx counters allocated if any */ 9988 rv =_bcm_kt2_oam_free_counter(unit, hash_data); 9989 9990 /* Clear opcode profile entry, if any */ 9991 if (hash_data->profile_index != _BCM_OAM_INVALID_INDEX) { 9992 if (upmep) { 9993 rv = soc_profile_mem_delete(unit, 9994 &oc->egr_oam_opcode_control_profile, 9995 hash_data->profile_index); 9996 } else { 9997 rv = soc_profile_mem_delete(unit, &oc->oam_opcode_control_profile, 9998 hash_data->profile_index); 9999 } 10000 } 10001 /* Clear dglp profile, if any */ 10002 if (hash_data->dglp1_profile_index != _BCM_OAM_INVALID_INDEX) { 10003 if (upmep) { 10004 rv = soc_profile_mem_delete(unit, &oc->egr_oam_dglp_profile, 10005 hash_data->dglp1_profile_index); 10006 } else { 10007 rv = soc_profile_mem_delete(unit, &oc->ing_oam_dglp_profile, 10008 hash_data->dglp1_profile_index); 10009 } 10010 } 10011 10012 if (hash_data->dglp2_profile_index != _BCM_OAM_INVALID_INDEX) { 10013 if (upmep) { 10014 rv = soc_profile_mem_delete(unit, &oc->egr_oam_dglp_profile, 10015 hash_data->dglp2_profile_index); 10016 } else { 10017 rv = soc_profile_mem_delete(unit, &oc->ing_oam_dglp_profile, 10018 hash_data->dglp2_profile_index); 10019 } 10020 } 10021 /* Clear Service pri map profile, if configured */ 10022 if (hash_data->pri_map_index != _BCM_OAM_INVALID_INDEX) { 10023 rv = soc_profile_mem_delete(unit, &oc->ing_service_pri_map, 10024 hash_data->pri_map_index); 10025 10026 } 10027 if (hash_data->egr_pri_map_index != _BCM_OAM_INVALID_INDEX) { 10028 rv = soc_profile_mem_delete(unit, &oc->egr_service_pri_map, 10029 hash_data->egr_pri_map_index); 10030 } 10031 /* Decrement TPID ref count, if already incremented */ 10032 if (hash_data->outer_tpid_profile_index != _BCM_OAM_INVALID_INDEX) { 10033 rv = _bcm_kt2_tpid_entry_delete(unit, 10034 hash_data->outer_tpid_profile_index, 10035 BCM_OAM_TPID_TYPE_OUTER); 10036 } 10037 if (hash_data->subport_tpid_profile_index != _BCM_OAM_INVALID_INDEX) { 10038 rv = _bcm_kt2_tpid_entry_delete(unit, 10039 hash_data->subport_tpid_profile_index, 10040 BCM_OAM_TPID_TYPE_SUBPORT); 10041 } 10042 if (hash_data->inner_tpid_profile_index != _BCM_OAM_INVALID_INDEX) { 10043 rv = _bcm_kt2_tpid_entry_delete(unit, 10044 hash_data->inner_tpid_profile_index, 10045 BCM_OAM_TPID_TYPE_INNER); 10046 } 10047 10048 /* It might already have been deleted as well. 10049 * So just log it as debug, in case it fails */ 10050 rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_delete(unit, hash_data); 10051 if (BCM_FAILURE(rv)) { 10052 LOG_DEBUG(BSL_LS_BCM_OAM, 10053 (BSL_META_U(unit, 10054 "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) -" 10055 " %s.\n"), unit, hash_data->ep_id, bcm_errmsg(rv))); 10056 } 10057 #if defined(INCLUDE_BHH) 10058 if((hash_data->type == bcmOAMEndpointTypeBHHMPLS) || 10059 (hash_data->type == bcmOAMEndpointTypeBHHMPLSVccv)) { 10060 shr_idxres_list_free(oc->bhh_pool, 10061 BCM_OAM_BHH_GET_UKERNEL_EP(hash_data->ep_id)); 10062 } else 10063 #endif 10064 { 10065 if (1 == hash_data->is_remote) { 10066 /* If remote endpoint, return index to remp pool */ 10067 shr_idxres_list_free(oc->rmep_pool, hash_data->remote_index); 10068 } else { 10069 /* If local endpoint, return index to lmep pool */ 10070 shr_idxres_list_free(oc->lmep_pool, hash_data->local_tx_index); 10071 } 10072 10073 /* return index to mep pool */ 10074 shr_idxres_list_free(oc->mep_pool, hash_data->ep_id); 10075 } 10076 /* Return entry to hash data entry to free pool. */ 10077 shr_htb_find(oc->ma_mep_htbl, hash_key, 10078 (shr_htb_data_t *)&h_data_stored, 1); 10079 10080 /* Clear contents of hash data element. */ 10081 _BCM_OAM_HASH_DATA_CLEAR(hash_data); 10082 } 10083 10084 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 10085 void 10086 _bcm_kt2_oam_group_info_dump(int unit, bcm_oam_group_t group_index, 10087 _bcm_oam_group_data_t *group_p) 10088 { 10089 int rv; 10090 bcm_oam_group_info_t group_info; 10091 10092 /* Initialize the group information structure. */ 10093 bcm_oam_group_info_t_init(&group_info); 10094 10095 /* Retrieve group information and set in group_info structure. */ 10096 rv = _bcm_kt2_oam_get_group(unit, group_index, group_p, &group_info); 10097 if (BCM_FAILURE(rv)) { 10098 LOG_ERROR(BSL_LS_BCM_OAM, 10099 (BSL_META_U(unit, 10100 "OAM(unit %d) Error: _bcm_kt2_oam_group_info_dump" 10101 " (GID=%d) - %s.\n"), 10102 unit, group_index, bcm_errmsg(rv))); 10103 return; 10104 } 10105 LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n"))); 10106 LOG_CLI((BSL_META_U(unit,"Group ID = %d details\r\n"), group_index)); 10107 LOG_CLI((BSL_META_U(unit,"Group Name = %s\r\n"), group_info.name)); 10108 LOG_CLI((BSL_META_U(unit,"Flags = %d\r\n"), group_info.flags)); 10109 LOG_CLI((BSL_META_U(unit,"Faults = %d\r\n"), group_info.faults)); 10110 LOG_CLI((BSL_META_U(unit,"Persistent_faults = %d\r\n"), 10111 group_info.persistent_faults)); 10112 LOG_CLI((BSL_META_U(unit,"clear_persistent_faults = %d\r\n"), 10113 group_info.clear_persistent_faults)); 10114 LOG_CLI((BSL_META_U(unit,"lowest_alarm_priority = %d\r\n"), 10115 group_info.lowest_alarm_priority)); 10116 LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n"))); 10117 } 10118 10119 void 10120 _bcm_kt2_oam_hash_data_dump(int unit, _bcm_oam_hash_data_t *h_data_p) 10121 { 10122 LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n"))); 10123 LOG_CLI((BSL_META_U(unit,"EP ID = %d\r\n"),h_data_p->ep_id)); 10124 LOG_CLI((BSL_META_U(unit,"Type = %d\r\n"),h_data_p->type)); 10125 LOG_CLI((BSL_META_U(unit,"In use = %d\r\n"),h_data_p->in_use)); 10126 LOG_CLI((BSL_META_U(unit,"Remote = %d\r\n"),h_data_p->is_remote)); 10127 LOG_CLI((BSL_META_U(unit,"Name = %d\r\n"),h_data_p->name)); 10128 LOG_CLI((BSL_META_U(unit,"Level = %d\r\n"),h_data_p->level)); 10129 LOG_CLI((BSL_META_U(unit,"Outer Vlan = %d\r\n"),h_data_p->vlan)); 10130 LOG_CLI((BSL_META_U(unit,"Inner Vlan = %d\r\n"),h_data_p->inner_vlan)); 10131 LOG_CLI((BSL_META_U(unit,"Gport = %d\r\n"),h_data_p->gport)); 10132 LOG_CLI((BSL_META_U(unit,"SGLP = %d\r\n"),h_data_p->sglp)); 10133 LOG_CLI((BSL_META_U(unit,"DGLP = %d\r\n"),h_data_p->dglp)); 10134 LOG_CLI((BSL_META_U(unit,"Tx ena = %d\r\n"),h_data_p->local_tx_enabled)); 10135 LOG_CLI((BSL_META_U(unit,"Rx ena = %d\r\n"),h_data_p->local_rx_enabled)); 10136 LOG_CLI((BSL_META_U(unit,"Grp idx = %d\r\n"),h_data_p->group_index)); 10137 LOG_CLI((BSL_META_U(unit,"Remote idx = %d\r\n"),h_data_p->remote_index)); 10138 LOG_CLI((BSL_META_U(unit,"LM ctr idx = %d\r\n"),h_data_p->lm_counter_index)); 10139 LOG_CLI((BSL_META_U(unit,"Pri map idx = %d\r\n"),h_data_p->pri_map_index)); 10140 LOG_CLI((BSL_META_U(unit,"Profile Idx = %d\r\n"),h_data_p->profile_index)); 10141 LOG_CLI((BSL_META_U(unit,"Local Tx index = %d\r\n"),h_data_p->local_tx_index)); 10142 LOG_CLI((BSL_META_U(unit,"Local Rx index = %d\r\n"),h_data_p->local_rx_index)); 10143 LOG_CLI((BSL_META_U(unit,"VP = %d\r\n"),h_data_p->vp)); 10144 LOG_CLI((BSL_META_U(unit,"Flags = 0x%x\r\n"),h_data_p->flags)); 10145 LOG_CLI((BSL_META_U(unit,"Flags2 = 0x%x\r\n"),h_data_p->flags2)); 10146 LOG_CLI((BSL_META_U(unit,"Vfp_entry = 0x%x\r\n"),h_data_p->vfp_entry)); 10147 LOG_CLI((BSL_META_U(unit,"Fp_entry_tx = 0x%x\r\n"),h_data_p->fp_entry_tx)); 10148 LOG_CLI((BSL_META_U(unit,"Fp_entry_rx = 0x%x\r\n"),h_data_p->fp_entry_rx)); 10149 LOG_CLI((BSL_META_U(unit,"Period = %d\r\n"),h_data_p->period)); 10150 LOG_CLI((BSL_META_U(unit,"Opcode flags = 0x%x\r\n"),h_data_p->opcode_flags)); 10151 LOG_CLI((BSL_META_U(unit,"TS format = %d\r\n"),h_data_p->ts_format)); 10152 LOG_CLI((BSL_META_U(unit,"Label = 0x%x\r\n"),h_data_p->label)); 10153 LOG_CLI((BSL_META_U(unit,"Vlan Pri = %d\r\n"),h_data_p->vlan_pri)); 10154 LOG_CLI((BSL_META_U(unit,"Egress if = 0x%x\r\n"),h_data_p->egress_if)); 10155 LOG_CLI((BSL_META_U(unit,"Int pri = %d\r\n"),h_data_p->int_pri)); 10156 LOG_CLI((BSL_META_U(unit,"Trunk index = %d\r\n"),h_data_p->trunk_index)); 10157 LOG_CLI((BSL_META_U(unit,"Domain = %d\r\n"),h_data_p->oam_domain)); 10158 LOG_CLI((BSL_META_U(unit,"Egr pri map idx = %d\r\n"),h_data_p->egr_pri_map_index)); 10159 LOG_CLI((BSL_META_U(unit,"Rx ctr = %d\r\n"),h_data_p->rx_ctr)); 10160 LOG_CLI((BSL_META_U(unit,"Tx ctr = %d\r\n"),h_data_p->tx_ctr)); 10161 LOG_CLI((BSL_META_U(unit,"src pp port = %d\r\n"),h_data_p->src_pp_port)); 10162 LOG_CLI((BSL_META_U(unit,"dst pp port = %d\r\n"),h_data_p->dst_pp_port)); 10163 LOG_CLI((BSL_META_U(unit,"DGLP1 = %d\r\n"),h_data_p->dglp1)); 10164 LOG_CLI((BSL_META_U(unit,"DGLP2 = %d\r\n"),h_data_p->dglp2)); 10165 LOG_CLI((BSL_META_U(unit,"DGLP1 Profile idx = %d\r\n"),h_data_p->dglp1_profile_index)); 10166 LOG_CLI((BSL_META_U(unit,"DGLP2 Profile idx = %d\r\n"),h_data_p->dglp2_profile_index)); 10167 LOG_CLI((BSL_META_U(unit,"Outer TPID = 0x%04X\r\n"),h_data_p->outer_tpid)); 10168 LOG_CLI((BSL_META_U(unit,"Inner TPID = 0x%04X\r\n"),h_data_p->inner_tpid)); 10169 LOG_CLI((BSL_META_U(unit,"SubPort TPID = %d\r\n"),h_data_p->subport_tpid)); 10170 LOG_CLI((BSL_META_U(unit,"Outer TPID profile idx = %d\r\n"),h_data_p->outer_tpid_profile_index)); 10171 LOG_CLI((BSL_META_U(unit,"Inner TPID profile idx = %d\r\n"),h_data_p->inner_tpid_profile_index)); 10172 LOG_CLI((BSL_META_U(unit,"SubPort TPID profile idx = %d\r\n"),h_data_p->subport_tpid_profile_index)); 10173 LOG_CLI((BSL_META_U(unit,"MA Base idx = %d\r\n"),h_data_p->ma_base_index)); 10174 LOG_CLI((BSL_META_U(unit,"Trunk ID = %d\r\n"),h_data_p->trunk_id)); 10175 LOG_CLI((BSL_META_U(unit,"Active MDL BITMAP = 0x%x\r\n"),h_data_p->active_mdl_bitmap)); 10176 LOG_CLI((BSL_META_U(unit,"Internal flags = 0x%x\r\n"),h_data_p->int_flags)); 10177 #if defined(INCLUDE_BHH) 10178 LOG_CLI((BSL_META_U(unit,"Cpu qid = %d\r\n"),h_data_p->cpu_qid)); 10179 LOG_CLI((BSL_META_U(unit,"BHH Endpoint Index = %d\r\n"),h_data_p->bhh_endpoint_index)); 10180 LOG_CLI((BSL_META_U(unit,"BHH DM ENTRY= %d\r\n"),h_data_p->bhh_dm_entry_rx)); 10181 LOG_CLI((BSL_META_U(unit,"BHH LM ENTRY= %d\r\n"),h_data_p->bhh_lm_entry_rx)); 10182 LOG_CLI((BSL_META_U(unit,"BHH ENTRY PKT RX= %d\r\n"),h_data_p->bhh_entry_pkt_rx)); 10183 LOG_CLI((BSL_META_U(unit,"BHH ENTRY PKT TX= %d\r\n"),h_data_p->bhh_entry_pkt_tx)); 10184 LOG_CLI((BSL_META_U(unit,"Src Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"), 10185 h_data_p->src_mac_address[0], h_data_p->src_mac_address[1], 10186 h_data_p->src_mac_address[2], h_data_p->src_mac_address[3], 10187 h_data_p->src_mac_address[4], h_data_p->src_mac_address[5])); 10188 LOG_CLI((BSL_META_U(unit,"Dst Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"), 10189 h_data_p->dst_mac_address[0], h_data_p->dst_mac_address[1], 10190 h_data_p->dst_mac_address[2], h_data_p->dst_mac_address[3], 10191 h_data_p->dst_mac_address[4], h_data_p->dst_mac_address[5])); 10192 LOG_CLI((BSL_META_U(unit,"Inner vlan pri = %d\r\n"),h_data_p->inner_vlan_pri)); 10193 LOG_CLI((BSL_META_U(unit,"egr label= %d\r\n"),h_data_p->egr_label)); 10194 LOG_CLI((BSL_META_U(unit,"egr label exp= %d\r\n"),h_data_p->egr_label_exp)); 10195 LOG_CLI((BSL_META_U(unit,"egr label ttl= %d\r\n"),h_data_p->egr_label_ttl)); 10196 #endif 10197 LOG_CLI((BSL_META_U(unit,"Vccv Type = %d\r\n"),h_data_p->vccv_type)); 10198 LOG_CLI((BSL_META_U(unit,"VPN = %d\r\n"),h_data_p->vpn)); 10199 LOG_CLI((BSL_META_U(unit,"PM profile attached = %d\r\n"),h_data_p->pm_profile_attached)); 10200 LOG_CLI((BSL_META_U(unit,"CTR Field id = %d\r\n"),h_data_p->ctr_field_id)); 10201 LOG_CLI((BSL_META_U(unit,"EGR CTR Field id = %d\r\n"),h_data_p->egr_ctr_field_id)); 10202 LOG_CLI((BSL_META_U(unit,"Resolved trunk gport based on trunk " 10203 "index 0x%x\r\n"), 10204 h_data_p->resolved_trunk_gport)); 10205 LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n"))); 10206 } 10207 10208 /* 10209 * Function: 10210 * _bcm_oam_sw_dump 10211 * Purpose: 10212 * Displays oam information maintained by software. 10213 * Parameters: 10214 * unit - Device unit number 10215 * Returns: 10216 * None 10217 */ 10218 void 10219 _bcm_kt2_oam_sw_dump(int unit) 10220 { 10221 int rv; 10222 bcm_oam_group_t grp_idx; 10223 _bcm_oam_control_t *oc = NULL; 10224 _bcm_oam_group_data_t *group_p = NULL; 10225 _bcm_oam_ep_list_t *ep_list_p = NULL; 10226 _bcm_oam_hash_data_t *ep_data_p = NULL; 10227 10228 LOG_CLI((BSL_META_U(unit,"OAM\n"))); 10229 /* Get OAM control structure. */ 10230 rv = _bcm_kt2_oam_control_get(unit, &oc); 10231 if(BCM_FAILURE(rv)) { 10232 LOG_ERROR(BSL_LS_BCM_OAM, 10233 (BSL_META_U(unit, 10234 "OAM(unit %d) Error: Get oam control variable\n"), 10235 unit)); 10236 10237 return; 10238 } 10239 10240 _BCM_OAM_LOCK(oc); 10241 10242 group_p = oc->group_info; 10243 for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) { 10244 if (group_p[grp_idx].in_use == 1) { 10245 ep_list_p = *(group_p[grp_idx].ep_list); 10246 _bcm_kt2_oam_group_info_dump(unit, grp_idx, group_p); 10247 while (ep_list_p != NULL) { 10248 ep_data_p = ep_list_p->ep_data_p; 10249 _bcm_kt2_oam_hash_data_dump(unit, ep_data_p); 10250 ep_list_p = ep_list_p->next; 10251 } 10252 } 10253 } 10254 10255 _BCM_OAM_UNLOCK(oc); 10256 } 10257 10258 void _bcm_kt2_oam_ma_idx_to_ep_id_mapping_print(int unit) 10259 { 10260 _bcm_oam_control_t *oc = NULL; /* Pointer to control structure. */ 10261 int i = 0; 10262 int rv = BCM_E_NONE; 10263 10264 rv = _bcm_kt2_oam_control_get(unit, &oc); 10265 if ((BCM_FAILURE(rv)) || (oc == NULL)) { 10266 return; 10267 } 10268 _BCM_OAM_LOCK(oc); 10269 10270 if (oc->_bcm_oam_ma_idx_to_ep_id_map != NULL) { 10271 for (i = 0; i < (oc->ma_idx_count + oc->egr_ma_idx_count);i++) { 10272 if (oc->_bcm_oam_ma_idx_to_ep_id_map[i] != _BCM_OAM_INVALID_INDEX) { 10273 LOG_CLI((BSL_META_U(unit,"MA_IDX = %d EP_ID = %d\r\n"), 10274 i, oc->_bcm_oam_ma_idx_to_ep_id_map[i])); 10275 } 10276 } 10277 } 10278 _BCM_OAM_UNLOCK(oc); 10279 } 10280 #endif 10281 10282 #if defined(BCM_WARM_BOOT_SUPPORT) 10283 #ifdef _KATANA2_DEBUG 10284 /* 10285 * Function: 10286 * _bcm_kt2_oam_tx_counter_recover 10287 * Purpose: 10288 * Recover Rx counter for MEP 10289 * Parameters: 10290 * unit - (IN) BCM device number 10291 * Retruns: 10292 * BCM_E_XXX 10293 */ 10294 STATIC int 10295 _bcm_kt2_oam_tx_counter_recover(int unit, soc_mem_t mem, 10296 uint32 *entry, 10297 _bcm_oam_hash_data_t *h_data_p) 10298 { 10299 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 10300 int rv = BCM_E_NONE;/* Operation return status. */ 10301 int up_mep = 0; 10302 mep_ctr_info_t *ctr_info; 10303 shr_aidxres_list_handle_t *ctr_pool; 10304 int *map; 10305 int ctr_type = 0; 10306 int ctr_valid = 0; 10307 int ctr_mdl = 0; 10308 10309 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 10310 if (mem == L3_ENTRY_IPV4_UNICASTm) { 10311 up_mep = 1; 10312 ctr_info = mep_ctr_info; 10313 map = &h_data_p->pri_map_index; 10314 } else if (mem == EGR_MP_GROUPm) { 10315 ctr_info = egr_mep_ctr_info; 10316 map = &h_data_p->egr_pri_map_index; 10317 } else { 10318 return BCM_E_INTERNAL; 10319 } 10320 ctr_pool = oc->ing_lm_ctr_pool; 10321 ctr_valid = soc_mem_field32_get(unit, mem, 10322 (uint32 *)entry, ctr_info[0].ctr_valid); 10323 10324 if (ctr_valid) { 10325 ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10326 ctr_info[0].ctr_mep_type); 10327 ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10328 ctr_info[0].ctr_mep_mdl); 10329 if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) { 10330 h_data_p->tx_ctr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10331 ctr_info[0].ctr_base_ptr); 10332 10333 h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 10334 *map = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10335 ctr_info[0].ctr_profile); 10336 /* Allocate 8 consecutive couters from the pool */ 10337 rv = shr_aidxres_list_reserve_block(ctr_pool[0], 10338 h_data_p->tx_ctr, 8); 10339 if (BCM_FAILURE(rv)) { 10340 LOG_ERROR(BSL_LS_BCM_OAM, 10341 (BSL_META_U(unit, 10342 "OAM Error: LM counter block alloc failed " 10343 "(EP=%d) - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 10344 return (rv); 10345 } 10346 } 10347 } 10348 ctr_valid = soc_mem_field32_get(unit, mem, 10349 (uint32 *)entry, ctr_info[1].ctr_valid); 10350 if (ctr_valid) { 10351 ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10352 ctr_info[1].ctr_mep_type); 10353 ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10354 ctr_info[1].ctr_mep_mdl); 10355 if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) { 10356 h_data_p->tx_ctr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10357 ctr_info[1].ctr_base_ptr); 10358 10359 h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 10360 *map = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10361 ctr_info[1].ctr_profile); 10362 /* Allocate 8 consecutive couters from the pool */ 10363 rv = shr_aidxres_list_reserve_block(ctr_pool[1], 10364 h_data_p->tx_ctr, 8); 10365 if (BCM_FAILURE(rv)) { 10366 LOG_ERROR(BSL_LS_BCM_OAM, 10367 (BSL_META_U(unit, 10368 "OAM Error: LM counter block alloc failed " 10369 "(EP=%d) - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 10370 return (rv); 10371 } 10372 } 10373 } 10374 return (rv); 10375 } 10376 10377 #endif /* _KATANA2_DEBUG */ 10378 10379 /* 10380 * Function: 10381 * _bcm_kt2_oam_rx_counter_recover 10382 * Purpose: 10383 * Recover Rx counter for MEP 10384 * Parameters: 10385 * unit - (IN) BCM device number 10386 * Retruns: 10387 * BCM_E_XXX 10388 */ 10389 STATIC int 10390 _bcm_kt2_oam_rx_counter_recover(int unit, soc_mem_t mem, 10391 uint32 *entry, 10392 _bcm_oam_hash_data_t *h_data_p) 10393 { 10394 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 10395 int rv = BCM_E_NONE;/* Operation return status. */ 10396 int up_mep = 0; 10397 mep_ctr_info_t *ctr_info; 10398 shr_aidxres_list_handle_t *ctr_pool; 10399 int *map; 10400 int ctr_valid = 0; 10401 int ctr_mdl = 0; 10402 int ctr_type = 0; 10403 soc_profile_mem_t *pri_map_profile; 10404 10405 10406 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 10407 if (mem == EGR_MP_GROUPm) { 10408 up_mep = 1; 10409 ctr_info = egr_mep_ctr_info; 10410 map = &h_data_p->egr_pri_map_index; 10411 pri_map_profile = &oc->egr_service_pri_map; 10412 } else { 10413 ctr_info = mep_ctr_info; 10414 map = &h_data_p->pri_map_index; 10415 pri_map_profile = &oc->ing_service_pri_map; 10416 } 10417 ctr_pool = oc->ing_lm_ctr_pool; 10418 ctr_valid = soc_mem_field32_get(unit, mem, 10419 (uint32 *)entry, ctr_info[0].ctr_valid); 10420 10421 if (ctr_valid) { 10422 ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10423 ctr_info[0].ctr_mep_type); 10424 ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10425 ctr_info[0].ctr_mep_mdl); 10426 if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) { 10427 h_data_p->rx_ctr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10428 ctr_info[0].ctr_base_ptr); 10429 10430 h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 10431 *map = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10432 ctr_info[0].ctr_profile); 10433 rv = soc_profile_mem_reference(unit, pri_map_profile, 10434 ((*map) * BCM_OAM_INTPRI_MAX), BCM_OAM_INTPRI_MAX); 10435 if (BCM_FAILURE(rv)) { 10436 LOG_ERROR(BSL_LS_BCM_OAM, 10437 (BSL_META_U(unit, 10438 "OAM Error: LM counter profile ref count " 10439 "increment failed (EP=%d) - %s.\n"), 10440 h_data_p->ep_id, bcm_errmsg(rv))); 10441 return (rv); 10442 } 10443 /* Allocate 8 consecutive couters from the pool */ 10444 rv = shr_aidxres_list_reserve_block(ctr_pool[0], 10445 h_data_p->rx_ctr, 8); 10446 if (BCM_FAILURE(rv)) { 10447 LOG_ERROR(BSL_LS_BCM_OAM, 10448 (BSL_META_U(unit, 10449 "OAM Error: LM counter block alloc failed " 10450 "(EP=%d) - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 10451 return (rv); 10452 } 10453 } 10454 } 10455 ctr_valid = soc_mem_field32_get(unit, mem, 10456 (uint32 *)entry, ctr_info[1].ctr_valid); 10457 if (ctr_valid) { 10458 ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10459 ctr_info[1].ctr_mep_type); 10460 ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10461 ctr_info[1].ctr_mep_mdl); 10462 if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) { 10463 h_data_p->rx_ctr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10464 ctr_info[1].ctr_base_ptr); 10465 10466 h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 10467 *map = soc_mem_field32_get(unit, mem, (uint32 *)entry, 10468 ctr_info[1].ctr_profile); 10469 rv = soc_profile_mem_reference(unit, pri_map_profile, 10470 ((*map) * BCM_OAM_INTPRI_MAX), BCM_OAM_INTPRI_MAX); 10471 if (BCM_FAILURE(rv)) { 10472 LOG_ERROR(BSL_LS_BCM_OAM, 10473 (BSL_META_U(unit, 10474 "OAM Error: LM counter profile ref count " 10475 "increment failed (EP=%d) - %s.\n"), 10476 h_data_p->ep_id, bcm_errmsg(rv))); 10477 return (rv); 10478 } 10479 /* Allocate 8 consecutive couters from the pool */ 10480 rv = shr_aidxres_list_reserve_block(ctr_pool[1], 10481 h_data_p->rx_ctr, 8); 10482 if (BCM_FAILURE(rv)) { 10483 LOG_ERROR(BSL_LS_BCM_OAM, 10484 (BSL_META_U(unit, 10485 "OAM Error: LM counter block alloc failed " 10486 "(EP=%d) - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 10487 return (rv); 10488 } 10489 } 10490 } 10491 return (rv); 10492 } 10493 /* 10494 * Function: 10495 * _bcm_kt2_oam_endpoint_alloc 10496 * Purpose: 10497 * Allocate an endpoint memory element. 10498 * Parameters: 10499 * ep_pp - (IN/OUT) Pointer to endpoint address pointer. 10500 * Returns: 10501 * BCM_E_XXX 10502 */ 10503 STATIC int 10504 _bcm_kt2_oam_endpoint_alloc(bcm_oam_endpoint_info_t **ep_pp) 10505 { 10506 bcm_oam_endpoint_info_t *ep_p = NULL; 10507 10508 _BCM_OAM_ALLOC(ep_p, bcm_oam_endpoint_info_t, 10509 sizeof(bcm_oam_endpoint_info_t), "Endpoint info"); 10510 if (NULL == ep_p) { 10511 return (BCM_E_MEMORY); 10512 } 10513 10514 *ep_pp = ep_p; 10515 10516 return (BCM_E_NONE); 10517 10518 } 10519 10520 /* 10521 * Function: 10522 * _bcm_kt2_oam_sync 10523 * Purpose: 10524 * Store OAM configuration to level two storage cache memory. 10525 * Parameters: 10526 * unit - (IN) Device unit number 10527 * Returns: 10528 * BCM_E_XXX 10529 */ 10530 int 10531 _bcm_kt2_oam_sync(int unit) 10532 { 10533 int rv; /* Operation return status. */ 10534 _bcm_oam_control_t *oc; 10535 int alloc_size = 0; 10536 int stable_size; 10537 soc_scache_handle_t scache_handle; 10538 uint8 *oam_scache; 10539 int grp_idx; 10540 _bcm_oam_group_data_t *group_p; /* Pointer to group list. */ 10541 int group_count = 0; 10542 _bcm_oam_ep_list_t *ep_list_p = NULL; 10543 _bcm_oam_hash_data_t ep_data; 10544 int ma_offset; 10545 int idx = 0; 10546 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 10547 10548 10549 /* Get OAM module storage size. */ 10550 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 10551 10552 /* If level 2 store is not configured return from here. */ 10553 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) { 10554 return BCM_E_NONE; 10555 } 10556 10557 /* Get handle to control structure. */ 10558 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 10559 10560 _BCM_OAM_LOCK(oc); 10561 10562 /* Initialize to group array pointer. */ 10563 group_p = oc->group_info; 10564 10565 for (grp_idx = 0; grp_idx < oc->group_count; grp_idx++) { 10566 10567 /* Check if the group is in use. */ 10568 if (BCM_E_EXISTS 10569 == shr_idxres_list_elem_state(oc->group_pool, grp_idx)) { 10570 group_count++; 10571 } 10572 } 10573 alloc_size += BCM_OAM_GROUP_NAME_LENGTH * (oc->group_count); 10574 /* To store OAM group count. */ 10575 alloc_size += sizeof(int); 10576 10577 /* To store FP GID. */ 10578 alloc_size += 3 * sizeof(bcm_field_group_t); 10579 10580 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 10581 10582 /* To store EP ids */ 10583 alloc_size += (_BCM_KT2_OAM_ENDPOINT_ID_SCACHE_SIZE); 10584 10585 /* Allocate memory to store oc->eth_oam_mp_group_vlan_key */ 10586 alloc_size += sizeof(uint8); 10587 10588 /* Check if memory has already been allocated */ 10589 rv = _bcm_esw_scache_ptr_get(unit, 10590 scache_handle, 10591 0, 10592 alloc_size, 10593 &oam_scache, 10594 BCM_WB_DEFAULT_VERSION, 10595 NULL 10596 ); 10597 if (!SOC_WARM_BOOT(unit) && (BCM_E_NOT_FOUND == rv)) { 10598 rv = _bcm_esw_scache_ptr_get(unit, 10599 scache_handle, 10600 1, 10601 alloc_size, 10602 &oam_scache, 10603 BCM_WB_DEFAULT_VERSION, 10604 NULL 10605 ); 10606 if (BCM_FAILURE(rv) 10607 || (NULL == oam_scache)) { 10608 goto cleanup; 10609 } 10610 } else if (BCM_FAILURE(rv)) { 10611 goto cleanup; 10612 } 10613 10614 /* Store the FP groups */ 10615 sal_memcpy(oam_scache, &oc->vfp_group, sizeof(bcm_field_group_t)); 10616 oam_scache += sizeof(bcm_field_group_t); 10617 10618 sal_memcpy(oam_scache, &oc->fp_vp_group, sizeof(bcm_field_group_t)); 10619 oam_scache += sizeof(bcm_field_group_t); 10620 10621 sal_memcpy(oam_scache, &oc->fp_glp_group, sizeof(bcm_field_group_t)); 10622 oam_scache += sizeof(bcm_field_group_t); 10623 10624 sal_memcpy(oam_scache, &group_count, sizeof(int)); 10625 oam_scache += sizeof(int); 10626 10627 for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) 10628 { 10629 /* Check if the group is in use. */ 10630 if (BCM_E_EXISTS 10631 == shr_idxres_list_elem_state(oc->group_pool, grp_idx)) { 10632 10633 sal_memcpy(oam_scache, group_p[grp_idx].name, 10634 BCM_OAM_GROUP_NAME_LENGTH); 10635 10636 oam_scache += BCM_OAM_GROUP_NAME_LENGTH; 10637 } 10638 } 10639 10640 /* Store logical endpoint indexes 10641 Following is scache allocation for different types of EPs 10642 ----------------------------------------------------------------------- 10643 | Rx DownMEP indexes | Rx UpMEP indexes | RMEP indexes | Tx MEP indexes | 10644 ----------------------------------------------------------------------- 10645 */ 10646 sal_memset(oam_scache, 0, _BCM_KT2_OAM_ENDPOINT_ID_SCACHE_SIZE); 10647 10648 for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) 10649 { 10650 if (group_p[grp_idx].in_use == 1) { 10651 ep_list_p = *(group_p[grp_idx].ep_list); 10652 while (ep_list_p != NULL) { 10653 sal_memcpy(&ep_data, ep_list_p->ep_data_p, sizeof(_bcm_oam_hash_data_t)); 10654 if (ep_data.type == bcmOAMEndpointTypeEthernet) { 10655 10656 if (ep_data.is_remote) { 10657 sal_memcpy(oam_scache + 10658 (_BCM_KT2_OAM_RMEP_SCACHE_LOCATION(ep_data.remote_index)), 10659 &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t)); 10660 } else { 10661 if (ep_data.local_tx_enabled) { 10662 sal_memcpy(oam_scache + 10663 (_BCM_KT2_OAM_TX_MEP_SCACHE_LOCATION(ep_data.local_tx_index)), 10664 &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t)); 10665 } 10666 if (ep_data.local_rx_enabled) { 10667 if (ep_data.flags & BCM_OAM_ENDPOINT_UP_FACING) { 10668 sal_memcpy(oam_scache + 10669 (_BCM_KT2_OAM_RX_UPMEP_SCACHE_LOCATION(ep_data.local_rx_index)), 10670 &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t)); 10671 } else { 10672 _bcm_kt2_oam_ma_index_offset_get(unit, &ep_data, &ma_offset); 10673 ep_data.local_rx_index = ep_data.ma_base_index + ma_offset; 10674 sal_memcpy(oam_scache + 10675 (_BCM_KT2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ep_data.local_rx_index)), 10676 &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t)); 10677 } 10678 10679 } 10680 } 10681 } 10682 ep_list_p = ep_list_p->next; 10683 } 10684 } 10685 } 10686 oam_scache += _BCM_KT2_OAM_ENDPOINT_ID_SCACHE_SIZE; 10687 10688 sal_memcpy(oam_scache, &(oc->eth_oam_mp_group_vlan_key), sizeof(uint8)); 10689 oam_scache += sizeof(uint8); 10690 10691 for (idx = 0; idx < oc->ep_count; idx++) { 10692 h_data_p = &oc->oam_hash_data[idx]; 10693 if (ETH_TYPE(h_data_p->type) && (h_data_p->in_use)) { 10694 sal_memcpy(oam_scache, &(h_data_p->flags), sizeof(uint32)); 10695 } 10696 oam_scache += sizeof(uint32); 10697 } 10698 10699 cleanup: 10700 _BCM_OAM_UNLOCK(oc); 10701 return (BCM_E_NONE); 10702 } 10703 10704 /* 10705 * Function: 10706 * _bcm_kt2_oam_wb_group_recover 10707 * Purpose: 10708 * Recover OAM group configuration. 10709 * Parameters: 10710 * unit - (IN) BCM device number 10711 * stable_size - (IN) OAM module Level2 storage size. 10712 * oam_scache - (IN) Pointer to scache address pointer. 10713 * Returns: 10714 * BCM_E_XXX 10715 */ 10716 STATIC int 10717 _bcm_kt2_oam_wb_group_recover(int unit, int stable_size, uint8 **oam_scache) 10718 { 10719 int index; /* Hw table index. */ 10720 _bcm_oam_group_data_t *group_p; /* Group info pointer. */ 10721 maid_reduction_entry_t maid_entry; /* Group entry info. */ 10722 ma_state_entry_t ma_state_ent; /* Group state info. */ 10723 int maid_reduction_valid = 0; /* Group valid. */ 10724 int ma_state_valid = 0; /* Group state valid. */ 10725 _bcm_oam_control_t *oc; /* Pointer to Control */ 10726 /* structure. */ 10727 int rv; /* Operation return */ 10728 /* status. */ 10729 10730 /* Control lock taken by calling routine. */ 10731 /* Get OAM control structure. */ 10732 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 10733 10734 for (index = 0; index < oc->group_count; index++) { 10735 10736 rv = READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, index, 10737 &maid_entry); 10738 if (BCM_FAILURE(rv)) { 10739 LOG_ERROR(BSL_LS_BCM_OAM, 10740 (BSL_META_U(unit, 10741 "OAM Error: (GID=%d) MAID_REDUCTION table read" 10742 " failed - %s.\n"), index, bcm_errmsg(rv))); 10743 goto cleanup; 10744 } 10745 10746 rv = READ_MA_STATEm(unit, MEM_BLOCK_ANY, index, &ma_state_ent); 10747 if (BCM_FAILURE(rv)) { 10748 LOG_ERROR(BSL_LS_BCM_OAM, 10749 (BSL_META_U(unit, 10750 "OAM Error: (GID=%d) MA_STATE table read" 10751 " failed - %s.\n"), index, bcm_errmsg(rv))); 10752 goto cleanup; 10753 } 10754 10755 maid_reduction_valid 10756 = soc_MAID_REDUCTIONm_field32_get(unit, &maid_entry, VALIDf); 10757 10758 ma_state_valid 10759 = soc_MA_STATEm_field32_get(unit, &ma_state_ent, VALIDf); 10760 10761 if (maid_reduction_valid || ma_state_valid) { 10762 10763 /* Entry must be valid in both the tables, else return error. */ 10764 if (!maid_reduction_valid || !ma_state_valid) { 10765 rv = BCM_E_INTERNAL; 10766 goto cleanup; 10767 } 10768 10769 /* Get the group memory pointer. */ 10770 group_p = &oc->group_info[index]; 10771 if (1 == group_p->in_use) { 10772 rv = BCM_E_INTERNAL; 10773 goto cleanup; 10774 } 10775 10776 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) { 10777 10778 /* Set group name as zeros. */ 10779 sal_memset(group_p->name, 0, BCM_OAM_GROUP_NAME_LENGTH); 10780 10781 } else { 10782 /* Get the group name from stored info. */ 10783 sal_memcpy(group_p->name, *oam_scache, 10784 BCM_OAM_GROUP_NAME_LENGTH); 10785 *oam_scache = (*oam_scache + BCM_OAM_GROUP_NAME_LENGTH); 10786 } 10787 10788 /* Reserve the group index. */ 10789 rv = shr_idxres_list_reserve(oc->group_pool, index, index); 10790 if (BCM_FAILURE(rv)) { 10791 LOG_ERROR(BSL_LS_BCM_OAM, 10792 (BSL_META_U(unit, 10793 "OAM Error: (GID=%d) Index reserve " 10794 " failed - %s.\n"), index, bcm_errmsg(rv))); 10795 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 10796 goto cleanup; 10797 } 10798 10799 /* Create the linked list to maintain group endpoint information. */ 10800 _BCM_OAM_ALLOC((group_p->ep_list), _bcm_oam_ep_list_t *, 10801 sizeof(_bcm_oam_ep_list_t *), "EP list head"); 10802 if (NULL == group_p->ep_list) { 10803 rv = BCM_E_MEMORY; 10804 goto cleanup; 10805 } 10806 10807 /* Initialize head node.*/ 10808 *group_p->ep_list = NULL; 10809 } 10810 } 10811 10812 return (BCM_E_NONE); 10813 10814 cleanup: 10815 10816 if (BCM_E_EXISTS 10817 == shr_idxres_list_elem_state(oc->group_pool, index)) { 10818 shr_idxres_list_free(oc->group_pool, index); 10819 } 10820 10821 return (rv); 10822 10823 } 10824 10825 /* 10826 * Function: 10827 * _bcm_kt2_oam_rmep_recover 10828 * Purpose: 10829 * Recover OAM remote endpoint configuration. 10830 * Parameters: 10831 * unit - (IN) BCM device number 10832 * index - (IN) Remote MEP hardware index. 10833 * l3_entry - (IN) RMEP view table entry pointer. 10834 * Returns: 10835 * BCM_E_XXX 10836 */ 10837 STATIC int 10838 _bcm_kt2_oam_rmep_recover(int unit, 10839 int index, 10840 l3_entry_1_entry_t *l3_entry, 10841 uint8 **scache, 10842 uint16 recovered_ver) 10843 { 10844 rmep_entry_t rmep_entry; /* Remote table entry. */ 10845 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 10846 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 10847 int rv; /* Operation return status. */ 10848 bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information. */ 10849 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 10850 int ep_id; /* Endpoint ID. */ 10851 int rmep_index; /* Index of RMEP table */ 10852 10853 LOG_DEBUG(BSL_LS_BCM_OAM, 10854 (BSL_META_U(unit, 10855 "OAM Info: _bcm_kt2_oam_rmep_recover.\n"))); 10856 /* 10857 * Get OAM control structure. 10858 * Note: Lock taken by calling routine. 10859 */ 10860 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 10861 10862 rmep_index = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, RMEP__RMEP_PTRf); 10863 10864 if (recovered_ver >= BCM_WB_VERSION_1_3) { 10865 /* Recover EP index from scache */ 10866 sal_memcpy(&ep_id, *scache + (_BCM_KT2_OAM_RMEP_SCACHE_LOCATION(rmep_index)), 10867 sizeof(bcm_oam_endpoint_t)); 10868 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id); 10869 if (BCM_FAILURE(rv)) { 10870 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 10871 LOG_ERROR(BSL_LS_BCM_OAM, 10872 (BSL_META_U(unit, 10873 "OAM Error: (EP_ID=%d) Index reserve " 10874 " failed - %s.\n"), ep_id, bcm_errmsg(rv))); 10875 return (rv); 10876 } 10877 10878 } else { 10879 10880 /* Allocate the next available endpoint index. */ 10881 rv = shr_idxres_list_alloc(oc->mep_pool, 10882 (shr_idxres_element_t *)&ep_id); 10883 if (BCM_FAILURE(rv)) { 10884 LOG_ERROR(BSL_LS_BCM_OAM, 10885 (BSL_META_U(unit, 10886 "OAM Error: Endpoint alloc (EP=%d) - %s.\n"), 10887 ep_id, bcm_errmsg(rv))); 10888 return (rv); 10889 } 10890 } 10891 10892 h_data_p = &oc->oam_hash_data[ep_id]; 10893 if (1 == h_data_p->in_use) { 10894 return(BCM_E_INTERNAL); 10895 } 10896 10897 /* 10898 * Clear the hash data element contents before 10899 * storing values. 10900 */ 10901 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 10902 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 10903 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 10904 h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX; 10905 h_data_p->profile_index = _BCM_OAM_INVALID_INDEX; 10906 h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 10907 h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 10908 h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 10909 h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 10910 h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 10911 h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 10912 h_data_p->trunk_id = BCM_TRUNK_INVALID; 10913 h_data_p->gport = 0; 10914 /* Get RMEP table index from LMEP view entry. */ 10915 h_data_p->remote_index 10916 = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, RMEP__RMEP_PTRf); 10917 10918 /* Get RMEP table entry contents. */ 10919 rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index, &rmep_entry); 10920 if (BCM_FAILURE(rv)) { 10921 LOG_ERROR(BSL_LS_BCM_OAM, 10922 (BSL_META_U(unit, 10923 "OAM Error: RMEP (index=%d) read failed - %s.\n"), 10924 h_data_p->remote_index, bcm_errmsg(rv))); 10925 goto cleanup; 10926 } 10927 10928 /* Has to be a valid RMEP, return error otherwise. */ 10929 if (!soc_RMEPm_field32_get(unit, &rmep_entry, VALIDf)) { 10930 rv = BCM_E_INTERNAL; 10931 goto cleanup; 10932 } 10933 10934 h_data_p->ep_id = ep_id; 10935 10936 h_data_p->is_remote = 1; 10937 10938 h_data_p->flags |= BCM_OAM_ENDPOINT_REMOTE; 10939 10940 h_data_p->group_index 10941 = soc_RMEPm_field32_get(unit, &rmep_entry, MAID_INDEXf); 10942 10943 h_data_p->period 10944 = _bcm_kt2_oam_ccm_hw_encode_to_msecs 10945 ((int) soc_RMEPm_field32_get(unit, &rmep_entry, 10946 RMEP_RECEIVED_CCMf)); 10947 10948 h_data_p->name 10949 = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, RMEP__MEPIDf); 10950 10951 h_data_p->local_tx_index = _BCM_OAM_INVALID_INDEX; 10952 h_data_p->local_rx_index = _BCM_OAM_INVALID_INDEX; 10953 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 10954 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 10955 10956 rv = shr_idxres_list_reserve(oc->rmep_pool, 10957 h_data_p->remote_index, 10958 h_data_p->remote_index); 10959 if (BCM_FAILURE(rv)) { 10960 LOG_ERROR(BSL_LS_BCM_OAM, 10961 (BSL_META_U(unit, 10962 "OAM Error: (RMEP=%d) Index reserve failed - %s.\n"), 10963 h_data_p->remote_index, bcm_errmsg(rv))); 10964 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 10965 goto cleanup; 10966 } 10967 10968 h_data_p->in_use = 1; 10969 10970 rv = _bcm_kt2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id); 10971 if (BCM_FAILURE(rv)) { 10972 goto cleanup; 10973 } 10974 10975 rv = _bcm_kt2_oam_endpoint_alloc(&ep_info); 10976 if (BCM_FAILURE(rv)) { 10977 _bcm_kt2_oam_group_ep_list_remove(unit, h_data_p->group_index, ep_id); 10978 goto cleanup; 10979 } 10980 10981 bcm_oam_endpoint_info_t_init(ep_info); 10982 10983 /* Set up endpoint information for key construction. */ 10984 ep_info->group = h_data_p->group_index; 10985 ep_info->name = h_data_p->name; 10986 ep_info->gport = h_data_p->gport; 10987 ep_info->id= h_data_p->ep_id; 10988 /* Calculate hash key for hash table insert operation. */ 10989 _bcm_kt2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 10990 10991 if ((recovered_ver < BCM_WB_VERSION_1_5) 10992 || (!ETH_TYPE(h_data_p->type))) { 10993 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 10994 if (BCM_FAILURE(rv)) { 10995 LOG_ERROR(BSL_LS_BCM_OAM, 10996 (BSL_META_U(unit, 10997 "OAM Error: Hash table insert failed " 10998 "EP=%d %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 10999 _bcm_kt2_oam_group_ep_list_remove(unit, h_data_p->group_index, ep_id); 11000 goto cleanup; 11001 } else { 11002 LOG_DEBUG(BSL_LS_BCM_OAM, 11003 (BSL_META_U(unit, 11004 "OAM Info: Hash Tbl (EP=%d) inserted" 11005 " - %s.\n"), ep_id, bcm_errmsg(rv))); 11006 } 11007 } 11008 11009 /* Add the H/w index to logical index mapping for RMEP */ 11010 oc->remote_endpoints[h_data_p->remote_index] = ep_info->id; 11011 11012 sal_free(ep_info); 11013 11014 LOG_DEBUG(BSL_LS_BCM_OAM, 11015 (BSL_META_U(unit, 11016 "OAM Info: _bcm_kt2_oam_rmep_recover - done.\n"))); 11017 11018 return (rv); 11019 11020 cleanup: 11021 11022 if (NULL != ep_info) { 11023 sal_free(ep_info); 11024 } 11025 11026 /* Release the endpoint ID if in use. */ 11027 if (BCM_E_EXISTS 11028 == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) { 11029 shr_idxres_list_free(oc->mep_pool, ep_id); 11030 } 11031 11032 /* Release the remote index if in use. */ 11033 if ((1 == h_data_p->in_use) 11034 && (BCM_E_EXISTS 11035 == shr_idxres_list_elem_state(oc->rmep_pool, 11036 h_data_p->remote_index))) { 11037 shr_idxres_list_free(oc->rmep_pool, h_data_p->remote_index); 11038 11039 } 11040 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 11041 11042 LOG_DEBUG(BSL_LS_BCM_OAM, 11043 (BSL_META_U(unit, 11044 "OAM Info: _bcm_kt2_oam_rmep_recover - error_done.\n"))); 11045 return (rv); 11046 } 11047 11048 /* 11049 * Function: 11050 * _bcm_kt2_oam_port_lmep_rx_config_recover 11051 * Purpose: 11052 * Recover OAM local endpoint Rx configuration for port based DownMEPs. 11053 * Parameters: 11054 * unit - (IN) BCM device number 11055 * index - (IN) Port entry hardware index. 11056 * port_entry - (IN) port table entry pointer. 11057 * Returns: 11058 * BCM_E_XXX 11059 */ 11060 STATIC int 11061 _bcm_kt2_oam_port_lmep_rx_config_recover(int unit, 11062 int index, 11063 port_tab_entry_t *port_entry, 11064 uint8 **scache, 11065 uint16 recovered_ver) 11066 { 11067 11068 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 11069 ma_index_entry_t ma_idx_entry; /* MA_INDEX table entry. */ 11070 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 11071 uint8 mdl_bitmap; /* Endpoint domain level bitmap. */ 11072 uint8 mdl; /* Maintenance domain level. */ 11073 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 11074 int rv, tmp_rv; /* Operation return status. */ 11075 _bcm_gport_dest_t gport_dest; /* Gport specification. */ 11076 bcm_gport_t gport; /* Gport value. */ 11077 int ep_id; /* Endpoint ID. */ 11078 bcm_module_t my_modid; 11079 int stm_index = 0; 11080 source_trunk_map_table_entry_t stm_entry; 11081 bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information. */ 11082 int ma_offset = 0; 11083 int ma_idx_entry_count = 0; 11084 shr_idxres_list_handle_t pool = NULL; 11085 int ma_idx; /* MA_TABLE index */ 11086 int ma_base_idx = 0; 11087 LOG_DEBUG(BSL_LS_BCM_OAM, 11088 (BSL_META_U(unit, 11089 "OAM Info: _bcm_kt2_oam_port_lmep_rx_config_recover .\n"))); 11090 /* 11091 * Get OAM control structure. 11092 * Note: Lock taken by calling routine. 11093 */ 11094 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 11095 11096 /* recover port based DownMEPs */ 11097 mdl_bitmap = soc_PORT_TABm_field32_get(unit, port_entry, MDL_BITMAPf); 11098 for (mdl = 0; mdl < _BCM_OAM_EP_LEVEL_COUNT; mdl++) { 11099 11100 if (mdl_bitmap & (1 << mdl)) { 11101 if (recovered_ver >= BCM_WB_VERSION_1_3) { 11102 11103 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 11104 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, 11105 my_modid, index, &stm_index)); 11106 SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_TABLEm(unit, 11107 MEM_BLOCK_ANY, stm_index, &stm_entry)); 11108 ma_base_idx = 11109 soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm_entry, 11110 MA_BASE_PTRf); 11111 11112 ma_idx = ma_base_idx + ma_offset; 11113 sal_memcpy(&ep_id, *(scache) + (_BCM_KT2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ma_idx)), 11114 sizeof(bcm_oam_endpoint_t)); 11115 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id); 11116 if (BCM_FAILURE(rv)) { 11117 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 11118 LOG_ERROR(BSL_LS_BCM_OAM, 11119 (BSL_META_U(unit, 11120 "OAM Error: (EP_ID=%d) Index reserve " 11121 " failed - %s.\n"), ep_id, bcm_errmsg(rv))); 11122 return (rv); 11123 } 11124 } else { 11125 /* Allocate the next available endpoint index. */ 11126 rv = shr_idxres_list_alloc(oc->mep_pool, 11127 (shr_idxres_element_t *)&ep_id); 11128 if (BCM_FAILURE(rv)) { 11129 LOG_ERROR(BSL_LS_BCM_OAM, 11130 (BSL_META_U(unit, 11131 "OAM Error: Endpoint alloc (EP=%d) - %s.\n"), 11132 ep_id, bcm_errmsg(rv))); 11133 goto cleanup; 11134 } 11135 } 11136 h_data_p = &oc->oam_hash_data[ep_id]; 11137 if (1 == h_data_p->in_use) { 11138 rv = BCM_E_INTERNAL; 11139 goto cleanup; 11140 } 11141 /* 11142 * Clear the hash data element contents before 11143 * storing values. 11144 */ 11145 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 11146 _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p); 11147 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 11148 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 11149 h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX; 11150 h_data_p->profile_index = _BCM_OAM_INVALID_INDEX; 11151 h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 11152 h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 11153 h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 11154 h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 11155 h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 11156 h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 11157 11158 11159 h_data_p->ep_id = ep_id; 11160 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 11161 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, 11162 my_modid, index, &stm_index)); 11163 SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_TABLEm(unit, 11164 MEM_BLOCK_ANY, stm_index, &stm_entry)); 11165 h_data_p->ma_base_index = 11166 soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm_entry, 11167 MA_BASE_PTRf); 11168 h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset; 11169 ma_offset++; 11170 11171 rv = READ_MA_INDEXm(unit, MEM_BLOCK_ANY, 11172 h_data_p->local_rx_index, &ma_idx_entry); 11173 if (BCM_FAILURE(rv)) { 11174 LOG_ERROR(BSL_LS_BCM_OAM, 11175 (BSL_META_U(unit, 11176 "OAM Error: MA_INDEX(index:%d) " 11177 "read failed -" " %s.\n"), 11178 h_data_p->local_rx_index, bcm_errmsg(rv))); 11179 goto cleanup; 11180 } 11181 11182 h_data_p->in_use = 1; 11183 h_data_p->is_remote = 0; 11184 h_data_p->local_rx_enabled = 1; 11185 h_data_p->flags |= BCM_OAM_ENDPOINT_CCM_RX; 11186 h_data_p->group_index 11187 = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf); 11188 11189 h_data_p->profile_index 11190 = soc_MA_INDEXm_field32_get 11191 (unit, &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf); 11192 11193 rv = soc_profile_mem_reference(unit, &oc->oam_opcode_control_profile, 11194 h_data_p->profile_index, 1); 11195 if (BCM_FAILURE(rv)) { 11196 LOG_ERROR(BSL_LS_BCM_OAM, 11197 (BSL_META_U(unit, 11198 "OAM Error: Profile entry recover failed " 11199 "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv))); 11200 goto cleanup; 11201 } 11202 h_data_p->name = 0xffff; 11203 h_data_p->level = mdl; 11204 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 11205 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 11206 h_data_p->oam_domain = 0; 11207 11208 /* Generic logical port type, construct gport from GLP. */ 11209 _bcm_gport_dest_t_init(&gport_dest); 11210 11211 gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 11212 gport_dest.modid = my_modid; 11213 gport_dest.port = index; 11214 h_data_p->sglp = index; 11215 11216 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport); 11217 if (BCM_FAILURE(rv)) { 11218 LOG_ERROR(BSL_LS_BCM_OAM, 11219 (BSL_META_U(unit, 11220 "OAM Error: Gport construct failed -" 11221 " %s.\n"), bcm_errmsg(rv))); 11222 goto cleanup; 11223 } 11224 h_data_p->gport = gport; 11225 11226 rv = _bcm_kt2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id); 11227 if (BCM_FAILURE(rv)) { 11228 goto cleanup; 11229 } 11230 11231 rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_add(unit, h_data_p); 11232 if (BCM_FAILURE(rv)) { 11233 LOG_ERROR(BSL_LS_BCM_OAM, 11234 (BSL_META_U(unit, 11235 "OAM(unit %d) Error: Remove mapping from ma_idx_to_ep_id list (EP=%d) -" 11236 " %s.\n"), unit, ep_id, bcm_errmsg(rv))); 11237 _bcm_kt2_oam_group_ep_list_remove(unit, 11238 h_data_p->group_index, 11239 ep_id); 11240 goto cleanup; 11241 } 11242 11243 rv = _bcm_kt2_oam_endpoint_alloc(&ep_info); 11244 if (BCM_FAILURE(rv)) { 11245 _bcm_kt2_oam_group_ep_list_remove(unit, 11246 h_data_p->group_index, 11247 ep_id); 11248 goto cleanup; 11249 } 11250 11251 bcm_oam_endpoint_info_t_init(ep_info); 11252 11253 /* Set up endpoint information for key construction. */ 11254 ep_info->group = h_data_p->group_index; 11255 ep_info->name = h_data_p->name; 11256 ep_info->gport = h_data_p->gport; 11257 ep_info->level = h_data_p->level; 11258 ep_info->vlan = 0; 11259 ep_info->inner_vlan = 0; 11260 11261 if ((recovered_ver < BCM_WB_VERSION_1_5) 11262 || (!ETH_TYPE(h_data_p->type))) { 11263 /* 11264 * Calculate hash key for hash table insert 11265 * operation. 11266 */ 11267 _bcm_kt2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 11268 11269 11270 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 11271 if (BCM_FAILURE(rv)) { 11272 LOG_ERROR(BSL_LS_BCM_OAM, 11273 (BSL_META_U(unit, 11274 "OAM Error: Hash table insert" 11275 " (EP=%d) failed - %s.\n"), 11276 h_data_p->ep_id, bcm_errmsg(rv))); 11277 11278 _bcm_kt2_oam_group_ep_list_remove(unit, 11279 h_data_p->group_index, 11280 ep_id); 11281 goto cleanup; 11282 } else { 11283 LOG_DEBUG(BSL_LS_BCM_OAM, 11284 (BSL_META_U(unit, 11285 "OAM Info: Hash Tbl (EP=%d)" 11286 " inserted - %s.\n"), ep_id, 11287 bcm_errmsg(rv))); 11288 } 11289 } 11290 sal_free(ep_info); 11291 ep_info = NULL; 11292 } 11293 } /* end of for loop */ 11294 if (mdl_bitmap) { 11295 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p, 11296 &ma_idx_entry_count,&pool)); 11297 rv = shr_idxres_list_reserve(pool, 11298 h_data_p->ma_base_index, 11299 h_data_p->ma_base_index + ma_idx_entry_count -1); 11300 if (BCM_FAILURE(rv)) { 11301 LOG_ERROR(BSL_LS_BCM_OAM, 11302 (BSL_META_U(unit, 11303 "OAM Error: (LMEP=%d) MA Index reserve " 11304 "failed" " - %s.\n"), h_data_p->ma_base_index, 11305 bcm_errmsg(rv))); 11306 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 11307 goto cleanup; 11308 } 11309 } 11310 11311 LOG_DEBUG(BSL_LS_BCM_OAM, 11312 (BSL_META_U(unit, 11313 "OAM Info: _bcm_kt2_oam_lmep_rx_config_recover" 11314 " - done.\n"))); 11315 return (BCM_E_NONE); 11316 11317 cleanup: 11318 /* Lets not check return value of delete during cleanup */ 11319 tmp_rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p); 11320 if (BCM_FAILURE(tmp_rv)) { 11321 LOG_DEBUG(BSL_LS_BCM_OAM, 11322 (BSL_META_U(unit, 11323 "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) " 11324 "during cleanup - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 11325 } 11326 11327 if (NULL != ep_info) { 11328 sal_free(ep_info); 11329 } 11330 11331 if (BCM_E_EXISTS 11332 == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) { 11333 shr_idxres_list_free(oc->mep_pool, ep_id); 11334 } 11335 if (NULL != h_data_p 11336 && (BCM_E_EXISTS 11337 == shr_idxres_list_elem_state(pool, 11338 h_data_p->ma_base_index))) { 11339 shr_idxres_list_free(pool, h_data_p->ma_base_index); 11340 } 11341 if (NULL != h_data_p) { 11342 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 11343 } 11344 11345 LOG_DEBUG(BSL_LS_BCM_OAM, 11346 (BSL_META_U(unit, 11347 "OAM Info: _bcm_kt2_oam_lmep_rx_config_recover" 11348 " - error_done.\n"))); 11349 return (rv); 11350 11351 } 11352 11353 /* 11354 * Function: 11355 * _bcm_kt2_oam_lmep_upmep_rx_config_recover 11356 * Purpose: 11357 * Recover OAM local endpoint Rx configuration for UpMEPS. 11358 * Parameters: 11359 * unit - (IN) BCM device number 11360 * index - (IN) Remote MEP hardware index. 11361 * egr_mp_grp_entry - (IN) Egress MP group table entry pointer. 11362 * Returns: 11363 * BCM_E_XXX 11364 */ 11365 STATIC int 11366 _bcm_kt2_oam_lmep_upmep_rx_config_recover(int unit, 11367 int index, 11368 egr_mp_group_entry_t *egr_mp_grp_entry, 11369 uint8 **scache, 11370 uint16 recovered_ver) 11371 { 11372 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 11373 ma_index_entry_t ma_idx_entry; /* MA_INDEX table entry. */ 11374 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 11375 uint8 mdl_bitmap; /* Endpoint domain level bitmap. */ 11376 uint8 mdl; /* Maintenance domain level. */ 11377 int rv, tmp_rv; /* Operation return status. */ 11378 _bcm_gport_dest_t gport_dest; /* Gport specification. */ 11379 bcm_gport_t gport; /* Gport value. */ 11380 uint16 glp; /* Generic logical port value. */ 11381 int ep_id; /* Endpoint ID. */ 11382 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 11383 bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information. */ 11384 int lmep_type = 0; 11385 int timestamp_type = 0; 11386 int ma_offset = 0; 11387 int ma_base_idx = 0; 11388 int ma_idx = 0; 11389 l3_entry_1_entry_t l3_entry; 11390 int l3_index = -1; 11391 uint8 mdl_mip = 0; 11392 11393 LOG_DEBUG(BSL_LS_BCM_OAM, 11394 (BSL_META_U(unit, 11395 "OAM Info: _bcm_kt2_oam_lmep_upmep_rx_config_recover .\n"))); 11396 /* 11397 * Get OAM control structure. 11398 * Note: Lock taken by calling routine. 11399 */ 11400 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 11401 11402 /* recover UpMEPs */ 11403 mdl_bitmap 11404 = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, MDL_BITMAP_ACTIVEf); 11405 11406 for (mdl = 0; mdl < _BCM_OAM_EP_LEVEL_COUNT; mdl++) { 11407 11408 if (mdl_bitmap & (1 << mdl)) { 11409 if (recovered_ver >= BCM_WB_VERSION_1_3) { 11410 11411 ma_base_idx = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, 11412 MA_BASE_PTRf); 11413 11414 ma_idx = ma_base_idx + ma_offset; 11415 11416 sal_memcpy(&ep_id, *(scache) + (_BCM_KT2_OAM_RX_UPMEP_SCACHE_LOCATION(ma_idx)), 11417 sizeof(bcm_oam_endpoint_t)); 11418 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id); 11419 if (BCM_FAILURE(rv)) { 11420 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 11421 LOG_ERROR(BSL_LS_BCM_OAM, 11422 (BSL_META_U(unit, 11423 "OAM Error: (EP_ID=%d) Index reserve " 11424 " failed - %s.\n"), ep_id, bcm_errmsg(rv))); 11425 return (rv); 11426 } 11427 } else { 11428 /* Allocate the next available endpoint index. */ 11429 rv = shr_idxres_list_alloc(oc->mep_pool, 11430 (shr_idxres_element_t *)&ep_id); 11431 if (BCM_FAILURE(rv)) { 11432 LOG_ERROR(BSL_LS_BCM_OAM, 11433 (BSL_META_U(unit, 11434 "OAM Error: Endpoint alloc (EP=%d) - %s.\n"), 11435 ep_id, bcm_errmsg(rv))); 11436 goto cleanup; 11437 } 11438 } 11439 h_data_p = &oc->oam_hash_data[ep_id]; 11440 if (1 == h_data_p->in_use) { 11441 rv = BCM_E_INTERNAL; 11442 goto cleanup; 11443 } 11444 11445 /* 11446 * Clear the hash data element contents before 11447 * storing values. 11448 */ 11449 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 11450 _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p); 11451 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 11452 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 11453 h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX; 11454 h_data_p->profile_index = _BCM_OAM_INVALID_INDEX; 11455 h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 11456 h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 11457 h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 11458 h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 11459 h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 11460 h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 11461 h_data_p->trunk_id = BCM_TRUNK_INVALID; 11462 11463 h_data_p->ep_id = ep_id; 11464 h_data_p->ma_base_index = 11465 (soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, 11466 MA_BASE_PTRf)); 11467 h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset; 11468 ma_offset++; 11469 11470 rv = READ_EGR_MA_INDEXm(unit, MEM_BLOCK_ANY, 11471 h_data_p->local_rx_index, &ma_idx_entry); 11472 if (BCM_FAILURE(rv)) { 11473 LOG_ERROR(BSL_LS_BCM_OAM, 11474 (BSL_META_U(unit, 11475 "OAM Error: EGR_MA_INDEX(index:%d) " 11476 "read failed -" " %s.\n"), 11477 h_data_p->local_rx_index, bcm_errmsg(rv))); 11478 goto cleanup; 11479 } 11480 11481 h_data_p->flags |= BCM_OAM_ENDPOINT_UP_FACING; 11482 h_data_p->in_use = 1; 11483 h_data_p->is_remote = 0; 11484 h_data_p->local_rx_enabled = 1; 11485 h_data_p->flags |= BCM_OAM_ENDPOINT_CCM_RX; 11486 h_data_p->group_index 11487 = soc_EGR_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf); 11488 11489 h_data_p->profile_index 11490 = soc_EGR_MA_INDEXm_field32_get 11491 (unit, &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf); 11492 11493 rv = soc_profile_mem_reference(unit, &oc->egr_oam_opcode_control_profile, 11494 h_data_p->profile_index, 1); 11495 if (BCM_FAILURE(rv)) { 11496 LOG_ERROR(BSL_LS_BCM_OAM, 11497 (BSL_META_U(unit, 11498 "OAM Error: Profile entry recover failed " 11499 "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv))); 11500 goto cleanup; 11501 } 11502 11503 h_data_p->dglp1_profile_index = 11504 soc_MA_INDEXm_field32_get 11505 (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf); 11506 rv = soc_profile_mem_reference(unit, &oc->egr_oam_dglp_profile, 11507 h_data_p->dglp1_profile_index, 1); 11508 if (BCM_FAILURE(rv)) { 11509 LOG_ERROR(BSL_LS_BCM_OAM, 11510 (BSL_META_U(unit, 11511 "OAM Error: DGLP profile ref count " 11512 "increment failed (EP=%d) - %s.\n"), 11513 h_data_p->ep_id, bcm_errmsg(rv))); 11514 goto cleanup; 11515 } 11516 h_data_p->dglp2_profile_index = 11517 soc_MA_INDEXm_field32_get 11518 (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf); 11519 rv = soc_profile_mem_reference(unit, &oc->egr_oam_dglp_profile, 11520 h_data_p->dglp2_profile_index, 1); 11521 if (BCM_FAILURE(rv)) { 11522 LOG_ERROR(BSL_LS_BCM_OAM, 11523 (BSL_META_U(unit, 11524 "OAM Error: DGLP profile ref count " 11525 "increment failed (EP=%d) - %s.\n"), 11526 h_data_p->ep_id, bcm_errmsg(rv))); 11527 goto cleanup; 11528 } 11529 #if defined(INCLUDE_BHH) 11530 h_data_p->cpu_qid 11531 = soc_EGR_MA_INDEXm_field32_get(unit, &ma_idx_entry, INT_PRIf); 11532 #endif 11533 h_data_p->name = 0xffff; 11534 h_data_p->level = mdl; 11535 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 11536 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 11537 /* recover counters */ 11538 rv = _bcm_kt2_oam_rx_counter_recover(unit, EGR_MP_GROUPm, 11539 (uint32 *)egr_mp_grp_entry, h_data_p); 11540 if (BCM_FAILURE(rv)) { 11541 LOG_ERROR(BSL_LS_BCM_OAM, 11542 (BSL_META_U(unit, 11543 "OAM Error: LM RX counter recover failed " 11544 "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv))); 11545 goto cleanup; 11546 } 11547 /* rx and tx counters are located at same index, but on diff mem */ 11548 if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) { 11549 h_data_p->tx_ctr = h_data_p->rx_ctr; 11550 } 11551 11552 /* time stamp */ 11553 timestamp_type = soc_EGR_MP_GROUPm_field32_get(unit, 11554 egr_mp_grp_entry, TIMESTAMP_TYPEf); 11555 if (timestamp_type) { 11556 h_data_p->ts_format = timestamp_type; 11557 } 11558 h_data_p->oam_domain = soc_EGR_MP_GROUPm_field32_get(unit, 11559 egr_mp_grp_entry, KEY_TYPEf); 11560 11561 switch (h_data_p->oam_domain) { 11562 case _BCM_OAM_DOMAIN_CVLAN: 11563 h_data_p->flags |= BCM_OAM_ENDPOINT_MATCH_INNER_VLAN; 11564 h_data_p->inner_vlan = soc_EGR_MP_GROUPm_field32_get(unit, 11565 egr_mp_grp_entry, CVIDf); 11566 break; 11567 11568 case _BCM_OAM_DOMAIN_SVLAN: 11569 h_data_p->vlan = soc_EGR_MP_GROUPm_field32_get(unit, 11570 egr_mp_grp_entry, SVIDf); 11571 break; 11572 11573 case _BCM_OAM_DOMAIN_S_PLUS_CVLAN: 11574 h_data_p->vlan = soc_EGR_MP_GROUPm_field32_get(unit, 11575 egr_mp_grp_entry, SVIDf); 11576 h_data_p->inner_vlan = soc_EGR_MP_GROUPm_field32_get(unit, 11577 egr_mp_grp_entry, CVIDf); 11578 h_data_p->flags |= BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN; 11579 break; 11580 11581 case _BCM_OAM_DOMAIN_VP: 11582 h_data_p->vp = soc_EGR_MP_GROUPm_field32_get(unit, 11583 egr_mp_grp_entry, DVPf); 11584 h_data_p->int_flags |= _BCM_OAM_ENDPOINT_IS_VP_BASED; 11585 break; 11586 default : 11587 break; 11588 11589 } 11590 11591 glp = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, DGLPf); 11592 11593 lmep_type = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, 11594 KEY_TYPEf); 11595 11596 if (lmep_type == _BCM_OAM_DOMAIN_VP) { 11597 #if defined(INCLUDE_L3) 11598 if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMim)) { 11599 11600 BCM_GPORT_MIM_PORT_ID_SET(h_data_p->gport, h_data_p->vp); 11601 11602 } else if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMpls)) { 11603 11604 BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp); 11605 11606 } else { 11607 LOG_ERROR(BSL_LS_BCM_OAM, 11608 (BSL_META_U(unit, 11609 "OAM Error: Invalid Virtual Port (SVP=%d)" 11610 " - %s.\n"), h_data_p->vp, 11611 bcm_errmsg(BCM_E_INTERNAL))); 11612 return (BCM_E_INTERNAL); 11613 } 11614 #endif 11615 } else { 11616 /* 11617 * Generic logical port type, construct gport from GLP. 11618 */ 11619 h_data_p->dglp = glp; 11620 11621 _bcm_gport_dest_t_init(&gport_dest); 11622 11623 if (_BCM_OAM_GLP_TRUNK_BIT_GET(glp)) { 11624 gport_dest.tgid = _BCM_OAM_GLP_TRUNK_ID_GET(glp); 11625 gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 11626 h_data_p->trunk_id = _BCM_OAM_GLP_TRUNK_ID_GET(glp); 11627 } else { 11628 gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 11629 gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(glp); 11630 gport_dest.port = _BCM_OAM_GLP_PORT_GET(glp); 11631 } 11632 11633 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport); 11634 if (BCM_FAILURE(rv)) { 11635 LOG_ERROR(BSL_LS_BCM_OAM, 11636 (BSL_META_U(unit, 11637 "OAM Error: Gport construct failed -" 11638 " %s.\n"), bcm_errmsg(rv))); 11639 goto cleanup; 11640 } 11641 11642 h_data_p->gport = gport; 11643 } 11644 h_data_p->dglp = glp; 11645 h_data_p->sglp = glp; 11646 11647 sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t)); 11648 L3_LOCK(unit); 11649 if (BCM_SUCCESS 11650 (_bcm_kt2_oam_find_lmep(unit, h_data_p, 11651 &l3_index, &l3_entry))) { 11652 mdl_mip = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, 11653 LMEP__MDL_BITMAP_PASSIVEf); 11654 } 11655 L3_UNLOCK(unit); 11656 11657 if (!(mdl_mip & (1 << h_data_p->level))) { 11658 /* Set the MIP flag */ 11659 h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE; 11660 } 11661 11662 rv = _bcm_kt2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id); 11663 if (BCM_FAILURE(rv)) { 11664 goto cleanup; 11665 } 11666 11667 rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_add(unit, h_data_p); 11668 if (BCM_FAILURE(rv)) { 11669 LOG_ERROR(BSL_LS_BCM_OAM, 11670 (BSL_META_U(unit, 11671 "OAM(unit %d) Error: Add mapping from ma_idx_to_ep_id list (EP=%d) -" 11672 " %s.\n"), unit, ep_id, bcm_errmsg(rv))); 11673 _bcm_kt2_oam_group_ep_list_remove(unit, 11674 h_data_p->group_index, 11675 ep_id); 11676 goto cleanup; 11677 } 11678 11679 11680 rv = _bcm_kt2_oam_endpoint_alloc(&ep_info); 11681 if (BCM_FAILURE(rv)) { 11682 _bcm_kt2_oam_group_ep_list_remove(unit, 11683 h_data_p->group_index, 11684 ep_id); 11685 goto cleanup; 11686 } 11687 11688 bcm_oam_endpoint_info_t_init(ep_info); 11689 11690 /* Set up endpoint information for key construction. */ 11691 ep_info->group = h_data_p->group_index; 11692 ep_info->name = h_data_p->name; 11693 ep_info->gport = h_data_p->gport; 11694 ep_info->level = h_data_p->level; 11695 ep_info->vlan = h_data_p->vlan; 11696 ep_info->inner_vlan = h_data_p->inner_vlan; 11697 ep_info->flags = h_data_p->flags; 11698 if ((recovered_ver < BCM_WB_VERSION_1_5) 11699 || (!ETH_TYPE(h_data_p->type))) { 11700 /* 11701 * Calculate hash key for hash table insert 11702 * operation. 11703 */ 11704 _bcm_kt2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 11705 11706 11707 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 11708 if (BCM_FAILURE(rv)) { 11709 LOG_ERROR(BSL_LS_BCM_OAM, 11710 (BSL_META_U(unit, 11711 "OAM Error: Hash table insert" 11712 " (EP=%d) failed - %s.\n"), 11713 h_data_p->ep_id, bcm_errmsg(rv))); 11714 11715 _bcm_kt2_oam_group_ep_list_remove(unit, 11716 h_data_p->group_index, 11717 ep_id); 11718 goto cleanup; 11719 } else { 11720 LOG_DEBUG(BSL_LS_BCM_OAM, 11721 (BSL_META_U(unit, 11722 "OAM Info: Hash Tbl (EP=%d)" 11723 " inserted - %s.\n"), ep_id, 11724 bcm_errmsg(rv))); 11725 } 11726 } 11727 sal_free(ep_info); 11728 ep_info = NULL; 11729 11730 } 11731 } /* end of for loop */ 11732 if (mdl_bitmap) { 11733 rv = shr_idxres_list_reserve(oc->egr_ma_idx_pool, 11734 h_data_p->ma_base_index, 11735 h_data_p->ma_base_index + 7); 11736 if (BCM_FAILURE(rv)) { 11737 LOG_ERROR(BSL_LS_BCM_OAM, 11738 (BSL_META_U(unit, 11739 "OAM Error: (LMEP=%d) EGR MA Index reserve " 11740 "failed" " - %s.\n"), h_data_p->remote_index, 11741 bcm_errmsg(rv))); 11742 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 11743 goto cleanup; 11744 } 11745 } 11746 11747 LOG_DEBUG(BSL_LS_BCM_OAM, 11748 (BSL_META_U(unit, 11749 "OAM Info: _bcm_kt2_oam_lmep_rx_config_recover" 11750 " - done.\n"))); 11751 return (BCM_E_NONE); 11752 11753 cleanup: 11754 /* Lets not check return value of delete during cleanup */ 11755 tmp_rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p); 11756 if (BCM_FAILURE(tmp_rv)) { 11757 LOG_DEBUG(BSL_LS_BCM_OAM, 11758 (BSL_META_U(unit, 11759 "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) " 11760 "during cleanup - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 11761 } 11762 11763 if (NULL != ep_info) { 11764 sal_free(ep_info); 11765 } 11766 11767 if (BCM_E_EXISTS 11768 == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) { 11769 shr_idxres_list_free(oc->mep_pool, ep_id); 11770 } 11771 /* return rx & tx counters allocated if any */ 11772 if (NULL != h_data_p) { 11773 rv =_bcm_kt2_oam_free_counter(unit, h_data_p); 11774 if (BCM_FAILURE(rv)) { 11775 LOG_ERROR(BSL_LS_BCM_OAM, 11776 (BSL_META_U(unit, 11777 "OAM Error: LM counter block " 11778 "free failed (EP=%d) - %s.\n"), 11779 ep_id, bcm_errmsg(rv))); 11780 } 11781 } 11782 if (NULL != h_data_p 11783 && (BCM_E_EXISTS 11784 == shr_idxres_list_elem_state(oc->egr_ma_idx_pool, 11785 h_data_p->ma_base_index))) { 11786 11787 shr_idxres_list_free(oc->egr_ma_idx_pool, h_data_p->ma_base_index); 11788 11789 } 11790 if (NULL != h_data_p) { 11791 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 11792 } 11793 LOG_DEBUG(BSL_LS_BCM_OAM, 11794 (BSL_META_U(unit, 11795 "OAM Info: _bcm_kt2_oam_lmep_rx_config_recover" 11796 " - error_done.\n"))); 11797 return (rv); 11798 } 11799 /* 11800 * Function: 11801 * _bcm_kt2_oam_lmep_downmep_rx_config_recover 11802 * Purpose: 11803 * Recover OAM local endpoint Rx configuration for DownMEPS. 11804 * Parameters: 11805 * unit - (IN) BCM device number 11806 * index - (IN) Remote MEP hardware index. 11807 * l3_entry - (IN) LMEP view table entry pointer. 11808 * Returns: 11809 * BCM_E_XXX 11810 */ 11811 STATIC int 11812 _bcm_kt2_oam_lmep_downmep_rx_config_recover(int unit, 11813 int index, 11814 l3_entry_1_entry_t *l3_entry, 11815 uint8 **scache, 11816 uint16 recovered_ver) 11817 { 11818 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 11819 ma_index_entry_t ma_idx_entry; /* IA_INDEX table entry. */ 11820 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 11821 uint8 mdl_bitmap; /* Endpoint domain level bitmap. */ 11822 uint8 mdl; /* Maintenance domain level. */ 11823 int rv, tmp_rv; /* Operation return status. */ 11824 _bcm_gport_dest_t gport_dest; /* Gport specification. */ 11825 bcm_gport_t gport; /* Gport value. */ 11826 uint16 glp; /* Generic logical port value. */ 11827 int ep_id; /* Endpoint ID. */ 11828 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 11829 bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information. */ 11830 int lmep_type = 0; 11831 int timestamp_type = 0; 11832 int ma_offset = 0; 11833 int ma_idx_entry_count = 0; 11834 shr_idxres_list_handle_t pool = NULL; 11835 int ma_base_idx = 0; 11836 int ma_idx = 0; 11837 egr_mp_group_entry_t egr_mp_group; 11838 int mp_grp_index = 0; 11839 uint8 mdl_mip = 0; 11840 11841 LOG_DEBUG(BSL_LS_BCM_OAM, 11842 (BSL_META_U(unit, 11843 "OAM Info: " 11844 "_bcm_kt2_oam_lmep_downmep_rx_config_recover .\n"))); 11845 /* 11846 * Get OAM control structure. 11847 * Note: Lock taken by calling routine. 11848 */ 11849 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 11850 11851 /* recover DownMEPs */ 11852 mdl_bitmap = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 11853 l3_entry, LMEP__MDL_BITMAP_ACTIVEf); 11854 11855 ma_base_idx = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, LMEP__MA_BASE_PTRf); 11856 11857 for (mdl = 0; mdl < _BCM_OAM_EP_LEVEL_COUNT; mdl++) { 11858 11859 if (mdl_bitmap & (1 << mdl)) { 11860 11861 if (recovered_ver >= BCM_WB_VERSION_1_3) { 11862 ma_idx = ma_base_idx + ma_offset; 11863 sal_memcpy(&ep_id, *(scache) + (_BCM_KT2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ma_idx)), 11864 sizeof(bcm_oam_endpoint_t)); 11865 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id); 11866 if (BCM_FAILURE(rv)) { 11867 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 11868 LOG_ERROR(BSL_LS_BCM_OAM, 11869 (BSL_META_U(unit, 11870 "OAM Error: (EP_ID=%d) Index reserve " 11871 " failed - %s.\n"), ep_id, bcm_errmsg(rv))); 11872 return (rv); 11873 } 11874 } else { 11875 /* Allocate the next available endpoint index. */ 11876 rv = shr_idxres_list_alloc(oc->mep_pool, 11877 (shr_idxres_element_t *)&ep_id); 11878 if (BCM_FAILURE(rv)) { 11879 LOG_ERROR(BSL_LS_BCM_OAM, 11880 (BSL_META_U(unit, 11881 "OAM Error: Endpoint alloc (EP=%d) - %s.\n"), 11882 ep_id, bcm_errmsg(rv))); 11883 goto cleanup; 11884 } 11885 } 11886 h_data_p = &oc->oam_hash_data[ep_id]; 11887 if (1 == h_data_p->in_use) { 11888 return(BCM_E_INTERNAL); 11889 } 11890 11891 /* 11892 * Clear the hash data element contents before 11893 * storing values. 11894 */ 11895 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 11896 11897 _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p); 11898 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 11899 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 11900 h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX; 11901 h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 11902 h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 11903 h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 11904 h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 11905 h_data_p->trunk_id = BCM_TRUNK_INVALID; 11906 11907 11908 11909 h_data_p->ep_id = ep_id; 11910 h_data_p->ma_base_index = 11911 soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, 11912 LMEP__MA_BASE_PTRf); 11913 h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset; 11914 ma_offset++; 11915 11916 rv = READ_MA_INDEXm 11917 (unit, MEM_BLOCK_ANY, h_data_p->local_rx_index, 11918 &ma_idx_entry); 11919 if (BCM_FAILURE(rv)) { 11920 LOG_ERROR(BSL_LS_BCM_OAM, 11921 (BSL_META_U(unit, 11922 "OAM Error: MA_INDEX (index:%d) read failed -" 11923 " %s.\n"), h_data_p->local_rx_index, 11924 bcm_errmsg(rv))); 11925 goto cleanup; 11926 } 11927 11928 h_data_p->in_use = 1; 11929 11930 h_data_p->is_remote = 0; 11931 11932 h_data_p->local_rx_enabled = 1; 11933 11934 h_data_p->flags |= BCM_OAM_ENDPOINT_CCM_RX; 11935 11936 h_data_p->group_index 11937 = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf); 11938 h_data_p->int_pri = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, INT_PRIf); 11939 11940 h_data_p->profile_index 11941 = soc_MA_INDEXm_field32_get 11942 (unit, &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf); 11943 rv = soc_profile_mem_reference(unit, &oc->oam_opcode_control_profile, 11944 h_data_p->profile_index, 1); 11945 if (BCM_FAILURE(rv)) { 11946 LOG_ERROR(BSL_LS_BCM_OAM, 11947 (BSL_META_U(unit, 11948 "OAM Error: Profile entry recover failed " 11949 "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv))); 11950 goto cleanup; 11951 } 11952 11953 h_data_p->dglp1_profile_index = 11954 soc_MA_INDEXm_field32_get 11955 (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf); 11956 rv = soc_profile_mem_reference(unit, &oc->ing_oam_dglp_profile, 11957 h_data_p->dglp1_profile_index, 1); 11958 if (BCM_FAILURE(rv)) { 11959 LOG_ERROR(BSL_LS_BCM_OAM, 11960 (BSL_META_U(unit, 11961 "OAM Error: DGLP profile ref count " 11962 "increment failed (EP=%d) - %s.\n"), 11963 h_data_p->ep_id, bcm_errmsg(rv))); 11964 goto cleanup; 11965 } 11966 h_data_p->dglp2_profile_index = 11967 soc_MA_INDEXm_field32_get 11968 (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf); 11969 rv = soc_profile_mem_reference(unit, &oc->ing_oam_dglp_profile, 11970 h_data_p->dglp2_profile_index, 1); 11971 if (BCM_FAILURE(rv)) { 11972 LOG_ERROR(BSL_LS_BCM_OAM, 11973 (BSL_META_U(unit, 11974 "OAM Error: DGLP profile ref count " 11975 "increment failed (EP=%d) - %s.\n"), 11976 h_data_p->ep_id, bcm_errmsg(rv))); 11977 goto cleanup; 11978 } 11979 11980 h_data_p->name = 0xffff; 11981 11982 h_data_p->level = mdl; 11983 11984 h_data_p->oam_domain = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 11985 l3_entry, 11986 LMEP__OAM_LMEP_KEY_SUBTYPEf); 11987 11988 switch (h_data_p->oam_domain) { 11989 case _BCM_OAM_DOMAIN_CVLAN: 11990 h_data_p->flags |= BCM_OAM_ENDPOINT_MATCH_INNER_VLAN; 11991 h_data_p->inner_vlan = 11992 soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 11993 l3_entry, LMEP__CVIDf); 11994 break; 11995 11996 case _BCM_OAM_DOMAIN_SVLAN: 11997 h_data_p->vlan = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 11998 l3_entry, LMEP__SVIDf); 11999 break; 12000 12001 case _BCM_OAM_DOMAIN_S_PLUS_CVLAN: 12002 h_data_p->vlan = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 12003 l3_entry, LMEP__SVIDf); 12004 h_data_p->inner_vlan = 12005 soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 12006 l3_entry, LMEP__CVIDf); 12007 h_data_p->flags |= 12008 BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN; 12009 break; 12010 12011 case _BCM_OAM_DOMAIN_VP: 12012 h_data_p->vp = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 12013 l3_entry, LMEP__SVPf); 12014 h_data_p->int_flags |= _BCM_OAM_ENDPOINT_IS_VP_BASED; 12015 break; 12016 default : 12017 break; 12018 12019 } 12020 12021 rv = _bcm_kt2_oam_rx_counter_recover(unit, 12022 L3_ENTRY_IPV4_UNICASTm, (uint32 *)l3_entry, h_data_p); 12023 if (BCM_FAILURE(rv)) { 12024 LOG_ERROR(BSL_LS_BCM_OAM, 12025 (BSL_META_U(unit, 12026 "OAM Error: LM counter recover failed " 12027 "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv))); 12028 goto cleanup; 12029 } 12030 /* rx and tx counters are located at same index, but on diff mem */ 12031 if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) { 12032 h_data_p->tx_ctr = h_data_p->rx_ctr; 12033 } 12034 12035 /* time stamp */ 12036 timestamp_type = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 12037 l3_entry, LMEP__TIMESTAMP_TYPEf); 12038 if (timestamp_type) { 12039 h_data_p->ts_format = timestamp_type; 12040 } 12041 glp = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, 12042 LMEP__SGLPf); 12043 12044 lmep_type = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, 12045 LMEP__OAM_LMEP_KEY_SUBTYPEf); 12046 12047 if (lmep_type == _BCM_OAM_DOMAIN_VP) { 12048 #if defined(INCLUDE_L3) 12049 if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMim)) { 12050 12051 BCM_GPORT_MIM_PORT_ID_SET(h_data_p->gport, h_data_p->vp); 12052 12053 } else if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMpls)) { 12054 12055 BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp); 12056 12057 } else { 12058 LOG_ERROR(BSL_LS_BCM_OAM, 12059 (BSL_META_U(unit, 12060 "OAM Error: Invalid Virtual Port (SVP=%d)" 12061 " - %s.\n"), h_data_p->vp, 12062 bcm_errmsg(BCM_E_INTERNAL))); 12063 return (BCM_E_INTERNAL); 12064 } 12065 #endif 12066 } else { 12067 /* 12068 * Generic logical port type, construct gport from GLP. 12069 */ 12070 _bcm_gport_dest_t_init(&gport_dest); 12071 12072 if (_BCM_OAM_GLP_TRUNK_BIT_GET(glp)) { 12073 gport_dest.tgid = _BCM_OAM_GLP_TRUNK_ID_GET(glp); 12074 gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 12075 h_data_p->trunk_id = _BCM_OAM_GLP_TRUNK_ID_GET(glp); 12076 } else { 12077 gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 12078 gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(glp); 12079 gport_dest.port = _BCM_OAM_GLP_PORT_GET(glp); 12080 } 12081 12082 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport); 12083 if (BCM_FAILURE(rv)) { 12084 LOG_ERROR(BSL_LS_BCM_OAM, 12085 (BSL_META_U(unit, 12086 "OAM Error: Gport construct failed -" 12087 " %s.\n"), bcm_errmsg(rv))); 12088 goto cleanup; 12089 } 12090 12091 h_data_p->gport = gport; 12092 } 12093 h_data_p->dglp = glp; 12094 h_data_p->sglp = glp; 12095 12096 sal_memset(&egr_mp_group, 0, sizeof(egr_mp_group_entry_t)); 12097 if (BCM_SUCCESS 12098 (_bcm_kt2_oam_find_egr_lmep(unit, h_data_p, 12099 &mp_grp_index, 12100 &egr_mp_group))) { 12101 mdl_mip = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, 12102 MDL_BITMAP_PASSIVEf); 12103 } 12104 12105 if (!(mdl_mip & (1 << h_data_p->level))) { 12106 /* Set the MIP flag */ 12107 h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE; 12108 } 12109 12110 rv = _bcm_kt2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id); 12111 if (BCM_FAILURE(rv)) { 12112 goto cleanup; 12113 } 12114 12115 rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_add(unit, h_data_p); 12116 if (BCM_FAILURE(rv)) { 12117 LOG_ERROR(BSL_LS_BCM_OAM, 12118 (BSL_META_U(unit, 12119 "OAM(unit %d) Error: Add mapping from ma_idx_to_ep_id list (EP=%d) -" 12120 " %s.\n"), unit, ep_id, bcm_errmsg(rv))); 12121 _bcm_kt2_oam_group_ep_list_remove(unit, 12122 h_data_p->group_index, 12123 ep_id); 12124 goto cleanup; 12125 } 12126 12127 12128 rv = _bcm_kt2_oam_endpoint_alloc(&ep_info); 12129 if (BCM_FAILURE(rv)) { 12130 _bcm_kt2_oam_group_ep_list_remove(unit, 12131 h_data_p->group_index, 12132 ep_id); 12133 goto cleanup; 12134 } 12135 12136 bcm_oam_endpoint_info_t_init(ep_info); 12137 12138 /* Set up endpoint information for key construction. */ 12139 ep_info->group = h_data_p->group_index; 12140 ep_info->name = h_data_p->name; 12141 ep_info->gport = h_data_p->gport; 12142 ep_info->level = h_data_p->level; 12143 ep_info->vlan = h_data_p->vlan; 12144 ep_info->inner_vlan = h_data_p->inner_vlan; 12145 if ((recovered_ver < BCM_WB_VERSION_1_5) 12146 || (!ETH_TYPE(h_data_p->type))) { 12147 /* 12148 * Calculate hash key for hash table insert 12149 * operation. 12150 */ 12151 _bcm_kt2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 12152 12153 12154 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 12155 if (BCM_FAILURE(rv)) { 12156 LOG_ERROR(BSL_LS_BCM_OAM, 12157 (BSL_META_U(unit, 12158 "OAM Error: Hash table insert" 12159 " (EP=%d) failed - %s.\n"), 12160 h_data_p->ep_id, bcm_errmsg(rv))); 12161 12162 _bcm_kt2_oam_group_ep_list_remove(unit, 12163 h_data_p->group_index, 12164 ep_id); 12165 goto cleanup; 12166 } else { 12167 LOG_DEBUG(BSL_LS_BCM_OAM, 12168 (BSL_META_U(unit, 12169 "OAM Info: Hash Tbl (EP=%d)" 12170 " inserted - %s.\n"), ep_id, 12171 bcm_errmsg(rv))); 12172 } 12173 } 12174 sal_free(ep_info); 12175 ep_info = NULL; 12176 } 12177 } /* end of for loop */ 12178 12179 if (mdl_bitmap) { 12180 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_ma_idx_num_entries_and_pool_get(unit, 12181 h_data_p, &ma_idx_entry_count, &pool)); 12182 rv = shr_idxres_list_reserve(pool, 12183 h_data_p->ma_base_index, 12184 h_data_p->ma_base_index + ma_idx_entry_count -1); 12185 if (BCM_FAILURE(rv)) { 12186 LOG_ERROR(BSL_LS_BCM_OAM, 12187 (BSL_META_U(unit, 12188 "OAM Error: (RMEP=%d) Index reserve failed" 12189 " - %s.\n"), h_data_p->remote_index, 12190 bcm_errmsg(rv))); 12191 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 12192 goto cleanup; 12193 } 12194 } 12195 12196 LOG_DEBUG(BSL_LS_BCM_OAM, 12197 (BSL_META_U(unit, 12198 "OAM Info: _bcm_kt2_oam_lmep_rx_config_recover" 12199 " - done.\n"))); 12200 return (BCM_E_NONE); 12201 12202 cleanup: 12203 tmp_rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p); 12204 if (BCM_FAILURE(tmp_rv)) { 12205 LOG_DEBUG(BSL_LS_BCM_OAM, 12206 (BSL_META_U(unit, 12207 "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) " 12208 "during cleanup - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 12209 } 12210 12211 12212 if (NULL != ep_info) { 12213 sal_free(ep_info); 12214 } 12215 12216 if (BCM_E_EXISTS 12217 == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) { 12218 shr_idxres_list_free(oc->mep_pool, ep_id); 12219 } 12220 /* return rx & tx counters allocated if any */ 12221 if (NULL != h_data_p) { 12222 rv =_bcm_kt2_oam_free_counter(unit, h_data_p); 12223 if (BCM_FAILURE(rv)) { 12224 LOG_ERROR(BSL_LS_BCM_OAM, 12225 (BSL_META_U(unit, 12226 "OAM Error: LM counter block " 12227 "free failed (EP=%d) - %s.\n"), 12228 ep_id, bcm_errmsg(rv))); 12229 } 12230 } 12231 if (NULL != h_data_p && (BCM_E_EXISTS 12232 == shr_idxres_list_elem_state(pool, 12233 h_data_p->ma_base_index))) { 12234 12235 shr_idxres_list_free(pool, h_data_p->ma_base_index); 12236 12237 } 12238 if (NULL != h_data_p) { 12239 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 12240 } 12241 LOG_DEBUG(BSL_LS_BCM_OAM, 12242 (BSL_META_U(unit, 12243 "OAM Info: _bcm_kt2_oam_lmep_rx_config_recover" 12244 " - error_done.\n"))); 12245 return (rv); 12246 } 12247 12248 /* 12249 * Function: 12250 * _bcm_kt2_oam_lmep_tx_config_recover 12251 * Purpose: 12252 * Recover OAM local endpoint Tx configuration. 12253 * Parameters: 12254 * unit - (IN) BCM device number 12255 * Returns: 12256 * BCM_E_XXX 12257 */ 12258 STATIC int 12259 _bcm_kt2_oam_lmep_tx_config_recover(int unit, 12260 uint8 **scache, 12261 uint16 recovered_ver) 12262 { 12263 _bcm_gport_dest_t gport_dest; /* Gport specification. */ 12264 bcm_gport_t gport; /* Gport value. */ 12265 int index; /* Hardware index. */ 12266 lmep_entry_t lmep_entry; /* LMEP table entry buffer. */ 12267 lmep_1_entry_t lmep_1_entry; /* LMEP table entry buffer. */ 12268 maid_reduction_entry_t maid_red_ent; /* MAID_REDUCTION table entry buf. */ 12269 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 12270 _bcm_oam_group_data_t *g_info_p; /* Group information pointer. */ 12271 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 12272 bcm_module_t modid; /* Module ID. */ 12273 bcm_port_t port_id; /* Port ID. */ 12274 bcm_trunk_t trunk_id; /* Trunk ID. */ 12275 uint32 grp_idx; /* Group index. */ 12276 uint16 glp; /* Generic logical port. */ 12277 uint16 vlan; /* VLAN ID. */ 12278 uint16 inner_vlan; /* Inner VLAN ID. */ 12279 uint8 level; /* Maintenance domain level. */ 12280 _bcm_oam_ep_list_t *cur; /* Current head node pointer. */ 12281 int ep_id = -1; /* Endpoint ID. */ 12282 uint8 match_found = 0; /* Matching endpoint found. */ 12283 int rv; /* Operation return status. */ 12284 bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information. */ 12285 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 12286 _bcm_oam_hash_data_t sh_data; /* Endpoint hash data pointer. */ 12287 uint32 ccm_period = 0; 12288 egr_port_entry_t egr_port_entry; 12289 uint8 mdl_mip = 0; 12290 int trunk_index = -1; 12291 int tpid_index = 0; 12292 12293 LOG_DEBUG(BSL_LS_BCM_OAM, 12294 (BSL_META_U(unit, 12295 "OAM Info: _bcm_kt2_oam_lmep_tx_config_recover.\n"))); 12296 12297 /* 12298 * Get OAM control structure. 12299 * Note: Lock taken by calling routine. 12300 */ 12301 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 12302 12303 rv = _bcm_kt2_oam_endpoint_alloc(&ep_info); 12304 if (BCM_FAILURE(rv)) { 12305 return (rv); 12306 } 12307 12308 /* 12309 * At this point, Remote MEP and Local MEP Rx config has been 12310 * recovered. Now, recover the Tx config for Local MEPs. 12311 */ 12312 for (index = 0; index < oc->lmep_count; index++) { 12313 12314 /* Get the LMEP table entry. */ 12315 rv = READ_LMEPm(unit, MEM_BLOCK_ANY, index, &lmep_entry); 12316 if (BCM_FAILURE(rv)) { 12317 LOG_ERROR(BSL_LS_BCM_OAM, 12318 (BSL_META_U(unit, 12319 "OAM Error: LMEP table read (index=%d) failed " 12320 "- %s.\n"), index, bcm_errmsg(rv))); 12321 goto cleanup; 12322 } 12323 12324 /* Get the LMEP_1 table entry. */ 12325 rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, index, &lmep_1_entry); 12326 if (BCM_FAILURE(rv)) { 12327 LOG_ERROR(BSL_LS_BCM_OAM, 12328 (BSL_META_U(unit, 12329 "OAM Error: LMEP_1 table read (index=%d) failed " 12330 "- %s.\n"), index, bcm_errmsg(rv))); 12331 goto cleanup; 12332 } 12333 ccm_period = _bcm_kt2_oam_ccm_hw_encode_to_msecs 12334 ((int) soc_LMEPm_field32_get(unit, &lmep_entry, 12335 CCM_INTERVALf)); 12336 if (ccm_period == BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) { 12337 continue; 12338 } 12339 grp_idx = soc_LMEPm_field32_get(unit, &lmep_entry, MAID_INDEXf); 12340 12341 rv = READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, grp_idx, &maid_red_ent); 12342 if (BCM_FAILURE(rv)) { 12343 LOG_ERROR(BSL_LS_BCM_OAM, 12344 (BSL_META_U(unit, 12345 "OAM Error: MAID_REDU read (GID=%d) failed " 12346 "- %s.\n"), grp_idx, bcm_errmsg(rv))); 12347 goto cleanup; 12348 } 12349 12350 if (soc_MAID_REDUCTIONm_field32_get(unit, &maid_red_ent, VALIDf)) { 12351 12352 /* Get pointer to group memory. */ 12353 g_info_p = &oc->group_info[grp_idx]; 12354 12355 vlan = soc_LMEPm_field32_get(unit, &lmep_entry, VLAN_IDf); 12356 inner_vlan = soc_LMEPm_field32_get(unit, &lmep_entry, CVLAN_TAGf); 12357 /* Only extract the VLAN ID portion of the tag. */ 12358 inner_vlan = inner_vlan & 0xfff; 12359 rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, index, &lmep_1_entry); 12360 if (BCM_FAILURE(rv)) { 12361 LOG_ERROR(BSL_LS_BCM_OAM, 12362 (BSL_META_U(unit, 12363 "OAM Error: LMEP_1 table read (index=%d) " 12364 "failed " "- %s.\n"), index, bcm_errmsg(rv))); 12365 goto cleanup; 12366 } 12367 12368 glp = soc_LMEP_1m_field32_get(unit, &lmep_1_entry, PP_PORTf); 12369 rv = _bcm_kt2_pp_port_to_modport_get(unit, glp, 12370 &modid, &port_id); 12371 if (BCM_FAILURE(rv)) { 12372 goto cleanup; 12373 } 12374 12375 level = soc_LMEPm_field32_get(unit, &lmep_entry, MDLf); 12376 12377 trunk_id = BCM_TRUNK_INVALID; 12378 if (vlan != 0 || inner_vlan != 0) { 12379 rv = bcm_esw_trunk_find(unit, modid, port_id, &trunk_id); 12380 if (BCM_FAILURE(rv) 12381 && (BCM_E_NOT_FOUND != rv)) { 12382 goto cleanup; 12383 } 12384 } 12385 12386 _bcm_gport_dest_t_init(&gport_dest); 12387 12388 if (BCM_TRUNK_INVALID != trunk_id) { 12389 gport_dest.tgid = trunk_id; 12390 gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 12391 12392 rv = _bcm_esw_oam_lmep_tx_trunk_config_recover(unit, 12393 trunk_id, 12394 port_id, 12395 &trunk_index); 12396 12397 if(BCM_FAILURE(rv)) { 12398 goto cleanup; 12399 } 12400 12401 } else { 12402 gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 12403 gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(glp); 12404 gport_dest.port = _BCM_OAM_GLP_PORT_GET(glp); 12405 } 12406 12407 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport); 12408 if (BCM_FAILURE(rv)) { 12409 LOG_ERROR(BSL_LS_BCM_OAM, 12410 (BSL_META_U(unit, 12411 "OAM Error: Gport construct failed" 12412 " - %s.\n"), bcm_errmsg(rv))); 12413 goto cleanup; 12414 } 12415 /* Get the endpoint list head pointer. */ 12416 cur = *(g_info_p->ep_list); 12417 if (NULL != cur) { 12418 while (NULL != cur) { 12419 h_data_p = cur->ep_data_p; 12420 if (NULL == h_data_p) { 12421 LOG_ERROR(BSL_LS_BCM_OAM, 12422 (BSL_META_U(unit, 12423 "OAM Error: Group (GID=%d) NULL" 12424 " endpoint list.\n"), grp_idx)); 12425 rv = BCM_E_INTERNAL; 12426 goto cleanup; 12427 } 12428 12429 if (vlan == h_data_p->vlan && 12430 inner_vlan == h_data_p->inner_vlan 12431 && gport == h_data_p->gport 12432 && level == h_data_p->level 12433 && 1 == h_data_p->local_rx_enabled) { 12434 match_found = 1; 12435 break; 12436 } 12437 cur = cur->next; 12438 } 12439 } 12440 12441 if (1 == match_found) { 12442 12443 bcm_oam_endpoint_info_t_init(ep_info); 12444 12445 /* Set up endpoint information for key construction. */ 12446 ep_info->group = h_data_p->group_index; 12447 ep_info->name = h_data_p->name; 12448 ep_info->gport = h_data_p->gport; 12449 ep_info->level = h_data_p->level; 12450 ep_info->vlan = h_data_p->vlan; 12451 ep_info->inner_vlan = h_data_p->inner_vlan; 12452 ep_info->flags = h_data_p->flags; 12453 12454 if ((recovered_ver < BCM_WB_VERSION_1_5) 12455 || (!ETH_TYPE(h_data_p->type))) { 12456 /* 12457 * Calculate hash key for hash table insert 12458 * operation. 12459 */ 12460 _bcm_kt2_oam_ep_hash_key_construct(unit, oc, ep_info, 12461 &hash_key); 12462 12463 /* 12464 * Delete insert done by Local Rx endpoint recovery code. 12465 * Endpoint name has been recovered and will result 12466 * in a different hash index. 12467 */ 12468 rv = shr_htb_find(oc->ma_mep_htbl, hash_key, 12469 (shr_htb_data_t *)&sh_data, 1); 12470 if (BCM_E_NOT_FOUND == rv) { 12471 goto cleanup; 12472 } 12473 } 12474 12475 } else { 12476 12477 if (recovered_ver >= BCM_WB_VERSION_1_3) { 12478 12479 sal_memcpy(&ep_id, 12480 *(scache) + _BCM_KT2_OAM_TX_MEP_SCACHE_LOCATION(index), 12481 sizeof(bcm_oam_endpoint_t)); 12482 12483 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id); 12484 if (BCM_FAILURE(rv)) { 12485 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 12486 LOG_ERROR(BSL_LS_BCM_OAM, 12487 (BSL_META_U(unit, 12488 "OAM Error: (EP_ID=%d) Index reserve " 12489 " failed - %s.\n"), ep_id, bcm_errmsg(rv))); 12490 goto cleanup; 12491 } 12492 } else { 12493 12494 /* Allocate the next available endpoint index. */ 12495 rv = shr_idxres_list_alloc(oc->mep_pool, 12496 (shr_idxres_element_t *)&ep_id); 12497 if (BCM_FAILURE(rv)) { 12498 LOG_ERROR(BSL_LS_BCM_OAM, 12499 (BSL_META_U(unit, 12500 "OAM Error: Endpoint alloc (EP=%d)" 12501 " - %s.\n"), ep_id, bcm_errmsg(rv))); 12502 goto cleanup; 12503 } 12504 } 12505 h_data_p = &oc->oam_hash_data[ep_id]; 12506 if (1 == h_data_p->in_use) { 12507 rv = BCM_E_INTERNAL; 12508 goto cleanup; 12509 } 12510 12511 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 12512 12513 _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p); 12514 12515 rv = _bcm_kt2_oam_group_ep_list_add(unit, grp_idx, ep_id); 12516 if (BCM_FAILURE(rv)) { 12517 LOG_ERROR(BSL_LS_BCM_OAM, 12518 (BSL_META_U(unit, 12519 "OAM Error: Adding (EP=%d)" 12520 " to (GID=%d) failed - %s.\n"), 12521 ep_id, grp_idx, bcm_errmsg(rv))); 12522 goto cleanup; 12523 } 12524 12525 h_data_p->ep_id = ep_id; 12526 h_data_p->group_index = grp_idx; 12527 h_data_p->local_rx_enabled = 0; 12528 h_data_p->vlan = vlan; 12529 h_data_p->inner_vlan = inner_vlan; 12530 h_data_p->gport = gport; 12531 h_data_p->level = level; 12532 if ((h_data_p->vlan == 0) && (h_data_p->inner_vlan == 0)) { 12533 h_data_p->oam_domain = _BCM_OAM_DOMAIN_PORT; 12534 } 12535 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 12536 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 12537 h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX; 12538 h_data_p->profile_index = _BCM_OAM_INVALID_INDEX; 12539 h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 12540 h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 12541 h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 12542 h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 12543 h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 12544 h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 12545 h_data_p->trunk_id = BCM_TRUNK_INVALID; 12546 } 12547 12548 h_data_p->src_pp_port = glp; 12549 h_data_p->dst_pp_port = glp; 12550 h_data_p->is_remote = 0; 12551 h_data_p->in_use = 1; 12552 h_data_p->local_tx_enabled = 1; 12553 h_data_p->local_tx_index = index; 12554 12555 if((-1) != trunk_index) { 12556 h_data_p->trunk_index = trunk_index; 12557 } 12558 12559 h_data_p->name 12560 = soc_LMEPm_field32_get(unit, &lmep_entry, MEPIDf); 12561 h_data_p->period 12562 = _bcm_kt2_oam_ccm_hw_encode_to_msecs 12563 ((int) soc_LMEPm_field32_get(unit, &lmep_entry, 12564 CCM_INTERVALf)); 12565 12566 if (BCM_PBMP_MEMBER(SOC_INFO(unit).general_pp_port_pbm, glp)) { 12567 h_data_p->flags2 |= BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW; 12568 } 12569 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_PORT) { 12570 rv = _bcm_kt2_oam_port_table_key_update(unit, PORT_TABm, h_data_p); 12571 if (BCM_FAILURE(rv)) { 12572 LOG_ERROR(BSL_LS_BCM_OAM, 12573 (BSL_META_U(unit, 12574 "OAM Error: Unable to increment key ref count " 12575 " - %s.\n"), bcm_errmsg(rv))); 12576 goto cleanup; 12577 } 12578 rv = _bcm_kt2_oam_port_table_key_update(unit, EGR_PORTm, h_data_p); 12579 if (BCM_FAILURE(rv)) { 12580 LOG_ERROR(BSL_LS_BCM_OAM, 12581 (BSL_META_U(unit, 12582 "OAM Error: Unable to increment key ref count " 12583 " - %s.\n"), bcm_errmsg(rv))); 12584 goto cleanup; 12585 } 12586 } else { 12587 rv = soc_mem_read(unit, EGR_PORTm, MEM_BLOCK_ANY, 12588 h_data_p->dst_pp_port, &egr_port_entry); 12589 if (BCM_FAILURE(rv)) { 12590 LOG_ERROR(BSL_LS_BCM_OAM, 12591 (BSL_META_U(unit, 12592 "OAM Error: EGR_PORT Table read failed" 12593 " - %s.\n"), bcm_errmsg(rv))); 12594 goto cleanup; 12595 } 12596 mdl_mip = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, 12597 MDL_BITMAP_PASSIVEf); 12598 if (!(mdl_mip & (1 << h_data_p->level))) { 12599 /* Set the MIP flag */ 12600 h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE; 12601 } 12602 } 12603 12604 /* For ethernet CCM TX endpoints, fetch TPIDs from HW. 12605 */ 12606 if (h_data_p->vlan != 0) { 12607 tpid_index = soc_LMEPm_field32_get(unit, &lmep_entry, 12608 SVLAN_TPID_INDEXf); 12609 rv = _bcm_kt2_oam_tpid_get(unit, BCM_OAM_TPID_TYPE_OUTER, 12610 tpid_index, &(h_data_p->outer_tpid)); 12611 if (BCM_FAILURE(rv)) { 12612 LOG_ERROR(BSL_LS_BCM_OAM, 12613 (BSL_META_U(unit, 12614 "OAM(unit %d) Error: Outer TPID fetch failed" 12615 " EP=%d %s.\n"), unit, ep_id, 12616 bcm_errmsg(rv))); 12617 goto cleanup; 12618 } 12619 h_data_p->outer_tpid_profile_index = tpid_index; 12620 KT2_OAM_OUTER_TPID_REF_COUNT(unit, tpid_index)++; 12621 } 12622 12623 if (h_data_p->inner_vlan != 0) { 12624 rv = _bcm_kt2_oam_tpid_get(unit, BCM_OAM_TPID_TYPE_INNER, 12625 0, &(h_data_p->inner_tpid)); 12626 if (BCM_FAILURE(rv)) { 12627 LOG_ERROR(BSL_LS_BCM_OAM, 12628 (BSL_META_U(unit, 12629 "OAM(unit %d) Error: Inner TPID fetch failed" 12630 " EP=%d %s.\n"), unit, ep_id, 12631 bcm_errmsg(rv))); 12632 goto cleanup; 12633 } 12634 h_data_p->inner_tpid_profile_index = 0; 12635 KT2_OAM_INNER_TPID_REF_COUNT(unit, 0)++; 12636 } 12637 12638 if ((BCM_GPORT_IS_SUBPORT_PORT(h_data_p->gport)) && 12639 (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, h_data_p->gport))) { 12640 tpid_index = soc_LMEPm_field32_get(unit, &lmep_entry, 12641 SUBPORT_TAG_TPID_INDEXf); 12642 rv = _bcm_kt2_oam_tpid_get(unit, BCM_OAM_TPID_TYPE_SUBPORT, 12643 tpid_index, &(h_data_p->subport_tpid)); 12644 if (BCM_FAILURE(rv)) { 12645 LOG_ERROR(BSL_LS_BCM_OAM, 12646 (BSL_META_U(unit, 12647 "OAM(unit %d) Error: Subport TPID fetch failed" 12648 " EP=%d %s.\n"), unit, ep_id, 12649 bcm_errmsg(rv))); 12650 goto cleanup; 12651 } 12652 h_data_p->subport_tpid_profile_index = tpid_index; 12653 KT2_OAM_SUBPORT_TPID_REF_COUNT(unit, tpid_index)++; 12654 } 12655 12656 rv = shr_idxres_list_reserve(oc->lmep_pool, 12657 h_data_p->local_tx_index, 12658 h_data_p->local_tx_index); 12659 if (BCM_FAILURE(rv)) { 12660 LOG_ERROR(BSL_LS_BCM_OAM, 12661 (BSL_META_U(unit, 12662 "OAM Error: Tx index=%d reserve failed" 12663 " - %s.\n"), index, bcm_errmsg(rv))); 12664 12665 _bcm_kt2_oam_group_ep_list_remove(unit, 12666 h_data_p->group_index, 12667 h_data_p->ep_id); 12668 12669 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 12670 goto cleanup; 12671 } 12672 12673 bcm_oam_endpoint_info_t_init(ep_info); 12674 12675 /* Set up endpoint information for key construction. */ 12676 ep_info->group = h_data_p->group_index; 12677 ep_info->name = h_data_p->name; 12678 ep_info->gport = h_data_p->gport; 12679 ep_info->level = h_data_p->level; 12680 ep_info->vlan = h_data_p->vlan; 12681 ep_info->inner_vlan = h_data_p->inner_vlan; 12682 ep_info->flags = h_data_p->flags; 12683 12684 if ((recovered_ver < BCM_WB_VERSION_1_5) 12685 || (!ETH_TYPE(h_data_p->type))) { 12686 /* 12687 * Calculate hash key for hash table insert 12688 * operation. 12689 */ 12690 _bcm_kt2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 12691 12692 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 12693 if (BCM_FAILURE(rv)) { 12694 LOG_ERROR(BSL_LS_BCM_OAM, 12695 (BSL_META_U(unit, 12696 "OAM Error: Hash table insert" 12697 " (EP=%d) failed - %s.\n"), 12698 h_data_p->ep_id, bcm_errmsg(rv))); 12699 12700 _bcm_kt2_oam_group_ep_list_remove(unit, 12701 h_data_p->group_index, 12702 h_data_p->ep_id); 12703 12704 goto cleanup; 12705 } else { 12706 LOG_DEBUG(BSL_LS_BCM_OAM, 12707 (BSL_META_U(unit, 12708 "OAM Info: Hash Tbl (EP=%d)" 12709 " inserted - %s.\n"), h_data_p->ep_id, 12710 bcm_errmsg(rv))); 12711 } 12712 } 12713 12714 } 12715 12716 match_found = 0; 12717 h_data_p = NULL; 12718 } 12719 12720 LOG_DEBUG(BSL_LS_BCM_OAM, 12721 (BSL_META_U(unit, 12722 "OAM Info: _bcm_kt2_oam_lmep_tx_config_recover" 12723 " - done.\n"))); 12724 sal_free(ep_info); 12725 return (rv); 12726 12727 cleanup: 12728 12729 if (NULL != ep_info) { 12730 sal_free(ep_info); 12731 } 12732 12733 if (0 == match_found && NULL != h_data_p) { 12734 /* Return endpoint index to MEP pool. */ 12735 if (BCM_E_EXISTS 12736 == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) { 12737 shr_idxres_list_free(oc->mep_pool, ep_id); 12738 } 12739 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 12740 } 12741 12742 if (BCM_E_EXISTS 12743 == shr_idxres_list_elem_state(oc->lmep_pool, index)) { 12744 shr_idxres_list_free(oc->lmep_pool, index); 12745 } 12746 12747 LOG_DEBUG(BSL_LS_BCM_OAM, 12748 (BSL_META_U(unit, 12749 "OAM Info: _bcm_kt2_oam_lmep_tx_config_recover" 12750 " - error_done.\n"))); 12751 return (rv); 12752 } 12753 12754 /* 12755 * Function: 12756 * _bcm_kt2_oam_wb_endpoints_recover 12757 * Purpose: 12758 * Recover OAM local endpoint Rx configuration. 12759 * Parameters: 12760 * unit - Device unit number. 12761 * stable_size - OAM module Level2 memory size. 12762 * oam_scache - Pointer to secondary storage buffer pointer. 12763 * Returns: 12764 * BCM_E_XXX 12765 */ 12766 STATIC int 12767 _bcm_kt2_oam_wb_endpoints_recover(int unit, 12768 int stable_size, 12769 uint8 **oam_scache, 12770 uint16 recovered_ver) 12771 { 12772 int index; /* Hardware index. */ 12773 uint32 entry_count; /* Max entries in L3_ENTRY_1/ 12774 EGR_MP_GROUP table. */ 12775 l3_entry_1_entry_t l3_entry; /* L3 table entry. */ 12776 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 12777 int rv; /* Operation return status. */ 12778 egr_mp_group_entry_t egr_mp_grp_entry;/* Egr MP group tbl entry buffer */ 12779 port_tab_entry_t port_entry; /* Port table entry buffer */ 12780 12781 /* 12782 * Get OAM control structure. 12783 * Note: Lock taken by calling routine. 12784 */ 12785 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 12786 12787 /* Get number of L3 table entries. */ 12788 entry_count = soc_mem_index_count(unit, L3_ENTRY_IPV4_UNICASTm); 12789 12790 /* Now get valid OAM endpoint entries. */ 12791 for (index = 0; index < entry_count; index++) { 12792 12793 rv = READ_L3_ENTRY_IPV4_UNICASTm(unit, MEM_BLOCK_ANY, index, &l3_entry); 12794 if (BCM_FAILURE(rv)) { 12795 LOG_ERROR(BSL_LS_BCM_OAM, 12796 (BSL_META_U(unit, 12797 "OAM Error: L3_ENTRY (index=%d) read" 12798 " failed - %s.\n"), index, bcm_errmsg(rv))); 12799 return (rv); 12800 } 12801 12802 if (soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, VALIDf)) { 12803 12804 switch (soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, 12805 KEY_TYPEf)) { 12806 12807 case SOC_MEM_KEY_L3_ENTRY_RMEP: 12808 rv = _bcm_kt2_oam_rmep_recover(unit, index, 12809 &l3_entry, oam_scache, recovered_ver); 12810 if (BCM_FAILURE(rv)) { 12811 LOG_ERROR(BSL_LS_BCM_OAM, 12812 (BSL_META_U(unit, 12813 "OAM Error: Remote endpoint" 12814 " (index=%d) reconstruct failed - %s.\n"), 12815 index, bcm_errmsg(rv))); 12816 return (rv); 12817 } 12818 break; 12819 12820 /* Recover all downMEP's */ 12821 case SOC_MEM_KEY_L3_ENTRY_LMEP: 12822 rv = _bcm_kt2_oam_lmep_downmep_rx_config_recover(unit, 12823 index, 12824 &l3_entry, 12825 oam_scache, 12826 recovered_ver); 12827 if (BCM_FAILURE(rv)) { 12828 LOG_ERROR(BSL_LS_BCM_OAM, 12829 (BSL_META_U(unit, 12830 "OAM Error: Local endpoint DownMEP" 12831 " (index=%d) reconstruct failed - %s.\n"), 12832 index, bcm_errmsg(rv))); 12833 return (rv); 12834 } 12835 break; 12836 12837 default: 12838 /* Not an OAM entry. */ 12839 continue; 12840 } 12841 } 12842 } 12843 /* Recover all UpMEPs */ 12844 /* Get number of EGR_MP_GROUP table entries. */ 12845 entry_count = soc_mem_index_count(unit, EGR_MP_GROUPm); 12846 12847 /* Now get valid OAM endpoint entries. */ 12848 for (index = 0; index < entry_count; index++) { 12849 rv = READ_EGR_MP_GROUPm(unit, MEM_BLOCK_ANY, index, &egr_mp_grp_entry); 12850 if (BCM_FAILURE(rv)) { 12851 LOG_ERROR(BSL_LS_BCM_OAM, 12852 (BSL_META_U(unit, 12853 "OAM Error: EGR_MP_GROUP ENTRY (index=%d) read" 12854 " failed - %s.\n"), index, bcm_errmsg(rv))); 12855 return (rv); 12856 } 12857 if (soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_grp_entry, VALIDf)) { 12858 rv = _bcm_kt2_oam_lmep_upmep_rx_config_recover(unit, index, 12859 &egr_mp_grp_entry, oam_scache, recovered_ver); 12860 if (BCM_FAILURE(rv)) { 12861 LOG_ERROR(BSL_LS_BCM_OAM, 12862 (BSL_META_U(unit, 12863 "OAM Error: Local endpoint UpMEP" 12864 " (index=%d) reconstruct failed - %s.\n"), 12865 index, bcm_errmsg(rv))); 12866 return (rv); 12867 } 12868 } 12869 } 12870 12871 /* recover endpoints from Port table */ 12872 /* Get number of PORT_TABLE table entries. */ 12873 entry_count = soc_mem_index_count(unit, PORT_TABm); 12874 /* Now get valid OAM endpoint entries. */ 12875 for (index = 0; index < entry_count; index++) { 12876 rv = READ_PORT_TABm(unit, MEM_BLOCK_ANY, index, &port_entry); 12877 if (BCM_FAILURE(rv)) { 12878 LOG_ERROR(BSL_LS_BCM_OAM, 12879 (BSL_META_U(unit, 12880 "OAM Error: Port table ENTRY (index=%d) read" 12881 " failed - %s.\n"), index, bcm_errmsg(rv))); 12882 return (rv); 12883 } 12884 if (soc_PORT_TABm_field32_get(unit, &port_entry, OAM_ENABLEf)) { 12885 rv = _bcm_kt2_oam_port_lmep_rx_config_recover(unit, index, 12886 &port_entry, 12887 oam_scache, recovered_ver); 12888 if (BCM_FAILURE(rv)) { 12889 LOG_ERROR(BSL_LS_BCM_OAM, 12890 (BSL_META_U(unit, 12891 "OAM Error: Port based local endpoint " 12892 " (index=%d) reconstruct failed - %s.\n"), 12893 index, bcm_errmsg(rv))); 12894 return (rv); 12895 } 12896 } 12897 } 12898 rv = _bcm_kt2_oam_lmep_tx_config_recover(unit, oam_scache, recovered_ver); 12899 if (BCM_FAILURE(rv)) { 12900 LOG_ERROR(BSL_LS_BCM_OAM, 12901 (BSL_META_U(unit, 12902 "OAM Error: Endpoint Tx config recovery" 12903 " failed - %s.\n"), bcm_errmsg(rv))); 12904 return (rv); 12905 } 12906 12907 return (BCM_E_NONE); 12908 } 12909 12910 /* 12911 * Function: 12912 * bcm_kt2_oam_scache_alloc 12913 * Purpose: 12914 * Allocate scache memory for OAM module 12915 * Parameters: 12916 * unit - (IN) BCM device number 12917 * Returns: 12918 * BCM_E_UNIT - Invalid BCM unit number. 12919 * BCM_E_UNAVAIL - OAM not support on this device. 12920 * BCM_E_MEMORY - Allocation failure 12921 * CM_E_XXX - Error code from bcm_XX_oam_init() 12922 * BCM_E_NONE - Success 12923 */ 12924 STATIC int 12925 bcm_kt2_oam_scache_alloc(int unit) { 12926 _bcm_oam_control_t *oc; 12927 soc_scache_handle_t scache_handle; 12928 uint8 *oam_scache; 12929 int alloc_sz = 0; 12930 12931 12932 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 12933 12934 alloc_sz = BCM_OAM_GROUP_NAME_LENGTH * (oc->group_count); 12935 12936 /* Number of oam groups */ 12937 alloc_sz += sizeof(int); 12938 12939 /* VFP group, IFP VP group, IFP GLP group */ 12940 alloc_sz += 3 * sizeof(bcm_field_group_t); 12941 12942 /* Allocate memory to store logical endpoint Ids */ 12943 alloc_sz += (_BCM_KT2_OAM_ENDPOINT_ID_SCACHE_SIZE); 12944 12945 /* Allocate memory to store oc->eth_oam_mp_group_vlan_key */ 12946 alloc_sz += sizeof(uint8); 12947 12948 /* FLAGS are stored for all ethernet OAM endpoints */ 12949 alloc_sz += (sizeof(uint32) * oc->ep_count); 12950 12951 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 12952 BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 1, 12953 alloc_sz, &oam_scache, BCM_WB_DEFAULT_VERSION, NULL)); 12954 return BCM_E_NONE; 12955 } 12956 12957 /* Given h_data_p, this function fills the endpoint_info required for 12958 * hash_key generation and inserts it at appropriate location. 12959 * 12960 * oc->lock is already assumed to be taken by caller */ 12961 int _bcm_kt2_oam_hash_tbl_insert_hash_data_entry(int unit, _bcm_oam_hash_data_t *h_data_p) 12962 { 12963 bcm_oam_endpoint_info_t ep_info; 12964 _bcm_oam_control_t *oc = NULL; /* Pointer to OAM control structure. */ 12965 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 12966 int rv = BCM_E_NONE; 12967 12968 12969 if (h_data_p == NULL) { 12970 return BCM_E_INTERNAL; 12971 } 12972 12973 /* Get OAM control structure. */ 12974 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 12975 12976 /* Initialize endpoint info structure. */ 12977 bcm_oam_endpoint_info_t_init(&ep_info); 12978 12979 /* Set up endpoint information for key construction. */ 12980 ep_info.group = h_data_p->group_index; 12981 ep_info.name = h_data_p->name; 12982 ep_info.gport = h_data_p->gport; 12983 ep_info.level = h_data_p->level; 12984 ep_info.vlan = h_data_p->vlan; 12985 ep_info.inner_vlan = h_data_p->inner_vlan; 12986 ep_info.flags = h_data_p->flags; 12987 12988 /* Construct hash key for lookup */ 12989 _bcm_kt2_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key); 12990 12991 /* Insert entry from hash table. */ 12992 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 12993 if (BCM_FAILURE(rv)) { 12994 LOG_ERROR(BSL_LS_BCM_OAM, 12995 (BSL_META_U(unit, 12996 "OAM(unit %d) Error: Hash table insert failed " 12997 "EP=%d %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 12998 } else { 12999 LOG_DEBUG(BSL_LS_BCM_OAM, 13000 (BSL_META_U(unit, 13001 "OAM(unit %d) Info: Hash Tbl (EP=%d) inserted" 13002 " - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 13003 } 13004 13005 return rv; 13006 } 13007 13008 13009 /* 13010 * Function: 13011 * _bcm_kt2_oam_reinit 13012 * Purpose: 13013 * Reconstruct OAM module software state. 13014 * Parameters: 13015 * unit - (IN) BCM device number 13016 * Retruns: 13017 * BCM_E_XXX 13018 */ 13019 STATIC int 13020 _bcm_kt2_oam_reinit(int unit) 13021 { 13022 uint32 group_count = 0; /* Stored OAM group count. */ 13023 int stable_size = 0; /* Secondary storage size. */ 13024 uint8 *oam_scache; /* Pointer to scache memory. */ 13025 soc_scache_handle_t scache_handle; /* Scache memory handler. */ 13026 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 13027 int rv; /* Operation return status. */ 13028 uint16 recovered_ver = 0; 13029 int realloc_size = 0; 13030 int idx = 0; 13031 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 13032 13033 LOG_DEBUG(BSL_LS_BCM_OAM, 13034 (BSL_META_U(unit, 13035 "OAM Info: OAM warm boot recovery.....\n"))); 13036 13037 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 13038 13039 /* Get OAM control structure. */ 13040 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 13041 13042 _BCM_OAM_LOCK(oc); 13043 13044 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) { 13045 13046 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 13047 13048 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0, 13049 &oam_scache, BCM_WB_DEFAULT_VERSION, 13050 &recovered_ver); 13051 if (BCM_E_NOT_FOUND == rv) { 13052 /* Upgrading from SDK release that does not have warmboot state */ 13053 bcm_kt2_oam_scache_alloc(unit); 13054 _BCM_OAM_UNLOCK(oc); 13055 return BCM_E_NONE; 13056 } else if (BCM_FAILURE(rv)) { 13057 goto cleanup; 13058 } else { 13059 if (recovered_ver < BCM_WB_VERSION_1_2 && MA_INDEX_ALLOC_SCHEME_SEPARATE_POOL) { 13060 LOG_WARN(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Warn:" 13061 " Warm upgrade from a older version which does not support " 13062 "flexible endpoint hw index allocation. Reverting to older " 13063 "scheme.\n"))); 13064 oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_COMBINED_POOL; 13065 /* Destroy the previous allocation and re-allocate based on this scheme */ 13066 rv = _bcm_kt2_oam_ma_idx_pool_destroy(oc); 13067 if (BCM_FAILURE(rv)) { 13068 goto cleanup; 13069 } 13070 rv = _bcm_kt2_oam_ma_idx_pool_create(oc); 13071 if (BCM_FAILURE(rv)) { 13072 goto cleanup; 13073 } 13074 } 13075 13076 /* Recover the FP groups */ 13077 sal_memcpy(&oc->vfp_group, oam_scache, sizeof(bcm_field_group_t)); 13078 oam_scache += sizeof(bcm_field_group_t); 13079 13080 sal_memcpy(&oc->fp_vp_group, oam_scache, sizeof(bcm_field_group_t)); 13081 oam_scache += sizeof(bcm_field_group_t); 13082 13083 sal_memcpy(&oc->fp_glp_group, oam_scache, sizeof(bcm_field_group_t)); 13084 oam_scache += sizeof(bcm_field_group_t); 13085 13086 /* Recover the OAM groups */ 13087 sal_memcpy(&group_count, oam_scache, sizeof(int)); 13088 oam_scache += sizeof(int); 13089 13090 } 13091 } else { 13092 rv = BCM_E_NONE; 13093 goto cleanup; 13094 } 13095 13096 rv = _bcm_kt2_oam_wb_group_recover(unit, stable_size, &oam_scache); 13097 13098 if (BCM_FAILURE(rv)) { 13099 LOG_ERROR(BSL_LS_BCM_OAM, 13100 (BSL_META_U(unit, 13101 "OAM Error: Group recovery failed - %s.\n"), 13102 bcm_errmsg(rv))); 13103 goto cleanup; 13104 } 13105 13106 rv = _bcm_kt2_oam_wb_endpoints_recover(unit, stable_size, &oam_scache, recovered_ver); 13107 if (BCM_FAILURE(rv)) { 13108 LOG_ERROR(BSL_LS_BCM_OAM, 13109 (BSL_META_U(unit, 13110 "OAM Error: Endpoint recovery failed - %s.\n"), 13111 bcm_errmsg(rv))); 13112 goto cleanup; 13113 } 13114 13115 if(recovered_ver >= BCM_WB_VERSION_1_3) { 13116 oam_scache += (_BCM_KT2_OAM_ENDPOINT_ID_SCACHE_SIZE); 13117 } 13118 13119 if (recovered_ver >= BCM_WB_VERSION_1_4) { 13120 sal_memcpy(&oc->eth_oam_mp_group_vlan_key, oam_scache, sizeof(uint8)); 13121 oam_scache += sizeof(uint8); 13122 } else { 13123 oc->eth_oam_mp_group_vlan_key = 13124 _BCM_KT2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT; 13125 } 13126 if (recovered_ver >= BCM_WB_VERSION_1_5) { 13127 for (idx = 0; idx < oc->ep_count; idx++) { 13128 h_data_p = &oc->oam_hash_data[idx]; 13129 if (ETH_TYPE(h_data_p->type) && (h_data_p->in_use)) { 13130 sal_memcpy(&(h_data_p->flags), oam_scache, sizeof(uint32)); 13131 rv = _bcm_kt2_oam_hash_tbl_insert_hash_data_entry(unit, h_data_p); 13132 if (BCM_FAILURE(rv)) { 13133 LOG_ERROR(BSL_LS_BCM_OAM, 13134 (BSL_META_U(unit, 13135 "OAM(unit %d) Error: Endpoint %d hash tbl insert failed - %s.\n"), 13136 unit, h_data_p->ep_id, bcm_errmsg(rv))); 13137 goto cleanup; 13138 } 13139 } 13140 oam_scache += sizeof(uint32); 13141 } 13142 } 13143 13144 /* In BCM_WB_VERSION_1_1 onwards we allocate memory for max OAM groups and 13145 not just the groups created, as such while upgrading from 13146 BCM_WB_VERSION_1_0 to BCM_WB_VERSION_1_1 or greater we must add the 13147 differential. 13148 */ 13149 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) { 13150 if (recovered_ver < BCM_WB_VERSION_1_1) { 13151 realloc_size += (BCM_OAM_GROUP_NAME_LENGTH * (oc->group_count - group_count)); 13152 } 13153 13154 /* BCM_WB_VERSION_1_3 onwards addition memory is used to store 13155 * software endpoint ids */ 13156 if(recovered_ver < BCM_WB_VERSION_1_3) { 13157 realloc_size += (_BCM_KT2_OAM_ENDPOINT_ID_SCACHE_SIZE); 13158 13159 } 13160 13161 if (recovered_ver < BCM_WB_VERSION_1_4) { 13162 realloc_size += sizeof(uint8); 13163 } 13164 13165 if (recovered_ver < BCM_WB_VERSION_1_5) { 13166 realloc_size += (sizeof(uint32) * oc->ep_count); 13167 } 13168 13169 /* Added the check to avoid any like-to-like recovery where realloc is not required */ 13170 if (realloc_size) { 13171 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 13172 rv = soc_scache_realloc(unit, scache_handle, realloc_size); 13173 if (SOC_FAILURE(rv)) { 13174 LOG_ERROR(BSL_LS_BCM_OAM, 13175 (BSL_META_U(unit, 13176 "OAM(unit %d) Error: scache alloc failed" 13177 " - %s.\n"), 13178 unit, bcm_errmsg(rv))); 13179 goto cleanup; 13180 } 13181 } 13182 } 13183 13184 13185 cleanup: 13186 _BCM_OAM_UNLOCK(oc); 13187 return (rv); 13188 } 13189 13190 #if defined(INCLUDE_BHH) 13191 /* 13192 * Function: 13193 * _bcm_kt2_oam_bhh_cos_map_recover 13194 * Purpose: 13195 * Reconstruct CoS Map config done for BHH 13196 * Parameters: 13197 * unit - (IN) BCM device number 13198 * Retruns: 13199 * BCM_E_XXX 13200 */ 13201 STATIC int 13202 _bcm_kt2_oam_bhh_cos_map_recover(int unit) 13203 { 13204 int rv = BCM_E_NONE; 13205 _bcm_oam_control_t *oc; 13206 int index; 13207 int cosq_map_size; 13208 bcm_rx_reasons_t reasons, reasons_mask; 13209 bcm_rx_reasons_t ach_error_reasons, invalid_error_reasons; 13210 bcm_rx_reasons_t bhh_lb_reasons; 13211 uint8 int_prio, int_prio_mask; 13212 uint32 packet_type, packet_type_mask; 13213 bcm_cos_queue_t cosq; 13214 13215 /* Get OAM Control Structure. */ 13216 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 13217 _BCM_OAM_LOCK(oc); 13218 13219 if (oc->ukernel_not_ready) { 13220 _BCM_OAM_UNLOCK(oc); 13221 return BCM_E_NONE; 13222 } 13223 13224 rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size); 13225 if(BCM_FAILURE(rv)) { 13226 LOG_ERROR(BSL_LS_BCM_OAM, 13227 (BSL_META_U(unit, 13228 "BHH Error:hw init. cosq maps size %s.\n"), 13229 bcm_errmsg(rv))); 13230 _BCM_OAM_UNLOCK(oc); 13231 return (rv); 13232 } 13233 13234 BCM_RX_REASON_CLEAR_ALL(ach_error_reasons); 13235 BCM_RX_REASON_SET(ach_error_reasons, bcmRxReasonBHHOAM); 13236 BCM_RX_REASON_SET(ach_error_reasons, bcmRxReasonOAMCCMSlowpath); 13237 13238 BCM_RX_REASON_CLEAR_ALL(invalid_error_reasons); 13239 BCM_RX_REASON_SET(invalid_error_reasons, bcmRxReasonBHHOAM); 13240 BCM_RX_REASON_SET(invalid_error_reasons, bcmRxReasonOAMLMDM); 13241 13242 BCM_RX_REASON_CLEAR_ALL(bhh_lb_reasons); 13243 BCM_RX_REASON_SET(bhh_lb_reasons, bcmRxReasonBHHOAM); 13244 BCM_RX_REASON_SET(bhh_lb_reasons, bcmRxReasonOAMSlowpath); 13245 13246 oc->cpu_cosq_ach_error_index = -1; 13247 oc->cpu_cosq_invalid_error_index = -1; 13248 oc->bhh_lb_index = -1; 13249 for (index = 0; index < cosq_map_size; index++) { 13250 rv = bcm_esw_rx_cosq_mapping_get(unit, index, 13251 &reasons, &reasons_mask, 13252 &int_prio, &int_prio_mask, 13253 &packet_type, &packet_type_mask, 13254 &cosq); 13255 if (rv == BCM_E_NONE) { 13256 13257 if (BCM_RX_REASON_EQ(reasons, ach_error_reasons) && 13258 BCM_RX_REASON_EQ(reasons_mask, ach_error_reasons)) { 13259 oc->cpu_cosq_ach_error_index = index; 13260 oc->cpu_cosq = cosq; 13261 } else if (BCM_RX_REASON_EQ(reasons, invalid_error_reasons) && 13262 BCM_RX_REASON_EQ(reasons_mask, invalid_error_reasons)) { 13263 oc->cpu_cosq_invalid_error_index = index; 13264 } else if (BCM_RX_REASON_EQ(reasons, bhh_lb_reasons) && 13265 BCM_RX_REASON_EQ(reasons_mask, bhh_lb_reasons)) { 13266 oc->bhh_lb_index = index; 13267 } 13268 } 13269 if( -1 != oc->cpu_cosq_ach_error_index && 13270 -1 != oc->cpu_cosq_invalid_error_index && 13271 -1 != oc->bhh_lb_index) { 13272 break; 13273 } 13274 } 13275 13276 if (index >= cosq_map_size) { 13277 LOG_VERBOSE(BSL_LS_BCM_OAM, 13278 (BSL_META_U(unit, 13279 "BHH Error: Could not recover cos map entry \n"))); 13280 } 13281 13282 _BCM_OAM_UNLOCK(oc); 13283 return rv; 13284 } 13285 #endif /* INCLUDE_BHH */ 13286 #endif /* BCM_WARM_BOOT_SUPPORT */ 13287 13288 STATIC int 13289 _bcm_kt2_oam_ma_idx_num_entries_and_pool_get(int unit, 13290 _bcm_oam_hash_data_t *h_data_p, 13291 int *num_ma_idx_entries, 13292 shr_idxres_list_handle_t *pool) 13293 { 13294 _bcm_oam_control_t *oc = NULL; 13295 13296 /* Get OAM control structure handle. */ 13297 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 13298 13299 if ((h_data_p == NULL) || (h_data_p->in_use == 0)) { 13300 return BCM_E_PARAM; 13301 } 13302 13303 switch (oc->ma_idx_alloc_scheme) { 13304 case _BCM_OAM_MA_IDX_ALLOC_COMBINED_POOL: 13305 *num_ma_idx_entries = 8; 13306 *pool = oc->ma_idx_pool; 13307 return BCM_E_NONE; 13308 break; 13309 case _BCM_OAM_MA_IDX_ALLOC_SEPARATE_POOL: 13310 if (h_data_p->type == bcmOAMEndpointTypeEthernet) { 13311 *num_ma_idx_entries = 8; 13312 *pool = oc->ma_idx_pool; 13313 } else if (BHH_EP_TYPE(h_data_p)) { 13314 *num_ma_idx_entries = 1; 13315 *pool = oc->mpls_oam_ma_idx_pool; 13316 } 13317 return BCM_E_NONE; 13318 break; 13319 default: 13320 /* Should not hit */ 13321 break; 13322 } 13323 return BCM_E_INTERNAL; 13324 } 13325 13326 STATIC int 13327 _bcm_kt2_oam_ma_idx_pool_create(_bcm_oam_control_t *oc) 13328 { 13329 int rv = BCM_E_NONE; 13330 13331 if (MA_INDEX_ALLOC_SCHEME_COMBINED_POOL) { 13332 rv = shr_idxres_list_create(&oc->ma_idx_pool, 0, 13333 oc->ma_idx_count - 1, 13334 0, oc->ma_idx_count -1, "ma_idx pool"); 13335 if (BCM_FAILURE(rv)) { 13336 return (rv); 13337 13338 } 13339 } else if (MA_INDEX_ALLOC_SCHEME_SEPARATE_POOL) { 13340 if (_BCM_ETH_OAM_NUM_SESSIONS != 0) { 13341 rv = shr_idxres_list_create(&oc->ma_idx_pool, 0, _BCM_ETH_OAM_NUM_SESSIONS-1, 13342 0, _BCM_ETH_OAM_NUM_SESSIONS-1, "ma_idx pool"); 13343 if (BCM_FAILURE(rv)) { 13344 return (rv); 13345 13346 } 13347 } 13348 13349 if (_BCM_MPLS_OAM_NUM_SESSIONS != 0) { 13350 rv = shr_idxres_list_create(&oc->mpls_oam_ma_idx_pool, 13351 _BCM_ETH_OAM_NUM_SESSIONS, 13352 _BCM_ETH_OAM_NUM_SESSIONS + _BCM_MPLS_OAM_NUM_SESSIONS-1, 13353 _BCM_ETH_OAM_NUM_SESSIONS, 13354 _BCM_ETH_OAM_NUM_SESSIONS + _BCM_MPLS_OAM_NUM_SESSIONS-1, 13355 "mpls oam ma_idx pool"); 13356 if (BCM_FAILURE(rv)) { 13357 return (rv); 13358 13359 } 13360 } 13361 } else { 13362 return (BCM_E_INTERNAL); 13363 13364 } 13365 return rv; 13366 } 13367 13368 STATIC int 13369 _bcm_kt2_oam_ma_idx_pool_destroy(_bcm_oam_control_t *oc) 13370 { 13371 if (NULL != oc->ma_idx_pool) { 13372 shr_idxres_list_destroy(oc->ma_idx_pool); 13373 oc->ma_idx_pool = NULL; 13374 } 13375 if (NULL != oc->mpls_oam_ma_idx_pool) { 13376 shr_idxres_list_destroy(oc->mpls_oam_ma_idx_pool); 13377 oc->mpls_oam_ma_idx_pool = NULL; 13378 } 13379 return BCM_E_NONE; 13380 } 13381 13382 13383 /* * * * * * * * * * * * * * * * * * * * 13384 * OAM BCM APIs * 13385 */ 13386 /* 13387 * Function: bcm_kt2_oam_init 13388 * 13389 * Purpose: 13390 * Initialize OAM module. 13391 * Parameters: 13392 * unit - (IN) BCM device number 13393 * Returns: 13394 * BCM_E_UNIT - Invalid BCM unit number. 13395 * BCM_E_UNAVAIL - OAM not support on this device. 13396 * BCM_E_MEMORY - Allocation failure 13397 * CM_E_XXX - Error code from bcm_XX_oam_init() 13398 * BCM_E_NONE - Success 13399 */ 13400 int 13401 bcm_kt2_oam_init(int unit) 13402 { 13403 _bcm_oam_control_t *oc = NULL; /* OAM control structure. */ 13404 int rv; /* Operation return value. */ 13405 uint32 size; /* Size of memory allocation. */ 13406 bcm_port_t port; /* Port number. */ 13407 int index = 0; 13408 bcm_oam_endpoint_t ep_index; /* Endpoint index. */ 13409 bcm_pbmp_t all_pbmp; 13410 #if defined(INCLUDE_BHH) 13411 int uc; 13412 uint8 carrier_code[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; 13413 char *carrier_code_str; 13414 uint32 node_id = 0; 13415 bhh_sdk_msg_ctrl_init_t msg_init; 13416 uint8 *buffer, *buffer_ptr; 13417 uint16 buffer_len, reply_len; 13418 int priority; 13419 int ukernel_not_ready = 0; 13420 uint8 bhh_consolidate_final_event = 0; 13421 #endif 13422 /* Ensure that the unit has OAM support. */ 13423 if (!soc_feature(unit, soc_feature_oam)) { 13424 LOG_ERROR(BSL_LS_BCM_OAM, 13425 (BSL_META_U(unit, 13426 "OAM Error: OAM not supported \n"))); 13427 return (BCM_E_UNAVAIL); 13428 } 13429 13430 /* Detach first if the module has been previously initialized. */ 13431 if (NULL != _kt2_oam_control[unit]) { 13432 _kt2_oam_control[unit]->init = FALSE; 13433 rv = bcm_kt2_oam_detach(unit); 13434 if (BCM_FAILURE(rv)) { 13435 LOG_ERROR(BSL_LS_BCM_OAM, 13436 (BSL_META_U(unit, 13437 "OAM Error: Module deinit - %s.\n"), 13438 bcm_errmsg(rv))); 13439 return (rv); 13440 } 13441 } 13442 13443 /* Allocate OAM control memeory for this unit. */ 13444 _BCM_OAM_ALLOC(oc, _bcm_oam_control_t, sizeof (_bcm_oam_control_t), 13445 "OAM control"); 13446 if (NULL == oc) { 13447 return (BCM_E_MEMORY); 13448 } 13449 13450 if (soc_feature(unit, soc_feature_bhh)) { 13451 #ifdef INCLUDE_BHH 13452 /* 13453 * Initialize uController side 13454 */ 13455 13456 /* 13457 * Start BHH application in BTE (Broadcom Task Engine) uController, 13458 * if not already running (warm boot). 13459 * Determine which uController is running BHH by choosing the first 13460 * uC that returns successfully. 13461 */ 13462 for (uc = 0; uc < SOC_INFO(unit).num_ucs; uc++) { 13463 if (!soc_uc_in_reset(unit, uc)) { 13464 rv = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_BHH, 13465 _BHH_UC_MSG_TIMEOUT_USECS, 13466 BHH_SDK_VERSION, 13467 BHH_UC_MIN_VERSION, 13468 _bcm_oam_bhh_appl_callback, NULL); 13469 if (SOC_E_NONE == rv) { 13470 /* BHH started successfully */ 13471 oc->uc_num = uc; 13472 break; 13473 } 13474 } 13475 } 13476 13477 if (uc >= SOC_INFO(unit).num_ucs) { /* Could not find or start BHH appl */ 13478 ukernel_not_ready = 1; 13479 LOG_ERROR(BSL_LS_BCM_OAM, 13480 (BSL_META_U(unit, 13481 "uKernel Not Ready, bhh not started\n"))); 13482 } 13483 #endif 13484 } 13485 13486 13487 /* Get number of endpoints and groups supported by this unit. */ 13488 rv = _bcm_kt2_oam_group_endpoint_count_init(unit, oc); 13489 if (BCM_FAILURE(rv)) { 13490 _bcm_kt2_oam_control_free(unit, oc); 13491 return (rv); 13492 } 13493 13494 if (soc_feature(unit, soc_feature_bhh)) { 13495 #if defined(INCLUDE_BHH) 13496 oc->unit = unit; 13497 13498 oc->ukernel_not_ready = ukernel_not_ready; 13499 /* Get SOC properties for BHH */ 13500 oc->bhh_endpoint_count = soc_property_get(unit, spn_BHH_NUM_SESSIONS, 128); 13501 oc->bhh_max_encap_length = 13502 soc_property_get(unit, 13503 spn_BHH_ENCAP_MAX_LENGTH, 13504 _BCM_OAM_BHH_DEFAULT_ENCAP_LENGTH); 13505 13506 13507 if(oc->bhh_max_encap_length > _BCM_OAM_BHH_MAX_ENCAP_LENGTH) { 13508 LOG_ERROR(BSL_LS_BCM_OAM, 13509 (BSL_META_U(unit, 13510 "Invalid max encap_length=%u\n"), 13511 oc->bhh_max_encap_length)); 13512 return BCM_E_CONFIG; 13513 } 13514 13515 carrier_code_str = soc_property_get_str(unit, spn_BHH_CARRIER_CODE); 13516 if (carrier_code_str != NULL) { 13517 /* 13518 * Note that the carrier code is specified in colon separated 13519 * MAC address format. 13520 */ 13521 if (_shr_parse_macaddr(carrier_code_str, carrier_code) < 0) { 13522 _bcm_kt2_oam_control_free(unit, oc); 13523 return (BCM_E_INTERNAL); 13524 } 13525 } 13526 13527 node_id = soc_property_get(unit, spn_BHH_NODE_ID, 0); 13528 bhh_consolidate_final_event = soc_property_get(unit, 13529 spn_BHH_CONSOLIDATED_FINAL_EVENT, 0); 13530 oc->ep_count += oc->bhh_endpoint_count; 13531 13532 if(oc->ep_count >= _BCM_OAM_KATANA2_ENDPOINT_MAX) { 13533 LOG_ERROR(BSL_LS_BCM_OAM, 13534 (BSL_META_U(unit, 13535 "OAM Error: OAM EP count %d not supported \n"), 13536 oc->ep_count)); 13537 _bcm_kt2_oam_control_free(unit, oc); 13538 return (BCM_E_PARAM); 13539 } 13540 #endif /* INCLUDE_BHH */ 13541 } 13542 13543 _BCM_MPLS_OAM_NUM_SESSIONS = soc_property_get(unit, spn_MPLS_OAM_NUM_SESSIONS, 13544 _BCM_MPLS_OAM_NUM_SESSIONS_INVALID); 13545 13546 if(_BCM_MPLS_OAM_NUM_SESSIONS == 13547 _BCM_MPLS_OAM_NUM_SESSIONS_INVALID) { 13548 /* Entry does not exist. Revert to old scheme */ 13549 oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_COMBINED_POOL; 13550 } else if (_BCM_MPLS_OAM_NUM_SESSIONS > soc_mem_index_max(unit, MA_INDEXm)){ 13551 /* If it is greater than max index of MA_INDEX table, 13552 * set it to max_index value and set it to newer index alloc scheme. 13553 */ 13554 _BCM_MPLS_OAM_NUM_SESSIONS = soc_mem_index_max(unit, MA_INDEXm); 13555 _BCM_ETH_OAM_NUM_SESSIONS = 0; 13556 oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_SEPARATE_POOL; 13557 } else { 13558 _BCM_ETH_OAM_NUM_SESSIONS = 13559 soc_mem_index_count(unit, MA_INDEXm) - _BCM_MPLS_OAM_NUM_SESSIONS; 13560 oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_SEPARATE_POOL; 13561 } 13562 13563 /* Mem_1: Allocate hash data memory */ 13564 /* size = sizeof(_bcm_oam_hash_data_t) * oc->ep_count; */ 13565 size = sizeof(_bcm_oam_hash_data_t) * _BCM_OAM_KATANA2_ENDPOINT_MAX; 13566 13567 _BCM_OAM_ALLOC(oc->oam_hash_data, _bcm_oam_hash_data_t, size, "Hash data"); 13568 if (NULL == oc->oam_hash_data) { 13569 _bcm_kt2_oam_control_free(unit, oc); 13570 return (BCM_E_MEMORY); 13571 } 13572 13573 /* Mem_2: Allocate group memory */ 13574 size = sizeof(_bcm_oam_group_data_t) * oc->group_count; 13575 13576 _BCM_OAM_ALLOC(oc->group_info, _bcm_oam_group_data_t, size, "Group Info"); 13577 13578 if (NULL == oc->group_info) { 13579 _bcm_kt2_oam_control_free(unit, oc); 13580 return (BCM_E_MEMORY); 13581 } 13582 13583 /* Allocate RMEP H/w to logical index mapping memory */ 13584 size = sizeof(bcm_oam_endpoint_t) * oc->rmep_count; 13585 13586 _BCM_OAM_ALLOC(oc->remote_endpoints, bcm_oam_endpoint_t, size, "RMEP Mapping"); 13587 if (NULL == oc->remote_endpoints) { 13588 _bcm_kt2_oam_control_free(unit, oc); 13589 return (BCM_E_MEMORY); 13590 } 13591 /* Initialize the mapping to BCM_OAM_ENDPOINT_INVALID */ 13592 for (ep_index = 0; ep_index < oc->rmep_count; ++ep_index) { 13593 oc->remote_endpoints[ep_index] = BCM_OAM_ENDPOINT_INVALID; 13594 } 13595 13596 /* Mem_3: Create application endpoint list. */ 13597 rv = shr_idxres_list_create(&oc->mep_pool, 0, oc->ep_count - 1, 13598 0, oc->ep_count -1, "endpoint pool"); 13599 if (BCM_FAILURE(rv)) { 13600 _bcm_kt2_oam_control_free(unit, oc); 13601 return (rv); 13602 } 13603 13604 /* Mem_4: Create local MEP endpoint list. */ 13605 rv = shr_idxres_list_create(&oc->lmep_pool, 0, oc->lmep_count - 1, 13606 0, oc->lmep_count -1, "lmep pool"); 13607 if (BCM_FAILURE(rv)) { 13608 _bcm_kt2_oam_control_free(unit, oc); 13609 return (rv); 13610 } 13611 13612 /* Mem_5: Create Remote MEP endpoint list. */ 13613 rv = shr_idxres_list_create(&oc->rmep_pool, 0, oc->rmep_count - 1, 13614 0, oc->rmep_count -1, "rmep pool"); 13615 if (BCM_FAILURE(rv)) { 13616 _bcm_kt2_oam_control_free(unit, oc); 13617 return (rv); 13618 } 13619 13620 /* Mem_6: Create MEP Rx state tracker table index endpoint list - DnMEP */ 13621 rv =_bcm_kt2_oam_ma_idx_pool_create(oc); 13622 if (BCM_FAILURE(rv)) { 13623 _bcm_kt2_oam_control_free(unit, oc); 13624 return (rv); 13625 13626 } 13627 13628 /* Mem_7: Create MEP Rx state tracker table index endpoint list -UpMEP */ 13629 rv = shr_idxres_list_create(&oc->egr_ma_idx_pool, 0, 13630 oc->egr_ma_idx_count - 1, 13631 0, oc->egr_ma_idx_count -1, "egr_ma_idx pool"); 13632 if (BCM_FAILURE(rv)) { 13633 _bcm_kt2_oam_control_free(unit, oc); 13634 return (rv); 13635 13636 } 13637 13638 /* Initialize to domain specific key by default, WB recovery might 13639 * overwrite it, depending on older SDK. 13640 */ 13641 oc->eth_oam_mp_group_vlan_key = _BCM_KT2_ETH_OAM_MP_GROUP_KEY_DOMAIN_SPECIFIC; 13642 13643 if(soc_feature(unit, soc_feature_bhh)) { 13644 #if defined(INCLUDE_BHH) 13645 /* Create BHH endpoint list. */ 13646 rv = shr_idxres_list_create(&oc->bhh_pool, 0, oc->bhh_endpoint_count - 1, 13647 0, oc->bhh_endpoint_count - 1, "bhh pool"); 13648 if (BCM_FAILURE(rv)) { 13649 LOG_ERROR(BSL_LS_BCM_OAM, 13650 (BSL_META_U(unit, 13651 "OAM Error: Creating BHH pool failed \n"))); 13652 _bcm_kt2_oam_control_free(unit, oc); 13653 return (rv); 13654 } 13655 13656 /* Reserve ep pool from mep_pool for BHH, manange BHH mep using bhh_pool */ 13657 rv = shr_idxres_list_reserve(oc->mep_pool, _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET, 13658 _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET + oc->bhh_endpoint_count - 1); 13659 13660 if (BCM_FAILURE(rv)) { 13661 LOG_ERROR(BSL_LS_BCM_OAM, 13662 (BSL_META_U(unit, 13663 "OAM Error: Reserving BHH endpoints from mep_pool " 13664 "failed \n"))); 13665 _bcm_kt2_oam_control_free(unit, oc); 13666 return (rv); 13667 } 13668 13669 #endif /* INCLUDE_BHH */ 13670 } 13671 13672 /* Mem_4: Create group list. */ 13673 rv = shr_idxres_list_create(&oc->group_pool, 0, oc->group_count - 1, 13674 0, oc->group_count - 1, "group pool"); 13675 if (BCM_FAILURE(rv)) { 13676 _bcm_kt2_oam_control_free(unit, oc); 13677 return (rv); 13678 } 13679 if(soc_feature(unit, soc_feature_bhh)) { 13680 #if defined(INCLUDE_BHH) 13681 if(ukernel_not_ready == 0){ 13682 int bhh_num_lm_sec_meps = soc_property_get(unit, spn_BHH_NUM_LM_ENABLED_SECTION_MEPS, 0); 13683 int bhh_num_lm_sec_counters = bhh_num_lm_sec_meps * 8; 13684 13685 if( bhh_num_lm_sec_counters > oc->lm_counter_cnt) { 13686 LOG_ERROR(BSL_LS_BCM_OAM, 13687 (BSL_META_U(unit, 13688 "OAM Error: Number of LM enabled section meps cannot be more than " 13689 "available lm counter count \n"))); 13690 _bcm_kt2_oam_control_free(unit, oc); 13691 return (BCM_E_PARAM); 13692 } 13693 if (bhh_num_lm_sec_counters) { 13694 oc->lm_counter_cnt = oc->lm_counter_cnt - bhh_num_lm_sec_counters; 13695 13696 rv = shr_aidxres_list_create(&oc->ing_lm_sec_mep_ctr_pool, 0, 13697 bhh_num_lm_sec_counters - 1, 0, 13698 bhh_num_lm_sec_counters - 1, 8, "ing_lm_sec_mep_ctr_pool"); 13699 if (BCM_FAILURE(rv)) { 13700 _bcm_kt2_oam_control_free(unit, oc); 13701 return (rv); 13702 } 13703 } 13704 } 13705 #endif 13706 } 13707 13708 /* Index management for Ingress LM counter pool 1 */ 13709 rv = shr_aidxres_list_create(&oc->ing_lm_ctr_pool[0], 0, 13710 oc->lm_counter_cnt - 1, 0, 13711 oc->lm_counter_cnt - 1, 8, "ing_lm_idx pool1"); 13712 if (BCM_FAILURE(rv)) { 13713 _bcm_kt2_oam_control_free(unit, oc); 13714 return (rv); 13715 13716 } 13717 /* Index management for Ingress LM counter pool 2 */ 13718 rv = shr_aidxres_list_create(&oc->ing_lm_ctr_pool[1], 0, 13719 oc->lm_counter_cnt - 1, 0, 13720 oc->lm_counter_cnt - 1, 8, "ing_lm_idx pool2"); 13721 if (BCM_FAILURE(rv)) { 13722 _bcm_kt2_oam_control_free(unit, oc); 13723 return (rv); 13724 } 13725 13726 13727 /* Mem_5: Create MA group and MEP hash table. */ 13728 rv = shr_htb_create(&oc->ma_mep_htbl, _BCM_OAM_KATANA2_ENDPOINT_MAX, 13729 sizeof(_bcm_oam_hash_key_t), "MA/MEP Hash"); 13730 if (BCM_FAILURE(rv)) { 13731 _bcm_kt2_oam_control_free(unit, oc); 13732 return (rv); 13733 } 13734 13735 /* Create protection mutex. */ 13736 oc->oc_lock = sal_mutex_create("oam_control.lock"); 13737 if (NULL == oc->oc_lock) { 13738 _bcm_kt2_oam_control_free(unit, oc); 13739 return (BCM_E_MEMORY); 13740 } 13741 13742 /* Register device OAM interrupt handler & SER handler call back routine.*/ 13743 soc_kt2_oam_handler_register(unit, _bcm_kt2_oam_handle_interrupt); 13744 soc_kt2_oam_ser_handler_register(unit, _bcm_kt2_oam_ser_handler); 13745 13746 /* Set up the unit OAM control structure. */ 13747 _kt2_oam_control[unit] = oc; 13748 #if defined (INCLUDE_BHH) 13749 if (soc_feature(unit, soc_feature_oam_pm)) { 13750 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_pm_init(unit)); 13751 } 13752 #endif 13753 /* Set up OAM module related profile tables. */ 13754 rv = _bcm_kt2_oam_profile_tables_init(unit, oc); 13755 if (BCM_FAILURE(rv)) { 13756 _bcm_kt2_oam_control_free(unit, oc); 13757 return (rv); 13758 } 13759 13760 /* Initialize all the TPID tables */ 13761 rv = _bcm_kt2_outer_tpid_init(unit); 13762 if (BCM_FAILURE(rv)) { 13763 _bcm_kt2_oam_control_free(unit, oc); 13764 return (rv); 13765 } 13766 rv = _bcm_kt2_inner_tpid_init(unit); 13767 if (BCM_FAILURE(rv)) { 13768 _bcm_kt2_oam_control_free(unit, oc); 13769 return (rv); 13770 } 13771 rv = _bcm_kt2_subport_tpid_init(unit); 13772 if (BCM_FAILURE(rv)) { 13773 _bcm_kt2_oam_control_free(unit, oc); 13774 return (rv); 13775 } 13776 rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_init(unit); 13777 if (BCM_FAILURE(rv)) { 13778 _bcm_kt2_oam_control_free(unit, oc); 13779 return rv; 13780 } 13781 13782 13783 #if defined(BCM_WARM_BOOT_SUPPORT) 13784 if(!SOC_WARM_BOOT(unit)) { 13785 bcm_kt2_oam_scache_alloc(unit); 13786 } 13787 if (SOC_WARM_BOOT(unit)) { 13788 rv = _bcm_kt2_oam_reinit(unit); 13789 if (BCM_FAILURE(rv)) { 13790 _bcm_kt2_oam_control_free(unit, oc); 13791 return (rv); 13792 } 13793 } else 13794 #endif 13795 { 13796 BCM_PBMP_CLEAR(all_pbmp); 13797 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 13798 13799 if (soc_feature(unit, soc_feature_flex_port)) { 13800 BCM_IF_ERROR_RETURN(_bcm_kt2_flexio_pbmp_update(unit, &all_pbmp)); 13801 } 13802 if (soc_feature(unit, soc_feature_linkphy_coe) || 13803 soc_feature(unit, soc_feature_subtag_coe)) { 13804 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 13805 } 13806 13807 /* Enable OAM processing on all ports of this unit. */ 13808 PBMP_ITER(all_pbmp, port) { 13809 rv = bcm_esw_port_control_set(unit, port, bcmPortControlOAMEnable, 13810 TRUE); 13811 if (BCM_FAILURE(rv)) { 13812 _bcm_kt2_oam_control_free(unit, oc); 13813 return (rv); 13814 } 13815 } 13816 13817 /* Enable CCM Rx timeouts. */ 13818 rv = _bcm_kt2_oam_ccm_rx_timeout_set(unit, 1); 13819 if (BCM_FAILURE(rv)) { 13820 _bcm_kt2_oam_control_free(unit, oc); 13821 return (rv); 13822 } 13823 13824 /* Enable CCM Tx control. */ 13825 rv = _bcm_kt2_oam_ccm_tx_config_set(unit, 1); 13826 if (BCM_FAILURE(rv)) { 13827 _bcm_kt2_oam_control_free(unit, oc); 13828 return (rv); 13829 } 13830 13831 13832 /* 13833 * Misc config: Enable IFP lookup on the CPU port. 13834 */ 13835 rv = _bcm_kt2_oam_misc_config(unit); 13836 if (BCM_FAILURE(rv)) { 13837 _bcm_kt2_oam_control_free(unit, oc); 13838 return (rv); 13839 } 13840 /* Set all the non CFM opcodes in opcode group -1 */ 13841 oc->opcode_grp_bmp[0] = ~(_BCM_OAM_OPCODE_TYPE_CFM_MASK); 13842 oc->opcode_grp_1_bmp[0] = 0; 13843 oc->opcode_grp_2_bmp[0] = 0; 13844 for (index = 1; index < 8; index ++) { 13845 oc->opcode_grp_bmp[index] = _BCM_OAM_OPCODE_TYPE_NON_CFM_MASK; 13846 oc->opcode_grp_1_bmp[index] = 0; 13847 oc->opcode_grp_2_bmp[index] = 0; 13848 } 13849 /* Init OAM opcode group */ 13850 rv =_bcm_kt2_oam_opcode_group_init(unit); 13851 if (BCM_FAILURE(rv)) { 13852 _bcm_kt2_oam_control_free(unit, oc); 13853 return (rv); 13854 } 13855 /* Set default values for flexible oam domain control */ 13856 rv = _bcm_kt2_oam_flexible_oam_domain_ctrl_set(unit); 13857 if (BCM_FAILURE(rv)) { 13858 _bcm_kt2_oam_control_free(unit, oc); 13859 return (rv); 13860 } 13861 /* Set default values for flexible ingress and egress drop control */ 13862 rv = _bcm_kt2_oam_flexible_drop_ctrl_set(unit); 13863 if (BCM_FAILURE(rv)) { 13864 _bcm_kt2_oam_control_free(unit, oc); 13865 return (rv); 13866 } 13867 /* Set default values for s-interface passive processing control */ 13868 rv = _bcm_kt2_oam_s_intf_passive_proc_ctrl_set(unit); 13869 if (BCM_FAILURE(rv)) { 13870 _bcm_kt2_oam_control_free(unit, oc); 13871 return (rv); 13872 } 13873 /* Enable OLP handling on HG ports */ 13874 rv = _bcm_kt2_oam_hg_olp_enable(unit); 13875 if (BCM_FAILURE(rv)) { 13876 _bcm_kt2_oam_control_free(unit, oc); 13877 return (rv); 13878 } 13879 /* Set default olp header type mapping */ 13880 rv = _bcm_kt2_oam_olp_header_type_mapping_set(unit); 13881 if (BCM_FAILURE(rv)) { 13882 _bcm_kt2_oam_control_free(unit, oc); 13883 return (rv); 13884 } 13885 /* Set OAM drop control to not to drop wrong version OAM packets */ 13886 rv = _bcm_kt2_oam_drop_ctrl_set(unit); 13887 if (BCM_FAILURE(rv)) { 13888 _bcm_kt2_oam_control_free(unit, oc); 13889 return (rv); 13890 } 13891 /* Set OAM LM cng and cpu data control*/ 13892 rv = _bcm_kt2_oam_lm_cng_cpu_ctrl_set_default(unit); 13893 if (BCM_FAILURE(rv)) { 13894 _bcm_kt2_oam_control_free(unit, oc); 13895 return (rv); 13896 } 13897 /* Set Magic port used in OLP-XGS communication */ 13898 rv = _bcm_kt2_oam_olp_magic_port_set(unit); 13899 if (BCM_FAILURE(rv)) { 13900 _bcm_kt2_oam_control_free(unit, oc); 13901 return (rv); 13902 } 13903 /* Disable MACSA Zero check */ 13904 rv = _bcm_kt2_oam_macsa_zero_check_disable(unit); 13905 if (BCM_FAILURE(rv)) { 13906 _bcm_kt2_oam_control_free(unit, oc); 13907 return (rv); 13908 } 13909 13910 } 13911 13912 /* 13913 * BHH init 13914 */ 13915 if(soc_feature(unit, soc_feature_bhh)) { 13916 #if defined(INCLUDE_BHH) 13917 if(ukernel_not_ready == 0){ 13918 /* 13919 * Initialize HOST side 13920 */ 13921 oc->cpu_cosq = soc_property_get(unit, spn_BHH_COSQ, BHH_COSQ_INVALID); 13922 13923 /* 13924 * Allocate DMA buffers 13925 * 13926 * DMA buffer will be used to send and receive 'long' messages 13927 * between SDK Host and uController (BTE). 13928 */ 13929 oc->dma_buffer_len = sizeof(shr_bhh_msg_ctrl_t); 13930 13931 /* Adding feature specific for dma_buf_len as currently 13932 * required buffer length for faults_get can be configurable 13933 * by user during init. So, taking the max value of either of 13934 * them for the purpose.Putting it under fature_check for 13935 * giving flexibility to user. 13936 */ 13937 #ifdef INCLUDE_OAM_FAULTS_MULTI_GET 13938 if(soc_feature(unit, soc_feature_faults_multi_ep_get)) { 13939 oc->dma_buffer_len = MAX((oc->bhh_endpoint_count * sizeof(uint32)), oc->dma_buffer_len); 13940 } 13941 #endif 13942 oc->dma_buffer = soc_cm_salloc(unit, oc->dma_buffer_len, 13943 "BHH DMA buffer"); 13944 if (!oc->dma_buffer) { 13945 _bcm_kt2_oam_control_free(unit, oc); 13946 return (BCM_E_MEMORY); 13947 } 13948 sal_memset(oc->dma_buffer, 0, oc->dma_buffer_len); 13949 13950 oc->dmabuf_reply = soc_cm_salloc(unit, oc->dma_buffer_len, 13951 "BHH uC reply"); 13952 if (!oc->dmabuf_reply) { 13953 _bcm_kt2_oam_control_free(unit, oc); 13954 return (BCM_E_MEMORY); 13955 } 13956 sal_memset(oc->dmabuf_reply, 0, oc->dma_buffer_len); 13957 13958 /* RX DMA channel (0..3) local to the uC */ 13959 oc->rx_channel = BCM_KT_BHH_RX_CHANNEL; 13960 13961 #if defined(BCM_WARM_BOOT_SUPPORT) 13962 if (!SOC_WARM_BOOT(unit)) { 13963 #endif 13964 /* Set control message data */ 13965 sal_memset(&msg_init, 0, sizeof(msg_init)); 13966 msg_init.num_sessions = oc->bhh_endpoint_count; 13967 msg_init.rx_channel = oc->rx_channel; 13968 msg_init.node_id = node_id; 13969 sal_memcpy(msg_init.carrier_code, carrier_code, SHR_BHH_CARRIER_CODE_LEN); 13970 msg_init.max_encap_length = oc->bhh_max_encap_length; 13971 if (bhh_consolidate_final_event) { 13972 msg_init.flags |= BHH_SDK_MSG_CTRL_INIT_ONLY_FINAL_EVENT; 13973 } 13974 13975 msg_init.data_collection_mode = oc->pm_bhh_lmdm_data_collection_mode; 13976 13977 /* Pack control message data into DMA buffer */ 13978 buffer = oc->dma_buffer; 13979 buffer_ptr = bhh_sdk_msg_ctrl_init_pack(unit, buffer, &msg_init); 13980 buffer_len = buffer_ptr - buffer; 13981 13982 /* Send BHH Init message to uC */ 13983 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 13984 MOS_MSG_SUBCLASS_BHH_INIT, 13985 buffer_len, 0, 13986 MOS_MSG_SUBCLASS_BHH_INIT_REPLY, 13987 &reply_len); 13988 13989 if (BCM_FAILURE(rv) || (reply_len != 0)) { 13990 _bcm_kt2_oam_control_free(unit, oc); 13991 return (BCM_E_INTERNAL); 13992 } 13993 #if defined(BCM_WARM_BOOT_SUPPORT) 13994 } 13995 #endif 13996 /* 13997 * Start event message callback thread 13998 */ 13999 priority = soc_property_get(unit, spn_BHH_THREAD_PRI, BHH_THREAD_PRI_DFLT); 14000 14001 if (oc->event_thread_id == NULL) { 14002 if ((oc->event_thread_id = 14003 sal_thread_create("bcmBHH", SAL_THREAD_STKSZ, 14004 priority, 14005 _bcm_kt2_oam_bhh_callback_thread, 14006 (void*)oc)) == SAL_THREAD_ERROR) { 14007 oc->event_thread_id = NULL; 14008 BCM_IF_ERROR_RETURN(bcm_kt2_oam_detach(unit)); 14009 return (BCM_E_MEMORY); 14010 } 14011 } 14012 /* 14013 * End BHH init 14014 */ 14015 } 14016 /* 14017 * Initialize HW 14018 */ 14019 #ifdef BCM_WARM_BOOT_SUPPORT 14020 if (SOC_WARM_BOOT(unit)) { 14021 rv = _bcm_kt2_oam_bhh_cos_map_recover(unit); 14022 } else 14023 #endif 14024 { 14025 rv = _bcm_kt2_oam_bhh_hw_init(unit); 14026 } 14027 14028 if (BCM_FAILURE(rv)) { 14029 BCM_IF_ERROR_RETURN(bcm_kt2_oam_detach(unit)); 14030 return rv; 14031 } 14032 14033 #endif /* INCLUDE_BHH */ 14034 } 14035 14036 /* OAM initialization complete. */ 14037 _kt2_oam_control[unit]->init = TRUE; 14038 return (BCM_E_NONE); 14039 } 14040 14041 /* 14042 * Function: 14043 * bcm_kt2_oam_detach 14044 * Purpose: 14045 * Shut down OAM subsystem 14046 * Parameters: 14047 * unit - (IN) BCM device number 14048 * Returns: 14049 * BCM_E_XXX 14050 */ 14051 int 14052 bcm_kt2_oam_detach(int unit) 14053 { 14054 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 14055 bcm_port_t port; /* Port number. */ 14056 int rv; /* Operation return status. */ 14057 bcm_pbmp_t all_pbmp; 14058 #if defined(INCLUDE_BHH) 14059 uint16 reply_len; 14060 sal_usecs_t timeout = 0; 14061 #endif 14062 14063 /* Get the device OAM module handle. */ 14064 oc = _kt2_oam_control[unit]; 14065 if (NULL == oc) { 14066 /* Module already uninitialized. */ 14067 return (BCM_E_NONE); 14068 } 14069 14070 /* Unregister all OAM interrupt event handlers and SER handler. */ 14071 soc_kt2_oam_handler_register(unit, NULL); 14072 soc_kt2_oam_ser_handler_register(unit, NULL); 14073 14074 if (NULL != oc->oc_lock) { 14075 _BCM_OAM_LOCK(oc); 14076 } 14077 14078 rv = _bcm_kt2_oam_events_unregister(unit, oc); 14079 if (BCM_FAILURE(rv)) { 14080 if (NULL != oc->oc_lock) { 14081 _BCM_OAM_UNLOCK(oc); 14082 } 14083 return (rv); 14084 } 14085 14086 /* Disable CCM Rx Timeouts. */ 14087 rv = _bcm_kt2_oam_ccm_rx_timeout_set(unit, 0); 14088 if (BCM_FAILURE(rv)) { 14089 if (NULL != oc->oc_lock) { 14090 _BCM_OAM_UNLOCK(oc); 14091 } 14092 return (rv); 14093 } 14094 14095 /* Disable CCM Tx control for the device. */ 14096 rv = _bcm_kt2_oam_ccm_tx_config_set(unit, 0); 14097 if (BCM_FAILURE(rv)) { 14098 if (NULL != oc->oc_lock) { 14099 _BCM_OAM_UNLOCK(oc); 14100 } 14101 return (rv); 14102 } 14103 14104 BCM_PBMP_CLEAR(all_pbmp); 14105 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 14106 14107 if (soc_feature(unit, soc_feature_flex_port)) { 14108 rv = _bcm_kt2_flexio_pbmp_update(unit, &all_pbmp); 14109 if (BCM_FAILURE(rv)) { 14110 _BCM_OAM_UNLOCK(oc); 14111 return rv; 14112 } 14113 } 14114 if (soc_feature(unit, soc_feature_linkphy_coe) || 14115 soc_feature(unit, soc_feature_subtag_coe)) { 14116 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 14117 } 14118 14119 /* Disable OAM PDU Rx processing on all ports. */ 14120 PBMP_ITER(all_pbmp, port) { 14121 rv = bcm_esw_port_control_set(unit, port, 14122 bcmPortControlOAMEnable, 0); 14123 if (BCM_FAILURE(rv)) { 14124 if (NULL != oc->oc_lock) { 14125 _BCM_OAM_UNLOCK(oc); 14126 } 14127 return (rv); 14128 } 14129 } 14130 14131 14132 /* 14133 * BHH specific 14134 */ 14135 if (soc_feature(unit, soc_feature_bhh)) { 14136 #if defined(INCLUDE_BHH) 14137 if (oc->ukernel_not_ready == 0) { 14138 /* 14139 * Event Handler thread exit signal 14140 */ 14141 timeout = sal_time_usecs() + 5000000; 14142 while (NULL != oc->event_thread_id) { 14143 soc_cmic_uc_msg_receive_cancel(unit, oc->uc_num, 14144 MOS_MSG_CLASS_BHH_EVENT); 14145 14146 if (sal_time_usecs() < timeout) { 14147 /*give some time to already running bhh callback thread 14148 * to schedule and exit */ 14149 sal_usleep(10000); 14150 } else { 14151 /*timeout*/ 14152 LOG_ERROR(BSL_LS_BCM_OAM, 14153 (BSL_META_U(unit, 14154 "BHH event thread did not exit.\n"))); 14155 _BCM_OAM_UNLOCK(oc); 14156 return BCM_E_INTERNAL; 14157 } 14158 } 14159 14160 /* 14161 * Send BHH Uninit message to uC 14162 * Ignore error since that may indicate uKernel was reloaded. 14163 */ 14164 #if defined(BCM_WARM_BOOT_SUPPORT) 14165 if (!SOC_WARM_BOOT(unit)) { 14166 #endif 14167 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 14168 MOS_MSG_SUBCLASS_BHH_UNINIT, 14169 0, 0, 14170 MOS_MSG_SUBCLASS_BHH_UNINIT_REPLY, 14171 &reply_len); 14172 if (BCM_SUCCESS(rv) && (reply_len != 0)) { 14173 if (NULL != oc->oc_lock) { 14174 _BCM_OAM_UNLOCK(oc); 14175 } 14176 return BCM_E_INTERNAL; 14177 } 14178 #if defined(BCM_WARM_BOOT_SUPPORT) 14179 } 14180 #endif 14181 14182 /* 14183 * Delete CPU COS queue mapping entries for BHH packets 14184 */ 14185 if (!SOC_WARM_BOOT(unit)) { 14186 if (oc->cpu_cosq_ach_error_index >= 0) { 14187 rv = bcm_esw_rx_cosq_mapping_delete(unit, 14188 oc->cpu_cosq_ach_error_index); 14189 if (BCM_FAILURE(rv)) { 14190 if (NULL != oc->oc_lock) { 14191 _BCM_OAM_UNLOCK(oc); 14192 } 14193 return (rv); 14194 } 14195 oc->cpu_cosq_ach_error_index = -1; 14196 } 14197 if (oc->cpu_cosq_invalid_error_index >= 0) { 14198 rv = bcm_esw_rx_cosq_mapping_delete(unit, 14199 oc->cpu_cosq_invalid_error_index); 14200 if (BCM_FAILURE(rv)) { 14201 if (NULL != oc->oc_lock) { 14202 _BCM_OAM_UNLOCK(oc); 14203 } 14204 return (rv); 14205 } 14206 oc->cpu_cosq_invalid_error_index = -1; 14207 } 14208 if (oc->bhh_lb_index >= 0) { 14209 rv = bcm_esw_rx_cosq_mapping_delete(unit, 14210 oc->bhh_lb_index); 14211 if (BCM_FAILURE(rv)) { 14212 if (NULL != oc->oc_lock) { 14213 _BCM_OAM_UNLOCK(oc); 14214 } 14215 return (rv); 14216 } 14217 oc->bhh_lb_index = -1; 14218 } 14219 } 14220 } 14221 #endif /* INCLUDE_BHH */ 14222 } 14223 14224 /* Destroy all groups and assoicated endpoints and free the resources. */ 14225 rv = bcm_kt2_oam_group_destroy_all(unit); 14226 if (BCM_FAILURE(rv)) { 14227 if (NULL != oc->oc_lock) { 14228 _BCM_OAM_UNLOCK(oc); 14229 } 14230 return (rv); 14231 } 14232 rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_destroy(unit); 14233 if (BCM_FAILURE(rv)) { 14234 if (NULL != oc->oc_lock) { 14235 _BCM_OAM_UNLOCK(oc); 14236 } 14237 return (rv); 14238 } 14239 14240 /* Release the protection mutex. */ 14241 _BCM_OAM_UNLOCK(oc); 14242 14243 /* Free OAM module allocated resources. */ 14244 _bcm_kt2_oam_control_free(unit, oc); 14245 14246 return (BCM_E_NONE); 14247 } 14248 14249 /* 14250 * Function: 14251 * bcm_kt2_oam_group_create 14252 * Purpose: 14253 * Create or replace an OAM group object 14254 * Parameters: 14255 * unit - (IN) BCM device number 14256 * group_info - (IN/OUT) Pointer to an OAM group information. 14257 * Returns: 14258 * BCM_E_XXX 14259 */ 14260 int 14261 bcm_kt2_oam_group_create(int unit, bcm_oam_group_info_t *group_info) 14262 { 14263 ma_state_entry_t ma_state_entry; /* MA State table entry. */ 14264 uint8 grp_name_hw_buf[BCM_OAM_GROUP_NAME_LENGTH]; /* Grp */ 14265 /* name. */ 14266 maid_reduction_entry_t maid_reduction_entry; /* MA ID reduction table */ 14267 _bcm_oam_group_data_t *ma_group; /* Pointer to group info. */ 14268 _bcm_oam_control_t *oc; /* OAM control structure. */ 14269 int rv; /* Operation return status. */ 14270 /* entry. */ 14271 uint8 sw_rdi; /* Remote defect indicator. */ 14272 14273 #if defined(BCM_KATANA2_SUPPORT) && defined(INCLUDE_BHH) 14274 bhh_sdk_msg_ctrl_sess_set_t msg_sess; 14275 uint8 *buffer, *buffer_ptr; 14276 uint16 buffer_len, reply_len; 14277 uint32 session_flags = 0; 14278 _bcm_oam_hash_data_t *h_data_p; 14279 _bcm_oam_ep_list_t *cur; 14280 #endif 14281 14282 /* Validate input parameter. */ 14283 if (NULL == group_info) { 14284 return (BCM_E_PARAM); 14285 } 14286 14287 /* Get OAM control structure handle. */ 14288 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 14289 14290 /* Validate group id. */ 14291 if (group_info->flags & BCM_OAM_GROUP_WITH_ID) { 14292 _BCM_OAM_GROUP_INDEX_VALIDATE(group_info->id); 14293 } 14294 14295 _BCM_OAM_LOCK(oc); 14296 14297 /* 14298 * If MA group create is called with replace flag bit set. 14299 * - Check and return error if a group does not exist with the ID. 14300 */ 14301 if (group_info->flags & BCM_OAM_GROUP_REPLACE) { 14302 if (group_info->flags & BCM_OAM_GROUP_WITH_ID) { 14303 14304 /* Search the list with the MA Group ID value. */ 14305 rv = shr_idxres_list_elem_state(oc->group_pool, group_info->id); 14306 if (BCM_E_EXISTS != rv) { 14307 _BCM_OAM_UNLOCK(oc); 14308 LOG_ERROR(BSL_LS_BCM_OAM, 14309 (BSL_META_U(unit, 14310 "OAM Error: Group does not exist.\n"))); 14311 return (BCM_E_PARAM); 14312 } 14313 } else { 14314 _BCM_OAM_UNLOCK(oc); 14315 LOG_ERROR(BSL_LS_BCM_OAM, 14316 (BSL_META_U(unit, 14317 "OAM Error: Replace command needs a " 14318 "valid Group ID.\n"))); 14319 return (BCM_E_PARAM); 14320 } 14321 } else if (group_info->flags & BCM_OAM_GROUP_WITH_ID) { 14322 /* 14323 * If MA group create is called with ID flag bit set. 14324 * - Check and return error if the ID is already in use. 14325 */ 14326 rv = shr_idxres_list_reserve(oc->group_pool, group_info->id, 14327 group_info->id); 14328 if (BCM_FAILURE(rv)) { 14329 _BCM_OAM_UNLOCK(oc); 14330 return ((rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv); 14331 } 14332 } else { 14333 /* Reserve the next available group index. */ 14334 rv = shr_idxres_list_alloc(oc->group_pool, 14335 (shr_idxres_element_t *) &group_info->id); 14336 if (BCM_FAILURE(rv)) { 14337 _BCM_OAM_UNLOCK(oc); 14338 LOG_ERROR(BSL_LS_BCM_OAM, 14339 (BSL_META_U(unit, 14340 "OAM Error: Group allocation (GID=%d)" 14341 " %s\n"), group_info->id, bcm_errmsg(rv))); 14342 return (rv); 14343 } 14344 } 14345 14346 /* Get this group memory to store group information. */ 14347 ma_group = &oc->group_info[group_info->id]; 14348 14349 /* Store the group name. */ 14350 sal_memcpy(&ma_group->name, &group_info->name, BCM_OAM_GROUP_NAME_LENGTH); 14351 14352 /* Store Lowest Alarm Priority */ 14353 ma_group->lowest_alarm_priority = group_info->lowest_alarm_priority; 14354 14355 if(!(group_info->flags & BCM_OAM_GROUP_REPLACE)) { 14356 _BCM_OAM_ALLOC((ma_group->ep_list),_bcm_oam_ep_list_t *, 14357 sizeof(_bcm_oam_ep_list_t *), "EP list head"); 14358 14359 /* Initialize head to NULL.*/ 14360 *ma_group->ep_list = NULL; 14361 } 14362 14363 /* 14364 * Maintenance Association ID - Reduction table update. 14365 */ 14366 14367 /* Prepare group name for hardware write. */ 14368 _bcm_kt2_oam_group_name_mangle(ma_group->name, grp_name_hw_buf); 14369 14370 sal_memset(&maid_reduction_entry, 0, sizeof(maid_reduction_entry_t)); 14371 14372 /* Calculate CRC32 value for the group name string and set in entry. */ 14373 soc_MAID_REDUCTIONm_field32_set 14374 (unit, &maid_reduction_entry, REDUCED_MAIDf, 14375 soc_draco_crc32(grp_name_hw_buf, BCM_OAM_GROUP_NAME_LENGTH)); 14376 14377 /* Check if software RDI flag bit needs to be set in hardware. */ 14378 sw_rdi = ((group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) ? 1 : 0); 14379 14380 /* Set RDI status for out going CCM PDUs. */ 14381 soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, SW_RDIf, 14382 sw_rdi); 14383 14384 if (soc_feature(unit, soc_feature_bhh)) { 14385 #if defined(BCM_KATANA2_SUPPORT) && defined(INCLUDE_BHH) 14386 /* Send message to uC to set the Soft RDI */ 14387 if (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) { 14388 14389 /* Get the endpoint list head pointer. */ 14390 cur = *(ma_group->ep_list); 14391 14392 while (NULL != cur) { 14393 h_data_p = cur->ep_data_p; 14394 if (NULL == h_data_p) { 14395 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 14396 "OAM Error: Group=%d endpoints access failed -" 14397 " %s.\n"), group_info->id, 14398 bcm_errmsg(BCM_E_INTERNAL))); 14399 _BCM_OAM_UNLOCK(oc); 14400 return (BCM_E_INTERNAL); 14401 } 14402 if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_BHH) { 14403 /* Set the RDI flag in session bits */ 14404 session_flags |= SHR_BHH_SESS_SET_F_RDI; 14405 14406 /* Get the session is from endpoint */ 14407 msg_sess.sess_id = 14408 BCM_OAM_BHH_GET_UKERNEL_EP(h_data_p->ep_id); 14409 14410 /* Pack control message data into DMA buffer */ 14411 msg_sess.flags = session_flags; 14412 14413 buffer = oc->dma_buffer; 14414 buffer_ptr = 14415 bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess); 14416 buffer_len = buffer_ptr - buffer; 14417 14418 /* Send BHH Session Update message to uC */ 14419 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 14420 MOS_MSG_SUBCLASS_BHH_SESS_SET, 14421 buffer_len, 0, 14422 MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY, 14423 &reply_len); 14424 if (BCM_FAILURE(rv)) { 14425 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 14426 "OAM Error: ukernel msg failed for" 14427 "%s.\n"), bcm_errmsg(rv))); 14428 _BCM_OAM_UNLOCK(oc); 14429 return (BCM_E_INTERNAL); 14430 } 14431 } 14432 cur = cur->next; 14433 } 14434 } 14435 #endif 14436 } 14437 14438 /* Enable hardware lookup for this entry. */ 14439 soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, VALIDf, 1); 14440 14441 14442 /* Write entry to hardware. */ 14443 rv = WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL, group_info->id, 14444 &maid_reduction_entry); 14445 if (BCM_FAILURE(rv)) { 14446 _BCM_OAM_UNLOCK(oc); 14447 return rv; 14448 } 14449 14450 /* 14451 * Maintenance Association State table update. 14452 */ 14453 sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t)); 14454 14455 /* 14456 * If it is a group info replace operation, retain previous group 14457 * defect status. 14458 */ 14459 if (group_info->flags & BCM_OAM_GROUP_REPLACE) { 14460 rv = READ_MA_STATEm(unit, MEM_BLOCK_ALL, group_info->id, 14461 &ma_state_entry); 14462 if (BCM_FAILURE(rv)) { 14463 _BCM_OAM_UNLOCK(oc); 14464 return rv; 14465 } 14466 } 14467 14468 /* Set the lowest alarm priority info. */ 14469 soc_MA_STATEm_field32_set(unit, &ma_state_entry, LOWESTALARMPRIf, 14470 group_info->lowest_alarm_priority); 14471 14472 /* Mark the entry as valid. */ 14473 soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, 1); 14474 14475 /* Write group information to hardware table. */ 14476 rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group_info->id, 14477 &ma_state_entry); 14478 if (BCM_FAILURE(rv)) { 14479 _BCM_OAM_UNLOCK(oc); 14480 return rv; 14481 } 14482 14483 /* Make the group as in used status. */ 14484 ma_group->in_use = 1; 14485 14486 _BCM_OAM_UNLOCK(oc); 14487 14488 #ifdef BCM_WARM_BOOT_SUPPORT 14489 SOC_CONTROL_LOCK(unit); 14490 SOC_CONTROL(unit)->scache_dirty = 1; 14491 SOC_CONTROL_UNLOCK(unit); 14492 #endif 14493 14494 return BCM_E_NONE; 14495 } 14496 14497 #if defined(INCLUDE_BHH) 14498 /* 14499 * Function: 14500 * _bcm_kt2_oam_get_group_sw_rdi 14501 * Purpose: 14502 * Get OAM group SW RDI information. 14503 * Parameters: 14504 * unit - (IN) BCM device number 14505 * group_index - (IN) Group hardware table index 14506 * group_sw_rdi - (OUT) Pointer to group SW RDI 14507 * Returns: 14508 * BCM_E_NONE - No errors. 14509 * BCM_E_XXX - Otherwise. 14510 */ 14511 STATIC int 14512 _bcm_kt2_oam_get_group_sw_rdi(int unit, bcm_oam_group_t group_index, 14513 uint8 *group_sw_rdi) 14514 { 14515 maid_reduction_entry_t maid_reduction_entry; /* MAID reduction entry. */ 14516 14517 BCM_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, 14518 group_index, 14519 &maid_reduction_entry)); 14520 14521 if (1 == soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry, 14522 SW_RDIf)) { 14523 *group_sw_rdi = 1; 14524 } 14525 return (BCM_E_NONE); 14526 } 14527 #endif 14528 14529 /* 14530 * Function: 14531 * bcm_kt2_oam_group_get 14532 * Purpose: 14533 * Get an OAM group object 14534 * Parameters: 14535 * unit - (IN) BCM device number 14536 * group - (IN) OAM Group ID. 14537 * group_info - (OUT) Pointer to group information buffer. 14538 * Returns: 14539 * BCM_E_XXX 14540 */ 14541 int 14542 bcm_kt2_oam_group_get(int unit, bcm_oam_group_t group, 14543 bcm_oam_group_info_t *group_info) 14544 { 14545 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 14546 _bcm_oam_group_data_t *group_p; /* Pointer to group list. */ 14547 int rv; /* Operation return status. */ 14548 14549 #if defined(INCLUDE_BHH) 14550 bhh_sdk_msg_ctrl_sess_get_t msg; 14551 uint8 *buffer, *buffer_ptr; 14552 uint16 buffer_len, reply_len; 14553 _bcm_oam_hash_data_t *h_data_p; 14554 _bcm_oam_ep_list_t *cur = NULL; 14555 int sess_id = 0; 14556 #endif 14557 14558 /* Validate input parameter. */ 14559 if (NULL == group_info) { 14560 return (BCM_E_PARAM); 14561 } 14562 14563 /* Get OAM device control structure. */ 14564 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 14565 14566 /* Validate group index. */ 14567 _BCM_OAM_GROUP_INDEX_VALIDATE(group); 14568 14569 _BCM_OAM_LOCK(oc); 14570 14571 /* Check if the group is in use. */ 14572 rv = shr_idxres_list_elem_state(oc->group_pool, group); 14573 if (BCM_E_EXISTS != rv) { 14574 _BCM_OAM_UNLOCK(oc); 14575 LOG_ERROR(BSL_LS_BCM_OAM, 14576 (BSL_META_U(unit, 14577 "OAM Error: GID=%d - %s.\n"), 14578 group, bcm_errmsg(rv))); 14579 return (rv); 14580 } 14581 14582 /* Get pointer to this group in the group list. */ 14583 group_p = oc->group_info; 14584 14585 /* Get the group information. */ 14586 rv = _bcm_kt2_oam_get_group(unit, group, group_p, group_info); 14587 if (BCM_FAILURE(rv)) { 14588 _BCM_OAM_UNLOCK(oc); 14589 LOG_ERROR(BSL_LS_BCM_OAM, 14590 (BSL_META_U(unit, 14591 "OAM Error: bcm_kt2_oam_group_get Group ID=%d " 14592 "- Failed.\n"), group)); 14593 return (rv); 14594 } 14595 14596 if (soc_feature(unit, soc_feature_bhh)) { 14597 #if defined(INCLUDE_BHH) 14598 14599 if (!oc->ukernel_not_ready) { 14600 group_p = &oc->group_info[group_info->id]; 14601 /* Get the endpoint list head pointer. */ 14602 if (group_p->ep_list != NULL) { 14603 cur = *(group_p->ep_list); 14604 } 14605 14606 while (NULL != cur) { 14607 h_data_p = cur->ep_data_p; 14608 if (NULL == h_data_p) { 14609 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 14610 "OAM(unit %d) Error: Group=%d endpoints access failed -" 14611 " %s.\n"), unit, group_info->id, 14612 bcm_errmsg(BCM_E_INTERNAL))); 14613 _BCM_OAM_UNLOCK(oc); 14614 return (BCM_E_INTERNAL); 14615 } 14616 if ((h_data_p->oam_domain == _BCM_OAM_DOMAIN_BHH) && 14617 !(h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) { 14618 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(h_data_p->ep_id); 14619 rv = _bcm_kt2_oam_bhh_msg_send_receive( 14620 unit, 14621 MOS_MSG_SUBCLASS_BHH_SESS_GET, 14622 sess_id, 0, 14623 MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY, 14624 &reply_len); 14625 if (BCM_FAILURE(rv)) { 14626 LOG_ERROR(BSL_LS_BCM_OAM, 14627 (BSL_META_U(unit, 14628 "OAM(unit %d) Error: ukernel msg failed for" 14629 "EP=%d %s.\n"), unit, h_data_p->ep_id, 14630 bcm_errmsg(rv))); 14631 _BCM_OAM_UNLOCK(oc); 14632 return (rv); 14633 } 14634 14635 /* Pack control message data into DMA buffer */ 14636 buffer = oc->dma_buffer; 14637 buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg); 14638 buffer_len = buffer_ptr - buffer; 14639 14640 if (reply_len != buffer_len) { 14641 rv = BCM_E_INTERNAL; 14642 LOG_ERROR(BSL_LS_BCM_OAM, 14643 (BSL_META_U(unit, 14644 "OAM(unit %d) Error: ukernel msg failed for" 14645 " EP=%d %s.\n"), unit, h_data_p->ep_id, 14646 bcm_errmsg(rv))); 14647 _BCM_OAM_UNLOCK(oc); 14648 return (rv); 14649 } else { 14650 if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){ 14651 group_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT; 14652 } 14653 if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){ 14654 group_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI; 14655 } 14656 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){ 14657 group_info->faults |= 14658 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL; 14659 } 14660 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){ 14661 group_info->faults |= 14662 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID; 14663 } 14664 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){ 14665 group_info->faults |= 14666 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID; 14667 } 14668 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){ 14669 group_info->faults |= 14670 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD; 14671 } 14672 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){ 14673 group_info->faults |= 14674 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY; 14675 } 14676 if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) { 14677 group_info->faults |= 14678 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS; 14679 } 14680 if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) { 14681 group_info->faults |= 14682 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI; 14683 } 14684 if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) { 14685 group_info->faults |= 14686 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI; 14687 } 14688 } 14689 } 14690 cur = cur->next; 14691 } 14692 } 14693 #endif 14694 } 14695 14696 _BCM_OAM_UNLOCK(oc); 14697 return (BCM_E_NONE); 14698 } 14699 14700 /* 14701 * Function: 14702 * bcm_kt2_oam_group_destroy 14703 * Purpose: 14704 * Destroy an OAM group object and its associated endpoints. 14705 * Parameters: 14706 * unit - (IN) BCM device number 14707 * group - (IN) The ID of the OAM group object to destroy 14708 * Returns: 14709 * BCM_E_XXX 14710 */ 14711 int 14712 bcm_kt2_oam_group_destroy(int unit, 14713 bcm_oam_group_t group) 14714 { 14715 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 14716 _bcm_oam_group_data_t *g_info_p; /* Pointer to group list. */ 14717 int rv; /* Operation return status. */ 14718 maid_reduction_entry_t maid_reduction_entry; /* MAID_REDUCTION entry. */ 14719 ma_state_entry_t ma_state_entry; /* MA_STATE table entry. */ 14720 14721 /* Get OAM device control structure. */ 14722 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 14723 14724 /* Validate group index. */ 14725 _BCM_OAM_GROUP_INDEX_VALIDATE(group); 14726 14727 _BCM_OAM_LOCK(oc); 14728 14729 /* Check if the group is in use. */ 14730 rv = shr_idxres_list_elem_state(oc->group_pool, group); 14731 if (BCM_E_EXISTS != rv) { 14732 _BCM_OAM_UNLOCK(oc); 14733 LOG_ERROR(BSL_LS_BCM_OAM, 14734 (BSL_META_U(unit, 14735 "OAM Error: GID=%d - %s.\n"), 14736 group, bcm_errmsg(rv))); 14737 return (rv); 14738 } 14739 14740 /* Get pointer to this group in the group list. */ 14741 g_info_p = &oc->group_info[group]; 14742 14743 rv = _bcm_kt2_oam_group_endpoints_destroy(unit, g_info_p); 14744 if (BCM_FAILURE(rv)) { 14745 _BCM_OAM_UNLOCK(oc); 14746 LOG_ERROR(BSL_LS_BCM_OAM, 14747 (BSL_META_U(unit, 14748 "OAM Error: bcm_kt2_oam_endpoint_destroy_all" 14749 " (GID=%d) - %s.\n"), group, bcm_errmsg(rv))); 14750 return (rv); 14751 } 14752 14753 sal_memset(&maid_reduction_entry, 0, sizeof(maid_reduction_entry_t)); 14754 rv = WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL, group, 14755 &maid_reduction_entry); 14756 if (BCM_FAILURE(rv)) { 14757 _BCM_OAM_UNLOCK(oc); 14758 LOG_DEBUG(BSL_LS_BCM_OAM, 14759 (BSL_META_U(unit, 14760 "OAM Error: MAID REDUCTION write " 14761 "(GID=%d) - %s.\n"), group, bcm_errmsg(rv))); 14762 return (rv); 14763 } 14764 14765 /* 14766 * Maintenance Association State table update. 14767 */ 14768 sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t)); 14769 14770 rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group, &ma_state_entry); 14771 if (BCM_FAILURE(rv)) { 14772 _BCM_OAM_UNLOCK(oc); 14773 LOG_ERROR(BSL_LS_BCM_OAM, 14774 (BSL_META_U(unit, 14775 "OAM Error: MA STATE write " 14776 "(GID=%d) - %s.\n"), group, bcm_errmsg(rv))); 14777 return (rv); 14778 } 14779 14780 /* Return Group ID back to free group. */ 14781 rv = shr_idxres_list_free(oc->group_pool, group); 14782 if (BCM_FAILURE(rv)) { 14783 _BCM_OAM_UNLOCK(oc); 14784 return (rv); 14785 } 14786 14787 #ifdef BCM_WARM_BOOT_SUPPORT 14788 SOC_CONTROL_LOCK(unit); 14789 SOC_CONTROL(unit)->scache_dirty = 1; 14790 SOC_CONTROL_UNLOCK(unit); 14791 #endif 14792 _BCM_OAM_UNLOCK(oc); 14793 return (BCM_E_NONE); 14794 } 14795 14796 /* 14797 * Function: 14798 * bcm_kt2_oam_group_destroy_all 14799 * Purpose: 14800 * Destroy all OAM group objects and their associated endpoints. 14801 * Parameters: 14802 * unit - (IN) BCM device number 14803 * Returns: 14804 * BCM_E_XXX 14805 */ 14806 int 14807 bcm_kt2_oam_group_destroy_all(int unit) 14808 { 14809 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 14810 int group; /* Maintenance Association group index. */ 14811 int rv; /* Operation return status . */ 14812 14813 /* Get device OAM control structure handle. */ 14814 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 14815 14816 _BCM_OAM_LOCK(oc); 14817 for (group = 0; group < oc->group_count; group++) { 14818 14819 /* Check if the group is in use. */ 14820 rv = shr_idxres_list_elem_state(oc->group_pool, group); 14821 if (BCM_E_EXISTS != rv) { 14822 continue; 14823 } 14824 14825 rv = bcm_kt2_oam_group_destroy(unit, group); 14826 if (BCM_FAILURE(rv)) { 14827 _BCM_OAM_UNLOCK(oc); 14828 LOG_ERROR(BSL_LS_BCM_OAM, 14829 (BSL_META_U(unit, 14830 "OAM Error: Group destroy failed " 14831 "(GID=%d) - %s.\n"), group, bcm_errmsg(rv))); 14832 return (rv); 14833 } 14834 } 14835 14836 #ifdef BCM_WARM_BOOT_SUPPORT 14837 SOC_CONTROL_LOCK(unit); 14838 SOC_CONTROL(unit)->scache_dirty = 1; 14839 SOC_CONTROL_UNLOCK(unit); 14840 #endif 14841 14842 _BCM_OAM_UNLOCK(oc); 14843 return (BCM_E_NONE); 14844 } 14845 14846 /* 14847 * Function: 14848 * bcm_kt2_oam_group_traverse 14849 * Purpose: 14850 * Traverse the entire set of OAM groups, calling a specified 14851 * callback for each one 14852 * Parameters: 14853 * unit - (IN) BCM device number 14854 * cb - (IN) Pointer to call back function. 14855 * user_data - (IN) Pointer to user supplied data. 14856 * Returns: 14857 * BCM_E_XXX 14858 */ 14859 int 14860 bcm_kt2_oam_group_traverse(int unit, bcm_oam_group_traverse_cb cb, 14861 void *user_data) 14862 { 14863 _bcm_oam_control_t *oc; /* OAM control structure pointer. */ 14864 bcm_oam_group_info_t group_info; /* Group information to be set. */ 14865 bcm_oam_group_t grp_idx; /* MA Group index. */ 14866 _bcm_oam_group_data_t *group_p; /* Pointer to group list. */ 14867 int rv; /* Operation return status. */ 14868 14869 if (NULL == cb) { 14870 return (BCM_E_PARAM); 14871 } 14872 14873 /* Get device OAM control structure handle. */ 14874 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 14875 14876 _BCM_OAM_LOCK(oc); 14877 14878 /* Initialize to group array pointer. */ 14879 group_p = oc->group_info; 14880 14881 for (grp_idx = 0; grp_idx < oc->group_count; grp_idx++) { 14882 14883 /* Check if the group is in use. */ 14884 if (BCM_E_EXISTS 14885 == shr_idxres_list_elem_state(oc->group_pool, grp_idx)) { 14886 14887 /* Initialize the group information structure. */ 14888 bcm_oam_group_info_t_init(&group_info); 14889 14890 /* Retrieve group information and set in group_info structure. */ 14891 rv = _bcm_kt2_oam_get_group(unit, grp_idx, group_p, &group_info); 14892 if (BCM_FAILURE(rv)) { 14893 _BCM_OAM_UNLOCK(oc); 14894 LOG_ERROR(BSL_LS_BCM_OAM, 14895 (BSL_META_U(unit, 14896 "OAM Error: _bcm_kt2_oam_get_group " 14897 "(GID=%d) - %s.\n"), grp_idx, bcm_errmsg(rv))); 14898 return (rv); 14899 } 14900 14901 /* Call the user call back routine with group information. */ 14902 rv = cb(unit, &group_info, user_data); 14903 if (BCM_FAILURE(rv)) { 14904 _BCM_OAM_UNLOCK(oc); 14905 LOG_ERROR(BSL_LS_BCM_OAM, 14906 (BSL_META_U(unit, 14907 "OAM Error: User call back routine " 14908 "(GID=%d) - %s.\n"), grp_idx, bcm_errmsg(rv))); 14909 return (rv); 14910 } 14911 } 14912 } 14913 14914 _BCM_OAM_UNLOCK(oc); 14915 14916 return BCM_E_NONE; 14917 } 14918 14919 14920 /* 14921 * Function: 14922 * bcm_kt2_oam_endpoint_lm_update 14923 * Purpose: 14924 * Update LM related params of an endpoint 14925 * Parameters: 14926 * unit - (IN) BCM device number 14927 * endpoint_info - (IN/OUT) Pointer to endpoint information buffer. 14928 * Returns: 14929 * BCM_E_XXX 14930 */ 14931 STATIC int 14932 bcm_kt2_oam_endpoint_lm_update(int unit, bcm_oam_endpoint_info_t *ep_info) 14933 { 14934 _bcm_oam_hash_data_t *h_data_p; 14935 _bcm_oam_control_t *oc; 14936 int loss_add, loss_del; 14937 int loss_configured; 14938 soc_profile_mem_t pri_map_prof_mem; 14939 uint32 pri_ent[BCM_OAM_INTPRI_MAX]; /* ing profile */ 14940 /* ing profile copy from HW*/ 14941 uint32 pri_ent_copy[BCM_OAM_INTPRI_MAX]; 14942 int i; 14943 void *entries[1]; 14944 int lm_ctr_pool_id = -1; 14945 int mem_index; 14946 egr_mp_group_entry_t egr_mp_group; 14947 l3_entry_1_entry_t l3_entry; /* LMEP view table entry.*/ 14948 int l3_index = -1; /* L3 table hardware index.*/ 14949 uint32 profile_index = -1; 14950 int rv = BCM_E_NONE; 14951 soc_mem_t mem = ING_SERVICE_PRI_MAPm;; 14952 14953 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 14954 14955 if (ep_info->flags & BCM_OAM_ENDPOINT_REMOTE) { 14956 /* Only LMEPs can update Loss parameters */ 14957 return BCM_E_PARAM; 14958 } 14959 14960 if (ep_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) { 14961 /* Only MEPs can update LM */ 14962 return BCM_E_PARAM; 14963 } 14964 14965 /* Validate endpoint index value. */ 14966 _BCM_OAM_EP_INDEX_VALIDATE(ep_info->id); 14967 14968 h_data_p = &oc->oam_hash_data[ep_info->id]; 14969 if (0 == h_data_p->in_use) { 14970 return BCM_E_NOT_FOUND; 14971 } 14972 14973 /* Figure out if loss is being added or deleted */ 14974 loss_add = loss_del = 0; 14975 loss_configured = 1; /* Indicates if BCM_OAM_ENDPOINT_LOSS_MEASUREMENT flag is 14976 * present in new & old config 14977 */ 14978 if (h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 14979 if (!(ep_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) { 14980 loss_del = 1; 14981 } 14982 } else { 14983 if (ep_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 14984 loss_add = 1; 14985 } else { 14986 /* BCM_OAM_ENDPOINT_LOSS_MEASUREMENT flag is not present in old/new 14987 * config. 14988 */ 14989 loss_configured = 0; 14990 } 14991 } 14992 14993 /* If loss configuration is present in either old & new configuration, then 14994 * find out if something is being modified in loss, updates will result in 14995 * delete and add. 14996 */ 14997 if (1 == loss_configured && 0 == loss_add && 0 == loss_del) { 14998 14999 lm_ctr_pool_id = (h_data_p->rx_ctr >> 24) & 0xFF; 15000 15001 if (lm_ctr_pool_id != ep_info->lm_ctr_pool_id) { 15002 loss_del = loss_add = 1; 15003 } 15004 15005 if(h_data_p->pri_map_index != _BCM_OAM_INVALID_INDEX) { 15006 15007 pri_map_prof_mem = oc->ing_service_pri_map; 15008 15009 for (i = 0; i < BCM_OAM_INTPRI_MAX; i++) { 15010 if (ep_info->pri_map[i] > _BCM_OAM_SERVICE_PRI_MAX_OFFSET) { 15011 return BCM_E_PARAM; 15012 } 15013 pri_ent[i] = ep_info->pri_map[i]; 15014 if (SOC_MEM_FIELD_VALID(unit, mem, OFFSET_VALIDf)) { 15015 soc_mem_field32_set(unit, mem, &pri_ent[i], OFFSET_VALIDf, 1); 15016 } 15017 } 15018 15019 soc_mem_lock(unit, mem); 15020 15021 entries[0] = &pri_ent_copy; 15022 15023 rv = soc_profile_mem_get(unit, &pri_map_prof_mem, 15024 (h_data_p->pri_map_index * BCM_OAM_INTPRI_MAX), 15025 BCM_OAM_INTPRI_MAX, (void *) entries); 15026 15027 if (BCM_FAILURE(rv)) { 15028 soc_mem_unlock(unit, mem); 15029 return rv; 15030 } 15031 15032 if (sal_memcmp(pri_ent, pri_ent_copy, 15033 sizeof(uint32)*BCM_OAM_INTPRI_MAX)){ 15034 rv = soc_profile_mem_delete(unit, &pri_map_prof_mem, 15035 (h_data_p->pri_map_index * BCM_OAM_INTPRI_MAX)); 15036 if (BCM_FAILURE(rv)) { 15037 LOG_ERROR(BSL_LS_BCM_OAM, 15038 (BSL_META_U(unit, 15039 "OAM Error: Profile table update error (idx=%d)" 15040 "- %s.\n"), h_data_p->pri_map_index, bcm_errmsg(rv))); 15041 soc_mem_unlock(unit, mem); 15042 return (rv); 15043 } 15044 15045 h_data_p->pri_map_index = profile_index; 15046 15047 loss_del = loss_add = 1; 15048 } 15049 soc_mem_unlock(unit, mem); 15050 } else { 15051 /* If for some reason i.e. warmboot,index became invalid 15052 * though loss is configured */ 15053 return BCM_E_INTERNAL; 15054 } 15055 15056 } 15057 15058 if (1 == loss_del) { 15059 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_find_lmep(unit, h_data_p, &l3_index, 15060 &l3_entry)); 15061 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_clear_counter(unit, L3_ENTRY_IPV4_UNICASTm, 15062 l3_index, h_data_p, 15063 (void *)&l3_entry)); 15064 15065 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_find_egr_lmep(unit, h_data_p, 15066 &mem_index, 15067 &egr_mp_group)); 15068 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_clear_counter(unit, EGR_MP_GROUPm, 15069 mem_index, h_data_p, 15070 (void *)&egr_mp_group)); 15071 h_data_p->flags &= ~BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 15072 } 15073 15074 if (1 == loss_add) { 15075 h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 15076 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_lmep_counters_set(unit, ep_info)); 15077 } 15078 15079 if(ep_info->type == bcmOAMEndpointTypeEthernet) { 15080 if((ep_info->ccm_tx_update_lm_counter_size) && 15081 (_BCM_OAM_INVALID_INDEX != h_data_p->local_tx_index)) { 15082 BCM_IF_ERROR_RETURN(bcm_kt2_oam_hw_ccm_tx_ctr_update(unit, ep_info)); 15083 } 15084 } 15085 15086 return BCM_E_NONE; 15087 } 15088 15089 15090 /* 15091 * Function: 15092 * bcm_kt2_oam_endpoint_create 15093 * Purpose: 15094 * Create or replace an OAM endpoint object 15095 * Parameters: 15096 * unit - (IN) BCM device number 15097 * endpoint_info - (IN/OUT) Pointer to endpoint information buffer. 15098 * Returns: 15099 * BCM_E_XXX 15100 */ 15101 int 15102 bcm_kt2_oam_endpoint_create(int unit, bcm_oam_endpoint_info_t *endpoint_info) 15103 { 15104 _bcm_oam_hash_data_t *hash_data = NULL; /* Endpoint hash data pointer. */ 15105 _bcm_oam_hash_key_t hash_key; /* Hash Key buffer. */ 15106 int ep_req_index; /* Requested endpoint index. */ 15107 int rv; /* Operation return status. */ 15108 _bcm_oam_control_t *oc; /* Pointer to OAM control */ 15109 /* structure. */ 15110 uint32 sglp = 0; /* Source global logical port. */ 15111 uint32 dglp = 0; /* Dest global logical port. */ 15112 uint32 svp = 0; /* Source virtual port */ 15113 bcm_port_t src_pp_port = 0; /* Source pp port. */ 15114 bcm_port_t dst_pp_port = 0; /* Dest pp port. */ 15115 int mep_ccm_tx = 0; /* Endpoint CCM Tx status. */ 15116 int mep_ccm_rx = 0; /* Endpoint CCM Rx status. */ 15117 int remote = 0; /* Remote endpoint status. */ 15118 int up_mep = 0; /* Endpoint is an upMep */ 15119 int key_type = 0; 15120 port_tab_entry_t port_entry; 15121 int oam_key1 = 0; 15122 int oam_key2 = 0; 15123 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 15124 int is_vp_valid = 0; 15125 bcm_gport_t tx_gport = BCM_GPORT_INVALID; 15126 15127 LOG_DEBUG(BSL_LS_BCM_OAM, 15128 (BSL_META_U(unit, 15129 "OAM Info: bcm_kt2_oam_endpoint_create " 15130 "Endpoint ID=%d.\n"), endpoint_info->id)); 15131 15132 /* Validate input parameter. */ 15133 if (NULL == endpoint_info) { 15134 return (BCM_E_PARAM); 15135 } 15136 15137 /* Get OAM Control Structure. */ 15138 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 15139 15140 _BCM_OAM_LOCK(oc); 15141 15142 #if defined(KEY_PRINT) 15143 _bcm_oam_hash_key_print(&hash_key); 15144 #endif 15145 15146 /* Calculate the hash key for given enpoint input parameters. */ 15147 _bcm_kt2_oam_ep_hash_key_construct(unit, oc, endpoint_info, &hash_key); 15148 15149 /* Validate endpoint input parameters. */ 15150 rv = _bcm_kt2_oam_endpoint_params_validate(unit, oc, &hash_key, 15151 endpoint_info); 15152 if (BCM_FAILURE(rv)) { 15153 LOG_ERROR(BSL_LS_BCM_OAM, 15154 (BSL_META_U(unit, 15155 "OAM Error: (EP=%d) - %s.\n"), 15156 endpoint_info->id, bcm_errmsg(rv))); 15157 _BCM_OAM_UNLOCK(oc); 15158 return (rv); 15159 } 15160 15161 if ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) && 15162 (endpoint_info->flags2 & BCM_OAM_ENDPOINT2_UPDATE_COUNTER_ACTION)) { 15163 /* Update LM parameters */ 15164 rv = bcm_kt2_oam_endpoint_lm_update(unit, endpoint_info); 15165 _BCM_OAM_UNLOCK(oc); 15166 return rv; 15167 } 15168 15169 if(soc_feature(unit, soc_feature_bhh)) { 15170 #if defined(INCLUDE_BHH) 15171 if(BHH_EP_TYPE(endpoint_info)) 15172 { 15173 if ((oc->ukernel_not_ready == 1) && 15174 (!(endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU))){ 15175 LOG_ERROR(BSL_LS_BCM_OAM, 15176 (BSL_META_U(unit, 15177 "OAM(unit %d) Error: BTE(ukernel) " 15178 "not ready.\n"), unit)); 15179 _BCM_OAM_UNLOCK(oc); 15180 return (BCM_E_INIT); 15181 } 15182 rv = bcm_kt2_oam_bhh_endpoint_create(unit, endpoint_info, &hash_key); 15183 if (BCM_FAILURE(rv)) { 15184 LOG_ERROR(BSL_LS_BCM_OAM, 15185 (BSL_META_U(unit, 15186 "OAM Error: BHH Endpoint create (EP=%d) - %s.\n"), 15187 endpoint_info->id, bcm_errmsg(rv))); 15188 } 15189 _BCM_OAM_UNLOCK(oc); 15190 15191 return (rv); 15192 } 15193 #endif /* INCLUDE_BHH */ 15194 } 15195 15196 /* Get MEP remote endpoint status. */ 15197 remote = (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0; 15198 15199 /* For remote endpoints gport is not required. 15200 Only group and MEP ID info is required. */ 15201 if (!remote) { 15202 /* Resolve given endpoint gport value to Source GLP and Dest GLP values. */ 15203 rv = _bcm_kt2_oam_endpoint_gport_resolve(unit, endpoint_info, &sglp, &dglp, 15204 &src_pp_port, &dst_pp_port, 15205 &svp, &trunk_id, &is_vp_valid, 15206 &tx_gport); 15207 15208 if (BCM_FAILURE(rv)) { 15209 LOG_ERROR(BSL_LS_BCM_OAM, 15210 (BSL_META_U(unit, 15211 "OAM Error: Gport resolve (EP=%d) - %s.\n"), 15212 endpoint_info->id, bcm_errmsg(rv))); 15213 _BCM_OAM_UNLOCK(oc); 15214 return (rv); 15215 } 15216 } 15217 15218 /* Get MEP CCM Tx status. */ 15219 mep_ccm_tx 15220 = ((endpoint_info->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) 15221 ? 1 : 0); 15222 15223 /* Get MEP CCM Rx status. */ 15224 mep_ccm_rx 15225 = ((endpoint_info->flags & _BCM_OAM_EP_RX_ENABLE) ? 1 : 0); 15226 15227 15228 /* Check whether up/down MEP */ 15229 if (endpoint_info->flags & BCM_OAM_ENDPOINT_UP_FACING) { 15230 up_mep = 1; 15231 } 15232 /* Set the search key type. */ 15233 if (is_vp_valid) { 15234 key_type = _BCM_OAM_DOMAIN_VP; 15235 } else if(endpoint_info->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) { 15236 key_type = _BCM_OAM_DOMAIN_CVLAN; 15237 } else if(endpoint_info->flags & 15238 BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) { 15239 key_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN; 15240 } else if((endpoint_info->vlan == 0) && (endpoint_info->inner_vlan == 0)) { 15241 key_type = _BCM_OAM_DOMAIN_PORT; 15242 } else { 15243 key_type = _BCM_OAM_DOMAIN_SVLAN; 15244 } 15245 15246 /* We need to set the OAM_KEY1 and OAM_KEY2 fields of the PORT_TABLE and 15247 EGR_PORT_TABLE based on the key_type of OAM */ 15248 if (trunk_id != BCM_TRUNK_INVALID) { 15249 rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, 15250 src_pp_port, &port_entry); 15251 if (BCM_FAILURE(rv)) { 15252 LOG_ERROR(BSL_LS_BCM_OAM, 15253 (BSL_META_U(unit, 15254 "OAM Error: Endpoint create (EP=%d) - %s.\n"), 15255 endpoint_info->id, bcm_errmsg(rv))); 15256 _BCM_OAM_UNLOCK(oc); 15257 return (rv); 15258 } 15259 15260 oam_key1 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY1f); 15261 oam_key2 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY2f); 15262 15263 if (key_type != _BCM_OAM_DOMAIN_PORT) { 15264 if ((oam_key1 > 0) && (oam_key2 > 0)) { 15265 if ((oam_key1 == key_type) || (oam_key2 == key_type)) { 15266 } else { 15267 LOG_ERROR(BSL_LS_BCM_OAM, 15268 (BSL_META_U(unit, 15269 "OAM Error: Invalid OAM domain to " 15270 "resolve (EP=%d) - %s.\n"), 15271 endpoint_info->id, bcm_errmsg(rv))); 15272 _BCM_OAM_UNLOCK(oc); 15273 return (BCM_E_PARAM); 15274 } 15275 } 15276 } 15277 } 15278 15279 /* For Downmep CCM tx purposes, int_pri variable is used like a cosq. 15280 * Hence verify if it is in the valid range, Else return error. 15281 * For UPMEP CCM tx purposes, int_pri is used as internal priority only. 15282 * Hence verify if it is in valid range of internal priority 15283 */ 15284 if (mep_ccm_tx && !up_mep && 15285 (!BCM_COSQ_QUEUE_VALID(unit, endpoint_info->int_pri))) { 15286 _BCM_OAM_UNLOCK(oc); 15287 return (BCM_E_PARAM); 15288 } else if (mep_ccm_tx && up_mep && 15289 (!(endpoint_info->int_pri >= 0 && endpoint_info->int_pri < BCM_OAM_INTPRI_MAX))) { 15290 _BCM_OAM_UNLOCK(oc); 15291 return (BCM_E_PARAM); 15292 } 15293 15294 /* Replace an existing endpoint. */ 15295 if (endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) { 15296 15297 rv = _bcm_kt2_oam_endpoint_destroy(unit, endpoint_info->id); 15298 if (BCM_FAILURE(rv)) { 15299 LOG_ERROR(BSL_LS_BCM_OAM, 15300 (BSL_META_U(unit, 15301 "OAM Error: Endpoint destroy (EP=%d) - %s.\n"), 15302 endpoint_info->id, bcm_errmsg(rv))); 15303 _BCM_OAM_UNLOCK(oc); 15304 return (rv); 15305 } 15306 } 15307 15308 /* Create a new endpoint with the requested ID. */ 15309 if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) { 15310 ep_req_index = endpoint_info->id; 15311 rv = shr_idxres_list_reserve(oc->mep_pool, ep_req_index, 15312 ep_req_index); 15313 if (BCM_FAILURE(rv)) { 15314 LOG_ERROR(BSL_LS_BCM_OAM, 15315 (BSL_META_U(unit, 15316 "OAM Error: Endpoint reserve (EP=%d) - %s.\n"), 15317 endpoint_info->id, bcm_errmsg(rv))); 15318 _BCM_OAM_UNLOCK(oc); 15319 return ((rv == BCM_E_RESOURCE) ? BCM_E_EXISTS : rv); 15320 } 15321 } else { 15322 /* Allocate the next available endpoint index. */ 15323 rv = shr_idxres_list_alloc(oc->mep_pool, 15324 (shr_idxres_element_t *)&ep_req_index); 15325 if (BCM_FAILURE(rv)) { 15326 LOG_ERROR(BSL_LS_BCM_OAM, 15327 (BSL_META_U(unit, 15328 "OAM Error: Endpoint alloc failed - %s.\n"), 15329 bcm_errmsg(rv))); 15330 _BCM_OAM_UNLOCK(oc); 15331 return (rv); 15332 } 15333 /* Set the allocated endpoint id value. */ 15334 endpoint_info->id = ep_req_index; 15335 } 15336 15337 /* Get the hash data pointer where the data is to be stored. */ 15338 hash_data = &oc->oam_hash_data[ep_req_index]; 15339 15340 /* Clear the hash data element contents before storing the values. */ 15341 _BCM_OAM_HASH_DATA_CLEAR(hash_data); 15342 hash_data->type = endpoint_info->type; 15343 hash_data->ep_id = endpoint_info->id; 15344 hash_data->is_remote = remote; 15345 hash_data->local_tx_enabled = mep_ccm_tx; 15346 hash_data->local_rx_enabled = mep_ccm_rx; 15347 hash_data->group_index = endpoint_info->group; 15348 hash_data->name = endpoint_info->name; 15349 hash_data->level = endpoint_info->level; 15350 hash_data->vlan = endpoint_info->vlan; 15351 hash_data->inner_vlan = endpoint_info->inner_vlan; 15352 hash_data->gport = endpoint_info->gport; 15353 hash_data->sglp = sglp; 15354 hash_data->dglp = dglp; 15355 hash_data->src_pp_port = src_pp_port; 15356 hash_data->dst_pp_port = dst_pp_port; 15357 hash_data->flags = endpoint_info->flags; 15358 hash_data->opcode_flags = ( endpoint_info->opcode_flags & 15359 _BCM_KT2_OAM_OPCODE_MASK ); 15360 hash_data->period = endpoint_info->ccm_period; 15361 hash_data->in_use = 1; 15362 hash_data->oam_domain = key_type; 15363 hash_data->outer_tpid = endpoint_info->outer_tpid; 15364 hash_data->inner_tpid = endpoint_info->inner_tpid; 15365 hash_data->subport_tpid = endpoint_info->subport_tpid; 15366 hash_data->int_pri = endpoint_info->int_pri; 15367 hash_data->trunk_index = endpoint_info->trunk_index; 15368 if (is_vp_valid) { 15369 hash_data->vp = svp; 15370 if (endpoint_info->flags & BCM_OAM_ENDPOINT_UP_FACING) { 15371 /* For implementation of VP based lookup on egress side (UP MEP) 15372 * We need to set EGR_DVP_ATTRIBUTE OAM_KEY3 = 1. 15373 */ 15374 rv = bcm_esw_port_control_set(unit, endpoint_info->gport, 15375 bcmPortControlOamLookupWithDvp, 15376 1); 15377 if (BCM_FAILURE(rv)) { 15378 _BCM_OAM_UNLOCK(oc); 15379 return (rv); 15380 } 15381 } 15382 hash_data->int_flags |= _BCM_OAM_ENDPOINT_IS_VP_BASED; 15383 } 15384 if(endpoint_info->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) { 15385 hash_data->inner_vlan = endpoint_info->inner_vlan; 15386 } 15387 hash_data->trunk_id = trunk_id; 15388 if (BCM_GPORT_IS_TRUNK(endpoint_info->gport)) { 15389 hash_data->resolved_trunk_gport = tx_gport; 15390 } 15391 /* Initialize hardware index as invalid indices. */ 15392 hash_data->local_tx_index = _BCM_OAM_INVALID_INDEX; 15393 hash_data->local_rx_index = _BCM_OAM_INVALID_INDEX; 15394 hash_data->remote_index = _BCM_OAM_INVALID_INDEX; 15395 hash_data->rx_ctr = _BCM_OAM_INVALID_INDEX; 15396 hash_data->tx_ctr = _BCM_OAM_INVALID_INDEX; 15397 hash_data->profile_index = _BCM_OAM_INVALID_INDEX; 15398 hash_data->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 15399 hash_data->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 15400 hash_data->pri_map_index = _BCM_OAM_INVALID_INDEX; 15401 hash_data->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 15402 hash_data->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 15403 hash_data->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 15404 hash_data->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 15405 hash_data->ma_base_index = _BCM_OAM_INVALID_INDEX; 15406 15407 if (1 == remote) { 15408 /* Allocate the next available index for RMEP table. */ 15409 rv = shr_idxres_list_alloc 15410 (oc->rmep_pool, 15411 (shr_idxres_element_t *)&hash_data->remote_index); 15412 if (BCM_FAILURE(rv)) { 15413 _BCM_OAM_UNLOCK(oc); 15414 LOG_ERROR(BSL_LS_BCM_OAM, 15415 (BSL_META_U(unit, 15416 "OAM Error: RMEP index alloc failed EP:%d %s.\n"), 15417 endpoint_info->id, bcm_errmsg(rv))); 15418 return (rv); 15419 } 15420 } else { 15421 15422 /* Allocate the next available index for LMEP table. */ 15423 if (1 == mep_ccm_tx) { 15424 rv = shr_idxres_list_alloc 15425 (oc->lmep_pool, 15426 (shr_idxres_element_t *)&hash_data->local_tx_index); 15427 if (BCM_FAILURE(rv)) { 15428 _BCM_OAM_UNLOCK(oc); 15429 LOG_ERROR(BSL_LS_BCM_OAM, 15430 (BSL_META_U(unit, 15431 "OAM Error: LMEP Tx index alloc failed EP:%d " 15432 "%s.\n"), endpoint_info->id, bcm_errmsg(rv))); 15433 return (rv); 15434 } 15435 } 15436 15437 /* Allocate the next available index for MA_INDEX table. */ 15438 if (1 == mep_ccm_rx) { 15439 /* check up or down MEP */ 15440 if (1 == up_mep) { 15441 rv = _bcm_kt2_oam_upmep_rx_endpoint_reserve(unit, 15442 endpoint_info); 15443 if (BCM_FAILURE(rv)) { 15444 if (1 == mep_ccm_tx) { 15445 /* Return Tx index to the LMEP pool. */ 15446 shr_idxres_list_free(oc->lmep_pool, 15447 hash_data->local_tx_index); 15448 } 15449 15450 /* Return endpoint index to MEP pool. */ 15451 shr_idxres_list_free(oc->mep_pool, endpoint_info->id); 15452 15453 _BCM_OAM_UNLOCK(oc); 15454 LOG_ERROR(BSL_LS_BCM_OAM, 15455 (BSL_META_U(unit, 15456 "OAM Error: LMEP Rx index alloc failed " 15457 "EP:%d " "%s.\n"), 15458 endpoint_info->id, bcm_errmsg(rv))); 15459 return (rv); 15460 } 15461 } else { /* down Mep */ 15462 rv = _bcm_kt2_oam_downmep_rx_endpoint_reserve(unit, 15463 endpoint_info); 15464 if (BCM_FAILURE(rv)) { 15465 if (1 == mep_ccm_tx) { 15466 /* Return Tx index to the LMEP pool. */ 15467 shr_idxres_list_free(oc->lmep_pool, 15468 hash_data->local_tx_index); 15469 } 15470 15471 /* Return endpoint index to MEP pool. */ 15472 shr_idxres_list_free(oc->mep_pool, endpoint_info->id); 15473 15474 _BCM_OAM_UNLOCK(oc); 15475 LOG_ERROR(BSL_LS_BCM_OAM, 15476 (BSL_META_U(unit, 15477 "OAM Error: LMEP Rx index alloc " 15478 "failed EP:%d " "%s.\n"), endpoint_info->id, 15479 bcm_errmsg(rv))); 15480 return (rv); 15481 } 15482 } 15483 } 15484 } 15485 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, hash_data); 15486 if (BCM_FAILURE(rv)) { 15487 LOG_ERROR(BSL_LS_BCM_OAM, 15488 (BSL_META_U(unit, 15489 "OAM Error: Hash table insert failed EP=%d %s.\n"), 15490 endpoint_info->id, bcm_errmsg(rv))); 15491 _bcm_kt2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 15492 _BCM_OAM_UNLOCK(oc); 15493 return (rv); 15494 } 15495 15496 if (1 == remote) { 15497 rv = _bcm_oam_kt2_remote_mep_hw_set(unit, endpoint_info); 15498 if (BCM_FAILURE(rv)) { 15499 LOG_DEBUG(BSL_LS_BCM_OAM, 15500 (BSL_META_U(unit, 15501 "OAM Error: Remote MEP set failed EP=%d %s.\n"), 15502 endpoint_info->id, bcm_errmsg(rv))); 15503 _bcm_kt2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 15504 _BCM_OAM_UNLOCK(oc); 15505 return (rv); 15506 } 15507 } else { 15508 if (mep_ccm_rx) { 15509 rv = _bcm_kt2_oam_local_rx_mep_hw_set(unit, endpoint_info); 15510 if (BCM_FAILURE(rv)) { 15511 LOG_ERROR(BSL_LS_BCM_OAM, 15512 (BSL_META_U(unit, 15513 "OAM Error: Rx config failed for EP=%d %s.\n"), 15514 endpoint_info->id, bcm_errmsg(rv))); 15515 _bcm_kt2_oam_endpoint_cleanup(unit, up_mep, 15516 hash_key, hash_data); 15517 _BCM_OAM_UNLOCK(oc); 15518 return (rv); 15519 } 15520 } 15521 if (mep_ccm_tx) { 15522 rv = _bcm_oam_kt2_local_tx_mep_hw_set(unit, endpoint_info); 15523 if (BCM_FAILURE(rv)) { 15524 LOG_ERROR(BSL_LS_BCM_OAM, 15525 (BSL_META_U(unit, 15526 "OAM Error: Tx config failed for EP=%d %s.\n"), 15527 endpoint_info->id, bcm_errmsg(rv))); 15528 _bcm_kt2_oam_endpoint_cleanup(unit, up_mep, 15529 hash_key, hash_data); 15530 _BCM_OAM_UNLOCK(oc); 15531 return (rv); 15532 } 15533 } 15534 15535 rv = _bcm_kt2_oam_port_table_key_update(unit, PORT_TABm, hash_data); 15536 if (BCM_FAILURE(rv)) { 15537 LOG_ERROR(BSL_LS_BCM_OAM, 15538 (BSL_META_U(unit, 15539 "OAM Error: Endpoint create (EP=%d) - %s.\n"), 15540 endpoint_info->id, bcm_errmsg(rv))); 15541 _bcm_kt2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 15542 _BCM_OAM_UNLOCK(oc); 15543 return (rv); 15544 } 15545 rv = _bcm_kt2_oam_port_table_key_update(unit, EGR_PORTm, hash_data); 15546 if (BCM_FAILURE(rv)) { 15547 LOG_ERROR(BSL_LS_BCM_OAM, 15548 (BSL_META_U(unit, 15549 "OAM Error: Endpoint create (EP=%d) - %s.\n"), 15550 endpoint_info->id, bcm_errmsg(rv))); 15551 _bcm_kt2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 15552 _BCM_OAM_UNLOCK(oc); 15553 return (rv); 15554 } 15555 /* Set OAM LM cng and cpu data control from LM flags*/ 15556 if(hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 15557 _bcm_kt2_oam_lm_cng_cpu_ctrl_set(unit, endpoint_info); 15558 } 15559 } 15560 15561 rv = _bcm_kt2_oam_group_ep_list_add(unit, endpoint_info->group, 15562 endpoint_info->id); 15563 if (BCM_FAILURE(rv)) { 15564 LOG_ERROR(BSL_LS_BCM_OAM, 15565 (BSL_META_U(unit, 15566 "OAM Error: failed to add entry to ep list " 15567 "for EP=%d %s.\n"), endpoint_info->id, bcm_errmsg(rv))); 15568 _bcm_kt2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 15569 _BCM_OAM_UNLOCK(oc); 15570 return (rv); 15571 } 15572 15573 rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_add(unit, hash_data); 15574 if (BCM_FAILURE(rv)) { 15575 LOG_ERROR(BSL_LS_BCM_OAM, 15576 (BSL_META_U(unit, 15577 "OAM(unit %d) Error: failed to add mapping to ma_idx_to_ep_id list " 15578 "for EP=%d %s.\n"), unit, endpoint_info->id, bcm_errmsg(rv))); 15579 _bcm_kt2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 15580 _BCM_OAM_UNLOCK(oc); 15581 return (rv); 15582 } 15583 _BCM_OAM_UNLOCK(oc); 15584 15585 #ifdef BCM_WARM_BOOT_SUPPORT 15586 SOC_CONTROL_LOCK(unit); 15587 SOC_CONTROL(unit)->scache_dirty = 1; 15588 SOC_CONTROL_UNLOCK(unit); 15589 #endif 15590 15591 return (BCM_E_NONE); 15592 } 15593 15594 /* 15595 * Function: 15596 * bcm_kt2_oam_hw_ccm_tx_ctr_get 15597 * Purpose: 15598 * Update CCM CTR params 15599 * Parameters: 15600 * unit - (IN) Unit number. 15601 * lmep_1_entry - (IN) lemp_1 entry read from HW 15602 * ep_info - (OUT) Pointer to get endpoint parameters 15603 * Returns: 15604 * BCM_E_XXX 15605 * Notes: 15606 */ 15607 void 15608 bcm_kt2_oam_hw_ccm_tx_ctr_get(int unit, 15609 lmep_1_entry_t *lmep_1_entry, 15610 bcm_oam_endpoint_info_t *endpoint_info) 15611 { 15612 int num_counter = 0; 15613 uint32 counter_base_id = 0; 15614 15615 if(soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_1_ACTIONf)) { 15616 15617 counter_base_id = soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_1_IDf); 15618 endpoint_info->ccm_tx_update_lm_counter_base_id[0] = (counter_base_id & 0xFFF8); 15619 endpoint_info->ccm_tx_update_lm_counter_offset[0] = counter_base_id % 8; 15620 num_counter++; 15621 } 15622 15623 if(soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_2_ACTIONf)) { 15624 15625 counter_base_id = soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_2_IDf); 15626 endpoint_info->ccm_tx_update_lm_counter_base_id[1] = (counter_base_id & 0xFFF8) + (1 << 24); 15627 endpoint_info->ccm_tx_update_lm_counter_offset[1] = counter_base_id % 8; 15628 num_counter++; 15629 } 15630 15631 endpoint_info->ccm_tx_update_lm_counter_size = num_counter; 15632 15633 return; 15634 } 15635 15636 15637 /* 15638 * Function: 15639 * bcm_kt2_oam_endpoint_get 15640 * Purpose: 15641 * Get an OAM endpoint object 15642 * Parameters: 15643 * unit - (IN) BCM device number 15644 * endpoint - (IN) Endpoint ID 15645 * endpoint_info - (OUT) Pointer to OAM endpoint information buffer. 15646 * Returns: 15647 * BCM_E_XXX 15648 */ 15649 int 15650 bcm_kt2_oam_endpoint_get(int unit, bcm_oam_endpoint_t endpoint, 15651 bcm_oam_endpoint_info_t *endpoint_info) 15652 { 15653 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 15654 int rv = BCM_E_NONE;/* Operation return status. */ 15655 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 15656 rmep_entry_t rmep_entry; /* Remote MEP entry buffer. */ 15657 lmep_entry_t lmep_entry; /* Local MEP entry buffer. */ 15658 lmep_1_entry_t lmep_1_entry; /* Local MEP entry buffer. */ 15659 void *entries[1]; 15660 uint32 mem_entries[BCM_OAM_INTPRI_MAX]; 15661 int i = 0; 15662 uint16 inner_vlan_pri = 0; 15663 #if defined(INCLUDE_BHH) 15664 bhh_sdk_msg_ctrl_sess_get_t msg; 15665 uint8 *buffer, *buffer_ptr; 15666 uint16 buffer_len, reply_len; 15667 int sess_id = 0; 15668 bcm_l3_egress_t l3_egress; 15669 bcm_l3_intf_t l3_intf; 15670 #endif 15671 uint16 glp = 0; 15672 bcm_gport_t tx_gport = 0; /* Gport value. */ 15673 15674 if (NULL == endpoint_info) { 15675 return (BCM_E_PARAM); 15676 } 15677 15678 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 15679 _BCM_OAM_EP_INDEX_VALIDATE(endpoint); 15680 _BCM_OAM_LOCK(oc); 15681 15682 h_data_p = &oc->oam_hash_data[endpoint]; 15683 if (NULL == h_data_p) { 15684 _BCM_OAM_UNLOCK(oc); 15685 return (BCM_E_INTERNAL); 15686 } 15687 15688 if (0 == h_data_p->in_use) { 15689 _BCM_OAM_UNLOCK(oc); 15690 return (BCM_E_NOT_FOUND); 15691 } 15692 LOG_DEBUG(BSL_LS_BCM_OAM, 15693 (BSL_META_U(unit, 15694 "OAM Info: Endpoint (EP=%d) remote=%d local_tx=%d" 15695 "local_tx_idx=%d local_rx_en=%d local_rx_idx=%d oam_domain=%d\n"), 15696 endpoint, h_data_p->is_remote, h_data_p->local_tx_enabled, 15697 h_data_p->local_tx_index, h_data_p->local_rx_enabled, 15698 h_data_p->local_rx_index, h_data_p->oam_domain)); 15699 if (bcmOAMEndpointTypeEthernet == h_data_p->type) { 15700 if (1 == h_data_p->is_remote) { 15701 15702 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 15703 15704 /* Get hardware table entry information. */ 15705 rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index, 15706 &rmep_entry); 15707 if (BCM_FAILURE(rv)) { 15708 LOG_ERROR(BSL_LS_BCM_OAM, 15709 (BSL_META_U(unit, 15710 "OAM Error: RMEP table read failed for" 15711 " EP=%d %s.\n"), endpoint, bcm_errmsg(rv))); 15712 _BCM_OAM_UNLOCK(oc); 15713 return (rv); 15714 } 15715 15716 rv = _bcm_kt2_oam_read_clear_faults(unit, h_data_p->remote_index, 15717 RMEPm, (uint32 *) &rmep_entry, 15718 (void *) endpoint_info); 15719 if (BCM_FAILURE(rv)) { 15720 LOG_ERROR(BSL_LS_BCM_OAM, 15721 (BSL_META_U(unit, 15722 "OAM Error: RMEP table read failed for" 15723 " EP=%d %s.\n"), endpoint, bcm_errmsg(rv))); 15724 _BCM_OAM_UNLOCK(oc); 15725 return (rv); 15726 } 15727 if (endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_GET_FAULTS_ONLY) { 15728 endpoint_info->flags2 &= ~BCM_OAM_ENDPOINT_FLAGS2_GET_FAULTS_ONLY; 15729 _BCM_OAM_UNLOCK(oc); 15730 return BCM_E_NONE; 15731 } 15732 } else { 15733 if (1 == h_data_p->local_tx_enabled) { 15734 15735 sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t)); 15736 15737 /* Get hardware table entry information. */ 15738 rv = READ_LMEPm(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, 15739 &lmep_entry); 15740 if (BCM_FAILURE(rv)) { 15741 LOG_ERROR(BSL_LS_BCM_OAM, 15742 (BSL_META_U(unit, 15743 "OAM Error: LMEP table read failed for EP=%d" 15744 " %s.\n"), endpoint, bcm_errmsg(rv))); 15745 _BCM_OAM_UNLOCK(oc); 15746 return (rv); 15747 } 15748 15749 soc_LMEPm_mac_addr_get(unit, &lmep_entry, SAf, 15750 endpoint_info->src_mac_address); 15751 15752 endpoint_info->pkt_pri 15753 = soc_LMEPm_field32_get(unit, &lmep_entry, PRIORITYf); 15754 15755 endpoint_info->port_state 15756 = (soc_LMEPm_field32_get 15757 (unit, &lmep_entry, PORT_TLVf) 15758 ? BCM_OAM_PORT_TLV_UP : BCM_OAM_PORT_TLV_BLOCKED); 15759 inner_vlan_pri = soc_LMEPm_field32_get(unit, &lmep_entry, CVLAN_TAGf); 15760 endpoint_info->inner_vlan = 0xFFF & inner_vlan_pri; 15761 endpoint_info->inner_pkt_pri = inner_vlan_pri >> 13; 15762 sal_memset(&lmep_1_entry, 0, sizeof(lmep_1_entry_t)); 15763 15764 /* Get hardware table entry information. */ 15765 rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, 15766 &lmep_1_entry); 15767 if (BCM_FAILURE(rv)) { 15768 LOG_ERROR(BSL_LS_BCM_OAM, 15769 (BSL_META_U(unit, 15770 "OAM Error: LMEP_1 table read failed " 15771 "for EP=%d"" %s.\n"), endpoint, bcm_errmsg(rv))); 15772 _BCM_OAM_UNLOCK(oc); 15773 return (rv); 15774 } 15775 soc_LMEP_1m_mac_addr_get(unit, &lmep_1_entry, DAf, 15776 endpoint_info->dst_mac_address); 15777 15778 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 15779 endpoint_info->int_pri = soc_LMEP_1m_field32_get(unit, 15780 &lmep_1_entry, INT_PRIf); 15781 } else { 15782 endpoint_info->int_pri = h_data_p->int_pri; 15783 } 15784 15785 endpoint_info->interface_state 15786 = soc_LMEP_1m_field32_get(unit, &lmep_1_entry, INTERFACE_TLVf); 15787 15788 bcm_kt2_oam_hw_ccm_tx_ctr_get(unit, &lmep_1_entry, endpoint_info); 15789 glp = soc_LMEP_1m_field32_get(unit, &lmep_1_entry, PP_PORTf); 15790 _BCM_KT2_SUBPORT_PORT_ID_SET(tx_gport, glp); 15791 if (BCM_PBMP_MEMBER(SOC_INFO(unit).general_pp_port_pbm, glp)) { 15792 _BCM_KT2_SUBPORT_PORT_TYPE_SET(tx_gport, _BCM_KT2_SUBPORT_TYPE_GENERAL); 15793 endpoint_info->tx_gport = tx_gport; 15794 endpoint_info->flags2 |= BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW; 15795 } 15796 } 15797 } 15798 } 15799 else if (soc_feature(unit, soc_feature_bhh) && 15800 BHH_EP_TYPE(h_data_p)) { 15801 #if defined(INCLUDE_BHH) 15802 if (!(h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) { 15803 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint); 15804 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 15805 MOS_MSG_SUBCLASS_BHH_SESS_GET, 15806 sess_id, 0, 15807 MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY, 15808 &reply_len); 15809 if (BCM_FAILURE(rv)) { 15810 LOG_ERROR(BSL_LS_BCM_OAM, 15811 (BSL_META_U(unit, 15812 "OAM(unit %d) Error: ukernel msg failed for" 15813 " EP=%d %s.\n"), unit, endpoint, bcm_errmsg(rv))); 15814 _BCM_OAM_UNLOCK(oc); 15815 return (rv); 15816 } 15817 15818 /* Pack control message data into DMA buffer */ 15819 buffer = oc->dma_buffer; 15820 buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg); 15821 buffer_len = buffer_ptr - buffer; 15822 15823 if (reply_len != buffer_len) { 15824 rv = BCM_E_INTERNAL; 15825 LOG_ERROR(BSL_LS_BCM_OAM, 15826 (BSL_META_U(unit, 15827 "OAM(unit %d) Error: ukernel msg failed for" 15828 " EP=%d %s.\n"), unit, endpoint, bcm_errmsg(rv))); 15829 _BCM_OAM_UNLOCK(oc); 15830 return (rv); 15831 } else { 15832 endpoint_info->int_pri = msg.tx_cos; 15833 endpoint_info->pkt_pri = msg.tx_pri; 15834 endpoint_info->mpls_exp = msg.priority; 15835 15836 if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE){ 15837 endpoint_info->name = msg.remote_mep_id; 15838 endpoint_info->ccm_period = msg.remote_period; 15839 } else { 15840 endpoint_info->name = msg.mep_id; 15841 endpoint_info->ccm_period = msg.local_period; 15842 } 15843 15844 if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){ 15845 endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT; 15846 } 15847 if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){ 15848 endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI; 15849 } 15850 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){ 15851 endpoint_info->faults |= 15852 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL; 15853 } 15854 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){ 15855 endpoint_info->faults |= 15856 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID; 15857 } 15858 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){ 15859 endpoint_info->faults |= 15860 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID; 15861 } 15862 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){ 15863 endpoint_info->faults |= 15864 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD; 15865 } 15866 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){ 15867 endpoint_info->faults |= 15868 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY; 15869 } 15870 if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) { 15871 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS; 15872 } 15873 if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) { 15874 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI; 15875 } 15876 if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) { 15877 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI; 15878 } 15879 } 15880 }else { 15881 endpoint_info->ccm_period = h_data_p->period; 15882 endpoint_info->int_pri = h_data_p->int_pri; 15883 endpoint_info->pkt_pri = h_data_p->vlan_pri; 15884 } 15885 15886 endpoint_info->intf_id = h_data_p->egress_if; 15887 endpoint_info->cpu_qid = h_data_p->cpu_qid; 15888 endpoint_info->mpls_label = h_data_p->label; 15889 endpoint_info->gport = h_data_p->gport; 15890 endpoint_info->vpn = h_data_p->vpn; 15891 endpoint_info->vccv_type = h_data_p->vccv_type; 15892 endpoint_info->egress_label.label = h_data_p->egr_label; 15893 endpoint_info->egress_label.exp = h_data_p->egr_label_exp; 15894 endpoint_info->egress_label.ttl = h_data_p->egr_label_ttl; 15895 endpoint_info->inner_pkt_pri = h_data_p->inner_vlan_pri; 15896 if (!BHH_EP_MPLS_SECTION_TYPE(h_data_p)) { 15897 /* 15898 * Get MAC address 15899 */ 15900 bcm_l3_egress_t_init(&l3_egress); 15901 bcm_l3_intf_t_init(&l3_intf); 15902 15903 if (BCM_FAILURE 15904 (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) { 15905 _BCM_OAM_UNLOCK(oc); 15906 return (BCM_E_INTERNAL); 15907 } 15908 15909 l3_intf.l3a_intf_id = l3_egress.intf; 15910 if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) { 15911 _BCM_OAM_UNLOCK(oc); 15912 return (BCM_E_INTERNAL); 15913 } 15914 15915 sal_memcpy(endpoint_info->src_mac_address, l3_intf.l3a_mac_addr, 15916 _BHH_MAC_ADDR_LENGTH); 15917 } else { 15918 sal_memcpy(endpoint_info->src_mac_address, h_data_p->src_mac_address, 15919 _BHH_MAC_ADDR_LENGTH); 15920 sal_memcpy(endpoint_info->dst_mac_address, h_data_p->dst_mac_address, 15921 _BHH_MAC_ADDR_LENGTH); 15922 } 15923 #else 15924 _BCM_OAM_UNLOCK(oc); 15925 return (BCM_E_UNAVAIL); 15926 #endif /* INCLUDE_BHH */ 15927 } 15928 else { 15929 _BCM_OAM_UNLOCK(oc); 15930 return (BCM_E_PARAM); 15931 } 15932 15933 /* BHH MEP Id & period already filled from uC msg */ 15934 if (!BHH_EP_TYPE(h_data_p)) { 15935 endpoint_info->name = h_data_p->name; 15936 endpoint_info->ccm_period = h_data_p->period; 15937 } 15938 15939 endpoint_info->id = endpoint; 15940 endpoint_info->group = h_data_p->group_index; 15941 endpoint_info->vlan = h_data_p->vlan; 15942 endpoint_info->inner_vlan = h_data_p->inner_vlan; 15943 endpoint_info->level = h_data_p->level; 15944 endpoint_info->gport = h_data_p->gport; 15945 endpoint_info->trunk_index = h_data_p->trunk_index; 15946 endpoint_info->flags |= h_data_p->flags; 15947 endpoint_info->flags &= ~(BCM_OAM_ENDPOINT_WITH_ID); 15948 endpoint_info->opcode_flags = h_data_p->opcode_flags; 15949 endpoint_info->type = h_data_p->type; 15950 endpoint_info->lm_counter_base_id = h_data_p->rx_ctr; 15951 endpoint_info->outer_tpid = h_data_p->outer_tpid; 15952 endpoint_info->inner_tpid = h_data_p->inner_tpid; 15953 endpoint_info->subport_tpid = h_data_p->subport_tpid; 15954 endpoint_info->timestamp_format = h_data_p->ts_format; 15955 entries[0] = &mem_entries; 15956 if (h_data_p->pri_map_index != _BCM_OAM_INVALID_INDEX) { 15957 rv = soc_profile_mem_get(unit, &oc->ing_service_pri_map, 15958 (h_data_p->pri_map_index * BCM_OAM_INTPRI_MAX), 15959 BCM_OAM_INTPRI_MAX, (void *)entries); 15960 for (i = 0; i < BCM_OAM_INTPRI_MAX ; i++) { 15961 if (SOC_MEM_FIELD_VALID(unit, ING_SERVICE_PRI_MAPm, OFFSET_VALIDf)) { 15962 soc_mem_field32_set(unit, ING_SERVICE_PRI_MAPm, &mem_entries[i], 15963 OFFSET_VALIDf, 0); 15964 endpoint_info->pri_map[i] = mem_entries[i]; 15965 } 15966 } 15967 endpoint_info->pri_map_id = h_data_p->pri_map_index; 15968 } 15969 _BCM_OAM_UNLOCK(oc); 15970 return (BCM_E_NONE); 15971 } 15972 15973 15974 /* 15975 * Function: 15976 * bcm_kt2_oam_endpoint_destroy 15977 * Purpose: 15978 * Destroy an OAM endpoint object 15979 * Parameters: 15980 * unit - (IN) BCM device number 15981 * endpoint - (IN) Endpoint ID to destroy. 15982 * result =s: 15983 * BCM_E_XXX 15984 */ 15985 int 15986 bcm_kt2_oam_endpoint_destroy(int unit, bcm_oam_endpoint_t endpoint) 15987 { 15988 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 15989 int rv; /* Operation return status. */ 15990 15991 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 15992 /* Validate endpoint index value. */ 15993 _BCM_OAM_EP_INDEX_VALIDATE(endpoint); 15994 15995 _BCM_OAM_LOCK(oc); 15996 15997 rv = _bcm_kt2_oam_endpoint_destroy(unit, endpoint); 15998 if (BCM_FAILURE(rv)) { 15999 LOG_ERROR(BSL_LS_BCM_OAM, 16000 (BSL_META_U(unit, 16001 "OAM Error: Endpoint destroy EP=%d failed - " 16002 "%s.\n"), endpoint, bcm_errmsg(rv))); 16003 } 16004 16005 _BCM_OAM_UNLOCK(oc); 16006 return (rv); 16007 } 16008 16009 /* 16010 * Function: 16011 * bcm_kt2_oam_endpoint_destroy_all 16012 * Purpose: 16013 * Destroy all OAM endpoint objects associated with a group. 16014 * Parameters: 16015 * unit - (IN) BCM device number 16016 * group - (IN) The OAM group whose endpoints should be destroyed 16017 * Returns: 16018 * BCM_E_XXX 16019 */ 16020 int 16021 bcm_kt2_oam_endpoint_destroy_all(int unit, bcm_oam_group_t group) 16022 { 16023 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 16024 int rv; /* Operation return status. */ 16025 _bcm_oam_group_data_t *g_info_p; 16026 16027 /* Get OAM device control structure. */ 16028 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 16029 16030 /* Validate group index. */ 16031 _BCM_OAM_GROUP_INDEX_VALIDATE(group); 16032 16033 _BCM_OAM_LOCK(oc); 16034 16035 /* Check if the group is in use. */ 16036 rv = shr_idxres_list_elem_state(oc->group_pool, group); 16037 if (BCM_E_EXISTS != rv) { 16038 _BCM_OAM_UNLOCK(oc); 16039 LOG_ERROR(BSL_LS_BCM_OAM, 16040 (BSL_META_U(unit, 16041 "OAM Error: Group ID=%d does not exist.\n"), 16042 group)); 16043 return (rv); 16044 } 16045 16046 /* Get the group data pointer. */ 16047 g_info_p = &oc->group_info[group]; 16048 rv = _bcm_kt2_oam_group_endpoints_destroy(unit, g_info_p); 16049 if (BCM_FAILURE(rv)) { 16050 LOG_ERROR(BSL_LS_BCM_OAM, 16051 (BSL_META_U(unit, 16052 "OAM Error: Group (GID=%d) endpoints destroy" 16053 " failed - %s.\n"), group, bcm_errmsg(rv))); 16054 _BCM_OAM_UNLOCK(oc); 16055 return (rv); 16056 } 16057 _BCM_OAM_UNLOCK(oc); 16058 return (rv); 16059 } 16060 16061 /* 16062 * Function: 16063 * bcm_kt2_oam_endpoint_traverse 16064 * Purpose: 16065 * Traverse the set of OAM endpoints associated with the 16066 * specified group, calling a specified callback for each one 16067 * Parameters: 16068 * unit - (IN) BCM device number 16069 * group - (IN) The OAM group whose endpoints should be traversed 16070 * cb - (IN) A pointer to the callback function to call for each OAM 16071 * endpoint in the specified group 16072 * user_data - (IN) Pointer to user data to supply in the callback 16073 * Returns: 16074 * BCM_E_XXX 16075 */ 16076 int 16077 bcm_kt2_oam_endpoint_traverse(int unit, bcm_oam_group_t group, 16078 bcm_oam_endpoint_traverse_cb cb, 16079 void *user_data) 16080 { 16081 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 16082 int rv; /* Operation return status. */ 16083 bcm_oam_endpoint_info_t ep_info; 16084 _bcm_oam_hash_data_t *h_data_p; 16085 _bcm_oam_ep_list_t *cur; 16086 _bcm_oam_group_data_t *g_info_p; 16087 16088 /* Validate input parameter. */ 16089 if (NULL == cb) { 16090 return (BCM_E_PARAM); 16091 } 16092 16093 /* Get OAM device control structure. */ 16094 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 16095 16096 /* Validate group index. */ 16097 _BCM_OAM_GROUP_INDEX_VALIDATE(group); 16098 16099 _BCM_OAM_LOCK(oc); 16100 16101 /* Check if the group is in use. */ 16102 rv = shr_idxres_list_elem_state(oc->group_pool, group); 16103 if (BCM_E_EXISTS != rv) { 16104 _BCM_OAM_UNLOCK(oc); 16105 LOG_ERROR(BSL_LS_BCM_OAM, 16106 (BSL_META_U(unit, 16107 "OAM Error: Group ID=%d does not exist.\n"), 16108 group)); 16109 return (rv); 16110 } 16111 16112 /* Get the group data pointer. */ 16113 g_info_p = &oc->group_info[group]; 16114 16115 /* Get the endpoint list head pointer. */ 16116 cur = *(g_info_p->ep_list); 16117 if (NULL == cur) { 16118 _BCM_OAM_UNLOCK(oc); 16119 LOG_DEBUG(BSL_LS_BCM_OAM, 16120 (BSL_META_U(unit, 16121 "OAM Info: No endpoints in group GID=%d.\n"), 16122 group)); 16123 return (BCM_E_NONE); 16124 } 16125 16126 /* Traverse to the tail of the list. */ 16127 while (NULL != cur->next) { 16128 LOG_DEBUG(BSL_LS_BCM_OAM, 16129 (BSL_META_U(unit, 16130 "OAM Info: GID=%d EP:%d.\n"), 16131 cur->ep_data_p->group_index, cur->ep_data_p->ep_id)); 16132 cur = cur->next; 16133 } 16134 16135 while (NULL != cur) { 16136 h_data_p = cur->ep_data_p; 16137 if (NULL == h_data_p) { 16138 LOG_ERROR(BSL_LS_BCM_OAM, 16139 (BSL_META_U(unit, 16140 "OAM Error: Group=%d endpoints access failed -" 16141 " %s.\n"), group, bcm_errmsg(BCM_E_INTERNAL))); 16142 _BCM_OAM_UNLOCK(oc); 16143 return (BCM_E_INTERNAL); 16144 } 16145 bcm_oam_endpoint_info_t_init(&ep_info); 16146 16147 rv = bcm_kt2_oam_endpoint_get(unit, h_data_p->ep_id, &ep_info); 16148 if (BCM_FAILURE(rv)) { 16149 _BCM_OAM_UNLOCK(oc); 16150 LOG_ERROR(BSL_LS_BCM_OAM, 16151 (BSL_META_U(unit, 16152 "OAM Error: EP=%d info get failed %s.\n"), 16153 h_data_p->ep_id, bcm_errmsg(rv))); 16154 return (rv); 16155 } 16156 16157 rv = cb(unit, &ep_info, user_data); 16158 if (BCM_FAILURE(rv)) { 16159 _BCM_OAM_UNLOCK(oc); 16160 LOG_ERROR(BSL_LS_BCM_OAM, 16161 (BSL_META_U(unit, 16162 "OAM Error: EP=%d callback failed - %s.\n"), 16163 h_data_p->ep_id, bcm_errmsg(rv))); 16164 return (rv); 16165 } 16166 cur = cur->prev; 16167 } 16168 _BCM_OAM_UNLOCK(oc); 16169 return (rv); 16170 } 16171 16172 /* 16173 * Function: 16174 * bcm_kt2_oam_event_register 16175 * Purpose: 16176 * Register a callback for handling OAM events 16177 * Parameters: 16178 * unit - (IN) BCM device number 16179 * event_types - (IN) The set of OAM events for which the specified 16180 * callback should be called. 16181 * cb - (IN) A pointer to the callback function to call for 16182 * the specified OAM events 16183 * user_data - (IN) Pointer to user data to supply in the callback 16184 * Returns: 16185 * BCM_E_XXX 16186 */ 16187 int 16188 bcm_kt2_oam_event_register(int unit, bcm_oam_event_types_t event_types, 16189 bcm_oam_event_cb cb, void *user_data) 16190 { 16191 _bcm_oam_control_t *oc; 16192 _bcm_oam_event_handler_t *event_h_p; 16193 _bcm_oam_event_handler_t *prev_p = NULL; 16194 bcm_oam_event_type_t e_type; 16195 uint32 rval; 16196 int hw_update = 0; 16197 uint32 event_bmp; 16198 int rv; /* Operation return status. */ 16199 16200 /* Validate event callback input parameter. */ 16201 if (NULL == cb) { 16202 return (BCM_E_PARAM); 16203 } 16204 16205 /* Check if an event is set for register in the events bitmap. */ 16206 SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp); 16207 if (0 == event_bmp) { 16208 /* No events specified. */ 16209 LOG_ERROR(BSL_LS_BCM_OAM, 16210 (BSL_META_U(unit, 16211 "OAM Error: No events specified for register.\n"))); 16212 return (BCM_E_PARAM); 16213 } 16214 16215 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 16216 16217 _BCM_OAM_LOCK(oc); 16218 16219 for (event_h_p = oc->event_handler_list_p; event_h_p != NULL; 16220 event_h_p = event_h_p->next_p) { 16221 if (event_h_p->cb == cb) { 16222 break; 16223 } 16224 prev_p = event_h_p; 16225 } 16226 16227 if (NULL == event_h_p) { 16228 16229 _BCM_OAM_ALLOC(event_h_p, _bcm_oam_event_handler_t, 16230 sizeof(_bcm_oam_event_handler_t), "OAM event handler"); 16231 16232 if (NULL == event_h_p) { 16233 LOG_ERROR(BSL_LS_BCM_OAM, 16234 (BSL_META_U(unit, 16235 "OAM Error: Event handler alloc failed -" 16236 " %s.\n"), bcm_errmsg(BCM_E_MEMORY))); 16237 _BCM_OAM_UNLOCK(oc); 16238 return (BCM_E_MEMORY); 16239 } 16240 16241 event_h_p->next_p = NULL; 16242 event_h_p->cb = cb; 16243 16244 SHR_BITCLR_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount); 16245 if (prev_p != NULL) { 16246 prev_p->next_p = event_h_p; 16247 } else { 16248 oc->event_handler_list_p = event_h_p; 16249 } 16250 } 16251 16252 rv = READ_CCM_INTERRUPT_CONTROLr(unit, &rval); 16253 if (BCM_FAILURE(rv)) { 16254 _BCM_OAM_UNLOCK(oc); 16255 LOG_ERROR(BSL_LS_BCM_OAM, 16256 (BSL_META_U(unit, 16257 "OAM Error: CCM interrupt control read failed -" 16258 " %s.\n"), bcm_errmsg(rv))); 16259 return (rv); 16260 } 16261 16262 for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) { 16263 if (SHR_BITGET(event_types.w, e_type)) { 16264 if(soc_feature(unit, soc_feature_bhh)) { 16265 #if defined(INCLUDE_BHH) 16266 /* 16267 * BHH events are generated by the uKernel 16268 */ 16269 if ((e_type == bcmOAMEventBHHLBTimeout) || 16270 (e_type == bcmOAMEventBHHLBDiscoveryUpdate) || 16271 (e_type == bcmOAMEventBHHCCMTimeout) || 16272 (e_type == bcmOAMEventBHHCCMTimeoutClear) || 16273 (e_type == bcmOAMEventBHHCCMState) || 16274 (e_type == bcmOAMEventBHHCCMRdi) || 16275 (e_type == bcmOAMEventBHHCCMUnknownMegLevel) || 16276 (e_type == bcmOAMEventBHHCCMUnknownMegId) || 16277 (e_type == bcmOAMEventBHHCCMUnknownMepId) || 16278 (e_type == bcmOAMEventBHHCCMUnknownPeriod) || 16279 (e_type == bcmOAMEventBHHCCMUnknownPriority) || 16280 (e_type == bcmOAMEventBHHCCMRdiClear) || 16281 (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) || 16282 (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) || 16283 (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) || 16284 (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) || 16285 (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) || 16286 (e_type == bcmOAMEventCsfLos) || 16287 (e_type == bcmOAMEventCsfFdi) || 16288 (e_type == bcmOAMEventCsfRdi) || 16289 (e_type == bcmOAMEventBhhPmCounterRollover) || 16290 (e_type == bcmOAMEventCsfDci)) { 16291 SHR_BITSET(event_h_p->event_types.w, e_type); 16292 oc->event_handler_cnt[e_type] += 1; 16293 continue; 16294 } 16295 #endif 16296 } 16297 if (!soc_reg_field_valid 16298 (unit, CCM_INTERRUPT_CONTROLr, 16299 _kt2_oam_intr_en_fields[e_type].field)) { 16300 continue; 16301 } 16302 16303 if (!SHR_BITGET(event_h_p->event_types.w, e_type)) { 16304 /* Add this event to the registered events list. */ 16305 SHR_BITSET(event_h_p->event_types.w, e_type); 16306 oc->event_handler_cnt[e_type] += 1; 16307 if (1 == oc->event_handler_cnt[e_type]) { 16308 hw_update = 1; 16309 soc_reg_field_set 16310 (unit, CCM_INTERRUPT_CONTROLr, &rval, 16311 _kt2_oam_intr_en_fields[e_type].field, 1); 16312 } 16313 } 16314 } 16315 } 16316 16317 event_h_p->user_data = user_data; 16318 16319 if (1 == hw_update) { 16320 rv = WRITE_CCM_INTERRUPT_CONTROLr(unit, rval); 16321 if (BCM_FAILURE(rv)) { 16322 _BCM_OAM_UNLOCK(oc); 16323 LOG_ERROR(BSL_LS_BCM_OAM, 16324 (BSL_META_U(unit, 16325 "OAM Error: CCM interrupt control write failed -" 16326 " %s.\n"), bcm_errmsg(rv))); 16327 return (rv); 16328 } 16329 } 16330 if (soc_feature(unit, soc_feature_bhh)) { 16331 #if defined(INCLUDE_BHH) 16332 /* 16333 * Update BHH Events mask 16334 */ 16335 rv = _bcm_kt2_oam_bhh_event_mask_set(unit); 16336 #endif /* INCLUDE_BHH */ 16337 } 16338 16339 _BCM_OAM_UNLOCK(oc); 16340 16341 return (BCM_E_NONE); 16342 } 16343 16344 /* 16345 * Function: 16346 * bcm_kt2_oam_event_unregister 16347 * Purpose: 16348 * Remove a registered event from the event handler list. 16349 * Parameters: 16350 * unit - (IN) BCM device number 16351 * event_types - (IN) The set of OAM events for which the specified 16352 * callback should not be called 16353 * cb - (IN) A pointer to the callback function to unregister 16354 * from the specified OAM events 16355 * Returns: 16356 * BCM_E_XXX 16357 */ 16358 int 16359 bcm_kt2_oam_event_unregister(int unit, bcm_oam_event_types_t event_types, 16360 bcm_oam_event_cb cb) 16361 { 16362 _bcm_oam_control_t *oc; 16363 _bcm_oam_event_handler_t *event_h_p; 16364 _bcm_oam_event_handler_t *prev_p = NULL; 16365 bcm_oam_event_type_t e_type; 16366 uint32 rval; 16367 int hw_update = 0; 16368 uint32 event_bmp; 16369 int rv; /* Operation return status. */ 16370 16371 /* Validate event callback input parameter. */ 16372 if (NULL == cb) { 16373 return (BCM_E_PARAM); 16374 } 16375 16376 /* Check if an event is set for unregister in the events bitmap. */ 16377 SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp); 16378 if (0 == event_bmp) { 16379 /* No events specified. */ 16380 LOG_ERROR(BSL_LS_BCM_OAM, 16381 (BSL_META_U(unit, 16382 "OAM Error: No events specified for register.\n"))); 16383 return (BCM_E_PARAM); 16384 } 16385 16386 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 16387 16388 _BCM_OAM_LOCK(oc); 16389 16390 for (event_h_p = oc->event_handler_list_p; event_h_p != NULL; 16391 event_h_p = event_h_p->next_p) { 16392 if (event_h_p->cb == cb) { 16393 break; 16394 } 16395 prev_p = event_h_p; 16396 } 16397 16398 if (NULL == event_h_p) { 16399 _BCM_OAM_UNLOCK(oc); 16400 return (BCM_E_NOT_FOUND); 16401 } 16402 16403 rv = READ_CCM_INTERRUPT_CONTROLr(unit, &rval); 16404 if (BCM_FAILURE(rv)) { 16405 _BCM_OAM_UNLOCK(oc); 16406 LOG_ERROR(BSL_LS_BCM_OAM, 16407 (BSL_META_U(unit, 16408 "OAM Error: CCM interrupt control read failed -" 16409 " %s.\n"), bcm_errmsg(rv))); 16410 return (rv); 16411 } 16412 16413 for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) { 16414 16415 if (SHR_BITGET(event_types.w, e_type)) { 16416 if(soc_feature(unit, soc_feature_bhh)) { 16417 #if defined(INCLUDE_BHH) 16418 /* 16419 * BHH events are generated by the uKernel 16420 */ 16421 if ((e_type == bcmOAMEventBHHLBTimeout) || 16422 (e_type == bcmOAMEventBHHLBDiscoveryUpdate) || 16423 (e_type == bcmOAMEventBHHCCMTimeout) || 16424 (e_type == bcmOAMEventBHHCCMTimeoutClear) || 16425 (e_type == bcmOAMEventBHHCCMState) || 16426 (e_type == bcmOAMEventBHHCCMRdi) || 16427 (e_type == bcmOAMEventBHHCCMUnknownMegLevel) || 16428 (e_type == bcmOAMEventBHHCCMUnknownMegId) || 16429 (e_type == bcmOAMEventBHHCCMUnknownMepId) || 16430 (e_type == bcmOAMEventBHHCCMUnknownPeriod) || 16431 (e_type == bcmOAMEventBHHCCMUnknownPriority) || 16432 (e_type == bcmOAMEventBHHCCMRdiClear) || 16433 (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) || 16434 (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) || 16435 (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) || 16436 (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) || 16437 (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) || 16438 (e_type == bcmOAMEventCsfLos) || 16439 (e_type == bcmOAMEventCsfFdi) || 16440 (e_type == bcmOAMEventCsfRdi) || 16441 (e_type == bcmOAMEventCsfDci) || 16442 (e_type == bcmOAMEventBhhPmCounterRollover)) { 16443 SHR_BITCLR(event_h_p->event_types.w, e_type); 16444 oc->event_handler_cnt[e_type] -= 1; 16445 continue; 16446 } 16447 #endif 16448 } 16449 16450 if (!soc_reg_field_valid 16451 (unit, CCM_INTERRUPT_CONTROLr, 16452 _kt2_oam_intr_en_fields[e_type].field)) { 16453 _BCM_OAM_UNLOCK(oc); 16454 return (BCM_E_UNAVAIL); 16455 } 16456 16457 if ((oc->event_handler_cnt[e_type] > 0) 16458 && SHR_BITGET(event_h_p->event_types.w, e_type)) { 16459 16460 /* Remove this event from the registered events list. */ 16461 SHR_BITCLR(event_h_p->event_types.w, e_type); 16462 16463 oc->event_handler_cnt[e_type] -= 1; 16464 16465 if (0 == oc->event_handler_cnt[e_type]) { 16466 hw_update = 1; 16467 soc_reg_field_set 16468 (unit, CCM_INTERRUPT_CONTROLr, &rval, 16469 _kt2_oam_intr_en_fields[e_type].field, 0); 16470 } 16471 } 16472 } 16473 } 16474 16475 if (1 == hw_update) { 16476 rv = WRITE_CCM_INTERRUPT_CONTROLr(unit, rval); 16477 if (BCM_FAILURE(rv)) { 16478 _BCM_OAM_UNLOCK(oc); 16479 LOG_ERROR(BSL_LS_BCM_OAM, 16480 (BSL_META_U(unit, 16481 "OAM Error: CCM interrupt control write failed -" 16482 " %s.\n"), bcm_errmsg(rv))); 16483 return (rv); 16484 } 16485 } 16486 16487 SHR_BITTEST_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount, event_bmp); 16488 16489 if (0 == event_bmp) { 16490 16491 if (NULL != prev_p) { 16492 16493 prev_p->next_p = event_h_p->next_p; 16494 16495 } else { 16496 16497 oc->event_handler_list_p = event_h_p->next_p; 16498 16499 } 16500 sal_free(event_h_p); 16501 } 16502 if(soc_feature(unit, soc_feature_bhh)) { 16503 #if defined(INCLUDE_BHH) 16504 /* 16505 * Update BHH Events mask 16506 */ 16507 rv = _bcm_kt2_oam_bhh_event_mask_set(unit); 16508 #endif /* INCLUDE_BHH */ 16509 } 16510 _BCM_OAM_UNLOCK(oc); 16511 return (BCM_E_NONE); 16512 } 16513 16514 16515 /* 16516 * Function: 16517 * bcm_kt2_oam_endpoint_action_set 16518 * Purpose: 16519 * Remove a registered event from the event handler list. 16520 * Parameters: 16521 * unit - (IN) BCM device number 16522 * endpoint - (IN) Endpoint id 16523 * action - (IN) Set of OAM endpoint actions, for a set of 16524 * opcodes specified. 16525 * Returns: 16526 * BCM_E_XXX 16527 * In order to put the opcodes into opcode group1 and group2, first call the 16528 * action set API with opcode action and set of opcodes that need to use 16529 * this action. This will put all these opcodes under group1. To put 16530 * the opcode to group2, call the set API with an action(with all the opcodes 16531 * that need this action) which is differing compared to group1. This will 16532 * classify the opcode to group2 16533 */ 16534 int bcm_kt2_oam_endpoint_action_set(int unit, bcm_oam_endpoint_t endpoint, 16535 bcm_oam_endpoint_action_t *action) 16536 { 16537 int rv = BCM_E_NONE; /* Operation return status. */ 16538 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 16539 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 16540 void *entries[1]; 16541 oam_opcode_control_profile_entry_t opcode_profile; 16542 egr_oam_opcode_control_profile_entry_t egr_opcode_profile; 16543 soc_profile_mem_t *profile_mem_ptr; 16544 soc_mem_t ma_index_mem = MA_INDEXm; 16545 ma_index_entry_t ma_idx_entry; /* MA_INDEX table entry buffer. */ 16546 egr_ma_index_entry_t egr_ma_idx_entry; /* EGR_MA_INDEX table entry buffer*/ 16547 void *ma_idx_ptr; 16548 int ma_offset = 0; 16549 uint32 old_profile_index = 0; 16550 char free_old_profile = 0; 16551 /*setting default value to 0 whcih will be converted to 1 16552 * if opcode control profile set is touched */ 16553 uint8 opcode_profile_changed = 0; 16554 16555 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 16556 _BCM_OAM_EP_INDEX_VALIDATE(endpoint); 16557 16558 sal_memset(&opcode_profile, 0, sizeof(oam_opcode_control_profile_entry_t)); 16559 sal_memset(&egr_opcode_profile, 0, 16560 sizeof(egr_oam_opcode_control_profile_entry_t)); 16561 16562 _BCM_OAM_LOCK(oc); 16563 16564 /* Check endpoint status. */ 16565 rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint); 16566 if ((BCM_E_EXISTS != rv)) { 16567 /* Endpoint not in use. */ 16568 LOG_ERROR(BSL_LS_BCM_OAM, 16569 (BSL_META_U(unit, 16570 "OAM Error: Endpoint EP=%d %s.\n"), 16571 endpoint, bcm_errmsg(rv))); 16572 _BCM_OAM_UNLOCK(oc); 16573 return (rv); 16574 } 16575 16576 h_data_p = &oc->oam_hash_data[endpoint]; 16577 if (NULL == h_data_p) { 16578 _BCM_OAM_UNLOCK(oc); 16579 return (BCM_E_INTERNAL); 16580 } 16581 16582 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 16583 entries[0] = &egr_opcode_profile; 16584 profile_mem_ptr = &oc->egr_oam_opcode_control_profile; 16585 ma_index_mem = EGR_MA_INDEXm; 16586 ma_idx_ptr = &egr_ma_idx_entry; 16587 } else { 16588 entries[0] = &opcode_profile; 16589 profile_mem_ptr = &oc->oam_opcode_control_profile; 16590 ma_idx_ptr = &ma_idx_entry; 16591 } 16592 16593 /* Get MA_INDEX offset */ 16594 rv = _bcm_kt2_oam_ma_index_offset_get(unit, h_data_p, &ma_offset); 16595 16596 h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset; 16597 16598 /* Using the profile index, get the profile */ 16599 if ((h_data_p->profile_index == _BCM_OAM_INVALID_INDEX) || 16600 (h_data_p->profile_index == 0)) { 16601 /* No profile exists or default profile is used, create one */ 16602 /* convert action into opcode profile entry */ 16603 rv = _bcm_kt2_oam_convert_action_to_opcode_entry(unit, action, 16604 endpoint, 16605 entries[0], 16606 &opcode_profile_changed); 16607 if (BCM_FAILURE(rv)) { 16608 _BCM_OAM_UNLOCK(oc); 16609 LOG_ERROR(BSL_LS_BCM_OAM, 16610 (BSL_META_U(unit, 16611 "OAM Error: Failed to convert action to " 16612 "profile -" " %s.\n"), bcm_errmsg(rv))); 16613 return (rv); 16614 } 16615 if(opcode_profile_changed) { 16616 rv = soc_profile_mem_add(unit, profile_mem_ptr, 16617 (void *)entries, 1, 16618 (uint32 *) &h_data_p->profile_index); 16619 if (BCM_FAILURE(rv)) { 16620 _BCM_OAM_UNLOCK(oc); 16621 LOG_ERROR(BSL_LS_BCM_OAM, 16622 (BSL_META_U(unit, 16623 "OAM Error: Soc profile mem add failed -" 16624 " %s.\n"), bcm_errmsg(rv))); 16625 return (rv); 16626 } 16627 } 16628 } else { 16629 free_old_profile = 1; 16630 old_profile_index = h_data_p->profile_index; 16631 16632 rv = soc_profile_mem_get(unit, profile_mem_ptr, 16633 old_profile_index, 1, entries); 16634 if (BCM_FAILURE(rv)) { 16635 _BCM_OAM_UNLOCK(oc); 16636 LOG_ERROR(BSL_LS_BCM_OAM, 16637 (BSL_META_U(unit, 16638 "OAM Error: Soc profile mem get failed -" 16639 " %s.\n"), bcm_errmsg(rv))); 16640 return (rv); 16641 } 16642 /* convert action into opcode profile entry */ 16643 _bcm_kt2_oam_convert_action_to_opcode_entry(unit, action, 16644 endpoint, 16645 entries[0], 16646 &opcode_profile_changed); 16647 16648 /* Add new profile */ 16649 rv = soc_profile_mem_add(unit, profile_mem_ptr, 16650 (void *)entries, 1, 16651 (uint32 *) &h_data_p->profile_index); 16652 if (BCM_FAILURE(rv)) { 16653 _BCM_OAM_UNLOCK(oc); 16654 LOG_ERROR(BSL_LS_BCM_OAM, 16655 (BSL_META_U(unit, 16656 "OAM Error: Soc profile mem add failed -" 16657 " %s.\n"), bcm_errmsg(rv))); 16658 return (rv); 16659 } 16660 } 16661 /* Set OAM opcode control profile table index. */ 16662 rv = soc_mem_read(unit, ma_index_mem, MEM_BLOCK_ANY, 16663 h_data_p->local_rx_index, ma_idx_ptr); 16664 if (BCM_FAILURE(rv)) { 16665 _BCM_OAM_UNLOCK(oc); 16666 LOG_ERROR(BSL_LS_BCM_OAM, 16667 (BSL_META_U(unit, 16668 "OAM Error: MA index table entry read failed " 16669 "%s.\n"), bcm_errmsg(rv))); 16670 return (rv); 16671 } 16672 soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr, 16673 OAM_OPCODE_CONTROL_PROFILE_PTRf, 16674 h_data_p->profile_index); 16675 rv = soc_mem_write(unit, ma_index_mem, MEM_BLOCK_ALL, 16676 h_data_p->local_rx_index, ma_idx_ptr); 16677 16678 /* Delete old profile once ma_index is pointing to new one*/ 16679 if(free_old_profile) { 16680 rv = soc_profile_mem_delete(unit, profile_mem_ptr, 16681 old_profile_index); 16682 if (BCM_FAILURE(rv)) { 16683 _BCM_OAM_UNLOCK(oc); 16684 LOG_ERROR(BSL_LS_BCM_OAM, 16685 (BSL_META_U(unit, 16686 "OAM Error: Soc profile mem delete failed -" 16687 " %s.\n"), bcm_errmsg(rv))); 16688 return (rv); 16689 } 16690 16691 } 16692 16693 _BCM_OAM_UNLOCK(oc); 16694 return rv; 16695 } 16696 16697 /* 16698 * Function: 16699 * _kt2_oam_opcode_control_field_set 16700 * Purpose: 16701 * Set the fields of opcode profile entry 16702 * Parameters: 16703 * unit - (IN) BCM device number 16704 * field_index - (IN) Opcode profile action to be set 16705 * mem - (IN) Opcode profile memory - ing/egr 16706 * oam_opcode - (IN) Oam opcode for which action needs to be set 16707 * value - (IN) value of the opcode action 16708 * profile - (OUT) Pointer to the opcode profile table index. 16709 * Returns: 16710 * BCM_E_XXX 16711 */ 16712 int 16713 _kt2_oam_opcode_control_field_set(int unit, bcm_oam_action_type_t field_index, 16714 soc_mem_t mem, int oam_opcode, int value, 16715 void *profile) 16716 { 16717 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 16718 ingress_oam_opcode_group_entry_t entry; 16719 int grp_1_modified = 0; 16720 int grp_2_modified = 0; 16721 uint32 opcode_bmp_1 = 0; 16722 uint32 opcode_bmp_2 = 0; 16723 soc_field_t cfm_field[bcmOAMActionCount+1][_BCM_OAM_OPCODE_TYPE_NON_CFM_FIRST] = { 16724 /* bcmOAMActionCountEnable */ 16725 { 0, 0, 0, 0, 0, 0}, 16726 /* bcmOAMActionMeterEnable */ 16727 { 0, 0, 0, 0, 0, 0}, 16728 /* bcmOAMActionDrop */ 16729 { 0, CCM_DROPf, LBR_DROPf, LBM_UC_DROPf, 16730 LTR_DROPf, LTM_DROPf }, 16731 /* bcmOAMActionCopyToCpu */ 16732 { 0, CCM_COPYTO_CPUf, LBR_COPYTO_CPUf, LBM_UC_COPYTO_CPUf, 16733 LTR_COPYTO_CPUf, LTM_COPYTO_CPUf}, 16734 /* bcmOAMActionFwdAsData */ 16735 { 0, 0, 0, 0, 0, 0 }, 16736 /* bcmOAMActionFwd */ 16737 { 0, FWD_LMEP_PKTf, LBR_FWDf, LBM_ACTIONf, LTR_FWDf, LTM_FWDf}, 16738 /* bcmOAMActionUcDrop */ 16739 { 0, 0, 0, LBM_UC_DROPf, 0, 0}, 16740 /* bcmOAMActionUcCopyToCpu */ 16741 { 0, 0, 0, LBM_UC_COPYTO_CPUf, 0, 0}, 16742 /* bcmOAMActionUcFwdAsData */ 16743 { 0, 0, 0, 0, 0, 0 }, 16744 /* bcmOAMActionUcFwd */ 16745 { 0, 0, 0, LBM_ACTIONf, 0, 0}, 16746 /* bcmOAMActionMcDrop */ 16747 { 0, 0, 0, LBM_MC_DROPf, 0, 0}, 16748 /* bcmOAMActionMcCopyToCpu */ 16749 { 0, 0, 0, LBM_MC_COPYTO_CPUf, 0, 0}, 16750 /* bcmOAMActionMcFwdAsData */ 16751 { 0, 0, 0, 0, 0, 0}, 16752 /* bcmOAMActionMcFwd*/ 16753 { 0, 0, 0, LBM_MC_FWDf, 0, 0}, 16754 /* bcmOAMActionLowMdlDrop */ 16755 { 0, LOW_MDL_CCM_FWD_ACTIONf, LOW_MDL_LB_LT_DROPf, 16756 LOW_MDL_LB_LT_DROPf, LOW_MDL_LB_LT_DROPf, 16757 LOW_MDL_LB_LT_DROPf }, 16758 /* bcmOAMActionLowMdlCopyToCpu */ 16759 { 0, LOW_MDL_CCM_COPYTO_CPUf, LOW_MDL_LB_LT_COPYTO_CPUf, 16760 LOW_MDL_LB_LT_COPYTO_CPUf, 16761 LOW_MDL_LB_LT_COPYTO_CPUf, LOW_MDL_LB_LT_COPYTO_CPUf}, 16762 /* bcmOAMActionLowMdlFwdAsData */ 16763 { 0, LOW_MDL_CCM_FWD_ACTIONf, LOW_MDL_LB_LT_DROPf, 16764 LOW_MDL_LB_LT_DROPf, 16765 LOW_MDL_LB_LT_DROPf, LOW_MDL_LB_LT_DROPf}, 16766 /* bcmOAMActionLowMdlFwd*/ 16767 { 0, 0, LOW_MDL_LB_LT_FWDf, LOW_MDL_LB_LT_FWDf, 0, 0}, 16768 /* bcmOAMActionMyStationMissCopyToCpu */ 16769 { 0, 0, LB_LT_UC_MY_STATION_MISS_COPYTO_CPUf, 16770 LB_LT_UC_MY_STATION_MISS_COPYTO_CPUf, 16771 LB_LT_UC_MY_STATION_MISS_COPYTO_CPUf, 16772 LB_LT_UC_MY_STATION_MISS_COPYTO_CPUf}, 16773 /* bcmOAMActionMyStationMissDrop */ 16774 { 0, 0, LB_LT_UC_MY_STATION_MISS_DROPf, 16775 LB_LT_UC_MY_STATION_MISS_DROPf, 16776 LB_LT_UC_MY_STATION_MISS_DROPf, 16777 LB_LT_UC_MY_STATION_MISS_DROPf}, 16778 /* bcmOAMActionMyStationMissFwdAsData */ 16779 { 0, 0, 0, 0, 0, 0}, 16780 /* bcmOAMActionMyStationMissFwd */ 16781 { 0, 0, LB_LT_UC_MY_STATION_MISS_FWDf, 16782 LB_LT_UC_MY_STATION_MISS_FWDf, 16783 LB_LT_UC_MY_STATION_MISS_FWDf, 16784 LB_LT_UC_MY_STATION_MISS_FWDf}, 16785 /* bcmOAMActionProcessInHw */ 16786 { 0, CCM_PROCESS_IN_HWf, 0, 0, 0, 0}, 16787 /* bcmOAMActionLowMdlCcmFwdAsRegularCcm */ 16788 { 0, LOW_MDL_CCM_FWD_ACTIONf, 0, 0, 0, 0}, 16789 { 0, 0, 0, 0, 0, 0} 16790 }; 16791 16792 soc_field_t non_cfm_field[bcmOAMActionCount+1][2]= { 16793 /* bcmOAMActionCountEnable */ 16794 { 0, 0 }, 16795 /* bcmOAMActionMeterEnable */ 16796 { 0, 0 }, 16797 /* bcmOAMActionDrop */ 16798 { OTHER_OPCODE_GROUP_1_UC_MY_STATION_HIT_ACTIONf, 16799 OTHER_OPCODE_GROUP_2_UC_MY_STATION_HIT_ACTIONf }, 16800 /* bcmOAMActionCopyToCpu */ 16801 { OTHER_OPCODE_GROUP_1_UC_MY_STATION_HIT_COPYTO_CPUf, 16802 OTHER_OPCODE_GROUP_2_UC_MY_STATION_HIT_COPYTO_CPUf }, 16803 /* bcmOAMActionFwdAsData */ 16804 { OTHER_OPCODE_GROUP_1_UC_MY_STATION_HIT_ACTIONf, 16805 OTHER_OPCODE_GROUP_2_UC_MY_STATION_HIT_ACTIONf }, 16806 /* bcmOAMActionFwd */ 16807 { OTHER_OPCODE_GROUP_1_UC_MY_STATION_HIT_ACTIONf, 16808 OTHER_OPCODE_GROUP_2_UC_MY_STATION_HIT_ACTIONf }, 16809 /* bcmOAMActionUcDrop */ 16810 { 0, 0 }, 16811 /* bcmOAMActionUcCopyToCpu */ 16812 { 0, 0 }, 16813 /* bcmOAMActionUcFwdAsData */ 16814 { 0, 0 }, 16815 /* bcmOAMActionUcFwd */ 16816 { 0, 0 }, 16817 /* bcmOAMActionMcDrop */ 16818 { OTHER_OPCODE_GROUP_1_MC_ACTIONf, 16819 OTHER_OPCODE_GROUP_2_MC_ACTIONf }, 16820 /* bcmOAMActionMcCopyToCpu */ 16821 { OTHER_OPCODE_GROUP_1_MC_COPYTO_CPUf, 16822 OTHER_OPCODE_GROUP_2_MC_COPYTO_CPUf }, 16823 /* bcmOAMActionMcFwdAsData */ 16824 { OTHER_OPCODE_GROUP_1_MC_ACTIONf, 16825 OTHER_OPCODE_GROUP_2_MC_ACTIONf }, 16826 /* bcmOAMActionMcFwd*/ 16827 { OTHER_OPCODE_GROUP_1_MC_ACTIONf, 16828 OTHER_OPCODE_GROUP_2_MC_ACTIONf }, 16829 /* bcmOAMActionLowMdlDrop */ 16830 { OTHER_OPCODE_GROUP_1_LOW_MDL_ACTIONf, 16831 OTHER_OPCODE_GROUP_2_LOW_MDL_ACTIONf}, 16832 /* bcmOAMActionLowMdlCopyToCpu */ 16833 { OTHER_OPCODE_GROUP_1_LOW_MDL_COPYTO_CPUf, 16834 OTHER_OPCODE_GROUP_2_LOW_MDL_COPYTO_CPUf }, 16835 /* bcmOAMActionLowMdlFwdAsData */ 16836 { OTHER_OPCODE_GROUP_1_LOW_MDL_ACTIONf, 16837 OTHER_OPCODE_GROUP_2_LOW_MDL_ACTIONf }, 16838 /* bcmOAMActionLowMdlFwd*/ 16839 { OTHER_OPCODE_GROUP_1_LOW_MDL_ACTIONf, 16840 OTHER_OPCODE_GROUP_2_LOW_MDL_ACTIONf}, 16841 /* bcmOAMActionMyStationMissCopyToCpu */ 16842 { OTHER_OPCODE_GROUP_1_UC_MY_STATION_MISS_COPYTO_CPUf, 16843 OTHER_OPCODE_GROUP_2_UC_MY_STATION_MISS_COPYTO_CPUf }, 16844 /* bcmOAMActionMyStationMissDrop */ 16845 { OTHER_OPCODE_GROUP_1_UC_MY_STATION_MISS_ACTIONf, 16846 OTHER_OPCODE_GROUP_2_UC_MY_STATION_MISS_ACTIONf }, 16847 /* bcmOAMActionMyStationMissFwdAsData */ 16848 { OTHER_OPCODE_GROUP_1_UC_MY_STATION_MISS_ACTIONf, 16849 OTHER_OPCODE_GROUP_2_UC_MY_STATION_MISS_ACTIONf }, 16850 /* bcmOAMActionMyStationMissFwd */ 16851 { OTHER_OPCODE_GROUP_1_UC_MY_STATION_MISS_ACTIONf, 16852 OTHER_OPCODE_GROUP_2_UC_MY_STATION_MISS_ACTIONf}, 16853 /* bcmOAMActionProcessInHw */ 16854 { 0, 0 }, 16855 /* bcmOAMActionLowMdlCcmFwdAsRegularCcm */ 16856 { 0, 0 }, 16857 { 0, 0 } 16858 }; 16859 16860 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 16861 16862 SHR_BITTEST_RANGE(oc->opcode_grp_1_bmp, 0, 16863 _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST, opcode_bmp_1); 16864 SHR_BITTEST_RANGE(oc->opcode_grp_2_bmp, 0, 16865 _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST, opcode_bmp_2); 16866 if (oam_opcode < _BCM_OAM_OPCODE_TYPE_NON_CFM_FIRST) { 16867 if (cfm_field[field_index][oam_opcode] != 0) { 16868 soc_mem_field32_set(unit, mem, profile, 16869 cfm_field[field_index][oam_opcode], value); 16870 } 16871 } else { 16872 if ((opcode_bmp_1 == 0) && (opcode_bmp_2 == 0)) { 16873 if (SHR_BITGET(oc->opcode_grp_bmp, oam_opcode)) { 16874 SHR_BITSET(oc->opcode_grp_1_bmp, oam_opcode); 16875 SHR_BITCLR(oc->opcode_grp_bmp, oam_opcode); 16876 opcode_bmp_1 = 1; 16877 grp_1_modified = 1; 16878 } 16879 } 16880 /* Changing the action for same opcode */ 16881 if (SHR_BITGET(oc->opcode_grp_1_bmp, oam_opcode)) { 16882 if (non_cfm_field[field_index][0] != 0) { 16883 soc_mem_field32_set(unit, mem, profile, 16884 non_cfm_field[field_index][0], value); 16885 } 16886 } else if (SHR_BITGET(oc->opcode_grp_2_bmp, oam_opcode)) { 16887 if (non_cfm_field[field_index][1] != 0) { 16888 soc_mem_field32_set(unit, mem, profile, 16889 non_cfm_field[field_index][1], value); 16890 } 16891 } else if (SHR_BITGET(oc->opcode_grp_bmp, oam_opcode)) { 16892 if (value == soc_mem_field32_get(unit, mem, profile, 16893 non_cfm_field[field_index][0])) { 16894 /* Add this opcode to group 1 */ 16895 grp_1_modified = 1; 16896 SHR_BITSET(oc->opcode_grp_1_bmp, oam_opcode); 16897 SHR_BITCLR(oc->opcode_grp_bmp, oam_opcode); 16898 if (non_cfm_field[field_index][0] != 0) { 16899 soc_mem_field32_set(unit, mem, profile, 16900 non_cfm_field[field_index][0], value); 16901 } 16902 } else if (value == soc_mem_field32_get(unit, mem, profile, 16903 non_cfm_field[field_index][1])) { 16904 /* Add this opcode to group 2 */ 16905 grp_2_modified = 1; 16906 SHR_BITSET(oc->opcode_grp_2_bmp, oam_opcode); 16907 SHR_BITCLR(oc->opcode_grp_bmp, oam_opcode); 16908 if (non_cfm_field[field_index][1] != 0) { 16909 soc_mem_field32_set(unit, mem, profile, 16910 non_cfm_field[field_index][1], value); 16911 } 16912 } else if (opcode_bmp_1 == 0) { 16913 grp_1_modified = 1; 16914 SHR_BITSET(oc->opcode_grp_1_bmp, oam_opcode); 16915 SHR_BITCLR(oc->opcode_grp_bmp, oam_opcode); 16916 if (non_cfm_field[field_index][0] != 0) { 16917 soc_mem_field32_set(unit, mem, profile, 16918 non_cfm_field[field_index][0], value); 16919 } 16920 } else if (opcode_bmp_2 == 0) { 16921 grp_2_modified = 1; 16922 SHR_BITSET(oc->opcode_grp_2_bmp, oam_opcode); 16923 SHR_BITCLR(oc->opcode_grp_bmp, oam_opcode); 16924 if (non_cfm_field[field_index][1] != 0) { 16925 soc_mem_field32_set(unit, mem, profile, 16926 non_cfm_field[field_index][1], value); 16927 } 16928 } else { 16929 /* Add the opcode to group 1 by default */ 16930 grp_1_modified = 1; 16931 SHR_BITSET(oc->opcode_grp_1_bmp, oam_opcode); 16932 SHR_BITCLR(oc->opcode_grp_bmp, oam_opcode); 16933 if (non_cfm_field[field_index][0] != 0) { 16934 soc_mem_field32_set(unit, mem, profile, 16935 non_cfm_field[field_index][0], value); 16936 } 16937 } 16938 } else { 16939 return (BCM_E_PARAM); 16940 } 16941 } 16942 if (mem == OAM_OPCODE_CONTROL_PROFILEm) { 16943 mem = INGRESS_OAM_OPCODE_GROUPm; 16944 } else { 16945 mem = EGR_OAM_OPCODE_GROUPm; 16946 } 16947 if (grp_1_modified) { 16948 soc_mem_field32_set(unit, mem, &entry, OPCODE_GROUP_VALIDf, 1); 16949 soc_mem_field32_set(unit, mem, &entry, OPCODE_GROUPf, 0); 16950 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, 16951 MEM_BLOCK_ANY, oam_opcode, &entry)); 16952 16953 } else if(grp_2_modified) { 16954 soc_mem_field32_set(unit, mem, &entry, OPCODE_GROUP_VALIDf, 1); 16955 soc_mem_field32_set(unit, mem, &entry, OPCODE_GROUPf, 1); 16956 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, 16957 MEM_BLOCK_ANY, oam_opcode, &entry)); 16958 } 16959 return (BCM_E_NONE); 16960 } 16961 16962 /* 16963 * Function: 16964 * _bcm_kt2_oam_resolve_dglp 16965 * Purpose: 16966 * Add an dglp profile entry 16967 * Parameters: 16968 * unit - (IN) BCM device number 16969 * mem - (IN) dglp profile memory - ing/egr 16970 * dglp - (IN) DGLP value 16971 * profile - (OUT) Pointer to the dglp profile table index. 16972 * olp_enable - (OUT) Pointer to field indicating whether olp is enabled on 16973 * the port. 16974 * Returns: 16975 * BCM_E_XXX 16976 */ 16977 int 16978 _bcm_kt2_oam_resolve_dglp(int unit, soc_mem_t mem, uint32 dglp, 16979 uint32 *profile_index, int *olp_enable) 16980 { 16981 int rv = BCM_E_NONE; 16982 egr_olp_dgpp_config_entry_t *buf; 16983 egr_olp_dgpp_config_entry_t *entry; 16984 egr_oam_dglp_profile_entry_t egr_dglp_profile_entry; 16985 ing_oam_dglp_profile_entry_t ing_dglp_profile_entry; 16986 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 16987 int index_max = 0; 16988 int index = 0; 16989 uint32 configured_dglp = 0; 16990 void *entries[1]; 16991 void *profile_entry; 16992 soc_mem_t profile_mem; 16993 soc_profile_mem_t profile_ptr; 16994 int entry_mem_size = 0; 16995 16996 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 16997 16998 if (mem == EGR_OAM_OPCODE_CONTROL_PROFILEm) { 16999 profile_entry = (void *)&egr_dglp_profile_entry; 17000 profile_mem = EGR_OAM_DGLP_PROFILEm; 17001 profile_ptr = oc->egr_oam_dglp_profile; 17002 } else { 17003 profile_entry = (void *)&ing_dglp_profile_entry; 17004 profile_mem = ING_OAM_DGLP_PROFILEm; 17005 profile_ptr = oc->ing_oam_dglp_profile; 17006 } 17007 /* Check whether this DGLP is already configured as OLP port */ 17008 entry_mem_size = sizeof(egr_olp_dgpp_config_entry_t); 17009 /* Allocate buffer to store the DMAed table entries. */ 17010 index_max = soc_mem_index_max(unit, EGR_OLP_DGPP_CONFIGm); 17011 buf = soc_cm_salloc(unit, entry_mem_size * (index_max + 1), 17012 "OLP dglp config table entry buffer"); 17013 if (NULL == buf) { 17014 return (BCM_E_MEMORY); 17015 } 17016 /* Initialize the entry buffer. */ 17017 sal_memset(buf, 0, sizeof(entry_mem_size) * (index_max + 1)); 17018 17019 /* Read the table entries into the buffer. */ 17020 rv = soc_mem_read_range(unit, EGR_OLP_DGPP_CONFIGm, MEM_BLOCK_ALL, 17021 0, index_max, buf); 17022 if (BCM_FAILURE(rv)) { 17023 if (buf) { 17024 soc_cm_sfree(unit, buf); 17025 } 17026 return rv; 17027 } 17028 17029 /* Iterate over the table entries. */ 17030 for (index = 0; index <= index_max; index++) { 17031 entry = soc_mem_table_idx_to_pointer 17032 (unit, EGR_OLP_DGPP_CONFIGm, egr_olp_dgpp_config_entry_t *, 17033 buf, index); 17034 17035 soc_mem_field_get(unit, EGR_OLP_DGPP_CONFIGm, 17036 (uint32 *)entry, DGLPf, &configured_dglp); 17037 if (dglp == configured_dglp) { 17038 *olp_enable = 1; 17039 break; 17040 } 17041 } 17042 if (buf) { 17043 soc_cm_sfree(unit, buf); 17044 } 17045 /* Add entry to dglp profile table. */ 17046 soc_mem_field32_set(unit, profile_mem, profile_entry, DGLPf, dglp); 17047 entries[0] = profile_entry; 17048 17049 rv = soc_profile_mem_add(unit, &profile_ptr, 17050 (void *)entries, 1, profile_index); 17051 if (BCM_FAILURE(rv)) { 17052 LOG_ERROR(BSL_LS_BCM_OAM, 17053 (BSL_META_U(unit, 17054 "OAM DGLP profile table is full - %s.\n"), 17055 bcm_errmsg(rv))); 17056 return rv; 17057 } 17058 return (BCM_E_NONE); 17059 } 17060 17061 /* 17062 * Function: 17063 * _bcm_kt2_ma_index_entry_modify 17064 * Purpose: 17065 * Set dglp profile pointer index in the MA index table entry 17066 * Parameters: 17067 * unit - (IN) BCM device number 17068 * index - (IN) MA index table index 17069 * mem - (IN) MA index memory - ing/egr 17070 * profile_index- (IN)DGLP profile index 17071 * olp_enable - (IN) indicates whether olp is enabled for this entry 17072 * dglp_prt - (OUT) Pointer to dglp1/2 profile. 17073 * Returns: 17074 * BCM_E_XXX 17075 */ 17076 int 17077 _bcm_kt2_ma_index_entry_modify(int unit, int index, soc_mem_t mem, 17078 int profile_index, int olp_enable, int *dglp_ptr) 17079 { 17080 int rv = BCM_E_NONE; 17081 ma_index_entry_t ma_idx_entry; /* MA_INDEX table entry buffer. */ 17082 egr_ma_index_entry_t egr_ma_idx_entry; /* EGR_MA_INDEX table entry buffer.*/ 17083 void *entry; 17084 17085 if (mem == EGR_MA_INDEXm) { 17086 entry = (void *)&egr_ma_idx_entry; 17087 } else { 17088 entry = (void *)&ma_idx_entry; 17089 } 17090 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, entry); 17091 if (BCM_FAILURE(rv)) { 17092 LOG_ERROR(BSL_LS_BCM_OAM, 17093 (BSL_META_U(unit, 17094 "OAM Error: MA index table entry read failed " 17095 "%s.\n"), bcm_errmsg(rv))); 17096 return (rv); 17097 } 17098 if (0 == soc_mem_field32_get(unit, mem, (uint32 *)entry, 17099 DGLP1_PROFILE_PTRf)){ 17100 17101 soc_mem_field32_set(unit, mem, entry, 17102 DGLP1_PROFILE_PTRf, profile_index); 17103 if (olp_enable) { 17104 soc_mem_field32_set(unit, mem, entry, DGLP1_OLP_HDR_ADDf, 1); 17105 } 17106 *dglp_ptr = _BCM_OAM_DGLP1_PROFILE_PTR; 17107 } else if (0 == soc_mem_field32_get(unit, mem, (uint32 *)entry, 17108 DGLP2_PROFILE_PTRf)){ 17109 17110 soc_mem_field32_set(unit, mem, entry, 17111 DGLP2_PROFILE_PTRf, profile_index); 17112 if (olp_enable) { 17113 soc_mem_field32_set(unit, mem, entry, DGLP2_OLP_HDR_ADDf, 1); 17114 } 17115 *dglp_ptr = _BCM_OAM_DGLP2_PROFILE_PTR; 17116 } 17117 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, entry)); 17118 return (BCM_E_NONE); 17119 } 17120 17121 /* 17122 * Function: 17123 * _kt2_oam_counter_control_set 17124 * Purpose: 17125 * Enable/disable LM counter for a particular opcode 17126 * Parameters: 17127 * unit - (IN) BCM device number 17128 * opcode_i - (IN) OAM opcode for which counter needs 17129 * to be enabled/disabled 17130 * value - (IN) Counter enable/disable 17131 * Returns: 17132 * BCM_E_XXX 17133 */ 17134 int 17135 _kt2_oam_counter_control_set(int unit, int opcode_i, int value) 17136 { 17137 int rv = BCM_E_NONE; 17138 egr_lm_counter_control_entry_t egr_ctr; 17139 lm_counter_control_entry_t ing_ctr; 17140 17141 rv = soc_mem_read(unit, LM_COUNTER_CONTROLm, MEM_BLOCK_ANY, 17142 opcode_i, &ing_ctr); 17143 if (BCM_FAILURE(rv)) { 17144 LOG_ERROR(BSL_LS_BCM_OAM, 17145 (BSL_META_U(unit, 17146 "OAM Error: Counter control table entry read " 17147 "failed %s.\n"), bcm_errmsg(rv))); 17148 return (rv); 17149 } 17150 soc_LM_COUNTER_CONTROLm_field32_set(unit, &ing_ctr, COUNT_ENABLEf, value); 17151 rv = soc_mem_write(unit, LM_COUNTER_CONTROLm, MEM_BLOCK_ALL, 17152 opcode_i, &ing_ctr); 17153 if (BCM_FAILURE(rv)) { 17154 LOG_ERROR(BSL_LS_BCM_OAM, 17155 (BSL_META_U(unit, 17156 "OAM Error: Counter control table entry wtite " 17157 "failed %s.\n"), bcm_errmsg(rv))); 17158 return (rv); 17159 } 17160 rv = soc_mem_read(unit, EGR_LM_COUNTER_CONTROLm, MEM_BLOCK_ANY, 17161 opcode_i, &egr_ctr); 17162 if (BCM_FAILURE(rv)) { 17163 LOG_ERROR(BSL_LS_BCM_OAM, 17164 (BSL_META_U(unit, 17165 "OAM Error: Counter control table entry read " 17166 "failed %s.\n"), bcm_errmsg(rv))); 17167 return (rv); 17168 } 17169 soc_EGR_LM_COUNTER_CONTROLm_field32_set(unit, &egr_ctr, 17170 COUNT_ENABLEf, value); 17171 rv = soc_mem_write(unit, EGR_LM_COUNTER_CONTROLm, MEM_BLOCK_ALL, 17172 opcode_i, &ing_ctr); 17173 if (BCM_FAILURE(rv)) { 17174 LOG_ERROR(BSL_LS_BCM_OAM, 17175 (BSL_META_U(unit, 17176 "OAM Error: Counter control table entry wtite " 17177 "failed %s.\n"), bcm_errmsg(rv))); 17178 return (rv); 17179 } 17180 return rv; 17181 } 17182 17183 /* 17184 * Function: 17185 * _bcm_kt2_oam_convert_action_to_opcode_entry 17186 * Purpose: 17187 * Convert endpoint action to opcode profile entry action 17188 * Parameters: 17189 * unit - (IN) BCM device number 17190 * action - (IN) Pointer to endpoint action 17191 * ep_id - (IN) Endpoint id 17192 * profile - (IN) Opcode profile table entry 17193 * Returns: 17194 * BCM_E_XXX 17195 */ 17196 int 17197 _bcm_kt2_oam_convert_action_to_opcode_entry(int unit, 17198 bcm_oam_endpoint_action_t *action, 17199 bcm_oam_endpoint_t ep_id, 17200 void *profile, 17201 uint8 *opcode_profile_changed) 17202 { 17203 int rv = BCM_E_NONE; 17204 int action_i = 0; 17205 int opcode_i = 0; 17206 int break_the_loop = 0; 17207 int profile_index = _BCM_OAM_INVALID_INDEX; 17208 int olp_enable = 0; 17209 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 17210 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 17211 soc_mem_t mem = OAM_OPCODE_CONTROL_PROFILEm; 17212 soc_mem_t ma_index_mem = MA_INDEXm; 17213 int dglp_ptr = 0; 17214 int skip_ma_index_modify = 0; 17215 int value = 0; 17216 bcm_module_t module_id; 17217 bcm_port_t port_id; 17218 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 17219 int local_id; 17220 uint32 dglp = 0; 17221 int reset = 0; 17222 17223 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 17224 17225 h_data_p = &oc->oam_hash_data[ep_id]; 17226 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 17227 ma_index_mem = EGR_MA_INDEXm; 17228 mem = EGR_OAM_OPCODE_CONTROL_PROFILEm; 17229 } 17230 17231 reset = (action->flags & BCM_OAM_ENDPOINT_ACTION_DISABLE) ? 1 : 0; 17232 17233 for (action_i = 0; action_i < bcmOAMActionCount; action_i++) { 17234 if (BCM_OAM_ACTION_GET(*action, action_i)) { 17235 for (opcode_i = 0; opcode_i <= _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST; 17236 opcode_i++) { 17237 if (BCM_OAM_OPCODE_GET(*action, opcode_i)) { 17238 switch (action_i) { 17239 case bcmOAMActionCountEnable: 17240 rv = _kt2_oam_counter_control_set(unit, opcode_i, 17241 !reset); 17242 if (BCM_FAILURE(rv)) { 17243 LOG_ERROR(BSL_LS_BCM_OAM, 17244 (BSL_META_U(unit, 17245 "OAM Error:Counter control " 17246 "set - %s.\n"), bcm_errmsg(rv))); 17247 return (rv); 17248 } 17249 break; 17250 17251 case bcmOAMActionDrop: 17252 case bcmOAMActionUcDrop: 17253 case bcmOAMActionMcDrop: 17254 case bcmOAMActionLowMdlDrop: 17255 case bcmOAMActionMyStationMissDrop: 17256 if ((action_i == bcmOAMActionLowMdlDrop) && 17257 (opcode_i == _BCM_OAM_OPCODE_TYPE_CCM)) { 17258 value = reset ? 0 : _BCM_OAM_LOW_MDL_DROP_PACKET; 17259 } else { 17260 value = !reset; 17261 } 17262 rv = _kt2_oam_opcode_control_field_set(unit, 17263 action_i, mem, opcode_i, 17264 value, profile); 17265 *opcode_profile_changed = 1; 17266 break; 17267 17268 case bcmOAMActionCopyToCpu: 17269 case bcmOAMActionUcCopyToCpu: 17270 case bcmOAMActionMcCopyToCpu: 17271 case bcmOAMActionLowMdlCopyToCpu: 17272 case bcmOAMActionMyStationMissCopyToCpu: 17273 rv = _kt2_oam_opcode_control_field_set(unit, 17274 action_i, mem, opcode_i, 17275 !reset, profile); 17276 *opcode_profile_changed = 1; 17277 break; 17278 17279 case bcmOAMActionFwdAsData: 17280 if (opcode_i == _BCM_OAM_OPCODE_TYPE_CCM) { 17281 /* Need not check reset in this case 17282 * since this is default case 17283 */ 17284 soc_mem_field32_set(unit, mem, profile, 17285 LOW_MDL_CCM_FWD_ACTIONf, 0); 17286 break_the_loop = 1; 17287 } 17288 *opcode_profile_changed = 1; 17289 break; 17290 17291 case bcmOAMActionFwd: 17292 case bcmOAMActionUcFwd: 17293 case bcmOAMActionMcFwd: 17294 case bcmOAMActionLowMdlFwd: 17295 case bcmOAMActionMyStationMissFwd: 17296 /* forward packets to DGLP1 or DGLP2 */ 17297 if (!skip_ma_index_modify) { 17298 SOC_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, 17299 action->destination, &module_id, 17300 &port_id, &trunk_id, &local_id)); 17301 if (BCM_GPORT_IS_TRUNK(action->destination) && 17302 (trunk_id != BCM_TRUNK_INVALID)) { 17303 /* Set LAG ID indicator bit */ 17304 dglp |= (1 << DGLP_LAG_ID_INDICATOR_SHIFT_BITS); 17305 } 17306 dglp |= ((module_id << DGLP_MODULE_ID_SHIFT_BITS) + port_id); 17307 17308 if (dglp == h_data_p->dglp1) { 17309 skip_ma_index_modify = 1; 17310 dglp_ptr = _BCM_OAM_DGLP1_PROFILE_PTR; 17311 } else if (dglp == h_data_p->dglp2) { 17312 skip_ma_index_modify = 1; 17313 dglp_ptr = _BCM_OAM_DGLP2_PROFILE_PTR; 17314 /* if both dglp1 and dglp2 are already set, 17315 return error */ 17316 } else if ((h_data_p->dglp1 > 0) && 17317 (h_data_p->dglp2 > 0)) { 17318 LOG_ERROR(BSL_LS_BCM_OAM, 17319 (BSL_META_U(unit, 17320 "OAM Error: Invalid action" 17321 "destination - %s.\n"), bcm_errmsg(rv))); 17322 return BCM_E_PARAM; 17323 } 17324 if (!skip_ma_index_modify) { 17325 rv = _bcm_kt2_oam_resolve_dglp(unit, mem, 17326 dglp, (uint32 *)&profile_index, 17327 &olp_enable); 17328 if (BCM_FAILURE(rv)) { 17329 LOG_ERROR(BSL_LS_BCM_OAM, 17330 (BSL_META_U(unit, 17331 "OAM Error: Gport " 17332 "to dglp-%s\n"), bcm_errmsg(rv))); 17333 return (rv); 17334 } 17335 if (profile_index != _BCM_OAM_INVALID_INDEX) { 17336 /* modify MA_INDEX table entry */ 17337 rv = _bcm_kt2_ma_index_entry_modify(unit, 17338 h_data_p->local_rx_index, 17339 ma_index_mem, profile_index, 17340 olp_enable, &dglp_ptr); 17341 if (BCM_FAILURE(rv)) { 17342 return rv; 17343 } 17344 if (dglp_ptr == 17345 _BCM_OAM_DGLP1_PROFILE_PTR) { 17346 h_data_p->dglp1 = dglp; 17347 h_data_p->dglp1_profile_index = 17348 profile_index; 17349 } else { 17350 h_data_p->dglp2 = dglp; 17351 h_data_p->dglp2_profile_index = 17352 profile_index; 17353 } 17354 skip_ma_index_modify = 1; 17355 } 17356 } 17357 } 17358 if (dglp_ptr == 0) { 17359 break; 17360 } 17361 /* Opcode control value is to bet set to 2 for 17362 DGLP1 and 3 for DGLP2 */ 17363 if (((opcode_i == _BCM_OAM_OPCODE_TYPE_LBM) && 17364 (action_i != bcmOAMActionMcFwd)) || 17365 (opcode_i >= _BCM_OAM_OPCODE_TYPE_NON_CFM_FIRST)) { 17366 value = dglp_ptr + 1; 17367 } else { 17368 value = dglp_ptr; 17369 } 17370 _kt2_oam_opcode_control_field_set(unit, action_i, 17371 mem, opcode_i, value, profile); 17372 *opcode_profile_changed = 1; 17373 break; 17374 17375 case bcmOAMActionUcFwdAsData: 17376 case bcmOAMActionMcFwdAsData: 17377 case bcmOAMActionLowMdlFwdAsData: 17378 case bcmOAMActionMyStationMissFwdAsData: 17379 /* Need not check reset in this case 17380 * since this is default case 17381 */ 17382 rv = _kt2_oam_opcode_control_field_set(unit, 17383 action_i, mem, opcode_i, 17384 _BCM_OAM_FWD_AS_DATA, profile); 17385 *opcode_profile_changed = 1; 17386 break; 17387 17388 case bcmOAMActionProcessInHw: 17389 if (opcode_i == _BCM_OAM_OPCODE_TYPE_CCM) { 17390 soc_mem_field32_set(unit, mem, profile, 17391 CCM_PROCESS_IN_HWf, !reset); 17392 } else if (opcode_i == _BCM_OAM_OPCODE_TYPE_LBM) { 17393 soc_mem_field32_set(unit, mem, profile, 17394 LBM_ACTIONf, !reset); 17395 } 17396 break_the_loop = 1; 17397 /* TBD - When CCM processing is done in HW, MA_PTR 17398 value in MA_INDEX table should be less than 2k. 17399 If not, we should return error */ 17400 *opcode_profile_changed = 1; 17401 break; 17402 17403 case bcmOAMActionLowMdlCcmFwdAsRegularCcm: 17404 if (opcode_i == _BCM_OAM_OPCODE_TYPE_CCM) { 17405 soc_mem_field32_set(unit, mem, profile, 17406 LOW_MDL_CCM_FWD_ACTIONf, !reset); 17407 break_the_loop = 1; 17408 } 17409 *opcode_profile_changed = 1; 17410 break; 17411 17412 default: 17413 break; 17414 } 17415 } 17416 if (break_the_loop) { 17417 dglp_ptr = 0; 17418 break_the_loop = 0; 17419 olp_enable = 0; 17420 profile_index = _BCM_OAM_INVALID_INDEX; 17421 break; 17422 } 17423 } 17424 } 17425 } 17426 return rv; 17427 } 17428 17429 /* 17430 * Function: 17431 * _bcm_kt2_oam_flex_drop_get 17432 * Purpose: 17433 * Query the value of the device-wide OAM control. 17434 * Parameters: 17435 * unit - (IN) BCM device number 17436 * type - (IN) OAM control type 17437 * arg - (OUT) A pointer to value of the control 17438 * Returns: 17439 * BCM_E_XXX 17440 */ 17441 int _bcm_kt2_oam_flex_drop_get(int unit, bcm_oam_control_type_t type, 17442 uint64 *arg) 17443 { 17444 uint32 rval_32; 17445 soc_reg_t reg = 0; 17446 uint32 is_64bit_reg = 0; 17447 int rv = BCM_E_NONE; 17448 17449 switch(type) { 17450 case bcmOamControlFlexibleDropPort: 17451 reg = OAM_PORT_INTERFACE_DROP_CONTROLr; 17452 break; 17453 17454 case bcmOamControlFlexibleDropCVlan: 17455 reg = OAM_C_INTERFACE_DROP_CONTROLr; 17456 break; 17457 17458 case bcmOamControlFlexibleDropSVlan: 17459 reg = OAM_S_INTERFACE_DROP_CONTROLr; 17460 break; 17461 17462 case bcmOamControlFlexibleDropCPlusSVlan: 17463 reg = OAM_S_C_INTERFACE_DROP_CONTROLr; 17464 break; 17465 17466 case bcmOamControlFlexibleDropVP: 17467 reg = OAM_SVP_INTERFACE_DROP_CONTROLr; 17468 break; 17469 17470 case bcmOamControlFlexibleDropEgressPort: 17471 reg = EGR_OAM_PORT_INTERFACE_DROP_CONTROL_64r; 17472 is_64bit_reg = 1; 17473 break; 17474 17475 case bcmOamControlFlexibleDropEgressCVlan: 17476 reg = EGR_OAM_C_INTERFACE_DROP_CONTROL_64r; 17477 is_64bit_reg = 1; 17478 break; 17479 17480 case bcmOamControlFlexibleDropEgressSVlan: 17481 reg = EGR_OAM_S_INTERFACE_DROP_CONTROL_64r; 17482 is_64bit_reg = 1; 17483 break; 17484 17485 case bcmOamControlFlexibleDropEgressCPlusSVlan: 17486 reg = EGR_OAM_S_C_INTERFACE_DROP_CONTROL_64r; 17487 is_64bit_reg = 1; 17488 break; 17489 17490 case bcmOamControlFlexibleDropEgressVP: 17491 reg = EGR_OAM_DVP_INTERFACE_DROP_CONTROL_64r; 17492 is_64bit_reg = 1; 17493 break; 17494 17495 case bcmOamControlFlexibleDropPasssiveSap: 17496 reg = OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 17497 break; 17498 17499 case bcmOamControlFlexibleDropEgressPasssiveSap: 17500 reg = EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 17501 break; 17502 17503 default: 17504 return (BCM_E_UNAVAIL); 17505 break; 17506 } 17507 if (is_64bit_reg == 0) { 17508 rv = soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval_32); 17509 if(BCM_SUCCESS(rv)) { 17510 COMPILER_64_SET(*arg, 0, rval_32); 17511 } 17512 } else { 17513 rv = soc_reg64_get(unit, reg, REG_PORT_ANY, 0, arg); 17514 } 17515 return rv; 17516 } 17517 17518 /* 17519 * Function: 17520 * _bcm_kt2_oam_flex_drop_get 17521 * Purpose: 17522 * Query the value of the device-wide OAM control. 17523 * Parameters: 17524 * unit - (IN) BCM device number 17525 * type - (IN) OAM control type 17526 * arg - (IN) value to be set for the control 17527 * Returns: 17528 * BCM_E_XXX 17529 */ 17530 int _bcm_kt2_oam_flex_drop_set(int unit, bcm_oam_control_type_t type, 17531 uint64 arg) 17532 { 17533 uint32 rval_32; 17534 soc_reg_t reg = 0; 17535 uint32 is_64bit_reg = 0; 17536 int rv = BCM_E_NONE; 17537 17538 switch(type) { 17539 case bcmOamControlFlexibleDropPort: 17540 reg = OAM_PORT_INTERFACE_DROP_CONTROLr; 17541 break; 17542 17543 case bcmOamControlFlexibleDropCVlan: 17544 reg = OAM_C_INTERFACE_DROP_CONTROLr; 17545 break; 17546 17547 case bcmOamControlFlexibleDropSVlan: 17548 reg = OAM_S_INTERFACE_DROP_CONTROLr; 17549 break; 17550 17551 case bcmOamControlFlexibleDropCPlusSVlan: 17552 reg = OAM_S_C_INTERFACE_DROP_CONTROLr; 17553 break; 17554 17555 case bcmOamControlFlexibleDropVP: 17556 reg = OAM_SVP_INTERFACE_DROP_CONTROLr; 17557 break; 17558 17559 case bcmOamControlFlexibleDropEgressPort: 17560 reg = EGR_OAM_PORT_INTERFACE_DROP_CONTROL_64r; 17561 is_64bit_reg = 1; 17562 break; 17563 17564 case bcmOamControlFlexibleDropEgressCVlan: 17565 reg = EGR_OAM_C_INTERFACE_DROP_CONTROL_64r; 17566 is_64bit_reg = 1; 17567 break; 17568 17569 case bcmOamControlFlexibleDropEgressSVlan: 17570 reg = EGR_OAM_S_INTERFACE_DROP_CONTROL_64r; 17571 is_64bit_reg = 1; 17572 break; 17573 17574 case bcmOamControlFlexibleDropEgressCPlusSVlan: 17575 reg = EGR_OAM_S_C_INTERFACE_DROP_CONTROL_64r; 17576 is_64bit_reg = 1; 17577 break; 17578 17579 case bcmOamControlFlexibleDropEgressVP: 17580 reg = EGR_OAM_DVP_INTERFACE_DROP_CONTROL_64r; 17581 is_64bit_reg = 1; 17582 break; 17583 17584 case bcmOamControlFlexibleDropPasssiveSap: 17585 reg = OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 17586 break; 17587 17588 case bcmOamControlFlexibleDropEgressPasssiveSap: 17589 reg = EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 17590 break; 17591 17592 default: 17593 return (BCM_E_UNAVAIL); 17594 break; 17595 } 17596 if (is_64bit_reg == 0) { 17597 COMPILER_64_TO_32_LO(rval_32, arg); 17598 rv = soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval_32); 17599 } else { 17600 rv = soc_reg64_set(unit, reg, REG_PORT_ANY, 0, arg); 17601 } 17602 return rv; 17603 } 17604 /* 17605 * Function: 17606 * bcm_kt2_oam_control_get 17607 * Purpose: 17608 * Query the value of the device-wide OAM control. 17609 * Parameters: 17610 * unit - (IN) BCM device number 17611 * type - (IN) OAM control type 17612 * arg - (OUT) A pointer to value of the control 17613 * Returns: 17614 * BCM_E_XXX 17615 */ 17616 int bcm_kt2_oam_control_get(int unit, bcm_oam_control_type_t type, 17617 uint64 *arg) 17618 { 17619 int rv = BCM_E_NONE; 17620 17621 switch(type) { 17622 case bcmOamControlFlexibleDropPort: 17623 case bcmOamControlFlexibleDropCVlan: 17624 case bcmOamControlFlexibleDropSVlan: 17625 case bcmOamControlFlexibleDropCPlusSVlan: 17626 case bcmOamControlFlexibleDropVP: 17627 case bcmOamControlFlexibleDropEgressPort: 17628 case bcmOamControlFlexibleDropEgressCVlan: 17629 case bcmOamControlFlexibleDropEgressSVlan: 17630 case bcmOamControlFlexibleDropEgressCPlusSVlan: 17631 case bcmOamControlFlexibleDropEgressVP: 17632 case bcmOamControlFlexibleDropPasssiveSap: 17633 case bcmOamControlFlexibleDropEgressPasssiveSap: 17634 rv = _bcm_kt2_oam_flex_drop_get(unit, type, arg); 17635 break; 17636 default: 17637 rv = BCM_E_UNAVAIL; 17638 break; 17639 } 17640 return rv; 17641 } 17642 17643 /* 17644 * Function: 17645 * bcm_kt2_oam_control_set 17646 * Purpose: 17647 * Set the value of the device-wide OAM control. 17648 * Parameters: 17649 * unit - (IN) BCM device number 17650 * type - (IN) OAM control type 17651 * arg - (IN) value to be set for control 17652 * Returns: 17653 * BCM_E_XXX 17654 */ 17655 int bcm_kt2_oam_control_set(int unit, bcm_oam_control_type_t type, 17656 uint64 arg) 17657 { 17658 int rv = BCM_E_NONE; 17659 switch(type) { 17660 case bcmOamControlFlexibleDropPort: 17661 case bcmOamControlFlexibleDropCVlan: 17662 case bcmOamControlFlexibleDropSVlan: 17663 case bcmOamControlFlexibleDropCPlusSVlan: 17664 case bcmOamControlFlexibleDropVP: 17665 case bcmOamControlFlexibleDropEgressPort: 17666 case bcmOamControlFlexibleDropEgressCVlan: 17667 case bcmOamControlFlexibleDropEgressSVlan: 17668 case bcmOamControlFlexibleDropEgressCPlusSVlan: 17669 case bcmOamControlFlexibleDropEgressVP: 17670 case bcmOamControlFlexibleDropPasssiveSap: 17671 case bcmOamControlFlexibleDropEgressPasssiveSap: 17672 rv = _bcm_kt2_oam_flex_drop_set(unit, type, arg); 17673 break; 17674 default: 17675 rv = BCM_E_UNAVAIL; 17676 break; 17677 } 17678 return rv; 17679 } 17680 17681 /* 17682 * Function: 17683 * bcm_kt2_oam_upmep_cosq_set 17684 * Purpose: 17685 * Set the value of the device-wide UP MEP PDU type CPU queue. 17686 * Parameters: 17687 * unit - (IN) BCM device number 17688 * upmep_pdu_type - (IN) UP MEP PDU type 17689 * cosq - (IN) value to be set for CPU queue 17690 * Returns: 17691 * BCM_E_XXX 17692 */ 17693 int bcm_kt2_oam_upmep_cosq_set(int unit, bcm_oam_upmep_pdu_type_t upmep_pdu_type, 17694 bcm_cos_queue_t cosq) 17695 { 17696 int rv = BCM_E_NONE; 17697 uint64 cpu_control_2_64; 17698 uint64 write_val; 17699 17700 SOC_IF_ERROR_RETURN( 17701 READ_EGR_CPU_CONTROL_2_64r(unit, &cpu_control_2_64)); 17702 switch(upmep_pdu_type) { 17703 case bcmOamUpmepPduTypeCcm: 17704 COMPILER_64_SET(write_val, 0, cosq); 17705 soc_reg64_field_set(unit, EGR_CPU_CONTROL_2_64r, &cpu_control_2_64, 17706 OAM_CCM_SLOWPATH_CPU_COSf, write_val); 17707 break; 17708 case bcmOamUpmepPduTypeLmDm: 17709 COMPILER_64_SET(write_val, 0, cosq); 17710 soc_reg64_field_set(unit, EGR_CPU_CONTROL_2_64r, &cpu_control_2_64, 17711 OAM_LMDM_CPU_COSf, write_val); 17712 break; 17713 case bcmOamUpmepPduTypeSlowpath: 17714 COMPILER_64_SET(write_val, 0, cosq); 17715 soc_reg64_field_set(unit, EGR_CPU_CONTROL_2_64r, &cpu_control_2_64, 17716 OAM_SLOWPATH_CPU_COSf, write_val); 17717 break; 17718 case bcmOamUpmepPduTypeCount : 17719 rv = BCM_E_PARAM; 17720 break; 17721 default: 17722 rv = BCM_E_UNAVAIL; 17723 break; 17724 } 17725 if (rv == BCM_E_NONE) { 17726 SOC_IF_ERROR_RETURN( 17727 WRITE_EGR_CPU_CONTROL_2_64r(unit, cpu_control_2_64)); 17728 } 17729 return rv; 17730 } 17731 17732 /* 17733 * Function: 17734 * bcm_kt2_oam_upmep_cosq_get 17735 * Purpose: 17736 * Query the value of the device-wide UP MEP PDU type CPU queue. 17737 * Parameters: 17738 * unit - (IN) BCM device number 17739 * upmep_pdu_type - (IN) UP MEP PDU type 17740 * cosq - (OUT) pointer to CPU queue to be get 17741 * Returns: 17742 * BCM_E_XXX 17743 */ 17744 int bcm_kt2_oam_upmep_cosq_get(int unit, bcm_oam_upmep_pdu_type_t upmep_pdu_type, 17745 bcm_cos_queue_t *cosq) 17746 { 17747 int rv = BCM_E_NONE; 17748 uint64 cpu_control_2_64; 17749 17750 SOC_IF_ERROR_RETURN( 17751 READ_EGR_CPU_CONTROL_2_64r(unit, &cpu_control_2_64)); 17752 switch(upmep_pdu_type) { 17753 case bcmOamUpmepPduTypeCcm: 17754 *cosq = soc_reg64_field32_get(unit, EGR_CPU_CONTROL_2_64r, 17755 cpu_control_2_64, OAM_CCM_SLOWPATH_CPU_COSf); 17756 break; 17757 case bcmOamUpmepPduTypeLmDm: 17758 *cosq = soc_reg64_field32_get(unit, EGR_CPU_CONTROL_2_64r, 17759 cpu_control_2_64, OAM_LMDM_CPU_COSf); 17760 break; 17761 case bcmOamUpmepPduTypeSlowpath: 17762 *cosq = soc_reg64_field32_get(unit, EGR_CPU_CONTROL_2_64r, 17763 cpu_control_2_64, OAM_SLOWPATH_CPU_COSf); 17764 break; 17765 case bcmOamUpmepPduTypeCount : 17766 rv = BCM_E_PARAM; 17767 break; 17768 default: 17769 rv = BCM_E_UNAVAIL; 17770 break; 17771 } 17772 return rv; 17773 } 17774 17775 #if defined(INCLUDE_BHH) 17776 /* 17777 * Function: 17778 * bcm_kt2_oam_mpls_tp_channel_type_tx_get 17779 * Purpose: 17780 * Get MPLS TP(BHH) ACH Channel type 17781 * Parameters: 17782 * unit (IN) BCM device number 17783 * channel_type (IN) Channel type is ignored in XGS devices 17784 * Value (OUT) User define MPLS TP(BHH) ACH channel type 17785 * 17786 * Returns: 17787 * BCM_E_NONE No error 17788 * BCM_E_XXXX Error 17789 */ 17790 int 17791 bcm_kt2_oam_mpls_tp_channel_type_tx_get(int unit, 17792 bcm_oam_mpls_tp_channel_type_t channel_type, 17793 int *value) 17794 { 17795 *value = kt2_oam_mpls_tp_ach_channel_type; 17796 return BCM_E_NONE; 17797 } 17798 17799 /* 17800 * Function: 17801 * bcm_kt2_oam_mpls_tp_channel_type_tx_set 17802 * Purpose: 17803 * Update MPLS TP(BHH) ACH Channel type with user defined value 17804 * Parameters: 17805 * unit (IN) BCM device number 17806 * channel_type (IN) Channel type is ignored in XGS devices 17807 * Value (IN) User define MPLS TP(BHH) ACH channel type 17808 * 17809 * Returns: 17810 * BCM_E_NONE No error 17811 * BCM_E_XXXX Error 17812 */ 17813 int 17814 bcm_kt2_oam_mpls_tp_channel_type_tx_set(int unit, 17815 bcm_oam_mpls_tp_channel_type_t channel_type, 17816 int value) 17817 { 17818 uint8 *buffer, *buffer_ptr; 17819 uint16 buffer_len, reply_len; 17820 int rv = BCM_E_NONE; 17821 uint32 *msg; 17822 _bcm_oam_control_t *oc; /* OAM control structure. */ 17823 17824 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 17825 _BCM_OAM_LOCK(oc); 17826 17827 if (oc->ukernel_not_ready) { 17828 _BCM_OAM_UNLOCK(oc); 17829 return BCM_E_INIT; 17830 } 17831 17832 if ((value != SHR_BHH_ACH_CHANNEL_TYPE) && 17833 (value != SHR_BHH_ACH_CHANNEL_TYPE_1)) { 17834 _BCM_OAM_UNLOCK(oc); 17835 return BCM_E_CONFIG; 17836 } 17837 17838 kt2_oam_mpls_tp_ach_channel_type = value; 17839 msg = (uint32 *)&kt2_oam_mpls_tp_ach_channel_type; 17840 17841 /* Set BHH ACH Type in BHH_RX_ACH_TYPE register */ 17842 rv = WRITE_BHH_RX_ACH_TYPEr(unit, kt2_oam_mpls_tp_ach_channel_type); 17843 17844 /* Pack control message data into DMA buffer */ 17845 buffer = oc->dma_buffer; 17846 buffer_ptr = bhh_sdk_msg_ctrl_ach_channel_type_msg_pack(buffer, msg); 17847 buffer_len = buffer_ptr - buffer; 17848 17849 rv = _bcm_kt2_oam_bhh_msg_send_receive( 17850 unit, 17851 MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE, 17852 buffer_len, 0, 17853 MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE_REPLY, 17854 &reply_len); 17855 17856 if (BCM_FAILURE(rv)) { 17857 _BCM_OAM_UNLOCK(oc); 17858 return (rv); 17859 } 17860 17861 _BCM_OAM_UNLOCK(oc); 17862 return BCM_E_NONE; 17863 } 17864 17865 /* 17866 * Function: 17867 * _bcm_kt2_oam_bhh_encap_hw_set 17868 * Purpose: 17869 * Sets BHH encapsulation type in HW device. 17870 * Parameters: 17871 * unit - (IN) Unit number. 17872 * module_id - (IN) Module id. 17873 * port_id - (IN) Port. 17874 * is_local - (IN) Indicates if module id is local. 17875 * endpoint_config - (IN) Pointer to BHH endpoint structure. 17876 * Returns: 17877 * BCM_E_XXX 17878 * Notes: 17879 */ 17880 STATIC int 17881 _bcm_kt2_oam_bhh_encap_hw_set(int unit, _bcm_oam_hash_data_t *h_data_p, 17882 bcm_module_t module_id, bcm_port_t port_id, 17883 int is_local, bcm_oam_endpoint_info_t *endpoint_info) 17884 { 17885 int rv = BCM_E_NONE; 17886 #if defined(BCM_KATANA2_SUPPORT) && defined(BCM_MPLS_SUPPORT) 17887 bcm_l3_egress_t l3_egress; 17888 int ingress_if; 17889 int i; 17890 int num_entries; 17891 mpls_entry_entry_t mpls_entry; 17892 mpls_entry_entry_t mpls_key; 17893 int vccv_type = 0; 17894 int mpls_index = 0; 17895 #endif /* BCM_KATANA2_SUPPORT && BCM_MPLS_SUPPORT */ 17896 17897 switch(h_data_p->type) { 17898 case bcmOAMEndpointTypeBHHMPLS: 17899 case bcmOAMEndpointTypeBHHMPLSVccv: 17900 17901 #if defined(BCM_KATANA2_SUPPORT) && defined(BCM_MPLS_SUPPORT) 17902 SOC_IF_ERROR_RETURN(bcm_tr_mpls_lock (unit)); 17903 17904 sal_memset(&mpls_key, 0, sizeof(mpls_key)); 17905 soc_MPLS_ENTRYm_field32_set(unit, &mpls_key, MPLS__MPLS_LABELf, 17906 h_data_p->label); 17907 17908 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &mpls_index, 17909 &mpls_key, &mpls_entry, 0); 17910 if (SOC_FAILURE(rv)) { 17911 bcm_tr_mpls_unlock (unit); 17912 return rv; 17913 } 17914 17915 if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, 17916 VALIDf) != 0x1)) { 17917 bcm_tr_mpls_unlock (unit); 17918 return (BCM_E_PARAM); 17919 } 17920 17921 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 17922 /* Get the control channel type */ 17923 vccv_type = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, 17924 MPLS__PW_CC_TYPEf); 17925 17926 if (vccv_type == 0) { /* No VCCV type configured */ 17927 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, 17928 MPLS__PW_CC_TYPEf, 17929 (h_data_p->vccv_type + 1)); 17930 17931 } else if (vccv_type != (h_data_p->vccv_type + 1)) { 17932 /* Endpoint add configuration conflicts with MPLS port add config */ 17933 bcm_tr_mpls_unlock(unit); 17934 return BCM_E_PARAM; 17935 } 17936 17937 } 17938 17939 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, 17940 MPLS__SESSION_IDENTIFIER_TYPEf, 1); 17941 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, MPLS__BHH_ENABLEf, 1); 17942 rv = soc_mem_write(unit, MPLS_ENTRYm, 17943 MEM_BLOCK_ANY, mpls_index, 17944 &mpls_entry); 17945 if (rv != SOC_E_NONE) { 17946 bcm_tr_mpls_unlock(unit); 17947 return rv; 17948 } 17949 17950 /* 17951 * PW CC-3 17952 * 17953 * Set MPLS entry DECAP_USE_TTL=0 for corresponding 17954 * Tunnel Terminator label. 17955 */ 17956 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 17957 if (h_data_p->vccv_type == bcmOamBhhVccvTtl) { 17958 rv = bcm_esw_l3_egress_get(unit, h_data_p->egress_if, 17959 &l3_egress); 17960 if (rv != BCM_E_NONE) { 17961 bcm_tr_mpls_unlock(unit); 17962 return rv; 17963 } 17964 17965 /* Look for Tunnel Terminator label */ 17966 num_entries = soc_mem_index_count(unit, MPLS_ENTRYm); 17967 for (i = 0; i < num_entries; i++) { 17968 rv = READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, i, &mpls_entry); 17969 if (rv != SOC_E_NONE) { 17970 bcm_tr_mpls_unlock(unit); 17971 return rv; 17972 } 17973 17974 if (!soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf)) { 17975 continue; 17976 } 17977 if (soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, 17978 MPLS__MPLS_ACTION_IF_BOSf) == 0x1) { 17979 continue; /* L2_SVP */ 17980 } 17981 17982 ingress_if = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, 17983 MPLS__L3_IIFf); 17984 if (ingress_if == l3_egress.intf) { 17985 /* Label found */ 17986 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, 17987 MPLS__DECAP_USE_TTLf, 0); 17988 rv = soc_mem_write(unit, MPLS_ENTRYm, 17989 MEM_BLOCK_ALL, i, 17990 &mpls_entry); 17991 if (rv != SOC_E_NONE) { 17992 bcm_tr_mpls_unlock(unit); 17993 return rv; 17994 } 17995 break; 17996 } 17997 } 17998 } 17999 } 18000 bcm_tr_mpls_unlock (unit); 18001 #else 18002 rv = BCM_E_UNAVAIL; 18003 #endif /* BCM_KATANA2_SUPPORT && BCM_MPLS_SUPPORT */ 18004 18005 break; 18006 18007 default: 18008 rv = BCM_E_UNAVAIL; 18009 break; 18010 } 18011 18012 return (rv); 18013 } 18014 18015 /* 18016 * Function: 18017 * _bcm_kt2_oam_bhh_encap_data_dump 18018 * Purpose: 18019 * Dumps buffer contents. 18020 * Parameters: 18021 * buffer - (IN) Buffer to dump data. 18022 * length - (IN) Length of buffer. 18023 * Returns: 18024 * None 18025 */ 18026 void 18027 _bcm_kt2_oam_bhh_encap_data_dump(uint8 *buffer, int length) 18028 { 18029 int i; 18030 18031 LOG_CLI((BSL_META("\nBHH encapsulation (length=%d):\n"), length)); 18032 18033 for (i = 0; i < length; i++) { 18034 if ((i % 16) == 0) { 18035 LOG_CLI((BSL_META("\n"))); 18036 } 18037 LOG_CLI((BSL_META(" %02x"), buffer[i])); 18038 } 18039 18040 LOG_CLI((BSL_META("\n"))); 18041 return; 18042 } 18043 18044 STATIC int 18045 _bcm_kt2_oam_bhh_ach_header_get(uint32 packet_flags, _ach_header_t *ach) 18046 { 18047 sal_memset(ach, 0, sizeof(*ach)); 18048 18049 ach->f_nibble = SHR_BHH_ACH_FIRST_NIBBLE; 18050 ach->version = SHR_BHH_ACH_VERSION; 18051 ach->reserved = 0; 18052 18053 ach->channel_type = kt2_oam_mpls_tp_ach_channel_type; 18054 18055 return (BCM_E_NONE); 18056 } 18057 18058 STATIC int 18059 _bcm_kt2_oam_bhh_mpls_label_get(uint32 label, uint8 exp, uint8 s, uint8 ttl, 18060 _mpls_label_t *mpls) 18061 { 18062 sal_memset(mpls, 0, sizeof(*mpls)); 18063 18064 mpls->label = label; 18065 mpls->exp = exp & 0x07; 18066 mpls->s = s; 18067 if(ttl) 18068 mpls->ttl = ttl; 18069 else 18070 mpls->ttl = _BHH_MPLS_DFLT_TTL; 18071 18072 return (BCM_E_NONE); 18073 } 18074 18075 STATIC int 18076 _bcm_kt2_oam_bhh_mpls_gal_label_get(_mpls_label_t *mpls, uint8 oam_exp) 18077 { 18078 return _bcm_kt2_oam_bhh_mpls_label_get(SHR_BHH_MPLS_GAL_LABEL, 18079 oam_exp, 1, 1, mpls); 18080 } 18081 18082 STATIC int 18083 _bcm_kt2_oam_bhh_mpls_labels_get(int unit, _bcm_oam_hash_data_t *h_data_p, 18084 uint32 packet_flags, 18085 int max_count, 18086 _mpls_label_t *pw_label, 18087 _mpls_label_t *mpls, 18088 int *mpls_count, bcm_if_t *l3_intf_id) 18089 { 18090 int count = 0; 18091 bcm_l3_egress_t l3_egress; 18092 bcm_mpls_port_t mpls_port; 18093 bcm_mpls_egress_label_t label_array[_BHH_MPLS_MAX_LABELS]; 18094 bcm_mpls_egress_label_t tmp_label; 18095 int label_count; 18096 int i = 0; 18097 18098 /* Get L3 objects */ 18099 bcm_l3_egress_t_init(&l3_egress); 18100 if (BCM_FAILURE(bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) { 18101 return (BCM_E_PARAM); 18102 } 18103 18104 /* Look for a tunnel associated with this interface */ 18105 if (BCM_SUCCESS 18106 (bcm_esw_mpls_tunnel_initiator_get(unit, l3_egress.intf, 18107 _BHH_MPLS_MAX_LABELS, 18108 label_array, &label_count))) { 18109 /* We need to swap the labels configured in tunnel initiator as 18110 * it returns labels in reverse order than how it should be in pkt. 18111 */ 18112 for (i = 0; i < (label_count / 2); i++) { 18113 sal_memcpy(&tmp_label, &label_array[i], sizeof(tmp_label)); 18114 sal_memcpy(&label_array[i], &label_array[label_count - 1 - i], 18115 sizeof(tmp_label)); 18116 sal_memcpy(&label_array[label_count - 1 - i], &tmp_label, 18117 sizeof(tmp_label)); 18118 } 18119 18120 /* Add VRL Label */ 18121 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS) { 18122 if ((l3_egress.mpls_label != BCM_MPLS_LABEL_INVALID) && 18123 (h_data_p->egr_label != BCM_MPLS_LABEL_INVALID) && 18124 (label_count < _BHH_MPLS_MAX_LABELS) ) { 18125 18126 label_array[label_count].label = l3_egress.mpls_label; 18127 label_array[label_count].exp = l3_egress.mpls_exp; 18128 label_array[label_count].ttl = l3_egress.mpls_ttl; 18129 label_count++; 18130 } 18131 /* Traverse through Label stack and match on control label, this 18132 * label should be the one just above GAL in the label stack, any 18133 * following labels should not be added. 18134 */ 18135 for (i = 0; i < label_count; i++) { 18136 if (label_array[i].label == h_data_p->egr_label) { 18137 label_count = i + 1; 18138 label_array[i].exp = h_data_p->egr_label_exp; 18139 if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) && 18140 h_data_p->egr_label_ttl) { 18141 label_array[i].ttl = h_data_p->egr_label_ttl; 18142 } 18143 break; 18144 } 18145 } 18146 } 18147 } 18148 18149 /* MPLS Router Alert */ 18150 if (packet_flags & _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT) { 18151 /* Ignore overrun error as RAL is only added for PW MEPs and so overrun 18152 * condition will not exist. 18153 */ 18154 /* coverity[overrun-local] */ 18155 label_array[label_count].label = SHR_BHH_MPLS_ROUTER_ALERT_LABEL; 18156 label_array[label_count].exp = 0; 18157 label_array[label_count].ttl = 0; 18158 label_count++; 18159 } 18160 18161 /* Use GPORT to resolve interface */ 18162 if (BCM_GPORT_IS_MPLS_PORT(h_data_p->gport)) { 18163 /* Get mpls port and label info */ 18164 bcm_mpls_port_t_init(&mpls_port); 18165 mpls_port.mpls_port_id = h_data_p->gport; 18166 if (BCM_FAILURE(bcm_esw_mpls_port_get(unit, h_data_p->vpn, 18167 &mpls_port))) { 18168 return (BCM_E_PARAM); 18169 } 18170 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv && 18171 h_data_p->vccv_type == bcmOamBhhVccvTtl) { 18172 mpls_port.egress_label.ttl = 0x1; 18173 } 18174 18175 label_array[label_count].label = mpls_port.egress_label.label; 18176 if (h_data_p->egr_label == mpls_port.egress_label.label) { 18177 label_array[label_count].exp = h_data_p->egr_label_exp; 18178 if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) && 18179 h_data_p->egr_label_ttl) { 18180 label_array[label_count].ttl = h_data_p->egr_label_ttl; 18181 } 18182 } else { 18183 label_array[label_count].exp = mpls_port.egress_label.exp; 18184 label_array[label_count].ttl = mpls_port.egress_label.ttl; 18185 } 18186 label_count++; 18187 } 18188 18189 18190 for (i=0; i < label_count; i++) { 18191 _bcm_kt2_oam_bhh_mpls_label_get(label_array[i].label, 18192 label_array[i].exp, 18193 0, 18194 label_array[i].ttl, 18195 &mpls[count++]); 18196 } 18197 18198 /* Set Bottom of Stack if there is no GAL label */ 18199 if (!(packet_flags & _BHH_ENCAP_PKT_GAL)) { 18200 mpls[count-1].s = 1; 18201 } 18202 18203 *mpls_count = count; 18204 18205 return (BCM_E_NONE); 18206 18207 } 18208 18209 STATIC int 18210 _bcm_kt2_oam_bhh_l2_header_get(int unit, _bcm_oam_hash_data_t *h_data_p, 18211 bcm_port_t port, uint16 etype, 18212 _l2_header_t *l2) 18213 { 18214 uint16 tpid; 18215 bcm_l3_egress_t l3_egress; 18216 bcm_l3_intf_t l3_intf; 18217 bcm_vlan_control_vlan_t vc; 18218 int tpid_select; 18219 bcm_pbmp_t pbmp, ubmp; 18220 18221 sal_memset(l2, 0, sizeof(*l2)); 18222 18223 if (!BHH_EP_MPLS_SECTION_TYPE(h_data_p)) { 18224 /* Get L3 interfaces */ 18225 bcm_l3_egress_t_init(&l3_egress); 18226 bcm_l3_intf_t_init(&l3_intf); 18227 18228 if (BCM_FAILURE 18229 (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) { 18230 return (BCM_E_PARAM); 18231 } 18232 18233 l3_intf.l3a_intf_id = l3_egress.intf; 18234 if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) { 18235 return (BCM_E_PARAM); 18236 } 18237 18238 /* Get TPID */ 18239 BCM_IF_ERROR_RETURN(bcm_esw_vlan_control_port_get(unit, 18240 port, 18241 bcmVlanPortOuterTpidSelect, 18242 &tpid_select)); 18243 if (tpid_select == BCM_PORT_OUTER_TPID) { 18244 BCM_IF_ERROR_RETURN(bcm_esw_port_tpid_get(unit, port, &tpid)); 18245 } else { 18246 BCM_IF_ERROR_RETURN( 18247 bcm_esw_vlan_control_vlan_get(unit, l3_intf.l3a_vid, &vc)); 18248 tpid = vc.outer_tpid; 18249 } 18250 18251 sal_memcpy(l2->dst_mac, l3_egress.mac_addr, _BHH_MAC_ADDR_LENGTH); 18252 sal_memcpy(l2->src_mac, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH); 18253 l2->vlan_tag.tpid = tpid; 18254 l2->vlan_tag.tci.prio = h_data_p->vlan_pri; 18255 l2->vlan_tag.tci.cfi = 0; 18256 l2->vlan_tag.tci.vid = l3_intf.l3a_vid; 18257 18258 BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_get(unit, 18259 l2->vlan_tag.tci.vid, 18260 &pbmp, 18261 &ubmp)); 18262 if (BCM_PBMP_MEMBER(ubmp, port)) { 18263 l2->vlan_tag.tpid = 0; /* Set to 0 to indicate untagged */ 18264 } 18265 18266 if (l3_intf.l3a_inner_vlan != 0) { 18267 BCM_IF_ERROR_RETURN(bcm_esw_port_inner_tpid_get(unit, port, &tpid)); 18268 l2->vlan_tag_inner.tpid = tpid; 18269 l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri; 18270 l2->vlan_tag_inner.tci.cfi = 0; 18271 l2->vlan_tag_inner.tci.vid = l3_intf.l3a_inner_vlan; 18272 } 18273 l2->etype = etype; 18274 } else { 18275 sal_memcpy(l2->dst_mac, h_data_p->dst_mac_address, _BHH_MAC_ADDR_LENGTH); 18276 sal_memcpy(l2->src_mac, h_data_p->src_mac_address, _BHH_MAC_ADDR_LENGTH); 18277 if((h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterVlan) || 18278 (h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan) || 18279 (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)){ 18280 if (h_data_p->vlan != 0) { 18281 l2->vlan_tag.tpid = h_data_p->outer_tpid; 18282 l2->vlan_tag.tci.prio = h_data_p->vlan_pri; 18283 l2->vlan_tag.tci.cfi = 0; 18284 l2->vlan_tag.tci.vid = h_data_p->vlan; 18285 } 18286 } 18287 if((h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan) || 18288 (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)){ 18289 l2->vlan_tag_inner.tpid = h_data_p->inner_tpid; 18290 l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri; 18291 l2->vlan_tag_inner.tci.cfi = 0; 18292 l2->vlan_tag_inner.tci.vid = h_data_p->inner_vlan; 18293 } 18294 l2->etype = SHR_BHH_L2_ETYPE_MPLS_UCAST; 18295 } 18296 return BCM_E_NONE; 18297 } 18298 STATIC uint8 * 18299 _bcm_kt2_oam_bhh_ach_header_pack(uint8 *buffer, _ach_header_t *ach) 18300 { 18301 uint32 tmp; 18302 18303 tmp = ((ach->f_nibble & 0xf) << 28) | ((ach->version & 0xf) << 24) | 18304 (ach->reserved << 16) | ach->channel_type; 18305 18306 _BHH_ENCAP_PACK_U32(buffer, tmp); 18307 18308 return (buffer); 18309 } 18310 18311 STATIC uint8 * 18312 _bcm_kt2_oam_bhh_mpls_label_pack(uint8 *buffer, _mpls_label_t *mpls) 18313 { 18314 uint32 tmp; 18315 18316 tmp = ((mpls->label & 0xfffff) << 12) | ((mpls->exp & 0x7) << 9) | 18317 ((mpls->s & 0x1) << 8) | mpls->ttl; 18318 _BHH_ENCAP_PACK_U32(buffer, tmp); 18319 18320 return (buffer); 18321 } 18322 18323 STATIC uint8 * 18324 _bcm_kt2_oam_bhh_l2_header_pack(uint8 *buffer, _l2_header_t *l2) 18325 { 18326 uint32 tmp; 18327 int i; 18328 18329 for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) { 18330 _BHH_ENCAP_PACK_U8(buffer, l2->dst_mac[i]); 18331 } 18332 18333 for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) { 18334 _BHH_ENCAP_PACK_U8(buffer, l2->src_mac[i]); 18335 } 18336 18337 /* Vlan Tag tpid = 0 indicates untagged */ 18338 if (0 != l2->vlan_tag.tpid) { 18339 tmp = (l2->vlan_tag.tpid << 16) | 18340 ((l2->vlan_tag.tci.prio & 0x7) << 13) | 18341 ((l2->vlan_tag.tci.cfi & 0x1) << 12) | 18342 (l2->vlan_tag.tci.vid & 0xfff); 18343 _BHH_ENCAP_PACK_U32(buffer, tmp); 18344 } 18345 18346 /*Inner Vlan Tag inner_tpid = 0 indicates single tag */ 18347 if (0 != l2->vlan_tag_inner.tpid) { 18348 tmp = (l2->vlan_tag_inner.tpid << 16) | 18349 ((l2->vlan_tag_inner.tci.prio & 0x7) << 13) | 18350 ((l2->vlan_tag_inner.tci.cfi & 0x1) << 12) | 18351 (l2->vlan_tag_inner.tci.vid & 0xfff); 18352 _BHH_ENCAP_PACK_U32(buffer, tmp); 18353 } 18354 _BHH_ENCAP_PACK_U16(buffer, l2->etype); 18355 18356 return (buffer); 18357 } 18358 18359 /* 18360 * Function: 18361 * _bcm_kt2_oam_bhh_encap_build_pack 18362 * Purpose: 18363 * Builds and packs the BHH packet encapsulation for a given 18364 * BHH tunnel type. 18365 * Parameters: 18366 * unit - (IN) Unit number. 18367 * port - (IN) Port. 18368 * endpoint_config - (IN/OUT) Pointer to BHH endpoint structure. 18369 * packet_flags - (IN) Flags for building packet. 18370 * buffer - (OUT) Buffer returning BHH encapsulation. 18371 * Returns: 18372 * BCM_E_XXX 18373 * Notes: 18374 * The returning BHH encapsulation includes only all the 18375 * encapsulation headers/labels and does not include 18376 * the BHH control packet. 18377 */ 18378 STATIC int 18379 _bcm_kt2_oam_bhh_encap_build_pack(int unit, bcm_port_t port, 18380 _bcm_oam_hash_data_t *h_data_p, 18381 uint32 packet_flags, 18382 uint8 *buffer, 18383 uint32 *encap_length) 18384 { 18385 uint8 *cur_ptr = buffer; 18386 uint16 etype = 0; 18387 bcm_if_t l3_intf_id = -1; 18388 _ach_header_t ach; 18389 _mpls_label_t mpls_gal; 18390 _mpls_label_t mpls_labels[_BHH_MPLS_MAX_LABELS]; 18391 _mpls_label_t pw_label; 18392 int mpls_count = 0; 18393 _l2_header_t l2; 18394 int i; 18395 18396 18397 /* 18398 * Get necessary headers/labels information. 18399 * 18400 * Following order is important since some headers/labels 18401 * may depend on previous header/label information. 18402 */ 18403 if (packet_flags & _BHH_ENCAP_PKT_G_ACH) { 18404 BCM_IF_ERROR_RETURN 18405 (_bcm_kt2_oam_bhh_ach_header_get(packet_flags, &ach)); 18406 } 18407 18408 if (packet_flags & _BHH_ENCAP_PKT_GAL) { 18409 if (h_data_p->egr_label == SHR_BHH_MPLS_GAL_LABEL) { 18410 BCM_IF_ERROR_RETURN 18411 (_bcm_kt2_oam_bhh_mpls_gal_label_get(&mpls_gal, 18412 h_data_p->egr_label_exp)); 18413 } else { 18414 BCM_IF_ERROR_RETURN 18415 (_bcm_kt2_oam_bhh_mpls_gal_label_get(&mpls_gal, 0)); 18416 } 18417 } 18418 18419 if (packet_flags & _BHH_ENCAP_PKT_MPLS) { 18420 etype = SHR_BHH_L2_ETYPE_MPLS_UCAST; 18421 BCM_IF_ERROR_RETURN 18422 (_bcm_kt2_oam_bhh_mpls_labels_get(unit, h_data_p, 18423 packet_flags, 18424 _BHH_MPLS_MAX_LABELS, 18425 &pw_label, 18426 mpls_labels, 18427 &mpls_count, 18428 &l3_intf_id)); 18429 } 18430 18431 /* Always build L2 Header */ 18432 BCM_IF_ERROR_RETURN 18433 (_bcm_kt2_oam_bhh_l2_header_get(unit, 18434 h_data_p, 18435 port, 18436 etype, 18437 &l2)); 18438 18439 /* 18440 * Pack header/labels into given buffer (network packet format). 18441 * 18442 * Following packing order must be followed to correctly 18443 * build the packet encapsulation. 18444 */ 18445 cur_ptr = buffer; 18446 18447 /* L2 Header is always present */ 18448 cur_ptr = _bcm_kt2_oam_bhh_l2_header_pack(cur_ptr, &l2); 18449 18450 if (packet_flags & _BHH_ENCAP_PKT_MPLS) { 18451 for (i = 0;i < mpls_count;i++) { 18452 cur_ptr = _bcm_kt2_oam_bhh_mpls_label_pack(cur_ptr, &mpls_labels[i]); 18453 } 18454 } 18455 18456 if (packet_flags & _BHH_ENCAP_PKT_GAL) { 18457 cur_ptr = _bcm_kt2_oam_bhh_mpls_label_pack(cur_ptr, &mpls_gal); 18458 } 18459 18460 if (packet_flags & _BHH_ENCAP_PKT_G_ACH) { 18461 cur_ptr = _bcm_kt2_oam_bhh_ach_header_pack(cur_ptr, &ach); 18462 } 18463 18464 18465 /* Set BHH encapsulation length */ 18466 *encap_length = cur_ptr - buffer; 18467 18468 return (BCM_E_NONE); 18469 } 18470 /* 18471 * Function: 18472 * _bcm_kt2_oam_bhh_encap_create 18473 * Purpose: 18474 * Creates a BHH packet encapsulation. 18475 * Parameters: 18476 * unit - (IN) Unit number. 18477 * port_id - (IN) Port. 18478 * endpoint_config - (IN/OUT) Pointer to BHH endpoint structure. 18479 * encap_data - (OUT) Buffer returning BHH encapsulation. 18480 * Returns: 18481 * BCM_E_XXX 18482 * Notes: 18483 * The returning BHH encapsulation buffer includes all the 18484 * corresponding headers/labels EXCEPT for the BHH control packet. 18485 */ 18486 STATIC int 18487 _bcm_kt2_oam_bhh_encap_create(int unit, bcm_port_t port_id, 18488 _bcm_oam_hash_data_t *h_data_p, 18489 uint8 *encap_data, 18490 uint8 *encap_type, 18491 uint32 *encap_length) 18492 { 18493 uint32 packet_flags; 18494 _bcm_oam_control_t *oc; 18495 18496 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 18497 18498 packet_flags = 0; 18499 18500 /* 18501 * Get BHH encapsulation packet format flags 18502 * 18503 * Also, perform the following for each BHH tunnel type: 18504 * - Check for valid parameter values 18505 * - Set specific values required by the BHH tunnel definition 18506 * (e.g. such as ttl=1,...) 18507 */ 18508 switch (h_data_p->type) { 18509 case bcmOAMEndpointTypeBHHMPLS: 18510 packet_flags |= 18511 (_BHH_ENCAP_PKT_MPLS | 18512 _BHH_ENCAP_PKT_GAL | 18513 _BHH_ENCAP_PKT_G_ACH); 18514 break; 18515 18516 case bcmOAMEndpointTypeBHHMPLSVccv: 18517 switch(h_data_p->vccv_type) { 18518 18519 case bcmOamBhhVccvChannelAch: 18520 packet_flags |= 18521 (_BHH_ENCAP_PKT_MPLS | 18522 _BHH_ENCAP_PKT_PW | 18523 _BHH_ENCAP_PKT_G_ACH); 18524 break; 18525 18526 case bcmOamBhhVccvRouterAlert: 18527 packet_flags |= 18528 (_BHH_ENCAP_PKT_MPLS | 18529 _BHH_ENCAP_PKT_PW | 18530 _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT | 18531 _BHH_ENCAP_PKT_G_ACH); 18532 break; 18533 18534 case bcmOamBhhVccvTtl: 18535 packet_flags |= 18536 (_BHH_ENCAP_PKT_MPLS | 18537 _BHH_ENCAP_PKT_PW | 18538 _BHH_ENCAP_PKT_G_ACH); 18539 break; 18540 18541 case bcmOamBhhVccvGal13: 18542 packet_flags |= 18543 (_BHH_ENCAP_PKT_MPLS | 18544 _BHH_ENCAP_PKT_PW | 18545 _BHH_ENCAP_PKT_GAL | 18546 _BHH_ENCAP_PKT_G_ACH); 18547 break; 18548 18549 default: 18550 return (BCM_E_PARAM); 18551 break; 18552 } 18553 break; 18554 case bcmOAMEndpointTypeBhhSection: 18555 case bcmOAMEndpointTypeBhhSectionInnervlan: 18556 case bcmOAMEndpointTypeBhhSectionOuterVlan: 18557 case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan: 18558 packet_flags |= 18559 (_BHH_ENCAP_PKT_GAL | 18560 _BHH_ENCAP_PKT_G_ACH); 18561 break; 18562 default: 18563 return (BCM_E_PARAM); 18564 } 18565 18566 /* Build header/labels and pack in buffer */ 18567 BCM_IF_ERROR_RETURN 18568 (_bcm_kt2_oam_bhh_encap_build_pack(unit, port_id, 18569 h_data_p, 18570 packet_flags, 18571 encap_data, 18572 encap_length)); 18573 18574 /* Set encap type (indicates uC side that checksum is required) */ 18575 *encap_type = SHR_BHH_ENCAP_TYPE_RAW; 18576 18577 #ifdef _BHH_DEBUG_DUMP 18578 _bcm_kt2_oam_bhh_encap_data_dump(encap_data, *encap_length); 18579 #endif 18580 18581 if (*encap_length > oc->bhh_max_encap_length) { 18582 LOG_ERROR(BSL_LS_BCM_OAM, 18583 (BSL_META_U(unit, 18584 "OAM(unit %d) Error: Encap length greater than max," 18585 "encap_length=%u max=%u\n"), 18586 unit, *encap_length, oc->bhh_max_encap_length)); 18587 return BCM_E_CONFIG; 18588 } 18589 18590 return (BCM_E_NONE); 18591 } 18592 18593 /* 18594 * Function: 18595 * _bcm_kt2_oam_bhh_appl_callback 18596 * Purpose: 18597 * Update FW BHH appl state 18598 * Parameters: 18599 * unit - (IN) Unit number. 18600 * uC - (IN) core number. 18601 * stage - (IN) core reset stage. 18602 * user_data - (IN) data pointer. 18603 * Returns: 18604 * BCM_E_XXX 18605 * Notes: 18606 */ 18607 18608 int _bcm_kt2_oam_bhh_appl_callback(int unit, 18609 int uC, 18610 soc_cmic_uc_shutdown_stage_t stage, 18611 void *user_data) { 18612 _bcm_oam_control_t *oc; 18613 18614 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 18615 _BCM_OAM_LOCK(oc); 18616 oc->ukernel_not_ready = 1; 18617 18618 _BCM_OAM_UNLOCK(oc); 18619 18620 return BCM_E_NONE; 18621 } 18622 18623 /* 18624 * Function: 18625 * bcm_kt2_oam_bhh_endpoint_create 18626 * Purpose: 18627 * Initialize the HW for BHH packet processing. 18628 * Configure: 18629 * - Copy to CPU BHH error packets 18630 * - CPU COS Queue for BHH packets 18631 * - RX DMA channel 18632 * Parameters: 18633 * unit - (IN) Unit number. 18634 * Returns: 18635 * BCM_E_XXX 18636 * Notes: 18637 */ 18638 int 18639 bcm_kt2_oam_bhh_endpoint_create(int unit, 18640 bcm_oam_endpoint_info_t *endpoint_info, 18641 _bcm_oam_hash_key_t *hash_key) 18642 { 18643 _bcm_oam_control_t *oc; 18644 _bcm_oam_hash_data_t *hash_data = NULL; /* Endpoint hash data pointer. */ 18645 _bcm_oam_group_data_t *group_p; /* Pointer to group data. */ 18646 int ep_req_index; /* Requested endpoint index. */ 18647 int rv = BCM_E_NONE; /* Operation return status. */ 18648 int is_remote = 0; /* Remote endpoint status. */ 18649 int is_replace; 18650 int is_local = 0; 18651 uint32 sglp = 0; /* Source global logical port. */ 18652 uint32 dglp = 0; /* Dest global logical port. */ 18653 bcm_module_t module_id; /* Module ID */ 18654 bcm_port_t port_id; 18655 bcm_trunk_t trunk_id; 18656 int local_id; 18657 uint32 svp = 0; /* Source virtual port */ 18658 bcm_port_t src_pp_port = 0; /* Source pp port. */ 18659 bcm_port_t dst_pp_port = 0; /* Dest pp port. */ 18660 bhh_sdk_msg_ctrl_sess_set_t msg_sess; 18661 bhh_sdk_msg_ctrl_rmep_create_t msg_rmep_create; 18662 uint8 *buffer, *buffer_ptr; 18663 uint16 buffer_len, reply_len; 18664 int encap = 0; 18665 uint32 session_flags; 18666 int bhh_pool_ep_idx = 0; 18667 egr_l3_next_hop_entry_t egr_nh_entry; 18668 int egr_nh_index; 18669 int is_vp_valid = 0; 18670 uint8 group_sw_rdi = 0; 18671 bcm_gport_t tx_gport; 18672 18673 LOG_DEBUG(BSL_LS_BCM_OAM, 18674 (BSL_META_U(unit, 18675 "BHH Info: bcm_kt2_oam_bhh_endpoint_create" 18676 "Endpoint ID=%d.\n"), endpoint_info->id)); 18677 18678 _BCM_OAM_BHH_IS_VALID(unit); 18679 18680 /* Validate input parameter. */ 18681 if (NULL == endpoint_info) { 18682 return (BCM_E_PARAM); 18683 } 18684 18685 /* Lock already taken by the calling routine. */ 18686 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 18687 18688 /* Perform BHH specific validation checks */ 18689 /* BHH EP can only be at the MAX Level */ 18690 if ( endpoint_info->level != _BCM_OAM_EP_LEVEL_MAX ) { 18691 LOG_ERROR(BSL_LS_BCM_OAM, 18692 (BSL_META_U(unit, 18693 "OAM Error: EP Level should be equal to %d\n"), 18694 _BCM_OAM_EP_LEVEL_MAX)); 18695 return (BCM_E_PARAM); 18696 } 18697 18698 /* Get MEP remote endpoint status. */ 18699 is_remote = (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0; 18700 18701 is_replace = ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) != 0); 18702 18703 /* Validate EP Id if BCM_OAM_ENDPOINT_WITH_ID flag is set */ 18704 if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) { 18705 if((endpoint_info->id < _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET) || 18706 (endpoint_info->id >= (_BCM_OAM_BHH_KT2_ENDPOINT_OFFSET 18707 + oc->bhh_endpoint_count))) { 18708 return (BCM_E_PARAM); 18709 } 18710 } 18711 18712 /* Validate remote EP Id if BCM_OAM_ENDPOINT_REMOTE flag is set */ 18713 if (is_remote) { 18714 if((endpoint_info->local_id < _BCM_OAM_BHH_KT2_ENDPOINT_OFFSET) || 18715 (endpoint_info->local_id >= (_BCM_OAM_BHH_KT2_ENDPOINT_OFFSET 18716 + oc->bhh_endpoint_count))) { 18717 return (BCM_E_PARAM); 18718 } 18719 } 18720 18721 if (is_replace) { 18722 hash_data = &oc->oam_hash_data[endpoint_info->id]; 18723 if (!hash_data->in_use) { 18724 return (BCM_E_NOT_FOUND); 18725 } 18726 18727 /* Delete original and recreate new EP */ 18728 rv = _bcm_kt2_oam_endpoint_destroy(unit, endpoint_info->id); 18729 if (BCM_FAILURE(rv)) { 18730 LOG_ERROR(BSL_LS_BCM_OAM, 18731 (BSL_META_U(unit, 18732 "OAM Error: Endpoint destroy (EP=%d) - %s.\n"), 18733 endpoint_info->id, bcm_errmsg(rv))); 18734 return (rv); 18735 } 18736 } 18737 18738 /* 18739 BHH API have been using L3_EGRESS type in 18740 bcm_oam_endpoint_info_t.intf field. 18741 However for supporting LM/DM on Katana2 this should be DVP_EGRESS type for PW, 18742 only CCM will work with L3_EGRESS type, retaining the old type for 18743 backward compatibility 18744 */ 18745 if(!BHH_EP_MPLS_SECTION_TYPE(endpoint_info)){ 18746 if ((endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv) && 18747 (endpoint_info->flags & (BCM_OAM_ENDPOINT_LOSS_MEASUREMENT | 18748 BCM_OAM_ENDPOINT_DELAY_MEASUREMENT))) { 18749 if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, endpoint_info->intf_id)) { 18750 LOG_ERROR(BSL_LS_BCM_OAM, 18751 (BSL_META_U(unit, 18752 "OAM Error: bcm_oam_endpoint_info_t.intf type" 18753 " not valid. It should be DVP_EGRESS type for LM/DM support.\n"))); 18754 return (BCM_E_PARAM); 18755 } 18756 } else { 18757 if ( !BCM_XGS3_L3_EGRESS_IDX_VALID(unit, endpoint_info->intf_id) & 18758 !BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, endpoint_info->intf_id) ) { 18759 LOG_ERROR(BSL_LS_BCM_OAM, 18760 (BSL_META_U(unit, 18761 "OAM Error: bcm_oam_endpoint_info_t.intf type" 18762 " not valid. It should be DVP_EGRESS or L3_EGRESS type.\n"))); 18763 return (BCM_E_PARAM); 18764 } 18765 } 18766 } 18767 /* Now that we passed the validation checks 18768 * Create a new endpoint with the requested ID. */ 18769 if ( !is_remote && (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) ) { 18770 18771 hash_data = &oc->oam_hash_data[endpoint_info->id]; 18772 18773 if (!is_replace && hash_data->in_use) { 18774 return (BCM_E_EXISTS); 18775 } 18776 18777 ep_req_index = endpoint_info->id; 18778 bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(ep_req_index); 18779 18780 if(BCM_FAILURE(rv)) { 18781 LOG_ERROR(BSL_LS_BCM_OAM, 18782 (BSL_META_U(unit, 18783 "BHH Error: Endpoint check (EP=%d) - %s.\n"), 18784 endpoint_info->id, bcm_errmsg(rv))); 18785 return (rv); 18786 } 18787 18788 if(!is_replace) { 18789 rv = shr_idxres_list_reserve(oc->bhh_pool, bhh_pool_ep_idx, 18790 bhh_pool_ep_idx); 18791 if (BCM_FAILURE(rv)) { 18792 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 18793 LOG_ERROR(BSL_LS_BCM_OAM, 18794 (BSL_META_U(unit, 18795 "BHH Error: Endpoint reserve (EP=%d) - %s.\n"), 18796 endpoint_info->id, bcm_errmsg(rv))); 18797 return (rv); 18798 } 18799 } 18800 } else { 18801 18802 /* BHH uses local and remote same index */ 18803 if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) { 18804 ep_req_index = endpoint_info->local_id; 18805 bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(ep_req_index); 18806 } 18807 else { 18808 /* Allocate the next available endpoint index. */ 18809 rv = shr_idxres_list_alloc(oc->bhh_pool, 18810 (shr_idxres_element_t *)&bhh_pool_ep_idx); 18811 if (BCM_FAILURE(rv)) { 18812 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_FULL) : rv; 18813 LOG_ERROR(BSL_LS_BCM_OAM, 18814 (BSL_META_U(unit, 18815 "BHH Error: Endpoint alloc failed - %s.\n"), 18816 bcm_errmsg(rv))); 18817 return (rv); 18818 } 18819 /* Set the allocated endpoint id value. */ 18820 ep_req_index = BCM_OAM_BHH_GET_SDK_EP(bhh_pool_ep_idx); 18821 } 18822 endpoint_info->id = ep_req_index; 18823 } 18824 18825 /* Get the hash data pointer where the data is to be stored. */ 18826 hash_data = &oc->oam_hash_data[ep_req_index]; 18827 group_p = &oc->group_info[endpoint_info->group]; 18828 18829 /* 18830 * The uKernel is not provisioned until both endpoints (local and remote) 18831 * are provisioned in the host. 18832 */ 18833 if (is_remote) { 18834 18835 if (!hash_data->in_use) { 18836 return (BCM_E_NOT_FOUND); 18837 } else if (hash_data->flags & BCM_OAM_ENDPOINT_REMOTE) { 18838 return (BCM_E_EXISTS); 18839 } 18840 18841 if(!(endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)){ 18842 /* 18843 * Now that both ends are provisioned the uKernel can be 18844 * configured. 18845 */ 18846 msg_rmep_create.sess_id = bhh_pool_ep_idx; 18847 msg_rmep_create.flags = 0; 18848 msg_rmep_create.enable = 1; 18849 msg_rmep_create.remote_mep_id = endpoint_info->name; 18850 18851 msg_rmep_create.period = _kt2_ccm_intervals[ 18852 _bcm_kt2_oam_ccm_msecs_to_hw_encode(endpoint_info->ccm_period)]; 18853 18854 /* Pack control message data into DMA buffer */ 18855 buffer = oc->dma_buffer; 18856 buffer_ptr = bhh_sdk_msg_ctrl_rmep_create_pack(buffer, &msg_rmep_create); 18857 buffer_len = buffer_ptr - buffer; 18858 18859 /* Send BHH Session Update message to uC */ 18860 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 18861 MOS_MSG_SUBCLASS_BHH_RMEP_CREATE, 18862 buffer_len, 0, 18863 MOS_MSG_SUBCLASS_BHH_RMEP_CREATE_REPLY, 18864 &reply_len); 18865 if (BCM_FAILURE(rv) || (reply_len != 0)) { 18866 LOG_ERROR(BSL_LS_BCM_OAM, 18867 (BSL_META_U(unit, 18868 "BHH(unit %d) Error: Endpoint destroy (EP=%d) - %s.\n"), 18869 unit, endpoint_info->id, bcm_errmsg(rv))); 18870 return (BCM_E_INTERNAL); 18871 } 18872 } 18873 18874 } else { 18875 18876 /* Resolve given endpoint gport value to SGLP and DGLP values. */ 18877 rv = _bcm_kt2_oam_endpoint_gport_resolve(unit, endpoint_info, &sglp, 18878 &dglp, &src_pp_port, 18879 &dst_pp_port, &svp, &trunk_id, 18880 &is_vp_valid, &tx_gport); 18881 if (BCM_FAILURE(rv)) { 18882 LOG_ERROR(BSL_LS_BCM_OAM, 18883 (BSL_META_U(unit, 18884 "OAM Error: Gport resolve (EP=%d) - %s.\n"), 18885 endpoint_info->id, bcm_errmsg(rv))); 18886 /* Return endpoint index to MEP pool. */ 18887 shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx); 18888 return (rv); 18889 } 18890 18891 /* Clear the hash data element contents before storing the values. */ 18892 _BCM_OAM_HASH_DATA_CLEAR(hash_data); 18893 hash_data->oam_domain = _BCM_OAM_DOMAIN_BHH; 18894 hash_data->type = endpoint_info->type; 18895 hash_data->ep_id = endpoint_info->id; 18896 hash_data->group_index = endpoint_info->group; 18897 hash_data->level = endpoint_info->level; 18898 hash_data->vlan = endpoint_info->vlan; 18899 hash_data->inner_vlan = endpoint_info->inner_vlan; 18900 hash_data->outer_tpid = endpoint_info->outer_tpid; 18901 hash_data->inner_tpid = endpoint_info->inner_tpid; 18902 hash_data->vlan_pri = endpoint_info->pkt_pri; 18903 hash_data->inner_vlan_pri = endpoint_info->inner_pkt_pri; 18904 hash_data->gport = endpoint_info->gport; 18905 hash_data->trunk_index = endpoint_info->trunk_index; 18906 hash_data->sglp = sglp; 18907 hash_data->dglp = dglp; 18908 hash_data->flags = endpoint_info->flags; 18909 hash_data->flags2 = endpoint_info->flags2; 18910 hash_data->period = endpoint_info->ccm_period; 18911 hash_data->vccv_type = endpoint_info->vccv_type; 18912 hash_data->vpn = endpoint_info->vpn; 18913 hash_data->name = endpoint_info->name; 18914 hash_data->egress_if = endpoint_info->intf_id; 18915 hash_data->cpu_qid = endpoint_info->cpu_qid; 18916 hash_data->int_pri = endpoint_info->int_pri; 18917 hash_data->label = endpoint_info->mpls_label; 18918 hash_data->local_tx_enabled = 0; 18919 hash_data->local_rx_enabled = 1; 18920 hash_data->ts_format = endpoint_info->timestamp_format; 18921 hash_data->egr_label = endpoint_info->egress_label.label; 18922 hash_data->egr_label_exp = endpoint_info->egress_label.exp; 18923 hash_data->egr_label_ttl = endpoint_info->egress_label.ttl; 18924 18925 /* Initialize hardware index as invalid indices. */ 18926 hash_data->local_tx_index = _BCM_OAM_INVALID_INDEX; 18927 hash_data->local_rx_index = _BCM_OAM_INVALID_INDEX; 18928 hash_data->remote_index = _BCM_OAM_INVALID_INDEX; 18929 hash_data->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 18930 hash_data->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 18931 hash_data->rx_ctr = _BCM_OAM_INVALID_INDEX; 18932 hash_data->tx_ctr = _BCM_OAM_INVALID_INDEX; 18933 hash_data->profile_index = _BCM_OAM_INVALID_INDEX; 18934 hash_data->pri_map_index = _BCM_OAM_INVALID_INDEX; 18935 hash_data->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 18936 hash_data->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 18937 hash_data->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 18938 hash_data->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 18939 hash_data->ma_base_index = _BCM_OAM_INVALID_INDEX; 18940 hash_data->pm_profile_attached = _BCM_OAM_INVALID_INDEX; 18941 sal_memcpy(hash_data->dst_mac_address, endpoint_info->dst_mac_address, 18942 _BHH_MAC_ADDR_LENGTH); 18943 sal_memcpy(hash_data->src_mac_address, endpoint_info->src_mac_address, 18944 _BHH_MAC_ADDR_LENGTH); 18945 hash_data->in_use = 1; 18946 18947 if(!BHH_EP_MPLS_SECTION_TYPE(endpoint_info)) { 18948 18949 /* Now that we have reserved the EP index, We can reserve MA INDEX */ 18950 rv = _bcm_kt2_oam_downmep_rx_endpoint_reserve(unit, endpoint_info); 18951 if (BCM_FAILURE(rv)) { 18952 /* Return endpoint index to MEP pool. */ 18953 shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx); 18954 LOG_ERROR(BSL_LS_BCM_OAM, 18955 (BSL_META_U(unit, 18956 "OAM Error: EP MA INDEX alloc" 18957 "failed EP:%d %s.\n"), endpoint_info->id, 18958 bcm_errmsg(rv))); 18959 return (rv); 18960 } 18961 18962 rv = _bcm_kt2_oam_local_rx_mep_hw_set(unit, endpoint_info); 18963 if (BCM_FAILURE(rv)) { 18964 LOG_ERROR(BSL_LS_BCM_OAM, 18965 (BSL_META_U(unit, 18966 "OAM Error: Rx config failed for EP=%d %s.\n"), 18967 endpoint_info->id, bcm_errmsg(rv))); 18968 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 18969 return (rv); 18970 } 18971 18972 /* Enable BHH in the EGR_L3_NEXT_HOP table */ 18973 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, endpoint_info->intf_id)) { 18974 egr_nh_index = endpoint_info->intf_id - 18975 BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 18976 } 18977 else { 18978 egr_nh_index = endpoint_info->intf_id - 18979 BCM_XGS3_EGRESS_IDX_MIN(unit); 18980 } 18981 rv = soc_mem_read(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ANY, 18982 egr_nh_index, &egr_nh_entry); 18983 if (BCM_FAILURE(rv)) { 18984 LOG_ERROR(BSL_LS_BCM_OAM, 18985 (BSL_META_U(unit, 18986 "OAM Error: reading EGR_L3_NEXT_HOP," 18987 "for EP=%d %s.\n"), endpoint_info->id, bcm_errmsg(rv))); 18988 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 18989 return (rv); 18990 } 18991 soc_mem_field32_set(unit, EGR_L3_NEXT_HOPm, &egr_nh_entry, MPLS__BHH_ENABLEf, 1); 18992 rv = soc_mem_write(unit, EGR_L3_NEXT_HOPm, MEM_BLOCK_ALL, 18993 egr_nh_index, &egr_nh_entry); 18994 if (BCM_FAILURE(rv)) { 18995 LOG_ERROR(BSL_LS_BCM_OAM, 18996 (BSL_META_U(unit, 18997 "OAM Error: writing EGR_L3_NEXT_HOP," 18998 "for EP=%d %s.\n"), endpoint_info->id, bcm_errmsg(rv))); 18999 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 19000 return (rv); 19001 } 19002 } else { 19003 if(hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 19004 shr_idxres_element_t ctr_index; 19005 19006 rv = _bcm_kt2_oam_bhh_sec_mep_alloc_counter(unit, &ctr_index); 19007 if (BCM_FAILURE(rv)) { 19008 LOG_ERROR(BSL_LS_BCM_OAM, 19009 (BSL_META_U(unit, 19010 "OAM Error: LM counter block alloc - %s.\n"), 19011 bcm_errmsg(rv))); 19012 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 19013 return (rv); 19014 } 19015 hash_data->rx_ctr = (0 << 24) | (ctr_index); /* Pool id 0 for ingress counters*/ 19016 hash_data->tx_ctr = (1 << 24) | (ctr_index); /* Pool id 1 for egress counters */ 19017 } 19018 } 19019 /* Get the Trunk, Port and Modid info for this Gport */ 19020 rv = _bcm_esw_gport_resolve(unit, tx_gport, &module_id, &port_id, 19021 &trunk_id, &local_id); 19022 if (BCM_FAILURE(rv)) { 19023 LOG_ERROR(BSL_LS_BCM_OAM, 19024 (BSL_META_U(unit, 19025 "BHH Error: Gport resolve (EP=%d) - %s.\n"), 19026 endpoint_info->id, bcm_errmsg(rv))); 19027 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 19028 return (rv); 19029 } 19030 19031 /* Get local port used for TX BHH packet */ 19032 rv = _bcm_esw_modid_is_local(unit, module_id, &is_local); 19033 if(BCM_FAILURE(rv)) { 19034 LOG_ERROR(BSL_LS_BCM_OAM, 19035 (BSL_META_U(unit, 19036 "BHH Error: local port for " 19037 "BHH TX failed(EP=%d) - %s.\n"), 19038 endpoint_info->id, bcm_errmsg(rv))); 19039 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 19040 return (rv); 19041 } 19042 19043 if (!is_local) { /* HG port */ 19044 rv = bcm_esw_stk_modport_get(unit, module_id, &port_id); 19045 if(BCM_FAILURE(rv)) { 19046 LOG_ERROR(BSL_LS_BCM_OAM, 19047 (BSL_META_U(unit, 19048 "BHH Error: HG port get failed " 19049 "(EP=%d) - %s.\n"), 19050 endpoint_info->id, bcm_errmsg(rv))); 19051 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 19052 return (rv); 19053 } 19054 } 19055 19056 /* Create or Update */ 19057 session_flags = (is_replace) ? 0 : SHR_BHH_SESS_SET_F_CREATE; 19058 19059 /* Set Endpoint config entry */ 19060 hash_data->bhh_endpoint_index = ep_req_index; 19061 19062 /* Set Encapsulation in HW */ 19063 if ((!BHH_EP_MPLS_SECTION_TYPE(endpoint_info)) && 19064 ((!is_replace) || (endpoint_info->flags & BCM_BHH_ENDPOINT_ENCAP_SET))) { 19065 rv = _bcm_kt2_oam_bhh_encap_hw_set(unit, hash_data, module_id, 19066 port_id, is_local, endpoint_info); 19067 if(BCM_FAILURE(rv)) { 19068 LOG_ERROR(BSL_LS_BCM_OAM, 19069 (BSL_META_U(unit, 19070 "BHH Error: HW encap set failed (EP=%d)" 19071 " - %s.\n"), 19072 endpoint_info->id, bcm_errmsg(rv))); 19073 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 19074 return (rv); 19075 } 19076 } 19077 19078 encap = 1; 19079 19080 if(!(endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) { 19081 /* Set control message data */ 19082 sal_memset(&msg_sess, 0, sizeof(msg_sess)); 19083 19084 /* 19085 * Set the BHH encapsulation data 19086 * 19087 * The function _bcm_kt2_oam_bhh_encap_create() is called first 19088 * since this sets some fields in 'hash_data' which are 19089 * used in the message. 19090 */ 19091 if (encap) { 19092 rv = _bcm_kt2_oam_bhh_encap_create(unit, 19093 port_id, 19094 hash_data, 19095 msg_sess.encap_data, 19096 &msg_sess.encap_type, 19097 &msg_sess.encap_length); 19098 19099 if(BCM_FAILURE(rv)) 19100 { 19101 LOG_ERROR(BSL_LS_BCM_OAM, 19102 (BSL_META_U(unit, 19103 "BHH Error: Endpoint destroy (EP=%d) - %s.\n"), 19104 endpoint_info->id, bcm_errmsg(rv))); 19105 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 19106 return (rv); 19107 } 19108 } 19109 19110 /* 19111 * Endpoint can be one of: CCM, LB, LM or DM. The default is CCM, 19112 * all others modes must be specified via a config flag. 19113 */ 19114 if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOOPBACK) 19115 session_flags |= SHR_BHH_SESS_SET_F_LB; 19116 else if (endpoint_info->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) 19117 session_flags |= SHR_BHH_SESS_SET_F_DM; 19118 else if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) 19119 session_flags |= SHR_BHH_SESS_SET_F_LM; 19120 else 19121 session_flags |= SHR_BHH_SESS_SET_F_CCM; 19122 19123 if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) 19124 session_flags |= SHR_BHH_SESS_SET_F_MIP; 19125 19126 _bcm_kt2_oam_get_group_sw_rdi (unit, endpoint_info->group, 19127 &group_sw_rdi); 19128 if (group_sw_rdi) { 19129 session_flags |= SHR_BHH_SESS_SET_F_RDI; 19130 } 19131 /*if (!local_tx_enabled) 19132 session_flags |= SHR_BHH_SESS_SET_F_PASSIVE;*/ 19133 19134 msg_sess.sess_id = bhh_pool_ep_idx; 19135 msg_sess.flags = session_flags; 19136 19137 msg_sess.mel = hash_data->level; 19138 msg_sess.mep_id = hash_data->name; 19139 sal_memcpy(msg_sess.meg_id, group_p->name, BCM_OAM_GROUP_NAME_LENGTH); 19140 19141 msg_sess.period = _kt2_ccm_intervals[ 19142 _bcm_kt2_oam_ccm_msecs_to_hw_encode(endpoint_info->ccm_period)]; 19143 19144 msg_sess.if_num = endpoint_info->intf_id; 19145 msg_sess.tx_port = port_id; 19146 msg_sess.tx_cos = endpoint_info->int_pri; 19147 msg_sess.tx_pri = endpoint_info->pkt_pri; 19148 msg_sess.tx_qnum = SOC_INFO(unit).port_uc_cosq_base[port_id] + endpoint_info->int_pri; 19149 msg_sess.lm_counter_index 19150 = hash_data->tx_ctr; 19151 19152 msg_sess.mpls_label = endpoint_info->mpls_label; 19153 19154 switch (endpoint_info->type) { 19155 case bcmOAMEndpointTypeBHHMPLS: 19156 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_LSP; 19157 msg_sess.priority = endpoint_info->mpls_exp; 19158 break; 19159 19160 case bcmOAMEndpointTypeBHHMPLSVccv: 19161 switch(endpoint_info->vccv_type) { 19162 19163 case bcmOamBhhVccvChannelAch: 19164 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_1; 19165 msg_sess.priority = endpoint_info->mpls_exp; 19166 break; 19167 19168 case bcmOamBhhVccvRouterAlert: 19169 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_2; 19170 msg_sess.priority = endpoint_info->mpls_exp; 19171 break; 19172 19173 case bcmOamBhhVccvTtl: 19174 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_3; 19175 msg_sess.priority = endpoint_info->mpls_exp; 19176 break; 19177 19178 case bcmOamBhhVccvGal13: 19179 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_4; 19180 msg_sess.priority = endpoint_info->mpls_exp; 19181 break; 19182 19183 default: 19184 return BCM_E_PARAM; 19185 break; 19186 } 19187 break; 19188 19189 case bcmOAMEndpointTypeBhhSection: 19190 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION; 19191 msg_sess.priority = 0; 19192 break; 19193 case bcmOAMEndpointTypeBhhSectionInnervlan: 19194 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_INNERVLAN; 19195 msg_sess.priority = endpoint_info->inner_pkt_pri; 19196 break; 19197 case bcmOAMEndpointTypeBhhSectionOuterVlan: 19198 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTERVLAN; 19199 msg_sess.priority = endpoint_info->pkt_pri; 19200 break; 19201 case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan: 19202 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTER_PLUS_INNERVLAN; 19203 msg_sess.priority = endpoint_info->pkt_pri; 19204 break; 19205 19206 default: 19207 return BCM_E_PARAM; 19208 } 19209 19210 /* Pack control message data into DMA buffer */ 19211 buffer = oc->dma_buffer; 19212 buffer_ptr = bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess); 19213 buffer_len = buffer_ptr - buffer; 19214 19215 /* Send BHH Session Update message to uC */ 19216 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 19217 MOS_MSG_SUBCLASS_BHH_SESS_SET, 19218 buffer_len, 0, 19219 MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY, 19220 &reply_len); 19221 if (BCM_FAILURE(rv) || (reply_len != 0)) { 19222 LOG_ERROR(BSL_LS_BCM_OAM, 19223 (BSL_META_U(unit, 19224 "BHH Error: Endpoint destroy (EP=%d) - %s.\n"), 19225 endpoint_info->id, bcm_errmsg(rv))); 19226 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 19227 return (rv); 19228 } 19229 } 19230 19231 if (!is_replace) { 19232 rv = _bcm_kt2_oam_group_ep_list_add(unit, endpoint_info->group, 19233 endpoint_info->id); 19234 } 19235 if (BCM_FAILURE(rv)) { 19236 LOG_ERROR(BSL_LS_BCM_OAM, 19237 (BSL_META_U(unit, 19238 "OAM Error: Tx config failed for EP=%d %s.\n"), 19239 endpoint_info->id, bcm_errmsg(rv))); 19240 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 19241 return (rv); 19242 } 19243 rv = _bcm_kt2_oam_ma_idx_to_ep_id_mapping_add(unit, hash_data); 19244 if (BCM_FAILURE(rv)) { 19245 LOG_ERROR(BSL_LS_BCM_OAM, 19246 (BSL_META_U(unit, 19247 "OAM(unit %d) Error: Add mapping from ma_idx_to_ep_id list (EP=%d) -" 19248 " %s.\n"), unit, hash_data->ep_id, bcm_errmsg(rv))); 19249 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 19250 return (rv); 19251 } 19252 19253 /* hash collision */ 19254 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, hash_data); 19255 if (BCM_FAILURE(rv)) { 19256 LOG_ERROR(BSL_LS_BCM_OAM, 19257 (BSL_META_U(unit, 19258 "OAM Error: Hash table insert failed EP=%d %s.\n"), 19259 endpoint_info->id, bcm_errmsg(rv))); 19260 _bcm_kt2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 19261 return (rv); 19262 } 19263 } 19264 hash_data->in_use = 1; 19265 19266 #ifdef BCM_WARM_BOOT_SUPPORT 19267 SOC_CONTROL_LOCK(unit); 19268 SOC_CONTROL(unit)->scache_dirty = 1; 19269 SOC_CONTROL_UNLOCK(unit); 19270 #endif 19271 19272 return (rv); 19273 } 19274 19275 /* 19276 * Function: 19277 * _bcm_kt2_oam_bhh_hw_init 19278 * Purpose: 19279 * Initialize the HW for BHH packet processing. 19280 * Configure: 19281 * - Copy to CPU BHH error packets 19282 * - CPU COS Queue for BHH packets 19283 * - RX DMA channel 19284 * Parameters: 19285 * unit - (IN) Unit number. 19286 * Returns: 19287 * BCM_E_XXX 19288 * Notes: 19289 */ 19290 STATIC int 19291 _bcm_kt2_oam_bhh_hw_init(int unit) 19292 { 19293 int rv = BCM_E_NONE; 19294 _bcm_oam_control_t *oc; /* OAM control structure. */ 19295 uint32 val=0; 19296 int index; 19297 int ach_error_index; 19298 int invalid_error_index; 19299 int bhh_lb_index; 19300 int cosq_map_size; 19301 bcm_rx_reasons_t reasons, reasons_mask; 19302 uint8 int_prio, int_prio_mask; 19303 uint32 packet_type, packet_type_mask; 19304 bcm_cos_queue_t cosq; 19305 bcm_rx_chan_t chan_id; 19306 int num_cosq = 0; 19307 int min_cosq, max_cosq; 19308 int i; 19309 19310 /* Get OAM Control Structure. */ 19311 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 19312 19313 _BCM_OAM_LOCK(oc); 19314 19315 /* 19316 * Send BHH lookup failure packet to CPU 19317 * Configure CPU_CONTROL_M register 19318 * Field BHH_SESSION_NOT_FOUND_TO_CPU 19319 */ 19320 rv = READ_CPU_CONTROL_Mr(unit, &val); 19321 if(BCM_FAILURE(rv)) { 19322 LOG_ERROR(BSL_LS_BCM_OAM, 19323 (BSL_META_U(unit, 19324 "BHH Error:hw init. Read CPU Control Reg %s.\n"), 19325 bcm_errmsg(rv))); 19326 _BCM_OAM_UNLOCK(oc); 19327 return (rv); 19328 } 19329 19330 /* Steer lookup failure packet to CPU */ 19331 soc_reg_field_set(unit, CPU_CONTROL_Mr, &val, 19332 BHH_SESSION_NOT_FOUND_TO_CPUf, 1); 19333 19334 rv = WRITE_CPU_CONTROL_Mr(unit, val); 19335 if(BCM_FAILURE(rv)) { 19336 LOG_ERROR(BSL_LS_BCM_OAM, 19337 (BSL_META_U(unit, 19338 "BHH Error:hw init. Write CPU_CONTROL_M Reg %s.\n"), 19339 bcm_errmsg(rv))); 19340 _BCM_OAM_UNLOCK(oc); 19341 return (rv); 19342 } 19343 19344 /* Set BHH ACH Type in BHH_RX_ACH_TYPE register */ 19345 rv = WRITE_BHH_RX_ACH_TYPEr(unit, SHR_BHH_ACH_CHANNEL_TYPE); 19346 19347 if(oc->ukernel_not_ready == 0){ 19348 /* 19349 * Get COSQ for BHH 19350 */ 19351 min_cosq = 0; 19352 for (i = 0; i < SOC_CMCS_NUM(unit); i++) { 19353 num_cosq = NUM_CPU_ARM_COSQ(unit, i); 19354 if (i == oc->uc_num + 1) { 19355 break; 19356 } 19357 min_cosq += num_cosq; 19358 } 19359 max_cosq = min_cosq + num_cosq - 1; 19360 19361 if(max_cosq < min_cosq) { 19362 LOG_ERROR(BSL_LS_BCM_OAM, 19363 (BSL_META_U(unit, 19364 "BHH Error: " 19365 "No BHH COS Queue available from uC%d - %s\n"), 19366 oc->uc_num, bcm_errmsg(BCM_E_CONFIG))); 19367 _BCM_OAM_UNLOCK(oc); 19368 return (BCM_E_CONFIG); 19369 } 19370 19371 /* check user configured COSq */ 19372 if (oc->cpu_cosq != BHH_COSQ_INVALID) { 19373 if ((oc->cpu_cosq < min_cosq) || 19374 (oc->cpu_cosq > max_cosq)) { 19375 _BCM_OAM_UNLOCK(oc); 19376 return (BCM_E_CONFIG); 19377 } 19378 min_cosq = max_cosq = oc->cpu_cosq; 19379 } 19380 19381 19382 /* 19383 * Assign RX DMA channel to CPU COS Queue 19384 * (This is the RX channel to listen on for BHH packets). 19385 * 19386 * DMA channels (12) are assigned 4 per processor: 19387 * (see /src/bcm/common/rx.c) 19388 * channels 0..3 --> PCI host 19389 * channels 4..7 --> uController 0 19390 * chnanels 8..11 --> uController 1 19391 * 19392 * The uControllers designate the 4 local DMA channels as follows: 19393 * local channel 0 --> TX 19394 * local channel 1..3 --> RX 19395 * 19396 * Each uController application needs to use a different 19397 * RX DMA channel to listen on. 19398 */ 19399 chan_id = (BCM_RX_CHANNELS * (SOC_ARM_CMC(unit, oc->uc_num))) + 19400 oc->rx_channel; 19401 19402 for (i = max_cosq; i >= min_cosq; i--) { 19403 rv = _bcm_common_rx_queue_channel_set(unit, i, chan_id); 19404 if(BCM_SUCCESS(rv)) { 19405 oc->cpu_cosq = i; 19406 break; 19407 } 19408 } 19409 19410 if (i < min_cosq) { 19411 rv = BCM_E_RESOURCE; 19412 LOG_ERROR(BSL_LS_BCM_OAM, 19413 (BSL_META_U(unit, 19414 "BHH Error: hw init." 19415 " queue channel set %s.\n"), 19416 bcm_errmsg(rv))); 19417 _BCM_OAM_UNLOCK(oc); 19418 return (rv); 19419 } 19420 19421 /* 19422 * Direct BHH packets to designated CPU COS Queue...or more accurately 19423 * BFD error packets. 19424 * 19425 * Reasons: 19426 * - bcmRxReasonBFD: BFD error 19427 * - bcmRxReasonBfdUnknownVersion: BFD Unknown ACH 19428 * NOTE: 19429 * The user input 'cpu_qid' (bcm_BHH_endpoint_t) could be 19430 * used to select different CPU COS queue. Currently, 19431 * all priorities are mapped into the same CPU COS Queue. 19432 */ 19433 19434 /* Find available entries in CPU COS queue map table */ 19435 ach_error_index = -1; /* COSQ map index for error packets */ 19436 invalid_error_index = -1; /* COSQ map index for error packets */ 19437 bhh_lb_index = -1; /* COSQ map index for LB packets */ 19438 rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size); 19439 if(BCM_FAILURE(rv)) { 19440 LOG_ERROR(BSL_LS_BCM_OAM, 19441 (BSL_META_U(unit, 19442 "BHH Error:hw init. cosq maps size %s.\n"), 19443 bcm_errmsg(rv))); 19444 _BCM_OAM_UNLOCK(oc); 19445 return (rv); 19446 } 19447 19448 for (index = cosq_map_size-1; index >= 0; index--) { 19449 rv = bcm_esw_rx_cosq_mapping_get(unit, index, 19450 &reasons, &reasons_mask, 19451 &int_prio, &int_prio_mask, 19452 &packet_type, &packet_type_mask, 19453 &cosq); 19454 if (rv == BCM_E_NOT_FOUND) { 19455 /* Assign first available index before default entries*/ 19456 rv = BCM_E_NONE; 19457 if (ach_error_index == -1) { 19458 ach_error_index = index; 19459 } else if (invalid_error_index == -1) { 19460 invalid_error_index = index; 19461 } else if (bhh_lb_index == -1) { 19462 bhh_lb_index = index; 19463 break; 19464 } 19465 } 19466 if (BCM_FAILURE(rv)) { 19467 LOG_ERROR(BSL_LS_BCM_OAM, 19468 (BSL_META_U(unit, 19469 "BHH Error:hw init. cosq maps get %s.\n"), 19470 bcm_errmsg(rv))); 19471 _BCM_OAM_UNLOCK(oc); 19472 return (rv); 19473 } 19474 } 19475 19476 if (ach_error_index == -1 || invalid_error_index == -1) { 19477 LOG_ERROR(BSL_LS_BCM_OAM, 19478 (BSL_META_U(unit, 19479 "BHH Error:hw init. ACH error %s.\n"), 19480 bcm_errmsg(rv))); 19481 _BCM_OAM_UNLOCK(oc); 19482 return (BCM_E_FULL); 19483 } 19484 19485 /* Set CPU COS Queue mapping */ 19486 BCM_RX_REASON_CLEAR_ALL(reasons); 19487 BCM_RX_REASON_SET(reasons, bcmRxReasonBHHOAM); /* BHH Packet */ 19488 BCM_RX_REASON_SET(reasons, bcmRxReasonOAMCCMSlowpath); /*OAM Slowpath CCM*/ 19489 19490 rv = bcm_esw_rx_cosq_mapping_set(unit, ach_error_index, 19491 reasons, reasons, 19492 0, 0, /* Any Internal Prio */ 19493 0, 0, /* Any packet type */ 19494 oc->cpu_cosq); 19495 if(BCM_FAILURE(rv)) { 19496 LOG_ERROR(BSL_LS_BCM_OAM, 19497 (BSL_META_U(unit, 19498 "BHH Error:hw init. cosq map set %s.\n"), 19499 bcm_errmsg(rv))); 19500 _BCM_OAM_UNLOCK(oc); 19501 return (rv); 19502 } 19503 oc->cpu_cosq_ach_error_index = ach_error_index; 19504 19505 19506 BCM_RX_REASON_CLEAR_ALL(reasons); 19507 BCM_RX_REASON_SET(reasons, bcmRxReasonBHHOAM); /* BHH Packet */ 19508 BCM_RX_REASON_SET(reasons, bcmRxReasonOAMLMDM); /*OAM Slowpath(LB/LBR)*/ 19509 19510 rv = bcm_esw_rx_cosq_mapping_set(unit, invalid_error_index, 19511 reasons, reasons, 19512 0, 0, /* Any Internal Prio */ 19513 0, 0, /* Any packet type */ 19514 oc->cpu_cosq); 19515 if(BCM_FAILURE(rv)) { 19516 LOG_ERROR(BSL_LS_BCM_OAM, 19517 (BSL_META_U(unit, 19518 "BHH Error:hw init. cosq map set %s.\n"), 19519 bcm_errmsg(rv))); 19520 _BCM_OAM_UNLOCK(oc); 19521 return (rv); 19522 } 19523 oc->cpu_cosq_invalid_error_index = invalid_error_index; 19524 19525 BCM_RX_REASON_CLEAR_ALL(reasons); 19526 BCM_RX_REASON_SET(reasons, bcmRxReasonBHHOAM); /* BHH Packet */ 19527 BCM_RX_REASON_SET(reasons, bcmRxReasonOAMSlowpath); /*OAM Slowpath */ 19528 19529 rv = bcm_esw_rx_cosq_mapping_set(unit, bhh_lb_index, 19530 reasons, reasons, 19531 0, 0, /* Any Internal Prio */ 19532 0, 0, /* Any packet type */ 19533 oc->cpu_cosq); 19534 if(BCM_FAILURE(rv)) { 19535 LOG_ERROR(BSL_LS_BCM_OAM, 19536 (BSL_META_U(unit, 19537 "BHH(unit %d) Error:hw init. cosq map set for" 19538 " Loopback %s.\n"), 19539 unit, bcm_errmsg(rv))); 19540 _BCM_OAM_UNLOCK(oc); 19541 return (rv); 19542 } 19543 oc->bhh_lb_index = bhh_lb_index; 19544 } 19545 19546 _BCM_OAM_UNLOCK(oc); 19547 return (rv); 19548 } 19549 19550 /* 19551 * Function: 19552 * _bcm_kt2_oam_bhh_session_hw_delete 19553 * Purpose: 19554 * Delete BHH Session in HW device. 19555 * Parameters: 19556 * unit - (IN) Unit number. 19557 * h_data_p- (IN) Pointer to BHH endpoint structure. 19558 * Returns: 19559 * BCM_E_XXX 19560 * Notes: 19561 */ 19562 STATIC int 19563 _bcm_kt2_oam_bhh_session_hw_delete(int unit, _bcm_oam_hash_data_t *h_data_p) 19564 { 19565 int rv = BCM_E_NONE; 19566 #if defined(BCM_KATANA2_SUPPORT) && defined(BCM_MPLS_SUPPORT) 19567 mpls_entry_entry_t mpls_entry; 19568 mpls_entry_entry_t mpls_key; 19569 int mpls_index = 0; 19570 #endif /* BCM_KATANA2_SUPPORT && BCM_MPLS_SUPPORT */ 19571 19572 19573 switch(h_data_p->type) { 19574 case bcmOAMEndpointTypeBHHMPLS: 19575 case bcmOAMEndpointTypeBHHMPLSVccv: 19576 #if defined(BCM_KATANA2_SUPPORT) && defined(BCM_MPLS_SUPPORT) 19577 SOC_IF_ERROR_RETURN(bcm_tr_mpls_lock (unit)); 19578 19579 sal_memset(&mpls_key, 0, sizeof(mpls_key)); 19580 soc_MPLS_ENTRYm_field32_set(unit, &mpls_key, 19581 MPLS__MPLS_LABELf, h_data_p->label); 19582 19583 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &mpls_index, 19584 &mpls_key, &mpls_entry, 0); 19585 /* It can so happen that this function is called when the switch is 19586 re-initailizing, then MPLS ENTRY will not be found, as MPLS init 19587 happens before OAM init and it would have cleared the MPLS Entry, as 19588 such its not an error scenario. Hence dont return failure from here.*/ 19589 19590 if (BCM_SUCCESS(rv)) { 19591 if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf) == 0x1)) 19592 { 19593 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, 19594 MPLS__BFD_ENABLEf, 0); 19595 rv = soc_mem_write(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, 19596 mpls_index, &mpls_entry); 19597 if (BCM_FAILURE(rv)) { 19598 LOG_ERROR(BSL_LS_BCM_OAM, 19599 (BSL_META_U(unit, 19600 "OAM Error: MPLS_ENTRY write failed - " 19601 "%s.\n"), bcm_errmsg(rv))); 19602 bcm_tr_mpls_unlock(unit); 19603 return (rv); 19604 } 19605 } 19606 } 19607 bcm_tr_mpls_unlock (unit); 19608 #endif /* BCM_KATANA2_SUPPORT && BCM_MPLS_SUPPORT */ 19609 break; 19610 19611 default: 19612 break; 19613 } 19614 19615 return (rv); 19616 } 19617 19618 /* 19619 * Function: 19620 * _bcm_kt2_oam_bhh_msg_send_receive 19621 * Purpose: 19622 * Sends given BHH control message to the uController. 19623 * Receives and verifies expected reply. 19624 * Performs DMA operation if required. 19625 * Parameters: 19626 * unit - (IN) Unit number. 19627 * s_subclass - (IN) BHH message subclass. 19628 * s_len - (IN) Value for 'len' field in message struct. 19629 * Length of buffer to flush if DMA send is required. 19630 * s_data - (IN) Value for 'data' field in message struct. 19631 * Ignored if message requires a DMA send/receive 19632 * operation. 19633 * r_subclass - (IN) Expected reply message subclass. 19634 * r_len - (OUT) Returns value in 'len' reply message field. 19635 * Returns: 19636 * BCM_E_XXX 19637 * Notes: 19638 * - The uc_msg 'len' and 'data' fields of mos_msg_data_t 19639 * can take any arbitrary data. 19640 * 19641 * BHH Long Control message: 19642 * - BHH control messages that require send/receive of information 19643 * that cannot fit in the uc_msg 'len' and 'data' fields need to 19644 * use DMA operations to exchange information (long control message). 19645 * 19646 * - BHH convention for long control messages for 19647 * 'mos_msg_data_t' fields: 19648 * 'len' size of the DMA buffer to send to uController 19649 * 'data' physical DMA memory address to send or receive 19650 * 19651 * DMA Operations: 19652 * - DMA read/write operation is performed when a long BHH control 19653 * message is involved. 19654 * 19655 * - Messages that require DMA operation (long control message) 19656 * is indicated by MOS_MSG_DMA_MSG(). 19657 * 19658 * - Callers must 'pack' and 'unpack' corresponding information 19659 * into/from DMA buffer indicated by BHH_INFO(unit)->dma_buffer. 19660 */ 19661 STATIC int 19662 _bcm_kt2_oam_bhh_msg_send_receive(int unit, uint8 s_subclass, 19663 uint16 s_len, uint32 s_data, 19664 uint8 r_subclass, uint16 *r_len) 19665 { 19666 int rv; 19667 _bcm_oam_control_t *oc; 19668 mos_msg_data_t send, reply; 19669 uint8 *dma_buffer; 19670 int dma_buffer_len; 19671 uint32 uc_rv; 19672 19673 /* Lock already taken by the calling routine. */ 19674 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 19675 19676 sal_memset(&send, 0, sizeof(send)); 19677 sal_memset(&reply, 0, sizeof(reply)); 19678 send.s.mclass = MOS_MSG_CLASS_BHH; 19679 send.s.subclass = s_subclass; 19680 send.s.len = bcm_htons(s_len); 19681 19682 /* 19683 * Set 'data' to DMA buffer address if a DMA operation is 19684 * required for send or receive. 19685 */ 19686 dma_buffer = oc->dma_buffer; 19687 dma_buffer_len = oc->dma_buffer_len; 19688 if (MOS_MSG_DMA_MSG(s_subclass) || 19689 MOS_MSG_DMA_MSG(r_subclass)) { 19690 send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer)); 19691 } else { 19692 send.s.data = bcm_htonl(s_data); 19693 } 19694 19695 /* Flush DMA memory */ 19696 if (MOS_MSG_DMA_MSG(s_subclass)) { 19697 soc_cm_sflush(unit, dma_buffer, s_len); 19698 } 19699 19700 /* Invalidate DMA memory to read */ 19701 if (MOS_MSG_DMA_MSG(r_subclass)) { 19702 soc_cm_sinval(unit, dma_buffer, dma_buffer_len); 19703 } 19704 19705 rv = soc_cmic_uc_msg_send_receive(unit, oc->uc_num, 19706 &send, &reply, 19707 _BHH_UC_MSG_TIMEOUT_USECS); 19708 19709 /* Check reply class, subclass */ 19710 if ((rv != SOC_E_NONE) || 19711 (reply.s.mclass != MOS_MSG_CLASS_BHH) || 19712 (reply.s.subclass != r_subclass)) { 19713 return (BCM_E_INTERNAL); 19714 } 19715 19716 /* Convert BHH uController error code to BCM */ 19717 uc_rv = bcm_ntohl(reply.s.data); 19718 switch(uc_rv) { 19719 case SHR_BHH_UC_E_NONE: 19720 rv = BCM_E_NONE; 19721 break; 19722 case SHR_BHH_UC_E_INTERNAL: 19723 rv = BCM_E_INTERNAL; 19724 break; 19725 case SHR_BHH_UC_E_MEMORY: 19726 rv = BCM_E_MEMORY; 19727 break; 19728 case SHR_BHH_UC_E_PARAM: 19729 rv = BCM_E_PARAM; 19730 break; 19731 case SHR_BHH_UC_E_RESOURCE: 19732 rv = BCM_E_RESOURCE; 19733 break; 19734 case SHR_BHH_UC_E_EXISTS: 19735 rv = BCM_E_EXISTS; 19736 break; 19737 case SHR_BHH_UC_E_NOT_FOUND: 19738 rv = BCM_E_NOT_FOUND; 19739 break; 19740 case SHR_BHH_UC_E_INIT: 19741 rv = BCM_E_INIT; 19742 break; 19743 default: 19744 rv = BCM_E_INTERNAL; 19745 break; 19746 } 19747 19748 *r_len = bcm_ntohs(reply.s.len); 19749 19750 return (rv); 19751 } 19752 19753 /* 19754 * Function: 19755 * _bcm_kt2_oam_bhh_callback_thread 19756 * Purpose: 19757 * Thread to listen for event messages from uController. 19758 * Parameters: 19759 * param - Pointer to BFD info structure. 19760 * Returns: 19761 * None 19762 */ 19763 STATIC void 19764 _bcm_kt2_oam_bhh_callback_thread(void *param) 19765 { 19766 int rv; 19767 _bcm_oam_control_t *oc = (_bcm_oam_control_t *)param; 19768 bcm_oam_event_types_t events; 19769 bcm_oam_event_type_t event_type; 19770 bhh_msg_event_t event_msg; 19771 int sess_id; 19772 uint32 event_mask, flags = 0; 19773 _bcm_oam_event_handler_t *event_handler_p; 19774 _bcm_oam_hash_data_t *h_data_p; 19775 int ep_id = 0; 19776 char thread_name[SAL_THREAD_NAME_MAX_LEN]; 19777 19778 thread_name[0] = 0; 19779 sal_thread_name(oc->event_thread_id, thread_name, sizeof (thread_name)); 19780 19781 while (1) { 19782 /* Wait on notifications from uController */ 19783 rv = soc_cmic_uc_msg_receive(oc->unit, oc->uc_num, 19784 MOS_MSG_CLASS_BHH_EVENT, &event_msg, 19785 sal_sem_FOREVER); 19786 19787 if (BCM_FAILURE(rv)) { 19788 break; /* Thread exit */ 19789 } 19790 19791 event_handler_p = oc->event_handler_list_p; 19792 /* Get data from event message */ 19793 sess_id = (int)bcm_ntohs(event_msg.s.len); 19794 ep_id = BCM_OAM_BHH_GET_SDK_EP(sess_id); 19795 19796 if (sess_id < 0 || 19797 sess_id >= oc->ep_count) { 19798 LOG_CLI((BSL_META_U(oc->unit, 19799 "Invalid sess_id:%d \n"), sess_id)); 19800 continue; 19801 } 19802 /* Check endpoint status. */ 19803 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 19804 if ((BCM_E_EXISTS != rv)) { 19805 /* Endpoint not in use. */ 19806 LOG_ERROR(BSL_LS_BCM_OAM, 19807 (BSL_META_U(oc->unit, 19808 "OAM Error: Endpoint EP=%d %s.\n"), 19809 ep_id, bcm_errmsg(rv))); 19810 } 19811 h_data_p = &oc->oam_hash_data[ep_id]; 19812 event_mask = bcm_ntohl(event_msg.s.data); 19813 19814 19815 /* Set events */ 19816 sal_memset(&events, 0, sizeof(events)); 19817 19818 if (event_mask & BHH_BTE_EVENT_LB_TIMEOUT) { 19819 LOG_DEBUG(BSL_LS_BCM_OAM, 19820 (BSL_META_U(oc->unit, 19821 "****** OAM BHH LB Timeout ******\n"))); 19822 19823 if (oc->event_handler_cnt[bcmOAMEventBHHLBTimeout] > 0) 19824 SHR_BITSET(events.w, bcmOAMEventBHHLBTimeout); 19825 } 19826 if (event_mask & BHH_BTE_EVENT_LB_DISCOVERY_UPDATE) { 19827 LOG_DEBUG(BSL_LS_BCM_OAM, 19828 (BSL_META_U(oc->unit, 19829 "****** OAM BHH LB Discovery Update ******\n"))); 19830 if (oc->event_handler_cnt[bcmOAMEventBHHLBDiscoveryUpdate] > 0) 19831 SHR_BITSET(events.w, bcmOAMEventBHHLBDiscoveryUpdate); 19832 } 19833 if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT) { 19834 LOG_DEBUG(BSL_LS_BCM_OAM, 19835 (BSL_META_U(oc->unit, 19836 "****** OAM BHH CCM Timeout ******\n"))); 19837 if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeout] > 0) 19838 SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeout); 19839 } 19840 if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR) { 19841 LOG_DEBUG(BSL_LS_BCM_OAM, 19842 (BSL_META_U(oc->unit, 19843 "****** OAM BHH CCM Timeout Clear ******\n"))); 19844 if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeoutClear] > 0) 19845 SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeoutClear); 19846 } 19847 if (event_mask & BHH_BTE_EVENT_STATE) { 19848 LOG_DEBUG(BSL_LS_BCM_OAM, 19849 (BSL_META_U(oc->unit, 19850 "****** OAM BHH State ******\n"))); 19851 if (oc->event_handler_cnt[bcmOAMEventBHHCCMState] > 0) 19852 SHR_BITSET(events.w, bcmOAMEventBHHCCMState); 19853 } 19854 19855 if (event_mask & BHH_BTE_EVENT_CCM_RDI) { 19856 LOG_DEBUG(BSL_LS_BCM_OAM, 19857 (BSL_META_U(oc->unit, 19858 "****** OAM BHH CCM RDI ******\n"))); 19859 if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdi] > 0) 19860 SHR_BITSET(events.w, bcmOAMEventBHHCCMRdi); 19861 } 19862 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL) { 19863 LOG_DEBUG(BSL_LS_BCM_OAM, 19864 (BSL_META_U(oc->unit, 19865 "****** OAM BHH CCM Unknown MEG LEVEL ******\n"))); 19866 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevel] > 0) 19867 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevel); 19868 } 19869 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID) { 19870 LOG_DEBUG(BSL_LS_BCM_OAM, 19871 (BSL_META_U(oc->unit, 19872 "****** OAM BHH CCM Unknown MEG ID ******\n"))); 19873 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegId] > 0) 19874 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegId); 19875 } 19876 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID) { 19877 LOG_DEBUG(BSL_LS_BCM_OAM, 19878 (BSL_META_U(oc->unit, 19879 "****** OAM BHH CCM Unknown MEP ID ******\n"))); 19880 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepId] > 0) 19881 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepId); 19882 } 19883 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD) { 19884 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriod] > 0) 19885 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriod); 19886 } 19887 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY) { 19888 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriority] > 0) 19889 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriority); 19890 } 19891 if (event_mask & BHH_BTE_EVENT_CCM_RDI_CLEAR) { 19892 if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdiClear] > 0) 19893 SHR_BITSET(events.w, bcmOAMEventBHHCCMRdiClear); 19894 } 19895 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR) { 19896 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevelClear] > 0) 19897 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevelClear); 19898 } 19899 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR) { 19900 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegIdClear] > 0) 19901 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegIdClear); 19902 } 19903 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR) { 19904 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepIdClear] > 0) 19905 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepIdClear); 19906 } 19907 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR) { 19908 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriodClear] > 0) 19909 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriodClear); 19910 } 19911 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR) { 19912 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriorityClear] > 0) 19913 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriorityClear); 19914 } 19915 if (event_mask & BHH_BTE_EVENT_CSF_LOS) { 19916 if (oc->event_handler_cnt[bcmOAMEventCsfLos] > 0) { 19917 SHR_BITSET(events.w, bcmOAMEventCsfLos); 19918 } 19919 } 19920 if (event_mask & BHH_BTE_EVENT_CSF_FDI) { 19921 if (oc->event_handler_cnt[bcmOAMEventCsfFdi] > 0) { 19922 SHR_BITSET(events.w, bcmOAMEventCsfFdi); 19923 } 19924 } 19925 if (event_mask & BHH_BTE_EVENT_CSF_RDI) { 19926 if (oc->event_handler_cnt[bcmOAMEventCsfRdi] > 0) { 19927 SHR_BITSET(events.w, bcmOAMEventCsfRdi); 19928 } 19929 } 19930 if (event_mask & BHH_BTE_EVENT_CSF_DCI) { 19931 if (oc->event_handler_cnt[bcmOAMEventCsfDci] > 0) { 19932 SHR_BITSET(events.w, bcmOAMEventCsfDci); 19933 } 19934 } 19935 if (event_mask & BHH_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER) { 19936 LOG_DEBUG(BSL_LS_BCM_OAM, 19937 (BSL_META_U(oc->unit, 19938 "****** OAM PM BHH Counter Rollover ******\n"))); 19939 19940 if (oc->event_handler_cnt[bcmOAMEventBhhPmCounterRollover] > 0) { 19941 SHR_BITSET(events.w, bcmOAMEventBhhPmCounterRollover); 19942 } 19943 } 19944 /* Loop over registered callbacks, 19945 * If any match the events field, then invoke 19946 */ 19947 for (event_handler_p = oc->event_handler_list_p; 19948 event_handler_p != NULL; 19949 event_handler_p = event_handler_p->next_p) { 19950 for (event_type = bcmOAMEventBHHLBTimeout; event_type < bcmOAMEventCount; ++event_type) { 19951 if (SHR_BITGET(events.w, event_type)) { 19952 if (SHR_BITGET(event_handler_p->event_types.w, 19953 event_type)) { 19954 event_handler_p->cb(oc->unit, 19955 flags, 19956 event_type, 19957 h_data_p->group_index, /* Group index */ 19958 ep_id, /* Endpoint index */ 19959 event_handler_p->user_data); 19960 } 19961 } 19962 } 19963 } 19964 } 19965 19966 oc->event_thread_id = NULL; 19967 LOG_VERBOSE(BSL_LS_BCM_OAM, 19968 (BSL_META_U(oc->unit, 19969 "Thread Exit:%s\n"), thread_name)); 19970 sal_thread_exit(0); 19971 } 19972 19973 /* BHH Event Handler */ 19974 typedef struct _event_handler_s { 19975 struct _event_handler_s *next; 19976 bcm_oam_event_types_t event_types; 19977 bcm_oam_event_cb cb; 19978 void *user_data; 19979 } _event_handler_t; 19980 19981 /* 19982 * Function: 19983 * _bcm_kt2_oam_bhh_event_mask_set 19984 * Purpose: 19985 * Set the BHH Events mask. 19986 * Events are set per BHH module. 19987 * Parameters: 19988 * unit - (IN) Unit number. 19989 * Returns: 19990 * BCM_E_NONE Operation completed successfully 19991 * BCM_E_XXX Operation failed 19992 * Notes: 19993 */ 19994 STATIC int 19995 _bcm_kt2_oam_bhh_event_mask_set(int unit) 19996 { 19997 _bcm_oam_control_t *oc; 19998 _bcm_oam_event_handler_t *event_handler_p; 19999 uint32 event_mask = 0; 20000 uint16 reply_len; 20001 int rv = BCM_E_NONE; 20002 20003 /* Lock already taken by the calling routine. */ 20004 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 20005 20006 /* Get event mask from all callbacks */ 20007 for (event_handler_p = oc->event_handler_list_p; 20008 event_handler_p != NULL; 20009 event_handler_p = event_handler_p->next_p) { 20010 20011 if (SHR_BITGET(event_handler_p->event_types.w, 20012 bcmOAMEventBHHLBTimeout)) { 20013 event_mask |= BHH_BTE_EVENT_LB_TIMEOUT; 20014 } 20015 if (SHR_BITGET(event_handler_p->event_types.w, 20016 bcmOAMEventBHHLBDiscoveryUpdate)) { 20017 event_mask |= BHH_BTE_EVENT_LB_DISCOVERY_UPDATE; 20018 } 20019 if (SHR_BITGET(event_handler_p->event_types.w, 20020 bcmOAMEventBHHCCMTimeout)) { 20021 event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT; 20022 } 20023 if (SHR_BITGET(event_handler_p->event_types.w, 20024 bcmOAMEventBHHCCMTimeoutClear)) { 20025 event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR; 20026 } 20027 if (SHR_BITGET(event_handler_p->event_types.w, 20028 bcmOAMEventBHHCCMState)) { 20029 event_mask |= BHH_BTE_EVENT_STATE; 20030 } 20031 if (SHR_BITGET(event_handler_p->event_types.w, 20032 bcmOAMEventBHHCCMRdi)) { 20033 event_mask |= BHH_BTE_EVENT_CCM_RDI; 20034 } 20035 if (SHR_BITGET(event_handler_p->event_types.w, 20036 bcmOAMEventBHHCCMUnknownMegLevel)) { 20037 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL; 20038 } 20039 if (SHR_BITGET(event_handler_p->event_types.w, 20040 bcmOAMEventBHHCCMUnknownMegId)) { 20041 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID; 20042 } 20043 if (SHR_BITGET(event_handler_p->event_types.w, 20044 bcmOAMEventBHHCCMUnknownMepId)) { 20045 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID; 20046 } 20047 if (SHR_BITGET(event_handler_p->event_types.w, 20048 bcmOAMEventBHHCCMUnknownPeriod)) { 20049 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD; 20050 } 20051 if (SHR_BITGET(event_handler_p->event_types.w, 20052 bcmOAMEventBHHCCMUnknownPriority)) { 20053 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY; 20054 } 20055 if (SHR_BITGET(event_handler_p->event_types.w, 20056 bcmOAMEventBHHCCMRdiClear)) { 20057 event_mask |= BHH_BTE_EVENT_CCM_RDI_CLEAR; 20058 } 20059 if (SHR_BITGET(event_handler_p->event_types.w, 20060 bcmOAMEventBHHCCMUnknownMegLevelClear)) { 20061 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR; 20062 } 20063 if (SHR_BITGET(event_handler_p->event_types.w, 20064 bcmOAMEventBHHCCMUnknownMegIdClear)) { 20065 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR; 20066 } 20067 if (SHR_BITGET(event_handler_p->event_types.w, 20068 bcmOAMEventBHHCCMUnknownMepIdClear)) { 20069 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR; 20070 } 20071 if (SHR_BITGET(event_handler_p->event_types.w, 20072 bcmOAMEventBHHCCMUnknownPeriodClear)) { 20073 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR; 20074 } 20075 if (SHR_BITGET(event_handler_p->event_types.w, 20076 bcmOAMEventBHHCCMUnknownPriorityClear)) { 20077 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR; 20078 } 20079 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfLos)) { 20080 event_mask |= BHH_BTE_EVENT_CSF_LOS; 20081 } 20082 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfFdi)) { 20083 event_mask |= BHH_BTE_EVENT_CSF_FDI; 20084 } 20085 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfRdi)) { 20086 event_mask |= BHH_BTE_EVENT_CSF_RDI; 20087 } 20088 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfDci)) { 20089 event_mask |= BHH_BTE_EVENT_CSF_DCI; 20090 } 20091 if (SHR_BITGET(event_handler_p->event_types.w, 20092 bcmOAMEventBhhPmCounterRollover)) { 20093 event_mask |= BHH_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER; 20094 } 20095 } 20096 20097 /* Update BHH event mask in uKernel */ 20098 if (event_mask != oc->event_mask) { 20099 /* Send BHH Event Mask message to uC */ 20100 rv = _bcm_kt2_oam_bhh_msg_send_receive 20101 (unit, 20102 MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET, 20103 0, event_mask, 20104 MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET_REPLY, 20105 &reply_len); 20106 20107 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 20108 rv = BCM_E_INTERNAL; 20109 } 20110 } 20111 20112 oc->event_mask = event_mask; 20113 20114 return (rv); 20115 } 20116 20117 /* 20118 * Function: 20119 * bcm_kt2_oam_loopback_add 20120 * Purpose: 20121 * 20122 * Parameters: 20123 * unit - Device unit number 20124 * Returns: 20125 * None 20126 */ 20127 int 20128 bcm_kt2_oam_loopback_add(int unit, bcm_oam_loopback_t *loopback_p) 20129 { 20130 _bcm_oam_control_t *oc; 20131 _bcm_oam_hash_data_t *h_data_p; 20132 int rv = BCM_E_NONE; 20133 bhh_sdk_msg_ctrl_loopback_add_t msg; 20134 uint8 *buffer, *buffer_ptr; 20135 uint16 buffer_len, reply_len; 20136 uint32 flags = 0; 20137 int sess_id = 0; 20138 20139 /* Get OAM Control Structure. */ 20140 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 20141 _BCM_OAM_LOCK(oc); 20142 20143 if (oc->ukernel_not_ready) { 20144 _BCM_OAM_UNLOCK(oc); 20145 return BCM_E_INIT; 20146 } 20147 20148 20149 BCM_OAM_BHH_VALIDATE_EP(loopback_p->id); 20150 20151 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id); 20152 20153 /* Check endpoint status. */ 20154 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 20155 if ((BCM_E_EXISTS != rv)) { 20156 /* Endpoint not in use. */ 20157 LOG_ERROR(BSL_LS_BCM_OAM, 20158 (BSL_META_U(unit, 20159 "OAM Error: Endpoint EP=%d %s.\n"), 20160 loopback_p->id, bcm_errmsg(rv))); 20161 _BCM_OAM_UNLOCK(oc); 20162 return (rv); 20163 } 20164 20165 h_data_p = &oc->oam_hash_data[loopback_p->id]; 20166 if (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU) { 20167 _BCM_OAM_UNLOCK(oc); 20168 return BCM_E_PARAM; 20169 } 20170 20171 20172 /* 20173 * Only BHH is supported 20174 */ 20175 if (BHH_EP_TYPE(h_data_p)) { 20176 20177 /* 20178 * Convert host space flags to uKernel space flags 20179 */ 20180 20181 if (loopback_p->flags & BCM_OAM_LOOPBACK_TX_ENABLE) { 20182 flags |= BCM_BHH_TX_ENABLE; 20183 } 20184 20185 if (loopback_p->flags & BCM_OAM_BHH_INC_REQUESTING_MEP_TLV) { 20186 flags |= BCM_BHH_INC_REQUESTING_MEP_TLV; 20187 } 20188 20189 if (loopback_p->flags & BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) { 20190 flags |= BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV; 20191 } else if (loopback_p->flags & BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) { 20192 flags |= BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV; 20193 } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MEP_TLV) { 20194 flags |= BCM_BHH_LBM_ICC_MEP_TLV; 20195 } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MIP_TLV) { 20196 flags |= BCM_BHH_LBM_ICC_MIP_TLV; 20197 } else { 20198 flags |= BCM_BHH_LBM_ICC_MEP_TLV; /* Default */ 20199 } 20200 20201 if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MEP_TLV) { 20202 flags |= BCM_BHH_LBR_ICC_MEP_TLV; 20203 } else if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MIP_TLV) { 20204 flags |= BCM_BHH_LBR_ICC_MIP_TLV; 20205 } 20206 20207 sal_memset(&msg, 0, sizeof(msg)); 20208 msg.flags = flags; 20209 msg.sess_id = sess_id; 20210 msg.int_pri = loopback_p->int_pri; 20211 msg.pkt_pri = loopback_p->pkt_pri; 20212 20213 /* 20214 * Set period 20215 */ 20216 msg.period = _kt2_ccm_intervals[ 20217 _bcm_kt2_oam_ccm_msecs_to_hw_encode( 20218 loopback_p->period)]; 20219 20220 /* 20221 * Check TTL 20222 */ 20223 if (loopback_p->ttl == 0 || loopback_p->ttl > 255) { 20224 _BCM_OAM_UNLOCK(oc); 20225 return BCM_E_PARAM; 20226 } 20227 20228 if (BHH_EP_MPLS_SECTION_TYPE(h_data_p) || 20229 (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv && 20230 h_data_p->vccv_type == bcmOamBhhVccvTtl)) { 20231 20232 msg.ttl = 1; /* Only TTL 1 is valid */ 20233 } else { 20234 msg.ttl = loopback_p->ttl; 20235 } 20236 20237 /* Pack control message data into DMA buffer */ 20238 buffer = oc->dma_buffer; 20239 buffer_ptr = bhh_sdk_msg_ctrl_loopback_add_pack(buffer, &msg); 20240 buffer_len = buffer_ptr - buffer; 20241 20242 /* Send BHH Session Update message to uC */ 20243 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 20244 MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD, 20245 buffer_len, 0, 20246 MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD_REPLY, 20247 &reply_len); 20248 20249 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 20250 rv = BCM_E_INTERNAL; 20251 } 20252 } 20253 else { 20254 rv = BCM_E_UNAVAIL; 20255 } 20256 20257 _BCM_OAM_UNLOCK(oc); 20258 return (rv); 20259 } 20260 20261 /* 20262 * Function: 20263 * bcm_kt2_oam_loopback_get 20264 * Purpose: 20265 * 20266 * Parameters: 20267 * unit - Device unit number 20268 * Returns: 20269 * None 20270 */ 20271 int 20272 bcm_kt2_oam_loopback_get(int unit, bcm_oam_loopback_t *loopback_p) 20273 { 20274 _bcm_oam_control_t *oc; 20275 int rv = BCM_E_NONE; 20276 bhh_sdk_msg_ctrl_loopback_get_t msg; 20277 _bcm_oam_hash_data_t *h_data_p; 20278 uint8 *buffer, *buffer_ptr; 20279 uint16 buffer_len, reply_len; 20280 int sess_id = 0; 20281 20282 /* Get OAM Control Structure. */ 20283 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 20284 _BCM_OAM_LOCK(oc); 20285 20286 if (oc->ukernel_not_ready) { 20287 _BCM_OAM_UNLOCK(oc); 20288 return BCM_E_INIT; 20289 } 20290 20291 20292 BCM_OAM_BHH_VALIDATE_EP(loopback_p->id); 20293 20294 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id); 20295 20296 /* Check endpoint status. */ 20297 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 20298 if ((BCM_E_EXISTS != rv)) { 20299 /* Endpoint not in use. */ 20300 LOG_ERROR(BSL_LS_BCM_OAM, 20301 (BSL_META_U(unit, 20302 "OAM Error: Endpoint EP=%d %s.\n"), 20303 loopback_p->id, bcm_errmsg(rv))); 20304 _BCM_OAM_UNLOCK(oc); 20305 return (rv); 20306 } 20307 20308 h_data_p = &oc->oam_hash_data[loopback_p->id]; 20309 20310 /* 20311 * Only BHH is supported 20312 */ 20313 if(BHH_EP_TYPE(h_data_p)) { 20314 20315 sal_memset(&msg, 0, sizeof(msg)); 20316 /* Send BHH Session Update message to uC */ 20317 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 20318 MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET, 20319 sess_id, 0, 20320 MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET_REPLY, 20321 &reply_len); 20322 if(BCM_FAILURE(rv)) { 20323 LOG_ERROR(BSL_LS_BCM_OAM, 20324 (BSL_META_U(unit, 20325 "OAM Error: Endpoint EP=%d %s.\n"), 20326 loopback_p->id, bcm_errmsg(rv))); 20327 _BCM_OAM_UNLOCK(oc); 20328 return (rv); 20329 } 20330 20331 /* Pack control message data into DMA buffer */ 20332 buffer = oc->dma_buffer; 20333 buffer_ptr = bhh_sdk_msg_ctrl_loopback_get_unpack(buffer, &msg); 20334 buffer_len = buffer_ptr - buffer; 20335 20336 20337 if (reply_len != buffer_len) { 20338 rv = BCM_E_INTERNAL; 20339 } else { 20340 /* 20341 * Convert kernel space flags to host space flags 20342 */ 20343 if (msg.flags & BCM_BHH_INC_REQUESTING_MEP_TLV) { 20344 loopback_p->flags |= BCM_OAM_BHH_INC_REQUESTING_MEP_TLV; 20345 } 20346 20347 if (msg.flags & BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) { 20348 loopback_p->flags |= BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV; 20349 } else if (msg.flags & BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) { 20350 loopback_p->flags |= BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV; 20351 } else if (msg.flags & BCM_BHH_LBM_ICC_MEP_TLV) { 20352 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MEP_TLV; 20353 } else if (msg.flags & BCM_BHH_LBM_ICC_MIP_TLV) { 20354 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MIP_TLV; 20355 } 20356 20357 if (msg.flags & BCM_BHH_LBR_ICC_MEP_TLV) { 20358 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MEP_TLV; 20359 } else if (msg.flags & BCM_BHH_LBR_ICC_MIP_TLV) { 20360 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MIP_TLV; 20361 } 20362 20363 if (msg.flags & BCM_BHH_TX_ENABLE) { 20364 loopback_p->flags |= BCM_OAM_LOOPBACK_TX_ENABLE; 20365 } 20366 20367 loopback_p->period = msg.period; 20368 loopback_p->ttl = msg.ttl; 20369 loopback_p->discovered_me.flags = msg.discovery_flags; 20370 loopback_p->discovered_me.name = msg.discovery_id; 20371 loopback_p->discovered_me.ttl = msg.discovery_ttl; 20372 loopback_p->rx_count = msg.rx_count; 20373 loopback_p->tx_count = msg.tx_count; 20374 loopback_p->drop_count = msg.drop_count; 20375 loopback_p->unexpected_response = msg.unexpected_response; 20376 loopback_p->out_of_sequence = msg.out_of_sequence; 20377 loopback_p->local_mipid_missmatch = msg.local_mipid_missmatch; 20378 loopback_p->remote_mipid_missmatch = msg.remote_mipid_missmatch; 20379 loopback_p->invalid_target_mep_tlv = msg.invalid_target_mep_tlv; 20380 loopback_p->invalid_mep_tlv_subtype = msg.invalid_mep_tlv_subtype; 20381 loopback_p->invalid_tlv_offset = msg.invalid_tlv_offset; 20382 loopback_p->int_pri = msg.int_pri; 20383 loopback_p->pkt_pri = msg.pkt_pri; 20384 20385 rv = BCM_E_NONE; 20386 } 20387 } 20388 else { 20389 rv = BCM_E_UNAVAIL; 20390 } 20391 20392 _BCM_OAM_UNLOCK(oc); 20393 20394 return (rv); 20395 } 20396 20397 /* 20398 * Function: 20399 * bcm_kt2_oam_loopback_delete 20400 * Purpose: 20401 * 20402 * Parameters: 20403 * unit - Device unit number 20404 * Returns: 20405 * None 20406 */ 20407 int 20408 bcm_kt2_oam_loopback_delete(int unit, bcm_oam_loopback_t *loopback_p) 20409 { 20410 _bcm_oam_control_t *oc; 20411 int rv = BCM_E_NONE; 20412 shr_bhh_msg_ctrl_loopback_delete_t msg; 20413 uint8 *buffer, *buffer_ptr; 20414 uint16 buffer_len, reply_len; 20415 int sess_id = 0; 20416 _bcm_oam_hash_data_t *h_data_p; 20417 20418 /* Get OAM Control Structure. */ 20419 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 20420 _BCM_OAM_LOCK(oc); 20421 20422 if (oc->ukernel_not_ready) { 20423 _BCM_OAM_UNLOCK(oc); 20424 return BCM_E_INIT; 20425 } 20426 20427 20428 BCM_OAM_BHH_VALIDATE_EP(loopback_p->id); 20429 20430 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id); 20431 20432 /* Check endpoint status. */ 20433 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 20434 if ((BCM_E_EXISTS != rv)) { 20435 /* Endpoint not in use. */ 20436 LOG_ERROR(BSL_LS_BCM_OAM, 20437 (BSL_META_U(unit, 20438 "OAM Error: Endpoint EP=%d %s.\n"), 20439 loopback_p->id, bcm_errmsg(rv))); 20440 _BCM_OAM_UNLOCK(oc); 20441 return (rv); 20442 } 20443 20444 h_data_p = &oc->oam_hash_data[loopback_p->id]; 20445 20446 /* 20447 * Only BHH is supported 20448 */ 20449 if(BHH_EP_TYPE(h_data_p)) { 20450 20451 msg.sess_id = sess_id; 20452 20453 /* Pack control message data into DMA buffer */ 20454 buffer = oc->dma_buffer; 20455 buffer_ptr = shr_bhh_msg_ctrl_loopback_delete_pack(buffer, &msg); 20456 buffer_len = buffer_ptr - buffer; 20457 20458 /* Send BHH Session Update message to uC */ 20459 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 20460 MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE, 20461 buffer_len, 0, 20462 MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE_REPLY, 20463 &reply_len); 20464 20465 if(BCM_SUCCESS(rv) && (reply_len != 0)) 20466 rv = BCM_E_INTERNAL; 20467 } 20468 else { 20469 _BCM_OAM_UNLOCK(oc); 20470 return BCM_E_UNAVAIL; 20471 } 20472 20473 _BCM_OAM_UNLOCK(oc); 20474 20475 return (rv); 20476 } 20477 20478 /* 20479 * Function: 20480 * bcm_kt2_oam_loss_add 20481 * Purpose: 20482 * Loss Measurement add 20483 * Parameters: 20484 * unit - Device unit number 20485 * Returns: 20486 * None 20487 */ 20488 int 20489 bcm_kt2_oam_loss_add(int unit, bcm_oam_loss_t *loss_p) 20490 { 20491 _bcm_oam_control_t *oc; 20492 _bcm_oam_hash_data_t *h_data_p; 20493 int rv = BCM_E_NONE; 20494 bhh_sdk_msg_ctrl_loss_add_t msg; 20495 uint8 *buffer, *buffer_ptr; 20496 uint16 buffer_len, reply_len; 20497 uint32 flags = 0; 20498 int sess_id = 0; 20499 20500 /* Get OAM Control Structure. */ 20501 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 20502 _BCM_OAM_LOCK(oc); 20503 20504 if (oc->ukernel_not_ready) { 20505 _BCM_OAM_UNLOCK(oc); 20506 return BCM_E_INIT; 20507 } 20508 20509 20510 BCM_OAM_BHH_VALIDATE_EP(loss_p->id); 20511 20512 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id); 20513 20514 /* Check endpoint status. */ 20515 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 20516 if ((BCM_E_EXISTS != rv)) { 20517 /* Endpoint not in use. */ 20518 LOG_ERROR(BSL_LS_BCM_OAM, 20519 (BSL_META_U(unit, 20520 "OAM Error: Endpoint EP=%d %s.\n"), 20521 loss_p->id, bcm_errmsg(rv))); 20522 _BCM_OAM_UNLOCK(oc); 20523 return (rv); 20524 } 20525 20526 h_data_p = &oc->oam_hash_data[loss_p->id]; 20527 if (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU) { 20528 _BCM_OAM_UNLOCK(oc); 20529 return BCM_E_PARAM; 20530 } 20531 20532 /* 20533 * Only BHH is supported 20534 */ 20535 if(BHH_EP_TYPE(h_data_p)) { 20536 20537 /* 20538 * Convert host space flags to uKernel space flags 20539 */ 20540 if (loss_p->flags & BCM_OAM_LOSS_SINGLE_ENDED) 20541 flags |= BCM_BHH_LM_SINGLE_ENDED; 20542 20543 if (loss_p->flags & BCM_OAM_LOSS_TX_ENABLE) 20544 flags |= BCM_BHH_LM_TX_ENABLE; 20545 20546 sal_memset(&msg, 0, sizeof(msg)); 20547 msg.flags = flags; 20548 msg.sess_id = sess_id; 20549 20550 /* 20551 * Set period 20552 */ 20553 msg.period = _kt2_ccm_intervals[_bcm_kt2_oam_ccm_msecs_to_hw_encode(loss_p->period)]; 20554 msg.int_pri = loss_p->int_pri; 20555 msg.pkt_pri = loss_p->pkt_pri; 20556 20557 /* Pack control message data into DMA buffer */ 20558 buffer = oc->dma_buffer; 20559 buffer_ptr = bhh_sdk_msg_ctrl_loss_add_pack(buffer, &msg); 20560 buffer_len = buffer_ptr - buffer; 20561 20562 /* Send BHH Session Update message to uC */ 20563 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 20564 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD, 20565 buffer_len, 0, 20566 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD_REPLY, 20567 &reply_len); 20568 20569 if(BCM_SUCCESS(rv) && (reply_len != 0)) 20570 rv = BCM_E_INTERNAL; 20571 } 20572 else { 20573 _BCM_OAM_UNLOCK(oc); 20574 return BCM_E_UNAVAIL; 20575 } 20576 20577 _BCM_OAM_UNLOCK(oc); 20578 return (rv); 20579 } 20580 20581 int 20582 bcm_kt2_oam_bhh_convert_ep_to_time_spec(bcm_time_spec_t* bts, int sec, int ns) 20583 { 20584 int rv = BCM_E_NONE; 20585 20586 if (bts != NULL) { 20587 /* if both seconds and nanoseconds are negative or both positive, 20588 * then the ucode's subtraction is ok. 20589 * if seconds and nanoseconds have different signs, then "borrow" 20590 * 1000000000 nanoseconds from seconds. 20591 */ 20592 if ((sec < 0) && (ns > 0)) { 20593 ns -= 1000000000; 20594 sec += 1; 20595 } else if ((sec > 0) && (ns < 0)) { 20596 ns += 1000000000; 20597 sec -= 1; 20598 } 20599 20600 if (ns < 0) { 20601 /* if still negative, then something else is wrong. 20602 * the nanoseconds field is the difference between two 20603 * (non-negative) time-stamps. 20604 */ 20605 rv = BCM_E_INTERNAL; 20606 } 20607 20608 /* if seconds is negative then set the bts is-negative flag, 20609 * and use the absolute value of seconds & nanoseconds. 20610 */ 20611 bts->isnegative = (sec < 0 ? 1 : 0); 20612 bts->seconds = BCM_OAM_BHH_ABS(sec); 20613 bts->nanoseconds = BCM_OAM_BHH_ABS(ns); 20614 } else { 20615 rv = BCM_E_INTERNAL; 20616 } 20617 20618 return rv; 20619 } 20620 20621 #ifdef _KATANA2_DEBUG 20622 /* d (difference) = m (minuend) - s (subtrahend) */ 20623 int 20624 bcm_oam_bhh_time_spec_subtract(bcm_time_spec_t* d, bcm_time_spec_t* m, bcm_time_spec_t* s) 20625 { 20626 int rv = BCM_E_NONE; 20627 int32 d_ns = 0; 20628 int32 d_s = 0; 20629 20630 if ((d != NULL) && (m != NULL) && (s != NULL)) { 20631 /* subtract the nanoseconds first, then borrow is necessary. */ 20632 d_ns = m->nanoseconds - s->nanoseconds; 20633 if (d_ns < 0) { 20634 m->seconds = m->seconds - 1; 20635 d_ns = 1000000000 + d_ns; 20636 } 20637 if (d_ns < 0) { 20638 /* if still negative, then error */ 20639 rv = BCM_E_INTERNAL; 20640 d_ns = abs(d_ns); 20641 } 20642 d->nanoseconds = d_ns; 20643 20644 /* subtract the seconds next, check for negative. */ 20645 d_s = m->seconds - s->seconds; 20646 if (d_s < 0) { 20647 d->isnegative = TRUE; 20648 d_s = abs(d_s); 20649 } else { 20650 d->isnegative = FALSE; 20651 } 20652 d->seconds = d_s; 20653 20654 } else { 20655 rv = BCM_E_INTERNAL; 20656 } 20657 20658 return rv; 20659 } 20660 #endif 20661 20662 /* 20663 * Function: 20664 * bcm_kt2_oam_loss_get 20665 * Purpose: 20666 * Loss Measurement get 20667 * Parameters: 20668 * unit - Device unit number 20669 * Returns: 20670 * None 20671 */ 20672 int 20673 bcm_kt2_oam_loss_get(int unit, bcm_oam_loss_t *loss_p) 20674 { 20675 _bcm_oam_control_t *oc; 20676 int rv = BCM_E_NONE; 20677 bhh_sdk_msg_ctrl_loss_get_t msg; 20678 _bcm_oam_hash_data_t *h_data_p; 20679 uint8 *buffer, *buffer_ptr; 20680 uint16 buffer_len, reply_len; 20681 int sess_id = 0; 20682 20683 /* Get OAM Control Structure. */ 20684 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 20685 _BCM_OAM_LOCK(oc); 20686 20687 if (oc->ukernel_not_ready) { 20688 _BCM_OAM_UNLOCK(oc); 20689 return BCM_E_INIT; 20690 } 20691 20692 BCM_OAM_BHH_VALIDATE_EP(loss_p->id); 20693 20694 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id); 20695 20696 /* Check endpoint status. */ 20697 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 20698 if ((BCM_E_EXISTS != rv)) { 20699 /* Endpoint not in use. */ 20700 LOG_ERROR(BSL_LS_BCM_OAM, 20701 (BSL_META_U(unit, 20702 "OAM Error: Endpoint EP=%d %s.\n"), 20703 loss_p->id, bcm_errmsg(rv))); 20704 _BCM_OAM_UNLOCK(oc); 20705 return (rv); 20706 } 20707 20708 h_data_p = &oc->oam_hash_data[loss_p->id]; 20709 20710 /* 20711 * Only BHH is supported 20712 */ 20713 if(BHH_EP_TYPE(h_data_p)) { 20714 20715 sal_memset(&msg, 0, sizeof(msg)); 20716 /* Send BHH Session Update message to uC */ 20717 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 20718 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET, 20719 sess_id, 0, 20720 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET_REPLY, 20721 &reply_len); 20722 if(BCM_FAILURE(rv)) { 20723 LOG_ERROR(BSL_LS_BCM_OAM, 20724 (BSL_META_U(unit, 20725 "OAM Error: Endpoint EP=%d %s.\n"), 20726 loss_p->id, bcm_errmsg(rv))); 20727 _BCM_OAM_UNLOCK(oc); 20728 return (rv); 20729 } 20730 20731 /* Pack control message data into DMA buffer */ 20732 buffer = oc->dma_buffer; 20733 buffer_ptr = bhh_sdk_msg_ctrl_loss_get_unpack(buffer, &msg); 20734 buffer_len = buffer_ptr - buffer; 20735 20736 if (reply_len != buffer_len) { 20737 rv = BCM_E_INTERNAL; 20738 } else { 20739 /* 20740 * Convert kernel space flags to host space flags 20741 */ 20742 if (msg.flags & BCM_BHH_LM_SINGLE_ENDED) { 20743 loss_p->flags |= BCM_OAM_LOSS_SINGLE_ENDED; 20744 } 20745 20746 if (msg.flags & BCM_BHH_LM_TX_ENABLE) { 20747 loss_p->flags |= BCM_OAM_LOSS_TX_ENABLE; 20748 } 20749 20750 if (msg.flags & BCM_BHH_LM_SLM) { 20751 loss_p->flags |= BCM_OAM_LOSS_SLM; 20752 } 20753 20754 loss_p->period = msg.period; 20755 loss_p->loss_threshold = msg.loss_threshold; 20756 loss_p->loss_nearend = msg.loss_nearend; 20757 loss_p->loss_farend = msg.loss_farend; 20758 loss_p->tx_nearend = msg.tx_nearend; 20759 loss_p->rx_nearend = msg.rx_nearend; 20760 loss_p->tx_farend = msg.tx_farend; 20761 loss_p->rx_farend = msg.rx_farend; 20762 loss_p->rx_oam_packets = msg.rx_oam_packets; 20763 loss_p->tx_oam_packets = msg.tx_oam_packets; 20764 loss_p->int_pri = msg.int_pri; 20765 loss_p->pkt_pri = msg.pkt_pri; 20766 20767 rv = BCM_E_NONE; 20768 } 20769 } 20770 else { 20771 _BCM_OAM_UNLOCK(oc); 20772 return BCM_E_UNAVAIL; 20773 } 20774 20775 _BCM_OAM_UNLOCK(oc); 20776 20777 return (rv); 20778 } 20779 20780 /* 20781 * Function: 20782 * bcm_kt2_oam_loss_delete 20783 * Purpose: 20784 * Loss Measurement Delete 20785 * Parameters: 20786 * unit - Device unit number 20787 * Returns: 20788 * None 20789 */ 20790 int 20791 bcm_kt2_oam_loss_delete(int unit, bcm_oam_loss_t *loss_p) 20792 { 20793 _bcm_oam_control_t *oc; 20794 int rv = BCM_E_NONE; 20795 shr_bhh_msg_ctrl_loss_delete_t msg; 20796 uint8 *buffer, *buffer_ptr; 20797 uint16 buffer_len, reply_len; 20798 int sess_id = 0; 20799 _bcm_oam_hash_data_t *h_data_p; 20800 20801 /* Get OAM Control Structure. */ 20802 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 20803 _BCM_OAM_LOCK(oc); 20804 20805 if (oc->ukernel_not_ready) { 20806 _BCM_OAM_UNLOCK(oc); 20807 return BCM_E_INIT; 20808 } 20809 20810 BCM_OAM_BHH_VALIDATE_EP(loss_p->id); 20811 20812 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id); 20813 20814 /* Check endpoint status. */ 20815 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 20816 if ((BCM_E_EXISTS != rv)) { 20817 /* Endpoint not in use. */ 20818 LOG_ERROR(BSL_LS_BCM_OAM, 20819 (BSL_META_U(unit, 20820 "OAM Error: Endpoint EP=%d %s.\n"), 20821 loss_p->id, bcm_errmsg(rv))); 20822 _BCM_OAM_UNLOCK(oc); 20823 return (rv); 20824 } 20825 20826 h_data_p = &oc->oam_hash_data[loss_p->id]; 20827 20828 /* 20829 * Only BHH is supported 20830 */ 20831 if(BHH_EP_TYPE(h_data_p)) { 20832 20833 msg.sess_id = sess_id; 20834 20835 /* Pack control message data into DMA buffer */ 20836 buffer = oc->dma_buffer; 20837 buffer_ptr = shr_bhh_msg_ctrl_loss_delete_pack(buffer, &msg); 20838 buffer_len = buffer_ptr - buffer; 20839 20840 /* Send BHH Session Update message to uC */ 20841 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 20842 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE, 20843 buffer_len, 0, 20844 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE_REPLY, 20845 &reply_len); 20846 20847 if(BCM_SUCCESS(rv) && (reply_len != 0)) 20848 rv = BCM_E_INTERNAL; 20849 } 20850 else { 20851 _BCM_OAM_UNLOCK(oc); 20852 return BCM_E_UNAVAIL; 20853 } 20854 20855 _BCM_OAM_UNLOCK(oc); 20856 20857 return (rv); 20858 } 20859 20860 /* 20861 * Function: 20862 * bcm_kt2_oam_delay_add 20863 * Purpose: 20864 * Delay Measurement add 20865 * Parameters: 20866 * unit - Device unit number 20867 * Returns: 20868 * None 20869 */ 20870 int 20871 bcm_kt2_oam_delay_add(int unit, bcm_oam_delay_t *delay_p) 20872 { 20873 _bcm_oam_control_t *oc; 20874 _bcm_oam_hash_data_t *h_data_p; 20875 int rv = BCM_E_NONE; 20876 bhh_sdk_msg_ctrl_delay_add_t msg; 20877 uint8 *buffer, *buffer_ptr; 20878 uint16 buffer_len, reply_len; 20879 uint32 flags = 0; 20880 int sess_id = 0; 20881 20882 /* Get OAM Control Structure. */ 20883 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 20884 _BCM_OAM_LOCK(oc); 20885 20886 if (oc->ukernel_not_ready) { 20887 _BCM_OAM_UNLOCK(oc); 20888 return BCM_E_INIT; 20889 } 20890 20891 20892 BCM_OAM_BHH_VALIDATE_EP(delay_p->id); 20893 20894 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id); 20895 20896 /* Check endpoint status. */ 20897 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 20898 if ((BCM_E_EXISTS != rv)) { 20899 /* Endpoint not in use. */ 20900 LOG_ERROR(BSL_LS_BCM_OAM, 20901 (BSL_META_U(unit, 20902 "OAM Error: Endpoint EP=%d %s.\n"), 20903 delay_p->id, bcm_errmsg(rv))); 20904 _BCM_OAM_UNLOCK(oc); 20905 return (rv); 20906 } 20907 20908 h_data_p = &oc->oam_hash_data[delay_p->id]; 20909 if (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU) { 20910 _BCM_OAM_UNLOCK(oc); 20911 return BCM_E_PARAM; 20912 } 20913 20914 /* 20915 * Only BHH is supported 20916 */ 20917 if(BHH_EP_TYPE(h_data_p)) { 20918 20919 /* 20920 * Convert host space flags to uKernel space flags 20921 */ 20922 if (delay_p->flags & BCM_OAM_DELAY_ONE_WAY) 20923 flags |= BCM_BHH_DM_ONE_WAY; 20924 20925 if (delay_p->flags & BCM_OAM_DELAY_TX_ENABLE) 20926 flags |= BCM_BHH_DM_TX_ENABLE; 20927 20928 sal_memset(&msg, 0, sizeof(msg)); 20929 msg.flags = flags; 20930 msg.sess_id = sess_id; 20931 msg.int_pri = delay_p->int_pri; 20932 msg.pkt_pri = delay_p->pkt_pri; 20933 20934 h_data_p->ts_format = delay_p->timestamp_format; 20935 20936 if(delay_p->timestamp_format == bcmOAMTimestampFormatIEEE1588v1) 20937 msg.dm_format = BCM_BHH_DM_TYPE_PTP; 20938 else 20939 msg.dm_format = BCM_BHH_DM_TYPE_NTP; 20940 20941 /* 20942 * Set period 20943 */ 20944 msg.period = _kt2_ccm_intervals[_bcm_kt2_oam_ccm_msecs_to_hw_encode(delay_p->period)]; 20945 20946 /* Pack control message data into DMA buffer */ 20947 buffer = oc->dma_buffer; 20948 buffer_ptr = bhh_sdk_msg_ctrl_delay_add_pack(buffer, &msg); 20949 buffer_len = buffer_ptr - buffer; 20950 20951 /* Send BHH Session Update message to uC */ 20952 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 20953 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD, 20954 buffer_len, 0, 20955 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD_REPLY, 20956 &reply_len); 20957 20958 if(BCM_SUCCESS(rv) && (reply_len != 0)) 20959 rv = BCM_E_INTERNAL; 20960 } 20961 else { 20962 _BCM_OAM_UNLOCK(oc); 20963 return BCM_E_UNAVAIL; 20964 } 20965 20966 _BCM_OAM_UNLOCK(oc); 20967 return (rv); 20968 } 20969 20970 /* 20971 * Function: 20972 * bcm_kt2_oam_delay_get 20973 * Purpose: 20974 * Delay Measurements get 20975 * Parameters: 20976 * unit - Device unit number 20977 * Returns: 20978 * None 20979 */ 20980 int 20981 bcm_kt2_oam_delay_get(int unit, bcm_oam_delay_t *delay_p) 20982 { 20983 _bcm_oam_control_t *oc; 20984 int rv = BCM_E_NONE; 20985 bhh_sdk_msg_ctrl_delay_get_t msg; 20986 _bcm_oam_hash_data_t *h_data_p; 20987 uint8 *buffer, *buffer_ptr; 20988 uint16 buffer_len, reply_len; 20989 int sess_id = 0; 20990 20991 /* Get OAM Control Structure. */ 20992 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 20993 _BCM_OAM_LOCK(oc); 20994 20995 if (oc->ukernel_not_ready) { 20996 _BCM_OAM_UNLOCK(oc); 20997 return BCM_E_INIT; 20998 } 20999 21000 BCM_OAM_BHH_VALIDATE_EP(delay_p->id); 21001 21002 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id); 21003 21004 /* Check endpoint status. */ 21005 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 21006 if ((BCM_E_EXISTS != rv)) { 21007 /* Endpoint not in use. */ 21008 LOG_ERROR(BSL_LS_BCM_OAM, 21009 (BSL_META_U(unit, 21010 "OAM Error: Endpoint EP=%d %s.\n"), 21011 delay_p->id, bcm_errmsg(rv))); 21012 _BCM_OAM_UNLOCK(oc); 21013 return (rv); 21014 } 21015 21016 h_data_p = &oc->oam_hash_data[delay_p->id]; 21017 21018 21019 /* 21020 * Only BHH is supported 21021 */ 21022 if(BHH_EP_TYPE(h_data_p)) { 21023 21024 sal_memset(&msg, 0, sizeof(msg)); 21025 /* Send BHH Session Update message to uC */ 21026 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 21027 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET, 21028 sess_id, 0, 21029 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET_REPLY, 21030 &reply_len); 21031 if(BCM_FAILURE(rv)) { 21032 LOG_ERROR(BSL_LS_BCM_OAM, 21033 (BSL_META_U(unit, 21034 "OAM Error: Endpoint EP=%d %s.\n"), 21035 delay_p->id, bcm_errmsg(rv))); 21036 _BCM_OAM_UNLOCK(oc); 21037 return (rv); 21038 } 21039 21040 /* Pack control message data into DMA buffer */ 21041 buffer = oc->dma_buffer; 21042 buffer_ptr = bhh_sdk_msg_ctrl_delay_get_unpack(buffer, &msg); 21043 buffer_len = buffer_ptr - buffer; 21044 21045 21046 if (reply_len != buffer_len) { 21047 rv = BCM_E_INTERNAL; 21048 } else { 21049 /* 21050 * Convert kernel space flags to host space flags 21051 */ 21052 if (msg.flags & BCM_BHH_DM_ONE_WAY) 21053 delay_p->flags |= BCM_OAM_DELAY_ONE_WAY; 21054 21055 if (msg.flags & BCM_BHH_DM_TX_ENABLE) 21056 delay_p->flags |= BCM_OAM_DELAY_TX_ENABLE; 21057 21058 delay_p->period = msg.period; 21059 21060 if(msg.dm_format == BCM_BHH_DM_TYPE_PTP) 21061 delay_p->timestamp_format = bcmOAMTimestampFormatIEEE1588v1; 21062 else 21063 delay_p->timestamp_format = bcmOAMTimestampFormatNTP; 21064 21065 rv = bcm_kt2_oam_bhh_convert_ep_to_time_spec(&(delay_p->delay), 21066 msg.delay_seconds, msg.delay_nanoseconds); 21067 if(BCM_SUCCESS(rv)) { 21068 rv = bcm_kt2_oam_bhh_convert_ep_to_time_spec(&(delay_p->txf), 21069 msg.txf_seconds, msg.txf_nanoseconds); 21070 } 21071 if(BCM_SUCCESS(rv)) { 21072 rv = bcm_kt2_oam_bhh_convert_ep_to_time_spec(&(delay_p->rxf), 21073 msg.rxf_seconds, msg.rxf_nanoseconds); 21074 } 21075 if(BCM_SUCCESS(rv)) { 21076 rv = bcm_kt2_oam_bhh_convert_ep_to_time_spec(&(delay_p->txb), 21077 msg.txb_seconds, msg.txb_nanoseconds); 21078 } 21079 if(BCM_SUCCESS(rv)) { 21080 rv = bcm_kt2_oam_bhh_convert_ep_to_time_spec(&(delay_p->rxb), 21081 msg.rxb_seconds, msg.rxb_nanoseconds); 21082 } 21083 delay_p->rx_oam_packets = msg.rx_oam_packets; 21084 delay_p->tx_oam_packets = msg.tx_oam_packets; 21085 delay_p->int_pri = msg.int_pri; 21086 delay_p->pkt_pri = msg.pkt_pri; 21087 21088 rv = BCM_E_NONE; 21089 } 21090 } 21091 else { 21092 _BCM_OAM_UNLOCK(oc); 21093 return BCM_E_UNAVAIL; 21094 } 21095 21096 _BCM_OAM_UNLOCK(oc); 21097 21098 return (rv); 21099 } 21100 21101 /* 21102 * Function: 21103 * bcm_kt2_oam_delay_delete 21104 * Purpose: 21105 * Delay Measurement Delete 21106 * Parameters: 21107 * unit - Device unit number 21108 * Returns: 21109 * None 21110 */ 21111 int 21112 bcm_kt2_oam_delay_delete(int unit, bcm_oam_delay_t *delay_p) 21113 { 21114 _bcm_oam_control_t *oc; 21115 int rv = BCM_E_NONE; 21116 shr_bhh_msg_ctrl_delay_delete_t msg; 21117 uint8 *buffer, *buffer_ptr; 21118 uint16 buffer_len, reply_len; 21119 int sess_id = 0; 21120 _bcm_oam_hash_data_t *h_data_p; 21121 21122 /* Get OAM Control Structure. */ 21123 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 21124 _BCM_OAM_LOCK(oc); 21125 21126 if (oc->ukernel_not_ready) { 21127 _BCM_OAM_UNLOCK(oc); 21128 return BCM_E_INIT; 21129 } 21130 21131 BCM_OAM_BHH_VALIDATE_EP(delay_p->id); 21132 21133 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id); 21134 21135 /* Check endpoint status. */ 21136 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 21137 if ((BCM_E_EXISTS != rv)) { 21138 /* Endpoint not in use. */ 21139 LOG_ERROR(BSL_LS_BCM_OAM, 21140 (BSL_META_U(unit, 21141 "OAM Error: Endpoint EP=%d %s.\n"), 21142 delay_p->id, bcm_errmsg(rv))); 21143 _BCM_OAM_UNLOCK(oc); 21144 return (rv); 21145 } 21146 21147 h_data_p = &oc->oam_hash_data[delay_p->id]; 21148 21149 /* 21150 * Only BHH is supported 21151 */ 21152 if(BHH_EP_TYPE(h_data_p)) { 21153 21154 msg.sess_id = sess_id; 21155 21156 /* Pack control message data into DMA buffer */ 21157 buffer = oc->dma_buffer; 21158 buffer_ptr = shr_bhh_msg_ctrl_delay_delete_pack(buffer, &msg); 21159 buffer_len = buffer_ptr - buffer; 21160 21161 /* Send BHH Session Update message to uC */ 21162 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 21163 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE, 21164 buffer_len, 0, 21165 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE_REPLY, 21166 &reply_len); 21167 21168 if(BCM_SUCCESS(rv) && (reply_len != 0)) 21169 rv = BCM_E_INTERNAL; 21170 } 21171 else { 21172 _BCM_OAM_UNLOCK(oc); 21173 return BCM_E_UNAVAIL; 21174 } 21175 21176 _BCM_OAM_UNLOCK(oc); 21177 21178 return (rv); 21179 } 21180 21181 int _bcm_kt2_oam_pm_init(int unit) 21182 { 21183 /* Profile data structure initialization */ 21184 _bcm_oam_pm_profile_control_t *pmc = NULL; 21185 int rv = BCM_E_NONE; 21186 _bcm_oam_control_t *oc = NULL; 21187 21188 rv = _bcm_kt2_oam_control_get(unit, &oc); 21189 21190 if (BCM_FAILURE(rv)) { 21191 LOG_ERROR(BSL_LS_BCM_OAM, 21192 (BSL_META_U(unit, 21193 "OAM(unit %d) Error: Oam control get failed " 21194 "- %s.\n"), unit, bcm_errmsg(rv))); 21195 return BCM_E_INIT; 21196 } 21197 21198 _BCM_OAM_LOCK(oc); 21199 21200 oc->pm_bhh_lmdm_data_collection_mode = soc_property_get(unit, 21201 spn_BHH_DATA_COLLECTION_MODE, _BCM_OAM_PM_COLLECTION_MODE_NONE); 21202 21203 /* Raw mode is not supported in KT2. Internally it will be taken as none. */ 21204 if ( _BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) { 21205 21206 oc->pm_bhh_lmdm_data_collection_mode = _BCM_OAM_PM_COLLECTION_MODE_NONE; 21207 21208 LOG_ERROR(BSL_LS_BCM_OAM, 21209 (BSL_META_U(unit, 21210 "OAM(unit %d) Error: Raw mode is not supported in KT2." 21211 "Selected mode is none \n"), unit)); 21212 21213 } 21214 21215 /* Allocate profiles only if one of them has processed stats 21216 * collection enabled 21217 */ 21218 if ((_BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc))) { 21219 _BCM_OAM_ALLOC(pmc, _bcm_oam_pm_profile_control_t, 21220 sizeof (_bcm_oam_pm_profile_control_t), 21221 "OAM PM profile control"); 21222 if (!pmc) { 21223 _BCM_OAM_UNLOCK(oc); 21224 return BCM_E_MEMORY; 21225 } 21226 21227 kt2_pm_profile_control[unit] = pmc; 21228 } 21229 /* 21230 * Allocate DMA buffers and raw data buffers. 21231 * 21232 * 1) DMA buffer will be used to send and receive 'long' messages 21233 * between SDK Host and uController (BTE). 21234 */ 21235 21236 /* DMA buffer */ 21237 if (_BCM_KT2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc)) { 21238 oc->pm_bhh_dma_buffer_len = sizeof(shr_oam_pm_msg_ctrl_t); 21239 oc->pm_bhh_dma_buffer = soc_cm_salloc(unit, oc->pm_bhh_dma_buffer_len, 21240 "PM DMA buffer"); 21241 if (!oc->pm_bhh_dma_buffer) { 21242 _BCM_OAM_UNLOCK(oc); 21243 return (BCM_E_MEMORY); 21244 } 21245 sal_memset(oc->pm_bhh_dma_buffer, 0, oc->pm_bhh_dma_buffer_len); 21246 } 21247 21248 _BCM_OAM_UNLOCK(oc); 21249 21250 return BCM_E_NONE; 21251 } 21252 21253 /* 21254 * Function: 21255 * _bcm_kt2_oam_pm_msg_send_receive 21256 * Purpose: 21257 * Sends given PM control message to the uController. 21258 * Receives and verifies expected reply. 21259 * Performs DMA operation if required. 21260 * Parameters: 21261 * unit - (IN) Unit number. 21262 * s_class - (IN) PM message class. 21263 * s_len - (IN) Value for 'len' field in message struct. 21264 * Length of buffer to flush if DMA send is required. 21265 * s_data - (IN) Value for 'data' field in message struct. 21266 * Ignored if message requires a DMA send/receive 21267 * operation. 21268 * r_subclass - (IN) Expected reply message subclass. 21269 * r_len - (OUT) Returns value in 'len' reply message field. 21270 * Returns: 21271 * BCM_E_XXX 21272 * Notes: 21273 * - The uc_msg 'len' and 'data' fields of mos_msg_data_t 21274 * can take any arbitrary data. 21275 * 21276 * PM Long Control message: 21277 * - PM control messages that require send/receive of information 21278 * that cannot fit in the uc_msg 'len' and 'data' fields need to 21279 * use DMA operations to exchange information (long control message). 21280 * 21281 * - PM convention for long control messages for 21282 * 'mos_msg_data_t' fields: 21283 * 'len' size of the DMA buffer to send to uController 21284 * 'data' physical DMA memory address to send or receive 21285 * 21286 * DMA Operations: 21287 * - DMA read/write operation is performed when a long BHH control 21288 * message is involved. 21289 * 21290 * - Messages that require DMA operation (long control message) 21291 * is indicated by MOS_MSG_DMA_MSG(). 21292 * 21293 * - Callers must 'pack' and 'unpack' corresponding information 21294 * into/from DMA buffer indicated by dma_buffer. 21295 */ 21296 STATIC int 21297 _bcm_kt2_oam_pm_msg_send_receive(int unit, uint8 s_class, uint8 s_subclass, 21298 uint16 s_len, uint32 s_data, 21299 uint8 r_subclass, uint16 *r_len) 21300 { 21301 int rv = BCM_E_NONE; 21302 _bcm_oam_control_t *oc; 21303 mos_msg_data_t send, reply; 21304 uint8 *dma_buffer = NULL; 21305 int dma_buffer_len = 0; 21306 uint32 uc_rv; 21307 int uc_num; 21308 21309 /* Lock already taken by the calling routine. */ 21310 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 21311 21312 sal_memset(&send, 0, sizeof(send)); 21313 sal_memset(&reply, 0, sizeof(reply)); 21314 send.s.mclass = s_class; 21315 send.s.subclass = s_subclass; 21316 send.s.len = bcm_htons(s_len); 21317 21318 /* 21319 * Set 'data' to DMA buffer address if a DMA operation is 21320 * required for send or receive. 21321 */ 21322 21323 dma_buffer = oc->pm_bhh_dma_buffer; 21324 dma_buffer_len = oc->pm_bhh_dma_buffer_len; 21325 21326 if (MOS_MSG_DMA_MSG(s_subclass) || 21327 MOS_MSG_DMA_MSG(r_subclass)) { 21328 send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer)); 21329 } else { 21330 send.s.data = bcm_htonl(s_data); 21331 } 21332 21333 /* Flush DMA memory */ 21334 if (MOS_MSG_DMA_MSG(s_subclass)) { 21335 soc_cm_sflush(unit, dma_buffer, s_len); 21336 } 21337 21338 /* Invalidate DMA memory to read */ 21339 if (MOS_MSG_DMA_MSG(r_subclass)) { 21340 soc_cm_sinval(unit, dma_buffer, dma_buffer_len); 21341 } 21342 21343 switch (s_class) { 21344 case MOS_MSG_CLASS_BHH: 21345 uc_num = oc->uc_num; 21346 break; 21347 21348 default: 21349 return BCM_E_PARAM; 21350 break; 21351 } 21352 21353 /* coverity[unreachable] */ 21354 rv = soc_cmic_uc_msg_send_receive(unit, uc_num, 21355 &send, &reply, 21356 _PM_UC_MSG_TIMEOUT_USECS); 21357 21358 /* Check reply class, subclass */ 21359 if ((rv != SOC_E_NONE) || 21360 (reply.s.mclass != s_class) || /* We can expect the same class that was sent */ 21361 (reply.s.subclass != r_subclass)) { 21362 return (BCM_E_INTERNAL); 21363 } 21364 21365 /* Convert OAM PM uController error code to BCM */ 21366 uc_rv = bcm_ntohl(reply.s.data); 21367 switch(uc_rv) { 21368 case SHR_OAM_PM_UC_E_NONE: 21369 rv = BCM_E_NONE; 21370 break; 21371 case SHR_OAM_PM_UC_E_INTERNAL: 21372 rv = BCM_E_INTERNAL; 21373 break; 21374 case SHR_OAM_PM_UC_E_MEMORY: 21375 rv = BCM_E_MEMORY; 21376 break; 21377 case SHR_OAM_PM_UC_E_PARAM: 21378 rv = BCM_E_PARAM; 21379 break; 21380 case SHR_OAM_PM_UC_E_RESOURCE: 21381 rv = BCM_E_RESOURCE; 21382 break; 21383 case SHR_OAM_PM_UC_E_EXISTS: 21384 rv = BCM_E_EXISTS; 21385 break; 21386 case SHR_OAM_PM_UC_E_NOT_FOUND: 21387 rv = BCM_E_NOT_FOUND; 21388 break; 21389 case SHR_OAM_PM_UC_E_UNAVAIL: 21390 rv = BCM_E_UNAVAIL; 21391 break; 21392 case SHR_OAM_PM_UC_E_VERSION: 21393 rv = BCM_E_CONFIG; 21394 break; 21395 case SHR_OAM_PM_UC_E_INIT: 21396 rv = BCM_E_INIT; 21397 break; 21398 default: 21399 rv = BCM_E_INTERNAL; 21400 break; 21401 } 21402 21403 *r_len = bcm_ntohs(reply.s.len); 21404 21405 return (rv); 21406 } 21407 21408 int _bcm_kt2_pm_profile_compare(bcm_oam_pm_profile_info_t *profile_info1, 21409 bcm_oam_pm_profile_info_t *profile_info2) 21410 { 21411 if (!(sal_memcmp(profile_info1->bin_edges, profile_info2->bin_edges, 21412 BCM_OAM_MAX_PM_PROFILE_BIN_EDGES * sizeof(uint32)))) { 21413 /* Match */ 21414 return 1; 21415 } 21416 return 0; 21417 } 21418 21419 int _bcm_kt2_pm_profile_exists(int unit, bcm_oam_pm_profile_info_t *profile_info) 21420 { 21421 int id = 0; 21422 _bcm_oam_pm_profile_control_t *pmc = NULL; 21423 21424 pmc = kt2_pm_profile_control[unit]; 21425 21426 if (!pmc) { 21427 return 0; 21428 } 21429 21430 for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) { 21431 if (_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, id)) { /* If a profile is in use */ 21432 if (_bcm_kt2_pm_profile_compare( 21433 _BCM_KT2_PM_CTRL_PROFILE_PTR(pmc, id), 21434 profile_info)) { 21435 return 1; 21436 } 21437 } 21438 } 21439 return 0; 21440 } 21441 21442 int 21443 _bcm_kt2_find_free_pm_profile_id(int unit, int *pm_profile_id) 21444 { 21445 int id = 0; 21446 _bcm_oam_pm_profile_control_t *pmc = NULL; 21447 21448 pmc = kt2_pm_profile_control[unit]; 21449 21450 if (!pmc) { 21451 return BCM_E_INIT; 21452 } 21453 21454 /* return the lowest un used id */ 21455 for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) { 21456 if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, id))) { /* If a profile is not in use */ 21457 *pm_profile_id = id; /* Assign it and return */ 21458 return BCM_E_NONE; 21459 } 21460 } 21461 return BCM_E_RESOURCE; 21462 } 21463 21464 int 21465 _bcm_kt2_oam_pm_profile_delete(int unit, bcm_oam_pm_profile_t profile_id, int all) 21466 { 21467 _bcm_oam_pm_profile_control_t *pmc; 21468 21469 pmc = kt2_pm_profile_control[unit]; 21470 21471 if (!pmc) { 21472 return BCM_E_INIT; 21473 } 21474 21475 /* Check it only if it is a delete for a particular profile */ 21476 if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id)) && !all) { 21477 /* It is not in use. Return error */ 21478 return BCM_E_NOT_FOUND; 21479 } 21480 /* Zero out that profile */ 21481 sal_memset(_BCM_KT2_PM_CTRL_PROFILE_PTR(pmc, profile_id), 0, 21482 sizeof(bcm_oam_pm_profile_info_t)); 21483 /* Mark it un used */ 21484 _BCM_KT2_SET_PM_CTRL_PROFILE_NOT_IN_USE(pmc, profile_id); 21485 21486 return BCM_E_NONE; 21487 } 21488 21489 int 21490 bcm_kt2_oam_pm_profile_delete(int unit, bcm_oam_pm_profile_t profile_id) 21491 { 21492 _bcm_oam_control_t *oc = NULL; 21493 int rv = BCM_E_NONE; 21494 21495 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 21496 _BCM_OAM_LOCK(oc); 21497 21498 if (!(_BCM_KT2_PM_PROFILE_ID_VALID(profile_id))) { 21499 21500 _BCM_OAM_UNLOCK(oc); 21501 return BCM_E_PARAM; 21502 } 21503 21504 rv = _bcm_kt2_oam_pm_profile_delete(unit, profile_id, 0); 21505 21506 _BCM_OAM_UNLOCK(oc); 21507 return rv; 21508 } 21509 21510 int 21511 bcm_kt2_oam_pm_profile_delete_all(int unit) 21512 { 21513 int id; 21514 _bcm_oam_control_t *oc = NULL; 21515 int rv = BCM_E_NONE; 21516 21517 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 21518 _BCM_OAM_LOCK(oc); 21519 21520 for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) { 21521 rv = _bcm_kt2_oam_pm_profile_delete(unit, id, 1); 21522 21523 if(rv != BCM_E_NONE) { 21524 _BCM_OAM_UNLOCK(oc); 21525 } 21526 } 21527 21528 _BCM_OAM_UNLOCK(oc); 21529 return BCM_E_NONE; 21530 } 21531 21532 int 21533 bcm_kt2_oam_pm_profile_create(int unit, bcm_oam_pm_profile_info_t *profile_info) 21534 { 21535 _bcm_oam_pm_profile_control_t *pmc = NULL; 21536 bcm_oam_pm_profile_info_t *profile_ptr = NULL; 21537 int pm_profile_id = 0; 21538 _bcm_oam_control_t *oc = NULL; 21539 int rv=BCM_E_NONE; 21540 21541 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 21542 _BCM_OAM_LOCK(oc); 21543 21544 pmc = kt2_pm_profile_control[unit]; 21545 21546 if (!pmc) { 21547 _BCM_OAM_UNLOCK(oc); 21548 return BCM_E_INIT; 21549 } 21550 21551 if (_BCM_KT2_PM_PROFILE_WITH_ID_FLAG_SET(profile_info)) { 21552 if (!(_BCM_KT2_PM_PROFILE_ID_VALID(profile_info->id))) { 21553 _BCM_OAM_UNLOCK(oc); 21554 return BCM_E_PARAM; 21555 } 21556 } 21557 21558 if (_BCM_KT2_PM_PROFILE_REPLACE_FLAG_SET(profile_info)) { 21559 if (!(_BCM_KT2_PM_PROFILE_WITH_ID_FLAG_SET(profile_info))) { 21560 /* replace needs the id to be present */ 21561 _BCM_OAM_UNLOCK(oc); 21562 return BCM_E_PARAM; 21563 } 21564 21565 if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, profile_info->id))) { 21566 /* Trying to replace a non-existent PM profile */ 21567 _BCM_OAM_UNLOCK(oc); 21568 return BCM_E_NOT_FOUND; 21569 } 21570 21571 /* Delete the previous profile. */ 21572 rv = _bcm_kt2_oam_pm_profile_delete(unit, 21573 profile_info->id, 0); 21574 21575 if(rv != BCM_E_NONE) { 21576 _BCM_OAM_UNLOCK(oc); 21577 return rv; 21578 } 21579 } 21580 21581 if (_BCM_KT2_PM_PROFILE_WITH_ID_FLAG_SET(profile_info)) { 21582 if (_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, profile_info->id)) { 21583 /* That profile id is in use. */ 21584 _BCM_OAM_UNLOCK(oc); 21585 return BCM_E_EXISTS; 21586 } 21587 /* Else use that as the id */ 21588 pm_profile_id = profile_info->id; 21589 } else { 21590 rv = _bcm_kt2_find_free_pm_profile_id(unit, 21591 &pm_profile_id); 21592 if(rv != BCM_E_NONE) { 21593 _BCM_OAM_UNLOCK(oc); 21594 return rv; 21595 } 21596 } 21597 21598 /* Check if such a profile already exists. */ 21599 if (_bcm_kt2_pm_profile_exists(unit, profile_info)) { 21600 21601 _BCM_OAM_UNLOCK(oc); 21602 return BCM_E_EXISTS; 21603 } 21604 21605 /* Copy it to local profile information */ 21606 profile_ptr = _BCM_KT2_PM_CTRL_PROFILE_PTR(pmc, pm_profile_id); 21607 sal_memcpy(profile_ptr, profile_info, 21608 sizeof(bcm_oam_pm_profile_info_t)); 21609 21610 /* Update the id in the profile */ 21611 profile_ptr->id = profile_info->id = pm_profile_id; 21612 21613 /* Current flags have only transient meaning, so clear them */ 21614 profile_ptr->flags = 0; 21615 21616 /* Mark that profile used */ 21617 _BCM_KT2_SET_PM_CTRL_PROFILE_IN_USE(pmc, pm_profile_id); 21618 21619 _BCM_OAM_UNLOCK(oc); 21620 21621 return BCM_E_NONE; 21622 } 21623 21624 int 21625 bcm_kt2_oam_pm_profile_get(int unit, bcm_oam_pm_profile_info_t *profile_info) 21626 { 21627 _bcm_oam_pm_profile_control_t *pmc; 21628 int profile_id = profile_info->id; 21629 21630 pmc = kt2_pm_profile_control[unit]; 21631 21632 if (!pmc) { 21633 return BCM_E_INIT; 21634 } 21635 21636 if (!(_BCM_KT2_PM_PROFILE_ID_VALID(profile_id))) { 21637 return BCM_E_PARAM; 21638 } 21639 21640 if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) { 21641 /* It is not in use. Return error */ 21642 return BCM_E_NOT_FOUND; 21643 } 21644 21645 /* Copy the profile to the profile structure passed */ 21646 sal_memcpy(profile_info, _BCM_KT2_PM_CTRL_PROFILE_PTR(pmc, profile_id), 21647 sizeof(bcm_oam_pm_profile_info_t)); 21648 21649 return BCM_E_NONE; 21650 } 21651 21652 int bcm_kt2_oam_pm_profile_attach(int unit, bcm_oam_endpoint_t endpoint_id, 21653 bcm_oam_pm_profile_t profile_id) 21654 { 21655 _bcm_oam_pm_profile_control_t *pmc = NULL; 21656 bcm_oam_pm_profile_info_t *profile_info = NULL; 21657 _bcm_oam_control_t *oc = NULL; 21658 _bcm_oam_hash_data_t *h_data_p = NULL; 21659 int rv = BCM_E_NONE; 21660 shr_oam_pm_msg_ctrl_profile_attach_t msg_profile_attach; 21661 uint8 msg_class = 0; 21662 uint16 reply_len = 0; 21663 uint8 msg_subclass = 0; 21664 uint8 msg_reply_subclass = 0; 21665 uint8 *buffer, *buffer_ptr; 21666 uint16 buffer_len; 21667 21668 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 21669 _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id); 21670 _BCM_OAM_LOCK(oc); 21671 21672 h_data_p = &oc->oam_hash_data[endpoint_id]; 21673 21674 if (!BHH_EP_TYPE(h_data_p)) { 21675 LOG_ERROR(BSL_LS_BCM_OAM, 21676 (BSL_META_U(unit, 21677 "OAM(unit %d) Error: EP=%d is not BHH endpoint\n"), 21678 unit, endpoint_id)); 21679 _BCM_OAM_UNLOCK(oc); 21680 return (BCM_E_UNAVAIL); 21681 } 21682 21683 if (0 == h_data_p->in_use) { 21684 LOG_ERROR(BSL_LS_BCM_OAM, 21685 (BSL_META_U(unit, 21686 "OAM(unit %d) Error: h_data_p not in use EP=%d\n"), 21687 unit, endpoint_id)); 21688 _BCM_OAM_UNLOCK(oc); 21689 return (BCM_E_NOT_FOUND); 21690 } 21691 pmc = kt2_pm_profile_control[unit]; 21692 21693 if (!pmc) { 21694 _BCM_OAM_UNLOCK(oc); 21695 return BCM_E_INIT; 21696 } 21697 21698 if (!(_BCM_KT2_PM_PROFILE_ID_VALID(profile_id))) { 21699 _BCM_OAM_UNLOCK(oc); 21700 return BCM_E_PARAM; 21701 } 21702 21703 /* Check profile id exists or not */ 21704 if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) { 21705 /* It is not in use. Return error */ 21706 _BCM_OAM_UNLOCK(oc); 21707 return BCM_E_NOT_FOUND; 21708 } 21709 /* Check if a profile id is already attached to this endpoint */ 21710 if (h_data_p->pm_profile_attached != _BCM_OAM_INVALID_INDEX) { 21711 _BCM_OAM_UNLOCK(oc); 21712 return BCM_E_EXISTS; 21713 } 21714 21715 /* Check if delay measurement flag is present for the endpoint */ 21716 if (!(h_data_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT)) { 21717 _BCM_OAM_UNLOCK(oc); 21718 return BCM_E_PARAM; 21719 } 21720 21721 profile_info = _BCM_KT2_PM_CTRL_PROFILE_PTR(pmc, profile_id); 21722 21723 /* Send info to u-Kernel about the profile attached with the endpoint */ 21724 sal_memset(&msg_profile_attach, 0, sizeof(msg_profile_attach)); 21725 21726 msg_class = MOS_MSG_CLASS_BHH; 21727 msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_ATTACH; 21728 msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_ATTACH_REPLY; 21729 msg_profile_attach.sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id); 21730 21731 msg_profile_attach.profile_id = profile_id; 21732 msg_profile_attach.profile_flags = profile_info->flags; 21733 sal_memcpy(&(msg_profile_attach.profile_edges), &(profile_info->bin_edges), 21734 (sizeof(uint32) * SHR_OAM_PM_MAX_PM_BIN_EDGES)); 21735 21736 /* Pack control message data into DMA buffer */ 21737 buffer = oc->pm_bhh_dma_buffer; 21738 buffer_ptr = shr_oam_pm_msg_ctrl_profile_attach_pack(buffer, &msg_profile_attach); 21739 buffer_len = buffer_ptr - buffer; 21740 21741 21742 rv = _bcm_kt2_oam_pm_msg_send_receive 21743 (unit, msg_class, 21744 msg_subclass, 21745 buffer_len, 0, 21746 msg_reply_subclass, 21747 &reply_len); 21748 21749 if(BCM_FAILURE(rv)) { 21750 _BCM_OAM_UNLOCK(oc); 21751 return BCM_E_INTERNAL; 21752 } 21753 21754 /* Attach it to the endpoint */ 21755 h_data_p->pm_profile_attached = profile_id; 21756 21757 _BCM_OAM_UNLOCK(oc); 21758 return BCM_E_NONE; 21759 } 21760 21761 int bcm_kt2_oam_pm_profile_detach(int unit, bcm_oam_endpoint_t endpoint_id, 21762 bcm_oam_pm_profile_t profile_id) 21763 { 21764 _bcm_oam_pm_profile_control_t *pmc = NULL; 21765 _bcm_oam_control_t *oc = NULL; 21766 _bcm_oam_hash_data_t *h_data_p = NULL; 21767 int rv = BCM_E_NONE; 21768 uint8 msg_class = 0; 21769 uint16 reply_len = 0; 21770 uint8 msg_subclass = 0; 21771 uint8 msg_reply_subclass = 0; 21772 uint16 sess_id = 0; 21773 21774 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 21775 _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id); 21776 _BCM_OAM_LOCK(oc); 21777 21778 h_data_p = &oc->oam_hash_data[endpoint_id]; 21779 21780 if (!BHH_EP_TYPE(h_data_p)) { 21781 LOG_ERROR(BSL_LS_BCM_OAM, 21782 (BSL_META_U(unit, 21783 "OAM(unit %d) Error: EP=%d is not BHH endpoint\n"), 21784 unit, endpoint_id)); 21785 _BCM_OAM_UNLOCK(oc); 21786 return (BCM_E_UNAVAIL); 21787 } 21788 21789 if (0 == h_data_p->in_use) { 21790 LOG_ERROR(BSL_LS_BCM_OAM, 21791 (BSL_META_U(unit, 21792 "OAM(unit %d) Error: h_data_p not in use EP=%d\n"), 21793 unit, endpoint_id)); 21794 _BCM_OAM_UNLOCK(oc); 21795 return (BCM_E_NOT_FOUND); 21796 } 21797 pmc = kt2_pm_profile_control[unit]; 21798 21799 if (!pmc) { 21800 _BCM_OAM_UNLOCK(oc); 21801 return BCM_E_INIT; 21802 } 21803 21804 if (!(_BCM_KT2_PM_PROFILE_ID_VALID(profile_id))) { 21805 _BCM_OAM_UNLOCK(oc); 21806 return BCM_E_PARAM; 21807 } 21808 21809 /* Check profile id exists or not */ 21810 if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) { 21811 /* It is not in use. Return error */ 21812 _BCM_OAM_UNLOCK(oc); 21813 return BCM_E_NOT_FOUND; 21814 } 21815 21816 /* Check if the passed profile id is the one that is attached */ 21817 if (profile_id != h_data_p->pm_profile_attached) { 21818 _BCM_OAM_UNLOCK(oc); 21819 return BCM_E_PARAM; 21820 } 21821 21822 msg_class = MOS_MSG_CLASS_BHH; 21823 msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_DETACH; 21824 msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_DETACH_REPLY; 21825 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id); 21826 21827 rv = _bcm_kt2_oam_pm_msg_send_receive 21828 (unit, msg_class, 21829 msg_subclass, 21830 sess_id, profile_id, 21831 msg_reply_subclass, 21832 &reply_len); 21833 21834 if(BCM_FAILURE(rv)) { 21835 _BCM_OAM_UNLOCK(oc); 21836 return BCM_E_INTERNAL; 21837 } 21838 /* Detach the profile from endpoint */ 21839 h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX; 21840 21841 _BCM_OAM_UNLOCK(oc); 21842 return BCM_E_NONE; 21843 } 21844 21845 21846 int bcm_kt2_oam_pm_profile_traverse(int unit, 21847 bcm_oam_pm_profile_traverse_cb cb, void *user_data) 21848 { 21849 int rv = BCM_E_NONE; /* Operation return status. */ 21850 bcm_oam_pm_profile_info_t *profile_info = NULL; 21851 _bcm_oam_pm_profile_control_t *pmc = NULL; 21852 int profile_id; 21853 21854 /* Validate input parameter. */ 21855 if (NULL == cb) { 21856 return (BCM_E_PARAM); 21857 } 21858 pmc = kt2_pm_profile_control[unit]; 21859 21860 if (!pmc) { 21861 return BCM_E_INIT; 21862 } 21863 21864 for (profile_id = 0; profile_id < _BCM_OAM_MAX_PM_PROFILES; profile_id++) { 21865 /* Check profile id is in use or not */ 21866 if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) { 21867 /* Skip that profile id */ 21868 continue; 21869 } 21870 profile_info = _BCM_KT2_PM_CTRL_PROFILE_PTR(pmc, profile_id); 21871 rv = cb(unit, profile_info, user_data); 21872 if (BCM_FAILURE(rv)) { 21873 LOG_ERROR(BSL_LS_BCM_OAM, 21874 (BSL_META_U(unit, 21875 "OAM(unit %d) Error: EP=%d callback failed - %s.\n"), 21876 unit, profile_id, bcm_errmsg(rv))); 21877 return (rv); 21878 } 21879 } 21880 21881 return (rv); 21882 } 21883 21884 void _bcm_kt2_oam_copy_stats_msg_to_stats_ptr(shr_oam_pm_msg_ctrl_pm_stats_get_t *stats_msg, 21885 bcm_oam_pm_stats_t *stats_ptr, 21886 uint8 pm_stat_extra_elem_feature) 21887 { 21888 stats_ptr->far_loss_min = stats_msg->far_loss_min; 21889 stats_ptr->far_tx_min = stats_msg->far_tx_min; 21890 stats_ptr->far_loss_max = stats_msg->far_loss_max; 21891 stats_ptr->far_tx_max = stats_msg->far_tx_max; 21892 stats_ptr->far_loss = stats_msg->far_loss; 21893 stats_ptr->near_loss_min = stats_msg->near_loss_min; 21894 stats_ptr->near_tx_min = stats_msg->near_tx_min; 21895 stats_ptr->near_loss_max = stats_msg->near_loss_max; 21896 stats_ptr->near_tx_max = stats_msg->near_tx_max; 21897 stats_ptr->near_loss = stats_msg->near_loss; 21898 stats_ptr->lm_tx_count = stats_msg->lm_tx_count; 21899 stats_ptr->DM_min = stats_msg->DM_min; 21900 stats_ptr->DM_max = stats_msg->DM_max; 21901 if(stats_msg->dm_rx_count) { 21902 stats_ptr->DM_avg = stats_msg->DM_avg/stats_msg->dm_rx_count; 21903 } 21904 stats_ptr->dm_tx_count = stats_msg->dm_tx_count; 21905 stats_ptr->profile_id = stats_msg->profile_id; 21906 sal_memcpy(&(stats_ptr->bin_counters), &(stats_msg->bin_counters), sizeof(uint32) * (SHR_OAM_PM_MAX_PM_BIN_EDGES + 1)); 21907 if(pm_stat_extra_elem_feature) { 21908 stats_ptr->lm_rx_count = stats_msg->lm_rx_count; 21909 stats_ptr->dm_rx_count = stats_msg->dm_rx_count; 21910 stats_ptr->far_total_tx_pkt_count = stats_msg->far_total_tx_pkt_count; 21911 stats_ptr->near_total_tx_pkt_count = stats_msg->near_total_tx_pkt_count; 21912 } 21913 21914 if (stats_msg->flags & SHR_OAM_PM_STATS_FLAG_COUNTER_ROLLOVER) { 21915 stats_ptr->flags |= BCM_OAM_PM_STATS_PROCESSED_COUNTER_ROLLOVER; 21916 } 21917 } 21918 21919 int bcm_kt2_oam_pm_stats_get(int unit, 21920 bcm_oam_endpoint_t endpoint_id, bcm_oam_pm_stats_t *stats_ptr) 21921 { 21922 _bcm_oam_pm_profile_control_t *pmc = NULL; 21923 _bcm_oam_control_t *oc = NULL; 21924 _bcm_oam_hash_data_t *h_data_p = NULL; 21925 shr_oam_pm_msg_ctrl_pm_stats_get_t stats_msg; 21926 int rv = BCM_E_NONE; 21927 uint16 sess_id = 0; 21928 uint8 msg_class = 0; 21929 uint16 reply_len = 0; 21930 uint8 msg_subclass = 0; 21931 uint8 msg_reply_subclass = 0; 21932 uint8 *dma_buffer = NULL; 21933 uint8 pm_stat_extra_elem_feature = 0; 21934 21935 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 21936 _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id); 21937 _BCM_OAM_LOCK(oc); 21938 21939 /* Check endpoint status. */ 21940 rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint_id); 21941 if ((BCM_E_EXISTS != rv)) { 21942 /* Endpoint not in use. */ 21943 LOG_ERROR(BSL_LS_BCM_OAM, 21944 (BSL_META_U(unit, 21945 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 21946 unit, endpoint_id, bcm_errmsg(rv))); 21947 _BCM_OAM_UNLOCK(oc); 21948 return (rv); 21949 } 21950 21951 h_data_p = &oc->oam_hash_data[endpoint_id]; 21952 21953 if (!BHH_EP_TYPE(h_data_p)) { 21954 LOG_ERROR(BSL_LS_BCM_OAM, 21955 (BSL_META_U(unit, 21956 "OAM(unit %d) Error: EP=%d is not BHH endpoint\n"), 21957 unit, endpoint_id)); 21958 _BCM_OAM_UNLOCK(oc); 21959 return (BCM_E_UNAVAIL); 21960 } 21961 21962 if (0 == h_data_p->in_use) { 21963 LOG_ERROR(BSL_LS_BCM_OAM, 21964 (BSL_META_U(unit, 21965 "OAM(unit %d) Error: h_data_p not in use EP=%d\n"), 21966 unit, endpoint_id)); 21967 _BCM_OAM_UNLOCK(oc); 21968 return (BCM_E_INTERNAL); 21969 } 21970 21971 pmc = kt2_pm_profile_control[unit]; 21972 21973 if (!pmc) { 21974 _BCM_OAM_UNLOCK(oc); 21975 return BCM_E_INIT; 21976 } 21977 21978 21979 msg_class = MOS_MSG_CLASS_BHH; 21980 msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_STATS_GET; 21981 msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_STATS_GET_REPLY; 21982 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id); 21983 pm_stat_extra_elem_feature = BHH_UC_FEATURE_CHECK(BHH_PM_STAT_EXTRA_ELEM); 21984 21985 dma_buffer = oc->pm_bhh_dma_buffer; 21986 rv = _bcm_kt2_oam_pm_msg_send_receive 21987 (unit, msg_class, 21988 msg_subclass, 21989 /* Pass the buffer pointer in data and sess id in length fields.*/ 21990 sess_id, soc_cm_l2p(unit, dma_buffer), 21991 msg_reply_subclass, 21992 &reply_len); 21993 21994 if(BCM_FAILURE(rv) || reply_len == 0) { 21995 _BCM_OAM_UNLOCK(oc); 21996 return BCM_E_INTERNAL; 21997 } 21998 21999 shr_oam_pm_msg_ctrl_pm_stats_get_unpack(dma_buffer, &stats_msg, pm_stat_extra_elem_feature); 22000 22001 _bcm_kt2_oam_copy_stats_msg_to_stats_ptr(&stats_msg, stats_ptr, pm_stat_extra_elem_feature); 22002 22003 _BCM_OAM_UNLOCK(oc); 22004 return BCM_E_NONE; 22005 } 22006 22007 22008 int 22009 bcm_kt2_oam_pm_profile_attach_get( 22010 int unit, 22011 bcm_oam_endpoint_t endpoint_id, 22012 bcm_oam_pm_profile_t *profile_id) 22013 { 22014 _bcm_oam_pm_profile_control_t *pmc = NULL; 22015 _bcm_oam_control_t *oc = NULL; 22016 _bcm_oam_hash_data_t *h_data_p = NULL; 22017 int rv = BCM_E_NONE; 22018 22019 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 22020 _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id); 22021 _BCM_OAM_LOCK(oc); 22022 22023 /* Check endpoint status. */ 22024 rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint_id); 22025 if ((BCM_E_EXISTS != rv)) { 22026 /* Endpoint not in use. */ 22027 LOG_ERROR(BSL_LS_BCM_OAM, 22028 (BSL_META_U(unit, 22029 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 22030 unit, endpoint_id, bcm_errmsg(rv))); 22031 _BCM_OAM_UNLOCK(oc); 22032 return (rv); 22033 } 22034 22035 h_data_p = &oc->oam_hash_data[endpoint_id]; 22036 22037 if (0 == h_data_p->in_use) { 22038 LOG_ERROR(BSL_LS_BCM_OAM, 22039 (BSL_META_U(unit, 22040 "OAM(unit %d) Error: h_data_p not in use EP=%d\n"), 22041 unit, endpoint_id)); 22042 _BCM_OAM_UNLOCK(oc); 22043 return (BCM_E_INTERNAL); 22044 } 22045 pmc = kt2_pm_profile_control[unit]; 22046 22047 if (!pmc) { 22048 _BCM_OAM_UNLOCK(oc); 22049 return BCM_E_INIT; 22050 } 22051 22052 /* Get the attached profile */ 22053 *profile_id = h_data_p->pm_profile_attached; 22054 22055 if (*profile_id == _BCM_OAM_INVALID_INDEX) { 22056 _BCM_OAM_UNLOCK(oc); 22057 return BCM_E_NOT_FOUND; 22058 } 22059 /* Check profile id is in use or not */ 22060 if (!(_BCM_KT2_PM_CTRL_PROFILE_IN_USE(pmc, *profile_id))) { 22061 /* It is not in use. Return error */ 22062 /* Ideally this should not happen */ 22063 _BCM_OAM_UNLOCK(oc); 22064 return BCM_E_INTERNAL; 22065 } 22066 22067 _BCM_OAM_UNLOCK(oc); 22068 return BCM_E_NONE; 22069 } 22070 22071 /* 22072 * Function: 22073 * bcm_kt2_oam_csf_add 22074 * Purpose: 22075 * Start CSF PDU transmission 22076 * Parameters: 22077 * unit - (IN) Unit number. 22078 * csf_ptr - (INOUT) CSF object 22079 * Returns: 22080 * BCM_E_XXX 22081 * Notes: 22082 */ 22083 int bcm_kt2_oam_csf_add(int unit, bcm_oam_csf_t *csf_p) 22084 { 22085 _bcm_oam_control_t *oc; 22086 _bcm_oam_hash_data_t *h_data_p; 22087 bhh_sdk_msg_ctrl_csf_add_t msg; 22088 uint8 *buffer, *buffer_ptr; 22089 uint16 buffer_len, reply_len; 22090 int sess_id = 0; 22091 int rv = BCM_E_NONE; 22092 22093 /* Get OAM Control Structure. */ 22094 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 22095 _BCM_OAM_LOCK(oc); 22096 22097 if (oc->ukernel_not_ready) { 22098 _BCM_OAM_UNLOCK(oc); 22099 return BCM_E_INIT; 22100 } 22101 22102 BCM_OAM_BHH_VALIDATE_EP(csf_p->id); 22103 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id); 22104 22105 /* Check endpoint status. */ 22106 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 22107 if ((BCM_E_EXISTS != rv)) { 22108 /* Endpoint not in use. */ 22109 LOG_ERROR(BSL_LS_BCM_OAM, 22110 (BSL_META_U(unit, 22111 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 22112 unit, csf_p->id, bcm_errmsg(rv))); 22113 _BCM_OAM_UNLOCK(oc); 22114 return (rv); 22115 } 22116 22117 if ((csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1S) && 22118 (csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1M)) { 22119 /* Only 1S and 1M are supported */ 22120 _BCM_OAM_UNLOCK(oc); 22121 return BCM_E_PARAM; 22122 } 22123 22124 h_data_p = &oc->oam_hash_data[csf_p->id]; 22125 /* 22126 * Only BHH is supported 22127 */ 22128 if (!BHH_EP_TYPE(h_data_p)) { 22129 _BCM_OAM_UNLOCK(oc); 22130 return BCM_E_UNAVAIL; 22131 } 22132 22133 sal_memset(&msg, 0, sizeof(msg)); 22134 msg.sess_id = sess_id; 22135 msg.int_pri = csf_p->int_pri; 22136 msg.pkt_pri = csf_p->pkt_pri; 22137 22138 switch(csf_p->type) { 22139 case BCM_OAM_CSF_LOS: 22140 msg.type = SHR_CSF_TYPE_LOS; 22141 break; 22142 22143 case BCM_OAM_CSF_FDI: 22144 msg.type = SHR_CSF_TYPE_FDI; 22145 break; 22146 22147 case BCM_OAM_CSF_RDI: 22148 msg.type = SHR_CSF_TYPE_RDI; 22149 break; 22150 22151 case BCM_OAM_CSF_DCI: 22152 msg.type = SHR_CSF_TYPE_DCI; 22153 break; 22154 22155 default: 22156 _BCM_OAM_UNLOCK(oc); 22157 return BCM_E_PARAM; 22158 } 22159 22160 /* 22161 * Set period 22162 */ 22163 msg.period = csf_p->period; 22164 22165 /* Pack control message data into DMA buffer */ 22166 buffer = oc->dma_buffer; 22167 buffer_ptr = bhh_sdk_msg_ctrl_csf_add_pack(buffer, &msg); 22168 buffer_len = buffer_ptr - buffer; 22169 22170 /* Send BHH Session Update message to uC */ 22171 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 22172 MOS_MSG_SUBCLASS_BHH_CSF_ADD, 22173 buffer_len, 0, 22174 MOS_MSG_SUBCLASS_BHH_CSF_ADD_REPLY, 22175 &reply_len); 22176 22177 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 22178 rv = BCM_E_INTERNAL; 22179 } 22180 22181 _BCM_OAM_UNLOCK(oc); 22182 return rv; 22183 } 22184 22185 /* 22186 * Function: 22187 * bcm_kt2_oam_csf_get 22188 * Purpose: 22189 * Get CSF info 22190 * Parameters: 22191 * unit - (IN) Unit number. 22192 * csf_ptr - (OUT) CSF object 22193 * Returns: 22194 * BCM_E_XXX 22195 * Notes: 22196 */ 22197 int bcm_kt2_oam_csf_get(int unit, bcm_oam_csf_t *csf_p) 22198 { 22199 _bcm_oam_control_t *oc; 22200 bhh_sdk_msg_ctrl_csf_get_t msg; 22201 _bcm_oam_hash_data_t *h_data_p; 22202 uint8 *buffer, *buffer_ptr; 22203 uint16 buffer_len, reply_len; 22204 int sess_id = 0; 22205 int rv = BCM_E_NONE; 22206 22207 /* Get OAM Control Structure. */ 22208 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 22209 _BCM_OAM_LOCK(oc); 22210 22211 if (oc->ukernel_not_ready) { 22212 _BCM_OAM_UNLOCK(oc); 22213 return BCM_E_INIT; 22214 } 22215 22216 BCM_OAM_BHH_VALIDATE_EP(csf_p->id); 22217 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id); 22218 22219 /* Check endpoint status. */ 22220 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 22221 if ((BCM_E_EXISTS != rv)) { 22222 /* Endpoint not in use. */ 22223 LOG_ERROR(BSL_LS_BCM_OAM, 22224 (BSL_META_U(unit, 22225 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 22226 unit, csf_p->id, bcm_errmsg(rv))); 22227 _BCM_OAM_UNLOCK(oc); 22228 return (rv); 22229 } 22230 22231 h_data_p = &oc->oam_hash_data[csf_p->id]; 22232 22233 if (!BHH_EP_TYPE(h_data_p)) { 22234 _BCM_OAM_UNLOCK(oc); 22235 return BCM_E_UNAVAIL; 22236 } 22237 22238 22239 sal_memset(&msg, 0, sizeof(msg)); 22240 22241 /* Send BHH Session Update message to uC */ 22242 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 22243 MOS_MSG_SUBCLASS_BHH_CSF_GET, 22244 sess_id, 0, 22245 MOS_MSG_SUBCLASS_BHH_CSF_GET_REPLY, 22246 &reply_len); 22247 if(BCM_FAILURE(rv)) { 22248 LOG_ERROR(BSL_LS_BCM_OAM, 22249 (BSL_META_U(unit, 22250 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 22251 unit, csf_p->id, bcm_errmsg(rv))); 22252 _BCM_OAM_UNLOCK(oc); 22253 return (rv); 22254 } 22255 22256 /* Pack control message data into DMA buffer */ 22257 buffer = oc->dma_buffer; 22258 buffer_ptr = bhh_sdk_msg_ctrl_csf_get_unpack(buffer, &msg); 22259 buffer_len = buffer_ptr - buffer; 22260 22261 22262 if (reply_len != buffer_len) { 22263 _BCM_OAM_UNLOCK(oc); 22264 return BCM_E_INTERNAL; 22265 } 22266 22267 switch(msg.type) { 22268 case SHR_CSF_TYPE_LOS: 22269 csf_p->type = BCM_OAM_CSF_LOS; 22270 break; 22271 22272 case SHR_CSF_TYPE_FDI: 22273 csf_p->type = BCM_OAM_CSF_FDI; 22274 break; 22275 22276 case SHR_CSF_TYPE_RDI: 22277 csf_p->type = BCM_OAM_CSF_RDI; 22278 break; 22279 22280 case SHR_CSF_TYPE_DCI: 22281 csf_p->type = BCM_OAM_CSF_DCI; 22282 break; 22283 22284 default: 22285 _BCM_OAM_UNLOCK(oc); 22286 return BCM_E_INTERNAL; 22287 } 22288 22289 csf_p->period = msg.period; 22290 csf_p->flags = msg.flags; 22291 csf_p->pkt_pri = msg.pkt_pri; 22292 csf_p->int_pri = msg.int_pri; 22293 22294 22295 _BCM_OAM_UNLOCK(oc); 22296 return BCM_E_NONE; 22297 22298 } 22299 22300 /* 22301 * Function: 22302 * bcm_kt2_oam_csf_delete 22303 * Purpose: 22304 * Stop CSF PDU transmission 22305 * Parameters: 22306 * unit - (IN Unit number. 22307 * csf_ptr - (IN) CSF object 22308 * Returns: 22309 * BCM_E_XXX 22310 * Notes: 22311 */ 22312 int bcm_kt2_oam_csf_delete(int unit, bcm_oam_csf_t *csf_p) 22313 { 22314 _bcm_oam_control_t *oc; 22315 _bcm_oam_hash_data_t *h_data_p; 22316 uint16 reply_len; 22317 int sess_id; 22318 int rv = BCM_E_NONE; 22319 22320 /* Get OAM Control Structure. */ 22321 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 22322 _BCM_OAM_LOCK(oc); 22323 22324 if (oc->ukernel_not_ready) { 22325 _BCM_OAM_UNLOCK(oc); 22326 return BCM_E_INIT; 22327 } 22328 22329 BCM_OAM_BHH_VALIDATE_EP(csf_p->id); 22330 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id); 22331 22332 /* Check endpoint status. */ 22333 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 22334 if ((BCM_E_EXISTS != rv)) { 22335 /* Endpoint not in use. */ 22336 LOG_ERROR(BSL_LS_BCM_OAM, 22337 (BSL_META_U(unit, 22338 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 22339 unit, csf_p->id, bcm_errmsg(rv))); 22340 _BCM_OAM_UNLOCK(oc); 22341 return (rv); 22342 } 22343 22344 h_data_p = &oc->oam_hash_data[csf_p->id]; 22345 22346 if (!BHH_EP_TYPE(h_data_p)) { 22347 _BCM_OAM_UNLOCK(oc); 22348 return BCM_E_UNAVAIL; 22349 } 22350 22351 /* Send BHH Session Update message to uC */ 22352 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 22353 MOS_MSG_SUBCLASS_BHH_CSF_DELETE, 22354 sess_id, 0, 22355 MOS_MSG_SUBCLASS_BHH_CSF_DELETE_REPLY, 22356 &reply_len); 22357 _BCM_OAM_UNLOCK(oc); 22358 return (rv); 22359 } 22360 #endif /* defined(INCLUDE_BHH) */ 22361 22362 /* 22363 * Function: 22364 * _bcm_kt2_bhh_endpoint_faults_multi_get 22365 * Purpose: 22366 * Function to get faults for multiple BHH endpoints 22367 * in a single call. 22368 * Parameters: 22369 * unit (IN) BCM device number 22370 * flags (IN) Flags is kept unused as of now. 22371 * This is for any future enhancement 22372 * max_endpoints (IN) Number of max endpoint for the protocol 22373 * faults (OUT) Pointer to faults for all endpoints 22374 * endpoint_count (OUT) Pointer to Number of valid endpoints with faults, 22375 * filled by get API. 22376 * 22377 * Returns: 22378 * BCM_E_NONE No error 22379 * BCM_E_XXXX Error 22380 */ 22381 22382 #if defined (INCLUDE_BHH) 22383 int _bcm_kt2_bhh_endpoint_faults_multi_get( 22384 int unit, 22385 uint32 flags, 22386 uint32 max_endpoints, 22387 bcm_oam_endpoint_fault_t *faults, 22388 uint32 *endpoint_count) 22389 { 22390 int rv = BCM_E_NONE; 22391 _bcm_oam_control_t *oc = NULL; 22392 bcm_oam_endpoint_fault_t *faults_temp = faults; 22393 uint8 *buffer; 22394 uint16 reply_len; 22395 uint32 sess_count; 22396 uint32 ep_id; 22397 uint32 ep_count = 0; 22398 uint32 faults_bitmap; 22399 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 22400 22401 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 22402 22403 _BCM_OAM_LOCK(oc); 22404 22405 if(max_endpoints != oc->bhh_endpoint_count) { 22406 rv = BCM_E_PARAM; 22407 _BCM_OAM_UNLOCK(oc); 22408 return (rv); 22409 } 22410 22411 sal_memset(faults, 0, ((sizeof(bcm_oam_endpoint_fault_t))*max_endpoints)); 22412 22413 rv = _bcm_kt2_oam_bhh_msg_send_receive(unit, 22414 MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET, 22415 0, 0, 22416 MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET_REPLY, 22417 &reply_len); 22418 22419 if (BCM_FAILURE(rv)) { 22420 LOG_ERROR(BSL_LS_BCM_OAM, 22421 (BSL_META_U(unit, 22422 "OAM(unit %d) Error: BHH uKernel msg failed for" 22423 "faults multi get %s.\n"), unit, 22424 bcm_errmsg(rv))); 22425 _BCM_OAM_UNLOCK(oc); 22426 return (rv); 22427 } 22428 22429 if(reply_len != (oc->bhh_endpoint_count * sizeof(uint32))) { 22430 rv = BCM_E_INTERNAL; 22431 _BCM_OAM_UNLOCK(oc); 22432 return (rv); 22433 } 22434 /* Unpack control message data into DMA buffer */ 22435 buffer = oc->dma_buffer; 22436 for(sess_count = 0;sess_count < oc->bhh_endpoint_count;sess_count++) 22437 { 22438 ep_id = BCM_OAM_BHH_GET_SDK_EP(sess_count); 22439 22440 /* Validate endpoint index value. */ 22441 BCM_OAM_BHH_VALIDATE_EP(ep_id); 22442 22443 h_data_p = &oc->oam_hash_data[ep_id]; 22444 22445 /* If endpoint not in use, ignore and continue for next session_id). 22446 * If session is running in hostCPU, skip and Go to ep_id.*/ 22447 if(!(h_data_p->in_use) || (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) { 22448 continue; 22449 } 22450 22451 _SHR_UNPACK_U32(buffer, faults_bitmap); 22452 22453 faults_temp->endpoint_id = BCM_OAM_BHH_GET_SDK_EP(sess_count); 22454 22455 if(faults_bitmap & BHH_BTE_EVENT_CCM_TIMEOUT){ 22456 faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT; 22457 } 22458 if(faults_bitmap & BHH_BTE_EVENT_CCM_RDI){ 22459 faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_RDI; 22460 } 22461 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){ 22462 faults_temp->faults |= 22463 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL; 22464 } 22465 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){ 22466 faults_temp->faults |= 22467 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID; 22468 } 22469 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){ 22470 faults_temp->faults |= 22471 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID; 22472 } 22473 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){ 22474 faults_temp->faults |= 22475 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD; 22476 } 22477 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){ 22478 faults_temp->faults |= 22479 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY; 22480 } 22481 22482 ep_count++; 22483 faults_temp++; 22484 22485 } 22486 22487 *endpoint_count = ep_count; 22488 _BCM_OAM_UNLOCK(oc); 22489 return (rv); 22490 22491 } 22492 #endif 22493 22494 /* Function: 22495 * bcm_kt2_oam_endpoint_faults_multi_get 22496 * Purpose: 22497 * Function to get faults for multiple endpoints per protocl 22498 * in a single call. 22499 * Parameters: 22500 * unit (IN) BCM device number 22501 * flags (IN) Flags is kept unused as of now. 22502 * This is for any future enhancement 22503 * endpoint_protocol (IN) Protocol type of the endpoints to retrieve faults 22504 * max_endpoints (IN) Number of max endpoint for the protocol 22505 * faults (OUT) Pointer to faults for all endpoints 22506 * endpoint_count (OUT) Pointer to Number of valid endpoints with faults, 22507 * by get API. 22508 * 22509 * Returns: 22510 * BCM_E_NONE No error 22511 * BCM_E_XXXX Error 22512 */ 22513 int bcm_kt2_oam_endpoint_faults_multi_get( 22514 int unit, 22515 uint32 flags, 22516 bcm_oam_protocol_type_t endpoint_protocol, 22517 uint32 max_endpoints, 22518 bcm_oam_endpoint_fault_t *faults, 22519 uint32 *endpoint_count) 22520 22521 { 22522 int rv = BCM_E_NONE; 22523 22524 if(!faults) { 22525 rv = BCM_E_PARAM; 22526 return (rv); 22527 } 22528 22529 switch(endpoint_protocol) { 22530 22531 #if defined(INCLUDE_BHH) 22532 case bcmOamProtocolBhh: 22533 *endpoint_count = 0; 22534 rv = _bcm_kt2_bhh_endpoint_faults_multi_get( 22535 unit, 22536 flags, 22537 max_endpoints, 22538 faults, 22539 endpoint_count); 22540 break; 22541 #endif 22542 default: 22543 rv = BCM_E_UNAVAIL; 22544 break; 22545 } 22546 22547 return rv; 22548 22549 } 22550 22551 /* This function assumes passed endpoint is a PORT MEP configured over trunk. */ 22552 int _bcm_kt2_oam_ep_trunk_ports_add_del_internal(int unit, _bcm_oam_hash_data_t *h_data_p, 22553 int max_ports, bcm_gport_t *port_arr, uint8 add) 22554 { 22555 _bcm_oam_hash_data_t old_hash_data; 22556 bcm_oam_endpoint_info_t ep_info; 22557 uint32 sglp = 0, dglp = 0; 22558 bcm_port_t src_pp_port = 0, dst_pp_port = 0, pp_port = 0; 22559 uint32 svp = 0; 22560 int vp_valid = 0; 22561 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 22562 bcm_gport_t tx_gport; 22563 int i, module_id = 0; 22564 uint8 active_mdl = 0; 22565 22566 22567 bcm_oam_endpoint_info_t_init(&ep_info); 22568 /* ********************************************** 22569 * SW configurations 22570 */ 22571 /* Keep a copy of old hash data for comparisons. 22572 */ 22573 sal_memcpy(&old_hash_data, h_data_p, sizeof(_bcm_oam_hash_data_t)); 22574 22575 22576 /* Call endpoint get to get the endpoint info */ 22577 BCM_IF_ERROR_RETURN(bcm_kt2_oam_endpoint_get(unit, h_data_p->ep_id, &ep_info)); 22578 /* First call endpoint gport resolve to correctly update new 22579 * sglp, dglp, src_pp_port, dst_pp_port variables. 22580 */ 22581 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_endpoint_gport_resolve(unit, &ep_info, &sglp, &dglp, 22582 &src_pp_port, &dst_pp_port, &svp, 22583 &trunk_id, &vp_valid, &tx_gport)); 22584 22585 /* Update the h_data_p. */ 22586 h_data_p->sglp = sglp; 22587 h_data_p->dglp = dglp; 22588 h_data_p->src_pp_port = src_pp_port; 22589 h_data_p->dst_pp_port = dst_pp_port; 22590 h_data_p->resolved_trunk_gport = tx_gport; 22591 22592 /* ************************************************ 22593 * HW configurations 22594 */ 22595 22596 for (i = 0; i < max_ports; i++) { 22597 BCM_IF_ERROR_RETURN 22598 (_bcm_kt2_pp_port_to_modport_get(unit, port_arr[i], 22599 &module_id, &pp_port)); 22600 if (add) { 22601 /* _bcm_kt2_oam_trunk_port_mdl_config needs to be called so that 22602 * new trunk members are programmed with MDL_BITMAP correctly. 22603 */ 22604 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_stm_table_update(unit, module_id, pp_port, h_data_p)); 22605 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_port_mdl_update(unit, pp_port, 0, h_data_p, &active_mdl)); 22606 } else { 22607 /* Delete the old ports' MDL BITMAP using _bcm_kt2_oam_port_mdl_update. And 22608 * clear STM table if this is the last endpoint on this port. 22609 */ 22610 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_port_mdl_update(unit, pp_port, 1, h_data_p, &active_mdl)); 22611 if (active_mdl == 0) { 22612 /* Setting index = -1 so that rx indexes are not freed up, since there are 22613 * other ports on the trunk on which this endpoint is placed. 22614 */ 22615 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_stm_table_clear(unit, module_id, -1, 22616 pp_port, 22617 h_data_p)); 22618 } 22619 } 22620 } 22621 22622 if (h_data_p->dst_pp_port != old_hash_data.dst_pp_port) { 22623 /* If dst_pp_port has changed, delete the old EGR_PORT MDL_PASSIVE BITMAP and 22624 * program the new port's EGR_PORT MDL_PASSIVE_BITMAP. 22625 */ 22626 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_port_mdl_passive_update(unit,1, &old_hash_data, 0)); 22627 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_port_mdl_passive_update(unit, 0 /* not reset */, 22628 h_data_p, active_mdl)); 22629 22630 if (ep_info.ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) { 22631 /* If dst_pp_port has changed, modify the LMEP table to reflect new 22632 * dst pp port and corresponding queue number. 22633 */ 22634 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_lmep_down_modify_new_dest_port(unit, h_data_p)); 22635 } 22636 } 22637 22638 return BCM_E_NONE; 22639 } 22640 22641 22642 int _bcm_kt2_oam_trunk_ports_add_del_internal(int unit, bcm_gport_t trunk_gport, 22643 int max_ports, bcm_gport_t *port_arr, uint8 add) 22644 { 22645 int rv = BCM_E_NONE; 22646 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 22647 _bcm_oam_control_t *oc = NULL; 22648 _bcm_oam_hash_data_t *h_data_p = NULL; 22649 int i; 22650 22651 22652 /* Validate port array and max ports inputs */ 22653 if (port_arr == NULL || max_ports == 0) { 22654 return BCM_E_PARAM; 22655 } 22656 22657 /* Check the gport is TRUNK */ 22658 if (!(BCM_GPORT_IS_TRUNK(trunk_gport))) { 22659 return BCM_E_PARAM; 22660 } 22661 22662 /* Get Trunk ID value from Gport */ 22663 trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport); 22664 22665 if (trunk_id == BCM_TRUNK_INVALID) { 22666 return BCM_E_PARAM; 22667 } 22668 22669 /* Get OAM control structure */ 22670 BCM_IF_ERROR_RETURN(_bcm_kt2_oam_control_get(unit, &oc)); 22671 _BCM_OAM_LOCK(oc); 22672 22673 for (i = 0; i < oc->ep_count; i++) { 22674 h_data_p = &oc->oam_hash_data[i]; 22675 /* This API is supported only for PORT MEPs on Trunks */ 22676 if ((ETH_TYPE(h_data_p->type)) && 22677 (h_data_p->in_use) && 22678 (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) && 22679 (h_data_p->gport == trunk_gport) && 22680 (h_data_p->trunk_id == trunk_id)) { 22681 rv = _bcm_kt2_oam_ep_trunk_ports_add_del_internal(unit, h_data_p, max_ports, port_arr, add); 22682 if (BCM_FAILURE(rv)) { 22683 _BCM_OAM_UNLOCK(oc); 22684 return rv; 22685 } 22686 } 22687 } 22688 _BCM_OAM_UNLOCK(oc); 22689 return rv; 22690 } 22691 22692 int bcm_kt2_oam_trunk_ports_add(int unit, bcm_gport_t trunk_gport, 22693 int max_ports, bcm_gport_t *port_arr) 22694 { 22695 return _bcm_kt2_oam_trunk_ports_add_del_internal(unit, trunk_gport, max_ports, port_arr, 1); 22696 } 22697 int bcm_kt2_oam_trunk_ports_delete(int unit, bcm_gport_t trunk_gport, 22698 int max_ports, bcm_gport_t *port_arr) 22699 { 22700 return _bcm_kt2_oam_trunk_ports_add_del_internal(unit, trunk_gport, max_ports, port_arr, 0); 22701 } 22702 #endif /* BCM_KATANA2_SUPPORT */