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 (21377B)


      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  * Tomahawk Instrumentation API
      9  */
     10 
     11 #include <soc/drv.h>
     12 
     13 #ifdef BCM_INSTRUMENTATION_SUPPORT
     14 
     15 #include <soc/mem.h>
     16 #include <soc/util.h>
     17 #include <soc/debug.h>
     18 #include <sal/types.h>
     19  #include <sal/core/sync.h>
     20  #include <sal/core/time.h>
     21 #include <bcm/types.h>
     22 #include <bcm/error.h>
     23 #include <bcm/port.h>
     24 #include <bcm/switch.h>
     25 #include <bcm/tx.h>
     26 #include <bcm_int/esw_dispatch.h>
     27 #include <bcm_int/esw/tx.h>
     28 #include <bcm_int/esw/port.h>
     29 #include <bcm_int/esw_dispatch.h>
     30 #include <bcm_int/esw/instrumentation.h> 
     31 
     32 /* Flag to check initialized status */
     33 STATIC int _pkt_trace_initialized[BCM_MAX_NUM_UNITS];
     34 
     35 /* Protection mutexes for each unit */
     36 sal_mutex_t _pkt_trace_mlock[BCM_MAX_NUM_UNITS];
     37 
     38 #define PKT_TRACE_LOCK(unit)    sal_mutex_take(_pkt_trace_mlock[unit], sal_mutex_FOREVER)
     39 #define PKT_TRACE_UNLOCK(unit)  sal_mutex_give(_pkt_trace_mlock[unit])
     40 
     41 #define UNIT_VALID_CHECK(unit) \
     42     if (((unit) < 0) || ((unit) >= BCM_MAX_NUM_UNITS)) { return BCM_E_UNIT; }
     43 
     44 #define PKT_TRACE_INIT_DONE(unit)    (_pkt_trace_mlock[unit] != NULL)
     45 
     46 #define PKT_TRACE_INIT_CHECK(unit) \
     47     do { \
     48         UNIT_VALID_CHECK(unit); \
     49         if (_pkt_trace_mlock[unit] == NULL) { return BCM_E_INIT; } \
     50     } while (0)
     51 
     52 /*
     53  * Function:
     54  *      bcm_esw_pkt_trace_hw_reset
     55  * Purpose:
     56  *      clean PTR_RESULTS_BUFFER_IVP/ISW1/ISW2 registers
     57  *      call this functio before sending a 
     58  *      visibilty packet
     59  * Parameters:
     60  *      IN :  unit
     61  * Returns:
     62  *      BCM_E_XXX
     63  */
     64 int _bcm_esw_pkt_trace_hw_reset(int unit)
     65 {
     66 #if defined(BCM_TOMAHAWK3_SUPPORT)
     67     if (SOC_IS_TOMAHAWK3(unit)) {
     68         /* Call low level routine to reset HW memories for all pipes */
     69         return _bcm_th3_pkt_trace_hw_reset(unit, -1);
     70     } else
     71 #endif
     72     if (SOC_IS_TOMAHAWKX(unit)) {
     73         return _bcm_th_pkt_trace_hw_reset(unit);
     74     }     
     75     return BCM_E_UNAVAIL; 
     76 }
     77 
     78 /*
     79  * Function:
     80  *      _bcm_esw_pkt_trace_src_port_set 
     81  * Purpose:
     82  *      set the destination port of 
     83  *      visiblity packet
     84  *      this must be called before visibilty packet 
     85  *      is sent to set the pipe to read the resuls 
     86  * Parameters:
     87  *      IN :  unit
     88  *      IN : logical_dst_port
     89  * Returns:
     90  *      BCM_E_XXX
     91  */
     92 int _bcm_esw_pkt_trace_src_port_set(int unit, uint32 logical_dst_port) 
     93 {
     94     if (SOC_IS_TOMAHAWKX(unit)) {
     95         return _bcm_th_pkt_trace_src_port_set(unit, logical_dst_port);
     96     } else if (SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit)) {
     97         return _bcm_td3_pkt_trace_src_port_set(unit, logical_dst_port);
     98     }
     99     return BCM_E_UNAVAIL; 
    100  }
    101 
    102 /*
    103  * Function:
    104  *      _bcm_esw_pkt_trace_src_port_get 
    105  * Purpose:
    106  *      get the destination port of 
    107  *      visiblity packet
    108  * Parameters:
    109  *      IN :  unit
    110  *      IN : logical_dst_port
    111  * Returns:
    112  *      BCM_E_XXXd
    113  */
    114 
    115 int _bcm_esw_pkt_trace_src_port_get(int unit) 
    116 {
    117     if (SOC_IS_TOMAHAWKX(unit)) {
    118         return _bcm_th_pkt_trace_src_port_get(unit);
    119     } else if (SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit)) {
    120         return _bcm_td3_pkt_trace_src_port_get(unit);
    121     }
    122     return BCM_E_UNAVAIL; 
    123 }
    124 
    125 /*
    126  * Function:
    127  *      _bcm_esw_pkt_trace_src_pipe_get 
    128  * Purpose:
    129  *      get the destination pipe of 
    130  *      visiblity packet
    131  * Parameters:
    132  *      IN :  unit
    133  *      IN : logical_dst_port
    134  * Returns:
    135  *      BCM_E_XXXd
    136  */
    137 int _bcm_esw_pkt_trace_src_pipe_get(int unit) 
    138 {
    139     if (SOC_IS_TOMAHAWKX(unit)) {
    140         return _bcm_th_pkt_trace_src_pipe_get(unit);
    141     } else if (SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit)) {
    142         return _bcm_td3_pkt_trace_src_pipe_get(unit);
    143     }
    144     return BCM_E_UNAVAIL; 
    145 }
    146 
    147 /*
    148  * Function:
    149  *      _bcm_esw_pkt_trace_pkt_profile_set 
    150  * Purpose:
    151  *      given visibility packet behavior options
    152  *      setting the profile id for the next visibility packet
    153  * Parameters:
    154  *      IN :  unit
    155  *      IN :  options (BCM_PKT_TRACE_LEARN/NO_IFP/FORWARD)
    156  * Returns:
    157  *      BCM_E_XXX
    158  */
    159 int _bcm_esw_pkt_trace_cpu_profile_set(int unit,uint32 options)
    160 {
    161     if (SOC_IS_TOMAHAWKX(unit)){
    162         return _bcm_th_pkt_trace_cpu_profile_set(unit, options);
    163     }  else if (SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit)) {
    164         return _bcm_td3_pkt_trace_cpu_profile_set(unit, options);
    165     }
    166     return BCM_E_UNAVAIL; 
    167 }
    168 
    169 /*
    170  * Function:
    171  *      _bcm_esw_pkt_trace_cpu_pkt_profile_get
    172  * Purpose:
    173  *      retrieve cpu profile id to be used for the
    174  *      next visibility packet
    175  * Parameters:
    176  *      IN :  unit
    177  *      INOUT : profile id 
    178  * Returns:
    179  *      BCM_E_XXX
    180  */
    181 
    182 int _bcm_esw_pkt_trace_cpu_profile_get(int unit, uint32* profile_id)
    183 {
    184     if (SOC_IS_TOMAHAWKX(unit)) {
    185         return _bcm_th_pkt_trace_cpu_profile_get(unit, profile_id);
    186     } else if (SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit)) {
    187         return _bcm_td3_pkt_trace_cpu_profile_get(unit, profile_id);
    188     }
    189     return BCM_E_UNAVAIL; 
    190 }
    191 
    192 /*
    193  * Function:
    194  *      _bcm_esw_pkt_trace_info_get
    195  * Purpose:
    196  *      Read visibility packet process data from PTR_RESULTS_BUFFER_IVP, ISW1,
    197  *      and ISW2 and store into bcm_switch_pkt_trace_info_s *
    198  * Parameters:
    199  *      unit - (IN) Unit number.
    200  *      pkt_trace_info - (INOUT) visibility pkt trace prcoess result
    201  * Returns:
    202  *      BCM_E_xxx
    203  * Notes:
    204  */
    205 int _bcm_esw_pkt_trace_info_get(int unit, 
    206                                uint32 options, uint8 port, 
    207                                int len, uint8 *data, 
    208                   bcm_switch_pkt_trace_info_t *pkt_trace_info)
    209 {
    210     bcm_pkt_t *pkt; 
    211     int rv = BCM_E_UNAVAIL;
    212     int values[6] = {0, 0, 0, 0, 0, 0};
    213     bcm_module_t mod_id = -1;
    214     bcm_port_t pp_port = -1;
    215     bcm_gport_t gport;
    216     bcm_trunk_t tgid;
    217     int id;
    218     UNIT_VALID_CHECK(unit);
    219 
    220     if (soc_feature(unit, soc_feature_visibility)) {
    221         soc_timeout_t   to; 
    222         uint8           num_trial = 0;
    223 
    224         if (pkt_trace_info == NULL || 
    225             data == NULL) {
    226             return BCM_E_PARAM;
    227         }
    228         memset(pkt_trace_info, 0x0, sizeof(bcm_switch_pkt_trace_info_t));
    229         PKT_TRACE_INIT_CHECK(unit);
    230 
    231         /* mutex lock*/
    232         PKT_TRACE_LOCK(unit);
    233         rv = bcm_pkt_alloc(unit, len, 0, &pkt);
    234         if (BCM_FAILURE(rv)) {
    235             goto clean_up;
    236         }
    237         pkt->call_back = 0;
    238         pkt->blk_count = 1;
    239         pkt->unit = unit;
    240         
    241         rv = bcm_pkt_memcpy(pkt, 0, data, len);
    242         /*new flag indicating that the packet is for visibility or masquerade */
    243         pkt->flags2 = BCM_PKT_F2_RX_PORT;
    244         /* adding visibility option to packet flag */
    245         pkt->flags2 |= BCM_PKT_F2_VISIBILITY_PKT;
    246         /* setting pkt trace src port number and profile id on the packet */
    247         pkt->rx_port = port; 
    248 
    249         /* Option 'BCM_PKT_TRACE_RETRIEVE_DATA_ONLY' is only supported on
    250          * TH3. All other devices should ignore the option. Hence remove it.
    251          */
    252         options &= ~BCM_PKT_TRACE_RETRIEVE_DATA_ONLY;
    253 
    254         /* store profile info to be used during tx*/
    255         _bcm_esw_pkt_trace_cpu_profile_set(unit, options);
    256         /* Software workaround for TH */
    257         if (SOC_IS_TOMAHAWK(unit) &&
    258             soc_feature(unit, soc_feature_th_pkt_trace_sw_war)) {
    259             rv = _bcm_th_pkt_trace_int_lbport_set(unit, port, 1, values);
    260             if (BCM_FAILURE(rv)) {
    261                 goto clean_up;
    262             }
    263         } else if (SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit)) {
    264             rv = bcm_esw_port_gport_get(unit,
    265                                         port,
    266                                         &gport);
    267 
    268             if (BCM_FAILURE(rv)) {
    269                 goto clean_up;
    270             }
    271             rv = _bcm_esw_gport_resolve(unit, gport,
    272                                        &mod_id, &pp_port,
    273                                        &tgid, &id);
    274             if (BCM_FAILURE(rv)) {
    275                 goto clean_up;
    276             }
    277             rv = _bcm_td3_pkt_trace_source_trunk_map_pp_set(unit,
    278                            mod_id,
    279                            pp_port,
    280                            0);
    281 
    282             if (BCM_FAILURE(rv)) {
    283                 goto clean_up;
    284             }
    285             rv =_bcm_td3_pkt_trace_init(unit);
    286             if (BCM_FAILURE(rv)) {
    287                 goto clean_up;
    288             }
    289 
    290             rv = _bcm_td3_pkt_trace_dop_config_set(unit);
    291             if (BCM_FAILURE(rv)) {
    292                 goto clean_up;
    293             }
    294         }
    295 
    296         /* transmit packet -- support only synchronous mode */
    297         rv = bcm_esw_tx(unit, pkt, NULL);
    298         if (BCM_FAILURE(rv)) {
    299             goto clean_up;
    300         }
    301 
    302         /* Software workaround for TH, recover the original configuration */
    303         if (SOC_IS_TOMAHAWK(unit) &&
    304             soc_feature(unit, soc_feature_th_pkt_trace_sw_war)) {
    305             rv =_bcm_th_pkt_trace_int_lbport_set(unit, port, 0, values);
    306             if (BCM_FAILURE(rv)) {
    307                 goto clean_up;
    308             }
    309         }
    310         soc_timeout_init(&to, SECOND_USEC, 0);
    311 
    312         if (SOC_IS_TOMAHAWKX(unit)) {
    313             for (;;num_trial++) {
    314                 rv = _bcm_th_pkt_trace_info_get(unit, pkt_trace_info);
    315                 if (rv == BCM_E_NONE) {
    316                     break;
    317                 }
    318                 if (soc_timeout_check(&to)) {
    319                     rv = BCM_E_TIMEOUT;
    320                     break;
    321                 }
    322                 sal_usleep(SECOND_USEC/4);
    323             }
    324         } else if (SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit)) {
    325             for (;;num_trial++) {
    326                 rv = _bcm_td3_pkt_trace_info_get(unit, pkt_trace_info);
    327                 if (rv == BCM_E_NONE) {
    328                     break;
    329                 }
    330                 if (soc_timeout_check(&to)) {
    331                     rv = BCM_E_TIMEOUT;
    332                     break;
    333                 }
    334                 sal_usleep(SECOND_USEC/4);
    335             }
    336         }
    337         if (SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit)) {
    338             if (BCM_SUCCESS(rv) && (pp_port > 0)) {
    339                 rv = _bcm_td3_pkt_trace_source_trunk_map_pp_set(unit,
    340                        mod_id,
    341                        pp_port,
    342                        1);
    343                 if (BCM_FAILURE(rv)) {
    344                     goto clean_up;
    345                 }
    346             }
    347         }
    348     }
    349 clean_up:
    350     if (soc_feature(unit, soc_feature_visibility)) {
    351         if (pkt != NULL) {
    352             bcm_pkt_free(unit, pkt);
    353         }
    354         /*mutex unlock */
    355         PKT_TRACE_UNLOCK(unit);
    356         return rv;
    357     }
    358 
    359     return rv;
    360 }
    361 
    362 /*
    363  * Function:
    364  *      _bcm_esw_pkt_trace_raw_data_get
    365  * Purpose:
    366  *      Read visibility packet trace
    367  *      debug information as raw data.
    368  * Parameters:
    369  *      unit          - (IN) Unit number.
    370  *      options       - (IN) CPU packet profile options for loopback port.
    371  *      port          - (IN) Source Masquered port.
    372  *      len           - (IN) Visibility packet data buffer length.
    373  *      data          - (IN) Visibility packet data buffer.
    374  *      raw_data_size - (INOUT) Raw data length.
    375  *      raw_data      - (INOUT) Visibility pkt trace raw data.
    376  * Returns:
    377  *      BCM_E_xxx
    378  * Notes:
    379  */
    380 int _bcm_esw_pkt_trace_raw_data_get(int unit,
    381                                uint32 options,
    382                                uint8 port,
    383                                int len,
    384                                uint8 *data,
    385                                uint32 raw_data_buf_size,
    386                                uint8 *raw_data,
    387                                uint32 *raw_data_size)
    388 {
    389 
    390     bcm_pkt_t *pkt;
    391     int rv = BCM_E_UNAVAIL;
    392     uint8  num_trial = 0;
    393     bcm_module_t mod_id;
    394     bcm_port_t pp_port;
    395     bcm_gport_t gport;
    396     bcm_trunk_t tgid;
    397     int id;
    398 
    399     UNIT_VALID_CHECK(unit);
    400 
    401 #if defined(BCM_TOMAHAWK3_SUPPORT)
    402     if (SOC_IS_TOMAHAWK3(unit)) {
    403         return BCM_E_UNAVAIL;
    404     }
    405 #endif
    406 
    407     if (soc_feature(unit, soc_feature_visibility)) {
    408         soc_timeout_t   to;
    409 
    410         if ((raw_data == NULL) ||
    411             (data == NULL) ||
    412             (raw_data_size == NULL)) {
    413             return BCM_E_PARAM;
    414         }
    415         if (raw_data_buf_size == 0) {
    416             return BCM_E_PARAM;
    417         }
    418         memset(raw_data, 0x0, raw_data_buf_size);
    419         *raw_data_size = raw_data_buf_size;
    420         PKT_TRACE_INIT_CHECK(unit);
    421 
    422         /* mutex lock*/
    423         PKT_TRACE_LOCK(unit);
    424         BCM_IF_ERROR_RETURN(bcm_pkt_alloc(unit, len, 0, &pkt));
    425         pkt->call_back = 0;
    426         pkt->blk_count = 1;
    427         pkt->unit = unit;
    428 
    429         rv = bcm_pkt_memcpy(pkt, 0, data, len);
    430         /*new flag indicating that the packet is for visibility or masquerade */
    431         pkt->flags2 = BCM_PKT_F2_RX_PORT;
    432         /* adding visibility option to packet flag */
    433         pkt->flags2 |= BCM_PKT_F2_VISIBILITY_PKT;
    434         /* setting pkt trace src port number and profile id on the packet */
    435         pkt->rx_port = port;
    436 
    437         /* store profile info to be used during tx*/
    438         _bcm_esw_pkt_trace_cpu_profile_set(unit, options);
    439         if (SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit)) {
    440             SOC_IF_ERROR_RETURN(bcm_esw_port_gport_get(unit, port,
    441                                                   &gport));
    442             SOC_IF_ERROR_RETURN(_bcm_esw_gport_resolve(unit, gport,
    443                                                        &mod_id, &pp_port,
    444                                                        &tgid, &id));
    445             BCM_IF_ERROR_RETURN(
    446                 _bcm_td3_pkt_trace_source_trunk_map_pp_set(unit,
    447                            mod_id,
    448                            pp_port,
    449                            0));
    450             BCM_IF_ERROR_RETURN(_bcm_td3_pkt_trace_init(unit));
    451             BCM_IF_ERROR_RETURN(
    452                 _bcm_td3_pkt_trace_dop_config_set(unit));
    453         }
    454 
    455         /* transmit packet -- support only synchronous mode */
    456         BCM_IF_ERROR_RETURN(bcm_esw_tx(unit, pkt, NULL));
    457         soc_timeout_init(&to, SECOND_USEC, 0);
    458 
    459         if (SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit)) {
    460             for (;;num_trial++) {
    461                 rv = _bcm_td3_pkt_trace_raw_data_get(unit,
    462                                           raw_data_size,
    463                                           raw_data);
    464                 if (rv == BCM_E_NONE) {
    465                     break;
    466                 }
    467                 if (soc_timeout_check(&to)) {
    468                     rv = BCM_E_TIMEOUT;
    469                     break;
    470                 }
    471                 sal_usleep(SECOND_USEC/4);
    472             }
    473         }
    474         bcm_pkt_free(unit, pkt);
    475         if (SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit)) {
    476             BCM_IF_ERROR_RETURN(
    477             _bcm_td3_pkt_trace_source_trunk_map_pp_set(unit,
    478                        mod_id,
    479                        pp_port,
    480                        1));
    481 
    482         }
    483         /*mutex unlock */
    484         PKT_TRACE_UNLOCK(unit);
    485         return rv;
    486     }
    487     return BCM_E_NONE;
    488 }
    489 /*
    490  * Function:    _bcm_esw_pkt_trace_free_resources
    491  * Purpose:     Free pkt trace resources
    492  * Parameters:  unit - SOC unit number
    493  * Returns:     Nothing
    494  */
    495 STATIC void
    496 _bcm_esw_pkt_trace_free_resources(int unit)
    497 {
    498     if (_pkt_trace_mlock[unit]) {
    499         sal_mutex_destroy(_pkt_trace_mlock[unit]);
    500         _pkt_trace_mlock[unit] = NULL;
    501     }
    502 }
    503 
    504 /* De-initialize pkt trace module */
    505 STATIC int
    506 _bcm_esw_pkt_trace_cleanup(int unit)
    507 {
    508     if (soc_feature(unit, soc_feature_visibility)) {
    509         _bcm_esw_pkt_trace_free_resources(unit);
    510 
    511         _pkt_trace_initialized[unit] = FALSE;
    512 
    513         return BCM_E_NONE;
    514     }
    515 
    516     return BCM_E_UNAVAIL;
    517 }
    518 
    519 /* Initialize pkt trace cpu profile table */
    520 int 
    521 _bcm_esw_cpu_pkt_profile_init(int unit)
    522 {
    523     if (SOC_IS_TOMAHAWKX(unit)) {
    524         BCM_IF_ERROR_RETURN(_bcm_th_pkt_trace_cpu_profile_init(unit));
    525         return BCM_E_NONE;
    526     }  else if (SOC_IS_TRIDENT3X(unit)) {
    527         BCM_IF_ERROR_RETURN(_bcm_td3_pkt_trace_cpu_profile_init(unit));
    528         return BCM_E_NONE;
    529     }
    530     return BCM_E_UNAVAIL; 
    531 }
    532 
    533 /* Initialize pkt trace module */
    534 int
    535 bcm_esw_pkt_trace_init(int unit)
    536 {
    537     UNIT_VALID_CHECK(unit);
    538     if (soc_feature(unit, soc_feature_visibility)) {
    539         if (_pkt_trace_initialized[unit]) {
    540             BCM_IF_ERROR_RETURN(_bcm_esw_pkt_trace_cleanup(unit));
    541         }
    542         if (_pkt_trace_mlock[unit] == NULL) {
    543             _pkt_trace_mlock[unit] = sal_mutex_create("packet trace mutex");
    544             if (_pkt_trace_mlock[unit] == NULL) {
    545                 _bcm_esw_pkt_trace_cleanup(unit);
    546                 return BCM_E_MEMORY;
    547             }
    548         }
    549         _pkt_trace_initialized[unit] = TRUE;
    550 
    551         BCM_IF_ERROR_RETURN(_bcm_esw_cpu_pkt_profile_init(unit));
    552 
    553         if (SOC_IS_TRIDENT3(unit) || SOC_IS_MAVERICK2(unit)) {
    554             BCM_IF_ERROR_RETURN(_bcm_td3_pkt_trace_init(unit));
    555         }
    556         return BCM_E_NONE;
    557     }
    558     return BCM_E_UNAVAIL;    
    559 }
    560 
    561 #if defined(BCM_TOMAHAWK3_SUPPORT)
    562 /*
    563  * Function:
    564  *      _bcm_th3_pkt_trace_info_get
    565  *
    566  * Purpose:
    567  *      Generate a visibility packet from the given payload and inject it.
    568  *      And/Or read the visibility packet's ingress pipeline processing
    569  *      information from PTR_RESULTS_BUFFER_XXX. Provide back the raw data
    570  *      and decoded information into the given bcm_switch_pkt_trace_info_t *
    571  *
    572  * Parameters:
    573  *      unit - (IN) Unit number.
    574  *      options - (IN) FLAGS to select pre-configured cpu_pkt_profile register
    575  *                     values and to provide additional instructions to the SDK.
    576  *      port - (IN) Logical port # to inject and/or read visibility data from.
    577  *      len - (IN) Length, in bytes, of the given packet.
    578  *      data - (IN) Packet bytes including the ETH Header.
    579  *      pkt_trace_info - (OUT) Visibility pkt trace process result
    580  *
    581  * Returns:
    582  *      BCM_E_xxx
    583  *
    584  * Notes:
    585  *      When options flag - 'BCM_PKT_TRACE_RETRIEVE_DATA_ONLY' is set,
    586  *      1) SDK would just retrieve the captured instrumentation data and not
    587  *          generate/inject any visibility packet. Hence, parameters 'data' and
    588  *          'len' are ignored.
    589  *      2) Parameter 'port' would accept value '-1'. In such scenario, SDK would
    590  *          poll data on each ingress pipe and return the first available data.
    591  */
    592 int _bcm_th3_pkt_trace_info_get(int unit, uint32 options,
    593                                 uint8 port, int len, uint8 *data,
    594                                 bcm_switch_pkt_trace_info_t *pkt_trace_info)
    595 {
    596     int             rv = BCM_E_UNAVAIL;
    597     int             pipe = -1;
    598     bcm_pkt_t       *pkt = NULL;
    599     soc_timeout_t   to;
    600 
    601     UNIT_VALID_CHECK(unit);
    602 
    603     if (soc_feature(unit, soc_feature_visibility)) {
    604 
    605         /* Check for invalid input */
    606         if (pkt_trace_info == NULL) {
    607             return BCM_E_PARAM;
    608         }
    609         PKT_TRACE_INIT_CHECK(unit);
    610 
    611         if (!(options & BCM_PKT_TRACE_RETRIEVE_DATA_ONLY)) {
    612             /* Check if packet payload is not given */
    613             if (NULL == data) {
    614                 return BCM_E_PARAM;
    615             }
    616 
    617             /* Check if the given port is invalid or not addressable */
    618             if (((uint8)-1) == port) {
    619                 return BCM_E_PORT;
    620             }
    621             if (!IS_ALL_PORT(unit, port)) {
    622                 return BCM_E_PORT;
    623             }
    624         }
    625 
    626         /* If the port is a valid port then extract the pipe from it */
    627         if (((uint8)-1) != port) {
    628             if (SOC_FAILURE(soc_port_pipe_get(unit, port, &pipe))) {
    629                 return BCM_E_PORT;
    630             }
    631         }
    632 
    633         /* Clear the given buffer to begin-with */
    634         memset(pkt_trace_info, 0x0, sizeof(bcm_switch_pkt_trace_info_t));
    635 
    636         /* Mutex lock*/
    637         PKT_TRACE_LOCK(unit);
    638 
    639         /* If Caller asked for synchronous mode then send the packet too */
    640         if (!(options & BCM_PKT_TRACE_RETRIEVE_DATA_ONLY)) {
    641 
    642             /* Allocate and fill-in pkt data structure */
    643             BCM_IF_ERROR_RETURN(bcm_pkt_alloc(unit, len, 0, &pkt));
    644             pkt->call_back = 0;
    645             pkt->blk_count = 1;
    646             pkt->unit = unit;
    647             rv = bcm_pkt_memcpy(pkt, 0, data, len);
    648 
    649             /* New flag indicating that the packet is for visibility or masquerade */
    650             pkt->flags2 = BCM_PKT_F2_RX_PORT | BCM_PKT_F2_VISIBILITY_PKT;
    651             /* Setting pkt trace src port number in the packet */
    652             pkt->rx_port = port;
    653 
    654             /* Store profile info to be used during tx*/
    655             _bcm_esw_pkt_trace_cpu_profile_set(unit, options);
    656 
    657             /* Transmit packet -- only in synchronous mode */
    658             BCM_IF_ERROR_RETURN(bcm_esw_tx(unit, pkt, NULL));
    659         }
    660 
    661         /* Set the time for timeout */
    662         soc_timeout_init(&to, SECOND_USEC, 0);
    663 
    664         /* Start retrieving the captured information */
    665         for (;;) {
    666             rv =
    667              _bcm_th3_pkt_trace_info_retrieve_data(unit, pipe, pkt_trace_info);
    668             if (rv == BCM_E_NONE) {
    669                 break;
    670             }
    671             if (soc_timeout_check(&to)) {
    672                 rv = BCM_E_TIMEOUT;
    673                 break;
    674             }
    675             sal_usleep(SECOND_USEC/4);
    676         }
    677 
    678         /* De-allocate the packet if allocated */
    679         if (NULL != pkt) {
    680             bcm_pkt_free(unit, pkt);
    681         }
    682 
    683         /* Mutex unlock */
    684         PKT_TRACE_UNLOCK(unit);
    685     }
    686     return rv;
    687 }
    688 #endif /* BCM_TOMAHAWK3_SUPPORT */
    689 #endif /* BCM_INSTRUMENTATION_SUPPORT */