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