diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /arch/x86/kernel/i8259.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'arch/x86/kernel/i8259.c')
-rw-r--r-- | arch/x86/kernel/i8259.c | 98 |
1 files changed, 43 insertions, 55 deletions
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c index cafa7c80ac95..65b8f5c2eebf 100644 --- a/arch/x86/kernel/i8259.c +++ b/arch/x86/kernel/i8259.c | |||
@@ -8,7 +8,7 @@ | |||
8 | #include <linux/random.h> | 8 | #include <linux/random.h> |
9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
10 | #include <linux/kernel_stat.h> | 10 | #include <linux/kernel_stat.h> |
11 | #include <linux/sysdev.h> | 11 | #include <linux/syscore_ops.h> |
12 | #include <linux/bitops.h> | 12 | #include <linux/bitops.h> |
13 | #include <linux/acpi.h> | 13 | #include <linux/acpi.h> |
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
@@ -29,24 +29,10 @@ | |||
29 | * plus some generic x86 specific things if generic specifics makes | 29 | * plus some generic x86 specific things if generic specifics makes |
30 | * any sense at all. | 30 | * any sense at all. |
31 | */ | 31 | */ |
32 | static void init_8259A(int auto_eoi); | ||
32 | 33 | ||
33 | static int i8259A_auto_eoi; | 34 | static int i8259A_auto_eoi; |
34 | DEFINE_RAW_SPINLOCK(i8259A_lock); | 35 | DEFINE_RAW_SPINLOCK(i8259A_lock); |
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); | ||
42 | |||
43 | struct irq_chip i8259A_chip = { | ||
44 | .name = "XT-PIC", | ||
45 | .mask = disable_8259A_irq, | ||
46 | .disable = disable_8259A_irq, | ||
47 | .unmask = enable_8259A_irq, | ||
48 | .mask_ack = mask_and_ack_8259A, | ||
49 | }; | ||
50 | 36 | ||
51 | /* | 37 | /* |
52 | * 8259A PIC functions to handle ISA devices: | 38 | * 8259A PIC functions to handle ISA devices: |
@@ -68,7 +54,7 @@ unsigned int cached_irq_mask = 0xffff; | |||
68 | */ | 54 | */ |
69 | unsigned long io_apic_irqs; | 55 | unsigned long io_apic_irqs; |
70 | 56 | ||
71 | static void disable_8259A_irq(unsigned int irq) | 57 | static void mask_8259A_irq(unsigned int irq) |
72 | { | 58 | { |
73 | unsigned int mask = 1 << irq; | 59 | unsigned int mask = 1 << irq; |
74 | unsigned long flags; | 60 | unsigned long flags; |
@@ -82,7 +68,12 @@ static void disable_8259A_irq(unsigned int irq) | |||
82 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); | 68 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
83 | } | 69 | } |
84 | 70 | ||
85 | static void enable_8259A_irq(unsigned int irq) | 71 | static void disable_8259A_irq(struct irq_data *data) |
72 | { | ||
73 | mask_8259A_irq(data->irq); | ||
74 | } | ||
75 | |||
76 | static void unmask_8259A_irq(unsigned int irq) | ||
86 | { | 77 | { |
87 | unsigned int mask = ~(1 << irq); | 78 | unsigned int mask = ~(1 << irq); |
88 | unsigned long flags; | 79 | unsigned long flags; |
@@ -96,6 +87,11 @@ static void enable_8259A_irq(unsigned int irq) | |||
96 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); | 87 | raw_spin_unlock_irqrestore(&i8259A_lock, flags); |
97 | } | 88 | } |
98 | 89 | ||
90 | static void enable_8259A_irq(struct irq_data *data) | ||
91 | { | ||
92 | unmask_8259A_irq(data->irq); | ||
93 | } | ||
94 | |||
99 | static int i8259A_irq_pending(unsigned int irq) | 95 | static int i8259A_irq_pending(unsigned int irq) |
100 | { | 96 | { |
101 | unsigned int mask = 1<<irq; | 97 | unsigned int mask = 1<<irq; |
@@ -116,8 +112,8 @@ static void make_8259A_irq(unsigned int irq) | |||
116 | { | 112 | { |
117 | disable_irq_nosync(irq); | 113 | disable_irq_nosync(irq); |
118 | io_apic_irqs &= ~(1<<irq); | 114 | io_apic_irqs &= ~(1<<irq); |
119 | set_irq_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq, | 115 | irq_set_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq, |
120 | "XT"); | 116 | i8259A_chip.name); |
121 | enable_irq(irq); | 117 | enable_irq(irq); |
122 | } | 118 | } |
123 | 119 | ||
@@ -150,8 +146,9 @@ static inline int i8259A_irq_real(unsigned int irq) | |||
150 | * first, _then_ send the EOI, and the order of EOI | 146 | * first, _then_ send the EOI, and the order of EOI |
151 | * to the two 8259s is important! | 147 | * to the two 8259s is important! |
152 | */ | 148 | */ |
153 | static void mask_and_ack_8259A(unsigned int irq) | 149 | static void mask_and_ack_8259A(struct irq_data *data) |
154 | { | 150 | { |
151 | unsigned int irq = data->irq; | ||
155 | unsigned int irqmask = 1 << irq; | 152 | unsigned int irqmask = 1 << irq; |
156 | unsigned long flags; | 153 | unsigned long flags; |
157 | 154 | ||
@@ -223,6 +220,14 @@ spurious_8259A_irq: | |||
223 | } | 220 | } |
224 | } | 221 | } |
225 | 222 | ||
223 | struct irq_chip i8259A_chip = { | ||
224 | .name = "XT-PIC", | ||
225 | .irq_mask = disable_8259A_irq, | ||
226 | .irq_disable = disable_8259A_irq, | ||
227 | .irq_unmask = enable_8259A_irq, | ||
228 | .irq_mask_ack = mask_and_ack_8259A, | ||
229 | }; | ||
230 | |||
226 | static char irq_trigger[2]; | 231 | static char irq_trigger[2]; |
227 | /** | 232 | /** |
228 | * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ | 233 | * ELCR registers (0x4d0, 0x4d1) control edge/level of IRQ |
@@ -240,20 +245,19 @@ static void save_ELCR(char *trigger) | |||
240 | trigger[1] = inb(0x4d1) & 0xDE; | 245 | trigger[1] = inb(0x4d1) & 0xDE; |
241 | } | 246 | } |
242 | 247 | ||
243 | static int i8259A_resume(struct sys_device *dev) | 248 | static void i8259A_resume(void) |
244 | { | 249 | { |
245 | init_8259A(i8259A_auto_eoi); | 250 | init_8259A(i8259A_auto_eoi); |
246 | restore_ELCR(irq_trigger); | 251 | restore_ELCR(irq_trigger); |
247 | return 0; | ||
248 | } | 252 | } |
249 | 253 | ||
250 | static int i8259A_suspend(struct sys_device *dev, pm_message_t state) | 254 | static int i8259A_suspend(void) |
251 | { | 255 | { |
252 | save_ELCR(irq_trigger); | 256 | save_ELCR(irq_trigger); |
253 | return 0; | 257 | return 0; |
254 | } | 258 | } |
255 | 259 | ||
256 | static int i8259A_shutdown(struct sys_device *dev) | 260 | static void i8259A_shutdown(void) |
257 | { | 261 | { |
258 | /* Put the i8259A into a quiescent state that | 262 | /* Put the i8259A into a quiescent state that |
259 | * the kernel initialization code can get it | 263 | * the kernel initialization code can get it |
@@ -261,21 +265,14 @@ static int i8259A_shutdown(struct sys_device *dev) | |||
261 | */ | 265 | */ |
262 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ | 266 | outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */ |
263 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-1 */ | 267 | outb(0xff, PIC_SLAVE_IMR); /* mask all of 8259A-1 */ |
264 | return 0; | ||
265 | } | 268 | } |
266 | 269 | ||
267 | static struct sysdev_class i8259_sysdev_class = { | 270 | static struct syscore_ops i8259_syscore_ops = { |
268 | .name = "i8259", | ||
269 | .suspend = i8259A_suspend, | 271 | .suspend = i8259A_suspend, |
270 | .resume = i8259A_resume, | 272 | .resume = i8259A_resume, |
271 | .shutdown = i8259A_shutdown, | 273 | .shutdown = i8259A_shutdown, |
272 | }; | 274 | }; |
273 | 275 | ||
274 | static struct sys_device device_i8259A = { | ||
275 | .id = 0, | ||
276 | .cls = &i8259_sysdev_class, | ||
277 | }; | ||
278 | |||
279 | static void mask_8259A(void) | 276 | static void mask_8259A(void) |
280 | { | 277 | { |
281 | unsigned long flags; | 278 | unsigned long flags; |
@@ -342,9 +339,9 @@ static void init_8259A(int auto_eoi) | |||
342 | * In AEOI mode we just have to mask the interrupt | 339 | * In AEOI mode we just have to mask the interrupt |
343 | * when acking. | 340 | * when acking. |
344 | */ | 341 | */ |
345 | i8259A_chip.mask_ack = disable_8259A_irq; | 342 | i8259A_chip.irq_mask_ack = disable_8259A_irq; |
346 | else | 343 | else |
347 | i8259A_chip.mask_ack = mask_and_ack_8259A; | 344 | i8259A_chip.irq_mask_ack = mask_and_ack_8259A; |
348 | 345 | ||
349 | udelay(100); /* wait for 8259A to initialize */ | 346 | udelay(100); /* wait for 8259A to initialize */ |
350 | 347 | ||
@@ -363,14 +360,6 @@ static void init_8259A(int auto_eoi) | |||
363 | static void legacy_pic_noop(void) { }; | 360 | static void legacy_pic_noop(void) { }; |
364 | static void legacy_pic_uint_noop(unsigned int unused) { }; | 361 | static void legacy_pic_uint_noop(unsigned int unused) { }; |
365 | static void legacy_pic_int_noop(int unused) { }; | 362 | static void legacy_pic_int_noop(int unused) { }; |
366 | |||
367 | static struct irq_chip dummy_pic_chip = { | ||
368 | .name = "dummy pic", | ||
369 | .mask = legacy_pic_uint_noop, | ||
370 | .unmask = legacy_pic_uint_noop, | ||
371 | .disable = legacy_pic_uint_noop, | ||
372 | .mask_ack = legacy_pic_uint_noop, | ||
373 | }; | ||
374 | static int legacy_pic_irq_pending_noop(unsigned int irq) | 363 | static int legacy_pic_irq_pending_noop(unsigned int irq) |
375 | { | 364 | { |
376 | return 0; | 365 | return 0; |
@@ -378,7 +367,9 @@ static int legacy_pic_irq_pending_noop(unsigned int irq) | |||
378 | 367 | ||
379 | struct legacy_pic null_legacy_pic = { | 368 | struct legacy_pic null_legacy_pic = { |
380 | .nr_legacy_irqs = 0, | 369 | .nr_legacy_irqs = 0, |
381 | .chip = &dummy_pic_chip, | 370 | .chip = &dummy_irq_chip, |
371 | .mask = legacy_pic_uint_noop, | ||
372 | .unmask = legacy_pic_uint_noop, | ||
382 | .mask_all = legacy_pic_noop, | 373 | .mask_all = legacy_pic_noop, |
383 | .restore_mask = legacy_pic_noop, | 374 | .restore_mask = legacy_pic_noop, |
384 | .init = legacy_pic_int_noop, | 375 | .init = legacy_pic_int_noop, |
@@ -389,7 +380,9 @@ struct legacy_pic null_legacy_pic = { | |||
389 | struct legacy_pic default_legacy_pic = { | 380 | struct legacy_pic default_legacy_pic = { |
390 | .nr_legacy_irqs = NR_IRQS_LEGACY, | 381 | .nr_legacy_irqs = NR_IRQS_LEGACY, |
391 | .chip = &i8259A_chip, | 382 | .chip = &i8259A_chip, |
392 | .mask_all = mask_8259A, | 383 | .mask = mask_8259A_irq, |
384 | .unmask = unmask_8259A_irq, | ||
385 | .mask_all = mask_8259A, | ||
393 | .restore_mask = unmask_8259A, | 386 | .restore_mask = unmask_8259A, |
394 | .init = init_8259A, | 387 | .init = init_8259A, |
395 | .irq_pending = i8259A_irq_pending, | 388 | .irq_pending = i8259A_irq_pending, |
@@ -398,17 +391,12 @@ struct legacy_pic default_legacy_pic = { | |||
398 | 391 | ||
399 | struct legacy_pic *legacy_pic = &default_legacy_pic; | 392 | struct legacy_pic *legacy_pic = &default_legacy_pic; |
400 | 393 | ||
401 | static int __init i8259A_init_sysfs(void) | 394 | static int __init i8259A_init_ops(void) |
402 | { | 395 | { |
403 | int error; | 396 | if (legacy_pic == &default_legacy_pic) |
404 | 397 | register_syscore_ops(&i8259_syscore_ops); | |
405 | if (legacy_pic != &default_legacy_pic) | ||
406 | return 0; | ||
407 | 398 | ||
408 | error = sysdev_class_register(&i8259_sysdev_class); | 399 | return 0; |
409 | if (!error) | ||
410 | error = sysdev_register(&device_i8259A); | ||
411 | return error; | ||
412 | } | 400 | } |
413 | 401 | ||
414 | device_initcall(i8259A_init_sysfs); | 402 | device_initcall(i8259A_init_ops); |