diff options
Diffstat (limited to 'drivers/ide/ide-atapi.c')
-rw-r--r-- | drivers/ide/ide-atapi.c | 52 |
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); |
107 | put_req: | ||
105 | blk_put_request(rq); | 108 | blk_put_request(rq); |
106 | |||
107 | return error; | 109 | return error; |
108 | } | 110 | } |
109 | EXPORT_SYMBOL_GPL(ide_queue_pc_tail); | 111 | EXPORT_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 | } |
211 | EXPORT_SYMBOL_GPL(ide_prep_sense); | 220 | EXPORT_SYMBOL_GPL(ide_prep_sense); |
212 | 221 | ||
213 | void ide_queue_sense_rq(ide_drive_t *drive, void *special) | 222 | int 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 | } |
225 | EXPORT_SYMBOL_GPL(ide_queue_sense_rq); | 240 | EXPORT_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 | } |
250 | EXPORT_SYMBOL_GPL(ide_retry_pc); | 266 | EXPORT_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 */ |