oam.c (299813B)
1 /* 2 * 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 */ 8 9 #include <shared/bsl.h> 10 11 #include <sal/core/libc.h> 12 #include <soc/defs.h> 13 #include <soc/drv.h> 14 #include <soc/scache.h> 15 #include <soc/profile_mem.h> 16 #include <soc/hash.h> 17 #include <soc/l3x.h> 18 #include <soc/enduro.h> 19 #if defined(BCM_KATANA_SUPPORT) 20 #include <soc/katana.h> 21 #endif /* BCM_KATANA_SUPPORT */ 22 23 #include <bcm/l3.h> 24 #include <bcm/oam.h> 25 26 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 27 #include <bcm_int/esw/bhh.h> 28 #include <bcm_int/esw/bhh_sdk_pack.h> 29 #include <soc/uc.h> 30 #endif /* BCM_KATANA_SUPPORT */ 31 32 #include <bcm_int/esw/oam.h> 33 #include <bcm_int/esw/port.h> 34 #include <bcm_int/esw/l3.h> 35 #include <bcm_int/esw/switch.h> 36 #include <bcm_int/esw/enduro.h> 37 #include <bcm_int/esw/virtual.h> 38 #include <bcm_int/esw_dispatch.h> 39 40 #if defined(BCM_ENDURO_SUPPORT) 41 42 #define BCM_OAM_LM_COUNTER_INDEX_INVALID (-1) 43 #define BCM_OAM_LM_COUNTER_OFFSET (8) 44 #define LEVEL_BIT_COUNT (3) 45 #define LEVEL_COUNT (1 << (LEVEL_BIT_COUNT)) 46 #define MAX_ENDPOINT_LEVEL (LEVEL_COUNT - 1) 47 #define MANGLED_GROUP_NAME_LENGTH (BCM_OAM_GROUP_NAME_LENGTH) 48 49 #define UNSUPPORTED_ENDPOINT_FLAGS \ 50 (BCM_OAM_ENDPOINT_CCM_COPYTOCPU | \ 51 BCM_OAM_ENDPOINT_CCM_DROP | \ 52 BCM_OAM_ENDPOINT_DM_COPYTOCPU | \ 53 BCM_OAM_ENDPOINT_DM_DROP | \ 54 BCM_OAM_ENDPOINT_LB_COPYTOCPU | \ 55 BCM_OAM_ENDPOINT_LB_DROP | \ 56 BCM_OAM_ENDPOINT_LT_COPYTOCPU | \ 57 BCM_OAM_ENDPOINT_LT_DROP | \ 58 BCM_OAM_ENDPOINT_USE_QOS_MAP | \ 59 BCM_OAM_ENDPOINT_MATCH_INNER_VLAN | \ 60 BCM_OAM_ENDPOINT_REMOTE_DEFECT_TX | \ 61 BCM_OAM_ENDPOINT_CCM_COPYFIRSTTOCPU | \ 62 BCM_OAM_ENDPOINT_PRI_TAG) 63 64 #define CHECK_INIT \ 65 if (!oam_info_p->initialized) \ 66 { \ 67 return BCM_E_INIT; \ 68 } 69 70 #define SET_OAM_INFO oam_info_p = &en_oam_info[unit]; 71 72 #define SET_GROUP(_group_index_) group_p = \ 73 oam_info_p->groups + _group_index_; 74 75 #define SET_ENDPOINT(_endpoint_index_) endpoint_p = \ 76 oam_info_p->endpoints + _endpoint_index_; 77 78 #define VALIDATE_GROUP_INDEX(_group_index_) \ 79 if ((_group_index_) < 0 || (_group_index_) >= oam_info_p->group_count) \ 80 { \ 81 return BCM_E_PARAM; \ 82 } \ 83 84 #define VALIDATE_ENDPOINT_INDEX(_endpoint_index_) \ 85 if ((_endpoint_index_) < 0 || \ 86 (_endpoint_index_) >= oam_info_p->endpoint_count) \ 87 { \ 88 return BCM_E_PARAM; \ 89 } \ 90 91 #define SET_LMEP_FIELD(unit, field, flag, mask) \ 92 if (soc_mem_field_valid(unit, L3_ENTRY_IPV4_UNICASTm, field)) { \ 93 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, field, \ 94 (flag & mask) ? 1 : 0); \ 95 } \ 96 97 #define GET_LMEP_FIELD(unit, field, flag) \ 98 if (soc_mem_field_valid(unit, L3_ENTRY_IPV4_UNICASTm, field)) { \ 99 if (soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, field)) { \ 100 endpoint_info->flags |= flag; \ 101 } \ 102 } 103 104 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 105 106 #define BCM_OAM_BHH_VALIDATE_END_POINT(oam_p, ep) \ 107 if(((ep) < (oam_info_p->remote_endpoint_count + \ 108 oam_info_p->local_tx_endpoint_count + \ 109 oam_info_p->local_rx_endpoint_count)) || \ 110 ((ep) >= oam_info_p->endpoint_count)) \ 111 { \ 112 return BCM_E_PARAM; \ 113 } 114 115 #define BCM_OAM_BHH_GET_UKERNEL_EP(oam_p, ep) \ 116 (ep - \ 117 (oam_p->remote_endpoint_count + \ 118 oam_p->local_tx_endpoint_count + \ 119 oam_p->local_rx_endpoint_count)) 120 121 #define BCM_OAM_BHH_GET_SDK_EP(oam_p, ep) \ 122 ((ep) + \ 123 (oam_p->remote_endpoint_count + \ 124 oam_p->local_tx_endpoint_count + \ 125 oam_p->local_rx_endpoint_count)) 126 /* 127 * Protos 128 */ 129 STATIC int _bcm_en_oam_bhh_hw_init(int unit); 130 STATIC int _bcm_en_oam_bhh_msg_send_receive(int unit, uint8 s_subclass, 131 uint16 s_len, uint32 s_data, 132 uint8 r_subclass, uint16 *r_len); 133 STATIC void _bcm_en_oam_bhh_callback_thread(void *param); 134 static int en_oam_mpls_tp_ach_channel_type = SHR_BHH_ACH_CHANNEL_TYPE; 135 136 #endif 137 138 /* Cache of ING_SERVICE_PRI_MAP Profile Table */ 139 static soc_profile_mem_t *ing_pri_map_profile[BCM_MAX_NUM_UNITS] = {NULL}; 140 #define ING_SERVICE_PRI_MAP_PROFILE_DEFAULT 0 141 142 #if defined(BCM_KATANA_SUPPORT) 143 /* Cache of OAM Opcode Profile Table */ 144 static soc_profile_mem_t *oam_opcode_profile[BCM_MAX_NUM_UNITS] = {NULL}; 145 #define OAM_OPCODE_PROFILE_DEFAULT 0 146 #endif /* BCM_KATANA_SUPPORT */ 147 148 #define SOC_MODID_BIT_POS(unit) _shr_popcount((unsigned int)SOC_PORT_ADDR_MAX(unit)) 149 #define SOC_MODID_MASK(unit) (SOC_INFO(unit).modid_max << SOC_MODID_BIT_POS(unit)) 150 151 static _bcm_oam_info_t en_oam_info[BCM_MAX_NUM_UNITS]; 152 static int _bcm_en_oam_quantize_ccm_period(int period); 153 154 static _bcm_oam_fault_t en_group_faults[] = 155 { 156 {CURRENT_XCON_CCM_DEFECTf, STICKY_XCON_CCM_DEFECTf, 157 BCM_OAM_GROUP_FAULT_CCM_XCON, 0x08}, 158 159 {CURRENT_ERROR_CCM_DEFECTf, STICKY_ERROR_CCM_DEFECTf, 160 BCM_OAM_GROUP_FAULT_CCM_ERROR, 0x04}, 161 162 {CURRENT_SOME_RMEP_CCM_DEFECTf, STICKY_SOME_RMEP_CCM_DEFECTf, 163 BCM_OAM_GROUP_FAULT_CCM_TIMEOUT, 0x02}, 164 165 {CURRENT_SOME_RDI_DEFECTf, STICKY_SOME_RDI_DEFECTf, 166 BCM_OAM_GROUP_FAULT_REMOTE, 0x01}, 167 168 {0, 0, 0, 0} 169 }; 170 171 static _bcm_oam_fault_t en_endpoint_faults[] = 172 { 173 {CURRENT_RMEP_PORT_STATUS_DEFECTf, STICKY_RMEP_PORT_STATUS_DEFECTf, 174 BCM_OAM_ENDPOINT_FAULT_PORT_DOWN, 0x08}, 175 176 {CURRENT_RMEP_INTERFACE_STATUS_DEFECTf, 177 STICKY_RMEP_INTERFACE_STATUS_DEFECTf, 178 BCM_OAM_ENDPOINT_FAULT_INTERFACE_DOWN, 0x04}, 179 180 {CURRENT_RMEP_CCM_DEFECTf, STICKY_RMEP_CCM_DEFECTf, 181 BCM_OAM_ENDPOINT_FAULT_CCM_TIMEOUT, 0x20}, 182 183 {CURRENT_RMEP_LAST_RDIf, STICKY_RMEP_LAST_RDIf, 184 BCM_OAM_ENDPOINT_FAULT_REMOTE, 0x10}, 185 186 {0, 0, 0, 0} 187 }; 188 189 typedef struct en_interrupt_enable_fields_s { 190 soc_field_t field; 191 uint32 value; 192 } en_interrupt_enable_fields_t; 193 194 #ifndef BCM_KATANA_SUPPORT 195 static _bcm_oam_interrupt_t en_interrupts[] = 196 { 197 {ANY_RMEP_TLV_PORT_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 198 ANY_RMEP_TLV_PORT_DOWN_INTRf, bcmOAMEventEndpointPortDown}, 199 200 {ANY_RMEP_TLV_PORT_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 201 ANY_RMEP_TLV_PORT_UP_INTRf, bcmOAMEventEndpointPortUp}, 202 203 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 204 ANY_RMEP_TLV_INTERFACE_DOWN_INTRf, bcmOAMEventEndpointInterfaceDown}, 205 206 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 207 ANY_RMEP_TLV_INTERFACE_UP_INTRf, bcmOAMEventEndpointInterfaceUp}, 208 209 {XCON_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf, 210 ERROR_CCM_DEFECT_INTRf, bcmOAMEventGroupCCMxcon}, 211 212 {ERROR_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf, 213 ERROR_CCM_DEFECT_INTRf, bcmOAMEventGroupCCMError}, 214 215 {SOME_RDI_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf, 216 SOME_RDI_DEFECT_INTRf, bcmOAMEventGroupRemote}, 217 218 {SOME_RMEP_CCM_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf, 219 SOME_RMEP_CCM_DEFECT_INTRf, bcmOAMEventGroupCCMTimeout}, 220 221 {INVALIDr, INVALIDf, 0} 222 }; 223 224 static en_interrupt_enable_fields_t en_interrupt_enable_fields[bcmOAMEventCount] = 225 { 226 /* This must be in the same order as the bcm_oam_event_type_t enum */ 227 { ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf, 1}, 228 { ANY_RMEP_TLV_PORT_UP_INT_ENABLEf, 1}, 229 { ANY_RMEP_TLV_INTERFACE_DOWN_INT_ENABLEf, 1}, 230 { ANY_RMEP_TLV_INTERFACE_UP_INT_ENABLEf, 1}, 231 { INVALIDf, 0}, 232 { INVALIDf, 0}, 233 { INVALIDf, 0}, 234 { INVALIDf, 0}, 235 { INVALIDf, 0}, 236 { INVALIDf, 0}, 237 { INVALIDf, 0}, 238 { INVALIDf, 0}, 239 { INVALIDf, 0}, 240 { INVALIDf, 0}, 241 { XCON_CCM_DEFECT_INT_ENABLEf, 1}, 242 { ERROR_CCM_DEFECT_INT_ENABLEf, 1}, 243 { SOME_RDI_DEFECT_INT_ENABLEf, 1}, 244 { SOME_RMEP_CCM_DEFECT_INT_ENABLEf, 1}, 245 { INVALIDf, 0} 246 }; 247 #else 248 249 static _bcm_oam_interrupt_t en_interrupts[] = 250 { 251 {ANY_RMEP_TLV_PORT_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 252 ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf, 253 bcmOAMEventEndpointPortDown}, 254 255 {ANY_RMEP_TLV_PORT_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 256 ANY_RMEP_TLV_PORT_UP_INT_ENABLEf, 257 bcmOAMEventEndpointPortUp}, 258 259 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 260 ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf, 261 bcmOAMEventEndpointInterfaceDown}, 262 263 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 264 ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf, 265 bcmOAMEventEndpointInterfaceUp}, 266 267 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 268 ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf, 269 bcmOAMEventEndpointInterfaceTestingToUp}, 270 271 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 272 ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf, 273 bcmOAMEventEndpointInterfaceUnknownToUp}, 274 275 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 276 ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf, 277 bcmOAMEventEndpointInterfaceDormantToUp}, 278 279 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 280 ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf, 281 bcmOAMEventEndpointInterfaceNotPresentToUp}, 282 283 {ANY_RMEP_TLV_INTERFACE_UP_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 284 ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf, 285 bcmOAMEventEndpointInterfaceLLDownToUp}, 286 287 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 288 ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf, 289 bcmOAMEventEndpointInterfaceTesting}, 290 291 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 292 ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf, 293 bcmOAMEventEndpointInterfaceUnkonwn}, 294 295 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 296 ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf, 297 bcmOAMEventEndpointInterfaceDormant}, 298 299 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 300 ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf, 301 bcmOAMEventEndpointInterfaceNotPresent}, 302 303 {ANY_RMEP_TLV_INTERFACE_DOWN_STATUSr, FIRST_RMEP_INDEXf, INVALIDf, 304 ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf, 305 bcmOAMEventEndpointInterfaceLLDown}, 306 307 {XCON_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf, 308 XCON_CCM_DEFECT_INT_ENABLEf, 309 bcmOAMEventGroupCCMxcon}, 310 311 {ERROR_CCM_DEFECT_STATUSr, INVALIDf, FIRST_MA_INDEXf, 312 ERROR_CCM_DEFECT_INT_ENABLEf, 313 bcmOAMEventGroupCCMError}, 314 315 {SOME_RDI_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf, 316 SOME_RDI_DEFECT_INT_ENABLEf, 317 bcmOAMEventGroupRemote}, 318 319 {SOME_RMEP_CCM_DEFECT_STATUSr, FIRST_RMEP_INDEXf, FIRST_MA_INDEXf, 320 SOME_RMEP_CCM_DEFECT_INT_ENABLEf, 321 bcmOAMEventGroupCCMTimeout}, 322 323 {INVALIDr, INVALIDf, 0} 324 }; 325 326 327 static en_interrupt_enable_fields_t en_interrupt_enable_fields[bcmOAMEventCount] = 328 { 329 /* This must be in the same order as the bcm_oam_event_type_t enum */ 330 { ANY_RMEP_TLV_PORT_DOWN_INT_ENABLEf, 1}, 331 { ANY_RMEP_TLV_PORT_UP_INT_ENABLEf, 1}, 332 { ANY_RMEP_TLV_INTERFACE_UP_TO_DOWN_TRANSITION_INT_ENABLEf, 1}, 333 { ANY_RMEP_TLV_INTERFACE_DOWN_TO_UP_TRANSITION_INT_ENABLEf, 1}, 334 { ANY_RMEP_TLV_INTERFACE_TESTING_TO_UP_TRANSITION_INT_ENABLEf, 1}, 335 { ANY_RMEP_TLV_INTERFACE_UNKNOWN_TO_UP_TRANSITION_INT_ENABLEf, 1}, 336 { ANY_RMEP_TLV_INTERFACE_DORMANT_TO_UP_TRANSITION_INT_ENABLEf, 1}, 337 { ANY_RMEP_TLV_INTERFACE_NOTPRESENT_TO_UP_TRANSITION_INT_ENABLEf, 1}, 338 { ANY_RMEP_TLV_INTERFACE_LLDOWN_TO_UP_TRANSITION_INT_ENABLEf, 1}, 339 { ANY_RMEP_TLV_INTERFACE_UP_TO_TESTING_TRANSITION_INT_ENABLEf, 1}, 340 { ANY_RMEP_TLV_INTERFACE_UP_TO_UNKNOWN_TRANSITION_INT_ENABLEf, 1}, 341 { ANY_RMEP_TLV_INTERFACE_UP_TO_DORMANT_TRANSITION_INT_ENABLEf, 1}, 342 { ANY_RMEP_TLV_INTERFACE_UP_TO_NOTPRESENT_TRANSITION_INT_ENABLEf, 1}, 343 { ANY_RMEP_TLV_INTERFACE_UP_TO_LLDOWN_TRANSITION_INT_ENABLEf, 1}, 344 { XCON_CCM_DEFECT_INT_ENABLEf, 1}, 345 { ERROR_CCM_DEFECT_INT_ENABLEf, 1}, 346 { SOME_RDI_DEFECT_INT_ENABLEf, 1}, 347 { SOME_RMEP_CCM_DEFECT_INT_ENABLEf, 1}, 348 { INVALIDf, 0} 349 }; 350 351 #endif 352 353 static uint32 en_ccm_periods[] = 354 { 355 BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED, 356 BCM_OAM_ENDPOINT_CCM_PERIOD_3MS, 357 BCM_OAM_ENDPOINT_CCM_PERIOD_10MS, 358 BCM_OAM_ENDPOINT_CCM_PERIOD_100MS, 359 BCM_OAM_ENDPOINT_CCM_PERIOD_1S, 360 BCM_OAM_ENDPOINT_CCM_PERIOD_10S, 361 BCM_OAM_ENDPOINT_CCM_PERIOD_1M, 362 BCM_OAM_ENDPOINT_CCM_PERIOD_10M, 363 _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED 364 }; 365 366 static void *_bcm_en_oam_alloc_clear(unsigned int size, char *description) 367 { 368 void *block_p; 369 370 block_p = sal_alloc(size, description); 371 372 if (block_p != NULL) 373 { 374 sal_memset(block_p, 0, size); 375 } 376 377 return block_p; 378 } 379 380 static int _bcm_en_oam_handle_interrupt(int unit, soc_field_t fault_field) 381 { 382 _bcm_oam_info_t *oam_info_p; 383 _bcm_oam_interrupt_t *interrupt_p; 384 uint32 interrupt_status; 385 bcm_oam_group_t group_index; 386 bcm_oam_endpoint_t endpoint_index; 387 _bcm_oam_event_handler_t *event_handler_p; 388 uint32 flags = 0; 389 390 SET_OAM_INFO; 391 392 CHECK_INIT; 393 394 BCM_IF_ERROR_RETURN(bcm_esw_oam_lock(unit)); 395 396 for (interrupt_p = en_interrupts; 397 interrupt_p->status_register != INVALIDr; 398 ++interrupt_p) 399 { 400 if (BCM_FAILURE(soc_reg32_get(unit, interrupt_p->status_register, 401 REG_PORT_ANY, 0, &interrupt_status))) { 402 continue; 403 } 404 405 if (!soc_reg_field_get(unit, interrupt_p->status_register, 406 interrupt_status, VALIDf)) 407 { 408 continue; 409 } 410 if (soc_reg_field_get(unit, interrupt_p->status_register, 411 interrupt_status, VALIDf) && 412 oam_info_p->event_handler_count[interrupt_p->event_type] > 0) 413 { 414 /* Reset callback flag for each interrupt */ 415 flags = 0; 416 group_index = (interrupt_p->group_index_field != INVALIDf) ? 417 (int)soc_reg_field_get(unit, interrupt_p->status_register, 418 interrupt_status, interrupt_p->group_index_field) : 419 BCM_OAM_GROUP_INVALID; 420 421 endpoint_index = (interrupt_p->endpoint_index_field != INVALIDf) ? 422 (int)soc_reg_field_get(unit, interrupt_p->status_register, 423 interrupt_status, interrupt_p->endpoint_index_field) : 424 BCM_OAM_ENDPOINT_INVALID; 425 426 if (endpoint_index != BCM_OAM_ENDPOINT_INVALID) 427 { 428 /* Find the logical endpoint for this RMEP */ 429 430 endpoint_index = oam_info_p->remote_endpoints[endpoint_index]; 431 } 432 433 flags |= soc_reg_field_get(unit, interrupt_p->status_register, 434 interrupt_status, MULTIf) ? BCM_OAM_EVENT_FLAGS_MULTIPLE : 0; 435 436 for (event_handler_p = oam_info_p->event_handler_list_p; 437 event_handler_p != NULL; 438 event_handler_p = event_handler_p->next_p) 439 { 440 if (SHR_BITGET(event_handler_p->event_types.w, 441 interrupt_p->event_type)) 442 { 443 event_handler_p->cb(unit, flags, interrupt_p->event_type, 444 group_index, endpoint_index, 445 event_handler_p->user_data); 446 } 447 } 448 } 449 450 /* Clear interrupt */ 451 if (BCM_FAILURE(soc_reg32_set(unit, interrupt_p->status_register, 452 REG_PORT_ANY, 0, 0))) { 453 continue; 454 } 455 } 456 457 return bcm_esw_oam_unlock(unit); 458 } 459 460 #ifdef BCM_WARM_BOOT_SUPPORT 461 462 #define BCM_WB_VERSION_1_0 SOC_SCACHE_VERSION(1,0) 463 #define BCM_WB_VERSION_1_1 SOC_SCACHE_VERSION(1,1) 464 #define BCM_WB_DEFAULT_VERSION BCM_WB_VERSION_1_1 465 466 #define BCM_OAM_WB_SCACHE_V1_REMOTE_EP_ID_OFFSET(_scache_, _remote_index_) \ 467 ((_scache_) + (_remote_index_) * sizeof(bcm_oam_endpoint_t)) 468 469 #define BCM_OAM_WB_SCACHE_V1_TX_EP_ID_OFFSET(_scache_, _tx_index_) \ 470 ((_scache_) + \ 471 ((oam_info_p->remote_endpoint_count + (_tx_index_)) * \ 472 sizeof(bcm_oam_endpoint_t))) 473 474 #define BCM_OAM_WB_SCACHE_V1_RX_EP_ID_OFFSET(_scache_, _rx_index_) \ 475 ((_scache_) + \ 476 ((oam_info_p->remote_endpoint_count + \ 477 oam_info_p->local_tx_endpoint_count + \ 478 (_rx_index_)) * sizeof(bcm_oam_endpoint_t))) 479 480 /* 481 * Function: 482 * bcm_en_oam_scache_alloc 483 * Purpose: 484 * Allocate memory for OAM module in scache 485 * Parameters: 486 * unit - (IN) Unit number. 487 * Returns: 488 * BCM_E_XXX 489 * Notes: 490 */ 491 STATIC int 492 bcm_en_oam_scache_alloc(int unit) 493 { 494 _bcm_oam_info_t *oam_info_p; 495 soc_scache_handle_t scache_handle; 496 uint8 *oam_scache; 497 int alloc_sz = 0; 498 499 SET_OAM_INFO; 500 alloc_sz = BCM_OAM_GROUP_NAME_LENGTH * (oam_info_p->group_count); 501 502 /* Number of oam groups */ 503 alloc_sz += sizeof(int); 504 505 /* VFP group, IFP VP group, IFP GLP group */ 506 alloc_sz += 3 * sizeof(bcm_field_group_t); 507 508 /* Endpoint id */ 509 alloc_sz += (oam_info_p->endpoint_count * sizeof(bcm_oam_endpoint_t)); 510 511 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 512 BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 1, 513 alloc_sz, &oam_scache, BCM_WB_DEFAULT_VERSION, NULL)); 514 return BCM_E_NONE; 515 } 516 517 static int _bcm_en_oam_warm_boot(int unit) 518 { 519 _bcm_oam_info_t *oam_info_p; 520 _bcm_oam_group_t *group_p; 521 int group_index; 522 maid_reduction_entry_t maid_reduction_entry; 523 ma_state_entry_t ma_state_entry; 524 int maid_reduction_valid; 525 int ma_state_valid; 526 _bcm_oam_endpoint_t *endpoint_p; 527 int l3_entry_count; 528 int l3_entry_index; 529 l3_entry_ipv4_unicast_entry_t l3_entry; 530 uint32 level_bitmap; 531 int level; 532 int lmep_index; 533 int stable_size; 534 int glp; 535 int port; 536 int epidx; 537 int group_count; 538 bcm_vlan_t vlan; 539 lmep_entry_t lmep_entry; 540 rmep_entry_t rmep_entry; 541 ma_index_entry_t ma_index_entry; 542 uint8 *oam_scache, *ptr; 543 soc_scache_handle_t scache_handle; 544 uint16 scache_version = 0; 545 int remote_index, local_rx_index; 546 int realloc_size = 0; 547 int rv = BCM_E_NONE; 548 549 SET_OAM_INFO; 550 551 /* Get groups */ 552 553 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 554 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) { 555 556 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 557 rv = _bcm_esw_scache_ptr_get(unit, scache_handle, 0, 0, 558 &oam_scache, BCM_WB_DEFAULT_VERSION, 559 &scache_version); 560 if (BCM_E_NOT_FOUND == rv) { 561 /* Upgrading from SDK release that does not have warmboot state */ 562 bcm_en_oam_scache_alloc(unit); 563 return BCM_E_NONE; 564 } else if (BCM_FAILURE(rv)) { 565 return rv; 566 } 567 568 /* Recover the FP groups */ 569 sal_memcpy(&oam_info_p->vfp_group, oam_scache, sizeof(bcm_field_group_t)); 570 oam_scache += sizeof(bcm_field_group_t); 571 sal_memcpy(&oam_info_p->fp_vp_group, oam_scache, sizeof(bcm_field_group_t)); 572 oam_scache += sizeof(bcm_field_group_t); 573 sal_memcpy(&oam_info_p->fp_glp_group, oam_scache, sizeof(bcm_field_group_t)); 574 oam_scache += sizeof(bcm_field_group_t); 575 576 /* Recover the OAM groups */ 577 sal_memcpy(&group_count, oam_scache, sizeof(int)); 578 oam_scache += sizeof(int); 579 } else { 580 return BCM_E_NONE; 581 } 582 583 for (group_index = 0; group_index < oam_info_p->group_count; 584 ++group_index) 585 { 586 SOC_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, 587 MEM_BLOCK_ANY, group_index, &maid_reduction_entry)); 588 589 SOC_IF_ERROR_RETURN(READ_MA_STATEm(unit, MEM_BLOCK_ANY, group_index, 590 &ma_state_entry)); 591 592 maid_reduction_valid = soc_MAID_REDUCTIONm_field32_get(unit, 593 &maid_reduction_entry, VALIDf); 594 595 ma_state_valid = soc_MA_STATEm_field32_get(unit, 596 &ma_state_entry, VALIDf); 597 598 if (maid_reduction_valid || ma_state_valid) 599 { 600 if (!maid_reduction_valid || !ma_state_valid) 601 { 602 return BCM_E_INTERNAL; 603 } 604 605 SET_GROUP(group_index); 606 607 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) { 608 /* Return zeros as the name */ 609 sal_memset(group_p->name, 0, BCM_OAM_GROUP_NAME_LENGTH); 610 } else { 611 /* Use stored values */ 612 /* 613 * COVERITY 614 * oam_scache has been initilized in _bcm_esw_scache_ptr_get 615 */ 616 /* coverity[uninit_use_in_call : FALSE] */ 617 memcpy(group_p->name, oam_scache, BCM_OAM_GROUP_NAME_LENGTH); 618 oam_scache += BCM_OAM_GROUP_NAME_LENGTH; 619 } 620 group_p->in_use = 1; 621 } 622 } 623 624 /* Get endpoints */ 625 epidx = -1; 626 l3_entry_count = soc_mem_index_count(unit, L3_ENTRY_IPV4_UNICASTm); 627 628 for (l3_entry_index = 0; l3_entry_index < l3_entry_count; ++l3_entry_index) 629 { 630 SOC_IF_ERROR_RETURN(READ_L3_ENTRY_IPV4_UNICASTm(unit, MEM_BLOCK_ANY, 631 l3_entry_index, &l3_entry)); 632 633 if (soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, VALIDf)) 634 { 635 switch (soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, KEY_TYPEf)) 636 { 637 case TR_L3_HASH_KEY_TYPE_RMEP: 638 remote_index = 639 soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, 640 RMEP__RMEP_PTRf); 641 642 if (scache_version >= BCM_WB_VERSION_1_1) { 643 ptr = BCM_OAM_WB_SCACHE_V1_REMOTE_EP_ID_OFFSET( 644 oam_scache, 645 remote_index); 646 sal_memcpy(&epidx, ptr, sizeof(bcm_oam_endpoint_t)); 647 } else { 648 epidx++; 649 } 650 SET_ENDPOINT(epidx); 651 652 endpoint_p->remote_index = remote_index; 653 SOC_IF_ERROR_RETURN(READ_RMEPm(unit, MEM_BLOCK_ANY, 654 endpoint_p->remote_index, &rmep_entry)); 655 656 if (!soc_RMEPm_field32_get(unit, &rmep_entry, VALIDf)) 657 { 658 return BCM_E_INTERNAL; 659 } 660 661 endpoint_p->in_use = 1; 662 endpoint_p->is_remote = 1; 663 664 endpoint_p->group_index = soc_RMEPm_field32_get(unit, 665 &rmep_entry, MAID_INDEXf); 666 667 endpoint_p->name = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 668 &l3_entry, RMEP__MEPIDf); 669 670 endpoint_p->level = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 671 &l3_entry, RMEP__MDLf); 672 673 endpoint_p->vlan = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 674 &l3_entry, RMEP__VIDf); 675 676 if (endpoint_p->vlan == 0) { 677 port = soc_L3_ENTRY_IPV4_UNICASTm_field32_get 678 (unit, &l3_entry, RMEP__SGLPf); 679 #if defined(INCLUDE_L3) 680 if (_bcm_vp_used_get(unit, port, _bcmVpTypeMim)) { 681 /* Associated with MIM VP */ 682 endpoint_p->vp = port; 683 } else 684 #endif /* INCLUDE_L3 */ 685 { 686 /* Associated with physical port */ 687 endpoint_p->glp = port; 688 } 689 } else { 690 endpoint_p->glp = soc_L3_ENTRY_IPV4_UNICASTm_field32_get 691 (unit, &l3_entry, RMEP__SGLPf); 692 } 693 694 SHR_BITSET(oam_info_p->remote_endpoints_in_use, 695 endpoint_p->remote_index); 696 oam_info_p->remote_endpoints[endpoint_p->remote_index] = 697 epidx; 698 699 break; 700 701 case TR_L3_HASH_KEY_TYPE_LMEP: 702 level_bitmap = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 703 &l3_entry, LMEP__MDL_BITMAPf); 704 705 for (level = 0; level < LEVEL_COUNT; ++level) 706 { 707 if (level_bitmap & (1 << level)) 708 { 709 /* There's an endpoint here at this level */ 710 local_rx_index = 711 soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 712 &l3_entry, LMEP__MA_BASE_PTRf) << 713 LEVEL_BIT_COUNT | level; 714 715 if (scache_version >= BCM_WB_VERSION_1_1) { 716 ptr = 717 BCM_OAM_WB_SCACHE_V1_RX_EP_ID_OFFSET( 718 oam_scache, 719 local_rx_index); 720 sal_memcpy(&epidx, ptr, 721 sizeof(bcm_oam_endpoint_t)); 722 } else { 723 epidx++; 724 } 725 SET_ENDPOINT(epidx); 726 727 endpoint_p->local_rx_index = local_rx_index; 728 SOC_IF_ERROR_RETURN(READ_MA_INDEXm(unit, 729 MEM_BLOCK_ANY, endpoint_p->local_rx_index, 730 &ma_index_entry)); 731 732 endpoint_p->in_use = 1; 733 endpoint_p->is_remote = 0; 734 endpoint_p->local_rx_enabled = 1; 735 736 endpoint_p->group_index = 737 soc_MA_INDEXm_field32_get(unit, 738 &ma_index_entry, MA_PTRf); 739 #if defined(BCM_KATANA_SUPPORT) 740 if (SOC_IS_KATANAX(unit)) { 741 endpoint_p->opcode_profile_index = 742 soc_MA_INDEXm_field32_get(unit, 743 &ma_index_entry, 744 OAM_OPCODE_CONTROL_PROFILE_PTRf); 745 746 /* Increment the reference count for the opcode_profile_count */ 747 rv = soc_profile_mem_reference(unit, oam_opcode_profile[unit], 748 endpoint_p->opcode_profile_index, 1); 749 if (BCM_FAILURE(rv)) { 750 LOG_ERROR(BSL_LS_BCM_OAM, 751 (BSL_META_U(unit, 752 "OAM Error: Opcode Profile entry recover failed " 753 "(EP=%d) - %s.\n"), epidx, bcm_errmsg(rv))); 754 return rv; 755 } 756 } 757 #endif /* BCM_KATANA_SUPPORT */ 758 /* Name is not used for receive-only endpoints */ 759 endpoint_p->name = 0xffff; 760 761 endpoint_p->level = level; 762 763 endpoint_p->vlan = 764 soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 765 &l3_entry, LMEP__VIDf); 766 767 if (endpoint_p->vlan == 0) { 768 endpoint_p->vp = 769 soc_L3_ENTRY_IPV4_UNICASTm_field32_get 770 (unit, &l3_entry, LMEP__SGLPf); 771 } else { 772 endpoint_p->glp = 773 soc_L3_ENTRY_IPV4_UNICASTm_field32_get 774 (unit, &l3_entry, LMEP__SGLPf); 775 } 776 777 SHR_BITSET(oam_info_p->local_rx_endpoints_in_use, 778 endpoint_p->local_rx_index); 779 780 } 781 } 782 783 break; 784 785 default: 786 continue; 787 } 788 } 789 } 790 791 SET_ENDPOINT(0); /* To avoid [-Werror=maybe-uninitialized] */ 792 for (lmep_index = 0; lmep_index < oam_info_p->local_tx_endpoint_count; 793 ++lmep_index) 794 { 795 SOC_IF_ERROR_RETURN(READ_LMEPm(unit, MEM_BLOCK_ANY, lmep_index, 796 &lmep_entry)); 797 798 group_index = soc_LMEPm_field32_get(unit, 799 &lmep_entry, MAID_INDEXf); 800 801 SOC_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, 802 MEM_BLOCK_ANY, group_index, &maid_reduction_entry)); 803 804 if (soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry, 805 VALIDf)) 806 { 807 glp = soc_LMEPm_field32_get(unit, &lmep_entry, DESTf); 808 vlan = soc_LMEPm_field32_get(unit, &lmep_entry, VLAN_IDf); 809 810 /* Check if a receive entry exists for this LMEP */ 811 if (scache_version >= BCM_WB_VERSION_1_1) { 812 ptr = BCM_OAM_WB_SCACHE_V1_TX_EP_ID_OFFSET(oam_scache, 813 lmep_index); 814 sal_memcpy(&epidx, ptr, sizeof(bcm_oam_endpoint_t)); 815 SET_ENDPOINT(epidx); 816 } else { 817 for (epidx = 0; epidx < oam_info_p->endpoint_count; epidx++) { 818 SET_ENDPOINT(epidx); 819 if (!endpoint_p->in_use) { 820 continue; 821 } 822 if ((endpoint_p->vlan == vlan) && (endpoint_p->glp == glp) && 823 (endpoint_p->name == 0xffff)) { 824 break; 825 } 826 } 827 if (epidx == oam_info_p->endpoint_count) { 828 /* Receive entry not found - local TX only */ 829 /* Allocate a new ID */ 830 for (epidx = 0; epidx < oam_info_p->endpoint_count; epidx++) { 831 SET_ENDPOINT(epidx); 832 if (!endpoint_p->in_use) { 833 break; 834 } 835 } 836 } 837 } 838 839 endpoint_p->glp = glp; 840 endpoint_p->vlan = vlan; 841 endpoint_p->in_use = 1; 842 endpoint_p->is_remote = 0; 843 endpoint_p->local_tx_enabled = 1; 844 endpoint_p->local_tx_index = lmep_index; 845 endpoint_p->name = soc_LMEPm_field32_get(unit, &lmep_entry, 846 MEPIDf); 847 endpoint_p->level = soc_LMEPm_field32_get(unit, &lmep_entry, 848 MDLf); 849 endpoint_p->group_index = group_index; 850 851 SHR_BITSET(oam_info_p->local_tx_endpoints_in_use, lmep_index); 852 } 853 } 854 855 if (scache_version >= BCM_WB_VERSION_1_1) { 856 oam_scache += (oam_info_p->endpoint_count * sizeof(bcm_oam_endpoint_t)); 857 } 858 859 if (!SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) && (stable_size > 0)) { 860 /* In BCM_WB_VERSION_1_1 onwards we allocate memory for storing EP 861 * indexes 862 */ 863 if (scache_version < BCM_WB_VERSION_1_1) { 864 realloc_size += (oam_info_p->endpoint_count * 865 sizeof(bcm_oam_endpoint_t)); 866 } 867 868 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 869 rv = soc_scache_realloc(unit, scache_handle, realloc_size); 870 if (SOC_FAILURE(rv)) { 871 LOG_ERROR(BSL_LS_BCM_OAM, 872 (BSL_META_U(unit,"OAM Error: scache alloc failed - %s.\n"), 873 bcm_errmsg(rv))); 874 return rv; 875 } 876 } 877 878 return BCM_E_NONE; 879 } 880 881 static int _bcm_en_oam_field_group_process(int unit, bcm_field_group_t group, 882 void *user_data) 883 { 884 _bcm_oam_info_t *oam_info_p; 885 _bcm_oam_endpoint_t *endpoint_p; 886 bcm_field_qset_t group_qset; 887 int glp, local_id, i, j, q, match, entry_size, entry_count, rv = BCM_E_NONE; 888 bcm_field_entry_t *entry_arr = NULL; 889 uint32 param0, param1; 890 bcm_gport_t gport_id; 891 bcm_module_t module_id, mod_mask; 892 bcm_port_t port_id, port_mask; 893 bcm_trunk_t trunk_id; 894 895 SET_OAM_INFO; 896 897 /* Get this group's QSET */ 898 BCM_IF_ERROR_RETURN(bcm_esw_field_group_get(unit, group, &group_qset)); 899 900 /* Check for the VFP QSET for a match */ 901 match = 1; 902 _FIELD_QSET_ITER(oam_info_p->vfp_qs, q) { 903 if (!BCM_FIELD_QSET_TEST(group_qset, bcmFieldQualifyStageLookup) || 904 !BCM_FIELD_QSET_TEST(group_qset, q)) { 905 match = 0; 906 break; 907 } 908 } 909 if (match && (oam_info_p->vfp_group == -1)) { 910 /* Get number of entries */ 911 rv = bcm_esw_field_entry_multi_get(unit, group, 0, NULL, &entry_count); 912 if (BCM_FAILURE(rv)) { 913 goto cleanup; 914 } 915 /* Get the actual entries - each entry belongs to an endpoint */ 916 entry_size = entry_count; 917 entry_arr = sal_alloc(entry_size * sizeof(bcm_field_entry_t), 918 "Entry array"); 919 if (entry_arr == NULL) { 920 rv = BCM_E_MEMORY; 921 goto cleanup; 922 } 923 rv = bcm_esw_field_entry_multi_get(unit, group, entry_size, entry_arr, 924 &entry_count); 925 if (BCM_FAILURE(rv)) { 926 goto cleanup; 927 } 928 for (i = 0; i < entry_count; i++) { 929 /* Check for bcmFieldActionIncomingMplsPortSet to find endpoint */ 930 rv = bcm_esw_field_action_get(unit, entry_arr[i], 931 bcmFieldActionIncomingMplsPortSet, 932 ¶m0, ¶m1); 933 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 934 goto cleanup; 935 } 936 if (BCM_SUCCESS(rv)) { 937 /* Find endpoint that matches this VP */ 938 for (j = 0; j < oam_info_p->endpoint_count; j++) { 939 endpoint_p = oam_info_p->endpoints + j; 940 if (!endpoint_p->in_use) { 941 continue; 942 } 943 if (endpoint_p->vp == param0) { 944 endpoint_p->vfp_entry = entry_arr[i]; 945 if (oam_info_p->vfp_group == -1) { 946 oam_info_p->vfp_group = group; 947 oam_info_p->vfp_entry_count = entry_count; 948 } 949 break; 950 } 951 } 952 } 953 if (rv == BCM_E_NOT_FOUND) { 954 /* The FP entry was not for an OAM endpoint */ 955 rv = BCM_E_NONE; 956 } 957 } 958 sal_free(entry_arr); 959 entry_arr = NULL; 960 } 961 962 /* Check for the IFP VP QSET for a match */ 963 match = 1; 964 _FIELD_QSET_ITER(oam_info_p->fp_vp_qs, q) { 965 if (!BCM_FIELD_QSET_TEST(group_qset, bcmFieldQualifyStageIngress) || 966 !BCM_FIELD_QSET_TEST(group_qset, q)) { 967 match = 0; 968 break; 969 } 970 } 971 if (match && (oam_info_p->fp_vp_group == -1)) { 972 /* Get number of entries */ 973 rv = bcm_esw_field_entry_multi_get(unit, group, 0, NULL, &entry_count); 974 if (BCM_FAILURE(rv)) { 975 goto cleanup; 976 } 977 /* Get the actual entries - each entry belongs to an endpoint */ 978 entry_size = entry_count; 979 entry_arr = sal_alloc(entry_size * sizeof(bcm_field_entry_t), 980 "Entry array"); 981 if (entry_arr == NULL) { 982 rv = BCM_E_MEMORY; 983 goto cleanup; 984 } 985 rv = bcm_esw_field_entry_multi_get(unit, group, entry_size, entry_arr, 986 &entry_count); 987 if (BCM_FAILURE(rv)) { 988 goto cleanup; 989 } 990 for (i = 0; i < entry_count; i++) { 991 /* Check for SrcMimGport to find endpoint */ 992 rv = bcm_esw_field_qualify_SrcMimGport_get(unit, entry_arr[i], 993 &gport_id); 994 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 995 goto cleanup; 996 } 997 if (BCM_SUCCESS(rv)) { 998 /* Find endpoint that matches this VP with possible actions */ 999 for (j = 0; j < oam_info_p->endpoint_count; j++) { 1000 endpoint_p = oam_info_p->endpoints + j; 1001 if (!endpoint_p->in_use) { 1002 continue; 1003 } 1004 if (endpoint_p->vp == BCM_GPORT_MIM_PORT_ID_GET(gport_id)) { 1005 if (oam_info_p->fp_vp_group == -1) { 1006 oam_info_p->fp_vp_group = group; 1007 oam_info_p->fp_vp_entry_count = entry_count; 1008 } 1009 endpoint_p->fp_entry_tx = entry_arr[i]; 1010 rv = bcm_esw_field_action_get(unit, entry_arr[i], 1011 bcmFieldActionOamLmBasePtr, 1012 ¶m0, ¶m1); 1013 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1014 goto cleanup; 1015 } 1016 if (rv != BCM_E_NOT_FOUND) { 1017 endpoint_p->lm_counter_index = param0; 1018 SHR_BITSET(oam_info_p->lm_counter_in_use, 1019 endpoint_p->lm_counter_index); 1020 } 1021 rv = bcm_esw_field_action_get(unit, entry_arr[i], 1022 bcmFieldActionOamServicePriMappingPtr, 1023 ¶m0, ¶m1); 1024 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1025 goto cleanup; 1026 } 1027 if (rv != BCM_E_NOT_FOUND) { 1028 endpoint_p->pri_map_index = param0; 1029 endpoint_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 1030 } 1031 rv = bcm_esw_field_action_get(unit, entry_arr[i], 1032 bcmFieldActionOamDmEnable, 1033 ¶m0, ¶m1); 1034 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1035 goto cleanup; 1036 } 1037 if (rv != BCM_E_NOT_FOUND) { 1038 if (param0 != 0) { 1039 endpoint_p->flags |= BCM_OAM_ENDPOINT_DELAY_MEASUREMENT; 1040 } 1041 } 1042 rv = bcm_esw_field_action_get(unit, entry_arr[i], 1043 bcmFieldActionOamUpMep, 1044 ¶m0, ¶m1); 1045 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1046 goto cleanup; 1047 } 1048 if (rv != BCM_E_NOT_FOUND) { 1049 if (param0 != 0) { 1050 endpoint_p->flags |= BCM_OAM_ENDPOINT_UP_FACING; 1051 } 1052 } 1053 break; 1054 } 1055 } 1056 } 1057 /* Check for DstMimGport to find endpoint */ 1058 rv = bcm_esw_field_qualify_DstMimGport_get(unit, entry_arr[i], 1059 &gport_id); 1060 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1061 goto cleanup; 1062 } 1063 if (BCM_SUCCESS(rv)) { 1064 /* Find endpoint that matches this VP */ 1065 for (j = 0; j < oam_info_p->endpoint_count; j++) { 1066 endpoint_p = oam_info_p->endpoints + j; 1067 if (!endpoint_p->in_use) { 1068 continue; 1069 } 1070 if (endpoint_p->vp == BCM_GPORT_MIM_PORT_ID_GET(gport_id)) { 1071 if (oam_info_p->fp_vp_group == -1) { 1072 oam_info_p->fp_vp_group = group; 1073 oam_info_p->fp_vp_entry_count = entry_count; 1074 } 1075 endpoint_p->fp_entry_rx = entry_arr[i]; 1076 rv = bcm_esw_field_action_get(unit, entry_arr[i], 1077 bcmFieldActionOamLmBasePtr, 1078 ¶m0, ¶m1); 1079 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1080 goto cleanup; 1081 } 1082 if (rv != BCM_E_NOT_FOUND) { 1083 endpoint_p->lm_counter_index = param0; 1084 SHR_BITSET(oam_info_p->lm_counter_in_use, 1085 endpoint_p->lm_counter_index); 1086 } 1087 rv = bcm_esw_field_action_get(unit, entry_arr[i], 1088 bcmFieldActionOamServicePriMappingPtr, 1089 ¶m0, ¶m1); 1090 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1091 goto cleanup; 1092 } 1093 if (rv != BCM_E_NOT_FOUND) { 1094 endpoint_p->pri_map_index = param0; 1095 } 1096 break; 1097 } 1098 } 1099 } 1100 if (rv == BCM_E_NOT_FOUND) { 1101 /* The FP entry was not for an OAM endpoint */ 1102 rv = BCM_E_NONE; 1103 } 1104 } 1105 sal_free(entry_arr); 1106 entry_arr = NULL; 1107 } 1108 1109 /* Check for the IFP GLP QSET for a match */ 1110 match = 1; 1111 _FIELD_QSET_ITER(oam_info_p->fp_glp_qs, q) { 1112 if (!BCM_FIELD_QSET_TEST(group_qset, bcmFieldQualifyStageIngress) || 1113 !BCM_FIELD_QSET_TEST(group_qset, q)) { 1114 match = 0; 1115 break; 1116 } 1117 } 1118 if (match && (oam_info_p->fp_glp_group == -1)) { 1119 /* Get number of entries */ 1120 rv = bcm_esw_field_entry_multi_get(unit, group, 0, NULL, &entry_count); 1121 if (BCM_FAILURE(rv)) { 1122 goto cleanup; 1123 } 1124 /* Get the actual entries - each entry belongs to an endpoint */ 1125 entry_size = entry_count; 1126 entry_arr = sal_alloc(entry_size * sizeof(bcm_field_entry_t), 1127 "Entry array"); 1128 if (entry_arr == NULL) { 1129 rv = BCM_E_MEMORY; 1130 goto cleanup; 1131 } 1132 rv = bcm_esw_field_entry_multi_get(unit, group, entry_size, entry_arr, 1133 &entry_count); 1134 if (BCM_FAILURE(rv)) { 1135 goto cleanup; 1136 } 1137 for (i = 0; i < entry_count; i++) { 1138 /* Check for SrcPort to find endpoint */ 1139 rv = bcm_esw_field_qualify_SrcPort_get(unit, entry_arr[i], 1140 &module_id, &mod_mask, 1141 &port_id, &port_mask); 1142 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1143 goto cleanup; 1144 } 1145 if (BCM_SUCCESS(rv)) { 1146 if (BCM_GPORT_IS_SET(port_id)) { 1147 rv = _bcm_esw_gport_resolve(unit, port_id, 1148 &module_id, &port_id, &trunk_id, &local_id); 1149 if (BCM_FAILURE(rv)) { 1150 goto cleanup; 1151 } 1152 } 1153 glp = (module_id << SOC_MODID_BIT_POS(unit)) | port_id; 1154 /* Find endpoint that matches this GLP with possible actions */ 1155 for (j = 0; j < oam_info_p->endpoint_count; j++) { 1156 endpoint_p = oam_info_p->endpoints + j; 1157 if (!endpoint_p->in_use) { 1158 continue; 1159 } 1160 if (endpoint_p->glp == glp) { 1161 if (oam_info_p->fp_glp_group == -1) { 1162 oam_info_p->fp_glp_group = group; 1163 oam_info_p->fp_glp_entry_count = entry_count; 1164 } 1165 endpoint_p->fp_entry_tx = entry_arr[i]; 1166 rv = bcm_esw_field_action_get(unit, entry_arr[i], 1167 bcmFieldActionOamLmBasePtr, 1168 ¶m0, ¶m1); 1169 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1170 goto cleanup; 1171 } 1172 if (rv != BCM_E_NOT_FOUND) { 1173 endpoint_p->lm_counter_index = param0; 1174 SHR_BITSET(oam_info_p->lm_counter_in_use, 1175 endpoint_p->lm_counter_index); 1176 } 1177 rv = bcm_esw_field_action_get(unit, entry_arr[i], 1178 bcmFieldActionOamServicePriMappingPtr, 1179 ¶m0, ¶m1); 1180 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1181 goto cleanup; 1182 } 1183 if (rv != BCM_E_NOT_FOUND) { 1184 endpoint_p->pri_map_index = param0; 1185 endpoint_p->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 1186 } 1187 rv = bcm_esw_field_action_get(unit, entry_arr[i], 1188 bcmFieldActionOamDmEnable, 1189 ¶m0, ¶m1); 1190 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1191 goto cleanup; 1192 } 1193 if (rv != BCM_E_NOT_FOUND) { 1194 if (param0 != 0) { 1195 endpoint_p->flags |= BCM_OAM_ENDPOINT_DELAY_MEASUREMENT; 1196 } 1197 } 1198 rv = bcm_esw_field_action_get(unit, entry_arr[i], 1199 bcmFieldActionOamUpMep, 1200 ¶m0, ¶m1); 1201 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1202 goto cleanup; 1203 } 1204 if (rv != BCM_E_NOT_FOUND) { 1205 if (param0 != 0) { 1206 endpoint_p->flags |= BCM_OAM_ENDPOINT_UP_FACING; 1207 } 1208 } 1209 break; 1210 } 1211 } 1212 } 1213 /* Check for DstPort to find endpoint */ 1214 rv = bcm_esw_field_qualify_DstPort_get(unit, entry_arr[i], 1215 &module_id, &mod_mask, 1216 &port_id, &port_mask); 1217 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1218 goto cleanup; 1219 } 1220 if (BCM_SUCCESS(rv)) { 1221 if (BCM_GPORT_IS_SET(port_id)) { 1222 rv = _bcm_esw_gport_resolve(unit, port_id, 1223 &module_id, &port_id, &trunk_id, &local_id); 1224 if (BCM_FAILURE(rv)) { 1225 goto cleanup; 1226 } 1227 } 1228 glp = (module_id << SOC_MODID_BIT_POS(unit)) | port_id; 1229 /* Find endpoint that matches this GLP */ 1230 for (j = 0; j < oam_info_p->endpoint_count; j++) { 1231 endpoint_p = oam_info_p->endpoints + j; 1232 if (!endpoint_p->in_use) { 1233 continue; 1234 } 1235 if (endpoint_p->glp == glp) { 1236 if (oam_info_p->fp_glp_group == -1) { 1237 oam_info_p->fp_glp_group = group; 1238 oam_info_p->fp_glp_entry_count = entry_count; 1239 } 1240 endpoint_p->fp_entry_rx = entry_arr[i]; 1241 rv = bcm_esw_field_action_get(unit, entry_arr[i], 1242 bcmFieldActionOamLmBasePtr, 1243 ¶m0, ¶m1); 1244 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1245 goto cleanup; 1246 } 1247 if (rv != BCM_E_NOT_FOUND) { 1248 endpoint_p->lm_counter_index = param0; 1249 SHR_BITSET(oam_info_p->lm_counter_in_use, 1250 endpoint_p->lm_counter_index); 1251 } 1252 rv = bcm_esw_field_action_get(unit, entry_arr[i], 1253 bcmFieldActionOamServicePriMappingPtr, 1254 ¶m0, ¶m1); 1255 if (BCM_FAILURE(rv) && (rv != BCM_E_NOT_FOUND)) { 1256 goto cleanup; 1257 } 1258 if (rv != BCM_E_NOT_FOUND) { 1259 endpoint_p->pri_map_index = param0; 1260 } 1261 break; 1262 } 1263 } 1264 } 1265 if (rv == BCM_E_NOT_FOUND) { 1266 /* The FP entry was not for an OAM endpoint */ 1267 rv = BCM_E_NONE; 1268 } 1269 } 1270 sal_free(entry_arr); 1271 entry_arr = NULL; 1272 } 1273 1274 cleanup: 1275 if (entry_arr != NULL) { 1276 sal_free(entry_arr); 1277 } 1278 return rv; 1279 } 1280 #endif /* BCM_WARM_BOOT_SUPPORT */ 1281 1282 static void _bcm_en_oam_uninstall_vfp(int unit, _bcm_oam_endpoint_t *endpoint_p) 1283 { 1284 _bcm_oam_info_t *oam_info_p; 1285 1286 SET_OAM_INFO; 1287 1288 if (endpoint_p->vfp_entry != 0) { 1289 (void)bcm_esw_field_entry_destroy(unit, endpoint_p->vfp_entry); 1290 oam_info_p->vfp_entry_count--; 1291 if (oam_info_p->vfp_entry_count == 0) { 1292 (void)bcm_esw_field_group_destroy(unit, oam_info_p->vfp_group); 1293 oam_info_p->vfp_group = 0; 1294 } 1295 endpoint_p->vfp_entry = 0; 1296 } 1297 } 1298 1299 static void _bcm_en_oam_uninstall_fp(int unit, _bcm_oam_endpoint_t *endpoint_p) 1300 { 1301 int i; 1302 _bcm_oam_info_t *oam_info_p; 1303 1304 SET_OAM_INFO; 1305 1306 if (endpoint_p->fp_entry_tx != 0) { 1307 (void)bcm_esw_field_entry_destroy(unit, endpoint_p->fp_entry_tx); 1308 } 1309 if (endpoint_p->fp_entry_rx != 0) { 1310 (void)bcm_esw_field_entry_destroy(unit, endpoint_p->fp_entry_rx); 1311 } 1312 if (endpoint_p->vp != 0) { 1313 if (endpoint_p->fp_entry_tx != 0) { 1314 oam_info_p->fp_vp_entry_count--; 1315 1316 if (oam_info_p->fp_vp_entry_count == 0) { 1317 (void)bcm_esw_field_group_destroy(unit, oam_info_p->fp_vp_group); 1318 oam_info_p->fp_vp_group = 0; 1319 } 1320 } 1321 endpoint_p->vp = 0; 1322 } else { 1323 for (i = 0; i < BCM_SWITCH_TRUNK_MAX_PORTCNT; i++) { 1324 if (endpoint_p->fp_entry_trunk[i]) { 1325 (void)bcm_esw_field_entry_destroy(unit, endpoint_p->fp_entry_trunk[i]); 1326 endpoint_p->fp_entry_trunk[i] = 0; 1327 } 1328 } 1329 if ((endpoint_p->fp_entry_tx != 0) || (endpoint_p->fp_entry_rx != 0)) { 1330 oam_info_p->fp_glp_entry_count--; 1331 1332 if (oam_info_p->fp_glp_entry_count == 0) { 1333 (void)bcm_esw_field_group_destroy(unit, oam_info_p->fp_glp_group); 1334 oam_info_p->fp_glp_group = 0; 1335 } 1336 } 1337 } 1338 1339 endpoint_p->fp_entry_tx = 0; 1340 endpoint_p->fp_entry_rx = 0; 1341 } 1342 1343 static int _bcm_en_oam_install_vfp(int unit, int endpoint_index, 1344 bcm_oam_endpoint_info_t *endpoint_info) 1345 { 1346 _bcm_oam_info_t *oam_info_p; 1347 _bcm_oam_endpoint_t *endpoint_p; 1348 bcm_gport_t port_id; 1349 bcm_mac_t mac_ones = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 1350 1351 SET_OAM_INFO; 1352 SET_ENDPOINT(endpoint_index); 1353 1354 if (oam_info_p->vfp_group == 0) { 1355 /* Create group first */ 1356 BCM_IF_ERROR_RETURN(bcm_esw_field_group_create(unit, 1357 oam_info_p->vfp_qs, 1358 BCM_FIELD_GROUP_PRIO_ANY, 1359 &oam_info_p->vfp_group)); 1360 } 1361 BCM_IF_ERROR_RETURN 1362 (bcm_esw_field_entry_create(unit, 1363 oam_info_p->vfp_group, 1364 &endpoint_p->vfp_entry)); 1365 1366 BCM_IF_ERROR_RETURN 1367 (bcm_esw_field_qualify_DstMac(unit, endpoint_p->vfp_entry, 1368 endpoint_info->src_mac_address, mac_ones)); 1369 1370 BCM_IF_ERROR_RETURN 1371 (bcm_esw_field_qualify_SrcMac(unit, endpoint_p->vfp_entry, 1372 endpoint_info->dst_mac_address, mac_ones)); 1373 1374 BCM_IF_ERROR_RETURN 1375 (bcm_esw_field_qualify_OuterVlanId(unit, endpoint_p->vfp_entry, 1376 endpoint_info->vlan, 0x0fff)); 1377 1378 BCM_GPORT_MPLS_PORT_ID_SET(port_id, endpoint_p->vp); 1379 1380 BCM_IF_ERROR_RETURN 1381 (bcm_esw_field_action_add(unit, endpoint_p->vfp_entry, 1382 bcmFieldActionIncomingMplsPortSet, 1383 port_id, 0)); 1384 1385 BCM_IF_ERROR_RETURN 1386 (bcm_esw_field_action_add(unit, endpoint_p->vfp_entry, 1387 bcmFieldActionOamPbbteLookupEnable, 1388 1, 0)); 1389 oam_info_p->vfp_entry_count++; 1390 1391 #ifdef BCM_WARM_BOOT_SUPPORT 1392 SOC_CONTROL_LOCK(unit); 1393 SOC_CONTROL(unit)->scache_dirty = 1; 1394 SOC_CONTROL_UNLOCK(unit); 1395 #endif 1396 1397 return BCM_E_NONE; 1398 } 1399 1400 /* 1401 * Function: 1402 * _bcm_en_oam_trunk_install_fp 1403 * Purpose: 1404 * Install fp entries for each port in the trunk for LM/DM higig packets sent 1405 * from CPU to hit and perform OAM operations. This is necessary because 1406 * there is no trunk information in higig header. 1407 * Parameters: 1408 * unit - (IN) Unit number. 1409 * add_mdl - (IN) Whether to install mdl as key. 1410 * endpoint_info - (IN) Pointer to an OAM endpoint structure 1411 * Returns: 1412 * BCM_E_XXX 1413 * Notes: 1414 */ 1415 static 1416 int _bcm_en_oam_trunk_install_fp(int unit, int add_mdl, _bcm_oam_endpoint_t *endpoint_p) 1417 { 1418 int rv = BCM_E_NONE; 1419 _bcm_oam_info_t *oam_info_p; 1420 bcm_field_group_t group; 1421 bcm_gport_t gport; 1422 bcm_ip6_t data, mask; 1423 int i, j; 1424 int member_count; 1425 bcm_trunk_member_t *member_array = NULL; 1426 1427 SET_OAM_INFO; 1428 1429 group = oam_info_p->fp_glp_group; 1430 1431 BCM_IF_ERROR_RETURN 1432 (bcm_esw_trunk_get(unit, endpoint_p->glp & 0x7F, NULL, 1433 0, NULL, &member_count)); 1434 1435 if (member_count > 0) { 1436 member_array = sal_alloc(sizeof(bcm_trunk_member_t) * member_count, 1437 "trunk member array"); 1438 if (NULL == member_array) { 1439 return BCM_E_MEMORY; 1440 } 1441 rv = bcm_esw_trunk_get(unit, endpoint_p->glp & 0x7F, NULL, 1442 member_count, member_array, &member_count); 1443 if (BCM_FAILURE(rv)) { 1444 sal_free(member_array); 1445 return rv; 1446 } 1447 } 1448 1449 for (i = 0; i < member_count; i++) { 1450 1451 rv = bcm_esw_field_entry_create(unit, group, 1452 &endpoint_p->fp_entry_trunk[i]); 1453 if (BCM_FAILURE(rv)) { 1454 sal_free(member_array); 1455 return rv; 1456 } 1457 1458 gport = member_array[i].gport; 1459 1460 if (endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING) { 1461 rv = bcm_esw_field_qualify_SrcPort(unit, endpoint_p->fp_entry_trunk[i], 1462 0, 0x3f, gport, BCM_FIELD_EXACT_MATCH_MASK); 1463 } else { 1464 rv = bcm_esw_field_qualify_DstPort(unit, endpoint_p->fp_entry_trunk[i], 1465 0, 0x3f, gport, BCM_FIELD_EXACT_MATCH_MASK); 1466 } 1467 if (BCM_FAILURE(rv)) { 1468 sal_free(member_array); 1469 return rv; 1470 } 1471 1472 rv = bcm_esw_field_qualify_OuterVlanId(unit, endpoint_p->fp_entry_trunk[i], 1473 endpoint_p->vlan, 0xfff); 1474 if (BCM_FAILURE(rv)) { 1475 sal_free(member_array); 1476 return rv; 1477 } 1478 1479 if ((add_mdl != 0) && (endpoint_p->vp == 0)) 1480 { 1481 /* 1482 * Add ethertype and MDL(with DstIp6) for smaller MDL on the same 1483 * (Port, VLAN) to trap LM packets to CPU. 1484 */ 1485 for (j = 0; j < 16; j++) { 1486 data[j] = mask[j] = 0; 1487 } 1488 data[0] = (endpoint_p->level << 5); 1489 mask[0] = 0xE0; 1490 1491 rv = bcm_esw_field_qualify_DstIp6(unit, endpoint_p->fp_entry_trunk[i], 1492 data, mask); 1493 if (BCM_FAILURE(rv)) { 1494 sal_free(member_array); 1495 return rv; 1496 } 1497 1498 rv = bcm_esw_field_qualify_EtherType(unit, endpoint_p->fp_entry_trunk[i], 1499 0x8902, 0xffff); 1500 if (BCM_FAILURE(rv)) { 1501 sal_free(member_array); 1502 return rv; 1503 } 1504 } 1505 1506 rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i], 1507 bcmFieldActionOamLmepEnable, 1508 1, 0); 1509 if (BCM_FAILURE(rv)) { 1510 sal_free(member_array); 1511 return rv; 1512 } 1513 1514 rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i], 1515 bcmFieldActionOamLmEnable, 1516 endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT? 1:0, 0); 1517 if (BCM_FAILURE(rv)) { 1518 sal_free(member_array); 1519 return rv; 1520 } 1521 1522 rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i], 1523 bcmFieldActionOamDmEnable, 1524 endpoint_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT? 1:0, 0); 1525 if (BCM_FAILURE(rv)) { 1526 sal_free(member_array); 1527 return rv; 1528 } 1529 1530 rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i], 1531 bcmFieldActionOamLmepMdl, 1532 endpoint_p->level, 0); 1533 if (BCM_FAILURE(rv)) { 1534 sal_free(member_array); 1535 return rv; 1536 } 1537 1538 rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i], 1539 bcmFieldActionOamUpMep, 1540 endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING? 1:0, 0); 1541 if (BCM_FAILURE(rv)) { 1542 sal_free(member_array); 1543 return rv; 1544 } 1545 1546 if (endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) 1547 { 1548 /* Assign LM counter and priority mapping table */ 1549 rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i], 1550 bcmFieldActionOamLmBasePtr, 1551 endpoint_p->lm_counter_index, 0); 1552 if (BCM_FAILURE(rv)) { 1553 sal_free(member_array); 1554 return rv; 1555 } 1556 1557 rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i], 1558 bcmFieldActionOamServicePriMappingPtr, 1559 endpoint_p->pri_map_index, 0); 1560 if (BCM_FAILURE(rv)) { 1561 sal_free(member_array); 1562 return rv; 1563 } 1564 } 1565 1566 rv = bcm_esw_field_action_add(unit, endpoint_p->fp_entry_trunk[i], 1567 bcmFieldActionOamTx, 1, 0); 1568 if (BCM_FAILURE(rv)) { 1569 sal_free(member_array); 1570 return rv; 1571 } 1572 } 1573 1574 if (NULL != member_array) { 1575 sal_free(member_array); 1576 } 1577 return rv; 1578 } 1579 1580 static 1581 int _bcm_en_oam_install_fp(int unit, int add_mdl, _bcm_oam_endpoint_t *endpoint_p) 1582 { 1583 _bcm_oam_info_t *oam_info_p; 1584 bcm_field_group_t group; 1585 bcm_gport_t gport; 1586 bcm_ip6_t data, mask; 1587 bcm_module_t module_id; 1588 bcm_port_t port_id; 1589 int i, mep_on_trunk = 0, skip_entry_rx = 0; 1590 1591 SET_OAM_INFO; 1592 1593 if ((endpoint_p->vp != 0) && (oam_info_p->fp_vp_group == 0)) { 1594 /* Create group first */ 1595 BCM_IF_ERROR_RETURN(bcm_esw_field_group_create(unit, 1596 oam_info_p->fp_vp_qs, 1597 BCM_FIELD_GROUP_PRIO_ANY, 1598 &oam_info_p->fp_vp_group)); 1599 } 1600 1601 if ((endpoint_p->vp == 0) && (oam_info_p->fp_glp_group == 0)) { 1602 /* Create group first */ 1603 BCM_IF_ERROR_RETURN(bcm_esw_field_group_create(unit, 1604 oam_info_p->fp_glp_qs, 1605 BCM_FIELD_GROUP_PRIO_ANY, 1606 &oam_info_p->fp_glp_group)); 1607 } 1608 1609 if (endpoint_p->vp) { 1610 group = oam_info_p->fp_vp_group; 1611 } else { 1612 group = oam_info_p->fp_glp_group; 1613 } 1614 1615 if (endpoint_p->glp & (1 << SOC_TRUNK_BIT_POS(unit))) { 1616 mep_on_trunk = 1; 1617 } 1618 1619 if ((mep_on_trunk != 0) && 1620 (endpoint_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) && 1621 !(endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) && 1622 !(endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING)) { 1623 /* 1624 * Skip the entry to match DM packets sent from CPU for down meps that are 1625 * created on trunk and only support delay measurement. Create entry for 1626 * each port in the trunk instead. This is only applied to DM down meps. 1627 * The entry is always required for LM MEP to record packet counts. 1628 */ 1629 skip_entry_rx = 1; 1630 } 1631 1632 BCM_IF_ERROR_RETURN 1633 (bcm_esw_field_entry_create(unit, 1634 group, 1635 &endpoint_p->fp_entry_tx)); 1636 1637 if (0 == skip_entry_rx) { 1638 BCM_IF_ERROR_RETURN 1639 (bcm_esw_field_entry_create(unit, 1640 group, 1641 &endpoint_p->fp_entry_rx)); 1642 } 1643 1644 if (endpoint_p->vp != 0) { 1645 BCM_GPORT_MIM_PORT_ID_SET(gport, endpoint_p->vp); 1646 1647 BCM_IF_ERROR_RETURN 1648 (bcm_esw_field_qualify_SrcMimGport(unit, endpoint_p->fp_entry_tx, 1649 gport)); 1650 BCM_IF_ERROR_RETURN 1651 (bcm_esw_field_qualify_DstMimGport(unit, endpoint_p->fp_entry_rx, 1652 gport)); 1653 } else { 1654 if (mep_on_trunk != 0) { 1655 /* Trunk */ 1656 BCM_GPORT_TRUNK_SET(gport, endpoint_p->glp & 0x7F); 1657 BCM_IF_ERROR_RETURN 1658 (bcm_esw_field_qualify_SrcTrunk(unit, endpoint_p->fp_entry_tx, 1659 gport, BCM_FIELD_EXACT_MATCH_MASK)); 1660 1661 if (!skip_entry_rx) { 1662 BCM_IF_ERROR_RETURN 1663 (bcm_esw_field_qualify_DstTrunk(unit, endpoint_p->fp_entry_rx, 1664 gport, BCM_FIELD_EXACT_MATCH_MASK)); 1665 } 1666 } else { 1667 module_id = (endpoint_p->glp & SOC_MODID_MASK(unit)) >> SOC_MODID_BIT_POS(unit); 1668 port_id = (endpoint_p->glp & SOC_PORT_ADDR_MAX(unit)); 1669 1670 if (module_id != 0) { 1671 /* Modport */ 1672 BCM_GPORT_MODPORT_SET(gport, module_id, port_id); 1673 } else { 1674 /* Local port */ 1675 BCM_IF_ERROR_RETURN(bcm_esw_port_gport_get(unit, port_id, &gport)); 1676 } 1677 BCM_IF_ERROR_RETURN 1678 (bcm_esw_field_qualify_SrcPort(unit, endpoint_p->fp_entry_tx, 1679 0, 0x3f, gport, BCM_FIELD_EXACT_MATCH_MASK)); 1680 BCM_IF_ERROR_RETURN 1681 (bcm_esw_field_qualify_DstPort(unit, endpoint_p->fp_entry_rx, 1682 0, 0x3f, gport, BCM_FIELD_EXACT_MATCH_MASK)); 1683 } 1684 1685 BCM_IF_ERROR_RETURN 1686 (bcm_esw_field_qualify_OuterVlanId(unit, endpoint_p->fp_entry_tx, 1687 endpoint_p->vlan, 0xfff)); 1688 1689 if (0 == skip_entry_rx) { 1690 BCM_IF_ERROR_RETURN 1691 (bcm_esw_field_qualify_OuterVlanId(unit, endpoint_p->fp_entry_rx, 1692 endpoint_p->vlan, 0xfff)); 1693 } 1694 } 1695 1696 if ((add_mdl != 0) && (endpoint_p->vp == 0)) 1697 { 1698 /* 1699 * Add ethertype and MDL(with DstIp6) for smaller MDL on the same 1700 * (Port, VLAN) to trap LM packets to CPU. 1701 */ 1702 for (i = 0; i < 16; i++) { 1703 data[i] = mask[i] = 0; 1704 } 1705 data[0] = (endpoint_p->level << 5); 1706 mask[0] = 0xE0; 1707 1708 BCM_IF_ERROR_RETURN 1709 (bcm_esw_field_qualify_DstIp6(unit, endpoint_p->fp_entry_tx, 1710 data, mask)); 1711 BCM_IF_ERROR_RETURN 1712 (bcm_esw_field_qualify_EtherType(unit, endpoint_p->fp_entry_tx, 1713 0x8902, 0xffff)); 1714 1715 if (0 == skip_entry_rx) { 1716 BCM_IF_ERROR_RETURN 1717 (bcm_esw_field_qualify_DstIp6(unit, endpoint_p->fp_entry_rx, 1718 data, mask)); 1719 BCM_IF_ERROR_RETURN 1720 (bcm_esw_field_qualify_EtherType(unit, endpoint_p->fp_entry_rx, 1721 0x8902, 0xffff)); 1722 } 1723 } 1724 1725 BCM_IF_ERROR_RETURN 1726 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx, 1727 bcmFieldActionOamLmepEnable, 1728 1, 0)); 1729 BCM_IF_ERROR_RETURN 1730 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx, 1731 bcmFieldActionOamLmEnable, 1732 endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT? 1:0, 0)); 1733 1734 BCM_IF_ERROR_RETURN 1735 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx, 1736 bcmFieldActionOamDmEnable, 1737 endpoint_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT? 1:0, 0)); 1738 1739 BCM_IF_ERROR_RETURN 1740 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx, 1741 bcmFieldActionOamLmepMdl, 1742 endpoint_p->level, 0)); 1743 1744 BCM_IF_ERROR_RETURN 1745 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx, 1746 bcmFieldActionOamUpMep, 1747 endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING? 1:0, 0)); 1748 1749 if (endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) 1750 { 1751 /* Assign LM counter and priority mapping table */ 1752 BCM_IF_ERROR_RETURN 1753 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx, 1754 bcmFieldActionOamLmBasePtr, 1755 endpoint_p->lm_counter_index, 0)); 1756 1757 BCM_IF_ERROR_RETURN 1758 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx, 1759 bcmFieldActionOamServicePriMappingPtr, 1760 endpoint_p->pri_map_index, 0)); 1761 } 1762 1763 BCM_IF_ERROR_RETURN 1764 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_tx, 1765 bcmFieldActionOamTx, 1766 endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING ? 1:0, 0)); 1767 1768 if (0 == skip_entry_rx) { 1769 1770 BCM_IF_ERROR_RETURN 1771 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx, 1772 bcmFieldActionOamLmepEnable, 1773 1, 0)); 1774 BCM_IF_ERROR_RETURN 1775 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx, 1776 bcmFieldActionOamLmEnable, 1777 endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT? 1:0, 0)); 1778 BCM_IF_ERROR_RETURN 1779 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx, 1780 bcmFieldActionOamDmEnable, 1781 endpoint_p->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT? 1:0, 0)); 1782 1783 BCM_IF_ERROR_RETURN 1784 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx, 1785 bcmFieldActionOamLmepMdl, 1786 endpoint_p->level, 0)); 1787 BCM_IF_ERROR_RETURN 1788 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx, 1789 bcmFieldActionOamUpMep, 1790 endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING? 1:0, 0)); 1791 1792 if (endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) 1793 { 1794 /* Allocate LM counter and priority mapping table */ 1795 BCM_IF_ERROR_RETURN 1796 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx, 1797 bcmFieldActionOamLmBasePtr, 1798 endpoint_p->lm_counter_index, 0)); 1799 BCM_IF_ERROR_RETURN 1800 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx, 1801 bcmFieldActionOamServicePriMappingPtr, 1802 endpoint_p->pri_map_index, 0)); 1803 } 1804 1805 BCM_IF_ERROR_RETURN 1806 (bcm_esw_field_action_add(unit, endpoint_p->fp_entry_rx, 1807 bcmFieldActionOamTx, 1808 endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING ? 0:1, 0)); 1809 1810 } /* if (0 == skip_entry_rx) */ 1811 1812 if (endpoint_p->vp != 0) { 1813 oam_info_p->fp_vp_entry_count++; 1814 } else { 1815 oam_info_p->fp_glp_entry_count++; 1816 } 1817 1818 if ((mep_on_trunk != 0) && 1819 !(endpoint_p->flags & BCM_OAM_ENDPOINT_UP_FACING)) { 1820 /* Create fp entry for each port in the trunk for down mep only. */ 1821 BCM_IF_ERROR_RETURN 1822 (_bcm_en_oam_trunk_install_fp(unit, add_mdl, endpoint_p)); 1823 } 1824 1825 #ifdef BCM_WARM_BOOT_SUPPORT 1826 SOC_CONTROL_LOCK(unit); 1827 SOC_CONTROL(unit)->scache_dirty = 1; 1828 SOC_CONTROL_UNLOCK(unit); 1829 #endif 1830 1831 return BCM_E_NONE; 1832 } 1833 1834 static void _bcm_en_oam_free_memory(int unit, _bcm_oam_info_t *oam_info_p) 1835 { 1836 if (NULL != oam_info_p->remote_endpoints) { 1837 sal_free(oam_info_p->remote_endpoints); 1838 oam_info_p->remote_endpoints = NULL; 1839 } 1840 1841 if (NULL != oam_info_p->remote_endpoints_in_use) { 1842 sal_free(oam_info_p->remote_endpoints_in_use); 1843 oam_info_p->remote_endpoints_in_use = NULL; 1844 } 1845 1846 if (NULL != oam_info_p->local_rx_endpoints_in_use) { 1847 sal_free(oam_info_p->local_rx_endpoints_in_use); 1848 oam_info_p->local_rx_endpoints_in_use = NULL; 1849 } 1850 1851 if (NULL != oam_info_p->local_tx_endpoints_in_use) { 1852 sal_free(oam_info_p->local_tx_endpoints_in_use); 1853 oam_info_p->local_tx_endpoints_in_use = NULL; 1854 } 1855 1856 if (NULL != oam_info_p->lm_counter_in_use) { 1857 sal_free(oam_info_p->lm_counter_in_use); 1858 oam_info_p->lm_counter_in_use = NULL; 1859 } 1860 1861 if (NULL != oam_info_p->endpoints) { 1862 sal_free(oam_info_p->endpoints); 1863 oam_info_p->endpoints = NULL; 1864 } 1865 1866 if (NULL != oam_info_p->groups) { 1867 sal_free(oam_info_p->groups); 1868 oam_info_p->groups = NULL; 1869 } 1870 1871 if (ing_pri_map_profile[unit]) { 1872 sal_free(ing_pri_map_profile[unit]); 1873 ing_pri_map_profile[unit] = NULL; 1874 } 1875 1876 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 1877 if (SOC_IS_KATANAX(unit)) { 1878 if (NULL != oam_info_p->dma_buffer){ 1879 soc_cm_sfree(oam_info_p->unit, oam_info_p->dma_buffer); 1880 oam_info_p->dma_buffer = NULL; 1881 } 1882 if (NULL != oam_info_p->dmabuf_reply){ 1883 soc_cm_sfree(oam_info_p->unit, oam_info_p->dmabuf_reply); 1884 oam_info_p->dmabuf_reply = NULL; 1885 } 1886 } 1887 #endif 1888 1889 #if defined(BCM_KATANA_SUPPORT) 1890 if (SOC_IS_KATANAX(unit)) { 1891 sal_free(oam_opcode_profile[unit]); 1892 oam_opcode_profile[unit] = NULL; 1893 } 1894 #endif /* BCM_KATANA_SUPPORT */ 1895 1896 } 1897 1898 static void _bcm_en_oam_event_unregister_all(_bcm_oam_info_t *oam_info_p) 1899 { 1900 _bcm_oam_event_handler_t *event_handler_p; 1901 _bcm_oam_event_handler_t *event_handler_to_delete_p; 1902 1903 event_handler_p = oam_info_p->event_handler_list_p; 1904 1905 while (event_handler_p != NULL) 1906 { 1907 event_handler_to_delete_p = event_handler_p; 1908 event_handler_p = event_handler_p->next_p; 1909 1910 sal_free(event_handler_to_delete_p); 1911 } 1912 oam_info_p->event_handler_list_p = NULL; 1913 } 1914 1915 /* 1916 * Function: 1917 * bcm_en_oam_init 1918 * Purpose: 1919 * Initialize the OAM subsystem 1920 * Parameters: 1921 * unit - (IN) Unit number. 1922 * Returns: 1923 * BCM_E_XXX 1924 * Notes: 1925 */ 1926 int 1927 bcm_en_oam_init( 1928 int unit) 1929 { 1930 _bcm_oam_info_t *oam_info_p; 1931 bcm_oam_endpoint_t endpoint_index; 1932 bcm_port_t port_index; 1933 uint32 register_value, temp_index; 1934 soc_mem_t mem; 1935 int entry_words; 1936 uint32 mem_entries[BCM_OAM_INTPRI_MAX]; 1937 void *entries[1]; 1938 int result, i; 1939 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 1940 int uc; 1941 uint8 carrier_code[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; 1942 char *carrier_code_str; 1943 uint32 node_id = 0; 1944 bhh_sdk_msg_ctrl_init_t msg_init; 1945 uint8 *buffer, *buffer_ptr; 1946 uint16 buffer_len, reply_len; 1947 int priority; 1948 int ukernel_not_ready = 0; 1949 uint8 bhh_consolidate_final_event = 0; 1950 int status; 1951 #endif 1952 1953 SET_OAM_INFO; 1954 1955 if (oam_info_p->initialized) 1956 { 1957 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 1958 } 1959 1960 if (soc_feature(unit, soc_feature_bhh)) { 1961 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 1962 if (SOC_IS_KATANAX(unit)) { 1963 /* 1964 * Initialize uController side 1965 */ 1966 1967 /* 1968 * Start BHH application in BTE (Broadcom Task Engine) uController, 1969 * if not already running (warm boot). 1970 * Determine which uController is running BHH by choosing the first 1971 * uC that returns successfully. 1972 */ 1973 for (uc = 0; uc < SOC_INFO(unit).num_ucs; uc++) { 1974 result = soc_uc_status(unit, uc, &status); 1975 if ((result == SOC_E_NONE) && (status != 0)) { 1976 result = soc_cmic_uc_appl_init(unit, uc, MOS_MSG_CLASS_BHH, 1977 _BHH_UC_MSG_TIMEOUT_USECS, 1978 BHH_SDK_VERSION, 1979 BHH_UC_MIN_VERSION, 1980 _bcm_oam_bhh_appl_callback, 1981 NULL); 1982 if (SOC_E_NONE == result) { 1983 /* BHH started successfully */ 1984 oam_info_p->uc_num = uc; 1985 break; 1986 } 1987 } 1988 } 1989 1990 if (uc >= SOC_INFO(unit).num_ucs) { /* Could not find or start BHH appl */ 1991 ukernel_not_ready = 1; 1992 LOG_ERROR(BSL_LS_BCM_OAM, 1993 (BSL_META_U(unit, 1994 "uKernel Not Ready, bhh not started\n"))); 1995 } 1996 } 1997 #endif 1998 } 1999 2000 2001 oam_info_p->group_count = soc_mem_index_count(unit, MA_STATEm); 2002 2003 oam_info_p->groups = 2004 _bcm_en_oam_alloc_clear(oam_info_p->group_count * 2005 sizeof(_bcm_oam_group_t), "_bcm_oam_group"); 2006 2007 if (oam_info_p->groups == NULL) 2008 { 2009 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2010 return BCM_E_MEMORY; 2011 } 2012 2013 oam_info_p->remote_endpoint_count = soc_mem_index_count(unit, RMEPm); 2014 oam_info_p->local_tx_endpoint_count = soc_mem_index_count(unit, LMEPm); 2015 2016 oam_info_p->local_rx_endpoint_count = 2017 soc_mem_index_count(unit, MA_INDEXm); 2018 2019 oam_info_p->endpoint_count = oam_info_p->remote_endpoint_count + 2020 oam_info_p->local_tx_endpoint_count + oam_info_p->local_rx_endpoint_count; 2021 2022 if (soc_feature(unit, soc_feature_bhh)) { 2023 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 2024 oam_info_p->unit = unit; 2025 2026 oam_info_p->ukernel_not_ready = ukernel_not_ready; 2027 /* Get SOC properties for BHH */ 2028 oam_info_p->bhh_endpoint_count = 2029 soc_property_get(unit, spn_BHH_NUM_SESSIONS, 256); 2030 2031 oam_info_p->bhh_max_encap_length = 2032 soc_property_get(unit, 2033 spn_BHH_ENCAP_MAX_LENGTH, 2034 _BCM_OAM_BHH_DEFAULT_ENCAP_LENGTH); 2035 2036 if(oam_info_p->bhh_max_encap_length > _BCM_OAM_BHH_MAX_ENCAP_LENGTH) { 2037 LOG_ERROR(BSL_LS_BCM_OAM, 2038 (BSL_META_U(unit, 2039 "Invalid max encap_length=%u\n"), 2040 oam_info_p->bhh_max_encap_length)); 2041 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2042 return BCM_E_CONFIG; 2043 } 2044 carrier_code_str = 2045 soc_property_get_str(unit, spn_BHH_CARRIER_CODE); 2046 if (carrier_code_str != NULL) { 2047 /* 2048 * Note that the carrier code is specified in colon separated 2049 * MAC address format. 2050 */ 2051 if (_shr_parse_macaddr(carrier_code_str, carrier_code) < 0) { 2052 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2053 return BCM_E_INTERNAL; 2054 } 2055 } 2056 2057 node_id = 2058 soc_property_get(unit, spn_BHH_NODE_ID, 0); 2059 bhh_consolidate_final_event = soc_property_get(unit, 2060 spn_BHH_CONSOLIDATED_FINAL_EVENT, 0); 2061 oam_info_p->endpoint_count += oam_info_p->bhh_endpoint_count; 2062 #endif 2063 } 2064 2065 oam_info_p->endpoints = 2066 _bcm_en_oam_alloc_clear(oam_info_p->endpoint_count * 2067 sizeof(_bcm_oam_endpoint_t), "_bcm_oam_endpoint"); 2068 2069 if (oam_info_p->endpoints == NULL) 2070 { 2071 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2072 return BCM_E_MEMORY; 2073 } 2074 2075 oam_info_p->local_tx_endpoints_in_use = 2076 _bcm_en_oam_alloc_clear(SHR_BITALLOCSIZE(oam_info_p->local_tx_endpoint_count), 2077 "local_tx_endpoints_in_use"); 2078 2079 if (oam_info_p->local_tx_endpoints_in_use == NULL) 2080 { 2081 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2082 return BCM_E_MEMORY; 2083 } 2084 2085 /* 2086 * Both TX and RX for one MEP 2087 */ 2088 oam_info_p->lm_counter_count = 2089 soc_mem_index_count(unit, OAM_LM_COUNTERSm) / 2; 2090 2091 oam_info_p->lm_counter_in_use = 2092 _bcm_en_oam_alloc_clear(SHR_BITALLOCSIZE(oam_info_p->lm_counter_count), 2093 "lm_counter_in_use"); 2094 2095 if (oam_info_p->lm_counter_in_use == NULL) 2096 { 2097 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2098 return BCM_E_MEMORY; 2099 } 2100 2101 oam_info_p->local_rx_endpoints_in_use = 2102 _bcm_en_oam_alloc_clear(SHR_BITALLOCSIZE(oam_info_p->local_rx_endpoint_count), 2103 "local_rx_endpoints_in_use"); 2104 2105 if (oam_info_p->local_rx_endpoints_in_use == NULL) 2106 { 2107 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2108 return BCM_E_MEMORY; 2109 } 2110 2111 for (endpoint_index = 0; endpoint_index < oam_info_p->endpoint_count; 2112 ++endpoint_index) 2113 { 2114 oam_info_p->endpoints[endpoint_index].lm_counter_index = 2115 BCM_OAM_LM_COUNTER_INDEX_INVALID; 2116 } 2117 2118 oam_info_p->remote_endpoints_in_use = 2119 _bcm_en_oam_alloc_clear(SHR_BITALLOCSIZE(oam_info_p->remote_endpoint_count), 2120 "remote_endpoints_in_use"); 2121 2122 if (oam_info_p->remote_endpoints_in_use == NULL) 2123 { 2124 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2125 return BCM_E_MEMORY; 2126 } 2127 2128 oam_info_p->remote_endpoints = 2129 sal_alloc(oam_info_p->remote_endpoint_count * sizeof(bcm_oam_endpoint_t), 2130 "rmep reverse lookup"); 2131 2132 if (oam_info_p->remote_endpoints == NULL) 2133 { 2134 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2135 return BCM_E_MEMORY; 2136 } 2137 2138 for (endpoint_index = 0; endpoint_index < oam_info_p->remote_endpoint_count; 2139 ++endpoint_index) 2140 { 2141 oam_info_p->remote_endpoints[endpoint_index] = BCM_OAM_ENDPOINT_INVALID; 2142 } 2143 #ifdef BCM_KATANA_SUPPORT 2144 if (SOC_IS_KATANA(unit)) { 2145 soc_kt_oam_handler_register(unit, _bcm_en_oam_handle_interrupt); 2146 } else 2147 #endif /* BCM_KATANA_SUPPORT */ 2148 { 2149 soc_enduro_oam_handler_register(unit, _bcm_en_oam_handle_interrupt); 2150 } 2151 #ifdef BCM_KATANA_SUPPORT 2152 if (SOC_IS_KATANAX(unit)) { 2153 /* Initialize the OAM_OPCODE_PROFILE table */ 2154 if (oam_opcode_profile[unit] == NULL) { 2155 oam_opcode_profile[unit] = 2156 sal_alloc(sizeof(soc_profile_mem_t), "OAM Opcode profile Mem"); 2157 if (oam_opcode_profile[unit] == NULL) { 2158 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2159 return BCM_E_MEMORY; 2160 } 2161 soc_profile_mem_t_init(oam_opcode_profile[unit]); 2162 } 2163 2164 /* Create profile table cache (or re-init if it already exists) */ 2165 mem = OAM_OPCODE_CONTROL_PROFILEm; 2166 entry_words = sizeof(oam_opcode_control_profile_entry_t) / sizeof(uint32); 2167 result = soc_profile_mem_create(unit, &mem, &entry_words, 2168 1, oam_opcode_profile[unit]); 2169 if (SOC_FAILURE(result)) { 2170 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2171 return result; 2172 } 2173 } 2174 #endif /* BCM_KATANA_SUPPORT */ 2175 2176 #ifdef BCM_WARM_BOOT_SUPPORT 2177 if (!SOC_WARM_BOOT(unit)) { 2178 bcm_en_oam_scache_alloc(unit); 2179 } 2180 if (SOC_WARM_BOOT(unit)) 2181 { 2182 _bcm_en_oam_warm_boot(unit); 2183 } 2184 else 2185 #endif /* BCM_WARM_BOOT_SUPPORT */ 2186 { 2187 /* Enable OAM message reception on all ports */ 2188 PBMP_ALL_ITER(unit, port_index) 2189 { 2190 result = bcm_esw_port_control_set(unit, port_index, 2191 bcmPortControlOAMEnable, 1); 2192 if (BCM_FAILURE(result)) 2193 { 2194 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2195 return result; 2196 } 2197 } 2198 2199 /* Enable CCM reception timeouts */ 2200 register_value = 0; 2201 2202 soc_reg_field_set(unit, OAM_TIMER_CONTROLr, ®ister_value, 2203 TIMER_ENABLEf, 1); 2204 2205 soc_reg_field_set(unit, OAM_TIMER_CONTROLr, ®ister_value, 2206 CLK_GRANf, 1); 2207 2208 result = WRITE_OAM_TIMER_CONTROLr(unit, register_value); 2209 if (SOC_FAILURE(result)) 2210 { 2211 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2212 return result; 2213 } 2214 2215 if (!SOC_IS_KATANA(unit)) 2216 { 2217 /* Common information for outgoing CCM packets */ 2218 result = WRITE_LMEP_COMMON_1r(unit, _BCM_OAM_MAC_DA_UPPER_32); 2219 if (SOC_FAILURE(result)) 2220 { 2221 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2222 return result; 2223 } 2224 } 2225 2226 /* Enable CCM transmission */ 2227 register_value = 0; 2228 2229 soc_reg_field_set(unit, OAM_TX_CONTROLr, ®ister_value, 2230 TX_ENABLEf, 1); 2231 soc_reg_field_set(unit, OAM_TX_CONTROLr, ®ister_value, 2232 CMIC_BUF_ENABLEf, 1); 2233 2234 result = WRITE_OAM_TX_CONTROLr(unit, register_value); 2235 if (SOC_FAILURE(result)) 2236 { 2237 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2238 return result; 2239 } 2240 2241 register_value = 0; 2242 soc_reg_field_set(unit, LMEP_COMMON_2r, ®ister_value, 2243 DA_15_3f, _BCM_OAM_MAC_DA_LOWER_13 >> 3); 2244 soc_reg_field_set(unit, LMEP_COMMON_2r, ®ister_value, 2245 L3f, 1); 2246 2247 result = WRITE_LMEP_COMMON_2r(unit, register_value); 2248 if (SOC_FAILURE(result)) 2249 { 2250 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2251 return result; 2252 } 2253 } 2254 2255 oam_info_p->vfp_entry_count = 0; 2256 2257 BCM_FIELD_QSET_INIT(oam_info_p->vfp_qs); 2258 BCM_FIELD_QSET_ADD(oam_info_p->vfp_qs, bcmFieldQualifyDstMac); 2259 BCM_FIELD_QSET_ADD(oam_info_p->vfp_qs, bcmFieldQualifySrcMac); 2260 BCM_FIELD_QSET_ADD(oam_info_p->vfp_qs, bcmFieldQualifyOuterVlanId); 2261 BCM_FIELD_QSET_ADD(oam_info_p->vfp_qs, bcmFieldQualifyStageLookup); 2262 2263 oam_info_p->fp_vp_entry_count = 0; 2264 oam_info_p->fp_glp_entry_count = 0; 2265 2266 BCM_FIELD_QSET_INIT(oam_info_p->fp_vp_qs); 2267 BCM_FIELD_QSET_ADD(oam_info_p->fp_vp_qs, bcmFieldQualifyOuterVlanId); 2268 BCM_FIELD_QSET_ADD(oam_info_p->fp_vp_qs, bcmFieldQualifyDstMimGport); 2269 BCM_FIELD_QSET_ADD(oam_info_p->fp_vp_qs, bcmFieldQualifySrcMimGport); 2270 BCM_FIELD_QSET_ADD(oam_info_p->fp_vp_qs, bcmFieldQualifyStageIngress); 2271 2272 BCM_FIELD_QSET_INIT(oam_info_p->fp_glp_qs); 2273 BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifyOuterVlanId); 2274 BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifyDstPort); 2275 BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifyDstTrunk); 2276 BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifySrcPort); 2277 BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifySrcTrunk); 2278 BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifyEtherType); 2279 BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifyDstIp6); 2280 BCM_FIELD_QSET_ADD(oam_info_p->fp_glp_qs, bcmFieldQualifyStageIngress); 2281 2282 /* 2283 * Enable ingress filter for CPU port so LM/DM packets sent from CPU 2284 * can be processed. 2285 */ 2286 result = bcm_esw_port_control_set(unit, CMIC_PORT(unit), 2287 bcmPortControlFilterIngress, 1); 2288 if (BCM_FAILURE(result)) 2289 { 2290 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2291 return result; 2292 } 2293 2294 /* Initialize the ING_VLAN_TAG_ACTION_PROFILE table */ 2295 if (ing_pri_map_profile[unit] == NULL) 2296 { 2297 ing_pri_map_profile[unit] = 2298 sal_alloc(sizeof(soc_profile_mem_t), "Ing Pri Map Profile Mem"); 2299 if (ing_pri_map_profile[unit] == NULL) 2300 { 2301 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2302 return BCM_E_MEMORY; 2303 } 2304 soc_profile_mem_t_init(ing_pri_map_profile[unit]); 2305 } 2306 2307 /* Create profile table cache (or re-init if it already exists) */ 2308 mem = ING_SERVICE_PRI_MAPm; 2309 entry_words = sizeof(ing_service_pri_map_entry_t) / sizeof(uint32); 2310 result = soc_profile_mem_create(unit, &mem, &entry_words, 1, 2311 ing_pri_map_profile[unit]); 2312 if (SOC_FAILURE(result)) { 2313 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2314 return result; 2315 } 2316 2317 2318 /* Initialize the ING_SERVICE_PRI_MAP_PROFILE_DEFAULT. All priorities 2319 * Map to zero. 2320 */ 2321 for (i = 0; i < BCM_OAM_INTPRI_MAX; i++) 2322 { 2323 mem_entries[i] = 0; 2324 if (SOC_MEM_FIELD_VALID(unit, mem, OFFSET_VALIDf)) { 2325 soc_mem_field32_set(unit, mem, &mem_entries[i], OFFSET_VALIDf, 1); 2326 } 2327 } 2328 entries[0] = &mem_entries; 2329 result = soc_profile_mem_add(unit, ing_pri_map_profile[unit], 2330 (void *) &entries, BCM_OAM_INTPRI_MAX, 2331 &temp_index); 2332 if (SOC_FAILURE(result)) { 2333 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2334 return result; 2335 } 2336 2337 2338 #ifdef BCM_WARM_BOOT_SUPPORT 2339 if (SOC_WARM_BOOT(unit)) 2340 { 2341 /* Recover FP groups and entries associated with OAM */ 2342 oam_info_p->vfp_group = -1; 2343 oam_info_p->fp_vp_group = -1; 2344 oam_info_p->fp_glp_group = -1; 2345 result = bcm_esw_field_group_traverse(unit, 2346 _bcm_en_oam_field_group_process, 2347 NULL); 2348 if (BCM_FAILURE(result)) { 2349 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2350 return result; 2351 } 2352 } 2353 #endif 2354 2355 /* 2356 * BHH init 2357 */ 2358 if (soc_feature(unit, soc_feature_bhh)) { 2359 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 2360 if (SOC_IS_KATANAX(unit)) { 2361 if(ukernel_not_ready == 0) { 2362 /* 2363 * Initialize HOST side 2364 */ 2365 oam_info_p->cpu_cosq = 2366 soc_property_get(unit, spn_BHH_COSQ, 42); 2367 2368 /* 2369 * Allocate DMA buffers 2370 * 2371 * DMA buffer will be used to send and receive 'long' messages 2372 * between SDK Host and uController (BTE). 2373 */ 2374 oam_info_p->dma_buffer_len = sizeof(shr_bhh_msg_ctrl_t); 2375 2376 /* Adding feature specific for dma_buf_len as currently 2377 * required buffer length for faults_get can be configurable 2378 * by user during init. So, taking the max value of either of 2379 * them for the purpose.Putting it under fature_check for 2380 * giving flexibility to user. 2381 */ 2382 #ifdef INCLUDE_OAM_FAULTS_MULTI_GET 2383 if(soc_feature(unit, soc_feature_faults_multi_ep_get)) { 2384 oam_info_p->dma_buffer_len = MAX((oam_info_p->bhh_endpoint_count * sizeof(uint32)), 2385 oam_info_p->dma_buffer_len); 2386 } 2387 #endif 2388 oam_info_p->dma_buffer = soc_cm_salloc(unit, 2389 oam_info_p->dma_buffer_len, 2390 "BHH DMA buffer"); 2391 if (!oam_info_p->dma_buffer) { 2392 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2393 return BCM_E_MEMORY; 2394 } 2395 sal_memset(oam_info_p->dma_buffer, 0, oam_info_p->dma_buffer_len); 2396 2397 oam_info_p->dmabuf_reply = soc_cm_salloc(unit, 2398 oam_info_p->dma_buffer_len, 2399 "BHH uC reply"); 2400 if (!oam_info_p->dmabuf_reply) { 2401 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2402 return BCM_E_MEMORY; 2403 } 2404 sal_memset(oam_info_p->dmabuf_reply, 0, oam_info_p->dma_buffer_len); 2405 2406 /* RX DMA channel (0..3) local to the uC */ 2407 oam_info_p->rx_channel = BCM_KT_BHH_RX_CHANNEL; 2408 2409 #if defined(BCM_WARM_BOOT_SUPPORT) 2410 if (!SOC_WARM_BOOT(unit)) { 2411 #endif 2412 /* Set control message data */ 2413 sal_memset(&msg_init, 0, sizeof(msg_init)); 2414 msg_init.num_sessions = oam_info_p->bhh_endpoint_count; 2415 msg_init.rx_channel = oam_info_p->rx_channel; 2416 msg_init.node_id = node_id; 2417 sal_memcpy(msg_init.carrier_code, carrier_code, 2418 SHR_BHH_CARRIER_CODE_LEN); 2419 msg_init.max_encap_length = oam_info_p->bhh_max_encap_length; 2420 if (bhh_consolidate_final_event) { 2421 msg_init.flags |= BHH_SDK_MSG_CTRL_INIT_ONLY_FINAL_EVENT; 2422 } 2423 /* Pack control message data into DMA buffer */ 2424 buffer = oam_info_p->dma_buffer; 2425 buffer_ptr = bhh_sdk_msg_ctrl_init_pack(unit, buffer, &msg_init); 2426 buffer_len = buffer_ptr - buffer; 2427 2428 /* Send BHH Init message to uC */ 2429 result = _bcm_en_oam_bhh_msg_send_receive(unit, 2430 MOS_MSG_SUBCLASS_BHH_INIT, 2431 buffer_len, 0, 2432 MOS_MSG_SUBCLASS_BHH_INIT_REPLY, 2433 &reply_len); 2434 2435 if (BCM_FAILURE(result) || (reply_len != 0)) { 2436 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2437 return BCM_E_INTERNAL; 2438 } 2439 #if defined(BCM_WARM_BOOT_SUPPORT) 2440 } 2441 #endif 2442 2443 /* 2444 * Start event message callback thread 2445 */ 2446 priority = soc_property_get(unit, 2447 spn_BHH_THREAD_PRI, 2448 BHH_THREAD_PRI_DFLT); 2449 2450 if (oam_info_p->event_thread_id == NULL) { 2451 if ((oam_info_p->event_thread_id = 2452 sal_thread_create("bcmBHH", SAL_THREAD_STKSZ, 2453 priority, 2454 _bcm_en_oam_bhh_callback_thread, 2455 (void*)oam_info_p)) == SAL_THREAD_ERROR) { 2456 2457 oam_info_p->event_thread_id = NULL; 2458 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2459 return BCM_E_MEMORY; 2460 } 2461 } 2462 /* 2463 * End BHH init 2464 */ 2465 } 2466 /* 2467 * Initialize HW 2468 */ 2469 result = _bcm_en_oam_bhh_hw_init(unit); 2470 if (BCM_FAILURE(result)) { 2471 BCM_IF_ERROR_RETURN(bcm_en_oam_detach(unit)); 2472 return result; 2473 } 2474 } 2475 #endif 2476 } 2477 2478 oam_info_p->initialized = 1; 2479 2480 return BCM_E_NONE; 2481 } 2482 2483 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 2484 2485 /* 2486 * Function: 2487 * bcm_en_oam_bhh_hw_init 2488 * Purpose: 2489 * Initialize the HW for BHH packet processing. 2490 * Configure: 2491 * - Copy to CPU BHH error packets 2492 * - CPU COS Queue for BHH packets 2493 * - RX DMA channel 2494 * Parameters: 2495 * unit - (IN) Unit number. 2496 * Returns: 2497 * BCM_E_XXX 2498 * Notes: 2499 */ 2500 STATIC int 2501 _bcm_en_oam_bhh_hw_init(int unit) 2502 { 2503 int rv = BCM_E_NONE; 2504 _bcm_oam_info_t *oam_info_p; 2505 uint32 val; 2506 int index; 2507 int ach_error_index; 2508 int invalid_error_index; 2509 int cosq_map_size; 2510 bcm_rx_reasons_t reasons, reasons_mask; 2511 uint8 int_prio, int_prio_mask; 2512 uint32 packet_type, packet_type_mask; 2513 bcm_cos_queue_t cosq; 2514 bcm_rx_chan_t chan_id; 2515 2516 SET_OAM_INFO; 2517 2518 /* 2519 * Send BHH error packet to CPU 2520 * 2521 * Configure CPU_CONTROL_0 register 2522 */ 2523 BCM_IF_ERROR_RETURN(READ_CPU_CONTROL_0r(unit, &val)); 2524 soc_reg_field_set(unit, CPU_CONTROL_0r, &val, 2525 BFD_UNKNOWN_VERSION_TOCPUf, 1); 2526 soc_reg_field_set(unit, CPU_CONTROL_0r, &val, 2527 BFD_YOUR_DISCRIMINATOR_NOT_FOUND_TOCPUf, 1); 2528 soc_reg_field_set(unit, CPU_CONTROL_0r, &val, 2529 BFD_UNKNOWN_CONTROL_PACKET_TOCPUf, 1); 2530 soc_reg_field_set(unit, CPU_CONTROL_0r, &val, 2531 BFD_UNKNOWN_ACH_CHANNEL_TYPE_TOCPUf, 1); 2532 soc_reg_field_set(unit, CPU_CONTROL_0r, &val, 2533 BFD_UNKNOWN_ACH_VERSION_TOCPUf, 1); 2534 BCM_IF_ERROR_RETURN(WRITE_CPU_CONTROL_0r(unit, val)); 2535 2536 /* 2537 * Set BFD ACH Channel Types 2538 */ 2539 #if 0 2540 BCM_IF_ERROR_RETURN(READ_BFD_RX_ACH_TYPE_MPLSTPr(unit, &val)); 2541 soc_reg_field_set(unit, BFD_RX_ACH_TYPE_MPLSTPr, &val, 2542 BFD_ACH_TYPE_MPLSTP_CVf, 2543 SHR_BHH_ACH_CHANNEL_TYPE); 2544 BCM_IF_ERROR_RETURN(WRITE_BFD_RX_ACH_TYPE_MPLSTPr(unit, val)); 2545 #endif 2546 2547 if(oam_info_p->ukernel_not_ready == 0) { 2548 /* 2549 * Direct BHH packets to designated CPU COS Queue...or more accurately 2550 * BFD error packets. 2551 * 2552 * Reasons: 2553 * - bcmRxReasonBFD: BFD error 2554 * - bcmRxReasonBfdUnknownVersion: BFD Unknown ACH 2555 * NOTE: 2556 * The user input 'cpu_qid' (bcm_BHH_endpoint_t) could be 2557 * used to select different CPU COS queue. Currently, 2558 * all priorities are mapped into the same CPU COS Queue. 2559 */ 2560 2561 /* Find available entries in CPU COS queue map table */ 2562 ach_error_index = -1; /* COSQ map index for error packets */ 2563 invalid_error_index = -1; /* COSQ map index for error packets */ 2564 BCM_IF_ERROR_RETURN 2565 (bcm_esw_rx_cosq_mapping_size_get(unit, &cosq_map_size)); 2566 2567 for (index = 0; index < cosq_map_size; index++) { 2568 rv = bcm_esw_rx_cosq_mapping_get(unit, index, 2569 &reasons, &reasons_mask, 2570 &int_prio, &int_prio_mask, 2571 &packet_type, &packet_type_mask, 2572 &cosq); 2573 if (rv == BCM_E_NOT_FOUND) { 2574 /* Assign first available index */ 2575 rv = BCM_E_NONE; 2576 if (ach_error_index == -1) { 2577 ach_error_index = index; 2578 } else if (invalid_error_index == -1) { 2579 invalid_error_index = index; 2580 break; 2581 } 2582 } 2583 if (BCM_FAILURE(rv)) { 2584 return rv; 2585 } 2586 } 2587 2588 if (ach_error_index == -1 || invalid_error_index == -1) { 2589 return BCM_E_FULL; 2590 } 2591 2592 /* Set CPU COS Queue mapping */ 2593 BCM_RX_REASON_CLEAR_ALL(reasons); 2594 BCM_RX_REASON_SET(reasons, bcmRxReasonBfd); /* BFD Error */ 2595 BCM_RX_REASON_SET(reasons, bcmRxReasonBfdUnknownVersion); /* Despite the name this reason */ 2596 /* code covers Unknown ACH */ 2597 2598 BCM_IF_ERROR_RETURN 2599 (bcm_esw_rx_cosq_mapping_set(unit, ach_error_index, 2600 reasons, reasons, 2601 0, 0, /* Any priority */ 2602 0, 0, /* Any packet type */ 2603 oam_info_p->cpu_cosq)); 2604 oam_info_p->cpu_cosq_ach_error_index = ach_error_index; 2605 2606 2607 BCM_RX_REASON_CLEAR_ALL(reasons); 2608 BCM_RX_REASON_SET(reasons, bcmRxReasonBfd); /* BFD Error */ 2609 BCM_RX_REASON_SET(reasons, bcmRxReasonBfdInvalidPacket); 2610 2611 BCM_IF_ERROR_RETURN 2612 (bcm_esw_rx_cosq_mapping_set(unit, invalid_error_index, 2613 reasons, reasons, 2614 0, 0, /* Any priority */ 2615 0, 0, /* Any packet type */ 2616 oam_info_p->cpu_cosq)); 2617 oam_info_p->cpu_cosq_invalid_error_index = invalid_error_index; 2618 2619 2620 /* 2621 * Assign RX DMA channel to CPU COS Queue 2622 * (This is the RX channel to listen on for BHH packets). 2623 * 2624 * DMA channels (12) are assigned 4 per processor: 2625 * (see /src/bcm/common/rx.c) 2626 * channels 0..3 --> PCI host 2627 * channels 4..7 --> uController 0 2628 * chnanels 8..11 --> uController 1 2629 * 2630 * The uControllers designate the 4 local DMA channels as follows: 2631 * local channel 0 --> TX 2632 * local channel 1..3 --> RX 2633 * 2634 * Each uController application needs to use a different 2635 * RX DMA channel to listen on. 2636 */ 2637 chan_id = (BCM_RX_CHANNELS * (SOC_ARM_CMC(unit, oam_info_p->uc_num))) + 2638 oam_info_p->rx_channel; 2639 2640 rv = _bcm_common_rx_queue_channel_set(unit, oam_info_p->cpu_cosq, chan_id); 2641 if (rv != BCM_E_NONE ) { 2642 LOG_ERROR(BSL_LS_BCM_COMMON, 2643 (BSL_META_U(unit, 2644 "BHH(unit %d) Error: No BHH COS Queue available from uC%d - %s\n"), 2645 unit, oam_info_p->uc_num, bcm_errmsg(BCM_E_CONFIG))); 2646 } 2647 } 2648 2649 return rv; 2650 } 2651 2652 2653 /* 2654 * Function: 2655 * _bcm_en_oam_bhh_find_l2x_entry 2656 */ 2657 STATIC int 2658 _bcm_en_oam_bhh_find_l2x_entry(int unit, uint32 key, int key_type, int ses_type, 2659 int *index, l2x_entry_t *l2_entry) 2660 { 2661 l2x_entry_t l2_key; 2662 2663 sal_memset(&l2_key, 0, sizeof(l2_key)); 2664 2665 soc_mem_field32_set(unit, L2Xm, &l2_key, KEY_TYPEf, key_type); 2666 soc_mem_field32_set(unit, L2Xm, &l2_key, 2667 SESSION_IDENTIFIER_TYPEf, ses_type); 2668 2669 if (ses_type) { 2670 soc_mem_field32_set(unit, L2Xm, &l2_key, LABELf, key); 2671 } else { 2672 soc_mem_field32_set(unit, L2Xm, &l2_key, 2673 YOUR_DISCRIMINATORf, key); 2674 } 2675 2676 return soc_mem_search(unit, L2Xm, MEM_BLOCK_ANY, index, 2677 &l2_key, l2_entry, 0); 2678 2679 } 2680 2681 /* 2682 * Function: 2683 * _bcm_en_oam_bhh_session_hw_delete 2684 * Purpose: 2685 * Delete BHH Session in HW device. 2686 * Parameters: 2687 * unit - (IN) Unit number. 2688 * endpoint_p - (IN) Pointer to BHH endpoint structure. 2689 * Returns: 2690 * BCM_E_XXX 2691 * Notes: 2692 */ 2693 STATIC int 2694 _bcm_en_oam_bhh_session_hw_delete(int unit, _bcm_oam_endpoint_t *endpoint_p) 2695 { 2696 int rv = BCM_E_NONE; 2697 int l2_index = 0; 2698 l2x_entry_t l2_entry; 2699 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) 2700 mpls_entry_entry_t mpls_entry; 2701 mpls_entry_entry_t mpls_key; 2702 int mpls_index = 0; 2703 #endif /* BCM_TRIUMPH_SUPPORT && BCM_MPLS_SUPPORT */ 2704 2705 2706 switch(endpoint_p->type) { 2707 case bcmOAMEndpointTypeBHHMPLS: 2708 case bcmOAMEndpointTypeBHHMPLSVccv: 2709 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) 2710 SOC_IF_ERROR_RETURN(bcm_tr_mpls_lock (unit)); 2711 2712 sal_memset(&mpls_key, 0, sizeof(mpls_key)); 2713 soc_MPLS_ENTRYm_field32_set(unit, &mpls_key, 2714 MPLS_LABELf, endpoint_p->label); 2715 2716 SOC_IF_ERROR_RETURN(soc_mem_search(unit, MPLS_ENTRYm, 2717 MEM_BLOCK_ANY, &mpls_index, 2718 &mpls_key, &mpls_entry, 0)); 2719 2720 if ((soc_MPLS_ENTRYm_field32_get(unit, 2721 &mpls_entry, VALIDf) != 0x1)) { 2722 bcm_tr_mpls_unlock (unit); 2723 return BCM_E_PARAM; 2724 } 2725 2726 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, BFD_ENABLEf, 0); 2727 2728 SOC_IF_ERROR_RETURN(soc_mem_write(unit, MPLS_ENTRYm, 2729 MEM_BLOCK_ANY, 2730 mpls_index, &mpls_entry)); 2731 2732 bcm_tr_mpls_unlock (unit); 2733 2734 if (BCM_SUCCESS(_bcm_en_oam_bhh_find_l2x_entry(unit, 2735 endpoint_p->label, 2736 4, 1, 2737 &l2_index, &l2_entry))) { 2738 soc_mem_delete_index(unit, L2Xm, MEM_BLOCK_ANY, l2_index); 2739 2740 } else { 2741 return BCM_E_PARAM; 2742 } 2743 #endif /* BCM_TRIUMPH_SUPPORT && BCM_MPLS_SUPPORT */ 2744 break; 2745 2746 default: 2747 break; 2748 } 2749 2750 return rv; 2751 } 2752 2753 /* 2754 * Function: 2755 * _bcm_en_oam_bhh_msg_send_receive 2756 * Purpose: 2757 * Sends given BHH control message to the uController. 2758 * Receives and verifies expected reply. 2759 * Performs DMA operation if required. 2760 * Parameters: 2761 * unit - (IN) Unit number. 2762 * s_subclass - (IN) BHH message subclass. 2763 * s_len - (IN) Value for 'len' field in message struct. 2764 * Length of buffer to flush if DMA send is required. 2765 * s_data - (IN) Value for 'data' field in message struct. 2766 * Ignored if message requires a DMA send/receive 2767 * operation. 2768 * r_subclass - (IN) Expected reply message subclass. 2769 * r_len - (OUT) Returns value in 'len' reply message field. 2770 * Returns: 2771 * BCM_E_XXX 2772 * Notes: 2773 * - The uc_msg 'len' and 'data' fields of mos_msg_data_t 2774 * can take any arbitrary data. 2775 * 2776 * BHH Long Control message: 2777 * - BHH control messages that require send/receive of information 2778 * that cannot fit in the uc_msg 'len' and 'data' fields need to 2779 * use DMA operations to exchange information (long control message). 2780 * 2781 * - BHH convention for long control messages for 2782 * 'mos_msg_data_t' fields: 2783 * 'len' size of the DMA buffer to send to uController 2784 * 'data' physical DMA memory address to send or receive 2785 * 2786 * DMA Operations: 2787 * - DMA read/write operation is performed when a long BHH control 2788 * message is involved. 2789 * 2790 * - Messages that require DMA operation (long control message) 2791 * is indicated by MOS_MSG_DMA_MSG(). 2792 * 2793 * - Callers must 'pack' and 'unpack' corresponding information 2794 * into/from DMA buffer indicated by BHH_INFO(unit)->dma_buffer. 2795 */ 2796 STATIC int 2797 _bcm_en_oam_bhh_msg_send_receive(int unit, uint8 s_subclass, 2798 uint16 s_len, uint32 s_data, 2799 uint8 r_subclass, uint16 *r_len) 2800 { 2801 int rv = BCM_E_NONE; 2802 _bcm_oam_info_t *oam_info_p; 2803 mos_msg_data_t send, reply; 2804 uint8 *dma_buffer; 2805 int dma_buffer_len; 2806 uint32 uc_rv; 2807 2808 SET_OAM_INFO; 2809 2810 sal_memset(&send, 0, sizeof(send)); 2811 sal_memset(&reply, 0, sizeof(reply)); 2812 send.s.mclass = MOS_MSG_CLASS_BHH; 2813 send.s.subclass = s_subclass; 2814 send.s.len = bcm_htons(s_len); 2815 2816 /* 2817 * Set 'data' to DMA buffer address if a DMA operation is 2818 * required for send or receive. 2819 */ 2820 dma_buffer = oam_info_p->dma_buffer; 2821 dma_buffer_len = oam_info_p->dma_buffer_len; 2822 if (MOS_MSG_DMA_MSG(s_subclass) || 2823 MOS_MSG_DMA_MSG(r_subclass)) { 2824 send.s.data = bcm_htonl(soc_cm_l2p(unit, dma_buffer)); 2825 } else { 2826 send.s.data = bcm_htonl(s_data); 2827 } 2828 2829 /* Flush DMA memory */ 2830 if (MOS_MSG_DMA_MSG(s_subclass)) { 2831 soc_cm_sflush(unit, dma_buffer, s_len); 2832 } 2833 2834 /* Invalidate DMA memory to read */ 2835 if (MOS_MSG_DMA_MSG(r_subclass)) { 2836 soc_cm_sinval(unit, dma_buffer, dma_buffer_len); 2837 } 2838 2839 rv = soc_cmic_uc_msg_send_receive(unit, oam_info_p->uc_num, 2840 &send, &reply, 2841 _BHH_UC_MSG_TIMEOUT_USECS); 2842 2843 /* Check reply class, subclass */ 2844 if ((rv != SOC_E_NONE) || 2845 (reply.s.mclass != MOS_MSG_CLASS_BHH) || 2846 (reply.s.subclass != r_subclass)) { 2847 return BCM_E_INTERNAL; 2848 } 2849 2850 /* Convert BHH uController error code to BCM */ 2851 uc_rv = bcm_ntohl(reply.s.data); 2852 switch(uc_rv) { 2853 case SHR_BHH_UC_E_NONE: 2854 rv = BCM_E_NONE; 2855 break; 2856 case SHR_BHH_UC_E_INTERNAL: 2857 rv = BCM_E_INTERNAL; 2858 break; 2859 case SHR_BHH_UC_E_MEMORY: 2860 rv = BCM_E_MEMORY; 2861 break; 2862 case SHR_BHH_UC_E_PARAM: 2863 rv = BCM_E_PARAM; 2864 break; 2865 case SHR_BHH_UC_E_RESOURCE: 2866 rv = BCM_E_RESOURCE; 2867 break; 2868 case SHR_BHH_UC_E_EXISTS: 2869 rv = BCM_E_EXISTS; 2870 break; 2871 case SHR_BHH_UC_E_NOT_FOUND: 2872 rv = BCM_E_NOT_FOUND; 2873 break; 2874 case SHR_BHH_UC_E_INIT: 2875 rv = BCM_E_INIT; 2876 break; 2877 default: 2878 rv = BCM_E_INTERNAL; 2879 break; 2880 } 2881 2882 *r_len = bcm_ntohs(reply.s.len); 2883 2884 return rv; 2885 } 2886 2887 STATIC uint8 * 2888 _bcm_en_oam_bhh_ach_header_pack(uint8 *buffer, _ach_header_t *ach) 2889 { 2890 uint32 tmp; 2891 2892 tmp = ((ach->f_nibble & 0xf) << 28) | ((ach->version & 0xf) << 24) | 2893 (ach->reserved << 16) | ach->channel_type; 2894 2895 _BHH_ENCAP_PACK_U32(buffer, tmp); 2896 2897 return buffer; 2898 } 2899 2900 STATIC uint8 * 2901 _bcm_en_oam_bhh_mpls_label_pack(uint8 *buffer, _mpls_label_t *mpls) 2902 { 2903 uint32 tmp; 2904 2905 tmp = ((mpls->label & 0xfffff) << 12) | ((mpls->exp & 0x7) << 9) | 2906 ((mpls->s & 0x1) << 8) | mpls->ttl; 2907 _BHH_ENCAP_PACK_U32(buffer, tmp); 2908 2909 return buffer; 2910 } 2911 2912 STATIC uint8 * 2913 _bcm_en_oam_bhh_l2_header_pack(uint8 *buffer, _l2_header_t *l2) 2914 { 2915 uint32 tmp; 2916 int i; 2917 2918 for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) { 2919 _BHH_ENCAP_PACK_U8(buffer, l2->dst_mac[i]); 2920 } 2921 2922 for (i = 0; i < _BHH_MAC_ADDR_LENGTH; i++) { 2923 _BHH_ENCAP_PACK_U8(buffer, l2->src_mac[i]); 2924 } 2925 2926 /* Vlan Tag tpid = 0 indicates untagged */ 2927 if (0 != l2->vlan_tag.tpid) { 2928 tmp = (l2->vlan_tag.tpid << 16) | 2929 ((l2->vlan_tag.tci.prio & 0x7) << 13) | 2930 ((l2->vlan_tag.tci.cfi & 0x1) << 12) | 2931 (l2->vlan_tag.tci.vid & 0xfff); 2932 _BHH_ENCAP_PACK_U32(buffer, tmp); 2933 } 2934 2935 /*Inner Vlan Tag inner_tpid = 0 indicates single tag */ 2936 if (0 != l2->vlan_tag_inner.tpid) { 2937 tmp = (l2->vlan_tag_inner.tpid << 16) | 2938 ((l2->vlan_tag_inner.tci.prio & 0x7) << 13) | 2939 ((l2->vlan_tag_inner.tci.cfi & 0x1) << 12) | 2940 (l2->vlan_tag_inner.tci.vid & 0xfff); 2941 _BHH_ENCAP_PACK_U32(buffer, tmp); 2942 } 2943 _BHH_ENCAP_PACK_U16(buffer, l2->etype); 2944 2945 return (buffer); 2946 } 2947 2948 /* 2949 * Function: 2950 * bcm_en_oam_mpls_tp_channel_type_tx_get 2951 * Purpose: 2952 * Get MPLS TP(BHH) ACH Channel type 2953 * Parameters: 2954 * unit (IN) BCM device number 2955 * channel_type (IN) Channel type is ignored in XGS devices 2956 * Value (OUT) User define MPLS TP(BHH) ACH channel type 2957 * 2958 * Returns: 2959 * BCM_E_NONE No error 2960 * BCM_E_XXXX Error 2961 */ 2962 int 2963 bcm_en_oam_mpls_tp_channel_type_tx_get(int unit, 2964 bcm_oam_mpls_tp_channel_type_t channel_type, 2965 int *value) 2966 { 2967 *value = en_oam_mpls_tp_ach_channel_type; 2968 return BCM_E_NONE; 2969 } 2970 2971 /* 2972 * Function: 2973 * bcm_en_oam_mpls_tp_channel_type_tx_set 2974 * Purpose: 2975 * Update MPLS TP(BHH) ACH Channel type with user defined value 2976 * Parameters: 2977 * unit (IN) BCM device number 2978 * channel_type (IN) Channel type is ignored in XGS devices 2979 * Value (IN) User define MPLS TP(BHH) ACH channel type 2980 * 2981 * Returns: 2982 * BCM_E_NONE No error 2983 * BCM_E_XXXX Error 2984 */ 2985 int 2986 bcm_en_oam_mpls_tp_channel_type_tx_set(int unit, 2987 bcm_oam_mpls_tp_channel_type_t channel_type, 2988 int value) 2989 { 2990 uint8 *buffer, *buffer_ptr; 2991 uint16 buffer_len, reply_len; 2992 int rv = BCM_E_NONE; 2993 _bcm_oam_info_t *oam_info_p; 2994 uint32 *msg; 2995 2996 SET_OAM_INFO; 2997 CHECK_INIT; 2998 2999 if(oam_info_p->ukernel_not_ready) { 3000 return BCM_E_INIT; 3001 } 3002 3003 if ((value != SHR_BHH_ACH_CHANNEL_TYPE) && 3004 (value != SHR_BHH_ACH_CHANNEL_TYPE_1)) { 3005 return BCM_E_CONFIG; 3006 } 3007 3008 en_oam_mpls_tp_ach_channel_type = value; 3009 msg = (uint32 *)&en_oam_mpls_tp_ach_channel_type; 3010 3011 /* Pack control message data into DMA buffer */ 3012 buffer = oam_info_p->dma_buffer; 3013 buffer_ptr = bhh_sdk_msg_ctrl_ach_channel_type_msg_pack(buffer, msg); 3014 buffer_len = buffer_ptr - buffer; 3015 3016 rv = _bcm_en_oam_bhh_msg_send_receive( 3017 unit, 3018 MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE, 3019 buffer_len, 0, 3020 MOS_MSG_SUBCLASS_BHH_ACH_CHANNEL_TYPE_REPLY, 3021 &reply_len); 3022 3023 if (BCM_FAILURE(rv)) { 3024 return (rv); 3025 } 3026 3027 return BCM_E_NONE; 3028 } 3029 3030 STATIC int 3031 _bcm_en_oam_bhh_ach_header_get(uint32 packet_flags, _ach_header_t *ach) 3032 { 3033 sal_memset(ach, 0, sizeof(*ach)); 3034 3035 ach->f_nibble = SHR_BHH_ACH_FIRST_NIBBLE; 3036 ach->version = SHR_BHH_ACH_VERSION; 3037 ach->reserved = 0; 3038 3039 ach->channel_type = en_oam_mpls_tp_ach_channel_type; 3040 3041 return BCM_E_NONE; 3042 } 3043 3044 STATIC int 3045 _bcm_en_oam_bhh_mpls_label_get(uint32 label, uint8 exp, uint8 s, uint8 ttl, 3046 _mpls_label_t *mpls) 3047 { 3048 sal_memset(mpls, 0, sizeof(*mpls)); 3049 3050 mpls->label = label; 3051 mpls->exp = exp & 0x07; 3052 mpls->s = s; 3053 if(ttl) 3054 mpls->ttl = ttl; 3055 else 3056 mpls->ttl = _BHH_MPLS_DFLT_TTL; 3057 3058 return BCM_E_NONE; 3059 } 3060 3061 STATIC int 3062 _bcm_en_oam_bhh_mpls_gal_label_get(_mpls_label_t *mpls, uint8 oam_exp) 3063 { 3064 return _bcm_en_oam_bhh_mpls_label_get(SHR_BHH_MPLS_GAL_LABEL, 3065 oam_exp, 1, 1, mpls); 3066 } 3067 3068 STATIC int 3069 _bcm_en_oam_bhh_mpls_labels_get(int unit, _bcm_oam_endpoint_t *endpoint_p, 3070 uint32 packet_flags, 3071 int max_count, 3072 _mpls_label_t *pw_label, 3073 _mpls_label_t *mpls, 3074 int *mpls_count, bcm_if_t *l3_intf_id) 3075 { 3076 int count = 0; 3077 bcm_l3_egress_t l3_egress; 3078 bcm_mpls_port_t mpls_port; 3079 bcm_mpls_egress_label_t label_array[_BHH_MPLS_MAX_LABELS]; 3080 bcm_mpls_egress_label_t tmp_label; 3081 int label_count; 3082 int i = 0; 3083 3084 /* Get L3 objects */ 3085 bcm_l3_egress_t_init(&l3_egress); 3086 if (BCM_FAILURE(bcm_esw_l3_egress_get(unit, endpoint_p->egress_if, &l3_egress))) { 3087 return BCM_E_PARAM; 3088 } 3089 3090 /* Look for a tunnel associated with this interface */ 3091 if (BCM_SUCCESS 3092 (bcm_esw_mpls_tunnel_initiator_get(unit, l3_egress.intf, 3093 _BHH_MPLS_MAX_LABELS, 3094 label_array, &label_count))) { 3095 3096 /* We need to swap the labels configured in tunnel initiator as 3097 * it returns labels in reverse order than how it should be in pkt. 3098 */ 3099 for (i = 0; i < (label_count / 2); i++) { 3100 sal_memcpy(&tmp_label, &label_array[i], sizeof(tmp_label)); 3101 sal_memcpy(&label_array[i], &label_array[label_count - 1 - i], 3102 sizeof(tmp_label)); 3103 sal_memcpy(&label_array[label_count - 1 - i], &tmp_label, 3104 sizeof(tmp_label)); 3105 } 3106 3107 /* Add VRL Label */ 3108 if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLS) { 3109 if ((l3_egress.mpls_label != BCM_MPLS_LABEL_INVALID) && 3110 (endpoint_p->egr_label != BCM_MPLS_LABEL_INVALID) && 3111 (label_count < _BHH_MPLS_MAX_LABELS) ) { 3112 3113 label_array[label_count].label = l3_egress.mpls_label; 3114 label_array[label_count].exp = l3_egress.mpls_exp; 3115 label_array[label_count].ttl = l3_egress.mpls_ttl; 3116 label_count++; 3117 } 3118 /* Traverse through Label stack and match on control label, this 3119 * label should be the one just above GAL in the label stack, any 3120 * following labels should not be added. 3121 */ 3122 for (i = 0; i < label_count; i++) { 3123 if (label_array[i].label == endpoint_p->egr_label) { 3124 label_count = i + 1; 3125 label_array[i].exp = endpoint_p->egr_label_exp; 3126 if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) && 3127 endpoint_p->egr_label_ttl) { 3128 label_array[i].ttl = endpoint_p->egr_label_ttl; 3129 } 3130 break; 3131 } 3132 } 3133 } 3134 } 3135 3136 /* MPLS Router Alert */ 3137 if (packet_flags & _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT) { 3138 /* Ignore overrun error as RAL is only added for PW MEPs and so overrun 3139 * condition will not exist. 3140 */ 3141 /* coverity[overrun-local] */ 3142 label_array[label_count].label = SHR_BHH_MPLS_ROUTER_ALERT_LABEL; 3143 label_array[label_count].exp = 0; 3144 label_array[label_count].ttl = 0; 3145 label_count++; 3146 } 3147 3148 /* Use GPORT to resolve interface */ 3149 if (BCM_GPORT_IS_MPLS_PORT(endpoint_p->gport)) { 3150 /* Get mpls port and label info */ 3151 bcm_mpls_port_t_init(&mpls_port); 3152 mpls_port.mpls_port_id = endpoint_p->gport; 3153 if (BCM_FAILURE(bcm_esw_mpls_port_get(unit, endpoint_p->vpn, 3154 &mpls_port))) { 3155 return BCM_E_PARAM; 3156 } 3157 if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv && 3158 endpoint_p->vccv_type == bcmOamBhhVccvTtl) { 3159 mpls_port.egress_label.ttl = 0x1; 3160 } 3161 label_array[label_count].label = mpls_port.egress_label.label; 3162 if (endpoint_p->egr_label == mpls_port.egress_label.label) { 3163 label_array[label_count].exp = endpoint_p->egr_label_exp; 3164 if (soc_property_get(unit, spn_MPLS_OAM_EGRESS_LABEL_TTL, 0) && 3165 endpoint_p->egr_label_ttl) { 3166 label_array[label_count].ttl = endpoint_p->egr_label_ttl; 3167 } 3168 } else { 3169 label_array[label_count].exp = mpls_port.egress_label.exp; 3170 label_array[label_count].ttl = mpls_port.egress_label.ttl; 3171 } 3172 label_count++; 3173 } 3174 3175 for (i=0; i < label_count; i++) { 3176 _bcm_en_oam_bhh_mpls_label_get(label_array[i].label, 3177 label_array[i].exp, 3178 0, 3179 label_array[i].ttl, 3180 &mpls[count++]); 3181 } 3182 3183 /* Set Bottom of Stack if there is no GAL label */ 3184 if (!(packet_flags & _BHH_ENCAP_PKT_GAL)) { 3185 mpls[count - 1].s = 1; 3186 } 3187 3188 *mpls_count = count; 3189 3190 return BCM_E_NONE; 3191 3192 } 3193 3194 STATIC int 3195 _bcm_en_oam_bhh_l2_header_get(int unit, _bcm_oam_endpoint_t *endpoint_p, 3196 bcm_port_t port, uint16 etype, 3197 _l2_header_t *l2) 3198 { 3199 uint16 tpid; 3200 bcm_l3_egress_t l3_egress; 3201 bcm_l3_intf_t l3_intf; 3202 bcm_vlan_control_vlan_t vc; 3203 int tpid_select; 3204 bcm_pbmp_t pbmp, ubmp; 3205 3206 sal_memset(l2, 0, sizeof(*l2)); 3207 /* Get L3 interfaces */ 3208 bcm_l3_egress_t_init(&l3_egress); 3209 bcm_l3_intf_t_init(&l3_intf); 3210 3211 if (BCM_FAILURE 3212 (bcm_esw_l3_egress_get(unit, endpoint_p->egress_if, &l3_egress))) { 3213 return (BCM_E_PARAM); 3214 } 3215 3216 l3_intf.l3a_intf_id = l3_egress.intf; 3217 if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) { 3218 return (BCM_E_PARAM); 3219 } 3220 3221 /* Get TPID */ 3222 BCM_IF_ERROR_RETURN(bcm_esw_vlan_control_port_get(unit, 3223 port, 3224 bcmVlanPortOuterTpidSelect, 3225 &tpid_select)); 3226 if (tpid_select == BCM_PORT_OUTER_TPID) { 3227 BCM_IF_ERROR_RETURN(bcm_esw_port_tpid_get(unit, port, &tpid)); 3228 } else { 3229 BCM_IF_ERROR_RETURN( 3230 bcm_esw_vlan_control_vlan_get(unit, l3_intf.l3a_vid, &vc)); 3231 tpid = vc.outer_tpid; 3232 } 3233 3234 sal_memcpy(l2->dst_mac, l3_egress.mac_addr, _BHH_MAC_ADDR_LENGTH); 3235 sal_memcpy(l2->src_mac, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH); 3236 l2->vlan_tag.tpid = tpid; 3237 l2->vlan_tag.tci.prio = endpoint_p->vlan_pri; 3238 l2->vlan_tag.tci.cfi = 0; 3239 l2->vlan_tag.tci.vid = l3_intf.l3a_vid; 3240 3241 BCM_IF_ERROR_RETURN(bcm_esw_vlan_port_get(unit, 3242 l2->vlan_tag.tci.vid, 3243 &pbmp, 3244 &ubmp)); 3245 if (BCM_PBMP_MEMBER(ubmp, port)) { 3246 l2->vlan_tag.tpid = 0; /* Set to 0 to indicate untagged */ 3247 } 3248 3249 if (l3_intf.l3a_inner_vlan != 0) { 3250 BCM_IF_ERROR_RETURN(bcm_esw_port_inner_tpid_get(unit, port, &tpid)); 3251 l2->vlan_tag_inner.tpid = tpid; 3252 l2->vlan_tag_inner.tci.prio = endpoint_p->inner_vlan_pri; 3253 l2->vlan_tag_inner.tci.cfi = 0; 3254 l2->vlan_tag_inner.tci.vid = l3_intf.l3a_inner_vlan; 3255 } 3256 l2->etype = etype; 3257 3258 return BCM_E_NONE; 3259 } 3260 /* 3261 * Function: 3262 * _bcm_en_oam_bhh_encap_build_pack 3263 * Purpose: 3264 * Builds and packs the BHH packet encapsulation for a given 3265 * BHH tunnel type. 3266 * Parameters: 3267 * unit - (IN) Unit number. 3268 * port - (IN) Port. 3269 * endpoint_config - (IN/OUT) Pointer to BHH endpoint structure. 3270 * packet_flags - (IN) Flags for building packet. 3271 * buffer - (OUT) Buffer returning BHH encapsulation. 3272 * Returns: 3273 * BCM_E_XXX 3274 * Notes: 3275 * The returning BHH encapsulation includes only all the 3276 * encapsulation headers/labels and does not include 3277 * the BHH control packet. 3278 */ 3279 STATIC int 3280 _bcm_en_oam_bhh_encap_build_pack(int unit, bcm_port_t port, 3281 _bcm_oam_endpoint_t *endpoint_p, 3282 uint32 packet_flags, 3283 uint8 *buffer, 3284 uint32 *encap_length) 3285 { 3286 uint8 *cur_ptr = buffer; 3287 uint16 etype = 0; 3288 bcm_if_t l3_intf_id = -1; 3289 _ach_header_t ach; 3290 _mpls_label_t mpls_gal; 3291 _mpls_label_t mpls_labels[_BHH_MPLS_MAX_LABELS]; 3292 _mpls_label_t pw_label; 3293 int mpls_count = 0; 3294 _l2_header_t l2; 3295 int i; 3296 3297 3298 /* 3299 * Get necessary headers/labels information. 3300 * 3301 * Following order is important since some headers/labels 3302 * may depend on previous header/label information. 3303 */ 3304 if (packet_flags & _BHH_ENCAP_PKT_G_ACH) { 3305 BCM_IF_ERROR_RETURN 3306 (_bcm_en_oam_bhh_ach_header_get(packet_flags, &ach)); 3307 } 3308 3309 if (packet_flags & _BHH_ENCAP_PKT_GAL) { 3310 if (endpoint_p->egr_label == SHR_BHH_MPLS_GAL_LABEL) { 3311 BCM_IF_ERROR_RETURN 3312 (_bcm_en_oam_bhh_mpls_gal_label_get(&mpls_gal, 3313 endpoint_p->egr_label_exp)); 3314 } else { 3315 BCM_IF_ERROR_RETURN 3316 (_bcm_en_oam_bhh_mpls_gal_label_get(&mpls_gal, 0)); 3317 } 3318 } 3319 3320 if (packet_flags & _BHH_ENCAP_PKT_MPLS) { 3321 etype = SHR_BHH_L2_ETYPE_MPLS_UCAST; 3322 BCM_IF_ERROR_RETURN 3323 (_bcm_en_oam_bhh_mpls_labels_get(unit, endpoint_p, 3324 packet_flags, 3325 _BHH_MPLS_MAX_LABELS, 3326 &pw_label, 3327 mpls_labels, 3328 &mpls_count, 3329 &l3_intf_id)); 3330 } 3331 3332 /* Always build L2 Header */ 3333 BCM_IF_ERROR_RETURN 3334 (_bcm_en_oam_bhh_l2_header_get(unit, 3335 endpoint_p, 3336 port, 3337 etype, 3338 &l2)); 3339 3340 3341 /* 3342 * Pack header/labels into given buffer (network packet format). 3343 * 3344 * Following packing order must be followed to correctly 3345 * build the packet encapsulation. 3346 */ 3347 cur_ptr = buffer; 3348 3349 /* L2 Header is always present */ 3350 cur_ptr = _bcm_en_oam_bhh_l2_header_pack(cur_ptr, &l2); 3351 3352 if (packet_flags & _BHH_ENCAP_PKT_MPLS) { 3353 for (i = 0;i < mpls_count;i++) { 3354 cur_ptr = _bcm_en_oam_bhh_mpls_label_pack(cur_ptr, &mpls_labels[i]); 3355 } 3356 } 3357 if (packet_flags & _BHH_ENCAP_PKT_GAL) { 3358 cur_ptr = _bcm_en_oam_bhh_mpls_label_pack(cur_ptr, &mpls_gal); 3359 } 3360 3361 if (packet_flags & _BHH_ENCAP_PKT_G_ACH) { 3362 cur_ptr = _bcm_en_oam_bhh_ach_header_pack(cur_ptr, &ach); 3363 } 3364 3365 3366 /* Set BHH encapsulation length */ 3367 *encap_length = cur_ptr - buffer; 3368 3369 return BCM_E_NONE; 3370 } 3371 3372 /* 3373 * Function: 3374 * _bcm_en_oam_bhh_encap_data_dump 3375 * Purpose: 3376 * Dumps buffer contents. 3377 * Parameters: 3378 * buffer - (IN) Buffer to dump data. 3379 * length - (IN) Length of buffer. 3380 * Returns: 3381 * None 3382 */ 3383 void 3384 _bcm_en_oam_bhh_encap_data_dump(uint8 *buffer, int length) 3385 { 3386 int i; 3387 3388 LOG_CLI((BSL_META("\nBHH encapsulation (length=%d):\n"), length)); 3389 3390 for (i = 0; i < length; i++) { 3391 if ((i % 16) == 0) { 3392 LOG_CLI((BSL_META("\n"))); 3393 } 3394 LOG_CLI((BSL_META(" %02x"), buffer[i])); 3395 } 3396 3397 LOG_CLI((BSL_META("\n"))); 3398 return; 3399 } 3400 3401 /* 3402 * Function: 3403 * _bcm_en_oam_bhh_encap_create 3404 * Purpose: 3405 * Creates a BHH packet encapsulation. 3406 * Parameters: 3407 * unit - (IN) Unit number. 3408 * port_id - (IN) Port. 3409 * endpoint_config - (IN/OUT) Pointer to BHH endpoint structure. 3410 * encap_data - (OUT) Buffer returning BHH encapsulation. 3411 * Returns: 3412 * BCM_E_XXX 3413 * Notes: 3414 * The returning BHH encapsulation buffer includes all the 3415 * corresponding headers/labels EXCEPT for the BHH control packet. 3416 */ 3417 STATIC int 3418 _bcm_en_oam_bhh_encap_create(int unit, bcm_port_t port_id, 3419 _bcm_oam_endpoint_t *endpoint_p, 3420 uint8 *encap_data, 3421 uint8 *encap_type, 3422 uint32 *encap_length) 3423 { 3424 uint32 packet_flags; 3425 _bcm_oam_info_t *oam_info_p; 3426 3427 SET_OAM_INFO; 3428 3429 packet_flags = 0; 3430 3431 /* 3432 * Get BHH encapsulation packet format flags 3433 * 3434 * Also, perform the following for each BHH tunnel type: 3435 * - Check for valid parameter values 3436 * - Set specific values required by the BHH tunnel definition 3437 * (e.g. such as ttl=1,...) 3438 */ 3439 switch (endpoint_p->type) { 3440 case bcmOAMEndpointTypeBHHMPLS: 3441 packet_flags |= 3442 (_BHH_ENCAP_PKT_MPLS | 3443 _BHH_ENCAP_PKT_GAL | 3444 _BHH_ENCAP_PKT_G_ACH); 3445 break; 3446 3447 case bcmOAMEndpointTypeBHHMPLSVccv: 3448 switch(endpoint_p->vccv_type) { 3449 3450 case bcmOamBhhVccvChannelAch: 3451 packet_flags |= 3452 (_BHH_ENCAP_PKT_MPLS | 3453 _BHH_ENCAP_PKT_PW | 3454 _BHH_ENCAP_PKT_G_ACH); 3455 break; 3456 3457 case bcmOamBhhVccvRouterAlert: 3458 packet_flags |= 3459 (_BHH_ENCAP_PKT_MPLS | 3460 _BHH_ENCAP_PKT_PW | 3461 _BHH_ENCAP_PKT_MPLS_ROUTER_ALERT | 3462 _BHH_ENCAP_PKT_G_ACH); 3463 break; 3464 3465 case bcmOamBhhVccvTtl: 3466 packet_flags |= 3467 (_BHH_ENCAP_PKT_MPLS | 3468 _BHH_ENCAP_PKT_PW | 3469 _BHH_ENCAP_PKT_G_ACH); 3470 break; 3471 3472 case bcmOamBhhVccvGal13: 3473 packet_flags |= 3474 (_BHH_ENCAP_PKT_MPLS | 3475 _BHH_ENCAP_PKT_PW | 3476 _BHH_ENCAP_PKT_GAL | 3477 _BHH_ENCAP_PKT_G_ACH); 3478 break; 3479 3480 default: 3481 return BCM_E_PARAM; 3482 break; 3483 } 3484 break; 3485 3486 default: 3487 return BCM_E_PARAM; 3488 } 3489 3490 /* Build header/labels and pack in buffer */ 3491 BCM_IF_ERROR_RETURN 3492 (_bcm_en_oam_bhh_encap_build_pack(unit, port_id, 3493 endpoint_p, 3494 packet_flags, 3495 encap_data, 3496 encap_length)); 3497 3498 /* Set encap type (indicates uC side that checksum is required) */ 3499 *encap_type = SHR_BHH_ENCAP_TYPE_RAW; 3500 #ifdef _BHH_DEBUG_DUMP 3501 _bcm_en_oam_bhh_encap_data_dump(encap_data, *encap_length); 3502 #endif 3503 3504 if (*encap_length > oam_info_p->bhh_max_encap_length) { 3505 LOG_ERROR(BSL_LS_BCM_OAM, 3506 (BSL_META_U(unit, 3507 "OAM(unit %d) Error: Encap length greater than max," 3508 "encap_length=%u max=%u\n"), 3509 unit, *encap_length, oam_info_p->bhh_max_encap_length)); 3510 return BCM_E_CONFIG; 3511 } 3512 3513 return BCM_E_NONE; 3514 } 3515 3516 /* 3517 * Function: 3518 * _bcm_en_oam_bhh_encap_hw_set 3519 * Purpose: 3520 * Sets BHH encapsulation type in HW device. 3521 * Parameters: 3522 * unit - (IN) Unit number. 3523 * module_id - (IN) Module id. 3524 * port_id - (IN) Port. 3525 * is_local - (IN) Indicates if module id is local. 3526 * endpoint_config - (IN) Pointer to BHH endpoint structure. 3527 * Returns: 3528 * BCM_E_XXX 3529 * Notes: 3530 */ 3531 STATIC int 3532 _bcm_en_oam_bhh_encap_hw_set(int unit, _bcm_oam_endpoint_t *endpoint_p, 3533 bcm_module_t module_id, bcm_port_t port_id, 3534 int is_local, bcm_cos_t int_pri) 3535 { 3536 int rv = BCM_E_NONE; 3537 l2x_entry_t l2_entry; 3538 _bcm_oam_info_t *oam_info_p; 3539 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) 3540 bcm_l3_egress_t l3_egress; 3541 int ingress_if; 3542 int i; 3543 int num_entries; 3544 mpls_entry_entry_t mpls_entry; 3545 mpls_entry_entry_t mpls_key; 3546 int vccv_type = 0; 3547 int mpls_index = 0; 3548 #endif /* BCM_TRIUMPH_SUPPORT && BCM_MPLS_SUPPORT */ 3549 3550 SET_OAM_INFO; 3551 3552 COMPILER_REFERENCE(oam_info_p); 3553 3554 switch(endpoint_p->type) { 3555 case bcmOAMEndpointTypeBHHMPLS: 3556 case bcmOAMEndpointTypeBHHMPLSVccv: 3557 3558 #if defined(BCM_TRIUMPH_SUPPORT) && defined(BCM_MPLS_SUPPORT) 3559 3560 /* Insert mpls label field to L2_ENTRY table. */ 3561 sal_memset(&l2_entry, 0, sizeof(l2_entry)); 3562 3563 soc_mem_field32_set(unit, L2Xm, &l2_entry, KEY_TYPEf, 4); 3564 soc_mem_field32_set(unit, L2Xm, &l2_entry, SESSION_IDENTIFIER_TYPEf, 3565 1); 3566 soc_mem_field32_set(unit, L2Xm, &l2_entry, LABELf, 3567 endpoint_p->label); 3568 soc_mem_field32_set(unit, L2Xm, &l2_entry, VALIDf, 1); 3569 3570 if (!is_local) { 3571 /* Set BHH_REMOTE = 1, DST_MOD, DST_PORT */ 3572 soc_mem_field32_set(unit, L2Xm, &l2_entry, BFD_REMOTEf, 1); 3573 soc_mem_field32_set(unit, L2Xm, &l2_entry, BFD_DST_MODf, 3574 module_id); 3575 soc_mem_field32_set(unit, L2Xm, &l2_entry, BFD_DST_PORTf, 3576 port_id); 3577 soc_mem_field32_set(unit, L2Xm, &l2_entry, BFD_INT_PRIf, 3578 int_pri); 3579 } else { 3580 soc_mem_field32_set(unit, L2Xm, &l2_entry, BFD_CPU_QUEUE_CLASSf, 3581 endpoint_p->cpu_qid); 3582 } 3583 3584 soc_mem_insert(unit, L2Xm, MEM_BLOCK_ANY, &l2_entry); 3585 3586 SOC_IF_ERROR_RETURN(bcm_tr_mpls_lock (unit)); 3587 3588 sal_memset(&mpls_key, 0, sizeof(mpls_key)); 3589 soc_MPLS_ENTRYm_field32_set(unit, &mpls_key, MPLS_LABELf, 3590 endpoint_p->label); 3591 3592 SOC_IF_ERROR_RETURN(soc_mem_search(unit, MPLS_ENTRYm, 3593 MEM_BLOCK_ANY, &mpls_index, 3594 &mpls_key, &mpls_entry, 0)); 3595 3596 if ((soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, 3597 VALIDf) != 0x1)) { 3598 bcm_tr_mpls_unlock (unit); 3599 return BCM_E_PARAM; 3600 } 3601 3602 if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 3603 /* Get the control channel type */ 3604 vccv_type = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, 3605 MPLS__PW_CC_TYPEf); 3606 3607 if (vccv_type == 0) { /* No VCCV type configured */ 3608 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, 3609 MPLS__PW_CC_TYPEf, 3610 (endpoint_p->vccv_type + 1)); 3611 3612 } else if (vccv_type != (endpoint_p->vccv_type + 1)) { 3613 /* Endpoint add configuration conflicts with MPLS 3614 * port add config 3615 */ 3616 bcm_tr_mpls_unlock(unit); 3617 return BCM_E_PARAM; 3618 } 3619 } 3620 3621 3622 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, 3623 SESSION_IDENTIFIER_TYPEf, 1); 3624 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, BFD_ENABLEf, 1); 3625 rv = soc_mem_write(unit, MPLS_ENTRYm, 3626 MEM_BLOCK_ANY, mpls_index, 3627 &mpls_entry); 3628 if (rv != SOC_E_NONE) { 3629 bcm_tr_mpls_unlock(unit); 3630 return rv; 3631 } 3632 3633 3634 /* 3635 * PW CC-3 3636 * 3637 * Set MPLS entry DECAP_USE_TTL=0 for corresponding 3638 * Tunnel Terminator label. 3639 */ 3640 if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 3641 if (endpoint_p->vccv_type == bcmOamBhhVccvTtl) { 3642 rv = bcm_esw_l3_egress_get(unit, endpoint_p->egress_if, 3643 &l3_egress); 3644 if (rv != BCM_E_NONE) { 3645 bcm_tr_mpls_unlock(unit); 3646 return rv; 3647 } 3648 3649 /* Look for Tunnel Terminator label */ 3650 num_entries = soc_mem_index_count(unit, MPLS_ENTRYm); 3651 for (i = 0; i < num_entries; i++) { 3652 rv = READ_MPLS_ENTRYm(unit, MEM_BLOCK_ANY, i, &mpls_entry); 3653 if (rv != SOC_E_NONE) { 3654 bcm_tr_mpls_unlock(unit); 3655 return rv; 3656 } 3657 3658 if (!soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, VALIDf)) { 3659 continue; 3660 } 3661 if (soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, 3662 MPLS_ACTION_IF_BOSf) == 0x1) { 3663 continue; /* L2_SVP */ 3664 } 3665 3666 ingress_if = soc_MPLS_ENTRYm_field32_get(unit, &mpls_entry, 3667 L3_IIFf); 3668 if (ingress_if == l3_egress.intf) { 3669 /* Label found */ 3670 soc_MPLS_ENTRYm_field32_set(unit, &mpls_entry, 3671 DECAP_USE_TTLf, 0); 3672 rv = soc_mem_write(unit, MPLS_ENTRYm, 3673 MEM_BLOCK_ALL, i, 3674 &mpls_entry); 3675 if (rv != SOC_E_NONE) { 3676 bcm_tr_mpls_unlock(unit); 3677 return rv; 3678 } 3679 break; 3680 } 3681 } 3682 } 3683 } 3684 3685 bcm_tr_mpls_unlock (unit); 3686 #endif /* BCM_TRIUMPH_SUPPORT && BCM_MPLS_SUPPORT */ 3687 break; 3688 3689 default: 3690 rv = BCM_E_UNAVAIL; 3691 break; 3692 } 3693 3694 return rv; 3695 } 3696 3697 /* BHH Event Handler */ 3698 typedef struct _event_handler_s { 3699 struct _event_handler_s *next; 3700 bcm_oam_event_types_t event_types; 3701 bcm_oam_event_cb cb; 3702 void *user_data; 3703 } _event_handler_t; 3704 3705 /* 3706 * Function: 3707 * _bcm_en_oam_bhh_event_mask_set 3708 * Purpose: 3709 * Set the BHH Events mask. 3710 * Events are set per BHH module. 3711 * Parameters: 3712 * unit - (IN) Unit number. 3713 * Returns: 3714 * BCM_E_NONE Operation completed successfully 3715 * BCM_E_XXX Operation failed 3716 * Notes: 3717 */ 3718 STATIC int 3719 _bcm_en_oam_bhh_event_mask_set(int unit) 3720 { 3721 _bcm_oam_info_t *oam_info_p; 3722 _bcm_oam_event_handler_t *event_handler_p; 3723 uint32 event_mask = 0; 3724 uint16 reply_len; 3725 3726 SET_OAM_INFO; 3727 3728 /* Get event mask from all callbacks */ 3729 for (event_handler_p = oam_info_p->event_handler_list_p; 3730 event_handler_p != NULL; 3731 event_handler_p = event_handler_p->next_p) { 3732 3733 if (SHR_BITGET(event_handler_p->event_types.w, 3734 bcmOAMEventBHHLBTimeout)) { 3735 event_mask |= BHH_BTE_EVENT_LB_TIMEOUT; 3736 } 3737 if (SHR_BITGET(event_handler_p->event_types.w, 3738 bcmOAMEventBHHLBDiscoveryUpdate)) { 3739 event_mask |= BHH_BTE_EVENT_LB_DISCOVERY_UPDATE; 3740 } 3741 if (SHR_BITGET(event_handler_p->event_types.w, 3742 bcmOAMEventBHHCCMTimeout)) { 3743 event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT; 3744 } 3745 if (SHR_BITGET(event_handler_p->event_types.w, 3746 bcmOAMEventBHHCCMState)) { 3747 event_mask |= BHH_BTE_EVENT_STATE; 3748 } 3749 if (SHR_BITGET(event_handler_p->event_types.w, 3750 bcmOAMEventBHHCCMTimeoutClear)) { 3751 event_mask |= BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR; 3752 } 3753 if (SHR_BITGET(event_handler_p->event_types.w, 3754 bcmOAMEventBHHCCMRdi)) { 3755 event_mask |= BHH_BTE_EVENT_CCM_RDI; 3756 } 3757 if (SHR_BITGET(event_handler_p->event_types.w, 3758 bcmOAMEventBHHCCMUnknownMegLevel)) { 3759 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL; 3760 } 3761 if (SHR_BITGET(event_handler_p->event_types.w, 3762 bcmOAMEventBHHCCMUnknownMegId)) { 3763 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID; 3764 } 3765 if (SHR_BITGET(event_handler_p->event_types.w, 3766 bcmOAMEventBHHCCMUnknownMepId)) { 3767 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID; 3768 } 3769 if (SHR_BITGET(event_handler_p->event_types.w, 3770 bcmOAMEventBHHCCMUnknownPeriod)) { 3771 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD; 3772 } 3773 if (SHR_BITGET(event_handler_p->event_types.w, 3774 bcmOAMEventBHHCCMUnknownPriority)) { 3775 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY; 3776 } 3777 if (SHR_BITGET(event_handler_p->event_types.w, 3778 bcmOAMEventBHHCCMRdiClear)) { 3779 event_mask |= BHH_BTE_EVENT_CCM_RDI_CLEAR; 3780 } 3781 if (SHR_BITGET(event_handler_p->event_types.w, 3782 bcmOAMEventBHHCCMUnknownMegLevelClear)) { 3783 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR; 3784 } 3785 if (SHR_BITGET(event_handler_p->event_types.w, 3786 bcmOAMEventBHHCCMUnknownMegIdClear)) { 3787 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR; 3788 } 3789 if (SHR_BITGET(event_handler_p->event_types.w, 3790 bcmOAMEventBHHCCMUnknownMepIdClear)) { 3791 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR; 3792 } 3793 if (SHR_BITGET(event_handler_p->event_types.w, 3794 bcmOAMEventBHHCCMUnknownPeriodClear)) { 3795 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR; 3796 } 3797 if (SHR_BITGET(event_handler_p->event_types.w, 3798 bcmOAMEventBHHCCMUnknownPriorityClear)) { 3799 event_mask |= BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR; 3800 } 3801 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfLos)) { 3802 event_mask |= BHH_BTE_EVENT_CSF_LOS; 3803 } 3804 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfFdi)) { 3805 event_mask |= BHH_BTE_EVENT_CSF_FDI; 3806 } 3807 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfRdi)) { 3808 event_mask |= BHH_BTE_EVENT_CSF_RDI; 3809 } 3810 if (SHR_BITGET(event_handler_p->event_types.w, bcmOAMEventCsfDci)) { 3811 event_mask |= BHH_BTE_EVENT_CSF_DCI; 3812 } 3813 } 3814 3815 /* Update BHH event mask in uKernel */ 3816 if (event_mask != oam_info_p->event_mask) { 3817 /* Send BHH Event Mask message to uC */ 3818 BCM_IF_ERROR_RETURN(_bcm_en_oam_bhh_msg_send_receive 3819 (unit, 3820 MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET, 3821 0, event_mask, 3822 MOS_MSG_SUBCLASS_BHH_EVENT_MASK_SET_REPLY, 3823 &reply_len)); 3824 3825 if (reply_len != 0) { 3826 return BCM_E_INTERNAL; 3827 } 3828 } 3829 3830 oam_info_p->event_mask = event_mask; 3831 3832 return BCM_E_NONE; 3833 } 3834 3835 /* 3836 * Function: 3837 * _bcm_en_oam_bhh_callback_thread 3838 * Purpose: 3839 * Thread to listen for event messages from uController. 3840 * Parameters: 3841 * param - Pointer to BFD info structure. 3842 * Returns: 3843 * None 3844 */ 3845 STATIC void 3846 _bcm_en_oam_bhh_callback_thread(void *param) 3847 { 3848 int rv; 3849 _bcm_oam_info_t *oam_info_p = (_bcm_oam_info_t*)param; 3850 bcm_oam_event_types_t events; 3851 bcm_oam_event_type_t event_type; 3852 bhh_msg_event_t event_msg; 3853 int sess_id; 3854 uint32 event_mask, flags = 0; 3855 _bcm_oam_event_handler_t *event_handler_p; 3856 _bcm_oam_endpoint_t *endpoint_p; 3857 char thread_name[SAL_THREAD_NAME_MAX_LEN]; 3858 3859 thread_name[0] = 0; 3860 LOG_VERBOSE(BSL_LS_SOC_COMMON, 3861 (BSL_META_U(oam_info_p->unit, 3862 "BHH callback thread starting\n"))); 3863 sal_thread_name(oam_info_p->event_thread_id, thread_name, sizeof (thread_name)); 3864 3865 while (1) { 3866 /* Wait on notifications from uController */ 3867 rv = soc_cmic_uc_msg_receive(oam_info_p->unit, oam_info_p->uc_num, 3868 MOS_MSG_CLASS_BHH_EVENT, &event_msg, 3869 sal_sem_FOREVER); 3870 3871 if (BCM_FAILURE(rv)) { 3872 break; /* Thread exit */ 3873 } else { 3874 3875 event_handler_p = oam_info_p->event_handler_list_p; 3876 3877 /* Get data from event message */ 3878 sess_id = 3879 BCM_OAM_BHH_GET_SDK_EP(oam_info_p, ((int)bcm_ntohs(event_msg.s.len))); 3880 3881 if (sess_id < 0 || 3882 sess_id >= oam_info_p->endpoint_count) { 3883 LOG_CLI((BSL_META_U(oam_info_p->unit, 3884 "****** Invalid sess_id:%d ******\n"), sess_id)); 3885 } else { 3886 SET_ENDPOINT(sess_id); 3887 event_mask = bcm_ntohl(event_msg.s.data); 3888 3889 /* Set events */ 3890 sal_memset(&events, 0, sizeof(events)); 3891 3892 if (event_mask & BHH_BTE_EVENT_LB_TIMEOUT) { 3893 /* LOG_CLI((BSL_META_U(oam_info_p->unit, 3894 "****** OAM BHH LB Timeout ******\n")));*/ 3895 3896 if (oam_info_p->event_handler_count[bcmOAMEventBHHLBTimeout] > 0) 3897 SHR_BITSET(events.w, bcmOAMEventBHHLBTimeout); 3898 } 3899 if (event_mask & BHH_BTE_EVENT_LB_DISCOVERY_UPDATE) { 3900 /* LOG_CLI((BSL_META_U(oam_info_p->unit, 3901 "****** OAM BHH LB Discovery Update ******\n")));*/ 3902 if (oam_info_p->event_handler_count[bcmOAMEventBHHLBDiscoveryUpdate] > 0) 3903 SHR_BITSET(events.w, bcmOAMEventBHHLBDiscoveryUpdate); 3904 } 3905 if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT) { 3906 /* LOG_CLI((BSL_META_U(oam_info_p->unit, 3907 "****** OAM BHH CCM Timeout ******\n")));*/ 3908 if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMTimeout] > 0) 3909 SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeout); 3910 } 3911 if (event_mask & BHH_BTE_EVENT_CCM_TIMEOUT_CLEAR) { 3912 if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMTimeoutClear] > 0) 3913 SHR_BITSET(events.w, bcmOAMEventBHHCCMTimeoutClear); 3914 } 3915 if (event_mask & BHH_BTE_EVENT_STATE) { 3916 /* LOG_CLI((BSL_META_U(oam_info_p->unit, 3917 "****** OAM BHH State ******\n")));*/ 3918 if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMState] > 0) 3919 SHR_BITSET(events.w, bcmOAMEventBHHCCMState); 3920 } 3921 3922 if (event_mask & BHH_BTE_EVENT_CCM_RDI) { 3923 /* LOG_CLI((BSL_META_U(oam_info_p->unit, 3924 "****** OAM BHH CCM RDI ******\n")));*/ 3925 if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMRdi] > 0) 3926 SHR_BITSET(events.w, bcmOAMEventBHHCCMRdi); 3927 } 3928 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL) { 3929 /* LOG_CLI((BSL_META_U(oam_info_p->unit, 3930 "****** OAM BHH CCM Unknown MEG Level ******\n")));*/ 3931 if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownMegLevel] > 0) 3932 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevel); 3933 } 3934 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID) { 3935 /* LOG_CLI((BSL_META_U(oam_info_p->unit, 3936 "****** OAM BHH CCM Unknown MEG ID ******\n")));*/ 3937 if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownMegId] > 0) 3938 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegId); 3939 } 3940 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID) { 3941 /* LOG_CLI((BSL_META_U(oam_info_p->unit, 3942 "****** OAM BHH CCM Unknown MEP ID ******\n")));*/ 3943 if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownMepId] > 0) 3944 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepId); 3945 } 3946 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD) { 3947 if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownPeriod] > 0) 3948 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriod); 3949 } 3950 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY) { 3951 if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownPriority] > 0) 3952 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriority); 3953 } 3954 if (event_mask & BHH_BTE_EVENT_CCM_RDI_CLEAR) { 3955 if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMRdiClear] > 0) 3956 SHR_BITSET(events.w, bcmOAMEventBHHCCMRdiClear); 3957 } 3958 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL_CLEAR) { 3959 if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownMegLevelClear] > 0) 3960 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegLevelClear); 3961 } 3962 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID_CLEAR) { 3963 if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownMegIdClear] > 0) 3964 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMegIdClear); 3965 } 3966 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID_CLEAR) { 3967 if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownMepIdClear] > 0) 3968 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownMepIdClear); 3969 } 3970 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD_CLEAR) { 3971 if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownPeriodClear] > 0) 3972 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPeriodClear); 3973 } 3974 if (event_mask & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY_CLEAR) { 3975 if (oam_info_p->event_handler_count[bcmOAMEventBHHCCMUnknownPriorityClear] > 0) 3976 SHR_BITSET(events.w, bcmOAMEventBHHCCMUnknownPriorityClear); 3977 } 3978 if (event_mask & BHH_BTE_EVENT_CSF_LOS) { 3979 if (oam_info_p->event_handler_count[bcmOAMEventCsfLos] > 0) { 3980 SHR_BITSET(events.w, bcmOAMEventCsfLos); 3981 } 3982 } 3983 if (event_mask & BHH_BTE_EVENT_CSF_FDI) { 3984 if (oam_info_p->event_handler_count[bcmOAMEventCsfFdi] > 0) { 3985 SHR_BITSET(events.w, bcmOAMEventCsfFdi); 3986 } 3987 } 3988 if (event_mask & BHH_BTE_EVENT_CSF_RDI) { 3989 if (oam_info_p->event_handler_count[bcmOAMEventCsfRdi] > 0) { 3990 SHR_BITSET(events.w, bcmOAMEventCsfRdi); 3991 } 3992 } 3993 if (event_mask & BHH_BTE_EVENT_CSF_DCI) { 3994 if (oam_info_p->event_handler_count[bcmOAMEventCsfDci] > 0) { 3995 SHR_BITSET(events.w, bcmOAMEventCsfDci); 3996 } 3997 } 3998 3999 4000 /* Loop over registered callbacks, 4001 * If any match the events field, then invoke 4002 */ 4003 for (event_handler_p = oam_info_p->event_handler_list_p; 4004 event_handler_p != NULL; 4005 event_handler_p = event_handler_p->next_p) { 4006 for (event_type = bcmOAMEventBHHLBTimeout; event_type < bcmOAMEventCount; ++event_type) { 4007 if (SHR_BITGET(events.w, event_type)) { 4008 if (SHR_BITGET(event_handler_p->event_types.w, 4009 event_type)) { 4010 event_handler_p->cb(oam_info_p->unit, 4011 flags, 4012 event_type, 4013 endpoint_p->group_index, /* Group index */ 4014 sess_id, /* Endpoint index */ 4015 event_handler_p->user_data); 4016 } 4017 } 4018 } 4019 } 4020 } 4021 } 4022 } 4023 4024 LOG_VERBOSE(BSL_LS_SOC_COMMON, 4025 (BSL_META_U(oam_info_p->unit, 4026 "BHH callback thread exiting\n"))); 4027 oam_info_p->event_thread_id = NULL; 4028 sal_thread_exit(0); 4029 } 4030 4031 /* 4032 * Function: 4033 * bcm_en_oam_loopback_add 4034 * Purpose: 4035 * 4036 * Parameters: 4037 * unit - Device unit number 4038 * Returns: 4039 * None 4040 */ 4041 int 4042 bcm_en_oam_loopback_add(int unit, bcm_oam_loopback_t *loopback_p) 4043 { 4044 _bcm_oam_info_t *oam_info_p; 4045 int result = BCM_E_UNAVAIL; 4046 bhh_sdk_msg_ctrl_loopback_add_t msg; 4047 _bcm_oam_endpoint_t *endpoint_p; 4048 uint8 *buffer, *buffer_ptr; 4049 uint16 buffer_len, reply_len; 4050 uint32 flags = 0; 4051 int sess_id = 0; 4052 4053 SET_OAM_INFO; 4054 4055 CHECK_INIT; 4056 4057 if(oam_info_p->ukernel_not_ready) { 4058 return BCM_E_INIT; 4059 } 4060 4061 BCM_OAM_BHH_VALIDATE_END_POINT(oam_info_p, loopback_p->id); 4062 4063 SET_ENDPOINT(loopback_p->id); 4064 4065 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, loopback_p->id); 4066 4067 /* 4068 * Only BHH is supported 4069 */ 4070 if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLS || 4071 endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 4072 4073 /* 4074 * Convert host space flags to uKernel space flags 4075 */ 4076 4077 if (loopback_p->flags & BCM_OAM_LOOPBACK_TX_ENABLE) { 4078 flags |= BCM_BHH_TX_ENABLE; 4079 } 4080 4081 if (loopback_p->flags & BCM_OAM_BHH_INC_REQUESTING_MEP_TLV) { 4082 flags |= BCM_BHH_INC_REQUESTING_MEP_TLV; 4083 } 4084 4085 if (loopback_p->flags & BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) { 4086 flags |= BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV; 4087 } else if (loopback_p->flags & BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) { 4088 flags |= BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV; 4089 } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MEP_TLV) { 4090 flags |= BCM_BHH_LBM_ICC_MEP_TLV; 4091 } else if (loopback_p->flags & BCM_OAM_BHH_LBM_ICC_MIP_TLV) { 4092 flags |= BCM_BHH_LBM_ICC_MIP_TLV; 4093 } else { 4094 flags |= BCM_BHH_LBM_ICC_MEP_TLV; /* Default */ 4095 } 4096 4097 if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MEP_TLV) { 4098 flags |= BCM_BHH_LBR_ICC_MEP_TLV; 4099 } else if (loopback_p->flags & BCM_OAM_BHH_LBR_ICC_MIP_TLV) { 4100 flags |= BCM_BHH_LBR_ICC_MIP_TLV; 4101 } 4102 4103 sal_memset(&msg, 0, sizeof(msg)); 4104 msg.flags = flags; 4105 msg.sess_id = sess_id; 4106 msg.int_pri = loopback_p->int_pri; 4107 msg.pkt_pri = loopback_p->pkt_pri; 4108 4109 /* 4110 * Set period 4111 */ 4112 msg.period = en_ccm_periods[_bcm_en_oam_quantize_ccm_period(loopback_p->period)]; 4113 4114 /* 4115 * Check TTL 4116 */ 4117 if (loopback_p->ttl == 0 || loopback_p->ttl > 255) { 4118 return BCM_E_PARAM; 4119 } 4120 4121 if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv && 4122 endpoint_p->vccv_type == bcmOamBhhVccvTtl) { 4123 4124 msg.ttl = 1; /* Only TTL 1 is valid */ 4125 } else { 4126 msg.ttl = loopback_p->ttl; 4127 } 4128 4129 /* Pack control message data into DMA buffer */ 4130 buffer = oam_info_p->dma_buffer; 4131 buffer_ptr = bhh_sdk_msg_ctrl_loopback_add_pack(buffer, &msg); 4132 buffer_len = buffer_ptr - buffer; 4133 4134 /* Send BHH Session Update message to uC */ 4135 BCM_IF_ERROR_RETURN 4136 (_bcm_en_oam_bhh_msg_send_receive(unit, 4137 MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD, 4138 buffer_len, 0, 4139 MOS_MSG_SUBCLASS_BHH_LOOPBACK_ADD_REPLY, 4140 &reply_len)); 4141 if (reply_len != 0) { 4142 result = BCM_E_INTERNAL; 4143 } else { 4144 result = BCM_E_NONE; 4145 } 4146 } 4147 else { 4148 return BCM_E_UNAVAIL; 4149 } 4150 4151 return result; 4152 } 4153 4154 4155 4156 /* 4157 * Function: 4158 * bcm_en_oam_loopback_get 4159 * Purpose: 4160 * 4161 * Parameters: 4162 * unit - Device unit number 4163 * Returns: 4164 * None 4165 */ 4166 int 4167 bcm_en_oam_loopback_get(int unit, bcm_oam_loopback_t *loopback_p) 4168 { 4169 _bcm_oam_info_t *oam_info_p; 4170 int result = BCM_E_UNAVAIL; 4171 bhh_sdk_msg_ctrl_loopback_get_t msg; 4172 _bcm_oam_endpoint_t *endpoint_p; 4173 uint8 *buffer, *buffer_ptr; 4174 uint16 buffer_len, reply_len; 4175 int sess_id = 0; 4176 4177 SET_OAM_INFO; 4178 4179 CHECK_INIT; 4180 4181 if(oam_info_p->ukernel_not_ready) { 4182 return BCM_E_INIT; 4183 } 4184 4185 BCM_OAM_BHH_VALIDATE_END_POINT(oam_info_p, loopback_p->id); 4186 4187 SET_ENDPOINT(loopback_p->id); 4188 4189 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, loopback_p->id); 4190 4191 /* 4192 * Only BHH is supported 4193 */ 4194 if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLS || 4195 endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 4196 4197 sal_memset(&msg, 0, sizeof(msg)); 4198 /* Send BHH Session Update message to uC */ 4199 BCM_IF_ERROR_RETURN 4200 (_bcm_en_oam_bhh_msg_send_receive(unit, 4201 MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET, 4202 sess_id, 0, 4203 MOS_MSG_SUBCLASS_BHH_LOOPBACK_GET_REPLY, 4204 &reply_len)); 4205 4206 /* Pack control message data into DMA buffer */ 4207 buffer = oam_info_p->dma_buffer; 4208 buffer_ptr = bhh_sdk_msg_ctrl_loopback_get_unpack(buffer, &msg); 4209 buffer_len = buffer_ptr - buffer; 4210 4211 if (reply_len != buffer_len) { 4212 result = BCM_E_INTERNAL; 4213 } else { 4214 /* 4215 * Convert kernel space flags to host space flags 4216 */ 4217 if (msg.flags & BCM_BHH_INC_REQUESTING_MEP_TLV) { 4218 loopback_p->flags |= BCM_OAM_BHH_INC_REQUESTING_MEP_TLV; 4219 } 4220 4221 if (msg.flags & BCM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV) { 4222 loopback_p->flags |= BCM_OAM_BHH_LBM_INGRESS_DISCOVERY_MEP_TLV; 4223 } else if (msg.flags & BCM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV) { 4224 loopback_p->flags |= BCM_OAM_BHH_LBM_EGRESS_DISCOVERY_MEP_TLV; 4225 } else if (msg.flags & BCM_BHH_LBM_ICC_MEP_TLV) { 4226 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MEP_TLV; 4227 } else if (msg.flags & BCM_BHH_LBM_ICC_MIP_TLV) { 4228 loopback_p->flags |= BCM_OAM_BHH_LBM_ICC_MIP_TLV; 4229 } 4230 4231 if (msg.flags & BCM_BHH_LBR_ICC_MEP_TLV) { 4232 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MEP_TLV; 4233 } else if (msg.flags & BCM_BHH_LBR_ICC_MIP_TLV) { 4234 loopback_p->flags |= BCM_OAM_BHH_LBR_ICC_MIP_TLV; 4235 } 4236 4237 if (msg.flags & BCM_BHH_TX_ENABLE) { 4238 loopback_p->flags |= BCM_OAM_LOOPBACK_TX_ENABLE; 4239 } 4240 4241 loopback_p->period = msg.period; 4242 loopback_p->ttl = msg.ttl; 4243 loopback_p->discovered_me.flags = msg.discovery_flags; 4244 loopback_p->discovered_me.name = msg.discovery_id; 4245 loopback_p->discovered_me.ttl = msg.discovery_ttl; 4246 loopback_p->rx_count = msg.rx_count; 4247 loopback_p->tx_count = msg.tx_count; 4248 loopback_p->drop_count = msg.drop_count; 4249 loopback_p->unexpected_response = msg.unexpected_response; 4250 loopback_p->out_of_sequence = msg.out_of_sequence; 4251 loopback_p->local_mipid_missmatch = msg.local_mipid_missmatch; 4252 loopback_p->remote_mipid_missmatch = msg.remote_mipid_missmatch; 4253 loopback_p->invalid_target_mep_tlv = msg.invalid_target_mep_tlv; 4254 loopback_p->invalid_mep_tlv_subtype = msg.invalid_mep_tlv_subtype; 4255 loopback_p->invalid_tlv_offset = msg.invalid_tlv_offset; 4256 loopback_p->int_pri = msg.int_pri; 4257 loopback_p->pkt_pri = msg.pkt_pri; 4258 4259 result = BCM_E_NONE; 4260 } 4261 } 4262 else { 4263 return BCM_E_UNAVAIL; 4264 } 4265 4266 return result; 4267 } 4268 4269 /* 4270 * Function: 4271 * bcm_en_oam_loopback_delete 4272 * Purpose: 4273 * 4274 * Parameters: 4275 * unit - Device unit number 4276 * Returns: 4277 * None 4278 */ 4279 int 4280 bcm_en_oam_loopback_delete(int unit, bcm_oam_loopback_t *loopback_p) 4281 { 4282 _bcm_oam_info_t *oam_info_p; 4283 int result = BCM_E_UNAVAIL; 4284 shr_bhh_msg_ctrl_loopback_delete_t msg; 4285 _bcm_oam_endpoint_t *endpoint_p; 4286 uint8 *buffer, *buffer_ptr; 4287 uint16 buffer_len, reply_len; 4288 int sess_id = 0; 4289 4290 SET_OAM_INFO; 4291 4292 CHECK_INIT; 4293 4294 if(oam_info_p->ukernel_not_ready) { 4295 return BCM_E_INIT; 4296 } 4297 4298 BCM_OAM_BHH_VALIDATE_END_POINT(oam_info_p, loopback_p->id); 4299 4300 SET_ENDPOINT(loopback_p->id); 4301 4302 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, loopback_p->id); 4303 4304 /* 4305 * Only BHH is supported 4306 */ 4307 if (endpoint_p->type == bcmOAMEndpointTypeBHHMPLS || 4308 endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv) { 4309 4310 msg.sess_id = sess_id; 4311 4312 /* Pack control message data into DMA buffer */ 4313 buffer = oam_info_p->dma_buffer; 4314 buffer_ptr = shr_bhh_msg_ctrl_loopback_delete_pack(buffer, &msg); 4315 buffer_len = buffer_ptr - buffer; 4316 4317 /* Send BHH Session Update message to uC */ 4318 BCM_IF_ERROR_RETURN 4319 (_bcm_en_oam_bhh_msg_send_receive(unit, 4320 MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE, 4321 buffer_len, 0, 4322 MOS_MSG_SUBCLASS_BHH_LOOPBACK_DELETE_REPLY, 4323 &reply_len)); 4324 if (reply_len != 0) { 4325 result = BCM_E_INTERNAL; 4326 } else { 4327 result = BCM_E_NONE; 4328 } 4329 } 4330 else { 4331 return BCM_E_UNAVAIL; 4332 } 4333 4334 return result; 4335 } 4336 4337 /* 4338 * Function: 4339 * bcm_en_oam_csf_add 4340 * Purpose: 4341 * Start CSF PDU transmission 4342 * Parameters: 4343 * unit - (IN) Unit number. 4344 * csf_ptr - (INOUT) CSF object 4345 * Returns: 4346 * BCM_E_XXX 4347 * Notes: 4348 */ 4349 int bcm_en_oam_csf_add(int unit, bcm_oam_csf_t *csf_p) 4350 { 4351 _bcm_oam_info_t *oam_info_p; 4352 _bcm_oam_endpoint_t *endpoint_p; 4353 bhh_sdk_msg_ctrl_csf_add_t msg; 4354 uint8 *buffer, *buffer_ptr; 4355 uint16 buffer_len, reply_len; 4356 int sess_id = 0; 4357 int rv = BCM_E_NONE; 4358 4359 SET_OAM_INFO; 4360 CHECK_INIT; 4361 if(oam_info_p->ukernel_not_ready) { 4362 return BCM_E_INIT; 4363 } 4364 4365 BCM_OAM_BHH_VALIDATE_END_POINT(oam_info_p, csf_p->id); 4366 SET_ENDPOINT(csf_p->id); 4367 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, csf_p->id); 4368 4369 if ((csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1S) && 4370 (csf_p->period != BCM_OAM_ENDPOINT_CCM_PERIOD_1M)) { 4371 /* Only 1S and 1M are supported */ 4372 return BCM_E_PARAM; 4373 } 4374 4375 /* 4376 * Only BHH is supported 4377 */ 4378 if (endpoint_p->type != bcmOAMEndpointTypeBHHMPLS && 4379 endpoint_p->type != bcmOAMEndpointTypeBHHMPLSVccv) { 4380 return BCM_E_UNAVAIL; 4381 } 4382 4383 sal_memset(&msg, 0, sizeof(msg)); 4384 msg.sess_id = sess_id; 4385 msg.int_pri = csf_p->int_pri; 4386 msg.pkt_pri = csf_p->pkt_pri; 4387 4388 switch(csf_p->type) { 4389 case BCM_OAM_CSF_LOS: 4390 msg.type = SHR_CSF_TYPE_LOS; 4391 break; 4392 4393 case BCM_OAM_CSF_FDI: 4394 msg.type = SHR_CSF_TYPE_FDI; 4395 break; 4396 4397 case BCM_OAM_CSF_RDI: 4398 msg.type = SHR_CSF_TYPE_RDI; 4399 break; 4400 4401 case BCM_OAM_CSF_DCI: 4402 msg.type = SHR_CSF_TYPE_DCI; 4403 break; 4404 4405 default: 4406 return BCM_E_PARAM; 4407 } 4408 4409 /* 4410 * Set period 4411 */ 4412 msg.period = csf_p->period; 4413 4414 /* Pack control message data into DMA buffer */ 4415 buffer = oam_info_p->dma_buffer; 4416 buffer_ptr = bhh_sdk_msg_ctrl_csf_add_pack(buffer, &msg); 4417 buffer_len = buffer_ptr - buffer; 4418 4419 /* Send BHH Session Update message to uC */ 4420 rv = _bcm_en_oam_bhh_msg_send_receive(unit, 4421 MOS_MSG_SUBCLASS_BHH_CSF_ADD, 4422 buffer_len, 0, 4423 MOS_MSG_SUBCLASS_BHH_CSF_ADD_REPLY, 4424 &reply_len); 4425 4426 if(BCM_SUCCESS(rv) && (reply_len != 0)) { 4427 rv = BCM_E_INTERNAL; 4428 } 4429 4430 return rv; 4431 } 4432 4433 /* 4434 * Function: 4435 * bcm_en_oam_csf_get 4436 * Purpose: 4437 * Get CSF info 4438 * Parameters: 4439 * unit - (IN) Unit number. 4440 * csf_ptr - (OUT) CSF object 4441 * Returns: 4442 * BCM_E_XXX 4443 * Notes: 4444 */ 4445 int bcm_en_oam_csf_get(int unit, bcm_oam_csf_t *csf_p) 4446 { 4447 _bcm_oam_info_t *oam_info_p; 4448 bhh_sdk_msg_ctrl_csf_get_t msg; 4449 _bcm_oam_endpoint_t *endpoint_p; 4450 uint8 *buffer, *buffer_ptr; 4451 uint16 buffer_len, reply_len; 4452 int sess_id = 0; 4453 int rv = BCM_E_NONE; 4454 4455 SET_OAM_INFO; 4456 CHECK_INIT; 4457 if(oam_info_p->ukernel_not_ready) { 4458 return BCM_E_INIT; 4459 } 4460 4461 BCM_OAM_BHH_VALIDATE_END_POINT(oam_info_p, csf_p->id); 4462 SET_ENDPOINT(csf_p->id); 4463 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, csf_p->id); 4464 4465 4466 /* 4467 * Only BHH is supported 4468 */ 4469 if (endpoint_p->type != bcmOAMEndpointTypeBHHMPLS && 4470 endpoint_p->type != bcmOAMEndpointTypeBHHMPLSVccv) { 4471 return BCM_E_UNAVAIL; 4472 } 4473 4474 /* Send BHH Session Update message to uC */ 4475 sal_memset(&msg, 0, sizeof(msg)); 4476 rv = _bcm_en_oam_bhh_msg_send_receive(unit, 4477 MOS_MSG_SUBCLASS_BHH_CSF_GET, 4478 sess_id, 0, 4479 MOS_MSG_SUBCLASS_BHH_CSF_GET_REPLY, 4480 &reply_len); 4481 if(BCM_FAILURE(rv)) { 4482 LOG_ERROR(BSL_LS_BCM_OAM, 4483 (BSL_META_U(unit, 4484 "OAM(unit %d) Error: Endpoint EP=%d %s.\n"), 4485 unit, csf_p->id, bcm_errmsg(rv))); 4486 return (rv); 4487 } 4488 4489 /* Pack control message data into DMA buffer */ 4490 buffer = oam_info_p->dma_buffer; 4491 buffer_ptr = bhh_sdk_msg_ctrl_csf_get_unpack(buffer, &msg); 4492 buffer_len = buffer_ptr - buffer; 4493 4494 4495 if (reply_len != buffer_len) { 4496 return BCM_E_INTERNAL; 4497 } 4498 4499 switch(msg.type) { 4500 case SHR_CSF_TYPE_LOS: 4501 csf_p->type = BCM_OAM_CSF_LOS; 4502 break; 4503 4504 case SHR_CSF_TYPE_FDI: 4505 csf_p->type = BCM_OAM_CSF_FDI; 4506 break; 4507 4508 case SHR_CSF_TYPE_RDI: 4509 csf_p->type = BCM_OAM_CSF_RDI; 4510 break; 4511 4512 case SHR_CSF_TYPE_DCI: 4513 csf_p->type = BCM_OAM_CSF_DCI; 4514 break; 4515 4516 default: 4517 return BCM_E_INTERNAL; 4518 } 4519 4520 csf_p->period = msg.period; 4521 csf_p->flags = msg.flags; 4522 csf_p->pkt_pri = msg.pkt_pri; 4523 csf_p->int_pri = msg.int_pri; 4524 4525 return BCM_E_NONE; 4526 4527 } 4528 4529 /* 4530 * Function: 4531 * bcm_en_oam_csf_delete 4532 * Purpose: 4533 * Stop CSF PDU transmission 4534 * Parameters: 4535 * unit - (IN Unit number. 4536 * csf_ptr - (IN) CSF object 4537 * Returns: 4538 * BCM_E_XXX 4539 * Notes: 4540 */ 4541 int bcm_en_oam_csf_delete(int unit, bcm_oam_csf_t *csf_p) 4542 { 4543 _bcm_oam_info_t *oam_info_p; 4544 _bcm_oam_endpoint_t *endpoint_p; 4545 uint16 reply_len; 4546 int sess_id; 4547 int rv = BCM_E_NONE; 4548 4549 SET_OAM_INFO; 4550 CHECK_INIT; 4551 if(oam_info_p->ukernel_not_ready) { 4552 return BCM_E_INIT; 4553 } 4554 4555 BCM_OAM_BHH_VALIDATE_END_POINT(oam_info_p, csf_p->id); 4556 SET_ENDPOINT(csf_p->id); 4557 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, csf_p->id); 4558 4559 /* 4560 * Only BHH is supported 4561 */ 4562 if (endpoint_p->type != bcmOAMEndpointTypeBHHMPLS && 4563 endpoint_p->type != bcmOAMEndpointTypeBHHMPLSVccv) { 4564 return BCM_E_UNAVAIL; 4565 } 4566 4567 /* Send BHH Session Update message to uC */ 4568 rv = _bcm_en_oam_bhh_msg_send_receive(unit, 4569 MOS_MSG_SUBCLASS_BHH_CSF_DELETE, 4570 sess_id, 0, 4571 MOS_MSG_SUBCLASS_BHH_CSF_DELETE_REPLY, 4572 &reply_len); 4573 return (rv); 4574 } 4575 #endif /* defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) */ 4576 4577 4578 /* 4579 * Function: 4580 * bcm_en_oam_detach 4581 * Purpose: 4582 * Shut down the OAM subsystem 4583 * Parameters: 4584 * unit - (IN) Unit number. 4585 * Returns: 4586 * BCM_E_XXX 4587 * Notes: 4588 */ 4589 int 4590 bcm_en_oam_detach( 4591 int unit) 4592 { 4593 _bcm_oam_info_t *oam_info_p; 4594 bcm_port_t port_index; 4595 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 4596 int rv; 4597 uint16 reply_len; 4598 sal_usecs_t timeout; 4599 int status; 4600 #endif 4601 4602 SET_OAM_INFO; 4603 4604 if (!oam_info_p->initialized) 4605 { 4606 return BCM_E_NONE; 4607 } 4608 4609 /* Disable CCM transmission */ 4610 4611 SOC_IF_ERROR_RETURN(WRITE_OAM_TX_CONTROLr(unit, 0)); 4612 4613 /* Disable OAM message reception on all ports */ 4614 4615 PBMP_ALL_ITER(unit, port_index) 4616 { 4617 BCM_IF_ERROR_RETURN(bcm_esw_port_control_set(unit, 4618 port_index, bcmPortControlOAMEnable, 0)); 4619 } 4620 4621 /* 4622 * BHH specific 4623 */ 4624 if (soc_feature(unit, soc_feature_bhh)) { 4625 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 4626 if (SOC_IS_KATANAX(unit)) { 4627 if (oam_info_p->ukernel_not_ready == 0) { 4628 /* 4629 * Event Handler thread exit signal 4630 */ 4631 timeout = sal_time_usecs() + 5000000; 4632 while (NULL != oam_info_p->event_thread_id) { 4633 soc_cmic_uc_msg_receive_cancel(unit, oam_info_p->uc_num, 4634 MOS_MSG_CLASS_BHH_EVENT); 4635 4636 if (sal_time_usecs() < timeout) { 4637 /*give some time to already running bhh callback thread 4638 * to schedule and exit */ 4639 sal_usleep(10000); 4640 } else { 4641 /*timeout*/ 4642 LOG_ERROR(BSL_LS_BCM_OAM, 4643 (BSL_META_U(unit, 4644 "BHH event thread did not exit.\n"))); 4645 return BCM_E_INTERNAL; 4646 } 4647 } 4648 4649 /* 4650 * Send BHH Uninit message to uC 4651 * Ignore error since that may indicate uKernel was reloaded. 4652 */ 4653 #if defined(BCM_WARM_BOOT_SUPPORT) 4654 if (!SOC_WARM_BOOT(unit)) { 4655 #endif 4656 SOC_IF_ERROR_RETURN(soc_uc_status(unit, oam_info_p->uc_num, &status)); 4657 if (status) { 4658 rv = _bcm_en_oam_bhh_msg_send_receive(unit, 4659 MOS_MSG_SUBCLASS_BHH_UNINIT, 4660 0, 0, 4661 MOS_MSG_SUBCLASS_BHH_UNINIT_REPLY, 4662 &reply_len); 4663 if (BCM_SUCCESS(rv) && (reply_len != 0)) { 4664 return BCM_E_INTERNAL; 4665 } 4666 } 4667 #if defined(BCM_WARM_BOOT_SUPPORT) 4668 } 4669 #endif 4670 4671 /* 4672 * Delete CPU COS queue mapping entries for BHH packets 4673 */ 4674 if (oam_info_p->cpu_cosq_ach_error_index >= 0) { 4675 BCM_IF_ERROR_RETURN 4676 (bcm_esw_rx_cosq_mapping_delete(unit, 4677 oam_info_p->cpu_cosq_ach_error_index)); 4678 oam_info_p->cpu_cosq_ach_error_index = -1; 4679 } 4680 if (oam_info_p->cpu_cosq_invalid_error_index >= 0) { 4681 BCM_IF_ERROR_RETURN 4682 (bcm_esw_rx_cosq_mapping_delete(unit, 4683 oam_info_p->cpu_cosq_invalid_error_index)); 4684 oam_info_p->cpu_cosq_invalid_error_index = -1; 4685 } 4686 } 4687 } 4688 #endif 4689 } 4690 4691 #ifdef BCM_KATANA_SUPPORT 4692 if (SOC_IS_KATANA(unit)) { 4693 soc_kt_oam_handler_register(unit, NULL); 4694 } else 4695 #endif /* BCM_KATANA_SUPPORT */ 4696 { 4697 soc_enduro_oam_handler_register(unit, NULL); 4698 } 4699 _bcm_en_oam_event_unregister_all(oam_info_p); 4700 4701 BCM_IF_ERROR_RETURN(bcm_en_oam_group_destroy_all(unit)); 4702 4703 /* De-initialize the ING_SERVICE_PRI_MAP table */ 4704 if (ing_pri_map_profile[unit]) { 4705 SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit, 4706 ing_pri_map_profile[unit])); 4707 sal_free(ing_pri_map_profile[unit]); 4708 ing_pri_map_profile[unit] = NULL; 4709 } 4710 4711 #if defined(BCM_KATANA_SUPPORT) 4712 if (SOC_IS_KATANAX(unit)) { 4713 /* De-initialize the OAM_OPCODE_PROFILE table */ 4714 SOC_IF_ERROR_RETURN(soc_profile_mem_destroy(unit, 4715 oam_opcode_profile[unit])); 4716 } 4717 #endif /* BCM_KATANA_SUPPORT */ 4718 4719 _bcm_en_oam_free_memory(unit, oam_info_p); 4720 sal_memset(oam_info_p, 0 , sizeof(_bcm_oam_info_t)); 4721 4722 return BCM_E_NONE; 4723 } 4724 4725 static void _bcm_en_oam_group_name_mangle(uint8 *name_p, 4726 uint8 *mangled_name_p) 4727 { 4728 uint8 *byte_p = name_p + BCM_OAM_GROUP_NAME_LENGTH - 1; 4729 int bytes_left = BCM_OAM_GROUP_NAME_LENGTH; 4730 4731 while (bytes_left > 0) 4732 { 4733 *mangled_name_p = *byte_p; 4734 4735 ++mangled_name_p; 4736 --byte_p; 4737 --bytes_left; 4738 } 4739 } 4740 4741 /* 4742 * Function: 4743 * bcm_en_oam_group_create 4744 * Purpose: 4745 * Create or replace an OAM group object 4746 * Parameters: 4747 * unit - (IN) Unit number. 4748 * group_info - (IN/OUT) Pointer to an OAM group structure 4749 * Returns: 4750 * BCM_E_XXX 4751 * Notes: 4752 */ 4753 int 4754 bcm_en_oam_group_create( 4755 int unit, 4756 bcm_oam_group_info_t *group_info) 4757 { 4758 _bcm_oam_info_t *oam_info_p; 4759 _bcm_oam_group_t *group_p; 4760 int replace; 4761 int group_index = 0; 4762 int copy_to_cpu = 0; 4763 4764 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 4765 bhh_sdk_msg_ctrl_sess_set_t msg_sess; 4766 uint8 *buffer, *buffer_ptr; 4767 uint16 buffer_len, reply_len; 4768 uint32 session_flags = 0; 4769 _bcm_oam_endpoint_t *endpoint_p; 4770 int endpoint_index; 4771 #endif 4772 4773 maid_reduction_entry_t maid_reduction_entry; 4774 ma_state_entry_t ma_state_entry; 4775 uint8 mangled_group_name[MANGLED_GROUP_NAME_LENGTH]; 4776 4777 SET_OAM_INFO; 4778 4779 CHECK_INIT; 4780 4781 replace = group_info->flags & BCM_OAM_GROUP_REPLACE; 4782 4783 if (group_info->flags & BCM_OAM_GROUP_WITH_ID) 4784 { 4785 if (soc_feature(unit, soc_feature_oam_lookup_bypass_cpu_tx_packets)) 4786 { 4787 if(group_info->id == 0) 4788 { 4789 return BCM_E_PARAM; 4790 } 4791 4792 } 4793 group_index = group_info->id; 4794 4795 VALIDATE_GROUP_INDEX(group_index); 4796 4797 if (!replace && (oam_info_p->groups[group_index].in_use)) 4798 { 4799 return BCM_E_EXISTS; 4800 } 4801 } 4802 else 4803 { 4804 if (replace) 4805 { 4806 return BCM_E_PARAM; 4807 } 4808 4809 if (soc_feature(unit, soc_feature_oam_lookup_bypass_cpu_tx_packets)) { 4810 group_index = 1; 4811 } 4812 for (; group_index < oam_info_p->group_count; 4813 ++group_index) 4814 { 4815 if (!oam_info_p->groups[group_index].in_use) 4816 { 4817 break; 4818 } 4819 } 4820 4821 if (group_index >= oam_info_p->group_count) 4822 { 4823 return BCM_E_FULL; 4824 } 4825 4826 group_info->id = group_index; 4827 } 4828 4829 SET_GROUP(group_index); 4830 4831 memcpy(group_p->name, group_info->name, BCM_OAM_GROUP_NAME_LENGTH); 4832 4833 /* MAID_REDUCTION entry */ 4834 4835 _bcm_en_oam_group_name_mangle(group_p->name, mangled_group_name); 4836 4837 sal_memset(&maid_reduction_entry, 0, sizeof(maid_reduction_entry_t)); 4838 4839 soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, REDUCED_MAIDf, 4840 soc_draco_crc32(mangled_group_name, MANGLED_GROUP_NAME_LENGTH)); 4841 4842 soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, SW_RDIf, 4843 (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) ? 1 : 0); 4844 4845 if (soc_feature(unit, soc_feature_bhh)) { 4846 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 4847 /* Send message to uC to set the Soft RDI, if RDI flag is set */ 4848 if (group_info->flags & BCM_OAM_GROUP_REMOTE_DEFECT_TX) { 4849 4850 /* Get the endpoint info of the group */ 4851 for (endpoint_index = 0; endpoint_index < oam_info_p->endpoint_count; 4852 ++endpoint_index) { 4853 SET_ENDPOINT(endpoint_index); 4854 4855 if (endpoint_p->in_use && endpoint_p->group_index == group_index) { 4856 4857 /* Set the RDI flag in session bits */ 4858 session_flags |= SHR_BHH_SESS_SET_F_RDI; 4859 4860 /* Get the session is from endpoint */ 4861 msg_sess.sess_id = 4862 BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, 4863 endpoint_index); 4864 4865 /* Pack control message data into DMA buffer */ 4866 msg_sess.flags = session_flags; 4867 4868 buffer = oam_info_p->dma_buffer; 4869 buffer_ptr = bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess); 4870 buffer_len = buffer_ptr - buffer; 4871 4872 /* Send BHH Session Update message to uC */ 4873 BCM_IF_ERROR_RETURN 4874 (_bcm_en_oam_bhh_msg_send_receive(unit, 4875 MOS_MSG_SUBCLASS_BHH_SESS_SET, 4876 buffer_len, 0, 4877 MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY, 4878 &reply_len)); 4879 if (reply_len != 0) { 4880 return BCM_E_INTERNAL; 4881 } 4882 } 4883 } 4884 } 4885 #endif 4886 } 4887 copy_to_cpu = ((group_info->flags & BCM_OAM_GROUP_COPY_TO_CPU) ? 1 : 0); 4888 soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, 4889 COPY_TO_CPUf, copy_to_cpu); 4890 4891 soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, VALIDf, 1); 4892 4893 SOC_IF_ERROR_RETURN(WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL, 4894 group_index, &maid_reduction_entry)); 4895 4896 /* MA_STATE entry */ 4897 sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t)); 4898 4899 if (replace) { 4900 /* Keep defect status if group is being replaced */ 4901 SOC_IF_ERROR_RETURN(READ_MA_STATEm(unit, MEM_BLOCK_ALL, group_index, 4902 &ma_state_entry)); 4903 } 4904 4905 soc_MA_STATEm_field32_set(unit, &ma_state_entry, LOWESTALARMPRIf, 4906 group_info->lowest_alarm_priority); 4907 4908 soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, 1); 4909 4910 SOC_IF_ERROR_RETURN(WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group_index, 4911 &ma_state_entry)); 4912 4913 /* Local control block */ 4914 4915 group_p->in_use = 1; 4916 4917 #ifdef BCM_WARM_BOOT_SUPPORT 4918 SOC_CONTROL_LOCK(unit); 4919 SOC_CONTROL(unit)->scache_dirty = 1; 4920 SOC_CONTROL_UNLOCK(unit); 4921 #endif 4922 4923 return BCM_E_NONE; 4924 } 4925 4926 static int _bcm_en_oam_read_clear_faults(int unit, int entry_index, 4927 _bcm_oam_fault_t *faults, soc_mem_t mem, uint32 *entry_p, 4928 uint32 *fault_bits_p, uint32 *persistent_fault_bits_p, 4929 uint32 clear_persistent_fault_bits) 4930 { 4931 _bcm_oam_fault_t *fault_p; 4932 uint32 ccm_read_control_reg_value = 0; 4933 uint32 clear_mask = 0; /* Mask to clear persistent faults*/ 4934 4935 for (fault_p = faults; fault_p->mask != 0; ++fault_p) 4936 { 4937 /* Current fault state */ 4938 4939 if (soc_mem_field32_get(unit, mem, entry_p, 4940 fault_p->current_field) != 0) 4941 { 4942 *fault_bits_p |= fault_p->mask; 4943 } 4944 4945 /* Sticky fault state */ 4946 4947 if (soc_mem_field32_get(unit, mem, entry_p, 4948 fault_p->sticky_field) != 0) 4949 { 4950 *persistent_fault_bits_p |= fault_p->mask; 4951 4952 /* Clear persistent faults if requested */ 4953 4954 if (clear_persistent_fault_bits) 4955 { 4956 clear_mask |= fault_p->clear_sticky_mask; 4957 } 4958 } 4959 } 4960 4961 /* If any clear bits were set, do the clear now */ 4962 4963 if (clear_persistent_fault_bits && clear_mask) 4964 { 4965 soc_reg_field_set(unit, CCM_READ_CONTROLr, 4966 &ccm_read_control_reg_value, BITS_TO_CLEARf, clear_mask); 4967 4968 soc_reg_field_set(unit, CCM_READ_CONTROLr, 4969 &ccm_read_control_reg_value, ENABLE_CLEARf, 1); 4970 /* 4971 * MA_STATE table, MEMORYf should be 0. 4972 */ 4973 if (mem == MA_STATEm) { 4974 soc_reg_field_set(unit, CCM_READ_CONTROLr, 4975 &ccm_read_control_reg_value, MEMORYf, 0); 4976 } else { 4977 soc_reg_field_set(unit, CCM_READ_CONTROLr, 4978 &ccm_read_control_reg_value, MEMORYf, 1); 4979 } 4980 4981 soc_reg_field_set(unit, CCM_READ_CONTROLr, 4982 &ccm_read_control_reg_value, INDEXf, entry_index); 4983 4984 SOC_IF_ERROR_RETURN(WRITE_CCM_READ_CONTROLr(unit, 4985 ccm_read_control_reg_value)); 4986 } 4987 4988 return BCM_E_NONE; 4989 } 4990 4991 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 4992 /* 4993 * Function: 4994 * _bcm_en_oam_get_group_sw_rdi 4995 * Purpose: 4996 * Get OAM group SW RDI information. 4997 * Parameters: 4998 * unit - (IN) BCM device number 4999 * group_index - (IN) Group hardware table index 5000 * group_sw_rdi - (OUT) Pointer to group SW RDI 5001 * Returns: 5002 * BCM_E_NONE - No errors. 5003 * BCM_E_XXX - Otherwise. 5004 */ 5005 STATIC int 5006 _bcm_en_oam_get_group_sw_rdi(int unit, bcm_oam_group_t group_index, 5007 uint8 *group_sw_rdi) 5008 { 5009 maid_reduction_entry_t maid_reduction_entry; /* MAID reduction entry. */ 5010 5011 BCM_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, 5012 group_index, 5013 &maid_reduction_entry)); 5014 5015 if (1 == soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry, 5016 SW_RDIf)) { 5017 *group_sw_rdi = 1; 5018 } 5019 return (BCM_E_NONE); 5020 } 5021 #endif 5022 5023 static int _bcm_en_oam_get_group(int unit, int group_index, 5024 _bcm_oam_group_t *group_p, bcm_oam_group_info_t *group_info) 5025 { 5026 maid_reduction_entry_t maid_reduction_entry; 5027 ma_state_entry_t ma_state_entry; 5028 5029 group_info->id = group_index; 5030 5031 if (!(group_info->flags & BCM_OAM_GROUP_GET_FAULTS_ONLY)) { 5032 memcpy(group_info->name, group_p->name, BCM_OAM_GROUP_NAME_LENGTH); 5033 5034 /* MAID_REDUCTION entry */ 5035 5036 SOC_IF_ERROR_RETURN(READ_MAID_REDUCTIONm(unit, MEM_BLOCK_ANY, group_index, 5037 &maid_reduction_entry)); 5038 5039 if (soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry, 5040 SW_RDIf) != 0) 5041 { 5042 group_info->flags |= BCM_OAM_GROUP_REMOTE_DEFECT_TX; 5043 } 5044 5045 if (soc_MAID_REDUCTIONm_field32_get(unit, &maid_reduction_entry, 5046 COPY_TO_CPUf) != 0) 5047 { 5048 group_info->flags |= BCM_OAM_GROUP_COPY_TO_CPU; 5049 } 5050 } else { 5051 group_info->flags &= ~BCM_OAM_GROUP_GET_FAULTS_ONLY; 5052 } 5053 5054 /* MA_STATE entry */ 5055 5056 SOC_IF_ERROR_RETURN(READ_MA_STATEm(unit, MEM_BLOCK_ANY, group_index, 5057 &ma_state_entry)); 5058 5059 /* Get the Lowest Alarm Priority value*/ 5060 group_info->lowest_alarm_priority = 5061 soc_MA_STATEm_field32_get(unit, &ma_state_entry, LOWESTALARMPRIf); 5062 5063 return _bcm_en_oam_read_clear_faults(unit, group_index, en_group_faults, 5064 MA_STATEm, (uint32 *) &ma_state_entry, &group_info->faults, 5065 &group_info->persistent_faults, group_info->clear_persistent_faults); 5066 } 5067 5068 /* 5069 * Function: 5070 * bcm_en_oam_group_get 5071 * Purpose: 5072 * Get an OAM group object 5073 * Parameters: 5074 * unit - (IN) Unit number. 5075 * group - (IN) The ID of the group object to get 5076 * group_info - (OUT) Pointer to an OAM group structure to receive the data 5077 * Returns: 5078 * BCM_E_XXX 5079 * Notes: 5080 */ 5081 int 5082 bcm_en_oam_group_get( 5083 int unit, 5084 bcm_oam_group_t group, 5085 bcm_oam_group_info_t *group_info) 5086 { 5087 _bcm_oam_info_t *oam_info_p; 5088 _bcm_oam_group_t *group_p; 5089 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 5090 bhh_sdk_msg_ctrl_sess_get_t msg; 5091 uint8 *buffer, *buffer_ptr; 5092 uint16 buffer_len, reply_len; 5093 int sess_id = 0; 5094 _bcm_oam_endpoint_t *endpoint_p; 5095 int endpoint_index; 5096 #endif 5097 5098 SET_OAM_INFO; 5099 5100 CHECK_INIT; 5101 5102 VALIDATE_GROUP_INDEX(group); 5103 5104 SET_GROUP(group); 5105 5106 if (!group_p->in_use) 5107 { 5108 return BCM_E_NOT_FOUND; 5109 } 5110 5111 BCM_IF_ERROR_RETURN(_bcm_en_oam_get_group(unit, group, group_p, group_info)); 5112 5113 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 5114 if ((soc_feature(unit, soc_feature_bhh)) && 5115 !(oam_info_p->ukernel_not_ready)) { 5116 /* Get the endpoint info of the group */ 5117 for (endpoint_index = 0; endpoint_index < oam_info_p->endpoint_count; 5118 ++endpoint_index) { 5119 SET_ENDPOINT(endpoint_index); 5120 5121 if ((endpoint_p->in_use && endpoint_p->group_index == group) && 5122 ((endpoint_p->type == bcmOAMEndpointTypeBHHMPLS) || 5123 (endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv))) { 5124 5125 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, endpoint_index); 5126 5127 BCM_IF_ERROR_RETURN 5128 (_bcm_en_oam_bhh_msg_send_receive(unit, 5129 MOS_MSG_SUBCLASS_BHH_SESS_GET, 5130 sess_id, 0, 5131 MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY, 5132 &reply_len)); 5133 5134 /* Pack control message data into DMA buffer */ 5135 buffer = oam_info_p->dma_buffer; 5136 buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg); 5137 buffer_len = buffer_ptr - buffer; 5138 if (reply_len != buffer_len) { 5139 return BCM_E_INTERNAL; 5140 } else { 5141 if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){ 5142 group_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT; 5143 } 5144 if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){ 5145 group_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI; 5146 } 5147 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){ 5148 group_info->faults |= 5149 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL; 5150 } 5151 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){ 5152 group_info->faults |= 5153 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID; 5154 } 5155 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){ 5156 group_info->faults |= 5157 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID; 5158 } 5159 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){ 5160 group_info->faults |= 5161 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD; 5162 } 5163 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){ 5164 group_info->faults |= 5165 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY; 5166 } 5167 if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) { 5168 group_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS; 5169 } 5170 if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) { 5171 group_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI; 5172 } 5173 if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) { 5174 group_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI; 5175 } 5176 } 5177 } 5178 } 5179 } 5180 #endif /* BCM_KATANA_SUPPORT && INCLUDE_BHH */ 5181 return BCM_E_NONE; 5182 } 5183 5184 static int _bcm_en_oam_destroy_group(int unit, int group_index, 5185 _bcm_oam_group_t *group_p) 5186 { 5187 maid_reduction_entry_t maid_reduction_entry; 5188 ma_state_entry_t ma_state_entry; 5189 5190 /* Remove all associated endpoints */ 5191 BCM_IF_ERROR_RETURN(bcm_en_oam_endpoint_destroy_all(unit, group_index)); 5192 5193 /* MAID_REDUCTION entry */ 5194 5195 soc_MAID_REDUCTIONm_field32_set(unit, &maid_reduction_entry, VALIDf, 0); 5196 5197 SOC_IF_ERROR_RETURN(WRITE_MAID_REDUCTIONm(unit, MEM_BLOCK_ALL, 5198 group_index, &maid_reduction_entry)); 5199 5200 /* MA_STATE entry */ 5201 5202 soc_MA_STATEm_field32_set(unit, &ma_state_entry, VALIDf, 0); 5203 5204 SOC_IF_ERROR_RETURN(WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, group_index, 5205 &ma_state_entry)); 5206 5207 group_p->in_use = 0; 5208 5209 #ifdef BCM_WARM_BOOT_SUPPORT 5210 SOC_CONTROL_LOCK(unit); 5211 SOC_CONTROL(unit)->scache_dirty = 1; 5212 SOC_CONTROL_UNLOCK(unit); 5213 #endif 5214 5215 return BCM_E_NONE; 5216 } 5217 5218 /* 5219 * Function: 5220 * bcm_en_oam_group_destroy 5221 * Purpose: 5222 * Destroy an OAM group object. All OAM endpoints associated 5223 * with the group will also be destroyed. 5224 * Parameters: 5225 * unit - (IN) Unit number. 5226 * group - (IN) The ID of the OAM group object to destroy 5227 * Returns: 5228 * BCM_E_XXX 5229 * Notes: 5230 */ 5231 int 5232 bcm_en_oam_group_destroy( 5233 int unit, 5234 bcm_oam_group_t group) 5235 { 5236 _bcm_oam_info_t *oam_info_p; 5237 _bcm_oam_group_t *group_p; 5238 5239 SET_OAM_INFO; 5240 5241 CHECK_INIT; 5242 5243 VALIDATE_GROUP_INDEX(group); 5244 5245 SET_GROUP(group); 5246 5247 if (!group_p->in_use) 5248 { 5249 return BCM_E_NOT_FOUND; 5250 } 5251 5252 return _bcm_en_oam_destroy_group(unit, group, group_p); 5253 } 5254 5255 /* 5256 * Function: 5257 * bcm_en_oam_group_destroy_all 5258 * Purpose: 5259 * Destroy all OAM group objects. All OAM endpoints will also be 5260 * destroyed. 5261 * Parameters: 5262 * unit - (IN) Unit number. 5263 * Returns: 5264 * BCM_E_XXX 5265 * Notes: 5266 */ 5267 int 5268 bcm_en_oam_group_destroy_all( 5269 int unit) 5270 { 5271 _bcm_oam_info_t *oam_info_p; 5272 _bcm_oam_group_t *group_p; 5273 int group_index; 5274 5275 SET_OAM_INFO; 5276 5277 CHECK_INIT; 5278 5279 for (group_index = 0; group_index < oam_info_p->group_count; 5280 ++group_index) 5281 { 5282 SET_GROUP(group_index); 5283 5284 if (group_p->in_use) 5285 { 5286 BCM_IF_ERROR_RETURN(_bcm_en_oam_destroy_group(unit, group_index, 5287 group_p)); 5288 } 5289 } 5290 5291 return BCM_E_NONE; 5292 } 5293 5294 /* 5295 * Function: 5296 * bcm_en_oam_group_traverse 5297 * Purpose: 5298 * Traverse the entire set of OAM groups, calling a specified 5299 * callback for each one 5300 * Parameters: 5301 * unit - (IN) Unit number. 5302 * cb - (IN) A pointer to the callback function to call for each OAM group 5303 * user_data - (IN) Pointer to user data to supply in the callback 5304 * Returns: 5305 * BCM_E_XXX 5306 * Notes: 5307 */ 5308 int 5309 bcm_en_oam_group_traverse( 5310 int unit, 5311 bcm_oam_group_traverse_cb cb, 5312 void *user_data) 5313 { 5314 _bcm_oam_info_t *oam_info_p; 5315 _bcm_oam_group_t *group_p; 5316 int group_index; 5317 bcm_oam_group_info_t group_info; 5318 5319 SET_OAM_INFO; 5320 5321 CHECK_INIT; 5322 5323 if (cb == NULL) 5324 { 5325 return BCM_E_PARAM; 5326 } 5327 5328 for (group_index = 0; group_index < oam_info_p->group_count; 5329 ++group_index) 5330 { 5331 SET_GROUP(group_index); 5332 5333 if (group_p->in_use) 5334 { 5335 bcm_oam_group_info_t_init(&group_info); 5336 5337 BCM_IF_ERROR_RETURN(_bcm_en_oam_get_group(unit, group_index, 5338 group_p, &group_info)); 5339 5340 BCM_IF_ERROR_RETURN(cb(unit, &group_info, user_data)); 5341 } 5342 } 5343 5344 return BCM_E_NONE; 5345 } 5346 5347 static int _bcm_en_oam_find_free_endpoint(SHR_BITDCL *endpoints, 5348 int endpoint_count, int increment, int offset) 5349 { 5350 int endpoint_index; 5351 5352 for (endpoint_index = 0; endpoint_index < endpoint_count; 5353 endpoint_index += increment) 5354 { 5355 if (!SHR_BITGET(endpoints, endpoint_index + offset)) 5356 { 5357 break; 5358 } 5359 } 5360 5361 if (endpoint_index >= endpoint_count) 5362 { 5363 endpoint_index = -1; 5364 } 5365 5366 return endpoint_index + offset; 5367 } 5368 5369 static int _bcm_en_oam_quantize_ccm_period(int period) 5370 { 5371 int quantized_period; 5372 5373 if (period == 0) 5374 { 5375 quantized_period = 0; 5376 } 5377 else 5378 { 5379 /* Find closest supported period */ 5380 5381 for (quantized_period = 1; 5382 en_ccm_periods[quantized_period] != 5383 _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED; ++quantized_period) 5384 { 5385 if ((uint32)period < en_ccm_periods[quantized_period]) 5386 { 5387 break; 5388 } 5389 } 5390 5391 if (quantized_period > 1) 5392 { 5393 if (en_ccm_periods[quantized_period] == 5394 _BCM_OAM_ENDPOINT_CCM_PERIOD_UNDEFINED) 5395 { 5396 /* Use the highest defined value */ 5397 5398 --quantized_period; 5399 } 5400 else 5401 { 5402 if (period - en_ccm_periods[quantized_period - 1] < 5403 en_ccm_periods[quantized_period] - period) 5404 { 5405 /* Closer to the lower value */ 5406 5407 --quantized_period; 5408 } 5409 } 5410 } 5411 } 5412 5413 return quantized_period; 5414 } 5415 5416 static void _bcm_en_oam_make_rmep_key(int unit, 5417 l3_entry_ipv4_unicast_entry_t *l3_key_p, uint16 name, int level, bcm_vlan_t vlan, 5418 uint32 sglp) 5419 { 5420 sal_memset(l3_key_p, 0, sizeof(l3_entry_ipv4_unicast_entry_t)); 5421 5422 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, RMEP__MEPIDf, name); 5423 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, RMEP__MDLf, level); 5424 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, RMEP__VIDf, vlan); 5425 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, RMEP__SGLPf, sglp); 5426 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, l3_key_p, KEY_TYPEf, 5427 TR_L3_HASH_KEY_TYPE_RMEP); 5428 } 5429 5430 static int _bcm_en_oam_delete_rmep(int unit, _bcm_oam_endpoint_t *endpoint_p) 5431 { 5432 _bcm_oam_info_t *oam_info_p; 5433 l3_entry_ipv4_unicast_entry_t l3_key; 5434 rmep_entry_t rmep_entry; 5435 ma_state_entry_t ma_state_entry; 5436 int some_rmep_ccm_defect_counter = 0; 5437 int current_some_rmep_ccm_defect = 0; 5438 int some_rdi_defect_counter = 0; 5439 int current_some_rdi_defect = 0; 5440 int cur_rmep_ccm_defect = 0; 5441 int cur_rmep_last_rdi = 0; 5442 int rv = BCM_E_NONE; 5443 int endpoint_index; 5444 5445 5446 SET_OAM_INFO; 5447 5448 sal_memset(&ma_state_entry, 0, sizeof(ma_state_entry_t)); 5449 SOC_IF_ERROR_RETURN(READ_MA_STATEm(unit, MEM_BLOCK_ANY, 5450 endpoint_p->group_index, 5451 &ma_state_entry)); 5452 5453 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 5454 SOC_IF_ERROR_RETURN(READ_RMEPm(unit, MEM_BLOCK_ANY, endpoint_p->remote_index, 5455 &rmep_entry)); 5456 cur_rmep_ccm_defect = soc_RMEPm_field32_get(unit, &rmep_entry, 5457 CURRENT_RMEP_CCM_DEFECTf); 5458 cur_rmep_last_rdi = soc_RMEPm_field32_get(unit, &rmep_entry, 5459 CURRENT_RMEP_LAST_RDIf); 5460 5461 if (cur_rmep_ccm_defect || cur_rmep_last_rdi) { 5462 some_rmep_ccm_defect_counter = soc_MA_STATEm_field32_get(unit, 5463 &ma_state_entry, 5464 SOME_RMEP_CCM_DEFECT_COUNTERf); 5465 current_some_rmep_ccm_defect = soc_MA_STATEm_field32_get(unit, 5466 &ma_state_entry, 5467 CURRENT_SOME_RMEP_CCM_DEFECTf); 5468 5469 if (cur_rmep_ccm_defect && some_rmep_ccm_defect_counter > 0) { 5470 --some_rmep_ccm_defect_counter; 5471 soc_MA_STATEm_field32_set(unit, &ma_state_entry, 5472 SOME_RMEP_CCM_DEFECT_COUNTERf, 5473 some_rmep_ccm_defect_counter); 5474 5475 if (some_rmep_ccm_defect_counter == 0) { 5476 current_some_rmep_ccm_defect = 0; 5477 soc_MA_STATEm_field32_set(unit, &ma_state_entry, 5478 CURRENT_SOME_RMEP_CCM_DEFECTf, 5479 current_some_rmep_ccm_defect); 5480 } 5481 } 5482 some_rdi_defect_counter = soc_MA_STATEm_field32_get(unit, 5483 &ma_state_entry, 5484 SOME_RDI_DEFECT_COUNTERf); 5485 current_some_rdi_defect = soc_MA_STATEm_field32_get(unit, 5486 &ma_state_entry, 5487 CURRENT_SOME_RDI_DEFECTf); 5488 if (cur_rmep_last_rdi && some_rdi_defect_counter > 0) { 5489 --some_rdi_defect_counter; 5490 soc_MA_STATEm_field32_set(unit, &ma_state_entry, 5491 SOME_RDI_DEFECT_COUNTERf, 5492 some_rdi_defect_counter); 5493 if (some_rdi_defect_counter == 0) { 5494 current_some_rdi_defect = 0; 5495 soc_MA_STATEm_field32_set(unit, &ma_state_entry, 5496 CURRENT_SOME_RDI_DEFECTf, 5497 current_some_rdi_defect); 5498 } 5499 } 5500 SOC_IF_ERROR_RETURN(WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, 5501 endpoint_p->group_index, 5502 &ma_state_entry)); 5503 } 5504 5505 /* RMEP entry */ 5506 SOC_IF_ERROR_RETURN(soc_mem_field32_modify(unit, RMEPm, 5507 endpoint_p->remote_index, VALIDf, 0)); 5508 5509 /* L3 entry */ 5510 if (endpoint_p->vp != 0) { 5511 _bcm_en_oam_make_rmep_key(unit, &l3_key, endpoint_p->name, 5512 endpoint_p->level, 0, endpoint_p->vp); 5513 } else { 5514 _bcm_en_oam_make_rmep_key(unit, &l3_key, endpoint_p->name, 5515 endpoint_p->level, endpoint_p->vlan, endpoint_p->glp); 5516 } 5517 5518 rv = soc_mem_delete(unit, L3_ENTRY_IPV4_UNICASTm, 5519 MEM_BLOCK_ALL, &l3_key); 5520 if ((BCM_FAILURE(rv)) && (rv != BCM_E_NOT_FOUND)) { 5521 /* The L3 entry may have got cleared as part of L3 init during a rc, 5522 * ignore BCM_E_NOT_FOUND error. 5523 */ 5524 return rv; 5525 } 5526 5527 /* Local control block */ 5528 5529 SHR_BITCLR(oam_info_p->remote_endpoints_in_use, endpoint_p->remote_index); 5530 5531 for (endpoint_index = 0; endpoint_index < oam_info_p->remote_endpoint_count; 5532 endpoint_index++) 5533 { 5534 if (SHR_BITGET(oam_info_p->remote_endpoints_in_use, endpoint_index)) 5535 { 5536 break; 5537 } 5538 } 5539 5540 /* None of endpoint is in use reset all CCM_DEFECT */ 5541 if (endpoint_index == oam_info_p->remote_endpoint_count) 5542 { 5543 soc_MA_STATEm_field32_set 5544 (unit, &ma_state_entry, CURRENT_XCON_CCM_DEFECTf, 5545 0); 5546 soc_MA_STATEm_field32_set 5547 (unit, &ma_state_entry, CURRENT_ERROR_CCM_DEFECTf, 5548 0); 5549 soc_MA_STATEm_field32_set 5550 (unit, &ma_state_entry, STICKY_ERROR_CCM_DEFECTf, 5551 0); 5552 soc_MA_STATEm_field32_set 5553 (unit, &ma_state_entry, ERROR_CCM_DEFECT_TIMESTAMPf, 5554 0); 5555 soc_MA_STATEm_field32_set 5556 (unit, &ma_state_entry, ERROR_CCM_DEFECT_RECEIVE_CCMf, 5557 0); 5558 SOC_IF_ERROR_RETURN(WRITE_MA_STATEm(unit, MEM_BLOCK_ALL, 5559 endpoint_p->group_index, 5560 &ma_state_entry)); 5561 } 5562 5563 oam_info_p->remote_endpoints[endpoint_p->remote_index] = 5564 BCM_OAM_ENDPOINT_INVALID; 5565 5566 return BCM_E_NONE; 5567 } 5568 5569 static int _bcm_en_oam_find_lmep(int unit, bcm_vlan_t vlan, uint32 sglp, 5570 int *index_p, l3_entry_ipv4_unicast_entry_t *l3_entry_p) 5571 { 5572 l3_entry_ipv4_unicast_entry_t l3_key; 5573 sal_memset(&l3_key, 0, sizeof(l3_entry_ipv4_unicast_entry_t)); 5574 5575 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_key, LMEP__VIDf, vlan); 5576 5577 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_key, LMEP__SGLPf, sglp); 5578 5579 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_key, KEY_TYPEf, 5580 TR_L3_HASH_KEY_TYPE_LMEP); 5581 5582 return soc_mem_search(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ANY, 5583 index_p, &l3_key, l3_entry_p, 0); 5584 } 5585 5586 /* 5587 * Function: 5588 * _bcm_en_oam_lm_search 5589 * Purpose: 5590 * Find how may LM endpoints have been created with the same port and VLAN 5591 * Parameters: 5592 * unit - (IN) Unit number. 5593 * current_endpoint_p - (IN) Pointer to an OAM endpoint structure 5594 * add - (IN) 1 = create, 0 = destroy 5595 * mdl_index - (OUT) Pointer to a sorted endpoint index 5596 * Returns: 5597 * Number of endpoints that need to recreate FP entries 5598 * Notes: 5599 */ 5600 static int _bcm_en_oam_lm_search( 5601 int unit, _bcm_oam_endpoint_t *current_endpoint_p, int add, int *mdl_index) 5602 { 5603 int i, j, k, max_index = 0; 5604 int level[LEVEL_COUNT]; 5605 _bcm_oam_info_t *oam_info_p; 5606 _bcm_oam_endpoint_t *endpoint_p = NULL; 5607 5608 if (!current_endpoint_p) { 5609 return 0; 5610 } 5611 5612 for (i = 0; i < LEVEL_COUNT; i++) { 5613 mdl_index[i] = -1; 5614 level[i] = LEVEL_COUNT; 5615 } 5616 5617 SET_OAM_INFO; 5618 5619 for (i = 0; i < oam_info_p->endpoint_count; i++) { 5620 5621 SET_ENDPOINT(i); 5622 5623 if ((endpoint_p == current_endpoint_p) && (add == 0)) { 5624 /* Skip current endpoint in destroy case */ 5625 continue; 5626 } 5627 5628 if ((endpoint_p->in_use || (add != 0)) && 5629 (endpoint_p->glp == current_endpoint_p->glp) && 5630 (endpoint_p->vlan == current_endpoint_p->vlan) && 5631 (endpoint_p->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) { 5632 /* Different MDL LM endpoints found. Save index in MDL order */ 5633 for (j = 0; j < LEVEL_COUNT && mdl_index[j] != -1; j++) { 5634 if (endpoint_p->level < level[j]) { 5635 for (k = max_index; k > j; k--) { 5636 if (mdl_index[k-1] != -1) { 5637 mdl_index[k] = mdl_index[k-1]; 5638 level[k] = level[k-1]; 5639 } 5640 } 5641 mdl_index[j] = i; 5642 level[j] = endpoint_p->level; 5643 break; 5644 } else if ((j == (max_index-1)) && (j < MAX_ENDPOINT_LEVEL)) { 5645 mdl_index[j+1] = i; 5646 level[j+1] = endpoint_p->level; 5647 break; 5648 } 5649 } 5650 /* Use the same LM counter index */ 5651 if ((endpoint_p != current_endpoint_p) && (add != 0)) { 5652 current_endpoint_p->lm_counter_index = endpoint_p->lm_counter_index; 5653 current_endpoint_p->pri_map_index = endpoint_p->pri_map_index; 5654 } 5655 5656 /* Save first element for destroy case */ 5657 if (max_index == 0) { 5658 mdl_index[0] = i; 5659 level[0] = endpoint_p->level; 5660 } 5661 max_index++; 5662 /* Destory entry and reinstall later */ 5663 if (endpoint_p != current_endpoint_p) { 5664 _bcm_en_oam_uninstall_fp(unit, endpoint_p); 5665 } 5666 } 5667 } 5668 5669 return max_index; 5670 } 5671 5672 static int _bcm_en_oam_delete_lmep(int unit, 5673 _bcm_oam_endpoint_t *endpoint_p) 5674 { 5675 _bcm_oam_info_t *oam_info_p; 5676 _bcm_oam_endpoint_t *current_endpoint_p; 5677 int i, j, l3_index, num_lm, mdl_index[LEVEL_COUNT]; 5678 l3_entry_ipv4_unicast_entry_t l3_entry; 5679 uint32 level_bitmap; 5680 int result = SOC_E_NONE; 5681 lmep_entry_t lmep_entry; 5682 5683 SET_OAM_INFO; 5684 5685 if (endpoint_p->local_tx_enabled) 5686 { 5687 /* LMEP entry */ 5688 5689 sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t)); 5690 WRITE_LMEPm(unit, MEM_BLOCK_ALL, 5691 endpoint_p->local_tx_index, &lmep_entry); 5692 5693 /* Local control block */ 5694 5695 SHR_BITCLR(oam_info_p->local_tx_endpoints_in_use, 5696 endpoint_p->local_tx_index); 5697 } 5698 5699 if (endpoint_p->local_rx_enabled) 5700 { 5701 /* MA_INDEX entry doesn't need to be touched */ 5702 5703 /* L3 entry */ 5704 5705 L3_LOCK(unit); 5706 5707 if (BCM_SUCCESS(_bcm_en_oam_find_lmep(unit, endpoint_p->vlan, 5708 endpoint_p->glp, &l3_index, &l3_entry)) || 5709 BCM_SUCCESS(_bcm_en_oam_find_lmep(unit, 0, 5710 endpoint_p->vp, &l3_index, &l3_entry))) 5711 { 5712 level_bitmap = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 5713 &l3_entry, LMEP__MDL_BITMAPf); 5714 5715 level_bitmap &= ~(1 << endpoint_p->level); 5716 5717 if (level_bitmap != 0) 5718 { 5719 /* Still endpoints here at other levels */ 5720 5721 result = soc_mem_field32_modify(unit, L3_ENTRY_IPV4_UNICASTm, 5722 l3_index, LMEP__MDL_BITMAPf, level_bitmap); 5723 } 5724 else 5725 { 5726 /* No endpoints left here at any level */ 5727 5728 result = soc_mem_field32_modify(unit, L3_ENTRY_IPV4_UNICASTm, 5729 l3_index, VALIDf, 0); 5730 } 5731 } 5732 5733 L3_UNLOCK(unit); 5734 5735 if ((BCM_FAILURE(result)) && (result != BCM_E_NOT_FOUND)) { 5736 /* The L3 entry may have got cleared as part of L3 init during a rc, 5737 * ignore BCM_E_NOT_FOUND error. 5738 */ 5739 return result; 5740 } 5741 5742 /* Local control block */ 5743 SHR_BITCLR(oam_info_p->local_rx_endpoints_in_use, 5744 endpoint_p->local_rx_index); 5745 5746 #if defined(BCM_KATANA_SUPPORT) 5747 if (SOC_IS_KATANAX(unit)) { 5748 result = soc_profile_mem_delete(unit, oam_opcode_profile[unit], 5749 endpoint_p->opcode_profile_index); 5750 endpoint_p->opcode_profile_index = 0; 5751 } 5752 #endif /* BCM_KATANA_SUPPORT */ 5753 5754 _bcm_en_oam_uninstall_vfp(unit, endpoint_p); 5755 _bcm_en_oam_uninstall_fp(unit, endpoint_p); 5756 5757 if (endpoint_p->lm_counter_index != BCM_OAM_LM_COUNTER_INDEX_INVALID) { 5758 num_lm = _bcm_en_oam_lm_search(unit, endpoint_p, 0, mdl_index); 5759 if (num_lm == 0) { 5760 SHR_BITCLR(oam_info_p->lm_counter_in_use, 5761 endpoint_p->lm_counter_index); 5762 SOC_IF_ERROR_RETURN( 5763 soc_profile_mem_delete(unit, ing_pri_map_profile[unit], 5764 endpoint_p->pri_map_index*BCM_OAM_INTPRI_MAX)); 5765 } else { 5766 for (i = 0; i < num_lm; i++) { 5767 current_endpoint_p = oam_info_p->endpoints + mdl_index[i]; 5768 BCM_IF_ERROR_RETURN( 5769 _bcm_en_oam_install_fp(unit, (i == (num_lm-1)) ? 0 : 1, current_endpoint_p)); 5770 BCM_IF_ERROR_RETURN( 5771 bcm_esw_field_entry_install(unit, current_endpoint_p->fp_entry_tx)); 5772 BCM_IF_ERROR_RETURN( 5773 bcm_esw_field_entry_install(unit, current_endpoint_p->fp_entry_rx)); 5774 for (j = 0; j < BCM_SWITCH_TRUNK_MAX_PORTCNT; j++) { 5775 if (current_endpoint_p->fp_entry_trunk[j]) { 5776 BCM_IF_ERROR_RETURN( 5777 bcm_esw_field_entry_install(unit, current_endpoint_p->fp_entry_trunk[j])); 5778 } 5779 } 5780 } 5781 } 5782 endpoint_p->lm_counter_index = BCM_OAM_LM_COUNTER_INDEX_INVALID; 5783 endpoint_p->pri_map_index = 0; 5784 } 5785 } 5786 return result; 5787 } 5788 5789 #if defined(BCM_KATANA_SUPPORT) 5790 static int _bcm_kt_set_oam_opcode_profile_entry(int unit, 5791 uint32 flags, uint32 *entry) 5792 { 5793 uint32 i, opcode; 5794 5795 for (i=0; i<31; i++) { 5796 5797 opcode = flags & (1 << i); 5798 5799 switch (opcode) { 5800 case BCM_OAM_OPCODE_CCM_IN_HW: 5801 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, CCM_PROCESS_IN_HWf, 1); 5802 break; 5803 5804 case BCM_OAM_OPCODE_CCM_COPY_TO_CPU: 5805 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, CCM_COPYTO_CPUf, 1); 5806 break; 5807 5808 case BCM_OAM_OPCODE_CCM_DROP: 5809 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, CCM_DROPf, 1); 5810 break; 5811 5812 case BCM_OAM_OPCODE_LBM_IN_HW: 5813 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LBM_PROCESS_IN_HWf, 1); 5814 break; 5815 5816 case BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU: 5817 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LBM_UC_COPYTO_CPUf, 1); 5818 break; 5819 case BCM_OAM_OPCODE_LBM_UC_DROP: 5820 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LBM_UC_DROPf, 1); 5821 break; 5822 5823 case BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU: 5824 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LBM_MC_COPYTO_CPUf, 1); 5825 break; 5826 5827 case BCM_OAM_OPCODE_LBM_MC_DROP: 5828 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LBM_MC_DROPf, 1); 5829 break; 5830 5831 case BCM_OAM_OPCODE_LBR_COPY_TO_CPU: 5832 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LBR_COPYTO_CPUf, 1); 5833 break; 5834 5835 case BCM_OAM_OPCODE_LBR_DROP: 5836 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LBR_DROPf, 1); 5837 break; 5838 5839 case BCM_OAM_OPCODE_LTM_COPY_TO_CPU: 5840 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LTM_COPYTO_CPUf, 1); 5841 break; 5842 5843 case BCM_OAM_OPCODE_LTM_DROP: 5844 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LTM_DROPf, 1); 5845 break; 5846 case BCM_OAM_OPCODE_LTR_COPY_TO_CPU: 5847 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LTR_COPYTO_CPUf, 1); 5848 break; 5849 5850 case BCM_OAM_OPCODE_LTR_DROP: 5851 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, LTR_DROPf, 1); 5852 break; 5853 5854 case BCM_OAM_OPCODE_LMEP_PKT_FWD: 5855 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, FWD_LMEP_PKTf, 1); 5856 break; 5857 5858 case BCM_OAM_OPCODE_OTHER_COPY_TO_CPU: 5859 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, OTHER_OPCODE_COPYTO_CPUf, 1); 5860 break; 5861 5862 case BCM_OAM_OPCODE_OTHER_DROP: 5863 soc_OAM_OPCODE_CONTROL_PROFILEm_field32_set(unit, entry, OTHER_OPCODE_DROPf, 1); 5864 break; 5865 5866 default: 5867 break; 5868 } 5869 } 5870 5871 return BCM_E_NONE; 5872 } 5873 5874 static int _bcm_kt_get_default_oam_opcode_profile_entry(int unit, 5875 uint32 *entry) 5876 { 5877 uint32 opcode_flags; 5878 5879 opcode_flags = BCM_OAM_OPCODE_CCM_COPY_TO_CPU | 5880 BCM_OAM_OPCODE_CCM_DROP | 5881 BCM_OAM_OPCODE_LBM_UC_COPY_TO_CPU | 5882 BCM_OAM_OPCODE_LBM_UC_DROP | 5883 BCM_OAM_OPCODE_LBM_MC_COPY_TO_CPU | 5884 BCM_OAM_OPCODE_LBM_MC_DROP | 5885 BCM_OAM_OPCODE_LBR_COPY_TO_CPU | 5886 BCM_OAM_OPCODE_LBR_DROP | 5887 BCM_OAM_OPCODE_LTM_COPY_TO_CPU | 5888 BCM_OAM_OPCODE_LTM_DROP | 5889 BCM_OAM_OPCODE_LTR_COPY_TO_CPU | 5890 BCM_OAM_OPCODE_LTR_DROP | 5891 BCM_OAM_OPCODE_OTHER_COPY_TO_CPU | 5892 BCM_OAM_OPCODE_OTHER_DROP; 5893 5894 _bcm_kt_set_oam_opcode_profile_entry(unit, opcode_flags, entry); 5895 5896 return BCM_E_NONE; 5897 } 5898 5899 #endif /* BCM_KATANA_SUPPORT */ 5900 5901 /* 5902 * Function: 5903 * _bcm_en_oam_destroy_endpoint 5904 * Purpose: 5905 * Destroy an OAM endpoint object 5906 * Parameters: 5907 * unit - (IN) Unit number. 5908 * endpoint_p - (IN) Pointer to an OAM endpoint structure 5909 * Returns: 5910 * BCM_E_XXX 5911 * Notes: 5912 */ 5913 static int _bcm_en_oam_destroy_endpoint(int unit, 5914 _bcm_oam_endpoint_t *endpoint_p) 5915 { 5916 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 5917 _bcm_oam_info_t *oam_info_p; 5918 uint16 reply_len; 5919 int sess_id = 0; 5920 5921 SET_OAM_INFO; 5922 #endif 5923 5924 if (endpoint_p->type == bcmOAMEndpointTypeEthernet) 5925 { 5926 if (endpoint_p->is_remote) 5927 { 5928 BCM_IF_ERROR_RETURN(_bcm_en_oam_delete_rmep(unit, endpoint_p)); 5929 } 5930 else 5931 { 5932 BCM_IF_ERROR_RETURN(_bcm_en_oam_delete_lmep(unit, endpoint_p)); 5933 } 5934 } 5935 /* 5936 * BHH specific 5937 */ 5938 else if (soc_feature(unit, soc_feature_bhh) && 5939 ((endpoint_p->type == bcmOAMEndpointTypeBHHMPLS) || 5940 (endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv))) 5941 { 5942 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 5943 if (endpoint_p->is_remote) { 5944 /* 5945 * BHH uses same index for local and remote. So, delete always goes through 5946 * local endpoint destory 5947 */ 5948 return BCM_E_NONE; 5949 } else { 5950 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, endpoint_p->bhh_endpoint_index); 5951 /* 5952 * Delete BHH Session in HW 5953 */ 5954 BCM_IF_ERROR_RETURN 5955 (_bcm_en_oam_bhh_session_hw_delete(unit, endpoint_p)); 5956 5957 /* 5958 * Send BHH Session Delete message to uC 5959 */ 5960 BCM_IF_ERROR_RETURN 5961 (_bcm_en_oam_bhh_msg_send_receive(unit, 5962 MOS_MSG_SUBCLASS_BHH_SESS_DELETE, 5963 sess_id, 0, 5964 MOS_MSG_SUBCLASS_BHH_SESS_DELETE_REPLY, 5965 &reply_len)); 5966 5967 if (reply_len != 0) { 5968 return BCM_E_INTERNAL; 5969 } 5970 } 5971 5972 endpoint_p->bhh_endpoint_index = -1; 5973 #else 5974 return (BCM_E_UNAVAIL); 5975 #endif 5976 } 5977 else { 5978 return (BCM_E_PARAM); 5979 } 5980 5981 sal_memset(endpoint_p,0,sizeof(_bcm_oam_endpoint_t)); 5982 endpoint_p->in_use = 0; 5983 endpoint_p->lm_counter_index = BCM_OAM_LM_COUNTER_INDEX_INVALID; 5984 5985 return BCM_E_NONE; 5986 } 5987 5988 /* 5989 * Function: 5990 * _bcm_en_oam_mepid_validate 5991 * Purpose: 5992 * Validate an endpoint MEP id. 5993 * Parameters: 5994 * unit - (IN) BCM device number 5995 * ep_info_p - (IN) Pointer to endpoint information. 5996 * Retruns: 5997 * BCM_E_XXX 5998 */ 5999 STATIC int 6000 _bcm_en_oam_mepid_validate(int unit, 6001 bcm_oam_endpoint_info_t *endpoint_info) 6002 { 6003 _bcm_oam_info_t *oam_info_p; 6004 _bcm_oam_endpoint_t *endpoint_p; 6005 int endpoint_index; 6006 6007 SET_OAM_INFO; 6008 6009 if (endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) { 6010 return BCM_E_NONE; 6011 } 6012 6013 for (endpoint_index = 0; endpoint_index < oam_info_p->endpoint_count; 6014 ++endpoint_index) { 6015 SET_ENDPOINT(endpoint_index); 6016 if (endpoint_p->in_use && 6017 endpoint_p->group_index == endpoint_info->group) { 6018 if (endpoint_p->name == endpoint_info->name) { 6019 return BCM_E_PARAM; 6020 } 6021 } 6022 } 6023 return BCM_E_NONE; 6024 } 6025 6026 /* 6027 * Function: 6028 * _bcm_en_oam_create_endpoint 6029 * Purpose: 6030 * Create or replace an OAM endpoint object 6031 * Parameters: 6032 * unit - (IN) Unit number. 6033 * endpoint_info - (IN/OUT) Pointer to an OAM endpoint structure 6034 * Returns: 6035 * BCM_E_XXX 6036 * Notes: 6037 */ 6038 static int 6039 _bcm_en_oam_create_endpoint( 6040 int unit, 6041 bcm_oam_endpoint_info_t *endpoint_info, 6042 _bcm_oam_endpoint_t **created_endpoint_p, 6043 int *num_lm, int *mdl_index) 6044 { 6045 _bcm_oam_info_t *oam_info_p; 6046 _bcm_oam_group_t *group_p; 6047 _bcm_oam_endpoint_t *endpoint_p, *current_endpoint_p; 6048 int i, replace, mdl_set = 0, replace_l3_entry = 0; 6049 int is_remote, is_local; 6050 int local_tx_enabled = 0; 6051 int local_rx_enabled = 0; 6052 int endpoint_index = 0; 6053 bcm_module_t module_id = -1; 6054 bcm_port_t port_id = -1; 6055 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 6056 int local_id = -1; 6057 uint32 vp = 0; 6058 rmep_entry_t rmep_entry; 6059 lmep_entry_t lmep_entry; 6060 lmep_1_entry_t lmep1_entry; 6061 ma_index_entry_t ma_index_entry; 6062 l3_entry_ipv4_unicast_entry_t l3_entry, l3_key; 6063 int quantization_index; 6064 int l3_index; 6065 uint32 level_bitmap, mem_entries[BCM_OAM_INTPRI_MAX], temp_index; 6066 int result = 0; 6067 void *entries[1]; 6068 uint32 oam_current_time; 6069 #if defined(BCM_KATANA_SUPPORT) 6070 uint32 opcode_entry = 0; 6071 #if defined(INCLUDE_BHH) 6072 bhh_sdk_msg_ctrl_sess_set_t msg_sess; 6073 bhh_sdk_msg_ctrl_rmep_create_t msg_rmep_create; 6074 uint8 *buffer, *buffer_ptr; 6075 uint16 buffer_len, reply_len; 6076 int encap = 0; 6077 uint32 session_flags; 6078 uint8 group_sw_rdi = 0; 6079 #endif /* INCLUDE_BHH */ 6080 #endif /* BCM_KATANA_SUPPORT */ 6081 int rv = BCM_E_NONE; 6082 uint32 src_glp = _BCM_OAM_INVALID_INDEX; 6083 uint32 dst_glp = _BCM_OAM_INVALID_INDEX; 6084 bcm_trunk_member_t *member_array = NULL; 6085 int member_count; 6086 bcm_gport_t member_gport; 6087 bcm_trunk_t tgid_out; 6088 int id_out; 6089 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 6090 int eth_oam_endpoint_count = 0; 6091 #endif 6092 int endpoint_start_index = 0; 6093 int endpoint_end_index = 0; 6094 6095 SET_OAM_INFO; 6096 6097 CHECK_INIT; 6098 6099 VALIDATE_GROUP_INDEX(endpoint_info->group); 6100 6101 if (endpoint_info->level > MAX_ENDPOINT_LEVEL) 6102 { 6103 /* Exceeds supported MDL level 0 - 7. */ 6104 return BCM_E_PARAM; 6105 } 6106 6107 /* Supported MEPID Name range is 1 - 8191, Skipping range check for MIP */ 6108 if (((endpoint_info->name < _BCM_OAM_EP_NAME_MIN) 6109 || (endpoint_info->name > _BCM_OAM_EP_NAME_MAX)) && 6110 !(endpoint_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE)) { 6111 LOG_ERROR(BSL_LS_BCM_OAM, 6112 (BSL_META_U(unit, 6113 "OAM Error: MEP Name should be in the range(%d-%d).\n"), 6114 _BCM_OAM_EP_NAME_MIN, _BCM_OAM_EP_NAME_MAX)); 6115 return (BCM_E_PARAM); 6116 } 6117 6118 /* Endpoint MIP's are not created with non-zero ccm period */ 6119 if ((endpoint_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) && 6120 (endpoint_info->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED)) { 6121 return (BCM_E_PARAM); 6122 } 6123 6124 if (endpoint_info->flags & UNSUPPORTED_ENDPOINT_FLAGS) 6125 { 6126 return BCM_E_UNAVAIL; 6127 } 6128 6129 if (endpoint_info->type != bcmOAMEndpointTypeEthernet) 6130 { 6131 #if defined(BCM_ENDURO_SUPPORT) 6132 if (SOC_IS_ENDURO(unit)) 6133 { 6134 /* Device supports Ethernet OAM only. */ 6135 return BCM_E_UNAVAIL; 6136 } 6137 #endif 6138 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 6139 if ((endpoint_info->type != bcmOAMEndpointTypeBHHMPLS) && 6140 (endpoint_info->type != bcmOAMEndpointTypeBHHMPLSVccv)) 6141 #endif 6142 { 6143 return BCM_E_UNAVAIL; 6144 } 6145 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 6146 if((endpoint_info->type == bcmOAMEndpointTypeBHHMPLS) || 6147 (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv)) 6148 { 6149 if (oam_info_p->ukernel_not_ready == 1) { 6150 LOG_ERROR(BSL_LS_BCM_OAM, 6151 (BSL_META_U(unit, 6152 "OAM(unit %d) Error: BTE(ukernel) " 6153 "not ready.\n"), unit)); 6154 return (BCM_E_INIT); 6155 } 6156 } 6157 if ((endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv) && 6158 (endpoint_info->vccv_type > bcmOamBhhVccvTtl)) 6159 { 6160 LOG_ERROR(BSL_LS_BCM_OAM, 6161 (BSL_META_U(unit, 6162 "BHH Error: vccv type %d not supported (EP=%d)\n"), 6163 endpoint_info->vccv_type, endpoint_info->id)); 6164 return (BCM_E_PARAM); 6165 } 6166 #endif 6167 } 6168 6169 replace = ((endpoint_info->flags & BCM_OAM_ENDPOINT_REPLACE) != 0); 6170 6171 if (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE) 6172 { 6173 if (endpoint_info->flags & 6174 (BCM_OAM_ENDPOINT_CCM_RX | BCM_OAM_ENDPOINT_LOOPBACK | 6175 BCM_OAM_ENDPOINT_DELAY_MEASUREMENT | BCM_OAM_ENDPOINT_LINKTRACE | 6176 BCM_OAM_ENDPOINT_LOSS_MEASUREMENT | 6177 BCM_OAM_ENDPOINT_PORT_STATE_TX | 6178 BCM_OAM_ENDPOINT_INTERFACE_STATE_TX )) 6179 { 6180 /* Specified flags aren't valid for RMEPs */ 6181 6182 return BCM_E_PARAM; 6183 } 6184 6185 is_remote = 1; 6186 } 6187 else 6188 { 6189 /* Local */ 6190 is_remote = 0; 6191 6192 local_tx_enabled = 6193 (endpoint_info->ccm_period != BCM_OAM_ENDPOINT_CCM_PERIOD_DISABLED); 6194 6195 local_rx_enabled = ((endpoint_info->flags & 6196 (BCM_OAM_ENDPOINT_CCM_RX | BCM_OAM_ENDPOINT_LOOPBACK | 6197 BCM_OAM_ENDPOINT_DELAY_MEASUREMENT | 6198 BCM_OAM_ENDPOINT_LOSS_MEASUREMENT | 6199 BCM_OAM_ENDPOINT_LINKTRACE)) != 0); 6200 } 6201 6202 if (soc_feature(unit, soc_feature_bhh)) { 6203 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 6204 eth_oam_endpoint_count = oam_info_p->remote_endpoint_count + 6205 oam_info_p->local_tx_endpoint_count + oam_info_p->local_rx_endpoint_count; 6206 #endif 6207 } 6208 6209 if (endpoint_info->flags & BCM_OAM_ENDPOINT_WITH_ID) 6210 { 6211 endpoint_index = endpoint_info->id; 6212 6213 if (soc_feature(unit, soc_feature_bhh)) { 6214 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 6215 if ((endpoint_info->type == bcmOAMEndpointTypeEthernet) && 6216 (endpoint_index >= eth_oam_endpoint_count)) 6217 { 6218 return BCM_E_PARAM; 6219 } 6220 else if (((endpoint_info->type == bcmOAMEndpointTypeBHHMPLS) || 6221 (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv)) && 6222 (endpoint_index < eth_oam_endpoint_count)) 6223 { 6224 return BCM_E_PARAM; 6225 } 6226 #endif 6227 } 6228 6229 VALIDATE_ENDPOINT_INDEX(endpoint_index); 6230 6231 if (replace && (!oam_info_p->endpoints[endpoint_index].in_use)) 6232 { 6233 return BCM_E_NOT_FOUND; 6234 } 6235 else if (!replace && (oam_info_p->endpoints[endpoint_index].in_use)) 6236 { 6237 return BCM_E_EXISTS; 6238 } 6239 } 6240 else 6241 { 6242 if (replace) 6243 { 6244 /* Replace specified with no ID */ 6245 6246 return BCM_E_PARAM; 6247 } 6248 6249 endpoint_start_index = 0; 6250 endpoint_end_index = oam_info_p->endpoint_count; 6251 6252 if (soc_feature(unit, soc_feature_bhh)) { 6253 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 6254 if(endpoint_info->type == bcmOAMEndpointTypeEthernet) 6255 { 6256 endpoint_start_index = 0; 6257 endpoint_end_index = eth_oam_endpoint_count; 6258 } 6259 else 6260 { 6261 endpoint_start_index = eth_oam_endpoint_count; 6262 endpoint_end_index = oam_info_p->endpoint_count; 6263 } 6264 #endif 6265 } 6266 6267 if (soc_feature(unit, soc_feature_bhh)) { 6268 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 6269 /* BHH uses local and remote same index */ 6270 if((endpoint_info->type != bcmOAMEndpointTypeEthernet) && 6271 (endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE)) 6272 { 6273 endpoint_index = endpoint_info->local_id; 6274 } 6275 #endif 6276 } 6277 6278 /* 6279 * Non-remote BHH EP. Get new ID 6280 */ 6281 if(!endpoint_index) { 6282 for (endpoint_index = endpoint_start_index; endpoint_index < endpoint_end_index; 6283 ++endpoint_index) 6284 { 6285 if (!oam_info_p->endpoints[endpoint_index].in_use) 6286 { 6287 break; 6288 } 6289 } 6290 6291 if (endpoint_index >= oam_info_p->endpoint_count) 6292 { 6293 return BCM_E_FULL; 6294 } 6295 6296 endpoint_info->id = endpoint_index; 6297 6298 } 6299 } 6300 6301 SET_ENDPOINT(endpoint_index); 6302 *created_endpoint_p = endpoint_p; 6303 SET_GROUP(endpoint_info->group); 6304 6305 if (!group_p->in_use) 6306 { 6307 /* Associating to a nonexistent group */ 6308 6309 return BCM_E_PARAM; 6310 } 6311 6312 /* 6313 * As per IEEE 802.1ag specifications,the MEP ID 6314 * should be unique within an OAM group. 6315 */ 6316 if(_bcm_en_oam_mepid_validate(unit, endpoint_info)) { 6317 LOG_ERROR(BSL_LS_BCM_OAM, 6318 (BSL_META_U(unit, 6319 "OAM Error: MEPID:%x passed is not unique in group %x\n"), 6320 endpoint_info->name, endpoint_info->group)); 6321 6322 return (BCM_E_EXISTS); 6323 } 6324 6325 /* Get Trunk ID or (Modid + Port) value from Gport */ 6326 BCM_IF_ERROR_RETURN 6327 (_bcm_esw_gport_resolve(unit, endpoint_info->gport, &module_id, 6328 &port_id, &trunk_id, &local_id)); 6329 6330 /* 6331 * If Gport is Trunk type, _bcm_esw_gport_resolve() 6332 * sets trunk_id. Using Trunk ID, get Dst Modid and Port value. 6333 */ 6334 if (BCM_GPORT_IS_TRUNK(endpoint_info->gport) && 6335 (BCM_TRUNK_INVALID == trunk_id)) { 6336 /* Has to be a valid Trunk. */ 6337 return (BCM_E_PARAM); 6338 } 6339 6340 if (BCM_TRUNK_INVALID != trunk_id) { 6341 6342 /* 6343 * CCM Tx is enabled on a trunk member port. 6344 * trunk_index value is required to derive the Modid and Port info. 6345 */ 6346 if (1 == local_tx_enabled 6347 && _BCM_OAM_INVALID_INDEX == endpoint_info->trunk_index) { 6348 /* Invalid Trunk member index passed. */ 6349 return (BCM_E_PORT); 6350 } 6351 6352 /* Get Trunk Info for the Trunk ID. */ 6353 BCM_IF_ERROR_RETURN 6354 (bcm_esw_trunk_get(unit, trunk_id, NULL, 0, NULL, &member_count)); 6355 if (0 == member_count) { 6356 /* No members have been added to the trunk group yet */ 6357 return BCM_E_PARAM; 6358 } 6359 member_array = sal_alloc(sizeof(bcm_trunk_member_t) * member_count, 6360 "trunk member array"); 6361 if (NULL == member_array) { 6362 return BCM_E_MEMORY; 6363 } 6364 rv = bcm_esw_trunk_get(unit, trunk_id, NULL, 6365 member_count, member_array, &member_count); 6366 if (BCM_FAILURE(rv)) { 6367 sal_free(member_array); 6368 return rv; 6369 } 6370 6371 /* Get the Modid and Port value using Trunk Index value. */ 6372 if (endpoint_info->trunk_index >= member_count) { 6373 sal_free(member_array); 6374 return BCM_E_PARAM; 6375 } 6376 member_gport = member_array[endpoint_info->trunk_index].gport; 6377 sal_free(member_array); 6378 BCM_IF_ERROR_RETURN 6379 (_bcm_esw_gport_resolve(unit, member_gport, &module_id, &port_id, 6380 &tgid_out, &id_out)); 6381 if ((-1 != tgid_out) || (-1 != id_out)) { 6382 return BCM_E_PARAM; 6383 } 6384 6385 /* Calculate the SGLP and DGLP values to program the MEP */ 6386 src_glp = ((1 << SOC_TRUNK_BIT_POS(unit)) | trunk_id); 6387 dst_glp = (module_id << SOC_MODID_BIT_POS(unit)) | port_id; 6388 } 6389 6390 /* 6391 * Application can resolve the trunk and pass the desginated 6392 * port as Gport value. Check if the Gport belongs to a trunk. 6393 */ 6394 if ((BCM_TRUNK_INVALID == trunk_id) 6395 && (BCM_GPORT_IS_MODPORT(endpoint_info->gport) 6396 || BCM_GPORT_IS_LOCAL(endpoint_info->gport))) { 6397 6398 /* When Gport is ModPort or Port type, _bcm_esw_gport_resolve() 6399 * returns Modid and Port value. Use these values to make the DGLP 6400 * value. 6401 */ 6402 dst_glp = ((module_id << SOC_MODID_BIT_POS(unit)) | port_id); 6403 6404 /* Use the Modid, Port value and determine if the port 6405 * belongs to a Trunk. 6406 */ 6407 rv = bcm_esw_trunk_find(unit, module_id, port_id, &trunk_id); 6408 if (BCM_SUCCESS(rv)) { 6409 /* 6410 * Port is member of a valid trunk. 6411 * Now create the SGLP value from Trunk ID. 6412 */ 6413 src_glp = (1 << SOC_TRUNK_BIT_POS(unit)) | trunk_id; 6414 } else { 6415 /* Port not a member of trunk. DGLP and SGLP are the same. */ 6416 src_glp = dst_glp; 6417 } 6418 } 6419 6420 if (BCM_GPORT_IS_MIM_PORT(endpoint_info->gport) || 6421 BCM_GPORT_IS_MPLS_PORT(endpoint_info->gport)) { 6422 vp = local_id; 6423 src_glp = dst_glp = ((module_id << SOC_MODID_BIT_POS(unit)) | port_id); 6424 6425 BCM_IF_ERROR_RETURN 6426 (_bcm_esw_modid_is_local(unit, module_id, &is_local)); 6427 if (is_local) { 6428 src_glp = dst_glp = ((module_id << SOC_MODID_BIT_POS(unit)) | port_id); 6429 } else { 6430 return BCM_E_PARAM; 6431 } 6432 } 6433 6434 /* 6435 * At this point, both src_glp and dst_glp should be valid. 6436 * Gport types other than TRUNK, MODPORT or LOCAL are not valid. 6437 */ 6438 if (_BCM_OAM_INVALID_INDEX == src_glp 6439 || _BCM_OAM_INVALID_INDEX == dst_glp) { 6440 return (BCM_E_PORT); 6441 } 6442 6443 quantization_index = 6444 _bcm_en_oam_quantize_ccm_period(endpoint_info->ccm_period); 6445 6446 6447 /* 6448 * Ethernet 6449 */ 6450 if (endpoint_info->type == bcmOAMEndpointTypeEthernet) 6451 { 6452 endpoint_p->type = endpoint_info->type; 6453 if (is_remote) 6454 { 6455 if (replace && !endpoint_p->is_remote) { 6456 /* Replacing Local to Remote, Delete existing LMEP */ 6457 BCM_IF_ERROR_RETURN(_bcm_en_oam_delete_lmep(unit, endpoint_p)); 6458 } 6459 6460 if ( !(replace) || (replace && !endpoint_p->is_remote) ) { 6461 /* Creating new Remote. Hence create new RMEP entry. 6462 Else if replace operation, reuse existing RMEP */ 6463 endpoint_p->remote_index = _bcm_en_oam_find_free_endpoint( 6464 oam_info_p->remote_endpoints_in_use, 6465 oam_info_p->remote_endpoint_count, 1, 0); 6466 if (endpoint_p->remote_index < 0) { 6467 return BCM_E_FULL; 6468 } 6469 6470 /* RMEP entry */ 6471 6472 sal_memset(&rmep_entry, 0, sizeof(rmep_entry_t)); 6473 6474 soc_RMEPm_field32_set(unit, &rmep_entry, MAID_INDEXf, 6475 endpoint_info->group); 6476 6477 /* 6478 * The following steps are necessary to enable CCM timeout events 6479 * without having received any CCMs. 6480 */ 6481 soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMP_VALIDf, 1); 6482 BCM_IF_ERROR_RETURN(READ_OAM_CURRENT_TIMEr(unit, &oam_current_time)); 6483 soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_TIMESTAMPf, 6484 oam_current_time); 6485 soc_RMEPm_field32_set(unit, &rmep_entry, RMEP_RECEIVED_CCMf, 6486 quantization_index); 6487 6488 /* End of timeout setup */ 6489 6490 soc_RMEPm_field32_set(unit, &rmep_entry, VALIDf, 1); 6491 6492 SOC_IF_ERROR_RETURN(WRITE_RMEPm(unit, MEM_BLOCK_ALL, 6493 endpoint_p->remote_index, &rmep_entry)); 6494 } 6495 6496 /* L3 entry */ 6497 if (replace && endpoint_p->is_remote) { 6498 if (vp != 0) { 6499 _bcm_en_oam_make_rmep_key(unit, &l3_key, endpoint_p->name, 6500 endpoint_p->level, 0, endpoint_p->vp); 6501 } else { 6502 _bcm_en_oam_make_rmep_key(unit, &l3_key, endpoint_p->name, 6503 endpoint_p->level, endpoint_p->vlan, endpoint_p->glp); 6504 } 6505 rv = soc_mem_search(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ANY, 6506 &l3_index, &l3_key, &l3_entry, 0); 6507 /* See if key not changed. */ 6508 if ((endpoint_info->name == endpoint_p->name) && 6509 (endpoint_info->level == endpoint_p->level) && 6510 (((endpoint_info->vlan == endpoint_p->vlan) && 6511 (src_glp == endpoint_p->glp)) || (vp == endpoint_p->vp))) { 6512 if (BCM_E_NONE == rv) { 6513 /* Replace current entry */ 6514 replace_l3_entry = 1; 6515 } 6516 } else { 6517 /* Delete replaced L3 RMEP. */ 6518 SOC_IF_ERROR_RETURN(soc_mem_delete(unit, L3_ENTRY_IPV4_UNICASTm, 6519 MEM_BLOCK_ALL, &l3_key)); 6520 } 6521 } 6522 sal_memset(&l3_entry, 0, sizeof(l3_entry_ipv4_unicast_entry_t)); 6523 6524 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__CCMf, 6525 quantization_index); 6526 6527 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__RMEP_PTRf, 6528 endpoint_p->remote_index); 6529 6530 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__MEPIDf, 6531 endpoint_info->name); 6532 6533 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__MDLf, 6534 endpoint_info->level); 6535 6536 if (vp) { 6537 #if defined(BCM_KATANA_SUPPORT) 6538 if (SOC_IS_KATANAX(unit)) { 6539 if(endpoint_info->flags & BCM_OAM_ENDPOINT_PBB_TE) { 6540 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, 6541 RMEP__ENTRY_IS_SVPf, 6542 1); 6543 } 6544 } 6545 #endif /* BCM_KATANA_SUPPORT */ 6546 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__VIDf, 0); 6547 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__SGLPf, vp); 6548 } else { 6549 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__VIDf, 6550 endpoint_info->vlan); 6551 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, RMEP__SGLPf, src_glp); 6552 } 6553 6554 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, KEY_TYPEf, 6555 TR_L3_HASH_KEY_TYPE_RMEP); 6556 6557 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, VALIDf, 1); 6558 6559 if (replace_l3_entry) { 6560 SOC_IF_ERROR_RETURN( 6561 soc_mem_write(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ALL, 6562 l3_index, &l3_entry)); 6563 } else { 6564 SOC_IF_ERROR_RETURN( 6565 soc_mem_insert(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ALL, &l3_entry)); 6566 } 6567 6568 /* Local control block */ 6569 6570 SHR_BITSET(oam_info_p->remote_endpoints_in_use, 6571 endpoint_p->remote_index); 6572 6573 oam_info_p->remote_endpoints[endpoint_p->remote_index] = 6574 endpoint_index; 6575 } 6576 else 6577 { 6578 6579 if (replace && endpoint_p->is_remote) { 6580 /* Delete original RMEP. */ 6581 BCM_IF_ERROR_RETURN(_bcm_en_oam_delete_rmep(unit, endpoint_p)); 6582 } 6583 6584 if (replace && endpoint_p->local_rx_enabled) { 6585 /* Delete replaced L3 LMEP and keep LMEP entry. */ 6586 result = endpoint_p->local_tx_enabled; 6587 BCM_IF_ERROR_RETURN(_bcm_en_oam_delete_lmep(unit, endpoint_p)); 6588 endpoint_p->local_tx_enabled = result; 6589 } 6590 6591 if (local_tx_enabled) 6592 { 6593 uint32 reversed_maid[BCM_OAM_GROUP_NAME_LENGTH / 4]; 6594 int word_index; 6595 6596 if (!(replace && endpoint_p->local_tx_enabled)) { 6597 endpoint_p->local_tx_index = 6598 _bcm_en_oam_find_free_endpoint(oam_info_p-> 6599 local_tx_endpoints_in_use, 6600 oam_info_p->local_tx_endpoint_count, 1, 0); 6601 6602 if (endpoint_p->local_tx_index < 0) 6603 { 6604 return BCM_E_FULL; 6605 } 6606 } 6607 6608 /* LMEP entry */ 6609 6610 sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t)); 6611 soc_LMEPm_field32_set(unit, &lmep_entry, MAID_INDEXf, 6612 endpoint_info->group); 6613 6614 soc_LMEPm_mac_addr_set(unit, &lmep_entry, SAf, 6615 endpoint_info->src_mac_address); 6616 6617 soc_LMEPm_field32_set(unit, &lmep_entry, MDLf, endpoint_info->level); 6618 soc_LMEPm_field32_set(unit, &lmep_entry, MEPIDf, endpoint_info->name); 6619 6620 soc_LMEPm_field32_set(unit, &lmep_entry, PRIORITYf, 6621 endpoint_info->pkt_pri); 6622 6623 soc_LMEPm_field32_set(unit, &lmep_entry, VLAN_IDf, endpoint_info->vlan); 6624 soc_LMEPm_field32_set(unit, &lmep_entry, CCMf, quantization_index); 6625 6626 soc_LMEPm_field32_set(unit, &lmep_entry, DESTf, dst_glp); 6627 6628 soc_LMEPm_field32_set(unit, &lmep_entry, MH_OPCODEf, 6629 BCM_HG_OPCODE_UC); 6630 6631 soc_LMEPm_field32_set(unit, &lmep_entry, INT_PRIf, 6632 endpoint_info->int_pri); 6633 6634 if (endpoint_info->flags & BCM_OAM_ENDPOINT_PORT_STATE_UPDATE) { 6635 if (endpoint_info->port_state > BCM_OAM_PORT_TLV_UP) { 6636 return BCM_E_PARAM; 6637 } 6638 soc_LMEPm_field32_set(unit, &lmep_entry, PORT_TLVf, 6639 (endpoint_info->port_state == BCM_OAM_PORT_TLV_UP) ? 1 : 0); 6640 } 6641 6642 if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_UPDATE) { 6643 if (SOC_IS_ENDURO(unit)) { 6644 if (endpoint_info->interface_state > BCM_OAM_INTERFACE_TLV_DOWN) { 6645 return BCM_E_PARAM; 6646 } 6647 soc_LMEPm_field32_set(unit, &lmep_entry, INTERFACE_TLVf, 6648 (endpoint_info->interface_state == BCM_OAM_INTERFACE_TLV_UP) ? 1 : 0); 6649 } else { 6650 if (endpoint_info->interface_state > BCM_OAM_INTERFACE_TLV_LLDOWN) { 6651 return BCM_E_PARAM; 6652 } 6653 soc_LMEPm_field32_set(unit, &lmep_entry, INTERFACE_TLVf, 6654 endpoint_info->interface_state); 6655 } 6656 } 6657 6658 if ((endpoint_info->flags & BCM_OAM_ENDPOINT_PORT_STATE_TX) || 6659 (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERFACE_STATE_TX)) { 6660 soc_LMEPm_field32_set(unit, &lmep_entry, INSERT_TLVf, 1); 6661 } 6662 6663 /* Word-reverse the MAID bytes for the hardware */ 6664 6665 for (word_index = 0; 6666 word_index < (BCM_OAM_GROUP_NAME_LENGTH / 4); 6667 ++word_index) 6668 { 6669 reversed_maid[word_index] = 6670 bcm_htonl(((uint32 *) group_p->name) 6671 [((BCM_OAM_GROUP_NAME_LENGTH / 4) - 1) - word_index]); 6672 } 6673 6674 soc_LMEPm_field_set(unit, &lmep_entry, MAIDf, reversed_maid); 6675 6676 SOC_IF_ERROR_RETURN(WRITE_LMEPm(unit, MEM_BLOCK_ALL, 6677 endpoint_p->local_tx_index, &lmep_entry)); 6678 6679 /* LMEP_1 entry */ 6680 6681 sal_memset(&lmep1_entry, 0, sizeof(lmep_1_entry_t)); 6682 6683 soc_LMEP_1m_mac_addr_set(unit, &lmep1_entry, MACDAf, 6684 endpoint_info->dst_mac_address); 6685 6686 SOC_IF_ERROR_RETURN(WRITE_LMEP_1m(unit, MEM_BLOCK_ALL, 6687 endpoint_p->local_tx_index, &lmep1_entry)); 6688 6689 /* Local control block */ 6690 6691 SHR_BITSET(oam_info_p->local_tx_endpoints_in_use, 6692 endpoint_p->local_tx_index); 6693 } 6694 6695 if (local_rx_enabled) 6696 { 6697 6698 /* L3 entry */ 6699 L3_LOCK(unit); 6700 6701 if (BCM_SUCCESS(_bcm_en_oam_find_lmep(unit, endpoint_info->vlan, 6702 src_glp, &l3_index, &l3_entry)) || 6703 BCM_SUCCESS(_bcm_en_oam_find_lmep(unit, 0, 6704 vp, &l3_index, &l3_entry))) 6705 { 6706 rv = BCM_E_NONE; 6707 /* 6708 * If there is a MATCH, check if this MD level is available at this 6709 * index. If it's already occupied, report resource error. 6710 * Else this MD level is available at this index. 6711 */ 6712 6713 level_bitmap = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 6714 &l3_entry, LMEP__MDL_BITMAPf); 6715 6716 level_bitmap &= (1 << endpoint_info->level); 6717 6718 if (!level_bitmap) { 6719 endpoint_p->local_rx_index = 6720 ((soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, 6721 LMEP__MA_BASE_PTRf) << 3) | endpoint_info->level); 6722 level_bitmap = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, 6723 &l3_entry, LMEP__MDL_BITMAPf); 6724 level_bitmap |= (1 << endpoint_info->level); 6725 rv = soc_mem_field32_modify(unit, L3_ENTRY_IPV4_UNICASTm, 6726 l3_index, LMEP__MDL_BITMAPf, level_bitmap); 6727 } else { 6728 rv = BCM_E_RESOURCE; 6729 } 6730 } else { 6731 rv = BCM_E_NONE; 6732 /* 6733 * If Entry is NOT found, select a new MA_INDEX for this MDL. 6734 */ 6735 6736 for (i = 0; i < oam_info_p->local_rx_endpoint_count; i += 8) 6737 { 6738 SHR_BITTEST_RANGE(oam_info_p->local_rx_endpoints_in_use, 6739 i, 8, mdl_set); 6740 if (0 == mdl_set) { 6741 break; 6742 } 6743 } 6744 if (i >= oam_info_p->local_rx_endpoint_count) { 6745 rv = BCM_E_FULL; 6746 } else { 6747 endpoint_p->local_rx_index = (i + endpoint_info->level); 6748 6749 sal_memset(&l3_entry, 0, sizeof(l3_entry_ipv4_unicast_entry_t)); 6750 6751 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, 6752 LMEP__MDL_BITMAPf, 1 << endpoint_info->level); 6753 6754 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, 6755 LMEP__MA_BASE_PTRf, 6756 endpoint_p->local_rx_index >> LEVEL_BIT_COUNT); 6757 6758 SET_LMEP_FIELD(unit, LMEP__DM_ENABLEf, endpoint_info->flags, 6759 BCM_OAM_ENDPOINT_DELAY_MEASUREMENT); 6760 SET_LMEP_FIELD(unit, LMEP__CCM_ENABLEf, endpoint_info->flags, 6761 BCM_OAM_ENDPOINT_CCM_RX); 6762 SET_LMEP_FIELD(unit, LMEP__LB_ENABLEf, endpoint_info->flags, 6763 BCM_OAM_ENDPOINT_LOOPBACK); 6764 SET_LMEP_FIELD(unit, LMEP__LT_ENABLEf, endpoint_info->flags, 6765 BCM_OAM_ENDPOINT_LINKTRACE); 6766 if (vp) { 6767 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, LMEP__VIDf, 6768 0); 6769 6770 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, LMEP__SGLPf, 6771 vp); 6772 } else { 6773 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, LMEP__VIDf, 6774 endpoint_info->vlan); 6775 6776 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, LMEP__SGLPf, 6777 src_glp); 6778 } 6779 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, KEY_TYPEf, 6780 TR_L3_HASH_KEY_TYPE_LMEP); 6781 6782 soc_L3_ENTRY_IPV4_UNICASTm_field32_set(unit, &l3_entry, VALIDf, 1); 6783 6784 rv = soc_mem_insert(unit, L3_ENTRY_IPV4_UNICASTm, 6785 MEM_BLOCK_ALL, &l3_entry); 6786 } 6787 } 6788 6789 L3_UNLOCK(unit); 6790 6791 if (rv != BCM_E_NONE && local_tx_enabled) 6792 { 6793 /* 6794 * Clean LMEP TX configuration. 6795 */ 6796 sal_memset(&lmep_entry, 0, sizeof(lmep_entry_t)); 6797 SOC_IF_ERROR_RETURN(WRITE_LMEPm(unit, MEM_BLOCK_ALL, 6798 endpoint_p->local_tx_index, &lmep_entry)); 6799 /* 6800 * Local control block 6801 */ 6802 SHR_BITCLR(oam_info_p->local_tx_endpoints_in_use, 6803 endpoint_p->local_tx_index); 6804 6805 return rv; 6806 } 6807 6808 #if defined(BCM_KATANA_SUPPORT) 6809 if (SOC_IS_KATANAX(unit)) { 6810 if (endpoint_info->opcode_flags) { 6811 SOC_IF_ERROR_RETURN 6812 (_bcm_kt_set_oam_opcode_profile_entry(unit, 6813 endpoint_info->opcode_flags, 6814 &opcode_entry)); 6815 } else { 6816 SOC_IF_ERROR_RETURN 6817 (_bcm_kt_get_default_oam_opcode_profile_entry(unit, 6818 &opcode_entry)); 6819 } 6820 soc_mem_lock(unit, OAM_OPCODE_CONTROL_PROFILEm); 6821 entries[0] = &opcode_entry; 6822 SOC_IF_ERROR_RETURN 6823 (soc_profile_mem_add(unit, oam_opcode_profile[unit], 6824 (void *) &entries, 1, &temp_index)); 6825 endpoint_p->opcode_profile_index = temp_index; 6826 soc_mem_unlock(unit, OAM_OPCODE_CONTROL_PROFILEm); 6827 } 6828 #endif /* BCM_KATANA_SUPPORT */ 6829 6830 /* MA_INDEX entry */ 6831 6832 sal_memset(&ma_index_entry, 0, sizeof(ma_index_entry)); 6833 6834 soc_MA_INDEXm_field32_set(unit, &ma_index_entry, MA_PTRf, 6835 endpoint_info->group); 6836 #if defined(BCM_KATANA_SUPPORT) 6837 if (SOC_IS_KATANAX(unit)) { 6838 soc_MA_INDEXm_field32_set(unit, &ma_index_entry, 6839 OAM_OPCODE_CONTROL_PROFILE_PTRf, 6840 endpoint_p->opcode_profile_index); 6841 if (endpoint_info->opcode_flags & BCM_OAM_OPCODE_CCM_COPY_TO_CPU) { 6842 soc_MA_INDEXm_field32_set(unit,&ma_index_entry, 6843 CPU_QUEUE_NUMf, 6844 endpoint_info->cpu_qid); 6845 } 6846 } 6847 #endif /* BCM_KATANA_SUPPORT */ 6848 6849 SOC_IF_ERROR_RETURN(WRITE_MA_INDEXm(unit, MEM_BLOCK_ALL, 6850 endpoint_p->local_rx_index, &ma_index_entry)); 6851 6852 SHR_BITSET(oam_info_p->local_rx_endpoints_in_use, 6853 endpoint_p->local_rx_index); 6854 } /* local_rx */ 6855 } 6856 /* Local control block */ 6857 6858 endpoint_p->is_remote = is_remote; 6859 endpoint_p->local_tx_enabled = local_tx_enabled; 6860 endpoint_p->local_rx_enabled = local_rx_enabled; 6861 endpoint_p->group_index = endpoint_info->group; 6862 endpoint_p->name = endpoint_info->name; 6863 endpoint_p->level = endpoint_info->level; 6864 endpoint_p->vlan = endpoint_info->vlan; 6865 endpoint_p->vp = vp; 6866 endpoint_p->glp = src_glp; 6867 endpoint_p->flags = endpoint_info->flags; 6868 #if defined(BCM_KATANA_SUPPORT) 6869 endpoint_p->opcode_flags = endpoint_info->opcode_flags; 6870 #endif /* BCM_KATANA_SUPPORT */ 6871 6872 if (local_rx_enabled) { 6873 if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 6874 *num_lm = _bcm_en_oam_lm_search(unit, endpoint_p, 1, mdl_index); 6875 if (*num_lm == 1) { 6876 /* Assign LM counter index for the first LM endpoint */ 6877 endpoint_p->lm_counter_index = 6878 _bcm_en_oam_find_free_endpoint(oam_info_p->lm_counter_in_use, 6879 oam_info_p->lm_counter_count, BCM_OAM_LM_COUNTER_OFFSET, 0); 6880 6881 if (endpoint_p->lm_counter_index < 0) { 6882 return BCM_E_FULL; 6883 } 6884 6885 SHR_BITSET(oam_info_p->lm_counter_in_use, 6886 endpoint_p->lm_counter_index); 6887 6888 /* Assign Pri Mapping pointer */ 6889 for (i = 0; i < BCM_OAM_INTPRI_MAX ; i++) { 6890 mem_entries[i] = endpoint_info->pri_map[i]; 6891 if (SOC_MEM_FIELD_VALID(unit, ING_SERVICE_PRI_MAPm, OFFSET_VALIDf)) { 6892 soc_mem_field32_set(unit, ING_SERVICE_PRI_MAPm, &mem_entries[i], 6893 OFFSET_VALIDf, 1); 6894 } 6895 } 6896 soc_mem_lock(unit, ING_SERVICE_PRI_MAPm); 6897 6898 entries[0] = &mem_entries; 6899 SOC_IF_ERROR_RETURN 6900 (soc_profile_mem_add(unit, ing_pri_map_profile[unit], 6901 (void *) &entries, BCM_OAM_INTPRI_MAX, &temp_index)); 6902 endpoint_p->pri_map_index = temp_index/BCM_OAM_INTPRI_MAX; 6903 soc_mem_unlock(unit, ING_SERVICE_PRI_MAPm); 6904 BCM_IF_ERROR_RETURN( 6905 _bcm_en_oam_install_fp(unit, 0, endpoint_p)); 6906 } else { 6907 for (i = 0; i < *num_lm; i++) { 6908 current_endpoint_p = oam_info_p->endpoints + mdl_index[i]; 6909 BCM_IF_ERROR_RETURN( 6910 _bcm_en_oam_install_fp(unit, 6911 (i == (*num_lm-1)) ? 0 : 1, current_endpoint_p)); 6912 } 6913 } 6914 } 6915 6916 if ((endpoint_info->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) && 6917 !(endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) { 6918 BCM_IF_ERROR_RETURN( 6919 _bcm_en_oam_install_fp(unit, 0, endpoint_p)); 6920 } 6921 6922 if (endpoint_info->flags & BCM_OAM_ENDPOINT_PBB_TE) { 6923 /* Install VFP */ 6924 BCM_IF_ERROR_RETURN( 6925 _bcm_en_oam_install_vfp(unit, endpoint_index, endpoint_info)); 6926 } 6927 } 6928 } 6929 /* 6930 * BHH Specific 6931 */ 6932 else if (soc_feature(unit, soc_feature_bhh) && 6933 ((endpoint_info->type == bcmOAMEndpointTypeBHHMPLS) || 6934 (endpoint_info->type == bcmOAMEndpointTypeBHHMPLSVccv))) { 6935 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 6936 6937 /* 6938 * The uKernel is not provisioned until both endpoints (local and remote) 6939 * are provisioned in the host. 6940 */ 6941 if (is_remote) { 6942 /* 6943 * Find the local endpoint. If it can't be found then abort. 6944 */ 6945 VALIDATE_ENDPOINT_INDEX(endpoint_info->local_id); 6946 6947 if (!oam_info_p->endpoints[endpoint_info->local_id].in_use) { 6948 return BCM_E_NOT_FOUND; 6949 } else if (oam_info_p->endpoints[endpoint_info->local_id].flags & BCM_OAM_ENDPOINT_REMOTE) { 6950 return BCM_E_EXISTS; 6951 } 6952 6953 /* 6954 * Now that both ends are provisioned the uKernel can be 6955 * configured. 6956 */ 6957 msg_rmep_create.sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, 6958 endpoint_info->local_id); 6959 msg_rmep_create.flags = 0; 6960 msg_rmep_create.enable = 1; 6961 msg_rmep_create.remote_mep_id = endpoint_info->name; 6962 6963 msg_rmep_create.period = en_ccm_periods[quantization_index]; 6964 6965 /* Pack control message data into DMA buffer */ 6966 buffer = oam_info_p->dma_buffer; 6967 buffer_ptr = bhh_sdk_msg_ctrl_rmep_create_pack(buffer, &msg_rmep_create); 6968 buffer_len = buffer_ptr - buffer; 6969 6970 /* Send BHH Session Update message to uC */ 6971 BCM_IF_ERROR_RETURN 6972 (_bcm_en_oam_bhh_msg_send_receive(unit, 6973 MOS_MSG_SUBCLASS_BHH_RMEP_CREATE, 6974 buffer_len, 0, 6975 MOS_MSG_SUBCLASS_BHH_RMEP_CREATE_REPLY, 6976 &reply_len)); 6977 if (reply_len != 0) { 6978 return BCM_E_INTERNAL; 6979 } 6980 6981 } else { 6982 6983 endpoint_p->type = endpoint_info->type; 6984 endpoint_p->name = endpoint_info->name; 6985 endpoint_p->level = endpoint_info->level; 6986 endpoint_p->vccv_type = endpoint_info->vccv_type; 6987 endpoint_p->group_index = endpoint_info->group; 6988 endpoint_p->vlan = endpoint_info->vlan; 6989 endpoint_p->vlan_pri = endpoint_info->pkt_pri; 6990 endpoint_p->inner_vlan_pri = endpoint_info->inner_pkt_pri; 6991 endpoint_p->vpn = endpoint_info->vpn; 6992 endpoint_p->vp = vp; 6993 endpoint_p->glp = src_glp; 6994 endpoint_p->egress_if = endpoint_info->intf_id; 6995 endpoint_p->cpu_qid = endpoint_info->cpu_qid; 6996 endpoint_p->label = endpoint_info->mpls_label; 6997 endpoint_p->gport = endpoint_info->gport; 6998 endpoint_p->trunk_index = endpoint_info->trunk_index; 6999 endpoint_p->flags = endpoint_info->flags; 7000 endpoint_p->local_tx_enabled = 0; 7001 endpoint_p->local_rx_enabled = 0; 7002 endpoint_p->egr_label = endpoint_info->egress_label.label; 7003 endpoint_p->egr_label_exp = endpoint_info->egress_label.exp; 7004 endpoint_p->egr_label_ttl = endpoint_info->egress_label.ttl; 7005 7006 /* Get local port used for TX BFD packet */ 7007 BCM_IF_ERROR_RETURN 7008 (_bcm_esw_modid_is_local(unit, module_id, &is_local)); 7009 if (!is_local) { /* HG port */ 7010 BCM_IF_ERROR_RETURN 7011 (bcm_esw_stk_modport_get(unit, module_id, &port_id)); 7012 } 7013 7014 7015 /* Create or Update */ 7016 session_flags = (replace) ? 0 : SHR_BHH_SESS_SET_F_CREATE; 7017 7018 /* Set Endpoint config entry */ 7019 endpoint_p->bhh_endpoint_index = endpoint_index; 7020 7021 7022 /* Set Encapsulation in HW */ 7023 if (!replace || (endpoint_info->flags & BCM_BHH_ENDPOINT_ENCAP_SET)) { 7024 BCM_IF_ERROR_RETURN 7025 (_bcm_en_oam_bhh_encap_hw_set(unit, endpoint_p, module_id, 7026 port_id, is_local, endpoint_info->int_pri)); 7027 encap = 1; 7028 } 7029 7030 7031 /* Set control message data */ 7032 sal_memset(&msg_sess, 0, sizeof(msg_sess)); 7033 7034 /* 7035 * Set the BHH encapsulation data 7036 * 7037 * The function _bcm_en_oam_bhh_encap_create() is called first 7038 * since this sets some fields in 'endpoint_p' which are 7039 * used in the message. 7040 */ 7041 if (encap) { 7042 BCM_IF_ERROR_RETURN 7043 (_bcm_en_oam_bhh_encap_create(unit, 7044 port_id, 7045 endpoint_p, 7046 msg_sess.encap_data, 7047 &msg_sess.encap_type, 7048 &msg_sess.encap_length)); 7049 } 7050 7051 /* 7052 * Endpoint can be one of: CCM, LB, LM or DM. The default is CCM, 7053 * all others modes must be specified via a config flag. 7054 */ 7055 if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOOPBACK) 7056 session_flags |= SHR_BHH_SESS_SET_F_LB; 7057 else if (endpoint_info->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) 7058 session_flags |= SHR_BHH_SESS_SET_F_DM; 7059 else if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) 7060 session_flags |= SHR_BHH_SESS_SET_F_LM; 7061 else 7062 session_flags |= SHR_BHH_SESS_SET_F_CCM; 7063 7064 if (endpoint_info->flags & BCM_OAM_ENDPOINT_INTERMEDIATE) 7065 session_flags |= SHR_BHH_SESS_SET_F_MIP; 7066 7067 _bcm_en_oam_get_group_sw_rdi (unit, endpoint_info->group, 7068 &group_sw_rdi); 7069 if (group_sw_rdi) { 7070 session_flags |= SHR_BHH_SESS_SET_F_RDI; 7071 } 7072 msg_sess.sess_id = 7073 BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, 7074 endpoint_p->bhh_endpoint_index); 7075 msg_sess.flags = session_flags; 7076 7077 if (endpoint_p->level > _BCM_OAM_BHH_MEL_MAX) 7078 return BCM_E_PARAM; 7079 7080 msg_sess.mel = endpoint_p->level; 7081 msg_sess.mep_id = endpoint_p->name; 7082 sal_memcpy(msg_sess.meg_id, group_p->name, BCM_OAM_GROUP_NAME_LENGTH); 7083 7084 msg_sess.period = en_ccm_periods[quantization_index]; 7085 7086 msg_sess.if_num = endpoint_info->intf_id; 7087 msg_sess.tx_port = port_id; 7088 if (BCM_TRUNK_INVALID == trunk_id) { 7089 msg_sess.rx_port = port_id; 7090 } else { 7091 msg_sess.rx_port = trunk_id; 7092 msg_sess.trunk_valid = 1; 7093 } 7094 msg_sess.tx_cos = endpoint_info->int_pri; 7095 msg_sess.tx_pri = endpoint_info->pkt_pri; 7096 msg_sess.tx_qnum = SOC_INFO(unit).port_cosq_base[port_id] + endpoint_info->int_pri; 7097 7098 msg_sess.mpls_label = endpoint_info->mpls_label; 7099 7100 switch (endpoint_p->type) { 7101 case bcmOAMEndpointTypeBHHMPLS: 7102 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_LSP; 7103 msg_sess.priority = endpoint_info->mpls_exp; 7104 break; 7105 7106 case bcmOAMEndpointTypeBHHMPLSVccv: 7107 switch(endpoint_p->vccv_type) { 7108 7109 case bcmOamBhhVccvChannelAch: 7110 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_1; 7111 msg_sess.priority = endpoint_info->mpls_exp; 7112 break; 7113 7114 case bcmOamBhhVccvRouterAlert: 7115 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_2; 7116 msg_sess.priority = endpoint_info->mpls_exp; 7117 break; 7118 7119 case bcmOamBhhVccvTtl: 7120 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_3; 7121 msg_sess.priority = endpoint_info->mpls_exp; 7122 break; 7123 7124 case bcmOamBhhVccvGal13: 7125 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PW_VCCV_4; 7126 msg_sess.priority = endpoint_info->mpls_exp; 7127 break; 7128 7129 default: 7130 return BCM_E_PARAM; 7131 break; 7132 } 7133 break; 7134 7135 case bcmOAMEndpointTypeBhhSection: 7136 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION; 7137 msg_sess.priority = 0; 7138 break; 7139 case bcmOAMEndpointTypeBhhSectionInnervlan: 7140 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_INNERVLAN; 7141 msg_sess.priority = endpoint_info->inner_pkt_pri; 7142 break; 7143 case bcmOAMEndpointTypeBhhSectionOuterVlan: 7144 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTERVLAN; 7145 msg_sess.priority = endpoint_info->pkt_pri; 7146 break; 7147 case bcmOAMEndpointTypeBhhSectionOuterPlusInnerVlan: 7148 msg_sess.endpoint_type = _SHR_BHH_EP_TYPE_PORT_SECTION_OUTER_PLUS_INNERVLAN; 7149 msg_sess.priority = endpoint_info->pkt_pri; 7150 break; 7151 7152 default: 7153 return BCM_E_PARAM; 7154 } 7155 7156 /* Pack control message data into DMA buffer */ 7157 buffer = oam_info_p->dma_buffer; 7158 buffer_ptr = bhh_sdk_msg_ctrl_sess_set_pack(buffer, &msg_sess); 7159 buffer_len = buffer_ptr - buffer; 7160 7161 /* Send BHH Session Update message to uC */ 7162 BCM_IF_ERROR_RETURN 7163 (_bcm_en_oam_bhh_msg_send_receive(unit, 7164 MOS_MSG_SUBCLASS_BHH_SESS_SET, 7165 buffer_len, 0, 7166 MOS_MSG_SUBCLASS_BHH_SESS_SET_REPLY, 7167 &reply_len)); 7168 if (reply_len != 0) { 7169 return BCM_E_INTERNAL; 7170 } 7171 } /* is_remote */ 7172 #else 7173 return (BCM_E_UNAVAIL); 7174 #endif /* defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) */ 7175 } 7176 else { 7177 return (BCM_E_PARAM); 7178 } 7179 7180 endpoint_p->in_use = 1; 7181 7182 #ifdef BCM_WARM_BOOT_SUPPORT 7183 SOC_CONTROL_LOCK(unit); 7184 SOC_CONTROL(unit)->scache_dirty = 1; 7185 SOC_CONTROL_UNLOCK(unit); 7186 #endif 7187 7188 return BCM_E_NONE; 7189 } 7190 7191 int 7192 bcm_en_oam_endpoint_create( 7193 int unit, 7194 bcm_oam_endpoint_info_t *endpoint_info) 7195 { 7196 int i, j, rv, num_lm = 0, mdl_index[LEVEL_COUNT]; 7197 _bcm_oam_info_t *oam_info_p; 7198 _bcm_oam_endpoint_t *created_endpoint_p = NULL, *current_endpoint_p; 7199 7200 rv = _bcm_en_oam_create_endpoint(unit, endpoint_info, &created_endpoint_p, 7201 &num_lm, mdl_index); 7202 7203 if (BCM_SUCCESS(rv) && (created_endpoint_p != NULL)) { 7204 if (endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT) { 7205 if (num_lm == 1) { 7206 BCM_IF_ERROR_RETURN( 7207 bcm_esw_field_entry_install(unit, created_endpoint_p->fp_entry_tx)); 7208 BCM_IF_ERROR_RETURN( 7209 bcm_esw_field_entry_install(unit, created_endpoint_p->fp_entry_rx)); 7210 for (j = 0; j < BCM_SWITCH_TRUNK_MAX_PORTCNT; j++) { 7211 if (created_endpoint_p->fp_entry_trunk[j]) { 7212 BCM_IF_ERROR_RETURN( 7213 bcm_esw_field_entry_install(unit, created_endpoint_p->fp_entry_trunk[j])); 7214 } 7215 } 7216 } else { 7217 SET_OAM_INFO; 7218 for (i = 0; i < num_lm; i++) { 7219 current_endpoint_p = oam_info_p->endpoints + mdl_index[i]; 7220 BCM_IF_ERROR_RETURN( 7221 bcm_esw_field_entry_install(unit, current_endpoint_p->fp_entry_tx)); 7222 BCM_IF_ERROR_RETURN( 7223 bcm_esw_field_entry_install(unit, current_endpoint_p->fp_entry_rx)); 7224 for (j = 0; j < BCM_SWITCH_TRUNK_MAX_PORTCNT; j++) { 7225 if (current_endpoint_p->fp_entry_trunk[j]) { 7226 BCM_IF_ERROR_RETURN( 7227 bcm_esw_field_entry_install(unit, current_endpoint_p->fp_entry_trunk[j])); 7228 } 7229 } 7230 } 7231 } 7232 } 7233 7234 if ((endpoint_info->flags & BCM_OAM_ENDPOINT_DELAY_MEASUREMENT) && 7235 !(endpoint_info->flags & BCM_OAM_ENDPOINT_LOSS_MEASUREMENT)) { 7236 if (created_endpoint_p->fp_entry_tx) { 7237 BCM_IF_ERROR_RETURN( 7238 bcm_esw_field_entry_install(unit, created_endpoint_p->fp_entry_tx)); 7239 } 7240 if (created_endpoint_p->fp_entry_rx) { 7241 BCM_IF_ERROR_RETURN( 7242 bcm_esw_field_entry_install(unit, created_endpoint_p->fp_entry_rx)); 7243 } 7244 for (j = 0; j < BCM_SWITCH_TRUNK_MAX_PORTCNT; j++) { 7245 if (created_endpoint_p->fp_entry_trunk[j]) { 7246 BCM_IF_ERROR_RETURN( 7247 bcm_esw_field_entry_install(unit, created_endpoint_p->fp_entry_trunk[j])); 7248 } 7249 } 7250 } 7251 7252 if (endpoint_info->flags & BCM_OAM_ENDPOINT_PBB_TE) { 7253 BCM_IF_ERROR_RETURN( 7254 bcm_esw_field_entry_install(unit, created_endpoint_p->vfp_entry)); 7255 7256 } 7257 } 7258 7259 return rv; 7260 } 7261 7262 static int _bcm_en_oam_get_endpoint(int unit, _bcm_oam_info_t *oam_info_p, int endpoint_index, 7263 _bcm_oam_endpoint_t *endpoint_p, bcm_oam_endpoint_info_t *endpoint_info) 7264 { 7265 rmep_entry_t rmep_entry; 7266 lmep_entry_t lmep_entry; 7267 l3_entry_ipv4_unicast_entry_t l3_key; 7268 l3_entry_ipv4_unicast_entry_t l3_entry; 7269 int l3_index; 7270 int quantization_index = 0; 7271 bcm_module_t module_id; 7272 bcm_port_t port_id; 7273 uint32 param0, param1; 7274 ing_service_pri_map_entry_t primap_entry; 7275 bcm_field_entry_t fp_entry; 7276 int i, rv = BCM_E_NONE; 7277 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 7278 bhh_sdk_msg_ctrl_sess_get_t msg; 7279 uint8 *buffer, *buffer_ptr; 7280 uint16 buffer_len, reply_len; 7281 int sess_id = 0; 7282 bcm_l3_egress_t l3_egress; 7283 bcm_l3_intf_t l3_intf; 7284 #endif 7285 7286 endpoint_info->id = endpoint_index; 7287 endpoint_info->group = endpoint_p->group_index; 7288 endpoint_info->name = endpoint_p->name; 7289 endpoint_info->level = endpoint_p->level; 7290 endpoint_info->vlan = endpoint_p->vlan; 7291 endpoint_info->type = endpoint_p->type; 7292 endpoint_info->flags = endpoint_p->flags; 7293 endpoint_info->trunk_index = endpoint_p->trunk_index; 7294 #if defined(BCM_KATANA_SUPPORT) 7295 endpoint_info->opcode_flags = endpoint_p->opcode_flags; 7296 #endif 7297 7298 if (endpoint_p->type == bcmOAMEndpointTypeEthernet) { 7299 if (endpoint_p->is_remote) 7300 { 7301 endpoint_info->flags |= BCM_OAM_ENDPOINT_REMOTE; 7302 7303 /* RMEP entry */ 7304 7305 SOC_IF_ERROR_RETURN(READ_RMEPm(unit, MEM_BLOCK_ANY, 7306 endpoint_p->remote_index, 7307 &rmep_entry)); 7308 7309 /* Get endpoint faults and clear presistent faults if Clear is SET */ 7310 BCM_IF_ERROR_RETURN(_bcm_en_oam_read_clear_faults(unit, 7311 endpoint_p->remote_index, 7312 en_endpoint_faults, 7313 RMEPm, 7314 (uint32 *) &rmep_entry, 7315 &endpoint_info->faults, 7316 &endpoint_info->persistent_faults, 7317 endpoint_info->clear_persistent_faults)); 7318 7319 if (endpoint_info->flags2 & BCM_OAM_ENDPOINT_FLAGS2_GET_FAULTS_ONLY) { 7320 endpoint_info->flags2 &= ~BCM_OAM_ENDPOINT_FLAGS2_GET_FAULTS_ONLY; 7321 return BCM_E_NONE; 7322 } 7323 /* L3 entry */ 7324 if (endpoint_p->vp != 0) { 7325 _bcm_en_oam_make_rmep_key(unit, &l3_key, endpoint_p->name, 7326 endpoint_p->level, 0, endpoint_p->vp); 7327 } else { 7328 _bcm_en_oam_make_rmep_key(unit, &l3_key, endpoint_p->name, 7329 endpoint_p->level, endpoint_p->vlan, endpoint_p->glp); 7330 } 7331 7332 if (BCM_FAILURE(soc_mem_search(unit, L3_ENTRY_IPV4_UNICASTm, MEM_BLOCK_ANY, 7333 &l3_index, &l3_key, &l3_entry, 0))) 7334 { 7335 return BCM_E_INTERNAL; 7336 } 7337 7338 quantization_index = soc_L3_ENTRY_IPV4_UNICASTm_field32_get(unit, &l3_entry, 7339 RMEP__CCMf); 7340 } 7341 else 7342 { 7343 /* Endpoint is local */ 7344 7345 if (endpoint_p->local_tx_enabled) 7346 { 7347 /* LMEP entry */ 7348 7349 SOC_IF_ERROR_RETURN(READ_LMEPm(unit, MEM_BLOCK_ANY, 7350 endpoint_p->local_tx_index, &lmep_entry)); 7351 7352 soc_LMEPm_mac_addr_get(unit, &lmep_entry, SAf, 7353 endpoint_info->src_mac_address); 7354 7355 endpoint_info->pkt_pri = soc_LMEPm_field32_get(unit, &lmep_entry, 7356 PRIORITYf); 7357 7358 endpoint_info->int_pri = soc_LMEPm_field32_get(unit, &lmep_entry, 7359 INT_PRIf); 7360 7361 quantization_index = soc_LMEPm_field32_get(unit, &lmep_entry, 7362 CCMf); 7363 7364 endpoint_info->port_state = 7365 soc_LMEPm_field32_get(unit, &lmep_entry, PORT_TLVf) ? 7366 BCM_OAM_PORT_TLV_UP : BCM_OAM_PORT_TLV_BLOCKED; 7367 7368 if (SOC_IS_ENDURO(unit)) { 7369 endpoint_info->interface_state = 7370 soc_LMEPm_field32_get(unit, &lmep_entry, INTERFACE_TLVf) ? 7371 BCM_OAM_INTERFACE_TLV_UP : BCM_OAM_INTERFACE_TLV_DOWN; 7372 } else { 7373 endpoint_info->interface_state = 7374 soc_LMEPm_field32_get(unit, &lmep_entry, INTERFACE_TLVf); 7375 } 7376 7377 if (soc_LMEPm_field32_get(unit, &lmep_entry, INSERT_TLVf)) { 7378 endpoint_info->flags |= (BCM_OAM_ENDPOINT_PORT_STATE_TX | 7379 BCM_OAM_ENDPOINT_INTERFACE_STATE_TX); 7380 } 7381 } 7382 7383 if (endpoint_p->local_rx_enabled) 7384 { 7385 /* L3 entry */ 7386 if (endpoint_p->vp != 0) { 7387 if (BCM_FAILURE(_bcm_en_oam_find_lmep(unit, 0, 7388 endpoint_p->vp, &l3_index, &l3_entry))) { 7389 return BCM_E_INTERNAL; 7390 } 7391 } else if (BCM_FAILURE(_bcm_en_oam_find_lmep(unit, endpoint_p->vlan, 7392 endpoint_p->glp, &l3_index, &l3_entry))) { 7393 return BCM_E_INTERNAL; 7394 } 7395 7396 GET_LMEP_FIELD(unit, LMEP__DM_ENABLEf, BCM_OAM_ENDPOINT_DELAY_MEASUREMENT); 7397 GET_LMEP_FIELD(unit, LMEP__CCM_ENABLEf, BCM_OAM_ENDPOINT_CCM_RX); 7398 GET_LMEP_FIELD(unit, LMEP__LB_ENABLEf, BCM_OAM_ENDPOINT_LOOPBACK); 7399 GET_LMEP_FIELD(unit, LMEP__LT_ENABLEf, BCM_OAM_ENDPOINT_LINKTRACE); 7400 7401 if (endpoint_p->fp_entry_tx != 0) { 7402 fp_entry = endpoint_p->fp_entry_tx; 7403 } else { 7404 fp_entry = endpoint_p->fp_entry_rx; 7405 } 7406 7407 if (fp_entry != 0) { 7408 rv = bcm_esw_field_action_get(unit, fp_entry, 7409 bcmFieldActionOamLmEnable, 7410 ¶m0, ¶m1); 7411 if (BCM_SUCCESS(rv)) { 7412 if (param0 != 0) { 7413 endpoint_info->flags |= BCM_OAM_ENDPOINT_LOSS_MEASUREMENT; 7414 } 7415 } 7416 7417 rv = bcm_esw_field_action_get(unit, fp_entry, 7418 bcmFieldActionOamUpMep, 7419 ¶m0, ¶m1); 7420 if (BCM_SUCCESS(rv)) { 7421 if (param0 != 0) { 7422 endpoint_info->flags |= BCM_OAM_ENDPOINT_UP_FACING; 7423 } 7424 } 7425 7426 rv = bcm_esw_field_action_get(unit, fp_entry, 7427 bcmFieldActionOamServicePriMappingPtr, 7428 ¶m0, ¶m1); 7429 if (BCM_SUCCESS(rv)) { 7430 for(i = 0; i < BCM_OAM_INTPRI_MAX; i++) { 7431 SOC_IF_ERROR_RETURN(READ_ING_SERVICE_PRI_MAPm(unit, 7432 MEM_BLOCK_ANY, 7433 param0*BCM_OAM_INTPRI_MAX+i, 7434 &primap_entry)); 7435 endpoint_info->pri_map[i] = 7436 (uint8)soc_ING_SERVICE_PRI_MAPm_field32_get(unit, &primap_entry, OFFSETf); 7437 } 7438 endpoint_info->pri_map_id = endpoint_p->pri_map_index; 7439 } 7440 } 7441 7442 if (endpoint_p->vfp_entry != 0) { 7443 endpoint_info->flags |= BCM_OAM_ENDPOINT_PBB_TE; 7444 } 7445 } 7446 } 7447 endpoint_info->ccm_period = en_ccm_periods[quantization_index]; 7448 } 7449 7450 #if defined(INCLUDE_L3) 7451 if (endpoint_p->vp != 0) { 7452 if (_bcm_vp_used_get(unit, endpoint_p->vp, _bcmVpTypeMim)) { 7453 BCM_GPORT_MIM_PORT_ID_SET(endpoint_info->gport, endpoint_p->vp); 7454 } else { 7455 BCM_GPORT_MPLS_PORT_ID_SET(endpoint_info->gport, endpoint_p->vp); 7456 } 7457 } else 7458 #endif /* INCLUDE_L3 */ 7459 { 7460 if (endpoint_p->glp & (1 << SOC_TRUNK_BIT_POS(unit))) 7461 { 7462 /* Trunk */ 7463 7464 BCM_GPORT_TRUNK_SET(endpoint_info->gport, endpoint_p->glp & 0x7F); 7465 } 7466 else 7467 { 7468 module_id = (endpoint_p->glp & SOC_MODID_MASK(unit)) >> 7469 SOC_MODID_BIT_POS(unit); 7470 port_id = (endpoint_p->glp & SOC_PORT_ADDR_MAX(unit)); 7471 7472 if (module_id != 0) 7473 { 7474 /* Modport */ 7475 7476 BCM_GPORT_MODPORT_SET(endpoint_info->gport, module_id, 7477 port_id); 7478 } 7479 else 7480 { 7481 /* Local port */ 7482 7483 BCM_IF_ERROR_RETURN(bcm_esw_port_gport_get(unit, port_id, 7484 &(endpoint_info->gport))); 7485 } 7486 } 7487 } 7488 7489 if (soc_feature(unit, soc_feature_bhh) && 7490 ((endpoint_p->type == bcmOAMEndpointTypeBHHMPLS) || 7491 (endpoint_p->type == bcmOAMEndpointTypeBHHMPLSVccv))) { 7492 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 7493 7494 sess_id = BCM_OAM_BHH_GET_UKERNEL_EP(oam_info_p, endpoint_index); 7495 7496 BCM_IF_ERROR_RETURN 7497 (_bcm_en_oam_bhh_msg_send_receive(unit, 7498 MOS_MSG_SUBCLASS_BHH_SESS_GET, 7499 sess_id, 0, 7500 MOS_MSG_SUBCLASS_BHH_SESS_GET_REPLY, 7501 &reply_len)); 7502 7503 /* Pack control message data into DMA buffer */ 7504 buffer = oam_info_p->dma_buffer; 7505 buffer_ptr = bhh_sdk_msg_ctrl_sess_get_unpack(buffer, &msg); 7506 buffer_len = buffer_ptr - buffer; 7507 if (reply_len != buffer_len) { 7508 return BCM_E_INTERNAL; 7509 } else { 7510 endpoint_info->int_pri = msg.tx_cos; 7511 endpoint_info->pkt_pri = msg.tx_pri; 7512 endpoint_info->mpls_exp = msg.priority; 7513 7514 if(endpoint_info->flags & BCM_OAM_ENDPOINT_REMOTE){ 7515 endpoint_info->name = msg.remote_mep_id; 7516 endpoint_info->ccm_period = msg.remote_period; 7517 } else { 7518 endpoint_info->name = msg.mep_id; 7519 endpoint_info->ccm_period = msg.local_period; 7520 } 7521 7522 if(msg.fault_flags & BHH_BTE_EVENT_CCM_TIMEOUT){ 7523 endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT; 7524 } 7525 if(msg.fault_flags & BHH_BTE_EVENT_CCM_RDI){ 7526 endpoint_info->faults |= BCM_OAM_BHH_FAULT_CCM_RDI; 7527 } 7528 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){ 7529 endpoint_info->faults |= 7530 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL; 7531 } 7532 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){ 7533 endpoint_info->faults |= 7534 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID; 7535 } 7536 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){ 7537 endpoint_info->faults |= 7538 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID; 7539 } 7540 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){ 7541 endpoint_info->faults |= 7542 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD; 7543 } 7544 if(msg.fault_flags & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){ 7545 endpoint_info->faults |= 7546 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY; 7547 } 7548 if(msg.fault_flags & BHH_BTE_EVENT_CSF_LOS) { 7549 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_LOS; 7550 } 7551 if(msg.fault_flags & BHH_BTE_EVENT_CSF_FDI) { 7552 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_FDI; 7553 } 7554 if(msg.fault_flags & BHH_BTE_EVENT_CSF_RDI) { 7555 endpoint_info->faults |= BCM_OAM_ENDPOINT_BHH_FAULT_CSF_RDI; 7556 } 7557 } 7558 7559 endpoint_info->intf_id = endpoint_p->egress_if; 7560 endpoint_info->cpu_qid = endpoint_p->cpu_qid; 7561 endpoint_info->mpls_label = endpoint_p->label; 7562 endpoint_info->gport = endpoint_p->gport; 7563 endpoint_info->vpn = endpoint_p->vpn; 7564 endpoint_info->vccv_type = endpoint_p->vccv_type; 7565 7566 /* 7567 * Get MAC address 7568 */ 7569 bcm_l3_egress_t_init(&l3_egress); 7570 bcm_l3_intf_t_init(&l3_intf); 7571 7572 if (BCM_FAILURE 7573 (bcm_esw_l3_egress_get(unit, endpoint_p->egress_if, &l3_egress))) { 7574 return BCM_E_INTERNAL; 7575 } 7576 7577 l3_intf.l3a_intf_id = l3_egress.intf; 7578 if (BCM_FAILURE(bcm_esw_l3_intf_get(unit, &l3_intf))) { 7579 return BCM_E_INTERNAL; 7580 } 7581 7582 sal_memcpy(endpoint_info->src_mac_address, l3_intf.l3a_mac_addr, _BHH_MAC_ADDR_LENGTH); 7583 #else 7584 return BCM_E_UNAVAIL; 7585 #endif 7586 } 7587 7588 return BCM_E_NONE; 7589 } 7590 7591 /* 7592 * Function: 7593 * _bcm_en_bhh_endpoint_faults_multi_get 7594 * Purpose: 7595 * Function to get faults for multiple BHH endpoints 7596 * in a single call. 7597 * Parameters: 7598 * unit (IN) BCM device number 7599 * flags (IN) Flags is kept unused as of now. 7600 * This is for any future enhancement 7601 * max_endpoints (IN) Number of max endpoint for the protocol 7602 * faults (OUT) Pointer to faults for all endpoints 7603 * endpoint_count (OUT) Pointer to Number of valid endpoints with faults, 7604 * filled by get API. 7605 * 7606 * Returns: 7607 * BCM_E_NONE No error 7608 * BCM_E_XXXX Error 7609 */ 7610 #if defined(BCM_KATANA_SUPPORT) && defined (INCLUDE_BHH) 7611 static int _bcm_en_bhh_endpoint_faults_multi_get( 7612 int unit, 7613 uint32 flags, 7614 uint32 max_endpoints, 7615 bcm_oam_endpoint_fault_t *faults, 7616 uint32 *endpoint_count) 7617 { 7618 int rv = BCM_E_NONE; 7619 bcm_oam_endpoint_fault_t *faults_temp = faults; 7620 uint8 *buffer; 7621 uint16 reply_len; 7622 uint32 sess_count; 7623 uint32 ep_id; 7624 uint32 ep_count = 0; 7625 uint32 faults_bitmap; 7626 7627 _bcm_oam_info_t *oam_info_p; 7628 _bcm_oam_endpoint_t *endpoint_p; 7629 7630 SET_OAM_INFO; 7631 7632 CHECK_INIT; 7633 7634 if(max_endpoints != oam_info_p->bhh_endpoint_count) { 7635 rv = BCM_E_PARAM; 7636 return (rv); 7637 } 7638 sal_memset(faults, 0, ((sizeof(bcm_oam_endpoint_fault_t))*max_endpoints)); 7639 7640 rv = _bcm_en_oam_bhh_msg_send_receive(unit, 7641 MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET, 7642 0, 0, 7643 MOS_MSG_SUBCLASS_BHH_FAULTS_MULTI_GET_REPLY, 7644 &reply_len); 7645 7646 if (BCM_FAILURE(rv)) { 7647 LOG_ERROR(BSL_LS_BCM_OAM, 7648 (BSL_META_U(unit, 7649 "OAM(unit %d) Error: BHH uKernel msg failed for" 7650 "faults multi get %s.\n"), unit, 7651 bcm_errmsg(rv))); 7652 return (rv); 7653 } 7654 7655 if(reply_len != (oam_info_p->bhh_endpoint_count * sizeof(uint32))) { 7656 rv = BCM_E_INTERNAL; 7657 return (rv); 7658 } 7659 /* Unpack control message data into DMA buffer */ 7660 buffer = oam_info_p->dma_buffer; 7661 for(sess_count = 0;sess_count < oam_info_p->bhh_endpoint_count;sess_count++) { 7662 ep_id = BCM_OAM_BHH_GET_SDK_EP(oam_info_p, sess_count); 7663 7664 VALIDATE_ENDPOINT_INDEX(ep_id); 7665 7666 SET_ENDPOINT(ep_id); 7667 7668 /* If endpoint not in use, ignore and continue for next session_id). 7669 * If session is running in hostCPU, skip and Go to ep_id.*/ 7670 if(!(endpoint_p->in_use)) { 7671 continue; 7672 } 7673 7674 _SHR_UNPACK_U32(buffer, faults_bitmap); 7675 7676 faults_temp->endpoint_id = ep_id; 7677 7678 if(faults_bitmap & BHH_BTE_EVENT_CCM_TIMEOUT){ 7679 faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_TIMEOUT; 7680 } 7681 if(faults_bitmap & BHH_BTE_EVENT_CCM_RDI){ 7682 faults_temp->faults |= BCM_OAM_BHH_FAULT_CCM_RDI; 7683 } 7684 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_LEVEL){ 7685 faults_temp->faults |= 7686 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_LEVEL; 7687 } 7688 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEG_ID){ 7689 faults_temp->faults |= 7690 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEG_ID; 7691 } 7692 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_MEP_ID){ 7693 faults_temp->faults |= 7694 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_MEP_ID; 7695 } 7696 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PERIOD){ 7697 faults_temp->faults |= 7698 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PERIOD; 7699 } 7700 if(faults_bitmap & BHH_BTE_EVENT_CCM_UNKNOWN_PRIORITY){ 7701 faults_temp->faults |= 7702 BCM_OAM_BHH_FAULT_CCM_UNKNOWN_PRIORITY; 7703 } 7704 ep_count++; 7705 faults_temp++; 7706 7707 } 7708 7709 *endpoint_count = ep_count; 7710 return (rv); 7711 7712 } 7713 7714 /* 7715 * Function: 7716 * _bcm_en_oam_bhh_appl_callback 7717 * Purpose: 7718 * Update FW BHH appl state 7719 * Parameters: 7720 * unit - (IN) Unit number. 7721 * uC - (IN) core number. 7722 * stage - (IN) core reset stage. 7723 * user_data - (IN) data pointer. 7724 * Returns: 7725 * BCM_E_XXX 7726 * Notes: 7727 */ 7728 7729 int _bcm_en_oam_bhh_appl_callback(int unit, 7730 int uC, 7731 soc_cmic_uc_shutdown_stage_t stage, 7732 void *user_data) { 7733 _bcm_oam_info_t *oam_info_p; 7734 7735 SET_OAM_INFO; 7736 BCM_IF_ERROR_RETURN(bcm_esw_oam_lock(unit)); 7737 oam_info_p->ukernel_not_ready = 1; 7738 return bcm_esw_oam_unlock(unit); 7739 7740 } 7741 7742 #endif 7743 7744 /* Function: 7745 * bcm_en_oam_endpoint_faults_multi_get 7746 * Purpose: 7747 * Function to get faults for multiple endpoints per protocl 7748 * in a single call. 7749 * Parameters: 7750 * unit (IN) BCM device number 7751 * flags (IN) Flags is kept unused as of now. 7752 * This is for any future enhancement 7753 * endpoint_protocol (IN) Protocol type of the endpoints to retrieve faults 7754 * max_endpoints (IN) Number of max endpoint for the protocol 7755 * faults (OUT) Pointer to faults for all endpoints 7756 * endpoint_count (OUT) Pointer to Number of valid endpoints with faults, 7757 * by get API. 7758 * 7759 * Returns: 7760 * BCM_E_NONE No error 7761 * BCM_E_XXXX Error 7762 */ 7763 int bcm_en_oam_endpoint_faults_multi_get( 7764 int unit, 7765 uint32 flags, 7766 bcm_oam_protocol_type_t endpoint_protocol, 7767 uint32 max_endpoints, 7768 bcm_oam_endpoint_fault_t *faults, 7769 uint32 *endpoint_count) 7770 7771 { 7772 int rv = BCM_E_NONE; 7773 7774 if(!faults) { 7775 rv = BCM_E_PARAM; 7776 return (rv); 7777 } 7778 7779 switch(endpoint_protocol) { 7780 7781 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 7782 case bcmOamProtocolBhh: 7783 *endpoint_count = 0; 7784 rv = _bcm_en_bhh_endpoint_faults_multi_get( 7785 unit, 7786 flags, 7787 max_endpoints, 7788 faults, 7789 endpoint_count); 7790 break; 7791 #endif 7792 default: 7793 rv = BCM_E_UNAVAIL; 7794 break; 7795 } 7796 7797 return rv; 7798 7799 } 7800 7801 /* 7802 * Function: 7803 * bcm_en_oam_endpoint_get 7804 * Purpose: 7805 * Get an OAM endpoint object 7806 * Parameters: 7807 * unit - (IN) Unit number. 7808 * endpoint - (IN) The ID of the endpoint object to get 7809 * endpoint_info - (OUT) Pointer to an OAM endpoint structure to receive the data 7810 * Returns: 7811 * BCM_E_XXX 7812 * Notes: 7813 */ 7814 int 7815 bcm_en_oam_endpoint_get( 7816 int unit, 7817 bcm_oam_endpoint_t endpoint, 7818 bcm_oam_endpoint_info_t *endpoint_info) 7819 { 7820 _bcm_oam_info_t *oam_info_p; 7821 _bcm_oam_endpoint_t *endpoint_p; 7822 7823 SET_OAM_INFO; 7824 7825 CHECK_INIT; 7826 7827 VALIDATE_ENDPOINT_INDEX(endpoint); 7828 7829 SET_ENDPOINT(endpoint); 7830 7831 if (!endpoint_p->in_use) 7832 { 7833 return BCM_E_NOT_FOUND; 7834 } 7835 7836 return _bcm_en_oam_get_endpoint(unit, oam_info_p, endpoint, endpoint_p, 7837 endpoint_info); 7838 } 7839 7840 /* 7841 * Function: 7842 * bcm_en_oam_endpoint_destroy 7843 * Purpose: 7844 * Destroy an OAM endpoint object 7845 * Parameters: 7846 * unit - (IN) Unit number. 7847 * endpoint - (IN) The ID of the OAM endpoint object to destroy 7848 * Returns: 7849 * BCM_E_XXX 7850 * Notes: 7851 */ 7852 int 7853 bcm_en_oam_endpoint_destroy( 7854 int unit, 7855 bcm_oam_endpoint_t endpoint) 7856 { 7857 _bcm_oam_info_t *oam_info_p; 7858 _bcm_oam_endpoint_t *endpoint_p; 7859 7860 SET_OAM_INFO; 7861 7862 CHECK_INIT; 7863 7864 VALIDATE_ENDPOINT_INDEX(endpoint); 7865 7866 SET_ENDPOINT(endpoint); 7867 7868 if (!endpoint_p->in_use) 7869 { 7870 return BCM_E_NOT_FOUND; 7871 } 7872 7873 return _bcm_en_oam_destroy_endpoint(unit, endpoint_p); 7874 } 7875 7876 /* 7877 * Function: 7878 * bcm_en_oam_endpoint_destroy_all 7879 * Purpose: 7880 * Destroy all OAM endpoint objects associated with a given OAM 7881 * group 7882 * Parameters: 7883 * unit - (IN) Unit number. 7884 * group - (IN) The OAM group whose endpoints should be destroyed 7885 * Returns: 7886 * BCM_E_XXX 7887 * Notes: 7888 */ 7889 int 7890 bcm_en_oam_endpoint_destroy_all( 7891 int unit, 7892 bcm_oam_group_t group) 7893 { 7894 _bcm_oam_info_t *oam_info_p; 7895 _bcm_oam_endpoint_t *endpoint_p; 7896 int endpoint_index; 7897 7898 SET_OAM_INFO; 7899 7900 CHECK_INIT; 7901 7902 VALIDATE_GROUP_INDEX(group); 7903 7904 if(!oam_info_p->groups[group].in_use) 7905 { 7906 LOG_CLI((BSL_META_U(unit, 7907 "OAM(unit %d) Error: Group ID=%d does not exist.\n"), unit, group)); 7908 return BCM_E_NOT_FOUND; 7909 } 7910 7911 for (endpoint_index = 0; endpoint_index < oam_info_p->endpoint_count; 7912 ++endpoint_index) 7913 { 7914 SET_ENDPOINT(endpoint_index); 7915 7916 if (endpoint_p->in_use && endpoint_p->group_index == group) 7917 { 7918 BCM_IF_ERROR_RETURN(_bcm_en_oam_destroy_endpoint(unit, 7919 endpoint_p)); 7920 } 7921 } 7922 7923 return BCM_E_NONE; 7924 } 7925 7926 /* 7927 * Function: 7928 * bcm_en_oam_endpoint_traverse 7929 * Purpose: 7930 * Traverse the set of OAM endpoints associated with the 7931 * specified group, calling a specified callback for each one 7932 * Parameters: 7933 * unit - (IN) Unit number. 7934 * group - (IN) The OAM group whose endpoints should be traversed 7935 * cb - (IN) A pointer to the callback function to call for each OAM endpoint in the specified group 7936 * user_data - (IN) Pointer to user data to supply in the callback 7937 * Returns: 7938 * BCM_E_XXX 7939 * Notes: 7940 */ 7941 int 7942 bcm_en_oam_endpoint_traverse( 7943 int unit, 7944 bcm_oam_group_t group, 7945 bcm_oam_endpoint_traverse_cb cb, 7946 void *user_data) 7947 { 7948 _bcm_oam_info_t *oam_info_p; 7949 _bcm_oam_endpoint_t *endpoint_p; 7950 int endpoint_index; 7951 bcm_oam_endpoint_info_t endpoint_info; 7952 7953 SET_OAM_INFO; 7954 7955 CHECK_INIT; 7956 7957 VALIDATE_GROUP_INDEX(group); 7958 7959 if (cb == NULL) 7960 { 7961 return BCM_E_PARAM; 7962 } 7963 7964 for (endpoint_index = 0; endpoint_index < oam_info_p->endpoint_count; 7965 ++endpoint_index) 7966 { 7967 SET_ENDPOINT(endpoint_index); 7968 7969 if (endpoint_p->in_use && endpoint_p->group_index == group) 7970 { 7971 bcm_oam_endpoint_info_t_init(&endpoint_info); 7972 BCM_IF_ERROR_RETURN(_bcm_en_oam_get_endpoint(unit, 7973 oam_info_p, endpoint_index, endpoint_p, &endpoint_info)); 7974 BCM_IF_ERROR_RETURN(cb(unit, &endpoint_info, user_data)); 7975 } 7976 } 7977 7978 return BCM_E_NONE; 7979 } 7980 7981 /* 7982 * Function: 7983 * bcm_en_oam_event_register 7984 * Purpose: 7985 * Register a callback for handling OAM events 7986 * Parameters: 7987 * unit - (IN) Unit number. 7988 * event_types - (IN) The set of OAM events for which the specified callback should be called 7989 * cb - (IN) A pointer to the callback function to call for the specified OAM events 7990 * user_data - (IN) Pointer to user data to supply in the callback 7991 * Returns: 7992 * BCM_E_XXX 7993 * Notes: 7994 */ 7995 int 7996 bcm_en_oam_event_register( 7997 int unit, 7998 bcm_oam_event_types_t event_types, 7999 bcm_oam_event_cb cb, 8000 void *user_data) 8001 { 8002 _bcm_oam_info_t *oam_info_p; 8003 uint32 result; 8004 _bcm_oam_event_handler_t *event_handler_p; 8005 _bcm_oam_event_handler_t *previous_p = NULL; 8006 bcm_oam_event_type_t event_type; 8007 uint32 interrupt_control_register_value; 8008 int update_interrupt_control = 0; 8009 8010 SET_OAM_INFO; 8011 8012 CHECK_INIT; 8013 8014 if (cb == NULL) 8015 { 8016 return BCM_E_PARAM; 8017 } 8018 8019 SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, result); 8020 8021 if (result == 0) 8022 { 8023 return BCM_E_PARAM; 8024 } 8025 8026 for (event_handler_p = oam_info_p->event_handler_list_p; 8027 event_handler_p != NULL; 8028 event_handler_p = event_handler_p->next_p) 8029 { 8030 if (event_handler_p->cb == cb) 8031 { 8032 break; 8033 } 8034 8035 previous_p = event_handler_p; 8036 } 8037 8038 if (event_handler_p == NULL) 8039 { 8040 /* This handler hasn't been registered yet */ 8041 8042 event_handler_p = sal_alloc(sizeof(_bcm_oam_event_handler_t), 8043 "OAM event handler"); 8044 8045 if (event_handler_p == NULL) 8046 { 8047 return BCM_E_MEMORY; 8048 } 8049 8050 event_handler_p->next_p = NULL; 8051 event_handler_p->cb = cb; 8052 8053 SHR_BITCLR_RANGE(event_handler_p->event_types.w, 0, bcmOAMEventCount); 8054 8055 if (previous_p != NULL) 8056 { 8057 previous_p->next_p = event_handler_p; 8058 } 8059 else 8060 { 8061 oam_info_p->event_handler_list_p = event_handler_p; 8062 } 8063 } 8064 8065 SOC_IF_ERROR_RETURN(READ_CCM_INTERRUPT_CONTROLr(unit, 8066 &interrupt_control_register_value)); 8067 8068 for (event_type = 0; event_type < bcmOAMEventCount; ++event_type) 8069 { 8070 if (SHR_BITGET(event_types.w, event_type)) 8071 { 8072 if (soc_feature(unit, soc_feature_bhh)) { 8073 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 8074 /* 8075 * BHH events are generated by the uKernel 8076 */ if ((event_type == bcmOAMEventBHHLBTimeout) || 8077 (event_type == bcmOAMEventBHHLBDiscoveryUpdate) || 8078 (event_type == bcmOAMEventBHHCCMTimeout) || 8079 (event_type == bcmOAMEventBHHCCMTimeoutClear) || 8080 (event_type == bcmOAMEventBHHCCMState) || 8081 (event_type == bcmOAMEventBHHCCMRdi) || 8082 (event_type == bcmOAMEventBHHCCMUnknownMegLevel) || 8083 (event_type == bcmOAMEventBHHCCMUnknownMegId) || 8084 (event_type == bcmOAMEventBHHCCMUnknownMepId) || 8085 (event_type == bcmOAMEventBHHCCMUnknownPeriod) || 8086 (event_type == bcmOAMEventBHHCCMUnknownPriority) || 8087 (event_type == bcmOAMEventBHHCCMRdiClear) || 8088 (event_type == bcmOAMEventBHHCCMUnknownMegLevelClear) || 8089 (event_type == bcmOAMEventBHHCCMUnknownMegIdClear) || 8090 (event_type == bcmOAMEventBHHCCMUnknownMepIdClear) || 8091 (event_type == bcmOAMEventBHHCCMUnknownPeriodClear) || 8092 (event_type == bcmOAMEventBHHCCMUnknownPriorityClear) || 8093 (event_type == bcmOAMEventCsfLos) || 8094 (event_type == bcmOAMEventCsfFdi) || 8095 (event_type == bcmOAMEventCsfRdi) || 8096 (event_type == bcmOAMEventCsfDci)) { 8097 SHR_BITSET(event_handler_p->event_types.w, event_type); 8098 ++(oam_info_p->event_handler_count[event_type]); 8099 continue; 8100 } 8101 8102 #endif 8103 } 8104 if (!soc_reg_field_valid(unit, CCM_INTERRUPT_CONTROLr, 8105 en_interrupt_enable_fields[event_type].field)) 8106 { 8107 continue; 8108 } 8109 if (!SHR_BITGET(event_handler_p->event_types.w, event_type)) 8110 { 8111 /* This handler isn't handling this event yet */ 8112 SHR_BITSET(event_handler_p->event_types.w, event_type); 8113 8114 ++(oam_info_p->event_handler_count[event_type]); 8115 8116 if (oam_info_p->event_handler_count[event_type] == 1) { 8117 /* This is the first handler for this event */ 8118 update_interrupt_control = 1; 8119 if (soc_reg_field_valid(unit, CCM_INTERRUPT_CONTROLr, 8120 en_interrupt_enable_fields[event_type].field)) { 8121 soc_reg_field_set(unit, CCM_INTERRUPT_CONTROLr, 8122 &interrupt_control_register_value, 8123 en_interrupt_enable_fields[event_type].field, 1); 8124 } 8125 } 8126 } 8127 } 8128 } 8129 8130 event_handler_p->user_data = user_data; 8131 8132 /* Enable any needed interrupts not yet enabled */ 8133 8134 if (update_interrupt_control) 8135 { 8136 SOC_IF_ERROR_RETURN(WRITE_CCM_INTERRUPT_CONTROLr(unit, 8137 interrupt_control_register_value)); 8138 } 8139 8140 if (soc_feature(unit, soc_feature_bhh)) { 8141 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 8142 /* 8143 * Update BHH Events mask 8144 */ 8145 if (SOC_IS_KATANAX(unit)) { 8146 return _bcm_en_oam_bhh_event_mask_set(unit); 8147 } 8148 #endif 8149 } 8150 8151 return BCM_E_NONE; 8152 } 8153 8154 /* 8155 * Function: 8156 * bcm_en_oam_event_unregister 8157 * Purpose: 8158 * Unregister a callback for handling OAM events 8159 * Parameters: 8160 * unit - (IN) Unit number. 8161 * event_types - (IN) The set of OAM events for which the specified callback should not be called 8162 * cb - (IN) A pointer to the callback function to unregister from the specified OAM events 8163 * Returns: 8164 * BCM_E_XXX 8165 * Notes: 8166 */ 8167 int 8168 bcm_en_oam_event_unregister( 8169 int unit, 8170 bcm_oam_event_types_t event_types, 8171 bcm_oam_event_cb cb) 8172 { 8173 _bcm_oam_info_t *oam_info_p; 8174 uint32 result; 8175 _bcm_oam_event_handler_t *event_handler_p; 8176 _bcm_oam_event_handler_t *previous_p = NULL; 8177 bcm_oam_event_type_t event_type; 8178 uint32 interrupt_control_register_value; 8179 int update_interrupt_control = 0; 8180 8181 SET_OAM_INFO; 8182 8183 CHECK_INIT; 8184 8185 if (cb == NULL) 8186 { 8187 return BCM_E_PARAM; 8188 } 8189 8190 SHR_BITTEST_RANGE(event_types.w, 0, bcmOAMEventCount, result); 8191 8192 if (result == 0) 8193 { 8194 return BCM_E_PARAM; 8195 } 8196 8197 for (event_handler_p = oam_info_p->event_handler_list_p; 8198 event_handler_p != NULL; 8199 event_handler_p = event_handler_p->next_p) 8200 { 8201 if (event_handler_p->cb == cb) 8202 { 8203 break; 8204 } 8205 8206 previous_p = event_handler_p; 8207 } 8208 8209 if (event_handler_p == NULL) 8210 { 8211 return BCM_E_NOT_FOUND; 8212 } 8213 8214 SOC_IF_ERROR_RETURN(READ_CCM_INTERRUPT_CONTROLr(unit, 8215 &interrupt_control_register_value)); 8216 8217 for (event_type = 0; event_type < bcmOAMEventCount; ++event_type) 8218 { 8219 if (SHR_BITGET(event_types.w, event_type)) 8220 { 8221 if(soc_feature(unit, soc_feature_bhh)) { 8222 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 8223 /* 8224 * BHH events are generated by the uKernel 8225 */ 8226 if ((event_type == bcmOAMEventBHHLBTimeout) || 8227 (event_type == bcmOAMEventBHHLBDiscoveryUpdate) || 8228 (event_type == bcmOAMEventBHHCCMTimeout) || 8229 (event_type == bcmOAMEventBHHCCMTimeoutClear) || 8230 (event_type == bcmOAMEventBHHCCMState) || 8231 (event_type == bcmOAMEventBHHCCMRdi) || 8232 (event_type == bcmOAMEventBHHCCMUnknownMegLevel) || 8233 (event_type == bcmOAMEventBHHCCMUnknownMegId) || 8234 (event_type == bcmOAMEventBHHCCMUnknownMepId) || 8235 (event_type == bcmOAMEventBHHCCMUnknownPeriod) || 8236 (event_type == bcmOAMEventBHHCCMUnknownPriority) || 8237 (event_type == bcmOAMEventBHHCCMRdiClear) || 8238 (event_type == bcmOAMEventBHHCCMUnknownMegLevelClear) || 8239 (event_type == bcmOAMEventBHHCCMUnknownMegIdClear) || 8240 (event_type == bcmOAMEventBHHCCMUnknownMepIdClear) || 8241 (event_type == bcmOAMEventBHHCCMUnknownPeriodClear) || 8242 (event_type == bcmOAMEventBHHCCMUnknownPriorityClear) || 8243 (event_type == bcmOAMEventCsfLos) || 8244 (event_type == bcmOAMEventCsfFdi) || 8245 (event_type == bcmOAMEventCsfRdi) || 8246 (event_type == bcmOAMEventCsfDci)) { 8247 SHR_BITCLR(event_handler_p->event_types.w, event_type); 8248 --(oam_info_p->event_handler_count[event_type]); 8249 continue; 8250 } 8251 8252 #endif 8253 } 8254 if (!soc_reg_field_valid(unit, CCM_INTERRUPT_CONTROLr, 8255 en_interrupt_enable_fields[event_type].field)) 8256 { 8257 continue; 8258 } 8259 if (oam_info_p->event_handler_count[event_type] > 0 && 8260 SHR_BITGET(event_handler_p->event_types.w, event_type)) 8261 { 8262 /* This handler has been handling this event */ 8263 8264 SHR_BITCLR(event_handler_p->event_types.w, event_type); 8265 8266 --(oam_info_p->event_handler_count[event_type]); 8267 8268 if (oam_info_p->event_handler_count[event_type] == 0) 8269 { 8270 /* No more handlers for this event */ 8271 8272 update_interrupt_control = 1; 8273 if (soc_reg_field_valid(unit, CCM_INTERRUPT_CONTROLr, 8274 en_interrupt_enable_fields[event_type].field)) { 8275 soc_reg_field_set(unit, CCM_INTERRUPT_CONTROLr, 8276 &interrupt_control_register_value, 8277 en_interrupt_enable_fields[event_type].field, 0); 8278 } 8279 } 8280 } 8281 } 8282 } 8283 8284 /* Disable any interrupts that lost their last handler */ 8285 8286 if (update_interrupt_control) 8287 { 8288 SOC_IF_ERROR_RETURN(WRITE_CCM_INTERRUPT_CONTROLr(unit, 8289 interrupt_control_register_value)); 8290 } 8291 8292 SHR_BITTEST_RANGE(event_handler_p->event_types.w, 0, bcmOAMEventCount, 8293 result); 8294 8295 if (result == 0) 8296 { 8297 /* No more events for this handler to handle */ 8298 8299 if (previous_p != NULL) 8300 { 8301 previous_p->next_p = event_handler_p->next_p; 8302 } 8303 else 8304 { 8305 oam_info_p->event_handler_list_p = event_handler_p->next_p; 8306 } 8307 8308 sal_free(event_handler_p); 8309 } 8310 8311 if (soc_feature(unit, soc_feature_bhh)) { 8312 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 8313 /* 8314 * Update BHH Events mask 8315 */ 8316 if (SOC_IS_KATANAX(unit)) { 8317 return _bcm_en_oam_bhh_event_mask_set(unit); 8318 } 8319 #endif 8320 } 8321 8322 return BCM_E_NONE; 8323 } 8324 8325 #if defined(BCM_KATANA_SUPPORT) && defined(INCLUDE_BHH) 8326 /* 8327 * Function: 8328 * _bcm_en_oam_trunk_ports_update 8329 * Purpose: 8330 * Associate or Dissociate ports from trunk in mapping table 8331 * maintained by BTE 8332 * Parameters: 8333 * unit - Device unit number 8334 * trunk_gport - Trunk Gport 8335 * max_ports - Num ports being added/deleted 8336 * port_arr - Array of physical port gports being added/deleted 8337 * add - add == 1 indicates ports are being added 8338 * Returns: 8339 * BCM_E_XXX 8340 */ 8341 STATIC int 8342 _bcm_en_oam_trunk_ports_update(int unit, bcm_gport_t trunk_gport, int max_ports, 8343 bcm_gport_t *port_arr, uint8 add) 8344 { 8345 bcm_trunk_t trunk_id = BCM_TRUNK_INVALID; 8346 _bcm_oam_info_t *oam_info_p; 8347 bhh_sdk_msg_ctrl_trunk_map_update_t msg; 8348 uint8 *buffer, *buffer_ptr; 8349 uint16 buffer_len, reply_len; 8350 int rv = BCM_E_NONE; 8351 int i; 8352 8353 SET_OAM_INFO; 8354 8355 if (oam_info_p->ukernel_not_ready) { 8356 return BCM_E_INIT; 8357 } 8358 8359 if (!BCM_GPORT_IS_TRUNK(trunk_gport)) { 8360 return BCM_E_PARAM; 8361 } 8362 8363 if (max_ports >= SHR_BHH_MAX_PORTS) { 8364 return BCM_E_PARAM; 8365 } 8366 8367 if (!port_arr) { 8368 return BCM_E_PARAM; 8369 } 8370 8371 trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport); 8372 if (trunk_id == BCM_TRUNK_INVALID) { 8373 return BCM_E_PARAM; 8374 } 8375 8376 if (add) { 8377 msg.trunk_id = trunk_id; 8378 } else { 8379 msg.trunk_id = SHR_BHH_INVALID_TRUNK_ID; 8380 } 8381 msg.num_ports = max_ports; 8382 for (i = 0; i < max_ports; i++) { 8383 if (BCM_GPORT_IS_LOCAL(port_arr[i])) { 8384 msg.port_list[i] = BCM_GPORT_LOCAL_GET(port_arr[i]); 8385 } else if (BCM_GPORT_IS_MODPORT(port_arr[i])) { 8386 msg.port_list[i] = BCM_GPORT_MODPORT_PORT_GET(port_arr[i]); 8387 } else { 8388 return BCM_E_PARAM; 8389 } 8390 } 8391 8392 /* Pack control message data into DMA buffer */ 8393 buffer = oam_info_p->dma_buffer; 8394 buffer_ptr = bhh_sdk_msg_ctrl_trunk_map_update_pack(buffer, &msg); 8395 buffer_len = buffer_ptr - buffer; 8396 8397 rv = _bcm_en_oam_bhh_msg_send_receive( 8398 unit, 8399 MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_UPDATE, 8400 buffer_len, 0, 8401 MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_UPDATE_REPLY, 8402 &reply_len); 8403 8404 8405 if (BCM_FAILURE(rv)) { 8406 return (rv); 8407 } 8408 8409 return BCM_E_NONE; 8410 } 8411 8412 /* 8413 * Function: 8414 * bcm_en_oam_trunk_ports_add 8415 * Purpose: 8416 * Associate ports from trunk in mapping table maintained by BTE 8417 * Parameters: 8418 * unit - Device unit number 8419 * trunk_gport - Trunk Gport 8420 * max_ports - Num ports being added 8421 * port_arr - Array of physical port gports being added 8422 * Returns: 8423 * BCM_E_XXX 8424 */ 8425 int bcm_en_oam_trunk_ports_add(int unit, bcm_gport_t trunk_gport, 8426 int max_ports, bcm_gport_t *port_arr) 8427 { 8428 return _bcm_en_oam_trunk_ports_update(unit, trunk_gport, max_ports, 8429 port_arr, 1); 8430 } 8431 8432 /* 8433 * Function: 8434 * bcm_en_oam_trunk_ports_delete 8435 * Purpose: 8436 * Dissociate ports from trunk in mapping table maintained by BTE 8437 * Parameters: 8438 * unit - Device unit number 8439 * trunk_gport - Trunk Gport 8440 * max_ports - Num ports being deleted 8441 * port_arr - Array of physical port gports being deleted 8442 * Returns: 8443 * BCM_E_XXX 8444 */ 8445 int bcm_en_oam_trunk_ports_delete(int unit, bcm_gport_t trunk_gport, 8446 int max_ports, bcm_gport_t *port_arr) 8447 { 8448 return _bcm_en_oam_trunk_ports_update(unit, trunk_gport, max_ports, 8449 port_arr, 0); 8450 } 8451 8452 /* 8453 * Function: 8454 * bcm_en_oam_trunk_ports_get 8455 * Purpose: 8456 * Get port to trunk mapping from UKERNEL 8457 * Parameters: 8458 * unit - (IN) BCM device number 8459 * trunk_gport - (IN) Trunk gport 8460 * max_ports - (IN) Max ports the port_arr can accomodate 8461 * port_arr - (OUT) Ports in the trunk 8462 * port_count - (OUT) Valid number of ports in the port_arr 8463 * 8464 * Returns: 8465 * BCM_E_XXX 8466 */ 8467 int 8468 bcm_en_oam_trunk_ports_get(int unit, bcm_gport_t trunk_gport, int max_ports, 8469 bcm_gport_t *port_arr, int *port_count) 8470 { 8471 bhh_sdk_msg_ctrl_trunk_map_get_t msg; 8472 uint8 *buffer, *buffer_ptr; 8473 uint16 buffer_len, reply_len; 8474 bcm_trunk_t trunk_id; 8475 _bcm_oam_info_t *oam_info_p; 8476 int rv = BCM_E_NONE; 8477 int i; 8478 8479 SET_OAM_INFO; 8480 8481 if (!BCM_GPORT_IS_TRUNK(trunk_gport)) { 8482 return BCM_E_PARAM; 8483 } 8484 8485 trunk_id = BCM_GPORT_TRUNK_GET(trunk_gport); 8486 if (trunk_id == BCM_TRUNK_INVALID) { 8487 return BCM_E_PARAM; 8488 } 8489 8490 8491 /* Send trunk_id in the send length variable */ 8492 rv = _bcm_en_oam_bhh_msg_send_receive( 8493 unit, 8494 MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_GET, 8495 trunk_id, 0, 8496 MOS_MSG_SUBCLASS_BHH_PORT_TRUNK_GET_REPLY, 8497 &reply_len); 8498 if (BCM_FAILURE(rv)) { 8499 return rv; 8500 } 8501 8502 sal_memset(&msg, 0, sizeof(msg)); 8503 buffer = oam_info_p->dma_buffer; 8504 buffer_ptr = bhh_sdk_msg_ctrl_trunk_map_get_unpack(buffer, &msg); 8505 buffer_len = buffer_ptr - buffer; 8506 8507 if (reply_len != buffer_len) { 8508 return BCM_E_INTERNAL; 8509 } 8510 8511 *port_count = msg.num_ports; 8512 for (i = 0; (i < *port_count) && (i < max_ports); i++) { 8513 port_arr[i] = msg.port_list[i]; 8514 } 8515 8516 return BCM_E_NONE;; 8517 } 8518 #endif /* BCM_KATANA_SUPPORT && INCLUDE_BHH */ 8519 8520 #if defined(BCM_WARM_BOOT_SUPPORT) 8521 int _bcm_en_oam_sync(int unit) 8522 { 8523 _bcm_oam_info_t *oam_info_p; 8524 _bcm_oam_group_t *group_p; 8525 int group_index, group_count = 0; 8526 int stable_size; 8527 soc_scache_handle_t scache_handle; 8528 uint8 *oam_scache, *ptr; 8529 bcm_oam_endpoint_t epidx; 8530 _bcm_oam_endpoint_t *endpoint_p; 8531 8532 SET_OAM_INFO; 8533 8534 CHECK_INIT; 8535 8536 SOC_IF_ERROR_RETURN(soc_stable_size_get(unit, &stable_size)); 8537 if (SOC_WARM_BOOT_SCACHE_IS_LIMITED(unit) || (stable_size == 0)) { 8538 return BCM_E_NONE; 8539 } 8540 8541 SOC_SCACHE_HANDLE_SET(scache_handle, unit, BCM_MODULE_OAM, 0); 8542 BCM_IF_ERROR_RETURN(_bcm_esw_scache_ptr_get(unit, scache_handle, 0, 8543 0, &oam_scache, 8544 BCM_WB_DEFAULT_VERSION, NULL)); 8545 8546 if (oam_scache == NULL) 8547 { 8548 return BCM_E_MEMORY; 8549 } 8550 8551 /* Store the FP groups */ 8552 sal_memcpy(oam_scache, &oam_info_p->vfp_group, sizeof(bcm_field_group_t)); 8553 oam_scache += sizeof(bcm_field_group_t); 8554 sal_memcpy(oam_scache, &oam_info_p->fp_vp_group, sizeof(bcm_field_group_t)); 8555 oam_scache += sizeof(bcm_field_group_t); 8556 sal_memcpy(oam_scache, &oam_info_p->fp_glp_group, sizeof(bcm_field_group_t)); 8557 oam_scache += sizeof(bcm_field_group_t); 8558 8559 /* Store the OAM group names */ 8560 sal_memcpy(oam_scache, &group_count, sizeof(int)); 8561 oam_scache += sizeof(int); 8562 8563 for (group_index = 0; group_index < oam_info_p->group_count; 8564 ++group_index) 8565 { 8566 SET_GROUP(group_index); 8567 8568 if (group_p->in_use) 8569 { 8570 memcpy(oam_scache, group_p->name, BCM_OAM_GROUP_NAME_LENGTH); 8571 8572 oam_scache += BCM_OAM_GROUP_NAME_LENGTH; 8573 } 8574 } 8575 8576 /* Store Endpoint IDs */ 8577 for (epidx = 0; epidx < oam_info_p->endpoint_count; epidx++) { 8578 8579 SET_ENDPOINT(epidx); 8580 if (!endpoint_p->in_use) { 8581 continue; 8582 } 8583 8584 if (endpoint_p->flags & BCM_OAM_ENDPOINT_REMOTE) { 8585 /* Remote Endpoint */ 8586 ptr = BCM_OAM_WB_SCACHE_V1_REMOTE_EP_ID_OFFSET( 8587 oam_scache, 8588 endpoint_p->remote_index); 8589 sal_memcpy(ptr, &epidx, sizeof(bcm_oam_endpoint_t)); 8590 } else { 8591 if (endpoint_p->local_tx_enabled) { 8592 /* Tx enabled Endpoint */ 8593 ptr = BCM_OAM_WB_SCACHE_V1_TX_EP_ID_OFFSET( 8594 oam_scache, 8595 endpoint_p->local_tx_index); 8596 sal_memcpy(ptr, &epidx, sizeof(bcm_oam_endpoint_t)); 8597 } 8598 if (endpoint_p->local_rx_enabled) { 8599 /* Rx enabled Endpoint */ 8600 ptr = BCM_OAM_WB_SCACHE_V1_RX_EP_ID_OFFSET( 8601 oam_scache, 8602 endpoint_p->local_rx_index); 8603 sal_memcpy(ptr, &epidx, sizeof(bcm_oam_endpoint_t)); 8604 } 8605 } 8606 } 8607 oam_scache += (oam_info_p->endpoint_count * sizeof(bcm_oam_endpoint_t)); 8608 8609 return BCM_E_NONE; 8610 } 8611 #endif /* BCM_WARM_BOOT_SUPPORT */ 8612 8613 #ifdef BCM_WARM_BOOT_SUPPORT_SW_DUMP 8614 void 8615 _bcm_en_oam_group_info_dump(int unit, bcm_oam_group_t group_index, 8616 _bcm_oam_group_t *group_p) 8617 { 8618 int rv; 8619 bcm_oam_group_info_t group_info; 8620 8621 /* Initialize the group information structure. */ 8622 bcm_oam_group_info_t_init(&group_info); 8623 8624 /* Retrieve group information and set in group_info structure. */ 8625 rv = _bcm_en_oam_get_group(unit, group_index, group_p, &group_info); 8626 if (BCM_FAILURE(rv)) { 8627 LOG_ERROR(BSL_LS_BCM_OAM, 8628 (BSL_META_U(unit, 8629 "OAM(unit %d) Error: _bcm_en_oam_group_info_dump" 8630 " (GID=%d) - %s.\n"), 8631 unit, group_index, bcm_errmsg(rv))); 8632 return; 8633 } 8634 LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n"))); 8635 LOG_CLI((BSL_META_U(unit,"Group ID = %d details\r\n"), group_index)); 8636 LOG_CLI((BSL_META_U(unit,"Group Name = %s\r\n"), group_info.name)); 8637 LOG_CLI((BSL_META_U(unit,"Flags = %d\r\n"), group_info.flags)); 8638 LOG_CLI((BSL_META_U(unit,"Faults = %d\r\n"), group_info.faults)); 8639 LOG_CLI((BSL_META_U(unit,"Persistent_faults = %d\r\n"), 8640 group_info.persistent_faults)); 8641 LOG_CLI((BSL_META_U(unit,"clear_persistent_faults = %d\r\n"), 8642 group_info.clear_persistent_faults)); 8643 LOG_CLI((BSL_META_U(unit,"lowest_alarm_priority = %d\r\n"), 8644 group_info.lowest_alarm_priority)); 8645 LOG_CLI((BSL_META_U(unit,"------------------------------------------\r\n"))); 8646 } 8647 8648 /* 8649 * Function: 8650 * _bcm_oam_sw_dump 8651 * Purpose: 8652 * Displays oam information maintained by software. 8653 * Parameters: 8654 * unit - Device unit number 8655 * Returns: 8656 * None 8657 */ 8658 void 8659 _bcm_en_oam_sw_dump(int unit) 8660 { 8661 _bcm_oam_info_t *oam_info_p; 8662 _bcm_oam_endpoint_t *endpoint_p; 8663 int group_idx, endpoint_idx; 8664 _bcm_oam_group_t *group_p; 8665 SHR_BITDCL word; 8666 SET_OAM_INFO; 8667 8668 LOG_CLI((BSL_META_U(unit, 8669 "\nSW Information OAM - Unit %d\n"), unit)); 8670 LOG_CLI((BSL_META_U(unit, 8671 " Group Info : \n"))); 8672 8673 for (group_idx = 0; group_idx < oam_info_p->group_count; group_idx++) { 8674 SET_GROUP(group_idx); 8675 if (group_p->in_use) { 8676 _bcm_en_oam_group_info_dump(unit, group_idx, group_p); 8677 } 8678 } 8679 8680 LOG_CLI((BSL_META_U(unit, 8681 "\n local_tx_endpoints_in_use \n"))); 8682 for (word = 0; word < _SHR_BITDCLSIZE 8683 (oam_info_p->local_tx_endpoint_count); word++) { 8684 LOG_CLI((BSL_META_U(unit, 8685 " word %d value %x "), word, 8686 oam_info_p->local_tx_endpoints_in_use[word])); 8687 } 8688 8689 LOG_CLI((BSL_META_U(unit, 8690 "\n local_rx_endpoints_in_use \n"))); 8691 for (word = 0; word < _SHR_BITDCLSIZE 8692 (oam_info_p->local_rx_endpoint_count); word++) { 8693 LOG_CLI((BSL_META_U(unit, 8694 " word %d value %x "), word, 8695 oam_info_p->local_rx_endpoints_in_use[word])); 8696 } 8697 8698 LOG_CLI((BSL_META_U(unit, 8699 "\n remote_endpoints_in_use \n"))); 8700 for (word = 0; word < _SHR_BITDCLSIZE 8701 (oam_info_p->remote_endpoint_count); word++) { 8702 LOG_CLI((BSL_META_U(unit, 8703 " word %d value %x "), word, 8704 oam_info_p->remote_endpoints_in_use[word])); 8705 } 8706 8707 LOG_CLI((BSL_META_U(unit, 8708 "\n Reverse RMEP lookup \n"))); 8709 for (endpoint_idx = 0; endpoint_idx < oam_info_p->remote_endpoint_count; 8710 endpoint_idx++) { 8711 if (SHR_BITGET(oam_info_p->remote_endpoints_in_use, endpoint_idx)) { 8712 LOG_CLI((BSL_META_U(unit, 8713 "RMEP %x \n"), 8714 oam_info_p->remote_endpoints[endpoint_idx])); 8715 } 8716 } 8717 8718 LOG_CLI((BSL_META_U(unit, 8719 "\n lm_counter_in_use \n"))); 8720 for (word = 0; word < _SHR_BITDCLSIZE 8721 (oam_info_p->lm_counter_count); word++) { 8722 LOG_CLI((BSL_META_U(unit, 8723 " word %d value %x "), word, 8724 oam_info_p->lm_counter_in_use[word])); 8725 } 8726 8727 LOG_CLI((BSL_META_U(unit, 8728 "\n Endpoint Information \n"))); 8729 for (endpoint_idx = 0; endpoint_idx < oam_info_p->endpoint_count; 8730 endpoint_idx++) { 8731 SET_ENDPOINT(endpoint_idx); 8732 if (!endpoint_p->in_use) { 8733 continue; 8734 } 8735 LOG_CLI((BSL_META_U(unit, 8736 "\n Endpoint index %d\n"), endpoint_idx)); 8737 LOG_CLI((BSL_META_U(unit, 8738 "\t Group index %d\n"), endpoint_p->group_index)); 8739 LOG_CLI((BSL_META_U(unit, 8740 "\t Name %x\n"), endpoint_p->name)); 8741 LOG_CLI((BSL_META_U(unit, 8742 "\t Level %d\n"), endpoint_p->level)); 8743 LOG_CLI((BSL_META_U(unit, 8744 "\t VLAN %d\n"), endpoint_p->vlan)); 8745 LOG_CLI((BSL_META_U(unit, 8746 "\t GLP %x\n"), endpoint_p->glp)); 8747 LOG_CLI((BSL_META_U(unit, 8748 "\t local_tx_enabled %d\n"), endpoint_p->local_tx_enabled)); 8749 LOG_CLI((BSL_META_U(unit, 8750 "\t local_rx_enabled %d\n"), endpoint_p->local_rx_enabled)); 8751 LOG_CLI((BSL_META_U(unit, 8752 "\t remote_index %d\n"), endpoint_p->remote_index)); 8753 LOG_CLI((BSL_META_U(unit, 8754 "\t local_tx_index %d\n"), endpoint_p->local_tx_index)); 8755 LOG_CLI((BSL_META_U(unit, 8756 "\t local_rx_index %d\n"), endpoint_p->local_rx_index)); 8757 LOG_CLI((BSL_META_U(unit, 8758 "\t VP %x\n"), endpoint_p->vp)); 8759 LOG_CLI((BSL_META_U(unit, 8760 "\t lm_counter_index %d\n"), endpoint_p->lm_counter_index)); 8761 LOG_CLI((BSL_META_U(unit, 8762 "\t pri_map_index %d\n"), endpoint_p->pri_map_index)); 8763 LOG_CLI((BSL_META_U(unit, 8764 "\t vfp_entry %d\n"), endpoint_p->vfp_entry)); 8765 LOG_CLI((BSL_META_U(unit, 8766 "\t fp_entry_tx %d\n"), endpoint_p->fp_entry_tx)); 8767 LOG_CLI((BSL_META_U(unit, 8768 "\t fp_entry_rx %d\n"), endpoint_p->fp_entry_rx)); 8769 } 8770 return; 8771 } 8772 #endif 8773 #endif /* defined(BCM_ENDURO) */