aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-atapi.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-04-18 18:00:42 -0400
committerTejun Heo <tj@kernel.org>2009-04-18 18:00:42 -0400
commit5c4be57249e2e09136446597d2fe2a967c6ffef0 (patch)
tree02509609a80013e0e1e3d447ddc41805f014cc50 /drivers/ide/ide-atapi.c
parent6b544fcc8cd0a04eb42de9d1ecdd345e979d6ada (diff)
ide-cd,atapi: use bio for internal commands
Impact: unify request data buffer handling rq->data is used mostly to pass kernel buffer through request queue without using bio. There are only a couple of places which still do this in kernel and converting to bio isn't difficult. This patch converts ide-cd and atapi to use bio instead of rq->data for request sense and internal pc commands. With previous change to unify sense request handling, this is relatively easily achieved by adding blk_rq_map_kern() during sense_rq prep and PC issue. If blk_rq_map_kern() fails for sense, the error is deferred till sense issue and aborts the failed command which triggered the sense. Note that this is a slim possibility as sense prep is done on each command issue, so for the above condition to actually trigger, all preps since the last sense issue till the issue of the request which would require a sense should fail. * do_request functions might sleep now. This should be okay as ide request_fn - do_ide_request() - is invoked only from make_request and plug work. Make sure this is the case by adding might_sleep() to do_ide_request(). * Functions which access the read sense data before the sense request is complete now should access bio_data(sense_rq->bio) as the sense buffer might have been copied during blk_rq_map_kern(). * ide-tape updated to map sg. * cdrom_do_block_pc() now doesn't have to deal with REQ_TYPE_ATA_PC special case. Simplified. * tp_ops->output/input_data path dropped from ide_pc_intr(). Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ide/ide-atapi.c')
-rw-r--r--drivers/ide/ide-atapi.c52
1 files changed, 31 insertions, 21 deletions
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c
index 972c522516f8..5cefe12f5622 100644
--- a/drivers/ide/ide-atapi.c
+++ b/drivers/ide/ide-atapi.c
@@ -94,16 +94,18 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk,
94 rq->special = (char *)pc; 94 rq->special = (char *)pc;
95 95
96 if (pc->req_xfer) { 96 if (pc->req_xfer) {
97 rq->data = pc->buf; 97 error = blk_rq_map_kern(drive->queue, rq, pc->buf, pc->req_xfer,
98 rq->data_len = pc->req_xfer; 98 GFP_NOIO);
99 if (error)
100 goto put_req;
99 } 101 }
100 102
101 memcpy(rq->cmd, pc->c, 12); 103 memcpy(rq->cmd, pc->c, 12);
102 if (drive->media == ide_tape) 104 if (drive->media == ide_tape)
103 rq->cmd[13] = REQ_IDETAPE_PC1; 105 rq->cmd[13] = REQ_IDETAPE_PC1;
104 error = blk_execute_rq(drive->queue, disk, rq, 0); 106 error = blk_execute_rq(drive->queue, disk, rq, 0);
107put_req:
105 blk_put_request(rq); 108 blk_put_request(rq);
106
107 return error; 109 return error;
108} 110}
109EXPORT_SYMBOL_GPL(ide_queue_pc_tail); 111EXPORT_SYMBOL_GPL(ide_queue_pc_tail);
@@ -168,6 +170,7 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
168 struct request_sense *sense = &drive->sense_data; 170 struct request_sense *sense = &drive->sense_data;
169 struct request *sense_rq = &drive->sense_rq; 171 struct request *sense_rq = &drive->sense_rq;
170 unsigned int cmd_len, sense_len; 172 unsigned int cmd_len, sense_len;
173 int err;
171 174
172 debug_log("%s: enter\n", __func__); 175 debug_log("%s: enter\n", __func__);
173 176
@@ -193,13 +196,19 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
193 memset(sense, 0, sizeof(*sense)); 196 memset(sense, 0, sizeof(*sense));
194 197
195 blk_rq_init(rq->q, sense_rq); 198 blk_rq_init(rq->q, sense_rq);
196 sense_rq->rq_disk = rq->rq_disk;
197 199
198 sense_rq->data = sense; 200 err = blk_rq_map_kern(drive->queue, sense_rq, sense, sense_len,
201 GFP_NOIO);
202 if (unlikely(err)) {
203 if (printk_ratelimit())
204 printk(KERN_WARNING "%s: failed to map sense buffer\n",
205 drive->name);
206 return;
207 }
208
209 sense_rq->rq_disk = rq->rq_disk;
199 sense_rq->cmd[0] = GPCMD_REQUEST_SENSE; 210 sense_rq->cmd[0] = GPCMD_REQUEST_SENSE;
200 sense_rq->cmd[4] = cmd_len; 211 sense_rq->cmd[4] = cmd_len;
201 sense_rq->data_len = sense_len;
202
203 sense_rq->cmd_type = REQ_TYPE_SENSE; 212 sense_rq->cmd_type = REQ_TYPE_SENSE;
204 sense_rq->cmd_flags |= REQ_PREEMPT; 213 sense_rq->cmd_flags |= REQ_PREEMPT;
205 214
@@ -210,9 +219,14 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq)
210} 219}
211EXPORT_SYMBOL_GPL(ide_prep_sense); 220EXPORT_SYMBOL_GPL(ide_prep_sense);
212 221
213void ide_queue_sense_rq(ide_drive_t *drive, void *special) 222int ide_queue_sense_rq(ide_drive_t *drive, void *special)
214{ 223{
215 BUG_ON(!drive->sense_rq_armed); 224 /* deferred failure from ide_prep_sense() */
225 if (!drive->sense_rq_armed) {
226 printk(KERN_WARNING "%s: failed queue sense request\n",
227 drive->name);
228 return -ENOMEM;
229 }
216 230
217 drive->sense_rq.special = special; 231 drive->sense_rq.special = special;
218 drive->sense_rq_armed = false; 232 drive->sense_rq_armed = false;
@@ -221,6 +235,7 @@ void ide_queue_sense_rq(ide_drive_t *drive, void *special)
221 235
222 elv_add_request(drive->queue, &drive->sense_rq, 236 elv_add_request(drive->queue, &drive->sense_rq,
223 ELEVATOR_INSERT_FRONT, 0); 237 ELEVATOR_INSERT_FRONT, 0);
238 return 0;
224} 239}
225EXPORT_SYMBOL_GPL(ide_queue_sense_rq); 240EXPORT_SYMBOL_GPL(ide_queue_sense_rq);
226 241
@@ -239,13 +254,14 @@ void ide_retry_pc(ide_drive_t *drive)
239 /* init pc from sense_rq */ 254 /* init pc from sense_rq */
240 ide_init_pc(pc); 255 ide_init_pc(pc);
241 memcpy(pc->c, sense_rq->cmd, 12); 256 memcpy(pc->c, sense_rq->cmd, 12);
242 pc->buf = sense_rq->data; 257 pc->buf = bio_data(sense_rq->bio); /* pointer to mapped address */
243 pc->req_xfer = sense_rq->data_len; 258 pc->req_xfer = sense_rq->data_len;
244 259
245 if (drive->media == ide_tape) 260 if (drive->media == ide_tape)
246 set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags); 261 set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags);
247 262
248 ide_queue_sense_rq(drive, pc); 263 if (ide_queue_sense_rq(drive, pc))
264 ide_complete_rq(drive, -EIO, blk_rq_bytes(drive->hwif->rq));
249} 265}
250EXPORT_SYMBOL_GPL(ide_retry_pc); 266EXPORT_SYMBOL_GPL(ide_retry_pc);
251 267
@@ -317,7 +333,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
317 struct ide_cmd *cmd = &hwif->cmd; 333 struct ide_cmd *cmd = &hwif->cmd;
318 struct request *rq = hwif->rq; 334 struct request *rq = hwif->rq;
319 const struct ide_tp_ops *tp_ops = hwif->tp_ops; 335 const struct ide_tp_ops *tp_ops = hwif->tp_ops;
320 xfer_func_t *xferfunc;
321 unsigned int timeout, done; 336 unsigned int timeout, done;
322 u16 bcount; 337 u16 bcount;
323 u8 stat, ireason, dsc = 0; 338 u8 stat, ireason, dsc = 0;
@@ -411,7 +426,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
411 rq->errors = -EIO; 426 rq->errors = -EIO;
412 } 427 }
413 428
414 if (drive->media == ide_tape) 429 if (drive->media == ide_tape && !rq->bio)
415 done = ide_rq_bytes(rq); /* FIXME */ 430 done = ide_rq_bytes(rq); /* FIXME */
416 else 431 else
417 done = blk_rq_bytes(rq); 432 done = blk_rq_bytes(rq);
@@ -448,16 +463,11 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive)
448 return ide_do_reset(drive); 463 return ide_do_reset(drive);
449 } 464 }
450 465
451 xferfunc = write ? tp_ops->output_data : tp_ops->input_data; 466 if (drive->media == ide_tape && pc->bh)
452 467 done = drive->pc_io_buffers(drive, pc, bcount, write);
453 if (drive->media == ide_floppy && pc->buf == NULL) { 468 else {
454 done = min_t(unsigned int, bcount, cmd->nleft); 469 done = min_t(unsigned int, bcount, cmd->nleft);
455 ide_pio_bytes(drive, cmd, write, done); 470 ide_pio_bytes(drive, cmd, write, done);
456 } else if (drive->media == ide_tape && pc->bh) {
457 done = drive->pc_io_buffers(drive, pc, bcount, write);
458 } else {
459 done = min_t(unsigned int, bcount, pc->req_xfer - pc->xferred);
460 xferfunc(drive, NULL, pc->cur_pos, done);
461 } 471 }
462 472
463 /* Update the current position */ 473 /* Update the current position */