diff --git a/drivers/ide/ide-eh.c b/drivers/ide/ide-eh.c index 1231b5e486f2..e2c04886616f 100644 --- a/drivers/ide/ide-eh.c +++ b/drivers/ide/ide-eh.c @@ -124,7 +124,16 @@ ide_startstop_t ide_error(ide_drive_t *drive, const char *msg, u8 stat) /* retry only "normal" I/O: */ if (!blk_fs_request(rq)) { rq->errors = 1; - ide_end_drive_cmd(drive, stat, err); + if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { + ide_task_t *task = rq->special; + + if (task) + ide_complete_task(drive, task, stat, err); + } else if (blk_pm_request(rq)) { + ide_complete_pm_rq(drive, rq); + return ide_stopped; + } + ide_complete_rq(drive, err); return ide_stopped; } diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index d1a79e8e0d69..39e7fda37c5f 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -101,7 +101,7 @@ static int ide_floppy_end_request(ide_drive_t *drive, int uptodate, int nsecs) } rq->errors = error; /* fixme: need to move this local also */ - ide_end_drive_cmd(drive, 0, 0); + ide_complete_rq(drive, 0); return 0; } diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index b8426e9c0906..4a97a97e56c4 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -144,49 +144,28 @@ int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq, } EXPORT_SYMBOL_GPL(ide_end_dequeued_request); -static void ide_complete_task(ide_drive_t *drive, ide_task_t *task, - u8 stat, u8 err) +void ide_complete_task(ide_drive_t *drive, ide_task_t *task, u8 stat, u8 err) { struct ide_taskfile *tf = &task->tf; + struct request *rq = task->rq; tf->error = err; tf->status = stat; drive->hwif->tp_ops->tf_read(drive, task); + if (rq && rq->cmd_type == REQ_TYPE_ATA_TASKFILE) + memcpy(rq->special, task, sizeof(*task)); + if (task->tf_flags & IDE_TFLAG_DYN) kfree(task); } -/** - * ide_end_drive_cmd - end an explicit drive command - * @drive: command - * @stat: status bits - * @err: error bits - * - * Clean up after success/failure of an explicit drive command. - * These get thrown onto the queue so they are synchronized with - * real I/O operations on the drive. - * - * In LBA48 mode we have to read the register set twice to get - * all the extra information out. - */ - -void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) +void ide_complete_rq(ide_drive_t *drive, u8 err) { ide_hwif_t *hwif = drive->hwif; struct request *rq = hwif->rq; - if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { - ide_task_t *task = (ide_task_t *)rq->special; - - if (task) - ide_complete_task(drive, task, stat, err); - } else if (blk_pm_request(rq)) { - ide_complete_pm_rq(drive, rq); - return; - } - hwif->rq = NULL; rq->errors = err; @@ -195,7 +174,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) blk_rq_bytes(rq)))) BUG(); } -EXPORT_SYMBOL(ide_end_drive_cmd); +EXPORT_SYMBOL(ide_complete_rq); void ide_kill_rq(ide_drive_t *drive, struct request *rq) { @@ -358,8 +337,9 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, #ifdef DEBUG printk("%s: DRIVE_CMD (null)\n", drive->name); #endif - ide_end_drive_cmd(drive, hwif->tp_ops->read_status(hwif), - ide_read_error(drive)); + (void)hwif->tp_ops->read_status(hwif); + + ide_complete_rq(drive, ide_read_error(drive)); return ide_stopped; } diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 4e6181c7bbda..de2d926e66c2 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -502,7 +502,7 @@ static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects) spin_lock_irqsave(&tape->lock, flags); - ide_end_drive_cmd(drive, 0, 0); + ide_complete_rq(drive, 0); spin_unlock_irqrestore(&tape->lock, flags); return 0; diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 02240a3ee0fb..297cf6f4c723 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -147,12 +147,9 @@ static ide_startstop_t task_no_data_intr(ide_drive_t *drive) } } return ide_error(drive, "task_no_data_intr", stat); - /* calls ide_end_drive_cmd */ } - if (!custom) - ide_end_drive_cmd(drive, stat, ide_read_error(drive)); - else if (tf->command == ATA_CMD_IDLEIMMEDIATE) { + if (custom && tf->command == ATA_CMD_IDLEIMMEDIATE) { hwif->tp_ops->tf_read(drive, task); if (tf->lbal != 0xc4) { printk(KERN_ERR "%s: head unload failed!\n", @@ -160,10 +157,22 @@ static ide_startstop_t task_no_data_intr(ide_drive_t *drive) ide_tf_dump(drive->name, tf); } else drive->dev_flags |= IDE_DFLAG_PARKED; - ide_end_drive_cmd(drive, stat, ide_read_error(drive)); - } else if (tf->command == ATA_CMD_SET_MULTI) + } else if (custom && tf->command == ATA_CMD_SET_MULTI) drive->mult_count = drive->mult_req; + if (custom == 0 || tf->command == ATA_CMD_IDLEIMMEDIATE) { + struct request *rq = hwif->rq; + u8 err = ide_read_error(drive); + + if (blk_pm_request(rq)) + ide_complete_pm_rq(drive, rq); + else { + if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) + ide_complete_task(drive, task, stat, err); + ide_complete_rq(drive, err); + } + } + return ide_stopped; } @@ -321,9 +330,12 @@ static ide_startstop_t task_error(ide_drive_t *drive, struct request *rq, void task_end_request(ide_drive_t *drive, struct request *rq, u8 stat) { if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { + ide_task_t *task = rq->special; u8 err = ide_read_error(drive); - ide_end_drive_cmd(drive, stat, err); + if (task) + ide_complete_task(drive, task, stat, err); + ide_complete_rq(drive, err); return; } diff --git a/include/linux/ide.h b/include/linux/ide.h index c5ac19e43fc0..83bed2f4378a 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1158,7 +1158,8 @@ extern ide_startstop_t ide_do_reset (ide_drive_t *); extern int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, int arg); -extern void ide_end_drive_cmd(ide_drive_t *, u8, u8); +void ide_complete_task(ide_drive_t *, ide_task_t *, u8, u8); +void ide_complete_rq(ide_drive_t *, u8); void ide_tf_dump(const char *, struct ide_taskfile *);