144961713Sgirish /* 244961713Sgirish * CDDL HEADER START 344961713Sgirish * 444961713Sgirish * The contents of this file are subject to the terms of the 544961713Sgirish * Common Development and Distribution License (the "License"). 644961713Sgirish * You may not use this file except in compliance with the License. 744961713Sgirish * 844961713Sgirish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 944961713Sgirish * or http://www.opensolaris.org/os/licensing. 1044961713Sgirish * See the License for the specific language governing permissions 1144961713Sgirish * and limitations under the License. 1244961713Sgirish * 1344961713Sgirish * When distributing Covered Code, include this CDDL HEADER in each 1444961713Sgirish * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1544961713Sgirish * If applicable, add the following below this CDDL HEADER, with the 1644961713Sgirish * fields enclosed by brackets "[]" replaced with your own identifying 1744961713Sgirish * information: Portions Copyright [yyyy] [name of copyright owner] 1844961713Sgirish * 1944961713Sgirish * CDDL HEADER END 2044961713Sgirish */ 2144961713Sgirish /* 2263e23a19Syc * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2344961713Sgirish * Use is subject to license terms. 2444961713Sgirish */ 2544961713Sgirish 2644961713Sgirish #pragma ident "%Z%%M% %I% %E% SMI" 2744961713Sgirish 2844961713Sgirish #include <nxge_impl.h> 2944961713Sgirish #include <nxge_ipp.h> 3044961713Sgirish 3114ea4bb7Ssd #define NXGE_IPP_FIFO_SYNC_TRY_COUNT 100 3214ea4bb7Ssd 33a3c5bd6dSspeer /* ARGSUSED */ 3444961713Sgirish nxge_status_t 3544961713Sgirish nxge_ipp_init(p_nxge_t nxgep) 3644961713Sgirish { 37a3c5bd6dSspeer uint8_t portn; 38a3c5bd6dSspeer uint32_t config; 39a3c5bd6dSspeer npi_handle_t handle; 40a3c5bd6dSspeer uint32_t pkt_size; 41a3c5bd6dSspeer ipp_status_t istatus; 42a3c5bd6dSspeer npi_status_t rs = NPI_SUCCESS; 43a3c5bd6dSspeer uint64_t val; 44a3c5bd6dSspeer uint32_t d0, d1, d2, d3, d4; 45a3c5bd6dSspeer int i; 46a3c5bd6dSspeer uint32_t dfifo_entries; 4744961713Sgirish 4844961713Sgirish handle = nxgep->npi_handle; 4944961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 5044961713Sgirish 5144961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_init: port%d", portn)); 5244961713Sgirish 5344961713Sgirish /* Initialize ECC and parity in SRAM of DFIFO and PFIFO */ 5459ac0c16Sdavemq if (nxgep->niu_type == N2_NIU) { 5559ac0c16Sdavemq dfifo_entries = IPP_NIU_DFIFO_ENTRIES; 562e59129aSraghus } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 5744961713Sgirish if (portn < 2) 5844961713Sgirish dfifo_entries = IPP_P0_P1_DFIFO_ENTRIES; 5944961713Sgirish else 6044961713Sgirish dfifo_entries = IPP_P2_P3_DFIFO_ENTRIES; 6159ac0c16Sdavemq } else { 6244961713Sgirish goto fail; 6359ac0c16Sdavemq } 6444961713Sgirish 6544961713Sgirish for (i = 0; i < dfifo_entries; i++) { 66a3c5bd6dSspeer if ((rs = npi_ipp_write_dfifo(handle, 67a3c5bd6dSspeer portn, i, 0, 0, 0, 0, 0)) != NPI_SUCCESS) 6844961713Sgirish goto fail; 69a3c5bd6dSspeer if ((rs = npi_ipp_read_dfifo(handle, portn, 70a3c5bd6dSspeer i, &d0, &d1, &d2, &d3, &d4)) != NPI_SUCCESS) 7144961713Sgirish goto fail; 7244961713Sgirish } 7344961713Sgirish 7444961713Sgirish /* Clear PFIFO DFIFO status bits */ 7544961713Sgirish if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 7644961713Sgirish goto fail; 7744961713Sgirish if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 7844961713Sgirish goto fail; 7944961713Sgirish 8044961713Sgirish /* 8144961713Sgirish * Soft reset to make sure we bring the FIFO pointers back to the 8244961713Sgirish * original initial position. 8344961713Sgirish */ 8444961713Sgirish if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) 8544961713Sgirish goto fail; 8644961713Sgirish 8744961713Sgirish /* Clean up ECC counter */ 8844961713Sgirish IPP_REG_RD(nxgep->npi_handle, portn, IPP_ECC_ERR_COUNTER_REG, &val); 89f6485eecSyc IPP_REG_RD(nxgep->npi_handle, portn, IPP_BAD_CKSUM_ERR_CNT_REG, &val); 9044961713Sgirish IPP_REG_RD(nxgep->npi_handle, portn, IPP_DISCARD_PKT_CNT_REG, &val); 9144961713Sgirish 9244961713Sgirish if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 9344961713Sgirish goto fail; 9444961713Sgirish 9544961713Sgirish /* Configure IPP port */ 9644961713Sgirish if ((rs = npi_ipp_iconfig(handle, INIT, portn, ICFG_IPP_ALL)) 97a3c5bd6dSspeer != NPI_SUCCESS) 9844961713Sgirish goto fail; 9944961713Sgirish nxgep->ipp.iconfig = ICFG_IPP_ALL; 10044961713Sgirish 10144961713Sgirish config = CFG_IPP | CFG_IPP_DFIFO_ECC_CORRECT | CFG_IPP_DROP_BAD_CRC | 102a3c5bd6dSspeer CFG_IPP_TCP_UDP_CKSUM; 10344961713Sgirish if ((rs = npi_ipp_config(handle, INIT, portn, config)) != NPI_SUCCESS) 10444961713Sgirish goto fail; 10544961713Sgirish nxgep->ipp.config = config; 10644961713Sgirish 10744961713Sgirish /* Set max packet size */ 10844961713Sgirish pkt_size = IPP_MAX_PKT_SIZE; 109a3c5bd6dSspeer if ((rs = npi_ipp_set_max_pktsize(handle, portn, 110a3c5bd6dSspeer IPP_MAX_PKT_SIZE)) != NPI_SUCCESS) 11144961713Sgirish goto fail; 11244961713Sgirish nxgep->ipp.max_pkt_size = pkt_size; 11344961713Sgirish 11444961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_init: port%d", portn)); 11544961713Sgirish 11644961713Sgirish return (NXGE_OK); 11744961713Sgirish fail: 11844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 11944961713Sgirish "nxge_ipp_init: Fail to initialize IPP Port #%d\n", 12044961713Sgirish portn)); 12144961713Sgirish return (NXGE_ERROR | rs); 12244961713Sgirish } 12344961713Sgirish 124a3c5bd6dSspeer /* ARGSUSED */ 12544961713Sgirish nxge_status_t 12644961713Sgirish nxge_ipp_disable(p_nxge_t nxgep) 12744961713Sgirish { 128a3c5bd6dSspeer uint8_t portn; 129a3c5bd6dSspeer uint32_t config; 130a3c5bd6dSspeer npi_handle_t handle; 131a3c5bd6dSspeer npi_status_t rs = NPI_SUCCESS; 13214ea4bb7Ssd uint16_t wr_ptr, rd_ptr; 13314ea4bb7Ssd uint32_t try_count; 13444961713Sgirish 13544961713Sgirish handle = nxgep->npi_handle; 13644961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 13744961713Sgirish 13844961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_disable: port%d", portn)); 13914ea4bb7Ssd (void) nxge_rx_mac_disable(nxgep); 14014ea4bb7Ssd 14114ea4bb7Ssd /* 142a3c5bd6dSspeer * Wait until ip read and write fifo pointers are equal 14314ea4bb7Ssd */ 14414ea4bb7Ssd (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 14514ea4bb7Ssd (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 14614ea4bb7Ssd try_count = NXGE_IPP_FIFO_SYNC_TRY_COUNT; 14714ea4bb7Ssd 14814ea4bb7Ssd while ((try_count > 0) && (rd_ptr != wr_ptr)) { 14914ea4bb7Ssd (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 15014ea4bb7Ssd (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 15114ea4bb7Ssd try_count--; 15214ea4bb7Ssd } 15314ea4bb7Ssd 15414ea4bb7Ssd if (try_count == 0) { 15514ea4bb7Ssd if ((rd_ptr != 0) && (wr_ptr != 1)) { 15614ea4bb7Ssd NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 157a3c5bd6dSspeer " nxge_ipp_disable: port%d failed" 158a3c5bd6dSspeer " rd_fifo != wr_fifo", portn)); 15914ea4bb7Ssd goto fail; 16014ea4bb7Ssd } 16114ea4bb7Ssd } 16244961713Sgirish /* disable the IPP */ 16344961713Sgirish config = nxgep->ipp.config; 164a3c5bd6dSspeer if ((rs = npi_ipp_config(handle, DISABLE, 165a3c5bd6dSspeer portn, config)) != NPI_SUCCESS) 16644961713Sgirish goto fail; 16744961713Sgirish 16844961713Sgirish /* IPP soft reset */ 169a3c5bd6dSspeer if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) 17044961713Sgirish goto fail; 17144961713Sgirish 17244961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_disable: port%d", portn)); 17344961713Sgirish return (NXGE_OK); 17444961713Sgirish fail: 17544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 176a3c5bd6dSspeer "nxge_ipp_disable: Fail to disable IPP Port #%d\n", portn)); 17744961713Sgirish return (NXGE_ERROR | rs); 17844961713Sgirish } 17944961713Sgirish 180a3c5bd6dSspeer /* ARGSUSED */ 18144961713Sgirish nxge_status_t 18244961713Sgirish nxge_ipp_reset(p_nxge_t nxgep) 18344961713Sgirish { 184a3c5bd6dSspeer uint8_t portn; 185a3c5bd6dSspeer uint32_t config; 186a3c5bd6dSspeer npi_handle_t handle; 187a3c5bd6dSspeer npi_status_t rs = NPI_SUCCESS; 18844961713Sgirish uint16_t wr_ptr, rd_ptr; 18944961713Sgirish uint32_t try_count; 190a3c5bd6dSspeer 19144961713Sgirish handle = nxgep->npi_handle; 19244961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 19344961713Sgirish 19444961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_reset: port%d", portn)); 19544961713Sgirish 19644961713Sgirish /* disable the IPP */ 19744961713Sgirish config = nxgep->ipp.config; 198a3c5bd6dSspeer if ((rs = npi_ipp_config(handle, DISABLE, 199a3c5bd6dSspeer portn, config)) != NPI_SUCCESS) 20044961713Sgirish goto fail; 20144961713Sgirish 20244961713Sgirish /* 203a3c5bd6dSspeer * Wait until ip read and write fifo pointers are equal 20444961713Sgirish */ 20544961713Sgirish (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 20644961713Sgirish (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 20714ea4bb7Ssd try_count = NXGE_IPP_FIFO_SYNC_TRY_COUNT; 20844961713Sgirish 20944961713Sgirish while ((try_count > 0) && (rd_ptr != wr_ptr)) { 21044961713Sgirish (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 21144961713Sgirish (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 21244961713Sgirish try_count--; 21344961713Sgirish } 21444961713Sgirish 21544961713Sgirish if (try_count == 0) { 21614ea4bb7Ssd if ((rd_ptr != 0) && (wr_ptr != 1)) { 21714ea4bb7Ssd NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 218a3c5bd6dSspeer " nxge_ipp_disable: port%d failed" 219a3c5bd6dSspeer " rd_fifo != wr_fifo", portn)); 22014ea4bb7Ssd goto fail; 22114ea4bb7Ssd } 22244961713Sgirish } 22344961713Sgirish 22444961713Sgirish /* IPP soft reset */ 22544961713Sgirish if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) { 22644961713Sgirish goto fail; 22744961713Sgirish } 22844961713Sgirish 22944961713Sgirish /* to reset control FIFO */ 230a3c5bd6dSspeer if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS) 23144961713Sgirish goto fail; 23244961713Sgirish 23344961713Sgirish /* 234a3c5bd6dSspeer * Making sure that error source is cleared if this is an injected 235a3c5bd6dSspeer * error. 23644961713Sgirish */ 23744961713Sgirish IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0); 23844961713Sgirish 23944961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_reset: port%d", portn)); 24044961713Sgirish return (NXGE_OK); 24144961713Sgirish fail: 24244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 24344961713Sgirish "nxge_ipp_init: Fail to Reset IPP Port #%d\n", 24444961713Sgirish portn)); 24544961713Sgirish return (NXGE_ERROR | rs); 24644961713Sgirish } 24744961713Sgirish 248a3c5bd6dSspeer /* ARGSUSED */ 24944961713Sgirish nxge_status_t 25044961713Sgirish nxge_ipp_enable(p_nxge_t nxgep) 25144961713Sgirish { 252a3c5bd6dSspeer uint8_t portn; 253a3c5bd6dSspeer uint32_t config; 254a3c5bd6dSspeer npi_handle_t handle; 255a3c5bd6dSspeer uint32_t pkt_size; 256a3c5bd6dSspeer npi_status_t rs = NPI_SUCCESS; 25744961713Sgirish 25844961713Sgirish handle = nxgep->npi_handle; 25944961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 26044961713Sgirish 26144961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_enable: port%d", portn)); 26244961713Sgirish 26344961713Sgirish config = CFG_IPP | CFG_IPP_DFIFO_ECC_CORRECT | CFG_IPP_DROP_BAD_CRC | 264a3c5bd6dSspeer CFG_IPP_TCP_UDP_CKSUM; 26544961713Sgirish if ((rs = npi_ipp_config(handle, INIT, portn, config)) != NPI_SUCCESS) 26644961713Sgirish goto fail; 26744961713Sgirish nxgep->ipp.config = config; 26844961713Sgirish 26944961713Sgirish /* Set max packet size */ 27044961713Sgirish pkt_size = IPP_MAX_PKT_SIZE; 271a3c5bd6dSspeer if ((rs = npi_ipp_set_max_pktsize(handle, portn, 272a3c5bd6dSspeer IPP_MAX_PKT_SIZE)) != NPI_SUCCESS) 27344961713Sgirish goto fail; 27444961713Sgirish nxgep->ipp.max_pkt_size = pkt_size; 27544961713Sgirish 27644961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_enable: port%d", portn)); 27744961713Sgirish return (NXGE_OK); 27844961713Sgirish fail: 27944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 280a3c5bd6dSspeer "nxge_ipp_init: Fail to Enable IPP Port #%d\n", portn)); 28144961713Sgirish return (NXGE_ERROR | rs); 28244961713Sgirish } 28344961713Sgirish 284*678453a8Sspeer /* ARGSUSED */ 285*678453a8Sspeer nxge_status_t 286*678453a8Sspeer nxge_ipp_drain(p_nxge_t nxgep) 287*678453a8Sspeer { 288*678453a8Sspeer uint8_t portn; 289*678453a8Sspeer npi_handle_t handle; 290*678453a8Sspeer npi_status_t rs = NPI_SUCCESS; 291*678453a8Sspeer uint16_t wr_ptr, rd_ptr; 292*678453a8Sspeer uint32_t try_count; 293*678453a8Sspeer 294*678453a8Sspeer handle = nxgep->npi_handle; 295*678453a8Sspeer portn = NXGE_GET_PORT_NUM(nxgep->function_num); 296*678453a8Sspeer 297*678453a8Sspeer NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_drain: port%d", portn)); 298*678453a8Sspeer 299*678453a8Sspeer /* 300*678453a8Sspeer * Wait until ip read and write fifo pointers are equal 301*678453a8Sspeer */ 302*678453a8Sspeer (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 303*678453a8Sspeer (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 304*678453a8Sspeer try_count = NXGE_IPP_FIFO_SYNC_TRY_COUNT; 305*678453a8Sspeer 306*678453a8Sspeer while ((try_count > 0) && (rd_ptr != wr_ptr)) { 307*678453a8Sspeer (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 308*678453a8Sspeer (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 309*678453a8Sspeer try_count--; 310*678453a8Sspeer } 311*678453a8Sspeer 312*678453a8Sspeer if (try_count == 0) { 313*678453a8Sspeer if ((rd_ptr != 0) && (wr_ptr != 1)) { 314*678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 315*678453a8Sspeer " nxge_ipp_drain: port%d failed" 316*678453a8Sspeer " rd_fifo != wr_fifo", portn)); 317*678453a8Sspeer goto fail; 318*678453a8Sspeer } 319*678453a8Sspeer } 320*678453a8Sspeer 321*678453a8Sspeer NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_drain: port%d", portn)); 322*678453a8Sspeer return (NXGE_OK); 323*678453a8Sspeer fail: 324*678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_ipp_init: " 325*678453a8Sspeer "Fail to Reset IPP Port #%d\n", portn)); 326*678453a8Sspeer return (NXGE_ERROR | rs); 327*678453a8Sspeer } 328*678453a8Sspeer 329a3c5bd6dSspeer /* ARGSUSED */ 33044961713Sgirish nxge_status_t 33144961713Sgirish nxge_ipp_handle_sys_errors(p_nxge_t nxgep) 33244961713Sgirish { 333a3c5bd6dSspeer npi_handle_t handle; 334a3c5bd6dSspeer npi_status_t rs = NPI_SUCCESS; 335a3c5bd6dSspeer p_nxge_ipp_stats_t statsp; 336a3c5bd6dSspeer ipp_status_t istatus; 337a3c5bd6dSspeer uint8_t portn; 338a3c5bd6dSspeer p_ipp_errlog_t errlogp; 339a3c5bd6dSspeer boolean_t rxport_fatal = B_FALSE; 340a3c5bd6dSspeer nxge_status_t status = NXGE_OK; 34153f3d8ecSyc uint8_t cnt8; 34253f3d8ecSyc uint16_t cnt16; 34344961713Sgirish 34444961713Sgirish handle = nxgep->npi_handle; 34544961713Sgirish statsp = (p_nxge_ipp_stats_t)&nxgep->statsp->ipp_stats; 34644961713Sgirish portn = nxgep->mac.portnum; 34744961713Sgirish 34844961713Sgirish errlogp = (p_ipp_errlog_t)&statsp->errlog; 34944961713Sgirish 35044961713Sgirish if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 35144961713Sgirish return (NXGE_ERROR | rs); 35244961713Sgirish 353a3c5bd6dSspeer if (istatus.value == 0) { 35444961713Sgirish /* 35544961713Sgirish * The error is not initiated from this port, so just exit. 35644961713Sgirish */ 35744961713Sgirish return (NXGE_OK); 358a3c5bd6dSspeer } 35944961713Sgirish 36044961713Sgirish if (istatus.bits.w0.dfifo_missed_sop) { 36144961713Sgirish statsp->sop_miss++; 36244961713Sgirish if ((rs = npi_ipp_get_dfifo_eopm_rdptr(handle, portn, 36344961713Sgirish &errlogp->dfifo_rd_ptr)) != NPI_SUCCESS) 36444961713Sgirish return (NXGE_ERROR | rs); 36544961713Sgirish if ((rs = npi_ipp_get_state_mach(handle, portn, 366a3c5bd6dSspeer &errlogp->state_mach)) != NPI_SUCCESS) 36744961713Sgirish return (NXGE_ERROR | rs); 36844961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 369a3c5bd6dSspeer NXGE_FM_EREPORT_IPP_SOP_MISS); 37044961713Sgirish if (statsp->sop_miss < IPP_MAX_ERR_SHOW) 37144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 37244961713Sgirish "nxge_ipp_err_evnts: fatal error: sop_miss\n")); 37344961713Sgirish rxport_fatal = B_TRUE; 37444961713Sgirish } 37544961713Sgirish if (istatus.bits.w0.dfifo_missed_eop) { 37644961713Sgirish statsp->eop_miss++; 37744961713Sgirish if ((rs = npi_ipp_get_dfifo_eopm_rdptr(handle, portn, 378a3c5bd6dSspeer &errlogp->dfifo_rd_ptr)) != NPI_SUCCESS) 37944961713Sgirish return (NXGE_ERROR | rs); 38044961713Sgirish if ((rs = npi_ipp_get_state_mach(handle, portn, 381a3c5bd6dSspeer &errlogp->state_mach)) != NPI_SUCCESS) 38244961713Sgirish return (NXGE_ERROR | rs); 38344961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 384a3c5bd6dSspeer NXGE_FM_EREPORT_IPP_EOP_MISS); 38544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 386a3c5bd6dSspeer "nxge_ipp_err_evnts: fatal error: eop_miss\n")); 38744961713Sgirish rxport_fatal = B_TRUE; 38844961713Sgirish } 38944961713Sgirish if (istatus.bits.w0.dfifo_uncorr_ecc_err) { 39014ea4bb7Ssd boolean_t ue_ecc_valid; 39114ea4bb7Ssd 392a3c5bd6dSspeer if ((status = nxge_ipp_eccue_valid_check(nxgep, 393a3c5bd6dSspeer &ue_ecc_valid)) != NXGE_OK) 39414ea4bb7Ssd return (status); 39514ea4bb7Ssd 39614ea4bb7Ssd if (ue_ecc_valid) { 39714ea4bb7Ssd statsp->dfifo_ue++; 39814ea4bb7Ssd if ((rs = npi_ipp_get_ecc_syndrome(handle, portn, 39944961713Sgirish &errlogp->ecc_syndrome)) != NPI_SUCCESS) 40014ea4bb7Ssd return (NXGE_ERROR | rs); 40114ea4bb7Ssd NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 402a3c5bd6dSspeer NXGE_FM_EREPORT_IPP_DFIFO_UE); 40314ea4bb7Ssd NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 40444961713Sgirish "nxge_ipp_err_evnts: fatal error: dfifo_ue\n")); 40514ea4bb7Ssd rxport_fatal = B_TRUE; 40614ea4bb7Ssd } 40744961713Sgirish } 40844961713Sgirish if (istatus.bits.w0.pre_fifo_perr) { 40944961713Sgirish statsp->pfifo_perr++; 41044961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 411a3c5bd6dSspeer NXGE_FM_EREPORT_IPP_PFIFO_PERR); 41244961713Sgirish if (statsp->pfifo_perr < IPP_MAX_ERR_SHOW) 41344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 414a3c5bd6dSspeer "nxge_ipp_err_evnts: " 415a3c5bd6dSspeer "fatal error: pre_pifo_perr\n")); 41644961713Sgirish rxport_fatal = B_TRUE; 41744961713Sgirish } 41844961713Sgirish if (istatus.bits.w0.pre_fifo_overrun) { 41944961713Sgirish statsp->pfifo_over++; 42044961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 421a3c5bd6dSspeer NXGE_FM_EREPORT_IPP_PFIFO_OVER); 42244961713Sgirish if (statsp->pfifo_over < IPP_MAX_ERR_SHOW) 42344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 424a3c5bd6dSspeer "nxge_ipp_err_evnts: " 425a3c5bd6dSspeer "fatal error: pfifo_over\n")); 42644961713Sgirish rxport_fatal = B_TRUE; 42744961713Sgirish } 42844961713Sgirish if (istatus.bits.w0.pre_fifo_underrun) { 42944961713Sgirish statsp->pfifo_und++; 43044961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 431a3c5bd6dSspeer NXGE_FM_EREPORT_IPP_PFIFO_UND); 43244961713Sgirish if (statsp->pfifo_und < IPP_MAX_ERR_SHOW) 43344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 434a3c5bd6dSspeer "nxge_ipp_err_evnts: " 435a3c5bd6dSspeer "fatal error: pfifo_und\n")); 43644961713Sgirish rxport_fatal = B_TRUE; 43744961713Sgirish } 43844961713Sgirish if (istatus.bits.w0.bad_cksum_cnt_ovfl) { 439d710877aSyc /* 44063e23a19Syc * Do not send FMA ereport or log error message 44163e23a19Syc * in /var/adm/messages because this error does not 44263e23a19Syc * indicate a HW failure. 44363e23a19Syc * 444d710877aSyc * Clear bit BAD_CS_MX of register IPP_INT_STAT 445d710877aSyc * by reading register IPP_BAD_CS_CNT 446d710877aSyc */ 44753f3d8ecSyc (void) npi_ipp_get_cs_err_count(handle, portn, &cnt16); 44844961713Sgirish statsp->bad_cs_cnt += IPP_BAD_CS_CNT_MASK; 44944961713Sgirish } 45044961713Sgirish if (istatus.bits.w0.pkt_discard_cnt_ovfl) { 451d710877aSyc /* 45263e23a19Syc * Do not send FMA ereport or log error message 45363e23a19Syc * in /var/adm/messages because this error does not 45463e23a19Syc * indicate a HW failure. 45563e23a19Syc * 456d710877aSyc * Clear bit PKT_DIS_MX of register IPP_INT_STAT 457d710877aSyc * by reading register IPP_PKT_DIS 458d710877aSyc */ 45953f3d8ecSyc (void) npi_ipp_get_pkt_dis_count(handle, portn, &cnt16); 46044961713Sgirish statsp->pkt_dis_cnt += IPP_PKT_DIS_CNT_MASK; 46144961713Sgirish } 46253f3d8ecSyc if (istatus.bits.w0.ecc_err_cnt_ovfl) { 463d710877aSyc /* 464d710877aSyc * Clear bit ECC_ERR_MAX of register IPP_INI_STAT 465d710877aSyc * by reading register IPP_ECC 466d710877aSyc */ 46753f3d8ecSyc (void) npi_ipp_get_ecc_err_count(handle, portn, &cnt8); 46853f3d8ecSyc statsp->ecc_err_cnt += IPP_ECC_CNT_MASK; 469f6485eecSyc /* 470f6485eecSyc * A defect in Neptune port2's IPP module could generate 471f6485eecSyc * many fake but harmless ECC errors under stress and cause 472f6485eecSyc * the ecc-error-counter register IPP_ECC to reach its 473f6485eecSyc * maximum value in a few seconds. To avoid false alarm, do 474f6485eecSyc * not report the error if it is port2. 475f6485eecSyc */ 476f6485eecSyc if (portn != 2) { 477f6485eecSyc NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 478f6485eecSyc NXGE_FM_EREPORT_IPP_ECC_ERR_MAX); 479f6485eecSyc if (statsp->ecc_err_cnt < (IPP_MAX_ERR_SHOW * 480f6485eecSyc IPP_ECC_CNT_MASK)) { 481f6485eecSyc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 482f6485eecSyc "nxge_ipp_err_evnts: pkt_ecc_err_max\n")); 483f6485eecSyc } 484f6485eecSyc } 48553f3d8ecSyc } 48644961713Sgirish /* 487a3c5bd6dSspeer * Making sure that error source is cleared if this is an injected 488a3c5bd6dSspeer * error. 48944961713Sgirish */ 49044961713Sgirish IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0); 49144961713Sgirish 49244961713Sgirish if (rxport_fatal) { 49344961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, 494a3c5bd6dSspeer " nxge_ipp_handle_sys_errors:" 495a3c5bd6dSspeer " fatal Error on Port #%d\n", portn)); 49644961713Sgirish status = nxge_ipp_fatal_err_recover(nxgep); 49744961713Sgirish if (status == NXGE_OK) { 49844961713Sgirish FM_SERVICE_RESTORED(nxgep); 49944961713Sgirish } 50044961713Sgirish } 50144961713Sgirish return (status); 50244961713Sgirish } 50344961713Sgirish 504a3c5bd6dSspeer /* ARGSUSED */ 50544961713Sgirish void 50644961713Sgirish nxge_ipp_inject_err(p_nxge_t nxgep, uint32_t err_id) 50744961713Sgirish { 508a3c5bd6dSspeer ipp_status_t ipps; 509a3c5bd6dSspeer ipp_ecc_ctrl_t ecc_ctrl; 510a3c5bd6dSspeer uint8_t portn = nxgep->mac.portnum; 51144961713Sgirish 51244961713Sgirish switch (err_id) { 51344961713Sgirish case NXGE_FM_EREPORT_IPP_DFIFO_UE: 51444961713Sgirish ecc_ctrl.value = 0; 51544961713Sgirish ecc_ctrl.bits.w0.cor_dbl = 1; 51644961713Sgirish ecc_ctrl.bits.w0.cor_1 = 1; 51744961713Sgirish ecc_ctrl.bits.w0.cor_lst = 1; 51844961713Sgirish cmn_err(CE_NOTE, "!Write 0x%llx to IPP_ECC_CTRL_REG\n", 519a3c5bd6dSspeer (unsigned long long) ecc_ctrl.value); 52044961713Sgirish IPP_REG_WR(nxgep->npi_handle, portn, IPP_ECC_CTRL_REG, 521a3c5bd6dSspeer ecc_ctrl.value); 52244961713Sgirish break; 523a3c5bd6dSspeer 52444961713Sgirish case NXGE_FM_EREPORT_IPP_DFIFO_CE: 52544961713Sgirish ecc_ctrl.value = 0; 52644961713Sgirish ecc_ctrl.bits.w0.cor_sng = 1; 52744961713Sgirish ecc_ctrl.bits.w0.cor_1 = 1; 52844961713Sgirish ecc_ctrl.bits.w0.cor_snd = 1; 52944961713Sgirish cmn_err(CE_NOTE, "!Write 0x%llx to IPP_ECC_CTRL_REG\n", 530a3c5bd6dSspeer (unsigned long long) ecc_ctrl.value); 53144961713Sgirish IPP_REG_WR(nxgep->npi_handle, portn, IPP_ECC_CTRL_REG, 532a3c5bd6dSspeer ecc_ctrl.value); 53344961713Sgirish break; 534a3c5bd6dSspeer 53544961713Sgirish case NXGE_FM_EREPORT_IPP_EOP_MISS: 53644961713Sgirish case NXGE_FM_EREPORT_IPP_SOP_MISS: 53744961713Sgirish case NXGE_FM_EREPORT_IPP_PFIFO_PERR: 53844961713Sgirish case NXGE_FM_EREPORT_IPP_ECC_ERR_MAX: 53944961713Sgirish case NXGE_FM_EREPORT_IPP_PFIFO_OVER: 54044961713Sgirish case NXGE_FM_EREPORT_IPP_PFIFO_UND: 54144961713Sgirish case NXGE_FM_EREPORT_IPP_BAD_CS_MX: 54244961713Sgirish case NXGE_FM_EREPORT_IPP_PKT_DIS_MX: 54344961713Sgirish case NXGE_FM_EREPORT_IPP_RESET_FAIL: 54444961713Sgirish IPP_REG_RD(nxgep->npi_handle, portn, IPP_INT_STATUS_REG, 54544961713Sgirish &ipps.value); 54644961713Sgirish if (err_id == NXGE_FM_EREPORT_IPP_EOP_MISS) 54744961713Sgirish ipps.bits.w0.dfifo_missed_eop = 1; 54844961713Sgirish else if (err_id == NXGE_FM_EREPORT_IPP_SOP_MISS) 54944961713Sgirish ipps.bits.w0.dfifo_missed_sop = 1; 55044961713Sgirish else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_UE) 55144961713Sgirish ipps.bits.w0.dfifo_uncorr_ecc_err = 1; 55244961713Sgirish else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_CE) 55344961713Sgirish ipps.bits.w0.dfifo_corr_ecc_err = 1; 55444961713Sgirish else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_PERR) 55544961713Sgirish ipps.bits.w0.pre_fifo_perr = 1; 556d710877aSyc else if (err_id == NXGE_FM_EREPORT_IPP_ECC_ERR_MAX) { 557d710877aSyc /* 558d710877aSyc * Fill register IPP_ECC with max ECC-error- 559d710877aSyc * counter value (0xff) to set the ECC_ERR_MAX bit 560d710877aSyc * of the IPP_INT_STAT register and trigger an 561d710877aSyc * FMA ereport. 562d710877aSyc */ 563d710877aSyc IPP_REG_WR(nxgep->npi_handle, portn, 564d710877aSyc IPP_ECC_ERR_COUNTER_REG, IPP_ECC_CNT_MASK); 565d710877aSyc } else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_OVER) 56644961713Sgirish ipps.bits.w0.pre_fifo_overrun = 1; 56744961713Sgirish else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_UND) 56844961713Sgirish ipps.bits.w0.pre_fifo_underrun = 1; 569d710877aSyc else if (err_id == NXGE_FM_EREPORT_IPP_BAD_CS_MX) { 570d710877aSyc /* 571d710877aSyc * Fill IPP_BAD_CS_CNT with max bad-checksum-counter 572d710877aSyc * value (0x3fff) to set the BAD_CS_MX bit of 573d710877aSyc * IPP_INT_STAT and trigger an FMA ereport. 574d710877aSyc */ 575d710877aSyc IPP_REG_WR(nxgep->npi_handle, portn, 576f6485eecSyc IPP_BAD_CKSUM_ERR_CNT_REG, IPP_BAD_CS_CNT_MASK); 577d710877aSyc } else if (err_id == NXGE_FM_EREPORT_IPP_PKT_DIS_MX) { 578d710877aSyc /* 579d710877aSyc * Fill IPP_PKT_DIS with max packet-discard-counter 580d710877aSyc * value (0x3fff) to set the PKT_DIS_MX bit of 581d710877aSyc * IPP_INT_STAT and trigger an FMA ereport. 582d710877aSyc */ 583d710877aSyc IPP_REG_WR(nxgep->npi_handle, portn, 584d710877aSyc IPP_DISCARD_PKT_CNT_REG, IPP_PKT_DIS_CNT_MASK); 585d710877aSyc } 58644961713Sgirish cmn_err(CE_NOTE, "!Write 0x%llx to IPP_INT_STATUS_REG\n", 587a3c5bd6dSspeer (unsigned long long) ipps.value); 58844961713Sgirish IPP_REG_WR(nxgep->npi_handle, portn, IPP_INT_STATUS_REG, 589a3c5bd6dSspeer ipps.value); 59044961713Sgirish break; 59144961713Sgirish } 59244961713Sgirish } 59344961713Sgirish 594a3c5bd6dSspeer /* ARGSUSED */ 59544961713Sgirish nxge_status_t 59644961713Sgirish nxge_ipp_fatal_err_recover(p_nxge_t nxgep) 59744961713Sgirish { 598a3c5bd6dSspeer npi_handle_t handle; 599a3c5bd6dSspeer npi_status_t rs = NPI_SUCCESS; 600a3c5bd6dSspeer nxge_status_t status = NXGE_OK; 601a3c5bd6dSspeer uint8_t portn; 602a3c5bd6dSspeer uint16_t wr_ptr; 603a3c5bd6dSspeer uint16_t rd_ptr; 604a3c5bd6dSspeer uint32_t try_count; 605a3c5bd6dSspeer uint32_t dfifo_entries; 606a3c5bd6dSspeer ipp_status_t istatus; 607a3c5bd6dSspeer uint32_t d0, d1, d2, d3, d4; 608a3c5bd6dSspeer int i; 60944961713Sgirish 61044961713Sgirish NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_ipp_fatal_err_recover")); 61144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 612a3c5bd6dSspeer "Recovering from RxPort error...")); 61344961713Sgirish 61444961713Sgirish handle = nxgep->npi_handle; 61544961713Sgirish portn = nxgep->mac.portnum; 61644961713Sgirish 61744961713Sgirish /* 618a3c5bd6dSspeer * Making sure that error source is cleared if this is an injected 619a3c5bd6dSspeer * error. 62044961713Sgirish */ 62144961713Sgirish IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0); 62244961713Sgirish 62344961713Sgirish /* Disable RxMAC */ 62444961713Sgirish if (nxge_rx_mac_disable(nxgep) != NXGE_OK) 62544961713Sgirish goto fail; 62644961713Sgirish 62744961713Sgirish /* When recovering from IPP, RxDMA channel resets are not necessary */ 62844961713Sgirish /* Reset ZCP CFIFO */ 62944961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset ZCP CFIFO...", portn)); 63044961713Sgirish if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS) 63144961713Sgirish goto fail; 63244961713Sgirish 63344961713Sgirish /* 634a3c5bd6dSspeer * Wait until ip read and write fifo pointers are equal 63544961713Sgirish */ 63644961713Sgirish (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 63744961713Sgirish (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 63844961713Sgirish try_count = 512; 63944961713Sgirish 64044961713Sgirish while ((try_count > 0) && (rd_ptr != wr_ptr)) { 64144961713Sgirish (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 64244961713Sgirish (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 64344961713Sgirish try_count--; 64444961713Sgirish } 64544961713Sgirish 64644961713Sgirish if (try_count == 0) { 64744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 648a3c5bd6dSspeer " nxge_ipp_reset: port%d IPP stalled..." 649a3c5bd6dSspeer " rd_fifo_ptr = 0x%x wr_fifo_ptr = 0x%x", 650a3c5bd6dSspeer portn, rd_ptr, wr_ptr)); 65144961713Sgirish /* 652a3c5bd6dSspeer * This means the fatal error occurred on the first line of the 653a3c5bd6dSspeer * fifo. In this case, just reset the IPP without draining the 654a3c5bd6dSspeer * PFIFO. 65544961713Sgirish */ 65644961713Sgirish } 65744961713Sgirish 65859ac0c16Sdavemq if (nxgep->niu_type == N2_NIU) { 65959ac0c16Sdavemq dfifo_entries = IPP_NIU_DFIFO_ENTRIES; 6602e59129aSraghus } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 66144961713Sgirish if (portn < 2) 66244961713Sgirish dfifo_entries = IPP_P0_P1_DFIFO_ENTRIES; 66344961713Sgirish else 66444961713Sgirish dfifo_entries = IPP_P2_P3_DFIFO_ENTRIES; 66559ac0c16Sdavemq } else { 66644961713Sgirish goto fail; 66759ac0c16Sdavemq } 66844961713Sgirish 66944961713Sgirish /* Clean up DFIFO SRAM entries */ 67044961713Sgirish for (i = 0; i < dfifo_entries; i++) { 671a3c5bd6dSspeer if ((rs = npi_ipp_write_dfifo(handle, portn, 672a3c5bd6dSspeer i, 0, 0, 0, 0, 0)) != NPI_SUCCESS) 67344961713Sgirish goto fail; 674a3c5bd6dSspeer if ((rs = npi_ipp_read_dfifo(handle, portn, i, 675a3c5bd6dSspeer &d0, &d1, &d2, &d3, &d4)) != NPI_SUCCESS) 67644961713Sgirish goto fail; 67744961713Sgirish } 67844961713Sgirish 67944961713Sgirish /* Clear PFIFO DFIFO status bits */ 68044961713Sgirish if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 68144961713Sgirish goto fail; 68244961713Sgirish if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 68344961713Sgirish goto fail; 68444961713Sgirish 68544961713Sgirish /* Reset IPP */ 68644961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset IPP...", portn)); 68744961713Sgirish if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) 68844961713Sgirish goto fail; 68944961713Sgirish 69044961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset RxMAC...", portn)); 69144961713Sgirish if (nxge_rx_mac_reset(nxgep) != NXGE_OK) 69244961713Sgirish goto fail; 69344961713Sgirish 69444961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Initialize RxMAC...", portn)); 69544961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 69644961713Sgirish goto fail; 69744961713Sgirish 69844961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Enable RxMAC...", portn)); 69944961713Sgirish if (nxge_rx_mac_enable(nxgep) != NXGE_OK) 70044961713Sgirish goto fail; 70144961713Sgirish 70244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 703d710877aSyc "Recovery successful, RxPort restored")); 70444961713Sgirish NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_ipp_fatal_err_recover")); 70544961713Sgirish 70644961713Sgirish return (NXGE_OK); 70744961713Sgirish fail: 70844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed")); 70944961713Sgirish return (status | rs); 71044961713Sgirish } 71114ea4bb7Ssd 712a3c5bd6dSspeer /* ARGSUSED */ 7131a4557b6Syc /* 71453f3d8ecSyc * A hardware bug may cause fake ECCUEs (ECC Uncorrectable Error). 7151a4557b6Syc * This function checks if a ECCUE is real(valid) or not. It is not 7161a4557b6Syc * real if rd_ptr == wr_ptr. 7171a4557b6Syc * The hardware module that has the bug is used not only by the IPP 7181a4557b6Syc * FIFO but also by the ZCP FIFO, therefore this function is also 7191a4557b6Syc * called by nxge_zcp_handle_sys_errors for validating the ZCP FIFO 7201a4557b6Syc * error. 7211a4557b6Syc */ 72214ea4bb7Ssd nxge_status_t 72314ea4bb7Ssd nxge_ipp_eccue_valid_check(p_nxge_t nxgep, boolean_t *valid) 72414ea4bb7Ssd { 72514ea4bb7Ssd npi_handle_t handle; 72614ea4bb7Ssd npi_status_t rs = NPI_SUCCESS; 72714ea4bb7Ssd uint8_t portn; 72814ea4bb7Ssd uint16_t rd_ptr; 72914ea4bb7Ssd uint16_t wr_ptr; 73014ea4bb7Ssd uint16_t curr_rd_ptr; 73114ea4bb7Ssd uint16_t curr_wr_ptr; 73214ea4bb7Ssd uint32_t stall_cnt; 73314ea4bb7Ssd uint32_t d0, d1, d2, d3, d4; 73414ea4bb7Ssd 73514ea4bb7Ssd handle = nxgep->npi_handle; 73614ea4bb7Ssd portn = nxgep->mac.portnum; 73714ea4bb7Ssd *valid = B_TRUE; 73814ea4bb7Ssd 73914ea4bb7Ssd if ((rs = npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr)) 740a3c5bd6dSspeer != NPI_SUCCESS) 74114ea4bb7Ssd goto fail; 7421a4557b6Syc if ((rs = npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr)) 743a3c5bd6dSspeer != NPI_SUCCESS) 74414ea4bb7Ssd goto fail; 74514ea4bb7Ssd 74614ea4bb7Ssd if (rd_ptr == wr_ptr) { 7471a4557b6Syc *valid = B_FALSE; /* FIFO not stuck, so it's not a real ECCUE */ 74814ea4bb7Ssd } else { 74914ea4bb7Ssd stall_cnt = 0; 750ee5416c9Syc /* 751ee5416c9Syc * Check if the two pointers are moving, the ECCUE is invali 752ee5416c9Syc * if either pointer is moving, which indicates that the FIFO 753ee5416c9Syc * is functional. 754ee5416c9Syc */ 75514ea4bb7Ssd while (stall_cnt < 16) { 756a3c5bd6dSspeer if ((rs = npi_ipp_get_dfifo_rd_ptr(handle, 757a3c5bd6dSspeer portn, &curr_rd_ptr)) != NPI_SUCCESS) 75814ea4bb7Ssd goto fail; 759a3c5bd6dSspeer if ((rs = npi_ipp_get_dfifo_wr_ptr(handle, 760a3c5bd6dSspeer portn, &curr_wr_ptr)) != NPI_SUCCESS) 76114ea4bb7Ssd goto fail; 76214ea4bb7Ssd 763ee5416c9Syc if (rd_ptr == curr_rd_ptr && wr_ptr == curr_wr_ptr) { 76414ea4bb7Ssd stall_cnt++; 765ee5416c9Syc } else { 76614ea4bb7Ssd *valid = B_FALSE; 76714ea4bb7Ssd break; 76814ea4bb7Ssd } 76914ea4bb7Ssd } 77014ea4bb7Ssd 771a3c5bd6dSspeer if (valid) { 772ee5416c9Syc /* 773d710877aSyc * Further check to see if the ECCUE is valid. The 774ee5416c9Syc * error is real if the LSB of d4 is 1, which 775ee5416c9Syc * indicates that the data that has set the ECC 776ee5416c9Syc * error flag is the 16-byte internal control word. 777ee5416c9Syc */ 778ee5416c9Syc if ((rs = npi_ipp_read_dfifo(handle, portn, rd_ptr, 779ee5416c9Syc &d0, &d1, &d2, &d3, &d4)) != NPI_SUCCESS) 78014ea4bb7Ssd goto fail; 78114ea4bb7Ssd if ((d4 & 0x1) == 0) /* Not the 1st line */ 78214ea4bb7Ssd *valid = B_FALSE; 78314ea4bb7Ssd } 78414ea4bb7Ssd } 78514ea4bb7Ssd return (NXGE_OK); 78614ea4bb7Ssd fail: 78714ea4bb7Ssd return (NXGE_ERROR | rs); 78814ea4bb7Ssd } 789