mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86/apic updates from Thomas Gleixner: "This is a major overhaul to the x86 apic subsystem consisting of the following parts: - Remove obsolete APIC driver abstractions (David Rientjes) - Use the irqdomain facilities to dynamically allocate IRQs for IOAPICs. This is a prerequisite to enable IOAPIC hotplug support, and it also frees up wasted vectors (Jiang Liu) - Misc fixlets. Despite the hickup in Ingos previous pull request - caused by the missing fixup for the suspend/resume issue reported by Borislav - I strongly recommend that this update finds its way into 3.17. Some history for you: This is preparatory work for physical IOAPIC hotplug. The first attempt to support this was done by Yinghai and I shot it down because it just added another layer of obscurity and complexity to the already existing mess without tackling the underlying shortcomings of the current implementation. After quite some on- and offlist discussions, I requested that the design of this functionality must use generic infrastructure, i.e. irq domains, which provide all the mechanisms to dynamically map linux interrupt numbers to physical interrupts. Jiang picked up the idea and did a great job of consolidating the existing interfaces to manage the x86 (IOAPIC) interrupt system by utilizing irq domains. The testing in tip, Linux-next and inside of Intel on various machines did not unearth any oddities until Borislav exposed it to one of his oddball machines. The issue was resolved quickly, but unfortunately the fix fell through the cracks and did not hit the tip tree before Ingo sent the pull request. Not entirely Ingos fault, I also assumed that the fix was already merged when Ingo asked me whether he could send it. Nevertheless this work has a proper design, has undergone several rounds of review and the final fallout after applying it to tip and integrating it into Linux-next has been more than moderate. It's the ground work not only for IOAPIC hotplug, it will also allow us to move the lowlevel vector allocation into the irqdomain hierarchy, which will benefit other architectures as well. Patches are posted already, but they are on hold for two weeks, see below. I really appreciate the competence and responsiveness Jiang has shown in course of this endavour. So I'm sure that any fallout of this will be addressed in a timely manner. FYI, I'm vanishing for 2 weeks into my annual kids summer camp kitchen duty^Wvacation, while you folks are drooling at KS/LinuxCon :) But HPA will have a look at the hopefully zero fallout until I'm back" * 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (53 commits) x86, irq, PCI: Keep IRQ assignment for PCI devices during suspend/hibernation x86/apic/vsmp: Make is_vsmp_box() static x86, apic: Remove enable_apic_mode callback x86, apic: Remove setup_portio_remap callback x86, apic: Remove multi_timer_check callback x86, apic: Replace noop_check_apicid_used x86, apic: Remove check_apicid_present callback x86, apic: Remove mps_oem_check callback x86, apic: Remove smp_callin_clear_local_apic callback x86, apic: Replace trampoline physical addresses with defaults x86, apic: Remove x86_32_numa_cpu_node callback x86: intel-mid: Use the new io_apic interfaces x86, vsmp: Remove is_vsmp_box() from apic_is_clustered_box() x86, irq: Clean up irqdomain transition code x86, irq, devicetree: Release IOAPIC pin when PCI device is disabled x86, irq, SFI: Release IOAPIC pin when PCI device is disabled x86, irq, mpparse: Release IOAPIC pin when PCI device is disabled x86, irq, ACPI: Release IOAPIC pin when PCI device is disabled x86, irq: Introduce helper functions to release IOAPIC pin x86, irq: Simplify the way to handle ISA IRQ ...
This commit is contained in:
commit
81c02a21b2
@ -434,6 +434,7 @@ config X86_INTEL_CE
|
||||
bool "CE4100 TV platform"
|
||||
depends on PCI
|
||||
depends on PCI_GODIRECT
|
||||
depends on X86_IO_APIC
|
||||
depends on X86_32
|
||||
depends on X86_EXTENDED_PLATFORM
|
||||
select X86_REBOOTFIXUPS
|
||||
@ -840,6 +841,7 @@ config X86_IO_APIC
|
||||
def_bool y
|
||||
depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC || PCI_MSI
|
||||
select GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
|
||||
select IRQ_DOMAIN
|
||||
|
||||
config X86_REROUTE_FOR_BROKEN_BOOT_IRQS
|
||||
bool "Reroute for broken boot IRQs"
|
||||
|
@ -85,14 +85,6 @@ static inline bool apic_from_smp_config(void)
|
||||
#include <asm/paravirt.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
extern int is_vsmp_box(void);
|
||||
#else
|
||||
static inline int is_vsmp_box(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
extern int setup_profiling_timer(unsigned int);
|
||||
|
||||
static inline void native_apic_mem_write(u32 reg, u32 v)
|
||||
@ -300,7 +292,6 @@ struct apic {
|
||||
|
||||
int dest_logical;
|
||||
unsigned long (*check_apicid_used)(physid_mask_t *map, int apicid);
|
||||
unsigned long (*check_apicid_present)(int apicid);
|
||||
|
||||
void (*vector_allocation_domain)(int cpu, struct cpumask *retmask,
|
||||
const struct cpumask *mask);
|
||||
@ -309,21 +300,11 @@ struct apic {
|
||||
void (*ioapic_phys_id_map)(physid_mask_t *phys_map, physid_mask_t *retmap);
|
||||
|
||||
void (*setup_apic_routing)(void);
|
||||
int (*multi_timer_check)(int apic, int irq);
|
||||
int (*cpu_present_to_apicid)(int mps_cpu);
|
||||
void (*apicid_to_cpu_present)(int phys_apicid, physid_mask_t *retmap);
|
||||
void (*setup_portio_remap)(void);
|
||||
int (*check_phys_apicid_present)(int phys_apicid);
|
||||
void (*enable_apic_mode)(void);
|
||||
int (*phys_pkg_id)(int cpuid_apic, int index_msb);
|
||||
|
||||
/*
|
||||
* When one of the next two hooks returns 1 the apic
|
||||
* is switched to this. Essentially they are additional
|
||||
* probe functions:
|
||||
*/
|
||||
int (*mps_oem_check)(struct mpc_table *mpc, char *oem, char *productid);
|
||||
|
||||
unsigned int (*get_apic_id)(unsigned long x);
|
||||
unsigned long (*set_apic_id)(unsigned int id);
|
||||
unsigned long apic_id_mask;
|
||||
@ -343,11 +324,7 @@ struct apic {
|
||||
/* wakeup_secondary_cpu */
|
||||
int (*wakeup_secondary_cpu)(int apicid, unsigned long start_eip);
|
||||
|
||||
int trampoline_phys_low;
|
||||
int trampoline_phys_high;
|
||||
|
||||
bool wait_for_init_deassert;
|
||||
void (*smp_callin_clear_local_apic)(void);
|
||||
void (*inquire_remote_apic)(int apicid);
|
||||
|
||||
/* apic ops */
|
||||
@ -378,14 +355,6 @@ struct apic {
|
||||
* won't be applied properly during early boot in this case.
|
||||
*/
|
||||
int (*x86_32_early_logical_apicid)(int cpu);
|
||||
|
||||
/*
|
||||
* Optional method called from setup_local_APIC() after logical
|
||||
* apicid is guaranteed to be known to initialize apicid -> node
|
||||
* mapping if NUMA initialization hasn't done so already. Don't
|
||||
* add new users.
|
||||
*/
|
||||
int (*x86_32_numa_cpu_node)(int cpu);
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -496,14 +465,12 @@ static inline unsigned default_get_apic_id(unsigned long x)
|
||||
}
|
||||
|
||||
/*
|
||||
* Warm reset vector default position:
|
||||
* Warm reset vector position:
|
||||
*/
|
||||
#define DEFAULT_TRAMPOLINE_PHYS_LOW 0x467
|
||||
#define DEFAULT_TRAMPOLINE_PHYS_HIGH 0x469
|
||||
#define TRAMPOLINE_PHYS_LOW 0x467
|
||||
#define TRAMPOLINE_PHYS_HIGH 0x469
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
extern int default_acpi_madt_oem_check(char *, char *);
|
||||
|
||||
extern void apic_send_IPI_self(int vector);
|
||||
|
||||
DECLARE_PER_CPU(int, x2apic_extra_bits);
|
||||
@ -552,6 +519,8 @@ static inline int default_apic_id_valid(int apicid)
|
||||
return (apicid < 255);
|
||||
}
|
||||
|
||||
extern int default_acpi_madt_oem_check(char *, char *);
|
||||
|
||||
extern void default_setup_apic_routing(void);
|
||||
|
||||
extern struct apic apic_noop;
|
||||
@ -635,11 +604,6 @@ static inline unsigned long default_check_apicid_used(physid_mask_t *map, int ap
|
||||
return physid_isset(apicid, *map);
|
||||
}
|
||||
|
||||
static inline unsigned long default_check_apicid_present(int bit)
|
||||
{
|
||||
return physid_isset(bit, phys_cpu_present_map);
|
||||
}
|
||||
|
||||
static inline void default_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
|
||||
{
|
||||
*retmap = *phys_map;
|
||||
|
@ -40,9 +40,6 @@ typedef struct {
|
||||
|
||||
DECLARE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat);
|
||||
|
||||
/* We can have at most NR_VECTORS irqs routed to a cpu at a time */
|
||||
#define MAX_HARDIRQS_PER_CPU NR_VECTORS
|
||||
|
||||
#define __ARCH_IRQ_STAT
|
||||
|
||||
#define inc_irq_stat(member) this_cpu_inc(irq_stat.member)
|
||||
|
@ -67,4 +67,9 @@ struct legacy_pic {
|
||||
extern struct legacy_pic *legacy_pic;
|
||||
extern struct legacy_pic null_legacy_pic;
|
||||
|
||||
static inline int nr_legacy_irqs(void)
|
||||
{
|
||||
return legacy_pic->nr_legacy_irqs;
|
||||
}
|
||||
|
||||
#endif /* _ASM_X86_I8259_H */
|
||||
|
@ -98,6 +98,8 @@ struct IR_IO_APIC_route_entry {
|
||||
#define IOAPIC_AUTO -1
|
||||
#define IOAPIC_EDGE 0
|
||||
#define IOAPIC_LEVEL 1
|
||||
#define IOAPIC_MAP_ALLOC 0x1
|
||||
#define IOAPIC_MAP_CHECK 0x2
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
|
||||
@ -118,9 +120,6 @@ extern int mp_irq_entries;
|
||||
/* MP IRQ source entries */
|
||||
extern struct mpc_intsrc mp_irqs[MAX_IRQ_SOURCES];
|
||||
|
||||
/* non-0 if default (table-less) MP configuration */
|
||||
extern int mpc_default_type;
|
||||
|
||||
/* Older SiS APIC requires we rewrite the index register */
|
||||
extern int sis_apic_bug;
|
||||
|
||||
@ -133,9 +132,6 @@ extern int noioapicquirk;
|
||||
/* -1 if "noapic" boot option passed */
|
||||
extern int noioapicreroute;
|
||||
|
||||
/* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */
|
||||
extern int timer_through_8259;
|
||||
|
||||
/*
|
||||
* If we use the IO-APIC for IRQ routing, disable automatic
|
||||
* assignment of PCI IRQ's.
|
||||
@ -145,14 +141,8 @@ extern int timer_through_8259;
|
||||
|
||||
struct io_apic_irq_attr;
|
||||
struct irq_cfg;
|
||||
extern int io_apic_set_pci_routing(struct device *dev, int irq,
|
||||
struct io_apic_irq_attr *irq_attr);
|
||||
void setup_IO_APIC_irq_extra(u32 gsi);
|
||||
extern void ioapic_insert_resources(void);
|
||||
|
||||
extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *,
|
||||
unsigned int, int,
|
||||
struct io_apic_irq_attr *);
|
||||
extern int native_setup_ioapic_entry(int, struct IO_APIC_route_entry *,
|
||||
unsigned int, int,
|
||||
struct io_apic_irq_attr *);
|
||||
@ -162,7 +152,6 @@ extern void native_compose_msi_msg(struct pci_dev *pdev,
|
||||
unsigned int irq, unsigned int dest,
|
||||
struct msi_msg *msg, u8 hpet_id);
|
||||
extern void native_eoi_ioapic_pin(int apic, int pin, int vector);
|
||||
int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr);
|
||||
|
||||
extern int save_ioapic_entries(void);
|
||||
extern void mask_ioapic_entries(void);
|
||||
@ -171,15 +160,40 @@ extern int restore_ioapic_entries(void);
|
||||
extern void setup_ioapic_ids_from_mpc(void);
|
||||
extern void setup_ioapic_ids_from_mpc_nocheck(void);
|
||||
|
||||
enum ioapic_domain_type {
|
||||
IOAPIC_DOMAIN_INVALID,
|
||||
IOAPIC_DOMAIN_LEGACY,
|
||||
IOAPIC_DOMAIN_STRICT,
|
||||
IOAPIC_DOMAIN_DYNAMIC,
|
||||
};
|
||||
|
||||
struct device_node;
|
||||
struct irq_domain;
|
||||
struct irq_domain_ops;
|
||||
|
||||
struct ioapic_domain_cfg {
|
||||
enum ioapic_domain_type type;
|
||||
const struct irq_domain_ops *ops;
|
||||
struct device_node *dev;
|
||||
};
|
||||
|
||||
struct mp_ioapic_gsi{
|
||||
u32 gsi_base;
|
||||
u32 gsi_end;
|
||||
};
|
||||
extern struct mp_ioapic_gsi mp_gsi_routing[];
|
||||
extern u32 gsi_top;
|
||||
int mp_find_ioapic(u32 gsi);
|
||||
int mp_find_ioapic_pin(int ioapic, u32 gsi);
|
||||
void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
|
||||
|
||||
extern int mp_find_ioapic(u32 gsi);
|
||||
extern int mp_find_ioapic_pin(int ioapic, u32 gsi);
|
||||
extern u32 mp_pin_to_gsi(int ioapic, int pin);
|
||||
extern int mp_map_gsi_to_irq(u32 gsi, unsigned int flags);
|
||||
extern void mp_unmap_irq(int irq);
|
||||
extern void __init mp_register_ioapic(int id, u32 address, u32 gsi_base,
|
||||
struct ioapic_domain_cfg *cfg);
|
||||
extern int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
|
||||
irq_hw_number_t hwirq);
|
||||
extern void mp_irqdomain_unmap(struct irq_domain *domain, unsigned int virq);
|
||||
extern int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node);
|
||||
extern void __init pre_init_apic_IRQ0(void);
|
||||
|
||||
extern void mp_save_irq(struct mpc_intsrc *m);
|
||||
@ -217,14 +231,12 @@ extern void io_apic_eoi(unsigned int apic, unsigned int vector);
|
||||
|
||||
#define io_apic_assign_pci_irqs 0
|
||||
#define setup_ioapic_ids_from_mpc x86_init_noop
|
||||
static const int timer_through_8259 = 0;
|
||||
static inline void ioapic_insert_resources(void) { }
|
||||
#define gsi_top (NR_IRQS_LEGACY)
|
||||
static inline int mp_find_ioapic(u32 gsi) { return 0; }
|
||||
|
||||
struct io_apic_irq_attr;
|
||||
static inline int io_apic_set_pci_routing(struct device *dev, int irq,
|
||||
struct io_apic_irq_attr *irq_attr) { return 0; }
|
||||
static inline u32 mp_pin_to_gsi(int ioapic, int pin) { return UINT_MAX; }
|
||||
static inline int mp_map_gsi_to_irq(u32 gsi, unsigned int flags) { return gsi; }
|
||||
static inline void mp_unmap_irq(int irq) { }
|
||||
|
||||
static inline int save_ioapic_entries(void)
|
||||
{
|
||||
|
@ -40,8 +40,6 @@ extern int mp_bus_id_to_type[MAX_MP_BUSSES];
|
||||
extern DECLARE_BITMAP(mp_bus_not_pci, MAX_MP_BUSSES);
|
||||
|
||||
extern unsigned int boot_cpu_physical_apicid;
|
||||
extern unsigned int max_physical_apicid;
|
||||
extern int mpc_default_type;
|
||||
extern unsigned long mp_lapic_addr;
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
@ -88,15 +86,6 @@ static inline void early_reserve_e820_mpc_new(void) { }
|
||||
#endif
|
||||
|
||||
int generic_processor_info(int apicid, int version);
|
||||
#ifdef CONFIG_ACPI
|
||||
extern void mp_register_ioapic(int id, u32 address, u32 gsi_base);
|
||||
extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
|
||||
u32 gsi);
|
||||
extern void mp_config_acpi_legacy_irqs(void);
|
||||
struct device;
|
||||
extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level,
|
||||
int active_high_low);
|
||||
#endif /* CONFIG_ACPI */
|
||||
|
||||
#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_LOCAL_APIC)
|
||||
|
||||
@ -161,8 +150,4 @@ static inline void physid_set_mask_of_physid(int physid, physid_mask_t *map)
|
||||
|
||||
extern physid_mask_t phys_cpu_present_map;
|
||||
|
||||
extern int generic_mps_oem_check(struct mpc_table *, char *, char *);
|
||||
|
||||
extern int default_acpi_madt_oem_check(char *, char *);
|
||||
|
||||
#endif /* _ASM_X86_MPSPEC_H */
|
||||
|
@ -26,12 +26,10 @@
|
||||
extern int of_ioapic;
|
||||
extern u64 initial_dtb;
|
||||
extern void add_dtb(u64 data);
|
||||
extern void x86_add_irq_domains(void);
|
||||
void x86_of_pci_init(void);
|
||||
void x86_dtb_init(void);
|
||||
#else
|
||||
static inline void add_dtb(u64 data) { }
|
||||
static inline void x86_add_irq_domains(void) { }
|
||||
static inline void x86_of_pci_init(void) { }
|
||||
static inline void x86_dtb_init(void) { }
|
||||
#define of_ioapic 0
|
||||
|
@ -17,11 +17,11 @@ static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
|
||||
spin_unlock_irqrestore(&rtc_lock, flags);
|
||||
local_flush_tlb();
|
||||
pr_debug("1.\n");
|
||||
*((volatile unsigned short *)phys_to_virt(apic->trampoline_phys_high)) =
|
||||
start_eip >> 4;
|
||||
*((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) =
|
||||
start_eip >> 4;
|
||||
pr_debug("2.\n");
|
||||
*((volatile unsigned short *)phys_to_virt(apic->trampoline_phys_low)) =
|
||||
start_eip & 0xf;
|
||||
*((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) =
|
||||
start_eip & 0xf;
|
||||
pr_debug("3.\n");
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ static inline void smpboot_restore_warm_reset_vector(void)
|
||||
CMOS_WRITE(0, 0xf);
|
||||
spin_unlock_irqrestore(&rtc_lock, flags);
|
||||
|
||||
*((volatile u32 *)phys_to_virt(apic->trampoline_phys_low)) = 0;
|
||||
*((volatile u32 *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0;
|
||||
}
|
||||
|
||||
static inline void __init smpboot_setup_io_apic(void)
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/ioport.h>
|
||||
@ -43,6 +44,7 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/mpspec.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/i8259.h>
|
||||
|
||||
#include "sleep.h" /* To include x86_acpi_suspend_lowlevel */
|
||||
static int __initdata acpi_force = 0;
|
||||
@ -93,44 +95,7 @@ static u32 isa_irq_to_gsi[NR_IRQS_LEGACY] __read_mostly = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
|
||||
};
|
||||
|
||||
static unsigned int gsi_to_irq(unsigned int gsi)
|
||||
{
|
||||
unsigned int irq = gsi + NR_IRQS_LEGACY;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < NR_IRQS_LEGACY; i++) {
|
||||
if (isa_irq_to_gsi[i] == gsi) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Provide an identity mapping of gsi == irq
|
||||
* except on truly weird platforms that have
|
||||
* non isa irqs in the first 16 gsis.
|
||||
*/
|
||||
if (gsi >= NR_IRQS_LEGACY)
|
||||
irq = gsi;
|
||||
else
|
||||
irq = gsi_top + gsi;
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
static u32 irq_to_gsi(int irq)
|
||||
{
|
||||
unsigned int gsi;
|
||||
|
||||
if (irq < NR_IRQS_LEGACY)
|
||||
gsi = isa_irq_to_gsi[irq];
|
||||
else if (irq < gsi_top)
|
||||
gsi = irq;
|
||||
else if (irq < (gsi_top + NR_IRQS_LEGACY))
|
||||
gsi = irq - gsi_top;
|
||||
else
|
||||
gsi = 0xffffffff;
|
||||
|
||||
return gsi;
|
||||
}
|
||||
#define ACPI_INVALID_GSI INT_MIN
|
||||
|
||||
/*
|
||||
* This is just a simple wrapper around early_ioremap(),
|
||||
@ -341,11 +306,145 @@ acpi_parse_lapic_nmi(struct acpi_subtable_header * header, const unsigned long e
|
||||
#endif /*CONFIG_X86_LOCAL_APIC */
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
#define MP_ISA_BUS 0
|
||||
|
||||
static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
|
||||
u32 gsi)
|
||||
{
|
||||
int ioapic;
|
||||
int pin;
|
||||
struct mpc_intsrc mp_irq;
|
||||
|
||||
/*
|
||||
* Convert 'gsi' to 'ioapic.pin'.
|
||||
*/
|
||||
ioapic = mp_find_ioapic(gsi);
|
||||
if (ioapic < 0)
|
||||
return;
|
||||
pin = mp_find_ioapic_pin(ioapic, gsi);
|
||||
|
||||
/*
|
||||
* TBD: This check is for faulty timer entries, where the override
|
||||
* erroneously sets the trigger to level, resulting in a HUGE
|
||||
* increase of timer interrupts!
|
||||
*/
|
||||
if ((bus_irq == 0) && (trigger == 3))
|
||||
trigger = 1;
|
||||
|
||||
mp_irq.type = MP_INTSRC;
|
||||
mp_irq.irqtype = mp_INT;
|
||||
mp_irq.irqflag = (trigger << 2) | polarity;
|
||||
mp_irq.srcbus = MP_ISA_BUS;
|
||||
mp_irq.srcbusirq = bus_irq; /* IRQ */
|
||||
mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
|
||||
mp_irq.dstirq = pin; /* INTIN# */
|
||||
|
||||
mp_save_irq(&mp_irq);
|
||||
|
||||
/*
|
||||
* Reset default identity mapping if gsi is also an legacy IRQ,
|
||||
* otherwise there will be more than one entry with the same GSI
|
||||
* and acpi_isa_irq_to_gsi() may give wrong result.
|
||||
*/
|
||||
if (gsi < nr_legacy_irqs() && isa_irq_to_gsi[gsi] == gsi)
|
||||
isa_irq_to_gsi[gsi] = ACPI_INVALID_GSI;
|
||||
isa_irq_to_gsi[bus_irq] = gsi;
|
||||
}
|
||||
|
||||
static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
|
||||
int polarity)
|
||||
{
|
||||
#ifdef CONFIG_X86_MPPARSE
|
||||
struct mpc_intsrc mp_irq;
|
||||
struct pci_dev *pdev;
|
||||
unsigned char number;
|
||||
unsigned int devfn;
|
||||
int ioapic;
|
||||
u8 pin;
|
||||
|
||||
if (!acpi_ioapic)
|
||||
return 0;
|
||||
if (!dev || !dev_is_pci(dev))
|
||||
return 0;
|
||||
|
||||
pdev = to_pci_dev(dev);
|
||||
number = pdev->bus->number;
|
||||
devfn = pdev->devfn;
|
||||
pin = pdev->pin;
|
||||
/* print the entry should happen on mptable identically */
|
||||
mp_irq.type = MP_INTSRC;
|
||||
mp_irq.irqtype = mp_INT;
|
||||
mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
|
||||
(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
|
||||
mp_irq.srcbus = number;
|
||||
mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
|
||||
ioapic = mp_find_ioapic(gsi);
|
||||
mp_irq.dstapic = mpc_ioapic_id(ioapic);
|
||||
mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
|
||||
|
||||
mp_save_irq(&mp_irq);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mp_register_gsi(struct device *dev, u32 gsi, int trigger,
|
||||
int polarity)
|
||||
{
|
||||
int irq, node;
|
||||
|
||||
if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
|
||||
return gsi;
|
||||
|
||||
/* Don't set up the ACPI SCI because it's already set up */
|
||||
if (acpi_gbl_FADT.sci_interrupt == gsi)
|
||||
return gsi;
|
||||
|
||||
trigger = trigger == ACPI_EDGE_SENSITIVE ? 0 : 1;
|
||||
polarity = polarity == ACPI_ACTIVE_HIGH ? 0 : 1;
|
||||
node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
|
||||
if (mp_set_gsi_attr(gsi, trigger, polarity, node)) {
|
||||
pr_warn("Failed to set pin attr for GSI%d\n", gsi);
|
||||
return -1;
|
||||
}
|
||||
|
||||
irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
if (enable_update_mptable)
|
||||
mp_config_acpi_gsi(dev, gsi, trigger, polarity);
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
||||
static void mp_unregister_gsi(u32 gsi)
|
||||
{
|
||||
int irq;
|
||||
|
||||
if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
|
||||
return;
|
||||
|
||||
if (acpi_gbl_FADT.sci_interrupt == gsi)
|
||||
return;
|
||||
|
||||
irq = mp_map_gsi_to_irq(gsi, 0);
|
||||
if (irq > 0)
|
||||
mp_unmap_irq(irq);
|
||||
}
|
||||
|
||||
static struct irq_domain_ops acpi_irqdomain_ops = {
|
||||
.map = mp_irqdomain_map,
|
||||
.unmap = mp_irqdomain_unmap,
|
||||
};
|
||||
|
||||
static int __init
|
||||
acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
|
||||
{
|
||||
struct acpi_madt_io_apic *ioapic = NULL;
|
||||
struct ioapic_domain_cfg cfg = {
|
||||
.type = IOAPIC_DOMAIN_DYNAMIC,
|
||||
.ops = &acpi_irqdomain_ops,
|
||||
};
|
||||
|
||||
ioapic = (struct acpi_madt_io_apic *)header;
|
||||
|
||||
@ -354,8 +453,12 @@ acpi_parse_ioapic(struct acpi_subtable_header * header, const unsigned long end)
|
||||
|
||||
acpi_table_print_madt_entry(header);
|
||||
|
||||
mp_register_ioapic(ioapic->id,
|
||||
ioapic->address, ioapic->global_irq_base);
|
||||
/* Statically assign IRQ numbers for IOAPICs hosting legacy IRQs */
|
||||
if (ioapic->global_irq_base < nr_legacy_irqs())
|
||||
cfg.type = IOAPIC_DOMAIN_LEGACY;
|
||||
|
||||
mp_register_ioapic(ioapic->id, ioapic->address, ioapic->global_irq_base,
|
||||
&cfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -378,11 +481,6 @@ static void __init acpi_sci_ioapic_setup(u8 bus_irq, u16 polarity, u16 trigger,
|
||||
if (acpi_sci_flags & ACPI_MADT_POLARITY_MASK)
|
||||
polarity = acpi_sci_flags & ACPI_MADT_POLARITY_MASK;
|
||||
|
||||
/*
|
||||
* mp_config_acpi_legacy_irqs() already setup IRQs < 16
|
||||
* If GSI is < 16, this will update its flags,
|
||||
* else it will create a new mp_irqs[] entry.
|
||||
*/
|
||||
mp_override_legacy_irq(bus_irq, polarity, trigger, gsi);
|
||||
|
||||
/*
|
||||
@ -504,25 +602,28 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
|
||||
outb(new >> 8, 0x4d1);
|
||||
}
|
||||
|
||||
int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
|
||||
int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
|
||||
{
|
||||
*irq = gsi_to_irq(gsi);
|
||||
int irq = mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC)
|
||||
setup_IO_APIC_irq_extra(gsi);
|
||||
#endif
|
||||
if (irq >= 0) {
|
||||
*irqp = irq;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
|
||||
|
||||
int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi)
|
||||
{
|
||||
if (isa_irq >= 16)
|
||||
return -1;
|
||||
*gsi = irq_to_gsi(isa_irq);
|
||||
return 0;
|
||||
if (isa_irq < nr_legacy_irqs() &&
|
||||
isa_irq_to_gsi[isa_irq] != ACPI_INVALID_GSI) {
|
||||
*gsi = isa_irq_to_gsi[isa_irq];
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int acpi_register_gsi_pic(struct device *dev, u32 gsi,
|
||||
@ -542,15 +643,25 @@ static int acpi_register_gsi_pic(struct device *dev, u32 gsi,
|
||||
static int acpi_register_gsi_ioapic(struct device *dev, u32 gsi,
|
||||
int trigger, int polarity)
|
||||
{
|
||||
int irq = gsi;
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
gsi = mp_register_gsi(dev, gsi, trigger, polarity);
|
||||
irq = mp_register_gsi(dev, gsi, trigger, polarity);
|
||||
#endif
|
||||
|
||||
return gsi;
|
||||
return irq;
|
||||
}
|
||||
|
||||
static void acpi_unregister_gsi_ioapic(u32 gsi)
|
||||
{
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
mp_unregister_gsi(gsi);
|
||||
#endif
|
||||
}
|
||||
|
||||
int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
|
||||
int trigger, int polarity) = acpi_register_gsi_pic;
|
||||
void (*__acpi_unregister_gsi)(u32 gsi) = NULL;
|
||||
|
||||
#ifdef CONFIG_ACPI_SLEEP
|
||||
int (*acpi_suspend_lowlevel)(void) = x86_acpi_suspend_lowlevel;
|
||||
@ -564,32 +675,22 @@ int (*acpi_suspend_lowlevel)(void);
|
||||
*/
|
||||
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
|
||||
{
|
||||
unsigned int irq;
|
||||
unsigned int plat_gsi = gsi;
|
||||
|
||||
plat_gsi = (*__acpi_register_gsi)(dev, gsi, trigger, polarity);
|
||||
irq = gsi_to_irq(plat_gsi);
|
||||
|
||||
return irq;
|
||||
return __acpi_register_gsi(dev, gsi, trigger, polarity);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_register_gsi);
|
||||
|
||||
void acpi_unregister_gsi(u32 gsi)
|
||||
{
|
||||
if (__acpi_unregister_gsi)
|
||||
__acpi_unregister_gsi(gsi);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
|
||||
|
||||
void __init acpi_set_irq_model_pic(void)
|
||||
{
|
||||
acpi_irq_model = ACPI_IRQ_MODEL_PIC;
|
||||
__acpi_register_gsi = acpi_register_gsi_pic;
|
||||
acpi_ioapic = 0;
|
||||
}
|
||||
|
||||
void __init acpi_set_irq_model_ioapic(void)
|
||||
static void __init acpi_set_irq_model_ioapic(void)
|
||||
{
|
||||
acpi_irq_model = ACPI_IRQ_MODEL_IOAPIC;
|
||||
__acpi_register_gsi = acpi_register_gsi_ioapic;
|
||||
__acpi_unregister_gsi = acpi_unregister_gsi_ioapic;
|
||||
acpi_ioapic = 1;
|
||||
}
|
||||
|
||||
@ -825,9 +926,8 @@ static int __init early_acpi_parse_madt_lapic_addr_ovr(void)
|
||||
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
|
||||
*/
|
||||
|
||||
count =
|
||||
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
|
||||
acpi_parse_lapic_addr_ovr, 0);
|
||||
count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
|
||||
acpi_parse_lapic_addr_ovr, 0);
|
||||
if (count < 0) {
|
||||
printk(KERN_ERR PREFIX
|
||||
"Error parsing LAPIC address override entry\n");
|
||||
@ -852,9 +952,8 @@ static int __init acpi_parse_madt_lapic_entries(void)
|
||||
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
|
||||
*/
|
||||
|
||||
count =
|
||||
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
|
||||
acpi_parse_lapic_addr_ovr, 0);
|
||||
count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE,
|
||||
acpi_parse_lapic_addr_ovr, 0);
|
||||
if (count < 0) {
|
||||
printk(KERN_ERR PREFIX
|
||||
"Error parsing LAPIC address override entry\n");
|
||||
@ -882,11 +981,10 @@ static int __init acpi_parse_madt_lapic_entries(void)
|
||||
return count;
|
||||
}
|
||||
|
||||
x2count =
|
||||
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
|
||||
acpi_parse_x2apic_nmi, 0);
|
||||
count =
|
||||
acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI, acpi_parse_lapic_nmi, 0);
|
||||
x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC_NMI,
|
||||
acpi_parse_x2apic_nmi, 0);
|
||||
count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_NMI,
|
||||
acpi_parse_lapic_nmi, 0);
|
||||
if (count < 0 || x2count < 0) {
|
||||
printk(KERN_ERR PREFIX "Error parsing LAPIC NMI entry\n");
|
||||
/* TBD: Cleanup to allow fallback to MPS */
|
||||
@ -897,44 +995,7 @@ static int __init acpi_parse_madt_lapic_entries(void)
|
||||
#endif /* CONFIG_X86_LOCAL_APIC */
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
#define MP_ISA_BUS 0
|
||||
|
||||
void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, u32 gsi)
|
||||
{
|
||||
int ioapic;
|
||||
int pin;
|
||||
struct mpc_intsrc mp_irq;
|
||||
|
||||
/*
|
||||
* Convert 'gsi' to 'ioapic.pin'.
|
||||
*/
|
||||
ioapic = mp_find_ioapic(gsi);
|
||||
if (ioapic < 0)
|
||||
return;
|
||||
pin = mp_find_ioapic_pin(ioapic, gsi);
|
||||
|
||||
/*
|
||||
* TBD: This check is for faulty timer entries, where the override
|
||||
* erroneously sets the trigger to level, resulting in a HUGE
|
||||
* increase of timer interrupts!
|
||||
*/
|
||||
if ((bus_irq == 0) && (trigger == 3))
|
||||
trigger = 1;
|
||||
|
||||
mp_irq.type = MP_INTSRC;
|
||||
mp_irq.irqtype = mp_INT;
|
||||
mp_irq.irqflag = (trigger << 2) | polarity;
|
||||
mp_irq.srcbus = MP_ISA_BUS;
|
||||
mp_irq.srcbusirq = bus_irq; /* IRQ */
|
||||
mp_irq.dstapic = mpc_ioapic_id(ioapic); /* APIC ID */
|
||||
mp_irq.dstirq = pin; /* INTIN# */
|
||||
|
||||
mp_save_irq(&mp_irq);
|
||||
|
||||
isa_irq_to_gsi[bus_irq] = gsi;
|
||||
}
|
||||
|
||||
void __init mp_config_acpi_legacy_irqs(void)
|
||||
static void __init mp_config_acpi_legacy_irqs(void)
|
||||
{
|
||||
int i;
|
||||
struct mpc_intsrc mp_irq;
|
||||
@ -952,7 +1013,7 @@ void __init mp_config_acpi_legacy_irqs(void)
|
||||
* Use the default configuration for the IRQs 0-15. Unless
|
||||
* overridden by (MADT) interrupt source override entries.
|
||||
*/
|
||||
for (i = 0; i < 16; i++) {
|
||||
for (i = 0; i < nr_legacy_irqs(); i++) {
|
||||
int ioapic, pin;
|
||||
unsigned int dstapic;
|
||||
int idx;
|
||||
@ -1000,84 +1061,6 @@ void __init mp_config_acpi_legacy_irqs(void)
|
||||
}
|
||||
}
|
||||
|
||||
static int mp_config_acpi_gsi(struct device *dev, u32 gsi, int trigger,
|
||||
int polarity)
|
||||
{
|
||||
#ifdef CONFIG_X86_MPPARSE
|
||||
struct mpc_intsrc mp_irq;
|
||||
struct pci_dev *pdev;
|
||||
unsigned char number;
|
||||
unsigned int devfn;
|
||||
int ioapic;
|
||||
u8 pin;
|
||||
|
||||
if (!acpi_ioapic)
|
||||
return 0;
|
||||
if (!dev || !dev_is_pci(dev))
|
||||
return 0;
|
||||
|
||||
pdev = to_pci_dev(dev);
|
||||
number = pdev->bus->number;
|
||||
devfn = pdev->devfn;
|
||||
pin = pdev->pin;
|
||||
/* print the entry should happen on mptable identically */
|
||||
mp_irq.type = MP_INTSRC;
|
||||
mp_irq.irqtype = mp_INT;
|
||||
mp_irq.irqflag = (trigger == ACPI_EDGE_SENSITIVE ? 4 : 0x0c) |
|
||||
(polarity == ACPI_ACTIVE_HIGH ? 1 : 3);
|
||||
mp_irq.srcbus = number;
|
||||
mp_irq.srcbusirq = (((devfn >> 3) & 0x1f) << 2) | ((pin - 1) & 3);
|
||||
ioapic = mp_find_ioapic(gsi);
|
||||
mp_irq.dstapic = mpc_ioapic_id(ioapic);
|
||||
mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
|
||||
|
||||
mp_save_irq(&mp_irq);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
|
||||
{
|
||||
int ioapic;
|
||||
int ioapic_pin;
|
||||
struct io_apic_irq_attr irq_attr;
|
||||
int ret;
|
||||
|
||||
if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
|
||||
return gsi;
|
||||
|
||||
/* Don't set up the ACPI SCI because it's already set up */
|
||||
if (acpi_gbl_FADT.sci_interrupt == gsi)
|
||||
return gsi;
|
||||
|
||||
ioapic = mp_find_ioapic(gsi);
|
||||
if (ioapic < 0) {
|
||||
printk(KERN_WARNING "No IOAPIC for GSI %u\n", gsi);
|
||||
return gsi;
|
||||
}
|
||||
|
||||
ioapic_pin = mp_find_ioapic_pin(ioapic, gsi);
|
||||
|
||||
if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
|
||||
printk(KERN_ERR "Invalid reference to IOAPIC pin "
|
||||
"%d-%d\n", mpc_ioapic_id(ioapic),
|
||||
ioapic_pin);
|
||||
return gsi;
|
||||
}
|
||||
|
||||
if (enable_update_mptable)
|
||||
mp_config_acpi_gsi(dev, gsi, trigger, polarity);
|
||||
|
||||
set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
|
||||
trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
|
||||
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
|
||||
ret = io_apic_set_pci_routing(dev, gsi_to_irq(gsi), &irq_attr);
|
||||
if (ret < 0)
|
||||
gsi = INT_MIN;
|
||||
|
||||
return gsi;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse IOAPIC related entries in MADT
|
||||
* returns 0 on success, < 0 on error
|
||||
@ -1107,9 +1090,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
count =
|
||||
acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
|
||||
MAX_IO_APICS);
|
||||
count = acpi_table_parse_madt(ACPI_MADT_TYPE_IO_APIC, acpi_parse_ioapic,
|
||||
MAX_IO_APICS);
|
||||
if (!count) {
|
||||
printk(KERN_ERR PREFIX "No IOAPIC entries present\n");
|
||||
return -ENODEV;
|
||||
@ -1118,9 +1100,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
|
||||
return count;
|
||||
}
|
||||
|
||||
count =
|
||||
acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr,
|
||||
nr_irqs);
|
||||
count = acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE,
|
||||
acpi_parse_int_src_ovr, nr_irqs);
|
||||
if (count < 0) {
|
||||
printk(KERN_ERR PREFIX
|
||||
"Error parsing interrupt source overrides entry\n");
|
||||
@ -1139,9 +1120,8 @@ static int __init acpi_parse_madt_ioapic_entries(void)
|
||||
/* Fill in identity legacy mappings where no override */
|
||||
mp_config_acpi_legacy_irqs();
|
||||
|
||||
count =
|
||||
acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src,
|
||||
nr_irqs);
|
||||
count = acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE,
|
||||
acpi_parse_nmi_src, nr_irqs);
|
||||
if (count < 0) {
|
||||
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
|
||||
/* TBD: Cleanup to allow fallback to MPS */
|
||||
|
@ -67,7 +67,7 @@ EXPORT_SYMBOL_GPL(boot_cpu_physical_apicid);
|
||||
/*
|
||||
* The highest APIC ID seen during enumeration.
|
||||
*/
|
||||
unsigned int max_physical_apicid;
|
||||
static unsigned int max_physical_apicid;
|
||||
|
||||
/*
|
||||
* Bitmask of physically existing CPUs:
|
||||
@ -1342,17 +1342,6 @@ void setup_local_APIC(void)
|
||||
/* always use the value from LDR */
|
||||
early_per_cpu(x86_cpu_to_logical_apicid, cpu) =
|
||||
logical_smp_processor_id();
|
||||
|
||||
/*
|
||||
* Some NUMA implementations (NUMAQ) don't initialize apicid to
|
||||
* node mapping during NUMA init. Now that logical apicid is
|
||||
* guaranteed to be known, give it another chance. This is already
|
||||
* a bit too late - percpu allocation has already happened without
|
||||
* proper NUMA affinity.
|
||||
*/
|
||||
if (apic->x86_32_numa_cpu_node)
|
||||
set_apicid_to_node(early_per_cpu(x86_cpu_to_apicid, cpu),
|
||||
apic->x86_32_numa_cpu_node(cpu));
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -2053,8 +2042,6 @@ void __init connect_bsp_APIC(void)
|
||||
imcr_pic_to_apic();
|
||||
}
|
||||
#endif
|
||||
if (apic->enable_apic_mode)
|
||||
apic->enable_apic_mode();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2451,51 +2438,6 @@ static void apic_pm_activate(void) { }
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
|
||||
static int apic_cluster_num(void)
|
||||
{
|
||||
int i, clusters, zeros;
|
||||
unsigned id;
|
||||
u16 *bios_cpu_apicid;
|
||||
DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
|
||||
|
||||
bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
|
||||
bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
|
||||
|
||||
for (i = 0; i < nr_cpu_ids; i++) {
|
||||
/* are we being called early in kernel startup? */
|
||||
if (bios_cpu_apicid) {
|
||||
id = bios_cpu_apicid[i];
|
||||
} else if (i < nr_cpu_ids) {
|
||||
if (cpu_present(i))
|
||||
id = per_cpu(x86_bios_cpu_apicid, i);
|
||||
else
|
||||
continue;
|
||||
} else
|
||||
break;
|
||||
|
||||
if (id != BAD_APICID)
|
||||
__set_bit(APIC_CLUSTERID(id), clustermap);
|
||||
}
|
||||
|
||||
/* Problem: Partially populated chassis may not have CPUs in some of
|
||||
* the APIC clusters they have been allocated. Only present CPUs have
|
||||
* x86_bios_cpu_apicid entries, thus causing zeroes in the bitmap.
|
||||
* Since clusters are allocated sequentially, count zeros only if
|
||||
* they are bounded by ones.
|
||||
*/
|
||||
clusters = 0;
|
||||
zeros = 0;
|
||||
for (i = 0; i < NUM_APIC_CLUSTERS; i++) {
|
||||
if (test_bit(i, clustermap)) {
|
||||
clusters += 1 + zeros;
|
||||
zeros = 0;
|
||||
} else
|
||||
++zeros;
|
||||
}
|
||||
|
||||
return clusters;
|
||||
}
|
||||
|
||||
static int multi_checked;
|
||||
static int multi;
|
||||
|
||||
@ -2540,20 +2482,7 @@ static void dmi_check_multi(void)
|
||||
int apic_is_clustered_box(void)
|
||||
{
|
||||
dmi_check_multi();
|
||||
if (multi)
|
||||
return 1;
|
||||
|
||||
if (!is_vsmp_box())
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* ScaleMP vSMPowered boxes have one cluster per board and TSCs are
|
||||
* not guaranteed to be synced between boards
|
||||
*/
|
||||
if (apic_cluster_num() > 1)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return multi;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -168,21 +168,16 @@ static struct apic apic_flat = {
|
||||
.disable_esr = 0,
|
||||
.dest_logical = APIC_DEST_LOGICAL,
|
||||
.check_apicid_used = NULL,
|
||||
.check_apicid_present = NULL,
|
||||
|
||||
.vector_allocation_domain = flat_vector_allocation_domain,
|
||||
.init_apic_ldr = flat_init_apic_ldr,
|
||||
|
||||
.ioapic_phys_id_map = NULL,
|
||||
.setup_apic_routing = NULL,
|
||||
.multi_timer_check = NULL,
|
||||
.cpu_present_to_apicid = default_cpu_present_to_apicid,
|
||||
.apicid_to_cpu_present = NULL,
|
||||
.setup_portio_remap = NULL,
|
||||
.check_phys_apicid_present = default_check_phys_apicid_present,
|
||||
.enable_apic_mode = NULL,
|
||||
.phys_pkg_id = flat_phys_pkg_id,
|
||||
.mps_oem_check = NULL,
|
||||
|
||||
.get_apic_id = flat_get_apic_id,
|
||||
.set_apic_id = set_apic_id,
|
||||
@ -196,10 +191,7 @@ static struct apic apic_flat = {
|
||||
.send_IPI_all = flat_send_IPI_all,
|
||||
.send_IPI_self = apic_send_IPI_self,
|
||||
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
.wait_for_init_deassert = false,
|
||||
.smp_callin_clear_local_apic = NULL,
|
||||
.inquire_remote_apic = default_inquire_remote_apic,
|
||||
|
||||
.read = native_apic_mem_read,
|
||||
@ -283,7 +275,6 @@ static struct apic apic_physflat = {
|
||||
.disable_esr = 0,
|
||||
.dest_logical = 0,
|
||||
.check_apicid_used = NULL,
|
||||
.check_apicid_present = NULL,
|
||||
|
||||
.vector_allocation_domain = default_vector_allocation_domain,
|
||||
/* not needed, but shouldn't hurt: */
|
||||
@ -291,14 +282,10 @@ static struct apic apic_physflat = {
|
||||
|
||||
.ioapic_phys_id_map = NULL,
|
||||
.setup_apic_routing = NULL,
|
||||
.multi_timer_check = NULL,
|
||||
.cpu_present_to_apicid = default_cpu_present_to_apicid,
|
||||
.apicid_to_cpu_present = NULL,
|
||||
.setup_portio_remap = NULL,
|
||||
.check_phys_apicid_present = default_check_phys_apicid_present,
|
||||
.enable_apic_mode = NULL,
|
||||
.phys_pkg_id = flat_phys_pkg_id,
|
||||
.mps_oem_check = NULL,
|
||||
|
||||
.get_apic_id = flat_get_apic_id,
|
||||
.set_apic_id = set_apic_id,
|
||||
@ -312,10 +299,7 @@ static struct apic apic_physflat = {
|
||||
.send_IPI_all = physflat_send_IPI_all,
|
||||
.send_IPI_self = apic_send_IPI_self,
|
||||
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
.wait_for_init_deassert = false,
|
||||
.smp_callin_clear_local_apic = NULL,
|
||||
.inquire_remote_apic = default_inquire_remote_apic,
|
||||
|
||||
.read = native_apic_mem_read,
|
||||
|
@ -89,16 +89,6 @@ static const struct cpumask *noop_target_cpus(void)
|
||||
return cpumask_of(0);
|
||||
}
|
||||
|
||||
static unsigned long noop_check_apicid_used(physid_mask_t *map, int apicid)
|
||||
{
|
||||
return physid_isset(apicid, *map);
|
||||
}
|
||||
|
||||
static unsigned long noop_check_apicid_present(int bit)
|
||||
{
|
||||
return physid_isset(bit, phys_cpu_present_map);
|
||||
}
|
||||
|
||||
static void noop_vector_allocation_domain(int cpu, struct cpumask *retmask,
|
||||
const struct cpumask *mask)
|
||||
{
|
||||
@ -133,27 +123,21 @@ struct apic apic_noop = {
|
||||
.target_cpus = noop_target_cpus,
|
||||
.disable_esr = 0,
|
||||
.dest_logical = APIC_DEST_LOGICAL,
|
||||
.check_apicid_used = noop_check_apicid_used,
|
||||
.check_apicid_present = noop_check_apicid_present,
|
||||
.check_apicid_used = default_check_apicid_used,
|
||||
|
||||
.vector_allocation_domain = noop_vector_allocation_domain,
|
||||
.init_apic_ldr = noop_init_apic_ldr,
|
||||
|
||||
.ioapic_phys_id_map = default_ioapic_phys_id_map,
|
||||
.setup_apic_routing = NULL,
|
||||
.multi_timer_check = NULL,
|
||||
|
||||
.cpu_present_to_apicid = default_cpu_present_to_apicid,
|
||||
.apicid_to_cpu_present = physid_set_mask_of_physid,
|
||||
|
||||
.setup_portio_remap = NULL,
|
||||
.check_phys_apicid_present = default_check_phys_apicid_present,
|
||||
.enable_apic_mode = NULL,
|
||||
|
||||
.phys_pkg_id = noop_phys_pkg_id,
|
||||
|
||||
.mps_oem_check = NULL,
|
||||
|
||||
.get_apic_id = noop_get_apic_id,
|
||||
.set_apic_id = NULL,
|
||||
.apic_id_mask = 0x0F << 24,
|
||||
@ -168,12 +152,7 @@ struct apic apic_noop = {
|
||||
|
||||
.wakeup_secondary_cpu = noop_wakeup_secondary_cpu,
|
||||
|
||||
/* should be safe */
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
|
||||
.wait_for_init_deassert = false,
|
||||
.smp_callin_clear_local_apic = NULL,
|
||||
.inquire_remote_apic = NULL,
|
||||
|
||||
.read = noop_apic_read,
|
||||
|
@ -217,21 +217,16 @@ static const struct apic apic_numachip __refconst = {
|
||||
.disable_esr = 0,
|
||||
.dest_logical = 0,
|
||||
.check_apicid_used = NULL,
|
||||
.check_apicid_present = NULL,
|
||||
|
||||
.vector_allocation_domain = default_vector_allocation_domain,
|
||||
.init_apic_ldr = flat_init_apic_ldr,
|
||||
|
||||
.ioapic_phys_id_map = NULL,
|
||||
.setup_apic_routing = NULL,
|
||||
.multi_timer_check = NULL,
|
||||
.cpu_present_to_apicid = default_cpu_present_to_apicid,
|
||||
.apicid_to_cpu_present = NULL,
|
||||
.setup_portio_remap = NULL,
|
||||
.check_phys_apicid_present = default_check_phys_apicid_present,
|
||||
.enable_apic_mode = NULL,
|
||||
.phys_pkg_id = numachip_phys_pkg_id,
|
||||
.mps_oem_check = NULL,
|
||||
|
||||
.get_apic_id = get_apic_id,
|
||||
.set_apic_id = set_apic_id,
|
||||
@ -246,10 +241,7 @@ static const struct apic apic_numachip __refconst = {
|
||||
.send_IPI_self = numachip_send_IPI_self,
|
||||
|
||||
.wakeup_secondary_cpu = numachip_wakeup_secondary,
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
.wait_for_init_deassert = false,
|
||||
.smp_callin_clear_local_apic = NULL,
|
||||
.inquire_remote_apic = NULL, /* REMRD not supported */
|
||||
|
||||
.read = native_apic_mem_read,
|
||||
|
@ -31,11 +31,6 @@ static unsigned long bigsmp_check_apicid_used(physid_mask_t *map, int apicid)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long bigsmp_check_apicid_present(int bit)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int bigsmp_early_logical_apicid(int cpu)
|
||||
{
|
||||
/* on bigsmp, logical apicid is the same as physical */
|
||||
@ -168,21 +163,16 @@ static struct apic apic_bigsmp = {
|
||||
.disable_esr = 1,
|
||||
.dest_logical = 0,
|
||||
.check_apicid_used = bigsmp_check_apicid_used,
|
||||
.check_apicid_present = bigsmp_check_apicid_present,
|
||||
|
||||
.vector_allocation_domain = default_vector_allocation_domain,
|
||||
.init_apic_ldr = bigsmp_init_apic_ldr,
|
||||
|
||||
.ioapic_phys_id_map = bigsmp_ioapic_phys_id_map,
|
||||
.setup_apic_routing = bigsmp_setup_apic_routing,
|
||||
.multi_timer_check = NULL,
|
||||
.cpu_present_to_apicid = bigsmp_cpu_present_to_apicid,
|
||||
.apicid_to_cpu_present = physid_set_mask_of_physid,
|
||||
.setup_portio_remap = NULL,
|
||||
.check_phys_apicid_present = bigsmp_check_phys_apicid_present,
|
||||
.enable_apic_mode = NULL,
|
||||
.phys_pkg_id = bigsmp_phys_pkg_id,
|
||||
.mps_oem_check = NULL,
|
||||
|
||||
.get_apic_id = bigsmp_get_apic_id,
|
||||
.set_apic_id = NULL,
|
||||
@ -196,11 +186,7 @@ static struct apic apic_bigsmp = {
|
||||
.send_IPI_all = bigsmp_send_IPI_all,
|
||||
.send_IPI_self = default_send_IPI_self,
|
||||
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
|
||||
.wait_for_init_deassert = true,
|
||||
.smp_callin_clear_local_apic = NULL,
|
||||
.inquire_remote_apic = default_inquire_remote_apic,
|
||||
|
||||
.read = native_apic_mem_read,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -88,21 +88,16 @@ static struct apic apic_default = {
|
||||
.disable_esr = 0,
|
||||
.dest_logical = APIC_DEST_LOGICAL,
|
||||
.check_apicid_used = default_check_apicid_used,
|
||||
.check_apicid_present = default_check_apicid_present,
|
||||
|
||||
.vector_allocation_domain = flat_vector_allocation_domain,
|
||||
.init_apic_ldr = default_init_apic_ldr,
|
||||
|
||||
.ioapic_phys_id_map = default_ioapic_phys_id_map,
|
||||
.setup_apic_routing = setup_apic_flat_routing,
|
||||
.multi_timer_check = NULL,
|
||||
.cpu_present_to_apicid = default_cpu_present_to_apicid,
|
||||
.apicid_to_cpu_present = physid_set_mask_of_physid,
|
||||
.setup_portio_remap = NULL,
|
||||
.check_phys_apicid_present = default_check_phys_apicid_present,
|
||||
.enable_apic_mode = NULL,
|
||||
.phys_pkg_id = default_phys_pkg_id,
|
||||
.mps_oem_check = NULL,
|
||||
|
||||
.get_apic_id = default_get_apic_id,
|
||||
.set_apic_id = NULL,
|
||||
@ -116,11 +111,7 @@ static struct apic apic_default = {
|
||||
.send_IPI_all = default_send_IPI_all,
|
||||
.send_IPI_self = default_send_IPI_self,
|
||||
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
|
||||
.wait_for_init_deassert = true,
|
||||
.smp_callin_clear_local_apic = NULL,
|
||||
.inquire_remote_apic = default_inquire_remote_apic,
|
||||
|
||||
.read = native_apic_mem_read,
|
||||
@ -214,29 +205,7 @@ void __init generic_apic_probe(void)
|
||||
printk(KERN_INFO "Using APIC driver %s\n", apic->name);
|
||||
}
|
||||
|
||||
/* These functions can switch the APIC even after the initial ->probe() */
|
||||
|
||||
int __init
|
||||
generic_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
|
||||
{
|
||||
struct apic **drv;
|
||||
|
||||
for (drv = __apicdrivers; drv < __apicdrivers_end; drv++) {
|
||||
if (!((*drv)->mps_oem_check))
|
||||
continue;
|
||||
if (!(*drv)->mps_oem_check(mpc, oem, productid))
|
||||
continue;
|
||||
|
||||
if (!cmdline_apic) {
|
||||
apic = *drv;
|
||||
printk(KERN_INFO "Switched to APIC driver `%s'.\n",
|
||||
apic->name);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function can switch the APIC even after the initial ->probe() */
|
||||
int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
{
|
||||
struct apic **drv;
|
||||
|
@ -249,21 +249,16 @@ static struct apic apic_x2apic_cluster = {
|
||||
.disable_esr = 0,
|
||||
.dest_logical = APIC_DEST_LOGICAL,
|
||||
.check_apicid_used = NULL,
|
||||
.check_apicid_present = NULL,
|
||||
|
||||
.vector_allocation_domain = cluster_vector_allocation_domain,
|
||||
.init_apic_ldr = init_x2apic_ldr,
|
||||
|
||||
.ioapic_phys_id_map = NULL,
|
||||
.setup_apic_routing = NULL,
|
||||
.multi_timer_check = NULL,
|
||||
.cpu_present_to_apicid = default_cpu_present_to_apicid,
|
||||
.apicid_to_cpu_present = NULL,
|
||||
.setup_portio_remap = NULL,
|
||||
.check_phys_apicid_present = default_check_phys_apicid_present,
|
||||
.enable_apic_mode = NULL,
|
||||
.phys_pkg_id = x2apic_phys_pkg_id,
|
||||
.mps_oem_check = NULL,
|
||||
|
||||
.get_apic_id = x2apic_get_apic_id,
|
||||
.set_apic_id = x2apic_set_apic_id,
|
||||
@ -277,10 +272,7 @@ static struct apic apic_x2apic_cluster = {
|
||||
.send_IPI_all = x2apic_send_IPI_all,
|
||||
.send_IPI_self = x2apic_send_IPI_self,
|
||||
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
.wait_for_init_deassert = false,
|
||||
.smp_callin_clear_local_apic = NULL,
|
||||
.inquire_remote_apic = NULL,
|
||||
|
||||
.read = native_apic_msr_read,
|
||||
|
@ -103,21 +103,16 @@ static struct apic apic_x2apic_phys = {
|
||||
.disable_esr = 0,
|
||||
.dest_logical = 0,
|
||||
.check_apicid_used = NULL,
|
||||
.check_apicid_present = NULL,
|
||||
|
||||
.vector_allocation_domain = default_vector_allocation_domain,
|
||||
.init_apic_ldr = init_x2apic_ldr,
|
||||
|
||||
.ioapic_phys_id_map = NULL,
|
||||
.setup_apic_routing = NULL,
|
||||
.multi_timer_check = NULL,
|
||||
.cpu_present_to_apicid = default_cpu_present_to_apicid,
|
||||
.apicid_to_cpu_present = NULL,
|
||||
.setup_portio_remap = NULL,
|
||||
.check_phys_apicid_present = default_check_phys_apicid_present,
|
||||
.enable_apic_mode = NULL,
|
||||
.phys_pkg_id = x2apic_phys_pkg_id,
|
||||
.mps_oem_check = NULL,
|
||||
|
||||
.get_apic_id = x2apic_get_apic_id,
|
||||
.set_apic_id = x2apic_set_apic_id,
|
||||
@ -131,10 +126,7 @@ static struct apic apic_x2apic_phys = {
|
||||
.send_IPI_all = x2apic_send_IPI_all,
|
||||
.send_IPI_self = x2apic_send_IPI_self,
|
||||
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
.wait_for_init_deassert = false,
|
||||
.smp_callin_clear_local_apic = NULL,
|
||||
.inquire_remote_apic = NULL,
|
||||
|
||||
.read = native_apic_msr_read,
|
||||
|
@ -365,21 +365,16 @@ static struct apic __refdata apic_x2apic_uv_x = {
|
||||
.disable_esr = 0,
|
||||
.dest_logical = APIC_DEST_LOGICAL,
|
||||
.check_apicid_used = NULL,
|
||||
.check_apicid_present = NULL,
|
||||
|
||||
.vector_allocation_domain = default_vector_allocation_domain,
|
||||
.init_apic_ldr = uv_init_apic_ldr,
|
||||
|
||||
.ioapic_phys_id_map = NULL,
|
||||
.setup_apic_routing = NULL,
|
||||
.multi_timer_check = NULL,
|
||||
.cpu_present_to_apicid = default_cpu_present_to_apicid,
|
||||
.apicid_to_cpu_present = NULL,
|
||||
.setup_portio_remap = NULL,
|
||||
.check_phys_apicid_present = default_check_phys_apicid_present,
|
||||
.enable_apic_mode = NULL,
|
||||
.phys_pkg_id = uv_phys_pkg_id,
|
||||
.mps_oem_check = NULL,
|
||||
|
||||
.get_apic_id = x2apic_get_apic_id,
|
||||
.set_apic_id = set_apic_id,
|
||||
@ -394,10 +389,7 @@ static struct apic __refdata apic_x2apic_uv_x = {
|
||||
.send_IPI_self = uv_send_IPI_self,
|
||||
|
||||
.wakeup_secondary_cpu = uv_wakeup_secondary,
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
.wait_for_init_deassert = false,
|
||||
.smp_callin_clear_local_apic = NULL,
|
||||
.inquire_remote_apic = NULL,
|
||||
|
||||
.read = native_apic_msr_read,
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <asm/apic.h>
|
||||
#include <asm/pci_x86.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/i8259.h>
|
||||
|
||||
__initdata u64 initial_dtb;
|
||||
char __initdata cmd_line[COMMAND_LINE_SIZE];
|
||||
@ -165,10 +166,79 @@ static void __init dtb_lapic_setup(void)
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
static unsigned int ioapic_id;
|
||||
|
||||
struct of_ioapic_type {
|
||||
u32 out_type;
|
||||
u32 trigger;
|
||||
u32 polarity;
|
||||
};
|
||||
|
||||
static struct of_ioapic_type of_ioapic_type[] =
|
||||
{
|
||||
{
|
||||
.out_type = IRQ_TYPE_EDGE_RISING,
|
||||
.trigger = IOAPIC_EDGE,
|
||||
.polarity = 1,
|
||||
},
|
||||
{
|
||||
.out_type = IRQ_TYPE_LEVEL_LOW,
|
||||
.trigger = IOAPIC_LEVEL,
|
||||
.polarity = 0,
|
||||
},
|
||||
{
|
||||
.out_type = IRQ_TYPE_LEVEL_HIGH,
|
||||
.trigger = IOAPIC_LEVEL,
|
||||
.polarity = 1,
|
||||
},
|
||||
{
|
||||
.out_type = IRQ_TYPE_EDGE_FALLING,
|
||||
.trigger = IOAPIC_EDGE,
|
||||
.polarity = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static int ioapic_xlate(struct irq_domain *domain,
|
||||
struct device_node *controller,
|
||||
const u32 *intspec, u32 intsize,
|
||||
irq_hw_number_t *out_hwirq, u32 *out_type)
|
||||
{
|
||||
struct of_ioapic_type *it;
|
||||
u32 line, idx, gsi;
|
||||
|
||||
if (WARN_ON(intsize < 2))
|
||||
return -EINVAL;
|
||||
|
||||
line = intspec[0];
|
||||
|
||||
if (intspec[1] >= ARRAY_SIZE(of_ioapic_type))
|
||||
return -EINVAL;
|
||||
|
||||
it = &of_ioapic_type[intspec[1]];
|
||||
|
||||
idx = (u32)(long)domain->host_data;
|
||||
gsi = mp_pin_to_gsi(idx, line);
|
||||
if (mp_set_gsi_attr(gsi, it->trigger, it->polarity, cpu_to_node(0)))
|
||||
return -EBUSY;
|
||||
|
||||
*out_hwirq = line;
|
||||
*out_type = it->out_type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct irq_domain_ops ioapic_irq_domain_ops = {
|
||||
.map = mp_irqdomain_map,
|
||||
.unmap = mp_irqdomain_unmap,
|
||||
.xlate = ioapic_xlate,
|
||||
};
|
||||
|
||||
static void __init dtb_add_ioapic(struct device_node *dn)
|
||||
{
|
||||
struct resource r;
|
||||
int ret;
|
||||
struct ioapic_domain_cfg cfg = {
|
||||
.type = IOAPIC_DOMAIN_DYNAMIC,
|
||||
.ops = &ioapic_irq_domain_ops,
|
||||
.dev = dn,
|
||||
};
|
||||
|
||||
ret = of_address_to_resource(dn, 0, &r);
|
||||
if (ret) {
|
||||
@ -176,7 +246,7 @@ static void __init dtb_add_ioapic(struct device_node *dn)
|
||||
dn->full_name);
|
||||
return;
|
||||
}
|
||||
mp_register_ioapic(++ioapic_id, r.start, gsi_top);
|
||||
mp_register_ioapic(++ioapic_id, r.start, gsi_top, &cfg);
|
||||
}
|
||||
|
||||
static void __init dtb_ioapic_setup(void)
|
||||
@ -238,148 +308,3 @@ void __init x86_dtb_init(void)
|
||||
dtb_setup_hpet();
|
||||
dtb_apic_setup();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
|
||||
struct of_ioapic_type {
|
||||
u32 out_type;
|
||||
u32 trigger;
|
||||
u32 polarity;
|
||||
};
|
||||
|
||||
static struct of_ioapic_type of_ioapic_type[] =
|
||||
{
|
||||
{
|
||||
.out_type = IRQ_TYPE_EDGE_RISING,
|
||||
.trigger = IOAPIC_EDGE,
|
||||
.polarity = 1,
|
||||
},
|
||||
{
|
||||
.out_type = IRQ_TYPE_LEVEL_LOW,
|
||||
.trigger = IOAPIC_LEVEL,
|
||||
.polarity = 0,
|
||||
},
|
||||
{
|
||||
.out_type = IRQ_TYPE_LEVEL_HIGH,
|
||||
.trigger = IOAPIC_LEVEL,
|
||||
.polarity = 1,
|
||||
},
|
||||
{
|
||||
.out_type = IRQ_TYPE_EDGE_FALLING,
|
||||
.trigger = IOAPIC_EDGE,
|
||||
.polarity = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static int ioapic_xlate(struct irq_domain *domain,
|
||||
struct device_node *controller,
|
||||
const u32 *intspec, u32 intsize,
|
||||
irq_hw_number_t *out_hwirq, u32 *out_type)
|
||||
{
|
||||
struct io_apic_irq_attr attr;
|
||||
struct of_ioapic_type *it;
|
||||
u32 line, idx;
|
||||
int rc;
|
||||
|
||||
if (WARN_ON(intsize < 2))
|
||||
return -EINVAL;
|
||||
|
||||
line = intspec[0];
|
||||
|
||||
if (intspec[1] >= ARRAY_SIZE(of_ioapic_type))
|
||||
return -EINVAL;
|
||||
|
||||
it = &of_ioapic_type[intspec[1]];
|
||||
|
||||
idx = (u32) domain->host_data;
|
||||
set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
|
||||
|
||||
rc = io_apic_setup_irq_pin_once(irq_find_mapping(domain, line),
|
||||
cpu_to_node(0), &attr);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
*out_hwirq = line;
|
||||
*out_type = it->out_type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct irq_domain_ops ioapic_irq_domain_ops = {
|
||||
.xlate = ioapic_xlate,
|
||||
};
|
||||
|
||||
static void dt_add_ioapic_domain(unsigned int ioapic_num,
|
||||
struct device_node *np)
|
||||
{
|
||||
struct irq_domain *id;
|
||||
struct mp_ioapic_gsi *gsi_cfg;
|
||||
int ret;
|
||||
int num;
|
||||
|
||||
gsi_cfg = mp_ioapic_gsi_routing(ioapic_num);
|
||||
num = gsi_cfg->gsi_end - gsi_cfg->gsi_base + 1;
|
||||
|
||||
id = irq_domain_add_linear(np, num, &ioapic_irq_domain_ops,
|
||||
(void *)ioapic_num);
|
||||
BUG_ON(!id);
|
||||
if (gsi_cfg->gsi_base == 0) {
|
||||
/*
|
||||
* The first NR_IRQS_LEGACY irq descs are allocated in
|
||||
* early_irq_init() and need just a mapping. The
|
||||
* remaining irqs need both. All of them are preallocated
|
||||
* and assigned so we can keep the 1:1 mapping which the ioapic
|
||||
* is having.
|
||||
*/
|
||||
irq_domain_associate_many(id, 0, 0, NR_IRQS_LEGACY);
|
||||
|
||||
if (num > NR_IRQS_LEGACY) {
|
||||
ret = irq_create_strict_mappings(id, NR_IRQS_LEGACY,
|
||||
NR_IRQS_LEGACY, num - NR_IRQS_LEGACY);
|
||||
if (ret)
|
||||
pr_err("Error creating mapping for the "
|
||||
"remaining IRQs: %d\n", ret);
|
||||
}
|
||||
irq_set_default_host(id);
|
||||
} else {
|
||||
ret = irq_create_strict_mappings(id, gsi_cfg->gsi_base, 0, num);
|
||||
if (ret)
|
||||
pr_err("Error creating IRQ mapping: %d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void __init ioapic_add_ofnode(struct device_node *np)
|
||||
{
|
||||
struct resource r;
|
||||
int i, ret;
|
||||
|
||||
ret = of_address_to_resource(np, 0, &r);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "Failed to obtain address for %s\n",
|
||||
np->full_name);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_ioapics; i++) {
|
||||
if (r.start == mpc_ioapic_addr(i)) {
|
||||
dt_add_ioapic_domain(i, np);
|
||||
return;
|
||||
}
|
||||
}
|
||||
printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name);
|
||||
}
|
||||
|
||||
void __init x86_add_irq_domains(void)
|
||||
{
|
||||
struct device_node *dp;
|
||||
|
||||
if (!of_have_populated_dt())
|
||||
return;
|
||||
|
||||
for_each_node_with_property(dp, "interrupt-controller") {
|
||||
if (of_device_is_compatible(dp, "intel,ce4100-ioapic"))
|
||||
ioapic_add_ofnode(dp);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void __init x86_add_irq_domains(void) { }
|
||||
#endif
|
||||
|
@ -78,7 +78,7 @@ void __init init_ISA_irqs(void)
|
||||
#endif
|
||||
legacy_pic->init(0);
|
||||
|
||||
for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
|
||||
for (i = 0; i < nr_legacy_irqs(); i++)
|
||||
irq_set_chip_and_handler_name(i, chip, handle_level_irq, name);
|
||||
}
|
||||
|
||||
@ -86,12 +86,6 @@ void __init init_IRQ(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/*
|
||||
* We probably need a better place for this, but it works for
|
||||
* now ...
|
||||
*/
|
||||
x86_add_irq_domains();
|
||||
|
||||
/*
|
||||
* On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.
|
||||
* If these IRQ's are handled by legacy interrupt-controllers like PIC,
|
||||
@ -100,7 +94,7 @@ void __init init_IRQ(void)
|
||||
* then this vector space can be freed and re-used dynamically as the
|
||||
* irq's migrate etc.
|
||||
*/
|
||||
for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
|
||||
for (i = 0; i < nr_legacy_irqs(); i++)
|
||||
per_cpu(vector_irq, 0)[IRQ0_VECTOR + i] = i;
|
||||
|
||||
x86_init.irqs.intr_init();
|
||||
@ -121,7 +115,7 @@ void setup_vector_irq(int cpu)
|
||||
* legacy PIC, for the new cpu that is coming online, setup the static
|
||||
* legacy vector to irq mapping:
|
||||
*/
|
||||
for (irq = 0; irq < legacy_pic->nr_legacy_irqs; irq++)
|
||||
for (irq = 0; irq < nr_legacy_irqs(); irq++)
|
||||
per_cpu(vector_irq, cpu)[IRQ0_VECTOR + irq] = irq;
|
||||
#endif
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/smp.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/irqdomain.h>
|
||||
|
||||
#include <asm/mtrr.h>
|
||||
#include <asm/mpspec.h>
|
||||
@ -67,7 +68,7 @@ static void __init MP_processor_info(struct mpc_cpu *m)
|
||||
boot_cpu_physical_apicid = m->apicid;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Processor #%d%s\n", m->apicid, bootup_cpu);
|
||||
pr_info("Processor #%d%s\n", m->apicid, bootup_cpu);
|
||||
generic_processor_info(apicid, m->apicver);
|
||||
}
|
||||
|
||||
@ -87,9 +88,8 @@ static void __init MP_bus_info(struct mpc_bus *m)
|
||||
|
||||
#if MAX_MP_BUSSES < 256
|
||||
if (m->busid >= MAX_MP_BUSSES) {
|
||||
printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
|
||||
" is too large, max. supported is %d\n",
|
||||
m->busid, str, MAX_MP_BUSSES - 1);
|
||||
pr_warn("MP table busid value (%d) for bustype %s is too large, max. supported is %d\n",
|
||||
m->busid, str, MAX_MP_BUSSES - 1);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@ -110,19 +110,29 @@ static void __init MP_bus_info(struct mpc_bus *m)
|
||||
mp_bus_id_to_type[m->busid] = MP_BUS_EISA;
|
||||
#endif
|
||||
} else
|
||||
printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
|
||||
pr_warn("Unknown bustype %s - ignoring\n", str);
|
||||
}
|
||||
|
||||
static struct irq_domain_ops mp_ioapic_irqdomain_ops = {
|
||||
.map = mp_irqdomain_map,
|
||||
.unmap = mp_irqdomain_unmap,
|
||||
};
|
||||
|
||||
static void __init MP_ioapic_info(struct mpc_ioapic *m)
|
||||
{
|
||||
struct ioapic_domain_cfg cfg = {
|
||||
.type = IOAPIC_DOMAIN_LEGACY,
|
||||
.ops = &mp_ioapic_irqdomain_ops,
|
||||
};
|
||||
|
||||
if (m->flags & MPC_APIC_USABLE)
|
||||
mp_register_ioapic(m->apicid, m->apicaddr, gsi_top);
|
||||
mp_register_ioapic(m->apicid, m->apicaddr, gsi_top, &cfg);
|
||||
}
|
||||
|
||||
static void __init print_mp_irq_info(struct mpc_intsrc *mp_irq)
|
||||
{
|
||||
apic_printk(APIC_VERBOSE, "Int: type %d, pol %d, trig %d, bus %02x,"
|
||||
" IRQ %02x, APIC ID %x, APIC INT %02x\n",
|
||||
apic_printk(APIC_VERBOSE,
|
||||
"Int: type %d, pol %d, trig %d, bus %02x, IRQ %02x, APIC ID %x, APIC INT %02x\n",
|
||||
mp_irq->irqtype, mp_irq->irqflag & 3,
|
||||
(mp_irq->irqflag >> 2) & 3, mp_irq->srcbus,
|
||||
mp_irq->srcbusirq, mp_irq->dstapic, mp_irq->dstirq);
|
||||
@ -135,8 +145,8 @@ static inline void __init MP_ioapic_info(struct mpc_ioapic *m) {}
|
||||
|
||||
static void __init MP_lintsrc_info(struct mpc_lintsrc *m)
|
||||
{
|
||||
apic_printk(APIC_VERBOSE, "Lint: type %d, pol %d, trig %d, bus %02x,"
|
||||
" IRQ %02x, APIC ID %x, APIC LINT %02x\n",
|
||||
apic_printk(APIC_VERBOSE,
|
||||
"Lint: type %d, pol %d, trig %d, bus %02x, IRQ %02x, APIC ID %x, APIC LINT %02x\n",
|
||||
m->irqtype, m->irqflag & 3, (m->irqflag >> 2) & 3, m->srcbusid,
|
||||
m->srcbusirq, m->destapic, m->destapiclint);
|
||||
}
|
||||
@ -148,34 +158,33 @@ static int __init smp_check_mpc(struct mpc_table *mpc, char *oem, char *str)
|
||||
{
|
||||
|
||||
if (memcmp(mpc->signature, MPC_SIGNATURE, 4)) {
|
||||
printk(KERN_ERR "MPTABLE: bad signature [%c%c%c%c]!\n",
|
||||
pr_err("MPTABLE: bad signature [%c%c%c%c]!\n",
|
||||
mpc->signature[0], mpc->signature[1],
|
||||
mpc->signature[2], mpc->signature[3]);
|
||||
return 0;
|
||||
}
|
||||
if (mpf_checksum((unsigned char *)mpc, mpc->length)) {
|
||||
printk(KERN_ERR "MPTABLE: checksum error!\n");
|
||||
pr_err("MPTABLE: checksum error!\n");
|
||||
return 0;
|
||||
}
|
||||
if (mpc->spec != 0x01 && mpc->spec != 0x04) {
|
||||
printk(KERN_ERR "MPTABLE: bad table version (%d)!!\n",
|
||||
mpc->spec);
|
||||
pr_err("MPTABLE: bad table version (%d)!!\n", mpc->spec);
|
||||
return 0;
|
||||
}
|
||||
if (!mpc->lapic) {
|
||||
printk(KERN_ERR "MPTABLE: null local APIC address!\n");
|
||||
pr_err("MPTABLE: null local APIC address!\n");
|
||||
return 0;
|
||||
}
|
||||
memcpy(oem, mpc->oem, 8);
|
||||
oem[8] = 0;
|
||||
printk(KERN_INFO "MPTABLE: OEM ID: %s\n", oem);
|
||||
pr_info("MPTABLE: OEM ID: %s\n", oem);
|
||||
|
||||
memcpy(str, mpc->productid, 12);
|
||||
str[12] = 0;
|
||||
|
||||
printk(KERN_INFO "MPTABLE: Product ID: %s\n", str);
|
||||
pr_info("MPTABLE: Product ID: %s\n", str);
|
||||
|
||||
printk(KERN_INFO "MPTABLE: APIC at: 0x%X\n", mpc->lapic);
|
||||
pr_info("MPTABLE: APIC at: 0x%X\n", mpc->lapic);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -188,8 +197,8 @@ static void skip_entry(unsigned char **ptr, int *count, int size)
|
||||
|
||||
static void __init smp_dump_mptable(struct mpc_table *mpc, unsigned char *mpt)
|
||||
{
|
||||
printk(KERN_ERR "Your mptable is wrong, contact your HW vendor!\n"
|
||||
"type %x\n", *mpt);
|
||||
pr_err("Your mptable is wrong, contact your HW vendor!\n");
|
||||
pr_cont("type %x\n", *mpt);
|
||||
print_hex_dump(KERN_ERR, " ", DUMP_PREFIX_ADDRESS, 16,
|
||||
1, mpc, mpc->length, 1);
|
||||
}
|
||||
@ -207,9 +216,6 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
|
||||
if (!smp_check_mpc(mpc, oem, str))
|
||||
return 0;
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
generic_mps_oem_check(mpc, oem, str);
|
||||
#endif
|
||||
/* Initialize the lapic mapping */
|
||||
if (!acpi_lapic)
|
||||
register_lapic_address(mpc->lapic);
|
||||
@ -259,7 +265,7 @@ static int __init smp_read_mpc(struct mpc_table *mpc, unsigned early)
|
||||
}
|
||||
|
||||
if (!num_processors)
|
||||
printk(KERN_ERR "MPTABLE: no processors registered!\n");
|
||||
pr_err("MPTABLE: no processors registered!\n");
|
||||
return num_processors;
|
||||
}
|
||||
|
||||
@ -295,16 +301,13 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type)
|
||||
* If it does, we assume it's valid.
|
||||
*/
|
||||
if (mpc_default_type == 5) {
|
||||
printk(KERN_INFO "ISA/PCI bus type with no IRQ information... "
|
||||
"falling back to ELCR\n");
|
||||
pr_info("ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
|
||||
|
||||
if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) ||
|
||||
ELCR_trigger(13))
|
||||
printk(KERN_ERR "ELCR contains invalid data... "
|
||||
"not using ELCR\n");
|
||||
pr_err("ELCR contains invalid data... not using ELCR\n");
|
||||
else {
|
||||
printk(KERN_INFO
|
||||
"Using ELCR to identify PCI interrupts\n");
|
||||
pr_info("Using ELCR to identify PCI interrupts\n");
|
||||
ELCR_fallback = 1;
|
||||
}
|
||||
}
|
||||
@ -353,7 +356,7 @@ static void __init construct_ioapic_table(int mpc_default_type)
|
||||
bus.busid = 0;
|
||||
switch (mpc_default_type) {
|
||||
default:
|
||||
printk(KERN_ERR "???\nUnknown standard configuration %d\n",
|
||||
pr_err("???\nUnknown standard configuration %d\n",
|
||||
mpc_default_type);
|
||||
/* fall through */
|
||||
case 1:
|
||||
@ -462,8 +465,8 @@ static int __init check_physptr(struct mpf_intel *mpf, unsigned int early)
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
smp_found_config = 0;
|
||||
#endif
|
||||
printk(KERN_ERR "BIOS bug, MP table errors detected!...\n"
|
||||
"... disabling SMP support. (tell your hw vendor)\n");
|
||||
pr_err("BIOS bug, MP table errors detected!...\n");
|
||||
pr_cont("... disabling SMP support. (tell your hw vendor)\n");
|
||||
early_iounmap(mpc, size);
|
||||
return -1;
|
||||
}
|
||||
@ -481,8 +484,7 @@ static int __init check_physptr(struct mpf_intel *mpf, unsigned int early)
|
||||
if (!mp_irq_entries) {
|
||||
struct mpc_bus bus;
|
||||
|
||||
printk(KERN_ERR "BIOS bug, no explicit IRQ entries, "
|
||||
"using default mptable. (tell your hw vendor)\n");
|
||||
pr_err("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
|
||||
|
||||
bus.type = MP_BUS;
|
||||
bus.busid = 0;
|
||||
@ -516,14 +518,14 @@ void __init default_get_smp_config(unsigned int early)
|
||||
if (acpi_lapic && acpi_ioapic)
|
||||
return;
|
||||
|
||||
printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
|
||||
mpf->specification);
|
||||
pr_info("Intel MultiProcessor Specification v1.%d\n",
|
||||
mpf->specification);
|
||||
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32)
|
||||
if (mpf->feature2 & (1 << 7)) {
|
||||
printk(KERN_INFO " IMCR and PIC compatibility mode.\n");
|
||||
pr_info(" IMCR and PIC compatibility mode.\n");
|
||||
pic_mode = 1;
|
||||
} else {
|
||||
printk(KERN_INFO " Virtual Wire compatibility mode.\n");
|
||||
pr_info(" Virtual Wire compatibility mode.\n");
|
||||
pic_mode = 0;
|
||||
}
|
||||
#endif
|
||||
@ -539,8 +541,7 @@ void __init default_get_smp_config(unsigned int early)
|
||||
return;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Default MP configuration #%d\n",
|
||||
mpf->feature1);
|
||||
pr_info("Default MP configuration #%d\n", mpf->feature1);
|
||||
construct_default_ISA_mptable(mpf->feature1);
|
||||
|
||||
} else if (mpf->physptr) {
|
||||
@ -550,7 +551,7 @@ void __init default_get_smp_config(unsigned int early)
|
||||
BUG();
|
||||
|
||||
if (!early)
|
||||
printk(KERN_INFO "Processors: %d\n", num_processors);
|
||||
pr_info("Processors: %d\n", num_processors);
|
||||
/*
|
||||
* Only use the first configuration found.
|
||||
*/
|
||||
@ -583,10 +584,10 @@ static int __init smp_scan_config(unsigned long base, unsigned long length)
|
||||
#endif
|
||||
mpf_found = mpf;
|
||||
|
||||
printk(KERN_INFO "found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n",
|
||||
(unsigned long long) virt_to_phys(mpf),
|
||||
(unsigned long long) virt_to_phys(mpf) +
|
||||
sizeof(*mpf) - 1, mpf);
|
||||
pr_info("found SMP MP-table at [mem %#010llx-%#010llx] mapped at [%p]\n",
|
||||
(unsigned long long) virt_to_phys(mpf),
|
||||
(unsigned long long) virt_to_phys(mpf) +
|
||||
sizeof(*mpf) - 1, mpf);
|
||||
|
||||
mem = virt_to_phys(mpf);
|
||||
memblock_reserve(mem, sizeof(*mpf));
|
||||
@ -735,7 +736,7 @@ static int __init replace_intsrc_all(struct mpc_table *mpc,
|
||||
int nr_m_spare = 0;
|
||||
unsigned char *mpt = ((unsigned char *)mpc) + count;
|
||||
|
||||
printk(KERN_INFO "mpc_length %x\n", mpc->length);
|
||||
pr_info("mpc_length %x\n", mpc->length);
|
||||
while (count < mpc->length) {
|
||||
switch (*mpt) {
|
||||
case MP_PROCESSOR:
|
||||
@ -862,13 +863,13 @@ static int __init update_mp_table(void)
|
||||
if (!smp_check_mpc(mpc, oem, str))
|
||||
return 0;
|
||||
|
||||
printk(KERN_INFO "mpf: %llx\n", (u64)virt_to_phys(mpf));
|
||||
printk(KERN_INFO "physptr: %x\n", mpf->physptr);
|
||||
pr_info("mpf: %llx\n", (u64)virt_to_phys(mpf));
|
||||
pr_info("physptr: %x\n", mpf->physptr);
|
||||
|
||||
if (mpc_new_phys && mpc->length > mpc_new_length) {
|
||||
mpc_new_phys = 0;
|
||||
printk(KERN_INFO "mpc_new_length is %ld, please use alloc_mptable=8k\n",
|
||||
mpc_new_length);
|
||||
pr_info("mpc_new_length is %ld, please use alloc_mptable=8k\n",
|
||||
mpc_new_length);
|
||||
}
|
||||
|
||||
if (!mpc_new_phys) {
|
||||
@ -879,10 +880,10 @@ static int __init update_mp_table(void)
|
||||
mpc->checksum = 0xff;
|
||||
new = mpf_checksum((unsigned char *)mpc, mpc->length);
|
||||
if (old == new) {
|
||||
printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
|
||||
pr_info("mpc is readonly, please try alloc_mptable instead\n");
|
||||
return 0;
|
||||
}
|
||||
printk(KERN_INFO "use in-position replacing\n");
|
||||
pr_info("use in-position replacing\n");
|
||||
} else {
|
||||
mpf->physptr = mpc_new_phys;
|
||||
mpc_new = phys_to_virt(mpc_new_phys);
|
||||
@ -892,7 +893,7 @@ static int __init update_mp_table(void)
|
||||
if (mpc_new_phys - mpf->physptr) {
|
||||
struct mpf_intel *mpf_new;
|
||||
/* steal 16 bytes from [0, 1k) */
|
||||
printk(KERN_INFO "mpf new: %x\n", 0x400 - 16);
|
||||
pr_info("mpf new: %x\n", 0x400 - 16);
|
||||
mpf_new = phys_to_virt(0x400 - 16);
|
||||
memcpy(mpf_new, mpf, 16);
|
||||
mpf = mpf_new;
|
||||
@ -900,7 +901,7 @@ static int __init update_mp_table(void)
|
||||
}
|
||||
mpf->checksum = 0;
|
||||
mpf->checksum -= mpf_checksum((unsigned char *)mpf, 16);
|
||||
printk(KERN_INFO "physptr new: %x\n", mpf->physptr);
|
||||
pr_info("physptr new: %x\n", mpf->physptr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -168,10 +168,6 @@ static void smp_callin(void)
|
||||
* CPU, first the APIC. (this is probably redundant on most
|
||||
* boards)
|
||||
*/
|
||||
|
||||
pr_debug("CALLIN, before setup_local_APIC()\n");
|
||||
if (apic->smp_callin_clear_local_apic)
|
||||
apic->smp_callin_clear_local_apic();
|
||||
setup_local_APIC();
|
||||
end_local_APIC_setup();
|
||||
|
||||
@ -1143,10 +1139,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
|
||||
enable_IO_APIC();
|
||||
|
||||
bsp_end_local_APIC_setup();
|
||||
|
||||
if (apic->setup_portio_remap)
|
||||
apic->setup_portio_remap();
|
||||
|
||||
smpboot_setup_io_apic();
|
||||
/*
|
||||
* Set up local APIC timer on boot CPU.
|
||||
|
@ -152,7 +152,7 @@ static void __init detect_vsmp_box(void)
|
||||
is_vsmp = 1;
|
||||
}
|
||||
|
||||
int is_vsmp_box(void)
|
||||
static int is_vsmp_box(void)
|
||||
{
|
||||
if (is_vsmp != -1)
|
||||
return is_vsmp;
|
||||
@ -166,7 +166,7 @@ int is_vsmp_box(void)
|
||||
static void __init detect_vsmp_box(void)
|
||||
{
|
||||
}
|
||||
int is_vsmp_box(void)
|
||||
static int is_vsmp_box(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -448,7 +448,7 @@ static void probe_pci_root_info(struct pci_root_info *info,
|
||||
return;
|
||||
|
||||
size = sizeof(*info->res) * info->res_num;
|
||||
info->res = kzalloc(size, GFP_KERNEL);
|
||||
info->res = kzalloc_node(size, GFP_KERNEL, info->sd.node);
|
||||
if (!info->res) {
|
||||
info->res_num = 0;
|
||||
return;
|
||||
@ -456,7 +456,7 @@ static void probe_pci_root_info(struct pci_root_info *info,
|
||||
|
||||
size = sizeof(*info->res_offset) * info->res_num;
|
||||
info->res_num = 0;
|
||||
info->res_offset = kzalloc(size, GFP_KERNEL);
|
||||
info->res_offset = kzalloc_node(size, GFP_KERNEL, info->sd.node);
|
||||
if (!info->res_offset) {
|
||||
kfree(info->res);
|
||||
info->res = NULL;
|
||||
@ -499,7 +499,7 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
|
||||
if (node != NUMA_NO_NODE && !node_online(node))
|
||||
node = NUMA_NO_NODE;
|
||||
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
info = kzalloc_node(sizeof(*info), GFP_KERNEL, node);
|
||||
if (!info) {
|
||||
printk(KERN_WARNING "pci_bus %04x:%02x: "
|
||||
"ignored (out of memory)\n", domain, busnum);
|
||||
|
@ -208,27 +208,31 @@ static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
|
||||
|
||||
static int intel_mid_pci_irq_enable(struct pci_dev *dev)
|
||||
{
|
||||
u8 pin;
|
||||
struct io_apic_irq_attr irq_attr;
|
||||
int polarity;
|
||||
|
||||
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
|
||||
if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
|
||||
polarity = 0; /* active high */
|
||||
else
|
||||
polarity = 1; /* active low */
|
||||
|
||||
/*
|
||||
* MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
|
||||
* IOAPIC RTE entries, so we just enable RTE for the device.
|
||||
*/
|
||||
irq_attr.ioapic = mp_find_ioapic(dev->irq);
|
||||
irq_attr.ioapic_pin = dev->irq;
|
||||
irq_attr.trigger = 1; /* level */
|
||||
if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
|
||||
irq_attr.polarity = 0; /* active high */
|
||||
else
|
||||
irq_attr.polarity = 1; /* active low */
|
||||
io_apic_set_pci_routing(&dev->dev, dev->irq, &irq_attr);
|
||||
if (mp_set_gsi_attr(dev->irq, 1, polarity, dev_to_node(&dev->dev)))
|
||||
return -EBUSY;
|
||||
if (mp_map_gsi_to_irq(dev->irq, IOAPIC_MAP_ALLOC) < 0)
|
||||
return -EBUSY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void intel_mid_pci_irq_disable(struct pci_dev *dev)
|
||||
{
|
||||
if (!dev->dev.power.is_prepared && dev->irq > 0)
|
||||
mp_unmap_irq(dev->irq);
|
||||
}
|
||||
|
||||
struct pci_ops intel_mid_pci_ops = {
|
||||
.read = pci_read,
|
||||
.write = pci_write,
|
||||
@ -245,6 +249,7 @@ int __init intel_mid_pci_init(void)
|
||||
pr_info("Intel MID platform detected, using MID PCI ops\n");
|
||||
pci_mmcfg_late_init();
|
||||
pcibios_enable_irq = intel_mid_pci_irq_enable;
|
||||
pcibios_disable_irq = intel_mid_pci_irq_disable;
|
||||
pci_root_ops = intel_mid_pci_ops;
|
||||
pci_soc_mode = 1;
|
||||
/* Continue with standard init */
|
||||
|
@ -26,6 +26,7 @@ static int acer_tm360_irqrouting;
|
||||
static struct irq_routing_table *pirq_table;
|
||||
|
||||
static int pirq_enable_irq(struct pci_dev *dev);
|
||||
static void pirq_disable_irq(struct pci_dev *dev);
|
||||
|
||||
/*
|
||||
* Never use: 0, 1, 2 (timer, keyboard, and cascade)
|
||||
@ -53,7 +54,7 @@ struct irq_router_handler {
|
||||
};
|
||||
|
||||
int (*pcibios_enable_irq)(struct pci_dev *dev) = pirq_enable_irq;
|
||||
void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL;
|
||||
void (*pcibios_disable_irq)(struct pci_dev *dev) = pirq_disable_irq;
|
||||
|
||||
/*
|
||||
* Check passed address for the PCI IRQ Routing Table signature
|
||||
@ -1186,7 +1187,7 @@ void pcibios_penalize_isa_irq(int irq, int active)
|
||||
|
||||
static int pirq_enable_irq(struct pci_dev *dev)
|
||||
{
|
||||
u8 pin;
|
||||
u8 pin = 0;
|
||||
|
||||
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
|
||||
if (pin && !pcibios_lookup_irq(dev, 1)) {
|
||||
@ -1227,8 +1228,6 @@ static int pirq_enable_irq(struct pci_dev *dev)
|
||||
}
|
||||
dev = temp_dev;
|
||||
if (irq >= 0) {
|
||||
io_apic_set_pci_routing(&dev->dev, irq,
|
||||
&irq_attr);
|
||||
dev->irq = irq;
|
||||
dev_info(&dev->dev, "PCI->APIC IRQ transform: "
|
||||
"INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
|
||||
@ -1254,3 +1253,12 @@ static int pirq_enable_irq(struct pci_dev *dev)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pirq_disable_irq(struct pci_dev *dev)
|
||||
{
|
||||
if (io_apic_assign_pci_irqs && !dev->dev.power.is_prepared &&
|
||||
dev->irq) {
|
||||
mp_unmap_irq(dev->irq);
|
||||
dev->irq = 0;
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <xen/features.h>
|
||||
#include <xen/events.h>
|
||||
#include <asm/xen/pci.h>
|
||||
#include <asm/i8259.h>
|
||||
|
||||
static int xen_pcifront_enable_irq(struct pci_dev *dev)
|
||||
{
|
||||
@ -40,7 +41,7 @@ static int xen_pcifront_enable_irq(struct pci_dev *dev)
|
||||
/* In PV DomU the Xen PCI backend puts the PIRQ in the interrupt line.*/
|
||||
pirq = gsi;
|
||||
|
||||
if (gsi < NR_IRQS_LEGACY)
|
||||
if (gsi < nr_legacy_irqs())
|
||||
share = 0;
|
||||
|
||||
rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront");
|
||||
@ -511,7 +512,7 @@ int __init pci_xen_initial_domain(void)
|
||||
xen_setup_acpi_sci();
|
||||
__acpi_register_gsi = acpi_register_gsi_xen;
|
||||
/* Pre-allocate legacy irqs */
|
||||
for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
|
||||
for (irq = 0; irq < nr_legacy_irqs(); irq++) {
|
||||
int trigger, polarity;
|
||||
|
||||
if (acpi_get_override_irq(irq, &trigger, &polarity) == -1)
|
||||
@ -522,7 +523,7 @@ int __init pci_xen_initial_domain(void)
|
||||
true /* Map GSI to PIRQ */);
|
||||
}
|
||||
if (0 == nr_ioapics) {
|
||||
for (irq = 0; irq < NR_IRQS_LEGACY; irq++)
|
||||
for (irq = 0; irq < nr_legacy_irqs(); irq++)
|
||||
xen_bind_pirq_gsi_to_irq(irq, irq, 0, "xt-pic");
|
||||
}
|
||||
return 0;
|
||||
|
@ -135,14 +135,10 @@ static void __init sdv_arch_setup(void)
|
||||
sdv_serial_fixup();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
static void sdv_pci_init(void)
|
||||
{
|
||||
x86_of_pci_init();
|
||||
/* We can't set this earlier, because we need to calibrate the timer */
|
||||
legacy_pic = &null_legacy_pic;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* CE4100 specific x86_init function overrides and early setup
|
||||
@ -155,7 +151,9 @@ void __init x86_ce4100_early_setup(void)
|
||||
x86_init.resources.probe_roms = x86_init_noop;
|
||||
x86_init.mpparse.get_smp_config = x86_init_uint_noop;
|
||||
x86_init.mpparse.find_smp_config = x86_init_noop;
|
||||
x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
|
||||
x86_init.pci.init = ce4100_pci_init;
|
||||
x86_init.pci.init_irq = sdv_pci_init;
|
||||
|
||||
/*
|
||||
* By default, the reboot method is ACPI which is supported by the
|
||||
@ -166,10 +164,5 @@ void __init x86_ce4100_early_setup(void)
|
||||
*/
|
||||
reboot_type = BOOT_KBD;
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
x86_init.pci.init_irq = sdv_pci_init;
|
||||
x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
|
||||
#endif
|
||||
|
||||
pm_power_off = ce4100_power_off;
|
||||
}
|
||||
|
@ -26,28 +26,18 @@ static struct platform_device wdt_dev = {
|
||||
|
||||
static int tangier_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ioapic;
|
||||
int irq;
|
||||
int gsi;
|
||||
struct intel_mid_wdt_pdata *pdata = pdev->dev.platform_data;
|
||||
struct io_apic_irq_attr irq_attr = { 0 };
|
||||
|
||||
if (!pdata)
|
||||
return -EINVAL;
|
||||
|
||||
irq = pdata->irq;
|
||||
ioapic = mp_find_ioapic(irq);
|
||||
if (ioapic >= 0) {
|
||||
int ret;
|
||||
irq_attr.ioapic = ioapic;
|
||||
irq_attr.ioapic_pin = irq;
|
||||
irq_attr.trigger = 1;
|
||||
/* irq_attr.polarity = 0; -> Active high */
|
||||
ret = io_apic_set_pci_routing(NULL, irq, &irq_attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
/* IOAPIC builds identity mapping between GSI and IRQ on MID */
|
||||
gsi = pdata->irq;
|
||||
if (mp_set_gsi_attr(gsi, 1, 0, cpu_to_node(0)) ||
|
||||
mp_map_gsi_to_irq(gsi, IOAPIC_MAP_ALLOC) <= 0) {
|
||||
dev_warn(&pdev->dev, "cannot find interrupt %d in ioapic\n",
|
||||
irq);
|
||||
gsi);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -432,9 +432,8 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
|
||||
struct sfi_table_simple *sb;
|
||||
struct sfi_device_table_entry *pentry;
|
||||
struct devs_id *dev = NULL;
|
||||
int num, i;
|
||||
int ioapic;
|
||||
struct io_apic_irq_attr irq_attr;
|
||||
int num, i, ret;
|
||||
int polarity;
|
||||
|
||||
sb = (struct sfi_table_simple *)table;
|
||||
num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry);
|
||||
@ -448,35 +447,30 @@ static int __init sfi_parse_devs(struct sfi_table_header *table)
|
||||
* devices, but they have separate RTE entry in IOAPIC
|
||||
* so we have to enable them one by one here
|
||||
*/
|
||||
ioapic = mp_find_ioapic(irq);
|
||||
if (ioapic >= 0) {
|
||||
irq_attr.ioapic = ioapic;
|
||||
irq_attr.ioapic_pin = irq;
|
||||
irq_attr.trigger = 1;
|
||||
if (intel_mid_identify_cpu() ==
|
||||
INTEL_MID_CPU_CHIP_TANGIER) {
|
||||
if (!strncmp(pentry->name,
|
||||
"r69001-ts-i2c", 13))
|
||||
/* active low */
|
||||
irq_attr.polarity = 1;
|
||||
else if (!strncmp(pentry->name,
|
||||
"synaptics_3202", 14))
|
||||
/* active low */
|
||||
irq_attr.polarity = 1;
|
||||
else if (irq == 41)
|
||||
/* fast_int_1 */
|
||||
irq_attr.polarity = 1;
|
||||
else
|
||||
/* active high */
|
||||
irq_attr.polarity = 0;
|
||||
} else {
|
||||
/* PNW and CLV go with active low */
|
||||
irq_attr.polarity = 1;
|
||||
}
|
||||
io_apic_set_pci_routing(NULL, irq, &irq_attr);
|
||||
if (intel_mid_identify_cpu() ==
|
||||
INTEL_MID_CPU_CHIP_TANGIER) {
|
||||
if (!strncmp(pentry->name, "r69001-ts-i2c", 13))
|
||||
/* active low */
|
||||
polarity = 1;
|
||||
else if (!strncmp(pentry->name,
|
||||
"synaptics_3202", 14))
|
||||
/* active low */
|
||||
polarity = 1;
|
||||
else if (irq == 41)
|
||||
/* fast_int_1 */
|
||||
polarity = 1;
|
||||
else
|
||||
/* active high */
|
||||
polarity = 0;
|
||||
} else {
|
||||
/* PNW and CLV go with active low */
|
||||
polarity = 1;
|
||||
}
|
||||
} else {
|
||||
irq = 0; /* No irq */
|
||||
|
||||
ret = mp_set_gsi_attr(irq, 1, polarity, NUMA_NO_NODE);
|
||||
if (ret == 0)
|
||||
ret = mp_map_gsi_to_irq(irq, IOAPIC_MAP_ALLOC);
|
||||
WARN_ON(ret < 0);
|
||||
}
|
||||
|
||||
dev = get_device_id(pentry->type, pentry->name);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/sfi.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irqdomain.h>
|
||||
|
||||
#include <asm/io_apic.h>
|
||||
#include <asm/mpspec.h>
|
||||
@ -70,19 +71,26 @@ static int __init sfi_parse_cpus(struct sfi_table_header *table)
|
||||
#endif /* CONFIG_X86_LOCAL_APIC */
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
static struct irq_domain_ops sfi_ioapic_irqdomain_ops = {
|
||||
.map = mp_irqdomain_map,
|
||||
};
|
||||
|
||||
static int __init sfi_parse_ioapic(struct sfi_table_header *table)
|
||||
{
|
||||
struct sfi_table_simple *sb;
|
||||
struct sfi_apic_table_entry *pentry;
|
||||
int i, num;
|
||||
struct ioapic_domain_cfg cfg = {
|
||||
.type = IOAPIC_DOMAIN_STRICT,
|
||||
.ops = &sfi_ioapic_irqdomain_ops,
|
||||
};
|
||||
|
||||
sb = (struct sfi_table_simple *)table;
|
||||
num = SFI_GET_NUM_ENTRIES(sb, struct sfi_apic_table_entry);
|
||||
pentry = (struct sfi_apic_table_entry *)sb->pentry;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
mp_register_ioapic(i, pentry->phys_addr, gsi_top);
|
||||
mp_register_ioapic(i, pentry->phys_addr, gsi_top, &cfg);
|
||||
pentry++;
|
||||
}
|
||||
|
||||
|
@ -481,6 +481,10 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
|
||||
if (!pin)
|
||||
return;
|
||||
|
||||
/* Keep IOAPIC pin configuration when suspending */
|
||||
if (dev->dev.power.is_prepared)
|
||||
return;
|
||||
|
||||
entry = acpi_pci_irq_lookup(dev, pin);
|
||||
if (!entry)
|
||||
return;
|
||||
@ -498,5 +502,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
|
||||
*/
|
||||
|
||||
dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
|
||||
acpi_unregister_gsi(gsi);
|
||||
if (gsi >= 0 && dev->irq > 0)
|
||||
acpi_unregister_gsi(gsi);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user