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 2006 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 nxge_status_t 32 nxge_ipp_init(p_nxge_t nxgep) 33 { 34 uint8_t portn; 35 uint32_t config; 36 npi_handle_t handle; 37 uint32_t pkt_size; 38 ipp_status_t istatus; 39 npi_status_t rs = NPI_SUCCESS; 40 uint64_t val; 41 uint32_t d0, d1, d2, d3, d4; 42 int i; 43 uint32_t dfifo_entries; 44 45 handle = nxgep->npi_handle; 46 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 47 48 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_init: port%d", portn)); 49 50 /* Initialize ECC and parity in SRAM of DFIFO and PFIFO */ 51 52 if ((nxgep->niu_type == NEPTUNE) || (nxgep->niu_type == NEPTUNE_2)) { 53 if (portn < 2) 54 dfifo_entries = IPP_P0_P1_DFIFO_ENTRIES; 55 else 56 dfifo_entries = IPP_P2_P3_DFIFO_ENTRIES; 57 } else if (nxgep->niu_type == N2_NIU) { 58 dfifo_entries = IPP_NIU_DFIFO_ENTRIES; 59 } else 60 goto fail; 61 62 for (i = 0; i < dfifo_entries; i++) { 63 if ((rs = npi_ipp_write_dfifo(handle, portn, i, 0, 0, 0, 0, 0)) 64 != NPI_SUCCESS) 65 goto fail; 66 if ((rs = npi_ipp_read_dfifo(handle, portn, i, &d0, &d1, &d2, 67 &d3, &d4)) != NPI_SUCCESS) 68 goto fail; 69 } 70 71 /* Clear PFIFO DFIFO status bits */ 72 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_TCP_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, IPP_MAX_PKT_SIZE)) != 108 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 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 131 handle = nxgep->npi_handle; 132 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 133 134 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_disable: port%d", portn)); 135 136 /* disable the IPP */ 137 config = nxgep->ipp.config; 138 if ((rs = npi_ipp_config(handle, DISABLE, portn, config)) 139 != NPI_SUCCESS) { 140 goto fail; 141 } 142 143 /* add code to reset control FIFO */ 144 /* IPP soft reset */ 145 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) { 146 goto fail; 147 } 148 149 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_disable: port%d", portn)); 150 151 return (NXGE_OK); 152 fail: 153 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 154 "nxge_ipp_disable: Fail to disable IPP Port #%d\n", 155 portn)); 156 return (NXGE_ERROR | rs); 157 } 158 159 nxge_status_t 160 nxge_ipp_reset(p_nxge_t nxgep) 161 { 162 uint8_t portn; 163 uint32_t config; 164 npi_handle_t handle; 165 npi_status_t rs = NPI_SUCCESS; 166 uint16_t wr_ptr, rd_ptr; 167 uint32_t try_count; 168 handle = nxgep->npi_handle; 169 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 170 171 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_reset: port%d", portn)); 172 173 /* disable the IPP */ 174 config = nxgep->ipp.config; 175 if ((rs = npi_ipp_config(handle, DISABLE, portn, config)) 176 != NPI_SUCCESS) { 177 goto fail; 178 } 179 180 /* 181 * Wait until ip read and write fifo pointers 182 * are equal 183 */ 184 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 185 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 186 try_count = 10; 187 188 while ((try_count > 0) && (rd_ptr != wr_ptr)) { 189 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 190 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 191 try_count--; 192 } 193 194 if (try_count == 0) { 195 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 196 " nxge_ipp_reset: port%d failed" 197 " rd_fifo != wr_fifo", portn)); 198 goto fail; 199 } 200 201 /* IPP soft reset */ 202 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) { 203 goto fail; 204 } 205 206 /* to reset control FIFO */ 207 if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS) { 208 goto fail; 209 } 210 211 /* 212 * Making sure that error source is cleared if this is an 213 * injected error. 214 */ 215 IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0); 216 217 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_reset: port%d", portn)); 218 219 return (NXGE_OK); 220 fail: 221 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 222 "nxge_ipp_init: Fail to Reset IPP Port #%d\n", 223 portn)); 224 return (NXGE_ERROR | rs); 225 } 226 227 228 229 nxge_status_t 230 nxge_ipp_enable(p_nxge_t nxgep) 231 { 232 uint8_t portn; 233 uint32_t config; 234 npi_handle_t handle; 235 uint32_t pkt_size; 236 npi_status_t rs = NPI_SUCCESS; 237 238 handle = nxgep->npi_handle; 239 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 240 241 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_enable: port%d", portn)); 242 243 config = CFG_IPP | CFG_IPP_DFIFO_ECC_CORRECT | CFG_IPP_DROP_BAD_CRC | 244 CFG_IPP_TCP_UDP_CKSUM; 245 if ((rs = npi_ipp_config(handle, INIT, portn, config)) != NPI_SUCCESS) 246 goto fail; 247 nxgep->ipp.config = config; 248 249 /* Set max packet size */ 250 pkt_size = IPP_MAX_PKT_SIZE; 251 if ((rs = npi_ipp_set_max_pktsize(handle, portn, IPP_MAX_PKT_SIZE)) != 252 NPI_SUCCESS) 253 goto fail; 254 nxgep->ipp.max_pkt_size = pkt_size; 255 256 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_enable: port%d", portn)); 257 258 return (NXGE_OK); 259 fail: 260 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 261 "nxge_ipp_init: Fail to Enable IPP Port #%d\n", 262 portn)); 263 return (NXGE_ERROR | rs); 264 } 265 266 267 nxge_status_t 268 nxge_ipp_handle_sys_errors(p_nxge_t nxgep) 269 { 270 npi_handle_t handle; 271 npi_status_t rs = NPI_SUCCESS; 272 p_nxge_ipp_stats_t statsp; 273 ipp_status_t istatus; 274 uint8_t portn; 275 p_ipp_errlog_t errlogp; 276 boolean_t rxport_fatal = B_FALSE; 277 nxge_status_t status = NXGE_OK; 278 279 handle = nxgep->npi_handle; 280 statsp = (p_nxge_ipp_stats_t)&nxgep->statsp->ipp_stats; 281 portn = nxgep->mac.portnum; 282 283 errlogp = (p_ipp_errlog_t)&statsp->errlog; 284 285 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 286 return (NXGE_ERROR | rs); 287 288 if (istatus.value == 0) 289 /* 290 * The error is not initiated from this port, so just exit. 291 */ 292 return (NXGE_OK); 293 294 if (istatus.bits.w0.dfifo_missed_sop) { 295 statsp->sop_miss++; 296 if ((rs = npi_ipp_get_dfifo_eopm_rdptr(handle, portn, 297 &errlogp->dfifo_rd_ptr)) != NPI_SUCCESS) 298 return (NXGE_ERROR | rs); 299 if ((rs = npi_ipp_get_state_mach(handle, portn, 300 &errlogp->state_mach)) != NPI_SUCCESS) 301 return (NXGE_ERROR | rs); 302 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 303 NXGE_FM_EREPORT_IPP_SOP_MISS); 304 if (statsp->sop_miss < IPP_MAX_ERR_SHOW) 305 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 306 "nxge_ipp_err_evnts: fatal error: sop_miss\n")); 307 rxport_fatal = B_TRUE; 308 } 309 if (istatus.bits.w0.dfifo_missed_eop) { 310 statsp->eop_miss++; 311 if ((rs = npi_ipp_get_dfifo_eopm_rdptr(handle, portn, 312 &errlogp->dfifo_rd_ptr)) != NPI_SUCCESS) 313 return (NXGE_ERROR | rs); 314 if ((rs = npi_ipp_get_state_mach(handle, portn, 315 &errlogp->state_mach)) != NPI_SUCCESS) 316 return (NXGE_ERROR | rs); 317 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 318 NXGE_FM_EREPORT_IPP_EOP_MISS); 319 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 320 "nxge_ipp_err_evnts: fatal error: eop_miss\n")); 321 rxport_fatal = B_TRUE; 322 } 323 if (istatus.bits.w0.dfifo_uncorr_ecc_err) { 324 statsp->dfifo_ue++; 325 if ((rs = npi_ipp_get_ecc_syndrome(handle, portn, 326 &errlogp->ecc_syndrome)) != NPI_SUCCESS) 327 return (NXGE_ERROR | rs); 328 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 329 NXGE_FM_EREPORT_IPP_DFIFO_UE); 330 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 331 "nxge_ipp_err_evnts: fatal error: dfifo_ue\n")); 332 rxport_fatal = B_TRUE; 333 } 334 #ifdef IPP_ECC_CORR_ERR 335 if (istatus.bits.w0.dfifo_corr_ecc_err) { 336 /* 337 * Do nothing here. ECC errors are collected from the 338 * ECC counter. 339 */ 340 ; 341 } 342 #endif 343 if (istatus.bits.w0.pre_fifo_perr) { 344 statsp->pfifo_perr++; 345 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 346 NXGE_FM_EREPORT_IPP_PFIFO_PERR); 347 if (statsp->pfifo_perr < IPP_MAX_ERR_SHOW) 348 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 349 "nxge_ipp_err_evnts: fatal error: pre_pifo_perr\n")); 350 rxport_fatal = B_TRUE; 351 } 352 if (istatus.bits.w0.ecc_err_cnt_ovfl) { 353 statsp->ecc_err_cnt += IPP_ECC_CNT_MASK; 354 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 355 NXGE_FM_EREPORT_IPP_ECC_ERR_MAX); 356 if (statsp->ecc_err_cnt < (IPP_MAX_ERR_SHOW * IPP_ECC_CNT_MASK)) 357 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 358 "nxge_ipp_err_evnts: ecc_err_max\n")); 359 } 360 if (istatus.bits.w0.pre_fifo_overrun) { 361 statsp->pfifo_over++; 362 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 363 NXGE_FM_EREPORT_IPP_PFIFO_OVER); 364 if (statsp->pfifo_over < IPP_MAX_ERR_SHOW) 365 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 366 "nxge_ipp_err_evnts: fatal error: pfifo_over\n")); 367 rxport_fatal = B_TRUE; 368 } 369 if (istatus.bits.w0.pre_fifo_underrun) { 370 statsp->pfifo_und++; 371 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 372 NXGE_FM_EREPORT_IPP_PFIFO_UND); 373 if (statsp->pfifo_und < IPP_MAX_ERR_SHOW) 374 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 375 "nxge_ipp_err_evnts: fatal error: pfifo_und\n")); 376 rxport_fatal = B_TRUE; 377 } 378 if (istatus.bits.w0.bad_cksum_cnt_ovfl) { 379 statsp->bad_cs_cnt += IPP_BAD_CS_CNT_MASK; 380 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 381 NXGE_FM_EREPORT_IPP_BAD_CS_MX); 382 if (statsp->bad_cs_cnt < 383 (IPP_MAX_ERR_SHOW * IPP_BAD_CS_CNT_MASK)) 384 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 385 "nxge_ipp_err_evnts: bad_cs_max\n")); 386 } 387 if (istatus.bits.w0.pkt_discard_cnt_ovfl) { 388 statsp->pkt_dis_cnt += IPP_PKT_DIS_CNT_MASK; 389 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 390 NXGE_FM_EREPORT_IPP_PKT_DIS_MX); 391 if (statsp->pkt_dis_cnt < 392 (IPP_MAX_ERR_SHOW * IPP_PKT_DIS_CNT_MASK)) 393 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 394 "nxge_ipp_err_evnts: pkt_dis_max\n")); 395 } 396 397 /* 398 * Making sure that error source is cleared if this is an 399 * injected error. 400 */ 401 IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0); 402 403 if (rxport_fatal) { 404 NXGE_DEBUG_MSG((nxgep, IPP_CTL, 405 " nxge_ipp_handle_sys_errors:" 406 " fatal Error on Port #%d\n", 407 portn)); 408 status = nxge_ipp_fatal_err_recover(nxgep); 409 #ifdef NXGE_FM 410 if (status == NXGE_OK) { 411 FM_SERVICE_RESTORED(nxgep); 412 } 413 #endif 414 } 415 416 return (status); 417 } 418 419 void 420 nxge_ipp_inject_err(p_nxge_t nxgep, uint32_t err_id) 421 { 422 ipp_status_t ipps; 423 ipp_ecc_ctrl_t ecc_ctrl; 424 uint8_t portn = nxgep->mac.portnum; 425 426 switch (err_id) { 427 case NXGE_FM_EREPORT_IPP_DFIFO_UE: 428 ecc_ctrl.value = 0; 429 ecc_ctrl.bits.w0.cor_dbl = 1; 430 ecc_ctrl.bits.w0.cor_1 = 1; 431 ecc_ctrl.bits.w0.cor_lst = 1; 432 cmn_err(CE_NOTE, "!Write 0x%llx to IPP_ECC_CTRL_REG\n", 433 (unsigned long long)ecc_ctrl.value); 434 IPP_REG_WR(nxgep->npi_handle, portn, IPP_ECC_CTRL_REG, 435 ecc_ctrl.value); 436 break; 437 case NXGE_FM_EREPORT_IPP_DFIFO_CE: 438 ecc_ctrl.value = 0; 439 ecc_ctrl.bits.w0.cor_sng = 1; 440 ecc_ctrl.bits.w0.cor_1 = 1; 441 ecc_ctrl.bits.w0.cor_snd = 1; 442 cmn_err(CE_NOTE, "!Write 0x%llx to IPP_ECC_CTRL_REG\n", 443 (unsigned long long)ecc_ctrl.value); 444 IPP_REG_WR(nxgep->npi_handle, portn, IPP_ECC_CTRL_REG, 445 ecc_ctrl.value); 446 break; 447 case NXGE_FM_EREPORT_IPP_EOP_MISS: 448 case NXGE_FM_EREPORT_IPP_SOP_MISS: 449 case NXGE_FM_EREPORT_IPP_PFIFO_PERR: 450 case NXGE_FM_EREPORT_IPP_ECC_ERR_MAX: 451 case NXGE_FM_EREPORT_IPP_PFIFO_OVER: 452 case NXGE_FM_EREPORT_IPP_PFIFO_UND: 453 case NXGE_FM_EREPORT_IPP_BAD_CS_MX: 454 case NXGE_FM_EREPORT_IPP_PKT_DIS_MX: 455 case NXGE_FM_EREPORT_IPP_RESET_FAIL: 456 IPP_REG_RD(nxgep->npi_handle, portn, IPP_INT_STATUS_REG, 457 &ipps.value); 458 if (err_id == NXGE_FM_EREPORT_IPP_EOP_MISS) 459 ipps.bits.w0.dfifo_missed_eop = 1; 460 else if (err_id == NXGE_FM_EREPORT_IPP_SOP_MISS) 461 ipps.bits.w0.dfifo_missed_sop = 1; 462 else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_UE) 463 ipps.bits.w0.dfifo_uncorr_ecc_err = 1; 464 else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_CE) 465 ipps.bits.w0.dfifo_corr_ecc_err = 1; 466 else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_PERR) 467 ipps.bits.w0.pre_fifo_perr = 1; 468 else if (err_id == NXGE_FM_EREPORT_IPP_ECC_ERR_MAX) 469 ipps.bits.w0.ecc_err_cnt_ovfl = 1; 470 else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_OVER) 471 ipps.bits.w0.pre_fifo_overrun = 1; 472 else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_UND) 473 ipps.bits.w0.pre_fifo_underrun = 1; 474 else if (err_id == NXGE_FM_EREPORT_IPP_BAD_CS_MX) 475 ipps.bits.w0.bad_cksum_cnt_ovfl = 1; 476 else if (err_id == NXGE_FM_EREPORT_IPP_PKT_DIS_MX) 477 ipps.bits.w0.pkt_discard_cnt_ovfl = 1; 478 cmn_err(CE_NOTE, "!Write 0x%llx to IPP_INT_STATUS_REG\n", 479 (unsigned long long)ipps.value); 480 IPP_REG_WR(nxgep->npi_handle, portn, IPP_INT_STATUS_REG, 481 ipps.value); 482 break; 483 } 484 } 485 486 nxge_status_t 487 nxge_ipp_fatal_err_recover(p_nxge_t nxgep) 488 { 489 npi_handle_t handle; 490 npi_status_t rs = NPI_SUCCESS; 491 nxge_status_t status = NXGE_OK; 492 uint8_t portn; 493 uint16_t wr_ptr; 494 uint16_t rd_ptr; 495 uint32_t try_count; 496 uint32_t dfifo_entries; 497 ipp_status_t istatus; 498 uint32_t d0, d1, d2, d3, d4; 499 int i; 500 501 NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_ipp_fatal_err_recover")); 502 503 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 504 "Recovering from RxPort error...")); 505 506 handle = nxgep->npi_handle; 507 portn = nxgep->mac.portnum; 508 509 /* 510 * Making sure that error source is cleared if this is an 511 * injected error. 512 */ 513 IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0); 514 515 /* Disable RxMAC */ 516 517 if (nxge_rx_mac_disable(nxgep) != NXGE_OK) 518 goto fail; 519 520 /* When recovering from IPP, RxDMA channel resets are not necessary */ 521 /* Reset ZCP CFIFO */ 522 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset ZCP CFIFO...", portn)); 523 if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS) 524 goto fail; 525 526 /* 527 * Wait until ip read and write fifo pointers 528 * are equal 529 */ 530 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 531 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 532 try_count = 512; 533 534 while ((try_count > 0) && (rd_ptr != wr_ptr)) { 535 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 536 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 537 try_count--; 538 } 539 540 if (try_count == 0) { 541 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 542 " nxge_ipp_reset: port%d IPP stalled..." 543 " rd_fifo_ptr = 0x%x wr_fifo_ptr = 0x%x", 544 portn, rd_ptr, wr_ptr)); 545 /* 546 * This means the fatal error occurred on the first line 547 * of the fifo. In this case, just reset the IPP without 548 * draining the PFIFO. 549 */ 550 } 551 552 if ((nxgep->niu_type == NEPTUNE) || (nxgep->niu_type == NEPTUNE_2)) { 553 if (portn < 2) 554 dfifo_entries = IPP_P0_P1_DFIFO_ENTRIES; 555 else 556 dfifo_entries = IPP_P2_P3_DFIFO_ENTRIES; 557 } else if (nxgep->niu_type == N2_NIU) { 558 dfifo_entries = IPP_NIU_DFIFO_ENTRIES; 559 } else 560 goto fail; 561 562 /* Clean up DFIFO SRAM entries */ 563 for (i = 0; i < dfifo_entries; i++) { 564 if ((rs = npi_ipp_write_dfifo(handle, portn, i, 0, 0, 0, 0, 0)) 565 != NPI_SUCCESS) 566 goto fail; 567 if ((rs = npi_ipp_read_dfifo(handle, portn, i, &d0, &d1, &d2, 568 &d3, &d4)) != NPI_SUCCESS) 569 goto fail; 570 } 571 572 /* Clear PFIFO DFIFO status bits */ 573 574 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 575 goto fail; 576 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 577 goto fail; 578 579 /* Reset IPP */ 580 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset IPP...", portn)); 581 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) 582 goto fail; 583 584 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset RxMAC...", portn)); 585 if (nxge_rx_mac_reset(nxgep) != NXGE_OK) 586 goto fail; 587 588 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Initialize RxMAC...", portn)); 589 590 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 591 goto fail; 592 593 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Enable RxMAC...", portn)); 594 595 if (nxge_rx_mac_enable(nxgep) != NXGE_OK) 596 goto fail; 597 598 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 599 "Recovery Sucessful, RxPort Restored")); 600 NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_ipp_fatal_err_recover")); 601 602 return (NXGE_OK); 603 fail: 604 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed")); 605 return (status | rs); 606 } 607