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, ®val)) < 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, ®val)) < 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, ®val)); 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, ®val)); 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, ®val)); 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, ®val)); 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, ®val)); 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, ®val)); 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, ®val)); 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, ®val)); 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, ®val)); 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, ®val)); 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 */