[SCSI] stex: stex_internal_copy should be called with sg_count in struct st_ccb
[sfrench/cifs-2.6.git] / drivers / scsi / stex.c
index 9ac83abc4028c2ec33cd80941e0bda1050003d0c..654430edf74db0525b35605e06b176126cb5aab1 100644 (file)
@@ -395,53 +395,34 @@ static struct req_msg *stex_alloc_req(struct st_hba *hba)
 static int stex_map_sg(struct st_hba *hba,
        struct req_msg *req, struct st_ccb *ccb)
 {
-       struct pci_dev *pdev = hba->pdev;
        struct scsi_cmnd *cmd;
-       dma_addr_t dma_handle;
-       struct scatterlist *src;
+       struct scatterlist *sg;
        struct st_sgtable *dst;
-       int i;
+       int i, nseg;
 
        cmd = ccb->cmd;
        dst = (struct st_sgtable *)req->variable;
        dst->max_sg_count = cpu_to_le16(ST_MAX_SG);
-       dst->sz_in_byte = cpu_to_le32(cmd->request_bufflen);
-
-       if (cmd->use_sg) {
-               int n_elem;
-
-               src = (struct scatterlist *) cmd->request_buffer;
-               n_elem = pci_map_sg(pdev, src,
-                       cmd->use_sg, cmd->sc_data_direction);
-               if (n_elem <= 0)
-                       return -EIO;
+       dst->sz_in_byte = cpu_to_le32(scsi_bufflen(cmd));
 
-               ccb->sg_count = n_elem;
-               dst->sg_count = cpu_to_le16((u16)n_elem);
+       nseg = scsi_dma_map(cmd);
+       if (nseg < 0)
+               return -EIO;
+       if (nseg) {
+               ccb->sg_count = nseg;
+               dst->sg_count = cpu_to_le16((u16)nseg);
 
-               for (i = 0; i < n_elem; i++, src++) {
-                       dst->table[i].count = cpu_to_le32((u32)sg_dma_len(src));
+               scsi_for_each_sg(cmd, sg, nseg, i) {
+                       dst->table[i].count = cpu_to_le32((u32)sg_dma_len(sg));
                        dst->table[i].addr =
-                               cpu_to_le32(sg_dma_address(src) & 0xffffffff);
+                               cpu_to_le32(sg_dma_address(sg) & 0xffffffff);
                        dst->table[i].addr_hi =
-                               cpu_to_le32((sg_dma_address(src) >> 16) >> 16);
+                               cpu_to_le32((sg_dma_address(sg) >> 16) >> 16);
                        dst->table[i].ctrl = SG_CF_64B | SG_CF_HOST;
                }
                dst->table[--i].ctrl |= SG_CF_EOT;
-               return 0;
        }
 
-       dma_handle = pci_map_single(pdev, cmd->request_buffer,
-               cmd->request_bufflen, cmd->sc_data_direction);
-       cmd->SCp.dma_handle = dma_handle;
-
-       ccb->sg_count = 1;
-       dst->sg_count = cpu_to_le16(1);
-       dst->table[0].addr = cpu_to_le32(dma_handle & 0xffffffff);
-       dst->table[0].addr_hi = cpu_to_le32((dma_handle >> 16) >> 16);
-       dst->table[0].count = cpu_to_le32((u32)cmd->request_bufflen);
-       dst->table[0].ctrl = SG_CF_EOT | SG_CF_64B | SG_CF_HOST;
-
        return 0;
 }
 
@@ -451,24 +432,24 @@ static void stex_internal_copy(struct scsi_cmnd *cmd,
        size_t lcount;
        size_t len;
        void *s, *d, *base = NULL;
-       if (*count > cmd->request_bufflen)
-               *count = cmd->request_bufflen;
+       size_t offset;
+
+       if (*count > scsi_bufflen(cmd))
+               *count = scsi_bufflen(cmd);
        lcount = *count;
        while (lcount) {
                len = lcount;
                s = (void *)src;
-               if (cmd->use_sg) {
-                       size_t offset = *count - lcount;
-                       s += offset;
-                       base = scsi_kmap_atomic_sg(cmd->request_buffer,
-                               sg_count, &offset, &len);
-                       if (base == NULL) {
-                               *count -= lcount;
-                               return;
-                       }
-                       d = base + offset;
-               } else
-                       d = cmd->request_buffer;
+
+               offset = *count - lcount;
+               s += offset;
+               base = scsi_kmap_atomic_sg(scsi_sglist(cmd),
+                                          sg_count, &offset, &len);
+               if (!base) {
+                       *count -= lcount;
+                       return;
+               }
+               d = base + offset;
 
                if (direction == ST_TO_CMD)
                        memcpy(d, s, len);
@@ -476,40 +457,18 @@ static void stex_internal_copy(struct scsi_cmnd *cmd,
                        memcpy(s, d, len);
 
                lcount -= len;
-               if (cmd->use_sg)
-                       scsi_kunmap_atomic_sg(base);
+               scsi_kunmap_atomic_sg(base);
        }
 }
 
-static int stex_direct_copy(struct scsi_cmnd *cmd,
-       const void *src, size_t count)
-{
-       struct st_hba *hba = (struct st_hba *) &cmd->device->host->hostdata[0];
-       size_t cp_len = count;
-       int n_elem = 0;
-
-       if (cmd->use_sg) {
-               n_elem = pci_map_sg(hba->pdev, cmd->request_buffer,
-                       cmd->use_sg, cmd->sc_data_direction);
-               if (n_elem <= 0)
-                       return 0;
-       }
-
-       stex_internal_copy(cmd, src, &cp_len, n_elem, ST_TO_CMD);
-
-       if (cmd->use_sg)
-               pci_unmap_sg(hba->pdev, cmd->request_buffer,
-                       cmd->use_sg, cmd->sc_data_direction);
-       return cp_len == count;
-}
-
 static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
 {
        struct st_frame *p;
        size_t count = sizeof(struct st_frame);
 
        p = hba->copy_buffer;
-       stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count, ST_FROM_CMD);
+       stex_internal_copy(ccb->cmd, p, &count, scsi_sg_count(ccb->cmd),
+                          ST_FROM_CMD);
        memset(p->base, 0, sizeof(u32)*6);
        *(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0);
        p->rom_addr = 0;
@@ -527,7 +486,8 @@ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
        p->subid =
                hba->pdev->subsystem_vendor << 16 | hba->pdev->subsystem_device;
 
-       stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count, ST_TO_CMD);
+       stex_internal_copy(ccb->cmd, p, &count, scsi_sg_count(ccb->cmd),
+                          ST_TO_CMD);
 }
 
 static void
@@ -594,8 +554,10 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
                unsigned char page;
                page = cmd->cmnd[2] & 0x3f;
                if (page == 0x8 || page == 0x3f) {
-                       stex_direct_copy(cmd, ms10_caching_page,
-                                       sizeof(ms10_caching_page));
+                       size_t cp_len = sizeof(ms10_caching_page);
+                       stex_internal_copy(cmd, ms10_caching_page,
+                                          &cp_len, scsi_sg_count(cmd),
+                                          ST_TO_CMD);
                        cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
                        done(cmd);
                } else
@@ -624,8 +586,10 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
                if (id != host->max_id - 1)
                        break;
                if (lun == 0 && (cmd->cmnd[1] & INQUIRY_EVPD) == 0) {
-                       stex_direct_copy(cmd, console_inq_page,
-                               sizeof(console_inq_page));
+                       size_t cp_len = sizeof(console_inq_page);
+                       stex_internal_copy(cmd, console_inq_page,
+                                          &cp_len, scsi_sg_count(cmd),
+                                          ST_TO_CMD);
                        cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
                        done(cmd);
                } else
@@ -634,6 +598,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
        case PASSTHRU_CMD:
                if (cmd->cmnd[1] == PASSTHRU_GET_DRVVER) {
                        struct st_drvver ver;
+                       size_t cp_len = sizeof(ver);
                        ver.major = ST_VER_MAJOR;
                        ver.minor = ST_VER_MINOR;
                        ver.oem = ST_OEM;
@@ -641,7 +606,9 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
                        ver.signature[0] = PASSTHRU_SIGNATURE;
                        ver.console_id = host->max_id - 1;
                        ver.host_no = hba->host->host_no;
-                       cmd->result = stex_direct_copy(cmd, &ver, sizeof(ver)) ?
+                       stex_internal_copy(cmd, &ver, &cp_len,
+                                          scsi_sg_count(cmd), ST_TO_CMD);
+                       cmd->result = sizeof(ver) == cp_len ?
                                DID_OK << 16 | COMMAND_COMPLETE << 8 :
                                DID_ERROR << 16 | COMMAND_COMPLETE << 8;
                        done(cmd);
@@ -678,18 +645,6 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
        return 0;
 }
 
-static void stex_unmap_sg(struct st_hba *hba, struct scsi_cmnd *cmd)
-{
-       if (cmd->sc_data_direction != DMA_NONE) {
-               if (cmd->use_sg)
-                       pci_unmap_sg(hba->pdev, cmd->request_buffer,
-                               cmd->use_sg, cmd->sc_data_direction);
-               else
-                       pci_unmap_single(hba->pdev, cmd->SCp.dma_handle,
-                               cmd->request_bufflen, cmd->sc_data_direction);
-       }
-}
-
 static void stex_scsi_done(struct st_ccb *ccb)
 {
        struct scsi_cmnd *cmd = ccb->cmd;
@@ -746,7 +701,7 @@ static void stex_copy_data(struct st_ccb *ccb,
        if (ccb->cmd == NULL)
                return;
        stex_internal_copy(ccb->cmd,
-               resp->variable, &count, ccb->sg_count, ST_TO_CMD);
+               resp->variable, &count, scsi_sg_count(ccb->cmd), ST_TO_CMD);
 }
 
 static void stex_ys_commands(struct st_hba *hba,
@@ -756,8 +711,8 @@ static void stex_ys_commands(struct st_hba *hba,
 
        if (ccb->cmd->cmnd[0] == MGT_CMD &&
                resp->scsi_status != SAM_STAT_CHECK_CONDITION) {
-               ccb->cmd->request_bufflen =
-                       le32_to_cpu(*(__le32 *)&resp->variable[0]);
+               scsi_set_resid(ccb->cmd, scsi_bufflen(ccb->cmd) -
+                       le32_to_cpu(*(__le32 *)&resp->variable[0]));
                return;
        }
 
@@ -771,7 +726,7 @@ static void stex_ys_commands(struct st_hba *hba,
 
                count = STEX_EXTRA_SIZE;
                stex_internal_copy(ccb->cmd, hba->copy_buffer,
-                       &count, ccb->sg_count, ST_FROM_CMD);
+                       &count, scsi_sg_count(ccb->cmd), ST_FROM_CMD);
                inq_data = (ST_INQ *)hba->copy_buffer;
                if (inq_data->DeviceTypeQualifier != 0)
                        ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT;
@@ -855,7 +810,7 @@ static void stex_mu_intr(struct st_hba *hba, u32 doorbell)
                                ccb->cmd->cmnd[1] == PASSTHRU_GET_ADAPTER))
                                stex_controller_info(hba, ccb);
 
-                       stex_unmap_sg(hba, ccb->cmd);
+                       scsi_dma_unmap(ccb->cmd);
                        stex_scsi_done(ccb);
                        hba->out_req_cnt--;
                } else if (ccb->req_type & PASSTHRU_REQ_TYPE) {
@@ -1028,7 +983,7 @@ static int stex_abort(struct scsi_cmnd *cmd)
        }
 
 fail_out:
-       stex_unmap_sg(hba, cmd);
+       scsi_dma_unmap(cmd);
        hba->wait_ccb->req = NULL; /* nullify the req's future return */
        hba->wait_ccb = NULL;
        result = FAILED;