diff options
author | np <np@FreeBSD.org> | 2013-02-26 21:25:17 +0000 |
---|---|---|
committer | np <np@FreeBSD.org> | 2013-02-26 21:25:17 +0000 |
commit | b32aae39278d9212e6a77b34e2f4e33b9b303e4a (patch) | |
tree | 22a95f58e2b6aeec4e90a5badd5acda78c9f0c9a /sys/dev | |
parent | 59b2f5398a5477c3d3a7461fd4d4966e0cb7c950 (diff) | |
download | FreeBSD-src-b32aae39278d9212e6a77b34e2f4e33b9b303e4a.zip FreeBSD-src-b32aae39278d9212e6a77b34e2f4e33b9b303e4a.tar.gz |
cxgbe(4): Report unusual out of band errors from the firmware.
Obtained from: Chelsio
MFC after: 5 days
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/cxgbe/common/t4_hw.c | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c index 3aea091..e00e779 100644 --- a/sys/dev/cxgbe/common/t4_hw.c +++ b/sys/dev/cxgbe/common/t4_hw.c @@ -154,6 +154,36 @@ u32 t4_hw_pci_read_cfg4(adapter_t *adap, int reg) } /* + * t4_report_fw_error - report firmware error + * @adap: the adapter + * + * The adapter firmware can indicate error conditions to the host. + * This routine prints out the reason for the firmware error (as + * reported by the firmware). + */ +static void t4_report_fw_error(struct adapter *adap) +{ + static const char *reason[] = { + "Crash", /* PCIE_FW_EVAL_CRASH */ + "During Device Preparation", /* PCIE_FW_EVAL_PREP */ + "During Device Configuration", /* PCIE_FW_EVAL_CONF */ + "During Device Initialization", /* PCIE_FW_EVAL_INIT */ + "Unexpected Event", /* PCIE_FW_EVAL_UNEXPECTEDEVENT */ + "Insufficient Airflow", /* PCIE_FW_EVAL_OVERHEAT */ + "Device Shutdown", /* PCIE_FW_EVAL_DEVICESHUTDOWN */ + "Reserved", /* reserved */ + }; + u32 pcie_fw; + + pcie_fw = t4_read_reg(adap, A_PCIE_FW); + if (!(pcie_fw & F_PCIE_FW_ERR)) + CH_ERR(adap, "Firmware error report called with no error\n"); + else + CH_ERR(adap, "Firmware reports adapter error: %s\n", + reason[G_PCIE_FW_EVAL(pcie_fw)]); +} + +/* * Get the reply to a mailbox command and store it in @rpl in big-endian order. */ static void get_mbox_rpl(struct adapter *adap, __be64 *rpl, int nflit, @@ -267,8 +297,15 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size, } } + /* + * We timed out waiting for a reply to our mailbox command. Report + * the error and also check to see if the firmware reported any + * errors ... + */ CH_ERR(adap, "command %#x in mailbox %d timed out\n", *(const u8 *)cmd, mbox); + if (t4_read_reg(adap, A_PCIE_FW) & F_PCIE_FW_ERR) + t4_report_fw_error(adap); return -ETIMEDOUT; } @@ -2033,9 +2070,11 @@ static void cim_intr_handler(struct adapter *adapter) { F_TIMEOUTMAINT , "CIM PIF MA timeout", -1, 1 }, { 0 } }; - int fat; + if (t4_read_reg(adapter, A_PCIE_FW) & F_PCIE_FW_ERR) + t4_report_fw_error(adapter); + fat = t4_handle_intr_status(adapter, A_CIM_HOST_INT_CAUSE, cim_intr_info) + t4_handle_intr_status(adapter, A_CIM_HOST_UPACC_INT_CAUSE, @@ -4103,12 +4142,16 @@ retry: /* * Issue the HELLO command to the firmware. If it's not successful * but indicates that we got a "busy" or "timeout" condition, retry - * the HELLO until we exhaust our retry limit. + * the HELLO until we exhaust our retry limit. If we do exceed our + * retry limit, check to see if the firmware left us any error + * information and report that if so ... */ ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); if (ret != FW_SUCCESS) { if ((ret == -EBUSY || ret == -ETIMEDOUT) && retries-- > 0) goto retry; + if (t4_read_reg(adap, A_PCIE_FW) & F_PCIE_FW_ERR) + t4_report_fw_error(adap); return ret; } |