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 /* 2263e23a19Syc148097 * 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_ipp.h> 306f45ec7bSml29623 316f45ec7bSml29623 #define NXGE_IPP_FIFO_SYNC_TRY_COUNT 100 326f45ec7bSml29623 336f45ec7bSml29623 /* ARGSUSED */ 346f45ec7bSml29623 nxge_status_t 356f45ec7bSml29623 nxge_ipp_init(p_nxge_t nxgep) 366f45ec7bSml29623 { 376f45ec7bSml29623 uint8_t portn; 386f45ec7bSml29623 uint32_t config; 396f45ec7bSml29623 npi_handle_t handle; 406f45ec7bSml29623 uint32_t pkt_size; 416f45ec7bSml29623 ipp_status_t istatus; 426f45ec7bSml29623 npi_status_t rs = NPI_SUCCESS; 436f45ec7bSml29623 uint64_t val; 446f45ec7bSml29623 uint32_t d0, d1, d2, d3, d4; 456f45ec7bSml29623 int i; 466f45ec7bSml29623 uint32_t dfifo_entries; 476f45ec7bSml29623 486f45ec7bSml29623 handle = nxgep->npi_handle; 496f45ec7bSml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 506f45ec7bSml29623 516f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_init: port%d", portn)); 526f45ec7bSml29623 536f45ec7bSml29623 /* Initialize ECC and parity in SRAM of DFIFO and PFIFO */ 5459ac0c16Sdavemq if (nxgep->niu_type == N2_NIU) { 5559ac0c16Sdavemq dfifo_entries = IPP_NIU_DFIFO_ENTRIES; 562e59129aSraghus } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 576f45ec7bSml29623 if (portn < 2) 586f45ec7bSml29623 dfifo_entries = IPP_P0_P1_DFIFO_ENTRIES; 596f45ec7bSml29623 else 606f45ec7bSml29623 dfifo_entries = IPP_P2_P3_DFIFO_ENTRIES; 6159ac0c16Sdavemq } else { 626f45ec7bSml29623 goto fail; 6359ac0c16Sdavemq } 646f45ec7bSml29623 656f45ec7bSml29623 for (i = 0; i < dfifo_entries; i++) { 666f45ec7bSml29623 if ((rs = npi_ipp_write_dfifo(handle, 676f45ec7bSml29623 portn, i, 0, 0, 0, 0, 0)) != NPI_SUCCESS) 686f45ec7bSml29623 goto fail; 696f45ec7bSml29623 if ((rs = npi_ipp_read_dfifo(handle, portn, 706f45ec7bSml29623 i, &d0, &d1, &d2, &d3, &d4)) != NPI_SUCCESS) 716f45ec7bSml29623 goto fail; 726f45ec7bSml29623 } 736f45ec7bSml29623 746f45ec7bSml29623 /* Clear PFIFO DFIFO status bits */ 756f45ec7bSml29623 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 766f45ec7bSml29623 goto fail; 776f45ec7bSml29623 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 786f45ec7bSml29623 goto fail; 796f45ec7bSml29623 806f45ec7bSml29623 /* 816f45ec7bSml29623 * Soft reset to make sure we bring the FIFO pointers back to the 826f45ec7bSml29623 * original initial position. 836f45ec7bSml29623 */ 846f45ec7bSml29623 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) 856f45ec7bSml29623 goto fail; 866f45ec7bSml29623 876f45ec7bSml29623 /* Clean up ECC counter */ 886f45ec7bSml29623 IPP_REG_RD(nxgep->npi_handle, portn, IPP_ECC_ERR_COUNTER_REG, &val); 89f6485eecSyc148097 IPP_REG_RD(nxgep->npi_handle, portn, IPP_BAD_CKSUM_ERR_CNT_REG, &val); 906f45ec7bSml29623 IPP_REG_RD(nxgep->npi_handle, portn, IPP_DISCARD_PKT_CNT_REG, &val); 916f45ec7bSml29623 926f45ec7bSml29623 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 936f45ec7bSml29623 goto fail; 946f45ec7bSml29623 956f45ec7bSml29623 /* Configure IPP port */ 966f45ec7bSml29623 if ((rs = npi_ipp_iconfig(handle, INIT, portn, ICFG_IPP_ALL)) 976f45ec7bSml29623 != NPI_SUCCESS) 986f45ec7bSml29623 goto fail; 996f45ec7bSml29623 nxgep->ipp.iconfig = ICFG_IPP_ALL; 1006f45ec7bSml29623 1016f45ec7bSml29623 config = CFG_IPP | CFG_IPP_DFIFO_ECC_CORRECT | CFG_IPP_DROP_BAD_CRC | 1026f45ec7bSml29623 CFG_IPP_TCP_UDP_CKSUM; 1036f45ec7bSml29623 if ((rs = npi_ipp_config(handle, INIT, portn, config)) != NPI_SUCCESS) 1046f45ec7bSml29623 goto fail; 1056f45ec7bSml29623 nxgep->ipp.config = config; 1066f45ec7bSml29623 1076f45ec7bSml29623 /* Set max packet size */ 1086f45ec7bSml29623 pkt_size = IPP_MAX_PKT_SIZE; 1096f45ec7bSml29623 if ((rs = npi_ipp_set_max_pktsize(handle, portn, 1106f45ec7bSml29623 IPP_MAX_PKT_SIZE)) != NPI_SUCCESS) 1116f45ec7bSml29623 goto fail; 1126f45ec7bSml29623 nxgep->ipp.max_pkt_size = pkt_size; 1136f45ec7bSml29623 1146f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_init: port%d", portn)); 1156f45ec7bSml29623 1166f45ec7bSml29623 return (NXGE_OK); 1176f45ec7bSml29623 fail: 1186f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1196f45ec7bSml29623 "nxge_ipp_init: Fail to initialize IPP Port #%d\n", 1206f45ec7bSml29623 portn)); 1216f45ec7bSml29623 return (NXGE_ERROR | rs); 1226f45ec7bSml29623 } 1236f45ec7bSml29623 1246f45ec7bSml29623 /* ARGSUSED */ 1256f45ec7bSml29623 nxge_status_t 1266f45ec7bSml29623 nxge_ipp_disable(p_nxge_t nxgep) 1276f45ec7bSml29623 { 1286f45ec7bSml29623 uint8_t portn; 1296f45ec7bSml29623 uint32_t config; 1306f45ec7bSml29623 npi_handle_t handle; 1316f45ec7bSml29623 npi_status_t rs = NPI_SUCCESS; 1326f45ec7bSml29623 uint16_t wr_ptr, rd_ptr; 1336f45ec7bSml29623 uint32_t try_count; 1346f45ec7bSml29623 1356f45ec7bSml29623 handle = nxgep->npi_handle; 1366f45ec7bSml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1376f45ec7bSml29623 1386f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_disable: port%d", portn)); 1396f45ec7bSml29623 (void) nxge_rx_mac_disable(nxgep); 1406f45ec7bSml29623 1416f45ec7bSml29623 /* 1426f45ec7bSml29623 * Wait until ip read and write fifo pointers are equal 1436f45ec7bSml29623 */ 1446f45ec7bSml29623 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 1456f45ec7bSml29623 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 1466f45ec7bSml29623 try_count = NXGE_IPP_FIFO_SYNC_TRY_COUNT; 1476f45ec7bSml29623 1486f45ec7bSml29623 while ((try_count > 0) && (rd_ptr != wr_ptr)) { 1496f45ec7bSml29623 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 1506f45ec7bSml29623 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 1516f45ec7bSml29623 try_count--; 1526f45ec7bSml29623 } 1536f45ec7bSml29623 1546f45ec7bSml29623 if (try_count == 0) { 1556f45ec7bSml29623 if ((rd_ptr != 0) && (wr_ptr != 1)) { 1566f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1576f45ec7bSml29623 " nxge_ipp_disable: port%d failed" 1586f45ec7bSml29623 " rd_fifo != wr_fifo", portn)); 1596f45ec7bSml29623 goto fail; 1606f45ec7bSml29623 } 1616f45ec7bSml29623 } 1626f45ec7bSml29623 /* disable the IPP */ 1636f45ec7bSml29623 config = nxgep->ipp.config; 1646f45ec7bSml29623 if ((rs = npi_ipp_config(handle, DISABLE, 1656f45ec7bSml29623 portn, config)) != NPI_SUCCESS) 1666f45ec7bSml29623 goto fail; 1676f45ec7bSml29623 1686f45ec7bSml29623 /* IPP soft reset */ 1696f45ec7bSml29623 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) 1706f45ec7bSml29623 goto fail; 1716f45ec7bSml29623 1726f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_disable: port%d", portn)); 1736f45ec7bSml29623 return (NXGE_OK); 1746f45ec7bSml29623 fail: 1756f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1766f45ec7bSml29623 "nxge_ipp_disable: Fail to disable IPP Port #%d\n", portn)); 1776f45ec7bSml29623 return (NXGE_ERROR | rs); 1786f45ec7bSml29623 } 1796f45ec7bSml29623 1806f45ec7bSml29623 /* ARGSUSED */ 1816f45ec7bSml29623 nxge_status_t 1826f45ec7bSml29623 nxge_ipp_reset(p_nxge_t nxgep) 1836f45ec7bSml29623 { 1846f45ec7bSml29623 uint8_t portn; 1856f45ec7bSml29623 uint32_t config; 1866f45ec7bSml29623 npi_handle_t handle; 1876f45ec7bSml29623 npi_status_t rs = NPI_SUCCESS; 1886f45ec7bSml29623 uint16_t wr_ptr, rd_ptr; 1896f45ec7bSml29623 uint32_t try_count; 1906f45ec7bSml29623 1916f45ec7bSml29623 handle = nxgep->npi_handle; 1926f45ec7bSml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1936f45ec7bSml29623 1946f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_reset: port%d", portn)); 1956f45ec7bSml29623 1966f45ec7bSml29623 /* disable the IPP */ 1976f45ec7bSml29623 config = nxgep->ipp.config; 1986f45ec7bSml29623 if ((rs = npi_ipp_config(handle, DISABLE, 1996f45ec7bSml29623 portn, config)) != NPI_SUCCESS) 2006f45ec7bSml29623 goto fail; 2016f45ec7bSml29623 2026f45ec7bSml29623 /* 2036f45ec7bSml29623 * Wait until ip read and write fifo pointers are equal 2046f45ec7bSml29623 */ 2056f45ec7bSml29623 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 2066f45ec7bSml29623 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 2076f45ec7bSml29623 try_count = NXGE_IPP_FIFO_SYNC_TRY_COUNT; 2086f45ec7bSml29623 2096f45ec7bSml29623 while ((try_count > 0) && (rd_ptr != wr_ptr)) { 2106f45ec7bSml29623 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 2116f45ec7bSml29623 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 2126f45ec7bSml29623 try_count--; 2136f45ec7bSml29623 } 2146f45ec7bSml29623 2156f45ec7bSml29623 if (try_count == 0) { 2166f45ec7bSml29623 if ((rd_ptr != 0) && (wr_ptr != 1)) { 2176f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2186f45ec7bSml29623 " nxge_ipp_disable: port%d failed" 2196f45ec7bSml29623 " rd_fifo != wr_fifo", portn)); 2206f45ec7bSml29623 goto fail; 2216f45ec7bSml29623 } 2226f45ec7bSml29623 } 2236f45ec7bSml29623 2246f45ec7bSml29623 /* IPP soft reset */ 2256f45ec7bSml29623 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) { 2266f45ec7bSml29623 goto fail; 2276f45ec7bSml29623 } 2286f45ec7bSml29623 2296f45ec7bSml29623 /* to reset control FIFO */ 2306f45ec7bSml29623 if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS) 2316f45ec7bSml29623 goto fail; 2326f45ec7bSml29623 2336f45ec7bSml29623 /* 2346f45ec7bSml29623 * Making sure that error source is cleared if this is an injected 2356f45ec7bSml29623 * error. 2366f45ec7bSml29623 */ 2376f45ec7bSml29623 IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0); 2386f45ec7bSml29623 2396f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_reset: port%d", portn)); 2406f45ec7bSml29623 return (NXGE_OK); 2416f45ec7bSml29623 fail: 2426f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2436f45ec7bSml29623 "nxge_ipp_init: Fail to Reset IPP Port #%d\n", 2446f45ec7bSml29623 portn)); 2456f45ec7bSml29623 return (NXGE_ERROR | rs); 2466f45ec7bSml29623 } 2476f45ec7bSml29623 2486f45ec7bSml29623 /* ARGSUSED */ 2496f45ec7bSml29623 nxge_status_t 2506f45ec7bSml29623 nxge_ipp_enable(p_nxge_t nxgep) 2516f45ec7bSml29623 { 2526f45ec7bSml29623 uint8_t portn; 2536f45ec7bSml29623 uint32_t config; 2546f45ec7bSml29623 npi_handle_t handle; 2556f45ec7bSml29623 uint32_t pkt_size; 2566f45ec7bSml29623 npi_status_t rs = NPI_SUCCESS; 2576f45ec7bSml29623 2586f45ec7bSml29623 handle = nxgep->npi_handle; 2596f45ec7bSml29623 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 2606f45ec7bSml29623 2616f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_enable: port%d", portn)); 2626f45ec7bSml29623 2636f45ec7bSml29623 config = CFG_IPP | CFG_IPP_DFIFO_ECC_CORRECT | CFG_IPP_DROP_BAD_CRC | 2646f45ec7bSml29623 CFG_IPP_TCP_UDP_CKSUM; 2656f45ec7bSml29623 if ((rs = npi_ipp_config(handle, INIT, portn, config)) != NPI_SUCCESS) 2666f45ec7bSml29623 goto fail; 2676f45ec7bSml29623 nxgep->ipp.config = config; 2686f45ec7bSml29623 2696f45ec7bSml29623 /* Set max packet size */ 2706f45ec7bSml29623 pkt_size = IPP_MAX_PKT_SIZE; 2716f45ec7bSml29623 if ((rs = npi_ipp_set_max_pktsize(handle, portn, 2726f45ec7bSml29623 IPP_MAX_PKT_SIZE)) != NPI_SUCCESS) 2736f45ec7bSml29623 goto fail; 2746f45ec7bSml29623 nxgep->ipp.max_pkt_size = pkt_size; 2756f45ec7bSml29623 2766f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_enable: port%d", portn)); 2776f45ec7bSml29623 return (NXGE_OK); 2786f45ec7bSml29623 fail: 2796f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2806f45ec7bSml29623 "nxge_ipp_init: Fail to Enable IPP Port #%d\n", portn)); 2816f45ec7bSml29623 return (NXGE_ERROR | rs); 2826f45ec7bSml29623 } 2836f45ec7bSml29623 2846f45ec7bSml29623 /* ARGSUSED */ 2856f45ec7bSml29623 nxge_status_t 286*678453a8Sspeer nxge_ipp_drain(p_nxge_t nxgep) 287*678453a8Sspeer { 288*678453a8Sspeer uint8_t portn; 289*678453a8Sspeer npi_handle_t handle; 290*678453a8Sspeer npi_status_t rs = NPI_SUCCESS; 291*678453a8Sspeer uint16_t wr_ptr, rd_ptr; 292*678453a8Sspeer uint32_t try_count; 293*678453a8Sspeer 294*678453a8Sspeer handle = nxgep->npi_handle; 295*678453a8Sspeer portn = NXGE_GET_PORT_NUM(nxgep->function_num); 296*678453a8Sspeer 297*678453a8Sspeer NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_drain: port%d", portn)); 298*678453a8Sspeer 299*678453a8Sspeer /* 300*678453a8Sspeer * Wait until ip read and write fifo pointers are equal 301*678453a8Sspeer */ 302*678453a8Sspeer (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 303*678453a8Sspeer (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 304*678453a8Sspeer try_count = NXGE_IPP_FIFO_SYNC_TRY_COUNT; 305*678453a8Sspeer 306*678453a8Sspeer while ((try_count > 0) && (rd_ptr != wr_ptr)) { 307*678453a8Sspeer (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 308*678453a8Sspeer (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 309*678453a8Sspeer try_count--; 310*678453a8Sspeer } 311*678453a8Sspeer 312*678453a8Sspeer if (try_count == 0) { 313*678453a8Sspeer if ((rd_ptr != 0) && (wr_ptr != 1)) { 314*678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 315*678453a8Sspeer " nxge_ipp_drain: port%d failed" 316*678453a8Sspeer " rd_fifo != wr_fifo", portn)); 317*678453a8Sspeer goto fail; 318*678453a8Sspeer } 319*678453a8Sspeer } 320*678453a8Sspeer 321*678453a8Sspeer NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_drain: port%d", portn)); 322*678453a8Sspeer return (NXGE_OK); 323*678453a8Sspeer fail: 324*678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_ipp_init: " 325*678453a8Sspeer "Fail to Reset IPP Port #%d\n", portn)); 326*678453a8Sspeer return (NXGE_ERROR | rs); 327*678453a8Sspeer } 328*678453a8Sspeer 329*678453a8Sspeer /* ARGSUSED */ 330*678453a8Sspeer nxge_status_t 3316f45ec7bSml29623 nxge_ipp_handle_sys_errors(p_nxge_t nxgep) 3326f45ec7bSml29623 { 3336f45ec7bSml29623 npi_handle_t handle; 3346f45ec7bSml29623 npi_status_t rs = NPI_SUCCESS; 3356f45ec7bSml29623 p_nxge_ipp_stats_t statsp; 3366f45ec7bSml29623 ipp_status_t istatus; 3376f45ec7bSml29623 uint8_t portn; 3386f45ec7bSml29623 p_ipp_errlog_t errlogp; 3396f45ec7bSml29623 boolean_t rxport_fatal = B_FALSE; 3406f45ec7bSml29623 nxge_status_t status = NXGE_OK; 34153f3d8ecSyc148097 uint8_t cnt8; 34253f3d8ecSyc148097 uint16_t cnt16; 3436f45ec7bSml29623 3446f45ec7bSml29623 handle = nxgep->npi_handle; 3456f45ec7bSml29623 statsp = (p_nxge_ipp_stats_t)&nxgep->statsp->ipp_stats; 3466f45ec7bSml29623 portn = nxgep->mac.portnum; 3476f45ec7bSml29623 3486f45ec7bSml29623 errlogp = (p_ipp_errlog_t)&statsp->errlog; 3496f45ec7bSml29623 3506f45ec7bSml29623 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 3516f45ec7bSml29623 return (NXGE_ERROR | rs); 3526f45ec7bSml29623 3536f45ec7bSml29623 if (istatus.value == 0) { 3546f45ec7bSml29623 /* 3556f45ec7bSml29623 * The error is not initiated from this port, so just exit. 3566f45ec7bSml29623 */ 3576f45ec7bSml29623 return (NXGE_OK); 3586f45ec7bSml29623 } 3596f45ec7bSml29623 3606f45ec7bSml29623 if (istatus.bits.w0.dfifo_missed_sop) { 3616f45ec7bSml29623 statsp->sop_miss++; 3626f45ec7bSml29623 if ((rs = npi_ipp_get_dfifo_eopm_rdptr(handle, portn, 3636f45ec7bSml29623 &errlogp->dfifo_rd_ptr)) != NPI_SUCCESS) 3646f45ec7bSml29623 return (NXGE_ERROR | rs); 3656f45ec7bSml29623 if ((rs = npi_ipp_get_state_mach(handle, portn, 3666f45ec7bSml29623 &errlogp->state_mach)) != NPI_SUCCESS) 3676f45ec7bSml29623 return (NXGE_ERROR | rs); 3686f45ec7bSml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 3696f45ec7bSml29623 NXGE_FM_EREPORT_IPP_SOP_MISS); 3706f45ec7bSml29623 if (statsp->sop_miss < IPP_MAX_ERR_SHOW) 3716f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3726f45ec7bSml29623 "nxge_ipp_err_evnts: fatal error: sop_miss\n")); 3736f45ec7bSml29623 rxport_fatal = B_TRUE; 3746f45ec7bSml29623 } 3756f45ec7bSml29623 if (istatus.bits.w0.dfifo_missed_eop) { 3766f45ec7bSml29623 statsp->eop_miss++; 3776f45ec7bSml29623 if ((rs = npi_ipp_get_dfifo_eopm_rdptr(handle, portn, 3786f45ec7bSml29623 &errlogp->dfifo_rd_ptr)) != NPI_SUCCESS) 3796f45ec7bSml29623 return (NXGE_ERROR | rs); 3806f45ec7bSml29623 if ((rs = npi_ipp_get_state_mach(handle, portn, 3816f45ec7bSml29623 &errlogp->state_mach)) != NPI_SUCCESS) 3826f45ec7bSml29623 return (NXGE_ERROR | rs); 3836f45ec7bSml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 3846f45ec7bSml29623 NXGE_FM_EREPORT_IPP_EOP_MISS); 3856f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3866f45ec7bSml29623 "nxge_ipp_err_evnts: fatal error: eop_miss\n")); 3876f45ec7bSml29623 rxport_fatal = B_TRUE; 3886f45ec7bSml29623 } 3896f45ec7bSml29623 if (istatus.bits.w0.dfifo_uncorr_ecc_err) { 3906f45ec7bSml29623 boolean_t ue_ecc_valid; 3916f45ec7bSml29623 3926f45ec7bSml29623 if ((status = nxge_ipp_eccue_valid_check(nxgep, 3936f45ec7bSml29623 &ue_ecc_valid)) != NXGE_OK) 3946f45ec7bSml29623 return (status); 3956f45ec7bSml29623 3966f45ec7bSml29623 if (ue_ecc_valid) { 3976f45ec7bSml29623 statsp->dfifo_ue++; 3986f45ec7bSml29623 if ((rs = npi_ipp_get_ecc_syndrome(handle, portn, 3996f45ec7bSml29623 &errlogp->ecc_syndrome)) != NPI_SUCCESS) 4006f45ec7bSml29623 return (NXGE_ERROR | rs); 4016f45ec7bSml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 4026f45ec7bSml29623 NXGE_FM_EREPORT_IPP_DFIFO_UE); 4036f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4046f45ec7bSml29623 "nxge_ipp_err_evnts: fatal error: dfifo_ue\n")); 4056f45ec7bSml29623 rxport_fatal = B_TRUE; 4066f45ec7bSml29623 } 4076f45ec7bSml29623 } 4086f45ec7bSml29623 if (istatus.bits.w0.pre_fifo_perr) { 4096f45ec7bSml29623 statsp->pfifo_perr++; 4106f45ec7bSml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 4116f45ec7bSml29623 NXGE_FM_EREPORT_IPP_PFIFO_PERR); 4126f45ec7bSml29623 if (statsp->pfifo_perr < IPP_MAX_ERR_SHOW) 4136f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4146f45ec7bSml29623 "nxge_ipp_err_evnts: " 4156f45ec7bSml29623 "fatal error: pre_pifo_perr\n")); 4166f45ec7bSml29623 rxport_fatal = B_TRUE; 4176f45ec7bSml29623 } 4186f45ec7bSml29623 if (istatus.bits.w0.pre_fifo_overrun) { 4196f45ec7bSml29623 statsp->pfifo_over++; 4206f45ec7bSml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 4216f45ec7bSml29623 NXGE_FM_EREPORT_IPP_PFIFO_OVER); 4226f45ec7bSml29623 if (statsp->pfifo_over < IPP_MAX_ERR_SHOW) 4236f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4246f45ec7bSml29623 "nxge_ipp_err_evnts: " 4256f45ec7bSml29623 "fatal error: pfifo_over\n")); 4266f45ec7bSml29623 rxport_fatal = B_TRUE; 4276f45ec7bSml29623 } 4286f45ec7bSml29623 if (istatus.bits.w0.pre_fifo_underrun) { 4296f45ec7bSml29623 statsp->pfifo_und++; 4306f45ec7bSml29623 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 4316f45ec7bSml29623 NXGE_FM_EREPORT_IPP_PFIFO_UND); 4326f45ec7bSml29623 if (statsp->pfifo_und < IPP_MAX_ERR_SHOW) 4336f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4346f45ec7bSml29623 "nxge_ipp_err_evnts: " 4356f45ec7bSml29623 "fatal error: pfifo_und\n")); 4366f45ec7bSml29623 rxport_fatal = B_TRUE; 4376f45ec7bSml29623 } 4386f45ec7bSml29623 if (istatus.bits.w0.bad_cksum_cnt_ovfl) { 439d710877aSyc148097 /* 44063e23a19Syc148097 * Do not send FMA ereport or log error message 44163e23a19Syc148097 * in /var/adm/messages because this error does not 44263e23a19Syc148097 * indicate a HW failure. 44363e23a19Syc148097 * 444d710877aSyc148097 * Clear bit BAD_CS_MX of register IPP_INT_STAT 445d710877aSyc148097 * by reading register IPP_BAD_CS_CNT 446d710877aSyc148097 */ 44753f3d8ecSyc148097 (void) npi_ipp_get_cs_err_count(handle, portn, &cnt16); 4486f45ec7bSml29623 statsp->bad_cs_cnt += IPP_BAD_CS_CNT_MASK; 4496f45ec7bSml29623 } 4506f45ec7bSml29623 if (istatus.bits.w0.pkt_discard_cnt_ovfl) { 451d710877aSyc148097 /* 45263e23a19Syc148097 * Do not send FMA ereport or log error message 45363e23a19Syc148097 * in /var/adm/messages because this error does not 45463e23a19Syc148097 * indicate a HW failure. 45563e23a19Syc148097 * 456d710877aSyc148097 * Clear bit PKT_DIS_MX of register IPP_INT_STAT 457d710877aSyc148097 * by reading register IPP_PKT_DIS 458d710877aSyc148097 */ 45953f3d8ecSyc148097 (void) npi_ipp_get_pkt_dis_count(handle, portn, &cnt16); 4606f45ec7bSml29623 statsp->pkt_dis_cnt += IPP_PKT_DIS_CNT_MASK; 4616f45ec7bSml29623 } 46253f3d8ecSyc148097 if (istatus.bits.w0.ecc_err_cnt_ovfl) { 463d710877aSyc148097 /* 464d710877aSyc148097 * Clear bit ECC_ERR_MAX of register IPP_INI_STAT 465d710877aSyc148097 * by reading register IPP_ECC 466d710877aSyc148097 */ 46753f3d8ecSyc148097 (void) npi_ipp_get_ecc_err_count(handle, portn, &cnt8); 46853f3d8ecSyc148097 statsp->ecc_err_cnt += IPP_ECC_CNT_MASK; 469f6485eecSyc148097 /* 470f6485eecSyc148097 * A defect in Neptune port2's IPP module could generate 471f6485eecSyc148097 * many fake but harmless ECC errors under stress and cause 472f6485eecSyc148097 * the ecc-error-counter register IPP_ECC to reach its 473f6485eecSyc148097 * maximum value in a few seconds. To avoid false alarm, do 474f6485eecSyc148097 * not report the error if it is port2. 475f6485eecSyc148097 */ 476f6485eecSyc148097 if (portn != 2) { 47753f3d8ecSyc148097 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 47853f3d8ecSyc148097 NXGE_FM_EREPORT_IPP_ECC_ERR_MAX); 47953f3d8ecSyc148097 if (statsp->ecc_err_cnt < (IPP_MAX_ERR_SHOW * 480f6485eecSyc148097 IPP_ECC_CNT_MASK)) { 48153f3d8ecSyc148097 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 48253f3d8ecSyc148097 "nxge_ipp_err_evnts: pkt_ecc_err_max\n")); 48353f3d8ecSyc148097 } 484f6485eecSyc148097 } 485f6485eecSyc148097 } 4866f45ec7bSml29623 /* 4876f45ec7bSml29623 * Making sure that error source is cleared if this is an injected 4886f45ec7bSml29623 * error. 4896f45ec7bSml29623 */ 4906f45ec7bSml29623 IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0); 4916f45ec7bSml29623 4926f45ec7bSml29623 if (rxport_fatal) { 4936f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IPP_CTL, 4946f45ec7bSml29623 " nxge_ipp_handle_sys_errors:" 4956f45ec7bSml29623 " fatal Error on Port #%d\n", portn)); 4966f45ec7bSml29623 status = nxge_ipp_fatal_err_recover(nxgep); 4976f45ec7bSml29623 if (status == NXGE_OK) { 4986f45ec7bSml29623 FM_SERVICE_RESTORED(nxgep); 4996f45ec7bSml29623 } 5006f45ec7bSml29623 } 5016f45ec7bSml29623 return (status); 5026f45ec7bSml29623 } 5036f45ec7bSml29623 5046f45ec7bSml29623 /* ARGSUSED */ 5056f45ec7bSml29623 void 5066f45ec7bSml29623 nxge_ipp_inject_err(p_nxge_t nxgep, uint32_t err_id) 5076f45ec7bSml29623 { 5086f45ec7bSml29623 ipp_status_t ipps; 5096f45ec7bSml29623 ipp_ecc_ctrl_t ecc_ctrl; 5106f45ec7bSml29623 uint8_t portn = nxgep->mac.portnum; 5116f45ec7bSml29623 5126f45ec7bSml29623 switch (err_id) { 5136f45ec7bSml29623 case NXGE_FM_EREPORT_IPP_DFIFO_UE: 5146f45ec7bSml29623 ecc_ctrl.value = 0; 5156f45ec7bSml29623 ecc_ctrl.bits.w0.cor_dbl = 1; 5166f45ec7bSml29623 ecc_ctrl.bits.w0.cor_1 = 1; 5176f45ec7bSml29623 ecc_ctrl.bits.w0.cor_lst = 1; 5186f45ec7bSml29623 cmn_err(CE_NOTE, "!Write 0x%llx to IPP_ECC_CTRL_REG\n", 5196f45ec7bSml29623 (unsigned long long) ecc_ctrl.value); 5206f45ec7bSml29623 IPP_REG_WR(nxgep->npi_handle, portn, IPP_ECC_CTRL_REG, 5216f45ec7bSml29623 ecc_ctrl.value); 5226f45ec7bSml29623 break; 5236f45ec7bSml29623 5246f45ec7bSml29623 case NXGE_FM_EREPORT_IPP_DFIFO_CE: 5256f45ec7bSml29623 ecc_ctrl.value = 0; 5266f45ec7bSml29623 ecc_ctrl.bits.w0.cor_sng = 1; 5276f45ec7bSml29623 ecc_ctrl.bits.w0.cor_1 = 1; 5286f45ec7bSml29623 ecc_ctrl.bits.w0.cor_snd = 1; 5296f45ec7bSml29623 cmn_err(CE_NOTE, "!Write 0x%llx to IPP_ECC_CTRL_REG\n", 5306f45ec7bSml29623 (unsigned long long) ecc_ctrl.value); 5316f45ec7bSml29623 IPP_REG_WR(nxgep->npi_handle, portn, IPP_ECC_CTRL_REG, 5326f45ec7bSml29623 ecc_ctrl.value); 5336f45ec7bSml29623 break; 5346f45ec7bSml29623 5356f45ec7bSml29623 case NXGE_FM_EREPORT_IPP_EOP_MISS: 5366f45ec7bSml29623 case NXGE_FM_EREPORT_IPP_SOP_MISS: 5376f45ec7bSml29623 case NXGE_FM_EREPORT_IPP_PFIFO_PERR: 5386f45ec7bSml29623 case NXGE_FM_EREPORT_IPP_ECC_ERR_MAX: 5396f45ec7bSml29623 case NXGE_FM_EREPORT_IPP_PFIFO_OVER: 5406f45ec7bSml29623 case NXGE_FM_EREPORT_IPP_PFIFO_UND: 5416f45ec7bSml29623 case NXGE_FM_EREPORT_IPP_BAD_CS_MX: 5426f45ec7bSml29623 case NXGE_FM_EREPORT_IPP_PKT_DIS_MX: 5436f45ec7bSml29623 case NXGE_FM_EREPORT_IPP_RESET_FAIL: 5446f45ec7bSml29623 IPP_REG_RD(nxgep->npi_handle, portn, IPP_INT_STATUS_REG, 5456f45ec7bSml29623 &ipps.value); 5466f45ec7bSml29623 if (err_id == NXGE_FM_EREPORT_IPP_EOP_MISS) 5476f45ec7bSml29623 ipps.bits.w0.dfifo_missed_eop = 1; 5486f45ec7bSml29623 else if (err_id == NXGE_FM_EREPORT_IPP_SOP_MISS) 5496f45ec7bSml29623 ipps.bits.w0.dfifo_missed_sop = 1; 5506f45ec7bSml29623 else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_UE) 5516f45ec7bSml29623 ipps.bits.w0.dfifo_uncorr_ecc_err = 1; 5526f45ec7bSml29623 else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_CE) 5536f45ec7bSml29623 ipps.bits.w0.dfifo_corr_ecc_err = 1; 5546f45ec7bSml29623 else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_PERR) 5556f45ec7bSml29623 ipps.bits.w0.pre_fifo_perr = 1; 556d710877aSyc148097 else if (err_id == NXGE_FM_EREPORT_IPP_ECC_ERR_MAX) { 557d710877aSyc148097 /* 558d710877aSyc148097 * Fill register IPP_ECC with max ECC-error- 559d710877aSyc148097 * counter value (0xff) to set the ECC_ERR_MAX bit 560d710877aSyc148097 * of the IPP_INT_STAT register and trigger an 561d710877aSyc148097 * FMA ereport. 562d710877aSyc148097 */ 563d710877aSyc148097 IPP_REG_WR(nxgep->npi_handle, portn, 564d710877aSyc148097 IPP_ECC_ERR_COUNTER_REG, IPP_ECC_CNT_MASK); 565d710877aSyc148097 } else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_OVER) 5666f45ec7bSml29623 ipps.bits.w0.pre_fifo_overrun = 1; 5676f45ec7bSml29623 else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_UND) 5686f45ec7bSml29623 ipps.bits.w0.pre_fifo_underrun = 1; 569d710877aSyc148097 else if (err_id == NXGE_FM_EREPORT_IPP_BAD_CS_MX) { 570d710877aSyc148097 /* 571d710877aSyc148097 * Fill IPP_BAD_CS_CNT with max bad-checksum-counter 572d710877aSyc148097 * value (0x3fff) to set the BAD_CS_MX bit of 573d710877aSyc148097 * IPP_INT_STAT and trigger an FMA ereport. 574d710877aSyc148097 */ 575d710877aSyc148097 IPP_REG_WR(nxgep->npi_handle, portn, 576f6485eecSyc148097 IPP_BAD_CKSUM_ERR_CNT_REG, IPP_BAD_CS_CNT_MASK); 577d710877aSyc148097 } else if (err_id == NXGE_FM_EREPORT_IPP_PKT_DIS_MX) { 578d710877aSyc148097 /* 579d710877aSyc148097 * Fill IPP_PKT_DIS with max packet-discard-counter 580d710877aSyc148097 * value (0x3fff) to set the PKT_DIS_MX bit of 581d710877aSyc148097 * IPP_INT_STAT and trigger an FMA ereport. 582d710877aSyc148097 */ 583d710877aSyc148097 IPP_REG_WR(nxgep->npi_handle, portn, 584d710877aSyc148097 IPP_DISCARD_PKT_CNT_REG, IPP_PKT_DIS_CNT_MASK); 585d710877aSyc148097 } 5866f45ec7bSml29623 cmn_err(CE_NOTE, "!Write 0x%llx to IPP_INT_STATUS_REG\n", 5876f45ec7bSml29623 (unsigned long long) ipps.value); 5886f45ec7bSml29623 IPP_REG_WR(nxgep->npi_handle, portn, IPP_INT_STATUS_REG, 5896f45ec7bSml29623 ipps.value); 5906f45ec7bSml29623 break; 5916f45ec7bSml29623 } 5926f45ec7bSml29623 } 5936f45ec7bSml29623 5946f45ec7bSml29623 /* ARGSUSED */ 5956f45ec7bSml29623 nxge_status_t 5966f45ec7bSml29623 nxge_ipp_fatal_err_recover(p_nxge_t nxgep) 5976f45ec7bSml29623 { 5986f45ec7bSml29623 npi_handle_t handle; 5996f45ec7bSml29623 npi_status_t rs = NPI_SUCCESS; 6006f45ec7bSml29623 nxge_status_t status = NXGE_OK; 6016f45ec7bSml29623 uint8_t portn; 6026f45ec7bSml29623 uint16_t wr_ptr; 6036f45ec7bSml29623 uint16_t rd_ptr; 6046f45ec7bSml29623 uint32_t try_count; 6056f45ec7bSml29623 uint32_t dfifo_entries; 6066f45ec7bSml29623 ipp_status_t istatus; 6076f45ec7bSml29623 uint32_t d0, d1, d2, d3, d4; 6086f45ec7bSml29623 int i; 6096f45ec7bSml29623 6106f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_ipp_fatal_err_recover")); 6116f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6126f45ec7bSml29623 "Recovering from RxPort error...")); 6136f45ec7bSml29623 6146f45ec7bSml29623 handle = nxgep->npi_handle; 6156f45ec7bSml29623 portn = nxgep->mac.portnum; 6166f45ec7bSml29623 6176f45ec7bSml29623 /* 6186f45ec7bSml29623 * Making sure that error source is cleared if this is an injected 6196f45ec7bSml29623 * error. 6206f45ec7bSml29623 */ 6216f45ec7bSml29623 IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0); 6226f45ec7bSml29623 6236f45ec7bSml29623 /* Disable RxMAC */ 6246f45ec7bSml29623 if (nxge_rx_mac_disable(nxgep) != NXGE_OK) 6256f45ec7bSml29623 goto fail; 6266f45ec7bSml29623 6276f45ec7bSml29623 /* When recovering from IPP, RxDMA channel resets are not necessary */ 6286f45ec7bSml29623 /* Reset ZCP CFIFO */ 6296f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset ZCP CFIFO...", portn)); 6306f45ec7bSml29623 if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS) 6316f45ec7bSml29623 goto fail; 6326f45ec7bSml29623 6336f45ec7bSml29623 /* 6346f45ec7bSml29623 * Wait until ip read and write fifo pointers are equal 6356f45ec7bSml29623 */ 6366f45ec7bSml29623 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 6376f45ec7bSml29623 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 6386f45ec7bSml29623 try_count = 512; 6396f45ec7bSml29623 6406f45ec7bSml29623 while ((try_count > 0) && (rd_ptr != wr_ptr)) { 6416f45ec7bSml29623 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr); 6426f45ec7bSml29623 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr); 6436f45ec7bSml29623 try_count--; 6446f45ec7bSml29623 } 6456f45ec7bSml29623 6466f45ec7bSml29623 if (try_count == 0) { 6476f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6486f45ec7bSml29623 " nxge_ipp_reset: port%d IPP stalled..." 6496f45ec7bSml29623 " rd_fifo_ptr = 0x%x wr_fifo_ptr = 0x%x", 6506f45ec7bSml29623 portn, rd_ptr, wr_ptr)); 6516f45ec7bSml29623 /* 6526f45ec7bSml29623 * This means the fatal error occurred on the first line of the 6536f45ec7bSml29623 * fifo. In this case, just reset the IPP without draining the 6546f45ec7bSml29623 * PFIFO. 6556f45ec7bSml29623 */ 6566f45ec7bSml29623 } 6576f45ec7bSml29623 65859ac0c16Sdavemq if (nxgep->niu_type == N2_NIU) { 65959ac0c16Sdavemq dfifo_entries = IPP_NIU_DFIFO_ENTRIES; 6602e59129aSraghus } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 6616f45ec7bSml29623 if (portn < 2) 6626f45ec7bSml29623 dfifo_entries = IPP_P0_P1_DFIFO_ENTRIES; 6636f45ec7bSml29623 else 6646f45ec7bSml29623 dfifo_entries = IPP_P2_P3_DFIFO_ENTRIES; 66559ac0c16Sdavemq } else { 6666f45ec7bSml29623 goto fail; 66759ac0c16Sdavemq } 6686f45ec7bSml29623 6696f45ec7bSml29623 /* Clean up DFIFO SRAM entries */ 6706f45ec7bSml29623 for (i = 0; i < dfifo_entries; i++) { 6716f45ec7bSml29623 if ((rs = npi_ipp_write_dfifo(handle, portn, 6726f45ec7bSml29623 i, 0, 0, 0, 0, 0)) != NPI_SUCCESS) 6736f45ec7bSml29623 goto fail; 6746f45ec7bSml29623 if ((rs = npi_ipp_read_dfifo(handle, portn, i, 6756f45ec7bSml29623 &d0, &d1, &d2, &d3, &d4)) != NPI_SUCCESS) 6766f45ec7bSml29623 goto fail; 6776f45ec7bSml29623 } 6786f45ec7bSml29623 6796f45ec7bSml29623 /* Clear PFIFO DFIFO status bits */ 6806f45ec7bSml29623 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 6816f45ec7bSml29623 goto fail; 6826f45ec7bSml29623 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS) 6836f45ec7bSml29623 goto fail; 6846f45ec7bSml29623 6856f45ec7bSml29623 /* Reset IPP */ 6866f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset IPP...", portn)); 6876f45ec7bSml29623 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) 6886f45ec7bSml29623 goto fail; 6896f45ec7bSml29623 6906f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset RxMAC...", portn)); 6916f45ec7bSml29623 if (nxge_rx_mac_reset(nxgep) != NXGE_OK) 6926f45ec7bSml29623 goto fail; 6936f45ec7bSml29623 6946f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Initialize RxMAC...", portn)); 6956f45ec7bSml29623 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 6966f45ec7bSml29623 goto fail; 6976f45ec7bSml29623 6986f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Enable RxMAC...", portn)); 6996f45ec7bSml29623 if (nxge_rx_mac_enable(nxgep) != NXGE_OK) 7006f45ec7bSml29623 goto fail; 7016f45ec7bSml29623 7026f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 703d710877aSyc148097 "Recovery successful, RxPort restored")); 7046f45ec7bSml29623 NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_ipp_fatal_err_recover")); 7056f45ec7bSml29623 7066f45ec7bSml29623 return (NXGE_OK); 7076f45ec7bSml29623 fail: 7086f45ec7bSml29623 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed")); 7096f45ec7bSml29623 return (status | rs); 7106f45ec7bSml29623 } 7116f45ec7bSml29623 7126f45ec7bSml29623 /* ARGSUSED */ 7131a4557b6Syc148097 /* 71453f3d8ecSyc148097 * A hardware bug may cause fake ECCUEs (ECC Uncorrectable Error). 7151a4557b6Syc148097 * This function checks if a ECCUE is real(valid) or not. It is not 7161a4557b6Syc148097 * real if rd_ptr == wr_ptr. 7171a4557b6Syc148097 * The hardware module that has the bug is used not only by the IPP 7181a4557b6Syc148097 * FIFO but also by the ZCP FIFO, therefore this function is also 7191a4557b6Syc148097 * called by nxge_zcp_handle_sys_errors for validating the ZCP FIFO 7201a4557b6Syc148097 * error. 7211a4557b6Syc148097 */ 7226f45ec7bSml29623 nxge_status_t 7236f45ec7bSml29623 nxge_ipp_eccue_valid_check(p_nxge_t nxgep, boolean_t *valid) 7246f45ec7bSml29623 { 7256f45ec7bSml29623 npi_handle_t handle; 7266f45ec7bSml29623 npi_status_t rs = NPI_SUCCESS; 7276f45ec7bSml29623 uint8_t portn; 7286f45ec7bSml29623 uint16_t rd_ptr; 7296f45ec7bSml29623 uint16_t wr_ptr; 7306f45ec7bSml29623 uint16_t curr_rd_ptr; 7316f45ec7bSml29623 uint16_t curr_wr_ptr; 7326f45ec7bSml29623 uint32_t stall_cnt; 7336f45ec7bSml29623 uint32_t d0, d1, d2, d3, d4; 7346f45ec7bSml29623 7356f45ec7bSml29623 handle = nxgep->npi_handle; 7366f45ec7bSml29623 portn = nxgep->mac.portnum; 7376f45ec7bSml29623 *valid = B_TRUE; 7386f45ec7bSml29623 7396f45ec7bSml29623 if ((rs = npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr)) 7406f45ec7bSml29623 != NPI_SUCCESS) 7416f45ec7bSml29623 goto fail; 7421a4557b6Syc148097 if ((rs = npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr)) 7436f45ec7bSml29623 != NPI_SUCCESS) 7446f45ec7bSml29623 goto fail; 7456f45ec7bSml29623 7466f45ec7bSml29623 if (rd_ptr == wr_ptr) { 7471a4557b6Syc148097 *valid = B_FALSE; /* FIFO not stuck, so it's not a real ECCUE */ 7486f45ec7bSml29623 } else { 7496f45ec7bSml29623 stall_cnt = 0; 750ee5416c9Syc148097 /* 751ee5416c9Syc148097 * Check if the two pointers are moving, the ECCUE is invali 752ee5416c9Syc148097 * if either pointer is moving, which indicates that the FIFO 753ee5416c9Syc148097 * is functional. 754ee5416c9Syc148097 */ 7556f45ec7bSml29623 while (stall_cnt < 16) { 7566f45ec7bSml29623 if ((rs = npi_ipp_get_dfifo_rd_ptr(handle, 7576f45ec7bSml29623 portn, &curr_rd_ptr)) != NPI_SUCCESS) 7586f45ec7bSml29623 goto fail; 7596f45ec7bSml29623 if ((rs = npi_ipp_get_dfifo_wr_ptr(handle, 7606f45ec7bSml29623 portn, &curr_wr_ptr)) != NPI_SUCCESS) 7616f45ec7bSml29623 goto fail; 7626f45ec7bSml29623 763ee5416c9Syc148097 if (rd_ptr == curr_rd_ptr && wr_ptr == curr_wr_ptr) { 7646f45ec7bSml29623 stall_cnt++; 765ee5416c9Syc148097 } else { 7666f45ec7bSml29623 *valid = B_FALSE; 7676f45ec7bSml29623 break; 7686f45ec7bSml29623 } 7696f45ec7bSml29623 } 7706f45ec7bSml29623 7716f45ec7bSml29623 if (valid) { 772ee5416c9Syc148097 /* 773d710877aSyc148097 * Further check to see if the ECCUE is valid. The 774ee5416c9Syc148097 * error is real if the LSB of d4 is 1, which 775ee5416c9Syc148097 * indicates that the data that has set the ECC 776ee5416c9Syc148097 * error flag is the 16-byte internal control word. 777ee5416c9Syc148097 */ 778ee5416c9Syc148097 if ((rs = npi_ipp_read_dfifo(handle, portn, rd_ptr, 779ee5416c9Syc148097 &d0, &d1, &d2, &d3, &d4)) != NPI_SUCCESS) 7806f45ec7bSml29623 goto fail; 7816f45ec7bSml29623 if ((d4 & 0x1) == 0) /* Not the 1st line */ 7826f45ec7bSml29623 *valid = B_FALSE; 7836f45ec7bSml29623 } 7846f45ec7bSml29623 } 7856f45ec7bSml29623 return (NXGE_OK); 7866f45ec7bSml29623 fail: 7876f45ec7bSml29623 return (NXGE_ERROR | rs); 7886f45ec7bSml29623 } 789