oam.c (559227B)
1 /* 2 * 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 * 8 * File: 9 * oam.c 10 * 11 * Purpose: 12 * OAM implementation for Triumph3 family of devices. 13 */ 14 15 #include <shared/bsl.h> 16 17 #include <sal/core/libc.h> 18 #include <soc/defs.h> 19 #include <soc/drv.h> 20 #include <soc/scache.h> 21 #include <soc/profile_mem.h> 22 #include <soc/hash.h> 23 #include <soc/l3x.h> 24 #include <soc/triumph3.h> 25 #include <soc/ism_hash.h> 26 27 #include <bcm/l3.h> 28 #include <bcm/oam.h> 29 30 #include <bcm_int/esw/oam.h> 31 #include <bcm_int/esw/port.h> 32 #include <bcm_int/esw/l3.h> 33 #include <bcm_int/esw/switch.h> 34 #include <bcm_int/esw/triumph3.h> 35 #include <bcm_int/esw/virtual.h> 36 #include <bcm_int/esw_dispatch.h> 37 38 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 39 #include <bcm_int/esw/bhh.h> 40 #include <bcm_int/esw/bhh_sdk_pack.h> 41 #include <soc/uc.h> 42 #endif /* BCM_TRIUMPH3_SUPPORT */ 43 #if defined(BCM_HURRICANE2_SUPPORT) 44 #include <soc/hurricane2.h> 45 #endif 46 #if defined(BCM_GREYHOUND_SUPPORT) 47 #include <soc/greyhound.h> 48 #endif 49 #if defined(BCM_HURRICANE3_SUPPORT) 50 #include <soc/hurricane3.h> 51 #endif 52 #if defined(BCM_GREYHOUND2_SUPPORT) 53 #include <soc/greyhound2.h> 54 #endif 55 #if defined(BCM_TRIUMPH3_SUPPORT) || defined(BCM_HURRICANE2_SUPPORT) 56 57 /* 58 * Device OAM control structure. 59 */ 60 _bcm_oam_control_t *_oam_control[SOC_MAX_NUM_DEVICES]; 61 62 /* * * * * * * * * * * * * * * * * * * 63 * OAM MACROS * 64 */ 65 /* 66 * Macro: 67 * _BCM_OAM_IS_INIT (internal) 68 * Purpose: 69 * Check that the unit is valid and confirm that the oam functions 70 * are initialized. 71 * Parameters: 72 * unit - BCM device number 73 * Notes: 74 * Results in return(BCM_E_UNIT), return(BCM_E_UNAVAIL), or 75 * return(BCM_E_INIT) if fails. 76 */ 77 #define _BCM_OAM_IS_INIT(unit) \ 78 do { \ 79 if (!soc_feature(unit, soc_feature_oam)) { \ 80 return (BCM_E_UNAVAIL); \ 81 } \ 82 if (_oam_control[unit] == NULL) { \ 83 LOG_ERROR(BSL_LS_BCM_OAM, \ 84 (BSL_META_U(unit, \ 85 "OAM Error: Module not initialized\n"))); \ 86 return (BCM_E_INIT); \ 87 } \ 88 } while (0) 89 90 /* 91 *Macro: 92 * _BCM_OAM_LOCK 93 * Purpose: 94 * Lock take the OAM control mutex 95 * Parameters: 96 * control - Pointer to OAM control structure. 97 */ 98 #define _BCM_OAM_LOCK(control) \ 99 sal_mutex_take((control)->oc_lock, sal_mutex_FOREVER) 100 101 /* 102 * Macro: 103 * _BCM_OAM_UNLOCK 104 * Purpose: 105 * Lock take the OAM control mutex 106 * Parameters: 107 * control - Pointer to OAM control structure. 108 */ 109 #define _BCM_OAM_UNLOCK(control) \ 110 sal_mutex_give((control)->oc_lock); 111 /* 112 * Macro: 113 * _BCM_OAM_HASH_DATA_CLEAR 114 * Purpose: 115 * Clear hash data memory occupied by one endpoint. 116 * Parameters: 117 * _ptr_ - Pointer to endpoint hash data memory. 118 */ 119 #define _BCM_OAM_HASH_DATA_CLEAR(_ptr_) \ 120 sal_memset(_ptr_, 0, sizeof(_bcm_oam_hash_data_t)); 121 122 /* 123 * Macro: 124 * _BCM_OAM_HASH_DATA_HW_IDX_INIT 125 * Purpose: 126 * Initialize hardware indices to invalid index for an endpoint hash data. 127 * Parameters: 128 * _ptr_ - Pointer to endpoint hash data memory. 129 */ 130 #define _BCM_OAM_HASH_DATA_HW_IDX_INIT(_ptr_) \ 131 do { \ 132 (_ptr_)->group_index = (_BCM_OAM_INVALID_INDEX); \ 133 (_ptr_)->remote_index = (_BCM_OAM_INVALID_INDEX); \ 134 (_ptr_)->profile_index = (_BCM_OAM_INVALID_INDEX); \ 135 (_ptr_)->pri_map_index = (_BCM_OAM_INVALID_INDEX); \ 136 (_ptr_)->lm_counter_index = (_BCM_OAM_INVALID_INDEX); \ 137 (_ptr_)->local_tx_index = (_BCM_OAM_INVALID_INDEX); \ 138 (_ptr_)->local_rx_index = (_BCM_OAM_INVALID_INDEX); \ 139 } while (0) 140 /* 141 * Macro: 142 * _BCM_OAM_ALLOC 143 * Purpose: 144 * Generic memory allocation routine. 145 * Parameters: 146 * _ptr_ - Pointer to allocated memory. 147 * _ptype_ - Pointer type. 148 * _size_ - Size of heap memory to be allocated. 149 * _descr_ - Information about this memory allocation. 150 */ 151 #define _BCM_OAM_ALLOC(_ptr_,_ptype_,_size_,_descr_) \ 152 do { \ 153 if (NULL == (_ptr_)) { \ 154 (_ptr_) = (_ptype_ *) sal_alloc((_size_), (_descr_)); \ 155 } \ 156 if((_ptr_) != NULL) { \ 157 sal_memset((_ptr_), 0, (_size_)); \ 158 } else { \ 159 LOG_ERROR(BSL_LS_BCM_OAM, \ 160 (BSL_META("OAM Error: Allocation failure %s\n"), \ 161 (_descr_))); \ 162 } \ 163 } while (0) 164 165 /* 166 * Macro: 167 * _BCM_OAM_GROUP_INDEX_VALIDATE 168 * Purpose: 169 * Validate OAM Group ID value. 170 * Parameters: 171 * _group_ - Group ID value. 172 */ 173 #define _BCM_OAM_GROUP_INDEX_VALIDATE(_group_) \ 174 do { \ 175 if ((_group_) < 0 || (_group_) >= oc->group_count) { \ 176 LOG_ERROR(BSL_LS_BCM_OAM, \ 177 (BSL_META("OAM Error: Invalid Group ID = %d.\n"), \ 178 _group_)); \ 179 return (BCM_E_PARAM); \ 180 } \ 181 } while (0); 182 183 /* 184 * Macro: 185 * _BCM_OAM_EP_INDEX_VALIDATE 186 * Purpose: 187 * Validate OAM Endpoint ID value. 188 * Parameters: 189 * _ep_ - Endpoint ID value. 190 */ 191 #define _BCM_OAM_EP_INDEX_VALIDATE(_ep_) \ 192 do { \ 193 if ((_ep_) < 0 || (_ep_) >= oc->ep_count) { \ 194 LOG_ERROR(BSL_LS_BCM_OAM, \ 195 (BSL_META("OAM Error: Invalid Endpoint ID" \ 196 " = %d.\n"), _ep_)); \ 197 return (BCM_E_PARAM); \ 198 } \ 199 } while (0); 200 201 /* 202 * Macro: 203 * _BCM_OAM_RMEP_INDEX_VALIDATE 204 * Purpose: 205 * Validate OAM Endpoint ID value. 206 * Parameters: 207 * _ep_ - Endpoint ID value. 208 */ 209 #define _BCM_OAM_RMEP_INDEX_VALIDATE(_ep_) \ 210 do { \ 211 if ((_ep_) < 0 || (_ep_) >= oc->rmep_count) { \ 212 LOG_ERROR(BSL_LS_BCM_OAM, \ 213 (BSL_META("OAM Error: Invalid RMEP Index" \ 214 " = %d.\n"), _ep_)); \ 215 return (BCM_E_PARAM); \ 216 } \ 217 } while (0); 218 219 /* 220 * Macro: 221 * _BCM_OAM_KEY_PACK 222 * Purpose: 223 * Pack the hash table look up key fields. 224 * Parameters: 225 * _dest_ - Hash key buffer. 226 * _src_ - Hash key field to be packed. 227 * _size_ - Hash key field size in bytes. 228 */ 229 #define _BCM_OAM_KEY_PACK(_dest_,_src_,_size_) \ 230 do { \ 231 sal_memcpy((_dest_), (_src_), (_size_)); \ 232 (_dest_) += (_size_); \ 233 } while (0) 234 /* 235 * Macro: 236 * _BCM_TR3_OAM_MOD_PORT_TO_GLP 237 * Purpose: 238 * Construct hardware SGLP value from module ID, port ID and Trunk ID value. 239 * Parameters: 240 * _modid_ - Module ID. 241 * _port_ - Port ID. 242 * _trunk_ - Trunk (1 - TRUE/0 - FALSE). 243 * _tgid_ - Trunk ID. 244 */ 245 #define _BCM_TR3_OAM_MOD_PORT_TO_GLP(_u_, _m_, _p_, _t_, _tgid_, _glp_) \ 246 do { \ 247 if ((_tgid_) != -1) { \ 248 (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_)) \ 249 | ((soc_mem_index_count((_u_), TRUNK_GROUPm) - 1) \ 250 & (_tgid_))); \ 251 } else { \ 252 (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_)) \ 253 | ((SOC_MODID_MAX(_u_) & (_m_)) \ 254 << (_shr_popcount((unsigned int) SOC_PORT_ADDR_MAX(_u_))) \ 255 | (SOC_PORT_ADDR_MAX(_u_) & (_p_)))); \ 256 } \ 257 LOG_DEBUG(BSL_LS_BCM_OAM, \ 258 (BSL_META("u:%d m:%d p:%d t:%d tgid:%d glp:%x\n"), \ 259 _u_, _m_, _p_, _t_, _tgid_, _glp_)); \ 260 } while (0) 261 262 /* 263 * LMEPm DESTf format mod_id[15:8] port_id[7:0] 264 */ 265 #define _BCM_OAM_LMEP_DEST_MODID_SHIFT (8) 266 267 /* 268 * Macro: 269 * _BCM_TR3_OAM_MOD_PORT_TO_DGLP 270 * Purpose: 271 * Construct hardware DGLP value from module ID, port ID and Trunk ID value. 272 * Add one to MOD shift as its 8 bit port and 8 bit mod in H/w 273 * Parameters: 274 * _modid_ - Module ID. 275 * _port_ - Port ID. 276 * _trunk_ - Trunk (1 - TRUE/0 - FALSE). 277 * _tgid_ - Trunk ID. 278 */ 279 #define _BCM_TR3_OAM_MOD_PORT_TO_DGLP(_u_, _m_, _p_, _t_, _tgid_, _glp_) \ 280 do { \ 281 if ((_tgid_) != -1) { \ 282 (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_)) \ 283 | ((soc_mem_index_count((_u_), TRUNK_GROUPm) - 1) \ 284 & (_tgid_))); \ 285 } else { \ 286 (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_)) \ 287 | ((SOC_MODID_MAX(_u_) & (_m_)) << \ 288 (_BCM_OAM_LMEP_DEST_MODID_SHIFT) \ 289 | (SOC_PORT_ADDR_MAX(_u_) & (_p_)))); \ 290 } \ 291 LOG_DEBUG(BSL_LS_BCM_OAM, \ 292 (BSL_META("u:%d m:%d p:%d t:%d tgid:%d glp:%x\n"), \ 293 _u_, _m_, _p_, _t_, _tgid_, _glp_)); \ 294 } while (0) 295 296 /* 297 * Macro: 298 * _BCM_OAM_GLP_XXX 299 * Purpose: 300 * Get components of generic logical port value. 301 * Parameters: 302 * _glp_ - Generic logical port. 303 */ 304 #define _BCM_OAM_GLP_TRUNK_BIT_GET(_u_,_glp_) \ 305 (0x1 & ((_glp_) >> SOC_TRUNK_BIT_POS(_u_))) 306 307 #define _BCM_OAM_GLP_TRUNK_ID_GET(_u_,_glp_) \ 308 ((soc_mem_index_count((_u_), TRUNK_GROUPm) - 1) & (_glp_)) 309 310 #define _BCM_OAM_GLP_MODULE_ID_GET(_u_,_glp_) \ 311 (SOC_MODID_MAX(_u_)& \ 312 ((_glp_) >> _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit)))) 313 314 #define _BCM_OAM_GLP_PORT_GET(_u_,_glp_) \ 315 (SOC_PORT_ADDR_MAX(_u_) & (_glp_)) 316 /* To recover Module Id from H/w DGLP field */ 317 #define _BCM_OAM_DGLP_MODULE_ID_GET(_glp_) (0xFF & ((_glp_) >> \ 318 _BCM_OAM_LMEP_DEST_MODID_SHIFT)) 319 320 /* 321 * Macro: 322 * _BCM_OAM_EP_LEVEL_XXX 323 * Purpose: 324 * Maintenance domain level bit count and level max value. 325 * Parameters: 326 * _glp_ - Generic logical port. 327 */ 328 #define _BCM_OAM_EP_LEVEL_COUNT (1 << (_BCM_OAM_EP_LEVEL_BIT_COUNT)) 329 #define _BCM_OAM_EP_LEVEL_MAX (_BCM_OAM_EP_LEVEL_COUNT - 1) 330 331 /* 332 * Macro: 333 * BCM_WB_XXX 334 * Purpose: 335 * OAM module scache version information. 336 * Parameters: 337 * (major number, minor number) 338 */ 339 #ifdef BCM_WARM_BOOT_SUPPORT 340 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 341 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 342 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 343 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 344 #define BCM_WB_VERSION_1_4 SOC_SCACHE_VERSION(1,4) 345 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_4 346 #endif 347 /* * * * * * * * * * * * * * * * * * * * * * * * * 348 * OAM function prototypes * 349 */ 350 #ifdef BCM_WARM_BOOT_SUPPORT 351 STATIC int 352 _bcm_tr3_oam_bhh_hw_config_scache_size_get (int unit); 353 #endif 354 355 /* * * * * * * * * * * * * * * * * * * * * * * * * 356 * OAM global data initialization * 357 */ 358 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 359 360 #define BHH_COSQ_INVALID 0xFFFF 361 362 /* 363 * Macro: 364 * _BCM_OAM_BHH_IS_VALID (internal) 365 * Purpose: 366 * Check that the BHH feature is available on this unit 367 * Parameters: 368 * unit - BCM device number 369 * Notes: 370 * Results in return(BCM_E_UNAVAIL), 371 */ 372 #define _BCM_OAM_BHH_IS_VALID(unit) \ 373 do { \ 374 if (!soc_feature(unit, soc_feature_bhh)) { \ 375 return (BCM_E_UNAVAIL); \ 376 } \ 377 } while (0) 378 379 #define BCM_OAM_BHH_GET_UKERNEL_EP(ep) \ 380 (ep - _BCM_OAM_BHH_ENDPOINT_OFFSET) 381 382 #define BCM_OAM_BHH_GET_SDK_EP(ep) \ 383 (ep + _BCM_OAM_BHH_ENDPOINT_OFFSET) 384 385 #define BCM_OAM_BHH_VALIDATE_EP(_ep_) \ 386 do { \ 387 if (((_ep_) < _BCM_OAM_BHH_ENDPOINT_OFFSET) || \ 388 ((_ep_) >= (_BCM_OAM_BHH_ENDPOINT_OFFSET \ 389 + oc->bhh_endpoint_count))) { \ 390 LOG_ERROR(BSL_LS_BCM_OAM, \ 391 (BSL_META("OAM Error: Invalid Endpoint ID" \ 392 " = %d.\n"), _ep_)); \ 393 _BCM_OAM_UNLOCK(oc); \ 394 return (BCM_E_PARAM); \ 395 } \ 396 } while (0); 397 398 #define BCM_OAM_BHH_ABS(x) (((x) < 0) ? (-(x)) : (x)) 399 400 STATIC int 401 _bcm_tr3_oam_bhh_session_hw_delete(int unit, _bcm_oam_hash_data_t *h_data_p); 402 STATIC int 403 _bcm_tr3_oam_bhh_msg_send_receive(int unit, uint8 s_subclass, 404 uint16 s_len, uint32 s_data, 405 uint8 r_subclass, uint16 *r_len, sal_usecs_t timeout); 406 STATIC int 407 _bcm_tr3_oam_bhh_hw_init(int unit); 408 STATIC void 409 _bcm_tr3_oam_bhh_callback_thread(void *param); 410 STATIC int 411 _bcm_tr3_oam_bhh_event_mask_set(int unit); 412 STATIC int 413 bcm_tr3_oam_bhh_endpoint_create(int unit, 414 bcm_oam_endpoint_info_t *endpoint_info, 415 _bcm_oam_hash_key_t *hash_key); 416 STATIC int 417 _bcm_tr3_oam_bhh_fp_init(int unit); 418 419 static int tr3_oam_mpls_tp_ach_channel_type = SHR_BHH_ACH_CHANNEL_TYPE; 420 #endif /* INCLUDE_BHH */ 421 422 /* 423 * Triumph3 device OAM CCM intervals array initialization.. 424 */ 425 static uint32 _tr3_ccm_intervals[] = 426 { 427 BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED, 428 BCM_OAM_ENDPOINT_CCM_PERIOD_3MS, 429 BCM_OAM_ENDPOINT_CCM_PERIOD_10MS, 430 BCM_OAM_ENDPOINT_CCM_PERIOD_100MS, 431 BCM_OAM_ENDPOINT_CCM_PERIOD_1S, 432 BCM_OAM_ENDPOINT_CCM_PERIOD_10S, 433 BCM_OAM_ENDPOINT_CCM_PERIOD_1M, 434 BCM_OAM_ENDPOINT_CCM_PERIOD_10M, 435 _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED 436 }; 437 438 /* 439 * OAM hardware interrupts to software events mapping array initialization. 440 * _tr3_oam_interrupts[] = 441 * {Interrupt status register, Remote MEP index field, MA index field, 442 * CCM_INTERRUPT_CONTROLr - Interrupt status Field, 443 * OAM event type}. 444 */ 445 static _bcm_oam_interrupt_t _tr3_oam_interrupts[] = 446 { 447 /* 1. Port down interrupt. */ 448 {ANY_RMEP_TLV_PORT_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 449 ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf, 450 bcmOAMEventEndpointPortDown}, 451 452 /* 2. Port up interrupt. */ 453 {ANY_RMEP_TLV_PORT_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 454 ANY_RMEP_TLV_PORT_UP_INT_ENABLEf, 455 bcmOAMEventEndpointPortUp}, 456 457 /* 3. Interface down interrupt. */ 458 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 459 ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf, 460 bcmOAMEventEndpointInterfaceDown}, 461 462 /* 4. Interface up interrupt. */ 463 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 464 ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf, 465 bcmOAMEventEndpointInterfaceUp}, 466 467 /* 5. Interface TLV Testing to Up interrupt. */ 468 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 469 ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf, 470 bcmOAMEventEndpointInterfaceTestingToUp}, 471 472 /* 6. Interface TLV Unknown to Up interrupt. */ 473 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 474 ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf, 475 bcmOAMEventEndpointInterfaceUnknownToUp}, 476 477 /* 7. Interface TLV Dormant to Up interrupt. */ 478 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 479 ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf, 480 bcmOAMEventEndpointInterfaceDormantToUp}, 481 482 /* 8. Interface TLV Not present to Up interrupt. */ 483 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 484 ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf, 485 bcmOAMEventEndpointInterfaceNotPresentToUp}, 486 487 /* 9. Interface Link Layer Down to Up interrupt. */ 488 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 489 ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf, 490 bcmOAMEventEndpointInterfaceLLDownToUp}, 491 492 /* 10. Interface up to testing transition interrupt. */ 493 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 494 ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf, 495 bcmOAMEventEndpointInterfaceTesting}, 496 497 /* 11. Interface up to unknown transition interrupt. */ 498 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 499 ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf, 500 bcmOAMEventEndpointInterfaceUnkonwn}, 501 502 /* 12. Interface up to dormant transition interrupt. */ 503 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 504 ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf, 505 bcmOAMEventEndpointInterfaceDormant}, 506 507 /* 13. Interface up to not present transition interrupt. */ 508 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 509 ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf, 510 bcmOAMEventEndpointInterfaceNotPresent}, 511 512 /* 14. Interface up to Link Layer Down transition interrupt. */ 513 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 514 ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf, 515 bcmOAMEventEndpointInterfaceLLDown}, 516 517 /* 15. Low MDL or unexpected MAID interrupt. */ 518 {XCON_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf, 519 XCON_CCM_DEFECT_INT_ENABLEf, 520 bcmOAMEventGroupCCMxcon}, 521 522 /* 523 * 16. Remote MEP lookup failed or CCM interval mismatch during Remote MEP 524 * lookup interrupt. 525 */ 526 {ERROR_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf, 527 ERROR_CCM_DEFECT_INT_ENABLEf, 528 bcmOAMEventGroupCCMError}, 529 530 /* 531 * 17. Some Remote defect indicator interrupt - aggregated health of remote 532 * MEPs. 533 */ 534 {SOME_RDI_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf, 535 SOME_RDI_DEFECT_INT_ENABLEf, 536 bcmOAMEventGroupRemote}, 537 538 /* 18. Aggregate health of remote MEP state machines interrupt. */ 539 {SOME_RMEP_CCM_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf, 540 SOME_RMEP_CCM_DEFECT_INT_ENABLEf, 541 bcmOAMEventGroupCCMTimeout}, 542 543 /* Invalid Interrupt - Always Last */ 544 {INVALIDr, INVALIDf, 0, bcmOAMEventCount} 545 }; 546 547 /* 548 * 0AM Group faults array initialization. 549 */ 550 static _bcm_oam_fault_t _tr3_oam_group_faults[] = 551 { 552 {CURRENT_XCON_CCM_DEFECTf, STICKY_XCON_CCM_DEFECTf, 553 BCM_OAM_GROUP_FAULT_CCM_XCON, 0x08}, 554 555 {CURRENT_ERROR_CCM_DEFECTf, STICKY_ERROR_CCM_DEFECTf, 556 BCM_OAM_GROUP_FAULT_CCM_ERROR, 0x04}, 557 558 {CURRENT_SOME_RMEP_CCM_DEFECTf, STICKY_SOME_RMEP_CCM_DEFECTf, 559 BCM_OAM_GROUP_FAULT_CCM_TIMEOUT, 0x02}, 560 561 {CURRENT_SOME_RDI_DEFECTf, STICKY_SOME_RDI_DEFECTf, 562 BCM_OAM_GROUP_FAULT_REMOTE, 0x01}, 563 564 {0, 0, 0, 0} 565 }; 566 567 /* 568 * 0AM Endpoint faults array initialization. 569 */ 570 static _bcm_oam_fault_t _tr3_oam_endpoint_faults[] = 571 { 572 {CURRENT_RMEP_PORT_STATUS_DEFECTf, 573 STICKY_RMEP_PORT_STATUS_DEFECTf, 574 BCM_OAM_ENDPOINT_FAULT_PORT_DOWN, 0x08}, 575 576 {CURRENT_RMEP_INTERFACE_STATUS_DEFECTf, 577 STICKY_RMEP_INTERFACE_STATUS_DEFECTf, 578 BCM_OAM_ENDPOINT_FAULT_INTERFACE_DOWN, 0x04}, 579 580 {CURRENT_RMEP_CCM_DEFECTf, 581 STICKY_RMEP_CCM_DEFECTf, 582 BCM_OAM_ENDPOINT_FAULT_CCM_TIMEOUT, 0x20}, 583 584 {CURRENT_RMEP_LAST_RDIf, 585 STICKY_RMEP_LAST_RDIf, 586 BCM_OAM_ENDPOINT_FAULT_REMOTE, 0x10}, 587 588 {0, 0, 0, 0} 589 }; 590 591 typedef struct _bcm_tr3_oam_intr_en_fields_s { 592 soc_field_t field; 593 uint32 value; 594 } _bcm_tr3_oam_intr_en_fields_t; 595 596 static _bcm_tr3_oam_intr_en_fields_t _tr3_oam_intr_en_fields[bcmOAMEventCount] = 597 { 598 /* 599 * Note: 600 * The order of hardware field names in the below initialization 601 * code must match the event enum order in bcm_oam_event_type_t. 602 */ 603 { ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf, 1}, 604 { ANY_RMEP_TLV_PORT_UP_INT_ENABLEf, 1}, 605 { ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf, 1}, 606 { ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf, 1}, 607 { ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf, 1}, 608 { ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf, 1}, 609 { ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf, 1}, 610 { ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf, 1}, 611 { ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf, 1}, 612 { ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf, 1}, 613 { ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf, 1}, 614 { ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf, 1}, 615 { ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf, 1}, 616 { ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf, 1}, 617 { XCON_CCM_DEFECT_INT_ENABLEf, 1}, 618 { ERROR_CCM_DEFECT_INT_ENABLEf, 1}, 619 { SOME_RDI_DEFECT_INT_ENABLEf, 1}, 620 { SOME_RMEP_CCM_DEFECT_INT_ENABLEf, 1}, 621 { INVALIDf, 0}, 622 { INVALIDf, 0}, 623 { INVALIDf, 0}, 624 { INVALIDf, 0}, 625 { INVALIDf, 0}, 626 { INVALIDf, 0}, 627 { INVALIDf, 0}, 628 { INVALIDf, 0}, 629 { INVALIDf, 0}, 630 { INVALIDf, 0}, 631 { INVALIDf, 0}, 632 { INVALIDf, 0}, 633 { INVALIDf, 0}, 634 { INVALIDf, 0}, 635 { INVALIDf, 0}, 636 { INVALIDf, 0}, 637 { INVALIDf, 0}, 638 { INVALIDf, 0}, 639 { INVALIDf, 0}, 640 { INVALIDf, 0}, 641 { INVALIDf, 0}, 642 { INVALIDf, 0}, 643 { INVALIDf, 0}, 644 { INVALIDf, 0}, 645 { INVALIDf, 0}, 646 { INVALIDf, 0} 647 }; 648 649 /* For Ethernet OAM Loss & Delay Measurement */ 650 typedef struct _bcm_oam_lm_dm_search_data_type_s { 651 bcm_oam_endpoint_type_t match_type; /* Endpoint Type. */ 652 bcm_oam_endpoint_t match_ep_id; /* Current Endpoint ID, being added. */ 653 bcm_vlan_t match_vlan; /* Vlan on which the EP is added. */ 654 uint32 match_gport; /* Gport on which the EP is added. */ 655 int match_count; /* No. of existing matching EPs 656 (exluding the current). */ 657 uint8 highest_level; /* Highest level of EP on vlan port. */ 658 bcm_oam_endpoint_t highest_level_ep_id; /* Existing matching EP id. */ 659 } _bcm_oam_lm_dm_search_data_type_t; 660 661 static _bcm_oam_lm_dm_search_data_type_t _bcm_oam_lm_dm_search_data; 662 663 STATIC int _bcm_tr3_oam_loss_delay_measurement_delete(int unit, 664 _bcm_oam_control_t *oc, _bcm_oam_hash_data_t *hash_data); 665 666 667 /* * * * * * * * * * * * * * * * * * * * * * * * * 668 * Static local functions * 669 */ 670 /* 671 * Function: 672 * _bcm_tr3_oam_ccm_msecs_to_hw_encode 673 * Purpose: 674 * Quanitze CCM interval from msecs to hardware encoding. 675 * Parameters: 676 * period - (IN) CCM interval in milli seconds. 677 * Retruns: 678 * Hardware encoding for the specified CCM interval value. 679 */ 680 STATIC int 681 _bcm_tr3_oam_ccm_msecs_to_hw_encode(int period) 682 { 683 int q_period = 0; /* Quantized CCM period value. */ 684 685 if (0 == period) { 686 return (q_period); 687 } 688 689 /* Find closest supported period */ 690 for (q_period = 1; _tr3_ccm_intervals[q_period] 691 != _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED; ++q_period) { 692 if (period < _tr3_ccm_intervals[q_period]) { 693 break; 694 } 695 } 696 697 if (_tr3_ccm_intervals[q_period] 698 == _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED) { 699 /* Use the highest defined value */ 700 --q_period; 701 } else { 702 if ((period - _tr3_ccm_intervals[q_period - 1]) 703 < (_tr3_ccm_intervals[q_period] - period)) { 704 /* Closer to the lower value */ 705 --q_period; 706 } 707 } 708 709 return q_period; 710 } 711 712 #if defined(BCM_WARM_BOOT_SUPPORT) 713 /* 714 * Function: 715 * _bcm_tr3_oam_ccm_hw_encode_to_msecs 716 * Purpose: 717 * Get CCM interval in msecs for a given hardware encoded value. 718 * Parameters: 719 * encode - (IN) CCM interval hardware encoding. 720 * Retruns: 721 * CCM interval in msecs. 722 */ 723 STATIC int 724 _bcm_tr3_oam_ccm_hw_encode_to_msecs(int encode) 725 { 726 return (_tr3_ccm_intervals[encode]); 727 } 728 #endif 729 730 /* 731 * Function: 732 * _bcm_tr3_oam_opcode_profile_entry_set 733 * Purpose: 734 * Program the OAM opcode control profile fields. 735 * Parameters: 736 * unit - (IN) BCM device number 737 * flags - (IN) Bitmap of opcode control settings. 738 * entry - (IN/OUT) Pointer to opcode control profile table entry buffer. 739 * Retruns: 740 * BCM_E_XXX 741 */ 742 STATIC int 743 _bcm_tr3_oam_opcode_profile_entry_set(int unit, 744 uint32 flags, 745 uint32 *entry) 746 { 747 uint32 ep_opcode; /* Endpoint opcode flag bits. */ 748 uint32 opcode_count = 0; /* Number of bits set. */ 749 int bp; /* bit position. */ 750 751 /* Validate opcode flag bits. */ 752 if (flags & ~(_BCM_TR3_OAM_OPCODE_MASK)) { 753 return (BCM_E_PARAM); 754 } 755 756 /* Get number of valid opcodes supported. */ 757 opcode_count = _shr_popcount(_BCM_TR3_OAM_OPCODE_MASK); 758 759 /* 760 * Iterate over opcode flag bits and set corresponding fields 761 * in entry buffer. 762 */ 763 for (bp = 0; bp < opcode_count; bp++) { 764 ep_opcode = (flags & (1 << bp)); 765 766 switch (ep_opcode) { 767 case BCM_OAM_OPCODE_CCM_IN_HW: 768 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 769 CCM_PROCESS_IN_HWf, 770 1); 771 break; 772 773 case BCM_OAM_OPCODE_CCM_COPY_TO_CPU: 774 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 775 CCM_COPYTO_CPUf, 1); 776 break; 777 778 case BCM_OAM_OPCODE_CCM_DROP: 779 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 780 CCM_DROPf, 1); 781 break; 782 783 case BCM_OAM_OPCODE_LBM_IN_HW: 784 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 785 LBM_UC_PROCESS_IN_HWf, 786 1); 787 break; 788 789 case BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU: 790 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 791 LBM_UC_COPYTO_CPUf, 792 1); 793 break; 794 795 case BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU: 796 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 797 LBM_MC_COPYTO_CPUf, 798 1); 799 break; 800 801 case BCM_OAM_OPCODE_LBM_MC_DROP: 802 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 803 LBM_MC_DROPf, 1); 804 break; 805 806 case BCM_OAM_OPCODE_LBR_COPY_TO_CPU: 807 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 808 LBR_COPYTO_CPUf, 1); 809 break; 810 811 case BCM_OAM_OPCODE_LBR_DROP: 812 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 813 LBR_DROPf, 1); 814 break; 815 816 case BCM_OAM_OPCODE_LTM_COPY_TO_CPU: 817 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 818 LTM_COPYTO_CPUf, 1); 819 break; 820 821 case BCM_OAM_OPCODE_LTM_DROP: 822 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 823 LTM_DROPf, 1); 824 break; 825 826 case BCM_OAM_OPCODE_LTR_COPY_TO_CPU: 827 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 828 LTR_COPYTO_CPUf, 1); 829 break; 830 831 case BCM_OAM_OPCODE_LTR_DROP: 832 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 833 LTR_DROPf, 1); 834 break; 835 836 case BCM_OAM_OPCODE_LMEP_PKT_FWD: 837 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 838 FWD_LMEP_PKTf, 1); 839 break; 840 841 case BCM_OAM_OPCODE_OTHER_COPY_TO_CPU: 842 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set 843 (unit, entry, OTHER_OPCODE_COPYTO_CPUf, 1); 844 break; 845 846 case BCM_OAM_OPCODE_OTHER_DROP: 847 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 848 OTHER_OPCODE_DROPf, 849 1); 850 break; 851 852 case BCM_OAM_OPCODE_LBM_UC_DROP: 853 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, 854 LBM_UC_DROPf, 1); 855 break; 856 857 default: 858 break; 859 } 860 } 861 862 return (BCM_E_NONE); 863 } 864 865 /* 866 * Function: 867 * _bcm_tr3_oam_opcode_profile_entry_set 868 * Purpose: 869 * Setup default OAM opcode control profile settings for an entry. 870 * Parameters: 871 * unit - (IN) BCM device number 872 * entry - (IN/OUT) Pointer to opcode control profile table entry buffer. 873 * Retruns: 874 * BCM_E_XXX 875 */ 876 int 877 _bcm_tr3_oam_opcode_profile_entry_init(int unit, 878 uint32 *entry) 879 { 880 uint32 opcode; /* Opcode flag bits. */ 881 int rv; /* Operation return status. */ 882 883 opcode = (BCM_OAM_OPCODE_CCM_COPY_TO_CPU | 884 BCM_OAM_OPCODE_CCM_DROP | 885 BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU | 886 BCM_OAM_OPCODE_LBM_UC_DROP | 887 BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU | 888 BCM_OAM_OPCODE_LBM_MC_DROP | 889 BCM_OAM_OPCODE_LBR_COPY_TO_CPU | 890 BCM_OAM_OPCODE_LBR_DROP | 891 BCM_OAM_OPCODE_LTM_COPY_TO_CPU | 892 BCM_OAM_OPCODE_LTM_DROP | 893 BCM_OAM_OPCODE_LTR_COPY_TO_CPU | 894 BCM_OAM_OPCODE_LTR_DROP | 895 BCM_OAM_OPCODE_OTHER_COPY_TO_CPU | 896 BCM_OAM_OPCODE_OTHER_DROP); 897 898 rv = _bcm_tr3_oam_opcode_profile_entry_set(unit, opcode, entry); 899 900 return (rv); 901 } 902 903 /* 904 * Function: 905 * _bcm_oam_ep_hash_key_construct 906 * Purpose: 907 * Construct hash table key for a given endpoint information. 908 * Parameters: 909 * unit - (IN) BCM device number 910 * oc - (IN) Pointer to OAM control structure. 911 * ep_info - (IN) Pointer to endpoint information structure. 912 * key - (IN/OUT) Pointer to hash key buffer. 913 * Retruns: 914 * None 915 */ 916 STATIC void 917 _bcm_oam_ep_hash_key_construct(int unit, 918 _bcm_oam_control_t *oc, 919 bcm_oam_endpoint_info_t *ep_info, 920 _bcm_oam_hash_key_t *key) 921 { 922 uint8 *loc = *key; 923 uint32 direction = 1; 924 925 sal_memset(key, 0, sizeof(_bcm_oam_hash_key_t)); 926 927 if (NULL != ep_info) { 928 929 _BCM_OAM_KEY_PACK(loc, &ep_info->group, sizeof(ep_info->group)); 930 931 _BCM_OAM_KEY_PACK(loc, &ep_info->name, sizeof(ep_info->name)); 932 933 _BCM_OAM_KEY_PACK(loc, &ep_info->gport, sizeof(ep_info->gport)); 934 935 _BCM_OAM_KEY_PACK(loc, &ep_info->level, sizeof(ep_info->level)); 936 937 _BCM_OAM_KEY_PACK(loc, &ep_info->vlan, sizeof(ep_info->vlan)); 938 939 _BCM_OAM_KEY_PACK(loc, &direction, sizeof(direction)); 940 } 941 942 /* End address should not exceed size of _bcm_oam_hash_key_t. */ 943 assert ((int) (loc - *key) <= sizeof(_bcm_oam_hash_key_t)); 944 } 945 946 #ifdef BCM_HURRICANE2_SUPPORT 947 /* 948 * Function: 949 * _bcm_hu2_oam_lmep_key_construct 950 * Purpose: 951 * Construct LMEP view lookup key for a given endpoint. 952 * Parameters: 953 * unit - (IN) BCM device number 954 * h_data_p - (IN) Pointer to endpoint hash data memory. 955 * l3_key_p - (IN/OUT) Pointer to entry buffer. 956 * Retruns: 957 * None 958 */ 959 STATIC void 960 _bcm_hu2_oam_lmep_key_construct(int unit, 961 const _bcm_oam_hash_data_t *h_data_p, 962 l3_entry_ipv4_unicast_entry_t *l3_key_p) 963 { 964 /* Set the search key type. */ 965 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 966 (unit, l3_key_p, KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_LMEP); 967 968 /* Set VLAN ID in search key. */ 969 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 970 (unit, l3_key_p, LMEP__VIDf, h_data_p->vlan); 971 972 973 /* SGLP contains generic logical port. */ 974 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 975 (unit, l3_key_p, LMEP__SGLPf, h_data_p->sglp); 976 977 } 978 979 /* 980 * Function: 981 * _bcm_hu2_oam_rmep_key_construct 982 * Purpose: 983 * Construct RMEP view lookup key for a given endpoint. 984 * Parameters: 985 * unit - (IN) BCM device number 986 * h_data_p - (IN) Pointer to endpoint hash data memory. 987 * l3_key_p - (IN/OUT) Pointer to entry buffer. 988 * Retruns: 989 * None 990 */ 991 STATIC void 992 _bcm_hu2_oam_rmep_key_construct(int unit, 993 const _bcm_oam_hash_data_t *h_data_p, 994 l3_entry_ipv4_unicast_entry_t *l3_key_p) 995 { 996 997 /* Set the search key type. */ 998 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 999 (unit, l3_key_p, KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_RMEP); 1000 1001 /* Set endpoint name. */ 1002 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 1003 (unit, l3_key_p, RMEP__MEPIDf, h_data_p->name); 1004 1005 /* Set the maintenance domain level. */ 1006 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 1007 (unit, l3_key_p, RMEP__MDLf, h_data_p->level); 1008 1009 /* 1010 * Set endpoint port on which remote device CCM packets will be received. 1011 */ 1012 /* SGLP contains generic logical port. */ 1013 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 1014 (unit, l3_key_p, RMEP__SGLPf, h_data_p->sglp); 1015 1016 /* Set VLAN ID in search key. */ 1017 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 1018 (unit, l3_key_p, RMEP__VIDf, h_data_p->vlan); 1019 } 1020 #endif /* BCM_HURRICANE2_SUPPORT */ 1021 1022 #ifdef BCM_TRIUMPH3_SUPPORT 1023 /* 1024 * Function: 1025 * _bcm_oam_lmep_key_construct 1026 * Purpose: 1027 * Construct LMEP view lookup key for a given endpoint. 1028 * Parameters: 1029 * unit - (IN) BCM device number 1030 * h_data_p - (IN) Pointer to endpoint hash data memory. 1031 * l3_key_p - (IN/OUT) Pointer to entry buffer. 1032 * Retruns: 1033 * None 1034 */ 1035 STATIC void 1036 _bcm_oam_lmep_key_construct(int unit, 1037 const _bcm_oam_hash_data_t *h_data_p, 1038 l3_entry_1_entry_t *l3_key_p) 1039 { 1040 /* Set the search key type. */ 1041 soc_L3_ENTRY_1m_field32_set 1042 (unit, l3_key_p, KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_1_LMEP_LMEP); 1043 1044 /* Set VLAN ID in search key. */ 1045 soc_L3_ENTRY_1m_field32_set 1046 (unit, l3_key_p, LMEP__VIDf, h_data_p->vlan); 1047 1048 /* Set port type status in the search key. */ 1049 if (BCM_GPORT_IS_MIM_PORT(h_data_p->gport) 1050 || BCM_GPORT_IS_MPLS_PORT(h_data_p->gport)) { 1051 1052 if (h_data_p->flags & BCM_OAM_ENDPOINT_PBB_TE) { 1053 /* SOURCE_TYPEf is '1' for virtual ports. */ 1054 soc_L3_ENTRY_1m_field32_set 1055 (unit, l3_key_p, LMEP__SOURCE_TYPEf, 1); 1056 } 1057 1058 /* SGLP field contains virtual port. */ 1059 soc_L3_ENTRY_1m_field32_set 1060 (unit, l3_key_p, LMEP__SGLPf, h_data_p->vp); 1061 1062 } else { 1063 1064 /* SGLP contains generic logical port. */ 1065 soc_L3_ENTRY_1m_field32_set 1066 (unit, l3_key_p, LMEP__SGLPf, h_data_p->sglp); 1067 1068 /* SGLP field contains generic logical port value. */ 1069 soc_L3_ENTRY_1m_field32_set 1070 (unit, l3_key_p, LMEP__SOURCE_TYPEf, 0); 1071 } 1072 } 1073 1074 /* 1075 * Function: 1076 * _bcm_oam_rmep_key_construct 1077 * Purpose: 1078 * Construct RMEP view lookup key for a given endpoint. 1079 * Parameters: 1080 * unit - (IN) BCM device number 1081 * h_data_p - (IN) Pointer to endpoint hash data memory. 1082 * l3_key_p - (IN/OUT) Pointer to entry buffer. 1083 * Retruns: 1084 * None 1085 */ 1086 STATIC void 1087 _bcm_oam_rmep_key_construct(int unit, 1088 const _bcm_oam_hash_data_t *h_data_p, 1089 l3_entry_1_entry_t *l3_key_p) 1090 { 1091 1092 /* Set the search key type. */ 1093 soc_L3_ENTRY_1m_field32_set 1094 (unit, l3_key_p, KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_1_RMEP_RMEP); 1095 1096 /* Set endpoint name. */ 1097 soc_L3_ENTRY_1m_field32_set 1098 (unit, l3_key_p, RMEP__MEPIDf, h_data_p->name); 1099 1100 /* Set the maintenance domain level. */ 1101 soc_L3_ENTRY_1m_field32_set 1102 (unit, l3_key_p, RMEP__MDLf, h_data_p->level); 1103 1104 /* 1105 * Set endpoint port on which remote device CCM packets will be received. 1106 * Port value could be SVP or SGLP. 1107 */ 1108 if (BCM_GPORT_IS_MIM_PORT(h_data_p->gport) 1109 || BCM_GPORT_IS_MPLS_PORT(h_data_p->gport)) { 1110 1111 if (h_data_p->flags & BCM_OAM_ENDPOINT_PBB_TE) { 1112 soc_L3_ENTRY_1m_field32_set 1113 (unit, l3_key_p, RMEP__SOURCE_TYPEf, 1); 1114 } 1115 1116 /* SGLP contains virtual port. */ 1117 soc_L3_ENTRY_1m_field32_set 1118 (unit, l3_key_p, RMEP__SGLPf, h_data_p->vp); 1119 1120 /* Set VLAN ID in search key. */ 1121 soc_L3_ENTRY_1m_field32_set 1122 (unit, l3_key_p, RMEP__VIDf, 0); 1123 } else { 1124 1125 /* SGLP contains generic logical port. */ 1126 soc_L3_ENTRY_1m_field32_set 1127 (unit, l3_key_p, RMEP__SGLPf, h_data_p->sglp); 1128 1129 /* Set VLAN ID in search key. */ 1130 soc_L3_ENTRY_1m_field32_set 1131 (unit, l3_key_p, RMEP__VIDf, h_data_p->vlan); 1132 } 1133 } 1134 #endif /* BCM_TRIUMPH3_SUPPORT */ 1135 1136 #if defined(KEY_PRINT) 1137 /* 1138 * Function: 1139 * _bcm_oam_hash_key_print 1140 * Purpose: 1141 * Print the contents of a hash key buffer. 1142 * Parameters: 1143 * hash_key - (IN) Pointer to hash key buffer. 1144 * Retruns: 1145 * None 1146 */ 1147 STATIC void 1148 _bcm_oam_hash_key_print(_bcm_oam_hash_key_t *hash_key) 1149 { 1150 int i; 1151 LOG_CLI((BSL_META_U(unit, 1152 "HASH KEY:"))); 1153 for(i = 0; i < _OAM_HASH_KEY_SIZE; i++) { 1154 LOG_CLI((BSL_META_U(unit, 1155 ":%u"), *(hash_key[i]))); 1156 } 1157 LOG_CLI((BSL_META_U(unit, 1158 "\n"))); 1159 } 1160 #endif 1161 1162 /* 1163 * Function: 1164 * _bcm_oam_control_get 1165 * Purpose: 1166 * Lookup a OAM control config from a bcm device id. 1167 * Parameters: 1168 * unit - (IN)BCM unit number. 1169 * oc - (OUT) OAM control structure. 1170 * Retruns: 1171 * BCM_E_XXX 1172 */ 1173 STATIC int 1174 _bcm_oam_control_get(int unit, _bcm_oam_control_t **oc) 1175 { 1176 if (NULL == oc) { 1177 return (BCM_E_PARAM); 1178 } 1179 1180 /* Ensure oam module is initialized. */ 1181 _BCM_OAM_IS_INIT(unit); 1182 1183 *oc = _oam_control[unit]; 1184 1185 return (BCM_E_NONE); 1186 } 1187 1188 /* 1189 * Function: 1190 * _bcm_oam_group_endpoint_count_init 1191 * Purpose: 1192 * Retrieves and initializes endpoint count information for this device. 1193 * Parameters: 1194 * unit - (IN) BCM unit number. 1195 * oc - (IN) Pointer to device OAM control structure. 1196 * Retruns: 1197 * BCM_E_XXX 1198 */ 1199 STATIC int 1200 _bcm_oam_group_endpoint_count_init(int unit, _bcm_oam_control_t *oc) 1201 { 1202 /* Input parameter check. */ 1203 if (NULL == oc) { 1204 return (BCM_E_PARAM); 1205 } 1206 1207 /* 1208 * Get endpoint hardware table index count values and 1209 * initialize device OAM control structure members variables. 1210 */ 1211 oc->rmep_count = soc_mem_index_count(unit, RMEPm); 1212 oc->lmep_count = soc_mem_index_count(unit, LMEPm); 1213 oc->ma_idx_count = soc_mem_index_count(unit, MA_INDEXm); 1214 1215 /* Max number of endpoints supported by the device. */ 1216 oc->ep_count = (oc->rmep_count + oc->lmep_count + oc->ma_idx_count); 1217 1218 LOG_DEBUG(BSL_LS_BCM_OAM, 1219 (BSL_META_U(unit, 1220 "OAM Info: Total No. endpoint Count = %d.\n"), 1221 oc->ep_count)); 1222 1223 /* Max number of MA Groups supported by device. */ 1224 oc->group_count = soc_mem_index_count(unit, MA_STATEm); 1225 LOG_DEBUG(BSL_LS_BCM_OAM, 1226 (BSL_META_U(unit, 1227 "OAM Info: Total No. Group Count = %d.\n"), 1228 oc->group_count)); 1229 1230 return (BCM_E_NONE); 1231 } 1232 1233 #ifdef BCM_HURRICANE2_SUPPORT 1234 /* 1235 * Function: 1236 * _bcm_hu2_oam_ccm_rx_timeout_enable 1237 * Purpose: 1238 * Enable CCM Timer operations for endpoint state table. 1239 * Parameters: 1240 * unit - (IN) BCM unit number. 1241 * state - () Enable/Disable. 1242 * Retruns: 1243 * BCM_E_XXX 1244 * Note: 1245 * RMEP_MA_STATE_REFRESH_INDEXr - CPU access for debug only. 1246 */ 1247 STATIC int 1248 _bcm_hu2_oam_ccm_rx_timeout_set(int unit, uint8 state) 1249 { 1250 int rv; /* Opreation return status. */ 1251 uint32 rval = 0; /* Register value. */ 1252 1253 BCM_IF_ERROR_RETURN(READ_IARB_OAM_REFRESH_CONTROLr(unit, &rval)); 1254 1255 soc_reg_field_set(unit, IARB_OAM_REFRESH_CONTROLr, &rval, 1256 REFRESH_ENABLEf, state ? 1 : 0); 1257 1258 rv = WRITE_IARB_OAM_REFRESH_CONTROLr(unit, rval); 1259 1260 return (rv); 1261 } 1262 #endif /* BCM_HURRICANE2_SUPPORT */ 1263 1264 /* 1265 * Function: 1266 * _bcm_oam_ccm_rx_timeout_enable 1267 * Purpose: 1268 * Enable CCM Timer operations for endpoint state table. 1269 * Parameters: 1270 * unit - (IN) BCM unit number. 1271 * state - () Enable/Disable. 1272 * Retruns: 1273 * BCM_E_XXX 1274 * Note: 1275 * RMEP_MA_STATE_REFRESH_INDEXr - CPU access for debug only. 1276 */ 1277 STATIC int 1278 _bcm_oam_ccm_rx_timeout_set(int unit, uint8 state) 1279 { 1280 int rv; /* Opreation return status. */ 1281 uint32 rval = 0; /* Register value. */ 1282 1283 /* Enable timer instructions to RMEP/MA_STATE Table. */ 1284 soc_reg_field_set(unit, OAM_TIMER_CONTROLr, &rval, 1285 TIMER_ENABLEf, state ? 1 : 0); 1286 1287 /* Set Clock granularity to 250us ticks - 1. */ 1288 soc_reg_field_set(unit, OAM_TIMER_CONTROLr, &rval, 1289 CLK_GRANf, 1); 1290 1291 rv = WRITE_OAM_TIMER_CONTROLr(unit, rval); 1292 if (BCM_FAILURE(rv)) { 1293 LOG_ERROR(BSL_LS_BCM_OAM, 1294 (BSL_META_U(unit, 1295 "OAM Error: Timer enable - Failed.\n"))); 1296 return (rv); 1297 } 1298 1299 BCM_IF_ERROR_RETURN(READ_AUX_ARB_CONTROL_2r(unit, &rval)); 1300 1301 soc_reg_field_set(unit, AUX_ARB_CONTROL_2r, &rval, 1302 OAM_REFRESH_ENABLEf, state ? 1 : 0); 1303 1304 BCM_IF_ERROR_RETURN(WRITE_AUX_ARB_CONTROL_2r(unit, rval)); 1305 1306 return (rv); 1307 } 1308 1309 /* 1310 * Function: 1311 * _bcm_oam_ccm_tx_config_enable 1312 * Purpose: 1313 * Enable transmission of OAM PDUs on local endpoint. 1314 * Parameters: 1315 * unit - (IN) BCM unit number. 1316 * state - (IN) Enable/Disable 1317 * Retruns: 1318 * BCM_E_XXX 1319 */ 1320 STATIC int 1321 _bcm_oam_ccm_tx_config_set(int unit, uint8 state) 1322 { 1323 int rv; /* Opreation return status. */ 1324 uint32 rval = 0; /* Register value. */ 1325 1326 /* Enable OAM LMEP Tx. */ 1327 soc_reg_field_set(unit, OAM_TX_CONTROLr, &rval, 1328 TX_ENABLEf, state ? 1 : 0); 1329 1330 /* Enable CMIC buffer. */ 1331 soc_reg_field_set(unit, OAM_TX_CONTROLr, &rval, 1332 CMIC_BUF_ENABLEf, state ? 1 : 0); 1333 1334 rv = WRITE_OAM_TX_CONTROLr(unit, rval); 1335 if (BCM_FAILURE(rv)) { 1336 LOG_ERROR(BSL_LS_BCM_OAM, 1337 (BSL_META_U(unit, 1338 "OAM Error: Tx config enable - Failed.\n"))); 1339 } 1340 return (rv); 1341 } 1342 1343 /* 1344 * Function: 1345 * _bcm_oam_misc_config 1346 * Purpose: 1347 * Miscellaneous OAM configurations: 1348 * 1. Disable L2 learning for OAM MAC address. 1349 * 2. Enable flooding of mcast packets on the vlan. 1350 * 3. Enable IFP lookup on the CPU port. 1351 * Parameters: 1352 * unit - (IN) BCM unit number. 1353 * Retruns: 1354 * BCM_E_XXX 1355 */ 1356 STATIC int 1357 _bcm_oam_misc_config(int unit) 1358 { 1359 int rv; /* Opreation return status. */ 1360 uint32 rval = 0; /* Register value. */ 1361 1362 /* Disable L2 learning of OAM packets. */ 1363 soc_reg_field_set(unit, LMEP_COMMONr, &rval, 1364 L3f, 1); 1365 1366 /* PFM 0: Flood MCAST packets on the vlan. */ 1367 soc_reg_field_set(unit, LMEP_COMMONr, &rval, 1368 PFMf, 0); 1369 1370 rv = WRITE_LMEP_COMMONr(unit, rval); 1371 if (BCM_FAILURE(rv)) { 1372 LOG_ERROR(BSL_LS_BCM_OAM, 1373 (BSL_META_U(unit, 1374 "OAM Error: Misc config - Failed.\n"))); 1375 return (rv); 1376 } 1377 1378 /* 1379 * Enable ingress FP for CPU port so LM/DM packets sent from CPU 1380 * can be processed. 1381 */ 1382 rv = bcm_esw_port_control_set(unit, CMIC_PORT(unit), 1383 bcmPortControlFilterIngress, 1); 1384 if (BCM_FAILURE(rv)) { 1385 LOG_ERROR(BSL_LS_BCM_OAM, 1386 (BSL_META_U(unit, 1387 "OAM Error: bcm_esw_port_control_set" 1388 " - Failed.\n"))); 1389 return (rv); 1390 } 1391 return (rv); 1392 1393 } 1394 1395 /* 1396 * Function: 1397 * _bcm_oam_profile_tables_init 1398 * Purpose: 1399 * Create ingress service priority mapping profile table and setup a 1400 * default profile. Create OAM opcode control profile table. 1401 * Parameters: 1402 * unit - (IN) BCM unit number. 1403 * oc - (IN) Pointer to OAM control structure. 1404 * Retruns: 1405 * BCM_E_XXX 1406 */ 1407 STATIC int 1408 _bcm_oam_profile_tables_init(int unit, _bcm_oam_control_t *oc) 1409 { 1410 int rv; /* Opreation return status. */ 1411 soc_mem_t mem; /* Profiled table memory. */ 1412 int entry_words; /* Profile table word size. */ 1413 int pri; /* Priority */ 1414 void *entries[1]; /* Profile entry. */ 1415 uint32 profile_index; /* Profile table index. */ 1416 ing_service_pri_map_entry_t pri_ent[BCM_OAM_INTPRI_MAX]; /* profile */ 1417 /* entry */ 1418 1419 /* Ingress Service Priority Map profile table initialization. */ 1420 soc_profile_mem_t_init(&oc->ing_service_pri_map); 1421 1422 entry_words = (sizeof(ing_service_pri_map_entry_t) / sizeof(uint32)); 1423 1424 mem = ING_SERVICE_PRI_MAPm; 1425 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 1426 &oc->ing_service_pri_map); 1427 if (BCM_FAILURE(rv)) { 1428 LOG_ERROR(BSL_LS_BCM_OAM, 1429 (BSL_META_U(unit, 1430 "OAM Error: service map profile - Failed.\n"))); 1431 return (rv); 1432 } 1433 1434 /* 1435 * Initialize ingress priority map profile table. 1436 * All priorities priorities map to priority:'0'. 1437 */ 1438 for (pri = 0; pri < BCM_OAM_INTPRI_MAX; pri++) 1439 { 1440 /* Clear ingress service pri map profile entry. */ 1441 sal_memcpy(&pri_ent[pri], soc_mem_entry_null(unit, mem), 1442 soc_mem_entry_words(unit, mem) * sizeof(uint32)); 1443 1444 if (SOC_MEM_FIELD_VALID(unit, mem, OFFSET_VALIDf)) { 1445 soc_mem_field32_set(unit, mem, &pri_ent[pri], OFFSET_VALIDf, 1); 1446 } 1447 } 1448 1449 1450 entries[0] = &pri_ent; 1451 rv = soc_profile_mem_add(unit, &oc->ing_service_pri_map, 1452 (void *) &entries, BCM_OAM_INTPRI_MAX, 1453 &profile_index); 1454 if (BCM_FAILURE(rv)) { 1455 LOG_ERROR(BSL_LS_BCM_OAM, 1456 (BSL_META_U(unit, 1457 "OAM Error: service map init - Failed.\n"))); 1458 return (rv); 1459 } 1460 1461 /* OAM Opcode Control profile table initialization. */ 1462 soc_profile_mem_t_init(&oc->oam_opcode_control_profile); 1463 1464 entry_words = sizeof(oam_opcode_control_profile_entry_t) 1465 / sizeof(uint32); 1466 1467 mem = OAM_OPCODE_CONTROL_PROFILEm; 1468 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 1469 &oc->oam_opcode_control_profile); 1470 if (BCM_FAILURE(rv)) { 1471 LOG_ERROR(BSL_LS_BCM_OAM, 1472 (BSL_META_U(unit, 1473 "OAM Error: opcode control profile - Failed.\n"))); 1474 return (rv); 1475 } 1476 1477 return (rv); 1478 } 1479 1480 /* 1481 * Function: 1482 * _bcm_tr3_oam_control_free 1483 * Purpose: 1484 * Free OAM control structure resources allocated by this unit. 1485 * Parameters: 1486 * unit - (IN) BCM unit number. 1487 * oc - (IN) Pointer to OAM control structure. 1488 * Retruns: 1489 * BCM_E_XXX 1490 */ 1491 STATIC int 1492 _bcm_tr3_oam_control_free(int unit, _bcm_oam_control_t *oc) 1493 { 1494 int status = 0; 1495 1496 _oam_control[unit] = NULL; 1497 1498 if (NULL == oc) { 1499 /* Module already un-initialized. */ 1500 return (BCM_E_NONE); 1501 } 1502 1503 /* Free protection mutex. */ 1504 if (NULL != oc->oc_lock) { 1505 sal_mutex_destroy(oc->oc_lock); 1506 } 1507 1508 /* Free hash data storage memory. */ 1509 if (NULL != oc->oam_hash_data) { 1510 sal_free(oc->oam_hash_data); 1511 } 1512 1513 /* Destory endpoint hash table. */ 1514 if (NULL != oc->ma_mep_htbl) { 1515 status = shr_htb_destroy(&oc->ma_mep_htbl, NULL); 1516 if (BCM_FAILURE(status)) { 1517 LOG_ERROR(BSL_LS_BCM_OAM, 1518 (BSL_META_U(unit, 1519 "Freeing ma_mep_htbl failed\n"))); 1520 } 1521 } 1522 1523 /* Destory group indices list. */ 1524 if (NULL != oc->group_pool) { 1525 shr_idxres_list_destroy(oc->group_pool); 1526 oc->group_pool = NULL; 1527 } 1528 1529 /* Destroy endpoint indices list. */ 1530 if (NULL != oc->mep_pool) { 1531 shr_idxres_list_destroy(oc->mep_pool); 1532 oc->mep_pool = NULL; 1533 } 1534 1535 /* Destroy local endpoint indices list. */ 1536 if (NULL != oc->lmep_pool) { 1537 shr_idxres_list_destroy(oc->lmep_pool); 1538 oc->lmep_pool = NULL; 1539 } 1540 1541 /* Destroy remote endpoint indices list. */ 1542 if (NULL != oc->rmep_pool) { 1543 shr_idxres_list_destroy(oc->rmep_pool); 1544 oc->rmep_pool = NULL; 1545 } 1546 1547 /* Destroy group indices list. */ 1548 if (NULL != oc->ma_idx_pool) { 1549 shr_idxres_list_destroy(oc->ma_idx_pool); 1550 oc->ma_idx_pool = NULL; 1551 } 1552 1553 /* Destroy lm counter indices list. */ 1554 if (NULL != oc->lm_counter_pool) { 1555 shr_idxres_list_destroy(oc->lm_counter_pool); 1556 oc->lm_counter_pool = NULL; 1557 } 1558 1559 if (soc_feature(unit, soc_feature_bhh)) { 1560 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 1561 /* Destroy bhh indices list. */ 1562 if (NULL != oc->bhh_pool) { 1563 shr_idxres_list_destroy(oc->bhh_pool); 1564 oc->bhh_pool = NULL; 1565 } 1566 if (NULL != oc->dma_buffer){ 1567 soc_cm_sfree(oc->unit, oc->dma_buffer); 1568 oc->dma_buffer = NULL; 1569 } 1570 if (NULL != oc->dmabuf_reply){ 1571 soc_cm_sfree(oc->unit, oc->dmabuf_reply); 1572 oc->dmabuf_reply = NULL; 1573 } 1574 #endif 1575 } 1576 1577 /* Free group memory. */ 1578 if (NULL != oc->group_info) { 1579 sal_free(oc->group_info); 1580 } 1581 1582 /* Free RMEP H/w to logical index mapping memory. */ 1583 if (NULL != oc->remote_endpoints) { 1584 sal_free(oc->remote_endpoints); 1585 } 1586 1587 /* Destroy ingress serivce priority mapping profile. */ 1588 if (NULL != oc->ing_service_pri_map.tables) { 1589 soc_profile_mem_destroy(unit, &oc->ing_service_pri_map); 1590 } 1591 1592 /* Destroy OAM opcode control profile. */ 1593 if (NULL != oc->oam_opcode_control_profile.tables) { 1594 soc_profile_mem_destroy(unit, &oc->oam_opcode_control_profile); 1595 } 1596 1597 /* Free OAM control structure memory. */ 1598 sal_free(oc); 1599 oc = NULL; 1600 1601 return (BCM_E_NONE); 1602 } 1603 1604 /* 1605 * Function: 1606 * _bcm_tr3_oam_handle_interrupt 1607 * Purpose: 1608 * Process OAM interrupts generated by endpoints. 1609 * Parameters: 1610 * unit - (IN) BCM unit number. 1611 * field - (IN) fault field. 1612 * Retruns: 1613 * BCM_E_XXX 1614 */ 1615 STATIC int 1616 _bcm_tr3_oam_handle_interrupt(int unit, soc_field_t field) 1617 { 1618 _bcm_oam_interrupt_t *intr; /* OAM interrupt. */ 1619 _bcm_oam_control_t *oc; /* OAM control structure. */ 1620 uint32 intr_rval; /* Interrupt register value. */ 1621 uint32 intr_cur_status; /* Interrupt status. */ 1622 uint32 flags; /* Interrupt flags. */ 1623 bcm_oam_group_t grp_index; /* MA group index. */ 1624 bcm_oam_endpoint_t remote_ep_index; /* Remote Endpoint index. */ 1625 int intr_multi; /* Event occured multiple times. */ 1626 int intr_count; /* No. of times event detected. */ 1627 int rv; /* Operation return status */ 1628 _bcm_oam_event_handler_t *e_handler; /* Pointer to Event handler. */ 1629 int ep_index_mask; /* Mask the EP Index read from intr 1630 status reg, based on table sz */ 1631 1632 1633 /* Get OAM control structure. */ 1634 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 1635 1636 _BCM_OAM_LOCK(oc); 1637 1638 /* Loop through the supported interrupts for this device. */ 1639 for (intr = _tr3_oam_interrupts; intr->status_register != INVALIDr; 1640 intr++) { 1641 1642 rv = soc_reg32_get(unit, intr->status_register, 1643 REG_PORT_ANY, 0, &intr_rval); 1644 if (BCM_FAILURE(rv)) { 1645 1646 continue; 1647 } 1648 1649 rv = soc_reg32_set(unit, intr->status_register, 1650 REG_PORT_ANY, 0, 0); 1651 if (BCM_FAILURE(rv)) { 1652 continue; 1653 } 1654 1655 /* Get status of interrupt from hardware. */ 1656 intr_cur_status = soc_reg_field_get(unit, intr->status_register, 1657 intr_rval, VALIDf); 1658 if (0 == intr_cur_status) { 1659 /* This interrupt event is not valid, so continue. */ 1660 continue; 1661 } 1662 1663 /* Get this interrupt event counter value. */ 1664 intr_count = oc->event_handler_cnt[intr->event_type]; 1665 1666 /* Check if the interrupt is set. */ 1667 if ((1 == intr_cur_status) && (intr_count > 0)) { 1668 flags = 0; 1669 1670 /* Get MA group index for this interrupt. */ 1671 if (INVALIDf != intr->group_index_field ) { 1672 grp_index = soc_reg_field_get(unit, intr->status_register, 1673 intr_rval, 1674 intr->group_index_field); 1675 } else { 1676 /* Group not valid for this interrupt. */ 1677 grp_index = BCM_OAM_GROUP_INVALID; 1678 } 1679 1680 /* Get H/w index of RMEP for this interrupt. */ 1681 if (INVALIDf != intr->endpoint_index_field ) { 1682 remote_ep_index = soc_reg_field_get(unit, intr->status_register, 1683 intr_rval, 1684 intr->endpoint_index_field); 1685 1686 /* For Apollo2, MSB(13) of the endpoint index is not applicable 1687 hence recommended to mask out the same */ 1688 ep_index_mask = soc_mem_index_max(unit, RMEPm); 1689 remote_ep_index &= ep_index_mask; 1690 1691 /* Get Logical index from H/w index for this RMEP. */ 1692 remote_ep_index = oc->remote_endpoints[remote_ep_index]; 1693 } else { 1694 /* Endpoint not valid for this interrupt. */ 1695 remote_ep_index = BCM_OAM_ENDPOINT_INVALID; 1696 } 1697 1698 /* Get interrupt MULTIf status. */ 1699 intr_multi = soc_reg_field_get(unit, intr->status_register, 1700 intr_rval, MULTIf); 1701 if (1 == intr_multi) { 1702 /* 1703 * Interrupt event asserted more than once. 1704 * Set flags status bit to indicate event multiple occurance. 1705 */ 1706 flags |= BCM_OAM_EVENT_FLAGS_MULTIPLE; 1707 } 1708 1709 /* Check and call all the handlers registerd for this event. */ 1710 for (e_handler = oc->event_handler_list_p; e_handler != NULL; 1711 e_handler = e_handler->next_p) { 1712 1713 /* Check if an event handler is register for this event type. */ 1714 if (SHR_BITGET(e_handler->event_types.w, intr->event_type)) { 1715 1716 /* Call the event handler with the call back parameters. */ 1717 e_handler->cb(unit, flags, intr->event_type, grp_index, 1718 remote_ep_index, e_handler->user_data); 1719 } 1720 } 1721 } 1722 } 1723 1724 _BCM_OAM_UNLOCK(oc); 1725 1726 return (BCM_E_NONE); 1727 } 1728 1729 /* 1730 * Function: 1731 * _bcm_tr3_oam_events_unregister 1732 * Purpose: 1733 * Unregister all OAM events for this unit. 1734 * Parameters: 1735 * unit - (IN) BCM unit number. 1736 * oc - (IN) Pointer to OAM control structure. 1737 * Retruns: 1738 * BCM_E_NONE 1739 */ 1740 STATIC int 1741 _bcm_tr3_oam_events_unregister(int unit, _bcm_oam_control_t *oc) 1742 { 1743 _bcm_oam_event_handler_t *e_handler; /* Pointer to event handler list. */ 1744 _bcm_oam_event_handler_t *e_delete; /* Event handler to be freed. */ 1745 1746 /* Control lock taken by the calling routine. */ 1747 1748 e_handler = oc->event_handler_list_p; 1749 1750 while (e_handler != NULL) { 1751 e_delete = e_handler; 1752 e_handler = e_handler->next_p; 1753 sal_free(e_delete); 1754 } 1755 1756 oc->event_handler_list_p = NULL; 1757 1758 return (BCM_E_NONE); 1759 } 1760 1761 1762 /* 1763 * Function: 1764 * _bcm_tr3_oam_clear_rmep 1765 * Purpose: 1766 * Delete RMEP entry or Install fresh RMEP entry in the Hardware, clearing 1767 * the faults. 1768 * 1769 * Parameters: 1770 * unit - (IN) BCM device number 1771 * h_data_p - (IN) Pointer to Endpoint info associated with RMEP entry 1772 * being cleared. 1773 * valid - (IN) 0 => Delete the H/w entry 1774 * 1 => Install fresh entry with faults cleared. 1775 * Returns: 1776 * BCM_E_XXX 1777 */ 1778 STATIC int 1779 _bcm_tr3_oam_clear_rmep (int unit, _bcm_oam_hash_data_t *h_data_p, int valid) 1780 { 1781 1782 rmep_entry_t rmep_entry; /* RMEP table entry. */ 1783 int rv = BCM_E_INTERNAL; /* Operation return status entry */ 1784 uint32 oam_cur_time; /* Current time in H/w state machine */ 1785 1786 LOG_VERBOSE(BSL_LS_BCM_OAM, 1787 (BSL_META_U(unit, 1788 "OAM, EP id %d, valid %d\n"), 1789 h_data_p->remote_index, valid)); 1790 1791 if (h_data_p == NULL) { 1792 LOG_ERROR(BSL_LS_BCM_OAM, 1793 (BSL_META_U(unit, 1794 "OAM ERR: Arg h_data_p NULL check failed\n"))); 1795 return BCM_E_INTERNAL; 1796 } 1797 1798 /* RMEP table programming. */ 1799 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 1800 1801 /* if valid==0 delete RMEP entry, else create a clean RMEP entry */ 1802 if (!(valid)) { 1803 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index, 1804 &rmep_entry); 1805 if (rv != BCM_E_NONE) { 1806 LOG_ERROR(BSL_LS_BCM_OAM, 1807 (BSL_META_U(unit, 1808 "OAM ERR: Deleting RMEP entry failied\n"))); 1809 } 1810 return (rv); 1811 } 1812 1813 /* Set the MA group index. */ 1814 soc_RMEPm_field32_set(unit, &rmep_entry, MAID_INDEXf, 1815 h_data_p->group_index); 1816 1817 /* 1818 * The following steps are necessary to enable CCM timeout events 1819 * without having received any CCMs. 1820 */ 1821 soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMP_VALIDf, 1); 1822 1823 BCM_IF_ERROR_RETURN(READ_OAM_CURRENT_TIMEr(unit, &oam_cur_time)); 1824 1825 soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMPf, oam_cur_time); 1826 1827 soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_RECEIVED_CCMf, 1828 _bcm_tr3_oam_ccm_msecs_to_hw_encode(h_data_p->period)); 1829 /* End of timeout setup */ 1830 1831 1832 soc_RMEPm_field32_set(unit, &rmep_entry, VALIDf, 1); 1833 1834 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index, 1835 &rmep_entry); 1836 if (rv != BCM_E_NONE) { 1837 LOG_ERROR(BSL_LS_BCM_OAM, 1838 (BSL_META_U(unit, 1839 "OAM ERR: Clearing RMEP entry failied\n"))); 1840 return (rv); 1841 } 1842 1843 return BCM_E_NONE; 1844 } 1845 1846 1847 /* 1848 * Function: 1849 * _bcm_tr3_oam_clear_ma_state 1850 * Purpose: 1851 * Delete MA_STATE entry or Install fresh MA_STATE entry in the Hardware, 1852 * Clearing the faults. 1853 * Parameters: 1854 * unit - (IN) BCM device number 1855 * group_info - (IN) Group info associated with MA_STATE entry being 1856 * cleared. 1857 * index - (IN) H/w index of MA_STATE entry to be modified. 1858 * valid - (IN) 0 => Delete the H/w entry 1859 * 1 => Install fresh entry with faults cleared. 1860 * Returns: 1861 * BCM_E_XXX 1862 */ 1863 STATIC int 1864 _bcm_tr3_oam_clear_ma_state(int unit, _bcm_oam_group_data_t *group_info, 1865 int index, int valid) 1866 { 1867 1868 ma_state_entry_t ma_state_entry; /* MA State table entry. */ 1869 1870 LOG_VERBOSE(BSL_LS_BCM_OAM, 1871 (BSL_META_U(unit, 1872 "OAM *group_info %p, index %d, valid %d\n"), 1873 group_info, index, valid)); 1874 1875 if (group_info == NULL) { 1876 LOG_ERROR(BSL_LS_BCM_OAM, 1877 (BSL_META_U(unit, 1878 "OAM ERR: Arg group_info NULL check failed\n"))); 1879 return BCM_E_INTERNAL; 1880 } 1881 1882 sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t)); 1883 1884 /* Mark the entry as valid. */ 1885 soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, valid); 1886 1887 /* Set the lowest alarm priority info. */ 1888 if (valid) { 1889 soc_MA_STATEm_field32_set(unit, &ma_state_entry, LOWESTALARMPRIf, 1890 group_info->lowest_alarm_priority); 1891 } 1892 1893 /* Write group information to hardware table. */ 1894 SOC_IF_ERROR_RETURN(WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, index, 1895 &ma_state_entry)); 1896 return BCM_E_NONE; 1897 } 1898 1899 1900 /* 1901 * Function: 1902 * _bcm_tr3_oam_group_recreate 1903 * Purpose: 1904 * Recreate MA_STATE and RMEP entries, due to current H/w limitation 1905 * Currently there is a race condition between H/w and Software 1906 * When RMEP is deleted and if it has any faults then, 1907 * MA_STATE remote fault counters need to be decremented by software. 1908 * However it may so happen that after reading RMEP faults and just 1909 * before RMEP deletion, the fault gets cleared and H/w already decremented 1910 * the MA_STATE table, now when software decrements the MA_STATE it would 1911 * get MA_STATE table into an inconsistent state. 1912 * As a solution we always recreate the entire group on a RMEP deletion. 1913 * Parameters: 1914 * unit - (IN) BCM device number 1915 * group_id - (IN) Group Index, 1916 * as per current implementation this is same as MA_STATE index. 1917 * Returns: 1918 * BCM_E_XXX 1919 * Expects: 1920 * OAM LOCK 1921 */ 1922 STATIC int 1923 _bcm_tr3_oam_group_recreate(int unit, int index) 1924 { 1925 _bcm_oam_control_t *oc; /* OAM control structure. */ 1926 _bcm_oam_group_data_t *group_info; /* OAM group info */ 1927 _bcm_oam_ep_list_t *cur_ep_ptr = NULL; /* Pointer to group's EP list */ 1928 /* entry. */ 1929 int rv = BCM_E_NONE; /* Operation return status. */ 1930 1931 /* Get OAM control structure handle. */ 1932 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 1933 1934 /* Get the handle to group info */ 1935 group_info = &(oc->group_info[index]); 1936 1937 /*if unused Group, just clear the MA_STATE index, including the valid bit*/ 1938 if (!(group_info->in_use)) { 1939 LOG_WARN(BSL_LS_BCM_OAM, 1940 (BSL_META_U(unit, 1941 "OAM, WARN: Recieved group recreate request for " 1942 "unused Group Id %d\n"), index)); 1943 1944 rv = _bcm_tr3_oam_clear_ma_state(unit, group_info, index, 0); 1945 if (BCM_FAILURE(rv)) { 1946 LOG_ERROR(BSL_LS_BCM_OAM, 1947 (BSL_META_U(unit, 1948 "OAM Error: MA_STATE clear failed group id %d - " 1949 "%s.\n"), index, bcm_errmsg(rv))); 1950 return rv; 1951 } 1952 return rv; 1953 } 1954 1955 /* 1. Traverse and delete the RMEPs in the group */ 1956 if (group_info->ep_list != NULL) { 1957 cur_ep_ptr = *(group_info->ep_list); 1958 } 1959 while (cur_ep_ptr) { 1960 if (cur_ep_ptr->ep_data_p->is_remote && cur_ep_ptr->ep_data_p->in_use) { 1961 rv = _bcm_tr3_oam_clear_rmep(unit, cur_ep_ptr->ep_data_p, 0); 1962 if (BCM_FAILURE(rv)) { 1963 LOG_ERROR(BSL_LS_BCM_OAM, 1964 (BSL_META_U(unit, 1965 "OAM Error: RMEP delete failed Ep id %d - " 1966 "%s.\n"), cur_ep_ptr->ep_data_p->ep_id, bcm_errmsg(rv))); 1967 return rv; 1968 } 1969 } 1970 cur_ep_ptr = cur_ep_ptr->next; 1971 } 1972 1973 /* 2. Clear the MA_STATE table faults */ 1974 rv = _bcm_tr3_oam_clear_ma_state(unit, group_info, index, 1); 1975 if (BCM_FAILURE(rv)) { 1976 LOG_ERROR(BSL_LS_BCM_OAM, 1977 (BSL_META_U(unit, 1978 "OAM Error: MA_STATE clear failed group id %d - " 1979 "%s.\n"), index, bcm_errmsg(rv))); 1980 return rv; 1981 } 1982 1983 /* 3. Recreate the RMEP table entries. Clearing the faults. */ 1984 if (group_info->ep_list != NULL) { 1985 cur_ep_ptr = *(group_info->ep_list); 1986 } 1987 while (cur_ep_ptr) { 1988 if (cur_ep_ptr->ep_data_p->is_remote && cur_ep_ptr->ep_data_p->in_use) { 1989 rv = _bcm_tr3_oam_clear_rmep(unit, cur_ep_ptr->ep_data_p, 1); 1990 if (BCM_FAILURE(rv)) { 1991 LOG_ERROR(BSL_LS_BCM_OAM, 1992 (BSL_META_U(unit, 1993 "OAM Error: RMEP clear failed EP id %d - " 1994 "%s.\n"), cur_ep_ptr->ep_data_p->ep_id, bcm_errmsg(rv))); 1995 return rv; 1996 } 1997 } 1998 cur_ep_ptr = cur_ep_ptr->next; 1999 } 2000 2001 return rv; 2002 } 2003 2004 2005 /* 2006 * Function: 2007 * _bcm_tr3_oam_ser_handler 2008 * Purpose: 2009 * Soft Error Correction routine for MA_STATE and RMEP tables. 2010 * Parameters: 2011 * unit - (IN) BCM device number 2012 * mem - (IN) Memory MA_STATE or RMEP. 2013 * index - (IN) Memory Index. 2014 * Returns: 2015 * BCM_E_XXX 2016 */ 2017 STATIC int 2018 _bcm_tr3_oam_ser_handler(int unit, soc_mem_t mem, int index) 2019 { 2020 int rv = BCM_E_NONE; /* Operation return status. */ 2021 _bcm_oam_control_t *oc = NULL; /* OAM control structure. */ 2022 bcm_oam_endpoint_t remote_ep_index; /* Remote Endpoint index. */ 2023 _bcm_oam_hash_data_t *ep_data = NULL; /* Remote Endpoint hash data */ 2024 rmep_entry_t rmep_entry; /* Remote MEP entry. */ 2025 LOG_VERBOSE(BSL_LS_BCM_OAM, 2026 (BSL_META_U(unit, 2027 "OAM SER on mem %s, index %d\n"), 2028 SOC_MEM_NAME(unit, mem), index)); 2029 2030 /* Get OAM control structure handle. */ 2031 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 2032 2033 switch(mem){ 2034 case MA_STATEm: 2035 _BCM_OAM_GROUP_INDEX_VALIDATE(index); 2036 _BCM_OAM_LOCK(oc); 2037 rv = _bcm_tr3_oam_group_recreate(unit, index); 2038 _BCM_OAM_UNLOCK(oc); 2039 break; 2040 2041 case RMEPm: 2042 _BCM_OAM_RMEP_INDEX_VALIDATE(index); 2043 _BCM_OAM_LOCK(oc); 2044 /* Get the logical index from H/w RMEP index */ 2045 remote_ep_index = oc->remote_endpoints[index]; 2046 if(remote_ep_index == BCM_OAM_ENDPOINT_INVALID) { 2047 /* clean the HW RMEP index */ 2048 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 2049 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, index, 2050 &rmep_entry); 2051 _BCM_OAM_UNLOCK(oc); 2052 break; 2053 } 2054 /* Get handle to Hash data */ 2055 ep_data = &(oc->oam_hash_data[remote_ep_index]); 2056 2057 if (!(ep_data->in_use)) { 2058 /* If endpoint not in use, just clear the RMEP entry in memory */ 2059 LOG_WARN(BSL_LS_BCM_OAM, 2060 (BSL_META_U(unit, 2061 "OAM, WARN: Recieved Parity Error on" 2062 "unused Remote Id %d\n"), remote_ep_index)); 2063 /* Just clear this entry including valid bit */ 2064 rv = _bcm_tr3_oam_clear_rmep(unit, ep_data, 0); 2065 } else { 2066 /* Get the group Id from EP data, call group recreate routine */ 2067 rv = _bcm_tr3_oam_group_recreate(unit, ep_data->group_index); 2068 } 2069 _BCM_OAM_UNLOCK(oc); 2070 break; 2071 2072 default: 2073 LOG_ERROR(BSL_LS_BCM_OAM, 2074 (BSL_META_U(unit, 2075 "OAM, ERR: Invalid mem in OAM SER correction " 2076 "routine %s\n"), SOC_MEM_NAME(unit, mem))); 2077 return BCM_E_INTERNAL; 2078 } 2079 2080 LOG_VERBOSE(BSL_LS_BCM_OAM, 2081 (BSL_META_U(unit, 2082 "OAM SER completed on mem %s, index %d, rv %d\n"), 2083 SOC_MEM_NAME(unit, mem), index, rv)); 2084 2085 return rv; 2086 2087 } 2088 2089 2090 /* 2091 * Function: 2092 * _bcm_tr3_oam_group_name_mangle 2093 * Purpose: 2094 * Build tbe group name for hardware table write. 2095 * Parameters: 2096 * name_p - (IN) OAM group name. 2097 * mangled_name_p - (IN/OUT) Buffer to write the group name in hardware 2098 * format. 2099 * Retruns: 2100 * None 2101 */ 2102 STATIC void 2103 _bcm_tr3_oam_group_name_mangle(uint8 *name_p, 2104 uint8 *mangled_name_p) 2105 { 2106 uint8 *byte_p; /* Pointer to group name buffer. */ 2107 int bytes_left; /* Number of bytes left in group name. */ 2108 2109 bytes_left = BCM_OAM_GROUP_NAME_LENGTH; 2110 byte_p = (name_p + BCM_OAM_GROUP_NAME_LENGTH - 1); 2111 2112 while (bytes_left > 0) { 2113 *mangled_name_p = *byte_p; 2114 ++mangled_name_p; 2115 --byte_p; 2116 --bytes_left; 2117 } 2118 } 2119 2120 /* 2121 * Function: 2122 * _bcm_tr3_oam_read_clear_faults 2123 * Purpose: 2124 * Clear OAM group and endpoint faults on hardware table read operation. 2125 * Parameters: 2126 * unit - (IN) BCM device number 2127 * index - (IN) Group/Endpoint hardware table index 2128 * mem - (IN) Memory/table value 2129 * entry - (IN) Pointer to group/endpoint entry 2130 * ma_mep - (IN) Pointer to group/endpoint info structure 2131 * Returns: 2132 * BCM_E_NONE - No errors. 2133 * BCM_E_XXX - Otherwise. 2134 */ 2135 STATIC int 2136 _bcm_tr3_oam_read_clear_faults(int unit, int index, soc_mem_t mem, 2137 uint32 *entry, void *ma_rmep) 2138 { 2139 bcm_oam_group_info_t *group_info_p; /* Pointer to group info */ 2140 /* structure. */ 2141 bcm_oam_endpoint_info_t *ep_info_p; /* Pointer to endpoint info */ 2142 /* structure. */ 2143 _bcm_oam_fault_t *faults_list; /* Pointer to faults list. */ 2144 uint32 *faults; /* Faults flag bits. */ 2145 uint32 *p_faults; /* Persistent faults bits. */ 2146 uint32 clear_p_faults; /* Clear persistent faults bits. */ 2147 uint32 rval = 0; /* Hardware register value. */ 2148 uint32 clear_mask = 0; /* Mask to clear persistent faults*/ 2149 2150 LOG_DEBUG(BSL_LS_BCM_OAM, 2151 (BSL_META_U(unit, 2152 "OAM Info: _bcm_tr3_oam_read_clear_faults index=%d " 2153 "Table=%d.\n"), index, mem)); 2154 2155 /* Switch on memory name. */ 2156 switch (mem) { 2157 /* OAM group state table. */ 2158 case MA_STATEm: 2159 /* Set the pointer to the start of the group faults array. */ 2160 faults_list = _tr3_oam_group_faults; 2161 2162 /* Typecast to group information structure pointer. */ 2163 group_info_p = (bcm_oam_group_info_t *) ma_rmep; 2164 2165 /* Get group faults information. */ 2166 faults = &group_info_p->faults; 2167 p_faults = &group_info_p->persistent_faults; 2168 clear_p_faults = group_info_p->clear_persistent_faults; 2169 break; 2170 2171 /* OAM remote endpoint table. */ 2172 case RMEPm: 2173 faults_list = _tr3_oam_endpoint_faults; 2174 ep_info_p = (bcm_oam_endpoint_info_t *) ma_rmep; 2175 faults = &ep_info_p->faults; 2176 p_faults = &ep_info_p->persistent_faults; 2177 clear_p_faults = ep_info_p->clear_persistent_faults; 2178 break; 2179 2180 default: 2181 return (BCM_E_NONE); 2182 } 2183 2184 /* Loop on list of valid faults. */ 2185 for (;faults_list->mask != 0; ++faults_list) { 2186 2187 /* Get faults status. */ 2188 if (0 != soc_mem_field32_get(unit, mem, entry, 2189 faults_list->current_field)) { 2190 *faults |= faults_list->mask; 2191 } 2192 2193 /* Get sticky faults status. */ 2194 if (0 != soc_mem_field32_get(unit, mem, entry, 2195 faults_list->sticky_field)) { 2196 2197 *p_faults |= faults_list->mask; 2198 2199 /* 2200 * If user has request to clear persistent faults, 2201 * then set BITS_TO_CLEARf field in the register buffer. 2202 */ 2203 if (clear_p_faults) { 2204 clear_mask |= faults_list->clear_sticky_mask; 2205 } 2206 } 2207 } 2208 2209 /* Check if faults need to be cleared. */ 2210 if (clear_mask && clear_p_faults) { 2211 2212 LOG_VERBOSE(BSL_LS_BCM_OAM, 2213 (BSL_META_U(unit, 2214 "OAM: clear_mask %d.\n"), 2215 clear_mask)); 2216 2217 soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, BITS_TO_CLEARf, 2218 clear_mask); 2219 2220 /* Enable clearing of faults. */ 2221 soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, ENABLE_CLEARf, 1); 2222 2223 2224 if (MA_STATEm == mem) { 2225 soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, MEMORYf, 0); 2226 } else { 2227 soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, MEMORYf, 1); 2228 } 2229 2230 soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, INDEXf, index); 2231 2232 /* Update read control register. */ 2233 BCM_IF_ERROR_RETURN(WRITE_CCM_READ_CONTROLr(unit, rval)); 2234 } 2235 2236 return (BCM_E_NONE); 2237 } 2238 2239 #if defined(INCLUDE_BHH) 2240 /* 2241 * Function: 2242 * _bcm_tr3_oam_get_group_sw_rdi 2243 * Purpose: 2244 * Get OAM group SW RDI information. 2245 * Parameters: 2246 * unit - (IN) BCM device number 2247 * group_index - (IN) Group hardware table index 2248 * group_sw_rdi - (OUT) Pointer to group SW RDI 2249 * Returns: 2250 * BCM_E_NONE - No errors. 2251 * BCM_E_XXX - Otherwise. 2252 */ 2253 STATIC int 2254 _bcm_tr3_oam_get_group_sw_rdi(int unit, bcm_oam_group_t group_index, 2255 uint8 *group_sw_rdi) 2256 { 2257 maid_reduction_entry_t maid_reduction_entry; /* MAID reduction entry. */ 2258 2259 BCM_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, 2260 group_index, 2261 &maid_reduction_entry)); 2262 2263 if (1 == soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry, 2264 SW_RDIf)) { 2265 *group_sw_rdi = 1; 2266 } 2267 return (BCM_E_NONE); 2268 } 2269 #endif 2270 2271 /* 2272 * Function: 2273 * _bcm_tr3_oam_get_group 2274 * Purpose: 2275 * Get OAM group information. 2276 * Parameters: 2277 * unit - (IN) BCM device number 2278 * group_index - (IN) Group hardware table index 2279 * group - (IN) Pointer to group array list 2280 * group_info - (IN/OUT) Pointer to group info structure 2281 * Returns: 2282 * BCM_E_NONE - No errors. 2283 * BCM_E_XXX - Otherwise. 2284 */ 2285 STATIC int 2286 _bcm_tr3_oam_get_group(int unit, bcm_oam_group_t group_index, 2287 _bcm_oam_group_data_t *group_p, 2288 bcm_oam_group_info_t *group_info) 2289 { 2290 maid_reduction_entry_t maid_reduction_entry; /* MAID reduction entry. */ 2291 ma_state_entry_t ma_state_entry; /* MA_STATE table entry. */ 2292 int rv; /* Operation return status. */ 2293 2294 group_info->id = group_index; 2295 2296 BCM_IF_ERROR_RETURN(READ_MA_STATEm(unit, MEM_BLOCK_ANY, 2297 group_index, 2298 &ma_state_entry)); 2299 2300 group_info->lowest_alarm_priority = soc_MA_STATEm_field32_get 2301 (unit, &ma_state_entry, 2302 LOWESTALARMPRIf); 2303 2304 rv = _bcm_tr3_oam_read_clear_faults(unit, group_index, 2305 MA_STATEm, 2306 (uint32 *) &ma_state_entry, 2307 group_info); 2308 if (BCM_FAILURE(rv)) { 2309 LOG_ERROR(BSL_LS_BCM_OAM, 2310 (BSL_META_U(unit, 2311 "OAM Error: Clean Faults Group ID=%d- Failed.\n"), 2312 group_index)); 2313 return (rv); 2314 } 2315 if (group_info->flags & BCM_OAM_GROUP_GET_FAULTS_ONLY) { 2316 group_info->flags &= ~BCM_OAM_GROUP_GET_FAULTS_ONLY; 2317 return BCM_E_NONE; 2318 } 2319 2320 sal_memcpy(group_info->name, group_p[group_index].name, 2321 BCM_OAM_GROUP_NAME_LENGTH); 2322 2323 BCM_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, 2324 group_index, 2325 &maid_reduction_entry)); 2326 2327 if (1 == soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry, 2328 SW_RDIf)) { 2329 group_info->flags |= BCM_OAM_GROUP_REMOTE_DEFECT_TX; 2330 } 2331 2332 return (BCM_E_NONE); 2333 } 2334 2335 /* 2336 * Function: 2337 * _bcm_oam_group_ep_list_add 2338 * Purpose: 2339 * Add an endpoint to a group endpoint linked list. 2340 * Parameters: 2341 * unit - (IN) BCM device number 2342 * group_id - (IN) OAM group ID. 2343 * ep_id - (IN) OAM endpoint ID. 2344 * Retruns: 2345 * BCM_E_XXX 2346 */ 2347 STATIC int 2348 _bcm_oam_group_ep_list_add(int unit, 2349 bcm_oam_group_t group_id, 2350 bcm_oam_endpoint_t ep_id) 2351 { 2352 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 2353 _bcm_oam_group_data_t *group_p; /* Pointer to group data. */ 2354 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 2355 _bcm_oam_ep_list_t *ep_list_p = NULL; /* Pointer to endpoint list. */ 2356 2357 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 2358 2359 group_p = &oc->group_info[group_id]; 2360 /* coverity : this check is present as part of secure coding method */ 2361 /* coverity[dead_error_condition] */ 2362 if (NULL == group_p) { 2363 LOG_ERROR(BSL_LS_BCM_OAM, 2364 /* coverity[dead_error_begin] */ 2365 (BSL_META_U(unit, 2366 "OAM Error: Group data access for GID=%d failed" 2367 " %s.\n"), group_id, bcm_errmsg(BCM_E_INTERNAL))); 2368 return (BCM_E_INTERNAL); 2369 } 2370 2371 h_data_p = &oc->oam_hash_data[ep_id]; 2372 /* this check is present as part of secure coding method */ 2373 /* coverity[dead_error_condition] */ 2374 if (NULL == h_data_p) { 2375 LOG_ERROR(BSL_LS_BCM_OAM, 2376 (BSL_META_U(unit, 2377 "OAM Error: Endpoint data access for EP=%d failed" 2378 /* coverity[dead_error_begin] */ 2379 " %s.\n"), ep_id, bcm_errmsg(BCM_E_INTERNAL))); 2380 return (BCM_E_INTERNAL); 2381 } 2382 2383 _BCM_OAM_ALLOC(ep_list_p, _bcm_oam_ep_list_t, sizeof(_bcm_oam_ep_list_t), 2384 "EP list"); 2385 if (NULL == ep_list_p) { 2386 LOG_ERROR(BSL_LS_BCM_OAM, 2387 (BSL_META_U(unit, 2388 "OAM Error: Endpoint list alloc for EP=%d failed" 2389 " %s.\n"), ep_id, bcm_errmsg(BCM_E_MEMORY))); 2390 return (BCM_E_MEMORY); 2391 } 2392 2393 ep_list_p->prev = NULL; 2394 ep_list_p->ep_data_p = h_data_p; 2395 if (NULL == (*group_p->ep_list)) { 2396 /* Add endpoint as head node. */ 2397 ep_list_p->next = NULL; 2398 *group_p->ep_list = ep_list_p; 2399 } else { 2400 /* Add the endpoint to the linked list. */ 2401 ep_list_p->next = *group_p->ep_list; 2402 (*group_p->ep_list)->prev = ep_list_p; 2403 *group_p->ep_list = ep_list_p; 2404 } 2405 2406 LOG_DEBUG(BSL_LS_BCM_OAM, 2407 (BSL_META_U(unit, 2408 "OAM Info: _bcm_oam_group_ep_list_add (GID=%d) (EP=%d).\n"), 2409 group_id, ep_id)); 2410 return (BCM_E_NONE); 2411 } 2412 2413 /* 2414 * Function: 2415 * _bcm_oam_group_ep_list_remove 2416 * Purpose: 2417 * Remove an endpoint to a group endpoint linked list. 2418 * Parameters: 2419 * unit - (IN) BCM device number 2420 * group_id - (IN) OAM group ID. 2421 * ep_id - (IN) OAM endpoint ID. 2422 * Retruns: 2423 * BCM_E_XXX 2424 */ 2425 STATIC int 2426 _bcm_oam_group_ep_list_remove(int unit, 2427 bcm_oam_group_t group_id, 2428 bcm_oam_endpoint_t ep_id) 2429 { 2430 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 2431 _bcm_oam_group_data_t *group_p; /* Pointer to group data. */ 2432 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 2433 _bcm_oam_ep_list_t *cur; /* Current endpoint node pointer. */ 2434 _bcm_oam_ep_list_t *del_node; /* Pointer to a node to be deleted. */ 2435 2436 /* Control lock already taken by calling routine. */ 2437 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 2438 2439 group_p = &oc->group_info[group_id]; 2440 cur = *group_p->ep_list; 2441 if (NULL == cur) { 2442 /* No endpoints to remove from this group. */ 2443 LOG_DEBUG(BSL_LS_BCM_OAM, 2444 (BSL_META_U(unit, 2445 "OAM Info: No endpoints to delete in group" 2446 " GID:%d.\n"), group_id)); 2447 return (BCM_E_NONE); 2448 } 2449 2450 /* Check if head node needs to be deleated. */ 2451 if (ep_id == cur->ep_data_p->ep_id) { 2452 /* Delete head node. */ 2453 del_node = *group_p->ep_list; 2454 if ((*group_p->ep_list)->next) { 2455 *group_p->ep_list = (*group_p->ep_list)->next; 2456 (*group_p->ep_list)->prev = NULL; 2457 } else { 2458 *group_p->ep_list = NULL; 2459 } 2460 sal_free(del_node); 2461 LOG_DEBUG(BSL_LS_BCM_OAM, 2462 (BSL_META_U(unit, 2463 "OAM Info: Head node delete GID=%d - Success\n"), 2464 group_id)); 2465 return (BCM_E_NONE); 2466 } 2467 2468 /* Traverse the list and delete the matching node. */ 2469 while (NULL != cur->next->next) { 2470 h_data_p = cur->next->ep_data_p; 2471 if (NULL == h_data_p) { 2472 LOG_ERROR(BSL_LS_BCM_OAM, 2473 (BSL_META_U(unit, 2474 "OAM Error: Group=%d endpoints access failed -" 2475 " %s.\n"), group_id, bcm_errmsg(BCM_E_INTERNAL))); 2476 return (BCM_E_INTERNAL); 2477 } 2478 2479 if (ep_id == h_data_p->ep_id) { 2480 del_node = cur->next; 2481 cur->next = del_node->next; 2482 del_node->next->prev = cur; 2483 sal_free(del_node); 2484 LOG_DEBUG(BSL_LS_BCM_OAM, 2485 (BSL_META_U(unit, 2486 "OAM Info: Node delete GID=%d - Success\n"), 2487 group_id)); 2488 return (BCM_E_NONE); 2489 } 2490 cur = cur->next; 2491 } 2492 2493 /* Check if tail node needs to be deleted. */ 2494 h_data_p = cur->next->ep_data_p; 2495 if (ep_id == h_data_p->ep_id) { 2496 /* Delete tail node. */ 2497 del_node = cur->next; 2498 cur->next = NULL; 2499 sal_free(del_node); 2500 LOG_DEBUG(BSL_LS_BCM_OAM, 2501 (BSL_META_U(unit, 2502 "OAM Info: Tail node delete GID=%d - Success\n"), 2503 group_id)); 2504 return (BCM_E_NONE); 2505 } 2506 2507 return (BCM_E_NOT_FOUND); 2508 } 2509 2510 /* 2511 * Function: 2512 * _bcm_oam_remote_mep_hw_set 2513 * Purpose: 2514 * Configure hardware tables for a remote endpoint. 2515 * Parameters: 2516 * unit - (IN) BCM device number 2517 * ep_info_p - (IN) Pointer to remote endpoint information. 2518 * Retruns: 2519 * BCM_E_XXX 2520 */ 2521 STATIC int 2522 _bcm_oam_remote_mep_hw_set(int unit, 2523 const bcm_oam_endpoint_info_t *ep_info_p) 2524 { 2525 uint32 l3_entry[SOC_MAX_MEM_WORDS]; /* Remote view entry. */ 2526 rmep_entry_t rmep_entry; /* Remote MEP entry. */ 2527 uint32 oam_cur_time; /* Current time. */ 2528 _bcm_oam_hash_data_t *h_data_p = NULL; /* Hash data pointer. */ 2529 int rv; /* Operation return status. */ 2530 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 2531 const bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint info. */ 2532 soc_mem_t mem; /* L3 entry memory */ 2533 2534 if (NULL == ep_info_p) { 2535 return (BCM_E_INTERNAL); 2536 } 2537 2538 /* Initialize local endpoint info pointer. */ 2539 ep_p = ep_info_p; 2540 2541 /* Lock already taken by the calling routine. */ 2542 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 2543 2544 /* Get endpoint hash data pointer. */ 2545 h_data_p = &oc->oam_hash_data[ep_p->id]; 2546 if (!(h_data_p->in_use)) { 2547 LOG_ERROR(BSL_LS_BCM_OAM, 2548 (BSL_META_U(unit, 2549 "OAM Error: EP valid check failed.\n"))); 2550 return (BCM_E_INTERNAL); 2551 } 2552 2553 /* RMEP table programming. */ 2554 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 2555 2556 /* Set the MA group index. */ 2557 soc_RMEPm_field32_set(unit, &rmep_entry, MAID_INDEXf, 2558 ep_p->group); 2559 2560 /* 2561 * The following steps are necessary to enable CCM timeout events 2562 * without having received any CCMs. 2563 */ 2564 soc_RMEPm_field32_set(unit, &rmep_entry, 2565 RMEP_TIMESTAMP_VALIDf, 1); 2566 2567 BCM_IF_ERROR_RETURN 2568 (READ_OAM_CURRENT_TIMEr(unit, &oam_cur_time)); 2569 2570 soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMPf, 2571 oam_cur_time); 2572 2573 soc_RMEPm_field32_set(unit, &rmep_entry, 2574 RMEP_RECEIVED_CCMf, 2575 _bcm_tr3_oam_ccm_msecs_to_hw_encode(h_data_p->period)); 2576 /* End of timeout setup */ 2577 2578 soc_RMEPm_field32_set(unit, &rmep_entry, VALIDf, 1); 2579 2580 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index, 2581 &rmep_entry); 2582 if (BCM_FAILURE(rv)) { 2583 LOG_ERROR(BSL_LS_BCM_OAM, 2584 (BSL_META_U(unit, 2585 "OAM Error: RMEP table write failed EP=%d %s.\n"), 2586 ep_info_p->id, bcm_errmsg(rv))); 2587 return (rv); 2588 } 2589 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 2590 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 2591 mem = L3_ENTRY_IPV4_UNICASTm; 2592 } else { 2593 mem = L3_ENTRY_1m; 2594 } 2595 /* L3 unicast table programming. */ 2596 sal_memset(&l3_entry, 0, sizeof(l3_entry)); 2597 2598 /* Set the CCM interval. */ 2599 soc_mem_field32_set 2600 (unit, mem, &l3_entry, RMEP__CCMf, 2601 _bcm_tr3_oam_ccm_msecs_to_hw_encode(h_data_p->period)); 2602 2603 /* Set the entry hardware index. */ 2604 soc_mem_field32_set(unit, mem, &l3_entry, RMEP__RMEP_PTRf, 2605 h_data_p->remote_index); 2606 2607 /* 2608 * Construct endpoint RMEP view key for L3 Table entry 2609 * insert operation. 2610 */ 2611 #ifdef BCM_HURRICANE2_SUPPORT 2612 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 2613 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 2614 _bcm_hu2_oam_rmep_key_construct(unit, h_data_p, 2615 (l3_entry_ipv4_unicast_entry_t *)l3_entry); 2616 } else 2617 #endif /* BCM_HURRICANE2_SUPPORT */ 2618 { 2619 #ifdef BCM_TRIUMPH3_SUPPORT 2620 2621 _bcm_oam_rmep_key_construct(unit, h_data_p, 2622 (l3_entry_1_entry_t *)l3_entry); 2623 #endif /* BCM_HURRICANE2_SUPPORT */ 2624 } 2625 /* Mark the entry as valid. */ 2626 soc_mem_field32_set(unit, mem, &l3_entry, VALIDf, 1); 2627 2628 /* Install entry in hardware. */ 2629 rv = soc_mem_insert(unit, mem, 2630 MEM_BLOCK_ALL, &l3_entry); 2631 if (BCM_FAILURE(rv)) { 2632 LOG_ERROR(BSL_LS_BCM_OAM, 2633 (BSL_META_U(unit, 2634 "OAM Error: L3 table insert failed EP=%d %s.\n"), 2635 ep_p->id, bcm_errmsg(rv))); 2636 return (rv); 2637 } 2638 2639 /* Add the H/w index to logical index mapping for RMEP */ 2640 oc->remote_endpoints[h_data_p->remote_index] = ep_p->id; 2641 2642 return (BCM_E_NONE); 2643 } 2644 2645 /* 2646 * Function: 2647 * _bcm_tr3_oam_find_lmep 2648 * Purpose: 2649 * Search LMEP view table and return the match entry hardware index and 2650 * match entry data. 2651 * Parameters: 2652 * unit - (IN) BCM device number 2653 * h_data_p - (IN) Pointer to endpoint hash data. 2654 * entry_idx - (IN/OUT) Pointer to match entry hardware index. 2655 * l3_entry_p - (IN/OUT) Pointer to match entry data. 2656 * Retruns: 2657 * BCM_E_XXX 2658 */ 2659 STATIC int 2660 _bcm_tr3_oam_find_lmep(int unit, const _bcm_oam_hash_data_t *h_data_p, 2661 int *entry_idx, 2662 uint32 *l3_entry_p) 2663 { 2664 uint32 l3_entry[SOC_MAX_MEM_WORDS]; /* L3 entry to search.*/ 2665 int rv; /* Operation return status. */ 2666 2667 if (NULL == h_data_p || NULL == entry_idx || NULL == l3_entry_p) { 2668 return (BCM_E_INTERNAL); 2669 } 2670 2671 sal_memset(&l3_entry, 0, sizeof(l3_entry)); 2672 2673 /* Construct endpoint LMEP view key for L3 Table entry search operation. */ 2674 #ifdef BCM_HURRICANE2_SUPPORT 2675 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 2676 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 2677 _bcm_hu2_oam_lmep_key_construct(unit, h_data_p, 2678 (l3_entry_ipv4_unicast_entry_t *)l3_entry); 2679 } else 2680 #endif /* BCM_HURRICANE2_SUPPORT */ 2681 { 2682 #ifdef BCM_TRIUMPH3_SUPPORT 2683 _bcm_oam_lmep_key_construct(unit, h_data_p, 2684 (l3_entry_1_entry_t *)l3_entry); 2685 #endif /* BCM_TRIUMPH3_SUPPORT */ 2686 } 2687 /* Take L3 module protection mutex to block any updates. */ 2688 L3_LOCK(unit); 2689 2690 /* Perform the search in L3_ENTRY_1 table. */ 2691 #ifdef BCM_HURRICANE2_SUPPORT 2692 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 2693 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 2694 rv = soc_mem_search(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ANY, 2695 entry_idx, &l3_entry, l3_entry_p, 0); 2696 } else 2697 #endif /* BCM_HURRICANE2_SUPPORT */ 2698 { 2699 rv = soc_mem_search(unit, L3_ENTRY_1m, MEM_BLOCK_ANY, entry_idx, 2700 &l3_entry, l3_entry_p, 0); 2701 2702 } 2703 if (BCM_FAILURE(rv)) { 2704 LOG_VERBOSE(BSL_LS_BCM_OAM, 2705 (BSL_META_U(unit, 2706 "OAM Error: L3 entry lookup vlan=%d port=%x %s.\n"), 2707 h_data_p->vlan, h_data_p->sglp, bcm_errmsg(rv))); 2708 } 2709 2710 /* Release L3 module protection mutex. */ 2711 L3_UNLOCK(unit); 2712 2713 return (rv); 2714 } 2715 2716 #ifdef BCM_HURRICANE2_SUPPORT 2717 2718 STATIC void _bcm_oam_cmic_tdm_slot_time_get(int unit, 2719 uint32 *cmic_tdm_slot_time) 2720 { 2721 if(SOC_IS_GREYHOUND(unit)) { 2722 *cmic_tdm_slot_time = 100; 2723 } 2724 2725 if(SOC_IS_GREYHOUND2(unit)) { 2726 *cmic_tdm_slot_time = 385; 2727 } 2728 2729 if(SOC_IS_HURRICANE2(unit)) { 2730 *cmic_tdm_slot_time = 75; 2731 } 2732 2733 if(SOC_IS_HURRICANE3(unit)) { 2734 *cmic_tdm_slot_time = 96; 2735 if(soc_feature(unit, soc_feature_wh2)) 2736 { 2737 *cmic_tdm_slot_time = 40; 2738 } 2739 } 2740 } 2741 2742 /* 2743 * Function: 2744 * _bcm_oam_modify_oam_tx_control 2745 * Purpose: 2746 * Modifies the OAM TX control based on the inputs. 2747 * Parameters: 2748 * unit - (IN) BCM device number 2749 * reg_val - (IN/OUT) Pointer to OAM TX control register value. 2750 * read_write - (IN) read and write /just write operation indication 2751 * tx_diable - (OUT) TX disable or not indication 2752 * Retruns: 2753 * BCM_E_XXX 2754 */ 2755 STATIC int 2756 _bcm_oam_modify_oam_tx_control(int unit, uint32 *reg_val, int read_write, 2757 uint8 *tx_diable) 2758 { 2759 int rv = BCM_E_NONE; 2760 uint32 rval = 0; 2761 uint32 set_val = 0; 2762 soc_info_t *si = &SOC_INFO(unit); 2763 uint32 cmic_tdm_slot_time = 0, clock_period = 0; 2764 uint32 delay_us = 0; 2765 2766 if(SOC_IS_GREYHOUND(unit) || SOC_IS_HURRICANE2(unit)) { 2767 if (read_write) { 2768 rv = READ_OAM_TX_CONTROLr(unit, &rval); 2769 if (BCM_FAILURE(rv)) { 2770 LOG_ERROR(BSL_LS_BCM_OAM, 2771 (BSL_META_U(unit, 2772 "OAM Error: reading OAM_TX_CONTROLr\n"))); 2773 return (rv); 2774 } 2775 *reg_val = rval; 2776 if( (rval&0x1) == 0x1 ) { 2777 set_val = (rval&0xFE); 2778 rv = WRITE_OAM_TX_CONTROLr(unit, set_val); 2779 if (BCM_FAILURE(rv)) { 2780 LOG_ERROR(BSL_LS_BCM_OAM, 2781 (BSL_META_U(unit, 2782 "OAM Error: writing OAM_TX_CONTROLr\n"))); 2783 return (rv); 2784 } 2785 /* Clock period caluclation in nano seconds. Fractional part 2786 will be truncated and we should be ok with it 2787 as only us granularity is needed */ 2788 clock_period = (1000/si->frequency); 2789 2790 _bcm_oam_cmic_tdm_slot_time_get(unit, &cmic_tdm_slot_time); 2791 2792 /* As per WAR provovided by HW team in GH-2161, 2793 wait time before LMEP table access is calculated as 2794 (512*(3+cmic_tdm_slot_time)+cmic_tdm_slot_time)*clock periods 2795 where (CMIC slot is 1/68@300Mhz) with device frequency of 300Mhz, 2796 cmic_tdm_slot_time = 68 cycles */ 2797 2798 /* Calculate the delay to be added in micro seconds */ 2799 delay_us = (((512*(3+cmic_tdm_slot_time) + cmic_tdm_slot_time) * 2800 clock_period)) /1000; 2801 sal_usleep(delay_us); 2802 } 2803 *tx_diable = 1; 2804 } else { 2805 rv = WRITE_OAM_TX_CONTROLr(unit, *reg_val); 2806 if (BCM_FAILURE(rv)) { 2807 LOG_ERROR(BSL_LS_BCM_OAM, 2808 (BSL_META_U(unit, 2809 "OAM Error: writing OAM_TX_CONTROLr\n"))); 2810 return (rv); 2811 } 2812 } 2813 } 2814 return rv; 2815 } 2816 #endif /* BCM_HURRICANE2_SUPPORT */ 2817 /* 2818 * Function: 2819 * _bcm_oam_local_tx_mep_hw_set 2820 * Purpose: 2821 * Configure hardware tables for a local CCM Tx enabled endpoint. 2822 * Parameters: 2823 * unit - (IN) BCM device number 2824 * ep_info_p - (IN) Pointer to remote endpoint information. 2825 * Retruns: 2826 * BCM_E_XXX 2827 */ 2828 STATIC int 2829 _bcm_oam_local_tx_mep_hw_set(int unit, 2830 const bcm_oam_endpoint_info_t *ep_info_p) 2831 { 2832 _bcm_oam_hash_data_t *hash_data; /* Pointer to endpoint hash data. */ 2833 lmep_entry_t entry; /* LMEP table entry. */ 2834 lmep_da_entry_t dmac_entry; /* LMEP table entry. */ 2835 int word; /* Word index. */ 2836 uint32 reversed_maid[BCM_OAM_GROUP_NAME_LENGTH / 4]; 2837 /* Group name in Hw format. */ 2838 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 2839 const bcm_oam_endpoint_info_t *ep_p;/* Pointer to endpoint info. */ 2840 #ifdef BCM_HURRICANE2_SUPPORT 2841 int rv; /* Operation return status. */ 2842 uint32 rval = 0; 2843 uint8 tx_disable = 0; 2844 #endif /* BCM_HURRICANE2_SUPPORT */ 2845 2846 if (NULL == ep_info_p) { 2847 return (BCM_E_INTERNAL); 2848 } 2849 2850 /* Initialize local endpoint info pointer. */ 2851 ep_p = ep_info_p; 2852 2853 /* Lock already taken by the calling routine. */ 2854 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 2855 2856 2857 /* Get the stored endpoint information from hash table. */ 2858 hash_data = &oc->oam_hash_data[ep_p->id]; 2859 if (!(hash_data->in_use)) { 2860 LOG_ERROR(BSL_LS_BCM_OAM, 2861 (BSL_META_U(unit, 2862 "OAM Error: EP valid check failed.\n"))); 2863 return (BCM_E_INTERNAL); 2864 } 2865 2866 sal_memset(&entry, 0, sizeof(lmep_entry_t)); 2867 2868 /* Set the Group base index. */ 2869 soc_LMEPm_field32_set(unit, &entry, MAID_INDEXf, ep_p->group); 2870 2871 /* Set source MAC address to be used on transmitted packets. */ 2872 soc_LMEPm_mac_addr_set(unit, &entry, SAf, ep_p->src_mac_address); 2873 2874 /* Set the Maintenance Domain Level. */ 2875 soc_LMEPm_field32_set(unit, &entry, MDLf, ep_p->level); 2876 2877 /* Set endpoint name. */ 2878 soc_LMEPm_field32_set(unit, &entry, MEPIDf, ep_p->name); 2879 2880 /* Set packet priority value to be used in transmitted packet. */ 2881 soc_LMEPm_field32_set(unit, &entry, LMEP_PRIORITYf, 2882 ep_p->pkt_pri); 2883 2884 /* 2885 * Set VLAN ID to be used in the transmitted packet. 2886 * For link level MEPs, this VLAN_ID == 0. 2887 */ 2888 soc_LMEPm_field32_set(unit, &entry, VLAN_IDf, ep_p->vlan); 2889 2890 /* Set interval between CCM packet transmissions. */ 2891 soc_LMEPm_field32_set 2892 (unit, &entry, CCM_INTERVALf, 2893 _bcm_tr3_oam_ccm_msecs_to_hw_encode(ep_p->ccm_period)); 2894 2895 /* Set the destination port on which packet needs to Tx. */ 2896 soc_LMEPm_field32_set(unit, &entry, DESTf, hash_data->dglp); 2897 2898 /* Set HiGig opcode to Unicast packet opcode. */ 2899 soc_LMEPm_field32_set(unit, &entry, MH_OPCODEf, BCM_HG_OPCODE_UC); 2900 2901 /* Set CCM packet internal priority used for scheduling. */ 2902 soc_LMEPm_field32_set(unit, &entry, INT_PRIf, ep_p->int_pri); 2903 2904 /* Set Port status TLV in CCM Tx packets. */ 2905 if (ep_p->flags & BCM_OAM_ENDPOINT_PORT_STATE_UPDATE) { 2906 if (ep_p->port_state > BCM_OAM_PORT_TLV_UP) { 2907 return (BCM_E_PARAM); 2908 } 2909 soc_LMEPm_field32_set(unit, &entry, PORT_TLVf, 2910 (ep_p->port_state == BCM_OAM_PORT_TLV_UP) 2911 ? 1 : 0); 2912 } 2913 2914 /* Set Interface status TLV in CCM Tx packets - 3-bits wide. */ 2915 if (ep_p->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_UPDATE) { 2916 if ((ep_p->interface_state < BCM_OAM_INTERFACE_TLV_UP) 2917 || (ep_p->interface_state > BCM_OAM_INTERFACE_TLV_LLDOWN)) { 2918 return (BCM_E_PARAM); 2919 } 2920 soc_LMEPm_field32_set(unit, &entry, INTERFACE_TLVf, 2921 ep_p->interface_state); 2922 } 2923 2924 /* 2925 * When this bit is '1', both port and interface TLV values are set in 2926 * CCM Tx packets. 2927 */ 2928 if ((ep_p->flags & BCM_OAM_ENDPOINT_PORT_STATE_TX) 2929 || (ep_p->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_TX)) { 2930 soc_LMEPm_field32_set(unit, &entry, INSERT_TLVf, 1); 2931 } 2932 2933 /* 2934 * Construct group name for hardware. 2935 * i.e Word-reverse the MAID bytes for hardware. 2936 */ 2937 for (word = 0; word < (BCM_OAM_GROUP_NAME_LENGTH / 4); 2938 ++word) { 2939 reversed_maid[word] 2940 = bcm_htonl(((uint32 *) oc->group_info[ep_p->group].name) 2941 [((BCM_OAM_GROUP_NAME_LENGTH / 4) - 1) - word]); 2942 } 2943 2944 /* Set the group name. */ 2945 soc_LMEPm_field_set(unit, &entry, MAIDf, reversed_maid); 2946 #ifdef BCM_HURRICANE2_SUPPORT 2947 rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 1, &tx_disable); 2948 if (BCM_FAILURE(rv)) { 2949 LOG_ERROR(BSL_LS_BCM_OAM, 2950 (BSL_META_U(unit, 2951 "OAM Error: in _bcm_oam_modify_oam_tx_control \n"))); 2952 return (rv); 2953 } 2954 #endif /* BCM_HURRICANE2_SUPPORT */ 2955 2956 /* Write entry to hardware LMEP table. */ 2957 SOC_IF_ERROR_RETURN 2958 (WRITE_LMEPm(unit, MEM_BLOCK_ALL, hash_data->local_tx_index, 2959 &entry)); 2960 /* LMEP_DA table programming. */ 2961 sal_memset(&dmac_entry, 0, sizeof(lmep_da_entry_t)); 2962 2963 /* Set CCM packet Destination MAC address value. */ 2964 #ifdef BCM_HURRICANE2_SUPPORT 2965 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 2966 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 2967 soc_mem_mac_addr_set(unit, LMEP_DAm, &dmac_entry, MACDAf, 2968 ep_p->dst_mac_address); 2969 2970 } else 2971 #endif /* BCM_HURRICANE2_SUPPORT */ 2972 { 2973 soc_mem_mac_addr_set(unit, LMEP_DAm, &dmac_entry, DAf, 2974 ep_p->dst_mac_address); 2975 } 2976 /* 2977 * Write the entry to hardware LMEP_DA table. 2978 * Use same hardware index as the LMEP table entry index. 2979 */ 2980 SOC_IF_ERROR_RETURN 2981 (WRITE_LMEP_DAm(unit, MEM_BLOCK_ALL, hash_data->local_tx_index, 2982 &dmac_entry)); 2983 2984 #ifdef BCM_HURRICANE2_SUPPORT 2985 if (tx_disable) { 2986 rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 0, &tx_disable); 2987 if (BCM_FAILURE(rv)) { 2988 LOG_ERROR(BSL_LS_BCM_OAM, 2989 (BSL_META_U(unit, 2990 "OAM Error: in _bcm_oam_modify_oam_tx_control \n"))); 2991 return (rv); 2992 } 2993 } 2994 #endif /* BCM_HURRICANE2_SUPPORT */ 2995 2996 return (BCM_E_NONE); 2997 } 2998 2999 /* 3000 * Function: 3001 * _bcm_oam_local_tx_mep_hw_set 3002 * Purpose: 3003 * Configure hardware tables for a local CCM Rx enabled endpoint. 3004 * Parameters: 3005 * unit - (IN) BCM device number 3006 * ep_info_p - (IN) Pointer to remote endpoint information. 3007 * Retruns: 3008 * BCM_E_XXX 3009 */ 3010 STATIC int 3011 _bcm_oam_local_rx_mep_hw_set(int unit, 3012 const bcm_oam_endpoint_info_t *ep_info_p) 3013 { 3014 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 3015 ma_index_entry_t ma_idx_entry; /* MA_INDEX table entry buffer. */ 3016 uint32 opcode_entry = 0; /* Opcode control profile entry. */ 3017 void *entries[1]; /* Pointer to opcode control entry. */ 3018 uint32 profile_index; /* opcode control profile index. */ 3019 uint32 l3_entry[SOC_MAX_MEM_WORDS]; /* L3 entry buffer. */ 3020 int l3_index = -1; /* L3 entry hardware index. */ 3021 int rv; /* Operation return status. */ 3022 uint8 mdl; /* Maintenance domain level. */ 3023 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 3024 const bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint info. */ 3025 soc_mem_t mem; /* L3 entry memory */ 3026 if (NULL == ep_info_p) { 3027 return (BCM_E_INTERNAL); 3028 } 3029 3030 /* Initialize local endpoint info pointer. */ 3031 ep_p = ep_info_p; 3032 3033 /* Lock already taken by the calling routine. */ 3034 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 3035 3036 /* Get endpoint hash data pointer. */ 3037 h_data_p = &oc->oam_hash_data[ep_p->id]; 3038 3039 /* Construct the opcode control profile table entry. */ 3040 if (ep_p->opcode_flags & _BCM_TR3_OAM_OPCODE_MASK) { 3041 /* Use application specified opcode control settings. */ 3042 rv = _bcm_tr3_oam_opcode_profile_entry_set(unit, 3043 ep_p->opcode_flags, 3044 &opcode_entry); 3045 if (BCM_FAILURE(rv)) { 3046 LOG_ERROR(BSL_LS_BCM_OAM, 3047 (BSL_META_U(unit, 3048 "OAM Error: Opcode profile set failed for EP=%d" 3049 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 3050 return (rv); 3051 } 3052 } else { 3053 /* Use default opcode control profile settings. */ 3054 rv = _bcm_tr3_oam_opcode_profile_entry_init(unit, &opcode_entry); 3055 if (BCM_FAILURE(rv)) { 3056 LOG_ERROR(BSL_LS_BCM_OAM, 3057 (BSL_META_U(unit, 3058 "OAM Error: Opcode profile init failed for EP=%d" 3059 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 3060 return (rv); 3061 } 3062 } 3063 3064 /* Add entry to profile table. */ 3065 entries[0] = &opcode_entry; 3066 3067 soc_mem_lock(unit, OAM_OPCODE_CONTROL_PROFILEm); 3068 3069 rv = soc_profile_mem_add(unit, &oc->oam_opcode_control_profile, 3070 (void *) &entries, 1, &profile_index); 3071 if (BCM_FAILURE(rv)) { 3072 LOG_ERROR(BSL_LS_BCM_OAM, 3073 (BSL_META_U(unit, 3074 "OAM Error: Opcode profile add failed for EP=%d" 3075 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 3076 soc_mem_unlock(unit, OAM_OPCODE_CONTROL_PROFILEm); 3077 return (rv); 3078 } 3079 3080 /* Release opcode control profile table lock. */ 3081 soc_mem_unlock(unit, OAM_OPCODE_CONTROL_PROFILEm); 3082 3083 /* Store endpoint OAM opcode profile table index value. */ 3084 h_data_p->profile_index = profile_index; 3085 3086 /* 3087 * MA_INDEX table programming. 3088 */ 3089 3090 /* Clear the entry data. */ 3091 sal_memset(&ma_idx_entry, 0, sizeof(ma_index_entry_t)); 3092 3093 /* Set group index value. */ 3094 soc_MA_INDEXm_field32_set(unit, &ma_idx_entry, MA_PTRf, 3095 ep_p->group); 3096 3097 /* Set OAM opcode control profile table index. */ 3098 soc_MA_INDEXm_field32_set(unit, &ma_idx_entry, 3099 OAM_OPCODE_CONTROL_PROFILE_PTRf, 3100 h_data_p->profile_index); 3101 3102 /* Set CPU CoS queue value. */ 3103 if (ep_p->opcode_flags & BCM_OAM_OPCODE_CCM_COPY_TO_CPU) { 3104 soc_MA_INDEXm_field32_set(unit, &ma_idx_entry, 3105 INT_PRIf, 3106 ep_p->cpu_qid); 3107 } 3108 3109 rv = WRITE_MA_INDEXm(unit, MEM_BLOCK_ALL, h_data_p->local_rx_index, 3110 &ma_idx_entry); 3111 if (BCM_FAILURE(rv)) { 3112 LOG_ERROR(BSL_LS_BCM_OAM, 3113 (BSL_META_U(unit, 3114 "OAM Error: MA_INDEX table write failed for EP=%d" 3115 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 3116 return (rv); 3117 } 3118 3119 /* L3 entry */ 3120 L3_LOCK(unit); 3121 3122 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 3123 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 3124 mem = L3_ENTRY_IPV4_UNICASTm; 3125 } else { 3126 mem = L3_ENTRY_1m; 3127 } 3128 3129 /* Initialize L3 entry buffer. */ 3130 sal_memset(&l3_entry, 0, sizeof(l3_entry)); 3131 3132 if (BCM_SUCCESS 3133 (_bcm_tr3_oam_find_lmep(unit, h_data_p, &l3_index, l3_entry))) { 3134 3135 /* There's already an entry for this vlan + glp or 0 + vp */ 3136 mdl = soc_mem_field32_get(unit, mem, &l3_entry, LMEP__MDL_BITMAPf); 3137 3138 mdl |= (1 << ep_p->level); 3139 3140 rv = soc_mem_field32_modify(unit, mem, l3_index, 3141 LMEP__MDL_BITMAPf, mdl); 3142 if (BCM_FAILURE(rv)) { 3143 LOG_ERROR(BSL_LS_BCM_OAM, 3144 (BSL_META_U(unit, 3145 "OAM Error: L3_ENTRY table update failed for EP=%d" 3146 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 3147 L3_UNLOCK(unit); 3148 return (rv); 3149 } 3150 } else { 3151 3152 /* This is the first entry at this vlan+glp */ 3153 sal_memset(&l3_entry, 0, sizeof(l3_entry)); 3154 3155 soc_mem_field32_set(unit, mem, &l3_entry, LMEP__MDL_BITMAPf, 3156 (1 << ep_p->level)); 3157 3158 soc_mem_field32_set 3159 (unit, mem, &l3_entry, LMEP__MA_BASE_PTRf, 3160 (h_data_p->local_rx_index >> _BCM_OAM_EP_LEVEL_BIT_COUNT)); 3161 3162 if (ep_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) { 3163 soc_mem_field32_set 3164 (unit, mem, &l3_entry, LMEP__EXP_TAG_STATUSf, 0x1); 3165 3166 soc_mem_field32_set 3167 (unit, mem, &l3_entry, LMEP__EXP_TAG_STATUS_MASKf, 0x1); 3168 } else if (ep_p->flags2 & 3169 BCM_OAM_ENDPOINT_FLAGS2_MATCH_SINGLE_TAGGED_OUTER_VLAN) { 3170 soc_mem_field32_set 3171 (unit, mem, &l3_entry, LMEP__EXP_TAG_STATUSf, 0x2); 3172 3173 soc_mem_field32_set 3174 (unit, mem, &l3_entry, LMEP__EXP_TAG_STATUS_MASKf, 0x3); 3175 } else { 3176 soc_mem_field32_set 3177 (unit, mem, &l3_entry, LMEP__EXP_TAG_STATUSf, 0x3); 3178 3179 soc_mem_field32_set 3180 (unit, mem, &l3_entry, LMEP__EXP_TAG_STATUS_MASKf, 0x2); 3181 } 3182 3183 /* Construct LMEP view key for L3 Table insert operation. */ 3184 #ifdef BCM_HURRICANE2_SUPPORT 3185 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 3186 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 3187 _bcm_hu2_oam_lmep_key_construct(unit, h_data_p, 3188 (l3_entry_ipv4_unicast_entry_t *)l3_entry); 3189 } else 3190 #endif /* BCM_HURRICANE2_SUPPORT */ 3191 { 3192 #ifdef BCM_TRIUMPH3_SUPPORT 3193 _bcm_oam_lmep_key_construct(unit, h_data_p, 3194 (l3_entry_1_entry_t *)l3_entry); 3195 #endif 3196 } 3197 soc_mem_field32_set(unit, mem, &l3_entry, VALIDf, 1); 3198 3199 rv = soc_mem_insert(unit, mem, MEM_BLOCK_ALL, &l3_entry); 3200 if (BCM_FAILURE(rv)) { 3201 LOG_ERROR(BSL_LS_BCM_OAM, 3202 (BSL_META_U(unit, 3203 "OAM Error: L3_ENTRY table insert failed for EP=%d" 3204 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 3205 L3_UNLOCK(unit); 3206 return (rv); 3207 } 3208 } 3209 3210 L3_UNLOCK(unit); 3211 3212 return (BCM_E_NONE); 3213 } 3214 3215 /* 3216 * Function: 3217 * _bcm_oam_rx_endpoint_reserve 3218 * Purpose: 3219 * Reserve an hardware index in the group state table to maintain the state 3220 * for a CCM Rx enabled endpoint. 3221 * Parameters: 3222 * unit - (IN) BCM device number 3223 * ep_info_p - (IN) Pointer to remote endpoint information. 3224 * Retruns: 3225 * BCM_E_XXX 3226 */ 3227 STATIC int 3228 _bcm_oam_rx_endpoint_reserve(int unit, 3229 const bcm_oam_endpoint_info_t *ep_info_p) 3230 { 3231 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 3232 int rv; /* Operation return status. */ 3233 uint32 l3_entry[SOC_MAX_MEM_WORDS]; /* L3 entry buffer. */ 3234 int l3_index = -1; /* L3 entry hardware index. */ 3235 int count = 0; /* Successful Hw indices allocated. */ 3236 uint8 mdl = 0; /* Maintenance domain level. */ 3237 int rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0}; 3238 /* Endpoint Rx hardware index. */ 3239 uint16 ma_base_idx; /* Base pointer to endpoint state */ 3240 /* table [MA_INDEX = (BASE + MDL)]. */ 3241 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 3242 const bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint information. */ 3243 soc_mem_t mem; /* L3 entry memory */ 3244 3245 if (NULL == ep_info_p) { 3246 return (BCM_E_INTERNAL); 3247 } 3248 3249 /* Lock already taken by the calling routine. */ 3250 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 3251 3252 /* Initialize local endpoint information pointer. */ 3253 ep_p = ep_info_p; 3254 3255 /* Get endpoint hash data pointer. */ 3256 h_data_p = &oc->oam_hash_data[ep_p->id]; 3257 if (!(h_data_p->in_use)) { 3258 return (BCM_E_INTERNAL); 3259 } 3260 3261 3262 /* Initialize L3 entry buffer. */ 3263 sal_memset(&l3_entry, 0, sizeof(l3_entry)); 3264 3265 /* Find out if a matching entry already installed in hardware table. */ 3266 rv = _bcm_tr3_oam_find_lmep(unit, h_data_p, &l3_index, l3_entry); 3267 if (BCM_FAILURE(rv)) { 3268 /* 3269 * If NO match found, allocate a new hardware index from MA_INDEX 3270 * pool. 3271 */ 3272 3273 /* 3274 * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA 3275 * group endpoints. While allocating the base index, next 7 hardware 3276 * indices are also reserved. 3277 */ 3278 rv = shr_idxres_list_alloc_set(oc->ma_idx_pool, 8, 3279 (shr_idxres_element_t *) rx_index, 3280 (shr_idxres_element_t *) &count); 3281 if (BCM_FAILURE(rv)) { 3282 LOG_ERROR(BSL_LS_BCM_OAM, 3283 (BSL_META_U(unit, 3284 "OAM Error: MA_INDEX index alloc failed EP:%d" 3285 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 3286 return (rv); 3287 } else { 3288 LOG_DEBUG(BSL_LS_BCM_OAM, 3289 (BSL_META_U(unit, 3290 "OAM Info: MA_INDEX alloc for EP:%d success." 3291 " rx_idx_base:%p alloc-count:%d.\n"), ep_p->id, 3292 rx_index, count)); 3293 } 3294 3295 /* Store hardware Rx index value for this endpoint. */ 3296 h_data_p->local_rx_index = (rx_index[0] + ep_p->level); 3297 } else if (BCM_SUCCESS(rv)) { 3298 3299 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 3300 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 3301 mem = L3_ENTRY_IPV4_UNICASTm; 3302 } else { 3303 mem = L3_ENTRY_1m; 3304 } 3305 /* Matching entry found, get installed entry MDL value. */ 3306 mdl = soc_mem_field32_get(unit, mem, &l3_entry, LMEP__MDL_BITMAPf); 3307 3308 /* Findout if MDLs are same. */ 3309 if (0 == (mdl & (1 << ep_p->level))) { 3310 ma_base_idx = soc_mem_field32_get(unit, mem, &l3_entry, 3311 LMEP__MA_BASE_PTRf); 3312 /* 3313 * MDLs are not same, so calculate Rx index for this new endpoint. 3314 * Endpoint MDL values can be (0-7). 8 MDLs are supported per-MA 3315 * group. Base Rx index written to hardware, so multiply by 8 3316 * i.e (<< _BCM_OAM_EP_LEVEL_BIT_COUNT) and add new endpoint MDL. 3317 */ 3318 h_data_p->local_rx_index 3319 = ((ma_base_idx << _BCM_OAM_EP_LEVEL_BIT_COUNT) 3320 | ep_p->level); 3321 } else { 3322 /* Rx index already taken return error. */ 3323 LOG_ERROR(BSL_LS_BCM_OAM, 3324 (BSL_META_U(unit, 3325 "OAM Error: No free Rx index found for EP:%d" 3326 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 3327 return (BCM_E_RESOURCE); 3328 } 3329 } 3330 3331 return (rv); 3332 } 3333 3334 /* 3335 * Function: 3336 * _bcm_tr3_oam_remote_endpoint_delete 3337 * Purpose: 3338 * Delete a remote endpoint. 3339 * Parameters: 3340 * unit - (IN) BCM device number 3341 * h_data_p - (IN) Pointer to endpoint hash data 3342 * Retruns: 3343 * BCM_E_XXX 3344 */ 3345 STATIC int 3346 _bcm_tr3_oam_remote_endpoint_delete(int unit, 3347 _bcm_oam_hash_data_t *h_data_p) 3348 { 3349 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 3350 uint32 l3_entry[SOC_MAX_MEM_WORDS];/* RMEP view table entry. */ 3351 ma_state_entry_t ma_state_entry; /* Group state machine table entry. */ 3352 rmep_entry_t rmep_entry; /* Remote endpoint table entry. */ 3353 int rv; /* Operation return status. */ 3354 uint32 some_rmep_ccm_defect_counter = 0; /* No. of RMEPs in MA with CCM */ 3355 /* defects. */ 3356 uint32 some_rdi_defect_counter = 0; /* No. of RMEPs in MA with RDI */ 3357 /* defects. */ 3358 uint32 cur_some_rdi_defect = 0; /* Any RMEP in MA with RDI defect. */ 3359 uint32 cur_some_rmep_ccm_defect = 0; /* Any RMEP in MA with CCM defect. */ 3360 uint32 cur_rmep_ccm_defect = 0; /* RMEP lookup failed or CCM */ 3361 /* interval mismatch. */ 3362 uint32 cur_rmep_last_rdi = 0; /* Last CCM RDI Rx from this RMEP. */ 3363 uint32 first, last, validLow, validHigh, freeCount, allocCount; 3364 3365 /* Lock already taken by the calling routine. */ 3366 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 3367 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 3368 3369 /* Get remote endpoint entry value from hardware. */ 3370 rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index, &rmep_entry); 3371 if (BCM_FAILURE(rv)) { 3372 LOG_ERROR(BSL_LS_BCM_OAM, 3373 (BSL_META_U(unit, 3374 "OAM Error: RMEP table read failed for EP=%d" 3375 "%s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 3376 return (rv); 3377 } 3378 3379 cur_rmep_ccm_defect 3380 = soc_RMEPm_field32_get(unit, &rmep_entry, 3381 CURRENT_RMEP_CCM_DEFECTf); 3382 3383 cur_rmep_last_rdi 3384 = soc_RMEPm_field32_get(unit, &rmep_entry, 3385 CURRENT_RMEP_LAST_RDIf); 3386 3387 sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry)); 3388 rv = READ_MA_STATEm(unit, MEM_BLOCK_ANY, h_data_p->group_index, 3389 &ma_state_entry); 3390 if (BCM_FAILURE(rv)) { 3391 LOG_ERROR(BSL_LS_BCM_OAM, 3392 (BSL_META_U(unit, 3393 "OAM Error: Group state (GID=%d) table read" 3394 " failed - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 3395 return (rv); 3396 } 3397 3398 if ((0 != cur_rmep_ccm_defect) || (0 != cur_rmep_last_rdi)) { 3399 3400 some_rmep_ccm_defect_counter 3401 = soc_MA_STATEm_field32_get(unit, &ma_state_entry, 3402 SOME_RMEP_CCM_DEFECT_COUNTERf); 3403 cur_some_rmep_ccm_defect 3404 = soc_MA_STATEm_field32_get(unit, &ma_state_entry, 3405 CURRENT_SOME_RMEP_CCM_DEFECTf); 3406 3407 if ((0 != cur_rmep_ccm_defect) 3408 && (some_rmep_ccm_defect_counter > 0)) { 3409 --some_rmep_ccm_defect_counter; 3410 soc_MA_STATEm_field32_set 3411 (unit, &ma_state_entry, SOME_RMEP_CCM_DEFECT_COUNTERf, 3412 some_rmep_ccm_defect_counter); 3413 3414 if (0 == some_rmep_ccm_defect_counter) { 3415 cur_some_rmep_ccm_defect = 0; 3416 soc_MA_STATEm_field32_set 3417 (unit, &ma_state_entry, CURRENT_SOME_RMEP_CCM_DEFECTf, 3418 cur_some_rmep_ccm_defect); 3419 } 3420 } 3421 3422 some_rdi_defect_counter 3423 = soc_MA_STATEm_field32_get(unit, &ma_state_entry, 3424 SOME_RDI_DEFECT_COUNTERf); 3425 cur_some_rdi_defect 3426 = soc_MA_STATEm_field32_get(unit, &ma_state_entry, 3427 CURRENT_SOME_RDI_DEFECTf); 3428 3429 if ((0 != cur_rmep_last_rdi) 3430 && (some_rdi_defect_counter > 0)) { 3431 --some_rdi_defect_counter; 3432 soc_MA_STATEm_field32_set 3433 (unit, &ma_state_entry, SOME_RDI_DEFECT_COUNTERf, 3434 some_rdi_defect_counter); 3435 3436 if (0 == some_rdi_defect_counter) { 3437 cur_some_rdi_defect = 0; 3438 soc_MA_STATEm_field32_set 3439 (unit, &ma_state_entry, CURRENT_SOME_RDI_DEFECTf, 3440 cur_some_rdi_defect); 3441 } 3442 } 3443 3444 rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, h_data_p->group_index, 3445 &ma_state_entry); 3446 if (BCM_FAILURE(rv)) { 3447 LOG_ERROR(BSL_LS_BCM_OAM, 3448 (BSL_META_U(unit, 3449 "OAM Error: Group state (GID=%d) table write" 3450 " failed - %s.\n"), h_data_p->group_index, 3451 bcm_errmsg(rv))); 3452 return (rv); 3453 } 3454 } 3455 3456 /* Clear RMEP table entry for this endpoint index. */ 3457 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 3458 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index, 3459 &rmep_entry); 3460 if (BCM_FAILURE(rv)) { 3461 LOG_ERROR(BSL_LS_BCM_OAM, 3462 (BSL_META_U(unit, 3463 "OAM Error: RMEP table write index=%x (EP=%d)" 3464 " - %s.\n"), h_data_p->remote_index, 3465 h_data_p->ep_id, bcm_errmsg(rv))); 3466 return (rv); 3467 } 3468 3469 sal_memset(&l3_entry, 0, sizeof(l3_entry)); 3470 3471 /* Construct endpoint RMEP view key for L3 Table entry delete operation. */ 3472 #ifdef BCM_HURRICANE2_SUPPORT 3473 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 3474 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 3475 _bcm_hu2_oam_rmep_key_construct(unit, h_data_p, 3476 (l3_entry_ipv4_unicast_entry_t *)l3_entry); 3477 rv = soc_mem_delete(unit, L3_ENTRY_IPV4_UNICASTm, 3478 MEM_BLOCK_ALL, &l3_entry); 3479 } else 3480 #endif /* BCM_HURRICANE2_SUPPORT */ 3481 { 3482 #ifdef BCM_TRIUMPH3_SUPPORT 3483 _bcm_oam_rmep_key_construct(unit, h_data_p, 3484 (l3_entry_1_entry_t *)l3_entry); 3485 rv = soc_mem_delete(unit, L3_ENTRY_1m, MEM_BLOCK_ALL, &l3_entry); 3486 #endif 3487 } 3488 if (BCM_FAILURE(rv) && (oc->init)) { 3489 LOG_ERROR(BSL_LS_BCM_OAM, 3490 (BSL_META_U(unit, 3491 "OAM Error: RMEP view update (EP=%d)" 3492 " - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 3493 return (rv); 3494 } 3495 3496 /* Return ID back to free RMEP ID pool. */ 3497 BCM_IF_ERROR_RETURN 3498 (shr_idxres_list_free(oc->rmep_pool, h_data_p->remote_index)); 3499 3500 rv = shr_idxres_list_state(oc->rmep_pool, 3501 &first, &last, 3502 &validLow, &validHigh, 3503 &freeCount, &allocCount); 3504 if (BCM_FAILURE(rv)) { 3505 LOG_ERROR(BSL_LS_BCM_OAM, 3506 (BSL_META_U(unit, 3507 "OAM Error: RMEP pool state get failed " 3508 " - %s.\n"), bcm_errmsg(rv))); 3509 return (rv); 3510 } 3511 3512 if(allocCount == 0) 3513 { 3514 soc_MA_STATEm_field32_set 3515 (unit, &ma_state_entry, CURRENT_XCON_CCM_DEFECTf, 3516 0); 3517 soc_MA_STATEm_field32_set 3518 (unit, &ma_state_entry, CURRENT_ERROR_CCM_DEFECTf, 3519 0); 3520 soc_MA_STATEm_field32_set 3521 (unit, &ma_state_entry, STICKY_ERROR_CCM_DEFECTf, 3522 0); 3523 soc_MA_STATEm_field32_set 3524 (unit, &ma_state_entry, ERROR_CCM_DEFECT_TIMESTAMPf, 3525 0); 3526 soc_MA_STATEm_field32_set 3527 (unit, &ma_state_entry, ERROR_CCM_DEFECT_RECEIVE_CCMf, 3528 0); 3529 rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, h_data_p->group_index, 3530 &ma_state_entry); 3531 if (BCM_FAILURE(rv)) { 3532 LOG_ERROR(BSL_LS_BCM_OAM, 3533 (BSL_META_U(unit, 3534 "OAM Error: Group state (GID=%d) table write" 3535 " failed - %s.\n"), h_data_p->group_index, 3536 bcm_errmsg(rv))); 3537 return (rv); 3538 } 3539 } 3540 /* Clear the H/w index to logical index Mapping for RMEP */ 3541 oc->remote_endpoints[h_data_p->remote_index] = BCM_OAM_ENDPOINT_INVALID; 3542 3543 return (BCM_E_NONE); 3544 } 3545 3546 /* 3547 * Function: 3548 * _bcm_tr3_oam_local_endpoint_delete 3549 * Purpose: 3550 * Delete a local endpoint. 3551 * Parameters: 3552 * unit - (IN) BCM device number 3553 * h_data_p - (IN) Pointer to endpoint hash data 3554 * Retruns: 3555 * BCM_E_XXX 3556 */ 3557 STATIC int 3558 _bcm_tr3_oam_local_endpoint_delete(int unit, _bcm_oam_hash_data_t *h_data_p) 3559 { 3560 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 3561 uint32 l3_entry[SOC_MAX_MEM_WORDS];/* LMEP view table entry.*/ 3562 lmep_entry_t lmep_entry; /* Local endpoint table entry. */ 3563 int l3_index = -1; /* L3 table hardware index. */ 3564 uint8 mdl; /* Maintenance domain level. */ 3565 int rv; /* Operation return status. */ 3566 uint32 ma_base_index; /* Endpoint tbl base index. */ 3567 uint32 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0}; 3568 /* Endpoint Rx hardware index. */ 3569 uint32 count; /* No. of Rx indices freed */ 3570 /* successfully. */ 3571 int idx; /* Iterator variable. */ 3572 soc_mem_t mem; /* L3 entry memory */ 3573 #ifdef BCM_HURRICANE2_SUPPORT 3574 uint32 rval = 0; 3575 uint8 tx_disable = 0; 3576 #endif /* BCM_HURRICANE2_SUPPORT */ 3577 3578 if (NULL == h_data_p){ 3579 return (BCM_E_INTERNAL); 3580 } 3581 3582 /* Lock already taken by the calling routine. */ 3583 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 3584 3585 3586 if (1 == h_data_p->local_tx_enabled) { 3587 3588 /* Clear endpoint Tx config in hardware. */ 3589 sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t)); 3590 3591 /*HW WAR to fix the issue of wrong LMEP index being written 3592 while deleting and adding same MEP in a loop */ 3593 #ifdef BCM_HURRICANE2_SUPPORT 3594 rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 1, &tx_disable); 3595 if (BCM_FAILURE(rv)) { 3596 LOG_ERROR(BSL_LS_BCM_OAM, 3597 (BSL_META_U(unit, 3598 "OAM Error: in _bcm_oam_modify_oam_tx_control \n"))); 3599 return (rv); 3600 } 3601 #endif /* BCM_HURRICANE2_SUPPORT */ 3602 rv = WRITE_LMEPm(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index, 3603 &lmep_entry); 3604 3605 #ifdef BCM_HURRICANE2_SUPPORT 3606 if (tx_disable) { 3607 rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 0, &tx_disable); 3608 if (BCM_FAILURE(rv)) { 3609 LOG_ERROR(BSL_LS_BCM_OAM, 3610 (BSL_META_U(unit, 3611 "OAM Error: in _bcm_oam_modify_oam_tx_control \n"))); 3612 return (rv); 3613 } 3614 } 3615 #endif /* BCM_HURRICANE2_SUPPORT */ 3616 if (BCM_FAILURE(rv)) { 3617 LOG_ERROR(BSL_LS_BCM_OAM, 3618 (BSL_META_U(unit, 3619 "OAM Error: LMEP table write (EP=%d)" 3620 " failed - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 3621 return (rv); 3622 } 3623 3624 /* Return ID back to free LMEP ID pool. */ 3625 BCM_IF_ERROR_RETURN 3626 (shr_idxres_list_free(oc->lmep_pool, h_data_p->local_tx_index)); 3627 } 3628 3629 if (1 == h_data_p->local_rx_enabled) { 3630 3631 /* If LM DM is enabled, delete FP entries created for the same */ 3632 if ( h_data_p->flags & 3633 (BCM_OAM_ENDPOINT_LOSS_MEASUREMENT | 3634 BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) ) { 3635 rv = _bcm_tr3_oam_loss_delay_measurement_delete(unit, oc, h_data_p); 3636 if (BCM_FAILURE(rv)) { 3637 LOG_ERROR(BSL_LS_BCM_OAM, 3638 (BSL_META_U(unit, 3639 "OAM Error: LM DM delete failed (EP=%d)" 3640 "- %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 3641 return (rv); 3642 } 3643 } 3644 3645 3646 /* Delete OAM opcode profile entry for this endpoint. */ 3647 rv = soc_profile_mem_delete(unit, &oc->oam_opcode_control_profile, 3648 h_data_p->profile_index); 3649 3650 if (BCM_FAILURE(rv)) { 3651 LOG_ERROR(BSL_LS_BCM_OAM, 3652 (BSL_META_U(unit, 3653 "OAM Error: Profile table update error (idx=%d)" 3654 "- %s.\n"), h_data_p->profile_index, bcm_errmsg(rv))); 3655 return (rv); 3656 } 3657 3658 /* Initialize L3 entry buffer. */ 3659 sal_memset(&l3_entry, 0, sizeof(l3_entry)); 3660 3661 rv = _bcm_tr3_oam_find_lmep(unit, h_data_p, &l3_index, l3_entry); 3662 if (BCM_SUCCESS(rv)) { 3663 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 3664 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 3665 mem = L3_ENTRY_IPV4_UNICASTm; 3666 } else { 3667 mem = L3_ENTRY_1m; 3668 } 3669 /* Endpoint found, get MDL bitmap value. */ 3670 mdl = soc_mem_field32_get(unit, mem, &l3_entry, 3671 LMEP__MDL_BITMAPf); 3672 3673 /* Clear the MDL bit for this endpoint. */ 3674 mdl &= ~(1 << h_data_p->level); 3675 3676 /* Take L3 module protection mutex to block any updates. */ 3677 L3_LOCK(unit); 3678 3679 if (0 != mdl) { 3680 /* Valid endpoints exist for other MDLs at this index. */ 3681 rv = soc_mem_field32_modify(unit, mem, l3_index, 3682 LMEP__MDL_BITMAPf, mdl); 3683 } else { 3684 rv = soc_mem_delete_index(unit, mem, MEM_BLOCK_ALL, 3685 l3_index); 3686 } 3687 3688 L3_UNLOCK(unit); 3689 3690 if (BCM_FAILURE(rv)) { 3691 LOG_ERROR(BSL_LS_BCM_OAM, 3692 (BSL_META_U(unit, 3693 "OAM Error: LMEP view update (EP=%d) -" 3694 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 3695 return (rv); 3696 } 3697 3698 /* This is the last Rx endpoint in this OAM group. */ 3699 if (0 == mdl) { 3700 ma_base_index = soc_mem_field32_get(unit, mem, &l3_entry, 3701 LMEP__MA_BASE_PTRf); 3702 /* Return Rx indices to free pool. */ 3703 for (idx = 0; idx < (1 << _BCM_OAM_EP_LEVEL_BIT_COUNT); idx++) { 3704 rx_index[idx] = (ma_base_index << _BCM_OAM_EP_LEVEL_BIT_COUNT) 3705 + idx; 3706 } 3707 3708 rv = shr_idxres_list_free_set(oc->ma_idx_pool, 8, 3709 (shr_idxres_element_t *) rx_index, 3710 (shr_idxres_element_t *) &count); 3711 if (BCM_FAILURE(rv) || (8 != count)) { 3712 LOG_ERROR(BSL_LS_BCM_OAM, 3713 (BSL_META_U(unit, 3714 "OAM Error: Rx index list free (EP=%d)" 3715 " (count=%d).\n"), h_data_p->ep_id, count)); 3716 return (rv); 3717 } 3718 } 3719 } else if (BCM_FAILURE(rv) && (oc->init)) { 3720 LOG_ERROR(BSL_LS_BCM_OAM, 3721 (BSL_META_U(unit, 3722 "OAM Error: LMEP table write (EP=%d) -" 3723 " %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 3724 return (rv); 3725 } 3726 } 3727 3728 /*SDK-147457:HW WAR to fix the issue of wrong LMEP index being written 3729 while deleting and adding same MEP in a loop */ 3730 #ifdef BCM_HURRICANE2_SUPPORT 3731 sal_usleep(3400); 3732 #endif /* BCM_HURRICANE2_SUPPORT */ 3733 3734 return (BCM_E_NONE); 3735 } 3736 3737 3738 /* 3739 * Function: 3740 * _bcm_tr3_oam_endpoint_destroy 3741 * Purpose: 3742 * Delete an endpoint and free all its allocated resources. 3743 * Parameters: 3744 * unit - (IN) BCM device number 3745 * ep_id - (IN) Endpoint ID value. 3746 * Retruns: 3747 * BCM_E_XXX 3748 */ 3749 STATIC int 3750 _bcm_tr3_oam_endpoint_destroy(int unit, 3751 bcm_oam_endpoint_t ep_id) 3752 { 3753 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 3754 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint data. */ 3755 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 3756 bcm_oam_endpoint_info_t ep_info; /* Endpoint information. */ 3757 _bcm_oam_hash_data_t h_data; /* Pointer to endpoint data. */ 3758 int rv; /* Operation return status. */ 3759 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 3760 uint16 reply_len; 3761 bcm_oam_endpoint_t bhh_pool_ep_id; 3762 #endif 3763 3764 /* Lock already taken by the calling routine. */ 3765 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 3766 3767 /* Get the hash data pointer. */ 3768 h_data_p = &oc->oam_hash_data[ep_id]; 3769 if(0 == h_data_p->in_use){ 3770 return BCM_E_NOT_FOUND; 3771 } 3772 3773 if(bcmOAMEndpointTypeEthernet == h_data_p->type) 3774 { 3775 /* Remove endpoint for group's endpoint list. */ 3776 rv = _bcm_oam_group_ep_list_remove(unit, h_data_p->group_index, 3777 h_data_p->ep_id); 3778 if (BCM_FAILURE(rv)) { 3779 LOG_ERROR(BSL_LS_BCM_OAM, 3780 (BSL_META_U(unit, 3781 "OAM Error: Remove from group list (EP=%d) -" 3782 " %s.\n"), ep_id, bcm_errmsg(rv))); 3783 return (rv); 3784 } 3785 3786 if (h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE) { 3787 BCM_IF_ERROR_RETURN 3788 (_bcm_tr3_oam_remote_endpoint_delete(unit, h_data_p)); 3789 3790 } else { 3791 BCM_IF_ERROR_RETURN 3792 (_bcm_tr3_oam_local_endpoint_delete(unit, h_data_p)); 3793 } 3794 3795 /* Return ID back to free MEP ID pool.*/ 3796 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->mep_pool, ep_id)); 3797 3798 /* Initialize endpoint info structure. */ 3799 bcm_oam_endpoint_info_t_init(&ep_info); 3800 3801 /* Set up endpoint information for key construction. */ 3802 ep_info.group = h_data_p->group_index; 3803 ep_info.name = h_data_p->name; 3804 ep_info.gport = h_data_p->gport; 3805 ep_info.level = h_data_p->level; 3806 ep_info.vlan = h_data_p->vlan; 3807 3808 /* Construct hash key for lookup + delete operation. */ 3809 _bcm_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key); 3810 3811 /* Remove entry from hash table. */ 3812 BCM_IF_ERROR_RETURN(shr_htb_find(oc->ma_mep_htbl, hash_key, 3813 (shr_htb_data_t *)&h_data, 3814 1)); 3815 3816 /* Clear the hash data memory previously occupied by this endpoint. */ 3817 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 3818 } 3819 /* 3820 * BHH specific 3821 */ 3822 else if (soc_feature(unit, soc_feature_bhh) && 3823 ((bcmOAMEndpointTypeBHHMPLS == h_data_p->type) || 3824 (bcmOAMEndpointTypeBHHMPLSVccv == h_data_p->type))) { 3825 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 3826 3827 if (h_data_p->is_remote) { 3828 /* 3829 * BHH uses same index for local and remote. So, delete always goes through 3830 * local endpoint destory 3831 */ 3832 return (BCM_E_NONE); 3833 } else { 3834 3835 bhh_pool_ep_id = BCM_OAM_BHH_GET_UKERNEL_EP(ep_id); 3836 3837 /* Delete BHH Session in HW. BCM_E_NOT_FOUND is not an error when 3838 switch is re-initializing as entry would have been already 3839 deleted by respective module init. */ 3840 rv = _bcm_tr3_oam_bhh_session_hw_delete(unit, h_data_p); 3841 if (BCM_FAILURE(rv) && rv != BCM_E_NOT_FOUND) { 3842 LOG_ERROR(BSL_LS_BCM_OAM, 3843 (BSL_META_U(unit, 3844 "OAM Error: bhh_session_hw_delete failled " 3845 "(EP=%d) - %s.\n"), ep_id, bcm_errmsg(rv))); 3846 return (rv); 3847 } 3848 3849 /* Send BHH Session Delete message to uC. Error response is not an 3850 during switch re-init as uKernel is reloaded and its state is 3851 cleared before oam init. As such endpoint wont exist during oam init*/ 3852 _bcm_tr3_oam_bhh_msg_send_receive(unit, 3853 MOS_MSG_SUBCLASS_BHH_SESS_DELETE, 3854 (int)bhh_pool_ep_id, 0, 3855 MOS_MSG_SUBCLASS_BHH_SESS_DELETE_REPLY, 3856 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 3857 3858 h_data_p->in_use = 0; 3859 3860 /* Remove endpoint for group's endpoint list. */ 3861 rv = _bcm_oam_group_ep_list_remove(unit, h_data_p->group_index, 3862 h_data_p->ep_id); 3863 if (BCM_FAILURE(rv)) { 3864 LOG_ERROR(BSL_LS_BCM_OAM, 3865 (BSL_META_U(unit, 3866 "OAM Error: Remove from group list (EP=%d) -" 3867 " %s.\n"), ep_id, bcm_errmsg(rv))); 3868 return (rv); 3869 } 3870 3871 /* Return ID back to free MEP ID pool.*/ 3872 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_id)); 3873 } 3874 #else 3875 return (BCM_E_UNAVAIL); 3876 #endif /* INCLUDE_BHH */ 3877 } 3878 else { 3879 return (BCM_E_PARAM); 3880 } 3881 3882 return (BCM_E_NONE); 3883 } 3884 3885 /* 3886 * Function: 3887 * _bcm_tr3_oam_group_endpoints_destroy 3888 * Purpose: 3889 * Delete all endpoints associated with a group and free all 3890 * resources allocated by these endpoints. 3891 * Parameters: 3892 * unit - (IN) BCM device number 3893 * g_info_p - (IN) Pointer to group information 3894 * Retruns: 3895 * BCM_E_XXX 3896 */ 3897 STATIC int 3898 _bcm_tr3_oam_group_endpoints_destroy(int unit, 3899 _bcm_oam_group_data_t *g_info_p) 3900 { 3901 bcm_oam_endpoint_t ep_id; /* Endpoint ID. */ 3902 _bcm_oam_ep_list_t *cur; /* Pointer to endpoint list node. */ 3903 int rv; /* Operation return status. */ 3904 3905 if (NULL == g_info_p) { 3906 return (BCM_E_INTERNAL); 3907 } 3908 3909 /* Get the endpoint list head pointer. */ 3910 cur = *(g_info_p->ep_list); 3911 if (NULL == cur) { 3912 LOG_DEBUG(BSL_LS_BCM_OAM, 3913 (BSL_META_U(unit, 3914 "OAM Info: No endpoints in group.\n"))); 3915 return (BCM_E_NONE); 3916 } 3917 3918 while (NULL != cur) { 3919 ep_id = cur->ep_data_p->ep_id; 3920 3921 LOG_DEBUG(BSL_LS_BCM_OAM, 3922 (BSL_META_U(unit, 3923 "OAM Info: GID=%d EP:%d.\n"), 3924 cur->ep_data_p->group_index, ep_id)); 3925 3926 cur = cur->next; 3927 3928 rv = _bcm_tr3_oam_endpoint_destroy(unit, ep_id); 3929 if (BCM_FAILURE(rv)) { 3930 LOG_ERROR(BSL_LS_BCM_OAM, 3931 (BSL_META_U(unit, 3932 "OAM Error: Endpoint destroy (EP=%d) - " 3933 "%s.\n"), ep_id, bcm_errmsg(rv))); 3934 return (rv); 3935 } 3936 } 3937 3938 return (BCM_E_NONE); 3939 } 3940 3941 /* 3942 * Function: 3943 * _bcm_tr3_oam_endpoint_gport_resolve 3944 * Purpose: 3945 * Resolve an endpoint GPORT value to SGLP and DGLP value. 3946 * Parameters: 3947 * unit - (IN) BCM device number 3948 * ep_info_p - (IN) Pointer to endpoint information. 3949 * src_glp - (IN/OUT) Pointer to source generic logical port value. 3950 * dst_glp - (IN/OUT) Pointer to destination generic logical port value. 3951 * tx_gport - (OUT) Gport on which PDUs need to be sent 3952 * Retruns: 3953 * BCM_E_XXX 3954 */ 3955 STATIC int 3956 _bcm_tr3_oam_endpoint_gport_resolve(int unit, bcm_oam_endpoint_info_t *ep_info_p, 3957 uint32 *src_glp, uint32 *dst_glp, 3958 bcm_trunk_t *trunk_id, bcm_gport_t *tx_gport) 3959 { 3960 bcm_module_t module_id; /* Module ID */ 3961 bcm_port_t port_id; /* Port ID. */ 3962 int local_id; /* Hardware ID. */ 3963 int tx_enabled = 0; /* CCM Tx enabled. */ 3964 bcm_trunk_info_t trunk_info; /* Trunk information. */ 3965 bcm_trunk_member_t *member_array = NULL; /* Trunk member array. */ 3966 bcm_trunk_t tmp_trunk_id; /* Temp Trunk id */ 3967 int member_count = 0; /* Trunk Member count. */ 3968 int rv; /* Return status. */ 3969 uint8 glp_valid = 0; /* Logical port valid. */ 3970 3971 /* Get Trunk ID or (Modid + Port) value from Gport */ 3972 BCM_IF_ERROR_RETURN 3973 (_bcm_esw_gport_resolve(unit, ep_info_p->gport, &module_id, 3974 &port_id, trunk_id, &local_id)); 3975 3976 /* Set CCM endpoint Tx status only for local endpoints. */ 3977 if (!(ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE)) { 3978 tx_enabled 3979 = (ep_info_p->ccm_period 3980 != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) ? 1 : 0; 3981 } 3982 3983 /* 3984 * If Gport is Trunk type, _bcm_esw_gport_resolve() 3985 * sets trunk_id. Using Trunk ID, get Dst Modid and Port value. 3986 */ 3987 if (BCM_GPORT_IS_TRUNK(ep_info_p->gport) && 3988 (BCM_TRUNK_INVALID == *trunk_id)) { 3989 /* Has to be a valid Trunk. */ 3990 return (BCM_E_PARAM); 3991 } 3992 3993 if (BCM_TRUNK_INVALID != *trunk_id) { 3994 3995 /* 3996 * CCM Tx is enabled on a trunk member port. 3997 * trunk_index value is required to derive the Modid and Port info. 3998 */ 3999 if (1 == tx_enabled 4000 && _BCM_OAM_INVALID_INDEX == ep_info_p->trunk_index) { 4001 /* Invalid Trunk member index passed. */ 4002 return (BCM_E_PORT); 4003 } 4004 4005 /* Construct Hw SGLP value. */ 4006 _BCM_TR3_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 1, *trunk_id, 4007 *src_glp); 4008 4009 /* Get count of ports in this trunk. */ 4010 BCM_IF_ERROR_RETURN 4011 (bcm_esw_trunk_get(unit, *trunk_id, NULL, 0, NULL, &member_count)); 4012 if (0 == member_count) { 4013 /* No members have been added to the trunk group yet */ 4014 return (BCM_E_PARAM); 4015 } 4016 4017 _BCM_OAM_ALLOC(member_array, bcm_trunk_member_t, 4018 sizeof(bcm_trunk_member_t) * member_count, "Trunk info"); 4019 if (NULL == member_array) { 4020 return (BCM_E_MEMORY); 4021 } 4022 4023 /* Get Trunk Info for the Trunk ID. */ 4024 rv = bcm_esw_trunk_get(unit, *trunk_id, &trunk_info, member_count, 4025 member_array, &member_count); 4026 if (BCM_FAILURE(rv)) { 4027 sal_free(member_array); 4028 return (rv); 4029 } 4030 4031 /* Check if the input trunk_index is valid. */ 4032 if (ep_info_p->trunk_index >= member_count) { 4033 sal_free(member_array); 4034 return (BCM_E_PARAM); 4035 } 4036 4037 /* Get the Modid and Port value using Trunk Index value. */ 4038 rv = _bcm_esw_gport_resolve 4039 (unit, member_array[ep_info_p->trunk_index].gport, 4040 &module_id, &port_id, &tmp_trunk_id, &local_id); 4041 if (BCM_FAILURE(rv)) { 4042 sal_free(member_array); 4043 return (rv); 4044 } 4045 4046 sal_free(member_array); 4047 4048 /* Construct Hw DGLP value. */ 4049 _BCM_TR3_OAM_MOD_PORT_TO_DGLP(unit, module_id, port_id, 0, -1, 4050 *dst_glp); 4051 *tx_gport = member_array[ep_info_p->trunk_index].gport; 4052 glp_valid = 1; 4053 } 4054 4055 /* 4056 * Application can resolve the trunk and pass the desginated 4057 * port as Gport value. Check if the Gport belongs to a trunk. 4058 */ 4059 if ((BCM_TRUNK_INVALID == *trunk_id) 4060 && (BCM_GPORT_IS_MODPORT(ep_info_p->gport) 4061 || BCM_GPORT_IS_LOCAL(ep_info_p->gport))) { 4062 4063 /* When Gport is ModPort or Port type, _bcm_esw_gport_resolve() 4064 * returns Modid and Port value. Use these values to make the DGLP 4065 * value. 4066 */ 4067 _BCM_TR3_OAM_MOD_PORT_TO_DGLP(unit, module_id, port_id, 0, -1, 4068 *dst_glp); 4069 4070 /* Use the Modid, Port value and determine if the port 4071 * belongs to a Trunk. 4072 */ 4073 rv = bcm_esw_trunk_find(unit, module_id, port_id, trunk_id); 4074 if (BCM_SUCCESS(rv)) { 4075 /* 4076 * Port is member of a valid trunk. 4077 * Now create the SGLP value from Trunk ID. 4078 */ 4079 _BCM_TR3_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 1, *trunk_id, 4080 *src_glp); 4081 4082 } else { 4083 /* Port not a member of trunk. Construct SGLP */ 4084 _BCM_TR3_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1, 4085 *src_glp); 4086 } 4087 glp_valid = 1; 4088 BCM_GPORT_MODPORT_SET(*tx_gport, module_id, port_id); 4089 } 4090 4091 if (BCM_GPORT_IS_MIM_PORT(ep_info_p->gport) || 4092 BCM_GPORT_IS_MPLS_PORT(ep_info_p->gport)) { 4093 4094 _BCM_TR3_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1, *src_glp); 4095 _BCM_TR3_OAM_MOD_PORT_TO_DGLP(unit, module_id, port_id, 0, -1, *dst_glp); 4096 BCM_GPORT_MODPORT_SET(*tx_gport, module_id, port_id); 4097 glp_valid = 1; 4098 } 4099 4100 /* 4101 * At this point, both src_glp and dst_glp should be valid. 4102 * Gport types other than TRUNK, MODPORT or LOCAL are not valid. 4103 */ 4104 if (0 == glp_valid) { 4105 return (BCM_E_PORT); 4106 } 4107 4108 return (BCM_E_NONE); 4109 } 4110 4111 /* 4112 * Function: 4113 * _bcm_tr3_oam_mepid_validate 4114 * Purpose: 4115 * Validate an endpoint MEP id. 4116 * Parameters: 4117 * unit - (IN) BCM device number 4118 * ep_info_p - (IN) Pointer to endpoint information. 4119 * Retruns: 4120 * BCM_E_XXX 4121 */ 4122 STATIC int 4123 _bcm_tr3_oam_mepid_validate(int unit, 4124 bcm_oam_endpoint_info_t *ep_info_p) 4125 { 4126 _bcm_oam_control_t *oc; 4127 _bcm_oam_group_data_t *group_p; /* Pointer to group list. */ 4128 _bcm_oam_ep_list_t *cur; /* Current head node pointer. */ 4129 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 4130 4131 /* Get OAM control structure. */ 4132 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 4133 4134 /* Get the group memory pointer. */ 4135 group_p = &oc->group_info[ep_info_p->group]; 4136 4137 if (1 != group_p->in_use) { 4138 return BCM_E_NONE; 4139 } 4140 cur = *group_p->ep_list; 4141 4142 /* Traverse the list and delete the matching node. */ 4143 while (NULL != cur) { 4144 h_data_p = cur->ep_data_p; 4145 if (NULL == h_data_p) { 4146 LOG_ERROR(BSL_LS_BCM_OAM, 4147 (BSL_META_U(unit, 4148 "OAM Error: Hash data is empty\n"))); 4149 return (BCM_E_INTERNAL); 4150 } 4151 if (ep_info_p->name == h_data_p->name) { 4152 if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE) && 4153 (cur->ep_data_p->ep_id == ep_info_p->id)) { 4154 } else { 4155 return BCM_E_PARAM; 4156 } 4157 } 4158 cur = cur->next; 4159 } 4160 return (BCM_E_NONE); 4161 } 4162 4163 /* 4164 * Function: 4165 * _bcm_tr3_oam_endpoint_params_validate 4166 * Purpose: 4167 * Validate an endpoint parameters. 4168 * Parameters: 4169 * unit - (IN) BCM device number 4170 * oc - (IN) Pointer to OAM control structure. 4171 * hash_key - (IN) Pointer to endpoint hash key value. 4172 * ep_info_p - (IN) Pointer to endpoint information. 4173 * Retruns: 4174 * BCM_E_XXX 4175 */ 4176 STATIC int 4177 _bcm_tr3_oam_endpoint_params_validate(int unit, 4178 _bcm_oam_control_t *oc, 4179 _bcm_oam_hash_key_t *hash_key, 4180 bcm_oam_endpoint_info_t *ep_info_p) 4181 { 4182 int rv; /* Operation return status. */ 4183 _bcm_oam_hash_data_t h_stored_data; 4184 4185 4186 LOG_DEBUG(BSL_LS_BCM_OAM, 4187 (BSL_META_U(unit, 4188 "OAM Info: _bcm_tr3_oam_endpoint_params_validate.\n"))); 4189 4190 /* Endpoint must be 802.1ag/Ethernet OAM type. */ 4191 if ((bcmOAMEndpointTypeEthernet != ep_info_p->type) 4192 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 4193 && /* BHH/Y.1731 OAM type */ 4194 (bcmOAMEndpointTypeBHHMPLS != ep_info_p->type) && 4195 (bcmOAMEndpointTypeBHHMPLSVccv != ep_info_p->type) 4196 #endif /* INCLUDE_BHH */ 4197 ) 4198 { 4199 /* Other OAM types are not supported, return error. */ 4200 return (BCM_E_UNAVAIL); 4201 } 4202 4203 /* Supported MDL level is 0 - 7. */ 4204 if ((ep_info_p->level < 0) || (ep_info_p->level > _BCM_OAM_EP_LEVEL_MAX)) { 4205 LOG_ERROR(BSL_LS_BCM_OAM, 4206 (BSL_META_U(unit, 4207 "OAM Error: EP Level should be in the range(0-%d).\n"), 4208 _BCM_OAM_EP_LEVEL_MAX )); 4209 return (BCM_E_PARAM); 4210 } 4211 4212 /* Supported MEPID Name range is 1 - 8191, Skipping range check for MIP */ 4213 if (((ep_info_p->name < _BCM_OAM_EP_NAME_MIN) 4214 || (ep_info_p->name > _BCM_OAM_EP_NAME_MAX)) && 4215 !(ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE)) { 4216 LOG_ERROR(BSL_LS_BCM_OAM, 4217 (BSL_META_U(unit, 4218 "OAM Error: MEP Name should be in the range(%d-%d).\n"), 4219 _BCM_OAM_EP_NAME_MIN, _BCM_OAM_EP_NAME_MAX)); 4220 return (BCM_E_PARAM); 4221 } 4222 4223 /* Check if any unsupported flags are passed the return BCM_E_PARAM */ 4224 if (ep_info_p->flags & BCM_OAM_ENDPOINT_CCM_COPYFIRSTTOCPU) { 4225 LOG_ERROR(BSL_LS_BCM_OAM, 4226 (BSL_META_U(unit, 4227 "OAM Error: Unsupported flag\n"))); 4228 return (BCM_E_PARAM); 4229 } 4230 4231 /* 4232 * Check and return error if invalid flag bits are set for remote 4233 * endpoint. 4234 */ 4235 if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE) 4236 && (ep_info_p->flags & _BCM_OAM_REMOTE_EP_INVALID_FLAGS_MASK)) { 4237 4238 return (BCM_E_PARAM); 4239 4240 } 4241 /* 4242 * Check and return error if MEPID is not unique within the group 4243 */ 4244 if(_bcm_tr3_oam_mepid_validate(unit, ep_info_p)) { 4245 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 4246 "OAM Error: MEPID:%x passed is not unique in group %x\n"), 4247 ep_info_p->name, ep_info_p->group)); 4248 return (BCM_E_EXISTS); 4249 } 4250 4251 /* For replace operation, endpoint ID is required. */ 4252 if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE) 4253 && !(ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID)) { 4254 4255 return (BCM_E_PARAM); 4256 4257 } 4258 4259 /* Validate endpoint index value. */ 4260 if (ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID) { 4261 4262 _BCM_OAM_EP_INDEX_VALIDATE(ep_info_p->id); 4263 } 4264 4265 /* MIP's are not created with non-zero ccm period */ 4266 if ((ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) && 4267 (ep_info_p->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED)) { 4268 return (BCM_E_PARAM); 4269 } 4270 4271 /* Validate endpoint group id. */ 4272 _BCM_OAM_GROUP_INDEX_VALIDATE(ep_info_p->group); 4273 4274 rv = shr_idxres_list_elem_state(oc->group_pool, ep_info_p->group); 4275 if (BCM_E_EXISTS != rv) { 4276 LOG_ERROR(BSL_LS_BCM_OAM, 4277 (BSL_META_U(unit, 4278 "OAM Error: Group (GID:%d) does not exist.\n"), 4279 ep_info_p->group)); 4280 return (BCM_E_PARAM); 4281 } 4282 4283 if(soc_feature(unit, soc_feature_bhh)) { 4284 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 4285 /* 4286 * BHH can have multiple LSPs/endpoint on same port/MDL 4287 * BHH does not have h/w support. So, return here 4288 */ 4289 if ((bcmOAMEndpointTypeBHHMPLS == ep_info_p->type) || 4290 (bcmOAMEndpointTypeBHHMPLSVccv == ep_info_p->type)) { 4291 return (BCM_E_NONE); 4292 } 4293 #endif 4294 } 4295 4296 #if defined(KEY_PRINT) 4297 _bcm_oam_hash_key_print(hash_key); 4298 #endif 4299 4300 /* 4301 * Lookup using hash key value. 4302 * Last param value '0' specifies keep the match entry. 4303 * Value '1' would mean remove the entry from the table. 4304 * Matched Params: 4305 * Group Name + Group ID + Endpoint Name + VLAN + MDL + Gport. 4306 */ 4307 rv = shr_htb_find(oc->ma_mep_htbl, *hash_key, 4308 (shr_htb_data_t *)&h_stored_data, 0); 4309 if (BCM_SUCCESS(rv) 4310 && !(ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE)) { 4311 4312 LOG_ERROR(BSL_LS_BCM_OAM, 4313 (BSL_META_U(unit, 4314 "OAM Error: Endpoint ID=%d %s.\n"), 4315 ep_info_p->id, bcm_errmsg(BCM_E_EXISTS))); 4316 4317 /* Endpoint must not be in use expect for Replace operation. */ 4318 return (BCM_E_EXISTS); 4319 4320 } else { 4321 4322 LOG_DEBUG(BSL_LS_BCM_OAM, 4323 (BSL_META_U(unit, 4324 "OAM Info: Endpoint ID=%d Available. %s.\n"), 4325 ep_info_p->id, bcm_errmsg(rv))); 4326 4327 } 4328 4329 4330 4331 return (BCM_E_NONE); 4332 } 4333 4334 /* 4335 * Function: 4336 * _bcm_tr3_oam_fp_entry_id_allocate 4337 * Purpose: 4338 * Allocate FP entry Id for Loss and Delay measurement 4339 * Parameters: 4340 * unit - (IN) BCM device number. 4341 * fp_group - (IN) Group Id under which the FP entry is created. 4342 * prio - (IN) Prioroty of FP Entry to be created. 4343 * fp_entry_id - (OUT) Created FP Entry Id 4344 * Retruns: 4345 * BCM_E_XXX 4346 */ 4347 STATIC int 4348 _bcm_tr3_oam_fp_entry_id_allocate(int unit, bcm_field_group_t fp_group, 4349 int prio, bcm_field_entry_t *fp_entry_id) { 4350 4351 int rv = 0; 4352 4353 if (NULL == fp_entry_id){ 4354 return (BCM_E_INTERNAL); 4355 } 4356 4357 rv = bcm_esw_field_entry_create(unit, fp_group, fp_entry_id); 4358 if (BCM_FAILURE(rv)) { 4359 LOG_ERROR(BSL_LS_BCM_OAM, 4360 (BSL_META_U(unit, 4361 "OAM Error: FP Entry Tx creation (tx), %s.\n"), 4362 bcm_errmsg(rv))); 4363 return (rv); 4364 } 4365 4366 rv = bcm_esw_field_entry_prio_set(unit, *fp_entry_id, prio); 4367 if (BCM_FAILURE(rv)) { 4368 LOG_ERROR(BSL_LS_BCM_OAM, 4369 (BSL_META_U(unit, 4370 "OAM Error: FP Entry Tx Prio Set (tx), %s.\n"), 4371 bcm_errmsg(rv))); 4372 return (rv); 4373 } 4374 4375 return (rv); 4376 4377 } 4378 4379 /* 4380 * Function: 4381 * _bcm_tr3_oam_fp_entry_action_add 4382 * Purpose: 4383 * Adds actions to the fp entry 4384 * Parameters: 4385 * unit - (IN) BCM device number 4386 * hash_data - (IN) Pointer to endpoint hash data. 4387 * fp_entry_id - (IN) FP Entry id 4388 * isTx - (IN) Whether entry matches tx or rx flow 4389 * Retruns: 4390 * BCM_E_XXX 4391 */ 4392 STATIC int 4393 _bcm_tr3_oam_fp_entry_action_add(int unit, _bcm_oam_hash_data_t *hash_data, 4394 bcm_field_entry_t fp_entry_id, uint8 isTx) { 4395 4396 int rv = 0; 4397 4398 if (NULL == hash_data){ 4399 return (BCM_E_INTERNAL); 4400 } 4401 4402 rv = bcm_esw_field_action_add(unit, fp_entry_id, 4403 bcmFieldActionOamLmepEnable, 1, 0); 4404 if (BCM_FAILURE(rv)) { 4405 LOG_ERROR(BSL_LS_BCM_OAM, 4406 (BSL_META_U(unit, 4407 "OAM Error: Adding action OamLmepEnable, EP=%d %s.\n"), 4408 hash_data->ep_id, bcm_errmsg(rv))); 4409 return (rv); 4410 } 4411 4412 rv = bcm_esw_field_action_add(unit, fp_entry_id, bcmFieldActionOamLmEnable, 4413 hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT? 1:0, 0); 4414 if (BCM_FAILURE(rv)) { 4415 LOG_ERROR(BSL_LS_BCM_OAM, 4416 (BSL_META_U(unit, 4417 "OAM Error: Adding action OamLmEnable, EP=%d %s.\n"), 4418 hash_data->ep_id, bcm_errmsg(rv))); 4419 return (rv); 4420 } 4421 4422 rv = bcm_esw_field_action_add(unit, fp_entry_id, bcmFieldActionOamDmEnable, 4423 hash_data->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT? 1:0, 0); 4424 if (BCM_FAILURE(rv)) { 4425 LOG_ERROR(BSL_LS_BCM_OAM, 4426 (BSL_META_U(unit, 4427 "OAM Error: Adding action OamDmEnable, EP=%d %s.\n"), 4428 hash_data->ep_id, bcm_errmsg(rv))); 4429 return (rv); 4430 } 4431 4432 if (hash_data->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT){ 4433 rv = bcm_esw_field_action_add(unit, fp_entry_id, 4434 bcmFieldActionOamDmTimeFormat, 4435 (hash_data->ts_format == bcmOAMTimestampFormatNTP ? 4436 BCM_FIELD_OAM_DM_TIME_FORMAT_NTP : 4437 BCM_FIELD_OAM_DM_TIME_FORMAT_IEEE1588), 0); 4438 if (BCM_FAILURE(rv)) { 4439 LOG_ERROR(BSL_LS_BCM_OAM, 4440 (BSL_META_U(unit, 4441 "OAM Error: Adding action DmTimeFormat, " 4442 "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 4443 return (rv); 4444 } 4445 } 4446 4447 rv = bcm_esw_field_action_add(unit, fp_entry_id, bcmFieldActionOamLmepMdl, 4448 hash_data->level, 0); 4449 if (BCM_FAILURE(rv)) { 4450 LOG_ERROR(BSL_LS_BCM_OAM, 4451 (BSL_META_U(unit, 4452 "OAM Error: Adding action LmepMdl (tx), EP=%d %s.\n"), 4453 hash_data->ep_id, bcm_errmsg(rv))); 4454 return (rv); 4455 } 4456 4457 rv = bcm_esw_field_action_add(unit, fp_entry_id, bcmFieldActionOamUpMep, 4458 hash_data->flags & BCM_OAM_ENDPOINT_UP_FACING? 1:0, 0); 4459 if (BCM_FAILURE(rv)) { 4460 LOG_ERROR(BSL_LS_BCM_OAM, 4461 (BSL_META_U(unit, 4462 "OAM Error: Adding action OamUpMep (tx), EP=%d %s.\n"), 4463 hash_data->ep_id, bcm_errmsg(rv))); 4464 return (rv); 4465 } 4466 4467 /* In the case of UP MEP Tx rule is actually Rx and vice versa */ 4468 rv = bcm_esw_field_action_add(unit, fp_entry_id, 4469 bcmFieldActionOamTx, isTx, 0); 4470 if (BCM_FAILURE(rv)) { 4471 LOG_ERROR(BSL_LS_BCM_OAM, 4472 (BSL_META_U(unit, 4473 "OAM Error: Adding action OamTx (tx), EP=%d %s.\n"), 4474 hash_data->ep_id, bcm_errmsg(rv))); 4475 return (rv); 4476 } 4477 4478 if (hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) 4479 { 4480 /* Assign LM counter and priority mapping table */ 4481 rv = bcm_esw_field_action_add(unit, fp_entry_id, 4482 bcmFieldActionOamLmBasePtr, hash_data->lm_counter_index, 0); 4483 if (BCM_FAILURE(rv)) { 4484 LOG_ERROR(BSL_LS_BCM_OAM, 4485 (BSL_META_U(unit, 4486 "OAM Error: Adding action OamUpMep (tx), " 4487 "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 4488 return (rv); 4489 } 4490 4491 rv = bcm_esw_field_action_add(unit, fp_entry_id, 4492 bcmFieldActionOamServicePriMappingPtr, hash_data->pri_map_index, 0); 4493 if (BCM_FAILURE(rv)) { 4494 LOG_ERROR(BSL_LS_BCM_OAM, 4495 (BSL_META_U(unit, 4496 "OAM Error: Adding action OamUpMep (tx), " 4497 "EP=%d %s.\n"), hash_data->pri_map_index, bcm_errmsg(rv))); 4498 return (rv); 4499 } 4500 4501 } 4502 4503 return (rv); 4504 4505 4506 } 4507 4508 /* 4509 * Function: 4510 * _bcm_tr3_oam_fp_trunk_create 4511 * Purpose: 4512 * Create FP Entry to match trunk memeber port from which 4513 * LM/DM packets generated by CPU will be transmitted. 4514 * Parameters: 4515 * unit - (IN) BCM device number 4516 * oc - (IN) Pointer to OAM control structure. 4517 * hash_data - (IN) Pointer to endpoint hash data. 4518 * Retruns: 4519 * BCM_E_XXX 4520 */ 4521 STATIC int 4522 _bcm_tr3_oam_fp_trunk_create(int unit, _bcm_oam_control_t *oc, 4523 _bcm_oam_hash_data_t *hash_data) { 4524 4525 int prio = 0; 4526 int rv= 0; 4527 bcm_field_entry_t fp_entry = -1; 4528 bcm_module_t modid = 0; 4529 bcm_port_t local_port; 4530 bcm_ip6_t mdl_data, mdl_mask; 4531 4532 if (NULL == oc || NULL == hash_data ){ 4533 return (BCM_E_INTERNAL); 4534 } 4535 4536 /* Group should already be created by now*/ 4537 if( oc->fp_glp_group == -1 ){ 4538 LOG_ERROR(BSL_LS_BCM_OAM, 4539 (BSL_META_U(unit, 4540 "OAM Error: FP Croup not present, EP=%d %s.\n"), 4541 hash_data->pri_map_index, bcm_errmsg(rv))); 4542 return (BCM_E_INTERNAL); 4543 } 4544 4545 /* Create fp entry */ 4546 /*******************/ 4547 /*Adding 1 to avoid hitting default Prio 0 at MAX_MDL*/ 4548 prio = (_BCM_OAM_MAX_MDL + 1) - hash_data->level; 4549 4550 rv = _bcm_tr3_oam_fp_entry_id_allocate(unit, oc->fp_glp_group, prio, 4551 &(hash_data->fp_entry_trunk[0])); 4552 if (BCM_FAILURE(rv)) { 4553 LOG_ERROR(BSL_LS_BCM_OAM, 4554 (BSL_META_U(unit, 4555 "OAM Error: FP Trunk Entry allocate (tx), EP=%d %s\n"), 4556 hash_data->ep_id, bcm_errmsg(rv))); 4557 return (rv); 4558 } 4559 fp_entry = hash_data->fp_entry_trunk[0]; 4560 4561 /* Add Qulaifiers */ 4562 /******************/ 4563 rv = bcm_esw_field_qualify_OuterVlanId(unit, fp_entry, hash_data->vlan, 4564 BCM_FIELD_EXACT_MATCH_MASK); 4565 if (BCM_FAILURE(rv)) { 4566 LOG_ERROR(BSL_LS_BCM_OAM, 4567 (BSL_META_U(unit, 4568 "OAM Error: Qualifying OuterVlanId (tx), EP=%d %s.\n"), 4569 hash_data->ep_id, bcm_errmsg(rv))); 4570 return (rv); 4571 } 4572 4573 /* hash_data->dglp already contains resolved trunk index port, use it to get 4574 * port and module for qualifying LM/DM packet transmitted from CPU */ 4575 LOG_VERBOSE(BSL_LS_BCM_OAM, 4576 (BSL_META_U(unit, 4577 "OAM - dglp %d.\n"), 4578 hash_data->dglp)); 4579 local_port = _BCM_OAM_GLP_PORT_GET(unit, hash_data->dglp); 4580 modid = _BCM_OAM_DGLP_MODULE_ID_GET(hash_data->dglp); 4581 LOG_VERBOSE(BSL_LS_BCM_OAM, 4582 (BSL_META_U(unit, 4583 "OAM - Local Port %d, modid %d.\n"), 4584 local_port, modid)); 4585 4586 rv = bcm_esw_field_qualify_DstPort(unit, fp_entry, modid, 4587 BCM_FIELD_EXACT_MATCH_MASK, local_port, BCM_FIELD_EXACT_MATCH_MASK); 4588 if (BCM_FAILURE(rv)) { 4589 LOG_ERROR(BSL_LS_BCM_OAM, 4590 (BSL_META_U(unit, 4591 "OAM Error: Qualifying DstPort (tx), EP=%d %s.\n"), 4592 hash_data->ep_id, bcm_errmsg(rv))); 4593 return (rv); 4594 } 4595 4596 rv = bcm_esw_field_qualify_EtherType(unit, fp_entry, _BCM_OAM_ETHER_TYPE, 4597 BCM_FIELD_EXACT_MATCH_MASK); 4598 if (BCM_FAILURE(rv)) { 4599 LOG_ERROR(BSL_LS_BCM_OAM, 4600 (BSL_META_U(unit, 4601 "OAM Error: EtherType (tx), EP=%d %s.\n"), 4602 hash_data->ep_id, bcm_errmsg(rv))); 4603 return (rv); 4604 } 4605 4606 sal_memset(&mdl_data, 0, sizeof(bcm_ip6_t)); 4607 sal_memset(&mdl_mask, 0, sizeof(bcm_ip6_t)); 4608 mdl_data[0] = (hash_data->level << 5); 4609 mdl_mask[0] = 0xE0; 4610 4611 rv = bcm_esw_field_qualify_DstIp6(unit, fp_entry, mdl_data, mdl_mask); 4612 if (BCM_FAILURE(rv)) { 4613 LOG_ERROR(BSL_LS_BCM_OAM, 4614 (BSL_META_U(unit, 4615 "OAM Error: Qualifying MDL (tx), EP=%d %s.\n"), 4616 hash_data->ep_id, bcm_errmsg(rv))); 4617 return (rv); 4618 } 4619 4620 /* Add Action */ 4621 /**************/ 4622 rv = _bcm_tr3_oam_fp_entry_action_add(unit, hash_data, fp_entry, 1); 4623 if (BCM_FAILURE(rv)) { 4624 LOG_ERROR(BSL_LS_BCM_OAM, 4625 (BSL_META_U(unit, 4626 "OAM Error: Adding action (tx), EP=%d %s.\n"), 4627 hash_data->ep_id, bcm_errmsg(rv))); 4628 return (rv); 4629 } 4630 4631 return (rv); 4632 4633 } 4634 4635 /* 4636 * Function: 4637 * _bcm_tr3_oam_fp_create 4638 * Purpose: 4639 * Create IFP entry for LOSS & DELAY Measurement 4640 * Parameters: 4641 * unit - (IN) BCM device number 4642 * oc - (IN-OUT) Pointer to OAM control structure. 4643 * hash_data - (IN-OUT) Pointer to endpoint hash data. 4644 * modify_entry - (OUT) Pointer to existing entries which were 4645 * modified and need re-installation. 4646 * Retruns: 4647 * BCM_E_XXX 4648 */ 4649 STATIC int 4650 _bcm_tr3_oam_fp_create(int unit, _bcm_oam_control_t *oc, 4651 _bcm_oam_hash_data_t *hash_data) { 4652 4653 int rv = 0, i; 4654 _bcm_oam_hash_data_t *existing_max_level_ep_data = NULL; 4655 bcm_field_entry_t fp_entry_tx = -1, fp_entry_rx = -1; 4656 /* To hold any existing entries if modified */ 4657 bcm_field_entry_t modify_entry[2] = {-1, -1}; 4658 uint32 gport = 0; 4659 bcm_trunk_t tgid = 0; 4660 bcm_module_t modid = 0; 4661 bcm_port_t local_port; 4662 int prio = 0; 4663 uint8 add_mdl = 0; 4664 bcm_ip6_t mdl_data, mdl_mask; 4665 int local_id; /* Hardware ID used in call to _bcm_esw_gport_resolve*/ 4666 4667 if ( (NULL == oc) || (NULL == hash_data) ){ 4668 return (BCM_E_INTERNAL); 4669 } 4670 4671 /* Create Group */ 4672 /****************/ 4673 if (oc->fp_glp_group == -1) { 4674 4675 /* Prepare the Qualifier, use the same group for all 3: 4676 * 1. physical port, 2. trunk and 3. virtual ports. 4677 */ 4678 BCM_FIELD_QSET_INIT(oc->fp_glp_qs); 4679 BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifyStageIngress); 4680 4681 BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifyOuterVlanId); 4682 BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifyDstPort); 4683 BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifyDstTrunk); 4684 BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifySrcPort); 4685 BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifySrcTrunk); 4686 BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifyEtherType); 4687 BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifyDstIp6); 4688 if (soc_feature(unit, soc_feature_mim)) { 4689 BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifyDstMimGport); 4690 BCM_FIELD_QSET_ADD(oc->fp_glp_qs, bcmFieldQualifySrcMimGport); 4691 } 4692 /* Create fp group */ 4693 rv = bcm_esw_field_group_create(unit, oc->fp_glp_qs, 4694 BCM_FIELD_GROUP_PRIO_ANY, &(oc->fp_glp_group)); 4695 if (BCM_FAILURE(rv)) { 4696 LOG_ERROR(BSL_LS_BCM_OAM, 4697 (BSL_META_U(unit, 4698 "OAM Error: Group creation, EP=%d %s.\n"), 4699 hash_data->ep_id, bcm_errmsg(rv))); 4700 return (rv); 4701 } 4702 4703 } 4704 4705 /* Create the FP entry */ 4706 /***********************/ 4707 /* Entry priority is inversely proportional to level, In case of Multiple 4708 * MEPs on same vlan port following is the scheme for installation. 4709 * -----Level 2-(Match port vlan ethertype and MDL)---- 4710 * -----Level 4-(Match port vlan ethertype and MDL)---- 4711 * -----Level 6-(Match port vlan)---------------------- 4712 */ 4713 4714 /* Adding 1 to avoid hitting default Prio 0 at MAX_MDL */ 4715 prio = (_BCM_OAM_MAX_MDL + 1) - hash_data->level; 4716 4717 rv = _bcm_tr3_oam_fp_entry_id_allocate(unit, oc->fp_glp_group, prio, 4718 &(hash_data->fp_entry_tx)); 4719 if (BCM_FAILURE(rv)) { 4720 LOG_ERROR(BSL_LS_BCM_OAM, 4721 (BSL_META_U(unit, 4722 "OAM Error: FP Entry allocate (tx), EP=%d %s.\n"), 4723 hash_data->ep_id, bcm_errmsg(rv))); 4724 return (rv); 4725 } 4726 4727 rv = _bcm_tr3_oam_fp_entry_id_allocate(unit, oc->fp_glp_group, prio, 4728 &(hash_data->fp_entry_rx)); 4729 if (BCM_FAILURE(rv)) { 4730 LOG_ERROR(BSL_LS_BCM_OAM, 4731 (BSL_META_U(unit, 4732 "OAM Error: FP Entry allocate (rx), EP=%d %s.\n"), 4733 hash_data->ep_id, bcm_errmsg(rv))); 4734 return (rv); 4735 } 4736 4737 4738 /* Add Qualifiers */ 4739 /******************/ 4740 /* 1. VP Case */ 4741 if (hash_data->vp != 0) { 4742 LOG_VERBOSE(BSL_LS_BCM_OAM, 4743 (BSL_META_U(unit, 4744 "OAM: MEP on VP\n"))); 4745 BCM_GPORT_MIM_PORT_ID_SET(gport, hash_data->vp); 4746 4747 rv = bcm_esw_field_qualify_DstMimGport(unit, hash_data->fp_entry_tx, 4748 gport); 4749 if (BCM_FAILURE(rv)) { 4750 LOG_ERROR(BSL_LS_BCM_OAM, 4751 (BSL_META_U(unit, 4752 "OAM Error: Qualifying DstMimGport (tx), " 4753 "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 4754 return (rv); 4755 } 4756 4757 rv = bcm_esw_field_qualify_SrcMimGport(unit, hash_data->fp_entry_rx, 4758 gport); 4759 if (BCM_FAILURE(rv)) { 4760 LOG_ERROR(BSL_LS_BCM_OAM, 4761 (BSL_META_U(unit, 4762 "OAM Error: Qualifying SrcMimGport (rx), " 4763 "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 4764 return (rv); 4765 } 4766 4767 } else { 4768 4769 /* If its not VP case then we need to qualify on outer vlan for rest */ 4770 rv = bcm_esw_field_qualify_OuterVlanId(unit, hash_data->fp_entry_tx, 4771 hash_data->vlan, BCM_FIELD_EXACT_MATCH_MASK); 4772 if (BCM_FAILURE(rv)) { 4773 LOG_ERROR(BSL_LS_BCM_OAM, 4774 (BSL_META_U(unit, 4775 "OAM Error: Qualifying OuterVlanId (tx), " 4776 "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 4777 return (rv); 4778 } 4779 4780 rv = bcm_esw_field_qualify_OuterVlanId(unit, hash_data->fp_entry_rx, 4781 hash_data->vlan, BCM_FIELD_EXACT_MATCH_MASK); 4782 if (BCM_FAILURE(rv)) { 4783 LOG_ERROR(BSL_LS_BCM_OAM, 4784 (BSL_META_U(unit, 4785 "OAM Error: Qualifying OuterVlanId (rx), " 4786 "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 4787 return (rv); 4788 } 4789 4790 rv = _bcm_esw_gport_resolve(unit, hash_data->gport, &modid, 4791 &local_port, &tgid, &local_id); 4792 if (BCM_FAILURE(rv)) { 4793 LOG_ERROR(BSL_LS_BCM_OAM, 4794 (BSL_META_U(unit, 4795 "OAM Error: call to _bcm_esw_gport_resolve " 4796 "failed, EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 4797 return (rv); 4798 } 4799 LOG_VERBOSE(BSL_LS_BCM_OAM, 4800 (BSL_META_U(unit, 4801 "OAM - Local Port %d, modid %d, trunkid %d.\n"), 4802 local_port, modid, tgid)); 4803 4804 /* 2. Trunk Case */ 4805 if (SOC_GPORT_IS_TRUNK(hash_data->gport)) { 4806 LOG_VERBOSE(BSL_LS_BCM_OAM, 4807 (BSL_META_U(unit, 4808 "OAM: MEP on Trunk\n"))); 4809 4810 if (BCM_TRUNK_INVALID == tgid) { 4811 LOG_ERROR(BSL_LS_BCM_OAM, 4812 (BSL_META_U(unit, 4813 "OAM Error: Invalid Trunkid, EP=%d %s.\n"), 4814 hash_data->ep_id, bcm_errmsg(rv))); 4815 return (rv); 4816 } 4817 4818 rv = bcm_esw_field_qualify_DstTrunk(unit, hash_data->fp_entry_tx, 4819 tgid, BCM_FIELD_EXACT_MATCH_MASK); 4820 if (BCM_FAILURE(rv)) { 4821 LOG_ERROR(BSL_LS_BCM_OAM, 4822 (BSL_META_U(unit, 4823 "OAM Error: Qualifying DstTrunk (tx), " 4824 "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 4825 return (rv); 4826 } 4827 4828 rv = bcm_esw_field_qualify_SrcTrunk(unit, hash_data->fp_entry_rx, 4829 tgid, BCM_FIELD_EXACT_MATCH_MASK); 4830 if (BCM_FAILURE(rv)) { 4831 LOG_ERROR(BSL_LS_BCM_OAM, 4832 (BSL_META_U(unit, 4833 "OAM Error: Qualifying SrcTrunk (rx), " 4834 "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 4835 return (rv); 4836 } 4837 4838 /*For Down MEP on LAG, Add FP Entry on primary port of the LAG also, 4839 * as when packet is sent from CPU, Trunk Id cannot be specified, 4840 * and the packet will carry primary port of the LAG as destination 4841 */ 4842 if (!(hash_data->flags & BCM_OAM_ENDPOINT_UP_FACING)){ 4843 rv = _bcm_tr3_oam_fp_trunk_create(unit, oc, hash_data); 4844 if (BCM_FAILURE(rv)) { 4845 LOG_ERROR(BSL_LS_BCM_OAM, 4846 (BSL_META_U(unit, 4847 "OAM Error: Creating Fp Entry on Trunk Tx " 4848 "port, EP=%d %s\n"), hash_data->ep_id, bcm_errmsg(rv))); 4849 return (rv); 4850 } 4851 } 4852 4853 } else { 4854 4855 /*3. Local Port*/ 4856 LOG_VERBOSE(BSL_LS_BCM_OAM, 4857 (BSL_META_U(unit, 4858 "OAM: MEP on Local Port\n"))); 4859 4860 rv = bcm_esw_field_qualify_DstPort(unit, hash_data->fp_entry_tx, 4861 modid, BCM_FIELD_EXACT_MATCH_MASK, 4862 local_port, BCM_FIELD_EXACT_MATCH_MASK); 4863 if (BCM_FAILURE(rv)) { 4864 LOG_ERROR(BSL_LS_BCM_OAM, 4865 (BSL_META_U(unit, 4866 "OAM Error: Qualifying DstPort (tx), " 4867 "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 4868 return (rv); 4869 } 4870 4871 rv = bcm_esw_field_qualify_SrcPort(unit, hash_data->fp_entry_rx, 4872 modid, BCM_FIELD_EXACT_MATCH_MASK, 4873 local_port, BCM_FIELD_EXACT_MATCH_MASK); 4874 if (BCM_FAILURE(rv)) { 4875 LOG_ERROR(BSL_LS_BCM_OAM, 4876 (BSL_META_U(unit, 4877 "OAM Error: Qualifying SrcPort (rx), " 4878 "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 4879 return (rv); 4880 } 4881 } 4882 } 4883 4884 /* Check if we need Ethertype and MDL Qualifier: 4885 * 1. If this the first LM/DM MEP on port vlan, 4886 * Qualification on Ethertype and MDL not needed. 4887 * 2. If this is not the first LM/DM MEP on port vlan, and also not of 4888 * highest level, then add Ethertype and MDL Qualifiers and insert. 4889 * 3. If this is not the fisrt LM/DM MEP on port vlan, and also of 4890 * highest level, then modify existing highest MEP entry, 4891 * Add Ethertype and MDL Qualifier to existing MEP entry and 4892 * insert the current one without Ethertype and MDL. 4893 */ 4894 sal_memset(&mdl_data, 0, sizeof(bcm_ip6_t)); 4895 sal_memset(&mdl_mask, 0, sizeof(bcm_ip6_t)); 4896 mdl_mask[0] = 0xE0; 4897 LOG_VERBOSE(BSL_LS_BCM_OAM, 4898 (BSL_META_U(unit, 4899 "OAM _bcm_oam_lm_dm_search_data.match_count %d, " 4900 "_bcm_oam_lm_dm_search_data.highest_level %d, hash_data->level %d\n"), 4901 _bcm_oam_lm_dm_search_data.match_count, 4902 _bcm_oam_lm_dm_search_data.highest_level, hash_data->level)); 4903 if ( (_bcm_oam_lm_dm_search_data.match_count) && 4904 (_bcm_oam_lm_dm_search_data.highest_level > hash_data->level) ) { 4905 4906 fp_entry_tx = hash_data->fp_entry_tx; 4907 fp_entry_rx = hash_data->fp_entry_rx; 4908 mdl_data[0] = hash_data->level << 5; 4909 add_mdl = 1; 4910 4911 } else { 4912 4913 if ( (_bcm_oam_lm_dm_search_data.match_count) && 4914 (_bcm_oam_lm_dm_search_data.highest_level < hash_data->level) ) { 4915 4916 existing_max_level_ep_data = 4917 &oc->oam_hash_data[_bcm_oam_lm_dm_search_data.highest_level_ep_id]; 4918 fp_entry_tx = existing_max_level_ep_data->fp_entry_tx; 4919 fp_entry_rx = existing_max_level_ep_data->fp_entry_rx; 4920 mdl_data[0] = existing_max_level_ep_data->level << 5; 4921 add_mdl = 1; 4922 modify_entry[0] = fp_entry_tx; 4923 modify_entry[1] = fp_entry_rx; 4924 4925 } 4926 } 4927 if (add_mdl) { 4928 LOG_VERBOSE(BSL_LS_BCM_OAM, 4929 (BSL_META_U(unit, 4930 "OAM add_mdl=true\n"))); 4931 4932 rv = bcm_esw_field_qualify_EtherType(unit, fp_entry_tx, 4933 _BCM_OAM_ETHER_TYPE, BCM_FIELD_EXACT_MATCH_MASK); 4934 if (BCM_FAILURE(rv)) { 4935 LOG_ERROR(BSL_LS_BCM_OAM, 4936 (BSL_META_U(unit, 4937 "OAM Error: EtherType (tx), EP=%d %s.\n"), 4938 hash_data->ep_id, bcm_errmsg(rv))); 4939 return (rv); 4940 } 4941 rv = bcm_esw_field_qualify_EtherType(unit, fp_entry_rx, 4942 _BCM_OAM_ETHER_TYPE, BCM_FIELD_EXACT_MATCH_MASK); 4943 if (BCM_FAILURE(rv)) { 4944 LOG_ERROR(BSL_LS_BCM_OAM, 4945 (BSL_META_U(unit, 4946 "OAM Error: EtherType (rx), EP=%d %s.\n"), 4947 hash_data->ep_id, bcm_errmsg(rv))); 4948 return (rv); 4949 } 4950 4951 rv = bcm_esw_field_qualify_DstIp6(unit, fp_entry_tx, 4952 mdl_data, mdl_mask); 4953 if (BCM_FAILURE(rv)) { 4954 LOG_ERROR(BSL_LS_BCM_OAM, 4955 (BSL_META_U(unit, 4956 "OAM Error: Qualifying MDL (tx), EP=%d %s.\n"), 4957 hash_data->ep_id, bcm_errmsg(rv))); 4958 return (rv); 4959 } 4960 rv = bcm_esw_field_qualify_DstIp6(unit, fp_entry_rx, 4961 mdl_data, mdl_mask); 4962 if (BCM_FAILURE(rv)) { 4963 LOG_ERROR(BSL_LS_BCM_OAM, 4964 (BSL_META_U(unit, 4965 "OAM Error: Qualifying MDL (rx), EP=%d %s.\n"), 4966 hash_data->ep_id, bcm_errmsg(rv))); 4967 return (rv); 4968 } 4969 } 4970 4971 4972 /* Add action */ 4973 /**************/ 4974 /* In the case of UP MEP Tx rule is actually Rx and vice versa */ 4975 rv = _bcm_tr3_oam_fp_entry_action_add(unit, 4976 hash_data, hash_data->fp_entry_tx, 4977 hash_data->flags & BCM_OAM_ENDPOINT_UP_FACING? 0:1); 4978 if (BCM_FAILURE(rv)) { 4979 LOG_ERROR(BSL_LS_BCM_OAM, 4980 (BSL_META_U(unit, 4981 "OAM Error: Adding action (tx), EP=%d %s.\n"), 4982 hash_data->ep_id, bcm_errmsg(rv))); 4983 return (rv); 4984 } 4985 4986 rv = _bcm_tr3_oam_fp_entry_action_add(unit, hash_data, 4987 hash_data->fp_entry_rx, hash_data->flags & BCM_OAM_ENDPOINT_UP_FACING? 1:0); 4988 if (BCM_FAILURE(rv)) { 4989 LOG_ERROR(BSL_LS_BCM_OAM, 4990 (BSL_META_U(unit, 4991 "OAM Error: Adding action (rx), EP=%d %s.\n"), 4992 hash_data->ep_id, bcm_errmsg(rv))); 4993 return (rv); 4994 } 4995 4996 /* Install Created/Modified entries */ 4997 /************************************/ 4998 /* Tx Entry */ 4999 rv = bcm_esw_field_entry_install(unit, hash_data->fp_entry_tx); 5000 if (BCM_FAILURE(rv)) { 5001 LOG_ERROR(BSL_LS_BCM_OAM, 5002 (BSL_META_U(unit, 5003 "OAM Error: FP Install failed (tx), EP=%d %s.\n"), 5004 hash_data->ep_id, bcm_errmsg(rv))); 5005 return (rv); 5006 } 5007 /* Rx Entry */ 5008 rv = bcm_esw_field_entry_install(unit, hash_data->fp_entry_rx); 5009 if (BCM_FAILURE(rv)) { 5010 LOG_ERROR(BSL_LS_BCM_OAM, 5011 (BSL_META_U(unit, 5012 "OAM Error: FP Install failed (tx), EP=%d %s.\n"), 5013 hash_data->ep_id, bcm_errmsg(rv))); 5014 return (rv); 5015 } 5016 /* Trunk Entry */ 5017 if (hash_data->fp_entry_trunk[0] != -1){ 5018 rv = bcm_esw_field_entry_install(unit, hash_data->fp_entry_trunk[0]); 5019 if (BCM_FAILURE(rv)) { 5020 LOG_ERROR(BSL_LS_BCM_OAM, 5021 (BSL_META_U(unit, 5022 "OAM Error: FP Install failed (Trunk), " 5023 "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 5024 return (rv); 5025 } 5026 } 5027 /* Any existing entries that were modified */ 5028 for (i=0; i<2; i++){ 5029 if (modify_entry[i] != -1) { 5030 rv = bcm_esw_field_entry_install(unit, modify_entry[i]); 5031 if (BCM_FAILURE(rv)) { 5032 LOG_ERROR(BSL_LS_BCM_OAM, 5033 (BSL_META_U(unit, 5034 "OAM Error: FP Modify failed, EP=%d %s.\n"), 5035 hash_data->ep_id, bcm_errmsg(rv))); 5036 return (rv); 5037 } 5038 } 5039 } 5040 5041 return (rv); 5042 5043 } 5044 5045 /* 5046 * Function: 5047 * _bcm_tr3_oam_pri_map_profile_create 5048 * Purpose: 5049 * Create ING_SERVICE_PRI_MAP entry for LM 5050 * Parameters: 5051 * unit - (IN) BCM device number 5052 * oc - (IN) Pointer to OAM control structure. 5053 * hash_data - (IN) Pointer to endpoint hash data. 5054 * endpoint_info - (IN) Pointer to endpoint info structure. 5055 * Retruns: 5056 * BCM_E_XXX 5057 */ 5058 STATIC int 5059 _bcm_tr3_oam_pri_map_profile_create(int unit, _bcm_oam_control_t *oc, 5060 _bcm_oam_hash_data_t *hash_data, bcm_oam_endpoint_info_t *endpoint_info) { 5061 5062 int rv = 0; 5063 ing_service_pri_map_entry_t pri_ent[BCM_OAM_INTPRI_MAX]; /* profile */ 5064 soc_mem_t mem; /* Profiled table memory. */ 5065 void *entries[1]; /* Profile entry. */ 5066 uint32 profile_index; /* Profile table index. */ 5067 uint8 pri = 0; 5068 5069 if ( (NULL == oc) || (NULL == hash_data) || (NULL == endpoint_info) ){ 5070 return (BCM_E_INTERNAL); 5071 } 5072 5073 /* 5074 * Initialize ingress priority map profile table. 5075 * All priorities priorities map to priority:'0'. 5076 */ 5077 mem = ING_SERVICE_PRI_MAPm; 5078 for (pri = 0; pri < BCM_OAM_INTPRI_MAX; pri++) { 5079 5080 /* Clear ingress service pri map profile entry. */ 5081 sal_memcpy(&pri_ent[pri], soc_mem_entry_null(unit, mem), 5082 soc_mem_entry_words(unit, mem) * sizeof(uint32)); 5083 5084 if (SOC_MEM_FIELD_VALID(unit, mem, OFFSETf)) { 5085 soc_mem_field32_set(unit, mem, &pri_ent[pri], OFFSETf, 5086 endpoint_info->pri_map[pri]); 5087 } 5088 5089 if (SOC_MEM_FIELD_VALID(unit, mem, OFFSET_VALIDf)) { 5090 soc_mem_field32_set(unit, mem, &pri_ent[pri], OFFSET_VALIDf, 1); 5091 } 5092 } 5093 entries[0] = &pri_ent; 5094 rv = soc_profile_mem_add(unit, &oc->ing_service_pri_map, 5095 (void *) &entries, BCM_OAM_INTPRI_MAX, &profile_index); 5096 if (BCM_FAILURE(rv)) { 5097 LOG_ERROR(BSL_LS_BCM_OAM, 5098 (BSL_META_U(unit, 5099 "OAM Error: service map profile add, EP=%d %s.\n"), 5100 hash_data->ep_id, bcm_errmsg(rv))); 5101 return (rv); 5102 } 5103 hash_data->pri_map_index = profile_index /BCM_OAM_INTPRI_MAX; 5104 5105 return (rv); 5106 5107 } 5108 5109 /* 5110 * Function: 5111 * _bcm_lm_dm_search_cb 5112 * Purpose: 5113 * Call back function to match existing LM endpoints over same vlan port. 5114 * Gives Existing Highest level enpoint, excluding the current(EP in context) 5115 * Parameters: 5116 * unit - (IN) BCM device number. 5117 * hash_key - (IN) Pointer to endpoint hash key value. 5118 * data - (IN) Pointer to endpoint hash data. 5119 * Retruns: 5120 * BCM_E_XXX 5121 */ 5122 STATIC int 5123 _bcm_lm_dm_search_cb(int unit, shr_htb_key_t key, shr_htb_data_t data) { 5124 int rv = 0; 5125 _bcm_oam_hash_data_t *h_data_ptr; 5126 5127 h_data_ptr = (_bcm_oam_hash_data_t *)data; 5128 if ( ( h_data_ptr->flags & (BCM_OAM_ENDPOINT_LOSS_MEASUREMENT | 5129 BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) ) && 5130 (h_data_ptr->in_use == 1) && 5131 (h_data_ptr->ep_id != _bcm_oam_lm_dm_search_data.match_ep_id) && 5132 (h_data_ptr->type == _bcm_oam_lm_dm_search_data.match_type) && 5133 (h_data_ptr->vlan == _bcm_oam_lm_dm_search_data.match_vlan) && 5134 (h_data_ptr->gport == _bcm_oam_lm_dm_search_data.match_gport) ) { 5135 _bcm_oam_lm_dm_search_data.match_count++; 5136 if (h_data_ptr->level >= _bcm_oam_lm_dm_search_data.highest_level) { 5137 _bcm_oam_lm_dm_search_data.highest_level = h_data_ptr->level; 5138 _bcm_oam_lm_dm_search_data.highest_level_ep_id = h_data_ptr->ep_id; 5139 } 5140 } 5141 5142 return rv; 5143 } 5144 5145 /* 5146 * Function: 5147 * _bcm_tr3_oam_loss_delay_measurement_add 5148 * Purpose: 5149 * Create LM/DM IFP entry and install the same. 5150 * Parameters: 5151 * unit - (IN) BCM device number 5152 * oc - (IN) Pointer to OAM control structure. 5153 * hash_data - (IN) Pointer to endpoint hash data. 5154 * endpoint_info - (IN) Pointer to endpoint info structure. 5155 * Retruns: 5156 * BCM_E_XXX 5157 */ 5158 STATIC int 5159 _bcm_tr3_oam_loss_delay_measurement_add(int unit, _bcm_oam_control_t *oc, 5160 _bcm_oam_hash_data_t *hash_data, bcm_oam_endpoint_info_t *endpoint_info) { 5161 5162 int rv=0; 5163 /*Hash data of existing endpoint on same vlan port */ 5164 _bcm_oam_hash_data_t *existing_ep_hash_data = NULL; 5165 5166 if ( (NULL == oc) || (NULL == hash_data) || (NULL == endpoint_info) ){ 5167 return (BCM_E_INTERNAL); 5168 } 5169 5170 sal_memset(&_bcm_oam_lm_dm_search_data, 0, 5171 sizeof(_bcm_oam_lm_dm_search_data_type_t)); 5172 5173 /*Set the match criteria for LM search*/ 5174 _bcm_oam_lm_dm_search_data.match_type = hash_data->type; 5175 _bcm_oam_lm_dm_search_data.match_ep_id = hash_data->ep_id; 5176 _bcm_oam_lm_dm_search_data.match_vlan = hash_data->vlan; 5177 _bcm_oam_lm_dm_search_data.match_gport = hash_data->gport; 5178 _bcm_oam_lm_dm_search_data.highest_level = 0; 5179 _bcm_oam_lm_dm_search_data.highest_level_ep_id = 0; 5180 5181 /* Iterate over existing enpoint to find 5182 if port vlan matching entry already exists */ 5183 rv = shr_htb_iterate(unit, oc->ma_mep_htbl, _bcm_lm_dm_search_cb); 5184 if (BCM_FAILURE(rv)) { 5185 LOG_ERROR(BSL_LS_BCM_OAM, 5186 (BSL_META_U(unit, 5187 "OAM Error: LM Search failed, EP=%d %s.\n"), 5188 hash_data->ep_id, bcm_errmsg(rv))); 5189 return (rv); 5190 } 5191 5192 LOG_VERBOSE(BSL_LS_BCM_OAM, 5193 (BSL_META_U(unit, 5194 "OAM: Existing EP on vlan port count=%d, " 5195 "Highest level=%d, EP=%d\n"), 5196 _bcm_oam_lm_dm_search_data.match_count, 5197 _bcm_oam_lm_dm_search_data.highest_level, 5198 _bcm_oam_lm_dm_search_data.highest_level_ep_id)); 5199 5200 if (hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 5201 5202 /* If enpoint already exists on same vlan port, 5203 * Use the Primap and Counter index of existing endpoint, 5204 * Its a hardware limitation that multi level endpoints 5205 * on same vlan port cannot have different primap 5206 */ 5207 if (_bcm_oam_lm_dm_search_data.match_count > 0) { 5208 existing_ep_hash_data = 5209 &oc->oam_hash_data[_bcm_oam_lm_dm_search_data.highest_level_ep_id]; 5210 hash_data->pri_map_index = existing_ep_hash_data->pri_map_index; 5211 hash_data->lm_counter_index = existing_ep_hash_data->lm_counter_index; 5212 5213 } else { 5214 /* Create ING_SERVICE_PRI_MAP profile for the endpoint */ 5215 rv = _bcm_tr3_oam_pri_map_profile_create(unit, oc, hash_data, 5216 endpoint_info); 5217 if (BCM_FAILURE(rv)) { 5218 LOG_ERROR(BSL_LS_BCM_OAM, 5219 (BSL_META_U(unit, 5220 "OAM Error: ING_SERVICE_PRI_MAP profile " 5221 "creation, EP=%d %s\n"), hash_data->ep_id, bcm_errmsg(rv))); 5222 return (rv); 5223 } 5224 5225 /* Allocate counter index. */ 5226 rv = shr_idxres_list_alloc(oc->lm_counter_pool, 5227 (shr_idxres_element_t *)&hash_data->lm_counter_index); 5228 if (BCM_FAILURE(rv)) { 5229 LOG_ERROR(BSL_LS_BCM_OAM, 5230 (BSL_META_U(unit, 5231 "OAM Error: lm counter idx alloc failed, " 5232 "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 5233 return (rv); 5234 } 5235 } 5236 } 5237 5238 /* Create Field entries / modify existing if needed. Also install*/ 5239 rv = _bcm_tr3_oam_fp_create(unit, oc, hash_data); 5240 if (BCM_FAILURE(rv)) { 5241 LOG_ERROR(BSL_LS_BCM_OAM, 5242 (BSL_META_U(unit, 5243 "OAM Error: FP Create failed, EP=%d %s.\n"), 5244 hash_data->ep_id, bcm_errmsg(rv))); 5245 5246 /* In case of failure, free the counter index and primap 5247 * only if the same has been newly created for this endpoint */ 5248 if (hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 5249 5250 /* If another enpoint exists on same vlan port, 5251 * Don't free primap and counter index, as they are shared */ 5252 if (_bcm_oam_lm_dm_search_data.match_count == 0){ 5253 5254 /* Free ING_SERVICE_PRI_MAP profile */ 5255 soc_profile_mem_delete(unit, &oc->ing_service_pri_map, 5256 (hash_data->pri_map_index * BCM_OAM_INTPRI_MAX)); 5257 5258 /* Free counter index. */ 5259 shr_idxres_list_free( oc->lm_counter_pool, 5260 (shr_idxres_element_t)hash_data->lm_counter_index); 5261 } 5262 } 5263 return (rv); 5264 } 5265 5266 /* Increment the group FP count */ 5267 oc->fp_glp_entry_cnt++; 5268 LOG_VERBOSE(BSL_LS_BCM_OAM, 5269 (BSL_META_U(unit, 5270 "OAM: oc->fp_glp_entry_cnt=%d\n"), 5271 oc->fp_glp_entry_cnt)); 5272 return (rv); 5273 } 5274 5275 5276 /* 5277 * Function: 5278 * _bcm_tr3_oam_loss_delay_measurement_delete 5279 * Purpose: 5280 * Delete LM/DM IFP entry and install the same. 5281 * Parameters: 5282 * unit - (IN) BCM device number 5283 * oc - (IN) Pointer to OAM control structure. 5284 * hash_data - (IN) Pointer to endpoint hash data. 5285 * Retruns: 5286 * BCM_E_XXX 5287 */ 5288 STATIC int 5289 _bcm_tr3_oam_loss_delay_measurement_delete(int unit, _bcm_oam_control_t *oc, 5290 _bcm_oam_hash_data_t *hash_data) { 5291 5292 int rv=0; 5293 /*Hash data of existing endpoint on same vlan port */ 5294 _bcm_oam_hash_data_t *existing_ep_hash_data = NULL; 5295 5296 if ( (NULL == oc) || (NULL == hash_data) ){ 5297 return (BCM_E_INTERNAL); 5298 } 5299 5300 sal_memset(&_bcm_oam_lm_dm_search_data, 0, 5301 sizeof(_bcm_oam_lm_dm_search_data_type_t)); 5302 5303 /*Set the match criteria for LM search*/ 5304 _bcm_oam_lm_dm_search_data.match_type = hash_data->type; 5305 _bcm_oam_lm_dm_search_data.match_ep_id = hash_data->ep_id; 5306 _bcm_oam_lm_dm_search_data.match_vlan = hash_data->vlan; 5307 _bcm_oam_lm_dm_search_data.match_gport = hash_data->gport; 5308 _bcm_oam_lm_dm_search_data.highest_level = 0; 5309 _bcm_oam_lm_dm_search_data.highest_level_ep_id = 0; 5310 5311 /* Iterate over existing enpoint to find if 5312 other port vlan matching entry already exists */ 5313 rv = shr_htb_iterate(unit, oc->ma_mep_htbl, _bcm_lm_dm_search_cb); 5314 if (BCM_FAILURE(rv)) { 5315 LOG_ERROR(BSL_LS_BCM_OAM, 5316 (BSL_META_U(unit, 5317 "OAM Error: LM Search failed, EP=%d %s.\n"), 5318 hash_data->ep_id, bcm_errmsg(rv))); 5319 return (rv); 5320 } 5321 5322 LOG_VERBOSE(BSL_LS_BCM_OAM, 5323 (BSL_META_U(unit, 5324 "OAM: Existing EP on vlan port count=%d, " 5325 "Highest level=%d, EP=%d\n"), 5326 _bcm_oam_lm_dm_search_data.match_count, 5327 _bcm_oam_lm_dm_search_data.highest_level, 5328 _bcm_oam_lm_dm_search_data.highest_level_ep_id)); 5329 5330 if (hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 5331 5332 /* If another enpoint exists on same vlan port, 5333 Don't free primap and counter index, as they are shared */ 5334 if (_bcm_oam_lm_dm_search_data.match_count == 0){ 5335 5336 /* Free ING_SERVICE_PRI_MAP profile */ 5337 rv = soc_profile_mem_delete(unit, 5338 &oc->ing_service_pri_map, 5339 (hash_data->pri_map_index * BCM_OAM_INTPRI_MAX)); 5340 if (BCM_FAILURE(rv)) { 5341 LOG_ERROR(BSL_LS_BCM_OAM, 5342 (BSL_META_U(unit, 5343 "OAM Error: ING_SERVICE_PRI_MAP profile " 5344 "deletion, EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 5345 return (rv); 5346 } 5347 5348 /* Free counter index. */ 5349 rv = shr_idxres_list_free( oc->lm_counter_pool, 5350 (shr_idxres_element_t)hash_data->lm_counter_index); 5351 if (BCM_FAILURE(rv)) { 5352 LOG_ERROR(BSL_LS_BCM_OAM, 5353 (BSL_META_U(unit, 5354 "OAM Error: lm counter idx free failed, " 5355 "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 5356 return (rv); 5357 } 5358 } 5359 } 5360 5361 /* If the EP we are deleting is at the lowest level and 5362 other EP exist at higher level 5363 Modify the other EP to remove Ethertype and Level match criteria. */ 5364 if ( _bcm_oam_lm_dm_search_data.match_count > 0 && 5365 _bcm_oam_lm_dm_search_data.highest_level < hash_data->level ) { 5366 5367 existing_ep_hash_data = 5368 &oc->oam_hash_data[_bcm_oam_lm_dm_search_data.highest_level_ep_id]; 5369 5370 rv = bcm_esw_field_qualifier_delete(unit, 5371 existing_ep_hash_data->fp_entry_tx, bcmFieldQualifyEtherType); 5372 if (BCM_FAILURE(rv)) { 5373 LOG_ERROR(BSL_LS_BCM_OAM, 5374 (BSL_META_U(unit, 5375 "OAM Error: Eth Type dequlaify (tx), EP=%d %s.\n"), 5376 hash_data->ep_id, bcm_errmsg(rv))); 5377 return (rv); 5378 } 5379 5380 rv = bcm_esw_field_qualifier_delete(unit, 5381 existing_ep_hash_data->fp_entry_tx, bcmFieldQualifyDstIp6); 5382 if (BCM_FAILURE(rv)) { 5383 LOG_ERROR(BSL_LS_BCM_OAM, 5384 (BSL_META_U(unit, 5385 "OAM Error: Level dequlaify (tx), EP=%d %s.\n"), 5386 hash_data->ep_id, bcm_errmsg(rv))); 5387 return (rv); 5388 } 5389 5390 rv = bcm_esw_field_qualifier_delete(unit, 5391 existing_ep_hash_data->fp_entry_rx, bcmFieldQualifyEtherType); 5392 if (BCM_FAILURE(rv)) { 5393 LOG_ERROR(BSL_LS_BCM_OAM, 5394 (BSL_META_U(unit, 5395 "OAM Error: Eth Type dequlaify (rx), EP=%d %s.\n"), 5396 hash_data->ep_id, bcm_errmsg(rv))); 5397 return (rv); 5398 } 5399 5400 rv = bcm_esw_field_qualifier_delete(unit, 5401 existing_ep_hash_data->fp_entry_rx, bcmFieldQualifyDstIp6); 5402 if (BCM_FAILURE(rv)) { 5403 LOG_ERROR(BSL_LS_BCM_OAM, 5404 (BSL_META_U(unit, 5405 "OAM Error: Level dequlaify (rx), EP=%d %s.\n"), 5406 hash_data->ep_id, bcm_errmsg(rv))); 5407 return (rv); 5408 } 5409 5410 /* Install Modified entries */ 5411 rv = bcm_esw_field_entry_install(unit, 5412 existing_ep_hash_data->fp_entry_tx); 5413 if (BCM_FAILURE(rv)) { 5414 LOG_ERROR(BSL_LS_BCM_OAM, 5415 (BSL_META_U(unit, 5416 "OAM Error: FP Install failed (tx), EP=%d %s.\n"), 5417 hash_data->ep_id, bcm_errmsg(rv))); 5418 return (rv); 5419 } 5420 5421 rv = bcm_esw_field_entry_install(unit, 5422 existing_ep_hash_data->fp_entry_rx); 5423 if (BCM_FAILURE(rv)) { 5424 LOG_ERROR(BSL_LS_BCM_OAM, 5425 (BSL_META_U(unit, 5426 "OAM Error: FP Install failed (tx), EP=%d %s.\n"), 5427 hash_data->ep_id, bcm_errmsg(rv))); 5428 return (rv); 5429 } 5430 5431 } 5432 5433 /* Delete FP entries for this EP*/ 5434 /* Tx Entry */ 5435 rv = bcm_esw_field_entry_destroy(unit, hash_data->fp_entry_tx); 5436 /* Field init happens before oam init. Due to this, FP entries are already 5437 * wiped out. Hence we need to ignore NOT_FOUND error. */ 5438 if ((BCM_FAILURE(rv)) && (rv != BCM_E_NOT_FOUND)) { 5439 LOG_ERROR(BSL_LS_BCM_OAM, 5440 (BSL_META_U(unit, 5441 "OAM Error: FP Destroy failed (tx), EP=%d %s.\n"), 5442 hash_data->ep_id, bcm_errmsg(rv))); 5443 return (rv); 5444 } 5445 hash_data->fp_entry_tx = -1; 5446 5447 /* Rx Entry */ 5448 rv = bcm_esw_field_entry_destroy(unit, hash_data->fp_entry_rx); 5449 /* Field init happens before oam init. Due to this, FP entries are already 5450 * wiped out. Hence we need to ignore NOT_FOUND error. */ 5451 if ((BCM_FAILURE(rv)) && (rv != BCM_E_NOT_FOUND)) { 5452 LOG_ERROR(BSL_LS_BCM_OAM, 5453 (BSL_META_U(unit, 5454 "OAM Error: FP Destroy failed (rx), EP=%d %s.\n"), 5455 hash_data->ep_id, bcm_errmsg(rv))); 5456 return (rv); 5457 } 5458 hash_data->fp_entry_rx = -1; 5459 5460 /* Trunk Entry */ 5461 if (hash_data->fp_entry_trunk[0] != -1) { 5462 rv = bcm_esw_field_entry_destroy(unit, hash_data->fp_entry_trunk[0]); 5463 /* Field init happens before oam init. Due to this, FP entries are already 5464 * wiped out. Hence we need to ignore NOT_FOUND error. */ 5465 if ((BCM_FAILURE(rv)) && (rv != BCM_E_NOT_FOUND)) { 5466 LOG_ERROR(BSL_LS_BCM_OAM, 5467 (BSL_META_U(unit, 5468 "OAM Error: FP Destroy failed (Trunk), " 5469 "EP=%d %s.\n"), hash_data->ep_id, bcm_errmsg(rv))); 5470 return (rv); 5471 } 5472 hash_data->fp_entry_trunk[0] = -1; 5473 } 5474 5475 /* Decrement the group FP count */ 5476 oc->fp_glp_entry_cnt--; 5477 LOG_VERBOSE(BSL_LS_BCM_OAM, 5478 (BSL_META_U(unit, 5479 "OAM: oc->fp_glp_entry_cnt=%d\n"), 5480 oc->fp_glp_entry_cnt)); 5481 /* If count goes 0 delete the group */ 5482 if (!(oc->fp_glp_entry_cnt)) { 5483 rv = bcm_esw_field_group_destroy(unit, oc->fp_glp_group); 5484 /* Field init happens before oam init. Due to this, FP groups are already 5485 * wiped out. Hence we need to ignore NOT_FOUND error. */ 5486 if ((BCM_FAILURE(rv)) && (rv != BCM_E_NOT_FOUND)) { 5487 LOG_ERROR(BSL_LS_BCM_OAM, 5488 (BSL_META_U(unit, 5489 "OAM Error: FP Group Destroy failed, EP=%d %s.\n"), 5490 hash_data->ep_id, bcm_errmsg(rv))); 5491 return (rv); 5492 } 5493 /* clear FP group ID to indicate that group was deleted */ 5494 oc->fp_glp_group = -1; 5495 } 5496 5497 return (BCM_E_NONE); 5498 } 5499 5500 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 5501 void 5502 _bcm_tr3_oam_group_info_dump(int unit, bcm_oam_group_t group_index, 5503 _bcm_oam_group_data_t *group_p) 5504 { 5505 int rv; 5506 bcm_oam_group_info_t group_info; 5507 5508 /* Initialize the group information structure. */ 5509 bcm_oam_group_info_t_init(&group_info); 5510 5511 /* Retrieve group information and set in group_info structure. */ 5512 rv = _bcm_tr3_oam_get_group(unit, group_index, group_p, &group_info); 5513 if (BCM_FAILURE(rv)) { 5514 LOG_ERROR(BSL_LS_BCM_OAM, 5515 (BSL_META_U(unit, 5516 "OAM(unit %d) Error: _bcm_tr3_oam_group_info_dump" 5517 " (GID=%d) - %s.\n"), 5518 unit, group_index, bcm_errmsg(rv))); 5519 return; 5520 } 5521 LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n"))); 5522 LOG_CLI((BSL_META_U(unit,"Group ID = %d details\r\n"), group_index)); 5523 LOG_CLI((BSL_META_U(unit,"Group Name = %s\r\n"), group_info.name)); 5524 LOG_CLI((BSL_META_U(unit,"Flags = %d\r\n"), group_info.flags)); 5525 LOG_CLI((BSL_META_U(unit,"Faults = %d\r\n"), group_info.faults)); 5526 LOG_CLI((BSL_META_U(unit,"Persistent_faults = %d\r\n"), 5527 group_info.persistent_faults)); 5528 LOG_CLI((BSL_META_U(unit,"clear_persistent_faults = %d\r\n"), 5529 group_info.clear_persistent_faults)); 5530 LOG_CLI((BSL_META_U(unit,"lowest_alarm_priority = %d\r\n"), 5531 group_info.lowest_alarm_priority)); 5532 LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n"))); 5533 } 5534 5535 /* 5536 * Function: 5537 * _bcm_oam_sw_dump 5538 * Purpose: 5539 * Displays oam information maintained by software. 5540 * Parameters: 5541 * unit - Device unit number 5542 * Returns: 5543 * None 5544 */ 5545 void 5546 _bcm_tr3_oam_sw_dump(int unit) 5547 { 5548 _bcm_oam_control_t *oc; 5549 int ep_id; 5550 int rv; 5551 bcm_oam_group_t grp_idx; 5552 _bcm_oam_group_data_t *group_p; 5553 5554 LOG_CLI((BSL_META_U(unit,"OAM\n"))); 5555 /* Get OAM control structure. */ 5556 rv = _bcm_oam_control_get(unit, &oc); 5557 if(BCM_FAILURE(rv)) { 5558 LOG_ERROR(BSL_LS_BCM_OAM, 5559 (BSL_META_U(unit, 5560 "OAM(unit %d) Error: Get oam control variable\n"), 5561 unit)); 5562 5563 return; 5564 } 5565 5566 _BCM_OAM_LOCK(oc); 5567 5568 group_p = oc->group_info; 5569 for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) { 5570 if (group_p[grp_idx].in_use == 1) { 5571 _bcm_tr3_oam_group_info_dump(unit, grp_idx, group_p); 5572 } 5573 } 5574 5575 _BCM_OAM_UNLOCK(oc); 5576 5577 for(ep_id=0; ep_id < oc->ep_count; ep_id++) { 5578 if (oc->oam_hash_data[ep_id].in_use) { 5579 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].flags = %d\n"), 5580 ep_id, oc->oam_hash_data[ep_id].flags)); 5581 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].flags2 = %d\n"), 5582 ep_id, oc->oam_hash_data[ep_id].flags2)); 5583 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].fp_entry_rx = %d\n"), 5584 ep_id, oc->oam_hash_data[ep_id].fp_entry_rx)); 5585 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].fp_entry_tx = %d\n"), 5586 ep_id, oc->oam_hash_data[ep_id].fp_entry_tx)); 5587 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].type = %d\n"), 5588 ep_id,oc->oam_hash_data[ep_id].type)); 5589 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].ep_id = %d\n"), 5590 ep_id,oc->oam_hash_data[ep_id].ep_id)); 5591 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].is_remote = %d\n"), 5592 ep_id,oc->oam_hash_data[ep_id].is_remote)); 5593 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].local_tx_enabled = %d\n"), 5594 ep_id,oc->oam_hash_data[ep_id].local_tx_enabled)); 5595 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].local_rx_enabled = %d\n"), 5596 ep_id,oc->oam_hash_data[ep_id].local_rx_enabled)); 5597 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].group_index = %d\n"), 5598 ep_id,oc->oam_hash_data[ep_id].group_index)); 5599 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].name = %d\n"), 5600 ep_id,oc->oam_hash_data[ep_id].name)); 5601 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].level = %d\n"), 5602 ep_id,oc->oam_hash_data[ep_id].level)); 5603 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].vlan = %d\n"), 5604 ep_id,oc->oam_hash_data[ep_id].vlan)); 5605 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].gport = %d\n"), 5606 ep_id,oc->oam_hash_data[ep_id].gport)); 5607 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].sglp = %d\n"), 5608 ep_id,oc->oam_hash_data[ep_id].sglp)); 5609 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].dglp = %d\n"), 5610 ep_id,oc->oam_hash_data[ep_id].dglp)); 5611 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].opcode_flags = %d\n"), 5612 ep_id,oc->oam_hash_data[ep_id].opcode_flags)); 5613 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].period = %d\n"), 5614 ep_id,oc->oam_hash_data[ep_id].period)); 5615 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].in_use = %d\n"), 5616 ep_id,oc->oam_hash_data[ep_id].in_use)); 5617 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].fp_entry_trunk[0] = %d\n"), 5618 ep_id,oc->oam_hash_data[ep_id].fp_entry_trunk[0])); 5619 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].ts_format = %d\n"), 5620 ep_id,oc->oam_hash_data[ep_id].ts_format)); 5621 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].local_tx_index = %d\n"), 5622 ep_id,oc->oam_hash_data[ep_id].local_tx_index)); 5623 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].local_rx_index = %d\n"), 5624 ep_id,oc->oam_hash_data[ep_id].local_rx_index)); 5625 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].remote_index = %d\n"), 5626 ep_id,oc->oam_hash_data[ep_id].remote_index)); 5627 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].inner_vlan = %d\n"), 5628 ep_id,oc->oam_hash_data[ep_id].inner_vlan)); 5629 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].lm_counter_index = %d\n"), 5630 ep_id,oc->oam_hash_data[ep_id].lm_counter_index)); 5631 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].pri_map_index = %d\n"), 5632 ep_id,oc->oam_hash_data[ep_id].pri_map_index)); 5633 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].vp = %d\n"), 5634 ep_id,oc->oam_hash_data[ep_id].vp)); 5635 LOG_CLI((BSL_META_U(unit,"\toam_hash_data[%d].vfp_entry = %d\n"), 5636 ep_id,oc->oam_hash_data[ep_id].vfp_entry)); 5637 } 5638 } 5639 } 5640 #endif 5641 5642 #if defined(BCM_WARM_BOOT_SUPPORT) 5643 /* 5644 * Function: 5645 * _bcm_tr3_oam_endpoint_alloc 5646 * Purpose: 5647 * Allocate an endpoint memory element. 5648 * Parameters: 5649 * ep_pp - (IN/OUT) Pointer to endpoint address pointer. 5650 * Returns: 5651 * BCM_E_XXX 5652 */ 5653 STATIC int 5654 _bcm_tr3_oam_endpoint_alloc(bcm_oam_endpoint_info_t **ep_pp) 5655 { 5656 bcm_oam_endpoint_info_t *ep_p = NULL; 5657 5658 _BCM_OAM_ALLOC(ep_p, bcm_oam_endpoint_info_t, 5659 sizeof(bcm_oam_endpoint_info_t), "Endpoint info"); 5660 if (NULL == ep_p) { 5661 return (BCM_E_MEMORY); 5662 } 5663 5664 *ep_pp = ep_p; 5665 5666 return (BCM_E_NONE); 5667 5668 } 5669 5670 /* 5671 * Function: 5672 * _bcm_tr3_oam_sync 5673 * Purpose: 5674 * Store OAM configuration to level two storage cache memory. 5675 * Parameters: 5676 * unit - (IN) Device unit number 5677 * Returns: 5678 * BCM_E_XXX 5679 */ 5680 int 5681 _bcm_tr3_oam_sync(int unit) 5682 { 5683 _bcm_oam_control_t *oc; 5684 int alloc_size = 0; 5685 int stable_size; 5686 soc_scache_handle_t scache_handle; 5687 uint8 *oam_scache; 5688 int grp_idx; 5689 _bcm_oam_group_data_t *group_p; /* Pointer to group list. */ 5690 int group_count = 0; 5691 int rv; 5692 _bcm_oam_ep_list_t *ep_list_p = NULL; 5693 _bcm_oam_hash_data_t ep_data; 5694 5695 /* Get OAM module storage size. */ 5696 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 5697 5698 /* If level 2 store is not configured return from here. */ 5699 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) { 5700 return (BCM_E_NONE); 5701 } 5702 5703 /* Get handle to control structure. */ 5704 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 5705 5706 _BCM_OAM_LOCK(oc); 5707 5708 /* Initialize to group array pointer. */ 5709 group_p = oc->group_info; 5710 5711 /* Storing the valid group count, as was done in BCM_WB_VERSION_1_0 */ 5712 for (grp_idx = 0; grp_idx < oc->group_count; grp_idx++) { 5713 if (BCM_E_EXISTS 5714 == shr_idxres_list_elem_state(oc->group_pool, grp_idx)) { 5715 group_count++; 5716 } 5717 } 5718 5719 alloc_size += BCM_OAM_GROUP_NAME_LENGTH * (oc->group_count); 5720 5721 /* To store OAM group count. */ 5722 alloc_size += sizeof(int); 5723 5724 /* To store FP GID. */ 5725 alloc_size += 3 * sizeof(bcm_field_group_t); 5726 5727 /* To store EP Ids */ 5728 alloc_size += (sizeof (bcm_oam_endpoint_t) * 5729 (oc->rmep_count + oc->lmep_count + oc->ma_idx_count)); 5730 5731 /* To store MEP TX , RX and LAG LM/DM FP entry numbers */ 5732 alloc_size += ((sizeof (bcm_field_entry_t) * 3) * 5733 (oc->ma_idx_count)); 5734 5735 /* Store the BHH Hw config */ 5736 alloc_size += _bcm_tr3_oam_bhh_hw_config_scache_size_get(unit); 5737 5738 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 5739 5740 /* Check if memory has already been allocated */ 5741 rv = _bcm_esw_scache_ptr_get(unit, 5742 scache_handle, 5743 0, 5744 alloc_size, 5745 &oam_scache, 5746 BCM_WB_DEFAULT_VERSION, 5747 NULL 5748 ); 5749 if (!SOC_WARM_BOOT(unit) && (BCM_E_NOT_FOUND == rv)) { 5750 rv = _bcm_esw_scache_ptr_get(unit, 5751 scache_handle, 5752 1, 5753 alloc_size, 5754 &oam_scache, 5755 BCM_WB_DEFAULT_VERSION, 5756 NULL 5757 ); 5758 if (BCM_FAILURE(rv) 5759 || (NULL == oam_scache)) { 5760 goto cleanup; 5761 } 5762 } else if (BCM_FAILURE(rv)) { 5763 goto cleanup; 5764 } 5765 5766 /* Store the FP groups */ 5767 sal_memcpy(oam_scache, &oc->vfp_group, sizeof(bcm_field_group_t)); 5768 oam_scache += sizeof(bcm_field_group_t); 5769 5770 sal_memcpy(oam_scache, &oc->fp_vp_group, sizeof(bcm_field_group_t)); 5771 oam_scache += sizeof(bcm_field_group_t); 5772 5773 sal_memcpy(oam_scache, &oc->fp_glp_group, sizeof(bcm_field_group_t)); 5774 oam_scache += sizeof(bcm_field_group_t); 5775 5776 sal_memcpy(oam_scache, &group_count, sizeof(int)); 5777 oam_scache += sizeof(int); 5778 5779 for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) 5780 { 5781 sal_memcpy(oam_scache, group_p[grp_idx].name, 5782 BCM_OAM_GROUP_NAME_LENGTH); 5783 5784 oam_scache += BCM_OAM_GROUP_NAME_LENGTH; 5785 } 5786 5787 5788 /* Store logical endpoint indexes 5789 Following is scache allocation for different types of EPs 5790 Rx MEP indexes (16K) 5791 RMEP index (8K) 5792 Tx MEP indexes (2K) 5793 */ 5794 sal_memset(oam_scache, 0, (sizeof (bcm_oam_endpoint_t) * 5795 (oc->rmep_count + oc->lmep_count + oc->ma_idx_count))); 5796 for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) 5797 { 5798 if (group_p[grp_idx].in_use == 1) { 5799 ep_list_p = *(group_p[grp_idx].ep_list); 5800 while (ep_list_p != NULL) { 5801 ep_data = *ep_list_p->ep_data_p; 5802 if (ep_data.type == bcmOAMEndpointTypeEthernet) { 5803 5804 if (ep_data.is_remote) { 5805 sal_memcpy(oam_scache + 5806 sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + 5807 ep_data.remote_index), 5808 &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t)); 5809 5810 } else { 5811 if (ep_data.local_tx_enabled) { 5812 sal_memcpy(oam_scache + 5813 sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + 5814 oc->rmep_count + ep_data.local_tx_index), 5815 &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t)); 5816 5817 } 5818 if (ep_data.local_rx_enabled) { 5819 sal_memcpy(oam_scache + 5820 sizeof(bcm_oam_endpoint_t) * (ep_data.local_rx_index), 5821 &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t)); 5822 5823 } 5824 } 5825 } 5826 ep_list_p = ep_list_p->next; 5827 } 5828 } 5829 } 5830 oam_scache += (sizeof (bcm_oam_endpoint_t) * 5831 (oc->rmep_count + oc->lmep_count + oc->ma_idx_count)); 5832 5833 /*Rx MEP Tx and Rx FP entry numbers for LM/DM*/ 5834 sal_memset(oam_scache, 0, ((sizeof (bcm_field_entry_t) * 3) * 5835 (oc->ma_idx_count))); 5836 for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) 5837 { 5838 if (group_p[grp_idx].in_use == 1) { 5839 ep_list_p = *(group_p[grp_idx].ep_list); 5840 while (ep_list_p != NULL) { 5841 ep_data = *ep_list_p->ep_data_p; 5842 if ((ep_data.type == bcmOAMEndpointTypeEthernet) && 5843 (!(ep_data.is_remote))) { 5844 if ((ep_data.local_rx_enabled) && 5845 ((ep_data.flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) || 5846 (ep_data.flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT))) { 5847 sal_memcpy(oam_scache + 5848 (sizeof(bcm_oam_endpoint_t) * (ep_data.local_rx_index)), 5849 &(ep_data.fp_entry_rx), sizeof (bcm_field_entry_t)); 5850 sal_memcpy(oam_scache + (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count))+ 5851 (sizeof(bcm_oam_endpoint_t) * (ep_data.local_rx_index)), 5852 &(ep_data.fp_entry_tx), sizeof (bcm_field_entry_t)); 5853 sal_memcpy(oam_scache + (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count) * 2)+ 5854 (sizeof(bcm_oam_endpoint_t) * (ep_data.local_rx_index)), 5855 &(ep_data.fp_entry_trunk[0]), sizeof (bcm_field_entry_t)); 5856 } 5857 } 5858 ep_list_p = ep_list_p->next; 5859 } 5860 } 5861 } 5862 oam_scache += (sizeof(bcm_field_entry_t) * 3) * (oc->ma_idx_count); 5863 5864 #if defined (INCLUDE_BHH) 5865 if(soc_feature(unit, soc_feature_bhh)) { 5866 if(oc->ukernel_not_ready == 0) { 5867 sal_memcpy(oam_scache, &(oc->bhh_lm_dm_enable), 5868 sizeof(oc->bhh_lm_dm_enable)); 5869 oam_scache += sizeof(oc->bhh_lm_dm_enable); 5870 5871 if (oc->bhh_lm_dm_enable) { 5872 sal_memcpy(oam_scache, &(oc->bhh_udf_mode), 5873 sizeof(oc->bhh_udf_mode)); 5874 oam_scache += sizeof(oc->bhh_udf_mode); 5875 5876 if (oc->bhh_udf_mode) { 5877 5878 sal_memcpy(oam_scache, &(oc->bhh_label_udf_id), 5879 sizeof(oc->bhh_label_udf_id)); 5880 oam_scache += sizeof(oc->bhh_label_udf_id); 5881 5882 sal_memcpy(oam_scache, &(oc->bhh_ach_udf_id), 5883 sizeof(oc->bhh_ach_udf_id)); 5884 oam_scache += sizeof(oc->bhh_ach_udf_id); 5885 5886 sal_memcpy(oam_scache, &(oc->bhh_opcode_udf_id), 5887 sizeof(oc->bhh_opcode_udf_id)); 5888 oam_scache += sizeof(oc->bhh_opcode_udf_id); 5889 5890 sal_memcpy(oam_scache, &(oc->bhh_udf_pkt_fmt_id), 5891 sizeof(oc->bhh_udf_pkt_fmt_id)); 5892 oam_scache += sizeof(oc->bhh_udf_pkt_fmt_id); 5893 5894 } else { 5895 5896 sal_memcpy(oam_scache, &(oc->bhh_label_qual_id), 5897 sizeof(oc->bhh_label_qual_id)); 5898 oam_scache += sizeof(oc->bhh_label_qual_id); 5899 5900 sal_memcpy(oam_scache, &(oc->bhh_ach_qual_id), 5901 sizeof(oc->bhh_ach_qual_id)); 5902 oam_scache += sizeof(oc->bhh_ach_qual_id); 5903 5904 sal_memcpy(oam_scache, &(oc->bhh_opcode_qual_id), 5905 sizeof(oc->bhh_opcode_qual_id)); 5906 oam_scache += sizeof(oc->bhh_opcode_qual_id); 5907 } 5908 } 5909 } 5910 } 5911 #endif /* INCLUDE_BHH */ 5912 5913 cleanup: 5914 _BCM_OAM_UNLOCK(oc); 5915 return (rv); 5916 } 5917 5918 /* 5919 * Function: 5920 * _bcm_tr3_oam_wb_group_recover 5921 * Purpose: 5922 * Recover OAM group configuratoin. 5923 * Parameters: 5924 * unit - (IN) BCM device number 5925 * stable_size - (IN) OAM module Level2 storage size. 5926 * oam_scache - (IN) Pointer to scache address pointer. 5927 * Returns: 5928 * BCM_E_XXX 5929 */ 5930 STATIC int 5931 _bcm_tr3_oam_wb_group_recover(int unit, int stable_size, uint8 **oam_scache, 5932 int grpal) 5933 { 5934 int index; /* Hw table index. */ 5935 _bcm_oam_group_data_t *group_p; /* Group info pointer. */ 5936 maid_reduction_entry_t maid_entry; /* Group entry info. */ 5937 ma_state_entry_t ma_state_ent; /* Group state info. */ 5938 int maid_reduction_valid = 0; /* Group valid. */ 5939 int ma_state_valid = 0; /* Group state valid. */ 5940 _bcm_oam_control_t *oc; /* Pointer to Control */ 5941 /* structure. */ 5942 int rv; /* Operation return */ 5943 /* status. */ 5944 5945 /* Control lock taken by calling routine. */ 5946 /* Get OAM control structure. */ 5947 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 5948 5949 for (index = 0; index < oc->group_count; index++) { 5950 5951 rv = READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, index, 5952 &maid_entry); 5953 if (BCM_FAILURE(rv)) { 5954 LOG_ERROR(BSL_LS_BCM_OAM, 5955 (BSL_META_U(unit, 5956 "OAM Error: (GID=%d) MAID_REDUCTION table read" 5957 " failed - %s.\n"), index, bcm_errmsg(rv))); 5958 goto cleanup; 5959 } 5960 5961 rv = READ_MA_STATEm(unit, MEM_BLOCK_ANY, index, &ma_state_ent); 5962 if (BCM_FAILURE(rv)) { 5963 LOG_ERROR(BSL_LS_BCM_OAM, 5964 (BSL_META_U(unit, 5965 "OAM Error: (GID=%d) MA_STATE table read" 5966 " failed - %s.\n"), index, bcm_errmsg(rv))); 5967 goto cleanup; 5968 } 5969 5970 maid_reduction_valid 5971 = soc_MAID_REDUCTIONm_field32_get(unit, &maid_entry, VALIDf); 5972 5973 ma_state_valid 5974 = soc_MA_STATEm_field32_get(unit, &ma_state_ent, VALIDf); 5975 5976 if (maid_reduction_valid || ma_state_valid) { 5977 5978 /* Entry must be valid in both the tables, else return error. */ 5979 if (!maid_reduction_valid || !ma_state_valid) { 5980 rv = BCM_E_INTERNAL; 5981 goto cleanup; 5982 } 5983 5984 /* Get the group memory pointer. */ 5985 group_p = &oc->group_info[index]; 5986 5987 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) { 5988 5989 /* Set group name as zeros. */ 5990 sal_memset(group_p->name, 0, BCM_OAM_GROUP_NAME_LENGTH); 5991 5992 } else { 5993 if (grpal) { 5994 sal_memcpy(group_p->name, 5995 *oam_scache + index * BCM_OAM_GROUP_NAME_LENGTH, 5996 BCM_OAM_GROUP_NAME_LENGTH); 5997 } else { 5998 /* Get the group name from stored info. */ 5999 sal_memcpy(group_p->name, *oam_scache, BCM_OAM_GROUP_NAME_LENGTH); 6000 *oam_scache = (*oam_scache + BCM_OAM_GROUP_NAME_LENGTH); 6001 } 6002 } 6003 6004 /* Reserve the group index. */ 6005 rv = shr_idxres_list_reserve(oc->group_pool, index, index); 6006 if (BCM_FAILURE(rv)) { 6007 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 6008 LOG_ERROR(BSL_LS_BCM_OAM, 6009 (BSL_META_U(unit, 6010 "OAM Error: (GID=%d) Index reserve " 6011 " failed - %s.\n"), index, bcm_errmsg(rv))); 6012 goto cleanup; 6013 } 6014 6015 /* Create the linked list to maintain group endpoint information. */ 6016 _BCM_OAM_ALLOC((group_p->ep_list), _bcm_oam_ep_list_t *, 6017 sizeof(_bcm_oam_ep_list_t *), "EP list head"); 6018 if (NULL == group_p->ep_list) { 6019 rv = BCM_E_MEMORY; 6020 goto cleanup; 6021 } 6022 6023 /* Initialize head node.*/ 6024 *group_p->ep_list = NULL; 6025 group_p->in_use = 1; 6026 } 6027 } 6028 6029 return (BCM_E_NONE); 6030 6031 cleanup: 6032 6033 if (BCM_E_EXISTS 6034 == shr_idxres_list_elem_state(oc->group_pool, index)) { 6035 shr_idxres_list_free(oc->group_pool, index); 6036 } 6037 6038 return (rv); 6039 6040 } 6041 6042 /* 6043 * Function: 6044 * _bcm_tr3_oam_rmep_recover 6045 * Purpose: 6046 * Recover OAM remote endpoint configuration. 6047 * Parameters: 6048 * unit - (IN) BCM device number 6049 * index - (IN) Remote MEP hardware index. 6050 * l3_entry - (IN) RMEP view table entry pointer. 6051 * Returns: 6052 * BCM_E_XXX 6053 */ 6054 STATIC int 6055 _bcm_tr3_oam_rmep_recover(int unit, int index, uint32 *l3_entry, uint8 **scache, 6056 uint16 recovered_ver) 6057 { 6058 rmep_entry_t rmep_entry; /* Remote table entry. */ 6059 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 6060 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 6061 int rv; /* Operation return status. */ 6062 _bcm_gport_dest_t gport_dest; /* Gport specification. */ 6063 bcm_gport_t gport; /* Gport value. */ 6064 uint8 source_type; /* Virtual or Logical Port. */ 6065 uint16 glp; /* Generic logical port value. */ 6066 bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information. */ 6067 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 6068 int ep_id; /* Endpoint ID. */ 6069 soc_mem_t mem; /* L3 entry memory */ 6070 int rmep_index; /* Index of RMEP table */ 6071 6072 LOG_DEBUG(BSL_LS_BCM_OAM, 6073 (BSL_META_U(unit, 6074 "OAM Info: _bcm_tr3_oam_rmep_recover.\n"))); 6075 /* 6076 * Get OAM control structure. 6077 * Note: Lock taken by calling routine. 6078 */ 6079 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 6080 6081 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 6082 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 6083 mem = L3_ENTRY_IPV4_UNICASTm; 6084 } else { 6085 mem = L3_ENTRY_1m; 6086 } 6087 6088 if (recovered_ver >= BCM_WB_VERSION_1_2) { 6089 /* Recover EP index from scache */ 6090 rmep_index = soc_mem_field32_get(unit, mem, l3_entry, RMEP__RMEP_PTRf); 6091 sal_memcpy(&ep_id, *scache + (sizeof(bcm_oam_endpoint_t) * 6092 (oc->ma_idx_count + rmep_index)), sizeof(bcm_oam_endpoint_t)); 6093 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id); 6094 if (BCM_FAILURE(rv)) { 6095 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 6096 LOG_ERROR(BSL_LS_BCM_OAM, 6097 (BSL_META_U(unit, 6098 "OAM Error: (EP_ID=%d) Index reserve " 6099 " failed - %s.\n"), ep_id, bcm_errmsg(rv))); 6100 return (rv); 6101 } 6102 6103 } else { 6104 6105 /* Allocate the next available endpoint index. */ 6106 rv = shr_idxres_list_alloc(oc->mep_pool, 6107 (shr_idxres_element_t *)&ep_id); 6108 if (BCM_FAILURE(rv)) { 6109 LOG_ERROR(BSL_LS_BCM_OAM, 6110 (BSL_META_U(unit, 6111 "OAM Error: Endpoint alloc (EP=%d) - %s.\n"), 6112 ep_id, bcm_errmsg(rv))); 6113 return (rv); 6114 } 6115 } 6116 6117 h_data_p = &oc->oam_hash_data[ep_id]; 6118 6119 /* 6120 * Clear the hash data element contents before 6121 * storing values. 6122 */ 6123 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 6124 6125 /* Get RMEP table index from LMEP view entry. */ 6126 h_data_p->remote_index 6127 = soc_mem_field32_get(unit, mem, l3_entry, RMEP__RMEP_PTRf); 6128 6129 /* Get RMEP table entry contents. */ 6130 rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index, &rmep_entry); 6131 if (BCM_FAILURE(rv)) { 6132 LOG_ERROR(BSL_LS_BCM_OAM, 6133 (BSL_META_U(unit, 6134 "OAM Error: RMEP (index=%d) read failed - %s.\n"), 6135 h_data_p->remote_index, bcm_errmsg(rv))); 6136 goto cleanup; 6137 } 6138 6139 /* Has to be a valid RMEP, return error otherwise. */ 6140 if (!soc_RMEPm_field32_get(unit, &rmep_entry, VALIDf)) { 6141 rv = BCM_E_INTERNAL; 6142 goto cleanup; 6143 } 6144 6145 h_data_p->ep_id = ep_id; 6146 6147 h_data_p->is_remote = 1; 6148 6149 h_data_p->flags |= BCM_OAM_ENDPOINT_REMOTE; 6150 6151 h_data_p->group_index 6152 = soc_RMEPm_field32_get(unit, &rmep_entry, MAID_INDEXf); 6153 6154 h_data_p->period 6155 = _bcm_tr3_oam_ccm_hw_encode_to_msecs 6156 ((int) soc_RMEPm_field32_get(unit, &rmep_entry, 6157 RMEP_RECEIVED_CCMf)); 6158 6159 h_data_p->name 6160 = soc_mem_field32_get(unit, mem, l3_entry, RMEP__MEPIDf); 6161 6162 h_data_p->level 6163 = soc_mem_field32_get(unit, mem, l3_entry, RMEP__MDLf); 6164 6165 h_data_p->vlan 6166 = soc_mem_field32_get(unit, mem, l3_entry, RMEP__VIDf); 6167 6168 h_data_p->local_tx_index = _BCM_OAM_INVALID_INDEX; 6169 h_data_p->local_rx_index = _BCM_OAM_INVALID_INDEX; 6170 6171 if (SOC_MEM_FIELD_VALID(unit, mem, RMEP__SOURCE_TYPEf)) { 6172 source_type 6173 = soc_mem_field32_get(unit, mem, l3_entry, RMEP__SOURCE_TYPEf); 6174 } else { 6175 source_type = 0; 6176 } 6177 glp = soc_mem_field32_get(unit, mem, l3_entry, RMEP__SGLPf); 6178 6179 /* Check if virtual port type. */ 6180 if (1 == source_type) { 6181 /* 6182 * Virtual port type, construct gport value from VP. 6183 */ 6184 h_data_p->vp = glp; 6185 #if defined(INCLUDE_L3) 6186 if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMim)) { 6187 BCM_GPORT_MIM_PORT_ID_SET(h_data_p->gport, h_data_p->vp); 6188 6189 } else if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMpls)) { 6190 6191 BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp); 6192 6193 } else { 6194 LOG_ERROR(BSL_LS_BCM_OAM, 6195 (BSL_META_U(unit, 6196 "OAM Error: Invalid Virtual Port (SVP=%d) " 6197 "- %s.\n"), h_data_p->vp, bcm_errmsg(BCM_E_INTERNAL))); 6198 rv = BCM_E_INTERNAL; 6199 goto cleanup; 6200 } 6201 #endif 6202 } else { 6203 /* 6204 * Generic logical port type, construct gport from GLP. 6205 */ 6206 h_data_p->sglp = glp; 6207 6208 _bcm_gport_dest_t_init(&gport_dest); 6209 6210 if (_BCM_OAM_GLP_TRUNK_BIT_GET(unit, glp)) { 6211 gport_dest.tgid = _BCM_OAM_GLP_TRUNK_ID_GET(unit, glp); 6212 gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 6213 } else { 6214 gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 6215 gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(unit, glp); 6216 gport_dest.port = _BCM_OAM_GLP_PORT_GET(unit, glp); 6217 } 6218 6219 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport); 6220 if (BCM_FAILURE(rv)) { 6221 LOG_ERROR(BSL_LS_BCM_OAM, 6222 (BSL_META_U(unit, 6223 "OAM Error: Gport construct failed - %s.\n"), 6224 bcm_errmsg(rv))); 6225 goto cleanup; 6226 } 6227 6228 h_data_p->gport = gport; 6229 } 6230 6231 rv = shr_idxres_list_reserve(oc->rmep_pool, 6232 h_data_p->remote_index, 6233 h_data_p->remote_index); 6234 if (BCM_FAILURE(rv)) { 6235 LOG_ERROR(BSL_LS_BCM_OAM, 6236 (BSL_META_U(unit, 6237 "OAM Error: (RMEP=%d) Index reserve failed - %s.\n"), 6238 h_data_p->remote_index, bcm_errmsg(rv))); 6239 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 6240 goto cleanup; 6241 } 6242 6243 h_data_p->in_use = 1; 6244 6245 rv = _bcm_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id); 6246 if (BCM_FAILURE(rv)) { 6247 goto cleanup; 6248 } 6249 6250 rv = _bcm_tr3_oam_endpoint_alloc(&ep_info); 6251 if (BCM_FAILURE(rv)) { 6252 _bcm_oam_group_ep_list_remove(unit, h_data_p->group_index, ep_id); 6253 goto cleanup; 6254 } 6255 6256 bcm_oam_endpoint_info_t_init(ep_info); 6257 6258 /* Set up endpoint information for key construction. */ 6259 ep_info->group = h_data_p->group_index; 6260 ep_info->name = h_data_p->name; 6261 ep_info->gport = h_data_p->gport; 6262 ep_info->level = h_data_p->level; 6263 ep_info->vlan = h_data_p->vlan; 6264 ep_info->id= h_data_p->ep_id; 6265 6266 /* Calculate hash key for hash table insert operation. */ 6267 _bcm_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 6268 6269 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 6270 if (BCM_FAILURE(rv)) { 6271 LOG_ERROR(BSL_LS_BCM_OAM, 6272 (BSL_META_U(unit, 6273 "OAM Error: Hash table insert failed " 6274 "EP=%d %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 6275 _bcm_oam_group_ep_list_remove(unit, h_data_p->group_index, ep_id); 6276 goto cleanup; 6277 } else { 6278 LOG_DEBUG(BSL_LS_BCM_OAM, 6279 (BSL_META_U(unit, 6280 "OAM Info: Hash Tbl (EP=%d) inserted" 6281 " - %s.\n"), ep_id, bcm_errmsg(rv))); 6282 } 6283 6284 /* Add the H/w index to logical index mapping for RMEP */ 6285 oc->remote_endpoints[h_data_p->remote_index] = ep_info->id; 6286 6287 sal_free(ep_info); 6288 ep_info = NULL; 6289 6290 LOG_DEBUG(BSL_LS_BCM_OAM, 6291 (BSL_META_U(unit, 6292 "OAM Info: _bcm_tr3_oam_rmep_recover - done.\n"))); 6293 6294 return (rv); 6295 6296 cleanup: 6297 6298 if (NULL != ep_info) { 6299 sal_free(ep_info); 6300 } 6301 6302 /* Release the endpoint ID if in use. */ 6303 if (BCM_E_EXISTS 6304 == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) { 6305 shr_idxres_list_free(oc->mep_pool, ep_id); 6306 } 6307 6308 /* Release the remote index if in use. */ 6309 if ((h_data_p->in_use == 1) 6310 && (BCM_E_EXISTS 6311 == shr_idxres_list_elem_state(oc->rmep_pool, 6312 h_data_p->remote_index))) { 6313 shr_idxres_list_free(oc->rmep_pool, h_data_p->remote_index); 6314 6315 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 6316 } 6317 6318 LOG_DEBUG(BSL_LS_BCM_OAM, 6319 (BSL_META_U(unit, 6320 "OAM Info: _bcm_tr3_oam_rmep_recover - error_done.\n"))); 6321 return (rv); 6322 } 6323 6324 /* 6325 * Function: 6326 * _bcm_tr3_oam_lmep_rx_config_recover 6327 * Purpose: 6328 * Recover OAM local endpoint Rx configuration. 6329 * Parameters: 6330 * unit - (IN) BCM device number 6331 * index - (IN) Remote MEP hardware index. 6332 * l3_entry - (IN) LMEP view table entry pointer. 6333 * Returns: 6334 * BCM_E_XXX 6335 */ 6336 STATIC int 6337 _bcm_tr3_oam_lmep_rx_config_recover(int unit, int index, uint32 *l3_entry, 6338 uint8 **scache, uint16 recovered_ver) 6339 { 6340 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 6341 ma_index_entry_t ma_idx_entry; /* IA_INDEX table entry. */ 6342 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 6343 uint8 mdl_bitmap; /* Endpoint domain level bitmap. */ 6344 uint8 mdl; /* Maintenance domain level. */ 6345 int rv; /* Operation return status. */ 6346 _bcm_gport_dest_t gport_dest; /* Gport specification. */ 6347 bcm_gport_t gport; /* Gport value. */ 6348 uint8 source_type; /* Virtual or Logical Port. */ 6349 uint16 glp; /* Generic logical port value. */ 6350 uint32 ma_base_idx; 6351 int ep_id; /* Endpoint ID. */ 6352 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 6353 bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information. */ 6354 soc_mem_t mem; /* L3 entry memory */ 6355 int ma_idx; /* MA_TABLE index */ 6356 6357 LOG_DEBUG(BSL_LS_BCM_OAM, 6358 (BSL_META_U(unit, 6359 "OAM Info: _bcm_tr3_oam_lmep_rx_config_recover.\n"))); 6360 /* 6361 * Get OAM control structure. 6362 * Note: Lock taken by calling routine. 6363 */ 6364 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 6365 6366 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 6367 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 6368 mem = L3_ENTRY_IPV4_UNICASTm; 6369 } else { 6370 mem = L3_ENTRY_1m; 6371 } 6372 6373 mdl_bitmap 6374 = soc_mem_field32_get(unit, mem, l3_entry, LMEP__MDL_BITMAPf); 6375 6376 for (mdl = 0; mdl < _BCM_OAM_EP_LEVEL_COUNT; mdl++) { 6377 6378 if (mdl_bitmap & (1 << mdl)) { 6379 if (recovered_ver >= BCM_WB_VERSION_1_2) { 6380 ma_base_idx = soc_mem_field32_get(unit, mem, l3_entry, 6381 LMEP__MA_BASE_PTRf); 6382 ma_idx = (ma_base_idx << _BCM_OAM_EP_LEVEL_BIT_COUNT) + mdl; 6383 sal_memcpy(&ep_id, *(scache) + sizeof(bcm_oam_endpoint_t) * 6384 ma_idx, sizeof(bcm_oam_endpoint_t)); 6385 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id); 6386 if (BCM_FAILURE(rv)) { 6387 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 6388 LOG_ERROR(BSL_LS_BCM_OAM, 6389 (BSL_META_U(unit, 6390 "OAM Error: (EP_ID=%d) Index reserve " 6391 " failed - %s.\n"), ep_id, bcm_errmsg(rv))); 6392 return (rv); 6393 } 6394 6395 } else { 6396 /* Allocate the next available endpoint index. */ 6397 rv = shr_idxres_list_alloc(oc->mep_pool, 6398 (shr_idxres_element_t *)&ep_id); 6399 if (BCM_FAILURE(rv)) { 6400 LOG_ERROR(BSL_LS_BCM_OAM, 6401 (BSL_META_U(unit, 6402 "OAM Error: Endpoint alloc (EP=%d) - %s.\n"), 6403 ep_id, bcm_errmsg(rv))); 6404 goto cleanup; 6405 } 6406 } 6407 6408 h_data_p = &oc->oam_hash_data[ep_id]; 6409 6410 /* 6411 * Clear the hash data element contents before 6412 * storing values. 6413 */ 6414 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 6415 6416 _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p); 6417 6418 h_data_p->ep_id = ep_id; 6419 6420 h_data_p->local_rx_index 6421 = ((soc_mem_field32_get(unit, mem, l3_entry, 6422 LMEP__MA_BASE_PTRf) << _BCM_OAM_EP_LEVEL_BIT_COUNT) 6423 | mdl); 6424 6425 rv = READ_MA_INDEXm 6426 (unit, MEM_BLOCK_ANY, h_data_p->local_rx_index, 6427 &ma_idx_entry); 6428 if (BCM_FAILURE(rv)) { 6429 LOG_ERROR(BSL_LS_BCM_OAM, 6430 (BSL_META_U(unit, 6431 "OAM Error: MA_INDEX (index:%d) read failed -" 6432 " %s.\n"), h_data_p->local_rx_index, 6433 bcm_errmsg(rv))); 6434 goto cleanup; 6435 } 6436 6437 h_data_p->in_use = 1; 6438 6439 h_data_p->is_remote = 0; 6440 6441 h_data_p->local_rx_enabled = 1; 6442 6443 h_data_p->flags |= BCM_OAM_ENDPOINT_CCM_RX; 6444 6445 h_data_p->group_index 6446 = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf); 6447 6448 h_data_p->profile_index 6449 = soc_MA_INDEXm_field32_get 6450 (unit, &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf); 6451 6452 rv = soc_profile_mem_reference(unit, &oc->oam_opcode_control_profile, 6453 h_data_p->profile_index, 1); 6454 6455 h_data_p->name = 0xffff; 6456 6457 h_data_p->level = mdl; 6458 6459 h_data_p->vlan 6460 = soc_mem_field32_get(unit, mem, l3_entry, LMEP__VIDf); 6461 6462 if (SOC_MEM_FIELD_VALID(unit, mem, LMEP__SOURCE_TYPEf)) { 6463 source_type 6464 = soc_mem_field32_get(unit, mem, l3_entry, LMEP__SOURCE_TYPEf); 6465 } else { 6466 source_type = 0; 6467 } 6468 6469 glp = soc_mem_field32_get(unit, mem, l3_entry, LMEP__SGLPf); 6470 6471 6472 /* Check if virtual port type. */ 6473 if (1 == source_type) { 6474 /* 6475 * Virtual port type, construct gport value from VP. 6476 */ 6477 h_data_p->vp = glp; 6478 #if defined(INCLUDE_L3) 6479 if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMim)) { 6480 6481 BCM_GPORT_MIM_PORT_ID_SET(h_data_p->gport, h_data_p->vp); 6482 6483 } else if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMpls)) { 6484 6485 BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp); 6486 6487 } else { 6488 LOG_ERROR(BSL_LS_BCM_OAM, 6489 (BSL_META_U(unit, 6490 "OAM Error: Invalid Virtual Port (SVP=%d)" 6491 " - %s.\n"), h_data_p->vp, 6492 bcm_errmsg(BCM_E_INTERNAL))); 6493 return (BCM_E_INTERNAL); 6494 } 6495 #endif 6496 } else { 6497 /* 6498 * Generic logical port type, construct gport from GLP. 6499 */ 6500 h_data_p->sglp = glp; 6501 6502 _bcm_gport_dest_t_init(&gport_dest); 6503 6504 if (_BCM_OAM_GLP_TRUNK_BIT_GET(unit, glp)) { 6505 gport_dest.tgid = _BCM_OAM_GLP_TRUNK_ID_GET(unit, glp); 6506 gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 6507 } else { 6508 gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 6509 gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(unit, glp); 6510 gport_dest.port = _BCM_OAM_GLP_PORT_GET(unit, glp); 6511 } 6512 6513 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport); 6514 if (BCM_FAILURE(rv)) { 6515 LOG_ERROR(BSL_LS_BCM_OAM, 6516 (BSL_META_U(unit, 6517 "OAM Error: Gport construct failed -" 6518 " %s.\n"), bcm_errmsg(rv))); 6519 goto cleanup; 6520 } 6521 6522 h_data_p->gport = gport; 6523 } 6524 h_data_p->fp_entry_tx = -1; 6525 h_data_p->fp_entry_rx = -1; 6526 h_data_p->fp_entry_trunk[0] = -1; 6527 ma_base_idx = soc_mem_field32_get(unit, mem, l3_entry, 6528 LMEP__MA_BASE_PTRf); 6529 ma_base_idx = ma_base_idx << _BCM_OAM_EP_LEVEL_BIT_COUNT; 6530 6531 rv = shr_idxres_list_reserve(oc->ma_idx_pool, 6532 ma_base_idx, 6533 ma_base_idx + 7); 6534 6535 /* ma_index for all 8 levels is reserved during first endpoint 6536 recovery as baseindex is common for all 8 levels, 6537 as such during second endpoint recovery with different 6538 level BCM_E_RESOURCE is expected and not an error 6539 */ 6540 if ( (BCM_FAILURE(rv)) && (rv != BCM_E_RESOURCE) ) { 6541 LOG_ERROR(BSL_LS_BCM_OAM, 6542 (BSL_META_U(unit, 6543 "OAM Error: (RMEP=%d) Index reserve failed" 6544 " - %s.\n"), h_data_p->remote_index, 6545 bcm_errmsg(rv))); 6546 goto cleanup; 6547 } 6548 6549 rv = _bcm_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id); 6550 if (BCM_FAILURE(rv)) { 6551 goto cleanup; 6552 } 6553 6554 rv = _bcm_tr3_oam_endpoint_alloc(&ep_info); 6555 if (BCM_FAILURE(rv)) { 6556 _bcm_oam_group_ep_list_remove(unit, 6557 h_data_p->group_index, 6558 ep_id); 6559 goto cleanup; 6560 } 6561 6562 bcm_oam_endpoint_info_t_init(ep_info); 6563 6564 /* Set up endpoint information for key construction. */ 6565 ep_info->group = h_data_p->group_index; 6566 ep_info->name = h_data_p->name; 6567 ep_info->gport = h_data_p->gport; 6568 ep_info->level = h_data_p->level; 6569 ep_info->vlan = h_data_p->vlan; 6570 6571 /* 6572 * Calculate hash key for hash table insert 6573 * operation. 6574 */ 6575 _bcm_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 6576 6577 sal_free(ep_info); 6578 ep_info = NULL; 6579 6580 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 6581 if (BCM_FAILURE(rv)) { 6582 LOG_ERROR(BSL_LS_BCM_OAM, 6583 (BSL_META_U(unit, 6584 "OAM Error: Hash table insert" 6585 " (EP=%d) failed - %s.\n"), 6586 h_data_p->ep_id, bcm_errmsg(rv))); 6587 6588 _bcm_oam_group_ep_list_remove(unit, 6589 h_data_p->group_index, 6590 ep_id); 6591 goto cleanup; 6592 } else { 6593 LOG_DEBUG(BSL_LS_BCM_OAM, 6594 (BSL_META_U(unit, 6595 "OAM Info: Hash Tbl (EP=%d)" 6596 " inserted - %s.\n"), ep_id, 6597 bcm_errmsg(rv))); 6598 } 6599 } 6600 } 6601 6602 LOG_DEBUG(BSL_LS_BCM_OAM, 6603 (BSL_META_U(unit, 6604 "OAM Info: _bcm_tr3_oam_lmep_rx_config_recover" 6605 " - done.\n"))); 6606 return (BCM_E_NONE); 6607 6608 cleanup: 6609 6610 if (NULL != ep_info) { 6611 sal_free(ep_info); 6612 } 6613 6614 if (BCM_E_EXISTS 6615 == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) { 6616 shr_idxres_list_free(oc->mep_pool, ep_id); 6617 } 6618 6619 if (NULL != h_data_p 6620 && (BCM_E_EXISTS 6621 == shr_idxres_list_elem_state(oc->ma_idx_pool, 6622 h_data_p->local_rx_index))) { 6623 6624 shr_idxres_list_free(oc->ma_idx_pool, h_data_p->local_rx_index); 6625 6626 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 6627 } 6628 6629 LOG_DEBUG(BSL_LS_BCM_OAM, 6630 (BSL_META_U(unit, 6631 "OAM Info: _bcm_tr3_oam_lmep_rx_config_recover" 6632 " - error_done.\n"))); 6633 return (rv); 6634 } 6635 6636 /* 6637 * Function: 6638 * _bcm_tr3_oam_lmep_tx_config_recover 6639 * Purpose: 6640 * Recover OAM local endpoint Tx configuration. 6641 * Parameters: 6642 * unit - (IN) BCM device number 6643 * Returns: 6644 * BCM_E_XXX 6645 */ 6646 STATIC int 6647 _bcm_tr3_oam_lmep_tx_config_recover(int unit, uint8 **scache, 6648 uint16 recovered_ver) 6649 { 6650 _bcm_gport_dest_t gport_dest; /* Gport specification. */ 6651 bcm_gport_t gport; /* Gport value. */ 6652 int index = 0; /* Hardware index. */ 6653 lmep_entry_t lmep_entry; /* LMEP table entry buffer. */ 6654 maid_reduction_entry_t maid_red_ent; /* MAID_REDUCTION table entry buf. */ 6655 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 6656 _bcm_oam_group_data_t *g_info_p; /* Group information pointer. */ 6657 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 6658 bcm_module_t modid; /* Module ID. */ 6659 bcm_port_t port_id; /* Port ID. */ 6660 bcm_trunk_t trunk_id; /* Trunk ID. */ 6661 uint32 grp_idx; /* Group index. */ 6662 uint16 glp,sglp; /* Generic logical port. */ 6663 uint16 vlan; /* VLAN ID. */ 6664 uint8 level; /* Maintenance domain level. */ 6665 _bcm_oam_ep_list_t *cur; /* Current head node pointer. */ 6666 int ep_id = -1; /* Endpoint ID. */ 6667 uint8 match_found = 0; /* Matching endpoint found. */ 6668 int rv; /* Operation return status. */ 6669 bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information. */ 6670 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 6671 _bcm_oam_hash_data_t *sh_data_p = NULL; /* Endpoint hash data pointer. */ 6672 uint32 ccm_period = 0; 6673 int trunk_index = -1; 6674 #ifdef BCM_HURRICANE2_SUPPORT 6675 uint32 rval = 0; 6676 uint8 tx_disable = 0; 6677 #endif /* BCM_HURRICANE2_SUPPORT */ 6678 6679 LOG_DEBUG(BSL_LS_BCM_OAM, 6680 (BSL_META_U(unit, 6681 "OAM Info: _bcm_tr3_oam_lmep_tx_config_recover.\n"))); 6682 6683 /* 6684 * Get OAM control structure. 6685 * Note: Lock taken by calling routine. 6686 */ 6687 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 6688 6689 rv = _bcm_tr3_oam_endpoint_alloc(&ep_info); 6690 if (BCM_FAILURE(rv)) { 6691 return (rv); 6692 } 6693 6694 /* 6695 * At this point, Remote MEP and Local MEP Rx config has been 6696 * recovered. Now, recover the Tx config for Local MEPs. 6697 */ 6698 #ifdef BCM_HURRICANE2_SUPPORT 6699 rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 1, &tx_disable); 6700 if (BCM_FAILURE(rv)) { 6701 LOG_ERROR(BSL_LS_BCM_OAM, 6702 (BSL_META_U(unit, 6703 "OAM Error: in _bcm_oam_modify_oam_tx_control \n"))); 6704 goto cleanup; 6705 } 6706 #endif /* BCM_HURRICANE2_SUPPORT */ 6707 6708 for (index = 0; index < oc->lmep_count; index++) { 6709 6710 /* Get the LMEP table entry. */ 6711 rv = READ_LMEPm(unit, MEM_BLOCK_ANY, index, &lmep_entry); 6712 if (BCM_FAILURE(rv)) { 6713 LOG_ERROR(BSL_LS_BCM_OAM, 6714 (BSL_META_U(unit, 6715 "OAM Error: LMEP table read (index=%d) failed " 6716 "- %s.\n"), index, bcm_errmsg(rv))); 6717 goto cleanup; 6718 } 6719 6720 grp_idx = soc_LMEPm_field32_get(unit, &lmep_entry, MAID_INDEXf); 6721 ccm_period = _bcm_tr3_oam_ccm_hw_encode_to_msecs 6722 ((int)soc_LMEPm_field32_get(unit, &lmep_entry, 6723 CCM_INTERVALf)); 6724 if (ccm_period == BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) { 6725 continue; 6726 } 6727 6728 rv = READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, grp_idx, &maid_red_ent); 6729 if (BCM_FAILURE(rv)) { 6730 LOG_ERROR(BSL_LS_BCM_OAM, 6731 (BSL_META_U(unit, 6732 "OAM Error: MAID_REDU read (GID=%d) failed " 6733 "- %s.\n"), grp_idx, bcm_errmsg(rv))); 6734 goto cleanup; 6735 } 6736 6737 if (soc_MAID_REDUCTIONm_field32_get(unit, &maid_red_ent, VALIDf)) { 6738 6739 /* Get pointer to group memory. */ 6740 g_info_p = &oc->group_info[grp_idx]; 6741 6742 vlan = soc_LMEPm_field32_get(unit, &lmep_entry, VLAN_IDf); 6743 6744 glp = soc_LMEPm_field32_get(unit, &lmep_entry, DESTf); 6745 6746 level = soc_LMEPm_field32_get(unit, &lmep_entry, MDLf); 6747 6748 modid = _BCM_OAM_DGLP_MODULE_ID_GET(glp); 6749 6750 port_id = _BCM_OAM_GLP_PORT_GET(unit, glp); 6751 6752 trunk_id = BCM_TRUNK_INVALID; 6753 rv = bcm_esw_trunk_find(unit, modid, port_id, &trunk_id); 6754 if (BCM_FAILURE(rv) 6755 && (BCM_E_NOT_FOUND != rv)) { 6756 goto cleanup; 6757 } 6758 6759 _bcm_gport_dest_t_init(&gport_dest); 6760 6761 if (BCM_TRUNK_INVALID != trunk_id) { 6762 gport_dest.tgid = trunk_id; 6763 gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 6764 _BCM_TR3_OAM_MOD_PORT_TO_GLP(unit, -1, 6765 -1, 1, gport_dest.tgid, sglp); 6766 6767 rv = _bcm_esw_oam_lmep_tx_trunk_config_recover(unit, 6768 trunk_id, 6769 port_id, 6770 &trunk_index); 6771 6772 if(BCM_FAILURE(rv)) { 6773 goto cleanup; 6774 } 6775 } else { 6776 gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 6777 gport_dest.modid = _BCM_OAM_DGLP_MODULE_ID_GET(glp); 6778 gport_dest.port = _BCM_OAM_GLP_PORT_GET(unit, glp); 6779 _BCM_TR3_OAM_MOD_PORT_TO_GLP(unit, gport_dest.modid, 6780 gport_dest.port, 0, -1, sglp); 6781 } 6782 6783 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport); 6784 if (BCM_FAILURE(rv)) { 6785 LOG_ERROR(BSL_LS_BCM_OAM, 6786 (BSL_META_U(unit, 6787 "OAM Error: Gport construct failed" 6788 " - %s.\n"), bcm_errmsg(rv))); 6789 goto cleanup; 6790 } 6791 6792 /* Get the endpoint list head pointer. */ 6793 cur = *(g_info_p->ep_list); 6794 if (NULL != cur) { 6795 while (NULL != cur) { 6796 h_data_p = cur->ep_data_p; 6797 if (NULL == h_data_p) { 6798 LOG_ERROR(BSL_LS_BCM_OAM, 6799 (BSL_META_U(unit, 6800 "OAM Error: Group (GID=%d) NULL" 6801 " endpoint list.\n"), grp_idx)); 6802 rv = BCM_E_INTERNAL; 6803 goto cleanup; 6804 } 6805 6806 if (vlan == h_data_p->vlan 6807 && gport == h_data_p->gport 6808 && level == h_data_p->level 6809 && 1 == h_data_p->local_rx_enabled) { 6810 match_found = 1; 6811 break; 6812 } 6813 cur = cur->next; 6814 } 6815 } 6816 6817 if (1 == match_found) { 6818 6819 bcm_oam_endpoint_info_t_init(ep_info); 6820 6821 /* Set up endpoint information for key construction. */ 6822 ep_info->group = h_data_p->group_index; 6823 ep_info->name = h_data_p->name; 6824 ep_info->gport = h_data_p->gport; 6825 ep_info->level = h_data_p->level; 6826 ep_info->vlan = h_data_p->vlan; 6827 ep_info->flags = h_data_p->flags; 6828 /* 6829 * Calculate hash key for hash table insert 6830 * operation. 6831 */ 6832 _bcm_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 6833 6834 _BCM_OAM_ALLOC(sh_data_p, _bcm_oam_hash_data_t, 6835 sizeof(_bcm_oam_hash_data_t), "Hash data"); 6836 6837 if (NULL == sh_data_p) { 6838 goto cleanup; 6839 } 6840 6841 /* 6842 * Delete insert done by Local Rx endpoint recovery code. 6843 * Endpoint name has been recovered and will result 6844 * in a different hash index. 6845 */ 6846 rv = shr_htb_find(oc->ma_mep_htbl, hash_key, 6847 (shr_htb_data_t *)sh_data_p, 1); 6848 if (BCM_E_NOT_FOUND == rv) { 6849 goto cleanup; 6850 } 6851 6852 sal_free(sh_data_p); 6853 sh_data_p = NULL; 6854 6855 } else { 6856 6857 if (recovered_ver >= BCM_WB_VERSION_1_2) { 6858 6859 sal_memcpy(&ep_id, *(scache) + sizeof(bcm_oam_endpoint_t) * 6860 (oc->rmep_count + oc->ma_idx_count + index), 6861 sizeof(bcm_oam_endpoint_t)); 6862 6863 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id); 6864 if (BCM_FAILURE(rv)) { 6865 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 6866 LOG_ERROR(BSL_LS_BCM_OAM, 6867 (BSL_META_U(unit, 6868 "OAM Error: (EP_ID=%d) Index reserve " 6869 " failed - %s.\n"), ep_id, bcm_errmsg(rv))); 6870 goto cleanup; 6871 } 6872 } else { 6873 /* Allocate the next available endpoint index. */ 6874 rv = shr_idxres_list_alloc(oc->mep_pool, 6875 (shr_idxres_element_t *)&ep_id); 6876 if (BCM_FAILURE(rv)) { 6877 LOG_ERROR(BSL_LS_BCM_OAM, 6878 (BSL_META_U(unit, 6879 "OAM Error: Endpoint alloc (EP=%d)" 6880 " - %s.\n"), ep_id, bcm_errmsg(rv))); 6881 goto cleanup; 6882 } 6883 } 6884 6885 h_data_p = &oc->oam_hash_data[ep_id]; 6886 6887 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 6888 6889 _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p); 6890 6891 rv = _bcm_oam_group_ep_list_add(unit, grp_idx, ep_id); 6892 if (BCM_FAILURE(rv)) { 6893 LOG_ERROR(BSL_LS_BCM_OAM, 6894 (BSL_META_U(unit, 6895 "OAM Error: Adding (EP=%d)" 6896 " to (GID=%d) failed - %s.\n"), 6897 ep_id, grp_idx, bcm_errmsg(rv))); 6898 goto cleanup; 6899 } 6900 6901 h_data_p->ep_id = ep_id; 6902 h_data_p->group_index = grp_idx; 6903 h_data_p->local_rx_enabled = 0; 6904 h_data_p->vlan = vlan; 6905 h_data_p->sglp = sglp; 6906 h_data_p->dglp = glp; 6907 h_data_p->gport = gport; 6908 h_data_p->level = level; 6909 } 6910 6911 h_data_p->is_remote = 0; 6912 h_data_p->local_tx_enabled = 1; 6913 h_data_p->local_tx_index = index; 6914 h_data_p->name 6915 = soc_LMEPm_field32_get(unit, &lmep_entry, MEPIDf); 6916 6917 h_data_p->period = _bcm_tr3_oam_ccm_hw_encode_to_msecs 6918 ((int)soc_LMEPm_field32_get(unit, &lmep_entry, 6919 CCM_INTERVALf)); 6920 if((-1) != trunk_index) { 6921 h_data_p->trunk_index = trunk_index; 6922 } 6923 rv = shr_idxres_list_reserve(oc->lmep_pool, 6924 h_data_p->local_tx_index, 6925 h_data_p->local_tx_index); 6926 if (BCM_FAILURE(rv)) { 6927 LOG_ERROR(BSL_LS_BCM_OAM, 6928 (BSL_META_U(unit, 6929 "OAM Error: Tx index=%d reserve failed" 6930 " - %s.\n"), index, bcm_errmsg(rv))); 6931 6932 _bcm_oam_group_ep_list_remove(unit, 6933 h_data_p->group_index, 6934 h_data_p->ep_id); 6935 6936 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 6937 goto cleanup; 6938 } 6939 6940 bcm_oam_endpoint_info_t_init(ep_info); 6941 6942 /* Set up endpoint information for key construction. */ 6943 ep_info->group = h_data_p->group_index; 6944 ep_info->name = h_data_p->name; 6945 ep_info->gport = h_data_p->gport; 6946 ep_info->level = h_data_p->level; 6947 ep_info->vlan = h_data_p->vlan; 6948 ep_info->flags = h_data_p->flags; 6949 /* 6950 * Calculate hash key for hash table insert 6951 * operation. 6952 */ 6953 _bcm_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 6954 6955 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 6956 if (BCM_FAILURE(rv)) { 6957 LOG_ERROR(BSL_LS_BCM_OAM, 6958 (BSL_META_U(unit, 6959 "OAM Error: Hash table insert" 6960 " (EP=%d) failed - %s.\n"), 6961 h_data_p->ep_id, bcm_errmsg(rv))); 6962 6963 _bcm_oam_group_ep_list_remove(unit, 6964 h_data_p->group_index, 6965 h_data_p->ep_id); 6966 6967 goto cleanup; 6968 } else { 6969 LOG_DEBUG(BSL_LS_BCM_OAM, 6970 (BSL_META_U(unit, 6971 "OAM Info: Hash Tbl (EP=%d)" 6972 " inserted - %s.\n"), h_data_p->ep_id, 6973 bcm_errmsg(rv))); 6974 } 6975 6976 } 6977 6978 match_found = 0; 6979 h_data_p = NULL; 6980 } 6981 #ifdef BCM_HURRICANE2_SUPPORT 6982 if (tx_disable) { 6983 rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 0, &tx_disable); 6984 if (BCM_FAILURE(rv)) { 6985 LOG_ERROR(BSL_LS_BCM_OAM, 6986 (BSL_META_U(unit, 6987 "OAM Error: in _bcm_oam_modify_oam_tx_control \n"))); 6988 goto cleanup; 6989 } 6990 } 6991 #endif /* BCM_HURRICANE2_SUPPORT */ 6992 6993 /*SDK-147457:HW WAR to fix the issue of wrong LMEP index being written 6994 while deleting and adding same MEP in a loop */ 6995 #ifdef BCM_HURRICANE2_SUPPORT 6996 sal_usleep(3400); 6997 #endif /* BCM_HURRICANE2_SUPPORT */ 6998 6999 LOG_DEBUG(BSL_LS_BCM_OAM, 7000 (BSL_META_U(unit, 7001 "OAM Info: _bcm_tr3_oam_lmep_tx_config_recover" 7002 " - done.\n"))); 7003 sal_free(ep_info); 7004 return (rv); 7005 7006 cleanup: 7007 7008 if (NULL != sh_data_p) { 7009 sal_free(sh_data_p); 7010 } 7011 7012 if (NULL != ep_info) { 7013 sal_free(ep_info); 7014 } 7015 7016 if (0 == match_found && NULL != h_data_p) { 7017 /* Return endpoint index to MEP pool. */ 7018 if (BCM_E_EXISTS 7019 == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) { 7020 shr_idxres_list_free(oc->mep_pool, ep_id); 7021 } 7022 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 7023 } 7024 7025 if (BCM_E_EXISTS 7026 == shr_idxres_list_elem_state(oc->lmep_pool, index)) { 7027 shr_idxres_list_free(oc->lmep_pool, index); 7028 } 7029 7030 LOG_DEBUG(BSL_LS_BCM_OAM, 7031 (BSL_META_U(unit, 7032 "OAM Info: _bcm_tr3_oam_lmep_tx_config_recover" 7033 " - error_done.\n"))); 7034 return (rv); 7035 } 7036 7037 /* 7038 * Function: 7039 * _bcm_tr3_oam_wb_endpoints_recover 7040 * Purpose: 7041 * Recover OAM local endpoint Rx configuration. 7042 * Parameters: 7043 * unit - Device unit number. 7044 * stable_size - OAM module Level2 memory size. 7045 * oam_scache - Pointer to secondary storage buffer pointer. 7046 * Returns: 7047 * BCM_E_XXX 7048 */ 7049 STATIC int 7050 _bcm_tr3_oam_wb_endpoints_recover(int unit, int stable_size, 7051 uint8 **oam_scache, uint16 recovered_ver ) 7052 { 7053 int index; /* Hardware index. */ 7054 uint32 l3_ent_count; /* Max entries in L3_ENTRY_1 table. */ 7055 uint32 l3_entry[SOC_MAX_MEM_WORDS]; /* L3 table entry. */ 7056 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 7057 int rv; /* Operation return status. */ 7058 soc_mem_t mem; /* L3 entry memory */ 7059 7060 /* 7061 * Get OAM control structure. 7062 * Note: Lock taken by calling routine. 7063 */ 7064 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 7065 7066 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 7067 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 7068 mem = L3_ENTRY_IPV4_UNICASTm; 7069 /* Get number of L3 table entries. */ 7070 l3_ent_count = soc_mem_index_count(unit, L3_ENTRY_IPV4_UNICASTm); 7071 } else { 7072 mem = L3_ENTRY_1m; 7073 /* Get number of L3 table entries. */ 7074 l3_ent_count = soc_mem_index_count(unit, L3_ENTRY_1m); 7075 } 7076 7077 sal_memset(&l3_entry, 0, sizeof(l3_entry)); 7078 7079 /* Now get valid OAM endpoint entries. */ 7080 for (index = 0; index < l3_ent_count; index++) { 7081 7082 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 7083 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 7084 rv = READ_L3_ENTRY_IPV4_UNICASTm(unit, MEM_BLOCK_ANY, 7085 index, &l3_entry); 7086 } else { 7087 rv = READ_L3_ENTRY_1m(unit, MEM_BLOCK_ANY, index, &l3_entry); 7088 } 7089 if (BCM_FAILURE(rv)) { 7090 LOG_ERROR(BSL_LS_BCM_OAM, 7091 (BSL_META_U(unit, 7092 "OAM Error: L3_ENTRY (index=%d) read" 7093 " failed - %s.\n"), index, bcm_errmsg(rv))); 7094 return (rv); 7095 } 7096 7097 #ifdef BCM_HURRICANE2_SUPPORT 7098 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 7099 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 7100 if (soc_mem_field32_get(unit, mem, &l3_entry, VALIDf)) { 7101 switch (soc_mem_field32_get(unit, mem, &l3_entry, KEY_TYPEf)) { 7102 7103 case SOC_MEM_KEY_L3_ENTRY_RMEP: 7104 rv = _bcm_tr3_oam_rmep_recover(unit, index, l3_entry, 7105 oam_scache, recovered_ver); 7106 if (BCM_FAILURE(rv)) { 7107 LOG_ERROR(BSL_LS_BCM_OAM, 7108 (BSL_META_U(unit, 7109 "OAM Error: Remote endpoint" 7110 " (index=%d) reconstruct failed - %s.\n"), 7111 index, bcm_errmsg(rv))); 7112 return (rv); 7113 } 7114 break; 7115 7116 case SOC_MEM_KEY_L3_ENTRY_LMEP: 7117 rv = _bcm_tr3_oam_lmep_rx_config_recover(unit, index, 7118 l3_entry, oam_scache, recovered_ver); 7119 if (BCM_FAILURE(rv)) { 7120 LOG_ERROR(BSL_LS_BCM_OAM, 7121 (BSL_META_U(unit, 7122 "OAM Error: Local endpoint" 7123 " (index=%d) reconstruct failed - %s.\n"), 7124 index, bcm_errmsg(rv))); 7125 return (rv); 7126 } 7127 break; 7128 7129 default: 7130 /* Not an OAM entry. */ 7131 continue; 7132 } 7133 } 7134 } 7135 #endif /* BCM_HURRICANE2_SUPPORT */ 7136 #ifdef BCM_TRIUMPH3_SUPPORT 7137 if (soc_mem_field32_get(unit, mem, &l3_entry, VALIDf)) { 7138 switch (soc_mem_field32_get(unit, mem, &l3_entry, KEY_TYPEf)) { 7139 7140 case SOC_MEM_KEY_L3_ENTRY_1_RMEP_RMEP: 7141 rv = _bcm_tr3_oam_rmep_recover(unit, index, l3_entry, 7142 oam_scache, recovered_ver); 7143 if (BCM_FAILURE(rv)) { 7144 LOG_ERROR(BSL_LS_BCM_OAM, 7145 (BSL_META_U(unit, 7146 "OAM Error: Remote endpoint" 7147 " (index=%d) reconstruct failed - %s.\n"), 7148 index, bcm_errmsg(rv))); 7149 return (rv); 7150 } 7151 break; 7152 7153 case SOC_MEM_KEY_L3_ENTRY_1_LMEP_LMEP: 7154 rv = _bcm_tr3_oam_lmep_rx_config_recover(unit, index, 7155 l3_entry, oam_scache, recovered_ver); 7156 if (BCM_FAILURE(rv)) { 7157 LOG_ERROR(BSL_LS_BCM_OAM, 7158 (BSL_META_U(unit, 7159 "OAM Error: Local endpoint" 7160 " (index=%d) reconstruct failed - %s.\n"), 7161 index, bcm_errmsg(rv))); 7162 return (rv); 7163 } 7164 break; 7165 7166 default: 7167 /* Not an OAM entry. */ 7168 continue; 7169 } 7170 } 7171 #endif /* BCM_TRIUMPH3_SUPPORT */ 7172 } 7173 rv = _bcm_tr3_oam_lmep_tx_config_recover(unit, oam_scache, recovered_ver); 7174 if (BCM_FAILURE(rv)) { 7175 LOG_ERROR(BSL_LS_BCM_OAM, 7176 (BSL_META_U(unit, 7177 "OAM Error: Endpoint Tx config recovery" 7178 " failed - %s.\n"), bcm_errmsg(rv))); 7179 return (rv); 7180 } 7181 return (BCM_E_NONE); 7182 } 7183 7184 /* 7185 * Function: bcm_tr3_oam_scache_alloc 7186 * 7187 * Purpose: 7188 * Allocate memory for OAM module in scache 7189 * Parameters: 7190 * unit - (IN) Unit number 7191 * Returns: 7192 * BCM_E_XXX 7193 */ 7194 STATIC int 7195 bcm_tr3_oam_scache_alloc(int unit) { 7196 _bcm_oam_control_t *oc; 7197 soc_scache_handle_t scache_handle; 7198 uint8 *oam_scache; 7199 int alloc_sz = 0; 7200 7201 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 7202 7203 alloc_sz = BCM_OAM_GROUP_NAME_LENGTH * (oc->group_count); 7204 7205 /* Number of oam groups */ 7206 alloc_sz += sizeof(int); 7207 7208 /* VFP group, IFP VP group, IFP GLP group */ 7209 alloc_sz += 3 * sizeof(bcm_field_group_t); 7210 7211 /* Allocate memory to store logical endpoint Ids */ 7212 alloc_sz += (sizeof (bcm_oam_endpoint_t) * (oc->rmep_count + 7213 oc->lmep_count + oc->ma_idx_count)); 7214 7215 /* To store MEP TX, RX and LAG LM/DM FP entry numbers */ 7216 alloc_sz += ((sizeof (bcm_field_entry_t) * 3) * 7217 (oc->ma_idx_count)); 7218 7219 /* Store the BHH Hw config */ 7220 alloc_sz += _bcm_tr3_oam_bhh_hw_config_scache_size_get(unit); 7221 7222 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 7223 BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 1, 7224 alloc_sz, &oam_scache, BCM_WB_DEFAULT_VERSION, NULL)); 7225 return BCM_E_NONE; 7226 } 7227 7228 /* 7229 * Function: 7230 * _bcm_tr3_oam_wb_endpoints_fp_entries_recover 7231 * Purpose: 7232 * Recover OAM Rx MEP FP entry numbers. 7233 * Parameters: 7234 * unit - Device unit number. 7235 * stable_size - OAM module Level2 memory size. 7236 * oam_scache - Pointer to secondary storage buffer pointer. 7237 * Returns: 7238 * BCM_E_XXX 7239 */ 7240 STATIC int 7241 _bcm_tr3_oam_wb_endpoints_fp_entries_recover(int unit, int stable_size, 7242 uint8 **oam_scache, uint16 recovered_ver ) 7243 7244 { 7245 _bcm_oam_control_t *oc; 7246 int grp_idx, rv; 7247 _bcm_oam_ep_list_t *ep_list_p = NULL; 7248 _bcm_oam_hash_data_t ep_data; 7249 _bcm_oam_hash_data_t *hash_data; 7250 _bcm_oam_group_data_t *group_p; /* Pointer to group list. */ 7251 uint32 param0 = 0, param1 = 0; 7252 7253 /* Get handle to control structure. */ 7254 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 7255 /* Initialize to group array pointer. */ 7256 group_p = oc->group_info; 7257 7258 for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) 7259 { 7260 if (group_p[grp_idx].in_use == 1) { 7261 ep_list_p = *(group_p[grp_idx].ep_list); 7262 while (ep_list_p != NULL) { 7263 ep_data = *ep_list_p->ep_data_p; 7264 if ((ep_data.type == bcmOAMEndpointTypeEthernet) && 7265 (!(ep_data.is_remote))) { 7266 if ((ep_data.local_rx_enabled)) { 7267 hash_data = &oc->oam_hash_data[ep_data.ep_id]; 7268 sal_memcpy(&(hash_data->fp_entry_rx), *oam_scache + 7269 (sizeof(bcm_oam_endpoint_t) * 7270 (ep_data.local_rx_index)), 7271 sizeof (bcm_field_entry_t)); 7272 7273 sal_memcpy(&(hash_data->fp_entry_tx), *oam_scache + 7274 (sizeof(bcm_oam_endpoint_t) * 7275 (oc->ma_idx_count)) + 7276 (sizeof(bcm_oam_endpoint_t) * 7277 (ep_data.local_rx_index)), 7278 sizeof (bcm_field_entry_t)); 7279 rv = bcm_esw_field_action_get(unit, 7280 hash_data->fp_entry_rx, 7281 bcmFieldActionOamLmEnable, ¶m0, ¶m1); 7282 if ((BCM_SUCCESS(rv)) && (param0 == 1)) { 7283 7284 hash_data->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 7285 if(ep_data.ep_id == 1){ 7286 hash_data->lm_counter_index = 0; 7287 } 7288 rv = bcm_esw_field_action_get(unit, 7289 hash_data->fp_entry_rx, 7290 bcmFieldActionOamLmBasePtr, 7291 ¶m0, 7292 ¶m1); 7293 if ((BCM_SUCCESS(rv)) && 7294 (hash_data->lm_counter_index == -1)) { 7295 hash_data->lm_counter_index = param0; 7296 }else{ 7297 /*FP entry warm boot has bug in recevery of action - 7298 when action is set to Zero*/ 7299 hash_data->lm_counter_index = 0; 7300 } 7301 /* Reserve the LM counter index recovered */ 7302 rv = shr_idxres_list_reserve(oc->lm_counter_pool, 7303 (shr_idxres_element_t)hash_data->lm_counter_index, 7304 (shr_idxres_element_t)hash_data->lm_counter_index); 7305 if (BCM_FAILURE(rv)) { 7306 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_FULL) : rv; 7307 LOG_ERROR(BSL_LS_BCM_OAM, 7308 (BSL_META_U(unit, 7309 "OAM Error: lm counter idx " 7310 "reserve failed - %s.\n"), 7311 bcm_errmsg(rv))); 7312 continue; 7313 } 7314 } 7315 7316 rv = bcm_esw_field_action_get(unit, 7317 hash_data->fp_entry_rx, 7318 bcmFieldActionOamDmEnable, ¶m0, ¶m1); 7319 if ((BCM_SUCCESS(rv)) && (param0 == 1)) { 7320 hash_data->flags |=BCM_OAM_ENDPOINT_DELAY_MEASUREMENT; 7321 } 7322 rv = bcm_esw_field_action_get(unit, 7323 hash_data->fp_entry_rx, 7324 bcmFieldActionOamServicePriMappingPtr, 7325 ¶m0, 7326 ¶m1); 7327 if ((BCM_SUCCESS(rv)) && (hash_data->pri_map_index == -1)) { 7328 hash_data->pri_map_index = param0; 7329 rv = soc_profile_mem_reference(unit, &oc->ing_service_pri_map, 7330 (hash_data->pri_map_index * BCM_OAM_INTPRI_MAX), 7331 BCM_OAM_INTPRI_MAX); 7332 if (BCM_FAILURE(rv)) { 7333 LOG_ERROR(BSL_LS_BCM_OAM, 7334 (BSL_META_U(unit, 7335 "OAM Error: lm counter profile ref count " 7336 "increment failed(EP=%d) - %s.\n"), 7337 hash_data->ep_id, bcm_errmsg(rv))); 7338 continue; 7339 } 7340 } 7341 if (SOC_GPORT_IS_TRUNK(hash_data->gport) && 7342 ((hash_data->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) || 7343 (hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT))) { 7344 sal_memcpy(&(hash_data->fp_entry_trunk[0]), *oam_scache + 7345 (sizeof(bcm_oam_endpoint_t) * 7346 (oc->ma_idx_count) * 2) + 7347 (sizeof(bcm_oam_endpoint_t) * 7348 (ep_data.local_rx_index)), 7349 sizeof (bcm_field_entry_t)); 7350 7351 } 7352 7353 } 7354 } 7355 ep_list_p = ep_list_p->next; 7356 } 7357 } 7358 } 7359 7360 return (BCM_E_NONE); 7361 } 7362 7363 STATIC int 7364 _bcm_tr3_oam_bhh_hw_config_scache_size_get (int unit) 7365 { 7366 _bcm_oam_control_t *oc; 7367 int scache_size = 0; 7368 7369 /* Lock already taken by the calling routine. */ 7370 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 7371 7372 #if defined (INCLUDE_BHH) 7373 if(soc_feature(unit, soc_feature_bhh)) { 7374 if(oc->ukernel_not_ready == 0) { 7375 /* Store LM/DM enable */ 7376 scache_size += sizeof(oc->bhh_lm_dm_enable); 7377 7378 if (oc->bhh_lm_dm_enable) { 7379 /* Store UDF mode */ 7380 scache_size += sizeof(oc->bhh_udf_mode); 7381 7382 if (oc->bhh_udf_mode) { 7383 /* Store label, ach & opcode UDF id */ 7384 scache_size += sizeof(oc->bhh_label_udf_id); 7385 scache_size += sizeof(oc->bhh_ach_udf_id); 7386 scache_size += sizeof(oc->bhh_opcode_udf_id); 7387 7388 /* Store pkt_fmt_id */ 7389 scache_size += sizeof(oc->bhh_udf_pkt_fmt_id); 7390 7391 } else { 7392 /* Store label, ach & opcode qual id */ 7393 scache_size += sizeof(oc->bhh_label_qual_id); 7394 scache_size += sizeof(oc->bhh_ach_qual_id); 7395 scache_size += sizeof(oc->bhh_opcode_qual_id); 7396 } 7397 } 7398 } 7399 } 7400 #endif 7401 return scache_size; 7402 } 7403 7404 #if defined(INCLUDE_BHH) 7405 /* 7406 * Function: 7407 * _bcm_tr3_oam_bhh_fp_recover 7408 * Purpose: 7409 * Recover the UDF for BHH LM/DM packet processing post warmboot. 7410 * Parameters: 7411 * unit - (IN) Unit number. 7412 * Returns: 7413 * BCM_E_XXX 7414 * Notes: 7415 */ 7416 STATIC int 7417 _bcm_tr3_oam_bhh_fp_recover(int unit, uint8 *oam_scache) 7418 { 7419 int rv = BCM_E_NONE; 7420 _bcm_oam_control_t *oc; 7421 7422 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 7423 _BCM_OAM_LOCK(oc); 7424 7425 if(oc->ukernel_not_ready) { 7426 _BCM_OAM_UNLOCK(oc); 7427 return BCM_E_NONE; 7428 } 7429 7430 sal_memcpy(&(oc->bhh_lm_dm_enable), oam_scache, 7431 sizeof(oc->bhh_lm_dm_enable)); 7432 oam_scache += sizeof(oc->bhh_lm_dm_enable); 7433 7434 if(!oc->bhh_lm_dm_enable) { 7435 _BCM_OAM_UNLOCK(oc); 7436 return BCM_E_NONE; 7437 } 7438 7439 BCM_FIELD_QSET_INIT(oc->bhh_lmdm_qset); 7440 BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifySrcPort); 7441 BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifyDstPort); 7442 BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifyOuterVlanId); 7443 BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifyDstL3Egress); 7444 7445 sal_memcpy(&(oc->bhh_udf_mode), oam_scache, 7446 sizeof(oc->bhh_udf_mode)); 7447 oam_scache += sizeof(oc->bhh_udf_mode); 7448 7449 if (oc->bhh_udf_mode) { /* Configure UDF using bcm_udf_xxx() APIs */ 7450 7451 sal_memcpy(&(oc->bhh_label_udf_id), oam_scache, 7452 sizeof(oc->bhh_label_udf_id)); 7453 oam_scache += sizeof(oc->bhh_label_udf_id); 7454 7455 sal_memcpy(&(oc->bhh_ach_udf_id), oam_scache, 7456 sizeof(oc->bhh_ach_udf_id)); 7457 oam_scache += sizeof(oc->bhh_ach_udf_id); 7458 7459 sal_memcpy(&(oc->bhh_opcode_udf_id), oam_scache, 7460 sizeof(oc->bhh_opcode_udf_id)); 7461 oam_scache += sizeof(oc->bhh_opcode_udf_id); 7462 7463 sal_memcpy(&(oc->bhh_udf_pkt_fmt_id), oam_scache, 7464 sizeof(oc->bhh_udf_pkt_fmt_id)); 7465 oam_scache += sizeof(oc->bhh_udf_pkt_fmt_id); 7466 7467 rv = bcm_esw_field_qset_id_multi_set(unit, 7468 bcmFieldQualifyUdf, 7469 1, 7470 &(oc->bhh_label_udf_id), 7471 &(oc->bhh_lmdm_qset)); 7472 if (BCM_FAILURE(rv)) { 7473 _BCM_OAM_UNLOCK(oc); 7474 return rv; 7475 } 7476 7477 rv = bcm_esw_field_qset_id_multi_set(unit, 7478 bcmFieldQualifyUdf, 7479 1, 7480 &(oc->bhh_ach_udf_id), 7481 &(oc->bhh_lmdm_qset)); 7482 if (BCM_FAILURE(rv)) { 7483 _BCM_OAM_UNLOCK(oc); 7484 return rv; 7485 } 7486 7487 7488 rv = bcm_esw_field_qset_id_multi_set(unit, 7489 bcmFieldQualifyUdf, 7490 1, 7491 &(oc->bhh_opcode_udf_id), 7492 &(oc->bhh_lmdm_qset)); 7493 if (BCM_FAILURE(rv)) { 7494 _BCM_OAM_UNLOCK(oc); 7495 return rv; 7496 } 7497 7498 7499 7500 } else { /* Configure UDF using bcm_field_xxx() APIs */ 7501 7502 bcm_field_data_packet_format_t_init(&oc->bhh_field_pkt_fmt); 7503 oc->bhh_field_pkt_fmt.relative_offset = 0; 7504 oc->bhh_field_pkt_fmt.l2 = BCM_FIELD_DATA_FORMAT_L2_ANY; 7505 oc->bhh_field_pkt_fmt.vlan_tag = BCM_FIELD_DATA_FORMAT_VLAN_TAG_ANY; 7506 oc->bhh_field_pkt_fmt.tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS; 7507 oc->bhh_field_pkt_fmt.mpls = BCM_FIELD_DATA_FORMAT_MPLS_ANY; 7508 7509 sal_memcpy(&(oc->bhh_label_qual_id), oam_scache, 7510 sizeof(oc->bhh_label_qual_id)); 7511 oam_scache += sizeof(oc->bhh_label_qual_id); 7512 7513 sal_memcpy(&(oc->bhh_ach_qual_id), oam_scache, 7514 sizeof(oc->bhh_ach_qual_id)); 7515 oam_scache += sizeof(oc->bhh_ach_qual_id); 7516 7517 sal_memcpy(&(oc->bhh_opcode_qual_id), oam_scache, 7518 sizeof(oc->bhh_opcode_qual_id)); 7519 oam_scache += sizeof(oc->bhh_opcode_qual_id); 7520 7521 rv = bcm_esw_field_qset_data_qualifier_add(unit, 7522 &oc->bhh_lmdm_qset, 7523 oc->bhh_label_qual_id); 7524 if (BCM_FAILURE(rv)) { 7525 _BCM_OAM_UNLOCK(oc); 7526 return rv; 7527 } 7528 7529 rv = bcm_esw_field_qset_data_qualifier_add(unit, 7530 &oc->bhh_lmdm_qset, 7531 oc->bhh_ach_qual_id); 7532 if (BCM_FAILURE(rv)) { 7533 _BCM_OAM_UNLOCK(oc); 7534 return rv; 7535 } 7536 7537 rv = bcm_esw_field_qset_data_qualifier_add(unit, 7538 &oc->bhh_lmdm_qset, 7539 oc->bhh_opcode_qual_id); 7540 if (BCM_FAILURE(rv)) { 7541 _BCM_OAM_UNLOCK(oc); 7542 return rv; 7543 } 7544 } 7545 7546 _BCM_OAM_UNLOCK(oc); 7547 return (rv); 7548 } 7549 7550 /* 7551 * Function: 7552 * _bcm_tr3_oam_bhh_fp_upgrade 7553 * Purpose: 7554 * Handle warm upgrade from a release which does not 7555 * have bhh_udf_mode set 7556 * Parameters: 7557 * unit - (IN) Unit number. 7558 * Returns: 7559 * BCM_E_XXX 7560 * Notes: 7561 */ 7562 STATIC int 7563 _bcm_tr3_oam_bhh_fp_upgrade(int unit) 7564 { 7565 int rv = BCM_E_NONE; 7566 _bcm_oam_control_t *oc; 7567 7568 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 7569 _BCM_OAM_LOCK(oc); 7570 7571 if(oc->ukernel_not_ready) { 7572 _BCM_OAM_UNLOCK(oc); 7573 return BCM_E_NONE; 7574 } 7575 7576 /* Upgrading with BHH BTE loaded, from a release which does not have 7577 * bhh_udf_mode defined, enable LM/DM & set udf_mode to field. 7578 */ 7579 oc->bhh_lm_dm_enable = 1; 7580 oc->bhh_udf_mode = 0; 7581 rv = _bcm_tr3_oam_bhh_fp_init(unit); 7582 7583 _BCM_OAM_UNLOCK(oc); 7584 return rv; 7585 } 7586 7587 /* 7588 * Function: 7589 * _bcm_tr3_oam_bhh_cos_map_recover 7590 * Purpose: 7591 * Recover the CoS map settings for BHH after warm boot 7592 * 7593 * Parameters: 7594 * unit - (IN) Unit number. 7595 * Returns: 7596 * BCM_E_XXX 7597 * Notes: 7598 */ 7599 STATIC int 7600 _bcm_tr3_oam_bhh_cos_map_recover(int unit) 7601 { 7602 int rv = BCM_E_NONE; 7603 _bcm_oam_control_t *oc; 7604 int index; 7605 int cosq_map_size; 7606 bcm_rx_reasons_t reasons, reasons_mask, reasons_cmp; 7607 uint8 int_prio, int_prio_mask; 7608 uint32 packet_type, packet_type_mask; 7609 bcm_cos_queue_t cosq; 7610 7611 /* Get OAM Control Structure. */ 7612 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 7613 7614 _BCM_OAM_LOCK(oc); 7615 7616 if(oc->ukernel_not_ready) { 7617 _BCM_OAM_UNLOCK(oc); 7618 return BCM_E_NONE; 7619 } 7620 7621 rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size); 7622 if(BCM_FAILURE(rv)) { 7623 LOG_ERROR(BSL_LS_BCM_OAM, 7624 (BSL_META_U(unit, 7625 "BHH Error:hw init. cosq maps size %s.\n"), 7626 bcm_errmsg(rv))); 7627 _BCM_OAM_UNLOCK(oc); 7628 return (rv); 7629 } 7630 7631 /* Get CPU COS Queue mapping */ 7632 BCM_RX_REASON_CLEAR_ALL(reasons_cmp); 7633 BCM_RX_REASON_SET(reasons_cmp, bcmRxReasonMplsUnknownAch); 7634 oc->cpu_cosq_ach_error_index = -1; 7635 7636 for (index = 0; index < cosq_map_size; index++) { 7637 rv = bcm_esw_rx_cosq_mapping_get(unit, index, 7638 &reasons, &reasons_mask, 7639 &int_prio, &int_prio_mask, 7640 &packet_type, &packet_type_mask, 7641 &cosq); 7642 if (rv == BCM_E_NONE) { 7643 7644 if (BCM_RX_REASON_EQ(reasons, reasons_cmp) && 7645 BCM_RX_REASON_EQ(reasons_mask, reasons_cmp)) { 7646 oc->cpu_cosq_ach_error_index = index; 7647 oc->cpu_cosq = cosq; 7648 break; 7649 } 7650 } 7651 } 7652 7653 if (index >= cosq_map_size) { 7654 LOG_VERBOSE(BSL_LS_BCM_OAM, 7655 (BSL_META_U(unit, 7656 "BHH Error: Could not recover cos map entry \n"))); 7657 } 7658 7659 _BCM_OAM_UNLOCK(oc); 7660 return rv; 7661 } 7662 #endif /* INCLUDE_BHH*/ 7663 7664 /* 7665 * Function: 7666 * _bcm_tr3_oam_reinit 7667 * Purpose: 7668 * Reconstruct OAM module software state. 7669 * Parameters: 7670 * unit - (IN) BCM device number 7671 * Retruns: 7672 * BCM_E_XXX 7673 */ 7674 STATIC int 7675 _bcm_tr3_oam_reinit(int unit) 7676 { 7677 uint32 group_count = 0; /* Stored OAM group count. */ 7678 int stable_size; /* Secondary storage size. */ 7679 uint8 *oam_scache; /* Pointer to scache memory. */ 7680 soc_scache_handle_t scache_handle; /* Scache memory handler. */ 7681 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 7682 int rv; /* Operation return status. */ 7683 uint16 recovered_ver = 0; 7684 int realloc_size = 0; 7685 7686 LOG_DEBUG(BSL_LS_BCM_OAM, 7687 (BSL_META_U(unit, 7688 "OAM Info: OAM warm boot recovery.....\n"))); 7689 7690 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 7691 7692 /* Get OAM control structure. */ 7693 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 7694 7695 _BCM_OAM_LOCK(oc); 7696 7697 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) { 7698 7699 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 7700 7701 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0, 7702 &oam_scache, BCM_WB_DEFAULT_VERSION, 7703 &recovered_ver); 7704 if (BCM_E_NOT_FOUND == rv) { 7705 /* Upgrading from SDK release that does not have warmboot state */ 7706 bcm_tr3_oam_scache_alloc(unit); 7707 _BCM_OAM_UNLOCK(oc); 7708 return BCM_E_NONE; 7709 } else if (BCM_FAILURE(rv)) { 7710 goto cleanup; 7711 } 7712 7713 /* Recover the FP groups */ 7714 sal_memcpy(&oc->vfp_group, oam_scache, sizeof(bcm_field_group_t)); 7715 oam_scache += sizeof(bcm_field_group_t); 7716 7717 sal_memcpy(&oc->fp_vp_group, oam_scache, sizeof(bcm_field_group_t)); 7718 oam_scache += sizeof(bcm_field_group_t); 7719 7720 sal_memcpy(&oc->fp_glp_group, oam_scache, sizeof(bcm_field_group_t)); 7721 oam_scache += sizeof(bcm_field_group_t); 7722 7723 /* Recover the OAM groups */ 7724 sal_memcpy(&group_count, oam_scache, sizeof(int)); 7725 oam_scache += sizeof(int); 7726 } else { 7727 rv = BCM_E_NONE; 7728 goto cleanup; 7729 } 7730 7731 if (recovered_ver >= BCM_WB_VERSION_1_1) { 7732 rv = _bcm_tr3_oam_wb_group_recover(unit, stable_size, &oam_scache, 1); 7733 oam_scache += BCM_OAM_GROUP_NAME_LENGTH * (oc->group_count); 7734 } else { 7735 rv = _bcm_tr3_oam_wb_group_recover(unit, stable_size, &oam_scache, 0); 7736 } 7737 7738 if (BCM_FAILURE(rv)) { 7739 LOG_ERROR(BSL_LS_BCM_OAM, 7740 (BSL_META_U(unit, 7741 "OAM Error: Group recovery failed - %s.\n"), 7742 bcm_errmsg(rv))); 7743 goto cleanup; 7744 } 7745 7746 rv = _bcm_tr3_oam_wb_endpoints_recover(unit, stable_size, &oam_scache, 7747 recovered_ver); 7748 if (BCM_FAILURE(rv)) { 7749 LOG_ERROR(BSL_LS_BCM_OAM, 7750 (BSL_META_U(unit, 7751 "OAM Error: Endpoint recovery failed - %s.\n"), 7752 bcm_errmsg(rv))); 7753 goto cleanup; 7754 } 7755 7756 if (recovered_ver >= BCM_WB_VERSION_1_2) { 7757 oam_scache += (sizeof (bcm_oam_endpoint_t) * 7758 (oc->rmep_count + oc->lmep_count + oc->ma_idx_count)); 7759 } 7760 7761 if (recovered_ver >= BCM_WB_VERSION_1_3) { 7762 rv = _bcm_tr3_oam_wb_endpoints_fp_entries_recover(unit, stable_size, 7763 &oam_scache, 7764 recovered_ver); 7765 if (BCM_FAILURE(rv)) { 7766 LOG_ERROR(BSL_LS_BCM_OAM, 7767 (BSL_META_U(unit, 7768 "OAM Error: Endpoint FP entries recovery " 7769 "failed - %s.\n"), 7770 bcm_errmsg(rv))); 7771 goto cleanup; 7772 } 7773 oam_scache += ((sizeof (bcm_field_entry_t) * 3) * 7774 (oc->ma_idx_count)); 7775 } 7776 7777 if (recovered_ver >= BCM_WB_VERSION_1_4) { 7778 #if defined(INCLUDE_BHH) 7779 if(soc_feature(unit, soc_feature_bhh)) { 7780 rv = _bcm_tr3_oam_bhh_fp_recover(unit, oam_scache); 7781 if (BCM_FAILURE(rv)) { 7782 LOG_ERROR(BSL_LS_BCM_OAM, 7783 (BSL_META_U(unit, 7784 "OAM Error: BHH fp recovery failed - %s \n"), 7785 bcm_errmsg(rv))); 7786 goto cleanup; 7787 } 7788 } 7789 #endif 7790 } else { 7791 #if defined(INCLUDE_BHH) 7792 if(soc_feature(unit, soc_feature_bhh)) { 7793 rv = _bcm_tr3_oam_bhh_fp_upgrade(unit); 7794 if (BCM_FAILURE(rv)) { 7795 LOG_ERROR(BSL_LS_BCM_OAM, 7796 (BSL_META_U(unit, 7797 "OAM Error: BHH FP upgrade failed - %s \n"), 7798 bcm_errmsg(rv))); 7799 goto cleanup; 7800 } 7801 7802 } 7803 #endif 7804 } 7805 7806 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) { 7807 7808 /* In BCM_WB_VERSION_1_1 onwards we allocate memory for max OAM groups and 7809 not just the groups created, as such while upgrading from 7810 BCM_WB_VERSION_1_0 to BCM_WB_VERSION_1_1 or greater we must add the 7811 differential. 7812 */ 7813 if (recovered_ver < BCM_WB_VERSION_1_1) { 7814 realloc_size += (BCM_OAM_GROUP_NAME_LENGTH * 7815 (oc->group_count - group_count)); 7816 } 7817 7818 /* In BCM_WB_VERSION_1_2 onwards we allocate memory for storing EP indexes 7819 also, as such while upgrading from any version lower than 7820 BCM_WB_VERSION_1_2 we must add the differential. 7821 */ 7822 if (recovered_ver < BCM_WB_VERSION_1_2) { 7823 realloc_size += (sizeof (bcm_oam_endpoint_t) * 7824 (oc->rmep_count + oc->lmep_count + oc->ma_idx_count)); 7825 } 7826 7827 /* In BCM_WB_VERSION_1_3 onwards we allocate memory for storing EP FP 7828 indexes also, as such while upgrading from any version lower than 7829 BCM_WB_VERSION_1_3 we must add the differential. 7830 */ 7831 if (recovered_ver < BCM_WB_VERSION_1_3) { 7832 realloc_size += ((sizeof (bcm_field_entry_t) * 2) * 7833 (oc->ma_idx_count)); 7834 } 7835 7836 /* In BCM_WB_VERSION_1_4 onwards we allocate memory for storing the 7837 * BHH H/w config, so must add differential while upgrading from 7838 * lower version 7839 */ 7840 if (recovered_ver < BCM_WB_VERSION_1_4) { 7841 /* Store the BHH Hw config */ 7842 realloc_size += _bcm_tr3_oam_bhh_hw_config_scache_size_get(unit); 7843 } 7844 7845 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 7846 rv = soc_scache_realloc(unit, scache_handle, realloc_size); 7847 if (SOC_FAILURE(rv)) { 7848 LOG_ERROR(BSL_LS_BCM_OAM, 7849 (BSL_META_U(unit,"OAM Error: scache alloc failed - %s.\n"), 7850 bcm_errmsg(rv))); 7851 goto cleanup; 7852 } 7853 } 7854 7855 cleanup: 7856 _BCM_OAM_UNLOCK(oc); 7857 return (rv); 7858 } 7859 #endif /* BCM_WARM_BOOT_SUPPORT */ 7860 7861 /* * * * * * * * * * * * * * * * * * * * 7862 * OAM BCM APIs * 7863 */ 7864 7865 /* 7866 * Function: bcm_tr3_oam_init 7867 * 7868 * Purpose: 7869 * Initialize OAM module. 7870 * Parameters: 7871 * unit - (IN) BCM device number 7872 * Returns: 7873 * BCM_E_UNIT - Invalid BCM unit number. 7874 * BCM_E_UNAVAIL - OAM not support on this device. 7875 * BCM_E_MEMORY - Allocation failure 7876 * CM_E_XXX - Error code from bcm_XX_oam_init() 7877 * BCM_E_NONE - Success 7878 */ 7879 int 7880 bcm_tr3_oam_init(int unit) 7881 { 7882 _bcm_oam_control_t *oc = NULL; /* OAM control structure. */ 7883 int rv; /* Operation return value. */ 7884 uint32 size; /* Size of memory allocation. */ 7885 bcm_port_t port; /* Port number. */ 7886 bcm_oam_endpoint_t ep_index; /* Endpoint index. */ 7887 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 7888 int uc; 7889 uint8 carrier_code[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; 7890 char *carrier_code_str; 7891 uint32 node_id = 0; 7892 bhh_sdk_msg_ctrl_init_t msg_init; 7893 uint8 *buffer, *buffer_ptr; 7894 uint16 buffer_len, reply_len; 7895 int priority; 7896 int ukernel_not_ready = 0; 7897 uint8 bhh_consolidate_final_event = 0; 7898 int status; 7899 #endif 7900 7901 7902 /* Ensure that the unit has OAM support. */ 7903 if (!soc_feature(unit, soc_feature_oam)) { 7904 LOG_ERROR(BSL_LS_BCM_OAM, 7905 (BSL_META_U(unit, 7906 "OAM Error: OAM not supported \n"))); 7907 return (BCM_E_UNAVAIL); 7908 } 7909 7910 /* Detach first if the module has been previously initialized. */ 7911 if (NULL != _oam_control[unit]) { 7912 _oam_control[unit]->init = FALSE; 7913 7914 /* COVERITY : Intentional stack use. Marking the event as intentional */ 7915 /* coverity[stack_use_callee] */ 7916 /* coverity[stack_use_overflow] */ 7917 rv = bcm_tr3_oam_detach(unit); 7918 if (BCM_FAILURE(rv)) { 7919 LOG_ERROR(BSL_LS_BCM_OAM, 7920 (BSL_META_U(unit, 7921 "OAM Error: Module deinit - %s.\n"), 7922 bcm_errmsg(rv))); 7923 return (rv); 7924 } 7925 } 7926 7927 /* Allocate OAM control memeory for this unit. */ 7928 _BCM_OAM_ALLOC(oc, _bcm_oam_control_t, sizeof (_bcm_oam_control_t), 7929 "OAM control"); 7930 if (NULL == oc) { 7931 return (BCM_E_MEMORY); 7932 } 7933 7934 if (soc_feature(unit, soc_feature_bhh)) { 7935 #ifdef INCLUDE_BHH 7936 /* 7937 * Initialize uController side 7938 */ 7939 7940 /* 7941 * Start BHH application in BTE (Broadcom Task Engine) uController, 7942 * if not already running (warm boot). 7943 * Determine which uController is running BHH by choosing the first 7944 * uC that returns successfully. 7945 */ 7946 for (uc = 0; uc < SOC_INFO(unit).num_ucs; uc++) { 7947 rv = soc_uc_status(unit, uc, &status); 7948 if ((rv == SOC_E_NONE) && (status != 0)) { 7949 rv = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_BHH, 7950 _BHH_UC_MSG_TIMEOUT_USECS, 7951 BHH_SDK_VERSION, 7952 BHH_UC_MIN_VERSION, 7953 _bcm_oam_bhh_appl_callback, NULL); 7954 if (SOC_E_NONE == rv) { 7955 /* BHH started successfully */ 7956 oc->uc_num = uc; 7957 break; 7958 } 7959 } 7960 } 7961 7962 if (uc >= SOC_INFO(unit).num_ucs) { /* Could not find or start BHH appl */ 7963 ukernel_not_ready = 1; 7964 LOG_ERROR(BSL_LS_BCM_OAM, 7965 (BSL_META_U(unit, 7966 "uKernel Not Ready, bhh not started\n"))); 7967 } 7968 #endif 7969 } 7970 7971 /* Get number of endpoints and groups supported by this unit. */ 7972 rv = _bcm_oam_group_endpoint_count_init(unit, oc); 7973 if (BCM_FAILURE(rv)) { 7974 _bcm_tr3_oam_control_free(unit, oc); 7975 return (rv); 7976 } 7977 7978 if (soc_feature(unit, soc_feature_bhh)) { 7979 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 7980 oc->unit = unit; 7981 7982 oc->ukernel_not_ready = ukernel_not_ready; 7983 /* Get SOC properties for BHH */ 7984 oc->bhh_endpoint_count = soc_property_get(unit, 7985 spn_BHH_NUM_SESSIONS, 128); 7986 oc->bhh_max_encap_length = 7987 soc_property_get(unit, 7988 spn_BHH_ENCAP_MAX_LENGTH, 7989 _BCM_OAM_BHH_DEFAULT_ENCAP_LENGTH); 7990 7991 if(oc->bhh_max_encap_length > _BCM_OAM_BHH_MAX_ENCAP_LENGTH) { 7992 LOG_ERROR(BSL_LS_BCM_OAM, 7993 (BSL_META_U(unit, 7994 "Invalid max encap_length=%u\n"), 7995 oc->bhh_max_encap_length)); 7996 return BCM_E_CONFIG; 7997 } 7998 7999 carrier_code_str = soc_property_get_str(unit, spn_BHH_CARRIER_CODE); 8000 if (carrier_code_str != NULL) { 8001 /* 8002 * Note that the carrier code is specified in colon separated 8003 * MAC address format. 8004 */ 8005 if (_shr_parse_macaddr(carrier_code_str, carrier_code) < 0) { 8006 _bcm_tr3_oam_control_free(unit, oc); 8007 return (BCM_E_INTERNAL); 8008 } 8009 } 8010 8011 node_id = soc_property_get(unit, spn_BHH_NODE_ID, 0); 8012 oc->bhh_lm_dm_enable = soc_property_get(unit, spn_BHH_LM_DM_ENABLE, 1); 8013 oc->bhh_udf_mode = soc_property_get(unit, spn_BHH_UDF_MODE, 1); 8014 bhh_consolidate_final_event = soc_property_get(unit, 8015 spn_BHH_CONSOLIDATED_FINAL_EVENT, 0); 8016 8017 oc->ep_count += oc->bhh_endpoint_count; 8018 8019 if(oc->ep_count >= _BCM_OAM_TRIUMPH3_ENDPOINT_MAX) { 8020 LOG_ERROR(BSL_LS_BCM_OAM, 8021 (BSL_META_U(unit, 8022 "OAM Error: OAM EP count %d not supported \n"), 8023 oc->ep_count)); 8024 _bcm_tr3_oam_control_free(unit, oc); 8025 return (BCM_E_PARAM); 8026 } 8027 #endif /* INCLUDE_BHH */ 8028 } 8029 8030 /* Mem_1: Allocate hash data memory */ 8031 /* size = sizeof(_bcm_oam_hash_data_t) * oc->ep_count; */ 8032 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 8033 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 8034 size = sizeof(_bcm_oam_hash_data_t) * _BCM_OAM_HURRICANE2_ENDPOINT_MAX; 8035 } else { 8036 size = sizeof(_bcm_oam_hash_data_t) * _BCM_OAM_TRIUMPH3_ENDPOINT_MAX; 8037 } 8038 _BCM_OAM_ALLOC(oc->oam_hash_data, _bcm_oam_hash_data_t, size, "Hash data"); 8039 if (NULL == oc->oam_hash_data) { 8040 _bcm_tr3_oam_control_free(unit, oc); 8041 return (BCM_E_MEMORY); 8042 } 8043 8044 /* Mem_2: Allocate group memory */ 8045 size = sizeof(_bcm_oam_group_data_t) * oc->group_count; 8046 8047 _BCM_OAM_ALLOC(oc->group_info, _bcm_oam_group_data_t, size, "Group Info"); 8048 8049 if (NULL == oc->group_info) { 8050 _bcm_tr3_oam_control_free(unit, oc); 8051 return (BCM_E_MEMORY); 8052 } 8053 8054 /* Mem 3: Allocate RMEP H/w to logical index mapping memory */ 8055 size = sizeof(bcm_oam_endpoint_t) * oc->rmep_count; 8056 _BCM_OAM_ALLOC(oc->remote_endpoints, bcm_oam_endpoint_t, size, "RMEP Mapping"); 8057 if (NULL == oc->remote_endpoints) { 8058 _bcm_tr3_oam_control_free(unit, oc); 8059 return (BCM_E_MEMORY); 8060 } 8061 /* Initialize the mapping to BCM_OAM_ENDPOINT_INVALID */ 8062 for (ep_index = 0; ep_index < oc->rmep_count; ++ep_index) { 8063 oc->remote_endpoints[ep_index] = BCM_OAM_ENDPOINT_INVALID; 8064 } 8065 8066 8067 8068 /* Mem_3: Create application endpoint list. */ 8069 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 8070 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 8071 oc->ep_count = _BCM_OAM_HURRICANE2_ENDPOINT_MAX; 8072 } else { 8073 oc->ep_count = _BCM_OAM_TRIUMPH3_ENDPOINT_MAX; 8074 } 8075 8076 rv = shr_idxres_list_create(&oc->mep_pool, 1, oc->ep_count - 1, 8077 1, oc->ep_count -1, "endpoint pool"); 8078 if (BCM_FAILURE(rv)) { 8079 _bcm_tr3_oam_control_free(unit, oc); 8080 return (rv); 8081 } 8082 8083 /* Mem_3: Create local MEP endpoint list. */ 8084 rv = shr_idxres_list_create(&oc->lmep_pool, 1, oc->lmep_count - 1, 8085 1, oc->lmep_count -1, "lmep pool"); 8086 if (BCM_FAILURE(rv)) { 8087 _bcm_tr3_oam_control_free(unit, oc); 8088 return (rv); 8089 } 8090 8091 /* Mem_3: Create Remote MEP endpoint list. */ 8092 rv = shr_idxres_list_create(&oc->rmep_pool, 1, oc->rmep_count - 1, 8093 1, oc->rmep_count -1, "rmep pool"); 8094 if (BCM_FAILURE(rv)) { 8095 _bcm_tr3_oam_control_free(unit, oc); 8096 return (rv); 8097 } 8098 8099 /* Mem_3: Create MEP Rx state tracker table index endpoint list. */ 8100 rv = shr_idxres_list_create(&oc->ma_idx_pool, 8, oc->ma_idx_count - 1, 8101 8, oc->ma_idx_count -1, "ma_idx pool"); 8102 if (BCM_FAILURE(rv)) { 8103 _bcm_tr3_oam_control_free(unit, oc); 8104 return (rv); 8105 8106 } 8107 8108 if(soc_feature(unit, soc_feature_bhh)) { 8109 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 8110 /* Mem_3: Create BHH endpoint list. */ 8111 rv = shr_idxres_list_create(&oc->bhh_pool, 0, oc->bhh_endpoint_count - 1, 8112 0, oc->bhh_endpoint_count - 1, "bhh pool"); 8113 if (BCM_FAILURE(rv)) { 8114 _bcm_tr3_oam_control_free(unit, oc); 8115 return (rv); 8116 } 8117 8118 /* Reserve ep pool from mep_pool for BHH, manange BHH mep using bhh_pool */ 8119 rv = shr_idxres_list_reserve(oc->mep_pool, _BCM_OAM_BHH_ENDPOINT_OFFSET, 8120 _BCM_OAM_BHH_ENDPOINT_OFFSET + oc->bhh_endpoint_count); 8121 8122 if (BCM_FAILURE(rv)) { 8123 _bcm_tr3_oam_control_free(unit, oc); 8124 return (rv); 8125 } 8126 #endif /* INCLUDE_BHH */ 8127 } 8128 8129 /* Mem_4: Create group list. */ 8130 rv = shr_idxres_list_create(&oc->group_pool, 1, oc->group_count - 1, 8131 1, oc->group_count - 1, "group pool"); 8132 if (BCM_FAILURE(rv)) { 8133 _bcm_tr3_oam_control_free(unit, oc); 8134 return (rv); 8135 } 8136 8137 8138 /* Mem_5: Create MA group and MEP hash table. */ 8139 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 8140 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 8141 rv = shr_htb_create(&oc->ma_mep_htbl, oc->ep_count, 8142 sizeof(_bcm_oam_hash_key_t), "MA/MEP Hash"); 8143 } else { 8144 rv = shr_htb_create(&oc->ma_mep_htbl, _BCM_OAM_TRIUMPH3_ENDPOINT_MAX, 8145 sizeof(_bcm_oam_hash_key_t), "MA/MEP Hash"); 8146 } 8147 if (BCM_FAILURE(rv)) { 8148 _bcm_tr3_oam_control_free(unit, oc); 8149 return (rv); 8150 } 8151 8152 /* 8153 * Both TX and RX for one MEP 8154 */ 8155 oc->lm_counter_cnt = 8156 soc_mem_index_count(unit, OAM_LM_COUNTERSm) / 2; 8157 8158 rv = shr_idxres_list_create(&oc->lm_counter_pool, 0, oc->lm_counter_cnt - 1, 8159 0, oc->lm_counter_cnt - 1, "lm counter pool"); 8160 if (BCM_FAILURE(rv)) { 8161 _bcm_tr3_oam_control_free(unit, oc); 8162 return (rv); 8163 } 8164 8165 for (ep_index = 0; ep_index < oc->ep_count; ++ep_index) { 8166 oc->oam_hash_data[ep_index].lm_counter_index = 8167 _BCM_OAM_LM_COUNTER_IDX_INVALID; 8168 } 8169 8170 /* Create protection mutex. */ 8171 oc->oc_lock = sal_mutex_create("oam_control.lock"); 8172 if (NULL == oc->oc_lock) { 8173 _bcm_tr3_oam_control_free(unit, oc); 8174 return (BCM_E_MEMORY); 8175 } 8176 #ifdef BCM_HURRICANE2_SUPPORT 8177 if (SOC_IS_HURRICANE2(unit)) { 8178 /* Register device OAM interrupt handler call back routine. */ 8179 soc_hurricane2_oam_handler_register(unit, 8180 _bcm_tr3_oam_handle_interrupt); 8181 soc_hurricane2_oam_ser_handler_register(unit, 8182 _bcm_tr3_oam_ser_handler); 8183 } else 8184 #endif 8185 #ifdef BCM_GREYHOUND_SUPPORT 8186 if (SOC_IS_GREYHOUND(unit)) { 8187 /* Register device OAM interrupt handler call back routine. */ 8188 soc_greyhound_oam_handler_register(unit, _bcm_tr3_oam_handle_interrupt); 8189 soc_greyhound_oam_ser_handler_register(unit, 8190 _bcm_tr3_oam_ser_handler); 8191 } else 8192 #endif 8193 #ifdef BCM_HURRICANE3_SUPPORT 8194 if (SOC_IS_HURRICANE3(unit)) { 8195 /* Register device OAM interrupt handler call back routine. */ 8196 soc_hr3_oam_handler_register(unit, _bcm_tr3_oam_handle_interrupt); 8197 soc_hr3_oam_ser_handler_register(unit, _bcm_tr3_oam_ser_handler); 8198 8199 } else 8200 #endif 8201 #ifdef BCM_GREYHOUND2_SUPPORT 8202 if (SOC_IS_GREYHOUND2(unit)) { 8203 /* Register device OAM interrupt handler call back routine. */ 8204 soc_gh2_oam_handler_register(unit, _bcm_tr3_oam_handle_interrupt); 8205 soc_gh2_oam_ser_handler_register(unit, 8206 _bcm_tr3_oam_ser_handler); 8207 } else 8208 #endif 8209 { 8210 #ifdef BCM_TRIUMPH3_SUPPORT 8211 /* Register device OAM interrupt handler call back routine. */ 8212 soc_tr3_oam_handler_register(unit, _bcm_tr3_oam_handle_interrupt); 8213 soc_tr3_oam_ser_handler_register(unit, _bcm_tr3_oam_ser_handler); 8214 #endif 8215 8216 } 8217 /* Set up the unit OAM control structure. */ 8218 _oam_control[unit] = oc; 8219 8220 /* Set up OAM module related profile tables. */ 8221 rv = _bcm_oam_profile_tables_init(unit, oc); 8222 if (BCM_FAILURE(rv)) { 8223 _bcm_tr3_oam_control_free(unit, oc); 8224 return (rv); 8225 } 8226 8227 #if defined(BCM_WARM_BOOT_SUPPORT) 8228 if (!SOC_WARM_BOOT(unit)) { 8229 bcm_tr3_oam_scache_alloc(unit); 8230 } 8231 8232 if (SOC_WARM_BOOT(unit)) { 8233 rv = _bcm_tr3_oam_reinit(unit); 8234 if (BCM_FAILURE(rv)) { 8235 _bcm_tr3_oam_control_free(unit, oc); 8236 return (rv); 8237 } 8238 } else 8239 #endif 8240 { 8241 /* Enable OAM processing on all ports of this unit. */ 8242 PBMP_ALL_ITER(unit, port) { 8243 rv = bcm_esw_port_control_set(unit, port, bcmPortControlOAMEnable, 8244 TRUE); 8245 if (BCM_FAILURE(rv)) { 8246 _bcm_tr3_oam_control_free(unit, oc); 8247 return (rv); 8248 } 8249 } 8250 8251 /* Enable CCM Rx timeouts. */ 8252 #ifdef BCM_HURRICANE2_SUPPORT 8253 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 8254 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 8255 rv = _bcm_hu2_oam_ccm_rx_timeout_set(unit, 1); 8256 } else 8257 #endif /* BCM_HURRICANE2_SUPPORT */ 8258 { 8259 rv = _bcm_oam_ccm_rx_timeout_set(unit, 1); 8260 } 8261 if (BCM_FAILURE(rv)) { 8262 _bcm_tr3_oam_control_free(unit, oc); 8263 return (rv); 8264 } 8265 8266 /* Enable CCM Tx control. */ 8267 if(SOC_REG_IS_VALID(unit, OAM_TX_CONTROLr)){ 8268 rv = _bcm_oam_ccm_tx_config_set(unit, 1); 8269 if (BCM_FAILURE(rv)) { 8270 _bcm_tr3_oam_control_free(unit, oc); 8271 return (rv); 8272 } 8273 } 8274 8275 /* Initailiza the FP group for LM/DM to -1 (Not created). */ 8276 oc->fp_glp_group = -1; 8277 8278 /* 8279 * Misc config: 8280 * 1. Prevent L2 learn for OAM MACs. 8281 * 2. PFM setting for MCAST packets. 8282 */ 8283 rv = _bcm_oam_misc_config(unit); 8284 if (BCM_FAILURE(rv)) { 8285 _bcm_tr3_oam_control_free(unit, oc); 8286 return (rv); 8287 } 8288 } 8289 8290 /* 8291 * BHH init 8292 */ 8293 if(soc_feature(unit, soc_feature_bhh)) { 8294 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 8295 if(ukernel_not_ready == 0){ 8296 /* 8297 * Initialize HOST side 8298 */ 8299 oc->cpu_cosq = soc_property_get(unit, spn_BHH_COSQ, 8300 BHH_COSQ_INVALID); 8301 8302 /* 8303 * Allocate DMA buffers 8304 * 8305 * DMA buffer will be used to send and receive 'long' messages 8306 * between SDK Host and uController (BTE). 8307 */ 8308 oc->dma_buffer_len = sizeof(shr_bhh_msg_ctrl_t); 8309 8310 /* Adding feature specific for dma_buf_len as currently 8311 * required buffer length for faults_get can be configurable 8312 * by user during init. So, taking the max value of either of 8313 * them for the purpose.Putting it under fature_check for 8314 * giving flexibility to user. 8315 */ 8316 #ifdef INCLUDE_OAM_FAULTS_MULTI_GET 8317 if(soc_feature(unit, soc_feature_faults_multi_ep_get)) { 8318 oc->dma_buffer_len = MAX((oc->bhh_endpoint_count * sizeof(uint32)), oc->dma_buffer_len); 8319 } 8320 #endif 8321 oc->dma_buffer = soc_cm_salloc(unit, oc->dma_buffer_len, 8322 "BHH DMA buffer"); 8323 if (!oc->dma_buffer) { 8324 _bcm_tr3_oam_control_free(unit, oc); 8325 return (BCM_E_MEMORY); 8326 } 8327 sal_memset(oc->dma_buffer, 0, oc->dma_buffer_len); 8328 8329 oc->dmabuf_reply = soc_cm_salloc(unit, oc->dma_buffer_len, 8330 "BHH uC reply"); 8331 if (!oc->dmabuf_reply) { 8332 _bcm_tr3_oam_control_free(unit, oc); 8333 return (BCM_E_MEMORY); 8334 } 8335 sal_memset(oc->dmabuf_reply, 0, oc->dma_buffer_len); 8336 8337 /* RX DMA channel (0..3) local to the uC */ 8338 oc->rx_channel = BCM_KT_BHH_RX_CHANNEL; 8339 8340 #if defined(BCM_WARM_BOOT_SUPPORT) 8341 if (!SOC_WARM_BOOT(unit)) { 8342 #endif 8343 /* Set control message data */ 8344 sal_memset(&msg_init, 0, sizeof(msg_init)); 8345 msg_init.num_sessions = oc->bhh_endpoint_count; 8346 msg_init.rx_channel = oc->rx_channel; 8347 msg_init.node_id = node_id; 8348 sal_memcpy(msg_init.carrier_code, carrier_code, 8349 SHR_BHH_CARRIER_CODE_LEN); 8350 msg_init.max_encap_length = oc->bhh_max_encap_length; 8351 if (bhh_consolidate_final_event) { 8352 msg_init.flags |= BHH_SDK_MSG_CTRL_INIT_ONLY_FINAL_EVENT; 8353 } 8354 8355 /* Pack control message data into DMA buffer */ 8356 buffer = oc->dma_buffer; 8357 buffer_ptr = bhh_sdk_msg_ctrl_init_pack(unit, buffer, &msg_init); 8358 buffer_len = buffer_ptr - buffer; 8359 8360 /* Send BHH Init message to uC */ 8361 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 8362 MOS_MSG_SUBCLASS_BHH_INIT, 8363 buffer_len, 0, 8364 MOS_MSG_SUBCLASS_BHH_INIT_REPLY, 8365 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 8366 8367 if (BCM_FAILURE(rv) || (reply_len != 0)) { 8368 _bcm_tr3_oam_control_free(unit, oc); 8369 return (BCM_E_INTERNAL); 8370 } 8371 #if defined(BCM_WARM_BOOT_SUPPORT) 8372 } 8373 #endif 8374 8375 /* 8376 * Start event message callback thread 8377 */ 8378 priority = soc_property_get(unit, spn_BHH_THREAD_PRI, 8379 BHH_THREAD_PRI_DFLT); 8380 8381 if (oc->event_thread_id == NULL) { 8382 if ((oc->event_thread_id = 8383 sal_thread_create("bcmBHH", SAL_THREAD_STKSZ, 8384 priority, 8385 _bcm_tr3_oam_bhh_callback_thread, 8386 (void*)oc)) == SAL_THREAD_ERROR) { 8387 oc->event_thread_id = NULL; 8388 BCM_IF_ERROR_RETURN(bcm_tr3_oam_detach(unit)); 8389 return (BCM_E_MEMORY); 8390 } 8391 } 8392 /* 8393 * End BHH init 8394 */ 8395 } 8396 /* 8397 * Initialize HW 8398 */ 8399 #ifdef BCM_WARM_BOOT_SUPPORT 8400 if (SOC_WARM_BOOT(unit)) { 8401 rv = _bcm_tr3_oam_bhh_cos_map_recover(unit); 8402 } else 8403 #endif 8404 { 8405 rv = _bcm_tr3_oam_bhh_hw_init(unit); 8406 } 8407 8408 if (BCM_FAILURE(rv)) { 8409 BCM_IF_ERROR_RETURN(bcm_tr3_oam_detach(unit)); 8410 return rv; 8411 } 8412 #endif /* BCM_TRIUMPH3_SUPPORT && INCLUDE_BHH */ 8413 } 8414 8415 /* OAM initialization complete. */ 8416 _oam_control[unit]->init = TRUE; 8417 return (BCM_E_NONE); 8418 } 8419 8420 /* 8421 * Function: 8422 * bcm_tr3_oam_detach 8423 * Purpose: 8424 * Shut down OAM subsystem 8425 * Parameters: 8426 * unit - (IN) BCM device number 8427 * Returns: 8428 * BCM_E_XXX 8429 */ 8430 int 8431 bcm_tr3_oam_detach(int unit) 8432 { 8433 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 8434 bcm_port_t port; /* Port number. */ 8435 int rv; /* Operation return status. */ 8436 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 8437 uint16 reply_len; 8438 sal_usecs_t timeout = 0; 8439 int status; 8440 #endif 8441 8442 8443 /* Get the device OAM module handle. */ 8444 oc = _oam_control[unit]; 8445 if (NULL == oc) { 8446 /* Module already uninitialized. */ 8447 return (BCM_E_NONE); 8448 } 8449 8450 /* Unregister all OAM interrupt event handlers. */ 8451 #ifdef BCM_HURRICANE2_SUPPORT 8452 if (SOC_IS_HURRICANE2(unit)) { 8453 /* Register device OAM interrupt handler call back routine. */ 8454 soc_hurricane2_oam_handler_register(unit, NULL); 8455 } else 8456 #endif 8457 #ifdef BCM_GREYHOUND_SUPPORT 8458 if (SOC_IS_GREYHOUND(unit)) { 8459 /* Register device OAM interrupt handler call back routine. */ 8460 soc_greyhound_oam_handler_register(unit, NULL); 8461 soc_greyhound_oam_ser_handler_register(unit, NULL); 8462 } else 8463 #endif 8464 #ifdef BCM_HURRICANE3_SUPPORT 8465 if (SOC_IS_HURRICANE3(unit)) { 8466 /* Register device OAM interrupt handler call back routine. */ 8467 soc_hr3_oam_handler_register(unit, NULL); 8468 soc_hr3_oam_ser_handler_register(unit, NULL); 8469 } else 8470 #endif 8471 #ifdef BCM_GREYHOUND2_SUPPORT 8472 if (SOC_IS_GREYHOUND2(unit)) { 8473 /* Unregister device OAM interrupt handler call back routine. */ 8474 soc_gh2_oam_handler_register(unit, NULL); 8475 soc_gh2_oam_ser_handler_register(unit, NULL); 8476 } else 8477 #endif 8478 { 8479 #ifdef BCM_TRIUMPH3_SUPPORT 8480 soc_tr3_oam_handler_register(unit, NULL); 8481 soc_tr3_oam_ser_handler_register(unit, NULL); 8482 #endif 8483 } 8484 if (NULL != oc->oc_lock) { 8485 _BCM_OAM_LOCK(oc); 8486 } 8487 8488 rv = _bcm_tr3_oam_events_unregister(unit, oc); 8489 if (BCM_FAILURE(rv)) { 8490 if (NULL != oc->oc_lock) { 8491 _BCM_OAM_UNLOCK(oc); 8492 } 8493 return (rv); 8494 } 8495 8496 /* Disable CCM Rx Timeouts. */ 8497 #ifdef BCM_HURRICANE2_SUPPORT 8498 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 8499 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 8500 rv = _bcm_hu2_oam_ccm_rx_timeout_set(unit, 1); 8501 } else 8502 #endif /* BCM_HURRICANE2_SUPPORT */ 8503 { 8504 rv = _bcm_oam_ccm_rx_timeout_set(unit, 0); 8505 } 8506 if (BCM_FAILURE(rv)) { 8507 if (NULL != oc->oc_lock) { 8508 _BCM_OAM_UNLOCK(oc); 8509 } 8510 return (rv); 8511 } 8512 8513 /* Disable CCM Tx control for the device. */ 8514 if(SOC_REG_IS_VALID(unit, OAM_TX_CONTROLr)){ 8515 rv = _bcm_oam_ccm_tx_config_set(unit, 0); 8516 if (BCM_FAILURE(rv)) { 8517 if (NULL != oc->oc_lock) { 8518 _BCM_OAM_UNLOCK(oc); 8519 } 8520 return (rv); 8521 } 8522 } 8523 8524 /* Disable OAM PDU Rx processing on all ports. */ 8525 PBMP_ALL_ITER(unit, port) { 8526 rv = bcm_esw_port_control_set(unit, port, 8527 bcmPortControlOAMEnable, 0); 8528 if (BCM_FAILURE(rv)) { 8529 if (NULL != oc->oc_lock) { 8530 _BCM_OAM_UNLOCK(oc); 8531 } 8532 return (rv); 8533 } 8534 } 8535 8536 /* 8537 * BHH specific 8538 */ 8539 if (soc_feature(unit, soc_feature_bhh)) { 8540 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 8541 if (oc->ukernel_not_ready == 0) { 8542 /* 8543 * Event Handler thread exit signal 8544 */ 8545 timeout = sal_time_usecs() + 5000000; 8546 while (NULL != oc->event_thread_id) { 8547 soc_cmic_uc_msg_receive_cancel(unit, oc->uc_num, 8548 MOS_MSG_CLASS_BHH_EVENT); 8549 8550 if (sal_time_usecs() < timeout) { 8551 /*give some time to already running bhh callback thread 8552 * to schedule and exit */ 8553 sal_usleep(10000); 8554 } else { 8555 /*timeout*/ 8556 LOG_ERROR(BSL_LS_BCM_OAM, 8557 (BSL_META_U(unit, 8558 "BHH event thread did not exit.\n"))); 8559 _BCM_OAM_UNLOCK(oc); 8560 return BCM_E_INTERNAL; 8561 } 8562 } 8563 8564 /* 8565 * Send BHH Uninit message to uC 8566 * Ignore error since that may indicate uKernel was reloaded. 8567 */ 8568 #if defined(BCM_WARM_BOOT_SUPPORT) 8569 if (!SOC_WARM_BOOT(unit)) { 8570 #endif 8571 SOC_IF_ERROR_RETURN(soc_uc_status(unit, oc->uc_num, &status)); 8572 if (status) { 8573 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 8574 MOS_MSG_SUBCLASS_BHH_UNINIT, 8575 0, 0, 8576 MOS_MSG_SUBCLASS_BHH_UNINIT_REPLY, 8577 &reply_len, 5000000); 8578 if (BCM_SUCCESS(rv) && (reply_len != 0)) { 8579 if (NULL != oc->oc_lock) { 8580 _BCM_OAM_UNLOCK(oc); 8581 } 8582 return BCM_E_INTERNAL; 8583 } 8584 } 8585 #if defined(BCM_WARM_BOOT_SUPPORT) 8586 } 8587 #endif 8588 8589 if (!SOC_WARM_BOOT(unit)) { 8590 /* 8591 * Delete CPU COS queue mapping entries for BHH packets 8592 */ 8593 if (oc->cpu_cosq_ach_error_index >= 0) { 8594 rv = bcm_esw_rx_cosq_mapping_delete(unit, 8595 oc->cpu_cosq_ach_error_index); 8596 if (BCM_FAILURE(rv)) { 8597 if (NULL != oc->oc_lock) { 8598 _BCM_OAM_UNLOCK(oc); 8599 } 8600 return (rv); 8601 } 8602 oc->cpu_cosq_ach_error_index = -1; 8603 } 8604 8605 /* Destroy UDF entries installed for BHH, since FP/UDF init happens 8606 * before OAM init, they may have already been destroyed hence 8607 * BCM_E_NOT_FOUND is not an error for this operation 8608 */ 8609 if (oc->bhh_lm_dm_enable) { 8610 if(oc->bhh_udf_mode) { 8611 rv = bcm_esw_udf_pkt_format_delete(unit, 8612 oc->bhh_label_udf_id, 8613 oc->bhh_udf_pkt_fmt_id); 8614 if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) { 8615 if (NULL != oc->oc_lock) { 8616 _BCM_OAM_UNLOCK(oc); 8617 } 8618 return (rv); 8619 } 8620 8621 rv = bcm_esw_udf_pkt_format_delete(unit, 8622 oc->bhh_ach_udf_id, 8623 oc->bhh_udf_pkt_fmt_id); 8624 if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) { 8625 if (NULL != oc->oc_lock) { 8626 _BCM_OAM_UNLOCK(oc); 8627 } 8628 return (rv); 8629 } 8630 8631 rv = bcm_esw_udf_pkt_format_delete(unit, 8632 oc->bhh_opcode_udf_id, 8633 oc->bhh_udf_pkt_fmt_id); 8634 if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) { 8635 if (NULL != oc->oc_lock) { 8636 _BCM_OAM_UNLOCK(oc); 8637 } 8638 return (rv); 8639 } 8640 8641 rv = bcm_esw_udf_pkt_format_destroy(unit, 8642 oc->bhh_udf_pkt_fmt_id); 8643 if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) { 8644 if (NULL != oc->oc_lock) { 8645 _BCM_OAM_UNLOCK(oc); 8646 } 8647 return (rv); 8648 } 8649 8650 rv = bcm_esw_udf_destroy(unit, oc->bhh_label_udf_id); 8651 if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) { 8652 if (NULL != oc->oc_lock) { 8653 _BCM_OAM_UNLOCK(oc); 8654 } 8655 return (rv); 8656 } 8657 8658 rv = bcm_esw_udf_destroy(unit, oc->bhh_ach_udf_id); 8659 if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) { 8660 if (NULL != oc->oc_lock) { 8661 _BCM_OAM_UNLOCK(oc); 8662 } 8663 return (rv); 8664 } 8665 8666 rv = bcm_esw_udf_destroy(unit, oc->bhh_opcode_udf_id); 8667 if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) { 8668 if (NULL != oc->oc_lock) { 8669 _BCM_OAM_UNLOCK(oc); 8670 } 8671 return (rv); 8672 } 8673 8674 } else { 8675 rv = bcm_esw_field_data_qualifier_packet_format_delete(unit, 8676 oc->bhh_label_qual_id, 8677 &(oc->bhh_field_pkt_fmt)); 8678 if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) { 8679 if (NULL != oc->oc_lock) { 8680 _BCM_OAM_UNLOCK(oc); 8681 } 8682 return (rv); 8683 } 8684 8685 rv = bcm_esw_field_data_qualifier_packet_format_delete(unit, 8686 oc->bhh_ach_qual_id, 8687 &(oc->bhh_field_pkt_fmt)); 8688 if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) { 8689 if (NULL != oc->oc_lock) { 8690 _BCM_OAM_UNLOCK(oc); 8691 } 8692 return (rv); 8693 } 8694 8695 rv = bcm_esw_field_data_qualifier_packet_format_delete(unit, 8696 oc->bhh_opcode_qual_id, 8697 &(oc->bhh_field_pkt_fmt)); 8698 if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) { 8699 if (NULL != oc->oc_lock) { 8700 _BCM_OAM_UNLOCK(oc); 8701 } 8702 return (rv); 8703 } 8704 8705 rv = bcm_esw_field_data_qualifier_destroy(unit, 8706 oc->bhh_label_qual_id); 8707 if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) { 8708 if (NULL != oc->oc_lock) { 8709 _BCM_OAM_UNLOCK(oc); 8710 } 8711 return (rv); 8712 } 8713 8714 rv = bcm_esw_field_data_qualifier_destroy(unit, 8715 oc->bhh_ach_qual_id); 8716 if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) { 8717 if (NULL != oc->oc_lock) { 8718 _BCM_OAM_UNLOCK(oc); 8719 } 8720 return (rv); 8721 } 8722 8723 rv = bcm_esw_field_data_qualifier_destroy(unit, 8724 oc->bhh_opcode_qual_id); 8725 if (rv != BCM_E_NOT_FOUND && BCM_FAILURE(rv)) { 8726 if (NULL != oc->oc_lock) { 8727 _BCM_OAM_UNLOCK(oc); 8728 } 8729 return (rv); 8730 } 8731 } 8732 } 8733 } 8734 } 8735 #endif /* INCLUDE_BHH */ 8736 } 8737 8738 /* Destroy all groups and assoicated endpoints and free the resources. */ 8739 rv = bcm_tr3_oam_group_destroy_all(unit); 8740 if (BCM_FAILURE(rv)) { 8741 if (NULL != oc->oc_lock) { 8742 _BCM_OAM_UNLOCK(oc); 8743 } 8744 return (rv); 8745 } 8746 8747 /* Release the protection mutex. */ 8748 _BCM_OAM_UNLOCK(oc); 8749 8750 /* Free OAM module allocated resources. */ 8751 _bcm_tr3_oam_control_free(unit, oc); 8752 8753 return (BCM_E_NONE); 8754 } 8755 8756 /* 8757 * Function: 8758 * bcm_tr3_oam_group_create 8759 * Purpose: 8760 * Create or replace an OAM group object 8761 * Parameters: 8762 * unit - (IN) BCM device number 8763 * group_info - (IN/OUT) Pointer to an OAM group information. 8764 * Returns: 8765 * BCM_E_XXX 8766 */ 8767 int 8768 bcm_tr3_oam_group_create(int unit, bcm_oam_group_info_t *group_info) 8769 { 8770 ma_state_entry_t ma_state_entry; /* MA State table entry. */ 8771 uint8 grp_name_hw_buf[BCM_OAM_GROUP_NAME_LENGTH]; /* Grp */ 8772 /* name. */ 8773 maid_reduction_entry_t maid_reduction_entry; /* MA ID reduction table */ 8774 _bcm_oam_group_data_t *ma_group; /* Pointer to group info. */ 8775 _bcm_oam_control_t *oc; /* OAM control structure. */ 8776 int rv; /* Operation return status. */ 8777 /* entry. */ 8778 uint8 sw_rdi; /* Remote defect indicator. */ 8779 8780 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 8781 bhh_sdk_msg_ctrl_sess_set_t msg_sess; 8782 uint8 *buffer, *buffer_ptr; 8783 uint16 buffer_len, reply_len; 8784 uint32 session_flags = 0; 8785 _bcm_oam_hash_data_t *h_data_p; 8786 _bcm_oam_ep_list_t *cur; 8787 #endif 8788 8789 /* Validate input parameter. */ 8790 if (NULL == group_info) { 8791 return (BCM_E_PARAM); 8792 } 8793 8794 /* Get OAM control structure handle. */ 8795 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 8796 8797 /* Validate group id. */ 8798 if (group_info->flags & BCM_OAM_GROUP_WITH_ID) { 8799 _BCM_OAM_GROUP_INDEX_VALIDATE(group_info->id); 8800 } 8801 8802 _BCM_OAM_LOCK(oc); 8803 8804 /* 8805 * If MA group create is called with replace flag bit set. 8806 * - Check and return error if a group does not exist with the ID. 8807 */ 8808 if (group_info->flags & BCM_OAM_GROUP_REPLACE) { 8809 if (group_info->flags & BCM_OAM_GROUP_WITH_ID) { 8810 8811 /* Search the list with the MA Group ID value. */ 8812 rv = shr_idxres_list_elem_state(oc->group_pool, group_info->id); 8813 if (BCM_E_EXISTS != rv) { 8814 _BCM_OAM_UNLOCK(oc); 8815 LOG_ERROR(BSL_LS_BCM_OAM, 8816 (BSL_META_U(unit, 8817 "OAM Error: Group does not exist.\n"))); 8818 return (BCM_E_PARAM); 8819 } 8820 } else { 8821 _BCM_OAM_UNLOCK(oc); 8822 LOG_ERROR(BSL_LS_BCM_OAM, 8823 (BSL_META_U(unit, 8824 "OAM Error: Replace command needs a valid Group ID.\n"))); 8825 return (BCM_E_PARAM); 8826 } 8827 } else if (group_info->flags & BCM_OAM_GROUP_WITH_ID) { 8828 /* 8829 * If MA group create is called with ID flag bit set. 8830 * - Check and return error if the ID is already in use. 8831 */ 8832 rv = shr_idxres_list_reserve(oc->group_pool, group_info->id, 8833 group_info->id); 8834 if (BCM_FAILURE(rv)) { 8835 _BCM_OAM_UNLOCK(oc); 8836 return ((rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv); 8837 } 8838 } else { 8839 /* Reserve the next available group index. */ 8840 rv = shr_idxres_list_alloc(oc->group_pool, 8841 (shr_idxres_element_t *) &group_info->id); 8842 if (BCM_FAILURE(rv)) { 8843 _BCM_OAM_UNLOCK(oc); 8844 LOG_ERROR(BSL_LS_BCM_OAM, 8845 (BSL_META_U(unit, 8846 "OAM Error: Group allocation (GID=%d)" 8847 " %s\n"), group_info->id, bcm_errmsg(rv))); 8848 return (rv); 8849 } 8850 } 8851 8852 /* Get this group memory to store group information. */ 8853 ma_group = &oc->group_info[group_info->id]; 8854 8855 /* Store the group name. */ 8856 sal_memcpy(&ma_group->name, &group_info->name, BCM_OAM_GROUP_NAME_LENGTH); 8857 8858 /* Store Lowest Alarm Priority */ 8859 ma_group->lowest_alarm_priority = group_info->lowest_alarm_priority; 8860 8861 if(!(group_info->flags & BCM_OAM_GROUP_REPLACE)) { 8862 _BCM_OAM_ALLOC((ma_group->ep_list),_bcm_oam_ep_list_t *, 8863 sizeof(_bcm_oam_ep_list_t *), "EP list head"); 8864 8865 /* Initialize head to NULL.*/ 8866 *ma_group->ep_list = NULL; 8867 } 8868 8869 /* 8870 * Maintenance Association ID - Reduction table update. 8871 */ 8872 8873 /* Prepare group name for hardware write. */ 8874 _bcm_tr3_oam_group_name_mangle(ma_group->name, grp_name_hw_buf); 8875 8876 sal_memset(&maid_reduction_entry, 0, sizeof(maid_reduction_entry_t)); 8877 8878 /* Calculate CRC32 value for the group name string and set in entry. */ 8879 soc_MAID_REDUCTIONm_field32_set 8880 (unit, &maid_reduction_entry, REDUCED_MAIDf, 8881 soc_draco_crc32(grp_name_hw_buf, BCM_OAM_GROUP_NAME_LENGTH)); 8882 8883 /* Check if software RDI flag bit needs to be set in hardware. */ 8884 sw_rdi = ((group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) ? 1 : 0); 8885 8886 /* Set RDI status for out going CCM PDUs. */ 8887 soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, SW_RDIf, 8888 sw_rdi); 8889 8890 if (soc_feature(unit, soc_feature_bhh)) { 8891 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 8892 /* Send message to uC to set the Soft RDI, if RDI flag is set */ 8893 if (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) { 8894 8895 /* Get the endpoint list head pointer. */ 8896 cur = *(ma_group->ep_list); 8897 8898 /* Traverse to the tail of the list. */ 8899 while (NULL != cur) { 8900 h_data_p = cur->ep_data_p; 8901 if (NULL == h_data_p) { 8902 LOG_ERROR(BSL_LS_BCM_OAM, 8903 (BSL_META_U(unit, 8904 "OAM Error: Group=%d endpoints access failed -" 8905 " %s.\n"), group_info->id, bcm_errmsg(BCM_E_INTERNAL))); 8906 _BCM_OAM_UNLOCK(oc); 8907 return (BCM_E_INTERNAL); 8908 } 8909 8910 if ((h_data_p->type == bcmOAMEndpointTypeBHHMPLS) || 8911 (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv)) { 8912 /* Set the RDI flag in session bits */ 8913 session_flags |= SHR_BHH_SESS_SET_F_RDI; 8914 8915 /* Get the session is from endpoint */ 8916 msg_sess.sess_id = 8917 BCM_OAM_BHH_GET_UKERNEL_EP(h_data_p->ep_id); 8918 8919 /* Pack control message data into DMA buffer */ 8920 msg_sess.flags = session_flags; 8921 8922 buffer = oc->dma_buffer; 8923 buffer_ptr = bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess); 8924 buffer_len = buffer_ptr - buffer; 8925 8926 /* Send BHH Session Update message to uC */ 8927 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 8928 MOS_MSG_SUBCLASS_BHH_SESS_SET, 8929 buffer_len, 0, 8930 MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY, 8931 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 8932 if (BCM_FAILURE(rv)) { 8933 LOG_ERROR(BSL_LS_BCM_OAM, 8934 (BSL_META_U(unit, 8935 "OAM Error: ukernel msg failed for" 8936 "%s.\n"), bcm_errmsg(rv))); 8937 _BCM_OAM_UNLOCK(oc); 8938 return (BCM_E_INTERNAL); 8939 } 8940 } 8941 cur = cur->next; 8942 } 8943 } 8944 #endif 8945 } 8946 8947 /* Enable hardware lookup for this entry. */ 8948 soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, VALIDf, 1); 8949 8950 8951 /* Write entry to hardware. */ 8952 rv = WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL, group_info->id, 8953 &maid_reduction_entry); 8954 if (SOC_FAILURE(rv)) { 8955 _BCM_OAM_UNLOCK(oc); 8956 return rv; 8957 } 8958 8959 /* 8960 * Maintenance Association State table update. 8961 */ 8962 sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t)); 8963 8964 /* 8965 * If it a group info replace operation, retain previous group 8966 * defect status. 8967 */ 8968 if (group_info->flags & BCM_OAM_GROUP_REPLACE) { 8969 rv = READ_MA_STATEm(unit, MEM_BLOCK_ALL, group_info->id, 8970 &ma_state_entry); 8971 if (SOC_FAILURE(rv)) { 8972 _BCM_OAM_UNLOCK(oc); 8973 return rv; 8974 } 8975 } 8976 8977 /* Set the lowest alarm priority info. */ 8978 soc_MA_STATEm_field32_set(unit, &ma_state_entry, LOWESTALARMPRIf, 8979 group_info->lowest_alarm_priority); 8980 8981 /* Mark the entry as valid. */ 8982 soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, 1); 8983 8984 /* Write group information to hardware table. */ 8985 rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group_info->id, &ma_state_entry); 8986 if (SOC_FAILURE(rv)) { 8987 _BCM_OAM_UNLOCK(oc); 8988 return rv; 8989 } 8990 8991 /* Make the group as in used status. */ 8992 ma_group->in_use = 1; 8993 8994 _BCM_OAM_UNLOCK(oc); 8995 8996 #ifdef BCM_WARM_BOOT_SUPPORT 8997 SOC_CONTROL_LOCK(unit); 8998 SOC_CONTROL(unit)->scache_dirty = 1; 8999 SOC_CONTROL_UNLOCK(unit); 9000 #endif 9001 9002 return (BCM_E_NONE); 9003 } 9004 9005 /* 9006 * Function: 9007 * bcm_tr3_oam_group_get 9008 * Purpose: 9009 * Get an OAM group object 9010 * Parameters: 9011 * unit - (IN) BCM device number 9012 * group - (IN) OAM Group ID. 9013 * group_info - (OUT) Pointer to group information buffer. 9014 * Returns: 9015 * BCM_E_XXX 9016 */ 9017 int 9018 bcm_tr3_oam_group_get(int unit, bcm_oam_group_t group, 9019 bcm_oam_group_info_t *group_info) 9020 { 9021 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 9022 _bcm_oam_group_data_t *group_p; /* Pointer to group list. */ 9023 int rv; /* Operation return status. */ 9024 9025 #if defined(INCLUDE_BHH) 9026 bhh_sdk_msg_ctrl_sess_get_t msg; 9027 uint8 *buffer, *buffer_ptr; 9028 uint16 buffer_len, reply_len; 9029 _bcm_oam_hash_data_t *h_data_p; 9030 _bcm_oam_ep_list_t *cur = NULL; 9031 int sess_id = 0; 9032 #endif 9033 9034 /* Validate input parameter. */ 9035 if (NULL == group_info) { 9036 return (BCM_E_PARAM); 9037 } 9038 9039 /* Get OAM device control structure. */ 9040 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 9041 9042 /* Validate group index. */ 9043 _BCM_OAM_GROUP_INDEX_VALIDATE(group); 9044 9045 _BCM_OAM_LOCK(oc); 9046 9047 /* Check if the group is in use. */ 9048 rv = shr_idxres_list_elem_state(oc->group_pool, group); 9049 if (BCM_E_EXISTS != rv) { 9050 _BCM_OAM_UNLOCK(oc); 9051 LOG_ERROR(BSL_LS_BCM_OAM, 9052 (BSL_META_U(unit, 9053 "OAM Error: GID=%d - %s.\n"), 9054 group, bcm_errmsg(rv))); 9055 return (rv); 9056 } 9057 9058 /* Get pointer to this group in the group list. */ 9059 group_p = oc->group_info; 9060 9061 /* Get the group information. */ 9062 rv = _bcm_tr3_oam_get_group(unit, group, group_p, group_info); 9063 if (BCM_FAILURE(rv)) { 9064 _BCM_OAM_UNLOCK(oc); 9065 LOG_ERROR(BSL_LS_BCM_OAM, 9066 (BSL_META_U(unit, 9067 "OAM Error: bcm_tr3_oam_group_get Group ID=%d " 9068 "- Failed.\n"), group)); 9069 return (rv); 9070 } 9071 9072 if (soc_feature(unit, soc_feature_bhh)) { 9073 #if defined(INCLUDE_BHH) 9074 if (!oc->ukernel_not_ready) { 9075 group_p = &oc->group_info[group_info->id]; 9076 /* Get the endpoint list head pointer. */ 9077 if (group_p->ep_list != NULL) { 9078 cur = *(group_p->ep_list); 9079 } 9080 9081 while (NULL != cur) { 9082 h_data_p = cur->ep_data_p; 9083 if (NULL == h_data_p) { 9084 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 9085 "OAM(unit %d) Error: Group=%d endpoints access failed -" 9086 " %s.\n"), unit, group_info->id, 9087 bcm_errmsg(BCM_E_INTERNAL))); 9088 _BCM_OAM_UNLOCK(oc); 9089 return (BCM_E_INTERNAL); 9090 } 9091 if ((h_data_p->type == bcmOAMEndpointTypeBHHMPLS) || 9092 (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv)) { 9093 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(h_data_p->ep_id); 9094 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 9095 MOS_MSG_SUBCLASS_BHH_SESS_GET, 9096 sess_id, 0, 9097 MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY, 9098 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 9099 if (BCM_FAILURE(rv)) { 9100 LOG_ERROR(BSL_LS_BCM_OAM, 9101 (BSL_META_U(unit, 9102 "OAM Error: ukernel msg failed for" 9103 "%s.\n"), bcm_errmsg(rv))); 9104 _BCM_OAM_UNLOCK(oc); 9105 return (rv); 9106 } 9107 9108 /* Pack control message data into DMA buffer */ 9109 buffer = oc->dma_buffer; 9110 buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg); 9111 buffer_len = buffer_ptr - buffer; 9112 9113 if (reply_len != buffer_len) { 9114 rv = BCM_E_INTERNAL; 9115 LOG_ERROR(BSL_LS_BCM_OAM, 9116 (BSL_META_U(unit, 9117 "OAM(unit %d) Error: ukernel msg failed for" 9118 " EP=%d %s.\n"), unit, h_data_p->ep_id, 9119 bcm_errmsg(rv))); 9120 _BCM_OAM_UNLOCK(oc); 9121 return (rv); 9122 } else { 9123 if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){ 9124 group_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT; 9125 } 9126 if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){ 9127 group_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI; 9128 } 9129 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){ 9130 group_info->faults |= 9131 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL; 9132 } 9133 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){ 9134 group_info->faults |= 9135 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID; 9136 } 9137 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){ 9138 group_info->faults |= 9139 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID; 9140 } 9141 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){ 9142 group_info->faults |= 9143 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD; 9144 } 9145 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){ 9146 group_info->faults |= 9147 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY; 9148 } 9149 if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) { 9150 group_info->faults |= 9151 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS; 9152 } 9153 if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) { 9154 group_info->faults |= 9155 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI; 9156 } 9157 if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) { 9158 group_info->faults |= 9159 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI; 9160 } 9161 } 9162 } 9163 cur = cur->next; 9164 } 9165 } 9166 #endif 9167 } 9168 9169 _BCM_OAM_UNLOCK(oc); 9170 return (BCM_E_NONE); 9171 } 9172 9173 /* 9174 * Function: 9175 * bcm_tr3_oam_group_destroy 9176 * Purpose: 9177 * Destroy an OAM group object and its associated endpoints. 9178 * Parameters: 9179 * unit - (IN) BCM device number 9180 * group - (IN) The ID of the OAM group object to destroy 9181 * Returns: 9182 * BCM_E_XXX 9183 */ 9184 int 9185 bcm_tr3_oam_group_destroy(int unit, 9186 bcm_oam_group_t group) 9187 { 9188 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 9189 _bcm_oam_group_data_t *g_info_p; /* Pointer to group list. */ 9190 int rv; /* Operation return status. */ 9191 maid_reduction_entry_t maid_reduction_entry; /* MAID_REDUCTION entry. */ 9192 ma_state_entry_t ma_state_entry; /* MA_STATE table entry. */ 9193 9194 /* Get OAM device control structure. */ 9195 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 9196 9197 /* Validate group index. */ 9198 _BCM_OAM_GROUP_INDEX_VALIDATE(group); 9199 9200 _BCM_OAM_LOCK(oc); 9201 9202 /* Check if the group is in use. */ 9203 rv = shr_idxres_list_elem_state(oc->group_pool, group); 9204 if (BCM_E_EXISTS != rv) { 9205 _BCM_OAM_UNLOCK(oc); 9206 LOG_ERROR(BSL_LS_BCM_OAM, 9207 (BSL_META_U(unit, 9208 "OAM Error: GID=%d - %s.\n"), 9209 group, bcm_errmsg(rv))); 9210 return (rv); 9211 } 9212 9213 /* Get pointer to this group in the group list. */ 9214 g_info_p = &oc->group_info[group]; 9215 9216 rv = _bcm_tr3_oam_group_endpoints_destroy(unit, g_info_p); 9217 if (BCM_FAILURE(rv)) { 9218 _BCM_OAM_UNLOCK(oc); 9219 LOG_ERROR(BSL_LS_BCM_OAM, 9220 (BSL_META_U(unit, 9221 "OAM Error: bcm_tr3_oam_endpoint_destroy_all" 9222 " (GID=%d) - %s.\n"), group, bcm_errmsg(rv))); 9223 return (rv); 9224 } 9225 9226 sal_memset(&maid_reduction_entry, 0, sizeof(maid_reduction_entry_t)); 9227 rv = WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL, group, 9228 &maid_reduction_entry); 9229 if (BCM_FAILURE(rv)) { 9230 _BCM_OAM_UNLOCK(oc); 9231 LOG_DEBUG(BSL_LS_BCM_OAM, 9232 (BSL_META_U(unit, 9233 "OAM Error: MAID REDUCTION write " 9234 "(GID=%d) - %s.\n"), group, bcm_errmsg(rv))); 9235 return (rv); 9236 } 9237 9238 /* 9239 * Maintenance Association State table update. 9240 */ 9241 sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t)); 9242 9243 rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group, &ma_state_entry); 9244 if (BCM_FAILURE(rv)) { 9245 _BCM_OAM_UNLOCK(oc); 9246 LOG_ERROR(BSL_LS_BCM_OAM, 9247 (BSL_META_U(unit, 9248 "OAM Error: MA STATE write " 9249 "(GID=%d) - %s.\n"), group, bcm_errmsg(rv))); 9250 return (rv); 9251 } 9252 9253 /* Return Group ID back to free group. */ 9254 rv = shr_idxres_list_free(oc->group_pool, group); 9255 if (BCM_FAILURE(rv)) { 9256 _BCM_OAM_UNLOCK(oc); 9257 LOG_ERROR(BSL_LS_BCM_OAM, 9258 (BSL_META_U(unit, 9259 "OAM Error: Idx free failed " 9260 "(GID=%d) - %s.\n"), group, bcm_errmsg(rv))); 9261 return (rv); 9262 } 9263 9264 _BCM_OAM_UNLOCK(oc); 9265 9266 #ifdef BCM_WARM_BOOT_SUPPORT 9267 SOC_CONTROL_LOCK(unit); 9268 SOC_CONTROL(unit)->scache_dirty = 1; 9269 SOC_CONTROL_UNLOCK(unit); 9270 #endif 9271 9272 return (BCM_E_NONE); 9273 } 9274 9275 /* 9276 * Function: 9277 * bcm_tr3_oam_group_destroy_all 9278 * Purpose: 9279 * Destroy all OAM group objects and their associated endpoints. 9280 * Parameters: 9281 * unit - (IN) BCM device number 9282 * Returns: 9283 * BCM_E_XXX 9284 */ 9285 int 9286 bcm_tr3_oam_group_destroy_all(int unit) 9287 { 9288 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 9289 int group; /* Maintenance Association group index. */ 9290 int rv; /* Operation return status . */ 9291 9292 /* Get device OAM control structure handle. */ 9293 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 9294 9295 _BCM_OAM_LOCK(oc); 9296 9297 for (group = 0; group < oc->group_count; group++) { 9298 9299 /* Check if the group is in use. */ 9300 rv = shr_idxres_list_elem_state(oc->group_pool, group); 9301 if (BCM_E_EXISTS != rv) { 9302 continue; 9303 } 9304 9305 rv = bcm_tr3_oam_group_destroy(unit, group); 9306 if (BCM_FAILURE(rv)) { 9307 _BCM_OAM_UNLOCK(oc); 9308 LOG_ERROR(BSL_LS_BCM_OAM, 9309 (BSL_META_U(unit, 9310 "OAM Error: Group destroy failed " 9311 "(GID=%d) - %s.\n"), group, bcm_errmsg(rv))); 9312 return (rv); 9313 } 9314 } 9315 9316 _BCM_OAM_UNLOCK(oc); 9317 9318 #ifdef BCM_WARM_BOOT_SUPPORT 9319 SOC_CONTROL_LOCK(unit); 9320 SOC_CONTROL(unit)->scache_dirty = 1; 9321 SOC_CONTROL_UNLOCK(unit); 9322 #endif 9323 9324 return (BCM_E_NONE); 9325 } 9326 9327 /* 9328 * Function: 9329 * bcm_tr3_oam_group_traverse 9330 * Purpose: 9331 * Traverse the entire set of OAM groups, calling a specified 9332 * callback for each one 9333 * Parameters: 9334 * unit - (IN) BCM device number 9335 * cb - (IN) Pointer to call back function. 9336 * user_data - (IN) Pointer to user supplied data. 9337 * Returns: 9338 * BCM_E_XXX 9339 */ 9340 int 9341 bcm_tr3_oam_group_traverse(int unit, bcm_oam_group_traverse_cb cb, 9342 void *user_data) 9343 { 9344 _bcm_oam_control_t *oc; /* OAM control structure pointer. */ 9345 bcm_oam_group_info_t group_info; /* Group information to be set. */ 9346 bcm_oam_group_t grp_idx; /* MA Group index. */ 9347 _bcm_oam_group_data_t *group_p; /* Pointer to group list. */ 9348 int rv; /* Operation return status. */ 9349 9350 if (NULL == cb) { 9351 return (BCM_E_PARAM); 9352 } 9353 9354 /* Get device OAM control structure handle. */ 9355 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 9356 9357 _BCM_OAM_LOCK(oc); 9358 9359 /* Initialize to group array pointer. */ 9360 group_p = oc->group_info; 9361 9362 for (grp_idx = 0; grp_idx < oc->group_count; grp_idx++) { 9363 9364 /* Check if the group is in use. */ 9365 if (BCM_E_EXISTS 9366 == shr_idxres_list_elem_state(oc->group_pool, grp_idx)) { 9367 9368 /* Initialize the group information structure. */ 9369 bcm_oam_group_info_t_init(&group_info); 9370 9371 /* Retrieve group information and set in group_info structure. */ 9372 rv = _bcm_tr3_oam_get_group(unit, grp_idx, group_p, &group_info); 9373 if (BCM_FAILURE(rv)) { 9374 _BCM_OAM_UNLOCK(oc); 9375 LOG_ERROR(BSL_LS_BCM_OAM, 9376 (BSL_META_U(unit, 9377 "OAM Error: _bcm_tr3_oam_get_group " 9378 "(GID=%d) - %s.\n"), grp_idx, bcm_errmsg(rv))); 9379 return (rv); 9380 } 9381 9382 /* Call the user call back routine with group information. */ 9383 rv = cb(unit, &group_info, user_data); 9384 if (BCM_FAILURE(rv)) { 9385 _BCM_OAM_UNLOCK(oc); 9386 LOG_ERROR(BSL_LS_BCM_OAM, 9387 (BSL_META_U(unit, 9388 "OAM Error: User call back routine " 9389 "(GID=%d) - %s.\n"), grp_idx, bcm_errmsg(rv))); 9390 return (rv); 9391 } 9392 } 9393 } 9394 9395 _BCM_OAM_UNLOCK(oc); 9396 9397 return (BCM_E_NONE); 9398 } 9399 9400 /* 9401 * Function: 9402 * bcm_tr3_oam_endpoint_create 9403 * Purpose: 9404 * Create or replace an OAM endpoint object 9405 * Parameters: 9406 * unit - (IN) BCM device number 9407 * endpoint_info - (IN/OUT) Pointer to endpoint information buffer. 9408 * Returns: 9409 * BCM_E_XXX 9410 */ 9411 int 9412 bcm_tr3_oam_endpoint_create(int unit, bcm_oam_endpoint_info_t *endpoint_info) 9413 { 9414 _bcm_oam_hash_data_t *hash_data = NULL; /* Endpoint hash data pointer. */ 9415 _bcm_oam_hash_data_t h_data_stored; /* Stored hash data. */ 9416 _bcm_oam_hash_key_t hash_key; /* Hash Key buffer. */ 9417 int ep_req_index; /* Requested endpoint index. */ 9418 int rv; /* Operation return status. */ 9419 _bcm_oam_control_t *oc; /* Pointer to OAM control */ 9420 /* structure. */ 9421 uint32 sglp = 0; /* Source global logical port. */ 9422 uint32 dglp = 0; /* Dest global logical port. */ 9423 int mep_ccm_tx = 0; /* Endpoint CCM Tx status. */ 9424 int mep_ccm_rx = 0; /* Endpoint CCM Rx status. */ 9425 int remote = 0; /* Remote endpoint status. */ 9426 bcm_gport_t tx_gport; 9427 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 9428 9429 9430 LOG_DEBUG(BSL_LS_BCM_OAM, 9431 (BSL_META_U(unit, 9432 "OAM Info: bcm_tr3_oam_endpoint_create " 9433 "Endpoint ID=%d.\n"), endpoint_info->id)); 9434 9435 /* Validate input parameter. */ 9436 if (NULL == endpoint_info) { 9437 return (BCM_E_PARAM); 9438 } 9439 9440 /* Get OAM Control Structure. */ 9441 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 9442 9443 _BCM_OAM_LOCK(oc); 9444 9445 #if defined(KEY_PRINT) 9446 _bcm_oam_hash_key_print(&hash_key); 9447 #endif 9448 9449 /* Calculate the hash key for given enpoint input parameters. */ 9450 _bcm_oam_ep_hash_key_construct(unit, oc, endpoint_info, &hash_key); 9451 9452 /* Validate endpoint input parameters. */ 9453 rv = _bcm_tr3_oam_endpoint_params_validate(unit, oc, &hash_key, 9454 endpoint_info); 9455 if (BCM_FAILURE(rv)) { 9456 LOG_ERROR(BSL_LS_BCM_OAM, 9457 (BSL_META_U(unit, 9458 "OAM Error: (EP=%d) - %s.\n"), 9459 endpoint_info->id, bcm_errmsg(rv))); 9460 _BCM_OAM_UNLOCK(oc); 9461 return (rv); 9462 } 9463 9464 /* Get MEP CCM Tx status. */ 9465 mep_ccm_tx 9466 = ((endpoint_info->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) 9467 ? 1 : 0); 9468 9469 /* Get MEP CCM Rx status. */ 9470 mep_ccm_rx 9471 = ((endpoint_info->flags & _BCM_OAM_EP_RX_ENABLE) ? 1 : 0); 9472 9473 /* Get MEP remote endpoint status. */ 9474 remote = (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0; 9475 9476 if(soc_feature(unit, soc_feature_bhh)) { 9477 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 9478 if((endpoint_info->type == bcmOAMEndpointTypeBHHMPLS) || 9479 (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv)) 9480 { 9481 if ((oc->ukernel_not_ready == 1) && 9482 (!(endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU))){ 9483 LOG_ERROR(BSL_LS_BCM_OAM, 9484 (BSL_META_U(unit, 9485 "OAM(unit %d) Error: BTE(ukernel) " 9486 "not ready.\n"), unit)); 9487 _BCM_OAM_UNLOCK(oc); 9488 return (BCM_E_INIT); 9489 } 9490 9491 rv = bcm_tr3_oam_bhh_endpoint_create(unit, endpoint_info, &hash_key); 9492 if (BCM_FAILURE(rv)) { 9493 LOG_ERROR(BSL_LS_BCM_OAM, 9494 (BSL_META_U(unit, 9495 "OAM Error: BHH Endpoint create (EP=%d) - %s.\n"), 9496 endpoint_info->id, bcm_errmsg(rv))); 9497 } 9498 _BCM_OAM_UNLOCK(oc); 9499 9500 return (rv); 9501 } 9502 #endif /* INCLUDE_BHH */ 9503 } 9504 9505 /* Resolve given endpoint gport value to Source GLP and Dest GLP values. */ 9506 rv = _bcm_tr3_oam_endpoint_gport_resolve(unit, endpoint_info, &sglp, 9507 &dglp, &trunk_id, &tx_gport); 9508 if (BCM_FAILURE(rv)) { 9509 LOG_ERROR(BSL_LS_BCM_OAM, 9510 (BSL_META_U(unit, 9511 "OAM Error: Gport resolve (EP=%d) - %s.\n"), 9512 endpoint_info->id, bcm_errmsg(rv))); 9513 _BCM_OAM_UNLOCK(oc); 9514 return (rv); 9515 } 9516 9517 /* Replace an existing endpoint. */ 9518 if (endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) { 9519 9520 rv = _bcm_tr3_oam_endpoint_destroy(unit, endpoint_info->id); 9521 if (BCM_FAILURE(rv)) { 9522 LOG_ERROR(BSL_LS_BCM_OAM, 9523 (BSL_META_U(unit, 9524 "OAM Error: Endpoint destroy (EP=%d) - %s.\n"), 9525 endpoint_info->id, bcm_errmsg(rv))); 9526 _BCM_OAM_UNLOCK(oc); 9527 return (rv); 9528 } 9529 } 9530 9531 /* Create a new endpoint with the requested ID. */ 9532 if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) { 9533 ep_req_index = endpoint_info->id; 9534 9535 rv = shr_idxres_list_reserve(oc->mep_pool, ep_req_index, 9536 ep_req_index); 9537 if (BCM_FAILURE(rv)) { 9538 LOG_ERROR(BSL_LS_BCM_OAM, 9539 (BSL_META_U(unit, 9540 "OAM Error: Endpoint reserve (EP=%d) - %s.\n"), 9541 endpoint_info->id, bcm_errmsg(rv))); 9542 _BCM_OAM_UNLOCK(oc); 9543 return ((rv == BCM_E_RESOURCE) ? BCM_E_EXISTS : rv); 9544 } 9545 } else { 9546 9547 /* Allocate the next available endpoint index. */ 9548 rv = shr_idxres_list_alloc(oc->mep_pool, 9549 (shr_idxres_element_t *)&ep_req_index); 9550 if (BCM_FAILURE(rv)) { 9551 LOG_ERROR(BSL_LS_BCM_OAM, 9552 (BSL_META_U(unit, 9553 "OAM Error: Endpoint alloc failed - %s.\n"), 9554 bcm_errmsg(rv))); 9555 _BCM_OAM_UNLOCK(oc); 9556 return (rv); 9557 } 9558 /* Set the allocated endpoint id value. */ 9559 endpoint_info->id = ep_req_index; 9560 } 9561 9562 /* Get the hash data pointer where the data is to be stored. */ 9563 hash_data = &oc->oam_hash_data[ep_req_index]; 9564 9565 /* Clear the hash data element contents before storing the values. */ 9566 _BCM_OAM_HASH_DATA_CLEAR(hash_data); 9567 hash_data->type = endpoint_info->type; 9568 hash_data->ep_id = endpoint_info->id; 9569 hash_data->is_remote = remote; 9570 hash_data->local_tx_enabled = mep_ccm_tx; 9571 hash_data->local_rx_enabled = mep_ccm_rx; 9572 hash_data->group_index = endpoint_info->group; 9573 hash_data->name = endpoint_info->name; 9574 hash_data->level = endpoint_info->level; 9575 hash_data->vlan = endpoint_info->vlan; 9576 hash_data->gport = endpoint_info->gport; 9577 hash_data->sglp = sglp; 9578 hash_data->dglp = dglp; 9579 hash_data->flags = endpoint_info->flags; 9580 hash_data->opcode_flags = (endpoint_info->opcode_flags & 9581 _BCM_TR3_OAM_OPCODE_MASK); 9582 hash_data->period = endpoint_info->ccm_period; 9583 hash_data->in_use = 1; 9584 hash_data->fp_entry_tx = -1; 9585 hash_data->fp_entry_rx = -1; 9586 hash_data->fp_entry_trunk[0] = -1; 9587 hash_data->ts_format = endpoint_info->timestamp_format; 9588 9589 /* Initialize hardware index as invalid indices. */ 9590 hash_data->local_tx_index = _BCM_OAM_INVALID_INDEX; 9591 hash_data->local_rx_index = _BCM_OAM_INVALID_INDEX; 9592 hash_data->remote_index = _BCM_OAM_INVALID_INDEX; 9593 9594 if (1 == remote) { 9595 /* Allocate the next available index for RMEP table. */ 9596 rv = shr_idxres_list_alloc 9597 (oc->rmep_pool, 9598 (shr_idxres_element_t *)&hash_data->remote_index); 9599 if (BCM_FAILURE(rv)) { 9600 _BCM_OAM_UNLOCK(oc); 9601 LOG_ERROR(BSL_LS_BCM_OAM, 9602 (BSL_META_U(unit, 9603 "OAM Error: RMEP index alloc failed EP:%d %s.\n"), 9604 endpoint_info->id, bcm_errmsg(rv))); 9605 return (rv); 9606 } 9607 } else { 9608 9609 /* Allocate the next available index for LMEP table. */ 9610 if (1 == mep_ccm_tx) { 9611 rv = shr_idxres_list_alloc 9612 (oc->lmep_pool, 9613 (shr_idxres_element_t *)&hash_data->local_tx_index); 9614 if (BCM_FAILURE(rv)) { 9615 _BCM_OAM_UNLOCK(oc); 9616 LOG_ERROR(BSL_LS_BCM_OAM, 9617 (BSL_META_U(unit, 9618 "OAM Error: LMEP Tx index alloc failed EP:%d " 9619 "%s.\n"), endpoint_info->id, bcm_errmsg(rv))); 9620 return (rv); 9621 } 9622 } 9623 9624 /* Allocate the next available index for MA_INDEX table. */ 9625 if (1 == mep_ccm_rx) { 9626 rv = _bcm_oam_rx_endpoint_reserve(unit, endpoint_info); 9627 if (BCM_FAILURE(rv)) { 9628 if (1 == mep_ccm_tx) { 9629 /* Return Tx index to the LMEP pool. */ 9630 shr_idxres_list_free(oc->lmep_pool, 9631 hash_data->local_tx_index); 9632 } 9633 9634 /* Return endpoint index to MEP pool. */ 9635 shr_idxres_list_free(oc->mep_pool, endpoint_info->id); 9636 9637 _BCM_OAM_UNLOCK(oc); 9638 LOG_ERROR(BSL_LS_BCM_OAM, 9639 (BSL_META_U(unit, 9640 "OAM Error: LMEP Rx index alloc failed EP:%d " 9641 "%s.\n"), endpoint_info->id, bcm_errmsg(rv))); 9642 return (rv); 9643 } 9644 } 9645 } 9646 9647 9648 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, hash_data); 9649 if (BCM_FAILURE(rv)) { 9650 LOG_ERROR(BSL_LS_BCM_OAM, 9651 (BSL_META_U(unit, 9652 "OAM Error: Hash table insert failed EP=%d %s.\n"), 9653 endpoint_info->id, bcm_errmsg(rv))); 9654 _BCM_OAM_UNLOCK(oc); 9655 return (rv); 9656 } 9657 9658 if (1 == remote) { 9659 rv = _bcm_oam_remote_mep_hw_set(unit, endpoint_info); 9660 if (BCM_FAILURE(rv)) { 9661 LOG_DEBUG(BSL_LS_BCM_OAM, 9662 (BSL_META_U(unit, 9663 "OAM Error: Remote MEP set failed EP=%d %s.\n"), 9664 endpoint_info->id, bcm_errmsg(rv))); 9665 /* 9666 * If not a replace operation, return the allocated indices 9667 * to free pool. 9668 */ 9669 if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE)) { 9670 shr_idxres_list_free(oc->mep_pool, endpoint_info->id); 9671 shr_idxres_list_free(oc->rmep_pool, hash_data->remote_index); 9672 9673 /* Return entry to hash data free pool. */ 9674 shr_htb_find(oc->ma_mep_htbl, hash_key, 9675 (shr_htb_data_t *) &h_data_stored, 1); 9676 9677 /* Clear contents of hash data element. */ 9678 _BCM_OAM_HASH_DATA_CLEAR(hash_data); 9679 } 9680 _BCM_OAM_UNLOCK(oc); 9681 return (rv); 9682 } 9683 } else { 9684 if (mep_ccm_tx) { 9685 9686 rv = _bcm_oam_local_tx_mep_hw_set(unit, endpoint_info); 9687 9688 9689 if (BCM_FAILURE(rv)) { 9690 LOG_ERROR(BSL_LS_BCM_OAM, 9691 (BSL_META_U(unit, 9692 "OAM Error: Tx config failed for EP=%d %s.\n"), 9693 endpoint_info->id, bcm_errmsg(rv))); 9694 /* 9695 * If not a replace operation, return the allocated indices 9696 * to free pool. 9697 */ 9698 if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE)) { 9699 shr_idxres_list_free(oc->mep_pool, endpoint_info->id); 9700 shr_idxres_list_free(oc->lmep_pool, 9701 hash_data->local_tx_index); 9702 9703 /* Return entry to hash data entry to free pool. */ 9704 shr_htb_find(oc->ma_mep_htbl, hash_key, 9705 (shr_htb_data_t *)&h_data_stored, 1); 9706 9707 /* Clear contents of hash data element. */ 9708 _BCM_OAM_HASH_DATA_CLEAR(hash_data); 9709 } 9710 _BCM_OAM_UNLOCK(oc); 9711 return (rv); 9712 } 9713 } 9714 9715 if (mep_ccm_rx) { 9716 9717 rv = _bcm_oam_local_rx_mep_hw_set(unit, endpoint_info); 9718 9719 9720 if (BCM_FAILURE(rv)) { 9721 LOG_ERROR(BSL_LS_BCM_OAM, 9722 (BSL_META_U(unit, 9723 "OAM Error: Rx config failed for EP=%d %s.\n"), 9724 endpoint_info->id, bcm_errmsg(rv))); 9725 /* 9726 * If not a replace operation, return the allocated indices 9727 * to free pool. 9728 */ 9729 if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE)) { 9730 shr_idxres_list_free(oc->ma_idx_pool, 9731 hash_data->local_rx_index); 9732 9733 shr_idxres_list_free(oc->mep_pool, endpoint_info->id); 9734 9735 if (1 == mep_ccm_tx) { 9736 shr_idxres_list_free(oc->lmep_pool, 9737 hash_data->local_tx_index); 9738 } 9739 9740 /* Return entry to hash data entry to free pool. */ 9741 shr_htb_find(oc->ma_mep_htbl, hash_key, 9742 (shr_htb_data_t *)&h_data_stored, 1); 9743 9744 /* Clear contents of hash data element. */ 9745 _BCM_OAM_HASH_DATA_CLEAR(hash_data); 9746 9747 } 9748 9749 /* Clear contents of hash data element. */ 9750 _BCM_OAM_UNLOCK(oc); 9751 return (rv); 9752 } else { 9753 if ( endpoint_info->flags & 9754 (BCM_OAM_ENDPOINT_LOSS_MEASUREMENT | 9755 BCM_OAM_ENDPOINT_DELAY_MEASUREMENT)) { 9756 9757 rv = _bcm_tr3_oam_loss_delay_measurement_add(unit, 9758 oc, hash_data, endpoint_info); 9759 if (BCM_FAILURE(rv)) { 9760 LOG_ERROR(BSL_LS_BCM_OAM, 9761 (BSL_META_U(unit, 9762 "OAM Error: FP insert failed for " 9763 "LM DM over EP=%d %s.\n"), endpoint_info->id, 9764 bcm_errmsg(rv))); 9765 9766 /* 9767 * If not a replace operation, return the allocated 9768 * indices to free pool. 9769 */ 9770 if (!(endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE)){ 9771 shr_idxres_list_free(oc->ma_idx_pool, 9772 hash_data->local_rx_index); 9773 9774 shr_idxres_list_free(oc->mep_pool,endpoint_info->id); 9775 9776 if (1 == mep_ccm_tx) { 9777 shr_idxres_list_free(oc->lmep_pool, 9778 hash_data->local_tx_index); 9779 } 9780 9781 /* Return entry to hash data entry to free pool. */ 9782 shr_htb_find(oc->ma_mep_htbl, hash_key, 9783 (shr_htb_data_t *)&h_data_stored, 1); 9784 9785 /* Clear contents of hash data element. */ 9786 _BCM_OAM_HASH_DATA_CLEAR(hash_data); 9787 } 9788 9789 9790 /* Unlock OAM Control Structure. */ 9791 _BCM_OAM_UNLOCK(oc); 9792 return (rv); 9793 } 9794 } 9795 } 9796 } 9797 } 9798 9799 rv = _bcm_oam_group_ep_list_add(unit, endpoint_info->group, 9800 endpoint_info->id); 9801 if (BCM_FAILURE(rv)) { 9802 LOG_ERROR(BSL_LS_BCM_OAM, 9803 (BSL_META_U(unit, 9804 "OAM Error: Tx config failed for EP=%d %s.\n"), 9805 endpoint_info->id, bcm_errmsg(rv))); 9806 _BCM_OAM_UNLOCK(oc); 9807 return (rv); 9808 } 9809 9810 _BCM_OAM_UNLOCK(oc); 9811 9812 /*SDK-147457:HW WAR to fix the issue of wrong LMEP index being written 9813 while deleting and adding same MEP in a loop */ 9814 #ifdef BCM_HURRICANE2_SUPPORT 9815 sal_usleep(3400); 9816 #endif /* BCM_HURRICANE2_SUPPORT */ 9817 9818 #ifdef BCM_WARM_BOOT_SUPPORT 9819 SOC_CONTROL_LOCK(unit); 9820 SOC_CONTROL(unit)->scache_dirty = 1; 9821 SOC_CONTROL_UNLOCK(unit); 9822 #endif 9823 9824 return (BCM_E_NONE); 9825 } 9826 9827 /* 9828 * Function: 9829 * bcm_tr3_oam_endpoint_get 9830 * Purpose: 9831 * Get an OAM endpoint object 9832 * Parameters: 9833 * unit - (IN) BCM device number 9834 * endpoint - (IN) Endpoint ID 9835 * endpoint_info - (OUT) Pointer to OAM endpoint information buffer. 9836 * Returns: 9837 * BCM_E_XXX 9838 */ 9839 int 9840 bcm_tr3_oam_endpoint_get(int unit, bcm_oam_endpoint_t endpoint, 9841 bcm_oam_endpoint_info_t *endpoint_info) 9842 { 9843 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 9844 int rv; /* Operation return status. */ 9845 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 9846 rmep_entry_t rmep_entry; /* Remote MEP entry buffer. */ 9847 lmep_entry_t lmep_entry; /* Local MEP entry buffer. */ 9848 lmep_da_entry_t dmac_entry; /* Local MEP entry buffer. */ 9849 uint8 pri_map[BCM_OAM_INTPRI_MAX]; 9850 int i; 9851 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 9852 bhh_sdk_msg_ctrl_sess_get_t msg; 9853 uint8 *buffer, *buffer_ptr; 9854 uint16 buffer_len, reply_len; 9855 int sess_id = 0; 9856 bcm_l3_egress_t l3_egress; 9857 bcm_l3_intf_t l3_intf; 9858 #endif 9859 #ifdef BCM_HURRICANE2_SUPPORT 9860 uint32 rval = 0; 9861 uint8 tx_disable = 0; 9862 #endif /* BCM_HURRICANE2_SUPPORT */ 9863 9864 if (NULL == endpoint_info) { 9865 return (BCM_E_PARAM); 9866 } 9867 9868 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 9869 9870 /* Validate endpoint index value. */ 9871 _BCM_OAM_EP_INDEX_VALIDATE(endpoint); 9872 9873 _BCM_OAM_LOCK(oc); 9874 9875 h_data_p = &oc->oam_hash_data[endpoint]; 9876 if (NULL == h_data_p) { 9877 _BCM_OAM_UNLOCK(oc); 9878 return (BCM_E_INTERNAL); 9879 } 9880 9881 if (0 == h_data_p->in_use) { 9882 _BCM_OAM_UNLOCK(oc); 9883 return (BCM_E_NOT_FOUND); 9884 } 9885 LOG_DEBUG(BSL_LS_BCM_OAM, 9886 (BSL_META_U(unit, 9887 "OAM Info: Endpoint (EP=%d) remote=%d local_tx=%d" 9888 "local_tx_idx=%d local_rx_en=%d local_rx_idx=%d\n"), 9889 endpoint, h_data_p->is_remote, h_data_p->local_tx_enabled, 9890 h_data_p->local_tx_index, h_data_p->local_rx_enabled, 9891 h_data_p->local_rx_index)); 9892 9893 if (bcmOAMEndpointTypeEthernet == h_data_p->type) { 9894 if (1 == h_data_p->is_remote) { 9895 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 9896 9897 /* Get hardware table entry information. */ 9898 rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index, 9899 &rmep_entry); 9900 if (BCM_FAILURE(rv)) { 9901 LOG_ERROR(BSL_LS_BCM_OAM, 9902 (BSL_META_U(unit, 9903 "OAM Error: RMEP table read failed for" 9904 " EP=%d %s.\n"), endpoint, bcm_errmsg(rv))); 9905 _BCM_OAM_UNLOCK(oc); 9906 return (rv); 9907 } 9908 9909 rv = _bcm_tr3_oam_read_clear_faults(unit, h_data_p->remote_index, 9910 RMEPm, (uint32 *) &rmep_entry, 9911 (void *) endpoint_info); 9912 if (BCM_FAILURE(rv)) { 9913 LOG_ERROR(BSL_LS_BCM_OAM, 9914 (BSL_META_U(unit, 9915 "OAM Error: RMEP table read failed for" 9916 " EP=%d %s.\n"), endpoint, bcm_errmsg(rv))); 9917 _BCM_OAM_UNLOCK(oc); 9918 return (rv); 9919 } 9920 if (endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_GET_FAULTS_ONLY) { 9921 endpoint_info->flags2 &= ~BCM_OAM_ENDPOINT_FLAGS2_GET_FAULTS_ONLY; 9922 _BCM_OAM_UNLOCK(oc); 9923 return BCM_E_NONE; 9924 } 9925 } else { 9926 if (1 == h_data_p->local_tx_enabled) { 9927 sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t)); 9928 #ifdef BCM_HURRICANE2_SUPPORT 9929 rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 1, 9930 &tx_disable); 9931 if (BCM_FAILURE(rv)) { 9932 LOG_ERROR(BSL_LS_BCM_OAM, 9933 (BSL_META_U(unit, 9934 "OAM Error: in _bcm_oam_modify_oam_tx_control \n"))); 9935 return (rv); 9936 } 9937 #endif /* BCM_HURRICANE2_SUPPORT */ 9938 /* Get hardware table entry information. */ 9939 rv = READ_LMEPm(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, 9940 &lmep_entry); 9941 if (BCM_FAILURE(rv)) { 9942 LOG_ERROR(BSL_LS_BCM_OAM, 9943 (BSL_META_U(unit, 9944 "OAM Error: LMEP table read failed for" 9945 " EP=%d %s.\n"), endpoint, bcm_errmsg(rv))); 9946 _BCM_OAM_UNLOCK(oc); 9947 return (rv); 9948 } 9949 9950 soc_LMEPm_mac_addr_get(unit, &lmep_entry, SAf, 9951 endpoint_info->src_mac_address); 9952 endpoint_info->pkt_pri = soc_LMEPm_field32_get(unit, 9953 &lmep_entry, 9954 LMEP_PRIORITYf); 9955 endpoint_info->int_pri = soc_LMEPm_field32_get(unit, 9956 &lmep_entry, 9957 INT_PRIf); 9958 endpoint_info->port_state = (soc_LMEPm_field32_get(unit, 9959 &lmep_entry, PORT_TLVf) 9960 ? BCM_OAM_PORT_TLV_UP 9961 : BCM_OAM_PORT_TLV_BLOCKED); 9962 endpoint_info->interface_state = soc_LMEPm_field32_get(unit, 9963 &lmep_entry, INTERFACE_TLVf); 9964 9965 sal_memset(&dmac_entry, 0, sizeof(lmep_da_entry_t)); 9966 9967 /* Get hardware table entry information. */ 9968 rv = READ_LMEP_DAm(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, 9969 &dmac_entry); 9970 #ifdef BCM_HURRICANE2_SUPPORT 9971 if (tx_disable) { 9972 rv = _bcm_oam_modify_oam_tx_control (unit, &rval, 0, 9973 &tx_disable); 9974 if (BCM_FAILURE(rv)) { 9975 LOG_ERROR(BSL_LS_BCM_OAM, 9976 (BSL_META_U(unit, 9977 "OAM Error: in _bcm_oam_modify_oam_tx_control \n"))); 9978 return (rv); 9979 } 9980 } 9981 #endif /* BCM_HURRICANE2_SUPPORT */ 9982 if (BCM_FAILURE(rv)) { 9983 LOG_ERROR(BSL_LS_BCM_OAM, 9984 (BSL_META_U(unit, 9985 "OAM Error: LMEP_DA table read failed for" 9986 " EP=%d %s.\n"), endpoint, bcm_errmsg(rv))); 9987 _BCM_OAM_UNLOCK(oc); 9988 return (rv); 9989 } 9990 9991 #ifdef BCM_HURRICANE2_SUPPORT 9992 if (SOC_IS_HURRICANE2(unit) || SOC_IS_GREYHOUND(unit) || 9993 SOC_IS_HURRICANE3(unit) || SOC_IS_GREYHOUND2(unit)) { 9994 soc_mem_mac_addr_get(unit, LMEP_DAm, &dmac_entry, MACDAf, 9995 endpoint_info->dst_mac_address); 9996 9997 } else 9998 #endif /* BCM_HURRICANE2_SUPPORT */ 9999 { 10000 soc_mem_mac_addr_get(unit, LMEP_DAm, &dmac_entry, DAf, 10001 endpoint_info->dst_mac_address); 10002 } 10003 } 10004 } 10005 } 10006 else if (soc_feature(unit, soc_feature_bhh) && 10007 ((h_data_p->type == bcmOAMEndpointTypeBHHMPLS) || 10008 (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv))) { 10009 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 10010 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint); 10011 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 10012 MOS_MSG_SUBCLASS_BHH_SESS_GET, 10013 sess_id, 0, 10014 MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY, 10015 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 10016 if (BCM_FAILURE(rv)) { 10017 LOG_ERROR(BSL_LS_BCM_OAM, 10018 (BSL_META_U(unit, 10019 "OAM Error: ukernel msg failed for" 10020 " EP=%d %s.\n"), endpoint, bcm_errmsg(rv))); 10021 _BCM_OAM_UNLOCK(oc); 10022 return (rv); 10023 } 10024 10025 /* Pack control message data into DMA buffer */ 10026 buffer = oc->dma_buffer; 10027 buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg); 10028 buffer_len = buffer_ptr - buffer; 10029 10030 if (reply_len != buffer_len) { 10031 rv = BCM_E_INTERNAL; 10032 LOG_ERROR(BSL_LS_BCM_OAM, 10033 (BSL_META_U(unit, 10034 "OAM Error: ukernel msg failed for" 10035 " EP=%d %s.\n"), endpoint, bcm_errmsg(rv))); 10036 _BCM_OAM_UNLOCK(oc); 10037 return (rv); 10038 } else { 10039 endpoint_info->int_pri = msg.tx_cos; 10040 endpoint_info->pkt_pri = msg.tx_pri; 10041 endpoint_info->mpls_exp = msg.priority; 10042 10043 if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE){ 10044 endpoint_info->name = msg.remote_mep_id; 10045 endpoint_info->ccm_period = msg.remote_period; 10046 } else { 10047 endpoint_info->name = msg.mep_id; 10048 endpoint_info->ccm_period = msg.local_period; 10049 } 10050 10051 if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){ 10052 endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT; 10053 } 10054 if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){ 10055 endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI; 10056 } 10057 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){ 10058 endpoint_info->faults |= 10059 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL; 10060 } 10061 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){ 10062 endpoint_info->faults |= 10063 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID; 10064 } 10065 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){ 10066 endpoint_info->faults |= 10067 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID; 10068 } 10069 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){ 10070 endpoint_info->faults |= 10071 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD; 10072 } 10073 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){ 10074 endpoint_info->faults |= 10075 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY; 10076 } 10077 if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) { 10078 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS; 10079 } 10080 if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) { 10081 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI; 10082 } 10083 if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) { 10084 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI; 10085 } 10086 } 10087 10088 endpoint_info->intf_id = h_data_p->egress_if; 10089 endpoint_info->cpu_qid = h_data_p->cpu_qid; 10090 endpoint_info->mpls_label = h_data_p->label; 10091 endpoint_info->gport = h_data_p->gport; 10092 endpoint_info->vpn = h_data_p->vpn; 10093 endpoint_info->vccv_type = h_data_p->vccv_type; 10094 endpoint_info->egress_label.label = h_data_p->egr_label; 10095 endpoint_info->egress_label.exp = h_data_p->egr_label_exp; 10096 endpoint_info->egress_label.ttl = h_data_p->egr_label_ttl; 10097 10098 /* 10099 * Get MAC address 10100 */ 10101 bcm_l3_egress_t_init(&l3_egress); 10102 bcm_l3_intf_t_init(&l3_intf); 10103 10104 if (BCM_FAILURE 10105 (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) { 10106 _BCM_OAM_UNLOCK(oc); 10107 return (BCM_E_INTERNAL); 10108 } 10109 10110 l3_intf.l3a_intf_id = l3_egress.intf; 10111 if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) { 10112 _BCM_OAM_UNLOCK(oc); 10113 return (BCM_E_INTERNAL); 10114 } 10115 10116 sal_memcpy(endpoint_info->src_mac_address, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH); 10117 #else 10118 _BCM_OAM_UNLOCK(oc); 10119 return (BCM_E_UNAVAIL); 10120 #endif /* INCLUDE_BHH */ 10121 } 10122 else { 10123 _BCM_OAM_UNLOCK(oc); 10124 return (BCM_E_PARAM); 10125 } 10126 10127 /* BHH MEP Id & period already filled from uC msg */ 10128 if (!(h_data_p->type == bcmOAMEndpointTypeBHHMPLS || 10129 h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv)) { 10130 endpoint_info->name = h_data_p->name; 10131 endpoint_info->ccm_period = h_data_p->period; 10132 } 10133 10134 endpoint_info->id = endpoint; 10135 endpoint_info->group = h_data_p->group_index; 10136 endpoint_info->vlan = h_data_p->vlan; 10137 endpoint_info->level = h_data_p->level; 10138 endpoint_info->gport = h_data_p->gport; 10139 endpoint_info->flags |= h_data_p->flags; 10140 endpoint_info->flags &= ~(BCM_OAM_ENDPOINT_WITH_ID); 10141 endpoint_info->opcode_flags = h_data_p->opcode_flags; 10142 endpoint_info->type = h_data_p->type; 10143 endpoint_info->trunk_index = h_data_p->trunk_index; 10144 10145 if(h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 10146 for(i = 0; i < BCM_OAM_INTPRI_MAX; i++) { 10147 rv = READ_ING_SERVICE_PRI_MAPm(unit, MEM_BLOCK_ANY, 10148 (h_data_p->pri_map_index * 10149 BCM_OAM_INTPRI_MAX) + i, 10150 &pri_map); 10151 if (SOC_FAILURE(rv)) { 10152 _BCM_OAM_UNLOCK(oc); 10153 return rv; 10154 } 10155 endpoint_info->pri_map[i] = 10156 soc_ING_SERVICE_PRI_MAPm_field32_get(unit, &pri_map, OFFSETf); 10157 } 10158 endpoint_info->pri_map_id = h_data_p->pri_map_index; 10159 } 10160 10161 _BCM_OAM_UNLOCK(oc); 10162 /*SDK-147457:HW WAR to fix the issue of wrong LMEP index being written 10163 while deleting and adding same MEP in a loop */ 10164 #ifdef BCM_HURRICANE2_SUPPORT 10165 sal_usleep(3400); 10166 #endif /* BCM_HURRICANE2_SUPPORT */ 10167 10168 return (BCM_E_NONE); 10169 } 10170 10171 10172 /* 10173 * Function: 10174 * bcm_tr3_oam_endpoint_destroy 10175 * Purpose: 10176 * Destroy an OAM endpoint object 10177 * Parameters: 10178 * unit - (IN) BCM device number 10179 * endpoint - (IN) Endpoint ID to destroy. 10180 * result =s: 10181 * BCM_E_XXX 10182 */ 10183 int 10184 bcm_tr3_oam_endpoint_destroy(int unit, bcm_oam_endpoint_t endpoint) 10185 { 10186 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 10187 int rv; /* Operation return status. */ 10188 10189 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 10190 /* Validate endpoint index value. */ 10191 _BCM_OAM_EP_INDEX_VALIDATE(endpoint); 10192 10193 _BCM_OAM_LOCK(oc); 10194 10195 rv = _bcm_tr3_oam_endpoint_destroy(unit, endpoint); 10196 if (BCM_FAILURE(rv)) { 10197 LOG_ERROR(BSL_LS_BCM_OAM, 10198 (BSL_META_U(unit, 10199 "OAM Error: Endpoint destroy EP=%d failed - " 10200 "%s.\n"), endpoint, bcm_errmsg(rv))); 10201 } 10202 10203 _BCM_OAM_UNLOCK(oc); 10204 return (rv); 10205 } 10206 10207 /* 10208 * Function: 10209 * bcm_tr3_oam_endpoint_destroy_all 10210 * Purpose: 10211 * Destroy all OAM endpoint objects associated with a group. 10212 * Parameters: 10213 * unit - (IN) BCM device number 10214 * group - (IN) The OAM group whose endpoints should be destroyed 10215 * Returns: 10216 * BCM_E_XXX 10217 */ 10218 int 10219 bcm_tr3_oam_endpoint_destroy_all(int unit, bcm_oam_group_t group) 10220 { 10221 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 10222 int rv; /* Operation return status. */ 10223 _bcm_oam_group_data_t *g_info_p; 10224 10225 /* Get OAM device control structure. */ 10226 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 10227 10228 /* Validate group index. */ 10229 _BCM_OAM_GROUP_INDEX_VALIDATE(group); 10230 10231 _BCM_OAM_LOCK(oc); 10232 10233 /* Check if the group is in use. */ 10234 rv = shr_idxres_list_elem_state(oc->group_pool, group); 10235 if (BCM_E_EXISTS != rv) { 10236 _BCM_OAM_UNLOCK(oc); 10237 LOG_ERROR(BSL_LS_BCM_OAM, 10238 (BSL_META_U(unit, 10239 "OAM Error: Group ID=%d does not exist.\n"), 10240 group)); 10241 return (rv); 10242 } 10243 10244 /* Get the group data pointer. */ 10245 g_info_p = &oc->group_info[group]; 10246 rv = _bcm_tr3_oam_group_endpoints_destroy(unit, g_info_p); 10247 if (BCM_FAILURE(rv)) { 10248 LOG_ERROR(BSL_LS_BCM_OAM, 10249 (BSL_META_U(unit, 10250 "OAM Error: Group (GID=%d) endpoints destroy" 10251 " failed - %s.\n"), group, bcm_errmsg(rv))); 10252 _BCM_OAM_UNLOCK(oc); 10253 return (rv); 10254 } 10255 _BCM_OAM_UNLOCK(oc); 10256 return (rv); 10257 } 10258 10259 /* 10260 * Function: 10261 * bcm_tr3_oam_endpoint_traverse 10262 * Purpose: 10263 * Traverse the set of OAM endpoints associated with the 10264 * specified group, calling a specified callback for each one 10265 * Parameters: 10266 * unit - (IN) BCM device number 10267 * group - (IN) The OAM group whose endpoints should be traversed 10268 * cb - (IN) A pointer to the callback function to call for each OAM 10269 * endpoint in the specified group 10270 * user_data - (IN) Pointer to user data to supply in the callback 10271 * Returns: 10272 * BCM_E_XXX 10273 */ 10274 int 10275 bcm_tr3_oam_endpoint_traverse(int unit, bcm_oam_group_t group, 10276 bcm_oam_endpoint_traverse_cb cb, 10277 void *user_data) 10278 { 10279 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 10280 int rv; /* Operation return status. */ 10281 bcm_oam_endpoint_info_t ep_info; 10282 _bcm_oam_hash_data_t *h_data_p; 10283 _bcm_oam_ep_list_t *cur; 10284 _bcm_oam_group_data_t *g_info_p; 10285 10286 /* Validate input parameter. */ 10287 if (NULL == cb) { 10288 return (BCM_E_PARAM); 10289 } 10290 10291 /* Get OAM device control structure. */ 10292 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 10293 10294 /* Validate group index. */ 10295 _BCM_OAM_GROUP_INDEX_VALIDATE(group); 10296 10297 _BCM_OAM_LOCK(oc); 10298 10299 /* Check if the group is in use. */ 10300 rv = shr_idxres_list_elem_state(oc->group_pool, group); 10301 if (BCM_E_EXISTS != rv) { 10302 _BCM_OAM_UNLOCK(oc); 10303 LOG_ERROR(BSL_LS_BCM_OAM, 10304 (BSL_META_U(unit, 10305 "OAM Error: Group ID=%d does not exist.\n"), 10306 group)); 10307 return (rv); 10308 } 10309 10310 /* Get the group data pointer. */ 10311 g_info_p = &oc->group_info[group]; 10312 10313 /* Get the endpoint list head pointer. */ 10314 cur = *(g_info_p->ep_list); 10315 if (NULL == cur) { 10316 _BCM_OAM_UNLOCK(oc); 10317 LOG_DEBUG(BSL_LS_BCM_OAM, 10318 (BSL_META_U(unit, 10319 "OAM Info: No endpoints in group GID=%d.\n"), 10320 group)); 10321 return (BCM_E_NONE); 10322 } 10323 10324 /* Traverse from Head to Tail */ 10325 while (NULL != cur) { 10326 h_data_p = cur->ep_data_p; 10327 if (NULL == h_data_p) { 10328 LOG_ERROR(BSL_LS_BCM_OAM, 10329 (BSL_META_U(unit, 10330 "OAM Error: Group=%d endpoints access failed -" 10331 " %s.\n"), group, bcm_errmsg(BCM_E_INTERNAL))); 10332 _BCM_OAM_UNLOCK(oc); 10333 return (BCM_E_INTERNAL); 10334 } 10335 bcm_oam_endpoint_info_t_init(&ep_info); 10336 10337 rv = bcm_tr3_oam_endpoint_get(unit, h_data_p->ep_id, &ep_info); 10338 if (BCM_FAILURE(rv)) { 10339 _BCM_OAM_UNLOCK(oc); 10340 LOG_ERROR(BSL_LS_BCM_OAM, 10341 (BSL_META_U(unit, 10342 "OAM Error: EP=%d info get failed %s.\n"), 10343 h_data_p->ep_id, bcm_errmsg(rv))); 10344 return (rv); 10345 } 10346 10347 /* Get the next node handle before calling the callback as current 10348 * node may move to the head if modification is performed in the 10349 * callback */ 10350 cur = cur->next; 10351 10352 rv = cb(unit, &ep_info, user_data); 10353 if (BCM_FAILURE(rv)) { 10354 _BCM_OAM_UNLOCK(oc); 10355 LOG_ERROR(BSL_LS_BCM_OAM, 10356 (BSL_META_U(unit, 10357 "OAM Error: EP=%d callback failed - %s.\n"), 10358 h_data_p->ep_id, bcm_errmsg(rv))); 10359 return (rv); 10360 } 10361 } 10362 _BCM_OAM_UNLOCK(oc); 10363 return (rv); 10364 } 10365 10366 /* 10367 * Function: 10368 * bcm_tr3_oam_event_register 10369 * Purpose: 10370 * Register a callback for handling OAM events 10371 * Parameters: 10372 * unit - (IN) BCM device number 10373 * event_types - (IN) The set of OAM events for which the specified 10374 * callback should be called. 10375 * cb - (IN) A pointer to the callback function to call for 10376 * the specified OAM events 10377 * user_data - (IN) Pointer to user data to supply in the callback 10378 * Returns: 10379 * BCM_E_XXX 10380 */ 10381 int 10382 bcm_tr3_oam_event_register(int unit, bcm_oam_event_types_t event_types, 10383 bcm_oam_event_cb cb, void *user_data) 10384 { 10385 _bcm_oam_control_t *oc; 10386 _bcm_oam_event_handler_t *event_h_p; 10387 _bcm_oam_event_handler_t *prev_p = NULL; 10388 bcm_oam_event_type_t e_type; 10389 uint32 rval; 10390 int hw_update = 0; 10391 uint32 event_bmp; 10392 int rv = BCM_E_NONE; /* Operation return status. */ 10393 10394 /* Validate event callback input parameter. */ 10395 if (NULL == cb) { 10396 return (BCM_E_PARAM); 10397 } 10398 10399 /* Check if an event is set for register in the events bitmap. */ 10400 SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp); 10401 if (0 == event_bmp) { 10402 /* No events specified. */ 10403 LOG_ERROR(BSL_LS_BCM_OAM, 10404 (BSL_META_U(unit, 10405 "OAM Error: No events specified for register.\n"))); 10406 return (BCM_E_PARAM); 10407 } 10408 10409 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 10410 10411 _BCM_OAM_LOCK(oc); 10412 10413 for (event_h_p = oc->event_handler_list_p; event_h_p != NULL; 10414 event_h_p = event_h_p->next_p) { 10415 if (event_h_p->cb == cb) { 10416 break; 10417 } 10418 prev_p = event_h_p; 10419 } 10420 10421 if (NULL == event_h_p) { 10422 10423 _BCM_OAM_ALLOC(event_h_p, _bcm_oam_event_handler_t, 10424 sizeof(_bcm_oam_event_handler_t), "OAM event handler"); 10425 10426 if (NULL == event_h_p) { 10427 _BCM_OAM_UNLOCK(oc); 10428 LOG_ERROR(BSL_LS_BCM_OAM, 10429 (BSL_META_U(unit, 10430 "OAM Error: Event handler alloc failed -" 10431 " %s.\n"), bcm_errmsg(BCM_E_MEMORY))); 10432 return (BCM_E_MEMORY); 10433 } 10434 10435 event_h_p->next_p = NULL; 10436 event_h_p->cb = cb; 10437 10438 SHR_BITCLR_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount); 10439 if (prev_p != NULL) { 10440 prev_p->next_p = event_h_p; 10441 } else { 10442 oc->event_handler_list_p = event_h_p; 10443 } 10444 } 10445 10446 rv = READ_CCM_INTERRUPT_CONTROLr(unit, &rval); 10447 if (BCM_FAILURE(rv)) { 10448 _BCM_OAM_UNLOCK(oc); 10449 LOG_ERROR(BSL_LS_BCM_OAM, 10450 (BSL_META_U(unit, 10451 "OAM Error: CCM interrupt control read failed -" 10452 " %s.\n"), bcm_errmsg(rv))); 10453 return (rv); 10454 } 10455 10456 for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) { 10457 if (SHR_BITGET(event_types.w, e_type)) { 10458 if(soc_feature(unit, soc_feature_bhh)) { 10459 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 10460 /* 10461 * BHH events are generated by the uKernel 10462 */ 10463 if ((e_type == bcmOAMEventBHHLBTimeout) || 10464 (e_type == bcmOAMEventBHHLBDiscoveryUpdate) || 10465 (e_type == bcmOAMEventBHHCCMTimeout) || 10466 (e_type == bcmOAMEventBHHCCMTimeoutClear) || 10467 (e_type == bcmOAMEventBHHCCMState) || 10468 (e_type == bcmOAMEventBHHCCMRdi) || 10469 (e_type == bcmOAMEventBHHCCMUnknownMegLevel) || 10470 (e_type == bcmOAMEventBHHCCMUnknownMegId) || 10471 (e_type == bcmOAMEventBHHCCMUnknownMepId) || 10472 (e_type == bcmOAMEventBHHCCMUnknownPeriod) || 10473 (e_type == bcmOAMEventBHHCCMUnknownPriority) || 10474 (e_type == bcmOAMEventBHHCCMRdiClear) || 10475 (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) || 10476 (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) || 10477 (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) || 10478 (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) || 10479 (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) || 10480 (e_type == bcmOAMEventCsfLos) || 10481 (e_type == bcmOAMEventCsfFdi) || 10482 (e_type == bcmOAMEventCsfRdi) || 10483 (e_type == bcmOAMEventCsfDci)) { 10484 SHR_BITSET(event_h_p->event_types.w, e_type); 10485 oc->event_handler_cnt[e_type] += 1; 10486 continue; 10487 } 10488 #endif 10489 } 10490 if (!soc_reg_field_valid 10491 (unit, CCM_INTERRUPT_CONTROLr, 10492 _tr3_oam_intr_en_fields[e_type].field)) { 10493 continue; 10494 } 10495 10496 if (!SHR_BITGET(event_h_p->event_types.w, e_type)) { 10497 /* Add this event to the registered events list. */ 10498 SHR_BITSET(event_h_p->event_types.w, e_type); 10499 oc->event_handler_cnt[e_type] += 1; 10500 if (1 == oc->event_handler_cnt[e_type]) { 10501 hw_update = 1; 10502 soc_reg_field_set 10503 (unit, CCM_INTERRUPT_CONTROLr, &rval, 10504 _tr3_oam_intr_en_fields[e_type].field, 1); 10505 } 10506 } 10507 } 10508 } 10509 10510 event_h_p->user_data = user_data; 10511 10512 if (1 == hw_update) { 10513 rv = WRITE_CCM_INTERRUPT_CONTROLr(unit, rval); 10514 if (BCM_FAILURE(rv)) { 10515 _BCM_OAM_UNLOCK(oc); 10516 LOG_ERROR(BSL_LS_BCM_OAM, 10517 (BSL_META_U(unit, 10518 "OAM Error: CCM interrupt control write failed -" 10519 " %s.\n"), bcm_errmsg(rv))); 10520 return (rv); 10521 } 10522 } 10523 10524 if (soc_feature(unit, soc_feature_bhh)) { 10525 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 10526 /* 10527 * Update BHH Events mask 10528 */ 10529 rv = _bcm_tr3_oam_bhh_event_mask_set(unit); 10530 #endif /* INCLUDE_BHH */ 10531 } 10532 10533 _BCM_OAM_UNLOCK(oc); 10534 10535 return (rv); 10536 } 10537 10538 /* 10539 * Function: 10540 * bcm_tr3_oam_event_unregister 10541 * Purpose: 10542 * Remove a registered event from the event handler list. 10543 * Parameters: 10544 * unit - (IN) BCM device number 10545 * event_types - (IN) The set of OAM events for which the specified 10546 * callback should not be called 10547 * cb - (IN) A pointer to the callback function to unregister 10548 * from the specified OAM events 10549 * Returns: 10550 * BCM_E_XXX 10551 */ 10552 int 10553 bcm_tr3_oam_event_unregister(int unit, bcm_oam_event_types_t event_types, 10554 bcm_oam_event_cb cb) 10555 { 10556 10557 _bcm_oam_control_t *oc; 10558 _bcm_oam_event_handler_t *event_h_p; 10559 _bcm_oam_event_handler_t *prev_p = NULL; 10560 bcm_oam_event_type_t e_type; 10561 uint32 rval; 10562 int hw_update = 0; 10563 uint32 event_bmp; 10564 int rv = BCM_E_NONE; /* Operation return status. */ 10565 10566 /* Validate event callback input parameter. */ 10567 if (NULL == cb) { 10568 return (BCM_E_PARAM); 10569 } 10570 10571 /* Check if an event is set for unregister in the events bitmap. */ 10572 SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp); 10573 if (0 == event_bmp) { 10574 /* No events specified. */ 10575 LOG_ERROR(BSL_LS_BCM_OAM, 10576 (BSL_META_U(unit, 10577 "OAM Error: No events specified for register.\n"))); 10578 return (BCM_E_PARAM); 10579 } 10580 10581 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 10582 10583 _BCM_OAM_LOCK(oc); 10584 10585 for (event_h_p = oc->event_handler_list_p; event_h_p != NULL; 10586 event_h_p = event_h_p->next_p) { 10587 if (event_h_p->cb == cb) { 10588 break; 10589 } 10590 prev_p = event_h_p; 10591 } 10592 10593 if (NULL == event_h_p) { 10594 _BCM_OAM_UNLOCK(oc); 10595 return (BCM_E_NOT_FOUND); 10596 } 10597 10598 rv = READ_CCM_INTERRUPT_CONTROLr(unit, &rval); 10599 if (BCM_FAILURE(rv)) { 10600 _BCM_OAM_UNLOCK(oc); 10601 LOG_ERROR(BSL_LS_BCM_OAM, 10602 (BSL_META_U(unit, 10603 "OAM Error: CCM interrupt control read failed -" 10604 " %s.\n"), bcm_errmsg(rv))); 10605 return (rv); 10606 } 10607 10608 for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) { 10609 10610 if (SHR_BITGET(event_types.w, e_type)) { 10611 if(soc_feature(unit, soc_feature_bhh)) { 10612 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 10613 /* 10614 * BHH events are generated by the uKernel 10615 */ 10616 if ((e_type == bcmOAMEventBHHLBTimeout) || 10617 (e_type == bcmOAMEventBHHLBDiscoveryUpdate) || 10618 (e_type == bcmOAMEventBHHCCMTimeout) || 10619 (e_type == bcmOAMEventBHHCCMTimeoutClear) || 10620 (e_type == bcmOAMEventBHHCCMState) || 10621 (e_type == bcmOAMEventBHHCCMRdi) || 10622 (e_type == bcmOAMEventBHHCCMUnknownMegLevel) || 10623 (e_type == bcmOAMEventBHHCCMUnknownMegId) || 10624 (e_type == bcmOAMEventBHHCCMUnknownMepId) || 10625 (e_type == bcmOAMEventBHHCCMUnknownPeriod) || 10626 (e_type == bcmOAMEventBHHCCMUnknownPriority) || 10627 (e_type == bcmOAMEventBHHCCMRdiClear) || 10628 (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) || 10629 (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) || 10630 (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) || 10631 (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) || 10632 (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) || 10633 (e_type == bcmOAMEventCsfLos) || 10634 (e_type == bcmOAMEventCsfFdi) || 10635 (e_type == bcmOAMEventCsfRdi) || 10636 (e_type == bcmOAMEventCsfDci)) { 10637 SHR_BITCLR(event_h_p->event_types.w, e_type); 10638 oc->event_handler_cnt[e_type] -= 1; 10639 continue; 10640 } 10641 #endif 10642 } 10643 10644 if (!soc_reg_field_valid 10645 (unit, CCM_INTERRUPT_CONTROLr, 10646 _tr3_oam_intr_en_fields[e_type].field)) { 10647 _BCM_OAM_UNLOCK(oc); 10648 return (BCM_E_UNAVAIL); 10649 } 10650 10651 if ((oc->event_handler_cnt[e_type] > 0) 10652 && SHR_BITGET(event_h_p->event_types.w, e_type)) { 10653 10654 /* Remove this event from the registered events list. */ 10655 SHR_BITCLR(event_h_p->event_types.w, e_type); 10656 10657 oc->event_handler_cnt[e_type] -= 1; 10658 10659 if (0 == oc->event_handler_cnt[e_type]) { 10660 hw_update = 1; 10661 soc_reg_field_set 10662 (unit, CCM_INTERRUPT_CONTROLr, &rval, 10663 _tr3_oam_intr_en_fields[e_type].field, 0); 10664 } 10665 } 10666 } 10667 } 10668 10669 if (1 == hw_update) { 10670 rv = WRITE_CCM_INTERRUPT_CONTROLr(unit, rval); 10671 if (BCM_FAILURE(rv)) { 10672 _BCM_OAM_UNLOCK(oc); 10673 LOG_ERROR(BSL_LS_BCM_OAM, 10674 (BSL_META_U(unit, 10675 "OAM Error: CCM interrupt control write failed -" 10676 " %s.\n"), bcm_errmsg(rv))); 10677 return (rv); 10678 } 10679 } 10680 10681 SHR_BITTEST_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount, event_bmp); 10682 10683 if (0 == event_bmp) { 10684 10685 if (NULL != prev_p) { 10686 10687 prev_p->next_p = event_h_p->next_p; 10688 10689 } else { 10690 10691 oc->event_handler_list_p = event_h_p->next_p; 10692 10693 } 10694 sal_free(event_h_p); 10695 } 10696 10697 if(soc_feature(unit, soc_feature_bhh)) { 10698 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 10699 /* 10700 * Update BHH Events mask 10701 */ 10702 rv = _bcm_tr3_oam_bhh_event_mask_set(unit); 10703 #endif /* INCLUDE_BHH */ 10704 } 10705 10706 _BCM_OAM_UNLOCK(oc); 10707 10708 return (rv); 10709 } 10710 10711 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(INCLUDE_BHH) 10712 /* 10713 * Function: 10714 * bcm_tr3_oam_mpls_tp_channel_type_tx_get 10715 * Purpose: 10716 * Get MPLS TP(BHH) ACH Channel type 10717 * Parameters: 10718 * unit (IN) BCM device number 10719 * channel_type (IN) Channel type is ignored in XGS devices 10720 * Value (OUT) User define MPLS TP(BHH) ACH channel type 10721 * 10722 * Returns: 10723 * BCM_E_NONE No error 10724 * BCM_E_XXXX Error 10725 */ 10726 int 10727 bcm_tr3_oam_mpls_tp_channel_type_tx_get(int unit, 10728 bcm_oam_mpls_tp_channel_type_t channel_type, 10729 int *value) 10730 { 10731 *value = tr3_oam_mpls_tp_ach_channel_type; 10732 return BCM_E_NONE; 10733 } 10734 10735 /* 10736 * Function: 10737 * bcm_ml_oam_opcodes_count_profile_delete 10738 * Purpose: 10739 * Update MPLS TP(BHH) ACH Channel type with user defined value 10740 * Parameters: 10741 * unit (IN) BCM device number 10742 * channel_type (IN) Channel type is ignored in XGS devices 10743 * Value (IN) User define MPLS TP(BHH) ACH channel type 10744 * 10745 * Returns: 10746 * BCM_E_NONE No error 10747 * BCM_E_XXXX Error 10748 */ 10749 int 10750 bcm_tr3_oam_mpls_tp_channel_type_tx_set(int unit, 10751 bcm_oam_mpls_tp_channel_type_t channel_type, 10752 int value) 10753 { 10754 uint8 *buffer, *buffer_ptr; 10755 uint16 buffer_len, reply_len; 10756 int rv = BCM_E_NONE; 10757 uint32 *msg; 10758 _bcm_oam_control_t *oc; 10759 10760 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 10761 _BCM_OAM_LOCK(oc); 10762 10763 if (oc->ukernel_not_ready) { 10764 _BCM_OAM_UNLOCK(oc); 10765 return BCM_E_INIT; 10766 } 10767 10768 if ((value != SHR_BHH_ACH_CHANNEL_TYPE) && 10769 (value != SHR_BHH_ACH_CHANNEL_TYPE_1)) { 10770 _BCM_OAM_UNLOCK(oc); 10771 return BCM_E_CONFIG; 10772 } 10773 10774 tr3_oam_mpls_tp_ach_channel_type = value; 10775 msg = (uint32 *)&tr3_oam_mpls_tp_ach_channel_type; 10776 10777 /* Pack control message data into DMA buffer */ 10778 buffer = oc->dma_buffer; 10779 buffer_ptr = bhh_sdk_msg_ctrl_ach_channel_type_msg_pack(buffer, msg); 10780 buffer_len = buffer_ptr - buffer; 10781 10782 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 10783 MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE, 10784 buffer_len, 0, 10785 MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE_REPLY, 10786 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 10787 10788 if (BCM_FAILURE(rv)) { 10789 _BCM_OAM_UNLOCK(oc); 10790 return (rv); 10791 } 10792 10793 _BCM_OAM_UNLOCK(oc); 10794 return BCM_E_NONE; 10795 } 10796 10797 /* 10798 * Function: 10799 * _bcm_tr3_oam_bhh_fp_set 10800 * Purpose: 10801 * Sets BHH FP for LM/DM in HW device. 10802 * Parameters: 10803 * unit - (IN) Unit number. 10804 * module_id - (IN) Module id. 10805 * port_id - (IN) Port. 10806 * is_local - (IN) Indicates if module id is local. 10807 * endpoint_config - (IN) Pointer to BHH endpoint structure. 10808 * Returns: 10809 * BCM_E_XXX 10810 * Notes: 10811 */ 10812 STATIC int 10813 _bcm_tr3_oam_bhh_fp_set(int unit, _bcm_oam_hash_data_t *hash_data, uint32 nhi, 10814 bcm_oam_endpoint_info_t *endpoint_info) 10815 { 10816 int rv = BCM_E_NONE; 10817 _bcm_oam_control_t *oc; 10818 bcm_gport_t gport; 10819 bcm_module_t module_id; 10820 bcm_port_t port_id; 10821 bcm_trunk_t trunk_id; 10822 int local_id; 10823 void *entries[1]; 10824 int i; 10825 uint32 mem_entries[BCM_OAM_INTPRI_MAX], profile_index; 10826 bcm_mpls_label_t label = hash_data->label << 12; 10827 uint32 label_mask = SHR_BHH_MPLS_LABEL_MASK; 10828 uint16 ach_type = tr3_oam_mpls_tp_ach_channel_type; 10829 uint16 ach_mask = 0xFFFF; 10830 uint8 op_code; 10831 uint8 op_mask; 10832 10833 /* Lock already taken by the calling routine. */ 10834 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 10835 10836 if(oc->bhh_lmdm_group == 0) { 10837 BCM_IF_ERROR_RETURN(bcm_esw_field_group_create(unit, 10838 oc->bhh_lmdm_qset, 10839 BCM_FIELD_GROUP_PRIO_ANY, &oc->bhh_lmdm_group)); 10840 oc->bhh_lmdm_entry_count = 0; 10841 } 10842 10843 rv = _bcm_esw_gport_resolve(unit, 10844 hash_data->gport, &module_id, &port_id, &trunk_id, &local_id); 10845 if (BCM_FAILURE(rv)) { 10846 LOG_ERROR(BSL_LS_BCM_OAM, 10847 (BSL_META_U(unit, 10848 "BHH Error: Gport resolve (EP=%d) - %s.\n"), 10849 hash_data->ep_id, bcm_errmsg(rv))); 10850 return (rv); 10851 } 10852 10853 if (BCM_TRUNK_INVALID != trunk_id) { 10854 BCM_GPORT_TRUNK_SET(gport, trunk_id); 10855 } else if (module_id != 0) { 10856 /* Modport */ 10857 BCM_GPORT_MODPORT_SET(gport, module_id, port_id); 10858 } else { 10859 /* Local port */ 10860 BCM_IF_ERROR_RETURN(bcm_esw_port_gport_get(unit, port_id, &gport)); 10861 } 10862 10863 if(hash_data->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) { 10864 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_create(unit, 10865 oc->bhh_lmdm_group, 10866 &hash_data->bhh_dm_entry_rx)); 10867 if (SOC_GPORT_IS_TRUNK(gport)) { 10868 BCM_IF_ERROR_RETURN( 10869 bcm_esw_field_qualify_SrcTrunk(unit, 10870 hash_data->bhh_dm_entry_rx, 10871 trunk_id, 10872 BCM_FIELD_EXACT_MATCH_MASK)); 10873 } else { 10874 BCM_IF_ERROR_RETURN( 10875 bcm_esw_field_qualify_SrcPort(unit, 10876 hash_data->bhh_dm_entry_rx, 10877 0, 0x3f, gport, 10878 BCM_FIELD_EXACT_MATCH_MASK)); 10879 } 10880 BCM_IF_ERROR_RETURN(bcm_esw_field_qualify_OuterVlanId(unit, 10881 hash_data->bhh_dm_entry_rx, 10882 hash_data->vlan, 0x0fff)); 10883 10884 op_code = SHR_BHH_OPCODE_DM_PREFIX; 10885 op_mask = SHR_BHH_OPCODE_DM_MASK; 10886 if (oc->bhh_udf_mode) { 10887 BCM_IF_ERROR_RETURN( 10888 bcm_esw_field_qualify_udf(unit, 10889 hash_data->bhh_dm_entry_rx, 10890 oc->bhh_label_udf_id, 10891 SHR_BHH_MPLS_LABEL_LENGTH, 10892 (uint8 *)&label, 10893 (uint8 *)&label_mask)); 10894 10895 BCM_IF_ERROR_RETURN( 10896 bcm_esw_field_qualify_udf(unit, 10897 hash_data->bhh_dm_entry_rx, 10898 oc->bhh_ach_qual_id, 10899 SHR_BHH_ACH_TYPE_LENGTH, 10900 (uint8 *)&ach_type, 10901 (uint8 *)&ach_mask)); 10902 10903 BCM_IF_ERROR_RETURN( 10904 bcm_esw_field_qualify_udf(unit, 10905 hash_data->bhh_dm_entry_rx, 10906 oc->bhh_opcode_qual_id, 10907 SHR_BHH_OPCODE_LEN, 10908 &op_code, 10909 &op_mask)); 10910 } else { 10911 BCM_IF_ERROR_RETURN( 10912 bcm_esw_field_qualify_data(unit, 10913 hash_data->bhh_dm_entry_rx, 10914 oc->bhh_label_qual_id, 10915 (uint8 *)&label, 10916 (uint8 *)&label_mask, 10917 SHR_BHH_MPLS_LABEL_LENGTH)); 10918 10919 BCM_IF_ERROR_RETURN( 10920 bcm_esw_field_qualify_data(unit, 10921 hash_data->bhh_dm_entry_rx, 10922 oc->bhh_ach_qual_id, 10923 (uint8 *)&ach_type, 10924 (uint8 *)&ach_mask, 10925 SHR_BHH_ACH_TYPE_LENGTH)); 10926 10927 BCM_IF_ERROR_RETURN( 10928 bcm_esw_field_qualify_data(unit, 10929 hash_data->bhh_dm_entry_rx, 10930 oc->bhh_opcode_qual_id, 10931 &op_code, 10932 &op_mask, 10933 SHR_BHH_OPCODE_LEN)); 10934 } 10935 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 10936 hash_data->bhh_dm_entry_rx, 10937 bcmFieldActionOamDmEnable, 1, 0)); 10938 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 10939 hash_data->bhh_dm_entry_rx, 10940 bcmFieldActionOamDmTimeFormat, 1, 0)); /* NTP */ 10941 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 10942 hash_data->bhh_dm_entry_rx, 10943 bcmFieldActionOamLmepEnable, 0, 0)); 10944 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 10945 hash_data->bhh_dm_entry_rx, 10946 bcmFieldActionOamLmDmSampleEnable, 1, 0)); 10947 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_install(unit, 10948 hash_data->bhh_dm_entry_rx)); 10949 if(hash_data->bhh_dm_entry_rx) 10950 oc->bhh_lmdm_entry_count++; 10951 } 10952 10953 if(hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 10954 /* Allocate the next available endpoint index. */ 10955 rv = shr_idxres_list_alloc(oc->lm_counter_pool, 10956 (shr_idxres_element_t *)&hash_data->lm_counter_index); 10957 if (BCM_FAILURE(rv)) { 10958 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_FULL) : rv; 10959 LOG_ERROR(BSL_LS_BCM_OAM, 10960 (BSL_META_U(unit, 10961 "BHH Error: lm counter idx alloc failed - %s.\n"), 10962 bcm_errmsg(rv))); 10963 return (rv); 10964 } 10965 10966 /* Assign Pri Mapping pointer */ 10967 for (i = 0; i < BCM_OAM_INTPRI_MAX ; i++) { 10968 mem_entries[i] = endpoint_info->pri_map[i]; 10969 if (SOC_MEM_FIELD_VALID(unit, ING_SERVICE_PRI_MAPm, OFFSET_VALIDf)) { 10970 soc_mem_field32_set(unit, ING_SERVICE_PRI_MAPm, &mem_entries[i], 10971 OFFSET_VALIDf, 1); 10972 } 10973 } 10974 10975 soc_mem_lock(unit, ING_SERVICE_PRI_MAPm); 10976 entries[0] = &mem_entries; 10977 rv = soc_profile_mem_add(unit, &oc->ing_service_pri_map, 10978 (void *) &entries, BCM_OAM_INTPRI_MAX, &profile_index); 10979 if (BCM_FAILURE(rv)) { 10980 LOG_ERROR(BSL_LS_BCM_OAM, 10981 (BSL_META_U(unit, 10982 "BHH Error: Adding ING_SERVICE_PRI_MAP entry" 10983 " - %s.\n"), bcm_errmsg(rv))); 10984 soc_mem_unlock(unit, ING_SERVICE_PRI_MAPm); 10985 return (rv); 10986 } 10987 hash_data->pri_map_index = profile_index/BCM_OAM_INTPRI_MAX; 10988 soc_mem_unlock(unit, ING_SERVICE_PRI_MAPm); 10989 10990 /* policy to get lm counter value into DCBs*/ 10991 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_create(unit, 10992 oc->bhh_lmdm_group, 10993 &hash_data->bhh_lm_entry_rx)); 10994 if (SOC_GPORT_IS_TRUNK(gport)) { 10995 BCM_IF_ERROR_RETURN( 10996 bcm_esw_field_qualify_SrcTrunk(unit, 10997 hash_data->bhh_lm_entry_rx, 10998 trunk_id, 10999 BCM_FIELD_EXACT_MATCH_MASK)); 11000 } else { 11001 BCM_IF_ERROR_RETURN( 11002 bcm_esw_field_qualify_SrcPort(unit, 11003 hash_data->bhh_lm_entry_rx, 11004 0, 0x3f, gport, 11005 BCM_FIELD_EXACT_MATCH_MASK)); 11006 } 11007 BCM_IF_ERROR_RETURN(bcm_esw_field_qualify_OuterVlanId(unit, 11008 hash_data->bhh_lm_entry_rx, 11009 hash_data->vlan, 0x0fff)); 11010 11011 op_code = SHR_BHH_OPCODE_LM_PREFIX; 11012 op_mask = SHR_BHH_OPCODE_LM_MASK; 11013 if(oc->bhh_udf_mode) { 11014 BCM_IF_ERROR_RETURN( 11015 bcm_esw_field_qualify_udf(unit, 11016 hash_data->bhh_lm_entry_rx, 11017 oc->bhh_label_udf_id, 11018 SHR_BHH_MPLS_LABEL_LENGTH, 11019 (uint8 *)&label, 11020 (uint8 *)&label_mask)); 11021 11022 BCM_IF_ERROR_RETURN( 11023 bcm_esw_field_qualify_udf(unit, 11024 hash_data->bhh_lm_entry_rx, 11025 oc->bhh_ach_udf_id, 11026 SHR_BHH_ACH_TYPE_LENGTH, 11027 (uint8 *)&ach_type, 11028 (uint8 *)&ach_mask)); 11029 11030 BCM_IF_ERROR_RETURN( 11031 bcm_esw_field_qualify_udf(unit, 11032 hash_data->bhh_lm_entry_rx, 11033 oc->bhh_opcode_udf_id, 11034 SHR_BHH_OPCODE_LEN, 11035 &op_code, 11036 &op_mask)); 11037 } else { 11038 BCM_IF_ERROR_RETURN( 11039 bcm_esw_field_qualify_data(unit, 11040 hash_data->bhh_lm_entry_rx, 11041 oc->bhh_label_qual_id, 11042 (uint8 *)&label, 11043 (uint8 *)&label_mask, 11044 SHR_BHH_MPLS_LABEL_LENGTH)); 11045 11046 BCM_IF_ERROR_RETURN( 11047 bcm_esw_field_qualify_data(unit, 11048 hash_data->bhh_lm_entry_rx, 11049 oc->bhh_ach_qual_id, 11050 (uint8 *)&ach_type, 11051 (uint8 *)&ach_mask, 11052 SHR_BHH_ACH_TYPE_LENGTH)); 11053 11054 BCM_IF_ERROR_RETURN( 11055 bcm_esw_field_qualify_data(unit, 11056 hash_data->bhh_lm_entry_rx, 11057 oc->bhh_opcode_qual_id, 11058 &op_code, 11059 &op_mask, 11060 SHR_BHH_OPCODE_LEN)); 11061 } 11062 11063 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11064 hash_data->bhh_lm_entry_rx, 11065 bcmFieldActionOamLmEnable, 1, 0)); 11066 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11067 hash_data->bhh_lm_entry_rx, 11068 bcmFieldActionOamLmepEnable, 0, 0)); 11069 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11070 hash_data->bhh_lm_entry_rx, 11071 bcmFieldActionOamLmBasePtr, 11072 hash_data->lm_counter_index, 0)); 11073 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11074 hash_data->bhh_lm_entry_rx, 11075 bcmFieldActionOamServicePriMappingPtr, 11076 hash_data->pri_map_index, 0)); 11077 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11078 hash_data->bhh_lm_entry_rx, 11079 bcmFieldActionOamTx, 0, 0)); 11080 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11081 hash_data->bhh_lm_entry_rx, 11082 bcmFieldActionOamLmDmSampleEnable, 1, 0)); 11083 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_install(unit, 11084 hash_data->bhh_lm_entry_rx)); 11085 if(hash_data->bhh_lm_entry_rx) 11086 oc->bhh_lmdm_entry_count++; 11087 11088 /* Count the Rx packets */ 11089 11090 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_create(unit, 11091 oc->bhh_lmdm_group, 11092 &hash_data->bhh_entry_pkt_rx)); 11093 if (SOC_GPORT_IS_TRUNK(gport)) { 11094 BCM_IF_ERROR_RETURN( 11095 bcm_esw_field_qualify_SrcTrunk(unit, 11096 hash_data->bhh_entry_pkt_rx, 11097 trunk_id, 11098 BCM_FIELD_EXACT_MATCH_MASK)); 11099 } else { 11100 BCM_IF_ERROR_RETURN( 11101 bcm_esw_field_qualify_SrcPort(unit, 11102 hash_data->bhh_entry_pkt_rx, 11103 0, 0x3f, gport, 11104 BCM_FIELD_EXACT_MATCH_MASK)); 11105 } 11106 BCM_IF_ERROR_RETURN(bcm_esw_field_qualify_OuterVlanId(unit, 11107 hash_data->bhh_entry_pkt_rx, 11108 hash_data->vlan, 0x0fff)); 11109 11110 if (oc->bhh_udf_mode) { 11111 BCM_IF_ERROR_RETURN( 11112 bcm_esw_field_qualify_udf(unit, 11113 hash_data->bhh_entry_pkt_rx, 11114 oc->bhh_label_udf_id, 11115 SHR_BHH_MPLS_LABEL_LENGTH, 11116 (uint8 *)&label, 11117 (uint8 *)&label_mask)); 11118 11119 } else { 11120 BCM_IF_ERROR_RETURN( 11121 bcm_esw_field_qualify_data(unit, 11122 hash_data->bhh_entry_pkt_rx, 11123 oc->bhh_label_qual_id, 11124 (uint8 *)&label, 11125 (uint8 *)&label_mask, 11126 SHR_BHH_MPLS_LABEL_LENGTH)); 11127 } 11128 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11129 hash_data->bhh_entry_pkt_rx, 11130 bcmFieldActionOamLmEnable, 1, 0)); 11131 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11132 hash_data->bhh_entry_pkt_rx, 11133 bcmFieldActionOamLmepEnable, 11134 1, 0)); 11135 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11136 hash_data->bhh_entry_pkt_rx, 11137 bcmFieldActionOamLmBasePtr, 11138 hash_data->lm_counter_index, 0)); 11139 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11140 hash_data->bhh_entry_pkt_rx, 11141 bcmFieldActionOamServicePriMappingPtr, 11142 hash_data->pri_map_index, 0)); 11143 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11144 hash_data->bhh_entry_pkt_rx, 11145 bcmFieldActionOamTx, 0, 0)); 11146 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_install(unit, 11147 hash_data->bhh_entry_pkt_rx)); 11148 if(hash_data->bhh_entry_pkt_rx) 11149 oc->bhh_lmdm_entry_count++; 11150 11151 /* Count the Tx packets */ 11152 11153 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_create(unit, 11154 oc->bhh_lmdm_group, 11155 &hash_data->bhh_entry_pkt_tx)); 11156 if (SOC_GPORT_IS_TRUNK(gport)) { 11157 BCM_IF_ERROR_RETURN( 11158 bcm_esw_field_qualify_DstTrunk(unit, 11159 hash_data->bhh_entry_pkt_tx, 11160 trunk_id, 11161 BCM_FIELD_EXACT_MATCH_MASK)); 11162 } else { 11163 BCM_IF_ERROR_RETURN( 11164 bcm_esw_field_qualify_DstPort(unit, 11165 hash_data->bhh_entry_pkt_tx, 11166 0, 0x3f, gport, 11167 BCM_FIELD_EXACT_MATCH_MASK)); 11168 } 11169 11170 BCM_IF_ERROR_RETURN(bcm_esw_field_qualify_OuterVlanId(unit, 11171 hash_data->bhh_entry_pkt_tx, 11172 hash_data->vlan, 0x0fff)); 11173 BCM_IF_ERROR_RETURN(bcm_esw_field_qualify_DstL3Egress(unit, 11174 hash_data->bhh_entry_pkt_tx, endpoint_info->intf_id)); 11175 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11176 hash_data->bhh_entry_pkt_tx, 11177 bcmFieldActionOamLmEnable, 1, 0)); 11178 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11179 hash_data->bhh_entry_pkt_tx, 11180 bcmFieldActionOamLmepEnable, 1, 0)); 11181 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11182 hash_data->bhh_entry_pkt_tx, 11183 bcmFieldActionOamLmBasePtr, 11184 hash_data->lm_counter_index, 0)); 11185 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11186 hash_data->bhh_entry_pkt_tx, 11187 bcmFieldActionOamServicePriMappingPtr, 11188 hash_data->pri_map_index, 0)); 11189 BCM_IF_ERROR_RETURN(bcm_esw_field_action_add(unit, 11190 hash_data->bhh_entry_pkt_tx, 11191 bcmFieldActionOamTx, 1, 0)); 11192 BCM_IF_ERROR_RETURN(bcm_esw_field_entry_install(unit, 11193 hash_data->bhh_entry_pkt_tx)); 11194 if(hash_data->bhh_entry_pkt_tx) 11195 oc->bhh_lmdm_entry_count++; 11196 11197 } 11198 11199 11200 return rv; 11201 } 11202 11203 /* 11204 * Function: 11205 * _bcm_tr3_oam_bhh_encap_hw_set 11206 * Purpose: 11207 * Sets BHH encapsulation type in HW device. 11208 * Parameters: 11209 * unit - (IN) Unit number. 11210 * module_id - (IN) Module id. 11211 * port_id - (IN) Port. 11212 * is_local - (IN) Indicates if module id is local. 11213 * endpoint_config - (IN) Pointer to BHH endpoint structure. 11214 * Returns: 11215 * BCM_E_XXX 11216 * Notes: 11217 */ 11218 STATIC int 11219 _bcm_tr3_oam_bhh_encap_hw_set(int unit, _bcm_oam_hash_data_t *h_data_p, 11220 bcm_module_t module_id, bcm_port_t port_id, 11221 int is_local, bcm_oam_endpoint_info_t *endpoint_info) 11222 { 11223 int rv = BCM_E_NONE; 11224 l2_entry_1_entry_t l2_entry_1; 11225 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) 11226 bcm_l3_egress_t l3_egress; 11227 int ingress_if; 11228 int i; 11229 int num_entries; 11230 mpls_entry_1_entry_t mpls_entry; 11231 mpls_entry_1_entry_t mpls_key; 11232 int mpls_index = 0; 11233 int nhi = 0; 11234 int vccv_type = 0; 11235 #endif /* BCM_TRIUMPH_SUPPORT && BCM_MPLS_SUPPORT */ 11236 11237 switch(h_data_p->type) { 11238 case bcmOAMEndpointTypeBHHMPLS: 11239 case bcmOAMEndpointTypeBHHMPLSVccv: 11240 11241 #if defined(BCM_TRIUMPH3_SUPPORT) && defined(BCM_MPLS_SUPPORT) 11242 11243 /* Insert mpls label field to L2_ENTRY table. */ 11244 sal_memset(&l2_entry_1, 0, sizeof(l2_entry_1)); 11245 11246 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, KEY_TYPEf, 12); 11247 11248 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, 11249 BFD__SESSION_IDENTIFIER_TYPEf, 1); 11250 11251 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, BFD__LABELf, 11252 h_data_p->label); 11253 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, VALIDf, 1); 11254 11255 if (!is_local) { 11256 /* Set BHH_REMOTE = 1, DST_MOD, DST_PORT */ 11257 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, BFD__REMOTEf, 1); 11258 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, BFD__MODULE_IDf, 11259 module_id); 11260 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, BFD__DGPPf, 11261 port_id); 11262 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, BFD__INT_PRIf, 11263 endpoint_info->int_pri); 11264 } else { 11265 #if 0 11266 11267 soc_mem_field32_set(unit, L2Xm, &l2_entry, BFD_RX_SESSION_INDEXf, 11268 h_data_p->bhh_endpoint_index); 11269 #endif 11270 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_entry_1, BFD__INT_PRIf, 11271 h_data_p->cpu_qid); 11272 } 11273 11274 soc_mem_insert(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, &l2_entry_1); 11275 11276 SOC_IF_ERROR_RETURN(bcm_tr_mpls_lock (unit)); 11277 11278 sal_memset(&mpls_key, 0, sizeof(mpls_key)); 11279 soc_MPLS_ENTRYm_field32_set(unit, &mpls_key, MPLS__MPLS_LABELf, 11280 h_data_p->label); 11281 soc_MPLS_ENTRYm_field32_set(unit, &mpls_key, KEY_TYPEf, 16); 11282 soc_MPLS_ENTRYm_field32_set(unit, &mpls_key, VALIDf, 1); 11283 11284 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &mpls_index, 11285 &mpls_key, &mpls_entry, 0); 11286 if (SOC_FAILURE(rv)) { 11287 bcm_tr_mpls_unlock(unit); 11288 return rv; 11289 } 11290 11291 if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, 11292 VALIDf) != 0x1)) { 11293 bcm_tr_mpls_unlock (unit); 11294 return (BCM_E_PARAM); 11295 } 11296 11297 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 11298 /* Get the control channel type */ 11299 vccv_type = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, 11300 MPLS__PW_CC_TYPEf); 11301 11302 if (vccv_type == 0) { /* No VCCV type configured */ 11303 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, 11304 MPLS__PW_CC_TYPEf, 11305 (h_data_p->vccv_type + 1)); 11306 11307 } else if (vccv_type != (h_data_p->vccv_type + 1)) { 11308 /* Endpoint add configuration conflicts with MPLS 11309 * port add config 11310 */ 11311 bcm_tr_mpls_unlock(unit); 11312 return BCM_E_PARAM; 11313 } 11314 } 11315 11316 11317 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, 11318 MPLS__SESSION_IDENTIFIER_TYPEf, 1); 11319 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, MPLS__BFD_ENABLEf, 1); 11320 rv = soc_mem_write(unit, MPLS_ENTRYm, 11321 MEM_BLOCK_ANY, mpls_index, 11322 &mpls_entry); 11323 if (rv != SOC_E_NONE) { 11324 bcm_tr_mpls_unlock(unit); 11325 return rv; 11326 } 11327 11328 /* 11329 * PW CC-3 11330 * 11331 * Set MPLS entry DECAP_USE_TTL=0 for corresponding 11332 * Tunnel Terminator label. 11333 */ 11334 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 11335 if (h_data_p->vccv_type == bcmOamBhhVccvTtl) { 11336 rv = bcm_esw_l3_egress_get(unit, h_data_p->egress_if, 11337 &l3_egress); 11338 if (rv != BCM_E_NONE) { 11339 bcm_tr_mpls_unlock(unit); 11340 return rv; 11341 } 11342 11343 /* Look for Tunnel Terminator label */ 11344 num_entries = soc_mem_index_count(unit, MPLS_ENTRYm); 11345 for (i = 0; i < num_entries; i++) { 11346 rv = READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, i, &mpls_entry); 11347 if (rv != SOC_E_NONE) { 11348 bcm_tr_mpls_unlock(unit); 11349 return rv; 11350 } 11351 11352 if (!soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf)) { 11353 continue; 11354 } 11355 if (soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, 11356 MPLS__MPLS_ACTION_IF_BOSf) == 0x1) { 11357 continue; /* L2_SVP */ 11358 } 11359 11360 ingress_if = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, 11361 MPLS__L3_IIFf); 11362 if (ingress_if == l3_egress.intf) { 11363 /* Label found */ 11364 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, 11365 MPLS__DECAP_USE_TTLf, 0); 11366 rv = soc_mem_write(unit, MPLS_ENTRYm, 11367 MEM_BLOCK_ALL, i, 11368 &mpls_entry); 11369 if (rv != SOC_E_NONE) { 11370 bcm_tr_mpls_unlock(unit); 11371 return rv; 11372 } 11373 break; 11374 } 11375 } 11376 } 11377 } 11378 bcm_tr_mpls_unlock (unit); 11379 #endif /* BCM_TRIUMPH3_SUPPORT && BCM_MPLS_SUPPORT */ 11380 break; 11381 11382 default: 11383 rv = BCM_E_UNAVAIL; 11384 break; 11385 } 11386 11387 11388 if((h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) || 11389 (h_data_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT)) 11390 { 11391 rv = _bcm_tr3_oam_bhh_fp_set(unit, h_data_p, nhi, endpoint_info); 11392 } 11393 11394 return (rv); 11395 } 11396 11397 /* 11398 * Function: 11399 * _bcm_tr3_oam_bhh_encap_data_dump 11400 * Purpose: 11401 * Dumps buffer contents. 11402 * Parameters: 11403 * buffer - (IN) Buffer to dump data. 11404 * length - (IN) Length of buffer. 11405 * Returns: 11406 * None 11407 */ 11408 void 11409 _bcm_tr3_oam_bhh_encap_data_dump(uint8 *buffer, int length) 11410 { 11411 int i; 11412 11413 LOG_CLI((BSL_META("\nBHH encapsulation (length=%d):\n"), length)); 11414 11415 for (i = 0; i < length; i++) { 11416 if ((i % 16) == 0) { 11417 LOG_CLI((BSL_META("\n"))); 11418 } 11419 LOG_CLI((BSL_META(" %02x"), buffer[i])); 11420 } 11421 11422 LOG_CLI((BSL_META("\n"))); 11423 return; 11424 } 11425 11426 STATIC int 11427 _bcm_tr3_oam_bhh_ach_header_get(uint32 packet_flags, _ach_header_t *ach) 11428 { 11429 sal_memset(ach, 0, sizeof(*ach)); 11430 11431 ach->f_nibble = SHR_BHH_ACH_FIRST_NIBBLE; 11432 ach->version = SHR_BHH_ACH_VERSION; 11433 ach->reserved = 0; 11434 11435 ach->channel_type = tr3_oam_mpls_tp_ach_channel_type; 11436 11437 return (BCM_E_NONE); 11438 } 11439 11440 STATIC int 11441 _bcm_tr3_oam_bhh_mpls_label_get(uint32 label, uint8 exp, uint8 s, uint8 ttl, 11442 _mpls_label_t *mpls) 11443 { 11444 sal_memset(mpls, 0, sizeof(*mpls)); 11445 11446 mpls->label = label; 11447 mpls->exp = exp & 0x07; 11448 mpls->s = s; 11449 if(ttl) 11450 mpls->ttl = ttl; 11451 else 11452 mpls->ttl = _BHH_MPLS_DFLT_TTL; 11453 11454 return (BCM_E_NONE); 11455 } 11456 11457 STATIC int 11458 _bcm_tr3_oam_bhh_mpls_gal_label_get(_mpls_label_t *mpls, uint8 oam_exp) 11459 { 11460 return _bcm_tr3_oam_bhh_mpls_label_get(SHR_BHH_MPLS_GAL_LABEL, 11461 oam_exp, 1, 1, mpls); 11462 } 11463 11464 STATIC int 11465 _bcm_tr3_oam_bhh_mpls_labels_get(int unit, _bcm_oam_hash_data_t *h_data_p, 11466 uint32 packet_flags, 11467 int max_count, 11468 _mpls_label_t *pw_label, 11469 _mpls_label_t *mpls, 11470 int *mpls_count, bcm_if_t *l3_intf_id) 11471 { 11472 int count = 0; 11473 bcm_l3_egress_t l3_egress; 11474 bcm_mpls_port_t mpls_port; 11475 bcm_mpls_egress_label_t label_array[_BHH_MPLS_MAX_LABELS]; 11476 bcm_mpls_egress_label_t tmp_label; 11477 int label_count; 11478 int i = 0; 11479 11480 /* Get L3 objects */ 11481 bcm_l3_egress_t_init(&l3_egress); 11482 if (BCM_FAILURE(bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) { 11483 return (BCM_E_PARAM); 11484 } 11485 11486 /* Look for a tunnel associated with this interface */ 11487 if (BCM_SUCCESS 11488 (bcm_esw_mpls_tunnel_initiator_get(unit, l3_egress.intf, 11489 _BHH_MPLS_MAX_LABELS, 11490 label_array, &label_count))) { 11491 /* We need to swap the labels configured in tunnel initiator as 11492 * it returns labels in reverse order than how it should be in pkt. 11493 */ 11494 for (i = 0; i < (label_count / 2); i++) { 11495 sal_memcpy(&tmp_label, &label_array[i], sizeof(tmp_label)); 11496 sal_memcpy(&label_array[i], &label_array[label_count - 1 - i], 11497 sizeof(tmp_label)); 11498 sal_memcpy(&label_array[label_count - 1 - i], &tmp_label, 11499 sizeof(tmp_label)); 11500 } 11501 11502 /* Add VRL Label */ 11503 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS) { 11504 if ((l3_egress.mpls_label != BCM_MPLS_LABEL_INVALID) && 11505 (h_data_p->egr_label != BCM_MPLS_LABEL_INVALID) && 11506 (label_count < _BHH_MPLS_MAX_LABELS) ) { 11507 11508 label_array[label_count].label = l3_egress.mpls_label; 11509 label_array[label_count].exp = l3_egress.mpls_exp; 11510 label_array[label_count].ttl = l3_egress.mpls_ttl; 11511 label_count++; 11512 } 11513 /* Traverse through Label stack and match on control label, this 11514 * label should be the one just above GAL in the label stack, any 11515 * following labels should not be added. 11516 */ 11517 for (i = 0; i < label_count; i++) { 11518 if (label_array[i].label == h_data_p->egr_label) { 11519 label_count = i + 1; 11520 label_array[i].exp = h_data_p->egr_label_exp; 11521 if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) && 11522 h_data_p->egr_label_ttl) { 11523 label_array[i].ttl = h_data_p->egr_label_ttl; 11524 } 11525 break; 11526 } 11527 } 11528 } 11529 } 11530 11531 /* MPLS Router Alert */ 11532 if (packet_flags & _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT) { 11533 /* Ignore overrun error as RAL is only added for PW MEPs and so overrun 11534 * condition will not exist. 11535 */ 11536 /* coverity[overrun-local] */ 11537 label_array[label_count].label = SHR_BHH_MPLS_ROUTER_ALERT_LABEL; 11538 label_array[label_count].exp = 0; 11539 label_array[label_count].ttl = 0; 11540 label_count++; 11541 } 11542 11543 /* Use GPORT to resolve interface */ 11544 if (BCM_GPORT_IS_MPLS_PORT(h_data_p->gport)) { 11545 /* Get mpls port and label info */ 11546 bcm_mpls_port_t_init(&mpls_port); 11547 mpls_port.mpls_port_id = h_data_p->gport; 11548 if (BCM_FAILURE(bcm_esw_mpls_port_get(unit, h_data_p->vpn, 11549 &mpls_port))) { 11550 return (BCM_E_PARAM); 11551 } 11552 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv && 11553 h_data_p->vccv_type == bcmOamBhhVccvTtl) { 11554 mpls_port.egress_label.ttl = 0x1; 11555 } 11556 label_array[label_count].label = mpls_port.egress_label.label; 11557 if (h_data_p->egr_label == mpls_port.egress_label.label) { 11558 label_array[label_count].exp = h_data_p->egr_label_exp; 11559 if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) && 11560 h_data_p->egr_label_ttl) { 11561 label_array[label_count].ttl = h_data_p->egr_label_ttl; 11562 } 11563 } else { 11564 label_array[label_count].exp = mpls_port.egress_label.exp; 11565 label_array[label_count].ttl = mpls_port.egress_label.ttl; 11566 } 11567 label_count++; 11568 } 11569 11570 for (i=0; i < label_count; i++) { 11571 _bcm_tr3_oam_bhh_mpls_label_get(label_array[i].label, 11572 label_array[i].exp, 11573 0, 11574 label_array[i].ttl, 11575 &mpls[count++]); 11576 } 11577 11578 /* Set Bottom of Stack if there is no GAL label */ 11579 if (!(packet_flags & _BHH_ENCAP_PKT_GAL)) { 11580 mpls[count-1].s = 1; 11581 } 11582 11583 *mpls_count = count; 11584 11585 return (BCM_E_NONE); 11586 11587 } 11588 11589 STATIC int 11590 _bcm_tr3_oam_bhh_l2_header_get(int unit, _bcm_oam_hash_data_t *h_data_p, 11591 bcm_port_t port, uint16 etype, 11592 _l2_header_t *l2) 11593 { 11594 uint16 tpid; 11595 bcm_l3_egress_t l3_egress; 11596 bcm_l3_intf_t l3_intf; 11597 bcm_vlan_control_vlan_t vc; 11598 int tpid_select; 11599 bcm_pbmp_t pbmp, ubmp; 11600 11601 sal_memset(l2, 0, sizeof(*l2)); 11602 /* Get L3 interfaces */ 11603 bcm_l3_egress_t_init(&l3_egress); 11604 bcm_l3_intf_t_init(&l3_intf); 11605 11606 if (BCM_FAILURE 11607 (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) { 11608 return (BCM_E_PARAM); 11609 } 11610 11611 l3_intf.l3a_intf_id = l3_egress.intf; 11612 if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) { 11613 return (BCM_E_PARAM); 11614 } 11615 11616 /* Get TPID */ 11617 BCM_IF_ERROR_RETURN(bcm_esw_vlan_control_port_get(unit, 11618 port, 11619 bcmVlanPortOuterTpidSelect, 11620 &tpid_select)); 11621 if (tpid_select == BCM_PORT_OUTER_TPID) { 11622 BCM_IF_ERROR_RETURN(bcm_esw_port_tpid_get(unit, port, &tpid)); 11623 } else { 11624 BCM_IF_ERROR_RETURN( 11625 bcm_esw_vlan_control_vlan_get(unit, l3_intf.l3a_vid, &vc)); 11626 tpid = vc.outer_tpid; 11627 } 11628 11629 sal_memcpy(l2->dst_mac, l3_egress.mac_addr, _BHH_MAC_ADDR_LENGTH); 11630 sal_memcpy(l2->src_mac, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH); 11631 l2->vlan_tag.tpid = tpid; 11632 l2->vlan_tag.tci.prio = h_data_p->vlan_pri; 11633 l2->vlan_tag.tci.cfi = 0; 11634 l2->vlan_tag.tci.vid = l3_intf.l3a_vid; 11635 11636 BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_get(unit, 11637 l2->vlan_tag.tci.vid, 11638 &pbmp, 11639 &ubmp)); 11640 if (BCM_PBMP_MEMBER(ubmp, port)) { 11641 l2->vlan_tag.tpid = 0; /* Set to 0 to indicate untagged */ 11642 } 11643 11644 if (l3_intf.l3a_inner_vlan != 0) { 11645 BCM_IF_ERROR_RETURN(bcm_esw_port_inner_tpid_get(unit, port, &tpid)); 11646 l2->vlan_tag_inner.tpid = tpid; 11647 l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri; 11648 l2->vlan_tag_inner.tci.cfi = 0; 11649 l2->vlan_tag_inner.tci.vid = l3_intf.l3a_inner_vlan; 11650 } 11651 l2->etype = etype; 11652 11653 return BCM_E_NONE; 11654 } 11655 STATIC uint8 * 11656 _bcm_tr3_oam_bhh_ach_header_pack(uint8 *buffer, _ach_header_t *ach) 11657 { 11658 uint32 tmp; 11659 11660 tmp = ((ach->f_nibble & 0xf) << 28) | ((ach->version & 0xf) << 24) | 11661 (ach->reserved << 16) | ach->channel_type; 11662 11663 _BHH_ENCAP_PACK_U32(buffer, tmp); 11664 11665 return (buffer); 11666 } 11667 11668 STATIC uint8 * 11669 _bcm_tr3_oam_bhh_mpls_label_pack(uint8 *buffer, _mpls_label_t *mpls) 11670 { 11671 uint32 tmp; 11672 11673 tmp = ((mpls->label & 0xfffff) << 12) | ((mpls->exp & 0x7) << 9) | 11674 ((mpls->s & 0x1) << 8) | mpls->ttl; 11675 _BHH_ENCAP_PACK_U32(buffer, tmp); 11676 11677 return (buffer); 11678 } 11679 11680 STATIC uint8 * 11681 _bcm_tr3_oam_bhh_l2_header_pack(uint8 *buffer, _l2_header_t *l2) 11682 { 11683 uint32 tmp; 11684 int i; 11685 11686 for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) { 11687 _BHH_ENCAP_PACK_U8(buffer, l2->dst_mac[i]); 11688 } 11689 11690 for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) { 11691 _BHH_ENCAP_PACK_U8(buffer, l2->src_mac[i]); 11692 } 11693 11694 /* Vlan Tag tpid = 0 indicates untagged */ 11695 if (0 != l2->vlan_tag.tpid) { 11696 tmp = (l2->vlan_tag.tpid << 16) | 11697 ((l2->vlan_tag.tci.prio & 0x7) << 13) | 11698 ((l2->vlan_tag.tci.cfi & 0x1) << 12) | 11699 (l2->vlan_tag.tci.vid & 0xfff); 11700 _BHH_ENCAP_PACK_U32(buffer, tmp); 11701 } 11702 11703 /*Inner Vlan Tag inner_tpid = 0 indicates single tag */ 11704 if (0 != l2->vlan_tag_inner.tpid) { 11705 tmp = (l2->vlan_tag_inner.tpid << 16) | 11706 ((l2->vlan_tag_inner.tci.prio & 0x7) << 13) | 11707 ((l2->vlan_tag_inner.tci.cfi & 0x1) << 12) | 11708 (l2->vlan_tag_inner.tci.vid & 0xfff); 11709 _BHH_ENCAP_PACK_U32(buffer, tmp); 11710 } 11711 _BHH_ENCAP_PACK_U16(buffer, l2->etype); 11712 11713 return (buffer); 11714 } 11715 /* 11716 * Function: 11717 * _bcm_tr3_oam_bhh_encap_build_pack 11718 * Purpose: 11719 * Builds and packs the BHH packet encapsulation for a given 11720 * BHH tunnel type. 11721 * Parameters: 11722 * unit - (IN) Unit number. 11723 * port - (IN) Port. 11724 * endpoint_config - (IN/OUT) Pointer to BHH endpoint structure. 11725 * packet_flags - (IN) Flags for building packet. 11726 * buffer - (OUT) Buffer returning BHH encapsulation. 11727 * Returns: 11728 * BCM_E_XXX 11729 * Notes: 11730 * The returning BHH encapsulation includes only all the 11731 * encapsulation headers/labels and does not include 11732 * the BHH control packet. 11733 */ 11734 STATIC int 11735 _bcm_tr3_oam_bhh_encap_build_pack(int unit, bcm_port_t port, 11736 _bcm_oam_hash_data_t *h_data_p, 11737 uint32 packet_flags, 11738 uint8 *buffer, 11739 uint32 *encap_length) 11740 { 11741 uint8 *cur_ptr = buffer; 11742 uint16 etype = 0; 11743 bcm_if_t l3_intf_id = -1; 11744 _ach_header_t ach; 11745 _mpls_label_t mpls_gal; 11746 _mpls_label_t mpls_labels[_BHH_MPLS_MAX_LABELS]; 11747 _mpls_label_t pw_label; 11748 int mpls_count = 0; 11749 _l2_header_t l2; 11750 int i; 11751 11752 11753 /* 11754 * Get necessary headers/labels information. 11755 * 11756 * Following order is important since some headers/labels 11757 * may depend on previous header/label information. 11758 */ 11759 if (packet_flags & _BHH_ENCAP_PKT_G_ACH) { 11760 BCM_IF_ERROR_RETURN 11761 (_bcm_tr3_oam_bhh_ach_header_get(packet_flags, &ach)); 11762 } 11763 11764 if (packet_flags & _BHH_ENCAP_PKT_GAL) { 11765 if (h_data_p->egr_label == SHR_BHH_MPLS_GAL_LABEL) { 11766 BCM_IF_ERROR_RETURN 11767 (_bcm_tr3_oam_bhh_mpls_gal_label_get(&mpls_gal, 11768 h_data_p->egr_label_exp)); 11769 } else { 11770 BCM_IF_ERROR_RETURN 11771 (_bcm_tr3_oam_bhh_mpls_gal_label_get(&mpls_gal, 0)); 11772 } 11773 } 11774 11775 if (packet_flags & _BHH_ENCAP_PKT_MPLS) { 11776 etype = SHR_BHH_L2_ETYPE_MPLS_UCAST; 11777 BCM_IF_ERROR_RETURN 11778 (_bcm_tr3_oam_bhh_mpls_labels_get(unit, h_data_p, 11779 packet_flags, 11780 _BHH_MPLS_MAX_LABELS, 11781 &pw_label, 11782 mpls_labels, 11783 &mpls_count, 11784 &l3_intf_id)); 11785 } 11786 11787 /* Always build L2 Header */ 11788 BCM_IF_ERROR_RETURN 11789 (_bcm_tr3_oam_bhh_l2_header_get(unit, 11790 h_data_p, 11791 port, 11792 etype, 11793 &l2)); 11794 11795 /* 11796 * Pack header/labels into given buffer (network packet format). 11797 * 11798 * Following packing order must be followed to correctly 11799 * build the packet encapsulation. 11800 */ 11801 cur_ptr = buffer; 11802 11803 /* L2 Header is always present */ 11804 cur_ptr = _bcm_tr3_oam_bhh_l2_header_pack(cur_ptr, &l2); 11805 11806 if (packet_flags & _BHH_ENCAP_PKT_MPLS) { 11807 for (i = 0;i < mpls_count;i++) { 11808 cur_ptr = _bcm_tr3_oam_bhh_mpls_label_pack(cur_ptr, &mpls_labels[i]); 11809 } 11810 } 11811 11812 if (packet_flags & _BHH_ENCAP_PKT_GAL) { 11813 cur_ptr = _bcm_tr3_oam_bhh_mpls_label_pack(cur_ptr, &mpls_gal); 11814 } 11815 11816 if (packet_flags & _BHH_ENCAP_PKT_G_ACH) { 11817 cur_ptr = _bcm_tr3_oam_bhh_ach_header_pack(cur_ptr, &ach); 11818 } 11819 11820 11821 /* Set BHH encapsulation length */ 11822 *encap_length = cur_ptr - buffer; 11823 11824 return (BCM_E_NONE); 11825 } 11826 11827 /* 11828 * Function: 11829 * _bcm_tr3_oam_bhh_encap_create 11830 * Purpose: 11831 * Creates a BHH packet encapsulation. 11832 * Parameters: 11833 * unit - (IN) Unit number. 11834 * port_id - (IN) Port. 11835 * endpoint_config - (IN/OUT) Pointer to BHH endpoint structure. 11836 * encap_data - (OUT) Buffer returning BHH encapsulation. 11837 * Returns: 11838 * BCM_E_XXX 11839 * Notes: 11840 * The returning BHH encapsulation buffer includes all the 11841 * corresponding headers/labels EXCEPT for the BHH control packet. 11842 */ 11843 STATIC int 11844 _bcm_tr3_oam_bhh_encap_create(int unit, bcm_port_t port_id, 11845 _bcm_oam_hash_data_t *h_data_p, 11846 uint8 *encap_data, 11847 uint8 *encap_type, 11848 uint32 *encap_length) 11849 { 11850 uint32 packet_flags; 11851 _bcm_oam_control_t *oc; 11852 11853 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 11854 11855 packet_flags = 0; 11856 11857 /* 11858 * Get BHH encapsulation packet format flags 11859 * 11860 * Also, perform the following for each BHH tunnel type: 11861 * - Check for valid parameter values 11862 * - Set specific values required by the BHH tunnel definition 11863 * (e.g. such as ttl=1,...) 11864 */ 11865 switch (h_data_p->type) { 11866 case bcmOAMEndpointTypeBHHMPLS: 11867 packet_flags |= 11868 (_BHH_ENCAP_PKT_MPLS | 11869 _BHH_ENCAP_PKT_GAL | 11870 _BHH_ENCAP_PKT_G_ACH); 11871 break; 11872 11873 case bcmOAMEndpointTypeBHHMPLSVccv: 11874 switch(h_data_p->vccv_type) { 11875 11876 case bcmOamBhhVccvChannelAch: 11877 packet_flags |= 11878 (_BHH_ENCAP_PKT_MPLS | 11879 _BHH_ENCAP_PKT_PW | 11880 _BHH_ENCAP_PKT_G_ACH); 11881 break; 11882 11883 case bcmOamBhhVccvRouterAlert: 11884 packet_flags |= 11885 (_BHH_ENCAP_PKT_MPLS | 11886 _BHH_ENCAP_PKT_PW | 11887 _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT | 11888 _BHH_ENCAP_PKT_G_ACH); 11889 break; 11890 11891 case bcmOamBhhVccvTtl: 11892 packet_flags |= 11893 (_BHH_ENCAP_PKT_MPLS | 11894 _BHH_ENCAP_PKT_PW | 11895 _BHH_ENCAP_PKT_G_ACH); 11896 break; 11897 11898 case bcmOamBhhVccvGal13: 11899 packet_flags |= 11900 (_BHH_ENCAP_PKT_MPLS | 11901 _BHH_ENCAP_PKT_PW | 11902 _BHH_ENCAP_PKT_GAL | 11903 _BHH_ENCAP_PKT_G_ACH); 11904 break; 11905 11906 default: 11907 return (BCM_E_PARAM); 11908 break; 11909 } 11910 break; 11911 11912 default: 11913 return (BCM_E_PARAM); 11914 } 11915 11916 /* Build header/labels and pack in buffer */ 11917 BCM_IF_ERROR_RETURN 11918 (_bcm_tr3_oam_bhh_encap_build_pack(unit, port_id, 11919 h_data_p, 11920 packet_flags, 11921 encap_data, 11922 encap_length)); 11923 11924 /* Set encap type (indicates uC side that checksum is required) */ 11925 *encap_type = SHR_BHH_ENCAP_TYPE_RAW; 11926 #ifdef _BHH_DEBUG_DUMP 11927 _bcm_tr3_oam_bhh_encap_data_dump(encap_data, *encap_length); 11928 #endif 11929 11930 if (*encap_length > oc->bhh_max_encap_length) { 11931 LOG_ERROR(BSL_LS_BCM_OAM, 11932 (BSL_META_U(unit, 11933 "OAM(unit %d) Error: Encap length greater than max," 11934 "encap_length=%u max=%u\n"), 11935 unit, *encap_length, oc->bhh_max_encap_length)); 11936 return BCM_E_CONFIG; 11937 } 11938 11939 return (BCM_E_NONE); 11940 } 11941 11942 /* 11943 * Function: 11944 * _bcm_tr3_oam_bhh_appl_callback 11945 * Purpose: 11946 * Update FW BHH appl state 11947 * Parameters: 11948 * unit - (IN) Unit number. 11949 * uC - (IN) core number. 11950 * stage - (IN) core reset stage. 11951 * user_data - (IN) data pointer. 11952 * Returns: 11953 * BCM_E_XXX 11954 * Notes: 11955 */ 11956 11957 int _bcm_tr3_oam_bhh_appl_callback(int unit, 11958 int uC, 11959 soc_cmic_uc_shutdown_stage_t stage, 11960 void *user_data) { 11961 _bcm_oam_control_t *oc; 11962 11963 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 11964 _BCM_OAM_LOCK(oc); 11965 oc->ukernel_not_ready = 1; 11966 11967 _BCM_OAM_UNLOCK(oc); 11968 11969 return BCM_E_NONE; 11970 } 11971 11972 /* 11973 * Function: 11974 * bcm_tr3_oam_bhh_endpoint_create 11975 * Purpose: 11976 * Initialize the HW for BHH packet processing. 11977 * Configure: 11978 * - Copy to CPU BHH error packets 11979 * - CPU COS Queue for BHH packets 11980 * - RX DMA channel 11981 * Parameters: 11982 * unit - (IN) Unit number. 11983 * Returns: 11984 * BCM_E_XXX 11985 * Notes: 11986 */ 11987 int 11988 bcm_tr3_oam_bhh_endpoint_create(int unit, 11989 bcm_oam_endpoint_info_t *endpoint_info, 11990 _bcm_oam_hash_key_t *hash_key) 11991 { 11992 _bcm_oam_control_t *oc; 11993 _bcm_oam_hash_data_t *hash_data = NULL; /* Endpoint hash data pointer. */ 11994 _bcm_oam_group_data_t *group_p; /* Pointer to group data. */ 11995 int ep_req_index; /* Requested endpoint index. */ 11996 int rv = BCM_E_NONE; /* Operation return status. */ 11997 int is_remote = 0; /* Remote endpoint status. */ 11998 int is_replace; 11999 uint32 sglp = 0; /* Source global logical port. */ 12000 uint32 dglp = 0; /* Dest global logical port. */ 12001 bcm_port_t port_id; 12002 bcm_trunk_t trunk_id; 12003 bcm_module_t module_id; 12004 bhh_sdk_msg_ctrl_sess_set_t msg_sess; 12005 bhh_sdk_msg_ctrl_rmep_create_t msg_rmep_create; 12006 uint8 *buffer, *buffer_ptr; 12007 uint16 buffer_len, reply_len; 12008 int encap = 0; 12009 uint32 session_flags; 12010 int bhh_pool_ep_idx = 0; 12011 uint8 group_sw_rdi = 0; 12012 bcm_gport_t tx_gport; 12013 12014 LOG_DEBUG(BSL_LS_BCM_OAM, 12015 (BSL_META_U(unit, 12016 "BHH Info: bcm_tr3_oam_bhh_endpoint_create" 12017 "Endpoint ID=%d.\n"), endpoint_info->id)); 12018 12019 _BCM_OAM_BHH_IS_VALID(unit); 12020 12021 /* Validate input parameter. */ 12022 if (NULL == endpoint_info) { 12023 return (BCM_E_PARAM); 12024 } 12025 12026 if ((endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv) && 12027 (endpoint_info->vccv_type > bcmOamBhhVccvTtl)) 12028 { 12029 LOG_ERROR(BSL_LS_BCM_OAM, 12030 (BSL_META_U(unit, 12031 "BHH Error: vccv type %d not supported (EP=%d)\n"), 12032 endpoint_info->vccv_type, endpoint_info->id)); 12033 return (BCM_E_PARAM); 12034 } 12035 /* Lock already taken by the calling routine. */ 12036 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 12037 12038 /* Get MEP remote endpoint status. */ 12039 is_remote = (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0; 12040 12041 12042 is_replace = ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) != 0); 12043 12044 /* Validate EP Id if BCM_OAM_ENDPOINT_WITH_ID flag is set */ 12045 if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) { 12046 if((endpoint_info->id < _BCM_OAM_BHH_ENDPOINT_OFFSET) || 12047 (endpoint_info->id >= (_BCM_OAM_BHH_ENDPOINT_OFFSET 12048 + oc->bhh_endpoint_count))) { 12049 return (BCM_E_PARAM); 12050 } 12051 } 12052 12053 /* Validate remote EP Id if BCM_OAM_ENDPOINT_REMOTE flag is set */ 12054 if (is_remote) { 12055 if((endpoint_info->local_id < _BCM_OAM_BHH_ENDPOINT_OFFSET) || 12056 (endpoint_info->local_id >= (_BCM_OAM_BHH_ENDPOINT_OFFSET 12057 + oc->bhh_endpoint_count))) { 12058 return (BCM_E_PARAM); 12059 } 12060 } 12061 12062 if((endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) || 12063 (endpoint_info->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT)) 12064 { 12065 if (!oc->bhh_lm_dm_enable) { 12066 LOG_ERROR(BSL_LS_BCM_OAM, 12067 (BSL_META_U(unit, 12068 "BHH Error: LM/DM not enabled (EP=%d)\n"), 12069 endpoint_info->id)); 12070 return (BCM_E_DISABLED); 12071 } 12072 } 12073 12074 12075 /* Create a new endpoint with the requested ID. */ 12076 if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) { 12077 hash_data = &oc->oam_hash_data[endpoint_info->id]; 12078 12079 if (is_replace && !hash_data->in_use) 12080 { 12081 return (BCM_E_NOT_FOUND); 12082 } 12083 else if (!is_replace && hash_data->in_use) 12084 { 12085 return (BCM_E_EXISTS); 12086 } 12087 12088 ep_req_index = endpoint_info->id; 12089 bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(ep_req_index); 12090 12091 if((ep_req_index < _BCM_OAM_BHH_ENDPOINT_OFFSET) || 12092 (ep_req_index >= (_BCM_OAM_BHH_ENDPOINT_OFFSET + oc->bhh_endpoint_count))) { 12093 rv = BCM_E_PARAM; 12094 } 12095 12096 if(BCM_FAILURE(rv)) { 12097 LOG_ERROR(BSL_LS_BCM_OAM, 12098 (BSL_META_U(unit, 12099 "BHH Error: Endpoint check (EP=%d) - %s.\n"), 12100 endpoint_info->id, bcm_errmsg(rv))); 12101 return (rv); 12102 } 12103 12104 if(!is_replace) { 12105 rv = shr_idxres_list_reserve(oc->bhh_pool, bhh_pool_ep_idx, 12106 bhh_pool_ep_idx); 12107 if (BCM_FAILURE(rv)) { 12108 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 12109 LOG_ERROR(BSL_LS_BCM_OAM, 12110 (BSL_META_U(unit, 12111 "BHH Error: Endpoint reserve (EP=%d) - %s.\n"), 12112 endpoint_info->id, bcm_errmsg(rv))); 12113 return (rv); 12114 } 12115 } 12116 } else { 12117 12118 if (is_replace) 12119 { 12120 /* Replace specified with no ID */ 12121 12122 return (BCM_E_PARAM); 12123 } 12124 12125 /* BHH uses local and remote same index */ 12126 if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) { 12127 ep_req_index = endpoint_info->local_id; 12128 bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(ep_req_index); 12129 } 12130 else { 12131 /* Allocate the next available endpoint index. */ 12132 rv = shr_idxres_list_alloc(oc->bhh_pool, 12133 (shr_idxres_element_t *)&bhh_pool_ep_idx); 12134 if (BCM_FAILURE(rv)) { 12135 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_FULL) : rv; 12136 LOG_ERROR(BSL_LS_BCM_OAM, 12137 (BSL_META_U(unit, 12138 "BHH Error: Endpoint alloc failed - %s.\n"), 12139 bcm_errmsg(rv))); 12140 return (rv); 12141 } 12142 /* Set the allocated endpoint id value. */ 12143 ep_req_index = BCM_OAM_BHH_GET_SDK_EP(bhh_pool_ep_idx); 12144 } 12145 endpoint_info->id = ep_req_index; 12146 } 12147 12148 /* Get the hash data pointer where the data is to be stored. */ 12149 hash_data = &oc->oam_hash_data[ep_req_index]; 12150 group_p = &oc->group_info[endpoint_info->group]; 12151 12152 /* 12153 *The uKernel is not provisioned until both endpoints (local and remote) 12154 * are provisioned in the host. 12155 */ 12156 if (is_remote) { 12157 12158 if (!hash_data->in_use) { 12159 return (BCM_E_NOT_FOUND); 12160 } else if (hash_data->flags & BCM_OAM_ENDPOINT_REMOTE) { 12161 return (BCM_E_EXISTS); 12162 } 12163 12164 /* 12165 * Now that both ends are provisioned the uKernel can be 12166 * configured. 12167 */ 12168 msg_rmep_create.sess_id = bhh_pool_ep_idx; 12169 msg_rmep_create.flags = 0; 12170 msg_rmep_create.enable = 1; 12171 msg_rmep_create.remote_mep_id = endpoint_info->name; 12172 msg_rmep_create.period = _tr3_ccm_intervals[ 12173 _bcm_tr3_oam_ccm_msecs_to_hw_encode(endpoint_info->ccm_period)]; 12174 12175 /* Pack control message data into DMA buffer */ 12176 buffer = oc->dma_buffer; 12177 buffer_ptr = bhh_sdk_msg_ctrl_rmep_create_pack(buffer, &msg_rmep_create); 12178 buffer_len = buffer_ptr - buffer; 12179 12180 /* Send BHH Session Update message to uC */ 12181 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 12182 MOS_MSG_SUBCLASS_BHH_RMEP_CREATE, 12183 buffer_len, 0, 12184 MOS_MSG_SUBCLASS_BHH_RMEP_CREATE_REPLY, 12185 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 12186 if (BCM_FAILURE(rv) || (reply_len != 0)) { 12187 LOG_ERROR(BSL_LS_BCM_OAM, 12188 (BSL_META_U(unit, 12189 "BHH Error: Endpoint destroy (EP=%d) - %s.\n"), 12190 endpoint_info->id, bcm_errmsg(rv))); 12191 return (BCM_E_INTERNAL); 12192 } 12193 } else { 12194 12195 /* Get the Trunk, Port and Modid info for this Gport */ 12196 BCM_IF_ERROR_RETURN( 12197 _bcm_tr3_oam_endpoint_gport_resolve(unit, endpoint_info, 12198 &sglp, &dglp, &trunk_id, 12199 &tx_gport)); 12200 port_id = BCM_GPORT_MODPORT_PORT_GET(tx_gport); 12201 module_id = BCM_GPORT_MODPORT_MODID_GET(tx_gport); 12202 12203 /* Clear the hash data element contents before storing the values. */ 12204 _BCM_OAM_HASH_DATA_CLEAR(hash_data); 12205 hash_data->type = endpoint_info->type; 12206 hash_data->ep_id = endpoint_info->id; 12207 hash_data->group_index = endpoint_info->group; 12208 hash_data->level = endpoint_info->level; 12209 hash_data->vlan = endpoint_info->vlan; 12210 hash_data->vlan_pri = endpoint_info->pkt_pri; 12211 hash_data->inner_vlan_pri = endpoint_info->inner_pkt_pri; 12212 hash_data->gport = endpoint_info->gport; 12213 hash_data->trunk_index = endpoint_info->trunk_index; 12214 hash_data->sglp = sglp; 12215 hash_data->dglp = dglp; 12216 hash_data->flags = endpoint_info->flags; 12217 hash_data->period = endpoint_info->ccm_period; 12218 hash_data->vccv_type = endpoint_info->vccv_type; 12219 hash_data->vpn = endpoint_info->vpn; 12220 hash_data->name = endpoint_info->name; 12221 hash_data->egress_if = endpoint_info->intf_id; 12222 hash_data->cpu_qid = endpoint_info->cpu_qid; 12223 hash_data->label = endpoint_info->mpls_label; 12224 hash_data->gport = endpoint_info->gport; 12225 hash_data->flags = endpoint_info->flags; 12226 hash_data->local_tx_enabled = 0; 12227 hash_data->local_rx_enabled = 0; 12228 hash_data->egr_label = endpoint_info->egress_label.label; 12229 hash_data->egr_label_exp = endpoint_info->egress_label.exp; 12230 hash_data->egr_label_ttl = endpoint_info->egress_label.ttl; 12231 12232 /* Initialize hardware index as invalid indices. */ 12233 hash_data->local_tx_index = _BCM_OAM_INVALID_INDEX; 12234 hash_data->local_rx_index = _BCM_OAM_INVALID_INDEX; 12235 hash_data->remote_index = _BCM_OAM_INVALID_INDEX; 12236 12237 #if 0 12238 /* hash collision!!! Is this needed for BHH? */ 12239 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, hash_data); 12240 if (BCM_FAILURE(rv)) { 12241 LOG_ERROR(BSL_LS_BCM_OAM, 12242 (BSL_META_U(unit, 12243 "BHH Error: Hash table insert failed EP=%d %s.\n"), 12244 endpoint_info->id, bcm_errmsg(rv))); 12245 return (rv); 12246 } 12247 #endif 12248 12249 /* Create or Update */ 12250 session_flags = (is_replace) ? 0 : SHR_BHH_SESS_SET_F_CREATE; 12251 12252 /* Set Endpoint config entry */ 12253 hash_data->bhh_endpoint_index = ep_req_index; 12254 12255 /* Set Encapsulation in HW */ 12256 if (!is_replace || (endpoint_info->flags & BCM_BHH_ENDPOINT_ENCAP_SET)) { 12257 rv = _bcm_tr3_oam_bhh_encap_hw_set(unit, hash_data, module_id, 12258 port_id, 1, endpoint_info); 12259 if(BCM_FAILURE(rv)) { 12260 /* Return ID back to free MEP ID pool.*/ 12261 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx)); 12262 LOG_ERROR(BSL_LS_BCM_OAM, 12263 (BSL_META_U(unit, 12264 "BHH Error: Encap set fail (EP=%d) - %s.\n"), 12265 endpoint_info->id, bcm_errmsg(rv))); 12266 return (rv); 12267 } 12268 encap = 1; 12269 } 12270 12271 /* Set control message data */ 12272 sal_memset(&msg_sess, 0, sizeof(msg_sess)); 12273 12274 /* 12275 * Set the BHH encapsulation data 12276 * 12277 * The function _bcm_tr3_oam_bhh_encap_create() is called first 12278 * since this sets some fields in 'hash_data' which are 12279 * used in the message. 12280 */ 12281 if (encap) { 12282 rv = _bcm_tr3_oam_bhh_encap_create(unit, 12283 port_id, 12284 hash_data, 12285 msg_sess.encap_data, 12286 &msg_sess.encap_type, 12287 &msg_sess.encap_length); 12288 12289 if(BCM_FAILURE(rv)) 12290 { 12291 /* Return ID back to free MEP ID pool.*/ 12292 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx)); 12293 LOG_ERROR(BSL_LS_BCM_OAM, 12294 (BSL_META_U(unit, 12295 "BHH Error: Endpoint destroy (EP=%d) - %s.\n"), 12296 endpoint_info->id, bcm_errmsg(rv))); 12297 return (rv); 12298 } 12299 } 12300 12301 /* 12302 * Endpoint can be one of: CCM, LB, LM or DM. The default is CCM, 12303 * all others modes must be specified via a config flag. 12304 */ 12305 if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOOPBACK) 12306 session_flags |= SHR_BHH_SESS_SET_F_LB; 12307 else if (endpoint_info->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) 12308 session_flags |= SHR_BHH_SESS_SET_F_DM; 12309 else if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) 12310 session_flags |= SHR_BHH_SESS_SET_F_LM; 12311 else 12312 session_flags |= SHR_BHH_SESS_SET_F_CCM; 12313 12314 if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) 12315 session_flags |= SHR_BHH_SESS_SET_F_MIP; 12316 12317 _bcm_tr3_oam_get_group_sw_rdi (unit, endpoint_info->group, 12318 &group_sw_rdi); 12319 if (group_sw_rdi) { 12320 session_flags |= SHR_BHH_SESS_SET_F_RDI; 12321 } 12322 /* 12323 if (!local_tx_enabled) 12324 session_flags |= SHR_BHH_SESS_SET_F_PASSIVE;*/ 12325 12326 msg_sess.sess_id = bhh_pool_ep_idx; 12327 msg_sess.flags = session_flags; 12328 12329 msg_sess.mel = hash_data->level; 12330 msg_sess.mep_id = hash_data->name; 12331 sal_memcpy(msg_sess.meg_id, group_p->name, BCM_OAM_GROUP_NAME_LENGTH); 12332 12333 msg_sess.period = _tr3_ccm_intervals[ 12334 _bcm_tr3_oam_ccm_msecs_to_hw_encode(endpoint_info->ccm_period)]; 12335 msg_sess.if_num = endpoint_info->intf_id; 12336 msg_sess.tx_port = port_id; 12337 if (BCM_TRUNK_INVALID == trunk_id) { 12338 msg_sess.rx_port = port_id; 12339 } else { 12340 msg_sess.rx_port = trunk_id; 12341 msg_sess.trunk_valid = 1; 12342 } 12343 msg_sess.tx_cos = endpoint_info->int_pri; 12344 msg_sess.tx_pri = endpoint_info->pkt_pri; 12345 msg_sess.tx_qnum = SOC_INFO(unit).port_uc_cosq_base[port_id] + endpoint_info->int_pri; 12346 msg_sess.lm_counter_index = 12347 hash_data->lm_counter_index | _BCM_OAM_LM_COUNTER_TX_OFFSET; 12348 12349 msg_sess.mpls_label = endpoint_info->mpls_label; 12350 12351 switch (endpoint_info->type) { 12352 case bcmOAMEndpointTypeBHHMPLS: 12353 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_LSP; 12354 msg_sess.priority = endpoint_info->mpls_exp; 12355 break; 12356 12357 case bcmOAMEndpointTypeBHHMPLSVccv: 12358 switch(endpoint_info->vccv_type) { 12359 12360 case bcmOamBhhVccvChannelAch: 12361 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_1; 12362 msg_sess.priority = endpoint_info->mpls_exp; 12363 break; 12364 12365 case bcmOamBhhVccvRouterAlert: 12366 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_2; 12367 msg_sess.priority = endpoint_info->mpls_exp; 12368 break; 12369 12370 case bcmOamBhhVccvTtl: 12371 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_3; 12372 msg_sess.priority = endpoint_info->mpls_exp; 12373 break; 12374 12375 case bcmOamBhhVccvGal13: 12376 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_4; 12377 msg_sess.priority = endpoint_info->mpls_exp; 12378 break; 12379 12380 default: 12381 return BCM_E_PARAM; 12382 break; 12383 } 12384 break; 12385 12386 case bcmOAMEndpointTypeBhhSection: 12387 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION; 12388 msg_sess.priority = 0; 12389 break; 12390 case bcmOAMEndpointTypeBhhSectionInnervlan: 12391 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_INNERVLAN; 12392 msg_sess.priority = endpoint_info->inner_pkt_pri; 12393 break; 12394 case bcmOAMEndpointTypeBhhSectionOuterVlan: 12395 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTERVLAN; 12396 msg_sess.priority = endpoint_info->pkt_pri; 12397 break; 12398 case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan: 12399 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTER_PLUS_INNERVLAN; 12400 msg_sess.priority = endpoint_info->pkt_pri; 12401 break; 12402 12403 default: 12404 return BCM_E_PARAM; 12405 } 12406 12407 /* Pack control message data into DMA buffer */ 12408 buffer = oc->dma_buffer; 12409 buffer_ptr = bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess); 12410 buffer_len = buffer_ptr - buffer; 12411 12412 /* Send BHH Session Update message to uC */ 12413 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 12414 MOS_MSG_SUBCLASS_BHH_SESS_SET, 12415 buffer_len, 0, 12416 MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY, 12417 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 12418 if (BCM_FAILURE(rv) || (reply_len != 0)) { 12419 /* Return ID back to free MEP ID pool.*/ 12420 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx)); 12421 LOG_ERROR(BSL_LS_BCM_OAM, 12422 (BSL_META_U(unit, 12423 "BHH Error: Endpoint destroy (EP=%d) - %s.\n"), 12424 endpoint_info->id, bcm_errmsg(rv))); 12425 return (rv); 12426 } 12427 12428 if (!is_replace) { 12429 rv = _bcm_oam_group_ep_list_add(unit, endpoint_info->group, 12430 endpoint_info->id); 12431 } 12432 12433 if (BCM_FAILURE(rv)) { 12434 /* Return ID back to free MEP ID pool.*/ 12435 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx)); 12436 LOG_ERROR(BSL_LS_BCM_OAM, 12437 (BSL_META_U(unit, 12438 "OAM Error: Tx config failed for EP=%d %s.\n"), 12439 endpoint_info->id, bcm_errmsg(rv))); 12440 return (rv); 12441 } 12442 } 12443 hash_data->in_use = 1; 12444 12445 #ifdef BCM_WARM_BOOT_SUPPORT 12446 SOC_CONTROL_LOCK(unit); 12447 SOC_CONTROL(unit)->scache_dirty = 1; 12448 SOC_CONTROL_UNLOCK(unit); 12449 #endif 12450 12451 return (rv); 12452 } 12453 12454 /* 12455 * Function: 12456 * _bcm_tr3_oam_bhh_fp_init 12457 * Purpose: 12458 * Initialize the fp for BHH LM/DM packet processing. 12459 * Configure: 12460 * - Qualifiers QSET 12461 * - Create Groups 12462 * Parameters: 12463 * unit - (IN) Unit number. 12464 * oc - (IN) OAM control structure. 12465 * Returns: 12466 * BCM_E_XXX 12467 * Notes: 12468 */ 12469 STATIC int 12470 _bcm_tr3_oam_bhh_fp_init(int unit) 12471 { 12472 int rv = BCM_E_NONE; 12473 _bcm_oam_control_t *oc; 12474 12475 /* Lock already taken by the calling routine. */ 12476 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 12477 12478 BCM_FIELD_QSET_INIT(oc->bhh_lmdm_qset); 12479 BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifySrcPort); 12480 BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifySrcTrunk); 12481 BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifyDstPort); 12482 BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifyDstTrunk); 12483 BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifyOuterVlanId); 12484 BCM_FIELD_QSET_ADD(oc->bhh_lmdm_qset, bcmFieldQualifyDstL3Egress); 12485 12486 12487 if (oc->bhh_udf_mode) { /* Configure UDF using bcm_udf_xxx() APIs */ 12488 bcm_udf_alloc_hints_t hints; 12489 bcm_udf_t label; 12490 bcm_udf_t ach; 12491 bcm_udf_t opcode; 12492 bcm_udf_pkt_format_info_t pkt_fmt; 12493 12494 bcm_udf_pkt_format_info_t_init(&pkt_fmt); 12495 pkt_fmt.prio = 0xffff; /* Highest priority */ 12496 pkt_fmt.l2 = BCM_PKT_FORMAT_L2_ANY; 12497 pkt_fmt.vlan_tag = BCM_PKT_FORMAT_VLAN_TAG_ANY; 12498 pkt_fmt.tunnel = BCM_PKT_FORMAT_TUNNEL_MPLS; 12499 pkt_fmt.mpls = BCM_PKT_FORMAT_MPLS_ANY; 12500 BCM_IF_ERROR_RETURN( 12501 bcm_esw_udf_pkt_format_create(unit, 12502 BCM_UDF_PKT_FORMAT_CREATE_O_NONE, 12503 &pkt_fmt, 12504 &(oc->bhh_udf_pkt_fmt_id))); 12505 12506 bcm_udf_alloc_hints_t_init (&hints); 12507 hints.flags = BCM_UDF_CREATE_O_FIELD_INGRESS; 12508 hints.qset = oc->bhh_lmdm_qset; 12509 12510 /* Match MPLS label */ 12511 bcm_udf_t_init(&label); 12512 label.layer = bcmUdfLayerL3OuterHeader; 12513 label.start = 0; 12514 label.width = SHR_BHH_MPLS_LABEL_LENGTH * 8; /* Convert to bits */ 12515 12516 12517 BCM_IF_ERROR_RETURN(bcm_esw_udf_create(unit, 12518 &hints, 12519 &label, 12520 &(oc->bhh_label_udf_id))); 12521 12522 BCM_IF_ERROR_RETURN( 12523 bcm_esw_udf_pkt_format_add(unit, 12524 oc->bhh_label_udf_id, 12525 oc->bhh_udf_pkt_fmt_id)); 12526 BCM_IF_ERROR_RETURN( 12527 bcm_esw_field_qset_id_multi_set(unit, 12528 bcmFieldQualifyUdf, 12529 1, 12530 &(oc->bhh_label_udf_id), 12531 &hints.qset)); 12532 12533 /* Match ACH channel type 0x8902 */ 12534 bcm_udf_t_init(&ach); 12535 ach.layer = bcmUdfLayerL3OuterHeader; 12536 ach.start = 10 * 8; /* Convert to bits*/ 12537 ach.width = SHR_BHH_ACH_TYPE_LENGTH * 8; 12538 12539 BCM_IF_ERROR_RETURN(bcm_esw_udf_create(unit, 12540 &hints, 12541 &ach, 12542 &(oc->bhh_ach_udf_id))); 12543 12544 BCM_IF_ERROR_RETURN( 12545 bcm_esw_udf_pkt_format_add(unit, 12546 oc->bhh_ach_udf_id, 12547 oc->bhh_udf_pkt_fmt_id)); 12548 BCM_IF_ERROR_RETURN( 12549 bcm_esw_field_qset_id_multi_set(unit, 12550 bcmFieldQualifyUdf, 12551 1, 12552 &(oc->bhh_ach_udf_id), 12553 &hints.qset)); 12554 12555 12556 /* Match opcode 45 or 46 or 47 */ 12557 bcm_udf_t_init(&opcode); 12558 opcode.layer = bcmUdfLayerL3OuterHeader; 12559 opcode.start = 13 * 8; /* Convert to bits*/ 12560 opcode.width = SHR_BHH_OPCODE_LEN * 8; 12561 12562 BCM_IF_ERROR_RETURN(bcm_esw_udf_create(unit, 12563 &hints, 12564 &opcode, 12565 &(oc->bhh_opcode_udf_id))); 12566 12567 BCM_IF_ERROR_RETURN(bcm_esw_udf_pkt_format_add(unit, 12568 oc->bhh_opcode_udf_id, 12569 oc->bhh_udf_pkt_fmt_id)); 12570 BCM_IF_ERROR_RETURN( 12571 bcm_esw_field_qset_id_multi_set(unit, 12572 bcmFieldQualifyUdf, 12573 1, 12574 &(oc->bhh_opcode_udf_id), 12575 &hints.qset)); 12576 oc->bhh_lmdm_qset = hints.qset; 12577 12578 } else { /* Configure UDF using bcm_field_xxx() APIs */ 12579 12580 bcm_field_data_packet_format_t pkt_fmt; 12581 bcm_field_data_qualifier_t label; 12582 bcm_field_data_qualifier_t ach; 12583 bcm_field_data_qualifier_t opcode; 12584 12585 bcm_field_data_packet_format_t_init(&pkt_fmt); 12586 pkt_fmt.relative_offset = 0; 12587 pkt_fmt.l2 = BCM_FIELD_DATA_FORMAT_L2_ANY; 12588 pkt_fmt.vlan_tag = BCM_FIELD_DATA_FORMAT_VLAN_TAG_ANY; 12589 pkt_fmt.tunnel = BCM_FIELD_DATA_FORMAT_TUNNEL_MPLS; 12590 pkt_fmt.mpls = BCM_FIELD_DATA_FORMAT_MPLS_ANY; 12591 12592 /* match mpls label */ 12593 bcm_field_data_qualifier_t_init(&label); 12594 label.offset_base = bcmFieldDataOffsetBaseOuterL3Header; 12595 label.offset = 0; 12596 label.length = SHR_BHH_MPLS_LABEL_LENGTH; 12597 BCM_IF_ERROR_RETURN(bcm_esw_field_data_qualifier_create(unit, &label)); 12598 BCM_IF_ERROR_RETURN( 12599 bcm_esw_field_data_qualifier_packet_format_add(unit, 12600 label.qual_id, 12601 &pkt_fmt)); 12602 BCM_IF_ERROR_RETURN( 12603 bcm_esw_field_qset_data_qualifier_add(unit, 12604 &oc->bhh_lmdm_qset, 12605 label.qual_id)); 12606 oc->bhh_label_qual_id = label.qual_id; 12607 12608 12609 /* match ACH channel type 0x8902 */ 12610 bcm_field_data_qualifier_t_init(&ach); 12611 ach.offset_base = bcmFieldDataOffsetBaseOuterL3Header; 12612 ach.offset = 10; 12613 ach.length = SHR_BHH_ACH_TYPE_LENGTH; 12614 BCM_IF_ERROR_RETURN(bcm_esw_field_data_qualifier_create(unit, &ach)); 12615 BCM_IF_ERROR_RETURN( 12616 bcm_esw_field_data_qualifier_packet_format_add(unit, 12617 ach.qual_id, 12618 &pkt_fmt)); 12619 BCM_IF_ERROR_RETURN( 12620 bcm_esw_field_qset_data_qualifier_add(unit, 12621 &oc->bhh_lmdm_qset, 12622 ach.qual_id)); 12623 oc->bhh_ach_qual_id = ach.qual_id; 12624 12625 12626 /* match opcode 45 or 46 or 47 */ 12627 bcm_field_data_qualifier_t_init(&opcode); 12628 opcode.offset_base = bcmFieldDataOffsetBaseOuterL3Header; 12629 opcode.offset = 13; 12630 opcode.length = SHR_BHH_OPCODE_LEN; 12631 BCM_IF_ERROR_RETURN(bcm_esw_field_data_qualifier_create(unit, &opcode)); 12632 BCM_IF_ERROR_RETURN( 12633 bcm_esw_field_data_qualifier_packet_format_add(unit, 12634 opcode.qual_id, 12635 &pkt_fmt)); 12636 BCM_IF_ERROR_RETURN( 12637 bcm_esw_field_qset_data_qualifier_add(unit, 12638 &oc->bhh_lmdm_qset, 12639 opcode.qual_id)); 12640 oc->bhh_opcode_qual_id = opcode.qual_id; 12641 12642 oc->bhh_field_pkt_fmt = pkt_fmt; 12643 12644 } 12645 return rv; 12646 } 12647 12648 /* 12649 * Function: 12650 * _bcm_tr3_oam_bhh_hw_init 12651 * Purpose: 12652 * Initialize the HW for BHH packet processing. 12653 * Configure: 12654 * - Copy to CPU BHH error packets 12655 * - CPU COS Queue for BHH packets 12656 * - RX DMA channel 12657 * Parameters: 12658 * unit - (IN) Unit number. 12659 * Returns: 12660 * BCM_E_XXX 12661 * Notes: 12662 */ 12663 STATIC int 12664 _bcm_tr3_oam_bhh_hw_init(int unit) 12665 { 12666 int rv = BCM_E_NONE; 12667 _bcm_oam_control_t *oc; /* OAM control structure. */ 12668 uint32 val; 12669 int index; 12670 int ach_error_index; 12671 int cosq_map_size; 12672 bcm_rx_reasons_t reasons, reasons_mask; 12673 uint8 int_prio, int_prio_mask; 12674 uint32 packet_type, packet_type_mask; 12675 bcm_cos_queue_t cosq; 12676 bcm_rx_chan_t chan_id; 12677 int num_cosq = 0; 12678 int min_cosq, max_cosq; 12679 int i; 12680 12681 /* Get OAM Control Structure. */ 12682 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 12683 12684 _BCM_OAM_LOCK(oc); 12685 12686 /* 12687 * Send BHH error packet to CPU 12688 * 12689 * Configure CPU_CONTROL_0 register 12690 */ 12691 rv = READ_CPU_CONTROL_0r(unit, &val); 12692 if(BCM_FAILURE(rv)) { 12693 LOG_ERROR(BSL_LS_BCM_OAM, 12694 (BSL_META_U(unit, 12695 "BHH Error:hw init. Read CPU Control Reg %s.\n"), 12696 bcm_errmsg(rv))); 12697 _BCM_OAM_UNLOCK(oc); 12698 return (rv); 12699 } 12700 12701 soc_reg_field_set(unit, CPU_CONTROL_0r, &val, 12702 BFD_UNKNOWN_VERSION_TOCPUf, 1); 12703 soc_reg_field_set(unit, CPU_CONTROL_0r, &val, 12704 BFD_YOUR_DISCRIMINATOR_NOT_FOUND_TOCPUf, 1); 12705 soc_reg_field_set(unit, CPU_CONTROL_0r, &val, 12706 BFD_UNKNOWN_CONTROL_PACKET_TOCPUf, 1); 12707 12708 rv = WRITE_CPU_CONTROL_0r(unit, val); 12709 if(BCM_FAILURE(rv)) { 12710 LOG_ERROR(BSL_LS_BCM_OAM, 12711 (BSL_META_U(unit, 12712 "BHH Error:hw init. Write CPU Control_0 Reg %s.\n"), 12713 bcm_errmsg(rv))); 12714 _BCM_OAM_UNLOCK(oc); 12715 return (rv); 12716 } 12717 12718 /* 12719 * Configure CPU_CONTROL_M register 12720 */ 12721 12722 rv = READ_CPU_CONTROL_Mr(unit, &val); 12723 if(BCM_FAILURE(rv)) { 12724 LOG_ERROR(BSL_LS_BCM_OAM, 12725 (BSL_META_U(unit, 12726 "BHH Error:hw init. Read CPU Control Reg %s.\n"), 12727 bcm_errmsg(rv))); 12728 _BCM_OAM_UNLOCK(oc); 12729 return (rv); 12730 } 12731 soc_reg_field_set(unit, CPU_CONTROL_Mr, &val, 12732 MPLS_UNKNOWN_ACH_TYPE_TO_CPUf, 1); 12733 soc_reg_field_set(unit, CPU_CONTROL_Mr, &val, 12734 MPLS_UNKNOWN_ACH_VERSION_TOCPUf, 1); 12735 rv = WRITE_CPU_CONTROL_Mr(unit, val); 12736 if(BCM_FAILURE(rv)) { 12737 LOG_ERROR(BSL_LS_BCM_OAM, 12738 (BSL_META_U(unit, 12739 "BHH Error:hw init. Write CPU Control_m Reg %s.\n"), 12740 bcm_errmsg(rv))); 12741 _BCM_OAM_UNLOCK(oc); 12742 return (rv); 12743 } 12744 12745 if(oc->ukernel_not_ready == 0){ 12746 /* 12747 * Get COSQ for BHH 12748 */ 12749 min_cosq = 0; 12750 for (i = 0; i < SOC_CMCS_NUM(unit); i++) { 12751 num_cosq = NUM_CPU_ARM_COSQ(unit, i); 12752 if (i == oc->uc_num + 1) { 12753 break; 12754 } 12755 min_cosq += num_cosq; 12756 } 12757 max_cosq = min_cosq + num_cosq - 1; 12758 12759 if(max_cosq < min_cosq) { 12760 LOG_ERROR(BSL_LS_BCM_OAM, 12761 (BSL_META_U(unit, 12762 "BHH Error: No BHH COS Queue available from uC%d - %s\n"), 12763 oc->uc_num, bcm_errmsg(BCM_E_CONFIG))); 12764 _BCM_OAM_UNLOCK(oc); 12765 return (BCM_E_CONFIG); 12766 } 12767 12768 /* check user configured COSq */ 12769 if (oc->cpu_cosq != BHH_COSQ_INVALID) { 12770 if ((oc->cpu_cosq < min_cosq) || 12771 (oc->cpu_cosq > max_cosq)) { 12772 _BCM_OAM_UNLOCK(oc); 12773 return (BCM_E_CONFIG); 12774 } 12775 min_cosq = max_cosq = oc->cpu_cosq; 12776 } 12777 12778 /* 12779 * Assign RX DMA channel to CPU COS Queue 12780 * (This is the RX channel to listen on for BHH packets). 12781 * 12782 * DMA channels (12) are assigned 4 per processor: 12783 * (see /src/bcm/common/rx.c) 12784 * channels 0..3 --> PCI host 12785 * channels 4..7 --> uController 0 12786 * chnanels 8..11 --> uController 1 12787 * 12788 * The uControllers designate the 4 local DMA channels as follows: 12789 * local channel 0 --> TX 12790 * local channel 1..3 --> RX 12791 * 12792 * Each uController application needs to use a different 12793 * RX DMA channel to listen on. 12794 */ 12795 chan_id = (BCM_RX_CHANNELS * (SOC_ARM_CMC(unit, oc->uc_num))) + 12796 oc->rx_channel; 12797 12798 for (i = max_cosq; i >= min_cosq; i--) { 12799 rv = _bcm_common_rx_queue_channel_set(unit, i, chan_id); 12800 if(BCM_SUCCESS(rv)) { 12801 oc->cpu_cosq = i; 12802 break; 12803 } 12804 } 12805 12806 if (i < min_cosq) { 12807 rv = BCM_E_RESOURCE; 12808 LOG_ERROR(BSL_LS_BCM_OAM, 12809 (BSL_META_U(unit, 12810 "BHH Error:hw init. queue channel set %s.\n"), 12811 bcm_errmsg(rv))); 12812 _BCM_OAM_UNLOCK(oc); 12813 return (rv); 12814 } 12815 12816 /* 12817 * Direct BHH packets to designated CPU COS Queue...or more accurately 12818 * BFD error packets. 12819 * 12820 * Reasons: 12821 * - bcmRxReasonBFD: BFD error 12822 * - bcmRxReasonBfdUnknownVersion: BFD Unknown ACH 12823 * NOTE: 12824 * The user input 'cpu_qid' (bcm_BHH_endpoint_t) could be 12825 * used to select different CPU COS queue. Currently, 12826 * all priorities are mapped into the same CPU COS Queue. 12827 */ 12828 12829 /* Find available entries in CPU COS queue map table */ 12830 ach_error_index = -1; /* COSQ map index for error packets */ 12831 rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size); 12832 if(BCM_FAILURE(rv)) { 12833 LOG_ERROR(BSL_LS_BCM_OAM, 12834 (BSL_META_U(unit, 12835 "BHH Error:hw init. cosq maps size %s.\n"), 12836 bcm_errmsg(rv))); 12837 _BCM_OAM_UNLOCK(oc); 12838 return (rv); 12839 } 12840 12841 for (index = 0; index < cosq_map_size; index++) { 12842 rv = bcm_esw_rx_cosq_mapping_get(unit, index, 12843 &reasons, &reasons_mask, 12844 &int_prio, &int_prio_mask, 12845 &packet_type, &packet_type_mask, 12846 &cosq); 12847 if (rv == BCM_E_NOT_FOUND) { 12848 /* Assign first available index */ 12849 rv = BCM_E_NONE; 12850 ach_error_index = index; 12851 break; 12852 } 12853 if (BCM_FAILURE(rv)) { 12854 LOG_ERROR(BSL_LS_BCM_OAM, 12855 (BSL_META_U(unit, 12856 "BHH Error:hw init. cosq maps get %s.\n"), 12857 bcm_errmsg(rv))); 12858 _BCM_OAM_UNLOCK(oc); 12859 return (rv); 12860 } 12861 } 12862 12863 if (ach_error_index == -1) { 12864 LOG_ERROR(BSL_LS_BCM_OAM, 12865 (BSL_META_U(unit, 12866 "BHH Error:hw init. ACH error %s.\n"), 12867 bcm_errmsg(rv))); 12868 _BCM_OAM_UNLOCK(oc); 12869 return (BCM_E_FULL); 12870 } 12871 12872 /* Set CPU COS Queue mapping */ 12873 BCM_RX_REASON_CLEAR_ALL(reasons); 12874 BCM_RX_REASON_SET(reasons, bcmRxReasonMplsUnknownAch); /* Despite the name this reason */ 12875 /* code covers Unknown ACH */ 12876 12877 rv = bcm_esw_rx_cosq_mapping_set(unit, ach_error_index, 12878 reasons, reasons, 12879 0, 0, /* Any priority */ 12880 0, 0, /* Any packet type */ 12881 oc->cpu_cosq); 12882 if(BCM_FAILURE(rv)) { 12883 LOG_ERROR(BSL_LS_BCM_OAM, 12884 (BSL_META_U(unit, 12885 "BHH Error:hw init. cosq map set %s.\n"), 12886 bcm_errmsg(rv))); 12887 _BCM_OAM_UNLOCK(oc); 12888 return (rv); 12889 } 12890 oc->cpu_cosq_ach_error_index = ach_error_index; 12891 12892 if (oc->bhh_lm_dm_enable) { 12893 rv = _bcm_tr3_oam_bhh_fp_init(unit); 12894 } 12895 } 12896 12897 _BCM_OAM_UNLOCK(oc); 12898 return (rv); 12899 } 12900 12901 /* 12902 * Function: 12903 * _bcm_tr3_oam_bhh_find_l2_entry_1 12904 */ 12905 STATIC int 12906 _bcm_tr3_oam_bhh_find_l2_entry_1(int unit, uint32 key, int key_type, int ses_type, 12907 int *index, l2_entry_1_entry_t *l2_entry_1) 12908 { 12909 l2_entry_1_entry_t l2_key; 12910 12911 sal_memset(&l2_key, 0, sizeof(l2_key)); 12912 12913 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_key, KEY_TYPEf, key_type); 12914 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_key, 12915 BFD__SESSION_IDENTIFIER_TYPEf, ses_type); 12916 12917 if (ses_type) { 12918 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_key, BFD__LABELf, key); 12919 } else { 12920 soc_mem_field32_set(unit, L2_ENTRY_1m, &l2_key, 12921 BFD__YOUR_DISCRIMINATORf, key); 12922 } 12923 12924 return soc_mem_search(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, index, 12925 &l2_key, l2_entry_1, 0); 12926 12927 } 12928 12929 /* 12930 * Function: 12931 * _bcm_tr3_oam_bhh_fp_delete 12932 * Purpose: 12933 * Sets BHH FP for LM/DM in HW device. 12934 * Parameters: 12935 * unit - (IN) Unit number. 12936 * module_id - (IN) Module id. 12937 * port_id - (IN) Port. 12938 * is_local - (IN) Indicates if module id is local. 12939 * endpoint_config - (IN) Pointer to BHH endpoint structure. 12940 * Returns: 12941 * BCM_E_XXX 12942 * Notes: 12943 */ 12944 STATIC int 12945 _bcm_tr3_oam_bhh_fp_delete(int unit, _bcm_oam_hash_data_t *h_data_p) 12946 { 12947 int rv = BCM_E_NONE; 12948 _bcm_oam_control_t *oc; 12949 12950 /* Lock already taken by the calling routine. */ 12951 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 12952 12953 if(h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 12954 if (h_data_p->bhh_entry_pkt_rx) { 12955 (void)bcm_esw_field_entry_destroy(unit, h_data_p->bhh_entry_pkt_rx); 12956 oc->bhh_lmdm_entry_count--; 12957 } 12958 if (h_data_p->bhh_entry_pkt_tx) { 12959 (void)bcm_esw_field_entry_destroy(unit, h_data_p->bhh_entry_pkt_tx); 12960 oc->bhh_lmdm_entry_count--; 12961 } 12962 if (h_data_p->bhh_lm_entry_rx) { 12963 (void)bcm_esw_field_entry_destroy(unit, h_data_p->bhh_lm_entry_rx); 12964 oc->bhh_lmdm_entry_count--; 12965 } 12966 } 12967 12968 if(h_data_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) { 12969 if (h_data_p->bhh_dm_entry_rx) { 12970 (void)bcm_esw_field_entry_destroy(unit, h_data_p->bhh_dm_entry_rx); 12971 oc->bhh_lmdm_entry_count--; 12972 } 12973 } 12974 12975 if (h_data_p->lm_counter_index != _BCM_OAM_LM_COUNTER_IDX_INVALID) { 12976 /* Return ID back to free lm counter pool.*/ 12977 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->lm_counter_pool, 12978 h_data_p->lm_counter_index)); 12979 h_data_p->lm_counter_index = _BCM_OAM_LM_COUNTER_IDX_INVALID; 12980 SOC_IF_ERROR_RETURN(soc_profile_mem_delete(unit, 12981 &oc->ing_service_pri_map, 12982 (h_data_p->pri_map_index * BCM_OAM_INTPRI_MAX))); 12983 } 12984 12985 if(oc->bhh_lmdm_entry_count == 0) { 12986 (void)bcm_esw_field_group_destroy(unit, oc->bhh_lmdm_group); 12987 oc->bhh_lmdm_group = 0; 12988 } 12989 12990 h_data_p->bhh_entry_pkt_tx = 0; 12991 h_data_p->bhh_entry_pkt_rx = 0; 12992 h_data_p->bhh_lm_entry_rx = 0; 12993 h_data_p->bhh_dm_entry_rx = 0; 12994 12995 return rv; 12996 } 12997 12998 12999 /* 13000 * Function: 13001 * _bcm_tr3_oam_bhh_session_hw_delete 13002 * Purpose: 13003 * Delete BHH Session in HW device. 13004 * Parameters: 13005 * unit - (IN) Unit number. 13006 * h_data_p- (IN) Pointer to BHH endpoint structure. 13007 * Returns: 13008 * BCM_E_XXX 13009 * Notes: 13010 */ 13011 STATIC int 13012 _bcm_tr3_oam_bhh_session_hw_delete(int unit, _bcm_oam_hash_data_t *h_data_p) 13013 { 13014 int rv = BCM_E_NONE; 13015 int l2_index = 0; 13016 l2_entry_1_entry_t l2_entry_1; 13017 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) 13018 mpls_entry_1_entry_t mpls_entry; 13019 mpls_entry_1_entry_t mpls_key; 13020 int mpls_index = 0; 13021 #endif /* BCM_TRIUMPH_SUPPORT && BCM_MPLS_SUPPORT */ 13022 13023 13024 switch(h_data_p->type) { 13025 case bcmOAMEndpointTypeBHHMPLS: 13026 case bcmOAMEndpointTypeBHHMPLSVccv: 13027 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) 13028 SOC_IF_ERROR_RETURN(bcm_tr_mpls_lock (unit)); 13029 13030 sal_memset(&mpls_key, 0, sizeof(mpls_key)); 13031 soc_MPLS_ENTRYm_field32_set(unit, &mpls_key, 13032 MPLS__MPLS_LABELf, h_data_p->label); 13033 soc_MPLS_ENTRYm_field32_set(unit, &mpls_key, KEY_TYPEf, 16); 13034 13035 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, &mpls_index, 13036 &mpls_key, &mpls_entry, 0); 13037 13038 /* It can so happen that this function is called when the switch is 13039 re-initailizing, then MPLS ENTRY will not be found, as MPLS init 13040 happens before OAM init and it would have cleared the MPLS Entry, as 13041 such its not an error scenario. Hence dont return failure from here.*/ 13042 if (BCM_SUCCESS(rv)) { 13043 if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf) == 0x1)) 13044 { 13045 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, 13046 MPLS__BFD_ENABLEf, 0); 13047 rv = soc_mem_write(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, 13048 mpls_index, &mpls_entry); 13049 if (BCM_FAILURE(rv)) { 13050 LOG_ERROR(BSL_LS_BCM_OAM, 13051 (BSL_META_U(unit, 13052 "OAM Error: MPLS_ENTRY write failed - " 13053 "%s.\n"), bcm_errmsg(rv))); 13054 bcm_tr_mpls_unlock(unit); 13055 return (rv); 13056 } 13057 } 13058 } 13059 bcm_tr_mpls_unlock (unit); 13060 13061 if (BCM_SUCCESS(_bcm_tr3_oam_bhh_find_l2_entry_1(unit, 13062 h_data_p->label, 13063 12, 1, 13064 &l2_index, &l2_entry_1))) { 13065 soc_mem_delete_index(unit, L2_ENTRY_1m, MEM_BLOCK_ANY, l2_index); 13066 13067 } 13068 #endif /* BCM_TRIUMPH_SUPPORT && BCM_MPLS_SUPPORT */ 13069 break; 13070 13071 default: 13072 break; 13073 } 13074 13075 if((h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) || 13076 (h_data_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT)) 13077 { 13078 rv = _bcm_tr3_oam_bhh_fp_delete(unit, h_data_p); 13079 } 13080 13081 return (rv); 13082 } 13083 13084 /* 13085 * Function: 13086 * _bcm_tr3_oam_bhh_msg_send_receive 13087 * Purpose: 13088 * Sends given BHH control message to the uController. 13089 * Receives and verifies expected reply. 13090 * Performs DMA operation if required. 13091 * Parameters: 13092 * unit - (IN) Unit number. 13093 * s_subclass - (IN) BHH message subclass. 13094 * s_len - (IN) Value for 'len' field in message struct. 13095 * Length of buffer to flush if DMA send is required. 13096 * s_data - (IN) Value for 'data' field in message struct. 13097 * Ignored if message requires a DMA send/receive 13098 * operation. 13099 * r_subclass - (IN) Expected reply message subclass. 13100 * r_len - (OUT) Returns value in 'len' reply message field. 13101 * Returns: 13102 * BCM_E_XXX 13103 * Notes: 13104 * - The uc_msg 'len' and 'data' fields of mos_msg_data_t 13105 * can take any arbitrary data. 13106 * 13107 * BHH Long Control message: 13108 * - BHH control messages that require send/receive of information 13109 * that cannot fit in the uc_msg 'len' and 'data' fields need to 13110 * use DMA operations to exchange information (long control message). 13111 * 13112 * - BHH convention for long control messages for 13113 * 'mos_msg_data_t' fields: 13114 * 'len' size of the DMA buffer to send to uController 13115 * 'data' physical DMA memory address to send or receive 13116 * 13117 * DMA Operations: 13118 * - DMA read/write operation is performed when a long BHH control 13119 * message is involved. 13120 * 13121 * - Messages that require DMA operation (long control message) 13122 * is indicated by MOS_MSG_DMA_MSG(). 13123 * 13124 * - Callers must 'pack' and 'unpack' corresponding information 13125 * into/from DMA buffer indicated by BHH_INFO(unit)->dma_buffer. 13126 */ 13127 STATIC int 13128 _bcm_tr3_oam_bhh_msg_send_receive(int unit, uint8 s_subclass, 13129 uint16 s_len, uint32 s_data, 13130 uint8 r_subclass, uint16 *r_len, sal_usecs_t timeout) 13131 { 13132 int rv; 13133 _bcm_oam_control_t *oc; 13134 mos_msg_data_t send, reply; 13135 uint8 *dma_buffer; 13136 int dma_buffer_len; 13137 uint32 uc_rv; 13138 13139 /* Lock already taken by the calling routine. */ 13140 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 13141 13142 sal_memset(&send, 0, sizeof(send)); 13143 sal_memset(&reply, 0, sizeof(reply)); 13144 send.s.mclass = MOS_MSG_CLASS_BHH; 13145 send.s.subclass = s_subclass; 13146 send.s.len = bcm_htons(s_len); 13147 13148 /* 13149 * Set 'data' to DMA buffer address if a DMA operation is 13150 * required for send or receive. 13151 */ 13152 dma_buffer = oc->dma_buffer; 13153 dma_buffer_len = oc->dma_buffer_len; 13154 if (MOS_MSG_DMA_MSG(s_subclass) || 13155 MOS_MSG_DMA_MSG(r_subclass)) { 13156 send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer)); 13157 } else { 13158 send.s.data = bcm_htonl(s_data); 13159 } 13160 13161 /* Flush DMA memory */ 13162 if (MOS_MSG_DMA_MSG(s_subclass)) { 13163 soc_cm_sflush(unit, dma_buffer, s_len); 13164 } 13165 13166 /* Invalidate DMA memory to read */ 13167 if (MOS_MSG_DMA_MSG(r_subclass)) { 13168 soc_cm_sinval(unit, dma_buffer, dma_buffer_len); 13169 } 13170 13171 rv = soc_cmic_uc_msg_send_receive(unit, oc->uc_num, 13172 &send, &reply, 13173 timeout); 13174 13175 /* Check reply class, subclass */ 13176 if ((rv != SOC_E_NONE) || 13177 (reply.s.mclass != MOS_MSG_CLASS_BHH) || 13178 (reply.s.subclass != r_subclass)) { 13179 return (BCM_E_INTERNAL); 13180 } 13181 13182 /* Convert BHH uController error code to BCM */ 13183 uc_rv = bcm_ntohl(reply.s.data); 13184 switch(uc_rv) { 13185 case SHR_BHH_UC_E_NONE: 13186 rv = BCM_E_NONE; 13187 break; 13188 case SHR_BHH_UC_E_INTERNAL: 13189 rv = BCM_E_INTERNAL; 13190 break; 13191 case SHR_BHH_UC_E_MEMORY: 13192 rv = BCM_E_MEMORY; 13193 break; 13194 case SHR_BHH_UC_E_PARAM: 13195 rv = BCM_E_PARAM; 13196 break; 13197 case SHR_BHH_UC_E_RESOURCE: 13198 rv = BCM_E_RESOURCE; 13199 break; 13200 case SHR_BHH_UC_E_EXISTS: 13201 rv = BCM_E_EXISTS; 13202 break; 13203 case SHR_BHH_UC_E_NOT_FOUND: 13204 rv = BCM_E_NOT_FOUND; 13205 break; 13206 case SHR_BHH_UC_E_INIT: 13207 rv = BCM_E_INIT; 13208 break; 13209 default: 13210 rv = BCM_E_INTERNAL; 13211 break; 13212 } 13213 13214 *r_len = bcm_ntohs(reply.s.len); 13215 13216 return (rv); 13217 } 13218 13219 /* 13220 * Function: 13221 * _bcm_tr3_oam_bhh_callback_thread 13222 * Purpose: 13223 * Thread to listen for event messages from uController. 13224 * Parameters: 13225 * param - Pointer to BFD info structure. 13226 * Returns: 13227 * None 13228 */ 13229 STATIC void 13230 _bcm_tr3_oam_bhh_callback_thread(void *param) 13231 { 13232 int rv; 13233 _bcm_oam_control_t *oc = (_bcm_oam_control_t *)param; 13234 bcm_oam_event_types_t events; 13235 bcm_oam_event_type_t event_type; 13236 bhh_msg_event_t event_msg; 13237 int sess_id; 13238 uint32 event_mask, flags = 0; 13239 _bcm_oam_event_handler_t *event_handler_p; 13240 _bcm_oam_hash_data_t *h_data_p; 13241 int ep_id = 0; 13242 char thread_name[SAL_THREAD_NAME_MAX_LEN]; 13243 13244 thread_name[0] = 0x0; 13245 sal_thread_name(oc->event_thread_id, thread_name, sizeof (thread_name)); 13246 LOG_VERBOSE(BSL_LS_SOC_COMMON, 13247 (BSL_META_U(oc->unit, 13248 "BHH callback thread starting\n"))); 13249 13250 while (1) { 13251 /* Wait on notifications from uController */ 13252 rv = soc_cmic_uc_msg_receive(oc->unit, oc->uc_num, 13253 MOS_MSG_CLASS_BHH_EVENT, &event_msg, 13254 sal_sem_FOREVER); 13255 13256 if (BCM_FAILURE(rv)) { 13257 break; /* Thread exit */ 13258 } 13259 13260 event_handler_p = oc->event_handler_list_p; 13261 /* Get data from event message */ 13262 sess_id = (int)bcm_ntohs(event_msg.s.len); 13263 ep_id = BCM_OAM_BHH_GET_SDK_EP(sess_id); 13264 13265 if (sess_id < 0 || 13266 sess_id >= oc->ep_count) { 13267 LOG_WARN(BSL_LS_BCM_OAM, 13268 (BSL_META_U(oc->unit, 13269 "Invalid sess_id:%d\n"), sess_id)); 13270 continue; 13271 } 13272 /* Check endpoint status. */ 13273 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 13274 if ((BCM_E_EXISTS != rv)) { 13275 /* Endpoint not in use. */ 13276 LOG_ERROR(BSL_LS_BCM_OAM, 13277 (BSL_META_U(oc->unit, 13278 "OAM Error: Endpoint EP=%d %s.\n"), 13279 ep_id, bcm_errmsg(rv))); 13280 } 13281 h_data_p = &oc->oam_hash_data[ep_id]; 13282 event_mask = bcm_ntohl(event_msg.s.data); 13283 13284 13285 /* Set events */ 13286 sal_memset(&events, 0, sizeof(events)); 13287 13288 if (event_mask & BHH_BTE_EVENT_LB_TIMEOUT) { 13289 LOG_DEBUG(BSL_LS_BCM_OAM, 13290 (BSL_META_U(oc->unit, 13291 "****** OAM BHH LB Timeout ******\n"))); 13292 13293 if (oc->event_handler_cnt[bcmOAMEventBHHLBTimeout] > 0) 13294 SHR_BITSET(events.w, bcmOAMEventBHHLBTimeout); 13295 } 13296 if (event_mask & BHH_BTE_EVENT_LB_DISCOVERY_UPDATE) { 13297 LOG_DEBUG(BSL_LS_BCM_OAM, 13298 (BSL_META_U(oc->unit, 13299 "****** OAM BHH LB Discovery Update ******\n"))); 13300 if (oc->event_handler_cnt[bcmOAMEventBHHLBDiscoveryUpdate] > 0) 13301 SHR_BITSET(events.w, bcmOAMEventBHHLBDiscoveryUpdate); 13302 } 13303 if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT) { 13304 LOG_DEBUG(BSL_LS_BCM_OAM, 13305 (BSL_META_U(oc->unit, 13306 "****** OAM BHH CCM Timeout ******\n"))); 13307 if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeout] > 0) 13308 SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeout); 13309 } 13310 if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR) { 13311 LOG_DEBUG(BSL_LS_BCM_OAM, 13312 (BSL_META_U(oc->unit, 13313 "****** OAM BHH CCM Timeout Clear ******\n"))); 13314 if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeoutClear] > 0) 13315 SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeoutClear); 13316 } 13317 if (event_mask & BHH_BTE_EVENT_STATE) { 13318 LOG_DEBUG(BSL_LS_BCM_OAM, 13319 (BSL_META_U(oc->unit, 13320 "****** OAM BHH State ******\n"))); 13321 if (oc->event_handler_cnt[bcmOAMEventBHHCCMState] > 0) 13322 SHR_BITSET(events.w, bcmOAMEventBHHCCMState); 13323 } 13324 13325 if (event_mask & BHH_BTE_EVENT_CCM_RDI) { 13326 LOG_DEBUG(BSL_LS_BCM_OAM, 13327 (BSL_META_U(oc->unit, 13328 "****** OAM BHH CCM RDI ******\n"))); 13329 if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdi] > 0) 13330 SHR_BITSET(events.w, bcmOAMEventBHHCCMRdi); 13331 } 13332 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL) { 13333 LOG_DEBUG(BSL_LS_BCM_OAM, 13334 (BSL_META_U(oc->unit, 13335 "****** OAM BHH CCM Unknown MEG Level ******\n"))); 13336 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevel] > 0) 13337 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevel); 13338 } 13339 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID) { 13340 LOG_DEBUG(BSL_LS_BCM_OAM, 13341 (BSL_META_U(oc->unit, 13342 "****** OAM BHH CCM Unknown MEG ID ******\n"))); 13343 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegId] > 0) 13344 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegId); 13345 } 13346 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID) { 13347 LOG_DEBUG(BSL_LS_BCM_OAM, 13348 (BSL_META_U(oc->unit, 13349 "****** OAM BHH CCM Unknown MEP ID ******\n"))); 13350 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepId] > 0) 13351 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepId); 13352 } 13353 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD) { 13354 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriod] > 0) 13355 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriod); 13356 } 13357 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY) { 13358 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriority] > 0) 13359 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriority); 13360 } 13361 if (event_mask & BHH_BTE_EVENT_CCM_RDI_CLEAR) { 13362 if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdiClear] > 0) 13363 SHR_BITSET(events.w, bcmOAMEventBHHCCMRdiClear); 13364 } 13365 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR) { 13366 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevelClear] > 0) 13367 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevelClear); 13368 } 13369 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR) { 13370 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegIdClear] > 0) 13371 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegIdClear); 13372 } 13373 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR) { 13374 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepIdClear] > 0) 13375 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepIdClear); 13376 } 13377 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR) { 13378 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriodClear] > 0) 13379 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriodClear); 13380 } 13381 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR) { 13382 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriorityClear] > 0) 13383 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriorityClear); 13384 } 13385 if (event_mask & BHH_BTE_EVENT_CSF_LOS) { 13386 if (oc->event_handler_cnt[bcmOAMEventCsfLos] > 0) { 13387 SHR_BITSET(events.w, bcmOAMEventCsfLos); 13388 } 13389 } 13390 if (event_mask & BHH_BTE_EVENT_CSF_FDI) { 13391 if (oc->event_handler_cnt[bcmOAMEventCsfFdi] > 0) { 13392 SHR_BITSET(events.w, bcmOAMEventCsfFdi); 13393 } 13394 } 13395 if (event_mask & BHH_BTE_EVENT_CSF_RDI) { 13396 if (oc->event_handler_cnt[bcmOAMEventCsfRdi] > 0) { 13397 SHR_BITSET(events.w, bcmOAMEventCsfRdi); 13398 } 13399 } 13400 if (event_mask & BHH_BTE_EVENT_CSF_DCI) { 13401 if (oc->event_handler_cnt[bcmOAMEventCsfDci] > 0) { 13402 SHR_BITSET(events.w, bcmOAMEventCsfDci); 13403 } 13404 } 13405 13406 /* Loop over registered callbacks, 13407 * If any match the events field, then invoke 13408 */ 13409 for (event_handler_p = oc->event_handler_list_p; 13410 event_handler_p != NULL; 13411 event_handler_p = event_handler_p->next_p) { 13412 for (event_type = bcmOAMEventBHHLBTimeout; event_type < bcmOAMEventCount; ++event_type) { 13413 if (SHR_BITGET(events.w, event_type)) { 13414 if (SHR_BITGET(event_handler_p->event_types.w, 13415 event_type)) { 13416 event_handler_p->cb(oc->unit, 13417 flags, 13418 event_type, 13419 h_data_p->group_index, /* Group index */ 13420 ep_id, /* Endpoint index */ 13421 event_handler_p->user_data); 13422 } 13423 } 13424 } 13425 } 13426 } 13427 13428 oc->event_thread_id = NULL; 13429 13430 LOG_VERBOSE(BSL_LS_SOC_COMMON, 13431 (BSL_META_U(oc->unit, 13432 "BHH callback thread stopped\n"))); 13433 sal_thread_exit(0); 13434 } 13435 13436 /* BHH Event Handler */ 13437 typedef struct _event_handler_s { 13438 struct _event_handler_s *next; 13439 bcm_oam_event_types_t event_types; 13440 bcm_oam_event_cb cb; 13441 void *user_data; 13442 } _event_handler_t; 13443 13444 /* 13445 * Function: 13446 * _bcm_tr3_oam_bhh_event_mask_set 13447 * Purpose: 13448 * Set the BHH Events mask. 13449 * Events are set per BHH module. 13450 * Parameters: 13451 * unit - (IN) Unit number. 13452 * Returns: 13453 * BCM_E_NONE Operation completed successfully 13454 * BCM_E_XXX Operation failed 13455 * Notes: 13456 */ 13457 STATIC int 13458 _bcm_tr3_oam_bhh_event_mask_set(int unit) 13459 { 13460 _bcm_oam_control_t *oc; 13461 _bcm_oam_event_handler_t *event_handler_p; 13462 uint32 event_mask = 0; 13463 uint16 reply_len; 13464 int rv = BCM_E_NONE; 13465 13466 /* Lock already taken by the calling routine. */ 13467 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 13468 13469 /* Get event mask from all callbacks */ 13470 for (event_handler_p = oc->event_handler_list_p; 13471 event_handler_p != NULL; 13472 event_handler_p = event_handler_p->next_p) { 13473 13474 if (SHR_BITGET(event_handler_p->event_types.w, 13475 bcmOAMEventBHHLBTimeout)) { 13476 event_mask |= BHH_BTE_EVENT_LB_TIMEOUT; 13477 } 13478 if (SHR_BITGET(event_handler_p->event_types.w, 13479 bcmOAMEventBHHLBDiscoveryUpdate)) { 13480 event_mask |= BHH_BTE_EVENT_LB_DISCOVERY_UPDATE; 13481 } 13482 if (SHR_BITGET(event_handler_p->event_types.w, 13483 bcmOAMEventBHHCCMTimeout)) { 13484 event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT; 13485 } 13486 if (SHR_BITGET(event_handler_p->event_types.w, 13487 bcmOAMEventBHHCCMTimeoutClear)) { 13488 event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR; 13489 } 13490 if (SHR_BITGET(event_handler_p->event_types.w, 13491 bcmOAMEventBHHCCMState)) { 13492 event_mask |= BHH_BTE_EVENT_STATE; 13493 } 13494 if (SHR_BITGET(event_handler_p->event_types.w, 13495 bcmOAMEventBHHCCMRdi)) { 13496 event_mask |= BHH_BTE_EVENT_CCM_RDI; 13497 } 13498 if (SHR_BITGET(event_handler_p->event_types.w, 13499 bcmOAMEventBHHCCMUnknownMegLevel)) { 13500 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL; 13501 } 13502 if (SHR_BITGET(event_handler_p->event_types.w, 13503 bcmOAMEventBHHCCMUnknownMegId)) { 13504 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID; 13505 } 13506 if (SHR_BITGET(event_handler_p->event_types.w, 13507 bcmOAMEventBHHCCMUnknownMepId)) { 13508 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID; 13509 } 13510 if (SHR_BITGET(event_handler_p->event_types.w, 13511 bcmOAMEventBHHCCMUnknownPeriod)) { 13512 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD; 13513 } 13514 if (SHR_BITGET(event_handler_p->event_types.w, 13515 bcmOAMEventBHHCCMUnknownPriority)) { 13516 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY; 13517 } 13518 if (SHR_BITGET(event_handler_p->event_types.w, 13519 bcmOAMEventBHHCCMRdiClear)) { 13520 event_mask |= BHH_BTE_EVENT_CCM_RDI_CLEAR; 13521 } 13522 if (SHR_BITGET(event_handler_p->event_types.w, 13523 bcmOAMEventBHHCCMUnknownMegLevelClear)) { 13524 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR; 13525 } 13526 if (SHR_BITGET(event_handler_p->event_types.w, 13527 bcmOAMEventBHHCCMUnknownMegIdClear)) { 13528 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR; 13529 } 13530 if (SHR_BITGET(event_handler_p->event_types.w, 13531 bcmOAMEventBHHCCMUnknownMepIdClear)) { 13532 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR; 13533 } 13534 if (SHR_BITGET(event_handler_p->event_types.w, 13535 bcmOAMEventBHHCCMUnknownPeriodClear)) { 13536 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR; 13537 } 13538 if (SHR_BITGET(event_handler_p->event_types.w, 13539 bcmOAMEventBHHCCMUnknownPriorityClear)) { 13540 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR; 13541 } 13542 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfLos)) { 13543 event_mask |= BHH_BTE_EVENT_CSF_LOS; 13544 } 13545 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfFdi)) { 13546 event_mask |= BHH_BTE_EVENT_CSF_FDI; 13547 } 13548 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfRdi)) { 13549 event_mask |= BHH_BTE_EVENT_CSF_RDI; 13550 } 13551 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfDci)) { 13552 event_mask |= BHH_BTE_EVENT_CSF_DCI; 13553 } 13554 } 13555 /* Update BHH event mask in uKernel */ 13556 if (event_mask != oc->event_mask) { 13557 /* Send BHH Event Mask message to uC */ 13558 rv = _bcm_tr3_oam_bhh_msg_send_receive 13559 (unit, 13560 MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET, 13561 0, event_mask, 13562 MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET_REPLY, 13563 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 13564 13565 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 13566 rv = BCM_E_INTERNAL; 13567 } 13568 } 13569 13570 oc->event_mask = event_mask; 13571 13572 return (rv); 13573 } 13574 13575 /* 13576 * Function: 13577 * bcm_tr3_oam_loopback_add 13578 * Purpose: 13579 * 13580 * Parameters: 13581 * unit - Device unit number 13582 * Returns: 13583 * None 13584 */ 13585 int 13586 bcm_tr3_oam_loopback_add(int unit, bcm_oam_loopback_t *loopback_p) 13587 { 13588 _bcm_oam_control_t *oc; 13589 _bcm_oam_hash_data_t *h_data_p; 13590 int rv = BCM_E_NONE; 13591 bhh_sdk_msg_ctrl_loopback_add_t msg; 13592 uint8 *buffer, *buffer_ptr; 13593 uint16 buffer_len, reply_len; 13594 uint32 flags = 0; 13595 int sess_id = 0; 13596 13597 /* Get OAM Control Structure. */ 13598 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 13599 _BCM_OAM_LOCK(oc); 13600 13601 if (oc->ukernel_not_ready) { 13602 _BCM_OAM_UNLOCK(oc); 13603 return BCM_E_INIT; 13604 } 13605 13606 13607 BCM_OAM_BHH_VALIDATE_EP(loopback_p->id); 13608 13609 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id); 13610 13611 /* Check endpoint status. */ 13612 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 13613 if ((BCM_E_EXISTS != rv)) { 13614 /* Endpoint not in use. */ 13615 LOG_ERROR(BSL_LS_BCM_OAM, 13616 (BSL_META_U(unit, 13617 "OAM Error: Endpoint EP=%d %s.\n"), 13618 loopback_p->id, bcm_errmsg(rv))); 13619 _BCM_OAM_UNLOCK(oc); 13620 return (rv); 13621 } 13622 13623 h_data_p = &oc->oam_hash_data[loopback_p->id]; 13624 13625 /* 13626 * Only BHH is supported 13627 */ 13628 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS || 13629 h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 13630 13631 /* 13632 * Convert host space flags to uKernel space flags 13633 */ 13634 13635 if (loopback_p->flags & BCM_OAM_LOOPBACK_TX_ENABLE) { 13636 flags |= BCM_BHH_TX_ENABLE; 13637 } 13638 13639 if (loopback_p->flags & BCM_OAM_BHH_INC_REQUESTING_MEP_TLV) { 13640 flags |= BCM_BHH_INC_REQUESTING_MEP_TLV; 13641 } 13642 13643 if (loopback_p->flags & BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) { 13644 flags |= BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV; 13645 } else if (loopback_p->flags & BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) { 13646 flags |= BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV; 13647 } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MEP_TLV) { 13648 flags |= BCM_BHH_LBM_ICC_MEP_TLV; 13649 } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MIP_TLV) { 13650 flags |= BCM_BHH_LBM_ICC_MIP_TLV; 13651 } else { 13652 flags |= BCM_BHH_LBM_ICC_MEP_TLV; /* Default */ 13653 } 13654 13655 if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MEP_TLV) { 13656 flags |= BCM_BHH_LBR_ICC_MEP_TLV; 13657 } else if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MIP_TLV) { 13658 flags |= BCM_BHH_LBR_ICC_MIP_TLV; 13659 } 13660 13661 sal_memset(&msg, 0, sizeof(msg)); 13662 msg.flags = flags; 13663 msg.sess_id = sess_id; 13664 msg.int_pri = loopback_p->int_pri; 13665 msg.pkt_pri = loopback_p->pkt_pri; 13666 13667 /* 13668 * Set period 13669 */ 13670 msg.period = _tr3_ccm_intervals[ 13671 _bcm_tr3_oam_ccm_msecs_to_hw_encode( 13672 loopback_p->period)]; 13673 13674 /* 13675 * Check TTL 13676 */ 13677 if (loopback_p->ttl == 0 || loopback_p->ttl > 255) { 13678 _BCM_OAM_UNLOCK(oc); 13679 return BCM_E_PARAM; 13680 } 13681 13682 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv && 13683 h_data_p->vccv_type == bcmOamBhhVccvTtl) { 13684 13685 msg.ttl = 1; /* Only TTL 1 is valid */ 13686 } else { 13687 msg.ttl = loopback_p->ttl; 13688 } 13689 13690 13691 13692 /* Pack control message data into DMA buffer */ 13693 buffer = oc->dma_buffer; 13694 buffer_ptr = bhh_sdk_msg_ctrl_loopback_add_pack(buffer, &msg); 13695 buffer_len = buffer_ptr - buffer; 13696 13697 /* Send BHH Session Update message to uC */ 13698 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 13699 MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD, 13700 buffer_len, 0, 13701 MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD_REPLY, 13702 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 13703 13704 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 13705 rv = BCM_E_INTERNAL; 13706 } 13707 } 13708 else { 13709 rv = BCM_E_UNAVAIL; 13710 } 13711 13712 _BCM_OAM_UNLOCK(oc); 13713 return (rv); 13714 } 13715 13716 /* 13717 * Function: 13718 * bcm_tr3_oam_loopback_get 13719 * Purpose: 13720 * 13721 * Parameters: 13722 * unit - Device unit number 13723 * Returns: 13724 * None 13725 */ 13726 int 13727 bcm_tr3_oam_loopback_get(int unit, bcm_oam_loopback_t *loopback_p) 13728 { 13729 _bcm_oam_control_t *oc; 13730 int rv = BCM_E_NONE; 13731 bhh_sdk_msg_ctrl_loopback_get_t msg; 13732 _bcm_oam_hash_data_t *h_data_p; 13733 uint8 *buffer, *buffer_ptr; 13734 uint16 buffer_len, reply_len; 13735 int sess_id = 0; 13736 13737 /* Get OAM Control Structure. */ 13738 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 13739 _BCM_OAM_LOCK(oc); 13740 13741 if (oc->ukernel_not_ready) { 13742 _BCM_OAM_UNLOCK(oc); 13743 return BCM_E_INIT; 13744 } 13745 13746 BCM_OAM_BHH_VALIDATE_EP(loopback_p->id); 13747 13748 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id); 13749 13750 /* Check endpoint status. */ 13751 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 13752 if ((BCM_E_EXISTS != rv)) { 13753 /* Endpoint not in use. */ 13754 LOG_ERROR(BSL_LS_BCM_OAM, 13755 (BSL_META_U(unit, 13756 "OAM Error: Endpoint EP=%d %s.\n"), 13757 loopback_p->id, bcm_errmsg(rv))); 13758 _BCM_OAM_UNLOCK(oc); 13759 return (rv); 13760 } 13761 13762 h_data_p = &oc->oam_hash_data[loopback_p->id]; 13763 13764 /* 13765 * Only BHH is supported 13766 */ 13767 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS || 13768 h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 13769 13770 sal_memset(&msg, 0, sizeof(msg)); 13771 /* Send BHH Session Update message to uC */ 13772 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 13773 MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET, 13774 sess_id, 0, 13775 MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET_REPLY, 13776 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 13777 if(BCM_FAILURE(rv)) { 13778 LOG_ERROR(BSL_LS_BCM_OAM, 13779 (BSL_META_U(unit, 13780 "OAM Error: Endpoint EP=%d %s.\n"), 13781 loopback_p->id, bcm_errmsg(rv))); 13782 _BCM_OAM_UNLOCK(oc); 13783 return (rv); 13784 } 13785 13786 /* Pack control message data into DMA buffer */ 13787 buffer = oc->dma_buffer; 13788 buffer_ptr = bhh_sdk_msg_ctrl_loopback_get_unpack(buffer, &msg); 13789 buffer_len = buffer_ptr - buffer; 13790 13791 13792 if (reply_len != buffer_len) { 13793 rv = BCM_E_INTERNAL; 13794 } else { 13795 /* 13796 * Convert kernel space flags to host space flags 13797 */ 13798 if (msg.flags & BCM_BHH_INC_REQUESTING_MEP_TLV) { 13799 loopback_p->flags |= BCM_OAM_BHH_INC_REQUESTING_MEP_TLV; 13800 } 13801 13802 if (msg.flags & BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) { 13803 loopback_p->flags |= BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV; 13804 } else if (msg.flags & BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) { 13805 loopback_p->flags |= BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV; 13806 } else if (msg.flags & BCM_BHH_LBM_ICC_MEP_TLV) { 13807 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MEP_TLV; 13808 } else if (msg.flags & BCM_BHH_LBM_ICC_MIP_TLV) { 13809 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MIP_TLV; 13810 } 13811 13812 if (msg.flags & BCM_BHH_LBR_ICC_MEP_TLV) { 13813 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MEP_TLV; 13814 } else if (msg.flags & BCM_BHH_LBR_ICC_MIP_TLV) { 13815 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MIP_TLV; 13816 } 13817 13818 if (msg.flags & BCM_BHH_TX_ENABLE) { 13819 loopback_p->flags |= BCM_OAM_LOOPBACK_TX_ENABLE; 13820 } 13821 13822 loopback_p->period = msg.period; 13823 loopback_p->ttl = msg.ttl; 13824 loopback_p->discovered_me.flags = msg.discovery_flags; 13825 loopback_p->discovered_me.name = msg.discovery_id; 13826 loopback_p->discovered_me.ttl = msg.discovery_ttl; 13827 loopback_p->rx_count = msg.rx_count; 13828 loopback_p->tx_count = msg.tx_count; 13829 loopback_p->drop_count = msg.drop_count; 13830 loopback_p->unexpected_response = msg.unexpected_response; 13831 loopback_p->out_of_sequence = msg.out_of_sequence; 13832 loopback_p->local_mipid_missmatch = msg.local_mipid_missmatch; 13833 loopback_p->remote_mipid_missmatch = msg.remote_mipid_missmatch; 13834 loopback_p->invalid_target_mep_tlv = msg.invalid_target_mep_tlv; 13835 loopback_p->invalid_mep_tlv_subtype = msg.invalid_mep_tlv_subtype; 13836 loopback_p->invalid_tlv_offset = msg.invalid_tlv_offset; 13837 loopback_p->int_pri = msg.int_pri; 13838 loopback_p->pkt_pri = msg.pkt_pri; 13839 13840 rv = BCM_E_NONE; 13841 } 13842 } 13843 else { 13844 rv = BCM_E_UNAVAIL; 13845 } 13846 13847 _BCM_OAM_UNLOCK(oc); 13848 13849 return (rv); 13850 } 13851 13852 /* 13853 * Function: 13854 * bcm_tr3_oam_loopback_delete 13855 * Purpose: 13856 * 13857 * Parameters: 13858 * unit - Device unit number 13859 * Returns: 13860 * None 13861 */ 13862 int 13863 bcm_tr3_oam_loopback_delete(int unit, bcm_oam_loopback_t *loopback_p) 13864 { 13865 _bcm_oam_control_t *oc; 13866 int rv = BCM_E_NONE; 13867 shr_bhh_msg_ctrl_loopback_delete_t msg; 13868 uint8 *buffer, *buffer_ptr; 13869 uint16 buffer_len, reply_len; 13870 int sess_id = 0; 13871 _bcm_oam_hash_data_t *h_data_p; 13872 13873 /* Get OAM Control Structure. */ 13874 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 13875 _BCM_OAM_LOCK(oc); 13876 13877 if (oc->ukernel_not_ready) { 13878 _BCM_OAM_UNLOCK(oc); 13879 return BCM_E_INIT; 13880 } 13881 13882 13883 BCM_OAM_BHH_VALIDATE_EP(loopback_p->id); 13884 13885 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id); 13886 13887 /* Check endpoint status. */ 13888 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 13889 if ((BCM_E_EXISTS != rv)) { 13890 /* Endpoint not in use. */ 13891 LOG_ERROR(BSL_LS_BCM_OAM, 13892 (BSL_META_U(unit, 13893 "OAM Error: Endpoint EP=%d %s.\n"), 13894 loopback_p->id, bcm_errmsg(rv))); 13895 _BCM_OAM_UNLOCK(oc); 13896 return (rv); 13897 } 13898 13899 h_data_p = &oc->oam_hash_data[loopback_p->id]; 13900 13901 /* 13902 * Only BHH is supported 13903 */ 13904 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS || 13905 h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 13906 13907 msg.sess_id = sess_id; 13908 13909 /* Pack control message data into DMA buffer */ 13910 buffer = oc->dma_buffer; 13911 buffer_ptr = shr_bhh_msg_ctrl_loopback_delete_pack(buffer, &msg); 13912 buffer_len = buffer_ptr - buffer; 13913 13914 /* Send BHH Session Update message to uC */ 13915 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 13916 MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE, 13917 buffer_len, 0, 13918 MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE_REPLY, 13919 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 13920 13921 if(BCM_SUCCESS(rv) && (reply_len != 0)) 13922 rv = BCM_E_INTERNAL; 13923 } 13924 else { 13925 _BCM_OAM_UNLOCK(oc); 13926 return BCM_E_UNAVAIL; 13927 } 13928 13929 _BCM_OAM_UNLOCK(oc); 13930 13931 return (rv); 13932 } 13933 13934 /* 13935 * Function: 13936 * bcm_tr3_oam_loss_add 13937 * Purpose: 13938 * Loss Measurement add 13939 * Parameters: 13940 * unit - Device unit number 13941 * Returns: 13942 * None 13943 */ 13944 int 13945 bcm_tr3_oam_loss_add(int unit, bcm_oam_loss_t *loss_p) 13946 { 13947 _bcm_oam_control_t *oc; 13948 _bcm_oam_hash_data_t *h_data_p; 13949 int rv = BCM_E_NONE; 13950 bhh_sdk_msg_ctrl_loss_add_t msg; 13951 uint8 *buffer, *buffer_ptr; 13952 uint16 buffer_len, reply_len; 13953 uint32 flags = 0; 13954 int sess_id = 0; 13955 13956 /* Get OAM Control Structure. */ 13957 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 13958 _BCM_OAM_LOCK(oc); 13959 13960 if (oc->ukernel_not_ready) { 13961 _BCM_OAM_UNLOCK(oc); 13962 return BCM_E_INIT; 13963 } 13964 13965 13966 if (!oc->bhh_lm_dm_enable) { 13967 LOG_ERROR(BSL_LS_BCM_OAM, 13968 (BSL_META_U(unit, 13969 "OAM Error: LM/DM not enabled\n"))); 13970 _BCM_OAM_UNLOCK(oc); 13971 return BCM_E_DISABLED; 13972 } 13973 13974 BCM_OAM_BHH_VALIDATE_EP(loss_p->id); 13975 13976 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id); 13977 13978 /* Check endpoint status. */ 13979 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 13980 if ((BCM_E_EXISTS != rv)) { 13981 /* Endpoint not in use. */ 13982 LOG_ERROR(BSL_LS_BCM_OAM, 13983 (BSL_META_U(unit, 13984 "OAM Error: Endpoint EP=%d %s.\n"), 13985 loss_p->id, bcm_errmsg(rv))); 13986 _BCM_OAM_UNLOCK(oc); 13987 return (rv); 13988 } 13989 13990 h_data_p = &oc->oam_hash_data[loss_p->id]; 13991 13992 /* 13993 * Only BHH is supported 13994 */ 13995 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS || 13996 h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 13997 13998 /* 13999 * Convert host space flags to uKernel space flags 14000 */ 14001 if (loss_p->flags & BCM_OAM_LOSS_SINGLE_ENDED) 14002 flags |= BCM_BHH_LM_SINGLE_ENDED; 14003 14004 if (loss_p->flags & BCM_OAM_LOSS_TX_ENABLE) 14005 flags |= BCM_BHH_LM_TX_ENABLE; 14006 14007 sal_memset(&msg, 0, sizeof(msg)); 14008 msg.flags = flags; 14009 msg.sess_id = sess_id; 14010 14011 /* 14012 * Set period 14013 */ 14014 msg.period = _tr3_ccm_intervals[_bcm_tr3_oam_ccm_msecs_to_hw_encode(loss_p->period)]; 14015 msg.int_pri = loss_p->int_pri; 14016 msg.pkt_pri = loss_p->pkt_pri; 14017 14018 /* Pack control message data into DMA buffer */ 14019 buffer = oc->dma_buffer; 14020 buffer_ptr = bhh_sdk_msg_ctrl_loss_add_pack(buffer, &msg); 14021 buffer_len = buffer_ptr - buffer; 14022 14023 /* Send BHH Session Update message to uC */ 14024 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 14025 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD, 14026 buffer_len, 0, 14027 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD_REPLY, 14028 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 14029 14030 if(BCM_SUCCESS(rv) && (reply_len != 0)) 14031 rv = BCM_E_INTERNAL; 14032 } 14033 else { 14034 _BCM_OAM_UNLOCK(oc); 14035 return BCM_E_UNAVAIL; 14036 } 14037 14038 _BCM_OAM_UNLOCK(oc); 14039 return (rv); 14040 } 14041 14042 int 14043 bcm_oam_bhh_convert_ep_to_time_spec(bcm_time_spec_t* bts, int sec, int ns) 14044 { 14045 int rv = BCM_E_NONE; 14046 14047 if (bts != NULL) { 14048 /* if both seconds and nanoseconds are negative or both positive, 14049 * then the ucode's subtraction is ok. 14050 * if seconds and nanoseconds have different signs, then "borrow" 14051 * 1000000000 nanoseconds from seconds. 14052 */ 14053 if ((sec < 0) && (ns > 0)) { 14054 ns -= 1000000000; 14055 sec += 1; 14056 } else if ((sec > 0) && (ns < 0)) { 14057 ns += 1000000000; 14058 sec -= 1; 14059 } 14060 14061 if (ns < 0) { 14062 /* if still negative, then something else is wrong. 14063 * the nanoseconds field is the difference between two 14064 * (non-negative) time-stamps. 14065 */ 14066 rv = BCM_E_INTERNAL; 14067 } 14068 14069 /* if seconds is negative then set the bts is-negative flag, 14070 * and use the absolute value of seconds & nanoseconds. 14071 */ 14072 bts->isnegative = (sec < 0 ? 1 : 0); 14073 bts->seconds = BCM_OAM_BHH_ABS(sec); 14074 bts->nanoseconds = BCM_OAM_BHH_ABS(ns); 14075 } else { 14076 rv = BCM_E_INTERNAL; 14077 } 14078 14079 return rv; 14080 } 14081 14082 #if 0 14083 /* d (difference) = m (minuend) - s (subtrahend) */ 14084 int 14085 bcm_oam_bhh_time_spec_subtract(bcm_time_spec_t* d, bcm_time_spec_t* m, bcm_time_spec_t* s) 14086 { 14087 int rv = BCM_E_NONE; 14088 int32 d_ns = 0; 14089 int32 d_s = 0; 14090 14091 if ((d != NULL) && (m != NULL) && (s != NULL)) { 14092 /* subtract the nanoseconds first, then borrow is necessary. */ 14093 d_ns = m->nanoseconds - s->nanoseconds; 14094 if (d_ns < 0) { 14095 m->seconds = m->seconds - 1; 14096 d_ns = 1000000000 + d_ns; 14097 } 14098 if (d_ns < 0) { 14099 /* if still negative, then error */ 14100 rv = BCM_E_INTERNAL; 14101 d_ns = abs(d_ns); 14102 } 14103 d->nanoseconds = d_ns; 14104 14105 /* subtract the seconds next, check for negative. */ 14106 d_s = m->seconds - s->seconds; 14107 if (d_s < 0) { 14108 d->isnegative = TRUE; 14109 d_s = abs(d_s); 14110 } else { 14111 d->isnegative = FALSE; 14112 } 14113 d->seconds = d_s; 14114 14115 } else { 14116 rv = BCM_E_INTERNAL; 14117 } 14118 14119 return rv; 14120 } 14121 #endif 14122 14123 /* 14124 * Function: 14125 * bcm_tr3_oam_loss_get 14126 * Purpose: 14127 * Loss Measurement get 14128 * Parameters: 14129 * unit - Device unit number 14130 * Returns: 14131 * None 14132 */ 14133 int 14134 bcm_tr3_oam_loss_get(int unit, bcm_oam_loss_t *loss_p) 14135 { 14136 _bcm_oam_control_t *oc; 14137 int rv = BCM_E_NONE; 14138 bhh_sdk_msg_ctrl_loss_get_t msg; 14139 _bcm_oam_hash_data_t *h_data_p; 14140 uint8 *buffer, *buffer_ptr; 14141 uint16 buffer_len, reply_len; 14142 int sess_id = 0; 14143 14144 /* Get OAM Control Structure. */ 14145 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 14146 _BCM_OAM_LOCK(oc); 14147 14148 if (oc->ukernel_not_ready) { 14149 _BCM_OAM_UNLOCK(oc); 14150 return BCM_E_INIT; 14151 } 14152 14153 14154 BCM_OAM_BHH_VALIDATE_EP(loss_p->id); 14155 14156 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id); 14157 14158 /* Check endpoint status. */ 14159 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 14160 if ((BCM_E_EXISTS != rv)) { 14161 /* Endpoint not in use. */ 14162 LOG_ERROR(BSL_LS_BCM_OAM, 14163 (BSL_META_U(unit, 14164 "OAM Error: Endpoint EP=%d %s.\n"), 14165 loss_p->id, bcm_errmsg(rv))); 14166 _BCM_OAM_UNLOCK(oc); 14167 return (rv); 14168 } 14169 14170 h_data_p = &oc->oam_hash_data[loss_p->id]; 14171 14172 /* 14173 * Only BHH is supported 14174 */ 14175 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS || 14176 h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 14177 14178 sal_memset(&msg, 0, sizeof(msg)); 14179 /* Send BHH Session Update message to uC */ 14180 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 14181 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET, 14182 sess_id, 0, 14183 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET_REPLY, 14184 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 14185 if(BCM_FAILURE(rv)) { 14186 LOG_ERROR(BSL_LS_BCM_OAM, 14187 (BSL_META_U(unit, 14188 "OAM Error: Endpoint EP=%d %s.\n"), 14189 loss_p->id, bcm_errmsg(rv))); 14190 _BCM_OAM_UNLOCK(oc); 14191 return (rv); 14192 } 14193 14194 /* Pack control message data into DMA buffer */ 14195 buffer = oc->dma_buffer; 14196 buffer_ptr = bhh_sdk_msg_ctrl_loss_get_unpack(buffer, &msg); 14197 buffer_len = buffer_ptr - buffer; 14198 14199 if (reply_len != buffer_len) { 14200 rv = BCM_E_INTERNAL; 14201 } else { 14202 /* 14203 * Convert kernel space flags to host space flags 14204 */ 14205 if (msg.flags & BCM_BHH_LM_SINGLE_ENDED) { 14206 loss_p->flags |= BCM_OAM_LOSS_SINGLE_ENDED; 14207 } 14208 14209 if (msg.flags & BCM_BHH_LM_TX_ENABLE) { 14210 loss_p->flags |= BCM_OAM_LOSS_TX_ENABLE; 14211 } 14212 14213 if (msg.flags & BCM_BHH_LM_SLM) { 14214 loss_p->flags |= BCM_OAM_LOSS_SLM; 14215 } 14216 14217 loss_p->period = msg.period; 14218 loss_p->loss_threshold = msg.loss_threshold; 14219 loss_p->loss_nearend = msg.loss_nearend; 14220 loss_p->loss_farend = msg.loss_farend; 14221 loss_p->tx_nearend = msg.tx_nearend; 14222 loss_p->rx_nearend = msg.rx_nearend; 14223 loss_p->tx_farend = msg.tx_farend; 14224 loss_p->rx_farend = msg.rx_farend; 14225 loss_p->rx_oam_packets = msg.rx_oam_packets; 14226 loss_p->tx_oam_packets = msg.tx_oam_packets; 14227 loss_p->int_pri = msg.int_pri; 14228 loss_p->pkt_pri = msg.pkt_pri; 14229 14230 rv = BCM_E_NONE; 14231 } 14232 } 14233 else { 14234 _BCM_OAM_UNLOCK(oc); 14235 return BCM_E_UNAVAIL; 14236 } 14237 14238 _BCM_OAM_UNLOCK(oc); 14239 14240 return (rv); 14241 } 14242 14243 /* 14244 * Function: 14245 * bcm_tr3_oam_loss_delete 14246 * Purpose: 14247 * Loss Measurement Delete 14248 * Parameters: 14249 * unit - Device unit number 14250 * Returns: 14251 * None 14252 */ 14253 int 14254 bcm_tr3_oam_loss_delete(int unit, bcm_oam_loss_t *loss_p) 14255 { 14256 _bcm_oam_control_t *oc; 14257 int rv = BCM_E_NONE; 14258 shr_bhh_msg_ctrl_loss_delete_t msg; 14259 uint8 *buffer, *buffer_ptr; 14260 uint16 buffer_len, reply_len; 14261 int sess_id = 0; 14262 _bcm_oam_hash_data_t *h_data_p; 14263 14264 /* Get OAM Control Structure. */ 14265 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 14266 _BCM_OAM_LOCK(oc); 14267 14268 if (oc->ukernel_not_ready) { 14269 _BCM_OAM_UNLOCK(oc); 14270 return BCM_E_INIT; 14271 } 14272 14273 14274 BCM_OAM_BHH_VALIDATE_EP(loss_p->id); 14275 14276 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id); 14277 14278 /* Check endpoint status. */ 14279 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 14280 if ((BCM_E_EXISTS != rv)) { 14281 /* Endpoint not in use. */ 14282 LOG_ERROR(BSL_LS_BCM_OAM, 14283 (BSL_META_U(unit, 14284 "OAM Error: Endpoint EP=%d %s.\n"), 14285 loss_p->id, bcm_errmsg(rv))); 14286 _BCM_OAM_UNLOCK(oc); 14287 return (rv); 14288 } 14289 14290 h_data_p = &oc->oam_hash_data[loss_p->id]; 14291 14292 /* 14293 * Only BHH is supported 14294 */ 14295 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS || 14296 h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 14297 14298 msg.sess_id = sess_id; 14299 14300 /* Pack control message data into DMA buffer */ 14301 buffer = oc->dma_buffer; 14302 buffer_ptr = shr_bhh_msg_ctrl_loss_delete_pack(buffer, &msg); 14303 buffer_len = buffer_ptr - buffer; 14304 14305 /* Send BHH Session Update message to uC */ 14306 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 14307 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE, 14308 buffer_len, 0, 14309 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE_REPLY, 14310 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 14311 14312 if(BCM_SUCCESS(rv) && (reply_len != 0)) 14313 rv = BCM_E_INTERNAL; 14314 } 14315 else { 14316 _BCM_OAM_UNLOCK(oc); 14317 return BCM_E_UNAVAIL; 14318 } 14319 14320 _BCM_OAM_UNLOCK(oc); 14321 14322 return (rv); 14323 } 14324 14325 /* 14326 * Function: 14327 * bcm_tr3_oam_delay_add 14328 * Purpose: 14329 * Delay Measurement add 14330 * Parameters: 14331 * unit - Device unit number 14332 * Returns: 14333 * None 14334 */ 14335 int 14336 bcm_tr3_oam_delay_add(int unit, bcm_oam_delay_t *delay_p) 14337 { 14338 _bcm_oam_control_t *oc; 14339 _bcm_oam_hash_data_t *h_data_p; 14340 int rv = BCM_E_NONE; 14341 bhh_sdk_msg_ctrl_delay_add_t msg; 14342 uint8 *buffer, *buffer_ptr; 14343 uint16 buffer_len, reply_len; 14344 uint32 flags = 0; 14345 int sess_id = 0; 14346 14347 /* Get OAM Control Structure. */ 14348 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 14349 _BCM_OAM_LOCK(oc); 14350 14351 if (oc->ukernel_not_ready) { 14352 _BCM_OAM_UNLOCK(oc); 14353 return BCM_E_INIT; 14354 } 14355 14356 14357 if (!oc->bhh_lm_dm_enable) { 14358 LOG_ERROR(BSL_LS_BCM_OAM, 14359 (BSL_META_U(unit, 14360 "OAM Error: LM/DM not enabled\n"))); 14361 _BCM_OAM_UNLOCK(oc); 14362 return BCM_E_DISABLED; 14363 } 14364 14365 14366 BCM_OAM_BHH_VALIDATE_EP(delay_p->id); 14367 14368 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id); 14369 14370 /* Check endpoint status. */ 14371 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 14372 if ((BCM_E_EXISTS != rv)) { 14373 /* Endpoint not in use. */ 14374 LOG_ERROR(BSL_LS_BCM_OAM, 14375 (BSL_META_U(unit, 14376 "OAM Error: Endpoint EP=%d %s.\n"), 14377 delay_p->id, bcm_errmsg(rv))); 14378 _BCM_OAM_UNLOCK(oc); 14379 return (rv); 14380 } 14381 14382 h_data_p = &oc->oam_hash_data[delay_p->id]; 14383 14384 /* 14385 * Only BHH is supported 14386 */ 14387 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS || 14388 h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 14389 /* 14390 * Convert host space flags to uKernel space flags 14391 */ 14392 if (delay_p->flags & BCM_OAM_DELAY_ONE_WAY) 14393 flags |= BCM_BHH_DM_ONE_WAY; 14394 14395 if (delay_p->flags & BCM_OAM_DELAY_TX_ENABLE) 14396 flags |= BCM_BHH_DM_TX_ENABLE; 14397 14398 sal_memset(&msg, 0, sizeof(msg)); 14399 msg.flags = flags; 14400 msg.sess_id = sess_id; 14401 msg.int_pri = delay_p->int_pri; 14402 msg.pkt_pri = delay_p->pkt_pri; 14403 14404 h_data_p->ts_format = delay_p->timestamp_format; 14405 14406 if(delay_p->timestamp_format == bcmOAMTimestampFormatIEEE1588v1) 14407 msg.dm_format = BCM_BHH_DM_TYPE_PTP; 14408 else 14409 msg.dm_format = BCM_BHH_DM_TYPE_NTP; 14410 14411 /* 14412 * Set period 14413 */ 14414 msg.period = _tr3_ccm_intervals[_bcm_tr3_oam_ccm_msecs_to_hw_encode(delay_p->period)]; 14415 14416 /* Pack control message data into DMA buffer */ 14417 buffer = oc->dma_buffer; 14418 buffer_ptr = bhh_sdk_msg_ctrl_delay_add_pack(buffer, &msg); 14419 buffer_len = buffer_ptr - buffer; 14420 14421 /* Send BHH Session Update message to uC */ 14422 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 14423 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD, 14424 buffer_len, 0, 14425 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD_REPLY, 14426 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 14427 14428 if(BCM_SUCCESS(rv) && (reply_len != 0)) 14429 rv = BCM_E_INTERNAL; 14430 } 14431 else { 14432 _BCM_OAM_UNLOCK(oc); 14433 return BCM_E_UNAVAIL; 14434 } 14435 14436 _BCM_OAM_UNLOCK(oc); 14437 return (rv); 14438 } 14439 14440 /* 14441 * Function: 14442 * bcm_tr3_oam_delay_get 14443 * Purpose: 14444 * Delay Measurements get 14445 * Parameters: 14446 * unit - Device unit number 14447 * Returns: 14448 * None 14449 */ 14450 int 14451 bcm_tr3_oam_delay_get(int unit, bcm_oam_delay_t *delay_p) 14452 { 14453 _bcm_oam_control_t *oc; 14454 int rv = BCM_E_NONE; 14455 bhh_sdk_msg_ctrl_delay_get_t msg; 14456 _bcm_oam_hash_data_t *h_data_p; 14457 uint8 *buffer, *buffer_ptr; 14458 uint16 buffer_len, reply_len; 14459 int sess_id = 0; 14460 14461 /* Get OAM Control Structure. */ 14462 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 14463 _BCM_OAM_LOCK(oc); 14464 14465 if (oc->ukernel_not_ready) { 14466 _BCM_OAM_UNLOCK(oc); 14467 return BCM_E_INIT; 14468 } 14469 14470 14471 BCM_OAM_BHH_VALIDATE_EP(delay_p->id); 14472 14473 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id); 14474 14475 /* Check endpoint status. */ 14476 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 14477 if ((BCM_E_EXISTS != rv)) { 14478 /* Endpoint not in use. */ 14479 LOG_ERROR(BSL_LS_BCM_OAM, 14480 (BSL_META_U(unit, 14481 "OAM Error: Endpoint EP=%d %s.\n"), 14482 delay_p->id, bcm_errmsg(rv))); 14483 _BCM_OAM_UNLOCK(oc); 14484 return (rv); 14485 } 14486 14487 h_data_p = &oc->oam_hash_data[delay_p->id]; 14488 14489 /* 14490 * Only BHH is supported 14491 */ 14492 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS || 14493 h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 14494 14495 sal_memset(&msg, 0, sizeof(msg)); 14496 /* Send BHH Session Update message to uC */ 14497 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 14498 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET, 14499 sess_id, 0, 14500 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET_REPLY, 14501 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 14502 if(BCM_FAILURE(rv)) { 14503 LOG_ERROR(BSL_LS_BCM_OAM, 14504 (BSL_META_U(unit, 14505 "OAM Error: Endpoint EP=%d %s.\n"), 14506 delay_p->id, bcm_errmsg(rv))); 14507 _BCM_OAM_UNLOCK(oc); 14508 return (rv); 14509 } 14510 14511 /* Pack control message data into DMA buffer */ 14512 buffer = oc->dma_buffer; 14513 buffer_ptr = bhh_sdk_msg_ctrl_delay_get_unpack(buffer, &msg); 14514 buffer_len = buffer_ptr - buffer; 14515 14516 14517 if (reply_len != buffer_len) { 14518 rv = BCM_E_INTERNAL; 14519 } else { 14520 /* 14521 * Convert kernel space flags to host space flags 14522 */ 14523 if (msg.flags & BCM_BHH_DM_ONE_WAY) 14524 delay_p->flags |= BCM_OAM_DELAY_ONE_WAY; 14525 14526 if (msg.flags & BCM_BHH_DM_TX_ENABLE) 14527 delay_p->flags |= BCM_OAM_DELAY_TX_ENABLE; 14528 14529 delay_p->period = msg.period; 14530 14531 if(msg.dm_format == BCM_BHH_DM_TYPE_PTP) 14532 delay_p->timestamp_format = bcmOAMTimestampFormatIEEE1588v1; 14533 else 14534 delay_p->timestamp_format = bcmOAMTimestampFormatNTP; 14535 14536 rv = bcm_oam_bhh_convert_ep_to_time_spec(&(delay_p->delay), 14537 msg.delay_seconds, msg.delay_nanoseconds); 14538 if(BCM_SUCCESS(rv)) { 14539 rv = bcm_oam_bhh_convert_ep_to_time_spec(&(delay_p->txf), 14540 msg.txf_seconds, msg.txf_nanoseconds); 14541 } 14542 if(BCM_SUCCESS(rv)) { 14543 rv = bcm_oam_bhh_convert_ep_to_time_spec(&(delay_p->rxf), 14544 msg.rxf_seconds, msg.rxf_nanoseconds); 14545 } 14546 if(BCM_SUCCESS(rv)) { 14547 rv = bcm_oam_bhh_convert_ep_to_time_spec(&(delay_p->txb), 14548 msg.txb_seconds, msg.txb_nanoseconds); 14549 } 14550 if(BCM_SUCCESS(rv)) { 14551 rv = bcm_oam_bhh_convert_ep_to_time_spec(&(delay_p->rxb), 14552 msg.rxb_seconds, msg.rxb_nanoseconds); 14553 } 14554 delay_p->rx_oam_packets = msg.rx_oam_packets; 14555 delay_p->tx_oam_packets = msg.tx_oam_packets; 14556 delay_p->int_pri = msg.int_pri; 14557 delay_p->pkt_pri = msg.pkt_pri; 14558 14559 rv = BCM_E_NONE; 14560 } 14561 } 14562 else { 14563 _BCM_OAM_UNLOCK(oc); 14564 return BCM_E_UNAVAIL; 14565 } 14566 14567 _BCM_OAM_UNLOCK(oc); 14568 14569 return (rv); 14570 } 14571 14572 /* 14573 * Function: 14574 * bcm_tr3_oam_delay_delete 14575 * Purpose: 14576 * Delay Measurement Delete 14577 * Parameters: 14578 * unit - Device unit number 14579 * Returns: 14580 * None 14581 */ 14582 int 14583 bcm_tr3_oam_delay_delete(int unit, bcm_oam_delay_t *delay_p) 14584 { 14585 _bcm_oam_control_t *oc; 14586 int rv = BCM_E_NONE; 14587 shr_bhh_msg_ctrl_delay_delete_t msg; 14588 uint8 *buffer, *buffer_ptr; 14589 uint16 buffer_len, reply_len; 14590 int sess_id = 0; 14591 _bcm_oam_hash_data_t *h_data_p; 14592 14593 /* Get OAM Control Structure. */ 14594 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 14595 _BCM_OAM_LOCK(oc); 14596 14597 if (oc->ukernel_not_ready) { 14598 _BCM_OAM_UNLOCK(oc); 14599 return BCM_E_INIT; 14600 } 14601 14602 14603 BCM_OAM_BHH_VALIDATE_EP(delay_p->id); 14604 14605 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id); 14606 14607 /* Check endpoint status. */ 14608 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 14609 if ((BCM_E_EXISTS != rv)) { 14610 /* Endpoint not in use. */ 14611 LOG_ERROR(BSL_LS_BCM_OAM, 14612 (BSL_META_U(unit, 14613 "OAM Error: Endpoint EP=%d %s.\n"), 14614 delay_p->id, bcm_errmsg(rv))); 14615 _BCM_OAM_UNLOCK(oc); 14616 return (rv); 14617 } 14618 14619 h_data_p = &oc->oam_hash_data[delay_p->id]; 14620 14621 /* 14622 * Only BHH is supported 14623 */ 14624 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLS || 14625 h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 14626 14627 msg.sess_id = sess_id; 14628 14629 /* Pack control message data into DMA buffer */ 14630 buffer = oc->dma_buffer; 14631 buffer_ptr = shr_bhh_msg_ctrl_delay_delete_pack(buffer, &msg); 14632 buffer_len = buffer_ptr - buffer; 14633 14634 /* Send BHH Session Update message to uC */ 14635 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 14636 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE, 14637 buffer_len, 0, 14638 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE_REPLY, 14639 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 14640 14641 if(BCM_SUCCESS(rv) && (reply_len != 0)) 14642 rv = BCM_E_INTERNAL; 14643 } 14644 else { 14645 rv = BCM_E_UNAVAIL; 14646 } 14647 14648 _BCM_OAM_UNLOCK(oc); 14649 14650 return (rv); 14651 } 14652 14653 /* 14654 * Function: 14655 * bcm_tr3_oam_csf_add 14656 * Purpose: 14657 * Start CSF PDU transmission 14658 * Parameters: 14659 * unit - (IN) Unit number. 14660 * csf_ptr - (INOUT) CSF object 14661 * Returns: 14662 * BCM_E_XXX 14663 * Notes: 14664 */ 14665 int bcm_tr3_oam_csf_add(int unit, bcm_oam_csf_t *csf_p) 14666 { 14667 _bcm_oam_control_t *oc; 14668 _bcm_oam_hash_data_t *h_data_p; 14669 bhh_sdk_msg_ctrl_csf_add_t msg; 14670 uint8 *buffer, *buffer_ptr; 14671 uint16 buffer_len, reply_len; 14672 int sess_id = 0; 14673 int rv = BCM_E_NONE; 14674 14675 /* Get OAM Control Structure. */ 14676 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 14677 _BCM_OAM_LOCK(oc); 14678 14679 if (oc->ukernel_not_ready) { 14680 _BCM_OAM_UNLOCK(oc); 14681 return BCM_E_INIT; 14682 } 14683 14684 BCM_OAM_BHH_VALIDATE_EP(csf_p->id); 14685 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id); 14686 14687 /* Check endpoint status. */ 14688 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 14689 if ((BCM_E_EXISTS != rv)) { 14690 /* Endpoint not in use. */ 14691 LOG_ERROR(BSL_LS_BCM_OAM, 14692 (BSL_META_U(unit, 14693 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 14694 unit, csf_p->id, bcm_errmsg(rv))); 14695 _BCM_OAM_UNLOCK(oc); 14696 return (rv); 14697 } 14698 14699 if ((csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1S) && 14700 (csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1M)) { 14701 /* Only 1S and 1M are supported */ 14702 _BCM_OAM_UNLOCK(oc); 14703 return BCM_E_PARAM; 14704 } 14705 14706 h_data_p = &oc->oam_hash_data[csf_p->id]; 14707 /* 14708 * Only BHH is supported 14709 */ 14710 if (h_data_p->type != bcmOAMEndpointTypeBHHMPLS && 14711 h_data_p->type != bcmOAMEndpointTypeBHHMPLSVccv) { 14712 _BCM_OAM_UNLOCK(oc); 14713 return BCM_E_UNAVAIL; 14714 } 14715 14716 sal_memset(&msg, 0, sizeof(msg)); 14717 msg.sess_id = sess_id; 14718 msg.int_pri = csf_p->int_pri; 14719 msg.pkt_pri = csf_p->pkt_pri; 14720 14721 switch(csf_p->type) { 14722 case BCM_OAM_CSF_LOS: 14723 msg.type = SHR_CSF_TYPE_LOS; 14724 break; 14725 14726 case BCM_OAM_CSF_FDI: 14727 msg.type = SHR_CSF_TYPE_FDI; 14728 break; 14729 14730 case BCM_OAM_CSF_RDI: 14731 msg.type = SHR_CSF_TYPE_RDI; 14732 break; 14733 14734 case BCM_OAM_CSF_DCI: 14735 msg.type = SHR_CSF_TYPE_DCI; 14736 break; 14737 14738 default: 14739 _BCM_OAM_UNLOCK(oc); 14740 return BCM_E_PARAM; 14741 } 14742 14743 /* 14744 * Set period 14745 */ 14746 msg.period = csf_p->period; 14747 14748 /* Pack control message data into DMA buffer */ 14749 buffer = oc->dma_buffer; 14750 buffer_ptr = bhh_sdk_msg_ctrl_csf_add_pack(buffer, &msg); 14751 buffer_len = buffer_ptr - buffer; 14752 14753 /* Send BHH Session Update message to uC */ 14754 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 14755 MOS_MSG_SUBCLASS_BHH_CSF_ADD, 14756 buffer_len, 0, 14757 MOS_MSG_SUBCLASS_BHH_CSF_ADD_REPLY, 14758 &reply_len, 14759 _BHH_UC_MSG_TIMEOUT_USECS); 14760 14761 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 14762 rv = BCM_E_INTERNAL; 14763 } 14764 14765 _BCM_OAM_UNLOCK(oc); 14766 return rv; 14767 } 14768 14769 /* 14770 * Function: 14771 * bcm_tr3_oam_csf_get 14772 * Purpose: 14773 * Get CSF info 14774 * Parameters: 14775 * unit - (IN) Unit number. 14776 * csf_ptr - (OUT) CSF object 14777 * Returns: 14778 * BCM_E_XXX 14779 * Notes: 14780 */ 14781 int bcm_tr3_oam_csf_get(int unit, bcm_oam_csf_t *csf_p) 14782 { 14783 _bcm_oam_control_t *oc; 14784 bhh_sdk_msg_ctrl_csf_get_t msg; 14785 _bcm_oam_hash_data_t *h_data_p; 14786 uint8 *buffer, *buffer_ptr; 14787 uint16 buffer_len, reply_len; 14788 int sess_id = 0; 14789 int rv = BCM_E_NONE; 14790 14791 /* Get OAM Control Structure. */ 14792 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 14793 _BCM_OAM_LOCK(oc); 14794 14795 if (oc->ukernel_not_ready) { 14796 _BCM_OAM_UNLOCK(oc); 14797 return BCM_E_INIT; 14798 } 14799 14800 BCM_OAM_BHH_VALIDATE_EP(csf_p->id); 14801 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id); 14802 14803 /* Check endpoint status. */ 14804 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 14805 if ((BCM_E_EXISTS != rv)) { 14806 /* Endpoint not in use. */ 14807 LOG_ERROR(BSL_LS_BCM_OAM, 14808 (BSL_META_U(unit, 14809 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 14810 unit, csf_p->id, bcm_errmsg(rv))); 14811 _BCM_OAM_UNLOCK(oc); 14812 return (rv); 14813 } 14814 14815 h_data_p = &oc->oam_hash_data[csf_p->id]; 14816 14817 if (h_data_p->type != bcmOAMEndpointTypeBHHMPLS && 14818 h_data_p->type != bcmOAMEndpointTypeBHHMPLSVccv) { 14819 _BCM_OAM_UNLOCK(oc); 14820 return BCM_E_UNAVAIL; 14821 } 14822 14823 14824 sal_memset(&msg, 0, sizeof(msg)); 14825 14826 /* Send BHH Session Update message to uC */ 14827 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 14828 MOS_MSG_SUBCLASS_BHH_CSF_GET, 14829 sess_id, 0, 14830 MOS_MSG_SUBCLASS_BHH_CSF_GET_REPLY, 14831 &reply_len, 14832 _BHH_UC_MSG_TIMEOUT_USECS); 14833 if(BCM_FAILURE(rv)) { 14834 LOG_ERROR(BSL_LS_BCM_OAM, 14835 (BSL_META_U(unit, 14836 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 14837 unit, csf_p->id, bcm_errmsg(rv))); 14838 _BCM_OAM_UNLOCK(oc); 14839 return (rv); 14840 } 14841 14842 /* Pack control message data into DMA buffer */ 14843 buffer = oc->dma_buffer; 14844 buffer_ptr = bhh_sdk_msg_ctrl_csf_get_unpack(buffer, &msg); 14845 buffer_len = buffer_ptr - buffer; 14846 14847 14848 if (reply_len != buffer_len) { 14849 _BCM_OAM_UNLOCK(oc); 14850 return BCM_E_INTERNAL; 14851 } 14852 14853 switch(msg.type) { 14854 case SHR_CSF_TYPE_LOS: 14855 csf_p->type = BCM_OAM_CSF_LOS; 14856 break; 14857 14858 case SHR_CSF_TYPE_FDI: 14859 csf_p->type = BCM_OAM_CSF_FDI; 14860 break; 14861 14862 case SHR_CSF_TYPE_RDI: 14863 csf_p->type = BCM_OAM_CSF_RDI; 14864 break; 14865 14866 case SHR_CSF_TYPE_DCI: 14867 csf_p->type = BCM_OAM_CSF_DCI; 14868 break; 14869 14870 default: 14871 _BCM_OAM_UNLOCK(oc); 14872 return BCM_E_INTERNAL; 14873 } 14874 14875 csf_p->period = msg.period; 14876 csf_p->flags = msg.flags; 14877 csf_p->pkt_pri = msg.pkt_pri; 14878 csf_p->int_pri = msg.int_pri; 14879 14880 14881 _BCM_OAM_UNLOCK(oc); 14882 return BCM_E_NONE; 14883 14884 } 14885 14886 /* 14887 * Function: 14888 * bcm_tr3_oam_csf_delete 14889 * Purpose: 14890 * Stop CSF PDU transmission 14891 * Parameters: 14892 * unit - (IN Unit number. 14893 * csf_ptr - (IN) CSF object 14894 * Returns: 14895 * BCM_E_XXX 14896 * Notes: 14897 */ 14898 int bcm_tr3_oam_csf_delete(int unit, bcm_oam_csf_t *csf_p) 14899 { 14900 _bcm_oam_control_t *oc; 14901 _bcm_oam_hash_data_t *h_data_p; 14902 uint16 reply_len; 14903 int sess_id; 14904 int rv = BCM_E_NONE; 14905 14906 /* Get OAM Control Structure. */ 14907 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 14908 _BCM_OAM_LOCK(oc); 14909 14910 if (oc->ukernel_not_ready) { 14911 _BCM_OAM_UNLOCK(oc); 14912 return BCM_E_INIT; 14913 } 14914 14915 BCM_OAM_BHH_VALIDATE_EP(csf_p->id); 14916 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id); 14917 14918 /* Check endpoint status. */ 14919 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 14920 if ((BCM_E_EXISTS != rv)) { 14921 /* Endpoint not in use. */ 14922 LOG_ERROR(BSL_LS_BCM_OAM, 14923 (BSL_META_U(unit, 14924 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 14925 unit, csf_p->id, bcm_errmsg(rv))); 14926 _BCM_OAM_UNLOCK(oc); 14927 return (rv); 14928 } 14929 14930 h_data_p = &oc->oam_hash_data[csf_p->id]; 14931 14932 if (h_data_p->type != bcmOAMEndpointTypeBHHMPLS && 14933 h_data_p->type != bcmOAMEndpointTypeBHHMPLSVccv) { 14934 _BCM_OAM_UNLOCK(oc); 14935 return BCM_E_UNAVAIL; 14936 } 14937 14938 /* Send BHH Session Update message to uC */ 14939 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 14940 MOS_MSG_SUBCLASS_BHH_CSF_DELETE, 14941 sess_id, 0, 14942 MOS_MSG_SUBCLASS_BHH_CSF_DELETE_REPLY, 14943 &reply_len, 14944 _BHH_UC_MSG_TIMEOUT_USECS); 14945 _BCM_OAM_UNLOCK(oc); 14946 return (rv); 14947 } 14948 #endif /* defined(INCLUDE_BHH) */ 14949 14950 /* 14951 * Function: 14952 * _bcm_tr3_bhh_endpoint_faults_multi_get 14953 * Purpose: 14954 * Function to get faults for multiple BHH endpoints 14955 * in a single call. 14956 * Parameters: 14957 * unit (IN) BCM device number 14958 * flags (IN) Flags is kept unused as of now. 14959 * This is for any future enhancement 14960 * max_endpoints (IN) Number of max endpoint for the protocol 14961 * faults (OUT) Pointer to faults for all endpoints 14962 * endpoint_count (OUT) Pointer to Number of valid endpoints with faults, 14963 * filled by get API. 14964 * 14965 * Returns: 14966 * BCM_E_NONE No error 14967 * BCM_E_XXXX Error 14968 */ 14969 #if defined (INCLUDE_BHH) 14970 int _bcm_tr3_bhh_endpoint_faults_multi_get( 14971 int unit, 14972 uint32 flags, 14973 uint32 max_endpoints, 14974 bcm_oam_endpoint_fault_t *faults, 14975 uint32 *endpoint_count) 14976 { 14977 int rv = BCM_E_NONE; 14978 _bcm_oam_control_t *oc = NULL; 14979 bcm_oam_endpoint_fault_t *faults_temp = faults; 14980 uint8 *buffer; 14981 uint16 reply_len; 14982 uint32 sess_count; 14983 uint32 ep_id; 14984 uint32 ep_count = 0; 14985 uint32 faults_bitmap; 14986 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 14987 14988 /* Get OAM control structure. */ 14989 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 14990 14991 _BCM_OAM_LOCK(oc); 14992 14993 if(max_endpoints != oc->bhh_endpoint_count) { 14994 rv = BCM_E_PARAM; 14995 _BCM_OAM_UNLOCK(oc); 14996 return (rv); 14997 } 14998 14999 sal_memset(faults, 0, ((sizeof(bcm_oam_endpoint_fault_t))*max_endpoints)); 15000 15001 rv = _bcm_tr3_oam_bhh_msg_send_receive(unit, 15002 MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET, 15003 0, 0, 15004 MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET_REPLY, 15005 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 15006 15007 15008 if (BCM_FAILURE(rv)) { 15009 LOG_ERROR(BSL_LS_BCM_OAM, 15010 (BSL_META_U(unit, 15011 "OAM(unit %d) Error: BHH uKernel msg failed for" 15012 "faults multi get %s.\n"), unit, 15013 bcm_errmsg(rv))); 15014 _BCM_OAM_UNLOCK(oc); 15015 return (rv); 15016 } 15017 15018 if(reply_len != (oc->bhh_endpoint_count * sizeof(uint32))) { 15019 rv = BCM_E_INTERNAL; 15020 _BCM_OAM_UNLOCK(oc); 15021 return (rv); 15022 } 15023 /* Unpack control message data into DMA buffer */ 15024 buffer = oc->dma_buffer; 15025 for(sess_count = 0;sess_count < oc->bhh_endpoint_count;sess_count++) 15026 { 15027 ep_id = BCM_OAM_BHH_GET_SDK_EP(sess_count); 15028 15029 /* Validate endpoint index value. */ 15030 BCM_OAM_BHH_VALIDATE_EP(ep_id); 15031 15032 h_data_p = &oc->oam_hash_data[ep_id]; 15033 15034 /* If endpoint not in use, ignore and continue for next session_id). 15035 * If session is running in hostCPU, skip and Go to ep_id.*/ 15036 if(!(h_data_p->in_use) || (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) { 15037 continue; 15038 } 15039 15040 _SHR_UNPACK_U32(buffer, faults_bitmap); 15041 15042 faults_temp->endpoint_id = BCM_OAM_BHH_GET_SDK_EP(sess_count); 15043 15044 if(faults_bitmap & BHH_BTE_EVENT_CCM_TIMEOUT){ 15045 faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT; 15046 } 15047 if(faults_bitmap & BHH_BTE_EVENT_CCM_RDI){ 15048 faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_RDI; 15049 } 15050 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){ 15051 faults_temp->faults |= 15052 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL; 15053 } 15054 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){ 15055 faults_temp->faults |= 15056 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID; 15057 } 15058 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){ 15059 faults_temp->faults |= 15060 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID; 15061 } 15062 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){ 15063 faults_temp->faults |= 15064 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD; 15065 } 15066 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){ 15067 faults_temp->faults |= 15068 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY; 15069 } 15070 15071 ep_count++; 15072 faults_temp++; 15073 15074 } 15075 15076 *endpoint_count = ep_count; 15077 _BCM_OAM_UNLOCK(oc); 15078 return (rv); 15079 15080 } 15081 #endif 15082 15083 /* Function: 15084 * bcm_tr3_oam_endpoint_faults_multi_get 15085 * Purpose: 15086 * Function to get faults for multiple endpoints per protocl 15087 * in a single call. 15088 * Parameters: 15089 * unit (IN) BCM device number 15090 * flags (IN) Flags is kept unused as of now. 15091 * This is for any future enhancement 15092 * endpoint_protocol (IN) Protocol type of the endpoints to retrieve faults 15093 * max_endpoints (IN) Number of max endpoint for the protocol 15094 * faults (OUT) Pointer to faults for all endpoints 15095 * endpoint_count (OUT) Pointer to Number of valid endpoints with faults, 15096 * by get API. 15097 * 15098 * Returns: 15099 * BCM_E_NONE No error 15100 * BCM_E_XXXX Error 15101 */ 15102 15103 int bcm_tr3_oam_endpoint_faults_multi_get( 15104 int unit, 15105 uint32 flags, 15106 bcm_oam_protocol_type_t endpoint_protocol, 15107 uint32 max_endpoints, 15108 bcm_oam_endpoint_fault_t *faults, 15109 uint32 *endpoint_count) 15110 15111 { 15112 int rv = BCM_E_NONE; 15113 15114 if(!faults) { 15115 rv = BCM_E_PARAM; 15116 return (rv); 15117 } 15118 15119 switch(endpoint_protocol) { 15120 15121 #if defined(INCLUDE_BHH) 15122 case bcmOamProtocolBhh: 15123 *endpoint_count = 0; 15124 rv = _bcm_tr3_bhh_endpoint_faults_multi_get( 15125 unit, 15126 flags, 15127 max_endpoints, 15128 faults, 15129 endpoint_count); 15130 break; 15131 #endif 15132 default: 15133 rv = BCM_E_UNAVAIL; 15134 break; 15135 } 15136 15137 return rv; 15138 15139 } 15140 15141 #if defined(INCLUDE_BHH) 15142 /* 15143 * Function: 15144 * _bcm_tr3_oam_trunk_ports_update 15145 * Purpose: 15146 * Associate or Dissociate ports from trunk in mapping table 15147 * maintained by BTE 15148 * Parameters: 15149 * unit - Device unit number 15150 * trunk_gport - Trunk Gport 15151 * max_ports - Num ports being added/deleted 15152 * port_arr - Array of physical port gports being added/deleted 15153 * add - add == 1 indicates ports are being added 15154 * Returns: 15155 * BCM_E_XXX 15156 */ 15157 STATIC int 15158 _bcm_tr3_oam_trunk_ports_update(int unit, bcm_gport_t trunk_gport, int max_ports, 15159 bcm_gport_t *port_arr, uint8 add) 15160 { 15161 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 15162 _bcm_oam_control_t *oc = NULL; 15163 bhh_sdk_msg_ctrl_trunk_map_update_t msg; 15164 uint8 *buffer, *buffer_ptr; 15165 uint16 buffer_len, reply_len; 15166 int rv = BCM_E_NONE; 15167 int i; 15168 15169 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 15170 _BCM_OAM_LOCK(oc); 15171 15172 if (oc->ukernel_not_ready) { 15173 _BCM_OAM_UNLOCK(oc); 15174 return BCM_E_INIT; 15175 } 15176 15177 if (!BCM_GPORT_IS_TRUNK(trunk_gport)) { 15178 _BCM_OAM_UNLOCK(oc); 15179 return BCM_E_PARAM; 15180 } 15181 15182 if (max_ports >= SHR_BHH_MAX_PORTS) { 15183 _BCM_OAM_UNLOCK(oc); 15184 return BCM_E_PARAM; 15185 } 15186 15187 if (!port_arr) { 15188 _BCM_OAM_UNLOCK(oc); 15189 return BCM_E_PARAM; 15190 } 15191 15192 trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport); 15193 if (trunk_id == BCM_TRUNK_INVALID) { 15194 _BCM_OAM_UNLOCK(oc); 15195 return BCM_E_PARAM; 15196 } 15197 15198 if (add) { 15199 msg.trunk_id = trunk_id; 15200 } else { 15201 msg.trunk_id = (uint16) SHR_BHH_INVALID_TRUNK_ID; 15202 } 15203 msg.num_ports = max_ports; 15204 for (i = 0; i < max_ports; i++) { 15205 if (BCM_GPORT_IS_LOCAL(port_arr[i])) { 15206 msg.port_list[i] = BCM_GPORT_LOCAL_GET(port_arr[i]); 15207 } else if (BCM_GPORT_IS_MODPORT(port_arr[i])) { 15208 msg.port_list[i] = BCM_GPORT_MODPORT_PORT_GET(port_arr[i]); 15209 } else { 15210 _BCM_OAM_UNLOCK(oc); 15211 return BCM_E_PARAM; 15212 } 15213 } 15214 15215 /* Pack control message data into DMA buffer */ 15216 buffer = oc->dma_buffer; 15217 buffer_ptr = bhh_sdk_msg_ctrl_trunk_map_update_pack(buffer, &msg); 15218 buffer_len = buffer_ptr - buffer; 15219 15220 rv = _bcm_tr3_oam_bhh_msg_send_receive( 15221 unit, 15222 MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_UPDATE, 15223 buffer_len, 0, 15224 MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_UPDATE_REPLY, 15225 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 15226 15227 15228 if (BCM_FAILURE(rv)) { 15229 _BCM_OAM_UNLOCK(oc); 15230 return rv; 15231 } 15232 15233 return BCM_E_NONE; 15234 } 15235 15236 /* 15237 * Function: 15238 * bcm_tr3_oam_trunk_ports_add 15239 * Purpose: 15240 * Associate ports from trunk in mapping table maintained by BTE 15241 * Parameters: 15242 * unit - Device unit number 15243 * trunk_gport - Trunk Gport 15244 * max_ports - Num ports being added 15245 * port_arr - Array of physical port gports being added 15246 * Returns: 15247 * BCM_E_XXX 15248 */ 15249 int bcm_tr3_oam_trunk_ports_add(int unit, bcm_gport_t trunk_gport, 15250 int max_ports, bcm_gport_t *port_arr) 15251 { 15252 return _bcm_tr3_oam_trunk_ports_update(unit, trunk_gport, max_ports, 15253 port_arr, 1); 15254 } 15255 15256 /* 15257 * Function: 15258 * bcm_tr3_oam_trunk_ports_delete 15259 * Purpose: 15260 * Dissociate ports from trunk in mapping table maintained by BTE 15261 * Parameters: 15262 * unit - Device unit number 15263 * trunk_gport - Trunk Gport 15264 * max_ports - Num ports being deleted 15265 * port_arr - Array of physical port gports being deleted 15266 * Returns: 15267 * BCM_E_XXX 15268 */ 15269 int bcm_tr3_oam_trunk_ports_delete(int unit, bcm_gport_t trunk_gport, 15270 int max_ports, bcm_gport_t *port_arr) 15271 { 15272 return _bcm_tr3_oam_trunk_ports_update(unit, trunk_gport, max_ports, 15273 port_arr, 0); 15274 } 15275 15276 /* 15277 * Function: 15278 * _bcm_fp_oam_port_trunk_map_get 15279 * Purpose: 15280 * Get port to trunk mapping from UKERNEL 15281 * Parameters: 15282 * unit - (IN) BCM device number 15283 * trunk_gport - (IN) Trunk gport 15284 * max_ports - (IN) Max ports the port_arr can accomodate 15285 * port_arr - (OUT) Ports in the trunk 15286 * port_count - (OUT) Valid number of ports in the port_arr 15287 * 15288 * Returns: 15289 * BCM_E_XXX 15290 */ 15291 int 15292 bcm_tr3_oam_trunk_ports_get(int unit, bcm_gport_t trunk_gport, int max_ports, 15293 bcm_gport_t *port_arr, int *port_count) 15294 { 15295 bhh_sdk_msg_ctrl_trunk_map_get_t msg; 15296 uint8 *buffer, *buffer_ptr; 15297 uint16 buffer_len, reply_len; 15298 bcm_trunk_t trunk_id; 15299 _bcm_oam_control_t *oc = NULL; 15300 int rv = BCM_E_NONE; 15301 int i; 15302 15303 if (!BCM_GPORT_IS_TRUNK(trunk_gport)) { 15304 return BCM_E_PARAM; 15305 } 15306 15307 trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport); 15308 if (trunk_id == BCM_TRUNK_INVALID) { 15309 return BCM_E_PARAM; 15310 } 15311 15312 /* Get OAM Control Structure. */ 15313 BCM_IF_ERROR_RETURN(_bcm_oam_control_get(unit, &oc)); 15314 _BCM_OAM_LOCK(oc); 15315 15316 /* Send trunk_id in the send length variable */ 15317 rv = _bcm_tr3_oam_bhh_msg_send_receive( 15318 unit, 15319 MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_GET, 15320 trunk_id, 0, 15321 MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_GET_REPLY, 15322 &reply_len, _BHH_UC_MSG_TIMEOUT_USECS); 15323 if (BCM_FAILURE(rv)) { 15324 _BCM_OAM_UNLOCK(oc); 15325 return rv; 15326 } 15327 15328 sal_memset(&msg, 0, sizeof(msg)); 15329 buffer = oc->dma_buffer; 15330 buffer_ptr = bhh_sdk_msg_ctrl_trunk_map_get_unpack(buffer, &msg); 15331 buffer_len = buffer_ptr - buffer; 15332 15333 if (reply_len != buffer_len) { 15334 _BCM_OAM_UNLOCK(oc); 15335 return BCM_E_INTERNAL; 15336 } 15337 15338 *port_count = msg.num_ports; 15339 for (i = 0; (i < *port_count) && (i < max_ports); i++) { 15340 port_arr[i] = msg.port_list[i]; 15341 } 15342 15343 _BCM_OAM_UNLOCK(oc); 15344 return BCM_E_NONE;; 15345 } 15346 #endif /* INCLUDE_BHH */ 15347 #endif