mirror of
https://github.com/fail0verflow/switch-linux.git
synced 2025-05-04 02:34:21 -04:00
Merge branch 'irq-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'irq-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (76 commits) x86, apic: Fix dummy apic read operation together with broken MP handling x86, apic: Restore irqs on fail paths x86: Print real IOAPIC version for x86-64 x86: enable_update_mptable should be a macro sparseirq: Allow early irq_desc allocation x86, io-apic: Don't mark pin_programmed early x86, irq: don't call mp_config_acpi_gsi() if update_mptable is not enabled x86, irq: update_mptable needs pci_routeirq x86: don't call read_apic_id if !cpu_has_apic x86, apic: introduce io_apic_irq_attr x86/pci: add 4 more return parameters to IO_APIC_get_PCI_irq_vector(), fix x86: read apic ID in the !acpi_lapic case x86: apic: Fixmap apic address even if apic disabled x86: display extended apic registers with print_local_APIC and cpu_debug code x86: read apic ID in the !acpi_lapic case x86: clean up and fix setup_clear/force_cpu_cap handling x86: apic: Check rev 3 fadt correctly for physical_apic bit x86/pci: update pirq_enable_irq() to setup io apic routing x86/acpi: move setup io apic routing out of CONFIG_ACPI scope x86/pci: add 4 more return parameters to IO_APIC_get_PCI_irq_vector() ...
This commit is contained in:
commit
f0d5e12bd4
80 changed files with 1271 additions and 1334 deletions
|
@ -1575,6 +1575,9 @@ and is between 256 and 4096 characters. It is defined in the file
|
||||||
noinitrd [RAM] Tells the kernel not to load any configured
|
noinitrd [RAM] Tells the kernel not to load any configured
|
||||||
initial RAM disk.
|
initial RAM disk.
|
||||||
|
|
||||||
|
nointremap [X86-64, Intel-IOMMU] Do not enable interrupt
|
||||||
|
remapping.
|
||||||
|
|
||||||
nointroute [IA-64]
|
nointroute [IA-64]
|
||||||
|
|
||||||
nojitter [IA64] Disables jitter checking for ITC timers.
|
nojitter [IA64] Disables jitter checking for ITC timers.
|
||||||
|
|
|
@ -176,22 +176,26 @@ cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
dp264_set_affinity(unsigned int irq, const struct cpumask *affinity)
|
dp264_set_affinity(unsigned int irq, const struct cpumask *affinity)
|
||||||
{
|
{
|
||||||
spin_lock(&dp264_irq_lock);
|
spin_lock(&dp264_irq_lock);
|
||||||
cpu_set_irq_affinity(irq, *affinity);
|
cpu_set_irq_affinity(irq, *affinity);
|
||||||
tsunami_update_irq_hw(cached_irq_mask);
|
tsunami_update_irq_hw(cached_irq_mask);
|
||||||
spin_unlock(&dp264_irq_lock);
|
spin_unlock(&dp264_irq_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
clipper_set_affinity(unsigned int irq, const struct cpumask *affinity)
|
clipper_set_affinity(unsigned int irq, const struct cpumask *affinity)
|
||||||
{
|
{
|
||||||
spin_lock(&dp264_irq_lock);
|
spin_lock(&dp264_irq_lock);
|
||||||
cpu_set_irq_affinity(irq - 16, *affinity);
|
cpu_set_irq_affinity(irq - 16, *affinity);
|
||||||
tsunami_update_irq_hw(cached_irq_mask);
|
tsunami_update_irq_hw(cached_irq_mask);
|
||||||
spin_unlock(&dp264_irq_lock);
|
spin_unlock(&dp264_irq_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct hw_interrupt_type dp264_irq_type = {
|
static struct hw_interrupt_type dp264_irq_type = {
|
||||||
|
|
|
@ -157,13 +157,15 @@ titan_cpu_set_irq_affinity(unsigned int irq, cpumask_t affinity)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
titan_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
|
titan_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
|
||||||
{
|
{
|
||||||
spin_lock(&titan_irq_lock);
|
spin_lock(&titan_irq_lock);
|
||||||
titan_cpu_set_irq_affinity(irq - 16, *affinity);
|
titan_cpu_set_irq_affinity(irq - 16, *affinity);
|
||||||
titan_update_irq_hw(titan_cached_irq_mask);
|
titan_update_irq_hw(titan_cached_irq_mask);
|
||||||
spin_unlock(&titan_irq_lock);
|
spin_unlock(&titan_irq_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -109,7 +109,7 @@ static void gic_unmask_irq(unsigned int irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
static void gic_set_cpu(unsigned int irq, const struct cpumask *mask_val)
|
static int gic_set_cpu(unsigned int irq, const struct cpumask *mask_val)
|
||||||
{
|
{
|
||||||
void __iomem *reg = gic_dist_base(irq) + GIC_DIST_TARGET + (gic_irq(irq) & ~3);
|
void __iomem *reg = gic_dist_base(irq) + GIC_DIST_TARGET + (gic_irq(irq) & ~3);
|
||||||
unsigned int shift = (irq % 4) * 8;
|
unsigned int shift = (irq % 4) * 8;
|
||||||
|
@ -122,6 +122,8 @@ static void gic_set_cpu(unsigned int irq, const struct cpumask *mask_val)
|
||||||
val |= 1 << (cpu + shift);
|
val |= 1 << (cpu + shift);
|
||||||
writel(val, reg);
|
writel(val, reg);
|
||||||
spin_unlock(&irq_controller_lock);
|
spin_unlock(&irq_controller_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -325,12 +325,14 @@ static void end_crisv32_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_affinity_crisv32_irq(unsigned int irq, const struct cpumask *dest)
|
int set_affinity_crisv32_irq(unsigned int irq, const struct cpumask *dest)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
spin_lock_irqsave(&irq_lock, flags);
|
spin_lock_irqsave(&irq_lock, flags);
|
||||||
irq_allocations[irq - FIRST_IRQ].mask = *dest;
|
irq_allocations[irq - FIRST_IRQ].mask = *dest;
|
||||||
spin_unlock_irqrestore(&irq_lock, flags);
|
spin_unlock_irqrestore(&irq_lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct irq_chip crisv32_irq_type = {
|
static struct irq_chip crisv32_irq_type = {
|
||||||
|
|
|
@ -21,9 +21,10 @@ hpsim_irq_noop (unsigned int irq)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
hpsim_set_affinity_noop(unsigned int a, const struct cpumask *b)
|
hpsim_set_affinity_noop(unsigned int a, const struct cpumask *b)
|
||||||
{
|
{
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct hw_interrupt_type irq_type_hp_sim = {
|
static struct hw_interrupt_type irq_type_hp_sim = {
|
||||||
|
|
|
@ -636,7 +636,7 @@ void __init acpi_numa_arch_fixup(void)
|
||||||
* success: return IRQ number (>=0)
|
* success: return IRQ number (>=0)
|
||||||
* failure: return < 0
|
* failure: return < 0
|
||||||
*/
|
*/
|
||||||
int acpi_register_gsi(u32 gsi, int triggering, int polarity)
|
int acpi_register_gsi(struct device *dev, u32 gsi, int triggering, int polarity)
|
||||||
{
|
{
|
||||||
if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
|
if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
|
||||||
return gsi;
|
return gsi;
|
||||||
|
@ -678,7 +678,8 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table)
|
||||||
|
|
||||||
fadt = (struct acpi_table_fadt *)fadt_header;
|
fadt = (struct acpi_table_fadt *)fadt_header;
|
||||||
|
|
||||||
acpi_register_gsi(fadt->sci_interrupt, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
|
acpi_register_gsi(NULL, fadt->sci_interrupt, ACPI_LEVEL_SENSITIVE,
|
||||||
|
ACPI_ACTIVE_LOW);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -329,7 +329,7 @@ unmask_irq (unsigned int irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static int
|
||||||
iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
|
iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
@ -343,15 +343,15 @@ iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
|
||||||
|
|
||||||
cpu = cpumask_first_and(cpu_online_mask, mask);
|
cpu = cpumask_first_and(cpu_online_mask, mask);
|
||||||
if (cpu >= nr_cpu_ids)
|
if (cpu >= nr_cpu_ids)
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
if (irq_prepare_move(irq, cpu))
|
if (irq_prepare_move(irq, cpu))
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
dest = cpu_physical_id(cpu);
|
dest = cpu_physical_id(cpu);
|
||||||
|
|
||||||
if (!iosapic_intr_info[irq].count)
|
if (!iosapic_intr_info[irq].count)
|
||||||
return; /* not an IOSAPIC interrupt */
|
return -1; /* not an IOSAPIC interrupt */
|
||||||
|
|
||||||
set_irq_affinity_info(irq, dest, redir);
|
set_irq_affinity_info(irq, dest, redir);
|
||||||
|
|
||||||
|
@ -376,7 +376,9 @@ iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
|
||||||
iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
|
iosapic_write(iosapic, IOSAPIC_RTE_HIGH(rte_index), high32);
|
||||||
iosapic_write(iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
|
iosapic_write(iosapic, IOSAPIC_RTE_LOW(rte_index), low32);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
static struct irq_chip ia64_msi_chip;
|
static struct irq_chip ia64_msi_chip;
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
static void ia64_set_msi_irq_affinity(unsigned int irq,
|
static int ia64_set_msi_irq_affinity(unsigned int irq,
|
||||||
const cpumask_t *cpu_mask)
|
const cpumask_t *cpu_mask)
|
||||||
{
|
{
|
||||||
struct msi_msg msg;
|
struct msi_msg msg;
|
||||||
|
@ -20,10 +20,10 @@ static void ia64_set_msi_irq_affinity(unsigned int irq,
|
||||||
int cpu = first_cpu(*cpu_mask);
|
int cpu = first_cpu(*cpu_mask);
|
||||||
|
|
||||||
if (!cpu_online(cpu))
|
if (!cpu_online(cpu))
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
if (irq_prepare_move(irq, cpu))
|
if (irq_prepare_move(irq, cpu))
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
read_msi_msg(irq, &msg);
|
read_msi_msg(irq, &msg);
|
||||||
|
|
||||||
|
@ -39,6 +39,8 @@ static void ia64_set_msi_irq_affinity(unsigned int irq,
|
||||||
|
|
||||||
write_msi_msg(irq, &msg);
|
write_msi_msg(irq, &msg);
|
||||||
cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
|
cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
|
|
||||||
|
@ -130,17 +132,17 @@ void arch_teardown_msi_irq(unsigned int irq)
|
||||||
|
|
||||||
#ifdef CONFIG_DMAR
|
#ifdef CONFIG_DMAR
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
|
static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
|
||||||
{
|
{
|
||||||
struct irq_cfg *cfg = irq_cfg + irq;
|
struct irq_cfg *cfg = irq_cfg + irq;
|
||||||
struct msi_msg msg;
|
struct msi_msg msg;
|
||||||
int cpu = cpumask_first(mask);
|
int cpu = cpumask_first(mask);
|
||||||
|
|
||||||
if (!cpu_online(cpu))
|
if (!cpu_online(cpu))
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
if (irq_prepare_move(irq, cpu))
|
if (irq_prepare_move(irq, cpu))
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
dmar_msi_read(irq, &msg);
|
dmar_msi_read(irq, &msg);
|
||||||
|
|
||||||
|
@ -151,6 +153,8 @@ static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
|
||||||
|
|
||||||
dmar_msi_write(irq, &msg);
|
dmar_msi_write(irq, &msg);
|
||||||
cpumask_copy(irq_desc[irq].affinity, mask);
|
cpumask_copy(irq_desc[irq].affinity, mask);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
|
|
||||||
|
|
|
@ -227,7 +227,7 @@ finish_up:
|
||||||
return new_irq_info;
|
return new_irq_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask)
|
static int sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask)
|
||||||
{
|
{
|
||||||
struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
|
struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
|
||||||
nasid_t nasid;
|
nasid_t nasid;
|
||||||
|
@ -239,6 +239,8 @@ static void sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask)
|
||||||
list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
|
list_for_each_entry_safe(sn_irq_info, sn_irq_info_safe,
|
||||||
sn_irq_lh[irq], list)
|
sn_irq_lh[irq], list)
|
||||||
(void)sn_retarget_vector(sn_irq_info, nasid, slice);
|
(void)sn_retarget_vector(sn_irq_info, nasid, slice);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
|
|
@ -151,7 +151,7 @@ int sn_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
static void sn_set_msi_irq_affinity(unsigned int irq,
|
static int sn_set_msi_irq_affinity(unsigned int irq,
|
||||||
const struct cpumask *cpu_mask)
|
const struct cpumask *cpu_mask)
|
||||||
{
|
{
|
||||||
struct msi_msg msg;
|
struct msi_msg msg;
|
||||||
|
@ -168,7 +168,7 @@ static void sn_set_msi_irq_affinity(unsigned int irq,
|
||||||
cpu = cpumask_first(cpu_mask);
|
cpu = cpumask_first(cpu_mask);
|
||||||
sn_irq_info = sn_msi_info[irq].sn_irq_info;
|
sn_irq_info = sn_msi_info[irq].sn_irq_info;
|
||||||
if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
|
if (sn_irq_info == NULL || sn_irq_info->irq_int_bit >= 0)
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release XIO resources for the old MSI PCI address
|
* Release XIO resources for the old MSI PCI address
|
||||||
|
@ -189,7 +189,7 @@ static void sn_set_msi_irq_affinity(unsigned int irq,
|
||||||
new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice);
|
new_irq_info = sn_retarget_vector(sn_irq_info, nasid, slice);
|
||||||
sn_msi_info[irq].sn_irq_info = new_irq_info;
|
sn_msi_info[irq].sn_irq_info = new_irq_info;
|
||||||
if (new_irq_info == NULL)
|
if (new_irq_info == NULL)
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Map the xio address into bus space
|
* Map the xio address into bus space
|
||||||
|
@ -206,6 +206,8 @@ static void sn_set_msi_irq_affinity(unsigned int irq,
|
||||||
|
|
||||||
write_msi_msg(irq, &msg);
|
write_msi_msg(irq, &msg);
|
||||||
cpumask_copy(irq_desc[irq].affinity, cpu_mask);
|
cpumask_copy(irq_desc[irq].affinity, cpu_mask);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
|
|
||||||
|
|
|
@ -177,7 +177,7 @@ static void octeon_irq_ciu0_disable(unsigned int irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
static void octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest)
|
static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest)
|
||||||
{
|
{
|
||||||
int cpu;
|
int cpu;
|
||||||
int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */
|
int bit = irq - OCTEON_IRQ_WORKQ0; /* Bit 0-63 of EN0 */
|
||||||
|
@ -199,6 +199,8 @@ static void octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask
|
||||||
*/
|
*/
|
||||||
cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
|
cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
|
||||||
write_unlock(&octeon_irq_ciu0_rwlock);
|
write_unlock(&octeon_irq_ciu0_rwlock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -292,7 +294,7 @@ static void octeon_irq_ciu1_disable(unsigned int irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
static void octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *dest)
|
static int octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask *dest)
|
||||||
{
|
{
|
||||||
int cpu;
|
int cpu;
|
||||||
int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */
|
int bit = irq - OCTEON_IRQ_WDOG0; /* Bit 0-63 of EN1 */
|
||||||
|
@ -315,6 +317,8 @@ static void octeon_irq_ciu1_set_affinity(unsigned int irq, const struct cpumask
|
||||||
*/
|
*/
|
||||||
cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
|
cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
|
||||||
write_unlock(&octeon_irq_ciu1_rwlock);
|
write_unlock(&octeon_irq_ciu1_rwlock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ static inline void smtc_im_ack_irq(unsigned int irq)
|
||||||
#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
|
#ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
|
||||||
#include <linux/cpumask.h>
|
#include <linux/cpumask.h>
|
||||||
|
|
||||||
extern void plat_set_irq_affinity(unsigned int irq,
|
extern int plat_set_irq_affinity(unsigned int irq,
|
||||||
const struct cpumask *affinity);
|
const struct cpumask *affinity);
|
||||||
extern void smtc_forward_irq(unsigned int irq);
|
extern void smtc_forward_irq(unsigned int irq);
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,7 @@ static void gic_unmask_irq(unsigned int irq)
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(gic_lock);
|
static DEFINE_SPINLOCK(gic_lock);
|
||||||
|
|
||||||
static void gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
|
static int gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
|
||||||
{
|
{
|
||||||
cpumask_t tmp = CPU_MASK_NONE;
|
cpumask_t tmp = CPU_MASK_NONE;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
@ -166,7 +166,7 @@ static void gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
|
||||||
|
|
||||||
cpumask_and(&tmp, cpumask, cpu_online_mask);
|
cpumask_and(&tmp, cpumask, cpu_online_mask);
|
||||||
if (cpus_empty(tmp))
|
if (cpus_empty(tmp))
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
/* Assumption : cpumask refers to a single CPU */
|
/* Assumption : cpumask refers to a single CPU */
|
||||||
spin_lock_irqsave(&gic_lock, flags);
|
spin_lock_irqsave(&gic_lock, flags);
|
||||||
|
@ -190,6 +190,7 @@ static void gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
|
||||||
cpumask_copy(irq_desc[irq].affinity, cpumask);
|
cpumask_copy(irq_desc[irq].affinity, cpumask);
|
||||||
spin_unlock_irqrestore(&gic_lock, flags);
|
spin_unlock_irqrestore(&gic_lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ struct plat_smp_ops msmtc_smp_ops = {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
void plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
|
int plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
|
||||||
{
|
{
|
||||||
cpumask_t tmask;
|
cpumask_t tmask;
|
||||||
int cpu = 0;
|
int cpu = 0;
|
||||||
|
@ -156,5 +156,7 @@ void plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
|
||||||
|
|
||||||
/* Do any generic SMTC IRQ affinity setup */
|
/* Do any generic SMTC IRQ affinity setup */
|
||||||
smtc_set_irq_affinity(irq, tmask);
|
smtc_set_irq_affinity(irq, tmask);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
|
#endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
|
||||||
|
|
|
@ -50,7 +50,7 @@ static void enable_bcm1480_irq(unsigned int irq);
|
||||||
static void disable_bcm1480_irq(unsigned int irq);
|
static void disable_bcm1480_irq(unsigned int irq);
|
||||||
static void ack_bcm1480_irq(unsigned int irq);
|
static void ack_bcm1480_irq(unsigned int irq);
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask);
|
static int bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PCI
|
#ifdef CONFIG_PCI
|
||||||
|
@ -109,7 +109,7 @@ void bcm1480_unmask_irq(int cpu, int irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
|
static int bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
|
||||||
{
|
{
|
||||||
int i = 0, old_cpu, cpu, int_on, k;
|
int i = 0, old_cpu, cpu, int_on, k;
|
||||||
u64 cur_ints;
|
u64 cur_ints;
|
||||||
|
@ -118,7 +118,7 @@ static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
|
||||||
|
|
||||||
if (cpumask_weight(mask) != 1) {
|
if (cpumask_weight(mask) != 1) {
|
||||||
printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
|
printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
i = cpumask_first(mask);
|
i = cpumask_first(mask);
|
||||||
|
|
||||||
|
@ -152,6 +152,8 @@ static void bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&bcm1480_imr_lock, flags);
|
spin_unlock_irqrestore(&bcm1480_imr_lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ static void enable_sb1250_irq(unsigned int irq);
|
||||||
static void disable_sb1250_irq(unsigned int irq);
|
static void disable_sb1250_irq(unsigned int irq);
|
||||||
static void ack_sb1250_irq(unsigned int irq);
|
static void ack_sb1250_irq(unsigned int irq);
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask);
|
static int sb1250_set_affinity(unsigned int irq, const struct cpumask *mask);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SIBYTE_HAS_LDT
|
#ifdef CONFIG_SIBYTE_HAS_LDT
|
||||||
|
@ -103,7 +103,7 @@ void sb1250_unmask_irq(int cpu, int irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
|
static int sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
|
||||||
{
|
{
|
||||||
int i = 0, old_cpu, cpu, int_on;
|
int i = 0, old_cpu, cpu, int_on;
|
||||||
u64 cur_ints;
|
u64 cur_ints;
|
||||||
|
@ -113,7 +113,7 @@ static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
|
||||||
|
|
||||||
if (cpumask_weight(mask) > 1) {
|
if (cpumask_weight(mask) > 1) {
|
||||||
printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
|
printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert logical CPU to physical CPU */
|
/* Convert logical CPU to physical CPU */
|
||||||
|
@ -143,6 +143,8 @@ static void sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
|
||||||
R_IMR_INTERRUPT_MASK));
|
R_IMR_INTERRUPT_MASK));
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&sb1250_imr_lock, flags);
|
spin_unlock_irqrestore(&sb1250_imr_lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -130,15 +130,17 @@ int cpu_check_affinity(unsigned int irq, const struct cpumask *dest)
|
||||||
return cpu_dest;
|
return cpu_dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest)
|
static int cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest)
|
||||||
{
|
{
|
||||||
int cpu_dest;
|
int cpu_dest;
|
||||||
|
|
||||||
cpu_dest = cpu_check_affinity(irq, dest);
|
cpu_dest = cpu_check_affinity(irq, dest);
|
||||||
if (cpu_dest < 0)
|
if (cpu_dest < 0)
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
cpumask_copy(&irq_desc[irq].affinity, dest);
|
cpumask_copy(&irq_desc[irq].affinity, dest);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -333,7 +333,7 @@ static void xics_eoi_lpar(unsigned int virq)
|
||||||
lpar_xirr_info_set((0xff << 24) | irq);
|
lpar_xirr_info_set((0xff << 24) | irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
|
static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
|
||||||
{
|
{
|
||||||
unsigned int irq;
|
unsigned int irq;
|
||||||
int status;
|
int status;
|
||||||
|
@ -342,14 +342,14 @@ static void xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
|
||||||
|
|
||||||
irq = (unsigned int)irq_map[virq].hwirq;
|
irq = (unsigned int)irq_map[virq].hwirq;
|
||||||
if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
|
if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
|
status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
|
printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
|
||||||
__func__, irq, status);
|
__func__, irq, status);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -363,7 +363,7 @@ static void xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"%s: No online cpus in the mask %s for irq %d\n",
|
"%s: No online cpus in the mask %s for irq %d\n",
|
||||||
__func__, cpulist, virq);
|
__func__, cpulist, virq);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = rtas_call(ibm_set_xive, 3, 1, NULL,
|
status = rtas_call(ibm_set_xive, 3, 1, NULL,
|
||||||
|
@ -372,8 +372,10 @@ static void xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
|
||||||
if (status) {
|
if (status) {
|
||||||
printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
|
printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
|
||||||
__func__, irq, status);
|
__func__, irq, status);
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct irq_chip xics_pic_direct = {
|
static struct irq_chip xics_pic_direct = {
|
||||||
|
|
|
@ -807,7 +807,7 @@ static void mpic_end_ipi(unsigned int irq)
|
||||||
|
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
|
|
||||||
void mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
|
int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
|
||||||
{
|
{
|
||||||
struct mpic *mpic = mpic_from_irq(irq);
|
struct mpic *mpic = mpic_from_irq(irq);
|
||||||
unsigned int src = mpic_irq_to_hw(irq);
|
unsigned int src = mpic_irq_to_hw(irq);
|
||||||
|
@ -824,6 +824,8 @@ void mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
|
||||||
mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
|
mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
|
||||||
mpic_physmask(cpus_addr(tmp)[0]));
|
mpic_physmask(cpus_addr(tmp)[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
|
static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
|
||||||
|
|
|
@ -36,6 +36,6 @@ static inline int mpic_pasemi_msi_init(struct mpic *mpic)
|
||||||
|
|
||||||
extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
|
extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
|
||||||
extern void mpic_set_vector(unsigned int virq, unsigned int vector);
|
extern void mpic_set_vector(unsigned int virq, unsigned int vector);
|
||||||
extern void mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask);
|
extern int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask);
|
||||||
|
|
||||||
#endif /* _POWERPC_SYSDEV_MPIC_H */
|
#endif /* _POWERPC_SYSDEV_MPIC_H */
|
||||||
|
|
|
@ -318,10 +318,12 @@ static void sun4u_irq_enable(unsigned int virt_irq)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sun4u_set_affinity(unsigned int virt_irq,
|
static int sun4u_set_affinity(unsigned int virt_irq,
|
||||||
const struct cpumask *mask)
|
const struct cpumask *mask)
|
||||||
{
|
{
|
||||||
sun4u_irq_enable(virt_irq);
|
sun4u_irq_enable(virt_irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't do anything. The desc->status check for IRQ_DISABLED in
|
/* Don't do anything. The desc->status check for IRQ_DISABLED in
|
||||||
|
@ -377,7 +379,7 @@ static void sun4v_irq_enable(unsigned int virt_irq)
|
||||||
ino, err);
|
ino, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sun4v_set_affinity(unsigned int virt_irq,
|
static int sun4v_set_affinity(unsigned int virt_irq,
|
||||||
const struct cpumask *mask)
|
const struct cpumask *mask)
|
||||||
{
|
{
|
||||||
unsigned int ino = virt_irq_table[virt_irq].dev_ino;
|
unsigned int ino = virt_irq_table[virt_irq].dev_ino;
|
||||||
|
@ -388,6 +390,8 @@ static void sun4v_set_affinity(unsigned int virt_irq,
|
||||||
if (err != HV_EOK)
|
if (err != HV_EOK)
|
||||||
printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): "
|
printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): "
|
||||||
"err(%d)\n", ino, cpuid, err);
|
"err(%d)\n", ino, cpuid, err);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sun4v_irq_disable(unsigned int virt_irq)
|
static void sun4v_irq_disable(unsigned int virt_irq)
|
||||||
|
@ -445,7 +449,7 @@ static void sun4v_virq_enable(unsigned int virt_irq)
|
||||||
dev_handle, dev_ino, err);
|
dev_handle, dev_ino, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sun4v_virt_set_affinity(unsigned int virt_irq,
|
static int sun4v_virt_set_affinity(unsigned int virt_irq,
|
||||||
const struct cpumask *mask)
|
const struct cpumask *mask)
|
||||||
{
|
{
|
||||||
unsigned long cpuid, dev_handle, dev_ino;
|
unsigned long cpuid, dev_handle, dev_ino;
|
||||||
|
@ -461,6 +465,8 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq,
|
||||||
printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): "
|
printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): "
|
||||||
"err(%d)\n",
|
"err(%d)\n",
|
||||||
dev_handle, dev_ino, cpuid, err);
|
dev_handle, dev_ino, cpuid, err);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sun4v_virq_disable(unsigned int virt_irq)
|
static void sun4v_virq_disable(unsigned int virt_irq)
|
||||||
|
|
|
@ -274,15 +274,9 @@ config SPARSE_IRQ
|
||||||
|
|
||||||
If you don't know what to do here, say N.
|
If you don't know what to do here, say N.
|
||||||
|
|
||||||
config NUMA_MIGRATE_IRQ_DESC
|
config NUMA_IRQ_DESC
|
||||||
bool "Move irq desc when changing irq smp_affinity"
|
def_bool y
|
||||||
depends on SPARSE_IRQ && NUMA
|
depends on SPARSE_IRQ && NUMA
|
||||||
depends on BROKEN
|
|
||||||
default n
|
|
||||||
---help---
|
|
||||||
This enables moving irq_desc to cpu/node that irq will use handled.
|
|
||||||
|
|
||||||
If you don't know what to do here, say N.
|
|
||||||
|
|
||||||
config X86_MPPARSE
|
config X86_MPPARSE
|
||||||
bool "Enable MPS table" if ACPI
|
bool "Enable MPS table" if ACPI
|
||||||
|
@ -355,7 +349,7 @@ config X86_UV
|
||||||
depends on X86_64
|
depends on X86_64
|
||||||
depends on X86_EXTENDED_PLATFORM
|
depends on X86_EXTENDED_PLATFORM
|
||||||
depends on NUMA
|
depends on NUMA
|
||||||
select X86_X2APIC
|
depends on X86_X2APIC
|
||||||
---help---
|
---help---
|
||||||
This option is needed in order to support SGI Ultraviolet systems.
|
This option is needed in order to support SGI Ultraviolet systems.
|
||||||
If you don't have one of these, you should say N here.
|
If you don't have one of these, you should say N here.
|
||||||
|
|
|
@ -195,7 +195,6 @@ CONFIG_HIGH_RES_TIMERS=y
|
||||||
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
|
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
|
||||||
CONFIG_SMP=y
|
CONFIG_SMP=y
|
||||||
CONFIG_SPARSE_IRQ=y
|
CONFIG_SPARSE_IRQ=y
|
||||||
# CONFIG_NUMA_MIGRATE_IRQ_DESC is not set
|
|
||||||
CONFIG_X86_FIND_SMP_CONFIG=y
|
CONFIG_X86_FIND_SMP_CONFIG=y
|
||||||
CONFIG_X86_MPPARSE=y
|
CONFIG_X86_MPPARSE=y
|
||||||
# CONFIG_X86_ELAN is not set
|
# CONFIG_X86_ELAN is not set
|
||||||
|
|
|
@ -107,8 +107,7 @@ extern u32 native_safe_apic_wait_icr_idle(void);
|
||||||
extern void native_apic_icr_write(u32 low, u32 id);
|
extern void native_apic_icr_write(u32 low, u32 id);
|
||||||
extern u64 native_apic_icr_read(void);
|
extern u64 native_apic_icr_read(void);
|
||||||
|
|
||||||
#define EIM_8BIT_APIC_ID 0
|
extern int x2apic_mode;
|
||||||
#define EIM_32BIT_APIC_ID 1
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_X2APIC
|
#ifdef CONFIG_X86_X2APIC
|
||||||
/*
|
/*
|
||||||
|
@ -166,10 +165,9 @@ static inline u64 native_x2apic_icr_read(void)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int x2apic, x2apic_phys;
|
extern int x2apic_phys;
|
||||||
extern void check_x2apic(void);
|
extern void check_x2apic(void);
|
||||||
extern void enable_x2apic(void);
|
extern void enable_x2apic(void);
|
||||||
extern void enable_IR_x2apic(void);
|
|
||||||
extern void x2apic_icr_write(u32 low, u32 id);
|
extern void x2apic_icr_write(u32 low, u32 id);
|
||||||
static inline int x2apic_enabled(void)
|
static inline int x2apic_enabled(void)
|
||||||
{
|
{
|
||||||
|
@ -183,6 +181,8 @@ static inline int x2apic_enabled(void)
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define x2apic_supported() (cpu_has_x2apic)
|
||||||
#else
|
#else
|
||||||
static inline void check_x2apic(void)
|
static inline void check_x2apic(void)
|
||||||
{
|
{
|
||||||
|
@ -190,28 +190,20 @@ static inline void check_x2apic(void)
|
||||||
static inline void enable_x2apic(void)
|
static inline void enable_x2apic(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static inline void enable_IR_x2apic(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
static inline int x2apic_enabled(void)
|
static inline int x2apic_enabled(void)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define x2apic 0
|
#define x2apic_preenabled 0
|
||||||
|
#define x2apic_supported() 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern void enable_IR_x2apic(void);
|
||||||
|
|
||||||
extern int get_physical_broadcast(void);
|
extern int get_physical_broadcast(void);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_X2APIC
|
extern void apic_disable(void);
|
||||||
static inline void ack_x2APIC_irq(void)
|
|
||||||
{
|
|
||||||
/* Docs say use 0 for future compatibility */
|
|
||||||
native_apic_msr_write(APIC_EOI, 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern int lapic_get_maxlvt(void);
|
extern int lapic_get_maxlvt(void);
|
||||||
extern void clear_local_APIC(void);
|
extern void clear_local_APIC(void);
|
||||||
extern void connect_bsp_APIC(void);
|
extern void connect_bsp_APIC(void);
|
||||||
|
@ -252,7 +244,7 @@ static inline void lapic_shutdown(void) { }
|
||||||
#define local_apic_timer_c2_ok 1
|
#define local_apic_timer_c2_ok 1
|
||||||
static inline void init_apic_mappings(void) { }
|
static inline void init_apic_mappings(void) { }
|
||||||
static inline void disable_local_APIC(void) { }
|
static inline void disable_local_APIC(void) { }
|
||||||
|
static inline void apic_disable(void) { }
|
||||||
#endif /* !CONFIG_X86_LOCAL_APIC */
|
#endif /* !CONFIG_X86_LOCAL_APIC */
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
# define APIC_INTEGRATED(x) (1)
|
# define APIC_INTEGRATED(x) (1)
|
||||||
#endif
|
#endif
|
||||||
#define APIC_XAPIC(x) ((x) >= 0x14)
|
#define APIC_XAPIC(x) ((x) >= 0x14)
|
||||||
|
#define APIC_EXT_SPACE(x) ((x) & 0x80000000)
|
||||||
#define APIC_TASKPRI 0x80
|
#define APIC_TASKPRI 0x80
|
||||||
#define APIC_TPRI_MASK 0xFFu
|
#define APIC_TPRI_MASK 0xFFu
|
||||||
#define APIC_ARBPRI 0x90
|
#define APIC_ARBPRI 0x90
|
||||||
|
@ -116,7 +117,9 @@
|
||||||
#define APIC_TDR_DIV_32 0x8
|
#define APIC_TDR_DIV_32 0x8
|
||||||
#define APIC_TDR_DIV_64 0x9
|
#define APIC_TDR_DIV_64 0x9
|
||||||
#define APIC_TDR_DIV_128 0xA
|
#define APIC_TDR_DIV_128 0xA
|
||||||
#define APIC_EILVT0 0x500
|
#define APIC_EFEAT 0x400
|
||||||
|
#define APIC_ECTRL 0x410
|
||||||
|
#define APIC_EILVTn(n) (0x500 + 0x10 * n)
|
||||||
#define APIC_EILVT_NR_AMD_K8 1 /* # of extended interrupts */
|
#define APIC_EILVT_NR_AMD_K8 1 /* # of extended interrupts */
|
||||||
#define APIC_EILVT_NR_AMD_10H 4
|
#define APIC_EILVT_NR_AMD_10H 4
|
||||||
#define APIC_EILVT_LVTOFF(x) (((x) >> 4) & 0xF)
|
#define APIC_EILVT_LVTOFF(x) (((x) >> 4) & 0xF)
|
||||||
|
@ -125,9 +128,6 @@
|
||||||
#define APIC_EILVT_MSG_NMI 0x4
|
#define APIC_EILVT_MSG_NMI 0x4
|
||||||
#define APIC_EILVT_MSG_EXT 0x7
|
#define APIC_EILVT_MSG_EXT 0x7
|
||||||
#define APIC_EILVT_MASKED (1 << 16)
|
#define APIC_EILVT_MASKED (1 << 16)
|
||||||
#define APIC_EILVT1 0x510
|
|
||||||
#define APIC_EILVT2 0x520
|
|
||||||
#define APIC_EILVT3 0x530
|
|
||||||
|
|
||||||
#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
|
#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
|
||||||
#define APIC_BASE_MSR 0x800
|
#define APIC_BASE_MSR 0x800
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */
|
#define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */
|
||||||
#define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers */
|
#define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers */
|
||||||
#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */
|
#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */
|
||||||
#define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Architecture */
|
#define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Exception */
|
||||||
#define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */
|
#define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */
|
||||||
#define X86_FEATURE_APIC (0*32+ 9) /* Onboard APIC */
|
#define X86_FEATURE_APIC (0*32+ 9) /* Onboard APIC */
|
||||||
#define X86_FEATURE_SEP (0*32+11) /* SYSENTER/SYSEXIT */
|
#define X86_FEATURE_SEP (0*32+11) /* SYSENTER/SYSEXIT */
|
||||||
|
@ -192,11 +192,11 @@ extern const char * const x86_power_flags[32];
|
||||||
#define clear_cpu_cap(c, bit) clear_bit(bit, (unsigned long *)((c)->x86_capability))
|
#define clear_cpu_cap(c, bit) clear_bit(bit, (unsigned long *)((c)->x86_capability))
|
||||||
#define setup_clear_cpu_cap(bit) do { \
|
#define setup_clear_cpu_cap(bit) do { \
|
||||||
clear_cpu_cap(&boot_cpu_data, bit); \
|
clear_cpu_cap(&boot_cpu_data, bit); \
|
||||||
set_bit(bit, (unsigned long *)cleared_cpu_caps); \
|
set_bit(bit, (unsigned long *)cpu_caps_cleared); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define setup_force_cpu_cap(bit) do { \
|
#define setup_force_cpu_cap(bit) do { \
|
||||||
set_cpu_cap(&boot_cpu_data, bit); \
|
set_cpu_cap(&boot_cpu_data, bit); \
|
||||||
clear_bit(bit, (unsigned long *)cleared_cpu_caps); \
|
set_bit(bit, (unsigned long *)cpu_caps_set); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define cpu_has_fpu boot_cpu_has(X86_FEATURE_FPU)
|
#define cpu_has_fpu boot_cpu_has(X86_FEATURE_FPU)
|
||||||
|
|
|
@ -63,7 +63,26 @@ extern unsigned long io_apic_irqs;
|
||||||
extern void init_VISWS_APIC_irqs(void);
|
extern void init_VISWS_APIC_irqs(void);
|
||||||
extern void setup_IO_APIC(void);
|
extern void setup_IO_APIC(void);
|
||||||
extern void disable_IO_APIC(void);
|
extern void disable_IO_APIC(void);
|
||||||
extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
|
|
||||||
|
struct io_apic_irq_attr {
|
||||||
|
int ioapic;
|
||||||
|
int ioapic_pin;
|
||||||
|
int trigger;
|
||||||
|
int polarity;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void set_io_apic_irq_attr(struct io_apic_irq_attr *irq_attr,
|
||||||
|
int ioapic, int ioapic_pin,
|
||||||
|
int trigger, int polarity)
|
||||||
|
{
|
||||||
|
irq_attr->ioapic = ioapic;
|
||||||
|
irq_attr->ioapic_pin = ioapic_pin;
|
||||||
|
irq_attr->trigger = trigger;
|
||||||
|
irq_attr->polarity = polarity;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int IO_APIC_get_PCI_irq_vector(int bus, int devfn, int pin,
|
||||||
|
struct io_apic_irq_attr *irq_attr);
|
||||||
extern void setup_ioapic_dest(void);
|
extern void setup_ioapic_dest(void);
|
||||||
|
|
||||||
extern void enable_IO_APIC(void);
|
extern void enable_IO_APIC(void);
|
||||||
|
|
|
@ -60,8 +60,4 @@ extern struct irq_chip i8259A_chip;
|
||||||
extern void mask_8259A(void);
|
extern void mask_8259A(void);
|
||||||
extern void unmask_8259A(void);
|
extern void unmask_8259A(void);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
|
||||||
extern void init_ISA_irqs(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _ASM_X86_I8259_H */
|
#endif /* _ASM_X86_I8259_H */
|
||||||
|
|
|
@ -154,22 +154,19 @@ extern int timer_through_8259;
|
||||||
extern int io_apic_get_unique_id(int ioapic, int apic_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_version(int ioapic);
|
||||||
extern int io_apic_get_redir_entries(int ioapic);
|
extern int io_apic_get_redir_entries(int ioapic);
|
||||||
extern int io_apic_set_pci_routing(int ioapic, int pin, int irq,
|
|
||||||
int edge_level, int active_high_low);
|
|
||||||
#endif /* CONFIG_ACPI */
|
#endif /* CONFIG_ACPI */
|
||||||
|
|
||||||
|
struct io_apic_irq_attr;
|
||||||
|
extern int io_apic_set_pci_routing(struct device *dev, int irq,
|
||||||
|
struct io_apic_irq_attr *irq_attr);
|
||||||
extern int (*ioapic_renumber_irq)(int ioapic, int irq);
|
extern int (*ioapic_renumber_irq)(int ioapic, int irq);
|
||||||
extern void ioapic_init_mappings(void);
|
extern void ioapic_init_mappings(void);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
|
||||||
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);
|
||||||
extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
|
extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
|
||||||
extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
|
extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
|
||||||
extern void reinit_intr_remapped_IO_APIC(int intr_remapping,
|
|
||||||
struct IO_APIC_route_entry **ioapic_entries);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern void probe_nr_irqs_gsi(void);
|
extern void probe_nr_irqs_gsi(void);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#ifndef _ASM_X86_IRQ_REMAPPING_H
|
#ifndef _ASM_X86_IRQ_REMAPPING_H
|
||||||
#define _ASM_X86_IRQ_REMAPPING_H
|
#define _ASM_X86_IRQ_REMAPPING_H
|
||||||
|
|
||||||
#define IRTE_DEST(dest) ((x2apic) ? dest : dest << 8)
|
#define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8)
|
||||||
|
|
||||||
#endif /* _ASM_X86_IRQ_REMAPPING_H */
|
#endif /* _ASM_X86_IRQ_REMAPPING_H */
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
# define SYSCALL_VECTOR 0x80
|
# define SYSCALL_VECTOR 0x80
|
||||||
|
# define IA32_SYSCALL_VECTOR 0x80
|
||||||
#else
|
#else
|
||||||
# define IA32_SYSCALL_VECTOR 0x80
|
# define IA32_SYSCALL_VECTOR 0x80
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -61,9 +61,11 @@ extern void get_smp_config(void);
|
||||||
#ifdef CONFIG_X86_MPPARSE
|
#ifdef CONFIG_X86_MPPARSE
|
||||||
extern void find_smp_config(void);
|
extern void find_smp_config(void);
|
||||||
extern void early_reserve_e820_mpc_new(void);
|
extern void early_reserve_e820_mpc_new(void);
|
||||||
|
extern int enable_update_mptable;
|
||||||
#else
|
#else
|
||||||
static inline void find_smp_config(void) { }
|
static inline void find_smp_config(void) { }
|
||||||
static inline void early_reserve_e820_mpc_new(void) { }
|
static inline void early_reserve_e820_mpc_new(void) { }
|
||||||
|
#define enable_update_mptable 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void __cpuinit generic_processor_info(int apicid, int version);
|
void __cpuinit generic_processor_info(int apicid, int version);
|
||||||
|
@ -72,20 +74,13 @@ 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,
|
extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
|
||||||
u32 gsi);
|
u32 gsi);
|
||||||
extern void mp_config_acpi_legacy_irqs(void);
|
extern void mp_config_acpi_legacy_irqs(void);
|
||||||
extern int mp_register_gsi(u32 gsi, int edge_level, int active_high_low);
|
struct device;
|
||||||
|
extern int mp_register_gsi(struct device *dev, u32 gsi, int edge_level,
|
||||||
|
int active_high_low);
|
||||||
extern int acpi_probe_gsi(void);
|
extern int acpi_probe_gsi(void);
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
#ifdef CONFIG_X86_IO_APIC
|
||||||
extern int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
|
|
||||||
u32 gsi, int triggering, int polarity);
|
|
||||||
extern int mp_find_ioapic(int gsi);
|
extern int mp_find_ioapic(int gsi);
|
||||||
extern int mp_find_ioapic_pin(int ioapic, int gsi);
|
extern int mp_find_ioapic_pin(int ioapic, int gsi);
|
||||||
#else
|
|
||||||
static inline int
|
|
||||||
mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
|
|
||||||
u32 gsi, int triggering, int polarity)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#else /* !CONFIG_ACPI: */
|
#else /* !CONFIG_ACPI: */
|
||||||
static inline int acpi_probe_gsi(void)
|
static inline int acpi_probe_gsi(void)
|
||||||
|
|
|
@ -135,7 +135,8 @@ extern struct cpuinfo_x86 boot_cpu_data;
|
||||||
extern struct cpuinfo_x86 new_cpu_data;
|
extern struct cpuinfo_x86 new_cpu_data;
|
||||||
|
|
||||||
extern struct tss_struct doublefault_tss;
|
extern struct tss_struct doublefault_tss;
|
||||||
extern __u32 cleared_cpu_caps[NCAPINTS];
|
extern __u32 cpu_caps_cleared[NCAPINTS];
|
||||||
|
extern __u32 cpu_caps_set[NCAPINTS];
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
DECLARE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
|
DECLARE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
|
||||||
|
|
|
@ -33,7 +33,6 @@ struct x86_quirks {
|
||||||
int (*setup_ioapic_ids)(void);
|
int (*setup_ioapic_ids)(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern void x86_quirk_pre_intr_init(void);
|
|
||||||
extern void x86_quirk_intr_init(void);
|
extern void x86_quirk_intr_init(void);
|
||||||
|
|
||||||
extern void x86_quirk_trap_init(void);
|
extern void x86_quirk_trap_init(void);
|
||||||
|
|
|
@ -180,7 +180,7 @@ extern int safe_smp_processor_id(void);
|
||||||
static inline int logical_smp_processor_id(void)
|
static inline int logical_smp_processor_id(void)
|
||||||
{
|
{
|
||||||
/* we don't want to mark this access volatile - bad code generation */
|
/* we don't want to mark this access volatile - bad code generation */
|
||||||
return GET_APIC_LOGICAL_ID(*(u32 *)(APIC_BASE + APIC_LDR));
|
return GET_APIC_LOGICAL_ID(apic_read(APIC_LDR));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -28,7 +28,7 @@ CFLAGS_paravirt.o := $(nostackp)
|
||||||
obj-y := process_$(BITS).o signal.o entry_$(BITS).o
|
obj-y := process_$(BITS).o signal.o entry_$(BITS).o
|
||||||
obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
|
obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
|
||||||
obj-y += time_$(BITS).o ioport.o ldt.o dumpstack.o
|
obj-y += time_$(BITS).o ioport.o ldt.o dumpstack.o
|
||||||
obj-y += setup.o i8259.o irqinit_$(BITS).o
|
obj-y += setup.o i8259.o irqinit.o
|
||||||
obj-$(CONFIG_X86_VISWS) += visws_quirks.o
|
obj-$(CONFIG_X86_VISWS) += visws_quirks.o
|
||||||
obj-$(CONFIG_X86_32) += probe_roms_32.o
|
obj-$(CONFIG_X86_32) += probe_roms_32.o
|
||||||
obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o
|
obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/bootmem.h>
|
#include <linux/bootmem.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/io_apic.h>
|
#include <asm/io_apic.h>
|
||||||
|
@ -522,7 +523,7 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq)
|
||||||
* success: return IRQ number (>=0)
|
* success: return IRQ number (>=0)
|
||||||
* failure: return < 0
|
* failure: return < 0
|
||||||
*/
|
*/
|
||||||
int acpi_register_gsi(u32 gsi, int triggering, int polarity)
|
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
|
||||||
{
|
{
|
||||||
unsigned int irq;
|
unsigned int irq;
|
||||||
unsigned int plat_gsi = gsi;
|
unsigned int plat_gsi = gsi;
|
||||||
|
@ -532,14 +533,14 @@ int acpi_register_gsi(u32 gsi, int triggering, int polarity)
|
||||||
* Make sure all (legacy) PCI IRQs are set as level-triggered.
|
* Make sure all (legacy) PCI IRQs are set as level-triggered.
|
||||||
*/
|
*/
|
||||||
if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
|
if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
|
||||||
if (triggering == ACPI_LEVEL_SENSITIVE)
|
if (trigger == ACPI_LEVEL_SENSITIVE)
|
||||||
eisa_set_level_irq(gsi);
|
eisa_set_level_irq(gsi);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
#ifdef CONFIG_X86_IO_APIC
|
||||||
if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
|
if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) {
|
||||||
plat_gsi = mp_register_gsi(gsi, triggering, polarity);
|
plat_gsi = mp_register_gsi(dev, gsi, trigger, polarity);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
acpi_gsi_to_irq(plat_gsi, &irq);
|
acpi_gsi_to_irq(plat_gsi, &irq);
|
||||||
|
@ -903,10 +904,8 @@ extern int es7000_plat;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
int apic_id;
|
|
||||||
int gsi_base;
|
int gsi_base;
|
||||||
int gsi_end;
|
int gsi_end;
|
||||||
DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
|
|
||||||
} mp_ioapic_routing[MAX_IO_APICS];
|
} mp_ioapic_routing[MAX_IO_APICS];
|
||||||
|
|
||||||
int mp_find_ioapic(int gsi)
|
int mp_find_ioapic(int gsi)
|
||||||
|
@ -986,16 +985,12 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
|
||||||
|
|
||||||
set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
|
set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
|
||||||
mp_ioapics[idx].apicid = uniq_ioapic_id(id);
|
mp_ioapics[idx].apicid = uniq_ioapic_id(id);
|
||||||
#ifdef CONFIG_X86_32
|
|
||||||
mp_ioapics[idx].apicver = io_apic_get_version(idx);
|
mp_ioapics[idx].apicver = io_apic_get_version(idx);
|
||||||
#else
|
|
||||||
mp_ioapics[idx].apicver = 0;
|
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* Build basic GSI lookup table to facilitate gsi->io_apic lookups
|
* Build basic GSI lookup table to facilitate gsi->io_apic lookups
|
||||||
* and to prevent reprogramming of IOAPIC pins (PCI GSIs).
|
* and to prevent reprogramming of IOAPIC pins (PCI GSIs).
|
||||||
*/
|
*/
|
||||||
mp_ioapic_routing[idx].apic_id = mp_ioapics[idx].apicid;
|
|
||||||
mp_ioapic_routing[idx].gsi_base = gsi_base;
|
mp_ioapic_routing[idx].gsi_base = gsi_base;
|
||||||
mp_ioapic_routing[idx].gsi_end = gsi_base +
|
mp_ioapic_routing[idx].gsi_end = gsi_base +
|
||||||
io_apic_get_redir_entries(idx);
|
io_apic_get_redir_entries(idx);
|
||||||
|
@ -1158,26 +1153,52 @@ void __init mp_config_acpi_legacy_irqs(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int mp_register_gsi(u32 gsi, int triggering, int polarity)
|
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)
|
||||||
|
return 0;
|
||||||
|
if (dev->bus != &pci_bus_type)
|
||||||
|
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 = mp_ioapics[ioapic].apicid;
|
||||||
|
mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
|
||||||
|
|
||||||
|
save_mp_irq(&mp_irq);
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mp_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity)
|
||||||
{
|
{
|
||||||
int ioapic;
|
int ioapic;
|
||||||
int ioapic_pin;
|
int ioapic_pin;
|
||||||
#ifdef CONFIG_X86_32
|
struct io_apic_irq_attr irq_attr;
|
||||||
#define MAX_GSI_NUM 4096
|
|
||||||
#define IRQ_COMPRESSION_START 64
|
|
||||||
|
|
||||||
static int pci_irq = IRQ_COMPRESSION_START;
|
|
||||||
/*
|
|
||||||
* Mapping between Global System Interrupts, which
|
|
||||||
* represent all possible interrupts, and IRQs
|
|
||||||
* assigned to actual devices.
|
|
||||||
*/
|
|
||||||
static int gsi_to_irq[MAX_GSI_NUM];
|
|
||||||
#else
|
|
||||||
|
|
||||||
if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
|
if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
|
||||||
return gsi;
|
return gsi;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Don't set up the ACPI SCI because it's already set up */
|
/* Don't set up the ACPI SCI because it's already set up */
|
||||||
if (acpi_gbl_FADT.sci_interrupt == gsi)
|
if (acpi_gbl_FADT.sci_interrupt == gsi)
|
||||||
|
@ -1196,95 +1217,24 @@ int mp_register_gsi(u32 gsi, int triggering, int polarity)
|
||||||
gsi = ioapic_renumber_irq(ioapic, gsi);
|
gsi = ioapic_renumber_irq(ioapic, gsi);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Avoid pin reprogramming. PRTs typically include entries
|
|
||||||
* with redundant pin->gsi mappings (but unique PCI devices);
|
|
||||||
* we only program the IOAPIC on the first.
|
|
||||||
*/
|
|
||||||
if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
|
if (ioapic_pin > MP_MAX_IOAPIC_PIN) {
|
||||||
printk(KERN_ERR "Invalid reference to IOAPIC pin "
|
printk(KERN_ERR "Invalid reference to IOAPIC pin "
|
||||||
"%d-%d\n", mp_ioapic_routing[ioapic].apic_id,
|
"%d-%d\n", mp_ioapics[ioapic].apicid,
|
||||||
ioapic_pin);
|
ioapic_pin);
|
||||||
return gsi;
|
return gsi;
|
||||||
}
|
}
|
||||||
if (test_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed)) {
|
|
||||||
pr_debug("Pin %d-%d already programmed\n",
|
|
||||||
mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
|
|
||||||
#ifdef CONFIG_X86_32
|
|
||||||
return (gsi < IRQ_COMPRESSION_START ? gsi : gsi_to_irq[gsi]);
|
|
||||||
#else
|
|
||||||
return gsi;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
set_bit(ioapic_pin, mp_ioapic_routing[ioapic].pin_programmed);
|
if (enable_update_mptable)
|
||||||
#ifdef CONFIG_X86_32
|
mp_config_acpi_gsi(dev, gsi, trigger, polarity);
|
||||||
/*
|
|
||||||
* For GSI >= 64, use IRQ compression
|
set_io_apic_irq_attr(&irq_attr, ioapic, ioapic_pin,
|
||||||
*/
|
trigger == ACPI_EDGE_SENSITIVE ? 0 : 1,
|
||||||
if ((gsi >= IRQ_COMPRESSION_START)
|
|
||||||
&& (triggering == ACPI_LEVEL_SENSITIVE)) {
|
|
||||||
/*
|
|
||||||
* For PCI devices assign IRQs in order, avoiding gaps
|
|
||||||
* due to unused I/O APIC pins.
|
|
||||||
*/
|
|
||||||
int irq = gsi;
|
|
||||||
if (gsi < MAX_GSI_NUM) {
|
|
||||||
/*
|
|
||||||
* Retain the VIA chipset work-around (gsi > 15), but
|
|
||||||
* avoid a problem where the 8254 timer (IRQ0) is setup
|
|
||||||
* via an override (so it's not on pin 0 of the ioapic),
|
|
||||||
* and at the same time, the pin 0 interrupt is a PCI
|
|
||||||
* type. The gsi > 15 test could cause these two pins
|
|
||||||
* to be shared as IRQ0, and they are not shareable.
|
|
||||||
* So test for this condition, and if necessary, avoid
|
|
||||||
* the pin collision.
|
|
||||||
*/
|
|
||||||
gsi = pci_irq++;
|
|
||||||
/*
|
|
||||||
* Don't assign IRQ used by ACPI SCI
|
|
||||||
*/
|
|
||||||
if (gsi == acpi_gbl_FADT.sci_interrupt)
|
|
||||||
gsi = pci_irq++;
|
|
||||||
gsi_to_irq[irq] = gsi;
|
|
||||||
} else {
|
|
||||||
printk(KERN_ERR "GSI %u is too high\n", gsi);
|
|
||||||
return gsi;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
|
|
||||||
triggering == ACPI_EDGE_SENSITIVE ? 0 : 1,
|
|
||||||
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
|
polarity == ACPI_ACTIVE_HIGH ? 0 : 1);
|
||||||
|
io_apic_set_pci_routing(dev, gsi, &irq_attr);
|
||||||
|
|
||||||
return gsi;
|
return gsi;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mp_config_acpi_gsi(unsigned char number, unsigned int devfn, u8 pin,
|
|
||||||
u32 gsi, int triggering, int polarity)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_X86_MPPARSE
|
|
||||||
struct mpc_intsrc mp_irq;
|
|
||||||
int ioapic;
|
|
||||||
|
|
||||||
if (!acpi_ioapic)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* print the entry should happen on mptable identically */
|
|
||||||
mp_irq.type = MP_INTSRC;
|
|
||||||
mp_irq.irqtype = mp_INT;
|
|
||||||
mp_irq.irqflag = (triggering == 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 = mp_ioapic_routing[ioapic].apic_id;
|
|
||||||
mp_irq.dstirq = mp_find_ioapic_pin(ioapic, gsi);
|
|
||||||
|
|
||||||
save_mp_irq(&mp_irq);
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse IOAPIC related entries in MADT
|
* Parse IOAPIC related entries in MADT
|
||||||
* returns 0 on success, < 0 on error
|
* returns 0 on success, < 0 on error
|
||||||
|
|
|
@ -98,6 +98,29 @@ early_param("lapic", parse_lapic);
|
||||||
/* Local APIC was disabled by the BIOS and enabled by the kernel */
|
/* Local APIC was disabled by the BIOS and enabled by the kernel */
|
||||||
static int enabled_via_apicbase;
|
static int enabled_via_apicbase;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle interrupt mode configuration register (IMCR).
|
||||||
|
* This register controls whether the interrupt signals
|
||||||
|
* that reach the BSP come from the master PIC or from the
|
||||||
|
* local APIC. Before entering Symmetric I/O Mode, either
|
||||||
|
* the BIOS or the operating system must switch out of
|
||||||
|
* PIC Mode by changing the IMCR.
|
||||||
|
*/
|
||||||
|
static inline void imcr_pic_to_apic(void)
|
||||||
|
{
|
||||||
|
/* select IMCR register */
|
||||||
|
outb(0x70, 0x22);
|
||||||
|
/* NMI and 8259 INTR go through APIC */
|
||||||
|
outb(0x01, 0x23);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void imcr_apic_to_pic(void)
|
||||||
|
{
|
||||||
|
/* select IMCR register */
|
||||||
|
outb(0x70, 0x22);
|
||||||
|
/* NMI and 8259 INTR go directly to BSP */
|
||||||
|
outb(0x00, 0x23);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
|
@ -111,13 +134,19 @@ static __init int setup_apicpmtimer(char *s)
|
||||||
__setup("apicpmtimer", setup_apicpmtimer);
|
__setup("apicpmtimer", setup_apicpmtimer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int x2apic_mode;
|
||||||
#ifdef CONFIG_X86_X2APIC
|
#ifdef CONFIG_X86_X2APIC
|
||||||
int x2apic;
|
|
||||||
/* x2apic enabled before OS handover */
|
/* x2apic enabled before OS handover */
|
||||||
static int x2apic_preenabled;
|
static int x2apic_preenabled;
|
||||||
static int disable_x2apic;
|
static int disable_x2apic;
|
||||||
static __init int setup_nox2apic(char *str)
|
static __init int setup_nox2apic(char *str)
|
||||||
{
|
{
|
||||||
|
if (x2apic_enabled()) {
|
||||||
|
pr_warning("Bios already enabled x2apic, "
|
||||||
|
"can't enforce nox2apic");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
disable_x2apic = 1;
|
disable_x2apic = 1;
|
||||||
setup_clear_cpu_cap(X86_FEATURE_X2APIC);
|
setup_clear_cpu_cap(X86_FEATURE_X2APIC);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -209,6 +238,31 @@ static int modern_apic(void)
|
||||||
return lapic_get_version() >= 0x14;
|
return lapic_get_version() >= 0x14;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bare function to substitute write operation
|
||||||
|
* and it's _that_ fast :)
|
||||||
|
*/
|
||||||
|
static void native_apic_write_dummy(u32 reg, u32 v)
|
||||||
|
{
|
||||||
|
WARN_ON_ONCE((cpu_has_apic || !disable_apic));
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 native_apic_read_dummy(u32 reg)
|
||||||
|
{
|
||||||
|
WARN_ON_ONCE((cpu_has_apic && !disable_apic));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* right after this call apic->write/read doesn't do anything
|
||||||
|
* note that there is no restore operation it works one way
|
||||||
|
*/
|
||||||
|
void apic_disable(void)
|
||||||
|
{
|
||||||
|
apic->read = native_apic_read_dummy;
|
||||||
|
apic->write = native_apic_write_dummy;
|
||||||
|
}
|
||||||
|
|
||||||
void native_apic_wait_icr_idle(void)
|
void native_apic_wait_icr_idle(void)
|
||||||
{
|
{
|
||||||
while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
|
while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
|
||||||
|
@ -348,7 +402,7 @@ static void __setup_APIC_LVTT(unsigned int clocks, int oneshot, int irqen)
|
||||||
|
|
||||||
static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask)
|
static void setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask)
|
||||||
{
|
{
|
||||||
unsigned long reg = (lvt_off << 4) + APIC_EILVT0;
|
unsigned long reg = (lvt_off << 4) + APIC_EILVTn(0);
|
||||||
unsigned int v = (mask << 16) | (msg_type << 8) | vector;
|
unsigned int v = (mask << 16) | (msg_type << 8) | vector;
|
||||||
|
|
||||||
apic_write(reg, v);
|
apic_write(reg, v);
|
||||||
|
@ -815,7 +869,7 @@ void clear_local_APIC(void)
|
||||||
u32 v;
|
u32 v;
|
||||||
|
|
||||||
/* APIC hasn't been mapped yet */
|
/* APIC hasn't been mapped yet */
|
||||||
if (!x2apic && !apic_phys)
|
if (!x2apic_mode && !apic_phys)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
maxlvt = lapic_get_maxlvt();
|
maxlvt = lapic_get_maxlvt();
|
||||||
|
@ -1287,7 +1341,7 @@ void check_x2apic(void)
|
||||||
{
|
{
|
||||||
if (x2apic_enabled()) {
|
if (x2apic_enabled()) {
|
||||||
pr_info("x2apic enabled by BIOS, switching to x2apic ops\n");
|
pr_info("x2apic enabled by BIOS, switching to x2apic ops\n");
|
||||||
x2apic_preenabled = x2apic = 1;
|
x2apic_preenabled = x2apic_mode = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1295,7 +1349,7 @@ void enable_x2apic(void)
|
||||||
{
|
{
|
||||||
int msr, msr2;
|
int msr, msr2;
|
||||||
|
|
||||||
if (!x2apic)
|
if (!x2apic_mode)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rdmsr(MSR_IA32_APICBASE, msr, msr2);
|
rdmsr(MSR_IA32_APICBASE, msr, msr2);
|
||||||
|
@ -1304,6 +1358,7 @@ void enable_x2apic(void)
|
||||||
wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
|
wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* CONFIG_X86_X2APIC */
|
||||||
|
|
||||||
void __init enable_IR_x2apic(void)
|
void __init enable_IR_x2apic(void)
|
||||||
{
|
{
|
||||||
|
@ -1312,32 +1367,21 @@ 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 = NULL;
|
||||||
|
|
||||||
if (!cpu_has_x2apic)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!x2apic_preenabled && disable_x2apic) {
|
|
||||||
pr_info("Skipped enabling x2apic and Interrupt-remapping "
|
|
||||||
"because of nox2apic\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x2apic_preenabled && disable_x2apic)
|
|
||||||
panic("Bios already enabled x2apic, can't enforce nox2apic");
|
|
||||||
|
|
||||||
if (!x2apic_preenabled && skip_ioapic_setup) {
|
|
||||||
pr_info("Skipped enabling x2apic and Interrupt-remapping "
|
|
||||||
"because of skipping io-apic setup\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = dmar_table_init();
|
ret = dmar_table_init();
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_info("dmar_table_init() failed with %d:\n", ret);
|
pr_debug("dmar_table_init() failed with %d:\n", ret);
|
||||||
|
goto ir_failed;
|
||||||
|
}
|
||||||
|
|
||||||
if (x2apic_preenabled)
|
if (!intr_remapping_supported()) {
|
||||||
panic("x2apic enabled by bios. But IR enabling failed");
|
pr_debug("intr-remapping not supported\n");
|
||||||
else
|
goto ir_failed;
|
||||||
pr_info("Not enabling x2apic,Intr-remapping\n");
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!x2apic_preenabled && skip_ioapic_setup) {
|
||||||
|
pr_info("Skipped enabling intr-remap because of skipping "
|
||||||
|
"io-apic setup\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1357,19 +1401,16 @@ void __init enable_IR_x2apic(void)
|
||||||
mask_IO_APIC_setup(ioapic_entries);
|
mask_IO_APIC_setup(ioapic_entries);
|
||||||
mask_8259A();
|
mask_8259A();
|
||||||
|
|
||||||
ret = enable_intr_remapping(EIM_32BIT_APIC_ID);
|
ret = enable_intr_remapping(x2apic_supported());
|
||||||
|
|
||||||
if (ret && x2apic_preenabled) {
|
|
||||||
local_irq_restore(flags);
|
|
||||||
panic("x2apic enabled by bios. But IR enabling failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto end_restore;
|
goto end_restore;
|
||||||
|
|
||||||
if (!x2apic) {
|
pr_info("Enabled Interrupt-remapping\n");
|
||||||
x2apic = 1;
|
|
||||||
|
if (x2apic_supported() && !x2apic_mode) {
|
||||||
|
x2apic_mode = 1;
|
||||||
enable_x2apic();
|
enable_x2apic();
|
||||||
|
pr_info("Enabled x2apic\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
end_restore:
|
end_restore:
|
||||||
|
@ -1378,37 +1419,34 @@ end_restore:
|
||||||
* IR enabling failed
|
* IR enabling failed
|
||||||
*/
|
*/
|
||||||
restore_IO_APIC_setup(ioapic_entries);
|
restore_IO_APIC_setup(ioapic_entries);
|
||||||
else
|
|
||||||
reinit_intr_remapped_IO_APIC(x2apic_preenabled, ioapic_entries);
|
|
||||||
|
|
||||||
unmask_8259A();
|
unmask_8259A();
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (!ret) {
|
|
||||||
if (!x2apic_preenabled)
|
|
||||||
pr_info("Enabled x2apic and interrupt-remapping\n");
|
|
||||||
else
|
|
||||||
pr_info("Enabled Interrupt-remapping\n");
|
|
||||||
} else
|
|
||||||
pr_err("Failed to enable Interrupt-remapping and x2apic\n");
|
|
||||||
if (ioapic_entries)
|
if (ioapic_entries)
|
||||||
free_ioapic_entries(ioapic_entries);
|
free_ioapic_entries(ioapic_entries);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ir_failed:
|
||||||
|
if (x2apic_preenabled)
|
||||||
|
panic("x2apic enabled by bios. But IR enabling failed");
|
||||||
|
else if (cpu_has_x2apic)
|
||||||
|
pr_info("Not enabling x2apic,Intr-remapping\n");
|
||||||
#else
|
#else
|
||||||
if (!cpu_has_x2apic)
|
if (!cpu_has_x2apic)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (x2apic_preenabled)
|
if (x2apic_preenabled)
|
||||||
panic("x2apic enabled prior OS handover,"
|
panic("x2apic enabled prior OS handover,"
|
||||||
" enable CONFIG_INTR_REMAP");
|
" enable CONFIG_X86_X2APIC, CONFIG_INTR_REMAP");
|
||||||
|
|
||||||
pr_info("Enable CONFIG_INTR_REMAP for enabling intr-remapping "
|
|
||||||
" and x2apic\n");
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_X86_X2APIC */
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
/*
|
/*
|
||||||
|
@ -1425,7 +1463,6 @@ static int __init detect_init_APIC(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
|
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
|
||||||
boot_cpu_physical_apicid = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -1539,32 +1576,49 @@ void __init early_init_lapic_mapping(void)
|
||||||
*/
|
*/
|
||||||
void __init init_apic_mappings(void)
|
void __init init_apic_mappings(void)
|
||||||
{
|
{
|
||||||
if (x2apic) {
|
unsigned int new_apicid;
|
||||||
|
|
||||||
|
if (x2apic_mode) {
|
||||||
boot_cpu_physical_apicid = read_apic_id();
|
boot_cpu_physical_apicid = read_apic_id();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* If no local APIC can be found return early */
|
||||||
* If no local APIC can be found then set up a fake all
|
|
||||||
* zeroes page to simulate the local APIC and another
|
|
||||||
* one for the IO-APIC.
|
|
||||||
*/
|
|
||||||
if (!smp_found_config && detect_init_APIC()) {
|
if (!smp_found_config && detect_init_APIC()) {
|
||||||
apic_phys = (unsigned long) alloc_bootmem_pages(PAGE_SIZE);
|
/* lets NOP'ify apic operations */
|
||||||
apic_phys = __pa(apic_phys);
|
pr_info("APIC: disable apic facility\n");
|
||||||
} else
|
apic_disable();
|
||||||
|
} else {
|
||||||
apic_phys = mp_lapic_addr;
|
apic_phys = mp_lapic_addr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* acpi lapic path already maps that address in
|
||||||
|
* acpi_register_lapic_address()
|
||||||
|
*/
|
||||||
|
if (!acpi_lapic)
|
||||||
set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
|
set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
|
||||||
|
|
||||||
apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n",
|
apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n",
|
||||||
APIC_BASE, apic_phys);
|
APIC_BASE, apic_phys);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fetch the APIC ID of the BSP in case we have a
|
* Fetch the APIC ID of the BSP in case we have a
|
||||||
* default configuration (or the MP table is broken).
|
* default configuration (or the MP table is broken).
|
||||||
*/
|
*/
|
||||||
if (boot_cpu_physical_apicid == -1U)
|
new_apicid = read_apic_id();
|
||||||
boot_cpu_physical_apicid = read_apic_id();
|
if (boot_cpu_physical_apicid != new_apicid) {
|
||||||
|
boot_cpu_physical_apicid = new_apicid;
|
||||||
|
/*
|
||||||
|
* yeah -- we lie about apic_version
|
||||||
|
* in case if apic was disabled via boot option
|
||||||
|
* but it's not a problem for SMP compiled kernel
|
||||||
|
* since smp_sanity_check is prepared for such a case
|
||||||
|
* and disable smp mode
|
||||||
|
*/
|
||||||
|
apic_version[new_apicid] =
|
||||||
|
GET_APIC_VERSION(apic_read(APIC_LVR));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1733,8 +1787,7 @@ void __init connect_bsp_APIC(void)
|
||||||
*/
|
*/
|
||||||
apic_printk(APIC_VERBOSE, "leaving PIC mode, "
|
apic_printk(APIC_VERBOSE, "leaving PIC mode, "
|
||||||
"enabling APIC mode.\n");
|
"enabling APIC mode.\n");
|
||||||
outb(0x70, 0x22);
|
imcr_pic_to_apic();
|
||||||
outb(0x01, 0x23);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (apic->enable_apic_mode)
|
if (apic->enable_apic_mode)
|
||||||
|
@ -1762,8 +1815,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
|
||||||
*/
|
*/
|
||||||
apic_printk(APIC_VERBOSE, "disabling APIC mode, "
|
apic_printk(APIC_VERBOSE, "disabling APIC mode, "
|
||||||
"entering PIC mode.\n");
|
"entering PIC mode.\n");
|
||||||
outb(0x70, 0x22);
|
imcr_apic_to_pic();
|
||||||
outb(0x00, 0x23);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1969,10 +2021,10 @@ static int lapic_suspend(struct sys_device *dev, pm_message_t state)
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
disable_local_APIC();
|
disable_local_APIC();
|
||||||
#ifdef CONFIG_INTR_REMAP
|
|
||||||
if (intr_remapping_enabled)
|
if (intr_remapping_enabled)
|
||||||
disable_intr_remapping();
|
disable_intr_remapping();
|
||||||
#endif
|
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1982,42 +2034,34 @@ static int lapic_resume(struct sys_device *dev)
|
||||||
unsigned int l, h;
|
unsigned int l, h;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int maxlvt;
|
int maxlvt;
|
||||||
|
int ret = 0;
|
||||||
#ifdef CONFIG_INTR_REMAP
|
|
||||||
int ret;
|
|
||||||
struct IO_APIC_route_entry **ioapic_entries = NULL;
|
struct IO_APIC_route_entry **ioapic_entries = NULL;
|
||||||
|
|
||||||
if (!apic_pm_state.active)
|
if (!apic_pm_state.active)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
if (x2apic) {
|
if (intr_remapping_enabled) {
|
||||||
ioapic_entries = alloc_ioapic_entries();
|
ioapic_entries = alloc_ioapic_entries();
|
||||||
if (!ioapic_entries) {
|
if (!ioapic_entries) {
|
||||||
WARN(1, "Alloc ioapic_entries in lapic resume failed.");
|
WARN(1, "Alloc ioapic_entries in lapic resume failed.");
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto restore;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = save_IO_APIC_setup(ioapic_entries);
|
ret = save_IO_APIC_setup(ioapic_entries);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
WARN(1, "Saving IO-APIC state failed: %d\n", ret);
|
WARN(1, "Saving IO-APIC state failed: %d\n", ret);
|
||||||
free_ioapic_entries(ioapic_entries);
|
free_ioapic_entries(ioapic_entries);
|
||||||
return ret;
|
goto restore;
|
||||||
}
|
}
|
||||||
|
|
||||||
mask_IO_APIC_setup(ioapic_entries);
|
mask_IO_APIC_setup(ioapic_entries);
|
||||||
mask_8259A();
|
mask_8259A();
|
||||||
enable_x2apic();
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
if (!apic_pm_state.active)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
local_irq_save(flags);
|
if (x2apic_mode)
|
||||||
if (x2apic)
|
|
||||||
enable_x2apic();
|
enable_x2apic();
|
||||||
#endif
|
|
||||||
|
|
||||||
else {
|
else {
|
||||||
/*
|
/*
|
||||||
* Make sure the APICBASE points to the right address
|
* Make sure the APICBASE points to the right address
|
||||||
|
@ -2055,21 +2099,16 @@ static int lapic_resume(struct sys_device *dev)
|
||||||
apic_write(APIC_ESR, 0);
|
apic_write(APIC_ESR, 0);
|
||||||
apic_read(APIC_ESR);
|
apic_read(APIC_ESR);
|
||||||
|
|
||||||
#ifdef CONFIG_INTR_REMAP
|
if (intr_remapping_enabled) {
|
||||||
if (intr_remapping_enabled)
|
reenable_intr_remapping(x2apic_mode);
|
||||||
reenable_intr_remapping(EIM_32BIT_APIC_ID);
|
|
||||||
|
|
||||||
if (x2apic) {
|
|
||||||
unmask_8259A();
|
unmask_8259A();
|
||||||
restore_IO_APIC_setup(ioapic_entries);
|
restore_IO_APIC_setup(ioapic_entries);
|
||||||
free_ioapic_entries(ioapic_entries);
|
free_ioapic_entries(ioapic_entries);
|
||||||
}
|
}
|
||||||
#endif
|
restore:
|
||||||
|
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
|
|
||||||
|
return ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2117,31 +2156,14 @@ static void apic_pm_activate(void) { }
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
/*
|
|
||||||
* apic_is_clustered_box() -- Check if we can expect good TSC
|
static int __cpuinit apic_cluster_num(void)
|
||||||
*
|
|
||||||
* Thus far, the major user of this is IBM's Summit2 series:
|
|
||||||
*
|
|
||||||
* Clustered boxes may have unsynced TSC problems if they are
|
|
||||||
* multi-chassis. Use available data to take a good guess.
|
|
||||||
* If in doubt, go HPET.
|
|
||||||
*/
|
|
||||||
__cpuinit int apic_is_clustered_box(void)
|
|
||||||
{
|
{
|
||||||
int i, clusters, zeros;
|
int i, clusters, zeros;
|
||||||
unsigned id;
|
unsigned id;
|
||||||
u16 *bios_cpu_apicid;
|
u16 *bios_cpu_apicid;
|
||||||
DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
|
DECLARE_BITMAP(clustermap, NUM_APIC_CLUSTERS);
|
||||||
|
|
||||||
/*
|
|
||||||
* there is not this kind of box with AMD CPU yet.
|
|
||||||
* Some AMD box with quadcore cpu and 8 sockets apicid
|
|
||||||
* will be [4, 0x23] or [8, 0x27] could be thought to
|
|
||||||
* vsmp box still need checking...
|
|
||||||
*/
|
|
||||||
if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && !is_vsmp_box())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
|
bios_cpu_apicid = early_per_cpu_ptr(x86_bios_cpu_apicid);
|
||||||
bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
|
bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
|
||||||
|
|
||||||
|
@ -2177,18 +2199,67 @@ __cpuinit int apic_is_clustered_box(void)
|
||||||
++zeros;
|
++zeros;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ScaleMP vSMPowered boxes have one cluster per board and TSCs are
|
return clusters;
|
||||||
* not guaranteed to be synced between boards
|
}
|
||||||
*/
|
|
||||||
if (is_vsmp_box() && clusters > 1)
|
static int __cpuinitdata multi_checked;
|
||||||
return 1;
|
static int __cpuinitdata multi;
|
||||||
|
|
||||||
|
static int __cpuinit set_multi(const struct dmi_system_id *d)
|
||||||
|
{
|
||||||
|
if (multi)
|
||||||
|
return 0;
|
||||||
|
pr_info("APIC: %s detected, Multi Chassis\n", d->ident);
|
||||||
|
multi = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const __cpuinitconst struct dmi_system_id multi_dmi_table[] = {
|
||||||
|
{
|
||||||
|
.callback = set_multi,
|
||||||
|
.ident = "IBM System Summit2",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
|
||||||
|
DMI_MATCH(DMI_PRODUCT_NAME, "Summit2"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __cpuinit dmi_check_multi(void)
|
||||||
|
{
|
||||||
|
if (multi_checked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dmi_check_system(multi_dmi_table);
|
||||||
|
multi_checked = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If clusters > 2, then should be multi-chassis.
|
* apic_is_clustered_box() -- Check if we can expect good TSC
|
||||||
* May have to revisit this when multi-core + hyperthreaded CPUs come
|
*
|
||||||
* out, but AFAIK this will work even for them.
|
* Thus far, the major user of this is IBM's Summit2 series:
|
||||||
|
* Clustered boxes may have unsynced TSC problems if they are
|
||||||
|
* multi-chassis.
|
||||||
|
* Use DMI to check them
|
||||||
*/
|
*/
|
||||||
return (clusters > 2);
|
__cpuinit 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;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -161,7 +161,7 @@ static int flat_apic_id_registered(void)
|
||||||
|
|
||||||
static int flat_phys_pkg_id(int initial_apic_id, int index_msb)
|
static int flat_phys_pkg_id(int initial_apic_id, int index_msb)
|
||||||
{
|
{
|
||||||
return hard_smp_processor_id() >> index_msb;
|
return initial_apic_id >> index_msb;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct apic apic_flat = {
|
struct apic apic_flat = {
|
||||||
|
@ -235,7 +235,7 @@ static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||||
* regardless of how many processors are present (x86_64 ES7000
|
* regardless of how many processors are present (x86_64 ES7000
|
||||||
* is an example).
|
* is an example).
|
||||||
*/
|
*/
|
||||||
if (acpi_gbl_FADT.header.revision > FADT2_REVISION_ID &&
|
if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
|
||||||
(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
|
(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
|
||||||
printk(KERN_DEBUG "system APIC only can use physical flat");
|
printk(KERN_DEBUG "system APIC only can use physical flat");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -145,7 +145,7 @@ es7000_rename_gsi(int ioapic, int gsi)
|
||||||
return gsi;
|
return gsi;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
|
static int __cpuinit wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
|
||||||
{
|
{
|
||||||
unsigned long vect = 0, psaival = 0;
|
unsigned long vect = 0, psaival = 0;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -50,7 +50,7 @@ static struct apic *apic_probe[] __initdata = {
|
||||||
void __init default_setup_apic_routing(void)
|
void __init default_setup_apic_routing(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_X86_X2APIC
|
#ifdef CONFIG_X86_X2APIC
|
||||||
if (x2apic && (apic != &apic_x2apic_phys &&
|
if (x2apic_mode && (apic != &apic_x2apic_phys &&
|
||||||
#ifdef CONFIG_X86_UV
|
#ifdef CONFIG_X86_UV
|
||||||
apic != &apic_x2apic_uv_x &&
|
apic != &apic_x2apic_uv_x &&
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -173,13 +173,6 @@ static inline int is_WPEG(struct rio_detail *rio){
|
||||||
rio->type == LookOutAWPEG || rio->type == LookOutBWPEG);
|
rio->type == LookOutAWPEG || rio->type == LookOutBWPEG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* In clustered mode, the high nibble of APIC ID is a cluster number.
|
|
||||||
* The low nibble is a 4-bit bitmap. */
|
|
||||||
#define XAPIC_DEST_CPUS_SHIFT 4
|
|
||||||
#define XAPIC_DEST_CPUS_MASK ((1u << XAPIC_DEST_CPUS_SHIFT) - 1)
|
|
||||||
#define XAPIC_DEST_CLUSTER_MASK (XAPIC_DEST_CPUS_MASK << XAPIC_DEST_CPUS_SHIFT)
|
|
||||||
|
|
||||||
#define SUMMIT_APIC_DFR_VALUE (APIC_DFR_CLUSTER)
|
#define SUMMIT_APIC_DFR_VALUE (APIC_DFR_CLUSTER)
|
||||||
|
|
||||||
static const struct cpumask *summit_target_cpus(void)
|
static const struct cpumask *summit_target_cpus(void)
|
||||||
|
|
|
@ -105,7 +105,7 @@ static void uv_vector_allocation_domain(int cpu, struct cpumask *retmask)
|
||||||
cpumask_set_cpu(cpu, retmask);
|
cpumask_set_cpu(cpu, retmask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uv_wakeup_secondary(int phys_apicid, unsigned long start_rip)
|
static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_rip)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
|
@ -583,15 +583,18 @@ void __init uv_system_init(void)
|
||||||
|
|
||||||
bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
|
bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
|
||||||
uv_blade_info = kmalloc(bytes, GFP_KERNEL);
|
uv_blade_info = kmalloc(bytes, GFP_KERNEL);
|
||||||
|
BUG_ON(!uv_blade_info);
|
||||||
|
|
||||||
get_lowmem_redirect(&lowmem_redir_base, &lowmem_redir_size);
|
get_lowmem_redirect(&lowmem_redir_base, &lowmem_redir_size);
|
||||||
|
|
||||||
bytes = sizeof(uv_node_to_blade[0]) * num_possible_nodes();
|
bytes = sizeof(uv_node_to_blade[0]) * num_possible_nodes();
|
||||||
uv_node_to_blade = kmalloc(bytes, GFP_KERNEL);
|
uv_node_to_blade = kmalloc(bytes, GFP_KERNEL);
|
||||||
|
BUG_ON(!uv_node_to_blade);
|
||||||
memset(uv_node_to_blade, 255, bytes);
|
memset(uv_node_to_blade, 255, bytes);
|
||||||
|
|
||||||
bytes = sizeof(uv_cpu_to_blade[0]) * num_possible_cpus();
|
bytes = sizeof(uv_cpu_to_blade[0]) * num_possible_cpus();
|
||||||
uv_cpu_to_blade = kmalloc(bytes, GFP_KERNEL);
|
uv_cpu_to_blade = kmalloc(bytes, GFP_KERNEL);
|
||||||
|
BUG_ON(!uv_cpu_to_blade);
|
||||||
memset(uv_cpu_to_blade, 255, bytes);
|
memset(uv_cpu_to_blade, 255, bytes);
|
||||||
|
|
||||||
blade = 0;
|
blade = 0;
|
||||||
|
|
|
@ -272,7 +272,7 @@ static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c)
|
||||||
#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
|
#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
|
||||||
int cpu = smp_processor_id();
|
int cpu = smp_processor_id();
|
||||||
int node;
|
int node;
|
||||||
unsigned apicid = hard_smp_processor_id();
|
unsigned apicid = cpu_has_apic ? hard_smp_processor_id() : c->apicid;
|
||||||
|
|
||||||
node = c->phys_proc_id;
|
node = c->phys_proc_id;
|
||||||
if (apicid_to_node[apicid] != NUMA_NO_NODE)
|
if (apicid_to_node[apicid] != NUMA_NO_NODE)
|
||||||
|
|
|
@ -299,7 +299,8 @@ static const char *__cpuinit table_lookup_model(struct cpuinfo_x86 *c)
|
||||||
return NULL; /* Not found */
|
return NULL; /* Not found */
|
||||||
}
|
}
|
||||||
|
|
||||||
__u32 cleared_cpu_caps[NCAPINTS] __cpuinitdata;
|
__u32 cpu_caps_cleared[NCAPINTS] __cpuinitdata;
|
||||||
|
__u32 cpu_caps_set[NCAPINTS] __cpuinitdata;
|
||||||
|
|
||||||
void load_percpu_segment(int cpu)
|
void load_percpu_segment(int cpu)
|
||||||
{
|
{
|
||||||
|
@ -768,6 +769,12 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
|
||||||
if (this_cpu->c_identify)
|
if (this_cpu->c_identify)
|
||||||
this_cpu->c_identify(c);
|
this_cpu->c_identify(c);
|
||||||
|
|
||||||
|
/* Clear/Set all flags overriden by options, after probe */
|
||||||
|
for (i = 0; i < NCAPINTS; i++) {
|
||||||
|
c->x86_capability[i] &= ~cpu_caps_cleared[i];
|
||||||
|
c->x86_capability[i] |= cpu_caps_set[i];
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
|
c->apicid = apic->phys_pkg_id(c->initial_apicid, 0);
|
||||||
#endif
|
#endif
|
||||||
|
@ -813,6 +820,16 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
init_hypervisor(c);
|
init_hypervisor(c);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear/Set all flags overriden by options, need do it
|
||||||
|
* before following smp all cpus cap AND.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < NCAPINTS; i++) {
|
||||||
|
c->x86_capability[i] &= ~cpu_caps_cleared[i];
|
||||||
|
c->x86_capability[i] |= cpu_caps_set[i];
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On SMP, boot_cpu_data holds the common feature set between
|
* On SMP, boot_cpu_data holds the common feature set between
|
||||||
* all CPUs; so make sure that we indicate which features are
|
* all CPUs; so make sure that we indicate which features are
|
||||||
|
@ -825,10 +842,6 @@ static void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
|
||||||
boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
|
boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear all flags overriden by options */
|
|
||||||
for (i = 0; i < NCAPINTS; i++)
|
|
||||||
c->x86_capability[i] &= ~cleared_cpu_caps[i];
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_MCE
|
#ifdef CONFIG_X86_MCE
|
||||||
/* Init Machine Check Exception if available. */
|
/* Init Machine Check Exception if available. */
|
||||||
mcheck_init(c);
|
mcheck_init(c);
|
||||||
|
|
|
@ -588,8 +588,20 @@ static void print_apic(void *arg)
|
||||||
seq_printf(seq, " TMICT\t\t: %08x\n", apic_read(APIC_TMICT));
|
seq_printf(seq, " TMICT\t\t: %08x\n", apic_read(APIC_TMICT));
|
||||||
seq_printf(seq, " TMCCT\t\t: %08x\n", apic_read(APIC_TMCCT));
|
seq_printf(seq, " TMCCT\t\t: %08x\n", apic_read(APIC_TMCCT));
|
||||||
seq_printf(seq, " TDCR\t\t: %08x\n", apic_read(APIC_TDCR));
|
seq_printf(seq, " TDCR\t\t: %08x\n", apic_read(APIC_TDCR));
|
||||||
#endif /* CONFIG_X86_LOCAL_APIC */
|
if (boot_cpu_has(X86_FEATURE_EXTAPIC)) {
|
||||||
|
unsigned int i, v, maxeilvt;
|
||||||
|
|
||||||
|
v = apic_read(APIC_EFEAT);
|
||||||
|
maxeilvt = (v >> 16) & 0xff;
|
||||||
|
seq_printf(seq, " EFEAT\t\t: %08x\n", v);
|
||||||
|
seq_printf(seq, " ECTRL\t\t: %08x\n", apic_read(APIC_ECTRL));
|
||||||
|
|
||||||
|
for (i = 0; i < maxeilvt; i++) {
|
||||||
|
v = apic_read(APIC_EILVTn(i));
|
||||||
|
seq_printf(seq, " EILVT%d\t\t: %08x\n", i, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_X86_LOCAL_APIC */
|
||||||
seq_printf(seq, "\n MSR\t:\n");
|
seq_printf(seq, "\n MSR\t:\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -229,12 +229,12 @@ static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void __cpuinit srat_detect_node(void)
|
static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
|
#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
|
||||||
unsigned node;
|
unsigned node;
|
||||||
int cpu = smp_processor_id();
|
int cpu = smp_processor_id();
|
||||||
int apicid = hard_smp_processor_id();
|
int apicid = cpu_has_apic ? hard_smp_processor_id() : c->apicid;
|
||||||
|
|
||||||
/* Don't do the funky fallback heuristics the AMD version employs
|
/* Don't do the funky fallback heuristics the AMD version employs
|
||||||
for now. */
|
for now. */
|
||||||
|
@ -400,7 +400,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Work around errata */
|
/* Work around errata */
|
||||||
srat_detect_node();
|
srat_detect_node(c);
|
||||||
|
|
||||||
if (cpu_has(c, X86_FEATURE_VMX))
|
if (cpu_has(c, X86_FEATURE_VMX))
|
||||||
detect_vmx_virtcap(c);
|
detect_vmx_virtcap(c);
|
||||||
|
|
|
@ -24,9 +24,9 @@ void (*generic_interrupt_extension)(void) = NULL;
|
||||||
*/
|
*/
|
||||||
void ack_bad_irq(unsigned int irq)
|
void ack_bad_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq);
|
if (printk_ratelimit())
|
||||||
|
pr_err("unexpected IRQ trap at vector %02x\n", irq);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_LOCAL_APIC
|
|
||||||
/*
|
/*
|
||||||
* Currently unexpected vectors happen only on SMP and APIC.
|
* Currently unexpected vectors happen only on SMP and APIC.
|
||||||
* We _must_ ack these because every local APIC has only N
|
* We _must_ ack these because every local APIC has only N
|
||||||
|
@ -36,9 +36,7 @@ void ack_bad_irq(unsigned int irq)
|
||||||
* completely.
|
* completely.
|
||||||
* But only ack when the APIC is enabled -AK
|
* But only ack when the APIC is enabled -AK
|
||||||
*/
|
*/
|
||||||
if (cpu_has_apic)
|
|
||||||
ack_APIC_irq();
|
ack_APIC_irq();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define irq_stats(x) (&per_cpu(irq_stat, x))
|
#define irq_stats(x) (&per_cpu(irq_stat, x))
|
||||||
|
@ -213,13 +211,10 @@ unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
|
||||||
irq = __get_cpu_var(vector_irq)[vector];
|
irq = __get_cpu_var(vector_irq)[vector];
|
||||||
|
|
||||||
if (!handle_irq(irq, regs)) {
|
if (!handle_irq(irq, regs)) {
|
||||||
#ifdef CONFIG_X86_64
|
|
||||||
if (!disable_apic)
|
|
||||||
ack_APIC_irq();
|
ack_APIC_irq();
|
||||||
#endif
|
|
||||||
|
|
||||||
if (printk_ratelimit())
|
if (printk_ratelimit())
|
||||||
printk(KERN_EMERG "%s: %d.%d No irq handler for vector (irq %d)\n",
|
pr_emerg("%s: %d.%d No irq handler for vector (irq %d)\n",
|
||||||
__func__, smp_processor_id(), vector, irq);
|
__func__, smp_processor_id(), vector, irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,25 @@
|
||||||
|
#include <linux/linkage.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/signal.h>
|
#include <linux/signal.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/timex.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
|
#include <linux/kprobes.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/kernel_stat.h>
|
#include <linux/kernel_stat.h>
|
||||||
#include <linux/sysdev.h>
|
#include <linux/sysdev.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/acpi.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/timer.h>
|
#include <asm/timer.h>
|
||||||
|
#include <asm/hw_irq.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
#include <asm/desc.h>
|
#include <asm/desc.h>
|
||||||
#include <asm/apic.h>
|
#include <asm/apic.h>
|
||||||
|
@ -22,7 +27,23 @@
|
||||||
#include <asm/i8259.h>
|
#include <asm/i8259.h>
|
||||||
#include <asm/traps.h>
|
#include <asm/traps.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
|
||||||
|
* (these are usually mapped to vectors 0x30-0x3f)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The IO-APIC gives us many more interrupt sources. Most of these
|
||||||
|
* are unused but an SMP system is supposed to have enough memory ...
|
||||||
|
* sometimes (mostly wrt. hw bugs) we get corrupted vectors all
|
||||||
|
* across the spectrum, so we really want to be prepared to get all
|
||||||
|
* of these. Plus, more powerful systems might have more than 64
|
||||||
|
* IO-APIC registers.
|
||||||
|
*
|
||||||
|
* (these are usually mapped into the 0x30-0xff vector range)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
/*
|
/*
|
||||||
* Note that on a 486, we don't want to do a SIGFPE on an irq13
|
* Note that on a 486, we don't want to do a SIGFPE on an irq13
|
||||||
* as the irq is unreliable, and exception 16 works correctly
|
* as the irq is unreliable, and exception 16 works correctly
|
||||||
|
@ -52,30 +73,7 @@ static struct irqaction fpu_irq = {
|
||||||
.handler = math_error_irq,
|
.handler = math_error_irq,
|
||||||
.name = "fpu",
|
.name = "fpu",
|
||||||
};
|
};
|
||||||
|
|
||||||
void __init init_ISA_irqs(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_LOCAL_APIC
|
|
||||||
init_bsp_APIC();
|
|
||||||
#endif
|
#endif
|
||||||
init_8259A(0);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 16 old-style INTA-cycle interrupts:
|
|
||||||
*/
|
|
||||||
for (i = 0; i < NR_IRQS_LEGACY; i++) {
|
|
||||||
struct irq_desc *desc = irq_to_desc(i);
|
|
||||||
|
|
||||||
desc->status = IRQ_DISABLED;
|
|
||||||
desc->action = NULL;
|
|
||||||
desc->depth = 1;
|
|
||||||
|
|
||||||
set_irq_chip_and_handler_name(i, &i8259A_chip,
|
|
||||||
handle_level_irq, "XT");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IRQ2 is cascade interrupt to second interrupt controller
|
* IRQ2 is cascade interrupt to second interrupt controller
|
||||||
|
@ -118,29 +116,37 @@ int vector_used_by_percpu_irq(unsigned int vector)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Overridden in paravirt.c */
|
static void __init init_ISA_irqs(void)
|
||||||
void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
|
|
||||||
|
|
||||||
void __init native_init_IRQ(void)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Execute any quirks before the call gates are initialised: */
|
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
|
||||||
x86_quirk_pre_intr_init();
|
init_bsp_APIC();
|
||||||
|
#endif
|
||||||
|
init_8259A(0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cover the whole vector space, no vector can escape
|
* 16 old-style INTA-cycle interrupts:
|
||||||
* us. (some of these will be overridden and become
|
|
||||||
* 'special' SMP interrupts)
|
|
||||||
*/
|
*/
|
||||||
for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) {
|
for (i = 0; i < NR_IRQS_LEGACY; i++) {
|
||||||
/* SYSCALL_VECTOR was reserved in trap_init. */
|
struct irq_desc *desc = irq_to_desc(i);
|
||||||
if (i != SYSCALL_VECTOR)
|
|
||||||
set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);
|
desc->status = IRQ_DISABLED;
|
||||||
|
desc->action = NULL;
|
||||||
|
desc->depth = 1;
|
||||||
|
|
||||||
|
set_irq_chip_and_handler_name(i, &i8259A_chip,
|
||||||
|
handle_level_irq, "XT");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Overridden in paravirt.c */
|
||||||
|
void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
|
||||||
|
|
||||||
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_SMP)
|
static void __init smp_intr_init(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
|
||||||
/*
|
/*
|
||||||
* The reschedule interrupt is a CPU-to-CPU reschedule-helper
|
* The reschedule interrupt is a CPU-to-CPU reschedule-helper
|
||||||
* IPI, driven by wakeup.
|
* IPI, driven by wakeup.
|
||||||
|
@ -160,7 +166,7 @@ void __init native_init_IRQ(void)
|
||||||
/* IPI for generic function call */
|
/* IPI for generic function call */
|
||||||
alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
|
alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
|
||||||
|
|
||||||
/* IPI for single call function */
|
/* IPI for generic single function call */
|
||||||
alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
|
alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
|
||||||
call_function_single_interrupt);
|
call_function_single_interrupt);
|
||||||
|
|
||||||
|
@ -168,8 +174,19 @@ void __init native_init_IRQ(void)
|
||||||
set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
|
set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
|
||||||
set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
|
set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* CONFIG_SMP */
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_LOCAL_APIC
|
static void __init apic_intr_init(void)
|
||||||
|
{
|
||||||
|
smp_intr_init();
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
|
||||||
|
alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
|
||||||
/* self generated IPI for local APIC timer */
|
/* self generated IPI for local APIC timer */
|
||||||
alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
|
alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
|
||||||
|
|
||||||
|
@ -179,16 +196,67 @@ void __init native_init_IRQ(void)
|
||||||
/* IPI vectors for APIC spurious and error interrupts */
|
/* IPI vectors for APIC spurious and error interrupts */
|
||||||
alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
|
alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
|
||||||
alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
|
alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
|
||||||
|
|
||||||
|
/* Performance monitoring interrupts: */
|
||||||
|
# ifdef CONFIG_PERF_COUNTERS
|
||||||
|
alloc_intr_gate(LOCAL_PERF_VECTOR, perf_counter_interrupt);
|
||||||
|
alloc_intr_gate(LOCAL_PENDING_VECTOR, perf_pending_interrupt);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_MCE_P4THERMAL)
|
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_MCE_P4THERMAL)
|
||||||
/* thermal monitor LVT interrupt */
|
/* thermal monitor LVT interrupt */
|
||||||
alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
|
alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* x86_quirk_pre_intr_init - initialisation prior to setting up interrupt vectors
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Perform any necessary interrupt initialisation prior to setting up
|
||||||
|
* the "ordinary" interrupt call gates. For legacy reasons, the ISA
|
||||||
|
* interrupts should be initialised here if the machine emulates a PC
|
||||||
|
* in any way.
|
||||||
|
**/
|
||||||
|
static void __init x86_quirk_pre_intr_init(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
|
if (x86_quirks->arch_pre_intr_init) {
|
||||||
|
if (x86_quirks->arch_pre_intr_init())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
init_ISA_irqs();
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init native_init_IRQ(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Execute any quirks before the call gates are initialised: */
|
||||||
|
x86_quirk_pre_intr_init();
|
||||||
|
|
||||||
|
apic_intr_init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cover the whole vector space, no vector can escape
|
||||||
|
* us. (some of these will be overridden and become
|
||||||
|
* 'special' SMP interrupts)
|
||||||
|
*/
|
||||||
|
for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) {
|
||||||
|
/* IA32_SYSCALL_VECTOR could be used in trap_init already. */
|
||||||
|
if (!test_bit(i, used_vectors))
|
||||||
|
set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);
|
||||||
|
}
|
||||||
|
|
||||||
if (!acpi_ioapic)
|
if (!acpi_ioapic)
|
||||||
setup_irq(2, &irq2);
|
setup_irq(2, &irq2);
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
/*
|
/*
|
||||||
* Call quirks after call gates are initialised (usually add in
|
* Call quirks after call gates are initialised (usually add in
|
||||||
* the architecture specific gates):
|
* the architecture specific gates):
|
||||||
|
@ -203,4 +271,5 @@ void __init native_init_IRQ(void)
|
||||||
setup_irq(FPU_IRQ, &fpu_irq);
|
setup_irq(FPU_IRQ, &fpu_irq);
|
||||||
|
|
||||||
irq_ctx_init(smp_processor_id());
|
irq_ctx_init(smp_processor_id());
|
||||||
|
#endif
|
||||||
}
|
}
|
|
@ -1,177 +0,0 @@
|
||||||
#include <linux/linkage.h>
|
|
||||||
#include <linux/errno.h>
|
|
||||||
#include <linux/signal.h>
|
|
||||||
#include <linux/sched.h>
|
|
||||||
#include <linux/ioport.h>
|
|
||||||
#include <linux/interrupt.h>
|
|
||||||
#include <linux/timex.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/random.h>
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/kernel_stat.h>
|
|
||||||
#include <linux/sysdev.h>
|
|
||||||
#include <linux/bitops.h>
|
|
||||||
#include <linux/acpi.h>
|
|
||||||
#include <linux/io.h>
|
|
||||||
#include <linux/delay.h>
|
|
||||||
|
|
||||||
#include <asm/atomic.h>
|
|
||||||
#include <asm/system.h>
|
|
||||||
#include <asm/hw_irq.h>
|
|
||||||
#include <asm/pgtable.h>
|
|
||||||
#include <asm/desc.h>
|
|
||||||
#include <asm/apic.h>
|
|
||||||
#include <asm/i8259.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
|
|
||||||
* (these are usually mapped to vectors 0x30-0x3f)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The IO-APIC gives us many more interrupt sources. Most of these
|
|
||||||
* are unused but an SMP system is supposed to have enough memory ...
|
|
||||||
* sometimes (mostly wrt. hw bugs) we get corrupted vectors all
|
|
||||||
* across the spectrum, so we really want to be prepared to get all
|
|
||||||
* of these. Plus, more powerful systems might have more than 64
|
|
||||||
* IO-APIC registers.
|
|
||||||
*
|
|
||||||
* (these are usually mapped into the 0x30-0xff vector range)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* IRQ2 is cascade interrupt to second interrupt controller
|
|
||||||
*/
|
|
||||||
|
|
||||||
static struct irqaction irq2 = {
|
|
||||||
.handler = no_action,
|
|
||||||
.name = "cascade",
|
|
||||||
};
|
|
||||||
DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
|
|
||||||
[0 ... IRQ0_VECTOR - 1] = -1,
|
|
||||||
[IRQ0_VECTOR] = 0,
|
|
||||||
[IRQ1_VECTOR] = 1,
|
|
||||||
[IRQ2_VECTOR] = 2,
|
|
||||||
[IRQ3_VECTOR] = 3,
|
|
||||||
[IRQ4_VECTOR] = 4,
|
|
||||||
[IRQ5_VECTOR] = 5,
|
|
||||||
[IRQ6_VECTOR] = 6,
|
|
||||||
[IRQ7_VECTOR] = 7,
|
|
||||||
[IRQ8_VECTOR] = 8,
|
|
||||||
[IRQ9_VECTOR] = 9,
|
|
||||||
[IRQ10_VECTOR] = 10,
|
|
||||||
[IRQ11_VECTOR] = 11,
|
|
||||||
[IRQ12_VECTOR] = 12,
|
|
||||||
[IRQ13_VECTOR] = 13,
|
|
||||||
[IRQ14_VECTOR] = 14,
|
|
||||||
[IRQ15_VECTOR] = 15,
|
|
||||||
[IRQ15_VECTOR + 1 ... NR_VECTORS - 1] = -1
|
|
||||||
};
|
|
||||||
|
|
||||||
int vector_used_by_percpu_irq(unsigned int vector)
|
|
||||||
{
|
|
||||||
int cpu;
|
|
||||||
|
|
||||||
for_each_online_cpu(cpu) {
|
|
||||||
if (per_cpu(vector_irq, cpu)[vector] != -1)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __init init_ISA_irqs(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
init_bsp_APIC();
|
|
||||||
init_8259A(0);
|
|
||||||
|
|
||||||
for (i = 0; i < NR_IRQS_LEGACY; i++) {
|
|
||||||
struct irq_desc *desc = irq_to_desc(i);
|
|
||||||
|
|
||||||
desc->status = IRQ_DISABLED;
|
|
||||||
desc->action = NULL;
|
|
||||||
desc->depth = 1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 16 old-style INTA-cycle interrupts:
|
|
||||||
*/
|
|
||||||
set_irq_chip_and_handler_name(i, &i8259A_chip,
|
|
||||||
handle_level_irq, "XT");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
|
|
||||||
|
|
||||||
static void __init smp_intr_init(void)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
/*
|
|
||||||
* The reschedule interrupt is a CPU-to-CPU reschedule-helper
|
|
||||||
* IPI, driven by wakeup.
|
|
||||||
*/
|
|
||||||
alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
|
|
||||||
|
|
||||||
/* IPIs for invalidation */
|
|
||||||
alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+0, invalidate_interrupt0);
|
|
||||||
alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+1, invalidate_interrupt1);
|
|
||||||
alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+2, invalidate_interrupt2);
|
|
||||||
alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+3, invalidate_interrupt3);
|
|
||||||
alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+4, invalidate_interrupt4);
|
|
||||||
alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+5, invalidate_interrupt5);
|
|
||||||
alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+6, invalidate_interrupt6);
|
|
||||||
alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+7, invalidate_interrupt7);
|
|
||||||
|
|
||||||
/* IPI for generic function call */
|
|
||||||
alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
|
|
||||||
|
|
||||||
/* IPI for generic single function call */
|
|
||||||
alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
|
|
||||||
call_function_single_interrupt);
|
|
||||||
|
|
||||||
/* Low priority IPI to cleanup after moving an irq */
|
|
||||||
set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
|
|
||||||
set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __init apic_intr_init(void)
|
|
||||||
{
|
|
||||||
smp_intr_init();
|
|
||||||
|
|
||||||
alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
|
|
||||||
alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
|
|
||||||
|
|
||||||
/* self generated IPI for local APIC timer */
|
|
||||||
alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
|
|
||||||
|
|
||||||
/* generic IPI for platform specific use */
|
|
||||||
alloc_intr_gate(GENERIC_INTERRUPT_VECTOR, generic_interrupt);
|
|
||||||
|
|
||||||
/* IPI vectors for APIC spurious and error interrupts */
|
|
||||||
alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
|
|
||||||
alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __init native_init_IRQ(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
init_ISA_irqs();
|
|
||||||
/*
|
|
||||||
* Cover the whole vector space, no vector can escape
|
|
||||||
* us. (some of these will be overridden and become
|
|
||||||
* 'special' SMP interrupts)
|
|
||||||
*/
|
|
||||||
for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
|
|
||||||
int vector = FIRST_EXTERNAL_VECTOR + i;
|
|
||||||
if (vector != IA32_SYSCALL_VECTOR)
|
|
||||||
set_intr_gate(vector, interrupt[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
apic_intr_init();
|
|
||||||
|
|
||||||
if (!acpi_ioapic)
|
|
||||||
setup_irq(2, &irq2);
|
|
||||||
}
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
|
||||||
#include <asm/mtrr.h>
|
#include <asm/mtrr.h>
|
||||||
#include <asm/mpspec.h>
|
#include <asm/mpspec.h>
|
||||||
|
@ -870,24 +871,17 @@ static
|
||||||
inline void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {}
|
inline void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {}
|
||||||
#endif /* CONFIG_X86_IO_APIC */
|
#endif /* CONFIG_X86_IO_APIC */
|
||||||
|
|
||||||
static int check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length,
|
static int
|
||||||
int count)
|
check_slot(unsigned long mpc_new_phys, unsigned long mpc_new_length, int count)
|
||||||
{
|
{
|
||||||
if (!mpc_new_phys) {
|
int ret = 0;
|
||||||
pr_info("No spare slots, try to append...take your risk, "
|
|
||||||
"new mpc_length %x\n", count);
|
if (!mpc_new_phys || count <= mpc_new_length) {
|
||||||
} else {
|
WARN(1, "update_mptable: No spare slots (length: %x)\n", count);
|
||||||
if (count <= mpc_new_length)
|
|
||||||
pr_info("No spare slots, try to append..., "
|
|
||||||
"new mpc_length %x\n", count);
|
|
||||||
else {
|
|
||||||
pr_err("mpc_new_length %lx is too small\n",
|
|
||||||
mpc_new_length);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init replace_intsrc_all(struct mpc_table *mpc,
|
static int __init replace_intsrc_all(struct mpc_table *mpc,
|
||||||
|
@ -946,7 +940,7 @@ static int __init replace_intsrc_all(struct mpc_table *mpc,
|
||||||
} else {
|
} else {
|
||||||
struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
|
struct mpc_intsrc *m = (struct mpc_intsrc *)mpt;
|
||||||
count += sizeof(struct mpc_intsrc);
|
count += sizeof(struct mpc_intsrc);
|
||||||
if (!check_slot(mpc_new_phys, mpc_new_length, count))
|
if (check_slot(mpc_new_phys, mpc_new_length, count) < 0)
|
||||||
goto out;
|
goto out;
|
||||||
assign_to_mpc_intsrc(&mp_irqs[i], m);
|
assign_to_mpc_intsrc(&mp_irqs[i], m);
|
||||||
mpc->length = count;
|
mpc->length = count;
|
||||||
|
@ -963,11 +957,14 @@ out:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __initdata enable_update_mptable;
|
int enable_update_mptable;
|
||||||
|
|
||||||
static int __init update_mptable_setup(char *str)
|
static int __init update_mptable_setup(char *str)
|
||||||
{
|
{
|
||||||
enable_update_mptable = 1;
|
enable_update_mptable = 1;
|
||||||
|
#ifdef CONFIG_PCI
|
||||||
|
pci_routeirq = 1;
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
early_param("update_mptable", update_mptable_setup);
|
early_param("update_mptable", update_mptable_setup);
|
||||||
|
@ -980,6 +977,9 @@ static int __initdata alloc_mptable;
|
||||||
static int __init parse_alloc_mptable_opt(char *p)
|
static int __init parse_alloc_mptable_opt(char *p)
|
||||||
{
|
{
|
||||||
enable_update_mptable = 1;
|
enable_update_mptable = 1;
|
||||||
|
#ifdef CONFIG_PCI
|
||||||
|
pci_routeirq = 1;
|
||||||
|
#endif
|
||||||
alloc_mptable = 1;
|
alloc_mptable = 1;
|
||||||
if (!p)
|
if (!p)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -996,24 +996,6 @@ void __init setup_arch(char **cmdline_p)
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
|
|
||||||
/**
|
|
||||||
* x86_quirk_pre_intr_init - initialisation prior to setting up interrupt vectors
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* Perform any necessary interrupt initialisation prior to setting up
|
|
||||||
* the "ordinary" interrupt call gates. For legacy reasons, the ISA
|
|
||||||
* interrupts should be initialised here if the machine emulates a PC
|
|
||||||
* in any way.
|
|
||||||
**/
|
|
||||||
void __init x86_quirk_pre_intr_init(void)
|
|
||||||
{
|
|
||||||
if (x86_quirks->arch_pre_intr_init) {
|
|
||||||
if (x86_quirks->arch_pre_intr_init())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
init_ISA_irqs();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* x86_quirk_intr_init - post gate setup interrupt initialisation
|
* x86_quirk_intr_init - post gate setup interrupt initialisation
|
||||||
*
|
*
|
||||||
|
|
|
@ -504,7 +504,7 @@ void __inquire_remote_apic(int apicid)
|
||||||
* INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
|
* INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
|
||||||
* won't ... remember to clear down the APIC, etc later.
|
* won't ... remember to clear down the APIC, etc later.
|
||||||
*/
|
*/
|
||||||
int __devinit
|
int __cpuinit
|
||||||
wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip)
|
wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip)
|
||||||
{
|
{
|
||||||
unsigned long send_status, accept_status = 0;
|
unsigned long send_status, accept_status = 0;
|
||||||
|
@ -538,7 +538,7 @@ wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip)
|
||||||
return (send_status | accept_status);
|
return (send_status | accept_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
int __devinit
|
static int __cpuinit
|
||||||
wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
|
wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
|
||||||
{
|
{
|
||||||
unsigned long send_status, accept_status = 0;
|
unsigned long send_status, accept_status = 0;
|
||||||
|
@ -822,10 +822,12 @@ do_rest:
|
||||||
/* mark "stuck" area as not stuck */
|
/* mark "stuck" area as not stuck */
|
||||||
*((volatile unsigned long *)trampoline_base) = 0;
|
*((volatile unsigned long *)trampoline_base) = 0;
|
||||||
|
|
||||||
|
if (get_uv_system_type() != UV_NON_UNIQUE_APIC) {
|
||||||
/*
|
/*
|
||||||
* Cleanup possible dangling ends...
|
* Cleanup possible dangling ends...
|
||||||
*/
|
*/
|
||||||
smpboot_restore_warm_reset_vector();
|
smpboot_restore_warm_reset_vector();
|
||||||
|
}
|
||||||
|
|
||||||
return boot_error;
|
return boot_error;
|
||||||
}
|
}
|
||||||
|
@ -990,10 +992,12 @@ static int __init smp_sanity_check(unsigned max_cpus)
|
||||||
*/
|
*/
|
||||||
if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) &&
|
if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid]) &&
|
||||||
!cpu_has_apic) {
|
!cpu_has_apic) {
|
||||||
printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
|
if (!disable_apic) {
|
||||||
|
pr_err("BIOS bug, local APIC #%d not detected!...\n",
|
||||||
boot_cpu_physical_apicid);
|
boot_cpu_physical_apicid);
|
||||||
printk(KERN_ERR "... forcing use of dummy APIC emulation."
|
pr_err("... forcing use of dummy APIC emulation."
|
||||||
"(tell your hw vendor)\n");
|
"(tell your hw vendor)\n");
|
||||||
|
}
|
||||||
smpboot_clear_io_apic();
|
smpboot_clear_io_apic();
|
||||||
arch_disable_smp_support();
|
arch_disable_smp_support();
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -969,11 +969,8 @@ void __init trap_init(void)
|
||||||
for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
|
for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
|
||||||
set_bit(i, used_vectors);
|
set_bit(i, used_vectors);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
|
||||||
set_bit(IA32_SYSCALL_VECTOR, used_vectors);
|
set_bit(IA32_SYSCALL_VECTOR, used_vectors);
|
||||||
#else
|
|
||||||
set_bit(SYSCALL_VECTOR, used_vectors);
|
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* Should be a barrier for any external CPU state:
|
* Should be a barrier for any external CPU state:
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -637,7 +637,7 @@ static void __init lguest_init_IRQ(void)
|
||||||
|
|
||||||
void lguest_setup_irq(unsigned int irq)
|
void lguest_setup_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
irq_to_desc_alloc_cpu(irq, 0);
|
irq_to_desc_alloc_node(irq, 0);
|
||||||
set_irq_chip_and_handler_name(irq, &lguest_irq_controller,
|
set_irq_chip_and_handler_name(irq, &lguest_irq_controller,
|
||||||
handle_level_irq, "level");
|
handle_level_irq, "level");
|
||||||
}
|
}
|
||||||
|
|
|
@ -889,6 +889,9 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (io_apic_assign_pci_irqs)
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Find IRQ routing entry */
|
/* Find IRQ routing entry */
|
||||||
|
|
||||||
if (!pirq_table)
|
if (!pirq_table)
|
||||||
|
@ -1039,56 +1042,15 @@ static void __init pcibios_fixup_irqs(void)
|
||||||
pirq_penalty[dev->irq]++;
|
pirq_penalty[dev->irq]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (io_apic_assign_pci_irqs)
|
||||||
|
return;
|
||||||
|
|
||||||
dev = NULL;
|
dev = NULL;
|
||||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
||||||
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
|
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
|
||||||
if (!pin)
|
if (!pin)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
|
||||||
/*
|
|
||||||
* Recalculate IRQ numbers if we use the I/O APIC.
|
|
||||||
*/
|
|
||||||
if (io_apic_assign_pci_irqs) {
|
|
||||||
int irq;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* interrupt pins are numbered starting from 1
|
|
||||||
*/
|
|
||||||
irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
|
|
||||||
PCI_SLOT(dev->devfn), pin - 1);
|
|
||||||
/*
|
|
||||||
* Busses behind bridges are typically not listed in the
|
|
||||||
* MP-table. In this case we have to look up the IRQ
|
|
||||||
* based on the parent bus, parent slot, and pin number.
|
|
||||||
* The SMP code detects such bridged busses itself so we
|
|
||||||
* should get into this branch reliably.
|
|
||||||
*/
|
|
||||||
if (irq < 0 && dev->bus->parent) {
|
|
||||||
/* go back to the bridge */
|
|
||||||
struct pci_dev *bridge = dev->bus->self;
|
|
||||||
int bus;
|
|
||||||
|
|
||||||
pin = pci_swizzle_interrupt_pin(dev, pin);
|
|
||||||
bus = bridge->bus->number;
|
|
||||||
irq = IO_APIC_get_PCI_irq_vector(bus,
|
|
||||||
PCI_SLOT(bridge->devfn), pin - 1);
|
|
||||||
if (irq >= 0)
|
|
||||||
dev_warn(&dev->dev,
|
|
||||||
"using bridge %s INT %c to "
|
|
||||||
"get IRQ %d\n",
|
|
||||||
pci_name(bridge),
|
|
||||||
'A' + pin - 1, irq);
|
|
||||||
}
|
|
||||||
if (irq >= 0) {
|
|
||||||
dev_info(&dev->dev,
|
|
||||||
"PCI->APIC IRQ transform: INT %c "
|
|
||||||
"-> IRQ %d\n",
|
|
||||||
'A' + pin - 1, irq);
|
|
||||||
dev->irq = irq;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* Still no IRQ? Try to lookup one...
|
* Still no IRQ? Try to lookup one...
|
||||||
*/
|
*/
|
||||||
|
@ -1183,6 +1145,19 @@ int __init pcibios_irq_init(void)
|
||||||
pcibios_enable_irq = pirq_enable_irq;
|
pcibios_enable_irq = pirq_enable_irq;
|
||||||
|
|
||||||
pcibios_fixup_irqs();
|
pcibios_fixup_irqs();
|
||||||
|
|
||||||
|
if (io_apic_assign_pci_irqs && pci_routeirq) {
|
||||||
|
struct pci_dev *dev = NULL;
|
||||||
|
/*
|
||||||
|
* PCI IRQ routing is set up by pci_enable_device(), but we
|
||||||
|
* also do it here in case there are still broken drivers that
|
||||||
|
* don't use pci_enable_device().
|
||||||
|
*/
|
||||||
|
printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
|
||||||
|
for_each_pci_dev(dev)
|
||||||
|
pirq_enable_irq(dev);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1213,16 +1188,23 @@ void pcibios_penalize_isa_irq(int irq, int active)
|
||||||
static int pirq_enable_irq(struct pci_dev *dev)
|
static int pirq_enable_irq(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
u8 pin;
|
u8 pin;
|
||||||
struct pci_dev *temp_dev;
|
|
||||||
|
|
||||||
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
|
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
|
||||||
if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
|
if (pin && !pcibios_lookup_irq(dev, 1)) {
|
||||||
char *msg = "";
|
char *msg = "";
|
||||||
|
|
||||||
if (io_apic_assign_pci_irqs) {
|
if (!io_apic_assign_pci_irqs && dev->irq)
|
||||||
int irq;
|
return 0;
|
||||||
|
|
||||||
irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin - 1);
|
if (io_apic_assign_pci_irqs) {
|
||||||
|
#ifdef CONFIG_X86_IO_APIC
|
||||||
|
struct pci_dev *temp_dev;
|
||||||
|
int irq;
|
||||||
|
struct io_apic_irq_attr irq_attr;
|
||||||
|
|
||||||
|
irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
|
||||||
|
PCI_SLOT(dev->devfn),
|
||||||
|
pin - 1, &irq_attr);
|
||||||
/*
|
/*
|
||||||
* Busses behind bridges are typically not listed in the MP-table.
|
* Busses behind bridges are typically not listed in the MP-table.
|
||||||
* In this case we have to look up the IRQ based on the parent bus,
|
* In this case we have to look up the IRQ based on the parent bus,
|
||||||
|
@ -1235,7 +1217,8 @@ static int pirq_enable_irq(struct pci_dev *dev)
|
||||||
|
|
||||||
pin = pci_swizzle_interrupt_pin(dev, pin);
|
pin = pci_swizzle_interrupt_pin(dev, pin);
|
||||||
irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
|
irq = IO_APIC_get_PCI_irq_vector(bridge->bus->number,
|
||||||
PCI_SLOT(bridge->devfn), pin - 1);
|
PCI_SLOT(bridge->devfn),
|
||||||
|
pin - 1, &irq_attr);
|
||||||
if (irq >= 0)
|
if (irq >= 0)
|
||||||
dev_warn(&dev->dev, "using bridge %s "
|
dev_warn(&dev->dev, "using bridge %s "
|
||||||
"INT %c to get IRQ %d\n",
|
"INT %c to get IRQ %d\n",
|
||||||
|
@ -1245,12 +1228,15 @@ static int pirq_enable_irq(struct pci_dev *dev)
|
||||||
}
|
}
|
||||||
dev = temp_dev;
|
dev = temp_dev;
|
||||||
if (irq >= 0) {
|
if (irq >= 0) {
|
||||||
|
io_apic_set_pci_routing(&dev->dev, irq,
|
||||||
|
&irq_attr);
|
||||||
|
dev->irq = irq;
|
||||||
dev_info(&dev->dev, "PCI->APIC IRQ transform: "
|
dev_info(&dev->dev, "PCI->APIC IRQ transform: "
|
||||||
"INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
|
"INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
|
||||||
dev->irq = irq;
|
|
||||||
return 0;
|
return 0;
|
||||||
} else
|
} else
|
||||||
msg = "; probably buggy MP table";
|
msg = "; probably buggy MP table";
|
||||||
|
#endif
|
||||||
} else if (pci_probe & PCI_BIOS_IRQ_SCAN)
|
} else if (pci_probe & PCI_BIOS_IRQ_SCAN)
|
||||||
msg = "";
|
msg = "";
|
||||||
else
|
else
|
||||||
|
|
|
@ -401,7 +401,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
|
||||||
/* Interrupt Line values above 0xF are forbidden */
|
/* Interrupt Line values above 0xF are forbidden */
|
||||||
if (dev->irq > 0 && (dev->irq <= 0xF)) {
|
if (dev->irq > 0 && (dev->irq <= 0xF)) {
|
||||||
printk(" - using IRQ %d\n", dev->irq);
|
printk(" - using IRQ %d\n", dev->irq);
|
||||||
acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE,
|
acpi_register_gsi(&dev->dev, dev->irq,
|
||||||
|
ACPI_LEVEL_SENSITIVE,
|
||||||
ACPI_ACTIVE_LOW);
|
ACPI_ACTIVE_LOW);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -410,7 +411,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = acpi_register_gsi(gsi, triggering, polarity);
|
rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
|
dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
|
||||||
pin_name(pin));
|
pin_name(pin));
|
||||||
|
|
|
@ -224,7 +224,7 @@ static void hpet_timer_set_irq(struct hpet_dev *devp)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
gsi = acpi_register_gsi(irq, ACPI_LEVEL_SENSITIVE,
|
gsi = acpi_register_gsi(NULL, irq, ACPI_LEVEL_SENSITIVE,
|
||||||
ACPI_ACTIVE_LOW);
|
ACPI_ACTIVE_LOW);
|
||||||
if (gsi > 0)
|
if (gsi > 0)
|
||||||
break;
|
break;
|
||||||
|
@ -939,7 +939,7 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
|
||||||
irqp = &res->data.extended_irq;
|
irqp = &res->data.extended_irq;
|
||||||
|
|
||||||
for (i = 0; i < irqp->interrupt_count; i++) {
|
for (i = 0; i < irqp->interrupt_count; i++) {
|
||||||
irq = acpi_register_gsi(irqp->interrupts[i],
|
irq = acpi_register_gsi(NULL, irqp->interrupts[i],
|
||||||
irqp->triggering, irqp->polarity);
|
irqp->triggering, irqp->polarity);
|
||||||
if (irq < 0)
|
if (irq < 0)
|
||||||
return AE_ERROR;
|
return AE_ERROR;
|
||||||
|
|
|
@ -702,7 +702,7 @@ static unsigned int iosapic_startup_irq(unsigned int irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
static void iosapic_set_affinity_irq(unsigned int irq,
|
static int iosapic_set_affinity_irq(unsigned int irq,
|
||||||
const struct cpumask *dest)
|
const struct cpumask *dest)
|
||||||
{
|
{
|
||||||
struct vector_info *vi = iosapic_get_vector(irq);
|
struct vector_info *vi = iosapic_get_vector(irq);
|
||||||
|
@ -712,7 +712,7 @@ static void iosapic_set_affinity_irq(unsigned int irq,
|
||||||
|
|
||||||
dest_cpu = cpu_check_affinity(irq, dest);
|
dest_cpu = cpu_check_affinity(irq, dest);
|
||||||
if (dest_cpu < 0)
|
if (dest_cpu < 0)
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
cpumask_copy(irq_desc[irq].affinity, cpumask_of(dest_cpu));
|
cpumask_copy(irq_desc[irq].affinity, cpumask_of(dest_cpu));
|
||||||
vi->txn_addr = txn_affinity_addr(irq, dest_cpu);
|
vi->txn_addr = txn_affinity_addr(irq, dest_cpu);
|
||||||
|
@ -724,6 +724,8 @@ static void iosapic_set_affinity_irq(unsigned int irq,
|
||||||
iosapic_set_irt_data(vi, &dummy_d0, &d1);
|
iosapic_set_irt_data(vi, &dummy_d0, &d1);
|
||||||
iosapic_wr_irt_entry(vi, d0, d1);
|
iosapic_wr_irt_entry(vi, d0, d1);
|
||||||
spin_unlock_irqrestore(&iosapic_lock, flags);
|
spin_unlock_irqrestore(&iosapic_lock, flags);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -153,12 +153,15 @@ int ibmphp_init_devno(struct slot **cur_slot)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
for (loop = 0; loop < len; loop++) {
|
for (loop = 0; loop < len; loop++) {
|
||||||
if ((*cur_slot)->number == rtable->slots[loop].slot) {
|
if ((*cur_slot)->number == rtable->slots[loop].slot &&
|
||||||
if ((*cur_slot)->bus == rtable->slots[loop].bus) {
|
(*cur_slot)->bus == rtable->slots[loop].bus) {
|
||||||
|
struct io_apic_irq_attr irq_attr;
|
||||||
|
|
||||||
(*cur_slot)->device = PCI_SLOT(rtable->slots[loop].devfn);
|
(*cur_slot)->device = PCI_SLOT(rtable->slots[loop].devfn);
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
(*cur_slot)->irq[i] = IO_APIC_get_PCI_irq_vector((int) (*cur_slot)->bus,
|
(*cur_slot)->irq[i] = IO_APIC_get_PCI_irq_vector((int) (*cur_slot)->bus,
|
||||||
(int) (*cur_slot)->device, i);
|
(int) (*cur_slot)->device, i,
|
||||||
|
&irq_attr);
|
||||||
|
|
||||||
debug("(*cur_slot)->irq[0] = %x\n",
|
debug("(*cur_slot)->irq[0] = %x\n",
|
||||||
(*cur_slot)->irq[0]);
|
(*cur_slot)->irq[0]);
|
||||||
|
@ -193,7 +196,6 @@ int ibmphp_init_devno(struct slot **cur_slot)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
kfree(rtable);
|
kfree(rtable);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -98,6 +98,7 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
|
||||||
int max_irq;
|
int max_irq;
|
||||||
int pos;
|
int pos;
|
||||||
int irq;
|
int irq;
|
||||||
|
int node;
|
||||||
|
|
||||||
pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ);
|
pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ);
|
||||||
if (!pos)
|
if (!pos)
|
||||||
|
@ -125,7 +126,8 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
|
||||||
cfg->msg.address_lo = 0xffffffff;
|
cfg->msg.address_lo = 0xffffffff;
|
||||||
cfg->msg.address_hi = 0xffffffff;
|
cfg->msg.address_hi = 0xffffffff;
|
||||||
|
|
||||||
irq = create_irq();
|
node = dev_to_node(&dev->dev);
|
||||||
|
irq = create_irq_nr(0, node);
|
||||||
|
|
||||||
if (irq <= 0) {
|
if (irq <= 0) {
|
||||||
kfree(cfg);
|
kfree(cfg);
|
||||||
|
|
|
@ -1972,15 +1972,6 @@ static int __init init_dmars(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_INTR_REMAP
|
|
||||||
if (!intr_remapping_enabled) {
|
|
||||||
ret = enable_intr_remapping(0);
|
|
||||||
if (ret)
|
|
||||||
printk(KERN_ERR
|
|
||||||
"IOMMU: enable interrupt remapping failed\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For each rmrr
|
* For each rmrr
|
||||||
* for each dev attached to rmrr
|
* for each dev attached to rmrr
|
||||||
|
|
|
@ -15,6 +15,14 @@ static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
|
||||||
static int ir_ioapic_num;
|
static int ir_ioapic_num;
|
||||||
int intr_remapping_enabled;
|
int intr_remapping_enabled;
|
||||||
|
|
||||||
|
static int disable_intremap;
|
||||||
|
static __init int setup_nointremap(char *str)
|
||||||
|
{
|
||||||
|
disable_intremap = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
early_param("nointremap", setup_nointremap);
|
||||||
|
|
||||||
struct irq_2_iommu {
|
struct irq_2_iommu {
|
||||||
struct intel_iommu *iommu;
|
struct intel_iommu *iommu;
|
||||||
u16 irte_index;
|
u16 irte_index;
|
||||||
|
@ -23,15 +31,12 @@ struct irq_2_iommu {
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_GENERIC_HARDIRQS
|
#ifdef CONFIG_GENERIC_HARDIRQS
|
||||||
static struct irq_2_iommu *get_one_free_irq_2_iommu(int cpu)
|
static struct irq_2_iommu *get_one_free_irq_2_iommu(int node)
|
||||||
{
|
{
|
||||||
struct irq_2_iommu *iommu;
|
struct irq_2_iommu *iommu;
|
||||||
int node;
|
|
||||||
|
|
||||||
node = cpu_to_node(cpu);
|
|
||||||
|
|
||||||
iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node);
|
iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node);
|
||||||
printk(KERN_DEBUG "alloc irq_2_iommu on cpu %d node %d\n", cpu, node);
|
printk(KERN_DEBUG "alloc irq_2_iommu on node %d\n", node);
|
||||||
|
|
||||||
return iommu;
|
return iommu;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +53,7 @@ static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
|
||||||
return desc->irq_2_iommu;
|
return desc->irq_2_iommu;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu)
|
static struct irq_2_iommu *irq_2_iommu_alloc_node(unsigned int irq, int node)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc;
|
struct irq_desc *desc;
|
||||||
struct irq_2_iommu *irq_iommu;
|
struct irq_2_iommu *irq_iommu;
|
||||||
|
@ -56,7 +61,7 @@ static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu)
|
||||||
/*
|
/*
|
||||||
* alloc irq desc if not allocated already.
|
* alloc irq desc if not allocated already.
|
||||||
*/
|
*/
|
||||||
desc = irq_to_desc_alloc_cpu(irq, cpu);
|
desc = irq_to_desc_alloc_node(irq, node);
|
||||||
if (!desc) {
|
if (!desc) {
|
||||||
printk(KERN_INFO "can not get irq_desc for %d\n", irq);
|
printk(KERN_INFO "can not get irq_desc for %d\n", irq);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -65,14 +70,14 @@ static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu)
|
||||||
irq_iommu = desc->irq_2_iommu;
|
irq_iommu = desc->irq_2_iommu;
|
||||||
|
|
||||||
if (!irq_iommu)
|
if (!irq_iommu)
|
||||||
desc->irq_2_iommu = get_one_free_irq_2_iommu(cpu);
|
desc->irq_2_iommu = get_one_free_irq_2_iommu(node);
|
||||||
|
|
||||||
return desc->irq_2_iommu;
|
return desc->irq_2_iommu;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
|
static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
|
||||||
{
|
{
|
||||||
return irq_2_iommu_alloc_cpu(irq, boot_cpu_id);
|
return irq_2_iommu_alloc_node(irq, cpu_to_node(boot_cpu_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !CONFIG_SPARSE_IRQ */
|
#else /* !CONFIG_SPARSE_IRQ */
|
||||||
|
@ -423,20 +428,6 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
|
||||||
readl, (sts & DMA_GSTS_IRTPS), sts);
|
readl, (sts & DMA_GSTS_IRTPS), sts);
|
||||||
spin_unlock_irqrestore(&iommu->register_lock, flags);
|
spin_unlock_irqrestore(&iommu->register_lock, flags);
|
||||||
|
|
||||||
if (mode == 0) {
|
|
||||||
spin_lock_irqsave(&iommu->register_lock, flags);
|
|
||||||
|
|
||||||
/* enable comaptiblity format interrupt pass through */
|
|
||||||
cmd = iommu->gcmd | DMA_GCMD_CFI;
|
|
||||||
iommu->gcmd |= DMA_GCMD_CFI;
|
|
||||||
writel(cmd, iommu->reg + DMAR_GCMD_REG);
|
|
||||||
|
|
||||||
IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
|
|
||||||
readl, (sts & DMA_GSTS_CFIS), sts);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&iommu->register_lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* global invalidation of interrupt entry cache before enabling
|
* global invalidation of interrupt entry cache before enabling
|
||||||
* interrupt-remapping.
|
* interrupt-remapping.
|
||||||
|
@ -516,6 +507,23 @@ end:
|
||||||
spin_unlock_irqrestore(&iommu->register_lock, flags);
|
spin_unlock_irqrestore(&iommu->register_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int __init intr_remapping_supported(void)
|
||||||
|
{
|
||||||
|
struct dmar_drhd_unit *drhd;
|
||||||
|
|
||||||
|
if (disable_intremap)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for_each_drhd_unit(drhd) {
|
||||||
|
struct intel_iommu *iommu = drhd->iommu;
|
||||||
|
|
||||||
|
if (!ecap_ir_support(iommu->ecap))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int __init enable_intr_remapping(int eim)
|
int __init enable_intr_remapping(int eim)
|
||||||
{
|
{
|
||||||
struct dmar_drhd_unit *drhd;
|
struct dmar_drhd_unit *drhd;
|
||||||
|
|
|
@ -123,7 +123,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = irq_flags(triggering, polarity, shareable);
|
flags = irq_flags(triggering, polarity, shareable);
|
||||||
irq = acpi_register_gsi(gsi, triggering, polarity);
|
irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
|
||||||
if (irq >= 0)
|
if (irq >= 0)
|
||||||
pcibios_penalize_isa_irq(irq, 1);
|
pcibios_penalize_isa_irq(irq, 1);
|
||||||
else
|
else
|
||||||
|
|
|
@ -335,7 +335,7 @@ static int find_unbound_irq(void)
|
||||||
if (irq == nr_irqs)
|
if (irq == nr_irqs)
|
||||||
panic("No available IRQ to bind to: increase nr_irqs!\n");
|
panic("No available IRQ to bind to: increase nr_irqs!\n");
|
||||||
|
|
||||||
desc = irq_to_desc_alloc_cpu(irq, 0);
|
desc = irq_to_desc_alloc_node(irq, 0);
|
||||||
if (WARN_ON(desc == NULL))
|
if (WARN_ON(desc == NULL))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -688,13 +688,13 @@ void rebind_evtchn_irq(int evtchn, int irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Rebind an evtchn so that it gets delivered to a specific cpu */
|
/* Rebind an evtchn so that it gets delivered to a specific cpu */
|
||||||
static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
|
static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
|
||||||
{
|
{
|
||||||
struct evtchn_bind_vcpu bind_vcpu;
|
struct evtchn_bind_vcpu bind_vcpu;
|
||||||
int evtchn = evtchn_from_irq(irq);
|
int evtchn = evtchn_from_irq(irq);
|
||||||
|
|
||||||
if (!VALID_EVTCHN(evtchn))
|
if (!VALID_EVTCHN(evtchn))
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
/* Send future instances of this interrupt to other vcpu. */
|
/* Send future instances of this interrupt to other vcpu. */
|
||||||
bind_vcpu.port = evtchn;
|
bind_vcpu.port = evtchn;
|
||||||
|
@ -707,13 +707,15 @@ static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu)
|
||||||
*/
|
*/
|
||||||
if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
|
if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0)
|
||||||
bind_evtchn_to_cpu(evtchn, tcpu);
|
bind_evtchn_to_cpu(evtchn, tcpu);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int set_affinity_irq(unsigned irq, const struct cpumask *dest)
|
||||||
static void set_affinity_irq(unsigned irq, const struct cpumask *dest)
|
|
||||||
{
|
{
|
||||||
unsigned tcpu = cpumask_first(dest);
|
unsigned tcpu = cpumask_first(dest);
|
||||||
rebind_irq_to_cpu(irq, tcpu);
|
|
||||||
|
return rebind_irq_to_cpu(irq, tcpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
int resend_irq_on_evtchn(unsigned int irq)
|
int resend_irq_on_evtchn(unsigned int irq)
|
||||||
|
|
|
@ -119,7 +119,7 @@ extern int pci_mmcfg_config_num;
|
||||||
extern int sbf_port;
|
extern int sbf_port;
|
||||||
extern unsigned long acpi_realmode_flags;
|
extern unsigned long acpi_realmode_flags;
|
||||||
|
|
||||||
int acpi_register_gsi (u32 gsi, int triggering, int polarity);
|
int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);
|
||||||
int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
|
int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
#ifdef CONFIG_X86_IO_APIC
|
||||||
|
|
|
@ -108,6 +108,7 @@ struct irte {
|
||||||
};
|
};
|
||||||
#ifdef CONFIG_INTR_REMAP
|
#ifdef CONFIG_INTR_REMAP
|
||||||
extern int intr_remapping_enabled;
|
extern int intr_remapping_enabled;
|
||||||
|
extern int intr_remapping_supported(void);
|
||||||
extern int enable_intr_remapping(int);
|
extern int enable_intr_remapping(int);
|
||||||
extern void disable_intr_remapping(void);
|
extern void disable_intr_remapping(void);
|
||||||
extern int reenable_intr_remapping(int);
|
extern int reenable_intr_remapping(int);
|
||||||
|
@ -157,6 +158,8 @@ static inline struct intel_iommu *map_ioapic_to_ir(int apic)
|
||||||
}
|
}
|
||||||
#define irq_remapped(irq) (0)
|
#define irq_remapped(irq) (0)
|
||||||
#define enable_intr_remapping(mode) (-1)
|
#define enable_intr_remapping(mode) (-1)
|
||||||
|
#define disable_intr_remapping() (0)
|
||||||
|
#define reenable_intr_remapping(mode) (0)
|
||||||
#define intr_remapping_enabled (0)
|
#define intr_remapping_enabled (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -566,6 +566,6 @@ struct irq_desc;
|
||||||
extern int early_irq_init(void);
|
extern int early_irq_init(void);
|
||||||
extern int arch_probe_nr_irqs(void);
|
extern int arch_probe_nr_irqs(void);
|
||||||
extern int arch_early_irq_init(void);
|
extern int arch_early_irq_init(void);
|
||||||
extern int arch_init_chip_data(struct irq_desc *desc, int cpu);
|
extern int arch_init_chip_data(struct irq_desc *desc, int node);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -117,7 +117,7 @@ struct irq_chip {
|
||||||
void (*eoi)(unsigned int irq);
|
void (*eoi)(unsigned int irq);
|
||||||
|
|
||||||
void (*end)(unsigned int irq);
|
void (*end)(unsigned int irq);
|
||||||
void (*set_affinity)(unsigned int irq,
|
int (*set_affinity)(unsigned int irq,
|
||||||
const struct cpumask *dest);
|
const struct cpumask *dest);
|
||||||
int (*retrigger)(unsigned int irq);
|
int (*retrigger)(unsigned int irq);
|
||||||
int (*set_type)(unsigned int irq, unsigned int flow_type);
|
int (*set_type)(unsigned int irq, unsigned int flow_type);
|
||||||
|
@ -187,7 +187,7 @@ struct irq_desc {
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
cpumask_var_t affinity;
|
cpumask_var_t affinity;
|
||||||
unsigned int cpu;
|
unsigned int node;
|
||||||
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
||||||
cpumask_var_t pending_mask;
|
cpumask_var_t pending_mask;
|
||||||
#endif
|
#endif
|
||||||
|
@ -201,26 +201,23 @@ struct irq_desc {
|
||||||
} ____cacheline_internodealigned_in_smp;
|
} ____cacheline_internodealigned_in_smp;
|
||||||
|
|
||||||
extern void arch_init_copy_chip_data(struct irq_desc *old_desc,
|
extern void arch_init_copy_chip_data(struct irq_desc *old_desc,
|
||||||
struct irq_desc *desc, int cpu);
|
struct irq_desc *desc, int node);
|
||||||
extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc);
|
extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc);
|
||||||
|
|
||||||
#ifndef CONFIG_SPARSE_IRQ
|
#ifndef CONFIG_SPARSE_IRQ
|
||||||
extern struct irq_desc irq_desc[NR_IRQS];
|
extern struct irq_desc irq_desc[NR_IRQS];
|
||||||
#else /* CONFIG_SPARSE_IRQ */
|
|
||||||
extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int cpu);
|
|
||||||
#endif /* CONFIG_SPARSE_IRQ */
|
|
||||||
|
|
||||||
extern struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu);
|
|
||||||
|
|
||||||
static inline struct irq_desc *
|
|
||||||
irq_remap_to_desc(unsigned int irq, struct irq_desc *desc)
|
|
||||||
{
|
|
||||||
#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
|
|
||||||
return irq_to_desc(irq);
|
|
||||||
#else
|
|
||||||
return desc;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_NUMA_IRQ_DESC
|
||||||
|
extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int node);
|
||||||
|
#else
|
||||||
|
static inline struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
|
||||||
|
{
|
||||||
|
return desc;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Migration helpers for obsolete names, they will go away:
|
* Migration helpers for obsolete names, they will go away:
|
||||||
|
@ -386,7 +383,7 @@ extern void set_irq_noprobe(unsigned int irq);
|
||||||
extern void set_irq_probe(unsigned int irq);
|
extern void set_irq_probe(unsigned int irq);
|
||||||
|
|
||||||
/* Handle dynamic irq creation and destruction */
|
/* Handle dynamic irq creation and destruction */
|
||||||
extern unsigned int create_irq_nr(unsigned int irq_want);
|
extern unsigned int create_irq_nr(unsigned int irq_want, int node);
|
||||||
extern int create_irq(void);
|
extern int create_irq(void);
|
||||||
extern void destroy_irq(unsigned int irq);
|
extern void destroy_irq(unsigned int irq);
|
||||||
|
|
||||||
|
@ -424,47 +421,48 @@ extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
/**
|
/**
|
||||||
* init_alloc_desc_masks - allocate cpumasks for irq_desc
|
* alloc_desc_masks - allocate cpumasks for irq_desc
|
||||||
* @desc: pointer to irq_desc struct
|
* @desc: pointer to irq_desc struct
|
||||||
* @cpu: cpu which will be handling the cpumasks
|
* @cpu: cpu which will be handling the cpumasks
|
||||||
* @boot: true if need bootmem
|
* @boot: true if need bootmem
|
||||||
*
|
*
|
||||||
* Allocates affinity and pending_mask cpumask if required.
|
* Allocates affinity and pending_mask cpumask if required.
|
||||||
* Returns true if successful (or not required).
|
* Returns true if successful (or not required).
|
||||||
* Side effect: affinity has all bits set, pending_mask has all bits clear.
|
|
||||||
*/
|
*/
|
||||||
static inline bool init_alloc_desc_masks(struct irq_desc *desc, int cpu,
|
static inline bool alloc_desc_masks(struct irq_desc *desc, int node,
|
||||||
bool boot)
|
bool boot)
|
||||||
{
|
{
|
||||||
int node;
|
#ifdef CONFIG_CPUMASK_OFFSTACK
|
||||||
|
|
||||||
if (boot) {
|
if (boot) {
|
||||||
alloc_bootmem_cpumask_var(&desc->affinity);
|
alloc_bootmem_cpumask_var(&desc->affinity);
|
||||||
cpumask_setall(desc->affinity);
|
|
||||||
|
|
||||||
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
||||||
alloc_bootmem_cpumask_var(&desc->pending_mask);
|
alloc_bootmem_cpumask_var(&desc->pending_mask);
|
||||||
cpumask_clear(desc->pending_mask);
|
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = cpu_to_node(cpu);
|
|
||||||
|
|
||||||
if (!alloc_cpumask_var_node(&desc->affinity, GFP_ATOMIC, node))
|
if (!alloc_cpumask_var_node(&desc->affinity, GFP_ATOMIC, node))
|
||||||
return false;
|
return false;
|
||||||
cpumask_setall(desc->affinity);
|
|
||||||
|
|
||||||
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
||||||
if (!alloc_cpumask_var_node(&desc->pending_mask, GFP_ATOMIC, node)) {
|
if (!alloc_cpumask_var_node(&desc->pending_mask, GFP_ATOMIC, node)) {
|
||||||
free_cpumask_var(desc->affinity);
|
free_cpumask_var(desc->affinity);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cpumask_clear(desc->pending_mask);
|
#endif
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void init_desc_masks(struct irq_desc *desc)
|
||||||
|
{
|
||||||
|
cpumask_setall(desc->affinity);
|
||||||
|
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
||||||
|
cpumask_clear(desc->pending_mask);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init_copy_desc_masks - copy cpumasks for irq_desc
|
* init_copy_desc_masks - copy cpumasks for irq_desc
|
||||||
* @old_desc: pointer to old irq_desc struct
|
* @old_desc: pointer to old irq_desc struct
|
||||||
|
@ -478,7 +476,7 @@ static inline bool init_alloc_desc_masks(struct irq_desc *desc, int cpu,
|
||||||
static inline void init_copy_desc_masks(struct irq_desc *old_desc,
|
static inline void init_copy_desc_masks(struct irq_desc *old_desc,
|
||||||
struct irq_desc *new_desc)
|
struct irq_desc *new_desc)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_CPUMASKS_OFFSTACK
|
#ifdef CONFIG_CPUMASK_OFFSTACK
|
||||||
cpumask_copy(new_desc->affinity, old_desc->affinity);
|
cpumask_copy(new_desc->affinity, old_desc->affinity);
|
||||||
|
|
||||||
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
||||||
|
@ -499,12 +497,16 @@ static inline void free_desc_masks(struct irq_desc *old_desc,
|
||||||
|
|
||||||
#else /* !CONFIG_SMP */
|
#else /* !CONFIG_SMP */
|
||||||
|
|
||||||
static inline bool init_alloc_desc_masks(struct irq_desc *desc, int cpu,
|
static inline bool alloc_desc_masks(struct irq_desc *desc, int node,
|
||||||
bool boot)
|
bool boot)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void init_desc_masks(struct irq_desc *desc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static inline void init_copy_desc_masks(struct irq_desc *old_desc,
|
static inline void init_copy_desc_masks(struct irq_desc *old_desc,
|
||||||
struct irq_desc *new_desc)
|
struct irq_desc *new_desc)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,5 +3,5 @@ obj-y := handle.o manage.o spurious.o resend.o chip.o devres.o
|
||||||
obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
|
obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
|
||||||
obj-$(CONFIG_PROC_FS) += proc.o
|
obj-$(CONFIG_PROC_FS) += proc.o
|
||||||
obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
|
obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
|
||||||
obj-$(CONFIG_NUMA_MIGRATE_IRQ_DESC) += numa_migrate.o
|
obj-$(CONFIG_NUMA_IRQ_DESC) += numa_migrate.o
|
||||||
obj-$(CONFIG_PM_SLEEP) += pm.o
|
obj-$(CONFIG_PM_SLEEP) += pm.o
|
||||||
|
|
|
@ -359,7 +359,6 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
|
||||||
|
|
||||||
spin_lock(&desc->lock);
|
spin_lock(&desc->lock);
|
||||||
mask_ack_irq(desc, irq);
|
mask_ack_irq(desc, irq);
|
||||||
desc = irq_remap_to_desc(irq, desc);
|
|
||||||
|
|
||||||
if (unlikely(desc->status & IRQ_INPROGRESS))
|
if (unlikely(desc->status & IRQ_INPROGRESS))
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
@ -438,7 +437,6 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
|
||||||
desc->status &= ~IRQ_INPROGRESS;
|
desc->status &= ~IRQ_INPROGRESS;
|
||||||
out:
|
out:
|
||||||
desc->chip->eoi(irq);
|
desc->chip->eoi(irq);
|
||||||
desc = irq_remap_to_desc(irq, desc);
|
|
||||||
|
|
||||||
spin_unlock(&desc->lock);
|
spin_unlock(&desc->lock);
|
||||||
}
|
}
|
||||||
|
@ -475,7 +473,6 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
|
||||||
!desc->action)) {
|
!desc->action)) {
|
||||||
desc->status |= (IRQ_PENDING | IRQ_MASKED);
|
desc->status |= (IRQ_PENDING | IRQ_MASKED);
|
||||||
mask_ack_irq(desc, irq);
|
mask_ack_irq(desc, irq);
|
||||||
desc = irq_remap_to_desc(irq, desc);
|
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
kstat_incr_irqs_this_cpu(irq, desc);
|
kstat_incr_irqs_this_cpu(irq, desc);
|
||||||
|
@ -483,7 +480,6 @@ handle_edge_irq(unsigned int irq, struct irq_desc *desc)
|
||||||
/* Start handling the irq */
|
/* Start handling the irq */
|
||||||
if (desc->chip->ack)
|
if (desc->chip->ack)
|
||||||
desc->chip->ack(irq);
|
desc->chip->ack(irq);
|
||||||
desc = irq_remap_to_desc(irq, desc);
|
|
||||||
|
|
||||||
/* Mark the IRQ currently in progress.*/
|
/* Mark the IRQ currently in progress.*/
|
||||||
desc->status |= IRQ_INPROGRESS;
|
desc->status |= IRQ_INPROGRESS;
|
||||||
|
@ -544,10 +540,8 @@ handle_percpu_irq(unsigned int irq, struct irq_desc *desc)
|
||||||
if (!noirqdebug)
|
if (!noirqdebug)
|
||||||
note_interrupt(irq, desc, action_ret);
|
note_interrupt(irq, desc, action_ret);
|
||||||
|
|
||||||
if (desc->chip->eoi) {
|
if (desc->chip->eoi)
|
||||||
desc->chip->eoi(irq);
|
desc->chip->eoi(irq);
|
||||||
desc = irq_remap_to_desc(irq, desc);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -582,10 +576,8 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
|
||||||
|
|
||||||
/* Uninstall? */
|
/* Uninstall? */
|
||||||
if (handle == handle_bad_irq) {
|
if (handle == handle_bad_irq) {
|
||||||
if (desc->chip != &no_irq_chip) {
|
if (desc->chip != &no_irq_chip)
|
||||||
mask_ack_irq(desc, irq);
|
mask_ack_irq(desc, irq);
|
||||||
desc = irq_remap_to_desc(irq, desc);
|
|
||||||
}
|
|
||||||
desc->status |= IRQ_DISABLED;
|
desc->status |= IRQ_DISABLED;
|
||||||
desc->depth = 1;
|
desc->depth = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
@ -81,45 +82,48 @@ static struct irq_desc irq_desc_init = {
|
||||||
.lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
|
.lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
|
||||||
};
|
};
|
||||||
|
|
||||||
void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr)
|
void __ref init_kstat_irqs(struct irq_desc *desc, int node, int nr)
|
||||||
{
|
{
|
||||||
int node;
|
|
||||||
void *ptr;
|
void *ptr;
|
||||||
|
|
||||||
node = cpu_to_node(cpu);
|
if (slab_is_available())
|
||||||
ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs), GFP_ATOMIC, node);
|
ptr = kzalloc_node(nr * sizeof(*desc->kstat_irqs),
|
||||||
|
GFP_ATOMIC, node);
|
||||||
|
else
|
||||||
|
ptr = alloc_bootmem_node(NODE_DATA(node),
|
||||||
|
nr * sizeof(*desc->kstat_irqs));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* don't overwite if can not get new one
|
* don't overwite if can not get new one
|
||||||
* init_copy_kstat_irqs() could still use old one
|
* init_copy_kstat_irqs() could still use old one
|
||||||
*/
|
*/
|
||||||
if (ptr) {
|
if (ptr) {
|
||||||
printk(KERN_DEBUG " alloc kstat_irqs on cpu %d node %d\n",
|
printk(KERN_DEBUG " alloc kstat_irqs on node %d\n", node);
|
||||||
cpu, node);
|
|
||||||
desc->kstat_irqs = ptr;
|
desc->kstat_irqs = ptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu)
|
static void init_one_irq_desc(int irq, struct irq_desc *desc, int node)
|
||||||
{
|
{
|
||||||
memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
|
memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
|
||||||
|
|
||||||
spin_lock_init(&desc->lock);
|
spin_lock_init(&desc->lock);
|
||||||
desc->irq = irq;
|
desc->irq = irq;
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
desc->cpu = cpu;
|
desc->node = node;
|
||||||
#endif
|
#endif
|
||||||
lockdep_set_class(&desc->lock, &irq_desc_lock_class);
|
lockdep_set_class(&desc->lock, &irq_desc_lock_class);
|
||||||
init_kstat_irqs(desc, cpu, nr_cpu_ids);
|
init_kstat_irqs(desc, node, nr_cpu_ids);
|
||||||
if (!desc->kstat_irqs) {
|
if (!desc->kstat_irqs) {
|
||||||
printk(KERN_ERR "can not alloc kstat_irqs\n");
|
printk(KERN_ERR "can not alloc kstat_irqs\n");
|
||||||
BUG_ON(1);
|
BUG_ON(1);
|
||||||
}
|
}
|
||||||
if (!init_alloc_desc_masks(desc, cpu, false)) {
|
if (!alloc_desc_masks(desc, node, false)) {
|
||||||
printk(KERN_ERR "can not alloc irq_desc cpumasks\n");
|
printk(KERN_ERR "can not alloc irq_desc cpumasks\n");
|
||||||
BUG_ON(1);
|
BUG_ON(1);
|
||||||
}
|
}
|
||||||
arch_init_chip_data(desc, cpu);
|
init_desc_masks(desc);
|
||||||
|
arch_init_chip_data(desc, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -169,7 +173,8 @@ int __init early_irq_init(void)
|
||||||
desc[i].irq = i;
|
desc[i].irq = i;
|
||||||
desc[i].kstat_irqs = kstat_irqs_legacy + i * nr_cpu_ids;
|
desc[i].kstat_irqs = kstat_irqs_legacy + i * nr_cpu_ids;
|
||||||
lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
|
lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
|
||||||
init_alloc_desc_masks(&desc[i], 0, true);
|
alloc_desc_masks(&desc[i], 0, true);
|
||||||
|
init_desc_masks(&desc[i]);
|
||||||
irq_desc_ptrs[i] = desc + i;
|
irq_desc_ptrs[i] = desc + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,11 +192,10 @@ struct irq_desc *irq_to_desc(unsigned int irq)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
|
struct irq_desc * __ref irq_to_desc_alloc_node(unsigned int irq, int node)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc;
|
struct irq_desc *desc;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int node;
|
|
||||||
|
|
||||||
if (irq >= nr_irqs) {
|
if (irq >= nr_irqs) {
|
||||||
WARN(1, "irq (%d) >= nr_irqs (%d) in irq_to_desc_alloc\n",
|
WARN(1, "irq (%d) >= nr_irqs (%d) in irq_to_desc_alloc\n",
|
||||||
|
@ -210,15 +214,17 @@ struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
|
||||||
if (desc)
|
if (desc)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
node = cpu_to_node(cpu);
|
if (slab_is_available())
|
||||||
desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
|
desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
|
||||||
printk(KERN_DEBUG " alloc irq_desc for %d on cpu %d node %d\n",
|
else
|
||||||
irq, cpu, node);
|
desc = alloc_bootmem_node(NODE_DATA(node), sizeof(*desc));
|
||||||
|
|
||||||
|
printk(KERN_DEBUG " alloc irq_desc for %d on node %d\n", irq, node);
|
||||||
if (!desc) {
|
if (!desc) {
|
||||||
printk(KERN_ERR "can not alloc irq_desc\n");
|
printk(KERN_ERR "can not alloc irq_desc\n");
|
||||||
BUG_ON(1);
|
BUG_ON(1);
|
||||||
}
|
}
|
||||||
init_one_irq_desc(irq, desc, cpu);
|
init_one_irq_desc(irq, desc, node);
|
||||||
|
|
||||||
irq_desc_ptrs[irq] = desc;
|
irq_desc_ptrs[irq] = desc;
|
||||||
|
|
||||||
|
@ -256,7 +262,8 @@ int __init early_irq_init(void)
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
desc[i].irq = i;
|
desc[i].irq = i;
|
||||||
init_alloc_desc_masks(&desc[i], 0, true);
|
alloc_desc_masks(&desc[i], 0, true);
|
||||||
|
init_desc_masks(&desc[i]);
|
||||||
desc[i].kstat_irqs = kstat_irqs_all[i];
|
desc[i].kstat_irqs = kstat_irqs_all[i];
|
||||||
}
|
}
|
||||||
return arch_early_irq_init();
|
return arch_early_irq_init();
|
||||||
|
@ -267,7 +274,7 @@ struct irq_desc *irq_to_desc(unsigned int irq)
|
||||||
return (irq < NR_IRQS) ? irq_desc + irq : NULL;
|
return (irq < NR_IRQS) ? irq_desc + irq : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
|
struct irq_desc *irq_to_desc_alloc_node(unsigned int irq, int node)
|
||||||
{
|
{
|
||||||
return irq_to_desc(irq);
|
return irq_to_desc(irq);
|
||||||
}
|
}
|
||||||
|
@ -453,11 +460,8 @@ unsigned int __do_IRQ(unsigned int irq)
|
||||||
/*
|
/*
|
||||||
* No locking required for CPU-local interrupts:
|
* No locking required for CPU-local interrupts:
|
||||||
*/
|
*/
|
||||||
if (desc->chip->ack) {
|
if (desc->chip->ack)
|
||||||
desc->chip->ack(irq);
|
desc->chip->ack(irq);
|
||||||
/* get new one */
|
|
||||||
desc = irq_remap_to_desc(irq, desc);
|
|
||||||
}
|
|
||||||
if (likely(!(desc->status & IRQ_DISABLED))) {
|
if (likely(!(desc->status & IRQ_DISABLED))) {
|
||||||
action_ret = handle_IRQ_event(irq, desc->action);
|
action_ret = handle_IRQ_event(irq, desc->action);
|
||||||
if (!noirqdebug)
|
if (!noirqdebug)
|
||||||
|
@ -468,10 +472,8 @@ unsigned int __do_IRQ(unsigned int irq)
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock(&desc->lock);
|
spin_lock(&desc->lock);
|
||||||
if (desc->chip->ack) {
|
if (desc->chip->ack)
|
||||||
desc->chip->ack(irq);
|
desc->chip->ack(irq);
|
||||||
desc = irq_remap_to_desc(irq, desc);
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* REPLAY is when Linux resends an IRQ that was dropped earlier
|
* REPLAY is when Linux resends an IRQ that was dropped earlier
|
||||||
* WAITING is used by probe to mark irqs that are being tested
|
* WAITING is used by probe to mark irqs that are being tested
|
||||||
|
|
|
@ -16,7 +16,7 @@ extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
|
||||||
extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
|
extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
|
||||||
|
|
||||||
extern struct lock_class_key irq_desc_lock_class;
|
extern struct lock_class_key irq_desc_lock_class;
|
||||||
extern void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr);
|
extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);
|
||||||
extern void clear_kstat_irqs(struct irq_desc *desc);
|
extern void clear_kstat_irqs(struct irq_desc *desc);
|
||||||
extern spinlock_t sparse_irq_lock;
|
extern spinlock_t sparse_irq_lock;
|
||||||
|
|
||||||
|
@ -42,6 +42,9 @@ static inline void unregister_handler_proc(unsigned int irq,
|
||||||
|
|
||||||
extern int irq_select_affinity_usr(unsigned int irq);
|
extern int irq_select_affinity_usr(unsigned int irq);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Debugging printout:
|
* Debugging printout:
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -80,7 +80,7 @@ int irq_can_set_affinity(unsigned int irq)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask)
|
irq_set_thread_affinity(struct irq_desc *desc, const struct cpumask *cpumask)
|
||||||
{
|
{
|
||||||
struct irqaction *action = desc->action;
|
struct irqaction *action = desc->action;
|
||||||
|
@ -109,17 +109,22 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask)
|
||||||
spin_lock_irqsave(&desc->lock, flags);
|
spin_lock_irqsave(&desc->lock, flags);
|
||||||
|
|
||||||
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
||||||
if (desc->status & IRQ_MOVE_PCNTXT)
|
if (desc->status & IRQ_MOVE_PCNTXT) {
|
||||||
desc->chip->set_affinity(irq, cpumask);
|
if (!desc->chip->set_affinity(irq, cpumask)) {
|
||||||
|
cpumask_copy(desc->affinity, cpumask);
|
||||||
|
irq_set_thread_affinity(desc, cpumask);
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
desc->status |= IRQ_MOVE_PENDING;
|
desc->status |= IRQ_MOVE_PENDING;
|
||||||
cpumask_copy(desc->pending_mask, cpumask);
|
cpumask_copy(desc->pending_mask, cpumask);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
if (!desc->chip->set_affinity(irq, cpumask)) {
|
||||||
cpumask_copy(desc->affinity, cpumask);
|
cpumask_copy(desc->affinity, cpumask);
|
||||||
desc->chip->set_affinity(irq, cpumask);
|
|
||||||
#endif
|
|
||||||
irq_set_thread_affinity(desc, cpumask);
|
irq_set_thread_affinity(desc, cpumask);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
desc->status |= IRQ_AFFINITY_SET;
|
desc->status |= IRQ_AFFINITY_SET;
|
||||||
spin_unlock_irqrestore(&desc->lock, flags);
|
spin_unlock_irqrestore(&desc->lock, flags);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
|
||||||
|
#include "internals.h"
|
||||||
|
|
||||||
void move_masked_irq(int irq)
|
void move_masked_irq(int irq)
|
||||||
{
|
{
|
||||||
|
@ -39,11 +42,12 @@ void move_masked_irq(int irq)
|
||||||
* masking the irqs.
|
* masking the irqs.
|
||||||
*/
|
*/
|
||||||
if (likely(cpumask_any_and(desc->pending_mask, cpu_online_mask)
|
if (likely(cpumask_any_and(desc->pending_mask, cpu_online_mask)
|
||||||
< nr_cpu_ids)) {
|
< nr_cpu_ids))
|
||||||
cpumask_and(desc->affinity,
|
if (!desc->chip->set_affinity(irq, desc->pending_mask)) {
|
||||||
desc->pending_mask, cpu_online_mask);
|
cpumask_copy(desc->affinity, desc->pending_mask);
|
||||||
desc->chip->set_affinity(irq, desc->affinity);
|
irq_set_thread_affinity(desc, desc->pending_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
cpumask_clear(desc->pending_mask);
|
cpumask_clear(desc->pending_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
|
|
||||||
static void init_copy_kstat_irqs(struct irq_desc *old_desc,
|
static void init_copy_kstat_irqs(struct irq_desc *old_desc,
|
||||||
struct irq_desc *desc,
|
struct irq_desc *desc,
|
||||||
int cpu, int nr)
|
int node, int nr)
|
||||||
{
|
{
|
||||||
init_kstat_irqs(desc, cpu, nr);
|
init_kstat_irqs(desc, node, nr);
|
||||||
|
|
||||||
if (desc->kstat_irqs != old_desc->kstat_irqs)
|
if (desc->kstat_irqs != old_desc->kstat_irqs)
|
||||||
memcpy(desc->kstat_irqs, old_desc->kstat_irqs,
|
memcpy(desc->kstat_irqs, old_desc->kstat_irqs,
|
||||||
|
@ -34,20 +34,20 @@ static void free_kstat_irqs(struct irq_desc *old_desc, struct irq_desc *desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool init_copy_one_irq_desc(int irq, struct irq_desc *old_desc,
|
static bool init_copy_one_irq_desc(int irq, struct irq_desc *old_desc,
|
||||||
struct irq_desc *desc, int cpu)
|
struct irq_desc *desc, int node)
|
||||||
{
|
{
|
||||||
memcpy(desc, old_desc, sizeof(struct irq_desc));
|
memcpy(desc, old_desc, sizeof(struct irq_desc));
|
||||||
if (!init_alloc_desc_masks(desc, cpu, false)) {
|
if (!alloc_desc_masks(desc, node, false)) {
|
||||||
printk(KERN_ERR "irq %d: can not get new irq_desc cpumask "
|
printk(KERN_ERR "irq %d: can not get new irq_desc cpumask "
|
||||||
"for migration.\n", irq);
|
"for migration.\n", irq);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
spin_lock_init(&desc->lock);
|
spin_lock_init(&desc->lock);
|
||||||
desc->cpu = cpu;
|
desc->node = node;
|
||||||
lockdep_set_class(&desc->lock, &irq_desc_lock_class);
|
lockdep_set_class(&desc->lock, &irq_desc_lock_class);
|
||||||
init_copy_kstat_irqs(old_desc, desc, cpu, nr_cpu_ids);
|
init_copy_kstat_irqs(old_desc, desc, node, nr_cpu_ids);
|
||||||
init_copy_desc_masks(old_desc, desc);
|
init_copy_desc_masks(old_desc, desc);
|
||||||
arch_init_copy_chip_data(old_desc, desc, cpu);
|
arch_init_copy_chip_data(old_desc, desc, node);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,12 +59,11 @@ static void free_one_irq_desc(struct irq_desc *old_desc, struct irq_desc *desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
|
static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
|
||||||
int cpu)
|
int node)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc;
|
struct irq_desc *desc;
|
||||||
unsigned int irq;
|
unsigned int irq;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int node;
|
|
||||||
|
|
||||||
irq = old_desc->irq;
|
irq = old_desc->irq;
|
||||||
|
|
||||||
|
@ -76,7 +75,6 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
|
||||||
if (desc && old_desc != desc)
|
if (desc && old_desc != desc)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
node = cpu_to_node(cpu);
|
|
||||||
desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
|
desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
|
||||||
if (!desc) {
|
if (!desc) {
|
||||||
printk(KERN_ERR "irq %d: can not get new irq_desc "
|
printk(KERN_ERR "irq %d: can not get new irq_desc "
|
||||||
|
@ -85,7 +83,7 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
|
||||||
desc = old_desc;
|
desc = old_desc;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
if (!init_copy_one_irq_desc(irq, old_desc, desc, cpu)) {
|
if (!init_copy_one_irq_desc(irq, old_desc, desc, node)) {
|
||||||
/* still use old one */
|
/* still use old one */
|
||||||
kfree(desc);
|
kfree(desc);
|
||||||
desc = old_desc;
|
desc = old_desc;
|
||||||
|
@ -97,9 +95,7 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
|
||||||
|
|
||||||
/* free the old one */
|
/* free the old one */
|
||||||
free_one_irq_desc(old_desc, desc);
|
free_one_irq_desc(old_desc, desc);
|
||||||
spin_unlock(&old_desc->lock);
|
|
||||||
kfree(old_desc);
|
kfree(old_desc);
|
||||||
spin_lock(&desc->lock);
|
|
||||||
|
|
||||||
return desc;
|
return desc;
|
||||||
|
|
||||||
|
@ -109,24 +105,14 @@ out_unlock:
|
||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct irq_desc *move_irq_desc(struct irq_desc *desc, int cpu)
|
struct irq_desc *move_irq_desc(struct irq_desc *desc, int node)
|
||||||
{
|
{
|
||||||
int old_cpu;
|
|
||||||
int node, old_node;
|
|
||||||
|
|
||||||
/* those all static, do move them */
|
/* those all static, do move them */
|
||||||
if (desc->irq < NR_IRQS_LEGACY)
|
if (desc->irq < NR_IRQS_LEGACY)
|
||||||
return desc;
|
return desc;
|
||||||
|
|
||||||
old_cpu = desc->cpu;
|
if (desc->node != node)
|
||||||
if (old_cpu != cpu) {
|
desc = __real_move_irq_desc(desc, node);
|
||||||
node = cpu_to_node(cpu);
|
|
||||||
old_node = cpu_to_node(old_cpu);
|
|
||||||
if (old_node != node)
|
|
||||||
desc = __real_move_irq_desc(desc, cpu);
|
|
||||||
else
|
|
||||||
desc->cpu = cpu;
|
|
||||||
}
|
|
||||||
|
|
||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -828,7 +828,7 @@ int __init __weak arch_early_irq_init(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __weak arch_init_chip_data(struct irq_desc *desc, int cpu)
|
int __weak arch_init_chip_data(struct irq_desc *desc, int node)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue