aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-11-08 13:45:37 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-11-08 13:45:37 -0500
commit082f2f84be5db164280483efa7eb1549d867353d (patch)
treec21e5863332a4035537e1f868b46ebc9c203a394
parentde8e7c12430a73654ae3cedbc45428d56c6b777b (diff)
parent48797ebd9e8b16fddcd4ef062f792314a6b9219a (diff)
Merge merom:v2.6/linux
* merom:v2.6/linux: x86-64: write IO APIC irq routing entries in correct order x86-64: clean up io-apic accesses
-rw-r--r--arch/x86_64/kernel/io_apic.c72
-rw-r--r--include/asm-x86_64/io_apic.h34
2 files changed, 69 insertions, 37 deletions
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index fe429e5d6b29..3b8f9c68ad3c 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -88,6 +88,52 @@ static struct irq_pin_list {
88 short apic, pin, next; 88 short apic, pin, next;
89} irq_2_pin[PIN_MAP_SIZE]; 89} irq_2_pin[PIN_MAP_SIZE];
90 90
91struct io_apic {
92 unsigned int index;
93 unsigned int unused[3];
94 unsigned int data;
95};
96
97static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
98{
99 return (void __iomem *) __fix_to_virt(FIX_IO_APIC_BASE_0 + idx)
100 + (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK);
101}
102
103static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
104{
105 struct io_apic __iomem *io_apic = io_apic_base(apic);
106 writel(reg, &io_apic->index);
107 return readl(&io_apic->data);
108}
109
110static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
111{
112 struct io_apic __iomem *io_apic = io_apic_base(apic);
113 writel(reg, &io_apic->index);
114 writel(value, &io_apic->data);
115}
116
117/*
118 * Re-write a value: to be used for read-modify-write
119 * cycles where the read already set up the index register.
120 */
121static inline void io_apic_modify(unsigned int apic, unsigned int value)
122{
123 struct io_apic __iomem *io_apic = io_apic_base(apic);
124 writel(value, &io_apic->data);
125}
126
127/*
128 * Synchronize the IO-APIC and the CPU by doing
129 * a dummy read from the IO-APIC
130 */
131static inline void io_apic_sync(unsigned int apic)
132{
133 struct io_apic __iomem *io_apic = io_apic_base(apic);
134 readl(&io_apic->data);
135}
136
91#define __DO_ACTION(R, ACTION, FINAL) \ 137#define __DO_ACTION(R, ACTION, FINAL) \
92 \ 138 \
93{ \ 139{ \
@@ -126,12 +172,34 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin)
126 return eu.entry; 172 return eu.entry;
127} 173}
128 174
175/*
176 * When we write a new IO APIC routing entry, we need to write the high
177 * word first! If the mask bit in the low word is clear, we will enable
178 * the interrupt, and we need to make sure the entry is fully populated
179 * before that happens.
180 */
129static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) 181static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e)
130{ 182{
131 unsigned long flags; 183 unsigned long flags;
132 union entry_union eu; 184 union entry_union eu;
133 eu.entry = e; 185 eu.entry = e;
134 spin_lock_irqsave(&ioapic_lock, flags); 186 spin_lock_irqsave(&ioapic_lock, flags);
187 io_apic_write(apic, 0x11 + 2*pin, eu.w2);
188 io_apic_write(apic, 0x10 + 2*pin, eu.w1);
189 spin_unlock_irqrestore(&ioapic_lock, flags);
190}
191
192/*
193 * When we mask an IO APIC routing entry, we need to write the low
194 * word first, in order to set the mask bit before we change the
195 * high bits!
196 */
197static void ioapic_mask_entry(int apic, int pin)
198{
199 unsigned long flags;
200 union entry_union eu = { .entry.mask = 1 };
201
202 spin_lock_irqsave(&ioapic_lock, flags);
135 io_apic_write(apic, 0x10 + 2*pin, eu.w1); 203 io_apic_write(apic, 0x10 + 2*pin, eu.w1);
136 io_apic_write(apic, 0x11 + 2*pin, eu.w2); 204 io_apic_write(apic, 0x11 + 2*pin, eu.w2);
137 spin_unlock_irqrestore(&ioapic_lock, flags); 205 spin_unlock_irqrestore(&ioapic_lock, flags);
@@ -256,9 +324,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
256 /* 324 /*
257 * Disable it in the IO-APIC irq-routing table: 325 * Disable it in the IO-APIC irq-routing table:
258 */ 326 */
259 memset(&entry, 0, sizeof(entry)); 327 ioapic_mask_entry(apic, pin);
260 entry.mask = 1;
261 ioapic_write_entry(apic, pin, entry);
262} 328}
263 329
264static void clear_IO_APIC (void) 330static void clear_IO_APIC (void)
diff --git a/include/asm-x86_64/io_apic.h b/include/asm-x86_64/io_apic.h
index 171ec2dc8c04..561ecbfd4cb5 100644
--- a/include/asm-x86_64/io_apic.h
+++ b/include/asm-x86_64/io_apic.h
@@ -12,10 +12,6 @@
12 12
13#define APIC_MISMATCH_DEBUG 13#define APIC_MISMATCH_DEBUG
14 14
15#define IO_APIC_BASE(idx) \
16 ((volatile int *)(__fix_to_virt(FIX_IO_APIC_BASE_0 + idx) \
17 + (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK)))
18
19/* 15/*
20 * The structure of the IO-APIC: 16 * The structure of the IO-APIC:
21 */ 17 */
@@ -119,36 +115,6 @@ extern struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
119/* non-0 if default (table-less) MP configuration */ 115/* non-0 if default (table-less) MP configuration */
120extern int mpc_default_type; 116extern int mpc_default_type;
121 117
122static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
123{
124 *IO_APIC_BASE(apic) = reg;
125 return *(IO_APIC_BASE(apic)+4);
126}
127
128static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
129{
130 *IO_APIC_BASE(apic) = reg;
131 *(IO_APIC_BASE(apic)+4) = value;
132}
133
134/*
135 * Re-write a value: to be used for read-modify-write
136 * cycles where the read already set up the index register.
137 */
138static inline void io_apic_modify(unsigned int apic, unsigned int value)
139{
140 *(IO_APIC_BASE(apic)+4) = value;
141}
142
143/*
144 * Synchronize the IO-APIC and the CPU by doing
145 * a dummy read from the IO-APIC
146 */
147static inline void io_apic_sync(unsigned int apic)
148{
149 (void) *(IO_APIC_BASE(apic)+4);
150}
151
152/* 1 if "noapic" boot option passed */ 118/* 1 if "noapic" boot option passed */
153extern int skip_ioapic_setup; 119extern int skip_ioapic_setup;
154 120