Merge branch 'x86/apic' into x86/platform
Reason: Devicetree based ioapic setup depends on the apic changes. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
commit
cb4cfd568c
|
@ -811,7 +811,7 @@ config X86_LOCAL_APIC
|
||||||
|
|
||||||
config X86_IO_APIC
|
config X86_IO_APIC
|
||||||
def_bool y
|
def_bool y
|
||||||
depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
|
depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC
|
||||||
|
|
||||||
config X86_VISWS_APIC
|
config X86_VISWS_APIC
|
||||||
def_bool y
|
def_bool y
|
||||||
|
|
|
@ -426,4 +426,16 @@ struct local_apic {
|
||||||
#else
|
#else
|
||||||
#define BAD_APICID 0xFFFFu
|
#define BAD_APICID 0xFFFFu
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum ioapic_irq_destination_types {
|
||||||
|
dest_Fixed = 0,
|
||||||
|
dest_LowestPrio = 1,
|
||||||
|
dest_SMI = 2,
|
||||||
|
dest__reserved_1 = 3,
|
||||||
|
dest_NMI = 4,
|
||||||
|
dest_INIT = 5,
|
||||||
|
dest__reserved_2 = 6,
|
||||||
|
dest_ExtINT = 7
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* _ASM_X86_APICDEF_H */
|
#endif /* _ASM_X86_APICDEF_H */
|
||||||
|
|
|
@ -63,17 +63,6 @@ union IO_APIC_reg_03 {
|
||||||
} __attribute__ ((packed)) bits;
|
} __attribute__ ((packed)) bits;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ioapic_irq_destination_types {
|
|
||||||
dest_Fixed = 0,
|
|
||||||
dest_LowestPrio = 1,
|
|
||||||
dest_SMI = 2,
|
|
||||||
dest__reserved_1 = 3,
|
|
||||||
dest_NMI = 4,
|
|
||||||
dest_INIT = 5,
|
|
||||||
dest__reserved_2 = 6,
|
|
||||||
dest_ExtINT = 7
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IO_APIC_route_entry {
|
struct IO_APIC_route_entry {
|
||||||
__u32 vector : 8,
|
__u32 vector : 8,
|
||||||
delivery_mode : 3, /* 000: FIXED
|
delivery_mode : 3, /* 000: FIXED
|
||||||
|
@ -106,6 +95,10 @@ struct IR_IO_APIC_route_entry {
|
||||||
index : 15;
|
index : 15;
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#define IOAPIC_AUTO -1
|
||||||
|
#define IOAPIC_EDGE 0
|
||||||
|
#define IOAPIC_LEVEL 1
|
||||||
|
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
#ifdef CONFIG_X86_IO_APIC
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -150,11 +143,6 @@ extern int timer_through_8259;
|
||||||
#define io_apic_assign_pci_irqs \
|
#define io_apic_assign_pci_irqs \
|
||||||
(mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
|
(mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
|
||||||
|
|
||||||
extern u8 io_apic_unique_id(u8 id);
|
|
||||||
extern int io_apic_get_unique_id(int ioapic, int apic_id);
|
|
||||||
extern int io_apic_get_version(int ioapic);
|
|
||||||
extern int io_apic_get_redir_entries(int ioapic);
|
|
||||||
|
|
||||||
struct io_apic_irq_attr;
|
struct io_apic_irq_attr;
|
||||||
extern int io_apic_set_pci_routing(struct device *dev, int irq,
|
extern int io_apic_set_pci_routing(struct device *dev, int irq,
|
||||||
struct io_apic_irq_attr *irq_attr);
|
struct io_apic_irq_attr *irq_attr);
|
||||||
|
@ -162,6 +150,8 @@ void setup_IO_APIC_irq_extra(u32 gsi);
|
||||||
extern void ioapic_and_gsi_init(void);
|
extern void ioapic_and_gsi_init(void);
|
||||||
extern void ioapic_insert_resources(void);
|
extern void ioapic_insert_resources(void);
|
||||||
|
|
||||||
|
int io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr);
|
||||||
|
|
||||||
extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
|
extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
|
||||||
extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
|
extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
|
||||||
extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
|
extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
|
||||||
|
@ -186,6 +176,8 @@ extern void __init pre_init_apic_IRQ0(void);
|
||||||
|
|
||||||
extern void mp_save_irq(struct mpc_intsrc *m);
|
extern void mp_save_irq(struct mpc_intsrc *m);
|
||||||
|
|
||||||
|
extern void disable_ioapic_support(void);
|
||||||
|
|
||||||
#else /* !CONFIG_X86_IO_APIC */
|
#else /* !CONFIG_X86_IO_APIC */
|
||||||
|
|
||||||
#define io_apic_assign_pci_irqs 0
|
#define io_apic_assign_pci_irqs 0
|
||||||
|
@ -199,6 +191,26 @@ static inline int mp_find_ioapic(u32 gsi) { return 0; }
|
||||||
struct io_apic_irq_attr;
|
struct io_apic_irq_attr;
|
||||||
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
|
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
|
||||||
struct io_apic_irq_attr *irq_attr) { return 0; }
|
struct io_apic_irq_attr *irq_attr) { return 0; }
|
||||||
|
|
||||||
|
static inline struct IO_APIC_route_entry **alloc_ioapic_entries(void)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void free_ioapic_entries(struct IO_APIC_route_entry **ent) { }
|
||||||
|
static inline int save_IO_APIC_setup(struct IO_APIC_route_entry **ent)
|
||||||
|
{
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mask_IO_APIC_setup(struct IO_APIC_route_entry **ent) { }
|
||||||
|
static inline int restore_IO_APIC_setup(struct IO_APIC_route_entry **ent)
|
||||||
|
{
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mp_save_irq(struct mpc_intsrc *m) { };
|
||||||
|
static inline void disable_ioapic_support(void) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _ASM_X86_IO_APIC_H */
|
#endif /* _ASM_X86_IO_APIC_H */
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include <asm/i8259.h>
|
#include <asm/i8259.h>
|
||||||
#include <asm/proto.h>
|
#include <asm/proto.h>
|
||||||
#include <asm/apic.h>
|
#include <asm/apic.h>
|
||||||
|
#include <asm/io_apic.h>
|
||||||
#include <asm/desc.h>
|
#include <asm/desc.h>
|
||||||
#include <asm/hpet.h>
|
#include <asm/hpet.h>
|
||||||
#include <asm/idle.h>
|
#include <asm/idle.h>
|
||||||
|
@ -1209,7 +1210,7 @@ void __cpuinit setup_local_APIC(void)
|
||||||
rdtscll(tsc);
|
rdtscll(tsc);
|
||||||
|
|
||||||
if (disable_apic) {
|
if (disable_apic) {
|
||||||
arch_disable_smp_support();
|
disable_ioapic_support();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1448,7 +1449,7 @@ int __init enable_IR(void)
|
||||||
void __init enable_IR_x2apic(void)
|
void __init enable_IR_x2apic(void)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct IO_APIC_route_entry **ioapic_entries = NULL;
|
struct IO_APIC_route_entry **ioapic_entries;
|
||||||
int ret, x2apic_enabled = 0;
|
int ret, x2apic_enabled = 0;
|
||||||
int dmar_table_init_ret;
|
int dmar_table_init_ret;
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,10 @@ DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
|
||||||
|
|
||||||
int skip_ioapic_setup;
|
int skip_ioapic_setup;
|
||||||
|
|
||||||
void arch_disable_smp_support(void)
|
/**
|
||||||
|
* disable_ioapic_support() - disables ioapic support at runtime
|
||||||
|
*/
|
||||||
|
void disable_ioapic_support(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_PCI
|
#ifdef CONFIG_PCI
|
||||||
noioapicquirk = 1;
|
noioapicquirk = 1;
|
||||||
|
@ -120,11 +123,14 @@ void arch_disable_smp_support(void)
|
||||||
static int __init parse_noapic(char *str)
|
static int __init parse_noapic(char *str)
|
||||||
{
|
{
|
||||||
/* disable IO-APIC */
|
/* disable IO-APIC */
|
||||||
arch_disable_smp_support();
|
disable_ioapic_support();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
early_param("noapic", parse_noapic);
|
early_param("noapic", parse_noapic);
|
||||||
|
|
||||||
|
static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
|
||||||
|
struct io_apic_irq_attr *attr);
|
||||||
|
|
||||||
/* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
|
/* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
|
||||||
void mp_save_irq(struct mpc_intsrc *m)
|
void mp_save_irq(struct mpc_intsrc *m)
|
||||||
{
|
{
|
||||||
|
@ -818,7 +824,7 @@ static int EISA_ELCR(unsigned int irq)
|
||||||
#define default_MCA_trigger(idx) (1)
|
#define default_MCA_trigger(idx) (1)
|
||||||
#define default_MCA_polarity(idx) default_ISA_polarity(idx)
|
#define default_MCA_polarity(idx) default_ISA_polarity(idx)
|
||||||
|
|
||||||
static int MPBIOS_polarity(int idx)
|
static int irq_polarity(int idx)
|
||||||
{
|
{
|
||||||
int bus = mp_irqs[idx].srcbus;
|
int bus = mp_irqs[idx].srcbus;
|
||||||
int polarity;
|
int polarity;
|
||||||
|
@ -860,7 +866,7 @@ static int MPBIOS_polarity(int idx)
|
||||||
return polarity;
|
return polarity;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int MPBIOS_trigger(int idx)
|
static int irq_trigger(int idx)
|
||||||
{
|
{
|
||||||
int bus = mp_irqs[idx].srcbus;
|
int bus = mp_irqs[idx].srcbus;
|
||||||
int trigger;
|
int trigger;
|
||||||
|
@ -932,16 +938,6 @@ static int MPBIOS_trigger(int idx)
|
||||||
return trigger;
|
return trigger;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int irq_polarity(int idx)
|
|
||||||
{
|
|
||||||
return MPBIOS_polarity(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int irq_trigger(int idx)
|
|
||||||
{
|
|
||||||
return MPBIOS_trigger(idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int pin_2_irq(int idx, int apic, int pin)
|
static int pin_2_irq(int idx, int apic, int pin)
|
||||||
{
|
{
|
||||||
int irq;
|
int irq;
|
||||||
|
@ -1220,10 +1216,6 @@ void __setup_vector_irq(int cpu)
|
||||||
static struct irq_chip ioapic_chip;
|
static struct irq_chip ioapic_chip;
|
||||||
static struct irq_chip ir_ioapic_chip;
|
static struct irq_chip ir_ioapic_chip;
|
||||||
|
|
||||||
#define IOAPIC_AUTO -1
|
|
||||||
#define IOAPIC_EDGE 0
|
|
||||||
#define IOAPIC_LEVEL 1
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
static inline int IO_APIC_irq_trigger(int irq)
|
static inline int IO_APIC_irq_trigger(int irq)
|
||||||
{
|
{
|
||||||
|
@ -1385,33 +1377,26 @@ static struct {
|
||||||
DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
|
DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
|
||||||
} mp_ioapic_routing[MAX_IO_APICS];
|
} mp_ioapic_routing[MAX_IO_APICS];
|
||||||
|
|
||||||
static void __init setup_IO_APIC_irqs(void)
|
static bool __init io_apic_pin_not_connected(int idx, int apic_id, int pin)
|
||||||
{
|
{
|
||||||
int apic_id, pin, idx, irq, notcon = 0;
|
if (idx != -1)
|
||||||
int node = cpu_to_node(0);
|
return false;
|
||||||
struct irq_cfg *cfg;
|
|
||||||
|
|
||||||
apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
|
apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n",
|
||||||
|
mp_ioapics[apic_id].apicid, pin);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init __io_apic_setup_irqs(unsigned int apic_id)
|
||||||
|
{
|
||||||
|
int idx, node = cpu_to_node(0);
|
||||||
|
struct io_apic_irq_attr attr;
|
||||||
|
unsigned int pin, irq;
|
||||||
|
|
||||||
for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
|
|
||||||
for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
|
for (pin = 0; pin < nr_ioapic_registers[apic_id]; pin++) {
|
||||||
idx = find_irq_entry(apic_id, pin, mp_INT);
|
idx = find_irq_entry(apic_id, pin, mp_INT);
|
||||||
if (idx == -1) {
|
if (io_apic_pin_not_connected(idx, apic_id, pin))
|
||||||
if (!notcon) {
|
|
||||||
notcon = 1;
|
|
||||||
apic_printk(APIC_VERBOSE,
|
|
||||||
KERN_DEBUG " %d-%d",
|
|
||||||
mp_ioapics[apic_id].apicid, pin);
|
|
||||||
} else
|
|
||||||
apic_printk(APIC_VERBOSE, " %d-%d",
|
|
||||||
mp_ioapics[apic_id].apicid, pin);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
if (notcon) {
|
|
||||||
apic_printk(APIC_VERBOSE,
|
|
||||||
" (apicid-pin) not connected\n");
|
|
||||||
notcon = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
irq = pin_2_irq(idx, apic_id, pin);
|
irq = pin_2_irq(idx, apic_id, pin);
|
||||||
|
|
||||||
|
@ -1423,25 +1408,24 @@ static void __init setup_IO_APIC_irqs(void)
|
||||||
* installed and if it returns 1:
|
* installed and if it returns 1:
|
||||||
*/
|
*/
|
||||||
if (apic->multi_timer_check &&
|
if (apic->multi_timer_check &&
|
||||||
apic->multi_timer_check(apic_id, irq))
|
apic->multi_timer_check(apic_id, irq))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
cfg = alloc_irq_and_cfg_at(irq, node);
|
set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
|
||||||
if (!cfg)
|
irq_polarity(idx));
|
||||||
continue;
|
|
||||||
|
|
||||||
add_pin_to_irq_node(cfg, node, apic_id, pin);
|
io_apic_setup_irq_pin(irq, node, &attr);
|
||||||
/*
|
|
||||||
* don't mark it in pin_programmed, so later acpi could
|
|
||||||
* set it correctly when irq < 16
|
|
||||||
*/
|
|
||||||
setup_ioapic_irq(apic_id, pin, irq, cfg, irq_trigger(idx),
|
|
||||||
irq_polarity(idx));
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (notcon)
|
static void __init setup_IO_APIC_irqs(void)
|
||||||
apic_printk(APIC_VERBOSE,
|
{
|
||||||
" (apicid-pin) not connected\n");
|
unsigned int apic_id;
|
||||||
|
|
||||||
|
apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
|
||||||
|
|
||||||
|
for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
|
||||||
|
__io_apic_setup_irqs(apic_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1452,7 +1436,7 @@ static void __init setup_IO_APIC_irqs(void)
|
||||||
void setup_IO_APIC_irq_extra(u32 gsi)
|
void setup_IO_APIC_irq_extra(u32 gsi)
|
||||||
{
|
{
|
||||||
int apic_id = 0, pin, idx, irq, node = cpu_to_node(0);
|
int apic_id = 0, pin, idx, irq, node = cpu_to_node(0);
|
||||||
struct irq_cfg *cfg;
|
struct io_apic_irq_attr attr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert 'gsi' to 'ioapic.pin'.
|
* Convert 'gsi' to 'ioapic.pin'.
|
||||||
|
@ -1472,21 +1456,10 @@ void setup_IO_APIC_irq_extra(u32 gsi)
|
||||||
if (apic_id == 0 || irq < NR_IRQS_LEGACY)
|
if (apic_id == 0 || irq < NR_IRQS_LEGACY)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cfg = alloc_irq_and_cfg_at(irq, node);
|
set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
|
||||||
if (!cfg)
|
irq_polarity(idx));
|
||||||
return;
|
|
||||||
|
|
||||||
add_pin_to_irq_node(cfg, node, apic_id, pin);
|
io_apic_setup_irq_pin_once(irq, node, &attr);
|
||||||
|
|
||||||
if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
|
|
||||||
pr_debug("Pin %d-%d already programmed\n",
|
|
||||||
mp_ioapics[apic_id].apicid, pin);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed);
|
|
||||||
|
|
||||||
setup_ioapic_irq(apic_id, pin, irq, cfg,
|
|
||||||
irq_trigger(idx), irq_polarity(idx));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3605,7 +3578,40 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_HT_IRQ */
|
#endif /* CONFIG_HT_IRQ */
|
||||||
|
|
||||||
int __init io_apic_get_redir_entries (int ioapic)
|
int
|
||||||
|
io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
|
||||||
|
{
|
||||||
|
struct irq_cfg *cfg = alloc_irq_and_cfg_at(irq, node);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!cfg)
|
||||||
|
return -EINVAL;
|
||||||
|
ret = __add_pin_to_irq_node(cfg, node, attr->ioapic, attr->ioapic_pin);
|
||||||
|
if (!ret)
|
||||||
|
setup_ioapic_irq(attr->ioapic, attr->ioapic_pin, irq, cfg,
|
||||||
|
attr->trigger, attr->polarity);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
|
||||||
|
struct io_apic_irq_attr *attr)
|
||||||
|
{
|
||||||
|
unsigned int id = attr->ioapic, pin = attr->ioapic_pin;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Avoid redundant programming */
|
||||||
|
if (test_bit(pin, mp_ioapic_routing[id].pin_programmed)) {
|
||||||
|
pr_debug("Pin %d-%d already programmed\n",
|
||||||
|
mp_ioapics[id].apicid, pin);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ret = io_apic_setup_irq_pin(irq, node, attr);
|
||||||
|
if (!ret)
|
||||||
|
set_bit(pin, mp_ioapic_routing[id].pin_programmed);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init io_apic_get_redir_entries(int ioapic)
|
||||||
{
|
{
|
||||||
union IO_APIC_reg_01 reg_01;
|
union IO_APIC_reg_01 reg_01;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -3659,96 +3665,24 @@ int __init arch_probe_nr_irqs(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int __io_apic_set_pci_routing(struct device *dev, int irq,
|
int io_apic_set_pci_routing(struct device *dev, int irq,
|
||||||
struct io_apic_irq_attr *irq_attr)
|
struct io_apic_irq_attr *irq_attr)
|
||||||
{
|
{
|
||||||
struct irq_cfg *cfg;
|
|
||||||
int node;
|
int node;
|
||||||
int ioapic, pin;
|
|
||||||
int trigger, polarity;
|
|
||||||
|
|
||||||
ioapic = irq_attr->ioapic;
|
|
||||||
if (!IO_APIC_IRQ(irq)) {
|
if (!IO_APIC_IRQ(irq)) {
|
||||||
apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
|
apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
|
||||||
ioapic);
|
irq_attr->ioapic);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dev)
|
node = dev ? dev_to_node(dev) : cpu_to_node(0);
|
||||||
node = dev_to_node(dev);
|
|
||||||
else
|
|
||||||
node = cpu_to_node(0);
|
|
||||||
|
|
||||||
cfg = alloc_irq_and_cfg_at(irq, node);
|
return io_apic_setup_irq_pin_once(irq, node, irq_attr);
|
||||||
if (!cfg)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
pin = irq_attr->ioapic_pin;
|
|
||||||
trigger = irq_attr->trigger;
|
|
||||||
polarity = irq_attr->polarity;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* IRQs < 16 are already in the irq_2_pin[] map
|
|
||||||
*/
|
|
||||||
if (irq >= legacy_pic->nr_legacy_irqs) {
|
|
||||||
if (__add_pin_to_irq_node(cfg, node, ioapic, pin)) {
|
|
||||||
printk(KERN_INFO "can not add pin %d for irq %d\n",
|
|
||||||
pin, irq);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setup_ioapic_irq(ioapic, pin, irq, cfg, trigger, polarity);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int io_apic_set_pci_routing(struct device *dev, int irq,
|
|
||||||
struct io_apic_irq_attr *irq_attr)
|
|
||||||
{
|
|
||||||
int ioapic, pin;
|
|
||||||
/*
|
|
||||||
* Avoid pin reprogramming. PRTs typically include entries
|
|
||||||
* with redundant pin->gsi mappings (but unique PCI devices);
|
|
||||||
* we only program the IOAPIC on the first.
|
|
||||||
*/
|
|
||||||
ioapic = irq_attr->ioapic;
|
|
||||||
pin = irq_attr->ioapic_pin;
|
|
||||||
if (test_bit(pin, mp_ioapic_routing[ioapic].pin_programmed)) {
|
|
||||||
pr_debug("Pin %d-%d already programmed\n",
|
|
||||||
mp_ioapics[ioapic].apicid, pin);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
set_bit(pin, mp_ioapic_routing[ioapic].pin_programmed);
|
|
||||||
|
|
||||||
return __io_apic_set_pci_routing(dev, irq, irq_attr);
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 __init io_apic_unique_id(u8 id)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_X86_32
|
|
||||||
if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
|
|
||||||
!APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
|
|
||||||
return io_apic_get_unique_id(nr_ioapics, id);
|
|
||||||
else
|
|
||||||
return id;
|
|
||||||
#else
|
|
||||||
int i;
|
|
||||||
DECLARE_BITMAP(used, 256);
|
|
||||||
|
|
||||||
bitmap_zero(used, 256);
|
|
||||||
for (i = 0; i < nr_ioapics; i++) {
|
|
||||||
struct mpc_ioapic *ia = &mp_ioapics[i];
|
|
||||||
__set_bit(ia->apicid, used);
|
|
||||||
}
|
|
||||||
if (!test_bit(id, used))
|
|
||||||
return id;
|
|
||||||
return find_first_zero_bit(used, 256);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
int __init io_apic_get_unique_id(int ioapic, int apic_id)
|
static int __init io_apic_get_unique_id(int ioapic, int apic_id)
|
||||||
{
|
{
|
||||||
union IO_APIC_reg_00 reg_00;
|
union IO_APIC_reg_00 reg_00;
|
||||||
static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
|
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)
|
||||||
|
|
||||||
return apic_id;
|
return apic_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u8 __init io_apic_unique_id(u8 id)
|
||||||
|
{
|
||||||
|
if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
|
||||||
|
!APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
|
||||||
|
return io_apic_get_unique_id(nr_ioapics, id);
|
||||||
|
else
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static u8 __init io_apic_unique_id(u8 id)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
DECLARE_BITMAP(used, 256);
|
||||||
|
|
||||||
|
bitmap_zero(used, 256);
|
||||||
|
for (i = 0; i < nr_ioapics; i++) {
|
||||||
|
struct mpc_ioapic *ia = &mp_ioapics[i];
|
||||||
|
__set_bit(ia->apicid, used);
|
||||||
|
}
|
||||||
|
if (!test_bit(id, used))
|
||||||
|
return id;
|
||||||
|
return find_first_zero_bit(used, 256);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int __init io_apic_get_version(int ioapic)
|
static int __init io_apic_get_version(int ioapic)
|
||||||
{
|
{
|
||||||
union IO_APIC_reg_01 reg_01;
|
union IO_APIC_reg_01 reg_01;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -4026,7 +3984,7 @@ int mp_find_ioapic_pin(int ioapic, u32 gsi)
|
||||||
return gsi - mp_gsi_routing[ioapic].gsi_base;
|
return gsi - mp_gsi_routing[ioapic].gsi_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bad_ioapic(unsigned long address)
|
static __init int bad_ioapic(unsigned long address)
|
||||||
{
|
{
|
||||||
if (nr_ioapics >= MAX_IO_APICS) {
|
if (nr_ioapics >= MAX_IO_APICS) {
|
||||||
printk(KERN_WARNING "WARING: Max # of I/O APICs (%d) exceeded "
|
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)
|
||||||
/* Enable IOAPIC early just for system timer */
|
/* Enable IOAPIC early just for system timer */
|
||||||
void __init pre_init_apic_IRQ0(void)
|
void __init pre_init_apic_IRQ0(void)
|
||||||
{
|
{
|
||||||
struct irq_cfg *cfg;
|
struct io_apic_irq_attr attr = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
printk(KERN_INFO "Early APIC setup for system timer0\n");
|
printk(KERN_INFO "Early APIC setup for system timer0\n");
|
||||||
#ifndef CONFIG_SMP
|
#ifndef CONFIG_SMP
|
||||||
physid_set_mask_of_physid(boot_cpu_physical_apicid,
|
physid_set_mask_of_physid(boot_cpu_physical_apicid,
|
||||||
&phys_cpu_present_map);
|
&phys_cpu_present_map);
|
||||||
#endif
|
#endif
|
||||||
/* Make sure the irq descriptor is set up */
|
|
||||||
cfg = alloc_irq_and_cfg_at(0, 0);
|
|
||||||
|
|
||||||
setup_local_APIC();
|
setup_local_APIC();
|
||||||
|
|
||||||
add_pin_to_irq_node(cfg, 0, 0, 0);
|
io_apic_setup_irq_pin(0, 0, &attr);
|
||||||
set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
|
set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
|
||||||
|
|
||||||
setup_ioapic_irq(0, 0, 0, cfg, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,7 @@
|
||||||
#include <asm/mtrr.h>
|
#include <asm/mtrr.h>
|
||||||
#include <asm/mwait.h>
|
#include <asm/mwait.h>
|
||||||
#include <asm/apic.h>
|
#include <asm/apic.h>
|
||||||
|
#include <asm/io_apic.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
#include <asm/uv/uv.h>
|
#include <asm/uv/uv.h>
|
||||||
#include <linux/mc146818rtc.h>
|
#include <linux/mc146818rtc.h>
|
||||||
|
@ -945,6 +946,14 @@ int __cpuinit native_cpu_up(unsigned int cpu)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* arch_disable_smp_support() - disables SMP support for x86 at runtime
|
||||||
|
*/
|
||||||
|
void arch_disable_smp_support(void)
|
||||||
|
{
|
||||||
|
disable_ioapic_support();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fall back to non SMP mode after errors.
|
* Fall back to non SMP mode after errors.
|
||||||
*
|
*
|
||||||
|
@ -1045,7 +1054,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
|
||||||
"(tell your hw vendor)\n");
|
"(tell your hw vendor)\n");
|
||||||
}
|
}
|
||||||
smpboot_clear_io_apic();
|
smpboot_clear_io_apic();
|
||||||
arch_disable_smp_support();
|
disable_ioapic_support();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue