From ae86afaee6a1c77c7a06d81dcc3bf872204d3bec Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 6 Jan 2009 17:20:48 +0100 Subject: 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 --- drivers/ide/ide-io.c | 58 ++++++++++++++++++++----------------------------- drivers/ide/ide-probe.c | 21 +++++++----------- drivers/ide/ide.c | 17 +-------------- 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) spin_unlock_irq(q->queue_lock); spin_lock_irq(&hwgroup->lock); - if (!ide_lock_hwgroup(hwgroup)) { + if (!ide_lock_hwgroup(hwgroup, hwif)) { ide_hwif_t *prev_port; repeat: prev_port = hwif->host->cur_port; @@ -1002,44 +1002,30 @@ void ide_timer_expiry (unsigned long data) * before completing the issuance of any new drive command, so we will not * be accidentally invoked as a result of any valid command completion * interrupt. - * - * Note that we must walk the entire hwgroup here. We know which hwif - * is doing the current command, but we don't know which hwif burped - * mysteriously. */ static void unexpected_intr(int irq, ide_hwif_t *hwif) { - ide_hwgroup_t *hwgroup = hwif->hwgroup; - u8 stat; - - /* - * handle the unexpected interrupt - */ - do { - if (hwif->irq == irq) { - stat = hwif->tp_ops->read_status(hwif); - - if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) { - /* Try to not flood the console with msgs */ - static unsigned long last_msgtime, count; - ++count; - if (time_after(jiffies, last_msgtime + HZ)) { - last_msgtime = jiffies; - printk(KERN_ERR "%s%s: unexpected interrupt, " - "status=0x%02x, count=%ld\n", - hwif->name, - (hwif->next==hwgroup->hwif) ? "" : "(?)", stat, count); - } - } + u8 stat = hwif->tp_ops->read_status(hwif); + + if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) { + /* Try to not flood the console with msgs */ + static unsigned long last_msgtime, count; + ++count; + + if (time_after(jiffies, last_msgtime + HZ)) { + last_msgtime = jiffies; + printk(KERN_ERR "%s: unexpected interrupt, " + "status=0x%02x, count=%ld\n", + hwif->name, stat, count); } - } while ((hwif = hwif->next) != hwgroup->hwif); + } } /** * ide_intr - default IDE interrupt handler * @irq: interrupt number - * @dev_id: hwif group + * @dev_id: hwif * @regs: unused weirdness from the kernel irq layer * * 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) irqreturn_t ide_intr (int irq, void *dev_id) { - unsigned long flags; - ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; - ide_hwif_t *hwif = hwgroup->hwif; + ide_hwif_t *hwif = (ide_hwif_t *)dev_id; + ide_hwgroup_t *hwgroup = hwif->hwgroup; ide_drive_t *uninitialized_var(drive); ide_handler_t *handler; + unsigned long flags; ide_startstop_t startstop; irqreturn_t irq_ret = IRQ_NONE; int plug_device = 0; - if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) - hwif = hwif->host->cur_port; + if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) { + if (hwif != hwif->host->cur_port) + goto out_early; + } spin_lock_irqsave(&hwgroup->lock, flags); @@ -1172,7 +1160,7 @@ out_handled: irq_ret = IRQ_HANDLED; out: spin_unlock_irqrestore(&hwgroup->lock, flags); - +out_early: if (plug_device) ide_plug_device(drive); 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) unsigned int index; ide_hwgroup_t *hwgroup; ide_hwif_t *match = NULL; + int sa = 0; mutex_lock(&ide_cfg_mtx); hwif->hwgroup = NULL; @@ -1076,24 +1077,18 @@ static int init_irq (ide_hwif_t *hwif) ide_ports[hwif->index] = hwif; - /* - * Allocate the irq, if not already obtained for another hwif - */ - if (!match || match->irq != hwif->irq) { - int sa = 0; #if defined(__mc68000__) - sa = IRQF_SHARED; + sa = IRQF_SHARED; #endif /* __mc68000__ */ - if (hwif->chipset == ide_pci) - sa = IRQF_SHARED; + if (hwif->chipset == ide_pci) + sa = IRQF_SHARED; - if (io_ports->ctl_addr) - hwif->tp_ops->set_irq(hwif, 1); + if (io_ports->ctl_addr) + hwif->tp_ops->set_irq(hwif, 1); - if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup)) - goto out_unlink; - } + if (request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwif)) + goto out_unlink; if (!hwif->rqsize) { 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); void ide_unregister(ide_hwif_t *hwif) { - ide_hwif_t *g; - ide_hwgroup_t *hwgroup; - int irq_count = 0; - BUG_ON(in_interrupt()); BUG_ON(irqs_disabled()); @@ -191,18 +187,7 @@ void ide_unregister(ide_hwif_t *hwif) ide_proc_unregister_port(hwif); - hwgroup = hwif->hwgroup; - /* - * free the irq if we were the only hwif using it - */ - g = hwgroup->hwif; - do { - if (g->irq == hwif->irq) - ++irq_count; - g = g->next; - } while (g != hwgroup->hwif); - if (irq_count == 1) - free_irq(hwif->irq, hwgroup); + free_irq(hwif->irq, hwif); ide_remove_port_from_hwgroup(hwif); 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); extern void ide_timer_expiry(unsigned long); extern irqreturn_t ide_intr(int irq, void *dev_id); -static inline int ide_lock_hwgroup(ide_hwgroup_t *hwgroup) +static inline int ide_lock_hwgroup(ide_hwgroup_t *hwgroup, ide_hwif_t *hwif) { if (hwgroup->busy) return 1; hwgroup->busy = 1; /* for atari only */ - ide_get_lock(ide_intr, hwgroup); + ide_get_lock(ide_intr, hwif); return 0; } -- cgit v1.2.3