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 /*
2263e23a19Syc * 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_ipp.h>
2844961713Sgirish
2914ea4bb7Ssd #define NXGE_IPP_FIFO_SYNC_TRY_COUNT 100
3014ea4bb7Ssd
31a3c5bd6dSspeer /* ARGSUSED */
3244961713Sgirish nxge_status_t
nxge_ipp_init(p_nxge_t nxgep)3344961713Sgirish nxge_ipp_init(p_nxge_t nxgep)
3444961713Sgirish {
35a3c5bd6dSspeer uint8_t portn;
36a3c5bd6dSspeer uint32_t config;
37a3c5bd6dSspeer npi_handle_t handle;
38a3c5bd6dSspeer uint32_t pkt_size;
39a3c5bd6dSspeer ipp_status_t istatus;
40a3c5bd6dSspeer npi_status_t rs = NPI_SUCCESS;
41a3c5bd6dSspeer uint64_t val;
42a3c5bd6dSspeer uint32_t d0, d1, d2, d3, d4;
43a3c5bd6dSspeer int i;
44a3c5bd6dSspeer uint32_t dfifo_entries;
4544961713Sgirish
4644961713Sgirish handle = nxgep->npi_handle;
4744961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num);
4844961713Sgirish
4944961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_init: port%d", portn));
5044961713Sgirish
5144961713Sgirish /* Initialize ECC and parity in SRAM of DFIFO and PFIFO */
5259ac0c16Sdavemq if (nxgep->niu_type == N2_NIU) {
5359ac0c16Sdavemq dfifo_entries = IPP_NIU_DFIFO_ENTRIES;
542e59129aSraghus } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
5544961713Sgirish if (portn < 2)
5644961713Sgirish dfifo_entries = IPP_P0_P1_DFIFO_ENTRIES;
5744961713Sgirish else
5844961713Sgirish dfifo_entries = IPP_P2_P3_DFIFO_ENTRIES;
5959ac0c16Sdavemq } else {
6044961713Sgirish goto fail;
6159ac0c16Sdavemq }
6244961713Sgirish
6344961713Sgirish for (i = 0; i < dfifo_entries; i++) {
64a3c5bd6dSspeer if ((rs = npi_ipp_write_dfifo(handle,
6552ccf843Smisaki portn, i, 0, 0, 0, 0, 0)) != NPI_SUCCESS)
6644961713Sgirish goto fail;
67a3c5bd6dSspeer if ((rs = npi_ipp_read_dfifo(handle, portn,
6852ccf843Smisaki i, &d0, &d1, &d2, &d3, &d4)) != NPI_SUCCESS)
6944961713Sgirish goto fail;
7044961713Sgirish }
7144961713Sgirish
7244961713Sgirish /* Clear PFIFO DFIFO status bits */
7344961713Sgirish if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
7444961713Sgirish goto fail;
7544961713Sgirish if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
7644961713Sgirish goto fail;
7744961713Sgirish
7844961713Sgirish /*
7944961713Sgirish * Soft reset to make sure we bring the FIFO pointers back to the
8044961713Sgirish * original initial position.
8144961713Sgirish */
8244961713Sgirish if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS)
8344961713Sgirish goto fail;
8444961713Sgirish
8544961713Sgirish /* Clean up ECC counter */
8644961713Sgirish IPP_REG_RD(nxgep->npi_handle, portn, IPP_ECC_ERR_COUNTER_REG, &val);
87f6485eecSyc IPP_REG_RD(nxgep->npi_handle, portn, IPP_BAD_CKSUM_ERR_CNT_REG, &val);
8844961713Sgirish IPP_REG_RD(nxgep->npi_handle, portn, IPP_DISCARD_PKT_CNT_REG, &val);
8944961713Sgirish
9044961713Sgirish if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
9144961713Sgirish goto fail;
9244961713Sgirish
9344961713Sgirish /* Configure IPP port */
9444961713Sgirish if ((rs = npi_ipp_iconfig(handle, INIT, portn, ICFG_IPP_ALL))
9552ccf843Smisaki != NPI_SUCCESS)
9644961713Sgirish goto fail;
9744961713Sgirish nxgep->ipp.iconfig = ICFG_IPP_ALL;
9844961713Sgirish
9944961713Sgirish config = CFG_IPP | CFG_IPP_DFIFO_ECC_CORRECT | CFG_IPP_DROP_BAD_CRC |
10052ccf843Smisaki CFG_IPP_TCP_UDP_CKSUM;
10144961713Sgirish if ((rs = npi_ipp_config(handle, INIT, portn, config)) != NPI_SUCCESS)
10244961713Sgirish goto fail;
10344961713Sgirish nxgep->ipp.config = config;
10444961713Sgirish
10544961713Sgirish /* Set max packet size */
10644961713Sgirish pkt_size = IPP_MAX_PKT_SIZE;
107a3c5bd6dSspeer if ((rs = npi_ipp_set_max_pktsize(handle, portn,
10852ccf843Smisaki IPP_MAX_PKT_SIZE)) != NPI_SUCCESS)
10944961713Sgirish goto fail;
11044961713Sgirish nxgep->ipp.max_pkt_size = pkt_size;
11144961713Sgirish
11244961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_init: port%d", portn));
11344961713Sgirish
11444961713Sgirish return (NXGE_OK);
11544961713Sgirish fail:
11644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
11752ccf843Smisaki "nxge_ipp_init: Fail to initialize IPP Port #%d\n",
11852ccf843Smisaki portn));
11944961713Sgirish return (NXGE_ERROR | rs);
12044961713Sgirish }
12144961713Sgirish
122a3c5bd6dSspeer /* ARGSUSED */
12344961713Sgirish nxge_status_t
nxge_ipp_disable(p_nxge_t nxgep)12444961713Sgirish nxge_ipp_disable(p_nxge_t nxgep)
12544961713Sgirish {
126a3c5bd6dSspeer uint8_t portn;
127a3c5bd6dSspeer uint32_t config;
128a3c5bd6dSspeer npi_handle_t handle;
129a3c5bd6dSspeer npi_status_t rs = NPI_SUCCESS;
13014ea4bb7Ssd uint16_t wr_ptr, rd_ptr;
13114ea4bb7Ssd uint32_t try_count;
13244961713Sgirish
13344961713Sgirish handle = nxgep->npi_handle;
13444961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num);
13544961713Sgirish
13644961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_disable: port%d", portn));
13714ea4bb7Ssd (void) nxge_rx_mac_disable(nxgep);
13814ea4bb7Ssd
13914ea4bb7Ssd /*
140a3c5bd6dSspeer * Wait until ip read and write fifo pointers are equal
14114ea4bb7Ssd */
14214ea4bb7Ssd (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
14314ea4bb7Ssd (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
14414ea4bb7Ssd try_count = NXGE_IPP_FIFO_SYNC_TRY_COUNT;
14514ea4bb7Ssd
14614ea4bb7Ssd while ((try_count > 0) && (rd_ptr != wr_ptr)) {
14714ea4bb7Ssd (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
14814ea4bb7Ssd (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
14914ea4bb7Ssd try_count--;
15014ea4bb7Ssd }
15114ea4bb7Ssd
15214ea4bb7Ssd if (try_count == 0) {
15314ea4bb7Ssd if ((rd_ptr != 0) && (wr_ptr != 1)) {
15414ea4bb7Ssd NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
15552ccf843Smisaki " nxge_ipp_disable: port%d failed"
15652ccf843Smisaki " rd_fifo != wr_fifo", portn));
15714ea4bb7Ssd goto fail;
15814ea4bb7Ssd }
15914ea4bb7Ssd }
16044961713Sgirish /* disable the IPP */
16144961713Sgirish config = nxgep->ipp.config;
162a3c5bd6dSspeer if ((rs = npi_ipp_config(handle, DISABLE,
16352ccf843Smisaki portn, config)) != NPI_SUCCESS)
16444961713Sgirish goto fail;
16544961713Sgirish
16644961713Sgirish /* IPP soft reset */
167a3c5bd6dSspeer if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS)
16844961713Sgirish goto fail;
16944961713Sgirish
17044961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_disable: port%d", portn));
17144961713Sgirish return (NXGE_OK);
17244961713Sgirish fail:
17344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
17452ccf843Smisaki "nxge_ipp_disable: Fail to disable IPP Port #%d\n", portn));
17544961713Sgirish return (NXGE_ERROR | rs);
17644961713Sgirish }
17744961713Sgirish
178a3c5bd6dSspeer /* ARGSUSED */
17944961713Sgirish nxge_status_t
nxge_ipp_reset(p_nxge_t nxgep)18044961713Sgirish nxge_ipp_reset(p_nxge_t nxgep)
18144961713Sgirish {
182a3c5bd6dSspeer uint8_t portn;
183a3c5bd6dSspeer uint32_t config;
184a3c5bd6dSspeer npi_handle_t handle;
185a3c5bd6dSspeer npi_status_t rs = NPI_SUCCESS;
18644961713Sgirish uint16_t wr_ptr, rd_ptr;
18744961713Sgirish uint32_t try_count;
188a3c5bd6dSspeer
18944961713Sgirish handle = nxgep->npi_handle;
19044961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num);
19144961713Sgirish
19244961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_reset: port%d", portn));
19344961713Sgirish
19444961713Sgirish /* disable the IPP */
19544961713Sgirish config = nxgep->ipp.config;
196a3c5bd6dSspeer if ((rs = npi_ipp_config(handle, DISABLE,
19752ccf843Smisaki portn, config)) != NPI_SUCCESS)
19844961713Sgirish goto fail;
19944961713Sgirish
20044961713Sgirish /*
201a3c5bd6dSspeer * Wait until ip read and write fifo pointers are equal
20244961713Sgirish */
20344961713Sgirish (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
20444961713Sgirish (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
20514ea4bb7Ssd try_count = NXGE_IPP_FIFO_SYNC_TRY_COUNT;
20644961713Sgirish
20744961713Sgirish while ((try_count > 0) && (rd_ptr != wr_ptr)) {
20844961713Sgirish (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
20944961713Sgirish (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
21044961713Sgirish try_count--;
21144961713Sgirish }
21244961713Sgirish
21344961713Sgirish if (try_count == 0) {
21414ea4bb7Ssd if ((rd_ptr != 0) && (wr_ptr != 1)) {
21514ea4bb7Ssd NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
21652ccf843Smisaki " nxge_ipp_disable: port%d failed"
21752ccf843Smisaki " rd_fifo != wr_fifo", portn));
21814ea4bb7Ssd goto fail;
21914ea4bb7Ssd }
22044961713Sgirish }
22144961713Sgirish
22244961713Sgirish /* IPP soft reset */
22344961713Sgirish if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) {
22444961713Sgirish goto fail;
22544961713Sgirish }
22644961713Sgirish
22744961713Sgirish /* to reset control FIFO */
228a3c5bd6dSspeer if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS)
22944961713Sgirish goto fail;
23044961713Sgirish
23144961713Sgirish /*
232a3c5bd6dSspeer * Making sure that error source is cleared if this is an injected
233a3c5bd6dSspeer * error.
23444961713Sgirish */
23544961713Sgirish IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0);
23644961713Sgirish
23744961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_reset: port%d", portn));
23844961713Sgirish return (NXGE_OK);
23944961713Sgirish fail:
24044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
24152ccf843Smisaki "nxge_ipp_init: Fail to Reset IPP Port #%d\n",
24252ccf843Smisaki portn));
24344961713Sgirish return (NXGE_ERROR | rs);
24444961713Sgirish }
24544961713Sgirish
246a3c5bd6dSspeer /* ARGSUSED */
24744961713Sgirish nxge_status_t
nxge_ipp_enable(p_nxge_t nxgep)24844961713Sgirish nxge_ipp_enable(p_nxge_t nxgep)
24944961713Sgirish {
250a3c5bd6dSspeer uint8_t portn;
251a3c5bd6dSspeer uint32_t config;
252a3c5bd6dSspeer npi_handle_t handle;
253a3c5bd6dSspeer uint32_t pkt_size;
254a3c5bd6dSspeer npi_status_t rs = NPI_SUCCESS;
25544961713Sgirish
25644961713Sgirish handle = nxgep->npi_handle;
25744961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num);
25844961713Sgirish
25944961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_enable: port%d", portn));
26044961713Sgirish
26144961713Sgirish config = CFG_IPP | CFG_IPP_DFIFO_ECC_CORRECT | CFG_IPP_DROP_BAD_CRC |
26252ccf843Smisaki CFG_IPP_TCP_UDP_CKSUM;
26344961713Sgirish if ((rs = npi_ipp_config(handle, INIT, portn, config)) != NPI_SUCCESS)
26444961713Sgirish goto fail;
26544961713Sgirish nxgep->ipp.config = config;
26644961713Sgirish
26744961713Sgirish /* Set max packet size */
26844961713Sgirish pkt_size = IPP_MAX_PKT_SIZE;
269a3c5bd6dSspeer if ((rs = npi_ipp_set_max_pktsize(handle, portn,
27052ccf843Smisaki IPP_MAX_PKT_SIZE)) != NPI_SUCCESS)
27144961713Sgirish goto fail;
27244961713Sgirish nxgep->ipp.max_pkt_size = pkt_size;
27344961713Sgirish
27444961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_enable: port%d", portn));
27544961713Sgirish return (NXGE_OK);
27644961713Sgirish fail:
27744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
27852ccf843Smisaki "nxge_ipp_init: Fail to Enable IPP Port #%d\n", portn));
27944961713Sgirish return (NXGE_ERROR | rs);
28044961713Sgirish }
28144961713Sgirish
282678453a8Sspeer /* ARGSUSED */
283678453a8Sspeer nxge_status_t
nxge_ipp_drain(p_nxge_t nxgep)284678453a8Sspeer nxge_ipp_drain(p_nxge_t nxgep)
285678453a8Sspeer {
286678453a8Sspeer uint8_t portn;
287678453a8Sspeer npi_handle_t handle;
288678453a8Sspeer npi_status_t rs = NPI_SUCCESS;
289678453a8Sspeer uint16_t wr_ptr, rd_ptr;
290678453a8Sspeer uint32_t try_count;
291678453a8Sspeer
292678453a8Sspeer handle = nxgep->npi_handle;
293678453a8Sspeer portn = NXGE_GET_PORT_NUM(nxgep->function_num);
294678453a8Sspeer
295678453a8Sspeer NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_drain: port%d", portn));
296678453a8Sspeer
297678453a8Sspeer /*
298678453a8Sspeer * Wait until ip read and write fifo pointers are equal
299678453a8Sspeer */
300678453a8Sspeer (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
301678453a8Sspeer (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
302678453a8Sspeer try_count = NXGE_IPP_FIFO_SYNC_TRY_COUNT;
303678453a8Sspeer
304678453a8Sspeer while ((try_count > 0) && (rd_ptr != wr_ptr)) {
305678453a8Sspeer (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
306678453a8Sspeer (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
307678453a8Sspeer try_count--;
308678453a8Sspeer }
309678453a8Sspeer
310678453a8Sspeer if (try_count == 0) {
311678453a8Sspeer if ((rd_ptr != 0) && (wr_ptr != 1)) {
312678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
313678453a8Sspeer " nxge_ipp_drain: port%d failed"
314678453a8Sspeer " rd_fifo != wr_fifo", portn));
315678453a8Sspeer goto fail;
316678453a8Sspeer }
317678453a8Sspeer }
318678453a8Sspeer
319678453a8Sspeer NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_drain: port%d", portn));
320678453a8Sspeer return (NXGE_OK);
321678453a8Sspeer fail:
322678453a8Sspeer NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_ipp_init: "
323678453a8Sspeer "Fail to Reset IPP Port #%d\n", portn));
324678453a8Sspeer return (NXGE_ERROR | rs);
325678453a8Sspeer }
326678453a8Sspeer
327a3c5bd6dSspeer /* ARGSUSED */
32844961713Sgirish nxge_status_t
nxge_ipp_handle_sys_errors(p_nxge_t nxgep)32944961713Sgirish nxge_ipp_handle_sys_errors(p_nxge_t nxgep)
33044961713Sgirish {
331a3c5bd6dSspeer npi_handle_t handle;
332a3c5bd6dSspeer npi_status_t rs = NPI_SUCCESS;
333a3c5bd6dSspeer p_nxge_ipp_stats_t statsp;
334a3c5bd6dSspeer ipp_status_t istatus;
335a3c5bd6dSspeer uint8_t portn;
336a3c5bd6dSspeer p_ipp_errlog_t errlogp;
337a3c5bd6dSspeer boolean_t rxport_fatal = B_FALSE;
338a3c5bd6dSspeer nxge_status_t status = NXGE_OK;
33953f3d8ecSyc uint8_t cnt8;
34053f3d8ecSyc uint16_t cnt16;
34144961713Sgirish
34244961713Sgirish handle = nxgep->npi_handle;
34344961713Sgirish statsp = (p_nxge_ipp_stats_t)&nxgep->statsp->ipp_stats;
34444961713Sgirish portn = nxgep->mac.portnum;
34544961713Sgirish
34644961713Sgirish errlogp = (p_ipp_errlog_t)&statsp->errlog;
34744961713Sgirish
34844961713Sgirish if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
34944961713Sgirish return (NXGE_ERROR | rs);
35044961713Sgirish
351a3c5bd6dSspeer if (istatus.value == 0) {
35244961713Sgirish /*
35344961713Sgirish * The error is not initiated from this port, so just exit.
35444961713Sgirish */
35544961713Sgirish return (NXGE_OK);
356a3c5bd6dSspeer }
35744961713Sgirish
35844961713Sgirish if (istatus.bits.w0.dfifo_missed_sop) {
35944961713Sgirish statsp->sop_miss++;
36044961713Sgirish if ((rs = npi_ipp_get_dfifo_eopm_rdptr(handle, portn,
36152ccf843Smisaki &errlogp->dfifo_rd_ptr)) != NPI_SUCCESS)
36244961713Sgirish return (NXGE_ERROR | rs);
36344961713Sgirish if ((rs = npi_ipp_get_state_mach(handle, portn,
36452ccf843Smisaki &errlogp->state_mach)) != NPI_SUCCESS)
36544961713Sgirish return (NXGE_ERROR | rs);
366b37cc459SToomas Soome NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
36752ccf843Smisaki NXGE_FM_EREPORT_IPP_SOP_MISS);
36844961713Sgirish if (statsp->sop_miss < IPP_MAX_ERR_SHOW)
36944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
37052ccf843Smisaki "nxge_ipp_err_evnts: fatal error: sop_miss\n"));
37144961713Sgirish rxport_fatal = B_TRUE;
37244961713Sgirish }
37344961713Sgirish if (istatus.bits.w0.dfifo_missed_eop) {
37444961713Sgirish statsp->eop_miss++;
37544961713Sgirish if ((rs = npi_ipp_get_dfifo_eopm_rdptr(handle, portn,
37652ccf843Smisaki &errlogp->dfifo_rd_ptr)) != NPI_SUCCESS)
37744961713Sgirish return (NXGE_ERROR | rs);
37844961713Sgirish if ((rs = npi_ipp_get_state_mach(handle, portn,
37952ccf843Smisaki &errlogp->state_mach)) != NPI_SUCCESS)
38044961713Sgirish return (NXGE_ERROR | rs);
381b37cc459SToomas Soome NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
38252ccf843Smisaki NXGE_FM_EREPORT_IPP_EOP_MISS);
38344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
38452ccf843Smisaki "nxge_ipp_err_evnts: fatal error: eop_miss\n"));
38544961713Sgirish rxport_fatal = B_TRUE;
38644961713Sgirish }
38744961713Sgirish if (istatus.bits.w0.dfifo_uncorr_ecc_err) {
38814ea4bb7Ssd boolean_t ue_ecc_valid;
38914ea4bb7Ssd
390a3c5bd6dSspeer if ((status = nxge_ipp_eccue_valid_check(nxgep,
39152ccf843Smisaki &ue_ecc_valid)) != NXGE_OK)
39214ea4bb7Ssd return (status);
39314ea4bb7Ssd
39414ea4bb7Ssd if (ue_ecc_valid) {
39514ea4bb7Ssd statsp->dfifo_ue++;
39614ea4bb7Ssd if ((rs = npi_ipp_get_ecc_syndrome(handle, portn,
39752ccf843Smisaki &errlogp->ecc_syndrome)) != NPI_SUCCESS)
39814ea4bb7Ssd return (NXGE_ERROR | rs);
399b37cc459SToomas Soome NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
40052ccf843Smisaki NXGE_FM_EREPORT_IPP_DFIFO_UE);
40114ea4bb7Ssd NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
40252ccf843Smisaki "nxge_ipp_err_evnts: fatal error: dfifo_ue\n"));
40314ea4bb7Ssd rxport_fatal = B_TRUE;
40414ea4bb7Ssd }
40544961713Sgirish }
40644961713Sgirish if (istatus.bits.w0.pre_fifo_perr) {
40744961713Sgirish statsp->pfifo_perr++;
408b37cc459SToomas Soome NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
40952ccf843Smisaki NXGE_FM_EREPORT_IPP_PFIFO_PERR);
41044961713Sgirish if (statsp->pfifo_perr < IPP_MAX_ERR_SHOW)
41144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
41252ccf843Smisaki "nxge_ipp_err_evnts: "
41352ccf843Smisaki "fatal error: pre_pifo_perr\n"));
41444961713Sgirish rxport_fatal = B_TRUE;
41544961713Sgirish }
41644961713Sgirish if (istatus.bits.w0.pre_fifo_overrun) {
41744961713Sgirish statsp->pfifo_over++;
418b37cc459SToomas Soome NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
41952ccf843Smisaki NXGE_FM_EREPORT_IPP_PFIFO_OVER);
42044961713Sgirish if (statsp->pfifo_over < IPP_MAX_ERR_SHOW)
42144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
42252ccf843Smisaki "nxge_ipp_err_evnts: "
42352ccf843Smisaki "fatal error: pfifo_over\n"));
42444961713Sgirish rxport_fatal = B_TRUE;
42544961713Sgirish }
42644961713Sgirish if (istatus.bits.w0.pre_fifo_underrun) {
42744961713Sgirish statsp->pfifo_und++;
428b37cc459SToomas Soome NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
42952ccf843Smisaki NXGE_FM_EREPORT_IPP_PFIFO_UND);
43044961713Sgirish if (statsp->pfifo_und < IPP_MAX_ERR_SHOW)
43144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
43252ccf843Smisaki "nxge_ipp_err_evnts: "
43352ccf843Smisaki "fatal error: pfifo_und\n"));
43444961713Sgirish rxport_fatal = B_TRUE;
43544961713Sgirish }
43644961713Sgirish if (istatus.bits.w0.bad_cksum_cnt_ovfl) {
437d710877aSyc /*
43863e23a19Syc * Do not send FMA ereport or log error message
43963e23a19Syc * in /var/adm/messages because this error does not
44063e23a19Syc * indicate a HW failure.
44163e23a19Syc *
442d710877aSyc * Clear bit BAD_CS_MX of register IPP_INT_STAT
443d710877aSyc * by reading register IPP_BAD_CS_CNT
444d710877aSyc */
44553f3d8ecSyc (void) npi_ipp_get_cs_err_count(handle, portn, &cnt16);
44644961713Sgirish statsp->bad_cs_cnt += IPP_BAD_CS_CNT_MASK;
44744961713Sgirish }
44844961713Sgirish if (istatus.bits.w0.pkt_discard_cnt_ovfl) {
449d710877aSyc /*
45063e23a19Syc * Do not send FMA ereport or log error message
45163e23a19Syc * in /var/adm/messages because this error does not
45263e23a19Syc * indicate a HW failure.
45363e23a19Syc *
454d710877aSyc * Clear bit PKT_DIS_MX of register IPP_INT_STAT
455d710877aSyc * by reading register IPP_PKT_DIS
456d710877aSyc */
45753f3d8ecSyc (void) npi_ipp_get_pkt_dis_count(handle, portn, &cnt16);
45844961713Sgirish statsp->pkt_dis_cnt += IPP_PKT_DIS_CNT_MASK;
45944961713Sgirish }
46053f3d8ecSyc if (istatus.bits.w0.ecc_err_cnt_ovfl) {
461d710877aSyc /*
462d710877aSyc * Clear bit ECC_ERR_MAX of register IPP_INI_STAT
463d710877aSyc * by reading register IPP_ECC
464d710877aSyc */
46553f3d8ecSyc (void) npi_ipp_get_ecc_err_count(handle, portn, &cnt8);
46653f3d8ecSyc statsp->ecc_err_cnt += IPP_ECC_CNT_MASK;
467f6485eecSyc /*
468f6485eecSyc * A defect in Neptune port2's IPP module could generate
469f6485eecSyc * many fake but harmless ECC errors under stress and cause
470f6485eecSyc * the ecc-error-counter register IPP_ECC to reach its
471f6485eecSyc * maximum value in a few seconds. To avoid false alarm, do
472f6485eecSyc * not report the error if it is port2.
473f6485eecSyc */
474f6485eecSyc if (portn != 2) {
475b37cc459SToomas Soome NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
476f6485eecSyc NXGE_FM_EREPORT_IPP_ECC_ERR_MAX);
477f6485eecSyc if (statsp->ecc_err_cnt < (IPP_MAX_ERR_SHOW *
478f6485eecSyc IPP_ECC_CNT_MASK)) {
479f6485eecSyc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
480f6485eecSyc "nxge_ipp_err_evnts: pkt_ecc_err_max\n"));
481f6485eecSyc }
482f6485eecSyc }
48353f3d8ecSyc }
48444961713Sgirish /*
485a3c5bd6dSspeer * Making sure that error source is cleared if this is an injected
486a3c5bd6dSspeer * error.
48744961713Sgirish */
48844961713Sgirish IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0);
48944961713Sgirish
49044961713Sgirish if (rxport_fatal) {
49144961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL,
49252ccf843Smisaki " nxge_ipp_handle_sys_errors:"
49352ccf843Smisaki " fatal Error on Port #%d\n", portn));
49444961713Sgirish status = nxge_ipp_fatal_err_recover(nxgep);
49544961713Sgirish if (status == NXGE_OK) {
49644961713Sgirish FM_SERVICE_RESTORED(nxgep);
49744961713Sgirish }
49844961713Sgirish }
49944961713Sgirish return (status);
50044961713Sgirish }
50144961713Sgirish
502a3c5bd6dSspeer /* ARGSUSED */
50344961713Sgirish void
nxge_ipp_inject_err(p_nxge_t nxgep,uint32_t err_id)50444961713Sgirish nxge_ipp_inject_err(p_nxge_t nxgep, uint32_t err_id)
50544961713Sgirish {
506a3c5bd6dSspeer ipp_status_t ipps;
507a3c5bd6dSspeer ipp_ecc_ctrl_t ecc_ctrl;
508a3c5bd6dSspeer uint8_t portn = nxgep->mac.portnum;
50944961713Sgirish
51044961713Sgirish switch (err_id) {
51144961713Sgirish case NXGE_FM_EREPORT_IPP_DFIFO_UE:
51244961713Sgirish ecc_ctrl.value = 0;
51344961713Sgirish ecc_ctrl.bits.w0.cor_dbl = 1;
51444961713Sgirish ecc_ctrl.bits.w0.cor_1 = 1;
51544961713Sgirish ecc_ctrl.bits.w0.cor_lst = 1;
51644961713Sgirish cmn_err(CE_NOTE, "!Write 0x%llx to IPP_ECC_CTRL_REG\n",
51752ccf843Smisaki (unsigned long long) ecc_ctrl.value);
51844961713Sgirish IPP_REG_WR(nxgep->npi_handle, portn, IPP_ECC_CTRL_REG,
51952ccf843Smisaki ecc_ctrl.value);
52044961713Sgirish break;
521a3c5bd6dSspeer
52244961713Sgirish case NXGE_FM_EREPORT_IPP_DFIFO_CE:
52344961713Sgirish ecc_ctrl.value = 0;
52444961713Sgirish ecc_ctrl.bits.w0.cor_sng = 1;
52544961713Sgirish ecc_ctrl.bits.w0.cor_1 = 1;
52644961713Sgirish ecc_ctrl.bits.w0.cor_snd = 1;
52744961713Sgirish cmn_err(CE_NOTE, "!Write 0x%llx to IPP_ECC_CTRL_REG\n",
52852ccf843Smisaki (unsigned long long) ecc_ctrl.value);
52944961713Sgirish IPP_REG_WR(nxgep->npi_handle, portn, IPP_ECC_CTRL_REG,
53052ccf843Smisaki ecc_ctrl.value);
53144961713Sgirish break;
532a3c5bd6dSspeer
53344961713Sgirish case NXGE_FM_EREPORT_IPP_EOP_MISS:
53444961713Sgirish case NXGE_FM_EREPORT_IPP_SOP_MISS:
53544961713Sgirish case NXGE_FM_EREPORT_IPP_PFIFO_PERR:
53644961713Sgirish case NXGE_FM_EREPORT_IPP_ECC_ERR_MAX:
53744961713Sgirish case NXGE_FM_EREPORT_IPP_PFIFO_OVER:
53844961713Sgirish case NXGE_FM_EREPORT_IPP_PFIFO_UND:
53944961713Sgirish case NXGE_FM_EREPORT_IPP_BAD_CS_MX:
54044961713Sgirish case NXGE_FM_EREPORT_IPP_PKT_DIS_MX:
54144961713Sgirish case NXGE_FM_EREPORT_IPP_RESET_FAIL:
54244961713Sgirish IPP_REG_RD(nxgep->npi_handle, portn, IPP_INT_STATUS_REG,
54352ccf843Smisaki &ipps.value);
54444961713Sgirish if (err_id == NXGE_FM_EREPORT_IPP_EOP_MISS)
54544961713Sgirish ipps.bits.w0.dfifo_missed_eop = 1;
54644961713Sgirish else if (err_id == NXGE_FM_EREPORT_IPP_SOP_MISS)
54744961713Sgirish ipps.bits.w0.dfifo_missed_sop = 1;
54844961713Sgirish else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_UE)
54944961713Sgirish ipps.bits.w0.dfifo_uncorr_ecc_err = 1;
55044961713Sgirish else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_CE)
55144961713Sgirish ipps.bits.w0.dfifo_corr_ecc_err = 1;
55244961713Sgirish else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_PERR)
55344961713Sgirish ipps.bits.w0.pre_fifo_perr = 1;
554d710877aSyc else if (err_id == NXGE_FM_EREPORT_IPP_ECC_ERR_MAX) {
555d710877aSyc /*
556d710877aSyc * Fill register IPP_ECC with max ECC-error-
557d710877aSyc * counter value (0xff) to set the ECC_ERR_MAX bit
558d710877aSyc * of the IPP_INT_STAT register and trigger an
559d710877aSyc * FMA ereport.
560d710877aSyc */
561d710877aSyc IPP_REG_WR(nxgep->npi_handle, portn,
562d710877aSyc IPP_ECC_ERR_COUNTER_REG, IPP_ECC_CNT_MASK);
563d710877aSyc } else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_OVER)
56444961713Sgirish ipps.bits.w0.pre_fifo_overrun = 1;
56544961713Sgirish else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_UND)
56644961713Sgirish ipps.bits.w0.pre_fifo_underrun = 1;
567d710877aSyc else if (err_id == NXGE_FM_EREPORT_IPP_BAD_CS_MX) {
568d710877aSyc /*
569d710877aSyc * Fill IPP_BAD_CS_CNT with max bad-checksum-counter
570d710877aSyc * value (0x3fff) to set the BAD_CS_MX bit of
571d710877aSyc * IPP_INT_STAT and trigger an FMA ereport.
572d710877aSyc */
573d710877aSyc IPP_REG_WR(nxgep->npi_handle, portn,
574f6485eecSyc IPP_BAD_CKSUM_ERR_CNT_REG, IPP_BAD_CS_CNT_MASK);
575d710877aSyc } else if (err_id == NXGE_FM_EREPORT_IPP_PKT_DIS_MX) {
576d710877aSyc /*
577d710877aSyc * Fill IPP_PKT_DIS with max packet-discard-counter
578d710877aSyc * value (0x3fff) to set the PKT_DIS_MX bit of
579d710877aSyc * IPP_INT_STAT and trigger an FMA ereport.
580d710877aSyc */
581d710877aSyc IPP_REG_WR(nxgep->npi_handle, portn,
582d710877aSyc IPP_DISCARD_PKT_CNT_REG, IPP_PKT_DIS_CNT_MASK);
583d710877aSyc }
58444961713Sgirish cmn_err(CE_NOTE, "!Write 0x%llx to IPP_INT_STATUS_REG\n",
58552ccf843Smisaki (unsigned long long) ipps.value);
58644961713Sgirish IPP_REG_WR(nxgep->npi_handle, portn, IPP_INT_STATUS_REG,
58752ccf843Smisaki ipps.value);
58844961713Sgirish break;
58944961713Sgirish }
59044961713Sgirish }
59144961713Sgirish
592a3c5bd6dSspeer /* ARGSUSED */
59344961713Sgirish nxge_status_t
nxge_ipp_fatal_err_recover(p_nxge_t nxgep)59444961713Sgirish nxge_ipp_fatal_err_recover(p_nxge_t nxgep)
59544961713Sgirish {
596a3c5bd6dSspeer npi_handle_t handle;
597a3c5bd6dSspeer npi_status_t rs = NPI_SUCCESS;
598a3c5bd6dSspeer nxge_status_t status = NXGE_OK;
599a3c5bd6dSspeer uint8_t portn;
600a3c5bd6dSspeer uint16_t wr_ptr;
601a3c5bd6dSspeer uint16_t rd_ptr;
602a3c5bd6dSspeer uint32_t try_count;
603a3c5bd6dSspeer uint32_t dfifo_entries;
604a3c5bd6dSspeer ipp_status_t istatus;
605a3c5bd6dSspeer uint32_t d0, d1, d2, d3, d4;
606a3c5bd6dSspeer int i;
60744961713Sgirish
60844961713Sgirish NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_ipp_fatal_err_recover"));
60944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
61052ccf843Smisaki "Recovering from RxPort error..."));
61144961713Sgirish
61244961713Sgirish handle = nxgep->npi_handle;
61344961713Sgirish portn = nxgep->mac.portnum;
61444961713Sgirish
61544961713Sgirish /*
616a3c5bd6dSspeer * Making sure that error source is cleared if this is an injected
617a3c5bd6dSspeer * error.
61844961713Sgirish */
61944961713Sgirish IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0);
62044961713Sgirish
62144961713Sgirish /* Disable RxMAC */
62244961713Sgirish if (nxge_rx_mac_disable(nxgep) != NXGE_OK)
62344961713Sgirish goto fail;
62444961713Sgirish
62544961713Sgirish /* When recovering from IPP, RxDMA channel resets are not necessary */
62644961713Sgirish /* Reset ZCP CFIFO */
62744961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset ZCP CFIFO...", portn));
62844961713Sgirish if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS)
62944961713Sgirish goto fail;
63044961713Sgirish
63144961713Sgirish /*
632a3c5bd6dSspeer * Wait until ip read and write fifo pointers are equal
63344961713Sgirish */
63444961713Sgirish (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
63544961713Sgirish (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
63644961713Sgirish try_count = 512;
63744961713Sgirish
63844961713Sgirish while ((try_count > 0) && (rd_ptr != wr_ptr)) {
63944961713Sgirish (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
64044961713Sgirish (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
64144961713Sgirish try_count--;
64244961713Sgirish }
64344961713Sgirish
64444961713Sgirish if (try_count == 0) {
64544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
64652ccf843Smisaki " nxge_ipp_reset: port%d IPP stalled..."
64752ccf843Smisaki " rd_fifo_ptr = 0x%x wr_fifo_ptr = 0x%x",
64852ccf843Smisaki portn, rd_ptr, wr_ptr));
64944961713Sgirish /*
650a3c5bd6dSspeer * This means the fatal error occurred on the first line of the
651a3c5bd6dSspeer * fifo. In this case, just reset the IPP without draining the
652a3c5bd6dSspeer * PFIFO.
65344961713Sgirish */
65444961713Sgirish }
65544961713Sgirish
65659ac0c16Sdavemq if (nxgep->niu_type == N2_NIU) {
65759ac0c16Sdavemq dfifo_entries = IPP_NIU_DFIFO_ENTRIES;
6582e59129aSraghus } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
65944961713Sgirish if (portn < 2)
66044961713Sgirish dfifo_entries = IPP_P0_P1_DFIFO_ENTRIES;
66144961713Sgirish else
66244961713Sgirish dfifo_entries = IPP_P2_P3_DFIFO_ENTRIES;
66359ac0c16Sdavemq } else {
66444961713Sgirish goto fail;
66559ac0c16Sdavemq }
66644961713Sgirish
66744961713Sgirish /* Clean up DFIFO SRAM entries */
66844961713Sgirish for (i = 0; i < dfifo_entries; i++) {
669a3c5bd6dSspeer if ((rs = npi_ipp_write_dfifo(handle, portn,
67052ccf843Smisaki i, 0, 0, 0, 0, 0)) != NPI_SUCCESS)
67144961713Sgirish goto fail;
672a3c5bd6dSspeer if ((rs = npi_ipp_read_dfifo(handle, portn, i,
67352ccf843Smisaki &d0, &d1, &d2, &d3, &d4)) != NPI_SUCCESS)
67444961713Sgirish goto fail;
67544961713Sgirish }
67644961713Sgirish
67744961713Sgirish /* Clear PFIFO DFIFO status bits */
67844961713Sgirish if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
67944961713Sgirish goto fail;
68044961713Sgirish if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
68144961713Sgirish goto fail;
68244961713Sgirish
68344961713Sgirish /* Reset IPP */
68444961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset IPP...", portn));
68544961713Sgirish if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS)
68644961713Sgirish goto fail;
68744961713Sgirish
68844961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset RxMAC...", portn));
68944961713Sgirish if (nxge_rx_mac_reset(nxgep) != NXGE_OK)
69044961713Sgirish goto fail;
69144961713Sgirish
69244961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Initialize RxMAC...", portn));
69344961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
69444961713Sgirish goto fail;
69544961713Sgirish
69644961713Sgirish NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Enable RxMAC...", portn));
69744961713Sgirish if (nxge_rx_mac_enable(nxgep) != NXGE_OK)
69844961713Sgirish goto fail;
69944961713Sgirish
70044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
70152ccf843Smisaki "Recovery successful, RxPort restored"));
70244961713Sgirish NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_ipp_fatal_err_recover"));
70344961713Sgirish
70444961713Sgirish return (NXGE_OK);
70544961713Sgirish fail:
70644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed"));
70744961713Sgirish return (status | rs);
70844961713Sgirish }
70914ea4bb7Ssd
710a3c5bd6dSspeer /* ARGSUSED */
7111a4557b6Syc /*
71253f3d8ecSyc * A hardware bug may cause fake ECCUEs (ECC Uncorrectable Error).
7131a4557b6Syc * This function checks if a ECCUE is real(valid) or not. It is not
7141a4557b6Syc * real if rd_ptr == wr_ptr.
7151a4557b6Syc * The hardware module that has the bug is used not only by the IPP
7161a4557b6Syc * FIFO but also by the ZCP FIFO, therefore this function is also
7171a4557b6Syc * called by nxge_zcp_handle_sys_errors for validating the ZCP FIFO
7181a4557b6Syc * error.
7191a4557b6Syc */
72014ea4bb7Ssd nxge_status_t
nxge_ipp_eccue_valid_check(p_nxge_t nxgep,boolean_t * valid)72114ea4bb7Ssd nxge_ipp_eccue_valid_check(p_nxge_t nxgep, boolean_t *valid)
72214ea4bb7Ssd {
72314ea4bb7Ssd npi_handle_t handle;
72414ea4bb7Ssd npi_status_t rs = NPI_SUCCESS;
72514ea4bb7Ssd uint8_t portn;
72614ea4bb7Ssd uint16_t rd_ptr;
72714ea4bb7Ssd uint16_t wr_ptr;
72814ea4bb7Ssd uint16_t curr_rd_ptr;
72914ea4bb7Ssd uint16_t curr_wr_ptr;
73014ea4bb7Ssd uint32_t stall_cnt;
73114ea4bb7Ssd uint32_t d0, d1, d2, d3, d4;
73214ea4bb7Ssd
73314ea4bb7Ssd handle = nxgep->npi_handle;
73414ea4bb7Ssd portn = nxgep->mac.portnum;
73514ea4bb7Ssd *valid = B_TRUE;
73614ea4bb7Ssd
73714ea4bb7Ssd if ((rs = npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr))
73852ccf843Smisaki != NPI_SUCCESS)
73914ea4bb7Ssd goto fail;
7401a4557b6Syc if ((rs = npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr))
74152ccf843Smisaki != NPI_SUCCESS)
74214ea4bb7Ssd goto fail;
74314ea4bb7Ssd
74414ea4bb7Ssd if (rd_ptr == wr_ptr) {
7451a4557b6Syc *valid = B_FALSE; /* FIFO not stuck, so it's not a real ECCUE */
74614ea4bb7Ssd } else {
74714ea4bb7Ssd stall_cnt = 0;
748ee5416c9Syc /*
749ee5416c9Syc * Check if the two pointers are moving, the ECCUE is invali
750ee5416c9Syc * if either pointer is moving, which indicates that the FIFO
751ee5416c9Syc * is functional.
752ee5416c9Syc */
75314ea4bb7Ssd while (stall_cnt < 16) {
754a3c5bd6dSspeer if ((rs = npi_ipp_get_dfifo_rd_ptr(handle,
75552ccf843Smisaki portn, &curr_rd_ptr)) != NPI_SUCCESS)
75614ea4bb7Ssd goto fail;
757a3c5bd6dSspeer if ((rs = npi_ipp_get_dfifo_wr_ptr(handle,
75852ccf843Smisaki portn, &curr_wr_ptr)) != NPI_SUCCESS)
75914ea4bb7Ssd goto fail;
76014ea4bb7Ssd
761ee5416c9Syc if (rd_ptr == curr_rd_ptr && wr_ptr == curr_wr_ptr) {
76214ea4bb7Ssd stall_cnt++;
763ee5416c9Syc } else {
76414ea4bb7Ssd *valid = B_FALSE;
76514ea4bb7Ssd break;
76614ea4bb7Ssd }
76714ea4bb7Ssd }
76814ea4bb7Ssd
769*4df3b64dSToomas Soome if (*valid) {
770ee5416c9Syc /*
771d710877aSyc * Further check to see if the ECCUE is valid. The
772ee5416c9Syc * error is real if the LSB of d4 is 1, which
773ee5416c9Syc * indicates that the data that has set the ECC
774ee5416c9Syc * error flag is the 16-byte internal control word.
775ee5416c9Syc */
776ee5416c9Syc if ((rs = npi_ipp_read_dfifo(handle, portn, rd_ptr,
777ee5416c9Syc &d0, &d1, &d2, &d3, &d4)) != NPI_SUCCESS)
77814ea4bb7Ssd goto fail;
77914ea4bb7Ssd if ((d4 & 0x1) == 0) /* Not the 1st line */
78014ea4bb7Ssd *valid = B_FALSE;
78114ea4bb7Ssd }
78214ea4bb7Ssd }
78314ea4bb7Ssd return (NXGE_OK);
78414ea4bb7Ssd fail:
78514ea4bb7Ssd return (NXGE_ERROR | rs);
78614ea4bb7Ssd }
787