diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2007-10-16 05:20:52 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2007-10-16 05:20:52 -0400 |
commit | d274a9878bcd028712ea4f3d96db72b63d3eba4d (patch) | |
tree | 156c237e5fa38e86e3caa57f8bdac07aef0da94d /drivers/scsi/ide-scsi.c | |
parent | 2f08fe5221b79aa1e240aa3938e9de6ab0baf1d3 (diff) |
ide-scsi: sg chaining support
Acked-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers/scsi/ide-scsi.c')
-rw-r--r-- | drivers/scsi/ide-scsi.c | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index d81bb076a15a..d297f64cd432 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c | |||
@@ -70,6 +70,7 @@ typedef struct idescsi_pc_s { | |||
70 | u8 *buffer; /* Data buffer */ | 70 | u8 *buffer; /* Data buffer */ |
71 | u8 *current_position; /* Pointer into the above buffer */ | 71 | u8 *current_position; /* Pointer into the above buffer */ |
72 | struct scatterlist *sg; /* Scatter gather table */ | 72 | struct scatterlist *sg; /* Scatter gather table */ |
73 | struct scatterlist *last_sg; /* Last sg element */ | ||
73 | int b_count; /* Bytes transferred from current entry */ | 74 | int b_count; /* Bytes transferred from current entry */ |
74 | struct scsi_cmnd *scsi_cmd; /* SCSI command */ | 75 | struct scsi_cmnd *scsi_cmd; /* SCSI command */ |
75 | void (*done)(struct scsi_cmnd *); /* Scsi completion routine */ | 76 | void (*done)(struct scsi_cmnd *); /* Scsi completion routine */ |
@@ -173,12 +174,6 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne | |||
173 | char *buf; | 174 | char *buf; |
174 | 175 | ||
175 | while (bcount) { | 176 | while (bcount) { |
176 | if (pc->sg - scsi_sglist(pc->scsi_cmd) > | ||
177 | scsi_sg_count(pc->scsi_cmd)) { | ||
178 | printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n"); | ||
179 | idescsi_discard_data (drive, bcount); | ||
180 | return; | ||
181 | } | ||
182 | count = min(pc->sg->length - pc->b_count, bcount); | 177 | count = min(pc->sg->length - pc->b_count, bcount); |
183 | if (PageHighMem(pc->sg->page)) { | 178 | if (PageHighMem(pc->sg->page)) { |
184 | unsigned long flags; | 179 | unsigned long flags; |
@@ -197,10 +192,17 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne | |||
197 | } | 192 | } |
198 | bcount -= count; pc->b_count += count; | 193 | bcount -= count; pc->b_count += count; |
199 | if (pc->b_count == pc->sg->length) { | 194 | if (pc->b_count == pc->sg->length) { |
200 | pc->sg++; | 195 | if (pc->sg == pc->last_sg) |
196 | break; | ||
197 | pc->sg = sg_next(pc->sg); | ||
201 | pc->b_count = 0; | 198 | pc->b_count = 0; |
202 | } | 199 | } |
203 | } | 200 | } |
201 | |||
202 | if (bcount) { | ||
203 | printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n"); | ||
204 | idescsi_discard_data (drive, bcount); | ||
205 | } | ||
204 | } | 206 | } |
205 | 207 | ||
206 | static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigned int bcount) | 208 | static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigned int bcount) |
@@ -209,12 +211,6 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign | |||
209 | char *buf; | 211 | char *buf; |
210 | 212 | ||
211 | while (bcount) { | 213 | while (bcount) { |
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"); | ||
215 | idescsi_output_zeros (drive, bcount); | ||
216 | return; | ||
217 | } | ||
218 | count = min(pc->sg->length - pc->b_count, bcount); | 214 | count = min(pc->sg->length - pc->b_count, bcount); |
219 | if (PageHighMem(pc->sg->page)) { | 215 | if (PageHighMem(pc->sg->page)) { |
220 | unsigned long flags; | 216 | unsigned long flags; |
@@ -233,10 +229,17 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign | |||
233 | } | 229 | } |
234 | bcount -= count; pc->b_count += count; | 230 | bcount -= count; pc->b_count += count; |
235 | if (pc->b_count == pc->sg->length) { | 231 | if (pc->b_count == pc->sg->length) { |
236 | pc->sg++; | 232 | if (pc->sg == pc->last_sg) |
233 | break; | ||
234 | pc->sg = sg_next(pc->sg); | ||
237 | pc->b_count = 0; | 235 | pc->b_count = 0; |
238 | } | 236 | } |
239 | } | 237 | } |
238 | |||
239 | if (bcount) { | ||
240 | printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n"); | ||
241 | idescsi_output_zeros (drive, bcount); | ||
242 | } | ||
240 | } | 243 | } |
241 | 244 | ||
242 | static void hexdump(u8 *x, int len) | 245 | static void hexdump(u8 *x, int len) |
@@ -804,6 +807,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd, | |||
804 | memcpy (pc->c, cmd->cmnd, cmd->cmd_len); | 807 | memcpy (pc->c, cmd->cmnd, cmd->cmd_len); |
805 | pc->buffer = NULL; | 808 | pc->buffer = NULL; |
806 | pc->sg = scsi_sglist(cmd); | 809 | pc->sg = scsi_sglist(cmd); |
810 | pc->last_sg = sg_last(pc->sg, cmd->use_sg); | ||
807 | pc->b_count = 0; | 811 | pc->b_count = 0; |
808 | pc->request_transfer = pc->buffer_size = scsi_bufflen(cmd); | 812 | pc->request_transfer = pc->buffer_size = scsi_bufflen(cmd); |
809 | pc->scsi_cmd = cmd; | 813 | pc->scsi_cmd = cmd; |