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

linkscan.c (10328B)


      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  * tr60 - Linkscan MDIO
      8  * Loop reading the MII registers ID0 and ID1(RO registers), verifying
      9  * they never change
     10  */
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <sal/types.h>
     15 #include <sal/core/boot.h>
     16 #include <sal/appl/sal.h>
     17 #include <appl/diag/system.h>
     18 #include <appl/diag/parse.h>
     19 #include <shared/bsl.h>
     20 #include <soc/types.h>
     21 #include <soc/debug.h>
     22 
     23 #include <soc/enet.h>
     24 #include <soc/counter.h>
     25 #include <soc/register.h>
     26 #include <soc/memory.h>
     27 #include <soc/phyctrl.h>
     28 #include <soc/phyreg.h>
     29 #include <soc/phy.h>
     30 #if defined(PORTMOD_SUPPORT)
     31 #include <soc/portmod/portmod.h>
     32 #endif
     33 
     34 #include <bcm/error.h>
     35 #include <bcm/port.h>
     36 #include <bcm/vlan.h>
     37 #include <bcm/link.h>
     38 #include <appl/test/loopback.h>
     39 
     40 #include "testlist.h"
     41 #include <appl/diag/system.h>
     42 #include <appl/diag/progress.h>
     43 
     44 #if defined(BCM_PETRA_SUPPORT)
     45 #include <soc/dpp/port_sw_db.h>
     46 #endif
     47 
     48 #ifdef PORTMOD_SUPPORT
     49 #include <soc/portmod/portmod.h>
     50 #include <soc/portmod/portmod_common.h>
     51 #endif /* PORTMOD_SUPPORT */
     52 #include <soc/esw/portctrl.h>
     53 
     54 #if defined (BCM_ESW_SUPPORT) || defined (BCM_PETRA_SUPPORT) || defined(BCM_DFE_SUPPORT) || defined(BCM_DNX_SUPPORT) || defined(BCM_DNXF_SUPPORT)
     55 
     56 typedef struct linkscan_work_s{
     57     int         ls_scan[SOC_MAX_NUM_PORTS];
     58     uint32      ls_id0[SOC_MAX_NUM_PORTS];
     59     uint32      ls_id1[SOC_MAX_NUM_PORTS];
     60     uint32      ls_flags[SOC_MAX_NUM_PORTS]; /* Internal phy? */
     61     pbmp_t      ls_ports;
     62     int         ls_reads;               /* # reads to perform */
     63 } linkscan_work_t;
     64 
     65 static linkscan_work_t *ls_work[SOC_MAX_NUM_DEVICES];
     66 
     67 int
     68 ls_test(int u, args_t *args, void *pa)
     69 {
     70     linkscan_work_t     *ls = (linkscan_work_t *)pa;
     71     soc_port_t          p;
     72     int                 rv, r;
     73     uint32              id0, id1;
     74 
     75     progress_init(ls->ls_reads, 1, 0);
     76     /*
     77      * Loop reading the MII registers ID0 and ID1, verifying they never change
     78      */
     79 
     80     for (r = 0; r < ls->ls_reads; ) {
     81         PBMP_ITER(ls->ls_ports, p) {
     82             rv = bcm_port_phy_get(u, p, ls->ls_flags[p],
     83                      BCM_PORT_PHY_REG_INDIRECT_ADDR(0, 0, MII_PHY_ID0_REG),
     84                                   &id0);
     85             if (rv < 0) {
     86                 test_error(u, "Failed to read port %d Phy-id %d ID0: %s\n",
     87                            p, PORT_TO_PHY_ADDR(u, p), bcm_errmsg(rv));
     88             }
     89             rv = bcm_port_phy_get(u, p, ls->ls_flags[p],
     90                      BCM_PORT_PHY_REG_INDIRECT_ADDR(0, 0, MII_PHY_ID1_REG),
     91                                   &id1);
     92             if (rv < 0) {
     93                 test_error(u, "Failed to read port %d Phy-id %d ID1: %s\n",
     94                            p, PORT_TO_PHY_ADDR(u, p), bcm_errmsg(rv));
     95             }
     96             if ((id0 != ls->ls_id0[p]) || (id1 != ls->ls_id1[p])) {
     97                 test_error(u,
     98                            "Register Compare error: port %s: "
     99                            "Expected phy id 0x%04x 0x%04x, "
    100                            "Read phy id 0x%04x 0x%04x",
    101                            SOC_PORT_NAME(u, p),
    102                            ls->ls_id0[p], ls->ls_id1[p], id0, id1);
    103             }
    104             r += 2;
    105             progress_report(2);
    106         }
    107     }
    108     progress_done();
    109     return(0);
    110 }
    111 
    112 int
    113 ls_test_init(int u, args_t *args, void **pa)
    114 {
    115     soc_port_t          p;
    116     int                 rv;
    117     linkscan_work_t     *ls;
    118     parse_table_t       pt;
    119     pbmp_t              pbmp;
    120 #if defined(PORTMOD_SUPPORT) 
    121     phymod_core_access_t core_access_arr[MAX_NUM_CORES];
    122     int max_buf = MAX_NUM_CORES; 
    123     int nof_cores, is_most_ext;
    124 #endif
    125 
    126     if (ls_work[u] == NULL) {
    127         ls_work[u] = sal_alloc(sizeof(linkscan_work_t), "ls_test");
    128         if (ls_work[u] == NULL) {
    129             test_error(u, "ERROR: cannot allocate memory\n");
    130             return -1;
    131         }
    132         sal_memset(ls_work[u], 0, sizeof(linkscan_work_t));
    133     }
    134     ls = ls_work[u];
    135 
    136     parse_table_init(u, &pt);
    137     parse_table_add(&pt, "Readcount", PQ_INT, (void *)100000, &ls->ls_reads,
    138                     NULL);
    139 
    140     if (parse_arg_eq(args, &pt) < 0 || ARG_CNT(args) != 0) {
    141         test_error(u, "%s: Invalid Option: %s\n", ARG_CMD(args),
    142                    ARG_CUR(args) ? ARG_CUR(args) : "*");
    143     }
    144     parse_arg_eq_done(&pt);
    145 
    146     /*
    147      * Save old state, and enable H/W link scanning on FE ports.
    148      */
    149 
    150     BCM_PBMP_CLEAR(pbmp);
    151 
    152     BCM_PBMP_ASSIGN(pbmp, PBMP_FE_ALL(u));      /* Handle Strata 24+2 */
    153 
    154     if (BCM_PBMP_IS_NULL(pbmp)) {
    155         BCM_PBMP_ASSIGN(pbmp, PBMP_GE_ALL(u));
    156     }
    157 
    158     if (BCM_PBMP_IS_NULL(pbmp)) {
    159         BCM_PBMP_ASSIGN(pbmp, PBMP_XE_ALL(u));
    160     }
    161 
    162 #ifdef BCM_XGS3_SWITCH_SUPPORT
    163     if (SOC_IS_XGS3_SWITCH(u)) { 
    164         BCM_PBMP_ASSIGN(pbmp, PBMP_PORT_ALL(u));
    165     } 
    166 #endif
    167 
    168 #if defined(BCM_PETRA_SUPPORT)
    169     if (SOC_IS_ARAD(u)) {
    170         uint32 flags;
    171         pbmp_t stat_ifs;
    172 
    173         BCM_PBMP_CLEAR(stat_ifs);
    174         PBMP_ITER(pbmp, p){
    175             rv = soc_port_sw_db_flags_get(u, p, &flags);
    176             if (0 > rv) {
    177             test_error(u, "soc_port_sw_db_flags_get: port %d: %s\n",
    178                        p, bcm_errmsg(rv));
    179             sal_free(ls);
    180             ls_work[u] = NULL;
    181             return(-1);
    182             }
    183             if(SOC_PORT_IS_STAT_INTERFACE(flags)) {
    184                 BCM_PBMP_PORT_ADD(stat_ifs, p);
    185             }
    186         }
    187         BCM_PBMP_REMOVE(pbmp, stat_ifs);
    188     }
    189 #endif
    190 
    191 #if defined(BCM_DFE_SUPPORT) || defined(BCM_PETRA_SUPPORT)
    192     if (SOC_IS_DFE(u) || SOC_IS_ARAD(u)) {
    193         BCM_PBMP_OR(pbmp, PBMP_SFI_ALL(u));
    194     }
    195 #endif
    196 
    197     if (BCM_PBMP_IS_NULL(pbmp)) {
    198         test_error(u, "Test not available on %s\n", soc_dev_name(u));
    199         sal_free(ls);
    200         ls_work[u] = NULL;
    201         return(-1);
    202     }
    203 
    204     if (bsl_check(bslLayerAppl, bslSourceTests, bslSeverityNormal, u)) {
    205         char    s[FORMAT_PBMP_MAX];
    206         (void)format_pbmp(u, s, sizeof(s), pbmp);
    207         LOG_INFO(BSL_LS_APPL_TESTS,
    208                  (BSL_META_U(u,
    209                              "Running on ports: %s\n"), s));
    210     }
    211 
    212     PBMP_ITER(pbmp, p) {
    213         if (0 > (rv = bcm_port_linkscan_get(u, p, &ls->ls_scan[p]))) {
    214             test_error(u, "bcm_port_linkscan_get: port %d: %s\n",
    215                        p, bcm_errmsg(rv));
    216             sal_free(ls);
    217             ls_work[u] = NULL;
    218             return(-1);
    219         }
    220     }
    221 
    222     /* At this point, can restore from it */
    223 
    224     BCM_PBMP_CLEAR(ls->ls_ports);
    225     *pa = (void *)ls;
    226 
    227     PBMP_ITER(pbmp, p) {
    228         /* Internal or external phy? */
    229         if (!SOC_USE_PORTCTRL(u)) {
    230             ls->ls_flags[p] =
    231                 (PORT_TO_PHY_ADDR(u, p) == PORT_TO_PHY_ADDR_INT(u, p)) ?
    232                 SOC_PHY_INTERNAL : 0;
    233         } 
    234 #if defined(PORTMOD_SUPPORT)            
    235         else {
    236             rv = portmod_port_core_access_get(u, p, 0, max_buf, 
    237                                     core_access_arr, &nof_cores, &is_most_ext);
    238 
    239             if (rv < 0) {
    240             test_error(u, "portmod_port_chain_core_access_get port %d: %s\n",
    241                        p, bcm_errmsg(rv));
    242             sal_free(ls);
    243             ls_work[u] = NULL;
    244             return(-1);
    245             }
    246             ls->ls_flags[p] = 
    247                 (is_most_ext == 1) ?
    248                 SOC_PHY_INTERNAL : 0;
    249         }
    250 #endif
    251         if (0 > (rv = bcm_port_linkscan_set(u, p, BCM_LINKSCAN_MODE_HW))) {
    252             test_error(u, "bcm_port_linkscan_set: port %d: %s\n",
    253                        p, bcm_errmsg(rv));
    254             sal_free(ls);
    255             ls_work[u] = NULL;
    256             return(-1);
    257         }
    258         rv = bcm_port_phy_get(u, p, ls->ls_flags[p],
    259              BCM_PORT_PHY_REG_INDIRECT_ADDR(0, 0, MII_PHY_ID0_REG),
    260                               &ls->ls_id0[p]);
    261         if (rv < 0) {
    262             if (rv == SOC_E_UNAVAIL) {
    263                 /* Skip this port, PHY read unsupported. NULL PHY? */
    264                 /* Restore linkscan state here */
    265                 if (0 > (rv = bcm_port_linkscan_set(u, p, ls->ls_scan[p]))) {
    266                     test_error(u, "bcm_port_linkscan_set: port %d: %s\n",
    267                                p, bcm_errmsg(rv));
    268                     sal_free(ls);
    269                     ls_work[u] = NULL;
    270                     return(-1);
    271                 }
    272                 LOG_WARN(BSL_LS_APPL_TESTS,
    273                          (BSL_META_U(u,
    274                                      "Port %d skipped due to unsupported PHY reads.\n"), p));
    275                 continue;
    276             } else {
    277                 test_error(u, "Failed to read port %d Phy-addr %d ID0: %s\n",
    278                            p, PORT_TO_PHY_ADDR(u, p), bcm_errmsg(rv));
    279                 sal_free(ls);
    280                 ls_work[u] = NULL;
    281                 return(-1);
    282             }
    283         }
    284         rv = bcm_port_phy_get(u, p, ls->ls_flags[p],
    285              BCM_PORT_PHY_REG_INDIRECT_ADDR(0, 0, MII_PHY_ID1_REG),
    286                               &ls->ls_id1[p]);
    287         if (rv < 0) {
    288             test_error(u, "Failed to read port %d Phy-addr %d ID1: %s\n",
    289                        p, PORT_TO_PHY_ADDR(u, p), bcm_errmsg(rv));
    290             sal_free(ls);
    291             ls_work[u] = NULL;
    292             return(-1);
    293         }
    294         LOG_INFO(BSL_LS_APPL_TESTS,
    295                  (BSL_META_U(u,
    296                              "unit %d port %s has phy id 0x%04x 0x%04x\n"),
    297                   u, SOC_PORT_NAME(u, p), ls->ls_id0[p], ls->ls_id1[p]));
    298         BCM_PBMP_PORT_ADD(ls->ls_ports, p);
    299     }
    300 
    301     if (BCM_PBMP_IS_NULL(ls->ls_ports)) {
    302         test_error(u, "No valid ports left to test!\n");
    303         sal_free(ls);
    304         ls_work[u] = NULL;
    305         return(-1);
    306     }
    307 
    308     return(0);
    309 }
    310 
    311 int
    312 ls_test_done(int u, void *pa)
    313 {
    314     soc_port_t          p;
    315     int                 rv;
    316     linkscan_work_t     *ls = (linkscan_work_t *)pa;
    317 
    318     if (NULL == ls) {
    319         return(0);
    320     }
    321 
    322     PBMP_ITER(ls->ls_ports, p) {
    323         if (0 > (rv = bcm_port_linkscan_set(u, p, ls->ls_scan[p]))) {
    324             test_error(u, "bcm_port_linkscan_set: port %d: %s\n",
    325                        p, bcm_errmsg(rv));
    326             sal_free(ls);
    327             ls_work[u] = NULL;
    328             return(-1);
    329         }
    330     }
    331     sal_free(ls);
    332     ls_work[u] = NULL;
    333     return(0);
    334 }
    335 #endif /* BCM_ESW_SUPPORT */