aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSantosh Vernekar <santosh.vernekar@qlogic.com>2013-08-23 03:40:18 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-09-03 10:27:56 -0400
commit41f79bde1d4e18fcd336dd5b6999ab9588daea54 (patch)
tree11789ccc92b3b58790105734c205a633829cb36a
parent909ee499c1c85e99ed3f9e99caf13a89f4de3d3a (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.c4
-rw-r--r--drivers/scsi/qla4xxx/ql4_83xx.h34
-rw-r--r--drivers/scsi/qla4xxx/ql4_glbl.h2
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c226
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 **/
262static int qla4_83xx_ms_mem_write_128b(struct scsi_qla_host *ha, uint64_t addr, 262int 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 */
304struct 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
315struct 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,
272int qla4xxx_get_acb(struct scsi_qla_host *ha, dma_addr_t acb_dma, 272int 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);
274int qla4_84xx_config_acb(struct scsi_qla_host *ha, int acb_config); 274int qla4_84xx_config_acb(struct scsi_qla_host *ha, int acb_config);
275int qla4_83xx_ms_mem_write_128b(struct scsi_qla_host *ha,
276 uint64_t addr, uint32_t *data, uint32_t count);
275 277
276extern int ql4xextended_error_logging; 278extern int ql4xextended_error_logging;
277extern int ql4xdontresethba; 279extern 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
1740static 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
1769static 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
1821error_exit:
1822 return rval;
1823}
1824
1825static 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
1934error_exit:
1935 if (rdmem_buffer)
1936 dma_free_coherent(&ha->pdev->dev, size, rdmem_buffer,
1937 rdmem_dma);
1938
1939 return rval;
1940}
1941
1740static int qla4_8xxx_minidump_process_l2tag(struct scsi_qla_host *ha, 1942static 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
2071static int qla4_8xxx_minidump_process_rdmem(struct scsi_qla_host *ha, 2273static 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
2355static 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
2153static void qla4_8xxx_mark_entry_skipped(struct scsi_qla_host *ha, 2377static 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)