aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ide/ide-io.c58
-rw-r--r--drivers/ide/ide-probe.c21
-rw-r--r--drivers/ide/ide.c17
-rw-r--r--include/linux/ide.h4
4 files changed, 34 insertions, 66 deletions
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 43bf43d802c3..1fc739f44154 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -723,7 +723,7 @@ void do_ide_request(struct request_queue *q)
723 spin_unlock_irq(q->queue_lock); 723 spin_unlock_irq(q->queue_lock);
724 spin_lock_irq(&hwgroup->lock); 724 spin_lock_irq(&hwgroup->lock);
725 725
726 if (!ide_lock_hwgroup(hwgroup)) { 726 if (!ide_lock_hwgroup(hwgroup, hwif)) {
727 ide_hwif_t *prev_port; 727 ide_hwif_t *prev_port;
728repeat: 728repeat:
729 prev_port = hwif->host->cur_port; 729 prev_port = hwif->host->cur_port;
@@ -1002,44 +1002,30 @@ void ide_timer_expiry (unsigned long data)
1002 * before completing the issuance of any new drive command, so we will not 1002 * before completing the issuance of any new drive command, so we will not
1003 * be accidentally invoked as a result of any valid command completion 1003 * be accidentally invoked as a result of any valid command completion
1004 * interrupt. 1004 * interrupt.
1005 *
1006 * Note that we must walk the entire hwgroup here. We know which hwif
1007 * is doing the current command, but we don't know which hwif burped
1008 * mysteriously.
1009 */ 1005 */
1010 1006
1011static void unexpected_intr(int irq, ide_hwif_t *hwif) 1007static void unexpected_intr(int irq, ide_hwif_t *hwif)
1012{ 1008{
1013 ide_hwgroup_t *hwgroup = hwif->hwgroup; 1009 u8 stat = hwif->tp_ops->read_status(hwif);
1014 u8 stat; 1010
1015 1011 if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
1016 /* 1012 /* Try to not flood the console with msgs */
1017 * handle the unexpected interrupt 1013 static unsigned long last_msgtime, count;
1018 */ 1014 ++count;
1019 do { 1015
1020 if (hwif->irq == irq) { 1016 if (time_after(jiffies, last_msgtime + HZ)) {
1021 stat = hwif->tp_ops->read_status(hwif); 1017 last_msgtime = jiffies;
1022 1018 printk(KERN_ERR "%s: unexpected interrupt, "
1023 if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) { 1019 "status=0x%02x, count=%ld\n",
1024 /* Try to not flood the console with msgs */ 1020 hwif->name, stat, count);
1025 static unsigned long last_msgtime, count;
1026 ++count;
1027 if (time_after(jiffies, last_msgtime + HZ)) {
1028 last_msgtime = jiffies;
1029 printk(KERN_ERR "%s%s: unexpected interrupt, "
1030 "status=0x%02x, count=%ld\n",
1031 hwif->name,
1032 (hwif->next==hwgroup->hwif) ? "" : "(?)", stat, count);
1033 }
1034 }
1035 } 1021 }
1036 } while ((hwif = hwif->next) != hwgroup->hwif); 1022 }
1037} 1023}
1038 1024
1039/** 1025/**
1040 * ide_intr - default IDE interrupt handler 1026 * ide_intr - default IDE interrupt handler
1041 * @irq: interrupt number 1027 * @irq: interrupt number
1042 * @dev_id: hwif group 1028 * @dev_id: hwif
1043 * @regs: unused weirdness from the kernel irq layer 1029 * @regs: unused weirdness from the kernel irq layer
1044 * 1030 *
1045 * This is the default IRQ handler for the IDE layer. You should 1031 * This is the default IRQ handler for the IDE layer. You should
@@ -1063,17 +1049,19 @@ static void unexpected_intr(int irq, ide_hwif_t *hwif)
1063 1049
1064irqreturn_t ide_intr (int irq, void *dev_id) 1050irqreturn_t ide_intr (int irq, void *dev_id)
1065{ 1051{
1066 unsigned long flags; 1052 ide_hwif_t *hwif = (ide_hwif_t *)dev_id;
1067 ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; 1053 ide_hwgroup_t *hwgroup = hwif->hwgroup;
1068 ide_hwif_t *hwif = hwgroup->hwif;
1069 ide_drive_t *uninitialized_var(drive); 1054 ide_drive_t *uninitialized_var(drive);
1070 ide_handler_t *handler; 1055 ide_handler_t *handler;
1056 unsigned long flags;
1071 ide_startstop_t startstop; 1057 ide_startstop_t startstop;
1072 irqreturn_t irq_ret = IRQ_NONE; 1058 irqreturn_t irq_ret = IRQ_NONE;
1073 int plug_device = 0; 1059 int plug_device = 0;
1074 1060
1075 if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) 1061 if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) {
1076 hwif = hwif->host->cur_port; 1062 if (hwif != hwif->host->cur_port)
1063 goto out_early;
1064 }
1077 1065
1078 spin_lock_irqsave(&hwgroup->lock, flags); 1066 spin_lock_irqsave(&hwgroup->lock, flags);
1079 1067
@@ -1172,7 +1160,7 @@ out_handled:
1172 irq_ret = IRQ_HANDLED; 1160 irq_ret = IRQ_HANDLED;
1173out: 1161out:
1174 spin_unlock_irqrestore(&hwgroup->lock, flags); 1162 spin_unlock_irqrestore(&hwgroup->lock, flags);
1175 1163out_early:
1176 if (plug_device) 1164 if (plug_device)
1177 ide_plug_device(drive); 1165 ide_plug_device(drive);
1178 1166
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index c5adb7b9c5b5..2752509531b7 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -1022,6 +1022,7 @@ static int init_irq (ide_hwif_t *hwif)
1022 unsigned int index; 1022 unsigned int index;
1023 ide_hwgroup_t *hwgroup; 1023 ide_hwgroup_t *hwgroup;
1024 ide_hwif_t *match = NULL; 1024 ide_hwif_t *match = NULL;
1025 int sa = 0;
1025 1026
1026 mutex_lock(&ide_cfg_mtx); 1027 mutex_lock(&ide_cfg_mtx);
1027 hwif->hwgroup = NULL; 1028 hwif->hwgroup = NULL;
@@ -1076,24 +1077,18 @@ static int init_irq (ide_hwif_t *hwif)
1076 1077
1077 ide_ports[hwif->index] = hwif; 1078 ide_ports[hwif->index] = hwif;
1078 1079
1079 /*
1080 * Allocate the irq, if not already obtained for another hwif
1081 */
1082 if (!match || match->irq != hwif->irq) {
1083 int sa = 0;
1084#if defined(__mc68000__) 1080#if defined(__mc68000__)
1085 sa = IRQF_SHARED; 1081 sa = IRQF_SHARED;
1086#endif /* __mc68000__ */ 1082#endif /* __mc68000__ */
1087 1083
1088 if (hwif->chipset == ide_pci) 1084 if (hwif->chipset == ide_pci)
1089 sa = IRQF_SHARED; 1085 sa = IRQF_SHARED;
1090 1086
1091 if (io_ports->ctl_addr) 1087 if (io_ports->ctl_addr)
1092 hwif->tp_ops->set_irq(hwif, 1); 1088 hwif->tp_ops->set_irq(hwif, 1);
1093 1089
1094 if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup)) 1090 if (request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwif))
1095 goto out_unlink; 1091 goto out_unlink;
1096 }
1097 1092
1098 if (!hwif->rqsize) { 1093 if (!hwif->rqsize) {
1099 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) || 1094 if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 46a2d4ca812b..5bc2e4782a55 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -175,10 +175,6 @@ EXPORT_SYMBOL_GPL(ide_port_unregister_devices);
175 175
176void ide_unregister(ide_hwif_t *hwif) 176void ide_unregister(ide_hwif_t *hwif)
177{ 177{
178 ide_hwif_t *g;
179 ide_hwgroup_t *hwgroup;
180 int irq_count = 0;
181
182 BUG_ON(in_interrupt()); 178 BUG_ON(in_interrupt());
183 BUG_ON(irqs_disabled()); 179 BUG_ON(irqs_disabled());
184 180
@@ -191,18 +187,7 @@ void ide_unregister(ide_hwif_t *hwif)
191 187
192 ide_proc_unregister_port(hwif); 188 ide_proc_unregister_port(hwif);
193 189
194 hwgroup = hwif->hwgroup; 190 free_irq(hwif->irq, hwif);
195 /*
196 * free the irq if we were the only hwif using it
197 */
198 g = hwgroup->hwif;
199 do {
200 if (g->irq == hwif->irq)
201 ++irq_count;
202 g = g->next;
203 } while (g != hwgroup->hwif);
204 if (irq_count == 1)
205 free_irq(hwif->irq, hwgroup);
206 191
207 ide_remove_port_from_hwgroup(hwif); 192 ide_remove_port_from_hwgroup(hwif);
208 193
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 3de13df8bcef..f5382ad0bd4c 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1274,14 +1274,14 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout);
1274extern void ide_timer_expiry(unsigned long); 1274extern void ide_timer_expiry(unsigned long);
1275extern irqreturn_t ide_intr(int irq, void *dev_id); 1275extern irqreturn_t ide_intr(int irq, void *dev_id);
1276 1276
1277static inline int ide_lock_hwgroup(ide_hwgroup_t *hwgroup) 1277static inline int ide_lock_hwgroup(ide_hwgroup_t *hwgroup, ide_hwif_t *hwif)
1278{ 1278{
1279 if (hwgroup->busy) 1279 if (hwgroup->busy)
1280 return 1; 1280 return 1;
1281 1281
1282 hwgroup->busy = 1; 1282 hwgroup->busy = 1;
1283 /* for atari only */ 1283 /* for atari only */
1284 ide_get_lock(ide_intr, hwgroup); 1284 ide_get_lock(ide_intr, hwif);
1285 1285
1286 return 0; 1286 return 0;
1287} 1287}