oam.c (1377446B)
1 /* 2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 3 * 4 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 5 * 6 * File: 7 * oam.c 8 * 9 * Purpose: 10 * OAM implementation for Saber2 family of devices. 11 */ 12 13 #include <shared/bsl.h> 14 #include <sal/core/libc.h> 15 #include <soc/defs.h> 16 #include <soc/drv.h> 17 #include <soc/mem.h> 18 #include <soc/profile_mem.h> 19 #include <soc/hash.h> 20 #include <soc/l3x.h> 21 #include <soc/katana2.h> 22 #include <soc/ism_hash.h> 23 #include <soc/scache.h> 24 #include <soc/tnl_term.h> 25 26 #include <bcm/l3.h> 27 #include <bcm/oam.h> 28 #include <bcm/cosq.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/triumph.h> 35 #include <bcm_int/esw/triumph3.h> 36 #include <bcm_int/esw/katana2.h> 37 #include <bcm_int/esw/saber2.h> 38 #include <bcm_int/esw/virtual.h> 39 #include <bcm_int/esw_dispatch.h> 40 #include <bcm_int/esw/failover.h> 41 #include <soc/shared/bhh_pkt.h> 42 #include <soc/shared/mpls_lm_dm_pkt.h> 43 #include <soc/shared/olp_pkt.h> 44 #include <soc/shared/olp_pack.h> 45 #include <soc/shared/oam_pm_shared.h> 46 47 #if defined(BCM_METROLITE_SUPPORT) 48 #include <soc/metrolite.h> 49 #endif 50 #if defined(BCM_SABER2_SUPPORT) 51 #include <bcm_int/esw/stack.h> 52 #include <bcm_int/esw/subport.h> 53 54 #if defined(INCLUDE_BHH) 55 #include <bcm_int/esw/bhh.h> 56 #include <bcm_int/esw/bhh_sdk_pack.h> 57 #endif /* INCLUDE_BHH */ 58 #include <soc/shared/oam_pm_pack.h> 59 60 /* 61 * Saber2 A0 has HW issue in inserting MP_GROUP entry due to TCAM atomicity. 62 * The HW Issue is fixed in B0 revision. 63 */ 64 static uint16 g_dev_id = 0; 65 static uint8 g_rev_id = 0; 66 67 #define BCM_SB2_TCAM_ATOMICITY_DISABLE(unit) {\ 68 if (g_rev_id == 0) {\ 69 soc_cm_get_id(unit, &g_dev_id, &g_rev_id); \ 70 }\ 71 if (g_rev_id == BCM56260_A0_REV_ID) { \ 72 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, AUX_ARB_CONTROL_2r,\ 73 REG_PORT_ANY, TCAM_ATOMIC_WRITE_ENABLEf, 0)); \ 74 }\ 75 } 76 #define BCM_SB2_TCAM_ATOMICITY_ENABLE(unit) {\ 77 if (g_rev_id == 0) {\ 78 soc_cm_get_id(unit, &g_dev_id, &g_rev_id); \ 79 }\ 80 if (g_rev_id == BCM56260_A0_REV_ID) { \ 81 BCM_IF_ERROR_RETURN(soc_reg_field32_modify(unit, AUX_ARB_CONTROL_2r,\ 82 REG_PORT_ANY, TCAM_ATOMIC_WRITE_ENABLEf, 1)); \ 83 }\ 84 } 85 86 /* Vlans will be programmed in ING/EGR MP_GROUP table depending on MEP_TYPE */ 87 #define _BCM_SB2_ETH_OAM_MP_GROUP_KEY_DOMAIN_SPECIFIC 0 88 /* Inner & Outer Vlan will be always programmed in ING/EGR MP_GROUP table */ 89 #define _BCM_SB2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT 1 90 91 #if defined(INCLUDE_ETH_LM_DM) 92 #include <bcm_int/esw/eth_lm_dm.h> 93 #include <soc/shared/eth_lm_dm_pkt.h> 94 #include <bcm_int/esw/eth_lm_dm_feature.h> 95 #include <bcm_int/esw/eth_lm_dm_sdk_msg.h> 96 #include <bcm_int/esw/eth_lm_dm_sdk_pack.h> 97 STATIC void 98 _bcm_sb2_oam_pm_ethlmdm_callback_thread(void *param); 99 100 STATIC int 101 _bcm_sb2_eth_lm_dm_loss_delete (int unit, 102 _bcm_oam_control_t *oc, 103 _bcm_oam_hash_data_t *h_data_p); 104 STATIC int 105 _bcm_sb2_eth_lm_dm_delay_delete (int unit, 106 _bcm_oam_control_t *oc, 107 _bcm_oam_hash_data_t *h_data_p); 108 STATIC int 109 _bcm_sb2_eth_lm_dm_event_mask_set(int unit); 110 #endif /* INCLUDE_ETH_LM_DM */ 111 112 #if defined(INCLUDE_MPLS_LM_DM) 113 #include <bcm_int/esw/mpls_lm_dm.h> 114 #include <bcm_int/esw/mpls_lm_dm_feature.h> 115 #include <bcm_int/esw/mpls_lm_dm_sdk_msg.h> 116 #include <bcm_int/esw/mpls_lm_dm_sdk_pack.h> 117 STATIC void 118 _bcm_sb2_oam_pm_mplslmdm_callback_thread(void *param); 119 STATIC int 120 _bcm_sb2_mpls_lm_dm_loss_delete(int unit, _bcm_oam_hash_data_t *h_data_p); 121 STATIC int 122 _bcm_sb2_mpls_lm_dm_delay_delete(int unit, _bcm_oam_hash_data_t *h_data_p); 123 STATIC int 124 _bcm_sb2_mpls_lm_dm_event_mask_set(int unit); 125 #endif 126 127 #if defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_BHH) 128 #include <soc/uc.h> 129 #endif 130 131 STATIC int 132 _bcm_sb2_oam_ma_idx_num_entries_and_pool_get(int unit, 133 _bcm_oam_hash_data_t *h_data_p, 134 int *num_ma_idx_entries, 135 shr_idxres_list_handle_t *pool); 136 STATIC int 137 _bcm_sb2_oam_ma_idx_pool_create(_bcm_oam_control_t *oc); 138 STATIC int 139 _bcm_sb2_oam_ma_idx_pool_destroy(_bcm_oam_control_t *oc); 140 STATIC int 141 _bcm_sb2_oam_control_get(int unit, _bcm_oam_control_t **oc); 142 143 144 STATIC INLINE bcm_oam_endpoint_t 145 _bcm_sb2_oam_ma_idx_to_ep_id_mapping_get (_bcm_oam_control_t *oc, int ma_idx); 146 147 /* 148 * Device OAM control structure. 149 */ 150 _bcm_oam_control_t *_sb2_oam_control[SOC_MAX_NUM_DEVICES]; 151 152 typedef struct _bcm_oam_pm_profile_int_info_s { 153 int id_status; 154 bcm_oam_pm_profile_info_t pm_profile; 155 }_bcm_oam_pm_profile_int_info_t; 156 typedef struct _bcm_oam_pm_profile_control_s { 157 _bcm_oam_pm_profile_int_info_t profile_info[_BCM_OAM_MAX_PM_PROFILES]; 158 }_bcm_oam_pm_profile_control_t; 159 160 161 _bcm_oam_pm_profile_control_t *pm_profile_control[SOC_MAX_NUM_DEVICES]; 162 163 #define _BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, id) (pmc->profile_info[id].id_status == 1) 164 #define _BCM_SB2_PM_CTRL_PROFILE_PTR(pmc, id) (&(pmc->profile_info[id].pm_profile)) 165 #define _BCM_SB2_SET_PM_CTRL_PROFILE_IN_USE(pmc, id) (pmc->profile_info[id].id_status = 1) 166 #define _BCM_SB2_SET_PM_CTRL_PROFILE_NOT_IN_USE(pmc, id) (pmc->profile_info[id].id_status = 0) 167 168 #define _BCM_SB2_PM_PROFILE_REPLACE_FLAG_SET(profile) (profile->flags & BCM_OAM_PM_PROFILE_REPLACE) 169 170 #define _BCM_SB2_PM_PROFILE_WITH_ID_FLAG_SET(profile) (profile->flags & BCM_OAM_PM_PROFILE_WITH_ID) 171 172 #define _BCM_SB2_PM_PROFILE_ID_VALID(profile_id) \ 173 ((profile_id >= 0) && (profile_id < _BCM_OAM_MAX_PM_PROFILES)) 174 175 /* PM raw data events handling macros */ 176 #define _BCM_SB2_EVENT_TYPE_PM_EVENT(event_types) ((SHR_BITGET(event_types.w, bcmOAMEventBHHRawData)) ||\ 177 (SHR_BITGET(event_types.w, bcmOAMEventEthLmDmRawData)) ||\ 178 (SHR_BITGET(event_types.w, bcmOAMEventMplsLmDmRawData))) 179 180 #define _BCM_SB2_BHH_OAM_PM_EVENT_TYPE(event_type) (event_type == bcmOAMEventBHHRawData) 181 182 #if defined (INCLUDE_BHH) 183 #define _BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc) \ 184 (oc->pm_bhh_lmdm_data_collection_mode != \ 185 _BCM_OAM_PM_COLLECTION_MODE_NONE) 186 #define _BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) \ 187 (oc->pm_bhh_lmdm_data_collection_mode == \ 188 _BCM_OAM_PM_COLLECTION_MODE_RAW_DATA) 189 #define _BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc) \ 190 (oc->pm_bhh_lmdm_data_collection_mode == \ 191 _BCM_OAM_PM_COLLECTION_MODE_PROCESSED_STATS) 192 static int sb2_oam_mpls_tp_ach_channel_type = SHR_BHH_ACH_CHANNEL_TYPE; 193 #else 194 #define _BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc) 0 195 #define _BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) 0 196 #define _BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc) 0 197 #endif 198 #if defined (INCLUDE_ETH_LM_DM) 199 #define _BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc) \ 200 (oc->pm_eth_lmdm_data_collection_mode != \ 201 _BCM_OAM_PM_COLLECTION_MODE_NONE) 202 #define _BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)\ 203 (oc->pm_eth_lmdm_data_collection_mode == \ 204 _BCM_OAM_PM_COLLECTION_MODE_RAW_DATA) 205 #define _BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)\ 206 (oc->pm_eth_lmdm_data_collection_mode == \ 207 _BCM_OAM_PM_COLLECTION_MODE_PROCESSED_STATS) 208 #else 209 #define _BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc) 0 210 #define _BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) 0 211 #define _BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc) 0 212 #endif 213 #if defined (INCLUDE_MPLS_LM_DM) 214 #define _BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc) \ 215 (oc->pm_mpls_lmdm_data_collection_mode != \ 216 _BCM_OAM_PM_COLLECTION_MODE_NONE) 217 #define _BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)\ 218 (oc->pm_mpls_lmdm_data_collection_mode ==\ 219 _BCM_OAM_PM_COLLECTION_MODE_RAW_DATA) 220 #define _BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc) \ 221 (oc->pm_mpls_lmdm_data_collection_mode ==\ 222 _BCM_OAM_PM_COLLECTION_MODE_PROCESSED_STATS) 223 #else 224 #define _BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc) 0 225 #define _BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc) 0 226 #define _BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc) 0 227 #endif 228 229 #define _BCM_SB2_OAM_PM_BHH_EVENT_IDX 0 230 #define _BCM_SB2_OAM_PM_ETH_LM_DM_EVENT_IDX 1 231 #define _BCM_SB2_OAM_PM_MPLS_LM_DM_EVENT_IDX 2 232 233 #define PM_READ_DONE_INDEX(event_idx) \ 234 (oc->pm_read_done_index[event_idx]) 235 #define PM_WRITE_DONE_INDEX(event_idx) \ 236 (oc->pm_write_done_index[event_idx]) 237 #define INCREMENT_PM_WRITE_DONE_INDEX(event_idx) \ 238 (((oc->pm_write_done_index[event_idx])+1)%BCM_OAM_MAX_PM_BUFFERS) 239 #define NUM_FREE_BUFFERS(event_idx)\ 240 (oc->pm_num_free_raw_data_buffers[event_idx]) 241 #define SET_NUM_FREE_BUFFERS(event_idx, value)\ 242 (oc->pm_num_free_raw_data_buffers[event_idx] = value) 243 #define DECR_NUM_FREE_BUFFERS(event_idx) \ 244 SET_NUM_FREE_BUFFERS(event_idx, (NUM_FREE_BUFFERS(event_idx) - 1)) 245 #define INCR_NUM_FREE_BUFFERS(event_idx) \ 246 SET_NUM_FREE_BUFFERS(event_idx, (NUM_FREE_BUFFERS(event_idx) + 1)) 247 248 249 250 #define VALID_PM_RAW_DATA_BUFFER_READ_WRITE_INDEX(index) \ 251 (index < BCM_OAM_MAX_PM_BUFFERS) 252 253 254 /* * * * * * * * * * * * * * * * * * * 255 * OAM MACROS * 256 */ 257 /* 258 * Macro: 259 * _BCM_OAM_IS_INIT (internal) 260 * Purpose: 261 * Check that the unit is valid and confirm that the oam functions 262 * are initialized. 263 * Parameters: 264 * unit - BCM device number 265 * Notes: 266 * Results in return(BCM_E_UNIT), return(BCM_E_UNAVAIL), or 267 * return(BCM_E_INIT) if fails. 268 */ 269 #define _BCM_OAM_IS_INIT(unit) \ 270 do { \ 271 if (!soc_feature(unit, soc_feature_oam)) { \ 272 return (BCM_E_UNAVAIL); \ 273 } \ 274 if (_sb2_oam_control[unit] == NULL) { \ 275 LOG_ERROR(BSL_LS_BCM_OAM, \ 276 (BSL_META_U(unit, \ 277 "OAM(unit %d) Error: Module not initialized\n"), \ 278 unit)); \ 279 return (BCM_E_INIT); \ 280 } \ 281 } while (0) 282 283 /* 284 *Macro: 285 * _BCM_OAM_LOCK 286 * Purpose: 287 * Lock take the OAM control mutex 288 * Parameters: 289 * control - Pointer to OAM control structure. 290 */ 291 #define _BCM_OAM_LOCK(control) \ 292 sal_mutex_take((control)->oc_lock, sal_mutex_FOREVER) 293 294 /* 295 * Macro: 296 * _BCM_OAM_UNLOCK 297 * Purpose: 298 * Lock take the OAM control mutex 299 * Parameters: 300 * control - Pointer to OAM control structure. 301 */ 302 #define _BCM_OAM_UNLOCK(control) \ 303 sal_mutex_give((control)->oc_lock); 304 /* 305 * Macro: 306 * _BCM_OAM_HASH_DATA_CLEAR 307 * Purpose: 308 * Clear hash data memory occupied by one endpoint. 309 * Parameters: 310 * _ptr_ - Pointer to endpoint hash data memory. 311 */ 312 #define _BCM_OAM_HASH_DATA_CLEAR(_ptr_) \ 313 sal_memset(_ptr_, 0, sizeof(_bcm_oam_hash_data_t)); 314 315 /* 316 * Macro: 317 * _BCM_OAM_HASH_DATA_HW_IDX_INIT 318 * Purpose: 319 * Initialize hardware indices to invalid index for an endpoint hash data. 320 * Parameters: 321 * _ptr_ - Pointer to endpoint hash data memory. 322 */ 323 #define _BCM_OAM_HASH_DATA_HW_IDX_INIT(_ptr_) \ 324 do { \ 325 (_ptr_)->group_index = (_BCM_OAM_INVALID_INDEX); \ 326 (_ptr_)->remote_index = (_BCM_OAM_INVALID_INDEX); \ 327 (_ptr_)->profile_index = (_BCM_OAM_INVALID_INDEX); \ 328 (_ptr_)->pri_map_index = (_BCM_OAM_INVALID_INDEX); \ 329 (_ptr_)->lm_counter_index = (_BCM_OAM_INVALID_INDEX); \ 330 (_ptr_)->local_tx_index = (_BCM_OAM_INVALID_INDEX); \ 331 (_ptr_)->local_rx_index = (_BCM_OAM_INVALID_INDEX); \ 332 } while (0) 333 /* 334 * Macro: 335 * _BCM_OAM_ALLOC 336 * Purpose: 337 * Generic memory allocation routine. 338 * Parameters: 339 * _ptr_ - Pointer to allocated memory. 340 * _ptype_ - Pointer type. 341 * _size_ - Size of heap memory to be allocated. 342 * _descr_ - Information about this memory allocation. 343 */ 344 #define _BCM_OAM_ALLOC(_ptr_,_ptype_,_size_,_descr_) \ 345 do { \ 346 if (NULL == (_ptr_)) { \ 347 (_ptr_) = (_ptype_ *) sal_alloc((_size_), (_descr_)); \ 348 } \ 349 if((_ptr_) != NULL) { \ 350 sal_memset((_ptr_), 0, (_size_)); \ 351 } else { \ 352 LOG_ERROR(BSL_LS_BCM_OAM, \ 353 (BSL_META("OAM Error: Allocation failure %s\n"), \ 354 (_descr_))); \ 355 } \ 356 } while (0) 357 358 /* 359 * Macro: 360 * _BCM_OAM_GROUP_INDEX_VALIDATE 361 * Purpose: 362 * Validate OAM Group ID value. 363 * Parameters: 364 * _group_ - Group ID value. 365 */ 366 #define _BCM_OAM_GROUP_INDEX_VALIDATE(_group_) \ 367 do { \ 368 if ((_group_) < 0 || (_group_) >= oc->group_count) { \ 369 LOG_ERROR(BSL_LS_BCM_OAM, \ 370 (BSL_META("OAM(unit %d) Error: Invalid Group ID = %d.\n"), \ 371 unit, _group_)); \ 372 return (BCM_E_PARAM); \ 373 } \ 374 } while (0); 375 376 /* 377 * Macro: 378 * _BCM_OAM_EP_INDEX_VALIDATE 379 * Purpose: 380 * Validate OAM Endpoint ID value. 381 * Parameters: 382 * _ep_ - Endpoint ID value. 383 */ 384 #define _BCM_OAM_EP_INDEX_VALIDATE(_ep_) \ 385 do { \ 386 if ((_ep_) < 0 || (_ep_) >= oc->ep_count) { \ 387 LOG_ERROR(BSL_LS_BCM_OAM, \ 388 (BSL_META("OAM(unit %d) Error: Invalid Endpoint ID" \ 389 " = %d.\n"), unit, _ep_)); \ 390 return (BCM_E_PARAM); \ 391 } \ 392 } while (0); 393 394 395 /* 396 * Macro: 397 * _BCM_OAM_RMEP_INDEX_VALIDATE 398 * Purpose: 399 * Validate OAM Endpoint ID value. 400 * Parameters: 401 * _ep_ - Endpoint ID value. 402 */ 403 #define _BCM_OAM_RMEP_INDEX_VALIDATE(_ep_) \ 404 do { \ 405 if ((_ep_) < 0 || (_ep_) >= oc->rmep_count) { \ 406 LOG_ERROR(BSL_LS_BCM_OAM, \ 407 (BSL_META("OAM(unit %d) Error: Invalid RMEP Index" \ 408 " = %d.\n"), unit, _ep_)); \ 409 return (BCM_E_PARAM); \ 410 } \ 411 } while (0); 412 /* 413 * Macro: 414 * DGLP_MODULE_ID_SHIFT_BITS 415 * Purpose: 416 * shift bits value used for SB2/ML for constructing DGLP. 417 */ 418 #define DGLP_MODULE_ID_SHIFT_BITS 7 419 420 /* 421 * Macro: 422 * _BCM_OAM_KEY_PACK 423 * Purpose: 424 * Pack the hash table look up key fields. 425 * Parameters: 426 * _dest_ - Hash key buffer. 427 * _src_ - Hash key field to be packed. 428 * _size_ - Hash key field size in bytes. 429 */ 430 #define _BCM_OAM_KEY_PACK(_dest_,_src_,_size_) \ 431 do { \ 432 sal_memcpy((_dest_), (_src_), (_size_)); \ 433 (_dest_) += (_size_); \ 434 } while (0) 435 /* 436 * Macro: 437 * _BCM_SB2_ML_OAM_DGLP_MODID_SHIFT_BIT 438 * Purpose: 439 * Return the shift_bit value for Mod_id reuired for DGLP. 440 * Parameters: 441 * _shift_bits_ - Shift bit value. 442 */ 443 #if defined (BCM_METROLITE_SUPPORT) 444 #define _BCM_SB2_ML_OAM_DGLP_MODID_SHIFT_BIT(_shift_bits_,_u_) \ 445 do { \ 446 if (SOC_IS_METROLITE(unit)) { \ 447 _shift_bits_ = DGLP_MODULE_ID_SHIFT_BITS; \ 448 } else { \ 449 _shift_bits_ = (_shr_popcount((unsigned int) SOC_PORT_ADDR_MAX(_u_))); \ 450 } \ 451 } while(0) 452 #else 453 #define _BCM_SB2_ML_OAM_DGLP_MODID_SHIFT_BIT(_shift_bits_,_u_) \ 454 do { \ 455 _shift_bits_ = (_shr_popcount((unsigned int) SOC_PORT_ADDR_MAX(_u_))); \ 456 } while(0) 457 #endif 458 459 /* 460 * Macro: 461 * _BCM_SB2_OAM_MOD_PORT_TO_GLP 462 * Purpose: 463 * Construct hadware GLP value from module ID, port ID and Trunk ID value. 464 * Parameters: 465 * _modid_ - Module ID. 466 * _port_ - Port ID. 467 * _trunk_ - Trunk (1 - TRUE/0 - FALSE). 468 * _tgid_ - Trunk ID. 469 */ 470 #define _BCM_SB2_OAM_MOD_PORT_TO_GLP(_u_, _m_, _p_, _t_, _tgid_, _glp_) \ 471 do { \ 472 uint32 shift_bits = -1; \ 473 _BCM_SB2_ML_OAM_DGLP_MODID_SHIFT_BIT(shift_bits,_u_); \ 474 if ((_tgid_) != -1) { \ 475 (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_)) \ 476 | ((soc_mem_index_count((_u_), TRUNK_GROUPm) - 1) \ 477 & (_tgid_))); \ 478 } else { \ 479 (_glp_) = (((0x1 & (_t_)) << SOC_TRUNK_BIT_POS(_u_)) \ 480 | ((SOC_MODID_MAX(_u_) & (_m_)) \ 481 << (shift_bits) \ 482 | (SOC_PORT_ADDR_MAX(_u_) & (_p_)))); \ 483 } \ 484 LOG_DEBUG(BSL_LS_BCM_OAM, \ 485 (BSL_META("u:%d m:%d p:%d t:%d tgid:%d glp:%x\n"), \ 486 _u_, _m_, _p_, _t_, _tgid_, _glp_)); \ 487 } while (0) 488 489 /* 490 * Macro: 491 * _BCM_OAM_GLP_XXX 492 * Purpose: 493 * Get components of generic logical port value. 494 * Parameters: 495 * _glp_ - Generic logical port. 496 */ 497 #define _BCM_OAM_GLP_TRUNK_BIT_GET(_glp_) (0x1 & ((_glp_) >> 15)) 498 #define _BCM_OAM_GLP_TRUNK_ID_GET(_glp_) (0xFF & (_glp_)) 499 #define _BCM_OAM_GLP_MODULE_ID_GET(_glp_) (0xFF & ((_glp_) >> 7)) 500 #define _BCM_OAM_GLP_PORT_GET(_glp_) (0x7F & (_glp_)) 501 502 /* 503 * Macro: 504 * _BCM_OAM_EP_LEVEL_XXX 505 * Purpose: 506 * Maintenance domain level bit count and level max value. 507 * Parameters: 508 * _glp_ - Generic logical port. 509 */ 510 #define _BCM_OAM_EP_LEVEL_COUNT (1 << (_BCM_OAM_EP_LEVEL_BIT_COUNT)) 511 #define _BCM_OAM_EP_LEVEL_MAX (_BCM_OAM_EP_LEVEL_COUNT - 1) 512 513 #define BHH_TYPE(type) ( (type == bcmOAMEndpointTypeBHHMPLS) || \ 514 (type == bcmOAMEndpointTypeBHHMPLSVccv)||\ 515 (type == bcmOAMEndpointTypeBhhSection)||\ 516 (type == bcmOAMEndpointTypeBhhSectionInnervlan)||\ 517 (type == bcmOAMEndpointTypeBhhSectionOuterVlan)||\ 518 (type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)\ 519 ) 520 521 #define BHH_EP_TYPE(ep) (BHH_TYPE(ep->type)) 522 523 #define BHH_EP_MPLS_SECTION_TYPE(ep) (\ 524 (ep->type == bcmOAMEndpointTypeBhhSection)||\ 525 (ep->type == bcmOAMEndpointTypeBhhSectionInnervlan)||\ 526 (ep->type == bcmOAMEndpointTypeBhhSectionOuterVlan)||\ 527 (ep->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)\ 528 ) 529 530 #define BHH_EP_LSP_TYPE(ep) (ep->type == bcmOAMEndpointTypeBHHMPLS) 531 532 533 #define MPLS_LM_DM_ENDPOINT_TYPE(ep) (\ 534 (ep->type == bcmOAMEndpointTypeMplsLmDmSectionPort)||\ 535 (ep->type == bcmOAMEndpointTypeMplsLmDmSectionInnervlan)||\ 536 (ep->type == bcmOAMEndpointTypeMplsLmDmSectionOuterVlan)||\ 537 (ep->type == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan)||\ 538 (ep->type == bcmOAMEndpointTypeMplsLmDmPw)||\ 539 (ep->type == bcmOAMEndpointTypeMplsLmDmLsp)\ 540 ) 541 542 #define MPLS_LM_DM_SECTION_ENDPOINT_TYPE(ep) (\ 543 (ep->type == bcmOAMEndpointTypeMplsLmDmSectionPort)||\ 544 (ep->type == bcmOAMEndpointTypeMplsLmDmSectionInnervlan)||\ 545 (ep->type == bcmOAMEndpointTypeMplsLmDmSectionOuterVlan)||\ 546 (ep->type == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan)) 547 548 #define MPLS_LM_DM_LSP_ENDPOINT_TYPE(ep) (\ 549 (ep->type == bcmOAMEndpointTypeMplsLmDmLsp)) 550 551 #define MPLS_LM_DM_PW_ENDPOINT_TYPE(ep) (\ 552 (ep->type == bcmOAMEndpointTypeMplsLmDmPw)) 553 554 #define _BCM_OAM_EP_IS_MIP(info) (info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) 555 556 #define ETH_TYPE(type) (type == bcmOAMEndpointTypeEthernet) 557 558 #define _BCM_SB2_OAM_EGR_LSP_MEP_LOOKUP_KEY_MEP_ID 0x1 559 #define _BCM_SB2_OAM_EGR_LSP_MEP_LOOKUP_KEY_EP_ID 0x2 560 561 /* 562 * Macro: 563 * BCM_WB_XXX 564 * Purpose: 565 * OAM module scache version information. 566 * Parameters: 567 * (major number, minor number) 568 */ 569 #ifdef BCM_WARM_BOOT_SUPPORT 570 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 571 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 572 #define BCM_WB_VERSION_1_2 SOC_SCACHE_VERSION(1,2) 573 /* This new version incorporates new MA_INDEX allocation scheme. 574 * Recovery of Endpoints allocated in new scheme will be 575 * done for this version or higher only */ 576 #define BCM_WB_VERSION_1_3 SOC_SCACHE_VERSION(1,3) 577 /* This ver supports recovery of PM profile */ 578 #define BCM_WB_VERSION_1_4 SOC_SCACHE_VERSION(1,4) 579 #define BCM_WB_VERSION_1_5 SOC_SCACHE_VERSION(1,5) 580 #define BCM_WB_VERSION_1_6 SOC_SCACHE_VERSION(1,6) 581 #define BCM_WB_VERSION_1_7 SOC_SCACHE_VERSION(1,7) 582 #define BCM_WB_VERSION_1_8 SOC_SCACHE_VERSION(1,8) 583 #define BCM_WB_VERSION_1_9 SOC_SCACHE_VERSION(1,9) 584 #define BCM_WB_VERSION_1_10 SOC_SCACHE_VERSION(1,10) 585 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_10 586 587 STATIC int bcm_sb2_oam_scache_alloc(int unit); 588 #endif 589 590 #define _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_TBL_SIZE \ 591 (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + oc->egr_ma_idx_count)) 592 593 #define _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_DOWNMEP_IDX(ma_base_index, ma_offset)\ 594 (ma_base_index + ma_offset) 595 #define _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_UPMEP_IDX(ma_base_index, ma_offset)\ 596 (oc->ma_idx_count + ma_base_index + ma_offset) 597 598 #define _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX(ma_base_index, ma_offset, is_upmep)\ 599 ((is_upmep)?\ 600 _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_UPMEP_IDX(ma_base_index, ma_offset)\ 601 :_BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_DOWNMEP_IDX(ma_base_index, ma_offset)) 602 603 /* Macros for endpoint id locations for different endpoint types. */ 604 #define _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE \ 605 (sizeof(bcm_oam_endpoint_t) * (oc->rmep_count + oc->lmep_count + oc->ma_idx_count + oc->egr_ma_idx_count)) 606 607 #define _BCM_SB2_OAM_RX_DOWNMEP_SCACHE_LOCATION(mep_index) \ 608 (sizeof(bcm_oam_endpoint_t) * mep_index) 609 #define _BCM_SB2_OAM_RX_UPMEP_SCACHE_LOCATION(mep_index) \ 610 (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + mep_index)) 611 #define _BCM_SB2_OAM_RMEP_SCACHE_LOCATION(rmep_index) \ 612 (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + oc->egr_ma_idx_count + rmep_index)) 613 #define _BCM_SB2_OAM_TX_MEP_SCACHE_LOCATION(mep_index) \ 614 (sizeof(bcm_oam_endpoint_t) * (oc->ma_idx_count + oc->egr_ma_idx_count + oc->rmep_count + mep_index)) 615 616 /* Warmboot helper for PM Id association */ 617 int _bcm_sb2_oam_pmid_scache_size(int unit) 618 { 619 int count = 0; 620 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM) 621 _bcm_oam_control_t *oc = _sb2_oam_control[unit]; 622 count = 623 #if defined(INCLUDE_ETH_LM_DM) 624 oc->eth_lm_dm_sess_count + 625 #endif 626 #if defined(INCLUDE_MPLS_LM_DM) 627 oc->mpls_lm_dm_sess_count + 628 #endif 629 #if defined(INCLUDE_BHH) 630 oc->bhh_endpoint_count + 631 #endif 632 count; 633 #endif 634 return (sizeof(int8) * (count)); 635 } 636 637 int _bcm_sb2_oam_eth_pmid_scache_loc(int unit, int sess) 638 { 639 return (sizeof(int8) * (sess)); 640 } 641 642 int _bcm_sb2_oam_mpls_pmid_scache_loc(int unit, int sess) 643 { 644 #if defined(INCLUDE_ETH_LM_DM) 645 _bcm_oam_control_t *oc = _sb2_oam_control[unit]; 646 #endif 647 return (sizeof(int8) * ( 648 #if defined(INCLUDE_ETH_LM_DM) 649 oc->eth_lm_dm_sess_count + 650 #endif 651 sess)); 652 } 653 654 int _bcm_sb2_oam_bhh_pmid_scache_loc(int unit, int sess) 655 { 656 #if defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM) 657 _bcm_oam_control_t *oc = _sb2_oam_control[unit]; 658 #endif 659 return (sizeof(int8) * ( 660 #if defined(INCLUDE_ETH_LM_DM) 661 oc->eth_lm_dm_sess_count + 662 #endif 663 #if defined(INCLUDE_MPLS_LM_DM) 664 oc->mpls_lm_dm_sess_count + 665 #endif 666 sess)); 667 } 668 669 #if defined(INCLUDE_ETH_LM_DM) 670 int8 *eth_oam_id_map = NULL; 671 #endif 672 #if defined(INCLUDE_MPLS_LM_DM) 673 int8 *mpls_oam_id_map = NULL; 674 #endif 675 676 /* Macro for PM profile information */ 677 #define _BCM_SB2_OAM_PM_PROFILE_SCACHE_SIZE \ 678 (sizeof(_bcm_oam_pm_profile_int_info_t) * (_BCM_OAM_MAX_PM_PROFILES)) 679 680 typedef struct _bcm_lmdm_oam_scache_info_s { 681 #if defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM) 682 bcm_vlan_t vlan; 683 bcm_vlan_t inner_vlan; 684 uint16 inner_tpid; 685 uint16 outer_tpid; 686 uint8 vlan_pri; 687 uint8 inner_vlan_pri; 688 bcm_mac_t dst_mac_address; 689 bcm_mac_t src_mac_address; 690 uint32 lm_dm_int_flag; 691 uint32 lm_dm_uc_session_id; 692 #endif 693 #if defined(INCLUDE_MPLS_LM_DM) 694 bcm_oam_group_t group_index; 695 #endif 696 bcm_vpn_t vpn; 697 uint8 egr_ctr_field_id; 698 }_bcm_lmdm_oam_scache_info_t; 699 700 #define _BCM_SB2_OAM_DOWN_MEP_LMDM_SCACHE_INFO_SIZE \ 701 (sizeof(_bcm_lmdm_oam_scache_info_t) * oc->ma_idx_count) 702 703 #if defined(INCLUDE_ETH_LM_DM) 704 #define _BCM_SB2_OAM_UP_MEP_LMDM_SCACHE_INFO_SIZE \ 705 (sizeof(_bcm_lmdm_oam_scache_info_t) * oc->egr_ma_idx_count) 706 #else 707 #define _BCM_SB2_OAM_UP_MEP_LMDM_SCACHE_INFO_SIZE (0) 708 #endif 709 710 #define _BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE \ 711 (_BCM_SB2_OAM_DOWN_MEP_LMDM_SCACHE_INFO_SIZE + \ 712 _BCM_SB2_OAM_UP_MEP_LMDM_SCACHE_INFO_SIZE) 713 714 #define _BCM_SB2_OAM_LM_DM_DOWN_MEP_SCACHE_INFO_LOCATION(mep_idx) \ 715 (sizeof(_bcm_lmdm_oam_scache_info_t) * (mep_idx)) 716 #define _BCM_SB2_OAM_LM_DM_UP_MEP_SCACHE_INFO_LOCATION(mep_idx) \ 717 (sizeof(_bcm_lmdm_oam_scache_info_t) * (oc->ma_idx_count + (mep_idx))) 718 719 #if defined(INCLUDE_MPLS_LM_DM) 720 typedef struct _bcm_mpls_lmdm_egr_label_scache_info_s { 721 bcm_mpls_label_t egr_label; 722 uint8 exp; 723 uint8 ttl; 724 }_bcm_sb2_oam_egr_label_scache_info_t; 725 #endif 726 727 #if defined(INCLUDE_MPLS_LM_DM) 728 #define _BCM_SB2_OAM_EGR_LABEL_SCACHE_SIZE \ 729 (sizeof(_bcm_sb2_oam_egr_label_scache_info_t) * oc->ma_idx_count) 730 #define _BCM_OAM_EGR_LABEL_SCACHE_OFFSET(mep_idx) \ 731 (sizeof(_bcm_sb2_oam_egr_label_scache_info_t) * mep_idx) 732 #else 733 #define _BCM_SB2_OAM_EGR_LABEL_SCACHE_SIZE (0) 734 #endif 735 736 737 /* Define the port used in OLP-XGS communication */ 738 #define _BCM_OAM_OLP_COMMUNICATION_PORT 0x7f 739 740 741 /* OAM opcode control profile actions */ 742 #define _BCM_SB2_OAM_OC_PROF_NORMAL_SWITCHING 0 743 #define _BCM_SB2_OAM_OC_PROF_DROP 1 744 #define _BCM_SB2_OAM_OC_PROF_FWD_TO_DGLP1 2 745 #define _BCM_SB2_OAM_OC_PROF_FWD_TO_DGLP2 3 746 #define _BCM_SB2_OAM_OC_PROF_FWD_TO_HW_ENGINE 4 747 #define _BCM_SB2_OAM_OC_PROF_FWD_TO_HW_LB_ENGINE 5 748 749 /* OAM_OPCODE_GROUP table key construction */ 750 /* COMPRESSED PROTOCOL : 751 * 0 - ETH-OAM 752 * 1 - BHH-OAM 753 * 2 - MPLS LM DM 754 * 3 - Reserved. 755 */ 756 #define _BCM_SB2_OAM_OPCODE_GRP_PROTO_ETH 0 757 #define _BCM_SB2_OAM_OPCODE_GRP_PROTO_BHH 1 758 #define _BCM_SB2_OAM_OPCODE_GRP_PROTO_MPLS_LMDM 2 759 760 /*KEY=(COMPRESSED_PROTOCOL(2bits),OPCODE(8 bits)) 761 OPCODE_GROUP 762 CPU_OPCODE */ 763 764 #define _BCM_SB2_OAM_OPCODE_GROUP_KEY_OPCODE_MASK 0xff /* 8 bits set */ 765 #define _BCM_SB2_OAM_OPCODE_GROUP_KEY_PROTO_MASK 0x3 /* 2 bits set */ 766 #define _BCM_SB2_OAM_OPCODE_GROUP_KEY_OPCODE_BITS 8 767 768 #define _BCM_SB2_OAM_OPCODE_GRP_KEY_FORM(proto, opcode) (\ 769 ((proto & _BCM_SB2_OAM_OPCODE_GROUP_KEY_PROTO_MASK) \ 770 << _BCM_SB2_OAM_OPCODE_GROUP_KEY_OPCODE_BITS) |\ 771 (opcode & _BCM_SB2_OAM_OPCODE_GROUP_KEY_OPCODE_MASK)) 772 #define _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(opcode) \ 773 (_BCM_SB2_OAM_OPCODE_GRP_KEY_FORM(_BCM_SB2_OAM_OPCODE_GRP_PROTO_ETH, \ 774 opcode)) 775 776 #define _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(opcode) \ 777 (_BCM_SB2_OAM_OPCODE_GRP_KEY_FORM(_BCM_SB2_OAM_OPCODE_GRP_PROTO_BHH, \ 778 opcode)) 779 780 #define _BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(opcode) \ 781 (_BCM_SB2_OAM_OPCODE_GRP_KEY_FORM(_BCM_SB2_OAM_OPCODE_GRP_PROTO_MPLS_LMDM, \ 782 opcode)) 783 784 785 /* Ethernet OAM opcode groups */ 786 #define _BCM_SB2_OPCODE_GROUP_ETH_OAM_CCM 3 787 #define _BCM_SB2_OPCODE_GROUP_ETH_OAM_LBR 4 788 #define _BCM_SB2_OPCODE_GROUP_ETH_OAM_LBM 5 789 #define _BCM_SB2_OPCODE_GROUP_ETH_OAM_LTR 4 790 #define _BCM_SB2_OPCODE_GROUP_ETH_OAM_LTM 6 791 792 #define _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 7 793 #define _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 8 794 795 /* BHH OAM opcode groups */ 796 #define _BCM_SB2_OPCODE_GROUP_BHH_OAM_CCM 9 797 #define _BCM_SB2_OPCODE_GROUP_BHH_OAM_LBR 10 798 #define _BCM_SB2_OPCODE_GROUP_BHH_OAM_LBM 11 799 #define _BCM_SB2_OPCODE_GROUP_BHH_OAM_LTR 12 800 #define _BCM_SB2_OPCODE_GROUP_BHH_OAM_LTM 13 801 802 #define _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 14 803 #define _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 15 804 805 /* MPLS LM DM opcode groups */ 806 #define _BCM_SB2_OPCODE_GROUP_MPLS_LM 0 807 #define _BCM_SB2_OPCODE_GROUP_MPLS_ILM 1 808 #define _BCM_SB2_OPCODE_GROUP_MPLS_DM 1 809 #define _BCM_SB2_OPCODE_GROUP_MPLS_LM_PLUS_DM 2 810 #define _BCM_SB2_OPCODE_GROUP_MPLS_ILM_PLUS_DM 2 811 812 #define _BCM_SB2_OAM_DEFAULT_OPCODE_PROFILE_INDEX 0 813 #define _BCM_SB2_OAM_NUM_OPCODE_GROUPS 16 814 815 #define _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE _BCM_SB2_OAM_NUM_OPCODE_GROUPS 816 817 /* ING LM COUNT PROFILE TABLE entries per profile(256 - Max no. of OAM opcode */ 818 #define _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE bcmOamOpcodeMax 819 820 /* CPU_OPCODE is filled one of these values */ 821 #define _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW 0 822 #define _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM 1 823 #define _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH 2 824 825 /* OLP_HDR_TYPE_COMPRESSED is filled with one of the below values. 826 * 827 * NOTE: BFD always has olp hdr type compressed to 0. HW automatically fills it. 828 * Should not be changed. 829 */ 830 831 #define _BCM_SB2_NO_OF_BITS_COMP_HDR 5 832 #define _BCM_SB2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET(comp_hdr) \ 833 ((1 << _BCM_SB2_NO_OF_BITS_COMP_HDR) | comp_hdr) 834 835 #define _BCM_SB2_BFD_OLP_HDR_TYPE_COMPRESSED 0 836 837 #define _BCM_SB2_ETH_OAM_CCM_OLP_HDR_TYPE_COMPRESSED 1 838 #define _BCM_SB2_ETH_OAM_LM_OLP_HDR_TYPE_COMPRESSED 2 839 #define _BCM_SB2_ETH_OAM_DM_OLP_HDR_TYPE_COMPRESSED 3 840 #define _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED 4 841 842 #define _BCM_SB2_BHH_CCM_OLP_HDR_TYPE_COMPRESSED 5 843 #define _BCM_SB2_BHH_LM_OLP_HDR_TYPE_COMPRESSED 6 844 #define _BCM_SB2_BHH_DM_OLP_HDR_TYPE_COMPRESSED 7 845 #define _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED 8 846 847 #define _BCM_SB2_MPLS_LMDM_DLM_OLP_HDR_TYPE_COMPRESSED 9 848 #define _BCM_SB2_MPLS_LMDM_DM_OLP_HDR_TYPE_COMPRESSED 10 849 #define _BCM_SB2_MPLS_LMDM_DLM_DM_OLP_HDR_TYPE_COMPRESSED 11 850 #define _BCM_SB2_MPLS_LMDM_ILM_OLP_HDR_TYPE_COMPRESSED 12 851 #define _BCM_SB2_MPLS_LMDM_ILM_DM_OLP_HDR_TYPE_COMPRESSED 13 852 #define _BCM_SB2_SAT_DOWNMEP_OLP_HDR_COMPRESSED 14 853 #define _BCM_SB2_OTH_ACH_OLP_HDR_COMPRESSED 15 854 855 #define _BCM_SB2_ETH_OAM_UP_MEP_CCM_OLP_HDR_TYPE_COMPRESSED \ 856 _BCM_SB2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET( \ 857 _BCM_SB2_ETH_OAM_CCM_OLP_HDR_TYPE_COMPRESSED) 858 859 #define _BCM_SB2_ETH_OAM_UP_MEP_LM_OLP_HDR_TYPE_COMPRESSED \ 860 _BCM_SB2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET( \ 861 _BCM_SB2_ETH_OAM_LM_OLP_HDR_TYPE_COMPRESSED) 862 863 #define _BCM_SB2_ETH_OAM_UP_MEP_DM_OLP_HDR_TYPE_COMPRESSED \ 864 _BCM_SB2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET( \ 865 _BCM_SB2_ETH_OAM_DM_OLP_HDR_TYPE_COMPRESSED) 866 867 #define _BCM_SB2_ETH_OAM_UP_MEP_OTHER_OC_OLP_HDR_TYPE_COMPRESSED \ 868 _BCM_SB2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET( \ 869 _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED) 870 871 #define _BCM_SAT_UPMEP_OLP_HDR_COMPRESSED \ 872 _BCM_SB2_UP_MEP_OLP_HDR_TYPE_COMPRESSED_GET( \ 873 _BCM_SB2_SAT_DOWNMEP_OLP_HDR_COMPRESSED) 874 875 /* OAM_OPCODE_CONTROL_PROFILE profile sizes */ 876 #define _BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE (sizeof(oam_opcode_control_profile_entry_t) *\ 877 _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE) 878 #define _BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE (sizeof(egr_oam_opcode_control_profile_entry_t) *\ 879 _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE) 880 /* ING_OAM_LM_COUNTER_CONTROL_PROFILE profile sizes */ 881 #define _BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE (sizeof(ing_lm_counter_control_entry_t) *\ 882 _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE) 883 #define _BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE (sizeof(egr_lm_counter_control_entry_t) *\ 884 _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE) 885 886 /* 4 bits from opcode group form lower 4 bits of profile index */ 887 #define NO_OF_BITS_OC_GRP 4 888 /* 8 bits from lm count profile form lower 8 bits of profile index */ 889 #define NO_OF_BITS_LM_COUNT_PROFILE 8 890 /* Oam opcode control Profile pointer from profile index and vice versa */ 891 #define _BCM_SB2_OAM_GET_PROFILE_PTR_FROM_INDEX(index) (index >> NO_OF_BITS_OC_GRP) 892 #define _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(ptr) (ptr << NO_OF_BITS_OC_GRP) 893 894 /* Oam opcode control Profile pointer from profile index and vice versa */ 895 #define _BCM_ML_OAM_GET_LM_COUNTER_CONTROL_PROFILE_PTR_FROM_INDEX(index) (index >> NO_OF_BITS_LM_COUNT_PROFILE) 896 #define _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(ptr) (ptr << NO_OF_BITS_LM_COUNT_PROFILE) 897 898 /* OLP_HEADER_TYPE filled with one of the following values. 899 * TX is never filled in mapping table since OLP_TX header doesnt use 900 * the mapping table. 901 */ 902 #define _BCM_SB2_OLP_HDR_TYPE_TX 0 903 #define _BCM_SB2_OLP_HDR_TYPE_RX 1 904 905 /* No. of counter pool that can be programmed per endpoint */ 906 #define _SB2_OAM_COUNTER_SIZE 3 907 908 /* OLP_HEADER_SUBTYPE filled with one of the following values */ 909 /* Down mep subtypes */ 910 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_CCM 0x01 911 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_LM 0x02 912 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_DM 0x03 913 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_OTHER_OC 0x04 914 #define _BCM_SB2_OLP_HDR_SUBTYPE_BHH_CCM 0x05 915 #define _BCM_SB2_OLP_HDR_SUBTYPE_BHH_LM 0x06 916 #define _BCM_SB2_OLP_HDR_SUBTYPE_BHH_DM 0x07 917 #define _BCM_SB2_OLP_HDR_SUBTYPE_BHH_OTHER_OC 0x08 918 #define _BCM_SB2_OLP_HDR_SUBTYPE_BFD 0x09 919 #define _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM 0x0A 920 #define _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_DM 0x0B 921 #define _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM_DM 0x0C 922 #define _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM 0x0D 923 #define _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM_DM 0x0E 924 #define _BCM_SB2_OLP_HDR_SUBTYPE_SAT 0x0F 925 #define _BCM_SB2_OLP_HDR_SUBTYPE_OTH_ACH 0x10 926 927 /* Up mep subtypes */ 928 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_CCM 0x11 929 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_LM 0x12 930 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_DM 0x13 931 #define _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_OTHER_OC 0x14 932 #define _BCM_SB2_OLP_HDR_SUBTYPE_SAT_UP 0x15 933 934 935 936 /* Possible values for MPLS_OAM_DOWNMEP_ENABLE field in MPLS_ENTRY memory */ 937 #define _BCM_SB2_MPLS_OAM_DISABLE 0 938 #define _BCM_SB2_MPLS_OAM_ENABLE_BHH 1 939 #define _BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM 2 940 #define _BCM_SB2_MPLS_OAM_ENABLE_RESERVED 3 941 942 /* Key formation and profile mapping ptr logic for 943 ING/EGR_SERVICE_PRI_MAP_0/1/2 table */ 944 #define NO_OF_BITS_FOR_PRI 4 945 #define _BCM_SB2_SERVICE_PRI_MAP_PROFILE_INDEX_TO_MAP_PTR(profile_index) \ 946 (profile_index >> NO_OF_BITS_FOR_PRI) 947 #define _BCM_SB2_SERVICE_PRI_MAP_PTR_TO_PROFILE_INDEX(map_ptr) \ 948 (map_ptr << NO_OF_BITS_FOR_PRI) 949 950 /* The default ING/EGR_SERVICE_PRI_MAP_0/1/2 would be 0 */ 951 #define _BCM_OAM_PRI_MAP_DEFAULT_INDEX 0 952 953 /* The valid ctr pool ids are 0/1/2 */ 954 #define _BCM_SB2_OAM_VALID_CTR_POOL_ID(ctr_pool_id) \ 955 (ctr_pool_id >= 0 && ctr_pool_id <= 2) 956 957 typedef struct _oam_tpid_s { 958 uint32 tpid; 959 uint32 ref_count; 960 } _oam_tpid_t; 961 962 typedef struct _bcm_sb2_opcode_group_entry_s { 963 int key; 964 int opcode_group; 965 int cpu_opcode; 966 int olp_hdr_type_compressed; 967 } _bcm_sb2_opcode_group_entry_t; 968 969 typedef struct _bcm_sb2_mpls_oam_ach_type_config_entry_s { 970 int valid; 971 int ach_type; 972 int opcode_valid; 973 int opcode; 974 int lm_count_enable; 975 int protocol_type; 976 } _bcm_sb2_mpls_oam_ach_type_config_entry_t; 977 978 #define BCM_MAX_TPID_ENTRIES 4 979 #define BCM_MAX_INNER_TPID_ENTRIES 1 980 981 982 #define BCM_OAM_TPID_TYPE_OUTER 0 983 #define BCM_OAM_TPID_TYPE_INNER 1 984 #define BCM_OAM_TPID_TYPE_SUBPORT 2 985 #define BCM_OAM_TPID_VALUE_ZERO 0 986 #define BCM_OAM_DEFAULT_TPID 0x8100 987 #define BCM_OAM_TPID_9100 0x9100 988 #define BCM_OAM_TPID_88A8 0x88A8 989 #define DGLP_LAG_ID_INDICATOR_SHIFT_BITS 15 990 #define _BCM_OAM_OPCODE_TYPE_CCM 1 991 #define _BCM_OAM_OPCODE_TYPE_LBR 2 992 #define _BCM_OAM_OPCODE_TYPE_LBM 3 993 #define _BCM_OAM_OPCODE_TYPE_LTR 4 994 #define _BCM_OAM_OPCODE_TYPE_LTM 5 995 #define _BCM_OAM_OPCODE_TYPE_NON_CFM_FIRST 6 996 #define _BCM_OAM_OPCODE_TYPE_AIS 33 997 #define _BCM_OAM_OPCODE_TYPE_LCK 35 998 #define _BCM_OAM_OPCODE_TYPE_TST 37 999 #define _BCM_OAM_OPCODE_TYPE_LIN_APS 39 1000 #define _BCM_OAM_OPCODE_TYPE_RING_APS 40 1001 #define _BCM_OAM_OPCODE_TYPE_MCC 41 1002 #define _BCM_OAM_OPCODE_TYPE_LMM 43 1003 #define _BCM_OAM_OPCODE_TYPE_LMR 42 1004 #define _BCM_OAM_OPCODE_TYPE_1DM 45 1005 #define _BCM_OAM_OPCODE_TYPE_DMM 47 1006 #define _BCM_OAM_OPCODE_TYPE_DMR 46 1007 #define _BCM_OAM_OPCODE_TYPE_EXM 49 1008 #define _BCM_OAM_OPCODE_TYPE_EXR 48 1009 #define _BCM_OAM_OPCODE_TYPE_VSM 51 1010 #define _BCM_OAM_OPCODE_TYPE_VSR 50 1011 #define _BCM_OAM_OPCODE_TYPE_SLR 54 1012 #define _BCM_OAM_OPCODE_TYPE_SLM 55 1013 #define _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST 0xFF 1014 #define _BCM_OAM_OPCODE_TYPE_CFM_MASK 0x3E 1015 #define _BCM_OAM_OPCODE_TYPE_NON_CFM_MASK 0xFFFFFFFF 1016 #define _BCM_OAM_DGLP1_PROFILE_PTR 0x1 1017 #define _BCM_OAM_DGLP2_PROFILE_PTR 0x2 1018 #define _BCM_OAM_SERVICE_PRI_MAX_OFFSET 0x7 1019 1020 STATIC _oam_tpid_t 1021 (*_sb2_oam_outer_tpid_tab[BCM_MAX_NUM_UNITS])[BCM_MAX_TPID_ENTRIES]; 1022 1023 STATIC _oam_tpid_t 1024 (*_sb2_oam_inner_tpid_tab[BCM_MAX_NUM_UNITS])[BCM_MAX_INNER_TPID_ENTRIES]; 1025 1026 STATIC _oam_tpid_t 1027 (*_sb2_oam_subport_tpid_tab[BCM_MAX_NUM_UNITS])[BCM_MAX_TPID_ENTRIES]; 1028 1029 STATIC sal_mutex_t _sb2_outer_tpid_lock[BCM_MAX_NUM_UNITS]; 1030 STATIC sal_mutex_t _sb2_inner_tpid_lock[BCM_MAX_NUM_UNITS]; 1031 STATIC sal_mutex_t _sb2_subport_tpid_lock[BCM_MAX_NUM_UNITS]; 1032 1033 /* OAM TPID registers and default values */ 1034 STATIC int sb2_outer_tpid[4] = { OUTER_TPID_0r, OUTER_TPID_1r, 1035 OUTER_TPID_2r, OUTER_TPID_3r }; 1036 1037 STATIC int sb2_default_outer_tpid[4] = { BCM_OAM_DEFAULT_TPID, BCM_OAM_TPID_9100, 1038 BCM_OAM_TPID_88A8, BCM_OAM_TPID_VALUE_ZERO}; 1039 1040 STATIC int sb2_subport_tpid[4] = { SUBPORT_TAG_TPID_0r, SUBPORT_TAG_TPID_1r, 1041 SUBPORT_TAG_TPID_2r, SUBPORT_TAG_TPID_3r }; 1042 1043 #define SB2_OAM_OUTER_TPID_TAB(unit) _sb2_oam_outer_tpid_tab[unit] 1044 #define SB2_OAM_INNER_TPID_TAB(unit) _sb2_oam_inner_tpid_tab[unit] 1045 #define SB2_OAM_SUBPORT_TPID_TAB(unit) _sb2_oam_subport_tpid_tab[unit] 1046 1047 #define SB2_OAM_OUTER_TPID_ENTRY(unit, index) \ 1048 ((*_sb2_oam_outer_tpid_tab[unit])[index].tpid) 1049 1050 #define SB2_OAM_INNER_TPID_ENTRY(unit, index) \ 1051 ((*_sb2_oam_inner_tpid_tab[unit])[index].tpid) 1052 1053 #define SB2_OAM_SUBPORT_TPID_ENTRY(unit, index) \ 1054 ((*_sb2_oam_subport_tpid_tab[unit])[index].tpid) 1055 1056 #define SB2_OAM_OUTER_TPID_REF_COUNT(unit, index) \ 1057 ((*_sb2_oam_outer_tpid_tab[unit])[index].ref_count) 1058 1059 #define SB2_OAM_INNER_TPID_REF_COUNT(unit, index) \ 1060 ((*_sb2_oam_inner_tpid_tab[unit])[index].ref_count) 1061 1062 #define SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, index) \ 1063 ((*_sb2_oam_subport_tpid_tab[unit])[index].ref_count) 1064 1065 #define SB2_OAM_OUTER_TPID_TAB_INIT_CHECK(unit) \ 1066 if (SB2_OAM_OUTER_TPID_TAB(unit) == NULL) { return BCM_E_INIT; } 1067 1068 #define SB2_OAM_INNER_TPID_TAB_INIT_CHECK(unit) \ 1069 if (SB2_OAM_INNER_TPID_TAB(unit) == NULL) { return BCM_E_INIT; } 1070 1071 #define SB2_OAM_SUBPORT_TPID_TAB_INIT_CHECK(unit) \ 1072 if (SB2_OAM_SUBPORT_TPID_TAB(unit) == NULL) { return BCM_E_INIT; } 1073 1074 #define BCM_SB2_OUTER_TPID_MUTEX(_u_) _sb2_outer_tpid_lock[_u_] 1075 #define BCM_SB2_INNER_TPID_MUTEX(_u_) _sb2_inner_tpid_lock[_u_] 1076 #define BCM_SB2_SUBPORT_TPID_MUTEX(_u_) _sb2_subport_tpid_lock[_u_] 1077 1078 #define BCM_SB2_OUTER_TPID_LOCK(_u_) \ 1079 ((_sb2_outer_tpid_lock[_u_]) ? \ 1080 sal_mutex_take(_sb2_outer_tpid_lock[_u_], sal_mutex_FOREVER) : \ 1081 (BCM_E_INTERNAL)) 1082 1083 #define BCM_SB2_INNER_TPID_LOCK(_u_) \ 1084 ((_sb2_inner_tpid_lock[_u_]) ? \ 1085 sal_mutex_take(_sb2_inner_tpid_lock[_u_], sal_mutex_FOREVER) : \ 1086 (BCM_E_INTERNAL)) 1087 1088 #define BCM_SB2_SUBPORT_TPID_LOCK(_u_) \ 1089 ((_sb2_subport_tpid_lock[_u_]) ? \ 1090 sal_mutex_take(_sb2_subport_tpid_lock[_u_], sal_mutex_FOREVER) : \ 1091 (BCM_E_INTERNAL)) 1092 1093 #define BCM_SB2_OUTER_TPID_UNLOCK(_u_) \ 1094 ((_sb2_outer_tpid_lock[_u_]) ? \ 1095 sal_mutex_give(_sb2_outer_tpid_lock[_u_]) : \ 1096 (BCM_E_INTERNAL)) 1097 1098 #define BCM_SB2_INNER_TPID_UNLOCK(_u_) \ 1099 ((_sb2_inner_tpid_lock[_u_]) ? \ 1100 sal_mutex_give(_sb2_inner_tpid_lock[_u_]) : \ 1101 (BCM_E_INTERNAL)) 1102 1103 #define BCM_SB2_SUBPORT_TPID_UNLOCK(_u_) \ 1104 ((_sb2_subport_tpid_lock[_u_]) ? \ 1105 sal_mutex_give(_sb2_subport_tpid_lock[_u_]) : \ 1106 (BCM_E_INTERNAL)) 1107 1108 /* Checks hash_data pointer's int_flags field */ 1109 #define _BCM_OAM_ETH_OAM_VP_TYPE(type, int_flags) \ 1110 ((type == bcmOAMEndpointTypeEthernet)\ 1111 && (int_flags & _BCM_OAM_ENDPOINT_IS_VP_BASED)) 1112 #define _BCM_OAM_EP_IS_ETH_OAM_VP_TYPE(h_data_p) \ 1113 (_BCM_OAM_ETH_OAM_VP_TYPE(h_data_p->type, h_data_p->int_flags)) 1114 1115 1116 /* * * * * * * * * * * * * * * * * * * * * * * * * 1117 * OAM function prototypes * 1118 */ 1119 1120 int _bcm_sb2_oam_convert_action_to_opcode_entry( 1121 int unit, 1122 bcm_oam_endpoint_action_t *action, 1123 bcm_oam_endpoint_t ep_id, 1124 void *profile, 1125 uint8 *opcode_profile_changed); 1126 int 1127 _sb2_oam_opcode_control_field_set(int unit, _bcm_oam_hash_data_t *h_data_p, 1128 bcm_oam_action_type_t action, 1129 soc_mem_t mem, int oam_opcode, uint32 value, 1130 void *profile); 1131 1132 int 1133 _bcm_sb2_oam_mpls_lsp_check_l3_tunnel_table_downmep_enable(int unit, 1134 _bcm_oam_hash_data_t *hash_data, int enable); 1135 int 1136 _bcm_sb2_oam_mpls_lsp_mpls_table_downmep_enable(int unit, 1137 _bcm_oam_hash_data_t *hash_data, int enable); 1138 int 1139 _bcm_sb2_oam_mpls_pw_egr_dvp_downmep_enable(int unit, 1140 _bcm_oam_hash_data_t *hash_data, int enable); 1141 int 1142 _bcm_sb2_oam_mpls_lsp_egr_l3_nxt_hop_downmep_enable(int unit, 1143 _bcm_oam_hash_data_t *hash_data, int enable); 1144 int 1145 _bcm_sb2_oam_mpls_pw_svp_table_downmep_enable(int unit, 1146 _bcm_oam_hash_data_t *hash_data, int enable); 1147 1148 #if defined(INCLUDE_ETH_LM_DM) || defined (INCLUDE_MPLS_LM_DM) || defined (INCLUDE_BHH) 1149 STATIC int 1150 _bcm_sb2_oam_olp_encap_header_decap(int unit, 1151 uint8 *encap_data, 1152 uint8 *counter_size, 1153 uint32 *counter_base_id, 1154 uint32 *counter_offset, 1155 uint8 *counter_action, 1156 uint8 *ts_mode, 1157 uint8 *lm_pdu_counter_offset, 1158 bcm_cos_t *int_pri, 1159 uint32 *counter_lm_counter_byte_offset); 1160 #endif 1161 1162 /* * * * * * * * * * * * * * * * * * * * * * * * * 1163 * OAM global data initialization * 1164 */ 1165 #if defined(INCLUDE_BHH) 1166 1167 #define BHH_COSQ_INVALID 0xFFFF 1168 1169 static uint8 bhh_lsp_egr_lookup_key = _BCM_SB2_OAM_EGR_LSP_MEP_LOOKUP_KEY_EP_ID; 1170 /* 1171 * Macro: 1172 * _BCM_OAM_BHH_IS_VALID (internal) 1173 * Purpose: 1174 * Check that the BHH feature is available on this unit 1175 * Parameters: 1176 * unit - BCM device number 1177 * Notes: 1178 * Results in return(BCM_E_UNAVAIL), 1179 */ 1180 #define _BCM_OAM_BHH_IS_VALID(unit) \ 1181 do { \ 1182 if (!soc_feature(unit, soc_feature_bhh)) { \ 1183 return (BCM_E_UNAVAIL); \ 1184 } \ 1185 } while (0) 1186 1187 #define BCM_OAM_BHH_GET_UKERNEL_EP(ep) \ 1188 (ep - _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc)) 1189 1190 #define BCM_OAM_BHH_GET_LSP_KEY(hash_data) \ 1191 ((bhh_lsp_egr_lookup_key == _BCM_SB2_OAM_EGR_LSP_MEP_LOOKUP_KEY_MEP_ID) ? \ 1192 ((hash_data)->name) : \ 1193 ((hash_data)->ep_id - _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc) + 1)) 1194 1195 #define BCM_OAM_BHH_GET_SDK_EP(ep) \ 1196 (ep + _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc)) 1197 1198 #define BCM_OAM_BHH_VALIDATE_EP(_ep_) \ 1199 do { \ 1200 if (((_ep_) < _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc)) || \ 1201 ((_ep_) >= (_BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc) \ 1202 + oc->bhh_endpoint_count))) { \ 1203 LOG_ERROR(BSL_LS_BCM_OAM, \ 1204 (BSL_META_U(unit, \ 1205 "OAM(unit %d) Error: Invalid Endpoint ID" \ 1206 " = %d.\n"), unit, _ep_)); \ 1207 _BCM_OAM_UNLOCK(oc); \ 1208 return (BCM_E_PARAM); \ 1209 } \ 1210 } while (0); 1211 1212 1213 STATIC int 1214 _bcm_sb2_oam_bhh_msg_send_receive(int unit, uint8 s_subclass, 1215 uint16 s_len, uint32 s_data, 1216 uint8 r_subclass, uint16 *r_len); 1217 1218 STATIC int 1219 _bcm_sb2_oam_bhh_hw_init(int unit); 1220 STATIC void 1221 _bcm_sb2_oam_bhh_callback_thread(void *param); 1222 STATIC int 1223 _bcm_sb2_oam_bhh_event_mask_set(int unit); 1224 STATIC int 1225 bcm_sb2_oam_bhh_endpoint_create(int unit, 1226 bcm_oam_endpoint_info_t *endpoint_info, 1227 _bcm_oam_hash_key_t *hash_key); 1228 STATIC int 1229 bcm_sb2_oam_bhh_endpoint_ccm_ctr_update(int unit, 1230 bcm_oam_endpoint_info_t *ep_info); 1231 STATIC uint8 * 1232 _bcm_sb2_oam_bhh_mpls_label_unpack(uint8 *buffer, _mpls_label_t *mpls); 1233 1234 STATIC void 1235 _bcm_sb2_oam_bhh_get_egress_label_from_encap(_bcm_oam_hash_data_t *h_data_p, 1236 uint8 *encap_data, 1237 uint16 encap_length, 1238 _mpls_label_t *label); 1239 1240 #endif /* INCLUDE_BHH */ 1241 1242 #define BCM_OAM_ABS(x) (((x) < 0) ? (-(x)) : (x)) 1243 1244 #if defined(INCLUDE_ETH_LM_DM) 1245 1246 #define SB2_ETH_LM_DM_UC_NUM 2 1247 #define ML_ETH_LM_DM_UC_NUM 0 1248 1249 #define BCM_SB2_ETH_LM_DM_RX_CHANNEL 11 1250 #define BCM_ML_ETH_LM_DM_RX_CHANNEL 5 1251 #define BCM_SB2_ETH_LM_DM_UC_RX_CHANNEL 1 /* Rx DMA channel uC view (0..3 ) */ 1252 #define BCM_SB2_ETH_LM_DM_CPU_COS 45 1253 #define BCM_ML_ETH_LM_DM_CPU_COS 37 1254 1255 STATIC int 1256 _bcm_sb2_oam_eth_lm_dm_msg_send_receive(int unit, uint8 s_subclass, 1257 uint16 s_len, uint32 s_data, 1258 uint8 r_subclass, uint16 *r_len); 1259 STATIC int 1260 _bcm_sb2_oam_eth_lm_dm_hw_init(int unit); 1261 1262 #endif /* INCLUDE_ETH_LM_DM */ 1263 1264 #if defined(INCLUDE_MPLS_LM_DM) 1265 1266 #define MPLS_LM_DM_COSQ_INVALID 0xFFFF 1267 #define MPLS_LM_DM_UC_NUM 2 1268 #define MPLS_LM_DM_MAX_SESSIONS 256 1269 1270 #define MPLS_LM_DM_RX_CHANNEL_SDK_VIEW 11 1271 #define MPLS_LM_DM_RX_CHANNEL_UC_VIEW 1 1272 #define MPLS_LM_DM_CPU_COS 45 1273 1274 #define _MPLS_LM_DM_MPLS_MAX_LABELS 4 /* Max MPLS labels in Saber2 */ 1275 1276 1277 STATIC int 1278 _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(int unit, uint8 s_subclass, 1279 uint16 s_len, uint32 s_data, 1280 uint8 r_subclass, uint16 *r_len); 1281 1282 STATIC int 1283 _bcm_sb2_oam_mpls_lm_dm_hw_init(int unit); 1284 1285 #if defined(BCM_METROLITE_SUPPORT) 1286 STATIC int 1287 _bcm_ml_oam_mpls_lm_dm_hw_init(int unit); 1288 #endif /* BCM_METROLITE_SUPPORT */ 1289 1290 #endif /* INCLUDE_MPLS_LM_DM */ 1291 1292 1293 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM) 1294 STATIC int 1295 bcm_sb2_oam_convert_ep_to_time_spec(bcm_time_spec_t* bts, int sec, int ns); 1296 #endif 1297 STATIC int 1298 _bcm_sb2_oam_pm_msg_send_receive(int unit, uint8 s_class, uint8 s_subclass, 1299 uint16 s_len, uint32 s_data, 1300 uint8 r_subclass, uint16 *r_len); 1301 1302 #if defined (INCLUDE_BHH) || defined (INCLUDE_ETH_LM_DM) || defined (INCLUDE_MPLS_LM_DM) 1303 STATIC void _bcm_sb2_oam_pm_event_msg_handle(_bcm_oam_control_t *oc, 1304 mos_msg_data_t *event_msg); 1305 #endif 1306 1307 int _bcm_sb2_oam_pm_init(int unit); 1308 1309 int 1310 _bcm_sb2_oam_mpls_entry_label_lookup(int unit, bcm_mpls_label_t label, 1311 uint32 sglp, int *mpls_index, 1312 mpls_entry_entry_t *found_entry); 1313 1314 STATIC int 1315 bcm_sb2_oam_hw_ccm_tx_ctr_update(int unit, 1316 bcm_oam_endpoint_info_t *ep_info); 1317 1318 #define _BCM_SB2_OAM_MAX_CCM_INTERVALS 8 1319 /* 1320 * Saber2 device OAM CCM intervals array initialization.. 1321 */ 1322 STATIC uint32 _sb2_ccm_intervals[] = 1323 { 1324 BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED, 1325 BCM_OAM_ENDPOINT_CCM_PERIOD_3MS, 1326 BCM_OAM_ENDPOINT_CCM_PERIOD_10MS, 1327 BCM_OAM_ENDPOINT_CCM_PERIOD_100MS, 1328 BCM_OAM_ENDPOINT_CCM_PERIOD_1S, 1329 BCM_OAM_ENDPOINT_CCM_PERIOD_10S, 1330 BCM_OAM_ENDPOINT_CCM_PERIOD_1M, 1331 BCM_OAM_ENDPOINT_CCM_PERIOD_10M, 1332 _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED 1333 }; 1334 1335 /* 1336 * OAM hardware interrupts to software events mapping array initialization. 1337 * _sb2_oam_interrupts[] = 1338 * {Interrupt status register, Remote MEP index field, MA index field, 1339 * CCM_INTERRUPT_CONTROLr - Interrupt status Field, 1340 * OAM event type}. 1341 */ 1342 STATIC _bcm_oam_interrupt_t _sb2_oam_interrupts[] = 1343 { 1344 /* 1. Port down interrupt. */ 1345 {ANY_RMEP_TLV_PORT_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 1346 ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf, 1347 bcmOAMEventEndpointPortDown}, 1348 1349 /* 2. Port up interrupt. */ 1350 {ANY_RMEP_TLV_PORT_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 1351 ANY_RMEP_TLV_PORT_UP_INT_ENABLEf, 1352 bcmOAMEventEndpointPortUp}, 1353 1354 /* 3. Interface down interrupt. */ 1355 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 1356 ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf, 1357 bcmOAMEventEndpointInterfaceDown}, 1358 1359 /* 4. Interface up interrupt. */ 1360 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 1361 ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf, 1362 bcmOAMEventEndpointInterfaceUp}, 1363 1364 /* 5. Interface TLV Testing to Up interrupt. */ 1365 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 1366 ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf, 1367 bcmOAMEventEndpointInterfaceTestingToUp}, 1368 1369 /* 6. Interface TLV Unknown to Up interrupt. */ 1370 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 1371 ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf, 1372 bcmOAMEventEndpointInterfaceUnknownToUp}, 1373 1374 /* 7. Interface TLV Dormant to Up interrupt. */ 1375 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 1376 ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf, 1377 bcmOAMEventEndpointInterfaceDormantToUp}, 1378 1379 /* 8. Interface TLV Not present to Up interrupt. */ 1380 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 1381 ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf, 1382 bcmOAMEventEndpointInterfaceNotPresentToUp}, 1383 1384 /* 9. Interface Link Layer Down to Up interrupt. */ 1385 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 1386 ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf, 1387 bcmOAMEventEndpointInterfaceLLDownToUp}, 1388 1389 /* 10. Interface up to testing transition interrupt. */ 1390 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 1391 ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf, 1392 bcmOAMEventEndpointInterfaceTesting}, 1393 1394 /* 11. Interface up to unknown transition interrupt. */ 1395 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 1396 ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf, 1397 bcmOAMEventEndpointInterfaceUnkonwn}, 1398 1399 /* 11. Interface up to dormant transition interrupt. */ 1400 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 1401 ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf, 1402 bcmOAMEventEndpointInterfaceDormant}, 1403 1404 /* 11. Interface up to not present transition interrupt. */ 1405 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 1406 ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf, 1407 bcmOAMEventEndpointInterfaceNotPresent}, 1408 1409 /* 11. Interface up to Link Layer Down transition interrupt. */ 1410 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 1411 ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf, 1412 bcmOAMEventEndpointInterfaceLLDown}, 1413 1414 /* 12. Low MDL or unexpected MAID interrupt. */ 1415 {XCON_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf, 1416 XCON_CCM_DEFECT_INT_ENABLEf, 1417 bcmOAMEventGroupCCMxcon}, 1418 1419 /* 1420 * 13. Remote MEP lookup failed or CCM interval mismatch during Remote MEP 1421 * lookup interrupt. 1422 */ 1423 {ERROR_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf, 1424 ERROR_CCM_DEFECT_INT_ENABLEf, 1425 bcmOAMEventGroupCCMError}, 1426 1427 /* 1428 * 14. Some Remote defect indicator interrupt - aggregated health of remote 1429 * MEPs. 1430 */ 1431 {SOME_RDI_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf, 1432 SOME_RDI_DEFECT_INT_ENABLEf, 1433 bcmOAMEventGroupRemote}, 1434 1435 /* 15. Aggregate health of remote MEP state machines interrupt. */ 1436 {SOME_RMEP_CCM_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf, 1437 SOME_RMEP_CCM_DEFECT_INT_ENABLEf, 1438 bcmOAMEventGroupCCMTimeout}, 1439 1440 /* Invalid Interrupt - Always Last */ 1441 {INVALIDr, INVALIDf, 0, bcmOAMEventCount} 1442 }; 1443 1444 /* 1445 * 0AM Group faults array initialization. 1446 */ 1447 STATIC _bcm_oam_fault_t _sb2_oam_group_faults[] = 1448 { 1449 {CURRENT_XCON_CCM_DEFECTf, STICKY_XCON_CCM_DEFECTf, 1450 BCM_OAM_GROUP_FAULT_CCM_XCON, 0x08}, 1451 1452 {CURRENT_ERROR_CCM_DEFECTf, STICKY_ERROR_CCM_DEFECTf, 1453 BCM_OAM_GROUP_FAULT_CCM_ERROR, 0x04}, 1454 1455 {CURRENT_SOME_RMEP_CCM_DEFECTf, STICKY_SOME_RMEP_CCM_DEFECTf, 1456 BCM_OAM_GROUP_FAULT_CCM_TIMEOUT, 0x02}, 1457 1458 {CURRENT_SOME_RDI_DEFECTf, STICKY_SOME_RDI_DEFECTf, 1459 BCM_OAM_GROUP_FAULT_REMOTE, 0x01}, 1460 1461 {0, 0, 0, 0} 1462 }; 1463 1464 /* 1465 * 0AM Endpoint faults array initialization. 1466 */ 1467 STATIC _bcm_oam_fault_t _sb2_oam_endpoint_faults[] = 1468 { 1469 {CURRENT_RMEP_PORT_STATUS_DEFECTf, 1470 STICKY_RMEP_PORT_STATUS_DEFECTf, 1471 BCM_OAM_ENDPOINT_FAULT_PORT_DOWN, 0x08}, 1472 1473 {CURRENT_RMEP_INTERFACE_STATUS_DEFECTf, 1474 STICKY_RMEP_INTERFACE_STATUS_DEFECTf, 1475 BCM_OAM_ENDPOINT_FAULT_INTERFACE_DOWN, 0x04}, 1476 1477 {CURRENT_RMEP_CCM_DEFECTf, 1478 STICKY_RMEP_CCM_DEFECTf, 1479 BCM_OAM_ENDPOINT_FAULT_CCM_TIMEOUT, 0x20}, 1480 1481 {CURRENT_RMEP_LAST_RDIf, 1482 STICKY_RMEP_LAST_RDIf, 1483 BCM_OAM_ENDPOINT_FAULT_REMOTE, 0x10}, 1484 1485 {0, 0, 0, 0} 1486 }; 1487 1488 typedef struct _bcm_sb2_oam_intr_en_fields_s { 1489 soc_field_t field; 1490 uint32 value; 1491 } _bcm_sb2_oam_intr_en_fields_t; 1492 1493 STATIC _bcm_sb2_oam_intr_en_fields_t _sb2_oam_intr_en_fields[bcmOAMEventCount] = 1494 { 1495 /* 1496 * Note: 1497 * The order of hardware field names in the below initialization 1498 * code must match the event enum order in bcm_oam_event_type_t. 1499 */ 1500 { ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf, 1}, 1501 { ANY_RMEP_TLV_PORT_UP_INT_ENABLEf, 1}, 1502 { ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf, 1}, 1503 { ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf, 1}, 1504 { ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf, 1}, 1505 { ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf, 1}, 1506 { ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf, 1}, 1507 { ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf, 1}, 1508 { ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf, 1}, 1509 { ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf, 1}, 1510 { ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf, 1}, 1511 { ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf, 1}, 1512 { ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf, 1}, 1513 { ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf, 1}, 1514 { XCON_CCM_DEFECT_INT_ENABLEf, 1}, 1515 { ERROR_CCM_DEFECT_INT_ENABLEf, 1}, 1516 { SOME_RDI_DEFECT_INT_ENABLEf, 1}, 1517 { SOME_RMEP_CCM_DEFECT_INT_ENABLEf, 1}, 1518 { INVALIDf, 0}, 1519 { INVALIDf, 0}, 1520 { INVALIDf, 0}, 1521 { INVALIDf, 0}, 1522 { INVALIDf, 0}, 1523 { INVALIDf, 0}, 1524 { INVALIDf, 0}, 1525 { INVALIDf, 0}, 1526 { INVALIDf, 0}, 1527 { INVALIDf, 0}, 1528 { INVALIDf, 0} 1529 }; 1530 1531 /* LM counter related fields */ 1532 STATIC sb2_mep_ctr_info_t sb2_mep_ctr_info[] = { 1533 { CTR1_VALIDf, CTR1_BASE_PTRf, 1534 CTR1_MEP_TYPEf, CTR1_MEP_MDLf, 1535 CTR1_SERVICE_PRI_MAP_PROFILE_PTRf, 1536 CTR1_SERVICE_PRI_MAP_MODEf, 1537 CTR1_LM_PAYLOAD_OFFSETf, 1538 CTR1_LM_COS_OFFSETf, CTR1_POOL_IDf 1539 }, 1540 { CTR2_VALIDf, CTR2_BASE_PTRf, 1541 CTR2_MEP_TYPEf, CTR2_MEP_MDLf, 1542 CTR2_SERVICE_PRI_MAP_PROFILE_PTRf, 1543 CTR2_SERVICE_PRI_MAP_MODEf, 1544 CTR2_LM_PAYLOAD_OFFSETf, 1545 CTR2_LM_COS_OFFSETf, CTR2_POOL_IDf 1546 } 1547 }; 1548 1549 /* OLP header type mapping */ 1550 typedef struct _bcm_sb2_olp_hdr_type_mapping_s { 1551 bcm_field_olp_header_type_t field_olp_hdr_type; 1552 uint8 mem_index; 1553 uint8 subtype; 1554 } _bcm_sb2_olp_hdr_type_mapping_t; 1555 1556 1557 STATIC _bcm_sb2_olp_hdr_type_mapping_t sb2_olp_hdr_type_mapping[] = { 1558 1559 /* BFD */ 1560 {bcmFieldOlpHeaderTypeBfdOam, _BCM_SB2_BFD_OLP_HDR_TYPE_COMPRESSED, 1561 _BCM_SB2_OLP_HDR_SUBTYPE_BFD}, 1562 /* ETH OAM Down MEP */ 1563 {bcmFieldOlpHeaderTypeEthOamCcm, _BCM_SB2_ETH_OAM_CCM_OLP_HDR_TYPE_COMPRESSED, 1564 _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_CCM}, 1565 1566 {bcmFieldOlpHeaderTypeEthOamLm, _BCM_SB2_ETH_OAM_LM_OLP_HDR_TYPE_COMPRESSED, 1567 _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_LM}, 1568 1569 {bcmFieldOlpHeaderTypeEthOamDm, _BCM_SB2_ETH_OAM_DM_OLP_HDR_TYPE_COMPRESSED, 1570 _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_DM}, 1571 1572 {bcmFieldOlpHeaderTypeEthOamOthers, _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED, 1573 _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_OTHER_OC}, 1574 1575 /* BHH */ 1576 {bcmFieldOlpHeaderTypeBhhOamCcm, _BCM_SB2_BHH_CCM_OLP_HDR_TYPE_COMPRESSED, 1577 _BCM_SB2_OLP_HDR_SUBTYPE_BHH_CCM}, 1578 1579 {bcmFieldOlpHeaderTypeBhhOamLm, _BCM_SB2_BHH_LM_OLP_HDR_TYPE_COMPRESSED, 1580 _BCM_SB2_OLP_HDR_SUBTYPE_BHH_LM}, 1581 1582 {bcmFieldOlpHeaderTypeBhhOamDm, _BCM_SB2_BHH_DM_OLP_HDR_TYPE_COMPRESSED, 1583 _BCM_SB2_OLP_HDR_SUBTYPE_BHH_DM}, 1584 1585 {bcmFieldOlpHeaderTypeBhhOamOthers, _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED, 1586 _BCM_SB2_OLP_HDR_SUBTYPE_BHH_OTHER_OC}, 1587 1588 /* MPLS LM/DM */ 1589 {bcmFieldOlpHeaderTypeRfc6374Dlm, _BCM_SB2_MPLS_LMDM_DLM_OLP_HDR_TYPE_COMPRESSED, 1590 _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM}, 1591 1592 {bcmFieldOlpHeaderTypeRfc6374Dm, _BCM_SB2_MPLS_LMDM_DM_OLP_HDR_TYPE_COMPRESSED, 1593 _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_DM}, 1594 1595 {bcmFieldOlpHeaderTypeRfc6374DlmPlusDm, _BCM_SB2_MPLS_LMDM_DLM_DM_OLP_HDR_TYPE_COMPRESSED, 1596 _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_DLM_DM}, 1597 1598 {bcmFieldOlpHeaderTypeRfc6374Ilm, _BCM_SB2_MPLS_LMDM_ILM_OLP_HDR_TYPE_COMPRESSED, 1599 _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM}, 1600 1601 {bcmFieldOlpHeaderTypeRfc6374IlmPlusDm, _BCM_SB2_MPLS_LMDM_ILM_DM_OLP_HDR_TYPE_COMPRESSED, 1602 _BCM_SB2_OLP_HDR_SUBTYPE_MPLS_LMDM_ILM_DM}, 1603 1604 1605 /* Down SAT */ 1606 {bcmFieldOlpHeaderTypeSat, _BCM_SB2_SAT_DOWNMEP_OLP_HDR_COMPRESSED, 1607 _BCM_SB2_OLP_HDR_SUBTYPE_SAT}, 1608 1609 /* Other ACH */ 1610 {bcmFieldOlpHeaderTypeOtherAch, _BCM_SB2_OTH_ACH_OLP_HDR_COMPRESSED, 1611 _BCM_SB2_OLP_HDR_SUBTYPE_OTH_ACH}, 1612 1613 /* 1614 * UpMEP header types are not programmable by FP, but OAM pipeline lookup 1615 * can assign UpMEP subtypes. 1616 */ 1617 1618 /* ETH-OAM Up MEP */ 1619 {bcmFieldOlpHeaderTypeEthOamUpMepCcm, _BCM_SB2_ETH_OAM_UP_MEP_CCM_OLP_HDR_TYPE_COMPRESSED, 1620 _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_CCM}, 1621 1622 {bcmFieldOlpHeaderTypeEthOamUpMepLm, _BCM_SB2_ETH_OAM_UP_MEP_LM_OLP_HDR_TYPE_COMPRESSED, 1623 _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_LM}, 1624 1625 {bcmFieldOlpHeaderTypeEthOamUpMepDm, _BCM_SB2_ETH_OAM_UP_MEP_DM_OLP_HDR_TYPE_COMPRESSED, 1626 _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_DM}, 1627 1628 {bcmFieldOlpHeaderTypeEthOamUpMepOthers, _BCM_SB2_ETH_OAM_UP_MEP_OTHER_OC_OLP_HDR_TYPE_COMPRESSED, 1629 _BCM_SB2_OLP_HDR_SUBTYPE_ETH_OAM_UPMEP_OTHER_OC}, 1630 1631 /* Up SAT*/ 1632 {bcmFieldOlpHeaderTypeUpSat, _BCM_SAT_UPMEP_OLP_HDR_COMPRESSED, 1633 _BCM_SB2_OLP_HDR_SUBTYPE_SAT_UP} 1634 }; 1635 1636 static uint8 sb2_olp_hdr_type_count = sizeof(sb2_olp_hdr_type_mapping) / 1637 sizeof(sb2_olp_hdr_type_mapping[0]); 1638 1639 1640 /* * * * * * * * * * * * * * * * * * * * * * * * * 1641 * Static local functions * 1642 */ 1643 1644 #if defined (INCLUDE_BHH) 1645 /* 1646 * Function: 1647 * _bcm_sb2_oam_period_validate 1648 * Purpose: 1649 * Validates whether OAM period is in allowed range or not . 1650 * Parameters: 1651 * period - (IN) OAM PDU interval in milli seconds. 1652 * Returns: 1653 * BCM_E_XXX 1654 */ 1655 STATIC int 1656 _bcm_sb2_oam_period_validate(int period) 1657 { 1658 int q_period = 0; /* OAM period value. */ 1659 1660 /* Find whether requested period is matching with supported period or not */ 1661 for (q_period = 0; q_period < 1662 _BCM_SB2_OAM_MAX_CCM_INTERVALS; q_period++) { 1663 if (period == _sb2_ccm_intervals[q_period]) { 1664 return BCM_E_NONE; 1665 } 1666 } 1667 1668 return BCM_E_PARAM; 1669 } 1670 #endif 1671 1672 void 1673 _bcm_sb2_oam_key_type_from_endpoint_get(bcm_oam_endpoint_type_t type, 1674 uint32 flags, bcm_vlan_t vlan, 1675 bcm_vlan_t inner_vlan, 1676 uint32 int_flags, int *key_type) 1677 { 1678 if((type == bcmOAMEndpointTypeMplsLmDmSectionPort) || 1679 (type == bcmOAMEndpointTypeBhhSection)) { 1680 *key_type = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION; 1681 } else if( 1682 (type == bcmOAMEndpointTypeMplsLmDmSectionInnervlan) || 1683 (type == bcmOAMEndpointTypeBhhSectionInnervlan)) { 1684 *key_type = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_CVLAN; 1685 } else if( 1686 (type == bcmOAMEndpointTypeMplsLmDmSectionOuterVlan) || 1687 (type == bcmOAMEndpointTypeBhhSectionOuterVlan)) { 1688 *key_type = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_SVLAN; 1689 } else if( 1690 (type == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan) || 1691 (type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)) { 1692 *key_type = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN; 1693 } else if( 1694 (type == bcmOAMEndpointTypeMplsLmDmPw) || 1695 (type == bcmOAMEndpointTypeBHHMPLSVccv)) { 1696 *key_type = _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW; 1697 } else if( 1698 (type == bcmOAMEndpointTypeMplsLmDmLsp) || 1699 (type == bcmOAMEndpointTypeBHHMPLS)) { 1700 *key_type = _BCM_SB2_OAM_DOMAIN_ING_MPLS_LMDM_LSP; 1701 } else if (_BCM_OAM_ETH_OAM_VP_TYPE(type, int_flags)) { 1702 *key_type = _BCM_OAM_DOMAIN_VP; 1703 } else if(flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) { 1704 *key_type = _BCM_OAM_DOMAIN_CVLAN; 1705 } else if(flags & 1706 BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) { 1707 *key_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN; 1708 } else if((vlan == 0) && (inner_vlan == 0)) { 1709 *key_type = _BCM_OAM_DOMAIN_PORT; 1710 } else { 1711 *key_type = _BCM_OAM_DOMAIN_SVLAN; 1712 } 1713 } 1714 1715 /* 1716 * Function: 1717 * _bcm_sb2_outer_tpid_init 1718 * Purpose: 1719 * Allocate and initialize memory to cache oam outer tpid entries. 1720 * Initialize lock for cached tpid entries. 1721 * Parameters: 1722 * unit - (IN)SOC unit number. 1723 * Returns: 1724 * BCM_E_XXX 1725 * Notes: 1726 */ 1727 int 1728 _bcm_sb2_outer_tpid_init(int unit) { 1729 int index; 1730 int alloc_size; 1731 uint32 reg32; 1732 int rv = BCM_E_NONE; 1733 1734 /* Allocate memory to cache OUTER_TPID entries. */ 1735 alloc_size = sizeof(_oam_tpid_t) * BCM_MAX_TPID_ENTRIES; 1736 if (SB2_OAM_OUTER_TPID_TAB(unit) == NULL) { 1737 SB2_OAM_OUTER_TPID_TAB(unit) = sal_alloc(alloc_size, 1738 "Cached OAM Outer TPIDs"); 1739 if (SB2_OAM_OUTER_TPID_TAB(unit) == NULL) { 1740 return BCM_E_MEMORY; 1741 } 1742 } 1743 sal_memset(SB2_OAM_OUTER_TPID_TAB(unit), 0, alloc_size); 1744 1745 /* Cache outer TPID table */ 1746 for (index = 0; index < BCM_MAX_TPID_ENTRIES; index++) { 1747 rv = soc_reg32_get(unit, sb2_outer_tpid[index], REG_PORT_ANY, 0, ®32); 1748 if (BCM_FAILURE(rv)) { 1749 sal_free(SB2_OAM_OUTER_TPID_TAB(unit)); 1750 SB2_OAM_OUTER_TPID_TAB(unit) = NULL; 1751 } 1752 SB2_OAM_OUTER_TPID_ENTRY(unit, index) = soc_reg_field_get(unit, 1753 sb2_outer_tpid[index], reg32, TPIDf); 1754 } 1755 1756 if (NULL == BCM_SB2_OUTER_TPID_MUTEX(unit)) { 1757 /* Create protection mutex. */ 1758 BCM_SB2_OUTER_TPID_MUTEX(unit) = sal_mutex_create("oamouter_tpid_lock"); 1759 if (NULL == BCM_SB2_OUTER_TPID_MUTEX(unit)) { 1760 return (BCM_E_MEMORY); 1761 } 1762 } 1763 return (BCM_E_NONE); 1764 } 1765 1766 /* 1767 * Function: 1768 * _bcm_sb2_inner_tpid_init 1769 * Purpose: 1770 * Allocate and initialize memory to cache oam inner tpid entries. 1771 * Initialize lock for cached tpid entries. 1772 * Parameters: 1773 * unit - (IN)SOC unit number. 1774 * Returns: 1775 * BCM_E_XXX 1776 * Notes: 1777 */ 1778 int 1779 _bcm_sb2_inner_tpid_init(int unit) { 1780 int alloc_size; 1781 uint32 reg32; 1782 int rv = BCM_E_NONE; 1783 1784 /* Allocate memory to cache INNER_TPID entries. */ 1785 alloc_size = sizeof(_oam_tpid_t) * BCM_MAX_INNER_TPID_ENTRIES; 1786 if (SB2_OAM_INNER_TPID_TAB(unit) == NULL) { 1787 SB2_OAM_INNER_TPID_TAB(unit) = sal_alloc(alloc_size, 1788 "Cached OAM Inner TPIDs"); 1789 if (SB2_OAM_INNER_TPID_TAB(unit) == NULL) { 1790 return BCM_E_MEMORY; 1791 } 1792 } 1793 sal_memset(SB2_OAM_INNER_TPID_TAB(unit), 0, alloc_size); 1794 1795 /* Cache Inner TPID table */ 1796 rv = soc_reg32_get(unit, INNER_TPIDr, REG_PORT_ANY, 0, ®32); 1797 if (BCM_FAILURE(rv)) { 1798 sal_free(SB2_OAM_INNER_TPID_TAB(unit)); 1799 SB2_OAM_INNER_TPID_TAB(unit) = NULL; 1800 } 1801 /* Inner TPID has only 1 entry. So, index is always 0 */ 1802 SB2_OAM_INNER_TPID_ENTRY(unit, 0) = soc_reg_field_get(unit, INNER_TPIDr, 1803 reg32, TPIDf); 1804 1805 if (NULL == BCM_SB2_INNER_TPID_MUTEX(unit)) { 1806 /* Create protection mutex. */ 1807 BCM_SB2_INNER_TPID_MUTEX(unit) = sal_mutex_create("oam inner_tpid_lock"); 1808 if (NULL == BCM_SB2_INNER_TPID_MUTEX(unit)) { 1809 return (BCM_E_MEMORY); 1810 } 1811 } 1812 return (BCM_E_NONE); 1813 } 1814 1815 /* 1816 * Function: 1817 * _bcm_sb2_subport_tpid_init 1818 * Purpose: 1819 * Allocate and initialize memory to cache oam subport tpid entries. 1820 * Initialize lock for cached tpid entries. 1821 * Parameters: 1822 * unit - (IN)SOC unit number. 1823 * Returns: 1824 * BCM_E_XXX 1825 * Notes: 1826 */ 1827 int 1828 _bcm_sb2_subport_tpid_init(int unit) { 1829 int index; 1830 int alloc_size; 1831 uint32 reg32; 1832 int rv = BCM_E_NONE; 1833 1834 /* Allocate memory to cache OUTER_TPID entries. */ 1835 alloc_size = sizeof(_oam_tpid_t) * BCM_MAX_TPID_ENTRIES; 1836 if (SB2_OAM_SUBPORT_TPID_TAB(unit) == NULL) { 1837 SB2_OAM_SUBPORT_TPID_TAB(unit) = sal_alloc(alloc_size, 1838 "Cached OAM Subport TPIDs"); 1839 if (SB2_OAM_SUBPORT_TPID_TAB(unit) == NULL) { 1840 return BCM_E_MEMORY; 1841 } 1842 } 1843 sal_memset(SB2_OAM_SUBPORT_TPID_TAB(unit), 0, alloc_size); 1844 1845 /* Cache Subport TPID table */ 1846 for (index = 0; index < BCM_MAX_TPID_ENTRIES; index++) { 1847 rv = soc_reg32_get(unit, sb2_subport_tpid[index], REG_PORT_ANY, 0, ®32); 1848 if (BCM_FAILURE(rv)) { 1849 sal_free(SB2_OAM_SUBPORT_TPID_TAB(unit)); 1850 SB2_OAM_SUBPORT_TPID_TAB(unit) = NULL; 1851 } 1852 SB2_OAM_SUBPORT_TPID_ENTRY(unit, index) = soc_reg_field_get(unit, 1853 sb2_subport_tpid[index], reg32, TPIDf); 1854 } 1855 1856 if (NULL == BCM_SB2_SUBPORT_TPID_MUTEX(unit)) { 1857 /* Create protection mutex. */ 1858 BCM_SB2_SUBPORT_TPID_MUTEX(unit) = sal_mutex_create("oam subport_tpid_lock"); 1859 if (NULL == BCM_SB2_SUBPORT_TPID_MUTEX(unit)) { 1860 return (BCM_E_MEMORY); 1861 } 1862 } 1863 return (BCM_E_NONE); 1864 } 1865 /* 1866 * Function : 1867 * _bcm_sb2_oam_tpid_get 1868 * 1869 * Purpose : 1870 * Get tpid value for tpid entry index in the HW. 1871 * 1872 * Parameters : 1873 * unit - (IN) BCM device number. 1874 * tpid_type -(IN) - outer/inner/subport 1875 * index - (IN) Entry index. 1876 * value - (OUT) TPID value in HW 1877 * Return : 1878 * BCM_E_XXX 1879 */ 1880 int 1881 _bcm_sb2_oam_tpid_get(int unit, int tpid_type, int index, int *value) 1882 { 1883 int rv = BCM_E_NONE; 1884 uint32 rval = 0; 1885 1886 if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 1887 if (index >= BCM_MAX_TPID_ENTRIES) { 1888 return (BCM_E_PARAM); 1889 } 1890 rv = soc_reg32_get(unit, sb2_outer_tpid[index], REG_PORT_ANY, 0, &rval); 1891 if (BCM_FAILURE(rv)) { 1892 return (BCM_E_PARAM); 1893 } 1894 *value = soc_reg_field_get(unit, sb2_outer_tpid[index], rval, TPIDf); 1895 } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 1896 if (index >= BCM_MAX_INNER_TPID_ENTRIES) { 1897 return (BCM_E_PARAM); 1898 } 1899 rv = soc_reg32_get(unit, INNER_TPIDr, REG_PORT_ANY, 0, &rval); 1900 if (BCM_FAILURE(rv)) { 1901 return (BCM_E_PARAM); 1902 } 1903 *value = soc_reg_field_get(unit, INNER_TPIDr, rval, TPIDf); 1904 } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 1905 if (index >= BCM_MAX_TPID_ENTRIES) { 1906 return (BCM_E_PARAM); 1907 } 1908 rv = soc_reg32_get(unit, sb2_subport_tpid[index], REG_PORT_ANY, 0, &rval); 1909 if (BCM_FAILURE(rv)) { 1910 return (BCM_E_PARAM); 1911 } 1912 *value = soc_reg_field_get(unit, sb2_subport_tpid[index], rval, TPIDf); 1913 } else { 1914 return (BCM_E_PARAM); 1915 } 1916 return (rv); 1917 } 1918 1919 /* 1920 * Function : 1921 * _bcm_sb2_oam_tpid_set 1922 * 1923 * Purpose : 1924 * Set tpid value for tpid entry index in the HW. 1925 * 1926 * Parameters : 1927 * unit - (IN) BCM device number. 1928 * tpid_type -(IN) - outer/inner/subport 1929 * index - (IN) Entry index. 1930 * value - (IN) Value to be set as tpid 1931 * Return : 1932 * BCM_E_XXX 1933 */ 1934 int 1935 _bcm_sb2_oam_tpid_set(int unit, int tpid_type, int index, int value) 1936 { 1937 int rv = BCM_E_NONE; 1938 uint32 rval = 0; 1939 1940 if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 1941 if (index >= BCM_MAX_TPID_ENTRIES) { 1942 return (BCM_E_PARAM); 1943 } 1944 soc_reg_field_set(unit, sb2_outer_tpid[index], &rval, TPIDf, value); 1945 rv = soc_reg32_set(unit, sb2_outer_tpid[index], REG_PORT_ANY, 0, rval); 1946 if (BCM_FAILURE(rv)) { 1947 return (BCM_E_PARAM); 1948 } 1949 } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 1950 if (index >= BCM_MAX_INNER_TPID_ENTRIES) { 1951 return (BCM_E_PARAM); 1952 } 1953 soc_reg_field_set(unit, INNER_TPIDr, &rval, TPIDf, value); 1954 rv = soc_reg32_set(unit, INNER_TPIDr, REG_PORT_ANY, 0, rval); 1955 if (BCM_FAILURE(rv)) { 1956 return (BCM_E_PARAM); 1957 } 1958 } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 1959 if (index >= BCM_MAX_TPID_ENTRIES) { 1960 return (BCM_E_PARAM); 1961 } 1962 soc_reg_field_set(unit, sb2_subport_tpid[index], &rval, TPIDf, value); 1963 rv = soc_reg32_set(unit, sb2_subport_tpid[index], REG_PORT_ANY, 0, rval); 1964 if (BCM_FAILURE(rv)) { 1965 return (BCM_E_PARAM); 1966 } 1967 } else { 1968 return (BCM_E_PARAM); 1969 } 1970 return (rv); 1971 } 1972 1973 /* 1974 * Function : 1975 * _bcm_sb2_oam_tpid_entry_get 1976 * 1977 * Purpose : 1978 * Get tpid value for tpid entry index . 1979 * 1980 * Parameters : 1981 * unit - (IN) BCM device number. 1982 * tpid - (OUT) TPID value. 1983 * index - (IN) Entry index. 1984 * 1985 * Return : 1986 * BCM_E_XXX 1987 */ 1988 int 1989 _bcm_sb2_oam_tpid_entry_get(int unit, uint16 *tpid, int index, int tpid_type) 1990 { 1991 if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 1992 if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) || 1993 (SB2_OAM_OUTER_TPID_REF_COUNT(unit, index) <= 0)) { 1994 return (BCM_E_PARAM); 1995 } 1996 *tpid = SB2_OAM_OUTER_TPID_ENTRY(unit, index); 1997 } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 1998 if ((index < 0) || (index >= BCM_MAX_INNER_TPID_ENTRIES) || 1999 (SB2_OAM_INNER_TPID_REF_COUNT(unit, index) <= 0)) { 2000 return (BCM_E_PARAM); 2001 } 2002 *tpid = SB2_OAM_INNER_TPID_ENTRY(unit, index); 2003 } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 2004 if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) || 2005 (SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, index) <= 0)) { 2006 return (BCM_E_PARAM); 2007 } 2008 *tpid = SB2_OAM_SUBPORT_TPID_ENTRY(unit, index); 2009 } else { 2010 return (BCM_E_PARAM); 2011 } 2012 return (BCM_E_NONE); 2013 } 2014 2015 /* 2016 * Function : 2017 * _bcm_sb2_oam_tpid_entry_delete 2018 * 2019 * Purpose : 2020 * Delete tpid entry by index. 2021 * 2022 * Parameters : 2023 * unit - (IN) BCM device number. 2024 * index - (IN) Entry index. 2025 * 2026 * Return : 2027 * BCM_E_XXX 2028 */ 2029 int 2030 _bcm_sb2_tpid_entry_delete(int unit, int index, int tpid_type) 2031 { 2032 int rv = BCM_E_NONE; 2033 if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 2034 BCM_SB2_OUTER_TPID_LOCK(unit); 2035 if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) || 2036 (SB2_OAM_OUTER_TPID_REF_COUNT(unit, index) <= 0)) { 2037 rv = BCM_E_PARAM; 2038 BCM_SB2_OUTER_TPID_UNLOCK(unit); 2039 return rv; 2040 } 2041 SB2_OAM_OUTER_TPID_REF_COUNT(unit, index)--; 2042 if (0 == SB2_OAM_OUTER_TPID_REF_COUNT(unit, index)) { 2043 SB2_OAM_OUTER_TPID_ENTRY(unit, index) = sb2_default_outer_tpid[index]; 2044 rv = _bcm_sb2_oam_tpid_set(unit, tpid_type, index, 2045 sb2_default_outer_tpid[index]); 2046 } 2047 BCM_SB2_OUTER_TPID_UNLOCK(unit); 2048 } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 2049 BCM_SB2_INNER_TPID_LOCK(unit); 2050 if ((index < 0) || (index >= BCM_MAX_INNER_TPID_ENTRIES) || 2051 (SB2_OAM_INNER_TPID_REF_COUNT(unit, index) <= 0)) { 2052 rv = BCM_E_PARAM; 2053 BCM_SB2_INNER_TPID_UNLOCK(unit); 2054 return rv; 2055 } 2056 SB2_OAM_INNER_TPID_REF_COUNT(unit, index)--; 2057 if (0 == SB2_OAM_INNER_TPID_REF_COUNT(unit, index)) { 2058 SB2_OAM_INNER_TPID_ENTRY(unit, index) = BCM_OAM_DEFAULT_TPID; 2059 rv = _bcm_sb2_oam_tpid_set(unit, tpid_type, index, 2060 BCM_OAM_DEFAULT_TPID); 2061 } 2062 BCM_SB2_INNER_TPID_UNLOCK(unit); 2063 } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 2064 BCM_SB2_SUBPORT_TPID_LOCK(unit); 2065 if ((index < 0) || (index >= BCM_MAX_TPID_ENTRIES) || 2066 (SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, index) <= 0)) { 2067 rv = BCM_E_PARAM; 2068 BCM_SB2_SUBPORT_TPID_UNLOCK(unit); 2069 return rv; 2070 } 2071 SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, index)--; 2072 if (0 == SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, index)) { 2073 SB2_OAM_SUBPORT_TPID_ENTRY(unit, index) = BCM_OAM_DEFAULT_TPID; 2074 rv = _bcm_sb2_oam_tpid_set(unit, tpid_type, index, 2075 BCM_OAM_DEFAULT_TPID); 2076 } 2077 BCM_SB2_SUBPORT_TPID_UNLOCK(unit); 2078 } else { 2079 return (BCM_E_PARAM); 2080 } 2081 return (rv); 2082 } 2083 2084 2085 /* 2086 * Function : 2087 * _bcm_sb2_tpid_lkup 2088 * 2089 * Purpose : 2090 * Get tpid entry index for specific tpid value. 2091 * 2092 * Parameters : 2093 * unit - (IN) BCM device number. 2094 * tpid - (IN) TPID value. 2095 * tpid_type - (IN) Type of the tpid - inner/outer/subport 2096 * index - (OUT) Entry index. 2097 * 2098 * Return : 2099 * BCM_E_XXX 2100 */ 2101 int 2102 _bcm_sb2_tpid_lkup(int unit, uint16 tpid, int tpid_type, int *index) 2103 { 2104 int i; 2105 if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 2106 for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) { 2107 if (SB2_OAM_OUTER_TPID_ENTRY(unit, i) == tpid) { 2108 *index = i; 2109 return BCM_E_NONE; 2110 } 2111 } 2112 } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 2113 for (i = 0; i < BCM_MAX_INNER_TPID_ENTRIES; i++) { 2114 if (SB2_OAM_INNER_TPID_ENTRY(unit, i) == tpid) { 2115 *index = i; 2116 return BCM_E_NONE; 2117 } 2118 } 2119 } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 2120 for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) { 2121 if (SB2_OAM_SUBPORT_TPID_ENTRY(unit, i) == tpid) { 2122 *index = i; 2123 return BCM_E_NONE; 2124 } 2125 } 2126 } 2127 return BCM_E_NOT_FOUND; 2128 } 2129 2130 /* 2131 * Function: 2132 * _bcm_sb2_tpid_entry_add 2133 * Purpose: 2134 * Add a new TPID entry. 2135 * Allocate and initialize memory to cache tpid entries. 2136 * Initialize lock for cached tpid entries. 2137 * Parameters: 2138 * unit - (IN) SOC unit number. 2139 * tpid - (IN) TPID to be added. 2140 * tpid_type - (IN) Type of the tpid - inner/outer/subport 2141 * index - (OUT) Index where the the new TPID is added. 2142 * Returns: 2143 * BCM_E_XXX 2144 * Notes: 2145 * If the same TPID already exists, simply increase the 2146 * reference count of the cached entry. Otherwise, add the entry 2147 * to the cached table and write the new entry to hardware. 2148 * Only four distinct TPID values are currently supported for 2149 * outer and subport TPID and only one value is supported for 2150 * inner tpid. 2151 */ 2152 2153 int 2154 _bcm_sb2_tpid_entry_add(int unit, uint16 tpid, int tpid_type, int *index) 2155 { 2156 int rv = BCM_E_NONE; 2157 int i, free_index; 2158 2159 free_index = -1; 2160 if (tpid_type == BCM_OAM_TPID_TYPE_OUTER) { 2161 BCM_SB2_OUTER_TPID_LOCK(unit); 2162 /* Search for an existing entry. */ 2163 for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) { 2164 if (SB2_OAM_OUTER_TPID_ENTRY(unit, i) == tpid) { 2165 SB2_OAM_OUTER_TPID_REF_COUNT(unit, i)++; 2166 *index = i; 2167 BCM_SB2_OUTER_TPID_UNLOCK(unit); 2168 return rv; 2169 } 2170 } 2171 for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) { 2172 if (SB2_OAM_OUTER_TPID_REF_COUNT(unit, i) == 0) { 2173 free_index = i; 2174 break; 2175 } 2176 } 2177 if (free_index < 0) { 2178 rv = BCM_E_RESOURCE; 2179 BCM_SB2_OUTER_TPID_UNLOCK(unit); 2180 return rv; 2181 } 2182 /* Insert the new configuration into tpid table as free 2183 entry is available */ 2184 rv = _bcm_sb2_oam_tpid_set(unit, tpid_type, free_index, tpid); 2185 if (BCM_FAILURE(rv)) { 2186 BCM_SB2_OUTER_TPID_UNLOCK(unit); 2187 return rv; 2188 } 2189 SB2_OAM_OUTER_TPID_ENTRY(unit, free_index) = tpid; 2190 SB2_OAM_OUTER_TPID_REF_COUNT(unit, free_index)++; 2191 *index = free_index; 2192 BCM_SB2_OUTER_TPID_UNLOCK(unit); 2193 } else if (tpid_type == BCM_OAM_TPID_TYPE_INNER) { 2194 BCM_SB2_INNER_TPID_LOCK(unit); 2195 /* Search for an existing entry */ 2196 for (i = 0; i < BCM_MAX_INNER_TPID_ENTRIES; i++) { 2197 if (SB2_OAM_INNER_TPID_ENTRY(unit, i) == tpid) { 2198 SB2_OAM_INNER_TPID_REF_COUNT(unit, i)++; 2199 *index = i; 2200 BCM_SB2_INNER_TPID_UNLOCK(unit); 2201 return rv; 2202 } 2203 } 2204 for (i = 0; i < BCM_MAX_INNER_TPID_ENTRIES; i++) { 2205 if (SB2_OAM_INNER_TPID_REF_COUNT(unit, i) == 0) { 2206 free_index = i; 2207 break; 2208 } 2209 } 2210 if (free_index < 0) { 2211 rv = BCM_E_RESOURCE; 2212 BCM_SB2_INNER_TPID_UNLOCK(unit); 2213 return rv; 2214 } 2215 /* Insert the new configuration into tpid table as free 2216 entry is available */ 2217 rv = _bcm_sb2_oam_tpid_set(unit, tpid_type, free_index, tpid); 2218 if (BCM_FAILURE(rv)) { 2219 BCM_SB2_INNER_TPID_UNLOCK(unit); 2220 return rv; 2221 } 2222 SB2_OAM_INNER_TPID_ENTRY(unit, free_index) = tpid; 2223 SB2_OAM_INNER_TPID_REF_COUNT(unit, free_index)++; 2224 *index = free_index; 2225 BCM_SB2_INNER_TPID_UNLOCK(unit); 2226 } else if (tpid_type == BCM_OAM_TPID_TYPE_SUBPORT) { 2227 BCM_SB2_SUBPORT_TPID_LOCK(unit); 2228 /* Search for an existing entry */ 2229 for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) { 2230 if (SB2_OAM_SUBPORT_TPID_ENTRY(unit, i) == tpid) { 2231 SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, i)++; 2232 *index = i; 2233 BCM_SB2_SUBPORT_TPID_UNLOCK(unit); 2234 return rv; 2235 } 2236 } 2237 for (i = 0; i < BCM_MAX_TPID_ENTRIES; i++) { 2238 if (SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, i) == 0) { 2239 free_index = i; 2240 break; 2241 } 2242 } 2243 if (free_index < 0) { 2244 rv = BCM_E_RESOURCE; 2245 BCM_SB2_SUBPORT_TPID_UNLOCK(unit); 2246 return rv; 2247 } 2248 /* Insert the new configuration into tpid table as free 2249 entry is available. */ 2250 rv = _bcm_sb2_oam_tpid_set(unit, tpid_type, free_index, tpid); 2251 if (BCM_FAILURE(rv)) { 2252 BCM_SB2_SUBPORT_TPID_UNLOCK(unit); 2253 return rv; 2254 } 2255 SB2_OAM_SUBPORT_TPID_ENTRY(unit, free_index) = tpid; 2256 SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, free_index)++; 2257 *index = free_index; 2258 BCM_SB2_SUBPORT_TPID_UNLOCK(unit); 2259 } else { 2260 rv = BCM_E_PARAM; 2261 } 2262 return rv; 2263 } 2264 2265 /* 2266 * Function: 2267 * _bcm_sb2_oam_ccm_msecs_to_hw_encode 2268 * Purpose: 2269 * Quanitze CCM interval from msecs to hardware encoding. 2270 * Parameters: 2271 * period - (IN) CCM interval in milli seconds. 2272 * Retruns: 2273 * Hardware encoding for the specified CCM interval value. 2274 */ 2275 STATIC int 2276 _bcm_sb2_oam_ccm_msecs_to_hw_encode(int period) 2277 { 2278 int q_period = 0; /* Quantized CCM period value. */ 2279 2280 if (0 == period) { 2281 return (q_period); 2282 } 2283 2284 /* Find closest supported period */ 2285 for (q_period = 1; _sb2_ccm_intervals[q_period] 2286 != _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED; ++q_period) { 2287 if (period < _sb2_ccm_intervals[q_period]) { 2288 break; 2289 } 2290 } 2291 2292 if (_sb2_ccm_intervals[q_period] 2293 == _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED) { 2294 /* Use the highest defined value */ 2295 --q_period; 2296 } else { 2297 if ((period - _sb2_ccm_intervals[q_period - 1]) 2298 < (_sb2_ccm_intervals[q_period] - period)) { 2299 /* Closer to the lower value */ 2300 --q_period; 2301 } 2302 } 2303 2304 return q_period; 2305 } 2306 2307 #if defined(BCM_WARM_BOOT_SUPPORT) 2308 /* 2309 * Function: 2310 * _bcm_sb2_oam_ccm_hw_encode_to_msecs 2311 * Purpose: 2312 * Get CCM interval in msecs for a given hardware encoded value. 2313 * Parameters: 2314 * encode - (IN) CCM interval hardware encoding. 2315 * Retruns: 2316 * CCM interval in msecs. 2317 */ 2318 STATIC int 2319 _bcm_sb2_oam_ccm_hw_encode_to_msecs(int encode) 2320 { 2321 return (_sb2_ccm_intervals[encode]); 2322 } 2323 #endif 2324 2325 int _bcm_sb2_opcode_flags_to_opcode_group_index(int unit, uint32 opcode_flags, 2326 bcm_oam_endpoint_type_t type, 2327 int *index_list, int *num_index) 2328 { 2329 int i; 2330 int rv; 2331 oam_opcode_group_entry_t opcode_grp_entry; 2332 int opcode_key[2] = {0, 0}; 2333 2334 switch(opcode_flags) { 2335 case BCM_OAM_OPCODE_CCM_COPY_TO_CPU: 2336 case BCM_OAM_OPCODE_CCM_DROP: 2337 case BCM_OAM_OPCODE_CCM_IN_HW: 2338 if (BHH_TYPE(type)) { 2339 opcode_key[0] = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM( 2340 _BCM_OAM_OPCODE_TYPE_CCM); 2341 } else { 2342 opcode_key[0] = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM( 2343 _BCM_OAM_OPCODE_TYPE_CCM); 2344 } 2345 *num_index = 1; 2346 break; 2347 2348 case BCM_OAM_OPCODE_LBM_IN_HW: 2349 case BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU: 2350 case BCM_OAM_OPCODE_LBM_UC_DROP: 2351 case BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU: 2352 case BCM_OAM_OPCODE_LBM_MC_DROP: 2353 if (BHH_TYPE(type)) { 2354 opcode_key[0] = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM( 2355 _BCM_OAM_OPCODE_TYPE_LBM); 2356 } else { 2357 opcode_key[0] = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM( 2358 _BCM_OAM_OPCODE_TYPE_LBM); 2359 } 2360 *num_index = 1; 2361 break; 2362 2363 case BCM_OAM_OPCODE_LBR_COPY_TO_CPU: 2364 case BCM_OAM_OPCODE_LBR_DROP: 2365 if (BHH_TYPE(type)) { 2366 opcode_key[0] = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM( 2367 _BCM_OAM_OPCODE_TYPE_LBR); 2368 } else { 2369 opcode_key[0] = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM( 2370 _BCM_OAM_OPCODE_TYPE_LBR); 2371 } 2372 *num_index = 1; 2373 break; 2374 2375 case BCM_OAM_OPCODE_LTM_COPY_TO_CPU: 2376 case BCM_OAM_OPCODE_LTM_DROP: 2377 if (BHH_TYPE(type)) { 2378 opcode_key[0] = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM( 2379 _BCM_OAM_OPCODE_TYPE_LTM); 2380 } else { 2381 opcode_key[0] = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM( 2382 _BCM_OAM_OPCODE_TYPE_LTM); 2383 } 2384 *num_index = 1; 2385 break; 2386 2387 case BCM_OAM_OPCODE_LTR_COPY_TO_CPU: 2388 case BCM_OAM_OPCODE_LTR_DROP: 2389 if (BHH_TYPE(type)) { 2390 opcode_key[0] = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM( 2391 _BCM_OAM_OPCODE_TYPE_LTR); 2392 } else { 2393 opcode_key[0] = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM( 2394 _BCM_OAM_OPCODE_TYPE_LTR); 2395 } 2396 *num_index = 1; 2397 break; 2398 2399 case BCM_OAM_OPCODE_OTHER_COPY_TO_CPU: 2400 case BCM_OAM_OPCODE_OTHER_DROP: 2401 if (BHH_TYPE(type)) { 2402 opcode_key[0] = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM( 2403 _BCM_OAM_OPCODE_TYPE_LMM); 2404 opcode_key[1] = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM( 2405 _BCM_OAM_OPCODE_TYPE_DMM); 2406 } else { 2407 opcode_key[0] = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM( 2408 _BCM_OAM_OPCODE_TYPE_LMM); 2409 opcode_key[1] = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM( 2410 _BCM_OAM_OPCODE_TYPE_DMM); 2411 } 2412 *num_index = 2; 2413 break; 2414 2415 default: 2416 return BCM_E_PARAM; 2417 break; 2418 } 2419 2420 for(i=0; i< (*num_index); i++) { 2421 rv = soc_mem_read(unit, OAM_OPCODE_GROUPm, MEM_BLOCK_ANY, 2422 opcode_key[i], &opcode_grp_entry); 2423 2424 if (BCM_FAILURE(rv)) { 2425 LOG_ERROR(BSL_LS_BCM_OAM, 2426 (BSL_META_U(unit, 2427 "OAM(unit %d) Error: OAM_OPCODE_GROUP table entry read " 2428 "failed %s.\n"), unit, bcm_errmsg(rv))); 2429 return rv; 2430 } 2431 2432 index_list[i] = soc_mem_field32_get(unit, OAM_OPCODE_GROUPm, 2433 &opcode_grp_entry, OPCODE_GROUPf); 2434 } 2435 2436 return BCM_E_NONE; 2437 } 2438 2439 int 2440 _bcm_sb2_oam_mpls_lm_dm_opcode_to_opcode_group_index(int unit, uint32 opcode, 2441 int *opcode_group) 2442 { 2443 int rv = BCM_E_NONE; 2444 int opcode_key; 2445 oam_opcode_group_entry_t opcode_grp_entry; 2446 2447 switch(opcode) { 2448 case bcmOamMplsLmDmOpcodeTypeLm: 2449 case bcmOamMplsLmDmOpcodeTypeDm: 2450 case bcmOamMplsLmDmOpcodeTypeIlm: 2451 case bcmOamMplsLmDmOpcodeTypeLmPlusDm: 2452 case bcmOamMplsLmDmOpcodeTypeIlmPlusDm: 2453 opcode_key = _BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(opcode); 2454 break; 2455 default: 2456 rv = BCM_E_PARAM; 2457 return rv; 2458 break; 2459 } 2460 2461 rv = soc_mem_read(unit, OAM_OPCODE_GROUPm, MEM_BLOCK_ANY, 2462 opcode_key, &opcode_grp_entry); 2463 2464 if (BCM_FAILURE(rv)) { 2465 LOG_ERROR(BSL_LS_BCM_OAM, 2466 (BSL_META_U(unit, 2467 "OAM(unit %d) Error: OAM_OPCODE_GROUP table entry read " 2468 "failed %s.\n"), unit, bcm_errmsg(rv))); 2469 return rv; 2470 } 2471 2472 *opcode_group = soc_mem_field32_get(unit, OAM_OPCODE_GROUPm, 2473 &opcode_grp_entry, OPCODE_GROUPf); 2474 2475 return rv; 2476 2477 } 2478 2479 int _bcm_sb2_opcode_to_opcode_group_index (int unit, _bcm_oam_hash_data_t *h_data_p, 2480 uint32 opcode) 2481 { 2482 int opcode_key = -1; 2483 oam_opcode_group_entry_t opcode_grp_entry; 2484 int rv; 2485 int opcode_group = -1; 2486 2487 if(opcode > _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST) { 2488 return opcode_group; 2489 } 2490 2491 if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 2492 BCM_IF_ERROR_RETURN( 2493 _bcm_sb2_oam_mpls_lm_dm_opcode_to_opcode_group_index(unit, opcode, 2494 &opcode_group)); 2495 return opcode_group; 2496 } 2497 2498 switch(opcode) { 2499 case _BCM_OAM_OPCODE_TYPE_CCM: 2500 case _BCM_OAM_OPCODE_TYPE_LBR: 2501 case _BCM_OAM_OPCODE_TYPE_LBM: 2502 case _BCM_OAM_OPCODE_TYPE_LTR: 2503 case _BCM_OAM_OPCODE_TYPE_LTM: 2504 case _BCM_OAM_OPCODE_TYPE_LMR: 2505 case _BCM_OAM_OPCODE_TYPE_LMM: 2506 case _BCM_OAM_OPCODE_TYPE_SLM: 2507 case _BCM_OAM_OPCODE_TYPE_SLR: 2508 case _BCM_OAM_OPCODE_TYPE_AIS: 2509 case _BCM_OAM_OPCODE_TYPE_LCK: 2510 case _BCM_OAM_OPCODE_TYPE_TST: 2511 case _BCM_OAM_OPCODE_TYPE_LIN_APS: 2512 case _BCM_OAM_OPCODE_TYPE_RING_APS: 2513 case _BCM_OAM_OPCODE_TYPE_1DM: 2514 case _BCM_OAM_OPCODE_TYPE_DMM: 2515 case _BCM_OAM_OPCODE_TYPE_DMR: 2516 case _BCM_OAM_OPCODE_TYPE_MCC: 2517 case _BCM_OAM_OPCODE_TYPE_EXM: 2518 case _BCM_OAM_OPCODE_TYPE_EXR: 2519 case _BCM_OAM_OPCODE_TYPE_VSM: 2520 case _BCM_OAM_OPCODE_TYPE_VSR: 2521 if (BHH_EP_TYPE(h_data_p)) { 2522 opcode_key = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(opcode); 2523 } else { 2524 opcode_key = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(opcode); 2525 } 2526 2527 break; 2528 } 2529 2530 if(opcode_key != -1) { 2531 rv = soc_mem_read(unit, OAM_OPCODE_GROUPm, MEM_BLOCK_ANY, 2532 opcode_key, &opcode_grp_entry); 2533 2534 if (BCM_FAILURE(rv)) { 2535 LOG_ERROR(BSL_LS_BCM_OAM, 2536 (BSL_META_U(unit, 2537 "OAM(unit %d) Error: OAM_OPCODE_GROUP table entry read " 2538 "failed %s.\n"), unit, bcm_errmsg(rv))); 2539 return opcode_group; 2540 } 2541 2542 opcode_group = soc_mem_field32_get(unit, OAM_OPCODE_GROUPm, 2543 &opcode_grp_entry, OPCODE_GROUPf); 2544 } 2545 2546 return opcode_group; 2547 2548 } 2549 2550 /* 2551 * Function: 2552 * _bcm_sb2_oam_opcode_profile_entry_set 2553 * Purpose: 2554 * Program the OAM opcode control profile fields. 2555 * Parameters: 2556 * unit - (IN) BCM device number 2557 * mem - (IN) Opcode profile memory - ingress/egress 2558 * flags - (IN) Bitmap of opcode control settings. 2559 * entry - (IN/OUT) Pointer to opcode control profile table 2560 * array of entries buffer. 2561 * Retruns: 2562 * BCM_E_XXX 2563 */ 2564 STATIC int 2565 _bcm_sb2_oam_opcode_profile_entry_set(int unit, _bcm_oam_hash_data_t *h_data_p, 2566 soc_mem_t mem, 2567 uint32 flags, 2568 void *entry) 2569 { 2570 uint32 ep_opcode; /* Endpoint opcode flag bits. */ 2571 uint32 opcode_count = 0; /* Number of bits set. */ 2572 int bp; /* bit position. */ 2573 int rv = BCM_E_NONE; /* Opreation return status. */ 2574 oam_opcode_control_profile_entry_t *temp_entry; 2575 oam_opcode_control_profile_entry_t *actual_entry; 2576 int index_list[2] = {0 , 0}; /* There can be atmost 2 indexes returned */ 2577 int index, num_index = 0; 2578 2579 2580 /* Validate opcode flag bits. */ 2581 if (flags & ~(_BCM_SB2_OAM_OPCODE_MASK)) { 2582 return (BCM_E_PARAM); 2583 } 2584 2585 /* Get number of valid opcodes supported. */ 2586 opcode_count = _shr_popcount(_BCM_SB2_OAM_OPCODE_MASK); 2587 2588 /* 2589 * Iterate over opcode flag bits and set corresponding fields 2590 * in entry buffer. 2591 */ 2592 for (bp = 0; bp < opcode_count; bp++) { 2593 ep_opcode = (flags & (1 << bp)); 2594 if(ep_opcode != 0) 2595 { 2596 rv = _bcm_sb2_opcode_flags_to_opcode_group_index(unit, ep_opcode, h_data_p->type, 2597 index_list, &num_index); 2598 if(rv < 0) 2599 { 2600 return BCM_E_PARAM; 2601 } 2602 for(index = 0; index < num_index; index++) 2603 { 2604 temp_entry = (oam_opcode_control_profile_entry_t *)entry; 2605 /* coverity[overrun-local] */ 2606 actual_entry = &(temp_entry[index_list[index]]); 2607 2608 /*NOTE: Setting of some fields is also done to 2609 maintain the legacy behavior */ 2610 /* LOW MDL CCM / LB/LT drop and LB/LT my station miss drop */ 2611 2612 switch (ep_opcode) { 2613 case BCM_OAM_OPCODE_CCM_COPY_TO_CPU: 2614 /* CCM packet could be UC as well as MC */ 2615 soc_mem_field32_set(unit, mem, actual_entry, 2616 UC_MY_STATION_HIT_COPYTO_CPUf, 1); 2617 if (!BHH_TYPE(h_data_p->type)) { 2618 soc_mem_field32_set(unit, mem, actual_entry, 2619 UC_MY_STATION_MISS_COPYTO_CPUf, 1); 2620 soc_mem_field32_set(unit, mem, actual_entry, MC_COPYTO_CPUf, 1); 2621 } else { 2622 soc_mem_field32_set(unit, mem, actual_entry, 2623 LOW_MDL_COPYTO_CPUf, 1); 2624 if (SOC_IS_METROLITE(unit)) { 2625 soc_mem_field32_set(unit, mem, actual_entry, 2626 EQUAL_MDL_SAMPLE_LM_COUNTERf, 1); 2627 } 2628 } 2629 break; 2630 case BCM_OAM_OPCODE_CCM_DROP: 2631 /* CCM packet could be UC as well as MC */ 2632 soc_mem_field32_set(unit, mem, actual_entry, 2633 UC_MY_STATION_HIT_ACTIONf, 2634 _BCM_SB2_OAM_OC_PROF_DROP); 2635 if (!BHH_TYPE(h_data_p->type)) { 2636 soc_mem_field32_set(unit, mem, actual_entry, 2637 UC_MY_STATION_MISS_ACTIONf, 2638 _BCM_SB2_OAM_OC_PROF_DROP); 2639 soc_mem_field32_set(unit, mem, actual_entry, MC_ACTIONf, 2640 _BCM_SB2_OAM_OC_PROF_DROP); 2641 } 2642 break; 2643 case BCM_OAM_OPCODE_CCM_IN_HW: 2644 /* CCM packet could be UC as well as MC */ 2645 soc_mem_field32_set(unit, mem, actual_entry, 2646 UC_MY_STATION_HIT_ACTIONf, 2647 _BCM_SB2_OAM_OC_PROF_FWD_TO_HW_ENGINE); 2648 if (!BHH_TYPE(h_data_p->type)) { 2649 soc_mem_field32_set(unit, mem, actual_entry, 2650 UC_MY_STATION_MISS_ACTIONf, 2651 _BCM_SB2_OAM_OC_PROF_FWD_TO_HW_ENGINE); 2652 soc_mem_field32_set(unit, mem, actual_entry, MC_ACTIONf, 2653 _BCM_SB2_OAM_OC_PROF_FWD_TO_HW_ENGINE); 2654 } 2655 break; 2656 case BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU: 2657 case BCM_OAM_OPCODE_LBR_COPY_TO_CPU: 2658 case BCM_OAM_OPCODE_LTR_COPY_TO_CPU: 2659 soc_mem_field32_set(unit, mem, actual_entry, 2660 UC_MY_STATION_HIT_COPYTO_CPUf, 1); 2661 if (!BHH_TYPE(h_data_p->type)) { 2662 soc_mem_field32_set(unit, mem, actual_entry, 2663 UC_MY_STATION_MISS_ACTIONf, 2664 _BCM_SB2_OAM_OC_PROF_DROP); 2665 } 2666 break; 2667 case BCM_OAM_OPCODE_LTM_COPY_TO_CPU: 2668 /* LTM comes with multicast class 2 DA */ 2669 soc_mem_field32_set(unit, mem, actual_entry, MC_COPYTO_CPUf, 1); 2670 break; 2671 2672 case BCM_OAM_OPCODE_LBM_IN_HW: 2673 /* LBM could be UC as well as MC */ 2674 soc_mem_field32_set(unit, mem, actual_entry, 2675 UC_MY_STATION_HIT_ACTIONf, 2676 _BCM_SB2_OAM_OC_PROF_FWD_TO_HW_LB_ENGINE); 2677 if (!BHH_TYPE(h_data_p->type)) { 2678 soc_mem_field32_set(unit, mem, actual_entry, 2679 UC_MY_STATION_MISS_ACTIONf, 2680 _BCM_SB2_OAM_OC_PROF_DROP); 2681 soc_mem_field32_set(unit, mem, actual_entry, MC_ACTIONf, 2682 _BCM_SB2_OAM_OC_PROF_FWD_TO_HW_ENGINE); 2683 } 2684 break; 2685 2686 case BCM_OAM_OPCODE_LBM_UC_DROP: 2687 case BCM_OAM_OPCODE_LBR_DROP: 2688 case BCM_OAM_OPCODE_LTR_DROP: 2689 /* Replies are always UC */ 2690 soc_mem_field32_set(unit, mem, actual_entry, 2691 UC_MY_STATION_HIT_ACTIONf, 2692 _BCM_SB2_OAM_OC_PROF_DROP); 2693 if (!BHH_TYPE(h_data_p->type)) { 2694 soc_mem_field32_set(unit, mem, actual_entry, 2695 UC_MY_STATION_MISS_ACTIONf, 2696 _BCM_SB2_OAM_OC_PROF_DROP); 2697 } 2698 break; 2699 case BCM_OAM_OPCODE_LTM_DROP: 2700 soc_mem_field32_set(unit, mem, actual_entry, MC_ACTIONf, 2701 _BCM_SB2_OAM_OC_PROF_DROP); 2702 break; 2703 2704 case BCM_OAM_OPCODE_LBM_MC_DROP: 2705 soc_mem_field32_set(unit, mem, actual_entry, MC_ACTIONf, 2706 _BCM_SB2_OAM_OC_PROF_DROP); 2707 break; 2708 2709 case BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU: 2710 soc_mem_field32_set(unit, mem, actual_entry, MC_COPYTO_CPUf, 1); 2711 break; 2712 2713 case BCM_OAM_OPCODE_OTHER_COPY_TO_CPU: 2714 if (!BHH_TYPE(h_data_p->type)) { 2715 soc_mem_field32_set(unit, mem, actual_entry, 2716 MC_COPYTO_CPUf, 1); 2717 soc_mem_field32_set(unit, mem, actual_entry, 2718 UC_MY_STATION_MISS_COPYTO_CPUf, 1); 2719 } 2720 soc_mem_field32_set(unit, mem, actual_entry, 2721 UC_MY_STATION_HIT_COPYTO_CPUf, 1); 2722 soc_mem_field32_set(unit, mem, actual_entry, 2723 LOW_MDL_COPYTO_CPUf, 1); 2724 if (index == 0) { 2725 soc_mem_field32_set(unit, mem, actual_entry, 2726 EQUAL_MDL_SAMPLE_LM_COUNTERf, 1); 2727 } else if (index == 1) { 2728 soc_mem_field32_set(unit, mem, actual_entry, 2729 EQUAL_MDL_SAMPLE_TIMESTAMPf, 1); 2730 } 2731 break; 2732 2733 case BCM_OAM_OPCODE_OTHER_DROP: 2734 if (!BHH_TYPE(h_data_p->type)) { 2735 soc_mem_field32_set(unit, mem, actual_entry, MC_ACTIONf, 2736 _BCM_SB2_OAM_OC_PROF_DROP); 2737 soc_mem_field32_set(unit, mem, actual_entry, 2738 UC_MY_STATION_MISS_ACTIONf, 2739 _BCM_SB2_OAM_OC_PROF_DROP); 2740 } 2741 soc_mem_field32_set(unit, mem, actual_entry, 2742 UC_MY_STATION_HIT_ACTIONf, 2743 _BCM_SB2_OAM_OC_PROF_DROP); 2744 break; 2745 2746 default: 2747 break; 2748 } 2749 if (_BCM_OAM_EP_IS_MIP(h_data_p)) { 2750 /* Do not drop low mdl*/ 2751 soc_mem_field32_set(unit, mem, actual_entry, 2752 LOW_MDL_ACTIONf, _BCM_SB2_OAM_OC_PROF_NORMAL_SWITCHING); 2753 } else { 2754 /* Drop LOW MDL packets. */ 2755 soc_mem_field32_set(unit, mem, actual_entry, 2756 LOW_MDL_ACTIONf, _BCM_SB2_OAM_OC_PROF_DROP); 2757 } 2758 } 2759 } 2760 } 2761 2762 return rv; 2763 } 2764 2765 2766 int 2767 _bcm_sb2_mpls_lmdm_opcode_profile_entry_init(int unit, 2768 soc_mem_t mem, 2769 void *entry) 2770 { 2771 int opcode, rv = BCM_E_NONE; 2772 _bcm_oam_hash_data_t hash_data; 2773 2774 sal_memset(&hash_data , 0, sizeof(hash_data)); 2775 /* All they care about is type field of hash_data inside 2776 _sb2_oam_opcode_control_field_set to be of type MPLS LM/DM. 2777 Filling one of MPLS LM/DM endpoint types 2778 */ 2779 hash_data.type = bcmOAMEndpointTypeMplsLmDmLsp; 2780 2781 /* Initialize action to copy to cpu for all MPLS LM/DM opcodes. */ 2782 for (opcode = bcmOamMplsLmDmOpcodeTypeLm; 2783 opcode <= bcmOamMplsLmDmOpcodeTypeIlmPlusDm; 2784 opcode++) { 2785 rv = _sb2_oam_opcode_control_field_set(unit, &hash_data, bcmOAMActionCopyToCpu, 2786 mem, opcode, 1, 2787 entry); 2788 if (BCM_FAILURE(rv)) { 2789 return rv; 2790 } 2791 2792 /* Pkt termination is required for sampling to work. Hence adding 2793 * drop action 2794 */ 2795 rv = _sb2_oam_opcode_control_field_set(unit, &hash_data, bcmOAMActionDrop, 2796 mem, opcode, 1, 2797 entry); 2798 if (BCM_FAILURE(rv)) { 2799 return rv; 2800 } 2801 2802 /* Sample LM Counter action for LM opcodes. 2803 * However, for ILM opcodes, we dont sample counters. */ 2804 if ((opcode == bcmOamMplsLmDmOpcodeTypeLm) || 2805 (opcode == bcmOamMplsLmDmOpcodeTypeLmPlusDm)) { 2806 rv = _sb2_oam_opcode_control_field_set(unit, &hash_data, 2807 bcmOAMActionSampleLmCounter, 2808 mem, opcode, 1, 2809 entry); 2810 } 2811 if (BCM_FAILURE(rv)) { 2812 return rv; 2813 } 2814 /* Sample timestamp for DM opcodes */ 2815 if ((opcode == bcmOamMplsLmDmOpcodeTypeDm) || 2816 (opcode == bcmOamMplsLmDmOpcodeTypeLmPlusDm) || 2817 (opcode == bcmOamMplsLmDmOpcodeTypeIlmPlusDm)) { 2818 rv = _sb2_oam_opcode_control_field_set(unit, &hash_data, 2819 bcmOAMActionSampleTimeStamp, 2820 mem, opcode, 1, 2821 entry); 2822 } 2823 if (BCM_FAILURE(rv)) { 2824 return rv; 2825 } 2826 } 2827 return rv; 2828 } 2829 2830 /* 2831 * Function: 2832 * _bcm_sb2_oam_opcode_profile_entry_init 2833 * Purpose: 2834 * Setup default OAM opcode control profile settings for MEP. 2835 * Parameters: 2836 * unit - (IN) BCM device number 2837 * mem - (IN) Opcode profile memory - ingress/egress 2838 * entry - (IN/OUT) Pointer to opcode control profile table entry buffer. 2839 * Retruns: 2840 * BCM_E_XXX 2841 */ 2842 int 2843 _bcm_sb2_oam_opcode_profile_entry_init(int unit, 2844 soc_mem_t mem, 2845 void *entry) 2846 { 2847 uint32 opcode; /* Opcode flag bits. */ 2848 int rv; /* Operation return status. */ 2849 2850 _bcm_oam_hash_data_t h_data; 2851 sal_memset(&h_data, 0, sizeof(_bcm_oam_hash_data_t)); 2852 2853 opcode = (BCM_OAM_OPCODE_CCM_COPY_TO_CPU | 2854 BCM_OAM_OPCODE_CCM_DROP | 2855 BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU | 2856 BCM_OAM_OPCODE_LBM_UC_DROP | 2857 BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU | 2858 BCM_OAM_OPCODE_LBM_MC_DROP | 2859 BCM_OAM_OPCODE_LBR_COPY_TO_CPU | 2860 BCM_OAM_OPCODE_LBR_DROP | 2861 BCM_OAM_OPCODE_LTM_COPY_TO_CPU | 2862 BCM_OAM_OPCODE_LTM_DROP | 2863 BCM_OAM_OPCODE_LTR_COPY_TO_CPU | 2864 BCM_OAM_OPCODE_LTR_DROP | 2865 BCM_OAM_OPCODE_OTHER_COPY_TO_CPU | 2866 BCM_OAM_OPCODE_OTHER_DROP 2867 ); 2868 /* Initialize for Ethernet OAM */ 2869 h_data.type = bcmOAMEndpointTypeEthernet; 2870 rv = _bcm_sb2_oam_opcode_profile_entry_set(unit, &h_data, 2871 mem, opcode, entry); 2872 if (BCM_FAILURE(rv)) { 2873 return rv; 2874 } 2875 /* Initialize for BHH OAM. Using one of the types of BHH endpoints */ 2876 h_data.type = bcmOAMEndpointTypeBHHMPLS; 2877 rv = _bcm_sb2_oam_opcode_profile_entry_set(unit, &h_data, 2878 mem, opcode, entry); 2879 if (BCM_FAILURE(rv)) { 2880 return rv; 2881 } 2882 /* Initialize for MPLS LM/DM */ 2883 rv = _bcm_sb2_mpls_lmdm_opcode_profile_entry_init(unit, mem, entry); 2884 if (BCM_FAILURE(rv)) { 2885 return rv; 2886 } 2887 return rv; 2888 } 2889 2890 /* 2891 * Function: 2892 * _bcm_sb2_oam_mip_opcode_profile_entry_init 2893 * Purpose: 2894 * Setup default OAM opcode control profile settings for MIP. 2895 * Parameters: 2896 * unit - (IN) BCM device number 2897 * mem - (IN) Opcode profile memory - ingress/egress 2898 * entry - (IN/OUT) Pointer to opcode control profile table entry buffer. 2899 * Retruns: 2900 * BCM_E_XXX 2901 */ 2902 int 2903 _bcm_sb2_oam_mip_opcode_profile_entry_init(int unit, 2904 soc_mem_t mem, 2905 void *entry) 2906 { 2907 uint32 opcode; /* Opcode flag bits. */ 2908 int rv; /* Operation return status. */ 2909 2910 _bcm_oam_hash_data_t h_data; 2911 sal_memset(&h_data, 0, sizeof(_bcm_oam_hash_data_t)); 2912 2913 h_data.flags |= BCM_OAM_ENDPOINT_INTERMEDIATE; 2914 2915 opcode = (BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU | 2916 BCM_OAM_OPCODE_LBM_UC_DROP | 2917 BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU | 2918 BCM_OAM_OPCODE_LBM_MC_DROP | 2919 BCM_OAM_OPCODE_LTM_COPY_TO_CPU | 2920 BCM_OAM_OPCODE_LTM_DROP); 2921 2922 /* Initialize for Ethernet OAM */ 2923 h_data.type = bcmOAMEndpointTypeEthernet; 2924 rv = _bcm_sb2_oam_opcode_profile_entry_set(unit, &h_data, 2925 mem, opcode, entry); 2926 if (BCM_FAILURE(rv)) { 2927 return rv; 2928 } 2929 /* Initialize for BHH OAM. Using one of the types of BHH endpoints */ 2930 h_data.type = bcmOAMEndpointTypeBHHMPLS; 2931 rv = _bcm_sb2_oam_opcode_profile_entry_set(unit, &h_data, 2932 mem, opcode, entry); 2933 if (BCM_FAILURE(rv)) { 2934 return rv; 2935 } 2936 /* No Initialization for MPLS LM/DM on MIP */ 2937 return rv; 2938 } 2939 2940 /* 2941 * Function: 2942 * _bcm_sb2_oam_lookup_interface_priorities_init 2943 * Purpose: 2944 * Init ingress and egress OAM_INTF_PROC_SELECT_CONTROL registers. 2945 * Parameters: 2946 * unit - (IN) BCM device number 2947 * Returns: 2948 * BCM_E_XXX 2949 */ 2950 int 2951 _bcm_sb2_oam_lookup_interface_priorities_init (int unit) 2952 { 2953 uint64 intf_select; 2954 uint64 egr_intf_select; 2955 uint64 write_val; 2956 2957 /* Default intf selection values for Ingress */ 2958 uint32 intf0_select = _BCM_OAM_DOMAIN_CVLAN; 2959 uint32 intf1_select = _BCM_OAM_DOMAIN_SVLAN; 2960 uint32 intf2_select = _BCM_OAM_DOMAIN_S_PLUS_CVLAN; 2961 uint32 intf3_select = _BCM_OAM_DOMAIN_VP; 2962 uint32 intf4_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION; 2963 uint32 intf5_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_CVLAN; 2964 uint32 intf6_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_SVLAN; 2965 uint32 intf7_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN; 2966 uint32 intf8_select = _BCM_SB2_OAM_DOMAIN_ING_MPLS_LMDM_LSP; 2967 uint32 intf9_select = _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW; 2968 2969 /* Default intf selection values for Egress */ 2970 uint32 egr_intf0_select = _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW; 2971 uint32 egr_intf1_select = _BCM_SB2_OAM_DOMAIN_EGR_MPLS_LMDM_LSP; 2972 uint32 egr_intf2_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN; 2973 uint32 egr_intf3_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_SVLAN; 2974 uint32 egr_intf4_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_CVLAN; 2975 uint32 egr_intf5_select = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION; 2976 uint32 egr_intf6_select = _BCM_OAM_DOMAIN_VP; 2977 uint32 egr_intf7_select = _BCM_OAM_DOMAIN_S_PLUS_CVLAN; 2978 uint32 egr_intf8_select = _BCM_OAM_DOMAIN_SVLAN; 2979 uint32 egr_intf9_select = _BCM_OAM_DOMAIN_CVLAN; 2980 2981 COMPILER_64_ZERO(intf_select); 2982 COMPILER_64_ZERO(egr_intf_select); 2983 COMPILER_64_ZERO(write_val); 2984 2985 /* Ingress OAM_INTF_PROC_SELECT_CONTROL register config */ 2986 SOC_IF_ERROR_RETURN( 2987 READ_OAM_INTF_PROC_SELECT_CONTROL_64r(unit, &intf_select)); 2988 COMPILER_64_SET(write_val, 0, intf0_select); 2989 soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select, 2990 INTF0f, write_val); 2991 COMPILER_64_SET(write_val, 0, intf1_select); 2992 soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select, 2993 INTF1f, write_val); 2994 COMPILER_64_SET(write_val, 0, intf2_select); 2995 soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select, 2996 INTF2f, write_val); 2997 COMPILER_64_SET(write_val, 0, intf3_select); 2998 soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select, 2999 INTF3f, write_val); 3000 COMPILER_64_SET(write_val, 0, intf4_select); 3001 soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select, 3002 INTF4f, write_val); 3003 COMPILER_64_SET(write_val, 0, intf5_select); 3004 soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select, 3005 INTF5f, write_val); 3006 COMPILER_64_SET(write_val, 0, intf6_select); 3007 soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select, 3008 INTF6f, write_val); 3009 COMPILER_64_SET(write_val, 0, intf7_select); 3010 soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select, 3011 INTF7f, write_val); 3012 COMPILER_64_SET(write_val, 0, intf8_select); 3013 soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select, 3014 INTF8f, write_val); 3015 COMPILER_64_SET(write_val, 0, intf9_select); 3016 soc_reg64_field_set(unit, OAM_INTF_PROC_SELECT_CONTROL_64r, &intf_select, 3017 INTF9f, write_val); 3018 3019 SOC_IF_ERROR_RETURN( 3020 WRITE_OAM_INTF_PROC_SELECT_CONTROL_64r(unit, intf_select)); 3021 3022 /* Egress OAM_INTF_PROC_SELECT_CONTROL register config */ 3023 3024 SOC_IF_ERROR_RETURN( 3025 READ_EGR_OAM_INTF_PROC_SELECT_CONTROL_64r(unit, &egr_intf_select)); 3026 3027 COMPILER_64_SET(write_val, 0, egr_intf0_select); 3028 soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r, 3029 &egr_intf_select, INTF0f, write_val); 3030 COMPILER_64_SET(write_val, 0, egr_intf1_select); 3031 soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r, 3032 &egr_intf_select, INTF1f, write_val); 3033 COMPILER_64_SET(write_val, 0, egr_intf2_select); 3034 soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r, 3035 &egr_intf_select, INTF2f, write_val); 3036 COMPILER_64_SET(write_val, 0, egr_intf3_select); 3037 soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r, 3038 &egr_intf_select, INTF3f, write_val); 3039 COMPILER_64_SET(write_val, 0, egr_intf4_select); 3040 soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r, 3041 &egr_intf_select, INTF4f, write_val); 3042 COMPILER_64_SET(write_val, 0, egr_intf5_select); 3043 soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r, 3044 &egr_intf_select, INTF5f, write_val); 3045 COMPILER_64_SET(write_val, 0, egr_intf6_select); 3046 soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r, 3047 &egr_intf_select, INTF6f, write_val); 3048 COMPILER_64_SET(write_val, 0, egr_intf7_select); 3049 soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r, 3050 &egr_intf_select, INTF7f, write_val); 3051 COMPILER_64_SET(write_val, 0, egr_intf8_select); 3052 soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r, 3053 &egr_intf_select, INTF8f, write_val); 3054 COMPILER_64_SET(write_val, 0, egr_intf9_select); 3055 soc_reg64_field_set(unit, EGR_OAM_INTF_PROC_SELECT_CONTROL_64r, 3056 &egr_intf_select, INTF9f, write_val); 3057 3058 SOC_IF_ERROR_RETURN( 3059 WRITE_EGR_OAM_INTF_PROC_SELECT_CONTROL_64r(unit, egr_intf_select)); 3060 3061 return (BCM_E_NONE); 3062 } 3063 3064 /* 3065 * Function: 3066 * _bcm_sb2_oam_lookup_key_priorities_init 3067 * Purpose: 3068 * Init ingress and egress OAM_KEY_SELECT_CONTROL registers. 3069 * Parameters: 3070 * unit - (IN) BCM device number 3071 * Returns: 3072 * BCM_E_XXX 3073 */ 3074 int 3075 _bcm_sb2_oam_lookup_key_priorities_init (int unit) 3076 { 3077 uint64 key_select; 3078 uint64 egr_key_select; 3079 uint64 write_val; 3080 3081 /* Default key selection values for Ingress */ 3082 uint32 key0_select = 2;/*VFP_KEY1*/ 3083 uint32 key1_select = 3;/*VFP_KEY2*/ 3084 uint32 key2_select = 0;/*ETH_KEY1*/ 3085 uint32 key3_select = 1;/*ETH_KEY2*/ 3086 uint32 key4_select = 4;/*MPLS_KEY1*/ 3087 uint32 key5_select = 5;/*MPLS_KEY2*/ 3088 uint32 key6_select = 6;/*MPLS_KEY3*/ 3089 uint32 key7_select = 7;/*SVP_KEY*/ 3090 uint32 key8_select = 8;/*SECTION_MEP_KEY*/ 3091 3092 /* Default key selection values for Egress */ 3093 uint32 egr_key0_select = 2;/*DVP_KEY*/ 3094 uint32 egr_key1_select = 3;/*MEPID*/ 3095 uint32 egr_key2_select = 0;/*ETH_KEY1*/ 3096 uint32 egr_key3_select = 1;/*ETH_KEY2*/ 3097 uint32 egr_key4_select = 4;/*SECTION_MEP_KEY*/ 3098 3099 COMPILER_64_ZERO(key_select); 3100 COMPILER_64_ZERO(egr_key_select); 3101 COMPILER_64_ZERO(write_val); 3102 3103 /* Ingress OAM_KEY_SELECT_CONTROL register config */ 3104 COMPILER_64_SET(write_val, 0, key0_select); 3105 soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select, 3106 KEY0f, write_val); 3107 COMPILER_64_SET(write_val, 0, key1_select); 3108 soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select, 3109 KEY1f, write_val); 3110 COMPILER_64_SET(write_val, 0, key2_select); 3111 soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select, 3112 KEY2f, write_val); 3113 COMPILER_64_SET(write_val, 0, key3_select); 3114 soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select, 3115 KEY3f, write_val); 3116 COMPILER_64_SET(write_val, 0, key4_select); 3117 soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select, 3118 KEY4f, write_val); 3119 COMPILER_64_SET(write_val, 0, key5_select); 3120 soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select, 3121 KEY5f, write_val); 3122 COMPILER_64_SET(write_val, 0, key6_select); 3123 soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select, 3124 KEY6f, write_val); 3125 COMPILER_64_SET(write_val, 0, key7_select); 3126 soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select, 3127 KEY7f, write_val); 3128 COMPILER_64_SET(write_val, 0, key8_select); 3129 soc_reg64_field_set(unit, OAM_KEY_SELECT_CONTROL_64r, &key_select, 3130 KEY8f, write_val); 3131 3132 SOC_IF_ERROR_RETURN(WRITE_OAM_KEY_SELECT_CONTROL_64r(unit, key_select)); 3133 3134 /* Egress OAM_KEY_SELECT_CONTROL register config */ 3135 3136 SOC_IF_ERROR_RETURN(READ_EGR_OAM_KEY_SELECT_CONTROL_64r(unit, &egr_key_select)); 3137 3138 COMPILER_64_SET(write_val, 0, egr_key0_select); 3139 soc_reg64_field_set(unit, EGR_OAM_KEY_SELECT_CONTROL_64r, &egr_key_select, 3140 KEY0f, write_val); 3141 COMPILER_64_SET(write_val, 0, egr_key1_select); 3142 soc_reg64_field_set(unit, EGR_OAM_KEY_SELECT_CONTROL_64r, &egr_key_select, 3143 KEY1f, write_val); 3144 COMPILER_64_SET(write_val, 0, egr_key2_select); 3145 soc_reg64_field_set(unit, EGR_OAM_KEY_SELECT_CONTROL_64r, &egr_key_select, 3146 KEY2f, write_val); 3147 COMPILER_64_SET(write_val, 0, egr_key3_select); 3148 soc_reg64_field_set(unit, EGR_OAM_KEY_SELECT_CONTROL_64r, &egr_key_select, 3149 KEY3f, write_val); 3150 COMPILER_64_SET(write_val, 0, egr_key4_select); 3151 soc_reg64_field_set(unit, EGR_OAM_KEY_SELECT_CONTROL_64r, &egr_key_select, 3152 KEY4f, write_val); 3153 3154 SOC_IF_ERROR_RETURN(WRITE_EGR_OAM_KEY_SELECT_CONTROL_64r(unit, egr_key_select)); 3155 3156 return (BCM_E_NONE); 3157 } 3158 3159 /* Entry indexes in mpls_oam_ach_type_config table for various 3160 * mpls lm dm ach types. 3161 * NOTE: 3162 * If you change these values, please make appropriate change in 3163 * _bcm_sb2_mpls_oam_ach_type_config_entry_t entry_info[] variable 3164 * in _bcm_sb2_oam_mpls_oam_ach_type_config_init function. 3165 */ 3166 #define _BCM_SB2_MPLS_LMDM_ACH_TYPE_LM_ENTRY 0x1 3167 #define _BCM_SB2_MPLS_LMDM_ACH_TYPE_ILM_ENTRY 0x2 3168 #define _BCM_SB2_MPLS_LMDM_ACH_TYPE_DM_ENTRY 0x3 3169 #define _BCM_SB2_MPLS_LMDM_ACH_TYPE_LMPLUSDM_ENTRY 0x4 3170 #define _BCM_SB2_MPLS_LMDM_ACH_TYPE_ILMPLUSDM_ENTRY 0x5 3171 3172 int 3173 _bcm_sb2_mpls_lmdm_ach_type_counter_enable(int unit, int opcode, int value) 3174 { 3175 int index = 0; 3176 soc_mem_t mem = MPLS_OAM_ACH_TYPE_CONFIGm; 3177 3178 switch (opcode) { 3179 case bcmOamMplsLmDmOpcodeTypeLm: 3180 index = _BCM_SB2_MPLS_LMDM_ACH_TYPE_LM_ENTRY; 3181 break; 3182 case bcmOamMplsLmDmOpcodeTypeIlm: 3183 index = _BCM_SB2_MPLS_LMDM_ACH_TYPE_ILM_ENTRY; 3184 break; 3185 case bcmOamMplsLmDmOpcodeTypeDm: 3186 index = _BCM_SB2_MPLS_LMDM_ACH_TYPE_DM_ENTRY; 3187 break; 3188 case bcmOamMplsLmDmOpcodeTypeLmPlusDm: 3189 index = _BCM_SB2_MPLS_LMDM_ACH_TYPE_LMPLUSDM_ENTRY; 3190 break; 3191 case bcmOamMplsLmDmOpcodeTypeIlmPlusDm: 3192 index = _BCM_SB2_MPLS_LMDM_ACH_TYPE_ILMPLUSDM_ENTRY; 3193 break; 3194 default: 3195 /* Other opcodes are not expected. */ 3196 return BCM_E_PARAM; 3197 break; 3198 } 3199 return (soc_mem_field32_modify(unit, mem, index, 3200 LM_COUNT_ENABLEf, value)); 3201 } 3202 3203 /* 3204 * Function: 3205 * _bcm_sb2_oam_mpls_oam_ach_type_config_init 3206 * Purpose: 3207 * Init ingress MPLS OAM ACH TYPE CONFIG table. 3208 * Parameters: 3209 * unit - (IN) BCM device number 3210 * Returns: 3211 * BCM_E_XXX 3212 */ 3213 int 3214 _bcm_sb2_oam_mpls_oam_ach_type_config_init(int unit) 3215 { 3216 int rv = BCM_E_NONE; 3217 mpls_oam_ach_type_config_entry_t *mpls_oam_ach_type_config_buf; 3218 int entry_mem_size; 3219 int index = 0; 3220 int entries_max = 0; 3221 soc_mem_t mem = MPLS_OAM_ACH_TYPE_CONFIGm; 3222 3223 _bcm_sb2_mpls_oam_ach_type_config_entry_t entry_info[]= { 3224 /* Valid, 3225 ach_type, 3226 opcode_valid, 3227 opcode, 3228 lm_count_enable, 3229 protocol_type 3230 */ 3231 {1, SHR_BHH_ACH_CHANNEL_TYPE, 0, -1, 0, 0}, /* BHH OAM */ 3232 {1, SHR_MPLS_LM_DM_ACH_TYPE_DLM, 1, bcmOamMplsLmDmOpcodeTypeLm, 0, 1}, /* MPLS LM */ 3233 {1, SHR_MPLS_LM_DM_ACH_TYPE_ILM, 1, bcmOamMplsLmDmOpcodeTypeIlm, 0, 1}, /* MPLS ILM */ 3234 {1, SHR_MPLS_LM_DM_ACH_TYPE_DM, 1, bcmOamMplsLmDmOpcodeTypeDm, 0, 1}, /* MPLS DM */ 3235 {1, SHR_MPLS_LM_DM_ACH_TYPE_DLM_DM, 1, bcmOamMplsLmDmOpcodeTypeLmPlusDm, 0, 1}, /* MPLS LM + DM */ 3236 {1, SHR_MPLS_LM_DM_ACH_TYPE_ILM_DM, 1, bcmOamMplsLmDmOpcodeTypeIlmPlusDm, 0, 1}, /* MPLS ILM + DM */ 3237 {1, 0x0022, 0, -1, 0, 2}, /* BFD CC */ 3238 {1, 0x0023, 0, -1, 0, 2}, /* BFD CV */ 3239 {1, 0x0007, 0, -1, 0, 3}, /* BFD Raw */ 3240 {1, 0x0021, 0, -1, 0, 5}, /* PW BFD IPv4 */ 3241 {1, 0x0057, 0, -1, 0, 5}, /* PW BFD IPv6 */ 3242 }; 3243 3244 entries_max = 3245 sizeof(entry_info)/sizeof(_bcm_sb2_mpls_oam_ach_type_config_entry_t); 3246 3247 entry_mem_size = sizeof(mpls_oam_ach_type_config_entry_t); 3248 3249 mpls_oam_ach_type_config_buf = soc_cm_salloc(unit, 3250 entry_mem_size, 3251 "MPLS OAM ACH TYPE CONFIG entry buffer"); 3252 3253 for (index = 0; index < entries_max; index++) 3254 { 3255 sal_memset(mpls_oam_ach_type_config_buf, 0, entry_mem_size); 3256 soc_mem_field32_set(unit, mem, 3257 (uint32 *)mpls_oam_ach_type_config_buf, VALIDf, 3258 entry_info[index].valid); 3259 soc_mem_field32_set(unit, mem, 3260 (uint32 *)mpls_oam_ach_type_config_buf, ACH_TYPEf, 3261 entry_info[index].ach_type); 3262 soc_mem_field32_set(unit, mem, 3263 (uint32 *)mpls_oam_ach_type_config_buf, OPCODE_VALIDf, 3264 entry_info[index].opcode_valid); 3265 if(entry_info[index].opcode != -1) 3266 { 3267 soc_mem_field32_set(unit, mem, 3268 (uint32 *)mpls_oam_ach_type_config_buf, OPCODEf, 3269 entry_info[index].opcode); 3270 } 3271 soc_mem_field32_set(unit, mem, 3272 (uint32 *)mpls_oam_ach_type_config_buf, LM_COUNT_ENABLEf, 3273 entry_info[index].lm_count_enable); 3274 soc_mem_field32_set(unit, mem, 3275 (uint32 *)mpls_oam_ach_type_config_buf, PROTOCOL_TYPEf, 3276 entry_info[index].protocol_type); 3277 3278 rv = soc_mem_write(unit, mem, 3279 MEM_BLOCK_ALL, index, mpls_oam_ach_type_config_buf); 3280 if (BCM_FAILURE(rv)) { 3281 if (mpls_oam_ach_type_config_buf) { 3282 soc_cm_sfree(unit, mpls_oam_ach_type_config_buf); 3283 } 3284 return rv; 3285 } 3286 } 3287 3288 if (mpls_oam_ach_type_config_buf) { 3289 soc_cm_sfree(unit, mpls_oam_ach_type_config_buf); 3290 } 3291 3292 return rv; 3293 } 3294 3295 /* 3296 * Function: 3297 * _bcm_sb2_oam_opcode_group_init 3298 * Purpose: 3299 * Init ingress and egress OAM opcode groups. 3300 * Parameters: 3301 * unit - (IN) BCM device number 3302 * Retruns: 3303 * BCM_E_XXX 3304 */ 3305 int 3306 _bcm_sb2_oam_opcode_group_init(int unit) 3307 { 3308 int rv = BCM_E_NONE; 3309 oam_opcode_group_entry_t *opcode_grp_buf; 3310 int entry_mem_size; /* Size of table entry. */ 3311 int index = 0; 3312 int entries_max = 0; 3313 _bcm_sb2_opcode_group_entry_t entry_info[] = { 3314 3315 /* ETH OAM */ 3316 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_CCM), 3317 _BCM_SB2_OPCODE_GROUP_ETH_OAM_CCM , 3318 _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH, 3319 _BCM_SB2_ETH_OAM_CCM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM CCM */ 3320 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LBR), 3321 _BCM_SB2_OPCODE_GROUP_ETH_OAM_LBR , 3322 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3323 _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LBR */ 3324 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LBM), 3325 _BCM_SB2_OPCODE_GROUP_ETH_OAM_LBM , 3326 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3327 _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LBM */ 3328 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LTR), 3329 _BCM_SB2_OPCODE_GROUP_ETH_OAM_LTR , 3330 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3331 _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LTR */ 3332 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LTM), 3333 _BCM_SB2_OPCODE_GROUP_ETH_OAM_LTM, 3334 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3335 _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LTM */ 3336 3337 /* NON CFM */ 3338 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LMM), 3339 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 , 3340 _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM, 3341 _BCM_SB2_ETH_OAM_LM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LMM */ 3342 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LMR), 3343 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 , 3344 _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM, 3345 _BCM_SB2_ETH_OAM_LM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LMR */ 3346 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_1DM), 3347 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 , 3348 _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM, 3349 _BCM_SB2_ETH_OAM_DM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM 1DM */ 3350 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_DMM), 3351 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 , 3352 _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM, 3353 _BCM_SB2_ETH_OAM_DM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM DMM */ 3354 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_DMR), 3355 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 , 3356 _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM, 3357 _BCM_SB2_ETH_OAM_DM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM DMR */ 3358 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_SLM), 3359 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 , 3360 _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM, 3361 _BCM_SB2_ETH_OAM_LM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM SLM */ 3362 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_SLR), 3363 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 , 3364 _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM, 3365 _BCM_SB2_ETH_OAM_LM_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM SLR */ 3366 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_AIS), 3367 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 , 3368 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3369 _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM AIS */ 3370 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LCK), 3371 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 , 3372 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3373 _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LCK */ 3374 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_TST), 3375 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 , 3376 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3377 _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM TST */ 3378 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LIN_APS), 3379 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 , 3380 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3381 _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM LIN_APS */ 3382 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_RING_APS), 3383 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_1 , 3384 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3385 _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM RING_APS */ 3386 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_MCC), 3387 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 , 3388 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3389 _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM MCC */ 3390 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_EXM), 3391 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 , 3392 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3393 _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM EXM */ 3394 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_EXR), 3395 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 , 3396 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3397 _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM EXR */ 3398 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_VSM), 3399 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 , 3400 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3401 _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM VSM */ 3402 {_BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_VSR), 3403 _BCM_SB2_OPCODE_GROUP_ETH_OAM_OTHER_2 , 3404 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3405 _BCM_SB2_ETH_OAM_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* ETH OAM VSR */ 3406 3407 /* BHH OAM */ 3408 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_CCM), 3409 _BCM_SB2_OPCODE_GROUP_BHH_OAM_CCM , 3410 _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH}, /* BHH OAM CCM */ 3411 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LBR), 3412 _BCM_SB2_OPCODE_GROUP_BHH_OAM_LBR , 3413 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW}, /* BHH OAM LBR */ 3414 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LBM), 3415 _BCM_SB2_OPCODE_GROUP_BHH_OAM_LBM , 3416 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW}, /* BHH OAM LBM */ 3417 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LTR), 3418 _BCM_SB2_OPCODE_GROUP_BHH_OAM_LTR , 3419 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW}, /* BHH OAM LTR */ 3420 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LTM), 3421 _BCM_SB2_OPCODE_GROUP_BHH_OAM_LTM, 3422 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW}, /* BHH OAM LTM */ 3423 3424 /* NON CFM */ 3425 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LMM), 3426 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 , 3427 _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM}, /* BHH OAM LMM */ 3428 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LMR), 3429 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 , 3430 _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM}, /* BHH OAM LMR */ 3431 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_1DM), 3432 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 , 3433 _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM}, /* BHH OAM 1DM */ 3434 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_DMM), 3435 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 , 3436 _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM}, /* BHH OAM DMM */ 3437 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_DMR), 3438 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 , 3439 _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM}, /* BHH OAM DMR */ 3440 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_SLM), 3441 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 , 3442 _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM}, /* BHH OAM SLM */ 3443 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_SLR), 3444 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 , 3445 _BCM_SB2_OPCODE_GROUP_CPU_PRI_MEDIUM}, /* BHH OAM SLR */ 3446 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_AIS), 3447 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 , 3448 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3449 _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM AIS */ 3450 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LCK), 3451 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 , 3452 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3453 _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM LCK */ 3454 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_TST), 3455 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 , 3456 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3457 _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM TST */ 3458 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_LIN_APS), 3459 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 , 3460 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3461 _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM LIN_APS */ 3462 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_RING_APS), 3463 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_1 , 3464 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3465 _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM RING_APS */ 3466 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_MCC), 3467 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 , 3468 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3469 _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM MCC */ 3470 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_EXM), 3471 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 , 3472 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3473 _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM EXM */ 3474 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_EXR), 3475 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 , 3476 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3477 _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM EXR */ 3478 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_VSM), 3479 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 , 3480 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3481 _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM VSM */ 3482 {_BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(_BCM_OAM_OPCODE_TYPE_VSR), 3483 _BCM_SB2_OPCODE_GROUP_BHH_OAM_OTHER_2 , 3484 _BCM_SB2_OPCODE_GROUP_CPU_PRI_LOW, 3485 _BCM_SB2_BHH_OTHER_OC_OLP_HDR_TYPE_COMPRESSED}, /* BHH OAM VSR */ 3486 3487 /* MPLS LM DM */ 3488 {_BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(bcmOamMplsLmDmOpcodeTypeLm), 3489 _BCM_SB2_OPCODE_GROUP_MPLS_LM, _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH, 3490 _BCM_SB2_MPLS_LMDM_DLM_OLP_HDR_TYPE_COMPRESSED}, /* MPLS (D)LM */ 3491 {_BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(bcmOamMplsLmDmOpcodeTypeIlm), 3492 _BCM_SB2_OPCODE_GROUP_MPLS_ILM, _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH, 3493 _BCM_SB2_MPLS_LMDM_ILM_OLP_HDR_TYPE_COMPRESSED}, /* MPLS ILM */ 3494 {_BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(bcmOamMplsLmDmOpcodeTypeDm), 3495 _BCM_SB2_OPCODE_GROUP_MPLS_DM, _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH, 3496 _BCM_SB2_MPLS_LMDM_DM_OLP_HDR_TYPE_COMPRESSED}, /* MPLS DM */ 3497 {_BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(bcmOamMplsLmDmOpcodeTypeLmPlusDm), 3498 _BCM_SB2_OPCODE_GROUP_MPLS_LM_PLUS_DM, _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH, 3499 _BCM_SB2_MPLS_LMDM_DLM_DM_OLP_HDR_TYPE_COMPRESSED}, /* MPLS (D)LM + DM */ 3500 {_BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(bcmOamMplsLmDmOpcodeTypeIlmPlusDm), 3501 _BCM_SB2_OPCODE_GROUP_MPLS_ILM_PLUS_DM, _BCM_SB2_OPCODE_GROUP_CPU_PRI_HIGH, 3502 _BCM_SB2_MPLS_LMDM_ILM_DM_OLP_HDR_TYPE_COMPRESSED}, /* MPLS (I)LM + DM */ 3503 3504 }; 3505 entries_max = sizeof(entry_info) / sizeof(_bcm_sb2_opcode_group_entry_t); 3506 3507 /* Set ingress and egress OAM opcode group */ 3508 entry_mem_size = sizeof(oam_opcode_group_entry_t); 3509 opcode_grp_buf = soc_cm_salloc(unit, entry_mem_size , 3510 "Opcode group entry buffer"); 3511 if (NULL == opcode_grp_buf) { 3512 return (BCM_E_MEMORY); 3513 } 3514 /* Initialize the entry buffer. */ 3515 sal_memset(opcode_grp_buf, 0, entry_mem_size); 3516 3517 for (index = 0; index < entries_max; index++) { 3518 soc_mem_field32_set(unit, OAM_OPCODE_GROUPm, 3519 (uint32 *)opcode_grp_buf, OPCODE_GROUPf, 3520 entry_info[index].opcode_group); 3521 soc_mem_field32_set(unit, OAM_OPCODE_GROUPm, 3522 (uint32 *)opcode_grp_buf, CPU_OPCODEf, 3523 entry_info[index].cpu_opcode); 3524 soc_mem_field32_set(unit, OAM_OPCODE_GROUPm, 3525 (uint32 *)opcode_grp_buf, OLP_HDR_TYPE_COMPRESSEDf, 3526 entry_info[index].olp_hdr_type_compressed); 3527 rv = soc_mem_write(unit, OAM_OPCODE_GROUPm, 3528 MEM_BLOCK_ALL, entry_info[index].key, opcode_grp_buf); 3529 if (BCM_FAILURE(rv)) { 3530 if (opcode_grp_buf) { 3531 soc_cm_sfree(unit, opcode_grp_buf); 3532 opcode_grp_buf = NULL; 3533 } 3534 return rv; 3535 } 3536 rv = soc_mem_write(unit, EGR_OAM_OPCODE_GROUPm, 3537 MEM_BLOCK_ALL, entry_info[index].key, opcode_grp_buf); 3538 if (BCM_FAILURE(rv)) { 3539 if (opcode_grp_buf) { 3540 soc_cm_sfree(unit, opcode_grp_buf); 3541 opcode_grp_buf = NULL; 3542 } 3543 return rv; 3544 } 3545 } 3546 if (opcode_grp_buf) { 3547 soc_cm_sfree(unit, opcode_grp_buf); 3548 } 3549 return (rv); 3550 } 3551 3552 3553 STATIC void 3554 _bcm_sb2_oam_get_passive_mdl_from_active_mdl(int unit, uint8 active_mdl, 3555 int ma_base_index, 3556 uint8 *passive_mdl, 3557 int is_upmep) 3558 { 3559 uint32 mdl_value[1] = { 0 }; 3560 int ma_offset = 0; 3561 int mdl = 0; 3562 bcm_oam_endpoint_t ep_id_at_mdl = _BCM_OAM_INVALID_INDEX; 3563 _bcm_oam_control_t *oc = NULL; 3564 _bcm_oam_hash_data_t *h_data_p = NULL; 3565 3566 /* coverity[check_return] */ 3567 _bcm_sb2_oam_control_get(unit, &oc); 3568 3569 if (oc == NULL) { 3570 /* Not expected */ 3571 return; 3572 } 3573 3574 /* Initialize passive_mdl to 0 */ 3575 *passive_mdl = 0; 3576 mdl_value[0] = active_mdl; 3577 3578 for (mdl = 0; mdl <= 7; mdl++) { 3579 if (SHR_BITGET(mdl_value, mdl)) { 3580 ep_id_at_mdl = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_get(oc, 3581 _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX 3582 (ma_base_index, ma_offset, is_upmep)); 3583 if (ep_id_at_mdl != _BCM_OAM_INVALID_INDEX) { 3584 h_data_p = &(oc->oam_hash_data[ep_id_at_mdl]); 3585 /* Set the passive bitmap only if it is not a MIP */ 3586 if (!_BCM_OAM_EP_IS_MIP(h_data_p)) { 3587 *passive_mdl = (1 << mdl) | ((1 << mdl) -1); 3588 } 3589 } else { 3590 /* Log an error. Ideally should not happen. */ 3591 LOG_ERROR(BSL_LS_BCM_OAM, 3592 (BSL_META_U(unit, 3593 "OAM(unit %d) Error: EP ID mapping get failed (MA_IDX=%d) -" 3594 "\n"), unit, ma_base_index+ma_offset)); 3595 } 3596 ma_offset++; 3597 } 3598 } 3599 } 3600 3601 3602 /* 3603 * Function: 3604 * _bcm_sb2_oam_ep_hash_key_construct 3605 * Purpose: 3606 * Construct hash table key for a given endpoint information. 3607 * Parameters: 3608 * unit - (IN) BCM device number 3609 * oc - (IN) Pointer to OAM control structure. 3610 * ep_info - (IN) Pointer to endpoint information structure. 3611 * key - (IN/OUT) Pointer to hash key buffer. 3612 * Retruns: 3613 * None 3614 */ 3615 STATIC void 3616 _bcm_sb2_oam_ep_hash_key_construct(int unit, 3617 _bcm_oam_control_t *oc, 3618 bcm_oam_endpoint_info_t *ep_info, 3619 _bcm_oam_hash_key_t *key) 3620 { 3621 uint8 *loc = *key; 3622 uint32 direction = 0; 3623 3624 sal_memset(key, 0, sizeof(_bcm_oam_hash_key_t)); 3625 3626 if (NULL != ep_info) { 3627 if ((ep_info->flags & BCM_OAM_ENDPOINT_UP_FACING)) { 3628 direction = 1; 3629 } 3630 3631 _BCM_OAM_KEY_PACK(loc, &ep_info->group, sizeof(ep_info->group)); 3632 3633 _BCM_OAM_KEY_PACK(loc, &ep_info->name, sizeof(ep_info->name)); 3634 3635 _BCM_OAM_KEY_PACK(loc, &ep_info->gport, sizeof(ep_info->gport)); 3636 3637 _BCM_OAM_KEY_PACK(loc, &ep_info->level, sizeof(ep_info->level)); 3638 3639 _BCM_OAM_KEY_PACK(loc, &ep_info->vlan, sizeof(ep_info->vlan)); 3640 3641 _BCM_OAM_KEY_PACK(loc, &ep_info->inner_vlan, 3642 sizeof(ep_info->inner_vlan)); 3643 _BCM_OAM_KEY_PACK(loc, &direction, sizeof(direction)); 3644 _BCM_OAM_KEY_PACK(loc, &ep_info->mpls_label, 3645 sizeof(ep_info->mpls_label)); 3646 _BCM_OAM_KEY_PACK(loc, &ep_info->type, sizeof(ep_info->type)); 3647 } 3648 3649 /* End address should not exceed size of _bcm_oam_hash_key_t. */ 3650 assert ((int) (loc - *key) <= sizeof(_bcm_oam_hash_key_t)); 3651 } 3652 3653 /* Return if a given PW endpoint's port is in protection or working state. 3654 Return values : 3655 0 - Working 3656 1 - Protection 3657 */ 3658 int 3659 _bcm_sb2_oam_mpls_lmdm_pw_protection_get(int unit, 3660 const _bcm_oam_hash_data_t *hash_data) 3661 { 3662 #if defined(INCLUDE_L3) 3663 int nh_index = 0, failover_nh_index = 0; 3664 ing_dvp_table_entry_t dvp; 3665 ing_l3_next_hop_entry_t failover_l3_next_hop; 3666 int rv = BCM_E_NONE; 3667 bcm_failover_t failover_id; 3668 bcm_multicast_t failover_mc_group; 3669 int failover_port_is_trunk = 0, failover_port_trunk = BCM_TRUNK_INVALID; 3670 int failover_port = 0, failover_modid = 0, mod_id = 0, port_id = 0; 3671 uint32 vp = hash_data->vp; 3672 3673 sal_memset(&dvp, 0, sizeof(ing_dvp_table_entry_t)); 3674 sal_memset(&failover_l3_next_hop, 0, sizeof(ing_l3_next_hop_entry_t)); 3675 3676 /* Read the ING_DVP table to get the next hop index */ 3677 rv = READ_ING_DVP_TABLEm(unit, MEM_BLOCK_ANY, vp, &dvp); 3678 if (BCM_FAILURE(rv)) { 3679 return 0; 3680 } 3681 3682 nh_index = soc_ING_DVP_TABLEm_field32_get(unit, &dvp, 3683 NEXT_HOP_INDEXf); 3684 3685 /* Use that nh index to find if there exists a failover nh index */ 3686 rv = _bcm_esw_failover_prot_nhi_get (unit, nh_index, 3687 &failover_id, &failover_nh_index, &failover_mc_group); 3688 3689 if (BCM_SUCCESS(rv)) { 3690 if (failover_nh_index > 0) { 3691 /* Failover enabled */ 3692 3693 /* Check if it is the same interface as ours. If it 3694 is the same interface, then our interface is in protection 3695 state else it is in working state. */ 3696 rv = READ_ING_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, failover_nh_index, 3697 &failover_l3_next_hop); 3698 if (BCM_FAILURE(rv)) { 3699 return 0; 3700 } 3701 failover_port_is_trunk = soc_ING_L3_NEXT_HOPm_field32_get(unit, 3702 &failover_l3_next_hop, 3703 Tf); 3704 if (failover_port_is_trunk) { 3705 if (hash_data->trunk_id != BCM_TRUNK_INVALID) { 3706 failover_port_trunk = soc_ING_L3_NEXT_HOPm_field32_get(unit, 3707 &failover_l3_next_hop, 3708 TGIDf); 3709 if (failover_port_trunk == hash_data->trunk_id) { 3710 /* Matched. Return PROTECTION state */ 3711 return 1; 3712 } 3713 /* No match. Return WORKING (or not PROTECTION) state */ 3714 return 0; 3715 } else { 3716 /* Endpoint port is not a trunk (or part of it), but 3717 failover port is. So return WORKING (or NOT PROTECTION). 3718 */ 3719 return 0; 3720 } 3721 } else { 3722 failover_modid = soc_ING_L3_NEXT_HOPm_field32_get(unit, 3723 &failover_l3_next_hop, 3724 MODULE_IDf); 3725 failover_port = soc_ING_L3_NEXT_HOPm_field32_get(unit, 3726 &failover_l3_next_hop, 3727 PORT_NUMf); 3728 port_id = _BCM_OAM_GLP_PORT_GET(hash_data->sglp); 3729 mod_id = _BCM_OAM_GLP_MODULE_ID_GET(hash_data->sglp); 3730 if ((failover_modid == mod_id) && 3731 (failover_port == port_id)) { 3732 /* Matched. Return PROTECTION state */ 3733 return 1; 3734 } 3735 return 0; 3736 } 3737 } 3738 return 0; 3739 } 3740 #endif /* INCLUDE_L3 */ 3741 return 0; 3742 } 3743 3744 STATIC void 3745 _bcm_sb2_oam_mpls_mp_group_key_construct (int unit, 3746 const _bcm_oam_hash_data_t *h_data_p, 3747 int is_egress, 3748 void *mp_group_key_p) 3749 { 3750 soc_field_t fields[4] = {INVALIDf, INVALIDf, INVALIDf, INVALIDf}; 3751 uint32 values[4] = {0,0,0,0}; 3752 int num_fields = 0; 3753 int field; 3754 #if defined(INCLUDE_BHH) 3755 _bcm_oam_control_t *oc; 3756 3757 /* coverity[check_return] */ 3758 _bcm_sb2_oam_control_get(unit, &oc); 3759 #endif /* INCLUDE_BHH */ 3760 3761 if ((MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) || 3762 (BHH_EP_MPLS_SECTION_TYPE(h_data_p))) { 3763 fields[0] = KEY_TYPEf; 3764 if ((h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionPort) || 3765 (h_data_p->type == bcmOAMEndpointTypeBhhSection)) { 3766 values[0] = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION; 3767 3768 fields[1] = GLPf; 3769 values[1] = h_data_p->sglp; 3770 3771 num_fields = 2; 3772 } else if ((h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionInnervlan) || 3773 (h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan)) { 3774 values[0] = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_CVLAN; 3775 3776 fields[1] = GLPf; 3777 values[1] = h_data_p->sglp; 3778 3779 fields[2] = CVIDf; 3780 values[2] = h_data_p->inner_vlan; 3781 3782 num_fields = 3; 3783 } else if ((h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionOuterVlan) || 3784 (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterVlan)) { 3785 values[0] = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_SVLAN; 3786 3787 fields[1] = GLPf; 3788 values[1] = h_data_p->sglp; 3789 3790 fields[2] = SVIDf; 3791 values[2] = h_data_p->vlan; 3792 3793 num_fields = 3; 3794 } else if ((h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan) || 3795 (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)) { 3796 values[0] = _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN; 3797 3798 fields[1] = GLPf; 3799 values[1] = h_data_p->sglp; 3800 3801 fields[2] = SVIDf; 3802 values[2] = h_data_p->vlan; 3803 3804 fields[3] = CVIDf; 3805 values[3] = h_data_p->inner_vlan; 3806 3807 num_fields = 4; 3808 } 3809 } else if ((MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p))|| 3810 (h_data_p->type == bcmOAMEndpointTypeBHHMPLS)) { 3811 fields[0] = KEY_TYPEf; 3812 if (is_egress) { 3813 values[0] = _BCM_SB2_OAM_DOMAIN_EGR_MPLS_LMDM_LSP; 3814 3815 fields[1] = MEPIDf; 3816 3817 if (MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) { 3818 values[1] = h_data_p->name; 3819 } else { 3820 #if defined(INCLUDE_BHH) 3821 values[1] = BCM_OAM_BHH_GET_LSP_KEY(h_data_p); 3822 #endif /* INCLUDE_BHH */ 3823 } 3824 3825 num_fields = 2; 3826 } else { 3827 values[0] = _BCM_SB2_OAM_DOMAIN_ING_MPLS_LMDM_LSP; 3828 #if defined(INCLUDE_L3) 3829 if (bcm_tr_mpls_port_independent_range(unit, h_data_p->label, 3830 BCM_GPORT_INVALID) != BCM_E_NONE) { 3831 /* SGLP contains generic logical port. */ 3832 fields[1] = GLPf; 3833 values[1] = h_data_p->sglp; 3834 } else { 3835 /* SGLP is invalid if label is port independent. */ 3836 fields[1] = GLPf; 3837 values[1] = 0xffff; 3838 } 3839 #else 3840 fields[1] = GLPf; 3841 values[1] = h_data_p->sglp; 3842 #endif 3843 3844 fields[2] = MPLS_LABELf; 3845 values[2] = h_data_p->label; 3846 3847 num_fields = 3; 3848 } 3849 } else if (MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p)) { 3850 fields[0] = KEY_TYPEf; 3851 values[0] = _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW; 3852 3853 fields[1] = VPf; 3854 if (is_egress) { 3855 values[1] = BCM_GPORT_MPLS_PORT_ID_GET(h_data_p->gport); 3856 } else { 3857 values[1] = h_data_p->vp; 3858 } 3859 3860 fields[2] = PROTECTIONf; 3861 if (is_egress) { 3862 values[2] = 0; /* Protection should be always set to 0 in egress */ 3863 } else { 3864 values[2] = _bcm_sb2_oam_mpls_lmdm_pw_protection_get(unit, h_data_p); 3865 } 3866 num_fields = 3; 3867 } else if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 3868 fields[0] = KEY_TYPEf; 3869 3870 if (is_egress) { 3871 values[0] = _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW; 3872 fields[1] = VPf; 3873 values[1] = BCM_GPORT_MPLS_PORT_ID_GET(h_data_p->gport); 3874 fields[2] = PROTECTIONf; 3875 values[2] = 0; 3876 } else { 3877 values[0] = _BCM_SB2_OAM_DOMAIN_ING_MPLS_LMDM_LSP; 3878 #if defined(INCLUDE_L3) 3879 if (bcm_tr_mpls_port_independent_range(unit, h_data_p->label, 3880 BCM_GPORT_INVALID) != BCM_E_NONE) { 3881 /* SGLP contains generic logical port. */ 3882 fields[1] = GLPf; 3883 values[1] = h_data_p->sglp; 3884 } else { 3885 /* SGLP is invalid if label is port independent. */ 3886 fields[1] = GLPf; 3887 values[1] = 0xffff; 3888 } 3889 #else 3890 fields[1] = GLPf; 3891 values[1] = h_data_p->sglp; 3892 #endif 3893 3894 fields[2] = MPLS_LABELf; 3895 values[2] = h_data_p->label; 3896 } 3897 num_fields = 3; 3898 } else { 3899 /* Should not be hit */ 3900 return; 3901 } 3902 3903 for (field = 0; field < num_fields; field++) { 3904 if (is_egress) { 3905 soc_EGR_MP_GROUPm_field32_set(unit, mp_group_key_p, fields[field], values[field]); 3906 } else { 3907 soc_MP_GROUPm_field32_set(unit, mp_group_key_p, fields[field], values[field]); 3908 } 3909 } 3910 } 3911 3912 /* 3913 * Function: 3914 * _bcm_sb2_oam_egr_lmep_key_construct 3915 * Purpose: 3916 * Construct egress MP group table lookup key for a given endpoint. 3917 * Parameters: 3918 * unit - (IN) BCM device number 3919 * h_data_p - (IN) Pointer to endpoint hash data memory. 3920 * egr_mp_grp_key_p - (IN/OUT) Pointer to entry buffer. 3921 * Retruns: 3922 * None 3923 */ 3924 STATIC void 3925 _bcm_sb2_oam_egr_lmep_key_construct(int unit, 3926 const _bcm_oam_hash_data_t *h_data_p, 3927 egr_mp_group_entry_t *egr_mp_grp_key_p) 3928 { 3929 _bcm_oam_control_t *oc = NULL; 3930 3931 /* coverity[check_return] */ 3932 _bcm_sb2_oam_control_get(unit, &oc); 3933 3934 /* Set the valid bit. */ 3935 soc_EGR_MP_GROUPm_field32_set 3936 (unit, egr_mp_grp_key_p, VALIDf, 1); 3937 /* Set the search key type. */ 3938 soc_EGR_MP_GROUPm_field32_set 3939 (unit, egr_mp_grp_key_p, KEY_TYPEf, h_data_p->oam_domain); 3940 3941 3942 if (BHH_EP_TYPE(h_data_p) || MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 3943 _bcm_sb2_oam_mpls_mp_group_key_construct(unit, h_data_p, 1, 3944 egr_mp_grp_key_p); 3945 } else if (_BCM_OAM_EP_IS_ETH_OAM_VP_TYPE(h_data_p)) { 3946 /* Set port type status in the search key. 3947 * VP field contains virtual port. 3948 */ 3949 soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p, VPf, h_data_p->vp); 3950 } else { 3951 if (oc->eth_oam_mp_group_vlan_key == 3952 _BCM_SB2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT) { 3953 /* In earlier versions of the SDK, both inner & outer vlan was always 3954 * programmed in the MP_GROUP irrespective of the MEP type, this has 3955 * been changed to program only CVLAN for CVLAN MEPs and SVLAN for 3956 * SVLAN MEPs. To avoid breaking warm-upgrade the old scheme is still 3957 * supported. 3958 */ 3959 soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p, 3960 SVIDf, h_data_p->vlan); 3961 3962 soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p, 3963 CVIDf, h_data_p->inner_vlan); 3964 3965 } else { 3966 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_CVLAN) { 3967 /* SVLAN/C+SVLAN */ 3968 soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p, 3969 SVIDf, h_data_p->vlan); 3970 } 3971 3972 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_SVLAN) { 3973 /* CLVAN/C+SVLAN */ 3974 soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p, 3975 CVIDf, h_data_p->inner_vlan); 3976 } 3977 } 3978 /* DGLP contains generic logical port. */ 3979 soc_EGR_MP_GROUPm_field32_set(unit, egr_mp_grp_key_p, 3980 GLPf, h_data_p->dglp); 3981 } 3982 } 3983 3984 /* 3985 * Function: 3986 * _bcm_sb2_oam_lmep_key_construct 3987 * Purpose: 3988 * Construct LMEP view lookup key for a given endpoint. 3989 * Parameters: 3990 * unit - (IN) BCM device number 3991 * h_data_p - (IN) Pointer to endpoint hash data memory. 3992 * mp_group_key_p - (IN/OUT) Pointer to entry buffer. 3993 * Retruns: 3994 * None 3995 */ 3996 STATIC void 3997 _bcm_sb2_oam_lmep_key_construct(int unit, 3998 const _bcm_oam_hash_data_t *h_data_p, 3999 mp_group_entry_t *mp_group_key_p) 4000 { 4001 _bcm_oam_control_t *oc = NULL; 4002 4003 /* coverity[check_return] */ 4004 _bcm_sb2_oam_control_get(unit, &oc); 4005 4006 /* Set the search key type. */ 4007 soc_MP_GROUPm_field32_set(unit, mp_group_key_p, KEY_TYPEf, 4008 h_data_p->oam_domain); 4009 4010 if (BHH_EP_TYPE(h_data_p) || MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 4011 _bcm_sb2_oam_mpls_mp_group_key_construct(unit, h_data_p, 4012 0, mp_group_key_p); 4013 4014 } else if (_BCM_OAM_EP_IS_ETH_OAM_VP_TYPE(h_data_p)) { 4015 /* Set port type status in the search key. 4016 * Vp field contains virtual port. 4017 */ 4018 soc_MP_GROUPm_field32_set(unit, mp_group_key_p, VPf, h_data_p->vp); 4019 4020 } else { /* Ethernet */ 4021 4022 if (oc->eth_oam_mp_group_vlan_key == 4023 _BCM_SB2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT) { 4024 /* In earlier versions of the SDK, both inner & outer vlan was always 4025 * programmed in the MP_GROUP irrespective of the MEP type, this has 4026 * been changed to program only CVLAN for CVLAN MEPs and SVLAN for 4027 * SVLAN MEPs. To avoid breaking warm-upgrade the old scheme is still 4028 * supported. 4029 */ 4030 soc_MP_GROUPm_field32_set(unit, mp_group_key_p, 4031 SVIDf, h_data_p->vlan); 4032 4033 soc_MP_GROUPm_field32_set(unit, mp_group_key_p, 4034 CVIDf, h_data_p->inner_vlan); 4035 4036 } else { 4037 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_CVLAN) { 4038 /* SVLAN/C+SVLAN */ 4039 soc_MP_GROUPm_field32_set(unit, mp_group_key_p, 4040 SVIDf, h_data_p->vlan); 4041 } 4042 4043 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_SVLAN) { 4044 /* CLVAN/C+SVLAN */ 4045 soc_MP_GROUPm_field32_set(unit, mp_group_key_p, 4046 CVIDf, h_data_p->inner_vlan); 4047 } 4048 } 4049 /* SGLP contains generic logical port. */ 4050 soc_MP_GROUPm_field32_set(unit, mp_group_key_p, 4051 GLPf, h_data_p->sglp); 4052 } 4053 } 4054 4055 /* 4056 * Function: 4057 * _bcm_sb2_oam_rmep_key_construct 4058 * Purpose: 4059 * Construct RMEP view lookup key for a given endpoint. 4060 * Parameters: 4061 * unit - (IN) BCM device number 4062 * h_data_p - (IN) Pointer to endpoint hash data memory. 4063 * l3_key_p - (IN/OUT) Pointer to entry buffer. 4064 * Retruns: 4065 * None 4066 */ 4067 STATIC void 4068 _bcm_sb2_oam_rmep_key_construct(int unit, 4069 const _bcm_oam_hash_data_t *h_data_p, 4070 l3_entry_1_entry_t *l3_key_p) 4071 { 4072 4073 /* Set the search key type. */ 4074 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 4075 (unit, l3_key_p, KEY_TYPEf, SOC_MEM_KEY_L3_ENTRY_RMEP); 4076 4077 /* Set endpoint name. */ 4078 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 4079 (unit, l3_key_p, RMEP__MEPIDf, h_data_p->name); 4080 4081 /* Set MA_PTR */ 4082 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 4083 (unit, l3_key_p, RMEP__MA_PTRf, h_data_p->group_index); 4084 4085 } 4086 4087 #if defined(KEY_PRINT) 4088 /* 4089 * Function: 4090 * _bcm_oam_hash_key_print 4091 * Purpose: 4092 * Print the contents of a hash key buffer. 4093 * Parameters: 4094 * hash_key - (IN) Pointer to hash key buffer. 4095 * Retruns: 4096 * None 4097 */ 4098 STATIC void 4099 _bcm_oam_hash_key_print(_bcm_oam_hash_key_t *hash_key) 4100 { 4101 int i; 4102 LOG_CLI((BSL_META_U(unit, 4103 "HASH KEY:"))); 4104 for(i = 0; i < _OAM_HASH_KEY_SIZE; i++) { 4105 LOG_CLI((BSL_META_U(unit, 4106 ":%u"), *(hash_key[i]))); 4107 } 4108 LOG_CLI((BSL_META_U(unit, 4109 "\n"))); 4110 } 4111 #endif 4112 4113 /* 4114 * Function: 4115 * _bcm_sb2_oam_control_get 4116 * Purpose: 4117 * Lookup a OAM control config from a bcm device id. 4118 * Parameters: 4119 * unit - (IN)BCM unit number. 4120 * oc - (OUT) OAM control structure. 4121 * Retruns: 4122 * BCM_E_XXX 4123 */ 4124 STATIC int 4125 _bcm_sb2_oam_control_get(int unit, _bcm_oam_control_t **oc) 4126 { 4127 if (NULL == oc) { 4128 return (BCM_E_PARAM); 4129 } 4130 4131 /* Ensure oam module is initialized. */ 4132 _BCM_OAM_IS_INIT(unit); 4133 4134 *oc = _sb2_oam_control[unit]; 4135 4136 return (BCM_E_NONE); 4137 } 4138 4139 /* 4140 * Function: 4141 * _bcm_sb2_oam_group_endpoint_count_init 4142 * Purpose: 4143 * Retrieves and initializes endpoint count information for this device. 4144 * Parameters: 4145 * unit - (IN) BCM unit number. 4146 * oc - (IN) Pointer to device OAM control structure. 4147 * Retruns: 4148 * BCM_E_XXX 4149 */ 4150 STATIC int 4151 _bcm_sb2_oam_group_endpoint_count_init(int unit, _bcm_oam_control_t *oc) 4152 { 4153 /* Input parameter check. */ 4154 if (NULL == oc) { 4155 return (BCM_E_PARAM); 4156 } 4157 4158 /* 4159 * Get endpoint hardware table index count values and 4160 * initialize device OAM control structure members variables. 4161 */ 4162 oc->rmep_count = soc_mem_index_count(unit, RMEPm); 4163 oc->lmep_count = soc_mem_index_count(unit, LMEPm); 4164 oc->ma_idx_count = soc_mem_index_count(unit, MA_INDEXm); 4165 oc->egr_ma_idx_count = soc_mem_index_count(unit, EGR_MA_INDEXm); 4166 4167 /* Max number of endpoints supported by the device. */ 4168 oc->ep_count = (oc->rmep_count + oc->lmep_count + oc->ma_idx_count + 4169 oc->egr_ma_idx_count); 4170 4171 LOG_VERBOSE(BSL_LS_BCM_OAM, 4172 (BSL_META_U(unit, 4173 "OAM(unit %d) Info: Total No. endpoint Count = %d.\n"), 4174 unit, oc->ep_count)); 4175 4176 /* Max number of MA Groups supported by device. */ 4177 oc->group_count = soc_mem_index_count(unit, MA_STATEm); 4178 LOG_VERBOSE(BSL_LS_BCM_OAM, 4179 (BSL_META_U(unit, 4180 "OAM(unit %d) Info: Total No. Group Count = %d.\n"), 4181 unit, oc->group_count)); 4182 4183 return (BCM_E_NONE); 4184 } 4185 4186 /* 4187 * Function: 4188 * _bcm_sb2_oam_ccm_rx_timeout_enable 4189 * Purpose: 4190 * Enable CCM Timer operations for endpoint state table. 4191 * Parameters: 4192 * unit - (IN) BCM unit number. 4193 * state - (IN) Enable/Disable. 4194 * Retruns: 4195 * BCM_E_XXX 4196 * Note: 4197 * RMEP_MA_STATE_REFRESH_INDEXr - CPU access for debug only. 4198 */ 4199 STATIC int 4200 _bcm_sb2_oam_ccm_rx_timeout_set(int unit, uint8 state) 4201 { 4202 int rv; /* Opreation return status. */ 4203 uint32 rval = 0; /* Register value. */ 4204 4205 /* Enable timer instructions to RMEP/MA_STATE Table. */ 4206 soc_reg_field_set(unit, OAM_TIMER_CONTROLr, &rval, 4207 TIMER_ENABLEf, state ? 1 : 0); 4208 4209 /* Set Clock granularity to 250us ticks - 1. */ 4210 soc_reg_field_set(unit, OAM_TIMER_CONTROLr, &rval, 4211 CLK_GRANf, 1); 4212 4213 rv = WRITE_OAM_TIMER_CONTROLr(unit, rval); 4214 if (BCM_FAILURE(rv)) { 4215 LOG_ERROR(BSL_LS_BCM_OAM, 4216 (BSL_META_U(unit, 4217 "OAM(unit %d) Error: Timer enable - Failed.\n"), 4218 unit)); 4219 return (rv); 4220 } 4221 4222 return (rv); 4223 } 4224 4225 /* 4226 * Function: 4227 * _bcm_sb2_oam_ccm_tx_config_enable 4228 * Purpose: 4229 * Enable transmission of OAM PDUs on local endpoint. 4230 * Parameters: 4231 * unit - (IN) BCM unit number. 4232 * state - (IN) Enable/Disable 4233 * Retruns: 4234 * BCM_E_XXX 4235 */ 4236 STATIC int 4237 _bcm_sb2_oam_ccm_tx_config_set(int unit, uint8 state) 4238 { 4239 int rv; /* Opreation return status. */ 4240 uint32 rval = 0; /* Register value. */ 4241 4242 /* Enable OAM LMEP Tx. */ 4243 soc_reg_field_set(unit, OAM_TX_CONTROLr, &rval, 4244 TX_ENABLEf, state ? 1 : 0); 4245 4246 /* Enable CMIC buffer. */ 4247 soc_reg_field_set(unit, OAM_TX_CONTROLr, &rval, 4248 CMIC_BUF_ENABLEf, state ? 1 : 0); 4249 4250 rv = WRITE_OAM_TX_CONTROLr(unit, rval); 4251 if (BCM_FAILURE(rv)) { 4252 LOG_ERROR(BSL_LS_BCM_OAM, 4253 (BSL_META_U(unit, 4254 "OAM(unit %d) Error: Tx config enable - Failed.\n"), 4255 unit)); 4256 } 4257 return (rv); 4258 } 4259 4260 /* 4261 * Function: 4262 * _bcm_sb2_oam_misc_config 4263 * Purpose: 4264 * Miscellaneous OAM configurations: 4265 * 1. Enable IFP lookup on the CPU port. 4266 * Parameters: 4267 * unit - (IN) BCM unit number. 4268 * Retruns: 4269 * BCM_E_XXX 4270 */ 4271 STATIC int 4272 _bcm_sb2_oam_misc_config(int unit) 4273 { 4274 int rv; /* Opreation return status. */ 4275 4276 /* 4277 * Enable ingress FP for CPU port so LM/DM packets sent from CPU 4278 * can be processed. 4279 */ 4280 rv = bcm_esw_port_control_set(unit, CMIC_PORT(unit), 4281 bcmPortControlFilterIngress, 1); 4282 if (BCM_FAILURE(rv)) { 4283 LOG_ERROR(BSL_LS_BCM_OAM, 4284 (BSL_META_U(unit, 4285 "OAM(unit %d) Error: bcm_esw_port_control_set" 4286 " - Failed.\n"), unit)); 4287 return (rv); 4288 } 4289 return (rv); 4290 4291 } 4292 4293 /* 4294 * Function: 4295 * _bcm_sb2_oam_profile_tables_init 4296 * Purpose: 4297 * Create ingress and egress service priority mapping profile table and 4298 * setup a default profile. Create Ingress and egress OAM opcode control 4299 * profile table, dglp profile 4300 * Parameters: 4301 * unit - (IN) BCM unit number. 4302 * oc - (IN) Pointer to OAM control structure. 4303 * Retruns: 4304 * BCM_E_XXX 4305 */ 4306 STATIC int 4307 _bcm_sb2_oam_profile_tables_init(int unit, _bcm_oam_control_t *oc) 4308 { 4309 int rv = BCM_E_NONE;/* Opreation return status. */ 4310 soc_mem_t mem; /* Profiled table memory. */ 4311 int entry_words; /* Profile table word size. */ 4312 int pri; /* Priority */ 4313 void *entries[1]; /* Profile entry. */ 4314 uint32 profile_index; /* Profile table index. */ 4315 bcm_module_t modid; 4316 uint32 dglp = 0; 4317 egr_oam_dglp_profile_entry_t egr_dglp_profile_entry; 4318 ing_oam_dglp_profile_entry_t ing_dglp_profile_entry; 4319 oam_opcode_control_profile_entry_t *opcode_entry; /* Opcode control 4320 profile entry. */ 4321 egr_oam_opcode_control_profile_entry_t *egr_opcode_entry; 4322 int map_id; 4323 bcm_qos_map_t map; 4324 4325 if (!SOC_WARM_BOOT(unit)) { 4326 /* 4327 * Initialize ingress/egress priority map profile table. 4328 * All internal priorities map to counter offset:'0'. 4329 */ 4330 BCM_IF_ERROR_RETURN(bcm_esw_qos_map_create(unit, 4331 BCM_QOS_MAP_OAM_INTPRI, 4332 &map_id)); 4333 for (pri = 0; pri < BCM_OAM_INTPRI_MAX; pri++) 4334 { 4335 sal_memset(&map, 0, sizeof(map)); 4336 map.int_pri = pri; 4337 map.counter_offset = 0; 4338 BCM_IF_ERROR_RETURN(bcm_esw_qos_map_add(unit, 4339 BCM_QOS_MAP_OAM_INTPRI, 4340 &map, map_id)); 4341 } 4342 /* Assign it to default priority map profile id */ 4343 oc->default_pri_map_id = map_id; 4344 } 4345 4346 /* OAM Opcode Control profile table initialization. */ 4347 soc_profile_mem_t_init(&oc->oam_opcode_control_profile); 4348 4349 entry_words = sizeof(oam_opcode_control_profile_entry_t) 4350 / sizeof(uint32); 4351 4352 mem = OAM_OPCODE_CONTROL_PROFILEm; 4353 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 4354 &oc->oam_opcode_control_profile); 4355 if (BCM_FAILURE(rv)) { 4356 LOG_ERROR(BSL_LS_BCM_OAM, 4357 (BSL_META_U(unit, 4358 "OAM(unit %d) Error: opcode control profile - Failed.\n"), 4359 unit)); 4360 return (rv); 4361 } 4362 if (!SOC_WARM_BOOT(unit)) { 4363 /* Create default opcode control profile */ 4364 opcode_entry = sal_alloc(_BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE, "opcode profile"); 4365 sal_memset(opcode_entry, 0, _BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE); 4366 rv = _bcm_sb2_oam_opcode_profile_entry_init(unit, mem, opcode_entry); 4367 if (BCM_FAILURE(rv)) { 4368 LOG_ERROR(BSL_LS_BCM_OAM, 4369 (BSL_META_U(unit, 4370 "OAM(unit %d) Error: Opcode profile init failed " 4371 " %s.\n"), unit, bcm_errmsg(rv))); 4372 if(opcode_entry) { 4373 sal_free(opcode_entry); 4374 } 4375 return (rv); 4376 } 4377 /* Add entry to profile table. */ 4378 entries[0] = opcode_entry; 4379 rv = soc_profile_mem_add(unit, &oc->oam_opcode_control_profile, 4380 (void *)entries, 4381 _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE, &profile_index); 4382 if (BCM_FAILURE(rv)) { 4383 LOG_ERROR(BSL_LS_BCM_OAM, 4384 (BSL_META_U(unit, 4385 "OAM(unit %d) Opcode profile table is full - %s.\n"), 4386 unit, bcm_errmsg(rv))); 4387 if(opcode_entry) { 4388 sal_free(opcode_entry); 4389 } 4390 return rv; 4391 } 4392 if(opcode_entry) { 4393 sal_free(opcode_entry); 4394 } 4395 } 4396 4397 /* Egress OAM Opcode Control profile table initialization. */ 4398 soc_profile_mem_t_init(&oc->egr_oam_opcode_control_profile); 4399 entry_words = sizeof(egr_oam_opcode_control_profile_entry_t) 4400 / sizeof(uint32); 4401 mem = EGR_OAM_OPCODE_CONTROL_PROFILEm; 4402 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 4403 &oc->egr_oam_opcode_control_profile); 4404 if (BCM_FAILURE(rv)) { 4405 LOG_ERROR(BSL_LS_BCM_OAM, 4406 (BSL_META_U(unit, 4407 "OAM(unit %d) Error: Egress opcode control profile- Failed.\n"), 4408 unit)); 4409 return (rv); 4410 } 4411 if (!SOC_WARM_BOOT(unit)) { 4412 egr_opcode_entry = sal_alloc(_BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE, "egr opcode profile"); 4413 /* Create default opcode control profile */ 4414 sal_memset(egr_opcode_entry, 0, _BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE); 4415 rv = _bcm_sb2_oam_opcode_profile_entry_init(unit, mem, egr_opcode_entry); 4416 if (BCM_FAILURE(rv)) { 4417 LOG_ERROR(BSL_LS_BCM_OAM, 4418 (BSL_META_U(unit, 4419 "OAM(unit %d) Error: Opcode profile init failed " 4420 " %s.\n"), unit, bcm_errmsg(rv))); 4421 if(egr_opcode_entry) { 4422 sal_free(egr_opcode_entry); 4423 } 4424 return (rv); 4425 } 4426 /* Add entry to profile table. */ 4427 entries[0] = egr_opcode_entry; 4428 rv = soc_profile_mem_add(unit, &oc->egr_oam_opcode_control_profile, 4429 (void *)entries, 4430 _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE, &profile_index); 4431 if (BCM_FAILURE(rv)) { 4432 LOG_ERROR(BSL_LS_BCM_OAM, 4433 (BSL_META_U(unit, 4434 "OAM(unit %d) Egr Opcode profile table is full - %s.\n"), 4435 unit, bcm_errmsg(rv))); 4436 if(egr_opcode_entry) { 4437 sal_free(egr_opcode_entry); 4438 } 4439 return rv; 4440 } 4441 if(egr_opcode_entry) { 4442 sal_free(egr_opcode_entry); 4443 } 4444 } 4445 4446 /* Ingress OAM dglp profile table initialisation */ 4447 soc_profile_mem_t_init(&oc->ing_oam_dglp_profile); 4448 4449 entry_words = sizeof(ing_oam_dglp_profile_entry_t) / sizeof(uint32); 4450 4451 mem = OAM_DGLP_PROFILEm; 4452 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 4453 &oc->ing_oam_dglp_profile); 4454 if (BCM_FAILURE(rv)) { 4455 LOG_ERROR(BSL_LS_BCM_OAM, 4456 (BSL_META_U(unit, 4457 "OAM(unit %d) Error: ING OAM DGLP profile create - Failed.\n"), 4458 unit)); 4459 return (rv); 4460 } 4461 if (!SOC_WARM_BOOT(unit)) { 4462 /* Add default profile */ 4463 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 4464 /* put local CPU as default dglp */ 4465 dglp = CMIC_PORT(unit); 4466 dglp |= ((modid << DGLP_MODULE_ID_SHIFT_BITS)); 4467 4468 soc_mem_field32_set(unit, OAM_DGLP_PROFILEm, 4469 &ing_dglp_profile_entry, DGLPf, dglp); 4470 entries[0] = &ing_dglp_profile_entry; 4471 4472 rv = soc_profile_mem_add(unit, &oc->ing_oam_dglp_profile, 4473 (void *)entries, 1, &profile_index); 4474 if (BCM_FAILURE(rv)) { 4475 LOG_ERROR(BSL_LS_BCM_OAM, 4476 (BSL_META_U(unit, 4477 "OAM(unit %d) DGLP profile table is full - %s.\n"), 4478 unit, bcm_errmsg(rv))); 4479 return rv; 4480 } 4481 } 4482 4483 4484 /* Egress OAM dglp profile table initialisation */ 4485 soc_profile_mem_t_init(&oc->egr_oam_dglp_profile); 4486 4487 entry_words = sizeof(egr_oam_dglp_profile_entry_t) / sizeof(uint32); 4488 4489 mem = EGR_OAM_DGLP_PROFILEm; 4490 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 4491 &oc->egr_oam_dglp_profile); 4492 if (BCM_FAILURE(rv)) { 4493 LOG_ERROR(BSL_LS_BCM_OAM, 4494 (BSL_META_U(unit, 4495 "OAM(unit %d) Error: EGR OAM DGLP profile create - Failed.\n"), 4496 unit)); 4497 return (rv); 4498 } 4499 if (!SOC_WARM_BOOT(unit)) { 4500 profile_index = 0; 4501 soc_mem_field32_set(unit, EGR_OAM_DGLP_PROFILEm, 4502 &egr_dglp_profile_entry, DGLPf, dglp); 4503 entries[0] = &egr_dglp_profile_entry; 4504 4505 rv = soc_profile_mem_add(unit, &oc->egr_oam_dglp_profile, 4506 (void *)entries, 1, &profile_index); 4507 if (BCM_FAILURE(rv)) { 4508 LOG_ERROR(BSL_LS_BCM_OAM, 4509 (BSL_META_U(unit, 4510 "OAM(unit %d) DGLP profile table is full - %s.\n"), 4511 unit, bcm_errmsg(rv))); 4512 return rv; 4513 } 4514 } 4515 4516 #if defined(BCM_METROLITE_SUPPORT) 4517 if (SOC_IS_METROLITE(unit)) { 4518 /* ING OAM LM count profile table initialization. 4519 * soc_profile_mem_add will be done in bcm_esw_oam_opcodes_count_profile_create API. 4520 * This will return the lm_count_profile index.*/ 4521 soc_profile_mem_t_init(&oc->ing_lm_counter_control_profile); 4522 4523 entry_words = sizeof(ing_lm_counter_control_entry_t) 4524 / sizeof(uint32); 4525 4526 mem = ING_LM_COUNTER_CONTROLm; 4527 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 4528 &oc->ing_lm_counter_control_profile); 4529 if (BCM_FAILURE(rv)) { 4530 LOG_ERROR(BSL_LS_BCM_OAM, 4531 (BSL_META_U(unit, 4532 "OAM(unit %d) Error: ING LM counter control profile - Failed.\n"), 4533 unit)); 4534 return (rv); 4535 } 4536 4537 /* EGR OAM LM count profile table initialization. 4538 * soc_profile_mem_add will be done in bcm_esw_oam_opcodes_count_profile_create API. 4539 * This will return the lm_count_profile index.*/ 4540 soc_profile_mem_t_init(&oc->egr_lm_counter_control_profile); 4541 4542 entry_words = sizeof(egr_lm_counter_control_entry_t) 4543 / sizeof(uint32); 4544 4545 mem = EGR_LM_COUNTER_CONTROLm; 4546 rv = soc_profile_mem_create(unit, &mem, &entry_words, 1, 4547 &oc->egr_lm_counter_control_profile); 4548 if (BCM_FAILURE(rv)) { 4549 LOG_ERROR(BSL_LS_BCM_OAM, 4550 (BSL_META_U(unit, 4551 "OAM(unit %d) Error: EGR LM counter control profile - Failed.\n"), 4552 unit)); 4553 return (rv); 4554 } 4555 } 4556 #endif 4557 return (rv); 4558 } 4559 4560 /* 4561 * Function: 4562 * _bcm_sb2_oam_control_free 4563 * Purpose: 4564 * Free OAM control structure resources allocated by this unit. 4565 * Parameters: 4566 * unit - (IN) BCM unit number. 4567 * oc - (IN) Pointer to OAM control structure. 4568 * Retruns: 4569 * BCM_E_XXX 4570 */ 4571 STATIC int 4572 _bcm_sb2_oam_control_free(int unit, _bcm_oam_control_t *oc) 4573 { 4574 int status = 0; 4575 _sb2_oam_control[unit] = NULL; 4576 4577 if (NULL == oc) { 4578 /* Module already un-initialized. */ 4579 return (BCM_E_NONE); 4580 } 4581 4582 /* Free protection mutex. */ 4583 if (NULL != oc->oc_lock) { 4584 sal_mutex_destroy(oc->oc_lock); 4585 } 4586 4587 /* Free hash data storage memory. */ 4588 if (NULL != oc->oam_hash_data) { 4589 sal_free(oc->oam_hash_data); 4590 } 4591 4592 /* Destory endpoint hash table. */ 4593 if (NULL != oc->ma_mep_htbl) { 4594 status = shr_htb_destroy(&oc->ma_mep_htbl, NULL); 4595 if (BCM_FAILURE(status)) { 4596 LOG_ERROR(BSL_LS_BCM_OAM, 4597 (BSL_META_U(unit, 4598 "Freeing ma_mep_htbl failed\n"))); 4599 } 4600 } 4601 4602 /* Destory group indices list. */ 4603 if (NULL != oc->group_pool) { 4604 shr_idxres_list_destroy(oc->group_pool); 4605 oc->group_pool = NULL; 4606 } 4607 4608 /* Destroy endpoint indices list. */ 4609 if (NULL != oc->mep_pool) { 4610 shr_idxres_list_destroy(oc->mep_pool); 4611 oc->mep_pool = NULL; 4612 } 4613 4614 /* Destroy local endpoint indices list. */ 4615 if (NULL != oc->lmep_pool) { 4616 shr_idxres_list_destroy(oc->lmep_pool); 4617 oc->lmep_pool = NULL; 4618 } 4619 4620 /* Destroy remote endpoint indices list. */ 4621 if (NULL != oc->rmep_pool) { 4622 shr_idxres_list_destroy(oc->rmep_pool); 4623 oc->rmep_pool = NULL; 4624 } 4625 4626 /* Destroy ingress and egress group indices list. */ 4627 4628 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_pool_destroy(oc)); 4629 4630 if (NULL != oc->egr_ma_idx_pool) { 4631 shr_idxres_list_destroy(oc->egr_ma_idx_pool); 4632 oc->egr_ma_idx_pool = NULL; 4633 } 4634 4635 /* Destroy LM counter indices list. */ 4636 if (NULL != oc->ing_lm_ctr_pool[0]) { 4637 shr_aidxres_list_destroy(oc->ing_lm_ctr_pool[0]); 4638 oc->ing_lm_ctr_pool[0] = NULL; 4639 } 4640 if (NULL != oc->ing_lm_ctr_pool[1]) { 4641 shr_aidxres_list_destroy(oc->ing_lm_ctr_pool[1]); 4642 oc->ing_lm_ctr_pool[1] = NULL; 4643 } 4644 if (NULL != oc->ing_lm_ctr_pool[2]) { 4645 shr_aidxres_list_destroy(oc->ing_lm_ctr_pool[2]); 4646 oc->ing_lm_ctr_pool[2] = NULL; 4647 } 4648 if (soc_feature(unit, soc_feature_bhh)) { 4649 #if defined(INCLUDE_BHH) 4650 /* Destroy bhh indices list. */ 4651 if (NULL != oc->bhh_pool) { 4652 shr_idxres_list_destroy(oc->bhh_pool); 4653 oc->bhh_pool = NULL; 4654 } 4655 if (NULL != oc->dma_buffer){ 4656 soc_cm_sfree(oc->unit, oc->dma_buffer); 4657 oc->dma_buffer = NULL; 4658 } 4659 if (NULL != oc->dmabuf_reply){ 4660 soc_cm_sfree(oc->unit, oc->dmabuf_reply); 4661 oc->dmabuf_reply = NULL; 4662 } 4663 if (NULL != oc->bhh_ma_index_in_use){ 4664 soc_cm_sfree(oc->unit, oc->bhh_ma_index_in_use); 4665 oc->bhh_ma_index_in_use = NULL; 4666 } 4667 if (NULL != oc->bhh_ep_grp_id){ 4668 soc_cm_sfree(oc->unit, oc->bhh_ep_grp_id); 4669 oc->bhh_ep_grp_id = NULL; 4670 } 4671 if (NULL != oc->bhh_ep_vpn){ 4672 soc_cm_sfree(oc->unit, oc->bhh_ep_vpn); 4673 oc->bhh_ep_vpn = NULL; 4674 } 4675 #endif 4676 } 4677 4678 if (soc_feature(unit, soc_feature_eth_lm_dm)) { 4679 #if defined(INCLUDE_ETH_LM_DM) 4680 /* Destroy ETH_LM_DM Session pool */ 4681 if (NULL != oc->eth_lm_dm_pool) { 4682 shr_idxres_list_destroy(oc->eth_lm_dm_pool); 4683 oc->eth_lm_dm_pool = NULL; 4684 } 4685 soc_cm_sfree(oc->unit, oc->eth_lm_dm_dma_buffer); 4686 soc_cm_sfree(oc->unit, oc->eth_lm_dm_dmabuf_reply); 4687 #endif 4688 } 4689 4690 #if defined(INCLUDE_MPLS_LM_DM) 4691 /* Destroy MPLS_LM_DM Session pool */ 4692 if (NULL != oc->mpls_lm_dm_pool) { 4693 shr_idxres_list_destroy(oc->mpls_lm_dm_pool); 4694 oc->mpls_lm_dm_pool = NULL; 4695 } 4696 soc_cm_sfree(oc->unit, oc->mpls_lm_dm_dma_buffer); 4697 soc_cm_sfree(oc->unit, oc->mpls_lm_dm_dmabuf_reply); 4698 #endif 4699 4700 if (soc_feature(unit, soc_feature_oam_pm)) { 4701 #if defined (INCLUDE_BHH) 4702 if (_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc)) { 4703 soc_cm_sfree(oc->unit, oc->pm_bhh_dma_buffer); 4704 } 4705 #endif 4706 #if defined (INCLUDE_ETH_LM_DM) 4707 if (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) { 4708 soc_cm_sfree(oc->unit, oc->pm_eth_lm_dm_dma_buffer); 4709 } 4710 if (NULL != oc->eth_lm_dm_sess_id_ep_id) { 4711 sal_free(oc->eth_lm_dm_sess_id_ep_id); 4712 oc->eth_lm_dm_sess_id_ep_id = NULL; 4713 } 4714 #endif 4715 #if defined (INCLUDE_MPLS_LM_DM) 4716 if (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) { 4717 soc_cm_sfree(oc->unit, oc->pm_mpls_lm_dm_dma_buffer); 4718 } 4719 if (NULL != oc->mpls_lm_dm_sess_id_ep_id) { 4720 sal_free(oc->mpls_lm_dm_sess_id_ep_id); 4721 oc->mpls_lm_dm_sess_id_ep_id = NULL; 4722 } 4723 #endif 4724 } 4725 4726 /* Free group memory. */ 4727 if (NULL != oc->group_info) { 4728 sal_free(oc->group_info); 4729 } 4730 4731 /* Free RMEP H/w to logical index mapping memory. */ 4732 if (NULL != oc->remote_endpoints) { 4733 sal_free(oc->remote_endpoints); 4734 } 4735 4736 /* Destroy Ingress OAM opcode control profile. */ 4737 if (NULL != oc->oam_opcode_control_profile.tables) { 4738 soc_profile_mem_destroy(unit, &oc->oam_opcode_control_profile); 4739 } 4740 /* Destroy Egress OAM opcode control profile. */ 4741 if (NULL != oc->egr_oam_opcode_control_profile.tables) { 4742 soc_profile_mem_destroy(unit, &oc->egr_oam_opcode_control_profile); 4743 } 4744 /* Destroy Ingress DGLP profile */ 4745 if (NULL != oc->ing_oam_dglp_profile.tables) { 4746 soc_profile_mem_destroy(unit, &oc->ing_oam_dglp_profile); 4747 } 4748 /* Destroy Egress DGLP profile */ 4749 if (NULL != oc->egr_oam_dglp_profile.tables) { 4750 soc_profile_mem_destroy(unit, &oc->egr_oam_dglp_profile); 4751 } 4752 #if defined (BCM_METROLITE_SUPPORT) 4753 if(SOC_IS_METROLITE(unit)) { 4754 /* Destroy Ingress OAM LM counter control profile. */ 4755 if (NULL != oc->ing_lm_counter_control_profile.tables) { 4756 soc_profile_mem_destroy(unit, &oc->ing_lm_counter_control_profile); 4757 } 4758 /* Destroy Egress OAM LM counter control profile. */ 4759 if (NULL != oc->egr_lm_counter_control_profile.tables) { 4760 soc_profile_mem_destroy(unit, &oc->egr_lm_counter_control_profile); 4761 } 4762 } 4763 #endif 4764 4765 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM) 4766 if (soc_feature(unit, soc_feature_oam_pm)) { 4767 if (pm_profile_control[unit]) { 4768 sal_free(pm_profile_control[unit]); 4769 pm_profile_control[unit] = NULL; 4770 } 4771 } 4772 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM || INCLUDE_ETH_LM_DM*/ 4773 4774 /* Free OAM control structure memory. */ 4775 sal_free(oc); 4776 oc = NULL; 4777 4778 return (BCM_E_NONE); 4779 } 4780 4781 /* 4782 * Function: 4783 * _bcm_sb2_oam_handle_interrupt 4784 * Purpose: 4785 * Process OAM interrupts generated by endpoints. 4786 * Parameters: 4787 * unit - (IN) BCM unit number. 4788 * field - (IN) fault field. 4789 * Retruns: 4790 * BCM_E_XXX 4791 */ 4792 STATIC int 4793 _bcm_sb2_oam_handle_interrupt(int unit, soc_field_t field) 4794 { 4795 _bcm_oam_interrupt_t *intr; /* OAM interrupt. */ 4796 _bcm_oam_control_t *oc; /* OAM control structure. */ 4797 uint32 intr_rval; /* Interrupt register value. */ 4798 uint32 intr_cur_status; /* Interrupt status. */ 4799 uint32 flags; /* Interrupt flags. */ 4800 bcm_oam_group_t grp_index; /* MA group index. */ 4801 bcm_oam_endpoint_t remote_ep_index; /* Remote Endpoint index. */ 4802 int intr_multi; /* Event occured multiple times. */ 4803 int intr_count; /* No. of times event detected. */ 4804 int rv; /* Operation return status */ 4805 _bcm_oam_event_handler_t *e_handler; /* Pointer to Event handler. */ 4806 4807 4808 /* Get OAM control structure. */ 4809 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 4810 4811 _BCM_OAM_LOCK(oc); 4812 4813 /* Loop through the supported interrupts for this device. */ 4814 for (intr = _sb2_oam_interrupts; intr->status_register != INVALIDr; 4815 intr++) { 4816 4817 rv = soc_reg32_get(unit, intr->status_register, 4818 REG_PORT_ANY, 0, &intr_rval); 4819 if (BCM_FAILURE(rv)) { 4820 4821 continue; 4822 } 4823 4824 rv = soc_reg32_set(unit, intr->status_register, 4825 REG_PORT_ANY, 0, 0); 4826 if (BCM_FAILURE(rv)) { 4827 continue; 4828 } 4829 4830 /* Get status of interrupt from hardware. */ 4831 intr_cur_status = soc_reg_field_get(unit, intr->status_register, 4832 intr_rval, VALIDf); 4833 if (0 == intr_cur_status) { 4834 /* This interrupt event is not valid, so continue. */ 4835 continue; 4836 } 4837 4838 /* Get this interrupt event counter value. */ 4839 intr_count = oc->event_handler_cnt[intr->event_type]; 4840 4841 /* Check if the interrupt is set. */ 4842 if ((1 == intr_cur_status) && (intr_count > 0)) { 4843 flags = 0; 4844 4845 /* Get MA group index for this interrupt. */ 4846 if (INVALIDf != intr->group_index_field ) { 4847 grp_index = soc_reg_field_get(unit, intr->status_register, 4848 intr_rval, 4849 intr->group_index_field); 4850 } else { 4851 /* Group not valid for this interrupt. */ 4852 grp_index = BCM_OAM_GROUP_INVALID; 4853 } 4854 4855 /* Get H/w index of RMEP for this interrupt. */ 4856 if (INVALIDf != intr->endpoint_index_field ) { 4857 remote_ep_index = soc_reg_field_get(unit, intr->status_register, 4858 intr_rval, 4859 intr->endpoint_index_field); 4860 4861 /* Get Logical index from H/w index for this RMEP. */ 4862 remote_ep_index = oc->remote_endpoints[remote_ep_index]; 4863 } else { 4864 /* Endpoint not valid for this interrupt. */ 4865 remote_ep_index = BCM_OAM_ENDPOINT_INVALID; 4866 } 4867 4868 /* Get interrupt MULTIf status. */ 4869 intr_multi = soc_reg_field_get(unit, intr->status_register, 4870 intr_rval, MULTIf); 4871 if (1 == intr_multi) { 4872 /* 4873 * Interrupt event asserted more than once. 4874 * Set flags status bit to indicate event multiple occurance. 4875 */ 4876 flags |= BCM_OAM_EVENT_FLAGS_MULTIPLE; 4877 } 4878 4879 /* Check and call all the handlers registerd for this event. */ 4880 for (e_handler = oc->event_handler_list_p; e_handler != NULL; 4881 e_handler = e_handler->next_p) { 4882 4883 /* Check if an event handler is register for this event type. */ 4884 if (SHR_BITGET(e_handler->event_types.w, intr->event_type)) { 4885 4886 /* Call the event handler with the call back parameters. */ 4887 e_handler->cb(unit, flags, intr->event_type, grp_index, 4888 remote_ep_index, e_handler->user_data); 4889 } 4890 } 4891 } 4892 } 4893 4894 _BCM_OAM_UNLOCK(oc); 4895 4896 return (BCM_E_NONE); 4897 } 4898 4899 /* 4900 * Function: 4901 * _bcm_sb2_oam_events_unregister 4902 * Purpose: 4903 * Unregister all OAM events for this unit. 4904 * Parameters: 4905 * unit - (IN) BCM unit number. 4906 * oc - (IN) Pointer to OAM control structure. 4907 * Retruns: 4908 * BCM_E_NONE 4909 */ 4910 STATIC int 4911 _bcm_sb2_oam_events_unregister(int unit, _bcm_oam_control_t *oc) 4912 { 4913 _bcm_oam_event_handler_t *e_handler; /* Pointer to event handler list. */ 4914 _bcm_oam_event_handler_t *e_delete; /* Event handler to be freed. */ 4915 4916 /* Control lock taken by the calling routine. */ 4917 4918 e_handler = oc->event_handler_list_p; 4919 4920 while (e_handler != NULL) { 4921 e_delete = e_handler; 4922 e_handler = e_handler->next_p; 4923 sal_free(e_delete); 4924 } 4925 4926 oc->event_handler_list_p = NULL; 4927 4928 return (BCM_E_NONE); 4929 } 4930 4931 4932 /* 4933 * Function: 4934 * _bcm_sb2_oam_clear_rmep 4935 * Purpose: 4936 * Delete RMEP entry or Install fresh RMEP entry in the Hardware, clearing 4937 * the faults. 4938 * 4939 * Parameters: 4940 * unit - (IN) BCM device number 4941 * h_data_p - (IN) Pointer to Endpoint info associated with RMEP entry 4942 * being cleared. 4943 * valid - (IN) 0 => Delete the H/w entry 4944 * 1 => Install fresh entry with faults cleared. 4945 * Returns: 4946 * BCM_E_XXX 4947 */ 4948 STATIC int 4949 _bcm_sb2_oam_clear_rmep (int unit, _bcm_oam_hash_data_t *h_data_p, int valid) 4950 { 4951 4952 rmep_entry_t rmep_entry; /* RMEP table entry. */ 4953 int rv = BCM_E_INTERNAL; /* Operation return status entry */ 4954 uint32 oam_cur_time; /* Current time in H/w state machine */ 4955 4956 LOG_VERBOSE(BSL_LS_BCM_OAM, 4957 (BSL_META_U(unit, 4958 "OAM(unit %d): %s, EP id %d, valid %d\n"), 4959 unit, FUNCTION_NAME(), h_data_p->remote_index, valid)); 4960 4961 if (h_data_p == NULL) { 4962 LOG_ERROR(BSL_LS_BCM_OAM, 4963 (BSL_META_U(unit, 4964 "OAM(unit %d), ERR: %s Arg h_data_p NULL check failed\n"), 4965 unit, FUNCTION_NAME())); 4966 return BCM_E_INTERNAL; 4967 } 4968 4969 /* RMEP table programming. */ 4970 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 4971 4972 /* if valid==0 delete RMEP entry, else create a clean RMEP entry */ 4973 if (!(valid)) { 4974 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index, 4975 &rmep_entry); 4976 if (rv != BCM_E_NONE) { 4977 LOG_ERROR(BSL_LS_BCM_OAM, 4978 (BSL_META_U(unit, 4979 "OAM(unit %d), ERR: %s Deleting RMEP entry failied\n"), 4980 unit, FUNCTION_NAME())); 4981 } 4982 return (rv); 4983 } 4984 4985 /* Set the MA group index. */ 4986 soc_RMEPm_field32_set(unit, &rmep_entry, MAID_INDEXf, 4987 h_data_p->group_index); 4988 4989 /* 4990 * The following steps are necessary to enable CCM timeout events 4991 * without having received any CCMs. 4992 */ 4993 soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMP_VALIDf, 1); 4994 4995 BCM_IF_ERROR_RETURN(READ_OAM_CURRENT_TIMEr(unit, &oam_cur_time)); 4996 4997 soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMPf, oam_cur_time); 4998 4999 soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_RECEIVED_CCMf, 5000 _bcm_sb2_oam_ccm_msecs_to_hw_encode(h_data_p->period)); 5001 /* End of timeout setup */ 5002 5003 5004 soc_RMEPm_field32_set(unit, &rmep_entry, VALIDf, 1); 5005 5006 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index, 5007 &rmep_entry); 5008 if (rv != BCM_E_NONE) { 5009 LOG_ERROR(BSL_LS_BCM_OAM, 5010 (BSL_META_U(unit, 5011 "OAM(unit %d), ERR: %s Clearing RMEP entry failied\n"), 5012 unit, FUNCTION_NAME())); 5013 return (rv); 5014 } 5015 5016 return BCM_E_NONE; 5017 } 5018 5019 5020 /* 5021 * Function: 5022 * _bcm_sb2_oam_clear_ma_state 5023 * Purpose: 5024 * Delete MA_STATE entry or Install fresh MA_STATE entry in the Hardware, 5025 * Clearing the faults. 5026 * Parameters: 5027 * unit - (IN) BCM device number 5028 * group_info - (IN) Group info associated with MA_STATE entry being 5029 * cleared. 5030 * index - (IN) H/w index of MA_STATE entry to be modified. 5031 * valid - (IN) 0 => Delete the H/w entry 5032 * 1 => Install fresh entry with faults cleared. 5033 * Returns: 5034 * BCM_E_XXX 5035 */ 5036 STATIC int 5037 _bcm_sb2_oam_clear_ma_state(int unit, _bcm_oam_group_data_t *group_info, 5038 int index, int valid) 5039 { 5040 5041 ma_state_entry_t ma_state_entry; /* MA State table entry. */ 5042 5043 LOG_VERBOSE(BSL_LS_BCM_OAM, 5044 (BSL_META_U(unit, 5045 "OAM(unit %d): %s, *group_info %p, index %d, valid %d\n"), 5046 unit, FUNCTION_NAME(), group_info, index, valid)); 5047 5048 if (group_info == NULL) { 5049 LOG_ERROR(BSL_LS_BCM_OAM, 5050 (BSL_META_U(unit, 5051 "OAM(unit %d), ERR: %s Arg group_info NULL check failed\n"), 5052 unit, FUNCTION_NAME())); 5053 return BCM_E_INTERNAL; 5054 } 5055 5056 sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t)); 5057 5058 /* Mark the entry as valid. */ 5059 soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, valid); 5060 5061 /* Set the lowest alarm priority info. */ 5062 if (valid) { 5063 soc_MA_STATEm_field32_set(unit, &ma_state_entry, LOWESTALARMPRIf, 5064 group_info->lowest_alarm_priority); 5065 } 5066 5067 /* Write group information to hardware table. */ 5068 SOC_IF_ERROR_RETURN(WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, index, 5069 &ma_state_entry)); 5070 return BCM_E_NONE; 5071 } 5072 5073 5074 /* 5075 * Function: 5076 * _bcm_sb2_oam_group_recreate 5077 * Purpose: 5078 * Recreate MA_STATE and RMEP entries, due to current H/w limitation 5079 * Currently there is a race condition between H/w and Software 5080 * When RMEP is deleted and if it has any faults then, 5081 * MA_STATE remote fault counters need to be decremented by software. 5082 * However it may so happen that after reading RMEP faults and just 5083 * before RMEP deletion, the fault gets cleared and H/w already decremented 5084 * the MA_STATE table, now when software decrements the MA_STATE it would 5085 * get MA_STATE table into an inconsistent state. 5086 * As a solution we always recreate the entire group on a RMEP deletion. 5087 * Parameters: 5088 * unit - (IN) BCM device number 5089 * group_id - (IN) Group Index, 5090 * as per current implementation this is same as MA_STATE index. 5091 * Returns: 5092 * BCM_E_XXX 5093 * Expects: 5094 * OAM LOCK 5095 */ 5096 STATIC int 5097 _bcm_sb2_oam_group_recreate(int unit, int index) 5098 { 5099 _bcm_oam_control_t *oc; /* OAM control structure. */ 5100 _bcm_oam_group_data_t *group_info; /* OAM group info */ 5101 _bcm_oam_ep_list_t *cur_ep_ptr = NULL; /* Pointer to group's EP list */ 5102 /* entry. */ 5103 int rv = BCM_E_NONE; /* Operation return status. */ 5104 5105 /* Get OAM control structure handle. */ 5106 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 5107 5108 /* Get the handle to group info */ 5109 group_info = &(oc->group_info[index]); 5110 5111 /*if unused Group, just clear the MA_STATE index, including the valid bit*/ 5112 if (!(group_info->in_use)) { 5113 LOG_WARN(BSL_LS_BCM_OAM, 5114 (BSL_META_U(unit, 5115 "OAM(unit %d), WARN: Recieved group recreate request for " 5116 "unused Group Id %d\n"), unit, index)); 5117 5118 rv = _bcm_sb2_oam_clear_ma_state(unit, group_info, index, 0); 5119 if (BCM_FAILURE(rv)) { 5120 LOG_ERROR(BSL_LS_BCM_OAM, 5121 (BSL_META_U(unit, 5122 "OAM(unit %d) Error: MA_STATE clear failed group id %d - " 5123 "%s.\n"), unit, index, bcm_errmsg(rv))); 5124 return rv; 5125 } 5126 5127 } 5128 5129 /* 1. Traverse and delete the RMEPs in the group */ 5130 if (group_info->ep_list != NULL) { 5131 cur_ep_ptr = *(group_info->ep_list); 5132 } 5133 while (cur_ep_ptr) { 5134 if (cur_ep_ptr->ep_data_p->is_remote && cur_ep_ptr->ep_data_p->in_use) { 5135 rv = _bcm_sb2_oam_clear_rmep(unit, cur_ep_ptr->ep_data_p, 0); 5136 if (BCM_FAILURE(rv)) { 5137 LOG_ERROR(BSL_LS_BCM_OAM, 5138 (BSL_META_U(unit, 5139 "OAM(unit %d) Error: RMEP delete failed Ep id %d - " 5140 "%s.\n"), unit, cur_ep_ptr->ep_data_p->ep_id, bcm_errmsg(rv))); 5141 return rv; 5142 } 5143 } 5144 cur_ep_ptr = cur_ep_ptr->next; 5145 } 5146 5147 /* 2. Clear the MA_STATE table faults */ 5148 rv = _bcm_sb2_oam_clear_ma_state(unit, group_info, index, 1); 5149 if (BCM_FAILURE(rv)) { 5150 LOG_ERROR(BSL_LS_BCM_OAM, 5151 (BSL_META_U(unit, 5152 "OAM(unit %d) Error: MA_STATE clear failed group id %d - " 5153 "%s.\n"), unit, index, bcm_errmsg(rv))); 5154 return rv; 5155 } 5156 5157 /* 3. Recreate the RMEP table entries. Clearing the faults. */ 5158 if (group_info->ep_list != NULL) { 5159 cur_ep_ptr = *(group_info->ep_list); 5160 } 5161 while (cur_ep_ptr) { 5162 if (cur_ep_ptr->ep_data_p->is_remote && cur_ep_ptr->ep_data_p->in_use) { 5163 rv = _bcm_sb2_oam_clear_rmep(unit, cur_ep_ptr->ep_data_p, 1); 5164 if (BCM_FAILURE(rv)) { 5165 LOG_ERROR(BSL_LS_BCM_OAM, 5166 (BSL_META_U(unit, 5167 "OAM(unit %d) Error: RMEP clear failed EP id %d - " 5168 "%s.\n"), unit, cur_ep_ptr->ep_data_p->ep_id, bcm_errmsg(rv))); 5169 return rv; 5170 } 5171 } 5172 cur_ep_ptr = cur_ep_ptr->next; 5173 } 5174 5175 return rv; 5176 } 5177 5178 5179 /* 5180 * Function: 5181 * _bcm_sb2_oam_ser_handler 5182 * Purpose: 5183 * Soft Error Correction routine for MA_STATE and RMEP tables. 5184 * Parameters: 5185 * unit - (IN) BCM device number 5186 * mem - (IN) Memory MA_STATE or RMEP. 5187 * index - (IN) Memory Index. 5188 * Returns: 5189 * BCM_E_XXX 5190 */ 5191 STATIC int 5192 _bcm_sb2_oam_ser_handler(int unit, soc_mem_t mem, int index) 5193 { 5194 int rv = BCM_E_NONE; /* Operation return status. */ 5195 _bcm_oam_control_t *oc = NULL; /* OAM control structure. */ 5196 bcm_oam_endpoint_t remote_ep_index; /* Remote Endpoint index. */ 5197 _bcm_oam_hash_data_t *ep_data = NULL; /* Remote Endpoint hash data */ 5198 5199 LOG_VERBOSE(BSL_LS_BCM_OAM, 5200 (BSL_META_U(unit, 5201 "OAM(unit %d) SER on mem %s, index %d\n"), 5202 unit, SOC_MEM_NAME(unit, mem), index)); 5203 5204 /* Get OAM control structure handle. */ 5205 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 5206 5207 switch(mem){ 5208 case MA_STATEm: 5209 _BCM_OAM_GROUP_INDEX_VALIDATE(index); 5210 _BCM_OAM_LOCK(oc); 5211 rv = _bcm_sb2_oam_group_recreate(unit, index); 5212 _BCM_OAM_UNLOCK(oc); 5213 break; 5214 5215 case RMEPm: 5216 _BCM_OAM_RMEP_INDEX_VALIDATE(index); 5217 _BCM_OAM_LOCK(oc); 5218 /* Get the logical index from H/w RMEP index */ 5219 remote_ep_index = oc->remote_endpoints[index]; 5220 if(remote_ep_index == BCM_OAM_ENDPOINT_INVALID) { 5221 /* If endpoint not in use, just clear the RMEP entry in memory */ 5222 rmep_entry_t rmep_entry; 5223 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 5224 5225 LOG_WARN(BSL_LS_BCM_OAM, 5226 (BSL_META_U(unit, 5227 "OAM(unit %d), WARN: Recieved Parity Error on" 5228 "index %d invalid Remote Id\n"), unit, index)); 5229 /* Just clear this entry including valid bit */ 5230 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, index, 5231 &rmep_entry); 5232 5233 } else { 5234 /* Get handle to Hash data */ 5235 ep_data = &(oc->oam_hash_data[remote_ep_index]); 5236 5237 if (!(ep_data->in_use)) { 5238 /* If endpoint not in use, just clear the RMEP entry in memory */ 5239 LOG_WARN(BSL_LS_BCM_OAM, 5240 (BSL_META_U(unit, 5241 "OAM(unit %d), WARN: Recieved Parity Error on" 5242 "unused Remote Id %d\n"), unit, remote_ep_index)); 5243 /* Just clear this entry including valid bit */ 5244 rv = _bcm_sb2_oam_clear_rmep(unit, ep_data, 0); 5245 } else { 5246 /* Get the group Id from EP data, call group recreate routine */ 5247 rv = _bcm_sb2_oam_group_recreate(unit, ep_data->group_index); 5248 } 5249 } 5250 _BCM_OAM_UNLOCK(oc); 5251 break; 5252 5253 default: 5254 LOG_ERROR(BSL_LS_BCM_OAM, 5255 (BSL_META_U(unit, 5256 "OAM(unit %d), ERR: Invalid mem in OAM SER correction " 5257 "routine %s\n"), unit, SOC_MEM_NAME(unit, mem))); 5258 return BCM_E_INTERNAL; 5259 } 5260 5261 LOG_VERBOSE(BSL_LS_BCM_OAM, 5262 (BSL_META_U(unit, 5263 "OAM(unit %d) SER completed on mem %s, index %d, rv %d\n"), 5264 unit, SOC_MEM_NAME(unit, mem), index, rv)); 5265 5266 return rv; 5267 5268 } 5269 5270 /* 5271 * Function: 5272 * _bcm_sb2_oam_group_name_mangle 5273 * Purpose: 5274 * Build tbe group name for hardware table write. 5275 * Parameters: 5276 * name_p - (IN) OAM group name. 5277 * mangled_name_p - (IN/OUT) Buffer to write the group name in hardware 5278 * format. 5279 * Retruns: 5280 * None 5281 */ 5282 STATIC void 5283 _bcm_sb2_oam_group_name_mangle(uint8 *name_p, 5284 uint8 *mangled_name_p) 5285 { 5286 uint8 *byte_p; /* Pointer to group name buffer. */ 5287 int bytes_left; /* Number of bytes left in group name. */ 5288 5289 bytes_left = BCM_OAM_GROUP_NAME_LENGTH; 5290 byte_p = (name_p + BCM_OAM_GROUP_NAME_LENGTH - 1); 5291 5292 while (bytes_left > 0) { 5293 *mangled_name_p = *byte_p; 5294 ++mangled_name_p; 5295 --byte_p; 5296 --bytes_left; 5297 } 5298 } 5299 5300 /* 5301 * Function: 5302 * _bcm_sb2_oam_read_clear_faults 5303 * Purpose: 5304 * Clear OAM group and endpoint faults on hardware table read operation. 5305 * Parameters: 5306 * unit - (IN) BCM device number 5307 * index - (IN) Group/Endpoint hardware table index 5308 * mem - (IN) Memory/table value 5309 * entry - (IN) Pointer to group/endpoint entry 5310 * ma_mep - (IN) Pointer to group/endpoint info structure 5311 * Returns: 5312 * BCM_E_NONE - No errors. 5313 * BCM_E_XXX - Otherwise. 5314 */ 5315 STATIC int 5316 _bcm_sb2_oam_read_clear_faults(int unit, int index, soc_mem_t mem, 5317 uint32 *entry, void *ma_rmep) 5318 { 5319 bcm_oam_group_info_t *group_info_p; /* Pointer to group info */ 5320 /* structure. */ 5321 bcm_oam_endpoint_info_t *ep_info_p; /* Pointer to endpoint info */ 5322 /* structure. */ 5323 _bcm_oam_fault_t *faults_list; /* Pointer to faults list. */ 5324 uint32 *faults; /* Faults flag bits. */ 5325 uint32 *p_faults; /* Persistent faults bits. */ 5326 uint32 clear_p_faults; /* Clear persistent faults bits. */ 5327 uint32 rval = 0; /* Hardware register value. */ 5328 uint32 clear_mask = 0; /* Mask to clear persistent faults*/ 5329 5330 LOG_DEBUG(BSL_LS_BCM_OAM, 5331 (BSL_META_U(unit, 5332 "OAM(unit %d) Info: _bcm_sb2_oam_read_clear_faults index=%d " 5333 "Table=%d.\n"), unit, index, mem)); 5334 5335 /* Switch on memory name. */ 5336 switch (mem) { 5337 /* OAM group state table. */ 5338 case MA_STATEm: 5339 /* Set the pointer to the start of the group faults array. */ 5340 faults_list = _sb2_oam_group_faults; 5341 5342 /* Typecast to group information structure pointer. */ 5343 group_info_p = (bcm_oam_group_info_t *) ma_rmep; 5344 5345 /* Get group faults information. */ 5346 faults = &group_info_p->faults; 5347 p_faults = &group_info_p->persistent_faults; 5348 clear_p_faults = group_info_p->clear_persistent_faults; 5349 break; 5350 5351 /* OAM remote endpoint table. */ 5352 case RMEPm: 5353 faults_list = _sb2_oam_endpoint_faults; 5354 ep_info_p = (bcm_oam_endpoint_info_t *) ma_rmep; 5355 faults = &ep_info_p->faults; 5356 p_faults = &ep_info_p->persistent_faults; 5357 clear_p_faults = ep_info_p->clear_persistent_faults; 5358 break; 5359 5360 default: 5361 return (BCM_E_NONE); 5362 } 5363 5364 /* Loop on list of valid faults. */ 5365 for (;faults_list->mask != 0; ++faults_list) { 5366 5367 /* Get faults status. */ 5368 if (0 != soc_mem_field32_get(unit, mem, entry, 5369 faults_list->current_field)) { 5370 *faults |= faults_list->mask; 5371 } 5372 5373 /* Get sticky faults status. */ 5374 if (0 != soc_mem_field32_get(unit, mem, entry, 5375 faults_list->sticky_field)) { 5376 5377 *p_faults |= faults_list->mask; 5378 5379 /* 5380 * If user has request to clear persistent faults, 5381 * then set BITS_TO_CLEARf field in the register buffer. 5382 */ 5383 if (clear_p_faults) { 5384 clear_mask |= faults_list->clear_sticky_mask; 5385 } 5386 } 5387 } 5388 5389 /* Check if faults need to be cleared. */ 5390 if (clear_mask && clear_p_faults) { 5391 5392 LOG_VERBOSE(BSL_LS_BCM_OAM, 5393 (BSL_META_U(unit, 5394 "OAM(unit %d): clear_mask %d.\n"), 5395 unit, clear_mask)); 5396 5397 soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, BITS_TO_CLEARf, 5398 clear_mask); 5399 5400 /* Enable clearing of faults. */ 5401 soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, ENABLE_CLEARf, 1); 5402 5403 5404 if (MA_STATEm == mem) { 5405 soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, MEMORYf, 0); 5406 } else { 5407 soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, MEMORYf, 1); 5408 } 5409 5410 soc_reg_field_set(unit, CCM_READ_CONTROLr, &rval, INDEXf, index); 5411 5412 /* Update read control register. */ 5413 BCM_IF_ERROR_RETURN(WRITE_CCM_READ_CONTROLr(unit, rval)); 5414 } 5415 5416 return (BCM_E_NONE); 5417 } 5418 5419 #if defined(INCLUDE_BHH) 5420 /* 5421 * Function: 5422 * _bcm_sb2_oam_get_group_sw_rdi 5423 * Purpose: 5424 * Get OAM group SW RDI information. 5425 * Parameters: 5426 * unit - (IN) BCM device number 5427 * group_index - (IN) Group hardware table index 5428 * group_sw_rdi - (OUT) Pointer to group SW RDI 5429 * Returns: 5430 * BCM_E_NONE - No errors. 5431 * BCM_E_XXX - Otherwise. 5432 */ 5433 STATIC int 5434 _bcm_sb2_oam_get_group_sw_rdi(int unit, bcm_oam_group_t group_index, 5435 uint8 *group_sw_rdi) 5436 { 5437 maid_reduction_entry_t maid_reduction_entry; /* MAID reduction entry. */ 5438 5439 BCM_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, 5440 group_index, 5441 &maid_reduction_entry)); 5442 5443 if (1 == soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry, 5444 SW_RDIf)) { 5445 *group_sw_rdi = 1; 5446 } 5447 return (BCM_E_NONE); 5448 } 5449 #endif 5450 5451 /* 5452 * Function: 5453 * _bcm_sb2_oam_get_group 5454 * Purpose: 5455 * Get OAM group information. 5456 * Parameters: 5457 * unit - (IN) BCM device number 5458 * group_index - (IN) Group hardware table index 5459 * group - (IN) Pointer to group array list 5460 * group_info - (IN/OUT) Pointer to group info structure 5461 * Returns: 5462 * BCM_E_NONE - No errors. 5463 * BCM_E_XXX - Otherwise. 5464 */ 5465 STATIC int 5466 _bcm_sb2_oam_get_group(int unit, bcm_oam_group_t group_index, 5467 _bcm_oam_group_data_t *group_p, 5468 bcm_oam_group_info_t *group_info) 5469 { 5470 maid_reduction_entry_t maid_reduction_entry; /* MAID reduction entry. */ 5471 ma_state_entry_t ma_state_entry; /* MA_STATE table entry. */ 5472 int rv; /* Operation return status. */ 5473 5474 group_info->id = group_index; 5475 5476 sal_memcpy(group_info->name, group_p[group_index].name, 5477 BCM_OAM_GROUP_NAME_LENGTH); 5478 5479 BCM_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, 5480 group_index, 5481 &maid_reduction_entry)); 5482 5483 if (1 == soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry, 5484 SW_RDIf)) { 5485 group_info->flags |= BCM_OAM_GROUP_REMOTE_DEFECT_TX; 5486 } 5487 5488 BCM_IF_ERROR_RETURN(READ_MA_STATEm(unit, MEM_BLOCK_ANY, 5489 group_index, 5490 &ma_state_entry)); 5491 5492 group_info->lowest_alarm_priority = soc_MA_STATEm_field32_get 5493 (unit, &ma_state_entry, 5494 LOWESTALARMPRIf); 5495 5496 rv = _bcm_sb2_oam_read_clear_faults(unit, group_index, 5497 MA_STATEm, 5498 (uint32 *) &ma_state_entry, 5499 group_info); 5500 if (BCM_FAILURE(rv)) { 5501 LOG_ERROR(BSL_LS_BCM_OAM, 5502 (BSL_META_U(unit, 5503 "OAM(unit %d) Error: Clean Faults Group ID=%d- Failed.\n"), 5504 unit, group_index)); 5505 return (rv); 5506 } 5507 return (BCM_E_NONE); 5508 } 5509 5510 5511 /* 5512 * Function: 5513 * _bcm_sb2_oam_endpoint_egress_interface_add 5514 * Purpose: 5515 * Add an egress interface to an 5516 * endpoint info egress interface linked list. 5517 * Parameters: 5518 * unit - (IN) BCM device number 5519 * h_data_p - (IN) Endpoint hash data 5520 * egress_if - (IN) Egress interface 5521 * gport - (IN) corresponding gport 5522 * Returns: 5523 * BCM_E_XXX 5524 */ 5525 STATIC int 5526 _bcm_sb2_oam_endpoint_egress_interface_add(int unit, 5527 _bcm_oam_hash_data_t *h_data_p, 5528 bcm_if_t egress_if, 5529 bcm_gport_t gport) 5530 { 5531 _bcm_oam_endpoint_egress_interface_list_t *egress_if_list_node = NULL; 5532 5533 _BCM_OAM_ALLOC(egress_if_list_node, _bcm_oam_endpoint_egress_interface_list_t, 5534 sizeof(_bcm_oam_endpoint_egress_interface_list_t), 5535 "Egress if lst"); 5536 if (NULL == egress_if_list_node) { 5537 LOG_ERROR(BSL_LS_BCM_OAM, 5538 (BSL_META_U(unit, 5539 "OAM(unit %d) Error: Egress if list " 5540 "alloc for EP=%d failed" 5541 " %s.\n"), unit, h_data_p->ep_id, 5542 bcm_errmsg(BCM_E_MEMORY))); 5543 return (BCM_E_MEMORY); 5544 } 5545 5546 egress_if_list_node->prev = NULL; 5547 egress_if_list_node->egress_if = egress_if; 5548 egress_if_list_node->gport = gport; 5549 if (NULL == (h_data_p->egress_if_list)) { 5550 /* Add endpoint as head node. */ 5551 egress_if_list_node->next = NULL; 5552 h_data_p->egress_if_list = egress_if_list_node; 5553 } else { 5554 /* Add the endpoint to the linked list. */ 5555 egress_if_list_node->next = h_data_p->egress_if_list; 5556 (h_data_p->egress_if_list)->prev = egress_if_list_node; 5557 h_data_p->egress_if_list = egress_if_list_node; 5558 } 5559 LOG_DEBUG(BSL_LS_BCM_OAM, 5560 (BSL_META_U(unit, 5561 "OAM(unit %d) Info: %s" 5562 " (EP_ID=%d) (INTF=0x%x).\n"), unit, __FUNCTION__, 5563 h_data_p->ep_id, 5564 egress_if)); 5565 return (BCM_E_NONE); 5566 } 5567 5568 /* 5569 * Function: 5570 * _bcm_sb2_oam_endpoint_egress_interface_delete 5571 * Purpose: 5572 * Delete an egress interface from an 5573 * endpoint info egress interface linked list. 5574 * Parameters: 5575 * unit - (IN) BCM device number 5576 * h_data_p - (IN) Endpoint hash data 5577 * gport - (IN) corresponding gport 5578 * Returns: 5579 * BCM_E_XXX 5580 */ 5581 STATIC int 5582 _bcm_sb2_oam_endpoint_egress_interface_delete(int unit, 5583 _bcm_oam_hash_data_t *h_data_p, 5584 bcm_gport_t gport) 5585 { 5586 _bcm_oam_endpoint_egress_interface_list_t *temp; 5587 _bcm_oam_endpoint_egress_interface_list_t *cur;/* Current endpoint node pointer.*/ 5588 _bcm_oam_endpoint_egress_interface_list_t *del_node;/* Pointer to a node to be deleted.*/ 5589 5590 cur = h_data_p->egress_if_list; 5591 if (NULL == cur) { 5592 /* No endpoints to remove from this group. */ 5593 LOG_DEBUG(BSL_LS_BCM_OAM, 5594 (BSL_META_U(unit, 5595 "OAM(unit %d) Info: No egress ifs to delete assoc to endpoint" 5596 " EP_ID:%d.\n"), unit, h_data_p->ep_id)); 5597 return (BCM_E_NONE); 5598 } 5599 5600 /* Check if head node needs to be deleated. */ 5601 if (gport == cur->gport) { 5602 /* Delete head node. */ 5603 del_node = h_data_p->egress_if_list; 5604 if ((h_data_p->egress_if_list)->next) { 5605 h_data_p->egress_if_list = (h_data_p->egress_if_list)->next; 5606 (h_data_p->egress_if_list)->prev = NULL; 5607 } else { 5608 h_data_p->egress_if_list = NULL; 5609 } 5610 sal_free(del_node); 5611 LOG_DEBUG(BSL_LS_BCM_OAM, 5612 (BSL_META_U(unit, 5613 "OAM(unit %d) Info: Head node delete EP_ID=%d - Success\n"), 5614 unit, h_data_p->ep_id)); 5615 return (BCM_E_NONE); 5616 } 5617 5618 /* Traverse the list and delete the matching node. */ 5619 while (NULL != cur->next->next) { 5620 temp = cur->next; 5621 5622 if (gport == temp->gport) { 5623 del_node = cur->next; 5624 cur->next = del_node->next; 5625 del_node->next->prev = cur; 5626 sal_free(del_node); 5627 LOG_DEBUG(BSL_LS_BCM_OAM, 5628 (BSL_META_U(unit, 5629 "OAM(unit %d) Info: Node delete EP_ID=%d - Success\n"), 5630 unit, h_data_p->ep_id)); 5631 return (BCM_E_NONE); 5632 } 5633 cur = cur->next; 5634 } 5635 5636 /* Check if tail node needs to be deleted. */ 5637 temp = cur->next; 5638 if (gport == temp->gport) { 5639 /* Delete tail node. */ 5640 del_node = cur->next; 5641 cur->next = NULL; 5642 sal_free(del_node); 5643 LOG_DEBUG(BSL_LS_BCM_OAM, 5644 (BSL_META_U(unit, 5645 "OAM(unit %d) Info: Tail node delete EP_ID=%d - Success\n"), 5646 unit, h_data_p->ep_id)); 5647 return (BCM_E_NONE); 5648 } 5649 5650 return (BCM_E_NOT_FOUND); 5651 } 5652 5653 /* 5654 * Function: 5655 * _bcm_sb2_oam_endpoint_egress_intf_add 5656 * Purpose: 5657 * Add an egress interface to an 5658 * endpoint info egress interface linked list. 5659 * Parameters: 5660 * unit - (IN) BCM device number 5661 * h_data_p - (IN) Endpoint hash data 5662 * egress_if - (IN) Egress interface 5663 * Returns: 5664 * BCM_E_XXX 5665 */ 5666 STATIC int 5667 _bcm_sb2_oam_endpoint_egress_intf_add(int unit, 5668 _bcm_oam_hash_data_t *h_data_p, 5669 bcm_if_t egress_if) 5670 { 5671 5672 return _bcm_sb2_oam_endpoint_egress_interface_add(unit, 5673 h_data_p, 5674 egress_if, 5675 BCM_GPORT_INVALID); 5676 } 5677 5678 /* 5679 * Function: 5680 * _bcm_sb2_oam_endpoint_egress_intf_delete 5681 * Purpose: 5682 * Delete an egress interface from an 5683 * endpoint info egress interface linked list. 5684 * Parameters: 5685 * unit - (IN) BCM device number 5686 * h_data_p - (IN) Endpoint hash data 5687 * egress_intf - (IN) egress interface identifier 5688 * Returns: 5689 * BCM_E_XXX 5690 */ 5691 5692 STATIC int 5693 _bcm_sb2_oam_endpoint_egress_intf_delete(int unit, 5694 _bcm_oam_hash_data_t *h_data_p, 5695 bcm_if_t egress_intf) 5696 { 5697 _bcm_oam_endpoint_egress_interface_list_t *temp; 5698 _bcm_oam_endpoint_egress_interface_list_t *cur;/* Current endpoint node pointer.*/ 5699 _bcm_oam_endpoint_egress_interface_list_t *del_node;/* Pointer to a node to be deleted.*/ 5700 5701 cur = h_data_p->egress_if_list; 5702 if (NULL == cur) { 5703 /* No endpoints to remove from this group. */ 5704 LOG_DEBUG(BSL_LS_BCM_OAM, 5705 (BSL_META_U(unit, 5706 "OAM(unit %d) Info: No egress ifs to delete assoc to endpoint" 5707 " EP_ID:%d.\n"), unit, h_data_p->ep_id)); 5708 return (BCM_E_NONE); 5709 } 5710 5711 /* Check if head node needs to be deleted. */ 5712 if (egress_intf == cur->egress_if) { 5713 /* Delete head node. */ 5714 del_node = h_data_p->egress_if_list; 5715 if ((h_data_p->egress_if_list)->next) { 5716 h_data_p->egress_if_list = (h_data_p->egress_if_list)->next; 5717 (h_data_p->egress_if_list)->prev = NULL; 5718 } else { 5719 h_data_p->egress_if_list = NULL; 5720 } 5721 sal_free(del_node); 5722 LOG_DEBUG(BSL_LS_BCM_OAM, 5723 (BSL_META_U(unit, 5724 "OAM(unit %d) Info: Head node delete EP_ID=%d - Success\n"), 5725 unit, h_data_p->ep_id)); 5726 return (BCM_E_NONE); 5727 } 5728 5729 /* Traverse the list and delete the matching node. */ 5730 while (NULL != cur->next->next) { 5731 temp = cur->next; 5732 5733 if (egress_intf == temp->egress_if) { 5734 del_node = cur->next; 5735 cur->next = del_node->next; 5736 del_node->next->prev = cur; 5737 sal_free(del_node); 5738 LOG_DEBUG(BSL_LS_BCM_OAM, 5739 (BSL_META_U(unit, 5740 "OAM(unit %d) Info: Node delete EP_ID=%d - Success\n"), 5741 unit, h_data_p->ep_id)); 5742 return (BCM_E_NONE); 5743 } 5744 cur = cur->next; 5745 } 5746 5747 /* Check if tail node needs to be deleted. */ 5748 temp = cur->next; 5749 if (egress_intf == temp->egress_if) { 5750 /* Delete tail node. */ 5751 del_node = cur->next; 5752 cur->next = NULL; 5753 sal_free(del_node); 5754 LOG_DEBUG(BSL_LS_BCM_OAM, 5755 (BSL_META_U(unit, 5756 "OAM(unit %d) Info: Tail node delete EP_ID=%d - Success\n"), 5757 unit, h_data_p->ep_id)); 5758 return (BCM_E_NONE); 5759 } 5760 5761 return (BCM_E_NOT_FOUND); 5762 } 5763 5764 /* 5765 * Function: 5766 * _bcm_sb2_oam_group_ep_list_add 5767 * Purpose: 5768 * Add an endpoint to a group endpoint linked list. 5769 * Parameters: 5770 * unit - (IN) BCM device number 5771 * group_id - (IN) OAM group ID. 5772 * ep_id - (IN) OAM endpoint ID. 5773 * Retruns: 5774 * BCM_E_XXX 5775 */ 5776 STATIC int 5777 _bcm_sb2_oam_group_ep_list_add(int unit, 5778 bcm_oam_group_t group_id, 5779 bcm_oam_endpoint_t ep_id) 5780 { 5781 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 5782 _bcm_oam_group_data_t *group_p; /* Pointer to group data. */ 5783 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 5784 _bcm_oam_ep_list_t *ep_list_p = NULL; /* Pointer to endpoint list. */ 5785 5786 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 5787 5788 group_p = &oc->group_info[group_id]; 5789 /* coverity[dead_error_condition] */ 5790 if (NULL == group_p) { 5791 LOG_ERROR(BSL_LS_BCM_OAM, 5792 (BSL_META_U(unit, 5793 "OAM(unit %d) Error: Group data access for GID=%d failed" 5794 /* coverity[dead_error_begin] */ 5795 " %s.\n"), unit, group_id, bcm_errmsg(BCM_E_INTERNAL))); 5796 return (BCM_E_INTERNAL); 5797 } 5798 5799 h_data_p = &oc->oam_hash_data[ep_id]; 5800 /* coverity[dead_error_condition] */ 5801 if (NULL == h_data_p) { 5802 LOG_ERROR(BSL_LS_BCM_OAM, 5803 (BSL_META_U(unit, 5804 "OAM(unit %d) Error: Endpoint data access for EP=%d failed" 5805 /* coverity[dead_error_begin] */ 5806 " %s.\n"), unit, ep_id, bcm_errmsg(BCM_E_INTERNAL))); 5807 return (BCM_E_INTERNAL); 5808 } 5809 5810 _BCM_OAM_ALLOC(ep_list_p, _bcm_oam_ep_list_t, sizeof(_bcm_oam_ep_list_t), 5811 "EP list"); 5812 if (NULL == ep_list_p) { 5813 LOG_ERROR(BSL_LS_BCM_OAM, 5814 (BSL_META_U(unit, 5815 "OAM(unit %d) Error: Endpoint list alloc for EP=%d failed" 5816 " %s.\n"), unit, ep_id, bcm_errmsg(BCM_E_MEMORY))); 5817 return (BCM_E_MEMORY); 5818 } 5819 5820 ep_list_p->prev = NULL; 5821 ep_list_p->ep_data_p = h_data_p; 5822 if (NULL == (*group_p->ep_list)) { 5823 /* Add endpoint as head node. */ 5824 ep_list_p->next = NULL; 5825 *group_p->ep_list = ep_list_p; 5826 } else { 5827 /* Add the endpoint to the linked list. */ 5828 ep_list_p->next = *group_p->ep_list; 5829 (*group_p->ep_list)->prev = ep_list_p; 5830 *group_p->ep_list = ep_list_p; 5831 } 5832 LOG_DEBUG(BSL_LS_BCM_OAM, 5833 (BSL_META_U(unit, 5834 "OAM(unit %d) Info: _bcm_sb2_oam_group_ep_list_add" 5835 " (GID=%d) (EP=%d).\n"), unit, group_id, ep_id)); 5836 return (BCM_E_NONE); 5837 } 5838 5839 /* 5840 * Function: 5841 * _bcm_sb2_oam_group_ep_list_remove 5842 * Purpose: 5843 * Remove an endpoint to a group endpoint linked list. 5844 * Parameters: 5845 * unit - (IN) BCM device number 5846 * group_id - (IN) OAM group ID. 5847 * ep_id - (IN) OAM endpoint ID. 5848 * Retruns: 5849 * BCM_E_XXX 5850 */ 5851 STATIC int 5852 _bcm_sb2_oam_group_ep_list_remove(int unit, 5853 bcm_oam_group_t group_id, 5854 bcm_oam_endpoint_t ep_id) 5855 { 5856 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 5857 _bcm_oam_group_data_t *group_p; /* Pointer to group data. */ 5858 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 5859 _bcm_oam_ep_list_t *cur; /* Current endpoint node pointer. */ 5860 _bcm_oam_ep_list_t *del_node; /* Pointer to a node to be deleted. */ 5861 5862 /* Control lock already taken by calling routine. */ 5863 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 5864 5865 group_p = &oc->group_info[group_id]; 5866 cur = *group_p->ep_list; 5867 if (NULL == cur) { 5868 /* No endpoints to remove from this group. */ 5869 LOG_DEBUG(BSL_LS_BCM_OAM, 5870 (BSL_META_U(unit, 5871 "OAM(unit %d) Info: No endpoints to delete in group" 5872 " GID:%d.\n"), unit, group_id)); 5873 return (BCM_E_NONE); 5874 } 5875 5876 /* Check if head node needs to be deleated. */ 5877 if (ep_id == cur->ep_data_p->ep_id) { 5878 /* Delete head node. */ 5879 del_node = *group_p->ep_list; 5880 if ((*group_p->ep_list)->next) { 5881 *group_p->ep_list = (*group_p->ep_list)->next; 5882 (*group_p->ep_list)->prev = NULL; 5883 } else { 5884 *group_p->ep_list = NULL; 5885 } 5886 sal_free(del_node); 5887 LOG_DEBUG(BSL_LS_BCM_OAM, 5888 (BSL_META_U(unit, 5889 "OAM(unit %d) Info: Head node delete GID=%d - Success\n"), 5890 unit, group_id)); 5891 return (BCM_E_NONE); 5892 } 5893 5894 /* Traverse the list and delete the matching node. */ 5895 while (NULL != cur->next->next) { 5896 h_data_p = cur->next->ep_data_p; 5897 if (NULL == h_data_p) { 5898 LOG_ERROR(BSL_LS_BCM_OAM, 5899 (BSL_META_U(unit, 5900 "OAM(unit %d) Error: Group=%d endpoints access failed -" 5901 " %s.\n"), unit, group_id, bcm_errmsg(BCM_E_INTERNAL))); 5902 return (BCM_E_INTERNAL); 5903 } 5904 5905 if (ep_id == h_data_p->ep_id) { 5906 del_node = cur->next; 5907 cur->next = del_node->next; 5908 del_node->next->prev = cur; 5909 sal_free(del_node); 5910 LOG_DEBUG(BSL_LS_BCM_OAM, 5911 (BSL_META_U(unit, 5912 "OAM(unit %d) Info: Node delete GID=%d - Success\n"), 5913 unit, group_id)); 5914 return (BCM_E_NONE); 5915 } 5916 cur = cur->next; 5917 } 5918 5919 /* Check if tail node needs to be deleted. */ 5920 h_data_p = cur->next->ep_data_p; 5921 if (ep_id == h_data_p->ep_id) { 5922 /* Delete tail node. */ 5923 del_node = cur->next; 5924 cur->next = NULL; 5925 sal_free(del_node); 5926 LOG_DEBUG(BSL_LS_BCM_OAM, 5927 (BSL_META_U(unit, 5928 "OAM(unit %d) Info: Tail node delete GID=%d - Success\n"), 5929 unit, group_id)); 5930 return (BCM_E_NONE); 5931 } 5932 5933 return (BCM_E_NOT_FOUND); 5934 } 5935 5936 /* 5937 * Function: 5938 * _bcm_oam_sb2_remote_mep_hw_set 5939 * Purpose: 5940 * Configure hardware tables for a remote endpoint. 5941 * Parameters: 5942 * unit - (IN) BCM device number 5943 * ep_info_p - (IN) Pointer to remote endpoint information. 5944 * Retruns: 5945 * BCM_E_XXX 5946 */ 5947 STATIC int 5948 _bcm_oam_sb2_remote_mep_hw_set(int unit, 5949 const bcm_oam_endpoint_info_t *ep_info_p) 5950 { 5951 l3_entry_1_entry_t l3_entry; /* Remote view entry. */ 5952 rmep_entry_t rmep_entry; /* Remote MEP entry. */ 5953 uint32 oam_cur_time; /* Current time. */ 5954 _bcm_oam_hash_data_t *h_data_p = NULL; /* Hash data pointer. */ 5955 int rv; /* Operation return status. */ 5956 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 5957 const bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint info. */ 5958 5959 if (NULL == ep_info_p) { 5960 return (BCM_E_INTERNAL); 5961 } 5962 5963 /* Initialize local endpoint info pointer. */ 5964 ep_p = ep_info_p; 5965 5966 /* Lock already taken by the calling routine. */ 5967 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 5968 5969 /* Get endpoint hash data pointer. */ 5970 h_data_p = &oc->oam_hash_data[ep_p->id]; 5971 if (0 == h_data_p->in_use) { 5972 return (BCM_E_INTERNAL); 5973 } 5974 5975 /* RMEP table programming. */ 5976 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 5977 5978 /* Set the MA group index. */ 5979 soc_RMEPm_field32_set(unit, &rmep_entry, MAID_INDEXf, 5980 ep_p->group); 5981 5982 /* 5983 * The following steps are necessary to enable CCM timeout events 5984 * without having received any CCMs. 5985 */ 5986 soc_RMEPm_field32_set(unit, &rmep_entry, 5987 RMEP_TIMESTAMP_VALIDf, 1); 5988 5989 BCM_IF_ERROR_RETURN 5990 (READ_OAM_CURRENT_TIMEr(unit, &oam_cur_time)); 5991 5992 soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMPf, 5993 oam_cur_time); 5994 5995 soc_RMEPm_field32_set(unit, &rmep_entry, 5996 RMEP_RECEIVED_CCMf, 5997 _bcm_sb2_oam_ccm_msecs_to_hw_encode(h_data_p->period)); 5998 /* End of timeout setup */ 5999 6000 soc_RMEPm_field32_set(unit, &rmep_entry, VALIDf, 1); 6001 6002 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index, 6003 &rmep_entry); 6004 if (BCM_FAILURE(rv)) { 6005 LOG_ERROR(BSL_LS_BCM_OAM, 6006 (BSL_META_U(unit, 6007 "OAM(unit %d) Error: RMEP table write failed EP=%d %s.\n"), 6008 unit, ep_info_p->id, bcm_errmsg(rv))); 6009 return (rv); 6010 } 6011 6012 /* L3 unicast table programming. */ 6013 sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t)); 6014 6015 /* Set the CCM interval. */ 6016 soc_L3_ENTRY_IPV4_UNICASTm_field32_set 6017 (unit, &l3_entry, RMEP__CCMf, 6018 _bcm_sb2_oam_ccm_msecs_to_hw_encode(h_data_p->period)); 6019 6020 /* Set the entry hardware index. */ 6021 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__RMEP_PTRf, 6022 h_data_p->remote_index); 6023 6024 /* 6025 * Construct endpoint RMEP view key for L3 Table entry 6026 * insert operation. 6027 */ 6028 _bcm_sb2_oam_rmep_key_construct(unit, h_data_p, &l3_entry); 6029 6030 /* Mark the entry as valid. */ 6031 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, VALIDf, 1); 6032 6033 /* Install entry in hardware. */ 6034 rv = soc_mem_insert(unit, L3_ENTRY_IPV4_UNICASTm, 6035 MEM_BLOCK_ALL, &l3_entry); 6036 if (BCM_FAILURE(rv)) { 6037 LOG_ERROR(BSL_LS_BCM_OAM, 6038 (BSL_META_U(unit, 6039 "OAM(unit %d) Error: L3 table insert failed EP=%d %s.\n"), 6040 unit, ep_p->id, bcm_errmsg(rv))); 6041 return (rv); 6042 } 6043 /* Add the H/w index to logical index mapping for RMEP */ 6044 oc->remote_endpoints[h_data_p->remote_index] = ep_p->id; 6045 6046 return (BCM_E_NONE); 6047 } 6048 /* 6049 * Function: 6050 * _bcm_sb2_oam_find_egr_lmep 6051 * Purpose: 6052 * Search EGR_MP_GROUP table and return the match entry hardware index and 6053 * match entry data. 6054 * Parameters: 6055 * unit - (IN) BCM device number 6056 * h_data_p - (IN) Pointer to endpoint hash data. 6057 * entry_idx - (OUT) Pointer to match entry hardware index. 6058 * mp_group_entry_p - (OUT) Pointer to match entry data. 6059 * Retruns: 6060 * BCM_E_XXX 6061 */ 6062 STATIC int 6063 _bcm_sb2_oam_find_egr_lmep(int unit, const _bcm_oam_hash_data_t *h_data_p, 6064 int *entry_idx, 6065 egr_mp_group_entry_t *mp_group_entry_p) 6066 { 6067 egr_mp_group_entry_t mp_group_entry; /* MP group table 6068 entry to search. */ 6069 int rv; /* Operation return status. */ 6070 6071 if (NULL == h_data_p || NULL == entry_idx || NULL == mp_group_entry_p) { 6072 return (BCM_E_INTERNAL); 6073 } 6074 6075 sal_memset(&mp_group_entry, 0, sizeof(egr_mp_group_entry_t)); 6076 6077 /* Construct endpoint egress MP group Table entry search operation. */ 6078 _bcm_sb2_oam_egr_lmep_key_construct(unit, h_data_p, &mp_group_entry); 6079 6080 soc_mem_lock(unit, EGR_MP_GROUPm); 6081 /* Perform the search in EGR_MP_GROUP table. */ 6082 rv = soc_mem_search(unit, EGR_MP_GROUPm, MEM_BLOCK_ANY, entry_idx, 6083 &mp_group_entry, mp_group_entry_p, 0); 6084 6085 if (SAL_BOOT_BCMSIM) { 6086 if(*entry_idx < 0) { 6087 rv = BCM_E_NOT_FOUND; 6088 } 6089 } 6090 soc_mem_unlock(unit, EGR_MP_GROUPm); 6091 if (BCM_FAILURE(rv)) { 6092 LOG_VERBOSE(BSL_LS_BCM_OAM, 6093 (BSL_META_U(unit, 6094 "OAM(unit %d) Error: Egr MP group entry lookup " 6095 "failed vlan=%d port =%x %s.\n"), 6096 unit, h_data_p->vlan, h_data_p->dglp, bcm_errmsg(rv))); 6097 } 6098 6099 return (rv); 6100 } 6101 6102 /* 6103 * Function: 6104 * _bcm_sb2_oam_find_lmep 6105 * Purpose: 6106 * Search LMEP view table and return the match entry hardware index and 6107 * match entry data. 6108 * Parameters: 6109 * unit - (IN) BCM device number 6110 * h_data_p - (IN) Pointer to endpoint hash data. 6111 * entry_idx - (OUT) Pointer to match entry hardware index. 6112 * mp_group_entry_p - (OUT) Pointer to match entry data. 6113 * Retruns: 6114 * BCM_E_XXX 6115 */ 6116 STATIC int 6117 _bcm_sb2_oam_find_lmep(int unit, const _bcm_oam_hash_data_t *h_data_p, 6118 int *entry_idx, 6119 mp_group_entry_t *mp_group_entry_p) 6120 { 6121 mp_group_entry_t mp_group_entry; /* MP group entry to search. */ 6122 int rv; /* Operation return status. */ 6123 6124 if (NULL == h_data_p || NULL == entry_idx || NULL == mp_group_entry_p) { 6125 return (BCM_E_INTERNAL); 6126 } 6127 6128 sal_memset(&mp_group_entry, 0, sizeof(mp_group_entry_t)); 6129 6130 /* Construct endpoint LMEP view key for L3 Table entry search operation. */ 6131 _bcm_sb2_oam_lmep_key_construct(unit, h_data_p, &mp_group_entry); 6132 6133 /* Take L3 module protection mutex to block any updates. */ 6134 L3_LOCK(unit); 6135 6136 BCM_SB2_TCAM_ATOMICITY_DISABLE(unit); 6137 /* Perform the search in MP_GROUP_ENTRY table. */ 6138 rv = soc_mem_search(unit, MP_GROUPm, MEM_BLOCK_ANY, entry_idx, 6139 &mp_group_entry, mp_group_entry_p, 0); 6140 BCM_SB2_TCAM_ATOMICITY_ENABLE(unit); 6141 if (BCM_FAILURE(rv)) { 6142 LOG_VERBOSE(BSL_LS_BCM_OAM, 6143 (BSL_META_U(unit, 6144 "OAM(unit %d) Error: MP group entry lookup vlan=%d port=%x %s.\n"), 6145 unit, h_data_p->vlan, h_data_p->sglp, bcm_errmsg(rv))); 6146 } 6147 6148 /* Release L3 module protection mutex. */ 6149 L3_UNLOCK(unit); 6150 6151 return (rv); 6152 } 6153 6154 STATIC int 6155 _bcm_sb2_oam_find_port_lmep(int unit, const _bcm_oam_hash_data_t *h_data_p, 6156 int *stm_index, source_trunk_map_table_entry_t *stm_entry, 6157 uint8 *mdl) 6158 { 6159 port_tab_entry_t port_entry; 6160 int rv = BCM_E_NONE; 6161 int port_id, mod_id; 6162 6163 rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, 6164 h_data_p->src_pp_port, &port_entry); 6165 6166 if (BCM_FAILURE(rv)) { 6167 return rv; 6168 } 6169 6170 *mdl = soc_PORT_TABm_field32_get(unit, &port_entry, MDL_BITMAPf); 6171 6172 if (*mdl == 0) { 6173 /* No port mep enabled already on this port */ 6174 return BCM_E_NOT_FOUND; 6175 } 6176 6177 port_id = _BCM_OAM_GLP_PORT_GET(h_data_p->sglp); 6178 mod_id = _BCM_OAM_GLP_MODULE_ID_GET(h_data_p->sglp); 6179 6180 /* Derive index to SOURCE_TRUNK_MAP tbl based on module ID and port*/ 6181 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, mod_id, 6182 port_id, stm_index)); 6183 BCM_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY, 6184 *stm_index, stm_entry)); 6185 return BCM_E_NONE; 6186 } 6187 6188 STATIC 6189 int _bcm_sb2_oam_lm_counters_mems_from_pool_get(int pool_id, soc_mem_t *mems) 6190 { 6191 switch(pool_id) { 6192 case 0: 6193 mems[0] = ING_OAM_LM_COUNTERS_0m; 6194 mems[1] = EGR_OAM_LM_COUNTERS_0m; 6195 break; 6196 case 1: 6197 mems[0] = ING_OAM_LM_COUNTERS_1m; 6198 mems[1] = EGR_OAM_LM_COUNTERS_1m; 6199 break; 6200 case 2: 6201 mems[0] = ING_OAM_LM_COUNTERS_2m; 6202 mems[1] = EGR_OAM_LM_COUNTERS_2m; 6203 break; 6204 default: 6205 /* should not happen */ 6206 return BCM_E_INTERNAL; 6207 break; 6208 } 6209 return BCM_E_NONE; 6210 } 6211 6212 6213 STATIC int 6214 _bcm_sb2_oam_lm_counters_hw_values_init(int unit, int pool_id, int ctr_index, 6215 bcm_oam_endpoint_info_t *ep_info_p) 6216 { 6217 ing_oam_lm_counters_0_entry_t entry; 6218 /* Ingress and egress. 2 memories */ 6219 soc_mem_t mems[2] = {INVALIDm, INVALIDm}; 6220 int index, entry_offset; 6221 6222 BCM_IF_ERROR_RETURN( 6223 _bcm_sb2_oam_lm_counters_mems_from_pool_get(pool_id, mems)); 6224 6225 for (index = 0; index < 2; index++) { 6226 sal_memset(&entry, 0, sizeof(entry)); 6227 6228 /* Set counter type */ 6229 if (ep_info_p->lm_ctr_type == bcmOamLmCounterTypePkt) { 6230 soc_mem_field32_set(unit, mems[index], &entry, LM_COUNT_TYPEf, 0); 6231 } else if (ep_info_p->lm_ctr_type == bcmOamLmCounterTypeByte) { 6232 soc_mem_field32_set(unit, mems[index], &entry, LM_COUNT_TYPEf, 1); 6233 } else { 6234 return BCM_E_PARAM; 6235 } 6236 6237 /* Set byte counter sample size and pdu ctr field size */ 6238 if (ep_info_p->lm_ctr_sample_size == bcmOamLmCounterSize32Bit) { 6239 soc_mem_field32_set(unit, mems[index], &entry, 6240 LM_COUNTER_SAMPLE_SIZEf, 0); 6241 } else if (ep_info_p->lm_ctr_sample_size == bcmOamLmCounterSize64Bit) { 6242 soc_mem_field32_set(unit, mems[index], &entry, 6243 LM_COUNTER_SAMPLE_SIZEf, 1); 6244 } else { 6245 return BCM_E_PARAM; 6246 } 6247 6248 if (MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) { 6249 soc_mem_field32_set(unit, mems[index], &entry, 6250 LM_PDU_COUNTER_FIELD_SIZEf, 1); 6251 } else { 6252 soc_mem_field32_set(unit, mems[index], &entry, 6253 LM_PDU_COUNTER_FIELD_SIZEf, 0); 6254 } 6255 6256 /* 8 entries allocated per endpoint */ 6257 for(entry_offset = 0; entry_offset < 8; entry_offset++) { 6258 BCM_IF_ERROR_RETURN(soc_mem_write(unit, mems[index], MEM_BLOCK_ALL, 6259 ctr_index + entry_offset, &entry)); 6260 } 6261 } 6262 6263 return BCM_E_NONE; 6264 } 6265 6266 STATIC int 6267 _bcm_sb2_oam_lm_counters_hw_values_reset(int unit, int pool_id, int index) 6268 { 6269 bcm_oam_endpoint_info_t ep_info; 6270 6271 /* Initialize the ep_info */ 6272 bcm_oam_endpoint_info_t_init(&ep_info); 6273 6274 /* Resetting to default values */ 6275 ep_info.lm_ctr_type = bcmOamLmCounterTypePkt; 6276 ep_info.lm_ctr_sample_size = bcmOamLmCounterSize32Bit; 6277 /* The type is Ethernet to set the PDU ctr 6278 * field size to 32 6279 */ 6280 ep_info.type = bcmOAMEndpointTypeEthernet; 6281 6282 return _bcm_sb2_oam_lm_counters_hw_values_init(unit, pool_id, index, 6283 &ep_info); 6284 } 6285 6286 /* 6287 * Function: 6288 * _bcm_sb2_oam_free_counter 6289 * Purpose: 6290 * Free counter from counter pool. 6291 * Parameters: 6292 * unit - (IN) BCM device number 6293 * Retruns: 6294 * BCM_E_XXX 6295 */ 6296 STATIC int 6297 _bcm_sb2_oam_free_counter(int unit, 6298 _bcm_oam_hash_data_t *hash_data) 6299 { 6300 int rv = BCM_E_NONE;/* Operation return status. */ 6301 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 6302 int pool_id = 0; 6303 6304 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 6305 6306 if (hash_data->rx_ctr != _BCM_OAM_INVALID_INDEX) { 6307 pool_id = (hash_data->rx_ctr >> 24); 6308 rv = shr_aidxres_list_free(oc->ing_lm_ctr_pool[pool_id], 6309 (hash_data->rx_ctr & 0xffffff)); 6310 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_lm_counters_hw_values_reset(unit, pool_id, 6311 hash_data->rx_ctr & 0xffffff)); 6312 if (BCM_FAILURE(rv)) { 6313 LOG_ERROR(BSL_LS_BCM_OAM, 6314 (BSL_META_U(unit, 6315 "OAM(unit %d) Error: LM counter block " 6316 "free failed (EP=%d) - %s.\n"), 6317 unit, hash_data->ep_id, bcm_errmsg(rv))); 6318 return (rv); 6319 } 6320 hash_data->rx_ctr = hash_data->tx_ctr = _BCM_OAM_INVALID_INDEX; 6321 } 6322 return (rv); 6323 } 6324 /* 6325 * Function: 6326 * _bcm_sb2_oam_alloc_counter 6327 * Purpose: 6328 * Allocate counter from counter pool. 6329 * Parameters: 6330 * unit - (IN) BCM device number 6331 * Retruns: 6332 * BCM_E_XXX 6333 */ 6334 STATIC int 6335 _bcm_sb2_oam_alloc_counter(int unit, bcm_oam_endpoint_info_t *ep_info_p, int pool_id, 6336 shr_idxres_element_t *ctr_index) 6337 { 6338 int rv; /* Operation return status. */ 6339 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 6340 6341 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 6342 6343 /* Allocate 8 consecutive couters from the pool */ 6344 rv = shr_aidxres_list_alloc_block(oc->ing_lm_ctr_pool[pool_id], 6345 8, ctr_index); 6346 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_lm_counters_hw_values_init(unit, pool_id, 6347 *ctr_index, ep_info_p)); 6348 if (BCM_FAILURE(rv)) { 6349 LOG_ERROR(BSL_LS_BCM_OAM, 6350 (BSL_META_U(unit, 6351 "OAM(unit %d) Error: LM counter block alloic failed " 6352 "- %s.\n"), unit, bcm_errmsg(rv))); 6353 return (rv); 6354 } 6355 return (BCM_E_NONE); 6356 } 6357 6358 6359 /* 6360 * Function: 6361 * _bcm_sb2_oam_counter_set 6362 * Purpose: 6363 * Set Rx counter for MEP 6364 * Parameters: 6365 * unit - (IN) BCM device number 6366 * Retruns: 6367 * BCM_E_XXX 6368 */ 6369 STATIC int 6370 _bcm_sb2_oam_counter_set(int unit, soc_mem_t mem, 6371 bcm_oam_endpoint_info_t *ep_info_p, 6372 uint32 *entry, 6373 shr_idxres_element_t *ctr_index, 6374 int *ctr_field_id, 6375 int *pool_id, 6376 int alloc_counter) 6377 { 6378 6379 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 6380 soc_field_t ctr1_field; 6381 soc_field_t ctr2_field; 6382 int ctr1_valid = 0; 6383 int ctr2_valid = 0; 6384 int rv = BCM_E_NONE;/* Operation return status. */ 6385 6386 /* Lock already taken by the calling routine. */ 6387 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 6388 6389 ctr1_field = CTR1_VALIDf; 6390 ctr2_field = CTR2_VALIDf; 6391 6392 ctr1_valid = soc_mem_field32_get(unit, mem, 6393 (uint32 *)entry, ctr1_field); 6394 ctr2_valid = soc_mem_field32_get(unit, mem, 6395 (uint32 *)entry, ctr2_field); 6396 6397 /* if both counters are already used, we can't enable LM on this endpoint */ 6398 if ((1 == ctr1_valid) && (1 == ctr2_valid)) { 6399 rv = BCM_E_RESOURCE; 6400 LOG_ERROR(BSL_LS_BCM_OAM, 6401 (BSL_META_U(unit, 6402 "OAM(unit %d) Error: 2 counters are already " 6403 "allocated for EP on this service interface" 6404 "%s.\n"), unit, bcm_errmsg(rv))); 6405 return (rv); 6406 } else if ((0 == ctr1_valid) && (1 == ctr2_valid)) { 6407 if (alloc_counter) { 6408 /* Pool id is provided by the user. */ 6409 *pool_id = ep_info_p->lm_ctr_pool_id; 6410 rv = _bcm_sb2_oam_alloc_counter(unit, ep_info_p, *pool_id, ctr_index); 6411 if (BCM_FAILURE(rv)) { 6412 LOG_ERROR(BSL_LS_BCM_OAM, 6413 (BSL_META_U(unit, 6414 "OAM(unit %d) Error: LM counter block alloc - %s.\n"), 6415 unit, bcm_errmsg(rv))); 6416 return (rv); 6417 } 6418 } 6419 *ctr_field_id = 0; 6420 ctr1_valid = 1; 6421 } else if ((0 == ctr2_valid) && (1 == ctr1_valid)) { 6422 if (alloc_counter) { 6423 /* Pool id is provided by the user. */ 6424 *pool_id = ep_info_p->lm_ctr_pool_id; 6425 rv = _bcm_sb2_oam_alloc_counter(unit, ep_info_p, *pool_id, ctr_index); 6426 if (BCM_FAILURE(rv)) { 6427 LOG_ERROR(BSL_LS_BCM_OAM, 6428 (BSL_META_U(unit, 6429 "OAM(unit %d) Error: LM counter block alloc - %s.\n"), 6430 unit, bcm_errmsg(rv))); 6431 return (rv); 6432 } 6433 } 6434 *ctr_field_id = 1; 6435 ctr2_valid = 1; 6436 } else { 6437 if (alloc_counter) { 6438 /* Pool id is provided by the user. */ 6439 *pool_id = ep_info_p->lm_ctr_pool_id; 6440 rv = _bcm_sb2_oam_alloc_counter(unit, ep_info_p, *pool_id, ctr_index); 6441 if (BCM_FAILURE(rv)) { 6442 LOG_ERROR(BSL_LS_BCM_OAM, 6443 (BSL_META_U(unit, 6444 "OAM(unit %d) Error: LM counter block alloc - %s.\n"), 6445 unit, bcm_errmsg(rv))); 6446 return (rv); 6447 } 6448 } 6449 /* Since both ctrs are free, use ctr1 */ 6450 *ctr_field_id = 0; 6451 ctr1_valid = 1; 6452 } 6453 return (rv); 6454 } 6455 6456 STATIC uint32 6457 _bcm_sb2_oam_qos_flags_to_mp_group_pri_mode(uint32 flags) 6458 { 6459 switch (flags) { 6460 case BCM_QOS_MAP_OAM_INTPRI: 6461 return 0; 6462 break; 6463 case BCM_QOS_MAP_OAM_OUTER_VLAN_PCP: 6464 return 2; 6465 break; 6466 case BCM_QOS_MAP_OAM_INNER_VLAN_PCP: 6467 return 3; 6468 break; 6469 case BCM_QOS_MAP_OAM_MPLS_EXP: 6470 return 1; 6471 break; 6472 } 6473 /* Default value is that of internal priority */ 6474 return 0; 6475 } 6476 6477 /* 6478 * Function: 6479 * _bcm_sb2_oam_lmep_counters_set 6480 * Purpose: 6481 * Get Tx counters for LMEP 6482 * Parameters: 6483 * unit - (IN) BCM device number 6484 * ep_info_p - (IN) Pointer to remote endpoint information. 6485 * Retruns: 6486 * BCM_E_XXX 6487 */ 6488 STATIC int 6489 _bcm_sb2_oam_lmep_counters_set(int unit, 6490 bcm_oam_endpoint_info_t *ep_info_p) 6491 { 6492 _bcm_oam_hash_data_t *hash_data; /* Pointer to endpoint hash data. */ 6493 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 6494 mp_group_entry_t mp_group_entry; /* MP group entry buffer.*/ 6495 int mp_group_index = -1;/* MP group entry hardware index.*/ 6496 shr_idxres_element_t ctr_index = 0; 6497 int pool_id = 0; 6498 int ctr_field_id = 0; 6499 egr_mp_group_entry_t egr_mp_group; /* Egress MP group tbl entry buffer */ 6500 int egr_mp_grp_index = 0; 6501 int rv = BCM_E_NONE;/* Operation return status. */ 6502 uint32 profile_index = 0; 6503 uint32 direction = 0; /* Up MEP or Down MEP */ 6504 uint32 flags = 0; /* Int pri or Exp or Inner dot1p 6505 or outer dot1p */ 6506 uint32 pri_mode = 0; 6507 uint32 map_ptr = 0; 6508 6509 /* Lock already taken by the calling routine. */ 6510 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 6511 6512 /* Get the stored endpoint information from hash table. */ 6513 hash_data = &oc->oam_hash_data[ep_info_p->id]; 6514 if (0 == hash_data->in_use) { 6515 return (BCM_E_INTERNAL); 6516 } 6517 6518 if (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 6519 direction = 1; 6520 } 6521 6522 6523 /*For downMEP Rx counters are in Ing Mp group table and for UpMEP 6524 it is in egr mp group table */ 6525 if (BCM_SUCCESS 6526 (_bcm_sb2_oam_find_lmep(unit, hash_data, &mp_group_index, &mp_group_entry))) { 6527 if (hash_data->rx_ctr == _BCM_OAM_INVALID_INDEX) { 6528 /* Allocate counters and configure the same in MP_Group entry */ 6529 rv = _bcm_sb2_oam_counter_set(unit, MP_GROUPm, 6530 ep_info_p, 6531 (uint32 *)&mp_group_entry, 6532 &ctr_index, 6533 &ctr_field_id, 6534 &pool_id, 6535 1); 6536 if (BCM_FAILURE(rv)) { 6537 LOG_ERROR(BSL_LS_BCM_OAM, 6538 (BSL_META_U(unit, 6539 "OAM(unit %d) Error: MP_GROUP_ENTRY table update failed " 6540 "for EP=%d due to counter allocation failure " 6541 "%s.\n"), unit, ep_info_p->id, bcm_errmsg(rv))); 6542 return (rv); 6543 } 6544 /* MS 8 bits of counter Id is pool id. LS 24 bits are index */ 6545 hash_data->rx_ctr = pool_id << 24 | (ctr_index); 6546 } else { 6547 pool_id = hash_data->rx_ctr >> 24; 6548 } 6549 hash_data->ctr_field_id = ctr_field_id; 6550 soc_MP_GROUPm_field32_set(unit, &mp_group_entry, 6551 sb2_mep_ctr_info[ctr_field_id].ctr_valid, 1); 6552 soc_MP_GROUPm_field32_set(unit, &mp_group_entry, 6553 sb2_mep_ctr_info[ctr_field_id].ctr_base_ptr, 6554 (hash_data->rx_ctr & 0xFFFFFF)); 6555 soc_MP_GROUPm_field32_set(unit, &mp_group_entry, 6556 sb2_mep_ctr_info[ctr_field_id].ctr_mep_type, direction); 6557 soc_MP_GROUPm_field32_set(unit, &mp_group_entry, 6558 sb2_mep_ctr_info[ctr_field_id].ctr_mep_mdl, ep_info_p->level); 6559 soc_MP_GROUPm_field32_set(unit, &mp_group_entry, 6560 sb2_mep_ctr_info[ctr_field_id].ctr_pool_id, pool_id); 6561 6562 /* If no priority map id is associated by user, associate it to 6563 * default priority map id 6564 */ 6565 if (0 == ep_info_p->pri_map_id) { 6566 ep_info_p->pri_map_id = oc->default_pri_map_id; 6567 } 6568 rv = _bcm_sb2_ing_service_pri_map_info_get(unit, ep_info_p->pri_map_id, 6569 &profile_index, &flags); 6570 hash_data->pri_map_index = ep_info_p->pri_map_id; 6571 6572 map_ptr = 6573 _BCM_SB2_SERVICE_PRI_MAP_PROFILE_INDEX_TO_MAP_PTR(profile_index); 6574 6575 soc_MP_GROUPm_field32_set(unit, &mp_group_entry, 6576 sb2_mep_ctr_info[ctr_field_id].ctr_profile, map_ptr); 6577 pri_mode = _bcm_sb2_oam_qos_flags_to_mp_group_pri_mode(flags); 6578 soc_MP_GROUPm_field32_set(unit, &mp_group_entry, 6579 sb2_mep_ctr_info[ctr_field_id].ctr_pri_mode, pri_mode); 6580 6581 BCM_SB2_TCAM_ATOMICITY_DISABLE(unit); 6582 rv = soc_mem_write(unit, MP_GROUPm, MEM_BLOCK_ALL, 6583 mp_group_index, &mp_group_entry); 6584 BCM_SB2_TCAM_ATOMICITY_ENABLE(unit); 6585 if (BCM_FAILURE(rv)) { 6586 LOG_ERROR(BSL_LS_BCM_OAM, 6587 (BSL_META_U(unit, 6588 "OAM(unit %d) Error: MP_GROUP_ENTRY table write failed " 6589 "for EP=%d %s.\n"), 6590 unit, ep_info_p->id, bcm_errmsg(rv))); 6591 return (rv); 6592 } 6593 6594 } else { 6595 LOG_ERROR(BSL_LS_BCM_OAM, 6596 (BSL_META_U(unit, 6597 "OAM(unit %d) Error: MP group tbl entry not found-%s.\n"), 6598 unit, bcm_errmsg(rv))); 6599 return rv; 6600 } 6601 6602 /*For downMEP Tx counters are in Egr Mp group table and for UpMEP it 6603 is in ING MP group table */ 6604 if (BCM_SUCCESS(_bcm_sb2_oam_find_egr_lmep(unit, hash_data, 6605 &egr_mp_grp_index, &egr_mp_group))) { 6606 if (SAL_BOOT_BCMSIM) { 6607 /* Added as WAR for Cmodel issue */ 6608 /* Construct endpoint egress MP group Table entry key part */ 6609 _bcm_sb2_oam_egr_lmep_key_construct(unit, hash_data, &egr_mp_group); 6610 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, VALIDf, 1); 6611 } 6612 if (hash_data->tx_ctr == _BCM_OAM_INVALID_INDEX) { 6613 /* Dont allocate counters. It is already allocated when oam_counter_set 6614 * is called before this(with MP_GROUP). 6615 * Just get the ctr_field_id. Set alloc_counter=0 6616 */ 6617 rv = _bcm_sb2_oam_counter_set(unit, EGR_MP_GROUPm, 6618 ep_info_p, 6619 (uint32 *)&egr_mp_group, 6620 &ctr_index, 6621 &ctr_field_id, 6622 &pool_id, 6623 0); 6624 if (BCM_FAILURE(rv)) { 6625 LOG_ERROR(BSL_LS_BCM_OAM, 6626 (BSL_META_U(unit, 6627 "OAM(unit %d) Error: EGR_MP_GROUP_ENTRY table update failed " 6628 "for EP=%d due to counter allocation failure " 6629 "%s.\n"), unit, ep_info_p->id, bcm_errmsg(rv))); 6630 return (rv); 6631 } 6632 /* MS 8 bits of counter Id is pool id. LS 24 bits are index */ 6633 hash_data->tx_ctr = pool_id << 24 | (ctr_index); 6634 } else { 6635 pool_id = hash_data->tx_ctr >> 24; 6636 } 6637 hash_data->egr_ctr_field_id = ctr_field_id; 6638 ep_info_p->lm_counter_base_id = hash_data->tx_ctr; 6639 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 6640 sb2_mep_ctr_info[ctr_field_id].ctr_valid, 1); 6641 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 6642 sb2_mep_ctr_info[ctr_field_id].ctr_base_ptr, 6643 (hash_data->tx_ctr & 0xFFFFFF)); 6644 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 6645 sb2_mep_ctr_info[ctr_field_id].ctr_mep_type, direction); 6646 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 6647 sb2_mep_ctr_info[ctr_field_id].ctr_mep_mdl, ep_info_p->level); 6648 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 6649 sb2_mep_ctr_info[ctr_field_id].ctr_pool_id, pool_id); 6650 6651 if (MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) { 6652 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 6653 sb2_mep_ctr_info[ctr_field_id].ctr_lm_payload_offset, 6654 ep_info_p->lm_payload_offset); 6655 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 6656 sb2_mep_ctr_info[ctr_field_id].ctr_lm_cos_offset, 6657 ep_info_p->lm_cos_offset); 6658 } 6659 6660 /* Profile ptr and priority mode is found already during 6661 ingress mp_group processing */ 6662 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 6663 sb2_mep_ctr_info[ctr_field_id].ctr_profile, map_ptr); 6664 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 6665 sb2_mep_ctr_info[ctr_field_id].ctr_pri_mode, pri_mode); 6666 hash_data->egr_pri_map_index = ep_info_p->pri_map_id; 6667 6668 rv = soc_mem_write(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL, 6669 egr_mp_grp_index, &egr_mp_group); 6670 if (BCM_FAILURE(rv)) { 6671 LOG_ERROR(BSL_LS_BCM_OAM, 6672 (BSL_META_U(unit, 6673 "OAM(unit %d) Error: EGR_MP_GROUP table update failed " 6674 "for EP=%d %s.\n"), 6675 unit, ep_info_p->id, bcm_errmsg(rv))); 6676 return (rv); 6677 } 6678 } else { 6679 LOG_ERROR(BSL_LS_BCM_OAM, 6680 (BSL_META_U(unit, 6681 "OAM(unit %d) Error: EGR MP group tbl entry not found-%s.\n"), 6682 unit, bcm_errmsg(rv))); 6683 return rv; 6684 } 6685 6686 return (rv); 6687 } 6688 6689 STATIC int 6690 _bcm_sb2_oam_lmep_down_modify_new_dest_port(int unit, _bcm_oam_hash_data_t *h_data_p) 6691 { 6692 6693 lmep_1_entry_t lmep_1_entry; /* LMEP_1 table entry.*/ 6694 6695 /* Get the LMEP_1 table entry. */ 6696 BCM_IF_ERROR_RETURN(READ_LMEP_1m(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, &lmep_1_entry)); 6697 6698 6699 /* Set the queue number */ 6700 if (h_data_p->tx_gport == BCM_GPORT_INVALID) { 6701 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, QUEUE_NUMf, 6702 SOC_INFO(unit).port_uc_cosq_base[h_data_p->dst_pp_port] + 6703 h_data_p->int_pri); 6704 } 6705 6706 /* Set the PP port */ 6707 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, PP_PORTf, h_data_p->dst_pp_port); 6708 6709 SOC_IF_ERROR_RETURN 6710 (WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index, 6711 &lmep_1_entry)); 6712 6713 6714 return (BCM_E_NONE); 6715 } 6716 6717 /* 6718 * Function: 6719 * _bcm_oam_sb2_local_tx_mep_hw_set 6720 * Purpose: 6721 * Configure hardware tables for a local CCM Tx enabled endpoint. 6722 * Parameters: 6723 * unit - (IN) BCM device number 6724 * ep_info_p - (IN) Pointer to remote endpoint information. 6725 * Retruns: 6726 * BCM_E_XXX 6727 */ 6728 STATIC int 6729 _bcm_oam_sb2_local_tx_mep_hw_set(int unit, 6730 bcm_oam_endpoint_info_t *ep_info_p) 6731 { 6732 int rv = BCM_E_NONE;/* Operation return status. */ 6733 _bcm_oam_hash_data_t *hash_data; /* Pointer to endpoint hash data. */ 6734 lmep_entry_t entry; /* LMEP table entry. */ 6735 lmep_1_entry_t entry_1; /* LMEP_1 table entry. */ 6736 int word; /* Word index. */ 6737 uint32 reversed_maid[BCM_OAM_GROUP_NAME_LENGTH / 4]; 6738 /* Group name in Hw format. */ 6739 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 6740 const bcm_oam_endpoint_info_t *ep_p;/* Pointer to endpoint info. */ 6741 int subport = 0; 6742 int oam_replacement_offset = 0; 6743 int tpid_index = 0; 6744 _bcm_kt2_subport_info_t subport_info; 6745 int up_mep = 0; 6746 int pp_port = 0; 6747 int pool = 0; 6748 int vlan_tag_control = 0; 6749 uint32 tag_type = 0; 6750 bcm_port_t local_tx_port = 0; 6751 int cosq_base = -1, count = -1; 6752 bcm_port_t up_mep_tx_port = 0; 6753 bcm_gport_t gport = 0; 6754 if (NULL == ep_info_p) { 6755 return (BCM_E_INTERNAL); 6756 } 6757 6758 /* Initialize local endpoint info pointer. */ 6759 ep_p = ep_info_p; 6760 6761 /* Lock already taken by the calling routine. */ 6762 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 6763 6764 /* Get the stored endpoint information from hash table. */ 6765 hash_data = &oc->oam_hash_data[ep_p->id]; 6766 if (0 == hash_data->in_use) { 6767 return(BCM_E_INTERNAL); 6768 } 6769 6770 sal_memset(&entry, 0, sizeof(lmep_entry_t)); 6771 sal_memset(&entry_1, 0, sizeof(lmep_1_entry_t)); 6772 6773 /* Set the Group base index. */ 6774 soc_LMEPm_field32_set(unit, &entry, MAID_INDEXf, ep_p->group); 6775 6776 /* Set source MAC address to be used on transmitted packets. */ 6777 soc_LMEPm_mac_addr_set(unit, &entry, SAf, ep_p->src_mac_address); 6778 6779 /* Set the Maintenance Domain Level. */ 6780 soc_LMEP_1m_field32_set(unit, &entry_1, MDLf, ep_p->level); 6781 6782 /* Set endpoint name. */ 6783 soc_LMEPm_field32_set(unit, &entry, MEPIDf, ep_p->name); 6784 6785 /* 6786 * Set VLAN ID to be used in the transmitted packet. 6787 * For link level MEPs, this VLAN_ID == 0. 6788 */ 6789 soc_LMEPm_field32_set(unit, &entry, SVLAN_TAGf, ep_p->vlan); 6790 6791 /* Set packet priority value to be used in transmitted packet. */ 6792 soc_LMEPm_field32_set(unit, &entry, PRIORITYf, ep_p->pkt_pri); 6793 6794 /* Set CVLAN Id */ 6795 soc_LMEPm_field32_set(unit, &entry, CVLAN_TAGf, ((ep_p->inner_pkt_pri << 13) | ep_p->inner_vlan)); 6796 6797 /* Set interval between CCM packet transmissions. */ 6798 soc_LMEPm_field32_set 6799 (unit, &entry, CCM_INTERVALf, 6800 _bcm_sb2_oam_ccm_msecs_to_hw_encode(ep_p->ccm_period)); 6801 6802 /* Set Port status TLV in CCM Tx packets. */ 6803 if (ep_p->flags & BCM_OAM_ENDPOINT_PORT_STATE_UPDATE) { 6804 if (ep_p->port_state > BCM_OAM_PORT_TLV_UP) { 6805 return BCM_E_PARAM; 6806 } 6807 soc_LMEPm_field32_set(unit, &entry, PORT_TLVf, 6808 (ep_p->port_state == BCM_OAM_PORT_TLV_UP) 6809 ? 1 : 0); 6810 } 6811 6812 6813 /* Set the MEP type - up/down */ 6814 soc_LMEPm_field32_set(unit, &entry, MEP_TYPEf, 6815 ((ep_p->flags & BCM_OAM_ENDPOINT_UP_FACING) ? 1 : 0)); 6816 /* 6817 * Construct group name for hardware. 6818 * i.e Word-reverse the MAID bytes for hardware. 6819 */ 6820 for (word = 0; word < (BCM_OAM_GROUP_NAME_LENGTH / 4); ++word) { 6821 reversed_maid[word] 6822 = bcm_htonl(((uint32 *) oc->group_info[ep_p->group].name) 6823 [((BCM_OAM_GROUP_NAME_LENGTH / 4) - 1) - word]); 6824 } 6825 6826 /* Set the group name. */ 6827 soc_LMEPm_field_set(unit, &entry, MAIDf, reversed_maid); 6828 /* Set OAM replacement offset & default TPID */ 6829 if (_BCM_OAM_EP_IS_ETH_OAM_VP_TYPE(hash_data)) { 6830 oam_replacement_offset = 1; 6831 if(hash_data->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) { 6832 oam_replacement_offset = 5; 6833 vlan_tag_control = 3; 6834 tag_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN; 6835 } else if (hash_data->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) { 6836 oam_replacement_offset = 3; 6837 vlan_tag_control = 1; 6838 tag_type =_BCM_OAM_DOMAIN_CVLAN; 6839 } else if (hash_data->vlan > 0) { 6840 oam_replacement_offset = 3; 6841 vlan_tag_control = 2; 6842 tag_type =_BCM_OAM_DOMAIN_SVLAN; 6843 } 6844 } 6845 6846 switch (hash_data->oam_domain) { 6847 case _BCM_OAM_DOMAIN_PORT: 6848 oam_replacement_offset = 1; 6849 vlan_tag_control = 0; 6850 break; 6851 6852 case _BCM_OAM_DOMAIN_CVLAN: 6853 vlan_tag_control = 1; 6854 oam_replacement_offset = 3; 6855 tag_type =_BCM_OAM_DOMAIN_CVLAN; 6856 break; 6857 6858 case _BCM_OAM_DOMAIN_SVLAN: 6859 oam_replacement_offset = 3; 6860 vlan_tag_control = 2; 6861 tag_type =_BCM_OAM_DOMAIN_SVLAN; 6862 break; 6863 6864 case _BCM_OAM_DOMAIN_S_PLUS_CVLAN: 6865 oam_replacement_offset = 5; 6866 vlan_tag_control = 3; 6867 tag_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN; 6868 break; 6869 6870 default: 6871 break; 6872 } 6873 6874 6875 /* if S or S+C vlan - set outer tpid index */ 6876 if ((tag_type == _BCM_OAM_DOMAIN_SVLAN) || 6877 (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN) 6878 ) { 6879 rv = _bcm_sb2_tpid_entry_add(unit, 6880 (ep_p->outer_tpid ? ep_p->outer_tpid : 6881 BCM_OAM_DEFAULT_TPID), 6882 BCM_OAM_TPID_TYPE_OUTER, &tpid_index); 6883 if (BCM_FAILURE(rv)) { 6884 LOG_ERROR(BSL_LS_BCM_OAM, 6885 (BSL_META_U(unit, 6886 "OAM(unit %d) Error: L3 entry config failed in TPID set " 6887 "for EP=%d %s.\n"), 6888 unit, ep_p->id, bcm_errmsg(rv))); 6889 return (rv); 6890 } 6891 hash_data->outer_tpid_profile_index = tpid_index; 6892 soc_LMEPm_field32_set(unit, &entry, SVLAN_TPID_INDEXf, tpid_index); 6893 } 6894 if ((tag_type == _BCM_OAM_DOMAIN_CVLAN) || 6895 /* C or S+C */ 6896 (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN) 6897 ) { 6898 rv = _bcm_sb2_tpid_entry_add(unit, 6899 (ep_p->inner_tpid ? ep_p->inner_tpid : 6900 BCM_OAM_DEFAULT_TPID), 6901 BCM_OAM_TPID_TYPE_INNER, &tpid_index); 6902 if (BCM_FAILURE(rv)) { 6903 LOG_ERROR(BSL_LS_BCM_OAM, 6904 (BSL_META_U(unit, 6905 "OAM(unit %d) Error: L3 entry config failed in TPID set " 6906 "for EP=%d"" %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 6907 return (rv); 6908 } 6909 hash_data->inner_tpid_profile_index = tpid_index; 6910 } 6911 6912 gport = hash_data->gport; 6913 if (BCM_GPORT_IS_TRUNK(ep_p->gport)) { 6914 gport = hash_data->resolved_trunk_gport; 6915 } 6916 if ((BCM_GPORT_IS_SUBPORT_PORT(gport)) && 6917 (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport))) { 6918 /* CoE port */ 6919 rv = _bcm_sb2_tpid_entry_add(unit, 6920 (ep_p->subport_tpid ? ep_p->subport_tpid : 6921 BCM_OAM_DEFAULT_TPID), 6922 BCM_OAM_TPID_TYPE_SUBPORT, &tpid_index); 6923 if (BCM_FAILURE(rv)) { 6924 LOG_ERROR(BSL_LS_BCM_OAM, 6925 (BSL_META_U(unit, 6926 "OAM(unit %d) Error: L3 entry config failed in TPID set " 6927 "for EP=%d %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 6928 return (rv); 6929 } 6930 soc_LMEPm_field32_set(unit, &entry, 6931 SUBPORT_TAG_TPID_INDEXf, tpid_index); 6932 hash_data->subport_tpid_profile_index = tpid_index; 6933 } 6934 6935 /* Set LMEP_1 table entry */ 6936 6937 /* If COE or LINKPHY port replacement offset should be increased 6938 by 2 to accomodate - stream_id/subport tag */ 6939 if (BCM_GPORT_IS_SUBPORT_PORT(gport)) { 6940 if ((_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport)) || 6941 (_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, gport))) { 6942 oam_replacement_offset += 2; 6943 subport = 1 << 2; 6944 } 6945 } 6946 6947 soc_LMEP_1m_field32_set(unit, &entry_1, OAM_REPLACEMENT_OFFSETf, 6948 oam_replacement_offset); 6949 6950 6951 /* Set Tag status of the generated CCM packet 6952 we can set it based on incoming packet tag info 6953 if SUBPORT - vlan tag control = 1 << 2 | hash_data->oam_domain & 0x3 */ 6954 if (subport) { 6955 soc_LMEP_1m_field32_set(unit, &entry_1, VLAN_TAG_CONTROLf, 6956 (subport | (vlan_tag_control & 0x3))); 6957 } else { 6958 soc_LMEP_1m_field32_set(unit, &entry_1, VLAN_TAG_CONTROLf, 6959 (vlan_tag_control & 0x3)); 6960 6961 } 6962 6963 /* allocate TX counters */ 6964 if ((ep_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) { 6965 if (ep_info_p->lm_counter_base_id != _BCM_OAM_LM_COUNTER_IDX_INVALID) { 6966 /* Get the counter pool id */ 6967 pool = ep_info_p->lm_counter_base_id >> 24; 6968 switch(pool){ 6969 case 0: 6970 /* Set Counter 1 ID and action */ 6971 soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_1_IDf, 6972 (ep_info_p->lm_counter_base_id & 0xFFFF)); 6973 soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_1_ACTIONf, 1); 6974 break; 6975 case 1: 6976 /* Set Counter 2 ID and action */ 6977 soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_2_IDf, 6978 (ep_info_p->lm_counter_base_id & 0xFFFF)); 6979 soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_2_ACTIONf, 1); 6980 break; 6981 case 2: 6982 /* Set Counter 3 ID and action */ 6983 soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_3_IDf, 6984 (ep_info_p->lm_counter_base_id & 0xFFFF)); 6985 soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_3_ACTIONf, 1); 6986 break; 6987 } 6988 } 6989 6990 if (ep_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 6991 /* TX counter is located in IP */ 6992 soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_1_LOCATIONf, 0); 6993 soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_2_LOCATIONf, 0); 6994 soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_3_LOCATIONf, 0); 6995 } else { 6996 /* TX counter is located in EP */ 6997 soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_1_LOCATIONf, 1); 6998 soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_2_LOCATIONf, 1); 6999 soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_3_LOCATIONf, 1); 7000 } 7001 } else { 7002 soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_1_ACTIONf, 0); 7003 soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_2_ACTIONf, 0); 7004 soc_LMEP_1m_field32_set(unit, &entry_1, COUNTER_3_ACTIONf, 0); 7005 } 7006 7007 if (ep_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 7008 up_mep = 1; 7009 } 7010 /* For DownMEP, set Queue number to which this packet must be enqueued */ 7011 if (!up_mep) { 7012 /* For DownMEPs, the queue that the CCM needs to go out 7013 * could be special type of queue apart from the queues that 7014 * are statically allocated for the ports. In such a case, 7015 * they need to pass the COSQ GPORT for the queue that needs to 7016 * be used via tx_gport variable. We get the cosq_base from that 7017 * and derive correct queue number by adding the cosq index got 7018 * in the int_pri variable. 7019 */ 7020 if ((ep_p->tx_gport != BCM_GPORT_INVALID) && 7021 (BCM_GPORT_IS_UCAST_QUEUE_GROUP(ep_p->tx_gport) || 7022 BCM_GPORT_IS_UCAST_SUBSCRIBER_QUEUE_GROUP(ep_p->tx_gport)) && 7023 !(BCM_GPORT_IS_SCHEDULER(ep_p->tx_gport))) { 7024 BCM_IF_ERROR_RETURN(_bcm_kt2_cosq_index_resolve(unit, ep_p->tx_gport, -1, 7025 _BCM_KT2_COSQ_INDEX_STYLE_UCAST_QUEUE, 7026 &local_tx_port, &cosq_base, &count)); 7027 soc_LMEP_1m_field32_set(unit, &entry_1, QUEUE_NUMf, 7028 cosq_base + ep_p->int_pri); 7029 } else { 7030 soc_LMEP_1m_field32_set(unit, &entry_1, QUEUE_NUMf, 7031 SOC_INFO(unit).port_uc_cosq_base[hash_data->dst_pp_port] + 7032 ep_p->int_pri); 7033 } 7034 /* Set the destination port on which packet needs to Tx. */ 7035 pp_port = hash_data->dst_pp_port; 7036 } else { 7037 soc_LMEP_1m_field32_set(unit, &entry_1, INT_PRIf, 7038 ep_p->int_pri); 7039 /* Set the source on which packet is received */ 7040 pp_port = hash_data->src_pp_port; 7041 } 7042 7043 if (ep_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW) { 7044 up_mep_tx_port = _BCM_KT2_SUBPORT_PORT_ID_GET(ep_p->tx_gport); 7045 hash_data->src_pp_port = up_mep_tx_port; 7046 pp_port = hash_data->src_pp_port; 7047 } 7048 /* Set the PP port */ 7049 soc_LMEP_1m_field32_set(unit, &entry_1, PP_PORTf, pp_port); 7050 7051 /* Set Outgoing Subport tag to be inserted into CCM packet */ 7052 if ((BCM_GPORT_IS_SUBPORT_PORT(gport)) && 7053 (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, gport))) { 7054 /* Get the subport tag */ 7055 rv = bcm_kt2_subport_pp_port_subport_info_get(unit, pp_port, 7056 &subport_info); 7057 if (BCM_FAILURE(rv)) { 7058 LOG_ERROR(BSL_LS_BCM_OAM, 7059 (BSL_META_U(unit, 7060 "OAM(unit %d) Error: failed to get subport tag EP=%d" 7061 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 7062 return (rv); 7063 } 7064 if (subport_info.port_type == _BCM_KT2_SUBPORT_TYPE_SUBTAG) { 7065 soc_LMEP_1m_field32_set(unit, &entry_1, SUBPORT_TAGf, 7066 subport_info.subtag); 7067 } 7068 } 7069 7070 /* Set Interface status TLV in CCM Tx packets - 3-bits wide. */ 7071 if (ep_p->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_UPDATE) { 7072 if ((ep_p->interface_state < BCM_OAM_INTERFACE_TLV_UP) 7073 || (ep_p->interface_state > BCM_OAM_INTERFACE_TLV_LLDOWN)) { 7074 return BCM_E_PARAM; 7075 } 7076 soc_LMEP_1m_field32_set(unit, &entry_1, INTERFACE_TLVf, 7077 ep_p->interface_state); 7078 } 7079 /* 7080 * When this bit is '1', both port and interface TLV values are set in 7081 * CCM Tx packets - set in LMEP table. 7082 */ 7083 if ((ep_p->flags & BCM_OAM_ENDPOINT_PORT_STATE_TX) 7084 || (ep_p->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_TX)) { 7085 soc_LMEPm_field32_set(unit, &entry, INSERT_TLVf, 1); 7086 } 7087 7088 /* Set CCM packet Destination MAC address value. */ 7089 soc_mem_mac_addr_set(unit, LMEP_1m, &entry_1, DAf, 7090 ep_p->dst_mac_address); 7091 7092 7093 /* Write entry to hardware LMEP table. */ 7094 SOC_IF_ERROR_RETURN 7095 (WRITE_LMEPm(unit, MEM_BLOCK_ALL, hash_data->local_tx_index, 7096 &entry)); 7097 7098 /* Write entry to hardware LMEP_1 table. */ 7099 SOC_IF_ERROR_RETURN 7100 (WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, hash_data->local_tx_index, 7101 &entry_1)); 7102 7103 7104 return (BCM_E_NONE); 7105 } 7106 7107 /* 7108 * Function: 7109 * _bcm_sb2_oam_stm_table_update 7110 * Purpose: 7111 * Update MA_BASE_PTR in source trunk MAP table 7112 * Parameters: 7113 * unit - (IN) BCM device number 7114 * mod_id - (IN) module id 7115 * port_id - (IN) port id 7116 * h_data_p - (IN) endpoint hash data 7117 * Retruns: 7118 * BCM_E_XXX 7119 */ 7120 STATIC int 7121 _bcm_sb2_oam_stm_table_update(int unit, bcm_module_t mod_id, 7122 bcm_port_t port_id, 7123 _bcm_oam_hash_data_t *h_data_p) 7124 { 7125 int stm_index = 0; 7126 int rv = BCM_E_NONE; 7127 7128 source_trunk_map_table_entry_t stm_entry; 7129 soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm); 7130 /* Derive index to SOURCE_TRUNK_MAP tbl based on module ID and port*/ 7131 rv = _bcm_esw_src_mod_port_table_index_get(unit, mod_id, 7132 port_id, &stm_index); 7133 7134 if(BCM_FAILURE(rv)) { 7135 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 7136 return rv; 7137 } 7138 7139 rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY, 7140 stm_index, &stm_entry); 7141 if(BCM_FAILURE(rv)) { 7142 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 7143 return rv; 7144 } 7145 7146 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry, MA_BASE_PTRf, 7147 h_data_p->ma_base_index); 7148 rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ALL, stm_index, 7149 &stm_entry); 7150 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 7151 return rv; 7152 } 7153 7154 7155 /* 7156 * Function: 7157 * _bcm_sb2_oam_port_mdl_update 7158 * Purpose: 7159 * Update MDL bitmap in port table 7160 * Parameters: 7161 * unit - (IN) BCM device number 7162 * pp_port - (IN) pp port id 7163 * reset - (IN) Reset MDL bitmap or not 7164 * h_data_p - (IN) endpoint hash data 7165 * mdl - (OUT) Maintenance domain level 7166 * Retruns: 7167 * BCM_E_XXX 7168 */ 7169 STATIC int 7170 _bcm_sb2_oam_port_mdl_update(int unit, uint32 pp_port, int reset, 7171 _bcm_oam_hash_data_t *h_data_p, uint8 *mdl) 7172 { 7173 port_tab_entry_t port_entry; 7174 7175 if (NULL == h_data_p) { 7176 return (BCM_E_INTERNAL); 7177 } 7178 BCM_IF_ERROR_RETURN 7179 (soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, pp_port, &port_entry)); 7180 7181 /* read and update MDL bitmap */ 7182 *mdl = soc_PORT_TABm_field32_get(unit, &port_entry, MDL_BITMAPf); 7183 if (reset) { 7184 /* Clear the MDL bit for this endpoint. */ 7185 *mdl &= ~(1 << h_data_p->level); 7186 7187 } else { 7188 *mdl |= (1 << h_data_p->level); 7189 } 7190 soc_PORT_TABm_field32_set(unit, &port_entry, MDL_BITMAPf, *mdl); 7191 BCM_IF_ERROR_RETURN 7192 (soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, pp_port, &port_entry)); 7193 7194 return BCM_E_NONE; 7195 } 7196 7197 /* 7198 * Function: 7199 * _bcm_sb2_oam_port_mdl_passive_update 7200 * Purpose: 7201 * Update passive MDL bitmap in egress port table 7202 * Parameters: 7203 * unit - (IN) BCM device number 7204 * reset - (IN) Reset MDL bitmap 7205 * h_data_p - (IN) endpoint hash data 7206 * Retruns: 7207 * BCM_E_XXX 7208 */ 7209 STATIC int 7210 _bcm_sb2_oam_port_mdl_passive_update(int unit, int reset, 7211 _bcm_oam_hash_data_t *h_data_p, uint8 mdl) 7212 { 7213 egr_port_entry_t egr_port_entry; 7214 uint8 passive_mdl = 0; /* Maintenance domain level-passive */ 7215 7216 if (NULL == h_data_p) { 7217 return (BCM_E_INTERNAL); 7218 } 7219 7220 /* Passive demux should not be done for MIP */ 7221 if (_BCM_OAM_EP_IS_MIP(h_data_p)) { 7222 return BCM_E_NONE; 7223 } 7224 7225 /* Set MDL passive bitmap in EGR_PORT table */ 7226 BCM_IF_ERROR_RETURN 7227 (soc_mem_read(unit, EGR_PORTm, MEM_BLOCK_ANY, h_data_p->dst_pp_port, 7228 &egr_port_entry)); 7229 7230 if (reset) { 7231 if (mdl > 0) { 7232 /* Passive MDL bitmap */ 7233 _bcm_sb2_oam_get_passive_mdl_from_active_mdl(unit, mdl, 7234 h_data_p->ma_base_index, &passive_mdl, 0); 7235 } else { 7236 passive_mdl = 0; 7237 } 7238 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 7239 MDL_BITMAP_PASSIVEf, passive_mdl); 7240 } else { 7241 /* read and update MDL bitmap */ 7242 mdl = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, 7243 MDL_BITMAP_PASSIVEf); 7244 mdl |= (1 << h_data_p->level); 7245 7246 /* Set all the bits till the highest configured MDL, so that there are 7247 no holes in the bitmap */ 7248 mdl |= ((1 << h_data_p->level) - 1); 7249 7250 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 7251 MDL_BITMAP_PASSIVEf, mdl); 7252 } 7253 BCM_IF_ERROR_RETURN 7254 (soc_mem_write(unit, EGR_PORTm, MEM_BLOCK_ALL, 7255 h_data_p->dst_pp_port, &egr_port_entry)); 7256 return BCM_E_NONE; 7257 } 7258 7259 /* 7260 * Function: 7261 * _bcm_sb2_oam_trunk_port_mdl_config 7262 * Purpose: 7263 * Update port mdl and stm table for OAM on trunk case 7264 * Parameters: 7265 * unit - (IN) BCM device number 7266 * h_data_p - (IN) Pointer to hash data 7267 * Retruns: 7268 * BCM_E_XXX 7269 */ 7270 STATIC int 7271 _bcm_sb2_oam_trunk_port_mdl_config(int unit, 7272 _bcm_oam_hash_data_t *h_data_p) 7273 { 7274 int rv = BCM_E_NONE;/* Operation return status. */ 7275 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 7276 int member_count = 0; 7277 bcm_port_t *member_array = NULL; /* Trunk member port array. */ 7278 int local_member_count = 0; 7279 int i = 0; 7280 bcm_port_t port = 0; 7281 bcm_module_t module_id; /* Module ID */ 7282 uint8 mdl = 0; 7283 7284 /* Lock already taken by the calling routine. */ 7285 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 7286 7287 if(h_data_p->trunk_id == BCM_TRUNK_INVALID) { 7288 return BCM_E_PARAM; 7289 } 7290 7291 /* Get all the local member ports belonging to this trunk */ 7292 BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, h_data_p->trunk_id, 7293 NULL, 0, NULL, &member_count)); 7294 if (0 == member_count) { 7295 /* No members have been added to the trunk group yet */ 7296 LOG_ERROR(BSL_LS_BCM_OAM, 7297 (BSL_META_U(unit, 7298 "OAM(unit %d) Error: No local members have been added to " 7299 "the trunk group yet - %s.\n"), unit, bcm_errmsg(rv))); 7300 return BCM_E_PARAM; 7301 } 7302 7303 _BCM_OAM_ALLOC(member_array, bcm_port_t, 7304 sizeof(bcm_port_t) * member_count, "Trunk info"); 7305 if (NULL == member_array) { 7306 return (BCM_E_MEMORY); 7307 } 7308 7309 /* Get members of the trunk belonging to this module */ 7310 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 7311 h_data_p->trunk_id, 7312 member_count, member_array, 7313 &local_member_count))) { 7314 if (local_member_count > 0) { 7315 for(i = 0; i < local_member_count; i++) { 7316 rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i], 7317 &module_id, &port); 7318 if (BCM_FAILURE(rv)) { 7319 sal_free(member_array); 7320 return (rv); 7321 } 7322 rv = _bcm_sb2_oam_stm_table_update(unit, module_id, 7323 member_array[i], h_data_p); 7324 if (BCM_FAILURE(rv)) { 7325 sal_free(member_array); 7326 return (rv); 7327 } 7328 rv =_bcm_sb2_oam_port_mdl_update(unit, member_array[i], 0, 7329 h_data_p, &mdl); 7330 if (BCM_FAILURE(rv)) { 7331 sal_free(member_array); 7332 return (rv); 7333 } 7334 } 7335 } 7336 h_data_p->active_mdl_bitmap = mdl; 7337 } 7338 sal_free(member_array); 7339 return BCM_E_NONE; 7340 } 7341 7342 /* 7343 * Function: 7344 * _bcm_sb2_port_domain_oam_hw_set 7345 * Purpose: 7346 * Configure port table and stm table entries for port based MEP. 7347 * Parameters: 7348 * unit - (IN) BCM device number 7349 * ep_info_p - (IN) Pointer to remote endpoint information. 7350 * Retruns: 7351 * BCM_E_XXX 7352 */ 7353 STATIC int 7354 _bcm_sb2_port_domain_oam_hw_set(int unit, 7355 const bcm_oam_endpoint_info_t *ep_info_p) 7356 { 7357 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 7358 int rv = BCM_E_NONE;/* Operation return status. */ 7359 uint8 mdl = 0; /* Maintenance domain level. */ 7360 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 7361 const bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint info. */ 7362 bcm_module_t mod_id = 0; 7363 bcm_port_t port_id = 0; 7364 7365 if (NULL == ep_info_p) { 7366 return (BCM_E_INTERNAL); 7367 } 7368 7369 /* Initialize local endpoint info pointer. */ 7370 ep_p = ep_info_p; 7371 7372 /* Lock already taken by the calling routine. */ 7373 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 7374 7375 /* Get endpoint hash data pointer. */ 7376 h_data_p = &oc->oam_hash_data[ep_p->id]; 7377 7378 /* Set port table and source trunk map table */ 7379 if (0 == ep_info_p->vlan) { 7380 if(h_data_p->trunk_id != BCM_TRUNK_INVALID) { 7381 rv = _bcm_sb2_oam_trunk_port_mdl_config(unit, h_data_p); 7382 } else { 7383 port_id = _BCM_OAM_GLP_PORT_GET(h_data_p->sglp); 7384 mod_id = _BCM_OAM_GLP_MODULE_ID_GET(h_data_p->sglp); 7385 BCM_IF_ERROR_RETURN 7386 (_bcm_sb2_oam_stm_table_update(unit, mod_id, 7387 port_id, h_data_p)); 7388 BCM_IF_ERROR_RETURN 7389 (_bcm_sb2_oam_port_mdl_update(unit, h_data_p->src_pp_port, 0, 7390 h_data_p, &mdl)); 7391 h_data_p->active_mdl_bitmap = mdl; 7392 } 7393 BCM_IF_ERROR_RETURN 7394 (_bcm_sb2_oam_port_mdl_passive_update(unit, 0, h_data_p, mdl)); 7395 } 7396 return (rv); 7397 } 7398 7399 7400 /* 7401 * Function: 7402 * _bcm_sb2_oam_ing_mp_group_entry_set 7403 * Purpose: 7404 * Configure MP Group entry tables entry for a local CCM Rx enabled endpoint. 7405 * Parameters: 7406 * unit - (IN) BCM device number 7407 * ep_info_p - (IN) Pointer to remote endpoint information. 7408 * Retruns: 7409 * BCM_E_XXX 7410 */ 7411 STATIC int 7412 _bcm_sb2_oam_ing_mp_group_entry_set(int unit, 7413 bcm_oam_endpoint_info_t *ep_info_p) 7414 { 7415 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 7416 mp_group_entry_t mp_group_entry; /* L3 entry buffer. */ 7417 int entry_index = -1; /* L3 entry hardware index. */ 7418 int rv; /* Operation return status. */ 7419 uint8 mdl = 0; /* Maintenance domain level. */ 7420 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 7421 bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint info. */ 7422 soc_field_t mdl_field = 0; 7423 int up_mep = 0; /* Endpoint is an upMep */ 7424 7425 if (NULL == ep_info_p) { 7426 return (BCM_E_INTERNAL); 7427 } 7428 7429 /* Initialize local endpoint info pointer. */ 7430 ep_p = ep_info_p; 7431 7432 /* Lock already taken by the calling routine. */ 7433 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 7434 7435 /* Get endpoint hash data pointer. */ 7436 h_data_p = &oc->oam_hash_data[ep_p->id]; 7437 7438 if (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 7439 up_mep = 1 ; 7440 mdl_field = MDL_BITMAP_PASSIVEf; 7441 } else { 7442 mdl_field = MDL_BITMAP_ACTIVEf; 7443 } 7444 /* MP Group entry */ 7445 L3_LOCK(unit); 7446 if (BCM_SUCCESS 7447 (_bcm_sb2_oam_find_lmep(unit, h_data_p, &entry_index, &mp_group_entry))) { 7448 7449 if ((mdl_field == MDL_BITMAP_PASSIVEf) && 7450 (_BCM_OAM_EP_IS_MIP(h_data_p))) { 7451 /* Passive demultiplexing should not be done on a MIP */ 7452 L3_UNLOCK(unit); 7453 return BCM_E_NONE; 7454 } 7455 /* There's already an entry for this */ 7456 mdl = soc_MP_GROUPm_field32_get(unit, &mp_group_entry, mdl_field); 7457 7458 /* If active bitmap is 0, so for first active endppoint in the mp_group 7459 * need to programme ma_base_ptr field during down_mep creation */ 7460 if((mdl == 0) && (up_mep == 0)) { 7461 soc_MP_GROUPm_field32_set(unit, &mp_group_entry, MA_BASE_PTRf, 7462 h_data_p->ma_base_index); 7463 } 7464 7465 mdl |= (1 << ep_p->level); 7466 7467 /* Set all the bits till the highest configured MDL, so that there are 7468 no holes in the passive bitmap */ 7469 if (up_mep) { 7470 mdl |= ((1 << ep_p->level) - 1); 7471 } 7472 /* set MDL bitmap passive or active depending on up or down mep */ 7473 soc_MP_GROUPm_field32_set(unit, &mp_group_entry, mdl_field, mdl); 7474 7475 BCM_SB2_TCAM_ATOMICITY_DISABLE(unit); 7476 rv = soc_mem_write(unit, MP_GROUPm, MEM_BLOCK_ALL, 7477 entry_index, &mp_group_entry); 7478 BCM_SB2_TCAM_ATOMICITY_ENABLE(unit); 7479 if (BCM_FAILURE(rv)) { 7480 L3_UNLOCK(unit); 7481 LOG_ERROR(BSL_LS_BCM_OAM, 7482 (BSL_META_U(unit, 7483 "OAM(unit %d) Error: MP_GROUP table update failed for " 7484 "EP=%d" " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 7485 return (rv); 7486 } 7487 } else { 7488 7489 /* This is the first entry at this */ 7490 sal_memset(&mp_group_entry, 0, sizeof(mp_group_entry_t)); 7491 7492 /* Passive demultiplexing should not be done on a MIP */ 7493 if (!((mdl_field == MDL_BITMAP_PASSIVEf) 7494 && (_BCM_OAM_EP_IS_MIP(h_data_p)))) { 7495 mdl |= (1 << ep_p->level); 7496 7497 /* Set all the bits till the highest configured MDL, so that there are 7498 no holes in the passive bitmap */ 7499 if (up_mep) { 7500 mdl |= ((1 << ep_p->level) - 1); 7501 } 7502 7503 /* set MDL bitmap passive or active depending on up or down mep */ 7504 soc_MP_GROUPm_field32_set(unit, &mp_group_entry, mdl_field, mdl); 7505 } 7506 7507 if (mdl == 0) { 7508 /* MDL = 0 for case of MIP. Dont make the entry valid by 7509 programming other fields. */ 7510 L3_UNLOCK(unit); 7511 return BCM_E_NONE; 7512 } 7513 7514 soc_MP_GROUPm_field32_set(unit, &mp_group_entry, 7515 MA_BASE_PTRf, 7516 h_data_p->ma_base_index); 7517 7518 /* Configure time stamp type 1588(PTP)/NTP */ 7519 soc_MP_GROUPm_field32_set(unit, &mp_group_entry, 7520 TIMESTAMP_TYPEf, 7521 ((ep_p->timestamp_format == bcmOAMTimestampFormatNTP) ? 1 : 0)); 7522 7523 h_data_p->ts_format = ep_p->timestamp_format; 7524 7525 /* Construct LMEP view key for L3 Table insert operation. */ 7526 _bcm_sb2_oam_lmep_key_construct(unit, h_data_p, &mp_group_entry); 7527 7528 7529 7530 soc_MP_GROUPm_field32_set(unit, &mp_group_entry, VALIDf, 1); 7531 7532 BCM_SB2_TCAM_ATOMICITY_DISABLE(unit); 7533 rv = soc_mem_insert(unit, MP_GROUPm, MEM_BLOCK_ALL, &mp_group_entry); 7534 BCM_SB2_TCAM_ATOMICITY_ENABLE(unit); 7535 if (BCM_FAILURE(rv)) { 7536 LOG_ERROR(BSL_LS_BCM_OAM, 7537 (BSL_META_U(unit, 7538 "OAM(unit %d) Error: MP_GROUP table insert failed for " 7539 "EP=%d" " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 7540 L3_UNLOCK(unit); 7541 return (rv); 7542 } 7543 } 7544 if (up_mep == 0) { 7545 h_data_p->active_mdl_bitmap = mdl; 7546 } 7547 L3_UNLOCK(unit); 7548 return (BCM_E_NONE); 7549 } 7550 7551 /* 7552 * Function: 7553 * _bcm_sb2_oam_egr_mp_group_entry_set 7554 * Purpose: 7555 * Configure Egress MP group tables entry for local CCM Rx enabled endpoint. 7556 * Parameters: 7557 * unit - (IN) BCM device number 7558 * ep_info_p - (IN) Pointer to remote endpoint information. 7559 * ctr_index - (OUT) LM counter index 7560 * Retruns: 7561 * BCM_E_XXX 7562 */ 7563 STATIC int 7564 _bcm_sb2_oam_egr_mp_group_entry_set(int unit, 7565 bcm_oam_endpoint_info_t *ep_info_p, 7566 shr_idxres_element_t *ctr_index) 7567 { 7568 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 7569 int rv; /* Operation return status. */ 7570 uint8 mdl = 0; /* Maintenance domain level. */ 7571 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 7572 bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint info. */ 7573 soc_field_t mdl_field = 0; 7574 egr_mp_group_entry_t egr_mp_group; /* Egress MP group tbl entry buffer */ 7575 int up_mep = 0; /* Endpoint is an upMep */ 7576 int mp_grp_index = 0; 7577 7578 if (NULL == ep_info_p) { 7579 return (BCM_E_INTERNAL); 7580 } 7581 7582 /* Initialize local endpoint info pointer. */ 7583 ep_p = ep_info_p; 7584 7585 /* Lock already taken by the calling routine. */ 7586 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 7587 7588 /* Get endpoint hash data pointer. */ 7589 h_data_p = &oc->oam_hash_data[ep_p->id]; 7590 7591 if (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 7592 up_mep = 1; 7593 mdl_field = MDL_BITMAP_ACTIVEf; 7594 } else { 7595 if (MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) { 7596 /* For MPLS LM DM configure active */ 7597 mdl_field = MDL_BITMAP_ACTIVEf; 7598 } else { 7599 mdl_field = MDL_BITMAP_PASSIVEf; 7600 } 7601 } 7602 7603 sal_memset(&egr_mp_group, 0, sizeof(egr_mp_group_entry_t)); 7604 7605 /* form the key to search EGR_MP_GRUP table */ 7606 if (BCM_SUCCESS 7607 (_bcm_sb2_oam_find_egr_lmep(unit, h_data_p, 7608 &mp_grp_index, &egr_mp_group))) { 7609 7610 /* There's already an entry for this */ 7611 if (SAL_BOOT_BCMSIM) { 7612 /* Added as WAR for Cmodel issue */ 7613 /* Construct endpoint egress MP group Table entry search operation. */ 7614 _bcm_sb2_oam_egr_lmep_key_construct(unit, h_data_p, &egr_mp_group); 7615 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, VALIDf, 1); 7616 } 7617 mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, mdl_field); 7618 7619 /* If active bitmap is 0, so for first active endppoint in the mp_group 7620 * need to programme ma_base_ptr field during up_mep creation */ 7621 if((mdl == 0) && up_mep) { 7622 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, MA_BASE_PTRf, 7623 h_data_p->ma_base_index); 7624 } 7625 /* Passive demultiplexing should not be done on a MIP */ 7626 if (!((mdl_field == MDL_BITMAP_PASSIVEf) 7627 && (_BCM_OAM_EP_IS_MIP(h_data_p)))) { 7628 mdl |= (1 << ep_p->level); 7629 7630 /* Set all the bits till the highest configured MDL, so that there are 7631 no holes in the passive bitmap */ 7632 if (mdl_field == MDL_BITMAP_PASSIVEf) { 7633 mdl |= ((1 << ep_p->level) - 1); 7634 } 7635 } 7636 /* set MDL bitmap passive or active depending on up or down mep */ 7637 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, mdl_field, mdl); 7638 7639 soc_mem_lock(unit, EGR_MP_GROUPm); 7640 7641 rv = soc_mem_write(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL, 7642 mp_grp_index, &egr_mp_group); 7643 if (BCM_FAILURE(rv)) { 7644 soc_mem_unlock(unit, EGR_MP_GROUPm); 7645 return (rv); 7646 } 7647 soc_mem_unlock(unit, EGR_MP_GROUPm); 7648 } else { 7649 7650 /* This is the first entry at this */ 7651 sal_memset(&egr_mp_group, 0, sizeof(egr_mp_group_entry_t)); 7652 7653 /* Passive demultiplexing should not be done on a MIP */ 7654 if (!((mdl_field == MDL_BITMAP_PASSIVEf) 7655 && (_BCM_OAM_EP_IS_MIP(h_data_p)))) { 7656 mdl = (1 << ep_p->level); 7657 /* Set all the bits till the highest configured MDL, so that there are 7658 no holes in the passive bitmap */ 7659 if ( mdl_field == MDL_BITMAP_PASSIVEf && !(BHH_EP_TYPE(ep_info_p)) ) { 7660 mdl |= ((1 << ep_p->level) - 1); 7661 } 7662 } 7663 7664 if (mdl == 0) { 7665 /* MDL = 0 for case of MIP. Dont make the entry valid by 7666 programming other fields. */ 7667 return BCM_E_NONE; 7668 } 7669 7670 /* set MDL bitmap passive or active depending on up or down mep */ 7671 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, mdl_field, mdl); 7672 7673 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, MA_BASE_PTRf, 7674 h_data_p->ma_base_index); 7675 7676 /* Configure time stamp type 1588(PTP)/NTP */ 7677 soc_EGR_MP_GROUPm_field32_set(unit, &egr_mp_group, 7678 TIMESTAMP_TYPEf, 7679 ((ep_p->timestamp_format == bcmOAMTimestampFormatNTP) ? 1 : 0)); 7680 7681 h_data_p->ts_format = ep_p->timestamp_format; 7682 7683 /* Construct LMEP view key for L3 Table insert operation. */ 7684 _bcm_sb2_oam_egr_lmep_key_construct(unit, h_data_p, &egr_mp_group); 7685 7686 soc_mem_lock(unit, EGR_MP_GROUPm); 7687 7688 rv = soc_mem_insert(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL, &egr_mp_group); 7689 if (BCM_FAILURE(rv)) { 7690 soc_mem_unlock(unit, EGR_MP_GROUPm); 7691 return (rv); 7692 } 7693 soc_mem_unlock(unit, EGR_MP_GROUPm); 7694 } 7695 if (up_mep == 1) { 7696 h_data_p->active_mdl_bitmap = mdl; 7697 } 7698 return (BCM_E_NONE); 7699 } 7700 7701 STATIC int 7702 _bcm_sb2_oam_ma_idx_to_ep_id_mapping_op (int unit, 7703 _bcm_oam_hash_data_t *h_data_p, 7704 soc_mem_t mem, 7705 int delete) 7706 { 7707 uint32 mdl_value[1] = { 0 }; 7708 int bit_pos = 0; 7709 int current_offset = 0; 7710 int new_offset = 0; 7711 int entry_count = 0; 7712 shr_idxres_list_handle_t pool; 7713 bcm_oam_endpoint_t *temp_array = NULL; 7714 _bcm_oam_control_t *oc = NULL; 7715 int ma_base_index = _BCM_OAM_INVALID_INDEX; 7716 int is_upmep = 0; 7717 mp_group_entry_t mp_group_entry; /* LMEP view table entry. */ 7718 int mp_grp_index = -1; /* hardware index. */ 7719 egr_mp_group_entry_t egr_mp_group; /* Egress MP group tbl entry buffer */ 7720 int egr_mp_grp_index = -1; 7721 int stm_index = 0; 7722 source_trunk_map_table_entry_t stm_entry; 7723 uint8 port_mdl = 0; 7724 int rv = BCM_E_NONE; 7725 7726 if (NULL == h_data_p) { 7727 return (BCM_E_INTERNAL); 7728 } 7729 7730 /* Lock already taken by the calling routine. */ 7731 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 7732 7733 if (mem == MA_INDEXm) { 7734 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit, 7735 h_data_p, &entry_count, &pool)); 7736 } else { 7737 entry_count = 8; 7738 } 7739 7740 if (entry_count <= 0) { 7741 return BCM_E_INTERNAL; 7742 } 7743 7744 ma_base_index = h_data_p->ma_base_index; 7745 is_upmep = (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING)?1:0; 7746 7747 if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) { 7748 rv = _bcm_sb2_oam_find_port_lmep(unit, h_data_p, &stm_index, &stm_entry, &port_mdl); 7749 if (BCM_SUCCESS(rv)) { 7750 mdl_value[0] = port_mdl; 7751 } else { 7752 /* If app is not initialized (say rc), then during detach (delete) 7753 * we will not find the entry. simply return without error */ 7754 if ((delete) && (rv == BCM_E_NOT_FOUND) && !(oc->init)) { 7755 return BCM_E_NONE; 7756 } else { 7757 return BCM_E_INTERNAL; 7758 } 7759 } 7760 } else if (is_upmep) { 7761 rv = _bcm_sb2_oam_find_egr_lmep(unit, h_data_p, 7762 &egr_mp_grp_index, &egr_mp_group); 7763 if (BCM_SUCCESS(rv)) { 7764 mdl_value[0] = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, 7765 MDL_BITMAP_ACTIVEf); 7766 } else { 7767 /* If app is not initialized (say rc), then during detach (delete) 7768 * we will not find the entry. simply return without error */ 7769 if ((delete) && (rv == BCM_E_NOT_FOUND) && !(oc->init)) { 7770 return BCM_E_NONE; 7771 } else { 7772 return BCM_E_INTERNAL; 7773 } 7774 } 7775 } else { 7776 rv = _bcm_sb2_oam_find_lmep(unit, h_data_p, &mp_grp_index, &mp_group_entry); 7777 if (BCM_SUCCESS(rv)) { 7778 mdl_value[0] = soc_MP_GROUPm_field32_get(unit, &mp_group_entry, 7779 MDL_BITMAP_ACTIVEf); 7780 } else { 7781 /* If app is not initialized (say rc), then during detach (delete) 7782 * we will not find the entry. simply return without error */ 7783 if ((delete) && (rv == BCM_E_NOT_FOUND) && !(oc->init)) { 7784 return BCM_E_NONE; 7785 } else { 7786 return BCM_E_INTERNAL; 7787 } 7788 } 7789 } 7790 7791 _BCM_OAM_ALLOC(temp_array, bcm_oam_endpoint_t, 7792 sizeof(bcm_oam_endpoint_t) * entry_count, "endpoint id array"); 7793 if (NULL == temp_array) { 7794 return (BCM_E_MEMORY); 7795 } 7796 /* Initialize the entry buffer. */ 7797 sal_memset(temp_array, _BCM_OAM_INVALID_INDEX, sizeof(bcm_oam_endpoint_t) * entry_count); 7798 7799 7800 7801 if (delete) { 7802 for (bit_pos = 0; bit_pos <= 7; bit_pos++) { 7803 if (SHR_BITGET(mdl_value, bit_pos)) { 7804 if (bit_pos == h_data_p->level) { 7805 current_offset++; 7806 } else { 7807 temp_array[new_offset] = 7808 oc->_bcm_oam_ma_idx_to_ep_id_map 7809 [_BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX 7810 (ma_base_index, current_offset, is_upmep)]; 7811 new_offset++; 7812 current_offset++; 7813 } 7814 } 7815 } 7816 } else { 7817 for (bit_pos = 0; bit_pos <= 7; bit_pos++) { 7818 if (SHR_BITGET(mdl_value, bit_pos)) { 7819 if (bit_pos == h_data_p->level) { 7820 temp_array[new_offset] = h_data_p->ep_id; 7821 new_offset++; 7822 } else { 7823 temp_array[new_offset] = 7824 oc->_bcm_oam_ma_idx_to_ep_id_map[ 7825 _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX(ma_base_index, 7826 current_offset, is_upmep)]; 7827 new_offset++; 7828 current_offset++; 7829 } 7830 } 7831 } 7832 } 7833 7834 sal_memcpy(&(oc->_bcm_oam_ma_idx_to_ep_id_map[ 7835 _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_IDX 7836 (ma_base_index, 0, is_upmep)]), 7837 temp_array, sizeof(bcm_oam_endpoint_t) * entry_count); 7838 7839 sal_free(temp_array); 7840 return (BCM_E_NONE); 7841 } 7842 7843 STATIC int 7844 _bcm_sb2_oam_ma_idx_to_ep_id_mapping_add (int unit, 7845 _bcm_oam_hash_data_t *h_data_p) 7846 { 7847 int is_upmep = 0; 7848 int is_remote = 0; 7849 int is_rx_enabled = 0; 7850 soc_mem_t mem = MA_INDEXm; 7851 int rv = BCM_E_NONE; 7852 7853 /* h_data_p being NULL could already be some other error 7854 * scenario. Lets not return error for such a scenario. 7855 */ 7856 if (h_data_p == NULL) { 7857 return BCM_E_NONE; 7858 } 7859 7860 is_upmep = (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING)?1:0; 7861 if (is_upmep) { 7862 mem = EGR_MA_INDEXm; 7863 } 7864 is_remote = (h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE)?1:0; 7865 is_rx_enabled = (h_data_p->local_rx_enabled == 1) && (h_data_p->ma_base_index != _BCM_OAM_INVALID_INDEX); 7866 if (is_remote || !is_rx_enabled) { 7867 /* Dont touch anything for remote endpoints or only tx enabled */ 7868 return BCM_E_NONE; 7869 } 7870 rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_op(unit, h_data_p, mem, 0); 7871 return rv; 7872 } 7873 7874 STATIC int 7875 _bcm_sb2_oam_ma_idx_to_ep_id_mapping_delete (int unit, 7876 _bcm_oam_hash_data_t *h_data_p) 7877 { 7878 int is_upmep = 0; 7879 int is_remote = 0; 7880 int is_rx_enabled = 0; 7881 soc_mem_t mem = MA_INDEXm; 7882 int rv = BCM_E_NONE; 7883 7884 /* h_data_p being NULL could already be some other error 7885 * scenario. Lets not return error for such a scenario. 7886 */ 7887 if (h_data_p == NULL) { 7888 return BCM_E_NONE; 7889 } 7890 7891 is_upmep = (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING)?1:0; 7892 if (is_upmep) { 7893 mem = EGR_MA_INDEXm; 7894 } 7895 is_remote = (h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE)?1:0; 7896 is_rx_enabled = (h_data_p->local_rx_enabled == 1) && (h_data_p->ma_base_index != _BCM_OAM_INVALID_INDEX); 7897 if (is_remote || !is_rx_enabled) { 7898 /* Dont touch anything for remote endpoints or only tx enabled */ 7899 return BCM_E_NONE; 7900 } 7901 rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_op(unit, h_data_p, mem, 1); 7902 return rv; 7903 } 7904 7905 STATIC INLINE bcm_oam_endpoint_t 7906 _bcm_sb2_oam_ma_idx_to_ep_id_mapping_get (_bcm_oam_control_t *oc, int ma_idx) 7907 { 7908 return oc->_bcm_oam_ma_idx_to_ep_id_map[ma_idx]; 7909 } 7910 7911 STATIC int _bcm_sb2_oam_ma_idx_to_ep_id_mapping_init (int unit) 7912 { 7913 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 7914 7915 /* Lock already taken by the calling routine. */ 7916 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 7917 7918 _BCM_OAM_ALLOC(oc->_bcm_oam_ma_idx_to_ep_id_map, bcm_oam_endpoint_t, 7919 _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_TBL_SIZE , "MA_IDX_TO_EP_ID map"); 7920 7921 if (oc->_bcm_oam_ma_idx_to_ep_id_map == NULL) { 7922 return BCM_E_MEMORY; 7923 } 7924 7925 /* Init it to all invalid */ 7926 sal_memset(oc->_bcm_oam_ma_idx_to_ep_id_map, _BCM_OAM_INVALID_INDEX, 7927 _BCM_SB2_OAM_MA_IDX_TO_EP_ID_MAPPING_TBL_SIZE); 7928 return BCM_E_NONE; 7929 } 7930 7931 STATIC int _bcm_sb2_oam_ma_idx_to_ep_id_mapping_destroy (int unit) 7932 { 7933 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 7934 7935 /* Lock already taken by the calling routine. */ 7936 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 7937 7938 if (oc->_bcm_oam_ma_idx_to_ep_id_map != NULL) { 7939 sal_free(oc->_bcm_oam_ma_idx_to_ep_id_map); 7940 oc->_bcm_oam_ma_idx_to_ep_id_map = NULL; 7941 } 7942 7943 return BCM_E_NONE; 7944 } 7945 7946 7947 7948 STATIC int 7949 _bcm_sb2_oam_ma_index_entry_set(int unit, 7950 _bcm_oam_hash_data_t *h_data_p, 7951 soc_mem_t mem, 7952 void *ma_idx_ptr, int delete) 7953 { 7954 int rv = BCM_E_NONE; 7955 uint32 mdl_value[1] = { 0 }; 7956 int bit_pos = 0; 7957 int current_offset = 0; 7958 int new_offset = 0; 7959 int entry_count = 0; 7960 int entry_mem_size = 0; 7961 ma_index_entry_t *entry_buf; 7962 ma_index_entry_t *entry; 7963 ma_index_entry_t *entry_current; 7964 shr_idxres_list_handle_t pool; 7965 7966 if (NULL == h_data_p) { 7967 return (BCM_E_INTERNAL); 7968 } 7969 7970 if (mem == MA_INDEXm) { 7971 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit, 7972 h_data_p, &entry_count, &pool)); 7973 new_offset = entry_count; 7974 entry_mem_size = sizeof(ma_index_entry_t); 7975 } else { 7976 entry_mem_size = sizeof(egr_ma_index_entry_t); 7977 new_offset = entry_count = 8; 7978 } 7979 7980 if (entry_count <= 0) { 7981 return BCM_E_INTERNAL; 7982 } 7983 7984 /* Allocate buffer to store the DMAed table entries. */ 7985 entry_buf = soc_cm_salloc(unit, entry_mem_size * entry_count * 2, 7986 "MA index table entry buffer"); 7987 if (NULL == entry_buf) { 7988 return (BCM_E_MEMORY); 7989 } 7990 /* Initialize the entry buffer. */ 7991 sal_memset(entry_buf, 0, entry_mem_size * entry_count * 2); 7992 7993 /* Read the table entries into the buffer. */ 7994 rv = soc_mem_read_range(unit, mem, MEM_BLOCK_ALL, h_data_p->ma_base_index, 7995 (h_data_p->ma_base_index + entry_count - 1), 7996 entry_buf); 7997 if (BCM_FAILURE(rv)) { 7998 if (entry_buf) { 7999 soc_cm_sfree(unit, entry_buf); 8000 } 8001 return rv; 8002 } 8003 8004 mdl_value[0] = h_data_p->active_mdl_bitmap; 8005 8006 if (delete) { 8007 for (bit_pos = 0; bit_pos <= 7; bit_pos++) { 8008 if (SHR_BITGET(mdl_value, bit_pos)) { 8009 if (bit_pos == h_data_p->level) { 8010 current_offset++; 8011 } else { 8012 entry = soc_mem_table_idx_to_pointer(unit, mem, 8013 ma_index_entry_t *, 8014 entry_buf, new_offset); 8015 entry_current = soc_mem_table_idx_to_pointer(unit, mem, 8016 ma_index_entry_t *, 8017 entry_buf, current_offset); 8018 sal_memcpy(entry, entry_current, entry_mem_size); 8019 new_offset++; 8020 current_offset++; 8021 } 8022 } 8023 } 8024 } else { 8025 for (bit_pos = 0; bit_pos <= 7; bit_pos++) { 8026 if (SHR_BITGET(mdl_value, bit_pos)) { 8027 if (bit_pos == h_data_p->level) { 8028 entry = soc_mem_table_idx_to_pointer(unit, mem, 8029 ma_index_entry_t *, 8030 entry_buf, new_offset); 8031 sal_memcpy(entry, ma_idx_ptr, entry_mem_size); 8032 /* Doing Mod entry_count since new_offset starts 8033 from entry_count */ 8034 h_data_p->local_rx_index = h_data_p->ma_base_index + 8035 (new_offset%entry_count); 8036 new_offset++; 8037 } else { 8038 entry = soc_mem_table_idx_to_pointer(unit, mem, 8039 ma_index_entry_t *, 8040 entry_buf, new_offset); 8041 entry_current = soc_mem_table_idx_to_pointer(unit, mem, 8042 ma_index_entry_t *, 8043 entry_buf, current_offset); 8044 sal_memcpy(entry, entry_current, entry_mem_size); 8045 new_offset++; 8046 current_offset++; 8047 } 8048 } 8049 } 8050 } 8051 /* Move to the entry_count index since from there the newly programmed 8052 * ma_index table memory is present */ 8053 entry = soc_mem_table_idx_to_pointer(unit, mem, ma_index_entry_t *, 8054 entry_buf, entry_count); 8055 rv = soc_mem_write_range(unit, mem, MEM_BLOCK_ALL, h_data_p->ma_base_index, 8056 (h_data_p->ma_base_index + entry_count - 1), 8057 entry); 8058 if (BCM_FAILURE(rv)) { 8059 if (entry_buf) { 8060 soc_cm_sfree(unit, entry_buf); 8061 } 8062 return rv; 8063 } 8064 if (entry_buf) { 8065 soc_cm_sfree(unit, entry_buf); 8066 } 8067 return (BCM_E_NONE); 8068 } 8069 8070 STATIC int 8071 _bcm_sb2_oam_port_table_ma_index_offset_get(int unit, 8072 _bcm_oam_hash_data_t *h_data_p, 8073 int *ma_offset) 8074 { 8075 int rv = BCM_E_NONE; 8076 uint32 mdl_value[1] = { 0 }; 8077 int bit_pos = 0; 8078 bcm_port_t port_id; /* Port ID. */ 8079 int local_member_count = 0; 8080 port_tab_entry_t port_entry; 8081 int offset_found = 0; 8082 8083 if (NULL == h_data_p) { 8084 return (BCM_E_INTERNAL); 8085 } 8086 if(h_data_p->trunk_id != BCM_TRUNK_INVALID) { 8087 rv = _bcm_sb2_oam_trunk_port_mdl_config(unit, h_data_p); 8088 8089 /* Get a member of the trunk belonging to this module */ 8090 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 8091 h_data_p->trunk_id, 1, 8092 &port_id, 8093 &local_member_count))) { 8094 } else { 8095 return (BCM_E_INTERNAL); 8096 } 8097 BCM_IF_ERROR_RETURN 8098 (soc_mem_read(unit, PORT_TABm, 8099 MEM_BLOCK_ANY, port_id, &port_entry)); 8100 } else { 8101 BCM_IF_ERROR_RETURN 8102 (soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, 8103 h_data_p->src_pp_port, &port_entry)); 8104 } 8105 mdl_value[0] = soc_PORT_TABm_field32_get(unit, &port_entry, MDL_BITMAPf); 8106 for (bit_pos = 0; bit_pos <= 7; bit_pos++) { 8107 if (SHR_BITGET(mdl_value, bit_pos)) { 8108 if (bit_pos == h_data_p->level) { 8109 offset_found = 1; 8110 break; 8111 } else { 8112 *ma_offset += 1; 8113 } 8114 } 8115 } 8116 h_data_p->active_mdl_bitmap = mdl_value[0]; 8117 /* Added the line below to avoid compiler warning - unused variable */ 8118 mdl_value[0] = *ma_offset; 8119 if (offset_found == 0) { 8120 #if 0 8121 return (BCM_E_INTERNAL); 8122 #else 8123 8124 /* Workaround for now. */ 8125 return (BCM_E_NOT_FOUND); 8126 #endif 8127 } 8128 return rv; 8129 } 8130 8131 8132 STATIC int 8133 _bcm_sb2_oam_mp_grp_table_ma_index_offset_get(int unit, 8134 _bcm_oam_hash_data_t *h_data_p, 8135 int *ma_offset) 8136 { 8137 int rv = BCM_E_NONE; 8138 uint32 mdl_value[1] = { 0 }; 8139 int bit_pos = 0; 8140 soc_mem_t mem = 0; 8141 mp_group_entry_t mp_group_entry; /* Mp group entry buffer. */ 8142 int entry_index = 0; 8143 egr_mp_group_entry_t egr_mp_group; /* Egress MP group tbl entry buffer */ 8144 void *entry; 8145 soc_field_t mdl_field = 0; 8146 int offset_found = 0; 8147 8148 if (NULL == h_data_p) { 8149 return (BCM_E_INTERNAL); 8150 } 8151 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 8152 mem = EGR_MP_GROUPm; 8153 mdl_field = MDL_BITMAP_ACTIVEf; 8154 entry = &egr_mp_group; 8155 if (BCM_FAILURE(_bcm_sb2_oam_find_egr_lmep(unit, h_data_p, 8156 &entry_index, 8157 &egr_mp_group))) { 8158 LOG_ERROR(BSL_LS_BCM_OAM, 8159 (BSL_META_U(unit, 8160 "OAM(unit %d) Error: EGR MP group tbl entry not found-%s.\n"), 8161 unit, bcm_errmsg(rv))); 8162 return rv; 8163 } 8164 } else { 8165 mem = MP_GROUPm; 8166 mdl_field = MDL_BITMAP_ACTIVEf; 8167 entry = &mp_group_entry; 8168 rv = _bcm_sb2_oam_find_lmep(unit, h_data_p, &entry_index, &mp_group_entry); 8169 if (rv != BCM_E_NONE) { 8170 /* If not found then it's a harm-less error. Treat it as not a error.*/ 8171 if (BCM_E_NOT_FOUND == rv) { 8172 LOG_VERBOSE(BSL_LS_BCM_OAM, 8173 (BSL_META_U(unit, 8174 "OAM(unit %d) Error: MP group tbl entry not found - %s.\n"), 8175 unit, bcm_errmsg(rv))); 8176 } else { 8177 LOG_ERROR(BSL_LS_BCM_OAM, 8178 (BSL_META_U(unit, 8179 "OAM(unit %d) Error: MP group tbl entry not found - %s.\n"), 8180 unit, bcm_errmsg(rv))); 8181 } 8182 return rv; 8183 } 8184 } 8185 mdl_value[0] = soc_mem_field32_get(unit, mem, entry, mdl_field); 8186 *ma_offset = 0; 8187 for (bit_pos = 0; bit_pos <= 7; bit_pos++) { 8188 if (SHR_BITGET(mdl_value, bit_pos)) { 8189 if (bit_pos == h_data_p->level) { 8190 offset_found = 1; 8191 break; 8192 } else { 8193 *ma_offset += 1; 8194 } 8195 } 8196 } 8197 h_data_p->active_mdl_bitmap = mdl_value[0]; 8198 if (offset_found == 0) { 8199 return (BCM_E_INTERNAL); 8200 } 8201 return rv; 8202 } 8203 8204 8205 STATIC int 8206 _bcm_sb2_oam_ma_index_offset_get(int unit, _bcm_oam_hash_data_t *h_data_p, 8207 int *ma_offset) 8208 { 8209 int rv = BCM_E_NONE; 8210 if (NULL == h_data_p) { 8211 return (BCM_E_INTERNAL); 8212 } 8213 if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) { 8214 rv = _bcm_sb2_oam_port_table_ma_index_offset_get(unit, h_data_p, 8215 ma_offset); 8216 /* BCM_E_NOT_FOUND is not an error when switch is re-initializing 8217 as entry would have been already deleted by port module init */ 8218 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 8219 LOG_ERROR(BSL_LS_BCM_OAM, 8220 (BSL_META_U(unit, 8221 "OAM(unit %d) Error: Port table read failed - %s.\n"), 8222 unit, bcm_errmsg(rv))); 8223 return rv; 8224 } 8225 } else { 8226 rv = _bcm_sb2_oam_mp_grp_table_ma_index_offset_get(unit, h_data_p, 8227 ma_offset); 8228 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 8229 LOG_ERROR(BSL_LS_BCM_OAM, 8230 (BSL_META_U(unit, 8231 "OAM(unit %d) Error: MP group table read failed - %s.\n"), 8232 unit, bcm_errmsg(rv))); 8233 return rv; 8234 } 8235 } 8236 return (BCM_E_NONE); 8237 } 8238 /* 8239 * Function: 8240 * _bcm_sb2_oam_local_rx_mep_hw_set 8241 * Purpose: 8242 * Configure hardware tables for a local CCM Rx enabled endpoint. 8243 * Parameters: 8244 * unit - (IN) BCM device number 8245 * ep_info_p - (IN) Pointer to remote endpoint information. 8246 * Retruns: 8247 * BCM_E_XXX 8248 */ 8249 STATIC int 8250 _bcm_sb2_oam_local_rx_mep_hw_set(int unit, 8251 bcm_oam_endpoint_info_t *ep_info_p) 8252 { 8253 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 8254 ma_index_entry_t ma_idx_entry; /* MA_INDEX table entry buffer. */ 8255 egr_ma_index_entry_t egr_ma_idx_entry; /* EGR_MA_INDEX table entry buffer*/ 8256 oam_opcode_control_profile_entry_t *opcode_entry = NULL; /* Opcode control 8257 profile entry. */ 8258 egr_oam_opcode_control_profile_entry_t *egr_opcode_entry = NULL; /* Egress 8259 Opcode control profile entry*/ 8260 void *entries[1]; /* Pointer to opcode control entry. */ 8261 uint32 profile_index = 0; /* opcode control profile index. */ 8262 int rv; /* Operation return status. */ 8263 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 8264 bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint info. */ 8265 soc_mem_t opcode_profile_mem = 0; 8266 soc_mem_t ma_index_mem = 0; 8267 shr_idxres_element_t egr_ctr_index = 0; 8268 soc_profile_mem_t *opcode_control_profile; /* profile to be used 8269 ingress or egress */ 8270 void *ma_idx_ptr; 8271 void *opcode_profile_entry; 8272 8273 8274 if (NULL == ep_info_p) { 8275 return (BCM_E_INTERNAL); 8276 } 8277 8278 /* Initialize local endpoint info pointer. */ 8279 ep_p = ep_info_p; 8280 8281 /* Lock already taken by the calling routine. */ 8282 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 8283 8284 /* Get endpoint hash data pointer. */ 8285 h_data_p = &oc->oam_hash_data[ep_p->id]; 8286 if ( 0 == h_data_p->in_use) { 8287 return (BCM_E_INTERNAL); 8288 } 8289 8290 if (ep_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 8291 opcode_profile_mem = EGR_OAM_OPCODE_CONTROL_PROFILEm; 8292 opcode_control_profile = &oc->egr_oam_opcode_control_profile; 8293 ma_index_mem = EGR_MA_INDEXm; 8294 ma_idx_ptr = &egr_ma_idx_entry; 8295 egr_opcode_entry = sal_alloc(_BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE, 8296 "egr opcode profile"); 8297 if(!egr_opcode_entry) 8298 { 8299 return BCM_E_MEMORY; 8300 } 8301 opcode_profile_entry = egr_opcode_entry; 8302 /* Clear the entry data. */ 8303 sal_memset(egr_opcode_entry, 0, 8304 _BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE); 8305 sal_memset(&egr_ma_idx_entry, 0, sizeof(egr_ma_index_entry_t)); 8306 } else { 8307 opcode_profile_mem = OAM_OPCODE_CONTROL_PROFILEm; 8308 opcode_control_profile = &oc->oam_opcode_control_profile; 8309 ma_index_mem = MA_INDEXm; 8310 ma_idx_ptr = &ma_idx_entry; 8311 opcode_entry = sal_alloc(_BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE, 8312 "opcode profile"); 8313 if(!opcode_entry) 8314 { 8315 return BCM_E_MEMORY; 8316 } 8317 opcode_profile_entry = opcode_entry; 8318 /* Clear the entry data. */ 8319 sal_memset(opcode_entry, 0, 8320 _BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE); 8321 sal_memset(&ma_idx_entry, 0, sizeof(ma_index_entry_t)); 8322 } 8323 8324 /* Construct the opcode control profile table entry. */ 8325 if (ep_p->opcode_flags & _BCM_SB2_OAM_OPCODE_MASK) { 8326 /* Use application specified opcode control settings. */ 8327 rv = _bcm_sb2_oam_opcode_profile_entry_set(unit, h_data_p, opcode_profile_mem, 8328 ep_p->opcode_flags, 8329 opcode_profile_entry); 8330 if (BCM_FAILURE(rv)) { 8331 LOG_ERROR(BSL_LS_BCM_OAM, 8332 (BSL_META_U(unit, 8333 "OAM(unit %d) Error: Opcode profile set failed for EP=%d" 8334 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 8335 if(egr_opcode_entry) { 8336 sal_free(egr_opcode_entry); 8337 } 8338 if(opcode_entry) { 8339 sal_free(opcode_entry); 8340 } 8341 return (rv); 8342 } 8343 } else { 8344 /* Use default opcode control profile settings. */ 8345 if (_BCM_OAM_EP_IS_MIP(h_data_p)) { 8346 rv = _bcm_sb2_oam_mip_opcode_profile_entry_init(unit, opcode_profile_mem, 8347 opcode_profile_entry); 8348 } else { 8349 rv = _bcm_sb2_oam_opcode_profile_entry_init(unit, opcode_profile_mem, 8350 opcode_profile_entry); 8351 } 8352 if (BCM_FAILURE(rv)) { 8353 LOG_ERROR(BSL_LS_BCM_OAM, 8354 (BSL_META_U(unit, 8355 "OAM(unit %d) Error: Opcode profile init failed for EP=%d" 8356 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 8357 if(egr_opcode_entry) { 8358 sal_free(egr_opcode_entry); 8359 } 8360 if(opcode_entry) { 8361 sal_free(opcode_entry); 8362 } 8363 return (rv); 8364 } 8365 } 8366 8367 soc_mem_lock(unit, opcode_profile_mem); 8368 /* Add entry to profile table. */ 8369 entries[0] = opcode_profile_entry; 8370 8371 rv = soc_profile_mem_add(unit, opcode_control_profile, 8372 (void *)entries, 8373 _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE, &profile_index); 8374 if (BCM_FAILURE(rv)) { 8375 LOG_ERROR(BSL_LS_BCM_OAM, 8376 (BSL_META_U(unit, 8377 "OAM(unit %d) Error: Opcode profile add failed for EP=%d" 8378 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 8379 /* Release opcode control profile table lock. */ 8380 soc_mem_unlock(unit, opcode_profile_mem); 8381 if(egr_opcode_entry) { 8382 sal_free(egr_opcode_entry); 8383 } 8384 if(opcode_entry) { 8385 sal_free(opcode_entry); 8386 } 8387 return (rv); 8388 } 8389 8390 /* Store endpoint OAM opcode profile table index value. */ 8391 h_data_p->profile_index = 8392 _BCM_SB2_OAM_GET_PROFILE_PTR_FROM_INDEX(profile_index); 8393 8394 /* Release opcode control profile table lock. */ 8395 soc_mem_unlock(unit, opcode_profile_mem); 8396 8397 if(egr_opcode_entry) { 8398 sal_free(egr_opcode_entry); 8399 } 8400 if(opcode_entry) { 8401 sal_free(opcode_entry); 8402 } 8403 8404 /* 8405 * MA_INDEX table programming. 8406 */ 8407 8408 8409 /* Set group index value. */ 8410 /* In case of BHH this needs to be the session Index */ 8411 #if defined(INCLUDE_BHH) 8412 if ( BHH_EP_TYPE(ep_p) ) { 8413 soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr, MA_PTRf, 8414 BCM_OAM_BHH_GET_UKERNEL_EP(ep_p->id)); 8415 } else 8416 #endif 8417 { 8418 8419 soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr, MA_PTRf, 8420 ep_p->group); 8421 } 8422 8423 8424 8425 /* Set OAM opcode control profile table index. */ 8426 soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr, 8427 OAM_OPCODE_CONTROL_PROFILE_PTRf, 8428 h_data_p->profile_index); 8429 8430 /* Set CPU CoS queue value. */ 8431 soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr, 8432 INT_PRIf, 8433 ep_p->int_pri); 8434 #if defined (BCM_METROLITE_SUPPORT) 8435 if(SOC_IS_METROLITE(unit)) { 8436 h_data_p->lm_count_profile = ep_p->lm_count_profile; 8437 8438 /* Set LM count profile index for the endpoint */ 8439 soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr, 8440 OAM_COUNT_PROFILEf, 8441 h_data_p->lm_count_profile); 8442 } 8443 #endif 8444 /* If the OAM domain is port, set source trunk map table */ 8445 if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) { 8446 rv = _bcm_sb2_port_domain_oam_hw_set(unit, ep_info_p); 8447 if (BCM_FAILURE(rv)) { 8448 LOG_ERROR(BSL_LS_BCM_OAM, 8449 (BSL_META_U(unit, 8450 "OAM(unit %d) Error: port OAM config failed for EP=%d" 8451 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 8452 return (rv); 8453 } 8454 } else { 8455 rv = _bcm_sb2_oam_ing_mp_group_entry_set(unit, ep_info_p); 8456 if (BCM_FAILURE(rv)) { 8457 LOG_ERROR(BSL_LS_BCM_OAM, 8458 (BSL_META_U(unit, 8459 "OAM(unit %d) Error: L3 entry config failed for EP=%d" 8460 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 8461 return (rv); 8462 } 8463 rv = _bcm_sb2_oam_egr_mp_group_entry_set(unit, ep_info_p, 8464 &egr_ctr_index); 8465 if (BCM_FAILURE(rv)) { 8466 LOG_ERROR(BSL_LS_BCM_OAM, 8467 (BSL_META_U(unit, 8468 "OAM(unit %d) Error: Egress MP group entry config " 8469 "failed for EP=%d %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 8470 return (rv); 8471 } 8472 8473 if ((ep_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) { 8474 rv = _bcm_sb2_oam_lmep_counters_set(unit, ep_info_p); 8475 if (BCM_FAILURE(rv)) { 8476 LOG_ERROR(BSL_LS_BCM_OAM, 8477 (BSL_META_U(unit, 8478 "OAM(unit %d) Error: Counter config failed for EP=%d" 8479 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 8480 if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) { 8481 rv = shr_aidxres_list_free(oc->ing_lm_ctr_pool[ 8482 (h_data_p->rx_ctr >> 24)], 8483 (h_data_p->rx_ctr & 0xffffff)); 8484 _bcm_sb2_oam_lm_counters_hw_values_reset(unit, h_data_p->rx_ctr >> 24, 8485 h_data_p->rx_ctr & 0xffffff); 8486 if (BCM_FAILURE(rv)) { 8487 LOG_ERROR(BSL_LS_BCM_OAM, 8488 (BSL_META_U(unit, 8489 "OAM(unit %d) Error: Ing LM counter block " 8490 "free failed (EP=%d) - %s.\n"), 8491 unit, ep_info_p->id, bcm_errmsg(rv))); 8492 return (rv); 8493 } 8494 } 8495 return (rv); 8496 } 8497 } else { 8498 /* If loss measurement is not configured, set it to invalid */ 8499 ep_info_p->lm_counter_base_id = _BCM_OAM_LM_COUNTER_IDX_INVALID; 8500 } 8501 } 8502 rv = _bcm_sb2_oam_ma_index_entry_set(unit, h_data_p, 8503 ma_index_mem, ma_idx_ptr, 0); 8504 if (BCM_FAILURE(rv)) { 8505 LOG_ERROR(BSL_LS_BCM_OAM, 8506 (BSL_META_U(unit, 8507 "OAM(unit %d) Error: MA_INDEX table write failed for EP=%d" 8508 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 8509 return (rv); 8510 } 8511 return rv; 8512 } 8513 8514 /* 8515 * Function: 8516 * _bcm_sb2_oam_upmep_rx_endpoint_reserve 8517 * Purpose: 8518 * Reserve an hardware index in the group state table to maintain the state 8519 * for a CCM Rx enabled endpoint. 8520 * Parameters: 8521 * unit - (IN) BCM device number 8522 * ep_info_p - (IN) Pointer to remote endpoint information. 8523 * Retruns: 8524 * BCM_E_XXX 8525 */ 8526 STATIC int 8527 _bcm_sb2_oam_upmep_rx_endpoint_reserve(int unit, 8528 const bcm_oam_endpoint_info_t *ep_info_p) 8529 { 8530 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 8531 int rv; /* Operation return status. */ 8532 egr_mp_group_entry_t egr_mp_grp_entry; /* egress mp group entry buffer. */ 8533 int mp_group_index = -1;/*MP group entry hardware index*/ 8534 int count = 0; /* Successful Hw indices allocated. */ 8535 uint8 mdl = 0; /* Maintenance domain level. */ 8536 uint32 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0}; 8537 /* Endpoint Rx hardware index. */ 8538 uint16 ma_base_idx; /* Base pointer to endpoint state */ 8539 /* table [MA_INDEX = (BASE + MDL)]. */ 8540 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 8541 const bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint information. */ 8542 8543 if (NULL == ep_info_p) { 8544 return (BCM_E_INTERNAL); 8545 } 8546 8547 /* Lock already taken by the calling routine. */ 8548 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 8549 8550 /* Initialize local endpoint information pointer. */ 8551 ep_p = ep_info_p; 8552 8553 /* Get endpoint hash data pointer. */ 8554 h_data_p = &oc->oam_hash_data[ep_p->id]; 8555 if (0 == h_data_p->in_use) { 8556 return(BCM_E_INTERNAL); 8557 } 8558 8559 /* Initialize egress MP group table entry buffer. */ 8560 sal_memset(&egr_mp_grp_entry, 0, sizeof(egr_mp_group_entry_t)); 8561 8562 /* Find out if a matching entry already installed in hardware table. */ 8563 rv = _bcm_sb2_oam_find_egr_lmep(unit, h_data_p, &mp_group_index, 8564 &egr_mp_grp_entry); 8565 if (BCM_FAILURE(rv)) { 8566 /* 8567 * If NO match found, allocate a new hardware index from EGR_MA_INDEX 8568 * pool. 8569 */ 8570 8571 /* 8572 * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA 8573 * group endpoints. While allocating the base index, next 7 hardware 8574 * indices are also reserved. 8575 */ 8576 rv = shr_idxres_list_alloc_set(oc->egr_ma_idx_pool, 8, 8577 (shr_idxres_element_t *) rx_index, 8578 (shr_idxres_element_t *) &count); 8579 if (BCM_FAILURE(rv)) { 8580 LOG_ERROR(BSL_LS_BCM_OAM, 8581 (BSL_META_U(unit, 8582 "OAM(unit %d) Error: EGR MA_INDEX index alloc failed EP:%d" 8583 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 8584 return (rv); 8585 } else { 8586 LOG_DEBUG(BSL_LS_BCM_OAM, 8587 (BSL_META_U(unit, 8588 "OAM(unit %d) Info: Egr MA_INDEX alloc for EP:%d success" 8589 " rx_idx_base:%d alloc-count:%d.\n"), unit, ep_p->id, 8590 rx_index[0], count)); 8591 h_data_p->ma_base_index = rx_index[0]; 8592 } 8593 8594 } else if (BCM_SUCCESS(rv)) { 8595 8596 /* Matching entry found, get installed entry MDL value. */ 8597 mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_grp_entry, 8598 MDL_BITMAP_ACTIVEf); 8599 8600 if (mdl == 0) { 8601 /* This is the first one in the active bitmap. 8602 Allocate the hw indexes. */ 8603 /* 8604 * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA 8605 * group endpoints. While allocating the base index, next 7 hardware 8606 * indices are also reserved. 8607 */ 8608 rv = shr_idxres_list_alloc_set(oc->egr_ma_idx_pool, 8, 8609 (shr_idxres_element_t *) rx_index, 8610 (shr_idxres_element_t *) &count); 8611 if (BCM_FAILURE(rv)) { 8612 LOG_ERROR(BSL_LS_BCM_OAM, 8613 (BSL_META_U(unit, 8614 "OAM(unit %d) Error: EGR MA_INDEX index alloc failed EP:%d" 8615 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 8616 return (rv); 8617 } else { 8618 LOG_DEBUG(BSL_LS_BCM_OAM, 8619 (BSL_META_U(unit, 8620 "OAM(unit %d) Info: Egr MA_INDEX alloc for EP:%d success" 8621 " rx_idx_base:%d alloc-count:%d.\n"), unit, ep_p->id, 8622 rx_index[0], count)); 8623 h_data_p->ma_base_index = rx_index[0]; 8624 } 8625 } else if (0 == (mdl & (1 << ep_p->level))) { /* Findout if MDLs are same. */ 8626 ma_base_idx = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_grp_entry, 8627 MA_BASE_PTRf); 8628 h_data_p->ma_base_index = ma_base_idx; 8629 } else { 8630 /* Rx index already taken return error. */ 8631 LOG_ERROR(BSL_LS_BCM_OAM, 8632 (BSL_META_U(unit, 8633 "OAM(unit %d) Error: No free Rx index found for EP:%d" 8634 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 8635 return (BCM_E_RESOURCE); 8636 } 8637 } 8638 return (rv); 8639 } 8640 8641 /* 8642 * Function: 8643 * _bcm_sb2_oam_downmep_rx_endpoint_reserve 8644 * Purpose: 8645 * Reserve an hardware index in the group state table to maintain the state 8646 * for a CCM Rx enabled endpoint. 8647 * Parameters: 8648 * unit - (IN) BCM device number 8649 * ep_info_p - (IN) Pointer to remote endpoint information. 8650 * Retruns: 8651 * BCM_E_XXX 8652 */ 8653 STATIC int 8654 _bcm_sb2_oam_downmep_rx_endpoint_reserve(int unit, 8655 const bcm_oam_endpoint_info_t *ep_info_p) 8656 { 8657 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 8658 int rv; /* Operation return status. */ 8659 mp_group_entry_t mp_group_entry; /* MP Group entry buffer. */ 8660 int entry_index = -1; /* MP group entry hardware index.*/ 8661 int count = 0; /* Successful Hw indices allocated. */ 8662 uint8 mdl = 0; /* Maintenance domain level. */ 8663 int rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0}; 8664 /* Endpoint Rx hardware index. */ 8665 uint16 ma_base_idx; /* Base pointer to endpoint state */ 8666 /* table [MA_INDEX = (BASE + MDL)]. */ 8667 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 8668 const bcm_oam_endpoint_info_t *ep_p; /* Pointer to endpoint information. */ 8669 int stm_index = 0; 8670 source_trunk_map_table_entry_t stm_entry; 8671 int ma_idx_entry_count = 0; 8672 shr_idxres_list_handle_t pool = NULL; 8673 8674 if (NULL == ep_info_p) { 8675 return (BCM_E_INTERNAL); 8676 } 8677 8678 /* Lock already taken by the calling routine. */ 8679 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 8680 8681 /* Initialize local endpoint information pointer. */ 8682 ep_p = ep_info_p; 8683 8684 /* Get endpoint hash data pointer. */ 8685 h_data_p = &oc->oam_hash_data[ep_p->id]; 8686 if ( 0 == h_data_p->in_use) { 8687 return (BCM_E_INTERNAL); 8688 } 8689 8690 /* Initialize MP group entry buffer. */ 8691 sal_memset(&mp_group_entry, 0, sizeof(mp_group_entry_t)); 8692 sal_memset(&stm_entry, 0, sizeof(source_trunk_map_table_entry_t)); 8693 8694 if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) { 8695 rv = _bcm_sb2_oam_find_port_lmep(unit, h_data_p, &stm_index, &stm_entry, &mdl); 8696 } else { 8697 /* Find out if a matching entry already installed in hardware table. */ 8698 rv = _bcm_sb2_oam_find_lmep(unit, h_data_p, &entry_index, &mp_group_entry); 8699 } 8700 if (BCM_FAILURE(rv)) { 8701 /* 8702 * If NO match found, allocate a new hardware index from MA_INDEX 8703 * pool. 8704 */ 8705 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p, 8706 &ma_idx_entry_count, &pool)); 8707 /* 8708 * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA 8709 * group endpoints. While allocating the base index, next 7 hardware 8710 * indices are also reserved. 8711 */ 8712 rv = shr_idxres_list_alloc_set(pool, ma_idx_entry_count, 8713 (shr_idxres_element_t *) rx_index, 8714 (shr_idxres_element_t *) &count); 8715 8716 if (BCM_FAILURE(rv)) { 8717 LOG_ERROR(BSL_LS_BCM_OAM, 8718 (BSL_META_U(unit, 8719 "OAM(unit %d) Error: MA_INDEX index alloc failed EP:%d" 8720 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 8721 return (rv); 8722 } else { 8723 LOG_DEBUG(BSL_LS_BCM_OAM, 8724 (BSL_META_U(unit, 8725 "OAM(unit %d) Info: MA_INDEX alloc for EP:%d success." 8726 " rx_idx_base:%d alloc-count:%d.\n"), unit, ep_p->id, 8727 rx_index[0], count)); 8728 } 8729 8730 h_data_p->ma_base_index = rx_index[0]; 8731 } else if (BCM_SUCCESS(rv)) { 8732 if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) { 8733 /* MDL already found.*/ 8734 /* Findout if MDLs are same. */ 8735 if (0 == (mdl & (1 << ep_p->level))) { 8736 ma_base_idx = 8737 soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm_entry, 8738 MA_BASE_PTRf); 8739 h_data_p->ma_base_index = ma_base_idx; 8740 } else { 8741 /* Rx index already taken return error. */ 8742 LOG_ERROR(BSL_LS_BCM_OAM, 8743 (BSL_META_U(unit, 8744 "OAM Error: No free Rx index found for EP:%d" 8745 " %s.\n"), ep_p->id, bcm_errmsg(rv))); 8746 return (BCM_E_RESOURCE); 8747 } 8748 } else { 8749 /* Matching entry found, get installed entry MDL value. */ 8750 mdl = soc_MP_GROUPm_field32_get(unit, &mp_group_entry, 8751 MDL_BITMAP_ACTIVEf); 8752 8753 if (mdl == 0) { 8754 /* This is the first one in the active bitmap. 8755 Allocate the hw indexes. */ 8756 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p, 8757 &ma_idx_entry_count, &pool)); 8758 /* 8759 * Endpoint MDL values can be (0-7) i.e 8 MDLs are supported per-MA 8760 * group endpoints. While allocating the base index, next 7 hardware 8761 * indices are also reserved. 8762 */ 8763 rv = shr_idxres_list_alloc_set(pool, ma_idx_entry_count, 8764 (shr_idxres_element_t *) rx_index, 8765 (shr_idxres_element_t *) &count); 8766 8767 if (BCM_FAILURE(rv)) { 8768 LOG_ERROR(BSL_LS_BCM_OAM, 8769 (BSL_META_U(unit, 8770 "OAM(unit %d) Error: MA_INDEX index alloc failed EP:%d" 8771 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 8772 return (rv); 8773 } else { 8774 LOG_DEBUG(BSL_LS_BCM_OAM, 8775 (BSL_META_U(unit, 8776 "OAM(unit %d) Info: MA_INDEX alloc for EP:%d success." 8777 " rx_idx_base:%d alloc-count:%d.\n"), unit, ep_p->id, 8778 rx_index[0], count)); 8779 } 8780 8781 h_data_p->ma_base_index = rx_index[0]; 8782 } else if (0 == (mdl & (1 << ep_p->level))) {/* Findout if MDLs are same. */ 8783 ma_base_idx = soc_MP_GROUPm_field32_get(unit, &mp_group_entry, 8784 MA_BASE_PTRf); 8785 h_data_p->ma_base_index = ma_base_idx; 8786 } else { 8787 /* Rx index already taken return error. */ 8788 LOG_ERROR(BSL_LS_BCM_OAM, 8789 (BSL_META_U(unit, 8790 "OAM(unit %d) Error: No free Rx index found for EP:%d" 8791 " %s.\n"), unit, ep_p->id, bcm_errmsg(rv))); 8792 return (BCM_E_RESOURCE); 8793 } 8794 } 8795 } 8796 8797 return (rv); 8798 } 8799 8800 /* 8801 * Function: 8802 * _bcm_sb2_oam_remote_endpoint_delete 8803 * Purpose: 8804 * Delete a remote endpoint. 8805 * Parameters: 8806 * unit - (IN) BCM device number 8807 * h_data_p - (IN) Pointer to endpoint hash data 8808 * Retruns: 8809 * BCM_E_XXX 8810 */ 8811 STATIC int 8812 _bcm_sb2_oam_remote_endpoint_delete(int unit, 8813 _bcm_oam_hash_data_t *h_data_p) 8814 { 8815 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 8816 l3_entry_1_entry_t l3_entry; /* RMEP view table entry. */ 8817 ma_state_entry_t ma_state_entry; /* Group state machine table entry. */ 8818 rmep_entry_t rmep_entry; /* Remote endpoint table entry. */ 8819 int rv; /* Operation return status. */ 8820 uint32 some_rmep_ccm_defect_counter = 0; /* No. of RMEPs in MA with CCM */ 8821 /* defects. */ 8822 uint32 some_rdi_defect_counter = 0; /* No. of RMEPs in MA with RDI */ 8823 /* defects. */ 8824 uint32 cur_some_rdi_defect = 0; /* Any RMEP in MA with RDI defect. */ 8825 uint32 cur_some_rmep_ccm_defect = 0; /* Any RMEP in MA with CCM defect. */ 8826 uint32 cur_rmep_ccm_defect = 0; /* RMEP lookup failed or CCM */ 8827 /* interval mismatch. */ 8828 uint32 cur_rmep_last_rdi = 0; /* Last CCM RDI Rx from this RMEP. */ 8829 uint32 first, last, validLow, validHigh, freeCount, allocCount; 8830 8831 8832 if(MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 8833 return BCM_E_INTERNAL; 8834 } 8835 8836 /* Lock already taken by the calling routine. */ 8837 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 8838 8839 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 8840 8841 /* Get remote endpoint entry value from hardware. */ 8842 rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index, &rmep_entry); 8843 if (BCM_FAILURE(rv)) { 8844 LOG_ERROR(BSL_LS_BCM_OAM, 8845 (BSL_META_U(unit, 8846 "OAM(unit %d) Error: RMEP table read failed for EP=%d" 8847 "%s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 8848 return (rv); 8849 } 8850 8851 cur_rmep_ccm_defect 8852 = soc_RMEPm_field32_get(unit, &rmep_entry, 8853 CURRENT_RMEP_CCM_DEFECTf); 8854 8855 cur_rmep_last_rdi 8856 = soc_RMEPm_field32_get(unit, &rmep_entry, 8857 CURRENT_RMEP_LAST_RDIf); 8858 8859 sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry)); 8860 rv = READ_MA_STATEm(unit, MEM_BLOCK_ANY, h_data_p->group_index, 8861 &ma_state_entry); 8862 if (BCM_FAILURE(rv)) { 8863 LOG_ERROR(BSL_LS_BCM_OAM, 8864 (BSL_META_U(unit, 8865 "OAM Error: Group state (GID=%d) table read" 8866 " failed - %s.\n"), h_data_p->ep_id, bcm_errmsg(rv))); 8867 return (rv); 8868 } 8869 8870 if ((0 != cur_rmep_ccm_defect) || (0 != cur_rmep_last_rdi)) { 8871 some_rmep_ccm_defect_counter 8872 = soc_MA_STATEm_field32_get(unit, &ma_state_entry, 8873 SOME_RMEP_CCM_DEFECT_COUNTERf); 8874 cur_some_rmep_ccm_defect 8875 = soc_MA_STATEm_field32_get(unit, &ma_state_entry, 8876 CURRENT_SOME_RMEP_CCM_DEFECTf); 8877 8878 if ((0 != cur_rmep_ccm_defect) 8879 && (some_rmep_ccm_defect_counter > 0)) { 8880 --some_rmep_ccm_defect_counter; 8881 soc_MA_STATEm_field32_set 8882 (unit, &ma_state_entry, SOME_RMEP_CCM_DEFECT_COUNTERf, 8883 some_rmep_ccm_defect_counter); 8884 8885 if (0 == some_rmep_ccm_defect_counter) { 8886 cur_some_rmep_ccm_defect = 0; 8887 soc_MA_STATEm_field32_set 8888 (unit, &ma_state_entry, CURRENT_SOME_RMEP_CCM_DEFECTf, 8889 cur_some_rmep_ccm_defect); 8890 } 8891 } 8892 8893 some_rdi_defect_counter 8894 = soc_MA_STATEm_field32_get(unit, &ma_state_entry, 8895 SOME_RDI_DEFECT_COUNTERf); 8896 cur_some_rdi_defect 8897 = soc_MA_STATEm_field32_get(unit, &ma_state_entry, 8898 CURRENT_SOME_RDI_DEFECTf); 8899 8900 if ((0 != cur_rmep_last_rdi) 8901 && (some_rdi_defect_counter > 0)) { 8902 --some_rdi_defect_counter; 8903 soc_MA_STATEm_field32_set 8904 (unit, &ma_state_entry, SOME_RDI_DEFECT_COUNTERf, 8905 some_rdi_defect_counter); 8906 8907 if (0 == some_rdi_defect_counter) { 8908 cur_some_rdi_defect = 0; 8909 soc_MA_STATEm_field32_set 8910 (unit, &ma_state_entry, CURRENT_SOME_RDI_DEFECTf, 8911 cur_some_rdi_defect); 8912 } 8913 } 8914 8915 rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, h_data_p->group_index, 8916 &ma_state_entry); 8917 if (BCM_FAILURE(rv)) { 8918 LOG_ERROR(BSL_LS_BCM_OAM, 8919 (BSL_META_U(unit, 8920 "OAM(unit %d) Error: Group state (GID=%d) table write" 8921 " failed - %s.\n"), unit, h_data_p->group_index, 8922 bcm_errmsg(rv))); 8923 return (rv); 8924 } 8925 } 8926 8927 /* Clear RMEP table entry for this endpoint index. */ 8928 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 8929 rv = WRITE_RMEPm(unit, MEM_BLOCK_ALL, h_data_p->remote_index, 8930 &rmep_entry); 8931 if (BCM_FAILURE(rv)) { 8932 LOG_ERROR(BSL_LS_BCM_OAM, 8933 (BSL_META_U(unit, 8934 "OAM(unit %d) Error: RMEP table write index=%x (EP=%d)" 8935 " - %s.\n"), unit, h_data_p->remote_index, 8936 h_data_p->ep_id, bcm_errmsg(rv))); 8937 return (rv); 8938 } 8939 8940 sal_memset(&l3_entry, 0, sizeof(l3_entry_1_entry_t)); 8941 8942 /* Construct endpoint RMEP view key for L3 Table entry delete operation. */ 8943 _bcm_sb2_oam_rmep_key_construct(unit, h_data_p, &l3_entry); 8944 8945 rv = soc_mem_delete(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ALL, &l3_entry); 8946 if (BCM_FAILURE(rv) && (oc->init)) { 8947 LOG_ERROR(BSL_LS_BCM_OAM, 8948 (BSL_META_U(unit, 8949 "OAM(unit %d) Error: RMEP view update (EP=%d)" 8950 " - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 8951 return (rv); 8952 } 8953 8954 /* Return ID back to free RMEP ID pool. */ 8955 BCM_IF_ERROR_RETURN 8956 (shr_idxres_list_free(oc->rmep_pool, h_data_p->remote_index)); 8957 8958 rv = shr_idxres_list_state(oc->rmep_pool, 8959 &first, &last, 8960 &validLow, &validHigh, 8961 &freeCount, &allocCount); 8962 if (BCM_FAILURE(rv)) { 8963 LOG_ERROR(BSL_LS_BCM_OAM, 8964 (BSL_META_U(unit, 8965 "OAM Error: RMEP pool state get failed " 8966 " - %s.\n"), bcm_errmsg(rv))); 8967 return (rv); 8968 } 8969 8970 if(allocCount == 0) 8971 { 8972 soc_MA_STATEm_field32_set 8973 (unit, &ma_state_entry, CURRENT_XCON_CCM_DEFECTf, 8974 0); 8975 soc_MA_STATEm_field32_set 8976 (unit, &ma_state_entry, CURRENT_ERROR_CCM_DEFECTf, 8977 0); 8978 soc_MA_STATEm_field32_set 8979 (unit, &ma_state_entry, STICKY_ERROR_CCM_DEFECTf, 8980 0); 8981 soc_MA_STATEm_field32_set 8982 (unit, &ma_state_entry, ERROR_CCM_DEFECT_TIMESTAMPf, 8983 0); 8984 soc_MA_STATEm_field32_set 8985 (unit, &ma_state_entry, ERROR_CCM_DEFECT_RECEIVE_CCMf, 8986 0); 8987 rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, h_data_p->group_index, 8988 &ma_state_entry); 8989 if (BCM_FAILURE(rv)) { 8990 LOG_ERROR(BSL_LS_BCM_OAM, 8991 (BSL_META_U(unit, 8992 "OAM Error: Group state (GID=%d) table write" 8993 " failed - %s.\n"), h_data_p->group_index, 8994 bcm_errmsg(rv))); 8995 return (rv); 8996 } 8997 } 8998 /* Clear the H/w index to logical index Mapping for RMEP */ 8999 oc->remote_endpoints[h_data_p->remote_index] = BCM_OAM_ENDPOINT_INVALID; 9000 9001 9002 return (BCM_E_NONE); 9003 } 9004 9005 /* 9006 * Function: 9007 * _bcm_sb2_oam_clear_counter 9008 * Purpose: 9009 * Remove the counter associated with the endpoint being deleted 9010 * Parameters: 9011 * unit - (IN) BCM device number 9012 * mem - (IN) MP_GROUP/EGR_MP_GROUP 9013 * index - (IN) Index of the table entry to be modified 9014 * h_data_p - (IN) Pointer to endpoint hash data 9015 * entry - (IN) pointer to table entry 9016 * Retruns: 9017 * BCM_E_XXX 9018 */ 9019 STATIC int 9020 _bcm_sb2_oam_clear_counter(int unit, soc_mem_t mem, 9021 int index, 9022 _bcm_oam_hash_data_t *h_data_p, 9023 void *entry) 9024 { 9025 int rv = BCM_E_NONE; 9026 sb2_mep_ctr_info_t *ctr_info; 9027 int ctr_type = 0; 9028 int ctr1_valid = 0; 9029 int ctr2_valid = 0; 9030 int ctr_mdl = 0; 9031 int up_mep = 0; 9032 int ctr_field_id = 0; 9033 9034 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 9035 up_mep = 1; 9036 } 9037 9038 if (mem == MP_GROUPm) { 9039 ctr_field_id = h_data_p->ctr_field_id; 9040 } else if (mem == EGR_MP_GROUPm) { 9041 ctr_field_id = h_data_p->egr_ctr_field_id; 9042 } else { 9043 return BCM_E_INTERNAL; 9044 } 9045 9046 ctr_info = sb2_mep_ctr_info; 9047 9048 ctr1_valid = soc_mem_field32_get(unit, mem, 9049 (uint32 *)entry, ctr_info[0].ctr_valid); 9050 if (ctr1_valid && ctr_field_id == 0) { 9051 ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry, 9052 ctr_info[0].ctr_mep_type); 9053 ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry, 9054 ctr_info[0].ctr_mep_mdl); 9055 if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) { 9056 ctr1_valid = 0; 9057 rv = soc_mem_field32_modify(unit, mem, index, 9058 ctr_info[0].ctr_valid, 0); 9059 } 9060 } 9061 ctr2_valid = soc_mem_field32_get(unit, mem, 9062 (uint32 *)entry, ctr_info[1].ctr_valid); 9063 if (ctr2_valid && ctr_field_id == 1) { 9064 ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry, 9065 ctr_info[1].ctr_mep_type); 9066 ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry, 9067 ctr_info[1].ctr_mep_mdl); 9068 if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) { 9069 rv = soc_mem_field32_modify(unit, mem, index, 9070 ctr_info[1].ctr_valid, 0); 9071 ctr2_valid = 0; 9072 } 9073 } 9074 9075 /* return rx & tx counters allocated if any */ 9076 rv =_bcm_sb2_oam_free_counter(unit, h_data_p); 9077 if (BCM_FAILURE(rv)) { 9078 LOG_ERROR(BSL_LS_BCM_OAM, 9079 (BSL_META_U(unit, 9080 "OAM(unit %d) Error: LM counter block " 9081 "free failed (EP=%d) - %s.\n"), 9082 unit, h_data_p->ep_id, bcm_errmsg(rv))); 9083 return (rv); 9084 } 9085 9086 return rv; 9087 } 9088 9089 /* 9090 * Function: 9091 * _bcm_sb2_oam_stm_table_clear 9092 * Purpose: 9093 * Clear MA base ptr and return MA index to the pool 9094 * Parameters: 9095 * unit - (IN) BCM device number 9096 * mod_id - (IN) Module Id 9097 * index - (IN) stm member index 9098 * port_id - (IN) port number 9099 * h_data_p - (IN) Pointer to hash data 9100 * Retruns: 9101 * BCM_E_XXX 9102 */ 9103 STATIC int 9104 _bcm_sb2_oam_stm_table_clear(int unit, bcm_module_t mod_id, int index, 9105 bcm_port_t port_id, 9106 _bcm_oam_hash_data_t *h_data_p) 9107 { 9108 int rv = BCM_E_NONE;/* Operation return status. */ 9109 int stm_index = 0; 9110 source_trunk_map_table_entry_t stm_entry; 9111 uint16 ma_base_idx; /* Base pointer to endpoint state */ 9112 /* table [MA_INDEX = (BASE + MDL)]. */ 9113 int idx = 0; 9114 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 9115 int count = 0; 9116 int ma_idx_entry_count = 0; 9117 shr_idxres_list_handle_t pool = NULL; 9118 9119 uint32 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0}; 9120 9121 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 9122 9123 soc_mem_lock(unit, SOURCE_TRUNK_MAP_TABLEm); 9124 9125 rv = _bcm_esw_src_mod_port_table_index_get(unit, 9126 mod_id, port_id, &stm_index); 9127 9128 if(BCM_FAILURE(rv)) { 9129 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 9130 return rv; 9131 } 9132 9133 rv = READ_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ANY, 9134 stm_index, &stm_entry); 9135 9136 if(BCM_FAILURE(rv)) { 9137 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 9138 return rv; 9139 } 9140 9141 ma_base_idx = soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, 9142 &stm_entry, MA_BASE_PTRf); 9143 if (index == 0) { 9144 /* Return Rx indices to free pool. */ 9145 for (idx = 0; idx < (1 << _BCM_OAM_EP_LEVEL_BIT_COUNT); idx++) { 9146 rx_index[idx] = ma_base_idx + idx; 9147 } 9148 9149 rv = _bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p, 9150 &ma_idx_entry_count, &pool); 9151 if(BCM_FAILURE(rv)) { 9152 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 9153 return rv; 9154 } 9155 9156 rv = shr_idxres_list_free_set(pool, ma_idx_entry_count, 9157 (shr_idxres_element_t *) rx_index, 9158 (shr_idxres_element_t *) &count); 9159 9160 /* Sometimes during module de init source trunk map is fully wiped 9161 * out before this is called. Hence ma_base_idx could be 0 instead 9162 * of right value. So ignore if this free fails 9163 */ 9164 if ((BCM_FAILURE(rv) || (8 != count)) && (ma_base_idx != 0)) { 9165 LOG_ERROR(BSL_LS_BCM_OAM, 9166 (BSL_META_U(unit, 9167 "OAM(unit %d) Error: Rx index list free (EP=%d)" 9168 " (count=%d).\n"), unit, h_data_p->ep_id, count)); 9169 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 9170 return (rv); 9171 } 9172 } 9173 9174 /* Set MA_BASE_PTR to 0 */ 9175 soc_SOURCE_TRUNK_MAP_TABLEm_field32_set(unit, &stm_entry, MA_BASE_PTRf, 0); 9176 9177 rv = WRITE_SOURCE_TRUNK_MAP_TABLEm(unit, MEM_BLOCK_ALL, stm_index, 9178 &stm_entry); 9179 soc_mem_unlock(unit, SOURCE_TRUNK_MAP_TABLEm); 9180 return rv; 9181 } 9182 9183 /* 9184 * Function: 9185 * _bcm_sb2_oam_trunk_port_mdl_update 9186 * Purpose: 9187 * Modify port, egr port and stm table entry 9188 * Parameters: 9189 * unit - (IN) BCM device number 9190 * h_data_p - (IN) Pointer to hash data 9191 * Retruns: 9192 * BCM_E_XXX 9193 */ 9194 STATIC int 9195 _bcm_sb2_oam_trunk_port_mdl_update(int unit, 9196 _bcm_oam_hash_data_t *h_data_p) 9197 { 9198 int rv = BCM_E_NONE; /* Operation return status. */ 9199 _bcm_oam_control_t *oc; /* Pointer to control structure*/ 9200 int member_count = 0; 9201 bcm_port_t *member_array = NULL; /* Trunk member port array. */ 9202 int local_member_count = 0; 9203 int i = 0; 9204 bcm_port_t pp_port = 0; 9205 bcm_module_t module_id; /* Module ID */ 9206 uint8 mdl = 0; 9207 9208 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 9209 9210 if(h_data_p->trunk_id == BCM_TRUNK_INVALID) { 9211 return BCM_E_PARAM; 9212 } 9213 9214 /* Get all the local member ports belonging to this trunk */ 9215 BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, h_data_p->trunk_id, 9216 NULL, 0, NULL, &member_count)); 9217 if (0 == member_count) { 9218 /* No members have been added to the trunk group yet */ 9219 LOG_ERROR(BSL_LS_BCM_OAM, 9220 (BSL_META_U(unit, 9221 "OAM(unit %d) Error: No local members have been added to " 9222 "the trunk group yet - %s.\n"), unit, bcm_errmsg(rv))); 9223 return BCM_E_PARAM; 9224 } 9225 9226 _BCM_OAM_ALLOC(member_array, bcm_port_t, 9227 sizeof(bcm_port_t) * member_count, "Trunk info"); 9228 if (NULL == member_array) { 9229 return (BCM_E_MEMORY); 9230 } 9231 9232 /* Get members of the trunk belonging to this module */ 9233 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 9234 h_data_p->trunk_id, 9235 member_count, member_array, 9236 &local_member_count))) { 9237 if (local_member_count > 0) { 9238 for(i = 0; i < local_member_count; i++) { 9239 rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i], 9240 &module_id, &pp_port); 9241 if (BCM_FAILURE(rv)) { 9242 sal_free(member_array); 9243 return (rv); 9244 } 9245 rv =_bcm_sb2_oam_port_mdl_update(unit, pp_port, 1, 9246 h_data_p, &mdl); 9247 if (BCM_FAILURE(rv)) { 9248 sal_free(member_array); 9249 return (rv); 9250 } 9251 } 9252 if (mdl == 0) { 9253 for(i = 0; i < local_member_count; i++) { 9254 rv = _bcm_sb2_oam_stm_table_clear(unit, module_id, i, 9255 member_array[i], h_data_p); 9256 if (BCM_FAILURE(rv)) { 9257 sal_free(member_array); 9258 return (rv); 9259 } 9260 } 9261 } 9262 rv = _bcm_sb2_oam_port_mdl_passive_update(unit, 1, h_data_p, mdl); 9263 if (BCM_FAILURE(rv)) { 9264 sal_free(member_array); 9265 return (rv); 9266 } 9267 9268 } 9269 } 9270 sal_free(member_array); 9271 return BCM_E_NONE; 9272 } 9273 /* 9274 * Function: 9275 * _bcm_sb2_port_domain_mdl_bitmap_update 9276 * Purpose: 9277 * Update Port table MDL bitmap and STM table MA_BASE_PTR. 9278 * Parameters: 9279 * unit - (IN) BCM device number 9280 * h_data_p - (IN) Pointer to endpoint hash data 9281 * Retruns: 9282 * BCM_E_XXX 9283 */ 9284 STATIC int 9285 _bcm_sb2_port_domain_mdl_bitmap_update(int unit, _bcm_oam_hash_data_t *h_data_p) 9286 { 9287 int rv = BCM_E_NONE;/* Operation return status. */ 9288 uint8 mdl; /* Maintenance domain level. */ 9289 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 9290 bcm_module_t mod_id = 0; 9291 bcm_port_t port_id = 0; 9292 9293 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 9294 9295 /* If the OAM domain is port */ 9296 if (_BCM_OAM_DOMAIN_PORT != h_data_p->oam_domain) { 9297 return (BCM_E_INTERNAL); 9298 } 9299 9300 if(h_data_p->trunk_id != BCM_TRUNK_INVALID) { 9301 rv = _bcm_sb2_oam_trunk_port_mdl_update(unit, h_data_p); 9302 } else { 9303 port_id = _BCM_OAM_GLP_PORT_GET(h_data_p->sglp); 9304 mod_id = _BCM_OAM_GLP_MODULE_ID_GET(h_data_p->sglp); 9305 BCM_IF_ERROR_RETURN 9306 (_bcm_sb2_oam_port_mdl_update(unit, h_data_p->src_pp_port, 9307 1, h_data_p, &mdl)); 9308 BCM_IF_ERROR_RETURN 9309 (_bcm_sb2_oam_port_mdl_passive_update(unit, 1, h_data_p, mdl)); 9310 if (mdl == 0) { 9311 BCM_IF_ERROR_RETURN 9312 (_bcm_sb2_oam_stm_table_clear(unit, mod_id, 0, 9313 port_id, h_data_p)); 9314 } 9315 } 9316 return (rv); 9317 } 9318 9319 /* 9320 * Function: 9321 * _bcm_sb2_oam_ing_mp_group_entry_destroy 9322 * Purpose: 9323 * Update Ingress MP group table(L3 Entry- LMEP view)entry. 9324 * Parameters: 9325 * unit - (IN) BCM device number 9326 * h_data_p - (IN) Pointer to endpoint hash data 9327 * active_mdl -(IN) Active MDL bitmap value 9328 * Retruns: 9329 * BCM_E_XXX 9330 */ 9331 STATIC int 9332 _bcm_sb2_oam_ing_mp_group_entry_destroy(int unit, _bcm_oam_hash_data_t *h_data_p, 9333 uint8 *active_mdl) 9334 { 9335 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 9336 mp_group_entry_t mp_group_entry; /* LMEP view table entry. */ 9337 int l3_index = -1; /* L3 table hardware index. */ 9338 int rv; /* Operation return status. */ 9339 uint8 mdl; /* Maintenance domain level. */ 9340 uint8 other_mdl = 0; /* Maintenance domain level. */ 9341 uint32 ma_base_index; /* Endpoint tbl base index. */ 9342 uint32 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0}; 9343 /* Endpoint Rx hardware index. */ 9344 uint32 count; /* No. of Rx indices freed */ 9345 /* successfully. */ 9346 int idx; /* Iterator variable. */ 9347 soc_field_t mdl_field = 0; 9348 soc_field_t other_mdl_field = 0; 9349 int upmep = 0; 9350 int ma_idx_entry_count = 0; 9351 shr_idxres_list_handle_t pool = NULL; 9352 9353 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 9354 /* Check whether up/down MEP */ 9355 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 9356 mdl_field = MDL_BITMAP_PASSIVEf; 9357 other_mdl_field = MDL_BITMAP_ACTIVEf; 9358 upmep = 1; 9359 } else { 9360 mdl_field = MDL_BITMAP_ACTIVEf; 9361 other_mdl_field = MDL_BITMAP_PASSIVEf; 9362 } 9363 rv = _bcm_sb2_oam_find_lmep(unit, h_data_p, &l3_index, &mp_group_entry); 9364 if (BCM_SUCCESS(rv)) { 9365 /* Endpoint found, get MDL bitmap value. */ 9366 mdl = soc_MP_GROUPm_field32_get(unit, &mp_group_entry, 9367 mdl_field); 9368 9369 /* Passive demultiplexing should not be done on a MIP. 9370 * Hence do not touch PASSIVE bitmap when destroying 9371 * also. 9372 */ 9373 if (!((mdl_field == MDL_BITMAP_PASSIVEf) && 9374 (_BCM_OAM_EP_IS_MIP(h_data_p)))) { 9375 /* Clear the MDL bit for this endpoint. */ 9376 mdl &= ~(1 << h_data_p->level); 9377 9378 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 9379 /* Passive MDL bitmap */ 9380 _bcm_sb2_oam_get_passive_mdl_from_active_mdl(unit, *active_mdl, 9381 h_data_p->ma_base_index, &mdl, 1); 9382 } else { 9383 *active_mdl = mdl; 9384 } 9385 } 9386 /* Take L3 module protection mutex to block any updates. */ 9387 L3_LOCK(unit); 9388 if (0 != mdl) { 9389 BCM_SB2_TCAM_ATOMICITY_DISABLE(unit); 9390 /* Valid endpoints exist for other MDLs at this index. */ 9391 rv = soc_mem_field32_modify(unit, MP_GROUPm, l3_index, 9392 mdl_field, mdl); 9393 BCM_SB2_TCAM_ATOMICITY_ENABLE(unit); 9394 if (BCM_FAILURE(rv)) { 9395 LOG_ERROR(BSL_LS_BCM_OAM, 9396 (BSL_META_U(unit, 9397 "OAM(unit %d) Error:L3 entry LMEP view update(EP=%d) -" 9398 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9399 L3_UNLOCK(unit); 9400 return (rv); 9401 } 9402 /* Clear the counter, if any */ 9403 rv = _bcm_sb2_oam_clear_counter(unit, MP_GROUPm, 9404 l3_index, h_data_p, 9405 (void *)&mp_group_entry); 9406 if (BCM_FAILURE(rv)) { 9407 LOG_ERROR(BSL_LS_BCM_OAM, 9408 (BSL_META_U(unit, 9409 "OAM(unit %d) Error: Clear counter failed (EP=%d) -" 9410 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9411 L3_UNLOCK(unit); 9412 return (rv); 9413 } 9414 9415 } else { 9416 /* check if other MDL bitmap is also zero (passive bitmap incase 9417 of downmep and active bitmap in case of upmep), if so delete the 9418 entry completely */ 9419 other_mdl = soc_MP_GROUPm_field32_get(unit, &mp_group_entry, 9420 other_mdl_field); 9421 if (0 == other_mdl) { 9422 BCM_SB2_TCAM_ATOMICITY_DISABLE(unit); 9423 rv = soc_mem_delete_index(unit, MP_GROUPm, 9424 MEM_BLOCK_ALL, l3_index); 9425 BCM_SB2_TCAM_ATOMICITY_ENABLE(unit); 9426 rv =_bcm_sb2_oam_free_counter(unit, h_data_p); 9427 if (BCM_FAILURE(rv)) { 9428 LOG_ERROR(BSL_LS_BCM_OAM, 9429 (BSL_META_U(unit, 9430 "OAM(unit %d) Error: LM counter block " 9431 "free failed (EP=%d) - %s.\n"), 9432 unit, h_data_p->ep_id, bcm_errmsg(rv))); 9433 L3_UNLOCK(unit); 9434 return (rv); 9435 } 9436 } else { 9437 /* Valid endpoints exist for other MDLs at this index. */ 9438 BCM_SB2_TCAM_ATOMICITY_DISABLE(unit); 9439 rv = soc_mem_field32_modify(unit, MP_GROUPm, 9440 l3_index, mdl_field, mdl); 9441 BCM_SB2_TCAM_ATOMICITY_ENABLE(unit); 9442 if (BCM_FAILURE(rv)) { 9443 LOG_ERROR(BSL_LS_BCM_OAM, 9444 (BSL_META_U(unit, 9445 "OAM(unit %d) Error: LMEP view update (EP=%d) -" 9446 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9447 L3_UNLOCK(unit); 9448 return (rv); 9449 } 9450 /* Clear the counter, if any */ 9451 rv = _bcm_sb2_oam_clear_counter(unit, MP_GROUPm, 9452 l3_index, h_data_p, 9453 (void *)&mp_group_entry); 9454 if (BCM_FAILURE(rv)) { 9455 LOG_ERROR(BSL_LS_BCM_OAM, 9456 (BSL_META_U(unit, 9457 "OAM(unit %d) Error: Clear counter failed (EP=%d) -" 9458 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9459 L3_UNLOCK(unit); 9460 return (rv); 9461 } 9462 9463 } 9464 } 9465 L3_UNLOCK(unit); 9466 9467 /* This is the last Rx endpoint in this OAM group. */ 9468 if ((0 == mdl) && (upmep == 0)) { 9469 ma_base_index = soc_MP_GROUPm_field32_get(unit, 9470 &mp_group_entry, 9471 MA_BASE_PTRf); 9472 /* Return Rx indices to free pool. */ 9473 for (idx = 0; idx < (1 << _BCM_OAM_EP_LEVEL_BIT_COUNT); idx++) { 9474 rx_index[idx] = ma_base_index + idx; 9475 } 9476 9477 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p, 9478 &ma_idx_entry_count, &pool)); 9479 rv = shr_idxres_list_free_set(pool, ma_idx_entry_count, 9480 (shr_idxres_element_t *) rx_index, 9481 (shr_idxres_element_t *) &count); 9482 9483 if (BCM_FAILURE(rv) || (8 != count)) { 9484 LOG_ERROR(BSL_LS_BCM_OAM, 9485 (BSL_META_U(unit, 9486 "OAM(unit %d) Error: Rx index list free (EP=%d)" 9487 " (count=%d).\n"), unit, h_data_p->ep_id, count)); 9488 return (rv); 9489 } 9490 } 9491 9492 } else if (BCM_FAILURE(rv) && (oc->init)) { 9493 /* We do not program passive bitmap for MIP. So dont throw error 9494 * if you don't find an entry, since we might not have created 9495 * such an entry at all. */ 9496 if (!((mdl_field == MDL_BITMAP_PASSIVEf) && 9497 (_BCM_OAM_EP_IS_MIP(h_data_p)))) { 9498 LOG_ERROR(BSL_LS_BCM_OAM, 9499 (BSL_META_U(unit, 9500 "OAM(unit %d) Error: L3 entry table lookup (EP=%d) -" 9501 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9502 return (rv); 9503 } 9504 } 9505 return (BCM_E_NONE); 9506 } 9507 9508 /* This is useful to find if an egr mp group has counters other 9509 * than our endpoint's counters. This is useful in case of 9510 * MPLS LSP endpoints which have the same lookup params and same 9511 * mdl as well(hence in the same egr_mp_group entry and having 9512 * same mdl bitmap) to know that there are endpoints with counters 9513 * other than given endpoint. Therefore we could avoid touching the 9514 * mdl bitmap or deleting the index itself during deleting of 9515 * endpoint 9516 */ 9517 #define MP_GRP_NUM_CTR_FIELD_IDS 2 9518 int _bcm_sb2_oam_egr_mp_group_num_counters_other_than_mine_get(int unit, 9519 egr_mp_group_entry_t *egr_mp_group, 9520 _bcm_oam_hash_data_t *h_data_p) 9521 { 9522 int num_ctrs = 0; 9523 int ctr_field_id; 9524 int ctr_valid = 0; 9525 sb2_mep_ctr_info_t *ctr_info; 9526 9527 if (!egr_mp_group || !h_data_p) { 9528 return 0; 9529 } 9530 9531 ctr_info = sb2_mep_ctr_info; 9532 9533 for (ctr_field_id = 0; ctr_field_id < MP_GRP_NUM_CTR_FIELD_IDS; 9534 ctr_field_id++) { 9535 if (h_data_p->egr_ctr_field_id == ctr_field_id) { 9536 /* If it is mine, skip counting */ 9537 continue; 9538 } 9539 ctr_valid = soc_mem_field32_get(unit, EGR_MP_GROUPm, 9540 (uint32 *)egr_mp_group, 9541 ctr_info[ctr_field_id].ctr_valid); 9542 if (ctr_valid) { 9543 num_ctrs++; 9544 } 9545 } 9546 return num_ctrs; 9547 } 9548 9549 /* 9550 * Function: 9551 * _bcm_sb2_oam_egr_mp_group_entry_destroy 9552 * Purpose: 9553 * Update Egress MP group table entry. 9554 * Parameters: 9555 * unit - (IN) BCM device number 9556 * h_data_p - (IN) Pointer to endpoint hash data 9557 * Retruns: 9558 * BCM_E_XXX 9559 */ 9560 STATIC int 9561 _bcm_sb2_oam_egr_mp_group_entry_destroy(int unit, 9562 _bcm_oam_hash_data_t *h_data_p, 9563 uint8 *active_mdl) 9564 { 9565 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 9566 uint8 mdl; /* Maintenance domain level. */ 9567 uint8 other_mdl = 0; /* Maintenance domain level. */ 9568 int rv; /* Operation return status. */ 9569 uint32 ma_base_index; /* Endpoint tbl base index. */ 9570 uint32 rx_index[1 << _BCM_OAM_EP_LEVEL_BIT_COUNT] = {0}; 9571 /* Endpoint Rx hardware index. */ 9572 uint32 count; /* No. of Rx indices freed */ 9573 /* successfully. */ 9574 int idx; /* Iterator variable. */ 9575 soc_field_t mdl_field = 0; 9576 soc_field_t other_mdl_field = 0; 9577 egr_mp_group_entry_t egr_mp_group; /* Egress MP group tbl entry buffer */ 9578 int mp_grp_index = 0; 9579 int upmep = 0; 9580 int num_egr_mp_grp_counters_other_than_mine = 0; 9581 9582 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 9583 9584 /* Check whether up/down MEP */ 9585 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 9586 mdl_field = MDL_BITMAP_ACTIVEf; 9587 other_mdl_field = MDL_BITMAP_PASSIVEf; 9588 upmep = 1; 9589 } else { 9590 if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 9591 mdl_field = MDL_BITMAP_ACTIVEf; 9592 other_mdl_field = MDL_BITMAP_PASSIVEf; 9593 } else { 9594 mdl_field = MDL_BITMAP_PASSIVEf; 9595 other_mdl_field = MDL_BITMAP_ACTIVEf; 9596 } 9597 } 9598 rv = _bcm_sb2_oam_find_egr_lmep(unit, h_data_p, 9599 &mp_grp_index, &egr_mp_group); 9600 if (BCM_SUCCESS(rv)) { 9601 /* Endpoint found, get MDL bitmap value. */ 9602 mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, 9603 mdl_field); 9604 /* Get number of counters other than mine */ 9605 num_egr_mp_grp_counters_other_than_mine = 9606 _bcm_sb2_oam_egr_mp_group_num_counters_other_than_mine_get( 9607 unit, &egr_mp_group, h_data_p); 9608 9609 /* Passive demultiplexing should not be done on a MIP. 9610 * Hence do not touch PASSIVE bitmap when destroying 9611 * also. 9612 */ 9613 if (!((mdl_field == MDL_BITMAP_PASSIVEf) && 9614 (_BCM_OAM_EP_IS_MIP(h_data_p)))) { 9615 /* Clear the MDL bit for this endpoint. */ 9616 mdl &= ~(1 << h_data_p->level); 9617 9618 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 9619 *active_mdl = mdl; 9620 } else{ 9621 /* Passive MDL bitmap */ 9622 _bcm_sb2_oam_get_passive_mdl_from_active_mdl(unit, *active_mdl, 9623 h_data_p->ma_base_index, &mdl, 0); 9624 } 9625 } 9626 /* Take L3 module protection mutex to block any updates. */ 9627 soc_mem_lock(unit, EGR_MP_GROUPm); 9628 if (0 != mdl) { 9629 /* Valid endpoints exist for other MDLs at this index. */ 9630 rv = soc_mem_field32_modify(unit, EGR_MP_GROUPm, mp_grp_index, 9631 mdl_field, mdl); 9632 if (BCM_FAILURE(rv)) { 9633 LOG_ERROR(BSL_LS_BCM_OAM, 9634 (BSL_META_U(unit, 9635 "OAM(unit %d) Error: EGR MP group table update (EP=%d) -" 9636 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9637 soc_mem_unlock(unit, EGR_MP_GROUPm); 9638 return (rv); 9639 } 9640 /* Clear the counter, if any */ 9641 rv = _bcm_sb2_oam_clear_counter(unit, EGR_MP_GROUPm, mp_grp_index, 9642 h_data_p, (void *)&egr_mp_group); 9643 if (BCM_FAILURE(rv)) { 9644 LOG_ERROR(BSL_LS_BCM_OAM, 9645 (BSL_META_U(unit, 9646 "OAM(unit %d) Error:EGR MP group table update(EP=%d) -" 9647 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9648 soc_mem_unlock(unit, EGR_MP_GROUPm); 9649 return (rv); 9650 } 9651 } else { 9652 /* check if other MDL bitmap is also zero (passive bitmap in case 9653 of downmep and active bitmap in case of upmep), if so delete the 9654 entry completely */ 9655 other_mdl = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, 9656 other_mdl_field); 9657 if ((0 == other_mdl) && 9658 (!((MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p))&& 9659 (num_egr_mp_grp_counters_other_than_mine >= 1)))) { 9660 rv = soc_mem_delete_index(unit, EGR_MP_GROUPm, MEM_BLOCK_ALL, 9661 mp_grp_index); 9662 rv =_bcm_sb2_oam_free_counter(unit, h_data_p); 9663 if (BCM_FAILURE(rv)) { 9664 LOG_ERROR(BSL_LS_BCM_OAM, 9665 (BSL_META_U(unit, 9666 "OAM(unit %d) Error: LM counter block " 9667 "free failed (EP=%d) - %s.\n"), 9668 unit, h_data_p->ep_id, bcm_errmsg(rv))); 9669 soc_mem_unlock(unit, EGR_MP_GROUPm); 9670 return (rv); 9671 } 9672 } else { 9673 if (!((MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p))&& 9674 (num_egr_mp_grp_counters_other_than_mine >= 1))) { 9675 rv = soc_mem_field32_modify(unit, EGR_MP_GROUPm, mp_grp_index, 9676 mdl_field, mdl); 9677 if (BCM_FAILURE(rv)) { 9678 LOG_ERROR(BSL_LS_BCM_OAM, 9679 (BSL_META_U(unit, 9680 "OAM(unit %d) Error: EGR MP group table update " 9681 "(EP=%d) -" " %s.\n"), unit, 9682 h_data_p->ep_id, bcm_errmsg(rv))); 9683 soc_mem_unlock(unit, EGR_MP_GROUPm); 9684 return (rv); 9685 } 9686 } 9687 /* Clear the counter, if any */ 9688 rv = _bcm_sb2_oam_clear_counter(unit, EGR_MP_GROUPm, mp_grp_index, 9689 h_data_p, (void *)&egr_mp_group); 9690 if (BCM_FAILURE(rv)) { 9691 LOG_ERROR(BSL_LS_BCM_OAM, 9692 (BSL_META_U(unit, 9693 "OAM(unit %d) Error:EGR MP group tbl update(EP=%d)-" 9694 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9695 soc_mem_unlock(unit, EGR_MP_GROUPm); 9696 return (rv); 9697 } 9698 } 9699 } 9700 soc_mem_unlock(unit, EGR_MP_GROUPm); 9701 9702 /* This is the last Rx endpoint in this OAM group. */ 9703 if ((0 == mdl) && (upmep)) { 9704 ma_base_index = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, 9705 MA_BASE_PTRf); 9706 /* Return Rx indices to free pool. */ 9707 for (idx = 0; idx < (1 << _BCM_OAM_EP_LEVEL_BIT_COUNT); idx++) { 9708 rx_index[idx] = ma_base_index + idx; 9709 } 9710 9711 rv = shr_idxres_list_free_set(oc->egr_ma_idx_pool, 8, 9712 (shr_idxres_element_t *) rx_index, 9713 (shr_idxres_element_t *) &count); 9714 if (BCM_FAILURE(rv) || (8 != count)) { 9715 LOG_ERROR(BSL_LS_BCM_OAM, 9716 (BSL_META_U(unit, 9717 "OAM(unit %d) Error: Egr Rx index list free (EP=%d)" 9718 " (count=%d).\n"), unit, h_data_p->ep_id, count)); 9719 return (rv); 9720 } 9721 } 9722 } else if (BCM_FAILURE(rv) && (oc->init)) { 9723 /* We do not program passive bitmap for MIP. So dont throw error 9724 * if you don't find an entry, since we might not have created 9725 * such an entry at all. */ 9726 if (!((mdl_field == MDL_BITMAP_PASSIVEf) && 9727 (_BCM_OAM_EP_IS_MIP(h_data_p)))) { 9728 LOG_ERROR(BSL_LS_BCM_OAM, 9729 (BSL_META_U(unit, 9730 "OAM(unit %d) Error: LMEP table write (EP=%d) -" 9731 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9732 return (rv); 9733 } 9734 } 9735 return (BCM_E_NONE); 9736 } 9737 9738 /* 9739 * Function: 9740 * _bcm_sb2_oam_local_endpoint_delete 9741 * Purpose: 9742 * Delete a local endpoint. 9743 * Parameters: 9744 * unit - (IN) BCM device number 9745 * h_data_p - (IN) Pointer to endpoint hash data 9746 * Retruns: 9747 * BCM_E_XXX 9748 */ 9749 STATIC int 9750 _bcm_sb2_oam_local_endpoint_delete(int unit, _bcm_oam_hash_data_t *h_data_p) 9751 { 9752 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 9753 lmep_entry_t lmep_entry; /* Local endpoint table entry. */ 9754 int rv; /* Operation return status. */ 9755 lmep_1_entry_t lmep_1_entry; /* LMEP_1 table entry. */ 9756 soc_profile_mem_t *opcode_control_profile; /* profile used - 9757 ingress or egress */ 9758 soc_profile_mem_t *dglp_profile; /* dglp profile used - 9759 ingress or egress */ 9760 ma_index_entry_t ma_idx_entry; /* MA_INDEX table entry buffer. */ 9761 ma_index_entry_t egr_ma_idx_entry;/* MA_INDEX table entry buffer. */ 9762 void *ma_idx_ptr; 9763 soc_mem_t ma_index_mem = 0; 9764 uint8 active_mdl = 0; 9765 int ma_offset = 0; 9766 9767 /* Lock already taken by the calling routine. */ 9768 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 9769 9770 if (1 == h_data_p->local_tx_enabled) { 9771 9772 /* Clear endpoint Tx config in hardware. */ 9773 sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t)); 9774 sal_memset(&lmep_1_entry, 0, sizeof(lmep_1_entry_t)); 9775 rv = WRITE_LMEPm(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index, 9776 &lmep_entry); 9777 9778 if (BCM_FAILURE(rv)) { 9779 LOG_ERROR(BSL_LS_BCM_OAM, 9780 (BSL_META_U(unit, 9781 "OAM(unit %d) Error: LMEP table write (EP=%d)" 9782 " failed - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9783 return (rv); 9784 } 9785 rv = WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index, 9786 &lmep_1_entry); 9787 if (BCM_FAILURE(rv)) { 9788 LOG_ERROR(BSL_LS_BCM_OAM, 9789 (BSL_META_U(unit, 9790 "OAM(unit %d) Error: LMEP_1 table write (EP=%d)" 9791 " failed - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9792 return (rv); 9793 } 9794 9795 /* Return ID back to free LMEP ID pool. */ 9796 BCM_IF_ERROR_RETURN 9797 (shr_idxres_list_free(oc->lmep_pool, h_data_p->local_tx_index)); 9798 9799 } 9800 9801 if (1 == h_data_p->local_rx_enabled) { 9802 /* Check whether up/down MEP */ 9803 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 9804 opcode_control_profile = &oc->egr_oam_opcode_control_profile; 9805 dglp_profile = &oc->egr_oam_dglp_profile; 9806 ma_index_mem = EGR_MA_INDEXm; 9807 sal_memset(&egr_ma_idx_entry, 0, sizeof(egr_ma_index_entry_t)); 9808 ma_idx_ptr = &egr_ma_idx_entry; 9809 } else { 9810 opcode_control_profile = &oc->oam_opcode_control_profile; 9811 dglp_profile = &oc->ing_oam_dglp_profile; 9812 ma_index_mem = MA_INDEXm; 9813 sal_memset(&ma_idx_entry, 0, sizeof(ma_index_entry_t)); 9814 ma_idx_ptr = &ma_idx_entry; 9815 } 9816 9817 /* Delete OAM opcode profile entry for this endpoint. */ 9818 rv = soc_profile_mem_delete(unit, opcode_control_profile, 9819 _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(h_data_p->profile_index)); 9820 if (BCM_FAILURE(rv)) { 9821 LOG_ERROR(BSL_LS_BCM_OAM, 9822 (BSL_META_U(unit, 9823 "OAM(unit %d) Error: Profile table update error (idx=%d)" 9824 "- %s.\n"), unit, h_data_p->profile_index, bcm_errmsg(rv))); 9825 return (rv); 9826 } 9827 /* Delete DGLP profile entry for this endpoint. */ 9828 if (h_data_p->dglp1_profile_index != _BCM_OAM_INVALID_INDEX) { 9829 rv = soc_profile_mem_delete(unit, dglp_profile, 9830 h_data_p->dglp1_profile_index); 9831 if (BCM_FAILURE(rv)) { 9832 LOG_ERROR(BSL_LS_BCM_OAM, 9833 (BSL_META_U(unit, 9834 "OAM(unit %d) Error: Profile table update " 9835 "error (idx=%d)" "- %s.\n"), unit, 9836 h_data_p->dglp1_profile_index, bcm_errmsg(rv))); 9837 return (rv); 9838 } 9839 } 9840 if (h_data_p->dglp2_profile_index != _BCM_OAM_INVALID_INDEX) { 9841 rv = soc_profile_mem_delete(unit, dglp_profile, 9842 h_data_p->dglp2_profile_index); 9843 if (BCM_FAILURE(rv)) { 9844 LOG_ERROR(BSL_LS_BCM_OAM, 9845 (BSL_META_U(unit, 9846 "OAM(unit %d) Error: Profile table update " 9847 "error (idx=%d)" "- %s.\n"), unit, 9848 h_data_p->dglp2_profile_index, bcm_errmsg(rv))); 9849 return (rv); 9850 } 9851 } 9852 /* Get MA_INDEX offset */ 9853 rv = _bcm_sb2_oam_ma_index_offset_get(unit, h_data_p, &ma_offset); 9854 if (BCM_FAILURE(rv)) { 9855 LOG_ERROR(BSL_LS_BCM_OAM, 9856 (BSL_META_U(unit, 9857 "OAM(unit %d) Error: MA INDEX table offset get failed EP=%d" 9858 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9859 return (rv); 9860 } 9861 9862 h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset; 9863 9864 /* Delete MA INDEX entry */ 9865 rv = _bcm_sb2_oam_ma_index_entry_set(unit, h_data_p, 9866 ma_index_mem, ma_idx_ptr, 1); 9867 if (BCM_FAILURE(rv)) { 9868 LOG_ERROR(BSL_LS_BCM_OAM, 9869 (BSL_META_U(unit, 9870 "OAM(unit %d) Error: MA INDEX table delete failed EP=%d" 9871 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9872 return (rv); 9873 } 9874 if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) { 9875 rv = _bcm_sb2_port_domain_mdl_bitmap_update(unit, h_data_p); 9876 if (BCM_FAILURE(rv)) { 9877 LOG_ERROR(BSL_LS_BCM_OAM, 9878 (BSL_META_U(unit, 9879 "OAM(unit %d) Error: port OAM MDL update failed EP=%d" 9880 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9881 return (rv); 9882 } 9883 } else if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 9884 rv = _bcm_sb2_oam_egr_mp_group_entry_destroy(unit, h_data_p, 9885 &active_mdl); 9886 if (BCM_FAILURE(rv)) { 9887 LOG_ERROR(BSL_LS_BCM_OAM, 9888 (BSL_META_U(unit, 9889 "OAM(unit %d) Error: Egr MP Group update (EP=%d) -" 9890 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9891 return (rv); 9892 } 9893 9894 /* Update Ingress MP group table(MP_GROUP_ENTRY) */ 9895 rv = _bcm_sb2_oam_ing_mp_group_entry_destroy(unit, h_data_p, &active_mdl); 9896 if (BCM_FAILURE(rv)) { 9897 LOG_ERROR(BSL_LS_BCM_OAM, 9898 (BSL_META_U(unit, 9899 "OAM(unit %d) Error: LMEP view update (EP=%d) -" 9900 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9901 return (rv); 9902 } 9903 } else { 9904 /* Update Ingress MP group table(MP_GROUP_ENTRY) */ 9905 rv = _bcm_sb2_oam_ing_mp_group_entry_destroy(unit, h_data_p, &active_mdl); 9906 if (BCM_FAILURE(rv)) { 9907 LOG_ERROR(BSL_LS_BCM_OAM, 9908 (BSL_META_U(unit, 9909 "OAM(unit %d) Error: LMEP view update (EP=%d) -" 9910 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9911 return (rv); 9912 9913 } 9914 rv = _bcm_sb2_oam_egr_mp_group_entry_destroy(unit, h_data_p, 9915 &active_mdl); 9916 if (BCM_FAILURE(rv)) { 9917 LOG_ERROR(BSL_LS_BCM_OAM, 9918 (BSL_META_U(unit, 9919 "OAM(unit %d) Error: Egr MP Group update (EP=%d) -" 9920 " %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 9921 return (rv); 9922 } 9923 } 9924 } 9925 return (BCM_E_NONE); 9926 } 9927 9928 9929 /* 9930 * Function: 9931 * _bcm_sb2_oam_port_table_key_update1 9932 * Purpose: 9933 * Update OAM_KEY1 and OAM_KEY2 in port table 9934 * Parameters: 9935 * unit - (IN) BCM device number 9936 * mem - (IN) PORT_TAB/EGR_PORT 9937 * pp_port - (IN) PP port 9938 * h_data_p - (IN/OUT) Pointer to endpoint hash data 9939 * Returns: 9940 * BCM_E_XXX 9941 */ 9942 int 9943 _bcm_sb2_oam_port_table_key_update1(int unit, soc_mem_t mem, int pp_port, 9944 _bcm_oam_hash_data_t *h_data_p) 9945 { 9946 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 9947 int rv = BCM_E_NONE; /* Operation return status. */ 9948 port_tab_entry_t port_entry; 9949 egr_port_entry_t egr_port_entry; 9950 int key_type = 0; 9951 int oam_key1 = 0; 9952 int oam_key2 = 0; 9953 void *port_entry_ptr; 9954 uint16 *key1_ref_count = NULL; 9955 uint16 *key2_ref_count = NULL; 9956 9957 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 9958 9959 9960 if(MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) && 9961 !MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) { 9962 /* Not expected to happen. Should be called only 9963 * for mpls section 9964 */ 9965 return BCM_E_INTERNAL; 9966 } 9967 9968 if (BHH_EP_TYPE(h_data_p) && 9969 !BHH_EP_MPLS_SECTION_TYPE(h_data_p)) { 9970 /* Not expected to happen. Should be called only 9971 * for mpls section 9972 */ 9973 return BCM_E_INTERNAL; 9974 } 9975 9976 /* Set the search key type. */ 9977 _bcm_sb2_oam_key_type_from_endpoint_get(h_data_p->type, h_data_p->flags, 9978 h_data_p->vlan, 9979 h_data_p->inner_vlan, h_data_p->int_flags, 9980 &key_type); 9981 9982 if (mem == PORT_TABm) { 9983 port_entry_ptr = &port_entry; 9984 key1_ref_count = &oc->oam_key1_ref_count[0]; 9985 key2_ref_count = &oc->oam_key2_ref_count[0]; 9986 } else { 9987 port_entry_ptr = &egr_port_entry; 9988 key1_ref_count = &oc->egr_oam_key1_ref_count[0]; 9989 key2_ref_count = &oc->egr_oam_key2_ref_count[0]; 9990 } 9991 9992 /* 9993 We need to set the OAM_KEY1 and OAM_KEY2 fields of the PORT_TABLE and 9994 EGR_PORT_TABLE based on the key_type of OAM */ 9995 9996 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, pp_port, port_entry_ptr); 9997 if (BCM_FAILURE(rv)) { 9998 LOG_ERROR(BSL_LS_BCM_OAM, 9999 (BSL_META_U(unit, 10000 "OAM(unit %d) Error: Port table read - %s.\n"), 10001 unit, bcm_errmsg(rv))); 10002 return (rv); 10003 } 10004 10005 if(!MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p) && 10006 !BHH_EP_MPLS_SECTION_TYPE(h_data_p)) { 10007 oam_key1 = soc_mem_field32_get(unit, mem, port_entry_ptr, OAM_KEY1f); 10008 oam_key2 = soc_mem_field32_get(unit, mem, port_entry_ptr, OAM_KEY2f); 10009 } 10010 10011 if ((key_type != _BCM_OAM_DOMAIN_PORT) 10012 && (!MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) 10013 && (!BHH_EP_MPLS_SECTION_TYPE(h_data_p))) { 10014 if ((oam_key1 > 0) && (oam_key2 > 0)) { 10015 if ((oam_key1 == key_type) || (oam_key2 == key_type)) { 10016 } else { 10017 LOG_ERROR(BSL_LS_BCM_OAM, 10018 (BSL_META_U(unit, 10019 "OAM(unit %d) Error: Invalid OAM domain to resolve " 10020 "(EP=%d) - %s.\n"), 10021 unit, h_data_p->ep_id, bcm_errmsg(rv))); 10022 return (BCM_E_PARAM); 10023 } 10024 } 10025 } 10026 10027 if (key_type != _BCM_OAM_DOMAIN_PORT) { 10028 if ((MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) || 10029 (BHH_EP_MPLS_SECTION_TYPE(h_data_p))) { 10030 soc_mem_field32_set(unit, mem, port_entry_ptr, 10031 MPLS_SECTION_OAM_KEYf, key_type); 10032 /* Enable section OAM for this port */ 10033 if (BHH_EP_MPLS_SECTION_TYPE(h_data_p)) { 10034 soc_mem_field32_set(unit, mem, port_entry_ptr, 10035 MPLS_SECTION_OAM_ENABLEf, 10036 _BCM_SB2_MPLS_OAM_ENABLE_BHH); 10037 } else if (MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) { 10038 soc_mem_field32_set(unit, mem, port_entry_ptr, 10039 MPLS_SECTION_OAM_ENABLEf, 10040 _BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM); 10041 } 10042 } else { 10043 if ((oam_key1 == 0) && (oam_key2 == 0)) { 10044 soc_mem_field32_set(unit, mem, port_entry_ptr, OAM_KEY1f, key_type); 10045 key1_ref_count[pp_port]++; 10046 } else if ((oam_key1 != key_type) && (oam_key2 == 0)) { 10047 if (key_type > oam_key1) { 10048 soc_mem_field32_set(unit, mem, port_entry_ptr, OAM_KEY2f, 10049 key_type); 10050 key2_ref_count[pp_port]++; 10051 } else { 10052 key2_ref_count[pp_port] = key1_ref_count[pp_port]; 10053 soc_mem_field32_set(unit, mem, port_entry_ptr, 10054 OAM_KEY1f, key_type); 10055 key1_ref_count[pp_port] = 1; 10056 soc_mem_field32_set(unit, mem, port_entry_ptr, 10057 OAM_KEY2f, oam_key1); 10058 } 10059 } else if ((oam_key2 != key_type) && (oam_key1 == 0)) { 10060 if (key_type < oam_key2) { 10061 soc_mem_field32_set(unit, mem, port_entry_ptr, OAM_KEY1f, 10062 key_type); 10063 key1_ref_count[pp_port]++; 10064 } else { 10065 key1_ref_count[pp_port] = key2_ref_count[pp_port]; 10066 soc_mem_field32_set(unit, mem, port_entry_ptr, 10067 OAM_KEY1f, oam_key2); 10068 soc_mem_field32_set(unit, mem, port_entry_ptr, 10069 OAM_KEY2f, key_type); 10070 key2_ref_count[pp_port] = 1; 10071 } 10072 } else if (oam_key1 == key_type) { 10073 key1_ref_count[pp_port]++; 10074 } else if (oam_key2 == key_type) { 10075 key2_ref_count[pp_port]++ ; 10076 } 10077 } 10078 if (SOC_WARM_BOOT(unit)) { 10079 return rv; 10080 } 10081 rv = soc_mem_write(unit, mem, MEM_BLOCK_ALL, pp_port, port_entry_ptr); 10082 if (BCM_FAILURE(rv)) { 10083 LOG_ERROR(BSL_LS_BCM_OAM, 10084 (BSL_META_U(unit, 10085 "OAM(unit %d) Error: Port table update failed " 10086 "%s.\n"), unit, bcm_errmsg(rv))); 10087 return (rv); 10088 } 10089 } 10090 return rv; 10091 } 10092 10093 /* 10094 * Function: 10095 * _bcm_sb2_oam_port_table_key_update 10096 * Purpose: 10097 * Update port table OAM key fields. 10098 * Parameters: 10099 * unit - (IN) BCM device number 10100 * mem - (IN) PORT_TAB/EGR_PORT 10101 * h_data_p - (IN/OUT) Pointer to endpoint hash data 10102 * Returns: 10103 * BCM_E_XXX 10104 */ 10105 int 10106 _bcm_sb2_oam_port_table_key_update(int unit, soc_mem_t mem, 10107 _bcm_oam_hash_data_t *h_data_p) 10108 { 10109 int rv = BCM_E_NONE; /* Operation return status. */ 10110 bcm_port_t *member_array = NULL; /* Trunk member port array. */ 10111 bcm_module_t module_id; /* Module ID */ 10112 bcm_port_t pp_port = 0; 10113 int member_count = 0; 10114 int local_member_count = 0; 10115 int i = 0; 10116 10117 if ((h_data_p->trunk_id != BCM_TRUNK_INVALID)) { 10118 /* Get count of ports in this trunk. */ 10119 BCM_IF_ERROR_RETURN 10120 (bcm_esw_trunk_get(unit, h_data_p->trunk_id, 10121 NULL, 0, NULL, &member_count)); 10122 if (0 == member_count) { 10123 /* No members have been added to the trunk group yet */ 10124 LOG_ERROR(BSL_LS_BCM_OAM, 10125 (BSL_META_U(unit, 10126 "OAM(unit %d) Error: No local members have been added to " 10127 "the trunk group yet - %s.\n"), unit, bcm_errmsg(rv))); 10128 return BCM_E_PARAM; 10129 } 10130 10131 _BCM_OAM_ALLOC(member_array, bcm_port_t, 10132 sizeof(bcm_port_t) * member_count, "Trunk info"); 10133 if (NULL == member_array) { 10134 return (BCM_E_MEMORY); 10135 10136 } 10137 10138 /* Get a member of the trunk belonging to this module */ 10139 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 10140 h_data_p->trunk_id, 10141 member_count, member_array, 10142 &local_member_count))) { 10143 if (local_member_count > 0) { 10144 for(i = 0; i < local_member_count; i++) { 10145 rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i], 10146 &module_id, &pp_port); 10147 if (BCM_FAILURE(rv)) { 10148 sal_free(member_array); 10149 return (rv); 10150 } 10151 rv = _bcm_sb2_oam_port_table_key_update1(unit, mem, 10152 pp_port, h_data_p); 10153 if (BCM_FAILURE(rv)) { 10154 sal_free(member_array); 10155 return (rv); 10156 } 10157 } 10158 10159 } 10160 } 10161 sal_free(member_array); 10162 } else { 10163 if (mem == PORT_TABm) { 10164 if (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW) { 10165 /* Program OAM_KEY1 in physical and subport port table entries, 10166 * src_pp_port refers to WAR PP port 10167 * dst_pp_port refers to PP port on which UP MEP is configured */ 10168 rv = _bcm_sb2_oam_port_table_key_update1(unit, mem, 10169 h_data_p->dst_pp_port, h_data_p); 10170 if (BCM_FAILURE(rv)) { 10171 return (rv); 10172 } 10173 } 10174 pp_port = h_data_p->src_pp_port; 10175 } else { 10176 pp_port = h_data_p->dst_pp_port; 10177 } 10178 rv = _bcm_sb2_oam_port_table_key_update1(unit, mem, pp_port, h_data_p); 10179 } 10180 return rv; 10181 } 10182 10183 /* 10184 * Function: 10185 * _bcm_sb2_oam_decrement_key_ref_count1 10186 * Purpose: 10187 * Decrement PORT tab key1/key2 usage ref count. 10188 * Parameters: 10189 * unit - (IN) BCM device number 10190 * src_pp_port - (IN) Source PP port 10191 * dst_pp_port - (IN) destination PP port 10192 * h_data_p - (IN) Endpoint hash data. 10193 * Retruns: 10194 * BCM_E_XXX 10195 */ 10196 int 10197 _bcm_sb2_oam_decrement_key_ref_count1(int unit, uint32 src_pp_port, 10198 uint32 dst_pp_port, 10199 _bcm_oam_hash_data_t *h_data_p) 10200 { 10201 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 10202 int rv = BCM_E_NONE; /* Operation return status. */ 10203 port_tab_entry_t port_entry; 10204 egr_port_entry_t egr_port_entry; 10205 int key_type = 0; 10206 uint32 oam_key1 = 0; 10207 uint32 oam_key2 = 0; 10208 int update_entry = 0; 10209 10210 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 10211 /* Set the search key type. */ 10212 _bcm_sb2_oam_key_type_from_endpoint_get(h_data_p->type, h_data_p->flags, 10213 h_data_p->vlan, 10214 h_data_p->inner_vlan, h_data_p->int_flags, 10215 &key_type); 10216 10217 rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, src_pp_port, &port_entry); 10218 if (BCM_FAILURE(rv)) { 10219 LOG_ERROR(BSL_LS_BCM_OAM, 10220 (BSL_META_U(unit, 10221 "OAM(unit %d) Error: Port table entry read failed - %s.\n"), 10222 unit, bcm_errmsg(rv))); 10223 return (rv); 10224 } 10225 rv = soc_mem_read(unit, EGR_PORTm, MEM_BLOCK_ANY, 10226 dst_pp_port, &egr_port_entry); 10227 if (BCM_FAILURE(rv)) { 10228 LOG_ERROR(BSL_LS_BCM_OAM, 10229 (BSL_META_U(unit, 10230 "OAM(unit %d) Error: Port table entry read failed - %s.\n"), 10231 unit, bcm_errmsg(rv))); 10232 return (rv); 10233 } 10234 10235 oam_key1 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY1f); 10236 oam_key2 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY2f); 10237 10238 if (key_type != _BCM_OAM_DOMAIN_PORT) { 10239 if ((MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) || 10240 (BHH_EP_MPLS_SECTION_TYPE(h_data_p))) { 10241 /* Update PORT table */ 10242 soc_PORT_TABm_field32_set(unit, &port_entry, 10243 MPLS_SECTION_OAM_KEYf, 0); 10244 /* Disable section OAM for this port */ 10245 if (BHH_EP_MPLS_SECTION_TYPE(h_data_p)) { 10246 soc_PORT_TABm_field32_set(unit, &port_entry, 10247 MPLS_SECTION_OAM_ENABLEf, 10248 0); 10249 } else if (MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) { 10250 soc_PORT_TABm_field32_set(unit, &port_entry, 10251 MPLS_SECTION_OAM_ENABLEf, 10252 0); 10253 } 10254 BCM_IF_ERROR_RETURN(soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, 10255 src_pp_port, &port_entry)); 10256 10257 /* Update EGR_PORT table */ 10258 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 10259 MPLS_SECTION_OAM_KEYf, 0); 10260 /* Disable section OAM for this port */ 10261 if (BHH_EP_MPLS_SECTION_TYPE(h_data_p)) { 10262 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 10263 MPLS_SECTION_OAM_ENABLEf, 10264 0); 10265 } else if (MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) { 10266 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, 10267 MPLS_SECTION_OAM_ENABLEf, 10268 0); 10269 } 10270 BCM_IF_ERROR_RETURN(soc_mem_write(unit, EGR_PORTm, MEM_BLOCK_ALL, 10271 dst_pp_port, &egr_port_entry)); 10272 } else { 10273 if (key_type == oam_key1) { 10274 oc->oam_key1_ref_count[src_pp_port]--; 10275 if (oc->oam_key1_ref_count[src_pp_port] == 0) { 10276 soc_PORT_TABm_field32_set(unit, &port_entry, OAM_KEY1f, 0); 10277 update_entry = 1; 10278 } 10279 } else if (key_type == oam_key2) { 10280 oc->oam_key2_ref_count[src_pp_port]--; 10281 if (oc->oam_key2_ref_count[src_pp_port] == 0) { 10282 soc_PORT_TABm_field32_set(unit, &port_entry, OAM_KEY2f, 0); 10283 update_entry = 1; 10284 } 10285 } 10286 if (update_entry) { 10287 rv = soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, 10288 src_pp_port, &port_entry); 10289 update_entry = 0; 10290 } 10291 10292 oam_key1 = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, OAM_KEY1f); 10293 oam_key2 = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, OAM_KEY2f); 10294 10295 if (key_type == oam_key1) { 10296 oc->egr_oam_key1_ref_count[dst_pp_port]--; 10297 if (oc->egr_oam_key1_ref_count[dst_pp_port] == 0) { 10298 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, OAM_KEY1f, 0); 10299 update_entry = 1; 10300 } 10301 } else if (key_type == oam_key2) { 10302 oc->egr_oam_key2_ref_count[dst_pp_port]--; 10303 if (oc->egr_oam_key2_ref_count[dst_pp_port] == 0) { 10304 soc_EGR_PORTm_field32_set(unit, &egr_port_entry, OAM_KEY2f, 0); 10305 update_entry = 1; 10306 } 10307 } 10308 if (update_entry) { 10309 rv = soc_mem_write(unit, EGR_PORTm, MEM_BLOCK_ALL, 10310 dst_pp_port, &egr_port_entry); 10311 update_entry = 0; 10312 } 10313 } 10314 } 10315 return rv; 10316 } 10317 10318 /* 10319 * Function: 10320 * _bcm_sb2_oam_decrement_pp_port_key_ref_count1 10321 * Purpose: 10322 * Decrement PORT tab key1/key2 usage ref count. 10323 * Parameters: 10324 * unit - (IN) BCM device number 10325 * src_pp_port - (IN) Source PP port 10326 * h_data_p - (IN) Endpoint hash data. 10327 * Retruns: 10328 * BCM_E_XXX 10329 */ 10330 STATIC int 10331 _bcm_sb2_oam_decrement_pp_port_key_ref_count1(int unit, uint32 src_pp_port, 10332 _bcm_oam_hash_data_t *h_data_p) 10333 { 10334 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 10335 int rv = BCM_E_NONE; /* Operation return status. */ 10336 port_tab_entry_t port_entry; 10337 int key_type = 0; 10338 uint32 oam_key1 = 0; 10339 uint32 oam_key2 = 0; 10340 int update_entry = 0; 10341 10342 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 10343 /* Set the search key type. */ 10344 _bcm_sb2_oam_key_type_from_endpoint_get(h_data_p->type, h_data_p->flags, 10345 h_data_p->vlan, 10346 h_data_p->inner_vlan, h_data_p->int_flags, 10347 &key_type); 10348 10349 rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, src_pp_port, &port_entry); 10350 if (BCM_FAILURE(rv)) { 10351 LOG_ERROR(BSL_LS_BCM_OAM, 10352 (BSL_META_U(unit, 10353 "OAM(unit %d) Error: Port table entry read failed - %s.\n"), 10354 unit, bcm_errmsg(rv))); 10355 return (rv); 10356 } 10357 10358 oam_key1 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY1f); 10359 oam_key2 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY2f); 10360 10361 if (key_type != _BCM_OAM_DOMAIN_PORT) { 10362 if (key_type == oam_key1) { 10363 oc->oam_key1_ref_count[src_pp_port]--; 10364 if (oc->oam_key1_ref_count[src_pp_port] == 0) { 10365 soc_PORT_TABm_field32_set(unit, &port_entry, OAM_KEY1f, 0); 10366 update_entry = 1; 10367 } 10368 } else if (key_type == oam_key2) { 10369 oc->oam_key2_ref_count[src_pp_port]--; 10370 if (oc->oam_key2_ref_count[src_pp_port] == 0) { 10371 soc_PORT_TABm_field32_set(unit, &port_entry, OAM_KEY2f, 0); 10372 update_entry = 1; 10373 } 10374 } 10375 if (update_entry) { 10376 rv = soc_mem_write(unit, PORT_TABm, MEM_BLOCK_ALL, 10377 src_pp_port, &port_entry); 10378 update_entry = 0; 10379 } 10380 } 10381 return rv; 10382 } 10383 10384 /* 10385 * Function: 10386 * _bcm_sb2_oam_decrement_key_ref_count 10387 * Purpose: 10388 * Decrement PORT tab key1/key2 usage ref count. 10389 * Parameters: 10390 * unit - (IN) BCM device number 10391 * h_data_p - (IN) Endpoint hash data. 10392 * Retruns: 10393 * BCM_E_XXX 10394 */ 10395 int 10396 _bcm_sb2_oam_decrement_key_ref_count(int unit, 10397 _bcm_oam_hash_data_t *h_data_p) 10398 { 10399 int rv = BCM_E_NONE; /* Operation return status. */ 10400 bcm_port_t *member_array = NULL; /* Trunk member port array. */ 10401 bcm_module_t module_id; /* Module ID */ 10402 bcm_port_t src_pp_port = 0; 10403 int member_count = 0; 10404 int local_member_count = 0; 10405 int i = 0; 10406 10407 if (h_data_p->trunk_id != BCM_TRUNK_INVALID) { 10408 /* Get count of ports in this trunk. */ 10409 BCM_IF_ERROR_RETURN 10410 (bcm_esw_trunk_get(unit, h_data_p->trunk_id, 10411 NULL, 0, NULL, &member_count)); 10412 if (0 == member_count) { 10413 /* No members have been added to the trunk group yet */ 10414 LOG_ERROR(BSL_LS_BCM_OAM, 10415 (BSL_META_U(unit, 10416 "OAM(unit %d) Error: No local members have been added to " 10417 "the trunk group yet - %s.\n"), unit, bcm_errmsg(rv))); 10418 return BCM_E_PARAM; 10419 } 10420 10421 _BCM_OAM_ALLOC(member_array, bcm_port_t, 10422 sizeof(bcm_port_t) * member_count, "Trunk info"); 10423 if (NULL == member_array) { 10424 return (BCM_E_MEMORY); 10425 10426 } 10427 10428 /* Get a member of the trunk belonging to this module */ 10429 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 10430 h_data_p->trunk_id, 10431 member_count, member_array, 10432 &local_member_count))) { 10433 if (local_member_count > 0) { 10434 for(i = 0; i < local_member_count; i++) { 10435 rv = _bcm_kt2_pp_port_to_modport_get(unit, member_array[i], 10436 &module_id, &src_pp_port); 10437 if (BCM_FAILURE(rv)) { 10438 sal_free(member_array); 10439 return (rv); 10440 } 10441 rv = _bcm_sb2_oam_decrement_key_ref_count1(unit, src_pp_port, 10442 h_data_p->dst_pp_port, h_data_p); 10443 if (BCM_FAILURE(rv)) { 10444 sal_free(member_array); 10445 return (rv); 10446 } 10447 } 10448 10449 } 10450 } 10451 sal_free(member_array); 10452 } else { 10453 if (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW) { 10454 /* Reset OAM_KEY1 in physical and subport port table entries, 10455 * src_pp_port refers to WAR PP port 10456 * dst_pp_port refers to PP port on which UP MEP is configured */ 10457 rv = _bcm_sb2_oam_decrement_pp_port_key_ref_count1(unit, 10458 h_data_p->dst_pp_port, h_data_p); 10459 if (BCM_FAILURE(rv)) { 10460 return (rv); 10461 } 10462 } 10463 10464 rv = _bcm_sb2_oam_decrement_key_ref_count1(unit, h_data_p->src_pp_port, 10465 h_data_p->dst_pp_port, h_data_p); 10466 } 10467 return rv; 10468 } 10469 10470 10471 10472 /* 10473 * Function: _bcm_sb2_oam_tpid_decrement_ref_count 10474 * 10475 * Purpose: 10476 * Decrement TPID reference count. 10477 * Parameters: 10478 * unit - (IN) BCM device number 10479 * h_data_p - (IN) Endpoint hash data. 10480 * Retruns: 10481 * BCM_E_XXX 10482 */ 10483 STATIC int 10484 _bcm_sb2_oam_tpid_decrement_ref_count(int unit, _bcm_oam_hash_data_t *h_data_p) 10485 { 10486 int rv = BCM_E_NONE; 10487 uint32 tag_type = 0; 10488 10489 /* If local CCM tx generation was not enabled, then the tpid entries 10490 * would not have been set. So do not try to delete them even though the 10491 * h_data_p->outer/inner/subport_tpid has a non zero value */ 10492 if (!h_data_p->local_tx_enabled) { 10493 return BCM_E_NONE; 10494 } 10495 10496 if (_BCM_OAM_EP_IS_ETH_OAM_VP_TYPE(h_data_p)) { 10497 if(h_data_p->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) { 10498 tag_type = _BCM_OAM_DOMAIN_S_PLUS_CVLAN; 10499 } else if (h_data_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) { 10500 tag_type =_BCM_OAM_DOMAIN_CVLAN; 10501 } else if (h_data_p->vlan > 0) { 10502 tag_type =_BCM_OAM_DOMAIN_SVLAN; 10503 } 10504 } else { 10505 tag_type =h_data_p->oam_domain; 10506 } 10507 10508 /* if S or S+C vlan - set outer tpid index */ 10509 if (((tag_type == _BCM_OAM_DOMAIN_SVLAN) || 10510 (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN) 10511 ) && 10512 (h_data_p->outer_tpid > 0)) { 10513 if (BCM_SUCCESS(rv)) { 10514 rv = _bcm_sb2_tpid_entry_delete(unit, 10515 h_data_p->outer_tpid_profile_index, 10516 BCM_OAM_TPID_TYPE_OUTER); 10517 if (BCM_FAILURE(rv)) { 10518 LOG_ERROR(BSL_LS_BCM_OAM, 10519 (BSL_META_U(unit, 10520 "OAM(unit %d) Error: L3 entry config failed in Outer TPID " 10521 "decrement ref count"" %s.\n"), unit, bcm_errmsg(rv))); 10522 return (rv); 10523 } 10524 } 10525 } 10526 if (((tag_type == _BCM_OAM_DOMAIN_CVLAN) || 10527 (tag_type == _BCM_OAM_DOMAIN_S_PLUS_CVLAN) 10528 ) && 10529 (h_data_p->inner_tpid > 0)) { 10530 /* C or S+C */ 10531 if (BCM_SUCCESS(rv)) { 10532 rv = _bcm_sb2_tpid_entry_delete(unit, 10533 h_data_p->inner_tpid_profile_index, 10534 BCM_OAM_TPID_TYPE_INNER); 10535 if (BCM_FAILURE(rv)) { 10536 LOG_ERROR(BSL_LS_BCM_OAM, 10537 (BSL_META_U(unit, 10538 "OAM(unit %d) Error: L3 entry config failed in Inner TPID " 10539 "decrement ref count"" %s.\n"), unit, bcm_errmsg(rv))); 10540 return (rv); 10541 } 10542 } 10543 } 10544 if ((BCM_GPORT_IS_SUBPORT_PORT(h_data_p->gport)) && 10545 (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, h_data_p->gport)) && 10546 (h_data_p->subport_tpid > 0)) { 10547 /* CoE port */ 10548 if (BCM_SUCCESS(rv)) { 10549 rv = _bcm_sb2_tpid_entry_delete(unit, 10550 h_data_p->subport_tpid_profile_index, 10551 BCM_OAM_TPID_TYPE_SUBPORT); 10552 if (BCM_FAILURE(rv)) { 10553 LOG_ERROR(BSL_LS_BCM_OAM, 10554 (BSL_META_U(unit, 10555 "OAM(unit %d) Error: L3 entry config failed in Subport TPID " 10556 "decrement ref count"" %s.\n"), unit, bcm_errmsg(rv))); 10557 return (rv); 10558 } 10559 } 10560 } 10561 return rv; 10562 } 10563 10564 /* 10565 * Function: 10566 * _bcm_sb2_oam_endpoint_destroy 10567 * Purpose: 10568 * Delete an endpoint and free all its allocated resources. 10569 * Parameters: 10570 * unit - (IN) BCM device number 10571 * ep_id - (IN) Endpoint ID value. 10572 * Retruns: 10573 * BCM_E_XXX 10574 */ 10575 STATIC int 10576 _bcm_sb2_oam_endpoint_destroy(int unit, 10577 bcm_oam_endpoint_t ep_id) 10578 { 10579 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 10580 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint data. */ 10581 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 10582 bcm_oam_endpoint_info_t ep_info; /* Endpoint information. */ 10583 _bcm_oam_hash_data_t h_data; /* Pointer to endpoint data. */ 10584 int rv; /* Operation return status. */ 10585 #if defined(INCLUDE_BHH) 10586 uint16 reply_len; 10587 bcm_oam_endpoint_t bhh_pool_ep_id; 10588 #endif 10589 10590 /* Lock already taken by the calling routine. */ 10591 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 10592 10593 /* Get the hash data pointer. */ 10594 h_data_p = &oc->oam_hash_data[ep_id]; 10595 if(0 == h_data_p->in_use){ 10596 return BCM_E_NOT_FOUND; 10597 } 10598 rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p); 10599 if (BCM_FAILURE(rv)) { 10600 LOG_ERROR(BSL_LS_BCM_OAM, 10601 (BSL_META_U(unit, 10602 "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) -" 10603 " %s.\n"), unit, ep_id, bcm_errmsg(rv))); 10604 return (rv); 10605 } 10606 #if defined(INCLUDE_MPLS_LM_DM) 10607 /* If endpoint is MPLS_LM_DM type and loss/Delay is enabled on the same, 10608 Free the UKernel session first */ 10609 if (!SOC_WARM_BOOT(unit)) { 10610 if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 10611 if (h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED) { 10612 _bcm_sb2_mpls_lm_dm_loss_delete(unit, h_data_p); 10613 } 10614 if (h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED) { 10615 _bcm_sb2_mpls_lm_dm_delay_delete(unit, h_data_p); 10616 } 10617 } 10618 } 10619 #endif 10620 10621 #if defined(INCLUDE_ETH_LM_DM) 10622 /* If endpoint is MPLS_LM_DM type and loss/Delay is enabled on the same, 10623 Free the UKernel session first */ 10624 if (!SOC_WARM_BOOT(unit)) { 10625 if (h_data_p->type == bcmOAMEndpointTypeEthernet) { 10626 if (h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_LM_IS_SET) { 10627 _bcm_sb2_eth_lm_dm_loss_delete(unit, oc, h_data_p); 10628 } 10629 if (h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_DM_IS_SET) { 10630 _bcm_sb2_eth_lm_dm_delay_delete(unit, oc, h_data_p); 10631 } 10632 } 10633 } 10634 #endif 10635 10636 /* Calling it commonly for MPLS LM/DM and BHH endpoints */ 10637 10638 if ((MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) || 10639 (h_data_p->type == bcmOAMEndpointTypeBHHMPLS)) { 10640 /* For rx disable the mpls oam for the label. */ 10641 10642 /* First check if the label is in l3 tunnel table and disable 10643 MPLS OAM if true. */ 10644 rv = _bcm_sb2_oam_mpls_lsp_check_l3_tunnel_table_downmep_enable(unit, 10645 h_data_p, 0); 10646 if (rv == BCM_E_NOT_FOUND) { 10647 /* If not found in L3 tunnel, find and update it in MPLS_ENTRY 10648 table */ 10649 rv = _bcm_sb2_oam_mpls_lsp_mpls_table_downmep_enable(unit, 10650 h_data_p, 0); 10651 /* This is called during de-init. MPLS module de-init happens before 10652 * OAM de-init. So if it is not found, do not return error. 10653 */ 10654 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 10655 LOG_ERROR(BSL_LS_BCM_OAM, 10656 (BSL_META_U(unit, 10657 "OAM(unit %d) Error: MPLS table update failed (EP=%d) - %s.\n"), 10658 unit, h_data_p->ep_id, bcm_errmsg(rv))); 10659 return (rv); 10660 } 10661 } else if (rv != BCM_E_NONE) { 10662 LOG_ERROR(BSL_LS_BCM_OAM, 10663 (BSL_META_U(unit, 10664 "OAM(unit %d) Error: L3 tunnel table update failed (EP=%d) - %s.\n"), 10665 unit, h_data_p->ep_id, bcm_errmsg(rv))); 10666 return (rv); 10667 } 10668 /* For tx disable the mpls oam for the egress intf. 10669 and write the mepid in egr_l3_next_hop table */ 10670 rv = _bcm_sb2_oam_mpls_lsp_egr_l3_nxt_hop_downmep_enable(unit, 10671 h_data_p, 0); 10672 if (BCM_FAILURE(rv)) { 10673 LOG_ERROR(BSL_LS_BCM_OAM, 10674 (BSL_META_U(unit, 10675 "OAM(unit %d) Error: EGR_L3_NEXT_HOP table update failed (EP=%d) - %s.\n"), 10676 unit, h_data_p->ep_id, bcm_errmsg(rv))); 10677 return (rv); 10678 } 10679 } else if (MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p)) { 10680 rv = _bcm_sb2_oam_mpls_pw_svp_table_downmep_enable(unit, 10681 h_data_p, 0); 10682 /* This is called during de-init. MPLS module de-init happens before 10683 * OAM de-init. So if it is not found, do not return error. 10684 */ 10685 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 10686 LOG_ERROR(BSL_LS_BCM_OAM, 10687 (BSL_META_U(unit, 10688 "OAM(unit %d) Error: SVP table update failed (EP=%d) - %s.\n"), 10689 unit, h_data_p->ep_id, bcm_errmsg(rv))); 10690 return (rv); 10691 } 10692 /* For tx disable the mpls oam for the egress dvp. 10693 */ 10694 rv = _bcm_sb2_oam_mpls_pw_egr_dvp_downmep_enable(unit, h_data_p, 0); 10695 if (BCM_FAILURE(rv)) { 10696 LOG_ERROR(BSL_LS_BCM_OAM, 10697 (BSL_META_U(unit, 10698 "OAM(unit %d) Error: EGR_L3_NEXT_HOP table update failed (EP=%d) - %s.\n"), 10699 unit, h_data_p->ep_id, bcm_errmsg(rv))); 10700 return (rv); 10701 } 10702 } else if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 10703 rv = _bcm_sb2_oam_mpls_lsp_mpls_table_downmep_enable(unit, 10704 h_data_p, 0); 10705 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 10706 LOG_ERROR(BSL_LS_BCM_OAM, 10707 (BSL_META_U(unit, 10708 "OAM(unit %d) Error: MPLS table update failed (EP=%d) - %s.\n"), 10709 unit, h_data_p->ep_id, bcm_errmsg(rv))); 10710 return (rv); 10711 } 10712 /* For tx disable the mpls oam for the egress dvp. 10713 */ 10714 rv = _bcm_sb2_oam_mpls_pw_egr_dvp_downmep_enable(unit, h_data_p, 0); 10715 if (BCM_FAILURE(rv)) { 10716 LOG_ERROR(BSL_LS_BCM_OAM, 10717 (BSL_META_U(unit, 10718 "OAM(unit %d) Error: EGR_L3_NEXT_HOP table update failed (EP=%d) - %s.\n"), 10719 unit, h_data_p->ep_id, bcm_errmsg(rv))); 10720 return (rv); 10721 } 10722 } 10723 if(bcmOAMEndpointTypeEthernet == h_data_p->type || 10724 (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p))) 10725 { 10726 10727 if ((h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE) && 10728 (!MPLS_LM_DM_ENDPOINT_TYPE(h_data_p))) { 10729 BCM_IF_ERROR_RETURN 10730 (_bcm_sb2_oam_remote_endpoint_delete(unit, h_data_p)); 10731 10732 } else { 10733 BCM_IF_ERROR_RETURN 10734 (_bcm_sb2_oam_local_endpoint_delete(unit, h_data_p)); 10735 if (bcmOAMEndpointTypeEthernet == h_data_p->type) { 10736 /* decrement TPID ref count */ 10737 BCM_IF_ERROR_RETURN 10738 (_bcm_sb2_oam_tpid_decrement_ref_count(unit, h_data_p)); 10739 } 10740 } 10741 10742 /* Remove endpoint for group's endpoint list. */ 10743 rv = _bcm_sb2_oam_group_ep_list_remove(unit, h_data_p->group_index, 10744 h_data_p->ep_id); 10745 if (BCM_FAILURE(rv)) { 10746 LOG_ERROR(BSL_LS_BCM_OAM, 10747 (BSL_META_U(unit, 10748 "OAM(unit %d) Error: Remove from group list (EP=%d) -" 10749 " %s.\n"), unit, ep_id, bcm_errmsg(rv))); 10750 return (rv); 10751 } 10752 10753 /* Return ID back to free MEP ID pool.*/ 10754 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->mep_pool, ep_id)); 10755 10756 /* Decrement PORT tab key1/key2 usage ref count */ 10757 if (!(h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE) && 10758 !(MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p) || 10759 MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p))) { 10760 BCM_IF_ERROR_RETURN 10761 (_bcm_sb2_oam_decrement_key_ref_count(unit, h_data_p)); 10762 } 10763 10764 /* Initialize endpoint info structure. */ 10765 bcm_oam_endpoint_info_t_init(&ep_info); 10766 10767 /* Set up endpoint information for key construction. */ 10768 ep_info.group = h_data_p->group_index; 10769 ep_info.name = h_data_p->name; 10770 ep_info.gport = h_data_p->gport; 10771 ep_info.level = h_data_p->level; 10772 ep_info.vlan = h_data_p->vlan; 10773 ep_info.inner_vlan = h_data_p->inner_vlan; 10774 ep_info.flags = h_data_p->flags; 10775 if (!(MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p))) { 10776 ep_info.mpls_label = h_data_p->label; 10777 } 10778 ep_info.type = h_data_p->type; 10779 10780 /* Construct hash key for lookup + delete operation. */ 10781 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key); 10782 10783 /* Remove entry from hash table. */ 10784 BCM_IF_ERROR_RETURN(shr_htb_find(oc->ma_mep_htbl, hash_key, 10785 (shr_htb_data_t *)&h_data, 10786 1)); 10787 10788 /* Clear the hash data memory previously occupied by this endpoint. */ 10789 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 10790 } 10791 /* 10792 * BHH specific 10793 */ 10794 else if (soc_feature(unit, soc_feature_bhh) && 10795 (BHH_EP_TYPE(h_data_p))) { 10796 #if defined(INCLUDE_BHH) 10797 10798 if (h_data_p->is_remote) { 10799 /* 10800 * BHH uses same index for local and remote. So, delete always goes through 10801 * local endpoint destory 10802 */ 10803 return (BCM_E_NONE); 10804 } else { 10805 10806 bhh_pool_ep_id = BCM_OAM_BHH_GET_UKERNEL_EP(ep_id); 10807 if ((!SOC_WARM_BOOT(unit)) && (oc->ukernel_not_ready == 0)) { 10808 /* Send BHH Session Delete message to uC. Error response is not an 10809 during switch re-init as uKernel is reloaded and its state is 10810 cleared before oam init. As such endpoint wont exist during oam init*/ 10811 if (!(h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) { 10812 _bcm_sb2_oam_bhh_msg_send_receive(unit, 10813 MOS_MSG_SUBCLASS_BHH_SESS_DELETE, 10814 (int)bhh_pool_ep_id, 0, 10815 MOS_MSG_SUBCLASS_BHH_SESS_DELETE_REPLY, 10816 &reply_len); 10817 } 10818 } 10819 rv = _bcm_sb2_oam_local_endpoint_delete(unit, h_data_p); 10820 if (BCM_FAILURE(rv)) { 10821 LOG_ERROR(BSL_LS_BCM_OAM, 10822 (BSL_META_U(unit, 10823 "OAM(unit %d) Error:BHH local_endpoint_delete failled " 10824 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 10825 return (rv); 10826 } 10827 h_data_p->in_use = 0; 10828 10829 10830 /* Remove endpoint for group's endpoint list. */ 10831 rv = _bcm_sb2_oam_group_ep_list_remove(unit, h_data_p->group_index, 10832 h_data_p->ep_id); 10833 if (BCM_FAILURE(rv)) { 10834 LOG_ERROR(BSL_LS_BCM_OAM, 10835 (BSL_META_U(unit, 10836 "OAM(unit %d) Error: Remove from group list (EP=%d) -" 10837 " %s.\n"), unit, ep_id, bcm_errmsg(rv))); 10838 return (rv); 10839 } 10840 10841 10842 /* Return ID back to free MEP ID pool.*/ 10843 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_id)); 10844 10845 /* Set up endpoint information for key construction. */ 10846 ep_info.group = h_data_p->group_index; 10847 ep_info.name = h_data_p->name; 10848 ep_info.gport = h_data_p->gport; 10849 ep_info.level = h_data_p->level; 10850 ep_info.vlan = h_data_p->vlan; 10851 ep_info.inner_vlan = h_data_p->inner_vlan; 10852 ep_info.flags = h_data_p->flags; 10853 ep_info.mpls_label = h_data_p->label; 10854 ep_info.type = h_data_p->type; 10855 10856 /* Construct hash key for lookup + delete operation. */ 10857 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key); 10858 10859 /* Remove entry from hash table. */ 10860 BCM_IF_ERROR_RETURN(shr_htb_find(oc->ma_mep_htbl, hash_key, 10861 (shr_htb_data_t *)&h_data, 10862 1)); 10863 10864 /* Clear the hash data memory previously occupied by this endpoint. */ 10865 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 10866 10867 } 10868 #else 10869 return (BCM_E_UNAVAIL); 10870 #endif /* INCLUDE_BHH */ 10871 } 10872 else { 10873 return (BCM_E_PARAM); 10874 } 10875 return (BCM_E_NONE); 10876 } 10877 10878 /* 10879 * Function: 10880 * _bcm_sb2_oam_group_endpoints_destroy 10881 * Purpose: 10882 * Delete all endpoints associated with a group and free all 10883 * resources allocated by these endpoints. 10884 * Parameters: 10885 * unit - (IN) BCM device number 10886 * g_info_p - (IN) Pointer to group information 10887 * Retruns: 10888 * BCM_E_XXX 10889 */ 10890 STATIC int 10891 _bcm_sb2_oam_group_endpoints_destroy(int unit, 10892 _bcm_oam_group_data_t *g_info_p) 10893 { 10894 bcm_oam_endpoint_t ep_id; /* Endpoint ID. */ 10895 _bcm_oam_ep_list_t *cur; /* Pointer to endpoint list node. */ 10896 int rv; /* Operation return status. */ 10897 10898 if (NULL == g_info_p) { 10899 return (BCM_E_INTERNAL); 10900 } 10901 10902 /* Get the endpoint list head pointer. */ 10903 cur = *(g_info_p->ep_list); 10904 if (NULL == cur) { 10905 LOG_DEBUG(BSL_LS_BCM_OAM, 10906 (BSL_META_U(unit, 10907 "OAM(unit %d) Info: No endpoints in group.\n"), 10908 unit)); 10909 return (BCM_E_NONE); 10910 } 10911 10912 while (NULL != cur) { 10913 ep_id = cur->ep_data_p->ep_id; 10914 10915 LOG_DEBUG(BSL_LS_BCM_OAM, 10916 (BSL_META_U(unit, 10917 "OAM(unit %d) Info: GID=%d EP:%d.\n"), 10918 unit, cur->ep_data_p->group_index, ep_id)); 10919 10920 cur = cur->next; 10921 10922 rv = _bcm_sb2_oam_endpoint_destroy(unit, ep_id); 10923 if (BCM_FAILURE(rv)) { 10924 LOG_ERROR(BSL_LS_BCM_OAM, 10925 (BSL_META_U(unit, 10926 "OAM(unit %d) Error: Endpoint destroy (EP=%d) - " 10927 "%s.\n"), unit, ep_id, bcm_errmsg(rv))); 10928 return (rv); 10929 } 10930 } 10931 10932 return (BCM_E_NONE); 10933 } 10934 10935 /* 10936 * Function: 10937 * _bcm_sb2_oam_endpoint_gport_resolve 10938 * Purpose: 10939 * Resolve an endpoint GPORT value to SGLP and DGLP value. 10940 * Parameters: 10941 * unit - (IN) BCM device number 10942 * ep_info_p - (IN/OUT) Pointer to endpoint information. 10943 * src_glp - (IN/OUT) Pointer to source generic logical port value. 10944 * dst_glp - (IN/OUT) Pointer to destination generic logical port value. 10945 * src_pp_port- (IN/OUT) Pointer to source pp port value. 10946 * dst_pp_port- (IN/OUT) Pointer to destination pp port value. 10947 * svp - (IN/OUT) Pointer to VP value 10948 * trunk_id - (IN/OUT) Pointer to trunk id 10949 * is_vp_valid - (OUT) VP is valid or not 10950 * Retruns: 10951 * BCM_E_XXX 10952 */ 10953 STATIC int 10954 _bcm_sb2_oam_endpoint_gport_resolve(int unit, 10955 bcm_oam_endpoint_info_t *ep_info_p, 10956 uint32 *src_glp, 10957 uint32 *dst_glp, 10958 bcm_port_t *src_pp_port, 10959 bcm_port_t *dst_pp_port, 10960 uint32 *svp, 10961 bcm_trunk_t *trunk_id, 10962 int *is_vp_valid, 10963 bcm_trunk_member_t *trunk_member) 10964 { 10965 bcm_module_t module_id; /* Module ID */ 10966 bcm_port_t port_id; /* Port ID. */ 10967 bcm_port_t port = 0; /* Port ID. */ 10968 int local_id; /* Hardware ID. */ 10969 int tx_enabled = 0; /* CCM Tx enabled. */ 10970 bcm_trunk_info_t trunk_info; /* Trunk information. */ 10971 bcm_trunk_member_t *member_array = NULL; /* Trunk member array. */ 10972 int member_count = 0; /* Trunk Member count. */ 10973 int rv = BCM_E_NONE; /* Return status. */ 10974 uint8 glp_valid = 0; /* Logical port valid. */ 10975 int local_member_count = 0; 10976 bcm_trunk_t tid = BCM_TRUNK_INVALID; 10977 int is_local = 0; 10978 uint8 is_port_mep = 0; 10979 10980 is_port_mep = ((ep_info_p->vlan == 0) && (ep_info_p->inner_vlan == 0)); 10981 /* Get Trunk ID or (Modid + Port) value from Gport */ 10982 BCM_IF_ERROR_RETURN 10983 (_bcm_esw_gport_resolve(unit, ep_info_p->gport, &module_id, 10984 &port_id, trunk_id, &local_id)); 10985 10986 /* Set CCM endpoint Tx status only for local endpoints. */ 10987 if (!(ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE)) { 10988 tx_enabled 10989 = (ep_info_p->ccm_period 10990 != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) ? 1 : 0; 10991 } 10992 10993 /* 10994 * If Gport is Trunk type, _bcm_esw_gport_resolve() 10995 * sets trunk_id. Using Trunk ID, get Dst Modid and Port value. 10996 */ 10997 if (BCM_GPORT_IS_TRUNK(ep_info_p->gport)) { 10998 10999 if (BCM_TRUNK_INVALID == *trunk_id) { 11000 /* Has to be a valid Trunk. */ 11001 return (BCM_E_PARAM); 11002 } 11003 11004 /* Construct Hw SGLP value. */ 11005 _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 1, *trunk_id, 11006 *src_glp); 11007 11008 /* Get a member of the trunk belonging to this module */ 11009 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, *trunk_id, 1, 11010 &port_id, 11011 &local_member_count))) { 11012 if(local_member_count) { 11013 BCM_IF_ERROR_RETURN 11014 (_bcm_kt2_pp_port_to_modport_get(unit, port_id, 11015 &module_id, &port)); 11016 *src_pp_port = port_id; 11017 } 11018 } 11019 /* 11020 * CCM Tx is enabled on a trunk member port. 11021 * trunk_index value is required to derive the Modid and Port info. 11022 */ 11023 if (1 == tx_enabled 11024 && _BCM_OAM_INVALID_INDEX == ep_info_p->trunk_index) { 11025 /* Invalid Trunk member index passed. */ 11026 return (BCM_E_PORT); 11027 } 11028 11029 /* Get count of ports in this trunk. */ 11030 BCM_IF_ERROR_RETURN 11031 (bcm_esw_trunk_get(unit, *trunk_id, NULL, 0, NULL, &member_count)); 11032 if (0 == member_count) { 11033 /* No members have been added to the trunk group yet */ 11034 return BCM_E_PARAM; 11035 } 11036 11037 _BCM_OAM_ALLOC(member_array, bcm_trunk_member_t, 11038 sizeof(bcm_trunk_member_t) * member_count, "Trunk info"); 11039 if (NULL == member_array) { 11040 return (BCM_E_MEMORY); 11041 } 11042 11043 /* Get Trunk Info for the Trunk ID. */ 11044 rv = bcm_esw_trunk_get(unit, *trunk_id, &trunk_info, member_count, 11045 member_array, &member_count); 11046 if (BCM_FAILURE(rv)) { 11047 sal_free(member_array); 11048 return (rv); 11049 } 11050 11051 /* Check if the input trunk_index is valid. */ 11052 if (ep_info_p->trunk_index >= member_count) { 11053 sal_free(member_array); 11054 return BCM_E_PARAM; 11055 } 11056 11057 /* Get the Modid and Port value using Trunk Index value. */ 11058 rv = _bcm_esw_gport_resolve 11059 (unit, member_array[ep_info_p->trunk_index].gport, 11060 &module_id, &port_id, &tid, &local_id); 11061 if (BCM_FAILURE(rv)) { 11062 sal_free(member_array); 11063 return (rv); 11064 } 11065 11066 sal_free(member_array); 11067 11068 /* Construct Hw DGLP value. */ 11069 _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1, 11070 *dst_glp); 11071 11072 /* Get HW PP port */ 11073 BCM_IF_ERROR_RETURN 11074 (_bcm_kt2_modport_to_pp_port_get(unit, module_id, port_id, 11075 dst_pp_port)); 11076 *dst_glp = *src_glp; 11077 glp_valid = 1; 11078 11079 *trunk_member = member_array[ep_info_p->trunk_index]; 11080 } 11081 11082 /* 11083 * Application can resolve the trunk and pass the desginated 11084 * port as Gport value. Check if the Gport belongs to a trunk. 11085 */ 11086 if ((BCM_TRUNK_INVALID == (*trunk_id)) 11087 && (BCM_GPORT_IS_MODPORT(ep_info_p->gport) 11088 || BCM_GPORT_IS_LOCAL(ep_info_p->gport))) { 11089 11090 /* When Gport is ModPort or Port type, _bcm_esw_gport_resolve() 11091 * returns Modid and Port value. Use these values to make the DGLP 11092 * value. 11093 */ 11094 _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1, 11095 *dst_glp); 11096 11097 /* get destination PP port */ 11098 BCM_IF_ERROR_RETURN 11099 (_bcm_kt2_modport_to_pp_port_get(unit, module_id, port_id, 11100 dst_pp_port)); 11101 11102 /* Use the Modid, Port value and determine if the port 11103 * belongs to a Trunk. 11104 */ 11105 if (!is_port_mep) { 11106 /* Dont find all other trunk members if it is a port mep */ 11107 rv = bcm_esw_trunk_find(unit, module_id, port_id, trunk_id); 11108 } 11109 if (BCM_SUCCESS(rv) && !is_port_mep) { 11110 /* 11111 * Port is member of a valid trunk. 11112 * Now create the SGLP value from Trunk ID. 11113 */ 11114 /* Get a member of the trunk belonging to this module */ 11115 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, *trunk_id, 1, 11116 &port_id, 11117 &local_member_count))) { 11118 if(local_member_count) { 11119 BCM_IF_ERROR_RETURN 11120 (_bcm_kt2_pp_port_to_modport_get(unit, port_id, 11121 &module_id, &port)); 11122 *src_pp_port = port_id; 11123 } 11124 11125 _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port, 1, 11126 *trunk_id, *src_glp); 11127 *dst_glp = *src_glp; 11128 } else { 11129 *src_pp_port = *dst_pp_port; 11130 } 11131 } else { 11132 /* Port not a member of trunk. DGLP and SGLP are the same. */ 11133 *src_glp = *dst_glp; 11134 *src_pp_port = *dst_pp_port; 11135 } 11136 glp_valid = 1; 11137 } 11138 if ((SOC_GPORT_IS_MIM_PORT(ep_info_p->gport)) || 11139 (SOC_GPORT_IS_MPLS_PORT(ep_info_p->gport)) || 11140 (SOC_GPORT_IS_VLAN_PORT(ep_info_p->gport))) { 11141 *svp = local_id; 11142 if(BCM_TRUNK_INVALID != (*trunk_id)){ 11143 11144 /* Construct Hw SGLP value. */ 11145 _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 1, *trunk_id, 11146 *src_glp); 11147 11148 /* Get a member of the trunk belonging to this module */ 11149 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, *trunk_id, 1, 11150 &port_id, 11151 &local_member_count))) { 11152 if(local_member_count) { 11153 BCM_IF_ERROR_RETURN 11154 (_bcm_kt2_pp_port_to_modport_get(unit, port_id, 11155 &module_id, &port)); 11156 *src_pp_port = port_id; 11157 } 11158 } 11159 /* 11160 * CCM Tx is enabled on a trunk member port. 11161 * trunk_index value is required to derive the Modid and Port info. 11162 */ 11163 if (1 == tx_enabled 11164 && _BCM_OAM_INVALID_INDEX == ep_info_p->trunk_index) { 11165 /* Invalid Trunk member index passed. */ 11166 return (BCM_E_PORT); 11167 } 11168 /* Get count of ports in this trunk. */ 11169 BCM_IF_ERROR_RETURN 11170 (bcm_esw_trunk_get(unit, *trunk_id, NULL, 0, NULL, &member_count)); 11171 if (0 == member_count) { 11172 /* No members have been added to the trunk group yet */ 11173 return BCM_E_PARAM; 11174 } 11175 11176 _BCM_OAM_ALLOC(member_array, bcm_trunk_member_t, 11177 sizeof(bcm_trunk_member_t) * member_count, "Trunk info"); 11178 if (NULL == member_array) { 11179 return (BCM_E_MEMORY); 11180 } 11181 11182 /* Get Trunk Info for the Trunk ID. */ 11183 rv = bcm_esw_trunk_get(unit, *trunk_id, &trunk_info, member_count, 11184 member_array, &member_count); 11185 if (BCM_FAILURE(rv)) { 11186 sal_free(member_array); 11187 return (rv); 11188 } 11189 11190 /* Check if the input trunk_index is valid. */ 11191 if (ep_info_p->trunk_index >= member_count) { 11192 sal_free(member_array); 11193 return BCM_E_PARAM; 11194 } 11195 11196 /* Get the Modid and Port value using Trunk Index value. */ 11197 rv = _bcm_esw_gport_resolve 11198 (unit, member_array[ep_info_p->trunk_index].gport, 11199 &module_id, &port_id, &tid, &local_id); 11200 if (BCM_FAILURE(rv)) { 11201 sal_free(member_array); 11202 return (rv); 11203 } 11204 11205 sal_free(member_array); 11206 11207 /* Construct Hw DGLP value. */ 11208 _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1, 11209 *dst_glp); 11210 11211 /* Get HW PP port */ 11212 BCM_IF_ERROR_RETURN 11213 (_bcm_kt2_modport_to_pp_port_get(unit, module_id, port_id, 11214 dst_pp_port)); 11215 *dst_glp = *src_glp; 11216 11217 *trunk_member = member_array[ep_info_p->trunk_index]; 11218 11219 }else { 11220 rv = _bcm_esw_modid_is_local(unit, module_id, &is_local); 11221 if(BCM_SUCCESS(rv) && (is_local)) { 11222 _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, 11223 -1, *dst_glp); 11224 *src_glp = *dst_glp; 11225 /* get destination PP port */ 11226 BCM_IF_ERROR_RETURN 11227 (_bcm_kt2_modport_to_pp_port_get(unit, module_id, port_id, 11228 dst_pp_port)); 11229 *src_pp_port = *dst_pp_port; 11230 } 11231 } 11232 glp_valid = 1; 11233 *is_vp_valid = 1; 11234 } 11235 11236 /* LinkPhy/CoE case */ 11237 if ((BCM_GPORT_IS_SUBPORT_PORT(ep_info_p->gport))) { 11238 if ((_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, ep_info_p->gport)) || 11239 (_BCM_KT2_GPORT_IS_LINKPHY_SUBPORT_PORT(unit, ep_info_p->gport))) { 11240 BCM_IF_ERROR_RETURN 11241 (_bcm_kt2_modport_to_pp_port_get(unit, module_id, port_id, 11242 dst_pp_port)); 11243 *src_pp_port = *dst_pp_port; 11244 _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port_id, 0, -1, 11245 *dst_glp); 11246 /* Use the Modid, Port value and determine if the port 11247 * belongs to a Trunk. 11248 */ 11249 if (!is_port_mep) { 11250 rv = bcm_esw_trunk_find(unit, module_id, port_id, trunk_id); 11251 } 11252 if (BCM_SUCCESS(rv) && !is_port_mep) { 11253 /* 11254 * Port is member of a valid trunk. 11255 * Now create the SGLP value from Trunk ID. 11256 */ 11257 /* Get a member of the trunk belonging to this module */ 11258 if (BCM_SUCCESS(_bcm_esw_trunk_local_members_get(unit, 11259 *trunk_id, 1, 11260 &port_id, 11261 &local_member_count))) { 11262 if(local_member_count) { 11263 BCM_IF_ERROR_RETURN 11264 (_bcm_kt2_pp_port_to_modport_get(unit, port_id, 11265 &module_id, &port)); 11266 *src_pp_port = port_id; 11267 } 11268 _BCM_SB2_OAM_MOD_PORT_TO_GLP(unit, module_id, port, 1, 11269 *trunk_id, *src_glp); 11270 *dst_glp = *src_glp; 11271 } 11272 } else { 11273 *src_glp = *dst_glp; 11274 } 11275 glp_valid = 1; 11276 } 11277 } 11278 11279 /* 11280 * At this point, both src_glp and dst_glp should be valid. 11281 * Gport types other than TRUNK, MODPORT or LOCAL are not valid. 11282 */ 11283 if (0 == glp_valid) { 11284 return (BCM_E_PORT); 11285 } 11286 return (BCM_E_NONE); 11287 } 11288 11289 /* 11290 * Function: 11291 * _bcm_sb2_oam_mepid_validate 11292 * Purpose: 11293 * Validate an endpoint MEP id. 11294 * Parameters: 11295 * unit - (IN) BCM device number 11296 * ep_info_p - (IN) Pointer to endpoint information. 11297 * Retruns: 11298 * BCM_E_XXX 11299 */ 11300 STATIC int 11301 _bcm_sb2_oam_mepid_validate(int unit, 11302 bcm_oam_endpoint_info_t *ep_info_p) 11303 { 11304 _bcm_oam_control_t *oc; 11305 _bcm_oam_group_data_t *group_p; /* Pointer to group list. */ 11306 _bcm_oam_ep_list_t *cur; /* Current head node pointer. */ 11307 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 11308 11309 /* Get OAM control structure. */ 11310 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 11311 11312 /* Get the group memory pointer. */ 11313 group_p = &oc->group_info[ep_info_p->group]; 11314 11315 if (1 != group_p->in_use) { 11316 return BCM_E_NONE; 11317 } 11318 cur = *group_p->ep_list; 11319 11320 /* Traverse the list and delete the matching node. */ 11321 while (NULL != cur) { 11322 h_data_p = cur->ep_data_p; 11323 if (NULL == h_data_p) { 11324 LOG_ERROR(BSL_LS_BCM_OAM, 11325 (BSL_META_U(unit, 11326 "OAM(unit %d) Error: Hash data is empty\n"), 11327 unit)); 11328 return (BCM_E_INTERNAL); 11329 } 11330 if (ep_info_p->name == h_data_p->name) { 11331 /* MEP NAME should be independently unique for RMEPs and LMEPs */ 11332 if (((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE) && 11333 (cur->ep_data_p->ep_id == ep_info_p->id)) || 11334 ((h_data_p->flags & BCM_OAM_ENDPOINT_REMOTE) != 11335 (ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE))) { 11336 } else { 11337 return BCM_E_PARAM; 11338 } 11339 } 11340 cur = cur->next; 11341 } 11342 return (BCM_E_NONE); 11343 } 11344 11345 /* Returns 0/1. 11346 * 0 - indicates either an invalid egress intf or mepid passed 11347 * did not match the earlier mepid. 11348 * 1 - indicates the egress intf doesnt have oam enabled already or 11349 * the mepid check passed. 11350 */ 11351 STATIC int 11352 _bcm_sb2_oam_check_mepid_for_egress_mpls_lmdm_lsp(int unit, 11353 bcm_oam_endpoint_info_t *ep_info_p) 11354 { 11355 #if defined(INCLUDE_L3) 11356 int egr_nh_index = 0; 11357 egr_l3_next_hop_entry_t egr_nh_entry; 11358 int rv = BCM_E_NONE; 11359 int oam_enable = 0, mep_id = -1; 11360 11361 sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry)); 11362 11363 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, ep_info_p->intf_id)) { 11364 egr_nh_index = ep_info_p->intf_id - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 11365 } 11366 else { 11367 egr_nh_index = ep_info_p->intf_id - BCM_XGS3_EGRESS_IDX_MIN(unit); 11368 } 11369 11370 rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, 11371 egr_nh_index, &egr_nh_entry); 11372 if (BCM_FAILURE(rv)) { 11373 /* not a valid egress intf. return check failed */ 11374 return 0; 11375 } 11376 11377 oam_enable = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, 11378 MPLS__MPLS_OAM_DOWNMEP_ENABLEf); 11379 if (!oam_enable) { 11380 return 1; 11381 } 11382 if (oam_enable == _BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM) { 11383 mep_id = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, 11384 MPLS__MEPIDf); 11385 11386 if (mep_id == ep_info_p->name) { 11387 /* Match found */ 11388 return 1; 11389 } 11390 } 11391 return 0; 11392 #endif 11393 return 1; 11394 } 11395 11396 /* 11397 * Function: 11398 * _bcm_sb2_oam_endpoint_params_validate 11399 * Purpose: 11400 * Validate an endpoint parameters. 11401 * Parameters: 11402 * unit - (IN) BCM device number 11403 * oc - (IN) Pointer to OAM control structure. 11404 * hash_key - (IN) Pointer to endpoint hash key value. 11405 * ep_info_p - (IN) Pointer to endpoint information. 11406 * Retruns: 11407 * BCM_E_XXX 11408 */ 11409 STATIC int 11410 _bcm_sb2_oam_endpoint_params_validate(int unit, 11411 _bcm_oam_control_t *oc, 11412 _bcm_oam_hash_key_t *hash_key, 11413 bcm_oam_endpoint_info_t *ep_info_p) 11414 { 11415 int rv; /* Operation return status. */ 11416 _bcm_oam_hash_data_t h_stored_data; 11417 int remote = 0; 11418 11419 11420 /* Get MEP remote endpoint status. */ 11421 remote = (ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0; 11422 11423 LOG_DEBUG(BSL_LS_BCM_OAM, 11424 (BSL_META_U(unit, 11425 "OAM(unit %d) Info: " 11426 "_bcm_sb2_oam_endpoint_params_validate.\n"), unit)); 11427 11428 /* Endpoint must be 802.1ag/Ethernet OAM type. */ 11429 if ((bcmOAMEndpointTypeEthernet != ep_info_p->type) 11430 #if defined(INCLUDE_BHH) 11431 && /* BHH/Y.1731 OAM type */ 11432 !(BHH_EP_TYPE(ep_info_p)) 11433 #endif /* INCLUDE_BHH */ 11434 && !(MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) 11435 ) 11436 { 11437 /* Other OAM types are not supported, return error. */ 11438 return BCM_E_UNAVAIL; 11439 } 11440 11441 /* Supported MDL level is 0 - 7. */ 11442 if ((!remote) && 11443 ((ep_info_p->level < 0) || (ep_info_p->level > _BCM_OAM_EP_LEVEL_MAX))) { 11444 LOG_ERROR(BSL_LS_BCM_OAM, 11445 (BSL_META_U(unit, 11446 "OAM(unit %d) Error: EP Level should be in the range(0-%d).\n"), 11447 unit, _BCM_OAM_EP_LEVEL_MAX )); 11448 return (BCM_E_PARAM); 11449 } 11450 11451 /* Supported MEPID Name range is 1 - 8191, Skipping range check for MIP and MPLS LM/DM */ 11452 if (((ep_info_p->name < _BCM_OAM_EP_NAME_MIN) 11453 || (ep_info_p->name > _BCM_OAM_EP_NAME_MAX)) && 11454 !(ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) && 11455 (!MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p))) { 11456 LOG_ERROR(BSL_LS_BCM_OAM, 11457 (BSL_META_U(unit, 11458 "OAM Error: MEP Name should be in the range(%d-%d).\n"), 11459 _BCM_OAM_EP_NAME_MIN, _BCM_OAM_EP_NAME_MAX)); 11460 return (BCM_E_PARAM); 11461 } 11462 11463 /* 11464 * Check and return error if invalid flag bits are set for remote 11465 * endpoint. 11466 */ 11467 if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE) 11468 && (ep_info_p->flags & _BCM_OAM_REMOTE_EP_INVALID_FLAGS_MASK)) { 11469 11470 return (BCM_E_PARAM); 11471 11472 } 11473 11474 /* There are no remote end-points in MPLS LM DM */ 11475 if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REMOTE) && 11476 (MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p))) { 11477 return (BCM_E_PARAM); 11478 } 11479 11480 /* 11481 * Check and return error if MEPID is not unique within the group 11482 * For MPLS LM/DM endpoints, MEPIDs need not be validated to be unique 11483 * within a group. 11484 */ 11485 if( (!MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) && 11486 _bcm_sb2_oam_mepid_validate(unit, ep_info_p) ) { 11487 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 11488 "OAM(unit %d) Error: MEPID:%x passed is not unique in group %x\n"), 11489 unit, ep_info_p->name, ep_info_p->group)); 11490 11491 return (BCM_E_EXISTS); 11492 } 11493 11494 /* Check if the egr intf given is common for some other endpoint. 11495 * In such a case the mepid for both endpoints should be same. Else 11496 * return error 11497 */ 11498 if ((MPLS_LM_DM_LSP_ENDPOINT_TYPE(ep_info_p)) && 11499 (!_bcm_sb2_oam_check_mepid_for_egress_mpls_lmdm_lsp(unit, ep_info_p))) { 11500 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 11501 "OAM(unit %d) Error: MEPID:%x given is wrong for the given " 11502 "egress interface %x\n"), 11503 unit, ep_info_p->name, ep_info_p->intf_id)); 11504 return (BCM_E_PARAM); 11505 } 11506 11507 /* For replace operation, endpoint ID is required. */ 11508 if ((ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE) 11509 && !(ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID)) { 11510 11511 return (BCM_E_PARAM); 11512 11513 } 11514 /* Port based MEP is supported only for down MEP */ 11515 if ((0 == ep_info_p->vlan) && (0 == ep_info_p->inner_vlan) && 11516 (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING) && (!remote)) { 11517 return (BCM_E_PARAM); 11518 } 11519 11520 /* If it is a Port + CVlan based MEP or Section Port + CVlan 11521 * based MEP and the CVlan (inner_vlan) is 0, return E_PARAM 11522 */ 11523 if ((0 == ep_info_p->inner_vlan) && 11524 ((ep_info_p->flags & BCM_OAM_ENDPOINT_MATCH_INNER_VLAN) || 11525 (ep_info_p->type == bcmOAMEndpointTypeMplsLmDmSectionInnervlan))) { 11526 return (BCM_E_PARAM); 11527 } 11528 11529 /* If it is a Port + S + CVlan based MEP or Section Port + S + CVlan 11530 * based MEP and one of SVlan(vlan) or CVlan (inner_vlan) is 0, 11531 * return E_PARAM 11532 */ 11533 if (((0 == ep_info_p->inner_vlan) || (0 == ep_info_p->vlan)) && 11534 ((ep_info_p->flags & BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN) || 11535 (ep_info_p->type == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan))) { 11536 return (BCM_E_PARAM); 11537 } 11538 11539 /* Validate the LM Counter pool id */ 11540 if ((ep_info_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) && 11541 !(_BCM_SB2_OAM_VALID_CTR_POOL_ID(ep_info_p->lm_ctr_pool_id))) { 11542 return (BCM_E_PARAM); 11543 } 11544 11545 /* MPLS LM DM should not have level other than 7 */ 11546 if ((MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) && 11547 (ep_info_p->level != 7)) { 11548 return (BCM_E_PARAM); 11549 } 11550 11551 /* MPLS LM DM is supported only for down MEP */ 11552 if((MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) && 11553 (ep_info_p->flags & BCM_OAM_ENDPOINT_UP_FACING)){ 11554 return (BCM_E_PARAM); 11555 } 11556 11557 /* MPLS LM Packet count cannot have 64 bit counter */ 11558 if((MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) && 11559 (ep_info_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) && 11560 (ep_info_p->lm_ctr_type == bcmOamLmCounterTypePkt) && 11561 (ep_info_p->lm_ctr_sample_size == bcmOamLmCounterSize64Bit)) { 11562 return (BCM_E_PARAM); 11563 } 11564 11565 /* MPLS LM+DM cannot have 64 bit counter */ 11566 if((MPLS_LM_DM_ENDPOINT_TYPE(ep_info_p)) && 11567 ((ep_info_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) && 11568 (ep_info_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT)) && 11569 (ep_info_p->lm_ctr_sample_size == bcmOamLmCounterSize64Bit)) { 11570 return (BCM_E_PARAM); 11571 } 11572 11573 /* Validate endpoint index value. */ 11574 if (ep_info_p->flags & BCM_OAM_ENDPOINT_WITH_ID) { 11575 _BCM_OAM_EP_INDEX_VALIDATE(ep_info_p->id); 11576 } 11577 11578 /* MIP's are not created with non-zero ccm period */ 11579 if ((ep_info_p->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) && 11580 (ep_info_p->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED)) { 11581 return (BCM_E_PARAM); 11582 } 11583 11584 /* Validate endpoint group id. */ 11585 _BCM_OAM_GROUP_INDEX_VALIDATE(ep_info_p->group); 11586 11587 rv = shr_idxres_list_elem_state(oc->group_pool, ep_info_p->group); 11588 if (BCM_E_EXISTS != rv) { 11589 LOG_ERROR(BSL_LS_BCM_OAM, 11590 (BSL_META_U(unit, 11591 "OAM(unit %d) Error: Group (GID:%d) does not exist.\n"), 11592 unit, ep_info_p->group)); 11593 return (BCM_E_PARAM); 11594 } 11595 11596 if(soc_feature(unit, soc_feature_bhh)) { 11597 #if defined(INCLUDE_BHH) 11598 /* 11599 * BHH can have multiple LSPs/endpoint on same port/MDL 11600 * BHH does not have h/w support. So, return here 11601 */ 11602 if ((bcmOAMEndpointTypeBHHMPLS == ep_info_p->type) || 11603 (bcmOAMEndpointTypeBHHMPLSVccv == ep_info_p->type)) { 11604 return (BCM_E_NONE); 11605 } 11606 #endif 11607 } 11608 11609 #if defined(KEY_PRINT) 11610 _bcm_oam_hash_key_print(hash_key); 11611 #endif 11612 11613 /* 11614 * Lookup using hash key value. 11615 * Last param value '0' specifies keep the match entry. 11616 * Value '1' would mean remove the entry from the table. 11617 * Matched Params: 11618 * Group Name + Group ID + Endpoint Name + VLAN + MDL + Gport. 11619 */ 11620 rv = shr_htb_find(oc->ma_mep_htbl, *hash_key, 11621 (shr_htb_data_t *)&h_stored_data, 0); 11622 if (BCM_SUCCESS(rv) 11623 && !(ep_info_p->flags & BCM_OAM_ENDPOINT_REPLACE)) { 11624 11625 LOG_ERROR(BSL_LS_BCM_OAM, 11626 (BSL_META_U(unit, 11627 "OAM(unit %d) Error: Endpoint ID=%d %s.\n"), 11628 unit, ep_info_p->id, bcm_errmsg(BCM_E_EXISTS))); 11629 11630 /* Endpoint must not be in use expect for Replace operation. */ 11631 return (BCM_E_EXISTS); 11632 11633 } else { 11634 11635 LOG_DEBUG(BSL_LS_BCM_OAM, 11636 (BSL_META_U(unit, 11637 "OAM(unit %d) Info: Endpoint ID=%d Available. %s.\n"), 11638 unit, ep_info_p->id, bcm_errmsg(rv))); 11639 11640 } 11641 11642 11643 11644 return (BCM_E_NONE); 11645 } 11646 11647 typedef struct _bcm_oam_flexible_oam_domain_vlan_ctrl_type1_s { 11648 uint32 start_index; 11649 uint32 end_index; 11650 soc_field_t tag_source_1; 11651 soc_field_t tag_source_2; 11652 soc_field_t data_processing; 11653 soc_field_t oam_processing; 11654 } _bcm_oam_flexible_oam_domain_c_vlan_ctrl_type1_t; 11655 11656 typedef struct _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_s { 11657 uint32 start_index; 11658 uint32 no_entries; 11659 uint32 increment; 11660 soc_field_t tag_source_1; 11661 soc_field_t tag_source_2; 11662 soc_field_t data_processing; 11663 soc_field_t oam_processing; 11664 } _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t; 11665 11666 /* 11667 * Function: 11668 * _bcm_sb2_oam_ing_flexible_oam_domain_ctrl_set 11669 * Purpose: 11670 * Set the default values for ingress flexible oam domain control 11671 * Parameters: 11672 * unit - (IN) BCM device number 11673 * Retruns: 11674 * BCM_E_XXX 11675 * Index to the ing flexible domain control table is 11676 * index[5] = pars_inner_pri_tagged; 11677 * index[4] = pars_inner_tagged; 11678 * index[3] = pars_outer_tagged; 11679 * index[2] = vxlt_inner_tagged; 11680 * index[1] = vxlt_outer_tagged; 11681 * index[0] = svp_valid; 11682 */ 11683 STATIC int 11684 _bcm_sb2_oam_ing_flexible_oam_domain_ctrl_set(int unit) 11685 { 11686 int rv = BCM_E_NONE; 11687 oam_flexible_domain_control_entry_t *ent_buf; 11688 oam_flexible_domain_control_entry_t *ent; 11689 int max_index = 0; 11690 int index = 0; 11691 int end_index = 0; 11692 int loop_index = 0; 11693 int entry_mem_size = 0; 11694 int entry_index = 0; 11695 int max_array_index = 0; 11696 uint32 action_set = 1; 11697 11698 11699 _bcm_oam_flexible_oam_domain_c_vlan_ctrl_type1_t c_vlan_ctrl_info[] = { 11700 /* Set values for C VLAN MEP pre-VXLT actions */ 11701 /* Action for incoming untagged packets */ 11702 { 4, 7, CVLAN_DOMAIN_PRE_VXLT_CVLAN_TAG_SOURCEf, 0, 11703 CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 11704 CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf }, 11705 /* Action for incoming single inner tagged but not 11706 priority tagged packets */ 11707 { 16, 23, CVLAN_DOMAIN_PRE_VXLT_CVLAN_TAG_SOURCEf, 0, 11708 CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 11709 CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf }, 11710 /* Action for incoming single inner priority tagged packets */ 11711 { 52, 55, CVLAN_DOMAIN_PRE_VXLT_CVLAN_TAG_SOURCEf, 0, 11712 CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 11713 CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf }, 11714 /* Set values for C VLAN MEP post-VXLT actions */ 11715 /* Action for incoming untagged packets */ 11716 { 4, 7, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 0, 11717 CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 11718 CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf }, 11719 /* Action for incoming single inner tagged but not 11720 priority tagged packets */ 11721 { 20, 23, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 0, 11722 CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 11723 CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf }, 11724 /* Action for incoming single inner priority tagged packets */ 11725 { 52, 55, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 0, 11726 CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 11727 CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf }, 11728 11729 {0, 63, MPLS_SECTION_DOMAIN_CVLAN_TAG_SOURCEf, 11730 MPLS_SECTION_DOMAIN_SVLAN_TAG_SOURCEf, 11731 MPLS_SECTION_DOMAIN_OAM_PROCESSING_ENABLEf, 11732 MPLS_SECTION_DOMAIN_DATA_PROCESSING_ENABLEf}, 11733 11734 }; 11735 11736 _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t s_vlan_ctrl_info[] = { 11737 11738 /* Set values for S VLAN MEP actions */ 11739 /* Action for incoming packet with single outer tagged after 11740 VXLT */ 11741 { 2, 2, 8, SVLAN_DOMAIN_SVLAN_TAG_SOURCEf, 0, 11742 SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 11743 SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf}, 11744 /* Action for incoming packet with double tag after VXLT */ 11745 { 6, 2, 8, SVLAN_DOMAIN_SVLAN_TAG_SOURCEf, 0, 11746 SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 11747 SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 11748 11749 /* Set values for S+C VLAN MEP actions */ 11750 /* Action for incoming packet with double tag after VXLT */ 11751 { 6, 2, 8, SVLAN_CVLAN_DOMAIN_SVLAN_TAG_SOURCEf, 11752 SVLAN_CVLAN_DOMAIN_CVLAN_TAG_SOURCEf, 11753 SVLAN_CVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 11754 SVLAN_CVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 11755 { 6, 2, 8, 0, 0, 11756 SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 11757 SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 11758 { 6, 2, 8, 0, 0, 11759 CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf, 11760 CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf }, 11761 { 6, 2, 8, 0, 11762 0, 11763 CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf, 11764 CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf }, 11765 { 0, 0 } /* table terminator */ 11766 }; 11767 11768 _bcm_oam_flexible_oam_domain_c_vlan_ctrl_type1_t *ctrl_info; 11769 _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t *s_ctrl_info; 11770 11771 11772 /* Read the table entries into the buffer. */ 11773 max_index = soc_mem_index_max(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm); 11774 11775 entry_mem_size = sizeof(oam_flexible_domain_control_entry_t); 11776 /* Allocate buffer to store the DMAed table entries. */ 11777 ent_buf = soc_cm_salloc(unit, entry_mem_size * (max_index + 1), 11778 "OAM flexible domain control table entry buffer"); 11779 if (NULL == ent_buf) { 11780 return (BCM_E_MEMORY); 11781 } 11782 /* Initialize the entry buffer. */ 11783 sal_memset(ent_buf, 0, sizeof(entry_mem_size) * (max_index + 1)); 11784 max_array_index = 11785 sizeof(c_vlan_ctrl_info) / 11786 sizeof(_bcm_oam_flexible_oam_domain_c_vlan_ctrl_type1_t); 11787 11788 /* Set action for C vlan */ 11789 for (index = 0; index < max_array_index;index++) { 11790 ctrl_info = &c_vlan_ctrl_info[index]; 11791 11792 for (entry_index = ctrl_info->start_index; 11793 entry_index <= ctrl_info->end_index; entry_index++) { 11794 ent = soc_mem_table_idx_to_pointer 11795 (unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 11796 oam_flexible_domain_control_entry_t *, 11797 ent_buf, entry_index); 11798 if (ctrl_info->tag_source_1 != 0) { 11799 soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 11800 (uint32 *)ent, ctrl_info->tag_source_1, &action_set); 11801 } 11802 if (ctrl_info->tag_source_2 != 0) { 11803 soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 11804 (uint32 *)ent, ctrl_info->tag_source_2, &action_set); 11805 } 11806 soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 11807 (uint32 *)ent, ctrl_info->data_processing, &action_set); 11808 soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 11809 (uint32 *)ent, ctrl_info->oam_processing, &action_set); 11810 } 11811 } 11812 11813 /* Set action for S and S+C vlan */ 11814 for (index = 0; ;index++) { 11815 s_ctrl_info = &s_vlan_ctrl_info[index]; 11816 if(s_ctrl_info->start_index == 0) { 11817 /* End of table */ 11818 break; 11819 } 11820 entry_index = s_ctrl_info->start_index; 11821 loop_index = s_ctrl_info->start_index; 11822 end_index = entry_index + s_ctrl_info->no_entries; 11823 while (entry_index <= max_index) { 11824 for (; loop_index < end_index; loop_index++) { 11825 ent = soc_mem_table_idx_to_pointer(unit, 11826 OAM_FLEXIBLE_DOMAIN_CONTROLm, 11827 oam_flexible_domain_control_entry_t *, 11828 ent_buf, loop_index); 11829 if (s_ctrl_info->tag_source_1 != 0) { 11830 soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 11831 (uint32 *)ent, s_ctrl_info->tag_source_1, &action_set); 11832 } 11833 if (s_ctrl_info->tag_source_2 != 0) { 11834 soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 11835 (uint32 *)ent, s_ctrl_info->tag_source_2, &action_set); 11836 } 11837 soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 11838 (uint32 *)ent, s_ctrl_info->data_processing, &action_set); 11839 soc_mem_field_set(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 11840 (uint32 *)ent, s_ctrl_info->oam_processing, &action_set); 11841 } 11842 entry_index += s_ctrl_info->increment; 11843 loop_index = entry_index; 11844 end_index = (entry_index + s_ctrl_info->no_entries); 11845 } 11846 } 11847 11848 rv = soc_mem_write_range(unit, OAM_FLEXIBLE_DOMAIN_CONTROLm, 11849 MEM_BLOCK_ALL, 0, max_index, ent_buf); 11850 if (BCM_FAILURE(rv)) { 11851 if (ent_buf) { 11852 soc_cm_sfree(unit, ent_buf); 11853 } 11854 return rv; 11855 } 11856 if (ent_buf) { 11857 soc_cm_sfree(unit, ent_buf); 11858 } 11859 11860 return rv; 11861 } 11862 /* 11863 * Function: 11864 * _bcm_sb2_oam_egr_flexible_oam_domain_ctrl_set 11865 * Purpose: 11866 * Set the default values for egress flexible oam domain control 11867 * Parameters: 11868 * unit - (IN) BCM device number 11869 * Retruns: 11870 * BCM_E_XXX 11871 */ 11872 11873 STATIC int 11874 _bcm_sb2_oam_egr_flexible_oam_domain_ctrl_set(int unit) 11875 { 11876 int rv = BCM_E_NONE; 11877 egr_oam_flexible_domain_control_entry_t *egr_ent_buf; 11878 egr_oam_flexible_domain_control_entry_t *ent; 11879 int max_index = 0; 11880 int index = 0; 11881 int end_index = 0; 11882 int loop_index = 0; 11883 int entry_mem_size = 0; 11884 int entry_index = 0; 11885 uint32 action_set = 1; 11886 11887 _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t vlan_ctrl_info[] = { 11888 11889 /* CVLAN MEP before VXLT */ 11890 { 16, 2, 4, 0, 0, 11891 CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 11892 CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf }, 11893 /* CVLAN MEP after VXLT */ 11894 { 4, 2, 8, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 0, 11895 CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 11896 CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf }, 11897 /* SVLAN MEP */ 11898 { 8, 8, 16, 0, 0, 11899 SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 11900 SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 11901 11902 /* Set values for Section MEP actions */ 11903 { 8, 8, 16, MPLS_SECTION_DOMAIN_CVLAN_TAG_SOURCEf, 11904 MPLS_SECTION_DOMAIN_SVLAN_TAG_SOURCEf, 11905 MPLS_SECTION_DOMAIN_OAM_PROCESSING_ENABLEf, 11906 MPLS_SECTION_DOMAIN_DATA_PROCESSING_ENABLEf}, 11907 /* S+C VLAN MEP */ 11908 { 14, 2, 18, SVLAN_CVLAN_DOMAIN_CVLAN_TAG_SOURCEf, 0, 11909 SVLAN_CVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 11910 SVLAN_CVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 11911 11912 { 24, 8, 8, 0, 0, 11913 SVLAN_CVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 11914 SVLAN_CVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 11915 { 24, 8, 8, 0, 0, 11916 CVLAN_DOMAIN_PRE_VXLT_DATA_PROCESSING_ENABLEf, 11917 CVLAN_DOMAIN_PRE_VXLT_OAM_PROCESSING_ENABLEf }, 11918 { 26, 2, 2, 0, 0, 11919 SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 11920 SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 11921 { 30, 2, 2, 0, 0, 11922 SVLAN_DOMAIN_DATA_PROCESSING_ENABLEf, 11923 SVLAN_DOMAIN_OAM_PROCESSING_ENABLEf }, 11924 { 30, 2, 2, CVLAN_DOMAIN_POST_VXLT_CVLAN_TAG_SOURCEf, 0, 11925 CVLAN_DOMAIN_POST_VXLT_DATA_PROCESSING_ENABLEf, 11926 CVLAN_DOMAIN_POST_VXLT_OAM_PROCESSING_ENABLEf }, 11927 { 0, 0 } /* table terminator */ 11928 }; 11929 11930 _bcm_oam_flexible_oam_domain_vlan_ctrl_type2_t *ctrl_info; 11931 11932 11933 /* Read the table entries into the buffer. */ 11934 max_index = soc_mem_index_max(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm); 11935 11936 entry_mem_size = sizeof(egr_oam_flexible_domain_control_entry_t); 11937 /* Allocate buffer to store the DMAed table entries. */ 11938 egr_ent_buf = soc_cm_salloc(unit, entry_mem_size * (max_index + 1), 11939 "OAM flexible domain control table entry buffer"); 11940 if (NULL == egr_ent_buf) { 11941 return (BCM_E_MEMORY); 11942 } 11943 /* Initialize the entry buffer. */ 11944 sal_memset(egr_ent_buf, 0, sizeof(entry_mem_size) * (max_index + 1)); 11945 11946 /* Set action for C, S and S+C vlan */ 11947 for (index = 0; ;index++) { 11948 ctrl_info = &vlan_ctrl_info[index]; 11949 if(ctrl_info->start_index == 0) { 11950 /* End of table */ 11951 break; 11952 } 11953 entry_index = ctrl_info->start_index; 11954 loop_index = ctrl_info->start_index; 11955 end_index = entry_index + ctrl_info->no_entries; 11956 while (entry_index <= max_index) { 11957 for (; loop_index < end_index; loop_index++) { 11958 ent = soc_mem_table_idx_to_pointer 11959 (unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 11960 egr_oam_flexible_domain_control_entry_t *, 11961 egr_ent_buf, loop_index); 11962 11963 if (ctrl_info->tag_source_1 != 0) { 11964 soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 11965 (uint32 *)ent, ctrl_info->tag_source_1, &action_set); 11966 } 11967 if (ctrl_info->tag_source_2 != 0) { 11968 soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 11969 (uint32 *)ent, ctrl_info->tag_source_2, &action_set); 11970 } 11971 soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 11972 (uint32 *)ent, ctrl_info->data_processing, &action_set); 11973 soc_mem_field_set(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 11974 (uint32 *)ent, ctrl_info->oam_processing, &action_set); 11975 } 11976 entry_index += ctrl_info->increment; 11977 loop_index = entry_index; 11978 end_index = (entry_index + ctrl_info->no_entries); 11979 } 11980 } 11981 11982 rv = soc_mem_write_range(unit, EGR_OAM_FLEXIBLE_DOMAIN_CONTROLm, 11983 MEM_BLOCK_ALL, 0, max_index, egr_ent_buf); 11984 if (BCM_FAILURE(rv)) { 11985 if (egr_ent_buf) { 11986 soc_cm_sfree(unit, egr_ent_buf); 11987 } 11988 return rv; 11989 } 11990 if (egr_ent_buf) { 11991 soc_cm_sfree(unit, egr_ent_buf); 11992 } 11993 return rv; 11994 } 11995 11996 11997 /* 11998 * Function: 11999 * _bcm_sb2_oam_flexible_oam_domain_ctrl_set 12000 * Purpose: 12001 * Set the default values for flexible oam domain control 12002 * Parameters: 12003 * unit - (IN) BCM device number 12004 * Retruns: 12005 * BCM_E_XXX 12006 */ 12007 STATIC int 12008 _bcm_sb2_oam_flexible_oam_domain_ctrl_set(int unit) 12009 { 12010 int rv = BCM_E_NONE; 12011 /* Set ingress flexible domain control */ 12012 rv = _bcm_sb2_oam_ing_flexible_oam_domain_ctrl_set(unit); 12013 if (BCM_FAILURE(rv)) { 12014 return (rv); 12015 } 12016 12017 /* Set egress flexible domain control */ 12018 rv = _bcm_sb2_oam_egr_flexible_oam_domain_ctrl_set(unit); 12019 if (BCM_FAILURE(rv)) { 12020 return (rv); 12021 } 12022 return rv; 12023 } 12024 12025 12026 typedef struct _bcm_oam_ing_flexible_drop_ctrl_s { 12027 soc_reg_t drop_ctrl_reg; 12028 uint32 vfp_drop_ctrl; 12029 uint32 olp_drop_ctrl; 12030 uint32 spst_drop_ctrl; 12031 uint32 tag_drop_ctrl; 12032 uint32 cvlan_bfr_vxlt_drop_ctrl; 12033 uint32 cvlan_after_vxlt_drop_ctrl; 12034 uint32 e2e_drop_ctrl; 12035 uint32 vlan_drop_ctrl; 12036 uint32 disc_drop_ctrl; 12037 } _bcm_oam_ing_flexible_drop_ctrl_t; 12038 12039 typedef struct _bcm_oam_egr_flexible_drop_ctrl_s { 12040 soc_reg_t drop_ctrl_reg; 12041 uint32 egr_drop_ctrl; 12042 uint32 evxlt_payload_drop_ctrl; 12043 uint32 cvlan_after_vxlt_drop_ctrl; 12044 uint32 cvlan_before_vxlt_drop_ctrl; 12045 } _bcm_oam_egr_flexible_drop_ctrl_t; 12046 12047 /* 12048 * Function: 12049 * _bcm_sb2_oam_ing_flexible_drop_ctrl_set 12050 * Purpose: 12051 * Set the default values for flexible ingress drop control 12052 * Parameters: 12053 * unit - (IN) BCM device number 12054 * Retruns: 12055 * BCM_E_XXX 12056 */ 12057 STATIC int 12058 _bcm_sb2_oam_ing_flexible_drop_ctrl_set(int unit) 12059 { 12060 uint64 en_rval; 12061 uint64 write_val; 12062 int index = 0; 12063 _bcm_oam_ing_flexible_drop_ctrl_t *flex_drop_info; 12064 _bcm_oam_ing_flexible_drop_ctrl_t ing_flex_drop[] = { 12065 { OAM_PORT_INTERFACE_DROP_CONTROL_64r, 0, 1, 0, 0, 0, 0, 1, 0, 0xe01c1 }, 12066 { OAM_C_INTERFACE_DROP_CONTROL_64r, 1, 1, 0, 0, 0, 1, 1, 0, 0xe01fd }, 12067 { OAM_S_INTERFACE_DROP_CONTROL_64r, 1, 1, 0, 1, 1, 1, 1, 5, 0xe01fd }, 12068 { OAM_S_C_INTERFACE_DROP_CONTROL_64r, 1, 1, 1, 1, 1, 1, 1, 7, 0xe01fd }, 12069 { OAM_SECTION_INTERFACE_DROP_CONTROL_64r, 1, 1, 1, 1, 1, 1, 1, 7, 0xe01fd }, 12070 { OAM_LSP_INTERFACE_DROP_CONTROL_64r, 1, 1, 1, 1, 1, 1, 1, 7, 0xe01fd }, 12071 { OAM_PW_INTERFACE_DROP_CONTROL_64r, 1, 1, 1, 1, 1, 1, 1, 7, 0xe01fd }, 12072 { 0 }, /* End of table */ 12073 }; 12074 12075 COMPILER_64_ZERO(en_rval); 12076 COMPILER_64_ZERO(write_val); 12077 12078 for (index = 0; ;index++) { 12079 flex_drop_info = &ing_flex_drop[index]; 12080 if(flex_drop_info->drop_ctrl_reg == 0) { 12081 /* End of table */ 12082 break; 12083 } 12084 12085 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, flex_drop_info->drop_ctrl_reg, 12086 REG_PORT_ANY, 0, &en_rval)); 12087 COMPILER_64_SET(write_val, 0, flex_drop_info->vfp_drop_ctrl); 12088 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 12089 &en_rval, VFP_DROP_CTRLf, 12090 write_val); 12091 COMPILER_64_SET(write_val, 0, flex_drop_info->olp_drop_ctrl); 12092 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 12093 &en_rval, OLP_ERROR_DROP_CTRLf, 12094 write_val); 12095 COMPILER_64_SET(write_val, 0, flex_drop_info->spst_drop_ctrl); 12096 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 12097 &en_rval, SPST_NOT_IN_FORWARDING_STATE_DROP_CTRLf, 12098 write_val); 12099 COMPILER_64_SET(write_val, 0, flex_drop_info->tag_drop_ctrl); 12100 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 12101 &en_rval, DISCARD_TAG_UNTAG_CTRLf, 12102 write_val); 12103 COMPILER_64_SET(write_val, 0, flex_drop_info->cvlan_bfr_vxlt_drop_ctrl); 12104 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 12105 &en_rval, 12106 CVLAN_INTF_BEFORE_VXLT_VXLT_MISS_DROP_CTRLf, 12107 write_val); 12108 COMPILER_64_SET(write_val, 0, flex_drop_info->cvlan_after_vxlt_drop_ctrl); 12109 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 12110 &en_rval, 12111 CVLAN_INTF_AFTER_VXLT_VXLT_MISS_DROP_CTRLf, 12112 write_val); 12113 COMPILER_64_SET(write_val, 0, flex_drop_info->e2e_drop_ctrl); 12114 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 12115 &en_rval, ERRORED_E2E_PKT_DROP_CTRLf, 12116 write_val); 12117 COMPILER_64_SET(write_val, 0, flex_drop_info->vlan_drop_ctrl); 12118 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 12119 &en_rval, VLAN_DROP_VECTOR_CTRLf, 12120 write_val); 12121 COMPILER_64_SET(write_val, 0, flex_drop_info->disc_drop_ctrl); 12122 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 12123 &en_rval, DISC_DROP_VECTOR_CTRLf, 12124 write_val); 12125 SOC_IF_ERROR_RETURN(soc_reg64_set(unit, flex_drop_info->drop_ctrl_reg, 12126 REG_PORT_ANY, 0, en_rval)); 12127 } 12128 return (BCM_E_NONE); 12129 } 12130 12131 /* 12132 * Function: 12133 * _bcm_sb2_oam_egr_flexible_drop_ctrl_set 12134 * Purpose: 12135 * Set the default values for flexible egress drop control 12136 * Parameters: 12137 * unit - (IN) BCM device number 12138 * Retruns: 12139 * BCM_E_XXX 12140 */ 12141 STATIC int 12142 _bcm_sb2_oam_egr_flexible_drop_ctrl_set(int unit) 12143 { 12144 uint64 en_rval; 12145 uint64 write_val; 12146 int index = 0; 12147 12148 _bcm_oam_egr_flexible_drop_ctrl_t *flex_drop_info; 12149 _bcm_oam_egr_flexible_drop_ctrl_t egr_flex_drop[] = { 12150 { EGR_OAM_PORT_INTERFACE_DROP_CONTROL_64r, 0x1e0787d, 1, 1, 1 }, 12151 { EGR_OAM_C_INTERFACE_DROP_CONTROL_64r, 0x1e0787c, 1, 1, 0 }, 12152 { EGR_OAM_S_INTERFACE_DROP_CONTROL_64r, 0x1e06848, 1, 0, 0 }, 12153 { EGR_OAM_S_C_INTERFACE_DROP_CONTROL_64r, 0x1e06048, 1, 0, 0 }, 12154 { EGR_OAM_SECTION_INTERFACE_DROP_CONTROL_64r, 0x1e06049, 1, 0, 0 }, 12155 { EGR_OAM_LSP_INTERFACE_DROP_CONTROL_64r, 0x1e06049, 1, 0, 0 }, 12156 { EGR_OAM_PW_INTERFACE_DROP_CONTROL_64r, 0x1e06049, 1, 0, 0 }, 12157 { 0 }, /* End of table */ 12158 }; 12159 12160 COMPILER_64_ZERO(en_rval); 12161 COMPILER_64_ZERO(write_val); 12162 12163 for (index = 0; ;index++) { 12164 flex_drop_info = &egr_flex_drop[index]; 12165 if(flex_drop_info->drop_ctrl_reg == 0) { 12166 /* End of table */ 12167 break; 12168 } 12169 12170 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, flex_drop_info->drop_ctrl_reg, 12171 REG_PORT_ANY, 0, &en_rval)); 12172 12173 COMPILER_64_SET(write_val, 0, flex_drop_info->egr_drop_ctrl); 12174 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 12175 &en_rval, EGR_DROP_VECTOR_CTRLf, 12176 write_val); 12177 12178 COMPILER_64_SET(write_val, 0, flex_drop_info->evxlt_payload_drop_ctrl); 12179 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 12180 &en_rval, 12181 EVXLT_APPLIED_TO_PAYLOAD_VXLT_MISS_DROP_CTRLf, 12182 write_val); 12183 12184 COMPILER_64_SET(write_val, 0, flex_drop_info->cvlan_after_vxlt_drop_ctrl); 12185 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 12186 &en_rval, 12187 EVXLT_APPLIED_TO_OUTER_L2_CVLAN_INTF_AFTER_VXLT_VXLT_MISS_DROP_CTRLf, 12188 write_val); 12189 12190 COMPILER_64_SET(write_val, 0, flex_drop_info->cvlan_before_vxlt_drop_ctrl); 12191 soc_reg64_field_set(unit, flex_drop_info->drop_ctrl_reg, 12192 &en_rval, 12193 EVXLT_APPLIED_TO_OUTER_L2_CVLAN_INTF_BEFORE_VXLT_VXLT_MISS_DROP_CTRLf, 12194 write_val); 12195 12196 SOC_IF_ERROR_RETURN(soc_reg64_set(unit, flex_drop_info->drop_ctrl_reg, 12197 REG_PORT_ANY, 0, en_rval)); 12198 } 12199 return (BCM_E_NONE); 12200 } 12201 12202 /* 12203 * Function: 12204 * _bcm_sb2_oam_flexible_drop_ctrl_set 12205 * Purpose: 12206 * Set the default values for flexible ingress and egress drop control 12207 * Parameters: 12208 * unit - (IN) BCM device number 12209 * Retruns: 12210 * BCM_E_XXX 12211 */ 12212 STATIC int 12213 _bcm_sb2_oam_flexible_drop_ctrl_set(int unit) 12214 { 12215 int rv = BCM_E_NONE; 12216 /* Set ingress flexible drop control */ 12217 rv = _bcm_sb2_oam_ing_flexible_drop_ctrl_set(unit); 12218 if (BCM_FAILURE(rv)) { 12219 return (rv); 12220 } 12221 12222 /* Set egress flexible drop control */ 12223 rv = _bcm_sb2_oam_egr_flexible_drop_ctrl_set(unit); 12224 if (BCM_FAILURE(rv)) { 12225 return (rv); 12226 } 12227 return rv; 12228 } 12229 12230 /* 12231 * Function: 12232 * _bcm_sb2_oam_s_intf_passive_proc_ctrl_set 12233 * Purpose: 12234 * Set the default values for s-interface passive processing control 12235 * Parameters: 12236 * unit - (IN) BCM device number 12237 * Retruns: 12238 * BCM_E_XXX 12239 */ 12240 STATIC int 12241 _bcm_sb2_oam_s_intf_passive_proc_ctrl_set(int unit) 12242 { 12243 uint32 en_rval = 0; 12244 /* Set ingress s_intf passive processing control */ 12245 SOC_IF_ERROR_RETURN( 12246 soc_reg32_get(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 12247 REG_PORT_ANY, 0, &en_rval)); 12248 12249 soc_reg_field_set(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 12250 &en_rval, SPST_NOT_IN_FORWARDING_STATE_DROP_CTRLf, 12251 0x1); 12252 /* Set ENIFILTER_DROP, INVALID_TPID_DROP and INVALID_VLAN_DROP */ 12253 soc_reg_field_set(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 12254 &en_rval, VLAN_DROP_VECTOR_CTRLf, 12255 0x7); 12256 SOC_IF_ERROR_RETURN( 12257 soc_reg32_set(unit, OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 12258 REG_PORT_ANY, 0, en_rval)); 12259 12260 en_rval = 0; 12261 /* Set egress s_intf passive processing control */ 12262 SOC_IF_ERROR_RETURN( 12263 soc_reg32_get(unit, EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 12264 REG_PORT_ANY, 0, &en_rval)); 12265 12266 12267 /* Set NOT_VLAN_MEMBER_DROP, STG_BLOCK_DROP, STG_DISABLE_DROP 12268 For details - refer to EGR_DROP_VECTOR */ 12269 soc_reg_field_set(unit, EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 12270 &en_rval, EGR_DROP_VECTOR_CTRLf, 12271 0x1030); 12272 12273 SOC_IF_ERROR_RETURN(soc_reg32_set(unit, 12274 EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr, 12275 REG_PORT_ANY, 0, en_rval)); 12276 return (BCM_E_NONE); 12277 } 12278 12279 /* 12280 * Function: 12281 * _bcm_sb2_oam_hg_olp_enable 12282 * Purpose: 12283 * Enable OLP handling on HG ports 12284 * Parameters: 12285 * unit - (IN) BCM device number 12286 * Retruns: 12287 * BCM_E_XXX 12288 */ 12289 STATIC int 12290 _bcm_sb2_oam_hg_olp_enable(int unit) 12291 { 12292 bcm_pbmp_t ports; 12293 bcm_port_t port; 12294 iarb_ing_physical_port_entry_t entry; 12295 12296 BCM_PBMP_ASSIGN(ports, PBMP_PORT_ALL(unit)); 12297 PBMP_ITER(ports, port) { 12298 if (IS_HG_PORT(unit, port)) { 12299 SOC_IF_ERROR_RETURN(soc_mem_read(unit, IARB_ING_PHYSICAL_PORTm, 12300 MEM_BLOCK_ANY, port, &entry)); 12301 soc_IARB_ING_PHYSICAL_PORTm_field32_set(unit, &entry, 12302 OLP_ENABLEf, 1); 12303 SOC_IF_ERROR_RETURN(soc_mem_write(unit, IARB_ING_PHYSICAL_PORTm, 12304 MEM_BLOCK_ALL, port, &entry)); 12305 } else { 12306 soc_IARB_ING_PHYSICAL_PORTm_field32_set(unit, &entry, 12307 OLP_ENABLEf, 0); 12308 } 12309 SOC_IF_ERROR_RETURN(soc_mem_write(unit, IARB_ING_PHYSICAL_PORTm, 12310 MEM_BLOCK_ALL, port, &entry)); 12311 } 12312 return (BCM_E_NONE); 12313 } 12314 12315 /* 12316 * Function: 12317 * _bcm_sb2_oam_olp_header_type_mapping_set 12318 * Purpose: 12319 * Set default olp header type mapping 12320 * Parameters: 12321 * unit - (IN) BCM device number 12322 * Retruns: 12323 * BCM_E_XXX 12324 */ 12325 STATIC int 12326 _bcm_sb2_oam_olp_header_type_mapping_set(int unit) 12327 { 12328 int index = 0; 12329 int mem_index_count = 0; 12330 egr_olp_header_type_mapping_entry_t entry; 12331 12332 mem_index_count = soc_mem_index_count(unit, EGR_OLP_HEADER_TYPE_MAPPINGm); 12333 12334 if (sb2_olp_hdr_type_count > mem_index_count) { 12335 return BCM_E_RESOURCE; 12336 } 12337 12338 for (index = 0; index < sb2_olp_hdr_type_count; index++) { 12339 soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set(unit, 12340 &entry, 12341 HDR_TYPEf, 12342 _BCM_SB2_OLP_HDR_TYPE_RX); 12343 12344 soc_EGR_OLP_HEADER_TYPE_MAPPINGm_field32_set( 12345 unit, 12346 &entry, 12347 HDR_SUBTYPEf, 12348 sb2_olp_hdr_type_mapping[index].subtype); 12349 12350 SOC_IF_ERROR_RETURN( 12351 WRITE_EGR_OLP_HEADER_TYPE_MAPPINGm( 12352 unit, 12353 MEM_BLOCK_ALL, 12354 sb2_olp_hdr_type_mapping[index].mem_index, 12355 &entry)); 12356 } 12357 12358 return BCM_E_NONE; 12359 } 12360 12361 /* 12362 * Function: _bcm_sb2_oam_olp_fp_hw_index_get 12363 * 12364 * Purpose: 12365 * Get OLP_HDR_TYPE_COMPRESSED corresponding to subtype 12366 * Parameters: 12367 * unit - (IN) BCM device number 12368 * Returns: 12369 * BCM_E_XXX 12370 */ 12371 int 12372 _bcm_sb2_oam_olp_fp_hw_index_get(int unit, 12373 bcm_field_olp_header_type_t olp_hdr_type, 12374 int *hwindex) 12375 { 12376 int index; 12377 12378 switch (olp_hdr_type) { 12379 /* SB2 does not allow IFP to program UpMEP header type for 12380 * ADD_OLP_HEADER action, as the OLP_HDR_TYPE_COMPRESSED in 12381 * FP_POLICY_TABLE is not wide enough to index Up MEP subtypes 12382 * in EGR_OLP_HEADER_TYPE_MAPPING 12383 */ 12384 case bcmFieldOlpHeaderTypeEthOamUpMepCcm: 12385 case bcmFieldOlpHeaderTypeEthOamUpMepLm: 12386 case bcmFieldOlpHeaderTypeEthOamUpMepDm: 12387 case bcmFieldOlpHeaderTypeEthOamUpMepOthers: 12388 case bcmFieldOlpHeaderTypeUpSat: 12389 return BCM_E_PARAM; 12390 12391 default: 12392 break; 12393 } 12394 12395 for (index = 0; index < sb2_olp_hdr_type_count; index++) { 12396 if (sb2_olp_hdr_type_mapping[index].field_olp_hdr_type == olp_hdr_type) { 12397 *hwindex = sb2_olp_hdr_type_mapping[index].mem_index; 12398 return BCM_E_NONE; 12399 } 12400 } 12401 12402 return BCM_E_NOT_FOUND; 12403 } 12404 12405 /* 12406 * Function: _bcm_sb2_oam_olp_hw_index_olp_type_get 12407 * 12408 * Purpose: 12409 * Get subtype corresponding to OLP_HDR_TYPE_COMPRESSED 12410 * Parameters: 12411 * unit - (IN) BCM device number 12412 * Returns: 12413 * BCM_E_XXX 12414 */ 12415 int 12416 _bcm_sb2_oam_olp_hw_index_olp_type_get(int unit, 12417 int hwindex, 12418 bcm_field_olp_header_type_t *olp_hdr_type) 12419 { 12420 int index; 12421 12422 for (index = 0; index < sb2_olp_hdr_type_count; index++) { 12423 if (sb2_olp_hdr_type_mapping[index].mem_index == hwindex) { 12424 12425 *olp_hdr_type = 12426 sb2_olp_hdr_type_mapping[hwindex].field_olp_hdr_type; 12427 12428 return BCM_E_NONE; 12429 } 12430 } 12431 return BCM_E_PARAM; 12432 } 12433 12434 /* 12435 * Function: 12436 * _bcm_sb2_oam_drop_ctrl_set 12437 * Purpose: 12438 * Set OAM drop control to not to drop wrong version OAM packets 12439 * Parameters: 12440 * unit - (IN) BCM device number 12441 * Retruns: 12442 * BCM_E_XXX 12443 */ 12444 STATIC int 12445 _bcm_sb2_oam_drop_ctrl_set(int unit) 12446 { 12447 uint32 drop_ctrl = 0; 12448 soc_reg_field_set(unit, OAM_DROP_CONTROLr, &drop_ctrl, 12449 IFP_OAM_UNKNOWN_OPCODE_VERSION_DROPf, 0); 12450 12451 SOC_IF_ERROR_RETURN(WRITE_OAM_DROP_CONTROLr(unit, drop_ctrl)); 12452 return (BCM_E_NONE); 12453 } 12454 12455 /* 12456 * Function: 12457 * _bcm_sb2_oam_lm_cng_cpu_ctrl_set_default 12458 * Purpose: 12459 * Set OAM LM cng and cpu data control 12460 * Parameters: 12461 * unit - (IN) BCM device number 12462 * Retruns: 12463 * BCM_E_XXX 12464 */ 12465 STATIC int 12466 _bcm_sb2_oam_lm_cng_cpu_ctrl_set_default(int unit) 12467 { 12468 uint32 rval = 0; 12469 /* Set OAM LM CNG control such that 12470 1. All colored packets are counted, 12471 2. Use LM_COLOR_MODE bit to qualify pre FP CNG for UPMEP TX 12472 counters in IP 12473 3. Use LM_COLOR_MODE bit to qualify post FP CNG for DOWNMEP RX 12474 counters in IP 12475 */ 12476 soc_reg_field_set(unit, ING_OAM_LM_CNG_CONTROLr, &rval, 12477 LM_COLOR_MODEf, 1); 12478 soc_reg_field_set(unit, ING_OAM_LM_CNG_CONTROLr, &rval, 12479 UPMEP_TX_CNG_SOURCEf, 1); 12480 soc_reg_field_set(unit, ING_OAM_LM_CNG_CONTROLr, &rval, 12481 DOWNMEP_RX_CNG_SOURCEf, 0); 12482 soc_reg_field_set(unit, ING_OAM_LM_CNG_CONTROLr, &rval, 12483 MPLS_OAM_LM_COLOR_MODEf, 0); 12484 SOC_IF_ERROR_RETURN(WRITE_ING_OAM_LM_CNG_CONTROLr(unit, rval)); 12485 12486 rval = 0; 12487 /* include all colored packets for LM accounting on egress side */ 12488 soc_reg_field_set(unit, EGR_OAM_LM_CNG_CONTROLr, &rval, 12489 LM_COLOR_MODEf, 1); 12490 soc_reg_field_set(unit, EGR_OAM_LM_CNG_CONTROLr, &rval, 12491 MPLS_OAM_LM_COLOR_MODEf, 0); 12492 SOC_IF_ERROR_RETURN(WRITE_EGR_OAM_LM_CNG_CONTROLr(unit, rval)); 12493 12494 rval = 0; 12495 12496 /* Set OAM_LM_CPU_DATA_CONTROL to not to count 12497 CPU generated data packets for loss measurement */ 12498 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 12499 OAM_LCPU_TX_CNT_DISABLEf, 1); 12500 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 12501 OAM_LCPU_RX_CNT_DISABLEf, 1); 12502 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 12503 OAM_SRCPORT0_TX_CNT_DISABLEf, 1); 12504 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 12505 OAM_SRCPORT0_RX_CNT_DISABLEf, 1); 12506 SOC_IF_ERROR_RETURN(WRITE_OAM_LM_CPU_DATA_CONTROLr(unit, rval)); 12507 12508 return (BCM_E_NONE); 12509 } 12510 /* 12511 * Function: 12512 * _bcm_sb2_oam_lm_cng_cpu_ctrl_set 12513 * Purpose: 12514 * Set OAM LM cng and cpu data control 12515 * Parameters: 12516 * unit - (IN) BCM device number 12517 * Retruns: 12518 * BCM_E_XXX 12519 */ 12520 STATIC int 12521 _bcm_sb2_oam_lm_cng_cpu_ctrl_set (int unit, bcm_oam_endpoint_info_t *ep) 12522 { 12523 uint32 rval = 0; 12524 uint32 egr_rval = 0; 12525 soc_field_t field; 12526 int up_mep = 0; 12527 int color_mode = 0; 12528 int cng_source = 0; 12529 int count_pkt = 1; 12530 if (ep->lm_flags) { 12531 /* read LM CNG register */ 12532 SOC_IF_ERROR_RETURN(READ_ING_OAM_LM_CNG_CONTROLr(unit, &rval)); 12533 SOC_IF_ERROR_RETURN(READ_EGR_OAM_LM_CNG_CONTROLr(unit, &egr_rval)); 12534 12535 if (ep->lm_flags & BCM_OAM_LOSS_COUNT_GREEN_AND_YELLOW) { 12536 color_mode = 1; 12537 } 12538 12539 if(MPLS_LM_DM_ENDPOINT_TYPE(ep)){ 12540 field = MPLS_OAM_LM_COLOR_MODEf; 12541 }else{ 12542 field = LM_COLOR_MODEf; 12543 } 12544 12545 soc_reg_field_set(unit, ING_OAM_LM_CNG_CONTROLr, &rval, 12546 field, color_mode); 12547 soc_reg_field_set(unit, EGR_OAM_LM_CNG_CONTROLr, &egr_rval, 12548 field, color_mode); 12549 12550 if (ep->flags & BCM_OAM_ENDPOINT_UP_FACING) { 12551 up_mep = 1; 12552 } 12553 if (ep->lm_flags & BCM_OAM_LOSS_COUNT_POST_TRAFFIC_CONDITIONING) { 12554 cng_source = 1; 12555 } 12556 if (up_mep) { 12557 soc_reg_field_set(unit, ING_OAM_LM_CNG_CONTROLr, &rval, 12558 UPMEP_TX_CNG_SOURCEf, cng_source); 12559 } else { 12560 soc_reg_field_set(unit, ING_OAM_LM_CNG_CONTROLr, &rval, 12561 DOWNMEP_RX_CNG_SOURCEf, cng_source); 12562 } 12563 /* write back the registrs */ 12564 SOC_IF_ERROR_RETURN(WRITE_ING_OAM_LM_CNG_CONTROLr(unit, rval)); 12565 SOC_IF_ERROR_RETURN(WRITE_EGR_OAM_LM_CNG_CONTROLr(unit, egr_rval)); 12566 /* Read LM CPU data control */ 12567 SOC_IF_ERROR_RETURN(READ_OAM_LM_CPU_DATA_CONTROLr(unit, &rval)); 12568 if (ep->lm_flags & BCM_OAM_LOSS_COUNT_CPU_RX_PKT) { 12569 count_pkt = 0; 12570 } 12571 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 12572 OAM_LCPU_RX_CNT_DISABLEf, count_pkt); 12573 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 12574 OAM_SRCPORT0_RX_CNT_DISABLEf, count_pkt); 12575 12576 if (ep->lm_flags & BCM_OAM_LOSS_COUNT_CPU_TX_PKT) { 12577 count_pkt = 0; 12578 } else { 12579 count_pkt = 1; 12580 } 12581 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 12582 OAM_LCPU_TX_CNT_DISABLEf, count_pkt); 12583 soc_reg_field_set(unit, OAM_LM_CPU_DATA_CONTROLr, &rval, 12584 OAM_SRCPORT0_TX_CNT_DISABLEf, count_pkt); 12585 SOC_IF_ERROR_RETURN(WRITE_OAM_LM_CPU_DATA_CONTROLr(unit, rval)); 12586 } 12587 return (BCM_E_NONE); 12588 } 12589 12590 /* 12591 * Function: 12592 * _bcm_sb2_oam_olp_magic_port_set 12593 * Purpose: 12594 * Set Magic port used in OLP-XGS communication 12595 * Parameters: 12596 * unit - (IN) BCM device number 12597 * Retruns: 12598 * BCM_E_XXX 12599 */ 12600 STATIC int 12601 _bcm_sb2_oam_olp_magic_port_set(int unit) 12602 { 12603 uint64 rval, set_val; 12604 int modid; 12605 COMPILER_64_ZERO(rval); 12606 /* configure modid and the magic port */ 12607 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &modid)); 12608 SOC_IF_ERROR_RETURN(READ_IARB_OLP_CONFIG_1r(unit, &rval)); 12609 12610 COMPILER_64_SET(set_val, 0, modid); 12611 soc_reg64_field_set(unit, IARB_OLP_CONFIG_1r, &rval, MY_MODIDf, set_val); 12612 COMPILER_64_SET(set_val, 0, _BCM_OAM_OLP_COMMUNICATION_PORT); 12613 soc_reg64_field_set(unit, IARB_OLP_CONFIG_1r, &rval, MY_PORT_NUMf, set_val); 12614 12615 SOC_IF_ERROR_RETURN(WRITE_IARB_OLP_CONFIG_1r(unit, rval)); 12616 return (BCM_E_NONE); 12617 } 12618 12619 int 12620 _bcm_sb2_oam_set_egr_oam_rx_mode(int unit, int enable) 12621 { 12622 /* Since it is just one bit register, we directly write it with 12623 * the value. 12624 */ 12625 BCM_IF_ERROR_RETURN(WRITE_EGR_OAM_RX_MODE_FOR_CPUr(unit, enable)); 12626 12627 return BCM_E_NONE; 12628 } 12629 12630 /* 12631 * Function: 12632 * _bcm_sb2_oam_macsa_zero_check_disable 12633 * Purpose: 12634 * Disable MACSA Zero check 12635 * Parameters: 12636 * unit - (IN) BCM device number 12637 * Retruns: 12638 * BCM_E_XXX 12639 */ 12640 STATIC int 12641 _bcm_sb2_oam_macsa_zero_check_disable(int unit) 12642 { 12643 uint32 rval = 0; 12644 soc_reg_field_set(unit, OAM_CONTROLr, &rval, 12645 MACSA_ZERO_CHECK_ENABLEf, 0); 12646 SOC_IF_ERROR_RETURN(WRITE_OAM_CONTROLr(unit, rval)); 12647 soc_reg_field_set(unit, EGR_OAM_CONTROLr, &rval, 12648 MACSA_ZERO_CHECK_ENABLEf, 0); 12649 SOC_IF_ERROR_RETURN(WRITE_EGR_OAM_CONTROLr(unit, rval)); 12650 return (BCM_E_NONE); 12651 } 12652 12653 /* 12654 * Function: 12655 * _bcm_sb2_oam_endpoint_cleanup 12656 * Purpose: 12657 * Free all the counters and the indexes allocated on endpoint create 12658 * failure 12659 * Parameters: 12660 * unit - (IN) BCM device number 12661 * upmep- (IN) UpMep/DownMep 12662 * hash_key (IN) 12663 * hash_data (IN) Pointer to endpoint hash data 12664 * Retruns: 12665 * BCM_E_XXX 12666 */ 12667 void 12668 _bcm_sb2_oam_endpoint_cleanup(int unit, int upmep, 12669 _bcm_oam_hash_key_t hash_key, 12670 _bcm_oam_hash_data_t *hash_data) 12671 { 12672 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 12673 int rv = BCM_E_NONE; 12674 _bcm_oam_hash_data_t h_data_stored; /* Stored hash data. */ 12675 uint8 active_mdl = 0; 12676 12677 rv = _bcm_sb2_oam_control_get(unit, &oc); 12678 if (BCM_FAILURE(rv)) { 12679 return; 12680 } 12681 if (upmep) { 12682 /* Delete Egress MP group entry, if already added */ 12683 rv = _bcm_sb2_oam_egr_mp_group_entry_destroy(unit, hash_data, 12684 &active_mdl); 12685 /* Update Ingress MP group table(MP_GROUP_ENTRY) */ 12686 rv = _bcm_sb2_oam_ing_mp_group_entry_destroy(unit, hash_data, &active_mdl); 12687 } else { 12688 /* Update Ingress MP group table(MP_GROUP_ENTRY) */ 12689 rv = _bcm_sb2_oam_ing_mp_group_entry_destroy(unit, hash_data, &active_mdl); 12690 /* Delete Egress MP group table entry, if already added */ 12691 rv = _bcm_sb2_oam_egr_mp_group_entry_destroy(unit, hash_data, 12692 &active_mdl); 12693 } 12694 /* return rx & tx counters allocated if any */ 12695 rv =_bcm_sb2_oam_free_counter(unit, hash_data); 12696 12697 /* Clear opcode profile entry, if any */ 12698 if (hash_data->profile_index != _BCM_OAM_INVALID_INDEX) { 12699 if (upmep) { 12700 rv = soc_profile_mem_delete(unit, 12701 &oc->egr_oam_opcode_control_profile, 12702 _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(hash_data->profile_index)); 12703 } else { 12704 rv = soc_profile_mem_delete(unit, &oc->oam_opcode_control_profile, 12705 _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(hash_data->profile_index)); 12706 } 12707 } 12708 /* Clear dglp profile, if any */ 12709 if (hash_data->dglp1_profile_index != _BCM_OAM_INVALID_INDEX) { 12710 if (upmep) { 12711 rv = soc_profile_mem_delete(unit, &oc->egr_oam_dglp_profile, 12712 hash_data->dglp1_profile_index); 12713 } else { 12714 rv = soc_profile_mem_delete(unit, &oc->ing_oam_dglp_profile, 12715 hash_data->dglp1_profile_index); 12716 } 12717 } 12718 12719 if (hash_data->dglp2_profile_index != _BCM_OAM_INVALID_INDEX) { 12720 if (upmep) { 12721 rv = soc_profile_mem_delete(unit, &oc->egr_oam_dglp_profile, 12722 hash_data->dglp2_profile_index); 12723 } else { 12724 rv = soc_profile_mem_delete(unit, &oc->ing_oam_dglp_profile, 12725 hash_data->dglp2_profile_index); 12726 } 12727 } 12728 12729 /* Decrement TPID ref count, if already incremented */ 12730 if (hash_data->outer_tpid_profile_index != _BCM_OAM_INVALID_INDEX) { 12731 rv = _bcm_sb2_tpid_entry_delete(unit, 12732 hash_data->outer_tpid_profile_index, 12733 BCM_OAM_TPID_TYPE_OUTER); 12734 } 12735 if (hash_data->subport_tpid_profile_index != _BCM_OAM_INVALID_INDEX) { 12736 rv = _bcm_sb2_tpid_entry_delete(unit, 12737 hash_data->subport_tpid_profile_index, 12738 BCM_OAM_TPID_TYPE_SUBPORT); 12739 } 12740 if (hash_data->inner_tpid_profile_index != _BCM_OAM_INVALID_INDEX) { 12741 rv = _bcm_sb2_tpid_entry_delete(unit, 12742 hash_data->inner_tpid_profile_index, 12743 BCM_OAM_TPID_TYPE_INNER); 12744 } 12745 12746 /* It might already have been deleted as well. 12747 * So just log it as debug, in case it fails */ 12748 rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_delete(unit, hash_data); 12749 if (BCM_FAILURE(rv)) { 12750 LOG_DEBUG(BSL_LS_BCM_OAM, 12751 (BSL_META_U(unit, 12752 "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) -" 12753 " %s.\n"), unit, hash_data->ep_id, bcm_errmsg(rv))); 12754 } 12755 #if defined(INCLUDE_BHH) 12756 if(BHH_EP_TYPE(hash_data)) { 12757 shr_idxres_list_free(oc->bhh_pool, BCM_OAM_BHH_GET_UKERNEL_EP(hash_data->ep_id)); 12758 } else 12759 #endif 12760 if (1 == hash_data->is_remote) { 12761 /* If remote endpoint, return index to remp pool */ 12762 shr_idxres_list_free(oc->rmep_pool, hash_data->remote_index); 12763 } else { 12764 /* If local endpoint, return index to lmep pool */ 12765 shr_idxres_list_free(oc->lmep_pool, hash_data->local_tx_index); 12766 } 12767 12768 /* return index to mep pool */ 12769 /* For BHH endpoints it needs to remain reserved. */ 12770 if (!BHH_EP_TYPE(hash_data)) { 12771 shr_idxres_list_free(oc->mep_pool, hash_data->ep_id); 12772 } 12773 12774 /* Return entry to hash data entry to free pool. */ 12775 shr_htb_find(oc->ma_mep_htbl, hash_key, 12776 (shr_htb_data_t *)&h_data_stored, 1); 12777 12778 /* Clear contents of hash data element. */ 12779 _BCM_OAM_HASH_DATA_CLEAR(hash_data); 12780 } 12781 12782 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 12783 void 12784 _bcm_sb2_oam_group_info_dump(int unit, bcm_oam_group_t group_index, 12785 _bcm_oam_group_data_t *group_p) 12786 { 12787 int rv; 12788 bcm_oam_group_info_t group_info; 12789 12790 /* Initialize the group information structure. */ 12791 bcm_oam_group_info_t_init(&group_info); 12792 12793 /* Retrieve group information and set in group_info structure. */ 12794 rv = _bcm_sb2_oam_get_group(unit, group_index, group_p, &group_info); 12795 if (BCM_FAILURE(rv)) { 12796 LOG_ERROR(BSL_LS_BCM_OAM, 12797 (BSL_META_U(unit, 12798 "OAM(unit %d) Error: _bcm_tr3_oam_group_info_dump" 12799 " (GID=%d) - %s.\n"), 12800 unit, group_index, bcm_errmsg(rv))); 12801 return; 12802 } 12803 LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n"))); 12804 LOG_CLI((BSL_META_U(unit,"Group ID = %d details\r\n"), group_index)); 12805 LOG_CLI((BSL_META_U(unit,"Group Name = %s\r\n"), group_info.name)); 12806 LOG_CLI((BSL_META_U(unit,"Flags = %d\r\n"), group_info.flags)); 12807 LOG_CLI((BSL_META_U(unit,"Faults = %d\r\n"), group_info.faults)); 12808 LOG_CLI((BSL_META_U(unit,"Persistent_faults = %d\r\n"), 12809 group_info.persistent_faults)); 12810 LOG_CLI((BSL_META_U(unit,"clear_persistent_faults = %d\r\n"), 12811 group_info.clear_persistent_faults)); 12812 LOG_CLI((BSL_META_U(unit,"lowest_alarm_priority = %d\r\n"), 12813 group_info.lowest_alarm_priority)); 12814 LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n"))); 12815 } 12816 12817 void 12818 _bcm_sb2_oam_hash_data_dump(int unit, _bcm_oam_hash_data_t *h_data_p) 12819 { 12820 LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n"))); 12821 LOG_CLI((BSL_META_U(unit,"EP ID = %d\r\n"),h_data_p->ep_id)); 12822 LOG_CLI((BSL_META_U(unit,"Type = %d\r\n"),h_data_p->type)); 12823 LOG_CLI((BSL_META_U(unit,"In use = %d\r\n"),h_data_p->in_use)); 12824 LOG_CLI((BSL_META_U(unit,"Remote = %d\r\n"),h_data_p->is_remote)); 12825 LOG_CLI((BSL_META_U(unit,"Name = %d\r\n"),h_data_p->name)); 12826 LOG_CLI((BSL_META_U(unit,"Level = %d\r\n"),h_data_p->level)); 12827 LOG_CLI((BSL_META_U(unit,"Outer Vlan = %d\r\n"),h_data_p->vlan)); 12828 LOG_CLI((BSL_META_U(unit,"Inner Vlan = %d\r\n"),h_data_p->inner_vlan)); 12829 LOG_CLI((BSL_META_U(unit,"Gport = %d\r\n"),h_data_p->gport)); 12830 LOG_CLI((BSL_META_U(unit,"SGLP = %d\r\n"),h_data_p->sglp)); 12831 LOG_CLI((BSL_META_U(unit,"DGLP = %d\r\n"),h_data_p->dglp)); 12832 LOG_CLI((BSL_META_U(unit,"Tx ena = %d\r\n"),h_data_p->local_tx_enabled)); 12833 LOG_CLI((BSL_META_U(unit,"Rx ena = %d\r\n"),h_data_p->local_rx_enabled)); 12834 LOG_CLI((BSL_META_U(unit,"Grp idx = %d\r\n"),h_data_p->group_index)); 12835 LOG_CLI((BSL_META_U(unit,"Remote idx = %d\r\n"),h_data_p->remote_index)); 12836 LOG_CLI((BSL_META_U(unit,"LM ctr idx = %d\r\n"),h_data_p->lm_counter_index)); 12837 LOG_CLI((BSL_META_U(unit,"Pri map idx = %d\r\n"),h_data_p->pri_map_index)); 12838 LOG_CLI((BSL_META_U(unit,"Profile Idx = %d\r\n"),h_data_p->profile_index)); 12839 LOG_CLI((BSL_META_U(unit,"Local Tx index = %d\r\n"),h_data_p->local_tx_index)); 12840 LOG_CLI((BSL_META_U(unit,"Local Rx index = %d\r\n"),h_data_p->local_rx_index)); 12841 LOG_CLI((BSL_META_U(unit,"VP = %d\r\n"),h_data_p->vp)); 12842 LOG_CLI((BSL_META_U(unit,"Flags = 0x%x\r\n"),h_data_p->flags)); 12843 LOG_CLI((BSL_META_U(unit,"Flags2 = 0x%x\r\n"),h_data_p->flags2)); 12844 LOG_CLI((BSL_META_U(unit,"Period = %d\r\n"),h_data_p->period)); 12845 LOG_CLI((BSL_META_U(unit,"Opcode flags = 0x%x\r\n"),h_data_p->opcode_flags)); 12846 LOG_CLI((BSL_META_U(unit,"TS format = %d\r\n"),h_data_p->ts_format)); 12847 LOG_CLI((BSL_META_U(unit,"Label = 0x%x\r\n"),h_data_p->label)); 12848 LOG_CLI((BSL_META_U(unit,"Vlan Pri = %d\r\n"),h_data_p->vlan_pri)); 12849 LOG_CLI((BSL_META_U(unit,"Egress if = 0x%x\r\n"),h_data_p->egress_if)); 12850 LOG_CLI((BSL_META_U(unit,"Domain = %d\r\n"),h_data_p->oam_domain)); 12851 LOG_CLI((BSL_META_U(unit,"Egr pri map idx = %d\r\n"),h_data_p->egr_pri_map_index)); 12852 LOG_CLI((BSL_META_U(unit,"Rx ctr = %d\r\n"),h_data_p->rx_ctr)); 12853 LOG_CLI((BSL_META_U(unit,"Tx ctr = %d\r\n"),h_data_p->tx_ctr)); 12854 LOG_CLI((BSL_META_U(unit,"src_pp_port = %d\r\n"),h_data_p->src_pp_port)); 12855 LOG_CLI((BSL_META_U(unit,"dst_pp_port = %d\r\n"),h_data_p->dst_pp_port)); 12856 LOG_CLI((BSL_META_U(unit,"DGLP1 = %d\r\n"),h_data_p->dglp1)); 12857 LOG_CLI((BSL_META_U(unit,"DGLP2 = %d\r\n"),h_data_p->dglp2)); 12858 LOG_CLI((BSL_META_U(unit,"DGLP1 Profile idx = %d\r\n"),h_data_p->dglp1_profile_index)); 12859 LOG_CLI((BSL_META_U(unit,"DGLP2 Profile idx = %d\r\n"),h_data_p->dglp2_profile_index)); 12860 LOG_CLI((BSL_META_U(unit,"Outer TPID = 0x%04X\r\n"),h_data_p->outer_tpid)); 12861 LOG_CLI((BSL_META_U(unit,"Inner TPID = 0x%04X\r\n"),h_data_p->inner_tpid)); 12862 LOG_CLI((BSL_META_U(unit,"SubPort TPID = %d\r\n"),h_data_p->subport_tpid)); 12863 LOG_CLI((BSL_META_U(unit,"Outer TPID profile idx = %d\r\n"),h_data_p->outer_tpid_profile_index)); 12864 LOG_CLI((BSL_META_U(unit,"Inner TPID profile idx = %d\r\n"),h_data_p->inner_tpid_profile_index)); 12865 LOG_CLI((BSL_META_U(unit,"SubPort TPID profile idx = %d\r\n"),h_data_p->subport_tpid_profile_index)); 12866 LOG_CLI((BSL_META_U(unit,"MA Base idx = %d\r\n"),h_data_p->ma_base_index)); 12867 LOG_CLI((BSL_META_U(unit,"Trunk ID = %d\r\n"),h_data_p->trunk_id)); 12868 LOG_CLI((BSL_META_U(unit,"Active MDL BITMAP = 0x%x\r\n"),h_data_p->active_mdl_bitmap)); 12869 LOG_CLI((BSL_META_U(unit,"Internal flags = 0x%x\r\n"),h_data_p->int_flags)); 12870 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM) 12871 LOG_CLI((BSL_META_U(unit,"Src Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"), 12872 h_data_p->src_mac_address[0], h_data_p->src_mac_address[1], 12873 h_data_p->src_mac_address[2], h_data_p->src_mac_address[3], 12874 h_data_p->src_mac_address[4], h_data_p->src_mac_address[5])); 12875 LOG_CLI((BSL_META_U(unit,"Dst Mac = %02X:%02X:%02X:%02X:%02X:%02X\r\n"), 12876 h_data_p->dst_mac_address[0], h_data_p->dst_mac_address[1], 12877 h_data_p->dst_mac_address[2], h_data_p->dst_mac_address[3], 12878 h_data_p->dst_mac_address[4], h_data_p->dst_mac_address[5])); 12879 LOG_CLI((BSL_META_U(unit,"Inner vlan pri = %d\r\n"),h_data_p->inner_vlan_pri)); 12880 #endif 12881 LOG_CLI((BSL_META_U(unit,"Vccv Type = %d\r\n"),h_data_p->vccv_type)); 12882 LOG_CLI((BSL_META_U(unit,"VPN = %d\r\n"),h_data_p->vpn)); 12883 LOG_CLI((BSL_META_U(unit,"PM profile attached = %d\r\n"),h_data_p->pm_profile_attached)); 12884 LOG_CLI((BSL_META_U(unit,"CTR Field id = %d\r\n"),h_data_p->ctr_field_id)); 12885 LOG_CLI((BSL_META_U(unit,"EGR CTR Field id = %d\r\n"),h_data_p->egr_ctr_field_id)); 12886 #if defined (INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM) 12887 LOG_CLI((BSL_META_U(unit,"LM DM Internal flag = %u\r\n"),h_data_p->lm_dm_int_flag)); 12888 LOG_CLI((BSL_META_U(unit,"LM DM Session Id = %u\r\n"),h_data_p->lm_dm_uc_session_id)); 12889 #endif 12890 LOG_CLI((BSL_META_U(unit,"Resolved trunk gport based on trunk " 12891 "index 0x%x\r\n"), 12892 h_data_p->resolved_trunk_gport)); 12893 LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n"))); 12894 } 12895 12896 /* 12897 * Function: 12898 * _bcm_oam_sw_dump 12899 * Purpose: 12900 * Displays oam information maintained by software. 12901 * Parameters: 12902 * unit - Device unit number 12903 * Returns: 12904 * None 12905 */ 12906 void 12907 _bcm_sb2_oam_sw_dump(int unit) 12908 { 12909 int rv; 12910 int grp_idx; 12911 _bcm_oam_control_t *oc; 12912 _bcm_oam_group_data_t *group_p = NULL; 12913 _bcm_oam_ep_list_t *ep_list_p = NULL; 12914 _bcm_oam_hash_data_t *ep_data_p = NULL; 12915 12916 LOG_CLI((BSL_META_U(unit,"OAM\n"))); 12917 /* Get OAM control structure. */ 12918 rv = _bcm_sb2_oam_control_get(unit, &oc); 12919 if(BCM_FAILURE(rv)) { 12920 LOG_ERROR(BSL_LS_BCM_OAM, 12921 (BSL_META_U(unit, 12922 "OAM(unit %d) Error: Get oam control variable\n"), 12923 unit)); 12924 12925 return; 12926 } 12927 12928 _BCM_OAM_LOCK(oc); 12929 12930 group_p = oc->group_info; 12931 for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) { 12932 if (group_p[grp_idx].in_use == 1) { 12933 ep_list_p = *(group_p[grp_idx].ep_list); 12934 _bcm_sb2_oam_group_info_dump(unit, grp_idx, group_p); 12935 while (ep_list_p != NULL) { 12936 ep_data_p = ep_list_p->ep_data_p; 12937 _bcm_sb2_oam_hash_data_dump(unit, ep_data_p); 12938 ep_list_p = ep_list_p->next; 12939 } 12940 } 12941 } 12942 12943 _BCM_OAM_UNLOCK(oc); 12944 12945 } 12946 void _bcm_sb2_oam_ma_idx_to_ep_id_mapping_print(int unit) 12947 { 12948 _bcm_oam_control_t *oc = NULL; /* Pointer to control structure. */ 12949 int i = 0; 12950 int rv = BCM_E_NONE; 12951 12952 rv = _bcm_sb2_oam_control_get(unit, &oc); 12953 if ((BCM_FAILURE(rv)) || (oc == NULL)) { 12954 return; 12955 } 12956 _BCM_OAM_LOCK(oc); 12957 12958 if (oc->_bcm_oam_ma_idx_to_ep_id_map != NULL) { 12959 for (i = 0; i < (oc->ma_idx_count + oc->egr_ma_idx_count);i++) { 12960 if (oc->_bcm_oam_ma_idx_to_ep_id_map[i] != _BCM_OAM_INVALID_INDEX) { 12961 LOG_CLI((BSL_META_U(unit,"MA_IDX = %d EP_ID = %d\r\n"), 12962 i, oc->_bcm_oam_ma_idx_to_ep_id_map[i])); 12963 } 12964 } 12965 } 12966 _BCM_OAM_UNLOCK(oc); 12967 } 12968 #endif 12969 12970 #if defined(BCM_WARM_BOOT_SUPPORT) 12971 #ifdef _SABER2_DEBUG 12972 /* 12973 * Function: 12974 * _bcm_sb2_oam_tx_counter_recover 12975 * Purpose: 12976 * Recover Rx counter for MEP 12977 * Parameters: 12978 * unit - (IN) BCM device number 12979 * Retruns: 12980 * BCM_E_XXX 12981 */ 12982 STATIC int 12983 _bcm_sb2_oam_tx_counter_recover(int unit, soc_mem_t mem, 12984 uint32 *entry, 12985 _bcm_oam_hash_data_t *h_data_p) 12986 { 12987 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 12988 int rv = BCM_E_NONE;/* Operation return status. */ 12989 int up_mep = 0; 12990 sb2_mep_ctr_info_t *ctr_info; 12991 shr_aidxres_list_handle_t *ctr_pool; 12992 int *map_id; 12993 int ctr_type = 0; 12994 int ctr_valid = 0; 12995 int ctr_mdl = 0; 12996 int ctr_pool_id = 0; 12997 uint32 profile_index = 0; 12998 uint32 map_ptr = 0; 12999 13000 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 13001 ctr_info = sb2_mep_ctr_info; 13002 if (mem == MP_GROUPm) { 13003 up_mep = 1; 13004 map_id = &h_data_p->pri_map_index; 13005 } else if (mem == EGR_MP_GROUPm) { 13006 map_id = &h_data_p->egr_pri_map_index; 13007 } else { 13008 return BCM_E_INTERNAL; 13009 } 13010 ctr_pool = oc->ing_lm_ctr_pool; 13011 ctr_valid = soc_mem_field32_get(unit, mem, 13012 (uint32 *)entry, ctr_info[0].ctr_valid); 13013 ctr_pool_id = soc_mem_field32_get(unit, mem, 13014 (uint32 *)entry, ctr_info[0].ctr_pool_id); 13015 13016 if (ctr_valid) { 13017 ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13018 ctr_info[0].ctr_mep_type); 13019 ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13020 ctr_info[0].ctr_mep_mdl); 13021 if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) { 13022 h_data_p->tx_ctr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13023 ctr_info[0].ctr_base_ptr); 13024 13025 h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 13026 map_ptr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13027 ctr_info[0].ctr_profile); 13028 13029 profile_index = _BCM_SB2_SERVICE_PRI_MAP_PTR_TO_PROFILE_INDEX(map_ptr); 13030 rv = _bcm_sb2_service_pri_map_info_id_get(unit, 13031 profile_index, 13032 map_id); 13033 13034 if (BCM_FAILURE(rv)) { 13035 LOG_ERROR(BSL_LS_BCM_OAM, 13036 (BSL_META_U(unit, 13037 "OAM(unit %d) Error: Service pri map id get failed " 13038 "(EP=%d) - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 13039 return (rv); 13040 } 13041 /* Allocate 8 consecutive couters from the pool */ 13042 rv = shr_aidxres_list_reserve_block(ctr_pool[ctr_pool_id], 13043 h_data_p->tx_ctr, 8); 13044 if (BCM_FAILURE(rv)) { 13045 LOG_ERROR(BSL_LS_BCM_OAM, 13046 (BSL_META_U(unit, 13047 "OAM(unit %d) Error: LM counter block alloc failed " 13048 "(EP=%d) - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 13049 return (rv); 13050 } 13051 } 13052 } 13053 ctr_valid = soc_mem_field32_get(unit, mem, 13054 (uint32 *)entry, ctr_info[1].ctr_valid); 13055 ctr_pool_id = soc_mem_field32_get(unit, mem, 13056 (uint32 *)entry, ctr_info[1].ctr_pool_id); 13057 if (ctr_valid) { 13058 ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13059 ctr_info[1].ctr_mep_type); 13060 ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13061 ctr_info[1].ctr_mep_mdl); 13062 if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) { 13063 h_data_p->tx_ctr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13064 ctr_info[1].ctr_base_ptr); 13065 13066 h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 13067 map_ptr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13068 ctr_info[1].ctr_profile); 13069 profile_index = _BCM_SB2_SERVICE_PRI_MAP_PTR_TO_PROFILE_INDEX(map_ptr); 13070 rv = _bcm_sb2_service_pri_map_info_id_get(unit, 13071 profile_index, 13072 map_id); 13073 13074 if (BCM_FAILURE(rv)) { 13075 LOG_ERROR(BSL_LS_BCM_OAM, 13076 (BSL_META_U(unit, 13077 "OAM(unit %d) Error: Service pri map id get failed " 13078 "(EP=%d) - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 13079 return (rv); 13080 } 13081 /* Allocate 8 consecutive couters from the pool */ 13082 rv = shr_aidxres_list_reserve_block(ctr_pool[ctr_pool_id], 13083 h_data_p->tx_ctr, 8); 13084 if (BCM_FAILURE(rv)) { 13085 LOG_ERROR(BSL_LS_BCM_OAM, 13086 (BSL_META_U(unit, 13087 "OAM(unit %d) Error: LM counter block alloc failed " 13088 "(EP=%d) - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 13089 return (rv); 13090 } 13091 } 13092 } 13093 return (rv); 13094 } 13095 13096 #endif /* _SABER2_DEBUG */ 13097 13098 /* 13099 * Function: 13100 * _bcm_sb2_oam_rx_counter_recover 13101 * Purpose: 13102 * Recover Rx counter for MEP 13103 * Parameters: 13104 * unit - (IN) BCM device number 13105 * Retruns: 13106 * BCM_E_XXX 13107 */ 13108 STATIC int 13109 _bcm_sb2_oam_rx_counter_recover(int unit, soc_mem_t mem, 13110 uint32 *entry, 13111 _bcm_oam_hash_data_t *h_data_p) 13112 { 13113 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 13114 int rv = BCM_E_NONE;/* Operation return status. */ 13115 int up_mep = 0; 13116 sb2_mep_ctr_info_t *ctr_info; 13117 shr_aidxres_list_handle_t *ctr_pool; 13118 int *map_id; 13119 int ctr_valid = 0; 13120 int ctr_mdl = 0; 13121 int ctr_type = 0; 13122 int ctr_pool_id = 0; 13123 int ctr_base_ptr = 0; 13124 uint32 profile_index = 0; 13125 uint32 map_ptr = 0; 13126 13127 13128 13129 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 13130 ctr_info = sb2_mep_ctr_info; 13131 if (mem == EGR_MP_GROUPm) { 13132 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 13133 up_mep = 1; 13134 } 13135 map_id = &h_data_p->egr_pri_map_index; 13136 } else { 13137 map_id = &h_data_p->pri_map_index; 13138 } 13139 ctr_pool = oc->ing_lm_ctr_pool; 13140 ctr_valid = soc_mem_field32_get(unit, mem, 13141 (uint32 *)entry, ctr_info[0].ctr_valid); 13142 ctr_pool_id = soc_mem_field32_get(unit, mem, 13143 (uint32 *)entry, ctr_info[0].ctr_pool_id); 13144 13145 if (ctr_valid) { 13146 ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13147 ctr_info[0].ctr_mep_type); 13148 ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13149 ctr_info[0].ctr_mep_mdl); 13150 if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) { 13151 ctr_base_ptr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13152 ctr_info[0].ctr_base_ptr); 13153 /* Encode pool id as well in the ctr id */ 13154 h_data_p->rx_ctr = ctr_base_ptr | (ctr_pool_id << 24); 13155 13156 h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 13157 map_ptr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13158 ctr_info[0].ctr_profile); 13159 profile_index = _BCM_SB2_SERVICE_PRI_MAP_PTR_TO_PROFILE_INDEX(map_ptr); 13160 rv = _bcm_sb2_service_pri_map_info_id_get(unit, 13161 profile_index, 13162 map_id); 13163 13164 if (BCM_FAILURE(rv)) { 13165 LOG_ERROR(BSL_LS_BCM_OAM, 13166 (BSL_META_U(unit, 13167 "OAM(unit %d) Error: Failed to get map" 13168 "id from hw idx(EP=%d) - %s.\n"), unit, 13169 h_data_p->ep_id, bcm_errmsg(rv))); 13170 return (rv); 13171 } 13172 rv = _bcm_sb2_service_pri_map_reference_add(unit, *map_id); 13173 if (BCM_FAILURE(rv)) { 13174 LOG_ERROR(BSL_LS_BCM_OAM, 13175 (BSL_META_U(unit, 13176 "OAM(unit %d) Error: LM counter profile ref count " 13177 "increment failed (EP=%d) - %s.\n"), unit, 13178 h_data_p->ep_id, bcm_errmsg(rv))); 13179 return (rv); 13180 } 13181 /* Allocate 8 consecutive couters from the pool */ 13182 rv = shr_aidxres_list_reserve_block(ctr_pool[ctr_pool_id], 13183 ctr_base_ptr, 8); 13184 if (BCM_FAILURE(rv)) { 13185 LOG_ERROR(BSL_LS_BCM_OAM, 13186 (BSL_META_U(unit, 13187 "OAM(unit %d) Error: LM counter block alloc failed " 13188 "(EP=%d) - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 13189 return (rv); 13190 } 13191 h_data_p->ctr_field_id = 0; 13192 } 13193 } 13194 ctr_valid = soc_mem_field32_get(unit, mem, 13195 (uint32 *)entry, ctr_info[1].ctr_valid); 13196 ctr_pool_id = soc_mem_field32_get(unit, mem, 13197 (uint32 *)entry, ctr_info[1].ctr_pool_id); 13198 if (ctr_valid) { 13199 ctr_type = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13200 ctr_info[1].ctr_mep_type); 13201 ctr_mdl = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13202 ctr_info[1].ctr_mep_mdl); 13203 if ((ctr_type == up_mep) && (ctr_mdl == h_data_p->level)) { 13204 ctr_base_ptr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13205 ctr_info[1].ctr_base_ptr); 13206 /* Encode pool id as well in the ctr id */ 13207 h_data_p->rx_ctr = ctr_base_ptr | (ctr_pool_id << 24); 13208 13209 h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 13210 map_ptr = soc_mem_field32_get(unit, mem, (uint32 *)entry, 13211 ctr_info[1].ctr_profile); 13212 profile_index = _BCM_SB2_SERVICE_PRI_MAP_PTR_TO_PROFILE_INDEX(map_ptr); 13213 rv = _bcm_sb2_service_pri_map_info_id_get(unit, 13214 profile_index, 13215 map_id); 13216 13217 if (BCM_FAILURE(rv)) { 13218 LOG_ERROR(BSL_LS_BCM_OAM, 13219 (BSL_META_U(unit, 13220 "OAM(unit %d) Error: Failed to get map" 13221 "id from hw idx(EP=%d) - %s.\n"), unit, 13222 h_data_p->ep_id, bcm_errmsg(rv))); 13223 return (rv); 13224 } 13225 rv = _bcm_sb2_service_pri_map_reference_add(unit, *map_id); 13226 if (BCM_FAILURE(rv)) { 13227 LOG_ERROR(BSL_LS_BCM_OAM, 13228 (BSL_META_U(unit, 13229 "OAM(unit %d) Error: LM counter profile ref count " 13230 "increment failed (EP=%d) - %s.\n"), unit, 13231 h_data_p->ep_id, bcm_errmsg(rv))); 13232 return (rv); 13233 } 13234 /* Allocate 8 consecutive couters from the pool */ 13235 rv = shr_aidxres_list_reserve_block(ctr_pool[ctr_pool_id], 13236 ctr_base_ptr, 8); 13237 if (BCM_FAILURE(rv)) { 13238 LOG_ERROR(BSL_LS_BCM_OAM, 13239 (BSL_META_U(unit, 13240 "OAM(unit %d) Error: LM counter block alloc failed " 13241 "(EP=%d) - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 13242 return (rv); 13243 } 13244 h_data_p->ctr_field_id = 1; 13245 } 13246 } 13247 return (rv); 13248 } 13249 /* 13250 * Function: 13251 * _bcm_sb2_oam_endpoint_alloc 13252 * Purpose: 13253 * Allocate an endpoint memory element. 13254 * Parameters: 13255 * ep_pp - (IN/OUT) Pointer to endpoint address pointer. 13256 * Returns: 13257 * BCM_E_XXX 13258 */ 13259 STATIC int 13260 _bcm_sb2_oam_endpoint_alloc(bcm_oam_endpoint_info_t **ep_pp) 13261 { 13262 bcm_oam_endpoint_info_t *ep_p = NULL; 13263 13264 _BCM_OAM_ALLOC(ep_p, bcm_oam_endpoint_info_t, 13265 sizeof(bcm_oam_endpoint_info_t), "Endpoint info"); 13266 if (NULL == ep_p) { 13267 return (BCM_E_MEMORY); 13268 } 13269 13270 *ep_pp = ep_p; 13271 13272 return (BCM_E_NONE); 13273 13274 } 13275 13276 STATIC void 13277 _bcm_sb2_oam_copy_lmdm_scache_info_to_hash_data( 13278 _bcm_lmdm_oam_scache_info_t *src, 13279 _bcm_oam_hash_data_t *dest) 13280 { 13281 #if defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM) 13282 dest->vlan = src->vlan; 13283 dest->inner_vlan = src->inner_vlan; 13284 dest->inner_tpid = src->inner_tpid; 13285 dest->outer_tpid = src->outer_tpid; 13286 dest->vlan_pri = src->vlan_pri; 13287 dest->inner_vlan_pri = src->inner_vlan_pri; 13288 sal_memcpy(&(dest->dst_mac_address), &(src->dst_mac_address), 13289 sizeof(bcm_mac_t)); 13290 sal_memcpy(&(dest->src_mac_address), &(src->src_mac_address), 13291 sizeof(bcm_mac_t)); 13292 dest->lm_dm_int_flag = src->lm_dm_int_flag; 13293 dest->lm_dm_uc_session_id = src->lm_dm_uc_session_id; 13294 #endif 13295 #if defined(INCLUDE_MPLS_LM_DM) 13296 dest->group_index = src->group_index; 13297 #endif 13298 dest->vpn = src->vpn; 13299 dest->egr_ctr_field_id = src->egr_ctr_field_id; 13300 } 13301 13302 STATIC void 13303 _bcm_sb2_oam_copy_lmdm_hash_data_to_scache_info( 13304 _bcm_oam_hash_data_t *src, 13305 _bcm_lmdm_oam_scache_info_t *dest) 13306 { 13307 #if defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM) 13308 dest->vlan = src->vlan; 13309 dest->inner_vlan = src->inner_vlan; 13310 dest->inner_tpid = src->inner_tpid; 13311 dest->outer_tpid = src->outer_tpid; 13312 dest->vlan_pri = src->vlan_pri; 13313 dest->inner_vlan_pri = src->inner_vlan_pri; 13314 sal_memcpy(&(dest->dst_mac_address), &(src->dst_mac_address), 13315 sizeof(bcm_mac_t)); 13316 sal_memcpy(&(dest->src_mac_address), &(src->src_mac_address), 13317 sizeof(bcm_mac_t)); 13318 dest->lm_dm_int_flag = src->lm_dm_int_flag; 13319 dest->lm_dm_uc_session_id = src->lm_dm_uc_session_id; 13320 #endif 13321 #if defined(INCLUDE_MPLS_LM_DM) 13322 dest->group_index = src->group_index; 13323 #endif 13324 dest->vpn = src->vpn; 13325 dest->egr_ctr_field_id = src->egr_ctr_field_id; 13326 } 13327 13328 #if defined(INCLUDE_MPLS_LM_DM) 13329 STATIC void 13330 _bcm_sb2_oam_copy_egr_label_to_scache( 13331 _bcm_oam_hash_data_t *src, _bcm_sb2_oam_egr_label_scache_info_t *dest) 13332 { 13333 dest->egr_label = src->egr_label; 13334 dest->exp = src->egr_label_exp; 13335 dest->ttl = src->egr_label_ttl; 13336 } 13337 13338 STATIC void 13339 _bcm_sb2_oam_copy_egr_label_scache_to_hash_data( 13340 _bcm_sb2_oam_egr_label_scache_info_t *src, _bcm_oam_hash_data_t *dst) 13341 { 13342 dst->egr_label = src->egr_label; 13343 dst->egr_label_exp = src->exp; 13344 dst->egr_label_ttl = src->ttl; 13345 } 13346 #endif 13347 13348 STATIC void 13349 _bcm_sb2_oam_lmdm_scache_info_set(_bcm_oam_hash_data_t *h_data_p, 13350 uint8 *scache, 13351 _bcm_oam_control_t *oc) 13352 { 13353 _bcm_lmdm_oam_scache_info_t *scache_info; 13354 13355 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 13356 #if defined(INCLUDE_ETH_LM_DM) 13357 scache_info = (_bcm_lmdm_oam_scache_info_t *)(scache + 13358 _BCM_SB2_OAM_LM_DM_UP_MEP_SCACHE_INFO_LOCATION(h_data_p->local_rx_index)); 13359 _bcm_sb2_oam_copy_lmdm_hash_data_to_scache_info(h_data_p, scache_info); 13360 #endif 13361 } else { 13362 scache_info = (_bcm_lmdm_oam_scache_info_t *)(scache + 13363 _BCM_SB2_OAM_LM_DM_DOWN_MEP_SCACHE_INFO_LOCATION(h_data_p->local_rx_index)); 13364 _bcm_sb2_oam_copy_lmdm_hash_data_to_scache_info(h_data_p, scache_info); 13365 } 13366 } 13367 13368 STATIC void 13369 _bcm_sb2_oam_lmdm_info_recover(_bcm_oam_hash_data_t *h_data_p, 13370 uint8 *scache, 13371 _bcm_oam_control_t *oc) 13372 { 13373 _bcm_lmdm_oam_scache_info_t *scache_info; 13374 #if defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM) 13375 int rv = BCM_E_NONE; 13376 #endif 13377 13378 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 13379 #if defined(INCLUDE_ETH_LM_DM) 13380 scache_info = (_bcm_lmdm_oam_scache_info_t *)(scache + 13381 _BCM_SB2_OAM_LM_DM_UP_MEP_SCACHE_INFO_LOCATION(h_data_p->local_rx_index)); 13382 _bcm_sb2_oam_copy_lmdm_scache_info_to_hash_data(scache_info, h_data_p); 13383 #endif 13384 } else { 13385 scache_info = (_bcm_lmdm_oam_scache_info_t *)(scache + 13386 _BCM_SB2_OAM_LM_DM_DOWN_MEP_SCACHE_INFO_LOCATION(h_data_p->local_rx_index)); 13387 _bcm_sb2_oam_copy_lmdm_scache_info_to_hash_data(scache_info, h_data_p); 13388 } 13389 13390 if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 13391 #if defined(INCLUDE_MPLS_LM_DM) 13392 if (h_data_p->lm_dm_uc_session_id != 0) { 13393 rv = shr_idxres_list_reserve(oc->mpls_lm_dm_pool, 13394 h_data_p->lm_dm_uc_session_id, h_data_p->lm_dm_uc_session_id); 13395 13396 if (BCM_FAILURE(rv)) { 13397 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, "MPLS_LM_DM (unit %d) Error:" 13398 " Session Id alloc failed EP:%d %s.\n"), oc->unit, h_data_p->ep_id, 13399 bcm_errmsg(rv))); 13400 return; 13401 } 13402 if(mpls_oam_id_map != NULL) { 13403 mpls_oam_id_map[h_data_p->lm_dm_uc_session_id - 1] = h_data_p->ep_id; 13404 } 13405 oc->mpls_lm_dm_sess_id_ep_id[h_data_p->lm_dm_uc_session_id] = h_data_p->ep_id; 13406 } 13407 #endif 13408 } else if (h_data_p->type == bcmOAMEndpointTypeEthernet) { 13409 #if defined(INCLUDE_ETH_LM_DM) 13410 if (h_data_p->lm_dm_uc_session_id != 0) { 13411 rv = shr_idxres_list_reserve(oc->eth_lm_dm_pool, 13412 h_data_p->lm_dm_uc_session_id, h_data_p->lm_dm_uc_session_id); 13413 13414 if (BCM_FAILURE(rv)) { 13415 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(oc->unit, "ETH_LM_DM (unit %d) Error:" 13416 " Session Id alloc failed EP:%d %s.\n"), oc->unit, h_data_p->ep_id, 13417 bcm_errmsg(rv))); 13418 return; 13419 } 13420 if(eth_oam_id_map != NULL) { 13421 eth_oam_id_map[h_data_p->lm_dm_uc_session_id - 1] = h_data_p->ep_id; 13422 } 13423 oc->eth_lm_dm_sess_id_ep_id[h_data_p->lm_dm_uc_session_id] = h_data_p->ep_id; 13424 } 13425 #endif 13426 } 13427 } 13428 13429 /* 13430 * Function: 13431 * _bcm_sb2_oam_sync 13432 * Purpose: 13433 * Store OAM configuration to level two storage cache memory. 13434 * Parameters: 13435 * unit - (IN) Device unit number 13436 * Returns: 13437 * BCM_E_XXX 13438 */ 13439 int 13440 _bcm_sb2_oam_sync(int unit) 13441 { 13442 int rv; /* Operation return status. */ 13443 _bcm_oam_control_t *oc; 13444 int stable_size; 13445 soc_scache_handle_t scache_handle; 13446 uint8 *oam_scache = NULL; 13447 uint8 *lm_dm_scache_info_ptr = NULL; 13448 int grp_idx; 13449 int ma_offset; 13450 _bcm_oam_group_data_t *group_p; /* Pointer to group list. */ 13451 int group_count = 0; 13452 #if defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_BHH) 13453 int itr; 13454 _bcm_oam_pm_profile_control_t *pmc = NULL; 13455 #endif 13456 _bcm_oam_ep_list_t *ep_list_p = NULL; 13457 _bcm_oam_hash_data_t ep_data; 13458 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 13459 uint8 trunk_index; 13460 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 13461 _bcm_oam_hash_data_t *h_data_p = NULL; 13462 int idx = 0; 13463 uint8 *tmp_oam_scache = NULL; 13464 int trunk_idx_size = 0; 13465 13466 /* Get OAM module storage size. */ 13467 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 13468 13469 /* If level 2 store is not configured return from here. */ 13470 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) { 13471 return BCM_E_NONE; 13472 } 13473 13474 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 13475 13476 /* Check if memory has already been allocated */ 13477 rv = _bcm_esw_scache_ptr_get(unit, 13478 scache_handle, 13479 0, 13480 0, 13481 &oam_scache, 13482 BCM_WB_DEFAULT_VERSION, 13483 NULL 13484 ); 13485 if (!SOC_WARM_BOOT(unit) && (BCM_E_NOT_FOUND == rv)) { 13486 BCM_IF_ERROR_RETURN(bcm_sb2_oam_scache_alloc(unit)); 13487 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0, &oam_scache, 13488 BCM_WB_DEFAULT_VERSION, NULL); 13489 if (BCM_FAILURE(rv)) { 13490 /* 13491 * COVERITY 13492 * 13493 * Coverity complains that oam_scache is not freed when it goes out 13494 * of scope, but the ptr should be freed by the scache module 13495 */ 13496 /* coverity[leaked_storage] */ 13497 return rv; 13498 } 13499 if (NULL == oam_scache) { 13500 return BCM_E_NOT_FOUND; 13501 } 13502 } else if (BCM_FAILURE(rv)) { 13503 /* 13504 * COVERITY 13505 * 13506 * Coverity complains that oam_scache is not freed when it goes out 13507 * of scope, but the ptr should be freed by the scache module 13508 */ 13509 /* coverity[leaked_storage : FALSE] */ 13510 return rv; 13511 } 13512 13513 /* Get handle to control structure. */ 13514 rv = _bcm_sb2_oam_control_get(unit, &oc); 13515 if (BCM_FAILURE(rv)) { 13516 /* 13517 * COVERITY 13518 * 13519 * Coverity complains that oam_scache is not freed when it goes out 13520 * of scope, but the ptr should be freed by the scache module 13521 */ 13522 /* coverity[leaked_storage] */ 13523 return rv; 13524 } 13525 _BCM_OAM_LOCK(oc); 13526 13527 /* Store the FP groups */ 13528 sal_memcpy(oam_scache, &oc->vfp_group, sizeof(bcm_field_group_t)); 13529 oam_scache += sizeof(bcm_field_group_t); 13530 13531 sal_memcpy(oam_scache, &oc->fp_vp_group, sizeof(bcm_field_group_t)); 13532 oam_scache += sizeof(bcm_field_group_t); 13533 13534 sal_memcpy(oam_scache, &oc->fp_glp_group, sizeof(bcm_field_group_t)); 13535 oam_scache += sizeof(bcm_field_group_t); 13536 13537 sal_memcpy(oam_scache, &group_count, sizeof(int)); 13538 oam_scache += sizeof(int); 13539 13540 group_p = oc->group_info; 13541 for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) 13542 { 13543 /* Check if the group is in use. */ 13544 if (BCM_E_EXISTS 13545 == shr_idxres_list_elem_state(oc->group_pool, grp_idx)) { 13546 13547 sal_memcpy(oam_scache, group_p[grp_idx].name, 13548 BCM_OAM_GROUP_NAME_LENGTH); 13549 13550 oam_scache += BCM_OAM_GROUP_NAME_LENGTH; 13551 } 13552 } 13553 #if defined(INCLUDE_BHH) 13554 if (oc->ukernel_not_ready == 0) { 13555 /*Store MA_INDEX allocated to BHH*/ 13556 for (idx = 0; idx < _SHR_BITDCLSIZE (oc->ma_idx_count); idx++) { 13557 sal_memcpy(oam_scache, &oc->bhh_ma_index_in_use[idx], 13558 sizeof(SHR_BITDCL)); 13559 oam_scache += sizeof(SHR_BITDCL); 13560 } 13561 13562 /*Store BHH endpoint group ids */ 13563 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) { 13564 sal_memcpy(oam_scache, &oc->bhh_ep_grp_id[idx], sizeof(short)); 13565 oam_scache += sizeof(short); 13566 } 13567 13568 /*Store BHH endpoint VPN */ 13569 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) { 13570 sal_memcpy(oam_scache, &oc->bhh_ep_vpn[idx], sizeof(short)); 13571 oam_scache += sizeof(short); 13572 } 13573 } 13574 #endif 13575 13576 /* Store logical endpoint indexes 13577 Following is scache allocation for different types of EPs 13578 ----------------------------------------------------------------------- 13579 | Rx DownMEP indexes | Rx UpMEP indexes | RMEP indexes | Tx MEP indexes | 13580 ----------------------------------------------------------------------- 13581 */ 13582 sal_memset(oam_scache, 0, 13583 _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE + 13584 _BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE); 13585 13586 for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) 13587 { 13588 if (group_p[grp_idx].in_use == 1) { 13589 ep_list_p = *(group_p[grp_idx].ep_list); 13590 while (ep_list_p != NULL) { 13591 sal_memcpy(&ep_data, ep_list_p->ep_data_p, sizeof(_bcm_oam_hash_data_t)); 13592 if (ep_data.type == bcmOAMEndpointTypeEthernet || 13593 MPLS_LM_DM_ENDPOINT_TYPE((&ep_data))) { 13594 13595 if (ep_data.is_remote) { 13596 sal_memcpy(oam_scache + 13597 (_BCM_SB2_OAM_RMEP_SCACHE_LOCATION(ep_data.remote_index)), 13598 &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t)); 13599 } else { 13600 if (ep_data.local_tx_enabled) { 13601 sal_memcpy(oam_scache + 13602 (_BCM_SB2_OAM_TX_MEP_SCACHE_LOCATION(ep_data.local_tx_index)), 13603 &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t)); 13604 } 13605 if (ep_data.local_rx_enabled) { 13606 if (ep_data.flags & BCM_OAM_ENDPOINT_UP_FACING) { 13607 sal_memcpy(oam_scache + 13608 (_BCM_SB2_OAM_RX_UPMEP_SCACHE_LOCATION(ep_data.local_rx_index)), 13609 &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t)); 13610 } else { 13611 _bcm_sb2_oam_ma_index_offset_get(unit, &ep_data, &ma_offset); 13612 ep_data.local_rx_index = ep_data.ma_base_index + ma_offset; 13613 sal_memcpy(oam_scache + 13614 (_BCM_SB2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ep_data.local_rx_index)), 13615 &(ep_data.ep_id), sizeof (bcm_oam_endpoint_t)); 13616 } 13617 13618 lm_dm_scache_info_ptr = oam_scache + 13619 _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE; 13620 13621 _bcm_sb2_oam_lmdm_scache_info_set(&ep_data, lm_dm_scache_info_ptr, oc); 13622 #if defined(INCLUDE_MPLS_LM_DM) 13623 if (MPLS_LM_DM_ENDPOINT_TYPE((&ep_data))) { 13624 lm_dm_scache_info_ptr += _BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE + 13625 _BCM_OAM_EGR_LABEL_SCACHE_OFFSET(ep_data.local_rx_index); 13626 _bcm_sb2_oam_copy_egr_label_to_scache(&ep_data, 13627 (_bcm_sb2_oam_egr_label_scache_info_t *)lm_dm_scache_info_ptr); 13628 } 13629 #endif 13630 } 13631 } 13632 } 13633 ep_list_p = ep_list_p->next; 13634 } 13635 } 13636 } 13637 oam_scache += _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE; 13638 oam_scache += _BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE; 13639 oam_scache += _BCM_SB2_OAM_EGR_LABEL_SCACHE_SIZE; 13640 13641 #if defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_BHH) 13642 /* Store pm profile */ 13643 if ((_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) || 13644 (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) || 13645 (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc))) { 13646 13647 pmc = pm_profile_control[unit]; 13648 13649 if (!pmc) { 13650 _BCM_OAM_UNLOCK(oc); 13651 /* 13652 * COVERITY 13653 * 13654 * Coverity complains that oam_scache is not freed when it goes out 13655 * of scope, but freeing the ptr is scache module's responsibility 13656 */ 13657 /* coverity[leaked_storage] */ 13658 return (BCM_E_INIT); 13659 } 13660 for(itr = 0; itr < _BCM_OAM_MAX_PM_PROFILES; itr++) { 13661 sal_memcpy(oam_scache, 13662 &(pmc->profile_info[itr]), sizeof(_bcm_oam_pm_profile_int_info_t)); 13663 oam_scache += sizeof(_bcm_oam_pm_profile_int_info_t); 13664 } 13665 13666 /* Store Ep id to PM mapping */ 13667 sal_memset(oam_scache, -1, _bcm_sb2_oam_pmid_scache_size(unit)); 13668 13669 for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) { 13670 if (group_p[grp_idx].in_use == 1) { 13671 ep_list_p = *(group_p[grp_idx].ep_list); 13672 while (ep_list_p != NULL) { 13673 13674 if (!(ep_list_p->ep_data_p->is_remote) && 13675 (ep_list_p->ep_data_p->local_rx_enabled)) { 13676 #if defined(INCLUDE_ETH_LM_DM) 13677 if (ETH_TYPE(ep_list_p->ep_data_p->type) && 13678 (ep_list_p->ep_data_p->lm_dm_uc_session_id)) { 13679 int8 profile_id; 13680 profile_id = (int8)(ep_list_p->ep_data_p->pm_profile_attached); 13681 13682 sal_memcpy(oam_scache + 13683 _bcm_sb2_oam_eth_pmid_scache_loc(unit, 13684 ep_list_p->ep_data_p->lm_dm_uc_session_id - 1), 13685 &(profile_id), 13686 sizeof (int8)); 13687 } 13688 #endif 13689 #if defined(INCLUDE_MPLS_LM_DM) 13690 if(MPLS_LM_DM_ENDPOINT_TYPE(ep_list_p->ep_data_p) && 13691 (ep_list_p->ep_data_p->lm_dm_uc_session_id)) { 13692 int8 profile_id; 13693 profile_id = (int8)(ep_list_p->ep_data_p->pm_profile_attached); 13694 13695 sal_memcpy(oam_scache + 13696 _bcm_sb2_oam_mpls_pmid_scache_loc(unit, 13697 ep_list_p->ep_data_p->lm_dm_uc_session_id - 1), 13698 &(profile_id), 13699 sizeof (int8)); 13700 } 13701 #endif 13702 #if defined(INCLUDE_BHH) 13703 if(BHH_TYPE(ep_list_p->ep_data_p->type)) { 13704 int8 profile_id; 13705 profile_id = (int8)(ep_list_p->ep_data_p->pm_profile_attached); 13706 13707 sal_memcpy(oam_scache + _bcm_sb2_oam_bhh_pmid_scache_loc(unit, 13708 BCM_OAM_BHH_GET_UKERNEL_EP(ep_list_p->ep_data_p->ep_id)), 13709 &(profile_id), 13710 sizeof (int8)); 13711 } 13712 #endif 13713 } 13714 ep_list_p = ep_list_p->next; 13715 } 13716 } 13717 } 13718 oam_scache += _bcm_sb2_oam_pmid_scache_size(unit); 13719 } 13720 #endif /* defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_BHH) */ 13721 13722 #if defined(INCLUDE_BHH) 13723 sal_memcpy(oam_scache, &bhh_lsp_egr_lookup_key, sizeof(uint8)); 13724 oam_scache += sizeof(uint8); 13725 #endif /* INCLUDE_BHH */ 13726 13727 #if defined(INCLUDE_MPLS_LM_DM) 13728 /* Hardcoded to MEP_ID for now */ 13729 *((uint8 *)(oam_scache)) = _BCM_SB2_OAM_EGR_LSP_MEP_LOOKUP_KEY_MEP_ID; 13730 oam_scache += sizeof(uint8); 13731 #endif /* INCLUDE_MPLS_LM_DM */ 13732 13733 #if defined(INCLUDE_BHH) 13734 if(soc_feature(unit, soc_feature_bhh)) { 13735 if (oc->ukernel_not_ready == 0) { 13736 13737 /*Store BHH endpoint VLAN_PRI and INNER_VLAN_PRI*/ 13738 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) { 13739 h_data_p = &oc->oam_hash_data[BCM_OAM_BHH_GET_SDK_EP(idx)]; 13740 if(h_data_p->in_use) { 13741 sal_memcpy(oam_scache, &h_data_p->vlan_pri, sizeof(uint8)); 13742 oam_scache += sizeof(uint8); 13743 sal_memcpy(oam_scache, &h_data_p->inner_vlan_pri, sizeof(uint8)); 13744 oam_scache += sizeof(uint8); 13745 } else { 13746 oam_scache += sizeof(uint8) * 2; 13747 } 13748 } 13749 } 13750 } 13751 #endif 13752 13753 sal_memcpy(oam_scache, &(oc->eth_oam_mp_group_vlan_key), sizeof(uint8)); 13754 oam_scache += sizeof(uint8); 13755 13756 tmp_oam_scache = oam_scache; 13757 #if defined(INCLUDE_BHH) 13758 if(soc_feature(unit, soc_feature_bhh)) { 13759 if (oc->ukernel_not_ready == 0) { 13760 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) { 13761 h_data_p = &oc->oam_hash_data[BCM_OAM_BHH_GET_SDK_EP(idx)]; 13762 if (h_data_p->in_use) { 13763 trunk_index = h_data_p->trunk_index; 13764 sal_memcpy(oam_scache, &trunk_index, sizeof(uint8)); 13765 oam_scache += sizeof(uint8); 13766 } 13767 } 13768 trunk_idx_size = sizeof(uint8) * oc->ma_idx_count; 13769 } 13770 } 13771 #endif /* INCLUDE_BHH */ 13772 #if defined(INCLUDE_MPLS_LM_DM) 13773 if (oc->mpls_lm_dm_ukernel_ready) { 13774 for (idx = 0; idx < oc->ep_count; idx++) { 13775 h_data_p = &oc->oam_hash_data[idx]; 13776 if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) && (h_data_p->in_use)) { 13777 trunk_index = h_data_p->trunk_index; 13778 sal_memcpy(oam_scache, &trunk_index, sizeof(uint8)); 13779 oam_scache += sizeof(uint8); 13780 } 13781 } 13782 trunk_idx_size = sizeof(uint8) * oc->ma_idx_count; 13783 } 13784 #endif /* INCLUDE_MPLS_LM_DM */ 13785 /* The above code doesnt move the scache pointer to the end of 13786 * its allocated section size. So we move it here. 13787 */ 13788 oam_scache = tmp_oam_scache + trunk_idx_size; 13789 13790 for (idx = 0; idx < oc->ep_count; idx++) { 13791 h_data_p = &oc->oam_hash_data[idx]; 13792 if (ETH_TYPE(h_data_p->type) && (h_data_p->in_use)) { 13793 sal_memcpy(oam_scache, &(h_data_p->flags), sizeof(uint32)); 13794 } 13795 oam_scache += sizeof(uint32); 13796 } 13797 13798 #if defined(INCLUDE_BHH) 13799 sal_memcpy(oam_scache, &sb2_oam_mpls_tp_ach_channel_type, 13800 sizeof(sb2_oam_mpls_tp_ach_channel_type)); 13801 oam_scache += sizeof(sb2_oam_mpls_tp_ach_channel_type); 13802 #endif /* INCLUDE_BHH */ 13803 13804 _BCM_OAM_UNLOCK(oc); 13805 /* 13806 * COVERITY 13807 * 13808 * Coverity complains that oam_scache is not freed when it goes out 13809 * of scope, but freeing the ptr is scache module's responsibility 13810 */ 13811 /* coverity[leaked_storage] */ 13812 return (BCM_E_NONE); 13813 } 13814 13815 /* 13816 * Function: 13817 * _bcm_sb2_oam_wb_group_recover 13818 * Purpose: 13819 * Recover OAM group configuration. 13820 * Parameters: 13821 * unit - (IN) BCM device number 13822 * stable_size - (IN) OAM module Level2 storage size. 13823 * oam_scache - (IN) Pointer to scache address pointer. 13824 * Returns: 13825 * BCM_E_XXX 13826 */ 13827 STATIC int 13828 _bcm_sb2_oam_wb_group_recover(int unit, int stable_size, uint8 **oam_scache) 13829 { 13830 int index; /* Hw table index. */ 13831 _bcm_oam_group_data_t *group_p; /* Group info pointer. */ 13832 maid_reduction_entry_t maid_entry; /* Group entry info. */ 13833 ma_state_entry_t ma_state_ent; /* Group state info. */ 13834 int maid_reduction_valid = 0; /* Group valid. */ 13835 int ma_state_valid = 0; /* Group state valid. */ 13836 _bcm_oam_control_t *oc; /* Pointer to Control */ 13837 /* structure. */ 13838 int rv; /* Operation return */ 13839 /* status. */ 13840 13841 /* Control lock taken by calling routine. */ 13842 /* Get OAM control structure. */ 13843 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 13844 13845 for (index = 0; index < oc->group_count; index++) { 13846 13847 rv = READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, index, 13848 &maid_entry); 13849 if (BCM_FAILURE(rv)) { 13850 LOG_ERROR(BSL_LS_BCM_OAM, 13851 (BSL_META_U(unit, 13852 "OAM(unit %d) Error: (GID=%d) MAID_REDUCTION table read" 13853 " failed - %s.\n"), unit, index, bcm_errmsg(rv))); 13854 goto cleanup; 13855 } 13856 13857 rv = READ_MA_STATEm(unit, MEM_BLOCK_ANY, index, &ma_state_ent); 13858 if (BCM_FAILURE(rv)) { 13859 LOG_ERROR(BSL_LS_BCM_OAM, 13860 (BSL_META_U(unit, 13861 "OAM(unit %d) Error: (GID=%d) MA_STATE table read" 13862 " failed - %s.\n"), unit, index, bcm_errmsg(rv))); 13863 goto cleanup; 13864 } 13865 13866 maid_reduction_valid 13867 = soc_MAID_REDUCTIONm_field32_get(unit, &maid_entry, VALIDf); 13868 13869 ma_state_valid 13870 = soc_MA_STATEm_field32_get(unit, &ma_state_ent, VALIDf); 13871 13872 if (maid_reduction_valid || ma_state_valid) { 13873 13874 /* Entry must be valid in both the tables, else return error. */ 13875 if (!maid_reduction_valid || !ma_state_valid) { 13876 rv = BCM_E_INTERNAL; 13877 goto cleanup; 13878 } 13879 13880 /* Get the group memory pointer. */ 13881 group_p = &oc->group_info[index]; 13882 if (1 == group_p->in_use) { 13883 rv = BCM_E_INTERNAL; 13884 goto cleanup; 13885 } 13886 13887 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) { 13888 13889 /* Set group name as zeros. */ 13890 sal_memset(group_p->name, 0, BCM_OAM_GROUP_NAME_LENGTH); 13891 13892 } else { 13893 13894 /* Get the group name from stored info. */ 13895 sal_memcpy(group_p->name, *oam_scache, 13896 BCM_OAM_GROUP_NAME_LENGTH); 13897 *oam_scache = (*oam_scache + BCM_OAM_GROUP_NAME_LENGTH); 13898 } 13899 13900 /* Reserve the group index. */ 13901 rv = shr_idxres_list_reserve(oc->group_pool, index, index); 13902 if (BCM_FAILURE(rv)) { 13903 LOG_ERROR(BSL_LS_BCM_OAM, 13904 (BSL_META_U(unit, 13905 "OAM(unit %d) Error: (GID=%d) Index reserve " 13906 " failed - %s.\n"), unit, index, bcm_errmsg(rv))); 13907 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 13908 goto cleanup; 13909 } 13910 13911 /* Create the linked list to maintain group endpoint information. */ 13912 _BCM_OAM_ALLOC((group_p->ep_list), _bcm_oam_ep_list_t *, 13913 sizeof(_bcm_oam_ep_list_t *), "EP list head"); 13914 if (NULL == group_p->ep_list) { 13915 rv = BCM_E_MEMORY; 13916 goto cleanup; 13917 } 13918 13919 /* Initialize head node.*/ 13920 *group_p->ep_list = NULL; 13921 group_p->in_use = 1; 13922 } 13923 } 13924 13925 return (BCM_E_NONE); 13926 13927 cleanup: 13928 13929 if (BCM_E_EXISTS 13930 == shr_idxres_list_elem_state(oc->group_pool, index)) { 13931 shr_idxres_list_free(oc->group_pool, index); 13932 } 13933 13934 return (rv); 13935 13936 } 13937 13938 /* 13939 * Function: 13940 * _bcm_sb2_oam_rmep_recover 13941 * Purpose: 13942 * Recover OAM remote endpoint configuration. 13943 * Parameters: 13944 * unit - (IN) BCM device number 13945 * index - (IN) Remote MEP hardware index. 13946 * l3_entry - (IN) RMEP view table entry pointer. 13947 * Returns: 13948 * BCM_E_XXX 13949 */ 13950 STATIC int 13951 _bcm_sb2_oam_rmep_recover(int unit, 13952 int index, 13953 l3_entry_1_entry_t *l3_entry, 13954 uint8 **scache, 13955 uint16 recovered_ver) 13956 { 13957 rmep_entry_t rmep_entry; /* Remote table entry. */ 13958 _bcm_oam_hash_data_t *h_data_p; /* Endpoint hash data pointer. */ 13959 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 13960 int rv; /* Operation return status. */ 13961 bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information. */ 13962 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 13963 int ep_id; /* Endpoint ID. */ 13964 int rmep_index; /* Index of RMEP table */ 13965 13966 LOG_DEBUG(BSL_LS_BCM_OAM, 13967 (BSL_META_U(unit, 13968 "OAM(unit %d) Info: _bcm_sb2_oam_rmep_recover.\n"), 13969 unit)); 13970 /* 13971 * Get OAM control structure. 13972 * Note: Lock taken by calling routine. 13973 */ 13974 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 13975 13976 rmep_index = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, RMEP__RMEP_PTRf); 13977 if (recovered_ver >= BCM_WB_VERSION_1_1) { 13978 /* Recover EP index from scache */ 13979 sal_memcpy(&ep_id, *scache + (_BCM_SB2_OAM_RMEP_SCACHE_LOCATION(rmep_index)), 13980 sizeof(bcm_oam_endpoint_t)); 13981 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id); 13982 if (BCM_FAILURE(rv)) { 13983 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 13984 LOG_ERROR(BSL_LS_BCM_OAM, 13985 (BSL_META_U(unit, 13986 "OAM Error: (EP_ID=%d) Index reserve " 13987 " failed - %s.\n"), ep_id, bcm_errmsg(rv))); 13988 return (rv); 13989 } 13990 13991 } else { 13992 13993 /* Allocate the next available endpoint index. */ 13994 rv = shr_idxres_list_alloc(oc->mep_pool, 13995 (shr_idxres_element_t *)&ep_id); 13996 if (BCM_FAILURE(rv)) { 13997 LOG_ERROR(BSL_LS_BCM_OAM, 13998 (BSL_META_U(unit, 13999 "OAM(unit %d) Error: Endpoint alloc (EP=%d) - %s.\n"), 14000 unit, ep_id, bcm_errmsg(rv))); 14001 return (rv); 14002 } 14003 } 14004 h_data_p = &oc->oam_hash_data[ep_id]; 14005 if (1 == h_data_p->in_use) { 14006 return(BCM_E_INTERNAL); 14007 } 14008 14009 /* 14010 * Clear the hash data element contents before 14011 * storing values. 14012 */ 14013 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 14014 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 14015 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 14016 h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX; 14017 h_data_p->profile_index = _BCM_OAM_INVALID_INDEX; 14018 h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX; 14019 h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 14020 h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 14021 h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 14022 h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 14023 h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 14024 h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 14025 h_data_p->trunk_id = BCM_TRUNK_INVALID; 14026 h_data_p->gport = 0; 14027 /* Get RMEP table index from LMEP view entry. */ 14028 h_data_p->remote_index = rmep_index; 14029 /* Get RMEP table entry contents. */ 14030 rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index, &rmep_entry); 14031 if (BCM_FAILURE(rv)) { 14032 LOG_ERROR(BSL_LS_BCM_OAM, 14033 (BSL_META_U(unit, 14034 "OAM(unit %d) Error: RMEP (index=%d) read failed - %s.\n"), 14035 unit, h_data_p->remote_index, bcm_errmsg(rv))); 14036 goto cleanup; 14037 } 14038 14039 /* Has to be a valid RMEP, return error otherwise. */ 14040 if (!soc_RMEPm_field32_get(unit, &rmep_entry, VALIDf)) { 14041 rv = BCM_E_INTERNAL; 14042 goto cleanup; 14043 } 14044 h_data_p->ep_id = ep_id; 14045 14046 h_data_p->is_remote = 1; 14047 14048 h_data_p->flags |= BCM_OAM_ENDPOINT_REMOTE; 14049 h_data_p->group_index 14050 = soc_RMEPm_field32_get(unit, &rmep_entry, MAID_INDEXf); 14051 14052 h_data_p->period 14053 = _bcm_sb2_oam_ccm_hw_encode_to_msecs 14054 ((int) soc_RMEPm_field32_get(unit, &rmep_entry, 14055 RMEP_RECEIVED_CCMf)); 14056 h_data_p->name 14057 = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, l3_entry, RMEP__MEPIDf); 14058 14059 h_data_p->local_tx_index = _BCM_OAM_INVALID_INDEX; 14060 h_data_p->local_rx_index = _BCM_OAM_INVALID_INDEX; 14061 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 14062 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 14063 14064 rv = shr_idxres_list_reserve(oc->rmep_pool, 14065 h_data_p->remote_index, 14066 h_data_p->remote_index); 14067 if (BCM_FAILURE(rv)) { 14068 LOG_ERROR(BSL_LS_BCM_OAM, 14069 (BSL_META_U(unit, 14070 "OAM(unit %d) Error: (RMEP=%d) Index reserve failed - %s.\n"), 14071 unit, h_data_p->remote_index, bcm_errmsg(rv))); 14072 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 14073 goto cleanup; 14074 } 14075 14076 h_data_p->in_use = 1; 14077 14078 rv = _bcm_sb2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id); 14079 if (BCM_FAILURE(rv)) { 14080 goto cleanup; 14081 } 14082 14083 rv = _bcm_sb2_oam_endpoint_alloc(&ep_info); 14084 if (BCM_FAILURE(rv)) { 14085 _bcm_sb2_oam_group_ep_list_remove(unit, h_data_p->group_index, ep_id); 14086 goto cleanup; 14087 } 14088 14089 bcm_oam_endpoint_info_t_init(ep_info); 14090 14091 /* Set up endpoint information for key construction. */ 14092 ep_info->group = h_data_p->group_index; 14093 ep_info->name = h_data_p->name; 14094 ep_info->gport = h_data_p->gport; 14095 ep_info->id= h_data_p->ep_id; 14096 14097 if ((recovered_ver < BCM_WB_VERSION_1_9) 14098 || (!ETH_TYPE(h_data_p->type))) { 14099 /* Calculate hash key for hash table insert operation. */ 14100 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 14101 14102 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 14103 if (BCM_FAILURE(rv)) { 14104 LOG_ERROR(BSL_LS_BCM_OAM, 14105 (BSL_META_U(unit, 14106 "OAM(unit %d) Error: Hash table insert failed " 14107 "EP=%d %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 14108 _bcm_sb2_oam_group_ep_list_remove(unit, h_data_p->group_index, ep_id); 14109 goto cleanup; 14110 } else { 14111 LOG_DEBUG(BSL_LS_BCM_OAM, 14112 (BSL_META_U(unit, 14113 "OAM(unit %d) Info: Hash Tbl (EP=%d) inserted" 14114 " - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 14115 } 14116 } 14117 14118 /* Add the H/w index to logical index mapping for RMEP */ 14119 oc->remote_endpoints[h_data_p->remote_index] = ep_info->id; 14120 14121 sal_free(ep_info); 14122 LOG_DEBUG(BSL_LS_BCM_OAM, 14123 (BSL_META_U(unit, 14124 "OAM(unit %d) Info: _bcm_sb2_oam_rmep_recover - done.\n"), 14125 unit)); 14126 14127 return (rv); 14128 cleanup: 14129 if (NULL != ep_info) { 14130 sal_free(ep_info); 14131 } 14132 /* Release the endpoint ID if in use. */ 14133 if (BCM_E_EXISTS 14134 == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) { 14135 shr_idxres_list_free(oc->mep_pool, ep_id); 14136 } 14137 14138 /* Release the remote index if in use. */ 14139 if ((1 == h_data_p->in_use) 14140 && (BCM_E_EXISTS 14141 == shr_idxres_list_elem_state(oc->rmep_pool, 14142 h_data_p->remote_index))) { 14143 shr_idxres_list_free(oc->rmep_pool, h_data_p->remote_index); 14144 14145 } 14146 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 14147 14148 LOG_DEBUG(BSL_LS_BCM_OAM, 14149 (BSL_META_U(unit, 14150 "OAM(unit %d) Info: _bcm_sb2_oam_rmep_recover - error_done.\n"), 14151 unit)); 14152 return (rv); 14153 } 14154 14155 /* 14156 * Function: 14157 * _bcm_sb2_oam_port_lmep_rx_config_recover 14158 * Purpose: 14159 * Recover OAM local endpoint Rx configuration for port based DownMEPs. 14160 * Parameters: 14161 * unit - (IN) BCM device number 14162 * index - (IN) Port entry hardware index. 14163 * port_entry - (IN) port table entry pointer. 14164 * Returns: 14165 * BCM_E_XXX 14166 */ 14167 STATIC int 14168 _bcm_sb2_oam_port_lmep_rx_config_recover(int unit, 14169 int index, 14170 port_tab_entry_t *port_entry, 14171 uint8 **scache, 14172 uint16 recovered_ver) 14173 { 14174 14175 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 14176 ma_index_entry_t ma_idx_entry; /* MA_INDEX table entry. */ 14177 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 14178 uint8 mdl_bitmap; /* Endpoint domain level bitmap. */ 14179 uint8 mdl; /* Maintenance domain level. */ 14180 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 14181 int rv, tmp_rv; /* Operation return status. */ 14182 _bcm_gport_dest_t gport_dest; /* Gport specification. */ 14183 bcm_gport_t gport; /* Gport value. */ 14184 int ep_id; /* Endpoint ID. */ 14185 bcm_module_t my_modid; 14186 int stm_index = 0; 14187 source_trunk_map_table_entry_t stm_entry; 14188 bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information. */ 14189 int ma_offset = 0; 14190 int ma_idx; /* MA_TABLE index */ 14191 int ma_base_idx = 0; 14192 int ma_idx_entry_count = 0; 14193 shr_idxres_list_handle_t pool = NULL; 14194 uint8 *lm_dm_scache_info_ptr = NULL; 14195 14196 LOG_DEBUG(BSL_LS_BCM_OAM, 14197 (BSL_META_U(unit, 14198 "OAM(unit %d) Info: _bcm_sb2_oam_port_lmep_rx_config_recover .\n"), 14199 unit)); 14200 /* 14201 * Get OAM control structure. 14202 * Note: Lock taken by calling routine. 14203 */ 14204 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 14205 14206 /* recover port based DownMEPs */ 14207 mdl_bitmap = soc_PORT_TABm_field32_get(unit, port_entry, MDL_BITMAPf); 14208 for (mdl = 0; mdl < _BCM_OAM_EP_LEVEL_COUNT; mdl++) { 14209 14210 if (mdl_bitmap & (1 << mdl)) { 14211 14212 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_modid)); 14213 BCM_IF_ERROR_RETURN(_bcm_esw_src_mod_port_table_index_get(unit, 14214 my_modid, index, &stm_index)); 14215 SOC_IF_ERROR_RETURN(READ_SOURCE_TRUNK_MAP_TABLEm(unit, 14216 MEM_BLOCK_ANY, stm_index, &stm_entry)); 14217 ma_base_idx = 14218 soc_SOURCE_TRUNK_MAP_TABLEm_field32_get(unit, &stm_entry, 14219 MA_BASE_PTRf); 14220 14221 if (recovered_ver >= BCM_WB_VERSION_1_1) { 14222 14223 ma_idx = ma_base_idx + ma_offset; 14224 sal_memcpy(&ep_id, *(scache) + (_BCM_SB2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ma_idx)), 14225 sizeof(bcm_oam_endpoint_t)); 14226 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id); 14227 if (BCM_FAILURE(rv)) { 14228 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 14229 LOG_ERROR(BSL_LS_BCM_OAM, 14230 (BSL_META_U(unit, 14231 "OAM Error: (EP_ID=%d) Index reserve " 14232 " failed - %s.\n"), ep_id, bcm_errmsg(rv))); 14233 return (rv); 14234 } 14235 } else { 14236 /* Allocate the next available endpoint index. */ 14237 rv = shr_idxres_list_alloc(oc->mep_pool, 14238 (shr_idxres_element_t *)&ep_id); 14239 if (BCM_FAILURE(rv)) { 14240 LOG_ERROR(BSL_LS_BCM_OAM, 14241 (BSL_META_U(unit, 14242 "OAM(unit %d) Error: Endpoint alloc (EP=%d) - %s.\n"), 14243 unit, ep_id, bcm_errmsg(rv))); 14244 goto cleanup; 14245 } 14246 } 14247 14248 h_data_p = &oc->oam_hash_data[ep_id]; 14249 if (1 == h_data_p->in_use) { 14250 rv = BCM_E_INTERNAL; 14251 goto cleanup; 14252 } 14253 14254 /* 14255 * Clear the hash data element contents before 14256 * storing values. 14257 */ 14258 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 14259 _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p); 14260 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 14261 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 14262 h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX; 14263 h_data_p->profile_index = _BCM_OAM_INVALID_INDEX; 14264 h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX; 14265 h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 14266 h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 14267 h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 14268 h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 14269 h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 14270 h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 14271 h_data_p->trunk_id = BCM_TRUNK_INVALID; 14272 #if defined (BCM_METROLITE_SUPPORT) 14273 if(SOC_IS_METROLITE(unit)) { 14274 h_data_p->lm_count_profile = _BCM_OAM_INVALID_INDEX; 14275 } 14276 #endif 14277 h_data_p->ep_id = ep_id; 14278 h_data_p->ma_base_index = ma_base_idx; 14279 h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset; 14280 ma_offset++; 14281 14282 rv = READ_MA_INDEXm(unit, MEM_BLOCK_ANY, 14283 h_data_p->local_rx_index, &ma_idx_entry); 14284 if (BCM_FAILURE(rv)) { 14285 LOG_ERROR(BSL_LS_BCM_OAM, 14286 (BSL_META_U(unit, 14287 "OAM(unit %d) Error: MA_INDEX(index:%d) " 14288 "read failed -" " %s.\n"), unit, 14289 h_data_p->local_rx_index, bcm_errmsg(rv))); 14290 goto cleanup; 14291 } 14292 14293 h_data_p->in_use = 1; 14294 h_data_p->is_remote = 0; 14295 h_data_p->local_rx_enabled = 1; 14296 h_data_p->flags |= BCM_OAM_ENDPOINT_CCM_RX; 14297 h_data_p->active_mdl_bitmap = mdl_bitmap; 14298 h_data_p->group_index 14299 = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf); 14300 14301 h_data_p->profile_index 14302 = soc_MA_INDEXm_field32_get 14303 (unit, &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf); 14304 14305 rv = soc_profile_mem_reference(unit, &oc->oam_opcode_control_profile, 14306 _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(h_data_p->profile_index), 14307 _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE); 14308 if (BCM_FAILURE(rv)) { 14309 LOG_ERROR(BSL_LS_BCM_OAM, 14310 (BSL_META_U(unit, 14311 "OAM(unit %d) Error: Profile entry recover failed " 14312 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 14313 goto cleanup; 14314 } 14315 #if defined(BCM_METROLITE_SUPPORT) 14316 if(SOC_IS_METROLITE(unit)) { 14317 h_data_p->lm_count_profile = soc_MA_INDEXm_field32_get (unit, &ma_idx_entry, 14318 OAM_COUNT_PROFILEf); 14319 rv = soc_profile_mem_reference(unit, &oc->ing_lm_counter_control_profile, 14320 h_data_p->lm_count_profile, 14321 _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE); 14322 if (BCM_FAILURE(rv)) { 14323 LOG_ERROR(BSL_LS_BCM_OAM, 14324 (BSL_META_U(unit, 14325 "OAM(unit %d) Error: Profile entry recover failed " 14326 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 14327 goto cleanup; 14328 } 14329 rv = soc_profile_mem_reference(unit, &oc->egr_lm_counter_control_profile, 14330 h_data_p->lm_count_profile, 14331 _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE); 14332 if (BCM_FAILURE(rv)) { 14333 LOG_ERROR(BSL_LS_BCM_OAM, 14334 (BSL_META_U(unit, 14335 "OAM(unit %d) Error: Profile entry recover failed " 14336 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 14337 goto cleanup; 14338 } 14339 } 14340 #endif 14341 14342 h_data_p->name = 0x0; /* No need to set it to 0xffff */ 14343 h_data_p->level = mdl; 14344 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 14345 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 14346 h_data_p->oam_domain = 0; 14347 14348 /* Generic logical port type, construct gport from GLP. */ 14349 _bcm_gport_dest_t_init(&gport_dest); 14350 14351 gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 14352 gport_dest.modid = my_modid; 14353 gport_dest.port = index; 14354 h_data_p->sglp = index; 14355 h_data_p->dglp = index; 14356 h_data_p->src_pp_port = index; 14357 14358 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport); 14359 if (BCM_FAILURE(rv)) { 14360 LOG_ERROR(BSL_LS_BCM_OAM, 14361 (BSL_META_U(unit, 14362 "OAM(unit %d) Error: Gport construct failed -" 14363 " %s.\n"), unit, bcm_errmsg(rv))); 14364 goto cleanup; 14365 } 14366 h_data_p->gport = gport; 14367 14368 rv = _bcm_sb2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id); 14369 if (BCM_FAILURE(rv)) { 14370 goto cleanup; 14371 } 14372 rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_add(unit, h_data_p); 14373 if (BCM_FAILURE(rv)) { 14374 LOG_ERROR(BSL_LS_BCM_OAM, 14375 (BSL_META_U(unit, 14376 "OAM(unit %d) Error: Remove mapping from ma_idx_to_ep_id list (EP=%d) -" 14377 " %s.\n"), unit, ep_id, bcm_errmsg(rv))); 14378 _bcm_sb2_oam_group_ep_list_remove(unit, 14379 h_data_p->group_index, 14380 ep_id); 14381 goto cleanup; 14382 } 14383 14384 rv = _bcm_sb2_oam_endpoint_alloc(&ep_info); 14385 if (BCM_FAILURE(rv)) { 14386 _bcm_sb2_oam_group_ep_list_remove(unit, 14387 h_data_p->group_index, 14388 ep_id); 14389 goto cleanup; 14390 } 14391 14392 bcm_oam_endpoint_info_t_init(ep_info); 14393 14394 /* Set up endpoint information for key construction. */ 14395 ep_info->group = h_data_p->group_index; 14396 ep_info->name = h_data_p->name; 14397 ep_info->gport = h_data_p->gport; 14398 ep_info->level = h_data_p->level; 14399 ep_info->vlan = 0; 14400 ep_info->inner_vlan = 0; 14401 14402 if ((recovered_ver < BCM_WB_VERSION_1_9) 14403 || (!ETH_TYPE(h_data_p->type))) { 14404 /* 14405 * Calculate hash key for hash table insert 14406 * operation. 14407 */ 14408 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 14409 14410 14411 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 14412 if (BCM_FAILURE(rv)) { 14413 LOG_ERROR(BSL_LS_BCM_OAM, 14414 (BSL_META_U(unit, 14415 "OAM(unit %d) Error: Hash table insert" 14416 " (EP=%d) failed - %s.\n"), unit, 14417 h_data_p->ep_id, bcm_errmsg(rv))); 14418 14419 _bcm_sb2_oam_group_ep_list_remove(unit, 14420 h_data_p->group_index, 14421 ep_id); 14422 goto cleanup; 14423 } else { 14424 LOG_DEBUG(BSL_LS_BCM_OAM, 14425 (BSL_META_U(unit, 14426 "OAM(unit %d) Info: Hash Tbl (EP=%d)" 14427 " inserted - %s.\n"), unit, ep_id, 14428 bcm_errmsg(rv))); 14429 } 14430 } 14431 14432 /* Now we support DM for Port MEPs. Hence try recovering it in case 14433 * there is an LM/DM session on the PORT MEP. 14434 */ 14435 if (recovered_ver >= BCM_WB_VERSION_1_1) { 14436 if (bcmOAMEndpointTypeEthernet == h_data_p->type) { 14437 lm_dm_scache_info_ptr = *scache + _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE; 14438 _bcm_sb2_oam_lmdm_info_recover(h_data_p, lm_dm_scache_info_ptr, oc); 14439 } 14440 } 14441 sal_free(ep_info); 14442 /* Make it NULL to avoid dangling pointer free in cleanup */ 14443 ep_info = NULL; 14444 } 14445 } /* end of for loop */ 14446 if (mdl_bitmap) { 14447 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit, h_data_p, 14448 &ma_idx_entry_count,&pool)); 14449 rv = shr_idxres_list_reserve(pool, 14450 h_data_p->ma_base_index, 14451 h_data_p->ma_base_index + ma_idx_entry_count - 1); 14452 14453 if (BCM_FAILURE(rv)) { 14454 LOG_ERROR(BSL_LS_BCM_OAM, 14455 (BSL_META_U(unit, 14456 "OAM(unit %d) Error: (LMEP=%d) MA Index reserve " 14457 "failed" " - %s.\n"), unit, h_data_p->remote_index, 14458 bcm_errmsg(rv))); 14459 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 14460 goto cleanup; 14461 } 14462 } 14463 14464 LOG_DEBUG(BSL_LS_BCM_OAM, 14465 (BSL_META_U(unit, 14466 "OAM(unit %d) Info: _bcm_sb2_oam_lmep_rx_config_recover" 14467 " - done.\n"), unit)); 14468 return (BCM_E_NONE); 14469 14470 cleanup: 14471 /* Lets not check return value of delete during cleanup */ 14472 tmp_rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p); 14473 if (BCM_FAILURE(tmp_rv)) { 14474 LOG_DEBUG(BSL_LS_BCM_OAM, 14475 (BSL_META_U(unit, 14476 "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) -" 14477 " during cleanup %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 14478 } 14479 14480 if (NULL != ep_info) { 14481 sal_free(ep_info); 14482 } 14483 14484 if (BCM_E_EXISTS 14485 == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) { 14486 shr_idxres_list_free(oc->mep_pool, ep_id); 14487 } 14488 if (NULL != h_data_p 14489 && (BCM_E_EXISTS 14490 == shr_idxres_list_elem_state(pool, 14491 h_data_p->ma_base_index))) { 14492 shr_idxres_list_free(pool, h_data_p->ma_base_index); 14493 } 14494 if (NULL != h_data_p) { 14495 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 14496 } 14497 14498 LOG_DEBUG(BSL_LS_BCM_OAM, 14499 (BSL_META_U(unit, 14500 "OAM(unit %d) Info: _bcm_sb2_oam_lmep_rx_config_recover" 14501 " - error_done.\n"), unit)); 14502 return (rv); 14503 14504 } 14505 14506 #if defined(INCLUDE_L3) 14507 STATIC void 14508 _bcm_sb2_egr_l3_nxt_hop_egress_if_get_from_mepid(int unit, _bcm_oam_hash_data_t *h_data_p) 14509 { 14510 int mem_index = 0, mem_idx_count = 0; 14511 egr_l3_next_hop_entry_t egr_nh_entry; 14512 int rv = BCM_E_NONE; 14513 int oam_enable = 0; 14514 uint16 mep_id = 0; 14515 bcm_l3_egress_t nh_info; 14516 14517 14518 mem_idx_count = soc_mem_index_count(unit, EGR_L3_NEXT_HOPm); 14519 14520 for (mem_index = 0; mem_index < mem_idx_count; mem_index++) { 14521 sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry)); 14522 14523 rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, mem_index, &egr_nh_entry); 14524 if (BCM_FAILURE(rv)) { 14525 continue; 14526 } 14527 oam_enable = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, 14528 MPLS__MPLS_OAM_DOWNMEP_ENABLEf); 14529 if (!oam_enable) { 14530 continue; 14531 } 14532 if (oam_enable == _BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM) { 14533 mep_id = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, 14534 MPLS__MEPIDf); 14535 14536 if (mep_id == h_data_p->name) { 14537 /* Match found */ 14538 sal_memset(&nh_info, 0, sizeof(nh_info)); 14539 rv = bcm_xgs3_nh_get(unit, mem_index, &nh_info); 14540 if (BCM_FAILURE(rv)) { 14541 LOG_DEBUG(BSL_LS_BCM_OAM, 14542 (BSL_META_U(unit, 14543 "OAM(unit %d) : NH info get failed for" 14544 " %d - %s.\n"), unit, mem_index, 14545 bcm_errmsg(rv))); 14546 continue; 14547 } 14548 if (nh_info.encap_id > 0 && 14549 nh_info.encap_id < BCM_XGS3_EGRESS_IDX_MIN(unit)) { 14550 h_data_p->egress_if = mem_index + BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 14551 } else { 14552 h_data_p->egress_if = mem_index + BCM_XGS3_EGRESS_IDX_MIN(unit); 14553 } 14554 } 14555 } 14556 } 14557 } 14558 #endif 14559 14560 STATIC int 14561 _bcm_sb2_oam_mpls_lmdm_find_lsp_ep_id_from_egr_ctr_info(_bcm_oam_control_t *oc, 14562 uint32 egr_ctr_pool_id, 14563 uint32 egr_ctr_idx) 14564 { 14565 int grp_idx; 14566 _bcm_oam_group_data_t *group_p; /* Pointer to group list. */ 14567 _bcm_oam_ep_list_t *ep_list_p = NULL; 14568 _bcm_oam_hash_data_t *ep_data_p = NULL; 14569 uint32 ep_ctr_pool_id; 14570 uint32 ep_ctr_idx; 14571 14572 /* Initialize to group array pointer. */ 14573 group_p = oc->group_info; 14574 14575 for (grp_idx = 0; grp_idx < oc->group_count; ++grp_idx) 14576 { 14577 if (group_p[grp_idx].in_use == 1) { 14578 ep_list_p = *(group_p[grp_idx].ep_list); 14579 while (ep_list_p != NULL) { 14580 ep_data_p = ep_list_p->ep_data_p; 14581 if ((MPLS_LM_DM_LSP_ENDPOINT_TYPE(ep_data_p)) && 14582 (ep_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) { 14583 ep_ctr_pool_id = (ep_data_p->rx_ctr >> 24) & 0xFF; 14584 ep_ctr_idx = ep_data_p->rx_ctr & 0xFFFFFF; 14585 if ((ep_ctr_pool_id == egr_ctr_pool_id) && 14586 (ep_ctr_idx == egr_ctr_idx)) { 14587 return ep_data_p->ep_id; 14588 } 14589 } 14590 ep_list_p = ep_list_p->next; 14591 } 14592 } 14593 } 14594 return -1; 14595 } 14596 14597 STATIC int 14598 _bcm_sb2_oam_mpls_lmdm_tx_config_recover_for_ep_id(int unit, 14599 _bcm_oam_hash_data_t *h_data_p, 14600 egr_mp_group_entry_t *egr_mp_grp_entry) 14601 { 14602 _bcm_oam_hash_data_t hash_data; /* Endpoint hash data pointer. */ 14603 bcm_oam_endpoint_info_t ep_info; /* Endpoint information */ 14604 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup */ 14605 _bcm_oam_control_t *oc; /* Pointer to control structure.*/ 14606 int rv = BCM_E_NONE; 14607 14608 14609 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 14610 /* This endpoint id should have already been recovered during 14611 downmep recover. If not return ERROR */ 14612 if (1 != h_data_p->in_use) { 14613 return (BCM_E_INTERNAL); 14614 } 14615 14616 /* Egress parameters to (EGR_)MP_GROUP varies only for LSP 14617 * endpoints only. Retrieve for LSP. 14618 */ 14619 if (MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) { 14620 14621 bcm_oam_endpoint_info_t_init(&ep_info); 14622 14623 /* Set up endpoint information for key construction. */ 14624 ep_info.group = h_data_p->group_index; 14625 ep_info.name = h_data_p->name; 14626 ep_info.gport = h_data_p->gport; 14627 ep_info.level = h_data_p->level; 14628 ep_info.vlan = h_data_p->vlan; 14629 ep_info.inner_vlan = h_data_p->inner_vlan; 14630 ep_info.flags = h_data_p->flags; 14631 ep_info.mpls_label = h_data_p->label; 14632 ep_info.type = h_data_p->type; 14633 14634 /* 14635 * Calculate hash key for hash table remove 14636 * operation. 14637 */ 14638 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, &ep_info, 14639 &hash_key); 14640 14641 /* 14642 * Delete insert done by Downmep Rx endpoint recovery code. 14643 */ 14644 rv = shr_htb_find(oc->ma_mep_htbl, hash_key, 14645 (shr_htb_data_t *)&hash_data, 1); 14646 if (BCM_E_NOT_FOUND == rv) { 14647 return BCM_E_INTERNAL; 14648 } 14649 14650 h_data_p->name = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, 14651 MEPIDf); 14652 /* 14653 * Endpoint name has been recovered and will result 14654 * in a different hash index. Insert with the new hash index. 14655 */ 14656 ep_info.name = h_data_p->name; 14657 14658 /* 14659 * Calculate hash key for hash table insert 14660 * operation. 14661 */ 14662 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, &ep_info, 14663 &hash_key); 14664 BCM_IF_ERROR_RETURN(shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p)); 14665 #if defined(INCLUDE_L3) 14666 /* Recover egress if from EGR_L3_NEXT_HOP using MEPID */ 14667 _bcm_sb2_egr_l3_nxt_hop_egress_if_get_from_mepid(unit, h_data_p); 14668 #endif 14669 } 14670 return BCM_E_NONE; 14671 } 14672 14673 STATIC int 14674 _bcm_sb2_oam_mpls_lmdm_tx_config_recover(_bcm_oam_control_t *oc, 14675 int ma_idx, 14676 uint8 *scache, 14677 egr_mp_group_entry_t *egr_mp_grp_entry) 14678 { 14679 int ep_id[2] = {0,0}; /* Atmost 2 endpoints could be associated with 14680 same egr_mp_group entry */ 14681 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 14682 int unit = oc->unit; 14683 int num_ep_id = 0; 14684 uint32 key_type = 0; 14685 int id = 0; 14686 int ctr1_valid = 0, ctr2_valid = 0; 14687 uint32 ctr1_pool_id = 0, ctr2_pool_id = 0, ctr1_base_idx = 0, ctr2_base_idx = 0; 14688 14689 key_type = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, KEY_TYPEf); 14690 14691 /* Only LSPs could have 2 endpoints associated with same egr_mp_group entry */ 14692 if (key_type == _BCM_SB2_OAM_DOMAIN_EGR_MPLS_LMDM_LSP) { 14693 ctr1_valid = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, 14694 CTR1_VALIDf); 14695 ctr2_valid = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, 14696 CTR2_VALIDf); 14697 if (ctr1_valid && ctr2_valid) { 14698 ctr1_pool_id = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, 14699 CTR1_POOL_IDf); 14700 ctr2_pool_id = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, 14701 CTR2_POOL_IDf); 14702 ctr1_base_idx = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, 14703 CTR1_BASE_PTRf); 14704 ctr2_base_idx = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, 14705 CTR2_BASE_PTRf); 14706 ep_id[0] = _bcm_sb2_oam_mpls_lmdm_find_lsp_ep_id_from_egr_ctr_info(oc, 14707 ctr1_pool_id, 14708 ctr1_base_idx); 14709 if (ep_id[0] != -1) { 14710 num_ep_id++; 14711 } 14712 ep_id[1] = _bcm_sb2_oam_mpls_lmdm_find_lsp_ep_id_from_egr_ctr_info(oc, 14713 ctr2_pool_id, 14714 ctr2_base_idx); 14715 if (ep_id[1] != -1) { 14716 num_ep_id++; 14717 } 14718 } else { 14719 /* Else take it from scache itself since it will match */ 14720 sal_memcpy(&(ep_id[0]), scache + (_BCM_SB2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ma_idx)), 14721 sizeof(bcm_oam_endpoint_t)); 14722 num_ep_id++; 14723 } 14724 } else { 14725 /* Else take it from scache itself since it will match */ 14726 sal_memcpy(&(ep_id[0]), scache + (_BCM_SB2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ma_idx)), 14727 sizeof(bcm_oam_endpoint_t)); 14728 num_ep_id++; 14729 } 14730 14731 for (id = 0; id < num_ep_id; id++) { 14732 h_data_p = &oc->oam_hash_data[ep_id[id]]; 14733 if (h_data_p->in_use != 1) { 14734 return BCM_E_INTERNAL; 14735 } 14736 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_mpls_lmdm_tx_config_recover_for_ep_id(unit, 14737 h_data_p, egr_mp_grp_entry)); 14738 } 14739 14740 return BCM_E_NONE; 14741 } 14742 14743 14744 /* 14745 * Function: 14746 * _bcm_sb2_oam_lmep_upmep_rx_config_recover 14747 * Purpose: 14748 * Recover OAM local endpoint Rx configuration for UpMEPS 14749 * and the BHH endpoint type. 14750 * Parameters: 14751 * unit - (IN) BCM device number 14752 * index - (IN) Remote MEP hardware index. 14753 * egr_mp_grp_entry - (IN) Egress MP group table entry pointer. 14754 * Returns: 14755 * BCM_E_XXX 14756 */ 14757 STATIC int 14758 _bcm_sb2_oam_lmep_upmep_rx_config_recover(int unit, 14759 int index, 14760 egr_mp_group_entry_t *egr_mp_grp_entry, 14761 uint8 **scache, 14762 uint16 recovered_ver) 14763 { 14764 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 14765 ma_index_entry_t ma_idx_entry; /* MA_INDEX table entry. */ 14766 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 14767 uint8 mdl_bitmap; /* Endpoint domain level bitmap. */ 14768 uint8 mdl; /* Maintenance domain level. */ 14769 int rv,tmp_rv; /* Operation return status. */ 14770 _bcm_gport_dest_t gport_dest; /* Gport specification. */ 14771 bcm_gport_t gport; /* Gport value. */ 14772 uint16 glp; /* Generic logical port value. */ 14773 int ep_id; /* Endpoint ID. */ 14774 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 14775 bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information. */ 14776 int lmep_type = 0; 14777 int timestamp_type = 0; 14778 int ma_offset = 0; 14779 uint8 oam_domain = 0; 14780 int ma_base_idx = 0; 14781 int ma_idx = 0; 14782 uint8 *lm_dm_scache_info_ptr = NULL; 14783 bcm_port_t pp_port; 14784 mp_group_entry_t mp_group_entry; 14785 int entry_index = -1; 14786 uint8 mdl_mip = 0; 14787 14788 LOG_DEBUG(BSL_LS_BCM_OAM, 14789 (BSL_META_U(unit, 14790 "OAM(unit %d) Info: _bcm_sb2_oam_lmep_upmep_rx_config_recover .\n"), 14791 unit)); 14792 /* 14793 * Get OAM control structure. 14794 * Note: Lock taken by calling routine. 14795 */ 14796 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 14797 14798 /* recover UpMEPs */ 14799 mdl_bitmap = soc_EGR_MP_GROUPm_field32_get(unit, 14800 egr_mp_grp_entry, 14801 MDL_BITMAP_ACTIVEf); 14802 14803 for (mdl = 0; mdl < _BCM_OAM_EP_LEVEL_COUNT; mdl++) { 14804 14805 if (mdl_bitmap & (1 << mdl)) { 14806 14807 ma_base_idx = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, 14808 MA_BASE_PTRf); 14809 ma_idx = ma_base_idx + ma_offset; 14810 14811 oam_domain = soc_EGR_MP_GROUPm_field32_get(unit, 14812 egr_mp_grp_entry, 14813 KEY_TYPEf); 14814 14815 if ((oam_domain >= _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW) && 14816 (oam_domain <= _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN)) { 14817 /* MPLS LM/DM endpoints doesnt have UP MEPs. But active bitmap is 14818 configured. We could recover some tx configs from it. 14819 Handle it separately. */ 14820 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_mpls_lmdm_tx_config_recover( 14821 oc, ma_idx, *scache, egr_mp_grp_entry)); 14822 continue; 14823 } 14824 14825 if (recovered_ver >= BCM_WB_VERSION_1_1) { 14826 sal_memcpy(&ep_id, *(scache) + (_BCM_SB2_OAM_RX_UPMEP_SCACHE_LOCATION(ma_idx)), 14827 sizeof(bcm_oam_endpoint_t)); 14828 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id); 14829 if (BCM_FAILURE(rv)) { 14830 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 14831 LOG_ERROR(BSL_LS_BCM_OAM, 14832 (BSL_META_U(unit, 14833 "OAM Error: (EP_ID=%d) Index reserve " 14834 " failed - %s.\n"), ep_id, bcm_errmsg(rv))); 14835 return (rv); 14836 } 14837 } else { 14838 14839 /* Allocate the next available endpoint index. */ 14840 rv = shr_idxres_list_alloc(oc->mep_pool, 14841 (shr_idxres_element_t *)&ep_id); 14842 if (BCM_FAILURE(rv)) { 14843 LOG_ERROR(BSL_LS_BCM_OAM, 14844 (BSL_META_U(unit, 14845 "OAM(unit %d) Error: Endpoint alloc (EP=%d) - %s.\n"), 14846 unit, ep_id, bcm_errmsg(rv))); 14847 goto cleanup; 14848 } 14849 } 14850 14851 h_data_p = &oc->oam_hash_data[ep_id]; 14852 if (1 == h_data_p->in_use) { 14853 rv = BCM_E_INTERNAL; 14854 goto cleanup; 14855 } 14856 14857 /* 14858 * Clear the hash data element contents before 14859 * storing values. 14860 */ 14861 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 14862 _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p); 14863 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 14864 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 14865 h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX; 14866 h_data_p->profile_index = _BCM_OAM_INVALID_INDEX; 14867 h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX; 14868 h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 14869 h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 14870 h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 14871 h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 14872 h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 14873 h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 14874 h_data_p->trunk_id = BCM_TRUNK_INVALID; 14875 #if defined (BCM_METROLITE_SUPPORT) 14876 if(SOC_IS_METROLITE(unit)) { 14877 h_data_p->lm_count_profile = _BCM_OAM_INVALID_INDEX; 14878 } 14879 #endif 14880 h_data_p->ep_id = ep_id; 14881 h_data_p->ma_base_index = ma_base_idx; 14882 h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset; 14883 h_data_p->active_mdl_bitmap = mdl_bitmap; 14884 ma_offset++; 14885 14886 rv = READ_EGR_MA_INDEXm(unit, MEM_BLOCK_ANY, 14887 h_data_p->local_rx_index, &ma_idx_entry); 14888 if (BCM_FAILURE(rv)) { 14889 LOG_ERROR(BSL_LS_BCM_OAM, 14890 (BSL_META_U(unit, 14891 "OAM(unit %d) Error: EGR_MA_INDEX(index:%d) " 14892 "read failed -" " %s.\n"), unit, 14893 h_data_p->local_rx_index, bcm_errmsg(rv))); 14894 goto cleanup; 14895 } 14896 14897 h_data_p->flags |= BCM_OAM_ENDPOINT_UP_FACING; 14898 h_data_p->in_use = 1; 14899 h_data_p->is_remote = 0; 14900 h_data_p->local_rx_enabled = 1; 14901 h_data_p->flags |= BCM_OAM_ENDPOINT_CCM_RX; 14902 h_data_p->group_index 14903 = soc_EGR_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf); 14904 14905 h_data_p->profile_index 14906 = soc_EGR_MA_INDEXm_field32_get 14907 (unit, &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf); 14908 14909 rv = soc_profile_mem_reference(unit, &oc->egr_oam_opcode_control_profile, 14910 _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(h_data_p->profile_index), 14911 _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE); 14912 if (BCM_FAILURE(rv)) { 14913 LOG_ERROR(BSL_LS_BCM_OAM, 14914 (BSL_META_U(unit, 14915 "OAM(unit %d) Error: Profile entry recover failed " 14916 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 14917 goto cleanup; 14918 } 14919 14920 #if defined(BCM_METROLITE_SUPPORT) 14921 if(SOC_IS_METROLITE(unit)) { 14922 h_data_p->lm_count_profile = soc_EGR_MA_INDEXm_field32_get (unit, &ma_idx_entry, 14923 OAM_COUNT_PROFILEf); 14924 rv = soc_profile_mem_reference(unit, &oc->ing_lm_counter_control_profile, 14925 h_data_p->lm_count_profile, 14926 _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE); 14927 if (BCM_FAILURE(rv)) { 14928 LOG_ERROR(BSL_LS_BCM_OAM, 14929 (BSL_META_U(unit, 14930 "OAM(unit %d) Error: LM Profile entry recover failed " 14931 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 14932 goto cleanup; 14933 } 14934 14935 rv = soc_profile_mem_reference(unit, &oc->egr_lm_counter_control_profile, 14936 h_data_p->lm_count_profile, 14937 _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE); 14938 if (BCM_FAILURE(rv)) { 14939 LOG_ERROR(BSL_LS_BCM_OAM, 14940 (BSL_META_U(unit, 14941 "OAM(unit %d) Error: LM Profile entry recover failed " 14942 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 14943 goto cleanup; 14944 } 14945 } 14946 #endif 14947 14948 h_data_p->dglp1_profile_index = 14949 soc_MA_INDEXm_field32_get 14950 (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf); 14951 rv = soc_profile_mem_reference(unit, &oc->egr_oam_dglp_profile, 14952 h_data_p->dglp1_profile_index, 1); 14953 if (BCM_FAILURE(rv)) { 14954 LOG_ERROR(BSL_LS_BCM_OAM, 14955 (BSL_META_U(unit, 14956 "OAM(unit %d) Error: DGLP profile ref count " 14957 "increment failed (EP=%d) - %s.\n"), unit, 14958 h_data_p->ep_id, bcm_errmsg(rv))); 14959 goto cleanup; 14960 } 14961 h_data_p->dglp2_profile_index = 14962 soc_MA_INDEXm_field32_get 14963 (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf); 14964 rv = soc_profile_mem_reference(unit, &oc->egr_oam_dglp_profile, 14965 h_data_p->dglp2_profile_index, 1); 14966 if (BCM_FAILURE(rv)) { 14967 LOG_ERROR(BSL_LS_BCM_OAM, 14968 (BSL_META_U(unit, 14969 "OAM(unit %d) Error: DGLP profile ref count " 14970 "increment failed (EP=%d) - %s.\n"), unit, 14971 h_data_p->ep_id, bcm_errmsg(rv))); 14972 goto cleanup; 14973 } 14974 #if defined(INCLUDE_BHH) 14975 h_data_p->cpu_qid 14976 = soc_EGR_MA_INDEXm_field32_get(unit, &ma_idx_entry, INT_PRIf); 14977 #endif 14978 h_data_p->name = 0x0; /* No need to set it to 0xffff */ 14979 h_data_p->level = mdl; 14980 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 14981 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 14982 /* recover counters */ 14983 rv = _bcm_sb2_oam_rx_counter_recover(unit, EGR_MP_GROUPm, 14984 (uint32 *)egr_mp_grp_entry, h_data_p); 14985 if (BCM_FAILURE(rv)) { 14986 LOG_ERROR(BSL_LS_BCM_OAM, 14987 (BSL_META_U(unit, 14988 "OAM(unit %d) Error: LM RX counter recover failed " 14989 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 14990 goto cleanup; 14991 } 14992 /* rx and tx counters are located at same index, but on diff mem */ 14993 if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) { 14994 h_data_p->tx_ctr = h_data_p->rx_ctr; 14995 } 14996 14997 /* time stamp */ 14998 timestamp_type = soc_EGR_MP_GROUPm_field32_get(unit, 14999 egr_mp_grp_entry, TIMESTAMP_TYPEf); 15000 if (timestamp_type) { 15001 h_data_p->ts_format = !timestamp_type; 15002 } 15003 15004 h_data_p->oam_domain = oam_domain; 15005 15006 switch (h_data_p->oam_domain) { 15007 case _BCM_OAM_DOMAIN_CVLAN: 15008 h_data_p->flags |= BCM_OAM_ENDPOINT_MATCH_INNER_VLAN; 15009 h_data_p->inner_vlan = soc_EGR_MP_GROUPm_field32_get(unit, 15010 egr_mp_grp_entry, CVIDf); 15011 break; 15012 15013 case _BCM_OAM_DOMAIN_SVLAN: 15014 h_data_p->vlan = soc_EGR_MP_GROUPm_field32_get(unit, 15015 egr_mp_grp_entry, SVIDf); 15016 break; 15017 15018 case _BCM_OAM_DOMAIN_S_PLUS_CVLAN: 15019 h_data_p->vlan = soc_EGR_MP_GROUPm_field32_get(unit, 15020 egr_mp_grp_entry, SVIDf); 15021 h_data_p->inner_vlan = soc_EGR_MP_GROUPm_field32_get(unit, 15022 egr_mp_grp_entry, CVIDf); 15023 h_data_p->flags |= BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN; 15024 break; 15025 15026 case _BCM_OAM_DOMAIN_VP: 15027 h_data_p->vp = soc_EGR_MP_GROUPm_field32_get(unit, 15028 egr_mp_grp_entry, VPf); 15029 h_data_p->int_flags |= _BCM_OAM_ENDPOINT_IS_VP_BASED; 15030 break; 15031 default : 15032 break; 15033 15034 } 15035 15036 glp = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, GLPf); 15037 15038 lmep_type = soc_EGR_MP_GROUPm_field32_get(unit, egr_mp_grp_entry, 15039 KEY_TYPEf); 15040 15041 if (lmep_type == _BCM_OAM_DOMAIN_VP) { 15042 #if defined(INCLUDE_L3) 15043 if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMim)) { 15044 15045 BCM_GPORT_MIM_PORT_ID_SET(h_data_p->gport, h_data_p->vp); 15046 15047 } else if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMpls)) { 15048 15049 BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp); 15050 15051 } else { 15052 LOG_ERROR(BSL_LS_BCM_OAM, 15053 (BSL_META_U(unit, 15054 "OAM(unit %d) Error: Invalid Virtual Port (SVP=%d)" 15055 " - %s.\n"), unit, h_data_p->vp, 15056 bcm_errmsg(BCM_E_INTERNAL))); 15057 return (BCM_E_INTERNAL); 15058 } 15059 #endif 15060 } else { 15061 /* 15062 * Generic logical port type, construct gport from GLP. 15063 */ 15064 h_data_p->dglp = glp; 15065 15066 _bcm_gport_dest_t_init(&gport_dest); 15067 15068 if (_BCM_OAM_GLP_TRUNK_BIT_GET(glp)) { 15069 gport_dest.tgid = _BCM_OAM_GLP_TRUNK_ID_GET(glp); 15070 gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 15071 h_data_p->trunk_id = _BCM_OAM_GLP_TRUNK_ID_GET(glp); 15072 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport); 15073 } else { 15074 gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 15075 gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(glp); 15076 gport_dest.port = _BCM_OAM_GLP_PORT_GET(glp); 15077 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit, gport_dest.modid, 15078 gport_dest.port, &pp_port)); 15079 /* Check if the pp_port corresponding to mod port is in 15080 * subport port range. 15081 */ 15082 if (SOC_PP_PORT_VALID(unit, pp_port)) { 15083 _BCM_KT2_SUBPORT_PORT_ID_SET(gport, pp_port); 15084 /* Get gport for subport port case */ 15085 rv = BCM_E_NONE; 15086 if (BCM_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) { 15087 _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport, _BCM_KT2_SUBPORT_TYPE_LINKPHY); 15088 } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) { 15089 _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport, _BCM_KT2_SUBPORT_TYPE_SUBTAG); 15090 } else { 15091 rv = BCM_E_PORT; 15092 } 15093 } else { 15094 /* Go through original gport construction */ 15095 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport); 15096 } 15097 } 15098 15099 if (BCM_FAILURE(rv)) { 15100 LOG_ERROR(BSL_LS_BCM_OAM, 15101 (BSL_META_U(unit, 15102 "OAM(unit %d) Error: Gport construct failed -" 15103 " %s.\n"), unit, bcm_errmsg(rv))); 15104 goto cleanup; 15105 } 15106 15107 h_data_p->gport = gport; 15108 } 15109 h_data_p->dglp = glp; 15110 h_data_p->sglp = glp; 15111 15112 sal_memset(&mp_group_entry, 0, sizeof(mp_group_entry_t)); 15113 L3_LOCK(unit); 15114 if (BCM_SUCCESS 15115 (_bcm_sb2_oam_find_lmep(unit, h_data_p, 15116 &entry_index, &mp_group_entry))) { 15117 mdl_mip = soc_MP_GROUPm_field32_get(unit, &mp_group_entry, 15118 MDL_BITMAP_PASSIVEf); 15119 } 15120 L3_UNLOCK(unit); 15121 15122 if (!(mdl_mip & (1 << h_data_p->level))) { 15123 /* Set the MIP flag */ 15124 h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE; 15125 } 15126 15127 /* Recover ETH LM/DM info */ 15128 if (recovered_ver >= BCM_WB_VERSION_1_1) { 15129 if (bcmOAMEndpointTypeEthernet == h_data_p->type) { 15130 lm_dm_scache_info_ptr = *scache + _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE; 15131 _bcm_sb2_oam_lmdm_info_recover(h_data_p, lm_dm_scache_info_ptr, oc); 15132 } 15133 } 15134 15135 rv = _bcm_sb2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id); 15136 if (BCM_FAILURE(rv)) { 15137 goto cleanup; 15138 } 15139 15140 rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_add(unit, h_data_p); 15141 if (BCM_FAILURE(rv)) { 15142 LOG_ERROR(BSL_LS_BCM_OAM, 15143 (BSL_META_U(unit, 15144 "OAM(unit %d) Error: Add mapping from ma_idx_to_ep_id list (EP=%d) -" 15145 " %s.\n"), unit, ep_id, bcm_errmsg(rv))); 15146 _bcm_sb2_oam_group_ep_list_remove(unit, 15147 h_data_p->group_index, 15148 ep_id); 15149 goto cleanup; 15150 } 15151 15152 15153 rv = _bcm_sb2_oam_endpoint_alloc(&ep_info); 15154 if (BCM_FAILURE(rv)) { 15155 _bcm_sb2_oam_group_ep_list_remove(unit, 15156 h_data_p->group_index, 15157 ep_id); 15158 goto cleanup; 15159 } 15160 15161 bcm_oam_endpoint_info_t_init(ep_info); 15162 15163 /* Set up endpoint information for key construction. */ 15164 ep_info->group = h_data_p->group_index; 15165 ep_info->name = h_data_p->name; 15166 ep_info->gport = h_data_p->gport; 15167 ep_info->level = h_data_p->level; 15168 ep_info->vlan = h_data_p->vlan; 15169 ep_info->inner_vlan = h_data_p->inner_vlan; 15170 ep_info->flags = h_data_p->flags; 15171 if (!(MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p))) { 15172 ep_info->mpls_label = h_data_p->label; 15173 } 15174 ep_info->type = h_data_p->type; 15175 if ((recovered_ver < BCM_WB_VERSION_1_9) 15176 || (!ETH_TYPE(h_data_p->type))) { 15177 /* 15178 * Calculate hash key for hash table insert 15179 * operation. 15180 */ 15181 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 15182 15183 15184 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 15185 if (BCM_FAILURE(rv)) { 15186 LOG_ERROR(BSL_LS_BCM_OAM, 15187 (BSL_META_U(unit, 15188 "OAM(unit %d) Error: Hash table insert" 15189 " (EP=%d) failed - %s.\n"), unit, 15190 h_data_p->ep_id, bcm_errmsg(rv))); 15191 15192 _bcm_sb2_oam_group_ep_list_remove(unit, 15193 h_data_p->group_index, 15194 ep_id); 15195 goto cleanup; 15196 } else { 15197 LOG_DEBUG(BSL_LS_BCM_OAM, 15198 (BSL_META_U(unit, 15199 "OAM(unit %d) Info: Hash Tbl (EP=%d)" 15200 " inserted - %s.\n"), unit, ep_id, 15201 bcm_errmsg(rv))); 15202 } 15203 } 15204 sal_free(ep_info); 15205 /* Make it NULL to avoid dangling pointer free in cleanup */ 15206 ep_info = NULL; 15207 } 15208 } /* end of for loop */ 15209 if (mdl_bitmap) { 15210 if (!((oam_domain >= _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW) && 15211 (oam_domain <= _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN))) { 15212 /* MPLS LM/DM endpoints doesnt have UP MEPs. But active bitmap 15213 is configured. So there would not be h_data_p here. do not 15214 touch egr_ma_idx_pool.*/ 15215 rv = shr_idxres_list_reserve(oc->egr_ma_idx_pool, 15216 h_data_p->ma_base_index, 15217 h_data_p->ma_base_index + 7); 15218 if (BCM_FAILURE(rv)) { 15219 LOG_ERROR(BSL_LS_BCM_OAM, 15220 (BSL_META_U(unit, 15221 "OAM(unit %d) Error: (LMEP=%d) EGR MA Index reserve " 15222 "failed" " - %s.\n"), unit, h_data_p->remote_index, 15223 bcm_errmsg(rv))); 15224 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 15225 goto cleanup; 15226 } 15227 } 15228 } 15229 15230 LOG_DEBUG(BSL_LS_BCM_OAM, 15231 (BSL_META_U(unit, 15232 "OAM(unit %d) Info: _bcm_sb2_oam_lmep_rx_config_recover" 15233 " - done.\n"), unit)); 15234 return (BCM_E_NONE); 15235 15236 cleanup: 15237 /* Lets not check return value of delete during cleanup */ 15238 tmp_rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p); 15239 if (BCM_FAILURE(tmp_rv)) { 15240 LOG_DEBUG(BSL_LS_BCM_OAM, 15241 (BSL_META_U(unit, 15242 "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) -" 15243 " during cleanup %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 15244 } 15245 15246 15247 if (NULL != ep_info) { 15248 sal_free(ep_info); 15249 } 15250 15251 if (BCM_E_EXISTS 15252 == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) { 15253 shr_idxres_list_free(oc->mep_pool, ep_id); 15254 } 15255 /* return rx & tx counters allocated if any */ 15256 if (NULL != h_data_p) { 15257 rv =_bcm_sb2_oam_free_counter(unit, h_data_p); 15258 if (BCM_FAILURE(rv)) { 15259 LOG_ERROR(BSL_LS_BCM_OAM, 15260 (BSL_META_U(unit, 15261 "OAM(unit %d) Error: LM counter block " 15262 "free failed (EP=%d) - %s.\n"), 15263 unit, ep_id, bcm_errmsg(rv))); 15264 } 15265 } 15266 if (NULL != h_data_p 15267 && (BCM_E_EXISTS 15268 == shr_idxres_list_elem_state(oc->egr_ma_idx_pool, 15269 h_data_p->ma_base_index))) { 15270 15271 shr_idxres_list_free(oc->egr_ma_idx_pool, h_data_p->ma_base_index); 15272 15273 } 15274 15275 if (NULL != h_data_p) { 15276 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 15277 } 15278 LOG_DEBUG(BSL_LS_BCM_OAM, 15279 (BSL_META_U(unit, 15280 "OAM(unit %d) Info: _bcm_sb2_oam_lmep_rx_config_recover" 15281 " - error_done.\n"), unit)); 15282 return (rv); 15283 } 15284 15285 /* 15286 * Function: 15287 * _bcm_sb2_oam_lmep_downmep_rx_config_recover 15288 * Purpose: 15289 * Recover OAM local endpoint Rx configuration for DownMEPS. 15290 * Parameters: 15291 * unit - (IN) BCM device number 15292 * index - (IN) Remote MEP hardware index. 15293 * mp_group_entry - (IN) LMEP view table entry pointer. 15294 * Returns: 15295 * BCM_E_XXX 15296 */ 15297 STATIC int 15298 _bcm_sb2_oam_lmep_downmep_rx_config_recover(int unit, 15299 int index, 15300 mp_group_entry_t *mp_group_entry, 15301 uint8 **scache, 15302 uint16 recovered_ver) 15303 { 15304 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 15305 ma_index_entry_t ma_idx_entry; /* IA_INDEX table entry. */ 15306 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 15307 uint8 mdl_bitmap; /* Endpoint domain level bitmap. */ 15308 uint8 mdl; /* Maintenance domain level. */ 15309 int rv, tmp_rv; /* Operation return status. */ 15310 _bcm_gport_dest_t gport_dest; /* Gport specification. */ 15311 bcm_gport_t gport; /* Gport value. */ 15312 uint16 glp; /* Generic logical port value. */ 15313 int ep_id; /* Endpoint ID. */ 15314 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 15315 bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information. */ 15316 int timestamp_type = 0; 15317 int ma_offset = 0; 15318 int ma_base_idx = 0; 15319 int ma_idx = 0; 15320 #if defined(INCLUDE_L3) 15321 bcm_mpls_port_t mpls_port; 15322 #endif 15323 uint8 *lm_dm_scache_info_ptr = NULL; 15324 #if defined(INCLUDE_BHH) 15325 bcm_oam_endpoint_t bhh_endpoint_index = 0; 15326 bhh_sdk_msg_ctrl_sess_get_t msg; 15327 mpls_entry_entry_t mpls_entry; 15328 uint16 buffer_len, reply_len; 15329 uint8 *buffer, *buffer_ptr; 15330 int mpls_index = -1; 15331 bcm_l3_egress_t l3_egress; 15332 bcm_l3_intf_t l3_intf; 15333 uint8* encap_data = NULL; 15334 uint32 sglp = 0; /* Source global logical port. */ 15335 uint32 dglp = 0; /* Dest global logical port. */ 15336 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 15337 uint32 svp = 0; /* Source virtual port */ 15338 int is_vp_valid = 0; 15339 bcm_trunk_member_t trunk_member; 15340 bcm_port_t src_pp_port, dst_pp_port; 15341 bcm_cos_t int_pri; 15342 _mpls_label_t label; 15343 #endif 15344 int ma_idx_entry_count = 0; 15345 shr_idxres_list_handle_t pool = NULL; 15346 bcm_port_t pp_port; 15347 egr_mp_group_entry_t egr_mp_group; 15348 int mp_grp_index = 0; 15349 uint8 mdl_mip = 0; 15350 15351 LOG_DEBUG(BSL_LS_BCM_OAM, 15352 (BSL_META_U(unit, 15353 "OAM(unit %d) Info: " 15354 "_bcm_sb2_oam_lmep_downmep_rx_config_recover .\n"), unit)); 15355 /* 15356 * Get OAM control structure. 15357 * Note: Lock taken by calling routine. 15358 */ 15359 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 15360 15361 /* recover DownMEPs */ 15362 mdl_bitmap = soc_MP_GROUPm_field32_get(unit, 15363 mp_group_entry, MDL_BITMAP_ACTIVEf); 15364 ma_base_idx = soc_MP_GROUPm_field32_get(unit, mp_group_entry, MA_BASE_PTRf); 15365 15366 for (mdl = 0; mdl < _BCM_OAM_EP_LEVEL_COUNT; mdl++) { 15367 15368 if (mdl_bitmap & (1 << mdl)) { 15369 #if defined(INCLUDE_BHH) 15370 if (soc_feature(unit, soc_feature_bhh) && 15371 oc->ukernel_not_ready == 0 && 15372 SHR_BITGET(oc->bhh_ma_index_in_use, ma_base_idx) && 15373 BHH_UC_FEATURE_CHECK(BHH_WB_SESS_GET)) { 15374 /* Read MA_INDEX_ENTRY */ 15375 15376 rv = READ_MA_INDEXm (unit, MEM_BLOCK_ANY, 15377 ma_base_idx, 15378 &ma_idx_entry); 15379 if (BCM_FAILURE(rv)) { 15380 LOG_ERROR(BSL_LS_BCM_OAM, 15381 (BSL_META_U(unit, 15382 "BHH(unit %d) Error: MA_INDEX (index:%d) read failed -" 15383 " %s.\n"), unit, ma_base_idx, 15384 bcm_errmsg(rv))); 15385 goto cleanup; 15386 } 15387 15388 /*Fetch endpoint id from MA_INDEX_ENTRY and reserve in bhh_pool*/ 15389 bhh_endpoint_index = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf); 15390 ep_id = BCM_OAM_BHH_GET_SDK_EP(bhh_endpoint_index); 15391 15392 h_data_p = &oc->oam_hash_data[ep_id]; 15393 15394 h_data_p->ep_id = ep_id; 15395 h_data_p->bhh_endpoint_index = ep_id; 15396 h_data_p->ma_base_index = ma_base_idx; 15397 h_data_p->local_rx_index = h_data_p->ma_base_index + _BCM_OAM_EP_LEVEL_MAX + 1; 15398 h_data_p->oam_domain = _BCM_SB2_OAM_DOMAIN_BHH; 15399 h_data_p->group_index = oc->bhh_ep_grp_id[bhh_endpoint_index]; 15400 h_data_p->vpn = oc->bhh_ep_vpn[bhh_endpoint_index]; 15401 h_data_p->local_tx_enabled = 0; 15402 h_data_p->local_rx_enabled = 1; 15403 h_data_p->level = mdl; 15404 h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX; 15405 if (!(h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) { 15406 /* Get the endpoint parameters from firmware */ 15407 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 15408 MOS_MSG_SUBCLASS_BHH_SESS_GET, 15409 bhh_endpoint_index, 0, 15410 MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY, 15411 &reply_len); 15412 if (BCM_FAILURE(rv)) { 15413 LOG_ERROR(BSL_LS_BCM_OAM, 15414 (BSL_META_U(unit, 15415 "BHH(unit %d) Error: ukernel msg " 15416 "failed for" 15417 " EP=%d %s.\n"), unit, 15418 bhh_endpoint_index, 15419 bcm_errmsg(rv))); 15420 goto cleanup; 15421 } 15422 15423 buffer = oc->dma_buffer; 15424 buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg); 15425 buffer_len = buffer_ptr - buffer; 15426 15427 if (reply_len != buffer_len) { 15428 rv = BCM_E_INTERNAL; 15429 LOG_ERROR(BSL_LS_BCM_OAM, 15430 (BSL_META_U(unit, 15431 "BHH(unit %d) Error: ukernel msg " 15432 "failed for" 15433 " EP=%d %s.\n"), unit, 15434 bhh_endpoint_index, 15435 bcm_errmsg(rv))); 15436 goto cleanup; 15437 } 15438 15439 h_data_p->name = msg.mep_id; 15440 h_data_p->egress_if = msg.if_num; 15441 h_data_p->period = msg.local_period; 15442 h_data_p->label = msg.mpls_label; 15443 /* Set the flags */ 15444 if (msg.flags & SHR_BHH_SESS_SET_F_LB) 15445 h_data_p->flags |= BCM_OAM_ENDPOINT_LOOPBACK; 15446 else if (msg.flags & SHR_BHH_SESS_SET_F_DM) 15447 h_data_p->flags |= BCM_OAM_ENDPOINT_DELAY_MEASUREMENT; 15448 else if (msg.flags & SHR_BHH_SESS_SET_F_LM) 15449 h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 15450 else if (msg.flags & SHR_BHH_SESS_SET_F_MIP) 15451 h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE; 15452 if (BHH_UC_FEATURE_CHECK(BHH_OLP_ENCAP_VALID)) { 15453 bcm_oam_endpoint_info_t ep_info; 15454 uint8 ts_mode; 15455 uint8 lm_pdu_counter_offset = 0; 15456 int i = 0; 15457 uint8 counter_action[BCM_OAM_LM_COUNTER_MAX]; 15458 /* If this feature is valid, then encap_data is valid */ 15459 if (BCM_FAILURE(_bcm_sb2_oam_olp_encap_header_decap(unit, 15460 msg.encap_data, 15461 &(ep_info.ccm_tx_update_lm_counter_size), 15462 ep_info.ccm_tx_update_lm_counter_base_id, 15463 ep_info.ccm_tx_update_lm_counter_offset, 15464 counter_action, 15465 &ts_mode, 15466 &lm_pdu_counter_offset, 15467 &int_pri, 15468 NULL))) 15469 { 15470 LOG_ERROR(BSL_LS_BCM_OAM, 15471 (BSL_META_U(unit, 15472 "BHH(unit %d) Error: Failed to " 15473 "decap OLP TX header EP=%d\n"), 15474 unit, bhh_endpoint_index)); 15475 goto cleanup; 15476 } 15477 for (i = 0; i < ep_info.ccm_tx_update_lm_counter_size; 15478 i++) { 15479 if (counter_action[i] == 15480 bcmOamCounterActionSample) { 15481 if (SOC_IS_METROLITE (unit)) { 15482 h_data_p->int_flags |= 15483 _BCM_OAM_ENDPOINT_BHH_PROACTIVE_LM; 15484 } 15485 } 15486 } 15487 } 15488 _bcm_sb2_oam_bhh_get_egress_label_from_encap(h_data_p, 15489 msg.encap_data, 15490 msg.encap_length, 15491 &label); 15492 h_data_p->egr_label = label.label; 15493 } 15494 h_data_p->active_mdl_bitmap = soc_MP_GROUPm_field32_get(unit, 15495 mp_group_entry, 15496 MDL_BITMAP_ACTIVEf); 15497 15498 if (!BHH_EP_MPLS_SECTION_TYPE(h_data_p)) { 15499 /* port value from l3_egress_if*/ 15500 bcm_l3_egress_t_init(&l3_egress); 15501 if (BCM_FAILURE (bcm_esw_l3_egress_get(unit, 15502 h_data_p->egress_if, &l3_egress))) { 15503 LOG_ERROR(BSL_LS_BCM_OAM, 15504 (BSL_META_U(unit, 15505 "BHH(unit %d) Error: Failed to get L3 egress object" 15506 " EP=%d egress_if=%d %s.\n"), unit, bhh_endpoint_index, 15507 h_data_p->egress_if, bcm_errmsg(rv))); 15508 goto cleanup; 15509 } 15510 15511 l3_intf.l3a_intf_id = l3_egress.intf; 15512 if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) { 15513 LOG_ERROR(BSL_LS_BCM_OAM, 15514 (BSL_META_U(unit, 15515 "BHH(unit %d) Error: Failed to get L3 interface" 15516 " EP=%d l3a_intf_id=%d %s.\n"), unit, bhh_endpoint_index, 15517 l3_intf.l3a_intf_id, bcm_errmsg(rv))); 15518 goto cleanup; 15519 } 15520 sal_memcpy(h_data_p->dst_mac_address, l3_egress.mac_addr, _BHH_MAC_ADDR_LENGTH); 15521 sal_memcpy(h_data_p->src_mac_address, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH); 15522 15523 h_data_p->sglp = l3_egress.port; 15524 h_data_p->src_pp_port = l3_egress.port; 15525 h_data_p->dst_pp_port = l3_egress.port; 15526 h_data_p->dglp = l3_egress.port; 15527 h_data_p->vlan = l3_intf.l3a_vid; 15528 } else { 15529 encap_data = msg.encap_data; 15530 sal_memcpy(h_data_p->dst_mac_address, encap_data, _BHH_MAC_ADDR_LENGTH); 15531 encap_data += _BHH_MAC_ADDR_LENGTH; 15532 15533 sal_memcpy(h_data_p->src_mac_address, encap_data, _BHH_MAC_ADDR_LENGTH); 15534 encap_data += _BHH_MAC_ADDR_LENGTH; 15535 } 15536 15537 15538 /*Construct gprort */ 15539 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 15540 BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp); 15541 } else { 15542 _bcm_gport_dest_t_init(&gport_dest); 15543 15544 if (_BCM_OAM_GLP_TRUNK_BIT_GET(h_data_p->sglp)) { 15545 gport_dest.tgid = _BCM_OAM_GLP_TRUNK_ID_GET(h_data_p->sglp); 15546 gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 15547 h_data_p->trunk_id = _BCM_OAM_GLP_TRUNK_ID_GET(h_data_p->sglp); 15548 } else { 15549 gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 15550 gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(h_data_p->sglp); 15551 gport_dest.port = _BCM_OAM_GLP_PORT_GET(h_data_p->sglp); 15552 } 15553 15554 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport); 15555 if (BCM_FAILURE(rv)) { 15556 LOG_ERROR(BSL_LS_BCM_OAM, 15557 (BSL_META_U(unit, 15558 "BHH(unit %d) Error: Gport construct failed -" 15559 " %s.\n"), unit, bcm_errmsg(rv))); 15560 goto cleanup; 15561 } 15562 15563 h_data_p->gport = gport; 15564 } 15565 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 15566 /* get vccv_type from MPLS_ENTRY */ 15567 rv = _bcm_sb2_oam_mpls_entry_label_lookup(unit, h_data_p->label, 15568 h_data_p->sglp, 15569 &mpls_index, 15570 &mpls_entry); 15571 if(rv != BCM_E_NONE) { 15572 /* Not found or some other error */ 15573 LOG_ERROR(BSL_LS_BCM_OAM, 15574 (BSL_META_U(unit, 15575 "BHH(unit %d) Error: (Label=%u) - %s.\n"), 15576 unit, h_data_p->label, bcm_errmsg(rv))); 15577 goto cleanup; 15578 } 15579 h_data_p->vccv_type = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, PW_CC_TYPEf); 15580 h_data_p->vccv_type--; 15581 } 15582 15583 15584 timestamp_type = soc_MP_GROUPm_field32_get(unit, mp_group_entry,TIMESTAMP_TYPEf); 15585 15586 h_data_p->ts_format = !(timestamp_type); 15587 15588 h_data_p->int_pri = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, INT_PRIf); 15589 15590 /* Populate the hardware indicies */ 15591 h_data_p->profile_index = soc_MA_INDEXm_field32_get (unit, 15592 &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf); 15593 15594 rv = soc_profile_mem_reference(unit, &oc->oam_opcode_control_profile, 15595 _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(h_data_p->profile_index), 15596 _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE); 15597 if (BCM_FAILURE(rv)) { 15598 LOG_ERROR(BSL_LS_BCM_OAM, 15599 (BSL_META_U(unit, 15600 "BHH(unit %d) Error: Profile entry recover failed " 15601 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 15602 goto cleanup; 15603 } 15604 15605 /* Recover Rx counters */ 15606 rv = _bcm_sb2_oam_rx_counter_recover(unit, 15607 MP_GROUPm, (uint32 *)mp_group_entry, h_data_p); 15608 if (BCM_FAILURE(rv)) { 15609 LOG_ERROR(BSL_LS_BCM_OAM, 15610 (BSL_META_U(unit, 15611 "OAM(unit %d) Error: LM rx counter recover failed " 15612 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 15613 goto cleanup; 15614 } 15615 15616 /* rx and tx counters are located at same index, but on diff mem */ 15617 if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) { 15618 h_data_p->tx_ctr = h_data_p->rx_ctr; 15619 } 15620 15621 /* Add endpoint to group */ 15622 rv = _bcm_sb2_oam_group_ep_list_add(unit, h_data_p->group_index, 15623 h_data_p->ep_id); 15624 15625 if (BCM_FAILURE(rv)) { 15626 /* Return ID back to free MEP ID pool.*/ 15627 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_endpoint_index)); 15628 LOG_ERROR(BSL_LS_BCM_OAM, 15629 (BSL_META_U(unit, 15630 "BHH(unit %d) Error: Tx config failed for EP=%d %s.\n"), 15631 unit, h_data_p->ep_id, bcm_errmsg(rv))); 15632 goto cleanup; 15633 } 15634 15635 rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_add(unit, h_data_p); 15636 if (BCM_FAILURE(rv)) { 15637 LOG_ERROR(BSL_LS_BCM_OAM, 15638 (BSL_META_U(unit, 15639 "OAM(unit %d) Error: Add mapping from ma_idx_to_ep_id list (EP=%d) -" 15640 " %s.\n"), unit, ep_id, bcm_errmsg(rv))); 15641 _bcm_sb2_oam_group_ep_list_remove(unit, 15642 h_data_p->group_index, 15643 h_data_p->ep_id); 15644 goto cleanup; 15645 } 15646 15647 rv = _bcm_sb2_oam_endpoint_alloc(&ep_info); 15648 if (BCM_FAILURE(rv)) { 15649 _bcm_sb2_oam_group_ep_list_remove(unit, 15650 h_data_p->group_index, 15651 h_data_p->ep_id); 15652 goto cleanup; 15653 } 15654 15655 bcm_oam_endpoint_info_t_init(ep_info); 15656 15657 /* Set up endpoint information for key construction. */ 15658 ep_info->group = h_data_p->group_index; 15659 ep_info->name = h_data_p->name; 15660 ep_info->gport = h_data_p->gport; 15661 ep_info->level = h_data_p->level; 15662 ep_info->vlan = h_data_p->vlan; 15663 ep_info->inner_vlan = h_data_p->inner_vlan; 15664 ep_info->mpls_label = h_data_p->label; 15665 ep_info->type = h_data_p->type; 15666 15667 /* Resolve given endpoint gport value to SGLP and DGLP values. */ 15668 rv = _bcm_sb2_oam_endpoint_gport_resolve(unit, ep_info, &sglp, 15669 &dglp, &src_pp_port, &dst_pp_port, 15670 &svp, &trunk_id, &is_vp_valid, 15671 &trunk_member); 15672 if (BCM_FAILURE(rv)) { 15673 LOG_ERROR(BSL_LS_BCM_OAM, 15674 (BSL_META_U(unit, 15675 "OAM(unit %d) Error: Gport resolve (EP=%d) - %s.\n"), 15676 unit, h_data_p->ep_id, bcm_errmsg(rv))); 15677 _BCM_OAM_UNLOCK(oc); 15678 return (rv); 15679 } 15680 if (BCM_TRUNK_INVALID != trunk_id) { 15681 h_data_p->trunk_id = trunk_id; 15682 h_data_p->resolved_trunk_gport = trunk_member.gport; 15683 } 15684 15685 /* 15686 * Calculate hash key for hash table insert 15687 * operation. 15688 */ 15689 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 15690 15691 sal_free(ep_info); 15692 15693 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 15694 if (BCM_FAILURE(rv)) { 15695 LOG_ERROR(BSL_LS_BCM_OAM, 15696 (BSL_META_U(unit, 15697 "BHH(unit %d) Error: Hash table insert" 15698 "(EP=%d) failed - %s.\n"), unit, 15699 h_data_p->ep_id, bcm_errmsg(rv))); 15700 goto cleanup; 15701 } else { 15702 LOG_DEBUG(BSL_LS_BCM_OAM, 15703 (BSL_META_U(unit, 15704 "BHH(unit %d) Info: Hash Tbl (EP=%d)" 15705 " inserted - %s.\n"), unit, ep_id, 15706 bcm_errmsg(rv))); 15707 } 15708 h_data_p->in_use = 1; 15709 15710 sal_memset(&egr_mp_group, 0, sizeof(egr_mp_group_entry_t)); 15711 if (BCM_SUCCESS 15712 (_bcm_sb2_oam_find_egr_lmep(unit, h_data_p, 15713 &mp_grp_index, 15714 &egr_mp_group))) { 15715 mdl_mip = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, 15716 MDL_BITMAP_PASSIVEf); 15717 } 15718 15719 if (!(mdl_mip & (1 << h_data_p->level))) { 15720 /* Set the MIP flag */ 15721 h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE; 15722 } 15723 15724 } else 15725 #endif /* BHH*/ 15726 { 15727 15728 if (recovered_ver >= BCM_WB_VERSION_1_1) { 15729 ma_idx = ma_base_idx + ma_offset; 15730 sal_memcpy(&ep_id, *(scache) + (_BCM_SB2_OAM_RX_DOWNMEP_SCACHE_LOCATION(ma_idx)), 15731 sizeof(bcm_oam_endpoint_t)); 15732 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id); 15733 if (BCM_FAILURE(rv)) { 15734 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 15735 LOG_ERROR(BSL_LS_BCM_OAM, 15736 (BSL_META_U(unit, 15737 "OAM Error: (EP_ID=%d) Index reserve " 15738 " failed - %s.\n"), ep_id, bcm_errmsg(rv))); 15739 return (rv); 15740 } 15741 } else { 15742 /* Allocate the next available endpoint index. */ 15743 rv = shr_idxres_list_alloc(oc->mep_pool, 15744 (shr_idxres_element_t *)&ep_id); 15745 if (BCM_FAILURE(rv)) { 15746 LOG_ERROR(BSL_LS_BCM_OAM, 15747 (BSL_META_U(unit, 15748 "OAM(unit %d) Error: Endpoint alloc (EP=%d) - %s.\n"), 15749 unit, ep_id, bcm_errmsg(rv))); 15750 goto cleanup; 15751 } 15752 } 15753 h_data_p = &oc->oam_hash_data[ep_id]; 15754 if (1 == h_data_p->in_use) { 15755 return(BCM_E_INTERNAL); 15756 } 15757 15758 /* 15759 * Clear the hash data element contents before 15760 * storing values. 15761 */ 15762 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 15763 15764 _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p); 15765 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 15766 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 15767 h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX; 15768 h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 15769 h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 15770 h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 15771 h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 15772 h_data_p->trunk_id = BCM_TRUNK_INVALID; 15773 h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX; 15774 15775 h_data_p->ep_id = ep_id; 15776 h_data_p->ma_base_index = 15777 soc_MP_GROUPm_field32_get(unit, mp_group_entry, 15778 MA_BASE_PTRf); 15779 h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset; 15780 ma_offset++; 15781 15782 rv = READ_MA_INDEXm 15783 (unit, MEM_BLOCK_ANY, h_data_p->local_rx_index, 15784 &ma_idx_entry); 15785 if (BCM_FAILURE(rv)) { 15786 LOG_ERROR(BSL_LS_BCM_OAM, 15787 (BSL_META_U(unit, 15788 "OAM(unit %d) Error: MA_INDEX (index:%d) read failed -" 15789 " %s.\n"), unit, h_data_p->local_rx_index, 15790 bcm_errmsg(rv))); 15791 goto cleanup; 15792 } 15793 15794 h_data_p->in_use = 1; 15795 15796 h_data_p->is_remote = 0; 15797 15798 h_data_p->local_rx_enabled = 1; 15799 15800 h_data_p->group_index 15801 = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf); 15802 15803 h_data_p->int_pri = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, INT_PRIf); 15804 15805 h_data_p->active_mdl_bitmap = 15806 soc_MP_GROUPm_field32_get(unit, mp_group_entry, 15807 MDL_BITMAP_ACTIVEf); 15808 15809 h_data_p->profile_index 15810 = soc_MA_INDEXm_field32_get 15811 (unit, &ma_idx_entry, OAM_OPCODE_CONTROL_PROFILE_PTRf); 15812 rv = soc_profile_mem_reference(unit, &oc->oam_opcode_control_profile, 15813 _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(h_data_p->profile_index), 15814 _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE); 15815 if (BCM_FAILURE(rv)) { 15816 LOG_ERROR(BSL_LS_BCM_OAM, 15817 (BSL_META_U(unit, 15818 "OAM(unit %d) Error: Profile entry recover failed " 15819 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 15820 goto cleanup; 15821 } 15822 15823 #if defined(BCM_METROLITE_SUPPORT) 15824 if(SOC_IS_METROLITE(unit)) { 15825 h_data_p->lm_count_profile = soc_MA_INDEXm_field32_get (unit, &ma_idx_entry, 15826 OAM_COUNT_PROFILEf); 15827 rv = soc_profile_mem_reference(unit, &oc->ing_lm_counter_control_profile, 15828 h_data_p->lm_count_profile, 15829 _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE); 15830 if (BCM_FAILURE(rv)) { 15831 LOG_ERROR(BSL_LS_BCM_OAM, 15832 (BSL_META_U(unit, 15833 "OAM(unit %d) Error: Profile entry recover failed " 15834 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 15835 goto cleanup; 15836 } 15837 rv = soc_profile_mem_reference(unit, &oc->egr_lm_counter_control_profile, 15838 h_data_p->lm_count_profile, 15839 _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE); 15840 if (BCM_FAILURE(rv)) { 15841 LOG_ERROR(BSL_LS_BCM_OAM, 15842 (BSL_META_U(unit, 15843 "OAM(unit %d) Error: Profile entry recover failed " 15844 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 15845 goto cleanup; 15846 } 15847 } 15848 #endif 15849 15850 h_data_p->dglp1_profile_index = 15851 soc_MA_INDEXm_field32_get 15852 (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf); 15853 rv = soc_profile_mem_reference(unit, &oc->ing_oam_dglp_profile, 15854 h_data_p->dglp1_profile_index, 1); 15855 if (BCM_FAILURE(rv)) { 15856 LOG_ERROR(BSL_LS_BCM_OAM, 15857 (BSL_META_U(unit, 15858 "OAM(unit %d) Error: DGLP profile ref count " 15859 "increment failed (EP=%d) - %s.\n"), unit, 15860 h_data_p->ep_id, bcm_errmsg(rv))); 15861 goto cleanup; 15862 } 15863 h_data_p->dglp2_profile_index = 15864 soc_MA_INDEXm_field32_get 15865 (unit, &ma_idx_entry, DGLP1_PROFILE_PTRf); 15866 rv = soc_profile_mem_reference(unit, &oc->ing_oam_dglp_profile, 15867 h_data_p->dglp2_profile_index, 1); 15868 if (BCM_FAILURE(rv)) { 15869 LOG_ERROR(BSL_LS_BCM_OAM, 15870 (BSL_META_U(unit, 15871 "OAM(unit %d) Error: DGLP profile ref count " 15872 "increment failed (EP=%d) - %s.\n"), unit, 15873 h_data_p->ep_id, bcm_errmsg(rv))); 15874 goto cleanup; 15875 } 15876 15877 h_data_p->name = 0x0; /* No need to set it to 0xffff */ 15878 15879 h_data_p->level = mdl; 15880 15881 h_data_p->oam_domain = soc_MP_GROUPm_field32_get(unit, 15882 mp_group_entry, 15883 KEY_TYPEf); 15884 15885 switch (h_data_p->oam_domain) { 15886 case _BCM_OAM_DOMAIN_CVLAN: 15887 h_data_p->flags |= BCM_OAM_ENDPOINT_MATCH_INNER_VLAN; 15888 h_data_p->inner_vlan = 15889 soc_MP_GROUPm_field32_get(unit, 15890 mp_group_entry, CVIDf); 15891 h_data_p->type = bcmOAMEndpointTypeEthernet; 15892 break; 15893 15894 case _BCM_OAM_DOMAIN_SVLAN: 15895 h_data_p->vlan = soc_MP_GROUPm_field32_get(unit, 15896 mp_group_entry, SVIDf); 15897 h_data_p->type = bcmOAMEndpointTypeEthernet; 15898 break; 15899 15900 case _BCM_OAM_DOMAIN_S_PLUS_CVLAN: 15901 h_data_p->vlan = soc_MP_GROUPm_field32_get(unit, 15902 mp_group_entry, SVIDf); 15903 h_data_p->inner_vlan = 15904 soc_MP_GROUPm_field32_get(unit, 15905 mp_group_entry, CVIDf); 15906 h_data_p->flags |= 15907 BCM_OAM_ENDPOINT_MATCH_OUTER_AND_INNER_VLAN; 15908 h_data_p->type = bcmOAMEndpointTypeEthernet; 15909 break; 15910 15911 case _BCM_OAM_DOMAIN_VP: 15912 h_data_p->vp = soc_MP_GROUPm_field32_get(unit, 15913 mp_group_entry, VPf); 15914 h_data_p->type = bcmOAMEndpointTypeEthernet; 15915 h_data_p->int_flags |= _BCM_OAM_ENDPOINT_IS_VP_BASED; 15916 break; 15917 case _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW: 15918 h_data_p->type = bcmOAMEndpointTypeMplsLmDmPw; 15919 /* Get the SVP */ 15920 h_data_p->vp = soc_MP_GROUPm_field32_get(unit, 15921 mp_group_entry, VPf); 15922 h_data_p->int_flags |= _BCM_OAM_ENDPOINT_IS_VP_BASED; 15923 break; 15924 case _BCM_SB2_OAM_DOMAIN_ING_MPLS_LMDM_LSP: 15925 case _BCM_SB2_OAM_DOMAIN_EGR_MPLS_LMDM_LSP: 15926 h_data_p->type = bcmOAMEndpointTypeMplsLmDmLsp; 15927 h_data_p->label = soc_MP_GROUPm_field32_get(unit, 15928 mp_group_entry, MPLS_LABELf); 15929 break; 15930 case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION: 15931 h_data_p->type = bcmOAMEndpointTypeMplsLmDmSectionPort; 15932 break; 15933 case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_CVLAN: 15934 h_data_p->type = bcmOAMEndpointTypeMplsLmDmSectionInnervlan; 15935 h_data_p->inner_vlan = soc_MP_GROUPm_field32_get(unit, 15936 mp_group_entry, CVIDf); 15937 break; 15938 case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_SVLAN: 15939 h_data_p->type = bcmOAMEndpointTypeMplsLmDmSectionOuterVlan; 15940 h_data_p->vlan = soc_MP_GROUPm_field32_get(unit, 15941 mp_group_entry, SVIDf); 15942 break; 15943 case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN: 15944 h_data_p->type = bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan; 15945 h_data_p->inner_vlan = soc_MP_GROUPm_field32_get(unit, 15946 mp_group_entry, CVIDf); 15947 h_data_p->vlan = soc_MP_GROUPm_field32_get(unit, 15948 mp_group_entry, SVIDf); 15949 break; 15950 default : 15951 break; 15952 15953 } 15954 15955 rv = _bcm_sb2_oam_rx_counter_recover(unit, 15956 MP_GROUPm, (uint32 *)mp_group_entry, h_data_p); 15957 if (BCM_FAILURE(rv)) { 15958 LOG_ERROR(BSL_LS_BCM_OAM, 15959 (BSL_META_U(unit, 15960 "OAM(unit %d) Error: LM counter recover failed " 15961 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 15962 goto cleanup; 15963 } 15964 /* rx and tx counters are located at same index, but on diff mem */ 15965 if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) { 15966 h_data_p->tx_ctr = h_data_p->rx_ctr; 15967 } 15968 15969 /* time stamp */ 15970 timestamp_type = soc_MP_GROUPm_field32_get(unit, 15971 mp_group_entry, TIMESTAMP_TYPEf); 15972 if (timestamp_type) { 15973 h_data_p->ts_format = !timestamp_type; 15974 } 15975 glp = soc_MP_GROUPm_field32_get(unit, mp_group_entry, 15976 GLPf); 15977 15978 if (h_data_p->oam_domain == _BCM_OAM_DOMAIN_VP) { 15979 #if defined(INCLUDE_L3) 15980 if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMim)) { 15981 15982 BCM_GPORT_MIM_PORT_ID_SET(h_data_p->gport, h_data_p->vp); 15983 15984 } else if (_bcm_vp_used_get(unit, glp, _bcmVpTypeMpls)) { 15985 15986 BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp); 15987 15988 } else { 15989 LOG_ERROR(BSL_LS_BCM_OAM, 15990 (BSL_META_U(unit, 15991 "OAM(unit %d) Error: Invalid Virtual Port (SVP=%d)" 15992 " - %s.\n"), unit, h_data_p->vp, 15993 bcm_errmsg(BCM_E_INTERNAL))); 15994 return (BCM_E_INTERNAL); 15995 } 15996 #endif 15997 } else { 15998 /* Not resolving GPORT for PW MPLS LM/DM endpoints and 15999 * MPLS LSP endpoints with port independent label 16000 */ 16001 #if defined(INCLUDE_L3) 16002 if ((!MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p)) || 16003 (MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p) && 16004 (bcm_tr_mpls_port_independent_range(unit, h_data_p->label, 16005 BCM_GPORT_INVALID) != BCM_E_NONE))) 16006 #endif 16007 { 16008 /* 16009 * Generic logical port type, construct gport from GLP. 16010 */ 16011 _bcm_gport_dest_t_init(&gport_dest); 16012 16013 if (_BCM_OAM_GLP_TRUNK_BIT_GET(glp)) { 16014 gport_dest.tgid = _BCM_OAM_GLP_TRUNK_ID_GET(glp); 16015 gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 16016 h_data_p->trunk_id = _BCM_OAM_GLP_TRUNK_ID_GET(glp); 16017 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport); 16018 } else { 16019 gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 16020 gport_dest.modid = _BCM_OAM_GLP_MODULE_ID_GET(glp); 16021 gport_dest.port = _BCM_OAM_GLP_PORT_GET(glp); 16022 16023 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit, gport_dest.modid, 16024 gport_dest.port, &pp_port)); 16025 /* Check if the pp_port corresponding to mod port is in 16026 * subport port range. 16027 */ 16028 if (SOC_PP_PORT_VALID(unit, pp_port)) { 16029 _BCM_KT2_SUBPORT_PORT_ID_SET(gport, pp_port); 16030 /* Get gport for subport port case */ 16031 rv = BCM_E_NONE; 16032 if (BCM_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) { 16033 _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport, _BCM_KT2_SUBPORT_TYPE_LINKPHY); 16034 } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) { 16035 _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport, _BCM_KT2_SUBPORT_TYPE_SUBTAG); 16036 } else { 16037 rv = BCM_E_PORT; 16038 } 16039 } else { 16040 /* Go through original gport construction */ 16041 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport); 16042 } 16043 } 16044 16045 16046 if (BCM_FAILURE(rv)) { 16047 LOG_ERROR(BSL_LS_BCM_OAM, 16048 (BSL_META_U(unit, 16049 "OAM(unit %d) Error: Gport construct failed -" 16050 " %s.\n"), unit, bcm_errmsg(rv))); 16051 goto cleanup; 16052 } 16053 16054 h_data_p->gport = gport; 16055 } 16056 } 16057 h_data_p->dglp = glp; 16058 h_data_p->sglp = glp; 16059 16060 /* If it is ETH/MPLS LM/DM endpoint, retrieve 16061 * back the parameters stored in scache. 16062 */ 16063 if (recovered_ver >= BCM_WB_VERSION_1_1) { 16064 if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) || 16065 bcmOAMEndpointTypeEthernet == h_data_p->type) { 16066 16067 lm_dm_scache_info_ptr = *scache + _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE; 16068 _bcm_sb2_oam_lmdm_info_recover(h_data_p, lm_dm_scache_info_ptr, oc); 16069 } 16070 } 16071 #if defined(INCLUDE_MPLS_LM_DM) 16072 if (recovered_ver >= BCM_WB_VERSION_1_2) { 16073 if (MPLS_LM_DM_ENDPOINT_TYPE (h_data_p)) { 16074 lm_dm_scache_info_ptr = 16075 *scache + _BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE + 16076 _BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE + 16077 _BCM_OAM_EGR_LABEL_SCACHE_OFFSET(h_data_p->local_rx_index); 16078 _bcm_sb2_oam_copy_egr_label_scache_to_hash_data( 16079 (_bcm_sb2_oam_egr_label_scache_info_t *)lm_dm_scache_info_ptr, h_data_p); 16080 } 16081 } 16082 #endif 16083 16084 #if defined(INCLUDE_L3) 16085 if (MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p)) { 16086 if (_bcm_vp_used_get(unit, h_data_p->vp, _bcmVpTypeMpls)) { 16087 BCM_GPORT_MPLS_PORT_ID_SET(h_data_p->gport, h_data_p->vp); 16088 bcm_mpls_port_t_init(&mpls_port); 16089 mpls_port.mpls_port_id = h_data_p->gport; 16090 rv = bcm_esw_mpls_port_get(unit, h_data_p->vpn, 16091 &mpls_port); 16092 if (BCM_FAILURE(rv)) { 16093 LOG_ERROR(BSL_LS_BCM_OAM, 16094 (BSL_META_U(unit, 16095 "OAM(unit %d) Error: PW MPLS port info recover failed " 16096 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 16097 goto cleanup; 16098 } 16099 h_data_p->egress_if = mpls_port.egress_tunnel_if; 16100 h_data_p->label = mpls_port.match_label; 16101 /* Doing minus 1 to fit the range 1-4 into range 0-3 for vccv type */ 16102 h_data_p->vccv_type = mpls_port.vccv_type - 1; 16103 } else { 16104 /* The VP is not of type MPLS. Should not happen */ 16105 LOG_ERROR(BSL_LS_BCM_OAM, 16106 (BSL_META_U(unit, 16107 "OAM(unit %d) Error: LM counter recover failed " 16108 "(EP=%d) - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 16109 goto cleanup; 16110 16111 } 16112 } 16113 #endif 16114 16115 if (h_data_p->type == bcmOAMEndpointTypeEthernet) { 16116 h_data_p->flags |= BCM_OAM_ENDPOINT_CCM_RX; 16117 } 16118 16119 sal_memset(&egr_mp_group, 0, sizeof(egr_mp_group_entry_t)); 16120 if (BCM_SUCCESS 16121 (_bcm_sb2_oam_find_egr_lmep(unit, h_data_p, 16122 &mp_grp_index, 16123 &egr_mp_group))) { 16124 mdl_mip = soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, 16125 MDL_BITMAP_PASSIVEf); 16126 } 16127 16128 if (!(mdl_mip & (1 << h_data_p->level))) { 16129 /* Set the MIP flag */ 16130 h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE; 16131 } 16132 16133 rv = _bcm_sb2_oam_group_ep_list_add(unit, h_data_p->group_index, ep_id); 16134 if (BCM_FAILURE(rv)) { 16135 goto cleanup; 16136 } 16137 16138 rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_add(unit, h_data_p); 16139 if (BCM_FAILURE(rv)) { 16140 _bcm_sb2_oam_group_ep_list_remove(unit, 16141 h_data_p->group_index, 16142 ep_id); 16143 goto cleanup; 16144 } 16145 16146 rv = _bcm_sb2_oam_endpoint_alloc(&ep_info); 16147 if (BCM_FAILURE(rv)) { 16148 _bcm_sb2_oam_group_ep_list_remove(unit, 16149 h_data_p->group_index, 16150 ep_id); 16151 goto cleanup; 16152 } 16153 16154 bcm_oam_endpoint_info_t_init(ep_info); 16155 16156 /* Set up endpoint information for key construction. */ 16157 ep_info->group = h_data_p->group_index; 16158 ep_info->name = h_data_p->name; 16159 ep_info->gport = h_data_p->gport; 16160 ep_info->level = h_data_p->level; 16161 ep_info->vlan = h_data_p->vlan; 16162 ep_info->inner_vlan = h_data_p->inner_vlan; 16163 if (!(MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p))) { 16164 ep_info->mpls_label = h_data_p->label; 16165 } 16166 ep_info->type = h_data_p->type; 16167 if ((recovered_ver < BCM_WB_VERSION_1_9) 16168 || (!ETH_TYPE(h_data_p->type))) { 16169 /* 16170 * Calculate hash key for hash table insert 16171 * operation. 16172 */ 16173 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 16174 16175 16176 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 16177 if (BCM_FAILURE(rv)) { 16178 LOG_ERROR(BSL_LS_BCM_OAM, 16179 (BSL_META_U(unit, 16180 "OAM(unit %d) Error: Hash table insert" 16181 " (EP=%d) failed - %s.\n"), unit, 16182 h_data_p->ep_id, bcm_errmsg(rv))); 16183 16184 _bcm_sb2_oam_group_ep_list_remove(unit, 16185 h_data_p->group_index, 16186 ep_id); 16187 goto cleanup; 16188 } else { 16189 LOG_DEBUG(BSL_LS_BCM_OAM, 16190 (BSL_META_U(unit, 16191 "OAM(unit %d) Info: Hash Tbl (EP=%d)" 16192 " inserted - %s.\n"), unit, ep_id, 16193 bcm_errmsg(rv))); 16194 } 16195 } 16196 sal_free(ep_info); 16197 /* Make it NULL to avoid dangling pointer free in cleanup */ 16198 ep_info = NULL; 16199 } 16200 } 16201 16202 } /* end of for loop */ 16203 if (mdl_bitmap) { 16204 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_ma_idx_num_entries_and_pool_get(unit, 16205 h_data_p, &ma_idx_entry_count, &pool)); 16206 rv = shr_idxres_list_reserve(pool, 16207 h_data_p->ma_base_index, 16208 h_data_p->ma_base_index + ma_idx_entry_count -1); 16209 if (BCM_FAILURE(rv)) { 16210 LOG_ERROR(BSL_LS_BCM_OAM, 16211 (BSL_META_U(unit, 16212 "OAM(unit %d) Error: (RMEP=%d) Index reserve failed" 16213 " - %s.\n"), unit, h_data_p->remote_index, 16214 bcm_errmsg(rv))); 16215 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 16216 goto cleanup; 16217 } 16218 } 16219 16220 LOG_DEBUG(BSL_LS_BCM_OAM, 16221 (BSL_META_U(unit, 16222 "OAM(unit %d) Info: _bcm_sb2_oam_lmep_rx_config_recover" 16223 " - done.\n"), unit)); 16224 return (BCM_E_NONE); 16225 16226 cleanup: 16227 16228 tmp_rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_delete(unit, h_data_p); 16229 if (BCM_FAILURE(tmp_rv)) { 16230 LOG_DEBUG(BSL_LS_BCM_OAM, 16231 (BSL_META_U(unit, 16232 "OAM(unit %d) Error: Remove from ma_idx to ep id map (EP=%d) -" 16233 " during cleanup %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 16234 } 16235 16236 16237 if (NULL != ep_info) { 16238 sal_free(ep_info); 16239 } 16240 16241 if (BCM_E_EXISTS 16242 == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) { 16243 shr_idxres_list_free(oc->mep_pool, ep_id); 16244 } 16245 #if defined(INCLUDE_BHH) 16246 if (BCM_E_EXISTS 16247 == shr_idxres_list_elem_state(oc->bhh_pool,bhh_endpoint_index)) { 16248 shr_idxres_list_free(oc->bhh_pool,bhh_endpoint_index); 16249 } 16250 #endif 16251 /* return rx & tx counters allocated if any */ 16252 if (NULL != h_data_p) { 16253 rv =_bcm_sb2_oam_free_counter(unit, h_data_p); 16254 if (BCM_FAILURE(rv)) { 16255 LOG_ERROR(BSL_LS_BCM_OAM, 16256 (BSL_META_U(unit, 16257 "OAM(unit %d) Error: LM counter block " 16258 "free failed (EP=%d) - %s.\n"), 16259 unit, ep_id, bcm_errmsg(rv))); 16260 } 16261 } 16262 if (NULL != h_data_p && (BCM_E_EXISTS 16263 == shr_idxres_list_elem_state(pool, 16264 h_data_p->ma_base_index))) { 16265 16266 shr_idxres_list_free(pool, h_data_p->ma_base_index); 16267 16268 } 16269 16270 if (NULL != h_data_p) { 16271 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 16272 } 16273 LOG_DEBUG(BSL_LS_BCM_OAM, 16274 (BSL_META_U(unit, 16275 "OAM(unit %d) Info: _bcm_sb2_oam_lmep_rx_config_recover" 16276 " - error_done.\n"), unit)); 16277 return (rv); 16278 16279 } 16280 16281 /* 16282 * Function: 16283 * _bcm_sb2_oam_lmep_tx_config_recover 16284 * Purpose: 16285 * Recover OAM local endpoint Tx configuration. 16286 * Parameters: 16287 * unit - (IN) BCM device number 16288 * Returns: 16289 * BCM_E_XXX 16290 */ 16291 STATIC int 16292 _bcm_sb2_oam_lmep_tx_config_recover(int unit, uint8 **scache, 16293 uint16 recovered_ver) 16294 { 16295 _bcm_gport_dest_t gport_dest; /* Gport specification. */ 16296 bcm_gport_t gport; /* Gport value. */ 16297 int index; /* Hardware index. */ 16298 lmep_entry_t lmep_entry; /* LMEP table entry buffer. */ 16299 lmep_1_entry_t lmep_1_entry; /* LMEP table entry buffer. */ 16300 maid_reduction_entry_t maid_red_ent; /* MAID_REDUCTION table entry buf. */ 16301 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 16302 _bcm_oam_group_data_t *g_info_p; /* Group information pointer. */ 16303 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 16304 bcm_module_t modid; /* Module ID. */ 16305 bcm_port_t port_id; /* Port ID. */ 16306 bcm_trunk_t trunk_id; /* Trunk ID. */ 16307 uint32 grp_idx; /* Group index. */ 16308 uint16 glp; /* Generic logical port. */ 16309 uint16 vlan; /* VLAN ID. */ 16310 uint16 inner_vlan; /* Inner VLAN ID. */ 16311 uint8 level; /* Maintenance domain level. */ 16312 _bcm_oam_ep_list_t *cur; /* Current head node pointer. */ 16313 int ep_id = -1; /* Endpoint ID. */ 16314 uint8 match_found = 0; /* Matching endpoint found. */ 16315 int rv; /* Operation return status. */ 16316 bcm_oam_endpoint_info_t *ep_info = NULL; /* Endpoint information. */ 16317 _bcm_oam_hash_data_t *h_data_p = NULL; /* Endpoint hash data pointer. */ 16318 _bcm_oam_hash_data_t sh_data; /* Endpoint hash data pointer. */ 16319 uint32 ccm_period = 0; 16320 bcm_port_t pp_port; 16321 egr_port_entry_t egr_port_entry; 16322 uint8 mdl_mip = 0; 16323 int trunk_index = -1; 16324 int tpid_index = 0; 16325 16326 LOG_DEBUG(BSL_LS_BCM_OAM, 16327 (BSL_META_U(unit, 16328 "OAM(unit %d) Info: _bcm_sb2_oam_lmep_tx_config_recover.\n"), 16329 unit)); 16330 16331 /* 16332 * Get OAM control structure. 16333 * Note: Lock taken by calling routine. 16334 */ 16335 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 16336 16337 rv = _bcm_sb2_oam_endpoint_alloc(&ep_info); 16338 if (BCM_FAILURE(rv)) { 16339 return (rv); 16340 } 16341 16342 /* 16343 * At this point, Remote MEP and Local MEP Rx config has been 16344 * recovered. Now, recover the Tx config for Local MEPs. 16345 */ 16346 for (index = 0; index < oc->lmep_count; index++) { 16347 16348 /* Get the LMEP table entry. */ 16349 rv = READ_LMEPm(unit, MEM_BLOCK_ANY, index, &lmep_entry); 16350 if (BCM_FAILURE(rv)) { 16351 LOG_ERROR(BSL_LS_BCM_OAM, 16352 (BSL_META_U(unit, 16353 "OAM(unit %d) Error: LMEP table read (index=%d) failed " 16354 "- %s.\n"), unit, index, bcm_errmsg(rv))); 16355 goto cleanup; 16356 } 16357 16358 /* Get the LMEP_1 table entry. */ 16359 rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, index, &lmep_1_entry); 16360 if (BCM_FAILURE(rv)) { 16361 LOG_ERROR(BSL_LS_BCM_OAM, 16362 (BSL_META_U(unit, 16363 "OAM(unit %d) Error: LMEP_1 table read (index=%d) failed " 16364 "- %s.\n"), unit, index, bcm_errmsg(rv))); 16365 goto cleanup; 16366 } 16367 ccm_period = _bcm_sb2_oam_ccm_hw_encode_to_msecs 16368 ((int) soc_LMEPm_field32_get(unit, &lmep_entry, 16369 CCM_INTERVALf)); 16370 if (ccm_period == BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) { 16371 continue; 16372 } 16373 grp_idx = soc_LMEPm_field32_get(unit, &lmep_entry, MAID_INDEXf); 16374 16375 rv = READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, grp_idx, &maid_red_ent); 16376 if (BCM_FAILURE(rv)) { 16377 LOG_ERROR(BSL_LS_BCM_OAM, 16378 (BSL_META_U(unit, 16379 "OAM(unit %d) Error: MAID_REDU read (GID=%d) failed " 16380 "- %s.\n"), unit, grp_idx, bcm_errmsg(rv))); 16381 goto cleanup; 16382 } 16383 16384 if (soc_MAID_REDUCTIONm_field32_get(unit, &maid_red_ent, VALIDf)) { 16385 16386 /* Get pointer to group memory. */ 16387 g_info_p = &oc->group_info[grp_idx]; 16388 if (0 == g_info_p->in_use) { 16389 rv = BCM_E_INTERNAL; 16390 goto cleanup; 16391 } 16392 16393 vlan = soc_LMEPm_field32_get(unit, &lmep_entry, VLAN_IDf); 16394 inner_vlan = soc_LMEPm_field32_get(unit, &lmep_entry, CVLAN_TAGf); 16395 /* Only extract the VLAN ID portion of the tag. */ 16396 inner_vlan = inner_vlan & 0xfff; 16397 rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, index, &lmep_1_entry); 16398 if (BCM_FAILURE(rv)) { 16399 LOG_ERROR(BSL_LS_BCM_OAM, 16400 (BSL_META_U(unit, 16401 "OAM(unit %d) Error: LMEP_1 table read (index=%d) " 16402 "failed " "- %s.\n"), unit, index, bcm_errmsg(rv))); 16403 goto cleanup; 16404 } 16405 16406 glp = soc_LMEP_1m_field32_get(unit, &lmep_1_entry, PP_PORTf); 16407 rv = _bcm_kt2_pp_port_to_modport_get(unit, glp, 16408 &modid, &port_id); 16409 if (BCM_FAILURE(rv)) { 16410 goto cleanup; 16411 } 16412 16413 level = soc_LMEP_1m_field32_get(unit, &lmep_1_entry, MDLf); 16414 16415 trunk_id = BCM_TRUNK_INVALID; 16416 if (vlan != 0 || inner_vlan != 0) { 16417 rv = bcm_esw_trunk_find(unit, modid, port_id, &trunk_id); 16418 if (BCM_FAILURE(rv) 16419 && (BCM_E_NOT_FOUND != rv)) { 16420 goto cleanup; 16421 } 16422 } 16423 16424 _bcm_gport_dest_t_init(&gport_dest); 16425 16426 if (BCM_TRUNK_INVALID != trunk_id) { 16427 gport_dest.tgid = trunk_id; 16428 gport_dest.gport_type = _SHR_GPORT_TYPE_TRUNK; 16429 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport); 16430 16431 rv = _bcm_esw_oam_lmep_tx_trunk_config_recover(unit, 16432 trunk_id, 16433 port_id, 16434 &trunk_index); 16435 16436 if(BCM_FAILURE(rv)) { 16437 goto cleanup; 16438 } 16439 16440 } else { 16441 gport_dest.gport_type = _SHR_GPORT_TYPE_MODPORT; 16442 gport_dest.modid = modid; 16443 gport_dest.port = port_id; 16444 16445 BCM_IF_ERROR_RETURN(_bcm_kt2_modport_to_pp_port_get(unit, gport_dest.modid, 16446 gport_dest.port, &pp_port)); 16447 /* Check if the pp_port corresponding to mod port is in 16448 * subport port range. 16449 */ 16450 rv = BCM_E_NONE; 16451 if (SOC_PP_PORT_VALID(unit, pp_port)) { 16452 _BCM_KT2_SUBPORT_PORT_ID_SET(gport, pp_port); 16453 /* Get gport for subport port case */ 16454 if (BCM_PBMP_MEMBER(SOC_INFO(unit).linkphy_pp_port_pbm, pp_port)) { 16455 _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport, _BCM_KT2_SUBPORT_TYPE_LINKPHY); 16456 } else if (BCM_PBMP_MEMBER(SOC_INFO(unit).subtag_pp_port_pbm, pp_port)) { 16457 _BCM_KT2_SUBPORT_PORT_TYPE_SET(gport, _BCM_KT2_SUBPORT_TYPE_SUBTAG); 16458 } else { 16459 rv = BCM_E_PORT; 16460 } 16461 } else { 16462 /* Go through original gport construction */ 16463 rv = _bcm_esw_gport_construct(unit, &gport_dest, &gport); 16464 } 16465 } 16466 if (BCM_FAILURE(rv)) { 16467 LOG_ERROR(BSL_LS_BCM_OAM, 16468 (BSL_META_U(unit, 16469 "OAM(unit %d) Error: Gport construct " 16470 "failed - %s.\n"), 16471 unit, bcm_errmsg(rv))); 16472 goto cleanup; 16473 } 16474 /* Get the endpoint list head pointer. */ 16475 cur = *(g_info_p->ep_list); 16476 if (NULL != cur) { 16477 while (NULL != cur) { 16478 h_data_p = cur->ep_data_p; 16479 if (NULL == h_data_p) { 16480 LOG_ERROR(BSL_LS_BCM_OAM, 16481 (BSL_META_U(unit, 16482 "OAM(unit %d) Error: Group (GID=%d) NULL" 16483 " endpoint list.\n"), unit, grp_idx)); 16484 rv = BCM_E_INTERNAL; 16485 goto cleanup; 16486 } 16487 16488 16489 if (vlan == h_data_p->vlan && 16490 inner_vlan == h_data_p->inner_vlan 16491 && gport == h_data_p->gport 16492 && level == h_data_p->level 16493 && 1 == h_data_p->local_rx_enabled) { 16494 match_found = 1; 16495 break; 16496 } 16497 cur = cur->next; 16498 } 16499 } 16500 16501 if (1 == match_found) { 16502 16503 bcm_oam_endpoint_info_t_init(ep_info); 16504 16505 /* Set up endpoint information for key construction. */ 16506 ep_info->group = h_data_p->group_index; 16507 ep_info->name = h_data_p->name; 16508 ep_info->gport = h_data_p->gport; 16509 ep_info->level = h_data_p->level; 16510 ep_info->vlan = h_data_p->vlan; 16511 ep_info->inner_vlan = h_data_p->inner_vlan; 16512 ep_info->flags = h_data_p->flags; 16513 if (!(MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p))) { 16514 ep_info->mpls_label = h_data_p->label; 16515 } 16516 ep_info->type = h_data_p->type; 16517 16518 if ((recovered_ver < BCM_WB_VERSION_1_9) 16519 || (!ETH_TYPE(h_data_p->type))) { 16520 /* 16521 * Calculate hash key for hash table insert 16522 * operation. 16523 */ 16524 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, ep_info, 16525 &hash_key); 16526 16527 16528 /* 16529 * Delete insert done by Local Rx endpoint recovery code. 16530 * Endpoint name has been recovered and will result 16531 * in a different hash index. 16532 */ 16533 rv = shr_htb_find(oc->ma_mep_htbl, hash_key, 16534 (shr_htb_data_t *)&sh_data, 1); 16535 if (BCM_E_NOT_FOUND == rv) { 16536 goto cleanup; 16537 } 16538 } 16539 16540 } else { 16541 16542 if (recovered_ver >= BCM_WB_VERSION_1_1) { 16543 16544 sal_memcpy(&ep_id, 16545 *(scache) + _BCM_SB2_OAM_TX_MEP_SCACHE_LOCATION(index), 16546 sizeof(bcm_oam_endpoint_t)); 16547 16548 rv = shr_idxres_list_reserve(oc->mep_pool, ep_id, ep_id); 16549 if (BCM_FAILURE(rv)) { 16550 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 16551 LOG_ERROR(BSL_LS_BCM_OAM, 16552 (BSL_META_U(unit, 16553 "OAM Error: (EP_ID=%d) Index reserve " 16554 " failed - %s.\n"), ep_id, bcm_errmsg(rv))); 16555 goto cleanup; 16556 } 16557 } else { 16558 /* Allocate the next available endpoint index. */ 16559 rv = shr_idxres_list_alloc(oc->mep_pool, 16560 (shr_idxres_element_t *)&ep_id); 16561 if (BCM_FAILURE(rv)) { 16562 LOG_ERROR(BSL_LS_BCM_OAM, 16563 (BSL_META_U(unit, 16564 "OAM(unit %d) Error: Endpoint alloc (EP=%d)" 16565 " - %s.\n"), unit, ep_id, bcm_errmsg(rv))); 16566 goto cleanup; 16567 } 16568 } 16569 16570 h_data_p = &oc->oam_hash_data[ep_id]; 16571 if (1 == h_data_p->in_use) { 16572 rv = BCM_E_INTERNAL; 16573 goto cleanup; 16574 } 16575 16576 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 16577 16578 _BCM_OAM_HASH_DATA_HW_IDX_INIT(h_data_p); 16579 16580 rv = _bcm_sb2_oam_group_ep_list_add(unit, grp_idx, ep_id); 16581 if (BCM_FAILURE(rv)) { 16582 LOG_ERROR(BSL_LS_BCM_OAM, 16583 (BSL_META_U(unit, 16584 "OAM(unit %d) Error: Adding (EP=%d)" 16585 " to (GID=%d) failed - %s.\n"), 16586 unit, ep_id, grp_idx, bcm_errmsg(rv))); 16587 goto cleanup; 16588 } 16589 16590 h_data_p->ep_id = ep_id; 16591 h_data_p->group_index = grp_idx; 16592 h_data_p->local_rx_enabled = 0; 16593 h_data_p->vlan = vlan; 16594 h_data_p->inner_vlan = inner_vlan; 16595 h_data_p->gport = gport; 16596 h_data_p->level = level; 16597 if ((h_data_p->vlan == 0) && (h_data_p->inner_vlan == 0)) { 16598 h_data_p->oam_domain = _BCM_OAM_DOMAIN_PORT; 16599 } 16600 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 16601 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 16602 h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX; 16603 h_data_p->profile_index = _BCM_OAM_INVALID_INDEX; 16604 h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX; 16605 h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 16606 h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 16607 h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 16608 h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 16609 h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 16610 h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 16611 h_data_p->trunk_id = BCM_TRUNK_INVALID; 16612 } 16613 if((-1) != trunk_index) { 16614 h_data_p->trunk_index = trunk_index; 16615 } 16616 16617 h_data_p->src_pp_port = glp; 16618 h_data_p->dst_pp_port = glp; 16619 h_data_p->is_remote = 0; 16620 h_data_p->in_use = 1; 16621 h_data_p->local_tx_enabled = 1; 16622 h_data_p->local_tx_index = index; 16623 h_data_p->name 16624 = soc_LMEPm_field32_get(unit, &lmep_entry, MEPIDf); 16625 h_data_p->period 16626 = _bcm_sb2_oam_ccm_hw_encode_to_msecs 16627 ((int) soc_LMEPm_field32_get(unit, &lmep_entry, 16628 CCM_INTERVALf)); 16629 16630 if (BCM_PBMP_MEMBER(SOC_INFO(unit).general_pp_port_pbm, glp)) { 16631 h_data_p->flags2 |= BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW; 16632 } 16633 if (h_data_p->oam_domain != _BCM_OAM_DOMAIN_PORT) { 16634 rv = _bcm_sb2_oam_port_table_key_update(unit, PORT_TABm, h_data_p); 16635 if (BCM_FAILURE(rv)) { 16636 LOG_ERROR(BSL_LS_BCM_OAM, 16637 (BSL_META_U(unit, 16638 "OAM(unit %d) Error: Unable to increment key ref count " 16639 " - %s.\n"), unit, bcm_errmsg(rv))); 16640 goto cleanup; 16641 } 16642 rv = _bcm_sb2_oam_port_table_key_update(unit, EGR_PORTm, h_data_p); 16643 if (BCM_FAILURE(rv)) { 16644 LOG_ERROR(BSL_LS_BCM_OAM, 16645 (BSL_META_U(unit, 16646 "OAM(unit %d) Error: Unable to increment key ref count " 16647 " - %s.\n"), unit, bcm_errmsg(rv))); 16648 goto cleanup; 16649 } 16650 } else { 16651 BCM_IF_ERROR_RETURN 16652 (soc_mem_read(unit, EGR_PORTm, MEM_BLOCK_ANY, 16653 h_data_p->dst_pp_port, &egr_port_entry)); 16654 mdl_mip = soc_EGR_PORTm_field32_get(unit, &egr_port_entry, 16655 MDL_BITMAP_PASSIVEf); 16656 if (!(mdl_mip & (1 << h_data_p->level))) { 16657 /* Set the MIP flag */ 16658 h_data_p->flags |= BCM_OAM_ENDPOINT_INTERMEDIATE; 16659 } 16660 } 16661 16662 /* For ethernet CCM TX endpoints, fetch TPIDs from HW. 16663 */ 16664 if (h_data_p->vlan != 0) { 16665 tpid_index = soc_LMEPm_field32_get(unit, &lmep_entry, 16666 SVLAN_TPID_INDEXf); 16667 rv = _bcm_sb2_oam_tpid_get(unit, BCM_OAM_TPID_TYPE_OUTER, 16668 tpid_index, &(h_data_p->outer_tpid)); 16669 if (BCM_FAILURE(rv)) { 16670 LOG_ERROR(BSL_LS_BCM_OAM, 16671 (BSL_META_U(unit, 16672 "OAM(unit %d) Error: Outer TPID fetch failed" 16673 " EP=%d %s.\n"), unit, ep_id, 16674 bcm_errmsg(rv))); 16675 goto cleanup; 16676 } 16677 h_data_p->outer_tpid_profile_index = tpid_index; 16678 SB2_OAM_OUTER_TPID_REF_COUNT(unit, tpid_index)++; 16679 } 16680 16681 if (h_data_p->inner_vlan != 0) { 16682 rv = _bcm_sb2_oam_tpid_get(unit, BCM_OAM_TPID_TYPE_INNER, 16683 0, &(h_data_p->inner_tpid)); 16684 if (BCM_FAILURE(rv)) { 16685 LOG_ERROR(BSL_LS_BCM_OAM, 16686 (BSL_META_U(unit, 16687 "OAM(unit %d) Error: Inner TPID fetch failed" 16688 " EP=%d %s.\n"), unit, ep_id, 16689 bcm_errmsg(rv))); 16690 goto cleanup; 16691 } 16692 h_data_p->inner_tpid_profile_index = 0; 16693 SB2_OAM_INNER_TPID_REF_COUNT(unit, 0)++; 16694 } 16695 16696 if ((BCM_GPORT_IS_SUBPORT_PORT(h_data_p->gport)) && 16697 (_BCM_KT2_GPORT_IS_SUBTAG_SUBPORT_PORT(unit, h_data_p->gport))) { 16698 tpid_index = soc_LMEPm_field32_get(unit, &lmep_entry, 16699 SUBPORT_TAG_TPID_INDEXf); 16700 rv = _bcm_sb2_oam_tpid_get(unit, BCM_OAM_TPID_TYPE_SUBPORT, 16701 tpid_index, &(h_data_p->subport_tpid)); 16702 if (BCM_FAILURE(rv)) { 16703 LOG_ERROR(BSL_LS_BCM_OAM, 16704 (BSL_META_U(unit, 16705 "OAM(unit %d) Error: Subport TPID fetch failed" 16706 " EP=%d %s.\n"), unit, ep_id, 16707 bcm_errmsg(rv))); 16708 goto cleanup; 16709 } 16710 h_data_p->subport_tpid_profile_index = tpid_index; 16711 SB2_OAM_SUBPORT_TPID_REF_COUNT(unit, tpid_index)++; 16712 } 16713 16714 rv = shr_idxres_list_reserve(oc->lmep_pool, 16715 h_data_p->local_tx_index, 16716 h_data_p->local_tx_index); 16717 if (BCM_FAILURE(rv)) { 16718 LOG_ERROR(BSL_LS_BCM_OAM, 16719 (BSL_META_U(unit, 16720 "OAM(unit %d) Error: Tx index=%d reserve failed" 16721 " - %s.\n"), unit, index, bcm_errmsg(rv))); 16722 16723 _bcm_sb2_oam_group_ep_list_remove(unit, 16724 h_data_p->group_index, 16725 h_data_p->ep_id); 16726 16727 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 16728 goto cleanup; 16729 } 16730 16731 bcm_oam_endpoint_info_t_init(ep_info); 16732 16733 /* Set up endpoint information for key construction. */ 16734 ep_info->group = h_data_p->group_index; 16735 ep_info->name = h_data_p->name; 16736 ep_info->gport = h_data_p->gport; 16737 ep_info->level = h_data_p->level; 16738 ep_info->vlan = h_data_p->vlan; 16739 ep_info->inner_vlan = h_data_p->inner_vlan; 16740 ep_info->flags = h_data_p->flags; 16741 if (!(MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p))) { 16742 ep_info->mpls_label = h_data_p->label; 16743 } 16744 ep_info->type = h_data_p->type; 16745 16746 if ((recovered_ver < BCM_WB_VERSION_1_9) 16747 || (!ETH_TYPE(h_data_p->type))) { 16748 /* 16749 * Calculate hash key for hash table insert 16750 * operation. 16751 */ 16752 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, ep_info, &hash_key); 16753 16754 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 16755 if (BCM_FAILURE(rv)) { 16756 LOG_ERROR(BSL_LS_BCM_OAM, 16757 (BSL_META_U(unit, 16758 "OAM(unit %d) Error: Hash table insert" 16759 " (EP=%d) failed - %s.\n"), unit, 16760 h_data_p->ep_id, bcm_errmsg(rv))); 16761 16762 _bcm_sb2_oam_group_ep_list_remove(unit, 16763 h_data_p->group_index, 16764 h_data_p->ep_id); 16765 16766 goto cleanup; 16767 } else { 16768 LOG_DEBUG(BSL_LS_BCM_OAM, 16769 (BSL_META_U(unit, 16770 "OAM(unit %d) Info: Hash Tbl (EP=%d)" 16771 " inserted - %s.\n"), unit, h_data_p->ep_id, 16772 bcm_errmsg(rv))); 16773 } 16774 } 16775 16776 } 16777 16778 match_found = 0; 16779 h_data_p = NULL; 16780 } 16781 16782 LOG_DEBUG(BSL_LS_BCM_OAM, 16783 (BSL_META_U(unit, 16784 "OAM(unit %d) Info: _bcm_sb2_oam_lmep_tx_config_recover" 16785 " - done.\n"), unit)); 16786 sal_free(ep_info); 16787 return (rv); 16788 16789 cleanup: 16790 16791 if (NULL != ep_info) { 16792 sal_free(ep_info); 16793 } 16794 16795 if (0 == match_found && NULL != h_data_p) { 16796 /* Return endpoint index to MEP pool. */ 16797 if (BCM_E_EXISTS 16798 == shr_idxres_list_elem_state(oc->mep_pool, ep_id)) { 16799 shr_idxres_list_free(oc->mep_pool, ep_id); 16800 } 16801 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 16802 } 16803 16804 if (BCM_E_EXISTS 16805 == shr_idxres_list_elem_state(oc->lmep_pool, index)) { 16806 shr_idxres_list_free(oc->lmep_pool, index); 16807 } 16808 16809 LOG_DEBUG(BSL_LS_BCM_OAM, 16810 (BSL_META_U(unit, 16811 "OAM(unit %d) Info: _bcm_sb2_oam_lmep_tx_config_recover" 16812 " - error_done.\n"), unit)); 16813 return (rv); 16814 } 16815 16816 #if defined(INCLUDE_BHH) 16817 /* 16818 * Function: 16819 * _bcm_sb2_oam_bhh_endpoint_type_recover 16820 * Purpose: 16821 * Recover BHH endpoint type from EGR_MP_GROUP table. 16822 * Parameters: 16823 * unit - Device unit number. 16824 * Returns: 16825 * BCM_E_XXX 16826 */ 16827 STATIC int 16828 _bcm_sb2_oam_bhh_endpoint_type_recover(int unit) 16829 { 16830 uint32 entry_count; 16831 uint32 index; 16832 egr_mp_group_entry_t egr_mp_grp_entry; 16833 ma_index_entry_t ma_idx_entry; 16834 uint32 ma_base_idx = 0; 16835 _bcm_oam_control_t *oc; 16836 int bhh_endpoint; 16837 bcm_oam_endpoint_t ep_id, bhh_endpoint_index; 16838 _bcm_oam_hash_data_t *h_data_p = NULL; 16839 int key_type; 16840 int rv = BCM_E_NONE; 16841 16842 /* 16843 * Get OAM control structure. 16844 * Note: Lock taken by calling routine. 16845 */ 16846 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 16847 16848 16849 if (!soc_feature(unit, soc_feature_bhh) || (oc->ukernel_not_ready != 0)) { 16850 return BCM_E_NONE; 16851 } 16852 16853 entry_count = soc_mem_index_count(unit, EGR_MP_GROUPm); 16854 for (index = 0; index < entry_count; index++) { 16855 bhh_endpoint = 0; 16856 rv = READ_EGR_MP_GROUPm(unit, MEM_BLOCK_ANY, index, &egr_mp_grp_entry); 16857 if (BCM_FAILURE(rv)) { 16858 return (rv); 16859 } 16860 if (soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_grp_entry, VALIDf)) { 16861 ma_base_idx = soc_EGR_MP_GROUPm_field32_get(unit, 16862 &egr_mp_grp_entry, 16863 MA_BASE_PTRf); 16864 16865 if (SHR_BITGET(oc->bhh_ma_index_in_use, ma_base_idx)) { 16866 bhh_endpoint = 1; 16867 } 16868 } 16869 if (1 == bhh_endpoint) { 16870 /* Read the MA_INDEX table (EGR_MA_INDEX is not programmed 16871 * for BHH endpoints) 16872 */ 16873 rv = READ_MA_INDEXm (unit, MEM_BLOCK_ANY, 16874 ma_base_idx, 16875 &ma_idx_entry); 16876 if (BCM_FAILURE(rv)) { 16877 LOG_ERROR(BSL_LS_BCM_OAM, 16878 (BSL_META_U(unit, 16879 "BHH(unit %d) Error: MA_INDEX (index:%d) read failed -" 16880 " %s.\n"), unit, ma_base_idx, 16881 bcm_errmsg(rv))); 16882 return rv; 16883 } 16884 16885 /*Fetch endpoint id from MA_INDEX_ENTRY and reserve in bhh_pool*/ 16886 bhh_endpoint_index = soc_MA_INDEXm_field32_get(unit, &ma_idx_entry, MA_PTRf); 16887 ep_id = BCM_OAM_BHH_GET_SDK_EP(bhh_endpoint_index); 16888 16889 h_data_p = &oc->oam_hash_data[ep_id]; 16890 if (1 == h_data_p->in_use) { 16891 return (BCM_E_INTERNAL); 16892 } 16893 rv = shr_idxres_list_reserve(oc->bhh_pool, bhh_endpoint_index, 16894 bhh_endpoint_index); 16895 if (BCM_FAILURE(rv)) { 16896 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 16897 LOG_ERROR(BSL_LS_BCM_OAM, 16898 (BSL_META_U(unit, 16899 "BHH(unit %d) Error: Endpoint reserve (EP=%d) - %s.\n"), 16900 unit, bhh_endpoint_index, bcm_errmsg(rv))); 16901 return rv; 16902 } 16903 16904 _BCM_OAM_HASH_DATA_CLEAR(h_data_p); 16905 h_data_p->local_tx_index = _BCM_OAM_INVALID_INDEX; 16906 h_data_p->local_rx_index = _BCM_OAM_INVALID_INDEX; 16907 h_data_p->remote_index = _BCM_OAM_INVALID_INDEX; 16908 h_data_p->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 16909 h_data_p->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 16910 h_data_p->rx_ctr = _BCM_OAM_INVALID_INDEX; 16911 h_data_p->tx_ctr = _BCM_OAM_INVALID_INDEX; 16912 h_data_p->profile_index = _BCM_OAM_INVALID_INDEX; 16913 h_data_p->pri_map_index = _BCM_OAM_INVALID_INDEX; 16914 h_data_p->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 16915 h_data_p->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 16916 h_data_p->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 16917 h_data_p->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 16918 h_data_p->ma_base_index = _BCM_OAM_INVALID_INDEX; 16919 h_data_p->trunk_id = BCM_TRUNK_INVALID; 16920 h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX; 16921 16922 h_data_p->ep_id = ep_id; 16923 h_data_p->bhh_endpoint_index = ep_id; 16924 16925 key_type = soc_EGR_MP_GROUPm_field32_get(unit, 16926 &egr_mp_grp_entry, 16927 KEY_TYPEf); 16928 16929 switch (key_type) { 16930 case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION: 16931 h_data_p->type = bcmOAMEndpointTypeBhhSection; 16932 h_data_p->sglp = soc_EGR_MP_GROUPm_field32_get(unit, 16933 &egr_mp_grp_entry, 16934 GLPf); 16935 break; 16936 16937 case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_CVLAN: 16938 h_data_p->type = bcmOAMEndpointTypeBhhSectionInnervlan; 16939 h_data_p->sglp = soc_EGR_MP_GROUPm_field32_get(unit, 16940 &egr_mp_grp_entry, 16941 GLPf); 16942 h_data_p->inner_vlan = soc_EGR_MP_GROUPm_field32_get(unit, 16943 &egr_mp_grp_entry, 16944 CVIDf); 16945 break; 16946 16947 case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_SVLAN: 16948 h_data_p->type = bcmOAMEndpointTypeBhhSectionOuterVlan; 16949 h_data_p->sglp = soc_EGR_MP_GROUPm_field32_get(unit, 16950 &egr_mp_grp_entry, 16951 GLPf); 16952 h_data_p->vlan = soc_EGR_MP_GROUPm_field32_get(unit, 16953 &egr_mp_grp_entry, 16954 SVIDf); 16955 break; 16956 16957 case _BCM_SB2_OAM_DOMAIN_MPLS_SECTION_S_PLUS_CVLAN: 16958 h_data_p->type = bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan; 16959 h_data_p->sglp = soc_EGR_MP_GROUPm_field32_get(unit, 16960 &egr_mp_grp_entry, 16961 GLPf); 16962 h_data_p->vlan = soc_EGR_MP_GROUPm_field32_get(unit, 16963 &egr_mp_grp_entry, 16964 SVIDf); 16965 h_data_p->inner_vlan = soc_EGR_MP_GROUPm_field32_get(unit, 16966 &egr_mp_grp_entry, 16967 CVIDf); 16968 break; 16969 16970 case _BCM_SB2_OAM_DOMAIN_EGR_MPLS_LMDM_LSP: 16971 h_data_p->type = bcmOAMEndpointTypeBHHMPLS; 16972 h_data_p->label = soc_EGR_MP_GROUPm_field32_get(unit, 16973 &egr_mp_grp_entry, 16974 MPLS_LABELf); 16975 h_data_p->sglp = soc_EGR_MP_GROUPm_field32_get(unit, 16976 &egr_mp_grp_entry, 16977 GLPf); 16978 break; 16979 case _BCM_SB2_OAM_DOMAIN_MPLS_LMDM_PW: 16980 h_data_p->type = bcmOAMEndpointTypeBHHMPLSVccv; 16981 h_data_p->vp = soc_EGR_MP_GROUPm_field32_get(unit, 16982 &egr_mp_grp_entry, 16983 VPf); 16984 break; 16985 } 16986 h_data_p->in_use = 1; 16987 } 16988 } 16989 return BCM_E_NONE; 16990 } 16991 #endif 16992 16993 /* 16994 * Function: 16995 * _bcm_sb2_oam_wb_endpoints_recover 16996 * Purpose: 16997 * Recover OAM local endpoint Rx configuration. 16998 * Parameters: 16999 * unit - Device unit number. 17000 * stable_size - OAM module Level2 memory size. 17001 * oam_scache - Pointer to secondary storage buffer pointer. 17002 * Returns: 17003 * BCM_E_XXX 17004 */ 17005 STATIC int 17006 _bcm_sb2_oam_wb_endpoints_recover(int unit, 17007 int stable_size, 17008 uint8 **oam_scache, uint16 recovered_ver) 17009 { 17010 int index; /* Hardware index. */ 17011 uint32 entry_count; /* Max entries in MP_GROUP/ 17012 EGR_MP_GROUP table. */ 17013 l3_entry_1_entry_t l3_entry; /* RMEP view table entry. */ 17014 _bcm_oam_control_t *oc; /* Pointer to control structure. */ 17015 int rv; /* Operation return status. */ 17016 mp_group_entry_t mp_group_entry; /* MP group tbl entry buffer */ 17017 egr_mp_group_entry_t egr_mp_grp_entry;/* Egr MP group tbl entry buffer */ 17018 port_tab_entry_t port_entry; /* Port table entry buffer */ 17019 17020 /* 17021 * Get OAM control structure. 17022 * Note: Lock taken by calling routine. 17023 */ 17024 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 17025 17026 /* Get number of L3 table entries. */ 17027 entry_count = soc_mem_index_count(unit, L3_ENTRY_IPV4_UNICASTm); 17028 17029 /* Now get valid OAM endpoint entries. */ 17030 for (index = 0; index < entry_count; index++) { 17031 17032 rv = READ_L3_ENTRY_IPV4_UNICASTm(unit, MEM_BLOCK_ANY, index, &l3_entry); 17033 if (BCM_FAILURE(rv)) { 17034 LOG_ERROR(BSL_LS_BCM_OAM, 17035 (BSL_META_U(unit, 17036 "OAM(unit %d) Error: L3_ENTRY (index=%d) read" 17037 " failed - %s.\n"), unit, index, bcm_errmsg(rv))); 17038 return (rv); 17039 } 17040 17041 if (soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, VALIDf)) { 17042 17043 switch (soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, 17044 KEY_TYPEf)) { 17045 17046 case SOC_MEM_KEY_L3_ENTRY_RMEP: 17047 rv = _bcm_sb2_oam_rmep_recover(unit, index, 17048 &l3_entry, oam_scache, recovered_ver); 17049 if (BCM_FAILURE(rv)) { 17050 LOG_ERROR(BSL_LS_BCM_OAM, 17051 (BSL_META_U(unit, 17052 "OAM(unit %d) Error: Remote endpoint" 17053 " (index=%d) reconstruct failed - %s.\n"), 17054 unit, index, bcm_errmsg(rv))); 17055 return (rv); 17056 } 17057 break; 17058 17059 default: 17060 /* Not an OAM entry. */ 17061 continue; 17062 } 17063 } 17064 } 17065 17066 #if defined(INCLUDE_BHH) 17067 /* Recover BHH endpoint types from EGR)_MP_GROUP table */ 17068 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_bhh_endpoint_type_recover(unit)); 17069 #endif /* BHH */ 17070 17071 /* Recover all downMEP's */ 17072 entry_count = soc_mem_index_count(unit, MP_GROUPm); 17073 for (index = 0; index < entry_count; index++) { 17074 BCM_SB2_TCAM_ATOMICITY_DISABLE(unit); 17075 rv = READ_MP_GROUPm(unit, MEM_BLOCK_ANY, index, &mp_group_entry); 17076 BCM_SB2_TCAM_ATOMICITY_ENABLE(unit); 17077 if (BCM_FAILURE(rv)) { 17078 LOG_ERROR(BSL_LS_BCM_OAM, 17079 (BSL_META_U(unit, 17080 "OAM(unit %d) Error: MP_GROUP ENTRY (index=%d) read" 17081 " failed - %s.\n"), unit, index, bcm_errmsg(rv))); 17082 return (rv); 17083 } 17084 if (soc_MP_GROUPm_field32_get(unit, &mp_group_entry, VALIDf)) { 17085 rv = _bcm_sb2_oam_lmep_downmep_rx_config_recover(unit, 17086 index, 17087 &mp_group_entry, oam_scache, recovered_ver); 17088 if (BCM_FAILURE(rv)) { 17089 LOG_ERROR(BSL_LS_BCM_OAM, 17090 (BSL_META_U(unit, 17091 "OAM(unit %d) Error: Local endpoint DownMEP" 17092 " (index=%d) reconstruct failed - %s.\n"), 17093 unit, index, bcm_errmsg(rv))); 17094 return (rv); 17095 } 17096 } 17097 } 17098 17099 /* Recover all UpMEPs */ 17100 /* Get number of EGR_MP_GROUP table entries. */ 17101 entry_count = soc_mem_index_count(unit, EGR_MP_GROUPm); 17102 17103 /* Now get valid OAM endpoint entries. */ 17104 for (index = 0; index < entry_count; index++) { 17105 rv = READ_EGR_MP_GROUPm(unit, MEM_BLOCK_ANY, index, &egr_mp_grp_entry); 17106 if (BCM_FAILURE(rv)) { 17107 LOG_ERROR(BSL_LS_BCM_OAM, 17108 (BSL_META_U(unit, 17109 "OAM(unit %d) Error: EGR_MP_GROUP ENTRY (index=%d) read" 17110 " failed - %s.\n"), unit, index, bcm_errmsg(rv))); 17111 return (rv); 17112 } 17113 if (soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_grp_entry, VALIDf)) { 17114 rv = _bcm_sb2_oam_lmep_upmep_rx_config_recover(unit, index, 17115 &egr_mp_grp_entry, 17116 oam_scache, recovered_ver); 17117 if (BCM_FAILURE(rv)) { 17118 LOG_ERROR(BSL_LS_BCM_OAM, 17119 (BSL_META_U(unit, 17120 "OAM(unit %d) Error: Local endpoint UpMEP" 17121 " (index=%d) reconstruct failed - %s.\n"), 17122 unit, index, bcm_errmsg(rv))); 17123 return (rv); 17124 } 17125 } 17126 } 17127 17128 17129 /* recover endpoints from Port table */ 17130 /* Get number of PORT_TABLE table entries. */ 17131 entry_count = soc_mem_index_count(unit, PORT_TABm); 17132 /* Now get valid OAM endpoint entries. */ 17133 for (index = 0; index < entry_count; index++) { 17134 rv = READ_PORT_TABm(unit, MEM_BLOCK_ANY, index, &port_entry); 17135 if (BCM_FAILURE(rv)) { 17136 LOG_ERROR(BSL_LS_BCM_OAM, 17137 (BSL_META_U(unit, 17138 "OAM(unit %d) Error: Port table ENTRY (index=%d) read" 17139 " failed - %s.\n"), unit, index, bcm_errmsg(rv))); 17140 return (rv); 17141 } 17142 if (soc_PORT_TABm_field32_get(unit, &port_entry, OAM_ENABLEf)) { 17143 rv = _bcm_sb2_oam_port_lmep_rx_config_recover(unit, index, 17144 &port_entry, 17145 oam_scache, recovered_ver); 17146 if (BCM_FAILURE(rv)) { 17147 LOG_ERROR(BSL_LS_BCM_OAM, 17148 (BSL_META_U(unit, 17149 "OAM(unit %d) Error: Port based local endpoint " 17150 " (index=%d) reconstruct failed - %s.\n"), 17151 unit, index, bcm_errmsg(rv))); 17152 return (rv); 17153 } 17154 } 17155 } 17156 rv = _bcm_sb2_oam_lmep_tx_config_recover(unit, oam_scache, recovered_ver); 17157 if (BCM_FAILURE(rv)) { 17158 LOG_ERROR(BSL_LS_BCM_OAM, 17159 (BSL_META_U(unit, 17160 "OAM(unit %d) Error: Endpoint Tx config recovery" 17161 " failed - %s.\n"), unit, bcm_errmsg(rv))); 17162 return (rv); 17163 } 17164 17165 return (BCM_E_NONE); 17166 } 17167 17168 /* 17169 * Function: 17170 * bcm_sb2_oam_scache_alloc 17171 * Purpose: 17172 * Allocate scache memory for OAM module 17173 * Parameters: 17174 * unit - (IN) BCM device number 17175 * Returns: 17176 * BCM_E_UNIT - Invalid BCM unit number. 17177 * BCM_E_UNAVAIL - OAM not support on this device. 17178 * BCM_E_MEMORY - Allocation failure 17179 * CM_E_XXX - Error code from bcm_XX_oam_init() 17180 * BCM_E_NONE - Success 17181 */ 17182 STATIC int 17183 bcm_sb2_oam_scache_alloc(int unit) { 17184 _bcm_oam_control_t *oc; 17185 soc_scache_handle_t scache_handle; 17186 uint8 *oam_scache; 17187 int alloc_sz = 0; 17188 int trunk_idx_size; 17189 17190 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 17191 17192 alloc_sz = BCM_OAM_GROUP_NAME_LENGTH * (oc->group_count); 17193 17194 /* Number of oam groups */ 17195 alloc_sz += sizeof(int); 17196 17197 /* VFP group, IFP VP group, IFP GLP group */ 17198 alloc_sz += 3 * sizeof(bcm_field_group_t); 17199 17200 #if defined(INCLUDE_BHH) 17201 if(soc_feature(unit, soc_feature_bhh)) { 17202 if (oc->ukernel_not_ready == 0) { 17203 /*Allocate to store BHH endpoint ids at corresponding MA_INDEX*/ 17204 alloc_sz += SHR_BITALLOCSIZE(oc->ma_idx_count); 17205 alloc_sz += sizeof(short) * oc->bhh_endpoint_count; /*bhh_ep_grp_id*/ 17206 alloc_sz += sizeof(short) * oc->bhh_endpoint_count; /*bhh_ep_vpn*/ 17207 } 17208 } 17209 #endif 17210 /* Allocate memory to store logical endpoint Ids */ 17211 alloc_sz += (_BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE); 17212 alloc_sz += (_BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE); 17213 alloc_sz += (_BCM_SB2_OAM_EGR_LABEL_SCACHE_SIZE); 17214 17215 #if defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_BHH) 17216 if ((_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) || 17217 (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) || 17218 (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc))) { 17219 /* Allocate memory for PM profile */ 17220 alloc_sz += (_BCM_SB2_OAM_PM_PROFILE_SCACHE_SIZE); 17221 /* Endpoint id to pm id map */ 17222 alloc_sz += _bcm_sb2_oam_pmid_scache_size(unit); 17223 } 17224 #endif 17225 17226 /* Allocate memory to store LSP lookup key_type in EGR_MP_GROUP */ 17227 #if defined(INCLUDE_BHH) 17228 alloc_sz += sizeof(uint8); 17229 #endif /* INCLUDE_BHH */ 17230 #if defined(INCLUDE_MPLS_LM_DM) 17231 alloc_sz += sizeof(uint8); 17232 #endif /* INCLUDE_MPLS_LM_DM */ 17233 17234 #if defined(INCLUDE_BHH) 17235 if(soc_feature(unit, soc_feature_bhh)) { 17236 if (oc->ukernel_not_ready == 0) { 17237 /* vlan_pri and inner_vlan_pri */ 17238 alloc_sz += sizeof(uint8) * oc->bhh_endpoint_count * 2; 17239 } 17240 } 17241 #endif 17242 17243 /* Allocate memory to store oc->eth_oam_mp_group_vlan_key */ 17244 alloc_sz += sizeof(uint8); 17245 17246 /* Store trunk index for BHH and MPLS LM/DM endpoints */ 17247 trunk_idx_size = 0; 17248 #if defined(INCLUDE_BHH) 17249 if(soc_feature(unit, soc_feature_bhh)) { 17250 if (oc->ukernel_not_ready == 0) { 17251 trunk_idx_size = sizeof(uint8) * oc->ma_idx_count; 17252 } 17253 } 17254 #endif /* INCLUDE_BHH */ 17255 #if defined(INCLUDE_MPLS_LM_DM) 17256 if (oc->mpls_lm_dm_ukernel_ready) { 17257 if (trunk_idx_size == 0 ) { 17258 /* No BHH */ 17259 trunk_idx_size = sizeof(uint8) * oc->ma_idx_count; 17260 } 17261 } 17262 #endif /* INCLUDE_MPLS_LM_DM */ 17263 alloc_sz += trunk_idx_size; 17264 17265 /* FLAGS are stored for all ethernet OAM endpoints */ 17266 alloc_sz += (sizeof(uint32) * oc->ep_count); 17267 17268 #if defined(INCLUDE_BHH) 17269 /* Allocate memory to store oam_mpls_tp_ach_channel_type */ 17270 alloc_sz += sizeof(sb2_oam_mpls_tp_ach_channel_type); 17271 #endif 17272 17273 17274 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 17275 BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 1, 17276 alloc_sz, &oam_scache, BCM_WB_DEFAULT_VERSION, NULL)); 17277 return BCM_E_NONE; 17278 } 17279 17280 /* Given h_data_p, this function fills the endpoint_info required for 17281 * hash_key generation and inserts it at appropriate location. 17282 * 17283 * oc->lock is already assumed to be taken by caller */ 17284 int _bcm_sb2_oam_hash_tbl_insert_hash_data_entry(int unit, _bcm_oam_hash_data_t *h_data_p) 17285 { 17286 bcm_oam_endpoint_info_t ep_info; 17287 _bcm_oam_control_t *oc = NULL; /* Pointer to OAM control structure. */ 17288 _bcm_oam_hash_key_t hash_key; /* Hash key buffer for lookup. */ 17289 int rv = BCM_E_NONE; 17290 17291 17292 if (h_data_p == NULL) { 17293 return BCM_E_INTERNAL; 17294 } 17295 17296 /* Get OAM control structure. */ 17297 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 17298 17299 /* Initialize endpoint info structure. */ 17300 bcm_oam_endpoint_info_t_init(&ep_info); 17301 17302 /* Set up endpoint information for key construction. */ 17303 ep_info.group = h_data_p->group_index; 17304 ep_info.name = h_data_p->name; 17305 ep_info.gport = h_data_p->gport; 17306 ep_info.level = h_data_p->level; 17307 ep_info.vlan = h_data_p->vlan; 17308 ep_info.inner_vlan = h_data_p->inner_vlan; 17309 ep_info.flags = h_data_p->flags; 17310 if (!(MPLS_LM_DM_PW_ENDPOINT_TYPE(h_data_p))) { 17311 ep_info.mpls_label = h_data_p->label; 17312 } 17313 ep_info.type = h_data_p->type; 17314 17315 /* Construct hash key for lookup */ 17316 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, &ep_info, &hash_key); 17317 17318 /* Insert entry from hash table. */ 17319 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, h_data_p); 17320 if (BCM_FAILURE(rv)) { 17321 LOG_ERROR(BSL_LS_BCM_OAM, 17322 (BSL_META_U(unit, 17323 "OAM(unit %d) Error: Hash table insert failed " 17324 "EP=%d %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 17325 } else { 17326 LOG_DEBUG(BSL_LS_BCM_OAM, 17327 (BSL_META_U(unit, 17328 "OAM(unit %d) Info: Hash Tbl (EP=%d) inserted" 17329 " - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 17330 } 17331 17332 return rv; 17333 } 17334 17335 /* 17336 * Function: 17337 * _bcm_sb2_oam_reinit 17338 * Purpose: 17339 * Reconstruct OAM module software state. 17340 * Parameters: 17341 * unit - (IN) BCM device number 17342 * Retruns: 17343 * BCM_E_XXX 17344 */ 17345 STATIC int 17346 _bcm_sb2_oam_reinit(int unit) 17347 { 17348 uint32 group_count; /* Stored OAM group count. */ 17349 int stable_size; /* Secondary storage size. */ 17350 uint8 *oam_scache = NULL; /* Pointer to scache memory. */ 17351 soc_scache_handle_t scache_handle; /* Scache memory handler. */ 17352 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 17353 int rv; /* Operation return status. */ 17354 int realloc_size = 0; 17355 uint16 recovered_ver = 0; 17356 int trunk_idx_size = 0; 17357 #if defined(INCLUDE_BHH) || defined(INCLUDE_MPLS_LM_DM) 17358 uint8 trunk_index; 17359 #endif /* INCLUDE_BHH || INCLUDE_MPLS_LM_DM */ 17360 _bcm_oam_hash_data_t *h_data_p = NULL; 17361 uint8 *tmp_oam_scache = NULL; 17362 int idx = 0; 17363 17364 17365 LOG_DEBUG(BSL_LS_BCM_OAM, 17366 (BSL_META_U(unit, 17367 "OAM(unit %d) Info: OAM warm boot recovery.....\n"), 17368 unit)); 17369 17370 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 17371 17372 /* Get OAM control structure. */ 17373 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 17374 17375 _BCM_OAM_LOCK(oc); 17376 17377 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) { 17378 17379 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 17380 17381 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0, 17382 &oam_scache, BCM_WB_DEFAULT_VERSION, 17383 &recovered_ver); 17384 if (BCM_E_NOT_FOUND == rv) { 17385 /* Upgrading from SDK release that does not have warmboot state */ 17386 bcm_sb2_oam_scache_alloc(unit); 17387 _BCM_OAM_UNLOCK(oc); 17388 return BCM_E_NONE; 17389 } else if (BCM_FAILURE(rv)) { 17390 goto cleanup; 17391 } 17392 17393 if (recovered_ver < BCM_WB_VERSION_1_3 && MA_INDEX_ALLOC_SCHEME_SEPARATE_POOL) { 17394 LOG_WARN(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Warn:" 17395 " Warm upgrade from a older version which does not support " 17396 "flexible endpoint hw index allocation. Reverting to older " 17397 "scheme.\n"))); 17398 oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_COMBINED_POOL; 17399 /* Destroy the previous allocation and re-allocate based on this scheme */ 17400 rv = _bcm_sb2_oam_ma_idx_pool_destroy(oc); 17401 if (BCM_FAILURE(rv)) { 17402 goto cleanup; 17403 } 17404 rv = _bcm_sb2_oam_ma_idx_pool_create(oc); 17405 if (BCM_FAILURE(rv)) { 17406 goto cleanup; 17407 } 17408 } 17409 17410 /* Recover the FP groups */ 17411 sal_memcpy(&oc->vfp_group, oam_scache, sizeof(bcm_field_group_t)); 17412 oam_scache += sizeof(bcm_field_group_t); 17413 17414 sal_memcpy(&oc->fp_vp_group, oam_scache, sizeof(bcm_field_group_t)); 17415 oam_scache += sizeof(bcm_field_group_t); 17416 17417 sal_memcpy(&oc->fp_glp_group, oam_scache, sizeof(bcm_field_group_t)); 17418 oam_scache += sizeof(bcm_field_group_t); 17419 17420 /* Recover the OAM groups */ 17421 sal_memcpy(&group_count, oam_scache, sizeof(int)); 17422 oam_scache += sizeof(int); 17423 17424 } else { 17425 rv = BCM_E_NONE; 17426 goto cleanup; 17427 } 17428 17429 rv = _bcm_sb2_oam_wb_group_recover(unit, stable_size, &oam_scache); 17430 if (BCM_FAILURE(rv)) { 17431 LOG_ERROR(BSL_LS_BCM_OAM, 17432 (BSL_META_U(unit, 17433 "OAM(unit %d) Error: Group recovery failed - %s.\n"), 17434 unit, bcm_errmsg(rv))); 17435 goto cleanup; 17436 } 17437 17438 #if defined(INCLUDE_BHH) 17439 if(soc_feature(unit, soc_feature_bhh)) { 17440 if(0 == oc->ukernel_not_ready && 17441 NULL != oam_scache) { 17442 17443 /*Store MA_INDEX allocated to BHH*/ 17444 for (idx = 0; idx < _SHR_BITDCLSIZE (oc->ma_idx_count); idx++) { 17445 sal_memcpy( &oc->bhh_ma_index_in_use[idx], oam_scache, 17446 sizeof(SHR_BITDCL)); 17447 oam_scache += sizeof(SHR_BITDCL); 17448 } 17449 17450 /*Store BHH endpoint group ids */ 17451 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) { 17452 sal_memcpy(&oc->bhh_ep_grp_id[idx], oam_scache, sizeof(short)); 17453 oam_scache += sizeof(short); 17454 } 17455 17456 /*Store BHH endpoint VPN */ 17457 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) { 17458 sal_memcpy(&oc->bhh_ep_vpn[idx], oam_scache, sizeof(short)); 17459 oam_scache += sizeof(short); 17460 } 17461 } 17462 } 17463 #endif 17464 #if defined(INCLUDE_ETH_LM_DM) 17465 /* sessId to EpId cache */ 17466 if(eth_oam_id_map == NULL) { 17467 eth_oam_id_map = sal_alloc(oc->eth_lm_dm_sess_count * 17468 sizeof(bcm_oam_endpoint_t), "eth_oam_sess_id_map"); 17469 } 17470 #endif 17471 #if defined(INCLUDE_MPLS_LM_DM) 17472 if(mpls_oam_id_map == NULL) { 17473 mpls_oam_id_map = sal_alloc(oc->mpls_lm_dm_sess_count * 17474 sizeof(bcm_oam_endpoint_t), "eth_oam_sess_id_map"); 17475 } 17476 #endif 17477 rv = _bcm_sb2_oam_wb_endpoints_recover(unit, stable_size, &oam_scache, recovered_ver); 17478 if (BCM_FAILURE(rv)) { 17479 LOG_ERROR(BSL_LS_BCM_OAM, 17480 (BSL_META_U(unit, 17481 "OAM(unit %d) Error: Endpoint recovery failed - %s.\n"), 17482 unit, bcm_errmsg(rv))); 17483 goto cleanup; 17484 } 17485 17486 if (recovered_ver >= BCM_WB_VERSION_1_1) { 17487 oam_scache += (_BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE); 17488 oam_scache += (_BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE); 17489 } 17490 if (recovered_ver >= BCM_WB_VERSION_1_2) { 17491 oam_scache += (_BCM_SB2_OAM_EGR_LABEL_SCACHE_SIZE); 17492 } 17493 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM) 17494 /* PM recovery */ 17495 if (recovered_ver >= BCM_WB_VERSION_1_4) { 17496 if ((_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) || 17497 (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) || 17498 (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc))) { 17499 17500 int8 pm_id; 17501 _bcm_oam_hash_data_t *h_data_p = NULL; 17502 int itr; 17503 _bcm_oam_pm_profile_control_t *pmc = NULL; 17504 pmc = pm_profile_control[unit]; 17505 17506 if (!pmc) { 17507 _BCM_OAM_UNLOCK(oc); 17508 return BCM_E_INIT; 17509 } 17510 for(itr = 0; itr < _BCM_OAM_MAX_PM_PROFILES; itr++) { 17511 sal_memcpy(&(pmc->profile_info[itr]), oam_scache, 17512 sizeof(_bcm_oam_pm_profile_int_info_t)); 17513 oam_scache += sizeof(_bcm_oam_pm_profile_int_info_t); 17514 } 17515 #if defined(INCLUDE_ETH_LM_DM) 17516 for(itr = 0; itr < oc->eth_lm_dm_sess_count; itr++) { 17517 sal_memcpy(&pm_id, oam_scache, sizeof(pm_id)); 17518 oam_scache += sizeof(pm_id); 17519 if(pm_id >= 0) { 17520 h_data_p = &oc->oam_hash_data[eth_oam_id_map[itr]]; 17521 if(h_data_p->in_use) { 17522 h_data_p->pm_profile_attached = pm_id; 17523 } 17524 } 17525 } 17526 sal_free(eth_oam_id_map); 17527 eth_oam_id_map = NULL; 17528 #endif 17529 #if defined(INCLUDE_MPLS_LM_DM) 17530 for(itr = 0; itr < oc->mpls_lm_dm_sess_count; itr++) { 17531 sal_memcpy(&pm_id, oam_scache, sizeof(pm_id)); 17532 oam_scache += sizeof(pm_id); 17533 if(pm_id >= 0) { 17534 h_data_p = &oc->oam_hash_data[mpls_oam_id_map[itr]]; 17535 if(h_data_p->in_use) { 17536 h_data_p->pm_profile_attached = pm_id; 17537 } 17538 } 17539 } 17540 sal_free(mpls_oam_id_map); 17541 mpls_oam_id_map = NULL; 17542 #endif 17543 #if defined(INCLUDE_BHH) 17544 for(itr = 0; itr < oc->bhh_endpoint_count; itr++) { 17545 sal_memcpy(&pm_id, oam_scache, sizeof(pm_id)); 17546 oam_scache += sizeof(pm_id); 17547 if(pm_id >= 0) { 17548 h_data_p = &oc->oam_hash_data[BCM_OAM_BHH_GET_SDK_EP(itr)]; 17549 if(h_data_p->in_use) { 17550 h_data_p->pm_profile_attached = pm_id; 17551 } 17552 } 17553 } 17554 #endif 17555 } 17556 } 17557 #endif 17558 17559 if (recovered_ver >= BCM_WB_VERSION_1_5) { 17560 #if defined(INCLUDE_BHH) 17561 sal_memcpy(&bhh_lsp_egr_lookup_key, oam_scache, sizeof(uint8)); 17562 oam_scache += sizeof(uint8); 17563 #endif /* INCLUDE_BHH */ 17564 #if defined(INCLUDE_MPLS_LM_DM) 17565 /* Skip over not used currently */ 17566 oam_scache += sizeof(uint8); 17567 #endif /* INCLUDE_MPLS_LM_DM */ 17568 } else { 17569 #if defined(INCLUDE_BHH) 17570 /* Warm booting from an older SDK release which had onl 17571 * MEP_ID based lookup 17572 */ 17573 bhh_lsp_egr_lookup_key = _BCM_SB2_OAM_EGR_LSP_MEP_LOOKUP_KEY_MEP_ID; 17574 #endif /* INCLUDE_BHH */ 17575 } 17576 17577 if (recovered_ver >= BCM_WB_VERSION_1_6) { 17578 #if defined(INCLUDE_BHH) 17579 if(soc_feature(unit, soc_feature_bhh)) { 17580 if(0 == oc->ukernel_not_ready && 17581 NULL != oam_scache) { 17582 uint8 vlan_pri; 17583 uint8 inner_vlan_pri; 17584 /* Store BHH endpoint VLAN_PRI and INNER_VLAN_PRI */ 17585 17586 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) { 17587 h_data_p = &oc->oam_hash_data[BCM_OAM_BHH_GET_SDK_EP(idx)]; 17588 if(h_data_p->in_use) { 17589 sal_memcpy(&vlan_pri, oam_scache, sizeof(uint8)); 17590 h_data_p->vlan_pri = vlan_pri; 17591 oam_scache += sizeof(uint8); 17592 sal_memcpy(&inner_vlan_pri, oam_scache, sizeof(uint8)); 17593 h_data_p->inner_vlan_pri = inner_vlan_pri; 17594 oam_scache += sizeof(uint8); 17595 } else { 17596 oam_scache += sizeof(uint8) * 2; 17597 } 17598 } 17599 } 17600 } 17601 #endif 17602 } 17603 17604 if (recovered_ver >= BCM_WB_VERSION_1_7) { 17605 sal_memcpy(&oc->eth_oam_mp_group_vlan_key, oam_scache, sizeof(uint8)); 17606 oam_scache += sizeof(uint8); 17607 } else { 17608 oc->eth_oam_mp_group_vlan_key = 17609 _BCM_SB2_ETH_OAM_MP_GROUP_KEY_DOMAIN_INDEPENDANT; 17610 } 17611 17612 tmp_oam_scache = oam_scache; 17613 if (recovered_ver >= BCM_WB_VERSION_1_8) { 17614 #if defined(INCLUDE_BHH) 17615 if(soc_feature(unit, soc_feature_bhh)) { 17616 if (oc->ukernel_not_ready == 0) { 17617 for (idx = 0; idx < oc->bhh_endpoint_count; idx++) { 17618 h_data_p = &oc->oam_hash_data[BCM_OAM_BHH_GET_SDK_EP(idx)]; 17619 if (h_data_p->in_use) { 17620 sal_memcpy(&trunk_index, oam_scache, sizeof(uint8)); 17621 oam_scache += sizeof(uint8); 17622 h_data_p->trunk_index = trunk_index; 17623 } 17624 } 17625 trunk_idx_size = sizeof(uint8) * oc->ma_idx_count; 17626 } 17627 } 17628 #endif /* INCLUDE_BHH */ 17629 #if defined(INCLUDE_MPLS_LM_DM) 17630 if (oc->mpls_lm_dm_ukernel_ready) { 17631 for (idx = 0; idx < oc->ep_count; idx++) { 17632 h_data_p = &oc->oam_hash_data[idx]; 17633 if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) && (h_data_p->in_use)) { 17634 sal_memcpy(&trunk_index, oam_scache, sizeof(uint8)); 17635 oam_scache += sizeof(uint8); 17636 h_data_p->trunk_index = trunk_index; 17637 } 17638 } 17639 trunk_idx_size = sizeof(uint8) * oc->ma_idx_count; 17640 } 17641 #endif /* INCLUDE_MPLS_LM_DM */ 17642 17643 } 17644 17645 /* The above code doesnt move the scache pointer to the end of 17646 * its allocated section size. So we move it here. 17647 */ 17648 oam_scache = tmp_oam_scache + trunk_idx_size; 17649 17650 if (recovered_ver >= BCM_WB_VERSION_1_9) { 17651 for (idx = 0; idx < oc->ep_count; idx++) { 17652 h_data_p = &oc->oam_hash_data[idx]; 17653 if (ETH_TYPE(h_data_p->type) && (h_data_p->in_use)) { 17654 sal_memcpy(&(h_data_p->flags), oam_scache, sizeof(uint32)); 17655 rv = _bcm_sb2_oam_hash_tbl_insert_hash_data_entry(unit, h_data_p); 17656 if (BCM_FAILURE(rv)) { 17657 LOG_ERROR(BSL_LS_BCM_OAM, 17658 (BSL_META_U(unit, 17659 "OAM(unit %d) Error: Endpoint %d hash tbl insert failed - %s.\n"), 17660 unit, h_data_p->ep_id, bcm_errmsg(rv))); 17661 goto cleanup; 17662 } 17663 } 17664 oam_scache += sizeof(uint32); 17665 } 17666 } 17667 17668 #if defined(INCLUDE_BHH) 17669 if (recovered_ver >= BCM_WB_VERSION_1_10) { 17670 sal_memcpy(&sb2_oam_mpls_tp_ach_channel_type, oam_scache, 17671 sizeof(sb2_oam_mpls_tp_ach_channel_type)); 17672 oam_scache += sizeof(sb2_oam_mpls_tp_ach_channel_type); 17673 } 17674 #endif /* INCLUDE_BHH */ 17675 17676 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) { 17677 /* In BCM_WB_VERSION_1_1 onwards we allocate memory for storing EP indexes 17678 also, as such while upgrading from any version lower than 17679 BCM_WB_VERSION_1_1 we must add the differential. 17680 */ 17681 if (recovered_ver < BCM_WB_VERSION_1_1) { 17682 realloc_size += (_BCM_SB2_OAM_ENDPOINT_ID_SCACHE_SIZE); 17683 realloc_size += (_BCM_SB2_OAM_LMDM_SCACHE_INFO_SIZE); 17684 } 17685 /* In BCM_WB_VERSION_1_2 onwards addition memory is used to store 17686 egress_label, as such adding the differential */ 17687 if (recovered_ver < BCM_WB_VERSION_1_2) { 17688 realloc_size += (_BCM_SB2_OAM_EGR_LABEL_SCACHE_SIZE); 17689 } 17690 /* BCM_WB_VERSION_1_4 onwards SDK recovers PM profile info */ 17691 if (recovered_ver < BCM_WB_VERSION_1_4) { 17692 #if defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_BHH) 17693 if ((_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) || 17694 (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) || 17695 (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc))) { 17696 realloc_size += (_BCM_SB2_OAM_PM_PROFILE_SCACHE_SIZE); 17697 realloc_size += (_bcm_sb2_oam_pmid_scache_size(unit)); 17698 } 17699 #endif 17700 } 17701 17702 /* BCM_WB_VERSION_1_4 onwards SDK recovers the lookup key_type for 17703 * LSP MEPs in EGR_MP_GROUP 17704 */ 17705 if (recovered_ver < BCM_WB_VERSION_1_5) { 17706 #if defined(INCLUDE_BHH) 17707 realloc_size += sizeof(uint8); 17708 #endif /* INCLUDE_BHH */ 17709 #if defined(INCLUDE_MPLS_LM_DM) 17710 realloc_size += sizeof(uint8); 17711 #endif /* INCLUDE_MPLS_LM_DM */ 17712 } 17713 17714 if (recovered_ver < BCM_WB_VERSION_1_6) { 17715 #if defined(INCLUDE_BHH) 17716 if(soc_feature(unit, soc_feature_bhh)) { 17717 if(0 == oc->ukernel_not_ready) { 17718 realloc_size += sizeof(uint8) * oc->bhh_endpoint_count * 2; 17719 } 17720 } 17721 #endif 17722 } 17723 17724 if (recovered_ver < BCM_WB_VERSION_1_7) { 17725 /* Allocate memory to store oc->eth_oam_mp_group_vlan_key */ 17726 realloc_size += sizeof(uint8); 17727 } 17728 17729 if (recovered_ver < BCM_WB_VERSION_1_8) { 17730 /* Store trunk index for BHH and MPLS LM/DM endpoints */ 17731 trunk_idx_size = 0; 17732 #if defined(INCLUDE_BHH) 17733 if(soc_feature(unit, soc_feature_bhh)) { 17734 if (oc->ukernel_not_ready == 0) { 17735 trunk_idx_size = sizeof(uint8) * oc->ma_idx_count; 17736 } 17737 } 17738 #endif /* INCLUDE_BHH */ 17739 #if defined(INCLUDE_MPLS_LM_DM) 17740 if (oc->mpls_lm_dm_ukernel_ready) { 17741 if (trunk_idx_size == 0 ) { 17742 /* No BHH */ 17743 trunk_idx_size = sizeof(uint8) * oc->ma_idx_count; 17744 } 17745 } 17746 #endif /* INCLUDE_MPLS_LM_DM */ 17747 realloc_size += trunk_idx_size; 17748 } 17749 17750 if (recovered_ver < BCM_WB_VERSION_1_9) { 17751 realloc_size += (sizeof(uint32) * oc->ep_count); 17752 } 17753 17754 if (recovered_ver < BCM_WB_VERSION_1_10) { 17755 /* Store the BHH ACH Channel Type */ 17756 #if defined(INCLUDE_BHH) 17757 realloc_size += sizeof(sb2_oam_mpls_tp_ach_channel_type); 17758 #endif /* INCLUDE_BHH */ 17759 } 17760 17761 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 17762 rv = soc_scache_realloc(unit, scache_handle, realloc_size); 17763 if (SOC_FAILURE(rv)) { 17764 LOG_ERROR(BSL_LS_BCM_OAM, 17765 (BSL_META_U(unit,"OAM Error: scache alloc failed - %s.\n"), 17766 bcm_errmsg(rv))); 17767 goto cleanup; 17768 } 17769 } 17770 17771 cleanup: 17772 _BCM_OAM_UNLOCK(oc); 17773 return (rv); 17774 } 17775 17776 17777 #if defined(INCLUDE_BHH) 17778 int bcmi_xgs5_bhh_version_exchange(int unit) 17779 { 17780 uint8 *buffer_reply, *buffer_req, *buffer_ptr; 17781 uint16 buffer_len, reply_len; 17782 bhh_sdk_version_exchange_msg_t sdk_msg,uc_msg; 17783 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 17784 int rv = BCM_E_NONE; 17785 17786 _BCM_OAM_BHH_IS_VALID(unit); 17787 17788 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 17789 17790 /* Pack control message data into DMA */ 17791 sdk_msg.version = BHH_SDK_VERSION; 17792 17793 buffer_req = oc->dma_buffer; 17794 buffer_ptr = bhh_sdk_version_exchange_msg_pack(buffer_req, &sdk_msg); 17795 buffer_len = buffer_ptr - buffer_req; 17796 17797 /* Send Message to exchange version value*/ 17798 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, MOS_MSG_SUBCLASS_BHH_VERSION_EXCHANGE, 17799 buffer_len, 0, 17800 MOS_MSG_SUBCLASS_BHH_VER_EXCHANGE_REPLY, 17801 &reply_len); 17802 if (rv == BCM_E_UNAVAIL) { 17803 bhh_firmware_version = BHH_UC_MIN_VERSION; 17804 return BCM_E_NONE; 17805 } else if (rv < 0) { 17806 return rv; 17807 } 17808 17809 sal_memset(&uc_msg, 0, sizeof(uc_msg)); 17810 buffer_reply = oc->dma_buffer; 17811 buffer_ptr = bhh_sdk_version_exchange_msg_unpack(buffer_reply, &uc_msg); 17812 buffer_len = buffer_ptr - buffer_reply; 17813 17814 if (reply_len != buffer_len) { 17815 return BCM_E_INTERNAL; 17816 } 17817 17818 bhh_firmware_version = uc_msg.version; 17819 return BCM_E_NONE; 17820 } 17821 17822 /* 17823 * Function: 17824 * _bcm_sb2_oam_bhh_cos_map_recover 17825 * Purpose: 17826 * Recover cos mappings done for BHH 17827 * Parameters: 17828 * unit - (IN) BCM device number 17829 * Retruns: 17830 * BCM_E_XXX 17831 */ 17832 STATIC int 17833 _bcm_sb2_oam_bhh_cos_map_recover(int unit) 17834 { 17835 int rv = BCM_E_NONE; 17836 _bcm_oam_control_t *oc; 17837 int index; 17838 int cosq_map_size; 17839 bcm_rx_reasons_t reasons, reasons_mask; 17840 bcm_rx_reasons_t ach_error_reasons, invalid_error_reasons; 17841 bcm_rx_reasons_t bhh_lb_reasons; 17842 uint8 int_prio, int_prio_mask; 17843 uint32 packet_type, packet_type_mask; 17844 bcm_cos_queue_t cosq; 17845 17846 /* Get OAM Control Structure. */ 17847 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 17848 _BCM_OAM_LOCK(oc); 17849 17850 if (oc->ukernel_not_ready) { 17851 _BCM_OAM_UNLOCK(oc); 17852 return BCM_E_NONE; 17853 } 17854 17855 rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size); 17856 if(BCM_FAILURE(rv)) { 17857 LOG_ERROR(BSL_LS_BCM_OAM, 17858 (BSL_META_U(unit, 17859 "BHH Error:hw init. cosq maps size %s.\n"), 17860 bcm_errmsg(rv))); 17861 _BCM_OAM_UNLOCK(oc); 17862 return (rv); 17863 } 17864 17865 BCM_RX_REASON_CLEAR_ALL(ach_error_reasons); 17866 BCM_RX_REASON_SET(ach_error_reasons, bcmRxReasonBHHOAM); 17867 BCM_RX_REASON_SET(ach_error_reasons, bcmRxReasonOAMCCMSlowpath); 17868 17869 BCM_RX_REASON_CLEAR_ALL(invalid_error_reasons); 17870 BCM_RX_REASON_SET(invalid_error_reasons, bcmRxReasonBHHOAM); 17871 BCM_RX_REASON_SET(invalid_error_reasons, bcmRxReasonOAMLMDM); 17872 17873 BCM_RX_REASON_CLEAR_ALL(bhh_lb_reasons); 17874 BCM_RX_REASON_SET(bhh_lb_reasons, bcmRxReasonBHHOAM); 17875 BCM_RX_REASON_SET(bhh_lb_reasons, bcmRxReasonOAMSlowpath); 17876 17877 oc->cpu_cosq_ach_error_index = -1; 17878 oc->cpu_cosq_invalid_error_index = -1; 17879 oc->bhh_lb_index = -1; 17880 for (index = 0; index < cosq_map_size; index++) { 17881 rv = bcm_esw_rx_cosq_mapping_get(unit, index, 17882 &reasons, &reasons_mask, 17883 &int_prio, &int_prio_mask, 17884 &packet_type, &packet_type_mask, 17885 &cosq); 17886 if (rv == BCM_E_NONE) { 17887 17888 if (BCM_RX_REASON_EQ(reasons, ach_error_reasons) && 17889 BCM_RX_REASON_EQ(reasons_mask, ach_error_reasons)) { 17890 oc->cpu_cosq_ach_error_index = index; 17891 oc->cpu_cosq = cosq; 17892 } else if (BCM_RX_REASON_EQ(reasons, invalid_error_reasons) && 17893 BCM_RX_REASON_EQ(reasons_mask, invalid_error_reasons)) { 17894 oc->cpu_cosq_invalid_error_index = index; 17895 } else if (BCM_RX_REASON_EQ(reasons, bhh_lb_reasons) && 17896 BCM_RX_REASON_EQ(reasons_mask, bhh_lb_reasons)) { 17897 oc->bhh_lb_index = index; 17898 } 17899 17900 if( -1 != oc->cpu_cosq_ach_error_index && 17901 -1 != oc->cpu_cosq_invalid_error_index && 17902 -1 != oc->bhh_lb_index) { 17903 break; 17904 } 17905 } 17906 } 17907 17908 if (index >= cosq_map_size) { 17909 LOG_ERROR(BSL_LS_BCM_OAM, 17910 (BSL_META_U(unit, 17911 "BHH Error: Could not recover cos map entry \n"))); 17912 } 17913 17914 _BCM_OAM_UNLOCK(oc); 17915 return rv; 17916 } 17917 #endif /* INCLUDE_BHH */ 17918 17919 #if defined(INCLUDE_ETH_LM_DM) 17920 /* 17921 * Function: 17922 * _bcm_sb2_oam_eth_lm_dm_cos_map_recover 17923 * Purpose: 17924 * Recover cos mapping done for ETH_LM_DM packet processing. 17925 * Parameters: 17926 * unit - (IN) Unit number. 17927 * Returns: 17928 * BCM_E_XXX 17929 * Notes: 17930 */ 17931 STATIC int 17932 _bcm_sb2_oam_eth_lm_dm_cos_map_recover(int unit) 17933 { 17934 int rv = BCM_E_NONE; 17935 _bcm_oam_control_t *oc; 17936 int index; 17937 int cosq_map_size; 17938 bcm_rx_reasons_t reasons, reasons_mask; 17939 bcm_rx_reasons_t eth_lm_dm_reasons; 17940 uint8 int_prio, int_prio_mask; 17941 uint32 packet_type, packet_type_mask; 17942 bcm_cos_queue_t cosq; 17943 17944 /* Get OAM Control Structure. */ 17945 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 17946 _BCM_OAM_LOCK(oc); 17947 17948 if (oc->eth_lm_dm_ukernel_not_ready) { 17949 _BCM_OAM_UNLOCK(oc); 17950 return BCM_E_NONE; 17951 } 17952 17953 rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size); 17954 if(BCM_FAILURE(rv)) { 17955 LOG_ERROR(BSL_LS_BCM_OAM, 17956 (BSL_META_U(unit, 17957 "ETH LM/DM Error:hw init. cosq maps size %s.\n"), 17958 bcm_errmsg(rv))); 17959 _BCM_OAM_UNLOCK(oc); 17960 return (rv); 17961 } 17962 17963 BCM_RX_REASON_CLEAR_ALL(eth_lm_dm_reasons); 17964 BCM_RX_REASON_SET(eth_lm_dm_reasons, bcmRxReasonOAMLMDM); 17965 17966 oc->eth_lm_dm_cosq_index = -1; 17967 for (index = 0; index < cosq_map_size; index++) { 17968 rv = bcm_esw_rx_cosq_mapping_get(unit, index, 17969 &reasons, &reasons_mask, 17970 &int_prio, &int_prio_mask, 17971 &packet_type, &packet_type_mask, 17972 &cosq); 17973 if (rv == BCM_E_NONE) { 17974 17975 if (BCM_RX_REASON_EQ(reasons, eth_lm_dm_reasons) && 17976 BCM_RX_REASON_EQ(reasons_mask, eth_lm_dm_reasons)) { 17977 oc->eth_lm_dm_cosq_index = index; 17978 oc->eth_lm_dm_cpu_cosq = cosq; 17979 } 17980 } 17981 if( -1 != oc->eth_lm_dm_cosq_index) { 17982 break; 17983 } 17984 } 17985 17986 if (index >= cosq_map_size) { 17987 LOG_VERBOSE(BSL_LS_BCM_OAM, 17988 (BSL_META_U(unit, 17989 "ETH LM/DM Error: Could not recover cos map entry \n"))); 17990 } 17991 17992 _BCM_OAM_UNLOCK(oc); 17993 return rv; 17994 } 17995 #endif /* INCLUDE_ETH_LM_DM */ 17996 17997 #if defined(INCLUDE_MPLS_LM_DM) 17998 /* 17999 * Function: 18000 * _bcm_sb2_oam_mpls_lm_dm_cos_map_recover 18001 * Purpose: 18002 * Recover the cos mapping config done for MPLS_LM_DM packet processing. 18003 * Parameters: 18004 * unit - (IN) Unit number. 18005 * Returns: 18006 * BCM_E_XXX 18007 * Notes: 18008 */ 18009 STATIC int 18010 _bcm_sb2_oam_mpls_lm_dm_cos_map_recover(int unit) 18011 { 18012 int rv = BCM_E_NONE; 18013 _bcm_oam_control_t *oc; 18014 int index; 18015 int cosq_map_size; 18016 bcm_rx_reasons_t reasons, reasons_mask; 18017 bcm_rx_reasons_t mpls_lm_dm_reasons; 18018 uint8 int_prio, int_prio_mask; 18019 uint32 packet_type, packet_type_mask; 18020 bcm_cos_queue_t cosq; 18021 18022 /* Get OAM Control Structure. */ 18023 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 18024 _BCM_OAM_LOCK(oc); 18025 18026 if (!oc->mpls_lm_dm_ukernel_ready) { 18027 _BCM_OAM_UNLOCK(oc); 18028 return BCM_E_NONE; 18029 } 18030 18031 rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size); 18032 if(BCM_FAILURE(rv)) { 18033 LOG_ERROR(BSL_LS_BCM_OAM, 18034 (BSL_META_U(unit, 18035 "MPLS LM/DM Error:hw init. cosq maps size %s.\n"), 18036 bcm_errmsg(rv))); 18037 _BCM_OAM_UNLOCK(oc); 18038 return (rv); 18039 } 18040 18041 BCM_RX_REASON_CLEAR_ALL(mpls_lm_dm_reasons); 18042 BCM_RX_REASON_SET(mpls_lm_dm_reasons, bcmRxReasonOAMMplsLmDm); 18043 18044 oc->mpls_lm_dm_cosq_index = -1; 18045 for (index = 0; index < cosq_map_size; index++) { 18046 rv = bcm_esw_rx_cosq_mapping_get(unit, index, 18047 &reasons, &reasons_mask, 18048 &int_prio, &int_prio_mask, 18049 &packet_type, &packet_type_mask, 18050 &cosq); 18051 if (rv == BCM_E_NONE) { 18052 18053 if (BCM_RX_REASON_EQ(reasons, mpls_lm_dm_reasons) && 18054 BCM_RX_REASON_EQ(reasons_mask, mpls_lm_dm_reasons)) { 18055 oc->mpls_lm_dm_cosq_index = index; 18056 oc->mpls_lm_dm_cpu_cosq = cosq; 18057 } 18058 } 18059 if( -1 != oc->mpls_lm_dm_cosq_index) { 18060 break; 18061 } 18062 } 18063 18064 if (index >= cosq_map_size) { 18065 LOG_VERBOSE(BSL_LS_BCM_OAM, 18066 (BSL_META_U(unit, 18067 "MPLS LM/DM Error: Could not recover cos map entry \n"))); 18068 } 18069 18070 _BCM_OAM_UNLOCK(oc); 18071 return rv; 18072 } 18073 #endif /* INCLUDE_MPLS_LM_DM */ 18074 18075 #endif /* BCM_WARM_BOOT_SUPPORT */ 18076 18077 STATIC int 18078 _bcm_sb2_oam_ma_idx_num_entries_and_pool_get(int unit, 18079 _bcm_oam_hash_data_t *h_data_p, 18080 int *num_ma_idx_entries, 18081 shr_idxres_list_handle_t *pool) 18082 { 18083 _bcm_oam_control_t *oc = NULL; 18084 18085 /* Get OAM control structure handle. */ 18086 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 18087 18088 if ((h_data_p == NULL) || (h_data_p->in_use == 0)) { 18089 return BCM_E_PARAM; 18090 } 18091 18092 switch (oc->ma_idx_alloc_scheme) { 18093 case _BCM_OAM_MA_IDX_ALLOC_COMBINED_POOL: 18094 *num_ma_idx_entries = 8; 18095 *pool = oc->ma_idx_pool; 18096 return BCM_E_NONE; 18097 break; 18098 case _BCM_OAM_MA_IDX_ALLOC_SEPARATE_POOL: 18099 if (h_data_p->type == bcmOAMEndpointTypeEthernet) { 18100 *num_ma_idx_entries = 8; 18101 *pool = oc->ma_idx_pool; 18102 } else if (BHH_EP_TYPE(h_data_p) || 18103 (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p))) { 18104 *num_ma_idx_entries = 1; 18105 *pool = oc->mpls_oam_ma_idx_pool; 18106 } 18107 return BCM_E_NONE; 18108 break; 18109 default: 18110 /* Should not hit */ 18111 break; 18112 } 18113 return BCM_E_INTERNAL; 18114 } 18115 18116 STATIC int 18117 _bcm_sb2_oam_ma_idx_pool_create(_bcm_oam_control_t *oc) 18118 { 18119 int rv = BCM_E_NONE; 18120 18121 if (MA_INDEX_ALLOC_SCHEME_COMBINED_POOL) { 18122 rv = shr_idxres_list_create(&oc->ma_idx_pool, 0, 18123 oc->ma_idx_count - 1, 18124 0, oc->ma_idx_count -1, "ma_idx pool"); 18125 if (BCM_FAILURE(rv)) { 18126 return (rv); 18127 18128 } 18129 } else if (MA_INDEX_ALLOC_SCHEME_SEPARATE_POOL) { 18130 if (_BCM_ETH_OAM_NUM_SESSIONS != 0) { 18131 rv = shr_idxres_list_create(&oc->ma_idx_pool, 0, _BCM_ETH_OAM_NUM_SESSIONS-1, 18132 0, _BCM_ETH_OAM_NUM_SESSIONS-1, "ma_idx pool"); 18133 if (BCM_FAILURE(rv)) { 18134 return (rv); 18135 18136 } 18137 } 18138 18139 if (_BCM_MPLS_OAM_NUM_SESSIONS != 0) { 18140 rv = shr_idxres_list_create(&oc->mpls_oam_ma_idx_pool, 18141 _BCM_ETH_OAM_NUM_SESSIONS, 18142 _BCM_ETH_OAM_NUM_SESSIONS + _BCM_MPLS_OAM_NUM_SESSIONS-1, 18143 _BCM_ETH_OAM_NUM_SESSIONS, 18144 _BCM_ETH_OAM_NUM_SESSIONS + _BCM_MPLS_OAM_NUM_SESSIONS-1, 18145 "mpls oam ma_idx pool"); 18146 if (BCM_FAILURE(rv)) { 18147 return (rv); 18148 18149 } 18150 } 18151 } else { 18152 return (BCM_E_INTERNAL); 18153 18154 } 18155 return rv; 18156 } 18157 18158 STATIC int 18159 _bcm_sb2_oam_ma_idx_pool_destroy(_bcm_oam_control_t *oc) 18160 { 18161 if (NULL != oc->ma_idx_pool) { 18162 shr_idxres_list_destroy(oc->ma_idx_pool); 18163 oc->ma_idx_pool = NULL; 18164 } 18165 if (NULL != oc->mpls_oam_ma_idx_pool) { 18166 shr_idxres_list_destroy(oc->mpls_oam_ma_idx_pool); 18167 oc->mpls_oam_ma_idx_pool = NULL; 18168 } 18169 return BCM_E_NONE; 18170 } 18171 18172 18173 /* * * * * * * * * * * * * * * * * * * * 18174 * OAM BCM APIs * 18175 */ 18176 /* 18177 * Function: bcm_sb2_oam_init 18178 * 18179 * Purpose: 18180 * Initialize OAM module. 18181 * Parameters: 18182 * unit - (IN) BCM device number 18183 * Returns: 18184 * BCM_E_UNIT - Invalid BCM unit number. 18185 * BCM_E_UNAVAIL - OAM not support on this device. 18186 * BCM_E_MEMORY - Allocation failure 18187 * CM_E_XXX - Error code from bcm_XX_oam_init() 18188 * BCM_E_NONE - Success 18189 */ 18190 int 18191 bcm_sb2_oam_init(int unit) 18192 { 18193 _bcm_oam_control_t *oc = NULL; /* OAM control structure. */ 18194 int rv; /* Operation return value. */ 18195 uint32 size; /* Size of memory allocation. */ 18196 bcm_port_t port; /* Port number. */ 18197 int index = 0; 18198 bcm_oam_endpoint_t ep_index; /* Endpoint index. */ 18199 bcm_pbmp_t all_pbmp; 18200 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM) 18201 uint8 *buffer, *buffer_ptr; 18202 uint16 buffer_len, reply_len; 18203 int uc_status; /* uController Status */ 18204 #endif 18205 #if defined(INCLUDE_BHH) 18206 int uc; 18207 #endif 18208 18209 #if defined(INCLUDE_BHH) 18210 uint8 carrier_code[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; 18211 char *carrier_code_str; 18212 uint32 node_id = 0; 18213 bhh_sdk_msg_ctrl_init_t msg_init; 18214 int priority; 18215 int ukernel_not_ready = 0; 18216 uint8 bhh_consolidate_final_event = 0; 18217 #endif 18218 18219 #if defined(INCLUDE_ETH_LM_DM) 18220 eth_lm_dm_sdk_msg_ctrl_init_t eth_msg_init; 18221 uint8 eth_lm_dm_ukernel_not_ready = 1; 18222 uint8 eth_lm_dm_default_cosq; 18223 #endif 18224 18225 #if defined(INCLUDE_MPLS_LM_DM) 18226 #if defined(BCM_METROLITE_SUPPORT) 18227 int mpls_lmdm_uc; 18228 #endif 18229 mpls_lm_dm_sdk_msg_ctrl_init_t mpls_lm_dm_msg_init; 18230 #endif 18231 18232 /* Ensure that the unit has OAM support. */ 18233 if (!soc_feature(unit, soc_feature_oam)) { 18234 LOG_ERROR(BSL_LS_BCM_OAM, 18235 (BSL_META_U(unit, 18236 "OAM(unit %d) Error: OAM not supported \n"), 18237 unit)); 18238 return (BCM_E_UNAVAIL); 18239 } 18240 18241 /* Detach first if the module has been previously initialized. */ 18242 if (NULL != _sb2_oam_control[unit]) { 18243 _sb2_oam_control[unit]->init = FALSE; 18244 rv = bcm_sb2_oam_detach(unit); 18245 if (BCM_FAILURE(rv)) { 18246 LOG_ERROR(BSL_LS_BCM_OAM, 18247 (BSL_META_U(unit, 18248 "OAM(unit %d) Error: Module deinit - %s.\n"), 18249 unit, bcm_errmsg(rv))); 18250 return (rv); 18251 } 18252 } 18253 18254 /* Allocate OAM control memeory for this unit. */ 18255 _BCM_OAM_ALLOC(oc, _bcm_oam_control_t, sizeof (_bcm_oam_control_t), 18256 "OAM control"); 18257 if (NULL == oc) { 18258 return (BCM_E_MEMORY); 18259 } 18260 18261 if (soc_feature(unit, soc_feature_bhh)) { 18262 #ifdef INCLUDE_BHH 18263 /* 18264 * Initialize uController side 18265 */ 18266 18267 /* 18268 * Start BHH application in BTE (Broadcom Task Engine) uController, 18269 * if not already running (warm boot). 18270 * Determine which uController is running BHH by choosing the first 18271 * uC that returns successfully. 18272 */ 18273 for (uc = 0; uc < SOC_INFO(unit).num_ucs; uc++) { 18274 rv = soc_uc_status(unit, uc, &uc_status); 18275 if ((rv == SOC_E_NONE) && (uc_status != 0)) { 18276 rv = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_BHH, 18277 _BHH_UC_MSG_TIMEOUT_USECS, 18278 BHH_SDK_VERSION, 18279 BHH_UC_MIN_VERSION, 18280 _bcm_oam_bhh_appl_callback, NULL); 18281 if (SOC_E_NONE == rv) { 18282 /* BHH started successfully */ 18283 oc->uc_num = uc; 18284 break; 18285 } 18286 } 18287 } 18288 18289 if (uc >= SOC_INFO(unit).num_ucs) { /* Could not find or start BHH appl */ 18290 ukernel_not_ready = 1; 18291 LOG_ERROR(BSL_LS_BCM_OAM, 18292 (BSL_META_U(unit, 18293 "uKernel Not Ready, bhh not started\n"))); 18294 } 18295 #endif 18296 } 18297 18298 if (soc_feature(unit, soc_feature_eth_lm_dm)) { 18299 #ifdef INCLUDE_ETH_LM_DM 18300 /* 18301 * Initialize uController side 18302 */ 18303 18304 /* 18305 * Start ETH LM/DM application in BTE (Broadcom Task Engine) uController, 18306 * if not already running (warm boot). 18307 */ 18308 if (SOC_IS_METROLITE(unit)) { 18309 oc->eth_lm_dm_uc_num = ML_ETH_LM_DM_UC_NUM; 18310 } else { 18311 oc->eth_lm_dm_uc_num = SB2_ETH_LM_DM_UC_NUM; 18312 } 18313 18314 rv = soc_uc_status(unit, oc->eth_lm_dm_uc_num, &uc_status); 18315 if ((rv == SOC_E_NONE) && (uc_status != 0)) { 18316 rv = soc_cmic_uc_appl_init(unit, oc->eth_lm_dm_uc_num, 18317 MOS_MSG_CLASS_ETH_LM_DM, 18318 _ETH_LM_DM_UC_MSG_TIMEOUT_USECS, 18319 ETH_LM_DM_SDK_VERSION, 18320 ETH_LM_DM_UC_MIN_VERSION, 18321 _bcm_oam_eth_lm_dm_appl_callback, NULL); 18322 18323 if (SOC_E_NONE == rv) { 18324 /* ETH_LM_DM started successfully */ 18325 eth_lm_dm_ukernel_not_ready = 0; 18326 } else { 18327 LOG_ERROR(BSL_LS_BCM_OAM, 18328 (BSL_META_U(unit, 18329 "uKernel Not Ready, ETH_LM_DM not started\n"))); 18330 } 18331 } 18332 oc->eth_lm_dm_ukernel_not_ready = eth_lm_dm_ukernel_not_ready; 18333 18334 #endif 18335 } 18336 18337 /* Get number of endpoints and groups supported by this unit. */ 18338 rv = _bcm_sb2_oam_group_endpoint_count_init(unit, oc); 18339 if (BCM_FAILURE(rv)) { 18340 _bcm_sb2_oam_control_free(unit, oc); 18341 return (rv); 18342 } 18343 oc->unit = unit; 18344 if (soc_feature(unit, soc_feature_bhh)) { 18345 #if defined(INCLUDE_BHH) 18346 18347 oc->ukernel_not_ready = ukernel_not_ready; 18348 /* Get SOC properties for BHH */ 18349 oc->bhh_endpoint_count = soc_property_get(unit, spn_BHH_NUM_SESSIONS, 128); 18350 oc->bhh_max_encap_length = 18351 soc_property_get(unit, 18352 spn_BHH_ENCAP_MAX_LENGTH, 18353 _BCM_OAM_BHH_DEFAULT_ENCAP_LENGTH); 18354 18355 if(oc->bhh_max_encap_length > _BCM_OAM_BHH_MAX_ENCAP_LENGTH) { 18356 LOG_ERROR(BSL_LS_BCM_OAM, 18357 (BSL_META_U(unit, 18358 "Invalid max encap_length=%u\n"), 18359 oc->bhh_max_encap_length)); 18360 return BCM_E_CONFIG; 18361 } 18362 18363 carrier_code_str = soc_property_get_str(unit, spn_BHH_CARRIER_CODE); 18364 if (carrier_code_str != NULL) { 18365 /* 18366 * Note that the carrier code is specified in colon separated 18367 * MAC address format. 18368 */ 18369 if (_shr_parse_macaddr(carrier_code_str, carrier_code) < 0) { 18370 _bcm_sb2_oam_control_free(unit, oc); 18371 return (BCM_E_INTERNAL); 18372 } 18373 } 18374 18375 node_id = soc_property_get(unit, spn_BHH_NODE_ID, 0); 18376 bhh_consolidate_final_event = soc_property_get(unit, 18377 spn_BHH_CONSOLIDATED_FINAL_EVENT, 0); 18378 18379 if(oc->ep_count > _BCM_OAM_SABER2_ENDPOINT_MAX) { 18380 LOG_ERROR(BSL_LS_BCM_OAM, 18381 (BSL_META_U(unit, 18382 "OAM(unit %d) Error: OAM EP count %d not supported \n"), 18383 unit, oc->ep_count)); 18384 _bcm_sb2_oam_control_free(unit, oc); 18385 return (BCM_E_PARAM); 18386 } 18387 #endif /* INCLUDE_BHH */ 18388 } 18389 18390 #if defined(INCLUDE_MPLS_LM_DM) 18391 oc->mpls_lm_dm_ukernel_ready = 0; 18392 18393 #if defined(BCM_METROLITE_SUPPORT) 18394 if (SOC_IS_METROLITE(unit)) { 18395 for (mpls_lmdm_uc = 0; mpls_lmdm_uc < SOC_INFO(unit).num_ucs; mpls_lmdm_uc++) { 18396 rv = soc_uc_status(unit, mpls_lmdm_uc, &uc_status); 18397 if ((rv == SOC_E_NONE) && (uc_status != 0)) { 18398 rv = soc_cmic_uc_appl_init(unit, mpls_lmdm_uc, MOS_MSG_CLASS_MPLS_LM_DM, 18399 _MPLS_LM_DM_UC_MSG_TIMEOUT_USECS, 18400 MPLS_LM_DM_SDK_VERSION, 18401 MPLS_LM_DM_UC_MIN_VERSION, 18402 _bcm_oam_mpls_lm_dm_appl_callback, NULL); 18403 if (SOC_E_NONE == rv) { 18404 /* MPLS_LM_DM started successfully */ 18405 oc->mpls_lm_dm_uc_num = mpls_lmdm_uc; 18406 break; 18407 } 18408 } 18409 } 18410 if (mpls_lmdm_uc >= SOC_INFO(unit).num_ucs) { 18411 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 18412 "uKernel Not Ready, MPLS_LM_DM not started\n"))); 18413 } else { 18414 oc->mpls_lm_dm_ukernel_ready = 1; 18415 } 18416 } else 18417 #endif 18418 { 18419 18420 /* Core #2 is used for MPLS_LMDM in Saber2*/ 18421 if (soc_uc_in_reset(unit, MPLS_LM_DM_UC_NUM)) { 18422 18423 LOG_WARN(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM Warn:" 18424 " uKernel Not Ready, MPLS_LM_DM not started.\n If MPLS_LM_DM" 18425 " app is not not needed, compile SDK by excluding MPLS_LM_DM" 18426 " from FEATURE_LIST.\n"))); 18427 } else { 18428 18429 /* Initialize uController side 18430 * Start MPLS_LM_DM application in BTE (Broadcom Task Engine) uController. 18431 * MPLS_LM_DM_UC_NUM runs the MPLS_LM_DM Application. 18432 */ 18433 rv = soc_cmic_uc_appl_init(unit, MPLS_LM_DM_UC_NUM, MOS_MSG_CLASS_MPLS_LM_DM, 18434 _MPLS_LM_DM_UC_MSG_TIMEOUT_USECS, MPLS_LM_DM_SDK_VERSION, 18435 MPLS_LM_DM_UC_MIN_VERSION, 18436 _bcm_oam_mpls_lm_dm_appl_callback, NULL); 18437 18438 if (SOC_E_NONE == rv) { 18439 oc->mpls_lm_dm_uc_num = MPLS_LM_DM_UC_NUM; 18440 oc->mpls_lm_dm_ukernel_ready = 1; 18441 } 18442 } 18443 } 18444 if (SOC_E_NONE == rv) { 18445 18446 /* MPLS_LM_DM started successfully */ 18447 oc->mpls_lm_dm_sess_count = MPLS_LM_DM_MAX_SESSIONS; 18448 18449 size = sizeof(uint32) * oc->mpls_lm_dm_sess_count; 18450 _BCM_OAM_ALLOC(oc->mpls_lm_dm_sess_id_ep_id, uint32, size, 18451 "MPLS LM DM SESSION TO EP ID MAP"); 18452 18453 /* Create MPLS_LM_DM session pool */ 18454 rv = shr_idxres_list_create(&oc->mpls_lm_dm_pool, 1, 18455 oc->mpls_lm_dm_sess_count, 1, oc->mpls_lm_dm_sess_count, 18456 "mpls_lm_dm pool"); 18457 18458 if (BCM_FAILURE(rv)) { 18459 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d) Error:" 18460 " Creating Session Id pool failed \n"), unit)); 18461 _bcm_sb2_oam_control_free(unit, oc); 18462 return (rv); 18463 } 18464 } else { 18465 /* Could not start MPLS_LM_DM appl */ 18466 LOG_WARN(BSL_LS_BCM_OAM, (BSL_META_U(unit, 18467 "OAM(unit %d) WARN: MPLS LM DM init failed\n"), unit)); 18468 } 18469 #endif 18470 _BCM_MPLS_OAM_NUM_SESSIONS = soc_property_get(unit, spn_MPLS_OAM_NUM_SESSIONS, 18471 _BCM_MPLS_OAM_NUM_SESSIONS_INVALID); 18472 18473 if(_BCM_MPLS_OAM_NUM_SESSIONS == 18474 _BCM_MPLS_OAM_NUM_SESSIONS_INVALID) { 18475 /* Entry does not exist. Revert to old scheme */ 18476 oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_COMBINED_POOL; 18477 } else if (_BCM_MPLS_OAM_NUM_SESSIONS > soc_mem_index_max(unit, MA_INDEXm)){ 18478 /* If it is greater than max index of MA_INDEX table, 18479 * set it to max_index value and set it to newer index alloc scheme. 18480 */ 18481 _BCM_MPLS_OAM_NUM_SESSIONS = soc_mem_index_max(unit, MA_INDEXm); 18482 _BCM_ETH_OAM_NUM_SESSIONS = 0; 18483 oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_SEPARATE_POOL; 18484 } else { 18485 _BCM_ETH_OAM_NUM_SESSIONS = 18486 soc_mem_index_count(unit, MA_INDEXm) - _BCM_MPLS_OAM_NUM_SESSIONS; 18487 oc->ma_idx_alloc_scheme = _BCM_OAM_MA_IDX_ALLOC_SEPARATE_POOL; 18488 } 18489 18490 /* Mem_1: Allocate hash data memory */ 18491 /* size = sizeof(_bcm_oam_hash_data_t) * oc->ep_count; */ 18492 size = sizeof(_bcm_oam_hash_data_t) * _BCM_OAM_SABER2_ENDPOINT_MAX; 18493 18494 _BCM_OAM_ALLOC(oc->oam_hash_data, _bcm_oam_hash_data_t, size, "Hash data"); 18495 if (NULL == oc->oam_hash_data) { 18496 _bcm_sb2_oam_control_free(unit, oc); 18497 return (BCM_E_MEMORY); 18498 } 18499 18500 /* Mem_2: Allocate group memory */ 18501 size = sizeof(_bcm_oam_group_data_t) * oc->group_count; 18502 18503 _BCM_OAM_ALLOC(oc->group_info, _bcm_oam_group_data_t, size, "Group Info"); 18504 18505 if (NULL == oc->group_info) { 18506 _bcm_sb2_oam_control_free(unit, oc); 18507 return (BCM_E_MEMORY); 18508 } 18509 18510 /* Allocate RMEP H/w to logical index mapping memory */ 18511 size = sizeof(bcm_oam_endpoint_t) * oc->rmep_count; 18512 18513 _BCM_OAM_ALLOC(oc->remote_endpoints, bcm_oam_endpoint_t, size, "RMEP Mapping"); 18514 if (NULL == oc->remote_endpoints) { 18515 _bcm_sb2_oam_control_free(unit, oc); 18516 return (BCM_E_MEMORY); 18517 } 18518 /* Initialize the mapping to BCM_OAM_ENDPOINT_INVALID */ 18519 for (ep_index = 0; ep_index < oc->rmep_count; ++ep_index) { 18520 oc->remote_endpoints[ep_index] = BCM_OAM_ENDPOINT_INVALID; 18521 } 18522 18523 /* Mem_3: Create application endpoint list. */ 18524 rv = shr_idxres_list_create(&oc->mep_pool, 0, oc->ep_count - 1, 18525 0, oc->ep_count -1, "endpoint pool"); 18526 if (BCM_FAILURE(rv)) { 18527 _bcm_sb2_oam_control_free(unit, oc); 18528 return (rv); 18529 } 18530 18531 /* Mem_4: Create local MEP endpoint list. */ 18532 rv = shr_idxres_list_create(&oc->lmep_pool, 0, oc->lmep_count - 1, 18533 0, oc->lmep_count -1, "lmep pool"); 18534 if (BCM_FAILURE(rv)) { 18535 _bcm_sb2_oam_control_free(unit, oc); 18536 return (rv); 18537 } 18538 18539 /* Mem_5: Create Remote MEP endpoint list. */ 18540 rv = shr_idxres_list_create(&oc->rmep_pool, 0, oc->rmep_count - 1, 18541 0, oc->rmep_count -1, "rmep pool"); 18542 if (BCM_FAILURE(rv)) { 18543 _bcm_sb2_oam_control_free(unit, oc); 18544 return (rv); 18545 } 18546 18547 /* Mem_6: Create MEP Rx state tracker table index endpoint list - DnMEP */ 18548 18549 rv =_bcm_sb2_oam_ma_idx_pool_create(oc); 18550 if (BCM_FAILURE(rv)) { 18551 _bcm_sb2_oam_control_free(unit, oc); 18552 return (rv); 18553 } 18554 18555 /* Mem_7: Create MEP Rx state tracker table index endpoint list -UpMEP */ 18556 rv = shr_idxres_list_create(&oc->egr_ma_idx_pool, 0, 18557 oc->egr_ma_idx_count - 1, 18558 0, oc->egr_ma_idx_count -1, "egr_ma_idx pool"); 18559 if (BCM_FAILURE(rv)) { 18560 _bcm_sb2_oam_control_free(unit, oc); 18561 return (rv); 18562 18563 } 18564 18565 /* Initialize to domain specific key by default, WB recovery might 18566 * overwrite it, depending on older SDK. 18567 */ 18568 oc->eth_oam_mp_group_vlan_key = _BCM_SB2_ETH_OAM_MP_GROUP_KEY_DOMAIN_SPECIFIC; 18569 18570 if(soc_feature(unit, soc_feature_bhh)) { 18571 #if defined(INCLUDE_BHH) 18572 /* Create BHH endpoint list. */ 18573 rv = shr_idxres_list_create(&oc->bhh_pool, 0, oc->bhh_endpoint_count - 1, 18574 0, oc->bhh_endpoint_count - 1, "bhh pool"); 18575 if (BCM_FAILURE(rv)) { 18576 LOG_ERROR(BSL_LS_BCM_OAM, 18577 (BSL_META_U(unit, 18578 "OAM(unit %d) Error: Creating BHH pool failed \n"), 18579 unit)); 18580 _bcm_sb2_oam_control_free(unit, oc); 18581 return (rv); 18582 } 18583 18584 /* Reserve ep pool from mep_pool for BHH, manange BHH mep using bhh_pool */ 18585 rv = shr_idxres_list_reserve(oc->mep_pool, _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc), 18586 _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc) + oc->bhh_endpoint_count - 1); 18587 18588 if (BCM_FAILURE(rv)) { 18589 LOG_ERROR(BSL_LS_BCM_OAM, 18590 (BSL_META_U(unit, 18591 "OAM(unit %d) Error: Reserving BHH endpoints from mep_pool " 18592 "failed rv %d\n"), unit, rv)); 18593 _bcm_sb2_oam_control_free(unit, oc); 18594 return (rv); 18595 } 18596 18597 #endif /* INCLUDE_BHH */ 18598 } 18599 18600 /* Mem_4: Create group list. */ 18601 rv = shr_idxres_list_create(&oc->group_pool, 0, oc->group_count - 1, 18602 0, oc->group_count - 1, "group pool"); 18603 if (BCM_FAILURE(rv)) { 18604 _bcm_sb2_oam_control_free(unit, oc); 18605 return (rv); 18606 } 18607 18608 /* Index management for Ingress LM counter pool 1 */ 18609 rv = shr_aidxres_list_create(&(oc->ing_lm_ctr_pool[0]), 0, 18610 _BCM_SB2_MAX_OAM_LM_CTRS_POOL_0(unit) - 1, 0, 18611 _BCM_SB2_MAX_OAM_LM_CTRS_POOL_0(unit) - 1, 8, 18612 "ing_lm_idx pool1"); 18613 if (BCM_FAILURE(rv)) { 18614 _bcm_sb2_oam_control_free(unit, oc); 18615 return (rv); 18616 18617 } 18618 /* Index management for Ingress LM counter pool 2 */ 18619 rv = shr_aidxres_list_create(&(oc->ing_lm_ctr_pool[1]), 0, 18620 _BCM_SB2_MAX_OAM_LM_CTRS_POOL_1(unit) - 1, 0, 18621 _BCM_SB2_MAX_OAM_LM_CTRS_POOL_1(unit) - 1, 8, 18622 "ing_lm_idx pool2"); 18623 if (BCM_FAILURE(rv)) { 18624 _bcm_sb2_oam_control_free(unit, oc); 18625 return (rv); 18626 } 18627 18628 /* Index management for Ingress LM counter pool 3 */ 18629 rv = shr_aidxres_list_create(&(oc->ing_lm_ctr_pool[2]), 0, 18630 _BCM_SB2_MAX_OAM_LM_CTRS_POOL_2(unit) - 1, 0, 18631 _BCM_SB2_MAX_OAM_LM_CTRS_POOL_2(unit) - 1, 8, 18632 "ing_lm_idx pool3"); 18633 if (BCM_FAILURE(rv)) { 18634 _bcm_sb2_oam_control_free(unit, oc); 18635 return (rv); 18636 } 18637 18638 18639 /* Mem_5: Create MA group and MEP hash table. */ 18640 18641 #if defined(BCM_METROLITE_SUPPORT) 18642 if (SOC_IS_METROLITE(unit)) { 18643 rv = shr_htb_create(&oc->ma_mep_htbl, _BCM_OAM_METROLITE_ENDPOINT_MAX, 18644 sizeof(_bcm_oam_hash_key_t), "MA/MEP Hash"); 18645 } else 18646 #endif 18647 { 18648 rv = shr_htb_create(&oc->ma_mep_htbl, _BCM_OAM_SABER2_ENDPOINT_MAX, 18649 sizeof(_bcm_oam_hash_key_t), "MA/MEP Hash"); 18650 } 18651 18652 if (BCM_FAILURE(rv)) { 18653 _bcm_sb2_oam_control_free(unit, oc); 18654 return (rv); 18655 } 18656 18657 /* Create protection mutex. */ 18658 oc->oc_lock = sal_mutex_create("oam_control.lock"); 18659 if (NULL == oc->oc_lock) { 18660 _bcm_sb2_oam_control_free(unit, oc); 18661 return (BCM_E_MEMORY); 18662 } 18663 18664 /* Register device OAM interrupt handler & SER handler call back routine.*/ 18665 soc_kt2_oam_handler_register(unit, _bcm_sb2_oam_handle_interrupt); 18666 soc_kt2_oam_ser_handler_register(unit, _bcm_sb2_oam_ser_handler); 18667 18668 /* Set up the unit OAM control structure. */ 18669 _sb2_oam_control[unit] = oc; 18670 18671 if (soc_feature(unit, soc_feature_oam_pm)) { 18672 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_pm_init(unit)); 18673 } 18674 18675 /* Init OAM opcode group */ 18676 rv =_bcm_sb2_oam_opcode_group_init(unit); 18677 if (BCM_FAILURE(rv)) { 18678 _bcm_sb2_oam_control_free(unit, oc); 18679 return (rv); 18680 } 18681 18682 /* Set up OAM module related profile tables. */ 18683 rv = _bcm_sb2_oam_profile_tables_init(unit, oc); 18684 if (BCM_FAILURE(rv)) { 18685 _bcm_sb2_oam_control_free(unit, oc); 18686 return (rv); 18687 } 18688 18689 /* Initialize all the TPID tables */ 18690 rv = _bcm_sb2_outer_tpid_init(unit); 18691 if (BCM_FAILURE(rv)) { 18692 _bcm_sb2_oam_control_free(unit, oc); 18693 return (rv); 18694 } 18695 rv = _bcm_sb2_inner_tpid_init(unit); 18696 if (BCM_FAILURE(rv)) { 18697 _bcm_sb2_oam_control_free(unit, oc); 18698 return (rv); 18699 } 18700 rv = _bcm_sb2_subport_tpid_init(unit); 18701 if (BCM_FAILURE(rv)) { 18702 _bcm_sb2_oam_control_free(unit, oc); 18703 return (rv); 18704 } 18705 18706 #if defined(BCM_WARM_BOOT_SUPPORT) 18707 if(!SOC_WARM_BOOT(unit)) 18708 #endif 18709 { 18710 BCM_PBMP_CLEAR(all_pbmp); 18711 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 18712 18713 if (soc_feature(unit, soc_feature_flex_port)) { 18714 #if defined(BCM_METROLITE_SUPPORT) 18715 if (SOC_IS_METROLITE(unit)) { 18716 BCM_IF_ERROR_RETURN(bcm_ml_flexio_pbmp_update(unit, &all_pbmp)); 18717 }else 18718 #endif 18719 { 18720 BCM_IF_ERROR_RETURN(bcm_sb2_flexio_pbmp_update(unit, &all_pbmp)); 18721 } 18722 } 18723 if (soc_feature(unit, soc_feature_linkphy_coe) || 18724 soc_feature(unit, soc_feature_subtag_coe)) { 18725 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 18726 } 18727 18728 if(SOC_IS_SABER2(unit)){ 18729 int oamp_enable = 0; 18730 BCM_IF_ERROR_RETURN(bcm_sb2_sat_oamp_enable_get(unit, &oamp_enable)); 18731 /* Skip OAMP port for saber2 device */ 18732 if(oamp_enable) { 18733 SOC_PBMP_PORT_REMOVE(all_pbmp, 18734 _BCM_SB2_SAT_OAMP_PHY_PORT_NUMBER); 18735 } 18736 } 18737 18738 /* Enable OAM processing on all ports of this unit. */ 18739 PBMP_ITER(all_pbmp, port) { 18740 rv = bcm_esw_port_control_set(unit, port, bcmPortControlOAMEnable, 18741 TRUE); 18742 if (BCM_FAILURE(rv)) { 18743 _bcm_sb2_oam_control_free(unit, oc); 18744 return (rv); 18745 } 18746 } 18747 18748 /* Enable CCM Rx timeouts. */ 18749 rv = _bcm_sb2_oam_ccm_rx_timeout_set(unit, 1); 18750 if (BCM_FAILURE(rv)) { 18751 _bcm_sb2_oam_control_free(unit, oc); 18752 return (rv); 18753 } 18754 18755 /* Enable CCM Tx control. */ 18756 rv = _bcm_sb2_oam_ccm_tx_config_set(unit, 1); 18757 if (BCM_FAILURE(rv)) { 18758 _bcm_sb2_oam_control_free(unit, oc); 18759 return (rv); 18760 } 18761 18762 18763 /* 18764 * Misc config: Enable IFP lookup on the CPU port. 18765 */ 18766 rv = _bcm_sb2_oam_misc_config(unit); 18767 if (BCM_FAILURE(rv)) { 18768 _bcm_sb2_oam_control_free(unit, oc); 18769 return (rv); 18770 } 18771 /* Set all the non CFM opcodes in opcode group -1 */ 18772 oc->opcode_grp_bmp[0] = ~(_BCM_OAM_OPCODE_TYPE_CFM_MASK); 18773 oc->opcode_grp_1_bmp[0] = 0; 18774 oc->opcode_grp_2_bmp[0] = 0; 18775 for (index = 1; index < 8; index ++) { 18776 oc->opcode_grp_bmp[index] = _BCM_OAM_OPCODE_TYPE_NON_CFM_MASK; 18777 oc->opcode_grp_1_bmp[index] = 0; 18778 oc->opcode_grp_2_bmp[index] = 0; 18779 } 18780 18781 /* Init MPLS OAM ach type config */ 18782 rv = _bcm_sb2_oam_mpls_oam_ach_type_config_init(unit); 18783 if (BCM_FAILURE(rv)) { 18784 _bcm_sb2_oam_control_free(unit, oc); 18785 return (rv); 18786 } 18787 /* Init OAM_KEY_SELECT_CONTROL registers */ 18788 rv = _bcm_sb2_oam_lookup_key_priorities_init(unit); 18789 if (BCM_FAILURE(rv)) { 18790 _bcm_sb2_oam_control_free(unit, oc); 18791 return (rv); 18792 } 18793 /* Init OAM_INTF_PROC_SELECT_CONTROL registers */ 18794 rv = _bcm_sb2_oam_lookup_interface_priorities_init(unit); 18795 if (BCM_FAILURE(rv)) { 18796 _bcm_sb2_oam_control_free(unit, oc); 18797 return (rv); 18798 } 18799 18800 /* Set default values for flexible oam domain control */ 18801 rv = _bcm_sb2_oam_flexible_oam_domain_ctrl_set(unit); 18802 if (BCM_FAILURE(rv)) { 18803 _bcm_sb2_oam_control_free(unit, oc); 18804 return (rv); 18805 } 18806 /* Set default values for flexible ingress and egress drop control */ 18807 rv = _bcm_sb2_oam_flexible_drop_ctrl_set(unit); 18808 if (BCM_FAILURE(rv)) { 18809 _bcm_sb2_oam_control_free(unit, oc); 18810 return (rv); 18811 } 18812 /* Set default values for s-interface passive processing control */ 18813 rv = _bcm_sb2_oam_s_intf_passive_proc_ctrl_set(unit); 18814 if (BCM_FAILURE(rv)) { 18815 _bcm_sb2_oam_control_free(unit, oc); 18816 return (rv); 18817 } 18818 /* Enable OLP handling on HG ports */ 18819 rv = _bcm_sb2_oam_hg_olp_enable(unit); 18820 if (BCM_FAILURE(rv)) { 18821 _bcm_sb2_oam_control_free(unit, oc); 18822 return (rv); 18823 } 18824 /* Set default olp header type mapping */ 18825 rv = _bcm_sb2_oam_olp_header_type_mapping_set(unit); 18826 if (BCM_FAILURE(rv)) { 18827 _bcm_sb2_oam_control_free(unit, oc); 18828 return (rv); 18829 } 18830 /* Set default behavior to add olp header for oam pkts to CPU */ 18831 rv = _bcm_sb2_oam_set_egr_oam_rx_mode(unit, 1); 18832 if (BCM_FAILURE(rv)) { 18833 _bcm_sb2_oam_control_free(unit, oc); 18834 return (rv); 18835 } 18836 /* Set OAM drop control to not to drop wrong version OAM packets */ 18837 rv = _bcm_sb2_oam_drop_ctrl_set(unit); 18838 if (BCM_FAILURE(rv)) { 18839 _bcm_sb2_oam_control_free(unit, oc); 18840 return (rv); 18841 } 18842 /* Set OAM LM cng and cpu data control*/ 18843 rv = _bcm_sb2_oam_lm_cng_cpu_ctrl_set_default(unit); 18844 if (BCM_FAILURE(rv)) { 18845 _bcm_sb2_oam_control_free(unit, oc); 18846 return (rv); 18847 } 18848 /* Set Magic port used in OLP-XGS communication */ 18849 rv = _bcm_sb2_oam_olp_magic_port_set(unit); 18850 if (BCM_FAILURE(rv)) { 18851 _bcm_sb2_oam_control_free(unit, oc); 18852 return (rv); 18853 } 18854 /* Disable MACSA Zero check */ 18855 rv = _bcm_sb2_oam_macsa_zero_check_disable(unit); 18856 if (BCM_FAILURE(rv)) { 18857 _bcm_sb2_oam_control_free(unit, oc); 18858 return (rv); 18859 } 18860 } 18861 18862 18863 /* 18864 * BHH init 18865 */ 18866 if(soc_feature(unit, soc_feature_bhh)) { 18867 #if defined(INCLUDE_BHH) 18868 if(ukernel_not_ready == 0){ 18869 /* 18870 * Initialize HOST side 18871 */ 18872 oc->cpu_cosq = soc_property_get(unit, spn_BHH_COSQ, 18873 BHH_COSQ_INVALID); 18874 18875 /* 18876 * Allocate DMA buffers 18877 * 18878 * DMA buffer will be used to send and receive 'long' messages 18879 * between SDK Host and uController (BTE). 18880 */ 18881 oc->dma_buffer_len = sizeof(bhh_sdk_msg_ctrl_t); 18882 18883 /* Adding feature specific for dma_buf_len as currently 18884 * required buffer length for faults_get can be configurable 18885 * by user during init. So, taking the max value of either of 18886 * them for the purpose.Putting it under fature_check for 18887 * giving flexibility to user. 18888 */ 18889 #ifdef INCLUDE_OAM_FAULTS_MULTI_GET 18890 if(soc_feature(unit, soc_feature_faults_multi_ep_get)) { 18891 oc->dma_buffer_len = MAX((oc->bhh_endpoint_count * sizeof(uint32)), oc->dma_buffer_len); 18892 } 18893 #endif 18894 oc->dma_buffer = soc_cm_salloc(unit, oc->dma_buffer_len, 18895 "BHH DMA buffer"); 18896 if (!oc->dma_buffer) { 18897 _bcm_sb2_oam_control_free(unit, oc); 18898 return (BCM_E_MEMORY); 18899 } 18900 sal_memset(oc->dma_buffer, 0, oc->dma_buffer_len); 18901 18902 oc->dmabuf_reply = soc_cm_salloc(unit, oc->dma_buffer_len, 18903 "BHH uC reply"); 18904 if (!oc->dmabuf_reply) { 18905 _bcm_sb2_oam_control_free(unit, oc); 18906 return (BCM_E_MEMORY); 18907 } 18908 18909 sal_memset(oc->dmabuf_reply, 0, oc->dma_buffer_len); 18910 18911 _BCM_OAM_ALLOC(oc->bhh_ma_index_in_use, SHR_BITDCL, 18912 SHR_BITALLOCSIZE(oc->ma_idx_count), 18913 "MA_INDEX ALLOCATED FOR BHH"); 18914 18915 _BCM_OAM_ALLOC(oc->bhh_ep_grp_id, short, 18916 sizeof(short) * oc->bhh_endpoint_count, 18917 "BHH endpoint group ids"); 18918 18919 _BCM_OAM_ALLOC(oc->bhh_ep_vpn, short, 18920 sizeof(short) * oc->bhh_endpoint_count, 18921 "BHH endpoint VPN ids"); 18922 18923 /* RX DMA channel (0..3) local to the uC */ 18924 oc->rx_channel = BCM_KT_BHH_RX_CHANNEL; 18925 18926 #ifdef BCM_WARM_BOOT_SUPPORT 18927 if (!SOC_WARM_BOOT(unit)) { 18928 #endif 18929 /* Set control message data */ 18930 sal_memset(&msg_init, 0, sizeof(msg_init)); 18931 msg_init.num_sessions = oc->bhh_endpoint_count; 18932 msg_init.rx_channel = oc->rx_channel; 18933 msg_init.node_id = node_id; 18934 sal_memcpy(msg_init.carrier_code, carrier_code, 18935 SHR_BHH_CARRIER_CODE_LEN); 18936 if (soc_feature(unit, soc_feature_oam_pm)) { 18937 msg_init.data_collection_mode = oc->pm_bhh_lmdm_data_collection_mode; 18938 } 18939 msg_init.max_encap_length = oc->bhh_max_encap_length; 18940 if (bhh_consolidate_final_event) { 18941 msg_init.flags |= BHH_SDK_MSG_CTRL_INIT_ONLY_FINAL_EVENT; 18942 } 18943 18944 /* Pack control message data into DMA buffer */ 18945 buffer = oc->dma_buffer; 18946 buffer_ptr = bhh_sdk_msg_ctrl_init_pack(unit, buffer, &msg_init); 18947 buffer_len = buffer_ptr - buffer; 18948 18949 /* Send BHH Init message to uC */ 18950 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 18951 MOS_MSG_SUBCLASS_BHH_INIT, 18952 buffer_len, 0, 18953 MOS_MSG_SUBCLASS_BHH_INIT_REPLY, 18954 &reply_len); 18955 18956 if (BCM_FAILURE(rv) || (reply_len != 0)) { 18957 _bcm_sb2_oam_control_free(unit, oc); 18958 return (BCM_E_INTERNAL); 18959 } 18960 18961 #ifdef BCM_WARM_BOOT_SUPPORT 18962 } 18963 #endif 18964 18965 /* 18966 * End BHH init 18967 */ 18968 } 18969 /* 18970 * Initialize HW 18971 */ 18972 #ifdef BCM_WARM_BOOT_SUPPORT 18973 if (SOC_WARM_BOOT(unit)) { 18974 rv = _bcm_sb2_oam_bhh_cos_map_recover(unit); 18975 } else 18976 #endif 18977 { 18978 rv = _bcm_sb2_oam_bhh_hw_init(unit); 18979 } 18980 18981 if (BCM_FAILURE(rv)) { 18982 BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit)); 18983 return rv; 18984 } 18985 18986 18987 #endif 18988 } 18989 18990 /* 18991 * ETH_LM_DM init 18992 */ 18993 if(soc_feature(unit, soc_feature_eth_lm_dm)) { 18994 #if defined(INCLUDE_ETH_LM_DM) 18995 18996 if(!oc->eth_lm_dm_ukernel_not_ready) { 18997 18998 /* Get number of sessions SOC properties for ETH_LM_DM */ 18999 oc->eth_lm_dm_sess_count = soc_property_get(unit, 19000 spn_ETH_LM_DM_NUM_SESSIONS, 19001 128); 19002 19003 size = sizeof(uint32) * oc->eth_lm_dm_sess_count; 19004 _BCM_OAM_ALLOC(oc->eth_lm_dm_sess_id_ep_id, uint32, size, 19005 "ETHLM DM SESSION TO EP ID MAP"); 19006 19007 /* Create ETH_LM_DM session pool */ 19008 rv = shr_idxres_list_create(&oc->eth_lm_dm_pool, 1, 19009 oc->eth_lm_dm_sess_count, 1, 19010 oc->eth_lm_dm_sess_count, 19011 "eth_lm_dm pool"); 19012 19013 if (BCM_FAILURE(rv)) { 19014 LOG_ERROR(BSL_LS_BCM_OAM, 19015 (BSL_META_U(unit, "ETH_LM_DM(unit %d) Error:" 19016 " Creating Session Id pool failed \n"), unit)); 19017 _bcm_sb2_oam_control_free(unit, oc); 19018 return (rv); 19019 } 19020 19021 /* 19022 * Initialize HOST side 19023 */ 19024 if (SOC_IS_METROLITE(unit)) { 19025 eth_lm_dm_default_cosq = BCM_ML_ETH_LM_DM_CPU_COS; 19026 } else { 19027 eth_lm_dm_default_cosq = BCM_SB2_ETH_LM_DM_CPU_COS; 19028 } 19029 oc->eth_lm_dm_cpu_cosq = soc_property_get(unit, 19030 spn_ETH_LM_DM_COSQ, 19031 eth_lm_dm_default_cosq); 19032 /* 19033 * Allocate DMA buffers 19034 * 19035 * DMA buffer will be used to send and receive 'long' messages 19036 * between SDK Host and uController (BTE). 19037 */ 19038 oc->eth_lm_dm_dma_buffer_len = sizeof(shr_eth_lm_dm_msg_ctrl_t); 19039 oc->eth_lm_dm_dma_buffer = soc_cm_salloc(unit, oc->eth_lm_dm_dma_buffer_len, 19040 "ETH_LM_DM DMA buffer"); 19041 if (!oc->eth_lm_dm_dma_buffer) { 19042 _bcm_sb2_oam_control_free(unit, oc); 19043 return (BCM_E_MEMORY); 19044 } 19045 sal_memset(oc->eth_lm_dm_dma_buffer, 0, oc->eth_lm_dm_dma_buffer_len); 19046 19047 oc->eth_lm_dm_dmabuf_reply = 19048 soc_cm_salloc(unit, sizeof(shr_eth_lm_dm_msg_ctrl_t), 19049 "ETH_LM_DM uC reply"); 19050 if (!oc->eth_lm_dm_dmabuf_reply) { 19051 _bcm_sb2_oam_control_free(unit, oc); 19052 return (BCM_E_MEMORY); 19053 } 19054 sal_memset(oc->eth_lm_dm_dmabuf_reply, 0, sizeof(shr_eth_lm_dm_msg_ctrl_t)); 19055 19056 /* RX DMA channel */ 19057 if (SOC_IS_METROLITE(unit)) { 19058 oc->eth_lm_dm_rx_channel = BCM_ML_ETH_LM_DM_RX_CHANNEL; 19059 } else { 19060 oc->eth_lm_dm_rx_channel = BCM_SB2_ETH_LM_DM_RX_CHANNEL; 19061 } 19062 19063 #ifdef BCM_WARM_BOOT_SUPPORT 19064 if (!SOC_WARM_BOOT(unit)) { 19065 #endif 19066 /* Set control message data */ 19067 sal_memset(ð_msg_init, 0, sizeof(eth_msg_init)); 19068 eth_msg_init.num_sessions = oc->eth_lm_dm_sess_count; 19069 eth_msg_init.rx_channel = BCM_SB2_ETH_LM_DM_UC_RX_CHANNEL; 19070 eth_msg_init.data_collection_mode = 19071 oc->pm_eth_lmdm_data_collection_mode; 19072 19073 /* Pack control message data into DMA buffer */ 19074 buffer = oc->eth_lm_dm_dma_buffer; 19075 buffer_ptr = eth_lm_dm_sdk_msg_ctrl_init_pack(buffer, 19076 ð_msg_init); 19077 buffer_len = buffer_ptr - buffer; 19078 19079 /* Send ETH_LM_DM Init message to uC */ 19080 rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit, 19081 MOS_MSG_SUBCLASS_ETH_LM_DM_INIT, 19082 buffer_len, 0, 19083 MOS_MSG_SUBCLASS_ETH_LM_DM_INIT_REPLY, 19084 &reply_len); 19085 19086 if (BCM_FAILURE(rv) || (reply_len != 0)) { 19087 _bcm_sb2_oam_control_free(unit, oc); 19088 return (BCM_E_INTERNAL); 19089 } 19090 #ifdef BCM_WARM_BOOT_SUPPORT 19091 } 19092 #endif 19093 } 19094 /* 19095 * Initialize HW.If the app is not processed in uKernel(uKernel not Ready) 19096 * still pipeleine or HW programming is required to send the LM/DM packets 19097 * to correct CPU 19098 */ 19099 #ifdef BCM_WARM_BOOT_SUPPORT 19100 if (SOC_WARM_BOOT(unit)) { 19101 rv = _bcm_sb2_oam_eth_lm_dm_cos_map_recover(unit); 19102 } else 19103 #endif 19104 { 19105 rv = _bcm_sb2_oam_eth_lm_dm_hw_init(unit); 19106 } 19107 19108 if (BCM_FAILURE(rv)) { 19109 BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit)); 19110 return rv; 19111 } 19112 19113 #endif 19114 } 19115 19116 #if defined(INCLUDE_MPLS_LM_DM) 19117 if(oc->mpls_lm_dm_ukernel_ready) { 19118 19119 /* 19120 * Allocate DMA buffers 19121 * DMA buffer will be used to send and receive 'long' messages 19122 * between SDK Host and uController (BTE). 19123 */ 19124 oc->mpls_lm_dm_dma_buffer_len = sizeof(mpls_lm_dm_sdk_msg_ctrl_t); 19125 oc->mpls_lm_dm_dma_buffer = soc_cm_salloc(unit, 19126 oc->mpls_lm_dm_dma_buffer_len, "MPLS_LM_DM DMA buffer"); 19127 if (!oc->mpls_lm_dm_dma_buffer) { 19128 _bcm_sb2_oam_control_free(unit, oc); 19129 return (BCM_E_MEMORY); 19130 } 19131 sal_memset(oc->mpls_lm_dm_dma_buffer, 0, oc->mpls_lm_dm_dma_buffer_len); 19132 19133 oc->mpls_lm_dm_dmabuf_reply = soc_cm_salloc(unit, 19134 sizeof(shr_mpls_lm_dm_msg_ctrl_t), "MPLS_LM_DM uC reply"); 19135 if (!oc->mpls_lm_dm_dmabuf_reply) { 19136 _bcm_sb2_oam_control_free(unit, oc); 19137 return (BCM_E_MEMORY); 19138 } 19139 sal_memset(oc->mpls_lm_dm_dmabuf_reply, 0, 19140 sizeof(mpls_lm_dm_sdk_msg_ctrl_t)); 19141 19142 #ifdef BCM_WARM_BOOT_SUPPORT 19143 /* If We are warm rebooting dont re-initialize the App */ 19144 if (!SOC_WARM_BOOT(unit)) { 19145 #endif 19146 19147 /* Send Initialize MPLS LM/DM App on UKERNEL */ 19148 /* Set control message data */ 19149 sal_memset(&mpls_lm_dm_msg_init, 0, sizeof(mpls_lm_dm_msg_init)); 19150 mpls_lm_dm_msg_init.num_sessions = oc->mpls_lm_dm_sess_count; 19151 mpls_lm_dm_msg_init.rx_channel = MPLS_LM_DM_RX_CHANNEL_UC_VIEW; 19152 19153 /* Add PM data collection mode to init message */ 19154 if (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) { 19155 if (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) 19156 { 19157 mpls_lm_dm_msg_init.flags |= SHR_MPLS_LM_DM_PM_MODE_RAW; 19158 } 19159 else { 19160 mpls_lm_dm_msg_init.flags |= SHR_MPLS_LM_DM_PM_MODE_STATS; 19161 } 19162 } 19163 19164 /* Pack control message data into DMA buffer */ 19165 buffer = oc->mpls_lm_dm_dma_buffer; 19166 buffer_ptr = mpls_lm_dm_sdk_msg_ctrl_init_pack(buffer, &mpls_lm_dm_msg_init); 19167 buffer_len = buffer_ptr - buffer; 19168 19169 /* Send MPLS_LM_DM Init message to uC */ 19170 rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit, 19171 MOS_MSG_SUBCLASS_MPLS_LM_DM_INIT, buffer_len, 0, 19172 MOS_MSG_SUBCLASS_MPLS_LM_DM_INIT_REPLY, &reply_len); 19173 19174 if (BCM_FAILURE(rv) || (reply_len != 0)) { 19175 /* Could not start MPLS_LM_DM appl */ 19176 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 19177 "MPLS LM DM Session alloc msg failed\n"), unit)); 19178 BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit)); 19179 return rv; 19180 } 19181 19182 #ifdef BCM_WARM_BOOT_SUPPORT 19183 } 19184 #endif 19185 /* 19186 * Initialize HW. If the app is not processed in uKernel(uKernel not 19187 * Ready) still pipeleine or HW programming is required to send the 19188 * LM/DM packets to correct CPU 19189 */ 19190 19191 /* RX DMA channel (0..3) local to the uC */ 19192 oc->mpls_lm_dm_rx_channel = MPLS_LM_DM_RX_CHANNEL_SDK_VIEW; 19193 oc->mpls_lm_dm_cpu_cosq = MPLS_LM_DM_COSQ_INVALID; 19194 #ifdef BCM_WARM_BOOT_SUPPORT 19195 if (SOC_WARM_BOOT(unit)) { 19196 rv = _bcm_sb2_oam_mpls_lm_dm_cos_map_recover(unit); 19197 } else 19198 #endif 19199 #if defined(BCM_METROLITE_SUPPORT) 19200 if (SOC_IS_METROLITE(unit)) { 19201 rv = _bcm_ml_oam_mpls_lm_dm_hw_init(unit); 19202 } else 19203 #endif 19204 { 19205 rv = _bcm_sb2_oam_mpls_lm_dm_hw_init(unit); 19206 } 19207 19208 if (BCM_FAILURE(rv)) { 19209 BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit)); 19210 return rv; 19211 } 19212 19213 } 19214 #endif 19215 19216 rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_init(unit); 19217 if (BCM_FAILURE(rv)) { 19218 BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit)); 19219 return rv; 19220 } 19221 19222 #if defined(BCM_WARM_BOOT_SUPPORT) 19223 if (!SOC_WARM_BOOT(unit)) { 19224 bcm_sb2_oam_scache_alloc(unit); 19225 } 19226 19227 #if defined(INCLUDE_BHH) 19228 if(soc_feature(unit, soc_feature_bhh)) { 19229 if(ukernel_not_ready == 0) { 19230 rv = bcmi_xgs5_bhh_version_exchange(unit); 19231 if (BCM_FAILURE(rv)) { 19232 _bcm_sb2_oam_control_free(unit, oc); 19233 return rv; 19234 } 19235 } 19236 } 19237 #endif 19238 19239 if (SOC_WARM_BOOT(unit)) { 19240 rv = _bcm_sb2_oam_reinit(unit); 19241 if (BCM_FAILURE(rv)) { 19242 _bcm_sb2_oam_control_free(unit, oc); 19243 return (rv); 19244 } 19245 } 19246 #endif 19247 19248 if(soc_feature(unit, soc_feature_bhh)) { 19249 #if defined(INCLUDE_BHH) 19250 if(ukernel_not_ready == 0){ 19251 /* 19252 * Start event message callback thread 19253 */ 19254 priority = soc_property_get(unit, spn_BHH_THREAD_PRI, 19255 BHH_THREAD_PRI_DFLT); 19256 19257 if (oc->event_thread_id == NULL) { 19258 sal_thread_t thread_id; 19259 thread_id = sal_thread_create("bcmBHH", SAL_THREAD_STKSZ, 19260 priority, _bcm_sb2_oam_bhh_callback_thread, 19261 (void*)oc); 19262 if (thread_id == SAL_THREAD_ERROR) { 19263 BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit)); 19264 return (BCM_E_MEMORY); 19265 } else { 19266 oc->event_thread_id = thread_id; 19267 } 19268 } 19269 } 19270 #endif 19271 } 19272 19273 if(soc_feature(unit, soc_feature_eth_lm_dm)) { 19274 #if defined(INCLUDE_ETH_LM_DM) 19275 if(!eth_lm_dm_ukernel_not_ready) { 19276 /* 19277 * Start event message callback thread 19278 */ 19279 if (oc->eth_lm_dm_pm_event_thread_id == NULL) { 19280 if ((oc->eth_lm_dm_pm_event_thread_id = 19281 sal_thread_create("bcmETHLMDM", SAL_THREAD_STKSZ, 19282 ETH_LMDM_EVENT_THREAD_PRIORITY, 19283 _bcm_sb2_oam_pm_ethlmdm_callback_thread, 19284 (void*)oc)) == SAL_THREAD_ERROR) { 19285 oc->eth_lm_dm_pm_event_thread_id = NULL; 19286 BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit)); 19287 return (BCM_E_MEMORY); 19288 } 19289 } 19290 } 19291 #endif 19292 } 19293 19294 #if defined(INCLUDE_MPLS_LM_DM) 19295 if(oc->mpls_lm_dm_ukernel_ready) { 19296 /* 19297 * Start event message callback thread 19298 */ 19299 if (oc->mpls_lm_dm_pm_event_thread_id == NULL) { 19300 if ((oc->mpls_lm_dm_pm_event_thread_id = 19301 sal_thread_create("bcmMPLSLMDM", SAL_THREAD_STKSZ, 19302 MPLS_LMDM_EVENT_THREAD_PRIORITY, 19303 _bcm_sb2_oam_pm_mplslmdm_callback_thread, 19304 (void*)oc)) == SAL_THREAD_ERROR) { 19305 oc->mpls_lm_dm_pm_event_thread_id = NULL; 19306 BCM_IF_ERROR_RETURN(bcm_sb2_oam_detach(unit)); 19307 return (BCM_E_MEMORY); 19308 } 19309 } 19310 } 19311 #endif 19312 19313 /* OAM initialization complete. */ 19314 _sb2_oam_control[unit]->init = TRUE; 19315 return (BCM_E_NONE); 19316 } 19317 19318 /* 19319 * Function: 19320 * bcm_sb2_oam_detach 19321 * Purpose: 19322 * Shut down OAM subsystem 19323 * Parameters: 19324 * unit - (IN) BCM device number 19325 * Returns: 19326 * BCM_E_XXX 19327 */ 19328 int 19329 bcm_sb2_oam_detach(int unit) 19330 { 19331 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 19332 bcm_port_t port; /* Port number. */ 19333 int rv; /* Operation return status. */ 19334 bcm_pbmp_t all_pbmp; 19335 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM) 19336 uint16 reply_len; 19337 int uc_status; 19338 #endif 19339 19340 /* Get the device OAM module handle. */ 19341 oc = _sb2_oam_control[unit]; 19342 if (NULL == oc) { 19343 /* Module already uninitialized. */ 19344 return (BCM_E_NONE); 19345 } 19346 19347 /* Unregister all OAM interrupt event handlers and SER handler. */ 19348 soc_kt2_oam_handler_register(unit, NULL); 19349 soc_kt2_oam_ser_handler_register(unit, NULL); 19350 19351 if (NULL != oc->oc_lock) { 19352 _BCM_OAM_LOCK(oc); 19353 } 19354 19355 rv = _bcm_sb2_oam_events_unregister(unit, oc); 19356 if (BCM_FAILURE(rv)) { 19357 if (NULL != oc->oc_lock) { 19358 _BCM_OAM_UNLOCK(oc); 19359 } 19360 return (rv); 19361 } 19362 19363 /* Disable CCM Rx Timeouts. */ 19364 rv = _bcm_sb2_oam_ccm_rx_timeout_set(unit, 0); 19365 if (BCM_FAILURE(rv)) { 19366 if (NULL != oc->oc_lock) { 19367 _BCM_OAM_UNLOCK(oc); 19368 } 19369 return (rv); 19370 } 19371 19372 /* Disable CCM Tx control for the device. */ 19373 rv = _bcm_sb2_oam_ccm_tx_config_set(unit, 0); 19374 if (BCM_FAILURE(rv)) { 19375 if (NULL != oc->oc_lock) { 19376 _BCM_OAM_UNLOCK(oc); 19377 } 19378 return (rv); 19379 } 19380 19381 BCM_PBMP_CLEAR(all_pbmp); 19382 BCM_PBMP_ASSIGN(all_pbmp, PBMP_ALL(unit)); 19383 19384 if (soc_feature(unit, soc_feature_flex_port)) { 19385 #if defined(BCM_METROLITE_SUPPORT) 19386 if (SOC_IS_METROLITE(unit)) { 19387 rv =bcm_ml_flexio_pbmp_update(unit, &all_pbmp); 19388 }else 19389 #endif 19390 { 19391 rv = bcm_sb2_flexio_pbmp_update(unit, &all_pbmp); 19392 } 19393 if (BCM_FAILURE(rv)) { 19394 _BCM_OAM_UNLOCK(oc); 19395 return (rv); 19396 } 19397 } 19398 if (soc_feature(unit, soc_feature_linkphy_coe) || 19399 soc_feature(unit, soc_feature_subtag_coe)) { 19400 _bcm_kt2_subport_pbmp_update(unit, &all_pbmp); 19401 } 19402 19403 #if defined(BCM_SABER2_SUPPORT) 19404 if(SOC_IS_SABER2(unit)){ 19405 int oamp_enable; 19406 (void)bcm_sb2_sat_oamp_enable_get(unit, &oamp_enable); 19407 /* Skip OAMP port for saber2 device */ 19408 if(oamp_enable) { 19409 SOC_PBMP_PORT_REMOVE(all_pbmp, 19410 _BCM_SB2_SAT_OAMP_PHY_PORT_NUMBER); 19411 } 19412 } 19413 #endif 19414 19415 /* Disable OAM PDU Rx processing on all ports. */ 19416 PBMP_ITER(all_pbmp, port) { 19417 rv = bcm_esw_port_control_set(unit, port, 19418 bcmPortControlOAMEnable, 0); 19419 if (BCM_FAILURE(rv)) { 19420 if (NULL != oc->oc_lock) { 19421 _BCM_OAM_UNLOCK(oc); 19422 } 19423 return (rv); 19424 } 19425 } 19426 19427 19428 19429 /* 19430 * BHH specific 19431 */ 19432 if (soc_feature(unit, soc_feature_bhh)) { 19433 #if defined(INCLUDE_BHH) 19434 if (oc->ukernel_not_ready == 0) { 19435 /* 19436 * Event Handler thread exit signal 19437 */ 19438 sal_usecs_t timeout = sal_time_usecs() + 5000000; 19439 while (NULL != oc->event_thread_id) { 19440 soc_cmic_uc_msg_receive_cancel(unit, oc->uc_num, 19441 MOS_MSG_CLASS_BHH_EVENT); 19442 19443 if (sal_time_usecs() < timeout) { 19444 /*give some time to already running bhh callback thread 19445 * to schedule and exit */ 19446 sal_usleep(10000); 19447 } else { 19448 /*timeout*/ 19449 LOG_ERROR(BSL_LS_BCM_OAM, 19450 (BSL_META_U(unit, 19451 "BHH event thread did not exit.\n"))); 19452 _BCM_OAM_UNLOCK(oc); 19453 return BCM_E_INTERNAL; 19454 } 19455 } 19456 if (!SOC_WARM_BOOT(unit)) { 19457 /* 19458 * Send BHH Uninit message to uC 19459 * Ignore error since that may indicate uKernel was reloaded. 19460 */ 19461 SOC_IF_ERROR_RETURN(soc_uc_status(unit, oc->uc_num, &uc_status)); 19462 if (uc_status) { 19463 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 19464 MOS_MSG_SUBCLASS_BHH_UNINIT, 19465 0, 0, 19466 MOS_MSG_SUBCLASS_BHH_UNINIT_REPLY, 19467 &reply_len); 19468 if (BCM_SUCCESS(rv) && (reply_len != 0)) { 19469 if (NULL != oc->oc_lock) { 19470 _BCM_OAM_UNLOCK(oc); 19471 } 19472 return BCM_E_INTERNAL; 19473 } 19474 } 19475 19476 /* 19477 * Delete CPU COS queue mapping entries for BHH packets 19478 */ 19479 if (oc->cpu_cosq_ach_error_index >= 0) { 19480 rv = bcm_esw_rx_cosq_mapping_delete(unit, 19481 oc->cpu_cosq_ach_error_index); 19482 if (BCM_FAILURE(rv)) { 19483 if (NULL != oc->oc_lock) { 19484 _BCM_OAM_UNLOCK(oc); 19485 } 19486 return (rv); 19487 } 19488 oc->cpu_cosq_ach_error_index = -1; 19489 } 19490 if (oc->cpu_cosq_invalid_error_index >= 0) { 19491 rv = bcm_esw_rx_cosq_mapping_delete(unit, 19492 oc->cpu_cosq_invalid_error_index); 19493 if (BCM_FAILURE(rv)) { 19494 if (NULL != oc->oc_lock) { 19495 _BCM_OAM_UNLOCK(oc); 19496 } 19497 return (rv); 19498 } 19499 oc->cpu_cosq_invalid_error_index = -1; 19500 } 19501 if (oc->bhh_lb_index >= 0) { 19502 rv = bcm_esw_rx_cosq_mapping_delete(unit, 19503 oc->bhh_lb_index); 19504 if (BCM_FAILURE(rv)) { 19505 if (NULL != oc->oc_lock) { 19506 _BCM_OAM_UNLOCK(oc); 19507 } 19508 return (rv); 19509 } 19510 oc->bhh_lb_index = -1; 19511 } 19512 } 19513 } 19514 19515 #endif /* INCLUDE_BHH */ 19516 } 19517 19518 /* 19519 * ETH_LM_DM specific 19520 */ 19521 if (soc_feature(unit, soc_feature_eth_lm_dm)) { 19522 #if defined(INCLUDE_ETH_LM_DM) 19523 if(!oc->eth_lm_dm_ukernel_not_ready) { 19524 /* 19525 * Event Handler thread exit signal 19526 */ 19527 sal_usecs_t timeout = sal_time_usecs() + 5000000; 19528 while (NULL != oc->eth_lm_dm_pm_event_thread_id) { 19529 soc_cmic_uc_msg_receive_cancel(unit, oc->eth_lm_dm_uc_num, 19530 MOS_MSG_CLASS_ETH_LM_DM_EVENT); 19531 19532 if (sal_time_usecs() < timeout) { 19533 /*give some time to already running ETH LM/DM callback thread 19534 * to schedule and exit */ 19535 sal_usleep(10000); 19536 } else { 19537 /*timeout*/ 19538 LOG_ERROR(BSL_LS_BCM_OAM, 19539 (BSL_META_U(unit, 19540 "ETH LM/DM event thread did not exit.\n"))); 19541 _BCM_OAM_UNLOCK(oc); 19542 return BCM_E_INTERNAL; 19543 } 19544 } 19545 19546 /* 19547 * Send ETH_LM_DM Uninit message to uC 19548 * Ignore error since that may indicate uKernel was reloaded. 19549 */ 19550 if (!SOC_WARM_BOOT(unit)) { 19551 SOC_IF_ERROR_RETURN(soc_uc_status(unit, oc->eth_lm_dm_uc_num, &uc_status)); 19552 if (uc_status) { 19553 rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit, 19554 MOS_MSG_SUBCLASS_ETH_LM_DM_UNINIT, 19555 0, 0, 19556 MOS_MSG_SUBCLASS_ETH_LM_DM_UNINIT_REPLY, 19557 &reply_len); 19558 if (BCM_SUCCESS(rv) && (reply_len != 0)) { 19559 if (NULL != oc->oc_lock) { 19560 _BCM_OAM_UNLOCK(oc); 19561 } 19562 return BCM_E_INTERNAL; 19563 } 19564 } 19565 19566 /* 19567 * Delete CPU COS queue mapping entries for ETH_LM_DM packets 19568 */ 19569 if (oc->eth_lm_dm_cosq_index >= 0) { 19570 rv = bcm_esw_rx_cosq_mapping_delete(unit, 19571 oc->eth_lm_dm_cosq_index); 19572 if (BCM_FAILURE(rv)) { 19573 if (NULL != oc->oc_lock) { 19574 _BCM_OAM_UNLOCK(oc); 19575 } 19576 return (rv); 19577 } 19578 oc->eth_lm_dm_cosq_index = -1; 19579 } 19580 } 19581 } 19582 #endif /* INCLUDE_ETH_LM_DM */ 19583 } 19584 19585 19586 /* MPLS_LM_DM specific */ 19587 #if defined(INCLUDE_MPLS_LM_DM) 19588 if(oc->mpls_lm_dm_ukernel_ready) { 19589 /* 19590 * Send MPLS_LM_DM Uninit message to uC 19591 * Ignore error since that may indicate uKernel was reloaded. 19592 */ 19593 if (!SOC_WARM_BOOT(unit)) { 19594 SOC_IF_ERROR_RETURN(soc_uc_status(unit, oc->mpls_lm_dm_uc_num, &uc_status)); 19595 if (uc_status) { 19596 rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit, 19597 MOS_MSG_SUBCLASS_MPLS_LM_DM_UNINIT, 0, 0, 19598 MOS_MSG_SUBCLASS_MPLS_LM_DM_UNINIT_REPLY, &reply_len); 19599 if (BCM_SUCCESS(rv) && (reply_len != 0)) { 19600 if (NULL != oc->oc_lock) { 19601 _BCM_OAM_UNLOCK(oc); 19602 } 19603 return BCM_E_INTERNAL; 19604 } 19605 } 19606 19607 /* Delete CPU COS queue mapping entries for ETH_LM_DM packets */ 19608 if (oc->mpls_lm_dm_cosq_index >= 0) { 19609 rv = bcm_esw_rx_cosq_mapping_delete(unit, oc->mpls_lm_dm_cosq_index); 19610 if (BCM_FAILURE(rv)) { 19611 if (NULL != oc->oc_lock) { 19612 _BCM_OAM_UNLOCK(oc); 19613 } 19614 return (rv); 19615 } 19616 oc->mpls_lm_dm_cosq_index = -1; 19617 } 19618 } 19619 /* 19620 * Event Handler thread exit signal 19621 */ 19622 sal_usecs_t timeout = sal_time_usecs() + 5000000; 19623 while (NULL != oc->mpls_lm_dm_pm_event_thread_id) { 19624 soc_cmic_uc_msg_receive_cancel(unit, oc->mpls_lm_dm_uc_num, 19625 MOS_MSG_CLASS_MPLS_LM_DM_EVENT); 19626 19627 if (sal_time_usecs() < timeout) { 19628 /*give some time to already running MPLS LM/DM callback thread 19629 * to schedule and exit */ 19630 sal_usleep(10000); 19631 } else { 19632 /*timeout*/ 19633 LOG_ERROR(BSL_LS_BCM_OAM, 19634 (BSL_META_U(unit, 19635 "MPLS LM/DM event thread did not exit.\n"))); 19636 _BCM_OAM_UNLOCK(oc); 19637 return BCM_E_INTERNAL; 19638 } 19639 } 19640 } 19641 #endif /* INCLUDE_MPLS_LM_DM */ 19642 19643 /* Destroy all groups and assoicated endpoints and free the resources. */ 19644 rv = bcm_sb2_oam_group_destroy_all(unit); 19645 if (BCM_FAILURE(rv)) { 19646 if (NULL != oc->oc_lock) { 19647 _BCM_OAM_UNLOCK(oc); 19648 } 19649 return (rv); 19650 } 19651 rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_destroy(unit); 19652 if (BCM_FAILURE(rv)) { 19653 if (NULL != oc->oc_lock) { 19654 _BCM_OAM_UNLOCK(oc); 19655 } 19656 return (rv); 19657 } 19658 19659 /* Release the protection mutex. */ 19660 _BCM_OAM_UNLOCK(oc); 19661 19662 /* Free OAM module allocated resources. */ 19663 _bcm_sb2_oam_control_free(unit, oc); 19664 19665 return (BCM_E_NONE); 19666 } 19667 19668 /* 19669 * Function: 19670 * bcm_sb2_oam_group_create 19671 * Purpose: 19672 * Create or replace an OAM group object 19673 * Parameters: 19674 * unit - (IN) BCM device number 19675 * group_info - (IN/OUT) Pointer to an OAM group information. 19676 * Returns: 19677 * BCM_E_XXX 19678 */ 19679 int 19680 bcm_sb2_oam_group_create(int unit, bcm_oam_group_info_t *group_info) 19681 { 19682 ma_state_entry_t ma_state_entry; /* MA State table entry. */ 19683 uint8 grp_name_hw_buf[BCM_OAM_GROUP_NAME_LENGTH]; /* Grp */ 19684 /* name. */ 19685 maid_reduction_entry_t maid_reduction_entry; /* MA ID reduction table */ 19686 _bcm_oam_group_data_t *ma_group; /* Pointer to group info. */ 19687 _bcm_oam_control_t *oc; /* OAM control structure. */ 19688 int rv; /* Operation return status. */ 19689 /* entry. */ 19690 uint8 sw_rdi; /* Remote defect indicator. */ 19691 19692 #if defined(BCM_SABER2_SUPPORT) && defined(INCLUDE_BHH) 19693 bhh_sdk_msg_ctrl_sess_set_t msg_sess; 19694 uint8 *buffer, *buffer_ptr; 19695 uint16 buffer_len, reply_len; 19696 uint32 session_flags = 0; 19697 _bcm_oam_hash_data_t *h_data_p; 19698 _bcm_oam_ep_list_t *cur; 19699 #endif 19700 19701 19702 /* Validate input parameter. */ 19703 if (NULL == group_info) { 19704 return (BCM_E_PARAM); 19705 } 19706 19707 /* Get OAM control structure handle. */ 19708 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 19709 19710 /* Validate group id. */ 19711 if (group_info->flags & BCM_OAM_GROUP_WITH_ID) { 19712 _BCM_OAM_GROUP_INDEX_VALIDATE(group_info->id); 19713 } 19714 19715 _BCM_OAM_LOCK(oc); 19716 19717 /* 19718 * If MA group create is called with replace flag bit set. 19719 * - Check and return error if a group does not exist with the ID. 19720 */ 19721 if (group_info->flags & BCM_OAM_GROUP_REPLACE) { 19722 if (group_info->flags & BCM_OAM_GROUP_WITH_ID) { 19723 19724 /* Search the list with the MA Group ID value. */ 19725 rv = shr_idxres_list_elem_state(oc->group_pool, group_info->id); 19726 if (BCM_E_EXISTS != rv) { 19727 _BCM_OAM_UNLOCK(oc); 19728 LOG_ERROR(BSL_LS_BCM_OAM, 19729 (BSL_META_U(unit, 19730 "OAM(unit %d) Error: Group does not exist.\n"), 19731 unit)); 19732 return (BCM_E_PARAM); 19733 } 19734 } else { 19735 _BCM_OAM_UNLOCK(oc); 19736 LOG_ERROR(BSL_LS_BCM_OAM, 19737 (BSL_META_U(unit, 19738 "OAM(unit %d) Error: Replace command needs a " 19739 "valid Group ID.\n"), unit)); 19740 return (BCM_E_PARAM); 19741 } 19742 } else if (group_info->flags & BCM_OAM_GROUP_WITH_ID) { 19743 /* 19744 * If MA group create is called with ID flag bit set. 19745 * - Check and return error if the ID is already in use. 19746 */ 19747 rv = shr_idxres_list_reserve(oc->group_pool, group_info->id, 19748 group_info->id); 19749 if (BCM_FAILURE(rv)) { 19750 _BCM_OAM_UNLOCK(oc); 19751 return ((rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv); 19752 } 19753 } else { 19754 /* Reserve the next available group index. */ 19755 rv = shr_idxres_list_alloc(oc->group_pool, 19756 (shr_idxres_element_t *) &group_info->id); 19757 if (BCM_FAILURE(rv)) { 19758 _BCM_OAM_UNLOCK(oc); 19759 LOG_ERROR(BSL_LS_BCM_OAM, 19760 (BSL_META_U(unit, 19761 "OAM(unit %d) Error: Group allocation (GID=%d)" 19762 " %s\n"), unit, group_info->id, bcm_errmsg(rv))); 19763 return (rv); 19764 } 19765 } 19766 19767 /* Get this group memory to store group information. */ 19768 ma_group = &oc->group_info[group_info->id]; 19769 19770 /* Store the group name. */ 19771 sal_memcpy(&ma_group->name, &group_info->name, BCM_OAM_GROUP_NAME_LENGTH); 19772 19773 /* Store Lowest Alarm Priority */ 19774 ma_group->lowest_alarm_priority = group_info->lowest_alarm_priority; 19775 19776 if(!(group_info->flags & BCM_OAM_GROUP_REPLACE)) { 19777 _BCM_OAM_ALLOC((ma_group->ep_list),_bcm_oam_ep_list_t *, 19778 sizeof(_bcm_oam_ep_list_t *), "EP list head"); 19779 19780 /* Initialize head to NULL.*/ 19781 *ma_group->ep_list = NULL; 19782 } 19783 19784 /* 19785 * Maintenance Association ID - Reduction table update. 19786 */ 19787 19788 /* Prepare group name for hardware write. */ 19789 _bcm_sb2_oam_group_name_mangle(ma_group->name, grp_name_hw_buf); 19790 19791 sal_memset(&maid_reduction_entry, 0, sizeof(maid_reduction_entry_t)); 19792 19793 /* Calculate CRC32 value for the group name string and set in entry. */ 19794 soc_MAID_REDUCTIONm_field32_set 19795 (unit, &maid_reduction_entry, REDUCED_MAIDf, 19796 soc_draco_crc32(grp_name_hw_buf, BCM_OAM_GROUP_NAME_LENGTH)); 19797 19798 /* Check if software RDI flag bit needs to be set in hardware. */ 19799 sw_rdi = ((group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) ? 1 : 0); 19800 19801 /* Set RDI status for out going CCM PDUs. */ 19802 soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, SW_RDIf, 19803 sw_rdi); 19804 19805 if (soc_feature(unit, soc_feature_bhh)) { 19806 #if defined(BCM_SABER2_SUPPORT) && defined(INCLUDE_BHH) 19807 /* Send message to uC to set the Soft RDI */ 19808 if (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) { 19809 19810 /* Get the endpoint list head pointer. */ 19811 cur = *(ma_group->ep_list); 19812 19813 while (NULL != cur) { 19814 h_data_p = cur->ep_data_p; 19815 if (NULL == h_data_p) { 19816 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 19817 "OAM(unit %d) Error: Group=%d endpoints access failed -" 19818 " %s.\n"), unit, group_info->id, 19819 bcm_errmsg(BCM_E_INTERNAL))); 19820 _BCM_OAM_UNLOCK(oc); 19821 return (BCM_E_INTERNAL); 19822 } 19823 if (h_data_p->oam_domain == _BCM_SB2_OAM_DOMAIN_BHH) { 19824 /* Set the RDI flag in session bits */ 19825 session_flags |= SHR_BHH_SESS_SET_F_RDI; 19826 19827 /* Get the session is from endpoint */ 19828 msg_sess.sess_id = 19829 BCM_OAM_BHH_GET_UKERNEL_EP(h_data_p->ep_id); 19830 19831 /* Pack control message data into DMA buffer */ 19832 msg_sess.flags = session_flags; 19833 19834 buffer = oc->dma_buffer; 19835 buffer_ptr = 19836 bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess); 19837 buffer_len = buffer_ptr - buffer; 19838 19839 /* Send BHH Session Update message to uC */ 19840 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 19841 MOS_MSG_SUBCLASS_BHH_SESS_SET, 19842 buffer_len, 0, 19843 MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY, 19844 &reply_len); 19845 if (BCM_FAILURE(rv)) { 19846 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 19847 "OAM(unit %d) Error: ukernel msg failed for" 19848 "%s.\n"), unit, bcm_errmsg(rv))); 19849 _BCM_OAM_UNLOCK(oc); 19850 return (BCM_E_INTERNAL); 19851 } 19852 } 19853 cur = cur->next; 19854 } 19855 } 19856 #endif 19857 } 19858 19859 /* Enable hardware lookup for this entry. */ 19860 soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, VALIDf, 1); 19861 19862 19863 /* Write entry to hardware. */ 19864 rv = WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL, group_info->id, 19865 &maid_reduction_entry); 19866 if (BCM_FAILURE(rv)) { 19867 _BCM_OAM_UNLOCK(oc); 19868 return rv; 19869 } 19870 19871 /* 19872 * Maintenance Association State table update. 19873 */ 19874 sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t)); 19875 19876 /* 19877 * If it is a group info replace operation, retain previous group 19878 * defect status. 19879 */ 19880 if (group_info->flags & BCM_OAM_GROUP_REPLACE) { 19881 rv = READ_MA_STATEm(unit, MEM_BLOCK_ALL, group_info->id, 19882 &ma_state_entry); 19883 if (BCM_FAILURE(rv)) { 19884 _BCM_OAM_UNLOCK(oc); 19885 return rv; 19886 } 19887 } 19888 19889 /* Set the lowest alarm priority info. */ 19890 soc_MA_STATEm_field32_set(unit, &ma_state_entry, LOWESTALARMPRIf, 19891 group_info->lowest_alarm_priority); 19892 19893 /* Mark the entry as valid. */ 19894 soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, 1); 19895 19896 /* Write group information to hardware table. */ 19897 rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group_info->id, 19898 &ma_state_entry); 19899 if (BCM_FAILURE(rv)) { 19900 _BCM_OAM_UNLOCK(oc); 19901 return rv; 19902 } 19903 19904 /* Make the group as in used status. */ 19905 ma_group->in_use = 1; 19906 19907 _BCM_OAM_UNLOCK(oc); 19908 19909 #ifdef BCM_WARM_BOOT_SUPPORT 19910 SOC_CONTROL_LOCK(unit); 19911 SOC_CONTROL(unit)->scache_dirty = 1; 19912 SOC_CONTROL_UNLOCK(unit); 19913 #endif 19914 return BCM_E_NONE; 19915 } 19916 19917 /* 19918 * Function: 19919 * bcm_sb2_oam_group_get 19920 * Purpose: 19921 * Get an OAM group object 19922 * Parameters: 19923 * unit - (IN) BCM device number 19924 * group - (IN) OAM Group ID. 19925 * group_info - (OUT) Pointer to group information buffer. 19926 * Returns: 19927 * BCM_E_XXX 19928 */ 19929 int 19930 bcm_sb2_oam_group_get(int unit, bcm_oam_group_t group, 19931 bcm_oam_group_info_t *group_info) 19932 { 19933 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 19934 _bcm_oam_group_data_t *group_p; /* Pointer to group list. */ 19935 int rv; /* Operation return status. */ 19936 19937 #if defined(INCLUDE_BHH) 19938 bhh_sdk_msg_ctrl_sess_get_t msg; 19939 uint8 *buffer, *buffer_ptr; 19940 uint16 buffer_len, reply_len; 19941 _bcm_oam_hash_data_t *h_data_p; 19942 _bcm_oam_ep_list_t *cur = NULL; 19943 int sess_id = 0; 19944 #endif 19945 19946 /* Validate input parameter. */ 19947 if (NULL == group_info) { 19948 return (BCM_E_PARAM); 19949 } 19950 19951 /* Get OAM device control structure. */ 19952 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 19953 19954 /* Validate group index. */ 19955 _BCM_OAM_GROUP_INDEX_VALIDATE(group); 19956 19957 _BCM_OAM_LOCK(oc); 19958 19959 /* Check if the group is in use. */ 19960 rv = shr_idxres_list_elem_state(oc->group_pool, group); 19961 if (BCM_E_EXISTS != rv) { 19962 _BCM_OAM_UNLOCK(oc); 19963 LOG_ERROR(BSL_LS_BCM_OAM, 19964 (BSL_META_U(unit, 19965 "OAM(unit %d) Error: GID=%d - %s.\n"), 19966 unit, group, bcm_errmsg(rv))); 19967 return (rv); 19968 } 19969 19970 /* Get pointer to this group in the group list. */ 19971 group_p = oc->group_info; 19972 19973 /* Get the group information. */ 19974 rv = _bcm_sb2_oam_get_group(unit, group, group_p, group_info); 19975 if (BCM_FAILURE(rv)) { 19976 _BCM_OAM_UNLOCK(oc); 19977 LOG_ERROR(BSL_LS_BCM_OAM, 19978 (BSL_META_U(unit, 19979 "OAM(unit %d) Error: bcm_sb2_oam_group_get Group ID=%d " 19980 "- Failed.\n"), unit, group)); 19981 return (rv); 19982 } 19983 19984 if (soc_feature(unit, soc_feature_bhh)) { 19985 #if defined(INCLUDE_BHH) 19986 if (!oc->ukernel_not_ready) { 19987 group_p = &oc->group_info[group_info->id]; 19988 /* Get the endpoint list head pointer. */ 19989 if (group_p->ep_list != NULL) { 19990 cur = *(group_p->ep_list); 19991 } 19992 19993 while (NULL != cur) { 19994 h_data_p = cur->ep_data_p; 19995 if (NULL == h_data_p) { 19996 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, 19997 "OAM(unit %d) Error: Group=%d endpoints access failed -" 19998 " %s.\n"), unit, group_info->id, 19999 bcm_errmsg(BCM_E_INTERNAL))); 20000 _BCM_OAM_UNLOCK(oc); 20001 return (BCM_E_INTERNAL); 20002 } 20003 if ((h_data_p->oam_domain == _BCM_SB2_OAM_DOMAIN_BHH) && 20004 !(h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) { 20005 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(h_data_p->ep_id); 20006 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 20007 MOS_MSG_SUBCLASS_BHH_SESS_GET, 20008 sess_id, 0, 20009 MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY, 20010 &reply_len); 20011 if (BCM_FAILURE(rv)) { 20012 LOG_ERROR(BSL_LS_BCM_OAM, 20013 (BSL_META_U(unit, 20014 "OAM(unit %d) Error: ukernel msg failed for" 20015 " EP=%d %s.\n"), unit, h_data_p->ep_id, 20016 bcm_errmsg(rv))); 20017 _BCM_OAM_UNLOCK(oc); 20018 return (rv); 20019 } 20020 20021 /* Pack control message data into DMA buffer */ 20022 buffer = oc->dma_buffer; 20023 buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg); 20024 buffer_len = buffer_ptr - buffer; 20025 20026 if (reply_len != buffer_len) { 20027 rv = BCM_E_INTERNAL; 20028 LOG_ERROR(BSL_LS_BCM_OAM, 20029 (BSL_META_U(unit, 20030 "OAM(unit %d) Error: ukernel msg failed for" 20031 " EP=%d %s.\n"), unit, h_data_p->ep_id, 20032 bcm_errmsg(rv))); 20033 _BCM_OAM_UNLOCK(oc); 20034 return (rv); 20035 } else { 20036 if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){ 20037 group_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT; 20038 } 20039 if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){ 20040 group_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI; 20041 } 20042 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){ 20043 group_info->faults |= 20044 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL; 20045 } 20046 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){ 20047 group_info->faults |= 20048 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID; 20049 } 20050 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){ 20051 group_info->faults |= 20052 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID; 20053 } 20054 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){ 20055 group_info->faults |= 20056 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD; 20057 } 20058 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){ 20059 group_info->faults |= 20060 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY; 20061 } 20062 if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) { 20063 group_info->faults |= 20064 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS; 20065 } 20066 if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) { 20067 group_info->faults |= 20068 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI; 20069 } 20070 if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) { 20071 group_info->faults |= 20072 BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI; 20073 } 20074 } 20075 } 20076 cur = cur->next; 20077 } 20078 } 20079 #endif 20080 } 20081 20082 _BCM_OAM_UNLOCK(oc); 20083 return (BCM_E_NONE); 20084 } 20085 20086 /* 20087 * Function: 20088 * bcm_sb2_oam_group_destroy 20089 * Purpose: 20090 * Destroy an OAM group object and its associated endpoints. 20091 * Parameters: 20092 * unit - (IN) BCM device number 20093 * group - (IN) The ID of the OAM group object to destroy 20094 * Returns: 20095 * BCM_E_XXX 20096 */ 20097 int 20098 bcm_sb2_oam_group_destroy(int unit, 20099 bcm_oam_group_t group) 20100 { 20101 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 20102 _bcm_oam_group_data_t *g_info_p; /* Pointer to group list. */ 20103 int rv; /* Operation return status. */ 20104 maid_reduction_entry_t maid_reduction_entry; /* MAID_REDUCTION entry. */ 20105 ma_state_entry_t ma_state_entry; /* MA_STATE table entry. */ 20106 20107 /* Get OAM device control structure. */ 20108 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 20109 20110 /* Validate group index. */ 20111 _BCM_OAM_GROUP_INDEX_VALIDATE(group); 20112 20113 _BCM_OAM_LOCK(oc); 20114 20115 /* Check if the group is in use. */ 20116 rv = shr_idxres_list_elem_state(oc->group_pool, group); 20117 if (BCM_E_EXISTS != rv) { 20118 _BCM_OAM_UNLOCK(oc); 20119 LOG_ERROR(BSL_LS_BCM_OAM, 20120 (BSL_META_U(unit, 20121 "OAM(unit %d) Error: GID=%d - %s.\n"), 20122 unit, group, bcm_errmsg(rv))); 20123 return (rv); 20124 } 20125 20126 /* Get pointer to this group in the group list. */ 20127 g_info_p = &oc->group_info[group]; 20128 20129 rv = _bcm_sb2_oam_group_endpoints_destroy(unit, g_info_p); 20130 if (BCM_FAILURE(rv)) { 20131 _BCM_OAM_UNLOCK(oc); 20132 LOG_ERROR(BSL_LS_BCM_OAM, 20133 (BSL_META_U(unit, 20134 "OAM(unit %d) Error: bcm_sb2_oam_endpoint_destroy_all" 20135 " (GID=%d) - %s.\n"), unit, group, bcm_errmsg(rv))); 20136 return (rv); 20137 } 20138 20139 sal_memset(&maid_reduction_entry, 0, sizeof(maid_reduction_entry_t)); 20140 rv = WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL, group, 20141 &maid_reduction_entry); 20142 if (BCM_FAILURE(rv)) { 20143 _BCM_OAM_UNLOCK(oc); 20144 LOG_DEBUG(BSL_LS_BCM_OAM, 20145 (BSL_META_U(unit, 20146 "OAM(unit %d) Error: MAID REDUCTION write " 20147 "(GID=%d) - %s.\n"), unit, group, bcm_errmsg(rv))); 20148 return (rv); 20149 } 20150 20151 /* 20152 * Maintenance Association State table update. 20153 */ 20154 sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t)); 20155 20156 rv = WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group, &ma_state_entry); 20157 if (BCM_FAILURE(rv)) { 20158 _BCM_OAM_UNLOCK(oc); 20159 LOG_ERROR(BSL_LS_BCM_OAM, 20160 (BSL_META_U(unit, 20161 "OAM(unit %d) Error: MA STATE write " 20162 "(GID=%d) - %s.\n"), unit, group, bcm_errmsg(rv))); 20163 return (rv); 20164 } 20165 20166 /* Return Group ID back to free group. */ 20167 rv = shr_idxres_list_free(oc->group_pool, group); 20168 if (BCM_FAILURE(rv)) { 20169 _BCM_OAM_UNLOCK(oc); 20170 return (rv); 20171 } 20172 20173 #ifdef BCM_WARM_BOOT_SUPPORT 20174 SOC_CONTROL_LOCK(unit); 20175 SOC_CONTROL(unit)->scache_dirty = 1; 20176 SOC_CONTROL_UNLOCK(unit); 20177 #endif 20178 _BCM_OAM_UNLOCK(oc); 20179 return (BCM_E_NONE); 20180 } 20181 20182 /* 20183 * Function: 20184 * bcm_sb2_oam_group_destroy_all 20185 * Purpose: 20186 * Destroy all OAM group objects and their associated endpoints. 20187 * Parameters: 20188 * unit - (IN) BCM device number 20189 * Returns: 20190 * BCM_E_XXX 20191 */ 20192 int 20193 bcm_sb2_oam_group_destroy_all(int unit) 20194 { 20195 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 20196 int group; /* Maintenance Association group index. */ 20197 int rv; /* Operation return status . */ 20198 20199 /* Get device OAM control structure handle. */ 20200 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 20201 20202 _BCM_OAM_LOCK(oc); 20203 for (group = 0; group < oc->group_count; group++) { 20204 20205 /* Check if the group is in use. */ 20206 rv = shr_idxres_list_elem_state(oc->group_pool, group); 20207 if (BCM_E_EXISTS != rv) { 20208 continue; 20209 } 20210 20211 rv = bcm_sb2_oam_group_destroy(unit, group); 20212 if (BCM_FAILURE(rv)) { 20213 _BCM_OAM_UNLOCK(oc); 20214 LOG_ERROR(BSL_LS_BCM_OAM, 20215 (BSL_META_U(unit, 20216 "OAM(unit %d) Error: Group destroy failed " 20217 "(GID=%d) - %s.\n"), unit, group, bcm_errmsg(rv))); 20218 return (rv); 20219 } 20220 } 20221 20222 #ifdef BCM_WARM_BOOT_SUPPORT 20223 SOC_CONTROL_LOCK(unit); 20224 SOC_CONTROL(unit)->scache_dirty = 1; 20225 SOC_CONTROL_UNLOCK(unit); 20226 #endif 20227 20228 _BCM_OAM_UNLOCK(oc); 20229 return (BCM_E_NONE); 20230 } 20231 20232 /* 20233 * Function: 20234 * bcm_sb2_oam_group_traverse 20235 * Purpose: 20236 * Traverse the entire set of OAM groups, calling a specified 20237 * callback for each one 20238 * Parameters: 20239 * unit - (IN) BCM device number 20240 * cb - (IN) Pointer to call back function. 20241 * user_data - (IN) Pointer to user supplied data. 20242 * Returns: 20243 * BCM_E_XXX 20244 */ 20245 int 20246 bcm_sb2_oam_group_traverse(int unit, bcm_oam_group_traverse_cb cb, 20247 void *user_data) 20248 { 20249 _bcm_oam_control_t *oc; /* OAM control structure pointer. */ 20250 bcm_oam_group_info_t group_info; /* Group information to be set. */ 20251 bcm_oam_group_t grp_idx; /* MA Group index. */ 20252 _bcm_oam_group_data_t *group_p; /* Pointer to group list. */ 20253 int rv; /* Operation return status. */ 20254 20255 if (NULL == cb) { 20256 return (BCM_E_PARAM); 20257 } 20258 20259 /* Get device OAM control structure handle. */ 20260 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 20261 20262 _BCM_OAM_LOCK(oc); 20263 20264 /* Initialize to group array pointer. */ 20265 group_p = oc->group_info; 20266 20267 for (grp_idx = 0; grp_idx < oc->group_count; grp_idx++) { 20268 20269 /* Check if the group is in use. */ 20270 if (BCM_E_EXISTS 20271 == shr_idxres_list_elem_state(oc->group_pool, grp_idx)) { 20272 20273 /* Initialize the group information structure. */ 20274 bcm_oam_group_info_t_init(&group_info); 20275 20276 /* Retrieve group information and set in group_info structure. */ 20277 rv = _bcm_sb2_oam_get_group(unit, grp_idx, group_p, &group_info); 20278 if (BCM_FAILURE(rv)) { 20279 _BCM_OAM_UNLOCK(oc); 20280 LOG_ERROR(BSL_LS_BCM_OAM, 20281 (BSL_META_U(unit, 20282 "OAM(unit %d) Error: _bcm_sb2_oam_get_group " 20283 "(GID=%d) - %s.\n"), unit, grp_idx, bcm_errmsg(rv))); 20284 return (rv); 20285 } 20286 20287 /* Call the user call back routine with group information. */ 20288 rv = cb(unit, &group_info, user_data); 20289 if (BCM_FAILURE(rv)) { 20290 _BCM_OAM_UNLOCK(oc); 20291 LOG_ERROR(BSL_LS_BCM_OAM, 20292 (BSL_META_U(unit, 20293 "OAM(unit %d) Error: User call back routine " 20294 "(GID=%d) - %s.\n"), unit, grp_idx, bcm_errmsg(rv))); 20295 return (rv); 20296 } 20297 } 20298 } 20299 20300 _BCM_OAM_UNLOCK(oc); 20301 20302 return BCM_E_NONE; 20303 } 20304 20305 int 20306 _bcm_sb2_oam_mpls_lsp_label_l3_tunnel_entry_get(int unit, 20307 _bcm_oam_hash_data_t *hash_data, 20308 soc_tunnel_term_t *tnl_entry) 20309 { 20310 #if defined(INCLUDE_L3) 20311 soc_tunnel_term_t tnl_key; 20312 bcm_mpls_tunnel_switch_t tnl_info; 20313 int rv = BCM_E_NONE; 20314 int index; 20315 20316 sal_memset(&tnl_key, 0, sizeof(tnl_key)); 20317 sal_memset(&tnl_info, 0, sizeof(tnl_info)); 20318 20319 /* Forming key only based on label */ 20320 if (bcm_tr_mpls_port_independent_range(unit, hash_data->label, 20321 BCM_GPORT_INVALID) != BCM_E_NONE) { 20322 /* Use Gport as the port if label is port dependent */ 20323 tnl_info.port = hash_data->gport; 20324 } else { 20325 /* Port is invalid if label is port independent. */ 20326 tnl_info.port = BCM_GPORT_INVALID; 20327 } 20328 tnl_info.label = hash_data->label; 20329 20330 /* Setup TCAM key */ 20331 rv = _bcm_tr3_mpls_tunnel_switch_frr_entry_key_init(unit, &tnl_info, &tnl_key); 20332 BCM_IF_ERROR_RETURN(rv); 20333 20334 /* Find tunnel terminator in TCAM. */ 20335 BCM_IF_ERROR_RETURN(soc_tunnel_term_match(unit, &tnl_key, tnl_entry, &index)); 20336 return BCM_E_NONE; 20337 #endif 20338 return BCM_E_UNAVAIL; 20339 } 20340 20341 int 20342 _bcm_sb2_oam_mpls_lsp_check_l3_tunnel_table_downmep_enable(int unit, 20343 _bcm_oam_hash_data_t *hash_data, int enable) 20344 { 20345 #if defined(INCLUDE_L3) 20346 soc_tunnel_term_t tnl_entry; 20347 uint32 tnl_index = 0; 20348 int rv = BCM_E_NONE; 20349 20350 sal_memset(&tnl_entry, 0, sizeof(tnl_entry)); 20351 20352 rv = _bcm_sb2_oam_mpls_lsp_label_l3_tunnel_entry_get(unit, hash_data, 20353 &tnl_entry); 20354 if (BCM_FAILURE(rv)) { 20355 return rv; 20356 } 20357 20358 if (BHH_EP_TYPE(hash_data)) { 20359 soc_L3_TUNNELm_field32_set(unit, &tnl_entry, MPLS__MPLS_OAM_DOWNMEP_ENABLEf, 20360 enable?_BCM_SB2_MPLS_OAM_ENABLE_BHH:0); 20361 } else if (MPLS_LM_DM_ENDPOINT_TYPE(hash_data)) { 20362 soc_L3_TUNNELm_field32_set(unit, &tnl_entry, MPLS__MPLS_OAM_DOWNMEP_ENABLEf, 20363 enable?_BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM:0); 20364 } else { 20365 return BCM_E_PARAM; 20366 } 20367 20368 /* Add tunnel terminator in TCAM. It will update the entry if it is already 20369 present. which is our case. */ 20370 rv = soc_tunnel_term_insert(unit, &tnl_entry, &tnl_index); 20371 return rv; 20372 #endif 20373 return BCM_E_UNAVAIL; 20374 } 20375 20376 int 20377 _bcm_sb2_oam_mpls_entry_label_lookup(int unit, bcm_mpls_label_t label, 20378 uint32 sglp, int *mpls_index, 20379 mpls_entry_entry_t *found_entry) 20380 { 20381 #if defined(INCLUDE_L3) 20382 mpls_entry_entry_t mpls_key_entry; 20383 int rv = BCM_E_NONE; 20384 20385 sal_memset(&mpls_key_entry, 0, sizeof(mpls_key_entry)); 20386 20387 soc_MPLS_ENTRYm_field32_set(unit, &mpls_key_entry, MPLS_LABELf, label); 20388 soc_MPLS_ENTRYm_field32_set(unit, &mpls_key_entry, VALIDf, 1); 20389 if (bcm_tr_mpls_port_independent_range(unit, label, 20390 BCM_GPORT_INVALID) != BCM_E_NONE) 20391 { 20392 soc_MPLS_ENTRYm_field32_set(unit, &mpls_key_entry, PORT_NUMf, sglp); 20393 } 20394 BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit)); 20395 rv = soc_mem_search(unit, MPLS_ENTRYm, MEM_BLOCK_ANY, mpls_index, 20396 &mpls_key_entry, found_entry, 0); 20397 bcm_tr_mpls_unlock(unit); 20398 20399 return rv; 20400 #endif /* INCLUDE_L3 */ 20401 return BCM_E_UNAVAIL; 20402 } 20403 20404 int 20405 _bcm_sb2_oam_mpls_lmdm_pw_svp_get(int unit, bcm_mpls_label_t label, 20406 uint32 sglp, 20407 uint32 *svp) 20408 { 20409 mpls_entry_entry_t mpls_entry; 20410 int rv = BCM_E_NONE; 20411 int mpls_index = -1; 20412 20413 sal_memset(&mpls_entry, 0, sizeof(mpls_entry)); 20414 20415 /* Lookup for the PW label */ 20416 rv = _bcm_sb2_oam_mpls_entry_label_lookup(unit, label, sglp, 20417 &mpls_index, 20418 &mpls_entry); 20419 if(rv != BCM_E_NONE) { 20420 /* Not found or some other error */ 20421 LOG_ERROR(BSL_LS_BCM_OAM, 20422 (BSL_META_U(unit, 20423 "OAM(unit %d) Error: (Label=%u) - %s.\n"), 20424 unit, label, bcm_errmsg(rv))); 20425 return rv; 20426 } 20427 20428 /* Return error if not valid */ 20429 if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf) != 0x1)) { 20430 return (BCM_E_PARAM); 20431 } 20432 20433 *svp = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, SOURCE_VPf); 20434 20435 return BCM_E_NONE; 20436 } 20437 20438 int 20439 _bcm_sb2_oam_mpls_lsp_egr_l3_nxt_hop_downmep_enable(int unit, 20440 _bcm_oam_hash_data_t *hash_data, int enable) 20441 { 20442 #if defined(INCLUDE_L3) 20443 int egr_nh_index = 0; 20444 egr_l3_next_hop_entry_t egr_nh_entry; 20445 int rv = BCM_E_NONE; 20446 _bcm_oam_control_t *oc; 20447 #if defined(INCLUDE_BHH) 20448 uint16 bhh_lsp_key; 20449 #endif /* INCLUDE_BHH */ 20450 20451 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 20452 20453 sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry)); 20454 20455 /* Enable MPLS OAM in the EGR_L3_NEXT_HOP table */ 20456 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, hash_data->egress_if)) { 20457 egr_nh_index = hash_data->egress_if - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 20458 } 20459 else { 20460 egr_nh_index = hash_data->egress_if - BCM_XGS3_EGRESS_IDX_MIN(unit); 20461 } 20462 20463 rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, 20464 egr_nh_index, &egr_nh_entry); 20465 if (BCM_FAILURE(rv)) { 20466 return (rv); 20467 } 20468 20469 if (BHH_EP_TYPE(hash_data)) { 20470 #if defined(INCLUDE_BHH) 20471 bhh_lsp_key = enable ? BCM_OAM_BHH_GET_LSP_KEY(hash_data) : 0; 20472 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry, 20473 MPLS__MPLS_OAM_DOWNMEP_ENABLEf, 20474 enable?_BCM_SB2_MPLS_OAM_ENABLE_BHH:0); 20475 20476 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry, 20477 MPLS__MEPIDf, 20478 bhh_lsp_key); 20479 #endif /* INCLUDE_BHH */ 20480 } else if (MPLS_LM_DM_ENDPOINT_TYPE(hash_data)) { 20481 soc_EGR_L3_NEXT_HOPm_field32_set( 20482 unit, &egr_nh_entry, 20483 MPLS__MPLS_OAM_DOWNMEP_ENABLEf, 20484 enable ? _BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM : 0); 20485 20486 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry, 20487 MPLS__MEPIDf, 20488 enable ? hash_data->name : 0); 20489 } else { 20490 return BCM_E_PARAM; 20491 } 20492 20493 20494 rv = WRITE_EGR_L3_NEXT_HOPm (unit, MEM_BLOCK_ALL, 20495 egr_nh_index, &egr_nh_entry); 20496 if (BCM_FAILURE(rv)) { 20497 return (rv); 20498 } 20499 20500 return BCM_E_NONE; 20501 #endif /* INCLUDE_L3 */ 20502 return BCM_E_UNAVAIL; 20503 } 20504 20505 int 20506 _bcm_sb2_oam_mpls_pw_egr_dvp_downmep_enable(int unit, _bcm_oam_hash_data_t *hash_data, int enable) 20507 { 20508 int vp = -1; 20509 egr_dvp_attribute_entry_t entry; 20510 20511 sal_memset(&entry, 0, sizeof(entry)); 20512 20513 vp = BCM_GPORT_MPLS_PORT_ID_GET(hash_data->gport); 20514 20515 if (vp == -1) { 20516 return BCM_E_PARAM; 20517 } 20518 20519 BCM_IF_ERROR_RETURN(READ_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ANY, vp, &entry)); 20520 if (BHH_EP_TYPE(hash_data)) { 20521 soc_EGR_DVP_ATTRIBUTEm_field32_set(unit, &entry, MPLS_OAM_DOWNMEP_ENABLEf, 20522 enable?_BCM_SB2_MPLS_OAM_ENABLE_BHH:0); 20523 } else if (MPLS_LM_DM_ENDPOINT_TYPE(hash_data)) { 20524 soc_EGR_DVP_ATTRIBUTEm_field32_set(unit, &entry, MPLS_OAM_DOWNMEP_ENABLEf, 20525 enable?_BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM:0); 20526 } else { 20527 return BCM_E_PARAM; 20528 } 20529 BCM_IF_ERROR_RETURN(WRITE_EGR_DVP_ATTRIBUTEm(unit, MEM_BLOCK_ANY, vp, &entry)); 20530 20531 return BCM_E_NONE; 20532 } 20533 20534 int 20535 _bcm_sb2_oam_mpls_lsp_mpls_table_downmep_enable(int unit, _bcm_oam_hash_data_t *hash_data, int enable) 20536 { 20537 #if defined(INCLUDE_L3) 20538 mpls_entry_entry_t mpls_entry; 20539 int rv = BCM_E_NONE; 20540 int mpls_index = -1; 20541 int vccv_type = 0; 20542 20543 sal_memset(&mpls_entry, 0, sizeof(mpls_entry)); 20544 20545 /* Lookup for the LSP label */ 20546 rv = _bcm_sb2_oam_mpls_entry_label_lookup(unit, hash_data->label, 20547 hash_data->sglp, 20548 &mpls_index, 20549 &mpls_entry); 20550 if (rv != BCM_E_NONE) { 20551 /* Not found or some other error */ 20552 if ((BCM_E_NOT_FOUND == rv) && (!enable)) { 20553 LOG_VERBOSE(BSL_LS_BCM_OAM, 20554 (BSL_META_U(unit, 20555 "OAM(unit %d) Error: (EP=%d) - %s.\n"), 20556 unit, hash_data->ep_id, bcm_errmsg(rv))); 20557 } else { 20558 LOG_ERROR(BSL_LS_BCM_OAM, 20559 (BSL_META_U(unit, 20560 "OAM(unit %d) Error: (EP=%d) - %s.\n"), 20561 unit, hash_data->ep_id, bcm_errmsg(rv))); 20562 } 20563 return rv; 20564 } 20565 20566 /* Return error if not valid */ 20567 if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf) != 0x1)) { 20568 return (BCM_E_PARAM); 20569 } 20570 20571 if (BHH_EP_TYPE(hash_data)) { 20572 /* Enable/Disable BHH on this label */ 20573 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, MPLS_OAM_DOWNMEP_ENABLEf, 20574 enable?_BCM_SB2_MPLS_OAM_ENABLE_BHH:0); 20575 } else if (MPLS_LM_DM_ENDPOINT_TYPE(hash_data)) { 20576 /* Enable/Disable MPLS LMDM on this label */ 20577 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, MPLS_OAM_DOWNMEP_ENABLEf, 20578 enable?_BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM:0); 20579 } else { 20580 return BCM_E_PARAM; 20581 } 20582 20583 if (hash_data->type == bcmOAMEndpointTypeBHHMPLSVccv || 20584 hash_data->type == bcmOAMEndpointTypeMplsLmDmPw) { 20585 20586 /* Get the control channel type */ 20587 vccv_type = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, PW_CC_TYPEf); 20588 if (vccv_type == 0) { /* No VCCV type configured */ 20589 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, PW_CC_TYPEf, 20590 (hash_data->vccv_type + 1)); 20591 } else if (vccv_type != (hash_data->vccv_type + 1)) { 20592 /* Endpoint add configuration conflicts with MPLS port add config */ 20593 return BCM_E_PARAM; 20594 } 20595 } 20596 20597 /* Write the MPLS entry back into the hw */ 20598 BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit)); 20599 rv = WRITE_MPLS_ENTRYm(unit, MEM_BLOCK_ALL, mpls_index, &mpls_entry); 20600 bcm_tr_mpls_unlock(unit); 20601 20602 return rv; 20603 #endif /* INCLUDE_L3 */ 20604 return BCM_E_UNAVAIL; 20605 } 20606 20607 int 20608 _bcm_sb2_oam_mpls_pw_svp_table_downmep_enable(int unit, _bcm_oam_hash_data_t *hash_data, int enable) 20609 { 20610 #if defined(INCLUDE_L3) 20611 mpls_entry_entry_t mpls_entry; 20612 int rv = BCM_E_NONE; 20613 int mpls_index = -1; 20614 source_vp_entry_t svp_entry; 20615 int svp = 0, vccv_type = 0; 20616 20617 sal_memset(&mpls_entry, 0, sizeof(mpls_entry)); 20618 /* Lookup for PW label */ 20619 rv = _bcm_sb2_oam_mpls_entry_label_lookup(unit, hash_data->label, 20620 hash_data->sglp, 20621 &mpls_index, 20622 &mpls_entry); 20623 20624 /* If this is called during de-init, and error is not found, do not print it. 20625 * MPLS module de-init happens before OAM de-init. 20626 */ 20627 20628 if(rv != BCM_E_NONE) { 20629 /* Not found or some other error */ 20630 if ((rv != BCM_E_NOT_FOUND) || (enable)) { 20631 LOG_ERROR(BSL_LS_BCM_OAM, 20632 (BSL_META_U(unit, 20633 "OAM(unit %d) Error: (EP=%d) - %s.\n"), 20634 unit, hash_data->ep_id, bcm_errmsg(rv))); 20635 } 20636 return rv; 20637 } 20638 20639 /* Return error if not valid */ 20640 if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf) != 1)) { 20641 return (BCM_E_PARAM); 20642 } 20643 20644 /* Get the source vp table index */ 20645 svp = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, SOURCE_VPf); 20646 20647 /* Get the control channel type */ 20648 vccv_type = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, PW_CC_TYPEf); 20649 20650 BCM_IF_ERROR_RETURN(bcm_tr_mpls_lock(unit)); 20651 20652 20653 if (vccv_type == 0) { /* No VCCV type configured */ 20654 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, PW_CC_TYPEf, 20655 (hash_data->vccv_type + 1)); 20656 20657 } else if (vccv_type != (hash_data->vccv_type + 1)) { 20658 /* Endpoint add configuration conflicts with MPLS port add config */ 20659 bcm_tr_mpls_unlock(unit); 20660 return BCM_E_PARAM; 20661 } 20662 20663 20664 if(hash_data->vccv_type == bcmOamBhhVccvGal13) { 20665 /* vccv type 4. GAL over PW. */ 20666 /* So it is not bottom of the stack. so set MPLS_ACTION_IF_NOT_BOS 20667 to 5 (POP_SVP) */ 20668 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, MPLS_ACTION_IF_NOT_BOSf, 20669 enable?5:0); 20670 } 20671 20672 /* Write the MPLS entry back into the hw */ 20673 rv = WRITE_MPLS_ENTRYm(unit, MEM_BLOCK_ALL, mpls_index, 20674 &mpls_entry); 20675 if (rv != SOC_E_NONE) { 20676 bcm_tr_mpls_unlock(unit); 20677 return rv; 20678 } 20679 20680 rv = READ_SOURCE_VPm(unit, MEM_BLOCK_ANY, svp, &svp_entry); 20681 20682 if (rv < 0) { 20683 bcm_tr_mpls_unlock(unit); 20684 return rv; 20685 } 20686 20687 if (MPLS_LM_DM_ENDPOINT_TYPE(hash_data)) { 20688 /* Enable MPLS LMDM on this label */ 20689 soc_SOURCE_VPm_field32_set(unit, &svp_entry, MPLS_OAM_DOWNMEP_ENABLEf, 20690 enable?_BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM:0); 20691 } else if (BHH_EP_TYPE(hash_data)) { 20692 soc_SOURCE_VPm_field32_set(unit, &svp_entry, MPLS_OAM_DOWNMEP_ENABLEf, 20693 enable?_BCM_SB2_MPLS_OAM_ENABLE_BHH:0); 20694 } else { 20695 bcm_tr_mpls_unlock(unit); 20696 return BCM_E_PARAM; 20697 } 20698 20699 20700 rv = WRITE_SOURCE_VPm(unit, MEM_BLOCK_ALL, svp, &svp_entry); 20701 20702 if (rv < 0) { 20703 bcm_tr_mpls_unlock(unit); 20704 return rv; 20705 } 20706 20707 bcm_tr_mpls_unlock(unit); 20708 20709 return BCM_E_NONE; 20710 #endif /* INCLUDE_L3 */ 20711 return BCM_E_UNAVAIL; 20712 } 20713 20714 /* 20715 * Function: 20716 * bcm_sb2_oam_hw_ccm_tx_ctr_update 20717 * Purpose: 20718 * Update CCM CTR params 20719 * Parameters: 20720 * unit - (IN) Unit number. 20721 * ep_info - (IN) Pointer to endpoint parameters 20722 * Returns: 20723 * BCM_E_XXX 20724 * Notes: 20725 */ 20726 STATIC int 20727 bcm_sb2_oam_hw_ccm_tx_ctr_update(int unit, 20728 bcm_oam_endpoint_info_t *ep_info) 20729 { 20730 20731 _bcm_oam_hash_data_t *h_data_p; 20732 _bcm_oam_control_t *oc; 20733 int rv=BCM_E_NONE; 20734 lmep_1_entry_t lmep_1_entry; /* LMEP_1 table entry.*/ 20735 uint8 num_counter; 20736 uint32 counter_id; 20737 uint32 pool; 20738 20739 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 20740 20741 h_data_p = &oc->oam_hash_data[ep_info->id]; 20742 20743 /* Get the LMEP_1 table entry. for the endpoint*/ 20744 rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, &lmep_1_entry); 20745 if (BCM_FAILURE(rv)) { 20746 LOG_ERROR(BSL_LS_BCM_OAM, 20747 (BSL_META_U(unit, 20748 "OAM(unit %d) Error: LMEP_1 table read (index=%d) failed " 20749 "- %s.\n"), unit, h_data_p->local_tx_index, bcm_errmsg(rv))); 20750 return rv; 20751 } 20752 20753 if (_SB2_OAM_COUNTER_SIZE < ep_info->ccm_tx_update_lm_counter_size) { 20754 return BCM_E_PARAM; 20755 } 20756 20757 for(num_counter = 0; num_counter < ep_info->ccm_tx_update_lm_counter_size; 20758 num_counter++) { 20759 20760 /* Get the counter pool id */ 20761 counter_id = ep_info->ccm_tx_update_lm_counter_base_id[num_counter] + 20762 ep_info->ccm_tx_update_lm_counter_offset[num_counter]; 20763 pool = counter_id >> 24; 20764 20765 switch(pool){ 20766 case 0: 20767 /* Set Counter 1 ID and action */ 20768 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_1_IDf, 20769 (counter_id & 0xFFFF)); 20770 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_1_ACTIONf, 1); 20771 break; 20772 case 1: 20773 /* Set Counter 2 ID and action */ 20774 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_2_IDf, 20775 (counter_id & 0xFFFF)); 20776 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_2_ACTIONf, 1); 20777 break; 20778 case 2: 20779 /* Set Counter 3 ID and action */ 20780 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_3_IDf, 20781 (counter_id & 0xFFFF)); 20782 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_3_ACTIONf, 1); 20783 break; 20784 default: 20785 return BCM_E_PARAM; 20786 } 20787 20788 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 20789 /* TX counter is located in IP (0) */ 20790 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_1_LOCATIONf, 0); 20791 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_2_LOCATIONf, 0); 20792 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_3_LOCATIONf, 0); 20793 } else { 20794 /* TX counter is located in EP (1) */ 20795 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_1_LOCATIONf, 1); 20796 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_2_LOCATIONf, 1); 20797 soc_LMEP_1m_field32_set(unit, &lmep_1_entry, COUNTER_3_LOCATIONf, 1); 20798 } 20799 } 20800 20801 rv = WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, h_data_p->local_tx_index, 20802 &lmep_1_entry); 20803 if (BCM_FAILURE(rv)) { 20804 LOG_ERROR(BSL_LS_BCM_OAM, 20805 (BSL_META_U(unit, 20806 "OAM(unit %d) Error: LMEP_1 table write (EP=%d)" 20807 " failed - %s.\n"), unit, h_data_p->ep_id, bcm_errmsg(rv))); 20808 return rv; 20809 } 20810 20811 return rv; 20812 } 20813 20814 /* 20815 * Function: 20816 * bcm_sb2_oam_endpoint_lm_update 20817 * Purpose: 20818 * Update LM related params of an endpoint 20819 * Parameters: 20820 * unit - (IN) BCM device number 20821 * endpoint_info - (IN/OUT) Pointer to endpoint information buffer. 20822 * Returns: 20823 * BCM_E_XXX 20824 */ 20825 STATIC int 20826 bcm_sb2_oam_endpoint_lm_update(int unit, bcm_oam_endpoint_info_t *ep_info) 20827 { 20828 _bcm_oam_hash_data_t *h_data_p; 20829 _bcm_oam_control_t *oc; 20830 int loss_add, loss_del; 20831 int loss_configured; 20832 soc_mem_t mems[2] = {INVALIDm, INVALIDm}; 20833 uint32 lm_payload_offset = -1; 20834 uint32 lm_cos_offset = -1; 20835 bcm_oam_lm_counter_type_t lm_ctr_type = bcmOamLmCounterTypeCount; 20836 bcm_oam_lm_counter_size_t lm_ctr_sample_size = bcmOamLmCounterSizeCount; 20837 int lm_ctr_pool_id = -1; 20838 int mem_index; 20839 int ctr_field_id = -1; 20840 ing_oam_lm_counters_0_entry_t lm_entry; 20841 egr_mp_group_entry_t egr_mp_group; 20842 mp_group_entry_t mp_group_entry; 20843 20844 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 20845 20846 if (ep_info->flags & BCM_OAM_ENDPOINT_REMOTE) { 20847 /* Only LMEPs can update Loss parameters */ 20848 return BCM_E_PARAM; 20849 } 20850 20851 if (ep_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) { 20852 /* Only MEPs can update LM */ 20853 return BCM_E_PARAM; 20854 } 20855 20856 /* Validate endpoint index value. */ 20857 _BCM_OAM_EP_INDEX_VALIDATE(ep_info->id); 20858 20859 h_data_p = &oc->oam_hash_data[ep_info->id]; 20860 if (0 == h_data_p->in_use) { 20861 return BCM_E_NOT_FOUND; 20862 } 20863 20864 /* Figure out if loss is being added or deleted */ 20865 loss_add = loss_del = 0; 20866 loss_configured = 1; /* Indicates if BCM_OAM_ENDPOINT_LOSS_MEASUREMENT flag is 20867 * present in new & old config 20868 */ 20869 if (h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 20870 if (!(ep_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) { 20871 loss_del = 1; 20872 } 20873 } else { 20874 if (ep_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 20875 loss_add = 1; 20876 } else { 20877 /* BCM_OAM_ENDPOINT_LOSS_MEASUREMENT flag is not present in old/new 20878 * config. 20879 */ 20880 loss_configured = 0; 20881 } 20882 } 20883 20884 /* If loss configuration is present in either old & new configuration, then 20885 * find out if something is being modified in loss, updates will result in 20886 * delete and add. 20887 */ 20888 if (1 == loss_configured && 0 == loss_add && 0 == loss_del) { 20889 20890 lm_ctr_pool_id = (h_data_p->rx_ctr >> 24) & 0xFF; 20891 if (MPLS_LM_DM_ENDPOINT_TYPE(ep_info)) { 20892 ctr_field_id = h_data_p->egr_ctr_field_id; 20893 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_find_egr_lmep(unit, h_data_p, 20894 &mem_index, 20895 &egr_mp_group)); 20896 BCM_IF_ERROR_RETURN( 20897 _bcm_sb2_oam_lm_counters_mems_from_pool_get(lm_ctr_pool_id, 20898 mems)); 20899 /* Getting info from one of the LM Counter pools (ingress or egress) 20900 * is enough 20901 */ 20902 SOC_IF_ERROR_RETURN(soc_mem_read(unit, mems[0], MEM_BLOCK_ANY, 20903 (h_data_p->rx_ctr & 0xFFFFFF), 20904 &lm_entry)); 20905 20906 lm_ctr_type = soc_mem_field32_get(unit, mems[0], &lm_entry, 20907 LM_COUNT_TYPEf); 20908 lm_ctr_sample_size = soc_mem_field32_get(unit, mems[0], &lm_entry, 20909 LM_COUNTER_SAMPLE_SIZEf); 20910 20911 lm_payload_offset = 20912 soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, 20913 sb2_mep_ctr_info[ctr_field_id].ctr_lm_payload_offset); 20914 20915 lm_cos_offset = 20916 soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, 20917 sb2_mep_ctr_info[ctr_field_id].ctr_lm_cos_offset); 20918 } 20919 20920 if (lm_ctr_pool_id != ep_info->lm_ctr_pool_id) { 20921 loss_del = loss_add = 1; 20922 } 20923 20924 if (0 == ep_info->pri_map_id) { 20925 ep_info->pri_map_id = oc->default_pri_map_id; 20926 } 20927 if (ep_info->pri_map_id != h_data_p->pri_map_index) { 20928 loss_del = loss_add = 1; 20929 } 20930 20931 if (MPLS_LM_DM_ENDPOINT_TYPE(ep_info)) { 20932 if (lm_ctr_type != ep_info->lm_ctr_type) { 20933 loss_del = loss_add = 1; 20934 } 20935 20936 if (lm_ctr_sample_size != ep_info->lm_ctr_sample_size) { 20937 loss_del = loss_add = 1; 20938 } 20939 20940 if (lm_payload_offset != ep_info->lm_payload_offset) { 20941 loss_del = loss_add = 1; 20942 } 20943 20944 if (lm_cos_offset != ep_info->lm_cos_offset) { 20945 loss_del = loss_add = 1; 20946 } 20947 } 20948 } 20949 20950 if (1 == loss_del) { 20951 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_find_lmep(unit, h_data_p, &mem_index, 20952 &mp_group_entry)); 20953 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_clear_counter(unit, MP_GROUPm, 20954 mem_index, h_data_p, 20955 (void *)&mp_group_entry)); 20956 20957 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_find_egr_lmep(unit, h_data_p, 20958 &mem_index, 20959 &egr_mp_group)); 20960 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_clear_counter(unit, EGR_MP_GROUPm, 20961 mem_index, h_data_p, 20962 (void *)&egr_mp_group)); 20963 h_data_p->flags &= ~BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 20964 } 20965 20966 if (1 == loss_add) { 20967 h_data_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 20968 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_lmep_counters_set(unit, ep_info)); 20969 } 20970 20971 if(ep_info->type == bcmOAMEndpointTypeEthernet) { 20972 if((ep_info->ccm_tx_update_lm_counter_size) && 20973 (_BCM_OAM_INVALID_INDEX != h_data_p->local_tx_index)) { 20974 BCM_IF_ERROR_RETURN(bcm_sb2_oam_hw_ccm_tx_ctr_update(unit, ep_info)); 20975 } 20976 } 20977 /* Update ctrs incremented/sampled by CCM */ 20978 #if defined(INCLUDE_BHH) 20979 if(BHH_EP_TYPE(h_data_p)) { 20980 BCM_IF_ERROR_RETURN(bcm_sb2_oam_bhh_endpoint_ccm_ctr_update(unit, 20981 ep_info)); 20982 } 20983 #endif /* INCLUDE_BHH */ 20984 20985 return BCM_E_NONE; 20986 } 20987 20988 /* 20989 * Function: 20990 * bcm_sb2_oam_endpoint_create 20991 * Purpose: 20992 * Create or replace an OAM endpoint object 20993 * Parameters: 20994 * unit - (IN) BCM device number 20995 * endpoint_info - (IN/OUT) Pointer to endpoint information buffer. 20996 * Returns: 20997 * BCM_E_XXX 20998 */ 20999 int 21000 bcm_sb2_oam_endpoint_create(int unit, bcm_oam_endpoint_info_t *endpoint_info) 21001 { 21002 _bcm_oam_hash_data_t *hash_data = NULL; /* Endpoint hash data pointer. */ 21003 _bcm_oam_hash_key_t hash_key; /* Hash Key buffer. */ 21004 int ep_req_index; /* Requested endpoint index. */ 21005 int rv; /* Operation return status. */ 21006 _bcm_oam_control_t *oc; /* Pointer to OAM control */ 21007 /* structure. */ 21008 uint32 sglp = 0; /* Source global logical port. */ 21009 uint32 dglp = 0; /* Dest global logical port. */ 21010 uint32 svp = 0; /* Source virtual port */ 21011 bcm_port_t src_pp_port = 0; /* Source pp port. */ 21012 bcm_port_t dst_pp_port = 0; /* Dest pp port. */ 21013 int mep_ccm_tx = 0; /* Endpoint CCM Tx status. */ 21014 int mep_ccm_rx = 0; /* Endpoint CCM Rx status. */ 21015 int remote = 0; /* Remote endpoint status. */ 21016 int up_mep = 0; /* Endpoint is an upMep */ 21017 int key_type = 0; 21018 port_tab_entry_t port_entry; 21019 int oam_key1 = 0; 21020 int oam_key2 = 0; 21021 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 21022 bcm_trunk_member_t trunk_member = {0}; 21023 #if defined(INCLUDE_L3) 21024 bcm_mpls_port_t mpls_port; 21025 #endif 21026 int is_vp_valid = 0; 21027 LOG_DEBUG(BSL_LS_BCM_OAM, 21028 (BSL_META_U(unit, 21029 "OAM(unit %d) Info: bcm_sb2_oam_endpoint_create " 21030 "Endpoint ID=%d.\n"), unit, endpoint_info->id)); 21031 21032 /* Validate input parameter. */ 21033 if (NULL == endpoint_info) { 21034 return (BCM_E_PARAM); 21035 } 21036 /* Get OAM Control Structure. */ 21037 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 21038 21039 _BCM_OAM_LOCK(oc); 21040 21041 #if defined(KEY_PRINT) 21042 _bcm_oam_hash_key_print(&hash_key); 21043 #endif 21044 21045 /* Calculate the hash key for given enpoint input parameters. */ 21046 _bcm_sb2_oam_ep_hash_key_construct(unit, oc, endpoint_info, &hash_key); 21047 21048 /* Validate endpoint input parameters. */ 21049 rv = _bcm_sb2_oam_endpoint_params_validate(unit, oc, &hash_key, 21050 endpoint_info); 21051 if (BCM_FAILURE(rv)) { 21052 LOG_ERROR(BSL_LS_BCM_OAM, 21053 (BSL_META_U(unit, 21054 "OAM(unit %d) Error: (EP=%d) - %s.\n"), 21055 unit, endpoint_info->id, bcm_errmsg(rv))); 21056 _BCM_OAM_UNLOCK(oc); 21057 return (rv); 21058 } 21059 21060 if ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) && 21061 (endpoint_info->flags2 & BCM_OAM_ENDPOINT2_UPDATE_COUNTER_ACTION)) { 21062 /* Update LM parameters */ 21063 rv = bcm_sb2_oam_endpoint_lm_update(unit, endpoint_info); 21064 _BCM_OAM_UNLOCK(oc); 21065 return rv; 21066 } 21067 21068 if(soc_feature(unit, soc_feature_bhh)) { 21069 #if defined(INCLUDE_BHH) 21070 if(BHH_EP_TYPE(endpoint_info)) 21071 { 21072 if ((oc->ukernel_not_ready == 1) && 21073 (!(endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU))){ 21074 LOG_ERROR(BSL_LS_BCM_OAM, 21075 (BSL_META_U(unit, 21076 "OAM(unit %d) Error: BTE(ukernel) " 21077 "not ready.\n"), unit)); 21078 _BCM_OAM_UNLOCK(oc); 21079 return (BCM_E_INIT); 21080 } 21081 21082 rv = bcm_sb2_oam_bhh_endpoint_create(unit, endpoint_info, &hash_key); 21083 if (BCM_FAILURE(rv)) { 21084 LOG_ERROR(BSL_LS_BCM_OAM, 21085 (BSL_META_U(unit, 21086 "OAM(unit %d) Error: BHH Endpoint create (EP=%d) - %s.\n"), 21087 unit, endpoint_info->id, bcm_errmsg(rv))); 21088 } 21089 _BCM_OAM_UNLOCK(oc); 21090 21091 return (rv); 21092 } 21093 #endif /* INCLUDE_BHH */ 21094 } 21095 21096 /* Get MEP remote endpoint status. */ 21097 remote = (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0; 21098 21099 /* For remote endpoints gport is not required. 21100 Only group and MEP ID info is required. */ 21101 if (!remote) { 21102 /* Resolve given endpoint gport value to Source GLP and Dest GLP values. */ 21103 rv = _bcm_sb2_oam_endpoint_gport_resolve(unit, endpoint_info, &sglp, &dglp, 21104 &src_pp_port, &dst_pp_port, &svp, &trunk_id, 21105 &is_vp_valid, &trunk_member); 21106 21107 if (BCM_FAILURE(rv)) { 21108 LOG_ERROR(BSL_LS_BCM_OAM, 21109 (BSL_META_U(unit, 21110 "OAM(unit %d) Error: Gport resolve (EP=%d) - %s.\n"), 21111 unit, endpoint_info->id, bcm_errmsg(rv))); 21112 _BCM_OAM_UNLOCK(oc); 21113 return (rv); 21114 } 21115 } 21116 21117 /* Get MEP CCM Tx status. */ 21118 mep_ccm_tx 21119 = ((endpoint_info->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) 21120 ? 1 : 0); 21121 21122 /* Get MEP CCM Rx status. */ 21123 mep_ccm_rx 21124 = ((endpoint_info->flags & _BCM_OAM_EP_RX_ENABLE) ? 1 : 0); 21125 /* The rx settings need to be enabled for MPLS LM DM endpoints as well */ 21126 if (MPLS_LM_DM_ENDPOINT_TYPE(endpoint_info)) { 21127 mep_ccm_rx = 1; 21128 } 21129 21130 21131 /* Check whether up/down MEP */ 21132 if (endpoint_info->flags & BCM_OAM_ENDPOINT_UP_FACING) { 21133 up_mep = 1; 21134 } 21135 /* Set the search key type. */ 21136 _bcm_sb2_oam_key_type_from_endpoint_get(endpoint_info->type, 21137 endpoint_info->flags, 21138 endpoint_info->vlan, 21139 endpoint_info->inner_vlan, 21140 is_vp_valid?_BCM_OAM_ENDPOINT_IS_VP_BASED:0, 21141 &key_type); 21142 21143 /* We need to set the OAM_KEY1 and OAM_KEY2 fields of the PORT_TABLE and 21144 EGR_PORT_TABLE based on the key_type of OAM */ 21145 if (trunk_id != BCM_TRUNK_INVALID) { 21146 rv = soc_mem_read(unit, PORT_TABm, MEM_BLOCK_ANY, 21147 src_pp_port, &port_entry); 21148 if (BCM_FAILURE(rv)) { 21149 LOG_ERROR(BSL_LS_BCM_OAM, 21150 (BSL_META_U(unit, 21151 "OAM(unit %d) Error: Endpoint create (EP=%d) - %s.\n"), 21152 unit, endpoint_info->id, bcm_errmsg(rv))); 21153 _BCM_OAM_UNLOCK(oc); 21154 return (rv); 21155 } 21156 21157 oam_key1 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY1f); 21158 oam_key2 = soc_PORT_TABm_field32_get(unit, &port_entry, OAM_KEY2f); 21159 21160 if (key_type != _BCM_OAM_DOMAIN_PORT) { 21161 if ((oam_key1 > 0) && (oam_key2 > 0)) { 21162 if ((oam_key1 == key_type) || (oam_key2 == key_type)) { 21163 } else { 21164 LOG_ERROR(BSL_LS_BCM_OAM, 21165 (BSL_META_U(unit, 21166 "OAM(unit %d) Error: Invalid OAM domain to " 21167 "resolve (EP=%d) - %s.\n"), 21168 unit, endpoint_info->id, bcm_errmsg(rv))); 21169 _BCM_OAM_UNLOCK(oc); 21170 return (BCM_E_PARAM); 21171 } 21172 } 21173 } 21174 } 21175 21176 /* For Downmep CCM tx purposes, int_pri variable is used like a cosq. 21177 * Hence verify if it is in the valid range, Else return error. 21178 * For UPMEP CCM tx purposes, int_pri is used as internal priority only. 21179 * Hence verify if it is in valid range of internal priority 21180 */ 21181 if (mep_ccm_tx && !up_mep && 21182 (!BCM_COSQ_QUEUE_VALID(unit, endpoint_info->int_pri))) { 21183 _BCM_OAM_UNLOCK(oc); 21184 return (BCM_E_PARAM); 21185 } else if (mep_ccm_tx && up_mep && 21186 (!(endpoint_info->int_pri >= 0 && endpoint_info->int_pri < BCM_OAM_INTPRI_MAX))) { 21187 _BCM_OAM_UNLOCK(oc); 21188 return (BCM_E_PARAM); 21189 } 21190 21191 /* Replace an existing endpoint. */ 21192 if (endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) { 21193 21194 rv = _bcm_sb2_oam_endpoint_destroy(unit, endpoint_info->id); 21195 if (BCM_FAILURE(rv)) { 21196 LOG_ERROR(BSL_LS_BCM_OAM, 21197 (BSL_META_U(unit, 21198 "OAM(unit %d) Error: Endpoint destroy (EP=%d) - %s.\n"), 21199 unit, endpoint_info->id, bcm_errmsg(rv))); 21200 _BCM_OAM_UNLOCK(oc); 21201 return (rv); 21202 } 21203 } 21204 21205 /* Create a new endpoint with the requested ID. */ 21206 if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) { 21207 ep_req_index = endpoint_info->id; 21208 rv = shr_idxres_list_reserve(oc->mep_pool, ep_req_index, 21209 ep_req_index); 21210 if (BCM_FAILURE(rv)) { 21211 LOG_ERROR(BSL_LS_BCM_OAM, 21212 (BSL_META_U(unit, 21213 "OAM(unit %d) Error: Endpoint reserve (EP=%d) - %s.\n"), 21214 unit, endpoint_info->id, bcm_errmsg(rv))); 21215 _BCM_OAM_UNLOCK(oc); 21216 return ((rv == BCM_E_RESOURCE) ? BCM_E_EXISTS : rv); 21217 } 21218 } else { 21219 /* Allocate the next available endpoint index. */ 21220 rv = shr_idxres_list_alloc(oc->mep_pool, 21221 (shr_idxres_element_t *)&ep_req_index); 21222 if (BCM_FAILURE(rv)) { 21223 LOG_ERROR(BSL_LS_BCM_OAM, 21224 (BSL_META_U(unit, 21225 "OAM(unit %d) Error: Endpoint alloc failed - %s.\n"), 21226 unit, bcm_errmsg(rv))); 21227 _BCM_OAM_UNLOCK(oc); 21228 return (rv); 21229 } 21230 /* Set the allocated endpoint id value. */ 21231 endpoint_info->id = ep_req_index; 21232 } 21233 21234 /* Get the hash data pointer where the data is to be stored. */ 21235 hash_data = &oc->oam_hash_data[ep_req_index]; 21236 21237 /* Clear the hash data element contents before storing the values. */ 21238 _BCM_OAM_HASH_DATA_CLEAR(hash_data); 21239 hash_data->type = endpoint_info->type; 21240 hash_data->vccv_type = endpoint_info->vccv_type; 21241 hash_data->ep_id = endpoint_info->id; 21242 hash_data->is_remote = remote; 21243 hash_data->local_tx_enabled = mep_ccm_tx; 21244 hash_data->local_rx_enabled = mep_ccm_rx; 21245 hash_data->group_index = endpoint_info->group; 21246 hash_data->name = endpoint_info->name; 21247 if (MPLS_LM_DM_ENDPOINT_TYPE(endpoint_info)) { 21248 /* For MPLS LM DM endpoints, the mdl level 21249 * should be hard coded to 7 21250 */ 21251 endpoint_info->level = 7; 21252 } 21253 hash_data->level = endpoint_info->level; 21254 hash_data->vlan = endpoint_info->vlan; 21255 hash_data->inner_vlan = endpoint_info->inner_vlan; 21256 hash_data->gport = endpoint_info->gport; 21257 hash_data->sglp = sglp; 21258 hash_data->dglp = dglp; 21259 hash_data->src_pp_port = src_pp_port; 21260 hash_data->dst_pp_port = dst_pp_port; 21261 hash_data->flags = endpoint_info->flags; 21262 hash_data->flags2 = endpoint_info->flags2; 21263 hash_data->tx_gport = endpoint_info->tx_gport; 21264 hash_data->opcode_flags = ( endpoint_info->opcode_flags & 21265 _BCM_SB2_OAM_OPCODE_MASK ); 21266 hash_data->period = endpoint_info->ccm_period; 21267 hash_data->in_use = 1; 21268 hash_data->oam_domain = key_type; 21269 hash_data->outer_tpid = endpoint_info->outer_tpid; 21270 hash_data->inner_tpid = endpoint_info->inner_tpid; 21271 hash_data->subport_tpid = endpoint_info->subport_tpid; 21272 hash_data->vpn = endpoint_info->vpn; 21273 hash_data->int_pri = endpoint_info->int_pri; 21274 hash_data->trunk_index = endpoint_info->trunk_index; 21275 21276 if ((MPLS_LM_DM_ENDPOINT_TYPE(endpoint_info)) && 21277 (!MPLS_LM_DM_SECTION_ENDPOINT_TYPE(endpoint_info))) { 21278 if (MPLS_LM_DM_PW_ENDPOINT_TYPE(endpoint_info)) { 21279 #if defined(INCLUDE_L3) 21280 bcm_mpls_port_t_init(&mpls_port); 21281 mpls_port.mpls_port_id = hash_data->gport; 21282 rv = bcm_esw_mpls_port_get(unit, hash_data->vpn, 21283 &mpls_port); 21284 if (BCM_FAILURE(rv)) { 21285 LOG_ERROR(BSL_LS_BCM_OAM, 21286 (BSL_META_U(unit, 21287 "OAM(unit %d) Error: MPLS port get failed - %s.\n"), 21288 unit, bcm_errmsg(rv))); 21289 _BCM_OAM_UNLOCK(oc); 21290 return (rv); 21291 } 21292 hash_data->egress_if = mpls_port.egress_tunnel_if; 21293 hash_data->label = mpls_port.match_label; 21294 #endif 21295 } else { 21296 hash_data->label = endpoint_info->mpls_label; 21297 hash_data->egress_if = endpoint_info->intf_id; 21298 } 21299 } 21300 if (is_vp_valid) { 21301 hash_data->vp = svp; 21302 if (endpoint_info->flags & BCM_OAM_ENDPOINT_UP_FACING) { 21303 /* For implementation of VP based lookup on egress side (UP MEP) 21304 * We need to set EGR_DVP_ATTRIBUTE OAM_KEY3 = 1. 21305 */ 21306 rv = bcm_esw_port_control_set(unit, endpoint_info->gport, 21307 bcmPortControlOamLookupWithDvp, 21308 1); 21309 if (BCM_FAILURE(rv)) { 21310 _BCM_OAM_UNLOCK(oc); 21311 return (rv); 21312 } 21313 } 21314 hash_data->int_flags |= _BCM_OAM_ENDPOINT_IS_VP_BASED; 21315 } 21316 hash_data->trunk_id = trunk_id; 21317 21318 if (BCM_GPORT_IS_TRUNK(endpoint_info->gport)) { 21319 hash_data->resolved_trunk_gport = trunk_member.gport; 21320 } 21321 #if defined(INCLUDE_ETH_LM_DM) || defined (INCLUDE_MPLS_LM_DM) 21322 memcpy(hash_data->src_mac_address, endpoint_info->src_mac_address, 21323 sizeof(bcm_mac_t)); 21324 memcpy(hash_data->dst_mac_address, endpoint_info->dst_mac_address, 21325 sizeof(bcm_mac_t)); 21326 #endif 21327 #if defined (INCLUDE_MPLS_LM_DM) 21328 if ( MPLS_LM_DM_ENDPOINT_TYPE(hash_data) ) { 21329 hash_data->egr_label = endpoint_info->egress_label.label; 21330 hash_data->egr_label_exp = endpoint_info->egress_label.exp; 21331 hash_data->egr_label_ttl = endpoint_info->egress_label.ttl; 21332 } 21333 #endif 21334 21335 /* Initialize hardware index as invalid indices. */ 21336 hash_data->local_tx_index = _BCM_OAM_INVALID_INDEX; 21337 hash_data->local_rx_index = _BCM_OAM_INVALID_INDEX; 21338 hash_data->remote_index = _BCM_OAM_INVALID_INDEX; 21339 hash_data->rx_ctr = _BCM_OAM_INVALID_INDEX; 21340 hash_data->tx_ctr = _BCM_OAM_INVALID_INDEX; 21341 hash_data->profile_index = _BCM_OAM_INVALID_INDEX; 21342 hash_data->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 21343 hash_data->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 21344 hash_data->pri_map_index = _BCM_OAM_INVALID_INDEX; 21345 hash_data->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 21346 hash_data->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 21347 hash_data->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 21348 hash_data->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 21349 hash_data->ma_base_index = _BCM_OAM_INVALID_INDEX; 21350 hash_data->pm_profile_attached = _BCM_OAM_INVALID_INDEX; 21351 hash_data->ctr_field_id = _BCM_OAM_INVALID_INDEX; 21352 hash_data->egr_ctr_field_id = _BCM_OAM_INVALID_INDEX; 21353 21354 if (1 == remote) { 21355 /* Allocate the next available index for RMEP table. */ 21356 rv = shr_idxres_list_alloc 21357 (oc->rmep_pool, 21358 (shr_idxres_element_t *)&hash_data->remote_index); 21359 if (BCM_FAILURE(rv)) { 21360 _BCM_OAM_UNLOCK(oc); 21361 LOG_ERROR(BSL_LS_BCM_OAM, 21362 (BSL_META_U(unit, 21363 "OAM(unit %d) Error: RMEP index alloc failed EP:%d %s.\n"), 21364 unit, endpoint_info->id, bcm_errmsg(rv))); 21365 return (rv); 21366 } 21367 } else { 21368 /* Allocate the next available index for LMEP table. */ 21369 if (1 == mep_ccm_tx) { 21370 rv = shr_idxres_list_alloc 21371 (oc->lmep_pool, 21372 (shr_idxres_element_t *)&hash_data->local_tx_index); 21373 if (BCM_FAILURE(rv)) { 21374 _BCM_OAM_UNLOCK(oc); 21375 LOG_ERROR(BSL_LS_BCM_OAM, 21376 (BSL_META_U(unit, 21377 "OAM(unit %d) Error: LMEP Tx index alloc failed EP:%d " 21378 "%s.\n"), unit, endpoint_info->id, bcm_errmsg(rv))); 21379 return (rv); 21380 } 21381 } 21382 21383 /* Allocate the next available index for MA_INDEX table. */ 21384 if (1 == mep_ccm_rx) { 21385 /* check up or down MEP */ 21386 if (1 == up_mep) { 21387 rv = _bcm_sb2_oam_upmep_rx_endpoint_reserve(unit, 21388 endpoint_info); 21389 if (BCM_FAILURE(rv)) { 21390 if (1 == mep_ccm_tx) { 21391 /* Return Tx index to the LMEP pool. */ 21392 shr_idxres_list_free(oc->lmep_pool, 21393 hash_data->local_tx_index); 21394 } 21395 21396 /* Return endpoint index to MEP pool. */ 21397 shr_idxres_list_free(oc->mep_pool, endpoint_info->id); 21398 21399 _BCM_OAM_UNLOCK(oc); 21400 LOG_ERROR(BSL_LS_BCM_OAM, 21401 (BSL_META_U(unit, 21402 "OAM(unit %d) Error: LMEP Rx index alloc failed " 21403 "EP:%d " "%s.\n"), unit, 21404 endpoint_info->id, bcm_errmsg(rv))); 21405 return (rv); 21406 } 21407 } else { /* down Mep */ 21408 rv = _bcm_sb2_oam_downmep_rx_endpoint_reserve(unit, 21409 endpoint_info); 21410 if (BCM_FAILURE(rv)) { 21411 if (1 == mep_ccm_tx) { 21412 /* Return Tx index to the LMEP pool. */ 21413 shr_idxres_list_free(oc->lmep_pool, 21414 hash_data->local_tx_index); 21415 } 21416 21417 /* Return endpoint index to MEP pool. */ 21418 shr_idxres_list_free(oc->mep_pool, endpoint_info->id); 21419 21420 _BCM_OAM_UNLOCK(oc); 21421 LOG_ERROR(BSL_LS_BCM_OAM, 21422 (BSL_META_U(unit, 21423 "OAM(unit %d) Error: LMEP Rx index alloc " 21424 "failed EP:%d " "%s.\n"), unit, endpoint_info->id, 21425 bcm_errmsg(rv))); 21426 return (rv); 21427 } 21428 } 21429 } 21430 } 21431 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, hash_data); 21432 if (BCM_FAILURE(rv)) { 21433 LOG_ERROR(BSL_LS_BCM_OAM, 21434 (BSL_META_U(unit, 21435 "OAM(unit %d) Error: Hash table insert failed EP=%d %s.\n"), 21436 unit, endpoint_info->id, bcm_errmsg(rv))); 21437 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 21438 _BCM_OAM_UNLOCK(oc); 21439 return (rv); 21440 } 21441 21442 if (1 == remote) { 21443 rv = _bcm_oam_sb2_remote_mep_hw_set(unit, endpoint_info); 21444 if (BCM_FAILURE(rv)) { 21445 LOG_DEBUG(BSL_LS_BCM_OAM, 21446 (BSL_META_U(unit, 21447 "OAM(unit %d) Error: Remote MEP set failed EP=%d %s.\n"), 21448 unit, endpoint_info->id, bcm_errmsg(rv))); 21449 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 21450 _BCM_OAM_UNLOCK(oc); 21451 return (rv); 21452 } 21453 } else { 21454 if (mep_ccm_rx) { 21455 rv = _bcm_sb2_oam_local_rx_mep_hw_set(unit, endpoint_info); 21456 if (BCM_FAILURE(rv)) { 21457 LOG_ERROR(BSL_LS_BCM_OAM, 21458 (BSL_META_U(unit, 21459 "OAM(unit %d) Error: Rx config failed for EP=%d %s.\n"), 21460 unit, endpoint_info->id, bcm_errmsg(rv))); 21461 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, 21462 hash_key, hash_data); 21463 _BCM_OAM_UNLOCK(oc); 21464 return (rv); 21465 } 21466 } 21467 if (mep_ccm_tx) { 21468 rv = _bcm_oam_sb2_local_tx_mep_hw_set(unit, endpoint_info); 21469 if (BCM_FAILURE(rv)) { 21470 LOG_ERROR(BSL_LS_BCM_OAM, 21471 (BSL_META_U(unit, 21472 "OAM(unit %d) Error: Tx config failed for EP=%d %s.\n"), 21473 unit, endpoint_info->id, bcm_errmsg(rv))); 21474 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, 21475 hash_key, hash_data); 21476 _BCM_OAM_UNLOCK(oc); 21477 return (rv); 21478 } 21479 } 21480 21481 if (MPLS_LM_DM_LSP_ENDPOINT_TYPE(endpoint_info)) { 21482 /* For rx enable the mpls oam for the label. */ 21483 21484 /* First check if the label is in l3 tunnel table and enable 21485 MPLS OAM if true. */ 21486 rv = _bcm_sb2_oam_mpls_lsp_check_l3_tunnel_table_downmep_enable(unit, 21487 hash_data, 1); 21488 if (rv == BCM_E_NOT_FOUND) { 21489 /* If not found in L3 tunnel, find and update it in MPLS_ENTRY 21490 table */ 21491 rv = _bcm_sb2_oam_mpls_lsp_mpls_table_downmep_enable(unit, 21492 hash_data, 1); 21493 if (BCM_FAILURE(rv)) { 21494 LOG_ERROR(BSL_LS_BCM_OAM, 21495 (BSL_META_U(unit, 21496 "OAM(unit %d) Error: MPLS table update failed (EP=%d) - %s.\n"), 21497 unit, endpoint_info->id, bcm_errmsg(rv))); 21498 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 21499 _BCM_OAM_UNLOCK(oc); 21500 return (rv); 21501 } 21502 } else if (rv != BCM_E_NONE) { 21503 LOG_ERROR(BSL_LS_BCM_OAM, 21504 (BSL_META_U(unit, 21505 "OAM(unit %d) Error: L3 tunnel table update failed (EP=%d) - %s.\n"), 21506 unit, endpoint_info->id, bcm_errmsg(rv))); 21507 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 21508 _BCM_OAM_UNLOCK(oc); 21509 return (rv); 21510 } 21511 /* For tx enable the mpls oam for the egress intf. 21512 and write the mepid in egr_l3_next_hop table */ 21513 rv = _bcm_sb2_oam_mpls_lsp_egr_l3_nxt_hop_downmep_enable(unit, 21514 hash_data, 1); 21515 if (BCM_FAILURE(rv)) { 21516 LOG_ERROR(BSL_LS_BCM_OAM, 21517 (BSL_META_U(unit, 21518 "OAM(unit %d) Error: EGR_L3_NEXT_HOP table update failed (EP=%d) - %s.\n"), 21519 unit, endpoint_info->id, bcm_errmsg(rv))); 21520 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 21521 _BCM_OAM_UNLOCK(oc); 21522 return (rv); 21523 } 21524 } else if (MPLS_LM_DM_PW_ENDPOINT_TYPE(endpoint_info)) { 21525 rv = _bcm_sb2_oam_mpls_pw_svp_table_downmep_enable(unit, 21526 hash_data, 1); 21527 if (BCM_FAILURE(rv)) { 21528 LOG_ERROR(BSL_LS_BCM_OAM, 21529 (BSL_META_U(unit, 21530 "OAM(unit %d) Error: SVP table update failed (EP=%d) - %s.\n"), 21531 unit, endpoint_info->id, bcm_errmsg(rv))); 21532 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 21533 _BCM_OAM_UNLOCK(oc); 21534 return (rv); 21535 } 21536 /* For tx enable the mpls oam for the egress dvp. 21537 */ 21538 rv = _bcm_sb2_oam_mpls_pw_egr_dvp_downmep_enable(unit, hash_data, 1); 21539 if (BCM_FAILURE(rv)) { 21540 LOG_ERROR(BSL_LS_BCM_OAM, 21541 (BSL_META_U(unit, 21542 "OAM(unit %d) Error: EGR_L3_NEXT_HOP table update failed (EP=%d) - %s.\n"), 21543 unit, endpoint_info->id, bcm_errmsg(rv))); 21544 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 21545 _BCM_OAM_UNLOCK(oc); 21546 return (rv); 21547 } 21548 } else { 21549 /* Ethernet OAM and MPLS Section OAM */ 21550 rv = _bcm_sb2_oam_port_table_key_update(unit, PORT_TABm, hash_data); 21551 if (BCM_FAILURE(rv)) { 21552 LOG_ERROR(BSL_LS_BCM_OAM, 21553 (BSL_META_U(unit, 21554 "OAM(unit %d) Error: Endpoint create (EP=%d) - %s.\n"), 21555 unit, endpoint_info->id, bcm_errmsg(rv))); 21556 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 21557 _BCM_OAM_UNLOCK(oc); 21558 return (rv); 21559 } 21560 rv = _bcm_sb2_oam_port_table_key_update(unit, EGR_PORTm, hash_data); 21561 if (BCM_FAILURE(rv)) { 21562 LOG_ERROR(BSL_LS_BCM_OAM, 21563 (BSL_META_U(unit, 21564 "OAM(unit %d) Error: Endpoint create (EP=%d) - %s.\n"), 21565 unit, endpoint_info->id, bcm_errmsg(rv))); 21566 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 21567 _BCM_OAM_UNLOCK(oc); 21568 return (rv); 21569 } 21570 } 21571 /* Set OAM LM cng and cpu data control from LM flags*/ 21572 if(hash_data->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 21573 _bcm_sb2_oam_lm_cng_cpu_ctrl_set(unit, endpoint_info); 21574 } 21575 } 21576 21577 rv = _bcm_sb2_oam_group_ep_list_add(unit, endpoint_info->group, 21578 endpoint_info->id); 21579 if (BCM_FAILURE(rv)) { 21580 LOG_ERROR(BSL_LS_BCM_OAM, 21581 (BSL_META_U(unit, 21582 "OAM(unit %d) Error: failed to add entry to ep list " 21583 "for EP=%d %s.\n"), unit, endpoint_info->id, bcm_errmsg(rv))); 21584 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 21585 _BCM_OAM_UNLOCK(oc); 21586 return (rv); 21587 } 21588 21589 rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_add(unit, hash_data); 21590 if (BCM_FAILURE(rv)) { 21591 LOG_ERROR(BSL_LS_BCM_OAM, 21592 (BSL_META_U(unit, 21593 "OAM(unit %d) Error: failed to add mapping to ma_idx_to_ep_id list " 21594 "for EP=%d %s.\n"), unit, endpoint_info->id, bcm_errmsg(rv))); 21595 _bcm_sb2_oam_endpoint_cleanup(unit, up_mep, hash_key, hash_data); 21596 _BCM_OAM_UNLOCK(oc); 21597 return (rv); 21598 } 21599 _BCM_OAM_UNLOCK(oc); 21600 21601 #ifdef BCM_WARM_BOOT_SUPPORT 21602 SOC_CONTROL_LOCK(unit); 21603 SOC_CONTROL(unit)->scache_dirty = 1; 21604 SOC_CONTROL_UNLOCK(unit); 21605 #endif 21606 21607 return (BCM_E_NONE); 21608 } 21609 21610 /* 21611 * Function: 21612 * bcm_sb2_oam_hw_ccm_tx_ctr_get 21613 * Purpose: 21614 * Update CCM CTR params 21615 * Parameters: 21616 * unit - (IN) Unit number. 21617 * lmep_1_entry - (IN) lemp_1 entry read from HW 21618 * ep_info - (OUT) Pointer to get endpoint parameters 21619 * Returns: 21620 * BCM_E_XXX 21621 * Notes: 21622 */ 21623 void 21624 bcm_sb2_oam_hw_ccm_tx_ctr_get(int unit, 21625 lmep_1_entry_t *lmep_1_entry, 21626 bcm_oam_endpoint_info_t *endpoint_info) 21627 { 21628 int num_counter = 0; 21629 uint32 counter_base_id = 0; 21630 21631 if(soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_1_ACTIONf)) { 21632 21633 counter_base_id = soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_1_IDf); 21634 endpoint_info->ccm_tx_update_lm_counter_base_id[0] = (counter_base_id & 0xFFF8); 21635 endpoint_info->ccm_tx_update_lm_counter_offset[0] = counter_base_id % 8; 21636 num_counter++; 21637 } 21638 21639 if(soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_2_ACTIONf)) { 21640 21641 counter_base_id = soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_2_IDf); 21642 endpoint_info->ccm_tx_update_lm_counter_base_id[1] = (counter_base_id & 0xFFF8) + (1 << 24); 21643 endpoint_info->ccm_tx_update_lm_counter_offset[1] = counter_base_id % 8; 21644 num_counter++; 21645 } 21646 21647 if(soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_3_ACTIONf)) { 21648 21649 counter_base_id = soc_LMEP_1m_field32_get(unit, lmep_1_entry, COUNTER_3_IDf); 21650 endpoint_info->ccm_tx_update_lm_counter_base_id[2] = (counter_base_id & 0xFFF8) + (2 << 24); 21651 endpoint_info->ccm_tx_update_lm_counter_offset[2] = counter_base_id % 8; 21652 num_counter++; 21653 } 21654 21655 endpoint_info->ccm_tx_update_lm_counter_size = num_counter; 21656 21657 return; 21658 } 21659 21660 /* 21661 * Function: 21662 * bcm_sb2_oam_endpoint_get 21663 * Purpose: 21664 * Get an OAM endpoint object 21665 * Parameters: 21666 * unit - (IN) BCM device number 21667 * endpoint - (IN) Endpoint ID 21668 * endpoint_info - (OUT) Pointer to OAM endpoint information buffer. 21669 * Returns: 21670 * BCM_E_XXX 21671 */ 21672 int 21673 bcm_sb2_oam_endpoint_get(int unit, bcm_oam_endpoint_t endpoint, 21674 bcm_oam_endpoint_info_t *endpoint_info) 21675 { 21676 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 21677 int rv = BCM_E_NONE;/* Operation return status. */ 21678 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 21679 rmep_entry_t rmep_entry; /* Remote MEP entry buffer. */ 21680 lmep_entry_t lmep_entry; /* Local MEP entry buffer. */ 21681 lmep_1_entry_t lmep_1_entry; /* Local MEP entry buffer. */ 21682 uint16 inner_vlan_pri = 0; /* Inner vlan and pri */ 21683 #if defined(INCLUDE_BHH) 21684 bhh_sdk_msg_ctrl_sess_get_t msg; 21685 uint8 *buffer, *buffer_ptr; 21686 uint16 buffer_len, reply_len; 21687 int sess_id = 0; 21688 bcm_l3_egress_t l3_egress; 21689 bcm_l3_intf_t l3_intf; 21690 uint8 ts_mode; 21691 uint8 lm_pdu_counter_offset = 0; 21692 bcm_cos_t int_pri; 21693 _mpls_label_t label; 21694 #endif 21695 egr_mp_group_entry_t egr_mp_group; 21696 int ctr_field_id = 0; 21697 int egr_mp_grp_idx = -1; 21698 /* Ingress and egress. 2 memories */ 21699 soc_mem_t mems[2] = {INVALIDm, INVALIDm}; 21700 ing_oam_lm_counters_0_entry_t lm_entry; 21701 int pool_id = -1; 21702 bcm_gport_t tx_gport = 0; /* Gport value. */ 21703 bcm_port_t pp_port = 0; 21704 21705 if (NULL == endpoint_info) { 21706 return (BCM_E_PARAM); 21707 } 21708 21709 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 21710 _BCM_OAM_EP_INDEX_VALIDATE(endpoint); 21711 _BCM_OAM_LOCK(oc); 21712 21713 21714 h_data_p = &oc->oam_hash_data[endpoint]; 21715 21716 if (0 == h_data_p->in_use) { 21717 LOG_DEBUG(BSL_LS_BCM_OAM, 21718 (BSL_META_U(unit, 21719 "OAM(unit %d) Error: h_data_p not in use EP=%d\n"), 21720 unit, endpoint)); 21721 _BCM_OAM_UNLOCK(oc); 21722 return (BCM_E_NOT_FOUND); 21723 } 21724 21725 LOG_DEBUG(BSL_LS_BCM_OAM, 21726 (BSL_META_U(unit, 21727 "OAM(unit %d) Info: Endpoint (EP=%d) remote=%d local_tx=%d" 21728 "local_tx_idx=%d local_rx_en=%d local_rx_idx=%d oam_domain=%d\n"), 21729 unit, endpoint, h_data_p->is_remote, h_data_p->local_tx_enabled, 21730 h_data_p->local_tx_index, h_data_p->local_rx_enabled, 21731 h_data_p->local_rx_index, h_data_p->oam_domain)); 21732 if ((bcmOAMEndpointTypeEthernet == h_data_p->type) || 21733 (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p))) { 21734 if (1 == h_data_p->is_remote) { 21735 21736 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 21737 21738 /* Get hardware table entry information. */ 21739 rv = READ_RMEPm(unit, MEM_BLOCK_ANY, h_data_p->remote_index, 21740 &rmep_entry); 21741 if (BCM_FAILURE(rv)) { 21742 LOG_ERROR(BSL_LS_BCM_OAM, 21743 (BSL_META_U(unit, 21744 "OAM(unit %d) Error: RMEP table read failed for" 21745 " EP=%d %s.\n"), unit, endpoint, bcm_errmsg(rv))); 21746 _BCM_OAM_UNLOCK(oc); 21747 return (rv); 21748 } 21749 21750 rv = _bcm_sb2_oam_read_clear_faults(unit, h_data_p->remote_index, 21751 RMEPm, (uint32 *) &rmep_entry, 21752 (void *) endpoint_info); 21753 if (BCM_FAILURE(rv)) { 21754 LOG_ERROR(BSL_LS_BCM_OAM, 21755 (BSL_META_U(unit, 21756 "OAM(unit %d) Error: RMEP table read failed for" 21757 " EP=%d %s.\n"), unit, endpoint, bcm_errmsg(rv))); 21758 _BCM_OAM_UNLOCK(oc); 21759 return (rv); 21760 } 21761 } else { 21762 if (1 == h_data_p->local_tx_enabled) { 21763 21764 sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t)); 21765 21766 /* Get hardware table entry information. */ 21767 rv = READ_LMEPm(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, 21768 &lmep_entry); 21769 if (BCM_FAILURE(rv)) { 21770 LOG_ERROR(BSL_LS_BCM_OAM, 21771 (BSL_META_U(unit, 21772 "OAM(unit %d) Error: LMEP table read failed for EP=%d" 21773 " %s.\n"), unit, endpoint, bcm_errmsg(rv))); 21774 _BCM_OAM_UNLOCK(oc); 21775 return (rv); 21776 } 21777 21778 soc_LMEPm_mac_addr_get(unit, &lmep_entry, SAf, 21779 endpoint_info->src_mac_address); 21780 21781 endpoint_info->pkt_pri 21782 = soc_LMEPm_field32_get(unit, &lmep_entry, PRIORITYf); 21783 21784 endpoint_info->port_state 21785 = (soc_LMEPm_field32_get 21786 (unit, &lmep_entry, PORT_TLVf) 21787 ? BCM_OAM_PORT_TLV_UP : BCM_OAM_PORT_TLV_BLOCKED); 21788 21789 inner_vlan_pri = soc_LMEPm_field32_get(unit, &lmep_entry, CVLAN_TAGf); 21790 endpoint_info->inner_vlan = 0xFFF & inner_vlan_pri; 21791 endpoint_info->inner_pkt_pri = inner_vlan_pri >> 13; 21792 21793 sal_memset(&lmep_1_entry, 0, sizeof(lmep_1_entry_t)); 21794 21795 /* Get hardware table entry information. */ 21796 rv = READ_LMEP_1m(unit, MEM_BLOCK_ANY, h_data_p->local_tx_index, 21797 &lmep_1_entry); 21798 if (BCM_FAILURE(rv)) { 21799 LOG_ERROR(BSL_LS_BCM_OAM, 21800 (BSL_META_U(unit, 21801 "OAM(unit %d) Error: LMEP_1 table read failed " 21802 "for EP=%d"" %s.\n"), unit, endpoint, bcm_errmsg(rv))); 21803 _BCM_OAM_UNLOCK(oc); 21804 return (rv); 21805 } 21806 soc_LMEP_1m_mac_addr_get(unit, &lmep_1_entry, DAf, 21807 endpoint_info->dst_mac_address); 21808 21809 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 21810 endpoint_info->int_pri = soc_LMEP_1m_field32_get(unit, 21811 &lmep_1_entry, INT_PRIf); 21812 } else { 21813 endpoint_info->int_pri = h_data_p->int_pri; 21814 } 21815 21816 endpoint_info->interface_state 21817 = soc_LMEP_1m_field32_get(unit, &lmep_1_entry, INTERFACE_TLVf); 21818 21819 bcm_sb2_oam_hw_ccm_tx_ctr_get(unit, &lmep_1_entry, endpoint_info); 21820 pp_port = soc_LMEP_1m_field32_get(unit, &lmep_1_entry, PP_PORTf); 21821 _BCM_KT2_SUBPORT_PORT_ID_SET(tx_gport, pp_port); 21822 if (BCM_PBMP_MEMBER(SOC_INFO(unit).general_pp_port_pbm, pp_port)) { 21823 _BCM_KT2_SUBPORT_PORT_TYPE_SET(tx_gport, _BCM_KT2_SUBPORT_TYPE_GENERAL); 21824 endpoint_info->tx_gport = tx_gport; 21825 endpoint_info->flags2 |= BCM_OAM_ENDPOINT_FLAGS2_VLAN_VP_UP_MEP_IN_HW; 21826 } 21827 } 21828 } 21829 } 21830 else if (soc_feature(unit, soc_feature_bhh) && 21831 (BHH_EP_TYPE(h_data_p))) { 21832 #if defined(INCLUDE_BHH) 21833 if (!(h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) { 21834 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint); 21835 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 21836 MOS_MSG_SUBCLASS_BHH_SESS_GET, 21837 sess_id, 0, 21838 MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY, 21839 &reply_len); 21840 if (BCM_FAILURE(rv)) { 21841 LOG_ERROR(BSL_LS_BCM_OAM, 21842 (BSL_META_U(unit, 21843 "OAM(unit %d) Error: ukernel msg failed for" 21844 " EP=%d %s.\n"), unit, endpoint, 21845 bcm_errmsg(rv))); 21846 _BCM_OAM_UNLOCK(oc); 21847 return (rv); 21848 } 21849 21850 /* Pack control message data into DMA buffer */ 21851 buffer = oc->dma_buffer; 21852 buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg); 21853 buffer_len = buffer_ptr - buffer; 21854 21855 if (reply_len != buffer_len) { 21856 rv = BCM_E_INTERNAL; 21857 LOG_ERROR(BSL_LS_BCM_OAM, 21858 (BSL_META_U(unit, 21859 "OAM(unit %d) Error: ukernel msg failed for" 21860 " EP=%d %s.\n"), unit, endpoint, 21861 bcm_errmsg(rv))); 21862 _BCM_OAM_UNLOCK(oc); 21863 return (rv); 21864 } else { 21865 endpoint_info->int_pri = msg.tx_cos; 21866 endpoint_info->pkt_pri = msg.tx_pri; 21867 endpoint_info->mpls_exp = msg.priority; 21868 21869 if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE){ 21870 endpoint_info->name = msg.remote_mep_id; 21871 endpoint_info->ccm_period = msg.remote_period; 21872 } else { 21873 endpoint_info->name = msg.mep_id; 21874 endpoint_info->ccm_period = msg.local_period; 21875 } 21876 21877 if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){ 21878 endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT; 21879 } 21880 if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){ 21881 endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI; 21882 } 21883 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){ 21884 endpoint_info->faults |= 21885 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL; 21886 } 21887 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){ 21888 endpoint_info->faults |= 21889 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID; 21890 } 21891 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){ 21892 endpoint_info->faults |= 21893 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID; 21894 } 21895 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){ 21896 endpoint_info->faults |= 21897 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD; 21898 } 21899 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){ 21900 endpoint_info->faults |= 21901 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY; 21902 } 21903 if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) { 21904 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS; 21905 } 21906 if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) { 21907 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI; 21908 } 21909 if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) { 21910 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI; 21911 } 21912 21913 if (BHH_UC_FEATURE_CHECK(BHH_OLP_ENCAP_VALID)) { 21914 /* If this feature is valid, then encap_data is valid */ 21915 if (BCM_FAILURE(_bcm_sb2_oam_olp_encap_header_decap(unit, 21916 msg.encap_data, 21917 &(endpoint_info->ccm_tx_update_lm_counter_size), 21918 endpoint_info->ccm_tx_update_lm_counter_base_id, 21919 endpoint_info->ccm_tx_update_lm_counter_offset, 21920 endpoint_info->ccm_tx_update_lm_counter_action, 21921 &ts_mode, 21922 &lm_pdu_counter_offset, 21923 &int_pri, 21924 NULL))) 21925 { 21926 _BCM_OAM_UNLOCK(oc); 21927 return (BCM_E_INTERNAL); 21928 } 21929 endpoint_info->int_pri = int_pri; 21930 } 21931 endpoint_info->egress_label.label = h_data_p->egr_label; 21932 _bcm_sb2_oam_bhh_get_egress_label_from_encap(h_data_p, 21933 msg.encap_data, 21934 msg.encap_length, 21935 &label); 21936 endpoint_info->egress_label.exp = label.exp; 21937 endpoint_info->egress_label.ttl = label.ttl; 21938 } 21939 } else { 21940 endpoint_info->ccm_period = h_data_p->period; 21941 endpoint_info->int_pri = h_data_p->int_pri; 21942 endpoint_info->pkt_pri = h_data_p->vlan_pri; 21943 } 21944 endpoint_info->intf_id = h_data_p->egress_if; 21945 endpoint_info->cpu_qid = h_data_p->cpu_qid; 21946 endpoint_info->mpls_label = h_data_p->label; 21947 endpoint_info->gport = h_data_p->gport; 21948 endpoint_info->vpn = h_data_p->vpn; 21949 endpoint_info->trunk_index = h_data_p->trunk_index; 21950 endpoint_info->pkt_pri = h_data_p->vlan_pri; 21951 endpoint_info->inner_pkt_pri = h_data_p->inner_vlan_pri; 21952 if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE){ 21953 endpoint_info->name = msg.remote_mep_id; 21954 endpoint_info->local_id = endpoint; 21955 } 21956 if(!BHH_EP_MPLS_SECTION_TYPE(h_data_p)){ 21957 /* 21958 * Get MAC address 21959 */ 21960 bcm_l3_egress_t_init(&l3_egress); 21961 bcm_l3_intf_t_init(&l3_intf); 21962 21963 if (BCM_FAILURE 21964 (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) { 21965 _BCM_OAM_UNLOCK(oc); 21966 return (BCM_E_INTERNAL); 21967 } 21968 21969 l3_intf.l3a_intf_id = l3_egress.intf; 21970 if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) { 21971 _BCM_OAM_UNLOCK(oc); 21972 return (BCM_E_INTERNAL); 21973 } 21974 21975 sal_memcpy(endpoint_info->src_mac_address, l3_intf.l3a_mac_addr, 21976 _BHH_MAC_ADDR_LENGTH); 21977 }else { 21978 sal_memcpy(endpoint_info->src_mac_address, h_data_p->src_mac_address, 21979 _BHH_MAC_ADDR_LENGTH); 21980 } 21981 #else 21982 _BCM_OAM_UNLOCK(oc); 21983 return (BCM_E_UNAVAIL); 21984 #endif /* INCLUDE_BHH */ 21985 } 21986 else { 21987 _BCM_OAM_UNLOCK(oc); 21988 return (BCM_E_PARAM); 21989 } 21990 21991 endpoint_info->id = endpoint; 21992 endpoint_info->group = h_data_p->group_index; 21993 21994 /* BHH MEP Id & period already filled from uC msg */ 21995 if (!BHH_EP_TYPE(h_data_p)) { 21996 endpoint_info->name = h_data_p->name; 21997 endpoint_info->ccm_period = h_data_p->period; 21998 } 21999 22000 endpoint_info->vlan = h_data_p->vlan; 22001 endpoint_info->inner_vlan = h_data_p->inner_vlan; 22002 endpoint_info->level = h_data_p->level; 22003 endpoint_info->gport = h_data_p->gport; 22004 endpoint_info->trunk_index = h_data_p->trunk_index; 22005 endpoint_info->flags |= h_data_p->flags; 22006 endpoint_info->flags &= ~(BCM_OAM_ENDPOINT_WITH_ID); 22007 endpoint_info->opcode_flags = h_data_p->opcode_flags; 22008 endpoint_info->flags2 = h_data_p->flags2; 22009 endpoint_info->type = h_data_p->type; 22010 endpoint_info->vccv_type = h_data_p->vccv_type; 22011 endpoint_info->lm_counter_base_id = h_data_p->tx_ctr; 22012 endpoint_info->outer_tpid = h_data_p->outer_tpid; 22013 endpoint_info->inner_tpid = h_data_p->inner_tpid; 22014 endpoint_info->subport_tpid = h_data_p->subport_tpid; 22015 endpoint_info->timestamp_format = h_data_p->ts_format; 22016 #if defined(INCLUDE_ETH_LM_DM) || defined (INCLUDE_MPLS_LM_DM) 22017 sal_memcpy(&(endpoint_info->dst_mac_address), 22018 &(h_data_p->dst_mac_address), sizeof(bcm_mac_t)); 22019 sal_memcpy(&(endpoint_info->src_mac_address), 22020 &(h_data_p->src_mac_address), sizeof(bcm_mac_t)); 22021 #endif 22022 if (MPLS_LM_DM_ENDPOINT_TYPE(endpoint_info)) { 22023 endpoint_info->intf_id = h_data_p->egress_if; 22024 endpoint_info->mpls_label = h_data_p->label; 22025 endpoint_info->vpn = h_data_p->vpn; 22026 #if defined(INCLUDE_MPLS_LM_DM) 22027 endpoint_info->egress_label.label = h_data_p->egr_label; 22028 endpoint_info->egress_label.exp = h_data_p->egr_label_exp; 22029 endpoint_info->egress_label.ttl = h_data_p->egr_label_ttl; 22030 #endif 22031 } 22032 22033 #if defined(BCM_METROLITE_SUPPORT) 22034 if(SOC_IS_METROLITE(unit)) { 22035 endpoint_info->lm_count_profile = h_data_p->lm_count_profile; 22036 } 22037 #endif 22038 if (h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 22039 ctr_field_id = h_data_p->egr_ctr_field_id; 22040 if (MPLS_LM_DM_ENDPOINT_TYPE(endpoint_info)) { 22041 rv = _bcm_sb2_oam_find_egr_lmep(unit, h_data_p, &egr_mp_grp_idx, 22042 &egr_mp_group); 22043 if (BCM_FAILURE(rv)) { 22044 _BCM_OAM_UNLOCK(oc); 22045 return (rv); 22046 } 22047 endpoint_info->lm_payload_offset = 22048 soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, 22049 sb2_mep_ctr_info[ctr_field_id].ctr_lm_payload_offset); 22050 endpoint_info->lm_cos_offset = 22051 soc_EGR_MP_GROUPm_field32_get(unit, &egr_mp_group, 22052 sb2_mep_ctr_info[ctr_field_id].ctr_lm_cos_offset); 22053 } 22054 if (h_data_p->rx_ctr != _BCM_OAM_INVALID_INDEX) { 22055 pool_id = (h_data_p->rx_ctr >> 24) & 0xFF; 22056 endpoint_info->lm_ctr_pool_id = pool_id; 22057 rv = _bcm_sb2_oam_lm_counters_mems_from_pool_get(pool_id, mems); 22058 if (BCM_FAILURE(rv)) { 22059 _BCM_OAM_UNLOCK(oc); 22060 return (rv); 22061 } 22062 /* Getting info from one of the LM Counter pools (ingress or egress) 22063 * is enough 22064 */ 22065 rv = soc_mem_read(unit, mems[0], MEM_BLOCK_ANY, 22066 (h_data_p->rx_ctr & 0xFFFFFF), &lm_entry); 22067 if (BCM_FAILURE(rv)) { 22068 _BCM_OAM_UNLOCK(oc); 22069 return (rv); 22070 } 22071 endpoint_info->lm_ctr_type = 22072 soc_mem_field32_get(unit, mems[0], &lm_entry, LM_COUNT_TYPEf); 22073 endpoint_info->lm_ctr_sample_size = 22074 soc_mem_field32_get(unit, mems[0], &lm_entry, LM_COUNTER_SAMPLE_SIZEf); 22075 } 22076 endpoint_info->pri_map_id = h_data_p->pri_map_index; 22077 } 22078 _BCM_OAM_UNLOCK(oc); 22079 return (BCM_E_NONE); 22080 } 22081 22082 22083 /* 22084 * Function: 22085 * bcm_sb2_oam_endpoint_destroy 22086 * Purpose: 22087 * Destroy an OAM endpoint object 22088 * Parameters: 22089 * unit - (IN) BCM device number 22090 * endpoint - (IN) Endpoint ID to destroy. 22091 * result =s: 22092 * BCM_E_XXX 22093 */ 22094 int 22095 bcm_sb2_oam_endpoint_destroy(int unit, bcm_oam_endpoint_t endpoint) 22096 { 22097 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 22098 int rv; /* Operation return status. */ 22099 22100 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 22101 _BCM_OAM_EP_INDEX_VALIDATE(endpoint); 22102 _BCM_OAM_LOCK(oc); 22103 22104 rv = _bcm_sb2_oam_endpoint_destroy(unit, endpoint); 22105 if (BCM_FAILURE(rv)) { 22106 LOG_ERROR(BSL_LS_BCM_OAM, 22107 (BSL_META_U(unit, 22108 "OAM(unit %d) Error: Endpoint destroy EP=%d failed - " 22109 "%s.\n"), unit, endpoint, bcm_errmsg(rv))); 22110 } 22111 22112 _BCM_OAM_UNLOCK(oc); 22113 return (rv); 22114 } 22115 22116 /* 22117 * Function: 22118 * bcm_sb2_oam_endpoint_destroy_all 22119 * Purpose: 22120 * Destroy all OAM endpoint objects associated with a group. 22121 * Parameters: 22122 * unit - (IN) BCM device number 22123 * group - (IN) The OAM group whose endpoints should be destroyed 22124 * Returns: 22125 * BCM_E_XXX 22126 */ 22127 int 22128 bcm_sb2_oam_endpoint_destroy_all(int unit, bcm_oam_group_t group) 22129 { 22130 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 22131 int rv; /* Operation return status. */ 22132 _bcm_oam_group_data_t *g_info_p; 22133 22134 /* Get OAM device control structure. */ 22135 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 22136 22137 /* Validate group index. */ 22138 _BCM_OAM_GROUP_INDEX_VALIDATE(group); 22139 22140 _BCM_OAM_LOCK(oc); 22141 22142 /* Check if the group is in use. */ 22143 rv = shr_idxres_list_elem_state(oc->group_pool, group); 22144 if (BCM_E_EXISTS != rv) { 22145 _BCM_OAM_UNLOCK(oc); 22146 LOG_ERROR(BSL_LS_BCM_OAM, 22147 (BSL_META_U(unit, 22148 "OAM(unit %d) Error: Group ID=%d does not exist.\n"), 22149 unit, group)); 22150 return (rv); 22151 } 22152 22153 /* Get the group data pointer. */ 22154 g_info_p = &oc->group_info[group]; 22155 rv = _bcm_sb2_oam_group_endpoints_destroy(unit, g_info_p); 22156 if (BCM_FAILURE(rv)) { 22157 LOG_ERROR(BSL_LS_BCM_OAM, 22158 (BSL_META_U(unit, 22159 "OAM(unit %d) Error: Group (GID=%d) endpoints destroy" 22160 " failed - %s.\n"), unit, group, bcm_errmsg(rv))); 22161 _BCM_OAM_UNLOCK(oc); 22162 return (rv); 22163 } 22164 _BCM_OAM_UNLOCK(oc); 22165 return (rv); 22166 } 22167 22168 /* 22169 * Function: 22170 * bcm_sb2_oam_endpoint_traverse 22171 * Purpose: 22172 * Traverse the set of OAM endpoints associated with the 22173 * specified group, calling a specified callback for each one 22174 * Parameters: 22175 * unit - (IN) BCM device number 22176 * group - (IN) The OAM group whose endpoints should be traversed 22177 * cb - (IN) A pointer to the callback function to call for each OAM 22178 * endpoint in the specified group 22179 * user_data - (IN) Pointer to user data to supply in the callback 22180 * Returns: 22181 * BCM_E_XXX 22182 */ 22183 int 22184 bcm_sb2_oam_endpoint_traverse(int unit, bcm_oam_group_t group, 22185 bcm_oam_endpoint_traverse_cb cb, 22186 void *user_data) 22187 { 22188 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 22189 int rv; /* Operation return status. */ 22190 bcm_oam_endpoint_info_t ep_info; 22191 _bcm_oam_hash_data_t *h_data_p; 22192 _bcm_oam_ep_list_t *cur; 22193 _bcm_oam_group_data_t *g_info_p; 22194 22195 /* Validate input parameter. */ 22196 if (NULL == cb) { 22197 return (BCM_E_PARAM); 22198 } 22199 22200 /* Get OAM device control structure. */ 22201 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 22202 22203 /* Validate group index. */ 22204 _BCM_OAM_GROUP_INDEX_VALIDATE(group); 22205 22206 _BCM_OAM_LOCK(oc); 22207 22208 /* Check if the group is in use. */ 22209 rv = shr_idxres_list_elem_state(oc->group_pool, group); 22210 if (BCM_E_EXISTS != rv) { 22211 _BCM_OAM_UNLOCK(oc); 22212 LOG_ERROR(BSL_LS_BCM_OAM, 22213 (BSL_META_U(unit, 22214 "OAM(unit %d) Error: Group ID=%d does not exist.\n"), 22215 unit, group)); 22216 return (rv); 22217 } 22218 22219 /* Get the group data pointer. */ 22220 g_info_p = &oc->group_info[group]; 22221 22222 /* Get the endpoint list head pointer. */ 22223 cur = *(g_info_p->ep_list); 22224 if (NULL == cur) { 22225 _BCM_OAM_UNLOCK(oc); 22226 LOG_DEBUG(BSL_LS_BCM_OAM, 22227 (BSL_META_U(unit, 22228 "OAM(unit %d) Info: No endpoints in group GID=%d.\n"), 22229 unit, group)); 22230 return (BCM_E_NONE); 22231 } 22232 22233 /* Traverse to the tail of the list. */ 22234 while (NULL != cur->next) { 22235 LOG_DEBUG(BSL_LS_BCM_OAM, 22236 (BSL_META_U(unit, 22237 "OAM(unit %d) Info: GID=%d EP:%d.\n"), 22238 unit, cur->ep_data_p->group_index, cur->ep_data_p->ep_id)); 22239 cur = cur->next; 22240 } 22241 22242 while (NULL != cur) { 22243 h_data_p = cur->ep_data_p; 22244 if (NULL == h_data_p) { 22245 LOG_ERROR(BSL_LS_BCM_OAM, 22246 (BSL_META_U(unit, 22247 "OAM(unit %d) Error: Group=%d endpoints access failed -" 22248 " %s.\n"), unit, group, bcm_errmsg(BCM_E_INTERNAL))); 22249 _BCM_OAM_UNLOCK(oc); 22250 return (BCM_E_INTERNAL); 22251 } 22252 bcm_oam_endpoint_info_t_init(&ep_info); 22253 22254 rv = bcm_sb2_oam_endpoint_get(unit, h_data_p->ep_id, &ep_info); 22255 if (BCM_FAILURE(rv)) { 22256 _BCM_OAM_UNLOCK(oc); 22257 LOG_ERROR(BSL_LS_BCM_OAM, 22258 (BSL_META_U(unit, 22259 "OAM(unit %d) Error: EP=%d info get failed %s.\n"), 22260 unit, h_data_p->ep_id, bcm_errmsg(rv))); 22261 return (rv); 22262 } 22263 22264 rv = cb(unit, &ep_info, user_data); 22265 if (BCM_FAILURE(rv)) { 22266 _BCM_OAM_UNLOCK(oc); 22267 LOG_ERROR(BSL_LS_BCM_OAM, 22268 (BSL_META_U(unit, 22269 "OAM(unit %d) Error: EP=%d callback failed - %s.\n"), 22270 unit, h_data_p->ep_id, bcm_errmsg(rv))); 22271 return (rv); 22272 } 22273 cur = cur->prev; 22274 } 22275 _BCM_OAM_UNLOCK(oc); 22276 return (rv); 22277 } 22278 22279 /* 22280 * Function: 22281 * bcm_sb2_oam_pm_event_register 22282 * Purpose: 22283 * Register a callback for handling OAM PM events 22284 * Parameters: 22285 * unit - (IN) BCM device number 22286 * event_types - (IN) The set of OAM PM events for which the specified 22287 * callback should be called. 22288 * cb - (IN) A pointer to the callback function to call for 22289 * the specified OAM PM events 22290 * user_data - (IN) Pointer to user data to supply in the callback 22291 * Returns: 22292 * BCM_E_XXX 22293 */ 22294 int 22295 bcm_sb2_oam_pm_event_register(int unit, bcm_oam_event_types_t event_types, 22296 bcm_oam_pm_event_cb cb, void *user_data) 22297 { 22298 _bcm_oam_control_t *oc; 22299 _bcm_oam_pm_event_handler_t *event_h_p; 22300 _bcm_oam_pm_event_handler_t *prev_p = NULL; 22301 bcm_oam_event_type_t e_type; 22302 int rv; /* Operation return status. */ 22303 uint16 reply_len = 0; 22304 uint8 msg_class = 0; 22305 uint8 msg_subclass = 0; 22306 uint8 msg_reply_subclass = 0; 22307 uint8 *dma_buffer = NULL; 22308 22309 /* Validate event callback input parameter. */ 22310 if (NULL == cb) { 22311 return (BCM_E_PARAM); 22312 } 22313 22314 /* Validate the event type to be of PM event type */ 22315 if (!(_BCM_SB2_EVENT_TYPE_PM_EVENT(event_types))) { 22316 return (BCM_E_PARAM); 22317 } 22318 22319 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 22320 22321 _BCM_OAM_LOCK(oc); 22322 22323 for (event_h_p = oc->pm_event_handler_list_p; event_h_p != NULL; 22324 event_h_p = event_h_p->next_p) { 22325 if (event_h_p->cb == cb) { 22326 break; 22327 } 22328 prev_p = event_h_p; 22329 } 22330 22331 if (NULL == event_h_p) { 22332 22333 _BCM_OAM_ALLOC(event_h_p, _bcm_oam_pm_event_handler_t, 22334 sizeof(_bcm_oam_pm_event_handler_t), "OAM event handler"); 22335 22336 if (NULL == event_h_p) { 22337 LOG_ERROR(BSL_LS_BCM_OAM, 22338 (BSL_META_U(unit, 22339 "OAM(unit %d) Error: Event handler alloc failed -" 22340 " %s.\n"), unit, bcm_errmsg(BCM_E_MEMORY))); 22341 _BCM_OAM_UNLOCK(oc); 22342 return (BCM_E_MEMORY); 22343 } 22344 22345 event_h_p->next_p = NULL; 22346 event_h_p->cb = cb; 22347 22348 SHR_BITCLR_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount); 22349 if (prev_p != NULL) { 22350 prev_p->next_p = event_h_p; 22351 } else { 22352 oc->pm_event_handler_list_p = event_h_p; 22353 } 22354 } 22355 22356 for (e_type = bcmOAMEventBHHRawData; 22357 e_type <= bcmOAMEventMplsLmDmRawData; 22358 ++e_type) { 22359 if (SHR_BITGET(event_types.w, e_type)) { 22360 if (!SHR_BITGET(event_h_p->event_types.w, e_type)) { 22361 /* Add this event to the registered events list. */ 22362 SHR_BITSET(event_h_p->event_types.w, e_type); 22363 if (e_type == bcmOAMEventBHHRawData) { 22364 msg_class = MOS_MSG_CLASS_BHH; 22365 msg_subclass = 22366 MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_SET; 22367 msg_reply_subclass = 22368 MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_SET_REPLY; 22369 #if defined (INCLUDE_BHH) 22370 dma_buffer = oc->pm_bhh_dma_buffer; 22371 #endif 22372 } 22373 if (e_type == bcmOAMEventMplsLmDmRawData) { 22374 msg_class = MOS_MSG_CLASS_MPLS_LM_DM; 22375 msg_subclass = 22376 MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_SET; 22377 msg_reply_subclass = 22378 MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_SET_REPLY; 22379 #if defined (INCLUDE_MPLS_LM_DM) 22380 dma_buffer = oc->pm_mpls_lm_dm_dma_buffer; 22381 #endif 22382 } 22383 if (e_type == bcmOAMEventEthLmDmRawData) { 22384 msg_class = MOS_MSG_CLASS_ETH_LM_DM; 22385 msg_subclass = 22386 MOS_MSG_SUBCLASS_ETH_LM_DM_PM_RAW_DATA_EVENT_SET; 22387 msg_reply_subclass = 22388 MOS_MSG_SUBCLASS_ETH_LM_DM_PM_RAW_DATA_EVENT_SET_REPLY; 22389 #if defined (INCLUDE_ETH_LM_DM) 22390 dma_buffer = oc->pm_eth_lm_dm_dma_buffer; 22391 #endif 22392 } 22393 rv = _bcm_sb2_oam_pm_msg_send_receive 22394 (unit, msg_class, 22395 msg_subclass, 22396 0, soc_cm_l2p(unit, dma_buffer), /* Send dma_buffer ptr in data */ 22397 msg_reply_subclass, 22398 &reply_len); 22399 22400 if(BCM_FAILURE(rv)) { 22401 _BCM_OAM_UNLOCK(oc); 22402 return BCM_E_INTERNAL; 22403 } 22404 oc->pm_event_handler_cnt[e_type] += 1; 22405 } 22406 } 22407 } 22408 22409 22410 event_h_p->user_data = user_data; 22411 22412 _BCM_OAM_UNLOCK(oc); 22413 22414 return (BCM_E_NONE); 22415 } 22416 22417 /* 22418 * Function: 22419 * bcm_sb2_oam_event_register 22420 * Purpose: 22421 * Register a callback for handling OAM events 22422 * Parameters: 22423 * unit - (IN) BCM device number 22424 * event_types - (IN) The set of OAM events for which the specified 22425 * callback should be called. 22426 * cb - (IN) A pointer to the callback function to call for 22427 * the specified OAM events 22428 * user_data - (IN) Pointer to user data to supply in the callback 22429 * Returns: 22430 * BCM_E_XXX 22431 */ 22432 int 22433 bcm_sb2_oam_event_register(int unit, bcm_oam_event_types_t event_types, 22434 bcm_oam_event_cb cb, void *user_data) 22435 { 22436 _bcm_oam_control_t *oc; 22437 _bcm_oam_event_handler_t *event_h_p; 22438 _bcm_oam_event_handler_t *prev_p = NULL; 22439 bcm_oam_event_type_t e_type; 22440 uint32 rval; 22441 int hw_update = 0; 22442 uint32 event_bmp; 22443 int rv; /* Operation return status. */ 22444 22445 /* Validate event callback input parameter. */ 22446 if (NULL == cb) { 22447 return (BCM_E_PARAM); 22448 } 22449 22450 /* Check if an event is set for register in the events bitmap. */ 22451 SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp); 22452 if (0 == event_bmp) { 22453 /* No events specified. */ 22454 LOG_ERROR(BSL_LS_BCM_OAM, 22455 (BSL_META_U(unit, 22456 "OAM(unit %d) Error: No events specified for register.\n"), 22457 unit)); 22458 return (BCM_E_PARAM); 22459 } 22460 22461 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 22462 22463 _BCM_OAM_LOCK(oc); 22464 22465 for (event_h_p = oc->event_handler_list_p; event_h_p != NULL; 22466 event_h_p = event_h_p->next_p) { 22467 if (event_h_p->cb == cb) { 22468 break; 22469 } 22470 prev_p = event_h_p; 22471 } 22472 22473 if (NULL == event_h_p) { 22474 22475 _BCM_OAM_ALLOC(event_h_p, _bcm_oam_event_handler_t, 22476 sizeof(_bcm_oam_event_handler_t), "OAM event handler"); 22477 22478 if (NULL == event_h_p) { 22479 LOG_ERROR(BSL_LS_BCM_OAM, 22480 (BSL_META_U(unit, 22481 "OAM(unit %d) Error: Event handler alloc failed -" 22482 " %s.\n"), unit, bcm_errmsg(BCM_E_MEMORY))); 22483 _BCM_OAM_UNLOCK(oc); 22484 return (BCM_E_MEMORY); 22485 } 22486 22487 event_h_p->next_p = NULL; 22488 event_h_p->cb = cb; 22489 22490 SHR_BITCLR_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount); 22491 if (prev_p != NULL) { 22492 prev_p->next_p = event_h_p; 22493 } else { 22494 oc->event_handler_list_p = event_h_p; 22495 } 22496 } 22497 22498 rv = READ_CCM_INTERRUPT_CONTROLr(unit, &rval); 22499 if (BCM_FAILURE(rv)) { 22500 _BCM_OAM_UNLOCK(oc); 22501 LOG_ERROR(BSL_LS_BCM_OAM, 22502 (BSL_META_U(unit, 22503 "OAM(unit %d) Error: CCM interrupt control read failed -" 22504 " %s.\n"), unit, bcm_errmsg(rv))); 22505 return (rv); 22506 } 22507 22508 for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) { 22509 if (SHR_BITGET(event_types.w, e_type)) { 22510 if(soc_feature(unit, soc_feature_bhh)) { 22511 #if defined(INCLUDE_BHH) 22512 /* 22513 * BHH events are generated by the uKernel 22514 */ 22515 if ((e_type == bcmOAMEventBHHLBTimeout) || 22516 (e_type == bcmOAMEventBHHLBDiscoveryUpdate) || 22517 (e_type == bcmOAMEventBHHCCMTimeout) || 22518 (e_type == bcmOAMEventBHHCCMTimeoutClear) || 22519 (e_type == bcmOAMEventBHHCCMState) || 22520 (e_type == bcmOAMEventBHHCCMRdi) || 22521 (e_type == bcmOAMEventBHHCCMUnknownMegLevel) || 22522 (e_type == bcmOAMEventBHHCCMUnknownMegId) || 22523 (e_type == bcmOAMEventBHHCCMUnknownMepId) || 22524 (e_type == bcmOAMEventBHHCCMUnknownPeriod) || 22525 (e_type == bcmOAMEventBHHCCMUnknownPriority) || 22526 (e_type == bcmOAMEventBHHCCMRdiClear) || 22527 (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) || 22528 (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) || 22529 (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) || 22530 (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) || 22531 (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) || 22532 (e_type == bcmOAMEventBhhPmCounterRollover) || 22533 (e_type == bcmOAMEventCsfLos) || 22534 (e_type == bcmOAMEventCsfFdi) || 22535 (e_type == bcmOAMEventCsfRdi) || 22536 (e_type == bcmOAMEventCsfDci)) { 22537 SHR_BITSET(event_h_p->event_types.w, e_type); 22538 oc->event_handler_cnt[e_type] += 1; 22539 continue; 22540 } 22541 #endif 22542 } 22543 if ((e_type == bcmOAMEventEthLmDmPmCounterRollover)) { 22544 #if defined(INCLUDE_ETH_LM_DM) 22545 /* 22546 * ETH_LM_DM events are generated by the uKernel 22547 */ 22548 SHR_BITSET(event_h_p->event_types.w, e_type); 22549 oc->event_handler_cnt[e_type] += 1; 22550 continue; 22551 #endif 22552 } 22553 if ((e_type == bcmOAMEventMplsLmDmPmCounterRollover)) { 22554 #if defined(INCLUDE_MPLS_LM_DM) 22555 /* 22556 * MPLS_LM_DM events are generated by the uKernel 22557 */ 22558 SHR_BITSET(event_h_p->event_types.w, e_type); 22559 oc->event_handler_cnt[e_type] += 1; 22560 continue; 22561 #endif 22562 } 22563 22564 if (!soc_reg_field_valid 22565 (unit, CCM_INTERRUPT_CONTROLr, 22566 _sb2_oam_intr_en_fields[e_type].field)) { 22567 continue; 22568 } 22569 22570 if (!SHR_BITGET(event_h_p->event_types.w, e_type)) { 22571 /* Add this event to the registered events list. */ 22572 SHR_BITSET(event_h_p->event_types.w, e_type); 22573 oc->event_handler_cnt[e_type] += 1; 22574 if (1 == oc->event_handler_cnt[e_type]) { 22575 hw_update = 1; 22576 soc_reg_field_set 22577 (unit, CCM_INTERRUPT_CONTROLr, &rval, 22578 _sb2_oam_intr_en_fields[e_type].field, 1); 22579 } 22580 } 22581 } 22582 } 22583 22584 event_h_p->user_data = user_data; 22585 22586 if (1 == hw_update) { 22587 rv = WRITE_CCM_INTERRUPT_CONTROLr(unit, rval); 22588 if (BCM_FAILURE(rv)) { 22589 _BCM_OAM_UNLOCK(oc); 22590 LOG_ERROR(BSL_LS_BCM_OAM, 22591 (BSL_META_U(unit, 22592 "OAM(unit %d) Error: CCM interrupt control write failed -" 22593 " %s.\n"), unit, bcm_errmsg(rv))); 22594 return (rv); 22595 } 22596 } 22597 if (soc_feature(unit, soc_feature_bhh)) { 22598 #if defined(INCLUDE_BHH) 22599 /* 22600 * Update BHH Events mask 22601 */ 22602 rv = _bcm_sb2_oam_bhh_event_mask_set(unit); 22603 #endif /* INCLUDE_BHH */ 22604 } 22605 #if defined(INCLUDE_ETH_LM_DM) 22606 if(!oc->eth_lm_dm_ukernel_not_ready) { 22607 /* 22608 * Update ETH_LM_DM Events mask 22609 */ 22610 rv = _bcm_sb2_eth_lm_dm_event_mask_set(unit); 22611 if (BCM_FAILURE(rv)) { 22612 _BCM_OAM_UNLOCK(oc); 22613 LOG_ERROR(BSL_LS_BCM_OAM, 22614 (BSL_META_U(unit, 22615 "OAM(unit %d) Error: failed to set ETH LM DM event mask-" 22616 " %s.\n"), unit, bcm_errmsg(rv))); 22617 return (rv); 22618 } 22619 } 22620 #endif 22621 #if defined(INCLUDE_MPLS_LM_DM) 22622 if(oc->mpls_lm_dm_ukernel_ready) { 22623 /* 22624 * Update MPLS_LM_DM Events mask 22625 */ 22626 rv = _bcm_sb2_mpls_lm_dm_event_mask_set(unit); 22627 if (BCM_FAILURE(rv)) { 22628 _BCM_OAM_UNLOCK(oc); 22629 LOG_ERROR(BSL_LS_BCM_OAM, 22630 (BSL_META_U(unit, 22631 "OAM(unit %d) Error: failed to set MPLS LM DM event mask-" 22632 " %s.\n"), unit, bcm_errmsg(rv))); 22633 return (rv); 22634 } 22635 } 22636 #endif 22637 22638 _BCM_OAM_UNLOCK(oc); 22639 22640 return (BCM_E_NONE); 22641 } 22642 22643 /* 22644 * Function: 22645 * bcm_sb2_oam_event_unregister 22646 * Purpose: 22647 * Remove a registered event from the event handler list. 22648 * Parameters: 22649 * unit - (IN) BCM device number 22650 * event_types - (IN) The set of OAM events for which the specified 22651 * callback should not be called 22652 * cb - (IN) A pointer to the callback function to unregister 22653 * from the specified OAM events 22654 * Returns: 22655 * BCM_E_XXX 22656 */ 22657 int 22658 bcm_sb2_oam_event_unregister(int unit, bcm_oam_event_types_t event_types, 22659 bcm_oam_event_cb cb) 22660 { 22661 _bcm_oam_control_t *oc; 22662 _bcm_oam_event_handler_t *event_h_p; 22663 _bcm_oam_event_handler_t *prev_p = NULL; 22664 bcm_oam_event_type_t e_type; 22665 uint32 rval; 22666 int hw_update = 0; 22667 uint32 event_bmp; 22668 int rv; /* Operation return status. */ 22669 22670 /* Validate event callback input parameter. */ 22671 if (NULL == cb) { 22672 return (BCM_E_PARAM); 22673 } 22674 22675 /* Check if an event is set for unregister in the events bitmap. */ 22676 SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, event_bmp); 22677 if (0 == event_bmp) { 22678 /* No events specified. */ 22679 LOG_ERROR(BSL_LS_BCM_OAM, 22680 (BSL_META_U(unit, 22681 "OAM(unit %d) Error: No events specified for register.\n"), 22682 unit)); 22683 return (BCM_E_PARAM); 22684 } 22685 22686 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 22687 22688 _BCM_OAM_LOCK(oc); 22689 22690 for (event_h_p = oc->event_handler_list_p; event_h_p != NULL; 22691 event_h_p = event_h_p->next_p) { 22692 if (event_h_p->cb == cb) { 22693 break; 22694 } 22695 prev_p = event_h_p; 22696 } 22697 22698 if (NULL == event_h_p) { 22699 _BCM_OAM_UNLOCK(oc); 22700 return (BCM_E_NOT_FOUND); 22701 } 22702 22703 rv = READ_CCM_INTERRUPT_CONTROLr(unit, &rval); 22704 if (BCM_FAILURE(rv)) { 22705 _BCM_OAM_UNLOCK(oc); 22706 LOG_ERROR(BSL_LS_BCM_OAM, 22707 (BSL_META_U(unit, 22708 "OAM(unit %d) Error: CCM interrupt control read failed -" 22709 " %s.\n"), unit, bcm_errmsg(rv))); 22710 return (rv); 22711 } 22712 22713 for (e_type = 0; e_type < bcmOAMEventCount; ++e_type) { 22714 22715 if (SHR_BITGET(event_types.w, e_type)) { 22716 if(soc_feature(unit, soc_feature_bhh)) { 22717 #if defined(INCLUDE_BHH) 22718 /* 22719 * BHH events are generated by the uKernel 22720 */ 22721 if ((e_type == bcmOAMEventBHHLBTimeout) || 22722 (e_type == bcmOAMEventBHHLBDiscoveryUpdate) || 22723 (e_type == bcmOAMEventBHHCCMTimeout) || 22724 (e_type == bcmOAMEventBHHCCMTimeoutClear) || 22725 (e_type == bcmOAMEventBHHCCMState) || 22726 (e_type == bcmOAMEventBHHCCMRdi) || 22727 (e_type == bcmOAMEventBHHCCMUnknownMegLevel) || 22728 (e_type == bcmOAMEventBHHCCMUnknownMegId) || 22729 (e_type == bcmOAMEventBHHCCMUnknownMepId) || 22730 (e_type == bcmOAMEventBHHCCMUnknownPeriod) || 22731 (e_type == bcmOAMEventBHHCCMUnknownPriority) || 22732 (e_type == bcmOAMEventBHHCCMRdiClear) || 22733 (e_type == bcmOAMEventBHHCCMUnknownMegLevelClear) || 22734 (e_type == bcmOAMEventBHHCCMUnknownMegIdClear) || 22735 (e_type == bcmOAMEventBHHCCMUnknownMepIdClear) || 22736 (e_type == bcmOAMEventBHHCCMUnknownPeriodClear) || 22737 (e_type == bcmOAMEventBHHCCMUnknownPriorityClear) || 22738 (e_type == bcmOAMEventBhhPmCounterRollover) || 22739 (e_type == bcmOAMEventCsfLos) || 22740 (e_type == bcmOAMEventCsfFdi) || 22741 (e_type == bcmOAMEventCsfRdi) || 22742 (e_type == bcmOAMEventCsfDci)) { 22743 SHR_BITCLR(event_h_p->event_types.w, e_type); 22744 oc->event_handler_cnt[e_type] -= 1; 22745 continue; 22746 } 22747 #endif 22748 } 22749 if ((e_type == bcmOAMEventEthLmDmPmCounterRollover)) { 22750 #if defined(INCLUDE_ETH_LM_DM) 22751 /* 22752 * ETH_LM_DM events are generated by the uKernel 22753 */ 22754 SHR_BITCLR(event_h_p->event_types.w, e_type); 22755 oc->event_handler_cnt[e_type] -= 1; 22756 continue; 22757 #endif 22758 } 22759 if ((e_type == bcmOAMEventMplsLmDmPmCounterRollover)) { 22760 #if defined(INCLUDE_MPLS_LM_DM) 22761 /* 22762 * MPLS_LM_DM events are generated by the uKernel 22763 */ 22764 SHR_BITCLR(event_h_p->event_types.w, e_type); 22765 oc->event_handler_cnt[e_type] -= 1; 22766 continue; 22767 #endif 22768 } 22769 22770 if (!soc_reg_field_valid 22771 (unit, CCM_INTERRUPT_CONTROLr, 22772 _sb2_oam_intr_en_fields[e_type].field)) { 22773 _BCM_OAM_UNLOCK(oc); 22774 return (BCM_E_UNAVAIL); 22775 } 22776 22777 if ((oc->event_handler_cnt[e_type] > 0) 22778 && SHR_BITGET(event_h_p->event_types.w, e_type)) { 22779 22780 /* Remove this event from the registered events list. */ 22781 SHR_BITCLR(event_h_p->event_types.w, e_type); 22782 22783 oc->event_handler_cnt[e_type] -= 1; 22784 22785 if (0 == oc->event_handler_cnt[e_type]) { 22786 hw_update = 1; 22787 soc_reg_field_set 22788 (unit, CCM_INTERRUPT_CONTROLr, &rval, 22789 _sb2_oam_intr_en_fields[e_type].field, 0); 22790 } 22791 } 22792 } 22793 } 22794 22795 if (1 == hw_update) { 22796 rv = WRITE_CCM_INTERRUPT_CONTROLr(unit, rval); 22797 if (BCM_FAILURE(rv)) { 22798 _BCM_OAM_UNLOCK(oc); 22799 LOG_ERROR(BSL_LS_BCM_OAM, 22800 (BSL_META_U(unit, 22801 "OAM(unit %d) Error: CCM interrupt control write failed -" 22802 " %s.\n"), unit, bcm_errmsg(rv))); 22803 return (rv); 22804 } 22805 } 22806 22807 SHR_BITTEST_RANGE(event_h_p->event_types.w, 0, bcmOAMEventCount, event_bmp); 22808 22809 if (0 == event_bmp) { 22810 22811 if (NULL != prev_p) { 22812 22813 prev_p->next_p = event_h_p->next_p; 22814 22815 } else { 22816 22817 oc->event_handler_list_p = event_h_p->next_p; 22818 22819 } 22820 sal_free(event_h_p); 22821 } 22822 if(soc_feature(unit, soc_feature_bhh)) { 22823 #if defined(INCLUDE_BHH) 22824 /* 22825 * Update BHH Events mask 22826 */ 22827 rv = _bcm_sb2_oam_bhh_event_mask_set(unit); 22828 #endif /* INCLUDE_BHH */ 22829 } 22830 #if defined(INCLUDE_ETH_LM_DM) 22831 if(!oc->eth_lm_dm_ukernel_not_ready) { 22832 /* 22833 * Update ETH_LM_DM Events mask 22834 */ 22835 rv = _bcm_sb2_eth_lm_dm_event_mask_set(unit); 22836 if (BCM_FAILURE(rv)) { 22837 _BCM_OAM_UNLOCK(oc); 22838 LOG_ERROR(BSL_LS_BCM_OAM, 22839 (BSL_META_U(unit, 22840 "OAM(unit %d) Error: failed to set ETH LM DM event mask-" 22841 " %s.\n"), unit, bcm_errmsg(rv))); 22842 return (rv); 22843 } 22844 } 22845 #endif 22846 #if defined(INCLUDE_MPLS_LM_DM) 22847 if(oc->mpls_lm_dm_ukernel_ready) { 22848 /* 22849 * Update MPLS_LM_DM Events mask 22850 */ 22851 rv = _bcm_sb2_mpls_lm_dm_event_mask_set(unit); 22852 if (BCM_FAILURE(rv)) { 22853 _BCM_OAM_UNLOCK(oc); 22854 LOG_ERROR(BSL_LS_BCM_OAM, 22855 (BSL_META_U(unit, 22856 "OAM(unit %d) Error: failed to set MPLS LM DM event mask-" 22857 " %s.\n"), unit, bcm_errmsg(rv))); 22858 return (rv); 22859 } 22860 } 22861 #endif 22862 22863 _BCM_OAM_UNLOCK(oc); 22864 return (BCM_E_NONE); 22865 } 22866 22867 /* 22868 * Function: 22869 * bcm_sb2_oam_pm_event_unregister 22870 * Purpose: 22871 * Remove a registered event from the event handler list. 22872 * Parameters: 22873 * unit - (IN) BCM device number 22874 * event_types - (IN) The set of OAM PM events for which the specified 22875 * callback should not be called 22876 * cb - (IN) A pointer to the callback function to unregister 22877 * from the specified OAM PM events 22878 * Returns: 22879 * BCM_E_XXX 22880 */ 22881 int 22882 bcm_sb2_oam_pm_event_unregister(int unit, bcm_oam_event_types_t event_types, 22883 bcm_oam_pm_event_cb cb) 22884 { 22885 _bcm_oam_control_t *oc; 22886 _bcm_oam_pm_event_handler_t *event_h_p; 22887 _bcm_oam_pm_event_handler_t *prev_p = NULL; 22888 bcm_oam_event_type_t e_type; 22889 int rv; /* Operation return status. */ 22890 uint8 msg_class = 0; 22891 uint16 reply_len = 0; 22892 uint8 msg_subclass = 0; 22893 uint8 msg_reply_subclass = 0; 22894 22895 /* Validate event callback input parameter. */ 22896 if (NULL == cb) { 22897 return (BCM_E_PARAM); 22898 } 22899 22900 /* Validate the event type to be of PM event type */ 22901 if (!_BCM_SB2_EVENT_TYPE_PM_EVENT(event_types)) { 22902 return (BCM_E_PARAM); 22903 } 22904 22905 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 22906 22907 _BCM_OAM_LOCK(oc); 22908 22909 for (event_h_p = oc->pm_event_handler_list_p; event_h_p != NULL; 22910 event_h_p = event_h_p->next_p) { 22911 if (event_h_p->cb == cb) { 22912 break; 22913 } 22914 prev_p = event_h_p; 22915 } 22916 22917 if (NULL == event_h_p) { 22918 _BCM_OAM_UNLOCK(oc); 22919 return (BCM_E_NOT_FOUND); 22920 } 22921 22922 for (e_type = bcmOAMEventBHHRawData; 22923 e_type <= bcmOAMEventMplsLmDmRawData; 22924 ++e_type) { 22925 22926 if (SHR_BITGET(event_types.w, e_type)) { 22927 if ((oc->pm_event_handler_cnt[e_type] > 0) 22928 && SHR_BITGET(event_h_p->event_types.w, e_type)) { 22929 22930 /* Remove this event from the registered events list. */ 22931 SHR_BITCLR(event_h_p->event_types.w, e_type); 22932 22933 oc->pm_event_handler_cnt[e_type] -= 1; 22934 22935 if (oc->pm_event_handler_cnt[e_type] == 0) { 22936 /* There are no event handlers for this event type 22937 * Send msg to uKernel to stop notifying this event. 22938 */ 22939 if (e_type == bcmOAMEventBHHRawData) { 22940 msg_class = MOS_MSG_CLASS_BHH; 22941 msg_subclass = 22942 MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_UNSET; 22943 msg_reply_subclass = 22944 MOS_MSG_SUBCLASS_BHH_PM_RAW_DATA_EVENT_UNSET_REPLY; 22945 } 22946 if (e_type == bcmOAMEventMplsLmDmRawData) { 22947 msg_class = MOS_MSG_CLASS_MPLS_LM_DM; 22948 msg_subclass = 22949 MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_UNSET; 22950 msg_reply_subclass = 22951 MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_RAW_DATA_EVENT_UNSET_REPLY; 22952 } 22953 if (e_type == bcmOAMEventEthLmDmRawData) { 22954 msg_class = MOS_MSG_CLASS_ETH_LM_DM; 22955 msg_subclass = 22956 MOS_MSG_SUBCLASS_ETH_LM_DM_PM_RAW_DATA_EVENT_UNSET; 22957 msg_reply_subclass = 22958 MOS_MSG_SUBCLASS_ETH_LM_DM_PM_RAW_DATA_EVENT_UNSET_REPLY; 22959 } 22960 rv = _bcm_sb2_oam_pm_msg_send_receive 22961 (unit, msg_class, 22962 msg_subclass, 22963 0, 0, 22964 msg_reply_subclass, 22965 &reply_len); 22966 if(BCM_FAILURE(rv)) { 22967 _BCM_OAM_UNLOCK(oc); 22968 return BCM_E_INTERNAL; 22969 } 22970 } 22971 } 22972 } 22973 } 22974 22975 if (!_BCM_SB2_EVENT_TYPE_PM_EVENT(event_h_p->event_types)) { 22976 /* No more PM events for this callback registered 22977 Delete the node. */ 22978 if (NULL != prev_p) { 22979 prev_p->next_p = event_h_p->next_p; 22980 22981 } else { 22982 oc->pm_event_handler_list_p = event_h_p->next_p; 22983 } 22984 sal_free(event_h_p); 22985 } 22986 22987 _BCM_OAM_UNLOCK(oc); 22988 return (BCM_E_NONE); 22989 } 22990 22991 /* 22992 * Function: 22993 * bcm_sb2_oam_endpoint_action_set 22994 * Purpose: 22995 * Remove a registered event from the event handler list. 22996 * Parameters: 22997 * unit - (IN) BCM device number 22998 * endpoint - (IN) Endpoint id 22999 * action - (IN) Set of OAM endpoint actions, for a set of 23000 * opcodes specified. 23001 * Returns: 23002 * BCM_E_XXX 23003 * In order to put the opcodes into opcode group1 and group2, first call the 23004 * action set API with opcode action and set of opcodes that need to use 23005 * this action. This will put all these opcodes under group1. To put 23006 * the opcode to group2, call the set API with an action(with all the opcodes 23007 * that need this action) which is differing compared to group1. This will 23008 * classify the opcode to group2 23009 */ 23010 int bcm_sb2_oam_endpoint_action_set(int unit, bcm_oam_endpoint_t endpoint, 23011 bcm_oam_endpoint_action_t *action) 23012 { 23013 int rv = BCM_E_NONE; /* Operation return status. */ 23014 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 23015 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 23016 void *entries[1]; 23017 oam_opcode_control_profile_entry_t *opcode_profile = NULL; 23018 egr_oam_opcode_control_profile_entry_t *egr_opcode_profile = NULL; 23019 soc_profile_mem_t *profile_mem_ptr; 23020 soc_mem_t ma_index_mem = MA_INDEXm; 23021 ma_index_entry_t ma_idx_entry; /* MA_INDEX table entry buffer. */ 23022 egr_ma_index_entry_t egr_ma_idx_entry; /* EGR_MA_INDEX table entry buffer*/ 23023 void *ma_idx_ptr; 23024 int ma_offset = 0; 23025 uint32 profile_index = 0,old_profile_index = 0; 23026 char free_old_profile = 0; 23027 /*setting default value to 0 whcih will be converted to 1 23028 * if opcode control profile set is touched */ 23029 uint8 opcode_profile_changed = 0; 23030 23031 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 23032 _BCM_OAM_EP_INDEX_VALIDATE(endpoint); 23033 _BCM_OAM_LOCK(oc); 23034 23035 /* Check endpoint status. */ 23036 rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint); 23037 if ((BCM_E_EXISTS != rv)) { 23038 /* Endpoint not in use. */ 23039 LOG_ERROR(BSL_LS_BCM_OAM, 23040 (BSL_META_U(unit, 23041 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 23042 unit, endpoint, bcm_errmsg(rv))); 23043 _BCM_OAM_UNLOCK(oc); 23044 return (rv); 23045 } 23046 23047 h_data_p = &oc->oam_hash_data[endpoint]; 23048 if (NULL == h_data_p) { 23049 _BCM_OAM_UNLOCK(oc); 23050 return (BCM_E_INTERNAL); 23051 } 23052 23053 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 23054 egr_opcode_profile = sal_alloc(_BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE, 23055 "egr opcode profile"); 23056 if(!egr_opcode_profile) { 23057 _BCM_OAM_UNLOCK(oc); 23058 return BCM_E_MEMORY; 23059 } 23060 sal_memset(egr_opcode_profile, 0, _BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE); 23061 entries[0] = egr_opcode_profile; 23062 profile_mem_ptr = &oc->egr_oam_opcode_control_profile; 23063 ma_index_mem = EGR_MA_INDEXm; 23064 ma_idx_ptr = &egr_ma_idx_entry; 23065 } else { 23066 opcode_profile = sal_alloc(_BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE, 23067 "opcode profile"); 23068 if(!opcode_profile) { 23069 _BCM_OAM_UNLOCK(oc); 23070 return BCM_E_MEMORY; 23071 } 23072 sal_memset(opcode_profile, 0, _BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE); 23073 entries[0] = opcode_profile; 23074 profile_mem_ptr = &oc->oam_opcode_control_profile; 23075 ma_idx_ptr = &ma_idx_entry; 23076 } 23077 23078 /* Get MA_INDEX offset */ 23079 rv = _bcm_sb2_oam_ma_index_offset_get(unit, h_data_p, &ma_offset); 23080 23081 h_data_p->local_rx_index = h_data_p->ma_base_index + ma_offset; 23082 23083 /* Using the profile index, get the profile */ 23084 if ((h_data_p->profile_index == _BCM_OAM_INVALID_INDEX) || 23085 (h_data_p->profile_index == 0)) { 23086 /* No profile exists or default profile is used, create one */ 23087 /* convert action into opcode profile entry */ 23088 rv = _bcm_sb2_oam_convert_action_to_opcode_entry(unit, action, 23089 endpoint, 23090 entries[0], 23091 &opcode_profile_changed); 23092 if (BCM_FAILURE(rv)) { 23093 _BCM_OAM_UNLOCK(oc); 23094 LOG_ERROR(BSL_LS_BCM_OAM, 23095 (BSL_META_U(unit, 23096 "OAM(unit %d) Error: Failed to convert action to " 23097 "profile -" " %s.\n"), unit, bcm_errmsg(rv))); 23098 if(opcode_profile) { 23099 sal_free(opcode_profile); 23100 } 23101 if(egr_opcode_profile) { 23102 sal_free(egr_opcode_profile); 23103 } 23104 return (rv); 23105 } 23106 if(opcode_profile_changed) { 23107 rv = soc_profile_mem_add(unit, profile_mem_ptr, 23108 (void *)entries, _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE, 23109 &profile_index); 23110 if (BCM_FAILURE(rv)) { 23111 _BCM_OAM_UNLOCK(oc); 23112 LOG_ERROR(BSL_LS_BCM_OAM, 23113 (BSL_META_U(unit, 23114 "OAM(unit %d) Error: Soc profile mem add failed -" 23115 " %s.\n"), unit, bcm_errmsg(rv))); 23116 if(opcode_profile) { 23117 sal_free(opcode_profile); 23118 } 23119 if(egr_opcode_profile) { 23120 sal_free(egr_opcode_profile); 23121 } 23122 return (rv); 23123 } 23124 } 23125 } else { 23126 free_old_profile = 1; 23127 old_profile_index = h_data_p->profile_index; 23128 23129 rv = soc_profile_mem_get(unit, profile_mem_ptr, 23130 _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(old_profile_index), 23131 _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE, entries); 23132 if (BCM_FAILURE(rv)) { 23133 _BCM_OAM_UNLOCK(oc); 23134 LOG_ERROR(BSL_LS_BCM_OAM, 23135 (BSL_META_U(unit, 23136 "OAM(unit %d) Error: Soc profile mem get failed -" 23137 " %s.\n"), unit, bcm_errmsg(rv))); 23138 if(opcode_profile) { 23139 sal_free(opcode_profile); 23140 } 23141 if(egr_opcode_profile) { 23142 sal_free(egr_opcode_profile); 23143 } 23144 return (rv); 23145 } 23146 23147 /* convert action into opcode profile entry */ 23148 _bcm_sb2_oam_convert_action_to_opcode_entry(unit, action, 23149 endpoint, 23150 entries[0], 23151 &opcode_profile_changed); 23152 23153 /* Add new profile */ 23154 rv = soc_profile_mem_add(unit, profile_mem_ptr, 23155 (void *)entries, _BCM_SB2_OAM_MAX_ENTRIES_PER_PROFILE, 23156 &profile_index); 23157 if (BCM_FAILURE(rv)) { 23158 _BCM_OAM_UNLOCK(oc); 23159 LOG_ERROR(BSL_LS_BCM_OAM, 23160 (BSL_META_U(unit, 23161 "OAM(unit %d) Error: Soc profile mem add failed -" 23162 " %s.\n"), unit, bcm_errmsg(rv))); 23163 if(opcode_profile) { 23164 sal_free(opcode_profile); 23165 } 23166 if(egr_opcode_profile) { 23167 sal_free(egr_opcode_profile); 23168 } 23169 return (rv); 23170 } 23171 } 23172 /* Set OAM opcode control profile table index. */ 23173 rv = soc_mem_read(unit, ma_index_mem, MEM_BLOCK_ANY, 23174 h_data_p->local_rx_index, ma_idx_ptr); 23175 if (BCM_FAILURE(rv)) { 23176 _BCM_OAM_UNLOCK(oc); 23177 LOG_ERROR(BSL_LS_BCM_OAM, 23178 (BSL_META_U(unit, 23179 "OAM(unit %d) Error: MA index table entry read failed " 23180 "%s.\n"), unit, bcm_errmsg(rv))); 23181 if(opcode_profile) { 23182 sal_free(opcode_profile); 23183 } 23184 if(egr_opcode_profile) { 23185 sal_free(egr_opcode_profile); 23186 } 23187 return (rv); 23188 } 23189 h_data_p->profile_index = 23190 _BCM_SB2_OAM_GET_PROFILE_PTR_FROM_INDEX(profile_index); 23191 soc_mem_field32_set(unit, ma_index_mem, ma_idx_ptr, 23192 OAM_OPCODE_CONTROL_PROFILE_PTRf, 23193 h_data_p->profile_index); 23194 rv = soc_mem_write(unit, ma_index_mem, MEM_BLOCK_ALL, 23195 h_data_p->local_rx_index, ma_idx_ptr); 23196 23197 /* Delete old profile once ma_index is pointing to new one*/ 23198 if(free_old_profile) { 23199 rv = soc_profile_mem_delete(unit, profile_mem_ptr, 23200 _BCM_SB2_OAM_GET_FIRST_INDEX_FROM_PROFILE_PTR(old_profile_index) 23201 ); 23202 if (BCM_FAILURE(rv)) { 23203 _BCM_OAM_UNLOCK(oc); 23204 LOG_ERROR(BSL_LS_BCM_OAM, 23205 (BSL_META_U(unit, 23206 "OAM(unit %d) Error: Soc profile mem delete failed -" 23207 " %s.\n"), unit, bcm_errmsg(rv))); 23208 if(opcode_profile) { 23209 sal_free(opcode_profile); 23210 } 23211 if(egr_opcode_profile) { 23212 sal_free(egr_opcode_profile); 23213 } 23214 return (rv); 23215 } 23216 } 23217 _BCM_OAM_UNLOCK(oc); 23218 if(opcode_profile) { 23219 sal_free(opcode_profile); 23220 } 23221 if(egr_opcode_profile) { 23222 sal_free(egr_opcode_profile); 23223 } 23224 return rv; 23225 } 23226 23227 int 23228 _bcm_sb2_oam_mpls_lm_dm_endpoint_actions_verify(int unit, 23229 _bcm_oam_hash_data_t *h_data_p, 23230 bcm_oam_action_type_t action) 23231 { 23232 switch(action) { 23233 case bcmOAMActionMcDrop: 23234 case bcmOAMActionMcCopyToCpu: 23235 case bcmOAMActionMcFwdAsData: 23236 case bcmOAMActionMcFwd: 23237 case bcmOAMActionMCProcessInInternalOamEngine: 23238 /* Multicast actions are not applicable for MPLS LM DM endpoints */ 23239 case bcmOAMActionL2StationHitProcessInInternalOamEngine: 23240 case bcmOAMActionL2StationMissProcessInInternalOamEngine: 23241 case bcmOAMActionLowMdlProcessInInternalOamEngine: 23242 case bcmOAMActionProcessInHw: 23243 /* Process in CCM/LB engine and HW are not applicable for MPLS LM/DM 23244 endpoints */ 23245 case bcmOAMActionMyStationMissCopyToCpu: 23246 case bcmOAMActionMyStationMissDrop: 23247 case bcmOAMActionMyStationMissFwdAsData: 23248 case bcmOAMActionMyStationMissFwd: 23249 case bcmOAMActionLowMdlDrop: 23250 case bcmOAMActionLowMdlCopyToCpu: 23251 case bcmOAMActionLowMdlFwdAsData: 23252 case bcmOAMActionLowMdlFwd: 23253 /* My station miss and low mdl actions are not applicable for 23254 MPLS LM/DM endpoints */ 23255 if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) || 23256 BHH_EP_TYPE(h_data_p)) { 23257 return BCM_E_PARAM; 23258 } 23259 break; 23260 default: 23261 return BCM_E_NONE; 23262 break; 23263 } 23264 return BCM_E_NONE; 23265 } 23266 23267 /* 23268 * Function: 23269 * _sb2_oam_opcode_control_field_set 23270 * Purpose: 23271 * Set the fields of opcode profile entry 23272 * Parameters: 23273 * unit - (IN) BCM device number 23274 * field_index - (IN) Opcode profile action to be set 23275 * mem - (IN) Opcode profile memory - ing/egr 23276 * oam_opcode - (IN) Oam opcode for which action needs to be set 23277 * value - (IN) value for the field to be set 23278 * profile - (OUT) Pointer to the opcode profile table index. 23279 * Returns: 23280 * BCM_E_XXX 23281 */ 23282 int 23283 _sb2_oam_opcode_control_field_set(int unit, _bcm_oam_hash_data_t *h_data_p, 23284 bcm_oam_action_type_t action, 23285 soc_mem_t mem, int oam_opcode, uint32 value, 23286 void *profile) 23287 { 23288 soc_field_t fields[3] = {0, 0, 0}; 23289 int index, num_fields = 0; 23290 int do_nothing = 0; 23291 int opcode_group_index = 0; 23292 oam_opcode_control_profile_entry_t *temp_entry = NULL; 23293 oam_opcode_control_profile_entry_t *actual_entry = NULL; 23294 23295 23296 /* Verify actions that are set on MPLS LM DM endpoints is valid */ 23297 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_mpls_lm_dm_endpoint_actions_verify(unit, 23298 h_data_p, 23299 action)); 23300 23301 opcode_group_index = _bcm_sb2_opcode_to_opcode_group_index(unit, h_data_p, 23302 oam_opcode); 23303 if(opcode_group_index < 0) 23304 { 23305 return BCM_E_PARAM; 23306 } 23307 temp_entry = (oam_opcode_control_profile_entry_t *)profile; 23308 actual_entry = &(temp_entry[opcode_group_index]); 23309 23310 switch (action) { 23311 /* General: Both UC and MC */ 23312 case bcmOAMActionCopyToCpu: 23313 fields[0] = UC_MY_STATION_HIT_COPYTO_CPUf; 23314 num_fields = 1; 23315 if (!MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) && 23316 !BHH_EP_TYPE(h_data_p)) { 23317 fields[1] = MC_COPYTO_CPUf; 23318 num_fields = 2; 23319 if(oam_opcode == _BCM_OAM_OPCODE_TYPE_CCM) { 23320 fields[2] = UC_MY_STATION_MISS_COPYTO_CPUf; 23321 num_fields = 3; 23322 } 23323 } 23324 break; 23325 23326 case bcmOAMActionFwdAsData: 23327 fields[0] = UC_MY_STATION_HIT_ACTIONf; 23328 num_fields = 1; 23329 if (!MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) && 23330 !BHH_EP_TYPE(h_data_p)) { 23331 fields[1] = MC_ACTIONf; 23332 num_fields = 2; 23333 if(oam_opcode == _BCM_OAM_OPCODE_TYPE_CCM) { 23334 fields[2] = UC_MY_STATION_MISS_ACTIONf; 23335 num_fields = 3; 23336 } 23337 } 23338 break; 23339 23340 case bcmOAMActionFwd: 23341 fields[0] = UC_MY_STATION_HIT_ACTIONf; 23342 num_fields = 1; 23343 if (!MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) && 23344 !BHH_EP_TYPE(h_data_p)) { 23345 fields[1] = MC_ACTIONf; 23346 num_fields = 2; 23347 if(oam_opcode == _BCM_OAM_OPCODE_TYPE_CCM) { 23348 fields[2] = UC_MY_STATION_MISS_ACTIONf; 23349 num_fields = 3; 23350 } 23351 } 23352 break; 23353 23354 case bcmOAMActionProcessInHw: 23355 if((oam_opcode == _BCM_OAM_OPCODE_TYPE_LBM) || 23356 (oam_opcode == _BCM_OAM_OPCODE_TYPE_LBR)){ 23357 fields[0] = UC_MY_STATION_HIT_ACTIONf; 23358 if(oam_opcode == _BCM_OAM_OPCODE_TYPE_LBM) { 23359 /* Only LBM can be UC or MC. */ 23360 fields[1] = MC_ACTIONf; 23361 num_fields = 2; 23362 } else { 23363 num_fields = 1; 23364 } 23365 } else if(oam_opcode == _BCM_OAM_OPCODE_TYPE_CCM) { 23366 fields[0] = UC_MY_STATION_HIT_ACTIONf; 23367 fields[1] = UC_MY_STATION_MISS_ACTIONf; 23368 fields[2] = MC_ACTIONf; 23369 num_fields = 3; 23370 } 23371 break; 23372 23373 case bcmOAMActionDrop: 23374 fields[0] = UC_MY_STATION_HIT_ACTIONf; 23375 num_fields = 1; 23376 if (!MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) && 23377 !BHH_EP_TYPE(h_data_p)) { 23378 fields[1] = MC_ACTIONf; 23379 num_fields = 2; 23380 if(oam_opcode == _BCM_OAM_OPCODE_TYPE_CCM) { 23381 fields[2] = UC_MY_STATION_MISS_ACTIONf; 23382 num_fields = 3; 23383 } 23384 } 23385 break; 23386 23387 /* UC actions */ 23388 case bcmOAMActionUcCopyToCpu: 23389 fields[0] = UC_MY_STATION_HIT_COPYTO_CPUf; 23390 num_fields = 1; 23391 break; 23392 23393 case bcmOAMActionUcFwdAsData: 23394 fields[0] = UC_MY_STATION_HIT_ACTIONf; 23395 num_fields = 1; 23396 break; 23397 23398 case bcmOAMActionUcFwd: 23399 fields[0] = UC_MY_STATION_HIT_ACTIONf; 23400 num_fields = 1; 23401 break; 23402 23403 23404 case bcmOAMActionL2StationHitProcessInInternalOamEngine: 23405 fields[0] = UC_MY_STATION_HIT_ACTIONf; 23406 num_fields = 1; 23407 break; 23408 23409 case bcmOAMActionUcDrop: 23410 fields[0] = UC_MY_STATION_HIT_ACTIONf; 23411 num_fields = 1; 23412 break; 23413 23414 /* MC actions */ 23415 case bcmOAMActionMcDrop: 23416 fields[0] = MC_ACTIONf; 23417 num_fields = 1; 23418 break; 23419 23420 case bcmOAMActionMcCopyToCpu: 23421 fields[0] = MC_COPYTO_CPUf; 23422 num_fields = 1; 23423 break; 23424 23425 case bcmOAMActionMcFwdAsData: 23426 fields[0] = MC_ACTIONf; 23427 num_fields = 1; 23428 break; 23429 23430 case bcmOAMActionMcFwd: 23431 fields[0] = MC_ACTIONf; 23432 num_fields = 1; 23433 break; 23434 23435 case bcmOAMActionMCProcessInInternalOamEngine: 23436 fields[0] = MC_ACTIONf; 23437 num_fields = 1; 23438 break; 23439 23440 /* Low MDL actions */ 23441 case bcmOAMActionLowMdlDrop: 23442 fields[0] = LOW_MDL_ACTIONf; 23443 num_fields = 1; 23444 break; 23445 23446 case bcmOAMActionLowMdlCopyToCpu: 23447 fields[0] = LOW_MDL_COPYTO_CPUf; 23448 num_fields = 1; 23449 break; 23450 23451 case bcmOAMActionLowMdlFwdAsData: 23452 fields[0] = LOW_MDL_ACTIONf; 23453 num_fields = 1; 23454 break; 23455 23456 case bcmOAMActionLowMdlFwd: 23457 fields[0] = LOW_MDL_ACTIONf; 23458 num_fields = 1; 23459 break; 23460 23461 case bcmOAMActionLowMdlCcmFwdAsRegularCcm: 23462 /* Not supported in Saber2 */ 23463 do_nothing = 1; 23464 break; 23465 23466 case bcmOAMActionLowMdlProcessInInternalOamEngine: 23467 fields[0] = LOW_MDL_ACTIONf; 23468 num_fields = 1; 23469 break; 23470 23471 /* UC station hit miss actions */ 23472 23473 case bcmOAMActionMyStationMissCopyToCpu: 23474 fields[0] = UC_MY_STATION_MISS_COPYTO_CPUf; 23475 num_fields = 1; 23476 break; 23477 23478 case bcmOAMActionMyStationMissDrop: 23479 fields[0] = UC_MY_STATION_MISS_ACTIONf; 23480 num_fields = 1; 23481 break; 23482 23483 case bcmOAMActionMyStationMissFwdAsData: 23484 fields[0] = UC_MY_STATION_MISS_ACTIONf; 23485 num_fields = 1; 23486 break; 23487 23488 case bcmOAMActionMyStationMissFwd: 23489 fields[0] = UC_MY_STATION_MISS_ACTIONf; 23490 num_fields = 1; 23491 break; 23492 23493 case bcmOAMActionL2StationMissProcessInInternalOamEngine: 23494 fields[0] = UC_MY_STATION_MISS_ACTIONf; 23495 num_fields = 1; 23496 break; 23497 23498 /* Misc actions */ 23499 case bcmOAMActionSLMEnable: 23500 /* Not supported in Saber2 */ 23501 do_nothing = 1; 23502 break; 23503 23504 case bcmOAMActionSampleTimeStamp: 23505 fields[0] = EQUAL_MDL_SAMPLE_TIMESTAMPf; 23506 num_fields = 1; 23507 break; 23508 case bcmOAMActionSampleLmCounter: 23509 fields[0] = EQUAL_MDL_SAMPLE_LM_COUNTERf; 23510 num_fields = 1; 23511 break; 23512 23513 default: 23514 do_nothing = 1; 23515 break; 23516 } 23517 if(!do_nothing){ 23518 for(index = 0; index < num_fields; index++){ 23519 soc_mem_field32_set(unit, mem, actual_entry, fields[index], 23520 value); 23521 } 23522 } 23523 return (BCM_E_NONE); 23524 } 23525 23526 /* 23527 * Function: 23528 * _bcm_sb2_oam_resolve_dglp 23529 * Purpose: 23530 * Add an dglp profile entry 23531 * Parameters: 23532 * unit - (IN) BCM device number 23533 * mem - (IN) dglp profile memory - ing/egr 23534 * dglp - (IN) DGLP value 23535 * profile - (OUT) Pointer to the dglp profile table index. 23536 * olp_enable - (OUT) Pointer to field indicating whether olp is enabled on 23537 * the port. 23538 * Returns: 23539 * BCM_E_XXX 23540 */ 23541 int 23542 _bcm_sb2_oam_resolve_dglp(int unit, soc_mem_t mem, uint32 dglp, 23543 uint32 *profile_index, int *olp_enable) 23544 { 23545 int rv = BCM_E_NONE; 23546 egr_olp_dgpp_config_entry_t *buf; 23547 egr_olp_dgpp_config_entry_t *entry; 23548 egr_oam_dglp_profile_entry_t egr_dglp_profile_entry; 23549 ing_oam_dglp_profile_entry_t ing_dglp_profile_entry; 23550 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 23551 int index_max = 0; 23552 int index = 0; 23553 uint32 configured_dglp = 0; 23554 void *entries[1]; 23555 void *profile_entry; 23556 soc_mem_t profile_mem; 23557 soc_profile_mem_t profile_ptr; 23558 int entry_mem_size = 0; 23559 23560 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 23561 23562 if (mem == EGR_OAM_OPCODE_CONTROL_PROFILEm) { 23563 profile_entry = (void *)&egr_dglp_profile_entry; 23564 profile_mem = EGR_OAM_DGLP_PROFILEm; 23565 profile_ptr = oc->egr_oam_dglp_profile; 23566 } else { 23567 profile_entry = (void *)&ing_dglp_profile_entry; 23568 profile_mem = OAM_DGLP_PROFILEm; 23569 profile_ptr = oc->ing_oam_dglp_profile; 23570 } 23571 /* Check whether this DGLP is already configured as OLP port */ 23572 entry_mem_size = sizeof(egr_olp_dgpp_config_entry_t); 23573 /* Allocate buffer to store the DMAed table entries. */ 23574 index_max = soc_mem_index_max(unit, EGR_OLP_DGPP_CONFIGm); 23575 buf = soc_cm_salloc(unit, entry_mem_size * (index_max + 1), 23576 "OLP dglp config table entry buffer"); 23577 if (NULL == buf) { 23578 return (BCM_E_MEMORY); 23579 } 23580 /* Initialize the entry buffer. */ 23581 sal_memset(buf, 0, sizeof(entry_mem_size) * (index_max + 1)); 23582 23583 /* Read the table entries into the buffer. */ 23584 rv = soc_mem_read_range(unit, EGR_OLP_DGPP_CONFIGm, MEM_BLOCK_ALL, 23585 0, index_max, buf); 23586 if (BCM_FAILURE(rv)) { 23587 if (buf) { 23588 soc_cm_sfree(unit, buf); 23589 } 23590 return rv; 23591 } 23592 23593 /* Iterate over the table entries. */ 23594 for (index = 0; index <= index_max; index++) { 23595 entry = soc_mem_table_idx_to_pointer 23596 (unit, EGR_OLP_DGPP_CONFIGm, egr_olp_dgpp_config_entry_t *, 23597 buf, index); 23598 23599 soc_mem_field_get(unit, EGR_OLP_DGPP_CONFIGm, 23600 (uint32 *)entry, DGLPf, &configured_dglp); 23601 if (dglp == configured_dglp) { 23602 *olp_enable = 1; 23603 break; 23604 } 23605 } 23606 if (buf) { 23607 soc_cm_sfree(unit, buf); 23608 } 23609 /* Add entry to dglp profile table. */ 23610 soc_mem_field32_set(unit, profile_mem, profile_entry, DGLPf, dglp); 23611 entries[0] = profile_entry; 23612 23613 rv = soc_profile_mem_add(unit, &profile_ptr, 23614 (void *)entries, 1, profile_index); 23615 if (BCM_FAILURE(rv)) { 23616 LOG_ERROR(BSL_LS_BCM_OAM, 23617 (BSL_META_U(unit, 23618 "OAM(unit %d) DGLP profile table is full - %s.\n"), 23619 unit, bcm_errmsg(rv))); 23620 return rv; 23621 } 23622 return (BCM_E_NONE); 23623 } 23624 23625 /* 23626 * Function: 23627 * _bcm_sb2_ma_index_entry_modify 23628 * Purpose: 23629 * Set dglp profile pointer index in the MA index table entry 23630 * Parameters: 23631 * unit - (IN) BCM device number 23632 * index - (IN) MA index table index 23633 * mem - (IN) MA index memory - ing/egr 23634 * profile_index- (IN)DGLP profile index 23635 * olp_enable - (IN) indicates whether olp is enabled for this entry 23636 * dglp_prt - (OUT) Pointer to dglp1/2 profile. 23637 * Returns: 23638 * BCM_E_XXX 23639 */ 23640 int 23641 _bcm_sb2_ma_index_entry_modify(int unit, int index, soc_mem_t mem, 23642 int profile_index, int olp_enable, int *dglp_ptr) 23643 { 23644 int rv = BCM_E_NONE; 23645 ma_index_entry_t ma_idx_entry; /* MA_INDEX table entry buffer. */ 23646 egr_ma_index_entry_t egr_ma_idx_entry; /* EGR_MA_INDEX table entry buffer.*/ 23647 void *entry; 23648 23649 if (mem == EGR_MA_INDEXm) { 23650 entry = (void *)&egr_ma_idx_entry; 23651 } else { 23652 entry = (void *)&ma_idx_entry; 23653 } 23654 rv = soc_mem_read(unit, mem, MEM_BLOCK_ANY, index, entry); 23655 if (BCM_FAILURE(rv)) { 23656 LOG_ERROR(BSL_LS_BCM_OAM, 23657 (BSL_META_U(unit, 23658 "OAM(unit %d) Error: MA index table entry read failed " 23659 "%s.\n"), unit, bcm_errmsg(rv))); 23660 return (rv); 23661 } 23662 if (0 == soc_mem_field32_get(unit, mem, (uint32 *)entry, 23663 DGLP1_PROFILE_PTRf)){ 23664 23665 soc_mem_field32_set(unit, mem, entry, 23666 DGLP1_PROFILE_PTRf, profile_index); 23667 if (olp_enable) { 23668 soc_mem_field32_set(unit, mem, entry, DGLP1_OLP_HDR_ADDf, 1); 23669 } 23670 *dglp_ptr = _BCM_OAM_DGLP1_PROFILE_PTR; 23671 } else if (0 == soc_mem_field32_get(unit, mem, (uint32 *)entry, 23672 DGLP2_PROFILE_PTRf)){ 23673 23674 soc_mem_field32_set(unit, mem, entry, 23675 DGLP2_PROFILE_PTRf, profile_index); 23676 if (olp_enable) { 23677 soc_mem_field32_set(unit, mem, entry, DGLP2_OLP_HDR_ADDf, 1); 23678 } 23679 *dglp_ptr = _BCM_OAM_DGLP2_PROFILE_PTR; 23680 } 23681 SOC_IF_ERROR_RETURN(soc_mem_write(unit, mem, MEM_BLOCK_ANY, index, entry)); 23682 return (BCM_E_NONE); 23683 } 23684 23685 /* 23686 * Function: 23687 * _sb2_oam_counter_control_set 23688 * Purpose: 23689 * Enable/disable LM counter for a particular opcode 23690 * Parameters: 23691 * unit - (IN) BCM device number 23692 * opcode_i - (IN) OAM opcode for which counter needs 23693 * to be enabled/disabled 23694 * value - (IN) Counter enable/disable 23695 * Returns: 23696 * BCM_E_XXX 23697 */ 23698 int 23699 _sb2_oam_counter_control_set(int unit, int opcode_i, int value) 23700 { 23701 int rv = BCM_E_NONE; 23702 egr_lm_counter_control_entry_t egr_ctr; 23703 lm_counter_control_entry_t ing_ctr; 23704 23705 rv = soc_mem_read(unit, ING_LM_COUNTER_CONTROLm, MEM_BLOCK_ANY, 23706 opcode_i, &ing_ctr); 23707 if (BCM_FAILURE(rv)) { 23708 LOG_ERROR(BSL_LS_BCM_OAM, 23709 (BSL_META_U(unit, 23710 "OAM(unit %d) Error: Counter control table entry read " 23711 "failed %s.\n"), unit, bcm_errmsg(rv))); 23712 return (rv); 23713 } 23714 soc_ING_LM_COUNTER_CONTROLm_field32_set(unit, &ing_ctr, COUNT_ENABLEf, value); 23715 rv = soc_mem_write(unit, ING_LM_COUNTER_CONTROLm, MEM_BLOCK_ALL, 23716 opcode_i, &ing_ctr); 23717 if (BCM_FAILURE(rv)) { 23718 LOG_ERROR(BSL_LS_BCM_OAM, 23719 (BSL_META_U(unit, 23720 "OAM(unit %d) Error: Counter control table entry wtite " 23721 "failed %s.\n"), unit, bcm_errmsg(rv))); 23722 return (rv); 23723 } 23724 rv = soc_mem_read(unit, EGR_LM_COUNTER_CONTROLm, MEM_BLOCK_ANY, 23725 opcode_i, &egr_ctr); 23726 if (BCM_FAILURE(rv)) { 23727 LOG_ERROR(BSL_LS_BCM_OAM, 23728 (BSL_META_U(unit, 23729 "OAM(unit %d) Error: Counter control table entry read " 23730 "failed %s.\n"), unit, bcm_errmsg(rv))); 23731 return (rv); 23732 } 23733 soc_EGR_LM_COUNTER_CONTROLm_field32_set(unit, &egr_ctr, 23734 COUNT_ENABLEf, value); 23735 rv = soc_mem_write(unit, EGR_LM_COUNTER_CONTROLm, MEM_BLOCK_ALL, 23736 opcode_i, &ing_ctr); 23737 if (BCM_FAILURE(rv)) { 23738 LOG_ERROR(BSL_LS_BCM_OAM, 23739 (BSL_META_U(unit, 23740 "OAM(unit %d) Error: Counter control table entry wtite " 23741 "failed %s.\n"), unit, bcm_errmsg(rv))); 23742 return (rv); 23743 } 23744 return rv; 23745 } 23746 23747 /* 23748 * Function: 23749 * _bcm_sb2_oam_convert_action_to_opcode_entry 23750 * Purpose: 23751 * Convert endpoint action to opcode profile entry action 23752 * Parameters: 23753 * unit - (IN) BCM device number 23754 * action - (IN) Pointer to endpoint action 23755 * ep_id - (IN) Endpoint id 23756 * profile - (IN) Opcode profile table entry 23757 * Returns: 23758 * BCM_E_XXX 23759 */ 23760 int 23761 _bcm_sb2_oam_convert_action_to_opcode_entry(int unit, 23762 bcm_oam_endpoint_action_t *action, 23763 bcm_oam_endpoint_t ep_id, 23764 void *profile, 23765 uint8 *opcode_profile_changed) 23766 { 23767 int rv = BCM_E_NONE; 23768 int action_i = 0; 23769 int opcode_i = 0; 23770 int break_the_loop = 0; 23771 int profile_index = _BCM_OAM_INVALID_INDEX; 23772 int olp_enable = 0; 23773 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 23774 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 23775 soc_mem_t mem = OAM_OPCODE_CONTROL_PROFILEm; 23776 soc_mem_t ma_index_mem = MA_INDEXm; 23777 int dglp_ptr = 0; 23778 int skip_ma_index_modify = 0; 23779 int value = 0; 23780 bcm_module_t module_id; 23781 bcm_port_t port_id; 23782 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 23783 int local_id; 23784 uint32 dglp = 0; 23785 int reset = 0; 23786 23787 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 23788 23789 h_data_p = &oc->oam_hash_data[ep_id]; 23790 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 23791 ma_index_mem = EGR_MA_INDEXm; 23792 mem = EGR_OAM_OPCODE_CONTROL_PROFILEm; 23793 } 23794 23795 reset = (action->flags & BCM_OAM_ENDPOINT_ACTION_DISABLE)?1:0; 23796 23797 23798 for (action_i = 0; action_i < bcmOAMActionCount; action_i++) { 23799 if (BCM_OAM_ACTION_GET(*action, action_i)) { 23800 for (opcode_i = 0; opcode_i <= _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST; 23801 opcode_i++) { 23802 if (BCM_OAM_OPCODE_GET(*action, opcode_i)) { 23803 switch (action_i) { 23804 case bcmOAMActionCountEnable: 23805 if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 23806 rv = _bcm_sb2_mpls_lmdm_ach_type_counter_enable(unit, opcode_i, !reset); 23807 } else { 23808 rv = _sb2_oam_counter_control_set(unit, opcode_i, !reset); 23809 } 23810 if (BCM_FAILURE(rv)) { 23811 LOG_ERROR(BSL_LS_BCM_OAM, 23812 (BSL_META_U(unit, 23813 "OAM(unit %d) Error:Counter control " 23814 "set - %s.\n"), unit, bcm_errmsg(rv))); 23815 return (rv); 23816 } 23817 break; 23818 23819 case bcmOAMActionDrop: 23820 case bcmOAMActionUcDrop: 23821 case bcmOAMActionMcDrop: 23822 case bcmOAMActionLowMdlDrop: 23823 case bcmOAMActionMyStationMissDrop: 23824 rv = _sb2_oam_opcode_control_field_set(unit, h_data_p, 23825 action_i, mem, opcode_i, 23826 reset?0:_BCM_SB2_OAM_OC_PROF_DROP, 23827 profile); 23828 *opcode_profile_changed = 1; 23829 break; 23830 23831 case bcmOAMActionCopyToCpu: 23832 case bcmOAMActionUcCopyToCpu: 23833 case bcmOAMActionMcCopyToCpu: 23834 case bcmOAMActionLowMdlCopyToCpu: 23835 case bcmOAMActionMyStationMissCopyToCpu: 23836 rv = _sb2_oam_opcode_control_field_set(unit, h_data_p, 23837 action_i, mem, opcode_i, 23838 !reset, profile); 23839 *opcode_profile_changed = 1; 23840 break; 23841 23842 case bcmOAMActionFwdAsData: 23843 if (opcode_i == _BCM_OAM_OPCODE_TYPE_CCM) { 23844 rv = _sb2_oam_opcode_control_field_set(unit, h_data_p, 23845 action_i, mem, opcode_i, 23846 /* Need not check reset in this case 23847 since this is default case */ 23848 _BCM_SB2_OAM_OC_PROF_NORMAL_SWITCHING, 23849 profile); 23850 break_the_loop = 1; 23851 } 23852 *opcode_profile_changed = 1; 23853 break; 23854 23855 case bcmOAMActionFwd: 23856 case bcmOAMActionUcFwd: 23857 case bcmOAMActionMcFwd: 23858 case bcmOAMActionLowMdlFwd: 23859 case bcmOAMActionMyStationMissFwd: 23860 /* forward packets to DGLP1 or DGLP2 */ 23861 /* Dont bother about dglp related info if 23862 * reset is set 23863 */ 23864 if (!skip_ma_index_modify && !reset) { 23865 SOC_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, 23866 action->destination, &module_id, 23867 &port_id, &trunk_id, &local_id)); 23868 if (BCM_GPORT_IS_TRUNK(action->destination) && 23869 (trunk_id != BCM_TRUNK_INVALID)) { 23870 /* Set LAG ID indicator bit */ 23871 dglp |= (1 << DGLP_LAG_ID_INDICATOR_SHIFT_BITS); 23872 } 23873 dglp |= ((module_id << DGLP_MODULE_ID_SHIFT_BITS) + port_id); 23874 23875 if (dglp == h_data_p->dglp1) { 23876 skip_ma_index_modify = 1; 23877 dglp_ptr = _BCM_OAM_DGLP1_PROFILE_PTR; 23878 value = _BCM_SB2_OAM_OC_PROF_FWD_TO_DGLP1; 23879 } else if (dglp == h_data_p->dglp2) { 23880 skip_ma_index_modify = 1; 23881 dglp_ptr = _BCM_OAM_DGLP2_PROFILE_PTR; 23882 value = _BCM_SB2_OAM_OC_PROF_FWD_TO_DGLP2; 23883 /* if both dglp1 and dglp2 are already set, 23884 return error */ 23885 } else if ((h_data_p->dglp1 > 0) && 23886 (h_data_p->dglp2 > 0)) { 23887 LOG_ERROR(BSL_LS_BCM_OAM, 23888 (BSL_META_U(unit, 23889 "OAM(unit %d) Error: Invalid action" 23890 "destination - %s.\n"), unit, bcm_errmsg(rv))); 23891 return BCM_E_PARAM; 23892 } 23893 if (!skip_ma_index_modify) { 23894 rv = _bcm_sb2_oam_resolve_dglp(unit, mem, 23895 dglp, (uint32 *)&profile_index, 23896 &olp_enable); 23897 if (BCM_FAILURE(rv)) { 23898 LOG_ERROR(BSL_LS_BCM_OAM, 23899 (BSL_META_U(unit, 23900 "OAM(unit %d) Error: Gport " 23901 "to dglp-%s\n"), unit, bcm_errmsg(rv))); 23902 return (rv); 23903 } 23904 if (profile_index != _BCM_OAM_INVALID_INDEX) { 23905 /* modify MA_INDEX table entry */ 23906 rv = _bcm_sb2_ma_index_entry_modify(unit, 23907 h_data_p->local_rx_index, 23908 ma_index_mem, profile_index, 23909 olp_enable, &dglp_ptr); 23910 if (BCM_FAILURE(rv)) { 23911 return rv; 23912 } 23913 if (dglp_ptr == 23914 _BCM_OAM_DGLP1_PROFILE_PTR) { 23915 h_data_p->dglp1 = dglp; 23916 h_data_p->dglp1_profile_index = 23917 profile_index; 23918 value = _BCM_SB2_OAM_OC_PROF_FWD_TO_DGLP1; 23919 } else { 23920 h_data_p->dglp2 = dglp; 23921 h_data_p->dglp2_profile_index = 23922 profile_index; 23923 value = _BCM_SB2_OAM_OC_PROF_FWD_TO_DGLP2; 23924 } 23925 skip_ma_index_modify = 1; 23926 } 23927 } 23928 } 23929 if ((!reset) && (dglp_ptr == 0)) { 23930 break; 23931 } 23932 /* Opcode control value is to bet set to 2 for 23933 DGLP1 and 3 for DGLP2 */ 23934 rv = _sb2_oam_opcode_control_field_set(unit, h_data_p, action_i, 23935 mem, opcode_i, reset?0:value, profile); 23936 *opcode_profile_changed = 1; 23937 break; 23938 23939 case bcmOAMActionUcFwdAsData: 23940 case bcmOAMActionMcFwdAsData: 23941 case bcmOAMActionLowMdlFwdAsData: 23942 case bcmOAMActionMyStationMissFwdAsData: 23943 rv = _sb2_oam_opcode_control_field_set(unit, h_data_p, 23944 action_i, mem, opcode_i, 23945 /* Need not check reset in this case 23946 since this is default case */ 23947 _BCM_SB2_OAM_OC_PROF_NORMAL_SWITCHING, 23948 profile); 23949 *opcode_profile_changed = 1; 23950 break; 23951 23952 case bcmOAMActionProcessInHw: 23953 case bcmOAMActionLowMdlProcessInInternalOamEngine: 23954 case bcmOAMActionL2StationMissProcessInInternalOamEngine: 23955 case bcmOAMActionMCProcessInInternalOamEngine: 23956 rv = _sb2_oam_opcode_control_field_set(unit, h_data_p, 23957 action_i, mem, opcode_i, 23958 reset?0:_BCM_SB2_OAM_OC_PROF_FWD_TO_HW_ENGINE, 23959 profile); 23960 break_the_loop = 1; 23961 *opcode_profile_changed = 1; 23962 /* TBD - When CCM processing is done in HW, MA_PTR 23963 value in MA_INDEX table should be less than 2k. 23964 If not, we should return error */ 23965 break; 23966 case bcmOAMActionL2StationHitProcessInInternalOamEngine: 23967 if((opcode_i == _BCM_OAM_OPCODE_TYPE_LBM) || 23968 (opcode_i == _BCM_OAM_OPCODE_TYPE_LBR)){ 23969 rv = _sb2_oam_opcode_control_field_set(unit, h_data_p, 23970 action_i, mem, opcode_i, 23971 reset?0:_BCM_SB2_OAM_OC_PROF_FWD_TO_HW_LB_ENGINE, 23972 profile); 23973 } else if(opcode_i == _BCM_OAM_OPCODE_TYPE_CCM) { 23974 rv = _sb2_oam_opcode_control_field_set(unit, h_data_p, 23975 action_i, mem, opcode_i, 23976 reset?0:_BCM_SB2_OAM_OC_PROF_FWD_TO_HW_ENGINE, 23977 profile); 23978 } 23979 break_the_loop = 1; 23980 *opcode_profile_changed = 1; 23981 break; 23982 case bcmOAMActionLowMdlCcmFwdAsRegularCcm: 23983 /* Not supported in SB2 */ 23984 break; 23985 23986 case bcmOAMActionSampleLmCounter: 23987 if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 23988 if ((opcode_i == bcmOamMplsLmDmOpcodeTypeIlm) || 23989 (opcode_i == bcmOamMplsLmDmOpcodeTypeIlmPlusDm) 23990 ) { 23991 /* ILM opcodes are NOT expected to 23992 sample LM counters */ 23993 return BCM_E_PARAM; 23994 } 23995 } 23996 /* Fall thru */ 23997 case bcmOAMActionSampleTimeStamp: 23998 rv = _sb2_oam_opcode_control_field_set(unit, h_data_p, 23999 action_i, mem, opcode_i, 24000 !reset, profile); 24001 *opcode_profile_changed = 1; 24002 break; 24003 24004 24005 default: 24006 break; 24007 } 24008 } 24009 if (break_the_loop) { 24010 dglp_ptr = 0; 24011 break_the_loop = 0; 24012 olp_enable = 0; 24013 profile_index = _BCM_OAM_INVALID_INDEX; 24014 break; 24015 } 24016 } 24017 } 24018 } 24019 return rv; 24020 } 24021 24022 /* 24023 * Function: 24024 * _bcm_sb2_oam_flex_drop_get 24025 * Purpose: 24026 * Query the value of the device-wide OAM control. 24027 * Parameters: 24028 * unit - (IN) BCM device number 24029 * type - (IN) OAM control type 24030 * arg - (OUT) A pointer to value of the control 24031 * Returns: 24032 * BCM_E_XXX 24033 */ 24034 int _bcm_sb2_oam_flex_drop_get(int unit, bcm_oam_control_type_t type, 24035 uint64 *arg) 24036 { 24037 uint32 rval_32; 24038 soc_reg_t reg = 0; 24039 uint32 is_64bit_reg = 0; 24040 int rv = BCM_E_NONE; 24041 24042 switch(type) { 24043 case bcmOamControlFlexibleDropPort: 24044 reg = OAM_PORT_INTERFACE_DROP_CONTROLr; 24045 break; 24046 24047 case bcmOamControlFlexibleDropCVlan: 24048 reg = OAM_C_INTERFACE_DROP_CONTROLr; 24049 break; 24050 24051 case bcmOamControlFlexibleDropSVlan: 24052 reg = OAM_S_INTERFACE_DROP_CONTROLr; 24053 break; 24054 24055 case bcmOamControlFlexibleDropCPlusSVlan: 24056 reg = OAM_S_C_INTERFACE_DROP_CONTROLr; 24057 break; 24058 24059 case bcmOamControlFlexibleDropVP: 24060 reg = OAM_SVP_INTERFACE_DROP_CONTROLr; 24061 break; 24062 24063 case bcmOamControlFlexibleDropEgressPort: 24064 reg = EGR_OAM_PORT_INTERFACE_DROP_CONTROL_64r; 24065 is_64bit_reg = 1; 24066 break; 24067 24068 case bcmOamControlFlexibleDropEgressCVlan: 24069 reg = EGR_OAM_C_INTERFACE_DROP_CONTROL_64r; 24070 is_64bit_reg = 1; 24071 break; 24072 24073 case bcmOamControlFlexibleDropEgressSVlan: 24074 reg = EGR_OAM_S_INTERFACE_DROP_CONTROL_64r; 24075 is_64bit_reg = 1; 24076 break; 24077 24078 case bcmOamControlFlexibleDropEgressCPlusSVlan: 24079 reg = EGR_OAM_S_C_INTERFACE_DROP_CONTROL_64r; 24080 is_64bit_reg = 1; 24081 break; 24082 24083 case bcmOamControlFlexibleDropEgressVP: 24084 reg = EGR_OAM_DVP_INTERFACE_DROP_CONTROL_64r; 24085 is_64bit_reg = 1; 24086 break; 24087 24088 case bcmOamControlFlexibleDropPasssiveSap: 24089 reg = OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 24090 break; 24091 24092 case bcmOamControlFlexibleDropEgressPasssiveSap: 24093 reg = EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 24094 break; 24095 24096 default: 24097 return (BCM_E_UNAVAIL); 24098 break; 24099 } 24100 if (is_64bit_reg == 0) { 24101 rv = soc_reg32_get(unit, reg, REG_PORT_ANY, 0, &rval_32); 24102 if(BCM_SUCCESS(rv)) { 24103 COMPILER_64_SET(*arg, 0, rval_32); 24104 } 24105 } else { 24106 rv = soc_reg64_get(unit, reg, REG_PORT_ANY, 0, arg); 24107 } 24108 return rv; 24109 } 24110 24111 /* 24112 * Function: 24113 * _bcm_sb2_oam_flex_drop_get 24114 * Purpose: 24115 * Query the value of the device-wide OAM control. 24116 * Parameters: 24117 * unit - (IN) BCM device number 24118 * type - (IN) OAM control type 24119 * arg - (IN) value to be set for the control 24120 * Returns: 24121 * BCM_E_XXX 24122 */ 24123 int _bcm_sb2_oam_flex_drop_set(int unit, bcm_oam_control_type_t type, 24124 uint64 arg) 24125 { 24126 uint32 rval_32; 24127 soc_reg_t reg = 0; 24128 uint32 is_64bit_reg = 0; 24129 int rv = BCM_E_NONE; 24130 24131 switch(type) { 24132 case bcmOamControlFlexibleDropPort: 24133 reg = OAM_PORT_INTERFACE_DROP_CONTROLr; 24134 break; 24135 24136 case bcmOamControlFlexibleDropCVlan: 24137 reg = OAM_C_INTERFACE_DROP_CONTROLr; 24138 break; 24139 24140 case bcmOamControlFlexibleDropSVlan: 24141 reg = OAM_S_INTERFACE_DROP_CONTROLr; 24142 break; 24143 24144 case bcmOamControlFlexibleDropCPlusSVlan: 24145 reg = OAM_S_C_INTERFACE_DROP_CONTROLr; 24146 break; 24147 24148 case bcmOamControlFlexibleDropVP: 24149 reg = OAM_SVP_INTERFACE_DROP_CONTROLr; 24150 break; 24151 24152 case bcmOamControlFlexibleDropEgressPort: 24153 reg = EGR_OAM_PORT_INTERFACE_DROP_CONTROL_64r; 24154 is_64bit_reg = 1; 24155 break; 24156 24157 case bcmOamControlFlexibleDropEgressCVlan: 24158 reg = EGR_OAM_C_INTERFACE_DROP_CONTROL_64r; 24159 is_64bit_reg = 1; 24160 break; 24161 24162 case bcmOamControlFlexibleDropEgressSVlan: 24163 reg = EGR_OAM_S_INTERFACE_DROP_CONTROL_64r; 24164 is_64bit_reg = 1; 24165 break; 24166 24167 case bcmOamControlFlexibleDropEgressCPlusSVlan: 24168 reg = EGR_OAM_S_C_INTERFACE_DROP_CONTROL_64r; 24169 is_64bit_reg = 1; 24170 break; 24171 24172 case bcmOamControlFlexibleDropEgressVP: 24173 reg = EGR_OAM_DVP_INTERFACE_DROP_CONTROL_64r; 24174 is_64bit_reg = 1; 24175 break; 24176 24177 case bcmOamControlFlexibleDropPasssiveSap: 24178 reg = OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 24179 break; 24180 24181 case bcmOamControlFlexibleDropEgressPasssiveSap: 24182 reg = EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 24183 break; 24184 24185 default: 24186 return (BCM_E_UNAVAIL); 24187 break; 24188 } 24189 if (is_64bit_reg == 0) { 24190 COMPILER_64_TO_32_LO(rval_32, arg); 24191 rv = soc_reg32_set(unit, reg, REG_PORT_ANY, 0, rval_32); 24192 } else { 24193 rv = soc_reg64_set(unit, reg, REG_PORT_ANY, 0, arg); 24194 } 24195 return rv; 24196 } 24197 /* 24198 * Function: 24199 * bcm_sb2_oam_control_get 24200 * Purpose: 24201 * Query the value of the device-wide OAM control. 24202 * Parameters: 24203 * unit - (IN) BCM device number 24204 * type - (IN) OAM control type 24205 * arg - (OUT) A pointer to value of the control 24206 * Returns: 24207 * BCM_E_XXX 24208 */ 24209 int bcm_sb2_oam_control_get(int unit, bcm_oam_control_type_t type, 24210 uint64 *arg) 24211 { 24212 int rv = BCM_E_NONE; 24213 24214 switch(type) { 24215 case bcmOamControlFlexibleDropPort: 24216 case bcmOamControlFlexibleDropCVlan: 24217 case bcmOamControlFlexibleDropSVlan: 24218 case bcmOamControlFlexibleDropCPlusSVlan: 24219 case bcmOamControlFlexibleDropVP: 24220 case bcmOamControlFlexibleDropEgressPort: 24221 case bcmOamControlFlexibleDropEgressCVlan: 24222 case bcmOamControlFlexibleDropEgressSVlan: 24223 case bcmOamControlFlexibleDropEgressCPlusSVlan: 24224 case bcmOamControlFlexibleDropEgressVP: 24225 case bcmOamControlFlexibleDropPasssiveSap: 24226 case bcmOamControlFlexibleDropEgressPasssiveSap: 24227 rv = _bcm_sb2_oam_flex_drop_get(unit, type, arg); 24228 break; 24229 default: 24230 rv = BCM_E_UNAVAIL; 24231 break; 24232 } 24233 return rv; 24234 } 24235 24236 /* Enables of counting MPLS LM DM packets with unknown ach */ 24237 int 24238 _bcm_sb2_oam_unknown_ach_count_enable(int unit) 24239 { 24240 uint32 rval = 0; 24241 soc_reg_field_set(unit, MPLS_UNKNOWN_CONTROL_PACKET_COUNTER_CONTROLr, &rval, 24242 COUNT_ENABLEf, 1); 24243 SOC_IF_ERROR_RETURN( 24244 WRITE_MPLS_UNKNOWN_CONTROL_PACKET_COUNTER_CONTROLr(unit, rval)); 24245 return BCM_E_NONE; 24246 } 24247 24248 /* 24249 * Function: 24250 * bcm_sb2_oam_control_set 24251 * Purpose: 24252 * Set the value of the device-wide OAM control. 24253 * Parameters: 24254 * unit - (IN) BCM device number 24255 * type - (IN) OAM control type 24256 * arg - (IN) value to be set for control 24257 * Returns: 24258 * BCM_E_XXX 24259 */ 24260 int bcm_sb2_oam_control_set(int unit, bcm_oam_control_type_t type, 24261 uint64 arg) 24262 { 24263 int rv = BCM_E_NONE; 24264 switch(type) { 24265 case bcmOamControlFlexibleDropPort: 24266 case bcmOamControlFlexibleDropCVlan: 24267 case bcmOamControlFlexibleDropSVlan: 24268 case bcmOamControlFlexibleDropCPlusSVlan: 24269 case bcmOamControlFlexibleDropVP: 24270 case bcmOamControlFlexibleDropEgressPort: 24271 case bcmOamControlFlexibleDropEgressCVlan: 24272 case bcmOamControlFlexibleDropEgressSVlan: 24273 case bcmOamControlFlexibleDropEgressCPlusSVlan: 24274 case bcmOamControlFlexibleDropEgressVP: 24275 case bcmOamControlFlexibleDropPasssiveSap: 24276 case bcmOamControlFlexibleDropEgressPasssiveSap: 24277 rv = _bcm_sb2_oam_flex_drop_set(unit, type, arg); 24278 break; 24279 case bcmOamControlUnknownAchCount: 24280 rv = _bcm_sb2_oam_unknown_ach_count_enable(unit); 24281 break; 24282 default: 24283 rv = BCM_E_UNAVAIL; 24284 break; 24285 } 24286 return rv; 24287 } 24288 24289 /* 24290 * Function: 24291 * bcm_sb2_oam_upmep_cosq_set 24292 * Purpose: 24293 * Set the value of the device-wide UP MEP PDU type CPU queue. 24294 * Parameters: 24295 * unit - (IN) BCM device number 24296 * upmep_pdu_type - (IN) UP MEP PDU type 24297 * cosq - (IN) value to be set for CPU queue 24298 * Returns: 24299 * BCM_E_XXX 24300 */ 24301 int bcm_sb2_oam_upmep_cosq_set(int unit, bcm_oam_upmep_pdu_type_t upmep_pdu_type, 24302 bcm_cos_queue_t cosq) 24303 { 24304 int rv = BCM_E_NONE; 24305 uint64 cpu_control_2_64; 24306 uint64 write_val; 24307 24308 SOC_IF_ERROR_RETURN( 24309 READ_EGR_CPU_CONTROL_2_64r(unit, &cpu_control_2_64)); 24310 switch(upmep_pdu_type) { 24311 case bcmOamUpmepPduTypeCcm: 24312 COMPILER_64_SET(write_val, 0, cosq); 24313 soc_reg64_field_set(unit, EGR_CPU_CONTROL_2_64r, &cpu_control_2_64, 24314 OAM_CCM_SLOWPATH_CPU_COSf, write_val); 24315 break; 24316 case bcmOamUpmepPduTypeLmDm: 24317 COMPILER_64_SET(write_val, 0, cosq); 24318 soc_reg64_field_set(unit, EGR_CPU_CONTROL_2_64r, &cpu_control_2_64, 24319 OAM_LMDM_CPU_COSf, write_val); 24320 break; 24321 case bcmOamUpmepPduTypeSlowpath: 24322 COMPILER_64_SET(write_val, 0, cosq); 24323 soc_reg64_field_set(unit, EGR_CPU_CONTROL_2_64r, &cpu_control_2_64, 24324 OAM_SLOWPATH_CPU_COSf, write_val); 24325 break; 24326 case bcmOamUpmepPduTypeCount : 24327 rv = BCM_E_PARAM; 24328 break; 24329 default: 24330 rv = BCM_E_UNAVAIL; 24331 break; 24332 } 24333 if (rv == BCM_E_NONE) { 24334 SOC_IF_ERROR_RETURN( 24335 WRITE_EGR_CPU_CONTROL_2_64r(unit, cpu_control_2_64)); 24336 } 24337 return rv; 24338 } 24339 24340 /* 24341 * Function: 24342 * bcm_sb2_oam_upmep_cosq_get 24343 * Purpose: 24344 * Query the value of the device-wide UP MEP PDU type CPU queue. 24345 * Parameters: 24346 * unit - (IN) BCM device number 24347 * upmep_pdu_type - (IN) UP MEP PDU type 24348 * cosq - (OUT) pointer to CPU queue to be get 24349 * Returns: 24350 * BCM_E_XXX 24351 */ 24352 int bcm_sb2_oam_upmep_cosq_get(int unit, bcm_oam_upmep_pdu_type_t upmep_pdu_type, 24353 bcm_cos_queue_t *cosq) 24354 { 24355 int rv = BCM_E_NONE; 24356 uint64 cpu_control_2_64; 24357 24358 SOC_IF_ERROR_RETURN( 24359 READ_EGR_CPU_CONTROL_2_64r(unit, &cpu_control_2_64)); 24360 switch(upmep_pdu_type) { 24361 case bcmOamUpmepPduTypeCcm: 24362 *cosq = soc_reg64_field32_get(unit, EGR_CPU_CONTROL_2_64r, 24363 cpu_control_2_64, OAM_CCM_SLOWPATH_CPU_COSf); 24364 break; 24365 case bcmOamUpmepPduTypeLmDm: 24366 *cosq = soc_reg64_field32_get(unit, EGR_CPU_CONTROL_2_64r, 24367 cpu_control_2_64, OAM_LMDM_CPU_COSf); 24368 break; 24369 case bcmOamUpmepPduTypeSlowpath: 24370 *cosq = soc_reg64_field32_get(unit, EGR_CPU_CONTROL_2_64r, 24371 cpu_control_2_64, OAM_SLOWPATH_CPU_COSf); 24372 break; 24373 case bcmOamUpmepPduTypeCount : 24374 rv = BCM_E_PARAM; 24375 break; 24376 default: 24377 rv = BCM_E_UNAVAIL; 24378 break; 24379 } 24380 return rv; 24381 } 24382 24383 int 24384 bcm_sb2_oam_reg_from_lookup_type_get(bcm_oam_lookup_type_t type) 24385 { 24386 switch(type) { 24387 case bcmOamLookupTypePort: 24388 return OAM_PORT_INTERFACE_DROP_CONTROL_64r; 24389 break; 24390 24391 case bcmOamLookupTypeInnerVlan: 24392 return OAM_C_INTERFACE_DROP_CONTROL_64r; 24393 break; 24394 24395 case bcmOamLookupTypeOuterVlan: 24396 return OAM_S_INTERFACE_DROP_CONTROL_64r; 24397 break; 24398 24399 case bcmOamLookupTypeOuterPlusInnerVlan: 24400 return OAM_S_C_INTERFACE_DROP_CONTROL_64r; 24401 break; 24402 24403 case bcmOamLookupTypeVirtualPort: 24404 return INVALIDr; 24405 break; 24406 24407 case bcmOamLookupTypeEgressPort: 24408 return EGR_OAM_PORT_INTERFACE_DROP_CONTROL_64r; 24409 break; 24410 24411 case bcmOamLookupTypeEgressInnerVlan: 24412 return EGR_OAM_C_INTERFACE_DROP_CONTROL_64r; 24413 break; 24414 24415 case bcmOamLookupTypeEgressOuterVlan: 24416 return EGR_OAM_S_INTERFACE_DROP_CONTROL_64r; 24417 break; 24418 24419 case bcmOamLookupTypeEgressOuterPlusInnerVlan: 24420 return EGR_OAM_S_C_INTERFACE_DROP_CONTROL_64r; 24421 break; 24422 24423 case bcmOamLookupTypeEgressVirtualPort: 24424 return INVALIDr; 24425 break; 24426 24427 case bcmOamLookupTypeOuterVlanPassive: 24428 return OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 24429 break; 24430 24431 case bcmOamLookupTypeEgressOuterVlanPassive: 24432 return EGR_OAM_S_INTERFACE_PASSIVE_PROCESSING_CONTROLr; 24433 break; 24434 24435 case bcmOamLookupTypeMplsSection: 24436 return OAM_SECTION_INTERFACE_DROP_CONTROL_64r; 24437 break; 24438 case bcmOamLookupTypeMplsLsp: 24439 return OAM_LSP_INTERFACE_DROP_CONTROL_64r; 24440 break; 24441 case bcmOamLookupTypeMplsPw: 24442 return OAM_PW_INTERFACE_DROP_CONTROL_64r; 24443 break; 24444 case bcmOamLookupTypeEgressMplsSection: 24445 return EGR_OAM_SECTION_INTERFACE_DROP_CONTROL_64r; 24446 break; 24447 case bcmOamLookupTypeEgressMplsLsp: 24448 return EGR_OAM_LSP_INTERFACE_DROP_CONTROL_64r; 24449 break; 24450 case bcmOamLookupTypeEgressMplsPw: 24451 return EGR_OAM_PW_INTERFACE_DROP_CONTROL_64r; 24452 break; 24453 default: 24454 return INVALIDr; 24455 break; 24456 } 24457 /* not reached */ 24458 return INVALIDr; 24459 } 24460 24461 /* Disc drop vectors */ 24462 #define CONTROL_FRAME_DROP 0x1 24463 #define FLOW_CONTROL_MESSAGE_DROP 0x40 24464 #define MACSA_EQUALS_DA_DROP 0x100 24465 #define AMT_CONTROL_PACKET_DROP 0x800 24466 #define UNKNOWN_SUBTENDING_PORT_DROP 0x20000 24467 24468 /* Vlan drop vectors */ 24469 #define ENIFILTER_DROP 0x2 24470 #define INVALID_TPID_DROP 0x4 24471 24472 /* MPLS drop control vectors */ 24473 #define MPLS_LABEL_MISS_DROP 0x1 24474 #define MPLS_INVALID_PAYLOAD_DROP 0x4 24475 #define MPLS_TTL_CHECK_FAIL_DROP 0x8 24476 24477 24478 /* EGR drop control vectors */ 24479 #define TTL_DROP 0x8 24480 #define STG_BLOCK_DROP 0x20 24481 #define STG_DISABLE_DROP 0x1000 24482 #define IPMC_L2_SELF_PORT 0x40 24483 #define PURGE_PKT 0x80 24484 #define AGED_PKT 0x100 24485 #define BAD_TDIP 0x200 24486 #define VLAN_NOT_FOUND 0x800 24487 #define PARITY_ERR_DROP 0x10000 24488 #define SPLIT_HORIZON 0x200000 24489 #define SOURCE_VIRTUAL_PORT_REMOVAL 0x400000 24490 #define NONUCAST_PRUNE_DROP 0x1000000 24491 24492 #define _BCM_SET_DISC_DROP_CTRL_BIT(arg, bitmap) (arg |= bitmap) 24493 #define _BCM_SET_VLAN_DROP_CTRL_BIT(arg, bitmap) (arg |= bitmap) 24494 #define _BCM_SET_EGR_DROP_CTRL_BIT(arg, bitmap) (arg |= bitmap) 24495 #define _BCM_SET_MPLS_DROP_CTRL_BIT(arg, bitmap) (arg |= bitmap) 24496 24497 24498 int 24499 bcm_sb2_oam_drop_field_condition_set(int unit, soc_reg_t reg, bcm_oam_condition_t condition, int enable) 24500 { 24501 uint32 arg = 0; 24502 soc_field_t field = INVALIDf; 24503 uint64 reg_val; 24504 uint32 field_val = 0; 24505 int set_arg = 0; /* Set the argument value directly */ 24506 24507 switch (condition) { 24508 case bcmOamConditionPFCDrop: 24509 _BCM_SET_DISC_DROP_CTRL_BIT(arg, CONTROL_FRAME_DROP); 24510 field = DISC_DROP_VECTOR_CTRLf; 24511 break; 24512 case bcmOamConditionFlowControlDrop: 24513 _BCM_SET_DISC_DROP_CTRL_BIT(arg, FLOW_CONTROL_MESSAGE_DROP); 24514 field = DISC_DROP_VECTOR_CTRLf; 24515 break; 24516 case bcmOamConditionMacsaEqualsMacdaDrop: 24517 _BCM_SET_DISC_DROP_CTRL_BIT(arg, MACSA_EQUALS_DA_DROP); 24518 field = DISC_DROP_VECTOR_CTRLf; 24519 break; 24520 case bcmOamConditionAutoMulticastTunnelControlPacketDrop: 24521 _BCM_SET_DISC_DROP_CTRL_BIT(arg, AMT_CONTROL_PACKET_DROP); 24522 field = DISC_DROP_VECTOR_CTRLf; 24523 break; 24524 case bcmOamConditionUnknownSubportErrorDrop: 24525 _BCM_SET_DISC_DROP_CTRL_BIT(arg, UNKNOWN_SUBTENDING_PORT_DROP); 24526 field = DISC_DROP_VECTOR_CTRLf; 24527 break; 24528 case bcmOamConditionSubportPktTagDrop: 24529 field = INVALIDf; 24530 break; 24531 case bcmOamConditionNoSubportPktTagDrop: 24532 field = INVALIDf; 24533 break; 24534 case bcmOamConditionIngressFilterDrop: 24535 _BCM_SET_VLAN_DROP_CTRL_BIT(arg, ENIFILTER_DROP); 24536 field = VLAN_DROP_VECTOR_CTRLf; 24537 break; 24538 case bcmOamConditionEgressFilterDrop: 24539 field = INVALIDf; 24540 break; 24541 case bcmOamConditionInvalidTpidDrop: 24542 _BCM_SET_VLAN_DROP_CTRL_BIT(arg, INVALID_TPID_DROP); 24543 field = VLAN_DROP_VECTOR_CTRLf; 24544 break; 24545 case bcmOamConditionOamMetadataHeaderErrorDrop: 24546 field = OLP_ERROR_DROP_CTRLf; 24547 arg = enable?1:0; 24548 set_arg = 1; 24549 break; 24550 case bcmOamConditionFieldLookupDrop: 24551 field = VFP_DROP_CTRLf; 24552 arg = enable?1:0; 24553 set_arg = 1; 24554 break; 24555 case bcmOamConditionSATDrop: 24556 field = SAT_DN_SAMP_RX_DROP_CTRLf; 24557 arg = enable?1:0; 24558 set_arg = 1; 24559 break; 24560 case bcmOamConditionVlanTranslateIngressMissDrop: 24561 field = CVLAN_INTF_BEFORE_VXLT_VXLT_MISS_DROP_CTRLf; 24562 arg = enable?1:0; 24563 set_arg = 1; 24564 break; 24565 case bcmOamConditionVlanTranslateEgressMissDrop: 24566 field = CVLAN_INTF_AFTER_VXLT_VXLT_MISS_DROP_CTRLf; 24567 arg = enable?1:0; 24568 set_arg = 1; 24569 break; 24570 case bcmOamConditionMplsLabelLookupMissDrop: 24571 _BCM_SET_MPLS_DROP_CTRL_BIT(arg, MPLS_LABEL_MISS_DROP); 24572 field = MPLS_DROP_VECTOR_CTRLf; 24573 break; 24574 case bcmOamConditionMplsInvalidActionDrop: 24575 _BCM_SET_MPLS_DROP_CTRL_BIT(arg, MPLS_LABEL_MISS_DROP); 24576 field = MPLS_DROP_VECTOR_CTRLf; 24577 break; 24578 case bcmOamConditionMplsInvalidPayloadDrop: 24579 _BCM_SET_MPLS_DROP_CTRL_BIT(arg, MPLS_INVALID_PAYLOAD_DROP); 24580 field = MPLS_DROP_VECTOR_CTRLf; 24581 break; 24582 case bcmOamConditionMplsTtlErrorDrop: 24583 _BCM_SET_MPLS_DROP_CTRL_BIT(arg, MPLS_TTL_CHECK_FAIL_DROP); 24584 field = MPLS_DROP_VECTOR_CTRLf; 24585 break; 24586 case bcmOamConditionStgNotInForwardDrop: 24587 field = SPST_NOT_IN_FORWARDING_STATE_DROP_CTRLf; 24588 arg = enable?1:0; 24589 set_arg = 1; 24590 break; 24591 case bcmOamConditionEgressTtlErrorDrop: 24592 _BCM_SET_EGR_DROP_CTRL_BIT(arg, TTL_DROP); 24593 field = EGR_DROP_VECTOR_CTRLf; 24594 break; 24595 case bcmOamConditionEgressStgBlockedDrop: 24596 _BCM_SET_EGR_DROP_CTRL_BIT(arg, STG_BLOCK_DROP); 24597 field = EGR_DROP_VECTOR_CTRLf; 24598 break; 24599 case bcmOamConditionEgressStgDisabledDrop: 24600 _BCM_SET_EGR_DROP_CTRL_BIT(arg, 24601 STG_DISABLE_DROP); 24602 field = EGR_DROP_VECTOR_CTRLf; 24603 break; 24604 case bcmOamConditionEgressIPMCSameVlanPruneDrop: 24605 _BCM_SET_EGR_DROP_CTRL_BIT(arg, 24606 IPMC_L2_SELF_PORT); 24607 field = EGR_DROP_VECTOR_CTRLf; 24608 break; 24609 case bcmOamConditionEgressMMUErrorDrop: 24610 _BCM_SET_EGR_DROP_CTRL_BIT(arg, 24611 PURGE_PKT | AGED_PKT); 24612 field = EGR_DROP_VECTOR_CTRLf; 24613 break; 24614 case bcmOamConditionEgressBadTdipDrop: 24615 _BCM_SET_EGR_DROP_CTRL_BIT(arg, 24616 BAD_TDIP); 24617 field = EGR_DROP_VECTOR_CTRLf; 24618 break; 24619 case bcmOamConditionEgressUnknownVlanDrop: 24620 _BCM_SET_EGR_DROP_CTRL_BIT(arg, 24621 VLAN_NOT_FOUND); 24622 field = EGR_DROP_VECTOR_CTRLf; 24623 break; 24624 case bcmOamConditionEgressCompositeErrorDrop: 24625 _BCM_SET_EGR_DROP_CTRL_BIT(arg, 24626 PARITY_ERR_DROP); 24627 field = EGR_DROP_VECTOR_CTRLf; 24628 break; 24629 case bcmOamConditionEgressSplitHorizonDrop: 24630 _BCM_SET_EGR_DROP_CTRL_BIT(arg, 24631 SPLIT_HORIZON); 24632 field = EGR_DROP_VECTOR_CTRLf; 24633 break; 24634 case bcmOamConditionEgressSVPRemovalDrop: 24635 _BCM_SET_EGR_DROP_CTRL_BIT(arg, 24636 SOURCE_VIRTUAL_PORT_REMOVAL); 24637 field = EGR_DROP_VECTOR_CTRLf; 24638 break; 24639 case bcmOamConditionEgressNonUCPruneDrop: 24640 _BCM_SET_EGR_DROP_CTRL_BIT(arg, 24641 NONUCAST_PRUNE_DROP); 24642 field = EGR_DROP_VECTOR_CTRLf; 24643 break; 24644 default: 24645 return BCM_E_PARAM; 24646 break; 24647 } 24648 /* Validate condition type */ 24649 if (field == INVALIDf) { 24650 return BCM_E_PARAM; 24651 } 24652 24653 /* Validate lookup and condition combination */ 24654 if (!soc_reg_field_valid(unit, reg, field)) { 24655 return BCM_E_PARAM; 24656 } 24657 24658 COMPILER_64_ZERO(reg_val); 24659 24660 SOC_IF_ERROR_RETURN(soc_reg64_get(unit, reg, 24661 REG_PORT_ANY, 0, ®_val)); 24662 /* Read the prev value */ 24663 field_val = soc_reg64_field32_get(unit, reg, reg_val, field); 24664 24665 /* Modify it */ 24666 if (!set_arg) { 24667 if (enable) { 24668 field_val |= arg; 24669 } else { 24670 field_val &= ~arg; 24671 } 24672 } else { 24673 field_val = arg; 24674 } 24675 24676 SOC_IF_ERROR_RETURN(soc_reg_field32_modify(unit, reg, 24677 REG_PORT_ANY, field, field_val)); 24678 return BCM_E_NONE; 24679 } 24680 24681 int 24682 bcm_sb2_oam_lookup_enable_set( 24683 int unit, 24684 bcm_oam_lookup_type_t type, 24685 bcm_oam_condition_t condition, 24686 int enable) 24687 { 24688 soc_reg_t reg = INVALIDr; 24689 24690 reg = bcm_sb2_oam_reg_from_lookup_type_get(type); 24691 /* Validate lookup type */ 24692 if (reg == INVALIDr) { 24693 return BCM_E_PARAM; 24694 } 24695 24696 return bcm_sb2_oam_drop_field_condition_set(unit, reg, condition, enable); 24697 } 24698 24699 int 24700 bcm_sb2_oam_lookup_enable_multi_set( 24701 int unit, 24702 bcm_oam_lookup_types_t type, 24703 bcm_oam_conditions_t conditions, 24704 int enable) 24705 { 24706 bcm_oam_lookup_type_t lookup; 24707 bcm_oam_condition_t condition; 24708 24709 for (lookup = 0; lookup < bcmOamLookupTypeCount; lookup++) { 24710 if (BCM_OAM_LOOKUP_TYPE_GET(type, lookup)) { 24711 for (condition = 0; condition < bcmOamConditionCount; condition++) { 24712 if (BCM_OAM_CONDITION_GET(conditions, condition)) { 24713 BCM_IF_ERROR_RETURN(bcm_sb2_oam_lookup_enable_set(unit, lookup, condition, enable)); 24714 } 24715 } 24716 } 24717 } 24718 return BCM_E_NONE; 24719 } 24720 24721 int 24722 bcm_sb2_oam_lookup_enable_get( 24723 int unit, 24724 bcm_oam_lookup_type_t type, 24725 bcm_oam_conditions_t *condition) 24726 { 24727 return BCM_E_NONE; 24728 } 24729 24730 #if defined(INCLUDE_BHH) 24731 /* 24732 * Function: 24733 * _bcm_sb2_oam_bhh_encap_data_dump 24734 * Purpose: 24735 * Dumps buffer contents. 24736 * Parameters: 24737 * buffer - (IN) Buffer to dump data. 24738 * length - (IN) Length of buffer. 24739 * Returns: 24740 * None 24741 */ 24742 void 24743 _bcm_sb2_oam_bhh_encap_data_dump(uint8 *buffer, int length) 24744 { 24745 int i; 24746 24747 LOG_CLI((BSL_META("\nBHH encapsulation (length=%d):\n"), length)); 24748 24749 for (i = 0; i < length; i++) { 24750 if ((i % 16) == 0) { 24751 LOG_CLI((BSL_META("\n"))); 24752 } 24753 LOG_CLI((BSL_META(" %02x"), buffer[i])); 24754 } 24755 24756 LOG_CLI((BSL_META("\n"))); 24757 return; 24758 } 24759 #endif /* defined(INCLUDE_BHH) */ 24760 24761 #if defined(INCLUDE_ETH_LM_DM) 24762 /* 24763 * Function: 24764 * _bcm_sb2_oam_eth_l2_encap_data_dump 24765 * Purpose: 24766 * Dumps buffer contents. 24767 * Parameters: 24768 * buffer - (IN) Buffer to dump data. 24769 * length - (IN) Length of buffer. 24770 * Returns: 24771 * None 24772 */ 24773 void 24774 _bcm_sb2_oam_eth_l2_encap_data_dump(uint8 *buffer, int length) 24775 { 24776 int i; 24777 24778 LOG_CLI((BSL_META("\nETH_LM_DM L2 encapsulation (length=%d):\n"), length)); 24779 24780 for (i = 0; i < length; i++) { 24781 if ((i % 16) == 0) { 24782 LOG_CLI((BSL_META("\n"))); 24783 } 24784 LOG_CLI((BSL_META(" %02x"), buffer[i])); 24785 } 24786 24787 LOG_CLI((BSL_META("\n"))); 24788 return; 24789 } 24790 24791 24792 #endif /* (INCLUDE_ETH_LM_DM) */ 24793 24794 /* 24795 * Function: 24796 * _bcm_sb2_oam_olp_l2_encap_data_dump 24797 * Purpose: 24798 * Dumps buffer contents. 24799 * Parameters: 24800 * buffer - (IN) Buffer to dump data. 24801 * length - (IN) Length of buffer. 24802 * Returns: 24803 * None 24804 */ 24805 void 24806 _bcm_sb2_oam_olp_l2_encap_data_dump(uint8 *buffer, int length) 24807 { 24808 int i; 24809 24810 LOG_CLI((BSL_META("\nETH_LM_DM OLP L2 encapsulation (length=%d):\n"), length)); 24811 24812 for (i = 0; i < length; i++) { 24813 if ((i % 16) == 0) { 24814 LOG_CLI((BSL_META("\n"))); 24815 } 24816 LOG_CLI((BSL_META(" %02x"), buffer[i])); 24817 } 24818 24819 LOG_CLI((BSL_META("\n"))); 24820 return; 24821 } 24822 24823 24824 /* 24825 * Function: 24826 * _bcm_sb2_oam_olp_tx_encap_data_dump 24827 * Purpose: 24828 * Dumps buffer contents. 24829 * Parameters: 24830 * buffer - (IN) Buffer to dump data. 24831 * length - (IN) Length of buffer. 24832 * Returns: 24833 * None 24834 */ 24835 void 24836 _bcm_sb2_oam_olp_tx_encap_data_dump(uint8 *buffer, int length) 24837 { 24838 int i; 24839 24840 LOG_CLI((BSL_META("\nETH_LM_DM OLP TX encapsulation (length=%d):\n"), length)); 24841 24842 for (i = 0; i < length; i++) { 24843 if ((i % 16) == 0) { 24844 LOG_CLI((BSL_META("\n"))); 24845 } 24846 LOG_CLI((BSL_META(" %02x"), buffer[i])); 24847 } 24848 24849 LOG_CLI((BSL_META("\n"))); 24850 return; 24851 } 24852 24853 #if defined(INCLUDE_BHH) 24854 /* 24855 * Function: 24856 * bcm_sb2_oam_mpls_tp_channel_type_tx_get 24857 * Purpose: 24858 * Get MPLS TP(BHH) ACH Channel type 24859 * Parameters: 24860 * unit (IN) BCM device number 24861 * channel_type (IN) Channel type is ignored in XGS devices 24862 * Value (OUT) User define MPLS TP(BHH) ACH channel type 24863 * 24864 * Returns: 24865 * BCM_E_NONE No error 24866 * BCM_E_XXXX Error 24867 */ 24868 int 24869 bcm_sb2_oam_mpls_tp_channel_type_tx_get(int unit, 24870 bcm_oam_mpls_tp_channel_type_t channel_type, 24871 int *value) 24872 { 24873 *value = sb2_oam_mpls_tp_ach_channel_type; 24874 return BCM_E_NONE; 24875 } 24876 24877 /* 24878 * Function: 24879 * bcm_sb2_oam_mpls_tp_channel_type_tx_set 24880 * Purpose: 24881 * Update MPLS TP(BHH) ACH Channel type with user defined value 24882 * Parameters: 24883 * unit (IN) BCM device number 24884 * channel_type (IN) Channel type is ignored in XGS devices 24885 * Value (IN) User define MPLS TP(BHH) ACH channel type 24886 * 24887 * Returns: 24888 * BCM_E_NONE No error 24889 * BCM_E_XXXX Error 24890 */ 24891 int 24892 bcm_sb2_oam_mpls_tp_channel_type_tx_set(int unit, 24893 bcm_oam_mpls_tp_channel_type_t channel_type, 24894 int value) 24895 { 24896 uint8 *buffer, *buffer_ptr; 24897 uint16 buffer_len, reply_len; 24898 int rv = BCM_E_NONE; 24899 int index = 0; 24900 soc_mem_t mem = MPLS_OAM_ACH_TYPE_CONFIGm; 24901 uint32 *msg; 24902 _bcm_oam_control_t *oc; 24903 24904 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 24905 _BCM_OAM_LOCK(oc); 24906 24907 if (oc->ukernel_not_ready) { 24908 _BCM_OAM_UNLOCK(oc); 24909 return BCM_E_INIT; 24910 } 24911 24912 if ((value != SHR_BHH_ACH_CHANNEL_TYPE) && 24913 (value != SHR_BHH_ACH_CHANNEL_TYPE_1)) { 24914 _BCM_OAM_UNLOCK(oc); 24915 return BCM_E_CONFIG; 24916 } 24917 24918 sb2_oam_mpls_tp_ach_channel_type = value; 24919 soc_mem_field32_modify(unit, mem, index, ACH_TYPEf, value); 24920 msg = (uint32 *)&sb2_oam_mpls_tp_ach_channel_type; 24921 24922 /* Pack control message data into DMA buffer */ 24923 buffer = oc->dma_buffer; 24924 buffer_ptr = bhh_sdk_msg_ctrl_ach_channel_type_msg_pack(buffer, msg); 24925 buffer_len = buffer_ptr - buffer; 24926 24927 rv = _bcm_sb2_oam_bhh_msg_send_receive( 24928 unit, 24929 MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE, 24930 buffer_len, 0, 24931 MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE_REPLY, 24932 &reply_len); 24933 24934 if (BCM_FAILURE(rv)) { 24935 _BCM_OAM_UNLOCK(oc); 24936 return (rv); 24937 } 24938 24939 _BCM_OAM_UNLOCK(oc); 24940 return BCM_E_NONE; 24941 } 24942 24943 STATIC int 24944 _bcm_sb2_oam_bhh_ach_header_get(uint32 packet_flags, _ach_header_t *ach) 24945 { 24946 sal_memset(ach, 0, sizeof(*ach)); 24947 24948 ach->f_nibble = SHR_BHH_ACH_FIRST_NIBBLE; 24949 ach->version = SHR_BHH_ACH_VERSION; 24950 ach->reserved = 0; 24951 24952 ach->channel_type = sb2_oam_mpls_tp_ach_channel_type; 24953 24954 return (BCM_E_NONE); 24955 } 24956 24957 STATIC int 24958 _bcm_sb2_oam_bhh_mpls_label_get(uint32 label, uint8 exp, uint8 s, uint8 ttl, 24959 _mpls_label_t *mpls) 24960 { 24961 sal_memset(mpls, 0, sizeof(*mpls)); 24962 24963 mpls->label = label; 24964 mpls->exp = exp & 0x07; 24965 mpls->s = s; 24966 if(ttl) 24967 mpls->ttl = ttl; 24968 else 24969 mpls->ttl = _BHH_MPLS_DFLT_TTL; 24970 24971 return (BCM_E_NONE); 24972 } 24973 24974 STATIC int 24975 _bcm_sb2_oam_bhh_mpls_gal_label_get(_mpls_label_t *mpls, uint8 oam_exp) 24976 { 24977 return _bcm_sb2_oam_bhh_mpls_label_get(SHR_BHH_MPLS_GAL_LABEL, 24978 oam_exp, 1, 1, mpls); 24979 } 24980 24981 STATIC int 24982 _bcm_sb2_oam_bhh_mpls_labels_get(int unit, _bcm_oam_hash_data_t *h_data_p, 24983 uint32 packet_flags, int max_count, 24984 _mpls_label_t *mpls, int *mpls_count, 24985 bcm_if_t *l3_intf_id, uint8 oam_exp, 24986 uint8 oam_ttl) 24987 { 24988 int count = 0; 24989 bcm_l3_egress_t l3_egress; 24990 bcm_mpls_port_t mpls_port; 24991 bcm_mpls_egress_label_t label_array[_BHH_MPLS_MAX_LABELS]; 24992 bcm_mpls_egress_label_t tmp_label; 24993 int label_count; 24994 int i = 0; 24995 24996 /* Get L3 objects */ 24997 bcm_l3_egress_t_init(&l3_egress); 24998 if (BCM_FAILURE(bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) { 24999 return (BCM_E_PARAM); 25000 } 25001 25002 /* Look for a tunnel associated with this interface */ 25003 if (BCM_SUCCESS 25004 (bcm_esw_mpls_tunnel_initiator_get(unit, l3_egress.intf, 25005 _BHH_MPLS_MAX_LABELS, 25006 label_array, &label_count))) { 25007 /* We need to swap the labels configured in tunnel initiator as 25008 * it returns labels in reverse order than how it should be in pkt. 25009 */ 25010 for (i = 0; i < (label_count / 2); i++) { 25011 sal_memcpy(&tmp_label, &label_array[i], sizeof(tmp_label)); 25012 sal_memcpy(&label_array[i], &label_array[label_count - 1 - i], 25013 sizeof(tmp_label)); 25014 sal_memcpy(&label_array[label_count - 1 - i], &tmp_label, 25015 sizeof(tmp_label)); 25016 } 25017 25018 /* Add VRL Label */ 25019 if (BHH_EP_LSP_TYPE(h_data_p)) { 25020 if ((l3_egress.mpls_label != BCM_MPLS_LABEL_INVALID) && 25021 (h_data_p->egr_label != BCM_MPLS_LABEL_INVALID) && 25022 (label_count < _BHH_MPLS_MAX_LABELS)) { 25023 label_array[label_count].label = l3_egress.mpls_label; 25024 label_array[label_count].exp = l3_egress.mpls_exp; 25025 label_array[label_count].ttl = l3_egress.mpls_ttl; 25026 label_count++; 25027 } 25028 /* Traverse through Label stack and match on control label, this 25029 * label should be the one just above GAL in the label stack, any 25030 * following labels should not be added. 25031 */ 25032 for (i = 0; i < label_count; i++) { 25033 if (label_array[i].label == h_data_p->egr_label) { 25034 label_array[i].exp = oam_exp; 25035 if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) && 25036 oam_ttl) { 25037 label_array[i].ttl = oam_ttl; 25038 } 25039 label_count = i + 1; 25040 break; 25041 } 25042 } 25043 } 25044 } 25045 25046 /* MPLS Router Alert */ 25047 if (packet_flags & _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT) { 25048 /* Ignore overrun error as RAL is only added for PW MEPs and so overrun 25049 * condition will not exist. 25050 */ 25051 /* coverity[overrun-local] */ 25052 label_array[label_count].label = SHR_BHH_MPLS_ROUTER_ALERT_LABEL; 25053 label_array[label_count].exp = 0; 25054 label_array[label_count].ttl = 0; 25055 label_count++; 25056 } 25057 25058 /* Use GPORT to resolve interface */ 25059 if (BCM_GPORT_IS_MPLS_PORT(h_data_p->gport)) { 25060 /* Get mpls port and label info */ 25061 bcm_mpls_port_t_init(&mpls_port); 25062 mpls_port.mpls_port_id = h_data_p->gport; 25063 if (BCM_FAILURE 25064 (bcm_esw_mpls_port_get(unit, h_data_p->vpn, 25065 &mpls_port))) { 25066 return (BCM_E_PARAM); 25067 } 25068 label_array[label_count].label = mpls_port.egress_label.label; 25069 /* Take the user provided exp, if the user passed the PW label */ 25070 if (h_data_p->egr_label == mpls_port.egress_label.label) { 25071 label_array[label_count].exp = oam_exp; 25072 if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) && 25073 oam_ttl) { 25074 label_array[label_count].ttl = oam_ttl; 25075 } 25076 } else { 25077 label_array[label_count].exp = mpls_port.egress_label.exp; 25078 label_array[label_count].ttl = mpls_port.egress_label.ttl; 25079 } 25080 25081 if (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv && 25082 h_data_p->vccv_type == bcmOamBhhVccvTtl) { 25083 label_array[label_count].ttl = 1; 25084 } 25085 label_count++; 25086 } 25087 25088 for (i=0; i < label_count; i++) { 25089 _bcm_sb2_oam_bhh_mpls_label_get(label_array[i].label, 25090 label_array[i].exp, 25091 0, 25092 label_array[i].ttl, 25093 &mpls[count++]); 25094 } 25095 25096 /* Set Bottom of Stack if there is no GAL label */ 25097 if (!(packet_flags & _BHH_ENCAP_PKT_GAL)) { 25098 mpls[count-1].s = 1; 25099 } 25100 25101 *mpls_count = count; 25102 25103 return (BCM_E_NONE); 25104 25105 } 25106 25107 STATIC int 25108 _bcm_sb2_oam_bhh_l2_header_get(int unit, _bcm_oam_hash_data_t *h_data_p, 25109 bcm_port_t port, uint16 etype, 25110 _l2_header_t *l2, uint8 *lm_pdu_counter_offset) 25111 { 25112 uint16 tpid; 25113 bcm_l3_egress_t l3_egress; 25114 bcm_l3_intf_t l3_intf; 25115 bcm_vlan_control_vlan_t vc; 25116 int tpid_select; 25117 bcm_pbmp_t pbmp, ubmp; 25118 25119 sal_memset(l2, 0, sizeof(*l2)); 25120 25121 if (!BHH_EP_MPLS_SECTION_TYPE(h_data_p)) { 25122 /* Get L3 interfaces */ 25123 bcm_l3_egress_t_init(&l3_egress); 25124 bcm_l3_intf_t_init(&l3_intf); 25125 25126 if (BCM_FAILURE 25127 (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) { 25128 return (BCM_E_PARAM); 25129 } 25130 25131 l3_intf.l3a_intf_id = l3_egress.intf; 25132 if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) { 25133 return (BCM_E_PARAM); 25134 } 25135 25136 /* Get TPID */ 25137 BCM_IF_ERROR_RETURN( 25138 bcm_esw_vlan_control_port_get(unit, 25139 port, 25140 bcmVlanPortOuterTpidSelect, 25141 &tpid_select)); 25142 if (tpid_select == BCM_PORT_OUTER_TPID) { 25143 BCM_IF_ERROR_RETURN(bcm_esw_port_tpid_get(unit, port, &tpid)); 25144 } else { 25145 BCM_IF_ERROR_RETURN( 25146 bcm_esw_vlan_control_vlan_get(unit, l3_intf.l3a_vid, &vc)); 25147 tpid = vc.outer_tpid; 25148 } 25149 25150 sal_memcpy(l2->dst_mac, l3_egress.mac_addr, _BHH_MAC_ADDR_LENGTH); 25151 sal_memcpy(l2->src_mac, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH); 25152 *lm_pdu_counter_offset += 2*_BHH_MAC_ADDR_LENGTH; 25153 l2->vlan_tag.tpid = tpid; 25154 l2->vlan_tag.tci.prio = h_data_p->vlan_pri; 25155 l2->vlan_tag.tci.cfi = 0; 25156 l2->vlan_tag.tci.vid = l3_intf.l3a_vid; 25157 *lm_pdu_counter_offset += 4; 25158 25159 BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_get(unit, 25160 l2->vlan_tag.tci.vid, 25161 &pbmp, 25162 &ubmp)); 25163 if (BCM_PBMP_MEMBER(ubmp, port)) { 25164 l2->vlan_tag.tpid = 0; /* Set to 0 to indicate untagged */ 25165 *lm_pdu_counter_offset -= 4; 25166 } 25167 25168 if (l3_intf.l3a_inner_vlan != 0) { 25169 BCM_IF_ERROR_RETURN(bcm_esw_port_inner_tpid_get(unit, port, &tpid)); 25170 l2->vlan_tag_inner.tpid = tpid; 25171 l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri; 25172 l2->vlan_tag_inner.tci.cfi = 0; 25173 l2->vlan_tag_inner.tci.vid = l3_intf.l3a_inner_vlan; 25174 *lm_pdu_counter_offset += 4; 25175 } 25176 }else { 25177 sal_memcpy(l2->dst_mac, h_data_p->dst_mac_address, _BHH_MAC_ADDR_LENGTH); 25178 sal_memcpy(l2->src_mac, h_data_p->src_mac_address, _BHH_MAC_ADDR_LENGTH); 25179 *lm_pdu_counter_offset += 2*_BHH_MAC_ADDR_LENGTH; 25180 if((h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterVlan) || 25181 (h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan) || 25182 (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)){ 25183 if (h_data_p->vlan != 0) { 25184 l2->vlan_tag.tpid = h_data_p->outer_tpid; 25185 l2->vlan_tag.tci.prio = h_data_p->vlan_pri; 25186 l2->vlan_tag.tci.cfi = 0; 25187 l2->vlan_tag.tci.vid = h_data_p->vlan; 25188 *lm_pdu_counter_offset += 4; 25189 } 25190 } 25191 if((h_data_p->type == bcmOAMEndpointTypeBhhSectionInnervlan) || 25192 (h_data_p->type == bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan)){ 25193 l2->vlan_tag_inner.tpid = h_data_p->inner_tpid; 25194 l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri; 25195 l2->vlan_tag_inner.tci.cfi = 0; 25196 l2->vlan_tag_inner.tci.vid = h_data_p->inner_vlan; 25197 *lm_pdu_counter_offset += 4; 25198 } 25199 etype = SHR_BHH_L2_ETYPE_MPLS_UCAST; 25200 } 25201 l2->etype = etype; 25202 *lm_pdu_counter_offset += 2; 25203 25204 return (BCM_E_NONE); 25205 } 25206 #endif /* (INCLUDE_BHH) */ 25207 25208 25209 #if defined(INCLUDE_ETH_LM_DM) 25210 /* Create L2 header for ETH_LM_DM OAM packet */ 25211 STATIC int 25212 _bcm_sb2_oam_eth_l2_header_get(int unit, _bcm_oam_hash_data_t *h_data_p, 25213 bcm_port_t port, uint16 etype, 25214 _eth_l2_header_t *l2, 25215 uint8 pkt_pri) 25216 { 25217 uint8 outer_pri = 0, inner_pri = 0; 25218 25219 switch(h_data_p->oam_domain) { 25220 25221 case _BCM_OAM_DOMAIN_CVLAN: 25222 outer_pri = h_data_p->vlan_pri; 25223 inner_pri = pkt_pri; 25224 break; 25225 25226 case _BCM_OAM_DOMAIN_SVLAN: 25227 outer_pri = pkt_pri; 25228 inner_pri = 0; 25229 break; 25230 25231 case _BCM_OAM_DOMAIN_S_PLUS_CVLAN: 25232 outer_pri = pkt_pri; 25233 inner_pri = h_data_p->inner_vlan_pri; 25234 break; 25235 25236 case _BCM_OAM_DOMAIN_PORT: 25237 outer_pri = 0; 25238 inner_pri = 0; 25239 break; 25240 25241 default: 25242 /* ETH LM/DM is not supported for other domains */ 25243 return BCM_E_UNAVAIL; 25244 } 25245 25246 memcpy(l2->src_mac, h_data_p->src_mac_address, sizeof(bcm_mac_t)); 25247 25248 if (h_data_p->outer_tpid) { 25249 l2->vlan_tag.tpid = h_data_p->outer_tpid; 25250 }else { 25251 l2->vlan_tag.tpid = BCM_OAM_DEFAULT_TPID; 25252 } 25253 l2->vlan_tag.tci.prio = outer_pri; 25254 l2->vlan_tag.tci.cfi = 0; 25255 l2->vlan_tag.tci.vid = h_data_p->vlan; 25256 25257 if (h_data_p->inner_tpid) { 25258 l2->inner_vlan_tag.tpid = h_data_p->inner_tpid; 25259 }else { 25260 l2->inner_vlan_tag.tpid = BCM_OAM_DEFAULT_TPID; 25261 } 25262 l2->inner_vlan_tag.tci.prio = inner_pri; 25263 l2->inner_vlan_tag.tci.cfi = 0; 25264 l2->inner_vlan_tag.tci.vid = h_data_p->inner_vlan; 25265 l2->etype = etype; 25266 25267 return (BCM_E_NONE); 25268 } 25269 25270 /* 25271 * Function: 25272 * _bcm_sb2_oam_bhh_appl_callback 25273 * Purpose: 25274 * Update FW BHH appl state 25275 * Parameters: 25276 * unit - (IN) Unit number. 25277 * uC - (IN) core number. 25278 * stage - (IN) core reset stage. 25279 * user_data - (IN) data pointer. 25280 * Returns: 25281 * BCM_E_XXX 25282 * Notes: 25283 */ 25284 25285 int _bcm_sb2_oam_eth_lm_dm_appl_callback(int unit, 25286 int uC, 25287 soc_cmic_uc_shutdown_stage_t stage, 25288 void *user_data) { 25289 _bcm_oam_control_t *oc; 25290 25291 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 25292 _BCM_OAM_LOCK(oc); 25293 oc->eth_lm_dm_ukernel_not_ready = 1; 25294 25295 _BCM_OAM_UNLOCK(oc); 25296 25297 return BCM_E_NONE; 25298 } 25299 25300 #endif 25301 25302 #if defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM) || defined(INCLUDE_BHH) 25303 /* Create OLP-L2 header for ETH_LM_DM Tx OAM packet */ 25304 STATIC int 25305 _bcm_sb2_oam_olp_l2_header_get(int unit, int cpu_dglp, soc_olp_l2_hdr_t *l2) 25306 { 25307 uint16 tpid; 25308 uint16 vlanId; 25309 uint16 ethertype; 25310 egr_olp_config_entry_t eolp_cfg; 25311 uint64 iarb_olp_cfg; 25312 uint64 iarb_olp_cfg_1; 25313 bcm_mac_t olp_mac; 25314 bcm_mac_t xgs_mac; 25315 int index; 25316 lmep_entry_t lmep_entry; 25317 int rv; 25318 25319 memset(l2, 0, sizeof(soc_olp_l2_hdr_t)); 25320 sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t)); 25321 sal_memset(&eolp_cfg, 0, sizeof(egr_olp_config_entry_t)); 25322 25323 rv = _bcm_switch_olp_dglp_get(unit, cpu_dglp, &olp_mac, &index); 25324 if (BCM_FAILURE(rv)) { 25325 LOG_ERROR(BSL_LS_BCM_OAM, 25326 (BSL_META_U(unit, 25327 "OAM(unit %d) Error: READ_EGR_OLP_DGPP_CONFIG table read failed" 25328 " %s.\n"), unit , bcm_errmsg(rv))); 25329 return (rv); 25330 } 25331 25332 /* Get MAC DA of OLP*/ 25333 rv = READ_EGR_OLP_CONFIGm(unit, MEM_BLOCK_ANY, 25334 0, &eolp_cfg); 25335 if (BCM_FAILURE(rv)) { 25336 LOG_ERROR(BSL_LS_BCM_OAM, 25337 (BSL_META_U(unit, 25338 "OAM(unit %d) Error: EGR_OLP_DGPP_CONFIG table read failed" 25339 " %s.\n"), unit, bcm_errmsg(rv))); 25340 return (rv); 25341 } 25342 soc_mem_mac_addr_get(unit ,EGR_OLP_CONFIGm, &eolp_cfg, 25343 MACSAf, xgs_mac); 25344 25345 /* Get TPID of OLP*/ 25346 rv = READ_EGR_OLP_CONFIGm(unit, MEM_BLOCK_ANY, 25347 0, &eolp_cfg); 25348 if (BCM_FAILURE(rv)) { 25349 LOG_ERROR(BSL_LS_BCM_OAM, 25350 (BSL_META_U(unit, 25351 "OAM(unit %d) Error: READ_EGR_OLP_CONFIG table read failed" 25352 " %s.\n"), unit, bcm_errmsg(rv))); 25353 return (rv); 25354 } 25355 tpid = soc_mem_field32_get(unit, EGR_OLP_CONFIGm, &eolp_cfg, 25356 VLAN_TPIDf); 25357 if (BCM_FAILURE(rv)) { 25358 LOG_ERROR(BSL_LS_BCM_OAM, 25359 (BSL_META_U(unit, 25360 "OAM(unit %d) Error: READ_EGR_OLP_CONFIG table read failed" 25361 " %s.\n"), unit, bcm_errmsg(rv))); 25362 return (rv); 25363 } 25364 /* Get hardware table entry information. */ 25365 rv = READ_IARB_OLP_CONFIGr(unit, &iarb_olp_cfg); 25366 if (BCM_FAILURE(rv)) { 25367 LOG_ERROR(BSL_LS_BCM_OAM, 25368 (BSL_META_U(unit, 25369 "OAM(unit %d) Error: IARB_OLP_CONFIG register read failed" 25370 " %s.\n"), unit , bcm_errmsg(rv))); 25371 return (rv); 25372 } 25373 ethertype = soc_reg64_field_get(unit, IARB_OLP_CONFIGr, 25374 iarb_olp_cfg, ETHERTYPEf); 25375 25376 rv = READ_IARB_OLP_CONFIG_1r(unit, &iarb_olp_cfg_1); 25377 if (BCM_FAILURE(rv)) { 25378 LOG_ERROR(BSL_LS_BCM_OAM, 25379 (BSL_META_U(unit, 25380 "OAM(unit %d) Error: READ_EGR_OLP_CONFIG_1 table read failed" 25381 " %s.\n"), unit , bcm_errmsg(rv))); 25382 return (rv); 25383 } 25384 vlanId = soc_reg64_field_get(unit, IARB_OLP_CONFIG_1r, 25385 iarb_olp_cfg_1, VLAN_IDf); 25386 25387 memcpy(l2->dst_mac, xgs_mac, sizeof(bcm_mac_t)); 25388 memcpy(l2->src_mac, olp_mac, sizeof(bcm_mac_t)); 25389 l2->tpid = tpid; 25390 l2->vlan = vlanId; 25391 l2->etherType = ethertype; 25392 25393 return (BCM_E_NONE); 25394 } 25395 #endif /* INCLUDE_ETH_LM_DM || INCLUDE_MPLS_LM_DM || INCLUDE_BHH */ 25396 25397 #if defined(INCLUDE_BHH) 25398 STATIC uint8 * 25399 _bcm_sb2_oam_bhh_ach_header_pack(uint8 *buffer, _ach_header_t *ach) 25400 { 25401 uint32 tmp; 25402 25403 tmp = ((ach->f_nibble & 0xf) << 28) | ((ach->version & 0xf) << 24) | 25404 (ach->reserved << 16) | ach->channel_type; 25405 25406 _BHH_ENCAP_PACK_U32(buffer, tmp); 25407 25408 return (buffer); 25409 } 25410 25411 STATIC uint8 * 25412 _bcm_sb2_oam_bhh_mpls_label_pack(uint8 *buffer, _mpls_label_t *mpls) 25413 { 25414 uint32 tmp; 25415 25416 tmp = ((mpls->label & 0xfffff) << 12) | ((mpls->exp & 0x7) << 9) | 25417 ((mpls->s & 0x1) << 8) | mpls->ttl; 25418 _BHH_ENCAP_PACK_U32(buffer, tmp); 25419 25420 return (buffer); 25421 } 25422 25423 STATIC uint8 * 25424 _bcm_sb2_oam_bhh_mpls_label_unpack(uint8 *buffer, _mpls_label_t *mpls) 25425 { 25426 uint32 tmp; 25427 25428 _SHR_UNPACK_U32(buffer, tmp); 25429 mpls->label = (tmp >> 12) & 0xfffff; 25430 mpls->exp = (tmp >> 9) & 0x7; 25431 mpls->s = (tmp >> 8) & 0x1; 25432 mpls->ttl = tmp & 0xffff; 25433 25434 return (buffer); 25435 } 25436 25437 STATIC uint8 * 25438 _bcm_sb2_oam_bhh_l2_header_pack(bcm_oam_endpoint_type_t type, 25439 uint8 *buffer, _l2_header_t *l2) 25440 { 25441 uint32 tmp; 25442 int i; 25443 25444 for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) { 25445 _BHH_ENCAP_PACK_U8(buffer, l2->dst_mac[i]); 25446 } 25447 25448 for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) { 25449 _BHH_ENCAP_PACK_U8(buffer, l2->src_mac[i]); 25450 } 25451 25452 /* Vlan Tag tpid = 0 indicates untagged */ 25453 if (0 != l2->vlan_tag.tpid) { 25454 tmp = (l2->vlan_tag.tpid << 16) | 25455 ((l2->vlan_tag.tci.prio & 0x7) << 13) | 25456 ((l2->vlan_tag.tci.cfi & 0x1) << 12) | 25457 (l2->vlan_tag.tci.vid & 0xfff); 25458 _BHH_ENCAP_PACK_U32(buffer, tmp); 25459 } 25460 25461 /*Inner Vlan Tag inner_tpid = 0 indicates single tag */ 25462 if (0 != l2->vlan_tag_inner.tpid) { 25463 tmp = (l2->vlan_tag_inner.tpid << 16) | 25464 ((l2->vlan_tag_inner.tci.prio & 0x7) << 13) | 25465 ((l2->vlan_tag_inner.tci.cfi & 0x1) << 12) | 25466 (l2->vlan_tag_inner.tci.vid & 0xfff); 25467 _BHH_ENCAP_PACK_U32(buffer, tmp); 25468 } 25469 _BHH_ENCAP_PACK_U16(buffer, l2->etype); 25470 25471 return (buffer); 25472 } 25473 #endif 25474 25475 #if defined(INCLUDE_ETH_LM_DM) 25476 STATIC uint8 * 25477 _bcm_sb2_oam_eth_l2_header_pack(uint8 *buffer, _eth_l2_header_t *l2) 25478 { 25479 uint32 tmp; 25480 int i; 25481 25482 for (i = 0; i < _ETH_LM_DM_MAC_ADDR_LENGTH; i++) { 25483 _ETH_LM_DM_ENCAP_PACK_U8(buffer, l2->dst_mac[i]); 25484 } 25485 25486 for (i = 0; i < _ETH_LM_DM_MAC_ADDR_LENGTH; i++) { 25487 _ETH_LM_DM_ENCAP_PACK_U8(buffer, l2->src_mac[i]); 25488 } 25489 25490 /* Outer vlan Tag */ 25491 if(l2->vlan_tag.tci.vid) { 25492 tmp = (l2->vlan_tag.tpid << 16) | ((l2->vlan_tag.tci.prio & 0x7) << 13) | 25493 ((l2->vlan_tag.tci.cfi & 0x1) << 12) | (l2->vlan_tag.tci.vid & 0xfff); 25494 _ETH_LM_DM_ENCAP_PACK_U32(buffer, tmp); 25495 } 25496 25497 /* Inner Vlan Tag */ 25498 if(l2->inner_vlan_tag.tci.vid) { 25499 tmp = (l2->inner_vlan_tag.tpid << 16) | ((l2->inner_vlan_tag.tci.prio & 0x7) << 13) | 25500 ((l2->inner_vlan_tag.tci.cfi & 0x1) << 12) | (l2->inner_vlan_tag.tci.vid & 0xfff); 25501 _ETH_LM_DM_ENCAP_PACK_U32(buffer, tmp); 25502 } 25503 25504 _ETH_LM_DM_ENCAP_PACK_U16(buffer, l2->etype); 25505 25506 return (buffer); 25507 } 25508 #endif 25509 25510 #if defined(INCLUDE_ETH_LM_DM) || defined (INCLUDE_MPLS_LM_DM) || defined (INCLUDE_BHH) 25511 STATIC uint8 * 25512 _bcm_sb2_oam_olp_l2_header_pack(uint8 *buffer, soc_olp_l2_hdr_t *l2) 25513 { 25514 25515 int i; 25516 25517 for (i = 0; i < 6; i++) { 25518 _SHR_PACK_U8(buffer, l2->dst_mac[i]); 25519 } 25520 25521 for (i = 0; i < 6; i++) { 25522 _SHR_PACK_U8(buffer, l2->src_mac[i]); 25523 } 25524 25525 /* Vlan tpid */ 25526 _SHR_PACK_U16(buffer, l2->tpid); 25527 25528 /* Vlan Id */ 25529 _SHR_PACK_U16(buffer, l2->vlan); 25530 25531 /* Ethertype */ 25532 _SHR_PACK_U16(buffer, l2->etherType); 25533 25534 return (buffer); 25535 } 25536 25537 STATIC uint8 *_bcm_sb2_oam_olp_l2_header_unpack(uint8 *buffer, soc_olp_l2_hdr_t *l2) 25538 { 25539 int i; 25540 25541 for (i = 0; i < 6; i++) { 25542 _SHR_UNPACK_U8(buffer, l2->dst_mac[i]); 25543 } 25544 25545 for (i = 0; i < 6; i++) { 25546 _SHR_UNPACK_U8(buffer, l2->src_mac[i]); 25547 } 25548 25549 /* Vlan tpid */ 25550 _SHR_UNPACK_U16(buffer, l2->tpid); 25551 25552 /* Vlan Id */ 25553 _SHR_UNPACK_U16(buffer, l2->vlan); 25554 25555 /* Ethertype */ 25556 _SHR_UNPACK_U16(buffer, l2->etherType); 25557 25558 return (buffer); 25559 } 25560 25561 STATIC int 25562 _bcm_sb2_oam_olp_tx_header_decap(int unit, 25563 uint8 *encap_data, 25564 uint8 *counter_size, 25565 uint32 *counter_base_id, 25566 uint32 *counter_offset, 25567 uint8 *counter_action, 25568 uint32 *counter_lm_counter_byte_offset, 25569 uint8 *ts_mode, 25570 uint8 *lm_pdu_counter_offset, 25571 bcm_cos_t *int_pri) 25572 { 25573 soc_olp_tx_hdr_t olp_oam_header; 25574 int i = 0, action[BCM_OAM_LM_COUNTER_MAX]; 25575 uint8 oam_replacement_offset; 25576 25577 /* NULL pointer */ 25578 if(!encap_data) { 25579 return BCM_E_MEMORY; 25580 } 25581 25582 sal_memset(&olp_oam_header, 0, sizeof(olp_oam_header)); 25583 encap_data = shr_olp_tx_header_unpack(encap_data, &olp_oam_header); 25584 25585 action[i] = SOC_OLP_TX_CTR1_ACTION_GET(&olp_oam_header); 25586 if ((action[i] == 1) || (action[i] == 2)) { 25587 /* We do a mod 8 since we always allocate counters in chunks of 8 */ 25588 counter_offset[i] = SOC_OLP_TX_CTR1_ID_GET(&olp_oam_header) % 8; 25589 counter_base_id[i] = 25590 SOC_OLP_TX_CTR1_ID_GET(&olp_oam_header) - counter_offset[i]; 25591 25592 if(counter_action) { 25593 counter_action[i]= action[i]; 25594 } 25595 if(counter_lm_counter_byte_offset) { 25596 counter_lm_counter_byte_offset[i] = 25597 SOC_OLP_TX_CTR1_OFF_LM_GET(&olp_oam_header); 25598 } 25599 25600 i++; 25601 } 25602 action[i] = SOC_OLP_TX_CTR2_ACTION_GET(&olp_oam_header); 25603 if ((action[i] == 1) || (action[i] == 2)) { 25604 /* We do a mod 8 since we always allocate counters in chunks of 8 */ 25605 counter_offset[i] = SOC_OLP_TX_CTR2_ID_GET(&olp_oam_header) % 8; 25606 /* Encode pool number = 1 in base id as well */ 25607 counter_base_id[i] = 25608 (SOC_OLP_TX_CTR2_ID_GET(&olp_oam_header) - counter_offset[i]) | (1 << 24); 25609 25610 if(counter_action) { 25611 counter_action[i]= action[i]; 25612 } 25613 25614 if(counter_lm_counter_byte_offset) { 25615 counter_lm_counter_byte_offset[i] = 25616 SOC_OLP_TX_CTR2_OFF_LM_GET(&olp_oam_header); 25617 } 25618 25619 i++; 25620 } 25621 action[i] = SOC_OLP_TX_CTR3_ACTION_GET(&olp_oam_header); 25622 if ((action[i] == 1) || (action[i] == 2)) { 25623 /* We do a mod 8 since we always allocate counters in chunks of 8 */ 25624 counter_offset[i] = SOC_OLP_TX_CTR3_ID_GET(&olp_oam_header) % 8; 25625 /* Encode pool number = 1 in base id as well */ 25626 counter_base_id[i] = 25627 (SOC_OLP_TX_CTR3_ID_GET(&olp_oam_header) - counter_offset[i]) | (2 << 24); 25628 25629 if(counter_action) { 25630 counter_action[i]= action[i]; 25631 } 25632 25633 if(counter_lm_counter_byte_offset) { 25634 counter_lm_counter_byte_offset[i] = 25635 SOC_OLP_TX_CTR2_OFF_LM_GET(&olp_oam_header); 25636 } 25637 25638 i++; 25639 } 25640 25641 *counter_size = i; 25642 25643 if(ts_mode) { 25644 *ts_mode = SOC_OLP_TX_TIMESTAMP_ACTION_GET(&olp_oam_header); 25645 } 25646 25647 oam_replacement_offset = SOC_OLP_TX_OAM_OFFSET_GET(&olp_oam_header); 25648 25649 if (oam_replacement_offset && lm_pdu_counter_offset) { 25650 *lm_pdu_counter_offset = (oam_replacement_offset << 1) + 14; 25651 } 25652 25653 if(int_pri) { 25654 *int_pri = SOC_OLP_TX_PRI_GET(&olp_oam_header); 25655 } 25656 return BCM_E_NONE; 25657 } 25658 25659 STATIC uint8 * 25660 _bcm_sb2_oam_olp_l2_header_decap (int unit, 25661 uint8 *encap_data, 25662 soc_olp_l2_hdr_t *olp_l2_header) 25663 { 25664 uint8 *buffer; 25665 sal_memset(olp_l2_header, 0, sizeof(soc_olp_l2_hdr_t)); 25666 buffer = _bcm_sb2_oam_olp_l2_header_unpack(encap_data, olp_l2_header); 25667 return buffer; 25668 } 25669 25670 25671 STATIC int 25672 _bcm_sb2_oam_olp_encap_header_decap(int unit, 25673 uint8 *encap_data, 25674 uint8 *counter_size, 25675 uint32 *counter_base_id, 25676 uint32 *counter_offset, 25677 uint8 *counter_action, 25678 uint8 *ts_mode, 25679 uint8 *lm_pdu_counter_offset, 25680 bcm_cos_t *int_pri, 25681 uint32 *counter_lm_counter_byte_offset) 25682 { 25683 soc_olp_l2_hdr_t olp_l2_header; 25684 int rv; 25685 25686 /* NULL pointer */ 25687 if(!encap_data) { 25688 return BCM_E_MEMORY; 25689 } 25690 25691 encap_data = _bcm_sb2_oam_olp_l2_header_decap(unit, encap_data, &olp_l2_header); 25692 25693 rv = _bcm_sb2_oam_olp_tx_header_decap(unit, 25694 encap_data, 25695 counter_size, 25696 counter_base_id, 25697 counter_offset, 25698 counter_action, 25699 counter_lm_counter_byte_offset, 25700 ts_mode, 25701 lm_pdu_counter_offset, 25702 int_pri); 25703 if(rv != BCM_E_NONE) { 25704 return rv; 25705 } 25706 25707 return BCM_E_NONE; 25708 } 25709 25710 25711 /* 25712 * Function: 25713 * _bcm_sb2_bhh_oam_olp_tx_header_create 25714 * Purpose: 25715 * Adds OLP Tx header packet to encapsulation. 25716 * Parameters: 25717 * unit - (IN) Unit number. 25718 * mod - (IN) module Id. 25719 * port_id - (IN) port Id. 25720 * ts_mode - (IN) Timestamp type for DM PDU. 25721 * lm_pdu_counter_offset - (IN) Counter offset in LM PDU. 25722 * encap_data - (OUT) Buffer returning MPLS OAM encapsulation. 25723 * encap_length - (OUT) Buffer length which contains 25724 * MPLS OAM encapsulation length. 25725 * int_pri - (IN) INT_PRI of OAM message. 25726 * Returns: 25727 * BCM_E_XXX 25728 * Notes: 25729 * The returning MPLS OAM encapsulation buffer includes 25730 * OLP TX header. 25731 */ 25732 25733 STATIC int 25734 _bcm_sb2_bhh_oam_olp_tx_header_create(int unit, 25735 bcm_module_t mod, bcm_port_t port_id, 25736 uint8 counter_size, 25737 uint32 *counter_base_id, 25738 uint32 *counter_offset, 25739 int *counter_action, 25740 uint32 *counter_byte_offset, 25741 uint8 ts_mode, 25742 uint8 lm_pdu_counter_offset, 25743 uint8 *encap_data, 25744 uint16 *encap_length, 25745 bcm_cos_t int_pri) 25746 { 25747 int rv = 0, i; 25748 soc_olp_l2_hdr_t olp_l2_header; 25749 soc_olp_tx_hdr_t olp_oam_header; 25750 uint8 *buffer_p = encap_data; 25751 int my_mod_id = 0; 25752 int cpu_dglp = 0; 25753 int cpu_port = 0; 25754 uint8 ctr_pool = 0; 25755 25756 sal_memset(&olp_l2_header, 0, sizeof(olp_l2_header)); 25757 25758 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_mod_id)); 25759 cpu_dglp = ((my_mod_id << DGLP_MODULE_ID_SHIFT_BITS) + cpu_port); 25760 /* Get OLP L2 Header for CPU port */ 25761 rv = _bcm_sb2_oam_olp_l2_header_get(unit, cpu_dglp, &olp_l2_header); 25762 if (BCM_FAILURE(rv)) { 25763 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM Error: " 25764 "OLP Header get failed.\n"))); 25765 return (rv); 25766 } 25767 25768 buffer_p = _bcm_sb2_oam_olp_l2_header_pack(buffer_p, &olp_l2_header); 25769 25770 sal_memset(&olp_oam_header, 0, sizeof(olp_oam_header)); 25771 /* Set Port number */ 25772 SOC_OLP_TX_PORT(&olp_oam_header) = port_id; 25773 SOC_OLP_TX_MODID(&olp_oam_header) = mod; 25774 SOC_OLP_TX_PRI(&olp_oam_header) = int_pri; 25775 25776 for (i=0; i< counter_size; i++) { 25777 25778 ctr_pool = (counter_base_id[i] & 0xFF000000) >> 24; 25779 if (ctr_pool == 0) { 25780 SOC_OLP_TX_CTR1_ID(&olp_oam_header) = 25781 (counter_base_id[i] & 0x00FFFFFF) + 25782 counter_offset[i]; 25783 25784 SOC_OLP_TX_CTR1_ACTION(&olp_oam_header) = 25785 counter_action[i]; 25786 /* Counter location is Egress */ 25787 SOC_OLP_TX_CTR1_LOCATION(&olp_oam_header) = 1; 25788 } 25789 if (ctr_pool == 1) { 25790 SOC_OLP_TX_CTR2_ID_SET(&olp_oam_header, 25791 (counter_base_id[i] & 0x00FFFFFF) + 25792 counter_offset[i] 25793 ); 25794 SOC_OLP_TX_CTR2_ACTION(&olp_oam_header) = 25795 counter_action[i]; 25796 SOC_OLP_TX_CTR2_LOCATION(&olp_oam_header) = 1; 25797 } 25798 if (ctr_pool == 2) { 25799 SOC_OLP_TX_CTR3_ID_SET(&olp_oam_header, 25800 (counter_base_id[i] & 0x00FFFFFF) + 25801 counter_offset[i] 25802 ); 25803 SOC_OLP_TX_CTR3_ACTION(&olp_oam_header) = 25804 counter_action[i]; 25805 SOC_OLP_TX_CTR3_LOCATION(&olp_oam_header) = 1; 25806 } 25807 } 25808 if(lm_pdu_counter_offset){ 25809 /* COUNTER OFFSET in OLP Header = 25810 * (L2 Encap + Counter field offset in MPLS OAM Header - 14)/2 25811 */ 25812 SOC_OLP_TX_OAM_OFFSET(&olp_oam_header) = 25813 (lm_pdu_counter_offset - 14) >> 1; 25814 } 25815 25816 SOC_OLP_TX_TIMESTAMP_ACTION(&olp_oam_header) = ts_mode; 25817 25818 /* Pack OLP OAM Encap */ 25819 buffer_p = shr_olp_tx_header_pack(buffer_p, &olp_oam_header); 25820 *encap_length += (buffer_p - encap_data); 25821 25822 return rv; 25823 } 25824 #endif /* INCLUDE_ETH_LM_DM || INCLUDE_MPLS_LM_DM || INCLUDE_BHH*/ 25825 25826 #if defined(INCLUDE_BHH) 25827 /* 25828 * Function: 25829 * _bcm_sb2_oam_bhh_encap_build_pack 25830 * Purpose: 25831 * Builds and packs the BHH packet encapsulation for a given 25832 * BHH tunnel type. 25833 * Parameters: 25834 * unit - (IN) Unit number. 25835 * port - (IN) Port. 25836 * endpoint_config - (IN/OUT) Pointer to BHH endpoint structure. 25837 * packet_flags - (IN) Flags for building packet. 25838 * buffer - (OUT) Buffer returning BHH encapsulation. 25839 * Returns: 25840 * BCM_E_XXX 25841 * Notes: 25842 * The returning BHH encapsulation includes only all the 25843 * encapsulation headers/labels and does not include 25844 * the BHH control packet. 25845 */ 25846 STATIC int 25847 _bcm_sb2_oam_bhh_encap_build_pack(int unit, bcm_module_t mod, bcm_port_t port, 25848 _bcm_oam_hash_data_t *h_data_p, 25849 uint32 packet_flags, uint8 *buffer, 25850 uint16 *encap_length, 25851 _bhh_oam_lm_dm_info_t *counter_info, 25852 bcm_cos_t int_pri, uint8 oam_exp, 25853 uint8 oam_ttl) 25854 { 25855 uint8 *cur_ptr = buffer; 25856 uint16 etype = 0; 25857 bcm_if_t l3_intf_id = -1; 25858 _ach_header_t ach; 25859 _mpls_label_t mpls_gal; 25860 _mpls_label_t mpls_labels[_BHH_MPLS_MAX_LABELS]; 25861 int mpls_count = 0; 25862 _l2_header_t l2; 25863 int i; 25864 25865 25866 /* 25867 * Get necessary headers/labels information. 25868 * 25869 * Following order is important since some headers/labels 25870 * may depend on previous header/label information. 25871 */ 25872 if (packet_flags & _BHH_ENCAP_PKT_G_ACH) { 25873 BCM_IF_ERROR_RETURN 25874 (_bcm_sb2_oam_bhh_ach_header_get(packet_flags, &ach)); 25875 counter_info->oam_replacement_offset += 4; 25876 } 25877 25878 if (packet_flags & _BHH_ENCAP_PKT_GAL) { 25879 if (h_data_p->egr_label == SHR_BHH_MPLS_GAL_LABEL) { 25880 BCM_IF_ERROR_RETURN 25881 (_bcm_sb2_oam_bhh_mpls_gal_label_get(&mpls_gal, oam_exp)); 25882 } else { 25883 BCM_IF_ERROR_RETURN 25884 (_bcm_sb2_oam_bhh_mpls_gal_label_get(&mpls_gal, 0)); 25885 } 25886 counter_info->oam_replacement_offset += 4; 25887 } 25888 25889 if (packet_flags & _BHH_ENCAP_PKT_MPLS) { 25890 etype = SHR_BHH_L2_ETYPE_MPLS_UCAST; 25891 BCM_IF_ERROR_RETURN 25892 (_bcm_sb2_oam_bhh_mpls_labels_get(unit, h_data_p, packet_flags, 25893 _BHH_MPLS_MAX_LABELS, mpls_labels, 25894 &mpls_count, &l3_intf_id, 25895 oam_exp, oam_ttl)); 25896 counter_info->oam_replacement_offset += (mpls_count *4); 25897 } 25898 25899 /* Always build L2 Header */ 25900 BCM_IF_ERROR_RETURN 25901 (_bcm_sb2_oam_bhh_l2_header_get(unit, 25902 h_data_p, 25903 port, 25904 etype, 25905 &l2, 25906 &counter_info->oam_replacement_offset)); 25907 /* 25908 * Pack header/labels into given buffer (network packet format). 25909 * 25910 * Following packing order must be followed to correctly 25911 * build the packet encapsulation. 25912 */ 25913 cur_ptr = buffer; 25914 25915 if (BHH_UC_FEATURE_CHECK(BHH_OLP_ENCAP_VALID)) { 25916 _bcm_sb2_bhh_oam_olp_tx_header_create(unit, mod, port, 25917 counter_info->counter_size, 25918 counter_info->counter_base_id, 25919 counter_info->counter_offset, 25920 counter_info->counter_action, 25921 counter_info->byte_count_offset, 25922 counter_info->ts_mode, 25923 counter_info->oam_replacement_offset, 25924 buffer, 25925 encap_length, int_pri); 25926 25927 cur_ptr = buffer + *encap_length; 25928 } 25929 25930 /* L2 Header is always present */ 25931 cur_ptr = _bcm_sb2_oam_bhh_l2_header_pack(h_data_p->type, cur_ptr, &l2); 25932 25933 if (packet_flags & _BHH_ENCAP_PKT_MPLS) { 25934 for (i = 0;i < mpls_count;i++) { 25935 cur_ptr = _bcm_sb2_oam_bhh_mpls_label_pack(cur_ptr, &mpls_labels[i]); 25936 } 25937 } 25938 25939 if (packet_flags & _BHH_ENCAP_PKT_GAL) { 25940 cur_ptr = _bcm_sb2_oam_bhh_mpls_label_pack(cur_ptr, &mpls_gal); 25941 } 25942 25943 if (packet_flags & _BHH_ENCAP_PKT_G_ACH) { 25944 cur_ptr = _bcm_sb2_oam_bhh_ach_header_pack(cur_ptr, &ach); 25945 } 25946 25947 25948 /* Set BHH encapsulation length */ 25949 *encap_length = cur_ptr - buffer; 25950 25951 return (BCM_E_NONE); 25952 } 25953 25954 #endif /* (INCLUDE_BHH) */ 25955 25956 #if defined(INCLUDE_ETH_LM_DM) 25957 /* 25958 * Function: 25959 * _bcm_sb2_oam_eth_l2_encap_build_pack 25960 * Purpose: 25961 * Builds and packs the ETH L2 packet encapsulation for a given 25962 * LM/DM PACKET. 25963 * Parameters: 25964 * unit - (IN) Unit number. 25965 * port - (IN) Port. 25966 * h_data_p - (IN/OUT) Pointer to hash_data structure. 25967 * buffer - (OUT) Buffer returning ETH L2 encapsulation. 25968 * buffer_len - (OUT) Length of ETH L2 encapsulation formed. 25969 * Returns: 25970 * BCM_E_XXX 25971 * Notes: 25972 * The returning ETH L2 encapsulation includes only all the 25973 * encapsulation headers and does not include 25974 * the ETH_LM_DM control packet. 25975 */ 25976 STATIC int 25977 _bcm_sb2_oam_eth_l2_encap_build_pack(int unit, bcm_port_t port, 25978 _bcm_oam_hash_data_t *h_data_p, 25979 uint8 *buffer, 25980 uint32 *encap_length, 25981 uint8 pkt_pri) 25982 { 25983 uint8 *cur_ptr = buffer; 25984 uint16 etype = 0; 25985 _eth_l2_header_t l2; 25986 25987 etype = SHR_ETH_LM_DM_L2_ETYPE_OAM; 25988 25989 25990 /* Always build L2 Header */ 25991 BCM_IF_ERROR_RETURN 25992 (_bcm_sb2_oam_eth_l2_header_get(unit, 25993 h_data_p, 25994 port, 25995 etype, 25996 &l2, 25997 pkt_pri)); 25998 25999 /* 26000 * Pack header into given buffer (network packet format). 26001 * 26002 * Following packing order must be followed to correctly 26003 * build the packet encapsulation. 26004 */ 26005 cur_ptr = buffer; 26006 26007 /* L2 Header is always present */ 26008 cur_ptr = _bcm_sb2_oam_eth_l2_header_pack(cur_ptr, &l2); 26009 26010 /* Set ETH-L2 encapsulation length */ 26011 *encap_length = cur_ptr - buffer; 26012 26013 return (BCM_E_NONE); 26014 } 26015 26016 /* 26017 * Function: 26018 * _bcm_sb2_oam_olp_l2_encap_build_pack 26019 * Purpose: 26020 * Builds and packs the OLP L2 packet encapsulation for a given 26021 * ETH_LM_DM control packet. 26022 * Parameters: 26023 * unit - (IN) Unit number. 26024 * cpu_dglp - (IN) DGLP Port for the olp. 26025 * buffer - (OUT) Buffer returning OLP L2 encapsulation. 26026 * encap_len - (OUT) Pointer to length of OLP L2 encapsulation. 26027 * Returns: 26028 * BCM_E_XXX 26029 * Notes: 26030 * The returning OLP L2 encapsulation includes only OLP L2 header 26031 * for the ETH_LM_DM control packet 26032 */ 26033 STATIC int 26034 _bcm_sb2_oam_olp_l2_encap_build_pack(int unit, 26035 int cpu_dglp, 26036 uint8 *buffer, 26037 uint32 *encap_length) 26038 { 26039 uint8 *cur_ptr = buffer; 26040 _olp_l2_header_t l2; 26041 26042 26043 /* Build OLP L2 Header */ 26044 BCM_IF_ERROR_RETURN 26045 (_bcm_sb2_oam_olp_l2_header_get(unit, 26046 cpu_dglp, 26047 &l2)); 26048 26049 /* 26050 * Pack header into given buffer (network packet format). 26051 * 26052 * Following packing order must be followed to correctly 26053 * build the packet encapsulation. 26054 */ 26055 cur_ptr = buffer; 26056 26057 /* L2 Header is always present */ 26058 cur_ptr = _bcm_sb2_oam_olp_l2_header_pack(cur_ptr, &l2); 26059 26060 /* Set OLP L2 encapsulation length */ 26061 *encap_length = cur_ptr - buffer; 26062 26063 return (BCM_E_NONE); 26064 } 26065 #endif /*(INCLUDE_ETH_LM_DM) */ 26066 26067 #if defined(INCLUDE_BHH) 26068 STATIC void 26069 _bcm_sb2_oam_bhh_get_egress_label_from_encap(_bcm_oam_hash_data_t *h_data_p, 26070 uint8 *encap_data, 26071 uint16 encap_length, 26072 _mpls_label_t *label) 26073 { 26074 uint16 oam_label_offset = 0; 26075 26076 if(!encap_length) { 26077 LOG_CLI((BSL_META("\nEncapsulation (length=%d):\n"), encap_length)); 26078 return; 26079 } 26080 26081 if (BHH_EP_MPLS_SECTION_TYPE(h_data_p)) { 26082 /* Go back ACH and GAL */ 26083 oam_label_offset = encap_length - 26084 (SHR_BHH_ACH_LENGTH + SHR_BHH_MPLS_LABEL_LENGTH); 26085 } else if (BHH_EP_LSP_TYPE(h_data_p)) { 26086 /* Go back ACH + GAL + OAM label */ 26087 oam_label_offset = encap_length - 26088 (SHR_BHH_ACH_LENGTH + (SHR_BHH_MPLS_LABEL_LENGTH * 2)); 26089 } else { /* PW */ 26090 if (h_data_p->vccv_type == bcmOamBhhVccvGal13) { 26091 /* Go back ACH + GAL + PW label */ 26092 oam_label_offset = encap_length - 26093 (SHR_BHH_ACH_LENGTH + (SHR_BHH_MPLS_LABEL_LENGTH * 2)); 26094 } else { 26095 /* Go back ACH and PW label */ 26096 oam_label_offset = encap_length - 26097 (SHR_BHH_ACH_LENGTH + SHR_BHH_MPLS_LABEL_LENGTH); 26098 } 26099 } 26100 26101 _bcm_sb2_oam_bhh_mpls_label_unpack(&(encap_data[oam_label_offset]), label); 26102 } 26103 26104 /* 26105 * Function: 26106 * _bcm_sb2_oam_bhh_encap_create 26107 * Purpose: 26108 * Creates a BHH packet encapsulation. 26109 * Parameters: 26110 * unit - (IN) Unit number. 26111 * port_id - (IN) Port. 26112 * endpoint_config - (IN/OUT) Pointer to BHH endpoint structure. 26113 * encap_data - (OUT) Buffer returning BHH encapsulation. 26114 * Returns: 26115 * BCM_E_XXX 26116 * Notes: 26117 * The returning BHH encapsulation buffer includes all the 26118 * corresponding headers/labels EXCEPT for the BHH control packet. 26119 */ 26120 STATIC int 26121 _bcm_sb2_oam_bhh_encap_create(int unit, bcm_module_t mod, bcm_port_t port_id, 26122 _bcm_oam_hash_data_t *h_data_p, uint8 *encap_data, 26123 uint8 *encap_type, uint16 *encap_length, 26124 _bhh_oam_lm_dm_info_t *counter_info, 26125 bcm_cos_t int_pri, uint8 oam_exp, uint8 oam_ttl) 26126 { 26127 uint32 packet_flags; 26128 _bcm_oam_control_t *oc; 26129 26130 /* Get device OAM control structure handle. */ 26131 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 26132 26133 26134 packet_flags = 0; 26135 26136 /* 26137 * Get BHH encapsulation packet format flags 26138 * 26139 * Also, perform the following for each BHH tunnel type: 26140 * - Check for valid parameter values 26141 * - Set specific values required by the BHH tunnel definition 26142 * (e.g. such as ttl=1,...) 26143 */ 26144 switch (h_data_p->type) { 26145 case bcmOAMEndpointTypeBHHMPLS: 26146 packet_flags |= 26147 (_BHH_ENCAP_PKT_MPLS | 26148 _BHH_ENCAP_PKT_GAL | 26149 _BHH_ENCAP_PKT_G_ACH); 26150 break; 26151 26152 case bcmOAMEndpointTypeBHHMPLSVccv: 26153 switch(h_data_p->vccv_type) { 26154 26155 case bcmOamBhhVccvChannelAch: 26156 packet_flags |= 26157 (_BHH_ENCAP_PKT_MPLS | 26158 _BHH_ENCAP_PKT_PW | 26159 _BHH_ENCAP_PKT_G_ACH); 26160 break; 26161 26162 case bcmOamBhhVccvRouterAlert: 26163 packet_flags |= 26164 (_BHH_ENCAP_PKT_MPLS | 26165 _BHH_ENCAP_PKT_PW | 26166 _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT | 26167 _BHH_ENCAP_PKT_G_ACH); 26168 break; 26169 26170 case bcmOamBhhVccvTtl: 26171 packet_flags |= 26172 (_BHH_ENCAP_PKT_MPLS | 26173 _BHH_ENCAP_PKT_PW | 26174 _BHH_ENCAP_PKT_G_ACH); 26175 break; 26176 26177 case bcmOamBhhVccvGal13: 26178 packet_flags |= 26179 (_BHH_ENCAP_PKT_MPLS | 26180 _BHH_ENCAP_PKT_PW | 26181 _BHH_ENCAP_PKT_GAL | 26182 _BHH_ENCAP_PKT_G_ACH); 26183 break; 26184 26185 default: 26186 return (BCM_E_PARAM); 26187 break; 26188 } 26189 break; 26190 26191 case bcmOAMEndpointTypeBhhSection: 26192 case bcmOAMEndpointTypeBhhSectionInnervlan: 26193 case bcmOAMEndpointTypeBhhSectionOuterVlan: 26194 case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan: 26195 packet_flags |= 26196 (_BHH_ENCAP_PKT_GAL | 26197 _BHH_ENCAP_PKT_G_ACH); 26198 break; 26199 default: 26200 return (BCM_E_PARAM); 26201 } 26202 26203 /* Build header/labels and pack in buffer */ 26204 BCM_IF_ERROR_RETURN 26205 (_bcm_sb2_oam_bhh_encap_build_pack(unit, mod, port_id, h_data_p, 26206 packet_flags, encap_data, 26207 encap_length, counter_info, int_pri, 26208 oam_exp, oam_ttl)); 26209 26210 /* Set encap type (indicates uC side that checksum is required) */ 26211 *encap_type = SHR_BHH_ENCAP_TYPE_RAW; 26212 26213 #ifdef _BHH_DEBUG_DUMP 26214 _bcm_sb2_oam_bhh_encap_data_dump(encap_data, *encap_length); 26215 #endif 26216 26217 if (*encap_length > oc->bhh_max_encap_length) { 26218 LOG_ERROR(BSL_LS_BCM_OAM, 26219 (BSL_META_U(unit, 26220 "OAM(unit %d) Error: Encap length greater than max," 26221 "encap_length=%u max=%u\n"), 26222 unit, *encap_length, oc->bhh_max_encap_length)); 26223 return BCM_E_CONFIG; 26224 } 26225 26226 return (BCM_E_NONE); 26227 } 26228 26229 #endif /* (INCLUDE_BHH) */ 26230 26231 #if defined(INCLUDE_ETH_LM_DM) 26232 /* 26233 * Function: 26234 * _bcm_sb2_oam_eth_encap_create 26235 * Purpose: 26236 * Creates a ETH_LM/DM packet encapsulation. 26237 * Parameters: 26238 * unit - (IN) Unit number. 26239 * port_id - (IN) Port. 26240 * encap_data - (OUT) Buffer returning BHH encapsulation. 26241 * Returns: 26242 * BCM_E_XXX 26243 * Notes: 26244 * The returning ETH and OLP L2 encapsulation buffer includes all the 26245 * corresponding headers ETH_LM_DM control packet. 26246 */ 26247 STATIC int 26248 _bcm_sb2_oam_eth_olp_encap_create(int unit, bcm_port_t port_id, 26249 int dglp, 26250 _bcm_oam_hash_data_t *h_data_p, 26251 uint8 *encap_data, 26252 uint32 *eth_l2_encap_length, 26253 uint32 *olp_l2_encap_length, 26254 uint8 pkt_pri) 26255 { 26256 26257 uint8 *eth_l2_encap; 26258 /* 26259 * Get ETH ans OLP L2 encapsulation header and put them 26260 * into the buffer contiguously though while copying in 26261 * Tx packet they will be copied seperately to contain 26262 * OLP Tx header 26263 */ 26264 26265 /* Build OLP L2 header and pack in buffer */ 26266 BCM_IF_ERROR_RETURN 26267 (_bcm_sb2_oam_olp_l2_encap_build_pack(unit, 26268 dglp, 26269 encap_data, 26270 olp_l2_encap_length)); 26271 26272 eth_l2_encap = encap_data + *olp_l2_encap_length; 26273 26274 /* Build ETH L2 header and pack in buffer */ 26275 BCM_IF_ERROR_RETURN 26276 (_bcm_sb2_oam_eth_l2_encap_build_pack(unit, port_id, 26277 h_data_p, 26278 eth_l2_encap, 26279 eth_l2_encap_length, 26280 pkt_pri)); 26281 26282 h_data_p->eth_l2_encap_length = *eth_l2_encap_length; 26283 #ifdef _ETH_LM_DM_DEBUG_DUMP 26284 _bcm_sb2_oam_eth_l2_encap_data_dump(encap_data, *eth_l2_encap_length); 26285 _bcm_sb2_oam_olp_l2_encap_data_dump(olp_l2_encap, *olp_l2_encap_length); 26286 #endif 26287 26288 return (BCM_E_NONE); 26289 } 26290 /* 26291 * Function: 26292 * _bcm_sb2_oam_loss_olp_tx_encap_create 26293 * Purpose: 26294 * Creates a OLP Tx header for LM control packet. 26295 * Parameters: 26296 * unit - (IN) Unit number. 26297 * h_data_p - (IN) Pointer to hash data structure 26298 * olp_encap_data - (OUT) Pointer to OLP Tx header 26299 * olp_encap_length- (OUT) Pointer to length of OLP Tx header 26300 * loss_p - pointer to provided loss structure 26301 * port_id - (IN) Port. 26302 * module_id - (IN) Module id 26303 * mep_type - (IN) MEP type - down or up. 26304 * Returns: 26305 * BCM_E_XXX 26306 * Notes: 26307 * The returning OLP Tx header has all the fields required for LM 26308 * packet. 26309 */ 26310 STATIC int 26311 _bcm_sb2_oam_loss_olp_tx_encap_create(int unit, 26312 _bcm_oam_hash_data_t *h_data_p, 26313 uint8 *olp_encap_data, 26314 uint32 *olp_encap_length, 26315 bcm_oam_loss_t *loss_p, 26316 bcm_port_t port_id, 26317 bcm_module_t module_id, 26318 uint8 mep_type) 26319 { 26320 olp_tx_hdr_t olp_tx_hdr; 26321 uint8 *data_temp; 26322 uint32 counter_pool = 0; 26323 int i; 26324 data_temp = olp_encap_data; 26325 26326 memset(&olp_tx_hdr, 0, sizeof(olp_tx_hdr_t)); 26327 /* OLP Tx header int_pri field is of 4-bits*/ 26328 SOC_OLP_TX_PRI(&olp_tx_hdr) = (loss_p->int_pri & 0xf); 26329 SOC_OLP_TX_HDR_STYPE(&olp_tx_hdr) = mep_type; /* D-MEP = 0, U-MEp =1*/ 26330 SOC_OLP_TX_PORT(&olp_tx_hdr) = (uint16)((port_id & 0xff) | ((module_id & 0xff)<<8)); 26331 26332 if (!(loss_p->flags & BCM_OAM_LOSS_SLM)) { 26333 /* 26334 * SOC_OLP_TX_CTR1_LOCATION(&olp_tx_hdr) = ~mep_type; 26335 * SOC_OLP_TX_CTR1_ID(&olp_tx_hdr) = h_data_p->tx_ctr; 26336 * SOC_OLP_TX_CTR1_ACTION(&olp_tx_hdr) = 2; 26337 */ 26338 26339 /* Set Counter indexes */ 26340 for (i=0; i< loss_p->lm_counter_size; i++) { 26341 26342 /* Counter pool index is 8 bit MSB of 24 bit counter base index */ 26343 counter_pool = (loss_p->lm_counter_base_id[i] & 0xFF000000) >> 24; 26344 26345 if (counter_pool == 0) { 26346 SOC_OLP_TX_CTR1_ID(&olp_tx_hdr) = 26347 (loss_p->lm_counter_base_id[i] & 0x00FFFFFF) + 26348 loss_p->lm_counter_offset[i]; 26349 26350 SOC_OLP_TX_CTR1_ACTION(&olp_tx_hdr) = 26351 loss_p->lm_counter_action[i]; 26352 26353 /* D-MEP(IP) = 0, U-MEP(EP) =1*/ 26354 SOC_OLP_TX_CTR1_LOCATION(&olp_tx_hdr) = ~mep_type; 26355 } 26356 26357 if (counter_pool == 1) { 26358 SOC_OLP_TX_CTR2_ID_SET(&olp_tx_hdr, 26359 (loss_p->lm_counter_base_id[i] & 0x00FFFFFF) + 26360 loss_p->lm_counter_offset[i]); 26361 26362 SOC_OLP_TX_CTR2_ACTION(&olp_tx_hdr) = 26363 loss_p->lm_counter_action[i]; 26364 26365 SOC_OLP_TX_CTR2_LOCATION(&olp_tx_hdr) = ~mep_type; 26366 } 26367 26368 if (counter_pool == 2) { 26369 SOC_OLP_TX_CTR3_ID_SET(&olp_tx_hdr, 26370 (loss_p->lm_counter_base_id[i] & 0x00FFFFFFFF) + 26371 loss_p->lm_counter_offset[i]); 26372 26373 SOC_OLP_TX_CTR3_ACTION(&olp_tx_hdr) = 26374 loss_p->lm_counter_action[i]; 26375 26376 SOC_OLP_TX_CTR3_LOCATION(&olp_tx_hdr) = ~mep_type; 26377 } 26378 } 26379 26380 SOC_OLP_TX_OAM_OFFSET(&olp_tx_hdr) = (h_data_p->eth_l2_encap_length + 26381 sizeof(shr_eth_lm_dm_header_t) - ETH_LM_DM_RPL_OFFSET_START) >> 26382 ETH_LM_DM_RPL_OFFSET_DIVIDER_BY_SHIFT; 26383 26384 } 26385 26386 /* Pack the OLP Tx header into the Tx buffer*/ 26387 data_temp = shr_olp_tx_header_pack(data_temp, &olp_tx_hdr); 26388 26389 /* Get the size of OLP Tx buffer*/ 26390 *olp_encap_length = data_temp - olp_encap_data; 26391 26392 /* Check the length of created OLP Tx header */ 26393 if(*olp_encap_length != SHR_ETH_LM_DM_OLP_TX_HDR_LENGTH) { 26394 return (BCM_E_PARAM); 26395 } 26396 26397 #ifdef _ETH_LM_DM_DEBUG_DUMP 26398 _bcm_sb2_oam_olp_tx_encap_data_dump(olp_encap_data, *olp_encap_length); 26399 #endif 26400 26401 return (BCM_E_NONE); 26402 } 26403 26404 /* 26405 * Function: 26406 * _bcm_sb2_oam_delay_olp_tx_encap_create 26407 * Purpose: 26408 * Creates a OLP Tx header for DM packet. 26409 * Parameters: 26410 * unit - (IN) Unit number. 26411 * h_data_p - (IN) Pointer to hash data structure 26412 * olp_encap_data - (OUT) Pointer to OLP Tx header 26413 * olp_encap_length- (OUT) Pointer to length of OLP Tx header 26414 * delay_p - (IN) Pointer to provided delay structure 26415 * port_id - (IN) Port. 26416 * module_id - (IN) Module id 26417 * mep_type - (IN) MEP type - down or up. 26418 * dm_format - (IN) DM format - PTP or NTP. 26419 * Returns: 26420 * BCM_E_XXX 26421 * Notes: 26422 * The returning OLP Tx header has all the fields required for DM 26423 * packet. 26424 */ 26425 STATIC int 26426 _bcm_sb2_oam_delay_olp_tx_encap_create(int unit, 26427 _bcm_oam_hash_data_t *h_data_p, 26428 uint8 *olp_encap_data, 26429 uint32 *olp_encap_length, 26430 bcm_oam_delay_t *delay_p, 26431 bcm_port_t port_id, 26432 bcm_module_t module_id, 26433 uint8 mep_type, 26434 uint8 dm_format) 26435 { 26436 olp_tx_hdr_t olp_tx_hdr; 26437 uint8 *data_temp; 26438 uint32 counter_pool = 0; 26439 int i; 26440 data_temp = olp_encap_data; 26441 26442 memset(&olp_tx_hdr, 0, sizeof(olp_tx_hdr_t)); 26443 26444 /* OLP Tx header int_pri field is of 4-bits*/ 26445 SOC_OLP_TX_PRI(&olp_tx_hdr) = (delay_p->int_pri & 0xf); 26446 26447 SOC_OLP_TX_HDR_STYPE(&olp_tx_hdr) = mep_type; /* D-MEP = 0, U-MEp =1*/ 26448 SOC_OLP_TX_PORT(&olp_tx_hdr) = (uint16)((port_id & 0xff) | ((module_id & 0xff)<<8)); 26449 26450 /* Set Counter indexes */ 26451 for (i=0; i< delay_p->dm_tx_update_lm_counter_size; i++) { 26452 26453 /* Counter pool index is 8 bit MSB of 24 bit counter base index */ 26454 counter_pool = (delay_p->dm_tx_update_lm_counter_base_id[i] & 0xFF000000) >> 24; 26455 26456 if (counter_pool == 0) { 26457 SOC_OLP_TX_CTR1_ID(&olp_tx_hdr) = 26458 (delay_p->dm_tx_update_lm_counter_base_id[i] & 0x00FFFFFF) + 26459 delay_p->dm_tx_update_lm_counter_offset[i]; 26460 26461 SOC_OLP_TX_CTR1_ACTION(&olp_tx_hdr) = 26462 bcmOamCounterActionIncrement; 26463 /* Counter location is Egress(1) for DownMEP(0) 26464 * and Ingress(0) for Up-MEP(1). */ 26465 SOC_OLP_TX_CTR1_LOCATION(&olp_tx_hdr) = ~mep_type; 26466 } 26467 26468 if (counter_pool == 1) { 26469 SOC_OLP_TX_CTR2_ID_SET(&olp_tx_hdr, 26470 (delay_p->dm_tx_update_lm_counter_base_id[i] & 0x00FFFFFF) + 26471 delay_p->dm_tx_update_lm_counter_offset[i]); 26472 26473 SOC_OLP_TX_CTR2_ACTION(&olp_tx_hdr) = 26474 bcmOamCounterActionIncrement; 26475 SOC_OLP_TX_CTR2_LOCATION(&olp_tx_hdr) = ~mep_type; 26476 } 26477 26478 if (counter_pool == 2) { 26479 SOC_OLP_TX_CTR3_ID_SET(&olp_tx_hdr, 26480 (delay_p->dm_tx_update_lm_counter_base_id[i] & 0x00FFFFFFFF) + 26481 delay_p->dm_tx_update_lm_counter_offset[i]); 26482 26483 SOC_OLP_TX_CTR3_ACTION(&olp_tx_hdr) = 26484 bcmOamCounterActionIncrement; 26485 SOC_OLP_TX_CTR3_LOCATION(&olp_tx_hdr) = ~mep_type; 26486 } 26487 } 26488 26489 SOC_OLP_TX_OAM_OFFSET(&olp_tx_hdr) = (h_data_p->eth_l2_encap_length + 26490 sizeof(shr_eth_lm_dm_header_t) - 26491 ETH_LM_DM_RPL_OFFSET_START) >> ETH_LM_DM_RPL_OFFSET_DIVIDER_BY_SHIFT; 26492 26493 SOC_OLP_TX_TIMESTAMP_ACTION(&olp_tx_hdr) = dm_format; 26494 26495 /* Pack the OLP Tx header into the Tx buffer*/ 26496 data_temp = shr_olp_tx_header_pack(data_temp, &olp_tx_hdr); 26497 26498 /* Get the size of OLP Tx buffer*/ 26499 *olp_encap_length = data_temp - olp_encap_data; 26500 26501 /* Check the length of created OLP Tx header */ 26502 if(*olp_encap_length != SHR_ETH_LM_DM_OLP_TX_HDR_LENGTH) { 26503 return (BCM_E_PARAM); 26504 } 26505 26506 #ifdef _ETH_LM_DM_DEBUG_DUMP 26507 _bcm_sb2_oam_olp_tx_encap_data_dump(olp_encap_data, *olp_encap_length); 26508 #endif 26509 26510 return (BCM_E_NONE); 26511 } 26512 #endif /* (INCLUDE_ETH_LM_DM) */ 26513 26514 #if defined(INCLUDE_BHH) 26515 26516 /* 26517 * Function: 26518 * bcm_sb2_oam_bhh_endpoint_ccm_ctr_update 26519 * Purpose: 26520 * Update CCM CTR params 26521 * Parameters: 26522 * unit - (IN) Unit number. 26523 * Returns: 26524 * BCM_E_XXX 26525 * Notes: 26526 */ 26527 STATIC int 26528 bcm_sb2_oam_bhh_endpoint_ccm_ctr_update(int unit, 26529 bcm_oam_endpoint_info_t *ep_info) 26530 { 26531 _bcm_oam_hash_data_t *h_data_p; 26532 _bcm_oam_control_t *oc; 26533 _bhh_oam_lm_dm_info_t counter_info; 26534 bhh_sdk_msg_session_update_t msg; 26535 uint8 encap_type; 26536 uint8 *buffer, *buffer_ptr; 26537 uint16 buffer_len, reply_len; 26538 bcm_module_t module_id; /* Module ID */ 26539 bcm_port_t port_id; 26540 bcm_trunk_t trunk_id; 26541 int local_id; 26542 int i; 26543 int rv = BCM_E_NONE; 26544 uint32 msg_flags = 0; 26545 uint8 proactive_lm_enable = 0; 26546 26547 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 26548 if (oc->ukernel_not_ready) { 26549 return BCM_E_NONE; 26550 } 26551 if (!BHH_UC_FEATURE_CHECK(BHH_OLP_ENCAP_VALID)) { 26552 /* BTE does not support OLP */ 26553 return BCM_E_NONE; 26554 } 26555 if(ep_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU) { 26556 return BCM_E_NONE; 26557 } 26558 26559 /* Validate endpoint index value. */ 26560 if((ep_info->id < _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc)) || 26561 (ep_info->id >= (_BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc) 26562 + oc->bhh_endpoint_count))) { 26563 return (BCM_E_PARAM); 26564 } 26565 26566 h_data_p = &oc->oam_hash_data[ep_info->id]; 26567 if (0 == h_data_p->in_use) { 26568 return (BCM_E_NOT_FOUND); 26569 } 26570 26571 BCM_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, h_data_p->gport, 26572 &module_id, &port_id, &trunk_id, 26573 &local_id)); 26574 26575 sal_memset(&counter_info, 0, sizeof(counter_info)); 26576 counter_info.counter_size = ep_info->ccm_tx_update_lm_counter_size; 26577 for (i = 0; i < ep_info->ccm_tx_update_lm_counter_size; i++) { 26578 counter_info.counter_base_id[i] = 26579 ep_info->ccm_tx_update_lm_counter_base_id[i]; 26580 counter_info.counter_offset[i] = 26581 ep_info->ccm_tx_update_lm_counter_offset[i]; 26582 counter_info.counter_action[i] = bcmOamCounterActionIncrement; 26583 counter_info.byte_count_offset[i] = 0; 26584 if (ep_info->ccm_tx_update_lm_counter_action[i] == 26585 bcmOamCounterActionSample) { 26586 if (SOC_IS_METROLITE (unit)) { 26587 if ((h_data_p->period == BCM_OAM_ENDPOINT_CCM_PERIOD_3MS) || 26588 (h_data_p->period == BCM_OAM_ENDPOINT_CCM_PERIOD_10MS)) { 26589 LOG_ERROR(BSL_LS_BCM_OAM, 26590 (BSL_META_U(unit, 26591 "BHH(unit %d)Error: Proactive LM is " 26592 "not supported with CCM interval <100ms" 26593 " (EP=%d)\n"), unit, ep_info->id)); 26594 return (BCM_E_PARAM); 26595 } 26596 counter_info.counter_action[i] = bcmOamCounterActionSample; 26597 proactive_lm_enable = 1; 26598 } else { 26599 LOG_ERROR(BSL_LS_BCM_OAM, 26600 (BSL_META_U(unit, 26601 "BHH(unit %d)Error: Saber2 does not" 26602 " support Proactive LM (EP=%d)\n"), 26603 unit, ep_info->id)); 26604 return (BCM_E_PARAM); 26605 } 26606 } 26607 } 26608 if (proactive_lm_enable) { 26609 msg_flags |= SHR_BHH_SESSION_UPDATE_PROACTIVE_LM_ENABLE; 26610 h_data_p->int_flags |= _BCM_OAM_ENDPOINT_BHH_PROACTIVE_LM; 26611 } else if ( h_data_p->int_flags & _BCM_OAM_ENDPOINT_BHH_PROACTIVE_LM) { 26612 msg_flags |= SHR_BHH_SESSION_UPDATE_PROACTIVE_LM_DISABLE; 26613 h_data_p->int_flags &= ~(_BCM_OAM_ENDPOINT_BHH_PROACTIVE_LM); 26614 } 26615 counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE; 26616 counter_info.oam_replacement_offset = SHR_BHH_LM_OFFSET_INSIDE_CCM_PDU; 26617 26618 sal_memset(&msg, 0, sizeof(msg)); 26619 26620 msg_flags |= SHR_BHH_SESSION_UPDATE_ENCAP; 26621 msg.flags = msg_flags; 26622 msg.sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(ep_info->id); 26623 msg.msg_type = BHH_CCM_MSG; 26624 rv = _bcm_sb2_oam_bhh_encap_create(unit, module_id, port_id, h_data_p, 26625 msg.encap_data, &encap_type, 26626 &(msg.encap_length), &counter_info, 26627 h_data_p->int_pri, 26628 h_data_p->egr_label_exp, 26629 h_data_p->egr_label_ttl); 26630 if (BCM_FAILURE(rv)) { 26631 return rv; 26632 } 26633 26634 /* Pack control message data into DMA buffer */ 26635 buffer = oc->dma_buffer; 26636 buffer_ptr = bhh_sdk_msg_ctrl_session_update_pack(buffer, &msg); 26637 buffer_len = buffer_ptr - buffer; 26638 26639 26640 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 26641 MOS_MSG_SUBCLASS_BHH_SESS_UPDATE, 26642 buffer_len, 0, 26643 MOS_MSG_SUBCLASS_BHH_SESS_UPDATE_REPLY, 26644 &reply_len); 26645 if (BCM_FAILURE(rv) || (reply_len != 0)) { 26646 return (BCM_E_INTERNAL); 26647 } 26648 return BCM_E_NONE; 26649 } 26650 26651 /* 26652 * Function: 26653 * _bcm_sb2_oam_bhh_appl_callback 26654 * Purpose: 26655 * Update FW BHH appl state 26656 * Parameters: 26657 * unit - (IN) Unit number. 26658 * uC - (IN) core number. 26659 * stage - (IN) core reset stage. 26660 * user_data - (IN) data pointer. 26661 * Returns: 26662 * BCM_E_XXX 26663 * Notes: 26664 */ 26665 26666 int _bcm_sb2_oam_bhh_appl_callback(int unit, 26667 int uC, 26668 soc_cmic_uc_shutdown_stage_t stage, 26669 void *user_data) { 26670 _bcm_oam_control_t *oc; 26671 26672 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 26673 _BCM_OAM_LOCK(oc); 26674 oc->ukernel_not_ready = 1; 26675 26676 _BCM_OAM_UNLOCK(oc); 26677 26678 return BCM_E_NONE; 26679 } 26680 26681 /* 26682 * Function: 26683 * bcm_sb2_oam_bhh_endpoint_create 26684 * Purpose: 26685 * Initialize the HW for BHH packet processing. 26686 * Configure: 26687 * - Copy to CPU BHH error packets 26688 * - CPU COS Queue for BHH packets 26689 * - RX DMA channel 26690 * Parameters: 26691 * unit - (IN) Unit number. 26692 * Returns: 26693 * BCM_E_XXX 26694 * Notes: 26695 */ 26696 int 26697 bcm_sb2_oam_bhh_endpoint_create(int unit, 26698 bcm_oam_endpoint_info_t *endpoint_info, 26699 _bcm_oam_hash_key_t *hash_key) 26700 { 26701 _bcm_oam_control_t *oc; 26702 _bcm_oam_hash_data_t *hash_data = NULL; /* Endpoint hash data pointer. */ 26703 _bcm_oam_group_data_t *group_p; /* Pointer to group data. */ 26704 int ep_req_index; /* Requested endpoint index. */ 26705 int rv = BCM_E_NONE; /* Operation return status. */ 26706 int is_remote = 0; /* Remote endpoint status. */ 26707 int is_replace; 26708 int is_local = 0; 26709 uint32 sglp = 0; /* Source global logical port. */ 26710 uint32 dglp = 0; /* Dest global logical port. */ 26711 bcm_module_t module_id; /* Module ID */ 26712 bcm_port_t port_id; 26713 bcm_trunk_t trunk_id; 26714 int local_id; 26715 uint32 svp = 0; /* Source virtual port */ 26716 bcm_port_t src_pp_port = 0; /* Source pp port. */ 26717 bcm_port_t dst_pp_port = 0; /* Dest pp port. */ 26718 bhh_sdk_msg_ctrl_sess_set_t msg_sess; 26719 bhh_sdk_msg_ctrl_rmep_create_t msg_rmep_create; 26720 uint8 *buffer, *buffer_ptr; 26721 uint16 buffer_len, reply_len; 26722 int encap = 0; 26723 uint32 session_flags; 26724 int bhh_pool_ep_idx = 0; 26725 int is_vp_valid = 0; 26726 bcm_trunk_member_t trunk_member; 26727 _bhh_oam_lm_dm_info_t counter_info; 26728 int i = 0; 26729 uint16 encap_length = 0; 26730 uint8 group_sw_rdi = 0; 26731 26732 LOG_DEBUG(BSL_LS_BCM_OAM, 26733 (BSL_META_U(unit, 26734 "BHH(unit %d) Info: bcm_sb2_oam_bhh_endpoint_create" 26735 "Endpoint ID=%d.\n"), unit, endpoint_info->id)); 26736 26737 _BCM_OAM_BHH_IS_VALID(unit); 26738 26739 /* Validate input parameter. */ 26740 if (NULL == endpoint_info) { 26741 return (BCM_E_PARAM); 26742 } 26743 26744 /* Lock already taken by the calling routine. */ 26745 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 26746 26747 26748 /* Get MEP remote endpoint status. */ 26749 is_remote = (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) ? 1 : 0; 26750 26751 is_replace = ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) != 0); 26752 26753 /* Perform BHH specific validation checks */ 26754 /* BHH EP can only be at the MAX Level */ 26755 if ( endpoint_info->level != _BCM_OAM_EP_LEVEL_MAX ) { 26756 LOG_ERROR(BSL_LS_BCM_OAM, 26757 (BSL_META_U(unit, 26758 "OAM(unit %d) Error: EP Level should be equal to %d\n"), 26759 unit, _BCM_OAM_EP_LEVEL_MAX)); 26760 return (BCM_E_PARAM); 26761 } 26762 26763 /*Validate CCM period */ 26764 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_period_validate 26765 (endpoint_info->ccm_period)); 26766 26767 /* Validate EP Id if BCM_OAM_ENDPOINT_WITH_ID flag is set */ 26768 if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) { 26769 if((endpoint_info->id < _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc)) || 26770 (endpoint_info->id >= (_BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc) 26771 + oc->bhh_endpoint_count))) { 26772 return (BCM_E_PARAM); 26773 } 26774 } 26775 26776 /* Validate remote EP Id if BCM_OAM_ENDPOINT_REMOTE flag is set */ 26777 if (is_remote) { 26778 if((endpoint_info->local_id < _BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc)) || 26779 (endpoint_info->local_id >= (_BCM_OAM_BHH_SB2_ENDPOINT_OFFSET(oc) 26780 + oc->bhh_endpoint_count))) { 26781 return (BCM_E_PARAM); 26782 } 26783 } 26784 26785 /* Validate if the gport is an MPLS port for PW MEP */ 26786 if (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv) { 26787 if (-1 == BCM_GPORT_MPLS_PORT_ID_GET(endpoint_info->gport)) { 26788 return BCM_E_PARAM; 26789 } 26790 } 26791 26792 if (is_replace) { 26793 hash_data = &oc->oam_hash_data[endpoint_info->id]; 26794 if (!hash_data->in_use) { 26795 return (BCM_E_NOT_FOUND); 26796 } 26797 26798 /* Delete original and recreate new EP */ 26799 rv = _bcm_sb2_oam_endpoint_destroy(unit, endpoint_info->id); 26800 if (BCM_FAILURE(rv)) { 26801 LOG_ERROR(BSL_LS_BCM_OAM, 26802 (BSL_META_U(unit, 26803 "OAM(unit %d) Error: Endpoint destroy (EP=%d) - %s.\n"), 26804 unit, endpoint_info->id, bcm_errmsg(rv))); 26805 return (rv); 26806 } 26807 } 26808 26809 /* 26810 BHH API have been using L3_EGRESS type in 26811 bcm_oam_endpoint_info_t.intf field. 26812 However for supporting LM/DM on Saber2 this should be DVP_EGRESS type for PW, 26813 only CCM will work with L3_EGRESS type, retaining the old type for 26814 backward compatibility 26815 */ 26816 if(!BHH_EP_MPLS_SECTION_TYPE(endpoint_info)){ 26817 if ((!BHH_EP_LSP_TYPE(endpoint_info)) && (endpoint_info->flags & 26818 (BCM_OAM_ENDPOINT_LOSS_MEASUREMENT | 26819 BCM_OAM_ENDPOINT_DELAY_MEASUREMENT))) { 26820 if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, endpoint_info->intf_id)) { 26821 LOG_ERROR(BSL_LS_BCM_OAM, 26822 (BSL_META_U(unit, 26823 "OAM(unit %d) Error: bcm_oam_endpoint_info_t.intf type" 26824 " not valid. It should be DVP_EGRESS type for LM/DM support.\n"), 26825 unit)); 26826 return (BCM_E_PARAM); 26827 } 26828 } else { 26829 if ( !BCM_XGS3_L3_EGRESS_IDX_VALID(unit, endpoint_info->intf_id) & 26830 !BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, endpoint_info->intf_id) ) { 26831 LOG_ERROR(BSL_LS_BCM_OAM, 26832 (BSL_META_U(unit, 26833 "OAM(unit %d) Error: bcm_oam_endpoint_info_t.intf type" 26834 " not valid. It should be DVP_EGRESS or L3_EGRESS type.\n"), 26835 unit)); 26836 return (BCM_E_PARAM); 26837 } 26838 } 26839 } 26840 /* Now that we passed the validation checks 26841 * Create a new endpoint with the requested ID. */ 26842 if ( !is_remote && (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) ) { 26843 26844 hash_data = &oc->oam_hash_data[endpoint_info->id]; 26845 26846 if (!is_replace && hash_data->in_use) { 26847 return (BCM_E_EXISTS); 26848 } 26849 26850 ep_req_index = endpoint_info->id; 26851 bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(ep_req_index); 26852 26853 if(BCM_FAILURE(rv)) { 26854 LOG_ERROR(BSL_LS_BCM_OAM, 26855 (BSL_META_U(unit, 26856 "BHH(unit %d) Error: Endpoint check (EP=%d) - %s.\n"), 26857 unit, endpoint_info->id, bcm_errmsg(rv))); 26858 return (rv); 26859 } 26860 26861 if(!is_replace) { 26862 rv = shr_idxres_list_reserve(oc->bhh_pool, bhh_pool_ep_idx, 26863 bhh_pool_ep_idx); 26864 if (BCM_FAILURE(rv)) { 26865 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_EXISTS) : rv; 26866 LOG_ERROR(BSL_LS_BCM_OAM, 26867 (BSL_META_U(unit, 26868 "BHH(unit %d) Error: Endpoint reserve (EP=%d) - %s.\n"), 26869 unit, endpoint_info->id, bcm_errmsg(rv))); 26870 return (rv); 26871 } 26872 } 26873 } else { 26874 26875 /* BHH uses local and remote same index */ 26876 if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) { 26877 ep_req_index = endpoint_info->local_id; 26878 bhh_pool_ep_idx = BCM_OAM_BHH_GET_UKERNEL_EP(ep_req_index); 26879 } 26880 else { 26881 /* Allocate the next available endpoint index. */ 26882 rv = shr_idxres_list_alloc(oc->bhh_pool, 26883 (shr_idxres_element_t *)&bhh_pool_ep_idx); 26884 if (BCM_FAILURE(rv)) { 26885 rv = (rv == BCM_E_RESOURCE) ? (BCM_E_FULL) : rv; 26886 LOG_ERROR(BSL_LS_BCM_OAM, 26887 (BSL_META_U(unit, 26888 "BHH(unit %d) Error: Endpoint alloc failed - %s.\n"), 26889 unit, bcm_errmsg(rv))); 26890 return (rv); 26891 } 26892 /* Set the allocated endpoint id value. */ 26893 ep_req_index = BCM_OAM_BHH_GET_SDK_EP(bhh_pool_ep_idx); 26894 } 26895 endpoint_info->id = ep_req_index; 26896 } 26897 26898 /* Get the hash data pointer where the data is to be stored. */ 26899 hash_data = &oc->oam_hash_data[ep_req_index]; 26900 group_p = &oc->group_info[endpoint_info->group]; 26901 26902 if (is_remote) { 26903 26904 if (!hash_data->in_use) { 26905 return (BCM_E_NOT_FOUND); 26906 } else if (hash_data->flags & BCM_OAM_ENDPOINT_REMOTE) { 26907 return (BCM_E_EXISTS); 26908 } 26909 if(!(endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)){ 26910 /* 26911 * Now that both ends are provisioned the uKernel can be 26912 * configured. 26913 */ 26914 msg_rmep_create.sess_id = bhh_pool_ep_idx; 26915 msg_rmep_create.flags = 0; 26916 msg_rmep_create.enable = 1; 26917 msg_rmep_create.remote_mep_id = endpoint_info->name; 26918 msg_rmep_create.period = _sb2_ccm_intervals[ 26919 _bcm_sb2_oam_ccm_msecs_to_hw_encode(endpoint_info->ccm_period)]; 26920 26921 /* Pack control message data into DMA buffer */ 26922 buffer = oc->dma_buffer; 26923 buffer_ptr = bhh_sdk_msg_ctrl_rmep_create_pack(buffer, 26924 &msg_rmep_create); 26925 buffer_len = buffer_ptr - buffer; 26926 26927 /* Send BHH Session Update message to uC */ 26928 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 26929 MOS_MSG_SUBCLASS_BHH_RMEP_CREATE, 26930 buffer_len, 0, 26931 MOS_MSG_SUBCLASS_BHH_RMEP_CREATE_REPLY, 26932 &reply_len); 26933 if (BCM_FAILURE(rv) || (reply_len != 0)) { 26934 LOG_ERROR(BSL_LS_BCM_OAM, 26935 (BSL_META_U(unit, 26936 "BHH(unit %d) Error: Endpoint create " 26937 "(EP=%d) - %s.\n"), 26938 unit, endpoint_info->id, bcm_errmsg(rv))); 26939 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx)); 26940 return (BCM_E_INTERNAL); 26941 } 26942 } 26943 } else { 26944 /* Resolve given endpoint gport value to SGLP and DGLP values. */ 26945 rv = _bcm_sb2_oam_endpoint_gport_resolve(unit, endpoint_info, &sglp, 26946 &dglp, &src_pp_port, &dst_pp_port, &svp, &trunk_id, 26947 &is_vp_valid, &trunk_member); 26948 if (BCM_FAILURE(rv)) { 26949 LOG_ERROR(BSL_LS_BCM_OAM, 26950 (BSL_META_U(unit, 26951 "OAM(unit %d) Error: Gport resolve (EP=%d) - %s.\n"), 26952 unit, endpoint_info->id, bcm_errmsg(rv))); 26953 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx)); 26954 return (rv); 26955 } 26956 26957 /* Clear the hash data element contents before storing the values */ 26958 _BCM_OAM_HASH_DATA_CLEAR(hash_data); 26959 hash_data->oam_domain = _BCM_SB2_OAM_DOMAIN_BHH; 26960 hash_data->type = endpoint_info->type; 26961 hash_data->ep_id = endpoint_info->id; 26962 hash_data->group_index = endpoint_info->group; 26963 hash_data->level = endpoint_info->level; 26964 hash_data->vlan = endpoint_info->vlan; 26965 hash_data->inner_vlan = endpoint_info->inner_vlan; 26966 hash_data->outer_tpid = endpoint_info->outer_tpid; 26967 hash_data->inner_tpid = endpoint_info->inner_tpid; 26968 hash_data->vlan_pri = endpoint_info->pkt_pri; 26969 hash_data->inner_vlan_pri = endpoint_info->inner_pkt_pri; 26970 hash_data->gport = endpoint_info->gport; 26971 hash_data->sglp = sglp; 26972 hash_data->dglp = dglp; 26973 hash_data->src_pp_port = src_pp_port; 26974 hash_data->dst_pp_port = dst_pp_port; 26975 hash_data->flags = endpoint_info->flags; 26976 hash_data->flags2 = endpoint_info->flags2; 26977 hash_data->int_pri = endpoint_info->int_pri; 26978 hash_data->period = endpoint_info->ccm_period; 26979 hash_data->vccv_type = endpoint_info->vccv_type; 26980 hash_data->vpn = endpoint_info->vpn; 26981 hash_data->name = endpoint_info->name; 26982 hash_data->egress_if = endpoint_info->intf_id; 26983 hash_data->cpu_qid = endpoint_info->cpu_qid; 26984 hash_data->label = endpoint_info->mpls_label; 26985 hash_data->gport = endpoint_info->gport; 26986 hash_data->local_tx_enabled = 0; 26987 hash_data->local_rx_enabled = 1; 26988 hash_data->ts_format = endpoint_info->timestamp_format; 26989 hash_data->trunk_index = endpoint_info->trunk_index; 26990 hash_data->egr_label = endpoint_info->egress_label.label; 26991 hash_data->egr_label_exp = endpoint_info->egress_label.exp; 26992 hash_data->egr_label_ttl = endpoint_info->egress_label.ttl; 26993 sal_memcpy(hash_data->dst_mac_address, 26994 endpoint_info->dst_mac_address, _BHH_MAC_ADDR_LENGTH); 26995 sal_memcpy(hash_data->src_mac_address, 26996 endpoint_info->src_mac_address, _BHH_MAC_ADDR_LENGTH); 26997 hash_data->trunk_id = trunk_id; 26998 if (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv) { 26999 rv = _bcm_sb2_oam_mpls_lmdm_pw_svp_get(unit, 27000 hash_data->label, hash_data->sglp, 27001 &(hash_data->vp)); 27002 if (BCM_FAILURE(rv)) { 27003 /* Return endpoint index to MEP pool. */ 27004 shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx); 27005 LOG_ERROR(BSL_LS_BCM_OAM, 27006 (BSL_META_U(unit, 27007 "OAM(unit %d) Error: svp get(EP=%d) - %s.\n"), 27008 unit, endpoint_info->id, bcm_errmsg(rv))); 27009 return (rv); 27010 } 27011 } 27012 /* Initialize hardware index as invalid indices. */ 27013 hash_data->local_tx_index = _BCM_OAM_INVALID_INDEX; 27014 hash_data->local_rx_index = _BCM_OAM_INVALID_INDEX; 27015 hash_data->remote_index = _BCM_OAM_INVALID_INDEX; 27016 hash_data->dglp1_profile_index = _BCM_OAM_INVALID_INDEX; 27017 hash_data->dglp2_profile_index = _BCM_OAM_INVALID_INDEX; 27018 hash_data->rx_ctr = _BCM_OAM_INVALID_INDEX; 27019 hash_data->tx_ctr = _BCM_OAM_INVALID_INDEX; 27020 hash_data->profile_index = _BCM_OAM_INVALID_INDEX; 27021 hash_data->pri_map_index = _BCM_OAM_INVALID_INDEX; 27022 hash_data->egr_pri_map_index = _BCM_OAM_INVALID_INDEX; 27023 hash_data->outer_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 27024 hash_data->subport_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 27025 hash_data->inner_tpid_profile_index = _BCM_OAM_INVALID_INDEX; 27026 hash_data->ma_base_index = _BCM_OAM_INVALID_INDEX; 27027 hash_data->pm_profile_attached = _BCM_OAM_INVALID_INDEX; 27028 hash_data->in_use = 1; 27029 27030 /* Now that we have reserved the EP index, We can reserve MA INDEX */ 27031 rv = _bcm_sb2_oam_downmep_rx_endpoint_reserve(unit, endpoint_info); 27032 if (BCM_FAILURE(rv)) { 27033 /* Return endpoint index to MEP pool. */ 27034 shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx); 27035 LOG_ERROR(BSL_LS_BCM_OAM, 27036 (BSL_META_U(unit, 27037 "OAM(unit %d) Error: EP MA INDEX alloc" 27038 "failed EP:%d %s.\n"), unit, endpoint_info->id, 27039 bcm_errmsg(rv))); 27040 return (rv); 27041 } 27042 27043 if (oc->ukernel_not_ready == 0) { 27044 /* Copy VPN and group id for warm boot recovery*/ 27045 oc->bhh_ep_vpn[bhh_pool_ep_idx] = hash_data->vpn; 27046 oc->bhh_ep_grp_id[bhh_pool_ep_idx] = hash_data->group_index; 27047 SHR_BITSET(oc->bhh_ma_index_in_use, hash_data->ma_base_index); 27048 } 27049 27050 rv = _bcm_sb2_oam_local_rx_mep_hw_set(unit, endpoint_info); 27051 if (BCM_FAILURE(rv)) { 27052 LOG_ERROR(BSL_LS_BCM_OAM, 27053 (BSL_META_U(unit, 27054 "OAM(unit %d) Error: Rx config failed for EP=%d %s.\n"), 27055 unit, endpoint_info->id, bcm_errmsg(rv))); 27056 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 27057 BCM_IF_ERROR_RETURN(shr_idxres_list_free(oc->bhh_pool, bhh_pool_ep_idx)); 27058 return (rv); 27059 } 27060 /* BHH Section OAM */ 27061 if (BHH_EP_MPLS_SECTION_TYPE(hash_data)) { 27062 rv = _bcm_sb2_oam_port_table_key_update(unit, PORT_TABm, hash_data); 27063 if (BCM_FAILURE(rv)) { 27064 LOG_ERROR(BSL_LS_BCM_OAM, 27065 (BSL_META_U(unit, 27066 "OAM(unit %d) Error: Port table update for " 27067 "section OAM(EP=%d) - %s.\n"), 27068 unit, endpoint_info->id, bcm_errmsg(rv))); 27069 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 27070 return (rv); 27071 } 27072 rv = _bcm_sb2_oam_port_table_key_update(unit, EGR_PORTm, hash_data); 27073 if (BCM_FAILURE(rv)) { 27074 LOG_ERROR(BSL_LS_BCM_OAM, 27075 (BSL_META_U(unit, 27076 "OAM(unit %d) Error: EGR Port table update for " 27077 "section OAM(EP=%d) - %s.\n"), 27078 unit, endpoint_info->id, bcm_errmsg(rv))); 27079 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 27080 return (rv); 27081 } 27082 }else { 27083 if (endpoint_info->type == bcmOAMEndpointTypeBHHMPLS) { 27084 /* For RX part enable BHH OAM for the label. */ 27085 27086 /* First check if the label is in l3 tunnel table and enable 27087 * BHH OAM if true. */ 27088 rv = _bcm_sb2_oam_mpls_lsp_check_l3_tunnel_table_downmep_enable(unit, 27089 hash_data, 1); 27090 if (rv == BCM_E_NOT_FOUND) { 27091 /* If not found in L3 tunnel, find and update it in MPLS_ENTRY 27092 * table */ 27093 rv = _bcm_sb2_oam_mpls_lsp_mpls_table_downmep_enable(unit, 27094 hash_data, 1); 27095 if (BCM_FAILURE(rv)) { 27096 LOG_ERROR(BSL_LS_BCM_OAM, 27097 (BSL_META_U(unit, 27098 "OAM(unit %d) Error: MPLS table " 27099 "update failed (EP=%d) - %s.\n"), 27100 unit, endpoint_info->id, 27101 bcm_errmsg(rv))); 27102 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, 27103 hash_data); 27104 return (rv); 27105 } 27106 } else if (rv != BCM_E_NONE) { 27107 LOG_ERROR(BSL_LS_BCM_OAM, 27108 (BSL_META_U(unit, 27109 "OAM(unit %d) Error: L3 tunnel table " 27110 "update failed (EP=%d) - %s.\n"), 27111 unit, endpoint_info->id, 27112 bcm_errmsg(rv))); 27113 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 27114 return (rv); 27115 } 27116 /* For TX part enable BHH OAM for the egress intf. 27117 * and write the mepid in egr_l3_next_hop table */ 27118 rv = _bcm_sb2_oam_mpls_lsp_egr_l3_nxt_hop_downmep_enable(unit, 27119 hash_data, 1); 27120 if (BCM_FAILURE(rv)) { 27121 LOG_ERROR(BSL_LS_BCM_OAM, 27122 (BSL_META_U(unit, 27123 "OAM(unit %d) Error: EGR_L3_NEXT_HOP " 27124 "table update failed (EP=%d) - %s.\n"), 27125 unit, endpoint_info->id, 27126 bcm_errmsg(rv))); 27127 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 27128 return (rv); 27129 } 27130 } else if (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv) { 27131 rv = _bcm_sb2_oam_mpls_lsp_mpls_table_downmep_enable(unit, 27132 hash_data, 1); 27133 if (BCM_FAILURE(rv)) { 27134 LOG_ERROR(BSL_LS_BCM_OAM, 27135 (BSL_META_U(unit, 27136 "OAM(unit %d) Error: MPLS LSP table update " 27137 "failed (EP=%d) - %s.\n"), 27138 unit, endpoint_info->id, 27139 bcm_errmsg(rv))); 27140 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 27141 return (rv); 27142 } 27143 /* For TX part enable BHH OAM for the egress dvp. 27144 */ 27145 rv = _bcm_sb2_oam_mpls_pw_egr_dvp_downmep_enable(unit, hash_data, 1); 27146 if (BCM_FAILURE(rv)) { 27147 LOG_ERROR(BSL_LS_BCM_OAM, 27148 (BSL_META_U(unit, 27149 "OAM(unit %d) Error: EGR_L3_NEXT_HOP " 27150 "table update failed (EP=%d) - %s.\n"), 27151 unit, endpoint_info->id, 27152 bcm_errmsg(rv))); 27153 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 27154 return (rv); 27155 } 27156 27157 } 27158 } 27159 encap = 1; 27160 27161 if (BCM_TRUNK_INVALID != trunk_id) { 27162 endpoint_info->gport = trunk_member.gport; 27163 hash_data->resolved_trunk_gport = trunk_member.gport; 27164 } 27165 /* Create or Update */ 27166 session_flags = (is_replace) ? 0 : SHR_BHH_SESS_SET_F_CREATE; 27167 27168 /* Set Endpoint config entry */ 27169 hash_data->bhh_endpoint_index = ep_req_index; 27170 27171 sal_memset(&counter_info, 0, sizeof(counter_info)); 27172 counter_info.counter_size = 27173 endpoint_info->ccm_tx_update_lm_counter_size; 27174 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 27175 { 27176 counter_info.counter_base_id[i] = 27177 endpoint_info->ccm_tx_update_lm_counter_base_id[i]; 27178 counter_info.counter_offset[i] = 27179 endpoint_info->ccm_tx_update_lm_counter_offset[i]; 27180 counter_info.counter_action[i] = bcmOamCounterActionIncrement; 27181 counter_info.byte_count_offset[i] = 0; 27182 } 27183 counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE; 27184 counter_info.oam_replacement_offset = SHR_BHH_LM_OFFSET_INSIDE_CCM_PDU; 27185 27186 if(!(endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) { 27187 27188 /* Get the Trunk, Port and Modid info for this Gport */ 27189 rv = _bcm_esw_gport_resolve(unit, 27190 endpoint_info->gport, &module_id, &port_id, &trunk_id, &local_id); 27191 27192 if (BCM_FAILURE(rv)) { 27193 LOG_ERROR(BSL_LS_BCM_OAM, 27194 (BSL_META_U(unit, 27195 "BHH(unit %d) Error: Gport resolve (EP=%d) - %s.\n"), 27196 unit, endpoint_info->id, bcm_errmsg(rv))); 27197 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 27198 return (rv); 27199 } 27200 /* Get local port used for TX BHH packet */ 27201 rv = _bcm_esw_modid_is_local(unit, module_id, &is_local); 27202 if(BCM_FAILURE(rv)) { 27203 LOG_ERROR(BSL_LS_BCM_OAM, 27204 (BSL_META_U(unit, 27205 "BHH(unit %d) Error: local port for " 27206 "BHH TX failed(ep=%d) - %s.\n"), 27207 unit, endpoint_info->id, bcm_errmsg(rv))); 27208 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 27209 return (rv); 27210 } 27211 27212 if (!is_local) { /* HG port */ 27213 rv = bcm_esw_stk_modport_get(unit, module_id, &port_id); 27214 if(BCM_FAILURE(rv)) { 27215 LOG_ERROR(BSL_LS_BCM_OAM, 27216 (BSL_META_U(unit, 27217 "BHH(unit %d) Error: HG port get failed " 27218 "(EP=%d) - %s.\n"), 27219 unit, endpoint_info->id, bcm_errmsg(rv))); 27220 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 27221 return (rv); 27222 } 27223 } 27224 /* Set control message data */ 27225 sal_memset(&msg_sess, 0, sizeof(msg_sess)); 27226 /* 27227 * Set the BHH encapsulation data 27228 * 27229 * The function _bcm_sb2_oam_bhh_encap_create() is called first 27230 * since this sets some fields in 'hash_data' which are 27231 * used in the message. 27232 */ 27233 if (encap) { 27234 rv = _bcm_sb2_oam_bhh_encap_create(unit, module_id, 27235 port_id, 27236 hash_data, 27237 msg_sess.encap_data, 27238 &msg_sess.encap_type, 27239 &encap_length, 27240 &counter_info, hash_data->int_pri, 27241 hash_data->egr_label_exp, 27242 hash_data->egr_label_ttl); 27243 27244 if(BCM_FAILURE(rv)) 27245 { 27246 LOG_ERROR(BSL_LS_BCM_OAM, 27247 (BSL_META_U(unit, 27248 "BHH(unit %d) Error: Encap create failed " 27249 "(EP=%d) - %s.\n"), 27250 unit, endpoint_info->id, bcm_errmsg(rv))); 27251 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 27252 return (rv); 27253 } 27254 } 27255 msg_sess.encap_length = encap_length; 27256 27257 /* 27258 * Endpoint can be one of: CCM, LB, LM or DM. The default is CCM, 27259 * all others modes must be specified via a config flag. 27260 */ 27261 if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOOPBACK) 27262 session_flags |= SHR_BHH_SESS_SET_F_LB; 27263 else if (endpoint_info->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) 27264 session_flags |= SHR_BHH_SESS_SET_F_DM; 27265 else if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) 27266 session_flags |= SHR_BHH_SESS_SET_F_LM; 27267 else 27268 session_flags |= SHR_BHH_SESS_SET_F_CCM; 27269 27270 if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) 27271 session_flags |= SHR_BHH_SESS_SET_F_MIP; 27272 27273 _bcm_sb2_oam_get_group_sw_rdi (unit, endpoint_info->group, 27274 &group_sw_rdi); 27275 if (group_sw_rdi) { 27276 session_flags |= SHR_BHH_SESS_SET_F_RDI; 27277 } 27278 /*if (!local_tx_enabled) 27279 session_flags |= SHR_BHH_SESS_SET_F_PASSIVE;*/ 27280 27281 msg_sess.sess_id = bhh_pool_ep_idx; 27282 msg_sess.flags = session_flags; 27283 27284 msg_sess.mel = hash_data->level; 27285 msg_sess.mep_id = hash_data->name; 27286 sal_memcpy(msg_sess.meg_id, group_p->name, BCM_OAM_GROUP_NAME_LENGTH); 27287 27288 msg_sess.period = _sb2_ccm_intervals[ 27289 _bcm_sb2_oam_ccm_msecs_to_hw_encode(endpoint_info->ccm_period)]; 27290 27291 msg_sess.if_num = endpoint_info->intf_id; 27292 msg_sess.tx_port = port_id; 27293 msg_sess.tx_cos = endpoint_info->int_pri; 27294 msg_sess.tx_pri = endpoint_info->pkt_pri; 27295 msg_sess.tx_qnum = SOC_INFO(unit).port_uc_cosq_base[port_id] + endpoint_info->int_pri; 27296 msg_sess.lm_counter_index = hash_data->tx_ctr; 27297 27298 msg_sess.mpls_label = endpoint_info->mpls_label; 27299 27300 switch (endpoint_info->type) { 27301 case bcmOAMEndpointTypeBHHMPLS: 27302 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_LSP; 27303 msg_sess.priority = endpoint_info->mpls_exp; 27304 break; 27305 27306 case bcmOAMEndpointTypeBHHMPLSVccv: 27307 switch(endpoint_info->vccv_type) { 27308 27309 case bcmOamBhhVccvChannelAch: 27310 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_1; 27311 msg_sess.priority = endpoint_info->mpls_exp; 27312 break; 27313 27314 case bcmOamBhhVccvRouterAlert: 27315 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_2; 27316 msg_sess.priority = endpoint_info->mpls_exp; 27317 break; 27318 27319 case bcmOamBhhVccvTtl: 27320 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_3; 27321 msg_sess.priority = endpoint_info->mpls_exp; 27322 break; 27323 27324 case bcmOamBhhVccvGal13: 27325 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_4; 27326 msg_sess.priority = endpoint_info->mpls_exp; 27327 break; 27328 27329 default: 27330 return BCM_E_PARAM; 27331 break; 27332 } 27333 break; 27334 27335 case bcmOAMEndpointTypeBhhSection: 27336 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION; 27337 msg_sess.priority = 0; 27338 break; 27339 case bcmOAMEndpointTypeBhhSectionInnervlan: 27340 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_INNERVLAN; 27341 msg_sess.priority = endpoint_info->inner_pkt_pri; 27342 break; 27343 case bcmOAMEndpointTypeBhhSectionOuterVlan: 27344 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTERVLAN; 27345 msg_sess.priority = endpoint_info->pkt_pri; 27346 break; 27347 case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan: 27348 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTER_PLUS_INNERVLAN; 27349 msg_sess.priority = endpoint_info->pkt_pri; 27350 break; 27351 27352 default: 27353 return BCM_E_PARAM; 27354 } 27355 27356 /* Pack control message data into DMA buffer */ 27357 buffer = oc->dma_buffer; 27358 buffer_ptr = bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess); 27359 buffer_len = buffer_ptr - buffer; 27360 27361 /* Send BHH Session Update message to uC */ 27362 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 27363 MOS_MSG_SUBCLASS_BHH_SESS_SET, 27364 buffer_len, 0, 27365 MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY, 27366 &reply_len); 27367 if (BCM_FAILURE(rv) || (reply_len != 0)) { 27368 LOG_ERROR(BSL_LS_BCM_OAM, 27369 (BSL_META_U(unit, 27370 "BHH(unit %d) Error: Session SET failed " 27371 "(EP=%d) - %s.\n"), 27372 unit, endpoint_info->id, bcm_errmsg(rv))); 27373 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 27374 return (rv); 27375 } 27376 } 27377 27378 if (!is_replace) { 27379 rv = _bcm_sb2_oam_group_ep_list_add(unit, endpoint_info->group, 27380 endpoint_info->id); 27381 } 27382 if (BCM_FAILURE(rv)) { 27383 LOG_ERROR(BSL_LS_BCM_OAM, 27384 (BSL_META_U(unit, 27385 "OAM(unit %d) Error: Tx config failed for EP=%d %s.\n"), 27386 unit, endpoint_info->id, bcm_errmsg(rv))); 27387 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 27388 return (rv); 27389 } 27390 rv = _bcm_sb2_oam_ma_idx_to_ep_id_mapping_add(unit, hash_data); 27391 if (BCM_FAILURE(rv)) { 27392 LOG_ERROR(BSL_LS_BCM_OAM, 27393 (BSL_META_U(unit, 27394 "OAM(unit %d) Error: Add mapping from ma_idx_to_ep_id list (EP=%d) -" 27395 " %s.\n"), unit, hash_data->ep_id, bcm_errmsg(rv))); 27396 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 27397 return (rv); 27398 } 27399 27400 /* hash collision */ 27401 rv = shr_htb_insert(oc->ma_mep_htbl, hash_key, hash_data); 27402 if (BCM_FAILURE(rv)) { 27403 LOG_ERROR(BSL_LS_BCM_OAM, 27404 (BSL_META_U(unit, 27405 "OAM(unit %d) Error: Hash table insert failed EP=%d %s.\n"), 27406 unit, endpoint_info->id, bcm_errmsg(rv))); 27407 _bcm_sb2_oam_endpoint_cleanup(unit, 0, *hash_key, hash_data); 27408 return (rv); 27409 } 27410 } 27411 hash_data->in_use = 1; 27412 27413 #ifdef BCM_WARM_BOOT_SUPPORT 27414 SOC_CONTROL_LOCK(unit); 27415 SOC_CONTROL(unit)->scache_dirty = 1; 27416 SOC_CONTROL_UNLOCK(unit); 27417 #endif 27418 27419 return (rv); 27420 } 27421 27422 /* 27423 * Function: 27424 * _bcm_sb2_oam_bhh_hw_init 27425 * Purpose: 27426 * Initialize the HW for BHH packet processing. 27427 * Configure: 27428 * - Copy to CPU BHH error packets 27429 * - CPU COS Queue for BHH packets 27430 * - RX DMA channel 27431 * Parameters: 27432 * unit - (IN) Unit number. 27433 * Returns: 27434 * BCM_E_XXX 27435 * Notes: 27436 */ 27437 STATIC int 27438 _bcm_sb2_oam_bhh_hw_init(int unit) 27439 { 27440 int rv = BCM_E_NONE; 27441 _bcm_oam_control_t *oc; /* OAM control structure. */ 27442 uint32 val=0; 27443 int index; 27444 int ach_error_index; 27445 int bhh_lb_index; 27446 int invalid_error_index; 27447 int cosq_map_size; 27448 bcm_rx_reasons_t reasons, reasons_mask; 27449 uint8 int_prio, int_prio_mask; 27450 uint32 packet_type, packet_type_mask; 27451 bcm_cos_queue_t cosq; 27452 bcm_rx_chan_t chan_id; 27453 int num_cosq = 0; 27454 int min_cosq, max_cosq; 27455 int i; 27456 27457 /* Get OAM Control Structure. */ 27458 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 27459 27460 _BCM_OAM_LOCK(oc); 27461 27462 /* 27463 * Send BHH lookup failure packet to CPU 27464 * Configure CPU_CONTROL_M register 27465 * Field BHH_SESSION_NOT_FOUND_TO_CPU 27466 */ 27467 rv = READ_CPU_CONTROL_Mr(unit, &val); 27468 if(BCM_FAILURE(rv)) { 27469 LOG_ERROR(BSL_LS_BCM_OAM, 27470 (BSL_META_U(unit, 27471 "BHH(unit %d) Error:hw init. Read CPU Control Reg %s.\n"), 27472 unit, bcm_errmsg(rv))); 27473 _BCM_OAM_UNLOCK(oc); 27474 return (rv); 27475 } 27476 27477 /* Steer lookup failure packet to CPU */ 27478 soc_reg_field_set(unit, CPU_CONTROL_Mr, &val, 27479 MPLS_CTRL_PACKET_SESSION_NOT_FOUND_TO_CPUf, 1); 27480 27481 rv = WRITE_CPU_CONTROL_Mr(unit, val); 27482 if(BCM_FAILURE(rv)) { 27483 LOG_ERROR(BSL_LS_BCM_OAM, 27484 (BSL_META_U(unit, 27485 "BHH(unit %d) Error:hw init. Write CPU_CONTROL_M Reg %s.\n"), 27486 unit, bcm_errmsg(rv))); 27487 _BCM_OAM_UNLOCK(oc); 27488 return (rv); 27489 } 27490 27491 if(oc->ukernel_not_ready == 0){ 27492 /* 27493 * Get COSQ for BHH 27494 */ 27495 min_cosq = 0; 27496 for (i = 0; i < SOC_CMCS_NUM(unit); i++) { 27497 num_cosq = NUM_CPU_ARM_COSQ(unit, i); 27498 if (i == oc->uc_num + 1) { 27499 break; 27500 } 27501 min_cosq += num_cosq; 27502 } 27503 max_cosq = min_cosq + num_cosq - 1; 27504 27505 if(max_cosq < min_cosq) { 27506 LOG_ERROR(BSL_LS_BCM_OAM, 27507 (BSL_META_U(unit, 27508 "BHH(unit %d) Error: " 27509 "No BHH COS Queue available from uC%d - %s\n"), 27510 unit, oc->uc_num, bcm_errmsg(BCM_E_CONFIG))); 27511 _BCM_OAM_UNLOCK(oc); 27512 return (BCM_E_CONFIG); 27513 } 27514 27515 /* check user configured COSq */ 27516 if (oc->cpu_cosq != BHH_COSQ_INVALID) { 27517 if ((oc->cpu_cosq < min_cosq) || 27518 (oc->cpu_cosq > max_cosq)) { 27519 _BCM_OAM_UNLOCK(oc); 27520 return (BCM_E_CONFIG); 27521 } 27522 min_cosq = max_cosq = oc->cpu_cosq; 27523 } 27524 27525 /* 27526 * Assign RX DMA channel to CPU COS Queue 27527 * (This is the RX channel to listen on for BHH packets). 27528 * 27529 * DMA channels (12) are assigned 4 per processor: 27530 * (see /src/bcm/common/rx.c) 27531 * channels 0..3 --> PCI host 27532 * channels 4..7 --> uController 0 27533 * chnanels 8..11 --> uController 1 27534 * 27535 * The uControllers designate the 4 local DMA channels as follows: 27536 * local channel 0 --> TX 27537 * local channel 1..3 --> RX 27538 * 27539 * Each uController application needs to use a different 27540 * RX DMA channel to listen on. 27541 */ 27542 chan_id = (BCM_RX_CHANNELS * (SOC_ARM_CMC(unit, oc->uc_num))) + 27543 oc->rx_channel; 27544 27545 for (i = max_cosq; i >= min_cosq; i--) { 27546 rv = _bcm_common_rx_queue_channel_set(unit, i, chan_id); 27547 if(BCM_SUCCESS(rv)) { 27548 oc->cpu_cosq = i; 27549 break; 27550 } 27551 } 27552 27553 if (i < min_cosq) { 27554 rv = BCM_E_RESOURCE; 27555 LOG_ERROR(BSL_LS_BCM_OAM, 27556 (BSL_META_U(unit, 27557 "BHH(unit %d) Error: hw init." 27558 " queue channel set %s.\n"), 27559 unit, bcm_errmsg(rv))); 27560 _BCM_OAM_UNLOCK(oc); 27561 return (rv); 27562 } 27563 27564 /* 27565 * Direct BHH packets to designated CPU COS Queue...or more accurately 27566 * BFD error packets. 27567 * 27568 * Reasons: 27569 * - bcmRxReasonBFD: BFD error 27570 * - bcmRxReasonBfdUnknownVersion: BFD Unknown ACH 27571 * NOTE: 27572 * The user input 'cpu_qid' (bcm_BHH_endpoint_t) could be 27573 * used to select different CPU COS queue. Currently, 27574 * all priorities are mapped into the same CPU COS Queue. 27575 */ 27576 27577 /* Find available entries in CPU COS queue map table */ 27578 ach_error_index = -1; /* COSQ map index for error packets */ 27579 invalid_error_index = -1; /* COSQ map index for error packets */ 27580 bhh_lb_index = -1; /* COSQ map index for LB packets */ 27581 rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size); 27582 if(BCM_FAILURE(rv)) { 27583 LOG_ERROR(BSL_LS_BCM_OAM, 27584 (BSL_META_U(unit, 27585 "BHH(unit %d) Error:hw init. cosq maps size %s.\n"), 27586 unit, bcm_errmsg(rv))); 27587 _BCM_OAM_UNLOCK(oc); 27588 return (rv); 27589 } 27590 27591 for (index = 0; index < cosq_map_size; index++) { 27592 rv = bcm_esw_rx_cosq_mapping_get(unit, index, 27593 &reasons, &reasons_mask, 27594 &int_prio, &int_prio_mask, 27595 &packet_type, &packet_type_mask, 27596 &cosq); 27597 if (rv == BCM_E_NOT_FOUND) { 27598 /* Assign first available index */ 27599 rv = BCM_E_NONE; 27600 if (ach_error_index == -1) { 27601 ach_error_index = index; 27602 } else if (invalid_error_index == -1) { 27603 invalid_error_index = index; 27604 } else if (bhh_lb_index == -1) { 27605 bhh_lb_index = index; 27606 break; 27607 } 27608 } 27609 if (BCM_FAILURE(rv)) { 27610 LOG_ERROR(BSL_LS_BCM_OAM, 27611 (BSL_META_U(unit, 27612 "BHH(unit %d) Error:hw init. cosq maps get %s.\n"), 27613 unit, bcm_errmsg(rv))); 27614 _BCM_OAM_UNLOCK(oc); 27615 return (rv); 27616 } 27617 } 27618 27619 if (ach_error_index == -1 || invalid_error_index == -1) { 27620 LOG_ERROR(BSL_LS_BCM_OAM, 27621 (BSL_META_U(unit, 27622 "BHH(unit %d) Error:hw init. ACH error %s.\n"), 27623 unit, bcm_errmsg(rv))); 27624 _BCM_OAM_UNLOCK(oc); 27625 return (BCM_E_FULL); 27626 } 27627 27628 /* Set CPU COS Queue mapping */ 27629 BCM_RX_REASON_CLEAR_ALL(reasons); 27630 BCM_RX_REASON_SET(reasons, bcmRxReasonBHHOAM); /* BHH Packet */ 27631 BCM_RX_REASON_SET(reasons, bcmRxReasonOAMCCMSlowpath); /*OAM Slowpath CCM*/ 27632 27633 rv = bcm_esw_rx_cosq_mapping_set(unit, ach_error_index, 27634 reasons, reasons, 27635 0, 0, /* Any Internal Prio */ 27636 0, 0, /* Any packet type */ 27637 oc->cpu_cosq); 27638 if(BCM_FAILURE(rv)) { 27639 LOG_ERROR(BSL_LS_BCM_OAM, 27640 (BSL_META_U(unit, 27641 "BHH(unit %d) Error:hw init. cosq map set %s.\n"), 27642 unit, bcm_errmsg(rv))); 27643 _BCM_OAM_UNLOCK(oc); 27644 return (rv); 27645 } 27646 oc->cpu_cosq_ach_error_index = ach_error_index; 27647 27648 BCM_RX_REASON_CLEAR_ALL(reasons); 27649 BCM_RX_REASON_SET(reasons, bcmRxReasonBHHOAM); /* BHH Packet */ 27650 BCM_RX_REASON_SET(reasons, bcmRxReasonOAMSlowpath); /*OAM Slowpath CCM*/ 27651 27652 rv = bcm_esw_rx_cosq_mapping_set(unit, bhh_lb_index, 27653 reasons, reasons, 27654 0, 0, /* Any Internal Prio */ 27655 0, 0, /* Any packet type */ 27656 oc->cpu_cosq); 27657 if(BCM_FAILURE(rv)) { 27658 LOG_ERROR(BSL_LS_BCM_OAM, 27659 (BSL_META_U(unit, 27660 "BHH(unit %d) Error:hw init. cosq map set for" 27661 " Loopback %s.\n"), 27662 unit, bcm_errmsg(rv))); 27663 _BCM_OAM_UNLOCK(oc); 27664 return (rv); 27665 } 27666 oc->bhh_lb_index = bhh_lb_index; 27667 27668 BCM_RX_REASON_CLEAR_ALL(reasons); 27669 BCM_RX_REASON_SET(reasons, bcmRxReasonBHHOAM); /* BHH Packet */ 27670 BCM_RX_REASON_SET(reasons, bcmRxReasonOAMLMDM); /*OAM Slowpath(LB/LBR)*/ 27671 27672 rv = bcm_esw_rx_cosq_mapping_set(unit, invalid_error_index, 27673 reasons, reasons, 27674 0, 0, /* Any Internal Prio */ 27675 0, 0, /* Any packet type */ 27676 oc->cpu_cosq); 27677 if(BCM_FAILURE(rv)) { 27678 LOG_ERROR(BSL_LS_BCM_OAM, 27679 (BSL_META_U(unit, 27680 "BHH(unit %d) Error:hw init. cosq map set %s.\n"), 27681 unit, bcm_errmsg(rv))); 27682 _BCM_OAM_UNLOCK(oc); 27683 return (rv); 27684 } 27685 oc->cpu_cosq_invalid_error_index = invalid_error_index; 27686 } 27687 27688 _BCM_OAM_UNLOCK(oc); 27689 return (rv); 27690 } 27691 #endif /*(INCLUDE_BHH) */ 27692 27693 #if defined(INCLUDE_ETH_LM_DM) 27694 /* 27695 * Function: 27696 * _bcm_sb2_oam_eth_lm_dm_hw_init 27697 * Purpose: 27698 * Initialize the HW for ETH_LM_DM packet processing. 27699 * Configure: 27700 * - Copy to CPU ETH_LM_DM error packets 27701 * - CPU COS Queue for ETH_LM_DM packets 27702 * - RX DMA channel 27703 * Parameters: 27704 * unit - (IN) Unit number. 27705 * Returns: 27706 * BCM_E_XXX 27707 * Notes: 27708 */ 27709 STATIC int 27710 _bcm_sb2_oam_eth_lm_dm_hw_init(int unit) 27711 { 27712 int rv = BCM_E_NONE; 27713 _bcm_oam_control_t *oc; /* OAM control structure. */ 27714 int index; 27715 int eth_lm_dm_index; 27716 int cosq_map_size; 27717 bcm_rx_reasons_t reasons, reasons_mask; 27718 uint8 int_prio, int_prio_mask; 27719 uint32 packet_type, packet_type_mask; 27720 bcm_cos_queue_t cosq; 27721 int eth_lm_dm_cosq; 27722 /* Get OAM Control Structure. */ 27723 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 27724 27725 if(!oc->eth_lm_dm_ukernel_not_ready) { 27726 27727 _BCM_OAM_LOCK(oc); 27728 27729 eth_lm_dm_cosq = oc->eth_lm_dm_cpu_cosq; 27730 /* 27731 * Assign RX DMA channel to CPU COS Queue 27732 * (This is the RX channel to listen on for ETH_LM_DM packets). 27733 * 27734 * DMA channels (12) are assigned 4 per processor: 27735 * (see /src/bcm/common/rx.c) 27736 * channels 0..3 --> PCI host 27737 * channels 4..7 --> uController 0 27738 * chnanels 8..11 --> uController 1 27739 * 27740 * The uControllers designate the 4 local DMA channels as follows: 27741 * local channel 0 --> TX 27742 * local channel 1..3 --> RX 27743 * 27744 * Each uController application needs to use a different 27745 * RX DMA channel to listen on. 27746 */ 27747 27748 rv = _bcm_common_rx_queue_channel_set(unit, 27749 eth_lm_dm_cosq, 27750 oc->eth_lm_dm_rx_channel); 27751 if(!BCM_SUCCESS(rv)) { 27752 LOG_ERROR(BSL_LS_BCM_OAM, 27753 (BSL_META_U(unit, 27754 "ETH_LM_DM(unit %d) Error: hw init." 27755 " queue channel set %s.\n"), 27756 unit, bcm_errmsg(rv))); 27757 _BCM_OAM_UNLOCK(oc); 27758 return (rv); 27759 27760 } 27761 27762 /* 27763 * Direct ETH_LM_DM packets to designated CPU COS Queue. 27764 * 27765 * Reasons: 27766 * - bcmRxReasonOAMLMDM: ETH_LM_DM packet breason code 27767 */ 27768 27769 /* Find available entries in CPU COS queue map table */ 27770 eth_lm_dm_index = -1; /* COSQ map index for error packets */ 27771 rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size); 27772 if(BCM_FAILURE(rv)) { 27773 LOG_ERROR(BSL_LS_BCM_OAM, 27774 (BSL_META_U(unit, 27775 "ETH_LM_DM(unit %d) Error:hw init. cosq maps size %s.\n"), 27776 unit, bcm_errmsg(rv))); 27777 _BCM_OAM_UNLOCK(oc); 27778 return (rv); 27779 } 27780 27781 for (index = 0; index < cosq_map_size; index++) { 27782 rv = bcm_esw_rx_cosq_mapping_get(unit, index, 27783 &reasons, &reasons_mask, 27784 &int_prio, &int_prio_mask, 27785 &packet_type, &packet_type_mask, 27786 &cosq); 27787 if (rv == BCM_E_NOT_FOUND) { 27788 /* Assign first available index */ 27789 rv = BCM_E_NONE; 27790 if (eth_lm_dm_index == -1) { 27791 eth_lm_dm_index = index; 27792 break; 27793 } 27794 } 27795 if (BCM_FAILURE(rv)) { 27796 LOG_ERROR(BSL_LS_BCM_OAM, 27797 (BSL_META_U(unit, 27798 "ETH_LM_DM(unit %d) Error:hw init. cosq maps get %s.\n"), 27799 unit, bcm_errmsg(rv))); 27800 _BCM_OAM_UNLOCK(oc); 27801 return (rv); 27802 } 27803 } 27804 27805 if (eth_lm_dm_index == -1) { 27806 LOG_ERROR(BSL_LS_BCM_OAM, 27807 (BSL_META_U(unit, 27808 "ETH_LM_DM(unit %d) Error:hw init. map_index error %s.\n"), 27809 unit, bcm_errmsg(rv))); 27810 _BCM_OAM_UNLOCK(oc); 27811 return (BCM_E_FULL); 27812 } 27813 27814 BCM_RX_REASON_CLEAR_ALL(reasons); 27815 BCM_RX_REASON_SET(reasons, bcmRxReasonOAMLMDM); /*OAM LM/DM*/ 27816 27817 rv = bcm_esw_rx_cosq_mapping_set(unit, eth_lm_dm_index, 27818 reasons, reasons, 27819 0, 0, /* Any Internal Prio */ 27820 0, 0, /* Any packet type */ 27821 oc->eth_lm_dm_cpu_cosq); 27822 if(BCM_FAILURE(rv)) { 27823 LOG_ERROR(BSL_LS_BCM_OAM, 27824 (BSL_META_U(unit, 27825 "ETH_LM_DM(unit %d) Error:hw init. cosq map set %s.\n"), 27826 unit, bcm_errmsg(rv))); 27827 _BCM_OAM_UNLOCK(oc); 27828 return (rv); 27829 } 27830 oc->eth_lm_dm_cosq_index = eth_lm_dm_index; 27831 27832 /* For sending the LM/DM packet to cos-mapping of BTE running ETH LM/DM for UP-MEP*/ 27833 rv = soc_reg_field32_modify(unit, EGR_CPU_CONTROL_2_64r, REG_PORT_ANY, 27834 OAM_LMDM_CPU_COSf, oc->eth_lm_dm_cpu_cosq); 27835 if (SOC_FAILURE(rv)) { 27836 _BCM_OAM_UNLOCK(oc); 27837 return rv; 27838 } 27839 27840 27841 _BCM_OAM_UNLOCK(oc); 27842 } 27843 return (rv); 27844 } 27845 27846 27847 STATIC int 27848 _bcm_sb2_eth_lm_dm_loss_delete (int unit, 27849 _bcm_oam_control_t *oc, 27850 _bcm_oam_hash_data_t *h_data_p) 27851 { 27852 int rv = BCM_E_NONE; 27853 uint8 *buffer, *buffer_ptr; 27854 uint16 buffer_len, reply_len; 27855 int sess_id = 0; 27856 27857 shr_eth_lm_dm_msg_ctrl_loss_delete_t msg; 27858 27859 sess_id = h_data_p->lm_dm_uc_session_id; 27860 27861 /* Validate session id. */ 27862 rv = shr_idxres_list_elem_state(oc->eth_lm_dm_pool, sess_id); 27863 if ((BCM_E_EXISTS != rv)) { 27864 /* Invalid session id */ 27865 LOG_ERROR(BSL_LS_BCM_OAM, 27866 (BSL_META_U(unit, 27867 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 27868 unit, h_data_p->ep_id, bcm_errmsg(rv))); 27869 return (rv); 27870 } 27871 27872 if (oc->eth_lm_dm_ukernel_not_ready == 1) { 27873 rv = BCM_E_INIT; 27874 return rv; 27875 27876 } 27877 27878 msg.sess_id = sess_id; 27879 27880 /* Pack control message data into DMA buffer */ 27881 buffer = oc->eth_lm_dm_dma_buffer; 27882 buffer_ptr = shr_eth_lm_dm_msg_ctrl_loss_delete_pack(buffer, &msg); 27883 buffer_len = buffer_ptr - buffer; 27884 27885 /* Send ETH LM/DM loss delete message to uC */ 27886 rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit, 27887 MOS_MSG_SUBCLASS_ETH_LM_DM_LOSS_MEASUREMENT_DELETE, 27888 buffer_len, 0, 27889 MOS_MSG_SUBCLASS_ETH_LM_DM_LOSS_MEASUREMENT_DELETE_REPLY, 27890 &reply_len); 27891 27892 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 27893 rv = BCM_E_INTERNAL; 27894 } 27895 27896 /* Delete DM instance from internal flags*/ 27897 h_data_p->lm_dm_int_flag &= ~_ETH_LM_DM_F_LM_IS_SET; 27898 27899 /* If DM is also not running then delete session from BTE */ 27900 if(!(h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_DM_IS_SET)) { 27901 27902 rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit, 27903 MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_DELETE, 27904 sess_id, 0, 27905 MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_DELETE_REPLY, 27906 &reply_len); 27907 27908 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 27909 rv = BCM_E_INTERNAL; 27910 } 27911 shr_idxres_list_free(oc->eth_lm_dm_pool, 27912 (shr_idxres_element_t)h_data_p->lm_dm_uc_session_id); 27913 27914 oc->eth_lm_dm_sess_id_ep_id[h_data_p->lm_dm_uc_session_id] = 0; 27915 h_data_p->lm_dm_uc_session_id = 0; 27916 h_data_p->lm_dm_int_flag = 0; 27917 27918 } 27919 27920 return rv; 27921 } 27922 27923 STATIC int 27924 _bcm_sb2_eth_lm_dm_delay_delete (int unit, 27925 _bcm_oam_control_t *oc, 27926 _bcm_oam_hash_data_t *h_data_p) 27927 { 27928 int rv = BCM_E_NONE; 27929 uint8 *buffer, *buffer_ptr; 27930 uint16 buffer_len, reply_len; 27931 int sess_id = 0; 27932 27933 shr_eth_lm_dm_msg_ctrl_delay_delete_t msg; 27934 27935 sess_id = h_data_p->lm_dm_uc_session_id; 27936 27937 /* Validate session id. */ 27938 rv = shr_idxres_list_elem_state(oc->eth_lm_dm_pool, sess_id); 27939 if ((BCM_E_EXISTS != rv)) { 27940 /* Invalid session id */ 27941 LOG_ERROR(BSL_LS_BCM_OAM, 27942 (BSL_META_U(unit, 27943 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 27944 unit, h_data_p->ep_id, bcm_errmsg(rv))); 27945 return (rv); 27946 } 27947 27948 if (oc->eth_lm_dm_ukernel_not_ready == 1) { 27949 rv = BCM_E_INIT; 27950 return rv; 27951 } 27952 27953 27954 msg.sess_id = sess_id; 27955 27956 /* Pack control message data into DMA buffer */ 27957 buffer = oc->eth_lm_dm_dma_buffer; 27958 buffer_ptr = shr_eth_lm_dm_msg_ctrl_delay_delete_pack(buffer, &msg); 27959 buffer_len = buffer_ptr - buffer; 27960 27961 /* Send ETH LM/DM delay delete message to uC */ 27962 rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit, 27963 MOS_MSG_SUBCLASS_ETH_LM_DM_DELAY_MEASUREMENT_DELETE, 27964 buffer_len, 0, 27965 MOS_MSG_SUBCLASS_ETH_LM_DM_DELAY_MEASUREMENT_DELETE_REPLY, 27966 &reply_len); 27967 27968 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 27969 rv = BCM_E_INTERNAL; 27970 return rv; 27971 } 27972 27973 /* Delete DM instance from internal flags*/ 27974 h_data_p->lm_dm_int_flag &= ~_ETH_LM_DM_F_DM_IS_SET; 27975 27976 /* If LM is also not running then delete session from BTE */ 27977 if(!(h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_LM_IS_SET)) { 27978 27979 rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit, 27980 MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_DELETE, 27981 sess_id, 0, 27982 MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_DELETE_REPLY, 27983 &reply_len); 27984 27985 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 27986 rv = BCM_E_INTERNAL; 27987 return rv; 27988 } 27989 27990 shr_idxres_list_free(oc->eth_lm_dm_pool, 27991 (shr_idxres_element_t)h_data_p->lm_dm_uc_session_id); 27992 27993 oc->eth_lm_dm_sess_id_ep_id[h_data_p->lm_dm_uc_session_id] = 0; 27994 h_data_p->lm_dm_uc_session_id = 0; 27995 h_data_p->lm_dm_int_flag = 0; 27996 } 27997 27998 return rv; 27999 } 28000 #endif /*(INCLUDE_ETH_LM_DM) */ 28001 28002 #if defined(INCLUDE_MPLS_LM_DM) 28003 /* 28004 * Function: 28005 * _bcm_sb2_oam_mpls_lm_dm_hw_init 28006 * Purpose: 28007 * Initialize the HW for MPLS_LM_DM packet processing. 28008 * Configure: 28009 * - Copy to CPU MPLS_LM_DM error packets 28010 * - CPU COS Queue for MPLS_LM_DM packets 28011 * - RX DMA channel 28012 * Parameters: 28013 * unit - (IN) Unit number. 28014 * Returns: 28015 * BCM_E_XXX 28016 * Notes: 28017 */ 28018 STATIC int 28019 _bcm_sb2_oam_mpls_lm_dm_hw_init(int unit) 28020 { 28021 int rv = BCM_E_NONE; 28022 _bcm_oam_control_t *oc; /* OAM control structure. */ 28023 int index; 28024 int mpls_lm_dm_index; 28025 int cosq_map_size; 28026 bcm_rx_reasons_t reasons, reasons_mask; 28027 uint8 int_prio, int_prio_mask; 28028 uint32 packet_type, packet_type_mask; 28029 bcm_cos_queue_t cosq; 28030 bcm_rx_chan_t chan_id; 28031 /* Get OAM Control Structure. */ 28032 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 28033 28034 _BCM_OAM_LOCK(oc); 28035 chan_id = oc->mpls_lm_dm_rx_channel; 28036 cosq = MPLS_LM_DM_CPU_COS; 28037 rv = _bcm_common_rx_queue_channel_set(unit, cosq, chan_id); 28038 if (BCM_FAILURE(rv)) { 28039 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM" 28040 " Error: cos to channel map set failed %s.\n"), bcm_errmsg(rv))); 28041 _BCM_OAM_UNLOCK(oc); 28042 return (rv); 28043 } 28044 oc->mpls_lm_dm_cpu_cosq = cosq; 28045 28046 /* 28047 * Direct MPLS_LM_DM packets to designated CPU COS Queue. 28048 * 28049 * Reasons: 28050 * - bcmRxReasonOAMLMDM: MPLS_LM_DM packet breason code 28051 */ 28052 28053 /* Find available entries in CPU COS queue map table */ 28054 mpls_lm_dm_index = -1; /* COSQ map index for error packets */ 28055 rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size); 28056 if(BCM_FAILURE(rv)) { 28057 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)" 28058 " Error:hw init. cos map size get %s.\n"), unit, bcm_errmsg(rv))); 28059 _BCM_OAM_UNLOCK(oc); 28060 return (rv); 28061 } 28062 28063 for (index = 0; index < cosq_map_size; index++) { 28064 rv = bcm_esw_rx_cosq_mapping_get(unit, index, &reasons, 28065 &reasons_mask, &int_prio, &int_prio_mask, &packet_type, 28066 &packet_type_mask, &cosq); 28067 28068 if (rv == BCM_E_NOT_FOUND) { 28069 /* Assign first available index */ 28070 rv = BCM_E_NONE; 28071 if (mpls_lm_dm_index == -1) { 28072 mpls_lm_dm_index = index; 28073 break; 28074 } 28075 } 28076 if (BCM_FAILURE(rv)) { 28077 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)" 28078 " Error:hw init. cosq map get %s.\n"), unit, bcm_errmsg(rv))); 28079 _BCM_OAM_UNLOCK(oc); 28080 return (rv); 28081 } 28082 } 28083 28084 if (mpls_lm_dm_index == -1) { 28085 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)" 28086 " Error:hw init. map_index error %s.\n"), unit, bcm_errmsg(rv))); 28087 _BCM_OAM_UNLOCK(oc); 28088 return (BCM_E_FULL); 28089 } 28090 28091 BCM_RX_REASON_CLEAR_ALL(reasons); 28092 BCM_RX_REASON_SET(reasons, bcmRxReasonOAMMplsLmDm); /* MPLS_LM_DM */ 28093 28094 rv = bcm_esw_rx_cosq_mapping_set(unit, mpls_lm_dm_index, 28095 reasons, reasons, 28096 0, 0, /* Any Internal Prio */ 28097 0, 0, /* Any packet type */ 28098 oc->mpls_lm_dm_cpu_cosq); 28099 if(BCM_FAILURE(rv)) { 28100 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)" 28101 " Error:hw init. cosq map set %s.\n"), unit, bcm_errmsg(rv))); 28102 _BCM_OAM_UNLOCK(oc); 28103 return (rv); 28104 } 28105 oc->mpls_lm_dm_cosq_index = mpls_lm_dm_index; 28106 28107 _BCM_OAM_UNLOCK(oc); 28108 return (rv); 28109 } 28110 28111 #if defined(BCM_METROLITE_SUPPORT) 28112 /* 28113 * Function: 28114 * _bcm_ml_oam_mpls_lm_dm_hw_init 28115 * Purpose: 28116 * Initialize the HW for MPLS_LM_DM packet processing. 28117 * Configure: 28118 * - Copy to CPU MPLS_LM_DM error packets 28119 * - CPU COS Queue for MPLS_LM_DM packets 28120 * - RX DMA channel 28121 * Parameters: 28122 * unit - (IN) Unit number. 28123 * Returns: 28124 * BCM_E_XXX 28125 * Notes: 28126 */ 28127 STATIC int 28128 _bcm_ml_oam_mpls_lm_dm_hw_init(int unit) 28129 { 28130 int rv = BCM_E_NONE; 28131 _bcm_oam_control_t *oc; /* OAM control structure. */ 28132 int index; 28133 int mpls_lm_dm_index; 28134 int cosq_map_size; 28135 bcm_rx_reasons_t reasons, reasons_mask; 28136 uint8 int_prio, int_prio_mask; 28137 uint32 packet_type, packet_type_mask; 28138 bcm_cos_queue_t cosq; 28139 bcm_rx_chan_t chan_id; 28140 int i, min_cosq, max_cosq, num_cosq = 0; 28141 /* Get OAM Control Structure. */ 28142 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 28143 28144 _BCM_OAM_LOCK(oc); 28145 28146 /* Get valid range of COS queues for uC where BFD is loaded */ 28147 min_cosq = 0; 28148 for (i = 0; i < SOC_CMCS_NUM(unit); i++) { 28149 num_cosq = NUM_CPU_ARM_COSQ(unit, i); 28150 if (i == oc->mpls_lm_dm_uc_num + 1) { 28151 break; 28152 } 28153 min_cosq += num_cosq; 28154 } 28155 max_cosq = min_cosq + num_cosq - 1; 28156 28157 /* Check that there is at least one COS queue assigned to the CMC */ 28158 if (max_cosq < min_cosq) { 28159 LOG_ERROR(BSL_LS_BCM_COMMON, 28160 (BSL_META_U(unit, 28161 "ERROR: No MPLS LM/DM COS Queue available from uC%d\n"), 28162 oc->mpls_lm_dm_uc_num)); 28163 _BCM_OAM_UNLOCK(oc); 28164 return BCM_E_CONFIG; 28165 } 28166 28167 chan_id = (BCM_RX_CHANNELS * (SOC_ARM_CMC(unit, oc->mpls_lm_dm_uc_num))) + 28168 MPLS_LM_DM_RX_CHANNEL_UC_VIEW; 28169 28170 for (i = max_cosq; i >= min_cosq; i--) { 28171 rv = _bcm_common_rx_queue_channel_set(unit, i, chan_id); 28172 if(BCM_SUCCESS(rv)) { 28173 oc->mpls_lm_dm_cpu_cosq = i; 28174 break; 28175 } 28176 } 28177 28178 if (i < min_cosq) { 28179 rv = BCM_E_RESOURCE; 28180 LOG_ERROR(BSL_LS_BCM_OAM, 28181 (BSL_META_U(unit, 28182 "BHH(unit %d) Error: hw init." 28183 " queue channel set %s.\n"), 28184 unit, bcm_errmsg(rv))); 28185 _BCM_OAM_UNLOCK(oc); 28186 return (rv); 28187 } 28188 28189 /* 28190 * Direct MPLS_LM_DM packets to designated CPU COS Queue. 28191 * 28192 * Reasons: 28193 * - bcmRxReasonOAMLMDM: MPLS_LM_DM packet breason code 28194 */ 28195 28196 /* Find available entries in CPU COS queue map table */ 28197 mpls_lm_dm_index = -1; /* COSQ map index for error packets */ 28198 rv = bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size); 28199 if(BCM_FAILURE(rv)) { 28200 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)" 28201 " Error:hw init. cos map size get %s.\n"), unit, bcm_errmsg(rv))); 28202 _BCM_OAM_UNLOCK(oc); 28203 return (rv); 28204 } 28205 28206 for (index = 0; index < cosq_map_size; index++) { 28207 rv = bcm_esw_rx_cosq_mapping_get(unit, index, &reasons, 28208 &reasons_mask, &int_prio, &int_prio_mask, &packet_type, 28209 &packet_type_mask, &cosq); 28210 28211 if (rv == BCM_E_NOT_FOUND) { 28212 /* Assign first available index */ 28213 rv = BCM_E_NONE; 28214 if (mpls_lm_dm_index == -1) { 28215 mpls_lm_dm_index = index; 28216 break; 28217 } 28218 } 28219 if (BCM_FAILURE(rv)) { 28220 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)" 28221 " Error:hw init. cosq map get %s.\n"), unit, bcm_errmsg(rv))); 28222 _BCM_OAM_UNLOCK(oc); 28223 return (rv); 28224 } 28225 } 28226 28227 if (mpls_lm_dm_index == -1) { 28228 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)" 28229 " Error:hw init. map_index error %s.\n"), unit, bcm_errmsg(rv))); 28230 _BCM_OAM_UNLOCK(oc); 28231 return (BCM_E_FULL); 28232 } 28233 28234 BCM_RX_REASON_CLEAR_ALL(reasons); 28235 BCM_RX_REASON_SET(reasons, bcmRxReasonOAMMplsLmDm); /* MPLS_LM_DM */ 28236 28237 rv = bcm_esw_rx_cosq_mapping_set(unit, mpls_lm_dm_index, 28238 reasons, reasons, 28239 0, 0, /* Any Internal Prio */ 28240 0, 0, /* Any packet type */ 28241 oc->mpls_lm_dm_cpu_cosq); 28242 if(BCM_FAILURE(rv)) { 28243 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM(unit %d)" 28244 " Error:hw init. cosq map set %s.\n"), unit, bcm_errmsg(rv))); 28245 _BCM_OAM_UNLOCK(oc); 28246 return (rv); 28247 } 28248 oc->mpls_lm_dm_cosq_index = mpls_lm_dm_index; 28249 28250 _BCM_OAM_UNLOCK(oc); 28251 return (rv); 28252 } 28253 28254 #endif /* BCM_METROLITE_SUPPORT */ 28255 /* 28256 * Function: 28257 * _bcm_sb2_oam_mpls_lm_dm_msg_send_receive 28258 * Purpose: 28259 * Sends given MPLS_LM_DM control message to the uController. 28260 * Receives and verifies expected reply. 28261 * Performs DMA operation if required. 28262 * Parameters: 28263 * unit - (IN) Unit number. 28264 * s_subclass - (IN) MPLS message subclass. 28265 * s_len - (IN) Value for 'len' field in message struct. 28266 * Length of buffer to flush if DMA send is required. 28267 * s_data - (IN) Value for 'data' field in message struct. 28268 * Ignored if message requires a DMA send/receive 28269 * operation. 28270 * r_subclass - (IN) Expected reply message subclass. 28271 * r_len - (OUT) Returns value in 'len' reply message field. 28272 * Returns: 28273 * BCM_E_XXX 28274 * Notes: 28275 * - The uc_msg 'len' and 'data' fields of mos_msg_data_t 28276 * can take any arbitrary data. 28277 * 28278 * MPLS_LM_DM Long Control message: 28279 * - MPLS_LM_DM control messages that require send/receive of information 28280 * that cannot fit in the uc_msg 'len' and 'data' fields need to 28281 * use DMA operations to exchange information (long control message). 28282 * 28283 * - MPLS_LM_DM convention for long control messages for 28284 * 'mos_msg_data_t' fields: 28285 * 'len' size of the DMA buffer to send to uController 28286 * 'data' physical DMA memory address to send or receive 28287 * 28288 * DMA Operations: 28289 * - DMA read/write operation is performed when a long MPLS_LM_DM control 28290 * message is involved. 28291 * 28292 * - Messages that require DMA operation (long control message) 28293 * is indicated by MOS_MSG_DMA_MSG(). 28294 * 28295 * - Callers must 'pack' and 'unpack' corresponding information into/from 28296 * DMA buffer indicated by OAM_INFO(unit)->mpls_lm_dm_dma_buffer. 28297 */ 28298 STATIC int 28299 _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(int unit, 28300 uint8 s_subclass, uint16 s_len, uint32 s_data, uint8 r_subclass, 28301 uint16 *r_len) 28302 { 28303 int rv; 28304 _bcm_oam_control_t *oc; 28305 mos_msg_data_t send, reply; 28306 uint8 *dma_buffer; 28307 int dma_buffer_len; 28308 uint32 uc_rv; 28309 28310 /* Lock already taken by the calling routine. */ 28311 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 28312 28313 sal_memset(&send, 0, sizeof(send)); 28314 sal_memset(&reply, 0, sizeof(reply)); 28315 send.s.mclass = MOS_MSG_CLASS_MPLS_LM_DM; 28316 send.s.subclass = s_subclass; 28317 send.s.len = bcm_htons(s_len); 28318 28319 /* 28320 * Set 'data' to DMA buffer address if a DMA operation is 28321 * required for send or receive. 28322 */ 28323 dma_buffer = oc->mpls_lm_dm_dma_buffer; 28324 dma_buffer_len = oc->mpls_lm_dm_dma_buffer_len; 28325 if (MOS_MSG_DMA_MSG(s_subclass) || 28326 MOS_MSG_DMA_MSG(r_subclass)) { 28327 send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer)); 28328 } else { 28329 send.s.data = bcm_htonl(s_data); 28330 } 28331 28332 /* Flush DMA memory */ 28333 if (MOS_MSG_DMA_MSG(s_subclass)) { 28334 soc_cm_sflush(unit, dma_buffer, s_len); 28335 } 28336 28337 /* Invalidate DMA memory to read */ 28338 if (MOS_MSG_DMA_MSG(r_subclass)) { 28339 soc_cm_sinval(unit, dma_buffer, dma_buffer_len); 28340 } 28341 28342 rv = soc_cmic_uc_msg_send_receive(unit, oc->mpls_lm_dm_uc_num, 28343 &send, &reply, 28344 _MPLS_LM_DM_UC_MSG_TIMEOUT_USECS); 28345 28346 /* Check reply class, subclass */ 28347 if ((rv != SOC_E_NONE) || 28348 (reply.s.mclass != MOS_MSG_CLASS_MPLS_LM_DM) || 28349 (reply.s.subclass != r_subclass)) { 28350 return (BCM_E_INTERNAL); 28351 } 28352 28353 /* Convert MPLS_LM_DM uController error code to BCM */ 28354 uc_rv = bcm_ntohl(reply.s.data); 28355 switch(uc_rv) { 28356 case SHR_MPLS_LM_DM_UC_E_NONE: 28357 rv = BCM_E_NONE; 28358 break; 28359 case SHR_MPLS_LM_DM_UC_E_INTERNAL: 28360 rv = BCM_E_INTERNAL; 28361 break; 28362 case SHR_MPLS_LM_DM_UC_E_MEMORY: 28363 rv = BCM_E_MEMORY; 28364 break; 28365 case SHR_MPLS_LM_DM_UC_E_PARAM: 28366 rv = BCM_E_PARAM; 28367 break; 28368 case SHR_MPLS_LM_DM_UC_E_RESOURCE: 28369 rv = BCM_E_RESOURCE; 28370 break; 28371 case SHR_MPLS_LM_DM_UC_E_EXISTS: 28372 rv = BCM_E_EXISTS; 28373 break; 28374 case SHR_MPLS_LM_DM_UC_E_NOT_FOUND: 28375 rv = BCM_E_NOT_FOUND; 28376 break; 28377 case SHR_MPLS_LM_DM_UC_E_INIT: 28378 rv = BCM_E_INIT; 28379 break; 28380 case SHR_MPLS_LM_DM_UC_E_UNAVAIL: 28381 rv = BCM_E_UNAVAIL; 28382 break; 28383 default: 28384 rv = BCM_E_INTERNAL; 28385 break; 28386 } 28387 28388 *r_len = bcm_ntohs(reply.s.len); 28389 28390 return (rv); 28391 } 28392 28393 STATIC uint8 * 28394 _bcm_sb2_oam_mpls_lm_dm_ach_header_pack(uint8 *buffer, 28395 _ach_header_t *ach) 28396 { 28397 uint32 tmp; 28398 28399 tmp = ((ach->f_nibble & 0xf) << 28) | ((ach->version & 0xf) << 24) | 28400 (ach->reserved << 16) | ach->channel_type; 28401 28402 _SHR_PACK_U32(buffer, tmp); 28403 28404 return (buffer); 28405 } 28406 28407 STATIC uint8 * 28408 _bcm_sb2_oam_mpls_lm_dm_mpls_label_pack(uint8 *buffer, 28409 _mpls_label_t *mpls) 28410 { 28411 uint32 tmp; 28412 28413 tmp = ((mpls->label & 0xfffff) << 12) | ((mpls->exp & 0x7) << 9) | 28414 ((mpls->s & 0x1) << 8) | mpls->ttl; 28415 _SHR_PACK_U32(buffer, tmp); 28416 28417 return (buffer); 28418 } 28419 28420 STATIC uint8 * 28421 _bcm_sb2_oam_mpls_lm_dm_l2_header_pack( 28422 bcm_oam_endpoint_type_t type, uint8 *buffer, _l2_header_t *l2) 28423 { 28424 uint32 tmp; 28425 int i; 28426 28427 for (i = 0; i < 6; i++) { 28428 _SHR_PACK_U8(buffer, l2->dst_mac[i]); 28429 } 28430 28431 for (i = 0; i < 6; i++) { 28432 _SHR_PACK_U8(buffer, l2->src_mac[i]); 28433 } 28434 28435 /* Vlan Tag tpid = 0 indicates untagged */ 28436 if (0 != l2->vlan_tag.tpid) { 28437 tmp = (l2->vlan_tag.tpid << 16) | 28438 ((l2->vlan_tag.tci.prio & 0x7) << 13) | 28439 ((l2->vlan_tag.tci.cfi & 0x1) << 12) | 28440 (l2->vlan_tag.tci.vid & 0xfff); 28441 _SHR_PACK_U32(buffer, tmp); 28442 } 28443 28444 /*Inner Vlan Tag inner_tpid = 0 indicates single tag */ 28445 if (0 != l2->vlan_tag_inner.tpid) { 28446 tmp = (l2->vlan_tag_inner.tpid << 16) | 28447 ((l2->vlan_tag_inner.tci.prio & 0x7) << 13) | 28448 ((l2->vlan_tag_inner.tci.cfi & 0x1) << 12) | 28449 (l2->vlan_tag_inner.tci.vid & 0xfff); 28450 _SHR_PACK_U32(buffer, tmp); 28451 } 28452 28453 _SHR_PACK_U16(buffer, l2->etype); 28454 28455 return (buffer); 28456 } 28457 28458 STATIC int 28459 _bcm_sb2_oam_mpls_lm_dm_ach_header_get(uint32 packet_flags, 28460 _ach_header_t *ach) 28461 { 28462 sal_memset(ach, 0, sizeof(*ach)); 28463 28464 ach->f_nibble = SHR_MPLS_LM_DM_ACH_FIRST_NIBBLE; 28465 ach->version = SHR_MPLS_LM_DM_ACH_VERSION; 28466 ach->reserved = 0; 28467 28468 ach->channel_type = (packet_flags & _MPLS_LM_DM_ACH_TYPE_MASK); 28469 28470 return (BCM_E_NONE); 28471 } 28472 28473 STATIC int 28474 _bcm_sb2_oam_mpls_lm_dm_mpls_label_get(uint32 label, uint8 exp, 28475 uint8 s, uint8 ttl, _mpls_label_t *mpls) 28476 { 28477 sal_memset(mpls, 0, sizeof(*mpls)); 28478 28479 mpls->label = label; 28480 mpls->exp = exp; 28481 mpls->s = s; 28482 if(ttl) 28483 mpls->ttl = ttl; 28484 else 28485 mpls->ttl = _MPLS_LM_DM_MPLS_DFLT_TTL; 28486 28487 return (BCM_E_NONE); 28488 } 28489 28490 STATIC int 28491 _bcm_sb2_oam_mpls_lm_dm_mpls_gal_label_get(_mpls_label_t *mpls) 28492 { 28493 return _bcm_sb2_oam_mpls_lm_dm_mpls_label_get(SHR_MPLS_LM_DM_MPLS_GAL_LABEL, 28494 0, 1, 1, mpls); 28495 } 28496 28497 STATIC int 28498 _bcm_sb2_oam_mpls_lm_dm_mpls_router_alert_label_get( 28499 _mpls_label_t *mpls) 28500 { 28501 return _bcm_sb2_oam_mpls_lm_dm_mpls_label_get( 28502 SHR_MPLS_LM_DM_MPLS_ROUTER_ALERT_LABEL, 0, 0, 0, mpls); 28503 } 28504 28505 STATIC int 28506 _bcm_sb2_oam_mpls_lm_dm_mpls_labels_get(int unit, 28507 _bcm_oam_hash_data_t *h_data_p, uint32 packet_flags, int max_count, 28508 _mpls_label_t *pw_label, _mpls_label_t *mpls, int *mpls_count, 28509 bcm_if_t *l3_intf_id) 28510 { 28511 int count = 0; 28512 bcm_l3_egress_t l3_egress; 28513 bcm_mpls_port_t mpls_port; 28514 bcm_mpls_egress_label_t label_array[_MPLS_LM_DM_MPLS_MAX_LABELS]; 28515 bcm_mpls_egress_label_t tmp_label; 28516 int label_count = 0; 28517 int i = 0; 28518 28519 /* Get L3 objects */ 28520 bcm_l3_egress_t_init(&l3_egress); 28521 if (BCM_FAILURE(bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) { 28522 return (BCM_E_PARAM); 28523 } 28524 28525 /* Look for a tunnel associated with this interface */ 28526 if (BCM_SUCCESS 28527 (bcm_esw_mpls_tunnel_initiator_get(unit, l3_egress.intf, 28528 _MPLS_LM_DM_MPLS_MAX_LABELS, 28529 label_array, &label_count))) { 28530 /* We need to sawp the if 2 labels configured in tunnel initiator as 28531 label in 2nd element should be put first during pkt construction */ 28532 if (label_count == 2) { 28533 sal_memcpy(&tmp_label, &label_array[0], sizeof(tmp_label)); 28534 sal_memcpy(&label_array[0], &label_array[1], sizeof(tmp_label)); 28535 sal_memcpy(&label_array[1], &tmp_label, sizeof(tmp_label)); 28536 } 28537 28538 /* Add VRL Label */ 28539 if MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p) { 28540 if ( (l3_egress.mpls_label != BCM_MPLS_LABEL_INVALID) && 28541 (label_count < _MPLS_LM_DM_MPLS_MAX_LABELS) ) { 28542 label_array[label_count].label = l3_egress.mpls_label; 28543 label_array[label_count].exp = l3_egress.mpls_exp; 28544 label_array[label_count].ttl = l3_egress.mpls_ttl; 28545 label_count++; 28546 } 28547 28548 /* Traverse through Label stack and match on control label, this 28549 label should be the one just above GAL in the label stack, any 28550 following labels should not be added */ 28551 for (i=0; i<label_count; i++) { 28552 if (label_array[i].label == h_data_p->egr_label) { 28553 if (h_data_p->egr_label_exp != 0) { 28554 /* Set the EXP for control Label */ 28555 label_array[i].exp = h_data_p->egr_label_exp; 28556 } 28557 if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) && 28558 (h_data_p->egr_label_ttl != 0)) { 28559 /* Set the TTL for control Label */ 28560 label_array[i].ttl = h_data_p->egr_label_ttl; 28561 } 28562 label_count = i+1; 28563 break; 28564 } 28565 } 28566 28567 } 28568 28569 for (i = 0; (i < label_count) && (count < max_count); i++) { 28570 _bcm_sb2_oam_mpls_lm_dm_mpls_label_get(label_array[i].label, 28571 label_array[i].exp, 28572 0, 28573 label_array[i].ttl, 28574 &mpls[count++]); 28575 } 28576 } 28577 28578 28579 /* MPLS Router Alert */ 28580 if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_MPLS_ROUTER_ALERT) { 28581 _bcm_sb2_oam_mpls_lm_dm_mpls_router_alert_label_get(&mpls[count++]); 28582 } 28583 28584 /* Use GPORT to resolve interface */ 28585 if (BCM_GPORT_IS_MPLS_PORT(h_data_p->gport)) { 28586 /* Get mpls port and label info */ 28587 bcm_mpls_port_t_init(&mpls_port); 28588 mpls_port.mpls_port_id = h_data_p->gport; 28589 if (BCM_FAILURE 28590 (bcm_esw_mpls_port_get(unit, h_data_p->vpn, 28591 &mpls_port))) { 28592 return (BCM_E_PARAM); 28593 } else { 28594 if (h_data_p->type == bcmOAMEndpointTypeMplsLmDmPw && 28595 h_data_p->vccv_type == bcmOamBhhVccvTtl) { 28596 mpls_port.egress_label.ttl = 0x1; 28597 } 28598 28599 _bcm_sb2_oam_mpls_lm_dm_mpls_label_get(mpls_port.egress_label.label, 28600 mpls_port.egress_label.exp, 0, mpls_port.egress_label.ttl, 28601 &mpls[count++]); 28602 } 28603 } 28604 28605 /* Set Bottom of Stack if there is no GAL label */ 28606 if (!(packet_flags & _MPLS_LM_DM_ENCAP_PKT_GAL)) { 28607 mpls[count-1].s = 1; 28608 } 28609 28610 *mpls_count = count; 28611 28612 return (BCM_E_NONE); 28613 28614 } 28615 28616 STATIC int 28617 _bcm_sb2_oam_mpls_lm_dm_l2_header_get(int unit, _bcm_oam_hash_data_t *h_data_p, 28618 bcm_port_t port, uint16 etype, 28619 _l2_header_t *l2) 28620 { 28621 uint16 tpid; 28622 bcm_l3_egress_t l3_egress; 28623 bcm_l3_intf_t l3_intf; 28624 bcm_vlan_control_vlan_t vc; 28625 int tpid_select; 28626 bcm_pbmp_t pbmp, ubmp; 28627 bcm_port_t local_port; 28628 28629 sal_memset(l2, 0, sizeof(*l2)); 28630 28631 if (!MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) { 28632 /* Get L3 interfaces */ 28633 bcm_l3_egress_t_init(&l3_egress); 28634 bcm_l3_intf_t_init(&l3_intf); 28635 28636 if (BCM_FAILURE 28637 (bcm_esw_l3_egress_get(unit, h_data_p->egress_if, &l3_egress))) { 28638 return (BCM_E_PARAM); 28639 } 28640 28641 l3_intf.l3a_intf_id = l3_egress.intf; 28642 if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) { 28643 return (BCM_E_PARAM); 28644 } 28645 28646 /* Get TPID */ 28647 BCM_IF_ERROR_RETURN( 28648 bcm_esw_vlan_control_port_get(unit, 28649 port, 28650 bcmVlanPortOuterTpidSelect, 28651 &tpid_select)); 28652 if (tpid_select == BCM_PORT_OUTER_TPID) { 28653 BCM_IF_ERROR_RETURN(bcm_esw_port_tpid_get(unit, port, &tpid)); 28654 } else { 28655 BCM_IF_ERROR_RETURN( 28656 bcm_esw_vlan_control_vlan_get(unit, l3_intf.l3a_vid, &vc)); 28657 tpid = vc.outer_tpid; 28658 } 28659 28660 sal_memcpy(l2->dst_mac, l3_egress.mac_addr, sizeof(bcm_mac_t)); 28661 sal_memcpy(l2->src_mac, l3_intf.l3a_mac_addr, sizeof(bcm_mac_t)); 28662 l2->vlan_tag.tpid = tpid; 28663 l2->vlan_tag.tci.prio = h_data_p->vlan_pri; 28664 l2->vlan_tag.tci.cfi = 0; 28665 l2->vlan_tag.tci.vid = l3_intf.l3a_vid; 28666 28667 BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_get(unit, 28668 l2->vlan_tag.tci.vid, 28669 &pbmp, 28670 &ubmp)); 28671 28672 if (BCM_E_NONE == bcm_esw_port_local_get(unit, port, &local_port)) { 28673 if (BCM_PBMP_MEMBER(ubmp, local_port)) { 28674 l2->vlan_tag.tpid = 0; /* Set to 0 to indicate untagged */ 28675 } 28676 } 28677 28678 if (l3_intf.l3a_inner_vlan != 0) { 28679 BCM_IF_ERROR_RETURN(bcm_esw_port_inner_tpid_get(unit, port, &tpid)); 28680 l2->vlan_tag_inner.tpid = tpid; 28681 l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri; 28682 l2->vlan_tag_inner.tci.cfi = 0; 28683 l2->vlan_tag_inner.tci.vid = l3_intf.l3a_inner_vlan; 28684 } 28685 28686 }else { 28687 sal_memcpy(l2->dst_mac, h_data_p->dst_mac_address, sizeof(bcm_mac_t)); 28688 sal_memcpy(l2->src_mac, h_data_p->src_mac_address, sizeof(bcm_mac_t)); 28689 if((h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionOuterVlan) || 28690 (h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan) || 28691 (h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionInnervlan)) { 28692 l2->vlan_tag.tpid = h_data_p->outer_tpid; 28693 l2->vlan_tag.tci.prio = h_data_p->vlan_pri; 28694 l2->vlan_tag.tci.cfi = 0; 28695 l2->vlan_tag.tci.vid = h_data_p->vlan; 28696 } 28697 if((h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionInnervlan) || 28698 (h_data_p->type == bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan)){ 28699 l2->vlan_tag_inner.tpid = h_data_p->inner_tpid; 28700 l2->vlan_tag_inner.tci.prio = h_data_p->inner_vlan_pri; 28701 l2->vlan_tag_inner.tci.cfi = 0; 28702 l2->vlan_tag_inner.tci.vid = h_data_p->inner_vlan; 28703 } 28704 etype = SHR_MPLS_LM_DM_L2_ETYPE_MPLS_UCAST; 28705 } 28706 l2->etype = etype; 28707 28708 return (BCM_E_NONE); 28709 } 28710 28711 /* 28712 * Function: 28713 * _bcm_sb2_oam_mpls_lm_dm_encap_build_pack 28714 * Purpose: 28715 * Builds and packs the MPLS_LM_DM packet encapsulation for a given 28716 * MPLS_LM_DM tunnel type. 28717 * Parameters: 28718 * unit - (IN) Unit number. 28719 * port - (IN) Port. 28720 * endpoint_config - (IN/OUT) Pointer to MPLS_LM_DM endpoint structure. 28721 * packet_flags - (IN) Flags for building packet. 28722 * buffer - (OUT) Buffer returning BHH encapsulation. 28723 * Returns: 28724 * BCM_E_XXX 28725 * Notes: 28726 * The returning MPLS_LM_DM encapsulation includes only all the 28727 * encapsulation headers/labels and does not include 28728 * the MPLS_LM_DM control packet. 28729 */ 28730 STATIC int 28731 _bcm_sb2_oam_mpls_lm_dm_encap_build_pack(int unit, 28732 bcm_port_t port, _bcm_oam_hash_data_t *h_data_p, uint32 packet_flags, 28733 uint8 *buffer, uint16 *encap_length) 28734 { 28735 uint8 *cur_ptr = buffer; 28736 uint16 etype = 0; 28737 bcm_if_t l3_intf_id = -1; 28738 _ach_header_t ach; 28739 _mpls_label_t mpls_gal; 28740 _mpls_label_t mpls_r_alert; 28741 _mpls_label_t mpls_labels[_MPLS_LM_DM_MPLS_MAX_LABELS]; 28742 _mpls_label_t pw_label; 28743 int mpls_count = 0; 28744 _l2_header_t l2; 28745 int i; 28746 28747 28748 /* 28749 * Get necessary headers/labels information. 28750 * 28751 * Following order is important since some headers/labels 28752 * may depend on previous header/label information. 28753 */ 28754 if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_G_ACH) { 28755 BCM_IF_ERROR_RETURN 28756 (_bcm_sb2_oam_mpls_lm_dm_ach_header_get(packet_flags, &ach)); 28757 } 28758 28759 if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_GAL) { 28760 BCM_IF_ERROR_RETURN 28761 (_bcm_sb2_oam_mpls_lm_dm_mpls_gal_label_get(&mpls_gal)); 28762 } 28763 28764 if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_MPLS_ROUTER_ALERT) { 28765 BCM_IF_ERROR_RETURN 28766 (_bcm_sb2_oam_mpls_lm_dm_mpls_router_alert_label_get(&mpls_r_alert)); 28767 } 28768 28769 if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_MPLS_LSP) { 28770 etype = SHR_MPLS_LM_DM_L2_ETYPE_MPLS_UCAST; 28771 BCM_IF_ERROR_RETURN 28772 (_bcm_sb2_oam_mpls_lm_dm_mpls_labels_get(unit, h_data_p, packet_flags, 28773 _MPLS_LM_DM_MPLS_MAX_LABELS, &pw_label, mpls_labels, &mpls_count, 28774 &l3_intf_id)); 28775 } 28776 28777 /* Always build L2 Header */ 28778 BCM_IF_ERROR_RETURN 28779 (_bcm_sb2_oam_mpls_lm_dm_l2_header_get(unit, h_data_p, port, etype, 28780 &l2)); 28781 28782 /* 28783 * Pack header/labels into given buffer (network packet format). 28784 * 28785 * Following packing order must be followed to correctly 28786 * build the packet encapsulation. 28787 */ 28788 cur_ptr = buffer; 28789 28790 /* L2 Header is always present */ 28791 cur_ptr = _bcm_sb2_oam_mpls_lm_dm_l2_header_pack(h_data_p->type, cur_ptr, 28792 &l2); 28793 28794 if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_MPLS_LSP) { 28795 for (i = 0;i < mpls_count;i++) { 28796 cur_ptr = _bcm_sb2_oam_mpls_lm_dm_mpls_label_pack(cur_ptr, 28797 &mpls_labels[i]); 28798 } 28799 } 28800 28801 if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_GAL) { 28802 cur_ptr = _bcm_sb2_oam_mpls_lm_dm_mpls_label_pack(cur_ptr, &mpls_gal); 28803 } 28804 28805 if (packet_flags & _MPLS_LM_DM_ENCAP_PKT_G_ACH) { 28806 cur_ptr = _bcm_sb2_oam_mpls_lm_dm_ach_header_pack(cur_ptr, &ach); 28807 } 28808 28809 28810 /* Set MPLS_LM_DM encapsulation length */ 28811 *encap_length = cur_ptr - buffer; 28812 28813 return (BCM_E_NONE); 28814 } 28815 28816 #ifdef _MPLS_LM_DM_DEBUG_DUMP 28817 void 28818 _bcm_sb2_oam_mpls_lm_dm_encap_data_dump(uint8 *buffer, int length) 28819 { 28820 int i; 28821 28822 LOG_CLI((BSL_META("\nEncapsulation (length=%d):\n"), length)); 28823 28824 for (i = 0; i < length; i++) { 28825 if ((i % 16) == 0) { 28826 LOG_CLI((BSL_META("\n"))); 28827 } 28828 LOG_CLI((BSL_META(" %02x"), buffer[i])); 28829 } 28830 28831 LOG_CLI((BSL_META("\n"))); 28832 return; 28833 } 28834 #endif 28835 28836 /* 28837 * Function: 28838 * _bcm_sb2_oam_mpls_lm_dm_encap_create 28839 * Purpose: 28840 * Creates a MPLS_LM_DM packet encapsulation. 28841 * Parameters: 28842 * unit - (IN) Unit number. 28843 * port_id - (IN) Port. 28844 * endpoint_config - (IN/OUT) Pointer to MPLS_LM_DM endpoint structure. 28845 * encap_data - (OUT) Buffer returning MPLS_LM_DM encapsulation. 28846 * Returns: 28847 * BCM_E_XXX 28848 * Notes: 28849 * The returning MPLS_LM_DM encapsulation buffer includes all the 28850 * corresponding headers/labels EXCEPT for the MPLS_LM_DM control packet. 28851 */ 28852 STATIC int 28853 _bcm_sb2_oam_mpls_lm_dm_encap_create(int unit, _bcm_oam_hash_data_t *h_data_p, 28854 bcm_port_t port, uint8 *encap_data, uint16 *encap_length, uint32 packet_flags) 28855 { 28856 28857 /* 28858 * Get MPLS_LM_DM encapsulation packet format flags 28859 * 28860 * Also, perform the following for each MPLS_LM_DM tunnel type: 28861 * - Check for valid parameter values 28862 * - Set specific values required by the MPLS_LM_DM tunnel definition 28863 * (e.g. such as ttl=1,...) 28864 */ 28865 switch (h_data_p->type) { 28866 case bcmOAMEndpointTypeMplsLmDmLsp: 28867 packet_flags |= 28868 (_MPLS_LM_DM_ENCAP_PKT_MPLS_LSP | 28869 _MPLS_LM_DM_ENCAP_PKT_GAL | 28870 _MPLS_LM_DM_ENCAP_PKT_G_ACH); 28871 break; 28872 28873 case bcmOAMEndpointTypeMplsLmDmPw: 28874 switch(h_data_p->vccv_type) { 28875 28876 case bcmOamBhhVccvChannelAch: 28877 packet_flags |= 28878 (_MPLS_LM_DM_ENCAP_PKT_MPLS_LSP | 28879 _MPLS_LM_DM_ENCAP_PKT_PW | 28880 _MPLS_LM_DM_ENCAP_PKT_G_ACH); 28881 break; 28882 28883 case bcmOamBhhVccvRouterAlert: 28884 packet_flags |= 28885 (_MPLS_LM_DM_ENCAP_PKT_MPLS_LSP | 28886 _MPLS_LM_DM_ENCAP_PKT_PW | 28887 _MPLS_LM_DM_ENCAP_PKT_MPLS_ROUTER_ALERT | 28888 _MPLS_LM_DM_ENCAP_PKT_G_ACH); 28889 break; 28890 28891 case bcmOamBhhVccvTtl: 28892 packet_flags |= 28893 (_MPLS_LM_DM_ENCAP_PKT_MPLS_LSP | 28894 _MPLS_LM_DM_ENCAP_PKT_PW | 28895 _MPLS_LM_DM_ENCAP_PKT_G_ACH); 28896 break; 28897 28898 case bcmOamBhhVccvGal13: 28899 packet_flags |= 28900 (_MPLS_LM_DM_ENCAP_PKT_MPLS_LSP | 28901 _MPLS_LM_DM_ENCAP_PKT_PW | 28902 _MPLS_LM_DM_ENCAP_PKT_GAL | 28903 _MPLS_LM_DM_ENCAP_PKT_G_ACH); 28904 break; 28905 28906 default: 28907 return (BCM_E_PARAM); 28908 break; 28909 } 28910 break; 28911 28912 case bcmOAMEndpointTypeMplsLmDmSectionPort: 28913 case bcmOAMEndpointTypeMplsLmDmSectionInnervlan: 28914 case bcmOAMEndpointTypeMplsLmDmSectionOuterVlan: 28915 case bcmOAMEndpointTypeMplsLmDmSectionOuterPlusInnerVlan: 28916 packet_flags |= 28917 (_MPLS_LM_DM_ENCAP_PKT_GAL | 28918 _MPLS_LM_DM_ENCAP_PKT_G_ACH); 28919 break; 28920 default: 28921 return (BCM_E_PARAM); 28922 } 28923 28924 /* Build header/labels and pack in buffer */ 28925 BCM_IF_ERROR_RETURN 28926 (_bcm_sb2_oam_mpls_lm_dm_encap_build_pack(unit, port, 28927 h_data_p, packet_flags, encap_data, encap_length)); 28928 28929 #ifdef _MPLS_LM_DM_DEBUG_DUMP 28930 _bcm_sb2_oam_mpls_lm_dm_encap_data_dump(encap_data, *encap_length); 28931 #endif 28932 28933 28934 return (BCM_E_NONE); 28935 } 28936 28937 /* 28938 * Function: 28939 * _bcm_sb2_mpls_lm_dm_get_tx_gport 28940 * Purpose: 28941 * Get the port where pkts need to be sent 28942 * Parameters: 28943 * unit - Device unit number 28944 * Returns: 28945 * None 28946 */ 28947 STATIC int 28948 _bcm_sb2_mpls_lm_dm_get_tx_gport(int unit, _bcm_oam_hash_data_t *h_data_p, 28949 bcm_gport_t *tx_gport) 28950 { 28951 28952 bcm_gport_t gport; 28953 bcm_trunk_t trunk; 28954 bcm_l3_egress_t l3_egress; 28955 bcm_trunk_info_t trunk_info; 28956 bcm_trunk_member_t *member_array = NULL; 28957 int member_count = 0; 28958 int rv = BCM_E_NONE; 28959 28960 if (MPLS_LM_DM_SECTION_ENDPOINT_TYPE(h_data_p)) { 28961 gport = h_data_p->gport; 28962 } else { 28963 bcm_l3_egress_t_init(&l3_egress); 28964 BCM_IF_ERROR_RETURN(bcm_esw_l3_egress_get(unit, h_data_p->egress_if, 28965 &l3_egress)); 28966 28967 if (l3_egress.flags & BCM_L3_TGID) { 28968 BCM_GPORT_TRUNK_SET(gport, l3_egress.trunk); 28969 } else { 28970 BCM_GPORT_MODPORT_SET(gport, l3_egress.module, l3_egress.port); 28971 } 28972 } 28973 28974 if (BCM_GPORT_IS_TRUNK(gport)) { 28975 trunk = BCM_GPORT_TRUNK_GET(gport); 28976 BCM_IF_ERROR_RETURN(bcm_esw_trunk_get(unit, trunk, NULL, 0, 28977 NULL, &member_count)); 28978 if (0 == member_count) { 28979 /* No members have been added to the trunk group yet */ 28980 return BCM_E_PARAM; 28981 } 28982 /* Check if the input trunk_index is valid. */ 28983 if (h_data_p->trunk_index >= member_count) { 28984 return BCM_E_PARAM; 28985 } 28986 28987 _BCM_OAM_ALLOC(member_array, bcm_trunk_member_t, 28988 sizeof(bcm_trunk_member_t) * member_count, 28989 "Trunk info"); 28990 if (NULL == member_array) { 28991 return (BCM_E_MEMORY); 28992 } 28993 28994 /* Get Trunk Info for the Trunk ID. */ 28995 rv = bcm_esw_trunk_get(unit, trunk, &trunk_info, member_count, 28996 member_array, &member_count); 28997 if (BCM_FAILURE(rv)) { 28998 sal_free(member_array); 28999 return (rv); 29000 } 29001 29002 *tx_gport = member_array[h_data_p->trunk_index].gport; 29003 sal_free(member_array); 29004 } else { 29005 *tx_gport = gport; 29006 } 29007 29008 return BCM_E_NONE; 29009 } 29010 29011 STATIC int 29012 _bcm_sb2_mpls_lm_dm_loss_add(int unit, _bcm_oam_hash_data_t *h_data_p, 29013 bcm_oam_loss_t *loss_p) 29014 { 29015 _bcm_oam_control_t *oc = NULL; 29016 uint8 *buffer_p = NULL; 29017 uint8 *buffer_after_pack_p = NULL; 29018 uint16 buffer_len = 0; 29019 uint16 reply_len = 0; 29020 uint32 session_id; 29021 soc_olp_l2_hdr_t olp_l2_header; 29022 soc_olp_tx_hdr_t olp_oam_header; 29023 mpls_lm_dm_sdk_msg_ctrl_loss_add_t loss_add_msg; 29024 int my_mod_id = 0; 29025 int cpu_dglp = 0; 29026 int cpu_port = 0; 29027 int rv = 0; 29028 uint32 packet_flags = 0; 29029 uint32 counter_pool = 0; 29030 int i; 29031 bcm_gport_t gport; 29032 bcm_oam_endpoint_info_t ep_info; 29033 29034 /* Get OAM control pointer */ 29035 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 29036 29037 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_mod_id)); 29038 29039 /* Initialize the Message structure */ 29040 sal_memset(&loss_add_msg, 0, sizeof(loss_add_msg)); 29041 29042 /* Validation Checks */ 29043 /* ----------------- */ 29044 /* Check if loss already added */ 29045 if (h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED) { 29046 return BCM_E_EXISTS; 29047 } 29048 /* Check for combined mode */ 29049 if (loss_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) { 29050 if (loss_p->flags & BCM_OAM_LOSS_SLM) { 29051 /* User wants to configure ILM+DM */ 29052 /* User can set 0 or more counters */ 29053 if ( (loss_p->lm_counter_size > BCM_OAM_LM_COUNTER_MAX) || 29054 (loss_p->lm_counter_size < 0) ) { 29055 return BCM_E_PARAM; 29056 } 29057 packet_flags |= SHR_MPLS_LM_DM_ACH_TYPE_ILM_DM; 29058 loss_add_msg.flags = SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM_DM; 29059 } else { 29060 /* User wants to configure DLM+DM */ 29061 /* User must set atleast one counter action */ 29062 if ( (loss_p->lm_counter_size > BCM_OAM_LM_COUNTER_MAX) || 29063 (loss_p->lm_counter_size <= 0) ) { 29064 return BCM_E_PARAM; 29065 } 29066 packet_flags |= SHR_MPLS_LM_DM_ACH_TYPE_DLM_DM; 29067 loss_add_msg.flags = SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM_DM; 29068 } 29069 loss_add_msg.flags |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED; 29070 } else { 29071 29072 if (loss_p->flags & BCM_OAM_LOSS_SLM) { 29073 /* User wants to configure ILM */ 29074 /* User can set 0 or more counters */ 29075 if ( (loss_p->lm_counter_size > BCM_OAM_LM_COUNTER_MAX) || 29076 (loss_p->lm_counter_size < 0) ) { 29077 return BCM_E_PARAM; 29078 } 29079 /* Set the ACH type in the packet flags for Pkt Encap construction */ 29080 packet_flags |= SHR_MPLS_LM_DM_ACH_TYPE_ILM; 29081 loss_add_msg.flags = SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM; 29082 29083 } else { 29084 /* User wants to configure DLM */ 29085 /* User must set atleast one counter action */ 29086 if ( (loss_p->lm_counter_size > BCM_OAM_LM_COUNTER_MAX) || 29087 (loss_p->lm_counter_size <= 0) ) { 29088 return BCM_E_PARAM; 29089 } 29090 packet_flags |= SHR_MPLS_LM_DM_ACH_TYPE_DLM; 29091 loss_add_msg.flags = SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM; 29092 29093 } 29094 } 29095 /* Active or Passive mode */ 29096 if (!(loss_p->flags & BCM_OAM_LOSS_TX_ENABLE)) { 29097 loss_add_msg.flags |= SHR_MPLS_LM_DM_PASSIVE_FLAG; 29098 } 29099 29100 /* Single or dual ended mode */ 29101 if (loss_p->flags & BCM_OAM_LOSS_SINGLE_ENDED) { 29102 loss_add_msg.flags |= SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG; 29103 } 29104 29105 /* Get byte or frame count, counter size if not SLM */ 29106 if (!(loss_p->flags & BCM_OAM_LOSS_SLM)) { 29107 rv = bcm_sb2_oam_endpoint_get(unit, loss_p->id, &ep_info); 29108 if (BCM_FAILURE(rv)) { 29109 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:" 29110 " EP info get failed EP:%d %s.\n"), unit, h_data_p->ep_id, 29111 bcm_errmsg(rv))); 29112 return (rv); 29113 } 29114 if (ep_info.lm_ctr_type == bcmOamLmCounterTypeByte) { 29115 loss_add_msg.flags |= SHR_MPLS_LM_DM_BYTE_COUNT_FLAG; 29116 29117 if (ep_info.lm_ctr_sample_size == bcmOamLmCounterSize64Bit) { 29118 if (loss_add_msg.flags & BCM_OAM_COMBINED_LOSS_DELAY) { 29119 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM " 29120 "(unit %d) Error: Combined mode not supported with 64-bit " 29121 "counter\n"), unit)); 29122 29123 return BCM_E_PARAM; 29124 } 29125 loss_add_msg.flags |= SHR_MPLS_LM_DM_64_BIT_FLAG; 29126 } 29127 } 29128 } 29129 29130 /* Reserve and program session Id for this EP */ 29131 /* ------------------------------------------ */ 29132 if (h_data_p->lm_dm_uc_session_id == 0 ) { 29133 rv = shr_idxres_list_alloc(oc->mpls_lm_dm_pool, 29134 (shr_idxres_element_t *)&session_id); 29135 29136 if (BCM_FAILURE(rv)) { 29137 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:" 29138 " Session Id alloc failed EP:%d %s.\n"), unit, h_data_p->ep_id, 29139 bcm_errmsg(rv))); 29140 return (rv); 29141 } 29142 29143 /* Program the session Id in the H/w table */ 29144 rv = soc_mem_field32_modify(unit, MA_INDEXm, h_data_p->ma_base_index, 29145 MA_PTRf, session_id); 29146 if (BCM_FAILURE(rv)) { 29147 shr_idxres_list_free(oc->mpls_lm_dm_pool, 29148 (shr_idxres_element_t)session_id); 29149 return (rv); 29150 } 29151 h_data_p->lm_dm_uc_session_id = session_id; 29152 } else { 29153 session_id = h_data_p->lm_dm_uc_session_id; 29154 } 29155 29156 /* Set the session Id in the message structure */ 29157 loss_add_msg.sess_id = session_id; 29158 29159 /* Set the periodicity */ 29160 loss_add_msg.period = loss_p->period; 29161 29162 rv = _bcm_sb2_mpls_lm_dm_get_tx_gport(unit, h_data_p, &gport); 29163 29164 /* Create L2 Encap */ 29165 /* --------------- */ 29166 rv = _bcm_sb2_oam_mpls_lm_dm_encap_create(unit, h_data_p, gport, 29167 loss_add_msg.l2_encap_data, &(loss_add_msg.l2_encap_length), 29168 packet_flags); 29169 if (BCM_FAILURE(rv)) { 29170 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:" 29171 " L2 Encap create failed EP:%d %s.\n"), unit, h_data_p->ep_id, 29172 bcm_errmsg(rv))); 29173 return (rv); 29174 } 29175 29176 29177 /* Creare OLP L2 Encap & Pack */ 29178 /* -------------------------- */ 29179 cpu_dglp = ((my_mod_id << DGLP_MODULE_ID_SHIFT_BITS) + cpu_port); 29180 _bcm_sb2_oam_olp_l2_header_get(unit, cpu_dglp, &olp_l2_header); 29181 /* Pack OLP L2 Encap */ 29182 buffer_p = _bcm_sb2_oam_olp_l2_header_pack(loss_add_msg.olp_encap_data, 29183 &olp_l2_header); 29184 29185 /* Create OLP OAM Encap & Pack */ 29186 /* --------------------------- */ 29187 sal_memset(&olp_oam_header, 0, sizeof(olp_oam_header)); 29188 /* Set Port number */ 29189 SOC_OLP_TX_PORT(&olp_oam_header) = BCM_GPORT_MODPORT_PORT_GET(gport); 29190 SOC_OLP_TX_MODID(&olp_oam_header) = BCM_GPORT_MODPORT_MODID_GET(gport); 29191 29192 29193 /* Set Counter indexes */ 29194 loss_add_msg.ctr_size = loss_p->lm_counter_size; 29195 for (i=0; i< loss_p->lm_counter_size; i++) { 29196 29197 /* Store base id and offset to uKernel for retrieval during get */ 29198 loss_add_msg.ctr_base_id[i] = loss_p->lm_counter_base_id[i]; 29199 loss_add_msg.ctr_offset[i] = loss_p->lm_counter_offset[i]; 29200 loss_add_msg.ctr_action[i] = loss_p->lm_counter_action[i]; 29201 loss_add_msg.ctr_byte_offset[i] = loss_p->lm_counter_byte_offset[i]; 29202 29203 /* Counter pool index is 8 bit MSB of 24 bit counter base index */ 29204 counter_pool = (loss_p->lm_counter_base_id[i] & 0xFF000000) >> 24; 29205 29206 if (counter_pool == 0) { 29207 SOC_OLP_TX_CTR1_ID(&olp_oam_header) = 29208 (loss_p->lm_counter_base_id[i] & 0x00FFFFFF) + 29209 loss_p->lm_counter_offset[i]; 29210 SOC_OLP_TX_CTR1_ACTION(&olp_oam_header) = 29211 loss_p->lm_counter_action[i]; 29212 /* Counter location is Egress */ 29213 SOC_OLP_TX_CTR1_LOCATION(&olp_oam_header) = 1; 29214 SOC_OLP_TX_CTR1_OFF_LM(&olp_oam_header) = 29215 loss_p->lm_counter_byte_offset[i] >> 1; 29216 29217 } 29218 if (counter_pool == 1) { 29219 SOC_OLP_TX_CTR2_ID_SET(&olp_oam_header, 29220 (loss_p->lm_counter_base_id[i] & 0x00FFFFFF) + 29221 loss_p->lm_counter_offset[i]); 29222 SOC_OLP_TX_CTR2_ACTION(&olp_oam_header) = 29223 loss_p->lm_counter_action[i]; 29224 SOC_OLP_TX_CTR2_LOCATION(&olp_oam_header) = 1; 29225 SOC_OLP_TX_CTR2_OFF_LM(&olp_oam_header) = 29226 loss_p->lm_counter_byte_offset[i] >> 1; 29227 } 29228 if (counter_pool == 2) { 29229 SOC_OLP_TX_CTR3_ID_SET(&olp_oam_header, 29230 (loss_p->lm_counter_base_id[i] & 0x00FFFFFFFF) + 29231 loss_p->lm_counter_offset[i]); 29232 SOC_OLP_TX_CTR3_ACTION(&olp_oam_header) = 29233 loss_p->lm_counter_action[i]; 29234 SOC_OLP_TX_CTR3_LOCATION(&olp_oam_header) = 1; 29235 SOC_OLP_TX_CTR3_OFF_LM(&olp_oam_header) = 29236 loss_p->lm_counter_byte_offset[i] >> 1; 29237 } 29238 } 29239 29240 /* COUNTER OFFSET in OLP Header = 29241 * (L2 Encap + Counter field offset in MPLS_LM_DM OAM Header - 14)/2 29242 */ 29243 SOC_OLP_TX_OAM_OFFSET(&olp_oam_header) = 29244 ((loss_add_msg.l2_encap_length + 20) - 14) >> 1; 29245 29246 /* Pack OLP OAM Encap */ 29247 shr_olp_tx_header_pack(buffer_p, &olp_oam_header); 29248 29249 #ifdef _MPLS_LM_DM_DEBUG_DUMP 29250 _bcm_sb2_oam_mpls_lm_dm_encap_data_dump(loss_add_msg.olp_encap_data, 29251 MPLS_LM_DM_OLP_HDR_LEN); 29252 #endif 29253 29254 29255 /* Send Loss Add message */ 29256 /* --------------------- */ 29257 buffer_p = oc->mpls_lm_dm_dma_buffer; 29258 buffer_after_pack_p = mpls_lm_dm_sdk_msg_ctrl_loss_add_pack(buffer_p, 29259 &loss_add_msg); 29260 buffer_len = buffer_after_pack_p - buffer_p; 29261 29262 rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit, 29263 MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_ADD, buffer_len, 0, 29264 MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_ADD_REPLY, 29265 &reply_len); 29266 29267 if (BCM_FAILURE(rv)|| (reply_len != 0)) { 29268 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:" 29269 " Loss Add Msg failed EP:%d %s.\n"), unit, h_data_p->ep_id, 29270 bcm_errmsg(rv))); 29271 return (rv); 29272 } 29273 29274 /* Store the session Id in hash data */ 29275 h_data_p->lm_dm_uc_session_id = session_id; 29276 oc->mpls_lm_dm_sess_id_ep_id[session_id] = h_data_p->ep_id; 29277 29278 /* Set the packet type in hash data */ 29279 if (loss_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) { 29280 if (h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED) { 29281 /* Both Loss & Delay have been added */ 29282 (loss_p->flags & BCM_OAM_LOSS_SLM ) ? 29283 (h_data_p->lm_dm_int_flag |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM_DM) : 29284 (h_data_p->lm_dm_int_flag |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM_DM); 29285 } 29286 } else { 29287 (loss_p->flags & BCM_OAM_LOSS_SLM ) ? 29288 (h_data_p->lm_dm_int_flag |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM) : 29289 (h_data_p->lm_dm_int_flag |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM); 29290 } 29291 h_data_p->lm_dm_int_flag |= SHR_MPLS_LM_DM_FLAG_LOSS_ADDED; 29292 loss_p->pm_id = h_data_p->lm_dm_uc_session_id; 29293 return rv; 29294 } 29295 29296 STATIC int 29297 _bcm_sb2_mpls_lm_dm_delay_add(int unit, _bcm_oam_hash_data_t *h_data_p, 29298 bcm_oam_delay_t *delay_p) 29299 { 29300 _bcm_oam_control_t *oc = NULL; 29301 uint8 *buffer_p = NULL; 29302 uint8 *buffer_after_pack_p = NULL; 29303 uint16 buffer_len = 0; 29304 uint16 reply_len = 0; 29305 uint32 session_id; 29306 soc_olp_l2_hdr_t olp_l2_header; 29307 soc_olp_tx_hdr_t olp_oam_header; 29308 mpls_lm_dm_sdk_msg_ctrl_delay_add_t delay_add_msg; 29309 int my_mod_id = 0; 29310 int cpu_dglp = 0; 29311 int cpu_port = 0; 29312 int rv = 0; 29313 uint32 packet_flags = 0; 29314 int skip_l2_encap = 0; 29315 bcm_gport_t gport; 29316 uint32 counter_pool = 0; 29317 int i; 29318 29319 /* Get OAM control pointer */ 29320 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 29321 29322 BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &my_mod_id)); 29323 29324 /* Initialize the Message structure */ 29325 sal_memset(&delay_add_msg, 0, sizeof(delay_add_msg)); 29326 29327 /* Validation Checks */ 29328 /* ----------------- */ 29329 /* Check if the DM is already enabled for this EP */ 29330 if (h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED) { 29331 return BCM_E_EXISTS; 29332 } 29333 /* Check if combined mode, in combined mode loss add will determine the ACH 29334 Header */ 29335 if (delay_p->flags & BCM_OAM_COMBINED_LOSS_DELAY) { 29336 skip_l2_encap = 1; 29337 delay_add_msg.flags = SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED; 29338 } else { 29339 /* Set the ACH type in the packet flags for Pkt Encap construction */ 29340 packet_flags |= SHR_MPLS_LM_DM_ACH_TYPE_DM; 29341 delay_add_msg.flags = SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DM; 29342 } 29343 29344 /* Active or Passive mode */ 29345 if (!(delay_p->flags & BCM_OAM_DELAY_TX_ENABLE)) { 29346 delay_add_msg.flags |= SHR_MPLS_LM_DM_PASSIVE_FLAG; 29347 } 29348 29349 /* Single or dual ended mode */ 29350 if (!(delay_p->flags & BCM_OAM_DELAY_ONE_WAY)) { 29351 delay_add_msg.flags |= SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG; 29352 } 29353 29354 /* Reserve and program session Id for this EP */ 29355 /* ------------------------------------------ */ 29356 if (h_data_p->lm_dm_uc_session_id == 0 ) { 29357 rv = shr_idxres_list_alloc(oc->mpls_lm_dm_pool, 29358 (shr_idxres_element_t *)&session_id); 29359 if (BCM_FAILURE(rv)) { 29360 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:" 29361 " Session Id alloc failed EP:%d %s.\n"), unit, h_data_p->ep_id, 29362 bcm_errmsg(rv))); 29363 return (rv); 29364 } 29365 29366 /* Program the session Id in the H/w table */ 29367 rv = soc_mem_field32_modify(unit, MA_INDEXm, h_data_p->ma_base_index, 29368 MA_PTRf, session_id); 29369 if (BCM_FAILURE(rv)) { 29370 shr_idxres_list_free(oc->mpls_lm_dm_pool, 29371 (shr_idxres_element_t)session_id); 29372 return (rv); 29373 } 29374 h_data_p->lm_dm_uc_session_id = session_id; 29375 } else { 29376 session_id = h_data_p->lm_dm_uc_session_id; 29377 } 29378 29379 /* Set the session Id in the message structure */ 29380 delay_add_msg.sess_id = session_id; 29381 29382 /* Set the periodicity */ 29383 delay_add_msg.period = delay_p->period; 29384 29385 /* Set timestamp format */ 29386 delay_add_msg.dm_format = delay_p->timestamp_format; 29387 29388 rv = _bcm_sb2_mpls_lm_dm_get_tx_gport(unit, h_data_p, &gport); 29389 29390 /* Create L2 Encap */ 29391 /* --------------- */ 29392 if (!(skip_l2_encap)) { 29393 rv = _bcm_sb2_oam_mpls_lm_dm_encap_create(unit, h_data_p, gport, 29394 delay_add_msg.l2_encap_data, &(delay_add_msg.l2_encap_length), 29395 packet_flags); 29396 if (BCM_FAILURE(rv)) { 29397 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:" 29398 " L2 Encap create failed EP:%d %s.\n"), unit, h_data_p->ep_id, 29399 bcm_errmsg(rv))); 29400 return (rv); 29401 } 29402 } 29403 29404 29405 /* Creare OLP L2 Encap & Pack */ 29406 /* -------------------------- */ 29407 cpu_dglp = ((my_mod_id << DGLP_MODULE_ID_SHIFT_BITS) + cpu_port); 29408 _bcm_sb2_oam_olp_l2_header_get(unit, cpu_dglp, &olp_l2_header); 29409 /* Pack OLP L2 Encap */ 29410 buffer_p = _bcm_sb2_oam_olp_l2_header_pack(delay_add_msg.olp_encap_data, 29411 &olp_l2_header); 29412 29413 sal_memset(&olp_oam_header, 0, sizeof(olp_oam_header)); 29414 /* Set Port number */ 29415 SOC_OLP_TX_PORT(&olp_oam_header) = BCM_GPORT_MODPORT_PORT_GET(gport); 29416 SOC_OLP_TX_MODID(&olp_oam_header) = BCM_GPORT_MODPORT_MODID_GET(gport); 29417 29418 /* Set Sample timestamp action */ 29419 SOC_OLP_TX_TIMESTAMP_ACTION(&olp_oam_header) = 29420 ((delay_p->timestamp_format == bcmOAMTimestampFormatNTP) ? 2:1); 29421 29422 /* Set Counter indexes */ 29423 for (i=0; i< delay_p->dm_tx_update_lm_counter_size; i++) { 29424 29425 /* Counter pool index is 8 bit MSB of 24 bit counter base index */ 29426 counter_pool = (delay_p->dm_tx_update_lm_counter_base_id[i] & 0xFF000000) >> 24; 29427 29428 if (counter_pool == 0) { 29429 SOC_OLP_TX_CTR1_ID(&olp_oam_header) = 29430 (delay_p->dm_tx_update_lm_counter_base_id[i] & 0x00FFFFFF) + 29431 delay_p->dm_tx_update_lm_counter_offset[i]; 29432 29433 SOC_OLP_TX_CTR1_ACTION(&olp_oam_header) = 29434 bcmOamCounterActionIncrement; 29435 /* Counter location is Egress */ 29436 SOC_OLP_TX_CTR1_LOCATION(&olp_oam_header) = 1; 29437 SOC_OLP_TX_CTR1_OFF_LM(&olp_oam_header) = 29438 delay_p->dm_tx_update_lm_counter_byte_offset[i] >> 1; 29439 29440 } 29441 if (counter_pool == 1) { 29442 SOC_OLP_TX_CTR2_ID_SET(&olp_oam_header, 29443 (delay_p->dm_tx_update_lm_counter_base_id[i] & 0x00FFFFFF) + 29444 delay_p->dm_tx_update_lm_counter_offset[i]); 29445 SOC_OLP_TX_CTR2_ACTION(&olp_oam_header) = 29446 bcmOamCounterActionIncrement; 29447 SOC_OLP_TX_CTR2_LOCATION(&olp_oam_header) = 1; 29448 SOC_OLP_TX_CTR2_OFF_LM(&olp_oam_header) = 29449 delay_p->dm_tx_update_lm_counter_byte_offset[i] >> 1; 29450 } 29451 if (counter_pool == 2) { 29452 SOC_OLP_TX_CTR3_ID_SET(&olp_oam_header, 29453 (delay_p->dm_tx_update_lm_counter_base_id[i] & 0x00FFFFFFFF) + 29454 delay_p->dm_tx_update_lm_counter_offset[i]); 29455 SOC_OLP_TX_CTR3_ACTION(&olp_oam_header) = 29456 bcmOamCounterActionIncrement; 29457 SOC_OLP_TX_CTR3_LOCATION(&olp_oam_header) = 1; 29458 SOC_OLP_TX_CTR3_OFF_LM(&olp_oam_header) = 29459 delay_p->dm_tx_update_lm_counter_byte_offset[i] >> 1; 29460 } 29461 } 29462 29463 /* TIMESTAMP OFFSET in OLP Header = 29464 * (L2 Encap + Timestamp field offset in MPLS_LM_DM OAM Header - 14)/2 29465 */ 29466 SOC_OLP_TX_OAM_OFFSET(&olp_oam_header) = 29467 ((delay_add_msg.l2_encap_length + 12 ) - 14) >> 1; 29468 29469 /* Pack OLP OAM Encap */ 29470 shr_olp_tx_header_pack(buffer_p, &olp_oam_header); 29471 29472 #ifdef _MPLS_LM_DM_DEBUG_DUMP 29473 _bcm_sb2_oam_mpls_lm_dm_encap_data_dump(delay_add_msg.olp_encap_data, 29474 MPLS_LM_DM_OLP_HDR_LEN); 29475 #endif 29476 29477 29478 /* Send Delay Add message */ 29479 /* --------------------- */ 29480 buffer_p = oc->mpls_lm_dm_dma_buffer; 29481 buffer_after_pack_p = mpls_lm_dm_sdk_msg_ctrl_delay_add_pack(buffer_p, 29482 &delay_add_msg); 29483 buffer_len = buffer_after_pack_p - buffer_p; 29484 29485 rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit, 29486 MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_ADD, buffer_len, 0, 29487 MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_ADD_REPLY, 29488 &reply_len); 29489 29490 if (BCM_FAILURE(rv)|| (reply_len != 0)) { 29491 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:" 29492 " Delay Add Msg failed EP:%d %s.\n"), unit, h_data_p->ep_id, 29493 bcm_errmsg(rv))); 29494 return (rv); 29495 } 29496 29497 /* Store the session Id in hash data */ 29498 h_data_p->lm_dm_uc_session_id = session_id; 29499 oc->mpls_lm_dm_sess_id_ep_id[session_id] = h_data_p->ep_id; 29500 29501 /* Set the packet type in hash data */ 29502 h_data_p->lm_dm_int_flag |= SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DM; 29503 h_data_p->lm_dm_int_flag |= SHR_MPLS_LM_DM_FLAG_DELAY_ADDED; 29504 29505 delay_p->pm_id = h_data_p->lm_dm_uc_session_id; 29506 29507 return rv; 29508 } 29509 29510 STATIC int 29511 _bcm_sb2_mpls_lm_dm_delay_delete(int unit, _bcm_oam_hash_data_t *h_data_p) 29512 { 29513 _bcm_oam_control_t *oc = NULL; 29514 uint8 *buffer_p = NULL; 29515 uint8 *buffer_after_pack_p = NULL; 29516 uint16 buffer_len = 0; 29517 uint16 reply_len = 0; 29518 shr_mpls_lm_dm_msg_ctrl_delay_delete_t delay_del_msg; 29519 int rv = 0; 29520 29521 /* Get OAM control pointer */ 29522 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 29523 29524 /* uKernel ready check*/ 29525 if (!oc->mpls_lm_dm_ukernel_ready) { 29526 rv = BCM_E_INIT; 29527 return rv; 29528 29529 } 29530 29531 /* Validation Checks */ 29532 /* ----------------- */ 29533 /* Check if the DM is enabled for this EP */ 29534 if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) { 29535 return BCM_E_NOT_FOUND; 29536 } 29537 29538 /* Initialize the Message structure */ 29539 sal_memset(&delay_del_msg, 0, sizeof(delay_del_msg)); 29540 delay_del_msg.sess_id = h_data_p->lm_dm_uc_session_id; 29541 29542 /* Send Delay del message */ 29543 /* ---------------------- */ 29544 buffer_p = oc->mpls_lm_dm_dma_buffer; 29545 buffer_after_pack_p = shr_mpls_lm_dm_msg_ctrl_delay_delete_pack(buffer_p, 29546 &delay_del_msg); 29547 buffer_len = buffer_after_pack_p - buffer_p; 29548 29549 rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit, 29550 MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_DELETE, buffer_len, 0, 29551 MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_DELETE_REPLY, 29552 &reply_len); 29553 29554 if (BCM_FAILURE(rv)|| (reply_len != 0)) { 29555 return (rv); 29556 } 29557 29558 /* Clear the packet type in hash data */ 29559 h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DM); 29560 h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_DELAY_ADDED); 29561 29562 if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED)) { 29563 h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED); 29564 } 29565 29566 /* Free the session Id in hash data */ 29567 if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED)) { 29568 shr_idxres_list_free(oc->mpls_lm_dm_pool, 29569 (shr_idxres_element_t)h_data_p->lm_dm_uc_session_id); 29570 oc->mpls_lm_dm_sess_id_ep_id[h_data_p->lm_dm_uc_session_id] = 0; 29571 h_data_p->lm_dm_uc_session_id = 0; 29572 soc_mem_field32_modify(unit, MA_INDEXm, h_data_p->ma_base_index, 29573 MA_PTRf, 0); 29574 } 29575 29576 return rv; 29577 } 29578 29579 STATIC int 29580 _bcm_sb2_mpls_lm_dm_loss_delete(int unit, _bcm_oam_hash_data_t *h_data_p) 29581 { 29582 _bcm_oam_control_t *oc = NULL; 29583 uint8 *buffer_p = NULL; 29584 uint8 *buffer_after_pack_p = NULL; 29585 uint16 buffer_len = 0; 29586 uint16 reply_len = 0; 29587 shr_mpls_lm_dm_msg_ctrl_loss_delete_t loss_del_msg; 29588 int rv = 0; 29589 29590 /* Get OAM control pointer */ 29591 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 29592 29593 /* uKernel ready check*/ 29594 if (!oc->mpls_lm_dm_ukernel_ready) { 29595 rv = BCM_E_INIT; 29596 return rv; 29597 29598 } 29599 29600 /* Validation Checks */ 29601 /* ----------------- */ 29602 /* Check if the LM is enabled for this EP */ 29603 if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED)) { 29604 return BCM_E_NOT_FOUND; 29605 } 29606 29607 /* Initialize the Message structure */ 29608 sal_memset(&loss_del_msg, 0, sizeof(loss_del_msg)); 29609 loss_del_msg.sess_id = h_data_p->lm_dm_uc_session_id; 29610 29611 /* Send Delay del message */ 29612 /* ---------------------- */ 29613 buffer_p = oc->mpls_lm_dm_dma_buffer; 29614 buffer_after_pack_p = shr_mpls_lm_dm_msg_ctrl_loss_delete_pack(buffer_p, 29615 &loss_del_msg); 29616 buffer_len = buffer_after_pack_p - buffer_p; 29617 29618 rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit, 29619 MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_DELETE, buffer_len, 0, 29620 MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_DELETE_REPLY, 29621 &reply_len); 29622 29623 if (BCM_FAILURE(rv)|| (reply_len != 0)) { 29624 return (rv); 29625 } 29626 29627 /* Clear the packet type in hash data (if set) */ 29628 h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM); 29629 h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM); 29630 h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_DLM_DM); 29631 h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM_DM); 29632 h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_LOSS_ADDED); 29633 29634 if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) { 29635 h_data_p->lm_dm_int_flag &= ~(SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED); 29636 } 29637 29638 /* Free the session Id in hash data */ 29639 if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) { 29640 shr_idxres_list_free(oc->mpls_lm_dm_pool, 29641 (shr_idxres_element_t)h_data_p->lm_dm_uc_session_id); 29642 oc->mpls_lm_dm_sess_id_ep_id[h_data_p->lm_dm_uc_session_id] = 0; 29643 h_data_p->lm_dm_uc_session_id = 0; 29644 soc_mem_field32_modify(unit, MA_INDEXm, h_data_p->ma_base_index, 29645 MA_PTRf, 0); 29646 } 29647 29648 return rv; 29649 } 29650 29651 STATIC int 29652 _bcm_sb2_mpls_lm_dm_loss_get(int unit, _bcm_oam_hash_data_t *h_data_p, 29653 bcm_oam_loss_t *loss_p) 29654 { 29655 _bcm_oam_control_t *oc = NULL; 29656 uint8 *buffer_p = NULL; 29657 uint8 *buffer_after_pack_p = NULL; 29658 uint16 buffer_len = 0; 29659 uint16 reply_len = 0; 29660 shr_mpls_lm_dm_msg_ctrl_loss_get_t loss_get_req; 29661 shr_mpls_lm_dm_msg_ctrl_loss_data_t loss_get_rsp; 29662 int rv = 0; 29663 int i = 0; 29664 29665 /* Get OAM control pointer */ 29666 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 29667 29668 /* Validation Checks */ 29669 /* ----------------- */ 29670 /* Check if the LM is enabled for this EP */ 29671 if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_LOSS_ADDED)) { 29672 return BCM_E_NOT_FOUND; 29673 } 29674 29675 sal_memset(&loss_get_req, 0, sizeof(loss_get_req)); 29676 loss_get_req.sess_id = h_data_p->lm_dm_uc_session_id; 29677 29678 buffer_p = oc->mpls_lm_dm_dma_buffer; 29679 buffer_after_pack_p = shr_mpls_lm_dm_msg_ctrl_loss_get_pack(buffer_p, 29680 &loss_get_req); 29681 buffer_len = buffer_after_pack_p - buffer_p; 29682 29683 /* Send Loss GET request */ 29684 rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit, 29685 MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_GET, buffer_len, 0, 29686 MOS_MSG_SUBCLASS_MPLS_LM_DM_LOSS_MEASUREMENT_GET_REPLY, 29687 &reply_len); 29688 29689 if (BCM_FAILURE(rv)) { 29690 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:" 29691 " Loss get Msg failed EP:%d %s.\n"), unit, h_data_p->ep_id, 29692 bcm_errmsg(rv))); 29693 return (rv); 29694 } 29695 29696 29697 /* Initialize the receive Message structure */ 29698 sal_memset(&loss_get_rsp, 0, sizeof(loss_get_rsp)); 29699 29700 /* Unpack loss get data */ 29701 /* ---------------------- */ 29702 buffer_p = oc->mpls_lm_dm_dma_buffer; 29703 buffer_after_pack_p = shr_mpls_lm_dm_msg_ctrl_loss_data_unpack(buffer_p, 29704 &loss_get_rsp); 29705 buffer_len = buffer_after_pack_p - buffer_p; 29706 29707 if (reply_len != buffer_len) { 29708 rv = BCM_E_INTERNAL; 29709 } 29710 29711 if (loss_get_rsp.flags & (SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM_DM | 29712 SHR_MPLS_LM_DM_FLAG_PKT_TYPE_ILM ) ) { 29713 loss_p->flags |= BCM_OAM_LOSS_SLM; 29714 } 29715 if (!(loss_get_rsp.flags & SHR_MPLS_LM_DM_PASSIVE_FLAG)) { 29716 loss_p->flags |= BCM_OAM_LOSS_TX_ENABLE; 29717 29718 } 29719 if (loss_get_rsp.flags & SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG) { 29720 loss_p->flags |= BCM_OAM_LOSS_SINGLE_ENDED; 29721 } 29722 if (loss_get_rsp.flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED) { 29723 loss_p->flags |= BCM_OAM_COMBINED_LOSS_DELAY; 29724 } 29725 29726 loss_p->period = loss_get_rsp.period; 29727 loss_p->loss_threshold = loss_get_rsp.loss_threshold; 29728 loss_p->rx_oam_packets = loss_get_rsp.rx_oam_packets; 29729 loss_p->tx_oam_packets = loss_get_rsp.tx_oam_packets; 29730 loss_p->int_pri = loss_get_rsp.int_pri; 29731 loss_p->pkt_pri = loss_get_rsp.pkt_pri; 29732 29733 loss_p->lm_counter_size = loss_get_rsp.ctr_size; 29734 29735 for (i=0; i<loss_p->lm_counter_size; i++) { 29736 loss_p->lm_counter_base_id[i] = loss_get_rsp.ctr_base_id[i]; 29737 loss_p->lm_counter_offset[i] = loss_get_rsp.ctr_offset[i]; 29738 loss_p->lm_counter_action[i] = loss_get_rsp.ctr_action[i]; 29739 loss_p->lm_counter_byte_offset[i] = loss_get_rsp.ctr_byte_offset[i]; 29740 } 29741 29742 if (loss_get_rsp.flags & SHR_MPLS_LM_DM_BYTE_COUNT_FLAG) { 29743 loss_p->loss_nearend_byte = loss_get_rsp.loss_nearend; 29744 loss_p->loss_farend_byte = loss_get_rsp.loss_farend; 29745 loss_p->tx_nearend_byte = loss_get_rsp.tx_nearend; 29746 loss_p->rx_nearend_byte = loss_get_rsp.rx_nearend; 29747 loss_p->tx_farend_byte = loss_get_rsp.tx_farend; 29748 loss_p->rx_farend_byte = loss_get_rsp.rx_farend; 29749 if (loss_get_rsp.flags & SHR_MPLS_LM_DM_64_BIT_FLAG) { 29750 loss_p->loss_nearend_byte_upper = loss_get_rsp.loss_nearend_upper; 29751 loss_p->loss_farend_byte_upper = loss_get_rsp.loss_farend_upper; 29752 loss_p->tx_nearend_byte_upper = loss_get_rsp.tx_nearend_upper; 29753 loss_p->rx_nearend_byte_upper = loss_get_rsp.rx_nearend_upper; 29754 loss_p->tx_farend_byte_upper = loss_get_rsp.tx_farend_upper; 29755 loss_p->rx_farend_byte_upper = loss_get_rsp.rx_farend_upper; 29756 } 29757 } else { 29758 loss_p->loss_nearend = loss_get_rsp.loss_nearend; 29759 loss_p->loss_farend = loss_get_rsp.loss_farend; 29760 loss_p->tx_nearend = loss_get_rsp.tx_nearend; 29761 loss_p->rx_nearend = loss_get_rsp.rx_nearend; 29762 loss_p->tx_farend = loss_get_rsp.tx_farend; 29763 loss_p->rx_farend = loss_get_rsp.rx_farend; 29764 } 29765 loss_p->pm_id = h_data_p->lm_dm_uc_session_id; 29766 29767 return rv; 29768 } 29769 29770 STATIC int 29771 _bcm_sb2_mpls_lm_dm_delay_get(int unit, _bcm_oam_hash_data_t *h_data_p, 29772 bcm_oam_delay_t *delay_p) 29773 { 29774 _bcm_oam_control_t *oc = NULL; 29775 uint8 *buffer_p = NULL; 29776 uint8 *buffer_after_pack_p = NULL; 29777 uint16 buffer_len = 0; 29778 uint16 reply_len = 0; 29779 shr_mpls_lm_dm_msg_ctrl_delay_get_t delay_get_req; 29780 mpls_lm_dm_sdk_msg_ctrl_delay_data_t delay_get_rsp; 29781 int rv = 0; 29782 29783 /* Get OAM control pointer */ 29784 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 29785 29786 /* Validation Checks */ 29787 /* ----------------- */ 29788 /* Check if the LM is enabled for this EP */ 29789 if (!(h_data_p->lm_dm_int_flag & SHR_MPLS_LM_DM_FLAG_DELAY_ADDED)) { 29790 return BCM_E_NOT_FOUND; 29791 } 29792 29793 sal_memset(&delay_get_req, 0, sizeof(delay_get_req)); 29794 delay_get_req.sess_id = h_data_p->lm_dm_uc_session_id; 29795 29796 buffer_p = oc->mpls_lm_dm_dma_buffer; 29797 buffer_after_pack_p = shr_mpls_lm_dm_msg_ctrl_delay_get_pack(buffer_p, 29798 &delay_get_req); 29799 buffer_len = buffer_after_pack_p - buffer_p; 29800 29801 /* Send Loss GET request */ 29802 rv = _bcm_sb2_oam_mpls_lm_dm_msg_send_receive(unit, 29803 MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_GET, buffer_len, 0, 29804 MOS_MSG_SUBCLASS_MPLS_LM_DM_DELAY_MEASUREMENT_GET_REPLY, 29805 &reply_len); 29806 29807 if (BCM_FAILURE(rv)) { 29808 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "MPLS_LM_DM (unit %d) Error:" 29809 " Loss get Msg failed EP:%d %s.\n"), unit, h_data_p->ep_id, 29810 bcm_errmsg(rv))); 29811 return (rv); 29812 } 29813 29814 29815 /* Initialize the receive Message structure */ 29816 sal_memset(&delay_get_rsp, 0, sizeof(delay_get_rsp)); 29817 29818 /* Unpack delay get data */ 29819 /* ---------------------- */ 29820 buffer_p = oc->mpls_lm_dm_dma_buffer; 29821 buffer_after_pack_p = mpls_lm_dm_sdk_msg_ctrl_delay_data_unpack(buffer_p, 29822 &delay_get_rsp); 29823 buffer_len = buffer_after_pack_p - buffer_p; 29824 29825 if (reply_len != buffer_len) { 29826 rv = BCM_E_INTERNAL; 29827 } 29828 29829 if (delay_get_rsp.flags & SHR_MPLS_LM_DM_FLAG_PKT_TYPE_COMBINED) { 29830 delay_p->flags |= BCM_OAM_COMBINED_LOSS_DELAY; 29831 } else { 29832 if (!(delay_get_rsp.flags & SHR_MPLS_LM_DM_PASSIVE_FLAG)) { 29833 delay_p->flags |= BCM_OAM_DELAY_TX_ENABLE; 29834 } 29835 if (!(delay_get_rsp.flags & SHR_MPLS_LM_DM_SINGLE_ENDED_FLAG)) { 29836 delay_p->flags |= BCM_OAM_DELAY_ONE_WAY; 29837 } 29838 } 29839 29840 delay_p->period = delay_get_rsp.period; 29841 delay_p->timestamp_format = delay_get_rsp.dm_format; 29842 rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->delay), 29843 delay_get_rsp.delay_seconds, delay_get_rsp.delay_nanoseconds); 29844 if(BCM_SUCCESS(rv)) { 29845 rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->txf), 29846 delay_get_rsp.txf_seconds, delay_get_rsp.txf_nanoseconds); 29847 } 29848 if(BCM_SUCCESS(rv)) { 29849 rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->rxf), 29850 delay_get_rsp.rxf_seconds, delay_get_rsp.rxf_nanoseconds); 29851 } 29852 if(BCM_SUCCESS(rv)) { 29853 rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->txb), 29854 delay_get_rsp.txb_seconds, delay_get_rsp.txb_nanoseconds); 29855 } 29856 if(BCM_SUCCESS(rv)) { 29857 rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->rxb), 29858 delay_get_rsp.rxb_seconds, delay_get_rsp.rxb_nanoseconds); 29859 } 29860 delay_p->rx_oam_packets = delay_get_rsp.rx_oam_packets; 29861 delay_p->tx_oam_packets = delay_get_rsp.tx_oam_packets; 29862 delay_p->int_pri = delay_get_rsp.int_pri; 29863 delay_p->pkt_pri = delay_get_rsp.pkt_pri; 29864 29865 delay_p->pm_id = h_data_p->lm_dm_uc_session_id; 29866 29867 if (BCM_FAILURE(_bcm_sb2_oam_olp_tx_header_decap(unit, 29868 delay_get_rsp.olp_tx_hdr, 29869 &delay_p->dm_tx_update_lm_counter_size, 29870 delay_p->dm_tx_update_lm_counter_base_id, 29871 delay_p->dm_tx_update_lm_counter_offset, 29872 NULL, 29873 delay_p->dm_tx_update_lm_counter_byte_offset, 29874 NULL, 29875 NULL, 29876 NULL))) { 29877 _BCM_OAM_UNLOCK(oc); 29878 return (BCM_E_INTERNAL); 29879 } 29880 29881 return rv; 29882 } 29883 29884 /* 29885 * Function: 29886 * _bcm_sb2_oam_mpls_lm_dm_appl_callback 29887 * Purpose: 29888 * Update FW MPLS LM/DM appl state 29889 * Parameters: 29890 * unit - (IN) Unit number. 29891 * uC - (IN) core number. 29892 * stage - (IN) core reset stage. 29893 * user_data - (IN) data pointer. 29894 * Returns: 29895 * BCM_E_XXX 29896 * Notes: 29897 */ 29898 29899 int _bcm_sb2_oam_mpls_lm_dm_appl_callback(int unit, 29900 int uC, 29901 soc_cmic_uc_shutdown_stage_t stage, 29902 void *user_data) { 29903 _bcm_oam_control_t *oc; 29904 29905 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 29906 _BCM_OAM_LOCK(oc); 29907 oc->mpls_lm_dm_ukernel_ready = 0; 29908 29909 _BCM_OAM_UNLOCK(oc); 29910 29911 return BCM_E_NONE; 29912 } 29913 29914 /* 29915 * Function: 29916 * _bcm_sb2_mpls_lm_dm_event_mask_set 29917 * Purpose: 29918 * Set the MPLS_LM_DM Events mask. 29919 * Events are set per BHH module. 29920 * Parameters: 29921 * unit - (IN) Unit number. 29922 * Returns: 29923 * BCM_E_NONE Operation completed successfully 29924 * BCM_E_XXX Operation failed 29925 * Notes: 29926 */ 29927 STATIC int 29928 _bcm_sb2_mpls_lm_dm_event_mask_set(int unit) 29929 { 29930 _bcm_oam_control_t *oc; 29931 _bcm_oam_event_handler_t *event_handler_p; 29932 uint16 reply_len; 29933 int rv = BCM_E_NONE; 29934 29935 /* Lock already taken by the calling routine. */ 29936 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 29937 29938 /* Get event mask from all callbacks */ 29939 for (event_handler_p = oc->event_handler_list_p; 29940 event_handler_p != NULL; 29941 event_handler_p = event_handler_p->next_p) { 29942 29943 /* Update MPLS_LM_DM event mask in uKernel */ 29944 if (SHR_BITGET(event_handler_p->event_types.w, 29945 bcmOAMEventMplsLmDmPmCounterRollover)) { 29946 /* Send MPLS_LM_DM Event Mask message to uC */ 29947 rv = _bcm_sb2_oam_pm_msg_send_receive(unit, 29948 MOS_MSG_CLASS_MPLS_LM_DM, 29949 MOS_MSG_SUBCLASS_MPLS_LM_DM_EVENT_MASK_SET, 29950 0, MPLS_LM_DM_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER, 29951 MOS_MSG_SUBCLASS_MPLS_LM_DM_EVENT_MASK_SET_REPLY, 29952 &reply_len); 29953 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 29954 rv = BCM_E_INTERNAL; 29955 } 29956 return (rv); 29957 } 29958 } 29959 return (rv); 29960 } 29961 #endif /*(INCLUDE_MPLS_LM_DM) */ 29962 29963 29964 29965 #if defined(INCLUDE_BHH) 29966 /* 29967 * Function: 29968 * _bcm_sb2_oam_bhh_msg_send_receive 29969 * Purpose: 29970 * Sends given BHH control message to the uController. 29971 * Receives and verifies expected reply. 29972 * Performs DMA operation if required. 29973 * Parameters: 29974 * unit - (IN) Unit number. 29975 * s_subclass - (IN) BHH message subclass. 29976 * s_len - (IN) Value for 'len' field in message struct. 29977 * Length of buffer to flush if DMA send is required. 29978 * s_data - (IN) Value for 'data' field in message struct. 29979 * Ignored if message requires a DMA send/receive 29980 * operation. 29981 * r_subclass - (IN) Expected reply message subclass. 29982 * r_len - (OUT) Returns value in 'len' reply message field. 29983 * Returns: 29984 * BCM_E_XXX 29985 * Notes: 29986 * - The uc_msg 'len' and 'data' fields of mos_msg_data_t 29987 * can take any arbitrary data. 29988 * 29989 * BHH Long Control message: 29990 * - BHH control messages that require send/receive of information 29991 * that cannot fit in the uc_msg 'len' and 'data' fields need to 29992 * use DMA operations to exchange information (long control message). 29993 * 29994 * - BHH convention for long control messages for 29995 * 'mos_msg_data_t' fields: 29996 * 'len' size of the DMA buffer to send to uController 29997 * 'data' physical DMA memory address to send or receive 29998 * 29999 * DMA Operations: 30000 * - DMA read/write operation is performed when a long BHH control 30001 * message is involved. 30002 * 30003 * - Messages that require DMA operation (long control message) 30004 * is indicated by MOS_MSG_DMA_MSG(). 30005 * 30006 * - Callers must 'pack' and 'unpack' corresponding information 30007 * into/from DMA buffer indicated by BHH_INFO(unit)->dma_buffer. 30008 */ 30009 STATIC int 30010 _bcm_sb2_oam_bhh_msg_send_receive(int unit, uint8 s_subclass, 30011 uint16 s_len, uint32 s_data, 30012 uint8 r_subclass, uint16 *r_len) 30013 { 30014 int rv; 30015 _bcm_oam_control_t *oc; 30016 mos_msg_data_t send, reply; 30017 uint8 *dma_buffer; 30018 int dma_buffer_len; 30019 uint32 uc_rv; 30020 30021 /* Lock already taken by the calling routine. */ 30022 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 30023 30024 sal_memset(&send, 0, sizeof(send)); 30025 sal_memset(&reply, 0, sizeof(reply)); 30026 send.s.mclass = MOS_MSG_CLASS_BHH; 30027 send.s.subclass = s_subclass; 30028 send.s.len = bcm_htons(s_len); 30029 30030 /* 30031 * Set 'data' to DMA buffer address if a DMA operation is 30032 * required for send or receive. 30033 */ 30034 dma_buffer = oc->dma_buffer; 30035 dma_buffer_len = oc->dma_buffer_len; 30036 if (MOS_MSG_DMA_MSG(s_subclass) || 30037 MOS_MSG_DMA_MSG(r_subclass)) { 30038 send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer)); 30039 } else { 30040 send.s.data = bcm_htonl(s_data); 30041 } 30042 30043 /* Flush DMA memory */ 30044 if (MOS_MSG_DMA_MSG(s_subclass)) { 30045 soc_cm_sflush(unit, dma_buffer, s_len); 30046 } 30047 30048 /* Invalidate DMA memory to read */ 30049 if (MOS_MSG_DMA_MSG(r_subclass)) { 30050 soc_cm_sinval(unit, dma_buffer, dma_buffer_len); 30051 } 30052 30053 rv = soc_cmic_uc_msg_send_receive(unit, oc->uc_num, 30054 &send, &reply, 30055 _BHH_UC_MSG_TIMEOUT_USECS); 30056 30057 /* Check reply class, subclass */ 30058 if (rv != SOC_E_NONE) { 30059 return (BCM_E_INTERNAL); 30060 } 30061 30062 /* Convert BHH uController error code to BCM */ 30063 uc_rv = bcm_ntohl(reply.s.data); 30064 switch(uc_rv) { 30065 case SHR_BHH_UC_E_NONE: 30066 rv = BCM_E_NONE; 30067 break; 30068 case SHR_BHH_UC_E_INTERNAL: 30069 rv = BCM_E_INTERNAL; 30070 break; 30071 case SHR_BHH_UC_E_MEMORY: 30072 rv = BCM_E_MEMORY; 30073 break; 30074 case SHR_BHH_UC_E_PARAM: 30075 rv = BCM_E_PARAM; 30076 break; 30077 case SHR_BHH_UC_E_RESOURCE: 30078 rv = BCM_E_RESOURCE; 30079 break; 30080 case SHR_BHH_UC_E_EXISTS: 30081 rv = BCM_E_EXISTS; 30082 break; 30083 case SHR_BHH_UC_E_NOT_FOUND: 30084 rv = BCM_E_NOT_FOUND; 30085 break; 30086 case SHR_BHH_UC_E_INIT: 30087 rv = BCM_E_INIT; 30088 break; 30089 case SHR_BHH_UC_E_UNAVAIL: 30090 rv = BCM_E_UNAVAIL; 30091 break; 30092 default: 30093 rv = BCM_E_INTERNAL; 30094 break; 30095 } 30096 30097 *r_len = bcm_ntohs(reply.s.len); 30098 /*Check reply class and subclass*/ 30099 if((rv == SOC_E_NONE) && ((reply.s.mclass != MOS_MSG_CLASS_BHH) || 30100 (reply.s.subclass != r_subclass))) 30101 { 30102 return BCM_E_INTERNAL; 30103 } 30104 30105 return (rv); 30106 } 30107 #endif /*(INCLUDE_BHH) */ 30108 30109 #if defined(INCLUDE_ETH_LM_DM) 30110 /* 30111 * Function: 30112 * _bcm_sb2_oam_eth_lm_dm_msg_send_receive 30113 * Purpose: 30114 * Sends given ETH_LM_DM control message to the uController. 30115 * Receives and verifies expected reply. 30116 * Performs DMA operation if required. 30117 * Parameters: 30118 * unit - (IN) Unit number. 30119 * s_subclass - (IN) BHH message subclass. 30120 * s_len - (IN) Value for 'len' field in message struct. 30121 * Length of buffer to flush if DMA send is required. 30122 * s_data - (IN) Value for 'data' field in message struct. 30123 * Ignored if message requires a DMA send/receive 30124 * operation. 30125 * r_subclass - (IN) Expected reply message subclass. 30126 * r_len - (OUT) Returns value in 'len' reply message field. 30127 * Returns: 30128 * BCM_E_XXX 30129 * Notes: 30130 * - The uc_msg 'len' and 'data' fields of mos_msg_data_t 30131 * can take any arbitrary data. 30132 * 30133 * ETH_LM_DM Long Control message: 30134 * - ETH_LM_DM control messages that require send/receive of information 30135 * that cannot fit in the uc_msg 'len' and 'data' fields need to 30136 * use DMA operations to exchange information (long control message). 30137 * 30138 * - ETH_LM_DM convention for long control messages for 30139 * 'mos_msg_data_t' fields: 30140 * 'len' size of the DMA buffer to send to uController 30141 * 'data' physical DMA memory address to send or receive 30142 * 30143 * DMA Operations: 30144 * - DMA read/write operation is performed when a long ETH_LM_DM control 30145 * message is involved. 30146 * 30147 * - Messages that require DMA operation (long control message) 30148 * is indicated by MOS_MSG_DMA_MSG(). 30149 * 30150 * - Callers must 'pack' and 'unpack' corresponding information 30151 * into/from DMA buffer indicated by BHH_INFO(unit)->dma_buffer. 30152 */ 30153 STATIC int 30154 _bcm_sb2_oam_eth_lm_dm_msg_send_receive(int unit, uint8 s_subclass, 30155 uint16 s_len, uint32 s_data, 30156 uint8 r_subclass, uint16 *r_len) 30157 { 30158 int rv; 30159 _bcm_oam_control_t *oc; 30160 mos_msg_data_t send, reply; 30161 uint8 *dma_buffer; 30162 int dma_buffer_len; 30163 uint32 uc_rv; 30164 30165 /* Lock already taken by the calling routine. */ 30166 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 30167 30168 sal_memset(&send, 0, sizeof(send)); 30169 sal_memset(&reply, 0, sizeof(reply)); 30170 send.s.mclass = MOS_MSG_CLASS_ETH_LM_DM; 30171 send.s.subclass = s_subclass; 30172 send.s.len = bcm_htons(s_len); 30173 30174 /* 30175 * Set 'data' to DMA buffer address if a DMA operation is 30176 * required for send or receive. 30177 */ 30178 dma_buffer = oc->eth_lm_dm_dma_buffer; 30179 dma_buffer_len = oc->eth_lm_dm_dma_buffer_len; 30180 if (MOS_MSG_DMA_MSG(s_subclass) || 30181 MOS_MSG_DMA_MSG(r_subclass)) { 30182 send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer)); 30183 } else { 30184 send.s.data = bcm_htonl(s_data); 30185 } 30186 30187 /* Flush DMA memory */ 30188 if (MOS_MSG_DMA_MSG(s_subclass)) { 30189 soc_cm_sflush(unit, dma_buffer, s_len); 30190 } 30191 30192 /* Invalidate DMA memory to read */ 30193 if (MOS_MSG_DMA_MSG(r_subclass)) { 30194 soc_cm_sinval(unit, dma_buffer, dma_buffer_len); 30195 } 30196 30197 rv = soc_cmic_uc_msg_send_receive(unit, oc->eth_lm_dm_uc_num, 30198 &send, &reply, 30199 _ETH_LM_DM_UC_MSG_TIMEOUT_USECS); 30200 30201 /* Check reply class, subclass */ 30202 if ((rv != SOC_E_NONE) || 30203 (reply.s.mclass != MOS_MSG_CLASS_ETH_LM_DM) || 30204 (reply.s.subclass != r_subclass)) { 30205 return (BCM_E_INTERNAL); 30206 } 30207 30208 /* Convert ETH_LM_DM uController error code to BCM */ 30209 uc_rv = bcm_ntohl(reply.s.data); 30210 switch(uc_rv) { 30211 case SHR_ETH_LM_DM_UC_E_NONE: 30212 rv = BCM_E_NONE; 30213 break; 30214 case SHR_ETH_LM_DM_UC_E_INTERNAL: 30215 rv = BCM_E_INTERNAL; 30216 break; 30217 case SHR_ETH_LM_DM_UC_E_MEMORY: 30218 rv = BCM_E_MEMORY; 30219 break; 30220 case SHR_ETH_LM_DM_UC_E_PARAM: 30221 rv = BCM_E_PARAM; 30222 break; 30223 case SHR_ETH_LM_DM_UC_E_RESOURCE: 30224 rv = BCM_E_RESOURCE; 30225 break; 30226 case SHR_ETH_LM_DM_UC_E_EXISTS: 30227 rv = BCM_E_EXISTS; 30228 break; 30229 case SHR_ETH_LM_DM_UC_E_NOT_FOUND: 30230 rv = BCM_E_NOT_FOUND; 30231 break; 30232 case SHR_ETH_LM_DM_UC_E_INIT: 30233 rv = BCM_E_INIT; 30234 break; 30235 default: 30236 rv = BCM_E_INTERNAL; 30237 break; 30238 } 30239 30240 *r_len = bcm_ntohs(reply.s.len); 30241 30242 return (rv); 30243 } 30244 30245 /* 30246 * Function: 30247 * _bcm_sb2_eth_lm_dm_event_mask_set 30248 * Purpose: 30249 * Set the ETH_LM_DM Events mask. 30250 * Events are set per BHH module. 30251 * Parameters: 30252 * unit - (IN) Unit number. 30253 * Returns: 30254 * BCM_E_NONE Operation completed successfully 30255 * BCM_E_XXX Operation failed 30256 * Notes: 30257 */ 30258 STATIC int 30259 _bcm_sb2_eth_lm_dm_event_mask_set(int unit) 30260 { 30261 _bcm_oam_control_t *oc; 30262 _bcm_oam_event_handler_t *event_handler_p; 30263 uint16 reply_len; 30264 int rv = BCM_E_NONE; 30265 30266 /* Lock already taken by the calling routine. */ 30267 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 30268 30269 /* Get event mask from all callbacks */ 30270 for (event_handler_p = oc->event_handler_list_p; 30271 event_handler_p != NULL; 30272 event_handler_p = event_handler_p->next_p) { 30273 30274 /* Update ETH_LM_DM event mask in uKernel */ 30275 if (SHR_BITGET(event_handler_p->event_types.w, 30276 bcmOAMEventEthLmDmPmCounterRollover)) { 30277 /* Send ETH_LM_DM Event Mask message to uC */ 30278 rv = _bcm_sb2_oam_pm_msg_send_receive (unit, 30279 MOS_MSG_CLASS_ETH_LM_DM, 30280 MOS_MSG_SUBCLASS_ETH_LM_DM_EVENT_MASK_SET, 30281 0, ETH_LM_DM_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER, 30282 MOS_MSG_SUBCLASS_ETH_LM_DM_EVENT_MASK_SET_REPLY, 30283 &reply_len); 30284 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 30285 rv = BCM_E_INTERNAL; 30286 } 30287 return (rv); 30288 } 30289 } 30290 return (rv); 30291 } 30292 30293 #endif /*(INCLUDE_ETH_LM_DM) */ 30294 30295 30296 #if defined(INCLUDE_BHH) 30297 /* 30298 * Function: 30299 * _bcm_sb2_oam_bhh_callback_thread 30300 * Purpose: 30301 * Thread to listen for event messages from uController. 30302 * Parameters: 30303 * param - Pointer to BFD info structure. 30304 * Returns: 30305 * None 30306 */ 30307 STATIC void 30308 _bcm_sb2_oam_bhh_callback_thread(void *param) 30309 { 30310 int rv; 30311 _bcm_oam_control_t *oc = (_bcm_oam_control_t *)param; 30312 bcm_oam_event_types_t events; 30313 bcm_oam_event_type_t event_type; 30314 bhh_msg_event_t event_msg; 30315 int sess_id; 30316 uint32 event_mask; 30317 _bcm_oam_event_handler_t *event_handler_p; 30318 _bcm_oam_hash_data_t *h_data_p; 30319 int ep_id = 0; 30320 char thread_name[SAL_THREAD_NAME_MAX_LEN]; 30321 uint8 msg_subclass = 0; 30322 30323 thread_name[0] = 0; 30324 sal_thread_name(oc->event_thread_id, thread_name, sizeof (thread_name)); 30325 30326 while (1) { 30327 /* Wait on notifications from uController */ 30328 rv = soc_cmic_uc_msg_receive(oc->unit, oc->uc_num, 30329 MOS_MSG_CLASS_BHH_EVENT, &event_msg, 30330 sal_sem_FOREVER); 30331 if (BCM_FAILURE(rv)) { 30332 break; /* Thread exit */ 30333 } 30334 30335 event_handler_p = oc->event_handler_list_p; 30336 /* Get data from event message */ 30337 sess_id = (int)bcm_ntohs(event_msg.s.len); 30338 ep_id = BCM_OAM_BHH_GET_SDK_EP(sess_id); 30339 30340 msg_subclass = event_msg.s.subclass; 30341 30342 if (msg_subclass == _BHH_EVENT_OAM_PM_EVENT) { 30343 /* Call PM message handling function and continue */ 30344 _bcm_sb2_oam_pm_event_msg_handle(oc, &event_msg); 30345 continue; 30346 } 30347 if (sess_id < 0 || 30348 sess_id >= oc->ep_count) { 30349 LOG_CLI((BSL_META_U(oc->unit, 30350 "%s: Invalid sess_id:%d \n"), FUNCTION_NAME(), sess_id)); 30351 continue; 30352 } 30353 30354 /* Check endpoint status. */ 30355 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 30356 if ((BCM_E_EXISTS != rv)) { 30357 /* Endpoint not in use. */ 30358 LOG_ERROR(BSL_LS_BCM_OAM, 30359 (BSL_META("OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 30360 oc->unit, ep_id, bcm_errmsg(rv))); 30361 continue; 30362 } 30363 h_data_p = &oc->oam_hash_data[ep_id]; 30364 event_mask = bcm_ntohl(event_msg.s.data); 30365 30366 /* Set events */ 30367 sal_memset(&events, 0, sizeof(events)); 30368 30369 if (event_mask & BHH_BTE_EVENT_LB_TIMEOUT) { 30370 LOG_DEBUG(BSL_LS_BCM_OAM, 30371 (BSL_META_U(oc->unit, 30372 "****** OAM BHH LB Timeout ******\n"))); 30373 30374 if (oc->event_handler_cnt[bcmOAMEventBHHLBTimeout] > 0) { 30375 SHR_BITSET(events.w, bcmOAMEventBHHLBTimeout); 30376 } 30377 } 30378 if (event_mask & BHH_BTE_EVENT_LB_DISCOVERY_UPDATE) { 30379 LOG_DEBUG(BSL_LS_BCM_OAM, 30380 (BSL_META_U(oc->unit, 30381 "****** OAM BHH LB Discovery Update ******\n"))); 30382 if (oc->event_handler_cnt[bcmOAMEventBHHLBDiscoveryUpdate] > 0) { 30383 SHR_BITSET(events.w, bcmOAMEventBHHLBDiscoveryUpdate); 30384 } 30385 } 30386 if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT) { 30387 LOG_DEBUG(BSL_LS_BCM_OAM, 30388 (BSL_META_U(oc->unit, 30389 "****** OAM BHH CCM Timeout ******\n"))); 30390 if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeout] > 0) { 30391 SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeout); 30392 } 30393 } 30394 if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR) { 30395 LOG_DEBUG(BSL_LS_BCM_OAM, 30396 (BSL_META_U(oc->unit, 30397 "****** OAM BHH CCM Timeout Clear ******\n"))); 30398 if (oc->event_handler_cnt[bcmOAMEventBHHCCMTimeoutClear] > 0) { 30399 SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeoutClear); 30400 } 30401 } 30402 if (event_mask & BHH_BTE_EVENT_STATE) { 30403 LOG_DEBUG(BSL_LS_BCM_OAM, 30404 (BSL_META_U(oc->unit, 30405 "****** OAM BHH State ******\n"))); 30406 if (oc->event_handler_cnt[bcmOAMEventBHHCCMState] > 0) { 30407 SHR_BITSET(events.w, bcmOAMEventBHHCCMState); 30408 } 30409 } 30410 if (event_mask & BHH_BTE_EVENT_CCM_RDI) { 30411 LOG_DEBUG(BSL_LS_BCM_OAM, 30412 (BSL_META_U(oc->unit, 30413 "****** OAM BHH CCM RDI ******\n"))); 30414 if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdi] > 0) { 30415 SHR_BITSET(events.w, bcmOAMEventBHHCCMRdi); 30416 } 30417 } 30418 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL) { 30419 LOG_DEBUG(BSL_LS_BCM_OAM, 30420 (BSL_META_U(oc->unit, 30421 "****** OAM BHH CCM Unknown MEG LEVEL ******\n"))); 30422 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevel] > 0) { 30423 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevel); 30424 } 30425 } 30426 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID) { 30427 LOG_DEBUG(BSL_LS_BCM_OAM, 30428 (BSL_META_U(oc->unit, 30429 "****** OAM BHH CCM Unknown MEG ID ******\n"))); 30430 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegId] > 0) { 30431 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegId); 30432 } 30433 } 30434 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID) { 30435 LOG_DEBUG(BSL_LS_BCM_OAM, 30436 (BSL_META_U(oc->unit, 30437 "****** OAM BHH CCM Unknown MEP ID ******\n"))); 30438 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepId] > 0) { 30439 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepId); 30440 } 30441 } 30442 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD) { 30443 LOG_DEBUG(BSL_LS_BCM_OAM, 30444 (BSL_META_U(oc->unit, 30445 "****** OAM BHH CCM Unknown Period ******\n"))); 30446 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriod] > 0) { 30447 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriod); 30448 } 30449 } 30450 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY) { 30451 LOG_DEBUG(BSL_LS_BCM_OAM, 30452 (BSL_META_U(oc->unit, 30453 "****** OAM BHH CCM Unknown Priority ******\n"))); 30454 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriority] > 0) { 30455 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriority); 30456 } 30457 } 30458 if (event_mask & BHH_BTE_EVENT_CCM_RDI_CLEAR) { 30459 LOG_DEBUG(BSL_LS_BCM_OAM, 30460 (BSL_META_U(oc->unit, 30461 "****** OAM BHH CCM RDI Clear ******\n"))); 30462 if (oc->event_handler_cnt[bcmOAMEventBHHCCMRdiClear] > 0) { 30463 SHR_BITSET(events.w, bcmOAMEventBHHCCMRdiClear); 30464 } 30465 } 30466 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR) { 30467 LOG_DEBUG(BSL_LS_BCM_OAM, 30468 (BSL_META_U(oc->unit, 30469 "****** OAM BHH CCM Unknown MEG Level Clear ******\n"))); 30470 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegLevelClear] > 0) { 30471 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevelClear); 30472 } 30473 } 30474 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR) { 30475 LOG_DEBUG(BSL_LS_BCM_OAM, 30476 (BSL_META_U(oc->unit, 30477 "****** OAM BHH CCM Unknown MEG ID Clear ******\n"))); 30478 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMegIdClear] > 0) { 30479 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegIdClear); 30480 } 30481 } 30482 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR) { 30483 LOG_DEBUG(BSL_LS_BCM_OAM, 30484 (BSL_META_U(oc->unit, 30485 "****** OAM BHH CCM Unknown MEP ID Clear ******\n"))); 30486 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownMepIdClear] > 0) { 30487 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepIdClear); 30488 } 30489 } 30490 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR) { 30491 LOG_DEBUG(BSL_LS_BCM_OAM, 30492 (BSL_META_U(oc->unit, 30493 "****** OAM BHH CCM Unknown Period Clear ******\n"))); 30494 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPeriodClear] > 0) { 30495 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriodClear); 30496 } 30497 } 30498 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR) { 30499 LOG_DEBUG(BSL_LS_BCM_OAM, 30500 (BSL_META_U(oc->unit, 30501 "****** OAM BHH CCM Unknown Priority Clear ******\n"))); 30502 if (oc->event_handler_cnt[bcmOAMEventBHHCCMUnknownPriorityClear] > 0) { 30503 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriorityClear); 30504 } 30505 } 30506 if (event_mask & BHH_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER) { 30507 LOG_DEBUG(BSL_LS_BCM_OAM, 30508 (BSL_META_U(oc->unit, 30509 "****** OAM PM BHH Counter Rollover ******\n"))); 30510 30511 if (oc->event_handler_cnt[bcmOAMEventBhhPmCounterRollover] > 0) { 30512 SHR_BITSET(events.w, bcmOAMEventBhhPmCounterRollover); 30513 } 30514 } 30515 if (event_mask & BHH_BTE_EVENT_CSF_LOS) { 30516 LOG_DEBUG(BSL_LS_BCM_OAM, 30517 (BSL_META_U(oc->unit, 30518 "****** OAM BHH CSF LOS ******\n"))); 30519 30520 if (oc->event_handler_cnt[bcmOAMEventCsfLos] > 0) { 30521 SHR_BITSET(events.w, bcmOAMEventCsfLos); 30522 } 30523 } 30524 if (event_mask & BHH_BTE_EVENT_CSF_FDI) { 30525 LOG_DEBUG(BSL_LS_BCM_OAM, 30526 (BSL_META_U(oc->unit, 30527 "****** OAM BHH CSF FDI ******\n"))); 30528 30529 if (oc->event_handler_cnt[bcmOAMEventCsfFdi] > 0) { 30530 SHR_BITSET(events.w, bcmOAMEventCsfFdi); 30531 } 30532 } 30533 if (event_mask & BHH_BTE_EVENT_CSF_RDI) { 30534 LOG_DEBUG(BSL_LS_BCM_OAM, 30535 (BSL_META_U(oc->unit, 30536 "****** OAM BHH CSF RDI ******\n"))); 30537 30538 if (oc->event_handler_cnt[bcmOAMEventCsfRdi] > 0) { 30539 SHR_BITSET(events.w, bcmOAMEventCsfRdi); 30540 } 30541 } 30542 if (event_mask & BHH_BTE_EVENT_CSF_DCI) { 30543 LOG_DEBUG(BSL_LS_BCM_OAM, 30544 (BSL_META_U(oc->unit, 30545 "****** OAM BHH CSF DCI ******\n"))); 30546 30547 if (oc->event_handler_cnt[bcmOAMEventCsfDci] > 0) { 30548 SHR_BITSET(events.w, bcmOAMEventCsfDci); 30549 } 30550 } 30551 /* Loop over registered callbacks, 30552 * If any match the events field, then invoke 30553 */ 30554 for (event_handler_p = oc->event_handler_list_p; 30555 event_handler_p != NULL; 30556 event_handler_p = event_handler_p->next_p) { 30557 for (event_type = bcmOAMEventBHHLBTimeout; event_type < bcmOAMEventCount; ++event_type) { 30558 if (SHR_BITGET(events.w, event_type)) { 30559 if (SHR_BITGET(event_handler_p->event_types.w, 30560 event_type)) { 30561 event_handler_p->cb(oc->unit, 30562 0, 30563 event_type, 30564 h_data_p->group_index, /* Group index */ 30565 ep_id, /* Endpoint index */ 30566 event_handler_p->user_data); 30567 } 30568 } 30569 } 30570 } 30571 } 30572 30573 oc->event_thread_id = NULL; 30574 LOG_VERBOSE(BSL_LS_BCM_OAM, 30575 (BSL_META_U(oc->unit, 30576 "Thread Exit:%s\n"), thread_name)); 30577 sal_thread_exit(0); 30578 } 30579 30580 /* BHH Event Handler */ 30581 typedef struct _event_handler_s { 30582 struct _event_handler_s *next; 30583 bcm_oam_event_types_t event_types; 30584 bcm_oam_event_cb cb; 30585 void *user_data; 30586 } _event_handler_t; 30587 30588 /* 30589 * Function: 30590 * _bcm_sb2_oam_bhh_event_mask_set 30591 * Purpose: 30592 * Set the BHH Events mask. 30593 * Events are set per BHH module. 30594 * Parameters: 30595 * unit - (IN) Unit number. 30596 * Returns: 30597 * BCM_E_NONE Operation completed successfully 30598 * BCM_E_XXX Operation failed 30599 * Notes: 30600 */ 30601 STATIC int 30602 _bcm_sb2_oam_bhh_event_mask_set(int unit) 30603 { 30604 _bcm_oam_control_t *oc; 30605 _bcm_oam_event_handler_t *event_handler_p; 30606 uint32 event_mask = 0; 30607 uint16 reply_len; 30608 int rv = BCM_E_NONE; 30609 30610 /* Lock already taken by the calling routine. */ 30611 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 30612 30613 /* Get event mask from all callbacks */ 30614 for (event_handler_p = oc->event_handler_list_p; 30615 event_handler_p != NULL; 30616 event_handler_p = event_handler_p->next_p) { 30617 30618 if (SHR_BITGET(event_handler_p->event_types.w, 30619 bcmOAMEventBHHLBTimeout)) { 30620 event_mask |= BHH_BTE_EVENT_LB_TIMEOUT; 30621 } 30622 if (SHR_BITGET(event_handler_p->event_types.w, 30623 bcmOAMEventBHHLBDiscoveryUpdate)) { 30624 event_mask |= BHH_BTE_EVENT_LB_DISCOVERY_UPDATE; 30625 } 30626 if (SHR_BITGET(event_handler_p->event_types.w, 30627 bcmOAMEventBHHCCMTimeout)) { 30628 event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT; 30629 } 30630 if (SHR_BITGET(event_handler_p->event_types.w, 30631 bcmOAMEventBHHCCMTimeoutClear)) { 30632 event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR; 30633 } 30634 if (SHR_BITGET(event_handler_p->event_types.w, 30635 bcmOAMEventBHHCCMState)) { 30636 event_mask |= BHH_BTE_EVENT_STATE; 30637 } 30638 if (SHR_BITGET(event_handler_p->event_types.w, 30639 bcmOAMEventBHHCCMRdi)) { 30640 event_mask |= BHH_BTE_EVENT_CCM_RDI; 30641 } 30642 if (SHR_BITGET(event_handler_p->event_types.w, 30643 bcmOAMEventBHHCCMUnknownMegLevel)) { 30644 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL; 30645 } 30646 if (SHR_BITGET(event_handler_p->event_types.w, 30647 bcmOAMEventBHHCCMUnknownMegId)) { 30648 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID; 30649 } 30650 if (SHR_BITGET(event_handler_p->event_types.w, 30651 bcmOAMEventBHHCCMUnknownMepId)) { 30652 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID; 30653 } 30654 if (SHR_BITGET(event_handler_p->event_types.w, 30655 bcmOAMEventBHHCCMUnknownPeriod)) { 30656 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD; 30657 } 30658 if (SHR_BITGET(event_handler_p->event_types.w, 30659 bcmOAMEventBHHCCMUnknownPriority)) { 30660 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY; 30661 } 30662 if (SHR_BITGET(event_handler_p->event_types.w, 30663 bcmOAMEventBHHCCMRdiClear)) { 30664 event_mask |= BHH_BTE_EVENT_CCM_RDI_CLEAR; 30665 } 30666 if (SHR_BITGET(event_handler_p->event_types.w, 30667 bcmOAMEventBHHCCMUnknownMegLevelClear)) { 30668 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR; 30669 } 30670 if (SHR_BITGET(event_handler_p->event_types.w, 30671 bcmOAMEventBHHCCMUnknownMegIdClear)) { 30672 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR; 30673 } 30674 if (SHR_BITGET(event_handler_p->event_types.w, 30675 bcmOAMEventBHHCCMUnknownMepIdClear)) { 30676 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR; 30677 } 30678 if (SHR_BITGET(event_handler_p->event_types.w, 30679 bcmOAMEventBHHCCMUnknownPeriodClear)) { 30680 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR; 30681 } 30682 if (SHR_BITGET(event_handler_p->event_types.w, 30683 bcmOAMEventBHHCCMUnknownPriorityClear)) { 30684 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR; 30685 } 30686 if (SHR_BITGET(event_handler_p->event_types.w, 30687 bcmOAMEventBhhPmCounterRollover)) { 30688 event_mask |= BHH_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER; 30689 } 30690 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfLos)) { 30691 event_mask |= BHH_BTE_EVENT_CSF_LOS; 30692 } 30693 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfFdi)) { 30694 event_mask |= BHH_BTE_EVENT_CSF_FDI; 30695 } 30696 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfRdi)) { 30697 event_mask |= BHH_BTE_EVENT_CSF_RDI; 30698 } 30699 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfDci)) { 30700 event_mask |= BHH_BTE_EVENT_CSF_DCI; 30701 } 30702 } 30703 30704 /* Update BHH event mask in uKernel */ 30705 if (event_mask != oc->event_mask) { 30706 /* Send BHH Event Mask message to uC */ 30707 rv = _bcm_sb2_oam_bhh_msg_send_receive 30708 (unit, 30709 MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET, 30710 0, event_mask, 30711 MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET_REPLY, 30712 &reply_len); 30713 30714 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 30715 rv = BCM_E_INTERNAL; 30716 } 30717 } 30718 30719 oc->event_mask = event_mask; 30720 30721 return (rv); 30722 } 30723 30724 /* 30725 * Function: 30726 * bcm_sb2_oam_loopback_add 30727 * Purpose: 30728 * 30729 * Parameters: 30730 * unit - Device unit number 30731 * Returns: 30732 * None 30733 */ 30734 int 30735 bcm_sb2_oam_loopback_add(int unit, bcm_oam_loopback_t *loopback_p) 30736 { 30737 _bcm_oam_control_t *oc; 30738 _bcm_oam_hash_data_t *h_data_p; 30739 int rv = BCM_E_NONE; 30740 bhh_sdk_msg_ctrl_loopback_add_t msg; 30741 uint8 *buffer, *buffer_ptr; 30742 uint16 buffer_len, reply_len; 30743 uint32 flags = 0; 30744 int sess_id = 0, i = 0; 30745 _bhh_oam_lm_dm_info_t counter_info; 30746 bcm_module_t module_id; 30747 bcm_port_t port_id; 30748 bcm_trunk_t trunk_id; 30749 int local_id; 30750 uint8 encap_type; 30751 30752 /* Get OAM Control Structure. */ 30753 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 30754 30755 _BCM_OAM_LOCK(oc); 30756 30757 BCM_OAM_BHH_VALIDATE_EP(loopback_p->id); 30758 30759 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id); 30760 30761 /* Check endpoint status. */ 30762 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 30763 if ((BCM_E_EXISTS != rv)) { 30764 /* Endpoint not in use. */ 30765 LOG_ERROR(BSL_LS_BCM_OAM, 30766 (BSL_META_U(unit, 30767 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 30768 unit, loopback_p->id, bcm_errmsg(rv))); 30769 _BCM_OAM_UNLOCK(oc); 30770 return (rv); 30771 } 30772 30773 h_data_p = &oc->oam_hash_data[loopback_p->id]; 30774 30775 rv = _bcm_sb2_oam_period_validate(loopback_p->period); 30776 if (BCM_FAILURE(rv)) { 30777 LOG_ERROR(BSL_LS_BCM_OAM, 30778 (BSL_META_U(unit, 30779 "OAM(unit %d) Error: Invalid period : %d\n"), 30780 unit, loopback_p->period)); 30781 _BCM_OAM_UNLOCK(oc); 30782 return (rv); 30783 } 30784 30785 sal_memset(&counter_info, 0, sizeof(counter_info)); 30786 counter_info.counter_size = loopback_p->lb_tx_update_lm_counter_size; 30787 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 30788 { 30789 counter_info.counter_base_id[i] = 30790 loopback_p->lb_tx_update_lm_counter_base_id[i]; 30791 counter_info.counter_offset[i] = 30792 loopback_p->lb_tx_update_lm_counter_offset[i]; 30793 counter_info.counter_action[i] = bcmOamCounterActionIncrement; 30794 counter_info.byte_count_offset[i] = 0; 30795 } 30796 counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE; 30797 30798 /* 30799 * Only BHH is supported 30800 */ 30801 if (BHH_EP_TYPE(h_data_p)) { 30802 30803 /* 30804 * Convert host space flags to uKernel space flags 30805 */ 30806 30807 if (loopback_p->flags & BCM_OAM_LOOPBACK_TX_ENABLE) { 30808 flags |= BCM_BHH_TX_ENABLE; 30809 } 30810 30811 if (loopback_p->flags & BCM_OAM_BHH_INC_REQUESTING_MEP_TLV) { 30812 flags |= BCM_BHH_INC_REQUESTING_MEP_TLV; 30813 } 30814 30815 if (loopback_p->flags & BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) { 30816 flags |= BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV; 30817 } else if (loopback_p->flags & BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) { 30818 flags |= BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV; 30819 } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MEP_TLV) { 30820 flags |= BCM_BHH_LBM_ICC_MEP_TLV; 30821 } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MIP_TLV) { 30822 flags |= BCM_BHH_LBM_ICC_MIP_TLV; 30823 } else { 30824 flags |= BCM_BHH_LBM_ICC_MEP_TLV; /* Default */ 30825 } 30826 30827 if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MEP_TLV) { 30828 flags |= BCM_BHH_LBR_ICC_MEP_TLV; 30829 } else if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MIP_TLV) { 30830 flags |= BCM_BHH_LBR_ICC_MIP_TLV; 30831 } 30832 30833 sal_memset(&msg, 0, sizeof(msg)); 30834 msg.flags = flags; 30835 msg.sess_id = sess_id; 30836 msg.int_pri = loopback_p->int_pri; 30837 msg.pkt_pri = loopback_p->pkt_pri; 30838 30839 /* 30840 * Set period 30841 */ 30842 msg.period = _sb2_ccm_intervals[ 30843 _bcm_sb2_oam_ccm_msecs_to_hw_encode( 30844 loopback_p->period)]; 30845 30846 /* 30847 * Check TTL 30848 */ 30849 if (loopback_p->ttl == 0 || loopback_p->ttl > 255) { 30850 _BCM_OAM_UNLOCK(oc); 30851 return BCM_E_PARAM; 30852 } 30853 30854 /* Check for default usage of int_pri */ 30855 if (loopback_p->int_pri == -1) { 30856 loopback_p->int_pri = 7; /*Use default */ 30857 } 30858 /* Check for default usage of pkt_pri */ 30859 if (loopback_p->pkt_pri == 0xff) { 30860 loopback_p->pkt_pri = 7; /*Use default */ 30861 } 30862 if (BHH_EP_MPLS_SECTION_TYPE(h_data_p) || 30863 (h_data_p->type == bcmOAMEndpointTypeBHHMPLSVccv && 30864 h_data_p->vccv_type == bcmOamBhhVccvTtl)) { 30865 30866 msg.ttl = 1; /* Only TTL 1 is valid */ 30867 } else { 30868 msg.ttl = loopback_p->ttl; 30869 } 30870 30871 if (h_data_p->trunk_id == BCM_TRUNK_INVALID) { 30872 rv = _bcm_esw_gport_resolve(unit, 30873 h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id); 30874 } else { 30875 rv = _bcm_esw_gport_resolve(unit, 30876 h_data_p->resolved_trunk_gport, &module_id, &port_id, 30877 &trunk_id, &local_id); 30878 } 30879 30880 /* 30881 * Set the BHH encapsulation data 30882 * 30883 * The function _bcm_sb2_oam_bhh_encap_create() is called first 30884 * since this sets some fields in 'hash_data' which are 30885 * used in the message. 30886 */ 30887 rv = _bcm_sb2_oam_bhh_encap_create(unit, module_id, port_id, h_data_p, 30888 msg.encap_data, &encap_type, 30889 &msg.encap_length, &counter_info, 30890 loopback_p->int_pri, 30891 loopback_p->pkt_pri, 30892 loopback_p->ttl); 30893 if(BCM_FAILURE(rv)) 30894 { 30895 LOG_ERROR(BSL_LS_BCM_OAM, 30896 (BSL_META_U(unit, 30897 "BHH(unit %d) Error: Encap create failed " 30898 " - %s.\n"), 30899 unit, bcm_errmsg(rv))); 30900 _BCM_OAM_UNLOCK(oc); 30901 return (rv); 30902 } 30903 30904 /* Pack control message data into DMA buffer */ 30905 buffer = oc->dma_buffer; 30906 buffer_ptr = bhh_sdk_msg_ctrl_loopback_add_pack(buffer, &msg); 30907 buffer_len = buffer_ptr - buffer; 30908 30909 /* Send BHH Session Update message to uC */ 30910 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 30911 MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD, 30912 buffer_len, 0, 30913 MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD_REPLY, 30914 &reply_len); 30915 30916 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 30917 rv = BCM_E_INTERNAL; 30918 } 30919 } 30920 else { 30921 rv = BCM_E_UNAVAIL; 30922 } 30923 30924 _BCM_OAM_UNLOCK(oc); 30925 return (rv); 30926 } 30927 30928 /* 30929 * Function: 30930 * bcm_sb2_oam_loopback_get 30931 * Purpose: 30932 * 30933 * Parameters: 30934 * unit - Device unit number 30935 * Returns: 30936 * None 30937 */ 30938 int 30939 bcm_sb2_oam_loopback_get(int unit, bcm_oam_loopback_t *loopback_p) 30940 { 30941 _bcm_oam_control_t *oc; 30942 int rv = BCM_E_NONE; 30943 bhh_sdk_msg_ctrl_loopback_get_t msg; 30944 _bcm_oam_hash_data_t *h_data_p; 30945 uint8 *buffer, *buffer_ptr; 30946 uint16 buffer_len, reply_len; 30947 int sess_id = 0; 30948 uint8 ts_mode; 30949 uint8 lm_pdu_counter_offset = 0; 30950 uint8 lm_counter_action[BCM_OAM_LM_COUNTER_MAX]; 30951 _mpls_label_t label; 30952 30953 30954 /* Get OAM Control Structure. */ 30955 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 30956 30957 _BCM_OAM_LOCK(oc); 30958 30959 BCM_OAM_BHH_VALIDATE_EP(loopback_p->id); 30960 30961 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id); 30962 30963 /* Check endpoint status. */ 30964 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 30965 if ((BCM_E_EXISTS != rv)) { 30966 /* Endpoint not in use. */ 30967 LOG_ERROR(BSL_LS_BCM_OAM, 30968 (BSL_META_U(unit, 30969 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 30970 unit, loopback_p->id, bcm_errmsg(rv))); 30971 _BCM_OAM_UNLOCK(oc); 30972 return (rv); 30973 } 30974 30975 h_data_p = &oc->oam_hash_data[loopback_p->id]; 30976 30977 /* 30978 * Only BHH is supported 30979 */ 30980 if (BHH_EP_TYPE(h_data_p)) { 30981 30982 sal_memset(&msg, 0, sizeof(msg)); 30983 /* Send BHH Session Update message to uC */ 30984 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 30985 MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET, 30986 sess_id, 0, 30987 MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET_REPLY, 30988 &reply_len); 30989 if(BCM_FAILURE(rv)) { 30990 LOG_ERROR(BSL_LS_BCM_OAM, 30991 (BSL_META_U(unit, 30992 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 30993 unit, loopback_p->id, bcm_errmsg(rv))); 30994 _BCM_OAM_UNLOCK(oc); 30995 return (rv); 30996 } 30997 30998 /* Pack control message data into DMA buffer */ 30999 buffer = oc->dma_buffer; 31000 buffer_ptr = bhh_sdk_msg_ctrl_loopback_get_unpack(buffer, &msg); 31001 buffer_len = buffer_ptr - buffer; 31002 31003 31004 if (reply_len != buffer_len) { 31005 rv = BCM_E_INTERNAL; 31006 } else { 31007 /* 31008 * Convert kernel space flags to host space flags 31009 */ 31010 if (msg.flags & BCM_BHH_INC_REQUESTING_MEP_TLV) { 31011 loopback_p->flags |= BCM_OAM_BHH_INC_REQUESTING_MEP_TLV; 31012 } 31013 31014 if (msg.flags & BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) { 31015 loopback_p->flags |= BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV; 31016 } else if (msg.flags & BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) { 31017 loopback_p->flags |= BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV; 31018 } else if (msg.flags & BCM_BHH_LBM_ICC_MEP_TLV) { 31019 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MEP_TLV; 31020 } else if (msg.flags & BCM_BHH_LBM_ICC_MIP_TLV) { 31021 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MIP_TLV; 31022 } 31023 31024 if (msg.flags & BCM_BHH_LBR_ICC_MEP_TLV) { 31025 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MEP_TLV; 31026 } else if (msg.flags & BCM_BHH_LBR_ICC_MIP_TLV) { 31027 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MIP_TLV; 31028 } 31029 31030 if (msg.flags & BCM_BHH_TX_ENABLE) { 31031 loopback_p->flags |= BCM_OAM_LOOPBACK_TX_ENABLE; 31032 } 31033 31034 loopback_p->period = msg.period; 31035 loopback_p->ttl = msg.ttl; 31036 loopback_p->discovered_me.flags = msg.discovery_flags; 31037 loopback_p->discovered_me.name = msg.discovery_id; 31038 loopback_p->discovered_me.ttl = msg.discovery_ttl; 31039 loopback_p->rx_count = msg.rx_count; 31040 loopback_p->tx_count = msg.tx_count; 31041 loopback_p->drop_count = msg.drop_count; 31042 loopback_p->unexpected_response = msg.unexpected_response; 31043 loopback_p->out_of_sequence = msg.out_of_sequence; 31044 loopback_p->local_mipid_missmatch = msg.local_mipid_missmatch; 31045 loopback_p->remote_mipid_missmatch = msg.remote_mipid_missmatch; 31046 loopback_p->invalid_target_mep_tlv = msg.invalid_target_mep_tlv; 31047 loopback_p->invalid_mep_tlv_subtype = msg.invalid_mep_tlv_subtype; 31048 loopback_p->invalid_tlv_offset = msg.invalid_tlv_offset; 31049 if (BHH_UC_FEATURE_CHECK(BHH_OLP_ENCAP_VALID)) { 31050 /* If this feature is valid, then encap_data is valid */ 31051 if (BCM_FAILURE(_bcm_sb2_oam_olp_encap_header_decap(unit, 31052 msg.encap_data, 31053 &(loopback_p->lb_tx_update_lm_counter_size), 31054 loopback_p->lb_tx_update_lm_counter_base_id, 31055 loopback_p->lb_tx_update_lm_counter_offset, 31056 lm_counter_action, 31057 &ts_mode, 31058 &lm_pdu_counter_offset, 31059 &(loopback_p->int_pri), 31060 NULL))) 31061 { 31062 _BCM_OAM_UNLOCK(oc); 31063 return (BCM_E_INTERNAL); 31064 } 31065 _bcm_sb2_oam_bhh_get_egress_label_from_encap(h_data_p, 31066 msg.encap_data, 31067 msg.encap_length, 31068 &label); 31069 loopback_p->pkt_pri = label.exp; 31070 loopback_p->ttl = label.ttl; 31071 } 31072 31073 rv = BCM_E_NONE; 31074 } 31075 } 31076 else { 31077 rv = BCM_E_UNAVAIL; 31078 } 31079 31080 _BCM_OAM_UNLOCK(oc); 31081 31082 return (rv); 31083 } 31084 31085 /* 31086 * Function: 31087 * bcm_sb2_oam_loopback_delete 31088 * Purpose: 31089 * 31090 * Parameters: 31091 * unit - Device unit number 31092 * Returns: 31093 * None 31094 */ 31095 int 31096 bcm_sb2_oam_loopback_delete(int unit, bcm_oam_loopback_t *loopback_p) 31097 { 31098 _bcm_oam_control_t *oc; 31099 int rv = BCM_E_NONE; 31100 shr_bhh_msg_ctrl_loopback_delete_t msg; 31101 uint8 *buffer, *buffer_ptr; 31102 uint16 buffer_len, reply_len; 31103 int sess_id = 0; 31104 _bcm_oam_hash_data_t *h_data_p; 31105 31106 /* Get OAM Control Structure. */ 31107 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 31108 31109 _BCM_OAM_LOCK(oc); 31110 31111 BCM_OAM_BHH_VALIDATE_EP(loopback_p->id); 31112 31113 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loopback_p->id); 31114 31115 /* Check endpoint status. */ 31116 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 31117 if ((BCM_E_EXISTS != rv)) { 31118 /* Endpoint not in use. */ 31119 LOG_ERROR(BSL_LS_BCM_OAM, 31120 (BSL_META_U(unit, 31121 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 31122 unit, loopback_p->id, bcm_errmsg(rv))); 31123 _BCM_OAM_UNLOCK(oc); 31124 return (rv); 31125 } 31126 31127 h_data_p = &oc->oam_hash_data[loopback_p->id]; 31128 31129 /* 31130 * Only BHH is supported 31131 */ 31132 if (BHH_EP_TYPE(h_data_p)) { 31133 31134 msg.sess_id = sess_id; 31135 31136 /* Pack control message data into DMA buffer */ 31137 buffer = oc->dma_buffer; 31138 buffer_ptr = shr_bhh_msg_ctrl_loopback_delete_pack(buffer, &msg); 31139 buffer_len = buffer_ptr - buffer; 31140 31141 /* Send BHH Session Update message to uC */ 31142 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 31143 MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE, 31144 buffer_len, 0, 31145 MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE_REPLY, 31146 &reply_len); 31147 31148 if(BCM_SUCCESS(rv) && (reply_len != 0)) 31149 rv = BCM_E_INTERNAL; 31150 } 31151 else { 31152 _BCM_OAM_UNLOCK(oc); 31153 return BCM_E_UNAVAIL; 31154 } 31155 31156 _BCM_OAM_UNLOCK(oc); 31157 31158 return (rv); 31159 } 31160 31161 /* 31162 * Function: 31163 * bcm_sb2_oam_csf_add 31164 * Purpose: 31165 * Start CSF PDU transmission 31166 * Parameters: 31167 * unit - (IN) Unit number. 31168 * csf_ptr - (INOUT) CSF object 31169 * Returns: 31170 * BCM_E_XXX 31171 * Notes: 31172 */ 31173 int bcm_sb2_oam_csf_add(int unit, bcm_oam_csf_t *csf_p) 31174 { 31175 _bcm_oam_control_t *oc; 31176 _bcm_oam_hash_data_t *h_data_p; 31177 bhh_sdk_msg_ctrl_csf_add_t msg; 31178 uint8 *buffer, *buffer_ptr; 31179 uint16 buffer_len, reply_len; 31180 _bhh_oam_lm_dm_info_t counter_info; 31181 bcm_module_t module_id; 31182 bcm_port_t port_id; 31183 bcm_trunk_t trunk_id; 31184 int local_id; 31185 uint8 encap_type; 31186 int sess_id = 0; 31187 int i; 31188 int rv = BCM_E_NONE; 31189 31190 /* Get OAM Control Structure. */ 31191 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 31192 _BCM_OAM_LOCK(oc); 31193 31194 if (oc->ukernel_not_ready) { 31195 _BCM_OAM_UNLOCK(oc); 31196 return BCM_E_INIT; 31197 } 31198 31199 BCM_OAM_BHH_VALIDATE_EP(csf_p->id); 31200 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id); 31201 31202 /* Check endpoint status. */ 31203 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 31204 if ((BCM_E_EXISTS != rv)) { 31205 /* Endpoint not in use. */ 31206 LOG_ERROR(BSL_LS_BCM_OAM, 31207 (BSL_META_U(unit, 31208 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 31209 unit, csf_p->id, bcm_errmsg(rv))); 31210 _BCM_OAM_UNLOCK(oc); 31211 return (rv); 31212 } 31213 31214 if ((csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1S) && 31215 (csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1M)) { 31216 /* Only 1S and 1M are supported */ 31217 _BCM_OAM_UNLOCK(oc); 31218 return BCM_E_PARAM; 31219 } 31220 31221 h_data_p = &oc->oam_hash_data[csf_p->id]; 31222 /* 31223 * Only BHH is supported 31224 */ 31225 if (!BHH_EP_TYPE(h_data_p)) { 31226 _BCM_OAM_UNLOCK(oc); 31227 return BCM_E_UNAVAIL; 31228 } 31229 31230 sal_memset(&counter_info, 0, sizeof(counter_info)); 31231 counter_info.counter_size = csf_p->csf_tx_update_lm_counter_size; 31232 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) { 31233 counter_info.counter_base_id[i] = 31234 csf_p->csf_tx_update_lm_counter_base_id[i]; 31235 counter_info.counter_offset[i] = 31236 csf_p->csf_tx_update_lm_counter_offset[i]; 31237 counter_info.counter_action[i] = bcmOamCounterActionIncrement; 31238 } 31239 counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE; 31240 31241 sal_memset(&msg, 0, sizeof(msg)); 31242 msg.sess_id = sess_id; 31243 msg.int_pri = csf_p->int_pri; 31244 msg.pkt_pri = csf_p->pkt_pri; 31245 31246 switch(csf_p->type) { 31247 case BCM_OAM_CSF_LOS: 31248 msg.type = SHR_CSF_TYPE_LOS; 31249 break; 31250 31251 case BCM_OAM_CSF_FDI: 31252 msg.type = SHR_CSF_TYPE_FDI; 31253 break; 31254 31255 case BCM_OAM_CSF_RDI: 31256 msg.type = SHR_CSF_TYPE_RDI; 31257 break; 31258 31259 case BCM_OAM_CSF_DCI: 31260 msg.type = SHR_CSF_TYPE_DCI; 31261 break; 31262 31263 default: 31264 _BCM_OAM_UNLOCK(oc); 31265 return BCM_E_PARAM; 31266 } 31267 31268 /* 31269 * Set period 31270 */ 31271 msg.period = csf_p->period; 31272 31273 if (h_data_p->trunk_id == BCM_TRUNK_INVALID) { 31274 rv = _bcm_esw_gport_resolve(unit, h_data_p->gport, 31275 &module_id, &port_id, 31276 &trunk_id, &local_id); 31277 } else { 31278 rv = _bcm_esw_gport_resolve(unit, 31279 h_data_p->resolved_trunk_gport, 31280 &module_id, &port_id, 31281 &trunk_id, &local_id); 31282 } 31283 if (rv != BCM_E_NONE) { 31284 _BCM_OAM_UNLOCK(oc); 31285 return rv; 31286 } 31287 31288 /* 31289 * Set the BHH encapsulation data 31290 */ 31291 rv = _bcm_sb2_oam_bhh_encap_create(unit, module_id, port_id, h_data_p, 31292 msg.encap_data, &encap_type, 31293 &msg.encap_length, &counter_info, 31294 csf_p->int_pri, csf_p->pkt_pri, 31295 h_data_p->egr_label_ttl); 31296 if(BCM_FAILURE(rv)) { 31297 LOG_ERROR(BSL_LS_BCM_OAM, 31298 (BSL_META_U(unit, 31299 "BHH(unit %d) Error: Encap create failed " 31300 " - %s.\n"), 31301 unit, bcm_errmsg(rv))); 31302 _BCM_OAM_UNLOCK(oc); 31303 return rv; 31304 } 31305 31306 /* Pack control message data into DMA buffer */ 31307 buffer = oc->dma_buffer; 31308 buffer_ptr = bhh_sdk_msg_ctrl_csf_add_pack(buffer, &msg); 31309 buffer_len = buffer_ptr - buffer; 31310 31311 /* Send BHH Session Update message to uC */ 31312 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 31313 MOS_MSG_SUBCLASS_BHH_CSF_ADD, 31314 buffer_len, 0, 31315 MOS_MSG_SUBCLASS_BHH_CSF_ADD_REPLY, 31316 &reply_len); 31317 31318 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 31319 rv = BCM_E_INTERNAL; 31320 } 31321 31322 _BCM_OAM_UNLOCK(oc); 31323 return rv; 31324 } 31325 31326 /* 31327 * Function: 31328 * bcm_sb2_oam_csf_get 31329 * Purpose: 31330 * Get CSF info 31331 * Parameters: 31332 * unit - (IN) Unit number. 31333 * csf_ptr - (OUT) CSF object 31334 * Returns: 31335 * BCM_E_XXX 31336 * Notes: 31337 */ 31338 int bcm_sb2_oam_csf_get(int unit, bcm_oam_csf_t *csf_p) 31339 { 31340 _bcm_oam_control_t *oc; 31341 bhh_sdk_msg_ctrl_csf_get_t msg; 31342 _bcm_oam_hash_data_t *h_data_p; 31343 uint8 *buffer, *buffer_ptr; 31344 uint16 buffer_len, reply_len; 31345 uint8 ts_mode; 31346 uint8 lm_pdu_counter_offset = 0; 31347 uint8 lm_counter_action[BCM_OAM_LM_COUNTER_MAX]; 31348 _mpls_label_t label; 31349 int sess_id = 0; 31350 int rv = BCM_E_NONE; 31351 31352 31353 /* Get OAM Control Structure. */ 31354 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 31355 _BCM_OAM_LOCK(oc); 31356 31357 if (oc->ukernel_not_ready) { 31358 _BCM_OAM_UNLOCK(oc); 31359 return BCM_E_INIT; 31360 } 31361 31362 BCM_OAM_BHH_VALIDATE_EP(csf_p->id); 31363 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id); 31364 31365 /* Check endpoint status. */ 31366 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 31367 if ((BCM_E_EXISTS != rv)) { 31368 /* Endpoint not in use. */ 31369 LOG_ERROR(BSL_LS_BCM_OAM, 31370 (BSL_META_U(unit, 31371 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 31372 unit, csf_p->id, bcm_errmsg(rv))); 31373 _BCM_OAM_UNLOCK(oc); 31374 return (rv); 31375 } 31376 31377 h_data_p = &oc->oam_hash_data[csf_p->id]; 31378 31379 if (!BHH_EP_TYPE(h_data_p)) { 31380 _BCM_OAM_UNLOCK(oc); 31381 return BCM_E_UNAVAIL; 31382 } 31383 31384 31385 sal_memset(&msg, 0, sizeof(msg)); 31386 31387 /* Send BHH Session Update message to uC */ 31388 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 31389 MOS_MSG_SUBCLASS_BHH_CSF_GET, 31390 sess_id, 0, 31391 MOS_MSG_SUBCLASS_BHH_CSF_GET_REPLY, 31392 &reply_len); 31393 if(BCM_FAILURE(rv)) { 31394 LOG_ERROR(BSL_LS_BCM_OAM, 31395 (BSL_META_U(unit, 31396 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 31397 unit, csf_p->id, bcm_errmsg(rv))); 31398 _BCM_OAM_UNLOCK(oc); 31399 return (rv); 31400 } 31401 31402 /* Pack control message data into DMA buffer */ 31403 buffer = oc->dma_buffer; 31404 buffer_ptr = bhh_sdk_msg_ctrl_csf_get_unpack(buffer, &msg); 31405 buffer_len = buffer_ptr - buffer; 31406 31407 31408 if (reply_len != buffer_len) { 31409 _BCM_OAM_UNLOCK(oc); 31410 return BCM_E_INTERNAL; 31411 } 31412 31413 switch(msg.type) { 31414 case SHR_CSF_TYPE_LOS: 31415 csf_p->type = BCM_OAM_CSF_LOS; 31416 break; 31417 31418 case SHR_CSF_TYPE_FDI: 31419 csf_p->type = BCM_OAM_CSF_FDI; 31420 break; 31421 31422 case SHR_CSF_TYPE_RDI: 31423 csf_p->type = BCM_OAM_CSF_RDI; 31424 break; 31425 31426 case SHR_CSF_TYPE_DCI: 31427 csf_p->type = BCM_OAM_CSF_DCI; 31428 break; 31429 31430 default: 31431 _BCM_OAM_UNLOCK(oc); 31432 return BCM_E_INTERNAL; 31433 } 31434 31435 csf_p->period = msg.period; 31436 csf_p->flags = msg.flags; 31437 31438 rv = _bcm_sb2_oam_olp_encap_header_decap(unit, msg.encap_data, 31439 &(csf_p->csf_tx_update_lm_counter_size), 31440 csf_p->csf_tx_update_lm_counter_base_id, 31441 csf_p->csf_tx_update_lm_counter_offset, 31442 lm_counter_action, &ts_mode, 31443 &lm_pdu_counter_offset, 31444 &(csf_p->int_pri), 31445 NULL); 31446 if (rv != BCM_E_NONE) { 31447 _BCM_OAM_UNLOCK(oc); 31448 return rv; 31449 } 31450 31451 _bcm_sb2_oam_bhh_get_egress_label_from_encap(h_data_p, msg.encap_data, 31452 msg.encap_length, &label); 31453 csf_p->pkt_pri = label.exp; 31454 31455 _BCM_OAM_UNLOCK(oc); 31456 return BCM_E_NONE; 31457 31458 } 31459 31460 /* 31461 * Function: 31462 * bcm_sb2_oam_csf_delete 31463 * Purpose: 31464 * Stop CSF PDU transmission 31465 * Parameters: 31466 * unit - (IN Unit number. 31467 * csf_ptr - (IN) CSF object 31468 * Returns: 31469 * BCM_E_XXX 31470 * Notes: 31471 */ 31472 int bcm_sb2_oam_csf_delete(int unit, bcm_oam_csf_t *csf_p) 31473 { 31474 _bcm_oam_control_t *oc; 31475 _bcm_oam_hash_data_t *h_data_p; 31476 uint16 reply_len; 31477 int sess_id; 31478 int rv = BCM_E_NONE; 31479 31480 /* Get OAM Control Structure. */ 31481 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 31482 _BCM_OAM_LOCK(oc); 31483 31484 if (oc->ukernel_not_ready) { 31485 _BCM_OAM_UNLOCK(oc); 31486 return BCM_E_INIT; 31487 } 31488 31489 BCM_OAM_BHH_VALIDATE_EP(csf_p->id); 31490 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(csf_p->id); 31491 31492 /* Check endpoint status. */ 31493 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 31494 if ((BCM_E_EXISTS != rv)) { 31495 /* Endpoint not in use. */ 31496 LOG_ERROR(BSL_LS_BCM_OAM, 31497 (BSL_META_U(unit, 31498 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 31499 unit, csf_p->id, bcm_errmsg(rv))); 31500 _BCM_OAM_UNLOCK(oc); 31501 return (rv); 31502 } 31503 31504 h_data_p = &oc->oam_hash_data[csf_p->id]; 31505 31506 if (!BHH_EP_TYPE(h_data_p)) { 31507 _BCM_OAM_UNLOCK(oc); 31508 return BCM_E_UNAVAIL; 31509 } 31510 31511 /* Send BHH Session Update message to uC */ 31512 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 31513 MOS_MSG_SUBCLASS_BHH_CSF_DELETE, 31514 sess_id, 0, 31515 MOS_MSG_SUBCLASS_BHH_CSF_DELETE_REPLY, 31516 &reply_len); 31517 31518 _BCM_OAM_UNLOCK(oc); 31519 return (rv); 31520 } 31521 31522 #endif /*(INCLUDE_BHH)*/ 31523 31524 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) || defined(INCLUDE_MPLS_LM_DM) 31525 /* 31526 * Function: 31527 * bcm_sb2_oam_loss_add 31528 * Purpose: 31529 * Loss Measurement add 31530 * Parameters: 31531 * unit - Device unit number 31532 * Returns: 31533 * None 31534 */ 31535 int 31536 bcm_sb2_oam_loss_add(int unit, bcm_oam_loss_t *loss_p) 31537 { 31538 _bcm_oam_control_t *oc; 31539 _bcm_oam_hash_data_t *h_data_p; 31540 int rv = BCM_E_NONE; 31541 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) 31542 uint8 *buffer, *buffer_ptr; 31543 uint16 buffer_len, reply_len; 31544 uint32 flags = 0; 31545 int sess_id = 0; 31546 #endif 31547 #if defined(INCLUDE_BHH) 31548 _bhh_oam_lm_dm_info_t counter_info; 31549 bcm_module_t module_id; 31550 bcm_port_t port_id; 31551 bcm_trunk_t trunk_id; 31552 int local_id, i = 0; 31553 uint8 encap_type; 31554 #endif 31555 31556 /* Get OAM Control Structure. */ 31557 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 31558 _BCM_OAM_EP_INDEX_VALIDATE(loss_p->id); 31559 _BCM_OAM_LOCK(oc); 31560 31561 31562 h_data_p = &oc->oam_hash_data[loss_p->id]; 31563 31564 if (!(h_data_p->in_use)) { 31565 /* Endpoint not in use. */ 31566 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 31567 "Endpoint EP=%d not configured.\n"), unit, loss_p->id)); 31568 _BCM_OAM_UNLOCK(oc); 31569 return BCM_E_NOT_FOUND; 31570 } 31571 #if defined(INCLUDE_MPLS_LM_DM) 31572 /* Check if EP type is MPLS_LM_DM, call respective routine */ 31573 if ( MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) ) { 31574 if (oc->mpls_lm_dm_ukernel_ready) { 31575 rv = _bcm_sb2_mpls_lm_dm_loss_add(unit, h_data_p, loss_p); 31576 _BCM_OAM_UNLOCK(oc); 31577 return rv; 31578 } else { 31579 _BCM_OAM_UNLOCK(oc); 31580 return BCM_E_UNAVAIL; 31581 } 31582 } 31583 #endif 31584 /* 31585 * BHH and ETH LM/DM is supported 31586 */ 31587 if (BHH_EP_TYPE(h_data_p)) { 31588 31589 #if defined (INCLUDE_BHH) 31590 bhh_sdk_msg_ctrl_loss_add_t msg; 31591 31592 if (oc->ukernel_not_ready) { 31593 _BCM_OAM_UNLOCK(oc); 31594 return BCM_E_INIT; 31595 } 31596 31597 BCM_OAM_BHH_VALIDATE_EP(loss_p->id); 31598 31599 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id); 31600 31601 /* Check endpoint status. */ 31602 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 31603 if ((BCM_E_EXISTS != rv)) { 31604 /* Endpoint not in use. */ 31605 LOG_ERROR(BSL_LS_BCM_OAM, 31606 (BSL_META_U(unit, 31607 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 31608 unit, loss_p->id, bcm_errmsg(rv))); 31609 _BCM_OAM_UNLOCK(oc); 31610 return (rv); 31611 } 31612 if (h_data_p->int_flags & _BCM_OAM_ENDPOINT_BHH_PROACTIVE_LM) { 31613 LOG_ERROR(BSL_LS_BCM_OAM, 31614 (BSL_META_U(unit, 31615 "OAM(unit %d) Error: Proactive LM is enabled " 31616 " on Endpoint EP=%d \n"), unit, loss_p->id)); 31617 _BCM_OAM_UNLOCK(oc); 31618 return BCM_E_PARAM; 31619 } 31620 if (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU) { 31621 _BCM_OAM_UNLOCK(oc); 31622 return BCM_E_PARAM; 31623 } 31624 31625 /* 31626 * Convert host space flags to uKernel space flags 31627 */ 31628 if (loss_p->flags & BCM_OAM_LOSS_SINGLE_ENDED) { 31629 flags |= BCM_BHH_LM_SINGLE_ENDED; 31630 } 31631 31632 if (loss_p->flags & BCM_OAM_LOSS_TX_ENABLE) { 31633 flags |= BCM_BHH_LM_TX_ENABLE; 31634 } 31635 31636 if (loss_p->flags & BCM_OAM_LOSS_SLM) { 31637 flags |= BCM_BHH_LM_SLM; 31638 } 31639 31640 rv = _bcm_sb2_oam_period_validate(loss_p->period); 31641 if (BCM_FAILURE(rv)) { 31642 LOG_ERROR(BSL_LS_BCM_OAM, 31643 (BSL_META_U(unit, 31644 "OAM(unit %d) Error: Invalid period : %d\n"), 31645 unit, loss_p->period)); 31646 _BCM_OAM_UNLOCK(oc); 31647 return rv; 31648 } 31649 sal_memset(&counter_info, 0, sizeof(counter_info)); 31650 counter_info.counter_size = loss_p->lm_counter_size; 31651 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 31652 { 31653 counter_info.counter_base_id[i] = loss_p->lm_counter_base_id[i]; 31654 counter_info.counter_offset[i] = loss_p->lm_counter_offset[i]; 31655 counter_info.counter_action[i] = loss_p->lm_counter_action[i]; 31656 counter_info.byte_count_offset[i] = 0; 31657 } 31658 counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NONE; 31659 counter_info.oam_replacement_offset = SHR_BHH_HEADER_LENGTH; 31660 31661 if (h_data_p->trunk_id == BCM_TRUNK_INVALID) { 31662 rv = _bcm_esw_gport_resolve(unit, 31663 h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id); 31664 } else { 31665 rv = _bcm_esw_gport_resolve(unit, 31666 h_data_p->resolved_trunk_gport, &module_id, &port_id, 31667 &trunk_id, &local_id); 31668 31669 } 31670 sal_memset(&msg, 0, sizeof(msg)); 31671 msg.flags = flags; 31672 msg.sess_id = sess_id; 31673 31674 /* 31675 * Set period 31676 */ 31677 msg.period = _sb2_ccm_intervals[_bcm_sb2_oam_ccm_msecs_to_hw_encode(loss_p->period)]; 31678 msg.int_pri = loss_p->int_pri; 31679 msg.pkt_pri = loss_p->pkt_pri; 31680 31681 rv = _bcm_sb2_oam_bhh_encap_create(unit, module_id, port_id, h_data_p, 31682 msg.encap_data, &encap_type, 31683 &msg.encap_length, &counter_info, 31684 loss_p->int_pri, loss_p->pkt_pri, 31685 h_data_p->egr_label_ttl); 31686 31687 if(BCM_FAILURE(rv)) 31688 { 31689 LOG_ERROR(BSL_LS_BCM_OAM, 31690 (BSL_META_U(unit, 31691 "BHH(unit %d) Error: Encap create failed " 31692 "- %s.\n"), 31693 unit, bcm_errmsg(rv))); 31694 _BCM_OAM_UNLOCK(oc); 31695 return (rv); 31696 } 31697 31698 /* Pack control message data into DMA buffer */ 31699 buffer = oc->dma_buffer; 31700 buffer_ptr = bhh_sdk_msg_ctrl_loss_add_pack(buffer, &msg); 31701 buffer_len = buffer_ptr - buffer; 31702 31703 31704 /* Send BHH Session Update message to uC */ 31705 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 31706 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD, 31707 buffer_len, 0, 31708 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_ADD_REPLY, 31709 &reply_len); 31710 31711 loss_p->pm_id = sess_id; 31712 31713 if(BCM_SUCCESS(rv) && (reply_len != 0)) 31714 rv = BCM_E_INTERNAL; 31715 #endif 31716 } else if (h_data_p->type == bcmOAMEndpointTypeEthernet) { 31717 #if defined(INCLUDE_ETH_LM_DM) 31718 shr_eth_lm_dm_msg_ctrl_loss_add_t msg; 31719 bcm_port_t port_id; 31720 bcm_module_t module_id; 31721 int local_id; 31722 bcm_trunk_t trunk_id; 31723 uint8 mep_type; 31724 uint32 session_flags = 0; 31725 shr_eth_lm_dm_msg_ctrl_sess_set_t msg_sess; 31726 int cpu_modid; 31727 bcm_port_t cpu_port; 31728 int cpu_dglp; 31729 uint32 olp_l2_encap_length; 31730 31731 31732 if (1 == oc->eth_lm_dm_ukernel_not_ready) { 31733 LOG_ERROR(BSL_LS_BCM_OAM, 31734 (BSL_META_U(unit, 31735 "ETH_LM_DM(unit %d) Error: BTE(ukernel) not ready\n"), 31736 unit)); 31737 _BCM_OAM_UNLOCK(oc); 31738 return (BCM_E_INIT); 31739 } 31740 31741 if (!(h_data_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) { 31742 LOG_ERROR(BSL_LS_BCM_OAM, 31743 (BSL_META_U(unit, 31744 "ETH_LM_DM(unit %d) Error: loss measurement not available (EP=%d)\n"), 31745 unit, loss_p->id)); 31746 _BCM_OAM_UNLOCK(oc); 31747 return BCM_E_UNAVAIL; 31748 31749 } 31750 31751 /* Get the Trunk, Port and Mod-id info for this G-port */ 31752 rv = _bcm_esw_gport_resolve(unit, 31753 h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id); 31754 31755 if (BCM_FAILURE(rv)) { 31756 LOG_ERROR(BSL_LS_BCM_OAM, 31757 (BSL_META_U(unit, 31758 "ETH_LM_DM(unit %d) Error: Gport resolve (EP=%d) - %s.\n"), 31759 unit, loss_p->id, bcm_errmsg(rv))); 31760 _BCM_OAM_UNLOCK(oc); 31761 return (rv); 31762 } 31763 31764 /* Reserve and program session Id for this EP */ 31765 /* ------------------------------------------ */ 31766 if (h_data_p->lm_dm_uc_session_id == 0 ) { 31767 rv = shr_idxres_list_alloc(oc->eth_lm_dm_pool, 31768 (shr_idxres_element_t *)&sess_id); 31769 31770 if (BCM_FAILURE(rv)) { 31771 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "ETH_LM_DM (unit %d) Error:" 31772 " Session Id alloc failed EP:%d %s.\n"), unit, h_data_p->ep_id, 31773 bcm_errmsg(rv))); 31774 _BCM_OAM_UNLOCK(oc); 31775 return (rv); 31776 } 31777 h_data_p->lm_dm_uc_session_id = sess_id; 31778 } else { 31779 sess_id = h_data_p->lm_dm_uc_session_id; 31780 } 31781 oc->eth_lm_dm_sess_id_ep_id[sess_id] = h_data_p->ep_id; 31782 31783 /* Set end-point type(dir) from the hash data flag*/ 31784 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 31785 mep_type = 1; 31786 } else { 31787 mep_type = 0; 31788 } 31789 31790 /* Get the cpu_dglp from cpu_modid and cpu_port*/ 31791 rv = bcm_esw_stk_my_modid_get(unit, &cpu_modid); 31792 if (BCM_FAILURE(rv)) { 31793 LOG_ERROR(BSL_LS_BCM_OAM, 31794 (BSL_META_U(unit, 31795 "OAM(unit %d) Error: MODID get failed - %s.\n"), 31796 unit, bcm_errmsg(rv))); 31797 _BCM_OAM_UNLOCK(oc); 31798 return (rv); 31799 } 31800 cpu_port = 0; 31801 cpu_dglp = ((cpu_modid << DGLP_MODULE_ID_SHIFT_BITS) + cpu_port); 31802 31803 rv = _bcm_sb2_oam_eth_olp_encap_create(unit, 31804 port_id, 31805 cpu_dglp, 31806 h_data_p, 31807 msg_sess.encap_data, 31808 &msg_sess.eth_l2_encap_length, 31809 &olp_l2_encap_length, 31810 loss_p->pkt_pri); 31811 if (BCM_FAILURE(rv)) { 31812 LOG_ERROR(BSL_LS_BCM_OAM, 31813 (BSL_META_U(unit, 31814 "ETH_LM_DM(unit %d) Error: encap create (EP=%d) - %s.\n"), 31815 unit, loss_p->id, bcm_errmsg(rv))); 31816 _BCM_OAM_UNLOCK(oc); 31817 return (rv); 31818 } 31819 31820 31821 msg_sess.sess_id = sess_id; 31822 msg_sess.mep_id = h_data_p->ep_id; 31823 31824 /* Set end-point type(dir) in session set message*/ 31825 msg_sess.mep_type = mep_type; 31826 msg_sess.mel = h_data_p->level; 31827 msg_sess.vlan_id = h_data_p->inner_vlan; 31828 msg_sess.outer_vlan_id = h_data_p->vlan; 31829 msg_sess.lm_counter_index = h_data_p->tx_ctr; 31830 msg_sess.group_id = h_data_p->group_index; 31831 msg_sess.tx_port = port_id; 31832 31833 /* Create or Update */ 31834 if (!(h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_SESSION_IS_SET)) { 31835 session_flags = SHR_ETH_LM_DM_SESS_SET_F_CREATE; 31836 } 31837 session_flags |= SHR_ETH_LM_DM_SESS_SET_F_LM; 31838 31839 if (h_data_p->lm_dm_int_flag & SHR_ETH_LM_DM_SESS_SET_F_DM) { 31840 session_flags |= SHR_ETH_LM_DM_SESS_SET_F_DM; 31841 } 31842 31843 31844 msg_sess.flags = session_flags; 31845 31846 /* Pack control message data into DMA buffer */ 31847 buffer = oc->eth_lm_dm_dma_buffer; 31848 buffer_ptr = shr_eth_lm_dm_msg_ctrl_sess_set_pack(buffer, &msg_sess); 31849 buffer_len = buffer_ptr - buffer; 31850 31851 /* Send ETH LM/DM session set message to uC */ 31852 rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit, 31853 MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_SET, 31854 buffer_len, 0, 31855 MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_SET_REPLY, 31856 &reply_len); 31857 31858 if(BCM_FAILURE(rv)) { 31859 LOG_ERROR(BSL_LS_BCM_OAM, 31860 (BSL_META_U(unit, 31861 "OAM(unit %d) Error Session set: Endpoint EP=%d %s.\n"), 31862 unit, loss_p->id, bcm_errmsg(rv))); 31863 _BCM_OAM_UNLOCK(oc); 31864 return (rv); 31865 } 31866 31867 /* Session has been set in the endpoint */ 31868 h_data_p->lm_dm_int_flag |= _ETH_LM_DM_F_SESSION_IS_SET; 31869 31870 /* 31871 * Convert host space flags to uKernel space flags 31872 */ 31873 if (loss_p->flags & BCM_OAM_LOSS_SINGLE_ENDED) { 31874 flags |= BCM_ETH_LM_SINGLE_ENDED; 31875 } 31876 31877 if (loss_p->flags & BCM_OAM_LOSS_TX_ENABLE) { 31878 flags |= BCM_ETH_LM_TX_ENABLE; 31879 } 31880 31881 if (loss_p->flags & BCM_OAM_LOSS_SLM) { 31882 flags |= BCM_ETH_LM_SLM; 31883 } 31884 31885 if (loss_p->flags & BCM_OAM_LOSS_UPDATE) { 31886 flags |= BCM_ETH_LM_UPDATE; 31887 } 31888 31889 msg.flags = flags; 31890 msg.sess_id = sess_id; 31891 msg.tx_qnum = SOC_INFO(unit).port_uc_cosq_base[port_id] + loss_p->int_pri; 31892 msg.period = 31893 _sb2_ccm_intervals[_bcm_sb2_oam_ccm_msecs_to_hw_encode(loss_p->period)]; 31894 msg.tx_cos = loss_p->int_pri; 31895 msg.tx_pri = loss_p->pkt_pri; 31896 31897 /* MAC-DA of loss_add struture is put into the L2 encap of Loss Tx control pkt*/ 31898 memcpy(msg.dst_mac, loss_p->peer_da_mac_address, sizeof(bcm_mac_t)); 31899 31900 msg.remote_mep_id = loss_p->remote_id; 31901 31902 /* Put OLP_TX header in loss add structure */ 31903 rv = _bcm_sb2_oam_loss_olp_tx_encap_create(unit, 31904 h_data_p, 31905 msg.olp_tx_hdr, 31906 &msg.olp_tx_hdr_length, 31907 loss_p, 31908 port_id, 31909 module_id, 31910 mep_type); 31911 31912 /* Pack control message data into DMA buffer */ 31913 buffer = oc->eth_lm_dm_dma_buffer; 31914 buffer_ptr = shr_eth_lm_dm_msg_ctrl_loss_add_pack(buffer, &msg); 31915 buffer_len = buffer_ptr - buffer; 31916 31917 /* Send ETH LM/DM loss add message to uC */ 31918 rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit, 31919 MOS_MSG_SUBCLASS_ETH_LM_DM_LOSS_MEASUREMENT_ADD, 31920 buffer_len, 0, 31921 MOS_MSG_SUBCLASS_ETH_LM_DM_LOSS_MEASUREMENT_ADD_REPLY, 31922 &reply_len); 31923 31924 h_data_p->lm_dm_int_flag |= _ETH_LM_DM_F_LM_IS_SET; 31925 31926 loss_p->pm_id = h_data_p->lm_dm_uc_session_id; 31927 31928 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 31929 rv = BCM_E_INTERNAL; 31930 } 31931 #endif 31932 } 31933 else { 31934 _BCM_OAM_UNLOCK(oc); 31935 return BCM_E_UNAVAIL; 31936 } 31937 31938 _BCM_OAM_UNLOCK(oc); 31939 return (rv); 31940 } 31941 31942 int 31943 bcm_sb2_oam_convert_ep_to_time_spec(bcm_time_spec_t* bts, int sec, int ns) 31944 { 31945 int rv = BCM_E_NONE; 31946 31947 if (bts != NULL) { 31948 /* if both seconds and nanoseconds are negative or both positive, 31949 * then the ucode's subtraction is ok. 31950 * if seconds and nanoseconds have different signs, then "borrow" 31951 * 1000000000 nanoseconds from seconds. 31952 */ 31953 if ((sec < 0) && (ns > 0)) { 31954 ns -= 1000000000; 31955 sec += 1; 31956 } else if ((sec > 0) && (ns < 0)) { 31957 ns += 1000000000; 31958 sec -= 1; 31959 } 31960 31961 if (ns < 0) { 31962 /* if still negative, then something else is wrong. 31963 * the nanoseconds field is the difference between two 31964 * (non-negative) time-stamps. 31965 */ 31966 rv = BCM_E_INTERNAL; 31967 } 31968 31969 /* if seconds is negative then set the bts is-negative flag, 31970 * and use the absolute value of seconds & nanoseconds. 31971 */ 31972 bts->isnegative = (sec < 0 ? 1 : 0); 31973 bts->seconds = BCM_OAM_ABS(sec); 31974 bts->nanoseconds = BCM_OAM_ABS(ns); 31975 } else { 31976 rv = BCM_E_INTERNAL; 31977 } 31978 31979 return rv; 31980 } 31981 31982 #ifdef _SABER2_DEBUG 31983 /* d (difference) = m (minuend) - s (subtrahend) */ 31984 int 31985 bcm_oam_bhh_time_spec_subtract(bcm_time_spec_t* d, bcm_time_spec_t* m, bcm_time_spec_t* s) 31986 { 31987 int rv = BCM_E_NONE; 31988 int32 d_ns = 0; 31989 int32 d_s = 0; 31990 31991 if ((d != NULL) && (m != NULL) && (s != NULL)) { 31992 /* subtract the nanoseconds first, then borrow is necessary. */ 31993 d_ns = m->nanoseconds - s->nanoseconds; 31994 if (d_ns < 0) { 31995 m->seconds = m->seconds - 1; 31996 d_ns = 1000000000 + d_ns; 31997 } 31998 if (d_ns < 0) { 31999 /* if still negative, then error */ 32000 rv = BCM_E_INTERNAL; 32001 d_ns = abs(d_ns); 32002 } 32003 d->nanoseconds = d_ns; 32004 32005 /* subtract the seconds next, check for negative. */ 32006 d_s = m->seconds - s->seconds; 32007 if (d_s < 0) { 32008 d->isnegative = TRUE; 32009 d_s = abs(d_s); 32010 } else { 32011 d->isnegative = FALSE; 32012 } 32013 d->seconds = d_s; 32014 32015 } else { 32016 rv = BCM_E_INTERNAL; 32017 } 32018 32019 return rv; 32020 } 32021 #endif 32022 32023 /* 32024 * Function: 32025 * bcm_sb2_oam_loss_get 32026 * Purpose: 32027 * Loss Measurement get 32028 * Parameters: 32029 * unit - Device unit number 32030 * Returns: 32031 * None 32032 */ 32033 int 32034 bcm_sb2_oam_loss_get(int unit, bcm_oam_loss_t *loss_p) 32035 { 32036 _bcm_oam_control_t *oc; 32037 int rv = BCM_E_NONE; 32038 _bcm_oam_hash_data_t *h_data_p; 32039 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) 32040 uint8 *buffer, *buffer_ptr; 32041 uint16 buffer_len, reply_len; 32042 int sess_id = 0; 32043 #endif 32044 #if defined(INCLUDE_BHH) 32045 uint8 ts_mode; 32046 uint8 lm_pdu_counter_offset = 0; 32047 uint8 counter_size = 0; 32048 bcm_cos_t int_pri = 0; 32049 _mpls_label_t label; 32050 uint8 lm_counter_action[BCM_OAM_LM_COUNTER_MAX]; 32051 int i; 32052 #endif 32053 32054 /* Get OAM Control Structure. */ 32055 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 32056 _BCM_OAM_EP_INDEX_VALIDATE(loss_p->id); 32057 _BCM_OAM_LOCK(oc); 32058 32059 h_data_p = &oc->oam_hash_data[loss_p->id]; 32060 if (!(h_data_p->in_use)) { 32061 /* Endpoint not in use. */ 32062 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 32063 "Endpoint EP=%d %s.\n"), unit, loss_p->id, bcm_errmsg(rv))); 32064 _BCM_OAM_UNLOCK(oc); 32065 return BCM_E_NOT_FOUND; 32066 } 32067 32068 #if defined(INCLUDE_MPLS_LM_DM) 32069 /* Check if EP type is MPLS_LM_DM, call respective routine */ 32070 if ( MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) ) { 32071 if (oc->mpls_lm_dm_ukernel_ready) { 32072 rv = _bcm_sb2_mpls_lm_dm_loss_get(unit, h_data_p, loss_p); 32073 _BCM_OAM_UNLOCK(oc); 32074 return rv; 32075 } else { 32076 _BCM_OAM_UNLOCK(oc); 32077 return BCM_E_UNAVAIL; 32078 } 32079 } 32080 #endif 32081 32082 /* 32083 * Only BHH is supported 32084 */ 32085 if (BHH_EP_TYPE(h_data_p)) { 32086 #if defined(INCLUDE_BHH) 32087 bhh_sdk_msg_ctrl_loss_get_t msg; 32088 32089 if (oc->ukernel_not_ready) { 32090 _BCM_OAM_UNLOCK(oc); 32091 return BCM_E_INIT; 32092 } 32093 32094 BCM_OAM_BHH_VALIDATE_EP(loss_p->id); 32095 32096 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id); 32097 32098 /* Check endpoint status. */ 32099 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 32100 if ((BCM_E_EXISTS != rv)) { 32101 /* Endpoint not in use. */ 32102 LOG_ERROR(BSL_LS_BCM_OAM, 32103 (BSL_META_U(unit, 32104 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 32105 unit, loss_p->id, bcm_errmsg(rv))); 32106 _BCM_OAM_UNLOCK(oc); 32107 return (rv); 32108 } 32109 32110 sal_memset(&msg, 0, sizeof(msg)); 32111 /* Send BHH Session Update message to uC */ 32112 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 32113 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET, 32114 sess_id, 0, 32115 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_GET_REPLY, 32116 &reply_len); 32117 if(BCM_FAILURE(rv)) { 32118 LOG_ERROR(BSL_LS_BCM_OAM, 32119 (BSL_META_U(unit, 32120 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 32121 unit, loss_p->id, bcm_errmsg(rv))); 32122 _BCM_OAM_UNLOCK(oc); 32123 return (rv); 32124 } 32125 32126 /* Pack control message data into DMA buffer */ 32127 buffer = oc->dma_buffer; 32128 buffer_ptr = bhh_sdk_msg_ctrl_loss_get_unpack(buffer, &msg); 32129 buffer_len = buffer_ptr - buffer; 32130 32131 if (reply_len != buffer_len) { 32132 rv = BCM_E_INTERNAL; 32133 } else { 32134 /* 32135 * Convert kernel space flags to host space flags 32136 */ 32137 if (msg.flags & BCM_BHH_LM_SINGLE_ENDED) { 32138 loss_p->flags |= BCM_OAM_LOSS_SINGLE_ENDED; 32139 } 32140 32141 if (msg.flags & BCM_BHH_LM_TX_ENABLE) { 32142 loss_p->flags |= BCM_OAM_LOSS_TX_ENABLE; 32143 } 32144 32145 if (msg.flags & BCM_BHH_LM_SLM) { 32146 loss_p->flags |= BCM_OAM_LOSS_SLM; 32147 } 32148 32149 if (BHH_UC_FEATURE_CHECK(BHH_OLP_ENCAP_VALID)) { 32150 /* If this feature is valid, then encap_data is valid */ 32151 if (BCM_FAILURE(_bcm_sb2_oam_olp_encap_header_decap(unit, 32152 msg.encap_data, 32153 &counter_size, 32154 loss_p->lm_counter_base_id, 32155 loss_p->lm_counter_offset, 32156 lm_counter_action, 32157 &ts_mode, 32158 &lm_pdu_counter_offset, 32159 &int_pri, 32160 NULL))) 32161 { 32162 _BCM_OAM_UNLOCK(oc); 32163 return (BCM_E_INTERNAL); 32164 } 32165 loss_p->lm_counter_size = counter_size; 32166 for (i = 0; i < loss_p->lm_counter_size; i++) { 32167 loss_p->lm_counter_action[i] = lm_counter_action[i]; 32168 } 32169 _bcm_sb2_oam_bhh_get_egress_label_from_encap(h_data_p, 32170 msg.encap_data, 32171 msg.encap_length, 32172 &label); 32173 loss_p->pkt_pri = label.exp; 32174 } 32175 32176 loss_p->period = msg.period; 32177 loss_p->loss_threshold = msg.loss_threshold; 32178 loss_p->loss_nearend = msg.loss_nearend; 32179 loss_p->loss_farend = msg.loss_farend; 32180 loss_p->tx_nearend = msg.tx_nearend; 32181 loss_p->rx_nearend = msg.rx_nearend; 32182 loss_p->tx_farend = msg.tx_farend; 32183 loss_p->rx_farend = msg.rx_farend; 32184 loss_p->rx_oam_packets = msg.rx_oam_packets; 32185 loss_p->tx_oam_packets = msg.tx_oam_packets; 32186 loss_p->int_pri = int_pri; 32187 loss_p->pm_id = sess_id; 32188 rv = BCM_E_NONE; 32189 } 32190 #endif 32191 } else if (h_data_p->type == bcmOAMEndpointTypeEthernet) { 32192 #if defined(INCLUDE_ETH_LM_DM) 32193 shr_eth_lm_dm_msg_ctrl_loss_get_t msg; 32194 32195 sess_id = h_data_p->lm_dm_uc_session_id; 32196 32197 /* Validate session id. */ 32198 rv = shr_idxres_list_elem_state(oc->eth_lm_dm_pool, sess_id); 32199 if ((BCM_E_EXISTS != rv)) { 32200 /* Invalid session id */ 32201 LOG_ERROR(BSL_LS_BCM_OAM, 32202 (BSL_META_U(unit, 32203 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 32204 unit, loss_p->id, bcm_errmsg(rv))); 32205 _BCM_OAM_UNLOCK(oc); 32206 return (rv); 32207 } 32208 32209 /* Send ETH_LM_DM Session get message to uC */ 32210 rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit, 32211 MOS_MSG_SUBCLASS_ETH_LM_DM_LOSS_MEASUREMENT_GET, 32212 sess_id, 0, 32213 MOS_MSG_SUBCLASS_ETH_LM_DM_LOSS_MEASUREMENT_GET_REPLY, 32214 &reply_len); 32215 if(BCM_FAILURE(rv)) { 32216 LOG_ERROR(BSL_LS_BCM_OAM, 32217 (BSL_META_U(unit, 32218 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 32219 unit, loss_p->id, bcm_errmsg(rv))); 32220 _BCM_OAM_UNLOCK(oc); 32221 return (rv); 32222 } 32223 32224 /* Pack control message data into DMA buffer */ 32225 buffer = oc->eth_lm_dm_dma_buffer; 32226 buffer_ptr = shr_eth_lm_dm_msg_ctrl_loss_get_unpack(buffer, &msg); 32227 buffer_len = buffer_ptr - buffer; 32228 32229 if (reply_len != buffer_len) { 32230 rv = BCM_E_INTERNAL; 32231 } else { 32232 uint8 counter_size; 32233 uint8 lm_counter_action[BCM_OAM_LM_COUNTER_MAX]; 32234 int i; 32235 /* 32236 * Convert kernel space flags to host space flags 32237 */ 32238 if (msg.flags & BCM_ETH_LM_SINGLE_ENDED) { 32239 loss_p->flags |= BCM_OAM_LOSS_SINGLE_ENDED; 32240 } 32241 32242 if (msg.flags & BCM_ETH_LM_TX_ENABLE) { 32243 loss_p->flags |= BCM_OAM_LOSS_TX_ENABLE; 32244 } 32245 32246 if (msg.flags & BCM_ETH_LM_SLM) { 32247 loss_p->flags |= BCM_OAM_LOSS_SLM; 32248 } 32249 32250 if (msg.flags & BCM_ETH_LM_UPDATE) { 32251 loss_p->flags |= BCM_OAM_LOSS_UPDATE; 32252 } 32253 32254 loss_p->period = msg.period; 32255 loss_p->loss_threshold = msg.loss_threshold; 32256 loss_p->loss_nearend = msg.loss_nearend; 32257 loss_p->loss_farend = msg.loss_farend; 32258 loss_p->tx_nearend = msg.tx_nearend; 32259 loss_p->rx_nearend = msg.rx_nearend; 32260 loss_p->tx_farend = msg.tx_farend; 32261 loss_p->rx_farend = msg.rx_farend; 32262 loss_p->rx_oam_packets = msg.rx_oam_packets; 32263 loss_p->tx_oam_packets = msg.tx_oam_packets; 32264 loss_p->int_pri = msg.tx_cos; 32265 loss_p->pkt_pri = msg.tx_pri; 32266 memcpy(loss_p->peer_da_mac_address, msg.dst_mac, sizeof(bcm_mac_t)); 32267 loss_p->remote_id = msg.remote_mep_id; 32268 loss_p->pm_id = h_data_p->lm_dm_uc_session_id; 32269 32270 if (BCM_FAILURE(_bcm_sb2_oam_olp_tx_header_decap(unit, 32271 msg.olp_tx_hdr, 32272 &counter_size, 32273 loss_p->lm_counter_base_id, 32274 loss_p->lm_counter_offset, 32275 lm_counter_action, 32276 NULL, 32277 NULL, 32278 NULL, 32279 NULL))) { 32280 _BCM_OAM_UNLOCK(oc); 32281 return (BCM_E_INTERNAL); 32282 } 32283 32284 loss_p->lm_counter_size = (uint32)counter_size; 32285 for (i = 0; i < loss_p->lm_counter_size; i++) { 32286 loss_p->lm_counter_action[i] = (int)lm_counter_action[i]; 32287 } 32288 } 32289 #endif 32290 } else { 32291 _BCM_OAM_UNLOCK(oc); 32292 return BCM_E_UNAVAIL; 32293 } 32294 32295 _BCM_OAM_UNLOCK(oc); 32296 32297 return (rv); 32298 } 32299 32300 /* 32301 * Function: 32302 * bcm_sb2_oam_loss_delete 32303 * Purpose: 32304 * Loss Measurement Delete 32305 * Parameters: 32306 * unit - Device unit number 32307 * Returns: 32308 * None 32309 */ 32310 int 32311 bcm_sb2_oam_loss_delete(int unit, bcm_oam_loss_t *loss_p) 32312 { 32313 _bcm_oam_control_t *oc; 32314 int rv = BCM_E_NONE; 32315 _bcm_oam_hash_data_t *h_data_p; 32316 #if defined(INCLUDE_BHH) 32317 uint8 *buffer, *buffer_ptr; 32318 uint16 buffer_len, reply_len; 32319 int sess_id = 0; 32320 #endif 32321 32322 /* Get OAM Control Structure. */ 32323 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 32324 _BCM_OAM_EP_INDEX_VALIDATE(loss_p->id); 32325 _BCM_OAM_LOCK(oc); 32326 32327 h_data_p = &oc->oam_hash_data[loss_p->id]; 32328 if (!(h_data_p->in_use)) { 32329 /* Endpoint not in use. */ 32330 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 32331 "Endpoint EP=%d %s.\n"), unit, loss_p->id, bcm_errmsg(rv))); 32332 _BCM_OAM_UNLOCK(oc); 32333 return BCM_E_NOT_FOUND; 32334 } 32335 32336 #if defined(INCLUDE_MPLS_LM_DM) 32337 /* Check if EP type is MPLS_LM_DM, call respective routine */ 32338 if ( MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) ) { 32339 if (oc->mpls_lm_dm_ukernel_ready) { 32340 rv = _bcm_sb2_mpls_lm_dm_loss_delete(unit, h_data_p); 32341 _BCM_OAM_UNLOCK(oc); 32342 return rv; 32343 } else { 32344 _BCM_OAM_UNLOCK(oc); 32345 return BCM_E_UNAVAIL; 32346 } 32347 } 32348 #endif 32349 32350 /* 32351 * Only BHH is supported 32352 */ 32353 if (BHH_EP_TYPE(h_data_p)) { 32354 #if defined(INCLUDE_BHH) 32355 shr_bhh_msg_ctrl_loss_delete_t msg; 32356 32357 if (oc->ukernel_not_ready) { 32358 _BCM_OAM_UNLOCK(oc); 32359 return BCM_E_INIT; 32360 } 32361 32362 BCM_OAM_BHH_VALIDATE_EP(loss_p->id); 32363 32364 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(loss_p->id); 32365 32366 /* Check endpoint status. */ 32367 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 32368 if ((BCM_E_EXISTS != rv)) { 32369 /* Endpoint not in use. */ 32370 LOG_ERROR(BSL_LS_BCM_OAM, 32371 (BSL_META_U(unit, 32372 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 32373 unit, loss_p->id, bcm_errmsg(rv))); 32374 _BCM_OAM_UNLOCK(oc); 32375 return (rv); 32376 } 32377 32378 h_data_p = &oc->oam_hash_data[loss_p->id]; 32379 32380 if (h_data_p->int_flags & _BCM_OAM_ENDPOINT_BHH_PROACTIVE_LM) { 32381 LOG_ERROR(BSL_LS_BCM_OAM, 32382 (BSL_META_U(unit, 32383 "OAM(unit %d) Error: Proactive LM is enabled " 32384 " No on demand LM on EP=%d \n"), 32385 unit, loss_p->id)); 32386 _BCM_OAM_UNLOCK(oc); 32387 return BCM_E_NOT_FOUND; 32388 } 32389 msg.sess_id = sess_id; 32390 32391 /* Pack control message data into DMA buffer */ 32392 buffer = oc->dma_buffer; 32393 buffer_ptr = shr_bhh_msg_ctrl_loss_delete_pack(buffer, &msg); 32394 buffer_len = buffer_ptr - buffer; 32395 32396 /* Send BHH Session Update message to uC */ 32397 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 32398 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE, 32399 buffer_len, 0, 32400 MOS_MSG_SUBCLASS_BHH_LOSS_MEASUREMENT_DELETE_REPLY, 32401 &reply_len); 32402 32403 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 32404 rv = BCM_E_INTERNAL; 32405 } 32406 #endif 32407 } else if (h_data_p->type == bcmOAMEndpointTypeEthernet) { 32408 #if defined(INCLUDE_ETH_LM_DM) 32409 if (h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_LM_IS_SET) { 32410 rv = _bcm_sb2_eth_lm_dm_loss_delete(unit, oc, h_data_p); 32411 _BCM_OAM_UNLOCK(oc); 32412 return rv; 32413 } else { 32414 _BCM_OAM_UNLOCK(oc); 32415 return BCM_E_EMPTY; 32416 } 32417 #endif 32418 } else { 32419 _BCM_OAM_UNLOCK(oc); 32420 return BCM_E_UNAVAIL; 32421 } 32422 32423 _BCM_OAM_UNLOCK(oc); 32424 32425 return (rv); 32426 } 32427 32428 /* 32429 * Function: 32430 * bcm_sb2_oam_delay_add 32431 * Purpose: 32432 * Delay Measurement add 32433 * Parameters: 32434 * unit - Device unit number 32435 * Returns: 32436 * None 32437 */ 32438 int 32439 bcm_sb2_oam_delay_add(int unit, bcm_oam_delay_t *delay_p) 32440 { 32441 _bcm_oam_control_t *oc; 32442 _bcm_oam_hash_data_t *h_data_p; 32443 int rv = BCM_E_NONE; 32444 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) 32445 uint8 *buffer, *buffer_ptr; 32446 uint16 buffer_len, reply_len; 32447 uint32 flags = 0; 32448 int sess_id = 0; 32449 #endif 32450 #if defined(INCLUDE_BHH) 32451 _bhh_oam_lm_dm_info_t counter_info; 32452 bcm_module_t module_id; 32453 bcm_port_t port_id; 32454 bcm_trunk_t trunk_id; 32455 int local_id, i = 0; 32456 uint8 encap_type; 32457 #endif 32458 32459 /* Get OAM Control Structure. */ 32460 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 32461 _BCM_OAM_EP_INDEX_VALIDATE(delay_p->id); 32462 _BCM_OAM_LOCK(oc); 32463 32464 h_data_p = &oc->oam_hash_data[delay_p->id]; 32465 if (!(h_data_p->in_use)) { 32466 /* Endpoint not in use. */ 32467 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 32468 "Endpoint EP=%d %s.\n"), unit, delay_p->id, bcm_errmsg(rv))); 32469 _BCM_OAM_UNLOCK(oc); 32470 return BCM_E_NOT_FOUND; 32471 } 32472 32473 #if defined(INCLUDE_MPLS_LM_DM) 32474 /* Check if EP type is MPLS_LM_DM, call respective routine */ 32475 if ( MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) ) { 32476 if (oc->mpls_lm_dm_ukernel_ready) { 32477 rv = _bcm_sb2_mpls_lm_dm_delay_add(unit, h_data_p, delay_p); 32478 _BCM_OAM_UNLOCK(oc); 32479 return rv; 32480 } else { 32481 _BCM_OAM_UNLOCK(oc); 32482 return BCM_E_UNAVAIL; 32483 } 32484 } 32485 #endif 32486 /* 32487 * Only BHH is supported 32488 */ 32489 if (BHH_EP_TYPE(h_data_p)) { 32490 #if defined(INCLUDE_BHH) 32491 32492 if (oc->ukernel_not_ready) { 32493 _BCM_OAM_UNLOCK(oc); 32494 return BCM_E_INIT; 32495 } 32496 32497 rv = _bcm_sb2_oam_period_validate(delay_p->period); 32498 if (BCM_FAILURE(rv)) { 32499 LOG_ERROR(BSL_LS_BCM_OAM, 32500 (BSL_META_U(unit, 32501 "OAM(unit %d) Error: Invalid period : %d\n"), 32502 unit, delay_p->period)); 32503 _BCM_OAM_UNLOCK(oc); 32504 return (rv); 32505 } 32506 32507 sal_memset(&counter_info, 0, sizeof(counter_info)); 32508 counter_info.counter_size = delay_p->dm_tx_update_lm_counter_size; 32509 for (i=0; i< BCM_OAM_LM_COUNTER_MAX; i++) 32510 { 32511 counter_info.counter_base_id[i] = 32512 delay_p->dm_tx_update_lm_counter_base_id[i]; 32513 counter_info.counter_offset[i] = 32514 delay_p->dm_tx_update_lm_counter_offset[i]; 32515 counter_info.counter_action[i] = bcmOamCounterActionIncrement; 32516 counter_info.byte_count_offset[i] = 0; 32517 } 32518 counter_info.oam_replacement_offset = SHR_BHH_HEADER_LENGTH; 32519 bhh_sdk_msg_ctrl_delay_add_t msg; 32520 BCM_OAM_BHH_VALIDATE_EP(delay_p->id); 32521 32522 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id); 32523 32524 /* Check endpoint status. */ 32525 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 32526 if ((BCM_E_EXISTS != rv)) { 32527 /* Endpoint not in use. */ 32528 LOG_ERROR(BSL_LS_BCM_OAM, 32529 (BSL_META_U(unit, 32530 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 32531 unit, delay_p->id, bcm_errmsg(rv))); 32532 _BCM_OAM_UNLOCK(oc); 32533 return (rv); 32534 } 32535 32536 if (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU) { 32537 _BCM_OAM_UNLOCK(oc); 32538 return BCM_E_PARAM; 32539 } 32540 32541 /* 32542 * Convert host space flags to uKernel space flags 32543 */ 32544 if (delay_p->flags & BCM_OAM_DELAY_ONE_WAY) { 32545 flags |= BCM_BHH_DM_ONE_WAY; 32546 } 32547 32548 if (delay_p->flags & BCM_OAM_DELAY_TX_ENABLE) { 32549 flags |= BCM_BHH_DM_TX_ENABLE; 32550 } 32551 32552 sal_memset(&msg, 0, sizeof(msg)); 32553 msg.flags = flags; 32554 msg.sess_id = sess_id; 32555 32556 h_data_p->ts_format = delay_p->timestamp_format; 32557 32558 if(delay_p->timestamp_format == bcmOAMTimestampFormatIEEE1588v1) { 32559 msg.dm_format = BCM_BHH_DM_TYPE_PTP; 32560 counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_PTP; 32561 } else { 32562 msg.dm_format = BCM_BHH_DM_TYPE_NTP; 32563 counter_info.ts_mode = BCM_PKT_TIMESTAMP_MODE_NTP; 32564 } 32565 /* 32566 * Set period 32567 */ 32568 msg.period = _sb2_ccm_intervals[_bcm_sb2_oam_ccm_msecs_to_hw_encode(delay_p->period)]; 32569 msg.int_pri = delay_p->int_pri; 32570 msg.pkt_pri = delay_p->pkt_pri; 32571 32572 if (h_data_p->trunk_id == BCM_TRUNK_INVALID) { 32573 rv = _bcm_esw_gport_resolve(unit, 32574 h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id); 32575 } else { 32576 rv = _bcm_esw_gport_resolve(unit, 32577 h_data_p->resolved_trunk_gport, &module_id, &port_id, 32578 &trunk_id, &local_id); 32579 } 32580 /* 32581 * Set the BHH encapsulation data 32582 * 32583 * The function _bcm_sb2_oam_bhh_encap_create() is called first 32584 * since this sets some fields in 'hash_data' which are 32585 * used in the message. 32586 */ 32587 rv = _bcm_sb2_oam_bhh_encap_create(unit, module_id, port_id, h_data_p, 32588 msg.encap_data, &encap_type, 32589 &msg.encap_length, &counter_info, 32590 delay_p->int_pri, delay_p->pkt_pri, 32591 h_data_p->egr_label_ttl); 32592 if(BCM_FAILURE(rv)) 32593 { 32594 LOG_ERROR(BSL_LS_BCM_OAM, 32595 (BSL_META_U(unit, 32596 "BHH(unit %d) Error: Encap create failed " 32597 " - %s.\n"), 32598 unit, bcm_errmsg(rv))); 32599 _BCM_OAM_UNLOCK(oc); 32600 return (rv); 32601 } 32602 32603 /* Only Data tlv is supported */ 32604 for (i = 0; i < BCM_OAM_MAX_NUM_TLVS_FOR_DM; i++) { 32605 if (delay_p->tlvs[i].tlv_type == bcmOamTlvTypeData) { 32606 32607 msg.data_tlv_len = delay_p->tlvs[i].tlv_length; 32608 } 32609 } 32610 32611 /* Pack control message data into DMA buffer */ 32612 buffer = oc->dma_buffer; 32613 buffer_ptr = bhh_sdk_msg_ctrl_delay_add_pack(buffer, &msg); 32614 buffer_len = buffer_ptr - buffer; 32615 32616 /* Send BHH Session Update message to uC */ 32617 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 32618 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD, 32619 buffer_len, 0, 32620 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_ADD_REPLY, 32621 &reply_len); 32622 32623 delay_p->pm_id = sess_id; 32624 32625 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 32626 rv = BCM_E_INTERNAL; 32627 } 32628 #endif 32629 } else if (h_data_p->type == bcmOAMEndpointTypeEthernet) { 32630 #if defined(INCLUDE_ETH_LM_DM) 32631 shr_eth_lm_dm_msg_ctrl_delay_add_t msg; 32632 bcm_port_t port_id; 32633 bcm_module_t module_id; 32634 int local_id; 32635 bcm_trunk_t trunk_id; 32636 uint8 mep_type; 32637 uint8 dm_format; 32638 shr_eth_lm_dm_msg_ctrl_sess_set_t msg_sess; 32639 int cpu_modid; 32640 bcm_port_t cpu_port; 32641 int cpu_dglp; 32642 uint32 olp_l2_encap_length; 32643 int session_flags = 0; 32644 32645 32646 if (1 == oc->eth_lm_dm_ukernel_not_ready) { 32647 LOG_ERROR(BSL_LS_BCM_OAM, 32648 (BSL_META_U(unit, 32649 "ETH_LM_DM(unit %d) Error: BTE(ukernel) not ready.\n"), 32650 unit)); 32651 _BCM_OAM_UNLOCK(oc); 32652 return (BCM_E_INIT); 32653 } 32654 32655 /* Get the Trunk, Port and Mod-id info for this G-port */ 32656 rv = _bcm_esw_gport_resolve(unit, 32657 h_data_p->gport, &module_id, &port_id, &trunk_id, &local_id); 32658 32659 if (BCM_FAILURE(rv)) { 32660 LOG_ERROR(BSL_LS_BCM_OAM, 32661 (BSL_META_U(unit, 32662 "ETH_LM_DM(unit %d) Error: Gport resolve (EP=%d) - %s.\n"), 32663 unit, delay_p->id, bcm_errmsg(rv))); 32664 _BCM_OAM_UNLOCK(oc); 32665 return (rv); 32666 } 32667 32668 /* Reserve and program session Id for this EP */ 32669 /* ------------------------------------------ */ 32670 if (h_data_p->lm_dm_uc_session_id == 0 ) { 32671 rv = shr_idxres_list_alloc(oc->eth_lm_dm_pool, 32672 (shr_idxres_element_t *)&sess_id); 32673 32674 if (BCM_FAILURE(rv)) { 32675 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "ETH_LM_DM (unit %d) Error:" 32676 " Session Id alloc failed EP:%d %s.\n"), unit, h_data_p->ep_id, 32677 bcm_errmsg(rv))); 32678 _BCM_OAM_UNLOCK(oc); 32679 return (rv); 32680 } 32681 h_data_p->lm_dm_uc_session_id = sess_id; 32682 } else { 32683 sess_id = h_data_p->lm_dm_uc_session_id; 32684 } 32685 oc->eth_lm_dm_sess_id_ep_id[sess_id] = h_data_p->ep_id; 32686 32687 /* Set end-point type(dir) from the hash data flag*/ 32688 if (h_data_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 32689 mep_type = 1; 32690 } else { 32691 mep_type = 0; 32692 } 32693 32694 if (delay_p->timestamp_format == bcmOAMTimestampFormatNTP) { 32695 dm_format = BCM_ETH_LM_DM_RPL_TYPE_NTP_DM; 32696 } else if (delay_p->timestamp_format == bcmOAMTimestampFormatIEEE1588v1) { 32697 dm_format = BCM_ETH_LM_DM_RPL_TYPE_PTP_DM; 32698 } else { 32699 _BCM_OAM_UNLOCK(oc); 32700 return BCM_E_PARAM; 32701 } 32702 32703 /* Get the cpu_dglp from cpu_modid and cpu_port*/ 32704 rv = bcm_esw_stk_my_modid_get(unit, &cpu_modid); 32705 if (BCM_FAILURE(rv)) { 32706 LOG_ERROR(BSL_LS_BCM_OAM, 32707 (BSL_META_U(unit, 32708 "OAM(unit %d) Error: MODID get failed - %s.\n"), 32709 unit, bcm_errmsg(rv))); 32710 _BCM_OAM_UNLOCK(oc); 32711 return (rv); 32712 } 32713 cpu_port = 0; 32714 cpu_dglp = ((cpu_modid << DGLP_MODULE_ID_SHIFT_BITS) + cpu_port); 32715 32716 rv = _bcm_sb2_oam_eth_olp_encap_create(unit, 32717 port_id, 32718 cpu_dglp, 32719 h_data_p, 32720 msg_sess.encap_data, 32721 &msg_sess.eth_l2_encap_length, 32722 &olp_l2_encap_length, 32723 delay_p->pkt_pri); 32724 32725 32726 if (BCM_FAILURE(rv)) { 32727 LOG_ERROR(BSL_LS_BCM_OAM, 32728 (BSL_META_U(unit, 32729 "ETH_LM_DM(unit %d) Error: encap create (EP=%d) - %s.\n"), 32730 unit, delay_p->id, bcm_errmsg(rv))); 32731 _BCM_OAM_UNLOCK(oc); 32732 return (rv); 32733 } 32734 32735 msg_sess.sess_id = sess_id; 32736 msg_sess.mep_id = h_data_p->ep_id; 32737 32738 /* Set end-point type(dir) in session set message*/ 32739 msg_sess.mep_type = mep_type; 32740 32741 msg_sess.mel = h_data_p->level; 32742 msg_sess.vlan_id = h_data_p->inner_vlan; 32743 msg_sess.outer_vlan_id = h_data_p->vlan; 32744 msg_sess.lm_counter_index = h_data_p->tx_ctr; 32745 msg_sess.group_id = h_data_p->group_index; 32746 msg_sess.tx_port = port_id; 32747 32748 /* Check if session is already created in uKernel */ 32749 if(!(h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_SESSION_IS_SET)) { 32750 session_flags = SHR_ETH_LM_DM_SESS_SET_F_CREATE; 32751 } 32752 if (h_data_p->lm_dm_int_flag & SHR_ETH_LM_DM_SESS_SET_F_LM) { 32753 session_flags |= SHR_ETH_LM_DM_SESS_SET_F_LM; 32754 } 32755 32756 session_flags |= SHR_ETH_LM_DM_SESS_SET_F_DM; 32757 32758 msg_sess.flags = session_flags; 32759 /* Pack control message data into DMA buffer */ 32760 buffer = oc->eth_lm_dm_dma_buffer; 32761 buffer_ptr = shr_eth_lm_dm_msg_ctrl_sess_set_pack(buffer, &msg_sess); 32762 buffer_len = buffer_ptr - buffer; 32763 32764 /* Send BHH Session Update message to uC */ 32765 rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit, 32766 MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_SET, 32767 buffer_len, 0, 32768 MOS_MSG_SUBCLASS_ETH_LM_DM_SESS_SET_REPLY, 32769 &reply_len); 32770 32771 if(BCM_FAILURE(rv)) { 32772 LOG_ERROR(BSL_LS_BCM_OAM, 32773 (BSL_META_U(unit, 32774 "OAM(unit %d) Error Session set: Endpoint EP=%d %s.\n"), 32775 unit, delay_p->id, bcm_errmsg(rv))); 32776 _BCM_OAM_UNLOCK(oc); 32777 return (rv); 32778 } 32779 32780 /* Session has been set in the endpoint */ 32781 h_data_p->lm_dm_int_flag |= _ETH_LM_DM_F_SESSION_IS_SET; 32782 32783 32784 msg.period = _sb2_ccm_intervals[_bcm_sb2_oam_ccm_msecs_to_hw_encode(delay_p->period)]; 32785 /* 32786 * Convert host space flags to uKernel space flags 32787 */ 32788 if (delay_p->flags & BCM_OAM_DELAY_ONE_WAY) { 32789 flags |= BCM_ETH_DM_ONE_WAY; 32790 } 32791 32792 if (delay_p->flags & BCM_OAM_DELAY_TX_ENABLE) { 32793 flags |= BCM_ETH_DM_TX_ENABLE; 32794 } else { 32795 msg.period = BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED; 32796 } 32797 32798 if (delay_p->flags & BCM_OAM_DELAY_UPDATE) { 32799 flags |= BCM_ETH_DM_UPDATE; 32800 } 32801 32802 msg.flags = flags; 32803 msg.sess_id = sess_id; 32804 msg.dm_format = dm_format; 32805 32806 /* Pkt TX params */ 32807 msg.tx_qnum = SOC_INFO(unit).port_uc_cosq_base[port_id] + delay_p->int_pri; 32808 msg.tx_cos = delay_p->int_pri; 32809 msg.tx_pri = delay_p->pkt_pri; 32810 32811 /* MAC-DA of delay_add struture is put into the L2 encap of Loss Tx control pkt*/ 32812 memcpy(msg.dst_mac, delay_p->peer_da_mac_address, sizeof(bcm_mac_t)); 32813 32814 msg.remote_mep_id = delay_p->remote_id; 32815 32816 /* Put OLP_TX header in loss add structure */ 32817 rv = _bcm_sb2_oam_delay_olp_tx_encap_create(unit, 32818 h_data_p, 32819 msg.olp_tx_hdr, 32820 &msg.olp_tx_hdr_length, 32821 delay_p, 32822 port_id, 32823 module_id, 32824 mep_type, 32825 dm_format); 32826 32827 32828 /* Pack control message data into DMA buffer */ 32829 buffer = oc->eth_lm_dm_dma_buffer; 32830 buffer_ptr = shr_eth_lm_dm_msg_ctrl_delay_add_pack(buffer, &msg); 32831 buffer_len = buffer_ptr - buffer; 32832 32833 /* Send BHH Session Update message to uC */ 32834 rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit, 32835 MOS_MSG_SUBCLASS_ETH_LM_DM_DELAY_MEASUREMENT_ADD, 32836 buffer_len, 0, 32837 MOS_MSG_SUBCLASS_ETH_LM_DM_DELAY_MEASUREMENT_ADD_REPLY, 32838 &reply_len); 32839 32840 h_data_p->lm_dm_int_flag |= _ETH_LM_DM_F_DM_IS_SET; 32841 32842 delay_p->pm_id = h_data_p->lm_dm_uc_session_id; 32843 32844 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 32845 rv = BCM_E_INTERNAL; 32846 } 32847 #endif 32848 } else { 32849 _BCM_OAM_UNLOCK(oc); 32850 return BCM_E_UNAVAIL; 32851 } 32852 32853 _BCM_OAM_UNLOCK(oc); 32854 return (rv); 32855 } 32856 32857 /* 32858 * Function: 32859 * bcm_sb2_oam_delay_get 32860 * Purpose: 32861 * Delay Measurements get 32862 * Parameters: 32863 * unit - Device unit number 32864 * Returns: 32865 * None 32866 */ 32867 int 32868 bcm_sb2_oam_delay_get(int unit, bcm_oam_delay_t *delay_p) 32869 { 32870 _bcm_oam_control_t *oc; 32871 int rv = BCM_E_NONE; 32872 _bcm_oam_hash_data_t *h_data_p; 32873 #if defined(INCLUDE_BHH) || defined(INCLUDE_ETH_LM_DM) 32874 uint8 *buffer, *buffer_ptr; 32875 uint16 buffer_len, reply_len; 32876 int sess_id = 0; 32877 #endif 32878 #if defined(INCLUDE_BHH) 32879 uint8 ts_mode; 32880 uint8 lm_pdu_counter_offset = 0; 32881 uint8 lm_counter_action[BCM_OAM_LM_COUNTER_MAX]; 32882 bcm_cos_t int_pri = 0; 32883 _mpls_label_t label; 32884 #endif 32885 32886 /* Get OAM Control Structure. */ 32887 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 32888 _BCM_OAM_EP_INDEX_VALIDATE(delay_p->id); 32889 _BCM_OAM_LOCK(oc); 32890 32891 h_data_p = &oc->oam_hash_data[delay_p->id]; 32892 if (!(h_data_p->in_use)) { 32893 /* Endpoint not in use. */ 32894 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 32895 "Endpoint EP=%d %s.\n"), unit, delay_p->id, bcm_errmsg(rv))); 32896 _BCM_OAM_UNLOCK(oc); 32897 return BCM_E_NOT_FOUND; 32898 } 32899 32900 #if defined(INCLUDE_MPLS_LM_DM) 32901 /* Check if EP type is MPLS_LM_DM, call respective routine */ 32902 if ( MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) ) { 32903 if (oc->mpls_lm_dm_ukernel_ready) { 32904 rv = _bcm_sb2_mpls_lm_dm_delay_get(unit, h_data_p, delay_p); 32905 _BCM_OAM_UNLOCK(oc); 32906 return rv; 32907 } else { 32908 _BCM_OAM_UNLOCK(oc); 32909 return BCM_E_UNAVAIL; 32910 } 32911 } 32912 #endif 32913 32914 /* 32915 * Only BHH is supported 32916 */ 32917 if (BHH_EP_TYPE(h_data_p)) { 32918 #if defined(INCLUDE_BHH) 32919 bhh_sdk_msg_ctrl_delay_get_t msg; 32920 32921 if (oc->ukernel_not_ready) { 32922 _BCM_OAM_UNLOCK(oc); 32923 return BCM_E_INIT; 32924 } 32925 32926 BCM_OAM_BHH_VALIDATE_EP(delay_p->id); 32927 32928 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id); 32929 32930 /* Check endpoint status. */ 32931 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 32932 if ((BCM_E_EXISTS != rv)) { 32933 /* Endpoint not in use. */ 32934 LOG_ERROR(BSL_LS_BCM_OAM, 32935 (BSL_META_U(unit, 32936 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 32937 unit, delay_p->id, bcm_errmsg(rv))); 32938 _BCM_OAM_UNLOCK(oc); 32939 return (rv); 32940 } 32941 32942 sal_memset(&msg, 0, sizeof(msg)); 32943 /* Send BHH Session Update message to uC */ 32944 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 32945 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET, 32946 sess_id, 0, 32947 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_GET_REPLY, 32948 &reply_len); 32949 if(BCM_FAILURE(rv)) { 32950 LOG_ERROR(BSL_LS_BCM_OAM, 32951 (BSL_META_U(unit, 32952 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 32953 unit, delay_p->id, bcm_errmsg(rv))); 32954 _BCM_OAM_UNLOCK(oc); 32955 return (rv); 32956 } 32957 32958 /* Pack control message data into DMA buffer */ 32959 buffer = oc->dma_buffer; 32960 buffer_ptr = bhh_sdk_msg_ctrl_delay_get_unpack(buffer, &msg); 32961 buffer_len = buffer_ptr - buffer; 32962 32963 32964 if (reply_len != buffer_len) { 32965 rv = BCM_E_INTERNAL; 32966 } else { 32967 /* 32968 * Convert kernel space flags to host space flags 32969 */ 32970 if (msg.flags & BCM_BHH_DM_ONE_WAY) { 32971 delay_p->flags |= BCM_OAM_DELAY_ONE_WAY; 32972 } 32973 32974 if (msg.flags & BCM_BHH_DM_TX_ENABLE) { 32975 delay_p->flags |= BCM_OAM_DELAY_TX_ENABLE; 32976 } 32977 32978 delay_p->period = msg.period; 32979 32980 if(msg.dm_format == BCM_BHH_DM_TYPE_PTP) 32981 delay_p->timestamp_format = bcmOAMTimestampFormatIEEE1588v1; 32982 else 32983 delay_p->timestamp_format = bcmOAMTimestampFormatNTP; 32984 32985 rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->delay), 32986 msg.delay_seconds, msg.delay_nanoseconds); 32987 if(BCM_SUCCESS(rv)) { 32988 rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->txf), 32989 msg.txf_seconds, msg.txf_nanoseconds); 32990 } 32991 if(BCM_SUCCESS(rv)) { 32992 rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->rxf), 32993 msg.rxf_seconds, msg.rxf_nanoseconds); 32994 } 32995 if(BCM_SUCCESS(rv)) { 32996 rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->txb), 32997 msg.txb_seconds, msg.txb_nanoseconds); 32998 } 32999 if(BCM_SUCCESS(rv)) { 33000 rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->rxb), 33001 msg.rxb_seconds, msg.rxb_nanoseconds); 33002 } 33003 33004 if (BHH_UC_FEATURE_CHECK(BHH_OLP_ENCAP_VALID)) { 33005 /* If this feature is valid, then encap_data is valid */ 33006 if (BCM_FAILURE(_bcm_sb2_oam_olp_encap_header_decap(unit, 33007 msg.encap_data, 33008 &(delay_p->dm_tx_update_lm_counter_size), 33009 delay_p->dm_tx_update_lm_counter_base_id, 33010 delay_p->dm_tx_update_lm_counter_offset, 33011 lm_counter_action, 33012 &ts_mode, 33013 &lm_pdu_counter_offset, 33014 &int_pri, 33015 NULL))) 33016 { 33017 _BCM_OAM_UNLOCK(oc); 33018 return (BCM_E_INTERNAL); 33019 } 33020 _bcm_sb2_oam_bhh_get_egress_label_from_encap(h_data_p, 33021 msg.encap_data, 33022 msg.encap_length, 33023 &label); 33024 delay_p->pkt_pri = label.exp; 33025 } 33026 33027 delay_p->rx_oam_packets = msg.rx_oam_packets; 33028 delay_p->tx_oam_packets = msg.tx_oam_packets; 33029 delay_p->int_pri = int_pri; 33030 delay_p->pm_id = sess_id; 33031 if (msg.data_tlv_len) { 33032 delay_p->tlvs[0].tlv_type = bcmOamTlvTypeData; 33033 delay_p->tlvs[0].tlv_length = msg.data_tlv_len; 33034 } 33035 rv = BCM_E_NONE; 33036 } 33037 #endif 33038 } else if (h_data_p->type == bcmOAMEndpointTypeEthernet) { 33039 #if defined(INCLUDE_ETH_LM_DM) 33040 shr_eth_lm_dm_msg_ctrl_delay_get_t msg; 33041 33042 sess_id = h_data_p->lm_dm_uc_session_id; 33043 33044 /* Validate session id. */ 33045 rv = shr_idxres_list_elem_state(oc->eth_lm_dm_pool, sess_id); 33046 if ((BCM_E_EXISTS != rv)) { 33047 /* Invalid session id */ 33048 LOG_ERROR(BSL_LS_BCM_OAM, 33049 (BSL_META_U(unit, 33050 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 33051 unit, delay_p->id, bcm_errmsg(rv))); 33052 _BCM_OAM_UNLOCK(oc); 33053 return (rv); 33054 } 33055 33056 /* Send ETH_LM_DM Delay get message to uC */ 33057 rv = _bcm_sb2_oam_eth_lm_dm_msg_send_receive(unit, 33058 MOS_MSG_SUBCLASS_ETH_LM_DM_DELAY_MEASUREMENT_GET, 33059 sess_id, 0, 33060 MOS_MSG_SUBCLASS_ETH_LM_DM_DELAY_MEASUREMENT_GET_REPLY, 33061 &reply_len); 33062 33063 if(BCM_FAILURE(rv)) { 33064 LOG_ERROR(BSL_LS_BCM_OAM, 33065 (BSL_META_U(unit, 33066 "OAM(unit %d) Error Delay Get: Endpoint EP=%d %s.\n"), 33067 unit, delay_p->id, bcm_errmsg(rv))); 33068 _BCM_OAM_UNLOCK(oc); 33069 return (rv); 33070 } 33071 33072 /* Pack control message data into DMA buffer */ 33073 buffer = oc->eth_lm_dm_dma_buffer; 33074 buffer_ptr = shr_eth_lm_dm_msg_ctrl_delay_get_unpack(buffer, &msg); 33075 buffer_len = buffer_ptr - buffer; 33076 33077 if (reply_len != buffer_len) { 33078 rv = BCM_E_INTERNAL; 33079 } else { 33080 /* 33081 * Convert kernel space flags to host space flags 33082 */ 33083 if (msg.flags & BCM_ETH_DM_ONE_WAY) { 33084 delay_p->flags |= BCM_OAM_DELAY_ONE_WAY; 33085 } 33086 33087 if (msg.flags & BCM_ETH_DM_TX_ENABLE) { 33088 delay_p->flags |= BCM_OAM_DELAY_TX_ENABLE; 33089 } 33090 33091 if (msg.flags & BCM_ETH_DM_UPDATE) { 33092 delay_p->flags |= BCM_OAM_DELAY_UPDATE; 33093 } 33094 33095 delay_p->period = msg.period; 33096 33097 if(msg.dm_format == BCM_ETH_LM_DM_RPL_TYPE_PTP_DM) { 33098 delay_p->timestamp_format = bcmOAMTimestampFormatIEEE1588v1; 33099 } else { 33100 delay_p->timestamp_format = bcmOAMTimestampFormatNTP; 33101 } 33102 33103 rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->delay), 33104 msg.delay_seconds, msg.delay_nanoseconds); 33105 if(BCM_SUCCESS(rv)) { 33106 rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->txf), 33107 msg.txf_seconds, msg.txf_nanoseconds); 33108 } 33109 if(BCM_SUCCESS(rv)) { 33110 rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->rxf), 33111 msg.rxf_seconds, msg.rxf_nanoseconds); 33112 } 33113 if(BCM_SUCCESS(rv)) { 33114 rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->txb), 33115 msg.txb_seconds, msg.txb_nanoseconds); 33116 } 33117 if(BCM_SUCCESS(rv)) { 33118 rv = bcm_sb2_oam_convert_ep_to_time_spec(&(delay_p->rxb), 33119 msg.rxb_seconds, msg.rxb_nanoseconds); 33120 } 33121 delay_p->rx_oam_packets = msg.rx_oam_packets; 33122 delay_p->tx_oam_packets = msg.tx_oam_packets; 33123 delay_p->int_pri = msg.tx_cos; 33124 delay_p->pkt_pri = msg.tx_pri; 33125 memcpy(delay_p->peer_da_mac_address, msg.dst_mac, sizeof(bcm_mac_t)); 33126 delay_p->remote_id = msg.remote_mep_id; 33127 delay_p->pm_id = h_data_p->lm_dm_uc_session_id; 33128 33129 if (BCM_FAILURE(_bcm_sb2_oam_olp_tx_header_decap(unit, 33130 msg.olp_tx_hdr, 33131 &delay_p->dm_tx_update_lm_counter_size, 33132 delay_p->dm_tx_update_lm_counter_base_id, 33133 delay_p->dm_tx_update_lm_counter_offset, 33134 NULL, 33135 NULL, 33136 NULL, 33137 NULL, 33138 NULL))) { 33139 _BCM_OAM_UNLOCK(oc); 33140 return (BCM_E_INTERNAL); 33141 } 33142 33143 rv = BCM_E_NONE; 33144 33145 } 33146 #endif 33147 } 33148 else { 33149 _BCM_OAM_UNLOCK(oc); 33150 return BCM_E_UNAVAIL; 33151 } 33152 33153 _BCM_OAM_UNLOCK(oc); 33154 33155 return (rv); 33156 } 33157 33158 /* 33159 * Function: 33160 * bcm_sb2_oam_delay_delete 33161 * Purpose: 33162 * Delay Measurement Delete 33163 * Parameters: 33164 * unit - Device unit number 33165 * Returns: 33166 * None 33167 */ 33168 int 33169 bcm_sb2_oam_delay_delete(int unit, bcm_oam_delay_t *delay_p) 33170 { 33171 _bcm_oam_control_t *oc; 33172 int rv = BCM_E_NONE; 33173 _bcm_oam_hash_data_t *h_data_p; 33174 #if defined(INCLUDE_BHH) 33175 uint8 *buffer, *buffer_ptr; 33176 uint16 buffer_len, reply_len; 33177 int sess_id = 0; 33178 #endif 33179 33180 /* Get OAM Control Structure. */ 33181 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 33182 _BCM_OAM_EP_INDEX_VALIDATE(delay_p->id); 33183 _BCM_OAM_LOCK(oc); 33184 33185 h_data_p = &oc->oam_hash_data[delay_p->id]; 33186 33187 if (!(h_data_p->in_use)) { 33188 /* Endpoint not in use. */ 33189 LOG_ERROR(BSL_LS_BCM_OAM, (BSL_META_U(unit, "OAM(unit %d) Error: " 33190 "Endpoint EP=%d %s.\n"), unit, delay_p->id, bcm_errmsg(rv))); 33191 _BCM_OAM_UNLOCK(oc); 33192 return BCM_E_NOT_FOUND; 33193 } 33194 33195 #if defined(INCLUDE_MPLS_LM_DM) 33196 /* Check if EP type is MPLS_LM_DM, call respective routine */ 33197 if ( MPLS_LM_DM_ENDPOINT_TYPE(h_data_p) ) { 33198 if (oc->mpls_lm_dm_ukernel_ready) { 33199 rv = _bcm_sb2_mpls_lm_dm_delay_delete(unit, h_data_p); 33200 _BCM_OAM_UNLOCK(oc); 33201 return rv; 33202 } else { 33203 _BCM_OAM_UNLOCK(oc); 33204 return BCM_E_UNAVAIL; 33205 } 33206 } 33207 #endif 33208 33209 /* 33210 * Only BHH is supported 33211 */ 33212 if (BHH_EP_TYPE(h_data_p)) { 33213 #if defined(INCLUDE_BHH) 33214 shr_bhh_msg_ctrl_delay_delete_t msg; 33215 33216 if (oc->ukernel_not_ready) { 33217 _BCM_OAM_UNLOCK(oc); 33218 return BCM_E_INIT; 33219 } 33220 33221 BCM_OAM_BHH_VALIDATE_EP(delay_p->id); 33222 33223 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(delay_p->id); 33224 33225 /* Check endpoint status. */ 33226 rv = shr_idxres_list_elem_state(oc->bhh_pool, sess_id); 33227 if ((BCM_E_EXISTS != rv)) { 33228 /* Endpoint not in use. */ 33229 LOG_ERROR(BSL_LS_BCM_OAM, 33230 (BSL_META_U(unit, 33231 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 33232 unit, delay_p->id, bcm_errmsg(rv))); 33233 _BCM_OAM_UNLOCK(oc); 33234 return (rv); 33235 } 33236 33237 msg.sess_id = sess_id; 33238 33239 /* Pack control message data into DMA buffer */ 33240 buffer = oc->dma_buffer; 33241 buffer_ptr = shr_bhh_msg_ctrl_delay_delete_pack(buffer, &msg); 33242 buffer_len = buffer_ptr - buffer; 33243 33244 /* Send BHH Session Update message to uC */ 33245 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 33246 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE, 33247 buffer_len, 0, 33248 MOS_MSG_SUBCLASS_BHH_DELAY_MEASUREMENT_DELETE_REPLY, 33249 &reply_len); 33250 33251 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 33252 rv = BCM_E_INTERNAL; 33253 } 33254 #endif 33255 } else if (h_data_p->type == bcmOAMEndpointTypeEthernet){ 33256 #if defined(INCLUDE_ETH_LM_DM) 33257 if (h_data_p->lm_dm_int_flag & _ETH_LM_DM_F_DM_IS_SET) { 33258 rv = _bcm_sb2_eth_lm_dm_delay_delete(unit, oc, h_data_p); 33259 _BCM_OAM_UNLOCK(oc); 33260 return rv; 33261 } else { 33262 _BCM_OAM_UNLOCK(oc); 33263 return BCM_E_EMPTY; 33264 } 33265 #endif 33266 } else { 33267 _BCM_OAM_UNLOCK(oc); 33268 return BCM_E_UNAVAIL; 33269 } 33270 33271 _BCM_OAM_UNLOCK(oc); 33272 33273 return (rv); 33274 } 33275 #endif /* (INCLUDE_BHH || INCLUDE_ETH_LM_DM ) || MPLS_LM_DM */ 33276 void _bcm_sb2_lm_dm_data_collection_modes_init(int unit) 33277 { 33278 _bcm_oam_control_t *oc = NULL; /* Pointer to control structure. */ 33279 int rv = BCM_E_NONE; 33280 33281 rv = _bcm_sb2_oam_control_get(unit, &oc); 33282 33283 if (BCM_FAILURE(rv)) { 33284 LOG_ERROR(BSL_LS_BCM_OAM, 33285 (BSL_META_U(unit, 33286 "OAM(unit %d) Error: Oam control get failed " 33287 "- %s.\n"), unit, bcm_errmsg(rv))); 33288 return; 33289 } 33290 #if defined (INCLUDE_ETH_LM_DM) 33291 oc->pm_eth_lmdm_data_collection_mode = soc_property_get(unit, 33292 spn_ETH_LMDM_DATA_COLLECTION_MODE, _BCM_OAM_PM_COLLECTION_MODE_NONE); 33293 #endif 33294 #if defined (INCLUDE_BHH) 33295 oc->pm_bhh_lmdm_data_collection_mode = soc_property_get(unit, 33296 spn_BHH_DATA_COLLECTION_MODE, _BCM_OAM_PM_COLLECTION_MODE_NONE); 33297 #endif 33298 #if defined (INCLUDE_MPLS_LM_DM) 33299 oc->pm_mpls_lmdm_data_collection_mode = soc_property_get(unit, 33300 spn_MPLS_LMDM_DATA_COLLECTION_MODE, _BCM_OAM_PM_COLLECTION_MODE_NONE); 33301 #endif 33302 } 33303 33304 int _bcm_sb2_oam_pm_init(int unit) 33305 { 33306 /* Profile data structure initialization */ 33307 _bcm_oam_pm_profile_control_t *pmc = NULL; 33308 int rv = BCM_E_NONE; 33309 _bcm_oam_control_t *oc = NULL; 33310 33311 rv = _bcm_sb2_oam_control_get(unit, &oc); 33312 33313 if (BCM_FAILURE(rv)) { 33314 LOG_ERROR(BSL_LS_BCM_OAM, 33315 (BSL_META_U(unit, 33316 "OAM(unit %d) Error: Oam control get failed " 33317 "- %s.\n"), unit, bcm_errmsg(rv))); 33318 return BCM_E_INIT; 33319 } 33320 33321 _BCM_OAM_LOCK(oc); 33322 33323 _bcm_sb2_lm_dm_data_collection_modes_init(unit); 33324 /* Allocate profiles only if one of them has processed stats 33325 * collection enabled 33326 */ 33327 if ((_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) || 33328 (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc)) || 33329 (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_PROCESSED(oc))) { 33330 _BCM_OAM_ALLOC(pmc, _bcm_oam_pm_profile_control_t, 33331 sizeof (_bcm_oam_pm_profile_control_t), 33332 "OAM PM profile control"); 33333 if (!pmc) { 33334 _BCM_OAM_UNLOCK(oc); 33335 return BCM_E_MEMORY; 33336 } 33337 33338 pm_profile_control[unit] = pmc; 33339 } 33340 /* 33341 * Allocate DMA buffers and raw data buffers. 33342 * 33343 * 1) DMA buffer will be used to send and receive 'long' messages 33344 * between SDK Host and uController (BTE). 33345 * 33346 * 33347 * 2) Allocate RAW data buffers which is provided 33348 * to Application during PM event callback 33349 */ 33350 #if defined (INCLUDE_BHH) 33351 /* DMA buffer */ 33352 if (_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_ENABLED(oc)) { 33353 oc->pm_bhh_dma_buffer_len = sizeof(shr_oam_pm_msg_ctrl_t); 33354 oc->pm_bhh_dma_buffer = soc_cm_salloc(unit, oc->pm_bhh_dma_buffer_len, 33355 "PM DMA buffer"); 33356 if (!oc->pm_bhh_dma_buffer) { 33357 _BCM_OAM_UNLOCK(oc); 33358 return (BCM_E_MEMORY); 33359 } 33360 sal_memset(oc->pm_bhh_dma_buffer, 0, oc->pm_bhh_dma_buffer_len); 33361 if (_BCM_SB2_OAM_PM_BHH_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) { 33362 /* Raw data buffers */ 33363 oc->pm_bhh_raw_data_num_buffers = soc_property_get(unit, 33364 spn_BHH_PM_RAW_DATA_BUFFERS, 4); 33365 } 33366 /* For first time, when we write this will be incremented to zero index */ 33367 PM_WRITE_DONE_INDEX(_BCM_SB2_OAM_PM_BHH_EVENT_IDX) = -1; 33368 PM_READ_DONE_INDEX(_BCM_SB2_OAM_PM_BHH_EVENT_IDX) = -1; 33369 /* Initially all the buffers are free */ 33370 NUM_FREE_BUFFERS(_BCM_SB2_OAM_PM_BHH_EVENT_IDX) = BCM_OAM_MAX_PM_BUFFERS; 33371 } 33372 #endif 33373 33374 #if defined (INCLUDE_MPLS_LM_DM) 33375 /* DMA buffer */ 33376 if (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) { 33377 oc->pm_mpls_lm_dm_dma_buffer_len = sizeof(shr_oam_pm_msg_ctrl_t); 33378 oc->pm_mpls_lm_dm_dma_buffer = soc_cm_salloc(unit, 33379 oc->pm_mpls_lm_dm_dma_buffer_len, 33380 "PM DMA buffer"); 33381 if (!oc->pm_mpls_lm_dm_dma_buffer) { 33382 _BCM_OAM_UNLOCK(oc); 33383 return (BCM_E_MEMORY); 33384 } 33385 sal_memset(oc->pm_mpls_lm_dm_dma_buffer, 0, 33386 oc->pm_mpls_lm_dm_dma_buffer_len); 33387 if (_BCM_SB2_OAM_PM_MPLS_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) { 33388 /* Raw data buffers */ 33389 oc->pm_mpls_lm_dm_raw_data_num_buffers = soc_property_get(unit, 33390 spn_MPLS_LMDM_PM_RAW_DATA_BUFFERS, 4); 33391 } 33392 /* For first time, when we write this will be incremented to zero index */ 33393 PM_WRITE_DONE_INDEX(_BCM_SB2_OAM_PM_MPLS_LM_DM_EVENT_IDX) = -1; 33394 PM_READ_DONE_INDEX(_BCM_SB2_OAM_PM_MPLS_LM_DM_EVENT_IDX) = -1; 33395 /* Initially all the buffers are free */ 33396 NUM_FREE_BUFFERS(_BCM_SB2_OAM_PM_MPLS_LM_DM_EVENT_IDX) = BCM_OAM_MAX_PM_BUFFERS; 33397 } 33398 #endif 33399 33400 #if defined (INCLUDE_ETH_LM_DM) 33401 /* DMA buffer */ 33402 if (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_ENABLED(oc)) { 33403 oc->pm_eth_lm_dm_dma_buffer_len = sizeof(shr_oam_pm_msg_ctrl_t); 33404 oc->pm_eth_lm_dm_dma_buffer = soc_cm_salloc(unit, 33405 oc->pm_eth_lm_dm_dma_buffer_len, 33406 "PM DMA buffer"); 33407 if (!oc->pm_eth_lm_dm_dma_buffer) { 33408 _BCM_OAM_UNLOCK(oc); 33409 return (BCM_E_MEMORY); 33410 } 33411 sal_memset(oc->pm_eth_lm_dm_dma_buffer, 0, 33412 oc->pm_eth_lm_dm_dma_buffer_len); 33413 if (_BCM_SB2_OAM_PM_ETH_LM_DM_DATA_COLLECTION_MODE_IS_RAW_DATA(oc)) { 33414 /* Raw data buffers */ 33415 oc->pm_eth_lm_dm_raw_data_num_buffers = soc_property_get(unit, 33416 spn_ETH_LMDM_PM_RAW_DATA_BUFFERS, 4); 33417 } 33418 /* For first time, when we write this will be incremented to zero index */ 33419 PM_WRITE_DONE_INDEX(_BCM_SB2_OAM_PM_ETH_LM_DM_EVENT_IDX) = -1; 33420 PM_READ_DONE_INDEX(_BCM_SB2_OAM_PM_ETH_LM_DM_EVENT_IDX) = -1; 33421 /* Initially all the buffers are free */ 33422 NUM_FREE_BUFFERS(_BCM_SB2_OAM_PM_ETH_LM_DM_EVENT_IDX) = BCM_OAM_MAX_PM_BUFFERS; 33423 } 33424 #endif 33425 33426 _BCM_OAM_UNLOCK(oc); 33427 33428 return BCM_E_NONE; 33429 } 33430 33431 uint8* _bcm_oam_pm_dma_buffer_from_endpoint_type_get(int unit, _bcm_oam_hash_data_t *h_data_p) 33432 { 33433 _bcm_oam_control_t *oc = NULL; 33434 int rv = BCM_E_NONE; 33435 33436 rv = _bcm_sb2_oam_control_get(unit, &oc); 33437 if (BCM_FAILURE(rv)) { 33438 return NULL; 33439 } 33440 33441 if (h_data_p->type == bcmOAMEndpointTypeEthernet) { 33442 #if defined (INCLUDE_ETH_LM_DM) 33443 return oc->pm_eth_lm_dm_dma_buffer; 33444 #else 33445 return NULL; 33446 #endif 33447 } else if (BHH_EP_TYPE(h_data_p)) { 33448 #if defined (INCLUDE_BHH) 33449 return oc->pm_bhh_dma_buffer; 33450 #else 33451 return NULL; 33452 #endif 33453 } else if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 33454 #if defined (INCLUDE_MPLS_LM_DM) 33455 return oc->pm_mpls_lm_dm_dma_buffer; 33456 #else 33457 return NULL; 33458 #endif 33459 } 33460 return NULL; 33461 } 33462 33463 int _bcm_oam_pm_dma_buffer_and_len_from_class_get(int unit, 33464 uint8 class, 33465 uint8 **buffer, 33466 int *buffer_len) 33467 { 33468 _bcm_oam_control_t *oc = NULL; 33469 int rv = BCM_E_NONE; 33470 33471 rv = _bcm_sb2_oam_control_get(unit, &oc); 33472 if (BCM_FAILURE(rv)) { 33473 return rv; 33474 } 33475 switch(class) { 33476 case MOS_MSG_CLASS_BHH: 33477 #if defined (INCLUDE_BHH) 33478 *buffer = oc->pm_bhh_dma_buffer; 33479 *buffer_len = oc->pm_bhh_dma_buffer_len; 33480 return BCM_E_NONE; 33481 #else 33482 return BCM_E_PARAM; 33483 #endif 33484 break; 33485 case MOS_MSG_CLASS_MPLS_LM_DM: 33486 #if defined (INCLUDE_MPLS_LM_DM) 33487 *buffer = oc->pm_mpls_lm_dm_dma_buffer; 33488 *buffer_len = oc->pm_mpls_lm_dm_dma_buffer_len; 33489 return BCM_E_NONE; 33490 #else 33491 return BCM_E_PARAM; 33492 #endif 33493 break; 33494 case MOS_MSG_CLASS_ETH_LM_DM: 33495 #if defined (INCLUDE_ETH_LM_DM) 33496 *buffer = oc->pm_eth_lm_dm_dma_buffer; 33497 *buffer_len = oc->pm_eth_lm_dm_dma_buffer_len; 33498 return BCM_E_NONE; 33499 #else 33500 return BCM_E_PARAM; 33501 #endif 33502 break; 33503 default: 33504 return BCM_E_PARAM; 33505 break; 33506 } 33507 return BCM_E_NONE; 33508 } 33509 33510 uint8* _bcm_sb2_oam_pm_dma_buffer_get(int unit, bcm_oam_event_type_t event_type) 33511 { 33512 _bcm_oam_control_t *oc = NULL; 33513 int rv = BCM_E_NONE; 33514 33515 rv = _bcm_sb2_oam_control_get(unit, &oc); 33516 if (BCM_FAILURE(rv)) { 33517 return NULL; 33518 } 33519 switch(event_type) { 33520 case bcmOAMEventBHHRawData: 33521 #if defined (INCLUDE_BHH) 33522 return oc->pm_bhh_dma_buffer; 33523 #else 33524 return NULL; 33525 #endif 33526 break; 33527 case bcmOAMEventEthLmDmRawData: 33528 #if defined (INCLUDE_ETH_LM_DM) 33529 return oc->pm_eth_lm_dm_dma_buffer; 33530 #else 33531 return NULL; 33532 #endif 33533 break; 33534 case bcmOAMEventMplsLmDmRawData: 33535 #if defined (INCLUDE_MPLS_LM_DM) 33536 return oc->pm_mpls_lm_dm_dma_buffer; 33537 #else 33538 return NULL; 33539 #endif 33540 break; 33541 default: 33542 return NULL; 33543 break; 33544 } 33545 return NULL; 33546 } 33547 33548 /* 33549 * Function: 33550 * _bcm_sb2_oam_pm_msg_send_receive 33551 * Purpose: 33552 * Sends given PM control message to the uController. 33553 * Receives and verifies expected reply. 33554 * Performs DMA operation if required. 33555 * Parameters: 33556 * unit - (IN) Unit number. 33557 * s_class - (IN) PM message class. 33558 * s_len - (IN) Value for 'len' field in message struct. 33559 * Length of buffer to flush if DMA send is required. 33560 * s_data - (IN) Value for 'data' field in message struct. 33561 * Ignored if message requires a DMA send/receive 33562 * operation. 33563 * r_subclass - (IN) Expected reply message subclass. 33564 * r_len - (OUT) Returns value in 'len' reply message field. 33565 * Returns: 33566 * BCM_E_XXX 33567 * Notes: 33568 * - The uc_msg 'len' and 'data' fields of mos_msg_data_t 33569 * can take any arbitrary data. 33570 * 33571 * PM Long Control message: 33572 * - PM control messages that require send/receive of information 33573 * that cannot fit in the uc_msg 'len' and 'data' fields need to 33574 * use DMA operations to exchange information (long control message). 33575 * 33576 * - PM convention for long control messages for 33577 * 'mos_msg_data_t' fields: 33578 * 'len' size of the DMA buffer to send to uController 33579 * 'data' physical DMA memory address to send or receive 33580 * 33581 * DMA Operations: 33582 * - DMA read/write operation is performed when a long BHH control 33583 * message is involved. 33584 * 33585 * - Messages that require DMA operation (long control message) 33586 * is indicated by MOS_MSG_DMA_MSG(). 33587 * 33588 * - Callers must 'pack' and 'unpack' corresponding information 33589 * into/from DMA buffer indicated by dma_buffer. 33590 */ 33591 STATIC int 33592 _bcm_sb2_oam_pm_msg_send_receive(int unit, uint8 s_class, uint8 s_subclass, 33593 uint16 s_len, uint32 s_data, 33594 uint8 r_subclass, uint16 *r_len) 33595 { 33596 int rv = BCM_E_NONE; 33597 _bcm_oam_control_t *oc; 33598 mos_msg_data_t send, reply; 33599 uint8 *dma_buffer = NULL; 33600 int dma_buffer_len = 0; 33601 uint32 uc_rv; 33602 int uc_num; 33603 33604 /* Lock already taken by the calling routine. */ 33605 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 33606 33607 sal_memset(&send, 0, sizeof(send)); 33608 sal_memset(&reply, 0, sizeof(reply)); 33609 send.s.mclass = s_class; 33610 send.s.subclass = s_subclass; 33611 send.s.len = bcm_htons(s_len); 33612 33613 /* 33614 * Set 'data' to DMA buffer address if a DMA operation is 33615 * required for send or receive. 33616 */ 33617 33618 BCM_IF_ERROR_RETURN(_bcm_oam_pm_dma_buffer_and_len_from_class_get( 33619 unit, s_class, 33620 &dma_buffer, 33621 &dma_buffer_len)); 33622 33623 if (MOS_MSG_DMA_MSG(s_subclass) || 33624 MOS_MSG_DMA_MSG(r_subclass)) { 33625 send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer)); 33626 } else { 33627 send.s.data = bcm_htonl(s_data); 33628 } 33629 33630 /* Flush DMA memory */ 33631 if (MOS_MSG_DMA_MSG(s_subclass)) { 33632 soc_cm_sflush(unit, dma_buffer, s_len); 33633 } 33634 33635 /* Invalidate DMA memory to read */ 33636 if (MOS_MSG_DMA_MSG(r_subclass)) { 33637 soc_cm_sinval(unit, dma_buffer, dma_buffer_len); 33638 } 33639 33640 switch (s_class) { 33641 #if defined (INCLUDE_BHH) 33642 case MOS_MSG_CLASS_BHH: 33643 uc_num = oc->uc_num; 33644 break; 33645 #endif 33646 #if defined (INCLUDE_ETH_LM_DM) 33647 case MOS_MSG_CLASS_ETH_LM_DM: 33648 uc_num = oc->eth_lm_dm_uc_num; 33649 break; 33650 #endif 33651 #if defined (INCLUDE_MPLS_LM_DM) 33652 case MOS_MSG_CLASS_MPLS_LM_DM: 33653 uc_num = oc->mpls_lm_dm_uc_num; 33654 break; 33655 #endif 33656 default: 33657 return BCM_E_PARAM; 33658 break; 33659 } 33660 33661 /* coverity[unreachable] */ 33662 rv = soc_cmic_uc_msg_send_receive(unit, uc_num, 33663 &send, &reply, 33664 _PM_UC_MSG_TIMEOUT_USECS); 33665 33666 /* Check reply class, subclass */ 33667 if ((rv != SOC_E_NONE) || 33668 (reply.s.mclass != s_class) || /* We can expect the same class that was sent */ 33669 (reply.s.subclass != r_subclass)) { 33670 return (BCM_E_INTERNAL); 33671 } 33672 33673 /* Convert OAM PM uController error code to BCM */ 33674 uc_rv = bcm_ntohl(reply.s.data); 33675 switch(uc_rv) { 33676 case SHR_OAM_PM_UC_E_NONE: 33677 rv = BCM_E_NONE; 33678 break; 33679 case SHR_OAM_PM_UC_E_INTERNAL: 33680 rv = BCM_E_INTERNAL; 33681 break; 33682 case SHR_OAM_PM_UC_E_MEMORY: 33683 rv = BCM_E_MEMORY; 33684 break; 33685 case SHR_OAM_PM_UC_E_PARAM: 33686 rv = BCM_E_PARAM; 33687 break; 33688 case SHR_OAM_PM_UC_E_RESOURCE: 33689 rv = BCM_E_RESOURCE; 33690 break; 33691 case SHR_OAM_PM_UC_E_EXISTS: 33692 rv = BCM_E_EXISTS; 33693 break; 33694 case SHR_OAM_PM_UC_E_NOT_FOUND: 33695 rv = BCM_E_NOT_FOUND; 33696 break; 33697 case SHR_OAM_PM_UC_E_UNAVAIL: 33698 rv = BCM_E_UNAVAIL; 33699 break; 33700 case SHR_OAM_PM_UC_E_VERSION: 33701 rv = BCM_E_CONFIG; 33702 break; 33703 case SHR_OAM_PM_UC_E_INIT: 33704 rv = BCM_E_INIT; 33705 break; 33706 default: 33707 rv = BCM_E_INTERNAL; 33708 break; 33709 } 33710 33711 *r_len = bcm_ntohs(reply.s.len); 33712 33713 return (rv); 33714 } 33715 33716 int _bcm_sb2_pm_profile_compare(bcm_oam_pm_profile_info_t *profile_info1, 33717 bcm_oam_pm_profile_info_t *profile_info2) 33718 { 33719 if (!(sal_memcmp(profile_info1->bin_edges, profile_info2->bin_edges, 33720 BCM_OAM_MAX_PM_PROFILE_BIN_EDGES * sizeof(uint32)))) { 33721 /* Match */ 33722 return 1; 33723 } 33724 return 0; 33725 } 33726 33727 int _bcm_sb2_pm_profile_exists(int unit, bcm_oam_pm_profile_info_t *profile_info) 33728 { 33729 int id = 0; 33730 _bcm_oam_pm_profile_control_t *pmc = NULL; 33731 33732 pmc = pm_profile_control[unit]; 33733 33734 if (!pmc) { 33735 return 0; 33736 } 33737 33738 for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) { 33739 if (_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, id)) { /* If a profile is in use */ 33740 if (_bcm_sb2_pm_profile_compare( 33741 _BCM_SB2_PM_CTRL_PROFILE_PTR(pmc, id), 33742 profile_info)) { 33743 return 1; 33744 } 33745 } 33746 } 33747 return 0; 33748 } 33749 33750 int 33751 _bcm_sb2_find_free_pm_profile_id(int unit, int *pm_profile_id) 33752 { 33753 int id = 0; 33754 _bcm_oam_pm_profile_control_t *pmc = NULL; 33755 33756 pmc = pm_profile_control[unit]; 33757 33758 if (!pmc) { 33759 return BCM_E_INIT; 33760 } 33761 33762 /* return the lowest un used id */ 33763 for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) { 33764 if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, id))) { /* If a profile is not in use */ 33765 *pm_profile_id = id; /* Assign it and return */ 33766 return BCM_E_NONE; 33767 } 33768 } 33769 return BCM_E_RESOURCE; 33770 } 33771 33772 int 33773 _bcm_sb2_oam_pm_profile_delete(int unit, bcm_oam_pm_profile_t profile_id, int all) 33774 { 33775 _bcm_oam_pm_profile_control_t *pmc; 33776 33777 pmc = pm_profile_control[unit]; 33778 33779 if (!pmc) { 33780 return BCM_E_INIT; 33781 } 33782 33783 /* Check it only if it is a delete for a particular profile */ 33784 if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id)) && !all) { 33785 /* It is not in use. Return error */ 33786 return BCM_E_NOT_FOUND; 33787 } 33788 /* Zero out that profile */ 33789 sal_memset(_BCM_SB2_PM_CTRL_PROFILE_PTR(pmc, profile_id), 0, 33790 sizeof(bcm_oam_pm_profile_info_t)); 33791 /* Mark it un used */ 33792 _BCM_SB2_SET_PM_CTRL_PROFILE_NOT_IN_USE(pmc, profile_id); 33793 33794 return BCM_E_NONE; 33795 } 33796 33797 int 33798 bcm_sb2_oam_pm_profile_delete(int unit, bcm_oam_pm_profile_t profile_id) 33799 { 33800 if (!(_BCM_SB2_PM_PROFILE_ID_VALID(profile_id))) { 33801 return BCM_E_PARAM; 33802 } 33803 return _bcm_sb2_oam_pm_profile_delete(unit, profile_id, 0); 33804 } 33805 33806 int 33807 bcm_sb2_oam_pm_profile_delete_all(int unit) 33808 { 33809 int id; 33810 for (id = 0; id < _BCM_OAM_MAX_PM_PROFILES; id++) { 33811 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_pm_profile_delete(unit, id, 1)); 33812 } 33813 return BCM_E_NONE; 33814 } 33815 33816 int 33817 bcm_sb2_oam_pm_profile_create(int unit, bcm_oam_pm_profile_info_t *profile_info) 33818 { 33819 _bcm_oam_pm_profile_control_t *pmc = NULL; 33820 bcm_oam_pm_profile_info_t *profile_ptr = NULL; 33821 int pm_profile_id = 0; 33822 33823 pmc = pm_profile_control[unit]; 33824 33825 if (!pmc) { 33826 return BCM_E_INIT; 33827 } 33828 33829 if (_BCM_SB2_PM_PROFILE_WITH_ID_FLAG_SET(profile_info)) { 33830 if (!(_BCM_SB2_PM_PROFILE_ID_VALID(profile_info->id))) { 33831 return BCM_E_PARAM; 33832 } 33833 } 33834 33835 if (_BCM_SB2_PM_PROFILE_REPLACE_FLAG_SET(profile_info)) { 33836 if (!(_BCM_SB2_PM_PROFILE_WITH_ID_FLAG_SET(profile_info))) { 33837 /* replace needs the id to be present */ 33838 return BCM_E_PARAM; 33839 } 33840 33841 if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, profile_info->id))) { 33842 /* Trying to replace a non-existent PM profile */ 33843 return BCM_E_NOT_FOUND; 33844 } 33845 33846 /* Delete the previous profile. */ 33847 BCM_IF_ERROR_RETURN(bcm_sb2_oam_pm_profile_delete(unit, 33848 profile_info->id)); 33849 } 33850 33851 if (_BCM_SB2_PM_PROFILE_WITH_ID_FLAG_SET(profile_info)) { 33852 if (_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, profile_info->id)) { 33853 /* That profile id is in use. */ 33854 return BCM_E_EXISTS; 33855 } 33856 /* Else use that as the id */ 33857 pm_profile_id = profile_info->id; 33858 } else { 33859 BCM_IF_ERROR_RETURN(_bcm_sb2_find_free_pm_profile_id(unit, 33860 &pm_profile_id)); 33861 } 33862 33863 /* Check if such a profile already exists. */ 33864 if (_bcm_sb2_pm_profile_exists(unit, profile_info)) { 33865 33866 return BCM_E_EXISTS; 33867 } 33868 33869 /* Copy it to local profile information */ 33870 profile_ptr = _BCM_SB2_PM_CTRL_PROFILE_PTR(pmc, pm_profile_id); 33871 sal_memcpy(profile_ptr, profile_info, 33872 sizeof(bcm_oam_pm_profile_info_t)); 33873 33874 /* Update the id in the profile */ 33875 profile_ptr->id = profile_info->id = pm_profile_id; 33876 33877 /* Current flags have only transient meaning, so clear them */ 33878 profile_ptr->flags = 0; 33879 33880 /* Mark that profile used */ 33881 _BCM_SB2_SET_PM_CTRL_PROFILE_IN_USE(pmc, pm_profile_id); 33882 33883 return BCM_E_NONE; 33884 } 33885 33886 int 33887 bcm_sb2_oam_pm_profile_get(int unit, bcm_oam_pm_profile_info_t *profile_info) 33888 { 33889 _bcm_oam_pm_profile_control_t *pmc; 33890 int profile_id = profile_info->id; 33891 33892 pmc = pm_profile_control[unit]; 33893 33894 if (!pmc) { 33895 return BCM_E_INIT; 33896 } 33897 33898 if (!(_BCM_SB2_PM_PROFILE_ID_VALID(profile_id))) { 33899 return BCM_E_PARAM; 33900 } 33901 33902 if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) { 33903 /* It is not in use. Return error */ 33904 return BCM_E_NOT_FOUND; 33905 } 33906 33907 /* Copy the profile to the profile structure passed */ 33908 sal_memcpy(profile_info, _BCM_SB2_PM_CTRL_PROFILE_PTR(pmc, profile_id), 33909 sizeof(bcm_oam_pm_profile_info_t)); 33910 33911 return BCM_E_NONE; 33912 } 33913 33914 int bcm_sb2_oam_pm_profile_attach(int unit, bcm_oam_endpoint_t endpoint_id, 33915 bcm_oam_pm_profile_t profile_id) 33916 { 33917 _bcm_oam_pm_profile_control_t *pmc = NULL; 33918 bcm_oam_pm_profile_info_t *profile_info = NULL; 33919 _bcm_oam_control_t *oc = NULL; 33920 _bcm_oam_hash_data_t *h_data_p = NULL; 33921 int rv = BCM_E_NONE; 33922 shr_oam_pm_msg_ctrl_profile_attach_t msg_profile_attach; 33923 uint8 msg_class = 0; 33924 uint16 reply_len = 0; 33925 uint8 msg_subclass = 0; 33926 uint8 msg_reply_subclass = 0; 33927 uint8 *buffer, *buffer_ptr; 33928 uint16 buffer_len; 33929 33930 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 33931 _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id); 33932 _BCM_OAM_LOCK(oc); 33933 33934 h_data_p = &oc->oam_hash_data[endpoint_id]; 33935 33936 if (0 == h_data_p->in_use) { 33937 LOG_ERROR(BSL_LS_BCM_OAM, 33938 (BSL_META_U(unit, 33939 "OAM(unit %d) Error: h_data_p not in use EP=%d\n"), 33940 unit, endpoint_id)); 33941 _BCM_OAM_UNLOCK(oc); 33942 return (BCM_E_NOT_FOUND); 33943 } 33944 pmc = pm_profile_control[unit]; 33945 33946 if (!pmc) { 33947 _BCM_OAM_UNLOCK(oc); 33948 return BCM_E_INIT; 33949 } 33950 33951 if (!(_BCM_SB2_PM_PROFILE_ID_VALID(profile_id))) { 33952 _BCM_OAM_UNLOCK(oc); 33953 return BCM_E_PARAM; 33954 } 33955 33956 /* Check profile id exists or not */ 33957 if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) { 33958 /* It is not in use. Return error */ 33959 _BCM_OAM_UNLOCK(oc); 33960 return BCM_E_NOT_FOUND; 33961 } 33962 /* Check if a profile id is already attached to this endpoint */ 33963 if (h_data_p->pm_profile_attached != _BCM_OAM_INVALID_INDEX) { 33964 _BCM_OAM_UNLOCK(oc); 33965 return BCM_E_EXISTS; 33966 } 33967 33968 /* Check if delay measurement flag is present for the endpoint */ 33969 if (!(h_data_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT)) { 33970 _BCM_OAM_UNLOCK(oc); 33971 return BCM_E_PARAM; 33972 } 33973 33974 profile_info = _BCM_SB2_PM_CTRL_PROFILE_PTR(pmc, profile_id); 33975 33976 /* Send info to u-Kernel about the profile attached with the endpoint */ 33977 sal_memset(&msg_profile_attach, 0, sizeof(msg_profile_attach)); 33978 33979 if (h_data_p->type == bcmOAMEndpointTypeEthernet) { 33980 msg_class = MOS_MSG_CLASS_ETH_LM_DM; 33981 msg_subclass = MOS_MSG_SUBCLASS_ETH_LM_DM_PM_PROFILE_ATTACH; 33982 msg_reply_subclass = MOS_MSG_SUBCLASS_ETH_LM_DM_PM_PROFILE_ATTACH_REPLY; 33983 #if defined (INCLUDE_ETH_LM_DM) 33984 msg_profile_attach.sess_id = h_data_p->lm_dm_uc_session_id; 33985 #endif 33986 } else if (BHH_EP_TYPE(h_data_p)) { 33987 msg_class = MOS_MSG_CLASS_BHH; 33988 msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_ATTACH; 33989 msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_ATTACH_REPLY; 33990 #if defined (INCLUDE_BHH) 33991 msg_profile_attach.sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id); 33992 #endif 33993 } else if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 33994 msg_class = MOS_MSG_CLASS_MPLS_LM_DM; 33995 msg_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_ATTACH; 33996 msg_reply_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_ATTACH_REPLY; 33997 #if defined (INCLUDE_MPLS_LM_DM) 33998 msg_profile_attach.sess_id = h_data_p->lm_dm_uc_session_id; 33999 #endif 34000 } 34001 34002 msg_profile_attach.profile_id = profile_id; 34003 msg_profile_attach.profile_flags = profile_info->flags; 34004 sal_memcpy(&(msg_profile_attach.profile_edges), &(profile_info->bin_edges), 34005 (sizeof(uint32) * SHR_OAM_PM_MAX_PM_BIN_EDGES)); 34006 34007 /* Pack control message data into DMA buffer */ 34008 buffer = _bcm_oam_pm_dma_buffer_from_endpoint_type_get(unit, h_data_p); 34009 buffer_ptr = shr_oam_pm_msg_ctrl_profile_attach_pack(buffer, &msg_profile_attach); 34010 buffer_len = buffer_ptr - buffer; 34011 34012 34013 rv = _bcm_sb2_oam_pm_msg_send_receive 34014 (unit, msg_class, 34015 msg_subclass, 34016 buffer_len, 0, 34017 msg_reply_subclass, 34018 &reply_len); 34019 34020 if(BCM_FAILURE(rv)) { 34021 _BCM_OAM_UNLOCK(oc); 34022 return BCM_E_INTERNAL; 34023 } 34024 34025 /* Attach it to the endpoint */ 34026 h_data_p->pm_profile_attached = profile_id; 34027 34028 _BCM_OAM_UNLOCK(oc); 34029 return BCM_E_NONE; 34030 } 34031 34032 int bcm_sb2_oam_pm_profile_detach(int unit, bcm_oam_endpoint_t endpoint_id, 34033 bcm_oam_pm_profile_t profile_id) 34034 { 34035 _bcm_oam_pm_profile_control_t *pmc = NULL; 34036 _bcm_oam_control_t *oc = NULL; 34037 _bcm_oam_hash_data_t *h_data_p = NULL; 34038 int rv = BCM_E_NONE; 34039 uint8 msg_class = 0; 34040 uint16 reply_len = 0; 34041 uint8 msg_subclass = 0; 34042 uint8 msg_reply_subclass = 0; 34043 uint16 sess_id = 0; 34044 34045 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 34046 _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id); 34047 _BCM_OAM_LOCK(oc); 34048 34049 h_data_p = &oc->oam_hash_data[endpoint_id]; 34050 34051 if (0 == h_data_p->in_use) { 34052 LOG_ERROR(BSL_LS_BCM_OAM, 34053 (BSL_META_U(unit, 34054 "OAM(unit %d) Error: h_data_p not in use EP=%d\n"), 34055 unit, endpoint_id)); 34056 _BCM_OAM_UNLOCK(oc); 34057 return (BCM_E_NOT_FOUND); 34058 } 34059 pmc = pm_profile_control[unit]; 34060 34061 if (!pmc) { 34062 _BCM_OAM_UNLOCK(oc); 34063 return BCM_E_INIT; 34064 } 34065 34066 if (!(_BCM_SB2_PM_PROFILE_ID_VALID(profile_id))) { 34067 _BCM_OAM_UNLOCK(oc); 34068 return BCM_E_PARAM; 34069 } 34070 34071 /* Check profile id exists or not */ 34072 if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) { 34073 /* It is not in use. Return error */ 34074 _BCM_OAM_UNLOCK(oc); 34075 return BCM_E_NOT_FOUND; 34076 } 34077 34078 /* Check if the passed profile id is the one that is attached */ 34079 if (profile_id != h_data_p->pm_profile_attached) { 34080 _BCM_OAM_UNLOCK(oc); 34081 return BCM_E_PARAM; 34082 } 34083 34084 if (h_data_p->type == bcmOAMEndpointTypeEthernet) { 34085 msg_class = MOS_MSG_CLASS_ETH_LM_DM; 34086 msg_subclass = MOS_MSG_SUBCLASS_ETH_LM_DM_PM_PROFILE_DETACH; 34087 msg_reply_subclass = MOS_MSG_SUBCLASS_ETH_LM_DM_PM_PROFILE_DETACH_REPLY; 34088 #if defined (INCLUDE_ETH_LM_DM) 34089 sess_id = h_data_p->lm_dm_uc_session_id; 34090 #endif 34091 } else if (BHH_EP_TYPE(h_data_p)) { 34092 msg_class = MOS_MSG_CLASS_BHH; 34093 msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_DETACH; 34094 msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_PROFILE_DETACH_REPLY; 34095 #if defined (INCLUDE_BHH) 34096 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id); 34097 #endif 34098 } else if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 34099 msg_class = MOS_MSG_CLASS_MPLS_LM_DM; 34100 msg_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_DETACH; 34101 msg_reply_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_PROFILE_DETACH_REPLY; 34102 #if defined (INCLUDE_MPLS_LM_DM) 34103 sess_id = h_data_p->lm_dm_uc_session_id; 34104 #endif 34105 } 34106 rv = _bcm_sb2_oam_pm_msg_send_receive 34107 (unit, msg_class, 34108 msg_subclass, 34109 sess_id, profile_id, 34110 msg_reply_subclass, 34111 &reply_len); 34112 34113 if(BCM_FAILURE(rv)) { 34114 _BCM_OAM_UNLOCK(oc); 34115 return BCM_E_INTERNAL; 34116 } 34117 /* Detach the profile from endpoint */ 34118 h_data_p->pm_profile_attached = _BCM_OAM_INVALID_INDEX; 34119 34120 _BCM_OAM_UNLOCK(oc); 34121 return BCM_E_NONE; 34122 } 34123 34124 34125 int bcm_sb2_oam_pm_profile_traverse(int unit, 34126 bcm_oam_pm_profile_traverse_cb cb, void *user_data) 34127 { 34128 int rv = BCM_E_NONE; /* Operation return status. */ 34129 bcm_oam_pm_profile_info_t *profile_info = NULL; 34130 _bcm_oam_pm_profile_control_t *pmc = NULL; 34131 int profile_id; 34132 34133 /* Validate input parameter. */ 34134 if (NULL == cb) { 34135 return (BCM_E_PARAM); 34136 } 34137 pmc = pm_profile_control[unit]; 34138 34139 if (!pmc) { 34140 return BCM_E_INIT; 34141 } 34142 34143 for (profile_id = 0; profile_id < _BCM_OAM_MAX_PM_PROFILES; profile_id++) { 34144 /* Check profile id is in use or not */ 34145 if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, profile_id))) { 34146 /* Skip that profile id */ 34147 continue; 34148 } 34149 profile_info = _BCM_SB2_PM_CTRL_PROFILE_PTR(pmc, profile_id); 34150 rv = cb(unit, profile_info, user_data); 34151 if (BCM_FAILURE(rv)) { 34152 LOG_ERROR(BSL_LS_BCM_OAM, 34153 (BSL_META_U(unit, 34154 "OAM(unit %d) Error: EP=%d callback failed - %s.\n"), 34155 unit, profile_id, bcm_errmsg(rv))); 34156 return (rv); 34157 } 34158 } 34159 34160 return (rv); 34161 } 34162 34163 void _bcm_sb2_oam_copy_stats_msg_to_stats_ptr(shr_oam_pm_msg_ctrl_pm_stats_get_t *stats_msg, 34164 bcm_oam_pm_stats_t *stats_ptr, 34165 uint8 pm_stat_extra_elem_feature) 34166 { 34167 stats_ptr->far_loss_min = stats_msg->far_loss_min; 34168 stats_ptr->far_tx_min = stats_msg->far_tx_min; 34169 stats_ptr->far_loss_max = stats_msg->far_loss_max; 34170 stats_ptr->far_tx_max = stats_msg->far_tx_max; 34171 stats_ptr->far_loss = stats_msg->far_loss; 34172 stats_ptr->near_loss_min = stats_msg->near_loss_min; 34173 stats_ptr->near_tx_min = stats_msg->near_tx_min; 34174 stats_ptr->near_loss_max = stats_msg->near_loss_max; 34175 stats_ptr->near_tx_max = stats_msg->near_tx_max; 34176 stats_ptr->near_loss = stats_msg->near_loss; 34177 stats_ptr->lm_tx_count = stats_msg->lm_tx_count; 34178 stats_ptr->DM_min = stats_msg->DM_min; 34179 stats_ptr->DM_max = stats_msg->DM_max; 34180 if(stats_msg->dm_rx_count) { 34181 stats_ptr->DM_avg = stats_msg->DM_avg/stats_msg->dm_rx_count; 34182 } 34183 stats_ptr->dm_tx_count = stats_msg->dm_tx_count; 34184 stats_ptr->profile_id = stats_msg->profile_id; 34185 sal_memcpy(&(stats_ptr->bin_counters), &(stats_msg->bin_counters), sizeof(uint32) * (SHR_OAM_PM_MAX_PM_BIN_EDGES + 1)); 34186 if(pm_stat_extra_elem_feature) { 34187 stats_ptr->lm_rx_count = stats_msg->lm_rx_count; 34188 stats_ptr->dm_rx_count = stats_msg->dm_rx_count; 34189 stats_ptr->far_total_tx_pkt_count = stats_msg->far_total_tx_pkt_count; 34190 stats_ptr->near_total_tx_pkt_count = stats_msg->near_total_tx_pkt_count; 34191 } 34192 34193 if (stats_msg->flags & SHR_OAM_PM_STATS_FLAG_COUNTER_ROLLOVER) { 34194 stats_ptr->flags |= BCM_OAM_PM_STATS_PROCESSED_COUNTER_ROLLOVER; 34195 } 34196 } 34197 34198 int bcm_sb2_oam_pm_stats_get(int unit, 34199 bcm_oam_endpoint_t endpoint_id, bcm_oam_pm_stats_t *stats_ptr) 34200 { 34201 _bcm_oam_pm_profile_control_t *pmc = NULL; 34202 _bcm_oam_control_t *oc = NULL; 34203 _bcm_oam_hash_data_t *h_data_p = NULL; 34204 shr_oam_pm_msg_ctrl_pm_stats_get_t stats_msg; 34205 int rv = BCM_E_NONE; 34206 uint16 sess_id = 0; 34207 uint8 msg_class = 0; 34208 uint16 reply_len = 0; 34209 uint8 msg_subclass = 0; 34210 uint8 msg_reply_subclass = 0; 34211 uint8 *dma_buffer = NULL; 34212 uint8 pm_stat_extra_elem_feature = 0; 34213 34214 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 34215 _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id); 34216 _BCM_OAM_LOCK(oc); 34217 34218 /* Check endpoint status. */ 34219 rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint_id); 34220 if ((BCM_E_EXISTS != rv)) { 34221 /* Endpoint not in use. */ 34222 LOG_ERROR(BSL_LS_BCM_OAM, 34223 (BSL_META_U(unit, 34224 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 34225 unit, endpoint_id, bcm_errmsg(rv))); 34226 _BCM_OAM_UNLOCK(oc); 34227 return (rv); 34228 } 34229 34230 h_data_p = &oc->oam_hash_data[endpoint_id]; 34231 34232 if (0 == h_data_p->in_use) { 34233 LOG_ERROR(BSL_LS_BCM_OAM, 34234 (BSL_META_U(unit, 34235 "OAM(unit %d) Error: h_data_p not in use EP=%d\n"), 34236 unit, endpoint_id)); 34237 _BCM_OAM_UNLOCK(oc); 34238 return (BCM_E_INTERNAL); 34239 } 34240 pmc = pm_profile_control[unit]; 34241 34242 if (!pmc) { 34243 _BCM_OAM_UNLOCK(oc); 34244 return BCM_E_INIT; 34245 } 34246 34247 34248 34249 if (h_data_p->type == bcmOAMEndpointTypeEthernet) { 34250 msg_class = MOS_MSG_CLASS_ETH_LM_DM; 34251 msg_subclass = MOS_MSG_SUBCLASS_ETH_LM_DM_PM_STATS_GET; 34252 msg_reply_subclass = MOS_MSG_SUBCLASS_ETH_LM_DM_PM_STATS_GET_REPLY; 34253 #if defined (INCLUDE_ETH_LM_DM) 34254 sess_id = h_data_p->lm_dm_uc_session_id; 34255 34256 if (sess_id == 0) { 34257 /* It is not in use. Return error */ 34258 _BCM_OAM_UNLOCK(oc); 34259 return BCM_E_NOT_FOUND; 34260 } 34261 34262 pm_stat_extra_elem_feature = ETH_LM_DM_UC_FEATURE_CHECK(ETH_LM_DM_PM_STAT_EXTRA_ELEM); 34263 #endif 34264 } else if (BHH_EP_TYPE(h_data_p)) { 34265 msg_class = MOS_MSG_CLASS_BHH; 34266 msg_subclass = MOS_MSG_SUBCLASS_BHH_PM_STATS_GET; 34267 msg_reply_subclass = MOS_MSG_SUBCLASS_BHH_PM_STATS_GET_REPLY; 34268 #if defined (INCLUDE_BHH) 34269 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(endpoint_id); 34270 pm_stat_extra_elem_feature = BHH_UC_FEATURE_CHECK(BHH_PM_STAT_EXTRA_ELEM); 34271 #endif 34272 } else if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 34273 msg_class = MOS_MSG_CLASS_MPLS_LM_DM; 34274 msg_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_STATS_GET; 34275 msg_reply_subclass = MOS_MSG_SUBCLASS_MPLS_LM_DM_PM_STATS_GET_REPLY; 34276 #if defined (INCLUDE_MPLS_LM_DM) 34277 sess_id = h_data_p->lm_dm_uc_session_id; 34278 34279 if (sess_id == 0) { 34280 /* It is not in use. Return error */ 34281 _BCM_OAM_UNLOCK(oc); 34282 return BCM_E_NOT_FOUND; 34283 } 34284 34285 pm_stat_extra_elem_feature = MPLS_LM_DM_UC_FEATURE_CHECK(MPLS_LM_DM_PM_STAT_EXTRA_ELEM); 34286 #endif 34287 } 34288 dma_buffer = _bcm_oam_pm_dma_buffer_from_endpoint_type_get(unit, h_data_p); 34289 rv = _bcm_sb2_oam_pm_msg_send_receive 34290 (unit, msg_class, 34291 msg_subclass, 34292 /* Pass the buffer pointer in data and sess id in length fields.*/ 34293 sess_id, soc_cm_l2p(unit, dma_buffer), 34294 msg_reply_subclass, 34295 &reply_len); 34296 34297 if(BCM_FAILURE(rv) || reply_len == 0) { 34298 _BCM_OAM_UNLOCK(oc); 34299 return BCM_E_INTERNAL; 34300 } 34301 34302 shr_oam_pm_msg_ctrl_pm_stats_get_unpack(dma_buffer, &stats_msg, pm_stat_extra_elem_feature); 34303 34304 _bcm_sb2_oam_copy_stats_msg_to_stats_ptr(&stats_msg, stats_ptr, pm_stat_extra_elem_feature); 34305 34306 _BCM_OAM_UNLOCK(oc); 34307 return BCM_E_NONE; 34308 } 34309 34310 34311 int 34312 bcm_sb2_oam_pm_profile_attach_get( 34313 int unit, 34314 bcm_oam_endpoint_t endpoint_id, 34315 bcm_oam_pm_profile_t *profile_id) 34316 { 34317 _bcm_oam_pm_profile_control_t *pmc = NULL; 34318 _bcm_oam_control_t *oc = NULL; 34319 _bcm_oam_hash_data_t *h_data_p = NULL; 34320 int rv = BCM_E_NONE; 34321 34322 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 34323 _BCM_OAM_EP_INDEX_VALIDATE(endpoint_id); 34324 _BCM_OAM_LOCK(oc); 34325 34326 /* Check endpoint status. */ 34327 rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint_id); 34328 if ((BCM_E_EXISTS != rv)) { 34329 /* Endpoint not in use. */ 34330 LOG_ERROR(BSL_LS_BCM_OAM, 34331 (BSL_META_U(unit, 34332 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 34333 unit, endpoint_id, bcm_errmsg(rv))); 34334 _BCM_OAM_UNLOCK(oc); 34335 return (rv); 34336 } 34337 34338 h_data_p = &oc->oam_hash_data[endpoint_id]; 34339 34340 if (0 == h_data_p->in_use) { 34341 LOG_ERROR(BSL_LS_BCM_OAM, 34342 (BSL_META_U(unit, 34343 "OAM(unit %d) Error: h_data_p not in use EP=%d\n"), 34344 unit, endpoint_id)); 34345 _BCM_OAM_UNLOCK(oc); 34346 return (BCM_E_INTERNAL); 34347 } 34348 pmc = pm_profile_control[unit]; 34349 34350 if (!pmc) { 34351 _BCM_OAM_UNLOCK(oc); 34352 return BCM_E_INIT; 34353 } 34354 34355 /* Get the attached profile */ 34356 *profile_id = h_data_p->pm_profile_attached; 34357 34358 if (*profile_id == _BCM_OAM_INVALID_INDEX) { 34359 _BCM_OAM_UNLOCK(oc); 34360 return BCM_E_NOT_FOUND; 34361 } 34362 /* Check profile id is in use or not */ 34363 if (!(_BCM_SB2_PM_CTRL_PROFILE_IN_USE(pmc, *profile_id))) { 34364 /* It is not in use. Return error */ 34365 /* Ideally this should not happen */ 34366 _BCM_OAM_UNLOCK(oc); 34367 return BCM_E_INTERNAL; 34368 } 34369 34370 _BCM_OAM_UNLOCK(oc); 34371 return BCM_E_NONE; 34372 } 34373 34374 void 34375 _bcm_sb2_write_dma_buffer_to_raw_buffer(int unit, uint8 *dma_buffer, 34376 bcm_oam_pm_raw_data_t *raw_data, int write_index) 34377 { 34378 shr_oam_pm_msg_ctrl_raw_buffer_unpack(dma_buffer, 34379 (shr_oam_pm_msg_ctrl_raw_buffer_t *)(&(raw_data->raw_buffer[write_index]))); 34380 } 34381 34382 int _bcm_sb2_oam_pm_raw_data_event_index_from_event_get(bcm_oam_event_type_t event_type) 34383 { 34384 switch (event_type) { 34385 case bcmOAMEventBHHRawData: 34386 return _BCM_SB2_OAM_PM_BHH_EVENT_IDX; 34387 break; 34388 case bcmOAMEventEthLmDmRawData: 34389 return _BCM_SB2_OAM_PM_ETH_LM_DM_EVENT_IDX; 34390 break; 34391 case bcmOAMEventMplsLmDmRawData: 34392 return _BCM_SB2_OAM_PM_MPLS_LM_DM_EVENT_IDX; 34393 break; 34394 default: 34395 return -1; 34396 break; 34397 } 34398 return -1; 34399 } 34400 34401 void _bcm_sb2_update_num_free_buffers(_bcm_oam_control_t *oc, 34402 int event_idx, int read_idx, 34403 int write_idx, int last_op) 34404 { 34405 /* Normal case */ 34406 if (read_idx < write_idx) { 34407 SET_NUM_FREE_BUFFERS(event_idx, 34408 (BCM_OAM_MAX_PM_BUFFERS - (write_idx - read_idx))); 34409 } else if (read_idx > write_idx) { 34410 /* rollover case */ 34411 SET_NUM_FREE_BUFFERS(event_idx, 34412 (read_idx - write_idx)); 34413 } else { /* read index = write index case */ 34414 if (last_op == 1) { 34415 /* Last operation was write, means write idx has caught 34416 up with read_idx. 34417 Just decrement the number of buffers by 1. 34418 Ideally this would mean the num of free buffers would 34419 become zero */ 34420 DECR_NUM_FREE_BUFFERS(event_idx); 34421 } else if (last_op == 0) { 34422 /* Last operation was read, means read idx has caught 34423 up with write idx. 34424 Just increment the number of buffers by 1. 34425 Ideally this would mean the num of free buffers would 34426 have become max. */ 34427 INCR_NUM_FREE_BUFFERS(event_idx); 34428 } 34429 } 34430 } 34431 /* Returns 0 - Not updated or 1 - Updated */ 34432 int 34433 _bcm_sb2_update_dma_buffer_into_raw_buffer(int unit, bcm_oam_event_type_t event_type, 34434 uint8 *dma_buffer,bcm_oam_pm_raw_data_t *raw_data) 34435 { 34436 int rv = BCM_E_NONE; 34437 int event_idx = -1; 34438 _bcm_oam_control_t *oc; 34439 int read_idx = -1; 34440 int write_idx = -1; 34441 34442 /* Get OAM Control Structure. */ 34443 rv = _bcm_sb2_oam_control_get(unit, &oc); 34444 if (BCM_FAILURE(rv)) { 34445 return FALSE; 34446 } 34447 34448 event_idx = _bcm_sb2_oam_pm_raw_data_event_index_from_event_get(event_type); 34449 if (event_idx == -1) { 34450 return FALSE; 34451 } 34452 34453 if (NUM_FREE_BUFFERS(event_idx) > 0) { 34454 PM_WRITE_DONE_INDEX(event_idx) = INCREMENT_PM_WRITE_DONE_INDEX(event_idx); 34455 /* Writing at the incremented index */ 34456 _bcm_sb2_write_dma_buffer_to_raw_buffer(unit, dma_buffer, raw_data, 34457 PM_WRITE_DONE_INDEX(event_idx)); 34458 } else { 34459 /* There are no free buffers. Do not update */ 34460 return FALSE; 34461 } 34462 read_idx = PM_READ_DONE_INDEX(event_idx); 34463 write_idx = PM_WRITE_DONE_INDEX(event_idx); 34464 34465 /* 1 passed indicates last operation was write */ 34466 _bcm_sb2_update_num_free_buffers(oc, event_idx, read_idx, write_idx, 1); 34467 34468 raw_data->read_index = PM_READ_DONE_INDEX(event_idx); 34469 raw_data->write_index = PM_WRITE_DONE_INDEX(event_idx); 34470 34471 return TRUE; 34472 } 34473 34474 int 34475 bcm_sb2_oam_pm_raw_data_read_done(int unit, 34476 bcm_oam_event_types_t event_types, 34477 uint32 read_index) 34478 { 34479 bcm_oam_event_type_t event_type; 34480 _bcm_oam_control_t *oc; 34481 int event_idx = -1; 34482 34483 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 34484 /* Do sanity validation of event_types and read_index */ 34485 if (!(_BCM_SB2_EVENT_TYPE_PM_EVENT(event_types))) { 34486 return BCM_E_PARAM; 34487 } 34488 34489 if (!(VALID_PM_RAW_DATA_BUFFER_READ_WRITE_INDEX(read_index))) { 34490 return BCM_E_PARAM; 34491 } 34492 34493 for (event_type = bcmOAMEventBHHRawData; event_type <= bcmOAMEventMplsLmDmRawData; event_type++) { 34494 if (BCM_OAM_EVENT_TYPE_GET(event_types, event_type)) { 34495 event_idx = _bcm_sb2_oam_pm_raw_data_event_index_from_event_get(event_type); 34496 if (event_idx == -1) { 34497 return BCM_E_PARAM; 34498 } 34499 PM_READ_DONE_INDEX(event_idx) = read_index; 34500 /* 0 passed indicates last operation was read */ 34501 _bcm_sb2_update_num_free_buffers(oc, event_idx, read_index, 34502 PM_WRITE_DONE_INDEX(event_idx), 0); 34503 } 34504 } 34505 return BCM_E_NONE; 34506 } 34507 34508 bcm_oam_pm_raw_data_t *_bcm_sb2_oam_pm_raw_data_info_get(int unit, 34509 bcm_oam_event_type_t event_type) 34510 { 34511 int rv = BCM_E_NONE; 34512 _bcm_oam_control_t *oc; 34513 34514 rv = _bcm_sb2_oam_control_get(unit, &oc); 34515 if (BCM_FAILURE(rv)) { 34516 return NULL; 34517 } 34518 switch (event_type) { 34519 case bcmOAMEventBHHRawData: 34520 #if defined (INCLUDE_BHH) 34521 return &(oc->pm_bhh_raw_data_info); 34522 #else 34523 return NULL; 34524 #endif 34525 break; 34526 case bcmOAMEventEthLmDmRawData: 34527 #if defined (INCLUDE_ETH_LM_DM) 34528 return &(oc->pm_eth_lm_dm_raw_data_info); 34529 #else 34530 return NULL; 34531 #endif 34532 break; 34533 case bcmOAMEventMplsLmDmRawData: 34534 #if defined (INCLUDE_MPLS_LM_DM) 34535 return &(oc->pm_mpls_lm_dm_raw_data_info); 34536 #else 34537 return NULL; 34538 #endif 34539 break; 34540 default: 34541 return NULL; 34542 break; 34543 } 34544 return NULL; 34545 } 34546 34547 #if defined (INCLUDE_BHH) || defined (INCLUDE_ETH_LM_DM) || defined (INCLUDE_MPLS_LM_DM) 34548 STATIC void _bcm_sb2_oam_pm_event_msg_handle(_bcm_oam_control_t *oc, 34549 mos_msg_data_t *event_msg) 34550 { 34551 bcm_oam_event_type_t event_type = 0; 34552 _bcm_oam_pm_event_handler_t *pm_event_handler_p; 34553 bcm_oam_pm_raw_data_t *raw_data = NULL; 34554 uint8 *dma_buffer = NULL; 34555 int is_updated = 0; 34556 #if defined (INCLUDE_MPLS_LM_DM) || defined (INCLUDE_ETH_LM_DM) 34557 uint32 event_mask; 34558 int sess_id; 34559 uint16 ep_id = 0; 34560 _bcm_oam_hash_data_t *h_data_p = NULL; 34561 bcm_oam_event_types_t events; 34562 _bcm_oam_event_handler_t *event_handler_p; 34563 #endif 34564 34565 switch (event_msg->s.mclass) { 34566 case MOS_MSG_CLASS_BHH_EVENT: 34567 event_type = bcmOAMEventBHHRawData; 34568 break; 34569 case MOS_MSG_CLASS_ETH_LM_DM_EVENT: 34570 #if defined (INCLUDE_ETH_LM_DM) 34571 event_mask = bcm_ntohl(event_msg->s.data); 34572 if (event_mask & ETH_LM_DM_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER) { 34573 event_type = bcmOAMEventEthLmDmPmCounterRollover; 34574 sess_id = (int)bcm_ntohs(event_msg->s.len); 34575 ep_id = oc->eth_lm_dm_sess_id_ep_id[sess_id]; 34576 h_data_p = &oc->oam_hash_data[ep_id]; 34577 /* Set events */ 34578 sal_memset(&events, 0, sizeof(events)); 34579 LOG_DEBUG(BSL_LS_BCM_OAM, 34580 (BSL_META_U(oc->unit, 34581 "****** OAM PM ETH_LM_DM Counter Rollover ******\n"))); 34582 if (oc->event_handler_cnt[bcmOAMEventEthLmDmPmCounterRollover] > 0) { 34583 SHR_BITSET(events.w, bcmOAMEventEthLmDmPmCounterRollover); 34584 } 34585 } else { 34586 event_type = bcmOAMEventEthLmDmRawData; 34587 } 34588 #endif 34589 break; 34590 case MOS_MSG_CLASS_MPLS_LM_DM_EVENT: 34591 #if defined (INCLUDE_MPLS_LM_DM) 34592 event_mask = bcm_ntohl(event_msg->s.data); 34593 if (event_mask & MPLS_LM_DM_BTE_EVENT_PM_STATS_COUNTER_ROLLOVER) { 34594 event_type = bcmOAMEventMplsLmDmPmCounterRollover; 34595 sess_id = (int)bcm_ntohs(event_msg->s.len); 34596 ep_id = oc->mpls_lm_dm_sess_id_ep_id[sess_id]; 34597 h_data_p = &oc->oam_hash_data[ep_id]; 34598 /* Set events */ 34599 sal_memset(&events, 0, sizeof(events)); 34600 LOG_DEBUG(BSL_LS_BCM_OAM, 34601 (BSL_META_U(oc->unit, 34602 "****** OAM PM MPLS_LM_DM Counter Rollover ******\n"))); 34603 if (oc->event_handler_cnt[bcmOAMEventMplsLmDmPmCounterRollover] > 0) { 34604 SHR_BITSET(events.w, bcmOAMEventMplsLmDmPmCounterRollover); 34605 } 34606 } else { 34607 event_type = bcmOAMEventMplsLmDmRawData; 34608 } 34609 #endif 34610 break; 34611 default: 34612 LOG_ERROR(BSL_LS_BCM_OAM, 34613 (BSL_META( 34614 "OAM(unit %d) Error: %s called" 34615 "for unknown protocol" 34616 "- %d.\n"), 34617 oc->unit, FUNCTION_NAME(), event_msg->s.mclass)); 34618 return; 34619 break; 34620 } 34621 34622 if (oc->pm_event_handler_cnt[event_type] < 0) { 34623 LOG_ERROR(BSL_LS_BCM_OAM, 34624 (BSL_META( 34625 "OAM(unit %d) Error: Received notif for" 34626 "event without callback - %d.\n"), 34627 oc->unit, event_type)); 34628 } 34629 34630 /* Loop over registered callbacks 34631 */ 34632 if ((event_type == bcmOAMEventEthLmDmPmCounterRollover) || 34633 (event_type == bcmOAMEventMplsLmDmPmCounterRollover)) { 34634 #if defined (INCLUDE_MPLS_LM_DM) || defined (INCLUDE_ETH_LM_DM) 34635 for (event_handler_p = oc->event_handler_list_p; event_handler_p != NULL; 34636 event_handler_p = event_handler_p->next_p) { 34637 if (SHR_BITGET(events.w, event_type)) { 34638 if (SHR_BITGET(event_handler_p->event_types.w, event_type)) { 34639 event_handler_p->cb(oc->unit, 34640 0, event_type, 34641 h_data_p->group_index, 34642 ep_id, 34643 event_handler_p->user_data); 34644 } 34645 } 34646 } 34647 #endif 34648 } else { 34649 for (pm_event_handler_p = oc->pm_event_handler_list_p; 34650 pm_event_handler_p != NULL; 34651 pm_event_handler_p = pm_event_handler_p->next_p) { 34652 if (SHR_BITGET(pm_event_handler_p->event_types.w, 34653 event_type)) { 34654 raw_data = _bcm_sb2_oam_pm_raw_data_info_get(oc->unit, 34655 event_type); 34656 dma_buffer = _bcm_sb2_oam_pm_dma_buffer_get(oc->unit, 34657 event_type); 34658 if (!raw_data) { 34659 /* Should not happen. This would mean you have received 34660 * a PM event for which you have not allocated buffers 34661 * itself. 34662 */ 34663 LOG_ERROR(BSL_LS_BCM_OAM, 34664 (BSL_META_U(oc->unit, 34665 "OAM(unit %d) Error: Oam raw data get failed " 34666 "event - %d.\n"), oc->unit, event_type)); 34667 } 34668 is_updated = _bcm_sb2_update_dma_buffer_into_raw_buffer(oc->unit, 34669 event_type, 34670 dma_buffer, 34671 raw_data); 34672 if (is_updated) { 34673 pm_event_handler_p->cb(oc->unit, 34674 event_type, 34675 raw_data, /* The raw data */ 34676 pm_event_handler_p->user_data); 34677 } else { 34678 /* Oops ! The event is lost ! */ 34679 LOG_WARN(BSL_LS_BCM_OAM, 34680 (BSL_META_U(oc->unit, 34681 "OAM(unit %d) Error: PM event missed " 34682 "event - %d.\n"), oc->unit, event_type)); 34683 } 34684 } 34685 } 34686 } 34687 34688 } 34689 #endif 34690 #if defined (INCLUDE_ETH_LM_DM) || defined (INCLUDE_MPLS_LM_DM) 34691 /* 34692 * Function: 34693 * _bcm_sb2_oam_pm_callback_thread_func 34694 * Purpose: 34695 * Thread to listen for event messages from uController for PM events. 34696 * Parameters: 34697 * oc - Pointer to oam control structures. 34698 * events - the set of events that we are listening. 34699 * Returns: 34700 * None 34701 */ 34702 STATIC void _bcm_oam_pm_callback_thread_func(_bcm_oam_control_t *oc, 34703 bcm_oam_event_types_t event_types) 34704 { 34705 int rv; 34706 mos_msg_data_t event_msg; 34707 char thread_name[SAL_THREAD_NAME_MAX_LEN]; 34708 sal_thread_t *pm_event_thread_id = NULL; 34709 int uc_num = -1; 34710 uint8 msg_class = 0; 34711 34712 if (BCM_OAM_EVENT_TYPE_GET(event_types, bcmOAMEventEthLmDmRawData) || 34713 BCM_OAM_EVENT_TYPE_GET(event_types, bcmOAMEventEthLmDmPmCounterRollover)) { 34714 pm_event_thread_id = &(oc->eth_lm_dm_pm_event_thread_id); 34715 #if defined (INCLUDE_ETH_LM_DM) 34716 uc_num = oc->eth_lm_dm_uc_num; 34717 #endif 34718 msg_class = MOS_MSG_CLASS_ETH_LM_DM_EVENT; 34719 } else if (BCM_OAM_EVENT_TYPE_GET(event_types, bcmOAMEventMplsLmDmRawData) || 34720 BCM_OAM_EVENT_TYPE_GET(event_types, bcmOAMEventMplsLmDmPmCounterRollover)) { 34721 pm_event_thread_id = &(oc->mpls_lm_dm_pm_event_thread_id); 34722 #if defined (INCLUDE_MPLS_LM_DM) 34723 uc_num = oc->mpls_lm_dm_uc_num; 34724 #endif 34725 msg_class = MOS_MSG_CLASS_MPLS_LM_DM_EVENT; 34726 } else { 34727 /* No other event is currently handled here. return. */ 34728 LOG_ERROR(BSL_LS_BCM_OAM, 34729 (BSL_META_U(oc->unit, 34730 "OAM(unit %d) Error: %s called for unknown " 34731 "event.\n"), oc->unit, FUNCTION_NAME())); 34732 return; 34733 } 34734 34735 thread_name[0] = 0; 34736 sal_thread_name(*pm_event_thread_id, thread_name, sizeof (thread_name)); 34737 34738 while (1) { 34739 /* Wait on notifications from uController */ 34740 rv = soc_cmic_uc_msg_receive(oc->unit, uc_num, 34741 msg_class, &event_msg, 34742 sal_sem_FOREVER); 34743 34744 if (BCM_FAILURE(rv)) { 34745 break; /* Thread exit */ 34746 } else { 34747 if ((event_msg.s.subclass == _ETH_LM_DM_EVENT_OAM_PM_EVENT) || 34748 (event_msg.s.subclass == _MPLS_LM_DM_EVENT_OAM_PM_EVENT)) { 34749 _bcm_sb2_oam_pm_event_msg_handle(oc, &event_msg); 34750 } else { 34751 LOG_ERROR(BSL_LS_BCM_OAM, 34752 (BSL_META( 34753 "OAM(unit %d) Error: Unknown PM event" 34754 "- %d.\n"), 34755 oc->unit, event_msg.s.subclass)); 34756 } 34757 } 34758 } 34759 34760 *pm_event_thread_id = NULL; 34761 LOG_ERROR(BSL_LS_BCM_OAM, 34762 (BSL_META_U(oc->unit, 34763 "Thread Exit:%s\n"), thread_name)); 34764 sal_thread_exit(0); 34765 } 34766 #endif 34767 34768 #if defined (INCLUDE_ETH_LM_DM) 34769 STATIC void 34770 _bcm_sb2_oam_pm_ethlmdm_callback_thread(void *param) 34771 { 34772 _bcm_oam_control_t *oc = (_bcm_oam_control_t *)param; 34773 bcm_oam_event_types_t event_types = {{0}}; 34774 34775 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEthLmDmRawData); 34776 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventEthLmDmPmCounterRollover); 34777 34778 _bcm_oam_pm_callback_thread_func(oc, event_types); 34779 } 34780 #endif 34781 #if defined (INCLUDE_MPLS_LM_DM) 34782 STATIC void 34783 _bcm_sb2_oam_pm_mplslmdm_callback_thread(void *param) 34784 { 34785 _bcm_oam_control_t *oc = (_bcm_oam_control_t *)param; 34786 bcm_oam_event_types_t event_types = {{0}}; 34787 34788 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventMplsLmDmRawData); 34789 BCM_OAM_EVENT_TYPE_SET(event_types, bcmOAMEventMplsLmDmPmCounterRollover); 34790 34791 _bcm_oam_pm_callback_thread_func(oc, event_types); 34792 } 34793 #endif 34794 34795 int 34796 bcm_sb2_oam_opcode_group_set(int unit, bcm_oam_protocol_type_t proto, 34797 bcm_oam_opcodes_t opcodes, uint8 opcode_group) { 34798 34799 int rv = BCM_E_NONE; 34800 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 34801 oam_opcode_group_entry_t opcode_grp_entry; 34802 int opcode_value; 34803 int opcode_key = -1; 34804 oam_opcode_control_profile_entry_t *opcode_entry = NULL; /* Opcode control 34805 profile entry. */ 34806 egr_oam_opcode_control_profile_entry_t *egr_opcode_entry = NULL; 34807 void *entries[1]; /* Profile entry. */ 34808 34809 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 34810 34811 _BCM_OAM_LOCK(oc); 34812 34813 if(opcode_group >= _BCM_SB2_OAM_NUM_OPCODE_GROUPS) { 34814 _BCM_OAM_UNLOCK(oc); 34815 return BCM_E_PARAM; 34816 } 34817 34818 for (opcode_value = 0; opcode_value <= _BCM_OAM_OPCODE_TYPE_NON_CFM_LAST; 34819 opcode_value++) { 34820 34821 if(BCM_OAM_OPCODES_BITMAP_GET(opcodes,opcode_value)){ 34822 34823 /* Try to form the key( _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(opcode_value))and 34824 * do a table lookup to modify the the entries opcode */ 34825 switch(proto) { 34826 case bcmOamProtocolEth: 34827 opcode_key = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(opcode_value); 34828 break; 34829 34830 case bcmOamProtocolBhh : 34831 opcode_key = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(opcode_value); 34832 break; 34833 34834 case bcmOamProtocolMplsLmDm : 34835 opcode_key = _BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(opcode_value); 34836 break; 34837 34838 default: 34839 rv = BCM_E_PARAM; 34840 _BCM_OAM_UNLOCK(oc); 34841 return rv; 34842 34843 } 34844 } 34845 34846 /* If opocde value is not preset in the opcodes bitmap then 34847 * opcode_key will not be set. So go for next opocode value in the bitmap */ 34848 34849 if(opcode_key == -1) { 34850 continue; 34851 } 34852 34853 rv = soc_mem_read(unit, OAM_OPCODE_GROUPm, MEM_BLOCK_ANY, 34854 opcode_key, &opcode_grp_entry); 34855 34856 if (BCM_FAILURE(rv)) { 34857 LOG_ERROR(BSL_LS_BCM_OAM, 34858 (BSL_META_U(unit, 34859 "OAM(unit %d) Error: OAM_OPCODE_GROUP table entry read " 34860 "failed %s.\n"), unit, bcm_errmsg(rv))); 34861 _BCM_OAM_UNLOCK(oc); 34862 return rv; 34863 } 34864 34865 soc_mem_field32_set(unit, OAM_OPCODE_GROUPm, 34866 &opcode_grp_entry, OPCODE_GROUPf, opcode_group); 34867 34868 rv = soc_mem_write(unit, OAM_OPCODE_GROUPm, 34869 MEM_BLOCK_ALL, opcode_key, &opcode_grp_entry); 34870 34871 if (BCM_FAILURE(rv)) { 34872 LOG_ERROR(BSL_LS_BCM_OAM, 34873 (BSL_META_U(unit, 34874 "OAM(unit %d) Error: OAM_OPCODE_GROUP table entry write " 34875 "failed %s.\n"), unit, bcm_errmsg(rv))); 34876 _BCM_OAM_UNLOCK(oc); 34877 return rv; 34878 } 34879 34880 rv = soc_mem_write(unit, EGR_OAM_OPCODE_GROUPm, 34881 MEM_BLOCK_ALL, opcode_key, &opcode_grp_entry); 34882 34883 if (BCM_FAILURE(rv)) { 34884 LOG_ERROR(BSL_LS_BCM_OAM, 34885 (BSL_META_U(unit, 34886 "OAM(unit %d) Error: EGR_OAM_OPCODE_GROUP table entry write " 34887 "failed %s.\n"), unit, bcm_errmsg(rv))); 34888 _BCM_OAM_UNLOCK(oc); 34889 return rv; 34890 } 34891 } 34892 34893 opcode_entry = sal_alloc(_BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE, "opcode profile"); 34894 sal_memset(opcode_entry, 0, _BCM_SB2_OAM_OC_SINGLE_PROFILE_SIZE); 34895 rv = _bcm_sb2_oam_opcode_profile_entry_init(unit, OAM_OPCODE_CONTROL_PROFILEm, opcode_entry); 34896 if (BCM_FAILURE(rv)) { 34897 LOG_ERROR(BSL_LS_BCM_OAM, 34898 (BSL_META_U(unit, 34899 "OAM(unit %d) Error: Opcode profile init failed " 34900 " %s.\n"), unit, bcm_errmsg(rv))); 34901 if(opcode_entry) { 34902 sal_free(opcode_entry); 34903 } 34904 _BCM_OAM_UNLOCK(oc); 34905 return (rv); 34906 } 34907 /* Add entry to profile table. */ 34908 entries[0] = opcode_entry; 34909 rv = soc_profile_mem_set(unit, &oc->oam_opcode_control_profile, 34910 (void *)entries, _BCM_SB2_OAM_DEFAULT_OPCODE_PROFILE_INDEX); 34911 if (BCM_FAILURE(rv)) { 34912 LOG_ERROR(BSL_LS_BCM_OAM, 34913 (BSL_META_U(unit, 34914 "OAM(unit %d) Opcode profile table is full - %s.\n"), 34915 unit, bcm_errmsg(rv))); 34916 if(opcode_entry) { 34917 sal_free(opcode_entry); 34918 } 34919 _BCM_OAM_UNLOCK(oc); 34920 return rv; 34921 } 34922 if(opcode_entry) { 34923 sal_free(opcode_entry); 34924 } 34925 34926 egr_opcode_entry = sal_alloc(_BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE, "egr opcode profile"); 34927 /* Create default opcode control profile */ 34928 sal_memset(egr_opcode_entry, 0, _BCM_SB2_EGR_OAM_OC_SINGLE_PROFILE_SIZE); 34929 rv = _bcm_sb2_oam_opcode_profile_entry_init(unit, EGR_OAM_OPCODE_CONTROL_PROFILEm, egr_opcode_entry); 34930 if (BCM_FAILURE(rv)) { 34931 LOG_ERROR(BSL_LS_BCM_OAM, 34932 (BSL_META_U(unit, 34933 "OAM(unit %d) Error: Opcode profile init failed " 34934 " %s.\n"), unit, bcm_errmsg(rv))); 34935 if(egr_opcode_entry) { 34936 sal_free(egr_opcode_entry); 34937 } 34938 _BCM_OAM_UNLOCK(oc); 34939 return (rv); 34940 } 34941 /* Add entry to profile table. */ 34942 entries[0] = egr_opcode_entry; 34943 rv = soc_profile_mem_set(unit, &oc->egr_oam_opcode_control_profile, 34944 (void *)entries, _BCM_SB2_OAM_DEFAULT_OPCODE_PROFILE_INDEX); 34945 if (BCM_FAILURE(rv)) { 34946 LOG_ERROR(BSL_LS_BCM_OAM, 34947 (BSL_META_U(unit, 34948 "OAM(unit %d) Egr Opcode profile table is full - %s.\n"), 34949 unit, bcm_errmsg(rv))); 34950 if(egr_opcode_entry) { 34951 sal_free(egr_opcode_entry); 34952 } 34953 _BCM_OAM_UNLOCK(oc); 34954 return rv; 34955 } 34956 if(egr_opcode_entry) { 34957 sal_free(egr_opcode_entry); 34958 } 34959 34960 _BCM_OAM_UNLOCK(oc); 34961 return rv; 34962 } 34963 34964 int 34965 bcm_sb2_oam_opcode_group_get(int unit, bcm_oam_protocol_type_t proto, 34966 bcm_oam_opcode_t opcode, uint8 *opcode_group) { 34967 34968 int rv = BCM_E_NONE; 34969 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 34970 oam_opcode_group_entry_t opcode_grp_entry; 34971 int opcode_key = -1; 34972 34973 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 34974 34975 _BCM_OAM_LOCK(oc); 34976 34977 if(opcode >= bcmOamOpcodeMax) { 34978 _BCM_OAM_UNLOCK(oc); 34979 return BCM_E_PARAM; 34980 } 34981 34982 /* Try to form the key( _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(opcode_value))and 34983 * do a table lookup to get the the opcode group*/ 34984 switch(proto) { 34985 case bcmOamProtocolEth: 34986 opcode_key = _BCM_SB2_ETH_OAM_OPCODE_GRP_KEY_FORM(opcode); 34987 break; 34988 34989 case bcmOamProtocolBhh : 34990 opcode_key = _BCM_SB2_BHH_OAM_OPCODE_GRP_KEY_FORM(opcode); 34991 break; 34992 34993 case bcmOamProtocolMplsLmDm : 34994 opcode_key = _BCM_SB2_MPLS_LMDM_OPCODE_GRP_KEY_FORM(opcode); 34995 break; 34996 34997 default: 34998 rv = BCM_E_PARAM; 34999 _BCM_OAM_UNLOCK(oc); 35000 return rv; 35001 } 35002 35003 rv = soc_mem_read(unit, OAM_OPCODE_GROUPm, MEM_BLOCK_ANY, 35004 opcode_key, &opcode_grp_entry); 35005 35006 if (BCM_FAILURE(rv)) { 35007 LOG_ERROR(BSL_LS_BCM_OAM, 35008 (BSL_META_U(unit, 35009 "OAM(unit %d) Error: OAM_OPCODE_GROUP table entry read " 35010 "failed %s.\n"), unit, bcm_errmsg(rv))); 35011 _BCM_OAM_UNLOCK(oc); 35012 return rv; 35013 } 35014 35015 *opcode_group = soc_mem_field32_get(unit, OAM_OPCODE_GROUPm, 35016 &opcode_grp_entry, OPCODE_GROUPf); 35017 35018 _BCM_OAM_UNLOCK(oc); 35019 return rv; 35020 } 35021 35022 35023 /* 35024 * Function: 35025 * bcm_sb2_oam_endpoint_egress_intf_egress_attach 35026 * Purpose: 35027 * Attach Egress object pointed by egress_intf to a MPLS LSP endpoint 35028 * 35029 * Parameters: 35030 * unit (IN) BCM device number 35031 * ep_d (IN) BHH endpoint ID 35032 * egress_intf (IN) Egress object 35033 * 35034 * Returns: 35035 * BCM_E_NONE No error 35036 * BCM_E_XXXX Error 35037 */ 35038 35039 int bcm_sb2_oam_endpoint_egress_intf_egress_attach(int unit, 35040 bcm_oam_endpoint_t ep_id, 35041 bcm_if_t egress_intf) 35042 { 35043 35044 int rv = BCM_E_UNAVAIL; 35045 #if defined(INCLUDE_L3) 35046 _bcm_oam_hash_data_t *h_data_p = NULL; 35047 _bcm_oam_control_t *oc = NULL; 35048 uint32 egr_nh_index = 0; 35049 egr_l3_next_hop_entry_t egr_nh_entry; 35050 int found = 0; 35051 _bcm_oam_endpoint_egress_interface_list_t *list_node = NULL; 35052 bcm_l3_egress_t l3_egress; 35053 35054 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 35055 _BCM_OAM_EP_INDEX_VALIDATE(ep_id); 35056 35057 _BCM_OAM_LOCK(oc); 35058 35059 /* Check endpoint status. */ 35060 rv = shr_idxres_list_elem_state(oc->mep_pool, ep_id); 35061 if ((BCM_E_EXISTS != rv)) { 35062 /* Endpoint not in use. */ 35063 LOG_ERROR(BSL_LS_BCM_OAM, 35064 (BSL_META_U(unit, 35065 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 35066 unit, ep_id, bcm_errmsg(rv))); 35067 _BCM_OAM_UNLOCK(oc); 35068 return (rv); 35069 } 35070 35071 /* Check the Existed Egress Interface Status */ 35072 bcm_l3_egress_t_init(&l3_egress); 35073 if (BCM_FAILURE 35074 (bcm_esw_l3_egress_get(unit, egress_intf, &l3_egress))) { 35075 _BCM_OAM_UNLOCK(oc); 35076 return BCM_E_NOT_FOUND; 35077 } 35078 35079 h_data_p = &oc->oam_hash_data[ep_id]; 35080 if ((NULL == h_data_p) || (h_data_p->in_use == 0)) { 35081 _BCM_OAM_UNLOCK(oc); 35082 return (BCM_E_INTERNAL); 35083 } 35084 /* Check if the endpoint is of type BHHMPLS or MPLS LM/DM LSP. Else return E_PARAM */ 35085 if (!BHH_EP_LSP_TYPE(h_data_p) && !MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) { 35086 _BCM_OAM_UNLOCK(oc); 35087 return BCM_E_PARAM; 35088 } 35089 35090 /* Run through the egress_if_list and check if the given egress interface 35091 already exists */ 35092 list_node = h_data_p->egress_if_list; 35093 while (list_node != NULL) { 35094 if (egress_intf == list_node->egress_if) { 35095 found = 1; 35096 break; 35097 } 35098 list_node = list_node->next; 35099 } 35100 if (found) { 35101 _BCM_OAM_UNLOCK(oc); 35102 return BCM_E_EXISTS; 35103 } 35104 35105 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, egress_intf)) { 35106 egr_nh_index = egress_intf - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 35107 } 35108 else if(BCM_XGS3_L3_EGRESS_IDX_VALID(unit, egress_intf)) { 35109 egr_nh_index = egress_intf - BCM_XGS3_EGRESS_IDX_MIN(unit); 35110 } else { 35111 _BCM_OAM_UNLOCK(oc); 35112 return BCM_E_PARAM; 35113 } 35114 35115 sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry)); 35116 rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, 35117 egr_nh_index, &egr_nh_entry); 35118 if (BCM_FAILURE(rv)) { 35119 _BCM_OAM_UNLOCK(oc); 35120 return (rv); 35121 } 35122 35123 /* Depending on whether endpoint is BHH or MPLS LM/DM, write 1/2 in MPLS_OAM_DOWNMEP_ENABLE. */ 35124 if (BHH_EP_TYPE(h_data_p)) { 35125 #if defined(INCLUDE_BHH) 35126 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry, 35127 MPLS__MPLS_OAM_DOWNMEP_ENABLEf, 35128 _BCM_SB2_MPLS_OAM_ENABLE_BHH); 35129 35130 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry, 35131 MPLS__MEPIDf, 35132 BCM_OAM_BHH_GET_LSP_KEY(h_data_p)); 35133 #endif /* INCLUDE_BHH */ 35134 } else if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 35135 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry, 35136 MPLS__MPLS_OAM_DOWNMEP_ENABLEf, 35137 _BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM); 35138 35139 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry, 35140 MPLS__MEPIDf, 35141 h_data_p->name); 35142 } else { 35143 _BCM_OAM_UNLOCK(oc); 35144 return BCM_E_PARAM; 35145 } 35146 35147 rv = WRITE_EGR_L3_NEXT_HOPm (unit, MEM_BLOCK_ALL, 35148 egr_nh_index, &egr_nh_entry); 35149 if (BCM_FAILURE(rv)) { 35150 _BCM_OAM_UNLOCK(oc); 35151 return (rv); 35152 } 35153 35154 /* Add the egress_if (encap_id) into the endpoint's egress_if_list */ 35155 _bcm_sb2_oam_endpoint_egress_intf_add(unit, h_data_p, egress_intf); 35156 35157 _BCM_OAM_UNLOCK(oc); 35158 rv = BCM_E_NONE; 35159 35160 #endif 35161 return rv; 35162 } 35163 35164 /* 35165 * Function: 35166 * bcm_sb2_oam_endpoint_egress_intf_egress_detach 35167 * Purpose: 35168 * detach Egress object pointed by egress_intf from a MPLS LSP endpoint 35169 * 35170 * Parameters: 35171 * unit (IN) BCM device number 35172 * ep_d (IN) BHH endpoint ID 35173 * egress_intf (IN) Egress object 35174 * 35175 * Returns: 35176 * BCM_E_NONE No error 35177 * BCM_E_XXXX Error 35178 */ 35179 35180 int bcm_sb2_oam_endpoint_egress_intf_egress_detach(int unit, 35181 bcm_oam_endpoint_t ep_id, 35182 bcm_if_t egress_intf) 35183 { 35184 int rv = BCM_E_UNAVAIL; 35185 #if defined(INCLUDE_L3) 35186 _bcm_oam_hash_data_t *h_data_p = NULL; 35187 _bcm_oam_control_t *oc = NULL; 35188 uint32 egr_nh_index = 0; 35189 egr_l3_next_hop_entry_t egr_nh_entry; 35190 uint16 mepid; 35191 int found = 0; 35192 _bcm_oam_endpoint_egress_interface_list_t *list_node = NULL; 35193 35194 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 35195 _BCM_OAM_EP_INDEX_VALIDATE(ep_id); 35196 35197 _BCM_OAM_LOCK(oc); 35198 35199 /* Check endpoint status. */ 35200 rv = shr_idxres_list_elem_state(oc->mep_pool, ep_id); 35201 if ((BCM_E_EXISTS != rv)) { 35202 /* Endpoint not in use. */ 35203 LOG_ERROR(BSL_LS_BCM_OAM, 35204 (BSL_META_U(unit, 35205 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 35206 unit, ep_id, bcm_errmsg(rv))); 35207 _BCM_OAM_UNLOCK(oc); 35208 return (rv); 35209 } 35210 35211 h_data_p = &oc->oam_hash_data[ep_id]; 35212 if ((NULL == h_data_p) || (h_data_p->in_use == 0)) { 35213 _BCM_OAM_UNLOCK(oc); 35214 return (BCM_E_INTERNAL); 35215 } 35216 35217 /* Check if the endpoint is of type BHHMPLS or MPLS LM/DM LSP. 35218 Else return E_PARAM */ 35219 if (!BHH_EP_LSP_TYPE(h_data_p) && !MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) { 35220 _BCM_OAM_UNLOCK(oc); 35221 return BCM_E_PARAM; 35222 } 35223 /* Run through the egress_if_list and check whether given egress interface 35224 is configured for this endpoint */ 35225 list_node = h_data_p->egress_if_list; 35226 while (list_node != NULL) { 35227 if (egress_intf == list_node->egress_if) { 35228 found = 1; 35229 break; 35230 } 35231 list_node = list_node->next; 35232 } 35233 35234 if (!found) { 35235 _BCM_OAM_UNLOCK(oc); 35236 return BCM_E_NOT_FOUND; 35237 } 35238 35239 if (BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, egress_intf)) { 35240 egr_nh_index = egress_intf - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 35241 } 35242 else if(BCM_XGS3_L3_EGRESS_IDX_VALID(unit, egress_intf)) { 35243 egr_nh_index = egress_intf - BCM_XGS3_EGRESS_IDX_MIN(unit); 35244 } else { 35245 _BCM_OAM_UNLOCK(oc); 35246 return BCM_E_PARAM; 35247 } 35248 35249 sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry)); 35250 rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, 35251 egr_nh_index, &egr_nh_entry); 35252 if (BCM_FAILURE(rv)) { 35253 _BCM_OAM_UNLOCK(oc); 35254 return (rv); 35255 } 35256 mepid = soc_EGR_L3_NEXT_HOPm_field32_get(unit, &egr_nh_entry, 35257 MPLS__MEPIDf); 35258 if ((MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) && 35259 (h_data_p->name != mepid)) { 35260 _BCM_OAM_UNLOCK(oc); 35261 return BCM_E_NOT_FOUND; 35262 } 35263 /* Reset the MPLS_OAM_DOWNMEP_ENABLE field */ 35264 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry, 35265 MPLS__MPLS_OAM_DOWNMEP_ENABLEf, 35266 0); 35267 35268 /* Reset the MEP_ID field in EGR_L3_NEXT_HOP */ 35269 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry, 35270 MPLS__MEPIDf, 35271 0); 35272 35273 rv = WRITE_EGR_L3_NEXT_HOPm (unit, MEM_BLOCK_ALL, 35274 egr_nh_index, &egr_nh_entry); 35275 if (BCM_FAILURE(rv)) { 35276 _BCM_OAM_UNLOCK(oc); 35277 return (rv); 35278 } 35279 35280 /* Delete the egress_if (encap_id) from the endpoint's egress_if_list */ 35281 _bcm_sb2_oam_endpoint_egress_intf_delete(unit, h_data_p, egress_intf); 35282 35283 _BCM_OAM_UNLOCK(oc); 35284 rv = BCM_E_NONE; 35285 #endif 35286 return rv; 35287 } 35288 35289 /* 35290 * Function: 35291 * bcm_sb2_oam_endpoint_egress_intf_egress_attach_get 35292 * Purpose: 35293 * Get the list of Egress interfaces attached to MPLS LSP endpoint 35294 * 35295 * Parameters: 35296 * unit (IN) BCM device number 35297 * ep_d (IN) BHH endpoint ID 35298 * size (IN) Size of array of egress interfaces passed in the egress_intf parameter. 35299 * egress_intf (OUT) Array of Egress object 35300 * count (OUT) The actual count of Egress interfaces returned in the egress_intf array. 35301 * 35302 * Returns: 35303 * BCM_E_NONE No error 35304 * BCM_E_XXXX Error 35305 */ 35306 35307 int bcm_sb2_oam_endpoint_egress_intf_egress_attach_get(int unit, 35308 bcm_oam_endpoint_t ep_id, 35309 int size, 35310 bcm_if_t *egress_intf, 35311 int *count) 35312 { 35313 int rv = BCM_E_UNAVAIL; 35314 #if defined(INCLUDE_L3) 35315 _bcm_oam_hash_data_t *h_data_p = NULL; 35316 _bcm_oam_control_t *oc = NULL; 35317 int index = 0; 35318 _bcm_oam_endpoint_egress_interface_list_t *list_node = NULL; 35319 35320 /* Check input parameters. */ 35321 if(size <= 0) { 35322 return BCM_E_PARAM; 35323 } 35324 35325 if (egress_intf == NULL || count == NULL) { 35326 return BCM_E_PARAM; 35327 } 35328 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 35329 _BCM_OAM_EP_INDEX_VALIDATE(ep_id); 35330 35331 _BCM_OAM_LOCK(oc); 35332 35333 /* Check endpoint status. */ 35334 rv = shr_idxres_list_elem_state(oc->mep_pool, ep_id); 35335 if ((BCM_E_EXISTS != rv)) { 35336 /* Endpoint not in use. */ 35337 LOG_ERROR(BSL_LS_BCM_OAM, 35338 (BSL_META_U(unit, 35339 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 35340 unit, ep_id, bcm_errmsg(rv))); 35341 _BCM_OAM_UNLOCK(oc); 35342 return (rv); 35343 } 35344 35345 h_data_p = &oc->oam_hash_data[ep_id]; 35346 if ((NULL == h_data_p) || (h_data_p->in_use == 0)) { 35347 _BCM_OAM_UNLOCK(oc); 35348 return (BCM_E_INTERNAL); 35349 } 35350 35351 /* Check if it is a LSP endpoint */ 35352 if (!BHH_EP_LSP_TYPE(h_data_p) && !MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) { 35353 _BCM_OAM_UNLOCK(oc); 35354 return BCM_E_PARAM; 35355 } 35356 /* Run through the egress_if_list and fill the egress gport and egress 35357 * interfaces */ 35358 list_node = h_data_p->egress_if_list; 35359 while (list_node != NULL) { 35360 egress_intf[index] = list_node->egress_if; 35361 index++; 35362 if (index == size) { 35363 break; 35364 } 35365 list_node = list_node->next; 35366 } 35367 *count = index; 35368 35369 _BCM_OAM_UNLOCK(oc); 35370 rv = BCM_E_NONE; 35371 #endif 35372 return rv; 35373 } 35374 35375 int bcm_sb2_oam_endpoint_gport_egress_attach(int unit, 35376 bcm_oam_endpoint_t endpoint, 35377 bcm_gport_t gport) 35378 { 35379 #if defined(INCLUDE_L3) 35380 bcm_if_t egress_if; 35381 _bcm_oam_hash_data_t *h_data_p = NULL; 35382 _bcm_oam_control_t *oc = NULL; 35383 uint32 egr_nh_index = 0; 35384 egr_l3_next_hop_entry_t egr_nh_entry; 35385 int rv = BCM_E_NONE; 35386 int found = 0; 35387 _bcm_oam_endpoint_egress_interface_list_t *list_node = NULL; 35388 35389 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 35390 _BCM_OAM_EP_INDEX_VALIDATE(endpoint); 35391 35392 _BCM_OAM_LOCK(oc); 35393 35394 /* Check endpoint status. */ 35395 rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint); 35396 if ((BCM_E_EXISTS != rv)) { 35397 /* Endpoint not in use. */ 35398 LOG_ERROR(BSL_LS_BCM_OAM, 35399 (BSL_META_U(unit, 35400 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 35401 unit, endpoint, bcm_errmsg(rv))); 35402 _BCM_OAM_UNLOCK(oc); 35403 return (rv); 35404 } 35405 35406 h_data_p = &oc->oam_hash_data[endpoint]; 35407 if ((NULL == h_data_p) || (h_data_p->in_use == 0)) { 35408 _BCM_OAM_UNLOCK(oc); 35409 return (BCM_E_INTERNAL); 35410 } 35411 35412 /* Check if it is an MPLS port and of type VPWS. Else return E_PARAM */ 35413 if (!BCM_GPORT_IS_MPLS_PORT(gport)) { 35414 _BCM_OAM_UNLOCK(oc); 35415 return BCM_E_PARAM; 35416 } 35417 /* Check if the endpoint is of type BHHMPLS or MPLS LM/DM LSP. Else return E_PARAM */ 35418 if (!BHH_EP_LSP_TYPE(h_data_p) && !MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) { 35419 _BCM_OAM_UNLOCK(oc); 35420 return BCM_E_PARAM; 35421 } 35422 35423 /* Run through the egress_if_list and check if the given egress gport 35424 already exists */ 35425 list_node = h_data_p->egress_if_list; 35426 while (list_node != NULL) { 35427 if (gport == list_node->gport) { 35428 found = 1; 35429 break; 35430 } 35431 list_node = list_node->next; 35432 } 35433 35434 if (found) { 35435 _BCM_OAM_UNLOCK(oc); 35436 return BCM_E_EXISTS; 35437 } 35438 35439 /* Do a MPLS Port get and get the encap_id */ 35440 rv = _bcm_tr_mpls_vpws_egress_if_get(unit, gport, &egress_if); 35441 if (BCM_FAILURE(rv)) { 35442 _BCM_OAM_UNLOCK(oc); 35443 return BCM_E_PARAM; 35444 } 35445 35446 /* Check the encap id is of dvp egress type */ 35447 if (!BCM_XGS3_DVP_EGRESS_IDX_VALID(unit, egress_if)) { 35448 _BCM_OAM_UNLOCK(oc); 35449 return BCM_E_PARAM; 35450 } 35451 /* Find the EGR_L3_NEXT_HOP index from encap id. */ 35452 egr_nh_index = egress_if - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 35453 /* Write the endpoint.name/id as MEP_ID into EGR_L3_NEXT_HOP */ 35454 sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry)); 35455 rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, 35456 egr_nh_index, &egr_nh_entry); 35457 if (BCM_FAILURE(rv)) { 35458 _BCM_OAM_UNLOCK(oc); 35459 return (rv); 35460 } 35461 35462 /* Depending on whether endpoint is BHH or MPLS LM/DM, write 1/2 in MPLS_OAM_DOWNMEP_ENABLE. */ 35463 if (BHH_EP_TYPE(h_data_p)) { 35464 #if defined(INCLUDE_BHH) 35465 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry, 35466 MPLS__MPLS_OAM_DOWNMEP_ENABLEf, 35467 _BCM_SB2_MPLS_OAM_ENABLE_BHH); 35468 35469 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry, 35470 MPLS__MEPIDf, 35471 BCM_OAM_BHH_GET_LSP_KEY(h_data_p)); 35472 #endif /* INCLUDE_BHH */ 35473 } else if (MPLS_LM_DM_ENDPOINT_TYPE(h_data_p)) { 35474 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry, 35475 MPLS__MPLS_OAM_DOWNMEP_ENABLEf, 35476 _BCM_SB2_MPLS_OAM_ENABLE_MPLS_LMDM); 35477 35478 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry, 35479 MPLS__MEPIDf, 35480 h_data_p->name); 35481 } else { 35482 _BCM_OAM_UNLOCK(oc); 35483 return BCM_E_PARAM; 35484 } 35485 35486 35487 rv = WRITE_EGR_L3_NEXT_HOPm (unit, MEM_BLOCK_ALL, 35488 egr_nh_index, &egr_nh_entry); 35489 if (BCM_FAILURE(rv)) { 35490 _BCM_OAM_UNLOCK(oc); 35491 return (rv); 35492 } 35493 35494 /* Add the gport and egress_if (encap_id) into the endpoint's egress_if_list */ 35495 _bcm_sb2_oam_endpoint_egress_interface_add(unit, h_data_p, egress_if, gport); 35496 35497 35498 _BCM_OAM_UNLOCK(oc); 35499 return BCM_E_NONE; 35500 #else 35501 return BCM_E_UNAVAIL; 35502 #endif 35503 } 35504 35505 int bcm_sb2_oam_endpoint_gport_egress_attach_get(int unit, 35506 bcm_oam_endpoint_t endpoint, 35507 int size, 35508 bcm_gport_t *gport, 35509 int *num_gports) 35510 { 35511 #if defined(INCLUDE_L3) 35512 _bcm_oam_hash_data_t *h_data_p = NULL; 35513 _bcm_oam_control_t *oc = NULL; 35514 _bcm_oam_endpoint_egress_interface_list_t *list_node = NULL; 35515 int rv = BCM_E_NONE; 35516 int index = 0; 35517 35518 /* Check input parameters. */ 35519 if(size <= 0) { 35520 return BCM_E_PARAM; 35521 } 35522 35523 if (gport == NULL || num_gports == NULL) { 35524 return BCM_E_PARAM; 35525 } 35526 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 35527 _BCM_OAM_EP_INDEX_VALIDATE(endpoint); 35528 35529 _BCM_OAM_LOCK(oc); 35530 35531 /* Check endpoint status. */ 35532 rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint); 35533 if ((BCM_E_EXISTS != rv)) { 35534 /* Endpoint not in use. */ 35535 LOG_ERROR(BSL_LS_BCM_OAM, 35536 (BSL_META_U(unit, 35537 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 35538 unit, endpoint, bcm_errmsg(rv))); 35539 _BCM_OAM_UNLOCK(oc); 35540 return (rv); 35541 } 35542 35543 h_data_p = &oc->oam_hash_data[endpoint]; 35544 if ((NULL == h_data_p) || (h_data_p->in_use == 0)) { 35545 _BCM_OAM_UNLOCK(oc); 35546 return (BCM_E_INTERNAL); 35547 } 35548 35549 /* Check if it is a LSP endpoint */ 35550 if (!BHH_EP_LSP_TYPE(h_data_p) && !MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) { 35551 _BCM_OAM_UNLOCK(oc); 35552 return BCM_E_PARAM; 35553 } 35554 /* Run through the egress_if_list and fill the egress gport and egress 35555 * interfaces */ 35556 list_node = h_data_p->egress_if_list; 35557 while (list_node != NULL) { 35558 gport[index] = list_node->gport; 35559 index++; 35560 if (index == size) { 35561 break; 35562 } 35563 list_node = list_node->next; 35564 } 35565 *num_gports = index; 35566 35567 _BCM_OAM_UNLOCK(oc); 35568 return BCM_E_NONE; 35569 #else 35570 return BCM_E_UNAVAIL; 35571 #endif 35572 } 35573 35574 int bcm_sb2_oam_endpoint_gport_egress_detach(int unit, 35575 bcm_oam_endpoint_t endpoint, 35576 bcm_gport_t gport) 35577 { 35578 #if defined(INCLUDE_L3) 35579 bcm_if_t egress_if; 35580 _bcm_oam_hash_data_t *h_data_p = NULL; 35581 _bcm_oam_control_t *oc = NULL; 35582 uint32 egr_nh_index = 0; 35583 egr_l3_next_hop_entry_t egr_nh_entry; 35584 int found = 0; 35585 _bcm_oam_endpoint_egress_interface_list_t *list_node = NULL; 35586 int rv = BCM_E_NONE; 35587 35588 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 35589 _BCM_OAM_EP_INDEX_VALIDATE(endpoint); 35590 35591 _BCM_OAM_LOCK(oc); 35592 35593 /* Check endpoint status. */ 35594 rv = shr_idxres_list_elem_state(oc->mep_pool, endpoint); 35595 if ((BCM_E_EXISTS != rv)) { 35596 /* Endpoint not in use. */ 35597 LOG_ERROR(BSL_LS_BCM_OAM, 35598 (BSL_META_U(unit, 35599 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 35600 unit, endpoint, bcm_errmsg(rv))); 35601 _BCM_OAM_UNLOCK(oc); 35602 return (rv); 35603 } 35604 35605 h_data_p = &oc->oam_hash_data[endpoint]; 35606 if ((NULL == h_data_p) || (h_data_p->in_use == 0)) { 35607 _BCM_OAM_UNLOCK(oc); 35608 return (BCM_E_INTERNAL); 35609 } 35610 35611 /* Check if it is an MPLS port and of type VPWS. Else return E_PARAM */ 35612 if (!BCM_GPORT_IS_MPLS_PORT(gport)) { 35613 _BCM_OAM_UNLOCK(oc); 35614 return BCM_E_PARAM; 35615 } 35616 /* Check if the endpoint is of type BHHMPLS or MPLS LM/DM LSP. Else return E_PARAM */ 35617 if (!BHH_EP_LSP_TYPE(h_data_p) && !MPLS_LM_DM_LSP_ENDPOINT_TYPE(h_data_p)) { 35618 _BCM_OAM_UNLOCK(oc); 35619 return BCM_E_PARAM; 35620 } 35621 /* Run through the egress_if_list and find the given egress gport 35622 and get the corresponding interface */ 35623 list_node = h_data_p->egress_if_list; 35624 while (list_node != NULL) { 35625 if (gport == list_node->gport) { 35626 found = 1; 35627 egress_if = list_node->egress_if; 35628 break; 35629 } 35630 list_node = list_node->next; 35631 } 35632 35633 if (!found) { 35634 _BCM_OAM_UNLOCK(oc); 35635 return BCM_E_NOT_FOUND; 35636 } 35637 35638 /* Find the EGR_L3_NEXT_HOP index from encap id. */ 35639 egr_nh_index = egress_if - BCM_XGS3_DVP_EGRESS_IDX_MIN(unit); 35640 35641 sal_memset(&egr_nh_entry, 0, sizeof(egr_nh_entry)); 35642 rv = READ_EGR_L3_NEXT_HOPm(unit, MEM_BLOCK_ANY, 35643 egr_nh_index, &egr_nh_entry); 35644 if (BCM_FAILURE(rv)) { 35645 _BCM_OAM_UNLOCK(oc); 35646 return (rv); 35647 } 35648 35649 /* Reset the MPLS_OAM_DOWNMEP_ENABLE field */ 35650 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry, 35651 MPLS__MPLS_OAM_DOWNMEP_ENABLEf, 35652 0); 35653 35654 /* Reset the MEP_ID field in EGR_L3_NEXT_HOP */ 35655 soc_EGR_L3_NEXT_HOPm_field32_set(unit, &egr_nh_entry, 35656 MPLS__MEPIDf, 35657 0); 35658 35659 rv = WRITE_EGR_L3_NEXT_HOPm (unit, MEM_BLOCK_ALL, 35660 egr_nh_index, &egr_nh_entry); 35661 if (BCM_FAILURE(rv)) { 35662 _BCM_OAM_UNLOCK(oc); 35663 return (rv); 35664 } 35665 35666 /* Delete the gport and egress_if (encap_id) from the endpoint's 35667 egress_if_list */ 35668 _bcm_sb2_oam_endpoint_egress_interface_delete(unit, h_data_p, 35669 gport); 35670 35671 _BCM_OAM_UNLOCK(oc); 35672 return BCM_E_NONE; 35673 #else 35674 return BCM_E_UNAVAIL; 35675 #endif 35676 } 35677 35678 /* 35679 * Function: 35680 * _bcm_sb2_bhh_endpoint_faults_multi_get 35681 * Purpose: 35682 * Function to get faults for multiple BHH endpoints 35683 * in a single call. 35684 * Parameters: 35685 * unit (IN) BCM device number 35686 * flags (IN) Flags is kept unused as of now. 35687 * This is for any future enhancement 35688 * max_endpoints (IN) Number of max endpoint for the protocol 35689 * faults (OUT) Pointer to faults for all endpoints 35690 * endpoint_count (OUT) Pointer to Number of valid endpoints with faults, 35691 * filled by get API. 35692 * 35693 * Returns: 35694 * BCM_E_NONE No error 35695 * BCM_E_XXXX Error 35696 */ 35697 35698 #if defined (INCLUDE_BHH) 35699 int _bcm_sb2_bhh_endpoint_faults_multi_get( 35700 int unit, 35701 uint32 flags, 35702 uint32 max_endpoints, 35703 bcm_oam_endpoint_fault_t *faults, 35704 uint32 *endpoint_count) 35705 { 35706 int rv = BCM_E_NONE; 35707 _bcm_oam_control_t *oc = NULL; 35708 bcm_oam_endpoint_fault_t *faults_temp = faults; 35709 uint8 *buffer; 35710 uint16 reply_len; 35711 uint32 sess_count; 35712 uint32 ep_id; 35713 uint32 ep_count = 0; 35714 uint32 faults_bitmap; 35715 _bcm_oam_hash_data_t *h_data_p; /* Pointer to endpoint hash data. */ 35716 35717 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 35718 35719 _BCM_OAM_LOCK(oc); 35720 35721 if(max_endpoints != oc->bhh_endpoint_count) { 35722 rv = BCM_E_PARAM; 35723 _BCM_OAM_UNLOCK(oc); 35724 return (rv); 35725 } 35726 35727 sal_memset(faults, 0, ((sizeof(bcm_oam_endpoint_fault_t))*max_endpoints)); 35728 35729 rv = _bcm_sb2_oam_bhh_msg_send_receive(unit, 35730 MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET, 35731 0, 0, 35732 MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET_REPLY, 35733 &reply_len); 35734 35735 if (BCM_FAILURE(rv)) { 35736 LOG_ERROR(BSL_LS_BCM_OAM, 35737 (BSL_META_U(unit, 35738 "OAM(unit %d) Error: BHH uKernel msg failed for" 35739 "faults multi get %s.\n"), unit, 35740 bcm_errmsg(rv))); 35741 _BCM_OAM_UNLOCK(oc); 35742 return (rv); 35743 } 35744 35745 if(reply_len != (oc->bhh_endpoint_count * sizeof(uint32))) { 35746 rv = BCM_E_INTERNAL; 35747 _BCM_OAM_UNLOCK(oc); 35748 return (rv); 35749 } 35750 /* Unpack control message data into DMA buffer */ 35751 buffer = oc->dma_buffer; 35752 for(sess_count = 0;sess_count < oc->bhh_endpoint_count;sess_count++) 35753 { 35754 ep_id = BCM_OAM_BHH_GET_SDK_EP(sess_count); 35755 35756 /* Validate endpoint index value. */ 35757 BCM_OAM_BHH_VALIDATE_EP(ep_id) 35758 35759 h_data_p = &oc->oam_hash_data[ep_id]; 35760 35761 /* If endpoint not in use, ignore and continue for next session_id). 35762 * If session is running in hostCPU, skip and Go to ep_id.*/ 35763 if(!(h_data_p->in_use) || (h_data_p->flags2 & BCM_OAM_ENDPOINT_FLAGS2_REDIRECT_TO_CPU)) { 35764 continue; 35765 } 35766 35767 _SHR_UNPACK_U32(buffer, faults_bitmap); 35768 35769 faults_temp->endpoint_id = BCM_OAM_BHH_GET_SDK_EP(sess_count); 35770 35771 if(faults_bitmap & BHH_BTE_EVENT_CCM_TIMEOUT){ 35772 faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT; 35773 } 35774 if(faults_bitmap & BHH_BTE_EVENT_CCM_RDI){ 35775 faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_RDI; 35776 } 35777 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){ 35778 faults_temp->faults |= 35779 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL; 35780 } 35781 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){ 35782 faults_temp->faults |= 35783 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID; 35784 } 35785 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){ 35786 faults_temp->faults |= 35787 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID; 35788 } 35789 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){ 35790 faults_temp->faults |= 35791 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD; 35792 } 35793 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){ 35794 faults_temp->faults |= 35795 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY; 35796 } 35797 35798 ep_count++; 35799 faults_temp++; 35800 35801 } 35802 35803 *endpoint_count = ep_count; 35804 _BCM_OAM_UNLOCK(oc); 35805 return (rv); 35806 35807 } 35808 #endif 35809 35810 /* 35811 * Function: 35812 * bcm_sb2_oam_endpoint_faults_multi_get 35813 * Purpose: 35814 * Function to get faults for multiple endpoints per protocl 35815 * in a single call. 35816 * Parameters: 35817 * unit (IN) BCM device number 35818 * flags (IN) Flags is kept unused as of now. 35819 * This is for any future enhancement 35820 * endpoint_protocol (IN) Protocol type of the endpoints to retrieve faults 35821 * max_endpoints (IN) Number of max endpoint for the protocol 35822 * faults (OUT) Pointer to faults for all endpoints 35823 * endpoint_count (OUT) Pointer to Number of valid endpoints with faults, 35824 * by get API. 35825 * 35826 * Returns: 35827 * BCM_E_NONE No error 35828 * BCM_E_XXXX Error 35829 */ 35830 35831 int bcm_sb2_oam_endpoint_faults_multi_get( 35832 int unit, 35833 uint32 flags, 35834 bcm_oam_protocol_type_t endpoint_protocol, 35835 uint32 max_endpoints, 35836 bcm_oam_endpoint_fault_t *faults, 35837 uint32 *endpoint_count) 35838 35839 { 35840 int rv = BCM_E_NONE; 35841 35842 if(!faults) { 35843 rv = BCM_E_PARAM; 35844 return (rv); 35845 } 35846 35847 switch(endpoint_protocol) { 35848 35849 #if defined(INCLUDE_BHH) 35850 case bcmOamProtocolBhh: 35851 *endpoint_count = 0; 35852 rv = _bcm_sb2_bhh_endpoint_faults_multi_get( 35853 unit, 35854 flags, 35855 max_endpoints, 35856 faults, 35857 endpoint_count); 35858 break; 35859 #endif 35860 default: 35861 rv = BCM_E_UNAVAIL; 35862 break; 35863 } 35864 35865 return rv; 35866 35867 } 35868 35869 /* This function assumes passed endpoint is a PORT MEP configured over trunk. */ 35870 int _bcm_sb2_oam_ep_trunk_ports_add_del_internal(int unit, _bcm_oam_hash_data_t *h_data_p, 35871 int max_ports, bcm_gport_t *port_arr, uint8 add) 35872 { 35873 _bcm_oam_hash_data_t old_hash_data; 35874 bcm_oam_endpoint_info_t ep_info; 35875 uint32 sglp = 0, dglp = 0; 35876 bcm_port_t src_pp_port = 0, dst_pp_port = 0, pp_port = 0; 35877 uint32 svp = 0; 35878 int vp_valid = 0; 35879 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 35880 bcm_trunk_member_t trunk_member; 35881 int i, module_id = 0; 35882 uint8 active_mdl = 0; 35883 35884 35885 bcm_oam_endpoint_info_t_init(&ep_info); 35886 /* ********************************************** 35887 * SW configurations 35888 */ 35889 /* Keep a copy of old hash data for comparisons. 35890 */ 35891 sal_memcpy(&old_hash_data, h_data_p, sizeof(_bcm_oam_hash_data_t)); 35892 35893 35894 /* Call endpoint get to get the endpoint info */ 35895 BCM_IF_ERROR_RETURN(bcm_sb2_oam_endpoint_get(unit, h_data_p->ep_id, &ep_info)); 35896 /* First call endpoint gport resolve to correctly update new 35897 * sglp, dglp, src_pp_port, dst_pp_port variables. 35898 */ 35899 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_endpoint_gport_resolve(unit, &ep_info, &sglp, &dglp, 35900 &src_pp_port, &dst_pp_port, &svp, 35901 &trunk_id, &vp_valid, &trunk_member)); 35902 35903 /* Update the h_data_p. */ 35904 h_data_p->sglp = sglp; 35905 h_data_p->dglp = dglp; 35906 h_data_p->src_pp_port = src_pp_port; 35907 h_data_p->dst_pp_port = dst_pp_port; 35908 h_data_p->resolved_trunk_gport = trunk_member.gport; 35909 35910 /* ************************************************ 35911 * HW configurations 35912 */ 35913 35914 for (i = 0; i < max_ports; i++) { 35915 BCM_IF_ERROR_RETURN 35916 (_bcm_kt2_pp_port_to_modport_get(unit, port_arr[i], 35917 &module_id, &pp_port)); 35918 if (add) { 35919 /* _bcm_sb2_oam_trunk_port_mdl_config needs to be called so that 35920 * new trunk members are programmed with MDL_BITMAP correctly. 35921 */ 35922 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_stm_table_update(unit, module_id, pp_port, h_data_p)); 35923 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_port_mdl_update(unit, pp_port, 0, h_data_p, &active_mdl)); 35924 } else { 35925 /* Delete the old ports' MDL BITMAP using _bcm_sb2_oam_port_mdl_update. And 35926 * clear STM table if this is the last endpoint on this port. 35927 */ 35928 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_port_mdl_update(unit, pp_port, 1, h_data_p, &active_mdl)); 35929 if (active_mdl == 0) { 35930 /* Setting index = -1 so that rx indexes are not freed up, since there are 35931 * other ports on the trunk on which this endpoint is placed. 35932 */ 35933 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_stm_table_clear(unit, module_id, -1, 35934 pp_port, 35935 h_data_p)); 35936 } 35937 } 35938 } 35939 35940 if (h_data_p->dst_pp_port != old_hash_data.dst_pp_port) { 35941 /* If dst_pp_port has changed, delete the old EGR_PORT MDL_PASSIVE BITMAP and 35942 * program the new port's EGR_PORT MDL_PASSIVE_BITMAP. 35943 */ 35944 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_port_mdl_passive_update(unit,1, &old_hash_data, 0)); 35945 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_port_mdl_passive_update(unit, 0 /* not reset */, 35946 h_data_p, active_mdl)); 35947 35948 if (ep_info.ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED) { 35949 /* If dst_pp_port has changed, modify the LMEP table to reflect new 35950 * dst pp port and corresponding queue number. 35951 */ 35952 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_lmep_down_modify_new_dest_port(unit, h_data_p)); 35953 } 35954 } 35955 35956 return BCM_E_NONE; 35957 } 35958 35959 35960 int _bcm_sb2_oam_trunk_ports_add_del_internal(int unit, bcm_gport_t trunk_gport, 35961 int max_ports, bcm_gport_t *port_arr, uint8 add) 35962 { 35963 int rv = BCM_E_NONE; 35964 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 35965 _bcm_oam_control_t *oc = NULL; 35966 _bcm_oam_hash_data_t *h_data_p = NULL; 35967 int i; 35968 35969 35970 /* Validate port array and max ports inputs */ 35971 if (port_arr == NULL || max_ports == 0) { 35972 return BCM_E_PARAM; 35973 } 35974 35975 /* Check the gport is TRUNK */ 35976 if (!(BCM_GPORT_IS_TRUNK(trunk_gport))) { 35977 return BCM_E_PARAM; 35978 } 35979 35980 /* Get Trunk ID value from Gport */ 35981 trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport); 35982 35983 if (trunk_id == BCM_TRUNK_INVALID) { 35984 return BCM_E_PARAM; 35985 } 35986 35987 /* Get OAM control structure */ 35988 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 35989 _BCM_OAM_LOCK(oc); 35990 35991 for (i = 0; i < oc->ep_count; i++) { 35992 h_data_p = &oc->oam_hash_data[i]; 35993 /* This API is supported only for PORT MEPs on Trunks */ 35994 if ((ETH_TYPE(h_data_p->type)) && 35995 (h_data_p->in_use) && 35996 (h_data_p->oam_domain == _BCM_OAM_DOMAIN_PORT) && 35997 (h_data_p->gport == trunk_gport) && 35998 (h_data_p->trunk_id == trunk_id)) { 35999 rv = _bcm_sb2_oam_ep_trunk_ports_add_del_internal(unit, h_data_p, max_ports, port_arr, add); 36000 if (BCM_FAILURE(rv)) { 36001 _BCM_OAM_UNLOCK(oc); 36002 return rv; 36003 } 36004 } 36005 } 36006 _BCM_OAM_UNLOCK(oc); 36007 return rv; 36008 } 36009 36010 int bcm_sb2_oam_trunk_ports_add(int unit, bcm_gport_t trunk_gport, 36011 int max_ports, bcm_gport_t *port_arr) 36012 { 36013 return _bcm_sb2_oam_trunk_ports_add_del_internal(unit, trunk_gport, max_ports, port_arr, 1); 36014 } 36015 int bcm_sb2_oam_trunk_ports_delete(int unit, bcm_gport_t trunk_gport, 36016 int max_ports, bcm_gport_t *port_arr) 36017 { 36018 return _bcm_sb2_oam_trunk_ports_add_del_internal(unit, trunk_gport, max_ports, port_arr, 0); 36019 } 36020 36021 /* 36022 * Function: 36023 * bcm_ml_oam_opcodes_count_profile_create 36024 * Purpose: 36025 * Create a new LM count profile for opcodes with all opcodes having counting disabled. 36026 * The id of the profile created is returned in lm_count_profile variable. 36027 * Parameters: 36028 * unit (IN) BCM device number 36029 * lm_count_profile (OUT) lm_count_profile id that will be returned by create API and 36030 * will be used for count_profile_set 36031 * 36032 * Returns: 36033 * BCM_E_NONE No error 36034 * BCM_E_XXXX Error 36035 */ 36036 #if defined(BCM_METROLITE_SUPPORT) 36037 int bcm_ml_oam_opcodes_count_profile_create( 36038 int unit, 36039 uint8 *lm_count_profile) 36040 36041 { 36042 int rv = BCM_E_NONE; 36043 _bcm_oam_control_t *oc = NULL; 36044 void *entries[1]; /* Profile entry. */ 36045 ing_lm_counter_control_entry_t *ing_lm_counter_control_entry; 36046 egr_lm_counter_control_entry_t *egr_lm_counter_control_entry; 36047 uint32 ing_lm_profile_index = -1; 36048 uint32 egr_lm_profile_index = -1; 36049 36050 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 36051 36052 _BCM_OAM_LOCK(oc); 36053 36054 /* ING OAM LM count control profile */ 36055 ing_lm_counter_control_entry = sal_alloc(_BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 36056 "ING OAM LM count control profile"); 36057 if(!ing_lm_counter_control_entry) { 36058 _BCM_OAM_UNLOCK(oc); 36059 rv = BCM_E_MEMORY; 36060 return rv; 36061 } 36062 36063 sal_memset(ing_lm_counter_control_entry, 0, 36064 _BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE); 36065 /* Add entry to profile table. */ 36066 entries[0] = ing_lm_counter_control_entry; 36067 rv = soc_profile_mem_add(unit, &oc->ing_lm_counter_control_profile, 36068 (void *)entries, 36069 _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE, 36070 &ing_lm_profile_index); 36071 36072 if (BCM_FAILURE(rv)) { 36073 LOG_ERROR(BSL_LS_BCM_OAM, 36074 (BSL_META_U(unit, 36075 "OAM(unit %d) ING OAM LM count control profile table is full - %s.\n"), 36076 unit, bcm_errmsg(rv))); 36077 if(ing_lm_counter_control_entry) { 36078 sal_free(ing_lm_counter_control_entry); 36079 } 36080 _BCM_OAM_UNLOCK(oc); 36081 return rv; 36082 } 36083 36084 if(ing_lm_counter_control_entry) { 36085 sal_free(ing_lm_counter_control_entry); 36086 } 36087 36088 /* EGR OAM LM count control profile */ 36089 egr_lm_counter_control_entry = sal_alloc(_BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 36090 "EGR OAM LM count control profile"); 36091 if(!egr_lm_counter_control_entry) { 36092 _BCM_OAM_UNLOCK(oc); 36093 rv = BCM_E_MEMORY; 36094 return rv; 36095 } 36096 36097 sal_memset(egr_lm_counter_control_entry, 0, 36098 _BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE); 36099 36100 /* Add entry to profile table. */ 36101 entries[0] = egr_lm_counter_control_entry; 36102 rv = soc_profile_mem_add(unit, &oc->egr_lm_counter_control_profile, 36103 (void *)entries, 36104 _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE, 36105 &egr_lm_profile_index); 36106 36107 if (BCM_FAILURE(rv)) { 36108 LOG_ERROR(BSL_LS_BCM_OAM, 36109 (BSL_META_U(unit, 36110 "OAM(unit %d) EGR OAM LM count control profile table is full - %s.\n"), 36111 unit, bcm_errmsg(rv))); 36112 if(egr_lm_counter_control_entry) { 36113 sal_free(egr_lm_counter_control_entry); 36114 } 36115 _BCM_OAM_UNLOCK(oc); 36116 return rv; 36117 } 36118 if(egr_lm_counter_control_entry) { 36119 sal_free(egr_lm_counter_control_entry); 36120 } 36121 36122 /* The ingress and egress profile index should match as they are identical tables 36123 * But if one of them is mistakenly written before calling this API, It will prohibit 36124 * different profile index for ingress and egress */ 36125 36126 if(egr_lm_profile_index != ing_lm_profile_index) { 36127 rv = BCM_E_INTERNAL; 36128 _BCM_OAM_UNLOCK(oc); 36129 return rv; 36130 } 36131 36132 *lm_count_profile = _BCM_ML_OAM_GET_LM_COUNTER_CONTROL_PROFILE_PTR_FROM_INDEX(ing_lm_profile_index); 36133 36134 _BCM_OAM_UNLOCK(oc); 36135 return rv; 36136 36137 } 36138 36139 /* 36140 * Function: 36141 * bcm_oam_opcodes_count_profile_set 36142 * Purpose: 36143 * Enable/disable counting for the opcodes in the opcodes_bitmap 36144 * in the profile pointed by lm_count_profile variable. 36145 * Parameters: 36146 * unit (IN) BCM device number 36147 * lm_count_profile (IN) OAM lm count profile index 36148 * count_enable (IN) Setting count enable (1) or disable (0) 36149 * opcodes_bitmap (IN) Opcode Bitmap for setting count for opcode packets 36150 * 36151 * Returns: 36152 * BCM_E_NONE No error 36153 * BCM_E_XXXX Error 36154 */ 36155 36156 int 36157 bcm_ml_oam_opcodes_count_profile_set( 36158 int unit, 36159 uint8 lm_count_profile, 36160 uint8 count_enable, 36161 bcm_oam_opcodes_t *opcodes_bitmap) 36162 { 36163 int rv = BCM_E_NONE; /* Operation return status. */ 36164 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 36165 void *entries[1]; 36166 int opcode_i; 36167 soc_profile_mem_t *profile_mem_ptr; 36168 ing_lm_counter_control_entry_t *ing_lm_counter_control_profile; 36169 egr_lm_counter_control_entry_t *egr_lm_counter_control_profile; 36170 36171 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 36172 36173 _BCM_OAM_LOCK(oc); 36174 36175 /* Setting ING_LM_COUNTER_CONTROL prpofile */ 36176 profile_mem_ptr = &oc->ing_lm_counter_control_profile; 36177 36178 ing_lm_counter_control_profile = sal_alloc(_BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 36179 "ING OAM LM count control profile"); 36180 if(!ing_lm_counter_control_profile) { 36181 _BCM_OAM_UNLOCK(oc); 36182 rv = BCM_E_MEMORY; 36183 return rv; 36184 } 36185 sal_memset(ing_lm_counter_control_profile, 0, 36186 _BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE); 36187 36188 entries[0] = ing_lm_counter_control_profile; 36189 36190 /* Get the profile with the given index to get the current status 36191 * of the profile in HW */ 36192 rv = soc_profile_mem_get(unit, profile_mem_ptr, 36193 _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile), 36194 _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE, (void *)entries); 36195 36196 if (BCM_FAILURE(rv)) { 36197 LOG_ERROR(BSL_LS_BCM_OAM, 36198 (BSL_META_U(unit, 36199 "OAM(unit %d) Error: ING OAM LM count control profile Get failed " 36200 " %s.\n"), unit, bcm_errmsg(rv))); 36201 if(ing_lm_counter_control_profile) { 36202 sal_free(ing_lm_counter_control_profile); 36203 } 36204 _BCM_OAM_UNLOCK(oc); 36205 return (rv); 36206 } 36207 36208 for(opcode_i = 0; opcode_i < _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE; 36209 opcode_i++) { 36210 /* Set the count_enable for the opcodes in the bitmap */ 36211 if(BCM_OAM_OPCODES_BITMAP_GET(*opcodes_bitmap,opcode_i)){ 36212 36213 soc_mem_field32_set(unit, ING_LM_COUNTER_CONTROLm, 36214 &ing_lm_counter_control_profile[opcode_i],COUNT_ENABLEf, count_enable); 36215 } 36216 } 36217 36218 rv = soc_profile_mem_set(unit, profile_mem_ptr, (void *) entries, 36219 _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile)); 36220 if (BCM_FAILURE(rv)) { 36221 LOG_ERROR(BSL_LS_BCM_OAM, 36222 (BSL_META_U(unit, 36223 "OAM(unit %d) ING OAM LM count control profile Set failed - %s.\n"), 36224 unit, bcm_errmsg(rv))); 36225 if(ing_lm_counter_control_profile) { 36226 sal_free(ing_lm_counter_control_profile); 36227 } 36228 _BCM_OAM_UNLOCK(oc); 36229 return rv; 36230 } 36231 36232 if(ing_lm_counter_control_profile) { 36233 sal_free(ing_lm_counter_control_profile); 36234 } 36235 36236 /* Setting EGR_LM_COUNTER_CONTROL prpofile */ 36237 profile_mem_ptr = &oc->egr_lm_counter_control_profile; 36238 36239 egr_lm_counter_control_profile = sal_alloc(_BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 36240 "EGR OAM LM count control profile"); 36241 if(!egr_lm_counter_control_profile) { 36242 _BCM_OAM_UNLOCK(oc); 36243 rv = BCM_E_MEMORY; 36244 return rv; 36245 } 36246 sal_memset(egr_lm_counter_control_profile, 0, 36247 _BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE); 36248 36249 entries[0] = egr_lm_counter_control_profile; 36250 36251 /* Get the profile with the given index to get the current status 36252 * of the profile in HW */ 36253 rv = soc_profile_mem_get(unit, profile_mem_ptr, 36254 _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile), 36255 _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE, (void *)entries); 36256 36257 if (BCM_FAILURE(rv)) { 36258 LOG_ERROR(BSL_LS_BCM_OAM, 36259 (BSL_META_U(unit, 36260 "OAM(unit %d) Error: EGR OAM LM count control profile Get failed " 36261 " %s.\n"), unit, bcm_errmsg(rv))); 36262 if(egr_lm_counter_control_profile) { 36263 sal_free(egr_lm_counter_control_profile); 36264 } 36265 _BCM_OAM_UNLOCK(oc); 36266 return (rv); 36267 } 36268 36269 for(opcode_i = 0; opcode_i < _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE; 36270 opcode_i++) { 36271 /* Set the count_enable for the opcodes in the bitmap */ 36272 if(BCM_OAM_OPCODES_BITMAP_GET(*opcodes_bitmap,opcode_i)){ 36273 36274 soc_mem_field32_set(unit, EGR_LM_COUNTER_CONTROLm, 36275 &egr_lm_counter_control_profile[opcode_i], COUNT_ENABLEf, count_enable); 36276 } 36277 } 36278 36279 rv = soc_profile_mem_set(unit, profile_mem_ptr, (void *)entries, 36280 _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile)); 36281 if (BCM_FAILURE(rv)) { 36282 LOG_ERROR(BSL_LS_BCM_OAM, 36283 (BSL_META_U(unit, 36284 "OAM(unit %d) ING OAM LM count control profile Set failed - %s.\n"), 36285 unit, bcm_errmsg(rv))); 36286 if(egr_lm_counter_control_profile) { 36287 sal_free(egr_lm_counter_control_profile); 36288 } 36289 _BCM_OAM_UNLOCK(oc); 36290 return rv; 36291 } 36292 36293 if(egr_lm_counter_control_profile) { 36294 sal_free(egr_lm_counter_control_profile); 36295 } 36296 36297 _BCM_OAM_UNLOCK(oc); 36298 return rv; 36299 } 36300 36301 /* 36302 * Function: 36303 * bcm_oam_opcodes_count_profile_get 36304 * Purpose: 36305 * Enable/disable counting for the opcodes in the opcodes_bitmap 36306 * in the profile pointed by lm_count_profile variable. 36307 * Parameters: 36308 * unit (IN) BCM device number 36309 * lm_count_profile (IN) OAM lm count profile index 36310 * count_enable (IN) Given count enable (1) or disable (0) 36311 * opcodes_bitmap (OUT) Opcode Bitmap for the given count_enable 36312 * information with the given lm_count_profile 36313 * 36314 * Returns: 36315 * BCM_E_NONE No error 36316 * BCM_E_XXXX Error 36317 */ 36318 int 36319 bcm_ml_oam_opcodes_count_profile_get( 36320 int unit, 36321 uint8 lm_count_profile, 36322 uint8 count_enable, 36323 bcm_oam_opcodes_t *opcodes_bitmap) 36324 { 36325 int rv = BCM_E_NONE; /* Operation return status. */ 36326 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 36327 void *entries[1]; 36328 int opcode_i; 36329 soc_profile_mem_t *profile_mem_ptr; 36330 ing_lm_counter_control_entry_t *ing_lm_counter_control_profile; 36331 egr_lm_counter_control_entry_t *egr_lm_counter_control_profile; 36332 uint8 count_enable_get; 36333 36334 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 36335 36336 _BCM_OAM_LOCK(oc); 36337 36338 /* Setting ING_LM_COUNTER_CONTROL prpofile */ 36339 profile_mem_ptr = &oc->ing_lm_counter_control_profile; 36340 36341 ing_lm_counter_control_profile = sal_alloc(_BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 36342 "ING OAM LM count control profile"); 36343 if(!ing_lm_counter_control_profile) { 36344 _BCM_OAM_UNLOCK(oc); 36345 rv = BCM_E_MEMORY; 36346 return rv; 36347 } 36348 sal_memset(ing_lm_counter_control_profile, 0, 36349 _BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE); 36350 36351 entries[0] = ing_lm_counter_control_profile; 36352 36353 /* Get the profile with the given index to get the current status 36354 * of the profile in HW */ 36355 rv = soc_profile_mem_get(unit, profile_mem_ptr, 36356 _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile), 36357 _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE, (void *)entries); 36358 36359 if (BCM_FAILURE(rv)) { 36360 LOG_ERROR(BSL_LS_BCM_OAM, 36361 (BSL_META_U(unit, 36362 "OAM(unit %d) Error: ING OAM LM count control profile Get failed " 36363 " %s.\n"), unit, bcm_errmsg(rv))); 36364 if(ing_lm_counter_control_profile) { 36365 sal_free(ing_lm_counter_control_profile); 36366 } 36367 _BCM_OAM_UNLOCK(oc); 36368 return (rv); 36369 } 36370 36371 /* Setting EGR_LM_COUNTER_CONTROL prpofile */ 36372 profile_mem_ptr = &oc->egr_lm_counter_control_profile; 36373 36374 egr_lm_counter_control_profile = sal_alloc(_BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 36375 "EGR OAM LM count control profile"); 36376 if(!egr_lm_counter_control_profile) { 36377 _BCM_OAM_UNLOCK(oc); 36378 rv = BCM_E_MEMORY; 36379 return rv; 36380 } 36381 sal_memset(egr_lm_counter_control_profile, 0, 36382 _BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE); 36383 36384 entries[0] = egr_lm_counter_control_profile; 36385 36386 /* Get the profile with the given index to get the current status 36387 * of the profile in HW */ 36388 rv = soc_profile_mem_get(unit, profile_mem_ptr, 36389 _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile), 36390 _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE, (void *)entries); 36391 36392 if (BCM_FAILURE(rv)) { 36393 LOG_ERROR(BSL_LS_BCM_OAM, 36394 (BSL_META_U(unit, 36395 "OAM(unit %d) Error: EGR OAM LM count control profile Get failed " 36396 " %s.\n"), unit, bcm_errmsg(rv))); 36397 if(ing_lm_counter_control_profile) { 36398 sal_free(ing_lm_counter_control_profile); 36399 } 36400 36401 if(egr_lm_counter_control_profile) { 36402 sal_free(egr_lm_counter_control_profile); 36403 } 36404 _BCM_OAM_UNLOCK(oc); 36405 return (rv); 36406 } 36407 36408 /* The prfoile entries for ingress and egress table should match */ 36409 if(sal_memcmp(ing_lm_counter_control_profile, egr_lm_counter_control_profile, 36410 _BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE)) { 36411 36412 rv = BCM_E_INTERNAL; 36413 _BCM_OAM_UNLOCK(oc); 36414 return (rv); 36415 } 36416 36417 for(opcode_i = 0; opcode_i < _BCM_ML_OAM_LM_COUNT_CONTROL_MAX_ENTRIES_PER_PROFILE; 36418 opcode_i++) { 36419 /* Set the count_enable for the opcodes in the bitmap */ 36420 count_enable_get = soc_mem_field32_get(unit, EGR_LM_COUNTER_CONTROLm, 36421 &egr_lm_counter_control_profile[opcode_i], COUNT_ENABLEf); 36422 36423 if(count_enable == count_enable_get) { 36424 BCM_OAM_OPCODES_BITMAP_SET(*opcodes_bitmap,opcode_i); 36425 } 36426 } 36427 36428 if(ing_lm_counter_control_profile) { 36429 sal_free(ing_lm_counter_control_profile); 36430 } 36431 36432 if(egr_lm_counter_control_profile) { 36433 sal_free(egr_lm_counter_control_profile); 36434 } 36435 _BCM_OAM_UNLOCK(oc); 36436 return rv; 36437 } 36438 36439 /* 36440 * Function: 36441 * bcm_ml_oam_opcodes_count_profile_delete 36442 * Purpose: 36443 * Delete the count profile with the id lm_count_profile 36444 * Parameters: 36445 * unit (IN) BCM device number 36446 * lm_count_profile (IN) Id of the lm_count_profile id that will be deleted 36447 * 36448 * Returns: 36449 * BCM_E_NONE No error 36450 * BCM_E_XXXX Error 36451 */ 36452 int 36453 bcm_ml_oam_opcodes_count_profile_delete( 36454 int unit, 36455 uint8 lm_count_profile) 36456 { 36457 int rv = BCM_E_NONE; /* Operation return status. */ 36458 _bcm_oam_control_t *oc; /* Pointer to OAM control structure. */ 36459 void *entries[1]; 36460 soc_profile_mem_t *profile_mem_ptr; 36461 ing_lm_counter_control_entry_t *ing_lm_counter_control_profile; 36462 egr_lm_counter_control_entry_t *egr_lm_counter_control_profile; 36463 36464 BCM_IF_ERROR_RETURN(_bcm_sb2_oam_control_get(unit, &oc)); 36465 36466 _BCM_OAM_LOCK(oc); 36467 36468 /* Setting ING_LM_COUNTER_CONTROL prpofile */ 36469 profile_mem_ptr = &oc->ing_lm_counter_control_profile; 36470 36471 ing_lm_counter_control_profile = sal_alloc(_BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 36472 "ING OAM LM count control profile"); 36473 if(!ing_lm_counter_control_profile) { 36474 _BCM_OAM_UNLOCK(oc); 36475 rv = BCM_E_MEMORY; 36476 return rv; 36477 } 36478 sal_memset(ing_lm_counter_control_profile, 0, 36479 _BCM_ML_ING_OAM_LM_COUNT_CONTROL_PROFILE_SIZE); 36480 36481 entries[0] = ing_lm_counter_control_profile; 36482 36483 rv = soc_profile_mem_set(unit, profile_mem_ptr, (void *) entries, 36484 _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile)); 36485 if (BCM_FAILURE(rv)) { 36486 LOG_ERROR(BSL_LS_BCM_OAM, 36487 (BSL_META_U(unit, 36488 "OAM(unit %d) ING OAM LM count control profile Get failed - %s.\n"), 36489 unit, bcm_errmsg(rv))); 36490 if(ing_lm_counter_control_profile) { 36491 sal_free(ing_lm_counter_control_profile); 36492 } 36493 _BCM_OAM_UNLOCK(oc); 36494 return rv; 36495 } 36496 36497 if(ing_lm_counter_control_profile) { 36498 sal_free(ing_lm_counter_control_profile); 36499 } 36500 36501 /* Setting EGR_LM_COUNTER_CONTROL prpofile */ 36502 profile_mem_ptr = &oc->egr_lm_counter_control_profile; 36503 36504 egr_lm_counter_control_profile = sal_alloc(_BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE, 36505 "EGR OAM LM count control profile"); 36506 if(!egr_lm_counter_control_profile) { 36507 _BCM_OAM_UNLOCK(oc); 36508 rv = BCM_E_MEMORY; 36509 return rv; 36510 } 36511 sal_memset(egr_lm_counter_control_profile, 0, 36512 _BCM_ML_EGR_OAM_LM_COUNT_CONTROL_PROFILE_SIZE); 36513 36514 entries[0] = egr_lm_counter_control_profile; 36515 36516 rv = soc_profile_mem_set(unit, profile_mem_ptr, (void *)entries, 36517 _BCM_ML_OAM_GET_FIRST_INDEX_FROM_LM_COUNTER_CONTROL_PROFILE_PTR(lm_count_profile)); 36518 if (BCM_FAILURE(rv)) { 36519 LOG_ERROR(BSL_LS_BCM_OAM, 36520 (BSL_META_U(unit, 36521 "OAM(unit %d) ING OAM LM count control profile Get failed - %s.\n"), 36522 unit, bcm_errmsg(rv))); 36523 if(egr_lm_counter_control_profile) { 36524 sal_free(egr_lm_counter_control_profile); 36525 } 36526 _BCM_OAM_UNLOCK(oc); 36527 return rv; 36528 } 36529 36530 if(egr_lm_counter_control_profile) { 36531 sal_free(egr_lm_counter_control_profile); 36532 } 36533 36534 _BCM_OAM_UNLOCK(oc); 36535 return rv; 36536 } 36537 #endif /* BCM_METROLITE_SUPPORT */ 36538 #endif /* BCM_SABER2_SUPPORT */