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