xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_zcp.c (revision 86ef0a63)
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 /*
2252ccf843Smisaki  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2344961713Sgirish  * Use is subject to license terms.
2444961713Sgirish  */
2544961713Sgirish 
2644961713Sgirish #include <nxge_impl.h>
2744961713Sgirish #include <nxge_zcp.h>
2814ea4bb7Ssd #include <nxge_ipp.h>
2914ea4bb7Ssd 
3044961713Sgirish nxge_status_t
nxge_zcp_init(p_nxge_t nxgep)3144961713Sgirish nxge_zcp_init(p_nxge_t nxgep)
3244961713Sgirish {
33a3c5bd6dSspeer 	uint8_t portn;
34a3c5bd6dSspeer 	npi_handle_t handle;
35a3c5bd6dSspeer 	zcp_iconfig_t istatus;
36a3c5bd6dSspeer 	npi_status_t rs = NPI_SUCCESS;
37a3c5bd6dSspeer 	int i;
38a3c5bd6dSspeer 	zcp_ram_unit_t w_data;
39a3c5bd6dSspeer 	zcp_ram_unit_t r_data;
40a3c5bd6dSspeer 	uint32_t cfifo_depth;
4144961713Sgirish 
4244961713Sgirish 	handle = nxgep->npi_handle;
4344961713Sgirish 	portn = NXGE_GET_PORT_NUM(nxgep->function_num);
4444961713Sgirish 
4559ac0c16Sdavemq 	if (nxgep->niu_type == N2_NIU) {
4659ac0c16Sdavemq 		cfifo_depth = ZCP_NIU_CFIFO_DEPTH;
472e59129aSraghus 	} else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
4844961713Sgirish 		if (portn < 2)
4944961713Sgirish 			cfifo_depth = ZCP_P0_P1_CFIFO_DEPTH;
5044961713Sgirish 		else
5144961713Sgirish 			cfifo_depth = ZCP_P2_P3_CFIFO_DEPTH;
5259ac0c16Sdavemq 	} else {
5359ac0c16Sdavemq 		goto fail;
5459ac0c16Sdavemq 	}
5544961713Sgirish 
5644961713Sgirish 	/* Clean up CFIFO */
5744961713Sgirish 	w_data.w0 = 0;
5844961713Sgirish 	w_data.w1 = 0;
5944961713Sgirish 	w_data.w2 = 0;
6044961713Sgirish 	w_data.w3 = 0;
6144961713Sgirish 	w_data.w4 = 0;
62a3c5bd6dSspeer 
6344961713Sgirish 	for (i = 0; i < cfifo_depth; i++) {
64a3c5bd6dSspeer 		if (npi_zcp_tt_cfifo_entry(handle, OP_SET,
6552ccf843Smisaki 		    portn, i, &w_data) != NPI_SUCCESS)
6644961713Sgirish 			goto fail;
67a3c5bd6dSspeer 		if (npi_zcp_tt_cfifo_entry(handle, OP_GET,
6852ccf843Smisaki 		    portn, i, &r_data) != NPI_SUCCESS)
6944961713Sgirish 			goto fail;
7044961713Sgirish 	}
7144961713Sgirish 
7244961713Sgirish 	if (npi_zcp_rest_cfifo_port(handle, portn) != NPI_SUCCESS)
73a3c5bd6dSspeer 		goto fail;
74a3c5bd6dSspeer 
7544961713Sgirish 	/*
76a3c5bd6dSspeer 	 * Making sure that error source is cleared if this is an injected
77a3c5bd6dSspeer 	 * error.
7844961713Sgirish 	 */
7944961713Sgirish 	switch (portn) {
8044961713Sgirish 	case 0:
8144961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
8244961713Sgirish 		break;
8344961713Sgirish 	case 1:
8444961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
8544961713Sgirish 		break;
8644961713Sgirish 	case 2:
8744961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
8844961713Sgirish 		break;
8944961713Sgirish 	case 3:
9044961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
9144961713Sgirish 		break;
9244961713Sgirish 	}
9344961713Sgirish 
9414ea4bb7Ssd 	if ((rs = npi_zcp_clear_istatus(handle)) != NPI_SUCCESS)
9514ea4bb7Ssd 		return (NXGE_ERROR | rs);
9644961713Sgirish 	if ((rs = npi_zcp_get_istatus(handle, &istatus)) != NPI_SUCCESS)
9744961713Sgirish 		return (NXGE_ERROR | rs);
9844961713Sgirish 	if ((rs = npi_zcp_iconfig(handle, INIT, ICFG_ZCP_ALL)) != NPI_SUCCESS)
9944961713Sgirish 		goto fail;
10044961713Sgirish 
10144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_zcp_init: port%d", portn));
10244961713Sgirish 	return (NXGE_OK);
10344961713Sgirish 
10444961713Sgirish fail:
10544961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
10652ccf843Smisaki 	    "nxge_zcp_init: Fail to initialize ZCP Port #%d\n", portn));
10744961713Sgirish 	return (NXGE_ERROR | rs);
10844961713Sgirish }
10944961713Sgirish 
11044961713Sgirish nxge_status_t
nxge_zcp_handle_sys_errors(p_nxge_t nxgep)11144961713Sgirish nxge_zcp_handle_sys_errors(p_nxge_t nxgep)
11244961713Sgirish {
113a3c5bd6dSspeer 	npi_handle_t handle;
114a3c5bd6dSspeer 	npi_status_t rs = NPI_SUCCESS;
115a3c5bd6dSspeer 	p_nxge_zcp_stats_t statsp;
116a3c5bd6dSspeer 	uint8_t portn;
117a3c5bd6dSspeer 	zcp_iconfig_t istatus;
118a3c5bd6dSspeer 	boolean_t rxport_fatal = B_FALSE;
119a3c5bd6dSspeer 	nxge_status_t status = NXGE_OK;
12044961713Sgirish 
12144961713Sgirish 	handle = nxgep->npi_handle;
12244961713Sgirish 	statsp = (p_nxge_zcp_stats_t)&nxgep->statsp->zcp_stats;
12344961713Sgirish 	portn = nxgep->mac.portnum;
12444961713Sgirish 
12544961713Sgirish 	if ((rs = npi_zcp_get_istatus(handle, &istatus)) != NPI_SUCCESS)
12644961713Sgirish 		return (NXGE_ERROR | rs);
12744961713Sgirish 
12844961713Sgirish 	if (istatus & ICFG_ZCP_RRFIFO_UNDERRUN) {
12944961713Sgirish 		statsp->rrfifo_underrun++;
130*b37cc459SToomas Soome 		NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
13152ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN);
13244961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
13352ccf843Smisaki 		    "nxge_zcp_err_evnts: rrfifo_underrun"));
13444961713Sgirish 	}
135a3c5bd6dSspeer 
13644961713Sgirish 	if (istatus & ICFG_ZCP_RRFIFO_OVERRUN) {
13744961713Sgirish 		statsp->rrfifo_overrun++;
138*b37cc459SToomas Soome 		NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
13952ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN);
14044961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
14152ccf843Smisaki 		    "nxge_zcp_err_evnts: buf_rrfifo_overrun"));
14244961713Sgirish 	}
143a3c5bd6dSspeer 
14444961713Sgirish 	if (istatus & ICFG_ZCP_RSPFIFO_UNCORR_ERR) {
14544961713Sgirish 		statsp->rspfifo_uncorr_err++;
146*b37cc459SToomas Soome 		NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
14752ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR);
14844961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
14952ccf843Smisaki 		    "nxge_zcp_err_evnts: rspfifo_uncorr_err"));
15044961713Sgirish 	}
151a3c5bd6dSspeer 
15244961713Sgirish 	if (istatus & ICFG_ZCP_BUFFER_OVERFLOW) {
15344961713Sgirish 		statsp->buffer_overflow++;
154*b37cc459SToomas Soome 		NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
15552ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW);
15644961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15752ccf843Smisaki 		    "nxge_zcp_err_evnts: buffer_overflow"));
15844961713Sgirish 		rxport_fatal = B_TRUE;
15944961713Sgirish 	}
160a3c5bd6dSspeer 
16144961713Sgirish 	if (istatus & ICFG_ZCP_STAT_TBL_PERR) {
16244961713Sgirish 		statsp->stat_tbl_perr++;
163*b37cc459SToomas Soome 		NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
16452ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR);
16544961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
16652ccf843Smisaki 		    "nxge_zcp_err_evnts: stat_tbl_perr"));
16744961713Sgirish 	}
168a3c5bd6dSspeer 
16944961713Sgirish 	if (istatus & ICFG_ZCP_DYN_TBL_PERR) {
17044961713Sgirish 		statsp->dyn_tbl_perr++;
171*b37cc459SToomas Soome 		NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
17252ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR);
17344961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
17452ccf843Smisaki 		    "nxge_zcp_err_evnts: dyn_tbl_perr"));
17544961713Sgirish 	}
176a3c5bd6dSspeer 
17744961713Sgirish 	if (istatus & ICFG_ZCP_BUF_TBL_PERR) {
17844961713Sgirish 		statsp->buf_tbl_perr++;
179*b37cc459SToomas Soome 		NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
18052ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR);
18144961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
18252ccf843Smisaki 		    "nxge_zcp_err_evnts: buf_tbl_perr"));
18344961713Sgirish 	}
184a3c5bd6dSspeer 
18544961713Sgirish 	if (istatus & ICFG_ZCP_TT_PROGRAM_ERR) {
18644961713Sgirish 		statsp->tt_program_err++;
187*b37cc459SToomas Soome 		NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
18852ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR);
18944961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
19052ccf843Smisaki 		    "nxge_zcp_err_evnts: tt_program_err"));
19144961713Sgirish 	}
192a3c5bd6dSspeer 
19344961713Sgirish 	if (istatus & ICFG_ZCP_RSP_TT_INDEX_ERR) {
19444961713Sgirish 		statsp->rsp_tt_index_err++;
195*b37cc459SToomas Soome 		NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
19652ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR);
19744961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
19852ccf843Smisaki 		    "nxge_zcp_err_evnts: rsp_tt_index_err"));
19944961713Sgirish 	}
200a3c5bd6dSspeer 
20144961713Sgirish 	if (istatus & ICFG_ZCP_SLV_TT_INDEX_ERR) {
20244961713Sgirish 		statsp->slv_tt_index_err++;
203*b37cc459SToomas Soome 		NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
20452ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR);
20544961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
20652ccf843Smisaki 		    "nxge_zcp_err_evnts: slv_tt_index_err"));
20744961713Sgirish 	}
208a3c5bd6dSspeer 
20944961713Sgirish 	if (istatus & ICFG_ZCP_TT_INDEX_ERR) {
21044961713Sgirish 		statsp->zcp_tt_index_err++;
211*b37cc459SToomas Soome 		NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
21252ccf843Smisaki 		    NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR);
21344961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21452ccf843Smisaki 		    "nxge_zcp_err_evnts: tt_index_err"));
21544961713Sgirish 	}
216a3c5bd6dSspeer 
21744961713Sgirish 	if (((portn == 0) && (istatus & ICFG_ZCP_CFIFO_ECC0)) ||
21852ccf843Smisaki 	    ((portn == 1) && (istatus & ICFG_ZCP_CFIFO_ECC1)) ||
21952ccf843Smisaki 	    ((portn == 2) && (istatus & ICFG_ZCP_CFIFO_ECC2)) ||
22052ccf843Smisaki 	    ((portn == 3) && (istatus & ICFG_ZCP_CFIFO_ECC3))) {
22114ea4bb7Ssd 		boolean_t ue_ecc_valid;
22214ea4bb7Ssd 
22314ea4bb7Ssd 		if ((status = nxge_ipp_eccue_valid_check(nxgep,
22452ccf843Smisaki 		    &ue_ecc_valid)) != NXGE_OK)
22514ea4bb7Ssd 			return (status);
22614ea4bb7Ssd 
22714ea4bb7Ssd 		if (ue_ecc_valid) {
22814ea4bb7Ssd 			statsp->cfifo_ecc++;
229*b37cc459SToomas Soome 			NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
23052ccf843Smisaki 			    NXGE_FM_EREPORT_ZCP_CFIFO_ECC);
23114ea4bb7Ssd 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
23252ccf843Smisaki 			    "nxge_zcp_err_evnts: port%d buf_cfifo_ecc",
23352ccf843Smisaki 			    portn));
23414ea4bb7Ssd 			rxport_fatal = B_TRUE;
23514ea4bb7Ssd 		}
23644961713Sgirish 	}
23744961713Sgirish 
23844961713Sgirish 	/*
239a3c5bd6dSspeer 	 * Making sure that error source is cleared if this is an injected
240a3c5bd6dSspeer 	 * error.
24144961713Sgirish 	 */
24244961713Sgirish 	switch (portn) {
24344961713Sgirish 	case 0:
24444961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
24544961713Sgirish 		break;
24644961713Sgirish 	case 1:
24744961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
24844961713Sgirish 		break;
24944961713Sgirish 	case 2:
25044961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
25144961713Sgirish 		break;
25244961713Sgirish 	case 3:
25344961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
25444961713Sgirish 		break;
25544961713Sgirish 	}
25644961713Sgirish 
25744961713Sgirish 	(void) npi_zcp_clear_istatus(handle);
25844961713Sgirish 
25944961713Sgirish 	if (rxport_fatal) {
26044961713Sgirish 		NXGE_DEBUG_MSG((nxgep, IPP_CTL,
26152ccf843Smisaki 		    " nxge_zcp_handle_sys_errors:"
26252ccf843Smisaki 		    " fatal Error on  Port #%d\n", portn));
26344961713Sgirish 		status = nxge_zcp_fatal_err_recover(nxgep);
26444961713Sgirish 		if (status == NXGE_OK) {
26544961713Sgirish 			FM_SERVICE_RESTORED(nxgep);
26644961713Sgirish 		}
26744961713Sgirish 	}
26844961713Sgirish 	return (status);
26944961713Sgirish }
27044961713Sgirish 
27144961713Sgirish void
nxge_zcp_inject_err(p_nxge_t nxgep,uint32_t err_id)27244961713Sgirish nxge_zcp_inject_err(p_nxge_t nxgep, uint32_t err_id)
27344961713Sgirish {
274a3c5bd6dSspeer 	zcp_int_stat_reg_t zcps;
275a3c5bd6dSspeer 	uint8_t portn = nxgep->mac.portnum;
276a3c5bd6dSspeer 	zcp_ecc_ctrl_t ecc_ctrl;
27744961713Sgirish 
27844961713Sgirish 	switch (err_id) {
27944961713Sgirish 	case NXGE_FM_EREPORT_ZCP_CFIFO_ECC:
28044961713Sgirish 		ecc_ctrl.value = 0;
28144961713Sgirish 		ecc_ctrl.bits.w0.cor_dbl = 1;
28244961713Sgirish 		ecc_ctrl.bits.w0.cor_lst = 1;
28344961713Sgirish 		ecc_ctrl.bits.w0.cor_all = 0;
28444961713Sgirish 		switch (portn) {
28544961713Sgirish 		case 0:
28644961713Sgirish 			cmn_err(CE_NOTE,
28752ccf843Smisaki 			    "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
28852ccf843Smisaki 			    (unsigned long long) ecc_ctrl.value, portn);
28944961713Sgirish 			NXGE_REG_WR64(nxgep->npi_handle,
29052ccf843Smisaki 			    ZCP_CFIFO_ECC_PORT0_REG,
29152ccf843Smisaki 			    ecc_ctrl.value);
29244961713Sgirish 			break;
29344961713Sgirish 		case 1:
29444961713Sgirish 			cmn_err(CE_NOTE,
29552ccf843Smisaki 			    "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
29652ccf843Smisaki 			    (unsigned long long) ecc_ctrl.value, portn);
29744961713Sgirish 			NXGE_REG_WR64(nxgep->npi_handle,
29852ccf843Smisaki 			    ZCP_CFIFO_ECC_PORT1_REG,
29952ccf843Smisaki 			    ecc_ctrl.value);
30044961713Sgirish 			break;
30144961713Sgirish 		case 2:
30244961713Sgirish 			cmn_err(CE_NOTE,
30352ccf843Smisaki 			    "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
30452ccf843Smisaki 			    (unsigned long long) ecc_ctrl.value, portn);
30544961713Sgirish 			NXGE_REG_WR64(nxgep->npi_handle,
30652ccf843Smisaki 			    ZCP_CFIFO_ECC_PORT2_REG,
30752ccf843Smisaki 			    ecc_ctrl.value);
30844961713Sgirish 			break;
30944961713Sgirish 		case 3:
31044961713Sgirish 			cmn_err(CE_NOTE,
31152ccf843Smisaki 			    "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
31252ccf843Smisaki 			    (unsigned long long) ecc_ctrl.value, portn);
31344961713Sgirish 			NXGE_REG_WR64(nxgep->npi_handle,
31452ccf843Smisaki 			    ZCP_CFIFO_ECC_PORT3_REG,
31552ccf843Smisaki 			    ecc_ctrl.value);
31644961713Sgirish 			break;
31744961713Sgirish 		}
31844961713Sgirish 		break;
319a3c5bd6dSspeer 
32044961713Sgirish 	case NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN:
32144961713Sgirish 	case NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR:
32244961713Sgirish 	case NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR:
32344961713Sgirish 	case NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR:
32444961713Sgirish 	case NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR:
32544961713Sgirish 	case NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN:
32644961713Sgirish 	case NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW:
32744961713Sgirish 	case NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR:
32844961713Sgirish 	case NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR:
32944961713Sgirish 	case NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR:
33044961713Sgirish 	case NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR:
33144961713Sgirish 		NXGE_REG_RD64(nxgep->npi_handle, ZCP_INT_STAT_TEST_REG,
33252ccf843Smisaki 		    &zcps.value);
33344961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN)
33444961713Sgirish 			zcps.bits.ldw.rrfifo_urun = 1;
33544961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR)
33644961713Sgirish 			zcps.bits.ldw.rspfifo_uc_err = 1;
33744961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR)
33844961713Sgirish 			zcps.bits.ldw.stat_tbl_perr = 1;
33944961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR)
34044961713Sgirish 			zcps.bits.ldw.dyn_tbl_perr = 1;
34144961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR)
34244961713Sgirish 			zcps.bits.ldw.buf_tbl_perr = 1;
34344961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_CFIFO_ECC) {
34444961713Sgirish 			switch (portn) {
34544961713Sgirish 			case 0:
34644961713Sgirish 				zcps.bits.ldw.cfifo_ecc0 = 1;
34744961713Sgirish 				break;
34844961713Sgirish 			case 1:
34944961713Sgirish 				zcps.bits.ldw.cfifo_ecc1 = 1;
35044961713Sgirish 				break;
35144961713Sgirish 			case 2:
35244961713Sgirish 				zcps.bits.ldw.cfifo_ecc2 = 1;
35344961713Sgirish 				break;
35444961713Sgirish 			case 3:
35544961713Sgirish 				zcps.bits.ldw.cfifo_ecc3 = 1;
35644961713Sgirish 				break;
35744961713Sgirish 			}
35844961713Sgirish 		}
35973ff8cc6SToomas Soome 		/* FALLTHROUGH */
360a3c5bd6dSspeer 
361a3c5bd6dSspeer 	default:
36244961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN)
36344961713Sgirish 			zcps.bits.ldw.rrfifo_orun = 1;
36444961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW)
36544961713Sgirish 			zcps.bits.ldw.buf_overflow = 1;
36644961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR)
36744961713Sgirish 			zcps.bits.ldw.tt_tbl_perr = 1;
36844961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR)
36944961713Sgirish 			zcps.bits.ldw.rsp_tt_index_err = 1;
37044961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR)
37144961713Sgirish 			zcps.bits.ldw.slv_tt_index_err = 1;
37244961713Sgirish 		if (err_id == NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR)
37344961713Sgirish 			zcps.bits.ldw.zcp_tt_index_err = 1;
37444961713Sgirish 		cmn_err(CE_NOTE, "!Write 0x%lx to ZCP_INT_STAT_TEST_REG\n",
37552ccf843Smisaki 		    zcps.value);
37644961713Sgirish 		NXGE_REG_WR64(nxgep->npi_handle, ZCP_INT_STAT_TEST_REG,
37752ccf843Smisaki 		    zcps.value);
37844961713Sgirish 		break;
37944961713Sgirish 	}
38044961713Sgirish }
38144961713Sgirish 
38244961713Sgirish nxge_status_t
nxge_zcp_fatal_err_recover(p_nxge_t nxgep)38344961713Sgirish nxge_zcp_fatal_err_recover(p_nxge_t nxgep)
38444961713Sgirish {
385a3c5bd6dSspeer 	npi_handle_t handle;
386a3c5bd6dSspeer 	npi_status_t rs = NPI_SUCCESS;
387a3c5bd6dSspeer 	nxge_status_t status = NXGE_OK;
388a3c5bd6dSspeer 	uint8_t portn;
389a3c5bd6dSspeer 	zcp_ram_unit_t w_data;
390a3c5bd6dSspeer 	zcp_ram_unit_t r_data;
391a3c5bd6dSspeer 	uint32_t cfifo_depth;
392a3c5bd6dSspeer 	int i;
39344961713Sgirish 
39444961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_zcp_fatal_err_recover"));
39544961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
39652ccf843Smisaki 	    "Recovering from RxPort error..."));
39744961713Sgirish 
39844961713Sgirish 	handle = nxgep->npi_handle;
39944961713Sgirish 	portn = nxgep->mac.portnum;
40044961713Sgirish 
40144961713Sgirish 	/* Disable RxMAC */
40244961713Sgirish 	if (nxge_rx_mac_disable(nxgep) != NXGE_OK)
40344961713Sgirish 		goto fail;
40444961713Sgirish 
40544961713Sgirish 	/* Make sure source is clear if this is an injected error */
40644961713Sgirish 	switch (portn) {
40744961713Sgirish 	case 0:
40844961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
40944961713Sgirish 		break;
41044961713Sgirish 	case 1:
41144961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
41244961713Sgirish 		break;
41344961713Sgirish 	case 2:
41444961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
41544961713Sgirish 		break;
41644961713Sgirish 	case 3:
41744961713Sgirish 		NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
41844961713Sgirish 		break;
41944961713Sgirish 	}
42044961713Sgirish 
42144961713Sgirish 	/* Clear up CFIFO */
42259ac0c16Sdavemq 	if (nxgep->niu_type == N2_NIU) {
42359ac0c16Sdavemq 		cfifo_depth = ZCP_NIU_CFIFO_DEPTH;
4242e59129aSraghus 	} else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
42544961713Sgirish 		if (portn < 2)
42644961713Sgirish 			cfifo_depth = ZCP_P0_P1_CFIFO_DEPTH;
42744961713Sgirish 		else
42844961713Sgirish 			cfifo_depth = ZCP_P2_P3_CFIFO_DEPTH;
42959ac0c16Sdavemq 	} else {
43059ac0c16Sdavemq 		goto fail;
43159ac0c16Sdavemq 	}
432a3c5bd6dSspeer 
43344961713Sgirish 	w_data.w0 = 0;
43444961713Sgirish 	w_data.w1 = 0;
43544961713Sgirish 	w_data.w2 = 0;
43644961713Sgirish 	w_data.w3 = 0;
43744961713Sgirish 	w_data.w4 = 0;
438a3c5bd6dSspeer 
43944961713Sgirish 	for (i = 0; i < cfifo_depth; i++) {
440a3c5bd6dSspeer 		if (npi_zcp_tt_cfifo_entry(handle, OP_SET,
44152ccf843Smisaki 		    portn, i, &w_data) != NPI_SUCCESS)
44244961713Sgirish 			goto fail;
443a3c5bd6dSspeer 		if (npi_zcp_tt_cfifo_entry(handle, OP_GET,
44452ccf843Smisaki 		    portn, i, &r_data) != NPI_SUCCESS)
44544961713Sgirish 			goto fail;
44644961713Sgirish 	}
44744961713Sgirish 
44844961713Sgirish 	/* When recovering from ZCP, RxDMA channel resets are not necessary */
44944961713Sgirish 	/* Reset ZCP CFIFO */
45044961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset ZCP CFIFO...", portn));
45144961713Sgirish 	if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS)
45244961713Sgirish 		goto fail;
45344961713Sgirish 
45444961713Sgirish 	/* Reset IPP */
45544961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset IPP...", portn));
45644961713Sgirish 	if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS)
45744961713Sgirish 		goto fail;
45844961713Sgirish 
45944961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset RxMAC...", portn));
46044961713Sgirish 	if (nxge_rx_mac_reset(nxgep) != NXGE_OK)
46144961713Sgirish 		goto fail;
46244961713Sgirish 
46344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Initialize RxMAC...", portn));
46444961713Sgirish 	if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
46544961713Sgirish 		goto fail;
46644961713Sgirish 
46744961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Enable RxMAC...", portn));
46844961713Sgirish 	if (nxge_rx_mac_enable(nxgep) != NXGE_OK)
46944961713Sgirish 		goto fail;
47044961713Sgirish 
47144961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
47252ccf843Smisaki 	    "Recovery Sucessful, RxPort Restored"));
47344961713Sgirish 	NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_zcp_fatal_err_recover"));
47444961713Sgirish 	return (NXGE_OK);
47544961713Sgirish fail:
47644961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed"));
47744961713Sgirish 	return (status | rs);
47844961713Sgirish }
479