x86/irq: Use cached IOAPIC entry instead of reading from hardware
Use cached IOAPIC entry instead of reading data from IOAPIC hardware registers to improve performance. Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> Tested-by: Joerg Roedel <jroedel@suse.de> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Cc: David Cohen <david.a.cohen@linux.intel.com> Cc: Sander Eikelenboom <linux@eikelenboom.it> Cc: David Vrabel <david.vrabel@citrix.com> Cc: Tony Luck <tony.luck@intel.com> Cc: Joerg Roedel <joro@8bytes.org> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Bjorn Helgaas <bhelgaas@google.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Rafael J. Wysocki <rjw@rjwysocki.net> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Dimitri Sivanich <sivanich@sgi.com> Cc: Grant Likely <grant.likely@linaro.org> Link: http://lkml.kernel.org/r/1428978610-28986-21-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
154d9e50e4
commit
0be275e3a5
|
@ -67,8 +67,13 @@
|
|||
list_for_each_entry(entry, &head, list)
|
||||
|
||||
/*
|
||||
* Is the SiS APIC rmw bug present ?
|
||||
* Is the SiS APIC rmw bug present ?
|
||||
* -1 = don't know, 0 = no, 1 = yes
|
||||
* When doing a read-modify-write operation on IOAPIC registers, older SiS APIC
|
||||
* requires we rewrite the index register again where the read already set up
|
||||
* the index register.
|
||||
* The code to make use of sis_apic_bug has been removed, but we don't want to
|
||||
* lose this knowledge.
|
||||
*/
|
||||
int sis_apic_bug = -1;
|
||||
|
||||
|
@ -293,22 +298,6 @@ static void io_apic_write(unsigned int apic, unsigned int reg,
|
|||
writel(value, &io_apic->data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-write a value: to be used for read-modify-write
|
||||
* cycles where the read already set up the index register.
|
||||
*
|
||||
* Older SiS APIC requires we rewrite the index register
|
||||
*/
|
||||
static void io_apic_modify(unsigned int apic, unsigned int reg,
|
||||
unsigned int value)
|
||||
{
|
||||
struct io_apic __iomem *io_apic = io_apic_base(apic);
|
||||
|
||||
if (sis_apic_bug)
|
||||
writel(reg, &io_apic->index);
|
||||
writel(value, &io_apic->data);
|
||||
}
|
||||
|
||||
union entry_union {
|
||||
struct { u32 w1, w2; };
|
||||
struct IO_APIC_route_entry entry;
|
||||
|
@ -445,29 +434,23 @@ static void __init replace_pin_at_irq_node(struct mp_chip_data *data, int node,
|
|||
add_pin_to_irq_node(data, node, newapic, newpin);
|
||||
}
|
||||
|
||||
static void __io_apic_modify_irq(struct irq_pin_list *entry,
|
||||
int mask_and, int mask_or,
|
||||
void (*final)(struct irq_pin_list *entry))
|
||||
{
|
||||
unsigned int reg, pin;
|
||||
|
||||
pin = entry->pin;
|
||||
reg = io_apic_read(entry->apic, 0x10 + pin * 2);
|
||||
reg &= mask_and;
|
||||
reg |= mask_or;
|
||||
io_apic_modify(entry->apic, 0x10 + pin * 2, reg);
|
||||
if (final)
|
||||
final(entry);
|
||||
}
|
||||
|
||||
static void io_apic_modify_irq(struct mp_chip_data *data,
|
||||
int mask_and, int mask_or,
|
||||
void (*final)(struct irq_pin_list *entry))
|
||||
{
|
||||
union entry_union eu;
|
||||
struct irq_pin_list *entry;
|
||||
|
||||
for_each_irq_pin(entry, data->irq_2_pin)
|
||||
__io_apic_modify_irq(entry, mask_and, mask_or, final);
|
||||
eu.entry = data->entry;
|
||||
eu.w1 &= mask_and;
|
||||
eu.w1 |= mask_or;
|
||||
data->entry = eu.entry;
|
||||
|
||||
for_each_irq_pin(entry, data->irq_2_pin) {
|
||||
io_apic_write(entry->apic, 0x10 + 2 * entry->pin, eu.w1);
|
||||
if (final)
|
||||
final(entry);
|
||||
}
|
||||
}
|
||||
|
||||
static void io_apic_sync(struct irq_pin_list *entry)
|
||||
|
@ -1739,28 +1722,6 @@ static unsigned int startup_ioapic_irq(struct irq_data *data)
|
|||
return was_pending;
|
||||
}
|
||||
|
||||
static void __target_IO_APIC_irq(unsigned int irq, struct irq_cfg *cfg,
|
||||
struct mp_chip_data *data)
|
||||
{
|
||||
int apic, pin;
|
||||
struct irq_pin_list *entry;
|
||||
u8 vector = cfg->vector;
|
||||
unsigned int dest = SET_APIC_LOGICAL_ID(cfg->dest_apicid);
|
||||
|
||||
for_each_irq_pin(entry, data->irq_2_pin) {
|
||||
unsigned int reg;
|
||||
|
||||
apic = entry->apic;
|
||||
pin = entry->pin;
|
||||
|
||||
io_apic_write(apic, 0x11 + pin*2, dest);
|
||||
reg = io_apic_read(apic, 0x10 + pin*2);
|
||||
reg &= ~IO_APIC_REDIR_VECTOR_MASK;
|
||||
reg |= vector;
|
||||
io_apic_modify(apic, 0x10 + pin*2, reg);
|
||||
}
|
||||
}
|
||||
|
||||
atomic_t irq_mis_count;
|
||||
|
||||
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
||||
|
@ -1926,6 +1887,7 @@ static int ioapic_set_affinity(struct irq_data *irq_data,
|
|||
{
|
||||
struct irq_data *parent = irq_data->parent_data;
|
||||
struct mp_chip_data *data = irq_data->chip_data;
|
||||
struct irq_pin_list *entry;
|
||||
struct irq_cfg *cfg;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
@ -1936,7 +1898,9 @@ static int ioapic_set_affinity(struct irq_data *irq_data,
|
|||
cfg = irqd_cfg(irq_data);
|
||||
data->entry.dest = cfg->dest_apicid;
|
||||
data->entry.vector = cfg->vector;
|
||||
__target_IO_APIC_irq(irq_data->irq, cfg, irq_data->chip_data);
|
||||
for_each_irq_pin(entry, data->irq_2_pin)
|
||||
__ioapic_write_entry(entry->apic, entry->pin,
|
||||
data->entry);
|
||||
}
|
||||
raw_spin_unlock_irqrestore(&ioapic_lock, flags);
|
||||
|
||||
|
|
Loading…
Reference in New Issue