aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-12-29 14:27:31 -0500
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2008-12-29 14:27:31 -0500
commit2a2ca6a96194c4744a2adeefbc09ce881f3c5abe (patch)
tree50b43d823d4a589fbfb8f8751278d6101cd3ecf3
parent6ea52226ca131a99bb619bd56fbeee566ea5a966 (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.c33
-rw-r--r--drivers/ide/ide-iops.c48
-rw-r--r--drivers/ide/ide-park.c16
-rw-r--r--drivers/ide/ide-probe.c26
-rw-r--r--drivers/ide/ide.c8
-rw-r--r--drivers/ide/umc8672.c11
-rw-r--r--drivers/scsi/ide-scsi.c32
-rw-r--r--include/linux/ide.h12
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)
1448out_handled: 1447out_handled:
1449 irq_ret = IRQ_HANDLED; 1448 irq_ret = IRQ_HANDLED;
1450out: 1449out:
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,
835void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, 835void 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
844EXPORT_SYMBOL(ide_set_handler); 846EXPORT_SYMBOL(ide_set_handler);
@@ -860,10 +862,11 @@ EXPORT_SYMBOL(ide_set_handler);
860void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler, 862void 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}
878EXPORT_SYMBOL(ide_execute_command); 881EXPORT_SYMBOL(ide_execute_command);
879 882
880void ide_execute_pkt_cmd(ide_drive_t *drive) 883void 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}
890EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd); 894EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
891 895
@@ -1076,22 +1080,16 @@ static void pre_reset(ide_drive_t *drive)
1076 */ 1080 */
1077static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) 1081static 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
8static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) 8static 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)
1263static void drive_release_dev (struct device *dev) 1266static 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
75DEFINE_MUTEX(ide_cfg_mtx); 75DEFINE_MUTEX(ide_cfg_mtx);
76 76
77__cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
78EXPORT_SYMBOL(ide_lock);
79
80static void ide_port_init_devices_data(ide_hwif_t *); 77static 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)
333static int set_pio_mode(ide_drive_t *drive, int arg) 330static 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[])
107static void umc_set_pio_mode(ide_drive_t *drive, const u8 pio) 107static 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
124static const struct ide_port_ops umc8672_port_ops = { 127static 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
631ide_unlock: 636ide_unlock:
632 spin_unlock_irq(&ide_lock); 637 spin_unlock_irq(&hwgroup->lock);
633no_drive: 638no_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
914typedef struct ide_driver_s ide_driver_t; 916typedef 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