aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-iops.c
diff options
context:
space:
mode:
authorElias Oltmanns <eo@nebensachen.de>2008-07-16 14:33:48 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-07-16 14:33:48 -0400
commit79e36a9f54aaf4a52eb2d9520953aa3960e99294 (patch)
tree70fae17d64a1facde8541184d7139c4bc12d03bf /drivers/ide/ide-iops.c
parent72a3d651b2fe341a8ae2ca164c395aa3007350cd (diff)
IDE: Fix HDIO_DRIVE_RESET handling
Currently, the code path executing an HDIO_DRIVE_RESET ioctl is broken in various ways. Most importantly, it is treated as an out of band request in an illegal way which may very likely lead to system lock ups. Use the drive's request queue to avoid this problem (and fix a locking issue for free along the way). 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>
Diffstat (limited to 'drivers/ide/ide-iops.c')
-rw-r--r--drivers/ide/ide-iops.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index 80ad4f234f3f..96f63eb12092 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -905,6 +905,14 @@ void ide_execute_pkt_cmd(ide_drive_t *drive)
905} 905}
906EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd); 906EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
907 907
908static inline void ide_complete_drive_reset(ide_drive_t *drive)
909{
910 struct request *rq = drive->hwif->hwgroup->rq;
911
912 if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET)
913 ide_end_request(drive, 1, 0);
914}
915
908/* needed below */ 916/* needed below */
909static ide_startstop_t do_reset1 (ide_drive_t *, int); 917static ide_startstop_t do_reset1 (ide_drive_t *, int);
910 918
@@ -940,7 +948,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
940 } 948 }
941 /* done polling */ 949 /* done polling */
942 hwgroup->polling = 0; 950 hwgroup->polling = 0;
943 hwgroup->resetting = 0; 951 ide_complete_drive_reset(drive);
944 return ide_stopped; 952 return ide_stopped;
945} 953}
946 954
@@ -961,7 +969,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
961 if (port_ops->reset_poll(drive)) { 969 if (port_ops->reset_poll(drive)) {
962 printk(KERN_ERR "%s: host reset_poll failure for %s.\n", 970 printk(KERN_ERR "%s: host reset_poll failure for %s.\n",
963 hwif->name, drive->name); 971 hwif->name, drive->name);
964 return ide_stopped; 972 goto out;
965 } 973 }
966 } 974 }
967 975
@@ -1004,7 +1012,8 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
1004 } 1012 }
1005 } 1013 }
1006 hwgroup->polling = 0; /* done polling */ 1014 hwgroup->polling = 0; /* done polling */
1007 hwgroup->resetting = 0; /* done reset attempt */ 1015out:
1016 ide_complete_drive_reset(drive);
1008 return ide_stopped; 1017 return ide_stopped;
1009} 1018}
1010 1019
@@ -1090,7 +1099,6 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
1090 1099
1091 /* For an ATAPI device, first try an ATAPI SRST. */ 1100 /* For an ATAPI device, first try an ATAPI SRST. */
1092 if (drive->media != ide_disk && !do_not_try_atapi) { 1101 if (drive->media != ide_disk && !do_not_try_atapi) {
1093 hwgroup->resetting = 1;
1094 pre_reset(drive); 1102 pre_reset(drive);
1095 SELECT_DRIVE(drive); 1103 SELECT_DRIVE(drive);
1096 udelay (20); 1104 udelay (20);
@@ -1112,10 +1120,10 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
1112 1120
1113 if (io_ports->ctl_addr == 0) { 1121 if (io_ports->ctl_addr == 0) {
1114 spin_unlock_irqrestore(&ide_lock, flags); 1122 spin_unlock_irqrestore(&ide_lock, flags);
1123 ide_complete_drive_reset(drive);
1115 return ide_stopped; 1124 return ide_stopped;
1116 } 1125 }
1117 1126
1118 hwgroup->resetting = 1;
1119 /* 1127 /*
1120 * Note that we also set nIEN while resetting the device, 1128 * Note that we also set nIEN while resetting the device,
1121 * to mask unwanted interrupts from the interface during the reset. 1129 * to mask unwanted interrupts from the interface during the reset.