|
@@ -1273,57 +1273,24 @@ static int tw_map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
|
|
|
int use_sg;
|
|
|
|
|
|
dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n");
|
|
|
-
|
|
|
- if (cmd->use_sg == 0)
|
|
|
- return 0;
|
|
|
|
|
|
- use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
|
|
|
-
|
|
|
- if (use_sg == 0) {
|
|
|
+ use_sg = scsi_dma_map(cmd);
|
|
|
+ if (use_sg < 0) {
|
|
|
printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
cmd->SCp.phase = TW_PHASE_SGLIST;
|
|
|
cmd->SCp.have_data_in = use_sg;
|
|
|
-
|
|
|
+
|
|
|
return use_sg;
|
|
|
} /* End tw_map_scsi_sg_data() */
|
|
|
|
|
|
-static u32 tw_map_scsi_single_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
|
|
|
-{
|
|
|
- dma_addr_t mapping;
|
|
|
-
|
|
|
- dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data()\n");
|
|
|
-
|
|
|
- if (cmd->request_bufflen == 0)
|
|
|
- return 0;
|
|
|
-
|
|
|
- mapping = pci_map_page(pdev, virt_to_page(cmd->request_buffer), offset_in_page(cmd->request_buffer), cmd->request_bufflen, DMA_BIDIRECTIONAL);
|
|
|
-
|
|
|
- if (mapping == 0) {
|
|
|
- printk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data(): pci_map_page() failed.\n");
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
- cmd->SCp.phase = TW_PHASE_SINGLE;
|
|
|
- cmd->SCp.have_data_in = mapping;
|
|
|
-
|
|
|
- return mapping;
|
|
|
-} /* End tw_map_scsi_single_data() */
|
|
|
-
|
|
|
static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
|
|
|
{
|
|
|
dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n");
|
|
|
|
|
|
- switch(cmd->SCp.phase) {
|
|
|
- case TW_PHASE_SINGLE:
|
|
|
- pci_unmap_page(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL);
|
|
|
- break;
|
|
|
- case TW_PHASE_SGLIST:
|
|
|
- pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
|
|
|
- break;
|
|
|
- }
|
|
|
+ scsi_dma_unmap(cmd);
|
|
|
} /* End tw_unmap_scsi_data() */
|
|
|
|
|
|
/* This function will reset a device extension */
|
|
@@ -1499,27 +1466,16 @@ static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,
|
|
|
void *buf;
|
|
|
unsigned int transfer_len;
|
|
|
unsigned long flags = 0;
|
|
|
+ struct scatterlist *sg = scsi_sglist(cmd);
|
|
|
|
|
|
- if (cmd->use_sg) {
|
|
|
- struct scatterlist *sg =
|
|
|
- (struct scatterlist *)cmd->request_buffer;
|
|
|
- local_irq_save(flags);
|
|
|
- buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
|
|
|
- transfer_len = min(sg->length, len);
|
|
|
- } else {
|
|
|
- buf = cmd->request_buffer;
|
|
|
- transfer_len = min(cmd->request_bufflen, len);
|
|
|
- }
|
|
|
+ local_irq_save(flags);
|
|
|
+ buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
|
|
|
+ transfer_len = min(sg->length, len);
|
|
|
|
|
|
memcpy(buf, data, transfer_len);
|
|
|
-
|
|
|
- if (cmd->use_sg) {
|
|
|
- struct scatterlist *sg;
|
|
|
|
|
|
- sg = (struct scatterlist *)cmd->request_buffer;
|
|
|
- kunmap_atomic(buf - sg->offset, KM_IRQ0);
|
|
|
- local_irq_restore(flags);
|
|
|
- }
|
|
|
+ kunmap_atomic(buf - sg->offset, KM_IRQ0);
|
|
|
+ local_irq_restore(flags);
|
|
|
}
|
|
|
|
|
|
/* 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)
|
|
|
{
|
|
|
TW_Command *command_packet;
|
|
|
unsigned long command_que_value;
|
|
|
- u32 lba = 0x0, num_sectors = 0x0, buffaddr = 0x0;
|
|
|
+ u32 lba = 0x0, num_sectors = 0x0;
|
|
|
int i, use_sg;
|
|
|
struct scsi_cmnd *srb;
|
|
|
- struct scatterlist *sglist;
|
|
|
+ struct scatterlist *sglist, *sg;
|
|
|
|
|
|
dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n");
|
|
|
|
|
|
- if (tw_dev->srb[request_id]->request_buffer == NULL) {
|
|
|
+ srb = tw_dev->srb[request_id];
|
|
|
+
|
|
|
+ sglist = scsi_sglist(srb);
|
|
|
+ if (!sglist) {
|
|
|
printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n");
|
|
|
return 1;
|
|
|
}
|
|
|
- sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
|
|
|
- srb = tw_dev->srb[request_id];
|
|
|
|
|
|
/* Initialize command packet */
|
|
|
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)
|
|
|
command_packet->byte8.io.lba = lba;
|
|
|
command_packet->byte6.block_count = num_sectors;
|
|
|
|
|
|
- /* Do this if there are no sg list entries */
|
|
|
- if (tw_dev->srb[request_id]->use_sg == 0) {
|
|
|
- dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n");
|
|
|
- buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
|
|
|
- if (buffaddr == 0)
|
|
|
- return 1;
|
|
|
+ use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
|
|
|
+ if (!use_sg)
|
|
|
+ return 1;
|
|
|
|
|
|
- command_packet->byte8.io.sgl[0].address = buffaddr;
|
|
|
- command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen;
|
|
|
+ scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) {
|
|
|
+ command_packet->byte8.io.sgl[i].address = sg_dma_address(sg);
|
|
|
+ command_packet->byte8.io.sgl[i].length = sg_dma_len(sg);
|
|
|
command_packet->size+=2;
|
|
|
}
|
|
|
|
|
|
- /* Do this if we have multiple sg list entries */
|
|
|
- if (tw_dev->srb[request_id]->use_sg > 0) {
|
|
|
- use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
|
|
|
- if (use_sg == 0)
|
|
|
- return 1;
|
|
|
-
|
|
|
- for (i=0;i<use_sg; i++) {
|
|
|
- command_packet->byte8.io.sgl[i].address = sg_dma_address(&sglist[i]);
|
|
|
- command_packet->byte8.io.sgl[i].length = sg_dma_len(&sglist[i]);
|
|
|
- command_packet->size+=2;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/* Update SG statistics */
|
|
|
- tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg;
|
|
|
+ tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]);
|
|
|
if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
|
|
|
tw_dev->max_sgl_entries = tw_dev->sgl_entries;
|
|
|
|