rx.c (64818B)
1 /* 2 * 3 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 4 * 5 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 6 * 7 * File: rx.c 8 * 9 * Purpose: 10 * 11 * Functions: 12 * _bcm_ptp_rx_init 13 * _bcm_ptp_rx_stack_create 14 * _bcm_ptp_rx_clock_create 15 * _bcm_ptp_external_rx_response_free 16 * _bcm_ptp_internal_rx_response_free 17 * _bcm_ptp_rx_response_flush 18 * _bcm_ptp_rx_response_get 19 * _bcm_ptp_rx_thread 20 * _bcm_ptp_rx_callback 21 * _bcm_ptp_rx_message_destination_port_get 22 * _bcm_ptp_rx_message_source_clock_identity_get 23 * _bcm_ptp_rx_message_length_get 24 * _bcm_ptp_register_management_callback 25 * _bcm_ptp_register_event_callback 26 * _bcm_ptp_register_signal_callback 27 * _bcm_ptp_register_peers_callback 28 * _bcm_ptp_register_fault_callback 29 * _bcm_ptp_unregister_management_callback 30 * _bcm_ptp_unregister_event_callback 31 * _bcm_ptp_unregister_signal_callback 32 * _bcm_ptp_unregister_peers_callback 33 * _bcm_ptp_event_message_monitor 34 * _bcm_ptp_signal_handler_default 35 */ 36 37 #if defined(INCLUDE_PTP) 38 39 #ifdef BCM_HIDE_DISPATCHABLE 40 #undef BCM_HIDE_DISPATCHABLE 41 #endif 42 43 #include <shared/bsl.h> 44 45 #include <soc/defs.h> 46 #include <soc/drv.h> 47 48 #include <bcm/pkt.h> 49 #include <bcm/tx.h> 50 #include <bcm/rx.h> 51 #include <bcm/error.h> 52 #include <bcm/ptp.h> 53 #include <bcm_int/common/ptp.h> 54 55 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) 56 #include <soc/uc_msg.h> 57 #endif 58 59 #include <soc/uc_dbg.h> 60 61 #ifdef BCM_ESMC_EXTDPLL_SUPPORT 62 #include <bcm_int/common/esmc.h> 63 #endif /* BCM_ESMC_EXTDPLL_SUPPORT */ 64 65 #if !defined(BCM_PTP_RX_POLL_WAIT_USEC) 66 #define BCM_PTP_RX_POLL_WAIT_USEC (1000) 67 #endif 68 69 void (*_bcm_ptp_arp_callback)(int unit, bcm_ptp_stack_id_t ptp_id, 70 int protocol, int src_addr_offset, 71 int payload_offset, int msg_len, uint8 *msg); 72 73 #define PTP_SDK_VERSION 0x01000000 74 #define PTP_UC_MIN_VERSION 0x01000000 75 76 #define PTP_RX_PACKET_MIN_SIZE_OCTETS (14) 77 #define PTP_RX_TUNNEL_MSG_MIN_SIZE_OCTETS (11) 78 #define PTP_RX_EVENT_MSG_MIN_SIZE_OCTETS (2) 79 #define PTP_RX_MGMT_MIN_SIZE (0x64) 80 #define PTP_RX_UDP_PAYLOAD_OFFSET (46) 81 82 /* PTP clock Rx data. */ 83 typedef struct _bcm_ptp_clock_rx_data_s { 84 _bcm_ptp_sem_t response_ready; 85 uint8 * volatile response_data; 86 volatile int response_len; 87 } _bcm_ptp_clock_rx_data_t; 88 89 /* Stack PTP Rx data arrays. */ 90 typedef struct _bcm_ptp_stack_rx_array_s { 91 _bcm_ptp_memstate_t memstate; 92 93 #if defined(BCM_PTP_EXTERNAL_STACK_SUPPORT) 94 bcm_mac_t host_mac; 95 bcm_mac_t top_mac; 96 int tpid; 97 int vlan; 98 #endif 99 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) 100 sal_thread_t rx_thread; 101 volatile int rx_thread_exit; 102 #endif 103 104 _bcm_ptp_clock_rx_data_t *clock_data; 105 } _bcm_ptp_stack_rx_array_t; 106 107 /* Unit PTP Rx data arrays. */ 108 typedef struct _bcm_ptp_unit_rx_array_s { 109 _bcm_ptp_memstate_t memstate; 110 111 bcm_ptp_cb management_cb; 112 bcm_ptp_cb event_cb; 113 bcm_ptp_cb signal_cb; 114 bcm_ptp_cb fault_cb; 115 bcm_ptp_cb peers_cb; 116 uint8 *management_user_data; 117 uint8 *event_user_data; 118 uint8 *signal_user_data; 119 uint8 *fault_user_data; 120 uint8 *peers_user_data; 121 122 _bcm_ptp_stack_rx_array_t *stack_array; 123 } _bcm_ptp_unit_rx_array_t; 124 125 static _bcm_ptp_unit_rx_array_t unit_rx_array[BCM_MAX_NUM_UNITS]; 126 127 128 129 int _bcm_ptp_most_recent_clock_num; 130 int _bcm_ptp_most_recent_port; 131 bcm_ptp_protocol_t _bcm_ptp_most_recent_protocol; 132 int _bcm_ptp_most_recent_src_addr_offset; 133 int _bcm_ptp_most_recent_msg_offset; 134 135 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 136 extern bcm_ptp_mbox_tsevent_stats_t mbox_tsevent_stats; 137 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */ 138 139 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) 140 static void _bcm_ptp_rx_thread(void *arg); 141 #endif 142 143 #if defined(BCM_PTP_EXTERNAL_STACK_SUPPORT) 144 bcm_rx_t _bcm_ptp_rx_callback( 145 int unit, 146 bcm_pkt_t *pkt, 147 void *cookie); 148 149 static int _bcm_ptp_rx_message_destination_port_get( 150 uint8 *message, 151 uint16 *dest_port); 152 153 static int _bcm_ptp_rx_message_source_clock_identity_get( 154 uint8 *message, 155 bcm_ptp_clock_identity_t *clock_identity); 156 157 static int _bcm_ptp_rx_message_length_get( 158 uint8 *message, 159 uint16 *message_len); 160 161 #endif /* defined(BCM_PTP_EXTERNAL_STACK_SUPPORT) */ 162 163 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) || defined(BCM_PTP_EXTERNAL_STACK_SUPPORT) 164 STATIC int _bcm_ptp_event_message_monitor( 165 int unit, 166 bcm_ptp_stack_id_t ptp_id, 167 int ev_data_len, 168 uint8 *ev_data, 169 int *ev_internal); 170 #endif 171 172 STATIC int _bcm_ptp_signal_handler_default( 173 int unit, 174 bcm_ptp_stack_id_t ptp_id, 175 int clock_num, 176 uint32 clock_port, 177 bcm_ptp_cb_type_t type, 178 bcm_ptp_cb_msg_t *msg, 179 void *user_data); 180 181 /* 182 * Function: 183 * _bcm_ptp_rx_init 184 * Purpose: 185 * Initialize the PTP Rx framework and data of a unit. 186 * Parameters: 187 * unit - (IN) Unit number. 188 * Returns: 189 * BCM_E_XXX 190 * Notes: 191 */ 192 int 193 _bcm_ptp_rx_init( 194 int unit) 195 { 196 int rv = BCM_E_UNAVAIL; 197 _bcm_ptp_stack_rx_array_t *stack_p; 198 int i; 199 200 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT, 201 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 202 return rv; 203 } 204 205 206 if (NULL == unit_rx_array[unit].stack_array) { 207 stack_p = sal_alloc(PTP_MAX_STACKS_PER_UNIT* 208 sizeof(_bcm_ptp_stack_rx_array_t),"Unit Rx arrays"); 209 } else { 210 stack_p = unit_rx_array[unit].stack_array; 211 } 212 if (!stack_p) { 213 unit_rx_array[unit].memstate = PTP_MEMSTATE_FAILURE; 214 return BCM_E_MEMORY; 215 } 216 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx, "%s: stack_p: %p\n", 217 __FUNCTION__, stack_p)); 218 219 for (i = 0; i < PTP_MAX_STACKS_PER_UNIT; ++i) { 220 stack_p[i].memstate = PTP_MEMSTATE_STARTUP; 221 } 222 223 unit_rx_array[unit].stack_array = stack_p; 224 unit_rx_array[unit].memstate = PTP_MEMSTATE_INITIALIZED; 225 226 unit_rx_array[unit].management_cb = NULL; 227 unit_rx_array[unit].event_cb = NULL; 228 unit_rx_array[unit].signal_cb = NULL; 229 unit_rx_array[unit].fault_cb = NULL; 230 231 unit_rx_array[unit].management_user_data = NULL; 232 unit_rx_array[unit].event_user_data = NULL; 233 unit_rx_array[unit].signal_user_data = NULL; 234 unit_rx_array[unit].fault_user_data = NULL; 235 236 /* 237 * Add default callback function for tunneled PTP signaling messages 238 */ 239 if (BCM_FAILURE(rv = _bcm_ptp_register_signal_callback(unit, 240 _bcm_ptp_signal_handler_default, NULL))) { 241 PTP_ERROR_FUNC("_bcm_ptp_register_signal_callback()"); 242 } 243 244 return BCM_E_NONE; 245 } 246 247 /* 248 * Function: 249 * _bcm_ptp_rx_init_detach 250 * Purpose: 251 * Shut down the PTP Rx framework and data of a unit. 252 * Parameters: 253 * unit - (IN) Unit number. 254 * Returns: 255 * BCM_E_XXX 256 * Notes: 257 */ 258 int 259 _bcm_ptp_rx_detach( 260 int unit) 261 { 262 if(unit_rx_array[unit].stack_array) { 263 unit_rx_array[unit].memstate = PTP_MEMSTATE_STARTUP; 264 sal_free(unit_rx_array[unit].stack_array); 265 unit_rx_array[unit].stack_array = NULL; 266 } 267 return BCM_E_NONE; 268 } 269 270 /* 271 * Function: 272 * _bcm_ptp_rx_stack_create 273 * Purpose: 274 * Create the PTP Rx data of a PTP stack. 275 * Parameters: 276 * unit - (IN) Unit number. 277 * ptp_id - (IN) PTP stack ID. 278 * host_mac - (IN) Host MAC address. 279 * top_mac - (IN) ToP MAC address. 280 * tpid - (IN) TPID for Host <-> ToP Communication 281 * vlan - (IN) VLAN for Host <-> ToP Communication 282 * Returns: 283 * BCM_E_XXX 284 * Notes: 285 */ 286 int 287 _bcm_ptp_rx_stack_create( 288 int unit, 289 bcm_ptp_stack_id_t ptp_id, 290 bcm_mac_t *host_mac, 291 bcm_mac_t *top_mac, 292 int tpid, 293 int vlan) 294 { 295 int rv = BCM_E_UNAVAIL; 296 _bcm_ptp_clock_rx_data_t *data_p; 297 int i; 298 299 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 300 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 301 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 302 return rv; 303 } 304 305 if (unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) { 306 LOG_VERBOSE(BSL_LS_BCM_COMMON, 307 (BSL_META_U(unit, 308 "PTP memory state not initialized\n"))); 309 return BCM_E_UNAVAIL; 310 } 311 312 data_p = sal_alloc(PTP_MAX_CLOCK_INSTANCES* 313 sizeof(_bcm_ptp_clock_rx_data_t), 314 "PTP stack Rx array"); 315 316 if (!data_p) { 317 unit_rx_array[unit].stack_array[ptp_id].memstate = 318 PTP_MEMSTATE_FAILURE; 319 LOG_VERBOSE(BSL_LS_BCM_COMMON, 320 (BSL_META_U(unit, 321 "PTP memory state error\n"))); 322 return BCM_E_MEMORY; 323 } 324 325 unit_rx_array[unit].stack_array[ptp_id].clock_data = data_p; 326 unit_rx_array[unit].stack_array[ptp_id].memstate = 327 PTP_MEMSTATE_INITIALIZED; 328 329 #if defined(BCM_PTP_EXTERNAL_STACK_SUPPORT) 330 if (SOC_HAS_PTP_EXTERNAL_STACK_SUPPORT(unit)) { 331 sal_memcpy(unit_rx_array[unit].stack_array[ptp_id].host_mac, host_mac, 332 sizeof(bcm_mac_t)); 333 334 sal_memcpy(unit_rx_array[unit].stack_array[ptp_id].top_mac, top_mac, 335 sizeof(bcm_mac_t)); 336 337 unit_rx_array[unit].stack_array[ptp_id].tpid = tpid; 338 unit_rx_array[unit].stack_array[ptp_id].vlan = vlan; 339 340 #ifndef CUSTOMER_CALLBACK 341 if (!bcm_rx_active(unit)) { 342 if (BCM_FAILURE(rv = bcm_rx_cfg_init(unit))) { 343 PTP_ERROR_FUNC("bcm_rx_cfg_init()"); 344 return rv; 345 } 346 347 if (BCM_FAILURE(rv = bcm_rx_start(unit, NULL))) { 348 PTP_ERROR_FUNC("bcm_rx_start()"); 349 return rv; 350 } 351 } 352 353 if (BCM_FAILURE(rv = bcm_rx_register(unit, "BCM_PTP_Rx", _bcm_ptp_rx_callback, 354 BCM_RX_PRIO_MAX, (void*)ptp_id, BCM_RCO_F_ALL_COS))) { 355 PTP_ERROR_FUNC("bcm_rx_register()"); 356 return rv; 357 } 358 #endif /* CUSTOMER_CALLBACK */ 359 } 360 #endif /* defined(BCM_PTP_EXTERNAL_STACK_SUPPORT) */ 361 362 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) 363 if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) { 364 _bcm_ptp_stack_info_t *stack_p; 365 _bcm_ptp_info_t *ptp_info_p; 366 367 SET_PTP_INFO; 368 stack_p = &ptp_info_p->stack_info[ptp_id]; 369 370 unit_rx_array[unit].stack_array[ptp_id].rx_thread_exit = FALSE; 371 372 unit_rx_array[unit].stack_array[ptp_id].rx_thread = sal_thread_create("PTP Rx", SAL_THREAD_STKSZ, 373 soc_property_get(unit, spn_UC_MSG_THREAD_PRI, 50) + 1, 374 _bcm_ptp_rx_thread, stack_p); 375 if (unit_rx_array[unit].stack_array[ptp_id].rx_thread == SAL_THREAD_ERROR) { 376 rv = BCM_E_INTERNAL; 377 PTP_ERROR_FUNC("sal_thread_create()"); 378 return rv; 379 } 380 } 381 #endif 382 383 for (i = 0; i < PTP_MAX_CLOCKS_PER_STACK; ++i) { 384 if (BCM_FAILURE(rv = _bcm_ptp_rx_clock_create(unit, ptp_id, i))) { 385 PTP_ERROR_FUNC("_bcm_ptp_rx_clock_create()"); 386 return rv; 387 } 388 } 389 390 return rv; 391 } 392 393 int 394 _bcm_ptp_rx_stack_destroy( 395 int unit, 396 bcm_ptp_stack_id_t ptp_id) 397 { 398 int rv = BCM_E_NONE; 399 int i; 400 401 if (unit_rx_array[unit].stack_array[ptp_id].memstate == PTP_MEMSTATE_FAILURE) { 402 /* Initialization / allocation did not succeed before, so just reset the state */ 403 unit_rx_array[unit].stack_array[ptp_id].memstate = PTP_MEMSTATE_STARTUP; 404 return BCM_E_NONE; 405 } 406 407 if (unit_rx_array[unit].stack_array[ptp_id].memstate != PTP_MEMSTATE_INITIALIZED) { 408 return BCM_E_INIT; 409 } 410 411 for (i = 0; i < PTP_MAX_CLOCKS_PER_STACK; ++i) { 412 if (BCM_FAILURE(rv = _bcm_ptp_rx_clock_destroy(unit, ptp_id, i))) { 413 PTP_ERROR_FUNC("_bcm_ptp_rx_clock_create()"); 414 return rv; 415 } 416 } 417 418 #if defined (BCM_PTP_EXTERNAL_STACK_SUPPORT) 419 #ifndef CUSTOMER_CALLBACK 420 421 if (BCM_FAILURE(rv = bcm_rx_unregister(unit, _bcm_ptp_rx_callback, BCM_RX_PRIO_MAX))) { 422 PTP_ERROR_FUNC("bcm_rx_unregister()"); 423 } 424 425 #endif /* CUSTOMER_CALLBACK */ 426 #endif /* BCM_PTP_EXTERNAL_STACK_SUPPORT */ 427 428 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) 429 if (SOC_HAS_PTP_INTERNAL_STACK_SUPPORT(unit)) { 430 if (unit_rx_array[unit].stack_array[ptp_id].rx_thread != SAL_THREAD_ERROR) { 431 unit_rx_array[unit].stack_array[ptp_id].rx_thread_exit = TRUE; 432 /* allow thread to exit */ 433 for (i=0; i < 50; i++) { 434 if (unit_rx_array[unit].stack_array[ptp_id].rx_thread == SAL_THREAD_ERROR) { 435 break; 436 } 437 sal_usleep(10000); 438 } 439 if (unit_rx_array[unit].stack_array[ptp_id].rx_thread != SAL_THREAD_ERROR) { 440 PTP_ERROR("PTP RX thread did not exit gracefully\n"); 441 } 442 } 443 } 444 #endif 445 446 unit_rx_array[unit].stack_array[ptp_id].memstate = PTP_MEMSTATE_STARTUP; 447 sal_free(unit_rx_array[unit].stack_array[ptp_id].clock_data); 448 unit_rx_array[unit].stack_array[ptp_id].clock_data = 0; 449 450 return rv; 451 } 452 453 /* 454 * Function: 455 * _bcm_ptp_rx_clock_create 456 * Purpose: 457 * Create the PTP Rx data of a PTP clock. 458 * Parameters: 459 * unit - (IN) Unit number. 460 * ptp_id - (IN) PTP stack ID. 461 * clock_num - (IN) PTP clock number. 462 * Returns: 463 * BCM_E_XXX 464 * Notes: 465 */ 466 int 467 _bcm_ptp_rx_clock_create( 468 int unit, 469 bcm_ptp_stack_id_t ptp_id, 470 int clock_num) 471 { 472 int rv = BCM_E_UNAVAIL; 473 474 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 475 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 476 return rv; 477 } 478 479 if ((unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 480 (unit_rx_array[unit].stack_array[ptp_id].memstate != 481 PTP_MEMSTATE_INITIALIZED)) { 482 return BCM_E_UNAVAIL; 483 } 484 485 unit_rx_array[unit].stack_array[ptp_id].clock_data[clock_num].response_data = 0; 486 unit_rx_array[unit].stack_array[ptp_id].clock_data[clock_num].response_len = 0; 487 488 unit_rx_array[unit].stack_array[ptp_id].clock_data[clock_num].response_ready = 489 _bcm_ptp_sem_create("BCM_PTP_resp", sal_sem_BINARY, 0); 490 491 return rv; 492 } 493 494 /* 495 * Function: 496 * _bcm_ptp_rx_clock_destroy 497 * Purpose: 498 * Destroy the PTP Rx data of a PTP clock. 499 * Parameters: 500 * unit - (IN) Unit number. 501 * ptp_id - (IN) PTP stack ID. 502 * clock_num - (IN) PTP clock number. 503 * Returns: 504 * BCM_E_XXX 505 * Notes: 506 */ 507 int 508 _bcm_ptp_rx_clock_destroy( 509 int unit, 510 bcm_ptp_stack_id_t ptp_id, 511 int clock_num) 512 { 513 int rv = BCM_E_NONE; 514 515 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 516 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 517 return rv; 518 } 519 520 if ((unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 521 (unit_rx_array[unit].stack_array[ptp_id].memstate != 522 PTP_MEMSTATE_INITIALIZED)) { 523 return BCM_E_UNAVAIL; 524 } 525 526 if (unit_rx_array[unit].stack_array[ptp_id].clock_data[clock_num].response_ready) { 527 _bcm_ptp_sem_destroy(unit_rx_array[unit].stack_array[ptp_id].clock_data[clock_num].response_ready); 528 unit_rx_array[unit].stack_array[ptp_id].clock_data[clock_num].response_ready = 0; 529 } 530 531 return rv; 532 } 533 534 535 /* External version */ 536 int 537 _bcm_ptp_external_rx_response_free(int unit, int ptp_id, uint8 *resp_data) 538 { 539 return bcm_rx_free(unit, resp_data - PTP_RX_UDP_PAYLOAD_OFFSET); 540 } 541 542 /* Internal version */ 543 int 544 _bcm_ptp_internal_rx_response_free(int unit, int ptp_id, uint8 *resp_data) 545 { 546 _bcm_ptp_stack_info_t *stack_p; 547 _bcm_ptp_info_t *ptp_info_p; 548 int i; 549 550 SET_PTP_INFO; 551 stack_p = &ptp_info_p->stack_info[ptp_id]; 552 for (i = 0; i < BCM_PTP_MAX_BUFFERS; ++i) { 553 if (stack_p->int_state.mboxes->mbox[i].data == resp_data) { 554 if (GET_MBOX_STATUS(stack_p, i) != MBOX_STATUS_PENDING_HOST) { 555 LOG_ERROR(BSL_LS_BCM_COMMON, 556 (BSL_META_U(unit, 557 "Invalid mbox status on PTP rx response free (%d)\n"), 558 GET_MBOX_STATUS(stack_p, i))); 559 } 560 SET_MBOX_STATUS(stack_p, i, MBOX_STATUS_EMPTY); 561 return BCM_E_NONE; 562 } 563 } 564 565 LOG_ERROR(BSL_LS_BCM_COMMON, 566 (BSL_META_U(unit, 567 "Invalid PTP rx response free (%p vs %p)\n"), 568 (void *)resp_data, (void*)stack_p->int_state.mboxes->mbox[i-1].data)); 569 570 return BCM_E_NOT_FOUND; 571 } 572 573 574 /* 575 * Function: 576 * _bcm_ptp_rx_response_flush 577 * Purpose: 578 * Flush prior Rx response. 579 * Parameters: 580 * unit - (IN) Unit number. 581 * ptp_id - (IN) PTP stack ID. 582 * clock_num - (IN) PTP clock number. 583 * Returns: 584 * BCM_E_XXX 585 * Notes: 586 */ 587 int 588 _bcm_ptp_rx_response_flush( 589 int unit, 590 bcm_ptp_stack_id_t ptp_id, 591 int clock_num) 592 { 593 int rv = BCM_E_UNAVAIL; 594 int spl; 595 596 uint8 *prior_data; 597 _bcm_ptp_stack_info_t *stack_p; 598 _bcm_ptp_info_t *ptp_info_p; 599 600 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 601 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 602 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 603 return rv; 604 } 605 606 if ((unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 607 (unit_rx_array[unit].stack_array[ptp_id].memstate != 608 PTP_MEMSTATE_INITIALIZED)) { 609 LOG_VERBOSE(BSL_LS_BCM_COMMON, 610 (BSL_META_U(unit, 611 "PTP memory state not initialized\n"))); 612 return BCM_E_UNAVAIL; 613 } 614 615 rv = _bcm_ptp_sem_take(unit_rx_array[unit].stack_array[ptp_id] 616 .clock_data[clock_num].response_ready, sal_mutex_NOWAIT); 617 618 if (rv == BCM_E_NONE) { 619 LOG_WARN(BSL_LS_BCM_PTP, 620 (BSL_META_U(unit, 621 "PTP mbox flush found waiting sem. Rx task blocked?\n"))); 622 } else { 623 LOG_WARN(BSL_LS_BCM_PTP, 624 (BSL_META_U(unit, 625 "PTP mbox flush: no sem waiting.\n"))); 626 } 627 628 /* 629 * Flush response. 630 * NOTICE: Response already waiting is unexpected. 631 */ 632 /* Lock. */ 633 spl = sal_splhi(); 634 635 prior_data = unit_rx_array[unit].stack_array[ptp_id] 636 .clock_data[clock_num].response_data; 637 638 unit_rx_array[unit].stack_array[ptp_id] 639 .clock_data[clock_num].response_data = 0; 640 641 /* Unlock. */ 642 sal_spl(spl); 643 644 SET_PTP_INFO; 645 stack_p = &ptp_info_p->stack_info[ptp_id]; 646 647 if (prior_data) { 648 stack_p->rx_free(unit, ptp_id, prior_data); 649 } 650 651 /* MBOX 0 is the one that has the response in it */ 652 SET_MBOX_STATUS(stack_p, 0, MBOX_STATUS_EMPTY); 653 654 return rv; 655 } 656 657 /* 658 * Function: 659 * _bcm_ptp_rx_response_get 660 * Purpose: 661 * Get Rx response data for a PTP clock. 662 * Parameters: 663 * unit - (IN) Unit number. 664 * ptp_id - (IN) PTP stack ID. 665 * clock_num - (IN) PTP clock number. 666 * usec - (IN) Semaphore timeout (usec). 667 * data - (OUT) Response data. 668 * data_len - (OUT) Response data size (octets). 669 * Returns: 670 * BCM_E_XXX 671 * Notes: 672 */ 673 int 674 _bcm_ptp_rx_response_get( 675 int unit, 676 bcm_ptp_stack_id_t ptp_id, 677 int clock_num, 678 int usec, 679 uint8 **data, 680 int *data_len) 681 { 682 int rv = BCM_E_UNAVAIL; 683 int spl; 684 sal_usecs_t expiration_time = sal_time_usecs() + usec; 685 686 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, 687 PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 688 return rv; 689 } 690 691 if ((unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 692 (unit_rx_array[unit].stack_array[ptp_id].memstate != 693 PTP_MEMSTATE_INITIALIZED)) { 694 return BCM_E_UNAVAIL; 695 } 696 697 rv = BCM_E_FAIL; 698 /* ptp_printf("Await resp @ %d\n", (int)sal_time_usecs()); */ 699 700 while (BCM_FAILURE(rv) && (int32) (sal_time_usecs() - expiration_time) < 0) { 701 rv = _bcm_ptp_sem_take(unit_rx_array[unit].stack_array[ptp_id].clock_data[clock_num].response_ready, usec); 702 } 703 if (BCM_FAILURE(rv)) { 704 LOG_VERBOSE(BSL_LS_BCM_COMMON, 705 (BSL_META_U(unit, 706 "Failed management Tx to ToP\n"))); 707 PTP_ERROR_FUNC("_bcm_ptp_sem_take()"); 708 return rv; 709 } 710 711 /* Lock. */ 712 spl = sal_splhi(); 713 714 *data = unit_rx_array[unit].stack_array[ptp_id] 715 .clock_data[clock_num].response_data; 716 717 *data_len = unit_rx_array[unit].stack_array[ptp_id] 718 .clock_data[clock_num].response_len; 719 720 unit_rx_array[unit].stack_array[ptp_id] 721 .clock_data[clock_num].response_data = 0; 722 723 /* Unlock. */ 724 sal_spl(spl); 725 726 return rv; 727 } 728 729 730 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) 731 static void _bcm_ptp_rx_thread(void *arg) 732 { 733 _bcm_ptp_stack_info_t *stack_p = arg; 734 int unit = stack_p->unit; 735 bcm_ptp_stack_id_t ptp_id = stack_p->stack_id; 736 int rv = 0; 737 _bcm_ptp_stack_rx_array_t *stack_rx = &unit_rx_array[unit].stack_array[ptp_id]; 738 bcm_ptp_cb_msg_t cb_msg; 739 int rx_thread_exit = 0; 740 741 /* sal_usecs_t last_time = 0; */ 742 /* sal_usecs_t this_time = 0; */ 743 744 while (1) { 745 int mbox; 746 747 /* mos_msg_data_t rcv; */ 748 /* int rv = soc_cmic_uc_msg_receive(stack_p->unit, stack_p->int_state.core_num, MOS_MSG_CLASS_1588, &rcv, sal_sem_FOREVER); */ 749 /* if (rv) { */ 750 /* /\* got error, so wait *\/ */ 751 /* sal_usleep(100000); */ 752 /* } */ 753 /* The uc_msg is just a signal that there is a message somewhere to get, so look through all mboxes */ 754 755 /* rather than getting woken by soc_cmic_uc_msg_receive, just poll */ 756 757 /* Note: on some SAL implementations, a short usleep is done by doing a 'yield' within a loop, 758 rather than a true 'sleep'. If no other tasks are using the CPU, this will effectively be a 759 busy-wait, as the yield will immediately return. This can make it appear that the PTP Rx thread 760 is using a lot of CPU, though this is only because no other task is in a running state. 761 To avoid this appearance of CPU load, the value of BCM_PTP_RX_POLL_WAIT_USEC can be increased 762 via the Make.local file, e.g.: CFGFLAGS += -DBCM_PTP_RX_POLL_WAIT_USEC=11000 763 */ 764 sal_usleep(BCM_PTP_RX_POLL_WAIT_USEC); 765 766 /* last_time = this_time; */ 767 /* this_time = sal_time_usecs(); */ 768 769 for (mbox = 0; mbox < BCM_PTP_MAX_BUFFERS; ++mbox) { 770 771 if (stack_rx->rx_thread_exit || (_bcm_ptp_running(unit) != BCM_E_NONE) 772 || (stack_p->int_state.mboxes == NULL)) { 773 /* Existing the rx thread */ 774 rx_thread_exit = 1; 775 break; 776 } 777 778 /* Invalidate cache for the shared memory before reading it */ 779 soc_cm_sinval(unit, (void*)&stack_p->int_state.mboxes->mbox[mbox].status, sizeof(stack_p->int_state.mboxes->mbox[mbox])); 780 781 switch (soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].status)) { 782 case MBOX_STATUS_ATTN_HOST_TUNNEL: { 783 int cb_flags = 0; 784 unsigned clock_num = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].clock_num); 785 int message_type = _bcm_ptp_uint16_read((uint8 *)stack_p->int_state.mboxes->mbox[mbox].data + MBOX_TUNNEL_MSG_TYPE_OFFSET); 786 int port_num = _bcm_ptp_uint16_read((uint8 *)stack_p->int_state.mboxes->mbox[mbox].data + MBOX_TUNNEL_PORT_NUM_OFFSET); 787 int protocol = _bcm_ptp_uint16_read((uint8 *)stack_p->int_state.mboxes->mbox[mbox].data + MBOX_TUNNEL_PROTOCOL_OFFSET); 788 int src_addr_offset = _bcm_ptp_uint16_read((uint8 *)stack_p->int_state.mboxes->mbox[mbox].data + MBOX_TUNNEL_SRC_ADDR_OFFS_OFFSET); 789 int ptp_offset = _bcm_ptp_uint16_read((uint8 *)stack_p->int_state.mboxes->mbox[mbox].data + MBOX_TUNNEL_PTP_OFFS_OFFSET); 790 uint8 * cb_data = (uint8 *)stack_p->int_state.mboxes->mbox[mbox].data + MBOX_TUNNEL_PACKET_OFFSET; 791 int cb_data_len = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].data_len) - MBOX_TUNNEL_PACKET_OFFSET; 792 793 bcm_ptp_clock_identity_t peer_clockIdentity; 794 bcm_ptp_clock_port_address_t peer_portAddress; 795 796 /* ptp_printf("Got Tunnel: MsgType:%d, Proto:%d Clk:%d\n", message_type, protocol, clock_num); */ 797 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx, 798 "Got Tunnel: MsgType:%d, Proto:%d Clk:%d\n", 799 message_type, protocol, clock_num)); 800 801 802 _bcm_ptp_most_recent_clock_num = clock_num; 803 _bcm_ptp_most_recent_port = port_num; 804 _bcm_ptp_most_recent_protocol = protocol; 805 _bcm_ptp_most_recent_src_addr_offset = src_addr_offset; 806 _bcm_ptp_most_recent_msg_offset = ptp_offset; 807 cb_flags = 0; 808 809 if (message_type == bcmPTP_MESSAGE_TYPE_SIGNALING || 810 message_type == bcmPTP_MESSAGE_TYPE_MANAGEMENT) { 811 /* Peer information for counts of Rx signaling and external management messages. */ 812 sal_memcpy(peer_clockIdentity, 813 cb_data + ptp_offset + PTP_PTPHDR_SRCPORT_OFFSET_OCTETS, 814 sizeof(bcm_ptp_clock_identity_t)); 815 816 peer_portAddress.addr_type = protocol; 817 sal_memset(peer_portAddress.address, 0, BCM_PTP_MAX_NETW_ADDR_SIZE); 818 switch (protocol) { 819 case bcmPTPUDPIPv4: 820 sal_memcpy(peer_portAddress.address, 821 cb_data + src_addr_offset, PTP_IPV4_ADDR_SIZE_BYTES); 822 break; 823 case bcmPTPUDPIPv6: 824 sal_memcpy(peer_portAddress.address, 825 cb_data + src_addr_offset, PTP_IPV6_ADDR_SIZE_BYTES); 826 break; 827 case bcmPTPIEEE8023: 828 sal_memcpy(peer_portAddress.address, 829 cb_data + src_addr_offset, PTP_MAC_ADDR_SIZE_BYTES); 830 break; 831 default: 832 ; 833 } 834 } 835 836 switch (message_type) { 837 case bcmPTP_MESSAGE_TYPE_SIGNALING: 838 /* Peer dataset counts of Rx signaling messages. */ 839 if (BCM_FAILURE(rv = _bcm_ptp_update_peer_counts(unit, ptp_id, clock_num, port_num, 840 &peer_clockIdentity, &peer_portAddress, 0, 0, 0, 0, 0, 0, 0, 1, 0, NULL))) { 841 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx, 842 "Error in _bcm_ptp_update_peer_counts()\n")); 843 PTP_ERROR_FUNC("_bcm_ptp_update_peer_counts()"); 844 } 845 846 if (unit_rx_array[unit].signal_cb) { 847 sal_memset(&cb_msg, 0, sizeof(bcm_ptp_cb_msg_t)); 848 cb_msg.length = cb_data_len; 849 cb_msg.data = cb_data; 850 unit_rx_array[unit].signal_cb(unit, ptp_id, clock_num, port_num, 851 bcmPTPCallbackTypeSignal, &cb_msg, 852 unit_rx_array[unit].signal_user_data); 853 } 854 break; 855 856 case bcmPTP_MESSAGE_TYPE_MANAGEMENT: 857 /* Peer dataset counts of Rx external management messages. */ 858 if (BCM_FAILURE(rv = _bcm_ptp_update_peer_counts(unit, ptp_id, clock_num, port_num, 859 &peer_clockIdentity, &peer_portAddress, 0, 0, 0, 0, 0, 0, 1, 0, 0, NULL))) { 860 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx, 861 "Error in _bcm_ptp_update_peer_counts()\n")); 862 PTP_ERROR_FUNC("_bcm_ptp_update_peer_counts()"); 863 } 864 865 if (unit_rx_array[unit].management_cb) { 866 sal_memset(&cb_msg, 0, sizeof(bcm_ptp_cb_msg_t)); 867 868 cb_msg.flags = cb_flags; 869 cb_msg.protocol = protocol; 870 cb_msg.src_addr_offset = src_addr_offset; 871 cb_msg.msg_offset = ptp_offset; 872 cb_msg.length = cb_data_len; 873 cb_msg.data = cb_data; 874 875 if (unit_rx_array[unit].management_cb(unit, ptp_id, clock_num, port_num, 876 bcmPTPCallbackTypeManagement, &cb_msg, 877 unit_rx_array[unit].management_user_data) 878 == bcmPTPCallbackAccept) { 879 if (BCM_FAILURE(rv =_bcm_ptp_tunnel_message_to_top(unit, 880 ptp_id, clock_num, port_num, 881 cb_data_len, cb_data, 1))) { 882 PTP_ERROR_FUNC("_bcm_ptp_tunnel_message_to_top()"); 883 } 884 } 885 } 886 break; 887 case bcmPTP_MESSAGE_TYPE_ARP: 888 if (_bcm_ptp_arp_callback) { 889 _bcm_ptp_arp_callback(unit, ptp_id, protocol, src_addr_offset, ptp_offset, cb_data_len, cb_data); 890 } 891 break; 892 893 case (0x0100): 894 895 if (BCM_FAILURE(rv = bcm_esmc_rx(unit, ptp_id, port_num, 896 protocol, cb_data_len, cb_data))) { 897 PTP_ERROR_FUNC("bcm_esmc_rx()"); 898 } 899 break; 900 901 default: 902 LOG_VERBOSE(BSL_LS_BCM_COMMON, 903 (BSL_META_U(unit, 904 "Improper PTP tunneled message type: %d in mbox %d\n"), message_type, mbox)); 905 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx, 906 "Improper PTP tunneled message type: %d in mbox %d\n", 907 message_type, mbox)); 908 break; 909 } 910 /* Free the mbox so the CMICm can use it again */ 911 SET_MBOX_STATUS(stack_p, mbox, MBOX_STATUS_EMPTY); 912 913 break; 914 } 915 916 case MBOX_STATUS_ATTN_HOST_EVENT: { 917 918 unsigned clock_num = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].clock_num); 919 int cb_flags = 0; 920 int cb_data_len = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].data_len); 921 uint8 *cb_data = (uint8 *)stack_p->int_state.mboxes->mbox[mbox].data; 922 int ev_internal = 0; 923 #ifdef PTP_RX_CALLBACK_DEBUG 924 LOG_CLI((BSL_META_U(unit, 925 "Rx thread : Host event(%d)\n"), cb_data_len)); 926 _bcm_ptp_dump_hex(cb_data, cb_data_len, 0); 927 #endif 928 929 if (BCM_FAILURE(rv = _bcm_ptp_event_message_monitor(unit, ptp_id, 930 cb_data_len, cb_data, &ev_internal))) { 931 PTP_ERROR_FUNC("_bcm_ptp_event_message_monitor()"); 932 } 933 934 if (unit_rx_array[unit].event_cb && !ev_internal) { 935 sal_memset(&cb_msg, 0, sizeof(bcm_ptp_cb_msg_t)); 936 cb_msg.length = cb_data_len; 937 cb_msg.data = cb_data; 938 cb_msg.flags = cb_flags; 939 unit_rx_array[unit].event_cb(unit, ptp_id, clock_num, 940 PTP_CLOCK_PORT_NUMBER_DEFAULT, 941 bcmPTPCallbackTypeEvent, &cb_msg, 942 unit_rx_array[unit].event_user_data); 943 } 944 945 SET_MBOX_STATUS(stack_p, mbox, MBOX_STATUS_EMPTY); 946 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx, "Got HOST_EVENT in mbox %d\n", mbox)); 947 break; 948 } 949 950 case MBOX_STATUS_ATTN_HOST_RESP: { 951 /* This really should only be in mbox 0, but here for generality */ 952 int clock_num = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].clock_num); 953 954 /* ptp_printf("Got HOST_RESP in mbox %d\n", mbox); */ 955 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx, "Got HOST_RESP in mbox %d\n", mbox)); 956 957 stack_rx->clock_data[clock_num].response_data = (uint8 *)stack_p->int_state.mboxes->mbox[mbox].data; 958 stack_rx->clock_data[clock_num].response_len = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].data_len); 959 960 SET_MBOX_STATUS(stack_p, mbox, MBOX_STATUS_PENDING_HOST); 961 962 rv = _bcm_ptp_sem_give(stack_rx->clock_data[clock_num].response_ready); 963 if (BCM_FAILURE(rv)) { 964 PTP_ERROR_FUNC("_bcm_ptp_sem_give()"); 965 } 966 break; 967 } 968 case MBOX_STATUS_ATTN_HOST_TIMESTAMPS: { 969 unsigned clock_num = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].clock_num); 970 int cb_data_len = soc_ntohl(stack_p->int_state.mboxes->mbox[mbox].data_len); 971 uint8 *cb_data = (uint8 *)stack_p->int_state.mboxes->mbox[mbox].data; 972 if (BCM_FAILURE(rv =_bcm_ptp_timestamp_queue_add(unit, 973 ptp_id, clock_num, cb_data_len, cb_data))) { 974 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 975 mbox_tsevent_stats.error_queue_add++; 976 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */ 977 PTP_ERROR_FUNC("_bcm_ptp_queue_timestamp_message()"); 978 } else { 979 #ifdef BCM_PTP_EXT_SERVO_SUPPORT 980 mbox_tsevent_stats.event_queued++; 981 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */ 982 } 983 SET_MBOX_STATUS(stack_p, mbox, MBOX_STATUS_EMPTY); 984 SOC_CMIC_UCDBG_LOG_ADD((unit, _bcmCmicUcDbgLogHostPtpRx, "Got HOST_TIMESTAMPS_EVENT in mbox %d\n", mbox)); 985 break; 986 } 987 } 988 } 989 /* exit the thread */ 990 if (rx_thread_exit) { 991 break; 992 } 993 } /* while (1) loop */ 994 995 stack_rx->rx_thread = SAL_THREAD_ERROR; 996 sal_thread_exit(0); 997 } 998 #endif /* defined(BCM_PTP_INTERNAL_STACK_SUPPORT) */ 999 1000 #if defined(BCM_PTP_EXTERNAL_STACK_SUPPORT) 1001 1002 bcm_rx_t 1003 _bcm_ptp_rx_callback( 1004 int unit, 1005 bcm_pkt_t *pkt, 1006 void *cookie) 1007 { 1008 int rv = BCM_E_UNAVAIL; 1009 int spl; 1010 1011 uint8 *prior_data; 1012 uint16 udp_dest_port; 1013 uint16 message_len; 1014 1015 int wrapClockNumber; 1016 int wrapPortNumber; 1017 bcm_ptp_message_type_t wrapMessageType; 1018 bcm_ptp_protocol_t wrapProtocol; 1019 uint16 wrapSrcAddrOffset; 1020 uint16 wrapPtpOffset; 1021 1022 _bcm_ptp_stack_info_t *stack_p; 1023 _bcm_ptp_info_t *ptp_info_p; 1024 bcm_ptp_clock_identity_t cb_clock_identity; 1025 bcm_ptp_stack_id_t cb_ptp_id = (bcm_ptp_stack_id_t)cookie; 1026 int cb_clock_num; 1027 uint32 cb_flags; 1028 int ev_internal = 0; 1029 int vlan, tpid; 1030 int i = 0; 1031 1032 bcm_ptp_clock_identity_t peer_clockIdentity; 1033 bcm_ptp_clock_port_address_t peer_portAddress; 1034 1035 bcm_ptp_cb_msg_t cb_msg; 1036 1037 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT, 1038 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1039 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 1040 return BCM_RX_NOT_HANDLED; 1041 } 1042 1043 if (unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) { 1044 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1045 (BSL_META_U(unit, 1046 "Rx unit data not initialized\n"))); 1047 return BCM_RX_NOT_HANDLED; 1048 } 1049 1050 #ifdef PTP_RX_CALLBACK_DEBUG 1051 LOG_CLI((BSL_META_U(unit, 1052 "_bcm_ptp_rx_callback(%d,%d)\n"), 1053 pkt->pkt_len, BCM_PKT_IEEE_LEN(pkt))); 1054 _bcm_ptp_dump_hex(BCM_PKT_IEEE(pkt), BCM_PKT_IEEE_LEN(pkt), 0); 1055 #endif 1056 1057 if (pkt->pkt_data[0].len < pkt->pkt_len || 1058 pkt->pkt_len < PTP_RX_PACKET_MIN_SIZE_OCTETS) { 1059 /* 1060 * Ignore packet. 1061 * NOTICE: inconsistent or incompatible packet length. 1062 */ 1063 return BCM_RX_NOT_HANDLED; 1064 } 1065 1066 if (BCM_FAILURE(rv = _bcm_ptp_rx_message_length_get(BCM_PKT_IEEE(pkt), 1067 &message_len))) { 1068 PTP_ERROR_FUNC("_bcm_ptp_rx_message_length_get()"); 1069 return BCM_RX_NOT_HANDLED; 1070 } 1071 1072 /* 1073 * Parse packet data. 1074 */ 1075 1076 /** Get destination port from UDP header, which is a proxy for packet 1077 * type and subsequent handling. 1078 */ 1079 if (BCM_FAILURE(rv = _bcm_ptp_rx_message_destination_port_get( 1080 BCM_PKT_IEEE(pkt), &udp_dest_port))) { 1081 PTP_ERROR_FUNC("_bcm_ptp_rx_message_destination_port_get()"); 1082 return BCM_RX_NOT_HANDLED; 1083 } 1084 1085 switch (udp_dest_port) { 1086 case (0x0140): 1087 /* Response message. */ 1088 1089 /* Sanity / Security check: Validate VLAN & MAC information for this clock */ 1090 tpid = _bcm_ptp_uint16_read(BCM_PKT_IEEE(pkt) + 12); /* 12: fixed offset for TPID/VLAN */ 1091 1092 /* Extract only vid, mask out Pri and CFI */ 1093 vlan = (_bcm_ptp_uint16_read(BCM_PKT_IEEE(pkt) + 14) & 0x0FFF); 1094 1095 if (tpid != unit_rx_array[unit].stack_array[cb_ptp_id].tpid || 1096 vlan != unit_rx_array[unit].stack_array[cb_ptp_id].vlan) { 1097 /* This is a PTP message, but not from our stack (since it is on the wrong VLAN). */ 1098 return BCM_RX_NOT_HANDLED; 1099 } 1100 1101 if (pkt->pkt_len < PTP_RX_MGMT_MIN_SIZE) { 1102 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1103 (BSL_META_U(unit, 1104 "Bad response len\n"))); 1105 return BCM_RX_NOT_HANDLED; 1106 } 1107 1108 /* 1109 * Parse packet data. 1110 * Lookup the unit number, PTP stack ID, and PTP clock number 1111 * association of the packet based on the sender's PTP clock 1112 * identity. 1113 */ 1114 if (BCM_FAILURE(rv = _bcm_ptp_rx_message_source_clock_identity_get( 1115 BCM_PKT_IEEE(pkt), &cb_clock_identity))) { 1116 PTP_ERROR_FUNC("_bcm_ptp_rx_message_source_clock_identity_get()"); 1117 return BCM_RX_NOT_HANDLED; 1118 } 1119 1120 if (BCM_FAILURE(rv = _bcm_ptp_clock_lookup(cb_clock_identity, unit, 1121 cb_ptp_id, &cb_clock_num))) { 1122 /* Not from one of this stack's clocks, so leave it */ 1123 return BCM_RX_NOT_HANDLED; 1124 } 1125 1126 /* 1127 * Ensure that Rx framework is initialized and Rx data structures are 1128 * created for the requisite unit and PTP stack. 1129 */ 1130 if ((unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 1131 (unit_rx_array[unit].stack_array[cb_ptp_id].memstate != 1132 PTP_MEMSTATE_INITIALIZED)) { 1133 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1134 (BSL_META_U(unit, 1135 "Rx unit/stack data not initialized\n"))); 1136 return BCM_RX_NOT_HANDLED; 1137 } 1138 1139 if (sal_memcmp(BCM_PKT_IEEE(pkt) + sizeof(bcm_mac_t), 1140 unit_rx_array[unit].stack_array[cb_ptp_id].top_mac, 1141 sizeof(bcm_mac_t)) != 0) { 1142 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1143 (BSL_META_U(unit, 1144 "Bad response smac\n"))); 1145 } 1146 1147 if (sal_memcmp(BCM_PKT_IEEE(pkt), 1148 unit_rx_array[unit].stack_array[cb_ptp_id].host_mac, 1149 sizeof(bcm_mac_t)) != 0) { 1150 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1151 (BSL_META_U(unit, 1152 "Bad response dmac\n"))); 1153 } 1154 1155 /* Lock. */ 1156 spl = sal_splhi(); 1157 1158 prior_data = unit_rx_array[unit].stack_array[cb_ptp_id] 1159 .clock_data[cb_clock_num] 1160 .response_data; 1161 1162 unit_rx_array[unit].stack_array[cb_ptp_id] 1163 .clock_data[cb_clock_num] 1164 .response_data = pkt->pkt_data[0].data + PTP_RX_UDP_PAYLOAD_OFFSET; 1165 1166 unit_rx_array[unit].stack_array[cb_ptp_id] 1167 .clock_data[cb_clock_num] 1168 .response_len = pkt->pkt_len - PTP_RX_UDP_PAYLOAD_OFFSET; 1169 1170 /* Unlock. */ 1171 sal_spl(spl); 1172 1173 /* 1174 * Free unclaimed response. 1175 * NOTICE: If prior data exists, it must be freed. 1176 */ 1177 if (prior_data) { 1178 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1179 (BSL_META_U(unit, 1180 "Unclaimed response freed\n"))); 1181 1182 SET_PTP_INFO; 1183 stack_p = &ptp_info_p->stack_info[cb_ptp_id]; 1184 1185 stack_p->rx_free(unit, cb_ptp_id, prior_data); 1186 } 1187 1188 rv = _bcm_ptp_sem_give(unit_rx_array[unit].stack_array[cb_ptp_id] 1189 .clock_data[cb_clock_num].response_ready); 1190 if (BCM_FAILURE(rv)) { 1191 PTP_ERROR_FUNC("_bcm_ptp_sem_give()"); 1192 } 1193 1194 return BCM_RX_HANDLED_OWNED; 1195 break; 1196 1197 case (0x0141): 1198 /* Forwarded (tunnel) message. */ 1199 if (message_len < PTP_RX_TUNNEL_MSG_MIN_SIZE_OCTETS) { 1200 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1201 (BSL_META_U(unit, 1202 "Invalid (too-short) tunnel message received (0x%04x)\n"), 1203 message_len)); 1204 return BCM_RX_HANDLED; 1205 } 1206 1207 /* 1208 * Parse wrapping header. 1209 * Move cursor forward to "remove" wrapping header. 1210 * 1211 * NOTICE: Forwarded tunnel message prepends an 11-element header, which 1212 * includes PTP message and addressing metadata. 1213 * Wrapping Header Octet 0 : Instance number. 1214 * Wrapping Header Octets 1...2 : Local (receiving) port number. 1215 * Wrapping Header Octets 3...4 : Message type. 1216 * Wrapping Header Octets 5...6 : Ethertype. 1217 * Wrapping Header Octets 7...8 : Source address offset. 1218 * Wrapping Header Octets 9...10 : PTP payload offset. 1219 */ 1220 i = PTP_PTPHDR_START_IDX; 1221 1222 wrapClockNumber = *(BCM_PKT_IEEE(pkt) + i); 1223 ++i; 1224 --message_len; 1225 1226 wrapPortNumber = _bcm_ptp_uint16_read(BCM_PKT_IEEE(pkt) + i); 1227 i += sizeof(uint16); 1228 message_len -= sizeof(uint16); 1229 1230 wrapMessageType = _bcm_ptp_uint16_read(BCM_PKT_IEEE(pkt) + i); 1231 i += sizeof(uint16); 1232 message_len -= sizeof(uint16); 1233 1234 wrapProtocol = _bcm_ptp_uint16_read(BCM_PKT_IEEE(pkt) + i); 1235 i += sizeof(uint16); 1236 message_len -= sizeof(uint16); 1237 1238 wrapSrcAddrOffset = _bcm_ptp_uint16_read(BCM_PKT_IEEE(pkt) + i); 1239 i += sizeof(uint16); 1240 message_len -= sizeof(uint16); 1241 1242 wrapPtpOffset = _bcm_ptp_uint16_read(BCM_PKT_IEEE(pkt) + i); 1243 i += sizeof(uint16); 1244 message_len -= sizeof(uint16); 1245 1246 1247 _bcm_ptp_most_recent_clock_num = wrapClockNumber; 1248 _bcm_ptp_most_recent_port = wrapPortNumber; 1249 _bcm_ptp_most_recent_protocol = wrapProtocol; 1250 _bcm_ptp_most_recent_src_addr_offset = wrapSrcAddrOffset; 1251 _bcm_ptp_most_recent_msg_offset = wrapPtpOffset; 1252 1253 /* 1254 * Parse packet data. 1255 * Lookup the unit number, PTP stack ID, and PTP clock number 1256 * association of the packet based on the recipient's PTP clock 1257 * identity. 1258 */ 1259 if (wrapMessageType == bcmPTP_MESSAGE_TYPE_SIGNALING || 1260 wrapMessageType == bcmPTP_MESSAGE_TYPE_MANAGEMENT) { 1261 /* PTP tunneled message. */ 1262 sal_memcpy(cb_clock_identity, 1263 BCM_PKT_IEEE(pkt) + i + wrapPtpOffset + PTP_PTPHDR_SIZE_OCTETS, 1264 sizeof(bcm_ptp_clock_identity_t)); 1265 1266 /* Peer information for counts of Rx signaling and external management messages. */ 1267 sal_memcpy(peer_clockIdentity, 1268 BCM_PKT_IEEE(pkt) + i + wrapPtpOffset + PTP_PTPHDR_SRCPORT_OFFSET_OCTETS, 1269 sizeof(bcm_ptp_clock_identity_t)); 1270 1271 peer_portAddress.addr_type = wrapProtocol; 1272 sal_memset(peer_portAddress.address, 0, BCM_PTP_MAX_NETW_ADDR_SIZE); 1273 switch (wrapProtocol) { 1274 case bcmPTPUDPIPv4: 1275 sal_memcpy(peer_portAddress.address, 1276 BCM_PKT_IEEE(pkt) + i + wrapSrcAddrOffset, PTP_IPV4_ADDR_SIZE_BYTES); 1277 break; 1278 case bcmPTPUDPIPv6: 1279 sal_memcpy(peer_portAddress.address, 1280 BCM_PKT_IEEE(pkt) + i + wrapSrcAddrOffset, PTP_IPV6_ADDR_SIZE_BYTES); 1281 break; 1282 case bcmPTPIEEE8023: 1283 sal_memcpy(peer_portAddress.address, 1284 BCM_PKT_IEEE(pkt) + i + wrapSrcAddrOffset, PTP_MAC_ADDR_SIZE_BYTES); 1285 break; 1286 default: 1287 ; 1288 } 1289 } else { 1290 /* Non-PTP tunneled message (e.g. ARP). */ 1291 1292 1293 sal_memset(cb_clock_identity, 0xff, sizeof(bcm_ptp_clock_identity_t)); 1294 } 1295 1296 if (BCM_FAILURE(rv = _bcm_ptp_clock_lookup(cb_clock_identity, unit, 1297 cb_ptp_id, &cb_clock_num))) { 1298 /* Not from one of this stack's clocks, so leave it */ 1299 return BCM_RX_NOT_HANDLED; 1300 } 1301 1302 /* 1303 * Ensure that Rx framework is initialized and Rx data structures are 1304 * created for the requisite unit and PTP stack. 1305 */ 1306 if ((unit_rx_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) || 1307 (unit_rx_array[unit].stack_array[cb_ptp_id].memstate != 1308 PTP_MEMSTATE_INITIALIZED)) { 1309 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1310 (BSL_META_U(unit, 1311 "Rx unit/stack data not initialized\n"))); 1312 return BCM_RX_NOT_HANDLED; 1313 } 1314 1315 switch (wrapMessageType) { 1316 case bcmPTP_MESSAGE_TYPE_SIGNALING: 1317 /* Peer dataset counts of Rx signaling messages. */ 1318 if (BCM_FAILURE(rv = _bcm_ptp_update_peer_counts(unit, cb_ptp_id, wrapClockNumber, wrapPortNumber, 1319 &peer_clockIdentity, &peer_portAddress, 0, 0, 0, 0, 0, 0, 0, 1, 0, NULL))) { 1320 PTP_ERROR_FUNC("_bcm_ptp_update_peer_counts()"); 1321 } 1322 1323 1324 cb_flags = 0; 1325 1326 if (unit_rx_array[unit].signal_cb) { 1327 cb_msg.flags = cb_flags; 1328 cb_msg.protocol = wrapProtocol; 1329 cb_msg.src_addr_offset = wrapSrcAddrOffset; 1330 cb_msg.msg_offset = wrapPtpOffset; 1331 cb_msg.length = message_len; 1332 cb_msg.data = BCM_PKT_IEEE(pkt) + i; 1333 1334 unit_rx_array[unit].signal_cb(unit, cb_ptp_id, 1335 cb_clock_num, wrapPortNumber, 1336 bcmPTPCallbackTypeSignal, &cb_msg, 1337 unit_rx_array[unit].signal_user_data); 1338 } 1339 break; 1340 1341 case bcmPTP_MESSAGE_TYPE_MANAGEMENT: 1342 /* Peer dataset counts of Rx external management messages. */ 1343 if (BCM_FAILURE(rv = _bcm_ptp_update_peer_counts(unit, cb_ptp_id, wrapClockNumber, wrapPortNumber, 1344 &peer_clockIdentity, &peer_portAddress, 0, 0, 0, 0, 0, 0, 1, 0, 0, NULL))) { 1345 PTP_ERROR_FUNC("_bcm_ptp_update_peer_counts()"); 1346 } 1347 1348 1349 cb_flags = 0; 1350 1351 if (unit_rx_array[unit].management_cb) { 1352 cb_msg.flags = cb_flags; 1353 cb_msg.protocol = wrapProtocol; 1354 cb_msg.src_addr_offset = wrapSrcAddrOffset; 1355 cb_msg.msg_offset = wrapPtpOffset; 1356 cb_msg.length = message_len; 1357 cb_msg.data = BCM_PKT_IEEE(pkt) + i; 1358 1359 if (unit_rx_array[unit].management_cb(unit, cb_ptp_id, 1360 cb_clock_num, wrapPortNumber, 1361 bcmPTPCallbackTypeManagement, &cb_msg, 1362 unit_rx_array[unit].management_user_data) == bcmPTPCallbackAccept) { 1363 /* Tunnel message to ToP. */ 1364 if (BCM_FAILURE(rv =_bcm_ptp_tunnel_message_to_top(unit, 1365 cb_ptp_id, cb_clock_num, wrapPortNumber, 1366 message_len, BCM_PKT_IEEE(pkt) + i, 1))) { 1367 PTP_ERROR_FUNC("_bcm_ptp_tunnel_message_to_top()"); 1368 } 1369 } 1370 } 1371 break; 1372 1373 case bcmPTP_MESSAGE_TYPE_ARP: 1374 if (_bcm_ptp_arp_callback) { 1375 _bcm_ptp_arp_callback(unit, cb_ptp_id, wrapProtocol, wrapSrcAddrOffset, 1376 wrapPtpOffset, message_len, BCM_PKT_IEEE(pkt) + i); 1377 } 1378 break; 1379 1380 default: 1381 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1382 (BSL_META_U(unit, 1383 "Invalid tunnel message received: " 1384 "unknown/unsupported type (0x%02x)\n"), wrapMessageType)); 1385 } 1386 break; 1387 1388 case (0x0142): 1389 /* Event message. */ 1390 if (message_len < PTP_RX_EVENT_MSG_MIN_SIZE_OCTETS) { 1391 LOG_VERBOSE(BSL_LS_BCM_COMMON, 1392 (BSL_META_U(unit, 1393 "Invalid (too-short) event message received (0x%04x)\n"), 1394 message_len)); 1395 return BCM_RX_HANDLED; 1396 } 1397 1398 1399 cb_ptp_id = 0; 1400 cb_clock_num = 0; 1401 cb_flags = 0; 1402 1403 if (BCM_FAILURE(rv = _bcm_ptp_event_message_monitor(unit, cb_ptp_id, 1404 message_len, BCM_PKT_IEEE(pkt) + PTP_PTPHDR_START_IDX, &ev_internal))) { 1405 PTP_ERROR_FUNC("_bcm_ptp_event_message_monitor()"); 1406 } 1407 1408 if (unit_rx_array[unit].event_cb && !ev_internal) { 1409 i = PTP_PTPHDR_START_IDX; 1410 1411 cb_msg.flags = cb_flags; 1412 cb_msg.protocol = bcmPTPUDPIPv4; 1413 cb_msg.src_addr_offset = 0; 1414 cb_msg.msg_offset = 0; 1415 cb_msg.length = message_len; 1416 cb_msg.data = BCM_PKT_IEEE(pkt) + i; 1417 1418 unit_rx_array[unit].event_cb(unit, cb_ptp_id, 1419 cb_clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT, 1420 bcmPTPCallbackTypeEvent, &cb_msg, 1421 unit_rx_array[unit].event_user_data); 1422 } 1423 1424 break; 1425 1426 default: 1427 #ifdef PTP_RX_CALLBACK_DEBUG 1428 LOG_CLI((BSL_META_U(unit, 1429 "UDP packet dst port 0x%04x not handled\n"), udp_dest_port)); 1430 #endif 1431 return BCM_RX_NOT_HANDLED; 1432 } 1433 1434 return BCM_RX_HANDLED; 1435 } 1436 1437 1438 /* 1439 * Function: 1440 * _bcm_ptp_rx_message_destination_port_get 1441 * Purpose: 1442 * Get destination port number in UDP header. 1443 * Parameters: 1444 * message - (IN) PTP management message. 1445 * dest_port - (OUT) Destination port number. 1446 * Returns: 1447 * BCM_E_XXX 1448 * Notes: 1449 */ 1450 static int 1451 _bcm_ptp_rx_message_destination_port_get( 1452 uint8 *message, 1453 uint16 *dest_port) 1454 { 1455 int i = PTP_UDPHDR_START_IDX + PTP_UDPHDR_DESTPORT_OFFSET_OCTETS; 1456 1457 *dest_port = _bcm_ptp_uint16_read(message + i); 1458 return BCM_E_NONE; 1459 } 1460 1461 1462 /* 1463 * Function: 1464 * _bcm_ptp_rx_message_source_clock_identity_get 1465 * Purpose: 1466 * Get PTP source clock identity in PTP common header. 1467 * Parameters: 1468 * message - (IN) PTP management message. 1469 * clock_identity - (OUT) PTP source clock identity. 1470 * Returns: 1471 * BCM_E_XXX 1472 * Notes: 1473 */ 1474 static int 1475 _bcm_ptp_rx_message_source_clock_identity_get( 1476 uint8 *message, 1477 bcm_ptp_clock_identity_t *clock_identity) 1478 { 1479 int i = PTP_PTPHDR_START_IDX + PTP_PTPHDR_SRCPORT_OFFSET_OCTETS; 1480 1481 sal_memcpy(clock_identity, message + i, sizeof(bcm_ptp_clock_identity_t)); 1482 return BCM_E_NONE; 1483 } 1484 1485 /* 1486 * Function: 1487 * _bcm_ptp_rx_message_length_get 1488 * Purpose: 1489 * Get the length of a message. 1490 * Parameters: 1491 * message - (IN) PTP management message. 1492 * message_len - (OUT) Message length (octets). 1493 * Returns: 1494 * BCM_E_XXX. 1495 * Notes: 1496 * Message length is size of Rx packet excluding headers. 1497 */ 1498 static int 1499 _bcm_ptp_rx_message_length_get( 1500 uint8 *message, 1501 uint16 *message_len) 1502 { 1503 int i = PTP_UDPHDR_START_IDX + PTP_UDPHDR_MSGLEN_OFFSET_OCTETS; 1504 1505 *message_len = _bcm_ptp_uint16_read(message + i) - PTP_UDPHDR_SIZE_OCTETS; 1506 return BCM_E_NONE; 1507 } 1508 1509 #endif /* defined(BCM_PTP_EXTERNAL_STACK_SUPPORT) */ 1510 1511 /* 1512 * Function: 1513 * _bcm_ptp_register_management_callback 1514 * Purpose: 1515 * Register a management callback function 1516 * Parameters: 1517 * unit - (IN) Unit number. 1518 * cb - (IN) A pointer to the callback function to call for the specified PTP events 1519 * user_data - (IN) Pointer to user data to supply in the callback 1520 * Returns: 1521 * BCM_E_XXX. 1522 * Notes: 1523 * The unit is already locked by the calling function 1524 */ 1525 int 1526 _bcm_ptp_register_management_callback( 1527 int unit, 1528 bcm_ptp_cb cb, 1529 void *user_data) 1530 { 1531 int rv = BCM_E_UNAVAIL; 1532 1533 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT, 1534 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1535 return rv; 1536 } 1537 1538 unit_rx_array[unit].management_cb = cb; 1539 unit_rx_array[unit].management_user_data = user_data; 1540 1541 return rv; 1542 } 1543 1544 /* 1545 * Function: 1546 * _bcm_ptp_register_event_callback 1547 * Purpose: 1548 * Register a event callback function 1549 * Parameters: 1550 * unit - (IN) Unit number. 1551 * cb - (IN) A pointer to the callback function to call for the specified PTP events 1552 * user_data - (IN) Pointer to user data to supply in the callback 1553 * Returns: 1554 * BCM_E_XXX. 1555 * Notes: 1556 * The unit is already locked by the calling function 1557 */ 1558 int 1559 _bcm_ptp_register_event_callback( 1560 int unit, 1561 bcm_ptp_cb cb, 1562 void *user_data) 1563 { 1564 int rv = BCM_E_UNAVAIL; 1565 1566 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT, 1567 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1568 return rv; 1569 } 1570 1571 unit_rx_array[unit].event_cb = cb; 1572 unit_rx_array[unit].event_user_data = user_data; 1573 1574 return rv; 1575 } 1576 1577 /* 1578 * Function: 1579 * _bcm_ptp_register_signal_callback 1580 * Purpose: 1581 * Register a signal callback function 1582 * Parameters: 1583 * unit - (IN) Unit number. 1584 * cb - (IN) A pointer to the callback function to call for the specified PTP events 1585 * user_data - (IN) Pointer to user data to supply in the callback 1586 * Returns: 1587 * BCM_E_XXX. 1588 * Notes: 1589 * The unit is already locked by the calling function 1590 */ 1591 int 1592 _bcm_ptp_register_signal_callback( 1593 int unit, 1594 bcm_ptp_cb cb, 1595 void *user_data) 1596 { 1597 int rv = BCM_E_UNAVAIL; 1598 1599 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT, 1600 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1601 return rv; 1602 } 1603 1604 unit_rx_array[unit].signal_cb = cb; 1605 unit_rx_array[unit].signal_user_data = user_data; 1606 1607 return rv; 1608 } 1609 1610 /* 1611 * Function: 1612 * _bcm_ptp_register_peers_callback 1613 * Purpose: 1614 * Register callback function to periodically get the peer counters 1615 * Parameters: 1616 * unit - (IN) Unit number. 1617 * cb - (IN) A pointer to the callback function to call for the specified PTP events 1618 * user_data - (IN) Pointer to user data to supply in the callback 1619 * Returns: 1620 * BCM_E_XXX. 1621 * Notes: 1622 * The unit is already locked by the calling function 1623 */ 1624 int 1625 _bcm_ptp_register_peers_callback( 1626 int unit, 1627 bcm_ptp_cb cb, 1628 void *user_data) 1629 { 1630 int rv = BCM_E_UNAVAIL; 1631 1632 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT, 1633 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1634 return rv; 1635 } 1636 1637 unit_rx_array[unit].peers_cb = cb; 1638 unit_rx_array[unit].peers_user_data = user_data; 1639 1640 return rv; 1641 } 1642 1643 /* 1644 * Function: 1645 * _bcm_ptp_register_fault_callback 1646 * Purpose: 1647 * Register a fault callback function 1648 * Parameters: 1649 * unit - (IN) Unit number. 1650 * cb - (IN) A pointer to the callback function to call for the specified PTP events 1651 * user_data - (IN) Pointer to user data to supply in the callback 1652 * Returns: 1653 * BCM_E_XXX. 1654 * Notes: 1655 * The unit is already locked by the calling function 1656 */ 1657 int 1658 _bcm_ptp_register_fault_callback( 1659 int unit, 1660 bcm_ptp_cb cb, 1661 void *user_data) 1662 { 1663 int rv = BCM_E_UNAVAIL; 1664 1665 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT, 1666 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1667 return rv; 1668 } 1669 1670 unit_rx_array[unit].fault_cb = cb; 1671 unit_rx_array[unit].fault_user_data = user_data; 1672 1673 return rv; 1674 } 1675 1676 /* 1677 * Function: 1678 * _bcm_ptp_unregister_management_callback 1679 * Purpose: 1680 * Unregister a management callback function 1681 * Parameters: 1682 * unit - (IN) Unit number. 1683 * Returns: 1684 * BCM_E_XXX. 1685 * Notes: 1686 * The unit is already locked by the calling function 1687 */ 1688 int 1689 _bcm_ptp_unregister_management_callback( 1690 int unit) 1691 { 1692 int rv = BCM_E_UNAVAIL; 1693 1694 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT, 1695 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1696 return rv; 1697 } 1698 1699 unit_rx_array[unit].management_cb = NULL; 1700 unit_rx_array[unit].management_user_data = NULL; 1701 1702 return rv; 1703 } 1704 1705 /* 1706 * Function: 1707 * _bcm_ptp_unregister_event_callback 1708 * Purpose: 1709 * Unregister a event callback function 1710 * Parameters: 1711 * unit - (IN) Unit number. 1712 * Returns: 1713 * BCM_E_XXX. 1714 * Notes: 1715 * The unit is already locked by the calling function 1716 */ 1717 int 1718 _bcm_ptp_unregister_event_callback( 1719 int unit) 1720 { 1721 int rv = BCM_E_UNAVAIL; 1722 1723 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT, 1724 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1725 return rv; 1726 } 1727 1728 unit_rx_array[unit].event_cb = NULL; 1729 unit_rx_array[unit].event_user_data = NULL; 1730 1731 return rv; 1732 } 1733 1734 /* 1735 * Function: 1736 * _bcm_ptp_unregister_signal_callback 1737 * Purpose: 1738 * Unregister a signal callback function 1739 * Parameters: 1740 * unit - (IN) Unit number. 1741 * Returns: 1742 * BCM_E_XXX. 1743 * Notes: 1744 * The unit is already locked by the calling function 1745 */ 1746 int 1747 _bcm_ptp_unregister_signal_callback( 1748 int unit) 1749 { 1750 int rv = BCM_E_UNAVAIL; 1751 1752 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT, 1753 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1754 return rv; 1755 } 1756 1757 unit_rx_array[unit].signal_cb = NULL; 1758 unit_rx_array[unit].signal_user_data = NULL; 1759 1760 return rv; 1761 } 1762 1763 /* 1764 * Function: 1765 * _bcm_ptp_unregister_peers_callback 1766 * Purpose: 1767 * Unregister a check peers callback function 1768 * Parameters: 1769 * unit - (IN) Unit number. 1770 * Returns: 1771 * BCM_E_XXX. 1772 * Notes: 1773 * The unit is already locked by the calling function 1774 */ 1775 int 1776 _bcm_ptp_unregister_peers_callback( 1777 int unit) 1778 { 1779 int rv = BCM_E_UNAVAIL; 1780 1781 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT, 1782 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1783 return rv; 1784 } 1785 1786 unit_rx_array[unit].peers_cb = NULL; 1787 unit_rx_array[unit].peers_user_data = NULL; 1788 1789 return rv; 1790 } 1791 1792 1793 /* 1794 * Function: 1795 * _bcm_ptp_unregister_fault_callback 1796 * Purpose: 1797 * Unregister a fault callback function 1798 * Parameters: 1799 * unit - (IN) Unit number. 1800 * Returns: 1801 * BCM_E_XXX. 1802 * Notes: 1803 * The unit is already locked by the calling function 1804 */ 1805 int 1806 _bcm_ptp_unregister_fault_callback( 1807 int unit) 1808 { 1809 int rv = BCM_E_UNAVAIL; 1810 1811 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT, 1812 PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1813 return rv; 1814 } 1815 1816 unit_rx_array[unit].fault_cb = NULL; 1817 unit_rx_array[unit].fault_user_data = NULL; 1818 1819 return rv; 1820 } 1821 1822 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT) || defined(BCM_PTP_EXTERNAL_STACK_SUPPORT) 1823 /* 1824 * Function: 1825 * _bcm_ptp_event_message_monitor 1826 * Purpose: 1827 * Monitor incoming event messages and perform basic operations req'd 1828 * for maintenance of host caches. 1829 * Parameters: 1830 * unit - (IN) Unit number. 1831 * ptp_id - (IN) PTP stack ID. 1832 * ev_data_len - (IN) Event message data length (octets). 1833 * ev_data - (IN) Event message data. 1834 * ev_internal - (OUT) Internal-only event. Do not pass to event callbacks. 1835 * Returns: 1836 * BCM_E_XXX - Function status. 1837 * Notes: 1838 */ 1839 STATIC int 1840 _bcm_ptp_event_message_monitor( 1841 int unit, 1842 bcm_ptp_stack_id_t ptp_id, 1843 int ev_data_len, 1844 uint8 *ev_data, 1845 int *ev_internal) 1846 { 1847 int rv; 1848 1849 uint8 event_clock_num; 1850 uint16 event_port_num; 1851 _bcm_ptp_event_t event_code; 1852 _bcm_ptp_port_state_t portState; 1853 #ifdef BCM_ESMC_EXTDPLL_SUPPORT 1854 int event_input_clock_num; 1855 #endif 1856 1857 int cursor = 0; 1858 1859 event_code = (_bcm_ptp_event_t)_bcm_ptp_uint16_read(ev_data + cursor); 1860 cursor += sizeof(uint16); 1861 1862 if (event_code == _bcm_ptp_state_change_event) { 1863 /* EVENT MONITOR: portState change. */ 1864 *ev_internal = 0; 1865 1866 /* Extract clock number and port number of event. */ 1867 event_clock_num = ev_data[cursor++]; 1868 event_port_num = _bcm_ptp_uint16_read(ev_data + cursor); 1869 cursor += sizeof(uint16); 1870 1871 /* Advance cursor and extract portState of event. */ 1872 cursor += BCM_PTP_CLOCK_EUID_IEEE1588_SIZE + 2; 1873 portState = (_bcm_ptp_port_state_t)ev_data[cursor]; 1874 1875 if (BCM_FAILURE(rv = _bcm_ptp_clock_cache_port_state_set(unit, ptp_id, 1876 event_clock_num, event_port_num, portState))) { 1877 return rv; 1878 } 1879 } else if (event_code == _bcm_ptp_tdev_event) { 1880 /* EVENT MONITOR: TDEV data analysis. */ 1881 *ev_internal = 1; 1882 1883 if (BCM_FAILURE(rv = _bcm_ptp_ctdev_gateway(unit, ptp_id, PTP_CLOCK_NUMBER_DEFAULT, 1884 ev_data_len, ev_data))) { 1885 return rv; 1886 } 1887 #if defined(BCM_PTP_EXTERNAL_STACK_SUPPORT) 1888 } else if (event_code == _bcm_ptp_top_ready_event) { 1889 _bcm_ptp_ext_fw_info_set(unit, ptp_id, ev_data + 2); 1890 #endif 1891 #ifdef BCM_ESMC_EXTDPLL_SUPPORT 1892 } else if (event_code == _bcm_ptp_synce_loss_event) { 1893 *ev_internal = 1; 1894 event_input_clock_num = _bcm_ptp_uint16_read(ev_data + cursor); 1895 bcm_extdpll_esmc_synce_event_handler(unit, ptp_id, event_input_clock_num); 1896 #endif /* BCM_ESMC_EXTDPLL_SUPPORT */ 1897 } 1898 1899 return BCM_E_NONE; 1900 } 1901 #endif 1902 1903 /* 1904 * Function: 1905 * _bcm_ptp_signal_handler_default 1906 * Purpose: 1907 * Default forwarded (tunneled) PTP signaling message callback handler. 1908 * Parameters: 1909 * unit - (IN) Unit number. 1910 * stack_id - (IN) PTP stack ID. 1911 * clock_num - (IN) PTP clock number. 1912 * clock_port - (IN) PTP port number. 1913 * type - (IN) Callback function type. 1914 * msg - (IN) Callback message data. 1915 * user_data - (IN) Callback user data. 1916 * Returns: 1917 * BCM_E_XXX (if failure) 1918 * bcmPTPCallbackAccept (if success) 1919 * Notes: 1920 */ 1921 STATIC int 1922 _bcm_ptp_signal_handler_default( 1923 int unit, 1924 bcm_ptp_stack_id_t ptp_id, 1925 int clock_num, 1926 uint32 clock_port, 1927 bcm_ptp_cb_type_t type, 1928 bcm_ptp_cb_msg_t *msg, 1929 void *user_data) 1930 { 1931 int rv = BCM_E_UNAVAIL; 1932 1933 int port_num = _bcm_ptp_most_recent_port; 1934 bcm_ptp_protocol_t protocol = _bcm_ptp_most_recent_protocol; 1935 int src_addr_offset = _bcm_ptp_most_recent_src_addr_offset; 1936 int msg_offset = _bcm_ptp_most_recent_msg_offset; 1937 1938 if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, 1939 clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT))) { 1940 PTP_ERROR_FUNC("_bcm_ptp_function_precheck()"); 1941 return rv; 1942 } 1943 1944 #ifdef PTP_RX_CALLBACK_DEBUG 1945 LOG_CLI((BSL_META_U(unit, 1946 "Signaling callback (Unit = %d, PTP Stack = %d)\n"), 1947 unit, ptp_id)); 1948 _bcm_ptp_dump_hex(msg->data, msg->length,0); 1949 #endif 1950 1951 return _bcm_ptp_process_incoming_signaling_msg(unit, ptp_id, clock_num, port_num, protocol, src_addr_offset, 1952 msg_offset, msg->length, msg->data); 1953 } 1954 1955 #endif /* defined(INCLUDE_PTP) */