Commit ac2b25e8 authored by Peter Chubb's avatar Peter Chubb Committed by David Mosberger

[PATCH] ia64: greatly speed-up I/O-SAPIC irq_enable()/irq_disable()

This patch changes the I/O SAPIC code to cache the low 32 bits of the mask
word in kernel memory.  This greatly speeds up mask_irq() and unmask_irq().

Normally, these operations are not on the speed-critical path of the
kernel but with certain devices drivers (including users-level device-
drivers) they can become performance-critical.
parent 4ab241d2
...@@ -103,6 +103,7 @@ static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED; ...@@ -103,6 +103,7 @@ static spinlock_t iosapic_lock = SPIN_LOCK_UNLOCKED;
static struct iosapic_intr_info { static struct iosapic_intr_info {
char *addr; /* base address of IOSAPIC */ char *addr; /* base address of IOSAPIC */
u32 low32; /* current value of low word of Redirection table entry */
unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */
char rte_index; /* IOSAPIC RTE index (-1 => not an IOSAPIC interrupt) */ char rte_index; /* IOSAPIC RTE index (-1 => not an IOSAPIC interrupt) */
unsigned char dmode : 3; /* delivery mode (see iosapic.h) */ unsigned char dmode : 3; /* delivery mode (see iosapic.h) */
...@@ -213,6 +214,7 @@ set_rte (unsigned int vector, unsigned int dest) ...@@ -213,6 +214,7 @@ set_rte (unsigned int vector, unsigned int dest)
writel(high32, addr + IOSAPIC_WINDOW); writel(high32, addr + IOSAPIC_WINDOW);
writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
writel(low32, addr + IOSAPIC_WINDOW); writel(low32, addr + IOSAPIC_WINDOW);
iosapic_intr_info[vector].low32 = low32;
} }
static void static void
...@@ -239,9 +241,10 @@ mask_irq (unsigned int irq) ...@@ -239,9 +241,10 @@ mask_irq (unsigned int irq)
spin_lock_irqsave(&iosapic_lock, flags); spin_lock_irqsave(&iosapic_lock, flags);
{ {
writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
low32 = readl(addr + IOSAPIC_WINDOW);
low32 |= (1 << IOSAPIC_MASK_SHIFT); /* set only the mask bit */ /* set only the mask bit */
low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK;
writel(low32, addr + IOSAPIC_WINDOW); writel(low32, addr + IOSAPIC_WINDOW);
} }
spin_unlock_irqrestore(&iosapic_lock, flags); spin_unlock_irqrestore(&iosapic_lock, flags);
...@@ -264,9 +267,7 @@ unmask_irq (unsigned int irq) ...@@ -264,9 +267,7 @@ unmask_irq (unsigned int irq)
spin_lock_irqsave(&iosapic_lock, flags); spin_lock_irqsave(&iosapic_lock, flags);
{ {
writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
low32 = readl(addr + IOSAPIC_WINDOW); low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK;
low32 &= ~(1 << IOSAPIC_MASK_SHIFT); /* clear only the mask bit */
writel(low32, addr + IOSAPIC_WINDOW); writel(low32, addr + IOSAPIC_WINDOW);
} }
spin_unlock_irqrestore(&iosapic_lock, flags); spin_unlock_irqrestore(&iosapic_lock, flags);
...@@ -307,9 +308,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) ...@@ -307,9 +308,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask)
{ {
/* get current delivery mode by reading the low32 */ /* get current delivery mode by reading the low32 */
writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
low32 = readl(addr + IOSAPIC_WINDOW); low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT);
low32 &= ~(7 << IOSAPIC_DELIVERY_SHIFT);
if (redir) if (redir)
/* change delivery mode to lowest priority */ /* change delivery mode to lowest priority */
low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT); low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT);
...@@ -317,6 +316,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask) ...@@ -317,6 +316,7 @@ iosapic_set_affinity (unsigned int irq, cpumask_t mask)
/* change delivery mode to fixed */ /* change delivery mode to fixed */
low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT); low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT);
iosapic_intr_info[vec].low32 = low32;
writel(IOSAPIC_RTE_HIGH(rte_index), addr + IOSAPIC_REG_SELECT); writel(IOSAPIC_RTE_HIGH(rte_index), addr + IOSAPIC_REG_SELECT);
writel(high32, addr + IOSAPIC_WINDOW); writel(high32, addr + IOSAPIC_WINDOW);
writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT); writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
......
...@@ -45,9 +45,9 @@ ...@@ -45,9 +45,9 @@
/* /*
* Mask bit * Mask bit
*/ */
#define IOSAPIC_MASK_SHIFT 16 #define IOSAPIC_MASK_SHIFT 16
#define IOSAPIC_UNMASK 0 #define IOSAPIC_MASK (1<<IOSAPIC_MASK_SHIFT)
#define IOSAPIC_MSAK 1
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
......
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