--- linux-2.5.6-pre2/drivers/scsi/hosts.h Tue Feb 19 18:10:59 2002 +++ linux/drivers/scsi/hosts.h Wed Mar 6 01:10:44 2002 @@ -286,6 +286,11 @@ unsigned highmem_io:1; + /* Have the high level code automatically handle DMA mapping of + Scsi_Request->request_buffer and Scsi_Request->sense_buf. */ + unsigned dma_map_request:1; + unsigned dma_map_sense:1; + /* * Name of proc directory */ --- linux-2.5.6-pre2/drivers/scsi/scsi.h Tue Feb 19 18:10:58 2002 +++ linux/drivers/scsi/scsi.h Wed Mar 6 02:31:05 2002 @@ -734,12 +732,14 @@ struct timer_list eh_timeout; /* Used to time out the command. */ void *request_buffer; /* Actual requested buffer */ + dma_addr_t request_dma_addr; /* These elements define the operation we ultimately want to perform */ unsigned char data_cmnd[MAX_COMMAND_SIZE]; unsigned short old_use_sg; /* We save use_sg here when requesting * sense info */ unsigned short use_sg; /* Number of pieces of scatter-gather */ + unsigned short sgcnt_dma; /* Returned by pci_map_sg. */ unsigned short sglist_len; /* size of malloc'd scatter-gather list */ unsigned short abort_reason; /* If the mid-level code requests an * abort, this is the reason. */ @@ -768,6 +768,7 @@ * when CHECK CONDITION is * received on original command * (auto-sense) */ + dma_addr_t sense_dma_addr; unsigned flags; --- linux-2.5.6-pre2/drivers/scsi/scsi.c Tue Feb 19 18:11:03 2002 +++ linux/drivers/scsi/scsi.c Wed Mar 6 02:43:55 2002 @@ -309,6 +309,76 @@ return SRpnt; } +static inline void +scsi_unmap_dma(Scsi_Cmnd *cmd) +{ + const Scsi_Host_Template *template = cmd->host->hostt; + + /* TODO: Simplify device drivers by having this routine rebuild + any cmd->use_sg==0 request as a cmd->use_sg==1 request. */ + + if (template->dma_map_request) { + int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); + if (cmd->use_sg) + pci_unmap_sg(cmd->host->pci_dev, + (struct scatterlist*)cmd->request_buffer, + cmd->use_sg, + dma_dir); + else if (cmd->request_bufflen) + pci_unmap_single(cmd->host->pci_dev, + cmd->request_dma_addr, + cmd->request_bufflen, + dma_dir); + } + + if (template->dma_map_sense && cmd->sense_dma_addr) + pci_unmap_single(cmd->host->pci_dev, + cmd->sense_dma_addr, + sizeof(cmd->sense_buffer), + PCI_DMA_FROMDEVICE); +} + +static inline int +scsi_map_dma(Scsi_Cmnd *cmd) +{ + const Scsi_Host_Template *template = cmd->host->hostt; + + /* TODO: Simplify device drivers by having this routine rebuild + any cmd->use_sg==0 request as a cmd->use_sg==1 request. */ + + if (template->dma_map_request) { + int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction); + if (cmd->use_sg) { + cmd->sgcnt_dma = pci_map_sg(cmd->host->pci_dev, + (struct scatterlist*) + cmd->request_buffer, + cmd->use_sg, + dma_dir); + if (cmd->sgcnt_dma <= 0) + return -EBUSY; + } else if (cmd->request_bufflen) { + cmd->request_dma_addr = + pci_map_single(cmd->host->pci_dev, + cmd->request_buffer, + cmd->request_bufflen, + dma_dir); + if (!cmd->request_dma_addr) + return -EBUSY; + } + } + if (template->dma_map_sense) { + cmd->sense_dma_addr = pci_map_single(cmd->host->pci_dev, + cmd->sense_buffer, + sizeof(cmd->sense_buffer), + PCI_DMA_FROMDEVICE); + if (!cmd->sense_dma_addr) { + scsi_unmap_dma(cmd); + return -EBUSY; + } + } + return 0; +} + /* * Function: scsi_release_request * @@ -706,6 +776,7 @@ * length exceeds what the host adapter can handle. */ if (CDB_SIZE(SCpnt) <= SCpnt->host->max_cmd_len) { + scsi_map_dma(SCpnt); spin_lock_irqsave(host->host_lock, flags); rtn = host->hostt->queuecommand(SCpnt, scsi_done); spin_unlock_irqrestore(host->host_lock, flags); @@ -1146,6 +1217,7 @@ SCSI_LOG_MLCOMPLETE(1, printk("Ignoring completion of %p due to timeout status", SCpnt)); return; } + scsi_unmap_dma(SCpnt); spin_lock_irqsave(&scsi_bhqueue_lock, flags); SCpnt->serial_number_at_timeout = 0;