diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-01-06 11:20:48 -0500 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-01-06 11:20:48 -0500 |
commit | ae86afaee6a1c77c7a06d81dcc3bf872204d3bec (patch) | |
tree | 992b5b436de3033c23c3dc6cd7ded617a4603eed | |
parent | bd53cbcce501b61921a1af2dddfa87c5b9923dfd (diff) |
ide: use per-port IRQ handlers
Use hwif instead of hwgroup as {request,free}_irq()'s cookie,
teach ide_intr() to return early for non-active serialized ports,
modify unexpected_intr() accordingly and then use per-port IRQ
handlers instead of per-hwgroup ones.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r-- | drivers/ide/ide-io.c | 58 | ||||
-rw-r--r-- | drivers/ide/ide-probe.c | 21 | ||||
-rw-r--r-- | drivers/ide/ide.c | 17 | ||||
-rw-r--r-- | include/linux/ide.h | 4 |
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; |
728 | repeat: | 728 | repeat: |
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 | ||
1011 | static void unexpected_intr(int irq, ide_hwif_t *hwif) | 1007 | static 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 | ||
1064 | irqreturn_t ide_intr (int irq, void *dev_id) | 1050 | irqreturn_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; |
1173 | out: | 1161 | out: |
1174 | spin_unlock_irqrestore(&hwgroup->lock, flags); | 1162 | spin_unlock_irqrestore(&hwgroup->lock, flags); |
1175 | 1163 | out_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 | ||
176 | void ide_unregister(ide_hwif_t *hwif) | 176 | void 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); | |||
1274 | extern void ide_timer_expiry(unsigned long); | 1274 | extern void ide_timer_expiry(unsigned long); |
1275 | extern irqreturn_t ide_intr(int irq, void *dev_id); | 1275 | extern irqreturn_t ide_intr(int irq, void *dev_id); |
1276 | 1276 | ||
1277 | static inline int ide_lock_hwgroup(ide_hwgroup_t *hwgroup) | 1277 | static 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 | } |