mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-10 23:20:05 +00:00
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>
This commit is contained in:
parent
bd53cbcce5
commit
ae86afaee6
@ -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)
|
|||||||
* 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;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* handle the unexpected interrupt
|
|
||||||
*/
|
|
||||||
do {
|
|
||||||
if (hwif->irq == irq) {
|
|
||||||
stat = hwif->tp_ops->read_status(hwif);
|
|
||||||
|
|
||||||
if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
|
if (!OK_STAT(stat, ATA_DRDY, BAD_STAT)) {
|
||||||
/* Try to not flood the console with msgs */
|
/* Try to not flood the console with msgs */
|
||||||
static unsigned long last_msgtime, count;
|
static unsigned long last_msgtime, count;
|
||||||
++count;
|
++count;
|
||||||
|
|
||||||
if (time_after(jiffies, last_msgtime + HZ)) {
|
if (time_after(jiffies, last_msgtime + HZ)) {
|
||||||
last_msgtime = jiffies;
|
last_msgtime = jiffies;
|
||||||
printk(KERN_ERR "%s%s: unexpected interrupt, "
|
printk(KERN_ERR "%s: unexpected interrupt, "
|
||||||
"status=0x%02x, count=%ld\n",
|
"status=0x%02x, count=%ld\n",
|
||||||
hwif->name,
|
hwif->name, stat, count);
|
||||||
(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)
|
|||||||
|
|
||||||
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 @@ out_handled:
|
|||||||
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)
|
|||||||
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,11 +1077,6 @@ 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__ */
|
||||||
@ -1091,9 +1087,8 @@ static int init_irq (ide_hwif_t *hwif)
|
|||||||
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);
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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);
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user