diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/3w-9xxx.c | 139 |
1 files changed, 42 insertions, 97 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index eb766c3af1c8..113aaed490d4 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c | |||
@@ -1306,22 +1306,26 @@ static irqreturn_t twa_interrupt(int irq, void *dev_instance) | |||
1306 | wake_up(&tw_dev->ioctl_wqueue); | 1306 | wake_up(&tw_dev->ioctl_wqueue); |
1307 | } | 1307 | } |
1308 | } else { | 1308 | } else { |
1309 | struct scsi_cmnd *cmd; | ||
1310 | |||
1311 | cmd = tw_dev->srb[request_id]; | ||
1312 | |||
1309 | twa_scsiop_execute_scsi_complete(tw_dev, request_id); | 1313 | twa_scsiop_execute_scsi_complete(tw_dev, request_id); |
1310 | /* If no error command was a success */ | 1314 | /* If no error command was a success */ |
1311 | if (error == 0) { | 1315 | if (error == 0) { |
1312 | tw_dev->srb[request_id]->result = (DID_OK << 16); | 1316 | cmd->result = (DID_OK << 16); |
1313 | } | 1317 | } |
1314 | 1318 | ||
1315 | /* If error, command failed */ | 1319 | /* If error, command failed */ |
1316 | if (error == 1) { | 1320 | if (error == 1) { |
1317 | /* Ask for a host reset */ | 1321 | /* Ask for a host reset */ |
1318 | tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1); | 1322 | cmd->result = (DID_OK << 16) | (CHECK_CONDITION << 1); |
1319 | } | 1323 | } |
1320 | 1324 | ||
1321 | /* Report residual bytes for single sgl */ | 1325 | /* Report residual bytes for single sgl */ |
1322 | if ((tw_dev->srb[request_id]->use_sg <= 1) && (full_command_packet->command.newcommand.status == 0)) { | 1326 | if ((scsi_sg_count(cmd) <= 1) && (full_command_packet->command.newcommand.status == 0)) { |
1323 | if (full_command_packet->command.newcommand.sg_list[0].length < tw_dev->srb[request_id]->request_bufflen) | 1327 | if (full_command_packet->command.newcommand.sg_list[0].length < scsi_bufflen(tw_dev->srb[request_id])) |
1324 | tw_dev->srb[request_id]->resid = tw_dev->srb[request_id]->request_bufflen - full_command_packet->command.newcommand.sg_list[0].length; | 1328 | scsi_set_resid(cmd, scsi_bufflen(cmd) - full_command_packet->command.newcommand.sg_list[0].length); |
1325 | } | 1329 | } |
1326 | 1330 | ||
1327 | /* Now complete the io */ | 1331 | /* Now complete the io */ |
@@ -1384,52 +1388,20 @@ static int twa_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id) | |||
1384 | { | 1388 | { |
1385 | int use_sg; | 1389 | int use_sg; |
1386 | struct scsi_cmnd *cmd = tw_dev->srb[request_id]; | 1390 | struct scsi_cmnd *cmd = tw_dev->srb[request_id]; |
1387 | struct pci_dev *pdev = tw_dev->tw_pci_dev; | ||
1388 | int retval = 0; | ||
1389 | |||
1390 | if (cmd->use_sg == 0) | ||
1391 | goto out; | ||
1392 | |||
1393 | use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL); | ||
1394 | 1391 | ||
1395 | if (use_sg == 0) { | 1392 | use_sg = scsi_dma_map(cmd); |
1393 | if (!use_sg) | ||
1394 | return 0; | ||
1395 | else if (use_sg < 0) { | ||
1396 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list"); | 1396 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to map scatter gather list"); |
1397 | goto out; | 1397 | return 0; |
1398 | } | 1398 | } |
1399 | 1399 | ||
1400 | cmd->SCp.phase = TW_PHASE_SGLIST; | 1400 | cmd->SCp.phase = TW_PHASE_SGLIST; |
1401 | cmd->SCp.have_data_in = use_sg; | 1401 | cmd->SCp.have_data_in = use_sg; |
1402 | retval = use_sg; | ||
1403 | out: | ||
1404 | return retval; | ||
1405 | } /* End twa_map_scsi_sg_data() */ | ||
1406 | 1402 | ||
1407 | /* This function will perform a pci-dma map for a single buffer */ | 1403 | return use_sg; |
1408 | static dma_addr_t twa_map_scsi_single_data(TW_Device_Extension *tw_dev, int request_id) | 1404 | } /* End twa_map_scsi_sg_data() */ |
1409 | { | ||
1410 | dma_addr_t mapping; | ||
1411 | struct scsi_cmnd *cmd = tw_dev->srb[request_id]; | ||
1412 | struct pci_dev *pdev = tw_dev->tw_pci_dev; | ||
1413 | dma_addr_t retval = 0; | ||
1414 | |||
1415 | if (cmd->request_bufflen == 0) { | ||
1416 | retval = 0; | ||
1417 | goto out; | ||
1418 | } | ||
1419 | |||
1420 | mapping = pci_map_single(pdev, cmd->request_buffer, cmd->request_bufflen, DMA_BIDIRECTIONAL); | ||
1421 | |||
1422 | if (mapping == 0) { | ||
1423 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1d, "Failed to map page"); | ||
1424 | goto out; | ||
1425 | } | ||
1426 | |||
1427 | cmd->SCp.phase = TW_PHASE_SINGLE; | ||
1428 | cmd->SCp.have_data_in = mapping; | ||
1429 | retval = mapping; | ||
1430 | out: | ||
1431 | return retval; | ||
1432 | } /* End twa_map_scsi_single_data() */ | ||
1433 | 1405 | ||
1434 | /* This function will poll for a response interrupt of a request */ | 1406 | /* This function will poll for a response interrupt of a request */ |
1435 | static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds) | 1407 | static int twa_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds) |
@@ -1815,15 +1787,13 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, | |||
1815 | u32 num_sectors = 0x0; | 1787 | u32 num_sectors = 0x0; |
1816 | int i, sg_count; | 1788 | int i, sg_count; |
1817 | struct scsi_cmnd *srb = NULL; | 1789 | struct scsi_cmnd *srb = NULL; |
1818 | struct scatterlist *sglist = NULL; | 1790 | struct scatterlist *sglist = NULL, *sg; |
1819 | dma_addr_t buffaddr = 0x0; | ||
1820 | int retval = 1; | 1791 | int retval = 1; |
1821 | 1792 | ||
1822 | if (tw_dev->srb[request_id]) { | 1793 | if (tw_dev->srb[request_id]) { |
1823 | if (tw_dev->srb[request_id]->request_buffer) { | ||
1824 | sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer; | ||
1825 | } | ||
1826 | srb = tw_dev->srb[request_id]; | 1794 | srb = tw_dev->srb[request_id]; |
1795 | if (scsi_sglist(srb)) | ||
1796 | sglist = scsi_sglist(srb); | ||
1827 | } | 1797 | } |
1828 | 1798 | ||
1829 | /* Initialize command packet */ | 1799 | /* Initialize command packet */ |
@@ -1856,32 +1826,12 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, | |||
1856 | 1826 | ||
1857 | if (!sglistarg) { | 1827 | if (!sglistarg) { |
1858 | /* Map sglist from scsi layer to cmd packet */ | 1828 | /* Map sglist from scsi layer to cmd packet */ |
1859 | if (tw_dev->srb[request_id]->use_sg == 0) { | ||
1860 | if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) { | ||
1861 | command_packet->sg_list[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]); | ||
1862 | command_packet->sg_list[0].length = cpu_to_le32(TW_MIN_SGL_LENGTH); | ||
1863 | if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) | ||
1864 | memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen); | ||
1865 | } else { | ||
1866 | buffaddr = twa_map_scsi_single_data(tw_dev, request_id); | ||
1867 | if (buffaddr == 0) | ||
1868 | goto out; | ||
1869 | |||
1870 | command_packet->sg_list[0].address = TW_CPU_TO_SGL(buffaddr); | ||
1871 | command_packet->sg_list[0].length = cpu_to_le32(tw_dev->srb[request_id]->request_bufflen); | ||
1872 | } | ||
1873 | command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), 1)); | ||
1874 | |||
1875 | if (command_packet->sg_list[0].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) { | ||
1876 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2d, "Found unaligned address during execute scsi"); | ||
1877 | goto out; | ||
1878 | } | ||
1879 | } | ||
1880 | 1829 | ||
1881 | if (tw_dev->srb[request_id]->use_sg > 0) { | 1830 | if (scsi_sg_count(srb)) { |
1882 | if ((tw_dev->srb[request_id]->use_sg == 1) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) { | 1831 | if ((scsi_sg_count(srb) == 1) && |
1883 | if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) { | 1832 | (scsi_bufflen(srb) < TW_MIN_SGL_LENGTH)) { |
1884 | struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer; | 1833 | if (srb->sc_data_direction == DMA_TO_DEVICE || srb->sc_data_direction == DMA_BIDIRECTIONAL) { |
1834 | struct scatterlist *sg = scsi_sglist(srb); | ||
1885 | char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | 1835 | char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; |
1886 | memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length); | 1836 | memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length); |
1887 | kunmap_atomic(buf - sg->offset, KM_IRQ0); | 1837 | kunmap_atomic(buf - sg->offset, KM_IRQ0); |
@@ -1893,16 +1843,16 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, | |||
1893 | if (sg_count == 0) | 1843 | if (sg_count == 0) |
1894 | goto out; | 1844 | goto out; |
1895 | 1845 | ||
1896 | for (i = 0; i < sg_count; i++) { | 1846 | scsi_for_each_sg(srb, sg, sg_count, i) { |
1897 | command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(&sglist[i])); | 1847 | command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(sg)); |
1898 | command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(&sglist[i])); | 1848 | command_packet->sg_list[i].length = cpu_to_le32(sg_dma_len(sg)); |
1899 | if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) { | 1849 | if (command_packet->sg_list[i].address & TW_CPU_TO_SGL(TW_ALIGNMENT_9000_SGL)) { |
1900 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi"); | 1850 | TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2e, "Found unaligned sgl address during execute scsi"); |
1901 | goto out; | 1851 | goto out; |
1902 | } | 1852 | } |
1903 | } | 1853 | } |
1904 | } | 1854 | } |
1905 | command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), tw_dev->srb[request_id]->use_sg)); | 1855 | command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), scsi_sg_count(tw_dev->srb[request_id]))); |
1906 | } | 1856 | } |
1907 | } else { | 1857 | } else { |
1908 | /* Internal cdb post */ | 1858 | /* Internal cdb post */ |
@@ -1932,7 +1882,7 @@ static int twa_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, | |||
1932 | 1882 | ||
1933 | /* Update SG statistics */ | 1883 | /* Update SG statistics */ |
1934 | if (srb) { | 1884 | if (srb) { |
1935 | tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg; | 1885 | tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]); |
1936 | if (tw_dev->sgl_entries > tw_dev->max_sgl_entries) | 1886 | if (tw_dev->sgl_entries > tw_dev->max_sgl_entries) |
1937 | tw_dev->max_sgl_entries = tw_dev->sgl_entries; | 1887 | tw_dev->max_sgl_entries = tw_dev->sgl_entries; |
1938 | } | 1888 | } |
@@ -1951,16 +1901,19 @@ out: | |||
1951 | /* This function completes an execute scsi operation */ | 1901 | /* This function completes an execute scsi operation */ |
1952 | static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id) | 1902 | static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id) |
1953 | { | 1903 | { |
1954 | if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH && | 1904 | struct scsi_cmnd *cmd = tw_dev->srb[request_id]; |
1955 | (tw_dev->srb[request_id]->sc_data_direction == DMA_FROM_DEVICE || | 1905 | int use_sg = scsi_sg_count(cmd); |
1956 | tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)) { | 1906 | |
1957 | if (tw_dev->srb[request_id]->use_sg == 0) { | 1907 | if (scsi_bufflen(cmd) < TW_MIN_SGL_LENGTH && |
1958 | memcpy(tw_dev->srb[request_id]->request_buffer, | 1908 | (cmd->sc_data_direction == DMA_FROM_DEVICE || |
1909 | cmd->sc_data_direction == DMA_BIDIRECTIONAL)) { | ||
1910 | if (!use_sg) | ||
1911 | memcpy(scsi_sglist(cmd), | ||
1959 | tw_dev->generic_buffer_virt[request_id], | 1912 | tw_dev->generic_buffer_virt[request_id], |
1960 | tw_dev->srb[request_id]->request_bufflen); | 1913 | scsi_bufflen(cmd)); |
1961 | } | 1914 | |
1962 | if (tw_dev->srb[request_id]->use_sg == 1) { | 1915 | if (use_sg == 1) { |
1963 | struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer; | 1916 | struct scatterlist *sg = scsi_sglist(tw_dev->srb[request_id]); |
1964 | char *buf; | 1917 | char *buf; |
1965 | unsigned long flags = 0; | 1918 | unsigned long flags = 0; |
1966 | local_irq_save(flags); | 1919 | local_irq_save(flags); |
@@ -2017,16 +1970,8 @@ static char *twa_string_lookup(twa_message_type *table, unsigned int code) | |||
2017 | static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id) | 1970 | static void twa_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id) |
2018 | { | 1971 | { |
2019 | struct scsi_cmnd *cmd = tw_dev->srb[request_id]; | 1972 | struct scsi_cmnd *cmd = tw_dev->srb[request_id]; |
2020 | struct pci_dev *pdev = tw_dev->tw_pci_dev; | ||
2021 | 1973 | ||
2022 | switch(cmd->SCp.phase) { | 1974 | scsi_dma_unmap(cmd); |
2023 | case TW_PHASE_SINGLE: | ||
2024 | pci_unmap_single(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL); | ||
2025 | break; | ||
2026 | case TW_PHASE_SGLIST: | ||
2027 | pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL); | ||
2028 | break; | ||
2029 | } | ||
2030 | } /* End twa_unmap_scsi_data() */ | 1975 | } /* End twa_unmap_scsi_data() */ |
2031 | 1976 | ||
2032 | /* scsi_host_template initializer */ | 1977 | /* scsi_host_template initializer */ |