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

ctrtest.c (26146B)


      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  * Counter Tests
      8  */
      9 #ifdef BSL_LOG_MODULE
     10 #error "BSL_LOG_MODULE redefined"
     11 #endif
     12 #define BSL_LOG_MODULE BSL_LS_SOCDNX_COUNTER
     13 
     14 #include <sal/types.h>
     15 
     16 #include <appl/diag/system.h>
     17 #include <appl/diag/parse.h>
     18 
     19 
     20 #include <soc/debug.h>
     21 #include <soc/counter.h>
     22 
     23 #include "testlist.h"
     24 
     25 #if defined(BCM_DNX_SUPPORT)
     26 #include <soc/dnx/stat/jer2_stat.h>
     27 #include <soc/dnx/dbal/dbal.h>
     28 #include <src/bcm/dnx/stat/mib/mib_stat_dbal.h>
     29 #endif
     30 
     31 
     32 #if defined BCM_PETRA_SUPPORT
     33 /*
     34 * Get counter type for input port
     35 */
     36 static soc_ctr_type_t
     37 get_port_ctype(int unit, soc_port_t port) {
     38     int blk = -1;
     39     int bindex = -1;
     40     int blktype = -1;
     41     int phy_port;
     42     soc_ctr_type_t ctype = -1;
     43 
     44     if (soc_feature(unit, soc_feature_logical_port_num)) {
     45         phy_port = SOC_INFO(unit).port_l2p_mapping[port];
     46     } else {
     47         phy_port = port;
     48     }
     49     blk = SOC_PORT_BLOCK(unit, phy_port);
     50     bindex = SOC_PORT_BINDEX(unit, phy_port);
     51 
     52     if (blk < 0 && bindex < 0) {
     53         return ctype;
     54     }
     55 
     56     blktype = SOC_BLOCK_INFO(unit, blk).type;
     57 
     58     switch (blktype) {
     59         case SOC_BLK_EPIC:
     60             ctype = SOC_CTR_TYPE_FE;
     61             break;
     62         case SOC_BLK_GPIC:
     63         case SOC_BLK_GPORT:
     64         case SOC_BLK_QGPORT:
     65         case SOC_BLK_SPORT:
     66             ctype = SOC_CTR_TYPE_GE;
     67             break;
     68         case SOC_BLK_XQPORT:
     69         case SOC_BLK_XGPORT:
     70             if (IS_XE_PORT(unit, port) || IS_HG_PORT(unit, port)) {
     71                 ctype = SOC_CTR_TYPE_XE;
     72             } else {
     73                 ctype = SOC_CTR_TYPE_GE;
     74             }
     75             break;
     76         case SOC_BLK_IPIC:
     77         case SOC_BLK_HPIC:
     78             ctype = SOC_CTR_TYPE_HG;
     79             break;
     80         case SOC_BLK_XPIC:
     81         case SOC_BLK_XPORT:
     82         case SOC_BLK_GXPORT:
     83         case SOC_BLK_XLPORT:
     84         case SOC_BLK_XLPORTB0:
     85         case SOC_BLK_XTPORT:
     86         case SOC_BLK_CLPORT:
     87         case SOC_BLK_MXQPORT:
     88         case SOC_BLK_XWPORT:
     89             if (SOC_IS_GREYHOUND(unit) && blktype == SOC_BLK_GXPORT){
     90                 if (SOC_BLOCK_PORT(unit, blk) < 0){
     91                     ctype = SOC_CTR_TYPE_XE;
     92                 } else {
     93                     /* Greyhound GE port with SOC_BLK_GXPORT case*/
     94                     ctype = SOC_CTR_TYPE_GE;
     95                 }
     96             } else {
     97                 ctype = SOC_CTR_TYPE_XE;
     98             }
     99             break;
    100         case SOC_BLK_CLG2PORT:
    101             ctype = SOC_CTR_TYPE_CE;
    102             break;
    103         case SOC_BLK_CLP:
    104         case SOC_BLK_XLP:
    105             if (IS_IL_PORT(unit, port)) {
    106             } else if (IS_CE_PORT(unit, port)) {
    107                 ctype = SOC_CTR_TYPE_CE;
    108             } else if (IS_QSGMII_PORT(unit,port)) {
    109                 ctype = SOC_CTR_TYPE_GE;
    110             } else {
    111                 ctype = SOC_CTR_TYPE_XE;
    112             }
    113             break;
    114         case SOC_BLK_MXQ:
    115             ctype = SOC_CTR_TYPE_GE;
    116             break;
    117         case SOC_BLK_CMIC:
    118             if (soc_feature(unit, soc_feature_cpuport_stat_dma)) {
    119                 ctype = SOC_CTR_TYPE_CPU;
    120                 break;
    121             }
    122         case SOC_BLK_CPIC:
    123         default:
    124             break;
    125         }
    126 
    127     return ctype;
    128 }
    129 #endif
    130 
    131 #if defined BCM_DNX_SUPPORT
    132 
    133 /**
    134  * brief - Test counter rw.
    135  */
    136 static int
    137 test_dnx_ctr_rw(
    138     int unit,
    139     int port,
    140     int counter_id)
    141 {
    142     int rv;
    143     uint64 val, incr;
    144     uint64 mask, pattern,tmp;
    145     int length;
    146     dbal_fields_e field_id;
    147     int loop;
    148     int res = 0;                /* test result - assume pass */
    149 
    150     rv = dnx_cdmib_counter_id_to_dbal_field_id_get(unit, port, counter_id, &field_id);
    151     if (rv != 0)
    152     {
    153         LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - counter type %d is not supported for port %d"), counter_id, port));
    154         res = 1;
    155     }
    156 
    157     rv = soc_jer2_stat_counter_length_get(unit, counter_id, &length);
    158     if (rv != 0)
    159     {
    160         LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - get length failed for counter type %d"), counter_id));
    161         res = 1;
    162     }
    163 
    164     COMPILER_64_MASK_CREATE(mask, length, 0);
    165     COMPILER_64_SET(incr, 0x55555555, 0x55555555);
    166     /*
    167      * The following loop sets pattern to:
    168      *
    169      *	0x00000000
    170      *	0x55555555
    171      *	0xaaaaaaaa
    172      *	0xffffffff
    173      */
    174 
    175     COMPILER_64_ZERO(pattern);
    176     for (loop = 0; loop < 4; loop++)
    177     {
    178         tmp = pattern;
    179 
    180         rv = dnx_cdmib_stat_dbal_set(unit, port, field_id, tmp);
    181         if (rv != 0)
    182         {
    183             LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - set value %08x%08x for counter type %d failed"),
    184                                       COMPILER_64_HI(tmp),COMPILER_64_LO(tmp), counter_id));
    185             res = 1;
    186         }
    187         COMPILER_64_ZERO(val);
    188         rv = dnx_cdmib_stat_dbal_get(unit, port, field_id, &val);
    189         if (rv != 0)
    190         {
    191             LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - get value failed for counter type %d"), counter_id));
    192             res = 1;
    193         }
    194 
    195 	    tmp = val;
    196 	    COMPILER_64_XOR(tmp, pattern);
    197 	    COMPILER_64_AND(tmp, mask);
    198 
    199 	    if (!COMPILER_64_IS_ZERO(tmp))
    200 	    {
    201             COMPILER_64_AND(pattern, mask);
    202             COMPILER_64_AND(val, mask);
    203             LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit,
    204                                         "Counter type %d miscompare:\n"
    205                                         "    wrote     0x%08x%08x\n"
    206                                         "    read      0x%08x%08x\n"),
    207                                         counter_id,
    208                                         COMPILER_64_HI(pattern),
    209                                         COMPILER_64_LO(pattern),
    210                                         COMPILER_64_HI(val),
    211                                         COMPILER_64_LO(val)));
    212             res = 1;
    213 	    }
    214 
    215         COMPILER_64_ADD_64(pattern, incr);
    216     }
    217 
    218     return res;
    219 }
    220 
    221 int ctr_dnx_test_rw(int unit, args_t *a, void *pa)
    222 {
    223     bcm_pbmp_t pbmp;
    224     int port;
    225     int counter_id;
    226     int rv;
    227     int res = 0;                /* test result - assume pass */
    228 
    229     BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
    230     BCM_PBMP_REMOVE(pbmp, PBMP_SFI_ALL(unit));
    231     BCM_PBMP_REMOVE(pbmp, PBMP_IL_ALL(unit));
    232     /*
    233      * Get first cdmib port
    234      */
    235     _SHR_PBMP_FIRST(pbmp, port);
    236 
    237     /*
    238      * Test Counter read/wirte
    239      */
    240     cli_out("Counter read/wirte test - Start\n");
    241 
    242     if (port == -1)
    243     {
    244         LOG_ERROR(BSL_LOG_MODULE,
    245                   (BSL_META_U(unit, "Error - Expecting one eth port at least\n")));
    246         res = 1;
    247     }
    248     else
    249     {
    250         for (counter_id = soc_jer2_counters_cdmib_r64; counter_id <= soc_jer2_counters_cdmib_tbyt; counter_id++)
    251         {
    252             rv = test_dnx_ctr_rw(unit, port, counter_id);
    253             if (rv != 0)
    254             {
    255                 res = 1;  /*set failed flag*/
    256             }
    257         }
    258     }
    259     cli_out("Counter read/wirte test - Done\n");
    260     /*
    261      * Final Result
    262      */
    263     if (res == 0)
    264     {
    265         cli_out("Counter read/wirte test- Pass\n");
    266     }
    267     return res;
    268 
    269 }
    270 
    271 /**
    272  * brief - Test counter width.
    273  */
    274 static int
    275 test_dnx_ctr_width(
    276     int unit,
    277     int port,
    278     int counter_id)
    279 {
    280     int rv;
    281     int res = 0;                /* test result - assume pass */
    282     uint64 val;
    283     dbal_fields_e field_id;
    284     int defined_width, actual_width;
    285 
    286     COMPILER_64_SET(val, 0xffffffff, 0xffffffff);
    287 
    288     rv = dnx_cdmib_counter_id_to_dbal_field_id_get(unit, port, counter_id, &field_id);
    289     if (rv != 0)
    290     {
    291         LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - counter type %d is not supported for port %d"), counter_id, port));
    292         res = 1;
    293     }
    294 
    295     rv = dnx_cdmib_stat_dbal_set(unit, port, field_id, val);
    296     if (rv != 0)
    297     {
    298         LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - set value %08x%08x for counter type %d failed"),
    299                                   COMPILER_64_HI(val),COMPILER_64_LO(val), counter_id));
    300         res = 1;
    301     }
    302 
    303     COMPILER_64_ZERO(val);
    304     rv = dnx_cdmib_stat_dbal_get(unit, port, field_id, &val);
    305     if (rv != 0)
    306     {
    307         LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - get value failed for counter type %d"), counter_id));
    308         res = 1;
    309     }
    310 
    311     rv = soc_jer2_stat_counter_length_get(unit, counter_id, &defined_width);
    312     if (rv != 0)
    313     {
    314         LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit, "Error - get length failed for counter type %d"), counter_id));
    315         res = 1;
    316     }
    317 
    318     actual_width = (_shr_popcount(COMPILER_64_LO(val)) + _shr_popcount(COMPILER_64_HI(val)));
    319     if (defined_width != actual_width)
    320     {
    321         LOG_ERROR(BSL_LOG_MODULE, (BSL_META_U(unit,
    322                                     "Counter type %d width mismatch"
    323                                     "defined width: %d bits, actual: %d bits\n"),
    324                                     counter_id, defined_width, actual_width));
    325         res = 1;
    326     }
    327 
    328     return res;
    329 }
    330 
    331 int ctr_dnx_test_width(int unit, args_t *a, void *pa)
    332 {
    333 
    334     bcm_pbmp_t pbmp;
    335     int port;
    336     int counter_id;
    337     int rv;
    338     int res = 0;                /* test result - assume pass */
    339 
    340     BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(unit));
    341     BCM_PBMP_REMOVE(pbmp, PBMP_SFI_ALL(unit));
    342     BCM_PBMP_REMOVE(pbmp, PBMP_IL_ALL(unit));
    343     /*
    344      * Get first cdmib port
    345      */
    346     _SHR_PBMP_FIRST(pbmp, port);
    347 
    348     /*
    349      * Test Counter widths
    350      */
    351     cli_out("Counter widths test - Start\n");
    352 
    353     if (port == -1)
    354     {
    355         LOG_ERROR(BSL_LOG_MODULE,
    356                   (BSL_META_U(unit, "Error - Expecting one eth port at least\n")));
    357         res = 1;
    358     }
    359     else
    360     {
    361         for (counter_id = soc_jer2_counters_cdmib_r64; counter_id <= soc_jer2_counters_cdmib_tbyt; counter_id++)
    362         {
    363             rv = test_dnx_ctr_width(unit, port, counter_id);
    364             if (rv != 0)
    365             {
    366                 res = 1;  /*set failed flag*/
    367             }
    368         }
    369     }
    370     cli_out("Counter widths test - Done\n");
    371     /*
    372      * Final Result
    373      */
    374     if (res == 0)
    375     {
    376         cli_out("Counter widths test- Pass\n");
    377     }
    378     return res;
    379 }
    380 
    381 #endif
    382 
    383 /*
    384  * Given a counter type, return a port that can be used for it.
    385  * Actually returns the first port of the appropriate type
    386  */
    387 static soc_port_t
    388 find_ctype_port(int unit, soc_ctr_type_t ctype)
    389 {
    390     switch (ctype) {
    391     case SOC_CTR_TYPE_FE:
    392 	if (SOC_PORT_NUM(unit, fe) < 1) {
    393 	    return -1;
    394 	}
    395 	return SOC_PORT(unit, fe, 0);
    396     case SOC_CTR_TYPE_GE:
    397     case SOC_CTR_TYPE_GFE:
    398 	if (SOC_PORT_NUM(unit, ge) < 1) {
    399 	    return -1;
    400 	}
    401 #ifdef BCM_GREYHOUND_SUPPORT
    402        if (SOC_IS_GREYHOUND(unit) && IS_XL_PORT(unit, SOC_PORT(unit, ge, 0))) {
    403            return -1;
    404        }
    405 #endif /* BCM_GREYHOUND_SUPPORT */
    406 	return SOC_PORT(unit, ge, 0);
    407     case SOC_CTR_TYPE_XE:
    408 	if (SOC_PORT_NUM(unit, xe) < 1) {
    409 	    return -1;
    410 	}
    411 #if defined BCM_PETRA_SUPPORT
    412     /*For QUX,XE ports in Viper core use ge counter type*/
    413     if (SOC_IS_QUX(unit)) {
    414         int i, port;
    415         for (i=0;i<SOC_PORT_NUM(unit, xe);i++) {
    416             port = SOC_PORT(unit, xe, i);
    417             if (SOC_CTR_TYPE_XE == get_port_ctype(unit,port)) {
    418                 return port;
    419             }
    420         }
    421         if (SOC_PORT_NUM(unit, xe) == i) {
    422             return -1;
    423         }
    424     } else
    425 #endif
    426     {
    427         return SOC_PORT(unit, xe, 0);
    428     }
    429     case SOC_CTR_TYPE_HG:
    430 	if (SOC_PORT_NUM(unit, hg) < 1) {
    431 	    return -1;
    432 	}
    433 	return SOC_PORT(unit, hg, 0);
    434     default:
    435 	return -1;
    436     }
    437 }
    438 
    439 /*
    440  * Routine to test the width of a counter in bits, as verified against
    441  * the width listed in the regsfile, for counters up to 32 bits.
    442  */
    443 
    444 static int
    445 test_width32(int unit, soc_reg_t ctr_reg, soc_port_t port)
    446 {
    447     uint32		val = 0;
    448     char		*name;
    449     int			regsfile_width, actual_width;
    450 #if  defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    451     int			r;
    452 #endif  /* BCM_ESW_SUPPORT */
    453 
    454     name = NULL;
    455     regsfile_width = SOC_REG_INFO(unit, ctr_reg).fields[0].len;
    456 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    457     if (soc_feature(unit, soc_feature_counter_parity) ||
    458         soc_reg_field_valid(unit, ctr_reg, PARITYf) ) {
    459         int i = 0;
    460         while((SOC_REG_INFO(unit, ctr_reg).fields + i) != NULL) { 
    461             if (SOC_REG_INFO(unit, ctr_reg).fields[i].field == COUNTf) {
    462                 regsfile_width = SOC_REG_INFO(unit, ctr_reg).fields[i].len;
    463                 break;
    464             }
    465             i++;
    466         }
    467     }
    468 #endif
    469 
    470 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    471     name = SOC_REG_NAME(unit, ctr_reg);
    472 
    473     if (soc_feature(unit, soc_feature_prime_ctr_writes)) {
    474         r = soc_counter_set32(unit, port, ctr_reg, 0, ~0);
    475     } else {
    476         r = soc_reg32_set(unit, ctr_reg, port, 0, ~0);
    477     }
    478 
    479     if ((r < 0) ||
    480         (r = soc_reg32_get(unit, ctr_reg, port, 0, &val)) < 0) {
    481         test_error(unit,
    482                    "Can't access counter %s.%s: %s\n",
    483                    name, SOC_PORT_NAME(unit, port), soc_errmsg(r));
    484         return -1;
    485     }
    486     if (soc_feature(unit, soc_feature_counter_parity) ||
    487         soc_reg_field_valid(unit, ctr_reg, PARITYf) ) {
    488         int bits;
    489         bits = soc_reg_field_length(unit, ctr_reg, COUNTf);
    490         val &= ((bits == 32 ? 0 : 1 << bits) - 1);
    491     }
    492 #endif
    493 
    494     actual_width = _shr_popcount(val);
    495 
    496     if (regsfile_width != actual_width) {
    497 	test_error(unit,
    498 		   "Counter %s.%s width mismatch: "
    499 		   "regsfile: %d bits, actual: %d bits\n",
    500 		   name, SOC_PORT_NAME(unit, port), regsfile_width,
    501                    actual_width);
    502 	return -1;
    503     }
    504     return 0;
    505 }
    506 
    507 /*
    508  * Routine to test the width of a counter in bits, as verified against
    509  * the width listed in the regsfile, for counters over 32 bits.
    510  */
    511 
    512 static int
    513 test_width64(int unit, soc_reg_t ctr_reg, soc_port_t port)
    514 {
    515     uint64		val;
    516     char		*name;
    517     int			regsfile_width, actual_width;
    518 #if  defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    519     int			r;
    520 #endif
    521 
    522     name = NULL;
    523     regsfile_width = SOC_REG_INFO(unit, ctr_reg).fields[0].len;
    524 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    525     if (soc_feature(unit, soc_feature_counter_parity) ||
    526         soc_reg_field_valid(unit, ctr_reg, PARITYf)) {
    527         int i = 0;
    528         while((SOC_REG_INFO(unit, ctr_reg).fields + i) != NULL) { 
    529             if (SOC_REG_INFO(unit, ctr_reg).fields[i].field == COUNTf) {
    530                 regsfile_width = SOC_REG_INFO(unit, ctr_reg).fields[i].len;
    531                 break;
    532             }
    533             i++;
    534         }
    535     }
    536 #endif
    537 
    538     COMPILER_64_SET(val, 0xffffffff, 0xffffffff);
    539 
    540 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    541     name = SOC_REG_NAME(unit, ctr_reg);
    542     if ((r = soc_reg64_set(unit, ctr_reg, port, 0, val)) < 0 ||
    543 	(r = soc_reg64_get(unit, ctr_reg, port, 0, &val)) < 0) {
    544 	test_error(unit,
    545 		   "Can't access counter %s.%s: %s\n",
    546 		   name, SOC_PORT_NAME(unit, port), soc_errmsg(r));
    547 	return -1;
    548     }
    549     val = soc_reg64_field_get(unit, ctr_reg, val,
    550                               SOC_REG_INFO(unit, ctr_reg).fields[0].field);
    551 #endif
    552     actual_width = (_shr_popcount(COMPILER_64_LO(val)) +
    553 		    _shr_popcount(COMPILER_64_HI(val)));
    554 
    555     if (regsfile_width != actual_width) {
    556 	test_error(unit,
    557 		   "Counter %s.%s width mismatch: "
    558 		   "regsfile: %d bits, actual: %d bits\n",
    559 		   name, SOC_PORT_NAME(unit, port),
    560                    regsfile_width, actual_width);
    561 	return -1;
    562     }
    563     return 0;
    564 }
    565 
    566 int
    567 ctr_test_width(int unit, args_t *a, void *pa)
    568 /*
    569  * Function: 	ctr_test_width
    570  * Purpose:	Test the widths of all counters as compared to regsfile
    571  * Parameters:	u - unit #.
    572  *		a - pointer to arguments.
    573  *		pa - ignored cookie.
    574  * Returns:	0
    575  */
    576 {
    577     int			i;
    578     soc_ctr_type_t      ctype;
    579     soc_reg_t           reg;
    580     soc_port_t		port;
    581 
    582     COMPILER_REFERENCE(a);
    583     COMPILER_REFERENCE(pa);
    584 
    585 #if defined BCM_DNX_SUPPORT
    586     return ctr_dnx_test_width(unit, a, pa);
    587 #endif
    588 
    589 #ifdef BCM_SHADOW_SUPPORT
    590     /* coverity[dead_error_line] */
    591     if (SOC_IS_SHADOW(unit)) {
    592         if (soc_reg_field32_modify(unit, ISW2_HW_CONTROLr, REG_PORT_ANY,
    593                                    XGS_COUNTER_COMPAT_MODEf, 1) < 0) {
    594             return -1;
    595         }
    596     }
    597 #endif
    598     for (ctype = SOC_CTR_TYPE_FE; ctype < SOC_CTR_NUM_TYPES; ctype++) {
    599         if (SOC_HAS_CTR_TYPE(unit, ctype)) {
    600 	    port = find_ctype_port(unit, ctype);
    601 	    if (port < 0) {
    602 		continue;
    603 	    }
    604             for (i = 0; i < SOC_CTR_MAP_SIZE(unit, ctype); i++) {
    605                 reg = SOC_CTR_TO_REG(unit, ctype, i);
    606                 if (!SOC_COUNTER_INVALID(unit, reg) && 
    607                       !(SOC_REG_INFO(unit, reg).flags & SOC_REG_FLAG_RO)) {
    608 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    609                     soc_regaddrinfo_t   ainfo;
    610                     uint64		mask;
    611                     uint32              addr;
    612                     int                 block;
    613                     uint8               at;
    614 
    615                     if (!SOC_REG_PORT_VALID(unit, reg, port)) {
    616                         continue;
    617                     }
    618                     addr = soc_reg_addr_get(unit, reg, port, 0,
    619                                             SOC_REG_ADDR_OPTION_NONE,
    620                                             &block, &at);
    621                     soc_regaddrinfo_extended_get(unit, &ainfo, block, at, addr);
    622                     if (SOC_COUNTER_INVALID(unit, ainfo.reg)) {
    623                         continue;
    624                     }
    625                     if (reg_mask_subset(unit, &ainfo, &mask)) {
    626                         /* Unimplemented in HW, skip */
    627                         continue;
    628                     }
    629 #endif
    630 
    631     	    if (SOC_REG_IS_COUNTER_TABLE(unit, reg) ||
    632                 SOC_REG_IS_64(unit, reg)) {
    633 			test_width64(unit, reg, port);
    634 		    } else {
    635 			test_width32(unit, reg, port);
    636 		    }
    637                 }
    638             }
    639         }
    640     }
    641 #ifdef BCM_SHADOW_SUPPORT
    642     if (SOC_IS_SHADOW(unit)) {
    643         if (soc_reg_field32_modify(unit, ISW2_HW_CONTROLr, REG_PORT_ANY,
    644                                    XGS_COUNTER_COMPAT_MODEf, 0) < 0) {
    645             return -1;
    646         }
    647     }
    648 #endif
    649 
    650     return 0;
    651 }
    652 
    653 /*
    654  * Routine to write a counter with several patterns and compare.
    655  * Works on counters <= 32 bits.
    656  */
    657 
    658 static int
    659 test_rw32(int unit, soc_reg_t ctr_reg, soc_port_t port)
    660 {
    661     char              *name;
    662     volatile uint32   pattern;  /* SiByte1250 workaround */
    663     uint32            mask, val;
    664 #if  defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    665     uint32            pattern_mask;
    666     int               r;
    667 #endif
    668     int               bits, patno;
    669 
    670     name = NULL;
    671     bits = SOC_REG_INFO(unit, ctr_reg).fields[0].len;
    672 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    673     if (soc_feature(unit, soc_feature_counter_parity) ||
    674         soc_reg_field_valid(unit, ctr_reg, PARITYf)) {
    675         int i = 0;
    676         while((SOC_REG_INFO(unit, ctr_reg).fields + i) != NULL) { 
    677             if (SOC_REG_INFO(unit, ctr_reg).fields[i].field == COUNTf) {
    678                 bits = SOC_REG_INFO(unit, ctr_reg).fields[i].len;
    679                 break;
    680             }
    681             i++;
    682         }
    683     }
    684 #endif
    685     mask = (bits == 32 ? 0 : 1 << bits) - 1;
    686 
    687     /*
    688      * The following loop sets pattern to:
    689      *
    690      *	0x00000000
    691      *	0x55555555
    692      *	0xaaaaaaaa
    693      *	0xffffffff
    694      */
    695 
    696     pattern = 0x00000000;
    697     val = 0;
    698 
    699     for (patno = 0; patno < 4; patno++) {
    700 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    701         name = SOC_REG_NAME(unit, ctr_reg);
    702         pattern_mask = pattern & mask;
    703         if (soc_feature(unit, soc_feature_prime_ctr_writes)) {
    704             r = soc_counter_set32(unit, port, ctr_reg, 0, pattern_mask);
    705         } else {
    706             r = soc_reg32_set(unit, ctr_reg, port, 0, pattern_mask);
    707         }
    708         if (r < 0) {
    709             val = pattern_mask;
    710 	    test_error(unit,
    711 		       "Can't write counter %s.%s: %s\n",
    712 		       name, SOC_PORT_NAME(unit, port), soc_errmsg(r));
    713         } else if ((r = soc_reg32_get(unit, ctr_reg, port, 0, &val)) < 0) {
    714 	    test_error(unit,
    715 		       "Can't access counter %s.%s: %s\n",
    716 		       name, SOC_PORT_NAME(unit, port), soc_errmsg(r));
    717         }
    718 #endif
    719         if (((val ^ pattern) & mask) != 0) {
    720 	    uint32 reread = 0;
    721 
    722 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    723 	   (void) soc_reg32_get(unit, ctr_reg, port, 0, &reread);
    724 #endif
    725 
    726 	    test_error(unit,
    727 		       "Counter %s.%s miscompare: \n"
    728                        "    wrote     0x%08x\n"
    729                        "    read      0x%08x\n"
    730                        "    re-read   0x%08x\n",
    731 		       name, SOC_PORT_NAME(unit, port),
    732 		       pattern & mask,
    733 		       val & mask,
    734 		       reread & mask);
    735 	}
    736 
    737 	pattern += 0x55555555;
    738     }
    739     return 0;
    740 }
    741 
    742 /*
    743  * Routine to write a counter with several patterns and compare.
    744  * Works on counters over 32 bits.
    745  */
    746 
    747 static int
    748 test_rw64(int unit, soc_reg_t ctr_reg, soc_port_t port)
    749 {
    750     char		*name;
    751     uint64		mask, pattern, tmp;
    752     uint64		val, incr;
    753     int			bits, patno;
    754 #if  defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    755     int                 r;
    756 #endif /* BCM_ESW_SUPPORT */
    757 
    758     name = NULL;
    759     bits = SOC_REG_INFO(unit, ctr_reg).fields[0].len;
    760 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    761     if (soc_feature(unit, soc_feature_counter_parity) ||
    762         soc_reg_field_valid(unit, ctr_reg, PARITYf) ) {
    763         int i = 0;
    764         while((SOC_REG_INFO(unit, ctr_reg).fields + i) != NULL) { 
    765             if (SOC_REG_INFO(unit, ctr_reg).fields[i].field == COUNTf) {
    766                 bits = SOC_REG_INFO(unit, ctr_reg).fields[i].len;
    767                 break;
    768             }
    769             i++;
    770         }
    771     }
    772 #endif
    773 
    774     COMPILER_64_MASK_CREATE(mask, bits, 0);
    775     COMPILER_64_SET(incr, 0x55555555, 0x55555555);
    776     COMPILER_64_SET(val, 0x0, 0x0);
    777 
    778     /*
    779      * The following loop sets pattern to:
    780      *
    781      *	0x00000000
    782      *	0x55555555
    783      *	0xaaaaaaaa
    784      *	0xffffffff
    785      */
    786 
    787     COMPILER_64_ZERO(pattern);
    788 
    789     for (patno = 0; patno < 4; patno++) {
    790 	tmp = pattern;
    791 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    792         name = SOC_REG_NAME(unit, ctr_reg);
    793 	if ((r = soc_reg64_set(unit, ctr_reg, port, 0, tmp)) < 0) {
    794             val = tmp;
    795 	    test_error(unit,
    796 		       "Can't write counter %s.%s: %s\n",
    797 		       name, SOC_PORT_NAME(unit, port), soc_errmsg(r));
    798 	} else if ((r = soc_reg64_get(unit, ctr_reg, port, 0, &val)) < 0) {
    799 	    test_error(unit,
    800 		       "Can't access counter %s.%s: %s\n",
    801 		       name, SOC_PORT_NAME(unit, port), soc_errmsg(r));
    802         }
    803 #endif
    804 	    tmp = val;
    805 	    COMPILER_64_XOR(tmp, pattern);
    806 	    COMPILER_64_AND(tmp, mask);
    807 
    808 	    if (!COMPILER_64_IS_ZERO(tmp)) {
    809 		uint64 reread;
    810 
    811                 COMPILER_64_ZERO(reread);
    812 
    813 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    814 		(void) soc_reg64_get(unit, ctr_reg, port, 0, &reread);
    815 #endif
    816 
    817 		COMPILER_64_AND(pattern, mask);
    818 		COMPILER_64_AND(val, mask);
    819 
    820 		test_error(unit,
    821 			   "Counter %s.%s miscompare:\n"
    822 			   "    wrote     0x%08x%08x\n"
    823                            "    read      0x%08x%08x\n"
    824 			   "    re-read   0x%08x%08x\n",
    825 			   name, SOC_PORT_NAME(unit, port),
    826 			   COMPILER_64_HI(pattern),
    827 			   COMPILER_64_LO(pattern),
    828 			   COMPILER_64_HI(val),
    829 			   COMPILER_64_LO(val),
    830 			   COMPILER_64_HI(reread),
    831 			   COMPILER_64_LO(reread));
    832 	    }
    833 
    834 	COMPILER_64_ADD_64(pattern, incr);
    835     }
    836     return 0;
    837 }
    838 
    839 int
    840 ctr_test_rw(int unit, args_t *a, void *pa)
    841 /*
    842  * Function: 	ctr_test_rw
    843  * Purpose:	Run test values through all counter registers
    844  * Parameters:	u - unit #.
    845  *		a - pointer to arguments.
    846  *		pa - ignored cookie.
    847  * Returns:	0
    848  */
    849 {
    850     int			i;
    851     soc_reg_t           reg;
    852     soc_ctr_type_t      ctype;
    853     soc_port_t		port;
    854 
    855     COMPILER_REFERENCE(a);
    856     COMPILER_REFERENCE(pa);
    857 
    858 #if defined BCM_DNX_SUPPORT
    859     return ctr_dnx_test_rw(unit, a, pa);
    860 #endif
    861 
    862 #ifdef BCM_SHADOW_SUPPORT
    863     /* coverity[dead_error_line] */
    864     if (SOC_IS_SHADOW(unit)) {
    865         if (soc_reg_field32_modify(unit, ISW2_HW_CONTROLr, REG_PORT_ANY,
    866                                    XGS_COUNTER_COMPAT_MODEf, 1) < 0) {
    867             return -1;
    868         }
    869     }
    870 #endif
    871 
    872     for (ctype = SOC_CTR_TYPE_FE; ctype < SOC_CTR_NUM_TYPES; ctype++) {
    873         if (SOC_HAS_CTR_TYPE(unit, ctype)) {
    874 	    port = find_ctype_port(unit, ctype);
    875 	    if (port < 0) {
    876 		continue;
    877 	    }
    878             for (i = 0; i < SOC_CTR_MAP_SIZE(unit, ctype); i++) {
    879                 reg = SOC_CTR_TO_REG(unit, ctype, i);
    880                 if (!SOC_COUNTER_INVALID(unit, reg) && 
    881                       !(SOC_REG_INFO(unit, reg).flags & SOC_REG_FLAG_RO)) {
    882 #if defined(BCM_ESW_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    883                     soc_regaddrinfo_t   ainfo;
    884                     uint64		mask;
    885                     uint32              addr;
    886                     int                 block;
    887                     uint8               at;
    888                     
    889                     if (!SOC_REG_PORT_VALID(unit, reg, port)) {
    890                         continue;
    891                     }
    892                     addr = soc_reg_addr_get(unit, reg, port, 0,
    893                                             SOC_REG_ADDR_OPTION_NONE,
    894                                             &block, &at);
    895                     soc_regaddrinfo_extended_get(unit, &ainfo, block, at, addr);
    896                     if (SOC_COUNTER_INVALID(unit, ainfo.reg)) {
    897                         continue;
    898                     }
    899                     if (reg_mask_subset(unit, &ainfo, &mask)) {
    900                         /* Unimplemented in HW, skip */
    901                         continue;
    902                     }
    903 #endif
    904     	    if (SOC_REG_IS_COUNTER_TABLE(unit, reg) ||
    905                 SOC_REG_IS_64(unit, reg)) {
    906 			test_rw64(unit, reg, port);
    907 		    } else {
    908 			test_rw32(unit, reg, port);
    909 		    }
    910                 }
    911             }
    912         }
    913     }
    914 #ifdef BCM_SHADOW_SUPPORT
    915     if (SOC_IS_SHADOW(unit)) {
    916         if (soc_reg_field32_modify(unit, ISW2_HW_CONTROLr, REG_PORT_ANY,
    917                                    XGS_COUNTER_COMPAT_MODEf, 0) < 0) {
    918             return -1;
    919         }
    920     }
    921 #endif
    922 
    923     return 0;
    924 }