[Patch Part2 v4 20/33] x86/irq: Use cached IOAPIC entry instead of reading from hardware

2015-01-19 Thread Jiang Liu
Use cached IOAPIC entry instead of reading data from IOAPIC hardware
registers to improve performance.

Signed-off-by: Jiang Liu 
Cc: Konrad Rzeszutek Wilk 
Cc: Tony Luck 
Cc: Joerg Roedel 
Cc: Greg Kroah-Hartman 
Cc: Bjorn Helgaas 
Cc: Benjamin Herrenschmidt 
Cc: Rafael J. Wysocki 
Cc: Randy Dunlap 
Cc: Yinghai Lu 
Cc: Borislav Petkov 
Cc: Grant Likely 
Link: 
http://lkml.kernel.org/r/1416901802-24211-30-git-send-email-jiang@linux.intel.com
Signed-off-by: Thomas Gleixner 
Tested-by: Joerg Roedel 
---
 arch/x86/kernel/apic/io_apic.c |   78 +++-
 1 file changed, 21 insertions(+), 57 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 2298ee7d86d3..83c3c90bd903 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -69,8 +69,13 @@
 int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
 
 /*
- *  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
+ * loss this knowledge.
  */
 int sis_apic_bug = -1;
 
@@ -295,22 +300,6 @@ static void io_apic_write(unsigned int apic, unsigned int 
reg,
writel(value, _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, _apic->index);
-   writel(value, _apic->data);
-}
-
 union entry_union {
struct { u32 w1, w2; };
struct IO_APIC_route_entry entry;
@@ -447,29 +436,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)
@@ -1737,28 +1720,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
@@ -1924,6 +1885,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;
@@ -1934,7 +1896,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);
+ 

[Patch Part2 v4 20/33] x86/irq: Use cached IOAPIC entry instead of reading from hardware

2015-01-19 Thread Jiang Liu
Use cached IOAPIC entry instead of reading data from IOAPIC hardware
registers to improve performance.

Signed-off-by: Jiang Liu jiang@linux.intel.com
Cc: Konrad Rzeszutek Wilk konrad.w...@oracle.com
Cc: Tony Luck tony.l...@intel.com
Cc: Joerg Roedel j...@8bytes.org
Cc: Greg Kroah-Hartman gre...@linuxfoundation.org
Cc: Bjorn Helgaas bhelg...@google.com
Cc: Benjamin Herrenschmidt b...@kernel.crashing.org
Cc: Rafael J. Wysocki r...@rjwysocki.net
Cc: Randy Dunlap rdun...@infradead.org
Cc: Yinghai Lu ying...@kernel.org
Cc: Borislav Petkov b...@alien8.de
Cc: Grant Likely grant.lik...@linaro.org
Link: 
http://lkml.kernel.org/r/1416901802-24211-30-git-send-email-jiang@linux.intel.com
Signed-off-by: Thomas Gleixner t...@linutronix.de
Tested-by: Joerg Roedel jroe...@suse.de
---
 arch/x86/kernel/apic/io_apic.c |   78 +++-
 1 file changed, 21 insertions(+), 57 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 2298ee7d86d3..83c3c90bd903 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -69,8 +69,13 @@
 int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
 
 /*
- *  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
+ * loss this knowledge.
  */
 int sis_apic_bug = -1;
 
@@ -295,22 +300,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;
@@ -447,29 +436,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)
@@ -1737,28 +1720,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
@@ -1924,6 +1885,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;
@@ -1934,7 +1896,9 @@ static int