diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2008-02-22 09:11:04 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2008-02-22 18:20:59 -0500 |
commit | c9872fe1add5709fffd42249e6ca1080999aa06a (patch) | |
tree | 8ee1278a998220785a3eaf1ae7c3fd4ba54ced22 | |
parent | 26106e3ca379e30790c41d8835e79395437152ec (diff) |
[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) | |||
467 | size_t count = sizeof(struct st_frame); | 467 | size_t count = sizeof(struct st_frame); |
468 | 468 | ||
469 | p = hba->copy_buffer; | 469 | p = hba->copy_buffer; |
470 | stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count, ST_FROM_CMD); | 470 | stex_internal_copy(ccb->cmd, p, &count, scsi_sg_count(ccb->cmd), |
471 | ST_FROM_CMD); | ||
471 | memset(p->base, 0, sizeof(u32)*6); | 472 | memset(p->base, 0, sizeof(u32)*6); |
472 | *(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0); | 473 | *(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0); |
473 | p->rom_addr = 0; | 474 | p->rom_addr = 0; |
@@ -485,7 +486,8 @@ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb) | |||
485 | p->subid = | 486 | p->subid = |
486 | hba->pdev->subsystem_vendor << 16 | hba->pdev->subsystem_device; | 487 | hba->pdev->subsystem_vendor << 16 | hba->pdev->subsystem_device; |
487 | 488 | ||
488 | stex_internal_copy(ccb->cmd, p, &count, ccb->sg_count, ST_TO_CMD); | 489 | stex_internal_copy(ccb->cmd, p, &count, scsi_sg_count(ccb->cmd), |
490 | ST_TO_CMD); | ||
489 | } | 491 | } |
490 | 492 | ||
491 | static void | 493 | static void |
@@ -699,7 +701,7 @@ static void stex_copy_data(struct st_ccb *ccb, | |||
699 | if (ccb->cmd == NULL) | 701 | if (ccb->cmd == NULL) |
700 | return; | 702 | return; |
701 | stex_internal_copy(ccb->cmd, | 703 | stex_internal_copy(ccb->cmd, |
702 | resp->variable, &count, ccb->sg_count, ST_TO_CMD); | 704 | resp->variable, &count, scsi_sg_count(ccb->cmd), ST_TO_CMD); |
703 | } | 705 | } |
704 | 706 | ||
705 | static void stex_ys_commands(struct st_hba *hba, | 707 | static void stex_ys_commands(struct st_hba *hba, |
@@ -724,7 +726,7 @@ static void stex_ys_commands(struct st_hba *hba, | |||
724 | 726 | ||
725 | count = STEX_EXTRA_SIZE; | 727 | count = STEX_EXTRA_SIZE; |
726 | stex_internal_copy(ccb->cmd, hba->copy_buffer, | 728 | stex_internal_copy(ccb->cmd, hba->copy_buffer, |
727 | &count, ccb->sg_count, ST_FROM_CMD); | 729 | &count, scsi_sg_count(ccb->cmd), ST_FROM_CMD); |
728 | inq_data = (ST_INQ *)hba->copy_buffer; | 730 | inq_data = (ST_INQ *)hba->copy_buffer; |
729 | if (inq_data->DeviceTypeQualifier != 0) | 731 | if (inq_data->DeviceTypeQualifier != 0) |
730 | ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT; | 732 | ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT; |