xref: /titanic_51/usr/src/uts/common/io/nxge/nxge_zcp.c (revision 52ccf843e173e2a4a657360b0a22853fd413905f)
16f45ec7bSml29623 /*
26f45ec7bSml29623  * CDDL HEADER START
36f45ec7bSml29623  *
46f45ec7bSml29623  * The contents of this file are subject to the terms of the
56f45ec7bSml29623  * Common Development and Distribution License (the "License").
66f45ec7bSml29623  * You may not use this file except in compliance with the License.
76f45ec7bSml29623  *
86f45ec7bSml29623  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96f45ec7bSml29623  * or http://www.opensolaris.org/os/licensing.
106f45ec7bSml29623  * See the License for the specific language governing permissions
116f45ec7bSml29623  * and limitations under the License.
126f45ec7bSml29623  *
136f45ec7bSml29623  * When distributing Covered Code, include this CDDL HEADER in each
146f45ec7bSml29623  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156f45ec7bSml29623  * If applicable, add the following below this CDDL HEADER, with the
166f45ec7bSml29623  * fields enclosed by brackets "[]" replaced with your own identifying
176f45ec7bSml29623  * information: Portions Copyright [yyyy] [name of copyright owner]
186f45ec7bSml29623  *
196f45ec7bSml29623  * CDDL HEADER END
206f45ec7bSml29623  */
216f45ec7bSml29623 /*
22*52ccf843Smisaki  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
236f45ec7bSml29623  * Use is subject to license terms.
246f45ec7bSml29623  */
256f45ec7bSml29623 
266f45ec7bSml29623 #pragma ident	"%Z%%M%	%I%	%E% SMI"
276f45ec7bSml29623 
286f45ec7bSml29623 #include <nxge_impl.h>
296f45ec7bSml29623 #include <nxge_zcp.h>
306f45ec7bSml29623 #include <nxge_ipp.h>
316f45ec7bSml29623 
326f45ec7bSml29623 nxge_status_t
336f45ec7bSml29623 nxge_zcp_init(p_nxge_t nxgep)
346f45ec7bSml29623 {
356f45ec7bSml29623 	uint8_t portn;
366f45ec7bSml29623 	npi_handle_t handle;
376f45ec7bSml29623 	zcp_iconfig_t istatus;
386f45ec7bSml29623 	npi_status_t rs = NPI_SUCCESS;
396f45ec7bSml29623 	int i;
406f45ec7bSml29623 	zcp_ram_unit_t w_data;
416f45ec7bSml29623 	zcp_ram_unit_t r_data;
426f45ec7bSml29623 	uint32_t cfifo_depth;
436f45ec7bSml29623 
446f45ec7bSml29623 	handle = nxgep->npi_handle;
456f45ec7bSml29623 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
466f45ec7bSml29623 
4759ac0c16Sdavemq 	if (nxgep->niu_type == N2_NIU) {
4859ac0c16Sdavemq 		cfifo_depth = ZCP_NIU_CFIFO_DEPTH;
492e59129aSraghus 	} else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
506f45ec7bSml29623 		if (portn < 2)
516f45ec7bSml29623 			cfifo_depth = ZCP_P0_P1_CFIFO_DEPTH;
526f45ec7bSml29623 		else
536f45ec7bSml29623 			cfifo_depth = ZCP_P2_P3_CFIFO_DEPTH;
5459ac0c16Sdavemq 	} else {
5559ac0c16Sdavemq 		goto fail;
5659ac0c16Sdavemq 	}
576f45ec7bSml29623 
586f45ec7bSml29623 	/* Clean up CFIFO */
596f45ec7bSml29623 	w_data.w0 = 0;
606f45ec7bSml29623 	w_data.w1 = 0;
616f45ec7bSml29623 	w_data.w2 = 0;
626f45ec7bSml29623 	w_data.w3 = 0;
636f45ec7bSml29623 	w_data.w4 = 0;
646f45ec7bSml29623 
656f45ec7bSml29623 	for (i = 0; i < cfifo_depth; i++) {
666f45ec7bSml29623 		if (npi_zcp_tt_cfifo_entry(handle, OP_SET,
676f45ec7bSml29623 		    portn, i, &w_data) != NPI_SUCCESS)
686f45ec7bSml29623 			goto fail;
696f45ec7bSml29623 		if (npi_zcp_tt_cfifo_entry(handle, OP_GET,
706f45ec7bSml29623 		    portn, i, &r_data) != NPI_SUCCESS)
716f45ec7bSml29623 			goto fail;
726f45ec7bSml29623 	}
736f45ec7bSml29623 
746f45ec7bSml29623 	if (npi_zcp_rest_cfifo_port(handle, portn) != NPI_SUCCESS)
756f45ec7bSml29623 		goto fail;
766f45ec7bSml29623 
776f45ec7bSml29623 	/*
786f45ec7bSml29623 	 * Making sure that error source is cleared if this is an injected
796f45ec7bSml29623 	 * error.
806f45ec7bSml29623 	 */
816f45ec7bSml29623 	switch (portn) {
826f45ec7bSml29623 	case 0:
836f45ec7bSml29623 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
846f45ec7bSml29623 		break;
856f45ec7bSml29623 	case 1:
866f45ec7bSml29623 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
876f45ec7bSml29623 		break;
886f45ec7bSml29623 	case 2:
896f45ec7bSml29623 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
906f45ec7bSml29623 		break;
916f45ec7bSml29623 	case 3:
926f45ec7bSml29623 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
936f45ec7bSml29623 		break;
946f45ec7bSml29623 	}
956f45ec7bSml29623 
966f45ec7bSml29623 	if ((rs = npi_zcp_clear_istatus(handle)) != NPI_SUCCESS)
976f45ec7bSml29623 		return (NXGE_ERROR | rs);
986f45ec7bSml29623 	if ((rs = npi_zcp_get_istatus(handle, &istatus)) != NPI_SUCCESS)
996f45ec7bSml29623 		return (NXGE_ERROR | rs);
1006f45ec7bSml29623 	if ((rs = npi_zcp_iconfig(handle, INIT, ICFG_ZCP_ALL)) != NPI_SUCCESS)
1016f45ec7bSml29623 		goto fail;
1026f45ec7bSml29623 
1036f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_zcp_init: port%d", portn));
1046f45ec7bSml29623 	return (NXGE_OK);
1056f45ec7bSml29623 
1066f45ec7bSml29623 fail:
1076f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1086f45ec7bSml29623 	    "nxge_zcp_init: Fail to initialize ZCP Port #%d\n", portn));
1096f45ec7bSml29623 	return (NXGE_ERROR | rs);
1106f45ec7bSml29623 }
1116f45ec7bSml29623 
1126f45ec7bSml29623 nxge_status_t
1136f45ec7bSml29623 nxge_zcp_handle_sys_errors(p_nxge_t nxgep)
1146f45ec7bSml29623 {
1156f45ec7bSml29623 	npi_handle_t handle;
1166f45ec7bSml29623 	npi_status_t rs = NPI_SUCCESS;
1176f45ec7bSml29623 	p_nxge_zcp_stats_t statsp;
1186f45ec7bSml29623 	uint8_t portn;
1196f45ec7bSml29623 	zcp_iconfig_t istatus;
1206f45ec7bSml29623 	boolean_t rxport_fatal = B_FALSE;
1216f45ec7bSml29623 	nxge_status_t status = NXGE_OK;
1226f45ec7bSml29623 
1236f45ec7bSml29623 	handle = nxgep->npi_handle;
1246f45ec7bSml29623 	statsp = (p_nxge_zcp_stats_t)&nxgep->statsp->zcp_stats;
1256f45ec7bSml29623 	portn = nxgep->mac.portnum;
1266f45ec7bSml29623 
1276f45ec7bSml29623 	if ((rs = npi_zcp_get_istatus(handle, &istatus)) != NPI_SUCCESS)
1286f45ec7bSml29623 		return (NXGE_ERROR | rs);
1296f45ec7bSml29623 
1306f45ec7bSml29623 	if (istatus & ICFG_ZCP_RRFIFO_UNDERRUN) {
1316f45ec7bSml29623 		statsp->rrfifo_underrun++;
1326f45ec7bSml29623 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
1336f45ec7bSml29623 		    NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN);
1346f45ec7bSml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1356f45ec7bSml29623 		    "nxge_zcp_err_evnts: rrfifo_underrun"));
1366f45ec7bSml29623 	}
1376f45ec7bSml29623 
1386f45ec7bSml29623 	if (istatus & ICFG_ZCP_RRFIFO_OVERRUN) {
1396f45ec7bSml29623 		statsp->rrfifo_overrun++;
1406f45ec7bSml29623 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
1416f45ec7bSml29623 		    NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN);
1426f45ec7bSml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1436f45ec7bSml29623 		    "nxge_zcp_err_evnts: buf_rrfifo_overrun"));
1446f45ec7bSml29623 	}
1456f45ec7bSml29623 
1466f45ec7bSml29623 	if (istatus & ICFG_ZCP_RSPFIFO_UNCORR_ERR) {
1476f45ec7bSml29623 		statsp->rspfifo_uncorr_err++;
1486f45ec7bSml29623 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
1496f45ec7bSml29623 		    NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR);
1506f45ec7bSml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1516f45ec7bSml29623 		    "nxge_zcp_err_evnts: rspfifo_uncorr_err"));
1526f45ec7bSml29623 	}
1536f45ec7bSml29623 
1546f45ec7bSml29623 	if (istatus & ICFG_ZCP_BUFFER_OVERFLOW) {
1556f45ec7bSml29623 		statsp->buffer_overflow++;
1566f45ec7bSml29623 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
1576f45ec7bSml29623 		    NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW);
1586f45ec7bSml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1596f45ec7bSml29623 		    "nxge_zcp_err_evnts: buffer_overflow"));
1606f45ec7bSml29623 		rxport_fatal = B_TRUE;
1616f45ec7bSml29623 	}
1626f45ec7bSml29623 
1636f45ec7bSml29623 	if (istatus & ICFG_ZCP_STAT_TBL_PERR) {
1646f45ec7bSml29623 		statsp->stat_tbl_perr++;
1656f45ec7bSml29623 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
1666f45ec7bSml29623 		    NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR);
1676f45ec7bSml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1686f45ec7bSml29623 		    "nxge_zcp_err_evnts: stat_tbl_perr"));
1696f45ec7bSml29623 	}
1706f45ec7bSml29623 
1716f45ec7bSml29623 	if (istatus & ICFG_ZCP_DYN_TBL_PERR) {
1726f45ec7bSml29623 		statsp->dyn_tbl_perr++;
1736f45ec7bSml29623 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
1746f45ec7bSml29623 		    NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR);
1756f45ec7bSml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1766f45ec7bSml29623 		    "nxge_zcp_err_evnts: dyn_tbl_perr"));
1776f45ec7bSml29623 	}
1786f45ec7bSml29623 
1796f45ec7bSml29623 	if (istatus & ICFG_ZCP_BUF_TBL_PERR) {
1806f45ec7bSml29623 		statsp->buf_tbl_perr++;
1816f45ec7bSml29623 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
1826f45ec7bSml29623 		    NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR);
1836f45ec7bSml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1846f45ec7bSml29623 		    "nxge_zcp_err_evnts: buf_tbl_perr"));
1856f45ec7bSml29623 	}
1866f45ec7bSml29623 
1876f45ec7bSml29623 	if (istatus & ICFG_ZCP_TT_PROGRAM_ERR) {
1886f45ec7bSml29623 		statsp->tt_program_err++;
1896f45ec7bSml29623 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
1906f45ec7bSml29623 		    NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR);
1916f45ec7bSml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1926f45ec7bSml29623 		    "nxge_zcp_err_evnts: tt_program_err"));
1936f45ec7bSml29623 	}
1946f45ec7bSml29623 
1956f45ec7bSml29623 	if (istatus & ICFG_ZCP_RSP_TT_INDEX_ERR) {
1966f45ec7bSml29623 		statsp->rsp_tt_index_err++;
1976f45ec7bSml29623 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
1986f45ec7bSml29623 		    NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR);
1996f45ec7bSml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2006f45ec7bSml29623 		    "nxge_zcp_err_evnts: rsp_tt_index_err"));
2016f45ec7bSml29623 	}
2026f45ec7bSml29623 
2036f45ec7bSml29623 	if (istatus & ICFG_ZCP_SLV_TT_INDEX_ERR) {
2046f45ec7bSml29623 		statsp->slv_tt_index_err++;
2056f45ec7bSml29623 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
2066f45ec7bSml29623 		    NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR);
2076f45ec7bSml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2086f45ec7bSml29623 		    "nxge_zcp_err_evnts: slv_tt_index_err"));
2096f45ec7bSml29623 	}
2106f45ec7bSml29623 
2116f45ec7bSml29623 	if (istatus & ICFG_ZCP_TT_INDEX_ERR) {
2126f45ec7bSml29623 		statsp->zcp_tt_index_err++;
2136f45ec7bSml29623 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
2146f45ec7bSml29623 		    NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR);
2156f45ec7bSml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2166f45ec7bSml29623 		    "nxge_zcp_err_evnts: tt_index_err"));
2176f45ec7bSml29623 	}
2186f45ec7bSml29623 
2196f45ec7bSml29623 	if (((portn == 0) && (istatus & ICFG_ZCP_CFIFO_ECC0)) ||
2206f45ec7bSml29623 	    ((portn == 1) && (istatus & ICFG_ZCP_CFIFO_ECC1)) ||
2216f45ec7bSml29623 	    ((portn == 2) && (istatus & ICFG_ZCP_CFIFO_ECC2)) ||
2226f45ec7bSml29623 	    ((portn == 3) && (istatus & ICFG_ZCP_CFIFO_ECC3))) {
2236f45ec7bSml29623 		boolean_t ue_ecc_valid;
2246f45ec7bSml29623 
2256f45ec7bSml29623 		if ((status = nxge_ipp_eccue_valid_check(nxgep,
2266f45ec7bSml29623 		    &ue_ecc_valid)) != NXGE_OK)
2276f45ec7bSml29623 			return (status);
2286f45ec7bSml29623 
2296f45ec7bSml29623 		if (ue_ecc_valid) {
2306f45ec7bSml29623 			statsp->cfifo_ecc++;
2316f45ec7bSml29623 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
2326f45ec7bSml29623 			    NXGE_FM_EREPORT_ZCP_CFIFO_ECC);
2336f45ec7bSml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2346f45ec7bSml29623 			    "nxge_zcp_err_evnts: port%d buf_cfifo_ecc",
2356f45ec7bSml29623 			    portn));
2366f45ec7bSml29623 			rxport_fatal = B_TRUE;
2376f45ec7bSml29623 		}
2386f45ec7bSml29623 	}
2396f45ec7bSml29623 
2406f45ec7bSml29623 	/*
2416f45ec7bSml29623 	 * Making sure that error source is cleared if this is an injected
2426f45ec7bSml29623 	 * error.
2436f45ec7bSml29623 	 */
2446f45ec7bSml29623 	switch (portn) {
2456f45ec7bSml29623 	case 0:
2466f45ec7bSml29623 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
2476f45ec7bSml29623 		break;
2486f45ec7bSml29623 	case 1:
2496f45ec7bSml29623 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
2506f45ec7bSml29623 		break;
2516f45ec7bSml29623 	case 2:
2526f45ec7bSml29623 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
2536f45ec7bSml29623 		break;
2546f45ec7bSml29623 	case 3:
2556f45ec7bSml29623 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
2566f45ec7bSml29623 		break;
2576f45ec7bSml29623 	}
2586f45ec7bSml29623 
2596f45ec7bSml29623 	(void) npi_zcp_clear_istatus(handle);
2606f45ec7bSml29623 
2616f45ec7bSml29623 	if (rxport_fatal) {
2626f45ec7bSml29623 		NXGE_DEBUG_MSG((nxgep, IPP_CTL,
2636f45ec7bSml29623 		    " nxge_zcp_handle_sys_errors:"
2646f45ec7bSml29623 		    " fatal Error on  Port #%d\n", portn));
2656f45ec7bSml29623 		status = nxge_zcp_fatal_err_recover(nxgep);
2666f45ec7bSml29623 		if (status == NXGE_OK) {
2676f45ec7bSml29623 			FM_SERVICE_RESTORED(nxgep);
2686f45ec7bSml29623 		}
2696f45ec7bSml29623 	}
2706f45ec7bSml29623 	return (status);
2716f45ec7bSml29623 }
2726f45ec7bSml29623 
2736f45ec7bSml29623 void
2746f45ec7bSml29623 nxge_zcp_inject_err(p_nxge_t nxgep, uint32_t err_id)
2756f45ec7bSml29623 {
2766f45ec7bSml29623 	zcp_int_stat_reg_t zcps;
2776f45ec7bSml29623 	uint8_t portn = nxgep->mac.portnum;
2786f45ec7bSml29623 	zcp_ecc_ctrl_t ecc_ctrl;
2796f45ec7bSml29623 
2806f45ec7bSml29623 	switch (err_id) {
2816f45ec7bSml29623 	case NXGE_FM_EREPORT_ZCP_CFIFO_ECC:
2826f45ec7bSml29623 		ecc_ctrl.value = 0;
2836f45ec7bSml29623 		ecc_ctrl.bits.w0.cor_dbl = 1;
2846f45ec7bSml29623 		ecc_ctrl.bits.w0.cor_lst = 1;
2856f45ec7bSml29623 		ecc_ctrl.bits.w0.cor_all = 0;
2866f45ec7bSml29623 		switch (portn) {
2876f45ec7bSml29623 		case 0:
2886f45ec7bSml29623 			cmn_err(CE_NOTE,
2896f45ec7bSml29623 			    "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
2906f45ec7bSml29623 			    (unsigned long long) ecc_ctrl.value, portn);
2916f45ec7bSml29623 			NXGE_REG_WR64(nxgep->npi_handle,
2926f45ec7bSml29623 			    ZCP_CFIFO_ECC_PORT0_REG,
2936f45ec7bSml29623 			    ecc_ctrl.value);
2946f45ec7bSml29623 			break;
2956f45ec7bSml29623 		case 1:
2966f45ec7bSml29623 			cmn_err(CE_NOTE,
2976f45ec7bSml29623 			    "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
2986f45ec7bSml29623 			    (unsigned long long) ecc_ctrl.value, portn);
2996f45ec7bSml29623 			NXGE_REG_WR64(nxgep->npi_handle,
3006f45ec7bSml29623 			    ZCP_CFIFO_ECC_PORT1_REG,
3016f45ec7bSml29623 			    ecc_ctrl.value);
3026f45ec7bSml29623 			break;
3036f45ec7bSml29623 		case 2:
3046f45ec7bSml29623 			cmn_err(CE_NOTE,
3056f45ec7bSml29623 			    "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
3066f45ec7bSml29623 			    (unsigned long long) ecc_ctrl.value, portn);
3076f45ec7bSml29623 			NXGE_REG_WR64(nxgep->npi_handle,
3086f45ec7bSml29623 			    ZCP_CFIFO_ECC_PORT2_REG,
3096f45ec7bSml29623 			    ecc_ctrl.value);
3106f45ec7bSml29623 			break;
3116f45ec7bSml29623 		case 3:
3126f45ec7bSml29623 			cmn_err(CE_NOTE,
3136f45ec7bSml29623 			    "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
3146f45ec7bSml29623 			    (unsigned long long) ecc_ctrl.value, portn);
3156f45ec7bSml29623 			NXGE_REG_WR64(nxgep->npi_handle,
3166f45ec7bSml29623 			    ZCP_CFIFO_ECC_PORT3_REG,
3176f45ec7bSml29623 			    ecc_ctrl.value);
3186f45ec7bSml29623 			break;
3196f45ec7bSml29623 		}
3206f45ec7bSml29623 		break;
3216f45ec7bSml29623 
3226f45ec7bSml29623 	case NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN:
3236f45ec7bSml29623 	case NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR:
3246f45ec7bSml29623 	case NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR:
3256f45ec7bSml29623 	case NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR:
3266f45ec7bSml29623 	case NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR:
3276f45ec7bSml29623 	case NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN:
3286f45ec7bSml29623 	case NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW:
3296f45ec7bSml29623 	case NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR:
3306f45ec7bSml29623 	case NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR:
3316f45ec7bSml29623 	case NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR:
3326f45ec7bSml29623 	case NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR:
3336f45ec7bSml29623 		NXGE_REG_RD64(nxgep->npi_handle, ZCP_INT_STAT_TEST_REG,
3346f45ec7bSml29623 		    &zcps.value);
3356f45ec7bSml29623 		if (err_id == NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN)
3366f45ec7bSml29623 			zcps.bits.ldw.rrfifo_urun = 1;
3376f45ec7bSml29623 		if (err_id == NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR)
3386f45ec7bSml29623 			zcps.bits.ldw.rspfifo_uc_err = 1;
3396f45ec7bSml29623 		if (err_id == NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR)
3406f45ec7bSml29623 			zcps.bits.ldw.stat_tbl_perr = 1;
3416f45ec7bSml29623 		if (err_id == NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR)
3426f45ec7bSml29623 			zcps.bits.ldw.dyn_tbl_perr = 1;
3436f45ec7bSml29623 		if (err_id == NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR)
3446f45ec7bSml29623 			zcps.bits.ldw.buf_tbl_perr = 1;
3456f45ec7bSml29623 		if (err_id == NXGE_FM_EREPORT_ZCP_CFIFO_ECC) {
3466f45ec7bSml29623 			switch (portn) {
3476f45ec7bSml29623 			case 0:
3486f45ec7bSml29623 				zcps.bits.ldw.cfifo_ecc0 = 1;
3496f45ec7bSml29623 				break;
3506f45ec7bSml29623 			case 1:
3516f45ec7bSml29623 				zcps.bits.ldw.cfifo_ecc1 = 1;
3526f45ec7bSml29623 				break;
3536f45ec7bSml29623 			case 2:
3546f45ec7bSml29623 				zcps.bits.ldw.cfifo_ecc2 = 1;
3556f45ec7bSml29623 				break;
3566f45ec7bSml29623 			case 3:
3576f45ec7bSml29623 				zcps.bits.ldw.cfifo_ecc3 = 1;
3586f45ec7bSml29623 				break;
3596f45ec7bSml29623 			}
3606f45ec7bSml29623 		}
3616f45ec7bSml29623 
3626f45ec7bSml29623 	default:
3636f45ec7bSml29623 		if (err_id == NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN)
3646f45ec7bSml29623 			zcps.bits.ldw.rrfifo_orun = 1;
3656f45ec7bSml29623 		if (err_id == NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW)
3666f45ec7bSml29623 			zcps.bits.ldw.buf_overflow = 1;
3676f45ec7bSml29623 		if (err_id == NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR)
3686f45ec7bSml29623 			zcps.bits.ldw.tt_tbl_perr = 1;
3696f45ec7bSml29623 		if (err_id == NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR)
3706f45ec7bSml29623 			zcps.bits.ldw.rsp_tt_index_err = 1;
3716f45ec7bSml29623 		if (err_id == NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR)
3726f45ec7bSml29623 			zcps.bits.ldw.slv_tt_index_err = 1;
3736f45ec7bSml29623 		if (err_id == NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR)
3746f45ec7bSml29623 			zcps.bits.ldw.zcp_tt_index_err = 1;
375adfcba55Sjoycey #if defined(__i386)
376adfcba55Sjoycey 		cmn_err(CE_NOTE, "!Write 0x%llx to ZCP_INT_STAT_TEST_REG\n",
377adfcba55Sjoycey 		    zcps.value);
378adfcba55Sjoycey #else
3796f45ec7bSml29623 		cmn_err(CE_NOTE, "!Write 0x%lx to ZCP_INT_STAT_TEST_REG\n",
3806f45ec7bSml29623 		    zcps.value);
381adfcba55Sjoycey #endif
3826f45ec7bSml29623 		NXGE_REG_WR64(nxgep->npi_handle, ZCP_INT_STAT_TEST_REG,
3836f45ec7bSml29623 		    zcps.value);
3846f45ec7bSml29623 		break;
3856f45ec7bSml29623 	}
3866f45ec7bSml29623 }
3876f45ec7bSml29623 
3886f45ec7bSml29623 nxge_status_t
3896f45ec7bSml29623 nxge_zcp_fatal_err_recover(p_nxge_t nxgep)
3906f45ec7bSml29623 {
3916f45ec7bSml29623 	npi_handle_t handle;
3926f45ec7bSml29623 	npi_status_t rs = NPI_SUCCESS;
3936f45ec7bSml29623 	nxge_status_t status = NXGE_OK;
3946f45ec7bSml29623 	uint8_t portn;
3956f45ec7bSml29623 	zcp_ram_unit_t w_data;
3966f45ec7bSml29623 	zcp_ram_unit_t r_data;
3976f45ec7bSml29623 	uint32_t cfifo_depth;
3986f45ec7bSml29623 	int i;
3996f45ec7bSml29623 
4006f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_zcp_fatal_err_recover"));
4016f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4026f45ec7bSml29623 	    "Recovering from RxPort error..."));
4036f45ec7bSml29623 
4046f45ec7bSml29623 	handle = nxgep->npi_handle;
4056f45ec7bSml29623 	portn = nxgep->mac.portnum;
4066f45ec7bSml29623 
4076f45ec7bSml29623 	/* Disable RxMAC */
4086f45ec7bSml29623 	if (nxge_rx_mac_disable(nxgep) != NXGE_OK)
4096f45ec7bSml29623 		goto fail;
4106f45ec7bSml29623 
4116f45ec7bSml29623 	/* Make sure source is clear if this is an injected error */
4126f45ec7bSml29623 	switch (portn) {
4136f45ec7bSml29623 	case 0:
4146f45ec7bSml29623 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
4156f45ec7bSml29623 		break;
4166f45ec7bSml29623 	case 1:
4176f45ec7bSml29623 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
4186f45ec7bSml29623 		break;
4196f45ec7bSml29623 	case 2:
4206f45ec7bSml29623 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
4216f45ec7bSml29623 		break;
4226f45ec7bSml29623 	case 3:
4236f45ec7bSml29623 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
4246f45ec7bSml29623 		break;
4256f45ec7bSml29623 	}
4266f45ec7bSml29623 
4276f45ec7bSml29623 	/* Clear up CFIFO */
42859ac0c16Sdavemq 	if (nxgep->niu_type == N2_NIU) {
42959ac0c16Sdavemq 		cfifo_depth = ZCP_NIU_CFIFO_DEPTH;
4302e59129aSraghus 	} else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
4316f45ec7bSml29623 		if (portn < 2)
4326f45ec7bSml29623 			cfifo_depth = ZCP_P0_P1_CFIFO_DEPTH;
4336f45ec7bSml29623 		else
4346f45ec7bSml29623 			cfifo_depth = ZCP_P2_P3_CFIFO_DEPTH;
43559ac0c16Sdavemq 	} else {
43659ac0c16Sdavemq 		goto fail;
43759ac0c16Sdavemq 	}
4386f45ec7bSml29623 
4396f45ec7bSml29623 	w_data.w0 = 0;
4406f45ec7bSml29623 	w_data.w1 = 0;
4416f45ec7bSml29623 	w_data.w2 = 0;
4426f45ec7bSml29623 	w_data.w3 = 0;
4436f45ec7bSml29623 	w_data.w4 = 0;
4446f45ec7bSml29623 
4456f45ec7bSml29623 	for (i = 0; i < cfifo_depth; i++) {
4466f45ec7bSml29623 		if (npi_zcp_tt_cfifo_entry(handle, OP_SET,
4476f45ec7bSml29623 		    portn, i, &w_data) != NPI_SUCCESS)
4486f45ec7bSml29623 			goto fail;
4496f45ec7bSml29623 		if (npi_zcp_tt_cfifo_entry(handle, OP_GET,
4506f45ec7bSml29623 		    portn, i, &r_data) != NPI_SUCCESS)
4516f45ec7bSml29623 			goto fail;
4526f45ec7bSml29623 	}
4536f45ec7bSml29623 
4546f45ec7bSml29623 	/* When recovering from ZCP, RxDMA channel resets are not necessary */
4556f45ec7bSml29623 	/* Reset ZCP CFIFO */
4566f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset ZCP CFIFO...", portn));
4576f45ec7bSml29623 	if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS)
4586f45ec7bSml29623 		goto fail;
4596f45ec7bSml29623 
4606f45ec7bSml29623 	/* Reset IPP */
4616f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset IPP...", portn));
4626f45ec7bSml29623 	if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS)
4636f45ec7bSml29623 		goto fail;
4646f45ec7bSml29623 
4656f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset RxMAC...", portn));
4666f45ec7bSml29623 	if (nxge_rx_mac_reset(nxgep) != NXGE_OK)
4676f45ec7bSml29623 		goto fail;
4686f45ec7bSml29623 
4696f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Initialize RxMAC...", portn));
4706f45ec7bSml29623 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
4716f45ec7bSml29623 		goto fail;
4726f45ec7bSml29623 
4736f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Enable RxMAC...", portn));
4746f45ec7bSml29623 	if (nxge_rx_mac_enable(nxgep) != NXGE_OK)
4756f45ec7bSml29623 		goto fail;
4766f45ec7bSml29623 
4776f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4786f45ec7bSml29623 	    "Recovery Sucessful, RxPort Restored"));
4796f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_zcp_fatal_err_recover"));
4806f45ec7bSml29623 	return (NXGE_OK);
4816f45ec7bSml29623 fail:
4826f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed"));
4836f45ec7bSml29623 	return (status | rs);
4846f45ec7bSml29623 }
485