diff options
author | Elias Oltmanns <eo@nebensachen.de> | 2008-07-16 14:33:48 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-07-16 14:33:48 -0400 |
commit | 64a8f00ff19508b3962c8a932375dbae88bee4d6 (patch) | |
tree | 6ec1de97fa6524987f133eee38e30af5e545aeb9 | |
parent | bb7ee9b1ec15358af870a81b0c6a03af29417f99 (diff) |
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>
-rw-r--r-- | Documentation/ioctl/hdio.txt | 2 | ||||
-rw-r--r-- | drivers/ide/ide-iops.c | 18 | ||||
-rw-r--r-- | drivers/ide/ide.c | 10 | ||||
-rw-r--r-- | 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 44d283d6b136..91a6ecbae0bb 100644 --- a/Documentation/ioctl/hdio.txt +++ b/Documentation/ioctl/hdio.txt | |||
@@ -508,6 +508,8 @@ HDIO_DRIVE_RESET execute a device reset | |||
508 | 508 | ||
509 | error returns: | 509 | error returns: |
510 | EACCES Access denied: requires CAP_SYS_ADMIN | 510 | EACCES Access denied: requires CAP_SYS_ADMIN |
511 | ENXIO No such device: phy dead or ctl_addr == 0 | ||
512 | EIO I/O error: reset timed out or hardware error | ||
511 | 513 | ||
512 | notes: | 514 | notes: |
513 | 515 | ||
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 96f63eb12092..44aaec256a30 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) | |||
905 | } | 905 | } |
906 | EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd); | 906 | EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd); |
907 | 907 | ||
908 | static inline void ide_complete_drive_reset(ide_drive_t *drive) | 908 | static inline void ide_complete_drive_reset(ide_drive_t *drive, int err) |
909 | { | 909 | { |
910 | struct request *rq = drive->hwif->hwgroup->rq; | 910 | struct request *rq = drive->hwif->hwgroup->rq; |
911 | 911 | ||
912 | if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) | 912 | if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) |
913 | ide_end_request(drive, 1, 0); | 913 | ide_end_request(drive, err ? err : 1, 0); |
914 | } | 914 | } |
915 | 915 | ||
916 | /* needed below */ | 916 | /* needed below */ |
@@ -948,7 +948,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) | |||
948 | } | 948 | } |
949 | /* done polling */ | 949 | /* done polling */ |
950 | hwgroup->polling = 0; | 950 | hwgroup->polling = 0; |
951 | ide_complete_drive_reset(drive); | 951 | ide_complete_drive_reset(drive, 0); |
952 | return ide_stopped; | 952 | return ide_stopped; |
953 | } | 953 | } |
954 | 954 | ||
@@ -964,9 +964,11 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) | |||
964 | ide_hwif_t *hwif = HWIF(drive); | 964 | ide_hwif_t *hwif = HWIF(drive); |
965 | const struct ide_port_ops *port_ops = hwif->port_ops; | 965 | const struct ide_port_ops *port_ops = hwif->port_ops; |
966 | u8 tmp; | 966 | u8 tmp; |
967 | int err = 0; | ||
967 | 968 | ||
968 | if (port_ops && port_ops->reset_poll) { | 969 | if (port_ops && port_ops->reset_poll) { |
969 | if (port_ops->reset_poll(drive)) { | 970 | err = port_ops->reset_poll(drive); |
971 | if (err) { | ||
970 | printk(KERN_ERR "%s: host reset_poll failure for %s.\n", | 972 | printk(KERN_ERR "%s: host reset_poll failure for %s.\n", |
971 | hwif->name, drive->name); | 973 | hwif->name, drive->name); |
972 | goto out; | 974 | goto out; |
@@ -983,6 +985,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) | |||
983 | } | 985 | } |
984 | printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); | 986 | printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); |
985 | drive->failures++; | 987 | drive->failures++; |
988 | err = -EIO; | ||
986 | } else { | 989 | } else { |
987 | printk("%s: reset: ", hwif->name); | 990 | printk("%s: reset: ", hwif->name); |
988 | tmp = ide_read_error(drive); | 991 | tmp = ide_read_error(drive); |
@@ -1009,11 +1012,12 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) | |||
1009 | if (tmp & 0x80) | 1012 | if (tmp & 0x80) |
1010 | printk("; slave: failed"); | 1013 | printk("; slave: failed"); |
1011 | printk("\n"); | 1014 | printk("\n"); |
1015 | err = -EIO; | ||
1012 | } | 1016 | } |
1013 | } | 1017 | } |
1014 | hwgroup->polling = 0; /* done polling */ | ||
1015 | out: | 1018 | out: |
1016 | ide_complete_drive_reset(drive); | 1019 | hwgroup->polling = 0; /* done polling */ |
1020 | ide_complete_drive_reset(drive, err); | ||
1017 | return ide_stopped; | 1021 | return ide_stopped; |
1018 | } | 1022 | } |
1019 | 1023 | ||
@@ -1120,7 +1124,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) | |||
1120 | 1124 | ||
1121 | if (io_ports->ctl_addr == 0) { | 1125 | if (io_ports->ctl_addr == 0) { |
1122 | spin_unlock_irqrestore(&ide_lock, flags); | 1126 | spin_unlock_irqrestore(&ide_lock, flags); |
1123 | ide_complete_drive_reset(drive); | 1127 | ide_complete_drive_reset(drive, -ENXIO); |
1124 | return ide_stopped; | 1128 | return ide_stopped; |
1125 | } | 1129 | } |
1126 | 1130 | ||
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 1ec983b00511..d4a6b102a772 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -529,17 +529,20 @@ static int generic_ide_resume(struct device *dev) | |||
529 | return err; | 529 | return err; |
530 | } | 530 | } |
531 | 531 | ||
532 | static void generic_drive_reset(ide_drive_t *drive) | 532 | static int generic_drive_reset(ide_drive_t *drive) |
533 | { | 533 | { |
534 | struct request *rq; | 534 | struct request *rq; |
535 | int ret = 0; | ||
535 | 536 | ||
536 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | 537 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); |
537 | rq->cmd_type = REQ_TYPE_SPECIAL; | 538 | rq->cmd_type = REQ_TYPE_SPECIAL; |
538 | rq->cmd_len = 1; | 539 | rq->cmd_len = 1; |
539 | rq->cmd[0] = REQ_DRIVE_RESET; | 540 | rq->cmd[0] = REQ_DRIVE_RESET; |
540 | rq->cmd_flags |= REQ_SOFTBARRIER; | 541 | rq->cmd_flags |= REQ_SOFTBARRIER; |
541 | blk_execute_rq(drive->queue, NULL, rq, 1); | 542 | if (blk_execute_rq(drive->queue, NULL, rq, 1)) |
543 | ret = rq->errors; | ||
542 | blk_put_request(rq); | 544 | blk_put_request(rq); |
545 | return ret; | ||
543 | } | 546 | } |
544 | 547 | ||
545 | int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, | 548 | 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 | |||
616 | if (!capable(CAP_SYS_ADMIN)) | 619 | if (!capable(CAP_SYS_ADMIN)) |
617 | return -EACCES; | 620 | return -EACCES; |
618 | 621 | ||
619 | generic_drive_reset(drive); | 622 | return generic_drive_reset(drive); |
620 | return 0; | ||
621 | 623 | ||
622 | case HDIO_GET_BUSSTATE: | 624 | case HDIO_GET_BUSSTATE: |
623 | if (!capable(CAP_SYS_ADMIN)) | 625 | if (!capable(CAP_SYS_ADMIN)) |
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index b75e9bb390a7..6e9d7655d89c 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) | |||
421 | if ((sata_stat & 0x03) != 0x03) { | 421 | if ((sata_stat & 0x03) != 0x03) { |
422 | printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", | 422 | printk(KERN_WARNING "%s: reset phy dead, status=0x%08x\n", |
423 | hwif->name, sata_stat); | 423 | hwif->name, sata_stat); |
424 | HWGROUP(drive)->polling = 0; | 424 | return -ENXIO; |
425 | return ide_started; | ||
426 | } | 425 | } |
427 | } | 426 | } |
428 | 427 | ||