aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCyrill Gorcunov <gorcunov@gmail.com>2008-08-16 15:21:53 -0400
committerIngo Molnar <mingo@elte.hu>2008-08-17 08:41:49 -0400
commit274cfe5912eebe9d4e1a4c451fe617289a181fcf (patch)
tree27c9a5c5cfd0d2ddf2c062168a0c9cbf25b35f53
parent24968cfdd4c3cf61338495dd0f9bb8a6907d2087 (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.c69
-rw-r--r--arch/x86/kernel/apic_64.c48
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 */
255static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) 258static 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
295static 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
303u8 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
309u8 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 */
285static int lapic_next_event(unsigned long delta, 318static 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
693static 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
700u8 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
706u8 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
1544static struct { 1548static 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,
81static void lapic_timer_broadcast(cpumask_t mask); 81static void lapic_timer_broadcast(cpumask_t mask);
82static void apic_pm_activate(void); 82static void apic_pm_activate(void);
83 83
84/*
85 * The local apic timer can be used for any function which is CPU local.
86 */
84static struct clock_event_device lapic_clockevent = { 87static 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 */
130void xapic_wait_icr_idle(void) 138void 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
177struct apic_ops __read_mostly *apic_ops = &xapic_ops; 185struct apic_ops __read_mostly *apic_ops = &xapic_ops;
178
179EXPORT_SYMBOL_GPL(apic_ops); 186EXPORT_SYMBOL_GPL(apic_ops);
180 187
181static void x2apic_wait_icr_idle(void) 188static 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
261static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen) 271static 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)
474void __init setup_boot_APIC_clock(void) 484void __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 */
1251void disconnect_bsp_APIC(int virt_wire_setup) 1272void 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
1349static struct { 1370static 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
1461static struct sysdev_class lapic_sysclass = { 1489static struct sysdev_class lapic_sysclass = {
1462 .name = "lapic", 1490 .name = "lapic",
1463 .resume = lapic_resume, 1491 .resume = lapic_resume,