aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-atapi.c
diff options
context:
space:
mode:
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 */