aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--drivers/ide/ide-atapi.c52
-rw-r--r--drivers/ide/ide-cd.c28
-rw-r--r--drivers/ide/ide-io.c3
-rw-r--r--drivers/ide/ide-tape.c3
-rw-r--r--include/linux/ide.h2
5 files changed, 52 insertions, 36 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 */
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 7b21c7eac5b0..392a5bdf2fd3 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -210,10 +210,12 @@ static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq)
210{ 210{
211 /* 211 /*
212 * For REQ_TYPE_SENSE, "rq->special" points to the original 212 * For REQ_TYPE_SENSE, "rq->special" points to the original
213 * failed request 213 * failed request. Also, the sense data should be read
214 * directly from rq which might be different from the original
215 * sense buffer if it got copied during mapping.
214 */ 216 */
215 struct request *failed = (struct request *)rq->special; 217 struct request *failed = (struct request *)rq->special;
216 struct request_sense *sense = &drive->sense_data; 218 void *sense = bio_data(rq->bio);
217 219
218 if (failed) { 220 if (failed) {
219 if (failed->sense) { 221 if (failed->sense) {
@@ -398,7 +400,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat)
398 400
399 /* if we got a CHECK_CONDITION status, queue a request sense command */ 401 /* if we got a CHECK_CONDITION status, queue a request sense command */
400 if (stat & ATA_ERR) 402 if (stat & ATA_ERR)
401 ide_queue_sense_rq(drive, NULL); 403 return ide_queue_sense_rq(drive, NULL) ? 2 : 1;
402 return 1; 404 return 1;
403 405
404end_request: 406end_request:
@@ -412,8 +414,7 @@ end_request:
412 414
413 hwif->rq = NULL; 415 hwif->rq = NULL;
414 416
415 ide_queue_sense_rq(drive, rq); 417 return ide_queue_sense_rq(drive, rq) ? 2 : 1;
416 return 1;
417 } else 418 } else
418 return 2; 419 return 2;
419} 420}
@@ -507,8 +508,12 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
507 rq->cmd_flags |= cmd_flags; 508 rq->cmd_flags |= cmd_flags;
508 rq->timeout = timeout; 509 rq->timeout = timeout;
509 if (buffer) { 510 if (buffer) {
510 rq->data = buffer; 511 error = blk_rq_map_kern(drive->queue, rq, buffer,
511 rq->data_len = *bufflen; 512 *bufflen, GFP_NOIO);
513 if (error) {
514 blk_put_request(rq);
515 return error;
516 }
512 } 517 }
513 518
514 error = blk_execute_rq(drive->queue, info->disk, rq, 0); 519 error = blk_execute_rq(drive->queue, info->disk, rq, 0);
@@ -802,15 +807,10 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq)
802 drive->dma = 0; 807 drive->dma = 0;
803 808
804 /* sg request */ 809 /* sg request */
805 if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) { 810 if (rq->bio) {
806 struct request_queue *q = drive->queue; 811 struct request_queue *q = drive->queue;
812 char *buf = bio_data(rq->bio);
807 unsigned int alignment; 813 unsigned int alignment;
808 char *buf;
809
810 if (rq->bio)
811 buf = bio_data(rq->bio);
812 else
813 buf = rq->data;
814 814
815 drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); 815 drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
816 816
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 9b9e8b1aae5e..3245c2dbda33 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -481,6 +481,9 @@ void do_ide_request(struct request_queue *q)
481 481
482 spin_unlock_irq(q->queue_lock); 482 spin_unlock_irq(q->queue_lock);
483 483
484 /* HLD do_request() callback might sleep, make sure it's okay */
485 might_sleep();
486
484 if (ide_lock_host(host, hwif)) 487 if (ide_lock_host(host, hwif))
485 goto plug_device_2; 488 goto plug_device_2;
486 489
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index 8324dfa78a3f..9b762a2d5d95 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -850,6 +850,9 @@ out:
850 850
851 cmd.rq = rq; 851 cmd.rq = rq;
852 852
853 ide_init_sg_cmd(&cmd, pc->req_xfer);
854 ide_map_sg(drive, &cmd);
855
853 return ide_tape_issue_pc(drive, &cmd, pc); 856 return ide_tape_issue_pc(drive, &cmd, pc);
854} 857}
855 858
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 9e67ccac3c1f..1957461ac762 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1183,7 +1183,7 @@ void ide_create_request_sense_cmd(ide_drive_t *, struct ide_atapi_pc *);
1183void ide_retry_pc(ide_drive_t *drive); 1183void ide_retry_pc(ide_drive_t *drive);
1184 1184
1185void ide_prep_sense(ide_drive_t *drive, struct request *rq); 1185void ide_prep_sense(ide_drive_t *drive, struct request *rq);
1186void ide_queue_sense_rq(ide_drive_t *drive, void *special); 1186int ide_queue_sense_rq(ide_drive_t *drive, void *special);
1187 1187
1188int ide_cd_expiry(ide_drive_t *); 1188int ide_cd_expiry(ide_drive_t *);
1189 1189