|
@@ -167,6 +167,34 @@ void t4_hw_pci_read_cfg4(struct adapter *adap, int reg, u32 *val)
|
|
|
t4_write_reg(adap, PCIE_CFG_SPACE_REQ, 0);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * t4_report_fw_error - report firmware error
|
|
|
+ * @adap: the adapter
|
|
|
+ *
|
|
|
+ * The adapter firmware can indicate error conditions to the host.
|
|
|
+ * If the firmware has indicated an error, print out the reason for
|
|
|
+ * the firmware error.
|
|
|
+ */
|
|
|
+static void t4_report_fw_error(struct adapter *adap)
|
|
|
+{
|
|
|
+ static const char *const 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, MA_PCIE_FW);
|
|
|
+ if (pcie_fw & FW_PCIE_FW_ERR)
|
|
|
+ dev_err(adap->pdev_dev, "Firmware reports adapter error: %s\n",
|
|
|
+ reason[FW_PCIE_FW_EVAL_GET(pcie_fw)]);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Get the reply to a mailbox command and store it in @rpl in big-endian order.
|
|
|
*/
|
|
@@ -300,6 +328,7 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
|
|
|
dump_mbox(adap, mbox, data_reg);
|
|
|
dev_err(adap->pdev_dev, "command %#x in mailbox %d timed out\n",
|
|
|
*(const u8 *)cmd, mbox);
|
|
|
+ t4_report_fw_error(adap);
|
|
|
return -ETIMEDOUT;
|
|
|
}
|
|
|
|
|
@@ -566,6 +595,7 @@ int t4_memory_rw(struct adapter *adap, int win, int mtype, u32 addr,
|
|
|
#define VPD_BASE 0x400
|
|
|
#define VPD_BASE_OLD 0
|
|
|
#define VPD_LEN 1024
|
|
|
+#define CHELSIO_VPD_UNIQUE_ID 0x82
|
|
|
|
|
|
/**
|
|
|
* t4_seeprom_wp - enable/disable EEPROM write protection
|
|
@@ -603,7 +633,14 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
|
|
|
ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(u32), vpd);
|
|
|
if (ret < 0)
|
|
|
goto out;
|
|
|
- addr = *vpd == 0x82 ? VPD_BASE : VPD_BASE_OLD;
|
|
|
+
|
|
|
+ /* The VPD shall have a unique identifier specified by the PCI SIG.
|
|
|
+ * For chelsio adapters, the identifier is 0x82. The first byte of a VPD
|
|
|
+ * shall be CHELSIO_VPD_UNIQUE_ID (0x82). The VPD programming software
|
|
|
+ * is expected to automatically put this entry at the
|
|
|
+ * beginning of the VPD.
|
|
|
+ */
|
|
|
+ addr = *vpd == CHELSIO_VPD_UNIQUE_ID ? VPD_BASE : VPD_BASE_OLD;
|
|
|
|
|
|
ret = pci_read_vpd(adapter->pdev, addr, VPD_LEN, vpd);
|
|
|
if (ret < 0)
|
|
@@ -667,6 +704,7 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
|
|
|
i = pci_vpd_info_field_size(vpd + sn - PCI_VPD_INFO_FLD_HDR_SIZE);
|
|
|
memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN));
|
|
|
strim(p->sn);
|
|
|
+ i = pci_vpd_info_field_size(vpd + pn - PCI_VPD_INFO_FLD_HDR_SIZE);
|
|
|
memcpy(p->pn, vpd + pn, min(i, PN_LEN));
|
|
|
strim(p->pn);
|
|
|
|
|
@@ -1394,15 +1432,18 @@ static void pcie_intr_handler(struct adapter *adapter)
|
|
|
|
|
|
int fat;
|
|
|
|
|
|
- fat = t4_handle_intr_status(adapter,
|
|
|
- PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
|
|
|
- sysbus_intr_info) +
|
|
|
- t4_handle_intr_status(adapter,
|
|
|
- PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
|
|
|
- pcie_port_intr_info) +
|
|
|
- t4_handle_intr_status(adapter, PCIE_INT_CAUSE,
|
|
|
- is_t4(adapter->params.chip) ?
|
|
|
- pcie_intr_info : t5_pcie_intr_info);
|
|
|
+ if (is_t4(adapter->params.chip))
|
|
|
+ fat = t4_handle_intr_status(adapter,
|
|
|
+ PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
|
|
|
+ sysbus_intr_info) +
|
|
|
+ t4_handle_intr_status(adapter,
|
|
|
+ PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
|
|
|
+ pcie_port_intr_info) +
|
|
|
+ t4_handle_intr_status(adapter, PCIE_INT_CAUSE,
|
|
|
+ pcie_intr_info);
|
|
|
+ else
|
|
|
+ fat = t4_handle_intr_status(adapter, PCIE_INT_CAUSE,
|
|
|
+ t5_pcie_intr_info);
|
|
|
|
|
|
if (fat)
|
|
|
t4_fatal_err(adapter);
|
|
@@ -1521,6 +1562,9 @@ static void cim_intr_handler(struct adapter *adapter)
|
|
|
|
|
|
int fat;
|
|
|
|
|
|
+ if (t4_read_reg(adapter, MA_PCIE_FW) & FW_PCIE_FW_ERR)
|
|
|
+ t4_report_fw_error(adapter);
|
|
|
+
|
|
|
fat = t4_handle_intr_status(adapter, CIM_HOST_INT_CAUSE,
|
|
|
cim_intr_info) +
|
|
|
t4_handle_intr_status(adapter, CIM_HOST_UPACC_INT_CAUSE,
|
|
@@ -1768,10 +1812,16 @@ static void ma_intr_handler(struct adapter *adap)
|
|
|
{
|
|
|
u32 v, status = t4_read_reg(adap, MA_INT_CAUSE);
|
|
|
|
|
|
- if (status & MEM_PERR_INT_CAUSE)
|
|
|
+ if (status & MEM_PERR_INT_CAUSE) {
|
|
|
dev_alert(adap->pdev_dev,
|
|
|
"MA parity error, parity status %#x\n",
|
|
|
t4_read_reg(adap, MA_PARITY_ERROR_STATUS));
|
|
|
+ if (is_t5(adap->params.chip))
|
|
|
+ dev_alert(adap->pdev_dev,
|
|
|
+ "MA parity error, parity status %#x\n",
|
|
|
+ t4_read_reg(adap,
|
|
|
+ MA_PARITY_ERROR_STATUS2));
|
|
|
+ }
|
|
|
if (status & MEM_WRAP_INT_CAUSE) {
|
|
|
v = t4_read_reg(adap, MA_INT_WRAP_STATUS);
|
|
|
dev_alert(adap->pdev_dev, "MA address wrap-around error by "
|
|
@@ -2733,12 +2783,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 < 0) {
|
|
|
if ((ret == -EBUSY || ret == -ETIMEDOUT) && retries-- > 0)
|
|
|
goto retry;
|
|
|
+ if (t4_read_reg(adap, MA_PCIE_FW) & FW_PCIE_FW_ERR)
|
|
|
+ t4_report_fw_error(adap);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -3742,6 +3796,7 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
|
|
|
lc->link_ok = link_ok;
|
|
|
lc->speed = speed;
|
|
|
lc->fc = fc;
|
|
|
+ lc->supported = be16_to_cpu(p->u.info.pcap);
|
|
|
t4_os_link_changed(adap, port, link_ok);
|
|
|
}
|
|
|
if (mod != pi->mod_type) {
|