aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/apic/apic.c5
-rw-r--r--arch/x86/kernel/apic/io_apic.c265
-rw-r--r--arch/x86/kernel/smpboot.c11
3 files changed, 122 insertions, 159 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 76b96d74978a..f0e079823c43 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -43,6 +43,7 @@
43#include <asm/i8259.h> 43#include <asm/i8259.h>
44#include <asm/proto.h> 44#include <asm/proto.h>
45#include <asm/apic.h> 45#include <asm/apic.h>
46#include <asm/io_apic.h>
46#include <asm/desc.h> 47#include <asm/desc.h>
47#include <asm/hpet.h> 48#include <asm/hpet.h>
48#include <asm/idle.h> 49#include <asm/idle.h>
@@ -1209,7 +1210,7 @@ void __cpuinit setup_local_APIC(void)
1209 rdtscll(tsc); 1210 rdtscll(tsc);
1210 1211
1211 if (disable_apic) { 1212 if (disable_apic) {
1212 arch_disable_smp_support(); 1213 disable_ioapic_support();
1213 return; 1214 return;
1214 } 1215 }
1215 1216
@@ -1448,7 +1449,7 @@ int __init enable_IR(void)
1448void __init enable_IR_x2apic(void) 1449void __init enable_IR_x2apic(void)
1449{ 1450{
1450 unsigned long flags; 1451 unsigned long flags;
1451 struct IO_APIC_route_entry **ioapic_entries = NULL; 1452 struct IO_APIC_route_entry **ioapic_entries;
1452 int ret, x2apic_enabled = 0; 1453 int ret, x2apic_enabled = 0;
1453 int dmar_table_init_ret; 1454 int dmar_table_init_ret;
1454 1455
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index ca9e2a3545a9..8d23e831a45e 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -108,7 +108,10 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
108 108
109int skip_ioapic_setup; 109int skip_ioapic_setup;
110 110
111void arch_disable_smp_support(void) 111/**
112 * disable_ioapic_support() - disables ioapic support at runtime
113 */
114void disable_ioapic_support(void)
112{ 115{
113#ifdef CONFIG_PCI 116#ifdef CONFIG_PCI
114 noioapicquirk = 1; 117 noioapicquirk = 1;
@@ -120,11 +123,14 @@ void arch_disable_smp_support(void)
120static int __init parse_noapic(char *str) 123static int __init parse_noapic(char *str)
121{ 124{
122 /* disable IO-APIC */ 125 /* disable IO-APIC */
123 arch_disable_smp_support(); 126 disable_ioapic_support();
124 return 0; 127 return 0;
125} 128}
126early_param("noapic", parse_noapic); 129early_param("noapic", parse_noapic);
127 130
131static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
132 struct io_apic_irq_attr *attr);
133
128/* Will be called in mpparse/acpi/sfi codes for saving IRQ info */ 134/* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
129void mp_save_irq(struct mpc_intsrc *m) 135void mp_save_irq(struct mpc_intsrc *m)
130{ 136{
@@ -818,7 +824,7 @@ static int EISA_ELCR(unsigned int irq)
818#define default_MCA_trigger(idx) (1) 824#define default_MCA_trigger(idx) (1)
819#define default_MCA_polarity(idx) default_ISA_polarity(idx) 825#define default_MCA_polarity(idx) default_ISA_polarity(idx)
820 826
821static int MPBIOS_polarity(int idx) 827static int irq_polarity(int idx)
822{ 828{
823 int bus = mp_irqs[idx].srcbus; 829 int bus = mp_irqs[idx].srcbus;
824 int polarity; 830 int polarity;
@@ -860,7 +866,7 @@ static int MPBIOS_polarity(int idx)
860 return polarity; 866 return polarity;
861} 867}
862 868
863static int MPBIOS_trigger(int idx) 869static int irq_trigger(int idx)
864{ 870{
865 int bus = mp_irqs[idx].srcbus; 871 int bus = mp_irqs[idx].srcbus;
866 int trigger; 872 int trigger;
@@ -932,16 +938,6 @@ static int MPBIOS_trigger(int idx)
932 return trigger; 938 return trigger;
933} 939}
934 940
935static inline int irq_polarity(int idx)
936{
937 return MPBIOS_polarity(idx);
938}
939
940static inline int irq_trigger(int idx)
941{
942 return MPBIOS_trigger(idx);
943}
944
945static int pin_2_irq(int idx, int apic, int pin) 941static int pin_2_irq(int idx, int apic, int pin)
946{ 942{
947 int irq; 943 int irq;
@@ -1220,10 +1216,6 @@ void __setup_vector_irq(int cpu)
1220static struct irq_chip ioapic_chip; 1216static struct irq_chip ioapic_chip;
1221static struct irq_chip ir_ioapic_chip; 1217static struct irq_chip ir_ioapic_chip;
1222 1218
1223#define IOAPIC_AUTO -1
1224#define IOAPIC_EDGE 0
1225#define IOAPIC_LEVEL 1
1226
1227#ifdef CONFIG_X86_32 1219#ifdef CONFIG_X86_32
1228static inline int IO_APIC_irq_trigger(int irq) 1220static inline int IO_APIC_irq_trigger(int irq)
1229{ 1221{
@@ -1385,33 +1377,26 @@ static struct {
1385 DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1); 1377 DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
1386} mp_ioapic_routing[MAX_IO_APICS]; 1378} mp_ioapic_routing[MAX_IO_APICS];
1387 1379
1388static void __init setup_IO_APIC_irqs(void) 1380static bool __init io_apic_pin_not_connected(int idx, int apic_id, int pin)
1389{ 1381{
1390 int apic_id, pin, idx, irq, notcon = 0; 1382 if (idx != -1)
1391 int node = cpu_to_node(0); 1383 return false;
1392 struct irq_cfg *cfg;
1393 1384
1394 apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n"); 1385 apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n",
1386 mp_ioapics[apic_id].apicid, pin);
1387 return true;
1388}
1389
1390static void __init __io_apic_setup_irqs(unsigned int apic_id)
1391{
1392 int idx, node = cpu_to_node(0);
1393 struct io_apic_irq_attr attr;
1394 unsigned int pin, irq;
1395 1395
1396 for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
1397 for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) { 1396 for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
1398 idx = find_irq_entry(apic_id, pin, mp_INT); 1397 idx = find_irq_entry(apic_id, pin, mp_INT);
1399 if (idx == -1) { 1398 if (io_apic_pin_not_connected(idx, apic_id, pin))
1400 if (!notcon) {
1401 notcon = 1;
1402 apic_printk(APIC_VERBOSE,
1403 KERN_DEBUG " %d-%d",
1404 mp_ioapics[apic_id].apicid, pin);
1405 } else
1406 apic_printk(APIC_VERBOSE, " %d-%d",
1407 mp_ioapics[apic_id].apicid, pin);
1408 continue; 1399 continue;
1409 }
1410 if (notcon) {
1411 apic_printk(APIC_VERBOSE,
1412 " (apicid-pin) not connected\n");
1413 notcon = 0;
1414 }
1415 1400
1416 irq = pin_2_irq(idx, apic_id, pin); 1401 irq = pin_2_irq(idx, apic_id, pin);
1417 1402
@@ -1423,25 +1408,24 @@ static void __init setup_IO_APIC_irqs(void)
1423 * installed and if it returns 1: 1408 * installed and if it returns 1:
1424 */ 1409 */
1425 if (apic->multi_timer_check && 1410 if (apic->multi_timer_check &&
1426 apic->multi_timer_check(apic_id, irq)) 1411 apic->multi_timer_check(apic_id, irq))
1427 continue; 1412 continue;
1428 1413
1429 cfg = alloc_irq_and_cfg_at(irq, node); 1414 set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
1430 if (!cfg) 1415 irq_polarity(idx));
1431 continue;
1432 1416
1433 add_pin_to_irq_node(cfg, node, apic_id, pin); 1417 io_apic_setup_irq_pin(irq, node, &attr);
1434 /*
1435 * don't mark it in pin_programmed, so later acpi could
1436 * set it correctly when irq < 16
1437 */
1438 setup_ioapic_irq(apic_id, pin, irq, cfg, irq_trigger(idx),
1439 irq_polarity(idx));
1440 } 1418 }
1419}
1441 1420
1442 if (notcon) 1421static void __init setup_IO_APIC_irqs(void)
1443 apic_printk(APIC_VERBOSE, 1422{
1444 " (apicid-pin) not connected\n"); 1423 unsigned int apic_id;
1424
1425 apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
1426
1427 for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
1428 __io_apic_setup_irqs(apic_id);
1445} 1429}
1446 1430
1447/* 1431/*
@@ -1452,7 +1436,7 @@ static void __init setup_IO_APIC_irqs(void)
1452void setup_IO_APIC_irq_extra(u32 gsi) 1436void setup_IO_APIC_irq_extra(u32 gsi)
1453{ 1437{
1454 int apic_id = 0, pin, idx, irq, node = cpu_to_node(0); 1438 int apic_id = 0, pin, idx, irq, node = cpu_to_node(0);
1455 struct irq_cfg *cfg; 1439 struct io_apic_irq_attr attr;
1456 1440
1457 /* 1441 /*
1458 * Convert 'gsi' to 'ioapic.pin'. 1442 * Convert 'gsi' to 'ioapic.pin'.
@@ -1472,21 +1456,10 @@ void setup_IO_APIC_irq_extra(u32 gsi)
1472 if (apic_id == 0 || irq < NR_IRQS_LEGACY) 1456 if (apic_id == 0 || irq < NR_IRQS_LEGACY)
1473 return; 1457 return;
1474 1458
1475 cfg = alloc_irq_and_cfg_at(irq, node); 1459 set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
1476 if (!cfg) 1460 irq_polarity(idx));
1477 return;
1478
1479 add_pin_to_irq_node(cfg, node, apic_id, pin);
1480
1481 if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
1482 pr_debug("Pin %d-%d already programmed\n",
1483 mp_ioapics[apic_id].apicid, pin);
1484 return;
1485 }
1486 set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed);
1487 1461
1488 setup_ioapic_irq(apic_id, pin, irq, cfg, 1462 io_apic_setup_irq_pin_once(irq, node, &attr);
1489 irq_trigger(idx), irq_polarity(idx));
1490} 1463}
1491 1464
1492/* 1465/*
@@ -3605,7 +3578,40 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
3605} 3578}
3606#endif /* CONFIG_HT_IRQ */ 3579#endif /* CONFIG_HT_IRQ */
3607 3580
3608int __init io_apic_get_redir_entries (int ioapic) 3581int
3582io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
3583{
3584 struct irq_cfg *cfg = alloc_irq_and_cfg_at(irq, node);
3585 int ret;
3586
3587 if (!cfg)
3588 return -EINVAL;
3589 ret = __add_pin_to_irq_node(cfg, node, attr->ioapic, attr->ioapic_pin);
3590 if (!ret)
3591 setup_ioapic_irq(attr->ioapic, attr->ioapic_pin, irq, cfg,
3592 attr->trigger, attr->polarity);
3593 return ret;
3594}
3595
3596static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
3597 struct io_apic_irq_attr *attr)
3598{
3599 unsigned int id = attr->ioapic, pin = attr->ioapic_pin;
3600 int ret;
3601
3602 /* Avoid redundant programming */
3603 if (test_bit(pin, mp_ioapic_routing[id].pin_programmed)) {
3604 pr_debug("Pin %d-%d already programmed\n",
3605 mp_ioapics[id].apicid, pin);
3606 return 0;
3607 }
3608 ret = io_apic_setup_irq_pin(irq, node, attr);
3609 if (!ret)
3610 set_bit(pin, mp_ioapic_routing[id].pin_programmed);
3611 return ret;
3612}
3613
3614static int __init io_apic_get_redir_entries(int ioapic)
3609{ 3615{
3610 union IO_APIC_reg_01 reg_01; 3616 union IO_APIC_reg_01 reg_01;
3611 unsigned long flags; 3617 unsigned long flags;
@@ -3659,96 +3665,24 @@ int __init arch_probe_nr_irqs(void)
3659} 3665}
3660#endif 3666#endif
3661 3667
3662static int __io_apic_set_pci_routing(struct device *dev, int irq, 3668int io_apic_set_pci_routing(struct device *dev, int irq,
3663 struct io_apic_irq_attr *irq_attr) 3669 struct io_apic_irq_attr *irq_attr)
3664{ 3670{
3665 struct irq_cfg *cfg;
3666 int node; 3671 int node;
3667 int ioapic, pin;
3668 int trigger, polarity;
3669 3672
3670 ioapic = irq_attr->ioapic;
3671 if (!IO_APIC_IRQ(irq)) { 3673 if (!IO_APIC_IRQ(irq)) {
3672 apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n", 3674 apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
3673 ioapic); 3675 irq_attr->ioapic);
3674 return -EINVAL; 3676 return -EINVAL;
3675 } 3677 }
3676 3678
3677 if (dev) 3679 node = dev ? dev_to_node(dev) : cpu_to_node(0);
3678 node = dev_to_node(dev);
3679 else
3680 node = cpu_to_node(0);
3681
3682 cfg = alloc_irq_and_cfg_at(irq, node);
3683 if (!cfg)
3684 return 0;
3685
3686 pin = irq_attr->ioapic_pin;
3687 trigger = irq_attr->trigger;
3688 polarity = irq_attr->polarity;
3689
3690 /*
3691 * IRQs < 16 are already in the irq_2_pin[] map
3692 */
3693 if (irq >= legacy_pic->nr_legacy_irqs) {
3694 if (__add_pin_to_irq_node(cfg, node, ioapic, pin)) {
3695 printk(KERN_INFO "can not add pin %d for irq %d\n",
3696 pin, irq);
3697 return 0;
3698 }
3699 }
3700
3701 setup_ioapic_irq(ioapic, pin, irq, cfg, trigger, polarity);
3702 3680
3703 return 0; 3681 return io_apic_setup_irq_pin_once(irq, node, irq_attr);
3704} 3682}
3705 3683
3706int io_apic_set_pci_routing(struct device *dev, int irq,
3707 struct io_apic_irq_attr *irq_attr)
3708{
3709 int ioapic, pin;
3710 /*
3711 * Avoid pin reprogramming. PRTs typically include entries
3712 * with redundant pin->gsi mappings (but unique PCI devices);
3713 * we only program the IOAPIC on the first.
3714 */
3715 ioapic = irq_attr->ioapic;
3716 pin = irq_attr->ioapic_pin;
3717 if (test_bit(pin, mp_ioapic_routing[ioapic].pin_programmed)) {
3718 pr_debug("Pin %d-%d already programmed\n",
3719 mp_ioapics[ioapic].apicid, pin);
3720 return 0;
3721 }
3722 set_bit(pin, mp_ioapic_routing[ioapic].pin_programmed);
3723
3724 return __io_apic_set_pci_routing(dev, irq, irq_attr);
3725}
3726
3727u8 __init io_apic_unique_id(u8 id)
3728{
3729#ifdef CONFIG_X86_32 3684#ifdef CONFIG_X86_32
3730 if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && 3685static int __init io_apic_get_unique_id(int ioapic, int apic_id)
3731 !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
3732 return io_apic_get_unique_id(nr_ioapics, id);
3733 else
3734 return id;
3735#else
3736 int i;
3737 DECLARE_BITMAP(used, 256);
3738
3739 bitmap_zero(used, 256);
3740 for (i = 0; i < nr_ioapics; i++) {
3741 struct mpc_ioapic *ia = &mp_ioapics[i];
3742 __set_bit(ia->apicid, used);
3743 }
3744 if (!test_bit(id, used))
3745 return id;
3746 return find_first_zero_bit(used, 256);
3747#endif
3748}
3749
3750#ifdef CONFIG_X86_32
3751int __init io_apic_get_unique_id(int ioapic, int apic_id)
3752{ 3686{
3753 union IO_APIC_reg_00 reg_00; 3687 union IO_APIC_reg_00 reg_00;
3754 static physid_mask_t apic_id_map = PHYSID_MASK_NONE; 3688 static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
@@ -3821,9 +3755,33 @@ int __init io_apic_get_unique_id(int ioapic, int apic_id)
3821 3755
3822 return apic_id; 3756 return apic_id;
3823} 3757}
3758
3759static u8 __init io_apic_unique_id(u8 id)
3760{
3761 if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
3762 !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
3763 return io_apic_get_unique_id(nr_ioapics, id);
3764 else
3765 return id;
3766}
3767#else
3768static u8 __init io_apic_unique_id(u8 id)
3769{
3770 int i;
3771 DECLARE_BITMAP(used, 256);
3772
3773 bitmap_zero(used, 256);
3774 for (i = 0; i < nr_ioapics; i++) {
3775 struct mpc_ioapic *ia = &mp_ioapics[i];
3776 __set_bit(ia->apicid, used);
3777 }
3778 if (!test_bit(id, used))
3779 return id;
3780 return find_first_zero_bit(used, 256);
3781}
3824#endif 3782#endif
3825 3783
3826int __init io_apic_get_version(int ioapic) 3784static int __init io_apic_get_version(int ioapic)
3827{ 3785{
3828 union IO_APIC_reg_01 reg_01; 3786 union IO_APIC_reg_01 reg_01;
3829 unsigned long flags; 3787 unsigned long flags;
@@ -4026,7 +3984,7 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi)
4026 return gsi - mp_gsi_routing[ioapic].gsi_base; 3984 return gsi - mp_gsi_routing[ioapic].gsi_base;
4027} 3985}
4028 3986
4029static int bad_ioapic(unsigned long address) 3987static __init int bad_ioapic(unsigned long address)
4030{ 3988{
4031 if (nr_ioapics >= MAX_IO_APICS) { 3989 if (nr_ioapics >= MAX_IO_APICS) {
4032 printk(KERN_WARNING "WARING: Max # of I/O APICs (%d) exceeded " 3990 printk(KERN_WARNING "WARING: Max # of I/O APICs (%d) exceeded "
@@ -4086,20 +4044,15 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
4086/* Enable IOAPIC early just for system timer */ 4044/* Enable IOAPIC early just for system timer */
4087void __init pre_init_apic_IRQ0(void) 4045void __init pre_init_apic_IRQ0(void)
4088{ 4046{
4089 struct irq_cfg *cfg; 4047 struct io_apic_irq_attr attr = { 0, 0, 0, 0 };
4090 4048
4091 printk(KERN_INFO "Early APIC setup for system timer0\n"); 4049 printk(KERN_INFO "Early APIC setup for system timer0\n");
4092#ifndef CONFIG_SMP 4050#ifndef CONFIG_SMP
4093 physid_set_mask_of_physid(boot_cpu_physical_apicid, 4051 physid_set_mask_of_physid(boot_cpu_physical_apicid,
4094 &phys_cpu_present_map); 4052 &phys_cpu_present_map);
4095#endif 4053#endif
4096 /* Make sure the irq descriptor is set up */
4097 cfg = alloc_irq_and_cfg_at(0, 0);
4098
4099 setup_local_APIC(); 4054 setup_local_APIC();
4100 4055
4101 add_pin_to_irq_node(cfg, 0, 0, 0); 4056 io_apic_setup_irq_pin(0, 0, &attr);
4102 set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge"); 4057 set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
4103
4104 setup_ioapic_irq(0, 0, 0, cfg, 0, 0);
4105} 4058}
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 08776a953487..09d0172a0059 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -64,6 +64,7 @@
64#include <asm/mtrr.h> 64#include <asm/mtrr.h>
65#include <asm/mwait.h> 65#include <asm/mwait.h>
66#include <asm/apic.h> 66#include <asm/apic.h>
67#include <asm/io_apic.h>
67#include <asm/setup.h> 68#include <asm/setup.h>
68#include <asm/uv/uv.h> 69#include <asm/uv/uv.h>
69#include <linux/mc146818rtc.h> 70#include <linux/mc146818rtc.h>
@@ -945,6 +946,14 @@ int __cpuinit native_cpu_up(unsigned int cpu)
945 return 0; 946 return 0;
946} 947}
947 948
949/**
950 * arch_disable_smp_support() - disables SMP support for x86 at runtime
951 */
952void arch_disable_smp_support(void)
953{
954 disable_ioapic_support();
955}
956
948/* 957/*
949 * Fall back to non SMP mode after errors. 958 * Fall back to non SMP mode after errors.
950 * 959 *
@@ -1045,7 +1054,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
1045 "(tell your hw vendor)\n"); 1054 "(tell your hw vendor)\n");
1046 } 1055 }
1047 smpboot_clear_io_apic(); 1056 smpboot_clear_io_apic();
1048 arch_disable_smp_support(); 1057 disable_ioapic_support();
1049 return -1; 1058 return -1;
1050 } 1059 }
1051 1060