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

instrumentation.c (36621B)


      1 /*
      2  * 
      3  *
      4  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      5  * 
      6  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      7  *
      8  * File:    instrumentation.c
      9  * Purpose: Tomahawk3 Instrumentation code
     10  */
     11 #if defined(BCM_TOMAHAWK3_SUPPORT)
     12 #include <soc/drv.h>
     13 
     14 #if defined(BCM_INSTRUMENTATION_SUPPORT)
     15 #include <soc/mem.h>
     16 #include <soc/format.h>
     17 #include <soc/tomahawk3.h>
     18 #include <bcm/switch.h>
     19 #include <bcm_int/esw/instrumentation.h>
     20 #include <bcm_int/esw_dispatch.h>
     21 #include <bcm_int/esw/port.h>
     22 #include <bcm_int/esw/firebolt.h>
     23 #include <bcm_int/esw/stg.h>
     24 #include <shared/bitop.h>
     25 
     26 #define TH3_PTR_RESULTS_IADAPT_MAX_INDEX    1
     27 #define TH3_PTR_RESULTS_IPARS_MAX_INDEX     1
     28 #define TH3_PTR_RESULTS_IFWD_MAX_INDEX      4
     29 #define TH3_PTR_RESULTS_ISW_MAX_INDEX       7
     30 
     31 #define TH3_IP_STAGE_PER_ENTRY_SIZE  8
     32 
     33 #define TH3_IADAPT_RAW_DATA_BYTES   \
     34             (TH3_PTR_RESULTS_IADAPT_MAX_INDEX * TH3_IP_STAGE_PER_ENTRY_SIZE)
     35 #define TH3_IPARS_RAW_DATA_BYTES    \
     36             (TH3_PTR_RESULTS_IPARS_MAX_INDEX * TH3_IP_STAGE_PER_ENTRY_SIZE)
     37 #define TH3_IFWD_RAW_DATA_BYTES     \
     38             (TH3_PTR_RESULTS_IFWD_MAX_INDEX * TH3_IP_STAGE_PER_ENTRY_SIZE)
     39 #define TH3_ISW_RAW_DATA_BYTES      \
     40             (TH3_PTR_RESULTS_ISW_MAX_INDEX * TH3_IP_STAGE_PER_ENTRY_SIZE)
     41 
     42 #define TH3_IPARS_RAW_DATA_OFFSET   0
     43 #define TH3_IADAPT_RAW_DATA_OFFSET  \
     44         (TH3_IPARS_RAW_DATA_OFFSET + TH3_IPARS_RAW_DATA_BYTES)
     45 #define TH3_IFWD_RAW_DATA_OFFSET    \
     46         (TH3_IADAPT_RAW_DATA_OFFSET + TH3_IADAPT_RAW_DATA_BYTES)
     47 #define TH3_ISW_RAW_DATA_OFFSET     \
     48         (TH3_IFWD_RAW_DATA_OFFSET + TH3_IFWD_RAW_DATA_BYTES)
     49 
     50 /*
     51  * Function:
     52  *     _bcm_th3_pkt_trace_hw_reset
     53  *
     54  * Purpose:
     55  *       clean PTR_RESULTS_BUFFER_IADAPT/IPARS/IFWD/ISW memories
     56  *       call this function before sending a visibilty packet
     57  *
     58  * Parameters:
     59  *      unit - (IN)  Device Number
     60  *      pipe - (IN)  Ingress Pipeline Number
     61  *
     62  * Returns:
     63  *      BCM_E_XXX
     64  *
     65  * Notes:
     66  *      If 'pipe' parameter is -1, memories for all pipes will
     67  *      get reset else memory for only that pipe gets reset
     68  */
     69 int _bcm_th3_pkt_trace_hw_reset(int unit, int pipe)
     70 {
     71     int         rv = BCM_E_NONE;
     72     uint32      active_pipes_bmap = 0x0;
     73     soc_mem_t   mem;
     74 
     75     if (-1 == pipe) {
     76         SOC_IF_ERROR_RETURN(
     77             soc_mem_clear(unit, PTR_RESULTS_BUFFER_IPARSm, MEM_BLOCK_ALL, 0));
     78         SOC_IF_ERROR_RETURN(
     79             soc_mem_clear(unit, PTR_RESULTS_BUFFER_IADAPTm, MEM_BLOCK_ALL, 0));
     80         SOC_IF_ERROR_RETURN(
     81             soc_mem_clear(unit, PTR_RESULTS_BUFFER_IFWDm, MEM_BLOCK_ALL, 0));
     82         SOC_IF_ERROR_RETURN(
     83             soc_mem_clear(unit, PTR_RESULTS_BUFFER_ISWm, MEM_BLOCK_ALL, 0));
     84 
     85     } else if ((pipe > -1) && (pipe < SOC_MAX_NUM_PIPES)) {
     86 
     87         /* Get pipe bitmap for active pipes in the system */
     88         soc_tomahawk3_pipe_map_get(unit, &active_pipes_bmap);
     89 
     90         /* Check if the given pipe is active on the device */
     91         if (active_pipes_bmap & (1 << pipe)) {
     92             mem = SOC_MEM_UNIQUE_ACC(unit, PTR_RESULTS_BUFFER_IPARSm)[pipe];
     93             SOC_IF_ERROR_RETURN(soc_mem_clear(unit, mem, MEM_BLOCK_ALL, 0));
     94 
     95             mem = SOC_MEM_UNIQUE_ACC(unit, PTR_RESULTS_BUFFER_IADAPTm)[pipe];
     96             SOC_IF_ERROR_RETURN(soc_mem_clear(unit, mem, MEM_BLOCK_ALL, 0));
     97 
     98             mem = SOC_MEM_UNIQUE_ACC(unit, PTR_RESULTS_BUFFER_IFWDm)[pipe];
     99             SOC_IF_ERROR_RETURN(soc_mem_clear(unit, mem, MEM_BLOCK_ALL, 0));
    100 
    101             mem = SOC_MEM_UNIQUE_ACC(unit, PTR_RESULTS_BUFFER_ISWm)[pipe];
    102             SOC_IF_ERROR_RETURN(soc_mem_clear(unit, mem, MEM_BLOCK_ALL, 0));
    103         } else {
    104             /* If the given pipe is not active then return error */
    105             rv = BCM_E_PARAM;
    106         }
    107     } else {
    108         rv = BCM_E_PARAM;
    109     }
    110 
    111     return rv;
    112 }
    113 
    114 /*
    115  * Function:
    116  *     _bcm_th3_pkt_trace_drop_reason_decode
    117  *
    118  * Purpose:
    119  *      decode the raw drop reason bits into Application
    120  *      understandable format
    121  *
    122  * Parameters:
    123  *      unit - (IN)  Device Number
    124  *      pkt_trace_info - (IN/OUT) User given packet trace structure.
    125  *
    126  * Returns:
    127  *      BCM_E_XXX
    128  *
    129  * Notes:
    130  *      Parameter 'pkt_trace_info' will be used as input to this function
    131  *      for member 'raw_data' and will be used as an output with respect
    132  *      to member 'pkt_trace_drop_reason'
    133  */
    134 static
    135 int _bcm_th3_pkt_trace_drop_reason_decode(int unit,
    136                                     bcm_switch_pkt_trace_info_t *pkt_trace_info)
    137 {
    138     int     fld_idx;
    139     int     bit_set_cnt = 0;
    140     uint32  pre_coun_v = 0;
    141     uint32  pkt_dp_v[2] = {0};
    142     uint32  disc_dp_v = 0;
    143     uint32  rsel_dp_v = 0;
    144     uint32  tl_dp_v = 0;
    145     uint32  vlan_dp_v = 0;
    146     uint32  pre_dp_v = 0;
    147     uint32  *isw_raw_data =
    148                 (uint32 *)(pkt_trace_info->raw_data + TH3_ISW_RAW_DATA_OFFSET);
    149     static const soc_field_t dp_flds[] = {
    150                                            RIPD4f,
    151                                            RIPHE4f,
    152                                            RIPD6f,
    153                                            RIPHE6f,
    154                                            BLOCK_MASK_DROPf,
    155                                            MTU_CHECK_FAILf,
    156                                            PARITYDf,
    157                                            PDISCf,
    158                                            RDROPf,
    159                                            RIMDRf,
    160                                            RPORTDf,
    161                                            RTUNEf
    162                                        };
    163 
    164     typedef struct {
    165         soc_field_t field;
    166         uint8       idx_fmt_map;
    167         uint8       reason;
    168     } drop_reason_map_t;
    169 
    170     /* Drop reasons TH3 cares to provide to Applications */
    171     const drop_reason_map_t drop_reason_map[] = {
    172         { INVALID_VLANf,            0 /* VLAN_DROP_VECTORfmt */,
    173             (uint8)bcmSwitchPktTraceDropReasonVlanNotValid              },
    174         { ENIFILTERf,               0 /* VLAN_DROP_VECTORfmt */,
    175             (uint8)bcmSwitchPktTraceDropReasonIngressPortNotInVlanMember},
    176         { INVALID_TPIDf,            0 /* VLAN_DROP_VECTORfmt */,
    177             (uint8)bcmSwitchPktTraceDropReasonTpidMismatch              },
    178         { IFP_DROPf,                1 /* RSEL_DROP_VECTORfmt */,
    179             (uint8)bcmSwitchPktTraceDropReasonStageIngress              },
    180         { TUNNEL_ERRORf,            1 /* RSEL_DROP_VECTORfmt */,
    181             (uint8)bcmSwitchPktTraceDropReasonTunnelError               },
    182         { BPDUf,                    2 /* PKT_PROC_DROP_VECTORfmt */,
    183             (uint8)bcmSwitchPktTraceDropReasonBpdu                      },
    184         { TUNNEL_DECAP_ECNf,        2 /* PKT_PROC_DROP_VECTORfmt */,
    185             (uint8)bcmSwitchPktTraceDropReasonTunnlDecapEcnError        },
    186         { VFPf,                     2 /* PKT_PROC_DROP_VECTORfmt */,
    187             (uint8)bcmSwitchPktTraceDropReasonStageLookup               },
    188         { CMLf,                     2 /* PKT_PROC_DROP_VECTORfmt */,
    189             (uint8)bcmSwitchPktTraceDropReasonUnknownSrcMac             },
    190         { L2DST_DISCARDf,           2 /* PKT_PROC_DROP_VECTORfmt */,
    191             (uint8)bcmSwitchPktTraceDropReasonL2DstDiscard              },
    192         { L2SRC_DISCARDf,           2 /* PKT_PROC_DROP_VECTORfmt */,
    193             (uint8)bcmSwitchPktTraceDropReasonL2SrcDiscard              },
    194         { L2SRC_STATIC_MOVEf,       2 /* PKT_PROC_DROP_VECTORfmt */,
    195             (uint8)bcmSwitchPktTraceDropReasonL2SrcStaticMove           },
    196         { L3DST_DISCARDf,           2 /* PKT_PROC_DROP_VECTORfmt */,
    197             (uint8)bcmSwitchPktTraceDropReasonL3DstDiscard              },
    198         { MACSA0f,                  2 /* PKT_PROC_DROP_VECTORfmt */,
    199             (uint8)bcmSwitchPktTraceDropReasonSrcMacZero                },
    200         { MULTICAST_INDEX_ERRORf,   2 /* PKT_PROC_DROP_VECTORfmt */,
    201             (uint8)bcmSwitchPktTraceDropReasonMcastIndexError           },
    202         { MY_STATIONf,              2 /* PKT_PROC_DROP_VECTORfmt */,
    203             (uint8)bcmSwitchPktTraceDropReasonMyStation                 },
    204         { PFMf,                     2 /* PKT_PROC_DROP_VECTORfmt */,
    205             (uint8)bcmSwitchPktTraceDropReasonMcastLookupMiss           },
    206         { PROTCOL_PKTf,             2 /* PKT_PROC_DROP_VECTORfmt */,
    207             (uint8)bcmSwitchPktTraceDropReasonProtocolPkt               },
    208         { SRC_ROUTEf,               2 /* PKT_PROC_DROP_VECTORfmt */,
    209             (uint8)bcmSwitchPktTraceDropReasonSrcRoute                  },
    210         { TAG_UNTAG_DISCARDf,       2 /* PKT_PROC_DROP_VECTORfmt */,
    211             (uint8)bcmSwitchPktTraceDropReasonPortTagPresentError       },
    212         { TIME_SYNC_PKTf,           2 /* PKT_PROC_DROP_VECTORfmt */,
    213             (uint8)bcmSwitchPktTraceDropReasonTimeSyncPkt               },
    214         { VLAN_CC_OR_PBTf,          2 /* PKT_PROC_DROP_VECTORfmt */,
    215             (uint8)bcmSwitchPktTraceDropReasonL2DstMissOrPbt            },
    216         { MPLS_LABEL_MISSf,         3 /* TUNNEL_PROC_DROP_VECTORfmt */,
    217             (uint8)bcmSwitchPktTraceDropReasonMplsLabelLookupMiss       },
    218         { MPLS_INVALID_ACTIONf,     3 /* TUNNEL_PROC_DROP_VECTORfmt */,
    219             (uint8)bcmSwitchPktTraceDropReasonMplsInvalidAction         },
    220         { MPLS_INVALID_PAYLOADf,    3 /* TUNNEL_PROC_DROP_VECTORfmt */,
    221             (uint8)bcmSwitchPktTraceDropReasonMplsInvalidPayload        },
    222         { MPLS_INVALID_CWf,         3 /* TUNNEL_PROC_DROP_VECTORfmt */,
    223             (uint8)bcmSwitchPktTraceDropReasonMplsInvalidControlWord    },
    224         { MPLS_TTL_CHECK_FAILf,     3 /* TUNNEL_PROC_DROP_VECTORfmt */,
    225             (uint8)bcmSwitchPktTraceDropReasonMplsTtlCheckFail          },
    226         { MPLS_GAL_LABELf,          3 /* TUNNEL_PROC_DROP_VECTORfmt */,
    227             (uint8)bcmSwitchPktTraceDropReasonMplsGalLabel              },
    228         { CONTROL_FRAMEf,           4 /* DISCARD_PROC_DROP_VECTORfmt */,
    229             (uint8)bcmSwitchPktTraceDropReasonControlFrame              },
    230         { IPV4_PROTOCOL_ERRORf,     4 /* DISCARD_PROC_DROP_VECTORfmt */,
    231             (uint8)bcmSwitchPktTraceDropReasonIpv4ProtocolError         },
    232         { IPV6_PROTOCOL_ERRORf,     4 /* DISCARD_PROC_DROP_VECTORfmt */,
    233             (uint8)bcmSwitchPktTraceDropReasonIpv6ProtocolError         },
    234         { LAG_FAIL_LOOPBACKf,       4 /* DISCARD_PROC_DROP_VECTORfmt */,
    235             (uint8)bcmSwitchPktTraceDropReasonLagFailLoopback           },
    236         { MACSA_EQUALS_DAf,         4 /* DISCARD_PROC_DROP_VECTORfmt */,
    237             (uint8)bcmSwitchPktTraceDropReasonL2SrcEqualL2Dst           },
    238         { RIPHE4f,                  5 /* PRE_COUNTER_UPDATE_VECTORfmt */,
    239             (uint8)bcmSwitchPktTraceDropReasonIpv4HeaderError           },
    240         { RIPHE6f,                  5 /* PRE_COUNTER_UPDATE_VECTORfmt */,
    241             (uint8)bcmSwitchPktTraceDropReasonIpv6HeaderError           },
    242         { RDROPf,                   5 /* PRE_COUNTER_UPDATE_VECTORfmt */,
    243             (uint8)bcmSwitchPktTraceDropReasonPortBitmapZero            },
    244         { RPORTDf,                  5 /* PRE_COUNTER_UPDATE_VECTORfmt */,
    245             (uint8)bcmSwitchPktTraceDropReasonStpNotForwarding          },
    246         { PARITYDf,                 5 /* PRE_COUNTER_UPDATE_VECTORfmt */,
    247             (uint8)bcmSwitchPktTraceDropReasonParityError               }
    248     };
    249 
    250     typedef struct {
    251         soc_format_t    fmt;
    252         void *          fmt_entry;
    253     } format_map_t;
    254 
    255     format_map_t fmt_map[] = {
    256         {   VLAN_DROP_VECTORfmt,           NULL },
    257         {   RSEL_DROP_VECTORfmt,           NULL },
    258         {   PKT_PROC_DROP_VECTORfmt,       NULL },
    259         {   TUNNEL_PROC_DROP_VECTORfmt,    NULL },
    260         {   DISCARD_PROC_DROP_VECTORfmt,   NULL },
    261         {   PRE_COUNTER_UPDATE_VECTORfmt,  NULL }
    262     };
    263 
    264     fmt_map[0].fmt_entry = (void *)&vlan_dp_v;
    265     fmt_map[1].fmt_entry = (void *)&rsel_dp_v;
    266     fmt_map[2].fmt_entry = (void *)&pkt_dp_v;
    267     fmt_map[3].fmt_entry = (void *)&tl_dp_v;
    268     fmt_map[4].fmt_entry = (void *)&disc_dp_v;
    269     fmt_map[5].fmt_entry = (void *)&pre_dp_v;
    270 
    271     /* Extract the PKT_PROC_DROP_VECTOR from the ISW.DW5 raw data */
    272     soc_format_field_get(unit,
    273                          INGRESS_COUNTER_UPDATE_VECTORfmt,
    274                          isw_raw_data + 10,
    275                          PKT_PROC_DROP_VECTORf,
    276                          pkt_dp_v);
    277 
    278     /* Extract the DISCARD_PROC_DROP_VECTOR from PKT_PROC_DROP_VECTOR
    279      * field and then clear the DISCARD_PROC_DROP_VECTOR from the pkt_dp_v
    280      */
    281     disc_dp_v = soc_format_field32_get(unit, PKT_PROC_DROP_VECTORfmt,
    282                                        pkt_dp_v, DISCARD_PROC_DROP_VECTORf);
    283     soc_format_field32_set(unit, PKT_PROC_DROP_VECTORfmt,
    284                            pkt_dp_v, DISCARD_PROC_DROP_VECTORf, 0x0);
    285 
    286     /* Extract the RSEL_DROP_VECTOR from PKT_PROC_DROP_VECTOR
    287      * field and then clear the RSEL_DROP_VECTOR from the pkt_dp_v
    288      */
    289     rsel_dp_v = soc_format_field32_get(unit, PKT_PROC_DROP_VECTORfmt,
    290                                        pkt_dp_v, RSEL_DROP_VECTORf);
    291     soc_format_field32_set(unit, PKT_PROC_DROP_VECTORfmt,
    292                            pkt_dp_v, RSEL_DROP_VECTORf, 0x0);
    293 
    294     /* Extract the TUNNEL_PROC_DROP_VECTOR from PKT_PROC_DROP_VECTOR
    295      * field and then clear the TUNNEL_PROC_DROP_VECTOR from the pkt_dp_v
    296      */
    297     tl_dp_v = soc_format_field32_get(unit, PKT_PROC_DROP_VECTORfmt,
    298                                      pkt_dp_v, TUNNEL_PROC_DROP_VECTORf);
    299     soc_format_field32_set(unit, PKT_PROC_DROP_VECTORfmt,
    300                            pkt_dp_v, TUNNEL_PROC_DROP_VECTORf, 0x0);
    301 
    302     /* Extract the VLAN_DROP_VECTOR from PKT_PROC_DROP_VECTOR
    303      * field and then clear the VLAN_DROP_VECTOR from the pkt_dp_v
    304      */
    305     vlan_dp_v = soc_format_field32_get(unit, PKT_PROC_DROP_VECTORfmt,
    306                                        pkt_dp_v, VLAN_DROP_VECTORf);
    307     soc_format_field32_set(unit, PKT_PROC_DROP_VECTORfmt,
    308                            pkt_dp_v, VLAN_DROP_VECTORf, 0x0);
    309 
    310     /* Extract the PRE_COUNTER_UPDATE_VECTORf from ISW Stage buffer */
    311     pre_coun_v = soc_format_field32_get(unit,
    312                      INSTR_BUFFER_ISW_DW6fmt,
    313                      isw_raw_data + 12,
    314                      PRE_COUNTER_UPDATE_VECTORf);
    315 
    316     /* Extract required drop vector from pre counter vector
    317      * RIPD4, RIPHE4, RIPD6, RIPHE6, BLOCK_MASK_DROP,
    318      * MTU_CHECK_FAIL, PARITYD, PDISC, RDROP, RIMDR, RPORTD, RTUNE
    319      */
    320     for (fld_idx=0 ; fld_idx < COUNTOF(dp_flds) ; fld_idx++) {
    321         if(soc_format_field32_get(unit,
    322            PRE_COUNTER_UPDATE_VECTORfmt, &pre_coun_v, dp_flds[fld_idx])) {
    323               soc_format_field32_set(unit,
    324                 PRE_COUNTER_UPDATE_VECTORfmt, &pre_dp_v, dp_flds[fld_idx], 0x1);
    325         }
    326     }
    327 
    328     /* Clear the drop reason bitmap begin-with */
    329     sal_memset(pkt_trace_info->pkt_trace_drop_reason,
    330                 0, sizeof(pkt_trace_info->pkt_trace_drop_reason));
    331 
    332     /* Capture the necessary drop reasons and clear the corresponding bit
    333      * in the source bitmap to indicate that the drop reason has been processed
    334      */
    335     for (fld_idx=0 ; fld_idx < COUNTOF(drop_reason_map) ; fld_idx++) {
    336         if (soc_format_field32_get(unit,
    337                 fmt_map[drop_reason_map[fld_idx].idx_fmt_map].fmt,
    338                 fmt_map[drop_reason_map[fld_idx].idx_fmt_map].fmt_entry,
    339                 drop_reason_map[fld_idx].field))
    340         {
    341             SHR_BITSET(pkt_trace_info->pkt_trace_drop_reason,
    342                        drop_reason_map[fld_idx].reason);
    343             soc_format_field32_set(unit,
    344                     fmt_map[drop_reason_map[fld_idx].idx_fmt_map].fmt,
    345                     fmt_map[drop_reason_map[fld_idx].idx_fmt_map].fmt_entry,
    346                     drop_reason_map[fld_idx].field,
    347                     0x0);
    348         }
    349     }
    350 
    351     /* If there are more drop reasons which are not yet captured/decoded
    352      * individually then mark the Internal drop reason too in the bitmap.
    353      */
    354     if (tl_dp_v || disc_dp_v || vlan_dp_v ||
    355          pre_dp_v || pkt_dp_v[0] || pkt_dp_v[1] || rsel_dp_v) {
    356         SHR_BITSET(pkt_trace_info->pkt_trace_drop_reason,
    357                     bcmSwitchPktTraceDropReasonInternal);
    358     }
    359 
    360     /* See if the drop reason bitmap has any drop bit set */
    361     SHR_BITCOUNT_RANGE(pkt_trace_info->pkt_trace_drop_reason,
    362                        bit_set_cnt, 0, bcmSwitchPktTraceDropReasonCount);
    363 
    364     /* If no error or drop bit is set then mark the bit for No Drop */
    365     if (0 == bit_set_cnt) {
    366         SHR_BITSET(
    367             pkt_trace_info->pkt_trace_drop_reason, bcmSwitchPktTraceNoDrop);
    368     }
    369 
    370     return BCM_E_NONE;
    371 }
    372 
    373 /*
    374  * Function:
    375  *    _bcm_th3_pkt_trace_raw_data_decode
    376  *
    377  * Purpose:
    378  *     decode the raw data from PTR_RESULTS_BUFFER_IADAPT/IFWD/ISW memories
    379  *     The memories are not read instead the data is interpreted from the
    380  *     'raw_data' buffer which already has been filled-in with the entries
    381  *     from the above mentioned memories.
    382  *
    383  * Parameters:
    384  *     unit - (IN)  Device Number
    385  *     pkt_trace_info - (IN/OUT) User given packet trace structure.
    386  *
    387  * Returns:
    388  *      BCM_E_XXX
    389  *
    390  * Notes:
    391  *      Parameter 'pkt_trace_info' will be used as input to this function
    392  *      for member 'raw_data' and will be used as an output with respect
    393  *      to other members.
    394  */
    395 static
    396 int _bcm_th3_pkt_trace_raw_data_decode(int unit,
    397                                   bcm_switch_pkt_trace_info_t *pkt_trace_info)
    398 {
    399     int                     rv = BCM_E_NONE;
    400 
    401     /* pkt lookup and resolution vars*/
    402     int                     l2x_index = -1;
    403     uint32                  lookup_status;
    404     uint32                  ing_stp_state;
    405     l2x_entry_t             l2x_entry;
    406 
    407     /* Trunk/LAG related vars */
    408     int                     tgid;
    409     uint32                  lag_hash_val;
    410     uint32                  trunk_group_size;
    411     uint32                  trunk_member_index;
    412     _bcm_gport_dest_t       dest;
    413     fast_trunk_size_entry_t trunk_size_entry;
    414 
    415 #ifdef INCLUDE_L3
    416     /* ECMP hashing information vars */
    417     int                     ecmp_id;
    418     uint32                  ecmp_ptr;
    419     uint32                  ecmp_index;
    420     ecmp_entry_t            ecmp_entry;
    421     ecmp_count_entry_t      ecmpc_entry;
    422     uint32                  ecmp_offset;
    423     uint32                  ecmp_rsl_done1;
    424     uint32                  ecmp_rsl_done2;
    425 #endif
    426 
    427     /* get hold of the respective pipeline stage data */
    428     uint32 *offset_isw_data;
    429     uint32 *iadapt_raw_data =
    430         (uint32 *)(pkt_trace_info->raw_data + TH3_IADAPT_RAW_DATA_OFFSET);
    431     uint32 *ifwd_raw_data =
    432         (uint32 *)(pkt_trace_info->raw_data + TH3_IFWD_RAW_DATA_OFFSET);
    433     uint32 *isw_raw_data =
    434         (uint32 *)(pkt_trace_info->raw_data + TH3_ISW_RAW_DATA_OFFSET);
    435 
    436     /* retrieve lookup status */
    437     lookup_status =
    438         soc_format_field32_get(
    439             unit, INSTR_BUFFER_IFWD_DW3fmt, ifwd_raw_data + 6, LOOKUP_STATUSf);
    440 
    441     /* fill ingress stp enum*/
    442     ing_stp_state =
    443         soc_format_field32_get(unit,
    444             IFP_LOOKUP_STATUS_VECTORfmt, &lookup_status, INGRESS_STG_STATEf);
    445     BCM_IF_ERROR_RETURN(_bcm_stg_pvp_translate(
    446         unit, ing_stp_state, (int *)&(pkt_trace_info->pkt_trace_stp_state)));
    447 
    448     /* fill in the lookup status bit vector */
    449     if (soc_format_field32_get(
    450          unit, IFP_LOOKUP_STATUS_VECTORfmt, &lookup_status, VALID_VLAN_IDf)) {
    451         SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status.
    452            pkt_trace_status_bitmap, bcmSwitchPktTraceLookupForwardingVlanValid);
    453     }
    454 
    455     if (soc_format_field32_get(
    456          unit, INSTR_BUFFER_IFWD_DW0fmt, ifwd_raw_data, L2LU_SRC_HITf)) {
    457         SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status.
    458            pkt_trace_status_bitmap, bcmSwitchPktTraceLookupL2SrcHit);
    459 
    460         /* Extract the index into L2X table for later use */
    461         l2x_index = soc_format_field32_get(
    462                 unit, INSTR_BUFFER_IFWD_DW0fmt, ifwd_raw_data, L2LU_SRC_INDEXf);
    463     }
    464 
    465     if (-1 != l2x_index) {
    466         soc_mem_lock(unit, L2Xm);
    467         rv = soc_mem_read(unit, L2Xm, MEM_BLOCK_ANY, l2x_index, &l2x_entry);
    468         soc_mem_unlock(unit, L2Xm);
    469 
    470         SOC_IF_ERROR_RETURN(rv);
    471 
    472         if(soc_L2Xm_field32_get(unit, &l2x_entry, BASE_VALIDf)) {
    473             if(soc_L2Xm_field32_get(unit, &l2x_entry, STATIC_BITf)) {
    474                 SHR_BITSET(pkt_trace_info->
    475                     pkt_trace_lookup_status.pkt_trace_status_bitmap,
    476                     bcmSwitchPktTraceLookupL2SrcStatic);
    477             }
    478         } else {
    479             return BCM_E_NOT_FOUND;
    480         }
    481     }
    482 
    483     if (soc_format_field32_get(
    484          unit, INSTR_BUFFER_IFWD_DW0fmt, ifwd_raw_data, L2LU_DST_HITf)) {
    485         SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status.
    486            pkt_trace_status_bitmap, bcmSwitchPktTraceLookupL2DstHit);
    487     }
    488 
    489     /* bcmSwitchPktTraceLookupL2CacheHit: Not available in TH3 */
    490 
    491     if (soc_format_field32_get(unit,
    492          INSTR_BUFFER_IFWD_DW1fmt, ifwd_raw_data + 2, L3_ENTRY_SRC_HITf)) {
    493         SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status.
    494            pkt_trace_status_bitmap, bcmSwitchPktTraceLookupL3SrcHostHit);
    495     }
    496 
    497     if (soc_format_field32_get(unit,
    498          INSTR_BUFFER_IFWD_DW1fmt, ifwd_raw_data + 2, L3_ENTRY_DST_HITf)) {
    499         SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status.
    500            pkt_trace_status_bitmap, bcmSwitchPktTraceLookupL3DestHostHit);
    501     }
    502 
    503     if (soc_format_field32_get(
    504          unit, INSTR_BUFFER_IFWD_DW2fmt, ifwd_raw_data + 4, LPM_HITf)) {
    505         SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status.
    506            pkt_trace_status_bitmap, bcmSwitchPktTraceLookupL3DestRouteHit);
    507     }
    508 
    509     /* bcmSwitchPktTraceLookupL2SrcMiss: Not available in TH3 */
    510 
    511     if (soc_format_field32_get(
    512          unit, IFP_LOOKUP_STATUS_VECTORfmt, &lookup_status, DOS_ATTACKf)) {
    513         SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status.
    514                    pkt_trace_status_bitmap, bcmSwitchPktTraceLookupDosAttack);
    515     }
    516 
    517     if (soc_format_field32_get(
    518          unit, IFP_LOOKUP_STATUS_VECTORfmt, &lookup_status, L3_TUNNEL_HITf)) {
    519         SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status.
    520                   pkt_trace_status_bitmap, bcmSwitchPktTraceLookupIpTunnelHit);
    521     }
    522 
    523     if (soc_format_field32_get(unit, IFP_LOOKUP_STATUS_VECTORfmt,
    524                     &lookup_status, MPLS_ENTRY_TABLE_LOOKUP_0_HITf)) {
    525         SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status.
    526                  pkt_trace_status_bitmap, bcmSwitchPktTraceLookupMplsLabel1Hit);
    527     }
    528 
    529     if (soc_format_field32_get(unit, IFP_LOOKUP_STATUS_VECTORfmt,
    530                     &lookup_status, MPLS_ENTRY_TABLE_LOOKUP_1_HITf)) {
    531         SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status.
    532                  pkt_trace_status_bitmap, bcmSwitchPktTraceLookupMplsLabel2Hit);
    533     }
    534 
    535     if (soc_format_field32_get(unit,
    536          IFP_LOOKUP_STATUS_VECTORfmt, &lookup_status, MPLS_BOS_TERMINATEDf)) {
    537         SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status.
    538                 pkt_trace_status_bitmap, bcmSwitchPktTraceLookupMplsTerminated);
    539     }
    540 
    541     if (soc_format_field32_get(
    542          unit, INSTR_BUFFER_IADAPT_DW0fmt, iadapt_raw_data, MY_STATION_HITf)) {
    543         SHR_BITSET(pkt_trace_info->pkt_trace_lookup_status.
    544                 pkt_trace_status_bitmap, bcmSwitchPktTraceLookupMystationHit);
    545     }
    546 
    547     /* fill packet resolution vector */
    548     pkt_trace_info->pkt_trace_resolution =
    549         soc_format_field32_get(unit, INSTR_BUFFER_ISW_DW0fmt,
    550                                 isw_raw_data, PKT_RESOLUTION_VECTORf);
    551 
    552 #ifdef INCLUDE_L3
    553     /* Retrieve the ECMP member resolution details */
    554     offset_isw_data = isw_raw_data + 2;
    555     ecmp_rsl_done1 = soc_format_field32_get(unit,
    556             INSTR_BUFFER_ISW_DW1fmt, offset_isw_data, ECMP_RESOLUTION_DONE1f);
    557     ecmp_rsl_done2 = soc_format_field32_get(unit,
    558             INSTR_BUFFER_ISW_DW1fmt, offset_isw_data, ECMP_RESOLUTION_DONE2f);
    559     if (ecmp_rsl_done1) {
    560         ecmp_id = soc_format_field32_get(unit,
    561                     INSTR_BUFFER_ISW_DW1fmt, offset_isw_data, ECMP_GROUP1f);
    562 
    563         SOC_IF_ERROR_RETURN
    564             (READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, ecmp_id, &ecmpc_entry));
    565 
    566         ecmp_ptr =
    567             soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, BASE_PTRf);
    568 
    569         ecmp_offset = soc_format_field32_get(unit,
    570                     INSTR_BUFFER_ISW_DW1fmt, offset_isw_data, ECMP_OFFSET1f);
    571 
    572         ecmp_index = (ecmp_ptr + ecmp_offset) &
    573                         (soc_mem_index_count(unit, L3_ECMPm) - 1);
    574 
    575         SOC_IF_ERROR_RETURN
    576             (READ_L3_ECMPm(unit, MEM_BLOCK_ANY, ecmp_index, &ecmp_entry));
    577         pkt_trace_info->pkt_trace_hash_info.ecmp_1_group = ecmp_id;
    578         pkt_trace_info->pkt_trace_hash_info.ecmp_1_group +=
    579                                                 BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit);
    580 
    581         pkt_trace_info->pkt_trace_hash_info.ecmp_1_egress =
    582                 soc_L3_ECMPm_field32_get(unit, &ecmp_entry, NEXT_HOP_INDEXf);
    583         pkt_trace_info->pkt_trace_hash_info.ecmp_1_egress +=
    584             ecmp_rsl_done2 ?
    585                 BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit) : BCM_XGS3_EGRESS_IDX_MIN(unit);
    586 
    587         pkt_trace_info->pkt_trace_hash_info.flags +=BCM_SWITCH_PKT_TRACE_ECMP_1;
    588     }
    589 
    590     if (ecmp_rsl_done2) {
    591         ecmp_id = soc_format_field32_get(unit,
    592                     INSTR_BUFFER_ISW_DW1fmt, offset_isw_data, ECMP_GROUP2f);
    593 
    594         SOC_IF_ERROR_RETURN
    595             (READ_L3_ECMP_COUNTm(unit, MEM_BLOCK_ANY, ecmp_id, &ecmpc_entry));
    596 
    597         ecmp_ptr =
    598             soc_L3_ECMP_COUNTm_field32_get(unit, &ecmpc_entry, BASE_PTRf);
    599 
    600         offset_isw_data = isw_raw_data + 4;
    601         ecmp_offset = soc_format_field32_get(unit,
    602                     INSTR_BUFFER_ISW_DW2fmt, offset_isw_data, ECMP_OFFSET2f);
    603 
    604         ecmp_index = (ecmp_ptr + ecmp_offset) &
    605                         (soc_mem_index_count(unit, L3_ECMPm) - 1);
    606 
    607         SOC_IF_ERROR_RETURN
    608             (READ_L3_ECMPm(unit, MEM_BLOCK_ANY, ecmp_index, &ecmp_entry));
    609 
    610         pkt_trace_info->pkt_trace_hash_info.ecmp_2_group = ecmp_id;
    611         pkt_trace_info->pkt_trace_hash_info.ecmp_2_group +=
    612                                                 BCM_XGS3_MPATH_EGRESS_IDX_MIN(unit);
    613 
    614         pkt_trace_info->pkt_trace_hash_info.ecmp_2_egress =
    615                 soc_L3_ECMPm_field32_get(unit, &ecmp_entry, NEXT_HOP_INDEXf);
    616         pkt_trace_info->pkt_trace_hash_info.ecmp_2_egress +=
    617                                                         BCM_XGS3_EGRESS_IDX_MIN(unit);
    618         pkt_trace_info->pkt_trace_hash_info.flags +=BCM_SWITCH_PKT_TRACE_ECMP_2;
    619     }
    620 #endif
    621 
    622     /* Decode LAG related fields */
    623     offset_isw_data = isw_raw_data + 4;
    624     if (soc_format_field32_get(unit,
    625          INSTR_BUFFER_ISW_DW2fmt, offset_isw_data, LAG_RESOLUTION_DONEf)) {
    626 
    627         /* Get the LAG ID */
    628         tgid = soc_format_field32_get(
    629                     unit, INSTR_BUFFER_ISW_DW2fmt, offset_isw_data, LAG_IDf);
    630 
    631         /* Get the number of Trunk members */
    632         BCM_IF_ERROR_RETURN(
    633            READ_FAST_TRUNK_SIZEm(unit, MEM_BLOCK_ANY, tgid, &trunk_size_entry));
    634         trunk_group_size    =
    635             soc_FAST_TRUNK_SIZEm_field32_get(unit, &trunk_size_entry, TG_SIZEf);
    636 
    637         /* Extract the member determination hash */
    638         lag_hash_val = soc_format_field32_get(unit,
    639                     INSTR_BUFFER_ISW_DW2fmt, offset_isw_data, HASH_VALUE_LAGf);
    640 
    641         /* Derive the Trunk member from Hash and Trunk group size */
    642         trunk_member_index  = (lag_hash_val % (trunk_group_size + 1)) & 0x3F;
    643 
    644         /* Determine the Port number from the Trunk member index */
    645         if (trunk_member_index < 32) {
    646             fast_trunk_ports_1_entry_t  trunk_entry;
    647              static const soc_field_t _th3_fast_port_fld[32] = {
    648                 TRUNK_MEMBER_0f,  TRUNK_MEMBER_1f,  TRUNK_MEMBER_2f,
    649                 TRUNK_MEMBER_3f,  TRUNK_MEMBER_4f,  TRUNK_MEMBER_5f,
    650                 TRUNK_MEMBER_6f,  TRUNK_MEMBER_7f,  TRUNK_MEMBER_8f,
    651                 TRUNK_MEMBER_9f,  TRUNK_MEMBER_10f, TRUNK_MEMBER_11f,
    652                 TRUNK_MEMBER_12f, TRUNK_MEMBER_13f, TRUNK_MEMBER_14f,
    653                 TRUNK_MEMBER_15f, TRUNK_MEMBER_16f, TRUNK_MEMBER_17f,
    654                 TRUNK_MEMBER_18f, TRUNK_MEMBER_19f, TRUNK_MEMBER_20f,
    655                 TRUNK_MEMBER_21f, TRUNK_MEMBER_22f, TRUNK_MEMBER_23f,
    656                 TRUNK_MEMBER_24f, TRUNK_MEMBER_25f, TRUNK_MEMBER_26f,
    657                 TRUNK_MEMBER_27f, TRUNK_MEMBER_28f, TRUNK_MEMBER_29f,
    658                 TRUNK_MEMBER_30f, TRUNK_MEMBER_31f
    659             };
    660             BCM_IF_ERROR_RETURN(
    661              READ_FAST_TRUNK_PORTS_1m(unit, MEM_BLOCK_ANY, tgid, &trunk_entry));
    662             dest.port = soc_FAST_TRUNK_PORTS_1m_field32_get(
    663                     unit, &trunk_entry, _th3_fast_port_fld[trunk_member_index]);
    664         } else {
    665             fast_trunk_ports_2_entry_t  trunk_entry;
    666             static const soc_field_t _th3_fast_port_fld[32] = {
    667                 TRUNK_MEMBER_32f, TRUNK_MEMBER_33f, TRUNK_MEMBER_34f,
    668                 TRUNK_MEMBER_35f, TRUNK_MEMBER_36f, TRUNK_MEMBER_37f,
    669                 TRUNK_MEMBER_38f, TRUNK_MEMBER_39f, TRUNK_MEMBER_40f,
    670                 TRUNK_MEMBER_41f, TRUNK_MEMBER_42f, TRUNK_MEMBER_43f,
    671                 TRUNK_MEMBER_44f, TRUNK_MEMBER_45f, TRUNK_MEMBER_46f,
    672                 TRUNK_MEMBER_47f, TRUNK_MEMBER_48f, TRUNK_MEMBER_49f,
    673                 TRUNK_MEMBER_50f, TRUNK_MEMBER_51f, TRUNK_MEMBER_52f,
    674                 TRUNK_MEMBER_53f, TRUNK_MEMBER_54f, TRUNK_MEMBER_55f,
    675                 TRUNK_MEMBER_56f, TRUNK_MEMBER_57f, TRUNK_MEMBER_58f,
    676                 TRUNK_MEMBER_59f, TRUNK_MEMBER_60f, TRUNK_MEMBER_61f,
    677                 TRUNK_MEMBER_62f, TRUNK_MEMBER_63f
    678             };
    679             BCM_IF_ERROR_RETURN(
    680              READ_FAST_TRUNK_PORTS_2m(unit, MEM_BLOCK_ANY, tgid, &trunk_entry));
    681             dest.port = soc_FAST_TRUNK_PORTS_2m_field32_get(
    682                 unit, &trunk_entry, _th3_fast_port_fld[trunk_member_index-32]);
    683         }
    684 
    685         /* Create a MODPORT GPORT from the local port numberii and save it  */
    686         BCM_IF_ERROR_RETURN(bcm_esw_stk_my_modid_get(unit, &(dest.modid)));
    687         dest.gport_type = _SHR_GPORT_TYPE_MODPORT;
    688         BCM_IF_ERROR_RETURN(
    689             _bcm_esw_gport_construct(unit,
    690                 &dest, &(pkt_trace_info->pkt_trace_hash_info.trunk_member)));
    691 
    692         /* Save the other Trunk information */
    693         pkt_trace_info->pkt_trace_hash_info.trunk = tgid;
    694         pkt_trace_info->pkt_trace_hash_info.flags += BCM_SWITCH_PKT_TRACE_TRUNK;
    695 
    696     } /* end lag resolution */
    697 
    698     /* Decode the drop reason raw bits */
    699     BCM_IF_ERROR_RETURN(
    700         _bcm_th3_pkt_trace_drop_reason_decode(unit, pkt_trace_info));
    701     return BCM_E_NONE;
    702 }
    703 
    704 /*
    705  * Function:
    706  *     __bcm_th3_pkt_trace_hw_buffer_read
    707  *
    708  * Purpose:
    709  *     Read the raw data from PTR_RESULTS_BUFFER_IADAPT/IFWD/ISW memories.
    710  *     Store the read data in its raw format into the given buffer. Also
    711  *     store the number of bytes written to the buffer if 'bytes_read'
    712  *     parameter is provided byt the caller.
    713  *
    714  * Parameters:
    715  *     unit - (IN)  Device Number
    716  *     pipe - (IN)  Ingress pipeline number
    717  *     buffer - (OUT) buffer where the captured data would be dumped.
    718  *     bytes_read - (OUT) Stores the number of bytes written to the buffer
    719  *
    720  * Returns:
    721  *     BCM_E_XXX
    722  *
    723  * Notes:
    724  *      Assumption is that all parameters are valid.
    725  *      Hence no addtional checks performed on them here.
    726  */
    727 static int __bcm_th3_pkt_trace_hw_buffer_read(
    728     int unit, int pipe, uint8 *buffer, uint32 *bytes_read)
    729 {
    730 
    731     uint8       mem_idx;
    732     uint8       entry_idx;
    733     uint32      byte_cnt;
    734     soc_mem_t   mem;
    735 
    736     const struct ptr_results_mem_info_s {
    737         soc_mem_t   mem;            /* Buffer Memory */
    738         uint8       max_idx;        /* Max number of entries */
    739     } mem_info_arr[] = {
    740         {   PTR_RESULTS_BUFFER_IPARSm,  TH3_PTR_RESULTS_IPARS_MAX_INDEX     },
    741         {   PTR_RESULTS_BUFFER_IADAPTm, TH3_PTR_RESULTS_IADAPT_MAX_INDEX    },
    742         {   PTR_RESULTS_BUFFER_IFWDm,   TH3_PTR_RESULTS_IFWD_MAX_INDEX      },
    743         {   PTR_RESULTS_BUFFER_ISWm,    TH3_PTR_RESULTS_ISW_MAX_INDEX       }
    744     };
    745 
    746     /* Initialize the bytes read count to 0 at first */
    747     if (NULL != bytes_read) {
    748         *bytes_read = 0;
    749     }
    750 
    751     /* Loop through all the entries of all the Ing. Pipe Stage Buffers */
    752     for (mem_idx=0, byte_cnt=0 ; mem_idx < COUNTOF(mem_info_arr) ; mem_idx++)
    753     {
    754         /* Retrieve the pipe specific memory instance */
    755         if (NULL == SOC_MEM_UNIQUE_ACC(unit, mem_info_arr[mem_idx].mem)) {
    756             return BCM_E_INTERNAL;
    757         }
    758         mem = SOC_MEM_UNIQUE_ACC(unit, mem_info_arr[mem_idx].mem)[pipe];
    759         if (mem == INVALIDm) {
    760             return BCM_E_INTERNAL;
    761         }
    762 
    763         /* Read the entry from HW tables entry by entry */
    764         for (entry_idx = 0 ;
    765              entry_idx < mem_info_arr[mem_idx].max_idx ; entry_idx++) {
    766             SOC_IF_ERROR_RETURN(
    767                 soc_mem_read(unit, mem, MEM_BLOCK_ANY,
    768                              entry_idx, buffer + byte_cnt));
    769 
    770             /* Adjust byte count with the number of bytes already read */
    771             byte_cnt += TH3_IP_STAGE_PER_ENTRY_SIZE;
    772         }
    773     }
    774 
    775     /* Populate the length of the data stored to the buffer */
    776     if (NULL != bytes_read) {
    777         *bytes_read = byte_cnt;
    778     }
    779 
    780     return BCM_E_NONE;
    781 }
    782 
    783 /*
    784  * Function:
    785  *     _bcm_th3_pkt_trace_info_retrieve_data
    786  *
    787  * Purpose:
    788  *     Read the data from PTR_RESULTS_BUFFER_IPARS/IADAPT/IFWD/ISW memories
    789  *     for the given pipe instance. Store the data in its raw format into the
    790  *     'raw_data' buffer in given data structure. Further it calls the decode
    791  *     function to decode some of the raw data.
    792  *
    793  *     If pipe parameter is passed as '-1' then all pipe instances for
    794  *     PTR_RESULTS_BUFFER_XXX memories would be polled for. The first
    795  *     available valid captured data would be given back to the user.
    796  *
    797  * Parameters:
    798  *     unit - (IN)  Device Number
    799  *     pipe - (IN)  Ingress pipeline number
    800  *     pkt_trace_info - (OUT) User given packet trace structure.
    801  *
    802  * Returns:
    803  *     BCM_E_XXX
    804  *
    805  * Notes:
    806  *   'pipe' parameter shoule be either -1 or range between 0 to 7 (inclusive).
    807  */
    808 int _bcm_th3_pkt_trace_info_retrieve_data(int unit, int pipe,
    809                               bcm_switch_pkt_trace_info_t *pkt_trace_info)
    810 {
    811     int     pipe_idx;
    812     int     min_pipe = pipe;
    813     int     max_pipe = pipe;
    814     uint32  byte_cnt = 0;
    815     uint32  byte_idx = 0;
    816     uint32  active_pipes_bmap = 0x0;
    817 
    818     /* Check for input parameters validity */
    819     if ((NULL == pkt_trace_info) || (pipe < -1) || (pipe >= SOC_MAX_NUM_PIPES)) {
    820         return BCM_E_PARAM;
    821     }
    822 
    823     /* Get pipe bitmap for the active pipes */
    824     soc_tomahawk3_pipe_map_get(unit, &active_pipes_bmap);
    825 
    826     /* If pipe is passed in as -1 then poll for data from all pipes */
    827     if (-1 == pipe) {
    828         min_pipe = 0;
    829         max_pipe = SOC_MAX_NUM_PIPES - 1;
    830     } else if (!(active_pipes_bmap & (1 << pipe))) {
    831         /* If a pipe is a valid number but it is inactive then return error */
    832         return BCM_E_PARAM;
    833     }
    834 
    835     /* Run the loop for the number of pipes */
    836     for (pipe_idx = min_pipe ; pipe_idx <= max_pipe ; pipe_idx++) {
    837 
    838         /* If the pipe is inactive, skip it */
    839         if (!(active_pipes_bmap & (1 << pipe_idx))) {
    840             continue;
    841         }
    842 
    843         /* Call routine to read the HW PktTrace capture memories for the pipe */
    844         BCM_IF_ERROR_RETURN(
    845             __bcm_th3_pkt_trace_hw_buffer_read(
    846                         unit, pipe_idx, pkt_trace_info->raw_data, &byte_cnt));
    847 
    848         /* See if we got valid data */
    849         for (byte_idx = 0 ; byte_idx < byte_cnt ; byte_idx += sizeof(uint32) ) {
    850             /* No need to worry about dword boundary as is is dword-aligned */
    851             if (*((uint32 *)(pkt_trace_info->raw_data + byte_idx))) {
    852                 break;
    853             }
    854         }
    855 
    856         /* If there is valid data then break out the loop to interpret it */
    857         if (byte_idx < byte_cnt) {
    858             break;
    859         }
    860     }
    861 
    862     /* If no valid data found then mark so */
    863     if (pipe_idx > max_pipe) {
    864         return BCM_E_BUSY;
    865     }
    866 
    867     /* Populate the lenght of the data stored to the buffer */
    868     pkt_trace_info->raw_data_length = byte_cnt;
    869 
    870     /* Store the pipe information on which the pkt trace has been captured */
    871     pkt_trace_info->dest_pipe_num = pipe_idx;
    872 
    873     /* Decode the raw data */
    874     BCM_IF_ERROR_RETURN(
    875         _bcm_th3_pkt_trace_raw_data_decode(unit, pkt_trace_info));
    876 
    877     return BCM_E_NONE;
    878 }
    879 
    880 #endif /* BCM_INSTRUMENTATION_SUPPORT */
    881 #endif /* BCM_TOMAHAWK3_SUPPORT */