13859Sml29623 /* 23859Sml29623 * CDDL HEADER START 33859Sml29623 * 43859Sml29623 * The contents of this file are subject to the terms of the 53859Sml29623 * Common Development and Distribution License (the "License"). 63859Sml29623 * You may not use this file except in compliance with the License. 73859Sml29623 * 83859Sml29623 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93859Sml29623 * or http://www.opensolaris.org/os/licensing. 103859Sml29623 * See the License for the specific language governing permissions 113859Sml29623 * and limitations under the License. 123859Sml29623 * 133859Sml29623 * When distributing Covered Code, include this CDDL HEADER in each 143859Sml29623 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153859Sml29623 * If applicable, add the following below this CDDL HEADER, with the 163859Sml29623 * fields enclosed by brackets "[]" replaced with your own identifying 173859Sml29623 * information: Portions Copyright [yyyy] [name of copyright owner] 183859Sml29623 * 193859Sml29623 * CDDL HEADER END 203859Sml29623 */ 213859Sml29623 /* 223859Sml29623 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 233859Sml29623 * Use is subject to license terms. 243859Sml29623 */ 253859Sml29623 263859Sml29623 #pragma ident "%Z%%M% %I% %E% SMI" 273859Sml29623 283859Sml29623 #include <nxge_impl.h> 293859Sml29623 #include <nxge_zcp.h> 303859Sml29623 #include <nxge_ipp.h> 313859Sml29623 323859Sml29623 nxge_status_t 333859Sml29623 nxge_zcp_init(p_nxge_t nxgep) 343859Sml29623 { 353859Sml29623 uint8_t portn; 363859Sml29623 npi_handle_t handle; 373859Sml29623 zcp_iconfig_t istatus; 383859Sml29623 npi_status_t rs = NPI_SUCCESS; 393859Sml29623 int i; 403859Sml29623 zcp_ram_unit_t w_data; 413859Sml29623 zcp_ram_unit_t r_data; 423859Sml29623 uint32_t cfifo_depth; 433859Sml29623 443859Sml29623 handle = nxgep->npi_handle; 453859Sml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 463859Sml29623 47*4732Sdavemq if (nxgep->niu_type == N2_NIU) { 48*4732Sdavemq cfifo_depth = ZCP_NIU_CFIFO_DEPTH; 49*4732Sdavemq } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep->niu_type)) { 503859Sml29623 if (portn < 2) 513859Sml29623 cfifo_depth = ZCP_P0_P1_CFIFO_DEPTH; 523859Sml29623 else 533859Sml29623 cfifo_depth = ZCP_P2_P3_CFIFO_DEPTH; 54*4732Sdavemq } else { 55*4732Sdavemq goto fail; 56*4732Sdavemq } 573859Sml29623 583859Sml29623 /* Clean up CFIFO */ 593859Sml29623 w_data.w0 = 0; 603859Sml29623 w_data.w1 = 0; 613859Sml29623 w_data.w2 = 0; 623859Sml29623 w_data.w3 = 0; 633859Sml29623 w_data.w4 = 0; 643859Sml29623 653859Sml29623 for (i = 0; i < cfifo_depth; i++) { 663859Sml29623 if (npi_zcp_tt_cfifo_entry(handle, OP_SET, 673859Sml29623 portn, i, &w_data) != NPI_SUCCESS) 683859Sml29623 goto fail; 693859Sml29623 if (npi_zcp_tt_cfifo_entry(handle, OP_GET, 703859Sml29623 portn, i, &r_data) != NPI_SUCCESS) 713859Sml29623 goto fail; 723859Sml29623 } 733859Sml29623 743859Sml29623 if (npi_zcp_rest_cfifo_port(handle, portn) != NPI_SUCCESS) 753859Sml29623 goto fail; 763859Sml29623 773859Sml29623 /* 783859Sml29623 * Making sure that error source is cleared if this is an injected 793859Sml29623 * error. 803859Sml29623 */ 813859Sml29623 switch (portn) { 823859Sml29623 case 0: 833859Sml29623 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0); 843859Sml29623 break; 853859Sml29623 case 1: 863859Sml29623 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0); 873859Sml29623 break; 883859Sml29623 case 2: 893859Sml29623 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0); 903859Sml29623 break; 913859Sml29623 case 3: 923859Sml29623 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0); 933859Sml29623 break; 943859Sml29623 } 953859Sml29623 963859Sml29623 if ((rs = npi_zcp_clear_istatus(handle)) != NPI_SUCCESS) 973859Sml29623 return (NXGE_ERROR | rs); 983859Sml29623 if ((rs = npi_zcp_get_istatus(handle, &istatus)) != NPI_SUCCESS) 993859Sml29623 return (NXGE_ERROR | rs); 1003859Sml29623 if ((rs = npi_zcp_iconfig(handle, INIT, ICFG_ZCP_ALL)) != NPI_SUCCESS) 1013859Sml29623 goto fail; 1023859Sml29623 1033859Sml29623 NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_zcp_init: port%d", portn)); 1043859Sml29623 return (NXGE_OK); 1053859Sml29623 1063859Sml29623 fail: 1073859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1083859Sml29623 "nxge_zcp_init: Fail to initialize ZCP Port #%d\n", portn)); 1093859Sml29623 return (NXGE_ERROR | rs); 1103859Sml29623 } 1113859Sml29623 1123859Sml29623 nxge_status_t 1133859Sml29623 nxge_zcp_handle_sys_errors(p_nxge_t nxgep) 1143859Sml29623 { 1153859Sml29623 npi_handle_t handle; 1163859Sml29623 npi_status_t rs = NPI_SUCCESS; 1173859Sml29623 p_nxge_zcp_stats_t statsp; 1183859Sml29623 uint8_t portn; 1193859Sml29623 zcp_iconfig_t istatus; 1203859Sml29623 boolean_t rxport_fatal = B_FALSE; 1213859Sml29623 nxge_status_t status = NXGE_OK; 1223859Sml29623 1233859Sml29623 handle = nxgep->npi_handle; 1243859Sml29623 statsp = (p_nxge_zcp_stats_t)&nxgep->statsp->zcp_stats; 1253859Sml29623 portn = nxgep->mac.portnum; 1263859Sml29623 1273859Sml29623 if ((rs = npi_zcp_get_istatus(handle, &istatus)) != NPI_SUCCESS) 1283859Sml29623 return (NXGE_ERROR | rs); 1293859Sml29623 1303859Sml29623 if (istatus & ICFG_ZCP_RRFIFO_UNDERRUN) { 1313859Sml29623 statsp->rrfifo_underrun++; 1323859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 1333859Sml29623 NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN); 1343859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1353859Sml29623 "nxge_zcp_err_evnts: rrfifo_underrun")); 1363859Sml29623 } 1373859Sml29623 1383859Sml29623 if (istatus & ICFG_ZCP_RRFIFO_OVERRUN) { 1393859Sml29623 statsp->rrfifo_overrun++; 1403859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 1413859Sml29623 NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN); 1423859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1433859Sml29623 "nxge_zcp_err_evnts: buf_rrfifo_overrun")); 1443859Sml29623 } 1453859Sml29623 1463859Sml29623 if (istatus & ICFG_ZCP_RSPFIFO_UNCORR_ERR) { 1473859Sml29623 statsp->rspfifo_uncorr_err++; 1483859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 1493859Sml29623 NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR); 1503859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1513859Sml29623 "nxge_zcp_err_evnts: rspfifo_uncorr_err")); 1523859Sml29623 } 1533859Sml29623 1543859Sml29623 if (istatus & ICFG_ZCP_BUFFER_OVERFLOW) { 1553859Sml29623 statsp->buffer_overflow++; 1563859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 1573859Sml29623 NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW); 1583859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1593859Sml29623 "nxge_zcp_err_evnts: buffer_overflow")); 1603859Sml29623 rxport_fatal = B_TRUE; 1613859Sml29623 } 1623859Sml29623 1633859Sml29623 if (istatus & ICFG_ZCP_STAT_TBL_PERR) { 1643859Sml29623 statsp->stat_tbl_perr++; 1653859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 1663859Sml29623 NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR); 1673859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1683859Sml29623 "nxge_zcp_err_evnts: stat_tbl_perr")); 1693859Sml29623 } 1703859Sml29623 1713859Sml29623 if (istatus & ICFG_ZCP_DYN_TBL_PERR) { 1723859Sml29623 statsp->dyn_tbl_perr++; 1733859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 1743859Sml29623 NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR); 1753859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1763859Sml29623 "nxge_zcp_err_evnts: dyn_tbl_perr")); 1773859Sml29623 } 1783859Sml29623 1793859Sml29623 if (istatus & ICFG_ZCP_BUF_TBL_PERR) { 1803859Sml29623 statsp->buf_tbl_perr++; 1813859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 1823859Sml29623 NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR); 1833859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1843859Sml29623 "nxge_zcp_err_evnts: buf_tbl_perr")); 1853859Sml29623 } 1863859Sml29623 1873859Sml29623 if (istatus & ICFG_ZCP_TT_PROGRAM_ERR) { 1883859Sml29623 statsp->tt_program_err++; 1893859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 1903859Sml29623 NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR); 1913859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1923859Sml29623 "nxge_zcp_err_evnts: tt_program_err")); 1933859Sml29623 } 1943859Sml29623 1953859Sml29623 if (istatus & ICFG_ZCP_RSP_TT_INDEX_ERR) { 1963859Sml29623 statsp->rsp_tt_index_err++; 1973859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 1983859Sml29623 NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR); 1993859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2003859Sml29623 "nxge_zcp_err_evnts: rsp_tt_index_err")); 2013859Sml29623 } 2023859Sml29623 2033859Sml29623 if (istatus & ICFG_ZCP_SLV_TT_INDEX_ERR) { 2043859Sml29623 statsp->slv_tt_index_err++; 2053859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 2063859Sml29623 NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR); 2073859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2083859Sml29623 "nxge_zcp_err_evnts: slv_tt_index_err")); 2093859Sml29623 } 2103859Sml29623 2113859Sml29623 if (istatus & ICFG_ZCP_TT_INDEX_ERR) { 2123859Sml29623 statsp->zcp_tt_index_err++; 2133859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 2143859Sml29623 NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR); 2153859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2163859Sml29623 "nxge_zcp_err_evnts: tt_index_err")); 2173859Sml29623 } 2183859Sml29623 2193859Sml29623 if (((portn == 0) && (istatus & ICFG_ZCP_CFIFO_ECC0)) || 2203859Sml29623 ((portn == 1) && (istatus & ICFG_ZCP_CFIFO_ECC1)) || 2213859Sml29623 ((portn == 2) && (istatus & ICFG_ZCP_CFIFO_ECC2)) || 2223859Sml29623 ((portn == 3) && (istatus & ICFG_ZCP_CFIFO_ECC3))) { 2233859Sml29623 boolean_t ue_ecc_valid; 2243859Sml29623 2253859Sml29623 if ((status = nxge_ipp_eccue_valid_check(nxgep, 2263859Sml29623 &ue_ecc_valid)) != NXGE_OK) 2273859Sml29623 return (status); 2283859Sml29623 2293859Sml29623 if (ue_ecc_valid) { 2303859Sml29623 statsp->cfifo_ecc++; 2313859Sml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 2323859Sml29623 NXGE_FM_EREPORT_ZCP_CFIFO_ECC); 2333859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2343859Sml29623 "nxge_zcp_err_evnts: port%d buf_cfifo_ecc", 2353859Sml29623 portn)); 2363859Sml29623 rxport_fatal = B_TRUE; 2373859Sml29623 } 2383859Sml29623 } 2393859Sml29623 2403859Sml29623 /* 2413859Sml29623 * Making sure that error source is cleared if this is an injected 2423859Sml29623 * error. 2433859Sml29623 */ 2443859Sml29623 switch (portn) { 2453859Sml29623 case 0: 2463859Sml29623 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0); 2473859Sml29623 break; 2483859Sml29623 case 1: 2493859Sml29623 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0); 2503859Sml29623 break; 2513859Sml29623 case 2: 2523859Sml29623 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0); 2533859Sml29623 break; 2543859Sml29623 case 3: 2553859Sml29623 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0); 2563859Sml29623 break; 2573859Sml29623 } 2583859Sml29623 2593859Sml29623 (void) npi_zcp_clear_istatus(handle); 2603859Sml29623 2613859Sml29623 if (rxport_fatal) { 2623859Sml29623 NXGE_DEBUG_MSG((nxgep, IPP_CTL, 2633859Sml29623 " nxge_zcp_handle_sys_errors:" 2643859Sml29623 " fatal Error on Port #%d\n", portn)); 2653859Sml29623 status = nxge_zcp_fatal_err_recover(nxgep); 2663859Sml29623 if (status == NXGE_OK) { 2673859Sml29623 FM_SERVICE_RESTORED(nxgep); 2683859Sml29623 } 2693859Sml29623 } 2703859Sml29623 return (status); 2713859Sml29623 } 2723859Sml29623 2733859Sml29623 void 2743859Sml29623 nxge_zcp_inject_err(p_nxge_t nxgep, uint32_t err_id) 2753859Sml29623 { 2763859Sml29623 zcp_int_stat_reg_t zcps; 2773859Sml29623 uint8_t portn = nxgep->mac.portnum; 2783859Sml29623 zcp_ecc_ctrl_t ecc_ctrl; 2793859Sml29623 2803859Sml29623 switch (err_id) { 2813859Sml29623 case NXGE_FM_EREPORT_ZCP_CFIFO_ECC: 2823859Sml29623 ecc_ctrl.value = 0; 2833859Sml29623 ecc_ctrl.bits.w0.cor_dbl = 1; 2843859Sml29623 ecc_ctrl.bits.w0.cor_lst = 1; 2853859Sml29623 ecc_ctrl.bits.w0.cor_all = 0; 2863859Sml29623 switch (portn) { 2873859Sml29623 case 0: 2883859Sml29623 cmn_err(CE_NOTE, 2893859Sml29623 "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n", 2903859Sml29623 (unsigned long long) ecc_ctrl.value, portn); 2913859Sml29623 NXGE_REG_WR64(nxgep->npi_handle, 2923859Sml29623 ZCP_CFIFO_ECC_PORT0_REG, 2933859Sml29623 ecc_ctrl.value); 2943859Sml29623 break; 2953859Sml29623 case 1: 2963859Sml29623 cmn_err(CE_NOTE, 2973859Sml29623 "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n", 2983859Sml29623 (unsigned long long) ecc_ctrl.value, portn); 2993859Sml29623 NXGE_REG_WR64(nxgep->npi_handle, 3003859Sml29623 ZCP_CFIFO_ECC_PORT1_REG, 3013859Sml29623 ecc_ctrl.value); 3023859Sml29623 break; 3033859Sml29623 case 2: 3043859Sml29623 cmn_err(CE_NOTE, 3053859Sml29623 "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n", 3063859Sml29623 (unsigned long long) ecc_ctrl.value, portn); 3073859Sml29623 NXGE_REG_WR64(nxgep->npi_handle, 3083859Sml29623 ZCP_CFIFO_ECC_PORT2_REG, 3093859Sml29623 ecc_ctrl.value); 3103859Sml29623 break; 3113859Sml29623 case 3: 3123859Sml29623 cmn_err(CE_NOTE, 3133859Sml29623 "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n", 3143859Sml29623 (unsigned long long) ecc_ctrl.value, portn); 3153859Sml29623 NXGE_REG_WR64(nxgep->npi_handle, 3163859Sml29623 ZCP_CFIFO_ECC_PORT3_REG, 3173859Sml29623 ecc_ctrl.value); 3183859Sml29623 break; 3193859Sml29623 } 3203859Sml29623 break; 3213859Sml29623 3223859Sml29623 case NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN: 3233859Sml29623 case NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR: 3243859Sml29623 case NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR: 3253859Sml29623 case NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR: 3263859Sml29623 case NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR: 3273859Sml29623 case NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN: 3283859Sml29623 case NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW: 3293859Sml29623 case NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR: 3303859Sml29623 case NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR: 3313859Sml29623 case NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR: 3323859Sml29623 case NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR: 3333859Sml29623 NXGE_REG_RD64(nxgep->npi_handle, ZCP_INT_STAT_TEST_REG, 3343859Sml29623 &zcps.value); 3353859Sml29623 if (err_id == NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN) 3363859Sml29623 zcps.bits.ldw.rrfifo_urun = 1; 3373859Sml29623 if (err_id == NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR) 3383859Sml29623 zcps.bits.ldw.rspfifo_uc_err = 1; 3393859Sml29623 if (err_id == NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR) 3403859Sml29623 zcps.bits.ldw.stat_tbl_perr = 1; 3413859Sml29623 if (err_id == NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR) 3423859Sml29623 zcps.bits.ldw.dyn_tbl_perr = 1; 3433859Sml29623 if (err_id == NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR) 3443859Sml29623 zcps.bits.ldw.buf_tbl_perr = 1; 3453859Sml29623 if (err_id == NXGE_FM_EREPORT_ZCP_CFIFO_ECC) { 3463859Sml29623 switch (portn) { 3473859Sml29623 case 0: 3483859Sml29623 zcps.bits.ldw.cfifo_ecc0 = 1; 3493859Sml29623 break; 3503859Sml29623 case 1: 3513859Sml29623 zcps.bits.ldw.cfifo_ecc1 = 1; 3523859Sml29623 break; 3533859Sml29623 case 2: 3543859Sml29623 zcps.bits.ldw.cfifo_ecc2 = 1; 3553859Sml29623 break; 3563859Sml29623 case 3: 3573859Sml29623 zcps.bits.ldw.cfifo_ecc3 = 1; 3583859Sml29623 break; 3593859Sml29623 } 3603859Sml29623 } 3613859Sml29623 3623859Sml29623 default: 3633859Sml29623 if (err_id == NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN) 3643859Sml29623 zcps.bits.ldw.rrfifo_orun = 1; 3653859Sml29623 if (err_id == NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW) 3663859Sml29623 zcps.bits.ldw.buf_overflow = 1; 3673859Sml29623 if (err_id == NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR) 3683859Sml29623 zcps.bits.ldw.tt_tbl_perr = 1; 3693859Sml29623 if (err_id == NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR) 3703859Sml29623 zcps.bits.ldw.rsp_tt_index_err = 1; 3713859Sml29623 if (err_id == NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR) 3723859Sml29623 zcps.bits.ldw.slv_tt_index_err = 1; 3733859Sml29623 if (err_id == NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR) 3743859Sml29623 zcps.bits.ldw.zcp_tt_index_err = 1; 3753859Sml29623 cmn_err(CE_NOTE, "!Write 0x%lx to ZCP_INT_STAT_TEST_REG\n", 3763859Sml29623 zcps.value); 3773859Sml29623 NXGE_REG_WR64(nxgep->npi_handle, ZCP_INT_STAT_TEST_REG, 3783859Sml29623 zcps.value); 3793859Sml29623 break; 3803859Sml29623 } 3813859Sml29623 } 3823859Sml29623 3833859Sml29623 nxge_status_t 3843859Sml29623 nxge_zcp_fatal_err_recover(p_nxge_t nxgep) 3853859Sml29623 { 3863859Sml29623 npi_handle_t handle; 3873859Sml29623 npi_status_t rs = NPI_SUCCESS; 3883859Sml29623 nxge_status_t status = NXGE_OK; 3893859Sml29623 uint8_t portn; 3903859Sml29623 zcp_ram_unit_t w_data; 3913859Sml29623 zcp_ram_unit_t r_data; 3923859Sml29623 uint32_t cfifo_depth; 3933859Sml29623 int i; 3943859Sml29623 3953859Sml29623 NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_zcp_fatal_err_recover")); 3963859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3973859Sml29623 "Recovering from RxPort error...")); 3983859Sml29623 3993859Sml29623 handle = nxgep->npi_handle; 4003859Sml29623 portn = nxgep->mac.portnum; 4013859Sml29623 4023859Sml29623 /* Disable RxMAC */ 4033859Sml29623 if (nxge_rx_mac_disable(nxgep) != NXGE_OK) 4043859Sml29623 goto fail; 4053859Sml29623 4063859Sml29623 /* Make sure source is clear if this is an injected error */ 4073859Sml29623 switch (portn) { 4083859Sml29623 case 0: 4093859Sml29623 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0); 4103859Sml29623 break; 4113859Sml29623 case 1: 4123859Sml29623 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0); 4133859Sml29623 break; 4143859Sml29623 case 2: 4153859Sml29623 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0); 4163859Sml29623 break; 4173859Sml29623 case 3: 4183859Sml29623 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0); 4193859Sml29623 break; 4203859Sml29623 } 4213859Sml29623 4223859Sml29623 /* Clear up CFIFO */ 423*4732Sdavemq if (nxgep->niu_type == N2_NIU) { 424*4732Sdavemq cfifo_depth = ZCP_NIU_CFIFO_DEPTH; 425*4732Sdavemq } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep->niu_type)) { 4263859Sml29623 if (portn < 2) 4273859Sml29623 cfifo_depth = ZCP_P0_P1_CFIFO_DEPTH; 4283859Sml29623 else 4293859Sml29623 cfifo_depth = ZCP_P2_P3_CFIFO_DEPTH; 430*4732Sdavemq } else { 431*4732Sdavemq goto fail; 432*4732Sdavemq } 4333859Sml29623 4343859Sml29623 w_data.w0 = 0; 4353859Sml29623 w_data.w1 = 0; 4363859Sml29623 w_data.w2 = 0; 4373859Sml29623 w_data.w3 = 0; 4383859Sml29623 w_data.w4 = 0; 4393859Sml29623 4403859Sml29623 for (i = 0; i < cfifo_depth; i++) { 4413859Sml29623 if (npi_zcp_tt_cfifo_entry(handle, OP_SET, 4423859Sml29623 portn, i, &w_data) != NPI_SUCCESS) 4433859Sml29623 goto fail; 4443859Sml29623 if (npi_zcp_tt_cfifo_entry(handle, OP_GET, 4453859Sml29623 portn, i, &r_data) != NPI_SUCCESS) 4463859Sml29623 goto fail; 4473859Sml29623 } 4483859Sml29623 4493859Sml29623 /* When recovering from ZCP, RxDMA channel resets are not necessary */ 4503859Sml29623 /* Reset ZCP CFIFO */ 4513859Sml29623 NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset ZCP CFIFO...", portn)); 4523859Sml29623 if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS) 4533859Sml29623 goto fail; 4543859Sml29623 4553859Sml29623 /* Reset IPP */ 4563859Sml29623 NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset IPP...", portn)); 4573859Sml29623 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) 4583859Sml29623 goto fail; 4593859Sml29623 4603859Sml29623 NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset RxMAC...", portn)); 4613859Sml29623 if (nxge_rx_mac_reset(nxgep) != NXGE_OK) 4623859Sml29623 goto fail; 4633859Sml29623 4643859Sml29623 NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Initialize RxMAC...", portn)); 4653859Sml29623 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 4663859Sml29623 goto fail; 4673859Sml29623 4683859Sml29623 NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Enable RxMAC...", portn)); 4693859Sml29623 if (nxge_rx_mac_enable(nxgep) != NXGE_OK) 4703859Sml29623 goto fail; 4713859Sml29623 4723859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4733859Sml29623 "Recovery Sucessful, RxPort Restored")); 4743859Sml29623 NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_zcp_fatal_err_recover")); 4753859Sml29623 return (NXGE_OK); 4763859Sml29623 fail: 4773859Sml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed")); 4783859Sml29623 return (status | rs); 4793859Sml29623 } 480