openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

management.c (118921B)


      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:    management.c
      8  *
      9  * Purpose: 
     10  *
     11  * Functions:
     12  *      _bcm_ptp_management_init
     13  *      _bcm_ptp_management_detach
     14  *      _bcm_ptp_management_stack_create
     15  *      _bcm_ptp_external_transport_init
     16  *      _bcm_ptp_external_transport_terminate
     17  *      _bcm_ptp_internal_transport_init
     18  *      _bcm_ptp_internal_transport_terminate
     19  *      _bcm_ptp_management_clock_create
     20  *      _bcm_ptp_management_message_send
     21  *      _bcm_ptp_tunnel_message_to_top
     22  *      _bcm_ptp_tunnel_message_to_world
     23  *      _bcm_ptp_external_tx
     24  *      _bcm_ptp_external_tx_completion
     25  *      _bcm_ptp_internal_tx
     26  *      _bcm_ptp_internal_tx_completion
     27  *      _bcm_ptp_unicast_slave_subscribe
     28  *      _bcm_ptp_management_domain_get
     29  *      _bcm_ptp_management_domain_set
     30  *      _bcm_ptp_management_message_create
     31  *      _bcm_ptp_management_message_macaddr_set
     32  *      _bcm_ptp_management_message_vlantag_set
     33  *      _bcm_ptp_management_message_ipaddr_set
     34  *      _bcm_ptp_management_message_ipv4hdr_checksum_set
     35  *      _bcm_ptp_management_message_port_set
     36  *      _bcm_ptp_management_message_domain_set
     37  *      _bcm_ptp_management_rfc791_checksum
     38  *      _bcm_ptp_rfc791_checksum_add_word
     39  *      _bcm_ptp_construct_udp_packet
     40  *      _bcm_ptp_construct_signaling_msg
     41  *      _bcm_ptp_construct_signaling_request_tlv
     42  *      _bcm_ptp_construct_signaling_cancel_tlv
     43  *      _bcm_ptp_construct_signaling_grant_tlv
     44  *      _bcm_ptp_construct_signaling_ack_cancel_tlv
     45  *      _bcm_ptp_signaling_message_append_tlv
     46  */
     47 
     48 #if defined(INCLUDE_PTP)
     49 
     50 #ifdef BCM_HIDE_DISPATCHABLE
     51 #undef BCM_HIDE_DISPATCHABLE
     52 #endif
     53 
     54 #include <shared/bsl.h>
     55 
     56 #include <soc/defs.h>
     57 #include <soc/drv.h>
     58 #include <shared/bsl.h>
     59 #include <bcm/pkt.h>
     60 #include <bcm/tx.h>
     61 #include <bcm/rx.h>
     62 
     63 #include <bcm/ptp.h>
     64 #include <bcm_int/common/ptp.h>
     65 #include <bcm_int/ptp_common.h>
     66 #include <bcm/error.h>
     67 
     68 #include <bcm_int/common/rx.h>
     69 #include <bcm_int/common/tx.h>
     70 
     71 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT)
     72 #include <soc/uc_msg.h>
     73 #endif
     74 
     75 /* Parameters and constants. */
     76 #define PTP_MGMT_RESPONSE_TIMEOUT_US         (10000000)  /* 1 sec */
     77 #define PTP_TUNNEL_MESSAGE_TIMEOUT_US        (100000)    /* 100 msec */
     78 #define PTP_TIMESTAMP_MESSAGE_TIMEOUT_US        (100000)    /* 100 msec */
     79 
     80 #define PTP_MGMT_RESP_ACTION_OFFSET          (46)
     81 #define PTP_MGMT_RESP_TLV_TYPE_OFFSET        (48)
     82 #define PTP_MGMT_RESP_TLV_LEN_OFFSET         (50)
     83 #define PTP_MGMT_RESP_TLV_VAL_OFFSET         (52)
     84 #define PTP_MGMT_RESP_PAYLOAD_OFFSET         (54)
     85 
     86 #define CLOCK_DATA(unit, ptp_id, clock_num) (unit_mgmt_array[unit].stack_array[ptp_id].clock_data[clock_num])
     87 #define STACK_DATA(unit, ptp_id)            (unit_mgmt_array[unit].stack_array[ptp_id])
     88 #define UNIT_DATA(unit)                     (unit_mgmt_array[unit])
     89 
     90 static const uint8 l2hdr_default[] =
     91 {
     92     /* Destination MAC address (zeros placeholder). */
     93     0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     94     /* Source MAC address (zeros placeholder). */
     95     0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     96 };
     97 
     98 static const uint8 vlanhdr_default[] =
     99 {
    100     /* Tag protocol identifier (TPID). */
    101     0x81, 0x00,
    102     /*
    103      * Priority code point (PCP),
    104      * canonical form indicator (CFI),
    105      * VLAN identifier (VID) .
    106      */
    107     0xe0, 0x00,
    108 };
    109 
    110 static const uint8 ethhdr_default[] =
    111 {
    112     /* Ethertype (0x0800 = IPv4, 0x86dd = IPv6). */
    113     0x08, 0x00,
    114 };
    115 
    116 static const uint8 ipv4hdr_default[] =
    117 {
    118     /* Version (IPv4), header length. */
    119     0x45,
    120     /*
    121      * Differential service code point (DSCP),
    122      * Explicit congestion notification (ECN).
    123      */
    124     0x00,
    125     /*
    126      * Total length (octets).
    127      * NOTICE: Placeholder value.
    128      */
    129     0x00, 0x52,
    130     /* Identification. */
    131     0x00, 0x00,
    132     /* Flags (Do not fragment), Fragment offset. */
    133     0x40, 0x00,
    134     /* Time to live (TTL). */
    135     0x01,
    136     /* Protocol (UDP). */
    137     0x11,
    138     /* Header checksum (zeros placeholder). */
    139     0x00, 0x00,
    140     /* Source IPv4 address (zeros placeholder). */
    141     0x00, 0x00, 0x00, 0x00,
    142     /* Destination IPv4 address (zeros placeholder). */
    143     0x00, 0x00, 0x00, 0x00,
    144 };
    145 
    146 static const uint8 udphdr_default[] =
    147 {
    148     /* Source port. */
    149     0x01, 0x40,
    150     /* Destination port. */
    151     0x01, 0x40,
    152     /*
    153      * Length (octets).
    154      * NOTICE: Placeholder value.
    155      */
    156     0x00, 0x00,
    157     /*
    158      * Checksum (optional).
    159      * NOTICE: 0x0000 indicates checksum skipped.
    160      */
    161     0x00, 0x00,
    162 };
    163 
    164 static const uint8 udphdr_tunnel[] =
    165 {
    166     /* Source port. */
    167     0x01, 0x41,
    168     /* Destination port. */
    169     0x01, 0x41,
    170     /* Length (zeros placeholder). */
    171     0x00, 0x00,
    172     /* Checksum (optional). */
    173     0x00, 0x00,
    174 };
    175 
    176 
    177 static const uint8 ptphdr_mgmt[] =
    178 {
    179     /* Message ID (management message) */
    180     bcmPTP_MESSAGE_TYPE_MANAGEMENT,
    181     /* PTP version. */
    182     0x02,
    183     /* PTP message length, TLV "V" part only */
    184     0x00, 0x00,
    185     /* PTP domain (zero default) */
    186     0x00,
    187     /* Reserved */
    188     0x00,
    189     /* PTP flags  (Unicast = true) */
    190     0x04, 0x00,
    191     /* Correction field */
    192     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    193     /* Reserved */
    194     0x00, 0x00, 0x00, 0x00,
    195     /* Source Clock ID  */
    196     0x00, 0x10, 0x94, 0xff, 0xfe, 0x00, 0x00, 0x04,
    197     /* Source Port Number */
    198     0x00, 0x01,
    199     /* Sequence ID */
    200     0x00, 0x01,
    201     /* Control field (management) */
    202     0x04,
    203     /* Log inter-message interval */
    204     0x7f,
    205 };
    206 
    207 
    208 static const uint8 mgmthdr_mgmt[]=
    209 {
    210     /* Target clock ID. */
    211     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    212     /* Target port ID. */
    213     0xff, 0xff,
    214     /* Starting boundary hops. */
    215     0x01,
    216     /* Boundary hops. */
    217     0x01,
    218     /* Action field. */
    219     0x00,
    220     /* Reserved. */
    221     0x00,
    222 };
    223 
    224 
    225 static const uint8 tlvhdr_mgmt[]=
    226 {
    227     /* TLV type (0x0001 = Management message). */
    228     0x00, 0x01,
    229     /* TLV length (octets) (0x0002 = TLV prefix, no payload placeholder) */
    230     0x00, 0x02,
    231      /* TLV value prefix (management ID, i.e. command definition) */
    232     0x00, 0x00,
    233 };
    234 
    235 static const uint8 ptphdr_ucsig[] =
    236 {
    237     /*
    238      * Message ID (signaling message).
    239      * Ref. IEEE Std. 1588-2008, Sect. 13.3.2.2.
    240      */
    241     bcmPTP_MESSAGE_TYPE_SIGNALING,
    242     /* PTP version. */
    243     0x02,
    244     /*
    245      * PTP message length, TLV "V" part only.
    246      * NOTICE: Placeholder based on REQUEST_UNICAST_TRANSMISSION TLV.
    247      */
    248     0x00, (PTP_UCSIG_REQUEST_TOTAL_SIZE_OCTETS - PTP_SIGHDR_START_IDX),
    249     /* PTP domain (zero default). */
    250     0x00, 0x00,
    251     /* PTP flags  (Unicast= true). */
    252     0x04, 0x00,
    253     /*
    254      * Correction field.
    255      * Ref. IEEE Std. 1588-2008, Chapter 13.3.2.7.
    256      */
    257     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    258     /* Reserved. */
    259     0x00, 0x00, 0x00, 0x00,
    260     /* Source port ID. */
    261     0x00, 0x10, 0x94, 0xff, 0xfe, 0x00, 0x00, 0x0d,
    262     0x00, 0x01,
    263     /* Sequence ID. */
    264     0x00, 0x02,
    265     /*
    266      * Control field (all others).
    267      * Ref. IEEE Std. 1588-2008, Sect. 13.3.2.10.
    268      */
    269     0x05,
    270     /*
    271      * Log inter-message interval.
    272      * Ref. IEEE Std. 1588-2008, Sect. 13.3.2.11.
    273      */
    274     0x7f,
    275 };
    276 
    277 static const uint8 tgtport_ucsig[] =
    278 {
    279     /* Signaling message target clock identity. */
    280     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    281     /* Signaling message target port. */
    282     0xff, 0xff,
    283 };
    284 
    285 static const uint8 unicast_request_tlv_ucsig[] =
    286 {
    287     /*
    288      * TLV type. (0x0004 = REQUEST_UNICAST_TRANSMISSION placeholder).
    289      * Ref. IEEE Std. 1588-2008, Sect. 14.1.1.
    290      */
    291     0x00, 0x04,
    292     /*
    293      * TLV length (octets).
    294      * NOTICE: Placeholder based on REQUEST_UNICAST_TRANSMISSION TLV.
    295      */
    296     0x00, (PTP_UCSIG_REQUEST_TLV_SIZE_OCTETS - 4),
    297     /*
    298      * TLV value (data). Message type (0x0b = Announce message, placeholder).
    299      * Ref. IEEE Std. 1588-2008, Sect. 13.3.2.2.
    300      */
    301     bcmPTP_MESSAGE_TYPE_ANNOUNCE,
    302     /* Interval. */
    303     0x00,
    304     /* Duration. */
    305     0x00, 0x00, 0x00, 0x14,
    306     /* Address type. */
    307     bcmPTPUDPIPv4,
    308     /* Peer address. */
    309     0x01, 0x02, 0x03, 0x04,
    310     0x00, 0x00, 0x00, 0x00,
    311     0x00, 0x00, 0x00, 0x00,
    312     0x00, 0x00, 0x00, 0x00,
    313     /* L2 header length (zeros placeholder). */
    314     0x00,
    315     /* L2 header (zeros placeholder). */
    316     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    317     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    318     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    319     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    320 };
    321 
    322 #define BCM_GPS_NUM_TIMESTAMPS_PER_BUFFER       110 /* Although only 100 timestamps are expected,
    323                                                      * max is set to 110 in order to account for
    324                                                      * extremely large frequency offsets*/
    325 
    326 uint64 gps_diff_ts[BCM_GPS_NUM_TIMESTAMPS_PER_BUFFER] = {0};
    327 bcm_ptp_port_identity_t g_gps_port_id = {{1,2,3,4,5,6,7,8},9};
    328 bcm_ptp_clock_port_address_t g_gps_port_address = {bcmPTPIEEE8023,{0xFE}};
    329 bcm_ptp_port_identity_t g_ptp_best_master_portId = {{0,0,0,0,0,0,0,0},0};
    330 
    331 /* Clock PTP management data. */
    332 typedef struct _bcm_ptp_clock_mgmt_data_s {
    333     uint8 domain; /* PTP domain. */
    334 } _bcm_ptp_clock_mgmt_data_t;
    335 
    336 /* Stack PTP management data array. */
    337 typedef struct _bcm_ptp_stack_mgmt_array_s {
    338     _bcm_ptp_memstate_t memstate;
    339 
    340     bcm_mac_t src_mac;
    341     bcm_mac_t dest_mac;
    342 
    343     bcm_ip_t src_ip;
    344     bcm_ip_t dest_ip;
    345 
    346     uint16 vlan;
    347     uint8 prio;
    348 
    349     _bcm_ptp_sem_t outgoing_available;  /* any outgoing message (management, signaling, tunneled) to TOP */
    350 
    351     bcm_pkt_t *mgmt_packet;
    352     bcm_pkt_t *tunnel_packet;
    353     bcm_pkt_t *ucsig_packet;
    354 
    355     _bcm_ptp_clock_mgmt_data_t *clock_data;
    356 } _bcm_ptp_stack_mgmt_array_t;
    357 
    358 /* Unit PTP management data array(s). */
    359 typedef struct _bcm_ptp_unit_mgmt_array_s {
    360     _bcm_ptp_memstate_t memstate;
    361     _bcm_ptp_stack_mgmt_array_t *stack_array;
    362 } _bcm_ptp_unit_mgmt_array_t;
    363 
    364 static const _bcm_ptp_clock_mgmt_data_t mgmt_default = { 0 };
    365 
    366 static _bcm_ptp_unit_mgmt_array_t unit_mgmt_array[BCM_MAX_NUM_UNITS];
    367 
    368 static int _bcm_ptp_management_message_create(
    369     uint8 *message);
    370 
    371 /* static int _bcm_ptp_management_message_make( */
    372 /*     uint8 *message,  */
    373 /*     uint8 action,  */
    374 /*     uint16 cmd,  */
    375 /*     uint8 *payload,  */
    376 /*     int payload_len); */
    377 
    378 /* static int _bcm_ptp_management_message_header_metadata_set( */
    379 /*     uint8 *message); */
    380 
    381 static int _bcm_ptp_management_message_macaddr_set(
    382     uint8 *message,
    383     bcm_mac_t *src_mac,
    384     bcm_mac_t *dest_mac);
    385 
    386 static int _bcm_ptp_management_message_vlantag_set(
    387     uint8 *message,
    388     uint16 vlan_tag,
    389     uint8 prio);
    390 
    391 static int _bcm_ptp_management_message_ipaddr_set(
    392     uint8 *message,
    393     bcm_ip_t src_ip,
    394     bcm_ip_t dest_ip);
    395 
    396 static int _bcm_ptp_management_message_ipv4hdr_checksum_set(
    397     uint8 *message);
    398 
    399 static int _bcm_ptp_management_message_port_set(
    400     uint8 *message,
    401     uint16 src_port,
    402     uint16 dest_port);
    403 
    404 /* static int _bcm_ptp_management_message_target_set( */
    405 /*     uint8 *message,  */
    406 /*     const bcm_ptp_clock_identity_t clock_identity,  */
    407 /*     uint16 port_num); */
    408 
    409 /* static int _bcm_ptp_management_message_length_get( */
    410 /*     uint8 *message); */
    411 
    412 #if 0 /* Unused. */
    413 static int _bcm_ptp_management_message_domain_get(
    414     uint8 *message,
    415     uint8 *domain);
    416 #endif /* Unused. */
    417 
    418 static uint16 _bcm_ptp_management_rfc791_checksum(
    419     uint8* packet,
    420     int packet_len);
    421 
    422 static uint16 _bcm_ptp_rfc791_checksum_add_word(
    423     uint16 prev_checksum,
    424     uint16 add_word);
    425 
    426 static sal_usecs_t send_pending_tunneled(
    427     void **arg_unit,
    428     void **arg_ptp_id,
    429     void **unused1,
    430     void **unused2);
    431 
    432 static int _bcm_ptp_tunnel_queue_add(
    433     int unit,
    434     bcm_ptp_stack_id_t ptp_id,
    435     int clock_idx,
    436     int tunnel_type,
    437     unsigned hdr_len,
    438     uint8 *hdr,
    439     unsigned data_len,
    440     uint8 *data);
    441 
    442 static int _bcm_ptp_tunnel_message(
    443     int unit,
    444     bcm_ptp_stack_id_t ptp_id,
    445     int clock_index,
    446     int tunnel_type,
    447     unsigned hdr_len,
    448     uint8 *hdr,
    449     unsigned payload_len,
    450     uint8 *payload);
    451 
    452 static sal_usecs_t send_pending_timestamp(
    453     void **arg_unit,
    454     void **arg_ptp_id,
    455     void **unused1,
    456     void **unused2);
    457 
    458 #ifdef BCM_PTP_EXT_SERVO_SUPPORT
    459 bcm_ptp_mbox_tsevent_stats_t mbox_tsevent_stats;
    460 
    461 void _bcm_ptp_dump_mbox_tsevent_stats() {
    462     bsl_printf("\n\t Events Queued              : %u", mbox_tsevent_stats.event_queued);
    463     bsl_printf("\n\t Events DeQueued            : %u", mbox_tsevent_stats.event_dequeued);
    464     bsl_printf("\n\t Event DLTS dequeued        : %u", mbox_tsevent_stats.event_dl_ts);
    465     bsl_printf("\n\t Event DLTS handled         : %u", mbox_tsevent_stats.event_dl_ts_handled);
    466     bsl_printf("\n\t Event DLTS above threshold : %u", mbox_tsevent_stats.event_dl_ts_above_thres);
    467     bsl_printf("\n\t Event ULTS dequeued        : %u", mbox_tsevent_stats.event_ul_ts);
    468     bsl_printf("\n\t Event ULTS handled         : %u", mbox_tsevent_stats.event_ul_ts_handled);
    469     bsl_printf("\n\t Event ULTS above threshold : %u", mbox_tsevent_stats.event_ul_ts_above_thres);
    470     bsl_printf("\n\t Event Master Add           : %u", mbox_tsevent_stats.event_master_add);
    471     bsl_printf("\n\t Event Master Remove        : %u", mbox_tsevent_stats.event_master_remove);
    472     bsl_printf("\n\t Event Master Change        : %u", mbox_tsevent_stats.event_master_change);
    473     bsl_printf("\n\t Event Unknown              : %u", mbox_tsevent_stats.event_unknown);
    474     bsl_printf("\n\t Error QueueAdd             : %u", mbox_tsevent_stats.error_queue_add);
    475     bsl_printf("\n\t TS RPC livecount           : %u\n", mbox_tsevent_stats.ts_rpc_livecount);
    476 }
    477 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */
    478 
    479 /*
    480  * Function:
    481  *      _bcm_ptp_management_init
    482  * Purpose:
    483  *      Initialize the PTP management framework of a unit.
    484  * Parameters:
    485  *      unit - (IN) Unit number.
    486  * Returns:
    487  *      BCM_E_XXX
    488  * Notes:
    489  */
    490 int
    491 _bcm_ptp_management_init(
    492     int unit)
    493 {
    494     int rv = BCM_E_UNAVAIL;
    495 
    496     _bcm_ptp_stack_mgmt_array_t *stack_p;
    497 
    498     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, PTP_STACK_ID_DEFAULT,
    499             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    500         return rv;
    501     }
    502 
    503     
    504     if (NULL == unit_mgmt_array[unit].stack_array) {
    505         stack_p = sal_alloc(PTP_MAX_STACKS_PER_UNIT*
    506                             sizeof(_bcm_ptp_stack_mgmt_array_t),"Unit MGMT arrays");
    507     } else {
    508         stack_p = unit_mgmt_array[unit].stack_array;
    509     }
    510     
    511     if (!stack_p) {
    512         unit_mgmt_array[unit].memstate = PTP_MEMSTATE_FAILURE;
    513         return BCM_E_MEMORY;
    514     }
    515 
    516     unit_mgmt_array[unit].stack_array = stack_p;
    517     unit_mgmt_array[unit].memstate = PTP_MEMSTATE_INITIALIZED;
    518 
    519     return rv;
    520 }
    521 
    522 /*
    523  * Function:
    524  *      _bcm_ptp_management_detach
    525  * Purpose:
    526  *      Shut down the PTP management framework of a unit.
    527  * Parameters:
    528  *      unit - (IN) Unit number.
    529  * Returns:
    530  *      BCM_E_XXX
    531  * Notes:
    532  */
    533 int
    534 _bcm_ptp_management_detach(
    535     int unit)
    536 {
    537     if(unit_mgmt_array[unit].stack_array) {
    538         unit_mgmt_array[unit].memstate = PTP_MEMSTATE_STARTUP;
    539         sal_free(unit_mgmt_array[unit].stack_array);
    540         unit_mgmt_array[unit].stack_array = NULL;
    541     }
    542     return BCM_E_NONE;
    543 }
    544 
    545 /*
    546  * Function:
    547  *      _bcm_ptp_management_stack_create
    548  * Purpose:
    549  *      Create the PTP management data array of a PTP stack
    550  * Parameters:
    551  *      unit       - (IN) Unit number.
    552  *      ptp_id     - (IN) PTP stack ID.
    553  *      src_mac    - (IN) Source MAC address.
    554  *      dest_mac   - (IN) Destination (PTP stack) MAC address.
    555  *      src_ip     - (IN) Source IPv4 address.
    556  *      dest_ip    - (IN) Destination (PTP stack) IPv4 address.
    557  *      vlan       - (IN) VLAN.
    558  *      prio       - (IN) VLAN priority.
    559  *      top_bitmap - (IN) ToP bitmap.
    560  * Returns:
    561  *      BCM_E_XXX
    562  * Notes:
    563  */
    564 int
    565 _bcm_ptp_management_stack_create(
    566     int unit,
    567     bcm_ptp_stack_id_t ptp_id,
    568     bcm_mac_t *src_mac,
    569     bcm_mac_t *dest_mac,
    570     bcm_ip_t src_ip,
    571     bcm_ip_t dest_ip,
    572     uint16 vlan,
    573     uint8 prio,
    574     bcm_pbmp_t top_bitmap)
    575 {
    576     int rv = BCM_E_UNAVAIL;
    577     _bcm_ptp_info_t *ptp_info_p;
    578     _bcm_ptp_stack_info_t *stack_p;
    579 
    580     _bcm_ptp_clock_mgmt_data_t *data_p;
    581 
    582     SET_PTP_INFO;
    583 
    584     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
    585             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    586         return rv;
    587     }
    588 
    589     if (unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) {
    590         return BCM_E_UNAVAIL;
    591     }
    592 
    593     stack_p = &ptp_info_p->stack_info[ptp_id];
    594 
    595     
    596     data_p = sal_alloc(PTP_MAX_CLOCK_INSTANCES * sizeof(_bcm_ptp_clock_mgmt_data_t), "PTP stack MGMT array");
    597 
    598     if (!data_p) {
    599         STACK_DATA(unit, ptp_id).memstate = PTP_MEMSTATE_FAILURE;
    600         return BCM_E_MEMORY;
    601     }
    602 
    603     STACK_DATA(unit, ptp_id).clock_data = data_p;
    604     STACK_DATA(unit, ptp_id).memstate = PTP_MEMSTATE_INITIALIZED;
    605 
    606     STACK_DATA(unit, ptp_id).outgoing_available = _bcm_ptp_sem_create("BCM PTP out", sal_sem_BINARY, 0);
    607     rv = _bcm_ptp_sem_give(STACK_DATA(unit, ptp_id).outgoing_available);
    608     if (BCM_FAILURE(rv)) {
    609         PTP_ERROR_FUNC("_bcm_ptp_sem_give()");
    610         return rv;
    611     }
    612 
    613     rv = stack_p->transport_init(unit, ptp_id, src_mac, dest_mac, src_ip, dest_ip, vlan, prio, top_bitmap);
    614 
    615     return rv;
    616 }
    617 
    618 /*
    619  * Function:
    620  *      _bcm_ptp_management_stack_destroy
    621  * Purpose:
    622  *      Destroy the PTP management data array of a PTP stack
    623  * Parameters:
    624  *      unit       - (IN) Unit number.
    625  *      ptp_id     - (IN) PTP stack ID.
    626  *      src_mac    - (IN) Source MAC address.
    627  *      dest_mac   - (IN) Destination (PTP stack) MAC address.
    628  *      src_ip     - (IN) Source IPv4 address.
    629  *      dest_ip    - (IN) Destination (PTP stack) IPv4 address.
    630  *      vlan       - (IN) VLAN.
    631  *      prio       - (IN) VLAN priority.
    632  *      top_bitmap - (IN) ToP bitmap.
    633  * Returns:
    634  *      BCM_E_XXX
    635  * Notes:
    636  */
    637 int
    638 _bcm_ptp_management_stack_destroy(
    639     int unit,
    640     bcm_ptp_stack_id_t ptp_id)
    641 {
    642     int rv = BCM_E_UNAVAIL;
    643     int retry_cnt = 0;
    644     _bcm_ptp_info_t *ptp_info_p;
    645     _bcm_ptp_stack_info_t *stack_p;
    646 
    647     SET_PTP_INFO;
    648 
    649     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
    650             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
    651         return rv;
    652     }
    653 
    654     if (unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) {
    655         return BCM_E_UNAVAIL;
    656     }
    657 
    658     stack_p = &ptp_info_p->stack_info[ptp_id];
    659 
    660     if (STACK_DATA(unit, ptp_id).memstate == PTP_MEMSTATE_INITIALIZED) {
    661         STACK_DATA(unit, ptp_id).memstate = PTP_MEMSTATE_STARTUP;
    662 
    663         while (retry_cnt++ < 5) {
    664             if (BCM_FAILURE(rv = _bcm_ptp_sem_take(
    665                     STACK_DATA(unit, ptp_id).outgoing_available, 
    666                     PTP_MGMT_RESPONSE_TIMEOUT_US))) {
    667                 PTP_ERROR_FUNC("_bcm_ptp_sem_take() in stack destroy");
    668             } else {
    669                 break;
    670             }
    671         }
    672 
    673         rv = stack_p->transport_terminate(unit, ptp_id);
    674 
    675         _bcm_ptp_sem_destroy(STACK_DATA(unit, ptp_id).outgoing_available);
    676         STACK_DATA(unit, ptp_id).outgoing_available = 0;
    677 
    678         sal_free(STACK_DATA(unit, ptp_id).clock_data);
    679         STACK_DATA(unit, ptp_id).clock_data = 0;
    680     }
    681 
    682     return rv;
    683 }
    684 
    685 /*
    686  * Function:
    687  *      _bcm_ptp_external_transport_init
    688  * Purpose:
    689  *      Initialize message transport to an external ToP
    690  * Parameters:
    691  *      unit       - (IN) Unit number.
    692  *      ptp_id     - (IN) PTP stack ID.
    693  *      src_mac    - (IN) Source MAC address.
    694  *      dest_mac   - (IN) Destination (PTP stack) MAC address.
    695  *      src_ip     - (IN) Source IPv4 address.
    696  *      dest_ip    - (IN) Destination (PTP stack) IPv4 address.
    697  *      vlan       - (IN) VLAN.
    698  *      prio       - (IN) VLAN priority.
    699  *      top_bitmap - (IN) ToP bitmap.
    700  * Returns:
    701  *      BCM_E_XXX
    702  * Notes:
    703  */
    704 int _bcm_ptp_external_transport_init(
    705     int unit,
    706     bcm_ptp_stack_id_t ptp_id,
    707     bcm_mac_t *src_mac,
    708     bcm_mac_t *dest_mac,
    709     bcm_ip_t src_ip,
    710     bcm_ip_t dest_ip,
    711     uint16 vlan,
    712     uint8 prio,
    713     bcm_pbmp_t top_bitmap)
    714 {
    715     bcm_pkt_t *mgmt_packet;
    716     bcm_pkt_t *tunnel_packet;
    717     bcm_pkt_t *ucsig_packet;
    718     int i = 0;
    719     int rv = BCM_E_UNAVAIL;
    720 
    721     sal_memcpy(STACK_DATA(unit, ptp_id).src_mac, src_mac, sizeof(bcm_mac_t));
    722 
    723     sal_memcpy(STACK_DATA(unit, ptp_id).dest_mac, dest_mac, sizeof(bcm_mac_t));
    724 
    725     STACK_DATA(unit, ptp_id).src_ip = src_ip;
    726     STACK_DATA(unit, ptp_id).dest_ip = dest_ip;
    727 
    728     STACK_DATA(unit, ptp_id).vlan = vlan;
    729     STACK_DATA(unit, ptp_id).prio = prio;
    730 
    731     rv = bcm_pkt_alloc(unit, 1600, BCM_TX_CRC_REGEN, &STACK_DATA(unit, ptp_id).mgmt_packet);
    732     if (BCM_FAILURE(rv)) {
    733         return rv;
    734     }
    735 
    736     rv = bcm_pkt_alloc(unit, 1600, BCM_TX_CRC_REGEN, &STACK_DATA(unit, ptp_id).tunnel_packet);
    737     if (BCM_FAILURE(rv)) {
    738         bcm_pkt_free(unit, STACK_DATA(unit, ptp_id).mgmt_packet);
    739         return rv;
    740     }
    741 
    742     rv = bcm_pkt_alloc(unit, 1600, BCM_TX_CRC_REGEN, &STACK_DATA(unit, ptp_id).ucsig_packet);
    743     if (BCM_FAILURE(rv)) {
    744         bcm_pkt_free(unit, STACK_DATA(unit, ptp_id).mgmt_packet);
    745         bcm_pkt_free(unit, STACK_DATA(unit, ptp_id).tunnel_packet);
    746         return rv;
    747     }
    748 
    749     mgmt_packet = STACK_DATA(unit, ptp_id).mgmt_packet;
    750     tunnel_packet = STACK_DATA(unit, ptp_id).tunnel_packet;
    751     ucsig_packet = STACK_DATA(unit, ptp_id).ucsig_packet;
    752 
    753     BCM_PBMP_ASSIGN(mgmt_packet->tx_pbmp, top_bitmap);
    754     BCM_PBMP_ASSIGN(tunnel_packet->tx_pbmp, top_bitmap);
    755     BCM_PBMP_ASSIGN(ucsig_packet->tx_pbmp, top_bitmap);
    756 
    757     _bcm_ptp_management_message_create(BCM_PKT_IEEE(mgmt_packet));
    758     _bcm_ptp_management_message_macaddr_set(BCM_PKT_IEEE(mgmt_packet),
    759         src_mac, dest_mac);
    760     _bcm_ptp_management_message_ipaddr_set(BCM_PKT_IEEE(mgmt_packet),
    761         src_ip, dest_ip);
    762     _bcm_ptp_management_message_vlantag_set(BCM_PKT_IEEE(mgmt_packet),
    763         vlan, prio);
    764 
    765     /* Make template (default) tunnel message packet. */
    766     i = 0;
    767     sal_memcpy(BCM_PKT_IEEE(tunnel_packet), l2hdr_default,
    768                sizeof(l2hdr_default));
    769     i += sizeof(l2hdr_default);
    770 
    771     sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i, vlanhdr_default,
    772                sizeof(vlanhdr_default));
    773     i += sizeof(vlanhdr_default);
    774 
    775     sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i, ethhdr_default,
    776                sizeof(ethhdr_default));
    777     i += sizeof(ethhdr_default);
    778 
    779     sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i, ipv4hdr_default,
    780                sizeof(ipv4hdr_default));
    781     i += sizeof(ipv4hdr_default);
    782 
    783     sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i, udphdr_tunnel,
    784                sizeof(udphdr_tunnel));
    785 
    786     _bcm_ptp_management_message_macaddr_set(BCM_PKT_IEEE(tunnel_packet),
    787         src_mac, dest_mac);
    788     _bcm_ptp_management_message_ipaddr_set(BCM_PKT_IEEE(tunnel_packet),
    789         src_ip, dest_ip);
    790     _bcm_ptp_management_message_vlantag_set(BCM_PKT_IEEE(tunnel_packet),
    791         vlan, prio);
    792 
    793     /* Make template (default) unicast transmission signaling packet. */
    794     i = 0;
    795     sal_memcpy(BCM_PKT_IEEE(ucsig_packet), l2hdr_default,
    796                sizeof(l2hdr_default));
    797     i += sizeof(l2hdr_default);
    798 
    799     sal_memcpy(BCM_PKT_IEEE(ucsig_packet) + i, vlanhdr_default,
    800                sizeof(vlanhdr_default));
    801     i += PTP_VLANHDR_SIZE_OCTETS;
    802 
    803     sal_memcpy(BCM_PKT_IEEE(ucsig_packet) + i, ethhdr_default,
    804                sizeof(ethhdr_default));
    805     i += sizeof(ethhdr_default);
    806 
    807     sal_memcpy(BCM_PKT_IEEE(ucsig_packet) + i, ipv4hdr_default,
    808                sizeof(ipv4hdr_default));
    809     i += sizeof(ipv4hdr_default);
    810 
    811     sal_memcpy(BCM_PKT_IEEE(ucsig_packet) + i, udphdr_default,
    812                sizeof(udphdr_default));
    813     i += sizeof(udphdr_default);
    814 
    815     _bcm_ptp_management_message_macaddr_set(BCM_PKT_IEEE(ucsig_packet),
    816         src_mac, dest_mac);
    817     _bcm_ptp_management_message_ipaddr_set(BCM_PKT_IEEE(ucsig_packet),
    818         src_ip, dest_ip);
    819     _bcm_ptp_management_message_vlantag_set(BCM_PKT_IEEE(ucsig_packet),
    820         vlan, prio);
    821 
    822     return rv;
    823 }
    824 
    825 /*
    826  * Function:
    827  *      _bcm_ptp_external_transport_terminate
    828  * Purpose:
    829  *      Terminate message transport to an external ToP
    830  * Parameters:
    831  *      unit       - (IN) Unit number.
    832  *      ptp_id     - (IN) PTP stack ID.
    833  * Returns:
    834  *      BCM_E_XXX
    835  * Notes:
    836  */
    837 int _bcm_ptp_external_transport_terminate(
    838     int unit,
    839     bcm_ptp_stack_id_t ptp_id)
    840 {
    841     
    842 
    843     bcm_pkt_free(unit, STACK_DATA(unit, ptp_id).ucsig_packet);
    844     STACK_DATA(unit, ptp_id).ucsig_packet = 0;
    845 
    846     bcm_pkt_free(unit, STACK_DATA(unit, ptp_id).tunnel_packet);
    847     STACK_DATA(unit, ptp_id).tunnel_packet = 0;
    848 
    849     bcm_pkt_free(unit, STACK_DATA(unit, ptp_id).mgmt_packet);
    850     STACK_DATA(unit, ptp_id).mgmt_packet = 0;
    851 
    852     return BCM_E_NONE;
    853 }
    854 
    855 /*
    856  * Function:
    857  *      _bcm_ptp_internal_transport_init
    858  * Purpose:
    859  *      Initialize message transport to an internal ToP core
    860  * Parameters:
    861  *      unit       - (IN) Unit number.
    862  *      ptp_id     - (IN) PTP stack ID.
    863  *      src_mac    - (IN) Source MAC address.
    864  *      dest_mac   - (IN) Destination (PTP stack) MAC address.
    865  *      src_ip     - (IN) Source IPv4 address.
    866  *      dest_ip    - (IN) Destination (PTP stack) IPv4 address.
    867  *      vlan       - (IN) VLAN.
    868  *      prio       - (IN) VLAN priority.
    869  *      top_bitmap - (IN) ToP bitmap.
    870  * Returns:
    871  *      BCM_E_XXX
    872  * Notes:
    873  */
    874 int _bcm_ptp_internal_transport_init(
    875     int unit,
    876     bcm_ptp_stack_id_t ptp_id,
    877     bcm_mac_t *src_mac,
    878     bcm_mac_t *dest_mac,
    879     bcm_ip_t src_ip,
    880     bcm_ip_t dest_ip,
    881     uint16 vlan,
    882     uint8 prio,
    883     bcm_pbmp_t top_bitmap)
    884 {
    885     return BCM_E_NONE;
    886 }
    887 
    888 /*
    889  * Function:
    890  *      _bcm_ptp_internal_transport_terminate
    891  * Purpose:
    892  *      Terminate message transport to an internal ToP core
    893  * Parameters:
    894  *      unit       - (IN) Unit number.
    895  *      ptp_id     - (IN) PTP stack ID.
    896  * Returns:
    897  *      BCM_E_XXX
    898  * Notes:
    899  */
    900 int _bcm_ptp_internal_transport_terminate(
    901     int unit,
    902     bcm_ptp_stack_id_t ptp_id)
    903 {
    904     return BCM_E_NONE;
    905 }
    906 
    907 /*
    908  * Function:
    909  *      _bcm_ptp_management_clock_create
    910  * Purpose:
    911  *      Create the PTP management data of a PTP clock.
    912  * Parameters:
    913  *      unit      - (IN) Unit number.
    914  *      ptp_id    - (IN) PTP stack ID.
    915  *      clock_num - (IN) PTP clock number.
    916  * Returns:
    917  *      BCM_E_XXX
    918  * Notes:
    919  */
    920 int
    921 _bcm_ptp_management_clock_create(
    922     int unit,
    923     bcm_ptp_stack_id_t ptp_id,
    924     int clock_num)
    925 {
    926     int rv = BCM_E_NONE;
    927 
    928     rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT);
    929     if (BCM_FAILURE(rv)) {
    930         return rv;
    931     }
    932 
    933     if ((unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
    934         (STACK_DATA(unit, ptp_id).memstate != PTP_MEMSTATE_INITIALIZED)) {
    935         return BCM_E_UNAVAIL;
    936     }
    937 
    938     CLOCK_DATA(unit, ptp_id, clock_num) = mgmt_default;
    939 
    940     return rv;
    941 }
    942 
    943 
    944 /*
    945  * Function:
    946  *      _bcm_ptp_management_message_send
    947  * Purpose:
    948  *      Send a PTP management message.
    949  * Parameters:
    950  *      unit            - (IN) Unit number.
    951  *      ptp_id          - (IN) PTP stack ID.
    952  *      clock_num       - (IN) PTP clock number.
    953  *      dest_clock_port - (IN) Destination PTP clock port.
    954  *      action          - (IN) PTP management action (actionField).
    955  *      cmd             - (IN) PTP command (managementId).
    956  *      payload         - (IN) PTP management message payload.
    957  *      payload_len     - (IN) PTP management message payload size (octets).
    958  *      resp            - (IN/OUT) PTP management message response.
    959  *      resp_len        - (OUT) PTP management message response size (octets).
    960  * Returns:
    961  *      BCM_E_XXX
    962  * Notes:
    963  */
    964 int
    965 _bcm_ptp_management_message_send(
    966     int unit,
    967     bcm_ptp_stack_id_t ptp_id,
    968     int clock_num,
    969     const bcm_ptp_port_identity_t* dest_clock_port,
    970     uint8 action,
    971     uint16 cmd,
    972     uint8* payload,
    973     int payload_len,
    974     uint8* resp,
    975     int* resp_len)
    976 {
    977     int rv = BCM_E_UNAVAIL;
    978     int rvbody = BCM_E_FAIL;
    979 
    980     uint8 *response_data;
    981     int response_len;
    982     int response_payload_len;
    983 
    984     uint8 resp_action;
    985 
    986     uint16 tlvtype;
    987     uint16 tlvlen;
    988 
    989     int tlv_len = 2 + payload_len;
    990     int message_len = 48 + 4 + tlv_len;
    991 
    992     uint8 message[1500];
    993 
    994     uint16 mgmt_id;
    995 
    996     int max_resp_len = (resp_len) ? *resp_len : 0;
    997 
    998     _bcm_ptp_info_t *ptp_info_p = &_bcm_common_ptp_info[unit];
    999     _bcm_ptp_stack_info_t *stack_p = &ptp_info_p->stack_info[ptp_id];
   1000 
   1001 /*    ptp_printf("_bcm_ptp_management_message_send(): ENTER | %s | @ t = %u |\n", */
   1002 /*               bcm_errmsg(BCM_E_NONE), (unsigned)sal_time_usecs());             */
   1003 
   1004     if (resp_len) {
   1005         *resp_len = 0;
   1006     }
   1007 
   1008     /* Sanity check running system */
   1009     rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT);
   1010     if (BCM_FAILURE(rv)) {
   1011         return rv;
   1012     }
   1013 
   1014     if ((unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
   1015         (STACK_DATA(unit, ptp_id).memstate != PTP_MEMSTATE_INITIALIZED)) {
   1016         /* Verify initialization */
   1017         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1018                     (BSL_META_U(unit,
   1019                                 "PTP send failed: Memory state\n")));
   1020         return BCM_E_UNAVAIL;
   1021     }
   1022 
   1023     rv = _bcm_ptp_sem_take(STACK_DATA(unit, ptp_id).outgoing_available, PTP_MGMT_RESPONSE_TIMEOUT_US);
   1024     if (BCM_FAILURE(rv)) {
   1025         PTP_ERROR_FUNC("_bcm_ptp_sem_take()");
   1026         return rv;
   1027     }
   1028 
   1029 /*     LOG_CLI((BSL_META_U(unit,
   1030                            "mgmt_send(len:%d)\n"), payload_len)); */
   1031 /*     _bcm_ptp_dump_hex(payload, payload_len, 0); */
   1032 
   1033     /* Init the mgmt message with presets */
   1034     sal_memset(message, 0, sizeof (message));
   1035 
   1036     sal_memcpy(message,
   1037                ptphdr_mgmt, sizeof(ptphdr_mgmt));
   1038     sal_memcpy(message + PTP_PTPHDR_SIZE_OCTETS,
   1039                mgmthdr_mgmt, sizeof(mgmthdr_mgmt));
   1040     sal_memcpy(message + PTP_PTPHDR_SIZE_OCTETS + PTP_MGMTHDR_SIZE_OCTETS,
   1041                tlvhdr_mgmt, sizeof(tlvhdr_mgmt));
   1042 
   1043     /* Make the PTP Packet header */
   1044     _bcm_ptp_uint16_write(message + PTP_PTPHDR_MSGLEN_OFFSET_OCTETS, message_len);
   1045 
   1046     message[PTP_PTPHDR_DOMAIN_OFFSET_OCTETS] = CLOCK_DATA(unit, ptp_id, clock_num).domain;
   1047 
   1048     /* Make the Management header */
   1049     sal_memcpy(message + PTP_PTPHDR_SIZE_OCTETS,
   1050                (uint8*)dest_clock_port->clock_identity, sizeof(bcm_ptp_clock_identity_t));
   1051 
   1052     _bcm_ptp_uint16_write(message + PTP_PTPHDR_SIZE_OCTETS + BCM_PTP_CLOCK_EUID_IEEE1588_SIZE,
   1053                           dest_clock_port->port_number);
   1054 
   1055     message[PTP_PTPHDR_SIZE_OCTETS + sizeof(bcm_ptp_port_identity_t) + 2] = action;
   1056 
   1057     /* Make the TLV header */
   1058     _bcm_ptp_uint16_write(message + PTP_PTPHDR_SIZE_OCTETS + PTP_MGMTHDR_SIZE_OCTETS + 2, tlv_len);
   1059 
   1060     _bcm_ptp_uint16_write(message + PTP_PTPHDR_SIZE_OCTETS + PTP_MGMTHDR_SIZE_OCTETS + 2 + 2, cmd);
   1061 
   1062     /* Make the payload */
   1063     sal_memcpy(message + PTP_PTPHDR_SIZE_OCTETS + PTP_MGMTHDR_SIZE_OCTETS + PTP_TLVHDR_SIZE_OCTETS,
   1064                payload, payload_len);
   1065 
   1066 /*   LOG_CLI((BSL_META_U(unit,
   1067                          "mgmt_send_tx(len:%d)\n"), message_len)); */
   1068 /*     _bcm_ptp_dump_hex(message, message_len, 0); */
   1069 
   1070     rv = stack_p->tx(unit, ptp_id, clock_num, PTP_MESSAGE_TO_TOP, 0, 0, message, message_len);
   1071 
   1072     if (rv != BCM_E_NONE) {
   1073         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1074                     (BSL_META_U(unit,
   1075                                 "PTP send failed: Tx error\n")));
   1076         goto release_mgmt_lock;
   1077     }
   1078 
   1079     /*
   1080      * Get rx buffer, either from rx callback or from cmicm wait task
   1081      * NOTICE: This call will return an rx response buffer that we will need to
   1082      *         release by notifying the Rx section
   1083      */
   1084     rv = _bcm_ptp_rx_response_get(unit, ptp_id, clock_num, PTP_MGMT_RESPONSE_TIMEOUT_US,
   1085                                   &response_data, &response_len);
   1086     if (BCM_FAILURE(rv)) {
   1087         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1088                     (BSL_META_U(unit,
   1089                                 "PTP send failed: No response\n")));
   1090         goto release_mgmt_lock;
   1091     }
   1092 
   1093     if (!response_data) {
   1094         LOG_ERROR(BSL_LS_BCM_COMMON,
   1095                   (BSL_META_U(unit,
   1096                               "Unexpected NULL response\n")));
   1097         goto release_mgmt_lock;
   1098     }
   1099 
   1100     rv = BCM_E_FAIL;
   1101     resp_action = (response_data[PTP_MGMT_RESP_ACTION_OFFSET] & 0x0f);
   1102 
   1103     if (((action == PTP_MGMTMSG_SET) || (action == PTP_MGMTMSG_GET)) && (resp_action != PTP_MGMTMSG_RESP)) {
   1104         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1105                     (BSL_META_U(unit,
   1106                                 "PTP send failed: Bad response action\n")));
   1107         goto dispose_of_resp;
   1108     }
   1109 
   1110     if ((action == PTP_MGMTMSG_CMD) && (resp_action != PTP_MGMTMSG_ACK) ) {
   1111         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1112                     (BSL_META_U(unit,
   1113                                 "PTP send failed: Bad cmd response action\n")));
   1114         goto dispose_of_resp;
   1115     }
   1116 
   1117     tlvtype = _bcm_ptp_uint16_read(response_data + PTP_MGMT_RESP_TLV_TYPE_OFFSET);
   1118 
   1119     if (tlvtype == bcmPTPTlvTypeManagementErrorStatus) {
   1120         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1121                     (BSL_META_U(unit,
   1122                                 "Error response: 0x%04x\n"),
   1123                      _bcm_ptp_uint16_read(response_data + PTP_MGMT_RESP_TLV_VAL_OFFSET)));
   1124         goto dispose_of_resp;
   1125     }
   1126 
   1127     tlvlen = _bcm_ptp_uint16_read(response_data + PTP_MGMT_RESP_TLV_LEN_OFFSET);
   1128 
   1129     if (tlvlen + PTP_MGMT_RESP_TLV_VAL_OFFSET > response_len) {
   1130         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1131                     (BSL_META_U(unit,
   1132                                 "PTP send failed: Bad TLV len\n")));
   1133         goto dispose_of_resp;
   1134     }
   1135 
   1136     mgmt_id = _bcm_ptp_uint16_read(response_data + PTP_MGMT_RESP_TLV_VAL_OFFSET);
   1137 
   1138     if (mgmt_id != cmd) {
   1139         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1140                     (BSL_META_U(unit,
   1141                                 "Bad mgmt ID: %04x vs %04x\n"), mgmt_id, cmd));
   1142         goto dispose_of_resp;
   1143     }
   1144 
   1145     if (resp && resp_len) {
   1146         response_payload_len = tlvlen - 2;
   1147         if (response_payload_len > max_resp_len) {
   1148             response_payload_len = max_resp_len;
   1149         }
   1150 
   1151         *resp_len = response_payload_len;
   1152         sal_memcpy(resp, response_data + PTP_MGMT_RESP_PAYLOAD_OFFSET, response_payload_len);
   1153     }
   1154 
   1155     rv = BCM_E_NONE;
   1156 
   1157 dispose_of_resp:
   1158     stack_p->rx_free(unit, ptp_id, response_data);
   1159 
   1160 release_mgmt_lock:
   1161     rvbody = rv;
   1162     if (BCM_FAILURE(rv = _bcm_ptp_sem_give(STACK_DATA(unit, ptp_id).outgoing_available))) {
   1163         PTP_ERROR_FUNC("_bcm_ptp_sem_give()");
   1164     }
   1165 
   1166 /*    ptp_printf("_bcm_ptp_management_message_send(): EXIT  | %s | @ t = %u |\n", */
   1167 /*               bcm_errmsg(rvbody), (unsigned)sal_time_usecs());                 */
   1168 
   1169     return rvbody ? rvbody : rv;
   1170 }
   1171 
   1172 
   1173 /*
   1174  * Function:
   1175  *      _bcm_ptp_tunnel_message_to_top
   1176  * Purpose:
   1177  *      Tunnel a message to ToP processor.
   1178  * Parameters:
   1179  *      unit        - (IN) Unit number.
   1180  *      ptp_id      - (IN) PTP stack ID.
   1181  *      clock_index - (IN) PTP clock index
   1182  *      port_index  - (IN) PTP port index
   1183  *      payload_len - (IN) Tunnel message payload size (octets).
   1184  *      payload     - (IN) Tunnel message payload.
   1185  *      async       - (IN) Message should be queued and sent asynchronously
   1186  * Returns:
   1187  *      BCM_E_XXX
   1188  * Notes:
   1189  */
   1190 int
   1191 _bcm_ptp_tunnel_message_to_top(
   1192     int unit,
   1193     bcm_ptp_stack_id_t ptp_id,
   1194     int clock_index,
   1195     int port_index,
   1196     unsigned payload_len,
   1197     uint8 *payload,
   1198     int async)
   1199 {
   1200     uint8 hdr[2] = {0};
   1201     _bcm_ptp_uint16_write(hdr, port_index);
   1202 
   1203     if (async) {
   1204         return _bcm_ptp_tunnel_queue_add(unit, ptp_id, clock_index, PTP_TUNNEL_TO_TOP, sizeof(hdr), hdr, payload_len, payload);
   1205     } else {
   1206         return _bcm_ptp_tunnel_message(unit, ptp_id, clock_index, PTP_TUNNEL_TO_TOP, sizeof(hdr), hdr, payload_len, payload);
   1207     }
   1208 }
   1209 
   1210 
   1211 /*
   1212  * Function:
   1213  *      _bcm_ptp_tunnel_message_to_world
   1214  * Purpose:
   1215  *      Tunnel a message to "world".
   1216  * Parameters:
   1217  *      unit        - (IN) Unit number.
   1218  *      ptp_id      - (IN) PTP stack ID.
   1219  *      clock_index - (IN) PTP clock index.
   1220  *      payload_len - (IN) Tunnel message payload size (octets).
   1221  *      payload     - (IN) Tunnel message payload.
   1222  *      async       - (IN) Message should be queued and sent asynchronously
   1223  * Returns:
   1224  *      BCM_E_XXX
   1225  * Notes:
   1226  */
   1227 int
   1228 _bcm_ptp_tunnel_message_to_world(
   1229     int unit,
   1230     bcm_ptp_stack_id_t ptp_id,
   1231     int clock_index,
   1232     unsigned payload_len,
   1233     uint8 *payload,
   1234     int async)
   1235 {
   1236     if (async) {
   1237         return _bcm_ptp_tunnel_queue_add(unit, ptp_id, clock_index, PTP_TUNNEL_FROM_TOP, 0, 0, payload_len, payload);
   1238     } else {
   1239         return _bcm_ptp_tunnel_message(unit, ptp_id, clock_index, PTP_TUNNEL_FROM_TOP, 0, 0, payload_len, payload);
   1240     }
   1241 }
   1242 
   1243 
   1244 /*
   1245  * Function:
   1246  *      _bcm_ptp_tunnel_message
   1247  * Purpose:
   1248  *      Tunnel a message out
   1249  * Parameters:
   1250  *      unit        - (IN) Unit number.
   1251  *      ptp_id      - (IN) PTP stack ID.
   1252  *      clock_index - (IN) PTP clock index.
   1253  *      clock_port  - (IN) PTP clock port if type is PTP_TUNNEL_TO_TOP
   1254  *      tunnel_type - (IN) PTP_TUNNEL_FROM_TOP, PTP_TUNNEL_TO_TOP, PTP_TUNNEL_SINGLE_TO_TOP
   1255  *      payload_len - (IN) Tunnel message payload size (octets).
   1256  *      payload     - (IN) Tunnel message payload.
   1257  * Returns:
   1258  *      BCM_E_XXX
   1259  * Notes:
   1260  */
   1261 static int
   1262 _bcm_ptp_tunnel_message(
   1263     int unit,
   1264     bcm_ptp_stack_id_t ptp_id,
   1265     int clock_index,
   1266     int tunnel_type,
   1267     unsigned hdr_len,
   1268     uint8 *hdr,
   1269     unsigned payload_len,
   1270     uint8 *payload)
   1271 {
   1272     _bcm_ptp_info_t *ptp_info_p = &_bcm_common_ptp_info[unit];
   1273     _bcm_ptp_stack_info_t *stack_p = &ptp_info_p->stack_info[ptp_id];
   1274 
   1275     int rv = BCM_E_NONE;
   1276     int rvbody = BCM_E_FAIL;
   1277     static int failure_count = 0;
   1278     static const int failure_log_threshold = 10;
   1279 
   1280     if ((unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
   1281         (STACK_DATA(unit, ptp_id).memstate != PTP_MEMSTATE_INITIALIZED)) {
   1282         /* Verify initialization */
   1283         LOG_VERBOSE(BSL_LS_BCM_PTP,
   1284                     (BSL_META_U(unit,
   1285                                 "PTP tunnel failed: Memory state\n")));
   1286         return BCM_E_UNAVAIL;
   1287     }
   1288 
   1289     rv = _bcm_ptp_sem_take(STACK_DATA(unit, ptp_id).outgoing_available, PTP_TUNNEL_MESSAGE_TIMEOUT_US);
   1290     if (BCM_FAILURE(rv)) {
   1291         if (++failure_count > failure_log_threshold) {
   1292             LOG_ERROR(BSL_LS_BCM_PTP,
   1293                       (BSL_META_U(unit,
   1294                                   "Repeated PTP tunnel failures due to busy state\n")));
   1295         } else {
   1296             LOG_VERBOSE(BSL_LS_BCM_PTP,
   1297                         (BSL_META_U(unit,
   1298                                     "PTP tunnel failure due to busy state\n")));
   1299         }
   1300         return rv;
   1301     }
   1302 
   1303     rv = stack_p->tx(unit, ptp_id, clock_index, tunnel_type, hdr, hdr_len, payload, payload_len);
   1304 
   1305     if (rv != BCM_E_NONE) {
   1306         LOG_VERBOSE(BSL_LS_BCM_PTP,
   1307                     (BSL_META_U(unit,
   1308                                 "PTP tunnel failed: Tx error\n")));
   1309         goto release_tunnel_lock;
   1310     }
   1311 
   1312     rv = stack_p->tx_completion(unit, ptp_id);
   1313 
   1314 release_tunnel_lock:
   1315     rvbody = rv;
   1316     if (BCM_FAILURE(rv = _bcm_ptp_sem_give(STACK_DATA(unit, ptp_id).outgoing_available))) {
   1317         PTP_ERROR_FUNC("_bcm_ptp_sem_give()");
   1318     }
   1319 
   1320     if (rvbody == BCM_E_NONE) {
   1321         failure_count = 0;
   1322     }
   1323 
   1324     return rvbody ? rvbody : rv;
   1325 }
   1326 
   1327 
   1328 
   1329 int
   1330 _bcm_ptp_external_tx(
   1331     int unit,
   1332     bcm_ptp_stack_id_t ptp_id,
   1333     int clock_num,
   1334     _bcm_ptp_transport_type_t transport,
   1335     uint8 *hdr,
   1336     int hdr_len,
   1337     uint8 *message,
   1338     int message_len)
   1339 {
   1340     int rv = BCM_E_NONE;
   1341 
   1342 /*     LOG_CLI((BSL_META_U(unit,
   1343                            "external_tx(type:%d len:%d)\n"), (int)transport, message_len)); */
   1344 /*     _bcm_ptp_dump_hex(message, message_len, 0); */
   1345 
   1346     /* Send the right kind of message */
   1347     switch (transport) {
   1348     case PTP_MESSAGE_TO_TOP:
   1349     {
   1350         /* WFT: probably should just allocate packet here rather than having pre-allocated... */
   1351         _bcm_ptp_stack_mgmt_array_t *mgmt = &STACK_DATA(unit, ptp_id);
   1352         bcm_pkt_t *mgmt_packet = mgmt->mgmt_packet;
   1353         uint8 *cursor = BCM_PKT_IEEE(mgmt_packet);
   1354         int prio = 0;
   1355 
   1356         /* L2 Header MACs*/
   1357         sal_memcpy(cursor, mgmt->dest_mac, sizeof(bcm_mac_t));  cursor += sizeof(bcm_mac_t);
   1358         sal_memcpy(cursor, mgmt->src_mac, sizeof(bcm_mac_t));  cursor += sizeof(bcm_mac_t);
   1359 
   1360         /*   VLAN */
   1361         *cursor++ = 0x81; *cursor++ = 0x00;
   1362         *cursor++ = (prio << 5) | (0x0f & (mgmt->vlan >> 8));
   1363         *cursor++ = (mgmt->vlan);
   1364 
   1365         /*   Ethertype: IPv4 */
   1366         *cursor++ = 0x08;
   1367         *cursor++ = 0x00;
   1368 
   1369         /* IPv4 Header */
   1370         *cursor++ = 0x45;  /*type & header length */
   1371         *cursor++ = 0x00;
   1372 
   1373         /*   IPv4 total length */
   1374         _bcm_ptp_uint16_write(cursor, 20 + 8 + hdr_len + message_len); cursor += 2;
   1375 
   1376         *cursor++ = 0;
   1377         *cursor++ = 0;
   1378 
   1379         *cursor++ = 0x40;  /* flags */
   1380         *cursor++ = 0;
   1381 
   1382         *cursor++ = 1;     /* TTL */
   1383         *cursor++ = 0x11;  /* protocol = UDP */
   1384 
   1385         *cursor++ = 0;     /* header checksum (zeros for computation) */
   1386         *cursor++ = 0;
   1387 
   1388         _bcm_ptp_uint32_write(cursor, mgmt->src_ip);  cursor += 4;
   1389         _bcm_ptp_uint32_write(cursor, mgmt->dest_ip);  cursor += 4;
   1390 
   1391         /* UDP Header */
   1392         _bcm_ptp_uint16_write(cursor, 0x140);  cursor += 2;  /* source port */
   1393         _bcm_ptp_uint16_write(cursor, 0x140);  cursor += 2;  /* dest port */
   1394 
   1395         _bcm_ptp_uint16_write(cursor, 8 + hdr_len + message_len);  cursor += 2;  /* UDP length */
   1396 
   1397         _bcm_ptp_uint16_write(cursor, 0);  cursor += 2;  /* UDP Checksum (optional) */
   1398 
   1399         /* Update IPv4 header checksum. */
   1400         rv = _bcm_ptp_management_message_ipv4hdr_checksum_set(BCM_PKT_IEEE(mgmt_packet));
   1401         
   1402 
   1403         sal_memcpy(cursor, hdr, hdr_len);  cursor += hdr_len;
   1404         sal_memcpy(cursor, message, message_len);  cursor += message_len;
   1405 
   1406         /*
   1407          * Set packet length.
   1408          * NOTICE: Includes 4 for the CRC appended to the packet
   1409          */
   1410         mgmt_packet->pkt_data[0].len = (cursor - BCM_PKT_IEEE(mgmt_packet)) + 4;
   1411 
   1412 /*      LOG_CLI((BSL_META_U(unit,
   1413                             "packet(len:%d)\n"), mgmt_packet->pkt_data[0].len)); */
   1414 /*         _bcm_ptp_dump_hex(BCM_PKT_IEEE(mgmt_packet), mgmt_packet->pkt_data[0].len, 0); */
   1415 
   1416         rv = bcm_tx(unit, mgmt_packet, NULL);
   1417 
   1418         break;
   1419     }
   1420 
   1421     case PTP_TUNNEL_TO_TOP:
   1422     {
   1423         int rv = BCM_E_UNAVAIL;
   1424 
   1425         bcm_pkt_t *tunnel_packet;
   1426 
   1427         uint16 udp_length = hdr_len + message_len + PTP_UDPHDR_SIZE_OCTETS;
   1428         uint16 ip_length  = udp_length + PTP_IPV4HDR_SIZE_OCTETS;
   1429         uint16 packet_length = ip_length + PTP_IPV4HDR_START_IDX;
   1430         int i = 0;
   1431 
   1432         tunnel_packet = STACK_DATA(unit, ptp_id).tunnel_packet;
   1433 
   1434         i = PTP_PTPHDR_START_IDX;
   1435         sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i, hdr, hdr_len);
   1436         sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i + hdr_len, message, message_len);
   1437 
   1438         i = PTP_UDPHDR_START_IDX + PTP_UDPHDR_MSGLEN_OFFSET_OCTETS;
   1439         _bcm_ptp_uint16_write(BCM_PKT_IEEE(tunnel_packet) + i, udp_length);
   1440 
   1441         i = PTP_IPV4HDR_START_IDX + PTP_IPV4HDR_MSGLEN_OFFSET_OCTETS;
   1442         _bcm_ptp_uint16_write(BCM_PKT_IEEE(tunnel_packet) + i, ip_length);
   1443 
   1444         _bcm_ptp_management_message_port_set(BCM_PKT_IEEE(tunnel_packet), 0x0141, 0x0141);
   1445 
   1446         /* Set IPv4 header checksum. */
   1447         if (BCM_FAILURE(rv = _bcm_ptp_management_message_ipv4hdr_checksum_set(
   1448                             BCM_PKT_IEEE(tunnel_packet)))) {
   1449             return rv;
   1450         }
   1451 
   1452         /* Set packet size. */
   1453         tunnel_packet->pkt_data[0].len = packet_length + 4;
   1454 
   1455         rv = bcm_tx(unit, tunnel_packet, NULL);
   1456 
   1457         break;
   1458     }
   1459 
   1460     case PTP_TUNNEL_FROM_TOP:
   1461     {
   1462         int rv = BCM_E_UNAVAIL;
   1463 
   1464         bcm_pkt_t *tunnel_packet;
   1465 
   1466         uint16 udp_length = hdr_len + message_len + PTP_UDPHDR_SIZE_OCTETS;
   1467         uint16 ip_length  = udp_length + PTP_IPV4HDR_SIZE_OCTETS;
   1468         uint16 packet_length = ip_length + PTP_IPV4HDR_START_IDX;
   1469         int i = 0;
   1470 
   1471         tunnel_packet = STACK_DATA(unit, ptp_id).tunnel_packet;
   1472 
   1473         i = PTP_PTPHDR_START_IDX;
   1474         sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i, hdr, hdr_len);
   1475         sal_memcpy(BCM_PKT_IEEE(tunnel_packet) + i + hdr_len, message, message_len);
   1476 
   1477         i = PTP_UDPHDR_START_IDX + PTP_UDPHDR_MSGLEN_OFFSET_OCTETS;
   1478         _bcm_ptp_uint16_write(BCM_PKT_IEEE(tunnel_packet) + i, udp_length);
   1479 
   1480         i = PTP_IPV4HDR_START_IDX + PTP_IPV4HDR_MSGLEN_OFFSET_OCTETS;
   1481         _bcm_ptp_uint16_write(BCM_PKT_IEEE(tunnel_packet) + i, ip_length);
   1482 
   1483         _bcm_ptp_management_message_port_set(BCM_PKT_IEEE(tunnel_packet), 0x0143, 0x0143);
   1484 
   1485         /* Set IPv4 header checksum. */
   1486         rv = _bcm_ptp_management_message_ipv4hdr_checksum_set(BCM_PKT_IEEE(tunnel_packet));
   1487         if (BCM_FAILURE(rv)) {
   1488             PTP_ERROR_FUNC("_bcm_ptp_management_message_ipv4hdr_checksum_set()");
   1489             return rv;
   1490         }
   1491 
   1492         /* Set packet size. */
   1493         tunnel_packet->pkt_data[0].len = packet_length + 4;
   1494 
   1495         rv = bcm_tx(unit, tunnel_packet, NULL);
   1496 
   1497         break;
   1498     }
   1499 
   1500     default:
   1501         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1502                     (BSL_META_U(unit,
   1503                                 "PTP external send failed: Unkmown transport type\n")));
   1504     }
   1505 
   1506     return rv;
   1507 }
   1508 
   1509 
   1510 int
   1511 _bcm_ptp_external_tx_completion(
   1512     int unit,
   1513     bcm_ptp_stack_id_t ptp_id)
   1514 {
   1515     /* message was already sent as a packet via switch, so it is already gone */
   1516     return BCM_E_NONE;
   1517 }
   1518 
   1519 #if defined(BCM_PTP_INTERNAL_STACK_SUPPORT)
   1520 int
   1521 _bcm_ptp_internal_tx(
   1522     int unit,
   1523     bcm_ptp_stack_id_t ptp_id,
   1524     int clock_num,
   1525     _bcm_ptp_transport_type_t transport,
   1526     uint8 *hdr,
   1527     int hdr_len,
   1528     uint8 *message,
   1529     int message_len)
   1530 
   1531 {
   1532     _bcm_ptp_info_t *ptp_info_p = &_bcm_common_ptp_info[unit];
   1533     _bcm_ptp_stack_info_t *stack_p = &ptp_info_p->stack_info[ptp_id];
   1534 
   1535     int rv = BCM_E_NONE;
   1536 
   1537     mos_msg_data_t uc_msg;
   1538     uint8 *msg_data;
   1539 
   1540     int wait_iter = 0;
   1541 
   1542     sal_memset(&uc_msg, 0, sizeof(uc_msg));
   1543     uc_msg.s.mclass = MOS_MSG_CLASS_1588;
   1544     uc_msg.s.subclass = MOS_MSG_SUBCLASS_MBOX_CMDRESP;
   1545 
   1546     /* mbox 0 reserved for cmd/resp */
   1547     msg_data = (uint8 *)stack_p->int_state.mboxes->mbox[0].data;
   1548 
   1549     if (GET_MBOX_STATUS(stack_p, 0) != MBOX_STATUS_EMPTY) {
   1550         /* wait for to-TOP buffer to be free */
   1551         while (GET_MBOX_STATUS(stack_p, 0) != MBOX_STATUS_EMPTY && wait_iter < 1000000) {
   1552             ++wait_iter;
   1553             sal_usleep(1);
   1554         }
   1555 
   1556         if (GET_MBOX_STATUS(stack_p, 0) != MBOX_STATUS_EMPTY) {
   1557             int old_status = GET_MBOX_STATUS(stack_p, 0);
   1558             /* Waiting failed.  Flush whatever is in the mbox to reset things.
   1559              * Note: If this is happening, a previous message send/receive has
   1560              *   likely failed.  Possible causes can be a block on the host side
   1561              *   Rx task, or a failure of the FW that we are trying to talk to
   1562              */
   1563             _bcm_ptp_rx_response_flush(unit, ptp_id, clock_num);
   1564             if (GET_MBOX_STATUS(stack_p, 0) != MBOX_STATUS_EMPTY) {
   1565                 LOG_ERROR(BSL_LS_BCM_PTP, (BSL_META_U(unit,
   1566                     "PTP mbox full and unflushable (status %d)\n"),
   1567                     old_status));
   1568                 return BCM_E_FAIL;
   1569             } else {
   1570                 LOG_ERROR(BSL_LS_BCM_PTP, (BSL_META_U(unit,
   1571                     "PTP mbox force-flushed (status %d)\n"),
   1572                     old_status));
   1573             }
   1574         } else if (wait_iter > 0) {
   1575             LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit,
   1576                 "PTP mbox contention, wait: %d\n"), wait_iter));
   1577         }
   1578     }
   1579 
   1580     sal_memcpy(msg_data, hdr, hdr_len);
   1581     sal_memcpy(msg_data + hdr_len, message, message_len);
   1582 
   1583     stack_p->int_state.mboxes->mbox[0].data_len = soc_htonl(hdr_len + message_len);
   1584     stack_p->int_state.mboxes->mbox[0].clock_num = soc_htonl(clock_num);
   1585 
   1586     /* Flush entire mbox structure so firmware can DMA it (before setting status, to avoid race) */
   1587     soc_cm_sflush(unit, (void*)&stack_p->int_state.mboxes->mbox[0],
   1588                   sizeof(stack_p->int_state.mboxes->mbox[0]));
   1589 
   1590     /* Send the right kind of message */
   1591     switch (transport) {
   1592     case PTP_MESSAGE_TO_TOP:
   1593         SET_MBOX_STATUS(stack_p, 0, MBOX_STATUS_ATTN_TOP_CMD);
   1594         break;
   1595     case PTP_TUNNEL_TO_TOP:
   1596         SET_MBOX_STATUS(stack_p, 0, MBOX_STATUS_ATTN_TOP_TUNNEL_TO_TOP);
   1597         break;
   1598     case PTP_TUNNEL_FROM_TOP:
   1599         SET_MBOX_STATUS(stack_p, 0, MBOX_STATUS_ATTN_TOP_TUNNEL_EXTERNAL);
   1600         break;
   1601     default:
   1602         LOG_ERROR(BSL_LS_BCM_COMMON,
   1603                   (BSL_META_U(unit,
   1604                               "PTP internal send failed: Unkmown transport type\n")));
   1605     }
   1606 
   1607     rv = soc_cmic_uc_msg_send(unit, stack_p->int_state.core_num, &uc_msg, 1000000);
   1608 
   1609     return rv;
   1610 }
   1611 
   1612 int
   1613 _bcm_ptp_internal_tx_completion(
   1614     int unit,
   1615     bcm_ptp_stack_id_t ptp_id)
   1616 {
   1617     _bcm_ptp_info_t *ptp_info_p = &_bcm_common_ptp_info[unit];
   1618     _bcm_ptp_stack_info_t *stack_p = &ptp_info_p->stack_info[ptp_id];
   1619     int iter;
   1620 
   1621     for (iter = 0; iter < 10000; ++iter) {
   1622         if (GET_MBOX_STATUS(stack_p, 0) == MBOX_STATUS_EMPTY) {
   1623             return BCM_E_NONE;
   1624         }
   1625         sal_usleep(1);
   1626     }
   1627 
   1628     LOG_ERROR(BSL_LS_BCM_COMMON,
   1629               (BSL_META_U(unit,
   1630                           "Failed async Tx to ToP.  No clear\n")));
   1631     return BCM_E_TIMEOUT;
   1632 }
   1633 
   1634 
   1635 #endif
   1636 
   1637 
   1638 /*
   1639  * Function:
   1640  *      _bcm_ptp_unicast_slave_subscribe
   1641  * Purpose:
   1642  *      Manage external slave subscriptions of a PTP clock port.
   1643  * Parameters:
   1644  *      unit       - (IN) Unit number.
   1645  *      ptp_id     - (IN) PTP stack ID.
   1646  *      clock_num  - (IN) PTP clock number.
   1647  *      clock_port - (IN) PTP clock port number.
   1648  *      slave_info - (IN) Unicast slave information.
   1649  *      msg_type   - (IN) PTP message type to request/cancel.
   1650  *      tlv_type   - (IN) TLV type (request/cancel unicast transmission).
   1651  *      interval   - (IN) Log inter-message interval (logInterMessagePeriod).
   1652  * Returns:
   1653  *      BCM_E_XXX
   1654  * Notes:
   1655  *      PTP unicast negotiation is used to manage external slave services
   1656  *      through REQUEST_UNICAST_TRANSMISSION and CANCEL_UNICAST_TRANSMISSION
   1657  *      TLVs.
   1658  *      Ref. IEEE Std. 1588-2008, Chapters 14.1 and 16.1.
   1659  */
   1660 int
   1661 _bcm_ptp_unicast_slave_subscribe(
   1662     int unit,
   1663     bcm_ptp_stack_id_t ptp_id,
   1664     int clock_num,
   1665     uint32 clock_port,
   1666     _bcm_ptp_clock_peer_ext_t *slave_info,
   1667     bcm_ptp_message_type_t msg_type,
   1668     bcm_ptp_tlv_type_t tlv_type,
   1669     int interval)
   1670 {
   1671     int rv = BCM_E_UNAVAIL;
   1672     int rvbody = BCM_E_FAIL;
   1673 
   1674     bcm_ptp_port_identity_t portid;
   1675     uint8 message[1500];
   1676     uint16 message_len;
   1677 
   1678     uint16 tlv_octets = 0;
   1679     uint16 sequence_id = 0x0002;
   1680 
   1681     uint8 *response_data;
   1682     uint16 response_tlv_type;
   1683     int response_len;
   1684     int i = 0;
   1685 
   1686     _bcm_ptp_info_t *ptp_info_p = &_bcm_common_ptp_info[unit];
   1687     _bcm_ptp_stack_info_t *stack_p = &ptp_info_p->stack_info[ptp_id];
   1688 
   1689     rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT);
   1690     if (BCM_FAILURE(rv)) {
   1691         return rv;
   1692     }
   1693 
   1694     if ((unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
   1695         (STACK_DATA(unit, ptp_id).memstate != PTP_MEMSTATE_INITIALIZED)) {
   1696         return BCM_E_UNAVAIL;
   1697     }
   1698 
   1699     rv = _bcm_ptp_sem_take(STACK_DATA(unit, ptp_id).outgoing_available, PTP_MGMT_RESPONSE_TIMEOUT_US);
   1700     if (BCM_FAILURE(rv)) {
   1701         PTP_ERROR_FUNC("_bcm_ptp_sem_take()");
   1702         return rv;
   1703     }
   1704 
   1705     /*
   1706      * TLV-type dependent message constructor parameters.
   1707      * Set unicast signaling message size information based on TLV type.
   1708      * Set sequence ID numbering scheme offset.
   1709      */
   1710     switch (tlv_type) {
   1711     case bcmPTPTlvTypeRequestUnicastTransmission:
   1712         tlv_octets = PTP_UCSIG_REQUEST_TLV_SIZE_OCTETS;
   1713         message_len = PTP_UCSIG_REQUEST_TOTAL_SIZE_OCTETS - PTP_PTPHDR_START_IDX;
   1714         sequence_id += 0;
   1715         break;
   1716 
   1717     case bcmPTPTlvTypeCancelUnicastTransmission:
   1718         tlv_octets = PTP_UCSIG_CANCEL_TLV_SIZE_OCTETS;
   1719         message_len = PTP_UCSIG_CANCEL_TOTAL_SIZE_OCTETS - PTP_PTPHDR_START_IDX;
   1720         sequence_id += 4;
   1721         break;
   1722 
   1723     default:
   1724         rv = BCM_E_PARAM;
   1725         goto release_return;
   1726     }
   1727 
   1728     /* Make unicast transmission message. */
   1729     sal_memset(message, 0, sizeof (message));
   1730 
   1731     sal_memcpy(message,
   1732                ptphdr_ucsig, sizeof(ptphdr_ucsig));
   1733     sal_memcpy(message + PTP_PTPHDR_SIZE_OCTETS,
   1734                tgtport_ucsig, sizeof(tgtport_ucsig));
   1735     sal_memcpy(message + PTP_PTPHDR_SIZE_OCTETS + PTP_MGMTHDR_SIZE_OCTETS,
   1736                unicast_request_tlv_ucsig, sizeof(unicast_request_tlv_ucsig));
   1737 
   1738     /* Insert PTP header length. */
   1739     _bcm_ptp_uint16_write(message + PTP_PTPHDR_MSGLEN_OFFSET_OCTETS, message_len);
   1740 
   1741     message[PTP_PTPHDR_DOMAIN_OFFSET_OCTETS] = CLOCK_DATA(unit, ptp_id, clock_num).domain;
   1742 
   1743     /*
   1744      * Insert source port identity.
   1745      * NOTICE: In this context, the source port is the remote port, i.e.,
   1746      *         requester/grantee of signaling messages.
   1747      */
   1748     sal_memcpy(message + PTP_PTPHDR_SRCPORT_OFFSET_OCTETS,
   1749                slave_info->peer.clock_identity, sizeof(bcm_ptp_clock_identity_t));
   1750 
   1751     _bcm_ptp_uint16_write(message + PTP_PTPHDR_SRCPORT_OFFSET_OCTETS + BCM_PTP_CLOCK_EUID_IEEE1588_SIZE,
   1752                           slave_info->peer.remote_port_number);
   1753 
   1754     /*
   1755      * Insert sequence ID.
   1756      * NOTICE: Logic uses a unique sequence IDs for distinct classes only of
   1757      *         REQUEST_UNICAST_TRANSMISSION and CANCEL_UNICAST_TRANSMISSION
   1758      *         signaling messages.
   1759      */
   1760     switch (msg_type) {
   1761     case bcmPTP_MESSAGE_TYPE_ANNOUNCE:
   1762         break;
   1763 
   1764     case bcmPTP_MESSAGE_TYPE_SYNC:
   1765        sequence_id += 1;
   1766        break;
   1767 
   1768     case bcmPTP_MESSAGE_TYPE_DELAY_RESP:
   1769        sequence_id += 2;
   1770        break;
   1771 
   1772     case bcmPTP_MESSAGE_TYPE_PDELAY_RESP:
   1773         sequence_id += 3;
   1774         break;
   1775 
   1776     default:
   1777         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1778                     (BSL_META_U(unit,
   1779                                 "PTP unicast subscribe failed: Unknown message type\n")));
   1780         rv = BCM_E_PARAM;
   1781         goto release_return;
   1782     }
   1783 
   1784     _bcm_ptp_uint16_write(message + PTP_PTPHDR_SEQID_OFFSET_OCTETS, sequence_id);
   1785 
   1786     /* Insert target port identity. */
   1787     rv = bcm_common_ptp_clock_port_identity_get(unit, ptp_id, clock_num, slave_info->peer.local_port_number, &portid);
   1788     if (BCM_FAILURE(rv)) {
   1789         goto release_return;
   1790     }
   1791 
   1792     sal_memcpy(message + PTP_SIGHDR_TGTCLOCK_OFFSET_OCTETS,
   1793                portid.clock_identity, sizeof(bcm_ptp_clock_identity_t));
   1794 
   1795     _bcm_ptp_uint16_write(message + PTP_SIGHDR_TGTPORT_OFFSET_OCTETS, slave_info->peer.local_port_number);
   1796 
   1797     /* Insert TLV type. */
   1798     _bcm_ptp_uint16_write(message + PTP_SIGHDR_SIZE_OCTETS, tlv_type);
   1799 
   1800     /* Insert TLV length. NOTICE: PTP message length, TLV "V" part only. */
   1801     _bcm_ptp_uint16_write(message + PTP_SIGHDR_SIZE_OCTETS + PTP_UCSIG_TLVLEN_OFFSET_OCTETS, (tlv_octets-4));
   1802 
   1803     /*
   1804      * Insert message type.
   1805      * NOTICE: IEEE Std. 1588-2008, Tables 73-75 specify following format for
   1806      *         4-bit message type (messageType).
   1807      *         |B7|B6|B5|B4|B3|B2|B1|B0| =
   1808      *         |messageType|X |X |X |X |. X = Reserved.
   1809      */
   1810     message[PTP_SIGHDR_SIZE_OCTETS + PTP_UCSIG_MSGTYPE_OFFSET_OCTETS] = ((msg_type << 4) & 0xf0);
   1811 
   1812     if (tlv_type == bcmPTPTlvTypeRequestUnicastTransmission) {
   1813         /* REQUEST_UNICAST_TRANSMISSION TLV. */
   1814 
   1815         /* Set log message interval. */
   1816         message[PTP_SIGHDR_SIZE_OCTETS + PTP_UCSIG_INTERVAL_OFFSET_OCTETS] = (uint8)interval;
   1817 
   1818         /* Set message duration. */
   1819         _bcm_ptp_uint32_write(message + PTP_SIGHDR_SIZE_OCTETS + PTP_UCSIG_INTERVAL_OFFSET_OCTETS + 1,
   1820                               PTP_UNICAST_NEVER_EXPIRE);
   1821 
   1822         /* Insert signaling message TLV data. Peer address */
   1823         i = PTP_SIGHDR_SIZE_OCTETS + PTP_UCSIG_ADDRTYPE_OFFSET_OCTETS;
   1824         switch (slave_info->peer.peer_address.addr_type) {
   1825         case bcmPTPUDPIPv4:
   1826             /* Ethernet/UDP/IPv4 address type. */
   1827             message[i++] = bcmPTPUDPIPv4;
   1828             sal_memset(message + i, 0, PTP_MAX_NETW_ADDR_SIZE);
   1829             _bcm_ptp_uint32_write(message + i, slave_info->peer.peer_address.ipv4_addr);
   1830 
   1831             break;
   1832 
   1833         case bcmPTPUDPIPv6:
   1834             /* Ethernet/UDP/IPv6 address type. */
   1835             message[i++] = bcmPTPUDPIPv6;
   1836             sal_memcpy(message + i, slave_info->peer.peer_address.ipv6_addr, sizeof(bcm_ip6_t));
   1837 
   1838             break;
   1839 
   1840         default:
   1841             /* Unknown or unsupported address type. */
   1842             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1843                         (BSL_META_U(unit,
   1844                                     "PTP unicast subscribe failed: Unknown or unsupported address type\n")));
   1845             rv = BCM_E_PARAM;
   1846             goto release_return;
   1847         }
   1848 
   1849         /* Signaling message L2 header length and L2 header. */
   1850         i += PTP_MAX_NETW_ADDR_SIZE;
   1851 
   1852         message[i++] =
   1853             (slave_info->peer.peer_address.raw_l2_header_length > PTP_MAX_L2_HEADER_LENGTH) ?
   1854             (PTP_MAX_L2_HEADER_LENGTH) : (slave_info->peer.peer_address.raw_l2_header_length);
   1855 
   1856         sal_memcpy(message + i,
   1857                    slave_info->peer.peer_address.raw_l2_header,
   1858                    slave_info->peer.peer_address.raw_l2_header_length);
   1859 
   1860         i += slave_info->peer.peer_address.raw_l2_header_length;
   1861 
   1862         /* Add Local address */
   1863         sal_memcpy(message + i, slave_info->local_address.address, PTP_MAX_NETW_ADDR_SIZE);
   1864         i += PTP_MAX_NETW_ADDR_SIZE;
   1865     } else if (tlv_type == bcmPTPTlvTypeCancelUnicastTransmission) {
   1866         /* CANCEL_UNICAST_TRANSMISSION TLV. */
   1867 
   1868         /* Reserved TLV element. */
   1869         message[PTP_SIGHDR_SIZE_OCTETS + PTP_UCSIG_CANCEL_RESERVED_OFFSET_OCTETS] = 0x00;
   1870 
   1871         /*
   1872          * Insert signaling message TLV data.
   1873          *    Peer address.
   1874          */
   1875         i = PTP_SIGHDR_SIZE_OCTETS + PTP_UCSIG_CANCEL_ADDRTYPE_OFFSET_OCTETS;
   1876         switch (slave_info->peer.peer_address.addr_type) {
   1877         case bcmPTPUDPIPv4:
   1878             /* Ethernet/UDP/IPv4 address type. */
   1879             message[i++] = bcmPTPUDPIPv4;
   1880             _bcm_ptp_uint32_write(message + i, slave_info->peer.peer_address.ipv4_addr);
   1881 
   1882             break;
   1883 
   1884         case bcmPTPUDPIPv6:
   1885             /* Ethernet/UDP/IPv6 address type. */
   1886             message[i++] = bcmPTPUDPIPv6;
   1887             sal_memcpy(message + i, slave_info->peer.peer_address.ipv6_addr, sizeof(bcm_ip6_t));
   1888 
   1889             break;
   1890 
   1891         default:
   1892             /* Unknown or unsupported address type. */
   1893             LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1894                         (BSL_META_U(unit,
   1895                                     "PTP unicast subscribe failed: Unknown or unsupported address type\n")));
   1896             rv = BCM_E_PARAM;
   1897             goto release_return;
   1898         }
   1899     }
   1900 
   1901 /*     LOG_CLI((BSL_META_U(unit,
   1902                            "sig_send_tx(len:%d)\n"), message_len)); */
   1903 /*     _bcm_ptp_dump_hex(message, message_len, 0); */
   1904 
   1905     /* Transmit message. */
   1906     rv = stack_p->tx(unit, ptp_id, clock_num, PTP_MESSAGE_TO_TOP, 0, 0, message, message_len);
   1907     if (BCM_FAILURE(rv)) {
   1908         PTP_ERROR_FUNC("tx()");
   1909         goto release_return;
   1910     }
   1911 
   1912     /*
   1913      * NOTICE: This call will return an rx response buffer that we
   1914      *         will own and need to free.
   1915      */
   1916     if (BCM_FAILURE(rv = _bcm_ptp_rx_response_get(unit, ptp_id, clock_num,
   1917             PTP_MGMT_RESPONSE_TIMEOUT_US, &response_data, &response_len))) {
   1918         PTP_ERROR_FUNC("bcmptp_rx_get_response()");
   1919         goto release_return;
   1920     }
   1921 
   1922     rv = BCM_E_FAIL;
   1923 
   1924     /* Parse response. */
   1925     response_tlv_type = _bcm_ptp_uint16_read(response_data +
   1926         PTP_SIGHDR_SIZE_OCTETS);
   1927     if (tlv_type == bcmPTPTlvTypeRequestUnicastTransmission &&
   1928             response_tlv_type != bcmPTPTlvTypeGrantUnicastTransmission) {
   1929         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1930                     (BSL_META_U(unit,
   1931                                 "PTP unicast subscribe failed: Unicast request failed\n")));
   1932         goto dispose_of_resp;
   1933     }
   1934 
   1935     if (tlv_type == bcmPTPTlvTypeCancelUnicastTransmission &&
   1936             response_tlv_type != bcmPTPTlvTypeAckCancelUnicastTransmission) {
   1937         LOG_VERBOSE(BSL_LS_BCM_COMMON,
   1938                     (BSL_META_U(unit,
   1939                                 "PTP unicast subscribe failed: Unicast cancel failed\n")));
   1940         goto dispose_of_resp;
   1941     }
   1942 
   1943     rv = BCM_E_NONE;
   1944 
   1945 dispose_of_resp:
   1946     stack_p->rx_free(unit, ptp_id, response_data);
   1947 
   1948 release_return:
   1949     rvbody = rv;
   1950     if (BCM_FAILURE(rv = _bcm_ptp_sem_give(STACK_DATA(unit, ptp_id).outgoing_available))) {
   1951         PTP_ERROR_FUNC("_bcm_ptp_sem_give()");
   1952     }
   1953 
   1954     return rvbody ? rvbody : rv;
   1955 }
   1956 
   1957 /*
   1958  * Function:
   1959  *      _bcm_ptp_management_domain_get
   1960  * Purpose:
   1961  *      Get the current domain used for PTP management messages for a PTP clock.
   1962  * Parameters:
   1963  *      unit      - (IN)  Unit number.
   1964  *      ptp_id    - (IN)  PTP stack ID.
   1965  *      clock_num - (IN)  PTP clock number.
   1966  *      domain    - (OUT) PTP domain.
   1967  * Returns:
   1968  *      BCM_E_XXX
   1969  * Notes:
   1970  */
   1971 int
   1972 _bcm_ptp_management_domain_get(
   1973     int unit,
   1974     bcm_ptp_stack_id_t ptp_id,
   1975     int clock_num,
   1976     uint8 *domain)
   1977 {
   1978     int rv = BCM_E_UNAVAIL;
   1979 
   1980     rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num, PTP_CLOCK_PORT_NUMBER_DEFAULT);
   1981     if (BCM_FAILURE(rv)) {
   1982         return rv;
   1983     }
   1984 
   1985     if ((unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
   1986         (STACK_DATA(unit, ptp_id).memstate != PTP_MEMSTATE_INITIALIZED)) {
   1987         return BCM_E_UNAVAIL;
   1988     }
   1989 
   1990     *domain = CLOCK_DATA(unit, ptp_id, clock_num).domain;
   1991 
   1992     return rv;
   1993 }
   1994 
   1995 /*
   1996  * Function:
   1997  *      _bcm_ptp_management_domain_set
   1998  * Purpose:
   1999  *      Set the domain to use in PTP management messages for a PTP clock.
   2000  * Parameters:
   2001  *      unit      - (IN) Unit number.
   2002  *      ptp_id    - (IN) PTP stack ID.
   2003  *      clock_num - (IN) PTP clock number.
   2004  *      domain    - (IN) PTP domain.
   2005  * Returns:
   2006  *      BCM_E_XXX
   2007  * Notes:
   2008  */
   2009 int
   2010 _bcm_ptp_management_domain_set(
   2011     int unit,
   2012     bcm_ptp_stack_id_t ptp_id,
   2013     int clock_num,
   2014     uint8 domain)
   2015 {
   2016     int rv = BCM_E_UNAVAIL;
   2017 
   2018     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id, clock_num,
   2019             PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   2020         return rv;
   2021     }
   2022 
   2023     if ((unit_mgmt_array[unit].memstate != PTP_MEMSTATE_INITIALIZED) ||
   2024         (STACK_DATA(unit, ptp_id).memstate != PTP_MEMSTATE_INITIALIZED)) {
   2025         return BCM_E_UNAVAIL;
   2026     }
   2027 
   2028     CLOCK_DATA(unit, ptp_id, clock_num).domain = domain;
   2029 
   2030     return rv;
   2031 }
   2032 
   2033 /*
   2034  * Function:
   2035  *      _bcm_ptp_management_message_create
   2036  * Purpose:
   2037  *      Create a PTP management message from template.
   2038  * Parameters:
   2039  *      message - (IN/OUT) PTP management message.
   2040  * Returns:
   2041  *      BCM_E_XXX
   2042  * Notes:
   2043  */
   2044 static int
   2045 _bcm_ptp_management_message_create(
   2046     uint8 *message)
   2047 {
   2048     int rv = BCM_E_UNAVAIL;
   2049     int i = 0;
   2050 
   2051     /*
   2052      * Management message header
   2053      * NOTICE: Includes L2, VLAN, IPv4, UDP, PTP, and management headers.
   2054      */
   2055     sal_memcpy(message, l2hdr_default, sizeof(l2hdr_default));
   2056     i += sizeof(l2hdr_default);
   2057 
   2058     sal_memcpy(message + i, vlanhdr_default, sizeof(vlanhdr_default));
   2059     i += sizeof(vlanhdr_default);
   2060 
   2061     sal_memcpy(message + i, ethhdr_default, sizeof(ethhdr_default));
   2062     i += sizeof(ethhdr_default);
   2063 
   2064     sal_memcpy(message + i, ipv4hdr_default, sizeof(ipv4hdr_default));
   2065     i += sizeof(ipv4hdr_default);
   2066 
   2067     sal_memcpy(message + i, udphdr_default, sizeof(udphdr_default));
   2068     i += sizeof(udphdr_default);
   2069 
   2070     sal_memcpy(message + i, ptphdr_mgmt, sizeof(ptphdr_mgmt));
   2071     i += sizeof(ptphdr_mgmt);
   2072 
   2073     sal_memcpy(message + i, mgmthdr_mgmt, sizeof(mgmthdr_mgmt));
   2074     i += sizeof(mgmthdr_mgmt);
   2075 
   2076     sal_memcpy(message + i, tlvhdr_mgmt, sizeof(tlvhdr_mgmt));
   2077 
   2078     /* Set L2 header (Ethertype= IPv4). */
   2079     i = PTP_L2HDR_SIZE_OCTETS + PTP_VLANHDR_SIZE_OCTETS;
   2080     message[i++] = 0x08;
   2081     message[i] = 0x00;
   2082 
   2083     /* Update IPv4 header checksum. */
   2084     rv = _bcm_ptp_management_message_ipv4hdr_checksum_set(message);
   2085 
   2086     return rv;
   2087 }
   2088 
   2089 /* /\* */
   2090 /*  * Function: */
   2091 /*  *      _bcm_ptp_management_message_make */
   2092 /*  * Purpose: */
   2093 /*  *      Make a PTP management message. */
   2094 /*  * Parameters: */
   2095 /*  *      message     - (IN/OUT) PTP management message. */
   2096 /*  *      action      - (IN) PTP management action (actionField). */
   2097 /*  *      cmd         - (IN) PTP command (managementId). */
   2098 /*  *      payload     - (IN) PTP management message payload. */
   2099 /*  *      payload_len - (IN) PTP management message payload size (octets). */
   2100 /*  * Returns: */
   2101 /*  *      BCM_E_XXX */
   2102 /*  * Notes: */
   2103 /*  *\/ */
   2104 /* static int  */
   2105 /* _bcm_ptp_management_message_make( */
   2106 /*     uint8 *message,  */
   2107 /*     uint8 action,  */
   2108 /*     uint16 cmd,  */
   2109 /*     uint8 *payload,  */
   2110 /*     int payload_len) */
   2111 /* { */
   2112 /*     int rv = BCM_E_UNAVAIL; */
   2113 /*     int i = 0; */
   2114 
   2115 /*     /\* Set management message action. *\/ */
   2116 /*     i = PTP_MGMTHDR_START_IDX + PTP_MGMTHDR_ACTION_OFFSET_OCTETS; */
   2117 /*     message[i] = action; */
   2118 
   2119 /*     /\*  */
   2120 /*      * Set TLV data. */
   2121 /*      * TLV length.   */
   2122 /*      *\/ */
   2123 /*     i = PTP_MGMTHDR_START_IDX + PTP_MGMTHDR_SIZE_OCTETS +  */
   2124 /*         PTP_TLVHDR_LEN_OFFSET_OCTETS; */
   2125 
   2126 /*     message[i++] = (uint8)((payload_len + PTP_TLVHDR_VAL_PREFIX_SIZE_OCTETS) >> 8); */
   2127 /*     message[i] = (uint8)((payload_len + PTP_TLVHDR_VAL_PREFIX_SIZE_OCTETS) & 0x00ff); */
   2128 
   2129 /*     /\*  */
   2130 /*      * Set TLV data.  */
   2131 /*      * TLV value prefix (management ID/command definition). */
   2132 /*      *\/ */
   2133 /*     i = PTP_MGMTHDR_START_IDX + PTP_MGMTHDR_SIZE_OCTETS +  */
   2134 /*         PTP_TLVHDR_VAL_PREFIX_OFFSET_OCTETS; */
   2135 
   2136 /*     message[i++]= (uint8)((cmd) >> 8); */
   2137 /*     message[i]= (uint8)((cmd) & 0x00ff); */
   2138 
   2139 /*     /\* */
   2140 /*      * Insert payload. */
   2141 /*      * TLV value body. */
   2142 /*      *\/ */
   2143 /*     sal_memcpy(message + PTP_MGMTMSG_TOTAL_HEADER_SIZE, payload, payload_len); */
   2144 
   2145 /*     /\* Update management message header metadata. *\/ */
   2146 /*     rv = _bcm_ptp_management_message_header_metadata_set(message); */
   2147 
   2148 /*     return rv; */
   2149 /* } */
   2150 
   2151 /*
   2152  * Function:
   2153  *      _bcm_ptp_management_message_header_metadata_set
   2154  * Purpose:
   2155  *      Set header lengths and IPv4 checksum based on PTP message payload.
   2156  * Parameters:
   2157  *      message     - (IN/OUT) PTP management message.
   2158  * Returns:
   2159  *      BCM_E_XXX
   2160  * Notes:
   2161  */
   2162 /* static int  */
   2163 /* _bcm_ptp_management_message_header_metadata_set( */
   2164 /*     uint8 *message) */
   2165 /* { */
   2166 /*     int rv = BCM_E_UNAVAIL; */
   2167 
   2168 /*     int tlv_length_pos; */
   2169 /*     uint16 tlv_length; */
   2170 /*     uint16 ptp_length; */
   2171 /*     uint16 udp_length; */
   2172 /*     uint16 ip_length; */
   2173 
   2174 /*     tlv_length_pos = PTP_MGMTHDR_START_IDX + PTP_MGMTHDR_SIZE_OCTETS +  */
   2175 /*                      PTP_TLVHDR_LEN_OFFSET_OCTETS; */
   2176 
   2177 /*     tlv_length = _bcm_ptp_uint16_read(message + tlv_length_pos); */
   2178 /*     ptp_length = tlv_length + PTP_PTPHDR_SIZE_OCTETS + PTP_MGMTHDR_SIZE_OCTETS +  */
   2179 /*                  PTP_TLVHDR_VAL_PREFIX_OFFSET_OCTETS; */
   2180 /*     udp_length = ptp_length + PTP_UDPHDR_SIZE_OCTETS; */
   2181 /*     ip_length = udp_length + PTP_IPV4HDR_SIZE_OCTETS; */
   2182 
   2183 /*     _bcm_ptp_uint16_write(message + PTP_PTPHDR_START_IDX +  */
   2184 /*                           PTP_PTPHDR_MSGLEN_OFFSET_OCTETS, ptp_length); */
   2185 /*     _bcm_ptp_uint16_write(message + PTP_UDPHDR_START_IDX +  */
   2186 /*                           PTP_UDPHDR_MSGLEN_OFFSET_OCTETS, udp_length); */
   2187 /*     _bcm_ptp_uint16_write(message + PTP_IPV4HDR_START_IDX +  */
   2188 /*                           PTP_IPV4HDR_MSGLEN_OFFSET_OCTETS, ip_length); */
   2189 
   2190 /*     /\* Update IPv4 header checksum. *\/ */
   2191 /*     rv = _bcm_ptp_management_message_ipv4hdr_checksum_set(message); */
   2192 
   2193 /*     return rv; */
   2194 /* } */
   2195 
   2196 /*
   2197  * Function:
   2198  *      _bcm_ptp_management_macaddr_set
   2199  * Purpose:
   2200  *      Set MAC addresses in PTP management message.
   2201  * Parameters:
   2202  *      message  - (IN/OUT) PTP management message.
   2203  *      src_mac  - (IN) Source MAC address.
   2204  *      dest_mac - (IN) Destination MAC address.
   2205  * Returns:
   2206  *      BCM_E_XXX
   2207  * Notes:
   2208  */
   2209 static int
   2210 _bcm_ptp_management_message_macaddr_set(
   2211     uint8 *message,
   2212     bcm_mac_t *src_mac,
   2213     bcm_mac_t *dest_mac)
   2214 {
   2215     int i = sizeof(bcm_mac_t);
   2216 
   2217     sal_memcpy(message, dest_mac, i);
   2218     sal_memcpy(message + i, src_mac, i);
   2219 
   2220     return BCM_E_NONE;
   2221 }
   2222 
   2223 /*
   2224  * Function:
   2225  *      _bcm_ptp_management_message_vlantag_set
   2226  * Purpose:
   2227  *      Set VLAN tag in PTP management message.
   2228  * Parameters:
   2229  *      message  - (IN/OUT) PTP management message.
   2230  *      vlan_tag - (IN) VLAN identifier (VID).
   2231  *      prio     - (IN) Priority code point (PCP).
   2232  * Returns:
   2233  *      BCM_E_XXX
   2234  * Notes:
   2235  */
   2236 static int
   2237 _bcm_ptp_management_message_vlantag_set(
   2238     uint8 *message,
   2239     uint16 vlan_tag,
   2240     uint8 prio)
   2241 {
   2242     int i = PTP_L2HDR_SIZE_OCTETS + PTP_VLANHDR_VID_OFFSET_OCTETS;
   2243 
   2244     /*
   2245      * Set VLAN tag.
   2246      * Logically combine VLAN identifier (VID) with priority code point (PCP).
   2247      *
   2248      *    IEEE 802.1Q VLAN tagging 32-bit frame.
   2249      *    |16 Bits|      16 Bits       |
   2250      *    |       |3 Bits|1 Bit|12 Bits|
   2251      *    |TPID   |PCP   |CFI  |VID    |
   2252      */
   2253     message[i++] = (prio << 5) | (0x0f & (vlan_tag >> 8));
   2254     message[i] = (vlan_tag & 0x00ff);
   2255 
   2256     return BCM_E_NONE;
   2257 }
   2258 
   2259 /*
   2260  * Function:
   2261  *      _bcm_ptp_management_message_ipaddr_set
   2262  * Purpose:
   2263  *      Set IP addresses in PTP management message.
   2264  * Parameters:
   2265  *      message - (IN/OUT) PTP management message.
   2266  *      src_ip  - (IN) Source IPv4 address.
   2267  *      dest_ip - (IN) Destination IPv4 address.
   2268  * Returns:
   2269  *      BCM_E_XXX
   2270  * Notes:
   2271  */
   2272 static int
   2273 _bcm_ptp_management_message_ipaddr_set(
   2274     uint8 *message,
   2275     bcm_ip_t src_ip,
   2276     bcm_ip_t dest_ip)
   2277 {
   2278     int rv = BCM_E_UNAVAIL;
   2279     int i = PTP_L2HDR_SIZE_OCTETS + PTP_ETHHDR_SIZE_OCTETS +
   2280             PTP_VLANHDR_SIZE_OCTETS + PTP_IPV4HDR_SRC_IPADDR_OFFSET_OCTETS;
   2281 
   2282     /* Update IPv4 header checksum. */
   2283     if (BCM_FAILURE(rv =
   2284             _bcm_ptp_management_message_ipv4hdr_checksum_set(message))) {
   2285         return rv;
   2286     }
   2287 
   2288     /* Set management message header IP addresses. */
   2289     _bcm_ptp_uint32_write(message + i, src_ip);
   2290     i += sizeof(bcm_ip_t);
   2291     _bcm_ptp_uint32_write(message + i, dest_ip);
   2292 
   2293     return BCM_E_NONE;
   2294 }
   2295 
   2296 /*
   2297  * Function:
   2298  *      _bcm_ptp_management_message_ipv4hdr_checksum_set
   2299  * Purpose:
   2300  *      Set IPv4 header checksum.
   2301  * Parameters:
   2302  *      message - (IN/OUT) PTP management message.
   2303  * Returns:
   2304  *      BCM_E_XXX
   2305  * Notes:
   2306  */
   2307 static int
   2308 _bcm_ptp_management_message_ipv4hdr_checksum_set(
   2309     uint8 *message)
   2310 {
   2311     uint16 chksum;
   2312     int i = PTP_L2HDR_SIZE_OCTETS + PTP_VLANHDR_SIZE_OCTETS +
   2313             PTP_ETHHDR_SIZE_OCTETS;
   2314 
   2315     /*
   2316      * Zero header checksum fields in IPv4 header.
   2317      * Ref. RFC 791, pp. 14.
   2318      */
   2319     message[i+PTP_IPV4HDR_HDR_CHKSUM_OFFSET_OCTETS] = 0x00;
   2320     message[i+PTP_IPV4HDR_HDR_CHKSUM_OFFSET_OCTETS+1] = 0x00;
   2321 
   2322     /* Calculate checksum. */
   2323     chksum = _bcm_ptp_management_rfc791_checksum(message + i,
   2324                                                  PTP_IPV4HDR_SIZE_OCTETS);
   2325 
   2326     /* Insert checksum answer in IPv4 header. */
   2327     message[i+PTP_IPV4HDR_HDR_CHKSUM_OFFSET_OCTETS] = (uint8)((chksum) >> 8);
   2328     message[i+PTP_IPV4HDR_HDR_CHKSUM_OFFSET_OCTETS+1] = (uint8)((chksum) & 0x00ff);
   2329 
   2330     return BCM_E_NONE;
   2331 }
   2332 
   2333 /*
   2334  * Function:
   2335  *      _bcm_ptp_management_message_port_set
   2336  * Purpose:
   2337  *      Set source and destination port numbers in UDP header.
   2338  * Parameters:
   2339  *      message   - (IN/OUT) PTP management message.
   2340  *      src_port  - (IN) Source port number.
   2341  *      dest_port - (IN) Destination port number.
   2342  * Returns:
   2343  *      BCM_E_XXX
   2344  * Notes:
   2345  */
   2346 static int
   2347 _bcm_ptp_management_message_port_set(
   2348     uint8 *message,
   2349     uint16 src_port,
   2350     uint16 dest_port)
   2351 {
   2352     int i = PTP_UDPHDR_START_IDX;
   2353 
   2354     _bcm_ptp_uint16_write(message + i, src_port);
   2355     i += sizeof(uint16);
   2356     _bcm_ptp_uint16_write(message + i, dest_port);
   2357 
   2358     return BCM_E_NONE;
   2359 }
   2360 
   2361 /*
   2362  * Function:
   2363  *      _bcm_ptp_management_message_target_set
   2364  * Purpose:
   2365  *      Set target PTP clock port identity in PTP management message.
   2366  * Parameters:
   2367  *      message        - (IN/OUT) PTP management message.
   2368  *      clock_identity - (IN) Target PTP clock identity.
   2369  *      port_num       - (IN) Target PTP clock port number.
   2370  * Returns:
   2371  *      BCM_E_XXX
   2372  * Notes:
   2373  */
   2374 /* static int  */
   2375 /* _bcm_ptp_management_message_target_set( */
   2376 /*     uint8 *message,  */
   2377 /*     const bcm_ptp_clock_identity_t clock_identity,  */
   2378 /*     uint16 port_num) */
   2379 /* { */
   2380 /*     int i = PTP_MGMTHDR_START_IDX;    */
   2381 
   2382 /*     sal_memcpy(message + i, clock_identity, sizeof(bcm_ptp_clock_identity_t)); */
   2383 /*     i += sizeof(bcm_ptp_clock_identity_t); */
   2384 /*     _bcm_ptp_uint16_write(message + i, port_num); */
   2385 
   2386 /*     return BCM_E_NONE; */
   2387 /* } */
   2388 
   2389 /*
   2390  * Function:
   2391  *      _bcm_ptp_management_message_length_get
   2392  * Purpose:
   2393  *      Get the length of PTP management message.
   2394  * Parameters:
   2395  *      message - (IN)  PTP management message.
   2396  * Returns:
   2397  *      Length.
   2398  * Notes:
   2399  */
   2400 /* static int  */
   2401 /* _bcm_ptp_management_message_length_get( */
   2402 /*     uint8 *message) */
   2403 /* { */
   2404 /*     int len = PTP_MGMTMSG_TOTAL_HEADER_SIZE - PTP_TLVHDR_VAL_PREFIX_SIZE_OCTETS; */
   2405 
   2406 /*     len += _bcm_ptp_uint16_read(message + PTP_MGMTHDR_START_IDX +  */
   2407 /*                                 PTP_MGMTHDR_SIZE_OCTETS +  */
   2408 /*                                 PTP_TLVHDR_LEN_OFFSET_OCTETS); */
   2409 
   2410 /*     return len;    */
   2411 /* } */
   2412 
   2413 #if 0 /* Unused. */
   2414 /*
   2415  * Function:
   2416  *      _bcm_ptp_management_message_domain_get
   2417  * Purpose:
   2418  *      Get the PTP domain in PTP management message.
   2419  * Parameters:
   2420  *      message - (IN)  PTP management message.
   2421  *      domain  - (OUT) PTP domain.
   2422  * Returns:
   2423  *      BCM_E_XXX
   2424  * Notes:
   2425  */
   2426 static int
   2427 _bcm_ptp_management_message_domain_get(
   2428     uint8 *message,
   2429     uint8 *domain)
   2430 {
   2431     *domain = message[PTP_PTPHDR_START_IDX + PTP_PTPHDR_DOMAIN_OFFSET_OCTETS];
   2432     return BCM_E_NONE;
   2433 }
   2434 #endif /* Unused. */
   2435 
   2436 /*
   2437  * Function:
   2438  *      _bcm_ptp_management_message_domain_set
   2439  * Purpose:
   2440  *      Set the PTP domain in PTP management message.
   2441  * Parameters:
   2442  *      message - (IN/OUT) PTP management message.
   2443  *      domain  - (IN) PTP domain.
   2444  * Returns:
   2445  *      BCM_E_XXX
   2446  * Notes:
   2447  */
   2448 int
   2449 _bcm_ptp_management_message_domain_set(
   2450     uint8 *message,
   2451     uint8 domain)
   2452 {
   2453     message[PTP_PTPHDR_START_IDX + PTP_PTPHDR_DOMAIN_OFFSET_OCTETS] = domain;
   2454     return BCM_E_NONE;
   2455 }
   2456 
   2457 /*
   2458  * Function:
   2459  *      _bcm_ptp_management_rfc791_checksum
   2460  * Purpose:
   2461  *      Calculate checksum of a packet per RFC 791.
   2462  * Parameters:
   2463  *      packet     - (IN) Packet.
   2464  *      packet_len - (IN) Packet size (octets).
   2465  * Returns:
   2466  *      Checksum.
   2467  * Notes:
   2468  *      Caller is responsible for zeroing header checksum fields if IPv4
   2469  *      packets are passed to the algorithm.
   2470  */
   2471 static uint16
   2472 _bcm_ptp_management_rfc791_checksum(
   2473     uint8 *packet,
   2474     int packet_len)
   2475 {
   2476     uint32 chksum = 0x00000000;
   2477 
   2478     /*
   2479      * CHECKSUM ALGORITHM: RFC 791, pp 14.
   2480      *
   2481      * "The checksum algorithm is:
   2482      *    The checksum field is the 16 bit one's complement of the one's
   2483      *    complement sum of all 16 bit words in the header. For purposes of
   2484      *    computing the checksum, the value of the checksum field is zero."
   2485      *
   2486      * NOTICE: An equivalent, efficient implementation algorithm enlists
   2487      *         32-bit addition and handles 16-bit overflows (carries) as
   2488      *         a penultimate step.
   2489      */
   2490 
   2491     while (packet_len > 1)
   2492     {
   2493         /* Assemble words from consecutive octets and add to sum. */
   2494         chksum += (uint32)((((uint16)packet[0]) << 8) | (packet[1]));
   2495 
   2496         /*
   2497          * Increment pointer in packet.
   2498          * Decrement remaining size.
   2499          */
   2500         packet += 2;
   2501         packet_len -= 2;
   2502     }
   2503 
   2504     /* Process odd octet. */
   2505     if (packet_len == 1) {
   2506         chksum += (uint32)(((uint16)packet[0]) << 8);
   2507     }
   2508 
   2509     /* Carry(ies). */
   2510     chksum = (chksum >> 16) + (chksum & 0x0000ffff);
   2511 
   2512     /*
   2513      * Result.
   2514      * NOTICE: 16-bit ones complement.
   2515      */
   2516     return (~((uint16)chksum));
   2517 }
   2518 
   2519 
   2520 /*
   2521  * Function:
   2522  *      _bcm_ptp_rfc791_checksum_add_word
   2523  * Purpose:
   2524  *      Calculate incremental checksum
   2525  * Parameters:
   2526  *      prev_checksum - (IN) Previous checksum
   2527  *      add_word      - (IN) word added
   2528  * Returns:
   2529  *      BCM_E_XXX
   2530  * Notes:
   2531  */
   2532 static uint16
   2533 _bcm_ptp_rfc791_checksum_add_word(
   2534     uint16 prev_checksum,
   2535     uint16 add_word)
   2536 {
   2537     uint32 intermediate = 0xffff & ~prev_checksum;
   2538     intermediate += add_word;
   2539     intermediate = (intermediate >> 16) + (intermediate & 0xffff);
   2540 
   2541     return (uint16)~intermediate;
   2542 }
   2543 
   2544 
   2545 /*
   2546  * Function:
   2547  *      _bcm_ptp_construct_udp_packet
   2548  * Purpose:
   2549  *      Construct UDP packet for signaling messages
   2550  * Parameters:
   2551  * Returns:
   2552  *      BCM_E_XXX
   2553  * Notes:
   2554  */
   2555 int
   2556 _bcm_ptp_construct_udp_packet(
   2557     bcm_ptp_clock_peer_t *peer,
   2558     bcm_ptp_clock_port_address_t *local_port,
   2559     uint8* udp_payload,
   2560     int udp_payload_len,
   2561     uint8* packet,
   2562     int *packet_len)
   2563 {
   2564     int ret = BCM_E_NONE;
   2565     int cursor = 0;
   2566     int ip_header_start, ip_checksum_pos;
   2567     int udp_header_start, udp_checksum_pos;
   2568     uint32 checksum;  /* 16 bit checksum, with overhead space for carry bits during computation */
   2569 
   2570     /* L2 Header */
   2571     sal_memcpy(packet, &peer->peer_address.raw_l2_header[0], peer->peer_address.raw_l2_header_length);
   2572     cursor += peer->peer_address.raw_l2_header_length;
   2573 
   2574     ip_header_start = cursor;
   2575 
   2576     switch (peer->peer_address.addr_type) {
   2577     case bcmPTPUDPIPv4:
   2578         packet[cursor++] = 0x45;  /* version */
   2579         packet[cursor++] = 0;     /* TOS */
   2580         _bcm_ptp_uint16_write(&packet[cursor], 20 + 8 + udp_payload_len);  /* Length: IP Hdr, UDP Hdr, payload */
   2581         cursor += 2;
   2582         _bcm_ptp_uint16_write(&packet[cursor], 0); /* ident */
   2583         cursor += 2;
   2584         packet[cursor++] = 0x40;            /* flags: don't fragment */
   2585         packet[cursor++] = 0;               /* fragment offset 0 */
   2586         packet[cursor++] = 64;              /* TTL = 64 */
   2587         packet[cursor++] = 17;              /* Proto = UDP */
   2588         ip_checksum_pos = cursor;
   2589         _bcm_ptp_uint16_write(&packet[cursor], 0); /* checksum (write as 0, then compute) */
   2590         cursor += 2;
   2591 
   2592         packet[cursor++] = local_port->address[0];
   2593         packet[cursor++] = local_port->address[1];
   2594         packet[cursor++] = local_port->address[2];
   2595         packet[cursor++] = local_port->address[3];
   2596 
   2597         _bcm_ptp_uint32_write(&packet[cursor], peer->peer_address.ipv4_addr);
   2598         cursor += 4;
   2599 
   2600         /* calculate and write the IP checksum */
   2601         checksum = _bcm_ptp_management_rfc791_checksum(&packet[ip_header_start], 20);
   2602         _bcm_ptp_uint16_write(&packet[ip_checksum_pos], checksum);
   2603 
   2604         /* UDP header */
   2605         udp_header_start = cursor;
   2606         _bcm_ptp_uint16_write(&packet[cursor], 320);  /* Source Port */
   2607         cursor += 2;
   2608         _bcm_ptp_uint16_write(&packet[cursor], 320);  /* Dest Port */
   2609         cursor += 2;
   2610 
   2611         _bcm_ptp_uint16_write(&packet[cursor], 8 + udp_payload_len);  /* Length: UDP Hdr, payload  */
   2612         cursor += 2;
   2613         _bcm_ptp_uint16_write(&packet[cursor], 0);                /* Checksum: 0 -> no checksum */
   2614         cursor += 2;
   2615 
   2616         sal_memcpy(&packet[cursor], udp_payload, udp_payload_len); /* Payload */
   2617         cursor += udp_payload_len;
   2618         break;
   2619 
   2620     case bcmPTPUDPIPv6:
   2621         packet[cursor++] = 0x6e;  /* version 6, class 0xe0 (high nybble) */
   2622         packet[cursor++] = 0;     /* class 0xe0 (low nybble), flow label 0 */
   2623         packet[cursor++] = 0;     /* flow label 0 */
   2624         packet[cursor++] = 0;     /* flow label 0 */
   2625         _bcm_ptp_uint16_write(&packet[cursor], 8 + udp_payload_len);  /* Length: UDP Hdr, payload (sic, no header len like ipv4) */
   2626         cursor += 2;
   2627         packet[cursor++] = 17;    /* Protocol: UDP */
   2628         packet[cursor++] = 64;    /* Hop Limit (TTL) */
   2629         sal_memcpy(&packet[cursor], &local_port->address[0], 16);
   2630         cursor += 16;
   2631         sal_memcpy(&packet[cursor], &peer->peer_address.ipv6_addr[0], 16);
   2632         cursor += 16;
   2633 
   2634         /* UDP header */
   2635         udp_header_start = cursor;
   2636         _bcm_ptp_uint16_write(&packet[cursor], 320);  /* Source Port */
   2637         cursor += 2;
   2638         _bcm_ptp_uint16_write(&packet[cursor], 320);  /* Dest Port */
   2639         cursor += 2;
   2640 
   2641         _bcm_ptp_uint16_write(&packet[cursor], 8 + udp_payload_len);  /* Length: UDP Hdr, payload   */
   2642         cursor += 2;
   2643         udp_checksum_pos = cursor;
   2644         _bcm_ptp_uint16_write(&packet[cursor], 0);                /* Checksum: 0 during calculation */
   2645         cursor += 2;
   2646 
   2647         sal_memcpy(&packet[cursor], udp_payload, udp_payload_len); /* Payload */
   2648         cursor += udp_payload_len;
   2649 
   2650         /* checksum over addrs, UDP, & payload */
   2651         checksum = _bcm_ptp_management_rfc791_checksum(&packet[udp_header_start - 32], 32 + 8 + udp_payload_len);
   2652         checksum = _bcm_ptp_rfc791_checksum_add_word(checksum, udp_payload_len + 8);  /* UDP header len + len */
   2653         checksum = _bcm_ptp_rfc791_checksum_add_word(checksum, 17);  /* UDP protocol field */
   2654         _bcm_ptp_uint16_write(&packet[udp_checksum_pos], checksum);
   2655 
   2656         break;
   2657 
   2658     default:
   2659         return BCM_E_PARAM;
   2660     }
   2661 
   2662     *packet_len = cursor;
   2663 
   2664     return ret;
   2665 }
   2666 
   2667 /*
   2668  * Function:
   2669  *      _bcm_ptp_construct_signaling_msg
   2670  * Purpose:
   2671  *      Construct the UDP payload for a signaling message,
   2672  *      given the TLV payload for the message
   2673  * Parameters:
   2674  * Returns:
   2675  *      BCM_E_XXX
   2676  * Notes:
   2677  */
   2678 int
   2679 _bcm_ptp_construct_signaling_msg(
   2680     bcm_ptp_port_identity_t *from_port,
   2681     bcm_ptp_clock_identity_t to_clock,
   2682     uint16 to_port,
   2683     int domain,
   2684     uint16 sequenceId,
   2685     uint8* tlv_payload,
   2686     int tlv_payload_len,
   2687     uint8* udp_payload,
   2688     int *udp_payload_len)
   2689 {
   2690     memset(udp_payload, 0, 34);  /* blank PTP header */
   2691     udp_payload[0] = bcmPTP_MESSAGE_TYPE_SIGNALING;
   2692     udp_payload[1] = 2;
   2693     _bcm_ptp_uint16_write(&udp_payload[2], 44 + tlv_payload_len);
   2694     udp_payload[4] = domain;
   2695     udp_payload[6] = 0x04;    /* flags: unicast */
   2696     sal_memcpy(&udp_payload[20], &from_port->clock_identity[0], 8);
   2697     _bcm_ptp_uint16_write(&udp_payload[28], from_port->port_number);
   2698     _bcm_ptp_uint16_write(&udp_payload[30], sequenceId);
   2699     udp_payload[32] = 0x05;   /* control field: all others */
   2700     udp_payload[33] = 0x7f;   /* logMessageInterval: 0x7f */
   2701 
   2702     sal_memcpy(&udp_payload[34], &to_clock[0], 8);
   2703     _bcm_ptp_uint16_write(&udp_payload[42], to_port);
   2704 
   2705     if (NULL != tlv_payload) {
   2706         sal_memcpy(&udp_payload[44], tlv_payload, tlv_payload_len);
   2707     } else {
   2708         tlv_payload_len = 0;
   2709     }
   2710 
   2711     *udp_payload_len = tlv_payload_len + 44;
   2712 
   2713     return BCM_E_NONE;
   2714 }
   2715 
   2716 
   2717 /*
   2718  * Function:
   2719  *      _bcm_ptp_construct_signaling_request_tlv
   2720  * Purpose:
   2721  *      Construct the TLV for a signaling msg request unicast transmission
   2722  * Parameters:
   2723  * Returns:
   2724  *      BCM_E_XXX
   2725  * Notes:
   2726  */
   2727 int
   2728 _bcm_ptp_construct_signaling_request_tlv(
   2729     int type,
   2730     int interval,
   2731     unsigned duration,
   2732     uint8* tlv_payload,
   2733     int *tlv_payload_len)
   2734 {
   2735     tlv_payload[0] = 0;  /* TLV type: */
   2736     tlv_payload[1] = bcmPTPTlvTypeRequestUnicastTransmission;
   2737     tlv_payload[2] = 0;  /* Length: */
   2738     tlv_payload[3] = 6;
   2739     tlv_payload[4] = (type << 4);
   2740     tlv_payload[5] = interval;
   2741     _bcm_ptp_uint32_write(&tlv_payload[6], duration);
   2742 
   2743     *tlv_payload_len = 10;
   2744 
   2745     return BCM_E_NONE;
   2746 }
   2747 
   2748 
   2749 /*
   2750  * Function:
   2751  *      _bcm_ptp_construct_signaling_cancel_tlv
   2752  * Purpose:
   2753  *      Construct the TLV for a signaling msg cancel unicast transmission
   2754  * Parameters:
   2755  * Returns:
   2756  *      BCM_E_XXX
   2757  * Notes:
   2758  */
   2759 int
   2760 _bcm_ptp_construct_signaling_cancel_tlv(
   2761     int type,
   2762     uint8* tlv_payload,
   2763     int *tlv_payload_len)
   2764 {
   2765     tlv_payload[0] = 0;  /* TLV type: */
   2766     tlv_payload[1] = bcmPTPTlvTypeCancelUnicastTransmission;
   2767     tlv_payload[2] = 0;  /* Length: */
   2768     tlv_payload[3] = 2;
   2769     tlv_payload[4] = (type << 4);
   2770     tlv_payload[5] = 0;
   2771 
   2772     *tlv_payload_len = 6;
   2773 
   2774     return BCM_E_NONE;
   2775 }
   2776 
   2777 
   2778 /*
   2779  * Function:
   2780  *      _bcm_ptp_construct_signaling_grant_tlv
   2781  * Purpose:
   2782  *      Construct the TLV for a signaling msg grant unicast transmission
   2783  * Parameters:
   2784  * Returns:
   2785  *      BCM_E_XXX
   2786  * Notes:
   2787  */
   2788 int
   2789 _bcm_ptp_construct_signaling_grant_tlv(
   2790     int type,
   2791     int interval,
   2792     unsigned duration,
   2793     int invite_renewal,
   2794     uint8* tlv_payload,
   2795     int *tlv_payload_len)
   2796 {
   2797     tlv_payload[0] = 0;  /* TLV type: */
   2798     tlv_payload[1] = bcmPTPTlvTypeGrantUnicastTransmission;
   2799     tlv_payload[2] = 0;  /* Length: */
   2800     tlv_payload[3] = 8;
   2801     tlv_payload[4] = (type << 4);
   2802     tlv_payload[5] = interval;
   2803     _bcm_ptp_uint32_write(&tlv_payload[6], duration);
   2804     tlv_payload[10] = 0;
   2805     tlv_payload[11] = invite_renewal;
   2806 
   2807     *tlv_payload_len = 12;
   2808     return BCM_E_NONE;
   2809 }
   2810 
   2811 
   2812 /*
   2813  * Function:
   2814  *      _bcm_ptp_construct_signaling_ack_cancel_tlv
   2815  * Purpose:
   2816  *      Construct the TLV for a signaling msg acknowledge cancel unicast transmission
   2817  * Parameters:
   2818  * Returns:
   2819  *      BCM_E_XXX
   2820  * Notes:
   2821  */
   2822 int
   2823 _bcm_ptp_construct_signaling_ack_cancel_tlv(
   2824     int type,
   2825     uint8* tlv_payload,
   2826     int *tlv_payload_len)
   2827 {
   2828     tlv_payload[0] = 0;  /* TLV type: */
   2829     tlv_payload[1] = bcmPTPTlvTypeAckCancelUnicastTransmission;
   2830     tlv_payload[2] = 0;  /* Length: */
   2831     tlv_payload[3] = 2;
   2832     tlv_payload[4] = (type << 4);
   2833     tlv_payload[5] = 0;
   2834 
   2835     *tlv_payload_len = 6;
   2836 
   2837     return BCM_E_NONE;
   2838 }
   2839 
   2840 
   2841 /*
   2842  * Function:
   2843  *      _bcm_ptp_signaling_message_append_tlv
   2844  * Purpose:
   2845  *      Append a TLV to a PTP signaling message.
   2846  * Parameters:
   2847  *      msg       (IN/OUT) - PTP signaling message.
   2848  *      msgLength (IN/OUT) - PTP signaling message length.
   2849  *      tlv       (IN)     - Signaling message TLV.
   2850  *      tlvLength (IN)     - Signaling message TLV length.
   2851  * Returns:
   2852  *      BCM_E_XXX - Function status.
   2853  * Notes:
   2854  */
   2855 int
   2856 _bcm_ptp_signaling_message_append_tlv(
   2857     uint8 *msg,
   2858     int *msgLength,
   2859     uint8 *tlv,
   2860     int tlvLength)
   2861 {
   2862     /* Argument checking and error handling. */
   2863     if (NULL == tlv) {
   2864         return BCM_E_FAIL;
   2865     }
   2866 
   2867     if ((*msgLength != (int)_bcm_ptp_uint16_read(msg + PTP_PTPHDR_MSGLEN_OFFSET_OCTETS)) ||
   2868         (tlvLength != (int)_bcm_ptp_uint16_read(tlv + PTP_TLVHDR_LEN_OFFSET_OCTETS) + 4)) {
   2869         return BCM_E_PARAM;
   2870     }
   2871 
   2872     /* Append TLV. */
   2873     sal_memcpy(msg + *msgLength, tlv, tlvLength);
   2874 
   2875     /* Update message length. */
   2876     *msgLength += tlvLength;
   2877     _bcm_ptp_uint16_write(msg + PTP_PTPHDR_MSGLEN_OFFSET_OCTETS, (uint16)*msgLength);
   2878 
   2879     return BCM_E_NONE;
   2880 }
   2881 
   2882 
   2883 /*
   2884  * Function:
   2885  *      _bcm_ptp_tunnel_queue_init
   2886  * Purpose:
   2887  *      Initializes the outgoing tunneled message queue
   2888  * Parameters:
   2889  *      unit      - (IN) Unit number.
   2890  *      ptp_id    - (IN) PTP stack ID.
   2891  * Returns:
   2892  *      BCM_E_XXX - Function status.
   2893  * Notes:
   2894  */
   2895 int
   2896 _bcm_ptp_tunnel_queue_init(
   2897     int unit,
   2898     bcm_ptp_stack_id_t ptp_id)
   2899 {
   2900     _bcm_ptp_tunnel_queue_t *queue;
   2901     int rv;
   2902 
   2903     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   2904             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   2905         return rv;
   2906     }
   2907 
   2908     queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].tunnel_queue;
   2909 
   2910     if (!queue->lock) {
   2911         queue->lock = _bcm_ptp_mutex_create("ptp.tunnel");
   2912     }
   2913 
   2914     if (shr_rdpc_callback_created(&queue->rdpc) == BCM_E_INIT) {
   2915         /* RDPC (and associated lock) is left in place on cleanup, so only create it once */
   2916         shr_rdpc_callback_create(&queue->rdpc, &send_pending_tunneled);
   2917     }
   2918 
   2919     queue->head = 0;
   2920     queue->tail = 0;
   2921 
   2922     return BCM_E_NONE;
   2923 }
   2924 
   2925 
   2926 /*
   2927  * Function:
   2928  *      _bcm_ptp_tunnel_queue_cleanup
   2929  * Purpose:
   2930  *      Cleans up the outgoing tunneled message queue for shutdown
   2931  * Parameters:
   2932  *      unit      - (IN) Unit number.
   2933  *      ptp_id    - (IN) PTP stack ID.
   2934  * Returns:
   2935  *      BCM_E_XXX - Function status.
   2936  * Notes:
   2937  */
   2938 int
   2939 _bcm_ptp_tunnel_queue_cleanup(
   2940     int unit,
   2941     bcm_ptp_stack_id_t ptp_id)
   2942 {
   2943     _bcm_ptp_tunnel_queue_t *queue;
   2944     int rv;
   2945 
   2946     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   2947             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   2948         return rv;
   2949     }
   2950 
   2951     queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].tunnel_queue;
   2952 
   2953     shr_rdpc_callback_stop(&queue->rdpc);
   2954 
   2955     PTP_MUTEX_TAKE(queue->lock, PTP_TUNNEL_MESSAGE_TIMEOUT_US);
   2956     queue->head = 0;
   2957     queue->tail = 0;
   2958     PTP_MUTEX_GIVE(queue->lock);
   2959 
   2960     return BCM_E_NONE;
   2961 }
   2962 
   2963 /*
   2964  * Function:
   2965  *      _bcm_ptp_tunnel_queue_add
   2966  * Purpose:
   2967  *      Adds a packet to the outgoing tunnel queue
   2968  * Parameters:
   2969  *      unit        - (IN) Unit number.
   2970  *      ptp_id      - (IN) PTP stack ID.
   2971  *      clock_idx   - (IN) PTP clock index
   2972  *      tunnel_type - (IN) Type of tunneling
   2973  *      hdr_len     - (IN) Length of header
   2974  *      hdr         - (IN) Header data
   2975  *      data_len    - (IN) Length of packet
   2976  *      data        - (IN) packet data
   2977  * Returns:
   2978  *      BCM_E_XXX - Function status.
   2979  * Notes:
   2980  */
   2981 int
   2982 _bcm_ptp_tunnel_queue_add(
   2983     int unit,
   2984     bcm_ptp_stack_id_t ptp_id,
   2985     int clock_idx,
   2986     int tunnel_type,
   2987     unsigned hdr_len,
   2988     uint8 *hdr,
   2989     unsigned data_len,
   2990     uint8 *data)
   2991 {
   2992     const int pkt_overhead = 4;  /* each entry has 1 byte type, 1 byte clock index, 16 bit length */
   2993     int len = hdr_len + data_len;
   2994     int padded_len = (len + 3) & 0xfffc;
   2995     int rv;
   2996     _bcm_ptp_tunnel_queue_t *queue;
   2997 
   2998 
   2999     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   3000             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   3001         return rv;
   3002     }
   3003 
   3004     /* If packet is too large for buffer, just exit */
   3005     if (len > padded_len ||
   3006         padded_len + 2 * pkt_overhead > BCM_PTP_TUNNEL_QUEUE_SIZE) {
   3007         return BCM_E_MEMORY;
   3008     }
   3009 
   3010     queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].tunnel_queue;
   3011     PTP_MUTEX_TAKE(queue->lock, PTP_TUNNEL_MESSAGE_TIMEOUT_US);
   3012 
   3013     /* If this packet won't fit in the remaining space before the end of the buffer, reset the head
   3014        we need space for overhead & packet, plus enough space for an
   3015        extra overhead to indicate that the buffer has wrapped */
   3016     if (queue->head + pkt_overhead + padded_len + pkt_overhead > BCM_PTP_TUNNEL_QUEUE_SIZE) {
   3017         queue->buf[queue->head] = 0;
   3018         queue->head = 0;
   3019     }
   3020 
   3021     if (queue->head < queue->tail &&
   3022         queue->head + pkt_overhead + padded_len + pkt_overhead > queue->tail) {
   3023         /* packet won't fit */
   3024         PTP_MUTEX_RELEASE_RETURN(queue->lock, BCM_E_MEMORY);
   3025     }
   3026     queue->buf[queue->head] = tunnel_type;
   3027     queue->buf[queue->head + 1] = clock_idx;
   3028     _bcm_ptp_uint16_write(queue->buf + queue->head + 2, (uint16)len);
   3029     sal_memcpy(queue->buf + queue->head + pkt_overhead, hdr, hdr_len);
   3030     sal_memcpy(queue->buf + queue->head + pkt_overhead + hdr_len, data, data_len);
   3031     queue->head += pkt_overhead + padded_len;
   3032 
   3033     PTP_MUTEX_GIVE(queue->lock);
   3034 
   3035     rv = shr_rdpc_callback_start(&queue->rdpc, 0, INT_TO_PTR(unit), INT_TO_PTR(ptp_id), INT_TO_PTR(0), INT_TO_PTR(0));
   3036 
   3037     return rv;
   3038 }
   3039 
   3040 
   3041 /*
   3042  * Function:
   3043  *      send_pending_tunneled
   3044  * Purpose:
   3045  *      Send any queued messages to be tunneled
   3046  * Parameters:
   3047  *      arg_unit      - (IN) Unit number (as void**).
   3048  *      arg_ptp_id    - (IN) PTP stack ID (as void**).
   3049  *      unused1       - (IN) Unused.
   3050  *      unused2       - (IN) Unused.
   3051  * Returns:
   3052  *      time interval before next call
   3053  * Notes:
   3054  */
   3055 static sal_usecs_t send_pending_tunneled(void **arg_unit, void **arg_ptp_id, void **unused1, void **unused2)
   3056 {
   3057     int unit = PTR_TO_INT(*arg_unit);
   3058     bcm_ptp_stack_id_t ptp_id = (bcm_ptp_stack_id_t)PTR_TO_INT(*arg_ptp_id);
   3059     int clock_idx, tunnel_type;
   3060     int len, padded_len;
   3061 
   3062     int rv;
   3063     _bcm_ptp_tunnel_queue_t *queue;
   3064     static uint8 buf[PTP_MGMTMSG_TOTAL_SIZE_OCTETS]; /* 1500 bytes */
   3065 
   3066     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   3067             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   3068         return 0;
   3069     }
   3070 
   3071     queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].tunnel_queue;
   3072 
   3073     PTP_MUTEX_TAKE(queue->lock, PTP_TUNNEL_MESSAGE_TIMEOUT_US);
   3074 
   3075     if (queue->buf[queue->tail] == 0) {
   3076         /* zero 'type' signals that it is time to wrap */
   3077         queue->tail = 0;
   3078     }
   3079 
   3080     if (queue->tail == queue->head) {
   3081         /* nothing in queue */
   3082         LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit, "PTP tunnel queue unexpectedly empty\n")));
   3083         PTP_MUTEX_RELEASE_RETURN(queue->lock, 0);
   3084     }
   3085     tunnel_type = queue->buf[queue->tail];
   3086     clock_idx = queue->buf[queue->tail + 1];
   3087     len = _bcm_ptp_uint16_read(queue->buf + queue->tail + 2);
   3088     sal_memcpy(buf, queue->buf + queue->tail + 4, len);
   3089     padded_len = (len + 3) & 0xfffc;
   3090     queue->tail += 4 + padded_len;
   3091     PTP_MUTEX_GIVE(queue->lock);
   3092 
   3093     if (BCM_FAILURE(rv = _bcm_ptp_tunnel_message(unit, ptp_id, clock_idx, tunnel_type, 0, 0, len, buf))) {
   3094         LOG_WARN(BSL_LS_BCM_PTP, (BSL_META_U(unit, "PTP delayed tunnel send failed\n")));
   3095     }
   3096     return 0;
   3097 }
   3098 /*
   3099  * Function:
   3100  *      _bcm_ptp_timestamp_queue_init
   3101  * Purpose:
   3102  *      Initializes the timestamp message queue
   3103  * Parameters:
   3104  *      unit      - (IN) Unit number.
   3105  *      ptp_id    - (IN) PTP stack ID.
   3106  * Returns:
   3107  *      BCM_E_XXX - Function status.
   3108  * Notes:
   3109  */
   3110 int
   3111 _bcm_ptp_timestamp_queue_init(
   3112     int unit,
   3113     bcm_ptp_stack_id_t ptp_id)
   3114 {
   3115     _bcm_ptp_timestamp_queue_t *queue;
   3116     int rv;
   3117 
   3118     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   3119             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   3120         return rv;
   3121     }
   3122 
   3123     queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].timestamp_queue;
   3124 
   3125     if (!queue->lock) {
   3126         queue->lock = _bcm_ptp_mutex_create("ptp.tsqueue");
   3127         if (queue->lock == NULL) {
   3128           bsl_printf("_bcm_ptp_timestamp_queue_init error\n");   
   3129           return BCM_E_MEMORY;
   3130         }
   3131     }
   3132     
   3133     queue->ts_list = (_bcm_ptp_timestamp_list_t *)sal_alloc(BCM_PTP_TIMESTAMP_QUEUE_SIZE * sizeof(_bcm_ptp_timestamp_list_t),
   3134                                          "PTP Timestamp List");
   3135     sal_memset(queue->ts_list, 0, sizeof(_bcm_ptp_timestamp_list_t) * BCM_PTP_TIMESTAMP_QUEUE_SIZE);
   3136    
   3137     bsl_printf("_bcm_ptp_timestamp_queue_t initiatilzed...................... \n");
   3138 
   3139     if (shr_rdpc_callback_created(&queue->rdpc) == BCM_E_INIT) {
   3140         /* RDPC (and associated lock) is left in place on cleanup, so only create it once */
   3141         shr_rdpc_callback_create(&queue->rdpc, &send_pending_timestamp);
   3142     }
   3143 
   3144     queue->head = -1;
   3145     queue->tail = -1;
   3146 
   3147     return BCM_E_NONE;
   3148 }
   3149 
   3150 
   3151 /*
   3152  * Function:
   3153  *      _bcm_ptp_timestamp_queue_cleanup
   3154  * Purpose:
   3155  *      Cleans up the outgoing timestamp queue for shutdown
   3156  * Parameters:
   3157  *      unit      - (IN) Unit number.
   3158  *      ptp_id    - (IN) PTP stack ID.
   3159  * Returns:
   3160  *      BCM_E_XXX - Function status.
   3161  * Notes:
   3162  */
   3163 int
   3164 _bcm_ptp_timestamp_queue_cleanup(
   3165     int unit,
   3166     bcm_ptp_stack_id_t ptp_id)
   3167 {
   3168     _bcm_ptp_timestamp_queue_t *queue;
   3169     _bcm_ptp_timestamp_list_t *tsList;
   3170     int idx = 0;
   3171     int rv;
   3172 
   3173     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   3174             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   3175         return rv;
   3176     }
   3177 
   3178     queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].timestamp_queue;
   3179 
   3180     shr_rdpc_callback_stop(&queue->rdpc);
   3181 
   3182     PTP_MUTEX_TAKE(queue->lock, PTP_TIMESTAMP_MESSAGE_TIMEOUT_US);
   3183     
   3184     tsList = queue->ts_list;
   3185     
   3186     bsl_printf("_bcm_ptp_timestamp_queue_t cleanup...................... \n");
   3187 
   3188     while(idx < BCM_PTP_TIMESTAMP_QUEUE_SIZE) {
   3189         if((tsList +idx)->data != NULL) {
   3190             sal_free((void *)((tsList + idx)->data));
   3191             (tsList + idx)->data = NULL;
   3192         }
   3193         idx++;
   3194     }
   3195     queue->head = -1;
   3196     queue->tail = -1;
   3197     sal_free((void *)tsList);
   3198     queue->ts_list = NULL;
   3199 
   3200     PTP_MUTEX_GIVE(queue->lock);
   3201 
   3202     return BCM_E_NONE;
   3203 }
   3204 
   3205 /*
   3206  * Function:
   3207  *      _bcm_ptp_timestamp_queue_add
   3208  * Purpose:
   3209  *      Adds a packet to the outgoing timestamp queue
   3210  * Parameters:
   3211  *      unit        - (IN) Unit number.
   3212  *      ptp_id      - (IN) PTP stack ID.
   3213  *      clock_idx   - (IN) PTP clock index
   3214  *      tunnel_type - (IN) Type of tunneling
   3215  *      hdr_len     - (IN) Length of header
   3216  *      hdr         - (IN) Header data
   3217  *      data_len    - (IN) Length of packet
   3218  *      data        - (IN) packet data
   3219  * Returns:
   3220  *      BCM_E_XXX - Function status.
   3221  * Notes:
   3222  */
   3223 int
   3224 _bcm_ptp_timestamp_queue_add(
   3225     int unit,
   3226     bcm_ptp_stack_id_t ptp_id,
   3227     int clock_idx,
   3228     unsigned data_len,
   3229     uint8 *data)
   3230 {
   3231     int rv;
   3232     _bcm_ptp_timestamp_queue_t *queue;
   3233     _bcm_ptp_timestamp_node_t *node;
   3234     _bcm_ptp_timestamp_list_t *tsList;
   3235 
   3236     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   3237             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   3238         return rv;
   3239     }
   3240 
   3241     /* If packet is too large for buffer, just exit */
   3242     if (data_len > sizeof(_bcm_ptp_timestamp_node_t)) {
   3243         return BCM_E_MEMORY;
   3244     }
   3245 
   3246     queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].timestamp_queue;
   3247 
   3248     if (queue->lock == NULL) {
   3249       bsl_printf("_bcm_ptp_timestamp_queue_add error\n");   
   3250       return BCM_E_MEMORY;
   3251     }
   3252     
   3253     PTP_MUTEX_TAKE(queue->lock, PTP_TIMESTAMP_MESSAGE_TIMEOUT_US);
   3254 
   3255     tsList = queue->ts_list;
   3256     
   3257     /* If this is last node set it to null and Wrap the list */
   3258     if ((queue->head == 0 && queue->tail == (BCM_PTP_TIMESTAMP_QUEUE_SIZE -1)) ||
   3259                 queue->tail == (queue->head - 1) % (BCM_PTP_TIMESTAMP_QUEUE_SIZE -1)) {
   3260 #ifdef PTP_EXT_SERVO_DEBUG
   3261         bsl_printf("Queue FULL %s,%d\n",__FUNCTION__,__LINE__);
   3262 #endif
   3263     } else {
   3264         /* Copy the Data in Node */
   3265         node = (_bcm_ptp_timestamp_node_t *)sal_alloc(sizeof(_bcm_ptp_timestamp_node_t), "PTP Timestamp node");
   3266         if (node == NULL) {
   3267             PTP_MUTEX_GIVE(queue->lock);
   3268             bsl_printf("%s,%d\n",__FUNCTION__,__LINE__);
   3269             return BCM_E_MEMORY;
   3270         }
   3271         sal_memcpy(node, data, data_len);
   3272 
   3273         if (queue->head == -1) {
   3274             queue->head = 0;
   3275             queue->tail = 0;
   3276         } else if (queue->tail == BCM_PTP_TIMESTAMP_QUEUE_SIZE - 1 && queue->head != 0) {
   3277             queue->tail = 0;
   3278         } else {
   3279             queue->tail++;
   3280         }
   3281         (tsList + queue->tail)->data = node;
   3282     }
   3283 
   3284     PTP_MUTEX_GIVE(queue->lock);
   3285 
   3286     rv = shr_rdpc_callback_start(&queue->rdpc, 0, INT_TO_PTR(unit), INT_TO_PTR(ptp_id), INT_TO_PTR(0), INT_TO_PTR(0));
   3287 
   3288     return rv;
   3289 }
   3290 
   3291 /*
   3292  * Function:
   3293  *      send_pending_timestamp
   3294  * Purpose:
   3295  *      Send any queued timestamps to servo
   3296  * Parameters:
   3297  *      arg_unit      - (IN) Unit number (as void**).
   3298  *      t
   3299  *      q
   3300  *      arg_ptp_id    - (IN) PTP stack ID (as void**).
   3301  *      unused1       - (IN) Unused.
   3302  *      unused2       - (IN) Unused.
   3303  * Returns:
   3304  *      time interval before next call
   3305  * Notes:
   3306  */
   3307 static sal_usecs_t send_pending_timestamp(void **arg_unit, void **arg_ptp_id, void **unused1, void **unused2)
   3308 {
   3309     int unit = PTR_TO_INT(*arg_unit);
   3310     bcm_ptp_stack_id_t ptp_id = (bcm_ptp_stack_id_t)PTR_TO_INT(*arg_ptp_id);
   3311     _bcm_ptp_timestamp_list_t *tsList;
   3312 
   3313     int rv;
   3314     _bcm_ptp_timestamp_queue_t *queue;
   3315 
   3316 
   3317     if (BCM_FAILURE(rv = _bcm_ptp_function_precheck(unit, ptp_id,
   3318             PTP_CLOCK_NUMBER_DEFAULT, PTP_CLOCK_PORT_NUMBER_DEFAULT))) {
   3319         return 0;
   3320     }
   3321 
   3322     queue = &_bcm_common_ptp_info[unit].stack_info[ptp_id].timestamp_queue;
   3323 
   3324     PTP_MUTEX_TAKE(queue->lock, PTP_TIMESTAMP_MESSAGE_TIMEOUT_US);
   3325 #ifdef BCM_PTP_EXT_SERVO_SUPPORT
   3326     mbox_tsevent_stats.ts_rpc_livecount++;
   3327 #endif
   3328     
   3329     tsList = queue->ts_list;
   3330     while(queue->head != -1 && (tsList + queue->head)->data != NULL)
   3331     {
   3332 #ifdef BCM_PTP_EXT_SERVO_SUPPORT
   3333         _bcm_ptp_ext_servo_event_t event_type;
   3334         int num_TS;
   3335         uint8 *ptr = NULL;
   3336         bcm_ptp_port_identity_t master_portId, best_master_portId;
   3337         bcm_ptp_clock_port_address_t master_portaddr;
   3338         bcm_ptp_timestamp_t first_TS = { 0, 0 };
   3339         uint32 int_usec=0;
   3340         int8 log_interval=10;
   3341         int is_unicast=0;
   3342         int i = 0;
   3343         uint64 temp_ts = 0;
   3344         bcm_ptp_clock_info_t *clock_info;
   3345         bcm_ptp_port_identity_t clk_portid;
   3346 
   3347 
   3348         mbox_tsevent_stats.event_dequeued++;
   3349 
   3350         event_type = _bcm_ptp_uint16_read((uint8 *)(tsList + queue->head)->data);
   3351 
   3352         switch ((_bcm_ptp_ext_servo_event_t)event_type) {
   3353             case _bcm_ptp_ext_servo_downlink_ts_event:
   3354             case _bcm_ptp_ext_servo_uplink_ts_event:
   3355 #if 0
   3356                 node = (_bcm_ptp_timestamp_node_t *) ((int8 *)(tsList + queue->head)->data + sizeof(uint16));
   3357                 bsl_printf("clockIdentity : %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",node->portId.clock_identity[0],
   3358                                          node->portId.clock_identity[1],
   3359                                          node->portId.clock_identity[2],
   3360                                          node->portId.clock_identity[3],
   3361                                          node->portId.clock_identity[4],
   3362                                          node->portId.clock_identity[5],
   3363                                          node->portId.clock_identity[6],
   3364                                         node->portId.clock_identity[7]);
   3365                 bsl_printf("portNumber                   : %u\n",node->portId.port_number);
   3366                 bsl_printf("msgSeqId                     : %d\n",node->msgSeqId);
   3367                 bsl_printf("flags                        : %d\n",node->flags);
   3368                 bsl_printf("numTs                        : %d\n",node->numTs);
   3369                 bsl_printf("tsType                       : %d\n",node->tsType);
   3370                 bsl_printf("DL TS: \n");
   3371                 for(idx =0; idx < node->numTs; idx++)
   3372                     bsl_printf("%lld ", (long long int)node->tsDiff[idx]);
   3373                 bsl_printf("\n");
   3374 #endif
   3375                 ptr =  ((uint8 *)(tsList + queue->head)->data + sizeof(uint16));
   3376 
   3377 #ifdef PTP_EXT_SERVO_DEBUG
   3378                 bsl_printf(" _bcm_ptp_ext_servo_up/downlink_ts_event:: \n");
   3379                 _bcm_ptp_dump_hex(ptr, 320, 0);
   3380 #endif
   3381                 sal_memcpy(&master_portId.clock_identity, ptr, sizeof(bcm_ptp_clock_identity_t));
   3382                 master_portId.port_number = _bcm_ptp_uint16_read(ptr+8);
   3383                 num_TS = _bcm_ptp_uint16_read(ptr+14);
   3384 
   3385                 log_interval= ptr[16];
   3386                 int_usec = _bcm_ptp_servo_usecintv_get(log_interval);
   3387 
   3388                 first_TS.seconds = _bcm_ptp_uint64_read(ptr+20);
   3389                 first_TS.nanoseconds = _bcm_ptp_uint32_read(ptr+28);
   3390 
   3391                 LOG_DEBUG(BSL_LS_BCM_PTP,
   3392                     (BSL_META_U(unit, "[UL:%d] master_portId: [%02x %02x %02x %02x %02x %02x %02x %02x : %d] numTs[%d] log_int[%d] first_TS[0x%016llx / %llds.%uns]\n"),
   3393                     event_type,
   3394                     master_portId.clock_identity[0], master_portId.clock_identity[1], master_portId.clock_identity[2], master_portId.clock_identity[3],
   3395                     master_portId.clock_identity[4], master_portId.clock_identity[5], master_portId.clock_identity[6], master_portId.clock_identity[7],
   3396                     master_portId.port_number, num_TS, log_interval,
   3397                     (long long signed int)first_TS.seconds,
   3398                     (long long signed int)first_TS.seconds, first_TS.nanoseconds));
   3399 
   3400 #ifdef BCM_PTP_EXT_SERVO_ABS_TS_SUPPORT
   3401                 /* absolute timestamps */
   3402                 if (event_type == _bcm_ptp_ext_servo_downlink_ts_event)
   3403                     _bcm_ptp_servo_AddFullTimestamps(unit, ptp_id, 0, &master_portId, num_TS, ptr + PTP_EXT_SERVO_TS_OFFSET, _bcm_ptp_ts_type_downlink, int_usec);
   3404                 else
   3405                     _bcm_ptp_servo_AddFullTimestamps(unit, ptp_id, 0, &master_portId, num_TS, ptr + PTP_EXT_SERVO_TS_OFFSET, _bcm_ptp_ts_type_uplink, int_usec);
   3406 #else 
   3407                 /* timestamp differences */
   3408                 if (event_type == _bcm_ptp_ext_servo_downlink_ts_event) {
   3409                     rv = _bcm_ptp_servo_AddTimestampDiffs(unit, ptp_id, 0, &master_portId, num_TS, first_TS, ptr + PTP_EXT_SERVO_TS_OFFSET, _bcm_ptp_ts_type_downlink, int_usec);
   3410                 } else {
   3411                     rv = _bcm_ptp_servo_AddTimestampDiffs(unit, ptp_id, 0, &master_portId, num_TS, first_TS, ptr + PTP_EXT_SERVO_TS_OFFSET, _bcm_ptp_ts_type_uplink, int_usec);
   3412                 }
   3413 
   3414 #endif /* BCM_PTP_EXT_SERVO_ABS_TS_SUPPORT */
   3415                 break;
   3416 
   3417             case _bcm_ptp_ext_servo_master_change_event:
   3418 
   3419                 clock_info = &_bcm_common_ptp_unit_array[unit].stack_array[ptp_id].clock_array[0].clock_info;
   3420 
   3421                 sal_memcpy(&clk_portid.clock_identity, &clock_info->clock_identity, sizeof(bcm_ptp_clock_identity_t));
   3422                 clk_portid.port_number = 0;
   3423 
   3424                 ptr =  ((uint8 *)(tsList + queue->head)->data + sizeof(uint16));
   3425 #ifdef PTP_EXT_SERVO_DEBUG
   3426                 bsl_printf(" _bcm_ptp_ext_servo_master_change_event: \n");
   3427 				_bcm_ptp_dump_hex(ptr, 64, 0);
   3428 #endif
   3429                 LOG_INFO(BSL_LS_BCM_PTP,
   3430                         (BSL_META_U(unit, " _bcm_ptp_ext_servo_master_change_event: \n")));
   3431                 mbox_tsevent_stats.event_master_change++;
   3432 
   3433                 /* Retrieve best master port Id */
   3434                 sal_memcpy(&best_master_portId.clock_identity, ptr+13, sizeof(bcm_ptp_clock_identity_t));
   3435                 best_master_portId.port_number = _bcm_ptp_uint16_read(ptr+21);
   3436 
   3437                 LOG_INFO(BSL_LS_BCM_PTP,
   3438                     (BSL_META_U(unit, "best_master_portId: [%02x %02x %02x %02x %02x %02x %02x %02x : %d] \n"),
   3439                     best_master_portId.clock_identity[0], best_master_portId.clock_identity[1],
   3440                     best_master_portId.clock_identity[2], best_master_portId.clock_identity[3],
   3441                     best_master_portId.clock_identity[4], best_master_portId.clock_identity[5],
   3442                     best_master_portId.clock_identity[6], best_master_portId.clock_identity[7],
   3443                     best_master_portId.port_number));
   3444 
   3445                 if (g_apts_enabled)
   3446                 {
   3447                     bcm_ptp_clock_apts_mode_t old_op_mode = g_apts_current_op_mode;
   3448 
   3449                     if (_bcm_ptp_peer_portid_compare(&best_master_portId, &clk_portid)) {
   3450                         /* Set PTP source as unavailable */
   3451                         g_apts_current_source_state &= _bcm_ptp_apts_avail_gps_synce;
   3452                         _bcm_ptp_apts_update_current_mode();
   3453 
   3454                         if (((old_op_mode == bcmPtpClockAptsModePtpPtp) || (old_op_mode == bcmPtpClockAptsModeSyncEPtp)) &&
   3455                                 ((g_apts_current_op_mode == bcmPtpClockAptsModeSyncEGps) || (g_apts_current_op_mode == bcmPtpClockAptsModeGpsGps)))
   3456                         {
   3457                             /* Switched from PTP to GPS - update servo with GPS as best master */
   3458                             if (BCM_FAILURE(rv = _bcm_ptp_servo_best_master_update(unit, ptp_id, 0, &g_gps_port_id)))
   3459                             {
   3460                                 PTP_ERROR_FUNC("_bcm_ptp_servo_best_master_update() - GPS");
   3461                             }
   3462                         }
   3463                     } else {
   3464                         /* Set PTP source as available */
   3465                         g_apts_current_source_state |= _bcm_ptp_apts_avail_ptp;
   3466                         _bcm_ptp_apts_update_current_mode();
   3467 
   3468                         if ((g_apts_current_op_mode == bcmPtpClockAptsModeSyncEGps) || (g_apts_current_op_mode == bcmPtpClockAptsModeGpsGps))
   3469                         {
   3470                             /* GPS is best master currently. Do not update IDT servo */
   3471                             LOG_INFO(BSL_LS_BCM_PTP,
   3472                                 (BSL_META_U(unit, "[APTS]: PTP best master changed but current mode requires servo to track GPS")));
   3473                         } else if (BCM_FAILURE(rv = _bcm_ptp_servo_best_master_update(unit, ptp_id, 0, &best_master_portId))) {
   3474                             PTP_ERROR_FUNC("_bcm_ptp_servo_best_master_update()");
   3475                         }
   3476                     }
   3477                     g_ptp_best_master_portId = best_master_portId;
   3478                 }
   3479                 else if (BCM_FAILURE(rv = _bcm_ptp_servo_best_master_update(unit, ptp_id, 0, &best_master_portId))) {
   3480                     PTP_ERROR_FUNC("_bcm_ptp_servo_best_master_update()");
   3481                 }
   3482                 break;
   3483 
   3484             case _bcm_ptp_ext_servo_master_avail_event:
   3485             case _bcm_ptp_ext_servo_master_unavail_event:
   3486 
   3487                 ptr =  ((uint8 *)(tsList + queue->head)->data + sizeof(uint16));
   3488 #ifdef PTP_EXT_SERVO_DEBUG
   3489                 bsl_printf(" _bcm_ptp_ext_servo_master_avail/unavail_event \n");
   3490 				_bcm_ptp_dump_hex(ptr, 64, 0);
   3491 #endif
   3492 
   3493                 /* Retrieve master port Id */
   3494                 sal_memcpy(&master_portId.clock_identity, ptr+13, sizeof(bcm_ptp_clock_identity_t));
   3495                 master_portId.port_number = _bcm_ptp_uint16_read(ptr+21);
   3496 
   3497                 is_unicast = ptr[24];
   3498 
   3499                 master_portaddr.addr_type =  ptr[25];
   3500                 memset(master_portaddr.address, 0, BCM_PTP_MAX_NETW_ADDR_SIZE);
   3501                 memcpy(master_portaddr.address, ptr+28, BCM_PTP_MAX_NETW_ADDR_SIZE);
   3502 
   3503                 /* Retrieve best master port Id */
   3504                 sal_memcpy(&best_master_portId.clock_identity, ptr+48, sizeof(bcm_ptp_clock_identity_t));
   3505                 best_master_portId.port_number = _bcm_ptp_uint16_read(ptr+56);
   3506 
   3507                 LOG_INFO(BSL_LS_BCM_PTP,
   3508 				    (BSL_META_U(unit, " %s \n"),
   3509                     (event_type == _bcm_ptp_ext_servo_master_avail_event)? "_bcm_ptp_ext_servo_master_avail_event:":"_bcm_ptp_ext_servo_master_unavail_event:"));
   3510                 LOG_INFO(BSL_LS_BCM_PTP,
   3511 				    (BSL_META_U(unit, "master_portId: [%02x %02x %02x %02x %02x %02x %02x %02x : %d] unicast[%d]\n"),
   3512                     master_portId.clock_identity[0], master_portId.clock_identity[1],
   3513                     master_portId.clock_identity[2], master_portId.clock_identity[3],
   3514                     master_portId.clock_identity[4], master_portId.clock_identity[5],
   3515                     master_portId.clock_identity[6], master_portId.clock_identity[7],
   3516                     master_portId.port_number, is_unicast));
   3517                 LOG_INFO(BSL_LS_BCM_PTP,
   3518 				    (BSL_META_U(unit, "master_portAddr: [%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x : AddrType:%d]\n"),
   3519                     master_portaddr.address[0], master_portaddr.address[1],master_portaddr.address[2], master_portaddr.address[3],
   3520                     master_portaddr.address[4], master_portaddr.address[5],master_portaddr.address[6], master_portaddr.address[7],
   3521                     master_portaddr.address[8], master_portaddr.address[9],master_portaddr.address[10], master_portaddr.address[11],
   3522                     master_portaddr.address[12], master_portaddr.address[13],master_portaddr.address[14], master_portaddr.address[5],
   3523                     master_portaddr.addr_type));
   3524                 LOG_INFO(BSL_LS_BCM_PTP,
   3525                     (BSL_META_U(unit, "best_master_portId: [%02x %02x %02x %02x %02x %02x %02x %02x : %d] \n"),
   3526                     best_master_portId.clock_identity[0], best_master_portId.clock_identity[1],
   3527                     best_master_portId.clock_identity[2], best_master_portId.clock_identity[3],
   3528                     best_master_portId.clock_identity[4], best_master_portId.clock_identity[5],
   3529                     best_master_portId.clock_identity[6], best_master_portId.clock_identity[7],
   3530                     best_master_portId.port_number));
   3531 
   3532                 if (event_type == _bcm_ptp_ext_servo_master_avail_event) {
   3533                     mbox_tsevent_stats.event_master_add++;
   3534                     if (BCM_FAILURE(rv = _bcm_ptp_servo_master_add(unit, ptp_id, 0, PTP_EXT_SERVO_MSTR_INST_UNKNOWN,
   3535 							                  &master_portId,
   3536 							                  &master_portaddr, is_unicast, 127))) {
   3537                         PTP_ERROR_FUNC("_bcm_ptp_servo_master_add()");
   3538                     }
   3539                 } else if(event_type == _bcm_ptp_ext_servo_master_unavail_event) {
   3540                     mbox_tsevent_stats.event_master_remove++;
   3541                     if (BCM_FAILURE(rv = _bcm_ptp_servo_master_remove(unit, ptp_id, 0,PTP_EXT_SERVO_MSTR_INST_UNKNOWN,
   3542                                               is_unicast,
   3543 							                  &master_portId,
   3544 							                  &best_master_portId, &master_portaddr))) {
   3545                         PTP_ERROR_FUNC("_bcm_ptp_servo_master_remove()");
   3546                     }
   3547                 }
   3548                 break;
   3549             case _bcm_ptp_ext_servo_gps_avail_event:
   3550             case _bcm_ptp_ext_servo_gps_unavail_event:
   3551                 is_unicast = 1;
   3552 
   3553                 LOG_INFO(BSL_LS_BCM_PTP,
   3554                     (BSL_META_U(unit, " %s \n"),
   3555                     (event_type == _bcm_ptp_ext_servo_gps_avail_event)? "_bcm_ptp_ext_servo_gps_avail_event:":"_bcm_ptp_ext_servo_gps_unavail_event:"));
   3556 
   3557                 LOG_INFO(BSL_LS_BCM_PTP,
   3558                     (BSL_META_U(unit, "gps master_portId: [%02x %02x %02x %02x %02x %02x %02x %02x : %d] unicast[%d]\n"),
   3559                     g_gps_port_id.clock_identity[0], g_gps_port_id.clock_identity[1],
   3560                     g_gps_port_id.clock_identity[2], g_gps_port_id.clock_identity[3],
   3561                     g_gps_port_id.clock_identity[4], g_gps_port_id.clock_identity[5],
   3562                     g_gps_port_id.clock_identity[6], g_gps_port_id.clock_identity[7],
   3563                     g_gps_port_id.port_number, is_unicast));
   3564                 LOG_INFO(BSL_LS_BCM_PTP,
   3565                     (BSL_META_U(unit, "gps master_portAddr: [%02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x : AddrType:%d]\n"),
   3566                     g_gps_port_address.address[0], g_gps_port_address.address[1],g_gps_port_address.address[2], g_gps_port_address.address[3],
   3567                     g_gps_port_address.address[4], g_gps_port_address.address[5],g_gps_port_address.address[6], g_gps_port_address.address[7],
   3568                     g_gps_port_address.address[8], g_gps_port_address.address[9],g_gps_port_address.address[10], g_gps_port_address.address[11],
   3569                     g_gps_port_address.address[12], g_gps_port_address.address[13],g_gps_port_address.address[14], g_gps_port_address.address[5],
   3570                     g_gps_port_address.addr_type));
   3571 
   3572                 if (event_type == _bcm_ptp_ext_servo_gps_avail_event)
   3573                 {
   3574                     if (BCM_FAILURE(rv = _bcm_ptp_servo_master_add(unit, ptp_id, 0, PTP_EXT_SERVO_MSTR_INST_UNKNOWN,
   3575                                                                   &g_gps_port_id,
   3576                                                                   &g_gps_port_address, is_unicast, 127))) {
   3577                         PTP_ERROR_FUNC("_bcm_ptp_servo_master_add() - GPS");
   3578                     }
   3579 
   3580                     g_apts_current_source_state |= _bcm_ptp_apts_avail_gps;
   3581                     _bcm_ptp_apts_update_current_mode();
   3582 
   3583                     if ((g_apts_current_op_mode == bcmPtpClockAptsModeSyncEGps) || (g_apts_current_op_mode == bcmPtpClockAptsModeGpsGps))
   3584                     {
   3585                         if (BCM_FAILURE(rv = _bcm_ptp_servo_best_master_update(unit, ptp_id, 0, &g_gps_port_id))){
   3586                             PTP_ERROR_FUNC("_bcm_ptp_servo_best_master_update() - GPS");
   3587                         }
   3588                     }
   3589                 } else if(event_type == _bcm_ptp_ext_servo_gps_unavail_event)
   3590                 {
   3591                     if (BCM_FAILURE(rv = _bcm_ptp_servo_master_remove(unit, ptp_id, 0,PTP_EXT_SERVO_MSTR_INST_UNKNOWN,
   3592                                               is_unicast,
   3593                                               &g_gps_port_id,
   3594                                               &g_gps_port_id, &g_gps_port_address))) {
   3595                         PTP_ERROR_FUNC("_bcm_ptp_servo_master_remove() - GPS");
   3596                     }
   3597 
   3598                     g_apts_current_source_state &= _bcm_ptp_apts_avail_ptp_synce;
   3599                     _bcm_ptp_apts_update_current_mode();
   3600 
   3601                     if ((g_apts_current_op_mode == bcmPtpClockAptsModeSyncEPtp) || (g_apts_current_op_mode == bcmPtpClockAptsModePtpPtp))
   3602                     {
   3603                         if (BCM_FAILURE(rv = _bcm_ptp_servo_best_master_update(unit, ptp_id, 0, &g_ptp_best_master_portId))){
   3604                             PTP_ERROR_FUNC("_bcm_ptp_servo_best_master_update() - GPS is down. Switching to PTP");
   3605                         }
   3606                     }
   3607                 }
   3608                 break;
   3609             case _bcm_ptp_ext_servo_gps_ts_event:
   3610                 if (g_apts_current_source_state & _bcm_ptp_apts_avail_gps)
   3611                 {
   3612                     /* reference tracker should be configured for GPS by now. Start sending ts diffs */
   3613                     ptr =  ((uint8 *)(tsList + queue->head)->data + sizeof(uint16));
   3614 
   3615                     temp_ts = _bcm_ptp_uint64_read(ptr);
   3616                     ptr += 8;
   3617 
   3618                     first_TS.seconds = (temp_ts/1000000000);
   3619                     first_TS.nanoseconds = 0;
   3620 
   3621                     num_TS =_bcm_ptp_uint16_read(ptr);
   3622                     ptr+= 2;
   3623 
   3624                     for (i = 0; i < num_TS; i++)
   3625                     {
   3626                         gps_diff_ts[i] = _bcm_ptp_uint64_read(ptr) - temp_ts;
   3627                         ptr += 8;
   3628                         temp_ts = (temp_ts + 10000000) % ((uint64)1 << 48);
   3629                     }
   3630 
   3631                     int_usec = 1000000;
   3632                     LOG_DEBUG(BSL_LS_BCM_PTP,
   3633                         (BSL_META_U(unit, "GPS: numTs[%d] log_int[%d] first_TS[0x%016llx / %llds.%uns]\n"),
   3634                                 num_TS, log_interval,
   3635                         (long long signed int)first_TS.seconds,
   3636                         (long long signed int)first_TS.seconds, first_TS.nanoseconds));
   3637 
   3638                     /* timestamp differences */
   3639                     rv = _bcm_ptp_servo_AddTimestampDiffs(unit, ptp_id, 0, &g_gps_port_id, num_TS, first_TS, (uint8 *)gps_diff_ts, _bcm_ptp_ts_type_downlink, int_usec);
   3640                     rv = _bcm_ptp_servo_AddTimestampDiffs(unit, ptp_id, 0, &g_gps_port_id, num_TS, first_TS, (uint8 *)gps_diff_ts, _bcm_ptp_ts_type_uplink, int_usec);
   3641                 }
   3642                 break;
   3643             default:
   3644                 mbox_tsevent_stats.event_unknown++;
   3645                 break;
   3646         }
   3647 #endif /* BCM_PTP_EXT_SERVO_SUPPORT */
   3648         sal_free((void *)((tsList + queue->head)->data));
   3649         (tsList + queue->head)->data = NULL;
   3650         if (queue->head == queue->tail) {
   3651             queue->head = queue->tail = -1;
   3652         } else if (queue->head == BCM_PTP_TIMESTAMP_QUEUE_SIZE -1) {
   3653             queue->head = 0;
   3654         } else
   3655             queue->head++;
   3656     }
   3657 #ifdef BCM_PTP_EXT_SERVO_SUPPORT
   3658     mbox_tsevent_stats.ts_rpc_livecount--;
   3659 #endif
   3660     
   3661     PTP_MUTEX_GIVE(queue->lock);
   3662 
   3663     return 0;
   3664 }
   3665 
   3666 
   3667 #endif /* defined(INCLUDE_PTP)*/