diff options
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_nx.c')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_nx.c | 738 |
1 files changed, 722 insertions, 16 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index e1e46b6dac75..228b67020d2c 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
8 | #include <linux/io.h> | 8 | #include <linux/io.h> |
9 | #include <linux/pci.h> | 9 | #include <linux/pci.h> |
10 | #include <linux/ratelimit.h> | ||
10 | #include "ql4_def.h" | 11 | #include "ql4_def.h" |
11 | #include "ql4_glbl.h" | 12 | #include "ql4_glbl.h" |
12 | 13 | ||
@@ -420,6 +421,38 @@ qla4_8xxx_rd_32(struct scsi_qla_host *ha, ulong off) | |||
420 | return data; | 421 | return data; |
421 | } | 422 | } |
422 | 423 | ||
424 | /* Minidump related functions */ | ||
425 | static int qla4_8xxx_md_rw_32(struct scsi_qla_host *ha, uint32_t off, | ||
426 | u32 data, uint8_t flag) | ||
427 | { | ||
428 | uint32_t win_read, off_value, rval = QLA_SUCCESS; | ||
429 | |||
430 | off_value = off & 0xFFFF0000; | ||
431 | writel(off_value, (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); | ||
432 | |||
433 | /* Read back value to make sure write has gone through before trying | ||
434 | * to use it. | ||
435 | */ | ||
436 | win_read = readl((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase)); | ||
437 | if (win_read != off_value) { | ||
438 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
439 | "%s: Written (0x%x) != Read (0x%x), off=0x%x\n", | ||
440 | __func__, off_value, win_read, off)); | ||
441 | return QLA_ERROR; | ||
442 | } | ||
443 | |||
444 | off_value = off & 0x0000FFFF; | ||
445 | |||
446 | if (flag) | ||
447 | writel(data, (void __iomem *)(off_value + CRB_INDIRECT_2M + | ||
448 | ha->nx_pcibase)); | ||
449 | else | ||
450 | rval = readl((void __iomem *)(off_value + CRB_INDIRECT_2M + | ||
451 | ha->nx_pcibase)); | ||
452 | |||
453 | return rval; | ||
454 | } | ||
455 | |||
423 | #define CRB_WIN_LOCK_TIMEOUT 100000000 | 456 | #define CRB_WIN_LOCK_TIMEOUT 100000000 |
424 | 457 | ||
425 | int qla4_8xxx_crb_win_lock(struct scsi_qla_host *ha) | 458 | int qla4_8xxx_crb_win_lock(struct scsi_qla_host *ha) |
@@ -1252,9 +1285,9 @@ qla4_8xxx_pci_mem_read_2M(struct scsi_qla_host *ha, | |||
1252 | } | 1285 | } |
1253 | 1286 | ||
1254 | if (j >= MAX_CTL_CHECK) { | 1287 | if (j >= MAX_CTL_CHECK) { |
1255 | if (printk_ratelimit()) | 1288 | printk_ratelimited(KERN_ERR |
1256 | ql4_printk(KERN_ERR, ha, | 1289 | "%s: failed to read through agent\n", |
1257 | "failed to read through agent\n"); | 1290 | __func__); |
1258 | break; | 1291 | break; |
1259 | } | 1292 | } |
1260 | 1293 | ||
@@ -1390,7 +1423,8 @@ qla4_8xxx_pci_mem_write_2M(struct scsi_qla_host *ha, | |||
1390 | if (j >= MAX_CTL_CHECK) { | 1423 | if (j >= MAX_CTL_CHECK) { |
1391 | if (printk_ratelimit()) | 1424 | if (printk_ratelimit()) |
1392 | ql4_printk(KERN_ERR, ha, | 1425 | ql4_printk(KERN_ERR, ha, |
1393 | "failed to write through agent\n"); | 1426 | "%s: failed to read through agent\n", |
1427 | __func__); | ||
1394 | ret = -1; | 1428 | ret = -1; |
1395 | break; | 1429 | break; |
1396 | } | 1430 | } |
@@ -1462,6 +1496,8 @@ qla4_8xxx_set_drv_active(struct scsi_qla_host *ha) | |||
1462 | 1496 | ||
1463 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | 1497 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); |
1464 | drv_active |= (1 << (ha->func_num * 4)); | 1498 | drv_active |= (1 << (ha->func_num * 4)); |
1499 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n", | ||
1500 | __func__, ha->host_no, drv_active); | ||
1465 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); | 1501 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); |
1466 | } | 1502 | } |
1467 | 1503 | ||
@@ -1472,6 +1508,8 @@ qla4_8xxx_clear_drv_active(struct scsi_qla_host *ha) | |||
1472 | 1508 | ||
1473 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | 1509 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); |
1474 | drv_active &= ~(1 << (ha->func_num * 4)); | 1510 | drv_active &= ~(1 << (ha->func_num * 4)); |
1511 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_active: 0x%08x\n", | ||
1512 | __func__, ha->host_no, drv_active); | ||
1475 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); | 1513 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_ACTIVE, drv_active); |
1476 | } | 1514 | } |
1477 | 1515 | ||
@@ -1497,6 +1535,8 @@ qla4_8xxx_set_rst_ready(struct scsi_qla_host *ha) | |||
1497 | 1535 | ||
1498 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | 1536 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); |
1499 | drv_state |= (1 << (ha->func_num * 4)); | 1537 | drv_state |= (1 << (ha->func_num * 4)); |
1538 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n", | ||
1539 | __func__, ha->host_no, drv_state); | ||
1500 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); | 1540 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); |
1501 | } | 1541 | } |
1502 | 1542 | ||
@@ -1507,6 +1547,8 @@ qla4_8xxx_clear_rst_ready(struct scsi_qla_host *ha) | |||
1507 | 1547 | ||
1508 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); | 1548 | drv_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_STATE); |
1509 | drv_state &= ~(1 << (ha->func_num * 4)); | 1549 | drv_state &= ~(1 << (ha->func_num * 4)); |
1550 | ql4_printk(KERN_INFO, ha, "%s(%ld): drv_state: 0x%08x\n", | ||
1551 | __func__, ha->host_no, drv_state); | ||
1510 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); | 1552 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_STATE, drv_state); |
1511 | } | 1553 | } |
1512 | 1554 | ||
@@ -1601,6 +1643,629 @@ static void qla4_8xxx_rom_lock_recovery(struct scsi_qla_host *ha) | |||
1601 | qla4_8xxx_rom_unlock(ha); | 1643 | qla4_8xxx_rom_unlock(ha); |
1602 | } | 1644 | } |
1603 | 1645 | ||
1646 | static void qla4_8xxx_minidump_process_rdcrb(struct scsi_qla_host *ha, | ||
1647 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
1648 | uint32_t **d_ptr) | ||
1649 | { | ||
1650 | uint32_t r_addr, r_stride, loop_cnt, i, r_value; | ||
1651 | struct qla82xx_minidump_entry_crb *crb_hdr; | ||
1652 | uint32_t *data_ptr = *d_ptr; | ||
1653 | |||
1654 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
1655 | crb_hdr = (struct qla82xx_minidump_entry_crb *)entry_hdr; | ||
1656 | r_addr = crb_hdr->addr; | ||
1657 | r_stride = crb_hdr->crb_strd.addr_stride; | ||
1658 | loop_cnt = crb_hdr->op_count; | ||
1659 | |||
1660 | for (i = 0; i < loop_cnt; i++) { | ||
1661 | r_value = qla4_8xxx_md_rw_32(ha, r_addr, 0, 0); | ||
1662 | *data_ptr++ = cpu_to_le32(r_addr); | ||
1663 | *data_ptr++ = cpu_to_le32(r_value); | ||
1664 | r_addr += r_stride; | ||
1665 | } | ||
1666 | *d_ptr = data_ptr; | ||
1667 | } | ||
1668 | |||
1669 | static int qla4_8xxx_minidump_process_l2tag(struct scsi_qla_host *ha, | ||
1670 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
1671 | uint32_t **d_ptr) | ||
1672 | { | ||
1673 | uint32_t addr, r_addr, c_addr, t_r_addr; | ||
1674 | uint32_t i, k, loop_count, t_value, r_cnt, r_value; | ||
1675 | unsigned long p_wait, w_time, p_mask; | ||
1676 | uint32_t c_value_w, c_value_r; | ||
1677 | struct qla82xx_minidump_entry_cache *cache_hdr; | ||
1678 | int rval = QLA_ERROR; | ||
1679 | uint32_t *data_ptr = *d_ptr; | ||
1680 | |||
1681 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
1682 | cache_hdr = (struct qla82xx_minidump_entry_cache *)entry_hdr; | ||
1683 | |||
1684 | loop_count = cache_hdr->op_count; | ||
1685 | r_addr = cache_hdr->read_addr; | ||
1686 | c_addr = cache_hdr->control_addr; | ||
1687 | c_value_w = cache_hdr->cache_ctrl.write_value; | ||
1688 | |||
1689 | t_r_addr = cache_hdr->tag_reg_addr; | ||
1690 | t_value = cache_hdr->addr_ctrl.init_tag_value; | ||
1691 | r_cnt = cache_hdr->read_ctrl.read_addr_cnt; | ||
1692 | p_wait = cache_hdr->cache_ctrl.poll_wait; | ||
1693 | p_mask = cache_hdr->cache_ctrl.poll_mask; | ||
1694 | |||
1695 | for (i = 0; i < loop_count; i++) { | ||
1696 | qla4_8xxx_md_rw_32(ha, t_r_addr, t_value, 1); | ||
1697 | |||
1698 | if (c_value_w) | ||
1699 | qla4_8xxx_md_rw_32(ha, c_addr, c_value_w, 1); | ||
1700 | |||
1701 | if (p_mask) { | ||
1702 | w_time = jiffies + p_wait; | ||
1703 | do { | ||
1704 | c_value_r = qla4_8xxx_md_rw_32(ha, c_addr, | ||
1705 | 0, 0); | ||
1706 | if ((c_value_r & p_mask) == 0) { | ||
1707 | break; | ||
1708 | } else if (time_after_eq(jiffies, w_time)) { | ||
1709 | /* capturing dump failed */ | ||
1710 | return rval; | ||
1711 | } | ||
1712 | } while (1); | ||
1713 | } | ||
1714 | |||
1715 | addr = r_addr; | ||
1716 | for (k = 0; k < r_cnt; k++) { | ||
1717 | r_value = qla4_8xxx_md_rw_32(ha, addr, 0, 0); | ||
1718 | *data_ptr++ = cpu_to_le32(r_value); | ||
1719 | addr += cache_hdr->read_ctrl.read_addr_stride; | ||
1720 | } | ||
1721 | |||
1722 | t_value += cache_hdr->addr_ctrl.tag_value_stride; | ||
1723 | } | ||
1724 | *d_ptr = data_ptr; | ||
1725 | return QLA_SUCCESS; | ||
1726 | } | ||
1727 | |||
1728 | static int qla4_8xxx_minidump_process_control(struct scsi_qla_host *ha, | ||
1729 | struct qla82xx_minidump_entry_hdr *entry_hdr) | ||
1730 | { | ||
1731 | struct qla82xx_minidump_entry_crb *crb_entry; | ||
1732 | uint32_t read_value, opcode, poll_time, addr, index, rval = QLA_SUCCESS; | ||
1733 | uint32_t crb_addr; | ||
1734 | unsigned long wtime; | ||
1735 | struct qla4_8xxx_minidump_template_hdr *tmplt_hdr; | ||
1736 | int i; | ||
1737 | |||
1738 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
1739 | tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *) | ||
1740 | ha->fw_dump_tmplt_hdr; | ||
1741 | crb_entry = (struct qla82xx_minidump_entry_crb *)entry_hdr; | ||
1742 | |||
1743 | crb_addr = crb_entry->addr; | ||
1744 | for (i = 0; i < crb_entry->op_count; i++) { | ||
1745 | opcode = crb_entry->crb_ctrl.opcode; | ||
1746 | if (opcode & QLA82XX_DBG_OPCODE_WR) { | ||
1747 | qla4_8xxx_md_rw_32(ha, crb_addr, | ||
1748 | crb_entry->value_1, 1); | ||
1749 | opcode &= ~QLA82XX_DBG_OPCODE_WR; | ||
1750 | } | ||
1751 | if (opcode & QLA82XX_DBG_OPCODE_RW) { | ||
1752 | read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0); | ||
1753 | qla4_8xxx_md_rw_32(ha, crb_addr, read_value, 1); | ||
1754 | opcode &= ~QLA82XX_DBG_OPCODE_RW; | ||
1755 | } | ||
1756 | if (opcode & QLA82XX_DBG_OPCODE_AND) { | ||
1757 | read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0); | ||
1758 | read_value &= crb_entry->value_2; | ||
1759 | opcode &= ~QLA82XX_DBG_OPCODE_AND; | ||
1760 | if (opcode & QLA82XX_DBG_OPCODE_OR) { | ||
1761 | read_value |= crb_entry->value_3; | ||
1762 | opcode &= ~QLA82XX_DBG_OPCODE_OR; | ||
1763 | } | ||
1764 | qla4_8xxx_md_rw_32(ha, crb_addr, read_value, 1); | ||
1765 | } | ||
1766 | if (opcode & QLA82XX_DBG_OPCODE_OR) { | ||
1767 | read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0); | ||
1768 | read_value |= crb_entry->value_3; | ||
1769 | qla4_8xxx_md_rw_32(ha, crb_addr, read_value, 1); | ||
1770 | opcode &= ~QLA82XX_DBG_OPCODE_OR; | ||
1771 | } | ||
1772 | if (opcode & QLA82XX_DBG_OPCODE_POLL) { | ||
1773 | poll_time = crb_entry->crb_strd.poll_timeout; | ||
1774 | wtime = jiffies + poll_time; | ||
1775 | read_value = qla4_8xxx_md_rw_32(ha, crb_addr, 0, 0); | ||
1776 | |||
1777 | do { | ||
1778 | if ((read_value & crb_entry->value_2) == | ||
1779 | crb_entry->value_1) | ||
1780 | break; | ||
1781 | else if (time_after_eq(jiffies, wtime)) { | ||
1782 | /* capturing dump failed */ | ||
1783 | rval = QLA_ERROR; | ||
1784 | break; | ||
1785 | } else | ||
1786 | read_value = qla4_8xxx_md_rw_32(ha, | ||
1787 | crb_addr, 0, 0); | ||
1788 | } while (1); | ||
1789 | opcode &= ~QLA82XX_DBG_OPCODE_POLL; | ||
1790 | } | ||
1791 | |||
1792 | if (opcode & QLA82XX_DBG_OPCODE_RDSTATE) { | ||
1793 | if (crb_entry->crb_strd.state_index_a) { | ||
1794 | index = crb_entry->crb_strd.state_index_a; | ||
1795 | addr = tmplt_hdr->saved_state_array[index]; | ||
1796 | } else { | ||
1797 | addr = crb_addr; | ||
1798 | } | ||
1799 | |||
1800 | read_value = qla4_8xxx_md_rw_32(ha, addr, 0, 0); | ||
1801 | index = crb_entry->crb_ctrl.state_index_v; | ||
1802 | tmplt_hdr->saved_state_array[index] = read_value; | ||
1803 | opcode &= ~QLA82XX_DBG_OPCODE_RDSTATE; | ||
1804 | } | ||
1805 | |||
1806 | if (opcode & QLA82XX_DBG_OPCODE_WRSTATE) { | ||
1807 | if (crb_entry->crb_strd.state_index_a) { | ||
1808 | index = crb_entry->crb_strd.state_index_a; | ||
1809 | addr = tmplt_hdr->saved_state_array[index]; | ||
1810 | } else { | ||
1811 | addr = crb_addr; | ||
1812 | } | ||
1813 | |||
1814 | if (crb_entry->crb_ctrl.state_index_v) { | ||
1815 | index = crb_entry->crb_ctrl.state_index_v; | ||
1816 | read_value = | ||
1817 | tmplt_hdr->saved_state_array[index]; | ||
1818 | } else { | ||
1819 | read_value = crb_entry->value_1; | ||
1820 | } | ||
1821 | |||
1822 | qla4_8xxx_md_rw_32(ha, addr, read_value, 1); | ||
1823 | opcode &= ~QLA82XX_DBG_OPCODE_WRSTATE; | ||
1824 | } | ||
1825 | |||
1826 | if (opcode & QLA82XX_DBG_OPCODE_MDSTATE) { | ||
1827 | index = crb_entry->crb_ctrl.state_index_v; | ||
1828 | read_value = tmplt_hdr->saved_state_array[index]; | ||
1829 | read_value <<= crb_entry->crb_ctrl.shl; | ||
1830 | read_value >>= crb_entry->crb_ctrl.shr; | ||
1831 | if (crb_entry->value_2) | ||
1832 | read_value &= crb_entry->value_2; | ||
1833 | read_value |= crb_entry->value_3; | ||
1834 | read_value += crb_entry->value_1; | ||
1835 | tmplt_hdr->saved_state_array[index] = read_value; | ||
1836 | opcode &= ~QLA82XX_DBG_OPCODE_MDSTATE; | ||
1837 | } | ||
1838 | crb_addr += crb_entry->crb_strd.addr_stride; | ||
1839 | } | ||
1840 | DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s\n", __func__)); | ||
1841 | return rval; | ||
1842 | } | ||
1843 | |||
1844 | static void qla4_8xxx_minidump_process_rdocm(struct scsi_qla_host *ha, | ||
1845 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
1846 | uint32_t **d_ptr) | ||
1847 | { | ||
1848 | uint32_t r_addr, r_stride, loop_cnt, i, r_value; | ||
1849 | struct qla82xx_minidump_entry_rdocm *ocm_hdr; | ||
1850 | uint32_t *data_ptr = *d_ptr; | ||
1851 | |||
1852 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
1853 | ocm_hdr = (struct qla82xx_minidump_entry_rdocm *)entry_hdr; | ||
1854 | r_addr = ocm_hdr->read_addr; | ||
1855 | r_stride = ocm_hdr->read_addr_stride; | ||
1856 | loop_cnt = ocm_hdr->op_count; | ||
1857 | |||
1858 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1859 | "[%s]: r_addr: 0x%x, r_stride: 0x%x, loop_cnt: 0x%x\n", | ||
1860 | __func__, r_addr, r_stride, loop_cnt)); | ||
1861 | |||
1862 | for (i = 0; i < loop_cnt; i++) { | ||
1863 | r_value = readl((void __iomem *)(r_addr + ha->nx_pcibase)); | ||
1864 | *data_ptr++ = cpu_to_le32(r_value); | ||
1865 | r_addr += r_stride; | ||
1866 | } | ||
1867 | DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s datacount: 0x%lx\n", | ||
1868 | __func__, (loop_cnt * sizeof(uint32_t)))); | ||
1869 | *d_ptr = data_ptr; | ||
1870 | } | ||
1871 | |||
1872 | static void qla4_8xxx_minidump_process_rdmux(struct scsi_qla_host *ha, | ||
1873 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
1874 | uint32_t **d_ptr) | ||
1875 | { | ||
1876 | uint32_t r_addr, s_stride, s_addr, s_value, loop_cnt, i, r_value; | ||
1877 | struct qla82xx_minidump_entry_mux *mux_hdr; | ||
1878 | uint32_t *data_ptr = *d_ptr; | ||
1879 | |||
1880 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
1881 | mux_hdr = (struct qla82xx_minidump_entry_mux *)entry_hdr; | ||
1882 | r_addr = mux_hdr->read_addr; | ||
1883 | s_addr = mux_hdr->select_addr; | ||
1884 | s_stride = mux_hdr->select_value_stride; | ||
1885 | s_value = mux_hdr->select_value; | ||
1886 | loop_cnt = mux_hdr->op_count; | ||
1887 | |||
1888 | for (i = 0; i < loop_cnt; i++) { | ||
1889 | qla4_8xxx_md_rw_32(ha, s_addr, s_value, 1); | ||
1890 | r_value = qla4_8xxx_md_rw_32(ha, r_addr, 0, 0); | ||
1891 | *data_ptr++ = cpu_to_le32(s_value); | ||
1892 | *data_ptr++ = cpu_to_le32(r_value); | ||
1893 | s_value += s_stride; | ||
1894 | } | ||
1895 | *d_ptr = data_ptr; | ||
1896 | } | ||
1897 | |||
1898 | static void qla4_8xxx_minidump_process_l1cache(struct scsi_qla_host *ha, | ||
1899 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
1900 | uint32_t **d_ptr) | ||
1901 | { | ||
1902 | uint32_t addr, r_addr, c_addr, t_r_addr; | ||
1903 | uint32_t i, k, loop_count, t_value, r_cnt, r_value; | ||
1904 | uint32_t c_value_w; | ||
1905 | struct qla82xx_minidump_entry_cache *cache_hdr; | ||
1906 | uint32_t *data_ptr = *d_ptr; | ||
1907 | |||
1908 | cache_hdr = (struct qla82xx_minidump_entry_cache *)entry_hdr; | ||
1909 | loop_count = cache_hdr->op_count; | ||
1910 | r_addr = cache_hdr->read_addr; | ||
1911 | c_addr = cache_hdr->control_addr; | ||
1912 | c_value_w = cache_hdr->cache_ctrl.write_value; | ||
1913 | |||
1914 | t_r_addr = cache_hdr->tag_reg_addr; | ||
1915 | t_value = cache_hdr->addr_ctrl.init_tag_value; | ||
1916 | r_cnt = cache_hdr->read_ctrl.read_addr_cnt; | ||
1917 | |||
1918 | for (i = 0; i < loop_count; i++) { | ||
1919 | qla4_8xxx_md_rw_32(ha, t_r_addr, t_value, 1); | ||
1920 | qla4_8xxx_md_rw_32(ha, c_addr, c_value_w, 1); | ||
1921 | addr = r_addr; | ||
1922 | for (k = 0; k < r_cnt; k++) { | ||
1923 | r_value = qla4_8xxx_md_rw_32(ha, addr, 0, 0); | ||
1924 | *data_ptr++ = cpu_to_le32(r_value); | ||
1925 | addr += cache_hdr->read_ctrl.read_addr_stride; | ||
1926 | } | ||
1927 | t_value += cache_hdr->addr_ctrl.tag_value_stride; | ||
1928 | } | ||
1929 | *d_ptr = data_ptr; | ||
1930 | } | ||
1931 | |||
1932 | static void qla4_8xxx_minidump_process_queue(struct scsi_qla_host *ha, | ||
1933 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
1934 | uint32_t **d_ptr) | ||
1935 | { | ||
1936 | uint32_t s_addr, r_addr; | ||
1937 | uint32_t r_stride, r_value, r_cnt, qid = 0; | ||
1938 | uint32_t i, k, loop_cnt; | ||
1939 | struct qla82xx_minidump_entry_queue *q_hdr; | ||
1940 | uint32_t *data_ptr = *d_ptr; | ||
1941 | |||
1942 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
1943 | q_hdr = (struct qla82xx_minidump_entry_queue *)entry_hdr; | ||
1944 | s_addr = q_hdr->select_addr; | ||
1945 | r_cnt = q_hdr->rd_strd.read_addr_cnt; | ||
1946 | r_stride = q_hdr->rd_strd.read_addr_stride; | ||
1947 | loop_cnt = q_hdr->op_count; | ||
1948 | |||
1949 | for (i = 0; i < loop_cnt; i++) { | ||
1950 | qla4_8xxx_md_rw_32(ha, s_addr, qid, 1); | ||
1951 | r_addr = q_hdr->read_addr; | ||
1952 | for (k = 0; k < r_cnt; k++) { | ||
1953 | r_value = qla4_8xxx_md_rw_32(ha, r_addr, 0, 0); | ||
1954 | *data_ptr++ = cpu_to_le32(r_value); | ||
1955 | r_addr += r_stride; | ||
1956 | } | ||
1957 | qid += q_hdr->q_strd.queue_id_stride; | ||
1958 | } | ||
1959 | *d_ptr = data_ptr; | ||
1960 | } | ||
1961 | |||
1962 | #define MD_DIRECT_ROM_WINDOW 0x42110030 | ||
1963 | #define MD_DIRECT_ROM_READ_BASE 0x42150000 | ||
1964 | |||
1965 | static void qla4_8xxx_minidump_process_rdrom(struct scsi_qla_host *ha, | ||
1966 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
1967 | uint32_t **d_ptr) | ||
1968 | { | ||
1969 | uint32_t r_addr, r_value; | ||
1970 | uint32_t i, loop_cnt; | ||
1971 | struct qla82xx_minidump_entry_rdrom *rom_hdr; | ||
1972 | uint32_t *data_ptr = *d_ptr; | ||
1973 | |||
1974 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
1975 | rom_hdr = (struct qla82xx_minidump_entry_rdrom *)entry_hdr; | ||
1976 | r_addr = rom_hdr->read_addr; | ||
1977 | loop_cnt = rom_hdr->read_data_size/sizeof(uint32_t); | ||
1978 | |||
1979 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1980 | "[%s]: flash_addr: 0x%x, read_data_size: 0x%x\n", | ||
1981 | __func__, r_addr, loop_cnt)); | ||
1982 | |||
1983 | for (i = 0; i < loop_cnt; i++) { | ||
1984 | qla4_8xxx_md_rw_32(ha, MD_DIRECT_ROM_WINDOW, | ||
1985 | (r_addr & 0xFFFF0000), 1); | ||
1986 | r_value = qla4_8xxx_md_rw_32(ha, | ||
1987 | MD_DIRECT_ROM_READ_BASE + | ||
1988 | (r_addr & 0x0000FFFF), 0, 0); | ||
1989 | *data_ptr++ = cpu_to_le32(r_value); | ||
1990 | r_addr += sizeof(uint32_t); | ||
1991 | } | ||
1992 | *d_ptr = data_ptr; | ||
1993 | } | ||
1994 | |||
1995 | #define MD_MIU_TEST_AGT_CTRL 0x41000090 | ||
1996 | #define MD_MIU_TEST_AGT_ADDR_LO 0x41000094 | ||
1997 | #define MD_MIU_TEST_AGT_ADDR_HI 0x41000098 | ||
1998 | |||
1999 | static int qla4_8xxx_minidump_process_rdmem(struct scsi_qla_host *ha, | ||
2000 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
2001 | uint32_t **d_ptr) | ||
2002 | { | ||
2003 | uint32_t r_addr, r_value, r_data; | ||
2004 | uint32_t i, j, loop_cnt; | ||
2005 | struct qla82xx_minidump_entry_rdmem *m_hdr; | ||
2006 | unsigned long flags; | ||
2007 | uint32_t *data_ptr = *d_ptr; | ||
2008 | |||
2009 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
2010 | m_hdr = (struct qla82xx_minidump_entry_rdmem *)entry_hdr; | ||
2011 | r_addr = m_hdr->read_addr; | ||
2012 | loop_cnt = m_hdr->read_data_size/16; | ||
2013 | |||
2014 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2015 | "[%s]: Read addr: 0x%x, read_data_size: 0x%x\n", | ||
2016 | __func__, r_addr, m_hdr->read_data_size)); | ||
2017 | |||
2018 | if (r_addr & 0xf) { | ||
2019 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2020 | "[%s]: Read addr 0x%x not 16 bytes alligned\n", | ||
2021 | __func__, r_addr)); | ||
2022 | return QLA_ERROR; | ||
2023 | } | ||
2024 | |||
2025 | if (m_hdr->read_data_size % 16) { | ||
2026 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2027 | "[%s]: Read data[0x%x] not multiple of 16 bytes\n", | ||
2028 | __func__, m_hdr->read_data_size)); | ||
2029 | return QLA_ERROR; | ||
2030 | } | ||
2031 | |||
2032 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2033 | "[%s]: rdmem_addr: 0x%x, read_data_size: 0x%x, loop_cnt: 0x%x\n", | ||
2034 | __func__, r_addr, m_hdr->read_data_size, loop_cnt)); | ||
2035 | |||
2036 | write_lock_irqsave(&ha->hw_lock, flags); | ||
2037 | for (i = 0; i < loop_cnt; i++) { | ||
2038 | qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_ADDR_LO, r_addr, 1); | ||
2039 | r_value = 0; | ||
2040 | qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_ADDR_HI, r_value, 1); | ||
2041 | r_value = MIU_TA_CTL_ENABLE; | ||
2042 | qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, r_value, 1); | ||
2043 | r_value = MIU_TA_CTL_START | MIU_TA_CTL_ENABLE; | ||
2044 | qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, r_value, 1); | ||
2045 | |||
2046 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
2047 | r_value = qla4_8xxx_md_rw_32(ha, MD_MIU_TEST_AGT_CTRL, | ||
2048 | 0, 0); | ||
2049 | if ((r_value & MIU_TA_CTL_BUSY) == 0) | ||
2050 | break; | ||
2051 | } | ||
2052 | |||
2053 | if (j >= MAX_CTL_CHECK) { | ||
2054 | printk_ratelimited(KERN_ERR | ||
2055 | "%s: failed to read through agent\n", | ||
2056 | __func__); | ||
2057 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
2058 | return QLA_SUCCESS; | ||
2059 | } | ||
2060 | |||
2061 | for (j = 0; j < 4; j++) { | ||
2062 | r_data = qla4_8xxx_md_rw_32(ha, | ||
2063 | MD_MIU_TEST_AGT_RDDATA[j], | ||
2064 | 0, 0); | ||
2065 | *data_ptr++ = cpu_to_le32(r_data); | ||
2066 | } | ||
2067 | |||
2068 | r_addr += 16; | ||
2069 | } | ||
2070 | write_unlock_irqrestore(&ha->hw_lock, flags); | ||
2071 | |||
2072 | DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s datacount: 0x%x\n", | ||
2073 | __func__, (loop_cnt * 16))); | ||
2074 | |||
2075 | *d_ptr = data_ptr; | ||
2076 | return QLA_SUCCESS; | ||
2077 | } | ||
2078 | |||
2079 | static void ql4_8xxx_mark_entry_skipped(struct scsi_qla_host *ha, | ||
2080 | struct qla82xx_minidump_entry_hdr *entry_hdr, | ||
2081 | int index) | ||
2082 | { | ||
2083 | entry_hdr->d_ctrl.driver_flags |= QLA82XX_DBG_SKIPPED_FLAG; | ||
2084 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2085 | "scsi(%ld): Skipping entry[%d]: ETYPE[0x%x]-ELEVEL[0x%x]\n", | ||
2086 | ha->host_no, index, entry_hdr->entry_type, | ||
2087 | entry_hdr->d_ctrl.entry_capture_mask)); | ||
2088 | } | ||
2089 | |||
2090 | /** | ||
2091 | * qla82xx_collect_md_data - Retrieve firmware minidump data. | ||
2092 | * @ha: pointer to adapter structure | ||
2093 | **/ | ||
2094 | static int qla4_8xxx_collect_md_data(struct scsi_qla_host *ha) | ||
2095 | { | ||
2096 | int num_entry_hdr = 0; | ||
2097 | struct qla82xx_minidump_entry_hdr *entry_hdr; | ||
2098 | struct qla4_8xxx_minidump_template_hdr *tmplt_hdr; | ||
2099 | uint32_t *data_ptr; | ||
2100 | uint32_t data_collected = 0; | ||
2101 | int i, rval = QLA_ERROR; | ||
2102 | uint64_t now; | ||
2103 | uint32_t timestamp; | ||
2104 | |||
2105 | if (!ha->fw_dump) { | ||
2106 | ql4_printk(KERN_INFO, ha, "%s(%ld) No buffer to dump\n", | ||
2107 | __func__, ha->host_no); | ||
2108 | return rval; | ||
2109 | } | ||
2110 | |||
2111 | tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *) | ||
2112 | ha->fw_dump_tmplt_hdr; | ||
2113 | data_ptr = (uint32_t *)((uint8_t *)ha->fw_dump + | ||
2114 | ha->fw_dump_tmplt_size); | ||
2115 | data_collected += ha->fw_dump_tmplt_size; | ||
2116 | |||
2117 | num_entry_hdr = tmplt_hdr->num_of_entries; | ||
2118 | ql4_printk(KERN_INFO, ha, "[%s]: starting data ptr: %p\n", | ||
2119 | __func__, data_ptr); | ||
2120 | ql4_printk(KERN_INFO, ha, | ||
2121 | "[%s]: no of entry headers in Template: 0x%x\n", | ||
2122 | __func__, num_entry_hdr); | ||
2123 | ql4_printk(KERN_INFO, ha, "[%s]: Capture Mask obtained: 0x%x\n", | ||
2124 | __func__, ha->fw_dump_capture_mask); | ||
2125 | ql4_printk(KERN_INFO, ha, "[%s]: Total_data_size 0x%x, %d obtained\n", | ||
2126 | __func__, ha->fw_dump_size, ha->fw_dump_size); | ||
2127 | |||
2128 | /* Update current timestamp before taking dump */ | ||
2129 | now = get_jiffies_64(); | ||
2130 | timestamp = (u32)(jiffies_to_msecs(now) / 1000); | ||
2131 | tmplt_hdr->driver_timestamp = timestamp; | ||
2132 | |||
2133 | entry_hdr = (struct qla82xx_minidump_entry_hdr *) | ||
2134 | (((uint8_t *)ha->fw_dump_tmplt_hdr) + | ||
2135 | tmplt_hdr->first_entry_offset); | ||
2136 | |||
2137 | /* Walk through the entry headers - validate/perform required action */ | ||
2138 | for (i = 0; i < num_entry_hdr; i++) { | ||
2139 | if (data_collected >= ha->fw_dump_size) { | ||
2140 | ql4_printk(KERN_INFO, ha, | ||
2141 | "Data collected: [0x%x], Total Dump size: [0x%x]\n", | ||
2142 | data_collected, ha->fw_dump_size); | ||
2143 | return rval; | ||
2144 | } | ||
2145 | |||
2146 | if (!(entry_hdr->d_ctrl.entry_capture_mask & | ||
2147 | ha->fw_dump_capture_mask)) { | ||
2148 | entry_hdr->d_ctrl.driver_flags |= | ||
2149 | QLA82XX_DBG_SKIPPED_FLAG; | ||
2150 | goto skip_nxt_entry; | ||
2151 | } | ||
2152 | |||
2153 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2154 | "Data collected: [0x%x], Dump size left:[0x%x]\n", | ||
2155 | data_collected, | ||
2156 | (ha->fw_dump_size - data_collected))); | ||
2157 | |||
2158 | /* Decode the entry type and take required action to capture | ||
2159 | * debug data | ||
2160 | */ | ||
2161 | switch (entry_hdr->entry_type) { | ||
2162 | case QLA82XX_RDEND: | ||
2163 | ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
2164 | break; | ||
2165 | case QLA82XX_CNTRL: | ||
2166 | rval = qla4_8xxx_minidump_process_control(ha, | ||
2167 | entry_hdr); | ||
2168 | if (rval != QLA_SUCCESS) { | ||
2169 | ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
2170 | goto md_failed; | ||
2171 | } | ||
2172 | break; | ||
2173 | case QLA82XX_RDCRB: | ||
2174 | qla4_8xxx_minidump_process_rdcrb(ha, entry_hdr, | ||
2175 | &data_ptr); | ||
2176 | break; | ||
2177 | case QLA82XX_RDMEM: | ||
2178 | rval = qla4_8xxx_minidump_process_rdmem(ha, entry_hdr, | ||
2179 | &data_ptr); | ||
2180 | if (rval != QLA_SUCCESS) { | ||
2181 | ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
2182 | goto md_failed; | ||
2183 | } | ||
2184 | break; | ||
2185 | case QLA82XX_BOARD: | ||
2186 | case QLA82XX_RDROM: | ||
2187 | qla4_8xxx_minidump_process_rdrom(ha, entry_hdr, | ||
2188 | &data_ptr); | ||
2189 | break; | ||
2190 | case QLA82XX_L2DTG: | ||
2191 | case QLA82XX_L2ITG: | ||
2192 | case QLA82XX_L2DAT: | ||
2193 | case QLA82XX_L2INS: | ||
2194 | rval = qla4_8xxx_minidump_process_l2tag(ha, entry_hdr, | ||
2195 | &data_ptr); | ||
2196 | if (rval != QLA_SUCCESS) { | ||
2197 | ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
2198 | goto md_failed; | ||
2199 | } | ||
2200 | break; | ||
2201 | case QLA82XX_L1DAT: | ||
2202 | case QLA82XX_L1INS: | ||
2203 | qla4_8xxx_minidump_process_l1cache(ha, entry_hdr, | ||
2204 | &data_ptr); | ||
2205 | break; | ||
2206 | case QLA82XX_RDOCM: | ||
2207 | qla4_8xxx_minidump_process_rdocm(ha, entry_hdr, | ||
2208 | &data_ptr); | ||
2209 | break; | ||
2210 | case QLA82XX_RDMUX: | ||
2211 | qla4_8xxx_minidump_process_rdmux(ha, entry_hdr, | ||
2212 | &data_ptr); | ||
2213 | break; | ||
2214 | case QLA82XX_QUEUE: | ||
2215 | qla4_8xxx_minidump_process_queue(ha, entry_hdr, | ||
2216 | &data_ptr); | ||
2217 | break; | ||
2218 | case QLA82XX_RDNOP: | ||
2219 | default: | ||
2220 | ql4_8xxx_mark_entry_skipped(ha, entry_hdr, i); | ||
2221 | break; | ||
2222 | } | ||
2223 | |||
2224 | data_collected = (uint8_t *)data_ptr - | ||
2225 | ((uint8_t *)((uint8_t *)ha->fw_dump + | ||
2226 | ha->fw_dump_tmplt_size)); | ||
2227 | skip_nxt_entry: | ||
2228 | /* next entry in the template */ | ||
2229 | entry_hdr = (struct qla82xx_minidump_entry_hdr *) | ||
2230 | (((uint8_t *)entry_hdr) + | ||
2231 | entry_hdr->entry_size); | ||
2232 | } | ||
2233 | |||
2234 | if ((data_collected + ha->fw_dump_tmplt_size) != ha->fw_dump_size) { | ||
2235 | ql4_printk(KERN_INFO, ha, | ||
2236 | "Dump data mismatch: Data collected: [0x%x], total_data_size:[0x%x]\n", | ||
2237 | data_collected, ha->fw_dump_size); | ||
2238 | goto md_failed; | ||
2239 | } | ||
2240 | |||
2241 | DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s Last entry: 0x%x\n", | ||
2242 | __func__, i)); | ||
2243 | md_failed: | ||
2244 | return rval; | ||
2245 | } | ||
2246 | |||
2247 | /** | ||
2248 | * qla4_8xxx_uevent_emit - Send uevent when the firmware dump is ready. | ||
2249 | * @ha: pointer to adapter structure | ||
2250 | **/ | ||
2251 | static void qla4_8xxx_uevent_emit(struct scsi_qla_host *ha, u32 code) | ||
2252 | { | ||
2253 | char event_string[40]; | ||
2254 | char *envp[] = { event_string, NULL }; | ||
2255 | |||
2256 | switch (code) { | ||
2257 | case QL4_UEVENT_CODE_FW_DUMP: | ||
2258 | snprintf(event_string, sizeof(event_string), "FW_DUMP=%ld", | ||
2259 | ha->host_no); | ||
2260 | break; | ||
2261 | default: | ||
2262 | /*do nothing*/ | ||
2263 | break; | ||
2264 | } | ||
2265 | |||
2266 | kobject_uevent_env(&(&ha->pdev->dev)->kobj, KOBJ_CHANGE, envp); | ||
2267 | } | ||
2268 | |||
1604 | /** | 2269 | /** |
1605 | * qla4_8xxx_device_bootstrap - Initialize device, set DEV_READY, start fw | 2270 | * qla4_8xxx_device_bootstrap - Initialize device, set DEV_READY, start fw |
1606 | * @ha: pointer to adapter structure | 2271 | * @ha: pointer to adapter structure |
@@ -1659,6 +2324,15 @@ dev_initialize: | |||
1659 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, QLA82XX_IDC_VERSION); | 2324 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DRV_IDC_VERSION, QLA82XX_IDC_VERSION); |
1660 | 2325 | ||
1661 | qla4_8xxx_idc_unlock(ha); | 2326 | qla4_8xxx_idc_unlock(ha); |
2327 | if (ql4xenablemd && test_bit(AF_FW_RECOVERY, &ha->flags) && | ||
2328 | !test_and_set_bit(AF_82XX_FW_DUMPED, &ha->flags)) { | ||
2329 | if (!qla4_8xxx_collect_md_data(ha)) { | ||
2330 | qla4_8xxx_uevent_emit(ha, QL4_UEVENT_CODE_FW_DUMP); | ||
2331 | } else { | ||
2332 | ql4_printk(KERN_INFO, ha, "Unable to collect minidump\n"); | ||
2333 | clear_bit(AF_82XX_FW_DUMPED, &ha->flags); | ||
2334 | } | ||
2335 | } | ||
1662 | rval = qla4_8xxx_try_start_fw(ha); | 2336 | rval = qla4_8xxx_try_start_fw(ha); |
1663 | qla4_8xxx_idc_lock(ha); | 2337 | qla4_8xxx_idc_lock(ha); |
1664 | 2338 | ||
@@ -1686,6 +2360,7 @@ static void | |||
1686 | qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) | 2360 | qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) |
1687 | { | 2361 | { |
1688 | uint32_t dev_state, drv_state, drv_active; | 2362 | uint32_t dev_state, drv_state, drv_active; |
2363 | uint32_t active_mask = 0xFFFFFFFF; | ||
1689 | unsigned long reset_timeout; | 2364 | unsigned long reset_timeout; |
1690 | 2365 | ||
1691 | ql4_printk(KERN_INFO, ha, | 2366 | ql4_printk(KERN_INFO, ha, |
@@ -1697,7 +2372,14 @@ qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) | |||
1697 | qla4_8xxx_idc_lock(ha); | 2372 | qla4_8xxx_idc_lock(ha); |
1698 | } | 2373 | } |
1699 | 2374 | ||
1700 | qla4_8xxx_set_rst_ready(ha); | 2375 | if (!test_bit(AF_82XX_RST_OWNER, &ha->flags)) { |
2376 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
2377 | "%s(%ld): reset acknowledged\n", | ||
2378 | __func__, ha->host_no)); | ||
2379 | qla4_8xxx_set_rst_ready(ha); | ||
2380 | } else { | ||
2381 | active_mask = (~(1 << (ha->func_num * 4))); | ||
2382 | } | ||
1701 | 2383 | ||
1702 | /* wait for 10 seconds for reset ack from all functions */ | 2384 | /* wait for 10 seconds for reset ack from all functions */ |
1703 | reset_timeout = jiffies + (ha->nx_reset_timeout * HZ); | 2385 | reset_timeout = jiffies + (ha->nx_reset_timeout * HZ); |
@@ -1709,12 +2391,24 @@ qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) | |||
1709 | "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n", | 2391 | "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n", |
1710 | __func__, ha->host_no, drv_state, drv_active); | 2392 | __func__, ha->host_no, drv_state, drv_active); |
1711 | 2393 | ||
1712 | while (drv_state != drv_active) { | 2394 | while (drv_state != (drv_active & active_mask)) { |
1713 | if (time_after_eq(jiffies, reset_timeout)) { | 2395 | if (time_after_eq(jiffies, reset_timeout)) { |
1714 | printk("%s: RESET TIMEOUT!\n", DRIVER_NAME); | 2396 | ql4_printk(KERN_INFO, ha, |
2397 | "%s: RESET TIMEOUT! drv_state: 0x%08x, drv_active: 0x%08x\n", | ||
2398 | DRIVER_NAME, drv_state, drv_active); | ||
1715 | break; | 2399 | break; |
1716 | } | 2400 | } |
1717 | 2401 | ||
2402 | /* | ||
2403 | * When reset_owner times out, check which functions | ||
2404 | * acked/did not ack | ||
2405 | */ | ||
2406 | if (test_bit(AF_82XX_RST_OWNER, &ha->flags)) { | ||
2407 | ql4_printk(KERN_INFO, ha, | ||
2408 | "%s(%ld): drv_state = 0x%x, drv_active = 0x%x\n", | ||
2409 | __func__, ha->host_no, drv_state, | ||
2410 | drv_active); | ||
2411 | } | ||
1718 | qla4_8xxx_idc_unlock(ha); | 2412 | qla4_8xxx_idc_unlock(ha); |
1719 | msleep(1000); | 2413 | msleep(1000); |
1720 | qla4_8xxx_idc_lock(ha); | 2414 | qla4_8xxx_idc_lock(ha); |
@@ -1723,14 +2417,18 @@ qla4_8xxx_need_reset_handler(struct scsi_qla_host *ha) | |||
1723 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); | 2417 | drv_active = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DRV_ACTIVE); |
1724 | } | 2418 | } |
1725 | 2419 | ||
2420 | /* Clear RESET OWNER as we are not going to use it any further */ | ||
2421 | clear_bit(AF_82XX_RST_OWNER, &ha->flags); | ||
2422 | |||
1726 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | 2423 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); |
1727 | ql4_printk(KERN_INFO, ha, "3:Device state is 0x%x = %s\n", dev_state, | 2424 | ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", dev_state, |
1728 | dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); | 2425 | dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); |
1729 | 2426 | ||
1730 | /* Force to DEV_COLD unless someone else is starting a reset */ | 2427 | /* Force to DEV_COLD unless someone else is starting a reset */ |
1731 | if (dev_state != QLA82XX_DEV_INITIALIZING) { | 2428 | if (dev_state != QLA82XX_DEV_INITIALIZING) { |
1732 | ql4_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n"); | 2429 | ql4_printk(KERN_INFO, ha, "HW State: COLD/RE-INIT\n"); |
1733 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD); | 2430 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_COLD); |
2431 | qla4_8xxx_set_rst_ready(ha); | ||
1734 | } | 2432 | } |
1735 | } | 2433 | } |
1736 | 2434 | ||
@@ -1765,8 +2463,9 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) | |||
1765 | } | 2463 | } |
1766 | 2464 | ||
1767 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | 2465 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); |
1768 | ql4_printk(KERN_INFO, ha, "1:Device state is 0x%x = %s\n", dev_state, | 2466 | DEBUG2(ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", |
1769 | dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); | 2467 | dev_state, dev_state < MAX_STATES ? |
2468 | qdev_state[dev_state] : "Unknown")); | ||
1770 | 2469 | ||
1771 | /* wait for 30 seconds for device to go ready */ | 2470 | /* wait for 30 seconds for device to go ready */ |
1772 | dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); | 2471 | dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ); |
@@ -1775,15 +2474,19 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha) | |||
1775 | while (1) { | 2474 | while (1) { |
1776 | 2475 | ||
1777 | if (time_after_eq(jiffies, dev_init_timeout)) { | 2476 | if (time_after_eq(jiffies, dev_init_timeout)) { |
1778 | ql4_printk(KERN_WARNING, ha, "Device init failed!\n"); | 2477 | ql4_printk(KERN_WARNING, ha, |
2478 | "%s: Device Init Failed 0x%x = %s\n", | ||
2479 | DRIVER_NAME, | ||
2480 | dev_state, dev_state < MAX_STATES ? | ||
2481 | qdev_state[dev_state] : "Unknown"); | ||
1779 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | 2482 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, |
1780 | QLA82XX_DEV_FAILED); | 2483 | QLA82XX_DEV_FAILED); |
1781 | } | 2484 | } |
1782 | 2485 | ||
1783 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); | 2486 | dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE); |
1784 | ql4_printk(KERN_INFO, ha, | 2487 | ql4_printk(KERN_INFO, ha, "Device state is 0x%x = %s\n", |
1785 | "2:Device state is 0x%x = %s\n", dev_state, | 2488 | dev_state, dev_state < MAX_STATES ? |
1786 | dev_state < MAX_STATES ? qdev_state[dev_state] : "Unknown"); | 2489 | qdev_state[dev_state] : "Unknown"); |
1787 | 2490 | ||
1788 | /* NOTE: Make sure idc unlocked upon exit of switch statement */ | 2491 | /* NOTE: Make sure idc unlocked upon exit of switch statement */ |
1789 | switch (dev_state) { | 2492 | switch (dev_state) { |
@@ -2184,6 +2887,7 @@ qla4_8xxx_isp_reset(struct scsi_qla_host *ha) | |||
2184 | ql4_printk(KERN_INFO, ha, "HW State: NEED RESET\n"); | 2887 | ql4_printk(KERN_INFO, ha, "HW State: NEED RESET\n"); |
2185 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | 2888 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, |
2186 | QLA82XX_DEV_NEED_RESET); | 2889 | QLA82XX_DEV_NEED_RESET); |
2890 | set_bit(AF_82XX_RST_OWNER, &ha->flags); | ||
2187 | } else | 2891 | } else |
2188 | ql4_printk(KERN_INFO, ha, "HW State: DEVICE INITIALIZING\n"); | 2892 | ql4_printk(KERN_INFO, ha, "HW State: DEVICE INITIALIZING\n"); |
2189 | 2893 | ||
@@ -2195,8 +2899,10 @@ qla4_8xxx_isp_reset(struct scsi_qla_host *ha) | |||
2195 | qla4_8xxx_clear_rst_ready(ha); | 2899 | qla4_8xxx_clear_rst_ready(ha); |
2196 | qla4_8xxx_idc_unlock(ha); | 2900 | qla4_8xxx_idc_unlock(ha); |
2197 | 2901 | ||
2198 | if (rval == QLA_SUCCESS) | 2902 | if (rval == QLA_SUCCESS) { |
2903 | ql4_printk(KERN_INFO, ha, "Clearing AF_RECOVERY in qla4_8xxx_isp_reset\n"); | ||
2199 | clear_bit(AF_FW_RECOVERY, &ha->flags); | 2904 | clear_bit(AF_FW_RECOVERY, &ha->flags); |
2905 | } | ||
2200 | 2906 | ||
2201 | return rval; | 2907 | return rval; |
2202 | } | 2908 | } |