1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <nxge_impl.h> 29 #include <nxge_ipp.h> 30 31 #define NXGE_IPP_FIFO_SYNC_TRY_COUNT 100 32 33 /* ARGSUSED */ 34 nxge_status_t 35 nxge_ipp_init(p_nxge_t nxgep) 36 { 37 uint8_t portn; 38 uint32_t config; 39 npi_handle_t handle; 40 uint32_t pkt_size; 41 ipp_status_t istatus; 42 npi_status_t rs = NPI_SUCCESS; 43 uint64_t val; 44 uint32_t d0, d1, d2, d3, d4; 45 int i; 46 uint32_t dfifo_entries; 47 48 handle = nxgep->npi_handle; 49 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 50 51 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_init: port%d", portn)); 52 53 /* Initialize ECC and parity in SRAM of DFIFO and PFIFO */ 54 if (nxgep->niu_type == N2_NIU) { 55 dfifo_entries = IPP_NIU_DFIFO_ENTRIES; 56 } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 57 if (portn < 2) 58 dfifo_entries = IPP_P0_P1_DFIFO_ENTRIES; 59 else 60 dfifo_entries = IPP_P2_P3_DFIFO_ENTRIES; 61 } else { 62 goto fail; 63 } 64 65 for (i = 0; i < dfifo_entries; i++) { 66 if ((rs = npi_ipp_write_dfifo(handle, 67 portn, i, 0, 0, 0, 0, 0)) != NPI_SUCCESS) 68 goto fail; 69 if ((rs = npi_ipp_read_dfifo(handle, portn, 70 i, &d0, &d1, &d2, &d3, &d4)) != NPI_SUCCESS) 71 goto fail; 72 } 73 74 /* Clear PFIFO DFIFO status bits */ 75 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 76 goto fail; 77 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 78 goto fail; 79 80 /* 81 * Soft reset to make sure we bring the FIFO pointers back to the 82 * original initial position. 83 */ 84 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) 85 goto fail; 86 87 /* Clean up ECC counter */ 88 IPP_REG_RD(nxgep->npi_handle, portn, IPP_ECC_ERR_COUNTER_REG, &val); 89 IPP_REG_RD(nxgep->npi_handle, portn, IPP_BAD_CKSUM_ERR_CNT_REG, &val); 90 IPP_REG_RD(nxgep->npi_handle, portn, IPP_DISCARD_PKT_CNT_REG, &val); 91 92 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 93 goto fail; 94 95 /* Configure IPP port */ 96 if ((rs = npi_ipp_iconfig(handle, INIT, portn, ICFG_IPP_ALL)) 97 != NPI_SUCCESS) 98 goto fail; 99 nxgep->ipp.iconfig = ICFG_IPP_ALL; 100 101 config = CFG_IPP | CFG_IPP_DFIFO_ECC_CORRECT | CFG_IPP_DROP_BAD_CRC | 102 CFG_IPP_TCP_UDP_CKSUM; 103 if ((rs = npi_ipp_config(handle, INIT, portn, config)) != NPI_SUCCESS) 104 goto fail; 105 nxgep->ipp.config = config; 106 107 /* Set max packet size */ 108 pkt_size = IPP_MAX_PKT_SIZE; 109 if ((rs = npi_ipp_set_max_pktsize(handle, portn, 110 IPP_MAX_PKT_SIZE)) != NPI_SUCCESS) 111 goto fail; 112 nxgep->ipp.max_pkt_size = pkt_size; 113 114 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_init: port%d", portn)); 115 116 return (NXGE_OK); 117 fail: 118 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 119 "nxge_ipp_init: Fail to initialize IPP Port #%d\n", 120 portn)); 121 return (NXGE_ERROR | rs); 122 } 123 124 /* ARGSUSED */ 125 nxge_status_t 126 nxge_ipp_disable(p_nxge_t nxgep) 127 { 128 uint8_t portn; 129 uint32_t config; 130 npi_handle_t handle; 131 npi_status_t rs = NPI_SUCCESS; 132 uint16_t wr_ptr, rd_ptr; 133 uint32_t try_count; 134 135 handle = nxgep->npi_handle; 136 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 137 138 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_disable: port%d", portn)); 139 (void) nxge_rx_mac_disable(nxgep); 140 141 /* 142 * Wait until ip read and write fifo pointers are equal 143 */ 144 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 145 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 146 try_count = NXGE_IPP_FIFO_SYNC_TRY_COUNT; 147 148 while ((try_count > 0) && (rd_ptr != wr_ptr)) { 149 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 150 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 151 try_count--; 152 } 153 154 if (try_count == 0) { 155 if ((rd_ptr != 0) && (wr_ptr != 1)) { 156 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 157 " nxge_ipp_disable: port%d failed" 158 " rd_fifo != wr_fifo", portn)); 159 goto fail; 160 } 161 } 162 /* disable the IPP */ 163 config = nxgep->ipp.config; 164 if ((rs = npi_ipp_config(handle, DISABLE, 165 portn, config)) != NPI_SUCCESS) 166 goto fail; 167 168 /* IPP soft reset */ 169 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) 170 goto fail; 171 172 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_disable: port%d", portn)); 173 return (NXGE_OK); 174 fail: 175 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 176 "nxge_ipp_disable: Fail to disable IPP Port #%d\n", portn)); 177 return (NXGE_ERROR | rs); 178 } 179 180 /* ARGSUSED */ 181 nxge_status_t 182 nxge_ipp_reset(p_nxge_t nxgep) 183 { 184 uint8_t portn; 185 uint32_t config; 186 npi_handle_t handle; 187 npi_status_t rs = NPI_SUCCESS; 188 uint16_t wr_ptr, rd_ptr; 189 uint32_t try_count; 190 191 handle = nxgep->npi_handle; 192 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 193 194 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_reset: port%d", portn)); 195 196 /* disable the IPP */ 197 config = nxgep->ipp.config; 198 if ((rs = npi_ipp_config(handle, DISABLE, 199 portn, config)) != NPI_SUCCESS) 200 goto fail; 201 202 /* 203 * Wait until ip read and write fifo pointers are equal 204 */ 205 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 206 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 207 try_count = NXGE_IPP_FIFO_SYNC_TRY_COUNT; 208 209 while ((try_count > 0) && (rd_ptr != wr_ptr)) { 210 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 211 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 212 try_count--; 213 } 214 215 if (try_count == 0) { 216 if ((rd_ptr != 0) && (wr_ptr != 1)) { 217 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 218 " nxge_ipp_disable: port%d failed" 219 " rd_fifo != wr_fifo", portn)); 220 goto fail; 221 } 222 } 223 224 /* IPP soft reset */ 225 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) { 226 goto fail; 227 } 228 229 /* to reset control FIFO */ 230 if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS) 231 goto fail; 232 233 /* 234 * Making sure that error source is cleared if this is an injected 235 * error. 236 */ 237 IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0); 238 239 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_reset: port%d", portn)); 240 return (NXGE_OK); 241 fail: 242 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 243 "nxge_ipp_init: Fail to Reset IPP Port #%d\n", 244 portn)); 245 return (NXGE_ERROR | rs); 246 } 247 248 /* ARGSUSED */ 249 nxge_status_t 250 nxge_ipp_enable(p_nxge_t nxgep) 251 { 252 uint8_t portn; 253 uint32_t config; 254 npi_handle_t handle; 255 uint32_t pkt_size; 256 npi_status_t rs = NPI_SUCCESS; 257 258 handle = nxgep->npi_handle; 259 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 260 261 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_enable: port%d", portn)); 262 263 config = CFG_IPP | CFG_IPP_DFIFO_ECC_CORRECT | CFG_IPP_DROP_BAD_CRC | 264 CFG_IPP_TCP_UDP_CKSUM; 265 if ((rs = npi_ipp_config(handle, INIT, portn, config)) != NPI_SUCCESS) 266 goto fail; 267 nxgep->ipp.config = config; 268 269 /* Set max packet size */ 270 pkt_size = IPP_MAX_PKT_SIZE; 271 if ((rs = npi_ipp_set_max_pktsize(handle, portn, 272 IPP_MAX_PKT_SIZE)) != NPI_SUCCESS) 273 goto fail; 274 nxgep->ipp.max_pkt_size = pkt_size; 275 276 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_enable: port%d", portn)); 277 return (NXGE_OK); 278 fail: 279 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 280 "nxge_ipp_init: Fail to Enable IPP Port #%d\n", portn)); 281 return (NXGE_ERROR | rs); 282 } 283 284 /* ARGSUSED */ 285 nxge_status_t 286 nxge_ipp_drain(p_nxge_t nxgep) 287 { 288 uint8_t portn; 289 npi_handle_t handle; 290 npi_status_t rs = NPI_SUCCESS; 291 uint16_t wr_ptr, rd_ptr; 292 uint32_t try_count; 293 294 handle = nxgep->npi_handle; 295 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 296 297 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_drain: port%d", portn)); 298 299 /* 300 * Wait until ip read and write fifo pointers are equal 301 */ 302 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 303 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 304 try_count = NXGE_IPP_FIFO_SYNC_TRY_COUNT; 305 306 while ((try_count > 0) && (rd_ptr != wr_ptr)) { 307 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 308 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 309 try_count--; 310 } 311 312 if (try_count == 0) { 313 if ((rd_ptr != 0) && (wr_ptr != 1)) { 314 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 315 " nxge_ipp_drain: port%d failed" 316 " rd_fifo != wr_fifo", portn)); 317 goto fail; 318 } 319 } 320 321 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_drain: port%d", portn)); 322 return (NXGE_OK); 323 fail: 324 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_ipp_init: " 325 "Fail to Reset IPP Port #%d\n", portn)); 326 return (NXGE_ERROR | rs); 327 } 328 329 /* ARGSUSED */ 330 nxge_status_t 331 nxge_ipp_handle_sys_errors(p_nxge_t nxgep) 332 { 333 npi_handle_t handle; 334 npi_status_t rs = NPI_SUCCESS; 335 p_nxge_ipp_stats_t statsp; 336 ipp_status_t istatus; 337 uint8_t portn; 338 p_ipp_errlog_t errlogp; 339 boolean_t rxport_fatal = B_FALSE; 340 nxge_status_t status = NXGE_OK; 341 uint8_t cnt8; 342 uint16_t cnt16; 343 344 handle = nxgep->npi_handle; 345 statsp = (p_nxge_ipp_stats_t)&nxgep->statsp->ipp_stats; 346 portn = nxgep->mac.portnum; 347 348 errlogp = (p_ipp_errlog_t)&statsp->errlog; 349 350 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 351 return (NXGE_ERROR | rs); 352 353 if (istatus.value == 0) { 354 /* 355 * The error is not initiated from this port, so just exit. 356 */ 357 return (NXGE_OK); 358 } 359 360 if (istatus.bits.w0.dfifo_missed_sop) { 361 statsp->sop_miss++; 362 if ((rs = npi_ipp_get_dfifo_eopm_rdptr(handle, portn, 363 &errlogp->dfifo_rd_ptr)) != NPI_SUCCESS) 364 return (NXGE_ERROR | rs); 365 if ((rs = npi_ipp_get_state_mach(handle, portn, 366 &errlogp->state_mach)) != NPI_SUCCESS) 367 return (NXGE_ERROR | rs); 368 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 369 NXGE_FM_EREPORT_IPP_SOP_MISS); 370 if (statsp->sop_miss < IPP_MAX_ERR_SHOW) 371 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 372 "nxge_ipp_err_evnts: fatal error: sop_miss\n")); 373 rxport_fatal = B_TRUE; 374 } 375 if (istatus.bits.w0.dfifo_missed_eop) { 376 statsp->eop_miss++; 377 if ((rs = npi_ipp_get_dfifo_eopm_rdptr(handle, portn, 378 &errlogp->dfifo_rd_ptr)) != NPI_SUCCESS) 379 return (NXGE_ERROR | rs); 380 if ((rs = npi_ipp_get_state_mach(handle, portn, 381 &errlogp->state_mach)) != NPI_SUCCESS) 382 return (NXGE_ERROR | rs); 383 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 384 NXGE_FM_EREPORT_IPP_EOP_MISS); 385 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 386 "nxge_ipp_err_evnts: fatal error: eop_miss\n")); 387 rxport_fatal = B_TRUE; 388 } 389 if (istatus.bits.w0.dfifo_uncorr_ecc_err) { 390 boolean_t ue_ecc_valid; 391 392 if ((status = nxge_ipp_eccue_valid_check(nxgep, 393 &ue_ecc_valid)) != NXGE_OK) 394 return (status); 395 396 if (ue_ecc_valid) { 397 statsp->dfifo_ue++; 398 if ((rs = npi_ipp_get_ecc_syndrome(handle, portn, 399 &errlogp->ecc_syndrome)) != NPI_SUCCESS) 400 return (NXGE_ERROR | rs); 401 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 402 NXGE_FM_EREPORT_IPP_DFIFO_UE); 403 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 404 "nxge_ipp_err_evnts: fatal error: dfifo_ue\n")); 405 rxport_fatal = B_TRUE; 406 } 407 } 408 if (istatus.bits.w0.pre_fifo_perr) { 409 statsp->pfifo_perr++; 410 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 411 NXGE_FM_EREPORT_IPP_PFIFO_PERR); 412 if (statsp->pfifo_perr < IPP_MAX_ERR_SHOW) 413 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 414 "nxge_ipp_err_evnts: " 415 "fatal error: pre_pifo_perr\n")); 416 rxport_fatal = B_TRUE; 417 } 418 if (istatus.bits.w0.pre_fifo_overrun) { 419 statsp->pfifo_over++; 420 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 421 NXGE_FM_EREPORT_IPP_PFIFO_OVER); 422 if (statsp->pfifo_over < IPP_MAX_ERR_SHOW) 423 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 424 "nxge_ipp_err_evnts: " 425 "fatal error: pfifo_over\n")); 426 rxport_fatal = B_TRUE; 427 } 428 if (istatus.bits.w0.pre_fifo_underrun) { 429 statsp->pfifo_und++; 430 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 431 NXGE_FM_EREPORT_IPP_PFIFO_UND); 432 if (statsp->pfifo_und < IPP_MAX_ERR_SHOW) 433 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 434 "nxge_ipp_err_evnts: " 435 "fatal error: pfifo_und\n")); 436 rxport_fatal = B_TRUE; 437 } 438 if (istatus.bits.w0.bad_cksum_cnt_ovfl) { 439 /* 440 * Do not send FMA ereport or log error message 441 * in /var/adm/messages because this error does not 442 * indicate a HW failure. 443 * 444 * Clear bit BAD_CS_MX of register IPP_INT_STAT 445 * by reading register IPP_BAD_CS_CNT 446 */ 447 (void) npi_ipp_get_cs_err_count(handle, portn, &cnt16); 448 statsp->bad_cs_cnt += IPP_BAD_CS_CNT_MASK; 449 } 450 if (istatus.bits.w0.pkt_discard_cnt_ovfl) { 451 /* 452 * Do not send FMA ereport or log error message 453 * in /var/adm/messages because this error does not 454 * indicate a HW failure. 455 * 456 * Clear bit PKT_DIS_MX of register IPP_INT_STAT 457 * by reading register IPP_PKT_DIS 458 */ 459 (void) npi_ipp_get_pkt_dis_count(handle, portn, &cnt16); 460 statsp->pkt_dis_cnt += IPP_PKT_DIS_CNT_MASK; 461 } 462 if (istatus.bits.w0.ecc_err_cnt_ovfl) { 463 /* 464 * Clear bit ECC_ERR_MAX of register IPP_INI_STAT 465 * by reading register IPP_ECC 466 */ 467 (void) npi_ipp_get_ecc_err_count(handle, portn, &cnt8); 468 statsp->ecc_err_cnt += IPP_ECC_CNT_MASK; 469 /* 470 * A defect in Neptune port2's IPP module could generate 471 * many fake but harmless ECC errors under stress and cause 472 * the ecc-error-counter register IPP_ECC to reach its 473 * maximum value in a few seconds. To avoid false alarm, do 474 * not report the error if it is port2. 475 */ 476 if (portn != 2) { 477 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 478 NXGE_FM_EREPORT_IPP_ECC_ERR_MAX); 479 if (statsp->ecc_err_cnt < (IPP_MAX_ERR_SHOW * 480 IPP_ECC_CNT_MASK)) { 481 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 482 "nxge_ipp_err_evnts: pkt_ecc_err_max\n")); 483 } 484 } 485 } 486 /* 487 * Making sure that error source is cleared if this is an injected 488 * error. 489 */ 490 IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0); 491 492 if (rxport_fatal) { 493 NXGE_DEBUG_MSG((nxgep, IPP_CTL, 494 " nxge_ipp_handle_sys_errors:" 495 " fatal Error on Port #%d\n", portn)); 496 status = nxge_ipp_fatal_err_recover(nxgep); 497 if (status == NXGE_OK) { 498 FM_SERVICE_RESTORED(nxgep); 499 } 500 } 501 return (status); 502 } 503 504 /* ARGSUSED */ 505 void 506 nxge_ipp_inject_err(p_nxge_t nxgep, uint32_t err_id) 507 { 508 ipp_status_t ipps; 509 ipp_ecc_ctrl_t ecc_ctrl; 510 uint8_t portn = nxgep->mac.portnum; 511 512 switch (err_id) { 513 case NXGE_FM_EREPORT_IPP_DFIFO_UE: 514 ecc_ctrl.value = 0; 515 ecc_ctrl.bits.w0.cor_dbl = 1; 516 ecc_ctrl.bits.w0.cor_1 = 1; 517 ecc_ctrl.bits.w0.cor_lst = 1; 518 cmn_err(CE_NOTE, "!Write 0x%llx to IPP_ECC_CTRL_REG\n", 519 (unsigned long long) ecc_ctrl.value); 520 IPP_REG_WR(nxgep->npi_handle, portn, IPP_ECC_CTRL_REG, 521 ecc_ctrl.value); 522 break; 523 524 case NXGE_FM_EREPORT_IPP_DFIFO_CE: 525 ecc_ctrl.value = 0; 526 ecc_ctrl.bits.w0.cor_sng = 1; 527 ecc_ctrl.bits.w0.cor_1 = 1; 528 ecc_ctrl.bits.w0.cor_snd = 1; 529 cmn_err(CE_NOTE, "!Write 0x%llx to IPP_ECC_CTRL_REG\n", 530 (unsigned long long) ecc_ctrl.value); 531 IPP_REG_WR(nxgep->npi_handle, portn, IPP_ECC_CTRL_REG, 532 ecc_ctrl.value); 533 break; 534 535 case NXGE_FM_EREPORT_IPP_EOP_MISS: 536 case NXGE_FM_EREPORT_IPP_SOP_MISS: 537 case NXGE_FM_EREPORT_IPP_PFIFO_PERR: 538 case NXGE_FM_EREPORT_IPP_ECC_ERR_MAX: 539 case NXGE_FM_EREPORT_IPP_PFIFO_OVER: 540 case NXGE_FM_EREPORT_IPP_PFIFO_UND: 541 case NXGE_FM_EREPORT_IPP_BAD_CS_MX: 542 case NXGE_FM_EREPORT_IPP_PKT_DIS_MX: 543 case NXGE_FM_EREPORT_IPP_RESET_FAIL: 544 IPP_REG_RD(nxgep->npi_handle, portn, IPP_INT_STATUS_REG, 545 &ipps.value); 546 if (err_id == NXGE_FM_EREPORT_IPP_EOP_MISS) 547 ipps.bits.w0.dfifo_missed_eop = 1; 548 else if (err_id == NXGE_FM_EREPORT_IPP_SOP_MISS) 549 ipps.bits.w0.dfifo_missed_sop = 1; 550 else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_UE) 551 ipps.bits.w0.dfifo_uncorr_ecc_err = 1; 552 else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_CE) 553 ipps.bits.w0.dfifo_corr_ecc_err = 1; 554 else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_PERR) 555 ipps.bits.w0.pre_fifo_perr = 1; 556 else if (err_id == NXGE_FM_EREPORT_IPP_ECC_ERR_MAX) { 557 /* 558 * Fill register IPP_ECC with max ECC-error- 559 * counter value (0xff) to set the ECC_ERR_MAX bit 560 * of the IPP_INT_STAT register and trigger an 561 * FMA ereport. 562 */ 563 IPP_REG_WR(nxgep->npi_handle, portn, 564 IPP_ECC_ERR_COUNTER_REG, IPP_ECC_CNT_MASK); 565 } else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_OVER) 566 ipps.bits.w0.pre_fifo_overrun = 1; 567 else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_UND) 568 ipps.bits.w0.pre_fifo_underrun = 1; 569 else if (err_id == NXGE_FM_EREPORT_IPP_BAD_CS_MX) { 570 /* 571 * Fill IPP_BAD_CS_CNT with max bad-checksum-counter 572 * value (0x3fff) to set the BAD_CS_MX bit of 573 * IPP_INT_STAT and trigger an FMA ereport. 574 */ 575 IPP_REG_WR(nxgep->npi_handle, portn, 576 IPP_BAD_CKSUM_ERR_CNT_REG, IPP_BAD_CS_CNT_MASK); 577 } else if (err_id == NXGE_FM_EREPORT_IPP_PKT_DIS_MX) { 578 /* 579 * Fill IPP_PKT_DIS with max packet-discard-counter 580 * value (0x3fff) to set the PKT_DIS_MX bit of 581 * IPP_INT_STAT and trigger an FMA ereport. 582 */ 583 IPP_REG_WR(nxgep->npi_handle, portn, 584 IPP_DISCARD_PKT_CNT_REG, IPP_PKT_DIS_CNT_MASK); 585 } 586 cmn_err(CE_NOTE, "!Write 0x%llx to IPP_INT_STATUS_REG\n", 587 (unsigned long long) ipps.value); 588 IPP_REG_WR(nxgep->npi_handle, portn, IPP_INT_STATUS_REG, 589 ipps.value); 590 break; 591 } 592 } 593 594 /* ARGSUSED */ 595 nxge_status_t 596 nxge_ipp_fatal_err_recover(p_nxge_t nxgep) 597 { 598 npi_handle_t handle; 599 npi_status_t rs = NPI_SUCCESS; 600 nxge_status_t status = NXGE_OK; 601 uint8_t portn; 602 uint16_t wr_ptr; 603 uint16_t rd_ptr; 604 uint32_t try_count; 605 uint32_t dfifo_entries; 606 ipp_status_t istatus; 607 uint32_t d0, d1, d2, d3, d4; 608 int i; 609 610 NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_ipp_fatal_err_recover")); 611 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 612 "Recovering from RxPort error...")); 613 614 handle = nxgep->npi_handle; 615 portn = nxgep->mac.portnum; 616 617 /* 618 * Making sure that error source is cleared if this is an injected 619 * error. 620 */ 621 IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0); 622 623 /* Disable RxMAC */ 624 if (nxge_rx_mac_disable(nxgep) != NXGE_OK) 625 goto fail; 626 627 /* When recovering from IPP, RxDMA channel resets are not necessary */ 628 /* Reset ZCP CFIFO */ 629 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset ZCP CFIFO...", portn)); 630 if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS) 631 goto fail; 632 633 /* 634 * Wait until ip read and write fifo pointers are equal 635 */ 636 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 637 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 638 try_count = 512; 639 640 while ((try_count > 0) && (rd_ptr != wr_ptr)) { 641 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 642 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 643 try_count--; 644 } 645 646 if (try_count == 0) { 647 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 648 " nxge_ipp_reset: port%d IPP stalled..." 649 " rd_fifo_ptr = 0x%x wr_fifo_ptr = 0x%x", 650 portn, rd_ptr, wr_ptr)); 651 /* 652 * This means the fatal error occurred on the first line of the 653 * fifo. In this case, just reset the IPP without draining the 654 * PFIFO. 655 */ 656 } 657 658 if (nxgep->niu_type == N2_NIU) { 659 dfifo_entries = IPP_NIU_DFIFO_ENTRIES; 660 } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 661 if (portn < 2) 662 dfifo_entries = IPP_P0_P1_DFIFO_ENTRIES; 663 else 664 dfifo_entries = IPP_P2_P3_DFIFO_ENTRIES; 665 } else { 666 goto fail; 667 } 668 669 /* Clean up DFIFO SRAM entries */ 670 for (i = 0; i < dfifo_entries; i++) { 671 if ((rs = npi_ipp_write_dfifo(handle, portn, 672 i, 0, 0, 0, 0, 0)) != NPI_SUCCESS) 673 goto fail; 674 if ((rs = npi_ipp_read_dfifo(handle, portn, i, 675 &d0, &d1, &d2, &d3, &d4)) != NPI_SUCCESS) 676 goto fail; 677 } 678 679 /* Clear PFIFO DFIFO status bits */ 680 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 681 goto fail; 682 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 683 goto fail; 684 685 /* Reset IPP */ 686 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset IPP...", portn)); 687 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) 688 goto fail; 689 690 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset RxMAC...", portn)); 691 if (nxge_rx_mac_reset(nxgep) != NXGE_OK) 692 goto fail; 693 694 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Initialize RxMAC...", portn)); 695 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 696 goto fail; 697 698 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Enable RxMAC...", portn)); 699 if (nxge_rx_mac_enable(nxgep) != NXGE_OK) 700 goto fail; 701 702 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 703 "Recovery successful, RxPort restored")); 704 NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_ipp_fatal_err_recover")); 705 706 return (NXGE_OK); 707 fail: 708 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed")); 709 return (status | rs); 710 } 711 712 /* ARGSUSED */ 713 /* 714 * A hardware bug may cause fake ECCUEs (ECC Uncorrectable Error). 715 * This function checks if a ECCUE is real(valid) or not. It is not 716 * real if rd_ptr == wr_ptr. 717 * The hardware module that has the bug is used not only by the IPP 718 * FIFO but also by the ZCP FIFO, therefore this function is also 719 * called by nxge_zcp_handle_sys_errors for validating the ZCP FIFO 720 * error. 721 */ 722 nxge_status_t 723 nxge_ipp_eccue_valid_check(p_nxge_t nxgep, boolean_t *valid) 724 { 725 npi_handle_t handle; 726 npi_status_t rs = NPI_SUCCESS; 727 uint8_t portn; 728 uint16_t rd_ptr; 729 uint16_t wr_ptr; 730 uint16_t curr_rd_ptr; 731 uint16_t curr_wr_ptr; 732 uint32_t stall_cnt; 733 uint32_t d0, d1, d2, d3, d4; 734 735 handle = nxgep->npi_handle; 736 portn = nxgep->mac.portnum; 737 *valid = B_TRUE; 738 739 if ((rs = npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr)) 740 != NPI_SUCCESS) 741 goto fail; 742 if ((rs = npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr)) 743 != NPI_SUCCESS) 744 goto fail; 745 746 if (rd_ptr == wr_ptr) { 747 *valid = B_FALSE; /* FIFO not stuck, so it's not a real ECCUE */ 748 } else { 749 stall_cnt = 0; 750 /* 751 * Check if the two pointers are moving, the ECCUE is invali 752 * if either pointer is moving, which indicates that the FIFO 753 * is functional. 754 */ 755 while (stall_cnt < 16) { 756 if ((rs = npi_ipp_get_dfifo_rd_ptr(handle, 757 portn, &curr_rd_ptr)) != NPI_SUCCESS) 758 goto fail; 759 if ((rs = npi_ipp_get_dfifo_wr_ptr(handle, 760 portn, &curr_wr_ptr)) != NPI_SUCCESS) 761 goto fail; 762 763 if (rd_ptr == curr_rd_ptr && wr_ptr == curr_wr_ptr) { 764 stall_cnt++; 765 } else { 766 *valid = B_FALSE; 767 break; 768 } 769 } 770 771 if (valid) { 772 /* 773 * Further check to see if the ECCUE is valid. The 774 * error is real if the LSB of d4 is 1, which 775 * indicates that the data that has set the ECC 776 * error flag is the 16-byte internal control word. 777 */ 778 if ((rs = npi_ipp_read_dfifo(handle, portn, rd_ptr, 779 &d0, &d1, &d2, &d3, &d4)) != NPI_SUCCESS) 780 goto fail; 781 if ((d4 & 0x1) == 0) /* Not the 1st line */ 782 *valid = B_FALSE; 783 } 784 } 785 return (NXGE_OK); 786 fail: 787 return (NXGE_ERROR | rs); 788 } 789