aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/apic/apic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/apic/apic.c')
-rw-r--r--arch/x86/kernel/apic/apic.c66
1 files changed, 42 insertions, 24 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 52fa56399a50..f98d84caf94c 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -186,7 +186,7 @@ static struct resource lapic_resource = {
186 .flags = IORESOURCE_MEM | IORESOURCE_BUSY, 186 .flags = IORESOURCE_MEM | IORESOURCE_BUSY,
187}; 187};
188 188
189static unsigned int calibration_result; 189unsigned int lapic_timer_frequency = 0;
190 190
191static void apic_pm_activate(void); 191static void apic_pm_activate(void);
192 192
@@ -454,7 +454,7 @@ static void lapic_timer_setup(enum clock_event_mode mode,
454 switch (mode) { 454 switch (mode) {
455 case CLOCK_EVT_MODE_PERIODIC: 455 case CLOCK_EVT_MODE_PERIODIC:
456 case CLOCK_EVT_MODE_ONESHOT: 456 case CLOCK_EVT_MODE_ONESHOT:
457 __setup_APIC_LVTT(calibration_result, 457 __setup_APIC_LVTT(lapic_timer_frequency,
458 mode != CLOCK_EVT_MODE_PERIODIC, 1); 458 mode != CLOCK_EVT_MODE_PERIODIC, 1);
459 break; 459 break;
460 case CLOCK_EVT_MODE_UNUSED: 460 case CLOCK_EVT_MODE_UNUSED:
@@ -638,6 +638,25 @@ static int __init calibrate_APIC_clock(void)
638 long delta, deltatsc; 638 long delta, deltatsc;
639 int pm_referenced = 0; 639 int pm_referenced = 0;
640 640
641 /**
642 * check if lapic timer has already been calibrated by platform
643 * specific routine, such as tsc calibration code. if so, we just fill
644 * in the clockevent structure and return.
645 */
646
647 if (lapic_timer_frequency) {
648 apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
649 lapic_timer_frequency);
650 lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR,
651 TICK_NSEC, lapic_clockevent.shift);
652 lapic_clockevent.max_delta_ns =
653 clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
654 lapic_clockevent.min_delta_ns =
655 clockevent_delta2ns(0xF, &lapic_clockevent);
656 lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
657 return 0;
658 }
659
641 local_irq_disable(); 660 local_irq_disable();
642 661
643 /* Replace the global interrupt handler */ 662 /* Replace the global interrupt handler */
@@ -679,12 +698,12 @@ static int __init calibrate_APIC_clock(void)
679 lapic_clockevent.min_delta_ns = 698 lapic_clockevent.min_delta_ns =
680 clockevent_delta2ns(0xF, &lapic_clockevent); 699 clockevent_delta2ns(0xF, &lapic_clockevent);
681 700
682 calibration_result = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS; 701 lapic_timer_frequency = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
683 702
684 apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta); 703 apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta);
685 apic_printk(APIC_VERBOSE, "..... mult: %u\n", lapic_clockevent.mult); 704 apic_printk(APIC_VERBOSE, "..... mult: %u\n", lapic_clockevent.mult);
686 apic_printk(APIC_VERBOSE, "..... calibration result: %u\n", 705 apic_printk(APIC_VERBOSE, "..... calibration result: %u\n",
687 calibration_result); 706 lapic_timer_frequency);
688 707
689 if (cpu_has_tsc) { 708 if (cpu_has_tsc) {
690 apic_printk(APIC_VERBOSE, "..... CPU clock speed is " 709 apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
@@ -695,13 +714,13 @@ static int __init calibrate_APIC_clock(void)
695 714
696 apic_printk(APIC_VERBOSE, "..... host bus clock speed is " 715 apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
697 "%u.%04u MHz.\n", 716 "%u.%04u MHz.\n",
698 calibration_result / (1000000 / HZ), 717 lapic_timer_frequency / (1000000 / HZ),
699 calibration_result % (1000000 / HZ)); 718 lapic_timer_frequency % (1000000 / HZ));
700 719
701 /* 720 /*
702 * Do a sanity check on the APIC calibration result 721 * Do a sanity check on the APIC calibration result
703 */ 722 */
704 if (calibration_result < (1000000 / HZ)) { 723 if (lapic_timer_frequency < (1000000 / HZ)) {
705 local_irq_enable(); 724 local_irq_enable();
706 pr_warning("APIC frequency too slow, disabling apic timer\n"); 725 pr_warning("APIC frequency too slow, disabling apic timer\n");
707 return -1; 726 return -1;
@@ -1437,27 +1456,21 @@ void enable_x2apic(void)
1437 1456
1438int __init enable_IR(void) 1457int __init enable_IR(void)
1439{ 1458{
1440#ifdef CONFIG_INTR_REMAP 1459#ifdef CONFIG_IRQ_REMAP
1441 if (!intr_remapping_supported()) { 1460 if (!intr_remapping_supported()) {
1442 pr_debug("intr-remapping not supported\n"); 1461 pr_debug("intr-remapping not supported\n");
1443 return 0; 1462 return -1;
1444 } 1463 }
1445 1464
1446 if (!x2apic_preenabled && skip_ioapic_setup) { 1465 if (!x2apic_preenabled && skip_ioapic_setup) {
1447 pr_info("Skipped enabling intr-remap because of skipping " 1466 pr_info("Skipped enabling intr-remap because of skipping "
1448 "io-apic setup\n"); 1467 "io-apic setup\n");
1449 return 0; 1468 return -1;
1450 } 1469 }
1451 1470
1452 if (enable_intr_remapping(x2apic_supported())) 1471 return enable_intr_remapping();
1453 return 0;
1454
1455 pr_info("Enabled Interrupt-remapping\n");
1456
1457 return 1;
1458
1459#endif 1472#endif
1460 return 0; 1473 return -1;
1461} 1474}
1462 1475
1463void __init enable_IR_x2apic(void) 1476void __init enable_IR_x2apic(void)
@@ -1481,11 +1494,11 @@ void __init enable_IR_x2apic(void)
1481 mask_ioapic_entries(); 1494 mask_ioapic_entries();
1482 1495
1483 if (dmar_table_init_ret) 1496 if (dmar_table_init_ret)
1484 ret = 0; 1497 ret = -1;
1485 else 1498 else
1486 ret = enable_IR(); 1499 ret = enable_IR();
1487 1500
1488 if (!ret) { 1501 if (ret < 0) {
1489 /* IR is required if there is APIC ID > 255 even when running 1502 /* IR is required if there is APIC ID > 255 even when running
1490 * under KVM 1503 * under KVM
1491 */ 1504 */
@@ -1499,6 +1512,9 @@ void __init enable_IR_x2apic(void)
1499 x2apic_force_phys(); 1512 x2apic_force_phys();
1500 } 1513 }
1501 1514
1515 if (ret == IRQ_REMAP_XAPIC_MODE)
1516 goto nox2apic;
1517
1502 x2apic_enabled = 1; 1518 x2apic_enabled = 1;
1503 1519
1504 if (x2apic_supported() && !x2apic_mode) { 1520 if (x2apic_supported() && !x2apic_mode) {
@@ -1508,19 +1524,21 @@ void __init enable_IR_x2apic(void)
1508 } 1524 }
1509 1525
1510nox2apic: 1526nox2apic:
1511 if (!ret) /* IR enabling failed */ 1527 if (ret < 0) /* IR enabling failed */
1512 restore_ioapic_entries(); 1528 restore_ioapic_entries();
1513 legacy_pic->restore_mask(); 1529 legacy_pic->restore_mask();
1514 local_irq_restore(flags); 1530 local_irq_restore(flags);
1515 1531
1516out: 1532out:
1517 if (x2apic_enabled) 1533 if (x2apic_enabled || !x2apic_supported())
1518 return; 1534 return;
1519 1535
1520 if (x2apic_preenabled) 1536 if (x2apic_preenabled)
1521 panic("x2apic: enabled by BIOS but kernel init failed."); 1537 panic("x2apic: enabled by BIOS but kernel init failed.");
1522 else if (cpu_has_x2apic) 1538 else if (ret == IRQ_REMAP_XAPIC_MODE)
1523 pr_info("Not enabling x2apic, Intr-remapping init failed.\n"); 1539 pr_info("x2apic not enabled, IRQ remapping is in xapic mode\n");
1540 else if (ret < 0)
1541 pr_info("x2apic not enabled, IRQ remapping init failed\n");
1524} 1542}
1525 1543
1526#ifdef CONFIG_X86_64 1544#ifdef CONFIG_X86_64