mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 03:06:10 +00:00
IDE: Report errors during drive reset back to user space
Make sure that each error condition during the execution of an HDIO_DRIVE_RESET ioctl is actually reported to the calling process. Also, unify the exit path of reset_pollfunc() when returning ide_stopped since the need of ->port_ops->reset_poll() to be treated specially has vanished (way back, it seems). Signed-off-by: Elias Oltmanns <eo@nebensachen.de> Cc: "Alan Cox" <alan@lxorguk.ukuu.org.uk> Cc: "Randy Dunlap" <randy.dunlap@oracle.com> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
This commit is contained in:
parent
bb7ee9b1ec
commit
64a8f00ff1
4 changed files with 20 additions and 13 deletions
|
@ -508,6 +508,8 @@ HDIO_DRIVE_RESET execute a device reset
|
|||
|
||||
error returns:
|
||||
EACCES Access denied: requires CAP_SYS_ADMIN
|
||||
ENXIO No such device: phy dead or ctl_addr == 0
|
||||
EIO I/O error: reset timed out or hardware error
|
||||
|
||||
notes:
|
||||
|
||||
|
|
|
@ -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 = drive->hwif->hwgroup->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 */
|
||||
|
@ -948,7 +948,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
|
|||
}
|
||||
/* done polling */
|
||||
hwgroup->polling = 0;
|
||||
ide_complete_drive_reset(drive);
|
||||
ide_complete_drive_reset(drive, 0);
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
|
@ -964,9 +964,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;
|
||||
|
@ -983,6 +985,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);
|
||||
|
@ -1009,11 +1012,12 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
|
|||
if (tmp & 0x80)
|
||||
printk("; slave: failed");
|
||||
printk("\n");
|
||||
err = -EIO;
|
||||
}
|
||||
}
|
||||
hwgroup->polling = 0; /* done polling */
|
||||
out:
|
||||
ide_complete_drive_reset(drive);
|
||||
hwgroup->polling = 0; /* done polling */
|
||||
ide_complete_drive_reset(drive, err);
|
||||
return ide_stopped;
|
||||
}
|
||||
|
||||
|
@ -1120,7 +1124,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
@ -616,8 +619,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
|
|||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EACCES;
|
||||
|
||||
generic_drive_reset(drive);
|
||||
return 0;
|
||||
return generic_drive_reset(drive);
|
||||
|
||||
case HDIO_GET_BUSSTATE:
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue