diff options
author | Boaz Harrosh <bharrosh@panasas.com> | 2007-09-18 06:27:43 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-12 14:49:08 -0400 |
commit | 427d0bd4fde60f40e9518817d826e48c05262a98 (patch) | |
tree | 973881b7afab9ecec00db9723d9995b2caab20f4 /drivers/scsi/ide-scsi.c | |
parent | 52aeeca9001d1b4037a8e5d0c001ebb5fdc61b37 (diff) |
[SCSI] ide-scsi.: convert to data accessors and !use_sg cleanup
- Convert ide-scsi to the new data accessors and cleanup
the !use_sg code paths.
In old code the driver was trying to translate narrow commands,
if received, to wide commands. This code path still assumed
scsi_cmnd->request_buffer is a linear char pointer.
This means that this driver was broken since 2.6.17.
As suggested by Christoph Hellwig I set
use_10_for_rw = 1; and use_10_for_ms = 1;
for this device and completely killed the translation.
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Acked-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/ide-scsi.c')
-rw-r--r-- | drivers/scsi/ide-scsi.c | 138 |
1 files changed, 13 insertions, 125 deletions
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 1cc01acc2808..3b55a6c10b6b 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c | |||
@@ -82,14 +82,12 @@ typedef struct idescsi_pc_s { | |||
82 | */ | 82 | */ |
83 | #define PC_DMA_IN_PROGRESS 0 /* 1 while DMA in progress */ | 83 | #define PC_DMA_IN_PROGRESS 0 /* 1 while DMA in progress */ |
84 | #define PC_WRITING 1 /* Data direction */ | 84 | #define PC_WRITING 1 /* Data direction */ |
85 | #define PC_TRANSFORM 2 /* transform SCSI commands */ | ||
86 | #define PC_TIMEDOUT 3 /* command timed out */ | 85 | #define PC_TIMEDOUT 3 /* command timed out */ |
87 | #define PC_DMA_OK 4 /* Use DMA */ | 86 | #define PC_DMA_OK 4 /* Use DMA */ |
88 | 87 | ||
89 | /* | 88 | /* |
90 | * SCSI command transformation layer | 89 | * SCSI command transformation layer |
91 | */ | 90 | */ |
92 | #define IDESCSI_TRANSFORM 0 /* Enable/Disable transformation */ | ||
93 | #define IDESCSI_SG_TRANSFORM 1 /* /dev/sg transformation */ | 91 | #define IDESCSI_SG_TRANSFORM 1 /* /dev/sg transformation */ |
94 | 92 | ||
95 | /* | 93 | /* |
@@ -175,7 +173,8 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne | |||
175 | char *buf; | 173 | char *buf; |
176 | 174 | ||
177 | while (bcount) { | 175 | while (bcount) { |
178 | if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) { | 176 | if (pc->sg - scsi_sglist(pc->scsi_cmd) > |
177 | scsi_sg_count(pc->scsi_cmd)) { | ||
179 | printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n"); | 178 | printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n"); |
180 | idescsi_discard_data (drive, bcount); | 179 | idescsi_discard_data (drive, bcount); |
181 | return; | 180 | return; |
@@ -210,7 +209,8 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign | |||
210 | char *buf; | 209 | char *buf; |
211 | 210 | ||
212 | while (bcount) { | 211 | while (bcount) { |
213 | if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) { | 212 | if (pc->sg - scsi_sglist(pc->scsi_cmd) > |
213 | scsi_sg_count(pc->scsi_cmd)) { | ||
214 | printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n"); | 214 | printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n"); |
215 | idescsi_output_zeros (drive, bcount); | 215 | idescsi_output_zeros (drive, bcount); |
216 | return; | 216 | return; |
@@ -239,77 +239,6 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign | |||
239 | } | 239 | } |
240 | } | 240 | } |
241 | 241 | ||
242 | /* | ||
243 | * Most of the SCSI commands are supported directly by ATAPI devices. | ||
244 | * idescsi_transform_pc handles the few exceptions. | ||
245 | */ | ||
246 | static inline void idescsi_transform_pc1 (ide_drive_t *drive, idescsi_pc_t *pc) | ||
247 | { | ||
248 | u8 *c = pc->c, *scsi_buf = pc->buffer, *sc = pc->scsi_cmd->cmnd; | ||
249 | char *atapi_buf; | ||
250 | |||
251 | if (!test_bit(PC_TRANSFORM, &pc->flags)) | ||
252 | return; | ||
253 | if (drive->media == ide_cdrom || drive->media == ide_optical) { | ||
254 | if (c[0] == READ_6 || c[0] == WRITE_6) { | ||
255 | c[8] = c[4]; c[5] = c[3]; c[4] = c[2]; | ||
256 | c[3] = c[1] & 0x1f; c[2] = 0; c[1] &= 0xe0; | ||
257 | c[0] += (READ_10 - READ_6); | ||
258 | } | ||
259 | if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) { | ||
260 | unsigned short new_len; | ||
261 | if (!scsi_buf) | ||
262 | return; | ||
263 | if ((atapi_buf = kmalloc(pc->buffer_size + 4, GFP_ATOMIC)) == NULL) | ||
264 | return; | ||
265 | memset(atapi_buf, 0, pc->buffer_size + 4); | ||
266 | memset (c, 0, 12); | ||
267 | c[0] = sc[0] | 0x40; | ||
268 | c[1] = sc[1]; | ||
269 | c[2] = sc[2]; | ||
270 | new_len = sc[4] + 4; | ||
271 | c[8] = new_len; | ||
272 | c[7] = new_len >> 8; | ||
273 | c[9] = sc[5]; | ||
274 | if (c[0] == MODE_SELECT_10) { | ||
275 | atapi_buf[1] = scsi_buf[0]; /* Mode data length */ | ||
276 | atapi_buf[2] = scsi_buf[1]; /* Medium type */ | ||
277 | atapi_buf[3] = scsi_buf[2]; /* Device specific parameter */ | ||
278 | atapi_buf[7] = scsi_buf[3]; /* Block descriptor length */ | ||
279 | memcpy(atapi_buf + 8, scsi_buf + 4, pc->buffer_size - 4); | ||
280 | } | ||
281 | pc->buffer = atapi_buf; | ||
282 | pc->request_transfer += 4; | ||
283 | pc->buffer_size += 4; | ||
284 | } | ||
285 | } | ||
286 | } | ||
287 | |||
288 | static inline void idescsi_transform_pc2 (ide_drive_t *drive, idescsi_pc_t *pc) | ||
289 | { | ||
290 | u8 *atapi_buf = pc->buffer; | ||
291 | u8 *sc = pc->scsi_cmd->cmnd; | ||
292 | u8 *scsi_buf = pc->scsi_cmd->request_buffer; | ||
293 | |||
294 | if (!test_bit(PC_TRANSFORM, &pc->flags)) | ||
295 | return; | ||
296 | if (drive->media == ide_cdrom || drive->media == ide_optical) { | ||
297 | if (pc->c[0] == MODE_SENSE_10 && sc[0] == MODE_SENSE) { | ||
298 | scsi_buf[0] = atapi_buf[1]; /* Mode data length */ | ||
299 | scsi_buf[1] = atapi_buf[2]; /* Medium type */ | ||
300 | scsi_buf[2] = atapi_buf[3]; /* Device specific parameter */ | ||
301 | scsi_buf[3] = atapi_buf[7]; /* Block descriptor length */ | ||
302 | memcpy(scsi_buf + 4, atapi_buf + 8, pc->request_transfer - 8); | ||
303 | } | ||
304 | if (pc->c[0] == INQUIRY) { | ||
305 | scsi_buf[2] |= 2; /* ansi_revision */ | ||
306 | scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2; /* response data format */ | ||
307 | } | ||
308 | } | ||
309 | if (atapi_buf && atapi_buf != scsi_buf) | ||
310 | kfree(atapi_buf); | ||
311 | } | ||
312 | |||
313 | static void hexdump(u8 *x, int len) | 242 | static void hexdump(u8 *x, int len) |
314 | { | 243 | { |
315 | int i; | 244 | int i; |
@@ -393,7 +322,6 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs) | |||
393 | idescsi_pc_t *pc = (idescsi_pc_t *) rq->special; | 322 | idescsi_pc_t *pc = (idescsi_pc_t *) rq->special; |
394 | int log = test_bit(IDESCSI_LOG_CMD, &scsi->log); | 323 | int log = test_bit(IDESCSI_LOG_CMD, &scsi->log); |
395 | struct Scsi_Host *host; | 324 | struct Scsi_Host *host; |
396 | u8 *scsi_buf; | ||
397 | int errors = rq->errors; | 325 | int errors = rq->errors; |
398 | unsigned long flags; | 326 | unsigned long flags; |
399 | 327 | ||
@@ -434,15 +362,6 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs) | |||
434 | pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16); | 362 | pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16); |
435 | } else { | 363 | } else { |
436 | pc->scsi_cmd->result = DID_OK << 16; | 364 | pc->scsi_cmd->result = DID_OK << 16; |
437 | idescsi_transform_pc2 (drive, pc); | ||
438 | if (log) { | ||
439 | printk ("ide-scsi: %s: suc %lu", drive->name, pc->scsi_cmd->serial_number); | ||
440 | if (!test_bit(PC_WRITING, &pc->flags) && pc->actually_transferred && pc->actually_transferred <= 1024 && pc->buffer) { | ||
441 | printk(", rst = "); | ||
442 | scsi_buf = pc->scsi_cmd->request_buffer; | ||
443 | hexdump(scsi_buf, min_t(unsigned, 16, pc->scsi_cmd->request_bufflen)); | ||
444 | } else printk("\n"); | ||
445 | } | ||
446 | } | 365 | } |
447 | host = pc->scsi_cmd->device->host; | 366 | host = pc->scsi_cmd->device->host; |
448 | spin_lock_irqsave(host->host_lock, flags); | 367 | spin_lock_irqsave(host->host_lock, flags); |
@@ -637,19 +556,14 @@ static int idescsi_map_sg(ide_drive_t *drive, idescsi_pc_t *pc) | |||
637 | return 1; | 556 | return 1; |
638 | 557 | ||
639 | sg = hwif->sg_table; | 558 | sg = hwif->sg_table; |
640 | scsi_sg = pc->scsi_cmd->request_buffer; | 559 | scsi_sg = scsi_sglist(pc->scsi_cmd); |
641 | segments = pc->scsi_cmd->use_sg; | 560 | segments = scsi_sg_count(pc->scsi_cmd); |
642 | 561 | ||
643 | if (segments > hwif->sg_max_nents) | 562 | if (segments > hwif->sg_max_nents) |
644 | return 1; | 563 | return 1; |
645 | 564 | ||
646 | if (!segments) { | 565 | hwif->sg_nents = segments; |
647 | hwif->sg_nents = 1; | 566 | memcpy(sg, scsi_sg, sizeof(*sg) * segments); |
648 | sg_init_one(sg, pc->scsi_cmd->request_buffer, pc->request_transfer); | ||
649 | } else { | ||
650 | hwif->sg_nents = segments; | ||
651 | memcpy(sg, scsi_sg, sizeof(*sg) * segments); | ||
652 | } | ||
653 | 567 | ||
654 | return 0; | 568 | return 0; |
655 | } | 569 | } |
@@ -744,7 +658,6 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) | |||
744 | { | 658 | { |
745 | if (drive->id && (drive->id->config & 0x0060) == 0x20) | 659 | if (drive->id && (drive->id->config & 0x0060) == 0x20) |
746 | set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags); | 660 | set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags); |
747 | set_bit(IDESCSI_TRANSFORM, &scsi->transform); | ||
748 | clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); | 661 | clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); |
749 | #if IDESCSI_DEBUG_LOG | 662 | #if IDESCSI_DEBUG_LOG |
750 | set_bit(IDESCSI_LOG_CMD, &scsi->log); | 663 | set_bit(IDESCSI_LOG_CMD, &scsi->log); |
@@ -838,6 +751,8 @@ static struct block_device_operations idescsi_ops = { | |||
838 | static int idescsi_slave_configure(struct scsi_device * sdp) | 751 | static int idescsi_slave_configure(struct scsi_device * sdp) |
839 | { | 752 | { |
840 | /* Configure detected device */ | 753 | /* Configure detected device */ |
754 | sdp->use_10_for_rw = 1; | ||
755 | sdp->use_10_for_ms = 1; | ||
841 | scsi_adjust_queue_depth(sdp, MSG_SIMPLE_TAG, sdp->host->cmd_per_lun); | 756 | scsi_adjust_queue_depth(sdp, MSG_SIMPLE_TAG, sdp->host->cmd_per_lun); |
842 | return 0; | 757 | return 0; |
843 | } | 758 | } |
@@ -862,24 +777,6 @@ static int idescsi_ioctl (struct scsi_device *dev, int cmd, void __user *arg) | |||
862 | return -EINVAL; | 777 | return -EINVAL; |
863 | } | 778 | } |
864 | 779 | ||
865 | static inline int should_transform(ide_drive_t *drive, struct scsi_cmnd *cmd) | ||
866 | { | ||
867 | idescsi_scsi_t *scsi = drive_to_idescsi(drive); | ||
868 | |||
869 | /* this was a layering violation and we can't support it | ||
870 | anymore, sorry. */ | ||
871 | #if 0 | ||
872 | struct gendisk *disk = cmd->request->rq_disk; | ||
873 | |||
874 | if (disk) { | ||
875 | struct struct scsi_device_Template **p = disk->private_data; | ||
876 | if (strcmp((*p)->scsi_driverfs_driver.name, "sg") == 0) | ||
877 | return test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); | ||
878 | } | ||
879 | #endif | ||
880 | return test_bit(IDESCSI_TRANSFORM, &scsi->transform); | ||
881 | } | ||
882 | |||
883 | static int idescsi_queue (struct scsi_cmnd *cmd, | 780 | static int idescsi_queue (struct scsi_cmnd *cmd, |
884 | void (*done)(struct scsi_cmnd *)) | 781 | void (*done)(struct scsi_cmnd *)) |
885 | { | 782 | { |
@@ -905,23 +802,14 @@ static int idescsi_queue (struct scsi_cmnd *cmd, | |||
905 | pc->flags = 0; | 802 | pc->flags = 0; |
906 | pc->rq = rq; | 803 | pc->rq = rq; |
907 | memcpy (pc->c, cmd->cmnd, cmd->cmd_len); | 804 | memcpy (pc->c, cmd->cmnd, cmd->cmd_len); |
908 | if (cmd->use_sg) { | 805 | pc->buffer = NULL; |
909 | pc->buffer = NULL; | 806 | pc->sg = scsi_sglist(cmd); |
910 | pc->sg = cmd->request_buffer; | ||
911 | } else { | ||
912 | pc->buffer = cmd->request_buffer; | ||
913 | pc->sg = NULL; | ||
914 | } | ||
915 | pc->b_count = 0; | 807 | pc->b_count = 0; |
916 | pc->request_transfer = pc->buffer_size = cmd->request_bufflen; | 808 | pc->request_transfer = pc->buffer_size = scsi_bufflen(cmd); |
917 | pc->scsi_cmd = cmd; | 809 | pc->scsi_cmd = cmd; |
918 | pc->done = done; | 810 | pc->done = done; |
919 | pc->timeout = jiffies + cmd->timeout_per_command; | 811 | pc->timeout = jiffies + cmd->timeout_per_command; |
920 | 812 | ||
921 | if (should_transform(drive, cmd)) | ||
922 | set_bit(PC_TRANSFORM, &pc->flags); | ||
923 | idescsi_transform_pc1 (drive, pc); | ||
924 | |||
925 | if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) { | 813 | if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) { |
926 | printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number); | 814 | printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number); |
927 | hexdump(cmd->cmnd, cmd->cmd_len); | 815 | hexdump(cmd->cmnd, cmd->cmd_len); |