diff options
Diffstat (limited to 'drivers/net/ethernet/chelsio/cxgb4/t4_hw.c')
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 79 |
1 files changed, 67 insertions, 12 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index a853133d8db8..41d04462b72e 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | |||
@@ -168,6 +168,34 @@ void t4_hw_pci_read_cfg4(struct adapter *adap, int reg, u32 *val) | |||
168 | } | 168 | } |
169 | 169 | ||
170 | /* | 170 | /* |
171 | * t4_report_fw_error - report firmware error | ||
172 | * @adap: the adapter | ||
173 | * | ||
174 | * The adapter firmware can indicate error conditions to the host. | ||
175 | * If the firmware has indicated an error, print out the reason for | ||
176 | * the firmware error. | ||
177 | */ | ||
178 | static void t4_report_fw_error(struct adapter *adap) | ||
179 | { | ||
180 | static const char *const reason[] = { | ||
181 | "Crash", /* PCIE_FW_EVAL_CRASH */ | ||
182 | "During Device Preparation", /* PCIE_FW_EVAL_PREP */ | ||
183 | "During Device Configuration", /* PCIE_FW_EVAL_CONF */ | ||
184 | "During Device Initialization", /* PCIE_FW_EVAL_INIT */ | ||
185 | "Unexpected Event", /* PCIE_FW_EVAL_UNEXPECTEDEVENT */ | ||
186 | "Insufficient Airflow", /* PCIE_FW_EVAL_OVERHEAT */ | ||
187 | "Device Shutdown", /* PCIE_FW_EVAL_DEVICESHUTDOWN */ | ||
188 | "Reserved", /* reserved */ | ||
189 | }; | ||
190 | u32 pcie_fw; | ||
191 | |||
192 | pcie_fw = t4_read_reg(adap, MA_PCIE_FW); | ||
193 | if (pcie_fw & FW_PCIE_FW_ERR) | ||
194 | dev_err(adap->pdev_dev, "Firmware reports adapter error: %s\n", | ||
195 | reason[FW_PCIE_FW_EVAL_GET(pcie_fw)]); | ||
196 | } | ||
197 | |||
198 | /* | ||
171 | * Get the reply to a mailbox command and store it in @rpl in big-endian order. | 199 | * Get the reply to a mailbox command and store it in @rpl in big-endian order. |
172 | */ | 200 | */ |
173 | static void get_mbox_rpl(struct adapter *adap, __be64 *rpl, int nflit, | 201 | static void get_mbox_rpl(struct adapter *adap, __be64 *rpl, int nflit, |
@@ -300,6 +328,7 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size, | |||
300 | dump_mbox(adap, mbox, data_reg); | 328 | dump_mbox(adap, mbox, data_reg); |
301 | dev_err(adap->pdev_dev, "command %#x in mailbox %d timed out\n", | 329 | dev_err(adap->pdev_dev, "command %#x in mailbox %d timed out\n", |
302 | *(const u8 *)cmd, mbox); | 330 | *(const u8 *)cmd, mbox); |
331 | t4_report_fw_error(adap); | ||
303 | return -ETIMEDOUT; | 332 | return -ETIMEDOUT; |
304 | } | 333 | } |
305 | 334 | ||
@@ -566,6 +595,7 @@ int t4_memory_rw(struct adapter *adap, int win, int mtype, u32 addr, | |||
566 | #define VPD_BASE 0x400 | 595 | #define VPD_BASE 0x400 |
567 | #define VPD_BASE_OLD 0 | 596 | #define VPD_BASE_OLD 0 |
568 | #define VPD_LEN 1024 | 597 | #define VPD_LEN 1024 |
598 | #define CHELSIO_VPD_UNIQUE_ID 0x82 | ||
569 | 599 | ||
570 | /** | 600 | /** |
571 | * t4_seeprom_wp - enable/disable EEPROM write protection | 601 | * t4_seeprom_wp - enable/disable EEPROM write protection |
@@ -603,7 +633,14 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p) | |||
603 | ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(u32), vpd); | 633 | ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(u32), vpd); |
604 | if (ret < 0) | 634 | if (ret < 0) |
605 | goto out; | 635 | goto out; |
606 | addr = *vpd == 0x82 ? VPD_BASE : VPD_BASE_OLD; | 636 | |
637 | /* The VPD shall have a unique identifier specified by the PCI SIG. | ||
638 | * For chelsio adapters, the identifier is 0x82. The first byte of a VPD | ||
639 | * shall be CHELSIO_VPD_UNIQUE_ID (0x82). The VPD programming software | ||
640 | * is expected to automatically put this entry at the | ||
641 | * beginning of the VPD. | ||
642 | */ | ||
643 | addr = *vpd == CHELSIO_VPD_UNIQUE_ID ? VPD_BASE : VPD_BASE_OLD; | ||
607 | 644 | ||
608 | ret = pci_read_vpd(adapter->pdev, addr, VPD_LEN, vpd); | 645 | ret = pci_read_vpd(adapter->pdev, addr, VPD_LEN, vpd); |
609 | if (ret < 0) | 646 | if (ret < 0) |
@@ -667,6 +704,7 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p) | |||
667 | i = pci_vpd_info_field_size(vpd + sn - PCI_VPD_INFO_FLD_HDR_SIZE); | 704 | i = pci_vpd_info_field_size(vpd + sn - PCI_VPD_INFO_FLD_HDR_SIZE); |
668 | memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN)); | 705 | memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN)); |
669 | strim(p->sn); | 706 | strim(p->sn); |
707 | i = pci_vpd_info_field_size(vpd + pn - PCI_VPD_INFO_FLD_HDR_SIZE); | ||
670 | memcpy(p->pn, vpd + pn, min(i, PN_LEN)); | 708 | memcpy(p->pn, vpd + pn, min(i, PN_LEN)); |
671 | strim(p->pn); | 709 | strim(p->pn); |
672 | 710 | ||
@@ -1394,15 +1432,18 @@ static void pcie_intr_handler(struct adapter *adapter) | |||
1394 | 1432 | ||
1395 | int fat; | 1433 | int fat; |
1396 | 1434 | ||
1397 | fat = t4_handle_intr_status(adapter, | 1435 | if (is_t4(adapter->params.chip)) |
1398 | PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS, | 1436 | fat = t4_handle_intr_status(adapter, |
1399 | sysbus_intr_info) + | 1437 | PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS, |
1400 | t4_handle_intr_status(adapter, | 1438 | sysbus_intr_info) + |
1401 | PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS, | 1439 | t4_handle_intr_status(adapter, |
1402 | pcie_port_intr_info) + | 1440 | PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS, |
1403 | t4_handle_intr_status(adapter, PCIE_INT_CAUSE, | 1441 | pcie_port_intr_info) + |
1404 | is_t4(adapter->params.chip) ? | 1442 | t4_handle_intr_status(adapter, PCIE_INT_CAUSE, |
1405 | pcie_intr_info : t5_pcie_intr_info); | 1443 | pcie_intr_info); |
1444 | else | ||
1445 | fat = t4_handle_intr_status(adapter, PCIE_INT_CAUSE, | ||
1446 | t5_pcie_intr_info); | ||
1406 | 1447 | ||
1407 | if (fat) | 1448 | if (fat) |
1408 | t4_fatal_err(adapter); | 1449 | t4_fatal_err(adapter); |
@@ -1521,6 +1562,9 @@ static void cim_intr_handler(struct adapter *adapter) | |||
1521 | 1562 | ||
1522 | int fat; | 1563 | int fat; |
1523 | 1564 | ||
1565 | if (t4_read_reg(adapter, MA_PCIE_FW) & FW_PCIE_FW_ERR) | ||
1566 | t4_report_fw_error(adapter); | ||
1567 | |||
1524 | fat = t4_handle_intr_status(adapter, CIM_HOST_INT_CAUSE, | 1568 | fat = t4_handle_intr_status(adapter, CIM_HOST_INT_CAUSE, |
1525 | cim_intr_info) + | 1569 | cim_intr_info) + |
1526 | t4_handle_intr_status(adapter, CIM_HOST_UPACC_INT_CAUSE, | 1570 | t4_handle_intr_status(adapter, CIM_HOST_UPACC_INT_CAUSE, |
@@ -1768,10 +1812,16 @@ static void ma_intr_handler(struct adapter *adap) | |||
1768 | { | 1812 | { |
1769 | u32 v, status = t4_read_reg(adap, MA_INT_CAUSE); | 1813 | u32 v, status = t4_read_reg(adap, MA_INT_CAUSE); |
1770 | 1814 | ||
1771 | if (status & MEM_PERR_INT_CAUSE) | 1815 | if (status & MEM_PERR_INT_CAUSE) { |
1772 | dev_alert(adap->pdev_dev, | 1816 | dev_alert(adap->pdev_dev, |
1773 | "MA parity error, parity status %#x\n", | 1817 | "MA parity error, parity status %#x\n", |
1774 | t4_read_reg(adap, MA_PARITY_ERROR_STATUS)); | 1818 | t4_read_reg(adap, MA_PARITY_ERROR_STATUS)); |
1819 | if (is_t5(adap->params.chip)) | ||
1820 | dev_alert(adap->pdev_dev, | ||
1821 | "MA parity error, parity status %#x\n", | ||
1822 | t4_read_reg(adap, | ||
1823 | MA_PARITY_ERROR_STATUS2)); | ||
1824 | } | ||
1775 | if (status & MEM_WRAP_INT_CAUSE) { | 1825 | if (status & MEM_WRAP_INT_CAUSE) { |
1776 | v = t4_read_reg(adap, MA_INT_WRAP_STATUS); | 1826 | v = t4_read_reg(adap, MA_INT_WRAP_STATUS); |
1777 | dev_alert(adap->pdev_dev, "MA address wrap-around error by " | 1827 | dev_alert(adap->pdev_dev, "MA address wrap-around error by " |
@@ -2733,12 +2783,16 @@ retry: | |||
2733 | /* | 2783 | /* |
2734 | * Issue the HELLO command to the firmware. If it's not successful | 2784 | * Issue the HELLO command to the firmware. If it's not successful |
2735 | * but indicates that we got a "busy" or "timeout" condition, retry | 2785 | * but indicates that we got a "busy" or "timeout" condition, retry |
2736 | * the HELLO until we exhaust our retry limit. | 2786 | * the HELLO until we exhaust our retry limit. If we do exceed our |
2787 | * retry limit, check to see if the firmware left us any error | ||
2788 | * information and report that if so. | ||
2737 | */ | 2789 | */ |
2738 | ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); | 2790 | ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); |
2739 | if (ret < 0) { | 2791 | if (ret < 0) { |
2740 | if ((ret == -EBUSY || ret == -ETIMEDOUT) && retries-- > 0) | 2792 | if ((ret == -EBUSY || ret == -ETIMEDOUT) && retries-- > 0) |
2741 | goto retry; | 2793 | goto retry; |
2794 | if (t4_read_reg(adap, MA_PCIE_FW) & FW_PCIE_FW_ERR) | ||
2795 | t4_report_fw_error(adap); | ||
2742 | return ret; | 2796 | return ret; |
2743 | } | 2797 | } |
2744 | 2798 | ||
@@ -3742,6 +3796,7 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl) | |||
3742 | lc->link_ok = link_ok; | 3796 | lc->link_ok = link_ok; |
3743 | lc->speed = speed; | 3797 | lc->speed = speed; |
3744 | lc->fc = fc; | 3798 | lc->fc = fc; |
3799 | lc->supported = be16_to_cpu(p->u.info.pcap); | ||
3745 | t4_os_link_changed(adap, port, link_ok); | 3800 | t4_os_link_changed(adap, port, link_ok); |
3746 | } | 3801 | } |
3747 | if (mod != pi->mod_type) { | 3802 | if (mod != pi->mod_type) { |