mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-16 23:45:31 +08:00
sata_mv: cache main_irq_mask register in hpriv
Part five of simplifying/fixing handling of the main_irq_mask register to resolve unexpected interrupt issues observed in 2.6.26-rc*. Keep a cached copy of the main_irq_mask so that we don't have to stall the CPU to read it on every pass through mv_interrupt. This significantly speeds up interrupt handling, both for sata_mv, and for any other driver/device sharing the same PCI IRQ line. Signed-off-by: Mark Lord <mlord@pobox.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
This commit is contained in:
parent
a44253d24a
commit
96e2c48793
@ -458,6 +458,7 @@ struct mv_port_signal {
|
|||||||
|
|
||||||
struct mv_host_priv {
|
struct mv_host_priv {
|
||||||
u32 hp_flags;
|
u32 hp_flags;
|
||||||
|
u32 main_irq_mask;
|
||||||
struct mv_port_signal signal[8];
|
struct mv_port_signal signal[8];
|
||||||
const struct mv_hw_ops *ops;
|
const struct mv_hw_ops *ops;
|
||||||
int n_ports;
|
int n_ports;
|
||||||
@ -843,10 +844,12 @@ static void mv_set_main_irq_mask(struct ata_host *host,
|
|||||||
struct mv_host_priv *hpriv = host->private_data;
|
struct mv_host_priv *hpriv = host->private_data;
|
||||||
u32 old_mask, new_mask;
|
u32 old_mask, new_mask;
|
||||||
|
|
||||||
old_mask = readl(hpriv->main_irq_mask_addr);
|
old_mask = hpriv->main_irq_mask;
|
||||||
new_mask = (old_mask & ~disable_bits) | enable_bits;
|
new_mask = (old_mask & ~disable_bits) | enable_bits;
|
||||||
if (new_mask != old_mask)
|
if (new_mask != old_mask) {
|
||||||
|
hpriv->main_irq_mask = new_mask;
|
||||||
writelfl(new_mask, hpriv->main_irq_mask_addr);
|
writelfl(new_mask, hpriv->main_irq_mask_addr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mv_enable_port_irqs(struct ata_port *ap,
|
static void mv_enable_port_irqs(struct ata_port *ap,
|
||||||
@ -2200,12 +2203,11 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
|
|||||||
struct ata_host *host = dev_instance;
|
struct ata_host *host = dev_instance;
|
||||||
struct mv_host_priv *hpriv = host->private_data;
|
struct mv_host_priv *hpriv = host->private_data;
|
||||||
unsigned int handled = 0;
|
unsigned int handled = 0;
|
||||||
u32 main_irq_cause, main_irq_mask, pending_irqs;
|
u32 main_irq_cause, pending_irqs;
|
||||||
|
|
||||||
spin_lock(&host->lock);
|
spin_lock(&host->lock);
|
||||||
main_irq_cause = readl(hpriv->main_irq_cause_addr);
|
main_irq_cause = readl(hpriv->main_irq_cause_addr);
|
||||||
main_irq_mask = readl(hpriv->main_irq_mask_addr);
|
pending_irqs = main_irq_cause & hpriv->main_irq_mask;
|
||||||
pending_irqs = main_irq_cause & main_irq_mask;
|
|
||||||
/*
|
/*
|
||||||
* Deal with cases where we either have nothing pending, or have read
|
* Deal with cases where we either have nothing pending, or have read
|
||||||
* a bogus register value which can indicate HW removal or PCI fault.
|
* a bogus register value which can indicate HW removal or PCI fault.
|
||||||
|
Loading…
Reference in New Issue
Block a user