diff options
Diffstat (limited to 'drivers/scsi/3w-xxxx.c')
-rw-r--r-- | drivers/scsi/3w-xxxx.c | 104 |
1 files changed, 23 insertions, 81 deletions
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 656bdb1352d8..c7995fc216e8 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c | |||
@@ -1273,57 +1273,24 @@ static int tw_map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) | |||
1273 | int use_sg; | 1273 | int use_sg; |
1274 | 1274 | ||
1275 | dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n"); | 1275 | dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n"); |
1276 | |||
1277 | if (cmd->use_sg == 0) | ||
1278 | return 0; | ||
1279 | 1276 | ||
1280 | use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL); | 1277 | use_sg = scsi_dma_map(cmd); |
1281 | 1278 | if (use_sg < 0) { | |
1282 | if (use_sg == 0) { | ||
1283 | printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n"); | 1279 | printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n"); |
1284 | return 0; | 1280 | return 0; |
1285 | } | 1281 | } |
1286 | 1282 | ||
1287 | cmd->SCp.phase = TW_PHASE_SGLIST; | 1283 | cmd->SCp.phase = TW_PHASE_SGLIST; |
1288 | cmd->SCp.have_data_in = use_sg; | 1284 | cmd->SCp.have_data_in = use_sg; |
1289 | 1285 | ||
1290 | return use_sg; | 1286 | return use_sg; |
1291 | } /* End tw_map_scsi_sg_data() */ | 1287 | } /* End tw_map_scsi_sg_data() */ |
1292 | 1288 | ||
1293 | static u32 tw_map_scsi_single_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) | ||
1294 | { | ||
1295 | dma_addr_t mapping; | ||
1296 | |||
1297 | dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data()\n"); | ||
1298 | |||
1299 | if (cmd->request_bufflen == 0) | ||
1300 | return 0; | ||
1301 | |||
1302 | mapping = pci_map_page(pdev, virt_to_page(cmd->request_buffer), offset_in_page(cmd->request_buffer), cmd->request_bufflen, DMA_BIDIRECTIONAL); | ||
1303 | |||
1304 | if (mapping == 0) { | ||
1305 | printk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data(): pci_map_page() failed.\n"); | ||
1306 | return 0; | ||
1307 | } | ||
1308 | |||
1309 | cmd->SCp.phase = TW_PHASE_SINGLE; | ||
1310 | cmd->SCp.have_data_in = mapping; | ||
1311 | |||
1312 | return mapping; | ||
1313 | } /* End tw_map_scsi_single_data() */ | ||
1314 | |||
1315 | static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) | 1289 | static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) |
1316 | { | 1290 | { |
1317 | dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n"); | 1291 | dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n"); |
1318 | 1292 | ||
1319 | switch(cmd->SCp.phase) { | 1293 | scsi_dma_unmap(cmd); |
1320 | case TW_PHASE_SINGLE: | ||
1321 | pci_unmap_page(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL); | ||
1322 | break; | ||
1323 | case TW_PHASE_SGLIST: | ||
1324 | pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL); | ||
1325 | break; | ||
1326 | } | ||
1327 | } /* End tw_unmap_scsi_data() */ | 1294 | } /* End tw_unmap_scsi_data() */ |
1328 | 1295 | ||
1329 | /* This function will reset a device extension */ | 1296 | /* This function will reset a device extension */ |
@@ -1499,27 +1466,16 @@ static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id, | |||
1499 | void *buf; | 1466 | void *buf; |
1500 | unsigned int transfer_len; | 1467 | unsigned int transfer_len; |
1501 | unsigned long flags = 0; | 1468 | unsigned long flags = 0; |
1469 | struct scatterlist *sg = scsi_sglist(cmd); | ||
1502 | 1470 | ||
1503 | if (cmd->use_sg) { | 1471 | local_irq_save(flags); |
1504 | struct scatterlist *sg = | 1472 | buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; |
1505 | (struct scatterlist *)cmd->request_buffer; | 1473 | transfer_len = min(sg->length, len); |
1506 | local_irq_save(flags); | ||
1507 | buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | ||
1508 | transfer_len = min(sg->length, len); | ||
1509 | } else { | ||
1510 | buf = cmd->request_buffer; | ||
1511 | transfer_len = min(cmd->request_bufflen, len); | ||
1512 | } | ||
1513 | 1474 | ||
1514 | memcpy(buf, data, transfer_len); | 1475 | memcpy(buf, data, transfer_len); |
1515 | |||
1516 | if (cmd->use_sg) { | ||
1517 | struct scatterlist *sg; | ||
1518 | 1476 | ||
1519 | sg = (struct scatterlist *)cmd->request_buffer; | 1477 | kunmap_atomic(buf - sg->offset, KM_IRQ0); |
1520 | kunmap_atomic(buf - sg->offset, KM_IRQ0); | 1478 | local_irq_restore(flags); |
1521 | local_irq_restore(flags); | ||
1522 | } | ||
1523 | } | 1479 | } |
1524 | 1480 | ||
1525 | /* This function is called by the isr to complete an inquiry command */ | 1481 | /* This function is called by the isr to complete an inquiry command */ |
@@ -1764,19 +1720,20 @@ static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id) | |||
1764 | { | 1720 | { |
1765 | TW_Command *command_packet; | 1721 | TW_Command *command_packet; |
1766 | unsigned long command_que_value; | 1722 | unsigned long command_que_value; |
1767 | u32 lba = 0x0, num_sectors = 0x0, buffaddr = 0x0; | 1723 | u32 lba = 0x0, num_sectors = 0x0; |
1768 | int i, use_sg; | 1724 | int i, use_sg; |
1769 | struct scsi_cmnd *srb; | 1725 | struct scsi_cmnd *srb; |
1770 | struct scatterlist *sglist; | 1726 | struct scatterlist *sglist, *sg; |
1771 | 1727 | ||
1772 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n"); | 1728 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n"); |
1773 | 1729 | ||
1774 | if (tw_dev->srb[request_id]->request_buffer == NULL) { | 1730 | srb = tw_dev->srb[request_id]; |
1731 | |||
1732 | sglist = scsi_sglist(srb); | ||
1733 | if (!sglist) { | ||
1775 | printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n"); | 1734 | printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n"); |
1776 | return 1; | 1735 | return 1; |
1777 | } | 1736 | } |
1778 | sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer; | ||
1779 | srb = tw_dev->srb[request_id]; | ||
1780 | 1737 | ||
1781 | /* Initialize command packet */ | 1738 | /* Initialize command packet */ |
1782 | command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; | 1739 | command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; |
@@ -1819,33 +1776,18 @@ static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id) | |||
1819 | command_packet->byte8.io.lba = lba; | 1776 | command_packet->byte8.io.lba = lba; |
1820 | command_packet->byte6.block_count = num_sectors; | 1777 | command_packet->byte6.block_count = num_sectors; |
1821 | 1778 | ||
1822 | /* Do this if there are no sg list entries */ | 1779 | use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); |
1823 | if (tw_dev->srb[request_id]->use_sg == 0) { | 1780 | if (!use_sg) |
1824 | dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n"); | 1781 | return 1; |
1825 | buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); | ||
1826 | if (buffaddr == 0) | ||
1827 | return 1; | ||
1828 | 1782 | ||
1829 | command_packet->byte8.io.sgl[0].address = buffaddr; | 1783 | scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) { |
1830 | command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen; | 1784 | command_packet->byte8.io.sgl[i].address = sg_dma_address(sg); |
1785 | command_packet->byte8.io.sgl[i].length = sg_dma_len(sg); | ||
1831 | command_packet->size+=2; | 1786 | command_packet->size+=2; |
1832 | } | 1787 | } |
1833 | 1788 | ||
1834 | /* Do this if we have multiple sg list entries */ | ||
1835 | if (tw_dev->srb[request_id]->use_sg > 0) { | ||
1836 | use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); | ||
1837 | if (use_sg == 0) | ||
1838 | return 1; | ||
1839 | |||
1840 | for (i=0;i<use_sg; i++) { | ||
1841 | command_packet->byte8.io.sgl[i].address = sg_dma_address(&sglist[i]); | ||
1842 | command_packet->byte8.io.sgl[i].length = sg_dma_len(&sglist[i]); | ||
1843 | command_packet->size+=2; | ||
1844 | } | ||
1845 | } | ||
1846 | |||
1847 | /* Update SG statistics */ | 1789 | /* Update SG statistics */ |
1848 | tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg; | 1790 | tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]); |
1849 | if (tw_dev->sgl_entries > tw_dev->max_sgl_entries) | 1791 | if (tw_dev->sgl_entries > tw_dev->max_sgl_entries) |
1850 | tw_dev->max_sgl_entries = tw_dev->sgl_entries; | 1792 | tw_dev->max_sgl_entries = tw_dev->sgl_entries; |
1851 | 1793 | ||