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