xref: /onnv-gate/usr/src/uts/common/io/nxge/nxge_txc.c (revision 6929:a596171cbf16)
13859Sml29623 /*
23859Sml29623  * CDDL HEADER START
33859Sml29623  *
43859Sml29623  * The contents of this file are subject to the terms of the
53859Sml29623  * Common Development and Distribution License (the "License").
63859Sml29623  * You may not use this file except in compliance with the License.
73859Sml29623  *
83859Sml29623  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93859Sml29623  * or http://www.opensolaris.org/os/licensing.
103859Sml29623  * See the License for the specific language governing permissions
113859Sml29623  * and limitations under the License.
123859Sml29623  *
133859Sml29623  * When distributing Covered Code, include this CDDL HEADER in each
143859Sml29623  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153859Sml29623  * If applicable, add the following below this CDDL HEADER, with the
163859Sml29623  * fields enclosed by brackets "[]" replaced with your own identifying
173859Sml29623  * information: Portions Copyright [yyyy] [name of copyright owner]
183859Sml29623  *
193859Sml29623  * CDDL HEADER END
203859Sml29623  */
213859Sml29623 /*
226495Sspeer  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
233859Sml29623  * Use is subject to license terms.
243859Sml29623  */
253859Sml29623 
263859Sml29623 #pragma ident	"%Z%%M%	%I%	%E% SMI"
273859Sml29623 
283859Sml29623 #include <sys/nxge/nxge_impl.h>
293859Sml29623 #include <sys/nxge/nxge_txc.h>
303859Sml29623 
313859Sml29623 static nxge_status_t
323859Sml29623 nxge_txc_handle_port_errors(p_nxge_t, uint32_t);
333859Sml29623 static void
343859Sml29623 nxge_txc_inject_port_err(uint8_t, txc_int_stat_dbg_t *,
353859Sml29623 			uint8_t istats);
363859Sml29623 extern nxge_status_t nxge_tx_port_fatal_err_recover(p_nxge_t);
373859Sml29623 
383859Sml29623 nxge_status_t
nxge_txc_init(p_nxge_t nxgep)393859Sml29623 nxge_txc_init(p_nxge_t nxgep)
403859Sml29623 {
413859Sml29623 	uint8_t			port;
423859Sml29623 	npi_handle_t		handle;
433859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
443859Sml29623 
453859Sml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
463859Sml29623 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
473859Sml29623 
483859Sml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_init: portn %d", port));
493859Sml29623 
503859Sml29623 	/*
513859Sml29623 	 * Enable the TXC controller.
523859Sml29623 	 */
533859Sml29623 	if ((rs = npi_txc_global_enable(handle)) != NPI_SUCCESS) {
543859Sml29623 		goto fail;
553859Sml29623 	}
563859Sml29623 
573859Sml29623 	/* Enable this port within the TXC. */
583859Sml29623 	if ((rs = npi_txc_port_enable(handle, port)) != NPI_SUCCESS) {
593859Sml29623 		goto fail;
603859Sml29623 	}
613859Sml29623 
623859Sml29623 	/* Bind DMA channels to this port. */
633859Sml29623 	if ((rs = npi_txc_port_dma_enable(handle, port,
64*6929Smisaki 	    TXDMA_PORT_BITMAP(nxgep))) != NPI_SUCCESS) {
653859Sml29623 		goto fail;
663859Sml29623 	}
673859Sml29623 
683859Sml29623 	/* Unmask all TXC interrupts */
693859Sml29623 	npi_txc_global_imask_set(handle, port, 0);
703859Sml29623 
713859Sml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_init: portn %d", port));
723859Sml29623 
733859Sml29623 	return (NXGE_OK);
743859Sml29623 fail:
753859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
76*6929Smisaki 	    "nxge_txc_init: Failed to initialize txc on port %d",
77*6929Smisaki 	    port));
783859Sml29623 
793859Sml29623 	return (NXGE_ERROR | rs);
803859Sml29623 }
813859Sml29623 
823859Sml29623 nxge_status_t
nxge_txc_uninit(p_nxge_t nxgep)833859Sml29623 nxge_txc_uninit(p_nxge_t nxgep)
843859Sml29623 {
853859Sml29623 	uint8_t			port;
863859Sml29623 	npi_handle_t		handle;
873859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
883859Sml29623 
893859Sml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
903859Sml29623 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
913859Sml29623 
923859Sml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_uninit: portn %d", port));
933859Sml29623 
943859Sml29623 	/*
953859Sml29623 	 * disable the TXC controller.
963859Sml29623 	 */
973859Sml29623 	if ((rs = npi_txc_global_disable(handle)) != NPI_SUCCESS) {
983859Sml29623 		goto fail;
993859Sml29623 	}
1003859Sml29623 
1013859Sml29623 	/* disable this port within the TXC. */
1023859Sml29623 	if ((rs = npi_txc_port_disable(handle, port)) != NPI_SUCCESS) {
1033859Sml29623 		goto fail;
1043859Sml29623 	}
1053859Sml29623 
1063859Sml29623 	/* unbind DMA channels to this port. */
1073859Sml29623 	if ((rs = npi_txc_port_dma_enable(handle, port, 0)) != NPI_SUCCESS) {
1083859Sml29623 		goto fail;
1093859Sml29623 	}
1103859Sml29623 
1113859Sml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_uninit: portn %d", port));
1123859Sml29623 
1133859Sml29623 	return (NXGE_OK);
1143859Sml29623 fail:
1153859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
116*6929Smisaki 	    "nxge_txc_init: Failed to initialize txc on port %d",
117*6929Smisaki 	    port));
1183859Sml29623 
1193859Sml29623 	return (NXGE_ERROR | rs);
1203859Sml29623 }
1213859Sml29623 
1226495Sspeer /*
1236495Sspeer  * nxge_txc_tdc_bind
1246495Sspeer  *
1256495Sspeer  *	Bind a TDC to a port.
1266495Sspeer  *
1276495Sspeer  * Arguments:
1286495Sspeer  * 	nxgep
1296495Sspeer  * 	channel		The channel to bind.
1306495Sspeer  *
1316495Sspeer  * Notes:
1326495Sspeer  *
1336495Sspeer  * NPI/NXGE function calls:
1346495Sspeer  *	npi_txc_control()
1356495Sspeer  *	npi_txc_global_imask_set()
1366495Sspeer  *	npi_txc_port_dma_enable()
1376495Sspeer  *
1386495Sspeer  * Registers accessed:
1396495Sspeer  *	TXC_CONTROL
1406495Sspeer  *	TXC_PORT_DMA
1416495Sspeer  *	TXC_INT_MASK
1426495Sspeer  *
1436495Sspeer  * Context:
1446495Sspeer  *	Service domain
1456495Sspeer  */
1466495Sspeer nxge_status_t
nxge_txc_tdc_bind(p_nxge_t nxgep,int channel)1476495Sspeer nxge_txc_tdc_bind(
1486495Sspeer 	p_nxge_t nxgep,
1496495Sspeer 	int channel)
1506495Sspeer {
1516495Sspeer 	uint8_t		port;
1526495Sspeer 	uint64_t	bitmap;
1536495Sspeer 	npi_handle_t	handle;
1546495Sspeer 	npi_status_t	rs = NPI_SUCCESS;
1556495Sspeer 	txc_control_t	txc_control;
1566495Sspeer 
1576495Sspeer 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
1586495Sspeer 
1596495Sspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
1606495Sspeer 	    "==> nxge_txc_tdc_bind(port %d, channel %d)", port, channel));
1616495Sspeer 
1626495Sspeer 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
1636495Sspeer 
1646495Sspeer 	/* Get the current value of TXC_CONTROL. */
1656495Sspeer 	(void) npi_txc_control(handle, OP_GET, &txc_control);
1666495Sspeer 
1676495Sspeer 	/* Mask all TXC interrupts for <port>. */
1686495Sspeer 	if (txc_control.value & (1 << port)) {
1696495Sspeer 		npi_txc_global_imask_set(handle, port, TXC_INT_MASK_IVAL);
1706495Sspeer 	}
1716495Sspeer 
1726495Sspeer 	/* Bind <channel> to <port>. */
1736495Sspeer 	/* Read in the old bitmap. */
1746495Sspeer 	TXC_FZC_CNTL_REG_READ64(handle, TXC_PORT_DMA_ENABLE_REG, port,
1756495Sspeer 	    &bitmap);
1766495Sspeer 
1776495Sspeer 	if (bitmap & (1 << channel)) {
1786495Sspeer 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1796495Sspeer 		    "nxge_txc_tdc_bind: channel %d already bound on port %d",
180*6929Smisaki 		    channel, port));
1816495Sspeer 	} else {
1826495Sspeer 		/* Bind the new channel. */
1836495Sspeer 		bitmap |= (1 << channel);
1846495Sspeer 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
185*6929Smisaki 		    "==> nxge_txc_tdc_bind(): bitmap = %lx", bitmap));
1866495Sspeer 
1876495Sspeer 		/* Write out the new bitmap. */
1886495Sspeer 		if ((rs = npi_txc_port_dma_enable(handle, port,
189*6929Smisaki 		    (uint32_t)bitmap)) != NPI_SUCCESS) {
1906495Sspeer 			goto fail;
1916495Sspeer 		}
1926495Sspeer 	}
1936495Sspeer 
1946495Sspeer 	/* Enable this port, if necessary. */
1956495Sspeer 	if (!(txc_control.value & (1 << port))) {
1966495Sspeer 		if ((rs = npi_txc_port_enable(handle, port)) != NPI_SUCCESS) {
1976495Sspeer 			goto fail;
1986495Sspeer 		}
1996495Sspeer 	}
2006495Sspeer 
2016495Sspeer 	/*
2026495Sspeer 	 * Enable the TXC controller, if necessary.
2036495Sspeer 	 */
2046495Sspeer 	if (txc_control.bits.ldw.txc_enabled == 0) {
2056495Sspeer 		if ((rs = npi_txc_global_enable(handle)) != NPI_SUCCESS) {
2066495Sspeer 			goto fail;
2076495Sspeer 		}
2086495Sspeer 	}
2096495Sspeer 
2106495Sspeer 	/* Unmask all TXC interrupts on <port> */
2116495Sspeer 	npi_txc_global_imask_set(handle, port, 0);
2126495Sspeer 
2136495Sspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
2146495Sspeer 	    "<== nxge_txc_tdc_bind(port %d, channel %d)", port, channel));
2156495Sspeer 
2166495Sspeer 	return (NXGE_OK);
2176495Sspeer fail:
2186495Sspeer 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2196495Sspeer 	    "nxge_txc_tdc_bind(port %d, channel %d) failed", port, channel));
2206495Sspeer 
2216495Sspeer 	return (NXGE_ERROR | rs);
2226495Sspeer }
2236495Sspeer 
2246495Sspeer /*
2256495Sspeer  * nxge_txc_tdc_unbind
2266495Sspeer  *
2276495Sspeer  *	Unbind a TDC from a port.
2286495Sspeer  *
2296495Sspeer  * Arguments:
2306495Sspeer  * 	nxgep
2316495Sspeer  * 	channel		The channel to unbind.
2326495Sspeer  *
2336495Sspeer  * Notes:
2346495Sspeer  *
2356495Sspeer  * NPI/NXGE function calls:
2366495Sspeer  *	npi_txc_control()
2376495Sspeer  *	npi_txc_global_imask_set()
2386495Sspeer  *	npi_txc_port_dma_enable()
2396495Sspeer  *
2406495Sspeer  * Registers accessed:
2416495Sspeer  *	TXC_CONTROL
2426495Sspeer  *	TXC_PORT_DMA
2436495Sspeer  *	TXC_INT_MASK
2446495Sspeer  *
2456495Sspeer  * Context:
2466495Sspeer  *	Service domain
2476495Sspeer  */
2486495Sspeer nxge_status_t
nxge_txc_tdc_unbind(p_nxge_t nxgep,int channel)2496495Sspeer nxge_txc_tdc_unbind(
2506495Sspeer 	p_nxge_t nxgep,
2516495Sspeer 	int channel)
2526495Sspeer {
2536495Sspeer 	uint8_t		port;
2546495Sspeer 	uint64_t	bitmap;
2556495Sspeer 	npi_handle_t	handle;
2566495Sspeer 	npi_status_t	rs = NPI_SUCCESS;
2576495Sspeer 
2586495Sspeer 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
2596495Sspeer 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
2606495Sspeer 
2616495Sspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
2626495Sspeer 	    "==> nxge_txc_tdc_unbind(port %d, channel %d)", port, channel));
2636495Sspeer 
2646495Sspeer 	/* Mask all TXC interrupts for <port>. */
2656495Sspeer 	npi_txc_global_imask_set(handle, port, TXC_INT_MASK_IVAL);
2666495Sspeer 
2676495Sspeer 	/* Unbind <channel>. */
2686495Sspeer 	/* Read in the old bitmap. */
2696495Sspeer 	TXC_FZC_CNTL_REG_READ64(handle, TXC_PORT_DMA_ENABLE_REG, port,
2706495Sspeer 	    &bitmap);
2716495Sspeer 
2726495Sspeer 	bitmap &= (~(1 << channel));
2736495Sspeer 
2746495Sspeer 	/* Write out the new bitmap. */
2756495Sspeer 	if ((rs = npi_txc_port_dma_enable(handle, port,
276*6929Smisaki 	    (uint32_t)bitmap)) != NPI_SUCCESS) {
2776495Sspeer 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2786495Sspeer 		    "npi_txc_port_dma_enable(%d, %d) failed: %x",
279*6929Smisaki 		    port, channel, rs));
2806495Sspeer 	}
2816495Sspeer 
2826495Sspeer 	/* Unmask all TXC interrupts on <port> */
2836495Sspeer 	if (bitmap)
2846495Sspeer 		npi_txc_global_imask_set(handle, port, 0);
2856495Sspeer 
2866495Sspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
2876495Sspeer 	    "<== nxge_txc_tdc_unbind(port %d, channel %d)", port, channel));
2886495Sspeer 
2896495Sspeer 	return (NXGE_OK);
2906495Sspeer fail:
2916495Sspeer 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
2926495Sspeer 	    "nxge_txc_tdc_unbind(port %d, channel %d) failed", port, channel));
2936495Sspeer 
2946495Sspeer 	return (NXGE_ERROR | rs);
2956495Sspeer }
2966495Sspeer 
2973859Sml29623 void
nxge_txc_regs_dump(p_nxge_t nxgep)2983859Sml29623 nxge_txc_regs_dump(p_nxge_t nxgep)
2993859Sml29623 {
3003859Sml29623 	uint32_t		cnt1, cnt2;
3013859Sml29623 	npi_handle_t		handle;
3023859Sml29623 	txc_control_t		control;
3033859Sml29623 	uint32_t		bitmap = 0;
3043859Sml29623 
3053859Sml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\nTXC dump: func # %d:\n",
306*6929Smisaki 	    nxgep->function_num));
3073859Sml29623 
3083859Sml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
3093859Sml29623 
3103859Sml29623 	(void) npi_txc_control(handle, OP_GET, &control);
3113859Sml29623 	(void) npi_txc_port_dma_list_get(handle, nxgep->function_num, &bitmap);
3123859Sml29623 
3133859Sml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC port control 0x%0llx",
314*6929Smisaki 	    (long long)control.value));
3153859Sml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC port bitmap 0x%x", bitmap));
3163859Sml29623 
3173859Sml29623 	(void) npi_txc_pkt_xmt_to_mac_get(handle, nxgep->function_num,
3183859Sml29623 	    &cnt1, &cnt2);
3193859Sml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC bytes to MAC %d "
320*6929Smisaki 	    "packets to MAC %d",
321*6929Smisaki 	    cnt1, cnt2));
3223859Sml29623 
3233859Sml29623 	(void) npi_txc_pkt_stuffed_get(handle, nxgep->function_num,
324*6929Smisaki 	    &cnt1, &cnt2);
3253859Sml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
326*6929Smisaki 	    "\n\tTXC ass packets %d reorder packets %d",
327*6929Smisaki 	    cnt1 & 0xffff, cnt2 & 0xffff));
3283859Sml29623 
3293859Sml29623 	(void) npi_txc_reorder_get(handle, nxgep->function_num, &cnt1);
3303859Sml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
331*6929Smisaki 	    "\n\tTXC reorder resource %d", cnt1 & 0xff));
3323859Sml29623 }
3333859Sml29623 
3343859Sml29623 nxge_status_t
nxge_txc_handle_sys_errors(p_nxge_t nxgep)3353859Sml29623 nxge_txc_handle_sys_errors(p_nxge_t nxgep)
3363859Sml29623 {
3373859Sml29623 	npi_handle_t		handle;
3383859Sml29623 	txc_int_stat_t		istatus;
3393859Sml29623 	uint32_t		err_status;
3403859Sml29623 	uint8_t			err_portn;
3413859Sml29623 	boolean_t		my_err = B_FALSE;
3423859Sml29623 	nxge_status_t		status = NXGE_OK;
3433859Sml29623 
3443859Sml29623 	handle = nxgep->npi_handle;
3453859Sml29623 	npi_txc_global_istatus_get(handle, (txc_int_stat_t *)&istatus.value);
3463859Sml29623 	switch (nxgep->mac.portnum) {
3473859Sml29623 	case 0:
3483859Sml29623 		if (istatus.bits.ldw.port0_int_status) {
3493859Sml29623 			my_err = B_TRUE;
3503859Sml29623 			err_portn = 0;
3513859Sml29623 			err_status = istatus.bits.ldw.port0_int_status;
3523859Sml29623 		}
3533859Sml29623 		break;
3543859Sml29623 	case 1:
3553859Sml29623 		if (istatus.bits.ldw.port1_int_status) {
3563859Sml29623 			my_err = B_TRUE;
3573859Sml29623 			err_portn = 1;
3583859Sml29623 			err_status = istatus.bits.ldw.port1_int_status;
3593859Sml29623 		}
3603859Sml29623 		break;
3613859Sml29623 	case 2:
3623859Sml29623 		if (istatus.bits.ldw.port2_int_status) {
3633859Sml29623 			my_err = B_TRUE;
3643859Sml29623 			err_portn = 2;
3653859Sml29623 			err_status = istatus.bits.ldw.port2_int_status;
3663859Sml29623 		}
3673859Sml29623 		break;
3683859Sml29623 	case 3:
3693859Sml29623 		if (istatus.bits.ldw.port3_int_status) {
3703859Sml29623 			my_err = B_TRUE;
3713859Sml29623 			err_portn = 3;
3723859Sml29623 			err_status = istatus.bits.ldw.port3_int_status;
3733859Sml29623 		}
3743859Sml29623 		break;
3753859Sml29623 	default:
3763859Sml29623 		return (NXGE_ERROR);
3773859Sml29623 	}
3783859Sml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
379*6929Smisaki 	    " nxge_txc_handle_sys_errors: errored port %d",
380*6929Smisaki 	    err_portn));
3813859Sml29623 	if (my_err) {
3823859Sml29623 		status = nxge_txc_handle_port_errors(nxgep, err_status);
3833859Sml29623 	}
3843859Sml29623 
3853859Sml29623 	return (status);
3863859Sml29623 }
3873859Sml29623 
3883859Sml29623 static nxge_status_t
nxge_txc_handle_port_errors(p_nxge_t nxgep,uint32_t err_status)3893859Sml29623 nxge_txc_handle_port_errors(p_nxge_t nxgep, uint32_t err_status)
3903859Sml29623 {
3913859Sml29623 	npi_handle_t		handle;
3923859Sml29623 	npi_status_t		rs = NPI_SUCCESS;
3933859Sml29623 	p_nxge_txc_stats_t	statsp;
3943859Sml29623 	txc_int_stat_t		istatus;
3953859Sml29623 	boolean_t		txport_fatal = B_FALSE;
3963859Sml29623 	uint8_t			portn;
3973859Sml29623 	nxge_status_t		status = NXGE_OK;
3983859Sml29623 
3993859Sml29623 	handle = nxgep->npi_handle;
4003859Sml29623 	statsp = (p_nxge_txc_stats_t)&nxgep->statsp->txc_stats;
4013859Sml29623 	portn = nxgep->mac.portnum;
4023859Sml29623 	istatus.value = 0;
4033859Sml29623 
4043859Sml29623 	if ((err_status & TXC_INT_STAT_RO_CORR_ERR) ||
405*6929Smisaki 	    (err_status & TXC_INT_STAT_RO_CORR_ERR) ||
406*6929Smisaki 	    (err_status & TXC_INT_STAT_RO_UNCORR_ERR) ||
407*6929Smisaki 	    (err_status & TXC_INT_STAT_REORDER_ERR)) {
4083859Sml29623 		if ((rs = npi_txc_ro_states_get(handle, portn,
409*6929Smisaki 		    &statsp->errlog.ro_st)) != NPI_SUCCESS) {
4103859Sml29623 			return (NXGE_ERROR | rs);
4113859Sml29623 		}
4123859Sml29623 
4133859Sml29623 		if (err_status & TXC_INT_STAT_RO_CORR_ERR) {
4143859Sml29623 			statsp->ro_correct_err++;
4153859Sml29623 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
416*6929Smisaki 			    NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR);
4173859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
418*6929Smisaki 			    "nxge_txc_err_evnts: "
419*6929Smisaki 			    "RO FIFO correctable error"));
4203859Sml29623 		}
4213859Sml29623 		if (err_status & TXC_INT_STAT_RO_UNCORR_ERR) {
4223859Sml29623 			statsp->ro_uncorrect_err++;
4233859Sml29623 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
424*6929Smisaki 			    NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR);
4253859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
426*6929Smisaki 			    "nxge_txc_err_evnts: "
427*6929Smisaki 			    "RO FIFO uncorrectable error"));
4283859Sml29623 		}
4293859Sml29623 		if (err_status & TXC_INT_STAT_REORDER_ERR) {
4303859Sml29623 			statsp->reorder_err++;
4313859Sml29623 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
432*6929Smisaki 			    NXGE_FM_EREPORT_TXC_REORDER_ERR);
4333859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
434*6929Smisaki 			    "nxge_txc_err_evnts: "
435*6929Smisaki 			    "fatal error: Reorder error"));
4363859Sml29623 			txport_fatal = B_TRUE;
4373859Sml29623 		}
4383859Sml29623 
4393859Sml29623 		if ((err_status & TXC_INT_STAT_RO_CORR_ERR) ||
440*6929Smisaki 		    (err_status & TXC_INT_STAT_RO_CORR_ERR) ||
441*6929Smisaki 		    (err_status & TXC_INT_STAT_RO_UNCORR_ERR)) {
4423859Sml29623 
4433859Sml29623 			if ((rs = npi_txc_ro_ecc_state_clr(handle, portn))
444*6929Smisaki 			    != NPI_SUCCESS)
4453859Sml29623 				return (NXGE_ERROR | rs);
4463859Sml29623 			/*
4473859Sml29623 			 * Making sure that error source is cleared if this is
4483859Sml29623 			 * an injected error.
4493859Sml29623 			 */
4503859Sml29623 			TXC_FZC_CNTL_REG_WRITE64(handle, TXC_ROECC_CTL_REG,
451*6929Smisaki 			    portn, 0);
4523859Sml29623 		}
4533859Sml29623 	}
4543859Sml29623 
4553859Sml29623 	if ((err_status & TXC_INT_STAT_SF_CORR_ERR) ||
456*6929Smisaki 	    (err_status & TXC_INT_STAT_SF_UNCORR_ERR)) {
4573859Sml29623 		if ((rs = npi_txc_sf_states_get(handle, portn,
458*6929Smisaki 		    &statsp->errlog.sf_st)) != NPI_SUCCESS) {
4593859Sml29623 			return (NXGE_ERROR | rs);
4603859Sml29623 		}
4613859Sml29623 		if (err_status & TXC_INT_STAT_SF_CORR_ERR) {
4623859Sml29623 			statsp->sf_correct_err++;
4633859Sml29623 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
464*6929Smisaki 			    NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR);
4653859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
466*6929Smisaki 			    "nxge_txc_err_evnts: "
467*6929Smisaki 			    "SF FIFO correctable error"));
4683859Sml29623 		}
4693859Sml29623 		if (err_status & TXC_INT_STAT_SF_UNCORR_ERR) {
4703859Sml29623 			statsp->sf_uncorrect_err++;
4713859Sml29623 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
472*6929Smisaki 			    NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR);
4733859Sml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
474*6929Smisaki 			    "nxge_txc_err_evnts: "
475*6929Smisaki 			    "SF FIFO uncorrectable error"));
4763859Sml29623 		}
4773859Sml29623 		if ((rs = npi_txc_sf_ecc_state_clr(handle, portn))
478*6929Smisaki 		    != NPI_SUCCESS)
4793859Sml29623 			return (NXGE_ERROR | rs);
4803859Sml29623 		/*
4813859Sml29623 		 * Making sure that error source is cleared if this is
4823859Sml29623 		 * an injected error.
4833859Sml29623 		 */
4843859Sml29623 		TXC_FZC_CNTL_REG_WRITE64(handle, TXC_SFECC_CTL_REG, portn, 0);
4853859Sml29623 	}
4863859Sml29623 
4873859Sml29623 	/* Clear corresponding errors */
4883859Sml29623 	switch (portn) {
4893859Sml29623 	case 0:
4903859Sml29623 		istatus.bits.ldw.port0_int_status = err_status;
4913859Sml29623 		break;
4923859Sml29623 	case 1:
4933859Sml29623 		istatus.bits.ldw.port1_int_status = err_status;
4943859Sml29623 		break;
4953859Sml29623 	case 2:
4963859Sml29623 		istatus.bits.ldw.port2_int_status = err_status;
4973859Sml29623 		break;
4983859Sml29623 	case 3:
4993859Sml29623 		istatus.bits.ldw.port3_int_status = err_status;
5003859Sml29623 		break;
5013859Sml29623 	default:
5023859Sml29623 		return (NXGE_ERROR);
5033859Sml29623 	}
5043859Sml29623 
5053859Sml29623 	npi_txc_global_istatus_clear(handle, istatus.value);
5063859Sml29623 
5073859Sml29623 	if (txport_fatal) {
5083859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
509*6929Smisaki 		    " nxge_txc_handle_port_errors:"
510*6929Smisaki 		    " fatal Error on Port#%d\n",
511*6929Smisaki 		    portn));
5123859Sml29623 		status = nxge_tx_port_fatal_err_recover(nxgep);
5133859Sml29623 		if (status == NXGE_OK) {
5143859Sml29623 			FM_SERVICE_RESTORED(nxgep);
5153859Sml29623 		}
5163859Sml29623 	}
5173859Sml29623 
5183859Sml29623 	return (status);
5193859Sml29623 }
5203859Sml29623 
5213859Sml29623 void
nxge_txc_inject_err(p_nxge_t nxgep,uint32_t err_id)5223859Sml29623 nxge_txc_inject_err(p_nxge_t nxgep, uint32_t err_id)
5233859Sml29623 {
5243859Sml29623 	txc_int_stat_dbg_t	txcs;
5253859Sml29623 	txc_roecc_ctl_t		ro_ecc_ctl;
5263859Sml29623 	txc_sfecc_ctl_t		sf_ecc_ctl;
5273859Sml29623 	uint8_t			portn = nxgep->mac.portnum;
5283859Sml29623 
5293859Sml29623 	cmn_err(CE_NOTE, "!TXC error Inject\n");
5303859Sml29623 	switch (err_id) {
5313859Sml29623 	case NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR:
5323859Sml29623 	case NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR:
5333859Sml29623 		ro_ecc_ctl.value = 0;
5343859Sml29623 		ro_ecc_ctl.bits.ldw.all_pkts = 1;
5353859Sml29623 		ro_ecc_ctl.bits.ldw.second_line_pkt = 1;
5363859Sml29623 		if (err_id == NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR)
5373859Sml29623 			ro_ecc_ctl.bits.ldw.single_bit_err = 1;
5383859Sml29623 		else
5393859Sml29623 			ro_ecc_ctl.bits.ldw.double_bit_err = 1;
5405125Sjoycey #if defined(__i386)
5415125Sjoycey 		cmn_err(CE_NOTE, "!Write 0x%llx to TXC_ROECC_CTL_REG\n",
542*6929Smisaki 		    ro_ecc_ctl.value);
5435125Sjoycey #else
5443859Sml29623 		cmn_err(CE_NOTE, "!Write 0x%lx to TXC_ROECC_CTL_REG\n",
545*6929Smisaki 		    ro_ecc_ctl.value);
5465125Sjoycey #endif
5473859Sml29623 		TXC_FZC_CNTL_REG_WRITE64(nxgep->npi_handle, TXC_ROECC_CTL_REG,
548*6929Smisaki 		    portn, ro_ecc_ctl.value);
5493859Sml29623 		break;
5503859Sml29623 	case NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR:
5513859Sml29623 	case NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR:
5523859Sml29623 		sf_ecc_ctl.value = 0;
5533859Sml29623 		sf_ecc_ctl.bits.ldw.all_pkts = 1;
5543859Sml29623 		sf_ecc_ctl.bits.ldw.second_line_pkt = 1;
5553859Sml29623 		if (err_id == NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR)
5563859Sml29623 			sf_ecc_ctl.bits.ldw.single_bit_err = 1;
5573859Sml29623 		else
5583859Sml29623 			sf_ecc_ctl.bits.ldw.double_bit_err = 1;
5595125Sjoycey #if defined(__i386)
5605125Sjoycey 		cmn_err(CE_NOTE, "!Write 0x%llx to TXC_SFECC_CTL_REG\n",
561*6929Smisaki 		    sf_ecc_ctl.value);
5625125Sjoycey #else
5633859Sml29623 		cmn_err(CE_NOTE, "!Write 0x%lx to TXC_SFECC_CTL_REG\n",
564*6929Smisaki 		    sf_ecc_ctl.value);
5655125Sjoycey #endif
5663859Sml29623 		TXC_FZC_CNTL_REG_WRITE64(nxgep->npi_handle, TXC_SFECC_CTL_REG,
567*6929Smisaki 		    portn, sf_ecc_ctl.value);
5683859Sml29623 		break;
5693859Sml29623 	case NXGE_FM_EREPORT_TXC_REORDER_ERR:
5703859Sml29623 		NXGE_REG_RD64(nxgep->npi_handle, TXC_INT_STAT_DBG_REG,
571*6929Smisaki 		    &txcs.value);
5723859Sml29623 		nxge_txc_inject_port_err(portn, &txcs,
573*6929Smisaki 		    TXC_INT_STAT_REORDER_ERR);
5745125Sjoycey #if defined(__i386)
5755125Sjoycey 		cmn_err(CE_NOTE, "!Write 0x%llx to TXC_INT_STAT_DBG_REG\n",
576*6929Smisaki 		    txcs.value);
5775125Sjoycey #else
5783859Sml29623 		cmn_err(CE_NOTE, "!Write 0x%lx to TXC_INT_STAT_DBG_REG\n",
579*6929Smisaki 		    txcs.value);
5805125Sjoycey #endif
5813859Sml29623 		NXGE_REG_WR64(nxgep->npi_handle, TXC_INT_STAT_DBG_REG,
582*6929Smisaki 		    txcs.value);
5833859Sml29623 		break;
5843859Sml29623 	default:
5853859Sml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
586*6929Smisaki 		    "nxge_txc_inject_err: Unknown err_id"));
5873859Sml29623 	}
5883859Sml29623 }
5893859Sml29623 
5903859Sml29623 static void
nxge_txc_inject_port_err(uint8_t portn,txc_int_stat_dbg_t * txcs,uint8_t istats)5913859Sml29623 nxge_txc_inject_port_err(uint8_t portn, txc_int_stat_dbg_t *txcs,
5923859Sml29623 				uint8_t istats)
5933859Sml29623 {
5943859Sml29623 	switch (portn) {
5953859Sml29623 	case 0:
5963859Sml29623 		txcs->bits.ldw.port0_int_status |= istats;
5973859Sml29623 		break;
5983859Sml29623 	case 1:
5993859Sml29623 		txcs->bits.ldw.port1_int_status |= istats;
6003859Sml29623 		break;
6013859Sml29623 	case 2:
6023859Sml29623 		txcs->bits.ldw.port2_int_status |= istats;
6033859Sml29623 		break;
6043859Sml29623 	case 3:
6053859Sml29623 		txcs->bits.ldw.port3_int_status |= istats;
6063859Sml29623 		break;
6073859Sml29623 	default:
6083859Sml29623 		;
6093859Sml29623 	}
6103859Sml29623 }
611