ide: use per-port IRQ handlers
Bartlomiej Zolnierkiewicz [Tue, 6 Jan 2009 16:20:48 +0000 (17:20 +0100)]
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>

drivers/ide/ide-io.c
drivers/ide/ide-probe.c
drivers/ide/ide.c
include/linux/ide.h

index 43bf43d..1fc739f 100644 (file)
@@ -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);
 
index c5adb7b..2752509 100644 (file)
@@ -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) ||
index 46a2d4c..5bc2e47 100644 (file)
@@ -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);
 
index 3de13df..f5382ad 100644 (file)
@@ -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;
 }