Make sure that each error condition during the execution of an HDIO_DRIVE_RESET ioctl is actually reported to the calling process. Signed-off-by: Elias Oltmanns <eo@xxxxxxxxxxxxxx> --- Documentation/ioctl/hdio.txt | 2 ++ drivers/ide/ide-iops.c | 18 +++++++++++------- drivers/ide/ide.c | 10 ++++++---- drivers/ide/pci/siimage.c | 3 +-- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/Documentation/ioctl/hdio.txt b/Documentation/ioctl/hdio.txt index a859734..28f5fdc 100644 --- a/Documentation/ioctl/hdio.txt +++ b/Documentation/ioctl/hdio.txt @@ -509,6 +509,8 @@ HDIO_DRIVE_RESET execute a device reset error returns: EACCES Access denied: requires CAP_SYS_ADMIN EBUSY Device busy: reset operation in progress already + ENXIO No such device: phy dead or ctl_addr == 0 + EIO I/O error: reset timed out or hardware error notes: diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index d68fc2a..286fc15 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -905,12 +905,12 @@ void ide_execute_pkt_cmd(ide_drive_t *drive) } EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd); -static inline void ide_complete_drive_reset(ide_drive_t *drive) +static inline void ide_complete_drive_reset(ide_drive_t *drive, int err) { struct request *rq = HWGROUP(drive)->rq; if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) - ide_end_request(drive, 1, 0); + ide_end_request(drive, err ? err : 1, 0); } /* needed below */ @@ -949,7 +949,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) /* done polling */ hwgroup->polling = 0; hwgroup->resetting = 0; - ide_complete_drive_reset(drive); + ide_complete_drive_reset(drive, 0); return ide_stopped; } @@ -965,9 +965,11 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) ide_hwif_t *hwif = HWIF(drive); const struct ide_port_ops *port_ops = hwif->port_ops; u8 tmp; + int err = 0; if (port_ops && port_ops->reset_poll) { - if (port_ops->reset_poll(drive)) { + err = port_ops->reset_poll(drive); + if (err) { printk(KERN_ERR "%s: host reset_poll failure for %s.\n", hwif->name, drive->name); goto out; @@ -984,6 +986,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) } printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); drive->failures++; + err = -EIO; } else { printk("%s: reset: ", hwif->name); tmp = ide_read_error(drive); @@ -1010,12 +1013,13 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) if (tmp & 0x80) printk("; slave: failed"); printk("\n"); + err = -EIO; } } +out: hwgroup->polling = 0; /* done polling */ hwgroup->resetting = 0; /* done reset attempt */ -out: - ide_complete_drive_reset(drive); + ide_complete_drive_reset(drive, err); return ide_stopped; } @@ -1123,7 +1127,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) if (io_ports->ctl_addr == 0) { spin_unlock_irqrestore(&ide_lock, flags); - ide_complete_drive_reset(drive); + ide_complete_drive_reset(drive, -ENXIO); return ide_stopped; } diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index bf17529..af46549 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -529,17 +529,20 @@ static int generic_ide_resume(struct device *dev) return err; } -static void generic_drive_reset(ide_drive_t *drive) +static int generic_drive_reset(ide_drive_t *drive) { struct request *rq; + int ret = 0; rq = blk_get_request(drive->queue, READ, __GFP_WAIT); rq->cmd_type = REQ_TYPE_SPECIAL; rq->cmd_len = 1; rq->cmd[0] = REQ_DRIVE_RESET; rq->cmd_flags |= REQ_SOFTBARRIER; - blk_execute_rq(drive->queue, NULL, rq, 1); + if (blk_execute_rq(drive->queue, NULL, rq, 1)) + ret = rq->errors; blk_put_request(rq); + return ret; } int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, @@ -622,9 +625,8 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device return -EBUSY; } spin_unlock_irqrestore(&ide_lock, flags); - generic_drive_reset(drive); - return 0; + return generic_drive_reset(drive); case HDIO_GET_BUSSTATE: if (!capable(CAP_SYS_ADMIN)) return -EACCES; diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index b75e9bb..6e9d765 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -421,8 +421,7 @@ static int sil_sata_reset_poll(ide_drive_t *drive) if ((sata_stat & 0x03) != 0x03) { printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", hwif->name, sata_stat); - HWGROUP(drive)->polling = 0; - return ide_started; + return -ENXIO; } } -- To unsubscribe from this list: send the line "unsubscribe linux-ide" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html