diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-12-29 14:27:31 -0500 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-12-29 14:27:31 -0500 |
commit | 2a2ca6a96194c4744a2adeefbc09ce881f3c5abe (patch) | |
tree | 50b43d823d4a589fbfb8f8751278d6101cd3ecf3 | |
parent | 6ea52226ca131a99bb619bd56fbeee566ea5a966 (diff) |
ide: replace the global ide_lock spinlock by per-hwgroup spinlocks (v2)
Now that (almost) all host drivers have been fixed not to abuse ide_lock
and core code usage of ide_lock has been sanitized we may safely replace
ide_lock by per-hwgroup locks.
This patch is partially based on earlier patch from Ravikiran G Thirumalai.
While at it:
- don't use deprecated HWIF() and HWGROUP() macros
- update locking documentation in ide.h
v2:
Add missing spin_lock_init(&hwgroup->lock). (Noticed by Elias Oltmanns)
Cc: Vaibhav V. Nivargi <vaibhav.nivargi@gmail.com>
Cc: Alok N. Kataria <alokk@calsoftinc.com>
Cc: Shai Fultheim <shai@scalex86.org>
Signed-off-by: Ravikiran Thirumalai <kiran@scalex86.org>
Cc: Elias Oltmanns <eo@nebensachen.de>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r-- | drivers/ide/ide-io.c | 33 | ||||
-rw-r--r-- | drivers/ide/ide-iops.c | 48 | ||||
-rw-r--r-- | drivers/ide/ide-park.c | 16 | ||||
-rw-r--r-- | drivers/ide/ide-probe.c | 26 | ||||
-rw-r--r-- | drivers/ide/ide.c | 8 | ||||
-rw-r--r-- | drivers/ide/umc8672.c | 11 | ||||
-rw-r--r-- | drivers/scsi/ide-scsi.c | 32 | ||||
-rw-r--r-- | include/linux/ide.h | 12 |
8 files changed, 100 insertions, 86 deletions
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 02059e96e6cd..72d0d702d5da 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
@@ -907,7 +907,7 @@ repeat: | |||
907 | 907 | ||
908 | /* | 908 | /* |
909 | * Issue a new request to a drive from hwgroup | 909 | * Issue a new request to a drive from hwgroup |
910 | * Caller must have already done spin_lock_irqsave(&ide_lock, ..); | 910 | * Caller must have already done spin_lock_irqsave(&hwgroup->lock, ..); |
911 | * | 911 | * |
912 | * A hwgroup is a serialized group of IDE interfaces. Usually there is | 912 | * A hwgroup is a serialized group of IDE interfaces. Usually there is |
913 | * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) | 913 | * exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640) |
@@ -919,7 +919,7 @@ repeat: | |||
919 | * possibly along with many other devices. This is especially common in | 919 | * possibly along with many other devices. This is especially common in |
920 | * PCI-based systems with off-board IDE controller cards. | 920 | * PCI-based systems with off-board IDE controller cards. |
921 | * | 921 | * |
922 | * The IDE driver uses the single global ide_lock spinlock to protect | 922 | * The IDE driver uses a per-hwgroup spinlock to protect |
923 | * access to the request queues, and to protect the hwgroup->busy flag. | 923 | * access to the request queues, and to protect the hwgroup->busy flag. |
924 | * | 924 | * |
925 | * The first thread into the driver for a particular hwgroup sets the | 925 | * The first thread into the driver for a particular hwgroup sets the |
@@ -935,7 +935,7 @@ repeat: | |||
935 | * will start the next request from the queue. If no more work remains, | 935 | * will start the next request from the queue. If no more work remains, |
936 | * the driver will clear the hwgroup->busy flag and exit. | 936 | * the driver will clear the hwgroup->busy flag and exit. |
937 | * | 937 | * |
938 | * The ide_lock (spinlock) is used to protect all access to the | 938 | * The per-hwgroup spinlock is used to protect all access to the |
939 | * hwgroup->busy flag, but is otherwise not needed for most processing in | 939 | * hwgroup->busy flag, but is otherwise not needed for most processing in |
940 | * the driver. This makes the driver much more friendlier to shared IRQs | 940 | * the driver. This makes the driver much more friendlier to shared IRQs |
941 | * than previous designs, while remaining 100% (?) SMP safe and capable. | 941 | * than previous designs, while remaining 100% (?) SMP safe and capable. |
@@ -948,7 +948,7 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) | |||
948 | ide_startstop_t startstop; | 948 | ide_startstop_t startstop; |
949 | int loops = 0; | 949 | int loops = 0; |
950 | 950 | ||
951 | /* caller must own ide_lock */ | 951 | /* caller must own hwgroup->lock */ |
952 | BUG_ON(!irqs_disabled()); | 952 | BUG_ON(!irqs_disabled()); |
953 | 953 | ||
954 | while (!hwgroup->busy) { | 954 | while (!hwgroup->busy) { |
@@ -1070,11 +1070,11 @@ static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq) | |||
1070 | */ | 1070 | */ |
1071 | if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) | 1071 | if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) |
1072 | disable_irq_nosync(hwif->irq); | 1072 | disable_irq_nosync(hwif->irq); |
1073 | spin_unlock(&ide_lock); | 1073 | spin_unlock(&hwgroup->lock); |
1074 | local_irq_enable_in_hardirq(); | 1074 | local_irq_enable_in_hardirq(); |
1075 | /* allow other IRQs while we start this request */ | 1075 | /* allow other IRQs while we start this request */ |
1076 | startstop = start_request(drive, rq); | 1076 | startstop = start_request(drive, rq); |
1077 | spin_lock_irq(&ide_lock); | 1077 | spin_lock_irq(&hwgroup->lock); |
1078 | if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) | 1078 | if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq) |
1079 | enable_irq(hwif->irq); | 1079 | enable_irq(hwif->irq); |
1080 | if (startstop == ide_stopped) | 1080 | if (startstop == ide_stopped) |
@@ -1172,7 +1172,7 @@ void ide_timer_expiry (unsigned long data) | |||
1172 | unsigned long flags; | 1172 | unsigned long flags; |
1173 | unsigned long wait = -1; | 1173 | unsigned long wait = -1; |
1174 | 1174 | ||
1175 | spin_lock_irqsave(&ide_lock, flags); | 1175 | spin_lock_irqsave(&hwgroup->lock, flags); |
1176 | 1176 | ||
1177 | if (((handler = hwgroup->handler) == NULL) || | 1177 | if (((handler = hwgroup->handler) == NULL) || |
1178 | (hwgroup->req_gen != hwgroup->req_gen_timer)) { | 1178 | (hwgroup->req_gen != hwgroup->req_gen_timer)) { |
@@ -1205,7 +1205,7 @@ void ide_timer_expiry (unsigned long data) | |||
1205 | hwgroup->timer.expires = jiffies + wait; | 1205 | hwgroup->timer.expires = jiffies + wait; |
1206 | hwgroup->req_gen_timer = hwgroup->req_gen; | 1206 | hwgroup->req_gen_timer = hwgroup->req_gen; |
1207 | add_timer(&hwgroup->timer); | 1207 | add_timer(&hwgroup->timer); |
1208 | spin_unlock_irqrestore(&ide_lock, flags); | 1208 | spin_unlock_irqrestore(&hwgroup->lock, flags); |
1209 | return; | 1209 | return; |
1210 | } | 1210 | } |
1211 | } | 1211 | } |
@@ -1215,7 +1215,7 @@ void ide_timer_expiry (unsigned long data) | |||
1215 | * the handler() function, which means we need to | 1215 | * the handler() function, which means we need to |
1216 | * globally mask the specific IRQ: | 1216 | * globally mask the specific IRQ: |
1217 | */ | 1217 | */ |
1218 | spin_unlock(&ide_lock); | 1218 | spin_unlock(&hwgroup->lock); |
1219 | hwif = HWIF(drive); | 1219 | hwif = HWIF(drive); |
1220 | /* disable_irq_nosync ?? */ | 1220 | /* disable_irq_nosync ?? */ |
1221 | disable_irq(hwif->irq); | 1221 | disable_irq(hwif->irq); |
@@ -1239,14 +1239,14 @@ void ide_timer_expiry (unsigned long data) | |||
1239 | hwif->tp_ops->read_status(hwif)); | 1239 | hwif->tp_ops->read_status(hwif)); |
1240 | } | 1240 | } |
1241 | drive->service_time = jiffies - drive->service_start; | 1241 | drive->service_time = jiffies - drive->service_start; |
1242 | spin_lock_irq(&ide_lock); | 1242 | spin_lock_irq(&hwgroup->lock); |
1243 | enable_irq(hwif->irq); | 1243 | enable_irq(hwif->irq); |
1244 | if (startstop == ide_stopped) | 1244 | if (startstop == ide_stopped) |
1245 | hwgroup->busy = 0; | 1245 | hwgroup->busy = 0; |
1246 | } | 1246 | } |
1247 | } | 1247 | } |
1248 | ide_do_request(hwgroup, IDE_NO_IRQ); | 1248 | ide_do_request(hwgroup, IDE_NO_IRQ); |
1249 | spin_unlock_irqrestore(&ide_lock, flags); | 1249 | spin_unlock_irqrestore(&hwgroup->lock, flags); |
1250 | } | 1250 | } |
1251 | 1251 | ||
1252 | /** | 1252 | /** |
@@ -1339,14 +1339,13 @@ irqreturn_t ide_intr (int irq, void *dev_id) | |||
1339 | { | 1339 | { |
1340 | unsigned long flags; | 1340 | unsigned long flags; |
1341 | ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; | 1341 | ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; |
1342 | ide_hwif_t *hwif; | 1342 | ide_hwif_t *hwif = hwgroup->hwif; |
1343 | ide_drive_t *drive; | 1343 | ide_drive_t *drive; |
1344 | ide_handler_t *handler; | 1344 | ide_handler_t *handler; |
1345 | ide_startstop_t startstop; | 1345 | ide_startstop_t startstop; |
1346 | irqreturn_t irq_ret = IRQ_NONE; | 1346 | irqreturn_t irq_ret = IRQ_NONE; |
1347 | 1347 | ||
1348 | spin_lock_irqsave(&ide_lock, flags); | 1348 | spin_lock_irqsave(&hwgroup->lock, flags); |
1349 | hwif = hwgroup->hwif; | ||
1350 | 1349 | ||
1351 | if (!ide_ack_intr(hwif)) | 1350 | if (!ide_ack_intr(hwif)) |
1352 | goto out; | 1351 | goto out; |
@@ -1416,7 +1415,7 @@ irqreturn_t ide_intr (int irq, void *dev_id) | |||
1416 | hwgroup->handler = NULL; | 1415 | hwgroup->handler = NULL; |
1417 | hwgroup->req_gen++; | 1416 | hwgroup->req_gen++; |
1418 | del_timer(&hwgroup->timer); | 1417 | del_timer(&hwgroup->timer); |
1419 | spin_unlock(&ide_lock); | 1418 | spin_unlock(&hwgroup->lock); |
1420 | 1419 | ||
1421 | if (hwif->port_ops && hwif->port_ops->clear_irq) | 1420 | if (hwif->port_ops && hwif->port_ops->clear_irq) |
1422 | hwif->port_ops->clear_irq(drive); | 1421 | hwif->port_ops->clear_irq(drive); |
@@ -1427,7 +1426,7 @@ irqreturn_t ide_intr (int irq, void *dev_id) | |||
1427 | /* service this interrupt, may set handler for next interrupt */ | 1426 | /* service this interrupt, may set handler for next interrupt */ |
1428 | startstop = handler(drive); | 1427 | startstop = handler(drive); |
1429 | 1428 | ||
1430 | spin_lock_irq(&ide_lock); | 1429 | spin_lock_irq(&hwgroup->lock); |
1431 | /* | 1430 | /* |
1432 | * Note that handler() may have set things up for another | 1431 | * Note that handler() may have set things up for another |
1433 | * interrupt to occur soon, but it cannot happen until | 1432 | * interrupt to occur soon, but it cannot happen until |
@@ -1448,7 +1447,7 @@ irqreturn_t ide_intr (int irq, void *dev_id) | |||
1448 | out_handled: | 1447 | out_handled: |
1449 | irq_ret = IRQ_HANDLED; | 1448 | irq_ret = IRQ_HANDLED; |
1450 | out: | 1449 | out: |
1451 | spin_unlock_irqrestore(&ide_lock, flags); | 1450 | spin_unlock_irqrestore(&hwgroup->lock, flags); |
1452 | return irq_ret; | 1451 | return irq_ret; |
1453 | } | 1452 | } |
1454 | 1453 | ||
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index c41c3b9b6f02..ad8bd6539283 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c | |||
@@ -835,10 +835,12 @@ static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, | |||
835 | void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, | 835 | void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, |
836 | unsigned int timeout, ide_expiry_t *expiry) | 836 | unsigned int timeout, ide_expiry_t *expiry) |
837 | { | 837 | { |
838 | ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; | ||
838 | unsigned long flags; | 839 | unsigned long flags; |
839 | spin_lock_irqsave(&ide_lock, flags); | 840 | |
841 | spin_lock_irqsave(&hwgroup->lock, flags); | ||
840 | __ide_set_handler(drive, handler, timeout, expiry); | 842 | __ide_set_handler(drive, handler, timeout, expiry); |
841 | spin_unlock_irqrestore(&ide_lock, flags); | 843 | spin_unlock_irqrestore(&hwgroup->lock, flags); |
842 | } | 844 | } |
843 | 845 | ||
844 | EXPORT_SYMBOL(ide_set_handler); | 846 | EXPORT_SYMBOL(ide_set_handler); |
@@ -860,10 +862,11 @@ EXPORT_SYMBOL(ide_set_handler); | |||
860 | void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler, | 862 | void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler, |
861 | unsigned timeout, ide_expiry_t *expiry) | 863 | unsigned timeout, ide_expiry_t *expiry) |
862 | { | 864 | { |
865 | ide_hwif_t *hwif = drive->hwif; | ||
866 | ide_hwgroup_t *hwgroup = hwif->hwgroup; | ||
863 | unsigned long flags; | 867 | unsigned long flags; |
864 | ide_hwif_t *hwif = HWIF(drive); | ||
865 | 868 | ||
866 | spin_lock_irqsave(&ide_lock, flags); | 869 | spin_lock_irqsave(&hwgroup->lock, flags); |
867 | __ide_set_handler(drive, handler, timeout, expiry); | 870 | __ide_set_handler(drive, handler, timeout, expiry); |
868 | hwif->tp_ops->exec_command(hwif, cmd); | 871 | hwif->tp_ops->exec_command(hwif, cmd); |
869 | /* | 872 | /* |
@@ -873,19 +876,20 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler, | |||
873 | * FIXME: we could skip this delay with care on non shared devices | 876 | * FIXME: we could skip this delay with care on non shared devices |
874 | */ | 877 | */ |
875 | ndelay(400); | 878 | ndelay(400); |
876 | spin_unlock_irqrestore(&ide_lock, flags); | 879 | spin_unlock_irqrestore(&hwgroup->lock, flags); |
877 | } | 880 | } |
878 | EXPORT_SYMBOL(ide_execute_command); | 881 | EXPORT_SYMBOL(ide_execute_command); |
879 | 882 | ||
880 | void ide_execute_pkt_cmd(ide_drive_t *drive) | 883 | void ide_execute_pkt_cmd(ide_drive_t *drive) |
881 | { | 884 | { |
882 | ide_hwif_t *hwif = drive->hwif; | 885 | ide_hwif_t *hwif = drive->hwif; |
886 | ide_hwgroup_t *hwgroup = hwif->hwgroup; | ||
883 | unsigned long flags; | 887 | unsigned long flags; |
884 | 888 | ||
885 | spin_lock_irqsave(&ide_lock, flags); | 889 | spin_lock_irqsave(&hwgroup->lock, flags); |
886 | hwif->tp_ops->exec_command(hwif, ATA_CMD_PACKET); | 890 | hwif->tp_ops->exec_command(hwif, ATA_CMD_PACKET); |
887 | ndelay(400); | 891 | ndelay(400); |
888 | spin_unlock_irqrestore(&ide_lock, flags); | 892 | spin_unlock_irqrestore(&hwgroup->lock, flags); |
889 | } | 893 | } |
890 | EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd); | 894 | EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd); |
891 | 895 | ||
@@ -1076,22 +1080,16 @@ static void pre_reset(ide_drive_t *drive) | |||
1076 | */ | 1080 | */ |
1077 | static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) | 1081 | static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) |
1078 | { | 1082 | { |
1079 | unsigned int unit; | 1083 | ide_hwif_t *hwif = drive->hwif; |
1080 | unsigned long flags, timeout; | 1084 | ide_hwgroup_t *hwgroup = hwif->hwgroup; |
1081 | ide_hwif_t *hwif; | 1085 | struct ide_io_ports *io_ports = &hwif->io_ports; |
1082 | ide_hwgroup_t *hwgroup; | 1086 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; |
1083 | struct ide_io_ports *io_ports; | ||
1084 | const struct ide_tp_ops *tp_ops; | ||
1085 | const struct ide_port_ops *port_ops; | 1087 | const struct ide_port_ops *port_ops; |
1088 | unsigned long flags, timeout; | ||
1089 | unsigned int unit; | ||
1086 | DEFINE_WAIT(wait); | 1090 | DEFINE_WAIT(wait); |
1087 | 1091 | ||
1088 | spin_lock_irqsave(&ide_lock, flags); | 1092 | spin_lock_irqsave(&hwgroup->lock, flags); |
1089 | hwif = HWIF(drive); | ||
1090 | hwgroup = HWGROUP(drive); | ||
1091 | |||
1092 | io_ports = &hwif->io_ports; | ||
1093 | |||
1094 | tp_ops = hwif->tp_ops; | ||
1095 | 1093 | ||
1096 | /* We must not reset with running handlers */ | 1094 | /* We must not reset with running handlers */ |
1097 | BUG_ON(hwgroup->handler != NULL); | 1095 | BUG_ON(hwgroup->handler != NULL); |
@@ -1106,7 +1104,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) | |||
1106 | hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; | 1104 | hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE; |
1107 | hwgroup->polling = 1; | 1105 | hwgroup->polling = 1; |
1108 | __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); | 1106 | __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); |
1109 | spin_unlock_irqrestore(&ide_lock, flags); | 1107 | spin_unlock_irqrestore(&hwgroup->lock, flags); |
1110 | return ide_started; | 1108 | return ide_started; |
1111 | } | 1109 | } |
1112 | 1110 | ||
@@ -1129,9 +1127,9 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) | |||
1129 | if (time_before_eq(timeout, now)) | 1127 | if (time_before_eq(timeout, now)) |
1130 | break; | 1128 | break; |
1131 | 1129 | ||
1132 | spin_unlock_irqrestore(&ide_lock, flags); | 1130 | spin_unlock_irqrestore(&hwgroup->lock, flags); |
1133 | timeout = schedule_timeout_uninterruptible(timeout - now); | 1131 | timeout = schedule_timeout_uninterruptible(timeout - now); |
1134 | spin_lock_irqsave(&ide_lock, flags); | 1132 | spin_lock_irqsave(&hwgroup->lock, flags); |
1135 | } while (timeout); | 1133 | } while (timeout); |
1136 | finish_wait(&ide_park_wq, &wait); | 1134 | finish_wait(&ide_park_wq, &wait); |
1137 | 1135 | ||
@@ -1143,7 +1141,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) | |||
1143 | pre_reset(&hwif->drives[unit]); | 1141 | pre_reset(&hwif->drives[unit]); |
1144 | 1142 | ||
1145 | if (io_ports->ctl_addr == 0) { | 1143 | if (io_ports->ctl_addr == 0) { |
1146 | spin_unlock_irqrestore(&ide_lock, flags); | 1144 | spin_unlock_irqrestore(&hwgroup->lock, flags); |
1147 | ide_complete_drive_reset(drive, -ENXIO); | 1145 | ide_complete_drive_reset(drive, -ENXIO); |
1148 | return ide_stopped; | 1146 | return ide_stopped; |
1149 | } | 1147 | } |
@@ -1179,7 +1177,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) | |||
1179 | if (port_ops && port_ops->resetproc) | 1177 | if (port_ops && port_ops->resetproc) |
1180 | port_ops->resetproc(drive); | 1178 | port_ops->resetproc(drive); |
1181 | 1179 | ||
1182 | spin_unlock_irqrestore(&ide_lock, flags); | 1180 | spin_unlock_irqrestore(&hwgroup->lock, flags); |
1183 | return ide_started; | 1181 | return ide_started; |
1184 | } | 1182 | } |
1185 | 1183 | ||
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c index 03b00e57e93f..63d01c55f865 100644 --- a/drivers/ide/ide-park.c +++ b/drivers/ide/ide-park.c | |||
@@ -7,17 +7,16 @@ DECLARE_WAIT_QUEUE_HEAD(ide_park_wq); | |||
7 | 7 | ||
8 | static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) | 8 | static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) |
9 | { | 9 | { |
10 | ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; | ||
10 | struct request_queue *q = drive->queue; | 11 | struct request_queue *q = drive->queue; |
11 | struct request *rq; | 12 | struct request *rq; |
12 | int rc; | 13 | int rc; |
13 | 14 | ||
14 | timeout += jiffies; | 15 | timeout += jiffies; |
15 | spin_lock_irq(&ide_lock); | 16 | spin_lock_irq(&hwgroup->lock); |
16 | if (drive->dev_flags & IDE_DFLAG_PARKED) { | 17 | if (drive->dev_flags & IDE_DFLAG_PARKED) { |
17 | ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; | 18 | int reset_timer = time_before(timeout, drive->sleep); |
18 | int reset_timer; | ||
19 | 19 | ||
20 | reset_timer = time_before(timeout, drive->sleep); | ||
21 | drive->sleep = timeout; | 20 | drive->sleep = timeout; |
22 | wake_up_all(&ide_park_wq); | 21 | wake_up_all(&ide_park_wq); |
23 | if (reset_timer && hwgroup->sleeping && | 22 | if (reset_timer && hwgroup->sleeping && |
@@ -26,10 +25,10 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) | |||
26 | hwgroup->busy = 0; | 25 | hwgroup->busy = 0; |
27 | blk_start_queueing(q); | 26 | blk_start_queueing(q); |
28 | } | 27 | } |
29 | spin_unlock_irq(&ide_lock); | 28 | spin_unlock_irq(&hwgroup->lock); |
30 | return; | 29 | return; |
31 | } | 30 | } |
32 | spin_unlock_irq(&ide_lock); | 31 | spin_unlock_irq(&hwgroup->lock); |
33 | 32 | ||
34 | rq = blk_get_request(q, READ, __GFP_WAIT); | 33 | rq = blk_get_request(q, READ, __GFP_WAIT); |
35 | rq->cmd[0] = REQ_PARK_HEADS; | 34 | rq->cmd[0] = REQ_PARK_HEADS; |
@@ -62,20 +61,21 @@ ssize_t ide_park_show(struct device *dev, struct device_attribute *attr, | |||
62 | char *buf) | 61 | char *buf) |
63 | { | 62 | { |
64 | ide_drive_t *drive = to_ide_device(dev); | 63 | ide_drive_t *drive = to_ide_device(dev); |
64 | ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; | ||
65 | unsigned long now; | 65 | unsigned long now; |
66 | unsigned int msecs; | 66 | unsigned int msecs; |
67 | 67 | ||
68 | if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD) | 68 | if (drive->dev_flags & IDE_DFLAG_NO_UNLOAD) |
69 | return -EOPNOTSUPP; | 69 | return -EOPNOTSUPP; |
70 | 70 | ||
71 | spin_lock_irq(&ide_lock); | 71 | spin_lock_irq(&hwgroup->lock); |
72 | now = jiffies; | 72 | now = jiffies; |
73 | if (drive->dev_flags & IDE_DFLAG_PARKED && | 73 | if (drive->dev_flags & IDE_DFLAG_PARKED && |
74 | time_after(drive->sleep, now)) | 74 | time_after(drive->sleep, now)) |
75 | msecs = jiffies_to_msecs(drive->sleep - now); | 75 | msecs = jiffies_to_msecs(drive->sleep - now); |
76 | else | 76 | else |
77 | msecs = 0; | 77 | msecs = 0; |
78 | spin_unlock_irq(&ide_lock); | 78 | spin_unlock_irq(&hwgroup->lock); |
79 | 79 | ||
80 | return snprintf(buf, 20, "%u\n", msecs); | 80 | return snprintf(buf, 20, "%u\n", msecs); |
81 | } | 81 | } |
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index c55bdbd22314..504bc9480e93 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -906,7 +906,8 @@ static int ide_init_queue(ide_drive_t *drive) | |||
906 | * do not. | 906 | * do not. |
907 | */ | 907 | */ |
908 | 908 | ||
909 | q = blk_init_queue_node(do_ide_request, &ide_lock, hwif_to_node(hwif)); | 909 | q = blk_init_queue_node(do_ide_request, &hwif->hwgroup->lock, |
910 | hwif_to_node(hwif)); | ||
910 | if (!q) | 911 | if (!q) |
911 | return 1; | 912 | return 1; |
912 | 913 | ||
@@ -947,7 +948,7 @@ static void ide_add_drive_to_hwgroup(ide_drive_t *drive) | |||
947 | { | 948 | { |
948 | ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; | 949 | ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; |
949 | 950 | ||
950 | spin_lock_irq(&ide_lock); | 951 | spin_lock_irq(&hwgroup->lock); |
951 | if (!hwgroup->drive) { | 952 | if (!hwgroup->drive) { |
952 | /* first drive for hwgroup. */ | 953 | /* first drive for hwgroup. */ |
953 | drive->next = drive; | 954 | drive->next = drive; |
@@ -957,7 +958,7 @@ static void ide_add_drive_to_hwgroup(ide_drive_t *drive) | |||
957 | drive->next = hwgroup->drive->next; | 958 | drive->next = hwgroup->drive->next; |
958 | hwgroup->drive->next = drive; | 959 | hwgroup->drive->next = drive; |
959 | } | 960 | } |
960 | spin_unlock_irq(&ide_lock); | 961 | spin_unlock_irq(&hwgroup->lock); |
961 | } | 962 | } |
962 | 963 | ||
963 | /* | 964 | /* |
@@ -1002,7 +1003,7 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif) | |||
1002 | 1003 | ||
1003 | ide_ports[hwif->index] = NULL; | 1004 | ide_ports[hwif->index] = NULL; |
1004 | 1005 | ||
1005 | spin_lock_irq(&ide_lock); | 1006 | spin_lock_irq(&hwgroup->lock); |
1006 | /* | 1007 | /* |
1007 | * Remove us from the hwgroup, and free | 1008 | * Remove us from the hwgroup, and free |
1008 | * the hwgroup if we were the only member | 1009 | * the hwgroup if we were the only member |
@@ -1030,7 +1031,7 @@ void ide_remove_port_from_hwgroup(ide_hwif_t *hwif) | |||
1030 | } | 1031 | } |
1031 | BUG_ON(hwgroup->hwif == hwif); | 1032 | BUG_ON(hwgroup->hwif == hwif); |
1032 | } | 1033 | } |
1033 | spin_unlock_irq(&ide_lock); | 1034 | spin_unlock_irq(&hwgroup->lock); |
1034 | } | 1035 | } |
1035 | 1036 | ||
1036 | /* | 1037 | /* |
@@ -1092,17 +1093,19 @@ static int init_irq (ide_hwif_t *hwif) | |||
1092 | * linked list, the first entry is the hwif that owns | 1093 | * linked list, the first entry is the hwif that owns |
1093 | * hwgroup->handler - do not change that. | 1094 | * hwgroup->handler - do not change that. |
1094 | */ | 1095 | */ |
1095 | spin_lock_irq(&ide_lock); | 1096 | spin_lock_irq(&hwgroup->lock); |
1096 | hwif->next = hwgroup->hwif->next; | 1097 | hwif->next = hwgroup->hwif->next; |
1097 | hwgroup->hwif->next = hwif; | 1098 | hwgroup->hwif->next = hwif; |
1098 | BUG_ON(hwif->next == hwif); | 1099 | BUG_ON(hwif->next == hwif); |
1099 | spin_unlock_irq(&ide_lock); | 1100 | spin_unlock_irq(&hwgroup->lock); |
1100 | } else { | 1101 | } else { |
1101 | hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO, | 1102 | hwgroup = kmalloc_node(sizeof(*hwgroup), GFP_KERNEL|__GFP_ZERO, |
1102 | hwif_to_node(hwif)); | 1103 | hwif_to_node(hwif)); |
1103 | if (hwgroup == NULL) | 1104 | if (hwgroup == NULL) |
1104 | goto out_up; | 1105 | goto out_up; |
1105 | 1106 | ||
1107 | spin_lock_init(&hwgroup->lock); | ||
1108 | |||
1106 | hwif->hwgroup = hwgroup; | 1109 | hwif->hwgroup = hwgroup; |
1107 | hwgroup->hwif = hwif->next = hwif; | 1110 | hwgroup->hwif = hwif->next = hwif; |
1108 | 1111 | ||
@@ -1263,20 +1266,21 @@ static void ide_remove_drive_from_hwgroup(ide_drive_t *drive) | |||
1263 | static void drive_release_dev (struct device *dev) | 1266 | static void drive_release_dev (struct device *dev) |
1264 | { | 1267 | { |
1265 | ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); | 1268 | ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); |
1269 | ide_hwgroup_t *hwgroup = drive->hwif->hwgroup; | ||
1266 | 1270 | ||
1267 | ide_proc_unregister_device(drive); | 1271 | ide_proc_unregister_device(drive); |
1268 | 1272 | ||
1269 | spin_lock_irq(&ide_lock); | 1273 | spin_lock_irq(&hwgroup->lock); |
1270 | ide_remove_drive_from_hwgroup(drive); | 1274 | ide_remove_drive_from_hwgroup(drive); |
1271 | kfree(drive->id); | 1275 | kfree(drive->id); |
1272 | drive->id = NULL; | 1276 | drive->id = NULL; |
1273 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; | 1277 | drive->dev_flags &= ~IDE_DFLAG_PRESENT; |
1274 | /* Messed up locking ... */ | 1278 | /* Messed up locking ... */ |
1275 | spin_unlock_irq(&ide_lock); | 1279 | spin_unlock_irq(&hwgroup->lock); |
1276 | blk_cleanup_queue(drive->queue); | 1280 | blk_cleanup_queue(drive->queue); |
1277 | spin_lock_irq(&ide_lock); | 1281 | spin_lock_irq(&hwgroup->lock); |
1278 | drive->queue = NULL; | 1282 | drive->queue = NULL; |
1279 | spin_unlock_irq(&ide_lock); | 1283 | spin_unlock_irq(&hwgroup->lock); |
1280 | 1284 | ||
1281 | complete(&drive->gendev_rel_comp); | 1285 | complete(&drive->gendev_rel_comp); |
1282 | } | 1286 | } |
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index bca6877ee6a5..41d042053548 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -74,9 +74,6 @@ static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, | |||
74 | 74 | ||
75 | DEFINE_MUTEX(ide_cfg_mtx); | 75 | DEFINE_MUTEX(ide_cfg_mtx); |
76 | 76 | ||
77 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock); | ||
78 | EXPORT_SYMBOL(ide_lock); | ||
79 | |||
80 | static void ide_port_init_devices_data(ide_hwif_t *); | 77 | static void ide_port_init_devices_data(ide_hwif_t *); |
81 | 78 | ||
82 | /* | 79 | /* |
@@ -333,6 +330,7 @@ static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio) | |||
333 | static int set_pio_mode(ide_drive_t *drive, int arg) | 330 | static int set_pio_mode(ide_drive_t *drive, int arg) |
334 | { | 331 | { |
335 | ide_hwif_t *hwif = drive->hwif; | 332 | ide_hwif_t *hwif = drive->hwif; |
333 | ide_hwgroup_t *hwgroup = hwif->hwgroup; | ||
336 | const struct ide_port_ops *port_ops = hwif->port_ops; | 334 | const struct ide_port_ops *port_ops = hwif->port_ops; |
337 | 335 | ||
338 | if (arg < 0 || arg > 255) | 336 | if (arg < 0 || arg > 255) |
@@ -347,9 +345,9 @@ static int set_pio_mode(ide_drive_t *drive, int arg) | |||
347 | unsigned long flags; | 345 | unsigned long flags; |
348 | 346 | ||
349 | /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */ | 347 | /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */ |
350 | spin_lock_irqsave(&ide_lock, flags); | 348 | spin_lock_irqsave(&hwgroup->lock, flags); |
351 | port_ops->set_pio_mode(drive, arg); | 349 | port_ops->set_pio_mode(drive, arg); |
352 | spin_unlock_irqrestore(&ide_lock, flags); | 350 | spin_unlock_irqrestore(&hwgroup->lock, flags); |
353 | } else | 351 | } else |
354 | port_ops->set_pio_mode(drive, arg); | 352 | port_ops->set_pio_mode(drive, arg); |
355 | } else { | 353 | } else { |
diff --git a/drivers/ide/umc8672.c b/drivers/ide/umc8672.c index 1da076e0c917..e29978cf6197 100644 --- a/drivers/ide/umc8672.c +++ b/drivers/ide/umc8672.c | |||
@@ -107,18 +107,21 @@ static void umc_set_speeds(u8 speeds[]) | |||
107 | static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio) | 107 | static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio) |
108 | { | 108 | { |
109 | ide_hwif_t *hwif = drive->hwif; | 109 | ide_hwif_t *hwif = drive->hwif; |
110 | unsigned long flags; | 110 | ide_hwgroup_t *mate_hwgroup = hwif->mate ? hwif->mate->hwgroup : NULL; |
111 | unsigned long uninitialized_var(flags); | ||
111 | 112 | ||
112 | printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", | 113 | printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", |
113 | drive->name, pio, pio_to_umc[pio]); | 114 | drive->name, pio, pio_to_umc[pio]); |
114 | spin_lock_irqsave(&ide_lock, flags); | 115 | if (mate_hwgroup) |
115 | if (hwif->mate && hwif->mate->hwgroup->handler) { | 116 | spin_lock_irqsave(&mate_hwgroup->lock, flags); |
117 | if (mate_hwgroup && mate_hwgroup->handler) { | ||
116 | printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n"); | 118 | printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n"); |
117 | } else { | 119 | } else { |
118 | current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; | 120 | current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio]; |
119 | umc_set_speeds(current_speeds); | 121 | umc_set_speeds(current_speeds); |
120 | } | 122 | } |
121 | spin_unlock_irqrestore(&ide_lock, flags); | 123 | if (mate_hwgroup) |
124 | spin_unlock_irqrestore(&mate_hwgroup->lock, flags); | ||
122 | } | 125 | } |
123 | 126 | ||
124 | static const struct ide_port_ops umc8672_port_ops = { | 127 | static const struct ide_port_ops umc8672_port_ops = { |
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 2370fd82ebfe..c24140aff8e7 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c | |||
@@ -578,6 +578,8 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd) | |||
578 | { | 578 | { |
579 | idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host); | 579 | idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host); |
580 | ide_drive_t *drive = scsi->drive; | 580 | ide_drive_t *drive = scsi->drive; |
581 | ide_hwif_t *hwif; | ||
582 | ide_hwgroup_t *hwgroup; | ||
581 | int busy; | 583 | int busy; |
582 | int ret = FAILED; | 584 | int ret = FAILED; |
583 | 585 | ||
@@ -594,13 +596,16 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd) | |||
594 | goto no_drive; | 596 | goto no_drive; |
595 | } | 597 | } |
596 | 598 | ||
597 | /* First give it some more time, how much is "right" is hard to say :-( */ | 599 | hwif = drive->hwif; |
600 | hwgroup = hwif->hwgroup; | ||
598 | 601 | ||
599 | busy = ide_wait_not_busy(HWIF(drive), 100); /* FIXME - uses mdelay which causes latency? */ | 602 | /* First give it some more time, how much is "right" is hard to say :-( |
603 | FIXME - uses mdelay which causes latency? */ | ||
604 | busy = ide_wait_not_busy(hwif, 100); | ||
600 | if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) | 605 | if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) |
601 | printk (KERN_WARNING "ide-scsi: drive did%s become ready\n", busy?" not":""); | 606 | printk (KERN_WARNING "ide-scsi: drive did%s become ready\n", busy?" not":""); |
602 | 607 | ||
603 | spin_lock_irq(&ide_lock); | 608 | spin_lock_irq(&hwgroup->lock); |
604 | 609 | ||
605 | /* If there is no pc running we're done (our interrupt took care of it) */ | 610 | /* If there is no pc running we're done (our interrupt took care of it) */ |
606 | pc = drive->pc; | 611 | pc = drive->pc; |
@@ -629,7 +634,7 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd) | |||
629 | } | 634 | } |
630 | 635 | ||
631 | ide_unlock: | 636 | ide_unlock: |
632 | spin_unlock_irq(&ide_lock); | 637 | spin_unlock_irq(&hwgroup->lock); |
633 | no_drive: | 638 | no_drive: |
634 | if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) | 639 | if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) |
635 | printk (KERN_WARNING "ide-scsi: abort returns %s\n", ret == SUCCESS?"success":"failed"); | 640 | printk (KERN_WARNING "ide-scsi: abort returns %s\n", ret == SUCCESS?"success":"failed"); |
@@ -642,6 +647,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd) | |||
642 | struct request *req; | 647 | struct request *req; |
643 | idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host); | 648 | idescsi_scsi_t *scsi = scsihost_to_idescsi(cmd->device->host); |
644 | ide_drive_t *drive = scsi->drive; | 649 | ide_drive_t *drive = scsi->drive; |
650 | ide_hwgroup_t *hwgroup; | ||
645 | int ready = 0; | 651 | int ready = 0; |
646 | int ret = SUCCESS; | 652 | int ret = SUCCESS; |
647 | 653 | ||
@@ -658,14 +664,18 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd) | |||
658 | return FAILED; | 664 | return FAILED; |
659 | } | 665 | } |
660 | 666 | ||
667 | hwgroup = drive->hwif->hwgroup; | ||
668 | |||
661 | spin_lock_irq(cmd->device->host->host_lock); | 669 | spin_lock_irq(cmd->device->host->host_lock); |
662 | spin_lock(&ide_lock); | 670 | spin_lock(&hwgroup->lock); |
663 | 671 | ||
664 | pc = drive->pc; | 672 | pc = drive->pc; |
673 | if (pc) | ||
674 | req = pc->rq; | ||
665 | 675 | ||
666 | if (pc == NULL || (req = pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) { | 676 | if (pc == NULL || req != hwgroup->rq || hwgroup->handler == NULL) { |
667 | printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n"); | 677 | printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n"); |
668 | spin_unlock(&ide_lock); | 678 | spin_unlock(&hwgroup->lock); |
669 | spin_unlock_irq(cmd->device->host->host_lock); | 679 | spin_unlock_irq(cmd->device->host->host_lock); |
670 | return FAILED; | 680 | return FAILED; |
671 | } | 681 | } |
@@ -685,10 +695,10 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd) | |||
685 | BUG(); | 695 | BUG(); |
686 | } | 696 | } |
687 | 697 | ||
688 | HWGROUP(drive)->rq = NULL; | 698 | hwgroup->rq = NULL; |
689 | HWGROUP(drive)->handler = NULL; | 699 | hwgroup->handler = NULL; |
690 | HWGROUP(drive)->busy = 1; /* will set this to zero when ide reset finished */ | 700 | hwgroup->busy = 1; /* will set this to zero when ide reset finished */ |
691 | spin_unlock(&ide_lock); | 701 | spin_unlock(&hwgroup->lock); |
692 | 702 | ||
693 | ide_do_reset(drive); | 703 | ide_do_reset(drive); |
694 | 704 | ||
diff --git a/include/linux/ide.h b/include/linux/ide.h index 010fb26a1579..c871d325cedb 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
@@ -909,6 +909,8 @@ typedef struct hwgroup_s { | |||
909 | 909 | ||
910 | int req_gen; | 910 | int req_gen; |
911 | int req_gen_timer; | 911 | int req_gen_timer; |
912 | |||
913 | spinlock_t lock; | ||
912 | } ide_hwgroup_t; | 914 | } ide_hwgroup_t; |
913 | 915 | ||
914 | typedef struct ide_driver_s ide_driver_t; | 916 | typedef struct ide_driver_s ide_driver_t; |
@@ -1610,13 +1612,13 @@ extern struct mutex ide_cfg_mtx; | |||
1610 | /* | 1612 | /* |
1611 | * Structure locking: | 1613 | * Structure locking: |
1612 | * | 1614 | * |
1613 | * ide_cfg_mtx and ide_lock together protect changes to | 1615 | * ide_cfg_mtx and hwgroup->lock together protect changes to |
1614 | * ide_hwif_t->{next,hwgroup} | 1616 | * ide_hwif_t->next |
1615 | * ide_drive_t->next | 1617 | * ide_drive_t->next |
1616 | * | 1618 | * |
1617 | * ide_hwgroup_t->busy: ide_lock | 1619 | * ide_hwgroup_t->busy: hwgroup->lock |
1618 | * ide_hwgroup_t->hwif: ide_lock | 1620 | * ide_hwgroup_t->hwif: hwgroup->lock |
1619 | * ide_hwif_t->mate: constant, no locking | 1621 | * ide_hwif_t->{hwgroup,mate}: constant, no locking |
1620 | * ide_drive_t->hwif: constant, no locking | 1622 | * ide_drive_t->hwif: constant, no locking |
1621 | */ | 1623 | */ |
1622 | 1624 | ||