aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/3w-xxxx.c104
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
1293static 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
1315static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd) 1289static 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