diff options
author | Cyrill Gorcunov <gorcunov@gmail.com> | 2008-08-16 15:21:53 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-08-17 08:41:49 -0400 |
commit | 274cfe5912eebe9d4e1a4c451fe617289a181fcf (patch) | |
tree | 27c9a5c5cfd0d2ddf2c062168a0c9cbf25b35f53 | |
parent | 24968cfdd4c3cf61338495dd0f9bb8a6907d2087 (diff) |
x86: apic - rearrange functions and comments
Rearrange functions and comments to find differences
easier.
Also use apic_printk in setup_boot_APIC_clock for
64bit mode.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/kernel/apic_32.c | 69 | ||||
-rw-r--r-- | arch/x86/kernel/apic_64.c | 48 |
2 files changed, 77 insertions, 40 deletions
diff --git a/arch/x86/kernel/apic_32.c b/arch/x86/kernel/apic_32.c index 6cb8aaaf10f5..9e8702eebd46 100644 --- a/arch/x86/kernel/apic_32.c +++ b/arch/x86/kernel/apic_32.c | |||
@@ -251,6 +251,9 @@ int lapic_get_maxlvt(void) | |||
251 | * this function twice on the boot CPU, once with a bogus timeout | 251 | * this function twice on the boot CPU, once with a bogus timeout |
252 | * value, second time for real. The other (noncalibrating) CPUs | 252 | * value, second time for real. The other (noncalibrating) CPUs |
253 | * call this function only once, with the real, calibrated value. | 253 | * call this function only once, with the real, calibrated value. |
254 | * | ||
255 | * We do reads before writes even if unnecessary, to get around the | ||
256 | * P5 APIC double write bug. | ||
254 | */ | 257 | */ |
255 | static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) | 258 | static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) |
256 | { | 259 | { |
@@ -280,6 +283,36 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) | |||
280 | } | 283 | } |
281 | 284 | ||
282 | /* | 285 | /* |
286 | * Setup extended LVT, AMD specific (K8, family 10h) | ||
287 | * | ||
288 | * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and | ||
289 | * MCE interrupts are supported. Thus MCE offset must be set to 0. | ||
290 | */ | ||
291 | |||
292 | #define APIC_EILVT_LVTOFF_MCE 0 | ||
293 | #define APIC_EILVT_LVTOFF_IBS 1 | ||
294 | |||
295 | static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask) | ||
296 | { | ||
297 | unsigned long reg = (lvt_off << 4) + APIC_EILVT0; | ||
298 | unsigned int v = (mask << 16) | (msg_type << 8) | vector; | ||
299 | |||
300 | apic_write(reg, v); | ||
301 | } | ||
302 | |||
303 | u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask) | ||
304 | { | ||
305 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask); | ||
306 | return APIC_EILVT_LVTOFF_MCE; | ||
307 | } | ||
308 | |||
309 | u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) | ||
310 | { | ||
311 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); | ||
312 | return APIC_EILVT_LVTOFF_IBS; | ||
313 | } | ||
314 | |||
315 | /* | ||
283 | * Program the next event, relative to now | 316 | * Program the next event, relative to now |
284 | */ | 317 | */ |
285 | static int lapic_next_event(unsigned long delta, | 318 | static int lapic_next_event(unsigned long delta, |
@@ -298,7 +331,7 @@ static void lapic_timer_setup(enum clock_event_mode mode, | |||
298 | unsigned long flags; | 331 | unsigned long flags; |
299 | unsigned int v; | 332 | unsigned int v; |
300 | 333 | ||
301 | /* Lapic used for broadcast ? */ | 334 | /* Lapic used as dummy for broadcast ? */ |
302 | if (evt->features & CLOCK_EVT_FEAT_DUMMY) | 335 | if (evt->features & CLOCK_EVT_FEAT_DUMMY) |
303 | return; | 336 | return; |
304 | 337 | ||
@@ -681,35 +714,6 @@ int setup_profiling_timer(unsigned int multiplier) | |||
681 | } | 714 | } |
682 | 715 | ||
683 | /* | 716 | /* |
684 | * Setup extended LVT, AMD specific (K8, family 10h) | ||
685 | * | ||
686 | * Vector mappings are hard coded. On K8 only offset 0 (APIC500) and | ||
687 | * MCE interrupts are supported. Thus MCE offset must be set to 0. | ||
688 | */ | ||
689 | |||
690 | #define APIC_EILVT_LVTOFF_MCE 0 | ||
691 | #define APIC_EILVT_LVTOFF_IBS 1 | ||
692 | |||
693 | static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask) | ||
694 | { | ||
695 | unsigned long reg = (lvt_off << 4) + APIC_EILVT0; | ||
696 | unsigned int v = (mask << 16) | (msg_type << 8) | vector; | ||
697 | apic_write(reg, v); | ||
698 | } | ||
699 | |||
700 | u8 setup_APIC_eilvt_mce(u8 vector, u8 msg_type, u8 mask) | ||
701 | { | ||
702 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_MCE, vector, msg_type, mask); | ||
703 | return APIC_EILVT_LVTOFF_MCE; | ||
704 | } | ||
705 | |||
706 | u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask) | ||
707 | { | ||
708 | setup_APIC_eilvt(APIC_EILVT_LVTOFF_IBS, vector, msg_type, mask); | ||
709 | return APIC_EILVT_LVTOFF_IBS; | ||
710 | } | ||
711 | |||
712 | /* | ||
713 | * Local APIC start and shutdown | 717 | * Local APIC start and shutdown |
714 | */ | 718 | */ |
715 | 719 | ||
@@ -1542,6 +1546,11 @@ void __cpuinit generic_processor_info(int apicid, int version) | |||
1542 | #ifdef CONFIG_PM | 1546 | #ifdef CONFIG_PM |
1543 | 1547 | ||
1544 | static struct { | 1548 | static struct { |
1549 | /* | ||
1550 | * 'active' is true if the local APIC was enabled by us and | ||
1551 | * not the BIOS; this signifies that we are also responsible | ||
1552 | * for disabling it before entering apm/acpi suspend | ||
1553 | */ | ||
1545 | int active; | 1554 | int active; |
1546 | /* r/w apic fields */ | 1555 | /* r/w apic fields */ |
1547 | unsigned int apic_id; | 1556 | unsigned int apic_id; |
diff --git a/arch/x86/kernel/apic_64.c b/arch/x86/kernel/apic_64.c index 13dea935b4eb..46523c0cc6f6 100644 --- a/arch/x86/kernel/apic_64.c +++ b/arch/x86/kernel/apic_64.c | |||
@@ -81,6 +81,9 @@ static void lapic_timer_setup(enum clock_event_mode mode, | |||
81 | static void lapic_timer_broadcast(cpumask_t mask); | 81 | static void lapic_timer_broadcast(cpumask_t mask); |
82 | static void apic_pm_activate(void); | 82 | static void apic_pm_activate(void); |
83 | 83 | ||
84 | /* | ||
85 | * The local apic timer can be used for any function which is CPU local. | ||
86 | */ | ||
84 | static struct clock_event_device lapic_clockevent = { | 87 | static struct clock_event_device lapic_clockevent = { |
85 | .name = "lapic", | 88 | .name = "lapic", |
86 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | 89 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT |
@@ -127,6 +130,11 @@ static int modern_apic(void) | |||
127 | return lapic_get_version() >= 0x14; | 130 | return lapic_get_version() >= 0x14; |
128 | } | 131 | } |
129 | 132 | ||
133 | /* | ||
134 | * Paravirt kernels also might be using these below ops. So we still | ||
135 | * use generic apic_read()/apic_write(), which might be pointing to different | ||
136 | * ops in PARAVIRT case. | ||
137 | */ | ||
130 | void xapic_wait_icr_idle(void) | 138 | void xapic_wait_icr_idle(void) |
131 | { | 139 | { |
132 | while (apic_read(APIC_ICR) & APIC_ICR_BUSY) | 140 | while (apic_read(APIC_ICR) & APIC_ICR_BUSY) |
@@ -175,7 +183,6 @@ static struct apic_ops xapic_ops = { | |||
175 | }; | 183 | }; |
176 | 184 | ||
177 | struct apic_ops __read_mostly *apic_ops = &xapic_ops; | 185 | struct apic_ops __read_mostly *apic_ops = &xapic_ops; |
178 | |||
179 | EXPORT_SYMBOL_GPL(apic_ops); | 186 | EXPORT_SYMBOL_GPL(apic_ops); |
180 | 187 | ||
181 | static void x2apic_wait_icr_idle(void) | 188 | static void x2apic_wait_icr_idle(void) |
@@ -244,6 +251,10 @@ int lapic_get_maxlvt(void) | |||
244 | return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2; | 251 | return APIC_INTEGRATED(GET_APIC_VERSION(v)) ? GET_APIC_MAXLVT(v) : 2; |
245 | } | 252 | } |
246 | 253 | ||
254 | /* | ||
255 | * Local APIC timer | ||
256 | */ | ||
257 | |||
247 | /* Clock divisor is set to 1 */ | 258 | /* Clock divisor is set to 1 */ |
248 | #define APIC_DIVISOR 1 | 259 | #define APIC_DIVISOR 1 |
249 | 260 | ||
@@ -257,7 +268,6 @@ int lapic_get_maxlvt(void) | |||
257 | * We do reads before writes even if unnecessary, to get around the | 268 | * We do reads before writes even if unnecessary, to get around the |
258 | * P5 APIC double write bug. | 269 | * P5 APIC double write bug. |
259 | */ | 270 | */ |
260 | |||
261 | static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) | 271 | static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) |
262 | { | 272 | { |
263 | unsigned int lvtt_value, tmp_value; | 273 | unsigned int lvtt_value, tmp_value; |
@@ -474,10 +484,10 @@ static int __init calibrate_APIC_clock(void) | |||
474 | void __init setup_boot_APIC_clock(void) | 484 | void __init setup_boot_APIC_clock(void) |
475 | { | 485 | { |
476 | /* | 486 | /* |
477 | * The local apic timer can be disabled via the kernel commandline. | 487 | * The local apic timer can be disabled via the kernel |
478 | * Register the lapic timer as a dummy clock event source on SMP | 488 | * commandline or from the CPU detection code. Register the lapic |
479 | * systems, so the broadcast mechanism is used. On UP systems simply | 489 | * timer as a dummy clock event source on SMP systems, so the |
480 | * ignore it. | 490 | * broadcast mechanism is used. On UP systems simply ignore it. |
481 | */ | 491 | */ |
482 | if (disable_apic_timer) { | 492 | if (disable_apic_timer) { |
483 | printk(KERN_INFO "Disabling APIC timer\n"); | 493 | printk(KERN_INFO "Disabling APIC timer\n"); |
@@ -489,7 +499,9 @@ void __init setup_boot_APIC_clock(void) | |||
489 | return; | 499 | return; |
490 | } | 500 | } |
491 | 501 | ||
492 | printk(KERN_INFO "Using local APIC timer interrupts.\n"); | 502 | apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n" |
503 | "calibrating APIC timer ...\n"); | ||
504 | |||
493 | if (calibrate_APIC_clock()) { | 505 | if (calibrate_APIC_clock()) { |
494 | /* No broadcast on UP ! */ | 506 | /* No broadcast on UP ! */ |
495 | if (num_possible_cpus() > 1) | 507 | if (num_possible_cpus() > 1) |
@@ -508,6 +520,7 @@ void __init setup_boot_APIC_clock(void) | |||
508 | printk(KERN_WARNING "APIC timer registered as dummy," | 520 | printk(KERN_WARNING "APIC timer registered as dummy," |
509 | " due to nmi_watchdog=%d!\n", nmi_watchdog); | 521 | " due to nmi_watchdog=%d!\n", nmi_watchdog); |
510 | 522 | ||
523 | /* Setup the lapic or request the broadcast */ | ||
511 | setup_APIC_timer(); | 524 | setup_APIC_timer(); |
512 | } | 525 | } |
513 | 526 | ||
@@ -577,6 +590,7 @@ void smp_apic_timer_interrupt(struct pt_regs *regs) | |||
577 | irq_enter(); | 590 | irq_enter(); |
578 | local_apic_timer_interrupt(); | 591 | local_apic_timer_interrupt(); |
579 | irq_exit(); | 592 | irq_exit(); |
593 | |||
580 | set_irq_regs(old_regs); | 594 | set_irq_regs(old_regs); |
581 | } | 595 | } |
582 | 596 | ||
@@ -1248,6 +1262,13 @@ void __init connect_bsp_APIC(void) | |||
1248 | enable_apic_mode(); | 1262 | enable_apic_mode(); |
1249 | } | 1263 | } |
1250 | 1264 | ||
1265 | /** | ||
1266 | * disconnect_bsp_APIC - detach the APIC from the interrupt system | ||
1267 | * @virt_wire_setup: indicates, whether virtual wire mode is selected | ||
1268 | * | ||
1269 | * Virtual wire mode is necessary to deliver legacy interrupts even when the | ||
1270 | * APIC is disabled. | ||
1271 | */ | ||
1251 | void disconnect_bsp_APIC(int virt_wire_setup) | 1272 | void disconnect_bsp_APIC(int virt_wire_setup) |
1252 | { | 1273 | { |
1253 | /* Go back to Virtual Wire compatibility mode */ | 1274 | /* Go back to Virtual Wire compatibility mode */ |
@@ -1347,9 +1368,11 @@ int hard_smp_processor_id(void) | |||
1347 | #ifdef CONFIG_PM | 1368 | #ifdef CONFIG_PM |
1348 | 1369 | ||
1349 | static struct { | 1370 | static struct { |
1350 | /* 'active' is true if the local APIC was enabled by us and | 1371 | /* |
1351 | not the BIOS; this signifies that we are also responsible | 1372 | * 'active' is true if the local APIC was enabled by us and |
1352 | for disabling it before entering apm/acpi suspend */ | 1373 | * not the BIOS; this signifies that we are also responsible |
1374 | * for disabling it before entering apm/acpi suspend | ||
1375 | */ | ||
1353 | int active; | 1376 | int active; |
1354 | /* r/w apic fields */ | 1377 | /* r/w apic fields */ |
1355 | unsigned int apic_id; | 1378 | unsigned int apic_id; |
@@ -1458,6 +1481,11 @@ static int lapic_resume(struct sys_device *dev) | |||
1458 | return 0; | 1481 | return 0; |
1459 | } | 1482 | } |
1460 | 1483 | ||
1484 | /* | ||
1485 | * This device has no shutdown method - fully functioning local APICs | ||
1486 | * are needed on every CPU up until machine_halt/restart/poweroff. | ||
1487 | */ | ||
1488 | |||
1461 | static struct sysdev_class lapic_sysclass = { | 1489 | static struct sysdev_class lapic_sysclass = { |
1462 | .name = "lapic", | 1490 | .name = "lapic", |
1463 | .resume = lapic_resume, | 1491 | .resume = lapic_resume, |