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

mmuerr.c (14393B)


      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  * SOC Error Handlers
      8  *
      9  * NOTE: These handlers are triggered by interrupts, but happen in their own
     10  *      contexts.
     11  */
     12 
     13 #include <sal/core/libc.h>
     14 #include <shared/alloc.h>
     15 #include <sal/core/time.h>
     16 #include <shared/bsl.h>
     17 #include <soc/mem.h>
     18 #include <soc/debug.h>
     19 #include <soc/cm.h>
     20 #include <soc/drv.h>
     21 #include <soc/mmuerr.h>
     22 
     23 #ifdef BCM_HERCULES_SUPPORT
     24 
     25 /*
     26  * Function:
     27  *      soc_mmu_error_init
     28  * Purpose:
     29  *      Initialize the statistics of the MMU error handler
     30  * Parameters:
     31  *      unit - StrataSwitch unit number.
     32  * Returns:
     33  *      SOC_E_NONE - success
     34  *      SOC_E_XXX on other failure
     35  * Notes:
     36  */
     37 
     38 int
     39 soc_mmu_error_init(int unit)
     40 {
     41     soc_control_t	*soc = SOC_CONTROL(unit);
     42     soc_mmu_error_t     *mmu_errors;
     43     soc_port_t          port;
     44     uint32		regval;
     45     int                 rv;
     46 
     47     /* Don't want any interrupts from MMU until initialized */
     48     /* This will be turned on by soc_mmu_init in drv.c */
     49     soc_pci_write(unit, CMIC_MMUIRQ_MASK, 0);    
     50 
     51     /* Free if allocated ... */
     52     if (soc->mmu_errors) {
     53         sal_free(soc->mmu_errors);
     54     }
     55 
     56     mmu_errors = sal_alloc(sizeof(soc_mmu_error_t) * SOC_MAX_NUM_PORTS,
     57                            "MMU error counters");
     58 
     59     if (mmu_errors == NULL) {
     60 	return SOC_E_MEMORY;
     61     }
     62     
     63     sal_memset(mmu_errors, 0, sizeof(soc_mmu_error_t) * SOC_MAX_NUM_PORTS);
     64 
     65     PBMP_ALL_ITER(unit, port) {
     66         mmu_errors[port].xq_parity = 0;
     67         mmu_errors[port].lla_parity = 0;
     68         mmu_errors[port].upk_parity = 0;
     69         mmu_errors[port].ing_parity = 0;
     70         mmu_errors[port].egr_parity = 0;
     71 
     72         if ((rv = READ_MMU_PP_SBE_CNTr(unit, port, &regval)) < 0) {
     73             sal_free(mmu_errors);
     74             return rv;
     75         }
     76 
     77         mmu_errors[port].pp_sbe_blocks = 
     78         mmu_errors[port].pp_sbe_blocks_init =
     79             soc_reg_field_get(unit, MMU_PP_SBE_CNTr, regval, BLOCKCOUNTf);
     80         
     81         mmu_errors[port].pp_sbe_cells = 
     82         mmu_errors[port].pp_sbe_cells_init =
     83             soc_reg_field_get(unit, MMU_PP_SBE_CNTr, regval, CELLCOUNTf);
     84         
     85         if ((rv = READ_MMU_PP_DBE_CNTr(unit, port, &regval)) < 0) {
     86             sal_free(mmu_errors);
     87             return rv;
     88         }
     89 
     90         mmu_errors[port].pp_dbe_blocks = 
     91         mmu_errors[port].pp_dbe_blocks_init =
     92             soc_reg_field_get(unit, MMU_PP_DBE_CNTr, regval, BLOCKCOUNTf);
     93         
     94         mmu_errors[port].pp_dbe_cells = 
     95         mmu_errors[port].pp_dbe_cells_init =
     96             soc_reg_field_get(unit, MMU_PP_DBE_CNTr, regval, CELLCOUNTf);
     97     }
     98 
     99     soc->mmu_errors = mmu_errors;
    100 
    101     /* Start up the interrupt handling now that we are initialized */
    102     soc_pci_write(unit, CMIC_MMUIRQ_MASK, CMIC_MMUIRQ_ENABLE_MASK);
    103     soc_intr_enable(unit, IRQ_MMU_IRQ_STAT);
    104 
    105     return SOC_E_NONE;    
    106 }
    107 
    108 /*
    109  * Function:
    110  *      soc_mmu_error_done
    111  * Purpose:
    112  *      Clean up the statistics of the MMU error handler
    113  * Parameters:
    114  *      unit - StrataSwitch unit number.
    115  * Returns:
    116  *      SOC_E_NONE - success
    117  *      SOC_E_XXX on other failure
    118  * Notes:
    119  */
    120 
    121 int
    122 soc_mmu_error_done(int unit)
    123 {
    124     soc_control_t	*soc = SOC_CONTROL(unit);
    125     soc_mmu_error_t     *mmu_errors = soc->mmu_errors;
    126     int                 port;
    127 
    128     if (mmu_errors == NULL) {
    129         return SOC_E_NONE;
    130     }
    131 
    132     PBMP_ALL_ITER(unit, port) {
    133         if  (mmu_errors[port].xq_parity) {
    134             LOG_ERROR(BSL_LS_SOC_MMU,
    135                       (BSL_META_U(unit,
    136                                   "UNIT %d Port %d MMU:  %d XQ Parity Errors\n"),
    137                        unit, port, mmu_errors[port].xq_parity));
    138         }
    139 
    140         if  (mmu_errors[port].lla_parity) {
    141             LOG_ERROR(BSL_LS_SOC_MMU,
    142                       (BSL_META_U(unit,
    143                                   "UNIT %d Port %d MMU:  %d LLA Parity Errors\n"),
    144                        unit, port, mmu_errors[port].lla_parity));
    145         }
    146 
    147          if  (mmu_errors[port].upk_parity) {
    148             LOG_ERROR(BSL_LS_SOC_MMU,
    149                       (BSL_META_U(unit,
    150                                   "UNIT %d Port %d MMU:  %d UPK Parity Errors\n"),
    151                        unit, port, mmu_errors[port].upk_parity));
    152         }
    153 
    154         if  (mmu_errors[port].ing_parity) {
    155             LOG_ERROR(BSL_LS_SOC_MMU,
    156                       (BSL_META_U(unit,
    157                                   "UNIT %d Port %d MMU:  %d ING Parity Errors\n"),
    158                        unit, port, mmu_errors[port].ing_parity));
    159         }
    160 
    161 #ifdef BCM_HERCULES15_SUPPORT
    162         if  (SOC_IS_HERCULES15(unit) && (mmu_errors[port].egr_parity)) {
    163             LOG_ERROR(BSL_LS_SOC_MMU,
    164                       (BSL_META_U(unit,
    165                                   "UNIT %d Port %d MMU:  %d EGR Parity Errors\n"),
    166                        unit, port, mmu_errors[port].egr_parity));
    167         }
    168 #endif /* BCM_HERCULES15_SUPPORT */
    169 
    170         if  (mmu_errors[port].pp_sbe_blocks ||
    171              mmu_errors[port].pp_sbe_cells ) {
    172             LOG_ERROR(BSL_LS_SOC_MMU,
    173                       (BSL_META_U(unit,
    174                                   "UNIT %d Port %d MMU SBE:  %d blocks, %d cells\n"),
    175                        unit, port, mmu_errors[port].pp_sbe_blocks,
    176                        mmu_errors[port].pp_sbe_cells));
    177         }
    178 
    179         if  (mmu_errors[port].pp_dbe_blocks ||
    180              mmu_errors[port].pp_dbe_cells ) {
    181             LOG_ERROR(BSL_LS_SOC_MMU,
    182                       (BSL_META_U(unit,
    183                                   "UNIT %d Port %d MMU DBE:  %d blocks, %d cells\n"),
    184                        unit, port, mmu_errors[port].pp_dbe_blocks,
    185                        mmu_errors[port].pp_dbe_cells));
    186         }
    187    }
    188 
    189     sal_free(mmu_errors);
    190     soc->mmu_errors = NULL;
    191 
    192     return SOC_E_NONE;
    193 }
    194 
    195 /*
    196  * Function:
    197  *      soc_mmu_error_port
    198  * Purpose:
    199  *      Analyze the source of a Hercules MMU interrupt from a port
    200  * Parameters:
    201  *      unit - StrataSwitch unit number.
    202  *      port - StrataSwitch port of the MMU to analyze.
    203  * Returns:
    204  *      SOC_E_NONE - success
    205  *      SOC_E_XXX on other failure
    206  * Notes:
    207  *      Some of these interrupt sources are fatal errors.  For now, assert.
    208  *      Eventually, these probably ought to have some more processing.
    209  */
    210 
    211 int
    212 soc_mmu_error_port(int unit, int port)
    213 {
    214     uint32		regval;
    215     int                 mmu_status;
    216     soc_mmu_error_t     *mmu_errors = SOC_CONTROL(unit)->mmu_errors;
    217 
    218     SOC_IF_ERROR_RETURN(READ_MMU_INTSTATr(unit, port, &regval));
    219 
    220     LOG_ERROR(BSL_LS_SOC_MMU,
    221               (BSL_META_U(unit,
    222                           "soc_mmu_error_port: u=%d p =%d MMU_INTSTAT %08x\n"),
    223                           unit, port, regval));
    224 
    225     mmu_status = regval & (SOC_IS_HERCULES15(unit) ?
    226                             SOC_ERR_HAND_MMU_ALL_H15 : SOC_ERR_HAND_MMU_ALL);
    227 
    228     if (mmu_status & SOC_ERR_HAND_MMU_XQ_PARITY) {
    229         mmu_errors[port].xq_parity++;
    230   
    231         SOC_IF_ERROR_RETURN(READ_MMU_XQ_PARADr(unit, port, &regval));
    232         LOG_ERROR(BSL_LS_SOC_MMU,
    233                   (BSL_META_U(unit,
    234                               "UNIT %d Port %s MMU XQ Parity Error at address 0x%08x\n"),
    235                    unit, SOC_PORT_NAME(unit, port), regval));
    236     }
    237 
    238     if (mmu_status & SOC_ERR_HAND_MMU_PP_SBE) {
    239         int blocks, cells, last_blocks, last_cells;
    240         int word, bit, bitpos, addr;
    241         
    242         last_blocks = mmu_errors[port].pp_sbe_blocks;
    243         last_cells = mmu_errors[port].pp_sbe_cells;
    244 
    245         SOC_IF_ERROR_RETURN(READ_MMU_PP_SBE_CNTr(unit, port, &regval));
    246         blocks = soc_reg_field_get(unit, MMU_PP_SBE_CNTr, regval,
    247                                    BLOCKCOUNTf);
    248         cells = soc_reg_field_get(unit, MMU_PP_SBE_CNTr, regval,
    249                                    CELLCOUNTf);
    250 
    251         if (((blocks - last_blocks) > 1) || ((cells - last_cells) > 1)) {
    252             LOG_ERROR(BSL_LS_SOC_MMU,
    253                       (BSL_META_U(unit,
    254                                   "UNIT %d Port %s MMU SBE Errors missed:\n\t"
    255                                   "%d blocks, %d cells\n"),
    256                        unit, SOC_PORT_NAME(unit, port),
    257                        blocks - last_blocks - 1, 
    258                        cells - last_cells - 1));
    259         }
    260 
    261         mmu_errors[port].pp_sbe_blocks = blocks;
    262         mmu_errors[port].pp_sbe_cells = cells;
    263 
    264         SOC_IF_ERROR_RETURN(READ_MMU_PP_SBE_LOGr(unit, port, &regval));
    265         bitpos = soc_reg_field_get(unit, MMU_PP_SBE_LOGr, regval, BITPOSf);
    266         addr = soc_reg_field_get(unit, MMU_PP_SBE_LOGr, regval, ADDRf);
    267         bit = bitpos & 0xff;
    268         word = bitpos >> 8;
    269 
    270         LOG_ERROR(BSL_LS_SOC_MMU,
    271                   (BSL_META_U(unit,
    272                               "UNIT %d Port %s MMU Packet Pool SBE Error\n\t"
    273                               "Entry %d, Word %d,  Bit position %d\n"),
    274                    unit, SOC_PORT_NAME(unit, port), addr, word, bit));
    275     }
    276 
    277     if (mmu_status & SOC_ERR_HAND_MMU_PP_DBE) {
    278         int blocks, cells, last_blocks, last_cells;
    279         int addr;
    280         
    281         last_blocks = mmu_errors[port].pp_dbe_blocks;
    282         last_cells = mmu_errors[port].pp_dbe_cells;
    283 
    284         SOC_IF_ERROR_RETURN(READ_MMU_PP_DBE_CNTr(unit, port, &regval));
    285         blocks = soc_reg_field_get(unit, MMU_PP_DBE_CNTr, regval, 
    286                                    BLOCKCOUNTf);
    287         cells = soc_reg_field_get(unit, MMU_PP_DBE_CNTr, regval,
    288                                    CELLCOUNTf);
    289 
    290         if (((blocks - last_blocks) > 1) || ((cells - last_cells) > 1)) {
    291             LOG_ERROR(BSL_LS_SOC_MMU,
    292                       (BSL_META_U(unit,
    293                                   "UNIT %d Port %s MMU DBE Errors missed:\n\t"
    294                                   "%d blocks, %d cells\n"),
    295                        unit, SOC_PORT_NAME(unit, port),
    296                        blocks - last_blocks - 1, 
    297                        cells - last_cells - 1));
    298         }
    299 
    300         mmu_errors[port].pp_dbe_blocks = blocks;
    301         mmu_errors[port].pp_dbe_cells = cells;
    302 
    303         SOC_IF_ERROR_RETURN(READ_MMU_PP_DBE_LOGr(unit, port, &regval));
    304 
    305         addr = soc_reg_field_get(unit, MMU_PP_DBE_LOGr, regval, ADDRf);
    306         
    307         LOG_ERROR(BSL_LS_SOC_MMU,
    308                   (BSL_META_U(unit,
    309                               "UNIT %d Port %s MMU Packet Pool DBE Error\n\t"
    310                               "Entry %d\n"),
    311                    unit, SOC_PORT_NAME(unit, port), addr));
    312     }
    313 
    314     if (mmu_status & SOC_ERR_HAND_MMU_LLA_PARITY) {
    315         mmu_errors[port].lla_parity++;
    316  
    317         SOC_IF_ERROR_RETURN(READ_MMU_LLA_PARADr(unit, port, &regval));
    318         LOG_ERROR(BSL_LS_SOC_MMU,
    319                   (BSL_META_U(unit,
    320                               "UNIT %d Port %s MMU LLA Parity Error at address 0x%08x\n"),
    321                    unit, SOC_PORT_NAME(unit, port), regval));
    322     }
    323 
    324     if (mmu_status & SOC_ERR_HAND_MMU_UPK_PARITY) {
    325         uint32 addr;
    326         int count;
    327 
    328         mmu_errors[port].upk_parity++;
    329   
    330         SOC_IF_ERROR_RETURN(READ_MMU_UPK_ERRLOGr(unit, port, &regval));
    331         addr = soc_reg_field_get(unit, MMU_UPK_ERRLOGr, regval, ADDRf);
    332         count = soc_reg_field_get(unit, MMU_UPK_ERRLOGr, regval, COUNTf);
    333 
    334         if (count > mmu_errors[port].upk_parity) {
    335             LOG_ERROR(BSL_LS_SOC_MMU,
    336                       (BSL_META_U(unit,
    337                                   "UNIT %d Port %s MMU UPK Parity Errors missed: %d\n"),
    338                        unit, SOC_PORT_NAME(unit, port),
    339                        count - mmu_errors[port].upk_parity));
    340         }
    341 
    342         LOG_ERROR(BSL_LS_SOC_MMU,
    343                   (BSL_META_U(unit,
    344                               "UNIT %d Port %s MMU UPK Parity Error at address 0x%08x\n"),
    345                    unit, SOC_PORT_NAME(unit, port), addr));
    346     }
    347 
    348     if (mmu_status & SOC_ERR_HAND_MMU_ING_PARITY) {
    349 	int	ingmem;
    350         char	*memory_string;
    351         static char *mstr[] = {
    352             "unknown table",
    353             "Ingress Buffer table",
    354             "VLAN table",
    355             "Ingress Buffer and VLAN tables",
    356             "Multicast table",
    357             "Ingress Buffer and Multicast tables",
    358             "VLAN and Multicast tables",
    359             "Ingress Buffer, VLAN, and Multicast tables"
    360         };
    361 
    362         mmu_errors[port].ing_parity++;
    363 
    364         SOC_IF_ERROR_RETURN(READ_MMU_ING_PARADr(unit, port, &regval));
    365         LOG_ERROR(BSL_LS_SOC_MMU,
    366                   (BSL_META_U(unit,
    367                               "soc_mmu_error_port: u=%d p =%d MMU_ING_PARAD %08x\n"),
    368                    unit, port, regval));
    369         ingmem = (regval >> SOC_MMU_ERR_ING_SHIFT) & SOC_MMU_ERR_ING_MASK;
    370 
    371         memory_string = mstr[ingmem];
    372         LOG_ERROR(BSL_LS_SOC_MMU,
    373                   (BSL_META_U(unit,
    374                               "UNIT %d Port %s MMU ING Parity Error in %s\n"),
    375                    unit, SOC_PORT_NAME(unit, port), memory_string));
    376     }
    377 
    378 #ifdef BCM_HERCULES15_SUPPORT
    379     if (SOC_IS_HERCULES15(unit) && (mmu_status & SOC_ERR_HAND_MMU_EGR_PARITY)){
    380         mmu_errors[port].egr_parity++;
    381  
    382         SOC_IF_ERROR_RETURN(READ_MMU_EGR_PARADr(unit, port, &regval));
    383         LOG_ERROR(BSL_LS_SOC_MMU,
    384                   (BSL_META_U(unit,
    385                               "soc_mmu_error_port: u=%d p =%d MMU_EGR_PARAD %08x\n"),
    386                    unit, port, regval));
    387     }
    388 #endif /* BCM_HERCULES15_SUPPORT */
    389     /* Clear the analyzed bits */
    390     SOC_IF_ERROR_RETURN(WRITE_MMU_INTCLRr(unit, port, mmu_status));
    391 
    392     return SOC_E_NONE;
    393 }
    394 
    395 /*
    396  * Function:
    397  *      soc_mmu_error_all
    398  * Purpose:
    399  *      Analyze the source of a Hercules MMU interrupt
    400  * Parameters:
    401  *      unit - StrataSwitch unit number.
    402  * Returns:
    403  *      SOC_E_NONE - success
    404  *      SOC_E_XXX on other failure
    405  */
    406 
    407 int
    408 soc_mmu_error_all(int unit)
    409 {
    410     uint32 src, port, bit;
    411     int rv = SOC_E_NONE;
    412 
    413     src = soc_pci_read(unit, CMIC_MMUIRQ_STAT);
    414 
    415     /* Should be < 9 */
    416     for (port = 0, bit = 1; port < 32; port++, bit <<= 1) {
    417 	if (!(src & bit)) {
    418 	    continue;
    419 	}
    420         if ((rv = soc_mmu_error_port(unit, port)) < 0) {
    421             /* If we missed some ports, the interrupt with trigger again */
    422             break;
    423         }
    424     }
    425 
    426     /* Re-enable the ports to interrupt now that they are serviced */
    427     soc_pci_write(unit, CMIC_MMUIRQ_MASK, CMIC_MMUIRQ_ENABLE_MASK);    
    428 
    429     return rv;
    430 }
    431 
    432 #endif /* BCM_HERCULES_SUPPORT */