summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-01-06 17:20:48 +0100
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-01-06 17:20:48 +0100
commitae86afaee6a1c77c7a06d81dcc3bf872204d3bec (patch)
tree992b5b436de3033c23c3dc6cd7ded617a4603eed
parentbd53cbcce501b61921a1af2dddfa87c5b9923dfd (diff)
downloadlinux-ae86afaee6a1c77c7a06d81dcc3bf872204d3bec.tar.gz
linux-ae86afaee6a1c77c7a06d81dcc3bf872204d3bec.tar.bz2
linux-ae86afaee6a1c77c7a06d81dcc3bf872204d3bec.zip
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.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)
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;
}