aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/apic_32.c')
-rw-r--r--arch/x86/kernel/apic_32.c69
1 files changed, 39 insertions, 30 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;