summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2008-02-22 23:11:03 +0900
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-02-22 17:20:39 -0600
commit26106e3ca379e30790c41d8835e79395437152ec (patch)
treec3f7825595819d4d607b642499616d3e5055bcb4
parenteafe1df9e311034cce204e43c0e45c91723b802f (diff)
[SCSI] stex: stex_direct_copy shouldn't call dma_map_sg
stex_direct_copy copies an in-kernel buffer to a sg list in order to spoof some SCSI commands. stex_direct_copy calls dma_map_sg and then stex_internal_copy with the value that dma_map_sg returned. It calls scsi_kmap_atomic_sg to copy data. scsi_kmap_atomic_sg doesn't see sg->dma_length so if dma_map_sg merges sg entries, stex_internal_copy gets the smaller number of sg entries than the acutual number, which means it wrongly think that the data length in the sg list is shorter than the actual length. stex_direct_copy shouldn't call dma_map_sg and it doesn't need since this code path doesn't involve dma transfers. This patch removes stex_direct_copy and simply calls stex_internal_copy with the actual number of sg entries. 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.c34
1 files changed, 12 insertions, 22 deletions
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index 72f6d801535..4b6861cf041 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -461,23 +461,6 @@ static void stex_internal_copy(struct scsi_cmnd *cmd,
}
}
-static int stex_direct_copy(struct scsi_cmnd *cmd,
- const void *src, size_t count)
-{
- size_t cp_len = count;
- int n_elem = 0;
-
- n_elem = scsi_dma_map(cmd);
- if (n_elem < 0)
- return 0;
-
- stex_internal_copy(cmd, src, &cp_len, n_elem, ST_TO_CMD);
-
- scsi_dma_unmap(cmd);
-
- return cp_len == count;
-}
-
static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
{
struct st_frame *p;
@@ -569,8 +552,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
@@ -599,8 +584,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
@@ -609,6 +596,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;
@@ -616,7 +604,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);