diff options
author | Santosh Vernekar <santosh.vernekar@qlogic.com> | 2013-08-23 03:40:18 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-09-03 10:27:56 -0400 |
commit | 41f79bde1d4e18fcd336dd5b6999ab9588daea54 (patch) | |
tree | 11789ccc92b3b58790105734c205a633829cb36a | |
parent | 909ee499c1c85e99ed3f9e99caf13a89f4de3d3a (diff) |
[SCSI] qla4xxx: Add pex-dma support for capturing minidump
Add pex-dma support for ISP8324 and ISP8042 to improve
the minidump capture time.
Signed-off-by: Santosh Vernekar <santosh.vernekar@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_83xx.c | 4 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_83xx.h | 34 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_glbl.h | 2 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_nx.c | 226 |
4 files changed, 263 insertions, 3 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_83xx.c b/drivers/scsi/qla4xxx/ql4_83xx.c index 9be4f8f356b2..8196c2f7915c 100644 --- a/drivers/scsi/qla4xxx/ql4_83xx.c +++ b/drivers/scsi/qla4xxx/ql4_83xx.c | |||
@@ -259,8 +259,8 @@ void qla4_83xx_rom_lock_recovery(struct scsi_qla_host *ha) | |||
259 | * Return: On success return QLA_SUCCESS | 259 | * Return: On success return QLA_SUCCESS |
260 | * On error return QLA_ERROR | 260 | * On error return QLA_ERROR |
261 | **/ | 261 | **/ |
262 | static int qla4_83xx_ms_mem_write_128b(struct scsi_qla_host *ha, uint64_t addr, | 262 | int qla4_83xx_ms_mem_write_128b(struct scsi_qla_host *ha, uint64_t addr, |
263 | uint32_t *data, uint32_t count) | 263 | uint32_t *data, uint32_t count) |
264 | { | 264 | { |
265 | int i, j; | 265 | int i, j; |
266 | uint32_t agt_ctrl; | 266 | uint32_t agt_ctrl; |
diff --git a/drivers/scsi/qla4xxx/ql4_83xx.h b/drivers/scsi/qla4xxx/ql4_83xx.h index 1b8c544a03e7..a0de6e25ea5a 100644 --- a/drivers/scsi/qla4xxx/ql4_83xx.h +++ b/drivers/scsi/qla4xxx/ql4_83xx.h | |||
@@ -290,4 +290,38 @@ struct qla4_83xx_idc_information { | |||
290 | uint32_t info3; /* IDC additional info */ | 290 | uint32_t info3; /* IDC additional info */ |
291 | }; | 291 | }; |
292 | 292 | ||
293 | #define QLA83XX_PEX_DMA_ENGINE_INDEX 8 | ||
294 | #define QLA83XX_PEX_DMA_BASE_ADDRESS 0x77320000 | ||
295 | #define QLA83XX_PEX_DMA_NUM_OFFSET 0x10000 | ||
296 | #define QLA83XX_PEX_DMA_CMD_ADDR_LOW 0x0 | ||
297 | #define QLA83XX_PEX_DMA_CMD_ADDR_HIGH 0x04 | ||
298 | #define QLA83XX_PEX_DMA_CMD_STS_AND_CNTRL 0x08 | ||
299 | |||
300 | #define QLA83XX_PEX_DMA_READ_SIZE (16 * 1024) | ||
301 | #define QLA83XX_PEX_DMA_MAX_WAIT (100 * 100) /* Max wait of 100 msecs */ | ||
302 | |||
303 | /* Read Memory: For Pex-DMA */ | ||
304 | struct qla4_83xx_minidump_entry_rdmem_pex_dma { | ||
305 | struct qla8xxx_minidump_entry_hdr h; | ||
306 | uint32_t desc_card_addr; | ||
307 | uint16_t dma_desc_cmd; | ||
308 | uint8_t rsvd[2]; | ||
309 | uint32_t start_dma_cmd; | ||
310 | uint8_t rsvd2[12]; | ||
311 | uint32_t read_addr; | ||
312 | uint32_t read_data_size; | ||
313 | }; | ||
314 | |||
315 | struct qla4_83xx_pex_dma_descriptor { | ||
316 | struct { | ||
317 | uint32_t read_data_size; /* 0-23: size, 24-31: rsvd */ | ||
318 | uint8_t rsvd[2]; | ||
319 | uint16_t dma_desc_cmd; | ||
320 | } cmd; | ||
321 | uint64_t src_addr; | ||
322 | uint64_t dma_bus_addr; /* 0-3: desc-cmd, 4-7: pci-func, | ||
323 | * 8-15: desc-cmd */ | ||
324 | uint8_t rsvd[24]; | ||
325 | } __packed; | ||
326 | |||
293 | #endif | 327 | #endif |
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index cec80b6c1f83..e6f2a2669dbd 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
@@ -272,6 +272,8 @@ int qla4xxx_set_acb(struct scsi_qla_host *ha, uint32_t *mbox_cmd, | |||
272 | int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma, | 272 | int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma, |
273 | uint32_t acb_type, uint32_t len); | 273 | uint32_t acb_type, uint32_t len); |
274 | int qla4_84xx_config_acb(struct scsi_qla_host *ha, int acb_config); | 274 | int qla4_84xx_config_acb(struct scsi_qla_host *ha, int acb_config); |
275 | int qla4_83xx_ms_mem_write_128b(struct scsi_qla_host *ha, | ||
276 | uint64_t addr, uint32_t *data, uint32_t count); | ||
275 | 277 | ||
276 | extern int ql4xextended_error_logging; | 278 | extern int ql4xextended_error_logging; |
277 | extern int ql4xdontresethba; | 279 | extern int ql4xdontresethba; |
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index 67831aa458b2..c41362c29fc8 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c | |||
@@ -1737,6 +1737,208 @@ static void qla4_8xxx_minidump_process_rdcrb(struct scsi_qla_host *ha, | |||
1737 | *d_ptr = data_ptr; | 1737 | *d_ptr = data_ptr; |
1738 | } | 1738 | } |
1739 | 1739 | ||
1740 | static int qla4_83xx_check_dma_engine_state(struct scsi_qla_host *ha) | ||
1741 | { | ||
1742 | int rval = QLA_SUCCESS; | ||
1743 | uint32_t dma_eng_num = 0, cmd_sts_and_cntrl = 0; | ||
1744 | uint64_t dma_base_addr = 0; | ||
1745 | struct qla4_8xxx_minidump_template_hdr *tmplt_hdr = NULL; | ||
1746 | |||
1747 | tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *) | ||
1748 | ha->fw_dump_tmplt_hdr; | ||
1749 | dma_eng_num = | ||
1750 | tmplt_hdr->saved_state_array[QLA83XX_PEX_DMA_ENGINE_INDEX]; | ||
1751 | dma_base_addr = QLA83XX_PEX_DMA_BASE_ADDRESS + | ||
1752 | (dma_eng_num * QLA83XX_PEX_DMA_NUM_OFFSET); | ||
1753 | |||
1754 | /* Read the pex-dma's command-status-and-control register. */ | ||
1755 | rval = ha->isp_ops->rd_reg_indirect(ha, | ||
1756 | (dma_base_addr + QLA83XX_PEX_DMA_CMD_STS_AND_CNTRL), | ||
1757 | &cmd_sts_and_cntrl); | ||
1758 | |||
1759 | if (rval) | ||
1760 | return QLA_ERROR; | ||
1761 | |||
1762 | /* Check if requested pex-dma engine is available. */ | ||
1763 | if (cmd_sts_and_cntrl & BIT_31) | ||
1764 | return QLA_SUCCESS; | ||
1765 | else | ||
1766 | return QLA_ERROR; | ||
1767 | } | ||
1768 | |||
1769 | static int qla4_83xx_start_pex_dma(struct scsi_qla_host *ha, | ||
1770 | struct qla4_83xx_minidump_entry_rdmem_pex_dma *m_hdr) | ||
1771 | { | ||
1772 | int rval = QLA_SUCCESS, wait = 0; | ||
1773 | uint32_t dma_eng_num = 0, cmd_sts_and_cntrl = 0; | ||
1774 | uint64_t dma_base_addr = 0; | ||
1775 | struct qla4_8xxx_minidump_template_hdr *tmplt_hdr = NULL; | ||
1776 | |||
1777 | tmplt_hdr = (struct qla4_8xxx_minidump_template_hdr *) | ||
1778 | ha->fw_dump_tmplt_hdr; | ||
1779 | dma_eng_num = | ||
1780 | tmplt_hdr->saved_state_array[QLA83XX_PEX_DMA_ENGINE_INDEX]; | ||
1781 | dma_base_addr = QLA83XX_PEX_DMA_BASE_ADDRESS + | ||
1782 | (dma_eng_num * QLA83XX_PEX_DMA_NUM_OFFSET); | ||
1783 | |||
1784 | rval = ha->isp_ops->wr_reg_indirect(ha, | ||
1785 | dma_base_addr + QLA83XX_PEX_DMA_CMD_ADDR_LOW, | ||
1786 | m_hdr->desc_card_addr); | ||
1787 | if (rval) | ||
1788 | goto error_exit; | ||
1789 | |||
1790 | rval = ha->isp_ops->wr_reg_indirect(ha, | ||
1791 | dma_base_addr + QLA83XX_PEX_DMA_CMD_ADDR_HIGH, 0); | ||
1792 | if (rval) | ||
1793 | goto error_exit; | ||
1794 | |||
1795 | rval = ha->isp_ops->wr_reg_indirect(ha, | ||
1796 | dma_base_addr + QLA83XX_PEX_DMA_CMD_STS_AND_CNTRL, | ||
1797 | m_hdr->start_dma_cmd); | ||
1798 | if (rval) | ||
1799 | goto error_exit; | ||
1800 | |||
1801 | /* Wait for dma operation to complete. */ | ||
1802 | for (wait = 0; wait < QLA83XX_PEX_DMA_MAX_WAIT; wait++) { | ||
1803 | rval = ha->isp_ops->rd_reg_indirect(ha, | ||
1804 | (dma_base_addr + QLA83XX_PEX_DMA_CMD_STS_AND_CNTRL), | ||
1805 | &cmd_sts_and_cntrl); | ||
1806 | if (rval) | ||
1807 | goto error_exit; | ||
1808 | |||
1809 | if ((cmd_sts_and_cntrl & BIT_1) == 0) | ||
1810 | break; | ||
1811 | else | ||
1812 | udelay(10); | ||
1813 | } | ||
1814 | |||
1815 | /* Wait a max of 100 ms, otherwise fallback to rdmem entry read */ | ||
1816 | if (wait >= QLA83XX_PEX_DMA_MAX_WAIT) { | ||
1817 | rval = QLA_ERROR; | ||
1818 | goto error_exit; | ||
1819 | } | ||
1820 | |||
1821 | error_exit: | ||
1822 | return rval; | ||
1823 | } | ||
1824 | |||
1825 | static int qla4_83xx_minidump_pex_dma_read(struct scsi_qla_host *ha, | ||
1826 | struct qla8xxx_minidump_entry_hdr *entry_hdr, | ||
1827 | uint32_t **d_ptr) | ||
1828 | { | ||
1829 | int rval = QLA_SUCCESS; | ||
1830 | struct qla4_83xx_minidump_entry_rdmem_pex_dma *m_hdr = NULL; | ||
1831 | uint32_t size, read_size; | ||
1832 | uint8_t *data_ptr = (uint8_t *)*d_ptr; | ||
1833 | void *rdmem_buffer = NULL; | ||
1834 | dma_addr_t rdmem_dma; | ||
1835 | struct qla4_83xx_pex_dma_descriptor dma_desc; | ||
1836 | |||
1837 | DEBUG2(ql4_printk(KERN_INFO, ha, "Entering fn: %s\n", __func__)); | ||
1838 | |||
1839 | rval = qla4_83xx_check_dma_engine_state(ha); | ||
1840 | if (rval != QLA_SUCCESS) { | ||
1841 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1842 | "%s: DMA engine not available. Fallback to rdmem-read.\n", | ||
1843 | __func__)); | ||
1844 | return QLA_ERROR; | ||
1845 | } | ||
1846 | |||
1847 | m_hdr = (struct qla4_83xx_minidump_entry_rdmem_pex_dma *)entry_hdr; | ||
1848 | rdmem_buffer = dma_alloc_coherent(&ha->pdev->dev, | ||
1849 | QLA83XX_PEX_DMA_READ_SIZE, | ||
1850 | &rdmem_dma, GFP_KERNEL); | ||
1851 | if (!rdmem_buffer) { | ||
1852 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1853 | "%s: Unable to allocate rdmem dma buffer\n", | ||
1854 | __func__)); | ||
1855 | return QLA_ERROR; | ||
1856 | } | ||
1857 | |||
1858 | /* Prepare pex-dma descriptor to be written to MS memory. */ | ||
1859 | /* dma-desc-cmd layout: | ||
1860 | * 0-3: dma-desc-cmd 0-3 | ||
1861 | * 4-7: pcid function number | ||
1862 | * 8-15: dma-desc-cmd 8-15 | ||
1863 | */ | ||
1864 | dma_desc.cmd.dma_desc_cmd = (m_hdr->dma_desc_cmd & 0xff0f); | ||
1865 | dma_desc.cmd.dma_desc_cmd |= ((PCI_FUNC(ha->pdev->devfn) & 0xf) << 0x4); | ||
1866 | dma_desc.dma_bus_addr = rdmem_dma; | ||
1867 | |||
1868 | size = 0; | ||
1869 | read_size = 0; | ||
1870 | /* | ||
1871 | * Perform rdmem operation using pex-dma. | ||
1872 | * Prepare dma in chunks of QLA83XX_PEX_DMA_READ_SIZE. | ||
1873 | */ | ||
1874 | while (read_size < m_hdr->read_data_size) { | ||
1875 | if (m_hdr->read_data_size - read_size >= | ||
1876 | QLA83XX_PEX_DMA_READ_SIZE) | ||
1877 | size = QLA83XX_PEX_DMA_READ_SIZE; | ||
1878 | else { | ||
1879 | size = (m_hdr->read_data_size - read_size); | ||
1880 | |||
1881 | if (rdmem_buffer) | ||
1882 | dma_free_coherent(&ha->pdev->dev, | ||
1883 | QLA83XX_PEX_DMA_READ_SIZE, | ||
1884 | rdmem_buffer, rdmem_dma); | ||
1885 | |||
1886 | rdmem_buffer = dma_alloc_coherent(&ha->pdev->dev, size, | ||
1887 | &rdmem_dma, | ||
1888 | GFP_KERNEL); | ||
1889 | if (!rdmem_buffer) { | ||
1890 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1891 | "%s: Unable to allocate rdmem dma buffer\n", | ||
1892 | __func__)); | ||
1893 | return QLA_ERROR; | ||
1894 | } | ||
1895 | dma_desc.dma_bus_addr = rdmem_dma; | ||
1896 | } | ||
1897 | |||
1898 | dma_desc.src_addr = m_hdr->read_addr + read_size; | ||
1899 | dma_desc.cmd.read_data_size = size; | ||
1900 | |||
1901 | /* Prepare: Write pex-dma descriptor to MS memory. */ | ||
1902 | rval = qla4_83xx_ms_mem_write_128b(ha, | ||
1903 | (uint64_t)m_hdr->desc_card_addr, | ||
1904 | (uint32_t *)&dma_desc, | ||
1905 | (sizeof(struct qla4_83xx_pex_dma_descriptor)/16)); | ||
1906 | if (rval == -1) { | ||
1907 | ql4_printk(KERN_INFO, ha, | ||
1908 | "%s: Error writing rdmem-dma-init to MS !!!\n", | ||
1909 | __func__); | ||
1910 | goto error_exit; | ||
1911 | } | ||
1912 | |||
1913 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1914 | "%s: Dma-desc: Instruct for rdmem dma (size 0x%x).\n", | ||
1915 | __func__, size)); | ||
1916 | /* Execute: Start pex-dma operation. */ | ||
1917 | rval = qla4_83xx_start_pex_dma(ha, m_hdr); | ||
1918 | if (rval != QLA_SUCCESS) { | ||
1919 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
1920 | "scsi(%ld): start-pex-dma failed rval=0x%x\n", | ||
1921 | ha->host_no, rval)); | ||
1922 | goto error_exit; | ||
1923 | } | ||
1924 | |||
1925 | memcpy(data_ptr, rdmem_buffer, size); | ||
1926 | data_ptr += size; | ||
1927 | read_size += size; | ||
1928 | } | ||
1929 | |||
1930 | DEBUG2(ql4_printk(KERN_INFO, ha, "Leaving fn: %s\n", __func__)); | ||
1931 | |||
1932 | *d_ptr = (uint32_t *)data_ptr; | ||
1933 | |||
1934 | error_exit: | ||
1935 | if (rdmem_buffer) | ||
1936 | dma_free_coherent(&ha->pdev->dev, size, rdmem_buffer, | ||
1937 | rdmem_dma); | ||
1938 | |||
1939 | return rval; | ||
1940 | } | ||
1941 | |||
1740 | static int qla4_8xxx_minidump_process_l2tag(struct scsi_qla_host *ha, | 1942 | static int qla4_8xxx_minidump_process_l2tag(struct scsi_qla_host *ha, |
1741 | struct qla8xxx_minidump_entry_hdr *entry_hdr, | 1943 | struct qla8xxx_minidump_entry_hdr *entry_hdr, |
1742 | uint32_t **d_ptr) | 1944 | uint32_t **d_ptr) |
@@ -2068,7 +2270,7 @@ static void qla4_82xx_minidump_process_rdrom(struct scsi_qla_host *ha, | |||
2068 | #define MD_MIU_TEST_AGT_ADDR_LO 0x41000094 | 2270 | #define MD_MIU_TEST_AGT_ADDR_LO 0x41000094 |
2069 | #define MD_MIU_TEST_AGT_ADDR_HI 0x41000098 | 2271 | #define MD_MIU_TEST_AGT_ADDR_HI 0x41000098 |
2070 | 2272 | ||
2071 | static int qla4_8xxx_minidump_process_rdmem(struct scsi_qla_host *ha, | 2273 | static int __qla4_8xxx_minidump_process_rdmem(struct scsi_qla_host *ha, |
2072 | struct qla8xxx_minidump_entry_hdr *entry_hdr, | 2274 | struct qla8xxx_minidump_entry_hdr *entry_hdr, |
2073 | uint32_t **d_ptr) | 2275 | uint32_t **d_ptr) |
2074 | { | 2276 | { |
@@ -2150,6 +2352,28 @@ static int qla4_8xxx_minidump_process_rdmem(struct scsi_qla_host *ha, | |||
2150 | return QLA_SUCCESS; | 2352 | return QLA_SUCCESS; |
2151 | } | 2353 | } |
2152 | 2354 | ||
2355 | static int qla4_8xxx_minidump_process_rdmem(struct scsi_qla_host *ha, | ||
2356 | struct qla8xxx_minidump_entry_hdr *entry_hdr, | ||
2357 | uint32_t **d_ptr) | ||
2358 | { | ||
2359 | uint32_t *data_ptr = *d_ptr; | ||
2360 | int rval = QLA_SUCCESS; | ||
2361 | |||
2362 | if (is_qla8032(ha) || is_qla8042(ha)) { | ||
2363 | rval = qla4_83xx_minidump_pex_dma_read(ha, entry_hdr, | ||
2364 | &data_ptr); | ||
2365 | if (rval != QLA_SUCCESS) { | ||
2366 | rval = __qla4_8xxx_minidump_process_rdmem(ha, entry_hdr, | ||
2367 | &data_ptr); | ||
2368 | } | ||
2369 | } else { | ||
2370 | rval = __qla4_8xxx_minidump_process_rdmem(ha, entry_hdr, | ||
2371 | &data_ptr); | ||
2372 | } | ||
2373 | *d_ptr = data_ptr; | ||
2374 | return rval; | ||
2375 | } | ||
2376 | |||
2153 | static void qla4_8xxx_mark_entry_skipped(struct scsi_qla_host *ha, | 2377 | static void qla4_8xxx_mark_entry_skipped(struct scsi_qla_host *ha, |
2154 | struct qla8xxx_minidump_entry_hdr *entry_hdr, | 2378 | struct qla8xxx_minidump_entry_hdr *entry_hdr, |
2155 | int index) | 2379 | int index) |