diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2008-02-22 15:11:04 +0100 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-02-23 00:20:59 +0100 |
commit | c9872fe1add5709fffd42249e6ca1080999aa06a (patch) | |
tree | 8ee1278a998220785a3eaf1ae7c3fd4ba54ced22 | |
parent | [SCSI] stex: stex_direct_copy shouldn't call dma_map_sg (diff) | |
download | linux-c9872fe1add5709fffd42249e6ca1080999aa06a.tar.xz linux-c9872fe1add5709fffd42249e6ca1080999aa06a.zip |
[SCSI] stex: stex_internal_copy should be called with sg_count in struct st_ccb
stex_internal_copy copies an in-kernel buffer to a sg list by using
scsi_kmap_atomic_sg. Some functions calls stex_internal_copy with
sg_count in struct st_ccb, which is the value that dma_map_sg
returned. However it might be shorter than the actual number of sg
entries (if the IOMMU merged the sg entries).
scsi_kmap_atomic_sg doesn't see sg->dma_length so stex_internal_copy
should be called with the actual number of sg entries
(i.e. scsi_sg_count), because if the sg entries were merged,
stex_direct_copy wrongly think that the data length in the sg list is
shorter than the actual length.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Acked-by: Ed Lin <ed.lin@promise.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
-rw-r--r-- | drivers/scsi/stex.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 4b6861cf0417..654430edf74d 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -467,7 +467,8 @@ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb) 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; @@ -485,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 @@ -699,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, @@ -724,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; |