xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_zcp.c (revision 52ccf843)
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 /*
22*52ccf843Smisaki  * 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_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;
492e59129aSraghus 	} 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,
67*52ccf843Smisaki 		    portn, i, &w_data) != NPI_SUCCESS)
6844961713Sgirish 			goto fail;
69a3c5bd6dSspeer 		if (npi_zcp_tt_cfifo_entry(handle, OP_GET,
70*52ccf843Smisaki 		    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,
108*52ccf843Smisaki 	    "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,
133*52ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN);
13444961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
135*52ccf843Smisaki 		    "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,
141*52ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN);
14244961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
143*52ccf843Smisaki 		    "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,
149*52ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR);
15044961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
151*52ccf843Smisaki 		    "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,
157*52ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW);
15844961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
159*52ccf843Smisaki 		    "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,
166*52ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR);
16744961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
168*52ccf843Smisaki 		    "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,
174*52ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR);
17544961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
176*52ccf843Smisaki 		    "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,
182*52ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR);
18344961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
184*52ccf843Smisaki 		    "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,
190*52ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR);
19144961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
192*52ccf843Smisaki 		    "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,
198*52ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR);
19944961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
200*52ccf843Smisaki 		    "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,
206*52ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR);
20744961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
208*52ccf843Smisaki 		    "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,
214*52ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR);
21544961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
216*52ccf843Smisaki 		    "nxge_zcp_err_evnts: tt_index_err"));
21744961713Sgirish 	}
218a3c5bd6dSspeer 
21944961713Sgirish 	if (((portn == 0) && (istatus & ICFG_ZCP_CFIFO_ECC0)) ||
220*52ccf843Smisaki 	    ((portn == 1) && (istatus & ICFG_ZCP_CFIFO_ECC1)) ||
221*52ccf843Smisaki 	    ((portn == 2) && (istatus & ICFG_ZCP_CFIFO_ECC2)) ||
222*52ccf843Smisaki 	    ((portn == 3) && (istatus & ICFG_ZCP_CFIFO_ECC3))) {
22314ea4bb7Ssd 		boolean_t ue_ecc_valid;
22414ea4bb7Ssd 
22514ea4bb7Ssd 		if ((status = nxge_ipp_eccue_valid_check(nxgep,
226*52ccf843Smisaki 		    &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,
232*52ccf843Smisaki 			    NXGE_FM_EREPORT_ZCP_CFIFO_ECC);
23314ea4bb7Ssd 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
234*52ccf843Smisaki 			    "nxge_zcp_err_evnts: port%d buf_cfifo_ecc",
235*52ccf843Smisaki 			    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,
263*52ccf843Smisaki 		    " nxge_zcp_handle_sys_errors:"
264*52ccf843Smisaki 		    " 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,
289*52ccf843Smisaki 			    "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
290*52ccf843Smisaki 			    (unsigned long long) ecc_ctrl.value, portn);
29144961713Sgirish 			NXGE_REG_WR64(nxgep->npi_handle,
292*52ccf843Smisaki 			    ZCP_CFIFO_ECC_PORT0_REG,
293*52ccf843Smisaki 			    ecc_ctrl.value);
29444961713Sgirish 			break;
29544961713Sgirish 		case 1:
29644961713Sgirish 			cmn_err(CE_NOTE,
297*52ccf843Smisaki 			    "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
298*52ccf843Smisaki 			    (unsigned long long) ecc_ctrl.value, portn);
29944961713Sgirish 			NXGE_REG_WR64(nxgep->npi_handle,
300*52ccf843Smisaki 			    ZCP_CFIFO_ECC_PORT1_REG,
301*52ccf843Smisaki 			    ecc_ctrl.value);
30244961713Sgirish 			break;
30344961713Sgirish 		case 2:
30444961713Sgirish 			cmn_err(CE_NOTE,
305*52ccf843Smisaki 			    "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
306*52ccf843Smisaki 			    (unsigned long long) ecc_ctrl.value, portn);
30744961713Sgirish 			NXGE_REG_WR64(nxgep->npi_handle,
308*52ccf843Smisaki 			    ZCP_CFIFO_ECC_PORT2_REG,
309*52ccf843Smisaki 			    ecc_ctrl.value);
31044961713Sgirish 			break;
31144961713Sgirish 		case 3:
31244961713Sgirish 			cmn_err(CE_NOTE,
313*52ccf843Smisaki 			    "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
314*52ccf843Smisaki 			    (unsigned long long) ecc_ctrl.value, portn);
31544961713Sgirish 			NXGE_REG_WR64(nxgep->npi_handle,
316*52ccf843Smisaki 			    ZCP_CFIFO_ECC_PORT3_REG,
317*52ccf843Smisaki 			    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,
334*52ccf843Smisaki 		    &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;
375adfcba55Sjoycey #if defined(__i386)
376adfcba55Sjoycey 		cmn_err(CE_NOTE, "!Write 0x%llx to ZCP_INT_STAT_TEST_REG\n",
377*52ccf843Smisaki 		    zcps.value);
378adfcba55Sjoycey #else
37944961713Sgirish 		cmn_err(CE_NOTE, "!Write 0x%lx to ZCP_INT_STAT_TEST_REG\n",
380*52ccf843Smisaki 		    zcps.value);
381adfcba55Sjoycey #endif
38244961713Sgirish 		NXGE_REG_WR64(nxgep->npi_handle, ZCP_INT_STAT_TEST_REG,
383*52ccf843Smisaki 		    zcps.value);
38444961713Sgirish 		break;
38544961713Sgirish 	}
38644961713Sgirish }
38744961713Sgirish 
38844961713Sgirish nxge_status_t
38944961713Sgirish nxge_zcp_fatal_err_recover(p_nxge_t nxgep)
39044961713Sgirish {
391a3c5bd6dSspeer 	npi_handle_t handle;
392a3c5bd6dSspeer 	npi_status_t rs = NPI_SUCCESS;
393a3c5bd6dSspeer 	nxge_status_t status = NXGE_OK;
394a3c5bd6dSspeer 	uint8_t portn;
395a3c5bd6dSspeer 	zcp_ram_unit_t w_data;
396a3c5bd6dSspeer 	zcp_ram_unit_t r_data;
397a3c5bd6dSspeer 	uint32_t cfifo_depth;
398a3c5bd6dSspeer 	int i;
39944961713Sgirish 
40044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_zcp_fatal_err_recover"));
40144961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
402*52ccf843Smisaki 	    "Recovering from RxPort error..."));
40344961713Sgirish 
40444961713Sgirish 	handle = nxgep->npi_handle;
40544961713Sgirish 	portn = nxgep->mac.portnum;
40644961713Sgirish 
40744961713Sgirish 	/* Disable RxMAC */
40844961713Sgirish 	if (nxge_rx_mac_disable(nxgep) != NXGE_OK)
40944961713Sgirish 		goto fail;
41044961713Sgirish 
41144961713Sgirish 	/* Make sure source is clear if this is an injected error */
41244961713Sgirish 	switch (portn) {
41344961713Sgirish 	case 0:
41444961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
41544961713Sgirish 		break;
41644961713Sgirish 	case 1:
41744961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
41844961713Sgirish 		break;
41944961713Sgirish 	case 2:
42044961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
42144961713Sgirish 		break;
42244961713Sgirish 	case 3:
42344961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
42444961713Sgirish 		break;
42544961713Sgirish 	}
42644961713Sgirish 
42744961713Sgirish 	/* 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)) {
43144961713Sgirish 		if (portn < 2)
43244961713Sgirish 			cfifo_depth = ZCP_P0_P1_CFIFO_DEPTH;
43344961713Sgirish 		else
43444961713Sgirish 			cfifo_depth = ZCP_P2_P3_CFIFO_DEPTH;
43559ac0c16Sdavemq 	} else {
43659ac0c16Sdavemq 		goto fail;
43759ac0c16Sdavemq 	}
438a3c5bd6dSspeer 
43944961713Sgirish 	w_data.w0 = 0;
44044961713Sgirish 	w_data.w1 = 0;
44144961713Sgirish 	w_data.w2 = 0;
44244961713Sgirish 	w_data.w3 = 0;
44344961713Sgirish 	w_data.w4 = 0;
444a3c5bd6dSspeer 
44544961713Sgirish 	for (i = 0; i < cfifo_depth; i++) {
446a3c5bd6dSspeer 		if (npi_zcp_tt_cfifo_entry(handle, OP_SET,
447*52ccf843Smisaki 		    portn, i, &w_data) != NPI_SUCCESS)
44844961713Sgirish 			goto fail;
449a3c5bd6dSspeer 		if (npi_zcp_tt_cfifo_entry(handle, OP_GET,
450*52ccf843Smisaki 		    portn, i, &r_data) != NPI_SUCCESS)
45144961713Sgirish 			goto fail;
45244961713Sgirish 	}
45344961713Sgirish 
45444961713Sgirish 	/* When recovering from ZCP, RxDMA channel resets are not necessary */
45544961713Sgirish 	/* Reset ZCP CFIFO */
45644961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset ZCP CFIFO...", portn));
45744961713Sgirish 	if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS)
45844961713Sgirish 		goto fail;
45944961713Sgirish 
46044961713Sgirish 	/* Reset IPP */
46144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset IPP...", portn));
46244961713Sgirish 	if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS)
46344961713Sgirish 		goto fail;
46444961713Sgirish 
46544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset RxMAC...", portn));
46644961713Sgirish 	if (nxge_rx_mac_reset(nxgep) != NXGE_OK)
46744961713Sgirish 		goto fail;
46844961713Sgirish 
46944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Initialize RxMAC...", portn));
47044961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
47144961713Sgirish 		goto fail;
47244961713Sgirish 
47344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Enable RxMAC...", portn));
47444961713Sgirish 	if (nxge_rx_mac_enable(nxgep) != NXGE_OK)
47544961713Sgirish 		goto fail;
47644961713Sgirish 
47744961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
478*52ccf843Smisaki 	    "Recovery Sucessful, RxPort Restored"));
47944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_zcp_fatal_err_recover"));
48044961713Sgirish 	return (NXGE_OK);
48144961713Sgirish fail:
48244961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed"));
48344961713Sgirish 	return (status | rs);
48444961713Sgirish }
485