xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_txc.c (revision 942c5e3c2dd127463517e5cc1694ee94ca45e021)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/nxge/nxge_impl.h>
29 #include <sys/nxge/nxge_txc.h>
30 
31 static nxge_status_t
32 nxge_txc_handle_port_errors(p_nxge_t, uint32_t);
33 static void
34 nxge_txc_inject_port_err(uint8_t, txc_int_stat_dbg_t *,
35 			uint8_t istats);
36 extern nxge_status_t nxge_tx_port_fatal_err_recover(p_nxge_t);
37 
38 nxge_status_t
39 nxge_txc_init(p_nxge_t nxgep)
40 {
41 	uint8_t			port;
42 	npi_handle_t		handle;
43 	npi_status_t		rs = NPI_SUCCESS;
44 
45 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
46 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
47 
48 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_init: portn %d", port));
49 
50 	/*
51 	 * Enable the TXC controller.
52 	 */
53 	if ((rs = npi_txc_global_enable(handle)) != NPI_SUCCESS) {
54 		goto fail;
55 	}
56 
57 	/* Enable this port within the TXC. */
58 	if ((rs = npi_txc_port_enable(handle, port)) != NPI_SUCCESS) {
59 		goto fail;
60 	}
61 
62 	/* Bind DMA channels to this port. */
63 	if ((rs = npi_txc_port_dma_enable(handle, port,
64 			TXDMA_PORT_BITMAP(nxgep))) != NPI_SUCCESS) {
65 		goto fail;
66 	}
67 
68 	/* Unmask all TXC interrupts */
69 	npi_txc_global_imask_set(handle, port, 0);
70 
71 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_init: portn %d", port));
72 
73 	return (NXGE_OK);
74 fail:
75 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
76 			"nxge_txc_init: Failed to initialize txc on port %d",
77 			port));
78 
79 	return (NXGE_ERROR | rs);
80 }
81 
82 nxge_status_t
83 nxge_txc_uninit(p_nxge_t nxgep)
84 {
85 	uint8_t			port;
86 	npi_handle_t		handle;
87 	npi_status_t		rs = NPI_SUCCESS;
88 
89 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
90 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
91 
92 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_uninit: portn %d", port));
93 
94 	/*
95 	 * disable the TXC controller.
96 	 */
97 	if ((rs = npi_txc_global_disable(handle)) != NPI_SUCCESS) {
98 		goto fail;
99 	}
100 
101 	/* disable this port within the TXC. */
102 	if ((rs = npi_txc_port_disable(handle, port)) != NPI_SUCCESS) {
103 		goto fail;
104 	}
105 
106 	/* unbind DMA channels to this port. */
107 	if ((rs = npi_txc_port_dma_enable(handle, port, 0)) != NPI_SUCCESS) {
108 		goto fail;
109 	}
110 
111 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_uninit: portn %d", port));
112 
113 	return (NXGE_OK);
114 fail:
115 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
116 			"nxge_txc_init: Failed to initialize txc on port %d",
117 			port));
118 
119 	return (NXGE_ERROR | rs);
120 }
121 
122 void
123 nxge_txc_regs_dump(p_nxge_t nxgep)
124 {
125 	uint32_t		cnt1, cnt2;
126 	npi_handle_t		handle;
127 	txc_control_t		control;
128 	uint32_t		bitmap = 0;
129 
130 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\nTXC dump: func # %d:\n",
131 		nxgep->function_num));
132 
133 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
134 
135 	(void) npi_txc_control(handle, OP_GET, &control);
136 	(void) npi_txc_port_dma_list_get(handle, nxgep->function_num, &bitmap);
137 
138 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC port control 0x%0llx",
139 		(long long)control.value));
140 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC port bitmap 0x%x", bitmap));
141 
142 	(void) npi_txc_pkt_xmt_to_mac_get(handle, nxgep->function_num,
143 	    &cnt1, &cnt2);
144 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC bytes to MAC %d "
145 		"packets to MAC %d",
146 		cnt1, cnt2));
147 
148 	(void) npi_txc_pkt_stuffed_get(handle, nxgep->function_num,
149 					    &cnt1, &cnt2);
150 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
151 		"\n\tTXC ass packets %d reorder packets %d",
152 		cnt1 & 0xffff, cnt2 & 0xffff));
153 
154 	(void) npi_txc_reorder_get(handle, nxgep->function_num, &cnt1);
155 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
156 		"\n\tTXC reorder resource %d", cnt1 & 0xff));
157 }
158 
159 nxge_status_t
160 nxge_txc_handle_sys_errors(p_nxge_t nxgep)
161 {
162 	npi_handle_t		handle;
163 	txc_int_stat_t		istatus;
164 	uint32_t		err_status;
165 	uint8_t			err_portn;
166 	boolean_t		my_err = B_FALSE;
167 	nxge_status_t		status = NXGE_OK;
168 
169 	handle = nxgep->npi_handle;
170 	npi_txc_global_istatus_get(handle, (txc_int_stat_t *)&istatus.value);
171 	switch (nxgep->mac.portnum) {
172 	case 0:
173 		if (istatus.bits.ldw.port0_int_status) {
174 			my_err = B_TRUE;
175 			err_portn = 0;
176 			err_status = istatus.bits.ldw.port0_int_status;
177 		}
178 		break;
179 	case 1:
180 		if (istatus.bits.ldw.port1_int_status) {
181 			my_err = B_TRUE;
182 			err_portn = 1;
183 			err_status = istatus.bits.ldw.port1_int_status;
184 		}
185 		break;
186 	case 2:
187 		if (istatus.bits.ldw.port2_int_status) {
188 			my_err = B_TRUE;
189 			err_portn = 2;
190 			err_status = istatus.bits.ldw.port2_int_status;
191 		}
192 		break;
193 	case 3:
194 		if (istatus.bits.ldw.port3_int_status) {
195 			my_err = B_TRUE;
196 			err_portn = 3;
197 			err_status = istatus.bits.ldw.port3_int_status;
198 		}
199 		break;
200 	default:
201 		return (NXGE_ERROR);
202 	}
203 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
204 			    " nxge_txc_handle_sys_errors: errored port %d",
205 			    err_portn));
206 	if (my_err) {
207 		status = nxge_txc_handle_port_errors(nxgep, err_status);
208 	}
209 
210 	return (status);
211 }
212 
213 static nxge_status_t
214 nxge_txc_handle_port_errors(p_nxge_t nxgep, uint32_t err_status)
215 {
216 	npi_handle_t		handle;
217 	npi_status_t		rs = NPI_SUCCESS;
218 	p_nxge_txc_stats_t	statsp;
219 	txc_int_stat_t		istatus;
220 	boolean_t		txport_fatal = B_FALSE;
221 	uint8_t			portn;
222 	nxge_status_t		status = NXGE_OK;
223 
224 	handle = nxgep->npi_handle;
225 	statsp = (p_nxge_txc_stats_t)&nxgep->statsp->txc_stats;
226 	portn = nxgep->mac.portnum;
227 	istatus.value = 0;
228 
229 	if ((err_status & TXC_INT_STAT_RO_CORR_ERR) ||
230 			(err_status & TXC_INT_STAT_RO_CORR_ERR) ||
231 			(err_status & TXC_INT_STAT_RO_UNCORR_ERR) ||
232 			(err_status & TXC_INT_STAT_REORDER_ERR)) {
233 		if ((rs = npi_txc_ro_states_get(handle, portn,
234 				&statsp->errlog.ro_st)) != NPI_SUCCESS) {
235 			return (NXGE_ERROR | rs);
236 		}
237 
238 		if (err_status & TXC_INT_STAT_RO_CORR_ERR) {
239 			statsp->ro_correct_err++;
240 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
241 					NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR);
242 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
243 				"nxge_txc_err_evnts: "
244 				"RO FIFO correctable error"));
245 		}
246 		if (err_status & TXC_INT_STAT_RO_UNCORR_ERR) {
247 			statsp->ro_uncorrect_err++;
248 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
249 					NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR);
250 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
251 				"nxge_txc_err_evnts: "
252 				"RO FIFO uncorrectable error"));
253 		}
254 		if (err_status & TXC_INT_STAT_REORDER_ERR) {
255 			statsp->reorder_err++;
256 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
257 					NXGE_FM_EREPORT_TXC_REORDER_ERR);
258 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
259 				"nxge_txc_err_evnts: "
260 				"fatal error: Reorder error"));
261 			txport_fatal = B_TRUE;
262 		}
263 
264 		if ((err_status & TXC_INT_STAT_RO_CORR_ERR) ||
265 			(err_status & TXC_INT_STAT_RO_CORR_ERR) ||
266 			(err_status & TXC_INT_STAT_RO_UNCORR_ERR)) {
267 
268 			if ((rs = npi_txc_ro_ecc_state_clr(handle, portn))
269 							!= NPI_SUCCESS)
270 				return (NXGE_ERROR | rs);
271 			/*
272 			 * Making sure that error source is cleared if this is
273 			 * an injected error.
274 			 */
275 			TXC_FZC_CNTL_REG_WRITE64(handle, TXC_ROECC_CTL_REG,
276 								portn, 0);
277 		}
278 	}
279 
280 	if ((err_status & TXC_INT_STAT_SF_CORR_ERR) ||
281 			(err_status & TXC_INT_STAT_SF_UNCORR_ERR)) {
282 		if ((rs = npi_txc_sf_states_get(handle, portn,
283 				&statsp->errlog.sf_st)) != NPI_SUCCESS) {
284 			return (NXGE_ERROR | rs);
285 		}
286 		if (err_status & TXC_INT_STAT_SF_CORR_ERR) {
287 			statsp->sf_correct_err++;
288 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
289 					NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR);
290 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
291 				"nxge_txc_err_evnts: "
292 				"SF FIFO correctable error"));
293 		}
294 		if (err_status & TXC_INT_STAT_SF_UNCORR_ERR) {
295 			statsp->sf_uncorrect_err++;
296 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
297 					NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR);
298 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
299 				"nxge_txc_err_evnts: "
300 				"SF FIFO uncorrectable error"));
301 		}
302 		if ((rs = npi_txc_sf_ecc_state_clr(handle, portn))
303 							!= NPI_SUCCESS)
304 			return (NXGE_ERROR | rs);
305 		/*
306 		 * Making sure that error source is cleared if this is
307 		 * an injected error.
308 		 */
309 		TXC_FZC_CNTL_REG_WRITE64(handle, TXC_SFECC_CTL_REG, portn, 0);
310 	}
311 
312 	/* Clear corresponding errors */
313 	switch (portn) {
314 	case 0:
315 		istatus.bits.ldw.port0_int_status = err_status;
316 		break;
317 	case 1:
318 		istatus.bits.ldw.port1_int_status = err_status;
319 		break;
320 	case 2:
321 		istatus.bits.ldw.port2_int_status = err_status;
322 		break;
323 	case 3:
324 		istatus.bits.ldw.port3_int_status = err_status;
325 		break;
326 	default:
327 		return (NXGE_ERROR);
328 	}
329 
330 	npi_txc_global_istatus_clear(handle, istatus.value);
331 
332 	if (txport_fatal) {
333 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
334 				" nxge_txc_handle_port_errors:"
335 				" fatal Error on Port#%d\n",
336 				portn));
337 		status = nxge_tx_port_fatal_err_recover(nxgep);
338 		if (status == NXGE_OK) {
339 			FM_SERVICE_RESTORED(nxgep);
340 		}
341 	}
342 
343 	return (status);
344 }
345 
346 void
347 nxge_txc_inject_err(p_nxge_t nxgep, uint32_t err_id)
348 {
349 	txc_int_stat_dbg_t	txcs;
350 	txc_roecc_ctl_t		ro_ecc_ctl;
351 	txc_sfecc_ctl_t		sf_ecc_ctl;
352 	uint8_t			portn = nxgep->mac.portnum;
353 
354 	cmn_err(CE_NOTE, "!TXC error Inject\n");
355 	switch (err_id) {
356 	case NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR:
357 	case NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR:
358 		ro_ecc_ctl.value = 0;
359 		ro_ecc_ctl.bits.ldw.all_pkts = 1;
360 		ro_ecc_ctl.bits.ldw.second_line_pkt = 1;
361 		if (err_id == NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR)
362 			ro_ecc_ctl.bits.ldw.single_bit_err = 1;
363 		else
364 			ro_ecc_ctl.bits.ldw.double_bit_err = 1;
365 #if defined(__i386)
366 		cmn_err(CE_NOTE, "!Write 0x%llx to TXC_ROECC_CTL_REG\n",
367 					ro_ecc_ctl.value);
368 #else
369 		cmn_err(CE_NOTE, "!Write 0x%lx to TXC_ROECC_CTL_REG\n",
370 					ro_ecc_ctl.value);
371 #endif
372 		TXC_FZC_CNTL_REG_WRITE64(nxgep->npi_handle, TXC_ROECC_CTL_REG,
373 					portn, ro_ecc_ctl.value);
374 		break;
375 	case NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR:
376 	case NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR:
377 		sf_ecc_ctl.value = 0;
378 		sf_ecc_ctl.bits.ldw.all_pkts = 1;
379 		sf_ecc_ctl.bits.ldw.second_line_pkt = 1;
380 		if (err_id == NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR)
381 			sf_ecc_ctl.bits.ldw.single_bit_err = 1;
382 		else
383 			sf_ecc_ctl.bits.ldw.double_bit_err = 1;
384 #if defined(__i386)
385 		cmn_err(CE_NOTE, "!Write 0x%llx to TXC_SFECC_CTL_REG\n",
386 					sf_ecc_ctl.value);
387 #else
388 		cmn_err(CE_NOTE, "!Write 0x%lx to TXC_SFECC_CTL_REG\n",
389 					sf_ecc_ctl.value);
390 #endif
391 		TXC_FZC_CNTL_REG_WRITE64(nxgep->npi_handle, TXC_SFECC_CTL_REG,
392 					portn, sf_ecc_ctl.value);
393 		break;
394 	case NXGE_FM_EREPORT_TXC_REORDER_ERR:
395 		NXGE_REG_RD64(nxgep->npi_handle, TXC_INT_STAT_DBG_REG,
396 					&txcs.value);
397 		nxge_txc_inject_port_err(portn, &txcs,
398 						TXC_INT_STAT_REORDER_ERR);
399 #if defined(__i386)
400 		cmn_err(CE_NOTE, "!Write 0x%llx to TXC_INT_STAT_DBG_REG\n",
401 					txcs.value);
402 #else
403 		cmn_err(CE_NOTE, "!Write 0x%lx to TXC_INT_STAT_DBG_REG\n",
404 					txcs.value);
405 #endif
406 		NXGE_REG_WR64(nxgep->npi_handle, TXC_INT_STAT_DBG_REG,
407 					txcs.value);
408 		break;
409 	default:
410 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
411 				"nxge_txc_inject_err: Unknown err_id"));
412 	}
413 }
414 
415 static void
416 nxge_txc_inject_port_err(uint8_t portn, txc_int_stat_dbg_t *txcs,
417 				uint8_t istats)
418 {
419 	switch (portn) {
420 	case 0:
421 		txcs->bits.ldw.port0_int_status |= istats;
422 		break;
423 	case 1:
424 		txcs->bits.ldw.port1_int_status |= istats;
425 		break;
426 	case 2:
427 		txcs->bits.ldw.port2_int_status |= istats;
428 		break;
429 	case 3:
430 		txcs->bits.ldw.port3_int_status |= istats;
431 		break;
432 	default:
433 		;
434 	}
435 }
436