| /* |
| * |
| * This file is provided under a dual BSD/GPLv2 license. When using or |
| * redistributing this file, you may do so under either license. |
| * |
| * GPL LICENSE SUMMARY |
| * |
| * Copyright(c) 2015 Intel Corporation. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of version 2 of the GNU General Public License as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, but |
| * WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * General Public License for more details. |
| * |
| * BSD LICENSE |
| * |
| * Copyright(c) 2015 Intel Corporation. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * - Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * - Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * - Neither the name of Intel Corporation nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| */ |
| |
| /* |
| * This file contains all of the code that is specific to the HFI chip |
| */ |
| |
| #include <linux/pci.h> |
| #include <linux/delay.h> |
| #include <linux/interrupt.h> |
| #include <linux/module.h> |
| |
| #include "hfi.h" |
| #include "trace.h" |
| #include "mad.h" |
| #include "pio.h" |
| #include "sdma.h" |
| #include "eprom.h" |
| |
| #define NUM_IB_PORTS 1 |
| |
| uint kdeth_qp; |
| module_param_named(kdeth_qp, kdeth_qp, uint, S_IRUGO); |
| MODULE_PARM_DESC(kdeth_qp, "Set the KDETH queue pair prefix"); |
| |
| uint num_vls = HFI1_MAX_VLS_SUPPORTED; |
| module_param(num_vls, uint, S_IRUGO); |
| MODULE_PARM_DESC(num_vls, "Set number of Virtual Lanes to use (1-8)"); |
| |
| /* |
| * Default time to aggregate two 10K packets from the idle state |
| * (timer not running). The timer starts at the end of the first packet, |
| * so only the time for one 10K packet and header plus a bit extra is needed. |
| * 10 * 1024 + 64 header byte = 10304 byte |
| * 10304 byte / 12.5 GB/s = 824.32ns |
| */ |
| uint rcv_intr_timeout = (824 + 16); /* 16 is for coalescing interrupt */ |
| module_param(rcv_intr_timeout, uint, S_IRUGO); |
| MODULE_PARM_DESC(rcv_intr_timeout, "Receive interrupt mitigation timeout in ns"); |
| |
| uint rcv_intr_count = 16; /* same as qib */ |
| module_param(rcv_intr_count, uint, S_IRUGO); |
| MODULE_PARM_DESC(rcv_intr_count, "Receive interrupt mitigation count"); |
| |
| ushort link_crc_mask = SUPPORTED_CRCS; |
| module_param(link_crc_mask, ushort, S_IRUGO); |
| MODULE_PARM_DESC(link_crc_mask, "CRCs to use on the link"); |
| |
| uint loopback; |
| module_param_named(loopback, loopback, uint, S_IRUGO); |
| MODULE_PARM_DESC(loopback, "Put into loopback mode (1 = serdes, 3 = external cable"); |
| |
| /* Other driver tunables */ |
| uint rcv_intr_dynamic = 1; /* enable dynamic mode for rcv int mitigation*/ |
| static ushort crc_14b_sideband = 1; |
| static uint use_flr = 1; |
| uint quick_linkup; /* skip LNI */ |
| |
| struct flag_table { |
| u64 flag; /* the flag */ |
| char *str; /* description string */ |
| u16 extra; /* extra information */ |
| u16 unused0; |
| u32 unused1; |
| }; |
| |
| /* str must be a string constant */ |
| #define FLAG_ENTRY(str, extra, flag) {flag, str, extra} |
| #define FLAG_ENTRY0(str, flag) {flag, str, 0} |
| |
| /* Send Error Consequences */ |
| #define SEC_WRITE_DROPPED 0x1 |
| #define SEC_PACKET_DROPPED 0x2 |
| #define SEC_SC_HALTED 0x4 /* per-context only */ |
| #define SEC_SPC_FREEZE 0x8 /* per-HFI only */ |
| |
| #define VL15CTXT 1 |
| #define MIN_KERNEL_KCTXTS 2 |
| #define NUM_MAP_REGS 32 |
| |
| /* Bit offset into the GUID which carries HFI id information */ |
| #define GUID_HFI_INDEX_SHIFT 39 |
| |
| /* extract the emulation revision */ |
| #define emulator_rev(dd) ((dd)->irev >> 8) |
| /* parallel and serial emulation versions are 3 and 4 respectively */ |
| #define is_emulator_p(dd) ((((dd)->irev) & 0xf) == 3) |
| #define is_emulator_s(dd) ((((dd)->irev) & 0xf) == 4) |
| |
| /* RSM fields */ |
| |
| /* packet type */ |
| #define IB_PACKET_TYPE 2ull |
| #define QW_SHIFT 6ull |
| /* QPN[7..1] */ |
| #define QPN_WIDTH 7ull |
| |
| /* LRH.BTH: QW 0, OFFSET 48 - for match */ |
| #define LRH_BTH_QW 0ull |
| #define LRH_BTH_BIT_OFFSET 48ull |
| #define LRH_BTH_OFFSET(off) ((LRH_BTH_QW << QW_SHIFT) | (off)) |
| #define LRH_BTH_MATCH_OFFSET LRH_BTH_OFFSET(LRH_BTH_BIT_OFFSET) |
| #define LRH_BTH_SELECT |
| #define LRH_BTH_MASK 3ull |
| #define LRH_BTH_VALUE 2ull |
| |
| /* LRH.SC[3..0] QW 0, OFFSET 56 - for match */ |
| #define LRH_SC_QW 0ull |
| #define LRH_SC_BIT_OFFSET 56ull |
| #define LRH_SC_OFFSET(off) ((LRH_SC_QW << QW_SHIFT) | (off)) |
| #define LRH_SC_MATCH_OFFSET LRH_SC_OFFSET(LRH_SC_BIT_OFFSET) |
| #define LRH_SC_MASK 128ull |
| #define LRH_SC_VALUE 0ull |
| |
| /* SC[n..0] QW 0, OFFSET 60 - for select */ |
| #define LRH_SC_SELECT_OFFSET ((LRH_SC_QW << QW_SHIFT) | (60ull)) |
| |
| /* QPN[m+n:1] QW 1, OFFSET 1 */ |
| #define QPN_SELECT_OFFSET ((1ull << QW_SHIFT) | (1ull)) |
| |
| /* defines to build power on SC2VL table */ |
| #define SC2VL_VAL( \ |
| num, \ |
| sc0, sc0val, \ |
| sc1, sc1val, \ |
| sc2, sc2val, \ |
| sc3, sc3val, \ |
| sc4, sc4val, \ |
| sc5, sc5val, \ |
| sc6, sc6val, \ |
| sc7, sc7val) \ |
| ( \ |
| ((u64)(sc0val) << SEND_SC2VLT##num##_SC##sc0##_SHIFT) | \ |
| ((u64)(sc1val) << SEND_SC2VLT##num##_SC##sc1##_SHIFT) | \ |
| ((u64)(sc2val) << SEND_SC2VLT##num##_SC##sc2##_SHIFT) | \ |
| ((u64)(sc3val) << SEND_SC2VLT##num##_SC##sc3##_SHIFT) | \ |
| ((u64)(sc4val) << SEND_SC2VLT##num##_SC##sc4##_SHIFT) | \ |
| ((u64)(sc5val) << SEND_SC2VLT##num##_SC##sc5##_SHIFT) | \ |
| ((u64)(sc6val) << SEND_SC2VLT##num##_SC##sc6##_SHIFT) | \ |
| ((u64)(sc7val) << SEND_SC2VLT##num##_SC##sc7##_SHIFT) \ |
| ) |
| |
| #define DC_SC_VL_VAL( \ |
| range, \ |
| e0, e0val, \ |
| e1, e1val, \ |
| e2, e2val, \ |
| e3, e3val, \ |
| e4, e4val, \ |
| e5, e5val, \ |
| e6, e6val, \ |
| e7, e7val, \ |
| e8, e8val, \ |
| e9, e9val, \ |
| e10, e10val, \ |
| e11, e11val, \ |
| e12, e12val, \ |
| e13, e13val, \ |
| e14, e14val, \ |
| e15, e15val) \ |
| ( \ |
| ((u64)(e0val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e0##_SHIFT) | \ |
| ((u64)(e1val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e1##_SHIFT) | \ |
| ((u64)(e2val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e2##_SHIFT) | \ |
| ((u64)(e3val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e3##_SHIFT) | \ |
| ((u64)(e4val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e4##_SHIFT) | \ |
| ((u64)(e5val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e5##_SHIFT) | \ |
| ((u64)(e6val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e6##_SHIFT) | \ |
| ((u64)(e7val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e7##_SHIFT) | \ |
| ((u64)(e8val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e8##_SHIFT) | \ |
| ((u64)(e9val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e9##_SHIFT) | \ |
| ((u64)(e10val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e10##_SHIFT) | \ |
| ((u64)(e11val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e11##_SHIFT) | \ |
| ((u64)(e12val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e12##_SHIFT) | \ |
| ((u64)(e13val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e13##_SHIFT) | \ |
| ((u64)(e14val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e14##_SHIFT) | \ |
| ((u64)(e15val) << DCC_CFG_SC_VL_TABLE_##range##_ENTRY##e15##_SHIFT) \ |
| ) |
| |
| /* all CceStatus sub-block freeze bits */ |
| #define ALL_FROZE (CCE_STATUS_SDMA_FROZE_SMASK \ |
| | CCE_STATUS_RXE_FROZE_SMASK \ |
| | CCE_STATUS_TXE_FROZE_SMASK \ |
| | CCE_STATUS_TXE_PIO_FROZE_SMASK) |
| /* all CceStatus sub-block TXE pause bits */ |
| #define ALL_TXE_PAUSE (CCE_STATUS_TXE_PIO_PAUSED_SMASK \ |
| | CCE_STATUS_TXE_PAUSED_SMASK \ |
| | CCE_STATUS_SDMA_PAUSED_SMASK) |
| /* all CceStatus sub-block RXE pause bits */ |
| #define ALL_RXE_PAUSE CCE_STATUS_RXE_PAUSED_SMASK |
| |
| /* |
| * CCE Error flags. |
| */ |
| static struct flag_table cce_err_status_flags[] = { |
| /* 0*/ FLAG_ENTRY0("CceCsrParityErr", |
| CCE_ERR_STATUS_CCE_CSR_PARITY_ERR_SMASK), |
| /* 1*/ FLAG_ENTRY0("CceCsrReadBadAddrErr", |
| CCE_ERR_STATUS_CCE_CSR_READ_BAD_ADDR_ERR_SMASK), |
| /* 2*/ FLAG_ENTRY0("CceCsrWriteBadAddrErr", |
| CCE_ERR_STATUS_CCE_CSR_WRITE_BAD_ADDR_ERR_SMASK), |
| /* 3*/ FLAG_ENTRY0("CceTrgtAsyncFifoParityErr", |
| CCE_ERR_STATUS_CCE_TRGT_ASYNC_FIFO_PARITY_ERR_SMASK), |
| /* 4*/ FLAG_ENTRY0("CceTrgtAccessErr", |
| CCE_ERR_STATUS_CCE_TRGT_ACCESS_ERR_SMASK), |
| /* 5*/ FLAG_ENTRY0("CceRspdDataParityErr", |
| CCE_ERR_STATUS_CCE_RSPD_DATA_PARITY_ERR_SMASK), |
| /* 6*/ FLAG_ENTRY0("CceCli0AsyncFifoParityErr", |
| CCE_ERR_STATUS_CCE_CLI0_ASYNC_FIFO_PARITY_ERR_SMASK), |
| /* 7*/ FLAG_ENTRY0("CceCsrCfgBusParityErr", |
| CCE_ERR_STATUS_CCE_CSR_CFG_BUS_PARITY_ERR_SMASK), |
| /* 8*/ FLAG_ENTRY0("CceCli2AsyncFifoParityErr", |
| CCE_ERR_STATUS_CCE_CLI2_ASYNC_FIFO_PARITY_ERR_SMASK), |
| /* 9*/ FLAG_ENTRY0("CceCli1AsyncFifoPioCrdtParityErr", |
| CCE_ERR_STATUS_CCE_CLI1_ASYNC_FIFO_PIO_CRDT_PARITY_ERR_SMASK), |
| /*10*/ FLAG_ENTRY0("CceCli1AsyncFifoPioCrdtParityErr", |
| CCE_ERR_STATUS_CCE_CLI1_ASYNC_FIFO_SDMA_HD_PARITY_ERR_SMASK), |
| /*11*/ FLAG_ENTRY0("CceCli1AsyncFifoRxdmaParityError", |
| CCE_ERR_STATUS_CCE_CLI1_ASYNC_FIFO_RXDMA_PARITY_ERROR_SMASK), |
| /*12*/ FLAG_ENTRY0("CceCli1AsyncFifoDbgParityError", |
| CCE_ERR_STATUS_CCE_CLI1_ASYNC_FIFO_DBG_PARITY_ERROR_SMASK), |
| /*13*/ FLAG_ENTRY0("PcicRetryMemCorErr", |
| CCE_ERR_STATUS_PCIC_RETRY_MEM_COR_ERR_SMASK), |
| /*14*/ FLAG_ENTRY0("PcicRetryMemCorErr", |
| CCE_ERR_STATUS_PCIC_RETRY_SOT_MEM_COR_ERR_SMASK), |
| /*15*/ FLAG_ENTRY0("PcicPostHdQCorErr", |
| CCE_ERR_STATUS_PCIC_POST_HD_QCOR_ERR_SMASK), |
| /*16*/ FLAG_ENTRY0("PcicPostHdQCorErr", |
| CCE_ERR_STATUS_PCIC_POST_DAT_QCOR_ERR_SMASK), |
| /*17*/ FLAG_ENTRY0("PcicPostHdQCorErr", |
| CCE_ERR_STATUS_PCIC_CPL_HD_QCOR_ERR_SMASK), |
| /*18*/ FLAG_ENTRY0("PcicCplDatQCorErr", |
| CCE_ERR_STATUS_PCIC_CPL_DAT_QCOR_ERR_SMASK), |
| /*19*/ FLAG_ENTRY0("PcicNPostHQParityErr", |
| CCE_ERR_STATUS_PCIC_NPOST_HQ_PARITY_ERR_SMASK), |
| /*20*/ FLAG_ENTRY0("PcicNPostDatQParityErr", |
| CCE_ERR_STATUS_PCIC_NPOST_DAT_QPARITY_ERR_SMASK), |
| /*21*/ FLAG_ENTRY0("PcicRetryMemUncErr", |
| CCE_ERR_STATUS_PCIC_RETRY_MEM_UNC_ERR_SMASK), |
| /*22*/ FLAG_ENTRY0("PcicRetrySotMemUncErr", |
| CCE_ERR_STATUS_PCIC_RETRY_SOT_MEM_UNC_ERR_SMASK), |
| /*23*/ FLAG_ENTRY0("PcicPostHdQUncErr", |
| CCE_ERR_STATUS_PCIC_POST_HD_QUNC_ERR_SMASK), |
| /*24*/ FLAG_ENTRY0("PcicPostDatQUncErr", |
| CCE_ERR_STATUS_PCIC_POST_DAT_QUNC_ERR_SMASK), |
| /*25*/ FLAG_ENTRY0("PcicCplHdQUncErr", |
| CCE_ERR_STATUS_PCIC_CPL_HD_QUNC_ERR_SMASK), |
| /*26*/ FLAG_ENTRY0("PcicCplDatQUncErr", |
| CCE_ERR_STATUS_PCIC_CPL_DAT_QUNC_ERR_SMASK), |
| /*27*/ FLAG_ENTRY0("PcicTransmitFrontParityErr", |
| CCE_ERR_STATUS_PCIC_TRANSMIT_FRONT_PARITY_ERR_SMASK), |
| /*28*/ FLAG_ENTRY0("PcicTransmitBackParityErr", |
| CCE_ERR_STATUS_PCIC_TRANSMIT_BACK_PARITY_ERR_SMASK), |
| /*29*/ FLAG_ENTRY0("PcicReceiveParityErr", |
| CCE_ERR_STATUS_PCIC_RECEIVE_PARITY_ERR_SMASK), |
| /*30*/ FLAG_ENTRY0("CceTrgtCplTimeoutErr", |
| CCE_ERR_STATUS_CCE_TRGT_CPL_TIMEOUT_ERR_SMASK), |
| /*31*/ FLAG_ENTRY0("LATriggered", |
| CCE_ERR_STATUS_LA_TRIGGERED_SMASK), |
| /*32*/ FLAG_ENTRY0("CceSegReadBadAddrErr", |
| CCE_ERR_STATUS_CCE_SEG_READ_BAD_ADDR_ERR_SMASK), |
| /*33*/ FLAG_ENTRY0("CceSegWriteBadAddrErr", |
| CCE_ERR_STATUS_CCE_SEG_WRITE_BAD_ADDR_ERR_SMASK), |
| /*34*/ FLAG_ENTRY0("CceRcplAsyncFifoParityErr", |
| CCE_ERR_STATUS_CCE_RCPL_ASYNC_FIFO_PARITY_ERR_SMASK), |
| /*35*/ FLAG_ENTRY0("CceRxdmaConvFifoParityErr", |
| CCE_ERR_STATUS_CCE_RXDMA_CONV_FIFO_PARITY_ERR_SMASK), |
| /*36*/ FLAG_ENTRY0("CceMsixTableCorErr", |
| CCE_ERR_STATUS_CCE_MSIX_TABLE_COR_ERR_SMASK), |
| /*37*/ FLAG_ENTRY0("CceMsixTableUncErr", |
| CCE_ERR_STATUS_CCE_MSIX_TABLE_UNC_ERR_SMASK), |
| /*38*/ FLAG_ENTRY0("CceIntMapCorErr", |
| CCE_ERR_STATUS_CCE_INT_MAP_COR_ERR_SMASK), |
| /*39*/ FLAG_ENTRY0("CceIntMapUncErr", |
| CCE_ERR_STATUS_CCE_INT_MAP_UNC_ERR_SMASK), |
| /*40*/ FLAG_ENTRY0("CceMsixCsrParityErr", |
| CCE_ERR_STATUS_CCE_MSIX_CSR_PARITY_ERR_SMASK), |
| /*41-63 reserved*/ |
| }; |
| |
| /* |
| * Misc Error flags |
| */ |
| #define MES(text) MISC_ERR_STATUS_MISC_##text##_ERR_SMASK |
| static struct flag_table misc_err_status_flags[] = { |
| /* 0*/ FLAG_ENTRY0("CSR_PARITY", MES(CSR_PARITY)), |
| /* 1*/ FLAG_ENTRY0("CSR_READ_BAD_ADDR", MES(CSR_READ_BAD_ADDR)), |
| /* 2*/ FLAG_ENTRY0("CSR_WRITE_BAD_ADDR", MES(CSR_WRITE_BAD_ADDR)), |
| /* 3*/ FLAG_ENTRY0("SBUS_WRITE_FAILED", MES(SBUS_WRITE_FAILED)), |
| /* 4*/ FLAG_ENTRY0("KEY_MISMATCH", MES(KEY_MISMATCH)), |
| /* 5*/ FLAG_ENTRY0("FW_AUTH_FAILED", MES(FW_AUTH_FAILED)), |
| /* 6*/ FLAG_ENTRY0("EFUSE_CSR_PARITY", MES(EFUSE_CSR_PARITY)), |
| /* 7*/ FLAG_ENTRY0("EFUSE_READ_BAD_ADDR", MES(EFUSE_READ_BAD_ADDR)), |
| /* 8*/ FLAG_ENTRY0("EFUSE_WRITE", MES(EFUSE_WRITE)), |
| /* 9*/ FLAG_ENTRY0("EFUSE_DONE_PARITY", MES(EFUSE_DONE_PARITY)), |
| /*10*/ FLAG_ENTRY0("INVALID_EEP_CMD", MES(INVALID_EEP_CMD)), |
| /*11*/ FLAG_ENTRY0("MBIST_FAIL", MES(MBIST_FAIL)), |
| /*12*/ FLAG_ENTRY0("PLL_LOCK_FAIL", MES(PLL_LOCK_FAIL)) |
| }; |
| |
| /* |
| * TXE PIO Error flags and consequences |
| */ |
| static struct flag_table pio_err_status_flags[] = { |
| /* 0*/ FLAG_ENTRY("PioWriteBadCtxt", |
| SEC_WRITE_DROPPED, |
| SEND_PIO_ERR_STATUS_PIO_WRITE_BAD_CTXT_ERR_SMASK), |
| /* 1*/ FLAG_ENTRY("PioWriteAddrParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_WRITE_ADDR_PARITY_ERR_SMASK), |
| /* 2*/ FLAG_ENTRY("PioCsrParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_CSR_PARITY_ERR_SMASK), |
| /* 3*/ FLAG_ENTRY("PioSbMemFifo0", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_SB_MEM_FIFO0_ERR_SMASK), |
| /* 4*/ FLAG_ENTRY("PioSbMemFifo1", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_SB_MEM_FIFO1_ERR_SMASK), |
| /* 5*/ FLAG_ENTRY("PioPccFifoParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_PCC_FIFO_PARITY_ERR_SMASK), |
| /* 6*/ FLAG_ENTRY("PioPecFifoParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_PEC_FIFO_PARITY_ERR_SMASK), |
| /* 7*/ FLAG_ENTRY("PioSbrdctlCrrelParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_SBRDCTL_CRREL_PARITY_ERR_SMASK), |
| /* 8*/ FLAG_ENTRY("PioSbrdctrlCrrelFifoParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_SBRDCTRL_CRREL_FIFO_PARITY_ERR_SMASK), |
| /* 9*/ FLAG_ENTRY("PioPktEvictFifoParityErr", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_PKT_EVICT_FIFO_PARITY_ERR_SMASK), |
| /*10*/ FLAG_ENTRY("PioSmPktResetParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_SM_PKT_RESET_PARITY_ERR_SMASK), |
| /*11*/ FLAG_ENTRY("PioVlLenMemBank0Unc", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_VL_LEN_MEM_BANK0_UNC_ERR_SMASK), |
| /*12*/ FLAG_ENTRY("PioVlLenMemBank1Unc", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_VL_LEN_MEM_BANK1_UNC_ERR_SMASK), |
| /*13*/ FLAG_ENTRY("PioVlLenMemBank0Cor", |
| 0, |
| SEND_PIO_ERR_STATUS_PIO_VL_LEN_MEM_BANK0_COR_ERR_SMASK), |
| /*14*/ FLAG_ENTRY("PioVlLenMemBank1Cor", |
| 0, |
| SEND_PIO_ERR_STATUS_PIO_VL_LEN_MEM_BANK1_COR_ERR_SMASK), |
| /*15*/ FLAG_ENTRY("PioCreditRetFifoParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_CREDIT_RET_FIFO_PARITY_ERR_SMASK), |
| /*16*/ FLAG_ENTRY("PioPpmcPblFifo", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_PPMC_PBL_FIFO_ERR_SMASK), |
| /*17*/ FLAG_ENTRY("PioInitSmIn", |
| 0, |
| SEND_PIO_ERR_STATUS_PIO_INIT_SM_IN_ERR_SMASK), |
| /*18*/ FLAG_ENTRY("PioPktEvictSmOrArbSm", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_PKT_EVICT_SM_OR_ARB_SM_ERR_SMASK), |
| /*19*/ FLAG_ENTRY("PioHostAddrMemUnc", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_HOST_ADDR_MEM_UNC_ERR_SMASK), |
| /*20*/ FLAG_ENTRY("PioHostAddrMemCor", |
| 0, |
| SEND_PIO_ERR_STATUS_PIO_HOST_ADDR_MEM_COR_ERR_SMASK), |
| /*21*/ FLAG_ENTRY("PioWriteDataParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_WRITE_DATA_PARITY_ERR_SMASK), |
| /*22*/ FLAG_ENTRY("PioStateMachine", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_STATE_MACHINE_ERR_SMASK), |
| /*23*/ FLAG_ENTRY("PioWriteQwValidParity", |
| SEC_WRITE_DROPPED|SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_WRITE_QW_VALID_PARITY_ERR_SMASK), |
| /*24*/ FLAG_ENTRY("PioBlockQwCountParity", |
| SEC_WRITE_DROPPED|SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_BLOCK_QW_COUNT_PARITY_ERR_SMASK), |
| /*25*/ FLAG_ENTRY("PioVlfVlLenParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_VLF_VL_LEN_PARITY_ERR_SMASK), |
| /*26*/ FLAG_ENTRY("PioVlfSopParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_VLF_SOP_PARITY_ERR_SMASK), |
| /*27*/ FLAG_ENTRY("PioVlFifoParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_VL_FIFO_PARITY_ERR_SMASK), |
| /*28*/ FLAG_ENTRY("PioPpmcBqcMemParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_PPMC_BQC_MEM_PARITY_ERR_SMASK), |
| /*29*/ FLAG_ENTRY("PioPpmcSopLen", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_PPMC_SOP_LEN_ERR_SMASK), |
| /*30-31 reserved*/ |
| /*32*/ FLAG_ENTRY("PioCurrentFreeCntParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_CURRENT_FREE_CNT_PARITY_ERR_SMASK), |
| /*33*/ FLAG_ENTRY("PioLastReturnedCntParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_LAST_RETURNED_CNT_PARITY_ERR_SMASK), |
| /*34*/ FLAG_ENTRY("PioPccSopHeadParity", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_PCC_SOP_HEAD_PARITY_ERR_SMASK), |
| /*35*/ FLAG_ENTRY("PioPecSopHeadParityErr", |
| SEC_SPC_FREEZE, |
| SEND_PIO_ERR_STATUS_PIO_PEC_SOP_HEAD_PARITY_ERR_SMASK), |
| /*36-63 reserved*/ |
| }; |
| |
| /* TXE PIO errors that cause an SPC freeze */ |
| #define ALL_PIO_FREEZE_ERR \ |
| (SEND_PIO_ERR_STATUS_PIO_WRITE_ADDR_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_CSR_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_SB_MEM_FIFO0_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_SB_MEM_FIFO1_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_PCC_FIFO_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_PEC_FIFO_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_SBRDCTL_CRREL_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_SBRDCTRL_CRREL_FIFO_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_PKT_EVICT_FIFO_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_SM_PKT_RESET_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_VL_LEN_MEM_BANK0_UNC_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_VL_LEN_MEM_BANK1_UNC_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_CREDIT_RET_FIFO_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_PPMC_PBL_FIFO_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_PKT_EVICT_SM_OR_ARB_SM_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_HOST_ADDR_MEM_UNC_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_WRITE_DATA_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_STATE_MACHINE_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_WRITE_QW_VALID_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_BLOCK_QW_COUNT_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_VLF_VL_LEN_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_VLF_SOP_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_VL_FIFO_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_PPMC_BQC_MEM_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_PPMC_SOP_LEN_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_CURRENT_FREE_CNT_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_LAST_RETURNED_CNT_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_PCC_SOP_HEAD_PARITY_ERR_SMASK \ |
| | SEND_PIO_ERR_STATUS_PIO_PEC_SOP_HEAD_PARITY_ERR_SMASK) |
| |
| /* |
| * TXE SDMA Error flags |
| */ |
| static struct flag_table sdma_err_status_flags[] = { |
| /* 0*/ FLAG_ENTRY0("SDmaRpyTagErr", |
| SEND_DMA_ERR_STATUS_SDMA_RPY_TAG_ERR_SMASK), |
| /* 1*/ FLAG_ENTRY0("SDmaCsrParityErr", |
| SEND_DMA_ERR_STATUS_SDMA_CSR_PARITY_ERR_SMASK), |
| /* 2*/ FLAG_ENTRY0("SDmaPcieReqTrackingUncErr", |
| SEND_DMA_ERR_STATUS_SDMA_PCIE_REQ_TRACKING_UNC_ERR_SMASK), |
| /* 3*/ FLAG_ENTRY0("SDmaPcieReqTrackingCorErr", |
| SEND_DMA_ERR_STATUS_SDMA_PCIE_REQ_TRACKING_COR_ERR_SMASK), |
| /*04-63 reserved*/ |
| }; |
| |
| /* TXE SDMA errors that cause an SPC freeze */ |
| #define ALL_SDMA_FREEZE_ERR \ |
| (SEND_DMA_ERR_STATUS_SDMA_RPY_TAG_ERR_SMASK \ |
| | SEND_DMA_ERR_STATUS_SDMA_CSR_PARITY_ERR_SMASK \ |
| | SEND_DMA_ERR_STATUS_SDMA_PCIE_REQ_TRACKING_UNC_ERR_SMASK) |
| |
| /* |
| * TXE Egress Error flags |
| */ |
| #define SEES(text) SEND_EGRESS_ERR_STATUS_##text##_ERR_SMASK |
| static struct flag_table egress_err_status_flags[] = { |
| /* 0*/ FLAG_ENTRY0("TxPktIntegrityMemCorErr", SEES(TX_PKT_INTEGRITY_MEM_COR)), |
| /* 1*/ FLAG_ENTRY0("TxPktIntegrityMemUncErr", SEES(TX_PKT_INTEGRITY_MEM_UNC)), |
| /* 2 reserved */ |
| /* 3*/ FLAG_ENTRY0("TxEgressFifoUnderrunOrParityErr", |
| SEES(TX_EGRESS_FIFO_UNDERRUN_OR_PARITY)), |
| /* 4*/ FLAG_ENTRY0("TxLinkdownErr", SEES(TX_LINKDOWN)), |
| /* 5*/ FLAG_ENTRY0("TxIncorrectLinkStateErr", SEES(TX_INCORRECT_LINK_STATE)), |
| /* 6 reserved */ |
| /* 7*/ FLAG_ENTRY0("TxPioLaunchIntfParityErr", |
| SEES(TX_PIO_LAUNCH_INTF_PARITY)), |
| /* 8*/ FLAG_ENTRY0("TxSdmaLaunchIntfParityErr", |
| SEES(TX_SDMA_LAUNCH_INTF_PARITY)), |
| /* 9-10 reserved */ |
| /*11*/ FLAG_ENTRY0("TxSbrdCtlStateMachineParityErr", |
| SEES(TX_SBRD_CTL_STATE_MACHINE_PARITY)), |
| /*12*/ FLAG_ENTRY0("TxIllegalVLErr", SEES(TX_ILLEGAL_VL)), |
| /*13*/ FLAG_ENTRY0("TxLaunchCsrParityErr", SEES(TX_LAUNCH_CSR_PARITY)), |
| /*14*/ FLAG_ENTRY0("TxSbrdCtlCsrParityErr", SEES(TX_SBRD_CTL_CSR_PARITY)), |
| /*15*/ FLAG_ENTRY0("TxConfigParityErr", SEES(TX_CONFIG_PARITY)), |
| /*16*/ FLAG_ENTRY0("TxSdma0DisallowedPacketErr", |
| SEES(TX_SDMA0_DISALLOWED_PACKET)), |
| /*17*/ FLAG_ENTRY0("TxSdma1DisallowedPacketErr", |
| SEES(TX_SDMA1_DISALLOWED_PACKET)), |
| /*18*/ FLAG_ENTRY0("TxSdma2DisallowedPacketErr", |
| SEES(TX_SDMA2_DISALLOWED_PACKET)), |
| /*19*/ FLAG_ENTRY0("TxSdma3DisallowedPacketErr", |
| SEES(TX_SDMA3_DISALLOWED_PACKET)), |
| /*20*/ FLAG_ENTRY0("TxSdma4DisallowedPacketErr", |
| SEES(TX_SDMA4_DISALLOWED_PACKET)), |
| /*21*/ FLAG_ENTRY0("TxSdma5DisallowedPacketErr", |
| SEES(TX_SDMA5_DISALLOWED_PACKET)), |
| /*22*/ FLAG_ENTRY0("TxSdma6DisallowedPacketErr", |
| SEES(TX_SDMA6_DISALLOWED_PACKET)), |
| /*23*/ FLAG_ENTRY0("TxSdma7DisallowedPacketErr", |
| SEES(TX_SDMA7_DISALLOWED_PACKET)), |
| /*24*/ FLAG_ENTRY0("TxSdma8DisallowedPacketErr", |
| SEES(TX_SDMA8_DISALLOWED_PACKET)), |
| /*25*/ FLAG_ENTRY0("TxSdma9DisallowedPacketErr", |
| SEES(TX_SDMA9_DISALLOWED_PACKET)), |
| /*26*/ FLAG_ENTRY0("TxSdma10DisallowedPacketErr", |
| SEES(TX_SDMA10_DISALLOWED_PACKET)), |
| /*27*/ FLAG_ENTRY0("TxSdma11DisallowedPacketErr", |
| SEES(TX_SDMA11_DISALLOWED_PACKET)), |
| /*28*/ FLAG_ENTRY0("TxSdma12DisallowedPacketErr", |
| SEES(TX_SDMA12_DISALLOWED_PACKET)), |
| /*29*/ FLAG_ENTRY0("TxSdma13DisallowedPacketErr", |
| SEES(TX_SDMA13_DISALLOWED_PACKET)), |
| /*30*/ FLAG_ENTRY0("TxSdma14DisallowedPacketErr", |
| SEES(TX_SDMA14_DISALLOWED_PACKET)), |
| /*31*/ FLAG_ENTRY0("TxSdma15DisallowedPacketErr", |
| SEES(TX_SDMA15_DISALLOWED_PACKET)), |
| /*32*/ FLAG_ENTRY0("TxLaunchFifo0UncOrParityErr", |
| SEES(TX_LAUNCH_FIFO0_UNC_OR_PARITY)), |
| /*33*/ FLAG_ENTRY0("TxLaunchFifo1UncOrParityErr", |
| SEES(TX_LAUNCH_FIFO1_UNC_OR_PARITY)), |
| /*34*/ FLAG_ENTRY0("TxLaunchFifo2UncOrParityErr", |
| SEES(TX_LAUNCH_FIFO2_UNC_OR_PARITY)), |
| /*35*/ FLAG_ENTRY0("TxLaunchFifo3UncOrParityErr", |
| SEES(TX_LAUNCH_FIFO3_UNC_OR_PARITY)), |
| /*36*/ FLAG_ENTRY0("TxLaunchFifo4UncOrParityErr", |
| SEES(TX_LAUNCH_FIFO4_UNC_OR_PARITY)), |
| /*37*/ FLAG_ENTRY0("TxLaunchFifo5UncOrParityErr", |
| SEES(TX_LAUNCH_FIFO5_UNC_OR_PARITY)), |
| /*38*/ FLAG_ENTRY0("TxLaunchFifo6UncOrParityErr", |
| SEES(TX_LAUNCH_FIFO6_UNC_OR_PARITY)), |
| /*39*/ FLAG_ENTRY0("TxLaunchFifo7UncOrParityErr", |
| SEES(TX_LAUNCH_FIFO7_UNC_OR_PARITY)), |
| /*40*/ FLAG_ENTRY0("TxLaunchFifo8UncOrParityErr", |
| SEES(TX_LAUNCH_FIFO8_UNC_OR_PARITY)), |
| /*41*/ FLAG_ENTRY0("TxCreditReturnParityErr", SEES(TX_CREDIT_RETURN_PARITY)), |
| /*42*/ FLAG_ENTRY0("TxSbHdrUncErr", SEES(TX_SB_HDR_UNC)), |
| /*43*/ FLAG_ENTRY0("TxReadSdmaMemoryUncErr", SEES(TX_READ_SDMA_MEMORY_UNC)), |
| /*44*/ FLAG_ENTRY0("TxReadPioMemoryUncErr", SEES(TX_READ_PIO_MEMORY_UNC)), |
| /*45*/ FLAG_ENTRY0("TxEgressFifoUncErr", SEES(TX_EGRESS_FIFO_UNC)), |
| /*46*/ FLAG_ENTRY0("TxHcrcInsertionErr", SEES(TX_HCRC_INSERTION)), |
| /*47*/ FLAG_ENTRY0("TxCreditReturnVLErr", SEES(TX_CREDIT_RETURN_VL)), |
| /*48*/ FLAG_ENTRY0("TxLaunchFifo0CorErr", SEES(TX_LAUNCH_FIFO0_COR)), |
| /*49*/ FLAG_ENTRY0("TxLaunchFifo1CorErr", SEES(TX_LAUNCH_FIFO1_COR)), |
| /*50*/ FLAG_ENTRY0("TxLaunchFifo2CorErr", SEES(TX_LAUNCH_FIFO2_COR)), |
| /*51*/ FLAG_ENTRY0("TxLaunchFifo3CorErr", SEES(TX_LAUNCH_FIFO3_COR)), |
| /*52*/ FLAG_ENTRY0("TxLaunchFifo4CorErr", SEES(TX_LAUNCH_FIFO4_COR)), |
| /*53*/ FLAG_ENTRY0("TxLaunchFifo5CorErr", SEES(TX_LAUNCH_FIFO5_COR)), |
| /*54*/ FLAG_ENTRY0("TxLaunchFifo6CorErr", SEES(TX_LAUNCH_FIFO6_COR)), |
| /*55*/ FLAG_ENTRY0("TxLaunchFifo7CorErr", SEES(TX_LAUNCH_FIFO7_COR)), |
| /*56*/ FLAG_ENTRY0("TxLaunchFifo8CorErr", SEES(TX_LAUNCH_FIFO8_COR)), |
| /*57*/ FLAG_ENTRY0("TxCreditOverrunErr", SEES(TX_CREDIT_OVERRUN)), |
| /*58*/ FLAG_ENTRY0("TxSbHdrCorErr", SEES(TX_SB_HDR_COR)), |
| /*59*/ FLAG_ENTRY0("TxReadSdmaMemoryCorErr", SEES(TX_READ_SDMA_MEMORY_COR)), |
| /*60*/ FLAG_ENTRY0("TxReadPioMemoryCorErr", SEES(TX_READ_PIO_MEMORY_COR)), |
| /*61*/ FLAG_ENTRY0("TxEgressFifoCorErr", SEES(TX_EGRESS_FIFO_COR)), |
| /*62*/ FLAG_ENTRY0("TxReadSdmaMemoryCsrUncErr", |
| SEES(TX_READ_SDMA_MEMORY_CSR_UNC)), |
| /*63*/ FLAG_ENTRY0("TxReadPioMemoryCsrUncErr", |
| SEES(TX_READ_PIO_MEMORY_CSR_UNC)), |
| }; |
| |
| /* |
| * TXE Egress Error Info flags |
| */ |
| #define SEEI(text) SEND_EGRESS_ERR_INFO_##text##_ERR_SMASK |
| static struct flag_table egress_err_info_flags[] = { |
| /* 0*/ FLAG_ENTRY0("Reserved", 0ull), |
| /* 1*/ FLAG_ENTRY0("VLErr", SEEI(VL)), |
| /* 2*/ FLAG_ENTRY0("JobKeyErr", SEEI(JOB_KEY)), |
| /* 3*/ FLAG_ENTRY0("JobKeyErr", SEEI(JOB_KEY)), |
| /* 4*/ FLAG_ENTRY0("PartitionKeyErr", SEEI(PARTITION_KEY)), |
| /* 5*/ FLAG_ENTRY0("SLIDErr", SEEI(SLID)), |
| /* 6*/ FLAG_ENTRY0("OpcodeErr", SEEI(OPCODE)), |
| /* 7*/ FLAG_ENTRY0("VLMappingErr", SEEI(VL_MAPPING)), |
| /* 8*/ FLAG_ENTRY0("RawErr", SEEI(RAW)), |
| /* 9*/ FLAG_ENTRY0("RawIPv6Err", SEEI(RAW_IPV6)), |
| /*10*/ FLAG_ENTRY0("GRHErr", SEEI(GRH)), |
| /*11*/ FLAG_ENTRY0("BypassErr", SEEI(BYPASS)), |
| /*12*/ FLAG_ENTRY0("KDETHPacketsErr", SEEI(KDETH_PACKETS)), |
| /*13*/ FLAG_ENTRY0("NonKDETHPacketsErr", SEEI(NON_KDETH_PACKETS)), |
| /*14*/ FLAG_ENTRY0("TooSmallIBPacketsErr", SEEI(TOO_SMALL_IB_PACKETS)), |
| /*15*/ FLAG_ENTRY0("TooSmallBypassPacketsErr", SEEI(TOO_SMALL_BYPASS_PACKETS)), |
| /*16*/ FLAG_ENTRY0("PbcTestErr", SEEI(PBC_TEST)), |
| /*17*/ FLAG_ENTRY0("BadPktLenErr", SEEI(BAD_PKT_LEN)), |
| /*18*/ FLAG_ENTRY0("TooLongIBPacketErr", SEEI(TOO_LONG_IB_PACKET)), |
| /*19*/ FLAG_ENTRY0("TooLongBypassPacketsErr", SEEI(TOO_LONG_BYPASS_PACKETS)), |
| /*20*/ FLAG_ENTRY0("PbcStaticRateControlErr", SEEI(PBC_STATIC_RATE_CONTROL)), |
| /*21*/ FLAG_ENTRY0("BypassBadPktLenErr", SEEI(BAD_PKT_LEN)), |
| }; |
| |
| /* TXE Egress errors that cause an SPC freeze */ |
| #define ALL_TXE_EGRESS_FREEZE_ERR \ |
| (SEES(TX_EGRESS_FIFO_UNDERRUN_OR_PARITY) \ |
| | SEES(TX_PIO_LAUNCH_INTF_PARITY) \ |
| | SEES(TX_SDMA_LAUNCH_INTF_PARITY) \ |
| | SEES(TX_SBRD_CTL_STATE_MACHINE_PARITY) \ |
| | SEES(TX_LAUNCH_CSR_PARITY) \ |
| | SEES(TX_SBRD_CTL_CSR_PARITY) \ |
| | SEES(TX_CONFIG_PARITY) \ |
| | SEES(TX_LAUNCH_FIFO0_UNC_OR_PARITY) \ |
| | SEES(TX_LAUNCH_FIFO1_UNC_OR_PARITY) \ |
| | SEES(TX_LAUNCH_FIFO2_UNC_OR_PARITY) \ |
| | SEES(TX_LAUNCH_FIFO3_UNC_OR_PARITY) \ |
| | SEES(TX_LAUNCH_FIFO4_UNC_OR_PARITY) \ |
| | SEES(TX_LAUNCH_FIFO5_UNC_OR_PARITY) \ |
| | SEES(TX_LAUNCH_FIFO6_UNC_OR_PARITY) \ |
| | SEES(TX_LAUNCH_FIFO7_UNC_OR_PARITY) \ |
| | SEES(TX_LAUNCH_FIFO8_UNC_OR_PARITY) \ |
| | SEES(TX_CREDIT_RETURN_PARITY)) |
| |
| /* |
| * TXE Send error flags |
| */ |
| #define SES(name) SEND_ERR_STATUS_SEND_##name##_ERR_SMASK |
| static struct flag_table send_err_status_flags[] = { |
| /* 0*/ FLAG_ENTRY0("SDmaRpyTagErr", SES(CSR_PARITY)), |
| /* 1*/ FLAG_ENTRY0("SendCsrReadBadAddrErr", SES(CSR_READ_BAD_ADDR)), |
| /* 2*/ FLAG_ENTRY0("SendCsrWriteBadAddrErr", SES(CSR_WRITE_BAD_ADDR)) |
| }; |
| |
| /* |
| * TXE Send Context Error flags and consequences |
| */ |
| static struct flag_table sc_err_status_flags[] = { |
| /* 0*/ FLAG_ENTRY("InconsistentSop", |
| SEC_PACKET_DROPPED | SEC_SC_HALTED, |
| SEND_CTXT_ERR_STATUS_PIO_INCONSISTENT_SOP_ERR_SMASK), |
| /* 1*/ FLAG_ENTRY("DisallowedPacket", |
| SEC_PACKET_DROPPED | SEC_SC_HALTED, |
| SEND_CTXT_ERR_STATUS_PIO_DISALLOWED_PACKET_ERR_SMASK), |
| /* 2*/ FLAG_ENTRY("WriteCrossesBoundary", |
| SEC_WRITE_DROPPED | SEC_SC_HALTED, |
| SEND_CTXT_ERR_STATUS_PIO_WRITE_CROSSES_BOUNDARY_ERR_SMASK), |
| /* 3*/ FLAG_ENTRY("WriteOverflow", |
| SEC_WRITE_DROPPED | SEC_SC_HALTED, |
| SEND_CTXT_ERR_STATUS_PIO_WRITE_OVERFLOW_ERR_SMASK), |
| /* 4*/ FLAG_ENTRY("WriteOutOfBounds", |
| SEC_WRITE_DROPPED | SEC_SC_HALTED, |
| SEND_CTXT_ERR_STATUS_PIO_WRITE_OUT_OF_BOUNDS_ERR_SMASK), |
| /* 5-63 reserved*/ |
| }; |
| |
| /* |
| * RXE Receive Error flags |
| */ |
| #define RXES(name) RCV_ERR_STATUS_RX_##name##_ERR_SMASK |
| static struct flag_table rxe_err_status_flags[] = { |
| /* 0*/ FLAG_ENTRY0("RxDmaCsrCorErr", RXES(DMA_CSR_COR)), |
| /* 1*/ FLAG_ENTRY0("RxDcIntfParityErr", RXES(DC_INTF_PARITY)), |
| /* 2*/ FLAG_ENTRY0("RxRcvHdrUncErr", RXES(RCV_HDR_UNC)), |
| /* 3*/ FLAG_ENTRY0("RxRcvHdrCorErr", RXES(RCV_HDR_COR)), |
| /* 4*/ FLAG_ENTRY0("RxRcvDataUncErr", RXES(RCV_DATA_UNC)), |
| /* 5*/ FLAG_ENTRY0("RxRcvDataCorErr", RXES(RCV_DATA_COR)), |
| /* 6*/ FLAG_ENTRY0("RxRcvQpMapTableUncErr", RXES(RCV_QP_MAP_TABLE_UNC)), |
| /* 7*/ FLAG_ENTRY0("RxRcvQpMapTableCorErr", RXES(RCV_QP_MAP_TABLE_COR)), |
| /* 8*/ FLAG_ENTRY0("RxRcvCsrParityErr", RXES(RCV_CSR_PARITY)), |
| /* 9*/ FLAG_ENTRY0("RxDcSopEopParityErr", RXES(DC_SOP_EOP_PARITY)), |
| /*10*/ FLAG_ENTRY0("RxDmaFlagUncErr", RXES(DMA_FLAG_UNC)), |
| /*11*/ FLAG_ENTRY0("RxDmaFlagCorErr", RXES(DMA_FLAG_COR)), |
| /*12*/ FLAG_ENTRY0("RxRcvFsmEncodingErr", RXES(RCV_FSM_ENCODING)), |
| /*13*/ FLAG_ENTRY0("RxRbufFreeListUncErr", RXES(RBUF_FREE_LIST_UNC)), |
| /*14*/ FLAG_ENTRY0("RxRbufFreeListCorErr", RXES(RBUF_FREE_LIST_COR)), |
| /*15*/ FLAG_ENTRY0("RxRbufLookupDesRegUncErr", RXES(RBUF_LOOKUP_DES_REG_UNC)), |
| /*16*/ FLAG_ENTRY0("RxRbufLookupDesRegUncCorErr", |
| RXES(RBUF_LOOKUP_DES_REG_UNC_COR)), |
| /*17*/ FLAG_ENTRY0("RxRbufLookupDesUncErr", RXES(RBUF_LOOKUP_DES_UNC)), |
| /*18*/ FLAG_ENTRY0("RxRbufLookupDesCorErr", RXES(RBUF_LOOKUP_DES_COR)), |
| /*19*/ FLAG_ENTRY0("RxRbufBlockListReadUncErr", |
| RXES(RBUF_BLOCK_LIST_READ_UNC)), |
| /*20*/ FLAG_ENTRY0("RxRbufBlockListReadCorErr", |
| RXES(RBUF_BLOCK_LIST_READ_COR)), |
| /*21*/ FLAG_ENTRY0("RxRbufCsrQHeadBufNumParityErr", |
| RXES(RBUF_CSR_QHEAD_BUF_NUM_PARITY)), |
| /*22*/ FLAG_ENTRY0("RxRbufCsrQEntCntParityErr", |
| RXES(RBUF_CSR_QENT_CNT_PARITY)), |
| /*23*/ FLAG_ENTRY0("RxRbufCsrQNextBufParityErr", |
| RXES(RBUF_CSR_QNEXT_BUF_PARITY)), |
| /*24*/ FLAG_ENTRY0("RxRbufCsrQVldBitParityErr", |
| RXES(RBUF_CSR_QVLD_BIT_PARITY)), |
| /*25*/ FLAG_ENTRY0("RxRbufCsrQHdPtrParityErr", RXES(RBUF_CSR_QHD_PTR_PARITY)), |
| /*26*/ FLAG_ENTRY0("RxRbufCsrQTlPtrParityErr", RXES(RBUF_CSR_QTL_PTR_PARITY)), |
| /*27*/ FLAG_ENTRY0("RxRbufCsrQNumOfPktParityErr", |
| RXES(RBUF_CSR_QNUM_OF_PKT_PARITY)), |
| /*28*/ FLAG_ENTRY0("RxRbufCsrQEOPDWParityErr", RXES(RBUF_CSR_QEOPDW_PARITY)), |
| /*29*/ FLAG_ENTRY0("RxRbufCtxIdParityErr", RXES(RBUF_CTX_ID_PARITY)), |
| /*30*/ FLAG_ENTRY0("RxRBufBadLookupErr", RXES(RBUF_BAD_LOOKUP)), |
| /*31*/ FLAG_ENTRY0("RxRbufFullErr", RXES(RBUF_FULL)), |
| /*32*/ FLAG_ENTRY0("RxRbufEmptyErr", RXES(RBUF_EMPTY)), |
| /*33*/ FLAG_ENTRY0("RxRbufFlRdAddrParityErr", RXES(RBUF_FL_RD_ADDR_PARITY)), |
| /*34*/ FLAG_ENTRY0("RxRbufFlWrAddrParityErr", RXES(RBUF_FL_WR_ADDR_PARITY)), |
| /*35*/ FLAG_ENTRY0("RxRbufFlInitdoneParityErr", |
| RXES(RBUF_FL_INITDONE_PARITY)), |
| /*36*/ FLAG_ENTRY0("RxRbufFlInitWrAddrParityErr", |
| RXES(RBUF_FL_INIT_WR_ADDR_PARITY)), |
| /*37*/ FLAG_ENTRY0("RxRbufNextFreeBufUncErr", RXES(RBUF_NEXT_FREE_BUF_UNC)), |
| /*38*/ FLAG_ENTRY0("RxRbufNextFreeBufCorErr", RXES(RBUF_NEXT_FREE_BUF_COR)), |
| /*39*/ FLAG_ENTRY0("RxLookupDesPart1UncErr", RXES(LOOKUP_DES_PART1_UNC)), |
| /*40*/ FLAG_ENTRY0("RxLookupDesPart1UncCorErr", |
| RXES(LOOKUP_DES_PART1_UNC_COR)), |
| /*41*/ FLAG_ENTRY0("RxLookupDesPart2ParityErr", |
| RXES(LOOKUP_DES_PART2_PARITY)), |
| /*42*/ FLAG_ENTRY0("RxLookupRcvArrayUncErr", RXES(LOOKUP_RCV_ARRAY_UNC)), |
| /*43*/ FLAG_ENTRY0("RxLookupRcvArrayCorErr", RXES(LOOKUP_RCV_ARRAY_COR)), |
| /*44*/ FLAG_ENTRY0("RxLookupCsrParityErr", RXES(LOOKUP_CSR_PARITY)), |
| /*45*/ FLAG_ENTRY0("RxHqIntrCsrParityErr", RXES(HQ_INTR_CSR_PARITY)), |
| /*46*/ FLAG_ENTRY0("RxHqIntrFsmErr", RXES(HQ_INTR_FSM)), |
| /*47*/ FLAG_ENTRY0("RxRbufDescPart1UncErr", RXES(RBUF_DESC_PART1_UNC)), |
| /*48*/ FLAG_ENTRY0("RxRbufDescPart1CorErr", RXES(RBUF_DESC_PART1_COR)), |
| /*49*/ FLAG_ENTRY0("RxRbufDescPart2UncErr", RXES(RBUF_DESC_PART2_UNC)), |
| /*50*/ FLAG_ENTRY0("RxRbufDescPart2CorErr", RXES(RBUF_DESC_PART2_COR)), |
| /*51*/ FLAG_ENTRY0("RxDmaHdrFifoRdUncErr", RXES(DMA_HDR_FIFO_RD_UNC)), |
| /*52*/ FLAG_ENTRY0("RxDmaHdrFifoRdCorErr", RXES(DMA_HDR_FIFO_RD_COR)), |
| /*53*/ FLAG_ENTRY0("RxDmaDataFifoRdUncErr", RXES(DMA_DATA_FIFO_RD_UNC)), |
| /*54*/ FLAG_ENTRY0("RxDmaDataFifoRdCorErr", RXES(DMA_DATA_FIFO_RD_COR)), |
| /*55*/ FLAG_ENTRY0("RxRbufDataUncErr", RXES(RBUF_DATA_UNC)), |
| /*56*/ FLAG_ENTRY0("RxRbufDataCorErr", RXES(RBUF_DATA_COR)), |
| /*57*/ FLAG_ENTRY0("RxDmaCsrParityErr", RXES(DMA_CSR_PARITY)), |
| /*58*/ FLAG_ENTRY0("RxDmaEqFsmEncodingErr", RXES(DMA_EQ_FSM_ENCODING)), |
| /*59*/ FLAG_ENTRY0("RxDmaDqFsmEncodingErr", RXES(DMA_DQ_FSM_ENCODING)), |
| /*60*/ FLAG_ENTRY0("RxDmaCsrUncErr", RXES(DMA_CSR_UNC)), |
| /*61*/ FLAG_ENTRY0("RxCsrReadBadAddrErr", RXES(CSR_READ_BAD_ADDR)), |
| /*62*/ FLAG_ENTRY0("RxCsrWriteBadAddrErr", RXES(CSR_WRITE_BAD_ADDR)), |
| /*63*/ FLAG_ENTRY0("RxCsrParityErr", RXES(CSR_PARITY)) |
| }; |
| |
| /* RXE errors that will trigger an SPC freeze */ |
| #define ALL_RXE_FREEZE_ERR \ |
| (RCV_ERR_STATUS_RX_RCV_QP_MAP_TABLE_UNC_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RCV_CSR_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_DMA_FLAG_UNC_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RCV_FSM_ENCODING_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_FREE_LIST_UNC_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_LOOKUP_DES_REG_UNC_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_LOOKUP_DES_REG_UNC_COR_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_LOOKUP_DES_UNC_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_BLOCK_LIST_READ_UNC_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_CSR_QHEAD_BUF_NUM_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_CSR_QENT_CNT_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_CSR_QNEXT_BUF_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_CSR_QVLD_BIT_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_CSR_QHD_PTR_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_CSR_QTL_PTR_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_CSR_QNUM_OF_PKT_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_CSR_QEOPDW_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_CTX_ID_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_BAD_LOOKUP_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_FULL_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_EMPTY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_FL_RD_ADDR_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_FL_WR_ADDR_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_FL_INITDONE_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_FL_INIT_WR_ADDR_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_NEXT_FREE_BUF_UNC_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_LOOKUP_DES_PART1_UNC_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_LOOKUP_DES_PART1_UNC_COR_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_LOOKUP_DES_PART2_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_LOOKUP_RCV_ARRAY_UNC_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_LOOKUP_CSR_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_HQ_INTR_CSR_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_HQ_INTR_FSM_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_DESC_PART1_UNC_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_DESC_PART1_COR_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_DESC_PART2_UNC_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_DMA_HDR_FIFO_RD_UNC_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_DMA_DATA_FIFO_RD_UNC_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_RBUF_DATA_UNC_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_DMA_CSR_PARITY_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_DMA_EQ_FSM_ENCODING_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_DMA_DQ_FSM_ENCODING_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_DMA_CSR_UNC_ERR_SMASK \ |
| | RCV_ERR_STATUS_RX_CSR_PARITY_ERR_SMASK) |
| |
| #define RXE_FREEZE_ABORT_MASK \ |
| (RCV_ERR_STATUS_RX_DMA_CSR_UNC_ERR_SMASK | \ |
| RCV_ERR_STATUS_RX_DMA_HDR_FIFO_RD_UNC_ERR_SMASK | \ |
| RCV_ERR_STATUS_RX_DMA_DATA_FIFO_RD_UNC_ERR_SMASK) |
| |
| /* |
| * DCC Error Flags |
| */ |
| #define DCCE(name) DCC_ERR_FLG_##name##_SMASK |
| static struct flag_table dcc_err_flags[] = { |
| FLAG_ENTRY0("bad_l2_err", DCCE(BAD_L2_ERR)), |
| FLAG_ENTRY0("bad_sc_err", DCCE(BAD_SC_ERR)), |
| FLAG_ENTRY0("bad_mid_tail_err", DCCE(BAD_MID_TAIL_ERR)), |
| FLAG_ENTRY0("bad_preemption_err", DCCE(BAD_PREEMPTION_ERR)), |
| FLAG_ENTRY0("preemption_err", DCCE(PREEMPTION_ERR)), |
| FLAG_ENTRY0("preemptionvl15_err", DCCE(PREEMPTIONVL15_ERR)), |
| FLAG_ENTRY0("bad_vl_marker_err", DCCE(BAD_VL_MARKER_ERR)), |
| FLAG_ENTRY0("bad_dlid_target_err", DCCE(BAD_DLID_TARGET_ERR)), |
| FLAG_ENTRY0("bad_lver_err", DCCE(BAD_LVER_ERR)), |
| FLAG_ENTRY0("uncorrectable_err", DCCE(UNCORRECTABLE_ERR)), |
| FLAG_ENTRY0("bad_crdt_ack_err", DCCE(BAD_CRDT_ACK_ERR)), |
| FLAG_ENTRY0("unsup_pkt_type", DCCE(UNSUP_PKT_TYPE)), |
| FLAG_ENTRY0("bad_ctrl_flit_err", DCCE(BAD_CTRL_FLIT_ERR)), |
| FLAG_ENTRY0("event_cntr_parity_err", DCCE(EVENT_CNTR_PARITY_ERR)), |
| FLAG_ENTRY0("event_cntr_rollover_err", DCCE(EVENT_CNTR_ROLLOVER_ERR)), |
| FLAG_ENTRY0("link_err", DCCE(LINK_ERR)), |
| FLAG_ENTRY0("misc_cntr_rollover_err", DCCE(MISC_CNTR_ROLLOVER_ERR)), |
| FLAG_ENTRY0("bad_ctrl_dist_err", DCCE(BAD_CTRL_DIST_ERR)), |
| FLAG_ENTRY0("bad_tail_dist_err", DCCE(BAD_TAIL_DIST_ERR)), |
| FLAG_ENTRY0("bad_head_dist_err", DCCE(BAD_HEAD_DIST_ERR)), |
| FLAG_ENTRY0("nonvl15_state_err", DCCE(NONVL15_STATE_ERR)), |
| FLAG_ENTRY0("vl15_multi_err", DCCE(VL15_MULTI_ERR)), |
| FLAG_ENTRY0("bad_pkt_length_err", DCCE(BAD_PKT_LENGTH_ERR)), |
| FLAG_ENTRY0("unsup_vl_err", DCCE(UNSUP_VL_ERR)), |
| FLAG_ENTRY0("perm_nvl15_err", DCCE(PERM_NVL15_ERR)), |
| FLAG_ENTRY0("slid_zero_err", DCCE(SLID_ZERO_ERR)), |
| FLAG_ENTRY0("dlid_zero_err", DCCE(DLID_ZERO_ERR)), |
| FLAG_ENTRY0("length_mtu_err", DCCE(LENGTH_MTU_ERR)), |
| FLAG_ENTRY0("rx_early_drop_err", DCCE(RX_EARLY_DROP_ERR)), |
| FLAG_ENTRY0("late_short_err", DCCE(LATE_SHORT_ERR)), |
| FLAG_ENTRY0("late_long_err", DCCE(LATE_LONG_ERR)), |
| FLAG_ENTRY0("late_ebp_err", DCCE(LATE_EBP_ERR)), |
| FLAG_ENTRY0("fpe_tx_fifo_ovflw_err", DCCE(FPE_TX_FIFO_OVFLW_ERR)), |
| FLAG_ENTRY0("fpe_tx_fifo_unflw_err", DCCE(FPE_TX_FIFO_UNFLW_ERR)), |
| FLAG_ENTRY0("csr_access_blocked_host", DCCE(CSR_ACCESS_BLOCKED_HOST)), |
| FLAG_ENTRY0("csr_access_blocked_uc", DCCE(CSR_ACCESS_BLOCKED_UC)), |
| FLAG_ENTRY0("tx_ctrl_parity_err", DCCE(TX_CTRL_PARITY_ERR)), |
| FLAG_ENTRY0("tx_ctrl_parity_mbe_err", DCCE(TX_CTRL_PARITY_MBE_ERR)), |
| FLAG_ENTRY0("tx_sc_parity_err", DCCE(TX_SC_PARITY_ERR)), |
| FLAG_ENTRY0("rx_ctrl_parity_mbe_err", DCCE(RX_CTRL_PARITY_MBE_ERR)), |
| FLAG_ENTRY0("csr_parity_err", DCCE(CSR_PARITY_ERR)), |
| FLAG_ENTRY0("csr_inval_addr", DCCE(CSR_INVAL_ADDR)), |
| FLAG_ENTRY0("tx_byte_shft_parity_err", DCCE(TX_BYTE_SHFT_PARITY_ERR)), |
| FLAG_ENTRY0("rx_byte_shft_parity_err", DCCE(RX_BYTE_SHFT_PARITY_ERR)), |
| FLAG_ENTRY0("fmconfig_err", DCCE(FMCONFIG_ERR)), |
| FLAG_ENTRY0("rcvport_err", DCCE(RCVPORT_ERR)), |
| }; |
| |
| /* |
| * LCB error flags |
| */ |
| #define LCBE(name) DC_LCB_ERR_FLG_##name##_SMASK |
| static struct flag_table lcb_err_flags[] = { |
| /* 0*/ FLAG_ENTRY0("CSR_PARITY_ERR", LCBE(CSR_PARITY_ERR)), |
| /* 1*/ FLAG_ENTRY0("INVALID_CSR_ADDR", LCBE(INVALID_CSR_ADDR)), |
| /* 2*/ FLAG_ENTRY0("RST_FOR_FAILED_DESKEW", LCBE(RST_FOR_FAILED_DESKEW)), |
| /* 3*/ FLAG_ENTRY0("ALL_LNS_FAILED_REINIT_TEST", |
| LCBE(ALL_LNS_FAILED_REINIT_TEST)), |
| /* 4*/ FLAG_ENTRY0("LOST_REINIT_STALL_OR_TOS", LCBE(LOST_REINIT_STALL_OR_TOS)), |
| /* 5*/ FLAG_ENTRY0("TX_LESS_THAN_FOUR_LNS", LCBE(TX_LESS_THAN_FOUR_LNS)), |
| /* 6*/ FLAG_ENTRY0("RX_LESS_THAN_FOUR_LNS", LCBE(RX_LESS_THAN_FOUR_LNS)), |
| /* 7*/ FLAG_ENTRY0("SEQ_CRC_ERR", LCBE(SEQ_CRC_ERR)), |
| /* 8*/ FLAG_ENTRY0("REINIT_FROM_PEER", LCBE(REINIT_FROM_PEER)), |
| /* 9*/ FLAG_ENTRY0("REINIT_FOR_LN_DEGRADE", LCBE(REINIT_FOR_LN_DEGRADE)), |
| /*10*/ FLAG_ENTRY0("CRC_ERR_CNT_HIT_LIMIT", LCBE(CRC_ERR_CNT_HIT_LIMIT)), |
| /*11*/ FLAG_ENTRY0("RCLK_STOPPED", LCBE(RCLK_STOPPED)), |
| /*12*/ FLAG_ENTRY0("UNEXPECTED_REPLAY_MARKER", LCBE(UNEXPECTED_REPLAY_MARKER)), |
| /*13*/ FLAG_ENTRY0("UNEXPECTED_ROUND_TRIP_MARKER", |
| LCBE(UNEXPECTED_ROUND_TRIP_MARKER)), |
| /*14*/ FLAG_ENTRY0("ILLEGAL_NULL_LTP", LCBE(ILLEGAL_NULL_LTP)), |
| /*15*/ FLAG_ENTRY0("ILLEGAL_FLIT_ENCODING", LCBE(ILLEGAL_FLIT_ENCODING)), |
| /*16*/ FLAG_ENTRY0("FLIT_INPUT_BUF_OFLW", LCBE(FLIT_INPUT_BUF_OFLW)), |
| /*17*/ FLAG_ENTRY0("VL_ACK_INPUT_BUF_OFLW", LCBE(VL_ACK_INPUT_BUF_OFLW)), |
| /*18*/ FLAG_ENTRY0("VL_ACK_INPUT_PARITY_ERR", LCBE(VL_ACK_INPUT_PARITY_ERR)), |
| /*19*/ FLAG_ENTRY0("VL_ACK_INPUT_WRONG_CRC_MODE", |
| LCBE(VL_ACK_INPUT_WRONG_CRC_MODE)), |
| /*20*/ FLAG_ENTRY0("FLIT_INPUT_BUF_MBE", LCBE(FLIT_INPUT_BUF_MBE)), |
| /*21*/ FLAG_ENTRY0("FLIT_INPUT_BUF_SBE", LCBE(FLIT_INPUT_BUF_SBE)), |
| /*22*/ FLAG_ENTRY0("REPLAY_BUF_MBE", LCBE(REPLAY_BUF_MBE)), |
| /*23*/ FLAG_ENTRY0("REPLAY_BUF_SBE", LCBE(REPLAY_BUF_SBE)), |
| /*24*/ FLAG_ENTRY0("CREDIT_RETURN_FLIT_MBE", LCBE(CREDIT_RETURN_FLIT_MBE)), |
| /*25*/ FLAG_ENTRY0("RST_FOR_LINK_TIMEOUT", LCBE(RST_FOR_LINK_TIMEOUT)), |
| /*26*/ FLAG_ENTRY0("RST_FOR_INCOMPLT_RND_TRIP", |
| LCBE(RST_FOR_INCOMPLT_RND_TRIP)), |
| /*27*/ FLAG_ENTRY0("HOLD_REINIT", LCBE(HOLD_REINIT)), |
| /*28*/ FLAG_ENTRY0("NEG_EDGE_LINK_TRANSFER_ACTIVE", |
| LCBE(NEG_EDGE_LINK_TRANSFER_ACTIVE)), |
| /*29*/ FLAG_ENTRY0("REDUNDANT_FLIT_PARITY_ERR", |
| LCBE(REDUNDANT_FLIT_PARITY_ERR)) |
| }; |
| |
| /* |
| * DC8051 Error Flags |
| */ |
| #define D8E(name) DC_DC8051_ERR_FLG_##name##_SMASK |
| static struct flag_table dc8051_err_flags[] = { |
| FLAG_ENTRY0("SET_BY_8051", D8E(SET_BY_8051)), |
| FLAG_ENTRY0("LOST_8051_HEART_BEAT", D8E(LOST_8051_HEART_BEAT)), |
| FLAG_ENTRY0("CRAM_MBE", D8E(CRAM_MBE)), |
| FLAG_ENTRY0("CRAM_SBE", D8E(CRAM_SBE)), |
| FLAG_ENTRY0("DRAM_MBE", D8E(DRAM_MBE)), |
| FLAG_ENTRY0("DRAM_SBE", D8E(DRAM_SBE)), |
| FLAG_ENTRY0("IRAM_MBE", D8E(IRAM_MBE)), |
| FLAG_ENTRY0("IRAM_SBE", D8E(IRAM_SBE)), |
| FLAG_ENTRY0("UNMATCHED_SECURE_MSG_ACROSS_BCC_LANES", |
| D8E(UNMATCHED_SECURE_MSG_ACROSS_BCC_LANES)), |
| FLAG_ENTRY0("INVALID_CSR_ADDR", D8E(INVALID_CSR_ADDR)), |
| }; |
| |
| /* |
| * DC8051 Information Error flags |
| * |
| * Flags in DC8051_DBG_ERR_INFO_SET_BY_8051.ERROR field. |
| */ |
| static struct flag_table dc8051_info_err_flags[] = { |
| FLAG_ENTRY0("Spico ROM check failed", SPICO_ROM_FAILED), |
| FLAG_ENTRY0("Unknown frame received", UNKNOWN_FRAME), |
| FLAG_ENTRY0("Target BER not met", TARGET_BER_NOT_MET), |
| FLAG_ENTRY0("Serdes internal loopback failure", |
| FAILED_SERDES_INTERNAL_LOOPBACK), |
| FLAG_ENTRY0("Failed SerDes init", FAILED_SERDES_INIT), |
| FLAG_ENTRY0("Failed LNI(Polling)", FAILED_LNI_POLLING), |
| FLAG_ENTRY0("Failed LNI(Debounce)", FAILED_LNI_DEBOUNCE), |
| FLAG_ENTRY0("Failed LNI(EstbComm)", FAILED_LNI_ESTBCOMM), |
| FLAG_ENTRY0("Failed LNI(OptEq)", FAILED_LNI_OPTEQ), |
| FLAG_ENTRY0("Failed LNI(VerifyCap_1)", FAILED_LNI_VERIFY_CAP1), |
| FLAG_ENTRY0("Failed LNI(VerifyCap_2)", FAILED_LNI_VERIFY_CAP2), |
| FLAG_ENTRY0("Failed LNI(ConfigLT)", FAILED_LNI_CONFIGLT) |
| }; |
| |
| /* |
| * DC8051 Information Host Information flags |
| * |
| * Flags in DC8051_DBG_ERR_INFO_SET_BY_8051.HOST_MSG field. |
| */ |
| static struct flag_table dc8051_info_host_msg_flags[] = { |
| FLAG_ENTRY0("Host request done", 0x0001), |
| FLAG_ENTRY0("BC SMA message", 0x0002), |
| FLAG_ENTRY0("BC PWR_MGM message", 0x0004), |
| FLAG_ENTRY0("BC Unknown message (BCC)", 0x0008), |
| FLAG_ENTRY0("BC Unknown message (LCB)", 0x0010), |
| FLAG_ENTRY0("External device config request", 0x0020), |
| FLAG_ENTRY0("VerifyCap all frames received", 0x0040), |
| FLAG_ENTRY0("LinkUp achieved", 0x0080), |
| FLAG_ENTRY0("Link going down", 0x0100), |
| }; |
| |
| |
| static u32 encoded_size(u32 size); |
| static u32 chip_to_opa_lstate(struct hfi1_devdata *dd, u32 chip_lstate); |
| static int set_physical_link_state(struct hfi1_devdata *dd, u64 state); |
| static void read_vc_remote_phy(struct hfi1_devdata *dd, u8 *power_management, |
| u8 *continuous); |
| static void read_vc_remote_fabric(struct hfi1_devdata *dd, u8 *vau, u8 *z, |
| u8 *vcu, u16 *vl15buf, u8 *crc_sizes); |
| static void read_vc_remote_link_width(struct hfi1_devdata *dd, |
| u8 *remote_tx_rate, u16 *link_widths); |
| static void read_vc_local_link_width(struct hfi1_devdata *dd, u8 *misc_bits, |
| u8 *flag_bits, u16 *link_widths); |
| static void read_remote_device_id(struct hfi1_devdata *dd, u16 *device_id, |
| u8 *device_rev); |
| static void read_mgmt_allowed(struct hfi1_devdata *dd, u8 *mgmt_allowed); |
| static void read_local_lni(struct hfi1_devdata *dd, u8 *enable_lane_rx); |
| static int read_tx_settings(struct hfi1_devdata *dd, u8 *enable_lane_tx, |
| u8 *tx_polarity_inversion, |
| u8 *rx_polarity_inversion, u8 *max_rate); |
| static void handle_sdma_eng_err(struct hfi1_devdata *dd, |
| unsigned int context, u64 err_status); |
| static void handle_qsfp_int(struct hfi1_devdata *dd, u32 source, u64 reg); |
| static void handle_dcc_err(struct hfi1_devdata *dd, |
| unsigned int context, u64 err_status); |
| static void handle_lcb_err(struct hfi1_devdata *dd, |
| unsigned int context, u64 err_status); |
| static void handle_8051_interrupt(struct hfi1_devdata *dd, u32 unused, u64 reg); |
| static void handle_cce_err(struct hfi1_devdata *dd, u32 unused, u64 reg); |
| static void handle_rxe_err(struct hfi1_devdata *dd, u32 unused, u64 reg); |
| static void handle_misc_err(struct hfi1_devdata *dd, u32 unused, u64 reg); |
| static void handle_pio_err(struct hfi1_devdata *dd, u32 unused, u64 reg); |
| static void handle_sdma_err(struct hfi1_devdata *dd, u32 unused, u64 reg); |
| static void handle_egress_err(struct hfi1_devdata *dd, u32 unused, u64 reg); |
| static void handle_txe_err(struct hfi1_devdata *dd, u32 unused, u64 reg); |
| static void set_partition_keys(struct hfi1_pportdata *); |
| static const char *link_state_name(u32 state); |
| static const char *link_state_reason_name(struct hfi1_pportdata *ppd, |
| u32 state); |
| static int do_8051_command(struct hfi1_devdata *dd, u32 type, u64 in_data, |
| u64 *out_data); |
| static int read_idle_sma(struct hfi1_devdata *dd, u64 *data); |
| static int thermal_init(struct hfi1_devdata *dd); |
| |
| static int wait_logical_linkstate(struct hfi1_pportdata *ppd, u32 state, |
| int msecs); |
| static void read_planned_down_reason_code(struct hfi1_devdata *dd, u8 *pdrrc); |
| static void handle_temp_err(struct hfi1_devdata *); |
| static void dc_shutdown(struct hfi1_devdata *); |
| static void dc_start(struct hfi1_devdata *); |
| |
| /* |
| * Error interrupt table entry. This is used as input to the interrupt |
| * "clear down" routine used for all second tier error interrupt register. |
| * Second tier interrupt registers have a single bit representing them |
| * in the top-level CceIntStatus. |
| */ |
| struct err_reg_info { |
| u32 status; /* status CSR offset */ |
| u32 clear; /* clear CSR offset */ |
| u32 mask; /* mask CSR offset */ |
| void (*handler)(struct hfi1_devdata *dd, u32 source, u64 reg); |
| const char *desc; |
| }; |
| |
| #define NUM_MISC_ERRS (IS_GENERAL_ERR_END - IS_GENERAL_ERR_START) |
| #define NUM_DC_ERRS (IS_DC_END - IS_DC_START) |
| #define NUM_VARIOUS (IS_VARIOUS_END - IS_VARIOUS_START) |
| |
| /* |
| * Helpers for building HFI and DC error interrupt table entries. Different |
| * helpers are needed because of inconsistent register names. |
| */ |
| #define EE(reg, handler, desc) \ |
| { reg##_STATUS, reg##_CLEAR, reg##_MASK, \ |
| handler, desc } |
| #define DC_EE1(reg, handler, desc) \ |
| { reg##_FLG, reg##_FLG_CLR, reg##_FLG_EN, handler, desc } |
| #define DC_EE2(reg, handler, desc) \ |
| { reg##_FLG, reg##_CLR, reg##_EN, handler, desc } |
| |
| /* |
| * Table of the "misc" grouping of error interrupts. Each entry refers to |
| * another register containing more information. |
| */ |
| static const struct err_reg_info misc_errs[NUM_MISC_ERRS] = { |
| /* 0*/ EE(CCE_ERR, handle_cce_err, "CceErr"), |
| /* 1*/ EE(RCV_ERR, handle_rxe_err, "RxeErr"), |
| /* 2*/ EE(MISC_ERR, handle_misc_err, "MiscErr"), |
| /* 3*/ { 0, 0, 0, NULL }, /* reserved */ |
| /* 4*/ EE(SEND_PIO_ERR, handle_pio_err, "PioErr"), |
| /* 5*/ EE(SEND_DMA_ERR, handle_sdma_err, "SDmaErr"), |
| /* 6*/ EE(SEND_EGRESS_ERR, handle_egress_err, "EgressErr"), |
| /* 7*/ EE(SEND_ERR, handle_txe_err, "TxeErr") |
| /* the rest are reserved */ |
| }; |
| |
| /* |
| * Index into the Various section of the interrupt sources |
| * corresponding to the Critical Temperature interrupt. |
| */ |
| #define TCRIT_INT_SOURCE 4 |
| |
| /* |
| * SDMA error interrupt entry - refers to another register containing more |
| * information. |
| */ |
| static const struct err_reg_info sdma_eng_err = |
| EE(SEND_DMA_ENG_ERR, handle_sdma_eng_err, "SDmaEngErr"); |
| |
| static const struct err_reg_info various_err[NUM_VARIOUS] = { |
| /* 0*/ { 0, 0, 0, NULL }, /* PbcInt */ |
| /* 1*/ { 0, 0, 0, NULL }, /* GpioAssertInt */ |
| /* 2*/ EE(ASIC_QSFP1, handle_qsfp_int, "QSFP1"), |
| /* 3*/ EE(ASIC_QSFP2, handle_qsfp_int, "QSFP2"), |
| /* 4*/ { 0, 0, 0, NULL }, /* TCritInt */ |
| /* rest are reserved */ |
| }; |
| |
| /* |
| * The DC encoding of mtu_cap for 10K MTU in the DCC_CFG_PORT_CONFIG |
| * register can not be derived from the MTU value because 10K is not |
| * a power of 2. Therefore, we need a constant. Everything else can |
| * be calculated. |
| */ |
| #define DCC_CFG_PORT_MTU_CAP_10240 7 |
| |
| /* |
| * Table of the DC grouping of error interrupts. Each entry refers to |
| * another register containing more information. |
| */ |
| static const struct err_reg_info dc_errs[NUM_DC_ERRS] = { |
| /* 0*/ DC_EE1(DCC_ERR, handle_dcc_err, "DCC Err"), |
| /* 1*/ DC_EE2(DC_LCB_ERR, handle_lcb_err, "LCB Err"), |
| /* 2*/ DC_EE2(DC_DC8051_ERR, handle_8051_interrupt, "DC8051 Interrupt"), |
| /* 3*/ /* dc_lbm_int - special, see is_dc_int() */ |
| /* the rest are reserved */ |
| }; |
| |
| struct cntr_entry { |
| /* |
| * counter name |
| */ |
| char *name; |
| |
| /* |
| * csr to read for name (if applicable) |
| */ |
| u64 csr; |
| |
| /* |
| * offset into dd or ppd to store the counter's value |
| */ |
| int offset; |
| |
| /* |
| * flags |
| */ |
| u8 flags; |
| |
| /* |
| * accessor for stat element, context either dd or ppd |
| */ |
| u64 (*rw_cntr)(const struct cntr_entry *, |
| void *context, |
| int vl, |
| int mode, |
| u64 data); |
| }; |
| |
| #define C_RCV_HDR_OVF_FIRST C_RCV_HDR_OVF_0 |
| #define C_RCV_HDR_OVF_LAST C_RCV_HDR_OVF_159 |
| |
| #define CNTR_ELEM(name, csr, offset, flags, accessor) \ |
| { \ |
| name, \ |
| csr, \ |
| offset, \ |
| flags, \ |
| accessor \ |
| } |
| |
| /* 32bit RXE */ |
| #define RXE32_PORT_CNTR_ELEM(name, counter, flags) \ |
| CNTR_ELEM(#name, \ |
| (counter * 8 + RCV_COUNTER_ARRAY32), \ |
| 0, flags | CNTR_32BIT, \ |
| port_access_u32_csr) |
| |
| #define RXE32_DEV_CNTR_ELEM(name, counter, flags) \ |
| CNTR_ELEM(#name, \ |
| (counter * 8 + RCV_COUNTER_ARRAY32), \ |
| 0, flags | CNTR_32BIT, \ |
| dev_access_u32_csr) |
| |
| /* 64bit RXE */ |
| #define RXE64_PORT_CNTR_ELEM(name, counter, flags) \ |
| CNTR_ELEM(#name, \ |
| (counter * 8 + RCV_COUNTER_ARRAY64), \ |
| 0, flags, \ |
| port_access_u64_csr) |
| |
| #define RXE64_DEV_CNTR_ELEM(name, counter, flags) \ |
| CNTR_ELEM(#name, \ |
| (counter * 8 + RCV_COUNTER_ARRAY64), \ |
| 0, flags, \ |
| dev_access_u64_csr) |
| |
| #define OVR_LBL(ctx) C_RCV_HDR_OVF_ ## ctx |
| #define OVR_ELM(ctx) \ |
| CNTR_ELEM("RcvHdrOvr" #ctx, \ |
| (RCV_HDR_OVFL_CNT + ctx*0x100), \ |
| 0, CNTR_NORMAL, port_access_u64_csr) |
| |
| /* 32bit TXE */ |
| #define TXE32_PORT_CNTR_ELEM(name, counter, flags) \ |
| CNTR_ELEM(#name, \ |
| (counter * 8 + SEND_COUNTER_ARRAY32), \ |
| 0, flags | CNTR_32BIT, \ |
| port_access_u32_csr) |
| |
| /* 64bit TXE */ |
| #define TXE64_PORT_CNTR_ELEM(name, counter, flags) \ |
| CNTR_ELEM(#name, \ |
| (counter * 8 + SEND_COUNTER_ARRAY64), \ |
| 0, flags, \ |
| port_access_u64_csr) |
| |
| # define TX64_DEV_CNTR_ELEM(name, counter, flags) \ |
| CNTR_ELEM(#name,\ |
| counter * 8 + SEND_COUNTER_ARRAY64, \ |
| 0, \ |
| flags, \ |
| dev_access_u64_csr) |
| |
| /* CCE */ |
| #define CCE_PERF_DEV_CNTR_ELEM(name, counter, flags) \ |
| CNTR_ELEM(#name, \ |
| (counter * 8 + CCE_COUNTER_ARRAY32), \ |
| 0, flags | CNTR_32BIT, \ |
| dev_access_u32_csr) |
| |
| #define CCE_INT_DEV_CNTR_ELEM(name, counter, flags) \ |
| CNTR_ELEM(#name, \ |
| (counter * 8 + CCE_INT_COUNTER_ARRAY32), \ |
| 0, flags | CNTR_32BIT, \ |
| dev_access_u32_csr) |
| |
| /* DC */ |
| #define DC_PERF_CNTR(name, counter, flags) \ |
| CNTR_ELEM(#name, \ |
| counter, \ |
| 0, \ |
| flags, \ |
| dev_access_u64_csr) |
| |
| #define DC_PERF_CNTR_LCB(name, counter, flags) \ |
| CNTR_ELEM(#name, \ |
| counter, \ |
| 0, \ |
| flags, \ |
| dc_access_lcb_cntr) |
| |
| /* ibp counters */ |
| #define SW_IBP_CNTR(name, cntr) \ |
| CNTR_ELEM(#name, \ |
| 0, \ |
| 0, \ |
| CNTR_SYNTH, \ |
| access_ibp_##cntr) |
| |
| u64 read_csr(const struct hfi1_devdata *dd, u32 offset) |
| { |
| u64 val; |
| |
| if (dd->flags & HFI1_PRESENT) { |
| val = readq((void __iomem *)dd->kregbase + offset); |
| return val; |
| } |
| return -1; |
| } |
| |
| void write_csr(const struct hfi1_devdata *dd, u32 offset, u64 value) |
| { |
| if (dd->flags & HFI1_PRESENT) |
| writeq(value, (void __iomem *)dd->kregbase + offset); |
| } |
| |
| void __iomem *get_csr_addr( |
| struct hfi1_devdata *dd, |
| u32 offset) |
| { |
| return (void __iomem *)dd->kregbase + offset; |
| } |
| |
| static inline u64 read_write_csr(const struct hfi1_devdata *dd, u32 csr, |
| int mode, u64 value) |
| { |
| u64 ret; |
| |
| |
| if (mode == CNTR_MODE_R) { |
| ret = read_csr(dd, csr); |
| } else if (mode == CNTR_MODE_W) { |
| write_csr(dd, csr, value); |
| ret = value; |
| } else { |
| dd_dev_err(dd, "Invalid cntr register access mode"); |
| return 0; |
| } |
| |
| hfi1_cdbg(CNTR, "csr 0x%x val 0x%llx mode %d", csr, ret, mode); |
| return ret; |
| } |
| |
| /* Dev Access */ |
| static u64 dev_access_u32_csr(const struct cntr_entry *entry, |
| void *context, int vl, int mode, u64 data) |
| { |
| struct hfi1_devdata *dd = context; |
| |
| if (vl != CNTR_INVALID_VL) |
| return 0; |
| return read_write_csr(dd, entry->csr, mode, data); |
| } |
| |
| static u64 dev_access_u64_csr(const struct cntr_entry *entry, void *context, |
| int vl, int mode, u64 data) |
| { |
| struct hfi1_devdata *dd = context; |
| |
| u64 val = 0; |
| u64 csr = entry->csr; |
| |
| if (entry->flags & CNTR_VL) { |
| if (vl == CNTR_INVALID_VL) |
| return 0; |
| csr += 8 * vl; |
| } else { |
| if (vl != CNTR_INVALID_VL) |
| return 0; |
| } |
| |
| val = read_write_csr(dd, csr, mode, data); |
| return val; |
| } |
| |
| static u64 dc_access_lcb_cntr(const struct cntr_entry *entry, void *context, |
| int vl, int mode, u64 data) |
| { |
| struct hfi1_devdata *dd = context; |
| u32 csr = entry->csr; |
| int ret = 0; |
| |
| if (vl != CNTR_INVALID_VL) |
| return 0; |
| if (mode == CNTR_MODE_R) |
| ret = read_lcb_csr(dd, csr, &data); |
| else if (mode == CNTR_MODE_W) |
| ret = write_lcb_csr(dd, csr, data); |
| |
| if (ret) { |
| dd_dev_err(dd, "Could not acquire LCB for counter 0x%x", csr); |
| return 0; |
| } |
| |
| hfi1_cdbg(CNTR, "csr 0x%x val 0x%llx mode %d", csr, data, mode); |
| return data; |
| } |
| |
| /* Port Access */ |
| static u64 port_access_u32_csr(const struct cntr_entry *entry, void *context, |
| int vl, int mode, u64 data) |
| { |
| struct hfi1_pportdata *ppd = context; |
| |
| if (vl != CNTR_INVALID_VL) |
| return 0; |
| return read_write_csr(ppd->dd, entry->csr, mode, data); |
| } |
| |
| static u64 port_access_u64_csr(const struct cntr_entry *entry, |
| void *context, int vl, int mode, u64 data) |
| { |
| struct hfi1_pportdata *ppd = context; |
| u64 val; |
| u64 csr = entry->csr; |
| |
| if (entry->flags & CNTR_VL) { |
| if (vl == CNTR_INVALID_VL) |
| return 0; |
| csr += 8 * vl; |
| } else { |
| if (vl != CNTR_INVALID_VL) |
| return 0; |
| } |
| val = read_write_csr(ppd->dd, csr, mode, data); |
| return val; |
| } |
| |
| /* Software defined */ |
| static inline u64 read_write_sw(struct hfi1_devdata *dd, u64 *cntr, int mode, |
| u64 data) |
| { |
| u64 ret; |
| |
| if (mode == CNTR_MODE_R) { |
| ret = *cntr; |
| } else if (mode == CNTR_MODE_W) { |
| *cntr = data; |
| ret = data; |
| } else { |
| dd_dev_err(dd, "Invalid cntr sw access mode"); |
| return 0; |
| } |
| |
| hfi1_cdbg(CNTR, "val 0x%llx mode %d", ret, mode); |
| |
| return ret; |
| } |
| |
| static u64 access_sw_link_dn_cnt(const struct cntr_entry *entry, void *context, |
| int vl, int mode, u64 data) |
| { |
| struct hfi1_pportdata *ppd = context; |
| |
| if (vl != CNTR_INVALID_VL) |
| return 0; |
| return read_write_sw(ppd->dd, &ppd->link_downed, mode, data); |
| } |
| |
| static u64 access_sw_link_up_cnt(const struct cntr_entry *entry, void *context, |
| int vl, int mode, u64 data) |
| { |
| struct hfi1_pportdata *ppd = context; |
| |
| if (vl != CNTR_INVALID_VL) |
| return 0; |
| return read_write_sw(ppd->dd, &ppd->link_up, mode, data); |
| } |
| |
| static u64 access_sw_xmit_discards(const struct cntr_entry *entry, |
| void *context, int vl, int mode, u64 data) |
| { |
| struct hfi1_pportdata *ppd = context; |
| |
| if (vl != CNTR_INVALID_VL) |
| return 0; |
| |
| return read_write_sw(ppd->dd, &ppd->port_xmit_discards, mode, data); |
| } |
| |
| static u64 access_xmit_constraint_errs(const struct cntr_entry *entry, |
| void *context, int vl, int mode, u64 data) |
| { |
| struct hfi1_pportdata *ppd = context; |
| |
| if (vl != CNTR_INVALID_VL) |
| return 0; |
| |
| return read_write_sw(ppd->dd, &ppd->port_xmit_constraint_errors, |
| mode, data); |
| } |
| |
| static u64 access_rcv_constraint_errs(const struct cntr_entry *entry, |
| void *context, int vl, int mode, u64 data) |
| { |
| struct hfi1_pportdata *ppd = context; |
| |
| if (vl != CNTR_INVALID_VL) |
| return 0; |
| |
| return read_write_sw(ppd->dd, &ppd->port_rcv_constraint_errors, |
| mode, data); |
| } |
| |
| u64 get_all_cpu_total(u64 __percpu *cntr) |
| { |
| int cpu; |
| u64 counter = 0; |
| |
| for_each_possible_cpu(cpu) |
| counter += *per_cpu_ptr(cntr, cpu); |
| return counter; |
| } |
| |
| static u64 read_write_cpu(struct hfi1_devdata *dd, u64 *z_val, |
| u64 __percpu *cntr, |
| int vl, int mode, u64 data) |
| { |
| |
| u64 ret = 0; |
| |
| if (vl != CNTR_INVALID_VL) |
| return 0; |
| |
| if (mode == CNTR_MODE_R) { |
| ret = get_all_cpu_total(cntr) - *z_val; |
| } else if (mode == CNTR_MODE_W) { |
| /* A write can only zero the counter */ |
| if (data == 0) |
| *z_val = get_all_cpu_total(cntr); |
| else |
| dd_dev_err(dd, "Per CPU cntrs can only be zeroed"); |
| } else { |
| dd_dev_err(dd, "Invalid cntr sw cpu access mode"); |
| return 0; |
| } |
| |
| return ret; |
| } |
| |
| static u64 access_sw_cpu_intr(const struct cntr_entry *entry, |
| void *context, int vl, int mode, u64 data) |
| { |
| struct hfi1_devdata *dd = context; |
| |
| return read_write_cpu(dd, &dd->z_int_counter, dd->int_counter, vl, |
| mode, data); |
| } |
| |
| static u64 access_sw_cpu_rcv_limit(const struct cntr_entry *entry, |
| void *context, int vl, int mode, u64 data) |
| { |
| struct hfi1_devdata *dd = context; |
| |
| return read_write_cpu(dd, &dd->z_rcv_limit, dd->rcv_limit, vl, |
| mode, data); |
| } |
| |
| static u64 access_sw_pio_wait(const struct cntr_entry *entry, |
| void *context, int vl, int mode, u64 data) |
| { |
| struct hfi1_devdata *dd = context; |
| |
| return dd->verbs_dev.n_piowait; |
| } |
| |
| static u64 access_sw_vtx_wait(const struct cntr_entry *entry, |
| void *context, int vl, int mode, u64 data) |
| { |
| struct hfi1_devdata *dd = context; |
| |
| return dd->verbs_dev.n_txwait; |
| } |
| |
| static u64 access_sw_kmem_wait(const struct cntr_entry *entry, |
| void *context, int vl, int mode, u64 data) |
| { |
| struct hfi1_devdata *dd = context; |
| |
| return dd->verbs_dev.n_kmem_wait; |
| } |
| |
| static u64 access_sw_send_schedule(const struct cntr_entry *entry, |
| void *context, int vl, int mode, u64 data) |
| { |
| struct hfi1_devdata *dd = (struct hfi1_devdata *)context; |
| |
| return dd->verbs_dev.n_send_schedule; |
| } |
| |
| #define def_access_sw_cpu(cntr) \ |
| static u64 access_sw_cpu_##cntr(const struct cntr_entry *entry, \ |
| void *context, int vl, int mode, u64 data) \ |
| { \ |
| struct hfi1_pportdata *ppd = (struct hfi1_pportdata *)context; \ |
| return read_write_cpu(ppd->dd, &ppd->ibport_data.z_ ##cntr, \ |
| ppd->ibport_data.cntr, vl, \ |
| mode, data); \ |
| } |
| |
| def_access_sw_cpu(rc_acks); |
| def_access_sw_cpu(rc_qacks); |
| def_access_sw_cpu(rc_delayed_comp); |
| |
| #define def_access_ibp_counter(cntr) \ |
| static u64 access_ibp_##cntr(const struct cntr_entry *entry, \ |
| void *context, int vl, int mode, u64 data) \ |
| { \ |
| struct hfi1_pportdata *ppd = (struct hfi1_pportdata *)context; \ |
| \ |
| if (vl != CNTR_INVALID_VL) \ |
| return 0; \ |
| \ |
| return read_write_sw(ppd->dd, &ppd->ibport_data.n_ ##cntr, \ |
| mode, data); \ |
| } |
| |
| def_access_ibp_counter(loop_pkts); |
| def_access_ibp_counter(rc_resends); |
| def_access_ibp_counter(rnr_naks); |
| def_access_ibp_counter(other_naks); |
| def_access_ibp_counter(rc_timeouts); |
| def_access_ibp_counter(pkt_drops); |
| def_access_ibp_counter(dmawait); |
| def_access_ibp_counter(rc_seqnak); |
| def_access_ibp_counter(rc_dupreq); |
| def_access_ibp_counter(rdma_seq); |
| def_access_ibp_counter(unaligned); |
| def_access_ibp_counter(seq_naks); |
| |
| static struct cntr_entry dev_cntrs[DEV_CNTR_LAST] = { |
| [C_RCV_OVF] = RXE32_DEV_CNTR_ELEM(RcvOverflow, RCV_BUF_OVFL_CNT, CNTR_SYNTH), |
| [C_RX_TID_FULL] = RXE32_DEV_CNTR_ELEM(RxTIDFullEr, RCV_TID_FULL_ERR_CNT, |
| CNTR_NORMAL), |
| [C_RX_TID_INVALID] = RXE32_DEV_CNTR_ELEM(RxTIDInvalid, RCV_TID_VALID_ERR_CNT, |
| CNTR_NORMAL), |
| [C_RX_TID_FLGMS] = RXE32_DEV_CNTR_ELEM(RxTidFLGMs, |
| RCV_TID_FLOW_GEN_MISMATCH_CNT, |
| CNTR_NORMAL), |
| [C_RX_CTX_RHQS] = RXE32_DEV_CNTR_ELEM(RxCtxRHQS, RCV_CONTEXT_RHQ_STALL, |
| CNTR_NORMAL), |
| [C_RX_CTX_EGRS] = RXE32_DEV_CNTR_ELEM(RxCtxEgrS, RCV_CONTEXT_EGR_STALL, |
| CNTR_NORMAL), |
| [C_RCV_TID_FLSMS] = RXE32_DEV_CNTR_ELEM(RxTidFLSMs, |
| RCV_TID_FLOW_SEQ_MISMATCH_CNT, CNTR_NORMAL), |
| [C_CCE_PCI_CR_ST] = CCE_PERF_DEV_CNTR_ELEM(CcePciCrSt, |
| CCE_PCIE_POSTED_CRDT_STALL_CNT, CNTR_NORMAL), |
| [C_CCE_PCI_TR_ST] = CCE_PERF_DEV_CNTR_ELEM(CcePciTrSt, CCE_PCIE_TRGT_STALL_CNT, |
| CNTR_NORMAL), |
| [C_CCE_PIO_WR_ST] = CCE_PERF_DEV_CNTR_ELEM(CcePioWrSt, CCE_PIO_WR_STALL_CNT, |
| CNTR_NORMAL), |
| [C_CCE_ERR_INT] = CCE_INT_DEV_CNTR_ELEM(CceErrInt, CCE_ERR_INT_CNT, |
| CNTR_NORMAL), |
| [C_CCE_SDMA_INT] = CCE_INT_DEV_CNTR_ELEM(CceSdmaInt, CCE_SDMA_INT_CNT, |
| CNTR_NORMAL), |
| [C_CCE_MISC_INT] = CCE_INT_DEV_CNTR_ELEM(CceMiscInt, CCE_MISC_INT_CNT, |
| CNTR_NORMAL), |
| [C_CCE_RCV_AV_INT] = CCE_INT_DEV_CNTR_ELEM(CceRcvAvInt, CCE_RCV_AVAIL_INT_CNT, |
| CNTR_NORMAL), |
| [C_CCE_RCV_URG_INT] = CCE_INT_DEV_CNTR_ELEM(CceRcvUrgInt, |
| CCE_RCV_URGENT_INT_CNT, CNTR_NORMAL), |
| [C_CCE_SEND_CR_INT] = CCE_INT_DEV_CNTR_ELEM(CceSndCrInt, |
| CCE_SEND_CREDIT_INT_CNT, CNTR_NORMAL), |
| [C_DC_UNC_ERR] = DC_PERF_CNTR(DcUnctblErr, DCC_ERR_UNCORRECTABLE_CNT, |
| CNTR_SYNTH), |
| [C_DC_RCV_ERR] = DC_PERF_CNTR(DcRecvErr, DCC_ERR_PORTRCV_ERR_CNT, CNTR_SYNTH), |
| [C_DC_FM_CFG_ERR] = DC_PERF_CNTR(DcFmCfgErr, DCC_ERR_FMCONFIG_ERR_CNT, |
| CNTR_SYNTH), |
| [C_DC_RMT_PHY_ERR] = DC_PERF_CNTR(DcRmtPhyErr, DCC_ERR_RCVREMOTE_PHY_ERR_CNT, |
| CNTR_SYNTH), |
| [C_DC_DROPPED_PKT] = DC_PERF_CNTR(DcDroppedPkt, DCC_ERR_DROPPED_PKT_CNT, |
| CNTR_SYNTH), |
| [C_DC_MC_XMIT_PKTS] = DC_PERF_CNTR(DcMcXmitPkts, |
| DCC_PRF_PORT_XMIT_MULTICAST_CNT, CNTR_SYNTH), |
| [C_DC_MC_RCV_PKTS] = DC_PERF_CNTR(DcMcRcvPkts, |
| DCC_PRF_PORT_RCV_MULTICAST_PKT_CNT, |
| CNTR_SYNTH), |
| [C_DC_XMIT_CERR] = DC_PERF_CNTR(DcXmitCorr, |
| DCC_PRF_PORT_XMIT_CORRECTABLE_CNT, CNTR_SYNTH), |
| [C_DC_RCV_CERR] = DC_PERF_CNTR(DcRcvCorrCnt, DCC_PRF_PORT_RCV_CORRECTABLE_CNT, |
| CNTR_SYNTH), |
| [C_DC_RCV_FCC] = DC_PERF_CNTR(DcRxFCntl, DCC_PRF_RX_FLOW_CRTL_CNT, |
| CNTR_SYNTH), |
| [C_DC_XMIT_FCC] = DC_PERF_CNTR(DcXmitFCntl, DCC_PRF_TX_FLOW_CRTL_CNT, |
| CNTR_SYNTH), |
| [C_DC_XMIT_FLITS] = DC_PERF_CNTR(DcXmitFlits, DCC_PRF_PORT_XMIT_DATA_CNT, |
| CNTR_SYNTH), |
| [C_DC_RCV_FLITS] = DC_PERF_CNTR(DcRcvFlits, DCC_PRF_PORT_RCV_DATA_CNT, |
| CNTR_SYNTH), |
| [C_DC_XMIT_PKTS] = DC_PERF_CNTR(DcXmitPkts, DCC_PRF_PORT_XMIT_PKTS_CNT, |
| CNTR_SYNTH), |
| [C_DC_RCV_PKTS] = DC_PERF_CNTR(DcRcvPkts, DCC_PRF_PORT_RCV_PKTS_CNT, |
| CNTR_SYNTH), |
| [C_DC_RX_FLIT_VL] = DC_PERF_CNTR(DcRxFlitVl, DCC_PRF_PORT_VL_RCV_DATA_CNT, |
| CNTR_SYNTH | CNTR_VL), |
| [C_DC_RX_PKT_VL] = DC_PERF_CNTR(DcRxPktVl, DCC_PRF_PORT_VL_RCV_PKTS_CNT, |
| CNTR_SYNTH | CNTR_VL), |
| [C_DC_RCV_FCN] = DC_PERF_CNTR(DcRcvFcn, DCC_PRF_PORT_RCV_FECN_CNT, CNTR_SYNTH), |
| [C_DC_RCV_FCN_VL] = DC_PERF_CNTR(DcRcvFcnVl, DCC_PRF_PORT_VL_RCV_FECN_CNT, |
| CNTR_SYNTH | CNTR_VL), |
| [C_DC_RCV_BCN] = DC_PERF_CNTR(DcRcvBcn, DCC_PRF_PORT_RCV_BECN_CNT, CNTR_SYNTH), |
| [C_DC_RCV_BCN_VL] = DC_PERF_CNTR(DcRcvBcnVl, DCC_PRF_PORT_VL_RCV_BECN_CNT, |
| CNTR_SYNTH | CNTR_VL), |
| [C_DC_RCV_BBL] = DC_PERF_CNTR(DcRcvBbl, DCC_PRF_PORT_RCV_BUBBLE_CNT, |
| CNTR_SYNTH), |
| [C_DC_RCV_BBL_VL] = DC_PERF_CNTR(DcRcvBblVl, DCC_PRF_PORT_VL_RCV_BUBBLE_CNT, |
| CNTR_SYNTH | CNTR_VL), |
| [C_DC_MARK_FECN] = DC_PERF_CNTR(DcMarkFcn, DCC_PRF_PORT_MARK_FECN_CNT, |
| CNTR_SYNTH), |
| [C_DC_MARK_FECN_VL] = DC_PERF_CNTR(DcMarkFcnVl, DCC_PRF_PORT_VL_MARK_FECN_CNT, |
| CNTR_SYNTH | CNTR_VL), |
| [C_DC_TOTAL_CRC] = |
| DC_PERF_CNTR_LCB(DcTotCrc, DC_LCB_ERR_INFO_TOTAL_CRC_ERR, |
| CNTR_SYNTH), |
| [C_DC_CRC_LN0] = DC_PERF_CNTR_LCB(DcCrcLn0, DC_LCB_ERR_INFO_CRC_ERR_LN0, |
| CNTR_SYNTH), |
| [C_DC_CRC_LN1] = DC_PERF_CNTR_LCB(DcCrcLn1, DC_LCB_ERR_INFO_CRC_ERR_LN1, |
| CNTR_SYNTH), |
| [C_DC_CRC_LN2] = DC_PERF_CNTR_LCB(DcCrcLn2, DC_LCB_ERR_INFO_CRC_ERR_LN2, |
| CNTR_SYNTH), |
| [C_DC_CRC_LN3] = DC_PERF_CNTR_LCB(DcCrcLn3, DC_LCB_ERR_INFO_CRC_ERR_LN3, |
| CNTR_SYNTH), |
| [C_DC_CRC_MULT_LN] = |
| DC_PERF_CNTR_LCB(DcMultLn, DC_LCB_ERR_INFO_CRC_ERR_MULTI_LN, |
| CNTR_SYNTH), |
| [C_DC_TX_REPLAY] = DC_PERF_CNTR_LCB(DcTxReplay, DC_LCB_ERR_INFO_TX_REPLAY_CNT, |
| CNTR_SYNTH), |
| [C_DC_RX_REPLAY] = DC_PERF_CNTR_LCB(DcRxReplay, DC_LCB_ERR_INFO_RX_REPLAY_CNT, |
| CNTR_SYNTH), |
| [C_DC_SEQ_CRC_CNT] = |
| DC_PERF_CNTR_LCB(DcLinkSeqCrc, DC_LCB_ERR_INFO_SEQ_CRC_CNT, |
| CNTR_SYNTH), |
| [C_DC_ESC0_ONLY_CNT] = |
| DC_PERF_CNTR_LCB(DcEsc0, DC_LCB_ERR_INFO_ESCAPE_0_ONLY_CNT, |
| CNTR_SYNTH), |
| [C_DC_ESC0_PLUS1_CNT] = |
| DC_PERF_CNTR_LCB(DcEsc1, DC_LCB_ERR_INFO_ESCAPE_0_PLUS1_CNT, |
| CNTR_SYNTH), |
| [C_DC_ESC0_PLUS2_CNT] = |
| DC_PERF_CNTR_LCB(DcEsc0Plus2, DC_LCB_ERR_INFO_ESCAPE_0_PLUS2_CNT, |
| CNTR_SYNTH), |
| [C_DC_REINIT_FROM_PEER_CNT] = |
| DC_PERF_CNTR_LCB(DcReinitPeer, DC_LCB_ERR_INFO_REINIT_FROM_PEER_CNT, |
| CNTR_SYNTH), |
| [C_DC_SBE_CNT] = DC_PERF_CNTR_LCB(DcSbe, DC_LCB_ERR_INFO_SBE_CNT, |
| CNTR_SYNTH), |
| [C_DC_MISC_FLG_CNT] = |
| DC_PERF_CNTR_LCB(DcMiscFlg, DC_LCB_ERR_INFO_MISC_FLG_CNT, |
| CNTR_SYNTH), |
| [C_DC_PRF_GOOD_LTP_CNT] = |
| DC_PERF_CNTR_LCB(DcGoodLTP, DC_LCB_PRF_GOOD_LTP_CNT, CNTR_SYNTH), |
| [C_DC_PRF_ACCEPTED_LTP_CNT] = |
| DC_PERF_CNTR_LCB(DcAccLTP, DC_LCB_PRF_ACCEPTED_LTP_CNT, |
| CNTR_SYNTH), |
| [C_DC_PRF_RX_FLIT_CNT] = |
| DC_PERF_CNTR_LCB(DcPrfRxFlit, DC_LCB_PRF_RX_FLIT_CNT, CNTR_SYNTH), |
| [C_DC_PRF_TX_FLIT_CNT] = |
| DC_PERF_CNTR_LCB(DcPrfTxFlit, DC_LCB_PRF_TX_FLIT_CNT, CNTR_SYNTH), |
| [C_DC_PRF_CLK_CNTR] = |
| DC_PERF_CNTR_LCB(DcPrfClk, DC_LCB_PRF_CLK_CNTR, CNTR_SYNTH), |
| [C_DC_PG_DBG_FLIT_CRDTS_CNT] = |
| DC_PERF_CNTR_LCB(DcFltCrdts, DC_LCB_PG_DBG_FLIT_CRDTS_CNT, CNTR_SYNTH), |
| [C_DC_PG_STS_PAUSE_COMPLETE_CNT] = |
| DC_PERF_CNTR_LCB(DcPauseComp, DC_LCB_PG_STS_PAUSE_COMPLETE_CNT, |
| CNTR_SYNTH), |
| [C_DC_PG_STS_TX_SBE_CNT] = |
| DC_PERF_CNTR_LCB(DcStsTxSbe, DC_LCB_PG_STS_TX_SBE_CNT, CNTR_SYNTH), |
| [C_DC_PG_STS_TX_MBE_CNT] = |
| DC_PERF_CNTR_LCB(DcStsTxMbe, DC_LCB_PG_STS_TX_MBE_CNT, |
| CNTR_SYNTH), |
| [C_SW_CPU_INTR] = CNTR_ELEM("Intr", 0, 0, CNTR_NORMAL, |
| access_sw_cpu_intr), |
| [C_SW_CPU_RCV_LIM] = CNTR_ELEM("RcvLimit", 0, 0, CNTR_NORMAL, |
| access_sw_cpu_rcv_limit), |
| [C_SW_VTX_WAIT] = CNTR_ELEM("vTxWait", 0, 0, CNTR_NORMAL, |
| access_sw_vtx_wait), |
| [C_SW_PIO_WAIT] = CNTR_ELEM("PioWait", 0, 0, CNTR_NORMAL, |
| access_sw_pio_wait), |
| [C_SW_KMEM_WAIT] = CNTR_ELEM("KmemWait", 0, 0, CNTR_NORMAL, |
| access_sw_kmem_wait), |
| [C_SW_SEND_SCHED] = CNTR_ELEM("SendSched", 0, 0, CNTR_NORMAL, |
| access_sw_send_schedule), |
| }; |
| |
| static struct cntr_entry port_cntrs[PORT_CNTR_LAST] = { |
| [C_TX_UNSUP_VL] = TXE32_PORT_CNTR_ELEM(TxUnVLErr, SEND_UNSUP_VL_ERR_CNT, |
| CNTR_NORMAL), |
| [C_TX_INVAL_LEN] = TXE32_PORT_CNTR_ELEM(TxInvalLen, SEND_LEN_ERR_CNT, |
| CNTR_NORMAL), |
| [C_TX_MM_LEN_ERR] = TXE32_PORT_CNTR_ELEM(TxMMLenErr, SEND_MAX_MIN_LEN_ERR_CNT, |
| CNTR_NORMAL), |
| [C_TX_UNDERRUN] = TXE32_PORT_CNTR_ELEM(TxUnderrun, SEND_UNDERRUN_CNT, |
| CNTR_NORMAL), |
| [C_TX_FLOW_STALL] = TXE32_PORT_CNTR_ELEM(TxFlowStall, SEND_FLOW_STALL_CNT, |
| CNTR_NORMAL), |
| [C_TX_DROPPED] = TXE32_PORT_CNTR_ELEM(TxDropped, SEND_DROPPED_PKT_CNT, |
| CNTR_NORMAL), |
| [C_TX_HDR_ERR] = TXE32_PORT_CNTR_ELEM(TxHdrErr, SEND_HEADERS_ERR_CNT, |
| CNTR_NORMAL), |
| [C_TX_PKT] = TXE64_PORT_CNTR_ELEM(TxPkt, SEND_DATA_PKT_CNT, CNTR_NORMAL), |
| [C_TX_WORDS] = TXE64_PORT_CNTR_ELEM(TxWords, SEND_DWORD_CNT, CNTR_NORMAL), |
| [C_TX_WAIT] = TXE64_PORT_CNTR_ELEM(TxWait, SEND_WAIT_CNT, CNTR_SYNTH), |
| [C_TX_FLIT_VL] = TXE64_PORT_CNTR_ELEM(TxFlitVL, SEND_DATA_VL0_CNT, |
| CNTR_SYNTH | CNTR_VL), |
| [C_TX_PKT_VL] = TXE64_PORT_CNTR_ELEM(TxPktVL, SEND_DATA_PKT_VL0_CNT, |
| CNTR_SYNTH | CNTR_VL), |
| [C_TX_WAIT_VL] = TXE64_PORT_CNTR_ELEM(TxWaitVL, SEND_WAIT_VL0_CNT, |
| CNTR_SYNTH | CNTR_VL), |
| [C_RX_PKT] = RXE64_PORT_CNTR_ELEM(RxPkt, RCV_DATA_PKT_CNT, CNTR_NORMAL), |
| [C_RX_WORDS] = RXE64_PORT_CNTR_ELEM(RxWords, RCV_DWORD_CNT, CNTR_NORMAL), |
| [C_SW_LINK_DOWN] = CNTR_ELEM("SwLinkDown", 0, 0, CNTR_SYNTH | CNTR_32BIT, |
| access_sw_link_dn_cnt), |
| [C_SW_LINK_UP] = CNTR_ELEM("SwLinkUp", 0, 0, CNTR_SYNTH | CNTR_32BIT, |
| access_sw_link_up_cnt), |
| [C_SW_XMIT_DSCD] = CNTR_ELEM("XmitDscd", 0, 0, CNTR_SYNTH | CNTR_32BIT, |
| access_sw_xmit_discards), |
| [C_SW_XMIT_DSCD_VL] = CNTR_ELEM("XmitDscdVl", 0, 0, |
| CNTR_SYNTH | CNTR_32BIT | CNTR_VL, |
| access_sw_xmit_discards), |
| [C_SW_XMIT_CSTR_ERR] = CNTR_ELEM("XmitCstrErr", 0, 0, CNTR_SYNTH, |
| access_xmit_constraint_errs), |
| [C_SW_RCV_CSTR_ERR] = CNTR_ELEM("RcvCstrErr", 0, 0, CNTR_SYNTH, |
| access_rcv_constraint_errs), |
| [C_SW_IBP_LOOP_PKTS] = SW_IBP_CNTR(LoopPkts, loop_pkts), |
| [C_SW_IBP_RC_RESENDS] = SW_IBP_CNTR(RcResend, rc_resends), |
| [C_SW_IBP_RNR_NAKS] = SW_IBP_CNTR(RnrNak, rnr_naks), |
| [C_SW_IBP_OTHER_NAKS] = SW_IBP_CNTR(OtherNak, other_naks), |
| [C_SW_IBP_RC_TIMEOUTS] = SW_IBP_CNTR(RcTimeOut, rc_timeouts), |
| [C_SW_IBP_PKT_DROPS] = SW_IBP_CNTR(PktDrop, pkt_drops), |
| [C_SW_IBP_DMA_WAIT] = SW_IBP_CNTR(DmaWait, dmawait), |
| [C_SW_IBP_RC_SEQNAK] = SW_IBP_CNTR(RcSeqNak, rc_seqnak), |
| [C_SW_IBP_RC_DUPREQ] = SW_IBP_CNTR(RcDupRew, rc_dupreq), |
| [C_SW_IBP_RDMA_SEQ] = SW_IBP_CNTR(RdmaSeq, rdma_seq), |
| [C_SW_IBP_UNALIGNED] = SW_IBP_CNTR(Unaligned, unaligned), |
| [C_SW_IBP_SEQ_NAK] = SW_IBP_CNTR(SeqNak, seq_naks), |
| [C_SW_CPU_RC_ACKS] = CNTR_ELEM("RcAcks", 0, 0, CNTR_NORMAL, |
| access_sw_cpu_rc_acks), |
| [C_SW_CPU_RC_QACKS] = CNTR_ELEM("RcQacks", 0, 0, CNTR_NORMAL, |
| access_sw_cpu_rc_qacks), |
| [C_SW_CPU_RC_DELAYED_COMP] = CNTR_ELEM("RcDelayComp", 0, 0, CNTR_NORMAL, |
| access_sw_cpu_rc_delayed_comp), |
| [OVR_LBL(0)] = OVR_ELM(0), [OVR_LBL(1)] = OVR_ELM(1), |
| [OVR_LBL(2)] = OVR_ELM(2), [OVR_LBL(3)] = OVR_ELM(3), |
| [OVR_LBL(4)] = OVR_ELM(4), [OVR_LBL(5)] = OVR_ELM(5), |
| [OVR_LBL(6)] = OVR_ELM(6), [OVR_LBL(7)] = OVR_ELM(7), |
| [OVR_LBL(8)] = OVR_ELM(8), [OVR_LBL(9)] = OVR_ELM(9), |
| [OVR_LBL(10)] = OVR_ELM(10), [OVR_LBL(11)] = OVR_ELM(11), |
| [OVR_LBL(12)] = OVR_ELM(12), [OVR_LBL(13)] = OVR_ELM(13), |
| [OVR_LBL(14)] = OVR_ELM(14), [OVR_LBL(15)] = OVR_ELM(15), |
| [OVR_LBL(16)] = OVR_ELM(16), [OVR_LBL(17)] = OVR_ELM(17), |
| [OVR_LBL(18)] = OVR_ELM(18), [OVR_LBL(19)] = OVR_ELM(19), |
| [OVR_LBL(20)] = OVR_ELM(20), [OVR_LBL(21)] = OVR_ELM(21), |
| [OVR_LBL(22)] = OVR_ELM(22), [OVR_LBL(23)] = OVR_ELM(23), |
| [OVR_LBL(24)] = OVR_ELM(24), [OVR_LBL(25)] = OVR_ELM(25), |
| [OVR_LBL(26)] = OVR_ELM(26), [OVR_LBL(27)] = OVR_ELM(27), |
| [OVR_LBL(28)] = OVR_ELM(28), [OVR_LBL(29)] = OVR_ELM(29), |
| [OVR_LBL(30)] = OVR_ELM(30), [OVR_LBL(31)] = OVR_ELM(31), |
| [OVR_LBL(32)] = OVR_ELM(32), [OVR_LBL(33)] = OVR_ELM(33), |
| [OVR_LBL(34)] = OVR_ELM(34), [OVR_LBL(35)] = OVR_ELM(35), |
| [OVR_LBL(36)] = OVR_ELM(36), [OVR_LBL(37)] = OVR_ELM(37), |
| [OVR_LBL(38)] = OVR_ELM(38), [OVR_LBL(39)] = OVR_ELM(39), |
| [OVR_LBL(40)] = OVR_ELM(40), [OVR_LBL(41)] = OVR_ELM(41), |
| [OVR_LBL(42)] = OVR_ELM(42), [OVR_LBL(43)] = OVR_ELM(43), |
| [OVR_LBL(44)] = OVR_ELM(44), [OVR_LBL(45)] = OVR_ELM(45), |
| [OVR_LBL(46)] = OVR_ELM(46), [OVR_LBL(47)] = OVR_ELM(47), |
| [OVR_LBL(48)] = OVR_ELM(48), [OVR_LBL(49)] = OVR_ELM(49), |
| [OVR_LBL(50)] = OVR_ELM(50), [OVR_LBL(51)] = OVR_ELM(51), |
| [OVR_LBL(52)] = OVR_ELM(52), [OVR_LBL(53)] = OVR_ELM(53), |
| [OVR_LBL(54)] = OVR_ELM(54), [OVR_LBL(55)] = OVR_ELM(55), |
| [OVR_LBL(56)] = OVR_ELM(56), [OVR_LBL(57)] = OVR_ELM(57), |
| [OVR_LBL(58)] = OVR_ELM(58), [OVR_LBL(59)] = OVR_ELM(59), |
| [OVR_LBL(60)] = OVR_ELM(60), [OVR_LBL(61)] = OVR_ELM(61), |
| [OVR_LBL(62)] = OVR_ELM(62), [OVR_LBL(63)] = OVR_ELM(63), |
| [OVR_LBL(64)] = OVR_ELM(64), [OVR_LBL(65)] = OVR_ELM(65), |
| [OVR_LBL(66)] = OVR_ELM(66), [OVR_LBL(67)] = OVR_ELM(67), |
| [OVR_LBL(68)] = OVR_ELM(68), [OVR_LBL(69)] = OVR_ELM(69), |
| [OVR_LBL(70)] = OVR_ELM(70), [OVR_LBL(71)] = OVR_ELM(71), |
| [OVR_LBL(72)] = OVR_ELM(72), [OVR_LBL(73)] = OVR_ELM(73), |
| [OVR_LBL(74)] = OVR_ELM(74), [OVR_LBL(75)] = OVR_ELM(75), |
| [OVR_LBL(76)] = OVR_ELM(76), [OVR_LBL(77)] = OVR_ELM(77), |
| [OVR_LBL(78)] = OVR_ELM(78), [OVR_LBL(79)] = OVR_ELM(79), |
| [OVR_LBL(80)] = OVR_ELM(80), [OVR_LBL(81)] = OVR_ELM(81), |
| [OVR_LBL(82)] = OVR_ELM(82), [OVR_LBL(83)] = OVR_ELM(83), |
| [OVR_LBL(84)] = OVR_ELM(84), [OVR_LBL(85)] = OVR_ELM(85), |
| [OVR_LBL(86)] = OVR_ELM(86), [OVR_LBL(87)] = OVR_ELM(87), |
| [OVR_LBL(88)] = OVR_ELM(88), [OVR_LBL(89)] = OVR_ELM(89), |
| [OVR_LBL(90)] = OVR_ELM(90), [OVR_LBL(91)] = OVR_ELM(91), |
| [OVR_LBL(92)] = OVR_ELM(92), [OVR_LBL(93)] = OVR_ELM(93), |
| [OVR_LBL(94)] = OVR_ELM(94), [OVR_LBL(95)] = OVR_ELM(95), |
| [OVR_LBL(96)] = OVR_ELM(96), [OVR_LBL(97)] = OVR_ELM(97), |
| [OVR_LBL(98)] = OVR_ELM(98), [OVR_LBL(99)] = OVR_ELM(99), |
| [OVR_LBL(100)] = OVR_ELM(100), [OVR_LBL(101)] = OVR_ELM(101), |
| [OVR_LBL(102)] = OVR_ELM(102), [OVR_LBL(103)] = OVR_ELM(103), |
| [OVR_LBL(104)] = OVR_ELM(104), [OVR_LBL(105)] = OVR_ELM(105), |
| [OVR_LBL(106)] = OVR_ELM(106), [OVR_LBL(107)] = OVR_ELM(107), |
| [OVR_LBL(108)] = OVR_ELM(108), [OVR_LBL(109)] = OVR_ELM(109), |
| [OVR_LBL(110)] = OVR_ELM(110), [OVR_LBL(111)] = OVR_ELM(111), |
| [OVR_LBL(112)] = OVR_ELM(112), [OVR_LBL(113)] = OVR_ELM(113), |
| [OVR_LBL(114)] = OVR_ELM(114), [OVR_LBL(115)] = OVR_ELM(115), |
| [OVR_LBL(116)] = OVR_ELM(116), [OVR_LBL(117)] = OVR_ELM(117), |
| [OVR_LBL(118)] = OVR_ELM(118), [OVR_LBL(119)] = OVR_ELM(119), |
| [OVR_LBL(120)] = OVR_ELM(120), [OVR_LBL(121)] = OVR_ELM(121), |
| [OVR_LBL(122)] = OVR_ELM(122), [OVR_LBL(123)] = OVR_ELM(123), |
| [OVR_LBL(124)] = OVR_ELM(124), [OVR_LBL(125)] = OVR_ELM(125), |
| [OVR_LBL(126)] = OVR_ELM(126), [OVR_LBL(127)] = OVR_ELM(127), |
| [OVR_LBL(128)] = OVR_ELM(128), [OVR_LBL(129)] = OVR_ELM(129), |
| [OVR_LBL(130)] = OVR_ELM(130), [OVR_LBL(131)] = OVR_ELM(131), |
| [OVR_LBL(132)] = OVR_ELM(132), [OVR_LBL(133)] = OVR_ELM(133), |
| [OVR_LBL(134)] = OVR_ELM(134), [OVR_LBL(135)] = OVR_ELM(135), |
| [OVR_LBL(136)] = OVR_ELM(136), [OVR_LBL(137)] = OVR_ELM(137), |
| [OVR_LBL(138)] = OVR_ELM(138), [OVR_LBL(139)] = OVR_ELM(139), |
| [OVR_LBL(140)] = OVR_ELM(140), [OVR_LBL(141)] = OVR_ELM(141), |
| [OVR_LBL(142)] = OVR_ELM(142), [OVR_LBL(143)] = OVR_ELM(143), |
| [OVR_LBL(144)] = OVR_ELM(144), [OVR_LBL(145)] = OVR_ELM(145), |
| [OVR_LBL(146)] = OVR_ELM(146), [OVR_LBL(147)] = OVR_ELM(147), |
| [OVR_LBL(148)] = OVR_ELM(148), [OVR_LBL(149)] = OVR_ELM(149), |
| [OVR_LBL(150)] = OVR_ELM(150), [OVR_LBL(151)] = OVR_ELM(151), |
| [OVR_LBL(152)] = OVR_ELM(152), [OVR_LBL(153)] = OVR_ELM(153), |
| [OVR_LBL(154)] = OVR_ELM(154), [OVR_LBL(155)] = OVR_ELM(155), |
| [OVR_LBL(156)] = OVR_ELM(156), [OVR_LBL(157)] = OVR_ELM(157), |
| [OVR_LBL(158)] = OVR_ELM(158), [OVR_LBL(159)] = OVR_ELM(159), |
| }; |
| |
| /* ======================================================================== */ |
| |
| /* return true if this is chip revision revision a0 */ |
| int is_a0(struct hfi1_devdata *dd) |
| { |
| return ((dd->revision >> CCE_REVISION_CHIP_REV_MINOR_SHIFT) |
| & CCE_REVISION_CHIP_REV_MINOR_MASK) == 0; |
| } |
| |
| /* return true if this is chip revision revision a */ |
| int is_ax(struct hfi1_devdata *dd) |
| { |
| u8 chip_rev_minor = |
| dd->revision >> CCE_REVISION_CHIP_REV_MINOR_SHIFT |
| & CCE_REVISION_CHIP_REV_MINOR_MASK; |
| return (chip_rev_minor & 0xf0) == 0; |
| } |
| |
| /* return true if this is chip revision revision b */ |
| int is_bx(struct hfi1_devdata *dd) |
| { |
| u8 chip_rev_minor = |
| dd->revision >> CCE_REVISION_CHIP_REV_MINOR_SHIFT |
| & CCE_REVISION_CHIP_REV_MINOR_MASK; |
| return !!(chip_rev_minor & 0x10); |
| } |
| |
| /* |
| * Append string s to buffer buf. Arguments curp and len are the current |
| * position and remaining length, respectively. |
| * |
| * return 0 on success, 1 on out of room |
| */ |
| static int append_str(char *buf, char **curp, int *lenp, const char *s) |
| { |
| char *p = *curp; |
| int len = *lenp; |
| int result = 0; /* success */ |
| char c; |
| |
| /* add a comma, if first in the buffer */ |
| if (p != buf) { |
| if (len == 0) { |
| result = 1; /* out of room */ |
| goto done; |
| } |
| *p++ = ','; |
| len--; |
| } |
| |
| /* copy the string */ |
| while ((c = *s++) != 0) { |
| if (len == 0) { |
| result = 1; /* out of room */ |
| goto done; |
| } |
| *p++ = c; |
| len--; |
| } |
| |
| done: |
| /* write return values */ |
| *curp = p; |
| *lenp = len; |
| |
| return result; |
| } |
| |
| /* |
| * Using the given flag table, print a comma separated string into |
| * the buffer. End in '*' if the buffer is too short. |
| */ |
| static char *flag_string(char *buf, int buf_len, u64 flags, |
| struct flag_table *table, int table_size) |
| { |
| char extra[32]; |
| char *p = buf; |
| int len = buf_len; |
| int no_room = 0; |
| int i; |
| |
| /* make sure there is at least 2 so we can form "*" */ |
| if (len < 2) |
| return ""; |
| |
| len--; /* leave room for a nul */ |
| for (i = 0; i < table_size; i++) { |
| if (flags & table[i].flag) { |
| no_room = append_str(buf, &p, &len, table[i].str); |
| if (no_room) |
| break; |
| flags &= ~table[i].flag; |
| } |
| } |
| |
| /* any undocumented bits left? */ |
| if (!no_room && flags) { |
| snprintf(extra, sizeof(extra), "bits 0x%llx", flags); |
| no_room = append_str(buf, &p, &len, extra); |
| } |
| |
| /* add * if ran out of room */ |
| if (no_room) { |
| /* may need to back up to add space for a '*' */ |
| if (len == 0) |
| --p; |
| *p++ = '*'; |
| } |
| |
| /* add final nul - space already allocated above */ |
| *p = 0; |
| return buf; |
| } |
| |
| /* first 8 CCE error interrupt source names */ |
| static const char * const cce_misc_names[] = { |
| "CceErrInt", /* 0 */ |
| "RxeErrInt", /* 1 */ |
| "MiscErrInt", /* 2 */ |
| "Reserved3", /* 3 */ |
| "PioErrInt", /* 4 */ |
| "SDmaErrInt", /* 5 */ |
| "EgressErrInt", /* 6 */ |
| "TxeErrInt" /* 7 */ |
| }; |
| |
| /* |
| * Return the miscellaneous error interrupt name. |
| */ |
| static char *is_misc_err_name(char *buf, size_t bsize, unsigned int source) |
| { |
| if (source < ARRAY_SIZE(cce_misc_names)) |
| strncpy(buf, cce_misc_names[source], bsize); |
| else |
| snprintf(buf, |
| bsize, |
| "Reserved%u", |
| source + IS_GENERAL_ERR_START); |
| |
| return buf; |
| } |
| |
| /* |
| * Return the SDMA engine error interrupt name. |
| */ |
| static char *is_sdma_eng_err_name(char *buf, size_t bsize, unsigned int source) |
| { |
| snprintf(buf, bsize, "SDmaEngErrInt%u", source); |
| return buf; |
| } |
| |
| /* |
| * Return the send context error interrupt name. |
| */ |
| static char *is_sendctxt_err_name(char *buf, size_t bsize, unsigned int source) |
| { |
| snprintf(buf, bsize, "SendCtxtErrInt%u", source); |
| return buf; |
| } |
| |
| static const char * const various_names[] = { |
| "PbcInt", |
| "GpioAssertInt", |
| "Qsfp1Int", |
| "Qsfp2Int", |
| "TCritInt" |
| }; |
| |
| /* |
| * Return the various interrupt name. |
| */ |
| static char *is_various_name(char *buf, size_t bsize, unsigned int source) |
| { |
| if (source < ARRAY_SIZE(various_names)) |
| strncpy(buf, various_names[source], bsize); |
| else |
| snprintf(buf, bsize, "Reserved%u", source+IS_VARIOUS_START); |
| return buf; |
| } |
| |
| /* |
| * Return the DC interrupt name. |
| */ |
| static char *is_dc_name(char *buf, size_t bsize, unsigned int source) |
| { |
| static const char * const dc_int_names[] = { |
| "common", |
| "lcb", |
| "8051", |
| "lbm" /* local block merge */ |
| }; |
| |
| if (source < ARRAY_SIZE(dc_int_names)) |
| snprintf(buf, bsize, "dc_%s_int", dc_int_names[source]); |
| else |
| snprintf(buf, bsize, "DCInt%u", source); |
| return buf; |
| } |
| |
| static const char * const sdma_int_names[] = { |
| "SDmaInt", |
| "SdmaIdleInt", |
| "SdmaProgressInt", |
| }; |
| |
| /* |
| * Return the SDMA engine interrupt name. |
| */ |
| static char *is_sdma_eng_name(char *buf, size_t bsize, unsigned int source) |
| { |
| /* what interrupt */ |
| unsigned int what = source / TXE_NUM_SDMA_ENGINES; |
| /* which engine */ |
| unsigned int which = source % TXE_NUM_SDMA_ENGINES; |
| |
| if (likely(what < 3)) |
| snprintf(buf, bsize, "%s%u", sdma_int_names[what], which); |
| else |
| snprintf(buf, bsize, "Invalid SDMA interrupt %u", source); |
| return buf; |
| } |
| |
| /* |
| * Return the receive available interrupt name. |
| */ |
| static char *is_rcv_avail_name(char *buf, size_t bsize, unsigned int source) |
| { |
| snprintf(buf, bsize, "RcvAvailInt%u", source); |
| return buf; |
| } |
| |
| /* |
| * Return the receive urgent interrupt name. |
| */ |
| static char *is_rcv_urgent_name(char *buf, size_t bsize, unsigned int source) |
| { |
| snprintf(buf, bsize, "RcvUrgentInt%u", source); |
| return buf; |
| } |
| |
| /* |
| * Return the send credit interrupt name. |
| */ |
| static char *is_send_credit_name(char *buf, size_t bsize, unsigned int source) |
| { |
| snprintf(buf, bsize, "SendCreditInt%u", source); |
| return buf; |
| } |
| |
| /* |
| * Return the reserved interrupt name. |
| */ |
| static char *is_reserved_name(char *buf, size_t bsize, unsigned int source) |
| { |
| snprintf(buf, bsize, "Reserved%u", source + IS_RESERVED_START); |
| return buf; |
| } |
| |
| static char *cce_err_status_string(char *buf, int buf_len, u64 flags) |
| { |
| return flag_string(buf, buf_len, flags, |
| cce_err_status_flags, ARRAY_SIZE(cce_err_status_flags)); |
| } |
| |
| static char *rxe_err_status_string(char *buf, int buf_len, u64 flags) |
| { |
| return flag_string(buf, buf_len, flags, |
| rxe_err_status_flags, ARRAY_SIZE(rxe_err_status_flags)); |
| } |
| |
| static char *misc_err_status_string(char *buf, int buf_len, u64 flags) |
| { |
| return flag_string(buf, buf_len, flags, misc_err_status_flags, |
| ARRAY_SIZE(misc_err_status_flags)); |
| } |
| |
| static char *pio_err_status_string(char *buf, int buf_len, u64 flags) |
| { |
| return flag_string(buf, buf_len, flags, |
| pio_err_status_flags, ARRAY_SIZE(pio_err_status_flags)); |
| } |
| |
| static char *sdma_err_status_string(char *buf, int buf_len, u64 flags) |
| { |
| return flag_string(buf, buf_len, flags, |
| sdma_err_status_flags, |
| ARRAY_SIZE(sdma_err_status_flags)); |
| } |
| |
| static char *egress_err_status_string(char *buf, int buf_len, u64 flags) |
| { |
| return flag_string(buf, buf_len, flags, |
| egress_err_status_flags, ARRAY_SIZE(egress_err_status_flags)); |
| } |
| |
| static char *egress_err_info_string(char *buf, int buf_len, u64 flags) |
| { |
| return flag_string(buf, buf_len, flags, |
| egress_err_info_flags, ARRAY_SIZE(egress_err_info_flags)); |
| } |
| |
| static char *send_err_status_string(char *buf, int buf_len, u64 flags) |
| { |
| return flag_string(buf, buf_len, flags, |
| send_err_status_flags, |
| ARRAY_SIZE(send_err_status_flags)); |
| } |
| |
| static void handle_cce_err(struct hfi1_devdata *dd, u32 unused, u64 reg) |
| { |
| char buf[96]; |
| |
| /* |
| * For most these errors, there is nothing that can be done except |
| * report or record it. |
| */ |
| dd_dev_info(dd, "CCE Error: %s\n", |
| cce_err_status_string(buf, sizeof(buf), reg)); |
| |
| if ((reg & CCE_ERR_STATUS_CCE_CLI2_ASYNC_FIFO_PARITY_ERR_SMASK) |
| && is_a0(dd) |
| && (dd->icode != ICODE_FUNCTIONAL_SIMULATOR)) { |
| /* this error requires a manual drop into SPC freeze mode */ |
| /* then a fix up */ |
| start_freeze_handling(dd->pport, FREEZE_SELF); |
| } |
| } |
| |
| /* |
| * Check counters for receive errors that do not have an interrupt |
| * associated with them. |
| */ |
| #define RCVERR_CHECK_TIME 10 |
| static void update_rcverr_timer(unsigned long opaque) |
| { |
| struct hfi1_devdata *dd = (struct hfi1_devdata *)opaque; |
| struct hfi1_pportdata *ppd = dd->pport; |
| u32 cur_ovfl_cnt = read_dev_cntr(dd, C_RCV_OVF, CNTR_INVALID_VL); |
| |
| if (dd->rcv_ovfl_cnt < cur_ovfl_cnt && |
| ppd->port_error_action & OPA_PI_MASK_EX_BUFFER_OVERRUN) { |
| dd_dev_info(dd, "%s: PortErrorAction bounce\n", __func__); |
| set_link_down_reason(ppd, |
| OPA_LINKDOWN_REASON_EXCESSIVE_BUFFER_OVERRUN, 0, |
| OPA_LINKDOWN_REASON_EXCESSIVE_BUFFER_OVERRUN); |
| queue_work(ppd->hfi1_wq, &ppd->link_bounce_work); |
| } |
| dd->rcv_ovfl_cnt = (u32) cur_ovfl_cnt; |
| |
| mod_timer(&dd->rcverr_timer, jiffies + HZ * RCVERR_CHECK_TIME); |
| } |
| |
| static int init_rcverr(struct hfi1_devdata *dd) |
| { |
| setup_timer(&dd->rcverr_timer, update_rcverr_timer, (unsigned long)dd); |
| /* Assume the hardware counter has been reset */ |
| dd->rcv_ovfl_cnt = 0; |
| return mod_timer(&dd->rcverr_timer, jiffies + HZ * RCVERR_CHECK_TIME); |
| } |
| |
| static void free_rcverr(struct hfi1_devdata *dd) |
| { |
| if (dd->rcverr_timer.data) |
| del_timer_sync(&dd->rcverr_timer); |
| dd->rcverr_timer.data = 0; |
| } |
| |
| static void handle_rxe_err(struct hfi1_devdata *dd, u32 unused, u64 reg) |
| { |
| char buf[96]; |
| |
| dd_dev_info(dd, "Receive Error: %s\n", |
| rxe_err_status_string(buf, sizeof(buf), reg)); |
| |
| if (reg & ALL_RXE_FREEZE_ERR) { |
| int flags = 0; |
| |
| /* |
| * Freeze mode recovery is disabled for the errors |
| * in RXE_FREEZE_ABORT_MASK |
| */ |
| if (is_a0(dd) && (reg & RXE_FREEZE_ABORT_MASK)) |
| flags = FREEZE_ABORT; |
| |
| start_freeze_handling(dd->pport, flags); |
| } |
| } |
| |
| static void handle_misc_err(struct hfi1_devdata *dd, u32 unused, u64 reg) |
| { |
| char buf[96]; |
| |
| dd_dev_info(dd, "Misc Error: %s", |
| misc_err_status_string(buf, sizeof(buf), reg)); |
| } |
| |
| static void handle_pio_err(struct hfi1_devdata *dd, u32 unused, u64 reg) |
| { |
| char buf[96]; |
| |
| dd_dev_info(dd, "PIO Error: %s\n", |
| pio_err_status_string(buf, sizeof(buf), reg)); |
| |
| if (reg & ALL_PIO_FREEZE_ERR) |
| start_freeze_handling(dd->pport, 0); |
| } |
| |
| static void handle_sdma_err(struct hfi1_devdata *dd, u32 unused, u64 reg) |
| { |
| char buf[96]; |
| |
| dd_dev_info(dd, "SDMA Error: %s\n", |
| sdma_err_status_string(buf, sizeof(buf), reg)); |
| |
| if (reg & ALL_SDMA_FREEZE_ERR) |
| start_freeze_handling(dd->pport, 0); |
| } |
| |
| static void count_port_inactive(struct hfi1_devdata *dd) |
| { |
| struct hfi1_pportdata *ppd = dd->pport; |
| |
| if (ppd->port_xmit_discards < ~(u64)0) |
| ppd->port_xmit_discards++; |
| } |
| |
| /* |
| * We have had a "disallowed packet" error during egress. Determine the |
| * integrity check which failed, and update relevant error counter, etc. |
| * |
| * Note that the SEND_EGRESS_ERR_INFO register has only a single |
| * bit of state per integrity check, and so we can miss the reason for an |
| * egress error if more than one packet fails the same integrity check |
| * since we cleared the corresponding bit in SEND_EGRESS_ERR_INFO. |
| */ |
| static void handle_send_egress_err_info(struct hfi1_devdata *dd) |
| { |
| struct hfi1_pportdata *ppd = dd->pport; |
| u64 src = read_csr(dd, SEND_EGRESS_ERR_SOURCE); /* read first */ |
| u64 info = read_csr(dd, SEND_EGRESS_ERR_INFO); |
| char buf[96]; |
| |
| /* clear down all observed info as quickly as possible after read */ |
| write_csr(dd, SEND_EGRESS_ERR_INFO, info); |
| |
| dd_dev_info(dd, |
| "Egress Error Info: 0x%llx, %s Egress Error Src 0x%llx\n", |
| info, egress_err_info_string(buf, sizeof(buf), info), src); |
| |
| /* Eventually add other counters for each bit */ |
| |
| if (info & SEND_EGRESS_ERR_INFO_TOO_LONG_IB_PACKET_ERR_SMASK) { |
| if (ppd->port_xmit_discards < ~(u64)0) |
| ppd->port_xmit_discards++; |
| } |
| } |
| |
| /* |
| * Input value is a bit position within the SEND_EGRESS_ERR_STATUS |
| * register. Does it represent a 'port inactive' error? |
| */ |
| static inline int port_inactive_err(u64 posn) |
| { |
| return (posn >= SEES(TX_LINKDOWN) && |
| posn <= SEES(TX_INCORRECT_LINK_STATE)); |
| } |
| |
| /* |
| * Input value is a bit position within the SEND_EGRESS_ERR_STATUS |
| * register. Does it represent a 'disallowed packet' error? |
| */ |
| static inline int disallowed_pkt_err(u64 posn) |
| { |
| return (posn >= SEES(TX_SDMA0_DISALLOWED_PACKET) && |
| posn <= SEES(TX_SDMA15_DISALLOWED_PACKET)); |
| } |
| |
| static void handle_egress_err(struct hfi1_devdata *dd, u32 unused, u64 reg) |
| { |
| u64 reg_copy = reg, handled = 0; |
| char buf[96]; |
| |
| if (reg & ALL_TXE_EGRESS_FREEZE_ERR) |
| start_freeze_handling(dd->pport, 0); |
| if (is_a0(dd) && (reg & |
| SEND_EGRESS_ERR_STATUS_TX_CREDIT_RETURN_VL_ERR_SMASK) |
| && (dd->icode != ICODE_FUNCTIONAL_SIMULATOR)) |
| start_freeze_handling(dd->pport, 0); |
| |
| while (reg_copy) { |
| int posn = fls64(reg_copy); |
| /* |
| * fls64() returns a 1-based offset, but we generally |
| * want 0-based offsets. |
| */ |
| int shift = posn - 1; |
| |
| if (port_inactive_err(shift)) { |
| count_port_inactive(dd); |
| handled |= (1ULL << shift); |
| } else if (disallowed_pkt_err(shift)) { |
| handle_send_egress_err_info(dd); |
| handled |= (1ULL << shift); |
| } |
| clear_bit(shift, (unsigned long *)®_copy); |
| } |
| |
| reg &= ~handled; |
| |
| if (reg) |
| dd_dev_info(dd, "Egress Error: %s\n", |
| egress_err_status_string(buf, sizeof(buf), reg)); |
| } |
| |
| static void handle_txe_err(struct hfi1_devdata *dd, u32 unused, u64 reg) |
| { |
| char buf[96]; |
| |
| dd_dev_info(dd, "Send Error: %s\n", |
| send_err_status_string(buf, sizeof(buf), reg)); |
| |
| } |
| |
| /* |
| * The maximum number of times the error clear down will loop before |
| * blocking a repeating error. This value is arbitrary. |
| */ |
| #define MAX_CLEAR_COUNT 20 |
| |
| /* |
| * Clear and handle an error register. All error interrupts are funneled |
| * through here to have a central location to correctly handle single- |
| * or multi-shot errors. |
| * |
| * For non per-context registers, call this routine with a context value |
| * of 0 so the per-context offset is zero. |
| * |
| * If the handler loops too many times, assume that something is wrong |
| * and can't be fixed, so mask the error bits. |
| */ |
| static void interrupt_clear_down(struct hfi1_devdata *dd, |
| u32 context, |
| const struct err_reg_info *eri) |
| { |
| u64 reg; |
| u32 count; |
| |
| /* read in a loop until no more errors are seen */ |
| count = 0; |
| while (1) { |
| reg = read_kctxt_csr(dd, context, eri->status); |
| if (reg == 0) |
| break; |
| write_kctxt_csr(dd, context, eri->clear, reg); |
| if (likely(eri->handler)) |
| eri->handler(dd, context, reg); |
| count++; |
| if (count > MAX_CLEAR_COUNT) { |
| u64 mask; |
| |
| dd_dev_err(dd, "Repeating %s bits 0x%llx - masking\n", |
| eri->desc, reg); |
| /* |
| * Read-modify-write so any other masked bits |
| * remain masked. |
| */ |
| mask = read_kctxt_csr(dd, context, eri->mask); |
| mask &= ~reg; |
| write_kctxt_csr(dd, context, eri->mask, mask); |
| break; |
| } |
| } |
| } |
| |
| /* |
| * CCE block "misc" interrupt. Source is < 16. |
| */ |
| static void is_misc_err_int(struct hfi1_devdata *dd, unsigned int source) |
| { |
| const struct err_reg_info *eri = &misc_errs[source]; |
| |
| if (eri->handler) { |
| interrupt_clear_down(dd, 0, eri); |
| } else { |
| dd_dev_err(dd, "Unexpected misc interrupt (%u) - reserved\n", |
| source); |
| } |
| } |
| |
| static char *send_context_err_status_string(char *buf, int buf_len, u64 flags) |
| { |
| return flag_string(buf, buf_len, flags, |
| sc_err_status_flags, ARRAY_SIZE(sc_err_status_flags)); |
| } |
| |
| /* |
| * Send context error interrupt. Source (hw_context) is < 160. |
| * |
| * All send context errors cause the send context to halt. The normal |
| * clear-down mechanism cannot be used because we cannot clear the |
| * error bits until several other long-running items are done first. |
| * This is OK because with the context halted, nothing else is going |
| * to happen on it anyway. |
| */ |
| static void is_sendctxt_err_int(struct hfi1_devdata *dd, |
| unsigned int hw_context) |
| { |
| struct send_context_info *sci; |
| struct send_context *sc; |
| char flags[96]; |
| u64 status; |
| u32 sw_index; |
| |
| sw_index = dd->hw_to_sw[hw_context]; |
| if (sw_index >= dd->num_send_contexts) { |
| dd_dev_err(dd, |
| "out of range sw index %u for send context %u\n", |
| sw_index, hw_context); |
| return; |
| } |
| sci = &dd->send_contexts[sw_index]; |
| sc = sci->sc; |
| if (!sc) { |
| dd_dev_err(dd, "%s: context %u(%u): no sc?\n", __func__, |
| sw_index, hw_context); |
| return; |
| } |
| |
| /* tell the software that a halt has begun */ |
| sc_stop(sc, SCF_HALTED); |
| |
| status = read_kctxt_csr(dd, hw_context, SEND_CTXT_ERR_STATUS); |
| |
| dd_dev_info(dd, "Send Context %u(%u) Error: %s\n", sw_index, hw_context, |
| send_context_err_status_string(flags, sizeof(flags), status)); |
| |
| if (status & SEND_CTXT_ERR_STATUS_PIO_DISALLOWED_PACKET_ERR_SMASK) |
| handle_send_egress_err_info(dd); |
| |
| /* |
| * Automatically restart halted kernel contexts out of interrupt |
| * context. User contexts must ask the driver to restart the context. |
| */ |
| if (sc->type != SC_USER) |
| queue_work(dd->pport->hfi1_wq, &sc->halt_work); |
| } |
| |
| static void handle_sdma_eng_err(struct hfi1_devdata *dd, |
| unsigned int source, u64 status) |
| { |
| struct sdma_engine *sde; |
| |
| sde = &dd->per_sdma[source]; |
| #ifdef CONFIG_SDMA_VERBOSITY |
| dd_dev_err(sde->dd, "CONFIG SDMA(%u) %s:%d %s()\n", sde->this_idx, |
| slashstrip(__FILE__), __LINE__, __func__); |
| dd_dev_err(sde->dd, "CONFIG SDMA(%u) source: %u status 0x%llx\n", |
| sde->this_idx, source, (unsigned long long)status); |
| #endif |
| sdma_engine_error(sde, status); |
| } |
| |
| /* |
| * CCE block SDMA error interrupt. Source is < 16. |
| */ |
| static void is_sdma_eng_err_int(struct hfi1_devdata *dd, unsigned int source) |
| { |
| #ifdef CONFIG_SDMA_VERBOSITY |
| struct sdma_engine *sde = &dd->per_sdma[source]; |
| |
| dd_dev_err(dd, "CONFIG SDMA(%u) %s:%d %s()\n", sde->this_idx, |
| slashstrip(__FILE__), __LINE__, __func__); |
| dd_dev_err(dd, "CONFIG SDMA(%u) source: %u\n", sde->this_idx, |
| source); |
| sdma_dumpstate(sde); |
| #endif |
| interrupt_clear_down(dd, source, &sdma_eng_err); |
| } |
| |
| /* |
| * CCE block "various" interrupt. Source is < 8. |
| */ |
| static void is_various_int(struct hfi1_devdata *dd, unsigned int source) |
| { |
| const struct err_reg_info *eri = &various_err[source]; |
| |
| /* |
| * TCritInt cannot go through interrupt_clear_down() |
| * because it is not a second tier interrupt. The handler |
| * should be called directly. |
| */ |
| if (source == TCRIT_INT_SOURCE) |
| handle_temp_err(dd); |
| else if (eri->handler) |
| interrupt_clear_down(dd, 0, eri); |
| else |
| dd_dev_info(dd, |
| "%s: Unimplemented/reserved interrupt %d\n", |
| __func__, source); |
| } |
| |
| static void handle_qsfp_int(struct hfi1_devdata *dd, u32 src_ctx, u64 reg) |
| { |
| /* source is always zero */ |
| struct hfi1_pportdata *ppd = dd->pport; |
| unsigned long flags; |
| u64 qsfp_int_mgmt = (u64)(QSFP_HFI0_INT_N | QSFP_HFI0_MODPRST_N); |
| |
| if (reg & QSFP_HFI0_MODPRST_N) { |
| |
| dd_dev_info(dd, "%s: ModPresent triggered QSFP interrupt\n", |
| __func__); |
| |
| if (!qsfp_mod_present(ppd)) { |
| ppd->driver_link_ready = 0; |
| /* |
| * Cable removed, reset all our information about the |
| * cache and cable capabilities |
| */ |
| |
| spin_lock_irqsave(&ppd->qsfp_info.qsfp_lock, flags); |
| /* |
| * We don't set cache_refresh_required here as we expect |
| * an interrupt when a cable is inserted |
| */ |
| ppd->qsfp_info.cache_valid = 0; |
| ppd->qsfp_info.qsfp_interrupt_functional = 0; |
| spin_unlock_irqrestore(&ppd->qsfp_info.qsfp_lock, |
| flags); |
| write_csr(dd, |
| dd->hfi1_id ? |
| ASIC_QSFP2_INVERT : |
| ASIC_QSFP1_INVERT, |
| qsfp_int_mgmt); |
| if (ppd->host_link_state == HLS_DN_POLL) { |
| /* |
| * The link is still in POLL. This means |
| * that the normal link down processing |
| * will not happen. We have to do it here |
| * before turning the DC off. |
| */ |
| queue_work(ppd->hfi1_wq, &ppd->link_down_work); |
| } |
| } else { |
| spin_lock_irqsave(&ppd->qsfp_info.qsfp_lock, flags); |
| ppd->qsfp_info.cache_valid = 0; |
| ppd->qsfp_info.cache_refresh_required = 1; |
| spin_unlock_irqrestore(&ppd->qsfp_info.qsfp_lock, |
| flags); |
| |
| qsfp_int_mgmt &= ~(u64)QSFP_HFI0_MODPRST_N; |
| write_csr(dd, |
| dd->hfi1_id ? |
| ASIC_QSFP2_INVERT : |
| ASIC_QSFP1_INVERT, |
| qsfp_int_mgmt); |
| } |
| } |
| |
| if (reg & QSFP_HFI0_INT_N) { |
| |
| dd_dev_info(dd, "%s: IntN triggered QSFP interrupt\n", |
| __func__); |
| spin_lock_irqsave(&ppd->qsfp_info.qsfp_lock, flags); |
| ppd->qsfp_info.check_interrupt_flags = 1; |
| ppd->qsfp_info.qsfp_interrupt_functional = 1; |
| spin_unlock_irqrestore(&ppd->qsfp_info.qsfp_lock, flags); |
| } |
| |
| /* Schedule the QSFP work only if there is a cable attached. */ |
| if (qsfp_mod_present(ppd)) |
| queue_work(ppd->hfi1_wq, &ppd->qsfp_info.qsfp_work); |
| } |
| |
| static int request_host_lcb_access(struct hfi1_devdata *dd) |
| { |
| int ret; |
| |
| ret = do_8051_command(dd, HCMD_MISC, |
| (u64)HCMD_MISC_REQUEST_LCB_ACCESS << LOAD_DATA_FIELD_ID_SHIFT, |
| NULL); |
| if (ret != HCMD_SUCCESS) { |
| dd_dev_err(dd, "%s: command failed with error %d\n", |
| __func__, ret); |
| } |
| return ret == HCMD_SUCCESS ? 0 : -EBUSY; |
| } |
| |
| static int request_8051_lcb_access(struct hfi1_devdata *dd) |
| { |
| int ret; |
| |
| ret = do_8051_command(dd, HCMD_MISC, |
| (u64)HCMD_MISC_GRANT_LCB_ACCESS << LOAD_DATA_FIELD_ID_SHIFT, |
| NULL); |
| if (ret != HCMD_SUCCESS) { |
| dd_dev_err(dd, "%s: command failed with error %d\n", |
| __func__, ret); |
| } |
| return ret == HCMD_SUCCESS ? 0 : -EBUSY; |
| } |
| |
| /* |
| * Set the LCB selector - allow host access. The DCC selector always |
| * points to the host. |
| */ |
| static inline void set_host_lcb_access(struct hfi1_devdata *dd) |
| { |
| write_csr(dd, DC_DC8051_CFG_CSR_ACCESS_SEL, |
| DC_DC8051_CFG_CSR_ACCESS_SEL_DCC_SMASK |
| | DC_DC8051_CFG_CSR_ACCESS_SEL_LCB_SMASK); |
| } |
| |
| /* |
| * Clear the LCB selector - allow 8051 access. The DCC selector always |
| * points to the host. |
| */ |
| static inline void set_8051_lcb_access(struct hfi1_devdata *dd) |
| { |
| write_csr(dd, DC_DC8051_CFG_CSR_ACCESS_SEL, |
| DC_DC8051_CFG_CSR_ACCESS_SEL_DCC_SMASK); |
| } |
| |
| /* |
| * Acquire LCB access from the 8051. If the host already has access, |
| * just increment a counter. Otherwise, inform the 8051 that the |
| * host is taking access. |
| * |
| * Returns: |
| * 0 on success |
| * -EBUSY if the 8051 has control and cannot be disturbed |
| * -errno if unable to acquire access from the 8051 |
| */ |
| int acquire_lcb_access(struct hfi1_devdata *dd, int sleep_ok) |
| { |
| struct hfi1_pportdata *ppd = dd->pport; |
| int ret = 0; |
| |
| /* |
| * Use the host link state lock so the operation of this routine |
| * { link state check, selector change, count increment } can occur |
| * as a unit against a link state change. Otherwise there is a |
| * race between the state change and the count increment. |
| */ |
| if (sleep_ok) { |
| mutex_lock(&ppd->hls_lock); |
| } else { |
| while (!mutex_trylock(&ppd->hls_lock)) |
| udelay(1); |
| } |
| |
| /* this access is valid only when the link is up */ |
| if ((ppd->host_link_state & HLS_UP) == 0) { |
| dd_dev_info(dd, "%s: link state %s not up\n", |
| __func__, link_state_name(ppd->host_link_state)); |
| ret = -EBUSY; |
| goto done; |
| } |
| |
| if (dd->lcb_access_count == 0) { |
| ret = request_host_lcb_access(dd); |
| if (ret) { |
| dd_dev_err(dd, |
| "%s: unable to acquire LCB access, err %d\n", |
| __func__, ret); |
| goto done; |
| } |
| set_host_lcb_access(dd); |
| } |
| dd->lcb_access_count++; |
| done: |
| mutex_unlock(&ppd->hls_lock); |
| return ret; |
| } |
| |
| /* |
| * Release LCB access by decrementing the use count. If the count is moving |
| * from 1 to 0, inform 8051 that it has control back. |
| * |
| * Returns: |
| * 0 on success |
| * -errno if unable to release access to the 8051 |
| */ |
| int release_lcb_access(struct hfi1_devdata *dd, int sleep_ok) |
| { |
| int ret = 0; |
| |
| /* |
| * Use the host link state lock because the acquire needed it. |
| * Here, we only need to keep { selector change, count decrement } |
| * as a unit. |
| */ |
| if (sleep_ok) { |
| mutex_lock(&dd->pport->hls_lock); |
| } else { |
| while (!mutex_trylock(&dd->pport->hls_lock)) |
| udelay(1); |
| } |
| |
| if (dd->lcb_access_count == 0) { |
| dd_dev_err(dd, "%s: LCB access count is zero. Skipping.\n", |
| __func__); |
| goto done; |
| } |
| |
| if (dd->lcb_access_count == 1) { |
| set_8051_lcb_access(dd); |
| ret = request_8051_lcb_access(dd); |
| if (ret) { |
| dd_dev_err(dd, |
| "%s: unable to release LCB access, err %d\n", |
| __func__, ret); |
| /* restore host access if the grant didn't work */ |
| set_host_lcb_access(dd); |
| goto done; |
| } |
| } |
| dd->lcb_access_count--; |
| done: |
| mutex_unlock(&dd->pport->hls_lock); |
| return ret; |
| } |
| |
| /* |
| * Initialize LCB access variables and state. Called during driver load, |
| * after most of the initialization is finished. |
| * |
| * The DC default is LCB access on for the host. The driver defaults to |
| * leaving access to the 8051. Assign access now - this constrains the call |
| * to this routine to be after all LCB set-up is done. In particular, after |
| * hf1_init_dd() -> set_up_interrupts() -> clear_all_interrupts() |
| */ |
| static void init_lcb_access(struct hfi1_devdata *dd) |
| { |
| dd->lcb_access_count = 0; |
| } |
| |
| /* |
| * Write a response back to a 8051 request. |
| */ |
| static void hreq_response(struct hfi1_devdata *dd, u8 return_code, u16 rsp_data) |
| { |
| write_csr(dd, DC_DC8051_CFG_EXT_DEV_0, |
| DC_DC8051_CFG_EXT_DEV_0_COMPLETED_SMASK |
| | (u64)return_code << DC_DC8051_CFG_EXT_DEV_0_RETURN_CODE_SHIFT |
| | (u64)rsp_data << DC_DC8051_CFG_EXT_DEV_0_RSP_DATA_SHIFT); |
| } |
| |
| /* |
| * Handle requests from the 8051. |
| */ |
| static void handle_8051_request(struct hfi1_devdata *dd) |
| { |
| u64 reg; |
| u16 data; |
| u8 type; |
| |
| reg = read_csr(dd, DC_DC8051_CFG_EXT_DEV_1); |
| if ((reg & DC_DC8051_CFG_EXT_DEV_1_REQ_NEW_SMASK) == 0) |
| return; /* no request */ |
| |
| /* zero out COMPLETED so the response is seen */ |
| write_csr(dd, DC_DC8051_CFG_EXT_DEV_0, 0); |
| |
| /* extract request details */ |
| type = (reg >> DC_DC8051_CFG_EXT_DEV_1_REQ_TYPE_SHIFT) |
| & DC_DC8051_CFG_EXT_DEV_1_REQ_TYPE_MASK; |
| data = (reg >> DC_DC8051_CFG_EXT_DEV_1_REQ_DATA_SHIFT) |
| & DC_DC8051_CFG_EXT_DEV_1_REQ_DATA_MASK; |
| |
| switch (type) { |
| case HREQ_LOAD_CONFIG: |
| case HREQ_SAVE_CONFIG: |
| case HREQ_READ_CONFIG: |
| case HREQ_SET_TX_EQ_ABS: |
| case HREQ_SET_TX_EQ_REL: |
| case HREQ_ENABLE: |
| dd_dev_info(dd, "8051 request: request 0x%x not supported\n", |
| type); |
| hreq_response(dd, HREQ_NOT_SUPPORTED, 0); |
| break; |
| |
| case HREQ_CONFIG_DONE: |
| hreq_response(dd, HREQ_SUCCESS, 0); |
| break; |
| |
| case HREQ_INTERFACE_TEST: |
| hreq_response(dd, HREQ_SUCCESS, data); |
| break; |
| |
| default: |
| dd_dev_err(dd, "8051 request: unknown request 0x%x\n", type); |
| hreq_response(dd, HREQ_NOT_SUPPORTED, 0); |
| break; |
| } |
| } |
| |
| static void write_global_credit(struct hfi1_devdata *dd, |
| u8 vau, u16 total, u16 shared) |
| { |
| write_csr(dd, SEND_CM_GLOBAL_CREDIT, |
| ((u64)total |
| << SEND_CM_GLOBAL_CREDIT_TOTAL_CREDIT_LIMIT_SHIFT) |
| | ((u64)shared |
| << SEND_CM_GLOBAL_CREDIT_SHARED_LIMIT_SHIFT) |
| | ((u64)vau << SEND_CM_GLOBAL_CREDIT_AU_SHIFT)); |
| } |
| |
| /* |
| * Set up initial VL15 credits of the remote. Assumes the rest of |
| * the CM credit registers are zero from a previous global or credit reset . |
| */ |
| void set_up_vl15(struct hfi1_devdata *dd, u8 vau, u16 vl15buf) |
| { |
| /* leave shared count at zero for both global and VL15 */ |
| write_global_credit(dd, vau, vl15buf, 0); |
| |
| /* We may need some credits for another VL when sending packets |
| * with the snoop interface. Dividing it down the middle for VL15 |
| * and VL0 should suffice. |
| */ |
| if (unlikely(dd->hfi1_snoop.mode_flag == HFI1_PORT_SNOOP_MODE)) { |
| write_csr(dd, SEND_CM_CREDIT_VL15, (u64)(vl15buf >> 1) |
| << SEND_CM_CREDIT_VL15_DEDICATED_LIMIT_VL_SHIFT); |
| write_csr(dd, SEND_CM_CREDIT_VL, (u64)(vl15buf >> 1) |
| << SEND_CM_CREDIT_VL_DEDICATED_LIMIT_VL_SHIFT); |
| } else { |
| write_csr(dd, SEND_CM_CREDIT_VL15, (u64)vl15buf |
| << SEND_CM_CREDIT_VL15_DEDICATED_LIMIT_VL_SHIFT); |
| } |
| } |
| |
| /* |
| * Zero all credit details from the previous connection and |
| * reset the CM manager's internal counters. |
| */ |
| void |