1 /*
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 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <nxge_impl.h>
27 #include <nxge_zcp.h>
28 #include <nxge_ipp.h>
29
30 nxge_status_t
nxge_zcp_init(p_nxge_t nxgep)31 nxge_zcp_init(p_nxge_t nxgep)
32 {
33 uint8_t portn;
34 npi_handle_t handle;
35 zcp_iconfig_t istatus;
36 npi_status_t rs = NPI_SUCCESS;
37 int i;
38 zcp_ram_unit_t w_data;
39 zcp_ram_unit_t r_data;
40 uint32_t cfifo_depth;
41
42 handle = nxgep->npi_handle;
43 portn = NXGE_GET_PORT_NUM(nxgep->function_num);
44
45 if (nxgep->niu_type == N2_NIU) {
46 cfifo_depth = ZCP_NIU_CFIFO_DEPTH;
47 } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
48 if (portn < 2)
49 cfifo_depth = ZCP_P0_P1_CFIFO_DEPTH;
50 else
51 cfifo_depth = ZCP_P2_P3_CFIFO_DEPTH;
52 } else {
53 goto fail;
54 }
55
56 /* Clean up CFIFO */
57 w_data.w0 = 0;
58 w_data.w1 = 0;
59 w_data.w2 = 0;
60 w_data.w3 = 0;
61 w_data.w4 = 0;
62
63 for (i = 0; i < cfifo_depth; i++) {
64 if (npi_zcp_tt_cfifo_entry(handle, OP_SET,
65 portn, i, &w_data) != NPI_SUCCESS)
66 goto fail;
67 if (npi_zcp_tt_cfifo_entry(handle, OP_GET,
68 portn, i, &r_data) != NPI_SUCCESS)
69 goto fail;
70 }
71
72 if (npi_zcp_rest_cfifo_port(handle, portn) != NPI_SUCCESS)
73 goto fail;
74
75 /*
76 * Making sure that error source is cleared if this is an injected
77 * error.
78 */
79 switch (portn) {
80 case 0:
81 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
82 break;
83 case 1:
84 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
85 break;
86 case 2:
87 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
88 break;
89 case 3:
90 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
91 break;
92 }
93
94 if ((rs = npi_zcp_clear_istatus(handle)) != NPI_SUCCESS)
95 return (NXGE_ERROR | rs);
96 if ((rs = npi_zcp_get_istatus(handle, &istatus)) != NPI_SUCCESS)
97 return (NXGE_ERROR | rs);
98 if ((rs = npi_zcp_iconfig(handle, INIT, ICFG_ZCP_ALL)) != NPI_SUCCESS)
99 goto fail;
100
101 NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_zcp_init: port%d", portn));
102 return (NXGE_OK);
103
104 fail:
105 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
106 "nxge_zcp_init: Fail to initialize ZCP Port #%d\n", portn));
107 return (NXGE_ERROR | rs);
108 }
109
110 nxge_status_t
nxge_zcp_handle_sys_errors(p_nxge_t nxgep)111 nxge_zcp_handle_sys_errors(p_nxge_t nxgep)
112 {
113 npi_handle_t handle;
114 npi_status_t rs = NPI_SUCCESS;
115 p_nxge_zcp_stats_t statsp;
116 uint8_t portn;
117 zcp_iconfig_t istatus;
118 boolean_t rxport_fatal = B_FALSE;
119 nxge_status_t status = NXGE_OK;
120
121 handle = nxgep->npi_handle;
122 statsp = (p_nxge_zcp_stats_t)&nxgep->statsp->zcp_stats;
123 portn = nxgep->mac.portnum;
124
125 if ((rs = npi_zcp_get_istatus(handle, &istatus)) != NPI_SUCCESS)
126 return (NXGE_ERROR | rs);
127
128 if (istatus & ICFG_ZCP_RRFIFO_UNDERRUN) {
129 statsp->rrfifo_underrun++;
130 NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
131 NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN);
132 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
133 "nxge_zcp_err_evnts: rrfifo_underrun"));
134 }
135
136 if (istatus & ICFG_ZCP_RRFIFO_OVERRUN) {
137 statsp->rrfifo_overrun++;
138 NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
139 NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN);
140 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
141 "nxge_zcp_err_evnts: buf_rrfifo_overrun"));
142 }
143
144 if (istatus & ICFG_ZCP_RSPFIFO_UNCORR_ERR) {
145 statsp->rspfifo_uncorr_err++;
146 NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
147 NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR);
148 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
149 "nxge_zcp_err_evnts: rspfifo_uncorr_err"));
150 }
151
152 if (istatus & ICFG_ZCP_BUFFER_OVERFLOW) {
153 statsp->buffer_overflow++;
154 NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
155 NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW);
156 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
157 "nxge_zcp_err_evnts: buffer_overflow"));
158 rxport_fatal = B_TRUE;
159 }
160
161 if (istatus & ICFG_ZCP_STAT_TBL_PERR) {
162 statsp->stat_tbl_perr++;
163 NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
164 NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR);
165 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
166 "nxge_zcp_err_evnts: stat_tbl_perr"));
167 }
168
169 if (istatus & ICFG_ZCP_DYN_TBL_PERR) {
170 statsp->dyn_tbl_perr++;
171 NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
172 NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR);
173 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
174 "nxge_zcp_err_evnts: dyn_tbl_perr"));
175 }
176
177 if (istatus & ICFG_ZCP_BUF_TBL_PERR) {
178 statsp->buf_tbl_perr++;
179 NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
180 NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR);
181 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
182 "nxge_zcp_err_evnts: buf_tbl_perr"));
183 }
184
185 if (istatus & ICFG_ZCP_TT_PROGRAM_ERR) {
186 statsp->tt_program_err++;
187 NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
188 NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR);
189 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
190 "nxge_zcp_err_evnts: tt_program_err"));
191 }
192
193 if (istatus & ICFG_ZCP_RSP_TT_INDEX_ERR) {
194 statsp->rsp_tt_index_err++;
195 NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
196 NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR);
197 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
198 "nxge_zcp_err_evnts: rsp_tt_index_err"));
199 }
200
201 if (istatus & ICFG_ZCP_SLV_TT_INDEX_ERR) {
202 statsp->slv_tt_index_err++;
203 NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
204 NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR);
205 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
206 "nxge_zcp_err_evnts: slv_tt_index_err"));
207 }
208
209 if (istatus & ICFG_ZCP_TT_INDEX_ERR) {
210 statsp->zcp_tt_index_err++;
211 NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
212 NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR);
213 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
214 "nxge_zcp_err_evnts: tt_index_err"));
215 }
216
217 if (((portn == 0) && (istatus & ICFG_ZCP_CFIFO_ECC0)) ||
218 ((portn == 1) && (istatus & ICFG_ZCP_CFIFO_ECC1)) ||
219 ((portn == 2) && (istatus & ICFG_ZCP_CFIFO_ECC2)) ||
220 ((portn == 3) && (istatus & ICFG_ZCP_CFIFO_ECC3))) {
221 boolean_t ue_ecc_valid;
222
223 if ((status = nxge_ipp_eccue_valid_check(nxgep,
224 &ue_ecc_valid)) != NXGE_OK)
225 return (status);
226
227 if (ue_ecc_valid) {
228 statsp->cfifo_ecc++;
229 NXGE_FM_REPORT_ERROR(nxgep, portn, 0,
230 NXGE_FM_EREPORT_ZCP_CFIFO_ECC);
231 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
232 "nxge_zcp_err_evnts: port%d buf_cfifo_ecc",
233 portn));
234 rxport_fatal = B_TRUE;
235 }
236 }
237
238 /*
239 * Making sure that error source is cleared if this is an injected
240 * error.
241 */
242 switch (portn) {
243 case 0:
244 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
245 break;
246 case 1:
247 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
248 break;
249 case 2:
250 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
251 break;
252 case 3:
253 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
254 break;
255 }
256
257 (void) npi_zcp_clear_istatus(handle);
258
259 if (rxport_fatal) {
260 NXGE_DEBUG_MSG((nxgep, IPP_CTL,
261 " nxge_zcp_handle_sys_errors:"
262 " fatal Error on Port #%d\n", portn));
263 status = nxge_zcp_fatal_err_recover(nxgep);
264 if (status == NXGE_OK) {
265 FM_SERVICE_RESTORED(nxgep);
266 }
267 }
268 return (status);
269 }
270
271 void
nxge_zcp_inject_err(p_nxge_t nxgep,uint32_t err_id)272 nxge_zcp_inject_err(p_nxge_t nxgep, uint32_t err_id)
273 {
274 zcp_int_stat_reg_t zcps;
275 uint8_t portn = nxgep->mac.portnum;
276 zcp_ecc_ctrl_t ecc_ctrl;
277
278 switch (err_id) {
279 case NXGE_FM_EREPORT_ZCP_CFIFO_ECC:
280 ecc_ctrl.value = 0;
281 ecc_ctrl.bits.w0.cor_dbl = 1;
282 ecc_ctrl.bits.w0.cor_lst = 1;
283 ecc_ctrl.bits.w0.cor_all = 0;
284 switch (portn) {
285 case 0:
286 cmn_err(CE_NOTE,
287 "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
288 (unsigned long long) ecc_ctrl.value, portn);
289 NXGE_REG_WR64(nxgep->npi_handle,
290 ZCP_CFIFO_ECC_PORT0_REG,
291 ecc_ctrl.value);
292 break;
293 case 1:
294 cmn_err(CE_NOTE,
295 "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
296 (unsigned long long) ecc_ctrl.value, portn);
297 NXGE_REG_WR64(nxgep->npi_handle,
298 ZCP_CFIFO_ECC_PORT1_REG,
299 ecc_ctrl.value);
300 break;
301 case 2:
302 cmn_err(CE_NOTE,
303 "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
304 (unsigned long long) ecc_ctrl.value, portn);
305 NXGE_REG_WR64(nxgep->npi_handle,
306 ZCP_CFIFO_ECC_PORT2_REG,
307 ecc_ctrl.value);
308 break;
309 case 3:
310 cmn_err(CE_NOTE,
311 "!Write 0x%llx to port%d ZCP_CFIFO_ECC_PORT\n",
312 (unsigned long long) ecc_ctrl.value, portn);
313 NXGE_REG_WR64(nxgep->npi_handle,
314 ZCP_CFIFO_ECC_PORT3_REG,
315 ecc_ctrl.value);
316 break;
317 }
318 break;
319
320 case NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN:
321 case NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR:
322 case NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR:
323 case NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR:
324 case NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR:
325 case NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN:
326 case NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW:
327 case NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR:
328 case NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR:
329 case NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR:
330 case NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR:
331 NXGE_REG_RD64(nxgep->npi_handle, ZCP_INT_STAT_TEST_REG,
332 &zcps.value);
333 if (err_id == NXGE_FM_EREPORT_ZCP_RRFIFO_UNDERRUN)
334 zcps.bits.ldw.rrfifo_urun = 1;
335 if (err_id == NXGE_FM_EREPORT_ZCP_RSPFIFO_UNCORR_ERR)
336 zcps.bits.ldw.rspfifo_uc_err = 1;
337 if (err_id == NXGE_FM_EREPORT_ZCP_STAT_TBL_PERR)
338 zcps.bits.ldw.stat_tbl_perr = 1;
339 if (err_id == NXGE_FM_EREPORT_ZCP_DYN_TBL_PERR)
340 zcps.bits.ldw.dyn_tbl_perr = 1;
341 if (err_id == NXGE_FM_EREPORT_ZCP_BUF_TBL_PERR)
342 zcps.bits.ldw.buf_tbl_perr = 1;
343 if (err_id == NXGE_FM_EREPORT_ZCP_CFIFO_ECC) {
344 switch (portn) {
345 case 0:
346 zcps.bits.ldw.cfifo_ecc0 = 1;
347 break;
348 case 1:
349 zcps.bits.ldw.cfifo_ecc1 = 1;
350 break;
351 case 2:
352 zcps.bits.ldw.cfifo_ecc2 = 1;
353 break;
354 case 3:
355 zcps.bits.ldw.cfifo_ecc3 = 1;
356 break;
357 }
358 }
359 /* FALLTHROUGH */
360
361 default:
362 if (err_id == NXGE_FM_EREPORT_ZCP_RRFIFO_OVERRUN)
363 zcps.bits.ldw.rrfifo_orun = 1;
364 if (err_id == NXGE_FM_EREPORT_ZCP_BUFFER_OVERFLOW)
365 zcps.bits.ldw.buf_overflow = 1;
366 if (err_id == NXGE_FM_EREPORT_ZCP_TT_PROGRAM_ERR)
367 zcps.bits.ldw.tt_tbl_perr = 1;
368 if (err_id == NXGE_FM_EREPORT_ZCP_RSP_TT_INDEX_ERR)
369 zcps.bits.ldw.rsp_tt_index_err = 1;
370 if (err_id == NXGE_FM_EREPORT_ZCP_SLV_TT_INDEX_ERR)
371 zcps.bits.ldw.slv_tt_index_err = 1;
372 if (err_id == NXGE_FM_EREPORT_ZCP_TT_INDEX_ERR)
373 zcps.bits.ldw.zcp_tt_index_err = 1;
374 cmn_err(CE_NOTE, "!Write 0x%lx to ZCP_INT_STAT_TEST_REG\n",
375 zcps.value);
376 NXGE_REG_WR64(nxgep->npi_handle, ZCP_INT_STAT_TEST_REG,
377 zcps.value);
378 break;
379 }
380 }
381
382 nxge_status_t
nxge_zcp_fatal_err_recover(p_nxge_t nxgep)383 nxge_zcp_fatal_err_recover(p_nxge_t nxgep)
384 {
385 npi_handle_t handle;
386 npi_status_t rs = NPI_SUCCESS;
387 nxge_status_t status = NXGE_OK;
388 uint8_t portn;
389 zcp_ram_unit_t w_data;
390 zcp_ram_unit_t r_data;
391 uint32_t cfifo_depth;
392 int i;
393
394 NXGE_DEBUG_MSG((nxgep, RX_CTL, "<== nxge_zcp_fatal_err_recover"));
395 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
396 "Recovering from RxPort error..."));
397
398 handle = nxgep->npi_handle;
399 portn = nxgep->mac.portnum;
400
401 /* Disable RxMAC */
402 if (nxge_rx_mac_disable(nxgep) != NXGE_OK)
403 goto fail;
404
405 /* Make sure source is clear if this is an injected error */
406 switch (portn) {
407 case 0:
408 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT0_REG, 0);
409 break;
410 case 1:
411 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT1_REG, 0);
412 break;
413 case 2:
414 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT2_REG, 0);
415 break;
416 case 3:
417 NXGE_REG_WR64(handle, ZCP_CFIFO_ECC_PORT3_REG, 0);
418 break;
419 }
420
421 /* Clear up CFIFO */
422 if (nxgep->niu_type == N2_NIU) {
423 cfifo_depth = ZCP_NIU_CFIFO_DEPTH;
424 } else if (NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) {
425 if (portn < 2)
426 cfifo_depth = ZCP_P0_P1_CFIFO_DEPTH;
427 else
428 cfifo_depth = ZCP_P2_P3_CFIFO_DEPTH;
429 } else {
430 goto fail;
431 }
432
433 w_data.w0 = 0;
434 w_data.w1 = 0;
435 w_data.w2 = 0;
436 w_data.w3 = 0;
437 w_data.w4 = 0;
438
439 for (i = 0; i < cfifo_depth; i++) {
440 if (npi_zcp_tt_cfifo_entry(handle, OP_SET,
441 portn, i, &w_data) != NPI_SUCCESS)
442 goto fail;
443 if (npi_zcp_tt_cfifo_entry(handle, OP_GET,
444 portn, i, &r_data) != NPI_SUCCESS)
445 goto fail;
446 }
447
448 /* When recovering from ZCP, RxDMA channel resets are not necessary */
449 /* Reset ZCP CFIFO */
450 NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset ZCP CFIFO...", portn));
451 if ((rs = npi_zcp_rest_cfifo_port(handle, portn)) != NPI_SUCCESS)
452 goto fail;
453
454 /* Reset IPP */
455 NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset IPP...", portn));
456 if ((rs = npi_ipp_reset(handle, portn)) != NPI_SUCCESS)
457 goto fail;
458
459 NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Reset RxMAC...", portn));
460 if (nxge_rx_mac_reset(nxgep) != NXGE_OK)
461 goto fail;
462
463 NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Initialize RxMAC...", portn));
464 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK)
465 goto fail;
466
467 NXGE_DEBUG_MSG((nxgep, RX_CTL, "port%d Enable RxMAC...", portn));
468 if (nxge_rx_mac_enable(nxgep) != NXGE_OK)
469 goto fail;
470
471 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
472 "Recovery Sucessful, RxPort Restored"));
473 NXGE_DEBUG_MSG((nxgep, RX_CTL, "==> nxge_zcp_fatal_err_recover"));
474 return (NXGE_OK);
475 fail:
476 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "Recovery failed"));
477 return (status | rs);
478 }
479