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: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
parent bd53cbcc
...@@ -723,7 +723,7 @@ void do_ide_request(struct request_queue *q) ...@@ -723,7 +723,7 @@ void do_ide_request(struct request_queue *q)
spin_unlock_irq(q->queue_lock); spin_unlock_irq(q->queue_lock);
spin_lock_irq(&hwgroup->lock); spin_lock_irq(&hwgroup->lock);
if (!ide_lock_hwgroup(hwgroup)) { if (!ide_lock_hwgroup(hwgroup, hwif)) {
ide_hwif_t *prev_port; ide_hwif_t *prev_port;
repeat: repeat:
prev_port = hwif->host->cur_port; prev_port = hwif->host->cur_port;
...@@ -1002,44 +1002,30 @@ void ide_timer_expiry (unsigned long data) ...@@ -1002,44 +1002,30 @@ void ide_timer_expiry (unsigned long data)
* before completing the issuance of any new drive command, so we will not * before completing the issuance of any new drive command, so we will not
* be accidentally invoked as a result of any valid command completion * be accidentally invoked as a result of any valid command completion
* interrupt. * 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) static void unexpected_intr(int irq, ide_hwif_t *hwif)
{ {
ide_hwgroup_t *hwgroup = hwif->hwgroup; u8 stat = hwif->tp_ops->read_status(hwif);
u8 stat;
if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
/* /* Try to not flood the console with msgs */
* handle the unexpected interrupt static unsigned long last_msgtime, count;
*/ ++count;
do {
if (hwif->irq == irq) { if (time_after(jiffies, last_msgtime + HZ)) {
stat = hwif->tp_ops->read_status(hwif); last_msgtime = jiffies;
printk(KERN_ERR "%s: unexpected interrupt, "
if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) { "status=0x%02x, count=%ld\n",
/* Try to not flood the console with msgs */ hwif->name, stat, count);
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);
}
}
} }
} while ((hwif = hwif->next) != hwgroup->hwif); }
} }
/** /**
* ide_intr - default IDE interrupt handler * ide_intr - default IDE interrupt handler
* @irq: interrupt number * @irq: interrupt number
* @dev_id: hwif group * @dev_id: hwif
* @regs: unused weirdness from the kernel irq layer * @regs: unused weirdness from the kernel irq layer
* *
* This is the default IRQ handler for the IDE layer. You should * 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,17 +1049,19 @@ static void unexpected_intr(int irq, ide_hwif_t *hwif)
irqreturn_t ide_intr (int irq, void *dev_id) irqreturn_t ide_intr (int irq, void *dev_id)
{ {
unsigned long flags; ide_hwif_t *hwif = (ide_hwif_t *)dev_id;
ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id; ide_hwgroup_t *hwgroup = hwif->hwgroup;
ide_hwif_t *hwif = hwgroup->hwif;
ide_drive_t *uninitialized_var(drive); ide_drive_t *uninitialized_var(drive);
ide_handler_t *handler; ide_handler_t *handler;
unsigned long flags;
ide_startstop_t startstop; ide_startstop_t startstop;
irqreturn_t irq_ret = IRQ_NONE; irqreturn_t irq_ret = IRQ_NONE;
int plug_device = 0; int plug_device = 0;
if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) if (hwif->host->host_flags & IDE_HFLAG_SERIALIZE) {
hwif = hwif->host->cur_port; if (hwif != hwif->host->cur_port)
goto out_early;
}
spin_lock_irqsave(&hwgroup->lock, flags); spin_lock_irqsave(&hwgroup->lock, flags);
...@@ -1172,7 +1160,7 @@ irqreturn_t ide_intr (int irq, void *dev_id) ...@@ -1172,7 +1160,7 @@ irqreturn_t ide_intr (int irq, void *dev_id)
irq_ret = IRQ_HANDLED; irq_ret = IRQ_HANDLED;
out: out:
spin_unlock_irqrestore(&hwgroup->lock, flags); spin_unlock_irqrestore(&hwgroup->lock, flags);
out_early:
if (plug_device) if (plug_device)
ide_plug_device(drive); ide_plug_device(drive);
......
...@@ -1022,6 +1022,7 @@ static int init_irq (ide_hwif_t *hwif) ...@@ -1022,6 +1022,7 @@ static int init_irq (ide_hwif_t *hwif)
unsigned int index; unsigned int index;
ide_hwgroup_t *hwgroup; ide_hwgroup_t *hwgroup;
ide_hwif_t *match = NULL; ide_hwif_t *match = NULL;
int sa = 0;
mutex_lock(&ide_cfg_mtx); mutex_lock(&ide_cfg_mtx);
hwif->hwgroup = NULL; hwif->hwgroup = NULL;
...@@ -1076,24 +1077,18 @@ static int init_irq (ide_hwif_t *hwif) ...@@ -1076,24 +1077,18 @@ static int init_irq (ide_hwif_t *hwif)
ide_ports[hwif->index] = 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__) #if defined(__mc68000__)
sa = IRQF_SHARED; sa = IRQF_SHARED;
#endif /* __mc68000__ */ #endif /* __mc68000__ */
if (hwif->chipset == ide_pci) if (hwif->chipset == ide_pci)
sa = IRQF_SHARED; sa = IRQF_SHARED;
if (io_ports->ctl_addr) if (io_ports->ctl_addr)
hwif->tp_ops->set_irq(hwif, 1); hwif->tp_ops->set_irq(hwif, 1);
if (request_irq(hwif->irq,&ide_intr,sa,hwif->name,hwgroup)) if (request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwif))
goto out_unlink; goto out_unlink;
}
if (!hwif->rqsize) { if (!hwif->rqsize) {
if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) || if ((hwif->host_flags & IDE_HFLAG_NO_LBA48) ||
......
...@@ -175,10 +175,6 @@ EXPORT_SYMBOL_GPL(ide_port_unregister_devices); ...@@ -175,10 +175,6 @@ EXPORT_SYMBOL_GPL(ide_port_unregister_devices);
void ide_unregister(ide_hwif_t *hwif) 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(in_interrupt());
BUG_ON(irqs_disabled()); BUG_ON(irqs_disabled());
...@@ -191,18 +187,7 @@ void ide_unregister(ide_hwif_t *hwif) ...@@ -191,18 +187,7 @@ void ide_unregister(ide_hwif_t *hwif)
ide_proc_unregister_port(hwif); ide_proc_unregister_port(hwif);
hwgroup = hwif->hwgroup; free_irq(hwif->irq, hwif);
/*
* 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);
ide_remove_port_from_hwgroup(hwif); ide_remove_port_from_hwgroup(hwif);
......
...@@ -1274,14 +1274,14 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout); ...@@ -1274,14 +1274,14 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout);
extern void ide_timer_expiry(unsigned long); extern void ide_timer_expiry(unsigned long);
extern irqreturn_t ide_intr(int irq, void *dev_id); 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) if (hwgroup->busy)
return 1; return 1;
hwgroup->busy = 1; hwgroup->busy = 1;
/* for atari only */ /* for atari only */
ide_get_lock(ide_intr, hwgroup); ide_get_lock(ide_intr, hwif);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment