xref: /titanic_52/usr/src/uts/common/io/nxge/nxge_txc.c (revision 52ccf843e173e2a4a657360b0a22853fd413905f)
16f45ec7bSml29623 /*
26f45ec7bSml29623  * CDDL HEADER START
36f45ec7bSml29623  *
46f45ec7bSml29623  * The contents of this file are subject to the terms of the
56f45ec7bSml29623  * Common Development and Distribution License (the "License").
66f45ec7bSml29623  * You may not use this file except in compliance with the License.
76f45ec7bSml29623  *
86f45ec7bSml29623  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96f45ec7bSml29623  * or http://www.opensolaris.org/os/licensing.
106f45ec7bSml29623  * See the License for the specific language governing permissions
116f45ec7bSml29623  * and limitations under the License.
126f45ec7bSml29623  *
136f45ec7bSml29623  * When distributing Covered Code, include this CDDL HEADER in each
146f45ec7bSml29623  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156f45ec7bSml29623  * If applicable, add the following below this CDDL HEADER, with the
166f45ec7bSml29623  * fields enclosed by brackets "[]" replaced with your own identifying
176f45ec7bSml29623  * information: Portions Copyright [yyyy] [name of copyright owner]
186f45ec7bSml29623  *
196f45ec7bSml29623  * CDDL HEADER END
206f45ec7bSml29623  */
216f45ec7bSml29623 /*
22*678453a8Sspeer  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
236f45ec7bSml29623  * Use is subject to license terms.
246f45ec7bSml29623  */
256f45ec7bSml29623 
266f45ec7bSml29623 #pragma ident	"%Z%%M%	%I%	%E% SMI"
276f45ec7bSml29623 
286f45ec7bSml29623 #include <sys/nxge/nxge_impl.h>
296f45ec7bSml29623 #include <sys/nxge/nxge_txc.h>
306f45ec7bSml29623 
316f45ec7bSml29623 static nxge_status_t
326f45ec7bSml29623 nxge_txc_handle_port_errors(p_nxge_t, uint32_t);
336f45ec7bSml29623 static void
346f45ec7bSml29623 nxge_txc_inject_port_err(uint8_t, txc_int_stat_dbg_t *,
356f45ec7bSml29623 			uint8_t istats);
366f45ec7bSml29623 extern nxge_status_t nxge_tx_port_fatal_err_recover(p_nxge_t);
376f45ec7bSml29623 
386f45ec7bSml29623 nxge_status_t
396f45ec7bSml29623 nxge_txc_init(p_nxge_t nxgep)
406f45ec7bSml29623 {
416f45ec7bSml29623 	uint8_t			port;
426f45ec7bSml29623 	npi_handle_t		handle;
436f45ec7bSml29623 	npi_status_t		rs = NPI_SUCCESS;
446f45ec7bSml29623 
456f45ec7bSml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
466f45ec7bSml29623 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
476f45ec7bSml29623 
486f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_init: portn %d", port));
496f45ec7bSml29623 
506f45ec7bSml29623 	/*
516f45ec7bSml29623 	 * Enable the TXC controller.
526f45ec7bSml29623 	 */
536f45ec7bSml29623 	if ((rs = npi_txc_global_enable(handle)) != NPI_SUCCESS) {
546f45ec7bSml29623 		goto fail;
556f45ec7bSml29623 	}
566f45ec7bSml29623 
576f45ec7bSml29623 	/* Enable this port within the TXC. */
586f45ec7bSml29623 	if ((rs = npi_txc_port_enable(handle, port)) != NPI_SUCCESS) {
596f45ec7bSml29623 		goto fail;
606f45ec7bSml29623 	}
616f45ec7bSml29623 
626f45ec7bSml29623 	/* Bind DMA channels to this port. */
636f45ec7bSml29623 	if ((rs = npi_txc_port_dma_enable(handle, port,
646f45ec7bSml29623 	    TXDMA_PORT_BITMAP(nxgep))) != NPI_SUCCESS) {
656f45ec7bSml29623 		goto fail;
666f45ec7bSml29623 	}
676f45ec7bSml29623 
686f45ec7bSml29623 	/* Unmask all TXC interrupts */
696f45ec7bSml29623 	npi_txc_global_imask_set(handle, port, 0);
706f45ec7bSml29623 
716f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_init: portn %d", port));
726f45ec7bSml29623 
736f45ec7bSml29623 	return (NXGE_OK);
746f45ec7bSml29623 fail:
756f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
766f45ec7bSml29623 	    "nxge_txc_init: Failed to initialize txc on port %d",
776f45ec7bSml29623 	    port));
786f45ec7bSml29623 
796f45ec7bSml29623 	return (NXGE_ERROR | rs);
806f45ec7bSml29623 }
816f45ec7bSml29623 
826f45ec7bSml29623 nxge_status_t
836f45ec7bSml29623 nxge_txc_uninit(p_nxge_t nxgep)
846f45ec7bSml29623 {
856f45ec7bSml29623 	uint8_t			port;
866f45ec7bSml29623 	npi_handle_t		handle;
876f45ec7bSml29623 	npi_status_t		rs = NPI_SUCCESS;
886f45ec7bSml29623 
896f45ec7bSml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
906f45ec7bSml29623 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
916f45ec7bSml29623 
926f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "==> nxge_txc_uninit: portn %d", port));
936f45ec7bSml29623 
946f45ec7bSml29623 	/*
956f45ec7bSml29623 	 * disable the TXC controller.
966f45ec7bSml29623 	 */
976f45ec7bSml29623 	if ((rs = npi_txc_global_disable(handle)) != NPI_SUCCESS) {
986f45ec7bSml29623 		goto fail;
996f45ec7bSml29623 	}
1006f45ec7bSml29623 
1016f45ec7bSml29623 	/* disable this port within the TXC. */
1026f45ec7bSml29623 	if ((rs = npi_txc_port_disable(handle, port)) != NPI_SUCCESS) {
1036f45ec7bSml29623 		goto fail;
1046f45ec7bSml29623 	}
1056f45ec7bSml29623 
1066f45ec7bSml29623 	/* unbind DMA channels to this port. */
1076f45ec7bSml29623 	if ((rs = npi_txc_port_dma_enable(handle, port, 0)) != NPI_SUCCESS) {
1086f45ec7bSml29623 		goto fail;
1096f45ec7bSml29623 	}
1106f45ec7bSml29623 
1116f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "<== nxge_txc_uninit: portn %d", port));
1126f45ec7bSml29623 
1136f45ec7bSml29623 	return (NXGE_OK);
1146f45ec7bSml29623 fail:
1156f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
1166f45ec7bSml29623 	    "nxge_txc_init: Failed to initialize txc on port %d",
1176f45ec7bSml29623 	    port));
1186f45ec7bSml29623 
1196f45ec7bSml29623 	return (NXGE_ERROR | rs);
1206f45ec7bSml29623 }
1216f45ec7bSml29623 
122*678453a8Sspeer /*
123*678453a8Sspeer  * nxge_txc_tdc_bind
124*678453a8Sspeer  *
125*678453a8Sspeer  *	Bind a TDC to a port.
126*678453a8Sspeer  *
127*678453a8Sspeer  * Arguments:
128*678453a8Sspeer  * 	nxgep
129*678453a8Sspeer  * 	channel		The channel to bind.
130*678453a8Sspeer  *
131*678453a8Sspeer  * Notes:
132*678453a8Sspeer  *
133*678453a8Sspeer  * NPI/NXGE function calls:
134*678453a8Sspeer  *	npi_txc_control()
135*678453a8Sspeer  *	npi_txc_global_imask_set()
136*678453a8Sspeer  *	npi_txc_port_dma_enable()
137*678453a8Sspeer  *
138*678453a8Sspeer  * Registers accessed:
139*678453a8Sspeer  *	TXC_CONTROL
140*678453a8Sspeer  *	TXC_PORT_DMA
141*678453a8Sspeer  *	TXC_INT_MASK
142*678453a8Sspeer  *
143*678453a8Sspeer  * Context:
144*678453a8Sspeer  *	Service domain
145*678453a8Sspeer  */
146*678453a8Sspeer nxge_status_t
147*678453a8Sspeer nxge_txc_tdc_bind(
148*678453a8Sspeer 	p_nxge_t nxgep,
149*678453a8Sspeer 	int channel)
150*678453a8Sspeer {
151*678453a8Sspeer 	uint8_t		port;
152*678453a8Sspeer 	uint64_t	bitmap;
153*678453a8Sspeer 	npi_handle_t	handle;
154*678453a8Sspeer 	npi_status_t	rs = NPI_SUCCESS;
155*678453a8Sspeer 	txc_control_t	txc_control;
156*678453a8Sspeer 
157*678453a8Sspeer 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
158*678453a8Sspeer 
159*678453a8Sspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
160*678453a8Sspeer 	    "==> nxge_txc_tdc_bind(port %d, channel %d)", port, channel));
161*678453a8Sspeer 
162*678453a8Sspeer 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
163*678453a8Sspeer 
164*678453a8Sspeer 	/* Get the current value of TXC_CONTROL. */
165*678453a8Sspeer 	(void) npi_txc_control(handle, OP_GET, &txc_control);
166*678453a8Sspeer 
167*678453a8Sspeer 	/* Mask all TXC interrupts for <port>. */
168*678453a8Sspeer 	if (txc_control.value & (1 << port)) {
169*678453a8Sspeer 		npi_txc_global_imask_set(handle, port, TXC_INT_MASK_IVAL);
170*678453a8Sspeer 	}
171*678453a8Sspeer 
172*678453a8Sspeer 	/* Bind <channel> to <port>. */
173*678453a8Sspeer 	/* Read in the old bitmap. */
174*678453a8Sspeer 	TXC_FZC_CNTL_REG_READ64(handle, TXC_PORT_DMA_ENABLE_REG, port,
175*678453a8Sspeer 	    &bitmap);
176*678453a8Sspeer 
177*678453a8Sspeer 	if (bitmap & (1 << channel)) {
178*678453a8Sspeer 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
179*678453a8Sspeer 		    "nxge_txc_tdc_bind: channel %d already bound on port %d",
180*678453a8Sspeer 		    channel, port));
181*678453a8Sspeer 	} else {
182*678453a8Sspeer 		/* Bind the new channel. */
183*678453a8Sspeer 		bitmap |= (1 << channel);
184*678453a8Sspeer 		NXGE_DEBUG_MSG((nxgep, TX_CTL,
185*678453a8Sspeer 		    "==> nxge_txc_tdc_bind(): bitmap = %lx", bitmap));
186*678453a8Sspeer 
187*678453a8Sspeer 		/* Write out the new bitmap. */
188*678453a8Sspeer 		if ((rs = npi_txc_port_dma_enable(handle, port,
189*678453a8Sspeer 		    (uint32_t)bitmap)) != NPI_SUCCESS) {
190*678453a8Sspeer 			goto fail;
191*678453a8Sspeer 		}
192*678453a8Sspeer 	}
193*678453a8Sspeer 
194*678453a8Sspeer 	/* Enable this port, if necessary. */
195*678453a8Sspeer 	if (!(txc_control.value & (1 << port))) {
196*678453a8Sspeer 		if ((rs = npi_txc_port_enable(handle, port)) != NPI_SUCCESS) {
197*678453a8Sspeer 			goto fail;
198*678453a8Sspeer 		}
199*678453a8Sspeer 	}
200*678453a8Sspeer 
201*678453a8Sspeer 	/*
202*678453a8Sspeer 	 * Enable the TXC controller, if necessary.
203*678453a8Sspeer 	 */
204*678453a8Sspeer 	if (txc_control.bits.ldw.txc_enabled == 0) {
205*678453a8Sspeer 		if ((rs = npi_txc_global_enable(handle)) != NPI_SUCCESS) {
206*678453a8Sspeer 			goto fail;
207*678453a8Sspeer 		}
208*678453a8Sspeer 	}
209*678453a8Sspeer 
210*678453a8Sspeer 	/* Unmask all TXC interrupts on <port> */
211*678453a8Sspeer 	npi_txc_global_imask_set(handle, port, 0);
212*678453a8Sspeer 
213*678453a8Sspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
214*678453a8Sspeer 	    "<== nxge_txc_tdc_bind(port %d, channel %d)", port, channel));
215*678453a8Sspeer 
216*678453a8Sspeer 	return (NXGE_OK);
217*678453a8Sspeer fail:
218*678453a8Sspeer 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
219*678453a8Sspeer 	    "nxge_txc_tdc_bind(port %d, channel %d) failed", port, channel));
220*678453a8Sspeer 
221*678453a8Sspeer 	return (NXGE_ERROR | rs);
222*678453a8Sspeer }
223*678453a8Sspeer 
224*678453a8Sspeer /*
225*678453a8Sspeer  * nxge_txc_tdc_unbind
226*678453a8Sspeer  *
227*678453a8Sspeer  *	Unbind a TDC from a port.
228*678453a8Sspeer  *
229*678453a8Sspeer  * Arguments:
230*678453a8Sspeer  * 	nxgep
231*678453a8Sspeer  * 	channel		The channel to unbind.
232*678453a8Sspeer  *
233*678453a8Sspeer  * Notes:
234*678453a8Sspeer  *
235*678453a8Sspeer  * NPI/NXGE function calls:
236*678453a8Sspeer  *	npi_txc_control()
237*678453a8Sspeer  *	npi_txc_global_imask_set()
238*678453a8Sspeer  *	npi_txc_port_dma_enable()
239*678453a8Sspeer  *
240*678453a8Sspeer  * Registers accessed:
241*678453a8Sspeer  *	TXC_CONTROL
242*678453a8Sspeer  *	TXC_PORT_DMA
243*678453a8Sspeer  *	TXC_INT_MASK
244*678453a8Sspeer  *
245*678453a8Sspeer  * Context:
246*678453a8Sspeer  *	Service domain
247*678453a8Sspeer  */
248*678453a8Sspeer nxge_status_t
249*678453a8Sspeer nxge_txc_tdc_unbind(
250*678453a8Sspeer 	p_nxge_t nxgep,
251*678453a8Sspeer 	int channel)
252*678453a8Sspeer {
253*678453a8Sspeer 	uint8_t		port;
254*678453a8Sspeer 	uint64_t	bitmap;
255*678453a8Sspeer 	npi_handle_t	handle;
256*678453a8Sspeer 	npi_status_t	rs = NPI_SUCCESS;
257*678453a8Sspeer 
258*678453a8Sspeer 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
259*678453a8Sspeer 	port = NXGE_GET_PORT_NUM(nxgep->function_num);
260*678453a8Sspeer 
261*678453a8Sspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
262*678453a8Sspeer 	    "==> nxge_txc_tdc_unbind(port %d, channel %d)", port, channel));
263*678453a8Sspeer 
264*678453a8Sspeer 	/* Mask all TXC interrupts for <port>. */
265*678453a8Sspeer 	npi_txc_global_imask_set(handle, port, TXC_INT_MASK_IVAL);
266*678453a8Sspeer 
267*678453a8Sspeer 	/* Unbind <channel>. */
268*678453a8Sspeer 	/* Read in the old bitmap. */
269*678453a8Sspeer 	TXC_FZC_CNTL_REG_READ64(handle, TXC_PORT_DMA_ENABLE_REG, port,
270*678453a8Sspeer 	    &bitmap);
271*678453a8Sspeer 
272*678453a8Sspeer 	bitmap &= (~(1 << channel));
273*678453a8Sspeer 
274*678453a8Sspeer 	/* Write out the new bitmap. */
275*678453a8Sspeer 	if ((rs = npi_txc_port_dma_enable(handle, port,
276*678453a8Sspeer 	    (uint32_t)bitmap)) != NPI_SUCCESS) {
277*678453a8Sspeer 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
278*678453a8Sspeer 		    "npi_txc_port_dma_enable(%d, %d) failed: %x",
279*678453a8Sspeer 		    port, channel, rs));
280*678453a8Sspeer 	}
281*678453a8Sspeer 
282*678453a8Sspeer 	/* Unmask all TXC interrupts on <port> */
283*678453a8Sspeer 	if (bitmap)
284*678453a8Sspeer 		npi_txc_global_imask_set(handle, port, 0);
285*678453a8Sspeer 
286*678453a8Sspeer 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
287*678453a8Sspeer 	    "<== nxge_txc_tdc_unbind(port %d, channel %d)", port, channel));
288*678453a8Sspeer 
289*678453a8Sspeer 	return (NXGE_OK);
290*678453a8Sspeer fail:
291*678453a8Sspeer 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
292*678453a8Sspeer 	    "nxge_txc_tdc_unbind(port %d, channel %d) failed", port, channel));
293*678453a8Sspeer 
294*678453a8Sspeer 	return (NXGE_ERROR | rs);
295*678453a8Sspeer }
296*678453a8Sspeer 
2976f45ec7bSml29623 void
2986f45ec7bSml29623 nxge_txc_regs_dump(p_nxge_t nxgep)
2996f45ec7bSml29623 {
3006f45ec7bSml29623 	uint32_t		cnt1, cnt2;
3016f45ec7bSml29623 	npi_handle_t		handle;
3026f45ec7bSml29623 	txc_control_t		control;
3036f45ec7bSml29623 	uint32_t		bitmap = 0;
3046f45ec7bSml29623 
3056f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\nTXC dump: func # %d:\n",
3066f45ec7bSml29623 	    nxgep->function_num));
3076f45ec7bSml29623 
3086f45ec7bSml29623 	handle = NXGE_DEV_NPI_HANDLE(nxgep);
3096f45ec7bSml29623 
3106f45ec7bSml29623 	(void) npi_txc_control(handle, OP_GET, &control);
3116f45ec7bSml29623 	(void) npi_txc_port_dma_list_get(handle, nxgep->function_num, &bitmap);
3126f45ec7bSml29623 
3136f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC port control 0x%0llx",
3146f45ec7bSml29623 	    (long long)control.value));
3156f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC port bitmap 0x%x", bitmap));
3166f45ec7bSml29623 
3176f45ec7bSml29623 	(void) npi_txc_pkt_xmt_to_mac_get(handle, nxgep->function_num,
3186f45ec7bSml29623 	    &cnt1, &cnt2);
3196f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL, "\n\tTXC bytes to MAC %d "
3206f45ec7bSml29623 	    "packets to MAC %d",
3216f45ec7bSml29623 	    cnt1, cnt2));
3226f45ec7bSml29623 
3236f45ec7bSml29623 	(void) npi_txc_pkt_stuffed_get(handle, nxgep->function_num,
3246f45ec7bSml29623 	    &cnt1, &cnt2);
3256f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
3266f45ec7bSml29623 	    "\n\tTXC ass packets %d reorder packets %d",
3276f45ec7bSml29623 	    cnt1 & 0xffff, cnt2 & 0xffff));
3286f45ec7bSml29623 
3296f45ec7bSml29623 	(void) npi_txc_reorder_get(handle, nxgep->function_num, &cnt1);
3306f45ec7bSml29623 	NXGE_DEBUG_MSG((nxgep, TX_CTL,
3316f45ec7bSml29623 	    "\n\tTXC reorder resource %d", cnt1 & 0xff));
3326f45ec7bSml29623 }
3336f45ec7bSml29623 
3346f45ec7bSml29623 nxge_status_t
3356f45ec7bSml29623 nxge_txc_handle_sys_errors(p_nxge_t nxgep)
3366f45ec7bSml29623 {
3376f45ec7bSml29623 	npi_handle_t		handle;
3386f45ec7bSml29623 	txc_int_stat_t		istatus;
3396f45ec7bSml29623 	uint32_t		err_status;
3406f45ec7bSml29623 	uint8_t			err_portn;
3416f45ec7bSml29623 	boolean_t		my_err = B_FALSE;
3426f45ec7bSml29623 	nxge_status_t		status = NXGE_OK;
3436f45ec7bSml29623 
3446f45ec7bSml29623 	handle = nxgep->npi_handle;
3456f45ec7bSml29623 	npi_txc_global_istatus_get(handle, (txc_int_stat_t *)&istatus.value);
3466f45ec7bSml29623 	switch (nxgep->mac.portnum) {
3476f45ec7bSml29623 	case 0:
3486f45ec7bSml29623 		if (istatus.bits.ldw.port0_int_status) {
3496f45ec7bSml29623 			my_err = B_TRUE;
3506f45ec7bSml29623 			err_portn = 0;
3516f45ec7bSml29623 			err_status = istatus.bits.ldw.port0_int_status;
3526f45ec7bSml29623 		}
3536f45ec7bSml29623 		break;
3546f45ec7bSml29623 	case 1:
3556f45ec7bSml29623 		if (istatus.bits.ldw.port1_int_status) {
3566f45ec7bSml29623 			my_err = B_TRUE;
3576f45ec7bSml29623 			err_portn = 1;
3586f45ec7bSml29623 			err_status = istatus.bits.ldw.port1_int_status;
3596f45ec7bSml29623 		}
3606f45ec7bSml29623 		break;
3616f45ec7bSml29623 	case 2:
3626f45ec7bSml29623 		if (istatus.bits.ldw.port2_int_status) {
3636f45ec7bSml29623 			my_err = B_TRUE;
3646f45ec7bSml29623 			err_portn = 2;
3656f45ec7bSml29623 			err_status = istatus.bits.ldw.port2_int_status;
3666f45ec7bSml29623 		}
3676f45ec7bSml29623 		break;
3686f45ec7bSml29623 	case 3:
3696f45ec7bSml29623 		if (istatus.bits.ldw.port3_int_status) {
3706f45ec7bSml29623 			my_err = B_TRUE;
3716f45ec7bSml29623 			err_portn = 3;
3726f45ec7bSml29623 			err_status = istatus.bits.ldw.port3_int_status;
3736f45ec7bSml29623 		}
3746f45ec7bSml29623 		break;
3756f45ec7bSml29623 	default:
3766f45ec7bSml29623 		return (NXGE_ERROR);
3776f45ec7bSml29623 	}
3786f45ec7bSml29623 	NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
3796f45ec7bSml29623 	    " nxge_txc_handle_sys_errors: errored port %d",
3806f45ec7bSml29623 	    err_portn));
3816f45ec7bSml29623 	if (my_err) {
3826f45ec7bSml29623 		status = nxge_txc_handle_port_errors(nxgep, err_status);
3836f45ec7bSml29623 	}
3846f45ec7bSml29623 
3856f45ec7bSml29623 	return (status);
3866f45ec7bSml29623 }
3876f45ec7bSml29623 
3886f45ec7bSml29623 static nxge_status_t
3896f45ec7bSml29623 nxge_txc_handle_port_errors(p_nxge_t nxgep, uint32_t err_status)
3906f45ec7bSml29623 {
3916f45ec7bSml29623 	npi_handle_t		handle;
3926f45ec7bSml29623 	npi_status_t		rs = NPI_SUCCESS;
3936f45ec7bSml29623 	p_nxge_txc_stats_t	statsp;
3946f45ec7bSml29623 	txc_int_stat_t		istatus;
3956f45ec7bSml29623 	boolean_t		txport_fatal = B_FALSE;
3966f45ec7bSml29623 	uint8_t			portn;
3976f45ec7bSml29623 	nxge_status_t		status = NXGE_OK;
3986f45ec7bSml29623 
3996f45ec7bSml29623 	handle = nxgep->npi_handle;
4006f45ec7bSml29623 	statsp = (p_nxge_txc_stats_t)&nxgep->statsp->txc_stats;
4016f45ec7bSml29623 	portn = nxgep->mac.portnum;
4026f45ec7bSml29623 	istatus.value = 0;
4036f45ec7bSml29623 
4046f45ec7bSml29623 	if ((err_status & TXC_INT_STAT_RO_CORR_ERR) ||
4056f45ec7bSml29623 	    (err_status & TXC_INT_STAT_RO_CORR_ERR) ||
4066f45ec7bSml29623 	    (err_status & TXC_INT_STAT_RO_UNCORR_ERR) ||
4076f45ec7bSml29623 	    (err_status & TXC_INT_STAT_REORDER_ERR)) {
4086f45ec7bSml29623 		if ((rs = npi_txc_ro_states_get(handle, portn,
4096f45ec7bSml29623 		    &statsp->errlog.ro_st)) != NPI_SUCCESS) {
4106f45ec7bSml29623 			return (NXGE_ERROR | rs);
4116f45ec7bSml29623 		}
4126f45ec7bSml29623 
4136f45ec7bSml29623 		if (err_status & TXC_INT_STAT_RO_CORR_ERR) {
4146f45ec7bSml29623 			statsp->ro_correct_err++;
4156f45ec7bSml29623 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
4166f45ec7bSml29623 			    NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR);
4176f45ec7bSml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4186f45ec7bSml29623 			    "nxge_txc_err_evnts: "
4196f45ec7bSml29623 			    "RO FIFO correctable error"));
4206f45ec7bSml29623 		}
4216f45ec7bSml29623 		if (err_status & TXC_INT_STAT_RO_UNCORR_ERR) {
4226f45ec7bSml29623 			statsp->ro_uncorrect_err++;
4236f45ec7bSml29623 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
4246f45ec7bSml29623 			    NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR);
4256f45ec7bSml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4266f45ec7bSml29623 			    "nxge_txc_err_evnts: "
4276f45ec7bSml29623 			    "RO FIFO uncorrectable error"));
4286f45ec7bSml29623 		}
4296f45ec7bSml29623 		if (err_status & TXC_INT_STAT_REORDER_ERR) {
4306f45ec7bSml29623 			statsp->reorder_err++;
4316f45ec7bSml29623 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
4326f45ec7bSml29623 			    NXGE_FM_EREPORT_TXC_REORDER_ERR);
4336f45ec7bSml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4346f45ec7bSml29623 			    "nxge_txc_err_evnts: "
4356f45ec7bSml29623 			    "fatal error: Reorder error"));
4366f45ec7bSml29623 			txport_fatal = B_TRUE;
4376f45ec7bSml29623 		}
4386f45ec7bSml29623 
4396f45ec7bSml29623 		if ((err_status & TXC_INT_STAT_RO_CORR_ERR) ||
4406f45ec7bSml29623 		    (err_status & TXC_INT_STAT_RO_CORR_ERR) ||
4416f45ec7bSml29623 		    (err_status & TXC_INT_STAT_RO_UNCORR_ERR)) {
4426f45ec7bSml29623 
4436f45ec7bSml29623 			if ((rs = npi_txc_ro_ecc_state_clr(handle, portn))
4446f45ec7bSml29623 			    != NPI_SUCCESS)
4456f45ec7bSml29623 				return (NXGE_ERROR | rs);
4466f45ec7bSml29623 			/*
4476f45ec7bSml29623 			 * Making sure that error source is cleared if this is
4486f45ec7bSml29623 			 * an injected error.
4496f45ec7bSml29623 			 */
4506f45ec7bSml29623 			TXC_FZC_CNTL_REG_WRITE64(handle, TXC_ROECC_CTL_REG,
4516f45ec7bSml29623 			    portn, 0);
4526f45ec7bSml29623 		}
4536f45ec7bSml29623 	}
4546f45ec7bSml29623 
4556f45ec7bSml29623 	if ((err_status & TXC_INT_STAT_SF_CORR_ERR) ||
4566f45ec7bSml29623 	    (err_status & TXC_INT_STAT_SF_UNCORR_ERR)) {
4576f45ec7bSml29623 		if ((rs = npi_txc_sf_states_get(handle, portn,
4586f45ec7bSml29623 		    &statsp->errlog.sf_st)) != NPI_SUCCESS) {
4596f45ec7bSml29623 			return (NXGE_ERROR | rs);
4606f45ec7bSml29623 		}
4616f45ec7bSml29623 		if (err_status & TXC_INT_STAT_SF_CORR_ERR) {
4626f45ec7bSml29623 			statsp->sf_correct_err++;
4636f45ec7bSml29623 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
4646f45ec7bSml29623 			    NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR);
4656f45ec7bSml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4666f45ec7bSml29623 			    "nxge_txc_err_evnts: "
4676f45ec7bSml29623 			    "SF FIFO correctable error"));
4686f45ec7bSml29623 		}
4696f45ec7bSml29623 		if (err_status & TXC_INT_STAT_SF_UNCORR_ERR) {
4706f45ec7bSml29623 			statsp->sf_uncorrect_err++;
4716f45ec7bSml29623 			NXGE_FM_REPORT_ERROR(nxgep, portn, NULL,
4726f45ec7bSml29623 			    NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR);
4736f45ec7bSml29623 			NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
4746f45ec7bSml29623 			    "nxge_txc_err_evnts: "
4756f45ec7bSml29623 			    "SF FIFO uncorrectable error"));
4766f45ec7bSml29623 		}
4776f45ec7bSml29623 		if ((rs = npi_txc_sf_ecc_state_clr(handle, portn))
4786f45ec7bSml29623 		    != NPI_SUCCESS)
4796f45ec7bSml29623 			return (NXGE_ERROR | rs);
4806f45ec7bSml29623 		/*
4816f45ec7bSml29623 		 * Making sure that error source is cleared if this is
4826f45ec7bSml29623 		 * an injected error.
4836f45ec7bSml29623 		 */
4846f45ec7bSml29623 		TXC_FZC_CNTL_REG_WRITE64(handle, TXC_SFECC_CTL_REG, portn, 0);
4856f45ec7bSml29623 	}
4866f45ec7bSml29623 
4876f45ec7bSml29623 	/* Clear corresponding errors */
4886f45ec7bSml29623 	switch (portn) {
4896f45ec7bSml29623 	case 0:
4906f45ec7bSml29623 		istatus.bits.ldw.port0_int_status = err_status;
4916f45ec7bSml29623 		break;
4926f45ec7bSml29623 	case 1:
4936f45ec7bSml29623 		istatus.bits.ldw.port1_int_status = err_status;
4946f45ec7bSml29623 		break;
4956f45ec7bSml29623 	case 2:
4966f45ec7bSml29623 		istatus.bits.ldw.port2_int_status = err_status;
4976f45ec7bSml29623 		break;
4986f45ec7bSml29623 	case 3:
4996f45ec7bSml29623 		istatus.bits.ldw.port3_int_status = err_status;
5006f45ec7bSml29623 		break;
5016f45ec7bSml29623 	default:
5026f45ec7bSml29623 		return (NXGE_ERROR);
5036f45ec7bSml29623 	}
5046f45ec7bSml29623 
5056f45ec7bSml29623 	npi_txc_global_istatus_clear(handle, istatus.value);
5066f45ec7bSml29623 
5076f45ec7bSml29623 	if (txport_fatal) {
5086f45ec7bSml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5096f45ec7bSml29623 		    " nxge_txc_handle_port_errors:"
5106f45ec7bSml29623 		    " fatal Error on Port#%d\n",
5116f45ec7bSml29623 		    portn));
5126f45ec7bSml29623 		status = nxge_tx_port_fatal_err_recover(nxgep);
5136f45ec7bSml29623 		if (status == NXGE_OK) {
5146f45ec7bSml29623 			FM_SERVICE_RESTORED(nxgep);
5156f45ec7bSml29623 		}
5166f45ec7bSml29623 	}
5176f45ec7bSml29623 
5186f45ec7bSml29623 	return (status);
5196f45ec7bSml29623 }
5206f45ec7bSml29623 
5216f45ec7bSml29623 void
5226f45ec7bSml29623 nxge_txc_inject_err(p_nxge_t nxgep, uint32_t err_id)
5236f45ec7bSml29623 {
5246f45ec7bSml29623 	txc_int_stat_dbg_t	txcs;
5256f45ec7bSml29623 	txc_roecc_ctl_t		ro_ecc_ctl;
5266f45ec7bSml29623 	txc_sfecc_ctl_t		sf_ecc_ctl;
5276f45ec7bSml29623 	uint8_t			portn = nxgep->mac.portnum;
5286f45ec7bSml29623 
5296f45ec7bSml29623 	cmn_err(CE_NOTE, "!TXC error Inject\n");
5306f45ec7bSml29623 	switch (err_id) {
5316f45ec7bSml29623 	case NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR:
5326f45ec7bSml29623 	case NXGE_FM_EREPORT_TXC_RO_UNCORRECT_ERR:
5336f45ec7bSml29623 		ro_ecc_ctl.value = 0;
5346f45ec7bSml29623 		ro_ecc_ctl.bits.ldw.all_pkts = 1;
5356f45ec7bSml29623 		ro_ecc_ctl.bits.ldw.second_line_pkt = 1;
5366f45ec7bSml29623 		if (err_id == NXGE_FM_EREPORT_TXC_RO_CORRECT_ERR)
5376f45ec7bSml29623 			ro_ecc_ctl.bits.ldw.single_bit_err = 1;
5386f45ec7bSml29623 		else
5396f45ec7bSml29623 			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",
542adfcba55Sjoycey 		    ro_ecc_ctl.value);
543adfcba55Sjoycey #else
5446f45ec7bSml29623 		cmn_err(CE_NOTE, "!Write 0x%lx to TXC_ROECC_CTL_REG\n",
5456f45ec7bSml29623 		    ro_ecc_ctl.value);
546adfcba55Sjoycey #endif
5476f45ec7bSml29623 		TXC_FZC_CNTL_REG_WRITE64(nxgep->npi_handle, TXC_ROECC_CTL_REG,
5486f45ec7bSml29623 		    portn, ro_ecc_ctl.value);
5496f45ec7bSml29623 		break;
5506f45ec7bSml29623 	case NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR:
5516f45ec7bSml29623 	case NXGE_FM_EREPORT_TXC_SF_UNCORRECT_ERR:
5526f45ec7bSml29623 		sf_ecc_ctl.value = 0;
5536f45ec7bSml29623 		sf_ecc_ctl.bits.ldw.all_pkts = 1;
5546f45ec7bSml29623 		sf_ecc_ctl.bits.ldw.second_line_pkt = 1;
5556f45ec7bSml29623 		if (err_id == NXGE_FM_EREPORT_TXC_SF_CORRECT_ERR)
5566f45ec7bSml29623 			sf_ecc_ctl.bits.ldw.single_bit_err = 1;
5576f45ec7bSml29623 		else
5586f45ec7bSml29623 			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",
561adfcba55Sjoycey 		    sf_ecc_ctl.value);
562adfcba55Sjoycey #else
5636f45ec7bSml29623 		cmn_err(CE_NOTE, "!Write 0x%lx to TXC_SFECC_CTL_REG\n",
5646f45ec7bSml29623 		    sf_ecc_ctl.value);
565adfcba55Sjoycey #endif
5666f45ec7bSml29623 		TXC_FZC_CNTL_REG_WRITE64(nxgep->npi_handle, TXC_SFECC_CTL_REG,
5676f45ec7bSml29623 		    portn, sf_ecc_ctl.value);
5686f45ec7bSml29623 		break;
5696f45ec7bSml29623 	case NXGE_FM_EREPORT_TXC_REORDER_ERR:
5706f45ec7bSml29623 		NXGE_REG_RD64(nxgep->npi_handle, TXC_INT_STAT_DBG_REG,
5716f45ec7bSml29623 		    &txcs.value);
5726f45ec7bSml29623 		nxge_txc_inject_port_err(portn, &txcs,
5736f45ec7bSml29623 		    TXC_INT_STAT_REORDER_ERR);
574adfcba55Sjoycey #if defined(__i386)
575adfcba55Sjoycey 		cmn_err(CE_NOTE, "!Write 0x%llx to TXC_INT_STAT_DBG_REG\n",
576adfcba55Sjoycey 		    txcs.value);
577adfcba55Sjoycey #else
5786f45ec7bSml29623 		cmn_err(CE_NOTE, "!Write 0x%lx to TXC_INT_STAT_DBG_REG\n",
5796f45ec7bSml29623 		    txcs.value);
580adfcba55Sjoycey #endif
5816f45ec7bSml29623 		NXGE_REG_WR64(nxgep->npi_handle, TXC_INT_STAT_DBG_REG,
5826f45ec7bSml29623 		    txcs.value);
5836f45ec7bSml29623 		break;
5846f45ec7bSml29623 	default:
5856f45ec7bSml29623 		NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL,
5866f45ec7bSml29623 		    "nxge_txc_inject_err: Unknown err_id"));
5876f45ec7bSml29623 	}
5886f45ec7bSml29623 }
5896f45ec7bSml29623 
5906f45ec7bSml29623 static void
5916f45ec7bSml29623 nxge_txc_inject_port_err(uint8_t portn, txc_int_stat_dbg_t *txcs,
5926f45ec7bSml29623 				uint8_t istats)
5936f45ec7bSml29623 {
5946f45ec7bSml29623 	switch (portn) {
5956f45ec7bSml29623 	case 0:
5966f45ec7bSml29623 		txcs->bits.ldw.port0_int_status |= istats;
5976f45ec7bSml29623 		break;
5986f45ec7bSml29623 	case 1:
5996f45ec7bSml29623 		txcs->bits.ldw.port1_int_status |= istats;
6006f45ec7bSml29623 		break;
6016f45ec7bSml29623 	case 2:
6026f45ec7bSml29623 		txcs->bits.ldw.port2_int_status |= istats;
6036f45ec7bSml29623 		break;
6046f45ec7bSml29623 	case 3:
6056f45ec7bSml29623 		txcs->bits.ldw.port3_int_status |= istats;
6066f45ec7bSml29623 		break;
6076f45ec7bSml29623 	default:
6086f45ec7bSml29623 		;
6096f45ec7bSml29623 	}
6106f45ec7bSml29623 }
611