xref: /illumos-gate/usr/src/uts/common/io/nxge/nxge_txc.c (revision 52ccf843)
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 /*
22678453a8Sspeer  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
2344961713Sgirish  * Use is subject to license terms.
2444961713Sgirish  */
2544961713Sgirish 
2644961713Sgirish #pragma ident	"%Z%%M%	%I%	%E% SMI"
2744961713Sgirish 
2844961713Sgirish #include <sys/nxge/nxge_impl.h>
2944961713Sgirish #include <sys/nxge/nxge_txc.h>
3044961713Sgirish 
3144961713Sgirish static nxge_status_t
3244961713Sgirish nxge_txc_handle_port_errors(p_nxge_t, uint32_t);
3344961713Sgirish static void
3444961713Sgirish nxge_txc_inject_port_err(uint8_t, txc_int_stat_dbg_t *,
3544961713Sgirish 			uint8_t istats);
3644961713Sgirish extern nxge_status_t nxge_tx_port_fatal_err_recover(p_nxge_t);
3744961713Sgirish 
3844961713Sgirish nxge_status_t
3944961713Sgirish nxge_txc_init(p_nxge_t nxgep)
4044961713Sgirish {
4144961713Sgirish 	uint8_t			port;
4244961713Sgirish 	npi_handle_t		handle;
4344961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
4444961713Sgirish 
4544961713Sgirish 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
4644961713Sgirish 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
4744961713Sgirish 
4844961713Sgirish 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_init: portn %d", port));
4944961713Sgirish 
5044961713Sgirish 	/*
5144961713Sgirish 	 * Enable the TXC controller.
5244961713Sgirish 	 */
5344961713Sgirish 	if ((rs = npi_txc_global_enable(handle)) != NPI_SUCCESS) {
5444961713Sgirish 		goto fail;
5544961713Sgirish 	}
5644961713Sgirish 
5744961713Sgirish 	/* Enable this port within the TXC. */
5844961713Sgirish 	if ((rs = npi_txc_port_enable(handle, port)) != NPI_SUCCESS) {
5944961713Sgirish 		goto fail;
6044961713Sgirish 	}
6144961713Sgirish 
6244961713Sgirish 	/* Bind DMA channels to this port. */
6344961713Sgirish 	if ((rs = npi_txc_port_dma_enable(handle, port,
64*52ccf843Smisaki 	    TXDMA_PORT_BITMAP(nxgep))) != NPI_SUCCESS) {
6544961713Sgirish 		goto fail;
6644961713Sgirish 	}
6744961713Sgirish 
6844961713Sgirish 	/* Unmask all TXC interrupts */
6944961713Sgirish 	npi_txc_global_imask_set(handle, port, 0);
7044961713Sgirish 
7144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_init: portn %d", port));
7244961713Sgirish 
7344961713Sgirish 	return (NXGE_OK);
7444961713Sgirish fail:
7544961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
76*52ccf843Smisaki 	    "nxge_txc_init: Failed to initialize txc on port %d",
77*52ccf843Smisaki 	    port));
7844961713Sgirish 
7944961713Sgirish 	return (NXGE_ERROR | rs);
8044961713Sgirish }
8144961713Sgirish 
8244961713Sgirish nxge_status_t
8344961713Sgirish nxge_txc_uninit(p_nxge_t nxgep)
8444961713Sgirish {
8544961713Sgirish 	uint8_t			port;
8644961713Sgirish 	npi_handle_t		handle;
8744961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
8844961713Sgirish 
8944961713Sgirish 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
9044961713Sgirish 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
9144961713Sgirish 
9244961713Sgirish 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_uninit: portn %d", port));
9344961713Sgirish 
9444961713Sgirish 	/*
9544961713Sgirish 	 * disable the TXC controller.
9644961713Sgirish 	 */
9744961713Sgirish 	if ((rs = npi_txc_global_disable(handle)) != NPI_SUCCESS) {
9844961713Sgirish 		goto fail;
9944961713Sgirish 	}
10044961713Sgirish 
10144961713Sgirish 	/* disable this port within the TXC. */
10244961713Sgirish 	if ((rs = npi_txc_port_disable(handle, port)) != NPI_SUCCESS) {
10344961713Sgirish 		goto fail;
10444961713Sgirish 	}
10544961713Sgirish 
10644961713Sgirish 	/* unbind DMA channels to this port. */
10744961713Sgirish 	if ((rs = npi_txc_port_dma_enable(handle, port, 0)) != NPI_SUCCESS) {
10844961713Sgirish 		goto fail;
10944961713Sgirish 	}
11044961713Sgirish 
11144961713Sgirish 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_uninit: portn %d", port));
11244961713Sgirish 
11344961713Sgirish 	return (NXGE_OK);
11444961713Sgirish fail:
11544961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
116*52ccf843Smisaki 	    "nxge_txc_init: Failed to initialize txc on port %d",
117*52ccf843Smisaki 	    port));
11844961713Sgirish 
11944961713Sgirish 	return (NXGE_ERROR | rs);
12044961713Sgirish }
12144961713Sgirish 
122678453a8Sspeer /*
123678453a8Sspeer  * nxge_txc_tdc_bind
124678453a8Sspeer  *
125678453a8Sspeer  *	Bind a TDC to a port.
126678453a8Sspeer  *
127678453a8Sspeer  * Arguments:
128678453a8Sspeer  * 	nxgep
129678453a8Sspeer  * 	channel		The channel to bind.
130678453a8Sspeer  *
131678453a8Sspeer  * Notes:
132678453a8Sspeer  *
133678453a8Sspeer  * NPI/NXGE function calls:
134678453a8Sspeer  *	npi_txc_control()
135678453a8Sspeer  *	npi_txc_global_imask_set()
136678453a8Sspeer  *	npi_txc_port_dma_enable()
137678453a8Sspeer  *
138678453a8Sspeer  * Registers accessed:
139678453a8Sspeer  *	TXC_CONTROL
140678453a8Sspeer  *	TXC_PORT_DMA
141678453a8Sspeer  *	TXC_INT_MASK
142678453a8Sspeer  *
143678453a8Sspeer  * Context:
144678453a8Sspeer  *	Service domain
145678453a8Sspeer  */
146678453a8Sspeer nxge_status_t
147678453a8Sspeer nxge_txc_tdc_bind(
148678453a8Sspeer 	p_nxge_t nxgep,
149678453a8Sspeer 	int channel)
150678453a8Sspeer {
151678453a8Sspeer 	uint8_t		port;
152678453a8Sspeer 	uint64_t	bitmap;
153678453a8Sspeer 	npi_handle_t	handle;
154678453a8Sspeer 	npi_status_t	rs = NPI_SUCCESS;
155678453a8Sspeer 	txc_control_t	txc_control;
156678453a8Sspeer 
157678453a8Sspeer 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
158678453a8Sspeer 
159678453a8Sspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
160678453a8Sspeer 	    "==> nxge_txc_tdc_bind(port %d, channel %d)", port, channel));
161678453a8Sspeer 
162678453a8Sspeer 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
163678453a8Sspeer 
164678453a8Sspeer 	/* Get the current value of TXC_CONTROL. */
165678453a8Sspeer 	(void) npi_txc_control(handle, OP_GET, &txc_control);
166678453a8Sspeer 
167678453a8Sspeer 	/* Mask all TXC interrupts for <port>. */
168678453a8Sspeer 	if (txc_control.value & (1 << port)) {
169678453a8Sspeer 		npi_txc_global_imask_set(handle, port, TXC_INT_MASK_IVAL);
170678453a8Sspeer 	}
171678453a8Sspeer 
172678453a8Sspeer 	/* Bind <channel> to <port>. */
173678453a8Sspeer 	/* Read in the old bitmap. */
174678453a8Sspeer 	TXC_FZC_CNTL_REG_READ64(handle, TXC_PORT_DMA_ENABLE_REG, port,
175678453a8Sspeer 	    &bitmap);
176678453a8Sspeer 
177678453a8Sspeer 	if (bitmap & (1 << channel)) {
178678453a8Sspeer 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
179678453a8Sspeer 		    "nxge_txc_tdc_bind: channel %d already bound on port %d",
180*52ccf843Smisaki 		    channel, port));
181678453a8Sspeer 	} else {
182678453a8Sspeer 		/* Bind the new channel. */
183678453a8Sspeer 		bitmap |= (1 << channel);
184678453a8Sspeer 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
185*52ccf843Smisaki 		    "==> nxge_txc_tdc_bind(): bitmap = %lx", bitmap));
186678453a8Sspeer 
187678453a8Sspeer 		/* Write out the new bitmap. */
188678453a8Sspeer 		if ((rs = npi_txc_port_dma_enable(handle, port,
189*52ccf843Smisaki 		    (uint32_t)bitmap)) != NPI_SUCCESS) {
190678453a8Sspeer 			goto fail;
191678453a8Sspeer 		}
192678453a8Sspeer 	}
193678453a8Sspeer 
194678453a8Sspeer 	/* Enable this port, if necessary. */
195678453a8Sspeer 	if (!(txc_control.value & (1 << port))) {
196678453a8Sspeer 		if ((rs = npi_txc_port_enable(handle, port)) != NPI_SUCCESS) {
197678453a8Sspeer 			goto fail;
198678453a8Sspeer 		}
199678453a8Sspeer 	}
200678453a8Sspeer 
201678453a8Sspeer 	/*
202678453a8Sspeer 	 * Enable the TXC controller, if necessary.
203678453a8Sspeer 	 */
204678453a8Sspeer 	if (txc_control.bits.ldw.txc_enabled == 0) {
205678453a8Sspeer 		if ((rs = npi_txc_global_enable(handle)) != NPI_SUCCESS) {
206678453a8Sspeer 			goto fail;
207678453a8Sspeer 		}
208678453a8Sspeer 	}
209678453a8Sspeer 
210678453a8Sspeer 	/* Unmask all TXC interrupts on <port> */
211678453a8Sspeer 	npi_txc_global_imask_set(handle, port, 0);
212678453a8Sspeer 
213678453a8Sspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
214678453a8Sspeer 	    "<== nxge_txc_tdc_bind(port %d, channel %d)", port, channel));
215678453a8Sspeer 
216678453a8Sspeer 	return (NXGE_OK);
217678453a8Sspeer fail:
218678453a8Sspeer 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
219678453a8Sspeer 	    "nxge_txc_tdc_bind(port %d, channel %d) failed", port, channel));
220678453a8Sspeer 
221678453a8Sspeer 	return (NXGE_ERROR | rs);
222678453a8Sspeer }
223678453a8Sspeer 
224678453a8Sspeer /*
225678453a8Sspeer  * nxge_txc_tdc_unbind
226678453a8Sspeer  *
227678453a8Sspeer  *	Unbind a TDC from a port.
228678453a8Sspeer  *
229678453a8Sspeer  * Arguments:
230678453a8Sspeer  * 	nxgep
231678453a8Sspeer  * 	channel		The channel to unbind.
232678453a8Sspeer  *
233678453a8Sspeer  * Notes:
234678453a8Sspeer  *
235678453a8Sspeer  * NPI/NXGE function calls:
236678453a8Sspeer  *	npi_txc_control()
237678453a8Sspeer  *	npi_txc_global_imask_set()
238678453a8Sspeer  *	npi_txc_port_dma_enable()
239678453a8Sspeer  *
240678453a8Sspeer  * Registers accessed:
241678453a8Sspeer  *	TXC_CONTROL
242678453a8Sspeer  *	TXC_PORT_DMA
243678453a8Sspeer  *	TXC_INT_MASK
244678453a8Sspeer  *
245678453a8Sspeer  * Context:
246678453a8Sspeer  *	Service domain
247678453a8Sspeer  */
248678453a8Sspeer nxge_status_t
249678453a8Sspeer nxge_txc_tdc_unbind(
250678453a8Sspeer 	p_nxge_t nxgep,
251678453a8Sspeer 	int channel)
252678453a8Sspeer {
253678453a8Sspeer 	uint8_t		port;
254678453a8Sspeer 	uint64_t	bitmap;
255678453a8Sspeer 	npi_handle_t	handle;
256678453a8Sspeer 	npi_status_t	rs = NPI_SUCCESS;
257678453a8Sspeer 
258678453a8Sspeer 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
259678453a8Sspeer 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
260678453a8Sspeer 
261678453a8Sspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
262678453a8Sspeer 	    "==> nxge_txc_tdc_unbind(port %d, channel %d)", port, channel));
263678453a8Sspeer 
264678453a8Sspeer 	/* Mask all TXC interrupts for <port>. */
265678453a8Sspeer 	npi_txc_global_imask_set(handle, port, TXC_INT_MASK_IVAL);
266678453a8Sspeer 
267678453a8Sspeer 	/* Unbind <channel>. */
268678453a8Sspeer 	/* Read in the old bitmap. */
269678453a8Sspeer 	TXC_FZC_CNTL_REG_READ64(handle, TXC_PORT_DMA_ENABLE_REG, port,
270678453a8Sspeer 	    &bitmap);
271678453a8Sspeer 
272678453a8Sspeer 	bitmap &= (~(1 << channel));
273678453a8Sspeer 
274678453a8Sspeer 	/* Write out the new bitmap. */
275678453a8Sspeer 	if ((rs = npi_txc_port_dma_enable(handle, port,
276*52ccf843Smisaki 	    (uint32_t)bitmap)) != NPI_SUCCESS) {
277678453a8Sspeer 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
278678453a8Sspeer 		    "npi_txc_port_dma_enable(%d, %d) failed: %x",
279*52ccf843Smisaki 		    port, channel, rs));
280678453a8Sspeer 	}
281678453a8Sspeer 
282678453a8Sspeer 	/* Unmask all TXC interrupts on <port> */
283678453a8Sspeer 	if (bitmap)
284678453a8Sspeer 		npi_txc_global_imask_set(handle, port, 0);
285678453a8Sspeer 
286678453a8Sspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
287678453a8Sspeer 	    "<== nxge_txc_tdc_unbind(port %d, channel %d)", port, channel));
288678453a8Sspeer 
289678453a8Sspeer 	return (NXGE_OK);
290678453a8Sspeer fail:
291678453a8Sspeer 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
292678453a8Sspeer 	    "nxge_txc_tdc_unbind(port %d, channel %d) failed", port, channel));
293678453a8Sspeer 
294678453a8Sspeer 	return (NXGE_ERROR | rs);
295678453a8Sspeer }
296678453a8Sspeer 
29744961713Sgirish void
29844961713Sgirish nxge_txc_regs_dump(p_nxge_t nxgep)
29944961713Sgirish {
30044961713Sgirish 	uint32_t		cnt1, cnt2;
30144961713Sgirish 	npi_handle_t		handle;
30244961713Sgirish 	txc_control_t		control;
30344961713Sgirish 	uint32_t		bitmap = 0;
30444961713Sgirish 
305a3c5bd6dSspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\nTXC dump: func # %d:\n",
306*52ccf843Smisaki 	    nxgep->function_num));
30744961713Sgirish 
30844961713Sgirish 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
30944961713Sgirish 
31044961713Sgirish 	(void) npi_txc_control(handle, OP_GET, &control);
31144961713Sgirish 	(void) npi_txc_port_dma_list_get(handle, nxgep->function_num, &bitmap);
31244961713Sgirish 
313a3c5bd6dSspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC port control 0x%0llx",
314*52ccf843Smisaki 	    (long long)control.value));
315a3c5bd6dSspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC port bitmap 0x%x", bitmap));
31644961713Sgirish 
31744961713Sgirish 	(void) npi_txc_pkt_xmt_to_mac_get(handle, nxgep->function_num,
31844961713Sgirish 	    &cnt1, &cnt2);
319a3c5bd6dSspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC bytes to MAC %d "
320*52ccf843Smisaki 	    "packets to MAC %d",
321*52ccf843Smisaki 	    cnt1, cnt2));
32244961713Sgirish 
32344961713Sgirish 	(void) npi_txc_pkt_stuffed_get(handle, nxgep->function_num,
324*52ccf843Smisaki 	    &cnt1, &cnt2);
325a3c5bd6dSspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
326*52ccf843Smisaki 	    "\n\tTXC ass packets %d reorder packets %d",
327*52ccf843Smisaki 	    cnt1 & 0xffff, cnt2 & 0xffff));
32844961713Sgirish 
32944961713Sgirish 	(void) npi_txc_reorder_get(handle, nxgep->function_num, &cnt1);
330a3c5bd6dSspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
331*52ccf843Smisaki 	    "\n\tTXC reorder resource %d", cnt1 & 0xff));
33244961713Sgirish }
33344961713Sgirish 
33444961713Sgirish nxge_status_t
33544961713Sgirish nxge_txc_handle_sys_errors(p_nxge_t nxgep)
33644961713Sgirish {
33744961713Sgirish 	npi_handle_t		handle;
33844961713Sgirish 	txc_int_stat_t		istatus;
33944961713Sgirish 	uint32_t		err_status;
34044961713Sgirish 	uint8_t			err_portn;
34144961713Sgirish 	boolean_t		my_err = B_FALSE;
34244961713Sgirish 	nxge_status_t		status = NXGE_OK;
34344961713Sgirish 
34444961713Sgirish 	handle = nxgep->npi_handle;
34544961713Sgirish 	npi_txc_global_istatus_get(handle, (txc_int_stat_t *)&istatus.value);
34644961713Sgirish 	switch (nxgep->mac.portnum) {
34744961713Sgirish 	case 0:
34844961713Sgirish 		if (istatus.bits.ldw.port0_int_status) {
34944961713Sgirish 			my_err = B_TRUE;
35044961713Sgirish 			err_portn = 0;
35144961713Sgirish 			err_status = istatus.bits.ldw.port0_int_status;
35244961713Sgirish 		}
35344961713Sgirish 		break;
35444961713Sgirish 	case 1:
35544961713Sgirish 		if (istatus.bits.ldw.port1_int_status) {
35644961713Sgirish 			my_err = B_TRUE;
35744961713Sgirish 			err_portn = 1;
35844961713Sgirish 			err_status = istatus.bits.ldw.port1_int_status;
35944961713Sgirish 		}
36044961713Sgirish 		break;
36144961713Sgirish 	case 2:
36244961713Sgirish 		if (istatus.bits.ldw.port2_int_status) {
36344961713Sgirish 			my_err = B_TRUE;
36444961713Sgirish 			err_portn = 2;
36544961713Sgirish 			err_status = istatus.bits.ldw.port2_int_status;
36644961713Sgirish 		}
36744961713Sgirish 		break;
36844961713Sgirish 	case 3:
36944961713Sgirish 		if (istatus.bits.ldw.port3_int_status) {
37044961713Sgirish 			my_err = B_TRUE;
37144961713Sgirish 			err_portn = 3;
37244961713Sgirish 			err_status = istatus.bits.ldw.port3_int_status;
37344961713Sgirish 		}
37444961713Sgirish 		break;
37544961713Sgirish 	default:
37644961713Sgirish 		return (NXGE_ERROR);
37744961713Sgirish 	}
37844961713Sgirish 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
379*52ccf843Smisaki 	    " nxge_txc_handle_sys_errors: errored port %d",
380*52ccf843Smisaki 	    err_portn));
38144961713Sgirish 	if (my_err) {
38244961713Sgirish 		status = nxge_txc_handle_port_errors(nxgep, err_status);
38344961713Sgirish 	}
38444961713Sgirish 
38544961713Sgirish 	return (status);
38644961713Sgirish }
38744961713Sgirish 
38844961713Sgirish static nxge_status_t
38944961713Sgirish nxge_txc_handle_port_errors(p_nxge_t nxgep, uint32_t err_status)
39044961713Sgirish {
39144961713Sgirish 	npi_handle_t		handle;
39244961713Sgirish 	npi_status_t		rs = NPI_SUCCESS;
39344961713Sgirish 	p_nxge_txc_stats_t	statsp;
39444961713Sgirish 	txc_int_stat_t		istatus;
39544961713Sgirish 	boolean_t		txport_fatal = B_FALSE;
39644961713Sgirish 	uint8_t			portn;
39744961713Sgirish 	nxge_status_t		status = NXGE_OK;
39844961713Sgirish 
39944961713Sgirish 	handle = nxgep->npi_handle;
40044961713Sgirish 	statsp = (p_nxge_txc_stats_t)&nxgep->statsp->txc_stats;
40144961713Sgirish 	portn = nxgep->mac.portnum;
40244961713Sgirish 	istatus.value = 0;
40344961713Sgirish 
40444961713Sgirish 	if ((err_status & TXC_INT_STAT_RO_CORR_ERR) ||
405*52ccf843Smisaki 	    (err_status & TXC_INT_STAT_RO_CORR_ERR) ||
406*52ccf843Smisaki 	    (err_status & TXC_INT_STAT_RO_UNCORR_ERR) ||
407*52ccf843Smisaki 	    (err_status & TXC_INT_STAT_REORDER_ERR)) {
40844961713Sgirish 		if ((rs = npi_txc_ro_states_get(handle, portn,
409*52ccf843Smisaki 		    &statsp->errlog.ro_st)) != NPI_SUCCESS) {
41044961713Sgirish 			return (NXGE_ERROR | rs);
41144961713Sgirish 		}
41244961713Sgirish 
41344961713Sgirish 		if (err_status & TXC_INT_STAT_RO_CORR_ERR) {
41444961713Sgirish 			statsp->ro_correct_err++;
41544961713Sgirish 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
416*52ccf843Smisaki 			    NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR);
41744961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
418*52ccf843Smisaki 			    "nxge_txc_err_evnts: "
419*52ccf843Smisaki 			    "RO FIFO correctable error"));
42044961713Sgirish 		}
42144961713Sgirish 		if (err_status & TXC_INT_STAT_RO_UNCORR_ERR) {
42244961713Sgirish 			statsp->ro_uncorrect_err++;
42344961713Sgirish 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
424*52ccf843Smisaki 			    NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR);
42544961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
426*52ccf843Smisaki 			    "nxge_txc_err_evnts: "
427*52ccf843Smisaki 			    "RO FIFO uncorrectable error"));
42844961713Sgirish 		}
42944961713Sgirish 		if (err_status & TXC_INT_STAT_REORDER_ERR) {
43044961713Sgirish 			statsp->reorder_err++;
43144961713Sgirish 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
432*52ccf843Smisaki 			    NXGE_FM_EREPORT_TXC_REORDER_ERR);
43344961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
434*52ccf843Smisaki 			    "nxge_txc_err_evnts: "
435*52ccf843Smisaki 			    "fatal error: Reorder error"));
43644961713Sgirish 			txport_fatal = B_TRUE;
43744961713Sgirish 		}
43844961713Sgirish 
43944961713Sgirish 		if ((err_status & TXC_INT_STAT_RO_CORR_ERR) ||
440*52ccf843Smisaki 		    (err_status & TXC_INT_STAT_RO_CORR_ERR) ||
441*52ccf843Smisaki 		    (err_status & TXC_INT_STAT_RO_UNCORR_ERR)) {
44244961713Sgirish 
44344961713Sgirish 			if ((rs = npi_txc_ro_ecc_state_clr(handle, portn))
444*52ccf843Smisaki 			    != NPI_SUCCESS)
44544961713Sgirish 				return (NXGE_ERROR | rs);
44644961713Sgirish 			/*
44744961713Sgirish 			 * Making sure that error source is cleared if this is
44844961713Sgirish 			 * an injected error.
44944961713Sgirish 			 */
45044961713Sgirish 			TXC_FZC_CNTL_REG_WRITE64(handle, TXC_ROECC_CTL_REG,
451*52ccf843Smisaki 			    portn, 0);
45244961713Sgirish 		}
45344961713Sgirish 	}
45444961713Sgirish 
45544961713Sgirish 	if ((err_status & TXC_INT_STAT_SF_CORR_ERR) ||
456*52ccf843Smisaki 	    (err_status & TXC_INT_STAT_SF_UNCORR_ERR)) {
45744961713Sgirish 		if ((rs = npi_txc_sf_states_get(handle, portn,
458*52ccf843Smisaki 		    &statsp->errlog.sf_st)) != NPI_SUCCESS) {
45944961713Sgirish 			return (NXGE_ERROR | rs);
46044961713Sgirish 		}
46144961713Sgirish 		if (err_status & TXC_INT_STAT_SF_CORR_ERR) {
46244961713Sgirish 			statsp->sf_correct_err++;
46344961713Sgirish 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
464*52ccf843Smisaki 			    NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR);
46544961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
466*52ccf843Smisaki 			    "nxge_txc_err_evnts: "
467*52ccf843Smisaki 			    "SF FIFO correctable error"));
46844961713Sgirish 		}
46944961713Sgirish 		if (err_status & TXC_INT_STAT_SF_UNCORR_ERR) {
47044961713Sgirish 			statsp->sf_uncorrect_err++;
47144961713Sgirish 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
472*52ccf843Smisaki 			    NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR);
47344961713Sgirish 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
474*52ccf843Smisaki 			    "nxge_txc_err_evnts: "
475*52ccf843Smisaki 			    "SF FIFO uncorrectable error"));
47644961713Sgirish 		}
47744961713Sgirish 		if ((rs = npi_txc_sf_ecc_state_clr(handle, portn))
478*52ccf843Smisaki 		    != NPI_SUCCESS)
47944961713Sgirish 			return (NXGE_ERROR | rs);
48044961713Sgirish 		/*
48144961713Sgirish 		 * Making sure that error source is cleared if this is
48244961713Sgirish 		 * an injected error.
48344961713Sgirish 		 */
48444961713Sgirish 		TXC_FZC_CNTL_REG_WRITE64(handle, TXC_SFECC_CTL_REG, portn, 0);
48544961713Sgirish 	}
48644961713Sgirish 
48744961713Sgirish 	/* Clear corresponding errors */
48844961713Sgirish 	switch (portn) {
48944961713Sgirish 	case 0:
49044961713Sgirish 		istatus.bits.ldw.port0_int_status = err_status;
49144961713Sgirish 		break;
49244961713Sgirish 	case 1:
49344961713Sgirish 		istatus.bits.ldw.port1_int_status = err_status;
49444961713Sgirish 		break;
49544961713Sgirish 	case 2:
49644961713Sgirish 		istatus.bits.ldw.port2_int_status = err_status;
49744961713Sgirish 		break;
49844961713Sgirish 	case 3:
49944961713Sgirish 		istatus.bits.ldw.port3_int_status = err_status;
50044961713Sgirish 		break;
50144961713Sgirish 	default:
50244961713Sgirish 		return (NXGE_ERROR);
50344961713Sgirish 	}
50444961713Sgirish 
50544961713Sgirish 	npi_txc_global_istatus_clear(handle, istatus.value);
50644961713Sgirish 
50744961713Sgirish 	if (txport_fatal) {
50844961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
509*52ccf843Smisaki 		    " nxge_txc_handle_port_errors:"
510*52ccf843Smisaki 		    " fatal Error on Port#%d\n",
511*52ccf843Smisaki 		    portn));
51244961713Sgirish 		status = nxge_tx_port_fatal_err_recover(nxgep);
51344961713Sgirish 		if (status == NXGE_OK) {
51444961713Sgirish 			FM_SERVICE_RESTORED(nxgep);
51544961713Sgirish 		}
51644961713Sgirish 	}
51744961713Sgirish 
51844961713Sgirish 	return (status);
51944961713Sgirish }
52044961713Sgirish 
52144961713Sgirish void
52244961713Sgirish nxge_txc_inject_err(p_nxge_t nxgep, uint32_t err_id)
52344961713Sgirish {
52444961713Sgirish 	txc_int_stat_dbg_t	txcs;
52544961713Sgirish 	txc_roecc_ctl_t		ro_ecc_ctl;
52644961713Sgirish 	txc_sfecc_ctl_t		sf_ecc_ctl;
52744961713Sgirish 	uint8_t			portn = nxgep->mac.portnum;
52844961713Sgirish 
52944961713Sgirish 	cmn_err(CE_NOTE, "!TXC error Inject\n");
53044961713Sgirish 	switch (err_id) {
53144961713Sgirish 	case NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR:
53244961713Sgirish 	case NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR:
53344961713Sgirish 		ro_ecc_ctl.value = 0;
53444961713Sgirish 		ro_ecc_ctl.bits.ldw.all_pkts = 1;
53544961713Sgirish 		ro_ecc_ctl.bits.ldw.second_line_pkt = 1;
53644961713Sgirish 		if (err_id == NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR)
53744961713Sgirish 			ro_ecc_ctl.bits.ldw.single_bit_err = 1;
53844961713Sgirish 		else
53944961713Sgirish 			ro_ecc_ctl.bits.ldw.double_bit_err = 1;
540adfcba55Sjoycey #if defined(__i386)
541adfcba55Sjoycey 		cmn_err(CE_NOTE, "!Write 0x%llx to TXC_ROECC_CTL_REG\n",
542*52ccf843Smisaki 		    ro_ecc_ctl.value);
543adfcba55Sjoycey #else
54444961713Sgirish 		cmn_err(CE_NOTE, "!Write 0x%lx to TXC_ROECC_CTL_REG\n",
545*52ccf843Smisaki 		    ro_ecc_ctl.value);
546adfcba55Sjoycey #endif
54744961713Sgirish 		TXC_FZC_CNTL_REG_WRITE64(nxgep->npi_handle, TXC_ROECC_CTL_REG,
548*52ccf843Smisaki 		    portn, ro_ecc_ctl.value);
54944961713Sgirish 		break;
55044961713Sgirish 	case NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR:
55144961713Sgirish 	case NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR:
55244961713Sgirish 		sf_ecc_ctl.value = 0;
55344961713Sgirish 		sf_ecc_ctl.bits.ldw.all_pkts = 1;
55444961713Sgirish 		sf_ecc_ctl.bits.ldw.second_line_pkt = 1;
55544961713Sgirish 		if (err_id == NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR)
55644961713Sgirish 			sf_ecc_ctl.bits.ldw.single_bit_err = 1;
55744961713Sgirish 		else
55844961713Sgirish 			sf_ecc_ctl.bits.ldw.double_bit_err = 1;
559adfcba55Sjoycey #if defined(__i386)
560adfcba55Sjoycey 		cmn_err(CE_NOTE, "!Write 0x%llx to TXC_SFECC_CTL_REG\n",
561*52ccf843Smisaki 		    sf_ecc_ctl.value);
562adfcba55Sjoycey #else
56344961713Sgirish 		cmn_err(CE_NOTE, "!Write 0x%lx to TXC_SFECC_CTL_REG\n",
564*52ccf843Smisaki 		    sf_ecc_ctl.value);
565adfcba55Sjoycey #endif
56644961713Sgirish 		TXC_FZC_CNTL_REG_WRITE64(nxgep->npi_handle, TXC_SFECC_CTL_REG,
567*52ccf843Smisaki 		    portn, sf_ecc_ctl.value);
56844961713Sgirish 		break;
56944961713Sgirish 	case NXGE_FM_EREPORT_TXC_REORDER_ERR:
57044961713Sgirish 		NXGE_REG_RD64(nxgep->npi_handle, TXC_INT_STAT_DBG_REG,
571*52ccf843Smisaki 		    &txcs.value);
57244961713Sgirish 		nxge_txc_inject_port_err(portn, &txcs,
573*52ccf843Smisaki 		    TXC_INT_STAT_REORDER_ERR);
574adfcba55Sjoycey #if defined(__i386)
575adfcba55Sjoycey 		cmn_err(CE_NOTE, "!Write 0x%llx to TXC_INT_STAT_DBG_REG\n",
576*52ccf843Smisaki 		    txcs.value);
577adfcba55Sjoycey #else
57844961713Sgirish 		cmn_err(CE_NOTE, "!Write 0x%lx to TXC_INT_STAT_DBG_REG\n",
579*52ccf843Smisaki 		    txcs.value);
580adfcba55Sjoycey #endif
58144961713Sgirish 		NXGE_REG_WR64(nxgep->npi_handle, TXC_INT_STAT_DBG_REG,
582*52ccf843Smisaki 		    txcs.value);
58344961713Sgirish 		break;
58444961713Sgirish 	default:
58544961713Sgirish 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
586*52ccf843Smisaki 		    "nxge_txc_inject_err: Unknown err_id"));
58744961713Sgirish 	}
58844961713Sgirish }
58944961713Sgirish 
59044961713Sgirish static void
59144961713Sgirish nxge_txc_inject_port_err(uint8_t portn, txc_int_stat_dbg_t *txcs,
59244961713Sgirish 				uint8_t istats)
59344961713Sgirish {
59444961713Sgirish 	switch (portn) {
59544961713Sgirish 	case 0:
59644961713Sgirish 		txcs->bits.ldw.port0_int_status |= istats;
59744961713Sgirish 		break;
59844961713Sgirish 	case 1:
59944961713Sgirish 		txcs->bits.ldw.port1_int_status |= istats;
60044961713Sgirish 		break;
60144961713Sgirish 	case 2:
60244961713Sgirish 		txcs->bits.ldw.port2_int_status |= istats;
60344961713Sgirish 		break;
60444961713Sgirish 	case 3:
60544961713Sgirish 		txcs->bits.ldw.port3_int_status |= istats;
60644961713Sgirish 		break;
60744961713Sgirish 	default:
60844961713Sgirish 		;
60944961713Sgirish 	}
61044961713Sgirish }
611