xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_zcp.c (revision 2e59129a)
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 /*
22a3c5bd6dSspeer  * Copyright 2007 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_zcp.h>
3014ea4bb7Ssd #include <nxge_ipp.h>
3114ea4bb7Ssd 
3244961713Sgirish nxge_status_t
3344961713Sgirish nxge_zcp_init(p_nxge_t nxgep)
3444961713Sgirish {
35a3c5bd6dSspeer 	uint8_t portn;
36a3c5bd6dSspeer 	npi_handle_t handle;
37a3c5bd6dSspeer 	zcp_iconfig_t istatus;
38a3c5bd6dSspeer 	npi_status_t rs = NPI_SUCCESS;
39a3c5bd6dSspeer 	int i;
40a3c5bd6dSspeer 	zcp_ram_unit_t w_data;
41a3c5bd6dSspeer 	zcp_ram_unit_t r_data;
42a3c5bd6dSspeer 	uint32_t cfifo_depth;
4344961713Sgirish 
4444961713Sgirish 	handle = nxgep->npi_handle;
4544961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
4644961713Sgirish 
4759ac0c16Sdavemq 	if (nxgep->niu_type == N2_NIU) {
4859ac0c16Sdavemq 		cfifo_depth = ZCP_NIU_CFIFO_DEPTH;
49*2e59129aSraghus 	} else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
5044961713Sgirish 		if (portn < 2)
5144961713Sgirish 			cfifo_depth = ZCP_P0_P1_CFIFO_DEPTH;
5244961713Sgirish 		else
5344961713Sgirish 			cfifo_depth = ZCP_P2_P3_CFIFO_DEPTH;
5459ac0c16Sdavemq 	} else {
5559ac0c16Sdavemq 		goto fail;
5659ac0c16Sdavemq 	}
5744961713Sgirish 
5844961713Sgirish 	/* Clean up CFIFO */
5944961713Sgirish 	w_data.w0 = 0;
6044961713Sgirish 	w_data.w1 = 0;
6144961713Sgirish 	w_data.w2 = 0;
6244961713Sgirish 	w_data.w3 = 0;
6344961713Sgirish 	w_data.w4 = 0;
64a3c5bd6dSspeer 
6544961713Sgirish 	for (i = 0; i < cfifo_depth; i++) {
66a3c5bd6dSspeer 		if (npi_zcp_tt_cfifo_entry(handle, OP_SET,
67a3c5bd6dSspeer 				portn, i, &w_data) != NPI_SUCCESS)
6844961713Sgirish 			goto fail;
69a3c5bd6dSspeer 		if (npi_zcp_tt_cfifo_entry(handle, OP_GET,
70a3c5bd6dSspeer 				portn, i, &r_data) != NPI_SUCCESS)
7144961713Sgirish 			goto fail;
7244961713Sgirish 	}
7344961713Sgirish 
7444961713Sgirish 	if (npi_zcp_rest_cfifo_port(handle, portn) != NPI_SUCCESS)
75a3c5bd6dSspeer 		goto fail;
76a3c5bd6dSspeer 
7744961713Sgirish 	/*
78a3c5bd6dSspeer 	 * Making sure that error source is cleared if this is an injected
79a3c5bd6dSspeer 	 * error.
8044961713Sgirish 	 */
8144961713Sgirish 	switch (portn) {
8244961713Sgirish 	case 0:
8344961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
8444961713Sgirish 		break;
8544961713Sgirish 	case 1:
8644961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
8744961713Sgirish 		break;
8844961713Sgirish 	case 2:
8944961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
9044961713Sgirish 		break;
9144961713Sgirish 	case 3:
9244961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
9344961713Sgirish 		break;
9444961713Sgirish 	}
9544961713Sgirish 
9614ea4bb7Ssd 	if ((rs = npi_zcp_clear_istatus(handle)) != NPI_SUCCESS)
9714ea4bb7Ssd 		return (NXGE_ERROR | rs);
9844961713Sgirish 	if ((rs = npi_zcp_get_istatus(handle, &istatus)) != NPI_SUCCESS)
9944961713Sgirish 		return (NXGE_ERROR | rs);
10044961713Sgirish 	if ((rs = npi_zcp_iconfig(handle, INIT, ICFG_ZCP_ALL)) != NPI_SUCCESS)
10144961713Sgirish 		goto fail;
10244961713Sgirish 
10344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_zcp_init: port%d", portn));
10444961713Sgirish 	return (NXGE_OK);
10544961713Sgirish 
10644961713Sgirish fail:
10744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
108a3c5bd6dSspeer 		"nxge_zcp_init: Fail to initialize ZCP Port #%d\n", portn));
10944961713Sgirish 	return (NXGE_ERROR | rs);
11044961713Sgirish }
11144961713Sgirish 
11244961713Sgirish nxge_status_t
11344961713Sgirish nxge_zcp_handle_sys_errors(p_nxge_t nxgep)
11444961713Sgirish {
115a3c5bd6dSspeer 	npi_handle_t handle;
116a3c5bd6dSspeer 	npi_status_t rs = NPI_SUCCESS;
117a3c5bd6dSspeer 	p_nxge_zcp_stats_t statsp;
118a3c5bd6dSspeer 	uint8_t portn;
119a3c5bd6dSspeer 	zcp_iconfig_t istatus;
120a3c5bd6dSspeer 	boolean_t rxport_fatal = B_FALSE;
121a3c5bd6dSspeer 	nxge_status_t status = NXGE_OK;
12244961713Sgirish 
12344961713Sgirish 	handle = nxgep->npi_handle;
12444961713Sgirish 	statsp = (p_nxge_zcp_stats_t)&nxgep->statsp->zcp_stats;
12544961713Sgirish 	portn = nxgep->mac.portnum;
12644961713Sgirish 
12744961713Sgirish 	if ((rs = npi_zcp_get_istatus(handle, &istatus)) != NPI_SUCCESS)
12844961713Sgirish 		return (NXGE_ERROR | rs);
12944961713Sgirish 
13044961713Sgirish 	if (istatus & ICFG_ZCP_RRFIFO_UNDERRUN) {
13144961713Sgirish 		statsp->rrfifo_underrun++;
13244961713Sgirish 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
133a3c5bd6dSspeer 			NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN);
13444961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
13544961713Sgirish 			"nxge_zcp_err_evnts: rrfifo_underrun"));
13644961713Sgirish 	}
137a3c5bd6dSspeer 
13844961713Sgirish 	if (istatus & ICFG_ZCP_RRFIFO_OVERRUN) {
13944961713Sgirish 		statsp->rrfifo_overrun++;
14044961713Sgirish 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
141a3c5bd6dSspeer 			NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN);
14244961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
14344961713Sgirish 			"nxge_zcp_err_evnts: buf_rrfifo_overrun"));
14444961713Sgirish 	}
145a3c5bd6dSspeer 
14644961713Sgirish 	if (istatus & ICFG_ZCP_RSPFIFO_UNCORR_ERR) {
14744961713Sgirish 		statsp->rspfifo_uncorr_err++;
14844961713Sgirish 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
149a3c5bd6dSspeer 			NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR);
15044961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15144961713Sgirish 			"nxge_zcp_err_evnts: rspfifo_uncorr_err"));
15244961713Sgirish 	}
153a3c5bd6dSspeer 
15444961713Sgirish 	if (istatus & ICFG_ZCP_BUFFER_OVERFLOW) {
15544961713Sgirish 		statsp->buffer_overflow++;
15644961713Sgirish 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
157a3c5bd6dSspeer 			NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW);
15844961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15944961713Sgirish 			"nxge_zcp_err_evnts: buffer_overflow"));
16044961713Sgirish 		rxport_fatal = B_TRUE;
16144961713Sgirish 	}
162a3c5bd6dSspeer 
16344961713Sgirish 	if (istatus & ICFG_ZCP_STAT_TBL_PERR) {
16444961713Sgirish 		statsp->stat_tbl_perr++;
16544961713Sgirish 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
166a3c5bd6dSspeer 			NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR);
16744961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16844961713Sgirish 			"nxge_zcp_err_evnts: stat_tbl_perr"));
16944961713Sgirish 	}
170a3c5bd6dSspeer 
17144961713Sgirish 	if (istatus & ICFG_ZCP_DYN_TBL_PERR) {
17244961713Sgirish 		statsp->dyn_tbl_perr++;
17344961713Sgirish 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
174a3c5bd6dSspeer 			NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR);
17544961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
17644961713Sgirish 			"nxge_zcp_err_evnts: dyn_tbl_perr"));
17744961713Sgirish 	}
178a3c5bd6dSspeer 
17944961713Sgirish 	if (istatus & ICFG_ZCP_BUF_TBL_PERR) {
18044961713Sgirish 		statsp->buf_tbl_perr++;
18144961713Sgirish 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
182a3c5bd6dSspeer 			NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR);
18344961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18444961713Sgirish 			"nxge_zcp_err_evnts: buf_tbl_perr"));
18544961713Sgirish 	}
186a3c5bd6dSspeer 
18744961713Sgirish 	if (istatus & ICFG_ZCP_TT_PROGRAM_ERR) {
18844961713Sgirish 		statsp->tt_program_err++;
18944961713Sgirish 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
190a3c5bd6dSspeer 			NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR);
19144961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
19244961713Sgirish 			"nxge_zcp_err_evnts: tt_program_err"));
19344961713Sgirish 	}
194a3c5bd6dSspeer 
19544961713Sgirish 	if (istatus & ICFG_ZCP_RSP_TT_INDEX_ERR) {
19644961713Sgirish 		statsp->rsp_tt_index_err++;
19744961713Sgirish 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
198a3c5bd6dSspeer 			NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR);
19944961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20044961713Sgirish 			"nxge_zcp_err_evnts: rsp_tt_index_err"));
20144961713Sgirish 	}
202a3c5bd6dSspeer 
20344961713Sgirish 	if (istatus & ICFG_ZCP_SLV_TT_INDEX_ERR) {
20444961713Sgirish 		statsp->slv_tt_index_err++;
20544961713Sgirish 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
206a3c5bd6dSspeer 			NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR);
20744961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20844961713Sgirish 			"nxge_zcp_err_evnts: slv_tt_index_err"));
20944961713Sgirish 	}
210a3c5bd6dSspeer 
21144961713Sgirish 	if (istatus & ICFG_ZCP_TT_INDEX_ERR) {
21244961713Sgirish 		statsp->zcp_tt_index_err++;
21344961713Sgirish 		NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
214a3c5bd6dSspeer 			NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR);
21544961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21644961713Sgirish 			"nxge_zcp_err_evnts: tt_index_err"));
21744961713Sgirish 	}
218a3c5bd6dSspeer 
21944961713Sgirish 	if (((portn == 0) && (istatus & ICFG_ZCP_CFIFO_ECC0)) ||
220a3c5bd6dSspeer 			((portn == 1) && (istatus & ICFG_ZCP_CFIFO_ECC1)) ||
221a3c5bd6dSspeer 			((portn == 2) && (istatus & ICFG_ZCP_CFIFO_ECC2)) ||
222a3c5bd6dSspeer 			((portn == 3) && (istatus & ICFG_ZCP_CFIFO_ECC3))) {
22314ea4bb7Ssd 		boolean_t ue_ecc_valid;
22414ea4bb7Ssd 
22514ea4bb7Ssd 		if ((status = nxge_ipp_eccue_valid_check(nxgep,
226a3c5bd6dSspeer 				&ue_ecc_valid)) != NXGE_OK)
22714ea4bb7Ssd 			return (status);
22814ea4bb7Ssd 
22914ea4bb7Ssd 		if (ue_ecc_valid) {
23014ea4bb7Ssd 			statsp->cfifo_ecc++;
23114ea4bb7Ssd 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
232a3c5bd6dSspeer 				NXGE_FM_EREPORT_ZCP_CFIFO_ECC);
23314ea4bb7Ssd 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
234a3c5bd6dSspeer 				"nxge_zcp_err_evnts: port%d buf_cfifo_ecc",
235a3c5bd6dSspeer 				portn));
23614ea4bb7Ssd 			rxport_fatal = B_TRUE;
23714ea4bb7Ssd 		}
23844961713Sgirish 	}
23944961713Sgirish 
24044961713Sgirish 	/*
241a3c5bd6dSspeer 	 * Making sure that error source is cleared if this is an injected
242a3c5bd6dSspeer 	 * error.
24344961713Sgirish 	 */
24444961713Sgirish 	switch (portn) {
24544961713Sgirish 	case 0:
24644961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
24744961713Sgirish 		break;
24844961713Sgirish 	case 1:
24944961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
25044961713Sgirish 		break;
25144961713Sgirish 	case 2:
25244961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
25344961713Sgirish 		break;
25444961713Sgirish 	case 3:
25544961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
25644961713Sgirish 		break;
25744961713Sgirish 	}
25844961713Sgirish 
25944961713Sgirish 	(void) npi_zcp_clear_istatus(handle);
26044961713Sgirish 
26144961713Sgirish 	if (rxport_fatal) {
26244961713Sgirish 		NXGE_DEBUG_MSG((nxgep, IPP_CTL,
263a3c5bd6dSspeer 			" nxge_zcp_handle_sys_errors:"
264a3c5bd6dSspeer 			" fatal Error on  Port #%d\n", portn));
26544961713Sgirish 		status = nxge_zcp_fatal_err_recover(nxgep);
26644961713Sgirish 		if (status == NXGE_OK) {
26744961713Sgirish 			FM_SERVICE_RESTORED(nxgep);
26844961713Sgirish 		}
26944961713Sgirish 	}
27044961713Sgirish 	return (status);
27144961713Sgirish }
27244961713Sgirish 
27344961713Sgirish void
27444961713Sgirish nxge_zcp_inject_err(p_nxge_t nxgep, uint32_t err_id)
27544961713Sgirish {
276a3c5bd6dSspeer 	zcp_int_stat_reg_t zcps;
277a3c5bd6dSspeer 	uint8_t portn = nxgep->mac.portnum;
278a3c5bd6dSspeer 	zcp_ecc_ctrl_t ecc_ctrl;
27944961713Sgirish 
28044961713Sgirish 	switch (err_id) {
28144961713Sgirish 	case NXGE_FM_EREPORT_ZCP_CFIFO_ECC:
28244961713Sgirish 		ecc_ctrl.value = 0;
28344961713Sgirish 		ecc_ctrl.bits.w0.cor_dbl = 1;
28444961713Sgirish 		ecc_ctrl.bits.w0.cor_lst = 1;
28544961713Sgirish 		ecc_ctrl.bits.w0.cor_all = 0;
28644961713Sgirish 		switch (portn) {
28744961713Sgirish 		case 0:
28844961713Sgirish 			cmn_err(CE_NOTE,
28944961713Sgirish 				"!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
290a3c5bd6dSspeer 				(unsigned long long) ecc_ctrl.value, portn);
29144961713Sgirish 			NXGE_REG_WR64(nxgep->npi_handle,
292a3c5bd6dSspeer 				ZCP_CFIFO_ECC_PORT0_REG,
293a3c5bd6dSspeer 				ecc_ctrl.value);
29444961713Sgirish 			break;
29544961713Sgirish 		case 1:
29644961713Sgirish 			cmn_err(CE_NOTE,
29744961713Sgirish 				"!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
298a3c5bd6dSspeer 				(unsigned long long) ecc_ctrl.value, portn);
29944961713Sgirish 			NXGE_REG_WR64(nxgep->npi_handle,
300a3c5bd6dSspeer 				ZCP_CFIFO_ECC_PORT1_REG,
301a3c5bd6dSspeer 				ecc_ctrl.value);
30244961713Sgirish 			break;
30344961713Sgirish 		case 2:
30444961713Sgirish 			cmn_err(CE_NOTE,
30544961713Sgirish 				"!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
306a3c5bd6dSspeer 				(unsigned long long) ecc_ctrl.value, portn);
30744961713Sgirish 			NXGE_REG_WR64(nxgep->npi_handle,
308a3c5bd6dSspeer 				ZCP_CFIFO_ECC_PORT2_REG,
309a3c5bd6dSspeer 				ecc_ctrl.value);
31044961713Sgirish 			break;
31144961713Sgirish 		case 3:
31244961713Sgirish 			cmn_err(CE_NOTE,
31344961713Sgirish 				"!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
314a3c5bd6dSspeer 				(unsigned long long) ecc_ctrl.value, portn);
31544961713Sgirish 			NXGE_REG_WR64(nxgep->npi_handle,
316a3c5bd6dSspeer 				ZCP_CFIFO_ECC_PORT3_REG,
317a3c5bd6dSspeer 				ecc_ctrl.value);
31844961713Sgirish 			break;
31944961713Sgirish 		}
32044961713Sgirish 		break;
321a3c5bd6dSspeer 
32244961713Sgirish 	case NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN:
32344961713Sgirish 	case NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR:
32444961713Sgirish 	case NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR:
32544961713Sgirish 	case NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR:
32644961713Sgirish 	case NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR:
32744961713Sgirish 	case NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN:
32844961713Sgirish 	case NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW:
32944961713Sgirish 	case NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR:
33044961713Sgirish 	case NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR:
33144961713Sgirish 	case NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR:
33244961713Sgirish 	case NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR:
33344961713Sgirish 		NXGE_REG_RD64(nxgep->npi_handle, ZCP_INT_STAT_TEST_REG,
334a3c5bd6dSspeer 			&zcps.value);
33544961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN)
33644961713Sgirish 			zcps.bits.ldw.rrfifo_urun = 1;
33744961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR)
33844961713Sgirish 			zcps.bits.ldw.rspfifo_uc_err = 1;
33944961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR)
34044961713Sgirish 			zcps.bits.ldw.stat_tbl_perr = 1;
34144961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR)
34244961713Sgirish 			zcps.bits.ldw.dyn_tbl_perr = 1;
34344961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR)
34444961713Sgirish 			zcps.bits.ldw.buf_tbl_perr = 1;
34544961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_CFIFO_ECC) {
34644961713Sgirish 			switch (portn) {
34744961713Sgirish 			case 0:
34844961713Sgirish 				zcps.bits.ldw.cfifo_ecc0 = 1;
34944961713Sgirish 				break;
35044961713Sgirish 			case 1:
35144961713Sgirish 				zcps.bits.ldw.cfifo_ecc1 = 1;
35244961713Sgirish 				break;
35344961713Sgirish 			case 2:
35444961713Sgirish 				zcps.bits.ldw.cfifo_ecc2 = 1;
35544961713Sgirish 				break;
35644961713Sgirish 			case 3:
35744961713Sgirish 				zcps.bits.ldw.cfifo_ecc3 = 1;
35844961713Sgirish 				break;
35944961713Sgirish 			}
36044961713Sgirish 		}
361a3c5bd6dSspeer 
362a3c5bd6dSspeer 	default:
36344961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN)
36444961713Sgirish 			zcps.bits.ldw.rrfifo_orun = 1;
36544961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW)
36644961713Sgirish 			zcps.bits.ldw.buf_overflow = 1;
36744961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR)
36844961713Sgirish 			zcps.bits.ldw.tt_tbl_perr = 1;
36944961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR)
37044961713Sgirish 			zcps.bits.ldw.rsp_tt_index_err = 1;
37144961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR)
37244961713Sgirish 			zcps.bits.ldw.slv_tt_index_err = 1;
37344961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR)
37444961713Sgirish 			zcps.bits.ldw.zcp_tt_index_err = 1;
37544961713Sgirish 		cmn_err(CE_NOTE, "!Write 0x%lx to ZCP_INT_STAT_TEST_REG\n",
376a3c5bd6dSspeer 			zcps.value);
37744961713Sgirish 		NXGE_REG_WR64(nxgep->npi_handle, ZCP_INT_STAT_TEST_REG,
378a3c5bd6dSspeer 			zcps.value);
37944961713Sgirish 		break;
38044961713Sgirish 	}
38144961713Sgirish }
38244961713Sgirish 
38344961713Sgirish nxge_status_t
38444961713Sgirish nxge_zcp_fatal_err_recover(p_nxge_t nxgep)
38544961713Sgirish {
386a3c5bd6dSspeer 	npi_handle_t handle;
387a3c5bd6dSspeer 	npi_status_t rs = NPI_SUCCESS;
388a3c5bd6dSspeer 	nxge_status_t status = NXGE_OK;
389a3c5bd6dSspeer 	uint8_t portn;
390a3c5bd6dSspeer 	zcp_ram_unit_t w_data;
391a3c5bd6dSspeer 	zcp_ram_unit_t r_data;
392a3c5bd6dSspeer 	uint32_t cfifo_depth;
393a3c5bd6dSspeer 	int i;
39444961713Sgirish 
39544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_zcp_fatal_err_recover"));
39644961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
397a3c5bd6dSspeer 		"Recovering from RxPort error..."));
39844961713Sgirish 
39944961713Sgirish 	handle = nxgep->npi_handle;
40044961713Sgirish 	portn = nxgep->mac.portnum;
40144961713Sgirish 
40244961713Sgirish 	/* Disable RxMAC */
40344961713Sgirish 	if (nxge_rx_mac_disable(nxgep) != NXGE_OK)
40444961713Sgirish 		goto fail;
40544961713Sgirish 
40644961713Sgirish 	/* Make sure source is clear if this is an injected error */
40744961713Sgirish 	switch (portn) {
40844961713Sgirish 	case 0:
40944961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
41044961713Sgirish 		break;
41144961713Sgirish 	case 1:
41244961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
41344961713Sgirish 		break;
41444961713Sgirish 	case 2:
41544961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
41644961713Sgirish 		break;
41744961713Sgirish 	case 3:
41844961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
41944961713Sgirish 		break;
42044961713Sgirish 	}
42144961713Sgirish 
42244961713Sgirish 	/* Clear up CFIFO */
42359ac0c16Sdavemq 	if (nxgep->niu_type == N2_NIU) {
42459ac0c16Sdavemq 		cfifo_depth = ZCP_NIU_CFIFO_DEPTH;
425*2e59129aSraghus 	} else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
42644961713Sgirish 		if (portn < 2)
42744961713Sgirish 			cfifo_depth = ZCP_P0_P1_CFIFO_DEPTH;
42844961713Sgirish 		else
42944961713Sgirish 			cfifo_depth = ZCP_P2_P3_CFIFO_DEPTH;
43059ac0c16Sdavemq 	} else {
43159ac0c16Sdavemq 		goto fail;
43259ac0c16Sdavemq 	}
433a3c5bd6dSspeer 
43444961713Sgirish 	w_data.w0 = 0;
43544961713Sgirish 	w_data.w1 = 0;
43644961713Sgirish 	w_data.w2 = 0;
43744961713Sgirish 	w_data.w3 = 0;
43844961713Sgirish 	w_data.w4 = 0;
439a3c5bd6dSspeer 
44044961713Sgirish 	for (i = 0; i < cfifo_depth; i++) {
441a3c5bd6dSspeer 		if (npi_zcp_tt_cfifo_entry(handle, OP_SET,
442a3c5bd6dSspeer 				portn, i, &w_data) != NPI_SUCCESS)
44344961713Sgirish 			goto fail;
444a3c5bd6dSspeer 		if (npi_zcp_tt_cfifo_entry(handle, OP_GET,
445a3c5bd6dSspeer 				portn, i, &r_data) != NPI_SUCCESS)
44644961713Sgirish 			goto fail;
44744961713Sgirish 	}
44844961713Sgirish 
44944961713Sgirish 	/* When recovering from ZCP, RxDMA channel resets are not necessary */
45044961713Sgirish 	/* Reset ZCP CFIFO */
45144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset ZCP CFIFO...", portn));
45244961713Sgirish 	if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS)
45344961713Sgirish 		goto fail;
45444961713Sgirish 
45544961713Sgirish 	/* Reset IPP */
45644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset IPP...", portn));
45744961713Sgirish 	if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS)
45844961713Sgirish 		goto fail;
45944961713Sgirish 
46044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset RxMAC...", portn));
46144961713Sgirish 	if (nxge_rx_mac_reset(nxgep) != NXGE_OK)
46244961713Sgirish 		goto fail;
46344961713Sgirish 
46444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Initialize RxMAC...", portn));
46544961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
46644961713Sgirish 		goto fail;
46744961713Sgirish 
46844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Enable RxMAC...", portn));
46944961713Sgirish 	if (nxge_rx_mac_enable(nxgep) != NXGE_OK)
47044961713Sgirish 		goto fail;
47144961713Sgirish 
47244961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
473a3c5bd6dSspeer 		"Recovery Sucessful, RxPort Restored"));
47444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_zcp_fatal_err_recover"));
47544961713Sgirish 	return (NXGE_OK);
47644961713Sgirish fail:
47744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed"));
47844961713Sgirish 	return (status | rs);
47944961713Sgirish }
480