diff options
Diffstat (limited to 'arch/x86/kernel/i8259.c')
-rw-r--r-- | arch/x86/kernel/i8259.c | 95 |
1 files changed, 72 insertions, 23 deletions
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c index df89102bef80..7c9f02c130f3 100644 --- a/arch/x86/kernel/i8259.c +++ b/arch/x86/kernel/i8259.c | |||
@@ -5,7 +5,6 @@ | |||
5 | #include <linux/ioport.h> | 5 | #include <linux/ioport.h> |
6 | #include <linux/interrupt.h> | 6 | #include <linux/interrupt.h> |
7 | #include <linux/timex.h> | 7 | #include <linux/timex.h> |
8 | #include <linux/slab.h> | ||
9 | #include <linux/random.h> | 8 | #include <linux/random.h> |
10 | #include <linux/init.h> | 9 | #include <linux/init.h> |
11 | #include <linux/kernel_stat.h> | 10 | #include <linux/kernel_stat.h> |
@@ -32,8 +31,14 @@ | |||
32 | */ | 31 | */ |
33 | 32 | ||
34 | static int i8259A_auto_eoi; | 33 | static int i8259A_auto_eoi; |
35 | DEFINE_SPINLOCK(i8259A_lock); | 34 | DEFINE_RAW_SPINLOCK(i8259A_lock); |
36 | static void mask_and_ack_8259A(unsigned int); | 35 | static void mask_and_ack_8259A(unsigned int); |
36 | static void mask_8259A(void); | ||
37 | static void unmask_8259A(void); | ||
38 | static void disable_8259A_irq(unsigned int irq); | ||
39 | static void enable_8259A_irq(unsigned int irq); | ||
40 | static void init_8259A(int auto_eoi); | ||
41 | static int i8259A_irq_pending(unsigned int irq); | ||
37 | 42 | ||
38 | struct irq_chip i8259A_chip = { | 43 | struct irq_chip i8259A_chip = { |
39 | .name = "XT-PIC", | 44 | .name = "XT-PIC", |
@@ -63,51 +68,51 @@ unsigned int cached_irq_mask = 0xffff; | |||
63 | */ | 68 | */ |
64 | unsigned long io_apic_irqs; | 69 | unsigned long io_apic_irqs; |
65 | 70 | ||
66 | void disable_8259A_irq(unsigned int irq) | 71 | static void disable_8259A_irq(unsigned int irq) |
67 | { | 72 | { |
68 | unsigned int mask = 1 << irq; | 73 | unsigned int mask = 1 << irq; |
69 | unsigned long flags; | 74 | unsigned long flags; |
70 | 75 | ||
71 | spin_lock_irqsave(&i8259A_lock, flags); | 76 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
72 | cached_irq_mask |= mask; | 77 | cached_irq_mask |= mask; |
73 | if (irq & 8) | 78 | if (irq & 8) |
74 | outb(cached_slave_mask, PIC_SLAVE_IMR); | 79 | outb(cached_slave_mask, PIC_SLAVE_IMR); |
75 | else | 80 | else |
76 | outb(cached_master_mask, PIC_MASTER_IMR); | 81 | outb(cached_master_mask, PIC_MASTER_IMR); |
77 | spin_unlock_irqrestore(&i8259A_lock, flags); | 82 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
78 | } | 83 | } |
79 | 84 | ||
80 | void enable_8259A_irq(unsigned int irq) | 85 | static void enable_8259A_irq(unsigned int irq) |
81 | { | 86 | { |
82 | unsigned int mask = ~(1 << irq); | 87 | unsigned int mask = ~(1 << irq); |
83 | unsigned long flags; | 88 | unsigned long flags; |
84 | 89 | ||
85 | spin_lock_irqsave(&i8259A_lock, flags); | 90 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
86 | cached_irq_mask &= mask; | 91 | cached_irq_mask &= mask; |
87 | if (irq & 8) | 92 | if (irq & 8) |
88 | outb(cached_slave_mask, PIC_SLAVE_IMR); | 93 | outb(cached_slave_mask, PIC_SLAVE_IMR); |
89 | else | 94 | else |
90 | outb(cached_master_mask, PIC_MASTER_IMR); | 95 | outb(cached_master_mask, PIC_MASTER_IMR); |
91 | spin_unlock_irqrestore(&i8259A_lock, flags); | 96 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
92 | } | 97 | } |
93 | 98 | ||
94 | int i8259A_irq_pending(unsigned int irq) | 99 | static int i8259A_irq_pending(unsigned int irq) |
95 | { | 100 | { |
96 | unsigned int mask = 1<<irq; | 101 | unsigned int mask = 1<<irq; |
97 | unsigned long flags; | 102 | unsigned long flags; |
98 | int ret; | 103 | int ret; |
99 | 104 | ||
100 | spin_lock_irqsave(&i8259A_lock, flags); | 105 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
101 | if (irq < 8) | 106 | if (irq < 8) |
102 | ret = inb(PIC_MASTER_CMD) & mask; | 107 | ret = inb(PIC_MASTER_CMD) & mask; |
103 | else | 108 | else |
104 | ret = inb(PIC_SLAVE_CMD) & (mask >> 8); | 109 | ret = inb(PIC_SLAVE_CMD) & (mask >> 8); |
105 | spin_unlock_irqrestore(&i8259A_lock, flags); | 110 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
106 | 111 | ||
107 | return ret; | 112 | return ret; |
108 | } | 113 | } |
109 | 114 | ||
110 | void make_8259A_irq(unsigned int irq) | 115 | static void make_8259A_irq(unsigned int irq) |
111 | { | 116 | { |
112 | disable_irq_nosync(irq); | 117 | disable_irq_nosync(irq); |
113 | io_apic_irqs &= ~(1<<irq); | 118 | io_apic_irqs &= ~(1<<irq); |
@@ -150,7 +155,7 @@ static void mask_and_ack_8259A(unsigned int irq) | |||
150 | unsigned int irqmask = 1 << irq; | 155 | unsigned int irqmask = 1 << irq; |
151 | unsigned long flags; | 156 | unsigned long flags; |
152 | 157 | ||
153 | spin_lock_irqsave(&i8259A_lock, flags); | 158 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
154 | /* | 159 | /* |
155 | * Lightweight spurious IRQ detection. We do not want | 160 | * Lightweight spurious IRQ detection. We do not want |
156 | * to overdo spurious IRQ handling - it's usually a sign | 161 | * to overdo spurious IRQ handling - it's usually a sign |
@@ -183,7 +188,7 @@ handle_real_irq: | |||
183 | outb(cached_master_mask, PIC_MASTER_IMR); | 188 | outb(cached_master_mask, PIC_MASTER_IMR); |
184 | outb(0x60+irq, PIC_MASTER_CMD); /* 'Specific EOI to master */ | 189 | outb(0x60+irq, PIC_MASTER_CMD); /* 'Specific EOI to master */ |
185 | } | 190 | } |
186 | spin_unlock_irqrestore(&i8259A_lock, flags); | 191 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
187 | return; | 192 | return; |
188 | 193 | ||
189 | spurious_8259A_irq: | 194 | spurious_8259A_irq: |
@@ -281,37 +286,37 @@ static int __init i8259A_init_sysfs(void) | |||
281 | 286 | ||
282 | device_initcall(i8259A_init_sysfs); | 287 | device_initcall(i8259A_init_sysfs); |
283 | 288 | ||
284 | void mask_8259A(void) | 289 | static void mask_8259A(void) |
285 | { | 290 | { |
286 | unsigned long flags; | 291 | unsigned long flags; |
287 | 292 | ||
288 | spin_lock_irqsave(&i8259A_lock, flags); | 293 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
289 | 294 | ||
290 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ | 295 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ |
291 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ | 296 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ |
292 | 297 | ||
293 | spin_unlock_irqrestore(&i8259A_lock, flags); | 298 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
294 | } | 299 | } |
295 | 300 | ||
296 | void unmask_8259A(void) | 301 | static void unmask_8259A(void) |
297 | { | 302 | { |
298 | unsigned long flags; | 303 | unsigned long flags; |
299 | 304 | ||
300 | spin_lock_irqsave(&i8259A_lock, flags); | 305 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
301 | 306 | ||
302 | outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */ | 307 | outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */ |
303 | outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */ | 308 | outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */ |
304 | 309 | ||
305 | spin_unlock_irqrestore(&i8259A_lock, flags); | 310 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
306 | } | 311 | } |
307 | 312 | ||
308 | void init_8259A(int auto_eoi) | 313 | static void init_8259A(int auto_eoi) |
309 | { | 314 | { |
310 | unsigned long flags; | 315 | unsigned long flags; |
311 | 316 | ||
312 | i8259A_auto_eoi = auto_eoi; | 317 | i8259A_auto_eoi = auto_eoi; |
313 | 318 | ||
314 | spin_lock_irqsave(&i8259A_lock, flags); | 319 | raw_spin_lock_irqsave(&i8259A_lock, flags); |
315 | 320 | ||
316 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ | 321 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ |
317 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ | 322 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-2 */ |
@@ -356,5 +361,49 @@ void init_8259A(int auto_eoi) | |||
356 | outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */ | 361 | outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */ |
357 | outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */ | 362 | outb(cached_slave_mask, PIC_SLAVE_IMR); /* restore slave IRQ mask */ |
358 | 363 | ||
359 | spin_unlock_irqrestore(&i8259A_lock, flags); | 364 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
360 | } | 365 | } |
366 | |||
367 | /* | ||
368 | * make i8259 a driver so that we can select pic functions at run time. the goal | ||
369 | * is to make x86 binary compatible among pc compatible and non-pc compatible | ||
370 | * platforms, such as x86 MID. | ||
371 | */ | ||
372 | |||
373 | static void legacy_pic_noop(void) { }; | ||
374 | static void legacy_pic_uint_noop(unsigned int unused) { }; | ||
375 | static void legacy_pic_int_noop(int unused) { }; | ||
376 | |||
377 | static struct irq_chip dummy_pic_chip = { | ||
378 | .name = "dummy pic", | ||
379 | .mask = legacy_pic_uint_noop, | ||
380 | .unmask = legacy_pic_uint_noop, | ||
381 | .disable = legacy_pic_uint_noop, | ||
382 | .mask_ack = legacy_pic_uint_noop, | ||
383 | }; | ||
384 | static int legacy_pic_irq_pending_noop(unsigned int irq) | ||
385 | { | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | struct legacy_pic null_legacy_pic = { | ||
390 | .nr_legacy_irqs = 0, | ||
391 | .chip = &dummy_pic_chip, | ||
392 | .mask_all = legacy_pic_noop, | ||
393 | .restore_mask = legacy_pic_noop, | ||
394 | .init = legacy_pic_int_noop, | ||
395 | .irq_pending = legacy_pic_irq_pending_noop, | ||
396 | .make_irq = legacy_pic_uint_noop, | ||
397 | }; | ||
398 | |||
399 | struct legacy_pic default_legacy_pic = { | ||
400 | .nr_legacy_irqs = NR_IRQS_LEGACY, | ||
401 | .chip = &i8259A_chip, | ||
402 | .mask_all = mask_8259A, | ||
403 | .restore_mask = unmask_8259A, | ||
404 | .init = init_8259A, | ||
405 | .irq_pending = i8259A_irq_pending, | ||
406 | .make_irq = make_8259A_irq, | ||
407 | }; | ||
408 | |||
409 | struct legacy_pic *legacy_pic = &default_legacy_pic; | ||