blob: deb1ad0b985265e97a4da3a233b803c278deb74c [file] [log] [blame]
girish44961712006-11-22 11:47:19 -08001/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
yc14809763e23a12008-03-10 18:33:37 -070022 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
girish44961712006-11-22 11:47:19 -080023 * Use is subject to license terms.
24 */
25
26#pragma ident "%Z%%M% %I% %E% SMI"
27
28#include <nxge_impl.h>
29#include <nxge_ipp.h>
30
sd7746814ea4bb2006-12-22 12:42:28 -080031#define NXGE_IPP_FIFO_SYNC_TRY_COUNT 100
32
speera3c5bd62007-01-30 11:29:19 -080033/* ARGSUSED */
girish44961712006-11-22 11:47:19 -080034nxge_status_t
35nxge_ipp_init(p_nxge_t nxgep)
36{
speera3c5bd62007-01-30 11:29:19 -080037 uint8_t portn;
38 uint32_t config;
39 npi_handle_t handle;
40 uint32_t pkt_size;
41 ipp_status_t istatus;
42 npi_status_t rs = NPI_SUCCESS;
43 uint64_t val;
44 uint32_t d0, d1, d2, d3, d4;
45 int i;
46 uint32_t dfifo_entries;
girish44961712006-11-22 11:47:19 -080047
48 handle = nxgep->npi_handle;
49 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
50
51 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_init: port%d", portn));
52
53 /* Initialize ECC and parity in SRAM of DFIFO and PFIFO */
davemq59ac0c12007-07-25 18:20:14 -070054 if (nxgep->niu_type == N2_NIU) {
55 dfifo_entries = IPP_NIU_DFIFO_ENTRIES;
raghus2e591292007-08-31 16:49:49 -070056 } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
girish44961712006-11-22 11:47:19 -080057 if (portn < 2)
58 dfifo_entries = IPP_P0_P1_DFIFO_ENTRIES;
59 else
60 dfifo_entries = IPP_P2_P3_DFIFO_ENTRIES;
davemq59ac0c12007-07-25 18:20:14 -070061 } else {
girish44961712006-11-22 11:47:19 -080062 goto fail;
davemq59ac0c12007-07-25 18:20:14 -070063 }
girish44961712006-11-22 11:47:19 -080064
65 for (i = 0; i < dfifo_entries; i++) {
speera3c5bd62007-01-30 11:29:19 -080066 if ((rs = npi_ipp_write_dfifo(handle,
misaki52ccf842008-06-20 15:53:36 -070067 portn, i, 0, 0, 0, 0, 0)) != NPI_SUCCESS)
girish44961712006-11-22 11:47:19 -080068 goto fail;
speera3c5bd62007-01-30 11:29:19 -080069 if ((rs = npi_ipp_read_dfifo(handle, portn,
misaki52ccf842008-06-20 15:53:36 -070070 i, &d0, &d1, &d2, &d3, &d4)) != NPI_SUCCESS)
girish44961712006-11-22 11:47:19 -080071 goto fail;
72 }
73
74 /* Clear PFIFO DFIFO status bits */
girish44961712006-11-22 11:47:19 -080075 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
76 goto fail;
77 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
78 goto fail;
79
80 /*
81 * Soft reset to make sure we bring the FIFO pointers back to the
82 * original initial position.
83 */
84 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS)
85 goto fail;
86
87 /* Clean up ECC counter */
88 IPP_REG_RD(nxgep->npi_handle, portn, IPP_ECC_ERR_COUNTER_REG, &val);
yc148097f6485ee2007-11-26 22:29:52 -080089 IPP_REG_RD(nxgep->npi_handle, portn, IPP_BAD_CKSUM_ERR_CNT_REG, &val);
girish44961712006-11-22 11:47:19 -080090 IPP_REG_RD(nxgep->npi_handle, portn, IPP_DISCARD_PKT_CNT_REG, &val);
91
92 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
93 goto fail;
94
95 /* Configure IPP port */
96 if ((rs = npi_ipp_iconfig(handle, INIT, portn, ICFG_IPP_ALL))
misaki52ccf842008-06-20 15:53:36 -070097 != NPI_SUCCESS)
girish44961712006-11-22 11:47:19 -080098 goto fail;
99 nxgep->ipp.iconfig = ICFG_IPP_ALL;
100
101 config = CFG_IPP | CFG_IPP_DFIFO_ECC_CORRECT | CFG_IPP_DROP_BAD_CRC |
misaki52ccf842008-06-20 15:53:36 -0700102 CFG_IPP_TCP_UDP_CKSUM;
girish44961712006-11-22 11:47:19 -0800103 if ((rs = npi_ipp_config(handle, INIT, portn, config)) != NPI_SUCCESS)
104 goto fail;
105 nxgep->ipp.config = config;
106
107 /* Set max packet size */
108 pkt_size = IPP_MAX_PKT_SIZE;
speera3c5bd62007-01-30 11:29:19 -0800109 if ((rs = npi_ipp_set_max_pktsize(handle, portn,
misaki52ccf842008-06-20 15:53:36 -0700110 IPP_MAX_PKT_SIZE)) != NPI_SUCCESS)
girish44961712006-11-22 11:47:19 -0800111 goto fail;
112 nxgep->ipp.max_pkt_size = pkt_size;
113
114 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_init: port%d", portn));
115
116 return (NXGE_OK);
117fail:
118 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
misaki52ccf842008-06-20 15:53:36 -0700119 "nxge_ipp_init: Fail to initialize IPP Port #%d\n",
120 portn));
girish44961712006-11-22 11:47:19 -0800121 return (NXGE_ERROR | rs);
122}
123
speera3c5bd62007-01-30 11:29:19 -0800124/* ARGSUSED */
girish44961712006-11-22 11:47:19 -0800125nxge_status_t
126nxge_ipp_disable(p_nxge_t nxgep)
127{
speera3c5bd62007-01-30 11:29:19 -0800128 uint8_t portn;
129 uint32_t config;
130 npi_handle_t handle;
131 npi_status_t rs = NPI_SUCCESS;
sd7746814ea4bb2006-12-22 12:42:28 -0800132 uint16_t wr_ptr, rd_ptr;
133 uint32_t try_count;
girish44961712006-11-22 11:47:19 -0800134
135 handle = nxgep->npi_handle;
136 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
137
138 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_disable: port%d", portn));
sd7746814ea4bb2006-12-22 12:42:28 -0800139 (void) nxge_rx_mac_disable(nxgep);
140
141 /*
speera3c5bd62007-01-30 11:29:19 -0800142 * Wait until ip read and write fifo pointers are equal
sd7746814ea4bb2006-12-22 12:42:28 -0800143 */
144 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
145 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
146 try_count = NXGE_IPP_FIFO_SYNC_TRY_COUNT;
147
148 while ((try_count > 0) && (rd_ptr != wr_ptr)) {
149 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
150 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
151 try_count--;
152 }
153
154 if (try_count == 0) {
155 if ((rd_ptr != 0) && (wr_ptr != 1)) {
156 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
misaki52ccf842008-06-20 15:53:36 -0700157 " nxge_ipp_disable: port%d failed"
158 " rd_fifo != wr_fifo", portn));
sd7746814ea4bb2006-12-22 12:42:28 -0800159 goto fail;
160 }
161 }
girish44961712006-11-22 11:47:19 -0800162 /* disable the IPP */
163 config = nxgep->ipp.config;
speera3c5bd62007-01-30 11:29:19 -0800164 if ((rs = npi_ipp_config(handle, DISABLE,
misaki52ccf842008-06-20 15:53:36 -0700165 portn, config)) != NPI_SUCCESS)
girish44961712006-11-22 11:47:19 -0800166 goto fail;
girish44961712006-11-22 11:47:19 -0800167
girish44961712006-11-22 11:47:19 -0800168 /* IPP soft reset */
speera3c5bd62007-01-30 11:29:19 -0800169 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS)
girish44961712006-11-22 11:47:19 -0800170 goto fail;
girish44961712006-11-22 11:47:19 -0800171
172 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_disable: port%d", portn));
girish44961712006-11-22 11:47:19 -0800173 return (NXGE_OK);
174fail:
175 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
misaki52ccf842008-06-20 15:53:36 -0700176 "nxge_ipp_disable: Fail to disable IPP Port #%d\n", portn));
girish44961712006-11-22 11:47:19 -0800177 return (NXGE_ERROR | rs);
178}
179
speera3c5bd62007-01-30 11:29:19 -0800180/* ARGSUSED */
girish44961712006-11-22 11:47:19 -0800181nxge_status_t
182nxge_ipp_reset(p_nxge_t nxgep)
183{
speera3c5bd62007-01-30 11:29:19 -0800184 uint8_t portn;
185 uint32_t config;
186 npi_handle_t handle;
187 npi_status_t rs = NPI_SUCCESS;
girish44961712006-11-22 11:47:19 -0800188 uint16_t wr_ptr, rd_ptr;
189 uint32_t try_count;
speera3c5bd62007-01-30 11:29:19 -0800190
girish44961712006-11-22 11:47:19 -0800191 handle = nxgep->npi_handle;
192 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
193
194 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_reset: port%d", portn));
195
196 /* disable the IPP */
197 config = nxgep->ipp.config;
speera3c5bd62007-01-30 11:29:19 -0800198 if ((rs = npi_ipp_config(handle, DISABLE,
misaki52ccf842008-06-20 15:53:36 -0700199 portn, config)) != NPI_SUCCESS)
girish44961712006-11-22 11:47:19 -0800200 goto fail;
girish44961712006-11-22 11:47:19 -0800201
202 /*
speera3c5bd62007-01-30 11:29:19 -0800203 * Wait until ip read and write fifo pointers are equal
girish44961712006-11-22 11:47:19 -0800204 */
205 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
206 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
sd7746814ea4bb2006-12-22 12:42:28 -0800207 try_count = NXGE_IPP_FIFO_SYNC_TRY_COUNT;
girish44961712006-11-22 11:47:19 -0800208
209 while ((try_count > 0) && (rd_ptr != wr_ptr)) {
210 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
211 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
212 try_count--;
213 }
214
215 if (try_count == 0) {
sd7746814ea4bb2006-12-22 12:42:28 -0800216 if ((rd_ptr != 0) && (wr_ptr != 1)) {
217 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
misaki52ccf842008-06-20 15:53:36 -0700218 " nxge_ipp_disable: port%d failed"
219 " rd_fifo != wr_fifo", portn));
sd7746814ea4bb2006-12-22 12:42:28 -0800220 goto fail;
221 }
girish44961712006-11-22 11:47:19 -0800222 }
223
224 /* IPP soft reset */
225 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS) {
226 goto fail;
227 }
228
229 /* to reset control FIFO */
speera3c5bd62007-01-30 11:29:19 -0800230 if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS)
girish44961712006-11-22 11:47:19 -0800231 goto fail;
girish44961712006-11-22 11:47:19 -0800232
233 /*
speera3c5bd62007-01-30 11:29:19 -0800234 * Making sure that error source is cleared if this is an injected
235 * error.
girish44961712006-11-22 11:47:19 -0800236 */
237 IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0);
238
239 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_reset: port%d", portn));
girish44961712006-11-22 11:47:19 -0800240 return (NXGE_OK);
241fail:
242 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
misaki52ccf842008-06-20 15:53:36 -0700243 "nxge_ipp_init: Fail to Reset IPP Port #%d\n",
244 portn));
girish44961712006-11-22 11:47:19 -0800245 return (NXGE_ERROR | rs);
246}
247
speera3c5bd62007-01-30 11:29:19 -0800248/* ARGSUSED */
girish44961712006-11-22 11:47:19 -0800249nxge_status_t
250nxge_ipp_enable(p_nxge_t nxgep)
251{
speera3c5bd62007-01-30 11:29:19 -0800252 uint8_t portn;
253 uint32_t config;
254 npi_handle_t handle;
255 uint32_t pkt_size;
256 npi_status_t rs = NPI_SUCCESS;
girish44961712006-11-22 11:47:19 -0800257
258 handle = nxgep->npi_handle;
259 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
260
261 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_enable: port%d", portn));
262
263 config = CFG_IPP | CFG_IPP_DFIFO_ECC_CORRECT | CFG_IPP_DROP_BAD_CRC |
misaki52ccf842008-06-20 15:53:36 -0700264 CFG_IPP_TCP_UDP_CKSUM;
girish44961712006-11-22 11:47:19 -0800265 if ((rs = npi_ipp_config(handle, INIT, portn, config)) != NPI_SUCCESS)
266 goto fail;
267 nxgep->ipp.config = config;
268
269 /* Set max packet size */
270 pkt_size = IPP_MAX_PKT_SIZE;
speera3c5bd62007-01-30 11:29:19 -0800271 if ((rs = npi_ipp_set_max_pktsize(handle, portn,
misaki52ccf842008-06-20 15:53:36 -0700272 IPP_MAX_PKT_SIZE)) != NPI_SUCCESS)
girish44961712006-11-22 11:47:19 -0800273 goto fail;
274 nxgep->ipp.max_pkt_size = pkt_size;
275
276 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_enable: port%d", portn));
girish44961712006-11-22 11:47:19 -0800277 return (NXGE_OK);
278fail:
279 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
misaki52ccf842008-06-20 15:53:36 -0700280 "nxge_ipp_init: Fail to Enable IPP Port #%d\n", portn));
girish44961712006-11-22 11:47:19 -0800281 return (NXGE_ERROR | rs);
282}
283
speera3c5bd62007-01-30 11:29:19 -0800284/* ARGSUSED */
girish44961712006-11-22 11:47:19 -0800285nxge_status_t
speer678453a2008-04-27 19:50:44 -0700286nxge_ipp_drain(p_nxge_t nxgep)
287{
288 uint8_t portn;
289 npi_handle_t handle;
290 npi_status_t rs = NPI_SUCCESS;
291 uint16_t wr_ptr, rd_ptr;
292 uint32_t try_count;
293
294 handle = nxgep->npi_handle;
295 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
296
297 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "==> nxge_ipp_drain: port%d", portn));
298
299 /*
300 * Wait until ip read and write fifo pointers are equal
301 */
302 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
303 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
304 try_count = NXGE_IPP_FIFO_SYNC_TRY_COUNT;
305
306 while ((try_count > 0) && (rd_ptr != wr_ptr)) {
307 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
308 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
309 try_count--;
310 }
311
312 if (try_count == 0) {
313 if ((rd_ptr != 0) && (wr_ptr != 1)) {
314 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
315 " nxge_ipp_drain: port%d failed"
316 " rd_fifo != wr_fifo", portn));
317 goto fail;
318 }
319 }
320
321 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "<== nxge_ipp_drain: port%d", portn));
322 return (NXGE_OK);
323fail:
324 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_ipp_init: "
325 "Fail to Reset IPP Port #%d\n", portn));
326 return (NXGE_ERROR | rs);
327}
328
329/* ARGSUSED */
330nxge_status_t
girish44961712006-11-22 11:47:19 -0800331nxge_ipp_handle_sys_errors(p_nxge_t nxgep)
332{
speera3c5bd62007-01-30 11:29:19 -0800333 npi_handle_t handle;
334 npi_status_t rs = NPI_SUCCESS;
335 p_nxge_ipp_stats_t statsp;
336 ipp_status_t istatus;
337 uint8_t portn;
338 p_ipp_errlog_t errlogp;
339 boolean_t rxport_fatal = B_FALSE;
340 nxge_status_t status = NXGE_OK;
yc14809753f3d8e2007-10-01 22:31:20 -0700341 uint8_t cnt8;
342 uint16_t cnt16;
girish44961712006-11-22 11:47:19 -0800343
344 handle = nxgep->npi_handle;
345 statsp = (p_nxge_ipp_stats_t)&nxgep->statsp->ipp_stats;
346 portn = nxgep->mac.portnum;
347
348 errlogp = (p_ipp_errlog_t)&statsp->errlog;
349
350 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
351 return (NXGE_ERROR | rs);
352
speera3c5bd62007-01-30 11:29:19 -0800353 if (istatus.value == 0) {
girish44961712006-11-22 11:47:19 -0800354 /*
355 * The error is not initiated from this port, so just exit.
356 */
357 return (NXGE_OK);
speera3c5bd62007-01-30 11:29:19 -0800358 }
girish44961712006-11-22 11:47:19 -0800359
360 if (istatus.bits.w0.dfifo_missed_sop) {
361 statsp->sop_miss++;
362 if ((rs = npi_ipp_get_dfifo_eopm_rdptr(handle, portn,
misaki52ccf842008-06-20 15:53:36 -0700363 &errlogp->dfifo_rd_ptr)) != NPI_SUCCESS)
girish44961712006-11-22 11:47:19 -0800364 return (NXGE_ERROR | rs);
365 if ((rs = npi_ipp_get_state_mach(handle, portn,
misaki52ccf842008-06-20 15:53:36 -0700366 &errlogp->state_mach)) != NPI_SUCCESS)
girish44961712006-11-22 11:47:19 -0800367 return (NXGE_ERROR | rs);
368 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
misaki52ccf842008-06-20 15:53:36 -0700369 NXGE_FM_EREPORT_IPP_SOP_MISS);
girish44961712006-11-22 11:47:19 -0800370 if (statsp->sop_miss < IPP_MAX_ERR_SHOW)
371 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
misaki52ccf842008-06-20 15:53:36 -0700372 "nxge_ipp_err_evnts: fatal error: sop_miss\n"));
girish44961712006-11-22 11:47:19 -0800373 rxport_fatal = B_TRUE;
374 }
375 if (istatus.bits.w0.dfifo_missed_eop) {
376 statsp->eop_miss++;
377 if ((rs = npi_ipp_get_dfifo_eopm_rdptr(handle, portn,
misaki52ccf842008-06-20 15:53:36 -0700378 &errlogp->dfifo_rd_ptr)) != NPI_SUCCESS)
girish44961712006-11-22 11:47:19 -0800379 return (NXGE_ERROR | rs);
380 if ((rs = npi_ipp_get_state_mach(handle, portn,
misaki52ccf842008-06-20 15:53:36 -0700381 &errlogp->state_mach)) != NPI_SUCCESS)
girish44961712006-11-22 11:47:19 -0800382 return (NXGE_ERROR | rs);
383 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
misaki52ccf842008-06-20 15:53:36 -0700384 NXGE_FM_EREPORT_IPP_EOP_MISS);
girish44961712006-11-22 11:47:19 -0800385 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
misaki52ccf842008-06-20 15:53:36 -0700386 "nxge_ipp_err_evnts: fatal error: eop_miss\n"));
girish44961712006-11-22 11:47:19 -0800387 rxport_fatal = B_TRUE;
388 }
389 if (istatus.bits.w0.dfifo_uncorr_ecc_err) {
sd7746814ea4bb2006-12-22 12:42:28 -0800390 boolean_t ue_ecc_valid;
391
speera3c5bd62007-01-30 11:29:19 -0800392 if ((status = nxge_ipp_eccue_valid_check(nxgep,
misaki52ccf842008-06-20 15:53:36 -0700393 &ue_ecc_valid)) != NXGE_OK)
sd7746814ea4bb2006-12-22 12:42:28 -0800394 return (status);
395
396 if (ue_ecc_valid) {
397 statsp->dfifo_ue++;
398 if ((rs = npi_ipp_get_ecc_syndrome(handle, portn,
misaki52ccf842008-06-20 15:53:36 -0700399 &errlogp->ecc_syndrome)) != NPI_SUCCESS)
sd7746814ea4bb2006-12-22 12:42:28 -0800400 return (NXGE_ERROR | rs);
401 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
misaki52ccf842008-06-20 15:53:36 -0700402 NXGE_FM_EREPORT_IPP_DFIFO_UE);
sd7746814ea4bb2006-12-22 12:42:28 -0800403 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
misaki52ccf842008-06-20 15:53:36 -0700404 "nxge_ipp_err_evnts: fatal error: dfifo_ue\n"));
sd7746814ea4bb2006-12-22 12:42:28 -0800405 rxport_fatal = B_TRUE;
406 }
girish44961712006-11-22 11:47:19 -0800407 }
girish44961712006-11-22 11:47:19 -0800408 if (istatus.bits.w0.pre_fifo_perr) {
409 statsp->pfifo_perr++;
410 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
misaki52ccf842008-06-20 15:53:36 -0700411 NXGE_FM_EREPORT_IPP_PFIFO_PERR);
girish44961712006-11-22 11:47:19 -0800412 if (statsp->pfifo_perr < IPP_MAX_ERR_SHOW)
413 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
misaki52ccf842008-06-20 15:53:36 -0700414 "nxge_ipp_err_evnts: "
415 "fatal error: pre_pifo_perr\n"));
girish44961712006-11-22 11:47:19 -0800416 rxport_fatal = B_TRUE;
417 }
girish44961712006-11-22 11:47:19 -0800418 if (istatus.bits.w0.pre_fifo_overrun) {
419 statsp->pfifo_over++;
420 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
misaki52ccf842008-06-20 15:53:36 -0700421 NXGE_FM_EREPORT_IPP_PFIFO_OVER);
girish44961712006-11-22 11:47:19 -0800422 if (statsp->pfifo_over < IPP_MAX_ERR_SHOW)
423 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
misaki52ccf842008-06-20 15:53:36 -0700424 "nxge_ipp_err_evnts: "
425 "fatal error: pfifo_over\n"));
girish44961712006-11-22 11:47:19 -0800426 rxport_fatal = B_TRUE;
427 }
428 if (istatus.bits.w0.pre_fifo_underrun) {
429 statsp->pfifo_und++;
430 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
misaki52ccf842008-06-20 15:53:36 -0700431 NXGE_FM_EREPORT_IPP_PFIFO_UND);
girish44961712006-11-22 11:47:19 -0800432 if (statsp->pfifo_und < IPP_MAX_ERR_SHOW)
433 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
misaki52ccf842008-06-20 15:53:36 -0700434 "nxge_ipp_err_evnts: "
435 "fatal error: pfifo_und\n"));
girish44961712006-11-22 11:47:19 -0800436 rxport_fatal = B_TRUE;
437 }
438 if (istatus.bits.w0.bad_cksum_cnt_ovfl) {
yc148097d7108772007-10-10 15:55:46 -0700439 /*
yc14809763e23a12008-03-10 18:33:37 -0700440 * Do not send FMA ereport or log error message
441 * in /var/adm/messages because this error does not
442 * indicate a HW failure.
443 *
yc148097d7108772007-10-10 15:55:46 -0700444 * Clear bit BAD_CS_MX of register IPP_INT_STAT
445 * by reading register IPP_BAD_CS_CNT
446 */
yc14809753f3d8e2007-10-01 22:31:20 -0700447 (void) npi_ipp_get_cs_err_count(handle, portn, &cnt16);
girish44961712006-11-22 11:47:19 -0800448 statsp->bad_cs_cnt += IPP_BAD_CS_CNT_MASK;
girish44961712006-11-22 11:47:19 -0800449 }
450 if (istatus.bits.w0.pkt_discard_cnt_ovfl) {
yc148097d7108772007-10-10 15:55:46 -0700451 /*
yc14809763e23a12008-03-10 18:33:37 -0700452 * Do not send FMA ereport or log error message
453 * in /var/adm/messages because this error does not
454 * indicate a HW failure.
455 *
yc148097d7108772007-10-10 15:55:46 -0700456 * Clear bit PKT_DIS_MX of register IPP_INT_STAT
457 * by reading register IPP_PKT_DIS
458 */
yc14809753f3d8e2007-10-01 22:31:20 -0700459 (void) npi_ipp_get_pkt_dis_count(handle, portn, &cnt16);
girish44961712006-11-22 11:47:19 -0800460 statsp->pkt_dis_cnt += IPP_PKT_DIS_CNT_MASK;
girish44961712006-11-22 11:47:19 -0800461 }
yc14809753f3d8e2007-10-01 22:31:20 -0700462 if (istatus.bits.w0.ecc_err_cnt_ovfl) {
yc148097d7108772007-10-10 15:55:46 -0700463 /*
464 * Clear bit ECC_ERR_MAX of register IPP_INI_STAT
465 * by reading register IPP_ECC
466 */
yc14809753f3d8e2007-10-01 22:31:20 -0700467 (void) npi_ipp_get_ecc_err_count(handle, portn, &cnt8);
468 statsp->ecc_err_cnt += IPP_ECC_CNT_MASK;
yc148097f6485ee2007-11-26 22:29:52 -0800469 /*
470 * A defect in Neptune port2's IPP module could generate
471 * many fake but harmless ECC errors under stress and cause
472 * the ecc-error-counter register IPP_ECC to reach its
473 * maximum value in a few seconds. To avoid false alarm, do
474 * not report the error if it is port2.
475 */
476 if (portn != 2) {
477 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
478 NXGE_FM_EREPORT_IPP_ECC_ERR_MAX);
479 if (statsp->ecc_err_cnt < (IPP_MAX_ERR_SHOW *
480 IPP_ECC_CNT_MASK)) {
481 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
482 "nxge_ipp_err_evnts: pkt_ecc_err_max\n"));
483 }
484 }
yc14809753f3d8e2007-10-01 22:31:20 -0700485 }
girish44961712006-11-22 11:47:19 -0800486 /*
speera3c5bd62007-01-30 11:29:19 -0800487 * Making sure that error source is cleared if this is an injected
488 * error.
girish44961712006-11-22 11:47:19 -0800489 */
490 IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0);
491
492 if (rxport_fatal) {
493 NXGE_DEBUG_MSG((nxgep, IPP_CTL,
misaki52ccf842008-06-20 15:53:36 -0700494 " nxge_ipp_handle_sys_errors:"
495 " fatal Error on Port #%d\n", portn));
girish44961712006-11-22 11:47:19 -0800496 status = nxge_ipp_fatal_err_recover(nxgep);
girish44961712006-11-22 11:47:19 -0800497 if (status == NXGE_OK) {
498 FM_SERVICE_RESTORED(nxgep);
499 }
girish44961712006-11-22 11:47:19 -0800500 }
girish44961712006-11-22 11:47:19 -0800501 return (status);
502}
503
speera3c5bd62007-01-30 11:29:19 -0800504/* ARGSUSED */
girish44961712006-11-22 11:47:19 -0800505void
506nxge_ipp_inject_err(p_nxge_t nxgep, uint32_t err_id)
507{
speera3c5bd62007-01-30 11:29:19 -0800508 ipp_status_t ipps;
509 ipp_ecc_ctrl_t ecc_ctrl;
510 uint8_t portn = nxgep->mac.portnum;
girish44961712006-11-22 11:47:19 -0800511
512 switch (err_id) {
513 case NXGE_FM_EREPORT_IPP_DFIFO_UE:
514 ecc_ctrl.value = 0;
515 ecc_ctrl.bits.w0.cor_dbl = 1;
516 ecc_ctrl.bits.w0.cor_1 = 1;
517 ecc_ctrl.bits.w0.cor_lst = 1;
518 cmn_err(CE_NOTE, "!Write 0x%llx to IPP_ECC_CTRL_REG\n",
misaki52ccf842008-06-20 15:53:36 -0700519 (unsigned long long) ecc_ctrl.value);
girish44961712006-11-22 11:47:19 -0800520 IPP_REG_WR(nxgep->npi_handle, portn, IPP_ECC_CTRL_REG,
misaki52ccf842008-06-20 15:53:36 -0700521 ecc_ctrl.value);
girish44961712006-11-22 11:47:19 -0800522 break;
speera3c5bd62007-01-30 11:29:19 -0800523
girish44961712006-11-22 11:47:19 -0800524 case NXGE_FM_EREPORT_IPP_DFIFO_CE:
525 ecc_ctrl.value = 0;
526 ecc_ctrl.bits.w0.cor_sng = 1;
527 ecc_ctrl.bits.w0.cor_1 = 1;
528 ecc_ctrl.bits.w0.cor_snd = 1;
529 cmn_err(CE_NOTE, "!Write 0x%llx to IPP_ECC_CTRL_REG\n",
misaki52ccf842008-06-20 15:53:36 -0700530 (unsigned long long) ecc_ctrl.value);
girish44961712006-11-22 11:47:19 -0800531 IPP_REG_WR(nxgep->npi_handle, portn, IPP_ECC_CTRL_REG,
misaki52ccf842008-06-20 15:53:36 -0700532 ecc_ctrl.value);
girish44961712006-11-22 11:47:19 -0800533 break;
speera3c5bd62007-01-30 11:29:19 -0800534
girish44961712006-11-22 11:47:19 -0800535 case NXGE_FM_EREPORT_IPP_EOP_MISS:
536 case NXGE_FM_EREPORT_IPP_SOP_MISS:
537 case NXGE_FM_EREPORT_IPP_PFIFO_PERR:
538 case NXGE_FM_EREPORT_IPP_ECC_ERR_MAX:
539 case NXGE_FM_EREPORT_IPP_PFIFO_OVER:
540 case NXGE_FM_EREPORT_IPP_PFIFO_UND:
541 case NXGE_FM_EREPORT_IPP_BAD_CS_MX:
542 case NXGE_FM_EREPORT_IPP_PKT_DIS_MX:
543 case NXGE_FM_EREPORT_IPP_RESET_FAIL:
544 IPP_REG_RD(nxgep->npi_handle, portn, IPP_INT_STATUS_REG,
misaki52ccf842008-06-20 15:53:36 -0700545 &ipps.value);
girish44961712006-11-22 11:47:19 -0800546 if (err_id == NXGE_FM_EREPORT_IPP_EOP_MISS)
547 ipps.bits.w0.dfifo_missed_eop = 1;
548 else if (err_id == NXGE_FM_EREPORT_IPP_SOP_MISS)
549 ipps.bits.w0.dfifo_missed_sop = 1;
550 else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_UE)
551 ipps.bits.w0.dfifo_uncorr_ecc_err = 1;
552 else if (err_id == NXGE_FM_EREPORT_IPP_DFIFO_CE)
553 ipps.bits.w0.dfifo_corr_ecc_err = 1;
554 else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_PERR)
555 ipps.bits.w0.pre_fifo_perr = 1;
yc148097d7108772007-10-10 15:55:46 -0700556 else if (err_id == NXGE_FM_EREPORT_IPP_ECC_ERR_MAX) {
557 /*
558 * Fill register IPP_ECC with max ECC-error-
559 * counter value (0xff) to set the ECC_ERR_MAX bit
560 * of the IPP_INT_STAT register and trigger an
561 * FMA ereport.
562 */
563 IPP_REG_WR(nxgep->npi_handle, portn,
564 IPP_ECC_ERR_COUNTER_REG, IPP_ECC_CNT_MASK);
565 } else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_OVER)
girish44961712006-11-22 11:47:19 -0800566 ipps.bits.w0.pre_fifo_overrun = 1;
567 else if (err_id == NXGE_FM_EREPORT_IPP_PFIFO_UND)
568 ipps.bits.w0.pre_fifo_underrun = 1;
yc148097d7108772007-10-10 15:55:46 -0700569 else if (err_id == NXGE_FM_EREPORT_IPP_BAD_CS_MX) {
570 /*
571 * Fill IPP_BAD_CS_CNT with max bad-checksum-counter
572 * value (0x3fff) to set the BAD_CS_MX bit of
573 * IPP_INT_STAT and trigger an FMA ereport.
574 */
575 IPP_REG_WR(nxgep->npi_handle, portn,
yc148097f6485ee2007-11-26 22:29:52 -0800576 IPP_BAD_CKSUM_ERR_CNT_REG, IPP_BAD_CS_CNT_MASK);
yc148097d7108772007-10-10 15:55:46 -0700577 } else if (err_id == NXGE_FM_EREPORT_IPP_PKT_DIS_MX) {
578 /*
579 * Fill IPP_PKT_DIS with max packet-discard-counter
580 * value (0x3fff) to set the PKT_DIS_MX bit of
581 * IPP_INT_STAT and trigger an FMA ereport.
582 */
583 IPP_REG_WR(nxgep->npi_handle, portn,
584 IPP_DISCARD_PKT_CNT_REG, IPP_PKT_DIS_CNT_MASK);
585 }
girish44961712006-11-22 11:47:19 -0800586 cmn_err(CE_NOTE, "!Write 0x%llx to IPP_INT_STATUS_REG\n",
misaki52ccf842008-06-20 15:53:36 -0700587 (unsigned long long) ipps.value);
girish44961712006-11-22 11:47:19 -0800588 IPP_REG_WR(nxgep->npi_handle, portn, IPP_INT_STATUS_REG,
misaki52ccf842008-06-20 15:53:36 -0700589 ipps.value);
girish44961712006-11-22 11:47:19 -0800590 break;
591 }
592}
593
speera3c5bd62007-01-30 11:29:19 -0800594/* ARGSUSED */
girish44961712006-11-22 11:47:19 -0800595nxge_status_t
596nxge_ipp_fatal_err_recover(p_nxge_t nxgep)
597{
speera3c5bd62007-01-30 11:29:19 -0800598 npi_handle_t handle;
599 npi_status_t rs = NPI_SUCCESS;
600 nxge_status_t status = NXGE_OK;
601 uint8_t portn;
602 uint16_t wr_ptr;
603 uint16_t rd_ptr;
604 uint32_t try_count;
605 uint32_t dfifo_entries;
606 ipp_status_t istatus;
607 uint32_t d0, d1, d2, d3, d4;
608 int i;
girish44961712006-11-22 11:47:19 -0800609
610 NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_ipp_fatal_err_recover"));
girish44961712006-11-22 11:47:19 -0800611 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
misaki52ccf842008-06-20 15:53:36 -0700612 "Recovering from RxPort error..."));
girish44961712006-11-22 11:47:19 -0800613
614 handle = nxgep->npi_handle;
615 portn = nxgep->mac.portnum;
616
617 /*
speera3c5bd62007-01-30 11:29:19 -0800618 * Making sure that error source is cleared if this is an injected
619 * error.
girish44961712006-11-22 11:47:19 -0800620 */
621 IPP_REG_WR(handle, portn, IPP_ECC_CTRL_REG, 0);
622
623 /* Disable RxMAC */
girish44961712006-11-22 11:47:19 -0800624 if (nxge_rx_mac_disable(nxgep) != NXGE_OK)
625 goto fail;
626
627 /* When recovering from IPP, RxDMA channel resets are not necessary */
628 /* Reset ZCP CFIFO */
629 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset ZCP CFIFO...", portn));
630 if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS)
631 goto fail;
632
633 /*
speera3c5bd62007-01-30 11:29:19 -0800634 * Wait until ip read and write fifo pointers are equal
girish44961712006-11-22 11:47:19 -0800635 */
636 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
637 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
638 try_count = 512;
639
640 while ((try_count > 0) && (rd_ptr != wr_ptr)) {
641 (void) npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr);
642 (void) npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr);
643 try_count--;
644 }
645
646 if (try_count == 0) {
647 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
misaki52ccf842008-06-20 15:53:36 -0700648 " nxge_ipp_reset: port%d IPP stalled..."
649 " rd_fifo_ptr = 0x%x wr_fifo_ptr = 0x%x",
650 portn, rd_ptr, wr_ptr));
girish44961712006-11-22 11:47:19 -0800651 /*
speera3c5bd62007-01-30 11:29:19 -0800652 * This means the fatal error occurred on the first line of the
653 * fifo. In this case, just reset the IPP without draining the
654 * PFIFO.
girish44961712006-11-22 11:47:19 -0800655 */
656 }
657
davemq59ac0c12007-07-25 18:20:14 -0700658 if (nxgep->niu_type == N2_NIU) {
659 dfifo_entries = IPP_NIU_DFIFO_ENTRIES;
raghus2e591292007-08-31 16:49:49 -0700660 } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
girish44961712006-11-22 11:47:19 -0800661 if (portn < 2)
662 dfifo_entries = IPP_P0_P1_DFIFO_ENTRIES;
663 else
664 dfifo_entries = IPP_P2_P3_DFIFO_ENTRIES;
davemq59ac0c12007-07-25 18:20:14 -0700665 } else {
girish44961712006-11-22 11:47:19 -0800666 goto fail;
davemq59ac0c12007-07-25 18:20:14 -0700667 }
girish44961712006-11-22 11:47:19 -0800668
669 /* Clean up DFIFO SRAM entries */
670 for (i = 0; i < dfifo_entries; i++) {
speera3c5bd62007-01-30 11:29:19 -0800671 if ((rs = npi_ipp_write_dfifo(handle, portn,
misaki52ccf842008-06-20 15:53:36 -0700672 i, 0, 0, 0, 0, 0)) != NPI_SUCCESS)
girish44961712006-11-22 11:47:19 -0800673 goto fail;
speera3c5bd62007-01-30 11:29:19 -0800674 if ((rs = npi_ipp_read_dfifo(handle, portn, i,
misaki52ccf842008-06-20 15:53:36 -0700675 &d0, &d1, &d2, &d3, &d4)) != NPI_SUCCESS)
girish44961712006-11-22 11:47:19 -0800676 goto fail;
677 }
678
679 /* Clear PFIFO DFIFO status bits */
girish44961712006-11-22 11:47:19 -0800680 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
681 goto fail;
682 if ((rs = npi_ipp_get_status(handle, portn, &istatus)) != NPI_SUCCESS)
683 goto fail;
684
685 /* Reset IPP */
686 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset IPP...", portn));
687 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS)
688 goto fail;
689
690 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Reset RxMAC...", portn));
691 if (nxge_rx_mac_reset(nxgep) != NXGE_OK)
692 goto fail;
693
694 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Initialize RxMAC...", portn));
girish44961712006-11-22 11:47:19 -0800695 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
696 goto fail;
697
698 NXGE_DEBUG_MSG((nxgep, IPP_CTL, "port%d Enable RxMAC...", portn));
girish44961712006-11-22 11:47:19 -0800699 if (nxge_rx_mac_enable(nxgep) != NXGE_OK)
700 goto fail;
701
702 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
misaki52ccf842008-06-20 15:53:36 -0700703 "Recovery successful, RxPort restored"));
girish44961712006-11-22 11:47:19 -0800704 NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_ipp_fatal_err_recover"));
705
706 return (NXGE_OK);
707fail:
708 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed"));
709 return (status | rs);
710}
sd7746814ea4bb2006-12-22 12:42:28 -0800711
speera3c5bd62007-01-30 11:29:19 -0800712/* ARGSUSED */
yc1480971a4557b2007-07-11 23:51:01 -0700713/*
yc14809753f3d8e2007-10-01 22:31:20 -0700714 * A hardware bug may cause fake ECCUEs (ECC Uncorrectable Error).
yc1480971a4557b2007-07-11 23:51:01 -0700715 * This function checks if a ECCUE is real(valid) or not. It is not
716 * real if rd_ptr == wr_ptr.
717 * The hardware module that has the bug is used not only by the IPP
718 * FIFO but also by the ZCP FIFO, therefore this function is also
719 * called by nxge_zcp_handle_sys_errors for validating the ZCP FIFO
720 * error.
721 */
sd7746814ea4bb2006-12-22 12:42:28 -0800722nxge_status_t
723nxge_ipp_eccue_valid_check(p_nxge_t nxgep, boolean_t *valid)
724{
725 npi_handle_t handle;
726 npi_status_t rs = NPI_SUCCESS;
727 uint8_t portn;
728 uint16_t rd_ptr;
729 uint16_t wr_ptr;
730 uint16_t curr_rd_ptr;
731 uint16_t curr_wr_ptr;
732 uint32_t stall_cnt;
733 uint32_t d0, d1, d2, d3, d4;
734
735 handle = nxgep->npi_handle;
736 portn = nxgep->mac.portnum;
737 *valid = B_TRUE;
738
739 if ((rs = npi_ipp_get_dfifo_rd_ptr(handle, portn, &rd_ptr))
misaki52ccf842008-06-20 15:53:36 -0700740 != NPI_SUCCESS)
sd7746814ea4bb2006-12-22 12:42:28 -0800741 goto fail;
yc1480971a4557b2007-07-11 23:51:01 -0700742 if ((rs = npi_ipp_get_dfifo_wr_ptr(handle, portn, &wr_ptr))
misaki52ccf842008-06-20 15:53:36 -0700743 != NPI_SUCCESS)
sd7746814ea4bb2006-12-22 12:42:28 -0800744 goto fail;
745
746 if (rd_ptr == wr_ptr) {
yc1480971a4557b2007-07-11 23:51:01 -0700747 *valid = B_FALSE; /* FIFO not stuck, so it's not a real ECCUE */
sd7746814ea4bb2006-12-22 12:42:28 -0800748 } else {
749 stall_cnt = 0;
yc148097ee5416c2007-09-16 21:47:51 -0700750 /*
751 * Check if the two pointers are moving, the ECCUE is invali
752 * if either pointer is moving, which indicates that the FIFO
753 * is functional.
754 */
sd7746814ea4bb2006-12-22 12:42:28 -0800755 while (stall_cnt < 16) {
speera3c5bd62007-01-30 11:29:19 -0800756 if ((rs = npi_ipp_get_dfifo_rd_ptr(handle,
misaki52ccf842008-06-20 15:53:36 -0700757 portn, &curr_rd_ptr)) != NPI_SUCCESS)
sd7746814ea4bb2006-12-22 12:42:28 -0800758 goto fail;
speera3c5bd62007-01-30 11:29:19 -0800759 if ((rs = npi_ipp_get_dfifo_wr_ptr(handle,
misaki52ccf842008-06-20 15:53:36 -0700760 portn, &curr_wr_ptr)) != NPI_SUCCESS)
sd7746814ea4bb2006-12-22 12:42:28 -0800761 goto fail;
762
yc148097ee5416c2007-09-16 21:47:51 -0700763 if (rd_ptr == curr_rd_ptr && wr_ptr == curr_wr_ptr) {
sd7746814ea4bb2006-12-22 12:42:28 -0800764 stall_cnt++;
yc148097ee5416c2007-09-16 21:47:51 -0700765 } else {
sd7746814ea4bb2006-12-22 12:42:28 -0800766 *valid = B_FALSE;
767 break;
768 }
769 }
770
speera3c5bd62007-01-30 11:29:19 -0800771 if (valid) {
yc148097ee5416c2007-09-16 21:47:51 -0700772 /*
yc148097d7108772007-10-10 15:55:46 -0700773 * Further check to see if the ECCUE is valid. The
yc148097ee5416c2007-09-16 21:47:51 -0700774 * error is real if the LSB of d4 is 1, which
775 * indicates that the data that has set the ECC
776 * error flag is the 16-byte internal control word.
777 */
778 if ((rs = npi_ipp_read_dfifo(handle, portn, rd_ptr,
779 &d0, &d1, &d2, &d3, &d4)) != NPI_SUCCESS)
sd7746814ea4bb2006-12-22 12:42:28 -0800780 goto fail;
781 if ((d4 & 0x1) == 0) /* Not the 1st line */
782 *valid = B_FALSE;
783 }
784 }
sd7746814ea4bb2006-12-22 12:42:28 -0800785 return (NXGE_OK);
786fail:
787 return (NXGE_ERROR | rs);
788}