Merge branch 'genirq-v28-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
This merges branches irq/genirq, irq/sparseirq-v4, timers/hpet-percpu and x86/uv. The sparseirq branch is just preliminary groundwork: no sparse IRQs are actually implemented by this tree anymore - just the new APIs are added while keeping the old way intact as well (the new APIs map 1:1 to irq_desc[]). The 'real' sparse IRQ support will then be a relatively small patch ontop of this - with a v2.6.29 merge target. * 'genirq-v28-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (178 commits) genirq: improve include files intr_remapping: fix typo io_apic: make irq_mis_count available on 64-bit too genirq: fix name space collisions of nr_irqs in arch/* genirq: fix name space collision of nr_irqs in autoprobe.c genirq: use iterators for irq_desc loops proc: fixup irq iterator genirq: add reverse iterator for irq_desc x86: move ack_bad_irq() to irq.c x86: unify show_interrupts() and proc helpers x86: cleanup show_interrupts genirq: cleanup the sparseirq modifications genirq: remove artifacts from sparseirq removal genirq: revert dynarray genirq: remove irq_to_desc_alloc genirq: remove sparse irq code genirq: use inline function for irq_to_desc genirq: consolidate nr_irqs and for_each_irq_desc() x86: remove sparse irq from Kconfig genirq: define nr_irqs for architectures with GENERIC_HARDIRQS=n ...
This commit is contained in:
@@ -47,7 +47,7 @@ typedef struct irq_swizzle_struct
|
|||||||
|
|
||||||
static irq_swizzle_t *sable_lynx_irq_swizzle;
|
static irq_swizzle_t *sable_lynx_irq_swizzle;
|
||||||
|
|
||||||
static void sable_lynx_init_irq(int nr_irqs);
|
static void sable_lynx_init_irq(int nr_of_irqs);
|
||||||
|
|
||||||
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SABLE)
|
#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SABLE)
|
||||||
|
|
||||||
@@ -530,11 +530,11 @@ sable_lynx_srm_device_interrupt(unsigned long vector)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void __init
|
static void __init
|
||||||
sable_lynx_init_irq(int nr_irqs)
|
sable_lynx_init_irq(int nr_of_irqs)
|
||||||
{
|
{
|
||||||
long i;
|
long i;
|
||||||
|
|
||||||
for (i = 0; i < nr_irqs; ++i) {
|
for (i = 0; i < nr_of_irqs; ++i) {
|
||||||
irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
|
irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;
|
||||||
irq_desc[i].chip = &sable_lynx_irq_type;
|
irq_desc[i].chip = &sable_lynx_irq_type;
|
||||||
}
|
}
|
||||||
|
@@ -143,7 +143,7 @@ static struct irq_chip ixdp2x00_cpld_irq_chip = {
|
|||||||
.unmask = ixdp2x00_irq_unmask
|
.unmask = ixdp2x00_irq_unmask
|
||||||
};
|
};
|
||||||
|
|
||||||
void __init ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long *mask_reg, unsigned long nr_irqs)
|
void __init ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigned long *mask_reg, unsigned long nr_of_irqs)
|
||||||
{
|
{
|
||||||
unsigned int irq;
|
unsigned int irq;
|
||||||
|
|
||||||
@@ -154,7 +154,7 @@ void __init ixdp2x00_init_irq(volatile unsigned long *stat_reg, volatile unsigne
|
|||||||
|
|
||||||
board_irq_stat = stat_reg;
|
board_irq_stat = stat_reg;
|
||||||
board_irq_mask = mask_reg;
|
board_irq_mask = mask_reg;
|
||||||
board_irq_count = nr_irqs;
|
board_irq_count = nr_of_irqs;
|
||||||
|
|
||||||
*board_irq_mask = 0xffffffff;
|
*board_irq_mask = 0xffffffff;
|
||||||
|
|
||||||
|
@@ -119,7 +119,7 @@ static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank)
|
|||||||
|
|
||||||
void __init omap_init_irq(void)
|
void __init omap_init_irq(void)
|
||||||
{
|
{
|
||||||
unsigned long nr_irqs = 0;
|
unsigned long nr_of_irqs = 0;
|
||||||
unsigned int nr_banks = 0;
|
unsigned int nr_banks = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -133,14 +133,14 @@ void __init omap_init_irq(void)
|
|||||||
|
|
||||||
omap_irq_bank_init_one(bank);
|
omap_irq_bank_init_one(bank);
|
||||||
|
|
||||||
nr_irqs += bank->nr_irqs;
|
nr_of_irqs += bank->nr_irqs;
|
||||||
nr_banks++;
|
nr_banks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(KERN_INFO "Total of %ld interrupts on %d active controller%s\n",
|
printk(KERN_INFO "Total of %ld interrupts on %d active controller%s\n",
|
||||||
nr_irqs, nr_banks, nr_banks > 1 ? "s" : "");
|
nr_of_irqs, nr_banks, nr_banks > 1 ? "s" : "");
|
||||||
|
|
||||||
for (i = 0; i < nr_irqs; i++) {
|
for (i = 0; i < nr_of_irqs; i++) {
|
||||||
set_irq_chip(i, &omap_irq_chip);
|
set_irq_chip(i, &omap_irq_chip);
|
||||||
set_irq_handler(i, handle_level_irq);
|
set_irq_handler(i, handle_level_irq);
|
||||||
set_irq_flags(i, IRQF_VALID);
|
set_irq_flags(i, IRQF_VALID);
|
||||||
|
@@ -191,7 +191,7 @@ static int __init eic_probe(struct platform_device *pdev)
|
|||||||
struct eic *eic;
|
struct eic *eic;
|
||||||
struct resource *regs;
|
struct resource *regs;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned int nr_irqs;
|
unsigned int nr_of_irqs;
|
||||||
unsigned int int_irq;
|
unsigned int int_irq;
|
||||||
int ret;
|
int ret;
|
||||||
u32 pattern;
|
u32 pattern;
|
||||||
@@ -224,7 +224,7 @@ static int __init eic_probe(struct platform_device *pdev)
|
|||||||
eic_writel(eic, IDR, ~0UL);
|
eic_writel(eic, IDR, ~0UL);
|
||||||
eic_writel(eic, MODE, ~0UL);
|
eic_writel(eic, MODE, ~0UL);
|
||||||
pattern = eic_readl(eic, MODE);
|
pattern = eic_readl(eic, MODE);
|
||||||
nr_irqs = fls(pattern);
|
nr_of_irqs = fls(pattern);
|
||||||
|
|
||||||
/* Trigger on low level unless overridden by driver */
|
/* Trigger on low level unless overridden by driver */
|
||||||
eic_writel(eic, EDGE, 0UL);
|
eic_writel(eic, EDGE, 0UL);
|
||||||
@@ -232,7 +232,7 @@ static int __init eic_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
eic->chip = &eic_chip;
|
eic->chip = &eic_chip;
|
||||||
|
|
||||||
for (i = 0; i < nr_irqs; i++) {
|
for (i = 0; i < nr_of_irqs; i++) {
|
||||||
set_irq_chip_and_handler(eic->first_irq + i, &eic_chip,
|
set_irq_chip_and_handler(eic->first_irq + i, &eic_chip,
|
||||||
handle_level_irq);
|
handle_level_irq);
|
||||||
set_irq_chip_data(eic->first_irq + i, eic);
|
set_irq_chip_data(eic->first_irq + i, eic);
|
||||||
@@ -256,7 +256,7 @@ static int __init eic_probe(struct platform_device *pdev)
|
|||||||
eic->regs, int_irq);
|
eic->regs, int_irq);
|
||||||
dev_info(&pdev->dev,
|
dev_info(&pdev->dev,
|
||||||
"Handling %u external IRQs, starting with IRQ %u\n",
|
"Handling %u external IRQs, starting with IRQ %u\n",
|
||||||
nr_irqs, eic->first_irq);
|
nr_of_irqs, eic->first_irq);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@@ -1242,14 +1242,6 @@ config EFI
|
|||||||
resultant kernel should continue to boot on existing non-EFI
|
resultant kernel should continue to boot on existing non-EFI
|
||||||
platforms.
|
platforms.
|
||||||
|
|
||||||
config IRQBALANCE
|
|
||||||
def_bool y
|
|
||||||
prompt "Enable kernel irq balancing"
|
|
||||||
depends on X86_32 && SMP && X86_IO_APIC
|
|
||||||
help
|
|
||||||
The default yes will allow the kernel to do irq load balancing.
|
|
||||||
Saying no will keep the kernel from doing irq load balancing.
|
|
||||||
|
|
||||||
config SECCOMP
|
config SECCOMP
|
||||||
def_bool y
|
def_bool y
|
||||||
prompt "Enable seccomp to safely compute untrusted bytecode"
|
prompt "Enable seccomp to safely compute untrusted bytecode"
|
||||||
|
@@ -287,7 +287,6 @@ CONFIG_MTRR=y
|
|||||||
# CONFIG_MTRR_SANITIZER is not set
|
# CONFIG_MTRR_SANITIZER is not set
|
||||||
CONFIG_X86_PAT=y
|
CONFIG_X86_PAT=y
|
||||||
CONFIG_EFI=y
|
CONFIG_EFI=y
|
||||||
# CONFIG_IRQBALANCE is not set
|
|
||||||
CONFIG_SECCOMP=y
|
CONFIG_SECCOMP=y
|
||||||
# CONFIG_HZ_100 is not set
|
# CONFIG_HZ_100 is not set
|
||||||
# CONFIG_HZ_250 is not set
|
# CONFIG_HZ_250 is not set
|
||||||
|
@@ -23,7 +23,7 @@ CFLAGS_hpet.o := $(nostackp)
|
|||||||
CFLAGS_tsc.o := $(nostackp)
|
CFLAGS_tsc.o := $(nostackp)
|
||||||
|
|
||||||
obj-y := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o
|
obj-y := process_$(BITS).o signal_$(BITS).o entry_$(BITS).o
|
||||||
obj-y += traps.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
|
obj-y += time_$(BITS).o ioport.o ldt.o
|
||||||
obj-y += setup.o i8259.o irqinit_$(BITS).o setup_percpu.o
|
obj-y += setup.o i8259.o irqinit_$(BITS).o setup_percpu.o
|
||||||
obj-$(CONFIG_X86_VISWS) += visws_quirks.o
|
obj-$(CONFIG_X86_VISWS) += visws_quirks.o
|
||||||
@@ -60,8 +60,8 @@ obj-$(CONFIG_X86_32_SMP) += smpcommon.o
|
|||||||
obj-$(CONFIG_X86_64_SMP) += tsc_sync.o smpcommon.o
|
obj-$(CONFIG_X86_64_SMP) += tsc_sync.o smpcommon.o
|
||||||
obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o
|
obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o
|
||||||
obj-$(CONFIG_X86_MPPARSE) += mpparse.o
|
obj-$(CONFIG_X86_MPPARSE) += mpparse.o
|
||||||
obj-$(CONFIG_X86_LOCAL_APIC) += apic_$(BITS).o nmi.o
|
obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o
|
||||||
obj-$(CONFIG_X86_IO_APIC) += io_apic_$(BITS).o
|
obj-$(CONFIG_X86_IO_APIC) += io_apic.o
|
||||||
obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups_32.o
|
obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups_32.o
|
||||||
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
|
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
|
||||||
obj-$(CONFIG_KEXEC) += machine_kexec_$(BITS).o
|
obj-$(CONFIG_KEXEC) += machine_kexec_$(BITS).o
|
||||||
@@ -108,7 +108,7 @@ obj-$(CONFIG_MICROCODE) += microcode.o
|
|||||||
# 64 bit specific files
|
# 64 bit specific files
|
||||||
ifeq ($(CONFIG_X86_64),y)
|
ifeq ($(CONFIG_X86_64),y)
|
||||||
obj-y += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o
|
obj-y += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o
|
||||||
obj-y += bios_uv.o
|
obj-y += bios_uv.o uv_irq.o uv_sysfs.o
|
||||||
obj-y += genx2apic_cluster.o
|
obj-y += genx2apic_cluster.o
|
||||||
obj-y += genx2apic_phys.o
|
obj-y += genx2apic_phys.o
|
||||||
obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o
|
obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o
|
||||||
|
@@ -1256,7 +1256,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)
|
|||||||
|
|
||||||
count =
|
count =
|
||||||
acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr,
|
acpi_table_parse_madt(ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, acpi_parse_int_src_ovr,
|
||||||
NR_IRQ_VECTORS);
|
nr_irqs);
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
printk(KERN_ERR PREFIX
|
printk(KERN_ERR PREFIX
|
||||||
"Error parsing interrupt source overrides entry\n");
|
"Error parsing interrupt source overrides entry\n");
|
||||||
@@ -1276,7 +1276,7 @@ static int __init acpi_parse_madt_ioapic_entries(void)
|
|||||||
|
|
||||||
count =
|
count =
|
||||||
acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src,
|
acpi_table_parse_madt(ACPI_MADT_TYPE_NMI_SOURCE, acpi_parse_nmi_src,
|
||||||
NR_IRQ_VECTORS);
|
nr_irqs);
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
|
printk(KERN_ERR PREFIX "Error parsing NMI SRC entry\n");
|
||||||
/* TBD: Cleanup to allow fallback to MPS */
|
/* TBD: Cleanup to allow fallback to MPS */
|
||||||
|
@@ -23,11 +23,13 @@
|
|||||||
#include <linux/mc146818rtc.h>
|
#include <linux/mc146818rtc.h>
|
||||||
#include <linux/kernel_stat.h>
|
#include <linux/kernel_stat.h>
|
||||||
#include <linux/sysdev.h>
|
#include <linux/sysdev.h>
|
||||||
|
#include <linux/ioport.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
#include <linux/clockchips.h>
|
#include <linux/clockchips.h>
|
||||||
#include <linux/acpi_pmtmr.h>
|
#include <linux/acpi_pmtmr.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/dmi.h>
|
#include <linux/dmi.h>
|
||||||
|
#include <linux/dmar.h>
|
||||||
|
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
@@ -36,8 +38,14 @@
|
|||||||
#include <asm/desc.h>
|
#include <asm/desc.h>
|
||||||
#include <asm/arch_hooks.h>
|
#include <asm/arch_hooks.h>
|
||||||
#include <asm/hpet.h>
|
#include <asm/hpet.h>
|
||||||
|
#include <asm/pgalloc.h>
|
||||||
#include <asm/i8253.h>
|
#include <asm/i8253.h>
|
||||||
#include <asm/nmi.h>
|
#include <asm/nmi.h>
|
||||||
|
#include <asm/idle.h>
|
||||||
|
#include <asm/proto.h>
|
||||||
|
#include <asm/timex.h>
|
||||||
|
#include <asm/apic.h>
|
||||||
|
#include <asm/i8259.h>
|
||||||
|
|
||||||
#include <mach_apic.h>
|
#include <mach_apic.h>
|
||||||
#include <mach_apicdef.h>
|
#include <mach_apicdef.h>
|
||||||
@@ -50,16 +58,58 @@
|
|||||||
# error SPURIOUS_APIC_VECTOR definition error
|
# error SPURIOUS_APIC_VECTOR definition error
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned long mp_lapic_addr;
|
#ifdef CONFIG_X86_32
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Knob to control our willingness to enable the local APIC.
|
* Knob to control our willingness to enable the local APIC.
|
||||||
*
|
*
|
||||||
* +1=force-enable
|
* +1=force-enable
|
||||||
*/
|
*/
|
||||||
static int force_enable_local_apic;
|
static int force_enable_local_apic;
|
||||||
int disable_apic;
|
/*
|
||||||
|
* APIC command line parameters
|
||||||
|
*/
|
||||||
|
static int __init parse_lapic(char *arg)
|
||||||
|
{
|
||||||
|
force_enable_local_apic = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
early_param("lapic", parse_lapic);
|
||||||
|
/* Local APIC was disabled by the BIOS and enabled by the kernel */
|
||||||
|
static int enabled_via_apicbase;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
static int apic_calibrate_pmtmr __initdata;
|
||||||
|
static __init int setup_apicpmtimer(char *s)
|
||||||
|
{
|
||||||
|
apic_calibrate_pmtmr = 1;
|
||||||
|
notsc_setup(NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
__setup("apicpmtimer", setup_apicpmtimer);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
#define HAVE_X2APIC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_X2APIC
|
||||||
|
int x2apic;
|
||||||
|
/* x2apic enabled before OS handover */
|
||||||
|
int x2apic_preenabled;
|
||||||
|
int disable_x2apic;
|
||||||
|
static __init int setup_nox2apic(char *str)
|
||||||
|
{
|
||||||
|
disable_x2apic = 1;
|
||||||
|
setup_clear_cpu_cap(X86_FEATURE_X2APIC);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
early_param("nox2apic", setup_nox2apic);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned long mp_lapic_addr;
|
||||||
|
int disable_apic;
|
||||||
/* Disable local APIC timer from the kernel commandline or via dmi quirk */
|
/* Disable local APIC timer from the kernel commandline or via dmi quirk */
|
||||||
static int disable_apic_timer __cpuinitdata;
|
static int disable_apic_timer __cpuinitdata;
|
||||||
/* Local APIC timer works in C2 */
|
/* Local APIC timer works in C2 */
|
||||||
@@ -110,9 +160,6 @@ static struct clock_event_device lapic_clockevent = {
|
|||||||
};
|
};
|
||||||
static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
|
static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
|
||||||
|
|
||||||
/* Local APIC was disabled by the BIOS and enabled by the kernel */
|
|
||||||
static int enabled_via_apicbase;
|
|
||||||
|
|
||||||
static unsigned long apic_phys;
|
static unsigned long apic_phys;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -202,6 +249,42 @@ static struct apic_ops xapic_ops = {
|
|||||||
struct apic_ops __read_mostly *apic_ops = &xapic_ops;
|
struct apic_ops __read_mostly *apic_ops = &xapic_ops;
|
||||||
EXPORT_SYMBOL_GPL(apic_ops);
|
EXPORT_SYMBOL_GPL(apic_ops);
|
||||||
|
|
||||||
|
#ifdef HAVE_X2APIC
|
||||||
|
static void x2apic_wait_icr_idle(void)
|
||||||
|
{
|
||||||
|
/* no need to wait for icr idle in x2apic */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 safe_x2apic_wait_icr_idle(void)
|
||||||
|
{
|
||||||
|
/* no need to wait for icr idle in x2apic */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void x2apic_icr_write(u32 low, u32 id)
|
||||||
|
{
|
||||||
|
wrmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), ((__u64) id) << 32 | low);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 x2apic_icr_read(void)
|
||||||
|
{
|
||||||
|
unsigned long val;
|
||||||
|
|
||||||
|
rdmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), val);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct apic_ops x2apic_ops = {
|
||||||
|
.read = native_apic_msr_read,
|
||||||
|
.write = native_apic_msr_write,
|
||||||
|
.icr_read = x2apic_icr_read,
|
||||||
|
.icr_write = x2apic_icr_write,
|
||||||
|
.wait_icr_idle = x2apic_wait_icr_idle,
|
||||||
|
.safe_wait_icr_idle = safe_x2apic_wait_icr_idle,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enable_NMI_through_LVT0 - enable NMI through local vector table 0
|
* enable_NMI_through_LVT0 - enable NMI through local vector table 0
|
||||||
*/
|
*/
|
||||||
@@ -219,6 +302,7 @@ void __cpuinit enable_NMI_through_LVT0(void)
|
|||||||
apic_write(APIC_LVT0, v);
|
apic_write(APIC_LVT0, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
/**
|
/**
|
||||||
* get_physical_broadcast - Get number of physical broadcast IDs
|
* get_physical_broadcast - Get number of physical broadcast IDs
|
||||||
*/
|
*/
|
||||||
@@ -226,6 +310,7 @@ int get_physical_broadcast(void)
|
|||||||
{
|
{
|
||||||
return modern_apic() ? 0xff : 0xf;
|
return modern_apic() ? 0xff : 0xf;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lapic_get_maxlvt - get the maximum number of local vector table entries
|
* lapic_get_maxlvt - get the maximum number of local vector table entries
|
||||||
@@ -247,11 +332,7 @@ int lapic_get_maxlvt(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Clock divisor */
|
/* Clock divisor */
|
||||||
#ifdef CONFG_X86_64
|
|
||||||
#define APIC_DIVISOR 1
|
|
||||||
#else
|
|
||||||
#define APIC_DIVISOR 16
|
#define APIC_DIVISOR 16
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function sets up the local APIC timer, with a timeout of
|
* This function sets up the local APIC timer, with a timeout of
|
||||||
@@ -383,7 +464,7 @@ static void lapic_timer_broadcast(cpumask_t mask)
|
|||||||
* Setup the local APIC timer for this CPU. Copy the initilized values
|
* Setup the local APIC timer for this CPU. Copy the initilized values
|
||||||
* of the boot CPU and register the clock event in the framework.
|
* of the boot CPU and register the clock event in the framework.
|
||||||
*/
|
*/
|
||||||
static void __devinit setup_APIC_timer(void)
|
static void __cpuinit setup_APIC_timer(void)
|
||||||
{
|
{
|
||||||
struct clock_event_device *levt = &__get_cpu_var(lapic_events);
|
struct clock_event_device *levt = &__get_cpu_var(lapic_events);
|
||||||
|
|
||||||
@@ -453,14 +534,51 @@ static void __init lapic_cal_handler(struct clock_event_device *dev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __init calibrate_by_pmtimer(long deltapm, long *delta)
|
||||||
|
{
|
||||||
|
const long pm_100ms = PMTMR_TICKS_PER_SEC / 10;
|
||||||
|
const long pm_thresh = pm_100ms / 100;
|
||||||
|
unsigned long mult;
|
||||||
|
u64 res;
|
||||||
|
|
||||||
|
#ifndef CONFIG_X86_PM_TIMER
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
apic_printk(APIC_VERBOSE, "... PM timer delta = %ld\n", deltapm);
|
||||||
|
|
||||||
|
/* Check, if the PM timer is available */
|
||||||
|
if (!deltapm)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mult = clocksource_hz2mult(PMTMR_TICKS_PER_SEC, 22);
|
||||||
|
|
||||||
|
if (deltapm > (pm_100ms - pm_thresh) &&
|
||||||
|
deltapm < (pm_100ms + pm_thresh)) {
|
||||||
|
apic_printk(APIC_VERBOSE, "... PM timer result ok\n");
|
||||||
|
} else {
|
||||||
|
res = (((u64)deltapm) * mult) >> 22;
|
||||||
|
do_div(res, 1000000);
|
||||||
|
printk(KERN_WARNING "APIC calibration not consistent "
|
||||||
|
"with PM Timer: %ldms instead of 100ms\n",
|
||||||
|
(long)res);
|
||||||
|
/* Correct the lapic counter value */
|
||||||
|
res = (((u64)(*delta)) * pm_100ms);
|
||||||
|
do_div(res, deltapm);
|
||||||
|
printk(KERN_INFO "APIC delta adjusted to PM-Timer: "
|
||||||
|
"%lu (%ld)\n", (unsigned long)res, *delta);
|
||||||
|
*delta = (long)res;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int __init calibrate_APIC_clock(void)
|
static int __init calibrate_APIC_clock(void)
|
||||||
{
|
{
|
||||||
struct clock_event_device *levt = &__get_cpu_var(lapic_events);
|
struct clock_event_device *levt = &__get_cpu_var(lapic_events);
|
||||||
const long pm_100ms = PMTMR_TICKS_PER_SEC/10;
|
|
||||||
const long pm_thresh = pm_100ms/100;
|
|
||||||
void (*real_handler)(struct clock_event_device *dev);
|
void (*real_handler)(struct clock_event_device *dev);
|
||||||
unsigned long deltaj;
|
unsigned long deltaj;
|
||||||
long delta, deltapm;
|
long delta;
|
||||||
int pm_referenced = 0;
|
int pm_referenced = 0;
|
||||||
|
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
@@ -470,10 +588,10 @@ static int __init calibrate_APIC_clock(void)
|
|||||||
global_clock_event->event_handler = lapic_cal_handler;
|
global_clock_event->event_handler = lapic_cal_handler;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Setup the APIC counter to 1e9. There is no way the lapic
|
* Setup the APIC counter to maximum. There is no way the lapic
|
||||||
* can underflow in the 100ms detection time frame
|
* can underflow in the 100ms detection time frame
|
||||||
*/
|
*/
|
||||||
__setup_APIC_LVTT(1000000000, 0, 0);
|
__setup_APIC_LVTT(0xffffffff, 0, 0);
|
||||||
|
|
||||||
/* Let the interrupts run */
|
/* Let the interrupts run */
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
@@ -490,34 +608,9 @@ static int __init calibrate_APIC_clock(void)
|
|||||||
delta = lapic_cal_t1 - lapic_cal_t2;
|
delta = lapic_cal_t1 - lapic_cal_t2;
|
||||||
apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta);
|
apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta);
|
||||||
|
|
||||||
/* Check, if the PM timer is available */
|
/* we trust the PM based calibration if possible */
|
||||||
deltapm = lapic_cal_pm2 - lapic_cal_pm1;
|
pm_referenced = !calibrate_by_pmtimer(lapic_cal_pm2 - lapic_cal_pm1,
|
||||||
apic_printk(APIC_VERBOSE, "... PM timer delta = %ld\n", deltapm);
|
&delta);
|
||||||
|
|
||||||
if (deltapm) {
|
|
||||||
unsigned long mult;
|
|
||||||
u64 res;
|
|
||||||
|
|
||||||
mult = clocksource_hz2mult(PMTMR_TICKS_PER_SEC, 22);
|
|
||||||
|
|
||||||
if (deltapm > (pm_100ms - pm_thresh) &&
|
|
||||||
deltapm < (pm_100ms + pm_thresh)) {
|
|
||||||
apic_printk(APIC_VERBOSE, "... PM timer result ok\n");
|
|
||||||
} else {
|
|
||||||
res = (((u64) deltapm) * mult) >> 22;
|
|
||||||
do_div(res, 1000000);
|
|
||||||
printk(KERN_WARNING "APIC calibration not consistent "
|
|
||||||
"with PM Timer: %ldms instead of 100ms\n",
|
|
||||||
(long)res);
|
|
||||||
/* Correct the lapic counter value */
|
|
||||||
res = (((u64) delta) * pm_100ms);
|
|
||||||
do_div(res, deltapm);
|
|
||||||
printk(KERN_INFO "APIC delta adjusted to PM-Timer: "
|
|
||||||
"%lu (%ld)\n", (unsigned long) res, delta);
|
|
||||||
delta = (long) res;
|
|
||||||
}
|
|
||||||
pm_referenced = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate the scaled math multiplication factor */
|
/* Calculate the scaled math multiplication factor */
|
||||||
lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS,
|
lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS,
|
||||||
@@ -559,7 +652,10 @@ static int __init calibrate_APIC_clock(void)
|
|||||||
|
|
||||||
levt->features &= ~CLOCK_EVT_FEAT_DUMMY;
|
levt->features &= ~CLOCK_EVT_FEAT_DUMMY;
|
||||||
|
|
||||||
/* We trust the pm timer based calibration */
|
/*
|
||||||
|
* PM timer calibration failed or not turned on
|
||||||
|
* so lets try APIC timer based calibration
|
||||||
|
*/
|
||||||
if (!pm_referenced) {
|
if (!pm_referenced) {
|
||||||
apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
|
apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
|
||||||
|
|
||||||
@@ -652,7 +748,7 @@ void __init setup_boot_APIC_clock(void)
|
|||||||
setup_APIC_timer();
|
setup_APIC_timer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __devinit setup_secondary_APIC_clock(void)
|
void __cpuinit setup_secondary_APIC_clock(void)
|
||||||
{
|
{
|
||||||
setup_APIC_timer();
|
setup_APIC_timer();
|
||||||
}
|
}
|
||||||
@@ -718,6 +814,9 @@ void smp_apic_timer_interrupt(struct pt_regs *regs)
|
|||||||
* Besides, if we don't timer interrupts ignore the global
|
* Besides, if we don't timer interrupts ignore the global
|
||||||
* interrupt lock, which is the WrongThing (tm) to do.
|
* interrupt lock, which is the WrongThing (tm) to do.
|
||||||
*/
|
*/
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
exit_idle();
|
||||||
|
#endif
|
||||||
irq_enter();
|
irq_enter();
|
||||||
local_apic_timer_interrupt();
|
local_apic_timer_interrupt();
|
||||||
irq_exit();
|
irq_exit();
|
||||||
@@ -991,40 +1090,43 @@ void __init init_bsp_APIC(void)
|
|||||||
|
|
||||||
static void __cpuinit lapic_setup_esr(void)
|
static void __cpuinit lapic_setup_esr(void)
|
||||||
{
|
{
|
||||||
unsigned long oldvalue, value, maxlvt;
|
unsigned int oldvalue, value, maxlvt;
|
||||||
if (lapic_is_integrated() && !esr_disable) {
|
|
||||||
if (esr_disable) {
|
|
||||||
/*
|
|
||||||
* Something untraceable is creating bad interrupts on
|
|
||||||
* secondary quads ... for the moment, just leave the
|
|
||||||
* ESR disabled - we can't do anything useful with the
|
|
||||||
* errors anyway - mbligh
|
|
||||||
*/
|
|
||||||
printk(KERN_INFO "Leaving ESR disabled.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* !82489DX */
|
|
||||||
maxlvt = lapic_get_maxlvt();
|
|
||||||
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
|
|
||||||
apic_write(APIC_ESR, 0);
|
|
||||||
oldvalue = apic_read(APIC_ESR);
|
|
||||||
|
|
||||||
/* enables sending errors */
|
if (!lapic_is_integrated()) {
|
||||||
value = ERROR_APIC_VECTOR;
|
|
||||||
apic_write(APIC_LVTERR, value);
|
|
||||||
/*
|
|
||||||
* spec says clear errors after enabling vector.
|
|
||||||
*/
|
|
||||||
if (maxlvt > 3)
|
|
||||||
apic_write(APIC_ESR, 0);
|
|
||||||
value = apic_read(APIC_ESR);
|
|
||||||
if (value != oldvalue)
|
|
||||||
apic_printk(APIC_VERBOSE, "ESR value before enabling "
|
|
||||||
"vector: 0x%08lx after: 0x%08lx\n",
|
|
||||||
oldvalue, value);
|
|
||||||
} else {
|
|
||||||
printk(KERN_INFO "No ESR for 82489DX.\n");
|
printk(KERN_INFO "No ESR for 82489DX.\n");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (esr_disable) {
|
||||||
|
/*
|
||||||
|
* Something untraceable is creating bad interrupts on
|
||||||
|
* secondary quads ... for the moment, just leave the
|
||||||
|
* ESR disabled - we can't do anything useful with the
|
||||||
|
* errors anyway - mbligh
|
||||||
|
*/
|
||||||
|
printk(KERN_INFO "Leaving ESR disabled.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
maxlvt = lapic_get_maxlvt();
|
||||||
|
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
|
||||||
|
apic_write(APIC_ESR, 0);
|
||||||
|
oldvalue = apic_read(APIC_ESR);
|
||||||
|
|
||||||
|
/* enables sending errors */
|
||||||
|
value = ERROR_APIC_VECTOR;
|
||||||
|
apic_write(APIC_LVTERR, value);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* spec says clear errors after enabling vector.
|
||||||
|
*/
|
||||||
|
if (maxlvt > 3)
|
||||||
|
apic_write(APIC_ESR, 0);
|
||||||
|
value = apic_read(APIC_ESR);
|
||||||
|
if (value != oldvalue)
|
||||||
|
apic_printk(APIC_VERBOSE, "ESR value before enabling "
|
||||||
|
"vector: 0x%08x after: 0x%08x\n",
|
||||||
|
oldvalue, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1033,24 +1135,27 @@ static void __cpuinit lapic_setup_esr(void)
|
|||||||
*/
|
*/
|
||||||
void __cpuinit setup_local_APIC(void)
|
void __cpuinit setup_local_APIC(void)
|
||||||
{
|
{
|
||||||
unsigned long value, integrated;
|
unsigned int value;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
/* Pound the ESR really hard over the head with a big hammer - mbligh */
|
/* Pound the ESR really hard over the head with a big hammer - mbligh */
|
||||||
if (esr_disable) {
|
if (lapic_is_integrated() && esr_disable) {
|
||||||
apic_write(APIC_ESR, 0);
|
apic_write(APIC_ESR, 0);
|
||||||
apic_write(APIC_ESR, 0);
|
apic_write(APIC_ESR, 0);
|
||||||
apic_write(APIC_ESR, 0);
|
apic_write(APIC_ESR, 0);
|
||||||
apic_write(APIC_ESR, 0);
|
apic_write(APIC_ESR, 0);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
integrated = lapic_is_integrated();
|
preempt_disable();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Double-check whether this APIC is really registered.
|
* Double-check whether this APIC is really registered.
|
||||||
|
* This is meaningless in clustered apic mode, so we skip it.
|
||||||
*/
|
*/
|
||||||
if (!apic_id_registered())
|
if (!apic_id_registered())
|
||||||
WARN_ON_ONCE(1);
|
BUG();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Intel recommends to set DFR, LDR and TPR before enabling
|
* Intel recommends to set DFR, LDR and TPR before enabling
|
||||||
@@ -1096,6 +1201,7 @@ void __cpuinit setup_local_APIC(void)
|
|||||||
*/
|
*/
|
||||||
value |= APIC_SPIV_APIC_ENABLED;
|
value |= APIC_SPIV_APIC_ENABLED;
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
/*
|
/*
|
||||||
* Some unknown Intel IO/APIC (or APIC) errata is biting us with
|
* Some unknown Intel IO/APIC (or APIC) errata is biting us with
|
||||||
* certain networking cards. If high frequency interrupts are
|
* certain networking cards. If high frequency interrupts are
|
||||||
@@ -1116,8 +1222,13 @@ void __cpuinit setup_local_APIC(void)
|
|||||||
* See also the comment in end_level_ioapic_irq(). --macro
|
* See also the comment in end_level_ioapic_irq(). --macro
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Enable focus processor (bit==0) */
|
/*
|
||||||
|
* - enable focus processor (bit==0)
|
||||||
|
* - 64bit mode always use processor focus
|
||||||
|
* so no need to set it
|
||||||
|
*/
|
||||||
value &= ~APIC_SPIV_FOCUS_DISABLED;
|
value &= ~APIC_SPIV_FOCUS_DISABLED;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set spurious IRQ vector
|
* Set spurious IRQ vector
|
||||||
@@ -1154,9 +1265,11 @@ void __cpuinit setup_local_APIC(void)
|
|||||||
value = APIC_DM_NMI;
|
value = APIC_DM_NMI;
|
||||||
else
|
else
|
||||||
value = APIC_DM_NMI | APIC_LVT_MASKED;
|
value = APIC_DM_NMI | APIC_LVT_MASKED;
|
||||||
if (!integrated) /* 82489DX */
|
if (!lapic_is_integrated()) /* 82489DX */
|
||||||
value |= APIC_LVT_LEVEL_TRIGGER;
|
value |= APIC_LVT_LEVEL_TRIGGER;
|
||||||
apic_write(APIC_LVT1, value);
|
apic_write(APIC_LVT1, value);
|
||||||
|
|
||||||
|
preempt_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __cpuinit end_local_APIC_setup(void)
|
void __cpuinit end_local_APIC_setup(void)
|
||||||
@@ -1177,6 +1290,153 @@ void __cpuinit end_local_APIC_setup(void)
|
|||||||
apic_pm_activate();
|
apic_pm_activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_X2APIC
|
||||||
|
void check_x2apic(void)
|
||||||
|
{
|
||||||
|
int msr, msr2;
|
||||||
|
|
||||||
|
rdmsr(MSR_IA32_APICBASE, msr, msr2);
|
||||||
|
|
||||||
|
if (msr & X2APIC_ENABLE) {
|
||||||
|
printk("x2apic enabled by BIOS, switching to x2apic ops\n");
|
||||||
|
x2apic_preenabled = x2apic = 1;
|
||||||
|
apic_ops = &x2apic_ops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable_x2apic(void)
|
||||||
|
{
|
||||||
|
int msr, msr2;
|
||||||
|
|
||||||
|
rdmsr(MSR_IA32_APICBASE, msr, msr2);
|
||||||
|
if (!(msr & X2APIC_ENABLE)) {
|
||||||
|
printk("Enabling x2apic\n");
|
||||||
|
wrmsr(MSR_IA32_APICBASE, msr | X2APIC_ENABLE, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void enable_IR_x2apic(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_INTR_REMAP
|
||||||
|
int ret;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (!cpu_has_x2apic)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!x2apic_preenabled && disable_x2apic) {
|
||||||
|
printk(KERN_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) {
|
||||||
|
printk(KERN_INFO
|
||||||
|
"Skipped enabling x2apic and Interrupt-remapping "
|
||||||
|
"because of skipping io-apic setup\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = dmar_table_init();
|
||||||
|
if (ret) {
|
||||||
|
printk(KERN_INFO
|
||||||
|
"dmar_table_init() failed with %d:\n", ret);
|
||||||
|
|
||||||
|
if (x2apic_preenabled)
|
||||||
|
panic("x2apic enabled by bios. But IR enabling failed");
|
||||||
|
else
|
||||||
|
printk(KERN_INFO
|
||||||
|
"Not enabling x2apic,Intr-remapping\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
local_irq_save(flags);
|
||||||
|
mask_8259A();
|
||||||
|
|
||||||
|
ret = save_mask_IO_APIC_setup();
|
||||||
|
if (ret) {
|
||||||
|
printk(KERN_INFO "Saving IO-APIC state failed: %d\n", ret);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = enable_intr_remapping(1);
|
||||||
|
|
||||||
|
if (ret && x2apic_preenabled) {
|
||||||
|
local_irq_restore(flags);
|
||||||
|
panic("x2apic enabled by bios. But IR enabling failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
goto end_restore;
|
||||||
|
|
||||||
|
if (!x2apic) {
|
||||||
|
x2apic = 1;
|
||||||
|
apic_ops = &x2apic_ops;
|
||||||
|
enable_x2apic();
|
||||||
|
}
|
||||||
|
|
||||||
|
end_restore:
|
||||||
|
if (ret)
|
||||||
|
/*
|
||||||
|
* IR enabling failed
|
||||||
|
*/
|
||||||
|
restore_IO_APIC_setup();
|
||||||
|
else
|
||||||
|
reinit_intr_remapped_IO_APIC(x2apic_preenabled);
|
||||||
|
|
||||||
|
end:
|
||||||
|
unmask_8259A();
|
||||||
|
local_irq_restore(flags);
|
||||||
|
|
||||||
|
if (!ret) {
|
||||||
|
if (!x2apic_preenabled)
|
||||||
|
printk(KERN_INFO
|
||||||
|
"Enabled x2apic and interrupt-remapping\n");
|
||||||
|
else
|
||||||
|
printk(KERN_INFO
|
||||||
|
"Enabled Interrupt-remapping\n");
|
||||||
|
} else
|
||||||
|
printk(KERN_ERR
|
||||||
|
"Failed to enable Interrupt-remapping and x2apic\n");
|
||||||
|
#else
|
||||||
|
if (!cpu_has_x2apic)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (x2apic_preenabled)
|
||||||
|
panic("x2apic enabled prior OS handover,"
|
||||||
|
" enable CONFIG_INTR_REMAP");
|
||||||
|
|
||||||
|
printk(KERN_INFO "Enable CONFIG_INTR_REMAP for enabling intr-remapping "
|
||||||
|
" and x2apic\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_X2APIC */
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
/*
|
||||||
|
* Detect and enable local APICs on non-SMP boards.
|
||||||
|
* Original code written by Keir Fraser.
|
||||||
|
* On AMD64 we trust the BIOS - if it says no APIC it is likely
|
||||||
|
* not correctly set up (usually the APIC timer won't work etc.)
|
||||||
|
*/
|
||||||
|
static int __init detect_init_APIC(void)
|
||||||
|
{
|
||||||
|
if (!cpu_has_apic) {
|
||||||
|
printk(KERN_INFO "No local APIC present\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
|
||||||
|
boot_cpu_physical_apicid = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
/*
|
/*
|
||||||
* Detect and initialize APIC
|
* Detect and initialize APIC
|
||||||
*/
|
*/
|
||||||
@@ -1255,12 +1515,46 @@ no_apic:
|
|||||||
printk(KERN_INFO "No local APIC present or hardware disabled\n");
|
printk(KERN_INFO "No local APIC present or hardware disabled\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
void __init early_init_lapic_mapping(void)
|
||||||
|
{
|
||||||
|
unsigned long phys_addr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no local APIC can be found then go out
|
||||||
|
* : it means there is no mpatable and MADT
|
||||||
|
*/
|
||||||
|
if (!smp_found_config)
|
||||||
|
return;
|
||||||
|
|
||||||
|
phys_addr = mp_lapic_addr;
|
||||||
|
|
||||||
|
set_fixmap_nocache(FIX_APIC_BASE, phys_addr);
|
||||||
|
apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
|
||||||
|
APIC_BASE, phys_addr);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fetch the APIC ID of the BSP in case we have a
|
||||||
|
* default configuration (or the MP table is broken).
|
||||||
|
*/
|
||||||
|
boot_cpu_physical_apicid = read_apic_id();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* init_apic_mappings - initialize APIC mappings
|
* init_apic_mappings - initialize APIC mappings
|
||||||
*/
|
*/
|
||||||
void __init init_apic_mappings(void)
|
void __init init_apic_mappings(void)
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_X2APIC
|
||||||
|
if (x2apic) {
|
||||||
|
boot_cpu_physical_apicid = read_apic_id();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If no local APIC can be found then set up a fake all
|
* If no local APIC can be found then set up a fake all
|
||||||
* zeroes page to simulate the local APIC and another
|
* zeroes page to simulate the local APIC and another
|
||||||
@@ -1273,8 +1567,8 @@ void __init init_apic_mappings(void)
|
|||||||
apic_phys = mp_lapic_addr;
|
apic_phys = mp_lapic_addr;
|
||||||
|
|
||||||
set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
|
set_fixmap_nocache(FIX_APIC_BASE, apic_phys);
|
||||||
printk(KERN_DEBUG "mapped APIC to %08lx (%08lx)\n", APIC_BASE,
|
apic_printk(APIC_VERBOSE, "mapped APIC to %08lx (%08lx)\n",
|
||||||
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
|
||||||
@@ -1282,18 +1576,27 @@ void __init init_apic_mappings(void)
|
|||||||
*/
|
*/
|
||||||
if (boot_cpu_physical_apicid == -1U)
|
if (boot_cpu_physical_apicid == -1U)
|
||||||
boot_cpu_physical_apicid = read_apic_id();
|
boot_cpu_physical_apicid = read_apic_id();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This initializes the IO-APIC and APIC hardware if this is
|
* This initializes the IO-APIC and APIC hardware if this is
|
||||||
* a UP kernel.
|
* a UP kernel.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int apic_version[MAX_APICS];
|
int apic_version[MAX_APICS];
|
||||||
|
|
||||||
int __init APIC_init_uniprocessor(void)
|
int __init APIC_init_uniprocessor(void)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
if (disable_apic) {
|
||||||
|
printk(KERN_INFO "Apic disabled\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!cpu_has_apic) {
|
||||||
|
disable_apic = 1;
|
||||||
|
printk(KERN_INFO "Apic disabled by BIOS\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (!smp_found_config && !cpu_has_apic)
|
if (!smp_found_config && !cpu_has_apic)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -1302,39 +1605,68 @@ int __init APIC_init_uniprocessor(void)
|
|||||||
*/
|
*/
|
||||||
if (!cpu_has_apic &&
|
if (!cpu_has_apic &&
|
||||||
APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
|
APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
|
||||||
printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n",
|
printk(KERN_ERR "BIOS bug, local APIC 0x%x not detected!...\n",
|
||||||
boot_cpu_physical_apicid);
|
boot_cpu_physical_apicid);
|
||||||
clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
|
clear_cpu_cap(&boot_cpu_data, X86_FEATURE_APIC);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_X2APIC
|
||||||
|
enable_IR_x2apic();
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
setup_apic_routing();
|
||||||
|
#endif
|
||||||
|
|
||||||
verify_local_APIC();
|
verify_local_APIC();
|
||||||
|
|
||||||
connect_bsp_APIC();
|
connect_bsp_APIC();
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
apic_write(APIC_ID, SET_APIC_ID(boot_cpu_physical_apicid));
|
||||||
|
#else
|
||||||
/*
|
/*
|
||||||
* Hack: In case of kdump, after a crash, kernel might be booting
|
* Hack: In case of kdump, after a crash, kernel might be booting
|
||||||
* on a cpu with non-zero lapic id. But boot_cpu_physical_apicid
|
* on a cpu with non-zero lapic id. But boot_cpu_physical_apicid
|
||||||
* might be zero if read from MP tables. Get it from LAPIC.
|
* might be zero if read from MP tables. Get it from LAPIC.
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_CRASH_DUMP
|
# ifdef CONFIG_CRASH_DUMP
|
||||||
boot_cpu_physical_apicid = read_apic_id();
|
boot_cpu_physical_apicid = read_apic_id();
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map);
|
physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map);
|
||||||
|
|
||||||
setup_local_APIC();
|
setup_local_APIC();
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
/*
|
||||||
|
* Now enable IO-APICs, actually call clear_IO_APIC
|
||||||
|
* We need clear_IO_APIC before enabling vector on BP
|
||||||
|
*/
|
||||||
|
if (!skip_ioapic_setup && nr_ioapics)
|
||||||
|
enable_IO_APIC();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
#ifdef CONFIG_X86_IO_APIC
|
||||||
if (!smp_found_config || skip_ioapic_setup || !nr_ioapics)
|
if (!smp_found_config || skip_ioapic_setup || !nr_ioapics)
|
||||||
#endif
|
#endif
|
||||||
localise_nmi_watchdog();
|
localise_nmi_watchdog();
|
||||||
end_local_APIC_setup();
|
end_local_APIC_setup();
|
||||||
|
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
#ifdef CONFIG_X86_IO_APIC
|
||||||
if (smp_found_config)
|
if (smp_found_config && !skip_ioapic_setup && nr_ioapics)
|
||||||
if (!skip_ioapic_setup && nr_ioapics)
|
setup_IO_APIC();
|
||||||
setup_IO_APIC();
|
# ifdef CONFIG_X86_64
|
||||||
|
else
|
||||||
|
nr_ioapics = 0;
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
setup_boot_APIC_clock();
|
||||||
|
check_nmi_watchdog();
|
||||||
|
#else
|
||||||
setup_boot_clock();
|
setup_boot_clock();
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1348,8 +1680,11 @@ int __init APIC_init_uniprocessor(void)
|
|||||||
*/
|
*/
|
||||||
void smp_spurious_interrupt(struct pt_regs *regs)
|
void smp_spurious_interrupt(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
unsigned long v;
|
u32 v;
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
exit_idle();
|
||||||
|
#endif
|
||||||
irq_enter();
|
irq_enter();
|
||||||
/*
|
/*
|
||||||
* Check if this really is a spurious interrupt and ACK it
|
* Check if this really is a spurious interrupt and ACK it
|
||||||
@@ -1360,10 +1695,14 @@ void smp_spurious_interrupt(struct pt_regs *regs)
|
|||||||
if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
|
if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
|
||||||
ack_APIC_irq();
|
ack_APIC_irq();
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
add_pda(irq_spurious_count, 1);
|
||||||
|
#else
|
||||||
/* see sw-dev-man vol 3, chapter 7.4.13.5 */
|
/* see sw-dev-man vol 3, chapter 7.4.13.5 */
|
||||||
printk(KERN_INFO "spurious APIC interrupt on CPU#%d, "
|
printk(KERN_INFO "spurious APIC interrupt on CPU#%d, "
|
||||||
"should never happen.\n", smp_processor_id());
|
"should never happen.\n", smp_processor_id());
|
||||||
__get_cpu_var(irq_stat).irq_spurious_count++;
|
__get_cpu_var(irq_stat).irq_spurious_count++;
|
||||||
|
#endif
|
||||||
irq_exit();
|
irq_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1372,8 +1711,11 @@ void smp_spurious_interrupt(struct pt_regs *regs)
|
|||||||
*/
|
*/
|
||||||
void smp_error_interrupt(struct pt_regs *regs)
|
void smp_error_interrupt(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
unsigned long v, v1;
|
u32 v, v1;
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
exit_idle();
|
||||||
|
#endif
|
||||||
irq_enter();
|
irq_enter();
|
||||||
/* First tickle the hardware, only then report what went on. -- REW */
|
/* First tickle the hardware, only then report what went on. -- REW */
|
||||||
v = apic_read(APIC_ESR);
|
v = apic_read(APIC_ESR);
|
||||||
@@ -1392,7 +1734,7 @@ void smp_error_interrupt(struct pt_regs *regs)
|
|||||||
6: Received illegal vector
|
6: Received illegal vector
|
||||||
7: Illegal register address
|
7: Illegal register address
|
||||||
*/
|
*/
|
||||||
printk(KERN_DEBUG "APIC error on CPU%d: %02lx(%02lx)\n",
|
printk(KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n",
|
||||||
smp_processor_id(), v , v1);
|
smp_processor_id(), v , v1);
|
||||||
irq_exit();
|
irq_exit();
|
||||||
}
|
}
|
||||||
@@ -1565,6 +1907,13 @@ void __cpuinit generic_processor_info(int apicid, int version)
|
|||||||
cpu_set(cpu, cpu_present_map);
|
cpu_set(cpu, cpu_present_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
int hard_smp_processor_id(void)
|
||||||
|
{
|
||||||
|
return read_apic_id();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Power management
|
* Power management
|
||||||
*/
|
*/
|
||||||
@@ -1640,7 +1989,7 @@ static int lapic_resume(struct sys_device *dev)
|
|||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef HAVE_X2APIC
|
||||||
if (x2apic)
|
if (x2apic)
|
||||||
enable_x2apic();
|
enable_x2apic();
|
||||||
else
|
else
|
||||||
@@ -1702,7 +2051,7 @@ static struct sys_device device_lapic = {
|
|||||||
.cls = &lapic_sysclass,
|
.cls = &lapic_sysclass,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void __devinit apic_pm_activate(void)
|
static void __cpuinit apic_pm_activate(void)
|
||||||
{
|
{
|
||||||
apic_pm_state.active = 1;
|
apic_pm_state.active = 1;
|
||||||
}
|
}
|
||||||
@@ -1728,16 +2077,87 @@ static void apic_pm_activate(void) { }
|
|||||||
|
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
/*
|
||||||
|
* apic_is_clustered_box() -- Check if we can expect good TSC
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
unsigned id;
|
||||||
|
u16 *bios_cpu_apicid;
|
||||||
|
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);
|
||||||
|
bitmap_zero(clustermap, NUM_APIC_CLUSTERS);
|
||||||
|
|
||||||
|
for (i = 0; i < NR_CPUS; i++) {
|
||||||
|
/* are we being called early in kernel startup? */
|
||||||
|
if (bios_cpu_apicid) {
|
||||||
|
id = bios_cpu_apicid[i];
|
||||||
|
}
|
||||||
|
else if (i < nr_cpu_ids) {
|
||||||
|
if (cpu_present(i))
|
||||||
|
id = per_cpu(x86_bios_cpu_apicid, i);
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (id != BAD_APICID)
|
||||||
|
__set_bit(APIC_CLUSTERID(id), clustermap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Problem: Partially populated chassis may not have CPUs in some of
|
||||||
|
* the APIC clusters they have been allocated. Only present CPUs have
|
||||||
|
* x86_bios_cpu_apicid entries, thus causing zeroes in the bitmap.
|
||||||
|
* Since clusters are allocated sequentially, count zeros only if
|
||||||
|
* they are bounded by ones.
|
||||||
|
*/
|
||||||
|
clusters = 0;
|
||||||
|
zeros = 0;
|
||||||
|
for (i = 0; i < NUM_APIC_CLUSTERS; i++) {
|
||||||
|
if (test_bit(i, clustermap)) {
|
||||||
|
clusters += 1 + zeros;
|
||||||
|
zeros = 0;
|
||||||
|
} else
|
||||||
|
++zeros;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ScaleMP vSMPowered boxes have one cluster per board and TSCs are
|
||||||
|
* not guaranteed to be synced between boards
|
||||||
|
*/
|
||||||
|
if (is_vsmp_box() && clusters > 1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If clusters > 2, then should be multi-chassis.
|
||||||
|
* May have to revisit this when multi-core + hyperthreaded CPUs come
|
||||||
|
* out, but AFAIK this will work even for them.
|
||||||
|
*/
|
||||||
|
return (clusters > 2);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* APIC command line parameters
|
* APIC command line parameters
|
||||||
*/
|
*/
|
||||||
static int __init parse_lapic(char *arg)
|
|
||||||
{
|
|
||||||
force_enable_local_apic = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
early_param("lapic", parse_lapic);
|
|
||||||
|
|
||||||
static int __init setup_disableapic(char *arg)
|
static int __init setup_disableapic(char *arg)
|
||||||
{
|
{
|
||||||
disable_apic = 1;
|
disable_apic = 1;
|
||||||
@@ -1779,7 +2199,6 @@ static int __init apic_set_verbosity(char *arg)
|
|||||||
if (!arg) {
|
if (!arg) {
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
skip_ioapic_setup = 0;
|
skip_ioapic_setup = 0;
|
||||||
ioapic_force = 1;
|
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
return -EINVAL;
|
return -EINVAL;
|
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* BIOS run time interface routines.
|
* BIOS run time interface routines.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
@@ -16,33 +14,128 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved.
|
||||||
|
* Copyright (c) Russ Anderson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/efi.h>
|
||||||
|
#include <asm/efi.h>
|
||||||
|
#include <linux/io.h>
|
||||||
#include <asm/uv/bios.h>
|
#include <asm/uv/bios.h>
|
||||||
|
#include <asm/uv/uv_hub.h>
|
||||||
|
|
||||||
const char *
|
struct uv_systab uv_systab;
|
||||||
x86_bios_strerror(long status)
|
|
||||||
|
s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
|
||||||
{
|
{
|
||||||
const char *str;
|
struct uv_systab *tab = &uv_systab;
|
||||||
switch (status) {
|
|
||||||
case 0: str = "Call completed without error"; break;
|
if (!tab->function)
|
||||||
case -1: str = "Not implemented"; break;
|
/*
|
||||||
case -2: str = "Invalid argument"; break;
|
* BIOS does not support UV systab
|
||||||
case -3: str = "Call completed with error"; break;
|
*/
|
||||||
default: str = "Unknown BIOS status code"; break;
|
return BIOS_STATUS_UNIMPLEMENTED;
|
||||||
|
|
||||||
|
return efi_call6((void *)__va(tab->function),
|
||||||
|
(u64)which, a1, a2, a3, a4, a5);
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
|
||||||
|
u64 a4, u64 a5)
|
||||||
|
{
|
||||||
|
unsigned long bios_flags;
|
||||||
|
s64 ret;
|
||||||
|
|
||||||
|
local_irq_save(bios_flags);
|
||||||
|
ret = uv_bios_call(which, a1, a2, a3, a4, a5);
|
||||||
|
local_irq_restore(bios_flags);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 uv_bios_call_reentrant(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
|
||||||
|
u64 a4, u64 a5)
|
||||||
|
{
|
||||||
|
s64 ret;
|
||||||
|
|
||||||
|
preempt_disable();
|
||||||
|
ret = uv_bios_call(which, a1, a2, a3, a4, a5);
|
||||||
|
preempt_enable();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long sn_partition_id;
|
||||||
|
EXPORT_SYMBOL_GPL(sn_partition_id);
|
||||||
|
long uv_coherency_id;
|
||||||
|
EXPORT_SYMBOL_GPL(uv_coherency_id);
|
||||||
|
long uv_region_size;
|
||||||
|
EXPORT_SYMBOL_GPL(uv_region_size);
|
||||||
|
int uv_type;
|
||||||
|
|
||||||
|
|
||||||
|
s64 uv_bios_get_sn_info(int fc, int *uvtype, long *partid, long *coher,
|
||||||
|
long *region)
|
||||||
|
{
|
||||||
|
s64 ret;
|
||||||
|
u64 v0, v1;
|
||||||
|
union partition_info_u part;
|
||||||
|
|
||||||
|
ret = uv_bios_call_irqsave(UV_BIOS_GET_SN_INFO, fc,
|
||||||
|
(u64)(&v0), (u64)(&v1), 0, 0);
|
||||||
|
if (ret != BIOS_STATUS_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
part.val = v0;
|
||||||
|
if (uvtype)
|
||||||
|
*uvtype = part.hub_version;
|
||||||
|
if (partid)
|
||||||
|
*partid = part.partition_id;
|
||||||
|
if (coher)
|
||||||
|
*coher = part.coherence_id;
|
||||||
|
if (region)
|
||||||
|
*region = part.region_size;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
s64 uv_bios_freq_base(u64 clock_type, u64 *ticks_per_second)
|
||||||
|
{
|
||||||
|
return uv_bios_call(UV_BIOS_FREQ_BASE, clock_type,
|
||||||
|
(u64)ticks_per_second, 0, 0, 0);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(uv_bios_freq_base);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef CONFIG_EFI
|
||||||
|
void uv_bios_init(void)
|
||||||
|
{
|
||||||
|
struct uv_systab *tab;
|
||||||
|
|
||||||
|
if ((efi.uv_systab == EFI_INVALID_TABLE_ADDR) ||
|
||||||
|
(efi.uv_systab == (unsigned long)NULL)) {
|
||||||
|
printk(KERN_CRIT "No EFI UV System Table.\n");
|
||||||
|
uv_systab.function = (unsigned long)NULL;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
long
|
tab = (struct uv_systab *)ioremap(efi.uv_systab,
|
||||||
x86_bios_freq_base(unsigned long which, unsigned long *ticks_per_second,
|
sizeof(struct uv_systab));
|
||||||
unsigned long *drift_info)
|
if (strncmp(tab->signature, "UVST", 4) != 0)
|
||||||
{
|
printk(KERN_ERR "bad signature in UV system table!");
|
||||||
struct uv_bios_retval isrv;
|
|
||||||
|
|
||||||
BIOS_CALL(isrv, BIOS_FREQ_BASE, which, 0, 0, 0, 0, 0, 0);
|
/*
|
||||||
*ticks_per_second = isrv.v0;
|
* Copy table to permanent spot for later use.
|
||||||
*drift_info = isrv.v1;
|
*/
|
||||||
return isrv.status;
|
memcpy(&uv_systab, tab, sizeof(struct uv_systab));
|
||||||
|
iounmap(tab);
|
||||||
|
|
||||||
|
printk(KERN_INFO "EFI UV System Table Revision %d\n", tab->revision);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(x86_bios_freq_base);
|
#else /* !CONFIG_EFI */
|
||||||
|
|
||||||
|
void uv_bios_init(void) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -249,7 +249,7 @@ static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c)
|
|||||||
}
|
}
|
||||||
numa_set_node(cpu, node);
|
numa_set_node(cpu, node);
|
||||||
|
|
||||||
printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
|
printk(KERN_INFO "CPU %d/0x%x -> Node %d\n", cpu, apicid, node);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -174,7 +174,7 @@ static void __cpuinit srat_detect_node(void)
|
|||||||
node = first_node(node_online_map);
|
node = first_node(node_online_map);
|
||||||
numa_set_node(cpu, node);
|
numa_set_node(cpu, node);
|
||||||
|
|
||||||
printk(KERN_INFO "CPU %d/%x -> Node %d\n", cpu, apicid, node);
|
printk(KERN_INFO "CPU %d/0x%x -> Node %d\n", cpu, apicid, node);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -366,6 +366,10 @@ void __init efi_init(void)
|
|||||||
SMBIOS_TABLE_GUID)) {
|
SMBIOS_TABLE_GUID)) {
|
||||||
efi.smbios = config_tables[i].table;
|
efi.smbios = config_tables[i].table;
|
||||||
printk(" SMBIOS=0x%lx ", config_tables[i].table);
|
printk(" SMBIOS=0x%lx ", config_tables[i].table);
|
||||||
|
} else if (!efi_guidcmp(config_tables[i].guid,
|
||||||
|
UV_SYSTEM_TABLE_GUID)) {
|
||||||
|
efi.uv_systab = config_tables[i].table;
|
||||||
|
printk(" UVsystab=0x%lx ", config_tables[i].table);
|
||||||
} else if (!efi_guidcmp(config_tables[i].guid,
|
} else if (!efi_guidcmp(config_tables[i].guid,
|
||||||
HCDP_TABLE_GUID)) {
|
HCDP_TABLE_GUID)) {
|
||||||
efi.hcdp = config_tables[i].table;
|
efi.hcdp = config_tables[i].table;
|
||||||
|
@@ -629,7 +629,7 @@ ENTRY(interrupt)
|
|||||||
ENTRY(irq_entries_start)
|
ENTRY(irq_entries_start)
|
||||||
RING0_INT_FRAME
|
RING0_INT_FRAME
|
||||||
vector=0
|
vector=0
|
||||||
.rept NR_IRQS
|
.rept NR_VECTORS
|
||||||
ALIGN
|
ALIGN
|
||||||
.if vector
|
.if vector
|
||||||
CFI_ADJUST_CFA_OFFSET -4
|
CFI_ADJUST_CFA_OFFSET -4
|
||||||
|
@@ -179,8 +179,10 @@ static int __init physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
|||||||
* 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");
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@@ -341,12 +341,12 @@ static __init void map_mmioh_high(int max_pnode)
|
|||||||
|
|
||||||
static __init void uv_rtc_init(void)
|
static __init void uv_rtc_init(void)
|
||||||
{
|
{
|
||||||
long status, ticks_per_sec, drift;
|
long status;
|
||||||
|
u64 ticks_per_sec;
|
||||||
|
|
||||||
status =
|
status = uv_bios_freq_base(BIOS_FREQ_BASE_REALTIME_CLOCK,
|
||||||
x86_bios_freq_base(BIOS_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec,
|
&ticks_per_sec);
|
||||||
&drift);
|
if (status != BIOS_STATUS_SUCCESS || ticks_per_sec < 100000) {
|
||||||
if (status != 0 || ticks_per_sec < 100000) {
|
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"unable to determine platform RTC clock frequency, "
|
"unable to determine platform RTC clock frequency, "
|
||||||
"guessing.\n");
|
"guessing.\n");
|
||||||
@@ -356,7 +356,22 @@ static __init void uv_rtc_init(void)
|
|||||||
sn_rtc_cycles_per_second = ticks_per_sec;
|
sn_rtc_cycles_per_second = ticks_per_sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool uv_system_inited;
|
/*
|
||||||
|
* Called on each cpu to initialize the per_cpu UV data area.
|
||||||
|
* ZZZ hotplug not supported yet
|
||||||
|
*/
|
||||||
|
void __cpuinit uv_cpu_init(void)
|
||||||
|
{
|
||||||
|
/* CPU 0 initilization will be done via uv_system_init. */
|
||||||
|
if (!uv_blade_info)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uv_blade_info[uv_numa_blade_id()].nr_online_cpus++;
|
||||||
|
|
||||||
|
if (get_uv_system_type() == UV_NON_UNIQUE_APIC)
|
||||||
|
set_x2apic_extra_bits(uv_hub_info->pnode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void __init uv_system_init(void)
|
void __init uv_system_init(void)
|
||||||
{
|
{
|
||||||
@@ -412,6 +427,9 @@ void __init uv_system_init(void)
|
|||||||
gnode_upper = (((unsigned long)node_id.s.node_id) &
|
gnode_upper = (((unsigned long)node_id.s.node_id) &
|
||||||
~((1 << n_val) - 1)) << m_val;
|
~((1 << n_val) - 1)) << m_val;
|
||||||
|
|
||||||
|
uv_bios_init();
|
||||||
|
uv_bios_get_sn_info(0, &uv_type, &sn_partition_id,
|
||||||
|
&uv_coherency_id, &uv_region_size);
|
||||||
uv_rtc_init();
|
uv_rtc_init();
|
||||||
|
|
||||||
for_each_present_cpu(cpu) {
|
for_each_present_cpu(cpu) {
|
||||||
@@ -433,7 +451,7 @@ void __init uv_system_init(void)
|
|||||||
uv_cpu_hub_info(cpu)->gpa_mask = (1 << (m_val + n_val)) - 1;
|
uv_cpu_hub_info(cpu)->gpa_mask = (1 << (m_val + n_val)) - 1;
|
||||||
uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper;
|
uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper;
|
||||||
uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base;
|
uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base;
|
||||||
uv_cpu_hub_info(cpu)->coherency_domain_number = 0;/* ZZZ */
|
uv_cpu_hub_info(cpu)->coherency_domain_number = uv_coherency_id;
|
||||||
uv_node_to_blade[nid] = blade;
|
uv_node_to_blade[nid] = blade;
|
||||||
uv_cpu_to_blade[cpu] = blade;
|
uv_cpu_to_blade[cpu] = blade;
|
||||||
max_pnode = max(pnode, max_pnode);
|
max_pnode = max(pnode, max_pnode);
|
||||||
@@ -448,21 +466,6 @@ void __init uv_system_init(void)
|
|||||||
map_mmr_high(max_pnode);
|
map_mmr_high(max_pnode);
|
||||||
map_config_high(max_pnode);
|
map_config_high(max_pnode);
|
||||||
map_mmioh_high(max_pnode);
|
map_mmioh_high(max_pnode);
|
||||||
uv_system_inited = true;
|
|
||||||
|
uv_cpu_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Called on each cpu to initialize the per_cpu UV data area.
|
|
||||||
* ZZZ hotplug not supported yet
|
|
||||||
*/
|
|
||||||
void __cpuinit uv_cpu_init(void)
|
|
||||||
{
|
|
||||||
BUG_ON(!uv_system_inited);
|
|
||||||
|
|
||||||
uv_blade_info[uv_numa_blade_id()].nr_online_cpus++;
|
|
||||||
|
|
||||||
if (get_uv_system_type() == UV_NON_UNIQUE_APIC)
|
|
||||||
set_x2apic_extra_bits(uv_hub_info->pnode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,29 +1,49 @@
|
|||||||
#include <linux/clocksource.h>
|
#include <linux/clocksource.h>
|
||||||
#include <linux/clockchips.h>
|
#include <linux/clockchips.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/sysdev.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/hpet.h>
|
#include <linux/hpet.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/sysdev.h>
|
#include <linux/cpu.h>
|
||||||
#include <linux/pm.h>
|
#include <linux/pm.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
|
||||||
#include <asm/fixmap.h>
|
#include <asm/fixmap.h>
|
||||||
#include <asm/hpet.h>
|
|
||||||
#include <asm/i8253.h>
|
#include <asm/i8253.h>
|
||||||
#include <asm/io.h>
|
#include <asm/hpet.h>
|
||||||
|
|
||||||
#define HPET_MASK CLOCKSOURCE_MASK(32)
|
#define HPET_MASK CLOCKSOURCE_MASK(32)
|
||||||
#define HPET_SHIFT 22
|
#define HPET_SHIFT 22
|
||||||
|
|
||||||
/* FSEC = 10^-15
|
/* FSEC = 10^-15
|
||||||
NSEC = 10^-9 */
|
NSEC = 10^-9 */
|
||||||
#define FSEC_PER_NSEC 1000000L
|
#define FSEC_PER_NSEC 1000000L
|
||||||
|
|
||||||
|
#define HPET_DEV_USED_BIT 2
|
||||||
|
#define HPET_DEV_USED (1 << HPET_DEV_USED_BIT)
|
||||||
|
#define HPET_DEV_VALID 0x8
|
||||||
|
#define HPET_DEV_FSB_CAP 0x1000
|
||||||
|
#define HPET_DEV_PERI_CAP 0x2000
|
||||||
|
|
||||||
|
#define EVT_TO_HPET_DEV(evt) container_of(evt, struct hpet_dev, evt)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* HPET address is set in acpi/boot.c, when an ACPI entry exists
|
* HPET address is set in acpi/boot.c, when an ACPI entry exists
|
||||||
*/
|
*/
|
||||||
unsigned long hpet_address;
|
unsigned long hpet_address;
|
||||||
static void __iomem *hpet_virt_address;
|
unsigned long hpet_num_timers;
|
||||||
|
static void __iomem *hpet_virt_address;
|
||||||
|
|
||||||
|
struct hpet_dev {
|
||||||
|
struct clock_event_device evt;
|
||||||
|
unsigned int num;
|
||||||
|
int cpu;
|
||||||
|
unsigned int irq;
|
||||||
|
unsigned int flags;
|
||||||
|
char name[10];
|
||||||
|
};
|
||||||
|
|
||||||
unsigned long hpet_readl(unsigned long a)
|
unsigned long hpet_readl(unsigned long a)
|
||||||
{
|
{
|
||||||
@@ -59,7 +79,7 @@ static inline void hpet_clear_mapping(void)
|
|||||||
static int boot_hpet_disable;
|
static int boot_hpet_disable;
|
||||||
int hpet_force_user;
|
int hpet_force_user;
|
||||||
|
|
||||||
static int __init hpet_setup(char* str)
|
static int __init hpet_setup(char *str)
|
||||||
{
|
{
|
||||||
if (str) {
|
if (str) {
|
||||||
if (!strncmp("disable", str, 7))
|
if (!strncmp("disable", str, 7))
|
||||||
@@ -80,7 +100,7 @@ __setup("nohpet", disable_hpet);
|
|||||||
|
|
||||||
static inline int is_hpet_capable(void)
|
static inline int is_hpet_capable(void)
|
||||||
{
|
{
|
||||||
return (!boot_hpet_disable && hpet_address);
|
return !boot_hpet_disable && hpet_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -102,6 +122,9 @@ EXPORT_SYMBOL_GPL(is_hpet_enabled);
|
|||||||
* timer 0 and timer 1 in case of RTC emulation.
|
* timer 0 and timer 1 in case of RTC emulation.
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_HPET
|
#ifdef CONFIG_HPET
|
||||||
|
|
||||||
|
static void hpet_reserve_msi_timers(struct hpet_data *hd);
|
||||||
|
|
||||||
static void hpet_reserve_platform_timers(unsigned long id)
|
static void hpet_reserve_platform_timers(unsigned long id)
|
||||||
{
|
{
|
||||||
struct hpet __iomem *hpet = hpet_virt_address;
|
struct hpet __iomem *hpet = hpet_virt_address;
|
||||||
@@ -111,10 +134,10 @@ static void hpet_reserve_platform_timers(unsigned long id)
|
|||||||
|
|
||||||
nrtimers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
|
nrtimers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT) + 1;
|
||||||
|
|
||||||
memset(&hd, 0, sizeof (hd));
|
memset(&hd, 0, sizeof(hd));
|
||||||
hd.hd_phys_address = hpet_address;
|
hd.hd_phys_address = hpet_address;
|
||||||
hd.hd_address = hpet;
|
hd.hd_address = hpet;
|
||||||
hd.hd_nirqs = nrtimers;
|
hd.hd_nirqs = nrtimers;
|
||||||
hpet_reserve_timer(&hd, 0);
|
hpet_reserve_timer(&hd, 0);
|
||||||
|
|
||||||
#ifdef CONFIG_HPET_EMULATE_RTC
|
#ifdef CONFIG_HPET_EMULATE_RTC
|
||||||
@@ -130,10 +153,12 @@ static void hpet_reserve_platform_timers(unsigned long id)
|
|||||||
hd.hd_irq[1] = HPET_LEGACY_RTC;
|
hd.hd_irq[1] = HPET_LEGACY_RTC;
|
||||||
|
|
||||||
for (i = 2; i < nrtimers; timer++, i++) {
|
for (i = 2; i < nrtimers; timer++, i++) {
|
||||||
hd.hd_irq[i] = (readl(&timer->hpet_config) & Tn_INT_ROUTE_CNF_MASK) >>
|
hd.hd_irq[i] = (readl(&timer->hpet_config) &
|
||||||
Tn_INT_ROUTE_CNF_SHIFT;
|
Tn_INT_ROUTE_CNF_MASK) >> Tn_INT_ROUTE_CNF_SHIFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hpet_reserve_msi_timers(&hd);
|
||||||
|
|
||||||
hpet_alloc(&hd);
|
hpet_alloc(&hd);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -227,60 +252,70 @@ static void hpet_legacy_clockevent_register(void)
|
|||||||
printk(KERN_DEBUG "hpet clockevent registered\n");
|
printk(KERN_DEBUG "hpet clockevent registered\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hpet_legacy_set_mode(enum clock_event_mode mode,
|
static int hpet_setup_msi_irq(unsigned int irq);
|
||||||
struct clock_event_device *evt)
|
|
||||||
|
static void hpet_set_mode(enum clock_event_mode mode,
|
||||||
|
struct clock_event_device *evt, int timer)
|
||||||
{
|
{
|
||||||
unsigned long cfg, cmp, now;
|
unsigned long cfg, cmp, now;
|
||||||
uint64_t delta;
|
uint64_t delta;
|
||||||
|
|
||||||
switch(mode) {
|
switch (mode) {
|
||||||
case CLOCK_EVT_MODE_PERIODIC:
|
case CLOCK_EVT_MODE_PERIODIC:
|
||||||
delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * hpet_clockevent.mult;
|
delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * evt->mult;
|
||||||
delta >>= hpet_clockevent.shift;
|
delta >>= evt->shift;
|
||||||
now = hpet_readl(HPET_COUNTER);
|
now = hpet_readl(HPET_COUNTER);
|
||||||
cmp = now + (unsigned long) delta;
|
cmp = now + (unsigned long) delta;
|
||||||
cfg = hpet_readl(HPET_T0_CFG);
|
cfg = hpet_readl(HPET_Tn_CFG(timer));
|
||||||
cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
|
cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
|
||||||
HPET_TN_SETVAL | HPET_TN_32BIT;
|
HPET_TN_SETVAL | HPET_TN_32BIT;
|
||||||
hpet_writel(cfg, HPET_T0_CFG);
|
hpet_writel(cfg, HPET_Tn_CFG(timer));
|
||||||
/*
|
/*
|
||||||
* The first write after writing TN_SETVAL to the
|
* The first write after writing TN_SETVAL to the
|
||||||
* config register sets the counter value, the second
|
* config register sets the counter value, the second
|
||||||
* write sets the period.
|
* write sets the period.
|
||||||
*/
|
*/
|
||||||
hpet_writel(cmp, HPET_T0_CMP);
|
hpet_writel(cmp, HPET_Tn_CMP(timer));
|
||||||
udelay(1);
|
udelay(1);
|
||||||
hpet_writel((unsigned long) delta, HPET_T0_CMP);
|
hpet_writel((unsigned long) delta, HPET_Tn_CMP(timer));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLOCK_EVT_MODE_ONESHOT:
|
case CLOCK_EVT_MODE_ONESHOT:
|
||||||
cfg = hpet_readl(HPET_T0_CFG);
|
cfg = hpet_readl(HPET_Tn_CFG(timer));
|
||||||
cfg &= ~HPET_TN_PERIODIC;
|
cfg &= ~HPET_TN_PERIODIC;
|
||||||
cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
|
cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
|
||||||
hpet_writel(cfg, HPET_T0_CFG);
|
hpet_writel(cfg, HPET_Tn_CFG(timer));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLOCK_EVT_MODE_UNUSED:
|
case CLOCK_EVT_MODE_UNUSED:
|
||||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||||
cfg = hpet_readl(HPET_T0_CFG);
|
cfg = hpet_readl(HPET_Tn_CFG(timer));
|
||||||
cfg &= ~HPET_TN_ENABLE;
|
cfg &= ~HPET_TN_ENABLE;
|
||||||
hpet_writel(cfg, HPET_T0_CFG);
|
hpet_writel(cfg, HPET_Tn_CFG(timer));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLOCK_EVT_MODE_RESUME:
|
case CLOCK_EVT_MODE_RESUME:
|
||||||
hpet_enable_legacy_int();
|
if (timer == 0) {
|
||||||
|
hpet_enable_legacy_int();
|
||||||
|
} else {
|
||||||
|
struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
|
||||||
|
hpet_setup_msi_irq(hdev->irq);
|
||||||
|
disable_irq(hdev->irq);
|
||||||
|
irq_set_affinity(hdev->irq, cpumask_of_cpu(hdev->cpu));
|
||||||
|
enable_irq(hdev->irq);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hpet_legacy_next_event(unsigned long delta,
|
static int hpet_next_event(unsigned long delta,
|
||||||
struct clock_event_device *evt)
|
struct clock_event_device *evt, int timer)
|
||||||
{
|
{
|
||||||
u32 cnt;
|
u32 cnt;
|
||||||
|
|
||||||
cnt = hpet_readl(HPET_COUNTER);
|
cnt = hpet_readl(HPET_COUNTER);
|
||||||
cnt += (u32) delta;
|
cnt += (u32) delta;
|
||||||
hpet_writel(cnt, HPET_T0_CMP);
|
hpet_writel(cnt, HPET_Tn_CMP(timer));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to read back the CMP register to make sure that
|
* We need to read back the CMP register to make sure that
|
||||||
@@ -292,6 +327,347 @@ static int hpet_legacy_next_event(unsigned long delta,
|
|||||||
return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
|
return (s32)((u32)hpet_readl(HPET_COUNTER) - cnt) >= 0 ? -ETIME : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hpet_legacy_set_mode(enum clock_event_mode mode,
|
||||||
|
struct clock_event_device *evt)
|
||||||
|
{
|
||||||
|
hpet_set_mode(mode, evt, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hpet_legacy_next_event(unsigned long delta,
|
||||||
|
struct clock_event_device *evt)
|
||||||
|
{
|
||||||
|
return hpet_next_event(delta, evt, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HPET MSI Support
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_PCI_MSI
|
||||||
|
|
||||||
|
static DEFINE_PER_CPU(struct hpet_dev *, cpu_hpet_dev);
|
||||||
|
static struct hpet_dev *hpet_devs;
|
||||||
|
|
||||||
|
void hpet_msi_unmask(unsigned int irq)
|
||||||
|
{
|
||||||
|
struct hpet_dev *hdev = get_irq_data(irq);
|
||||||
|
unsigned long cfg;
|
||||||
|
|
||||||
|
/* unmask it */
|
||||||
|
cfg = hpet_readl(HPET_Tn_CFG(hdev->num));
|
||||||
|
cfg |= HPET_TN_FSB;
|
||||||
|
hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
|
||||||
|
}
|
||||||
|
|
||||||
|
void hpet_msi_mask(unsigned int irq)
|
||||||
|
{
|
||||||
|
unsigned long cfg;
|
||||||
|
struct hpet_dev *hdev = get_irq_data(irq);
|
||||||
|
|
||||||
|
/* mask it */
|
||||||
|
cfg = hpet_readl(HPET_Tn_CFG(hdev->num));
|
||||||
|
cfg &= ~HPET_TN_FSB;
|
||||||
|
hpet_writel(cfg, HPET_Tn_CFG(hdev->num));
|
||||||
|
}
|
||||||
|
|
||||||
|
void hpet_msi_write(unsigned int irq, struct msi_msg *msg)
|
||||||
|
{
|
||||||
|
struct hpet_dev *hdev = get_irq_data(irq);
|
||||||
|
|
||||||
|
hpet_writel(msg->data, HPET_Tn_ROUTE(hdev->num));
|
||||||
|
hpet_writel(msg->address_lo, HPET_Tn_ROUTE(hdev->num) + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void hpet_msi_read(unsigned int irq, struct msi_msg *msg)
|
||||||
|
{
|
||||||
|
struct hpet_dev *hdev = get_irq_data(irq);
|
||||||
|
|
||||||
|
msg->data = hpet_readl(HPET_Tn_ROUTE(hdev->num));
|
||||||
|
msg->address_lo = hpet_readl(HPET_Tn_ROUTE(hdev->num) + 4);
|
||||||
|
msg->address_hi = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hpet_msi_set_mode(enum clock_event_mode mode,
|
||||||
|
struct clock_event_device *evt)
|
||||||
|
{
|
||||||
|
struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
|
||||||
|
hpet_set_mode(mode, evt, hdev->num);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hpet_msi_next_event(unsigned long delta,
|
||||||
|
struct clock_event_device *evt)
|
||||||
|
{
|
||||||
|
struct hpet_dev *hdev = EVT_TO_HPET_DEV(evt);
|
||||||
|
return hpet_next_event(delta, evt, hdev->num);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hpet_setup_msi_irq(unsigned int irq)
|
||||||
|
{
|
||||||
|
if (arch_setup_hpet_msi(irq)) {
|
||||||
|
destroy_irq(irq);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hpet_assign_irq(struct hpet_dev *dev)
|
||||||
|
{
|
||||||
|
unsigned int irq;
|
||||||
|
|
||||||
|
irq = create_irq();
|
||||||
|
if (!irq)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
set_irq_data(irq, dev);
|
||||||
|
|
||||||
|
if (hpet_setup_msi_irq(irq))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
dev->irq = irq;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t hpet_interrupt_handler(int irq, void *data)
|
||||||
|
{
|
||||||
|
struct hpet_dev *dev = (struct hpet_dev *)data;
|
||||||
|
struct clock_event_device *hevt = &dev->evt;
|
||||||
|
|
||||||
|
if (!hevt->event_handler) {
|
||||||
|
printk(KERN_INFO "Spurious HPET timer interrupt on HPET timer %d\n",
|
||||||
|
dev->num);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
hevt->event_handler(hevt);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hpet_setup_irq(struct hpet_dev *dev)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (request_irq(dev->irq, hpet_interrupt_handler,
|
||||||
|
IRQF_SHARED|IRQF_NOBALANCING, dev->name, dev))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
disable_irq(dev->irq);
|
||||||
|
irq_set_affinity(dev->irq, cpumask_of_cpu(dev->cpu));
|
||||||
|
enable_irq(dev->irq);
|
||||||
|
|
||||||
|
printk(KERN_DEBUG "hpet: %s irq %d for MSI\n",
|
||||||
|
dev->name, dev->irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This should be called in specific @cpu */
|
||||||
|
static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
|
||||||
|
{
|
||||||
|
struct clock_event_device *evt = &hdev->evt;
|
||||||
|
uint64_t hpet_freq;
|
||||||
|
|
||||||
|
WARN_ON(cpu != smp_processor_id());
|
||||||
|
if (!(hdev->flags & HPET_DEV_VALID))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (hpet_setup_msi_irq(hdev->irq))
|
||||||
|
return;
|
||||||
|
|
||||||
|
hdev->cpu = cpu;
|
||||||
|
per_cpu(cpu_hpet_dev, cpu) = hdev;
|
||||||
|
evt->name = hdev->name;
|
||||||
|
hpet_setup_irq(hdev);
|
||||||
|
evt->irq = hdev->irq;
|
||||||
|
|
||||||
|
evt->rating = 110;
|
||||||
|
evt->features = CLOCK_EVT_FEAT_ONESHOT;
|
||||||
|
if (hdev->flags & HPET_DEV_PERI_CAP)
|
||||||
|
evt->features |= CLOCK_EVT_FEAT_PERIODIC;
|
||||||
|
|
||||||
|
evt->set_mode = hpet_msi_set_mode;
|
||||||
|
evt->set_next_event = hpet_msi_next_event;
|
||||||
|
evt->shift = 32;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The period is a femto seconds value. We need to calculate the
|
||||||
|
* scaled math multiplication factor for nanosecond to hpet tick
|
||||||
|
* conversion.
|
||||||
|
*/
|
||||||
|
hpet_freq = 1000000000000000ULL;
|
||||||
|
do_div(hpet_freq, hpet_period);
|
||||||
|
evt->mult = div_sc((unsigned long) hpet_freq,
|
||||||
|
NSEC_PER_SEC, evt->shift);
|
||||||
|
/* Calculate the max delta */
|
||||||
|
evt->max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, evt);
|
||||||
|
/* 5 usec minimum reprogramming delta. */
|
||||||
|
evt->min_delta_ns = 5000;
|
||||||
|
|
||||||
|
evt->cpumask = cpumask_of_cpu(hdev->cpu);
|
||||||
|
clockevents_register_device(evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_HPET
|
||||||
|
/* Reserve at least one timer for userspace (/dev/hpet) */
|
||||||
|
#define RESERVE_TIMERS 1
|
||||||
|
#else
|
||||||
|
#define RESERVE_TIMERS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void hpet_msi_capability_lookup(unsigned int start_timer)
|
||||||
|
{
|
||||||
|
unsigned int id;
|
||||||
|
unsigned int num_timers;
|
||||||
|
unsigned int num_timers_used = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
id = hpet_readl(HPET_ID);
|
||||||
|
|
||||||
|
num_timers = ((id & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT);
|
||||||
|
num_timers++; /* Value read out starts from 0 */
|
||||||
|
|
||||||
|
hpet_devs = kzalloc(sizeof(struct hpet_dev) * num_timers, GFP_KERNEL);
|
||||||
|
if (!hpet_devs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hpet_num_timers = num_timers;
|
||||||
|
|
||||||
|
for (i = start_timer; i < num_timers - RESERVE_TIMERS; i++) {
|
||||||
|
struct hpet_dev *hdev = &hpet_devs[num_timers_used];
|
||||||
|
unsigned long cfg = hpet_readl(HPET_Tn_CFG(i));
|
||||||
|
|
||||||
|
/* Only consider HPET timer with MSI support */
|
||||||
|
if (!(cfg & HPET_TN_FSB_CAP))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
hdev->flags = 0;
|
||||||
|
if (cfg & HPET_TN_PERIODIC_CAP)
|
||||||
|
hdev->flags |= HPET_DEV_PERI_CAP;
|
||||||
|
hdev->num = i;
|
||||||
|
|
||||||
|
sprintf(hdev->name, "hpet%d", i);
|
||||||
|
if (hpet_assign_irq(hdev))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
hdev->flags |= HPET_DEV_FSB_CAP;
|
||||||
|
hdev->flags |= HPET_DEV_VALID;
|
||||||
|
num_timers_used++;
|
||||||
|
if (num_timers_used == num_possible_cpus())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk(KERN_INFO "HPET: %d timers in total, %d timers will be used for per-cpu timer\n",
|
||||||
|
num_timers, num_timers_used);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_HPET
|
||||||
|
static void hpet_reserve_msi_timers(struct hpet_data *hd)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!hpet_devs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < hpet_num_timers; i++) {
|
||||||
|
struct hpet_dev *hdev = &hpet_devs[i];
|
||||||
|
|
||||||
|
if (!(hdev->flags & HPET_DEV_VALID))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
hd->hd_irq[hdev->num] = hdev->irq;
|
||||||
|
hpet_reserve_timer(hd, hdev->num);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct hpet_dev *hpet_get_unused_timer(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!hpet_devs)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < hpet_num_timers; i++) {
|
||||||
|
struct hpet_dev *hdev = &hpet_devs[i];
|
||||||
|
|
||||||
|
if (!(hdev->flags & HPET_DEV_VALID))
|
||||||
|
continue;
|
||||||
|
if (test_and_set_bit(HPET_DEV_USED_BIT,
|
||||||
|
(unsigned long *)&hdev->flags))
|
||||||
|
continue;
|
||||||
|
return hdev;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hpet_work_struct {
|
||||||
|
struct delayed_work work;
|
||||||
|
struct completion complete;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void hpet_work(struct work_struct *w)
|
||||||
|
{
|
||||||
|
struct hpet_dev *hdev;
|
||||||
|
int cpu = smp_processor_id();
|
||||||
|
struct hpet_work_struct *hpet_work;
|
||||||
|
|
||||||
|
hpet_work = container_of(w, struct hpet_work_struct, work.work);
|
||||||
|
|
||||||
|
hdev = hpet_get_unused_timer();
|
||||||
|
if (hdev)
|
||||||
|
init_one_hpet_msi_clockevent(hdev, cpu);
|
||||||
|
|
||||||
|
complete(&hpet_work->complete);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hpet_cpuhp_notify(struct notifier_block *n,
|
||||||
|
unsigned long action, void *hcpu)
|
||||||
|
{
|
||||||
|
unsigned long cpu = (unsigned long)hcpu;
|
||||||
|
struct hpet_work_struct work;
|
||||||
|
struct hpet_dev *hdev = per_cpu(cpu_hpet_dev, cpu);
|
||||||
|
|
||||||
|
switch (action & 0xf) {
|
||||||
|
case CPU_ONLINE:
|
||||||
|
INIT_DELAYED_WORK(&work.work, hpet_work);
|
||||||
|
init_completion(&work.complete);
|
||||||
|
/* FIXME: add schedule_work_on() */
|
||||||
|
schedule_delayed_work_on(cpu, &work.work, 0);
|
||||||
|
wait_for_completion(&work.complete);
|
||||||
|
break;
|
||||||
|
case CPU_DEAD:
|
||||||
|
if (hdev) {
|
||||||
|
free_irq(hdev->irq, hdev);
|
||||||
|
hdev->flags &= ~HPET_DEV_USED;
|
||||||
|
per_cpu(cpu_hpet_dev, cpu) = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return NOTIFY_OK;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
static int hpet_setup_msi_irq(unsigned int irq)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static void hpet_msi_capability_lookup(unsigned int start_timer)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_HPET
|
||||||
|
static void hpet_reserve_msi_timers(struct hpet_data *hd)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int hpet_cpuhp_notify(struct notifier_block *n,
|
||||||
|
unsigned long action, void *hcpu)
|
||||||
|
{
|
||||||
|
return NOTIFY_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clock source related code
|
* Clock source related code
|
||||||
*/
|
*/
|
||||||
@@ -427,8 +803,10 @@ int __init hpet_enable(void)
|
|||||||
|
|
||||||
if (id & HPET_ID_LEGSUP) {
|
if (id & HPET_ID_LEGSUP) {
|
||||||
hpet_legacy_clockevent_register();
|
hpet_legacy_clockevent_register();
|
||||||
|
hpet_msi_capability_lookup(2);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
hpet_msi_capability_lookup(0);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_nohpet:
|
out_nohpet:
|
||||||
@@ -445,6 +823,8 @@ out_nohpet:
|
|||||||
*/
|
*/
|
||||||
static __init int hpet_late_init(void)
|
static __init int hpet_late_init(void)
|
||||||
{
|
{
|
||||||
|
int cpu;
|
||||||
|
|
||||||
if (boot_hpet_disable)
|
if (boot_hpet_disable)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
@@ -460,6 +840,13 @@ static __init int hpet_late_init(void)
|
|||||||
|
|
||||||
hpet_reserve_platform_timers(hpet_readl(HPET_ID));
|
hpet_reserve_platform_timers(hpet_readl(HPET_ID));
|
||||||
|
|
||||||
|
for_each_online_cpu(cpu) {
|
||||||
|
hpet_cpuhp_notify(NULL, CPU_ONLINE, (void *)(long)cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This notifier should be called after workqueue is ready */
|
||||||
|
hotcpu_notifier(hpet_cpuhp_notify, -20);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
fs_initcall(hpet_late_init);
|
fs_initcall(hpet_late_init);
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
189
arch/x86/kernel/irq.c
Normal file
189
arch/x86/kernel/irq.c
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* Common interrupt code for 32 and 64 bit
|
||||||
|
*/
|
||||||
|
#include <linux/cpu.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/kernel_stat.h>
|
||||||
|
#include <linux/seq_file.h>
|
||||||
|
|
||||||
|
#include <asm/apic.h>
|
||||||
|
#include <asm/io_apic.h>
|
||||||
|
#include <asm/smp.h>
|
||||||
|
|
||||||
|
atomic_t irq_err_count;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 'what should we do if we get a hw irq event on an illegal vector'.
|
||||||
|
* each architecture has to answer this themselves.
|
||||||
|
*/
|
||||||
|
void ack_bad_irq(unsigned int irq)
|
||||||
|
{
|
||||||
|
printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq);
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
|
/*
|
||||||
|
* Currently unexpected vectors happen only on SMP and APIC.
|
||||||
|
* We _must_ ack these because every local APIC has only N
|
||||||
|
* irq slots per priority level, and a 'hanging, unacked' IRQ
|
||||||
|
* holds up an irq slot - in excessive cases (when multiple
|
||||||
|
* unexpected vectors occur) that might lock up the APIC
|
||||||
|
* completely.
|
||||||
|
* But only ack when the APIC is enabled -AK
|
||||||
|
*/
|
||||||
|
if (cpu_has_apic)
|
||||||
|
ack_APIC_irq();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_32
|
||||||
|
# define irq_stats(x) (&per_cpu(irq_stat,x))
|
||||||
|
#else
|
||||||
|
# define irq_stats(x) cpu_pda(x)
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* /proc/interrupts printing:
|
||||||
|
*/
|
||||||
|
static int show_other_interrupts(struct seq_file *p)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
seq_printf(p, "NMI: ");
|
||||||
|
for_each_online_cpu(j)
|
||||||
|
seq_printf(p, "%10u ", irq_stats(j)->__nmi_count);
|
||||||
|
seq_printf(p, " Non-maskable interrupts\n");
|
||||||
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
|
seq_printf(p, "LOC: ");
|
||||||
|
for_each_online_cpu(j)
|
||||||
|
seq_printf(p, "%10u ", irq_stats(j)->apic_timer_irqs);
|
||||||
|
seq_printf(p, " Local timer interrupts\n");
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
seq_printf(p, "RES: ");
|
||||||
|
for_each_online_cpu(j)
|
||||||
|
seq_printf(p, "%10u ", irq_stats(j)->irq_resched_count);
|
||||||
|
seq_printf(p, " Rescheduling interrupts\n");
|
||||||
|
seq_printf(p, "CAL: ");
|
||||||
|
for_each_online_cpu(j)
|
||||||
|
seq_printf(p, "%10u ", irq_stats(j)->irq_call_count);
|
||||||
|
seq_printf(p, " Function call interrupts\n");
|
||||||
|
seq_printf(p, "TLB: ");
|
||||||
|
for_each_online_cpu(j)
|
||||||
|
seq_printf(p, "%10u ", irq_stats(j)->irq_tlb_count);
|
||||||
|
seq_printf(p, " TLB shootdowns\n");
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_X86_MCE
|
||||||
|
seq_printf(p, "TRM: ");
|
||||||
|
for_each_online_cpu(j)
|
||||||
|
seq_printf(p, "%10u ", irq_stats(j)->irq_thermal_count);
|
||||||
|
seq_printf(p, " Thermal event interrupts\n");
|
||||||
|
# ifdef CONFIG_X86_64
|
||||||
|
seq_printf(p, "THR: ");
|
||||||
|
for_each_online_cpu(j)
|
||||||
|
seq_printf(p, "%10u ", irq_stats(j)->irq_threshold_count);
|
||||||
|
seq_printf(p, " Threshold APIC interrupts\n");
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
|
seq_printf(p, "SPU: ");
|
||||||
|
for_each_online_cpu(j)
|
||||||
|
seq_printf(p, "%10u ", irq_stats(j)->irq_spurious_count);
|
||||||
|
seq_printf(p, " Spurious interrupts\n");
|
||||||
|
#endif
|
||||||
|
seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
|
||||||
|
#if defined(CONFIG_X86_IO_APIC)
|
||||||
|
seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int show_interrupts(struct seq_file *p, void *v)
|
||||||
|
{
|
||||||
|
unsigned long flags, any_count = 0;
|
||||||
|
int i = *(loff_t *) v, j;
|
||||||
|
struct irqaction *action;
|
||||||
|
struct irq_desc *desc;
|
||||||
|
|
||||||
|
if (i > nr_irqs)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (i == nr_irqs)
|
||||||
|
return show_other_interrupts(p);
|
||||||
|
|
||||||
|
/* print header */
|
||||||
|
if (i == 0) {
|
||||||
|
seq_printf(p, " ");
|
||||||
|
for_each_online_cpu(j)
|
||||||
|
seq_printf(p, "CPU%-8d",j);
|
||||||
|
seq_putc(p, '\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
desc = irq_to_desc(i);
|
||||||
|
spin_lock_irqsave(&desc->lock, flags);
|
||||||
|
#ifndef CONFIG_SMP
|
||||||
|
any_count = kstat_irqs(i);
|
||||||
|
#else
|
||||||
|
for_each_online_cpu(j)
|
||||||
|
any_count |= kstat_irqs_cpu(i, j);
|
||||||
|
#endif
|
||||||
|
action = desc->action;
|
||||||
|
if (!action && !any_count)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
seq_printf(p, "%3d: ", i);
|
||||||
|
#ifndef CONFIG_SMP
|
||||||
|
seq_printf(p, "%10u ", kstat_irqs(i));
|
||||||
|
#else
|
||||||
|
for_each_online_cpu(j)
|
||||||
|
seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
|
||||||
|
#endif
|
||||||
|
seq_printf(p, " %8s", desc->chip->name);
|
||||||
|
seq_printf(p, "-%-8s", desc->name);
|
||||||
|
|
||||||
|
if (action) {
|
||||||
|
seq_printf(p, " %s", action->name);
|
||||||
|
while ((action = action->next) != NULL)
|
||||||
|
seq_printf(p, ", %s", action->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
seq_putc(p, '\n');
|
||||||
|
out:
|
||||||
|
spin_unlock_irqrestore(&desc->lock, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* /proc/stat helpers
|
||||||
|
*/
|
||||||
|
u64 arch_irq_stat_cpu(unsigned int cpu)
|
||||||
|
{
|
||||||
|
u64 sum = irq_stats(cpu)->__nmi_count;
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
|
sum += irq_stats(cpu)->apic_timer_irqs;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
sum += irq_stats(cpu)->irq_resched_count;
|
||||||
|
sum += irq_stats(cpu)->irq_call_count;
|
||||||
|
sum += irq_stats(cpu)->irq_tlb_count;
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_X86_MCE
|
||||||
|
sum += irq_stats(cpu)->irq_thermal_count;
|
||||||
|
# ifdef CONFIG_X86_64
|
||||||
|
sum += irq_stats(cpu)->irq_threshold_count;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
|
sum += irq_stats(cpu)->irq_spurious_count;
|
||||||
|
#endif
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 arch_irq_stat(void)
|
||||||
|
{
|
||||||
|
u64 sum = atomic_read(&irq_err_count);
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_IO_APIC
|
||||||
|
sum += atomic_read(&irq_mis_count);
|
||||||
|
#endif
|
||||||
|
return sum;
|
||||||
|
}
|
@@ -25,29 +25,6 @@ EXPORT_PER_CPU_SYMBOL(irq_stat);
|
|||||||
DEFINE_PER_CPU(struct pt_regs *, irq_regs);
|
DEFINE_PER_CPU(struct pt_regs *, irq_regs);
|
||||||
EXPORT_PER_CPU_SYMBOL(irq_regs);
|
EXPORT_PER_CPU_SYMBOL(irq_regs);
|
||||||
|
|
||||||
/*
|
|
||||||
* 'what should we do if we get a hw irq event on an illegal vector'.
|
|
||||||
* each architecture has to answer this themselves.
|
|
||||||
*/
|
|
||||||
void ack_bad_irq(unsigned int irq)
|
|
||||||
{
|
|
||||||
printk(KERN_ERR "unexpected IRQ trap at vector %02x\n", irq);
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_LOCAL_APIC
|
|
||||||
/*
|
|
||||||
* Currently unexpected vectors happen only on SMP and APIC.
|
|
||||||
* We _must_ ack these because every local APIC has only N
|
|
||||||
* irq slots per priority level, and a 'hanging, unacked' IRQ
|
|
||||||
* holds up an irq slot - in excessive cases (when multiple
|
|
||||||
* unexpected vectors occur) that might lock up the APIC
|
|
||||||
* completely.
|
|
||||||
* But only ack when the APIC is enabled -AK
|
|
||||||
*/
|
|
||||||
if (cpu_has_apic)
|
|
||||||
ack_APIC_irq();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_STACKOVERFLOW
|
#ifdef CONFIG_DEBUG_STACKOVERFLOW
|
||||||
/* Debugging check for stack overflow: is there less than 1KB free? */
|
/* Debugging check for stack overflow: is there less than 1KB free? */
|
||||||
static int check_stack_overflow(void)
|
static int check_stack_overflow(void)
|
||||||
@@ -223,20 +200,25 @@ unsigned int do_IRQ(struct pt_regs *regs)
|
|||||||
{
|
{
|
||||||
struct pt_regs *old_regs;
|
struct pt_regs *old_regs;
|
||||||
/* high bit used in ret_from_ code */
|
/* high bit used in ret_from_ code */
|
||||||
int overflow, irq = ~regs->orig_ax;
|
int overflow;
|
||||||
struct irq_desc *desc = irq_desc + irq;
|
unsigned vector = ~regs->orig_ax;
|
||||||
|
struct irq_desc *desc;
|
||||||
|
unsigned irq;
|
||||||
|
|
||||||
if (unlikely((unsigned)irq >= NR_IRQS)) {
|
|
||||||
printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
|
|
||||||
__func__, irq);
|
|
||||||
BUG();
|
|
||||||
}
|
|
||||||
|
|
||||||
old_regs = set_irq_regs(regs);
|
old_regs = set_irq_regs(regs);
|
||||||
irq_enter();
|
irq_enter();
|
||||||
|
irq = __get_cpu_var(vector_irq)[vector];
|
||||||
|
|
||||||
overflow = check_stack_overflow();
|
overflow = check_stack_overflow();
|
||||||
|
|
||||||
|
desc = irq_to_desc(irq);
|
||||||
|
if (unlikely(!desc)) {
|
||||||
|
printk(KERN_EMERG "%s: cannot handle IRQ %d vector %#x cpu %d\n",
|
||||||
|
__func__, irq, vector, smp_processor_id());
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
if (!execute_on_irq_stack(overflow, desc, irq)) {
|
if (!execute_on_irq_stack(overflow, desc, irq)) {
|
||||||
if (unlikely(overflow))
|
if (unlikely(overflow))
|
||||||
print_stack_overflow();
|
print_stack_overflow();
|
||||||
@@ -248,146 +230,6 @@ unsigned int do_IRQ(struct pt_regs *regs)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Interrupt statistics:
|
|
||||||
*/
|
|
||||||
|
|
||||||
atomic_t irq_err_count;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* /proc/interrupts printing:
|
|
||||||
*/
|
|
||||||
|
|
||||||
int show_interrupts(struct seq_file *p, void *v)
|
|
||||||
{
|
|
||||||
int i = *(loff_t *) v, j;
|
|
||||||
struct irqaction * action;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (i == 0) {
|
|
||||||
seq_printf(p, " ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "CPU%-8d",j);
|
|
||||||
seq_putc(p, '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i < NR_IRQS) {
|
|
||||||
unsigned any_count = 0;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&irq_desc[i].lock, flags);
|
|
||||||
#ifndef CONFIG_SMP
|
|
||||||
any_count = kstat_irqs(i);
|
|
||||||
#else
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
any_count |= kstat_cpu(j).irqs[i];
|
|
||||||
#endif
|
|
||||||
action = irq_desc[i].action;
|
|
||||||
if (!action && !any_count)
|
|
||||||
goto skip;
|
|
||||||
seq_printf(p, "%3d: ",i);
|
|
||||||
#ifndef CONFIG_SMP
|
|
||||||
seq_printf(p, "%10u ", kstat_irqs(i));
|
|
||||||
#else
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
|
|
||||||
#endif
|
|
||||||
seq_printf(p, " %8s", irq_desc[i].chip->name);
|
|
||||||
seq_printf(p, "-%-8s", irq_desc[i].name);
|
|
||||||
|
|
||||||
if (action) {
|
|
||||||
seq_printf(p, " %s", action->name);
|
|
||||||
while ((action = action->next) != NULL)
|
|
||||||
seq_printf(p, ", %s", action->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
seq_putc(p, '\n');
|
|
||||||
skip:
|
|
||||||
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
|
|
||||||
} else if (i == NR_IRQS) {
|
|
||||||
seq_printf(p, "NMI: ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ", nmi_count(j));
|
|
||||||
seq_printf(p, " Non-maskable interrupts\n");
|
|
||||||
#ifdef CONFIG_X86_LOCAL_APIC
|
|
||||||
seq_printf(p, "LOC: ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ",
|
|
||||||
per_cpu(irq_stat,j).apic_timer_irqs);
|
|
||||||
seq_printf(p, " Local timer interrupts\n");
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
seq_printf(p, "RES: ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ",
|
|
||||||
per_cpu(irq_stat,j).irq_resched_count);
|
|
||||||
seq_printf(p, " Rescheduling interrupts\n");
|
|
||||||
seq_printf(p, "CAL: ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ",
|
|
||||||
per_cpu(irq_stat,j).irq_call_count);
|
|
||||||
seq_printf(p, " Function call interrupts\n");
|
|
||||||
seq_printf(p, "TLB: ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ",
|
|
||||||
per_cpu(irq_stat,j).irq_tlb_count);
|
|
||||||
seq_printf(p, " TLB shootdowns\n");
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_X86_MCE
|
|
||||||
seq_printf(p, "TRM: ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ",
|
|
||||||
per_cpu(irq_stat,j).irq_thermal_count);
|
|
||||||
seq_printf(p, " Thermal event interrupts\n");
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_X86_LOCAL_APIC
|
|
||||||
seq_printf(p, "SPU: ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ",
|
|
||||||
per_cpu(irq_stat,j).irq_spurious_count);
|
|
||||||
seq_printf(p, " Spurious interrupts\n");
|
|
||||||
#endif
|
|
||||||
seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
|
|
||||||
#if defined(CONFIG_X86_IO_APIC)
|
|
||||||
seq_printf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* /proc/stat helpers
|
|
||||||
*/
|
|
||||||
u64 arch_irq_stat_cpu(unsigned int cpu)
|
|
||||||
{
|
|
||||||
u64 sum = nmi_count(cpu);
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_LOCAL_APIC
|
|
||||||
sum += per_cpu(irq_stat, cpu).apic_timer_irqs;
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
sum += per_cpu(irq_stat, cpu).irq_resched_count;
|
|
||||||
sum += per_cpu(irq_stat, cpu).irq_call_count;
|
|
||||||
sum += per_cpu(irq_stat, cpu).irq_tlb_count;
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_X86_MCE
|
|
||||||
sum += per_cpu(irq_stat, cpu).irq_thermal_count;
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_X86_LOCAL_APIC
|
|
||||||
sum += per_cpu(irq_stat, cpu).irq_spurious_count;
|
|
||||||
#endif
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 arch_irq_stat(void)
|
|
||||||
{
|
|
||||||
u64 sum = atomic_read(&irq_err_count);
|
|
||||||
|
|
||||||
#ifdef CONFIG_X86_IO_APIC
|
|
||||||
sum += atomic_read(&irq_mis_count);
|
|
||||||
#endif
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_HOTPLUG_CPU
|
#ifdef CONFIG_HOTPLUG_CPU
|
||||||
#include <mach_apic.h>
|
#include <mach_apic.h>
|
||||||
|
|
||||||
@@ -395,20 +237,22 @@ void fixup_irqs(cpumask_t map)
|
|||||||
{
|
{
|
||||||
unsigned int irq;
|
unsigned int irq;
|
||||||
static int warned;
|
static int warned;
|
||||||
|
struct irq_desc *desc;
|
||||||
|
|
||||||
for (irq = 0; irq < NR_IRQS; irq++) {
|
for_each_irq_desc(irq, desc) {
|
||||||
cpumask_t mask;
|
cpumask_t mask;
|
||||||
|
|
||||||
if (irq == 2)
|
if (irq == 2)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
cpus_and(mask, irq_desc[irq].affinity, map);
|
cpus_and(mask, desc->affinity, map);
|
||||||
if (any_online_cpu(mask) == NR_CPUS) {
|
if (any_online_cpu(mask) == NR_CPUS) {
|
||||||
printk("Breaking affinity for irq %i\n", irq);
|
printk("Breaking affinity for irq %i\n", irq);
|
||||||
mask = map;
|
mask = map;
|
||||||
}
|
}
|
||||||
if (irq_desc[irq].chip->set_affinity)
|
if (desc->chip->set_affinity)
|
||||||
irq_desc[irq].chip->set_affinity(irq, mask);
|
desc->chip->set_affinity(irq, mask);
|
||||||
else if (irq_desc[irq].action && !(warned++))
|
else if (desc->action && !(warned++))
|
||||||
printk("Cannot set affinity for irq %i\n", irq);
|
printk("Cannot set affinity for irq %i\n", irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,28 +18,6 @@
|
|||||||
#include <asm/idle.h>
|
#include <asm/idle.h>
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
|
|
||||||
atomic_t irq_err_count;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 'what should we do if we get a hw irq event on an illegal vector'.
|
|
||||||
* each architecture has to answer this themselves.
|
|
||||||
*/
|
|
||||||
void ack_bad_irq(unsigned int irq)
|
|
||||||
{
|
|
||||||
printk(KERN_WARNING "unexpected IRQ trap at vector %02x\n", irq);
|
|
||||||
/*
|
|
||||||
* Currently unexpected vectors happen only on SMP and APIC.
|
|
||||||
* We _must_ ack these because every local APIC has only N
|
|
||||||
* irq slots per priority level, and a 'hanging, unacked' IRQ
|
|
||||||
* holds up an irq slot - in excessive cases (when multiple
|
|
||||||
* unexpected vectors occur) that might lock up the APIC
|
|
||||||
* completely.
|
|
||||||
* But don't ack when the APIC is disabled. -AK
|
|
||||||
*/
|
|
||||||
if (!disable_apic)
|
|
||||||
ack_APIC_irq();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_STACKOVERFLOW
|
#ifdef CONFIG_DEBUG_STACKOVERFLOW
|
||||||
/*
|
/*
|
||||||
* Probabilistic stack overflow check:
|
* Probabilistic stack overflow check:
|
||||||
@@ -64,122 +42,6 @@ static inline void stack_overflow_check(struct pt_regs *regs)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Generic, controller-independent functions:
|
|
||||||
*/
|
|
||||||
|
|
||||||
int show_interrupts(struct seq_file *p, void *v)
|
|
||||||
{
|
|
||||||
int i = *(loff_t *) v, j;
|
|
||||||
struct irqaction * action;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (i == 0) {
|
|
||||||
seq_printf(p, " ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "CPU%-8d",j);
|
|
||||||
seq_putc(p, '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i < NR_IRQS) {
|
|
||||||
unsigned any_count = 0;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&irq_desc[i].lock, flags);
|
|
||||||
#ifndef CONFIG_SMP
|
|
||||||
any_count = kstat_irqs(i);
|
|
||||||
#else
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
any_count |= kstat_cpu(j).irqs[i];
|
|
||||||
#endif
|
|
||||||
action = irq_desc[i].action;
|
|
||||||
if (!action && !any_count)
|
|
||||||
goto skip;
|
|
||||||
seq_printf(p, "%3d: ",i);
|
|
||||||
#ifndef CONFIG_SMP
|
|
||||||
seq_printf(p, "%10u ", kstat_irqs(i));
|
|
||||||
#else
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
|
|
||||||
#endif
|
|
||||||
seq_printf(p, " %8s", irq_desc[i].chip->name);
|
|
||||||
seq_printf(p, "-%-8s", irq_desc[i].name);
|
|
||||||
|
|
||||||
if (action) {
|
|
||||||
seq_printf(p, " %s", action->name);
|
|
||||||
while ((action = action->next) != NULL)
|
|
||||||
seq_printf(p, ", %s", action->name);
|
|
||||||
}
|
|
||||||
seq_putc(p, '\n');
|
|
||||||
skip:
|
|
||||||
spin_unlock_irqrestore(&irq_desc[i].lock, flags);
|
|
||||||
} else if (i == NR_IRQS) {
|
|
||||||
seq_printf(p, "NMI: ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ", cpu_pda(j)->__nmi_count);
|
|
||||||
seq_printf(p, " Non-maskable interrupts\n");
|
|
||||||
seq_printf(p, "LOC: ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ", cpu_pda(j)->apic_timer_irqs);
|
|
||||||
seq_printf(p, " Local timer interrupts\n");
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
seq_printf(p, "RES: ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ", cpu_pda(j)->irq_resched_count);
|
|
||||||
seq_printf(p, " Rescheduling interrupts\n");
|
|
||||||
seq_printf(p, "CAL: ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ", cpu_pda(j)->irq_call_count);
|
|
||||||
seq_printf(p, " Function call interrupts\n");
|
|
||||||
seq_printf(p, "TLB: ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ", cpu_pda(j)->irq_tlb_count);
|
|
||||||
seq_printf(p, " TLB shootdowns\n");
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_X86_MCE
|
|
||||||
seq_printf(p, "TRM: ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ", cpu_pda(j)->irq_thermal_count);
|
|
||||||
seq_printf(p, " Thermal event interrupts\n");
|
|
||||||
seq_printf(p, "THR: ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ", cpu_pda(j)->irq_threshold_count);
|
|
||||||
seq_printf(p, " Threshold APIC interrupts\n");
|
|
||||||
#endif
|
|
||||||
seq_printf(p, "SPU: ");
|
|
||||||
for_each_online_cpu(j)
|
|
||||||
seq_printf(p, "%10u ", cpu_pda(j)->irq_spurious_count);
|
|
||||||
seq_printf(p, " Spurious interrupts\n");
|
|
||||||
seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* /proc/stat helpers
|
|
||||||
*/
|
|
||||||
u64 arch_irq_stat_cpu(unsigned int cpu)
|
|
||||||
{
|
|
||||||
u64 sum = cpu_pda(cpu)->__nmi_count;
|
|
||||||
|
|
||||||
sum += cpu_pda(cpu)->apic_timer_irqs;
|
|
||||||
#ifdef CONFIG_SMP
|
|
||||||
sum += cpu_pda(cpu)->irq_resched_count;
|
|
||||||
sum += cpu_pda(cpu)->irq_call_count;
|
|
||||||
sum += cpu_pda(cpu)->irq_tlb_count;
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_X86_MCE
|
|
||||||
sum += cpu_pda(cpu)->irq_thermal_count;
|
|
||||||
sum += cpu_pda(cpu)->irq_threshold_count;
|
|
||||||
#endif
|
|
||||||
sum += cpu_pda(cpu)->irq_spurious_count;
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 arch_irq_stat(void)
|
|
||||||
{
|
|
||||||
return atomic_read(&irq_err_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* do_IRQ handles all normal device IRQ's (the special
|
* do_IRQ handles all normal device IRQ's (the special
|
||||||
* SMP cross-CPU interrupts have their own specific
|
* SMP cross-CPU interrupts have their own specific
|
||||||
@@ -188,6 +50,7 @@ u64 arch_irq_stat(void)
|
|||||||
asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
|
asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct pt_regs *old_regs = set_irq_regs(regs);
|
struct pt_regs *old_regs = set_irq_regs(regs);
|
||||||
|
struct irq_desc *desc;
|
||||||
|
|
||||||
/* high bit used in ret_from_ code */
|
/* high bit used in ret_from_ code */
|
||||||
unsigned vector = ~regs->orig_ax;
|
unsigned vector = ~regs->orig_ax;
|
||||||
@@ -201,8 +64,9 @@ asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
|
|||||||
stack_overflow_check(regs);
|
stack_overflow_check(regs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (likely(irq < NR_IRQS))
|
desc = irq_to_desc(irq);
|
||||||
generic_handle_irq(irq);
|
if (likely(desc))
|
||||||
|
generic_handle_irq_desc(irq, desc);
|
||||||
else {
|
else {
|
||||||
if (!disable_apic)
|
if (!disable_apic)
|
||||||
ack_APIC_irq();
|
ack_APIC_irq();
|
||||||
@@ -223,8 +87,9 @@ void fixup_irqs(cpumask_t map)
|
|||||||
{
|
{
|
||||||
unsigned int irq;
|
unsigned int irq;
|
||||||
static int warned;
|
static int warned;
|
||||||
|
struct irq_desc *desc;
|
||||||
|
|
||||||
for (irq = 0; irq < NR_IRQS; irq++) {
|
for_each_irq_desc(irq, desc) {
|
||||||
cpumask_t mask;
|
cpumask_t mask;
|
||||||
int break_affinity = 0;
|
int break_affinity = 0;
|
||||||
int set_affinity = 1;
|
int set_affinity = 1;
|
||||||
@@ -233,32 +98,32 @@ void fixup_irqs(cpumask_t map)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* interrupt's are disabled at this point */
|
/* interrupt's are disabled at this point */
|
||||||
spin_lock(&irq_desc[irq].lock);
|
spin_lock(&desc->lock);
|
||||||
|
|
||||||
if (!irq_has_action(irq) ||
|
if (!irq_has_action(irq) ||
|
||||||
cpus_equal(irq_desc[irq].affinity, map)) {
|
cpus_equal(desc->affinity, map)) {
|
||||||
spin_unlock(&irq_desc[irq].lock);
|
spin_unlock(&desc->lock);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpus_and(mask, irq_desc[irq].affinity, map);
|
cpus_and(mask, desc->affinity, map);
|
||||||
if (cpus_empty(mask)) {
|
if (cpus_empty(mask)) {
|
||||||
break_affinity = 1;
|
break_affinity = 1;
|
||||||
mask = map;
|
mask = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (irq_desc[irq].chip->mask)
|
if (desc->chip->mask)
|
||||||
irq_desc[irq].chip->mask(irq);
|
desc->chip->mask(irq);
|
||||||
|
|
||||||
if (irq_desc[irq].chip->set_affinity)
|
if (desc->chip->set_affinity)
|
||||||
irq_desc[irq].chip->set_affinity(irq, mask);
|
desc->chip->set_affinity(irq, mask);
|
||||||
else if (!(warned++))
|
else if (!(warned++))
|
||||||
set_affinity = 0;
|
set_affinity = 0;
|
||||||
|
|
||||||
if (irq_desc[irq].chip->unmask)
|
if (desc->chip->unmask)
|
||||||
irq_desc[irq].chip->unmask(irq);
|
desc->chip->unmask(irq);
|
||||||
|
|
||||||
spin_unlock(&irq_desc[irq].lock);
|
spin_unlock(&desc->lock);
|
||||||
|
|
||||||
if (break_affinity && set_affinity)
|
if (break_affinity && set_affinity)
|
||||||
printk("Broke affinity for irq %i\n", irq);
|
printk("Broke affinity for irq %i\n", irq);
|
||||||
|
@@ -69,6 +69,13 @@ void __init init_ISA_irqs (void)
|
|||||||
* 16 old-style INTA-cycle interrupts:
|
* 16 old-style INTA-cycle interrupts:
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
|
/* first time call this irq_desc */
|
||||||
|
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,
|
set_irq_chip_and_handler_name(i, &i8259A_chip,
|
||||||
handle_level_irq, "XT");
|
handle_level_irq, "XT");
|
||||||
}
|
}
|
||||||
@@ -83,6 +90,27 @@ static struct irqaction irq2 = {
|
|||||||
.name = "cascade",
|
.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
|
||||||
|
};
|
||||||
|
|
||||||
/* Overridden in paravirt.c */
|
/* Overridden in paravirt.c */
|
||||||
void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
|
void init_IRQ(void) __attribute__((weak, alias("native_init_IRQ")));
|
||||||
|
|
||||||
@@ -98,22 +126,14 @@ void __init native_init_IRQ(void)
|
|||||||
* us. (some of these will be overridden and become
|
* us. (some of these will be overridden and become
|
||||||
* 'special' SMP interrupts)
|
* 'special' SMP interrupts)
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < (NR_VECTORS - FIRST_EXTERNAL_VECTOR); i++) {
|
for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) {
|
||||||
int vector = FIRST_EXTERNAL_VECTOR + i;
|
|
||||||
if (i >= NR_IRQS)
|
|
||||||
break;
|
|
||||||
/* SYSCALL_VECTOR was reserved in trap_init. */
|
/* SYSCALL_VECTOR was reserved in trap_init. */
|
||||||
if (!test_bit(vector, used_vectors))
|
if (i != SYSCALL_VECTOR)
|
||||||
set_intr_gate(vector, interrupt[i]);
|
set_intr_gate(i, interrupt[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_SMP)
|
|
||||||
/*
|
|
||||||
* IRQ0 must be given a fixed assignment and initialized,
|
|
||||||
* because it's used before the IO-APIC is set up.
|
|
||||||
*/
|
|
||||||
set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
|
|
||||||
|
|
||||||
|
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_SMP)
|
||||||
/*
|
/*
|
||||||
* 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.
|
||||||
@@ -128,6 +148,9 @@ void __init native_init_IRQ(void)
|
|||||||
|
|
||||||
/* IPI for single call function */
|
/* IPI for single call function */
|
||||||
set_intr_gate(CALL_FUNCTION_SINGLE_VECTOR, call_function_single_interrupt);
|
set_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);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_X86_LOCAL_APIC
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
|
@@ -142,23 +142,19 @@ void __init init_ISA_irqs(void)
|
|||||||
init_bsp_APIC();
|
init_bsp_APIC();
|
||||||
init_8259A(0);
|
init_8259A(0);
|
||||||
|
|
||||||
for (i = 0; i < NR_IRQS; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
irq_desc[i].status = IRQ_DISABLED;
|
/* first time call this irq_desc */
|
||||||
irq_desc[i].action = NULL;
|
struct irq_desc *desc = irq_to_desc(i);
|
||||||
irq_desc[i].depth = 1;
|
|
||||||
|
|
||||||
if (i < 16) {
|
desc->status = IRQ_DISABLED;
|
||||||
/*
|
desc->action = NULL;
|
||||||
* 16 old-style INTA-cycle interrupts:
|
desc->depth = 1;
|
||||||
*/
|
|
||||||
set_irq_chip_and_handler_name(i, &i8259A_chip,
|
/*
|
||||||
|
* 16 old-style INTA-cycle interrupts:
|
||||||
|
*/
|
||||||
|
set_irq_chip_and_handler_name(i, &i8259A_chip,
|
||||||
handle_level_irq, "XT");
|
handle_level_irq, "XT");
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* 'high' PCI IRQs filled in on demand
|
|
||||||
*/
|
|
||||||
irq_desc[i].chip = &no_irq_chip;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,9 +35,6 @@ static void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
|
|||||||
if (!(word & (1 << 13))) {
|
if (!(word & (1 << 13))) {
|
||||||
dev_info(&dev->dev, "Intel E7520/7320/7525 detected; "
|
dev_info(&dev->dev, "Intel E7520/7320/7525 detected; "
|
||||||
"disabling irq balancing and affinity\n");
|
"disabling irq balancing and affinity\n");
|
||||||
#ifdef CONFIG_IRQBALANCE
|
|
||||||
irqbalance_disable("");
|
|
||||||
#endif
|
|
||||||
noirqdebug_setup("");
|
noirqdebug_setup("");
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
no_irq_affinity = 1;
|
no_irq_affinity = 1;
|
||||||
|
@@ -1073,6 +1073,7 @@ void __init setup_arch(char **cmdline_p)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
prefill_possible_map();
|
prefill_possible_map();
|
||||||
|
|
||||||
#ifdef CONFIG_X86_64
|
#ifdef CONFIG_X86_64
|
||||||
init_cpu_to_node();
|
init_cpu_to_node();
|
||||||
#endif
|
#endif
|
||||||
@@ -1080,6 +1081,9 @@ void __init setup_arch(char **cmdline_p)
|
|||||||
init_apic_mappings();
|
init_apic_mappings();
|
||||||
ioapic_init_mappings();
|
ioapic_init_mappings();
|
||||||
|
|
||||||
|
/* need to wait for io_apic is mapped */
|
||||||
|
nr_irqs = probe_nr_irqs();
|
||||||
|
|
||||||
kvm_guest_init();
|
kvm_guest_init();
|
||||||
|
|
||||||
e820_reserve_resources();
|
e820_reserve_resources();
|
||||||
|
@@ -140,25 +140,30 @@ static void __init setup_cpu_pda_map(void)
|
|||||||
*/
|
*/
|
||||||
void __init setup_per_cpu_areas(void)
|
void __init setup_per_cpu_areas(void)
|
||||||
{
|
{
|
||||||
ssize_t size = PERCPU_ENOUGH_ROOM;
|
ssize_t size, old_size;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
int cpu;
|
int cpu;
|
||||||
|
unsigned long align = 1;
|
||||||
|
|
||||||
/* Setup cpu_pda map */
|
/* Setup cpu_pda map */
|
||||||
setup_cpu_pda_map();
|
setup_cpu_pda_map();
|
||||||
|
|
||||||
/* Copy section for each CPU (we discard the original) */
|
/* Copy section for each CPU (we discard the original) */
|
||||||
size = PERCPU_ENOUGH_ROOM;
|
old_size = PERCPU_ENOUGH_ROOM;
|
||||||
|
align = max_t(unsigned long, PAGE_SIZE, align);
|
||||||
|
size = roundup(old_size, align);
|
||||||
printk(KERN_INFO "PERCPU: Allocating %zd bytes of per cpu data\n",
|
printk(KERN_INFO "PERCPU: Allocating %zd bytes of per cpu data\n",
|
||||||
size);
|
size);
|
||||||
|
|
||||||
for_each_possible_cpu(cpu) {
|
for_each_possible_cpu(cpu) {
|
||||||
#ifndef CONFIG_NEED_MULTIPLE_NODES
|
#ifndef CONFIG_NEED_MULTIPLE_NODES
|
||||||
ptr = alloc_bootmem_pages(size);
|
ptr = __alloc_bootmem(size, align,
|
||||||
|
__pa(MAX_DMA_ADDRESS));
|
||||||
#else
|
#else
|
||||||
int node = early_cpu_to_node(cpu);
|
int node = early_cpu_to_node(cpu);
|
||||||
if (!node_online(node) || !NODE_DATA(node)) {
|
if (!node_online(node) || !NODE_DATA(node)) {
|
||||||
ptr = alloc_bootmem_pages(size);
|
ptr = __alloc_bootmem(size, align,
|
||||||
|
__pa(MAX_DMA_ADDRESS));
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO
|
||||||
"cpu %d has no node %d or node-local memory\n",
|
"cpu %d has no node %d or node-local memory\n",
|
||||||
cpu, node);
|
cpu, node);
|
||||||
@@ -167,7 +172,8 @@ void __init setup_per_cpu_areas(void)
|
|||||||
cpu, __pa(ptr));
|
cpu, __pa(ptr));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ptr = alloc_bootmem_pages_node(NODE_DATA(node), size);
|
ptr = __alloc_bootmem_node(NODE_DATA(node), size, align,
|
||||||
|
__pa(MAX_DMA_ADDRESS));
|
||||||
if (ptr)
|
if (ptr)
|
||||||
printk(KERN_DEBUG "per cpu data for cpu%d on node%d at %016lx\n",
|
printk(KERN_DEBUG "per cpu data for cpu%d on node%d at %016lx\n",
|
||||||
cpu, node, __pa(ptr));
|
cpu, node, __pa(ptr));
|
||||||
@@ -175,7 +181,6 @@ void __init setup_per_cpu_areas(void)
|
|||||||
#endif
|
#endif
|
||||||
per_cpu_offset(cpu) = ptr - __per_cpu_start;
|
per_cpu_offset(cpu) = ptr - __per_cpu_start;
|
||||||
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
|
memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(KERN_DEBUG "NR_CPUS: %d, nr_cpu_ids: %d, nr_node_ids %d\n",
|
printk(KERN_DEBUG "NR_CPUS: %d, nr_cpu_ids: %d, nr_node_ids %d\n",
|
||||||
|
@@ -543,10 +543,10 @@ static inline void __inquire_remote_apic(int apicid)
|
|||||||
int timeout;
|
int timeout;
|
||||||
u32 status;
|
u32 status;
|
||||||
|
|
||||||
printk(KERN_INFO "Inquiring remote APIC #%d...\n", apicid);
|
printk(KERN_INFO "Inquiring remote APIC 0x%x...\n", apicid);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(regs); i++) {
|
for (i = 0; i < ARRAY_SIZE(regs); i++) {
|
||||||
printk(KERN_INFO "... APIC #%d %s: ", apicid, names[i]);
|
printk(KERN_INFO "... APIC 0x%x %s: ", apicid, names[i]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for idle.
|
* Wait for idle.
|
||||||
@@ -874,7 +874,7 @@ do_rest:
|
|||||||
start_ip = setup_trampoline();
|
start_ip = setup_trampoline();
|
||||||
|
|
||||||
/* So we see what's up */
|
/* So we see what's up */
|
||||||
printk(KERN_INFO "Booting processor %d/%d ip %lx\n",
|
printk(KERN_INFO "Booting processor %d APIC 0x%x ip 0x%lx\n",
|
||||||
cpu, apicid, start_ip);
|
cpu, apicid, start_ip);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
79
arch/x86/kernel/uv_irq.c
Normal file
79
arch/x86/kernel/uv_irq.c
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* SGI UV IRQ functions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
|
|
||||||
|
#include <asm/apic.h>
|
||||||
|
#include <asm/uv/uv_irq.h>
|
||||||
|
|
||||||
|
static void uv_noop(unsigned int irq)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int uv_noop_ret(unsigned int irq)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uv_ack_apic(unsigned int irq)
|
||||||
|
{
|
||||||
|
ack_APIC_irq();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct irq_chip uv_irq_chip = {
|
||||||
|
.name = "UV-CORE",
|
||||||
|
.startup = uv_noop_ret,
|
||||||
|
.shutdown = uv_noop,
|
||||||
|
.enable = uv_noop,
|
||||||
|
.disable = uv_noop,
|
||||||
|
.ack = uv_noop,
|
||||||
|
.mask = uv_noop,
|
||||||
|
.unmask = uv_noop,
|
||||||
|
.eoi = uv_ack_apic,
|
||||||
|
.end = uv_noop,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up a mapping of an available irq and vector, and enable the specified
|
||||||
|
* MMR that defines the MSI that is to be sent to the specified CPU when an
|
||||||
|
* interrupt is raised.
|
||||||
|
*/
|
||||||
|
int uv_setup_irq(char *irq_name, int cpu, int mmr_blade,
|
||||||
|
unsigned long mmr_offset)
|
||||||
|
{
|
||||||
|
int irq;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
irq = create_irq();
|
||||||
|
if (irq <= 0)
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
ret = arch_enable_uv_irq(irq_name, irq, cpu, mmr_blade, mmr_offset);
|
||||||
|
if (ret != irq)
|
||||||
|
destroy_irq(irq);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(uv_setup_irq);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tear down a mapping of an irq and vector, and disable the specified MMR that
|
||||||
|
* defined the MSI that was to be sent to the specified CPU when an interrupt
|
||||||
|
* was raised.
|
||||||
|
*
|
||||||
|
* Set mmr_blade and mmr_offset to what was passed in on uv_setup_irq().
|
||||||
|
*/
|
||||||
|
void uv_teardown_irq(unsigned int irq, int mmr_blade, unsigned long mmr_offset)
|
||||||
|
{
|
||||||
|
arch_disable_uv_irq(mmr_blade, mmr_offset);
|
||||||
|
destroy_irq(irq);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(uv_teardown_irq);
|
72
arch/x86/kernel/uv_sysfs.c
Normal file
72
arch/x86/kernel/uv_sysfs.c
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* This file supports the /sys/firmware/sgi_uv interfaces for SGI UV.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved.
|
||||||
|
* Copyright (c) Russ Anderson
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/sysdev.h>
|
||||||
|
#include <asm/uv/bios.h>
|
||||||
|
|
||||||
|
struct kobject *sgi_uv_kobj;
|
||||||
|
|
||||||
|
static ssize_t partition_id_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
return snprintf(buf, PAGE_SIZE, "%ld\n", sn_partition_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t coherence_id_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
return snprintf(buf, PAGE_SIZE, "%ld\n", partition_coherence_id());
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute partition_id_attr =
|
||||||
|
__ATTR(partition_id, S_IRUGO, partition_id_show, NULL);
|
||||||
|
|
||||||
|
static struct kobj_attribute coherence_id_attr =
|
||||||
|
__ATTR(coherence_id, S_IRUGO, coherence_id_show, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
static int __init sgi_uv_sysfs_init(void)
|
||||||
|
{
|
||||||
|
unsigned long ret;
|
||||||
|
|
||||||
|
if (!sgi_uv_kobj)
|
||||||
|
sgi_uv_kobj = kobject_create_and_add("sgi_uv", firmware_kobj);
|
||||||
|
if (!sgi_uv_kobj) {
|
||||||
|
printk(KERN_WARNING "kobject_create_and_add sgi_uv failed \n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sysfs_create_file(sgi_uv_kobj, &partition_id_attr.attr);
|
||||||
|
if (ret) {
|
||||||
|
printk(KERN_WARNING "sysfs_create_file partition_id failed \n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = sysfs_create_file(sgi_uv_kobj, &coherence_id_attr.attr);
|
||||||
|
if (ret) {
|
||||||
|
printk(KERN_WARNING "sysfs_create_file coherence_id failed \n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_initcall(sgi_uv_sysfs_init);
|
@@ -484,10 +484,11 @@ static void disable_cobalt_irq(unsigned int irq)
|
|||||||
static unsigned int startup_cobalt_irq(unsigned int irq)
|
static unsigned int startup_cobalt_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
|
|
||||||
spin_lock_irqsave(&cobalt_lock, flags);
|
spin_lock_irqsave(&cobalt_lock, flags);
|
||||||
if ((irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING)))
|
if ((desc->status & (IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING)))
|
||||||
irq_desc[irq].status &= ~(IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING);
|
desc->status &= ~(IRQ_DISABLED | IRQ_INPROGRESS | IRQ_WAITING);
|
||||||
enable_cobalt_irq(irq);
|
enable_cobalt_irq(irq);
|
||||||
spin_unlock_irqrestore(&cobalt_lock, flags);
|
spin_unlock_irqrestore(&cobalt_lock, flags);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -506,9 +507,10 @@ static void ack_cobalt_irq(unsigned int irq)
|
|||||||
static void end_cobalt_irq(unsigned int irq)
|
static void end_cobalt_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
|
|
||||||
spin_lock_irqsave(&cobalt_lock, flags);
|
spin_lock_irqsave(&cobalt_lock, flags);
|
||||||
if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
|
if (!(desc->status & (IRQ_DISABLED | IRQ_INPROGRESS)))
|
||||||
enable_cobalt_irq(irq);
|
enable_cobalt_irq(irq);
|
||||||
spin_unlock_irqrestore(&cobalt_lock, flags);
|
spin_unlock_irqrestore(&cobalt_lock, flags);
|
||||||
}
|
}
|
||||||
@@ -626,12 +628,12 @@ static irqreturn_t piix4_master_intr(int irq, void *dev_id)
|
|||||||
|
|
||||||
spin_unlock_irqrestore(&i8259A_lock, flags);
|
spin_unlock_irqrestore(&i8259A_lock, flags);
|
||||||
|
|
||||||
desc = irq_desc + realirq;
|
desc = irq_to_desc(realirq);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* handle this 'virtual interrupt' as a Cobalt one now.
|
* handle this 'virtual interrupt' as a Cobalt one now.
|
||||||
*/
|
*/
|
||||||
kstat_cpu(smp_processor_id()).irqs[realirq]++;
|
kstat_incr_irqs_this_cpu(realirq, desc);
|
||||||
|
|
||||||
if (likely(desc->action != NULL))
|
if (likely(desc->action != NULL))
|
||||||
handle_IRQ_event(realirq, desc->action);
|
handle_IRQ_event(realirq, desc->action);
|
||||||
@@ -662,27 +664,29 @@ void init_VISWS_APIC_irqs(void)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < CO_IRQ_APIC0 + CO_APIC_LAST + 1; i++) {
|
for (i = 0; i < CO_IRQ_APIC0 + CO_APIC_LAST + 1; i++) {
|
||||||
irq_desc[i].status = IRQ_DISABLED;
|
struct irq_desc *desc = irq_to_desc(i);
|
||||||
irq_desc[i].action = 0;
|
|
||||||
irq_desc[i].depth = 1;
|
desc->status = IRQ_DISABLED;
|
||||||
|
desc->action = 0;
|
||||||
|
desc->depth = 1;
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
irq_desc[i].chip = &cobalt_irq_type;
|
desc->chip = &cobalt_irq_type;
|
||||||
}
|
}
|
||||||
else if (i == CO_IRQ_IDE0) {
|
else if (i == CO_IRQ_IDE0) {
|
||||||
irq_desc[i].chip = &cobalt_irq_type;
|
desc->chip = &cobalt_irq_type;
|
||||||
}
|
}
|
||||||
else if (i == CO_IRQ_IDE1) {
|
else if (i == CO_IRQ_IDE1) {
|
||||||
irq_desc[i].chip = &cobalt_irq_type;
|
desc->chip = &cobalt_irq_type;
|
||||||
}
|
}
|
||||||
else if (i == CO_IRQ_8259) {
|
else if (i == CO_IRQ_8259) {
|
||||||
irq_desc[i].chip = &piix4_master_irq_type;
|
desc->chip = &piix4_master_irq_type;
|
||||||
}
|
}
|
||||||
else if (i < CO_IRQ_APIC0) {
|
else if (i < CO_IRQ_APIC0) {
|
||||||
irq_desc[i].chip = &piix4_virtual_irq_type;
|
desc->chip = &piix4_virtual_irq_type;
|
||||||
}
|
}
|
||||||
else if (IS_CO_APIC(i)) {
|
else if (IS_CO_APIC(i)) {
|
||||||
irq_desc[i].chip = &cobalt_irq_type;
|
desc->chip = &cobalt_irq_type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -235,11 +235,14 @@ static void __devinit vmi_time_init_clockevent(void)
|
|||||||
|
|
||||||
void __init vmi_time_init(void)
|
void __init vmi_time_init(void)
|
||||||
{
|
{
|
||||||
|
unsigned int cpu;
|
||||||
/* Disable PIT: BIOSes start PIT CH0 with 18.2hz peridic. */
|
/* Disable PIT: BIOSes start PIT CH0 with 18.2hz peridic. */
|
||||||
outb_pit(0x3a, PIT_MODE); /* binary, mode 5, LSB/MSB, ch 0 */
|
outb_pit(0x3a, PIT_MODE); /* binary, mode 5, LSB/MSB, ch 0 */
|
||||||
|
|
||||||
vmi_time_init_clockevent();
|
vmi_time_init_clockevent();
|
||||||
setup_irq(0, &vmi_clock_action);
|
setup_irq(0, &vmi_clock_action);
|
||||||
|
for_each_possible_cpu(cpu)
|
||||||
|
per_cpu(vector_irq, cpu)[vmi_get_timer_vector()] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_LOCAL_APIC
|
#ifdef CONFIG_X86_LOCAL_APIC
|
||||||
|
@@ -582,7 +582,7 @@ static void __init lguest_init_IRQ(void)
|
|||||||
for (i = 0; i < LGUEST_IRQS; i++) {
|
for (i = 0; i < LGUEST_IRQS; i++) {
|
||||||
int vector = FIRST_EXTERNAL_VECTOR + i;
|
int vector = FIRST_EXTERNAL_VECTOR + i;
|
||||||
if (vector != SYSCALL_VECTOR) {
|
if (vector != SYSCALL_VECTOR) {
|
||||||
set_intr_gate(vector, interrupt[i]);
|
set_intr_gate(vector, interrupt[vector]);
|
||||||
set_irq_chip_and_handler_name(i, &lguest_irq_controller,
|
set_irq_chip_and_handler_name(i, &lguest_irq_controller,
|
||||||
handle_level_irq,
|
handle_level_irq,
|
||||||
"level");
|
"level");
|
||||||
|
@@ -41,6 +41,10 @@ static const struct dmi_system_id bigsmp_dmi_table[] = {
|
|||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static cpumask_t vector_allocation_domain(int cpu)
|
||||||
|
{
|
||||||
|
return cpumask_of_cpu(cpu);
|
||||||
|
}
|
||||||
|
|
||||||
static int probe_bigsmp(void)
|
static int probe_bigsmp(void)
|
||||||
{
|
{
|
||||||
|
@@ -75,4 +75,18 @@ static int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static cpumask_t vector_allocation_domain(int cpu)
|
||||||
|
{
|
||||||
|
/* Careful. Some cpus do not strictly honor the set of cpus
|
||||||
|
* specified in the interrupt destination when using lowest
|
||||||
|
* priority interrupt delivery mode.
|
||||||
|
*
|
||||||
|
* In particular there was a hyperthreading cpu observed to
|
||||||
|
* deliver interrupts to the wrong hyperthread when only one
|
||||||
|
* hyperthread was specified in the interrupt desitination.
|
||||||
|
*/
|
||||||
|
cpumask_t domain = { { [0] = APIC_ALL_CPUS, } };
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
struct genapic __initdata_refok apic_es7000 = APIC_INIT("es7000", probe_es7000);
|
struct genapic __initdata_refok apic_es7000 = APIC_INIT("es7000", probe_es7000);
|
||||||
|
@@ -38,4 +38,18 @@ static int acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cpumask_t vector_allocation_domain(int cpu)
|
||||||
|
{
|
||||||
|
/* Careful. Some cpus do not strictly honor the set of cpus
|
||||||
|
* specified in the interrupt destination when using lowest
|
||||||
|
* priority interrupt delivery mode.
|
||||||
|
*
|
||||||
|
* In particular there was a hyperthreading cpu observed to
|
||||||
|
* deliver interrupts to the wrong hyperthread when only one
|
||||||
|
* hyperthread was specified in the interrupt desitination.
|
||||||
|
*/
|
||||||
|
cpumask_t domain = { { [0] = APIC_ALL_CPUS, } };
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
struct genapic apic_numaq = APIC_INIT("NUMAQ", probe_numaq);
|
struct genapic apic_numaq = APIC_INIT("NUMAQ", probe_numaq);
|
||||||
|
@@ -23,4 +23,18 @@ static int probe_summit(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cpumask_t vector_allocation_domain(int cpu)
|
||||||
|
{
|
||||||
|
/* Careful. Some cpus do not strictly honor the set of cpus
|
||||||
|
* specified in the interrupt destination when using lowest
|
||||||
|
* priority interrupt delivery mode.
|
||||||
|
*
|
||||||
|
* In particular there was a hyperthreading cpu observed to
|
||||||
|
* deliver interrupts to the wrong hyperthread when only one
|
||||||
|
* hyperthread was specified in the interrupt desitination.
|
||||||
|
*/
|
||||||
|
cpumask_t domain = { { [0] = APIC_ALL_CPUS, } };
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
struct genapic apic_summit = APIC_INIT("summit", probe_summit);
|
struct genapic apic_summit = APIC_INIT("summit", probe_summit);
|
||||||
|
@@ -1483,7 +1483,7 @@ static void disable_local_vic_irq(unsigned int irq)
|
|||||||
* the interrupt off to another CPU */
|
* the interrupt off to another CPU */
|
||||||
static void before_handle_vic_irq(unsigned int irq)
|
static void before_handle_vic_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
irq_desc_t *desc = irq_desc + irq;
|
irq_desc_t *desc = irq_to_desc(irq);
|
||||||
__u8 cpu = smp_processor_id();
|
__u8 cpu = smp_processor_id();
|
||||||
|
|
||||||
_raw_spin_lock(&vic_irq_lock);
|
_raw_spin_lock(&vic_irq_lock);
|
||||||
@@ -1518,7 +1518,7 @@ static void before_handle_vic_irq(unsigned int irq)
|
|||||||
/* Finish the VIC interrupt: basically mask */
|
/* Finish the VIC interrupt: basically mask */
|
||||||
static void after_handle_vic_irq(unsigned int irq)
|
static void after_handle_vic_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
irq_desc_t *desc = irq_desc + irq;
|
irq_desc_t *desc = irq_to_desc(irq);
|
||||||
|
|
||||||
_raw_spin_lock(&vic_irq_lock);
|
_raw_spin_lock(&vic_irq_lock);
|
||||||
{
|
{
|
||||||
|
@@ -21,7 +21,6 @@ void xen_force_evtchn_callback(void)
|
|||||||
|
|
||||||
static void __init __xen_init_IRQ(void)
|
static void __init __xen_init_IRQ(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_X86_64
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Create identity vector->irq map */
|
/* Create identity vector->irq map */
|
||||||
@@ -31,7 +30,6 @@ static void __init __xen_init_IRQ(void)
|
|||||||
for_each_possible_cpu(cpu)
|
for_each_possible_cpu(cpu)
|
||||||
per_cpu(vector_irq, cpu)[i] = i;
|
per_cpu(vector_irq, cpu)[i] = i;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_X86_64 */
|
|
||||||
|
|
||||||
xen_init_IRQ();
|
xen_init_IRQ();
|
||||||
}
|
}
|
||||||
|
@@ -241,7 +241,7 @@ static noinline int xen_spin_lock_slow(struct raw_spinlock *lock, bool irq_enabl
|
|||||||
ADD_STATS(taken_slow_spurious, !xen_test_irq_pending(irq));
|
ADD_STATS(taken_slow_spurious, !xen_test_irq_pending(irq));
|
||||||
} while (!xen_test_irq_pending(irq)); /* check for spurious wakeups */
|
} while (!xen_test_irq_pending(irq)); /* check for spurious wakeups */
|
||||||
|
|
||||||
kstat_this_cpu.irqs[irq]++;
|
kstat_incr_irqs_this_cpu(irq, irq_to_desc(irq));
|
||||||
|
|
||||||
out:
|
out:
|
||||||
raw_local_irq_restore(flags);
|
raw_local_irq_restore(flags);
|
||||||
|
@@ -219,7 +219,7 @@ static void hpet_timer_set_irq(struct hpet_dev *devp)
|
|||||||
for (irq = find_first_bit(&v, HPET_MAX_IRQ); irq < HPET_MAX_IRQ;
|
for (irq = find_first_bit(&v, HPET_MAX_IRQ); irq < HPET_MAX_IRQ;
|
||||||
irq = find_next_bit(&v, HPET_MAX_IRQ, 1 + irq)) {
|
irq = find_next_bit(&v, HPET_MAX_IRQ, 1 + irq)) {
|
||||||
|
|
||||||
if (irq >= NR_IRQS) {
|
if (irq >= nr_irqs) {
|
||||||
irq = HPET_MAX_IRQ;
|
irq = HPET_MAX_IRQ;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -558,9 +558,26 @@ struct timer_rand_state {
|
|||||||
unsigned dont_count_entropy:1;
|
unsigned dont_count_entropy:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct timer_rand_state input_timer_state;
|
|
||||||
static struct timer_rand_state *irq_timer_state[NR_IRQS];
|
static struct timer_rand_state *irq_timer_state[NR_IRQS];
|
||||||
|
|
||||||
|
static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
|
||||||
|
{
|
||||||
|
if (irq >= nr_irqs)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return irq_timer_state[irq];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_timer_rand_state(unsigned int irq, struct timer_rand_state *state)
|
||||||
|
{
|
||||||
|
if (irq >= nr_irqs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
irq_timer_state[irq] = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct timer_rand_state input_timer_state;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function adds entropy to the entropy "pool" by using timing
|
* This function adds entropy to the entropy "pool" by using timing
|
||||||
* delays. It uses the timer_rand_state structure to make an estimate
|
* delays. It uses the timer_rand_state structure to make an estimate
|
||||||
@@ -648,11 +665,15 @@ EXPORT_SYMBOL_GPL(add_input_randomness);
|
|||||||
|
|
||||||
void add_interrupt_randomness(int irq)
|
void add_interrupt_randomness(int irq)
|
||||||
{
|
{
|
||||||
if (irq >= NR_IRQS || irq_timer_state[irq] == NULL)
|
struct timer_rand_state *state;
|
||||||
|
|
||||||
|
state = get_timer_rand_state(irq);
|
||||||
|
|
||||||
|
if (state == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DEBUG_ENT("irq event %d\n", irq);
|
DEBUG_ENT("irq event %d\n", irq);
|
||||||
add_timer_randomness(irq_timer_state[irq], 0x100 + irq);
|
add_timer_randomness(state, 0x100 + irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_BLOCK
|
#ifdef CONFIG_BLOCK
|
||||||
@@ -912,7 +933,12 @@ void rand_initialize_irq(int irq)
|
|||||||
{
|
{
|
||||||
struct timer_rand_state *state;
|
struct timer_rand_state *state;
|
||||||
|
|
||||||
if (irq >= NR_IRQS || irq_timer_state[irq])
|
if (irq >= nr_irqs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
state = get_timer_rand_state(irq);
|
||||||
|
|
||||||
|
if (state)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -921,7 +947,7 @@ void rand_initialize_irq(int irq)
|
|||||||
*/
|
*/
|
||||||
state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL);
|
state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL);
|
||||||
if (state)
|
if (state)
|
||||||
irq_timer_state[irq] = state;
|
set_timer_rand_state(irq, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_BLOCK
|
#ifdef CONFIG_BLOCK
|
||||||
|
@@ -641,7 +641,7 @@ static int __devinit giu_probe(struct platform_device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
irq = platform_get_irq(dev, 0);
|
irq = platform_get_irq(dev, 0);
|
||||||
if (irq < 0 || irq >= NR_IRQS)
|
if (irq < 0 || irq >= nr_irqs)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
return cascade_irq(irq, giu_get_irq);
|
return cascade_irq(irq, giu_get_irq);
|
||||||
|
@@ -1143,7 +1143,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
|||||||
|
|
||||||
if (!is_out) {
|
if (!is_out) {
|
||||||
int irq = gpio_to_irq(gpio);
|
int irq = gpio_to_irq(gpio);
|
||||||
struct irq_desc *desc = irq_desc + irq;
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
|
|
||||||
/* This races with request_irq(), set_irq_type(),
|
/* This races with request_irq(), set_irq_type(),
|
||||||
* and set_irq_wake() ... but those are "rare".
|
* and set_irq_wake() ... but those are "rare".
|
||||||
|
@@ -123,7 +123,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc)
|
|||||||
irqnr = asic->irq_base +
|
irqnr = asic->irq_base +
|
||||||
(ASIC3_GPIOS_PER_BANK * bank)
|
(ASIC3_GPIOS_PER_BANK * bank)
|
||||||
+ i;
|
+ i;
|
||||||
desc = irq_desc + irqnr;
|
desc = irq_to_desc(irqnr);
|
||||||
desc->handle_irq(irqnr, desc);
|
desc->handle_irq(irqnr, desc);
|
||||||
if (asic->irq_bothedge[bank] & bit)
|
if (asic->irq_bothedge[bank] & bit)
|
||||||
asic3_irq_flip_edge(asic, base,
|
asic3_irq_flip_edge(asic, base,
|
||||||
@@ -136,7 +136,7 @@ static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc)
|
|||||||
for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) {
|
for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) {
|
||||||
/* They start at bit 4 and go up */
|
/* They start at bit 4 and go up */
|
||||||
if (status & (1 << (i - ASIC3_NUM_GPIOS + 4))) {
|
if (status & (1 << (i - ASIC3_NUM_GPIOS + 4))) {
|
||||||
desc = irq_desc + asic->irq_base + i;
|
desc = irq_to_desc(asic->irq_base + i);
|
||||||
desc->handle_irq(asic->irq_base + i,
|
desc->handle_irq(asic->irq_base + i,
|
||||||
desc);
|
desc);
|
||||||
}
|
}
|
||||||
|
@@ -112,7 +112,7 @@ static void egpio_handler(unsigned int irq, struct irq_desc *desc)
|
|||||||
/* Run irq handler */
|
/* Run irq handler */
|
||||||
pr_debug("got IRQ %d\n", irqpin);
|
pr_debug("got IRQ %d\n", irqpin);
|
||||||
irq = ei->irq_start + irqpin;
|
irq = ei->irq_start + irqpin;
|
||||||
desc = &irq_desc[irq];
|
desc = irq_to_desc(irq);
|
||||||
desc->handle_irq(irq, desc);
|
desc->handle_irq(irq, desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -90,7 +90,7 @@ static int vortex_debug = 1;
|
|||||||
#include <linux/eisa.h>
|
#include <linux/eisa.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <asm/irq.h> /* For NR_IRQS only. */
|
#include <asm/irq.h> /* For nr_irqs only. */
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
@@ -1221,7 +1221,7 @@ static int __devinit vortex_probe1(struct device *gendev,
|
|||||||
if (print_info)
|
if (print_info)
|
||||||
printk(", IRQ %d\n", dev->irq);
|
printk(", IRQ %d\n", dev->irq);
|
||||||
/* Tell them about an invalid IRQ. */
|
/* Tell them about an invalid IRQ. */
|
||||||
if (dev->irq <= 0 || dev->irq >= NR_IRQS)
|
if (dev->irq <= 0 || dev->irq >= nr_irqs)
|
||||||
printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n",
|
printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n",
|
||||||
dev->irq);
|
dev->irq);
|
||||||
|
|
||||||
|
@@ -416,10 +416,10 @@ static int ser12_open(struct net_device *dev)
|
|||||||
if (!dev || !bc)
|
if (!dev || !bc)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
if (!dev->base_addr || dev->base_addr > 0xffff-SER12_EXTENT ||
|
if (!dev->base_addr || dev->base_addr > 0xffff-SER12_EXTENT ||
|
||||||
dev->irq < 2 || dev->irq > NR_IRQS) {
|
dev->irq < 2 || dev->irq > nr_irqs) {
|
||||||
printk(KERN_INFO "baycom_ser_fdx: invalid portnumber (max %u) "
|
printk(KERN_INFO "baycom_ser_fdx: invalid portnumber (max %u) "
|
||||||
"or irq (2 <= irq <= %d)\n",
|
"or irq (2 <= irq <= %d)\n",
|
||||||
0xffff-SER12_EXTENT, NR_IRQS);
|
0xffff-SER12_EXTENT, nr_irqs);
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
if (bc->baud < 300 || bc->baud > 4800) {
|
if (bc->baud < 300 || bc->baud > 4800) {
|
||||||
|
@@ -1465,7 +1465,7 @@ static void z8530_init(void)
|
|||||||
printk(KERN_INFO "Init Z8530 driver: %u channels, IRQ", Nchips*2);
|
printk(KERN_INFO "Init Z8530 driver: %u channels, IRQ", Nchips*2);
|
||||||
|
|
||||||
flag=" ";
|
flag=" ";
|
||||||
for (k = 0; k < NR_IRQS; k++)
|
for (k = 0; k < nr_irqs; k++)
|
||||||
if (Ivec[k].used)
|
if (Ivec[k].used)
|
||||||
{
|
{
|
||||||
printk("%s%d", flag, k);
|
printk("%s%d", flag, k);
|
||||||
@@ -1728,7 +1728,7 @@ static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
|
|||||||
|
|
||||||
if (hwcfg.irq == 2) hwcfg.irq = 9;
|
if (hwcfg.irq == 2) hwcfg.irq = 9;
|
||||||
|
|
||||||
if (hwcfg.irq < 0 || hwcfg.irq >= NR_IRQS)
|
if (hwcfg.irq < 0 || hwcfg.irq >= nr_irqs)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!Ivec[hwcfg.irq].used && hwcfg.irq)
|
if (!Ivec[hwcfg.irq].used && hwcfg.irq)
|
||||||
@@ -2148,7 +2148,7 @@ static void __exit scc_cleanup_driver(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* To unload the port must be closed so no real IRQ pending */
|
/* To unload the port must be closed so no real IRQ pending */
|
||||||
for (k=0; k < NR_IRQS ; k++)
|
for (k = 0; k < nr_irqs ; k++)
|
||||||
if (Ivec[k].used) free_irq(k, NULL);
|
if (Ivec[k].used) free_irq(k, NULL);
|
||||||
|
|
||||||
local_irq_enable();
|
local_irq_enable();
|
||||||
|
@@ -318,7 +318,7 @@ sbni_pci_probe( struct net_device *dev )
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( pci_irq_line <= 0 || pci_irq_line >= NR_IRQS )
|
if (pci_irq_line <= 0 || pci_irq_line >= nr_irqs)
|
||||||
printk( KERN_WARNING " WARNING: The PCI BIOS assigned "
|
printk( KERN_WARNING " WARNING: The PCI BIOS assigned "
|
||||||
"this PCI card to IRQ %d, which is unlikely "
|
"this PCI card to IRQ %d, which is unlikely "
|
||||||
"to work!.\n"
|
"to work!.\n"
|
||||||
|
@@ -298,7 +298,8 @@ struct pci_port_ops dino_port_ops = {
|
|||||||
|
|
||||||
static void dino_disable_irq(unsigned int irq)
|
static void dino_disable_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
struct dino_device *dino_dev = irq_desc[irq].chip_data;
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
|
struct dino_device *dino_dev = desc->chip_data;
|
||||||
int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
|
int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
|
||||||
|
|
||||||
DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, irq);
|
DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, irq);
|
||||||
@@ -310,7 +311,8 @@ static void dino_disable_irq(unsigned int irq)
|
|||||||
|
|
||||||
static void dino_enable_irq(unsigned int irq)
|
static void dino_enable_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
struct dino_device *dino_dev = irq_desc[irq].chip_data;
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
|
struct dino_device *dino_dev = desc->chip_data;
|
||||||
int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
|
int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
|
||||||
u32 tmp;
|
u32 tmp;
|
||||||
|
|
||||||
|
@@ -346,10 +346,10 @@ static int __init eisa_probe(struct parisc_device *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Reserve IRQ2 */
|
/* Reserve IRQ2 */
|
||||||
irq_desc[2].action = &irq2_action;
|
irq_to_desc(2)->action = &irq2_action;
|
||||||
|
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
irq_desc[i].chip = &eisa_interrupt_type;
|
irq_to_desc(i)->chip = &eisa_interrupt_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
EISA_bus = 1;
|
EISA_bus = 1;
|
||||||
|
@@ -108,7 +108,8 @@ int gsc_find_local_irq(unsigned int irq, int *global_irqs, int limit)
|
|||||||
|
|
||||||
static void gsc_asic_disable_irq(unsigned int irq)
|
static void gsc_asic_disable_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
struct gsc_asic *irq_dev = irq_desc[irq].chip_data;
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
|
struct gsc_asic *irq_dev = desc->chip_data;
|
||||||
int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
|
int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
|
||||||
u32 imr;
|
u32 imr;
|
||||||
|
|
||||||
@@ -123,7 +124,8 @@ static void gsc_asic_disable_irq(unsigned int irq)
|
|||||||
|
|
||||||
static void gsc_asic_enable_irq(unsigned int irq)
|
static void gsc_asic_enable_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
struct gsc_asic *irq_dev = irq_desc[irq].chip_data;
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
|
struct gsc_asic *irq_dev = desc->chip_data;
|
||||||
int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
|
int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
|
||||||
u32 imr;
|
u32 imr;
|
||||||
|
|
||||||
@@ -159,12 +161,14 @@ static struct hw_interrupt_type gsc_asic_interrupt_type = {
|
|||||||
int gsc_assign_irq(struct hw_interrupt_type *type, void *data)
|
int gsc_assign_irq(struct hw_interrupt_type *type, void *data)
|
||||||
{
|
{
|
||||||
static int irq = GSC_IRQ_BASE;
|
static int irq = GSC_IRQ_BASE;
|
||||||
|
struct irq_desc *desc;
|
||||||
|
|
||||||
if (irq > GSC_IRQ_MAX)
|
if (irq > GSC_IRQ_MAX)
|
||||||
return NO_IRQ;
|
return NO_IRQ;
|
||||||
|
|
||||||
irq_desc[irq].chip = type;
|
desc = irq_to_desc(irq);
|
||||||
irq_desc[irq].chip_data = data;
|
desc->chip = type;
|
||||||
|
desc->chip_data = data;
|
||||||
return irq++;
|
return irq++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -619,7 +619,9 @@ iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1)
|
|||||||
|
|
||||||
static struct vector_info *iosapic_get_vector(unsigned int irq)
|
static struct vector_info *iosapic_get_vector(unsigned int irq)
|
||||||
{
|
{
|
||||||
return irq_desc[irq].chip_data;
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
|
|
||||||
|
return desc->chip_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iosapic_disable_irq(unsigned int irq)
|
static void iosapic_disable_irq(unsigned int irq)
|
||||||
|
@@ -363,7 +363,9 @@ int superio_fixup_irq(struct pci_dev *pcidev)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
irq_desc[i].chip = &superio_interrupt_type;
|
struct irq_desc *desc = irq_to_desc(i);
|
||||||
|
|
||||||
|
desc->chip = &superio_interrupt_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -193,7 +193,7 @@ dmar_parse_dev(struct dmar_drhd_unit *dmaru)
|
|||||||
{
|
{
|
||||||
struct acpi_dmar_hardware_unit *drhd;
|
struct acpi_dmar_hardware_unit *drhd;
|
||||||
static int include_all;
|
static int include_all;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
|
||||||
drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
|
drhd = (struct acpi_dmar_hardware_unit *) dmaru->hdr;
|
||||||
|
|
||||||
@@ -212,7 +212,7 @@ dmar_parse_dev(struct dmar_drhd_unit *dmaru)
|
|||||||
include_all = 1;
|
include_all = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret || (dmaru->devices_cnt == 0 && !dmaru->include_all)) {
|
if (ret) {
|
||||||
list_del(&dmaru->list);
|
list_del(&dmaru->list);
|
||||||
kfree(dmaru);
|
kfree(dmaru);
|
||||||
}
|
}
|
||||||
@@ -289,6 +289,24 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dmar_table_detect - checks to see if the platform supports DMAR devices
|
||||||
|
*/
|
||||||
|
static int __init dmar_table_detect(void)
|
||||||
|
{
|
||||||
|
acpi_status status = AE_OK;
|
||||||
|
|
||||||
|
/* if we could find DMAR table, then there are DMAR devices */
|
||||||
|
status = acpi_get_table(ACPI_SIG_DMAR, 0,
|
||||||
|
(struct acpi_table_header **)&dmar_tbl);
|
||||||
|
|
||||||
|
if (ACPI_SUCCESS(status) && !dmar_tbl) {
|
||||||
|
printk (KERN_WARNING PREFIX "Unable to map DMAR\n");
|
||||||
|
status = AE_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ACPI_SUCCESS(status) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* parse_dmar_table - parses the DMA reporting table
|
* parse_dmar_table - parses the DMA reporting table
|
||||||
@@ -300,6 +318,12 @@ parse_dmar_table(void)
|
|||||||
struct acpi_dmar_header *entry_header;
|
struct acpi_dmar_header *entry_header;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do it again, earlier dmar_tbl mapping could be mapped with
|
||||||
|
* fixed map.
|
||||||
|
*/
|
||||||
|
dmar_table_detect();
|
||||||
|
|
||||||
dmar = (struct acpi_table_dmar *)dmar_tbl;
|
dmar = (struct acpi_table_dmar *)dmar_tbl;
|
||||||
if (!dmar)
|
if (!dmar)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
@@ -373,10 +397,10 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev)
|
|||||||
|
|
||||||
int __init dmar_dev_scope_init(void)
|
int __init dmar_dev_scope_init(void)
|
||||||
{
|
{
|
||||||
struct dmar_drhd_unit *drhd;
|
struct dmar_drhd_unit *drhd, *drhd_n;
|
||||||
int ret = -ENODEV;
|
int ret = -ENODEV;
|
||||||
|
|
||||||
for_each_drhd_unit(drhd) {
|
list_for_each_entry_safe(drhd, drhd_n, &dmar_drhd_units, list) {
|
||||||
ret = dmar_parse_dev(drhd);
|
ret = dmar_parse_dev(drhd);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -384,8 +408,8 @@ int __init dmar_dev_scope_init(void)
|
|||||||
|
|
||||||
#ifdef CONFIG_DMAR
|
#ifdef CONFIG_DMAR
|
||||||
{
|
{
|
||||||
struct dmar_rmrr_unit *rmrr;
|
struct dmar_rmrr_unit *rmrr, *rmrr_n;
|
||||||
for_each_rmrr_units(rmrr) {
|
list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) {
|
||||||
ret = rmrr_parse_dev(rmrr);
|
ret = rmrr_parse_dev(rmrr);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -430,30 +454,11 @@ int __init dmar_table_init(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* early_dmar_detect - checks to see if the platform supports DMAR devices
|
|
||||||
*/
|
|
||||||
int __init early_dmar_detect(void)
|
|
||||||
{
|
|
||||||
acpi_status status = AE_OK;
|
|
||||||
|
|
||||||
/* if we could find DMAR table, then there are DMAR devices */
|
|
||||||
status = acpi_get_table(ACPI_SIG_DMAR, 0,
|
|
||||||
(struct acpi_table_header **)&dmar_tbl);
|
|
||||||
|
|
||||||
if (ACPI_SUCCESS(status) && !dmar_tbl) {
|
|
||||||
printk (KERN_WARNING PREFIX "Unable to map DMAR\n");
|
|
||||||
status = AE_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ACPI_SUCCESS(status) ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void __init detect_intel_iommu(void)
|
void __init detect_intel_iommu(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = early_dmar_detect();
|
ret = dmar_table_detect();
|
||||||
|
|
||||||
#ifdef CONFIG_DMAR
|
#ifdef CONFIG_DMAR
|
||||||
{
|
{
|
||||||
@@ -479,14 +484,16 @@ void __init detect_intel_iommu(void)
|
|||||||
" x2apic support\n");
|
" x2apic support\n");
|
||||||
|
|
||||||
dmar_disabled = 1;
|
dmar_disabled = 1;
|
||||||
return;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret && !no_iommu && !iommu_detected && !swiotlb &&
|
if (ret && !no_iommu && !iommu_detected && !swiotlb &&
|
||||||
!dmar_disabled)
|
!dmar_disabled)
|
||||||
iommu_detected = 1;
|
iommu_detected = 1;
|
||||||
}
|
}
|
||||||
|
end:
|
||||||
#endif
|
#endif
|
||||||
|
dmar_tbl = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -126,7 +126,8 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)
|
|||||||
cfg->msg.address_hi = 0xffffffff;
|
cfg->msg.address_hi = 0xffffffff;
|
||||||
|
|
||||||
irq = create_irq();
|
irq = create_irq();
|
||||||
if (irq < 0) {
|
|
||||||
|
if (irq <= 0) {
|
||||||
kfree(cfg);
|
kfree(cfg);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#include <linux/interrupt.h>
|
||||||
#include <linux/dmar.h>
|
#include <linux/dmar.h>
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
@@ -11,41 +12,64 @@ 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 struct {
|
struct irq_2_iommu {
|
||||||
struct intel_iommu *iommu;
|
struct intel_iommu *iommu;
|
||||||
u16 irte_index;
|
u16 irte_index;
|
||||||
u16 sub_handle;
|
u16 sub_handle;
|
||||||
u8 irte_mask;
|
u8 irte_mask;
|
||||||
} irq_2_iommu[NR_IRQS];
|
};
|
||||||
|
|
||||||
|
static struct irq_2_iommu irq_2_iommuX[NR_IRQS];
|
||||||
|
|
||||||
|
static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
|
||||||
|
{
|
||||||
|
return (irq < nr_irqs) ? irq_2_iommuX + irq : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
|
||||||
|
{
|
||||||
|
return irq_2_iommu(irq);
|
||||||
|
}
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(irq_2_ir_lock);
|
static DEFINE_SPINLOCK(irq_2_ir_lock);
|
||||||
|
|
||||||
|
static struct irq_2_iommu *valid_irq_2_iommu(unsigned int irq)
|
||||||
|
{
|
||||||
|
struct irq_2_iommu *irq_iommu;
|
||||||
|
|
||||||
|
irq_iommu = irq_2_iommu(irq);
|
||||||
|
|
||||||
|
if (!irq_iommu)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!irq_iommu->iommu)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return irq_iommu;
|
||||||
|
}
|
||||||
|
|
||||||
int irq_remapped(int irq)
|
int irq_remapped(int irq)
|
||||||
{
|
{
|
||||||
if (irq > NR_IRQS)
|
return valid_irq_2_iommu(irq) != NULL;
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!irq_2_iommu[irq].iommu)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_irte(int irq, struct irte *entry)
|
int get_irte(int irq, struct irte *entry)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
struct irq_2_iommu *irq_iommu;
|
||||||
|
|
||||||
if (!entry || irq > NR_IRQS)
|
if (!entry)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
spin_lock(&irq_2_ir_lock);
|
spin_lock(&irq_2_ir_lock);
|
||||||
if (!irq_2_iommu[irq].iommu) {
|
irq_iommu = valid_irq_2_iommu(irq);
|
||||||
|
if (!irq_iommu) {
|
||||||
spin_unlock(&irq_2_ir_lock);
|
spin_unlock(&irq_2_ir_lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
|
index = irq_iommu->irte_index + irq_iommu->sub_handle;
|
||||||
*entry = *(irq_2_iommu[irq].iommu->ir_table->base + index);
|
*entry = *(irq_iommu->iommu->ir_table->base + index);
|
||||||
|
|
||||||
spin_unlock(&irq_2_ir_lock);
|
spin_unlock(&irq_2_ir_lock);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -54,6 +78,7 @@ int get_irte(int irq, struct irte *entry)
|
|||||||
int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
|
int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
|
||||||
{
|
{
|
||||||
struct ir_table *table = iommu->ir_table;
|
struct ir_table *table = iommu->ir_table;
|
||||||
|
struct irq_2_iommu *irq_iommu;
|
||||||
u16 index, start_index;
|
u16 index, start_index;
|
||||||
unsigned int mask = 0;
|
unsigned int mask = 0;
|
||||||
int i;
|
int i;
|
||||||
@@ -61,6 +86,10 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
|
|||||||
if (!count)
|
if (!count)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/* protect irq_2_iommu_alloc later */
|
||||||
|
if (irq >= nr_irqs)
|
||||||
|
return -1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* start the IRTE search from index 0.
|
* start the IRTE search from index 0.
|
||||||
*/
|
*/
|
||||||
@@ -100,10 +129,11 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
|
|||||||
for (i = index; i < index + count; i++)
|
for (i = index; i < index + count; i++)
|
||||||
table->base[i].present = 1;
|
table->base[i].present = 1;
|
||||||
|
|
||||||
irq_2_iommu[irq].iommu = iommu;
|
irq_iommu = irq_2_iommu_alloc(irq);
|
||||||
irq_2_iommu[irq].irte_index = index;
|
irq_iommu->iommu = iommu;
|
||||||
irq_2_iommu[irq].sub_handle = 0;
|
irq_iommu->irte_index = index;
|
||||||
irq_2_iommu[irq].irte_mask = mask;
|
irq_iommu->sub_handle = 0;
|
||||||
|
irq_iommu->irte_mask = mask;
|
||||||
|
|
||||||
spin_unlock(&irq_2_ir_lock);
|
spin_unlock(&irq_2_ir_lock);
|
||||||
|
|
||||||
@@ -124,31 +154,33 @@ static void qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
|
|||||||
int map_irq_to_irte_handle(int irq, u16 *sub_handle)
|
int map_irq_to_irte_handle(int irq, u16 *sub_handle)
|
||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
|
struct irq_2_iommu *irq_iommu;
|
||||||
|
|
||||||
spin_lock(&irq_2_ir_lock);
|
spin_lock(&irq_2_ir_lock);
|
||||||
if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
|
irq_iommu = valid_irq_2_iommu(irq);
|
||||||
|
if (!irq_iommu) {
|
||||||
spin_unlock(&irq_2_ir_lock);
|
spin_unlock(&irq_2_ir_lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*sub_handle = irq_2_iommu[irq].sub_handle;
|
*sub_handle = irq_iommu->sub_handle;
|
||||||
index = irq_2_iommu[irq].irte_index;
|
index = irq_iommu->irte_index;
|
||||||
spin_unlock(&irq_2_ir_lock);
|
spin_unlock(&irq_2_ir_lock);
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
|
int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
|
||||||
{
|
{
|
||||||
spin_lock(&irq_2_ir_lock);
|
struct irq_2_iommu *irq_iommu;
|
||||||
if (irq >= NR_IRQS || irq_2_iommu[irq].iommu) {
|
|
||||||
spin_unlock(&irq_2_ir_lock);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
irq_2_iommu[irq].iommu = iommu;
|
spin_lock(&irq_2_ir_lock);
|
||||||
irq_2_iommu[irq].irte_index = index;
|
|
||||||
irq_2_iommu[irq].sub_handle = subhandle;
|
irq_iommu = irq_2_iommu_alloc(irq);
|
||||||
irq_2_iommu[irq].irte_mask = 0;
|
|
||||||
|
irq_iommu->iommu = iommu;
|
||||||
|
irq_iommu->irte_index = index;
|
||||||
|
irq_iommu->sub_handle = subhandle;
|
||||||
|
irq_iommu->irte_mask = 0;
|
||||||
|
|
||||||
spin_unlock(&irq_2_ir_lock);
|
spin_unlock(&irq_2_ir_lock);
|
||||||
|
|
||||||
@@ -157,16 +189,19 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
|
|||||||
|
|
||||||
int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
|
int clear_irte_irq(int irq, struct intel_iommu *iommu, u16 index)
|
||||||
{
|
{
|
||||||
|
struct irq_2_iommu *irq_iommu;
|
||||||
|
|
||||||
spin_lock(&irq_2_ir_lock);
|
spin_lock(&irq_2_ir_lock);
|
||||||
if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
|
irq_iommu = valid_irq_2_iommu(irq);
|
||||||
|
if (!irq_iommu) {
|
||||||
spin_unlock(&irq_2_ir_lock);
|
spin_unlock(&irq_2_ir_lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
irq_2_iommu[irq].iommu = NULL;
|
irq_iommu->iommu = NULL;
|
||||||
irq_2_iommu[irq].irte_index = 0;
|
irq_iommu->irte_index = 0;
|
||||||
irq_2_iommu[irq].sub_handle = 0;
|
irq_iommu->sub_handle = 0;
|
||||||
irq_2_iommu[irq].irte_mask = 0;
|
irq_2_iommu(irq)->irte_mask = 0;
|
||||||
|
|
||||||
spin_unlock(&irq_2_ir_lock);
|
spin_unlock(&irq_2_ir_lock);
|
||||||
|
|
||||||
@@ -178,16 +213,18 @@ int modify_irte(int irq, struct irte *irte_modified)
|
|||||||
int index;
|
int index;
|
||||||
struct irte *irte;
|
struct irte *irte;
|
||||||
struct intel_iommu *iommu;
|
struct intel_iommu *iommu;
|
||||||
|
struct irq_2_iommu *irq_iommu;
|
||||||
|
|
||||||
spin_lock(&irq_2_ir_lock);
|
spin_lock(&irq_2_ir_lock);
|
||||||
if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
|
irq_iommu = valid_irq_2_iommu(irq);
|
||||||
|
if (!irq_iommu) {
|
||||||
spin_unlock(&irq_2_ir_lock);
|
spin_unlock(&irq_2_ir_lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
iommu = irq_2_iommu[irq].iommu;
|
iommu = irq_iommu->iommu;
|
||||||
|
|
||||||
index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
|
index = irq_iommu->irte_index + irq_iommu->sub_handle;
|
||||||
irte = &iommu->ir_table->base[index];
|
irte = &iommu->ir_table->base[index];
|
||||||
|
|
||||||
set_64bit((unsigned long *)irte, irte_modified->low | (1 << 1));
|
set_64bit((unsigned long *)irte, irte_modified->low | (1 << 1));
|
||||||
@@ -203,18 +240,20 @@ int flush_irte(int irq)
|
|||||||
{
|
{
|
||||||
int index;
|
int index;
|
||||||
struct intel_iommu *iommu;
|
struct intel_iommu *iommu;
|
||||||
|
struct irq_2_iommu *irq_iommu;
|
||||||
|
|
||||||
spin_lock(&irq_2_ir_lock);
|
spin_lock(&irq_2_ir_lock);
|
||||||
if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
|
irq_iommu = valid_irq_2_iommu(irq);
|
||||||
|
if (!irq_iommu) {
|
||||||
spin_unlock(&irq_2_ir_lock);
|
spin_unlock(&irq_2_ir_lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
iommu = irq_2_iommu[irq].iommu;
|
iommu = irq_iommu->iommu;
|
||||||
|
|
||||||
index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
|
index = irq_iommu->irte_index + irq_iommu->sub_handle;
|
||||||
|
|
||||||
qi_flush_iec(iommu, index, irq_2_iommu[irq].irte_mask);
|
qi_flush_iec(iommu, index, irq_iommu->irte_mask);
|
||||||
spin_unlock(&irq_2_ir_lock);
|
spin_unlock(&irq_2_ir_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -246,28 +285,30 @@ int free_irte(int irq)
|
|||||||
int index, i;
|
int index, i;
|
||||||
struct irte *irte;
|
struct irte *irte;
|
||||||
struct intel_iommu *iommu;
|
struct intel_iommu *iommu;
|
||||||
|
struct irq_2_iommu *irq_iommu;
|
||||||
|
|
||||||
spin_lock(&irq_2_ir_lock);
|
spin_lock(&irq_2_ir_lock);
|
||||||
if (irq >= NR_IRQS || !irq_2_iommu[irq].iommu) {
|
irq_iommu = valid_irq_2_iommu(irq);
|
||||||
|
if (!irq_iommu) {
|
||||||
spin_unlock(&irq_2_ir_lock);
|
spin_unlock(&irq_2_ir_lock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
iommu = irq_2_iommu[irq].iommu;
|
iommu = irq_iommu->iommu;
|
||||||
|
|
||||||
index = irq_2_iommu[irq].irte_index + irq_2_iommu[irq].sub_handle;
|
index = irq_iommu->irte_index + irq_iommu->sub_handle;
|
||||||
irte = &iommu->ir_table->base[index];
|
irte = &iommu->ir_table->base[index];
|
||||||
|
|
||||||
if (!irq_2_iommu[irq].sub_handle) {
|
if (!irq_iommu->sub_handle) {
|
||||||
for (i = 0; i < (1 << irq_2_iommu[irq].irte_mask); i++)
|
for (i = 0; i < (1 << irq_iommu->irte_mask); i++)
|
||||||
set_64bit((unsigned long *)irte, 0);
|
set_64bit((unsigned long *)irte, 0);
|
||||||
qi_flush_iec(iommu, index, irq_2_iommu[irq].irte_mask);
|
qi_flush_iec(iommu, index, irq_iommu->irte_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
irq_2_iommu[irq].iommu = NULL;
|
irq_iommu->iommu = NULL;
|
||||||
irq_2_iommu[irq].irte_index = 0;
|
irq_iommu->irte_index = 0;
|
||||||
irq_2_iommu[irq].sub_handle = 0;
|
irq_iommu->sub_handle = 0;
|
||||||
irq_2_iommu[irq].irte_mask = 0;
|
irq_iommu->irte_mask = 0;
|
||||||
|
|
||||||
spin_unlock(&irq_2_ir_lock);
|
spin_unlock(&irq_2_ir_lock);
|
||||||
|
|
||||||
|
@@ -273,7 +273,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
|
|||||||
goto fail0d;
|
goto fail0d;
|
||||||
cf->socket.pci_irq = board->irq_pin;
|
cf->socket.pci_irq = board->irq_pin;
|
||||||
} else
|
} else
|
||||||
cf->socket.pci_irq = NR_IRQS + 1;
|
cf->socket.pci_irq = nr_irqs + 1;
|
||||||
|
|
||||||
/* pcmcia layer only remaps "real" memory not iospace */
|
/* pcmcia layer only remaps "real" memory not iospace */
|
||||||
cf->socket.io_offset = (unsigned long)
|
cf->socket.io_offset = (unsigned long)
|
||||||
|
@@ -233,15 +233,18 @@ static struct hw_interrupt_type hd64465_ss_irq_type = {
|
|||||||
*/
|
*/
|
||||||
static void hs_map_irq(hs_socket_t *sp, unsigned int irq)
|
static void hs_map_irq(hs_socket_t *sp, unsigned int irq)
|
||||||
{
|
{
|
||||||
|
struct irq_desc *desc;
|
||||||
|
|
||||||
DPRINTK("hs_map_irq(sock=%d irq=%d)\n", sp->number, irq);
|
DPRINTK("hs_map_irq(sock=%d irq=%d)\n", sp->number, irq);
|
||||||
|
|
||||||
if (irq >= HS_NUM_MAPPED_IRQS)
|
if (irq >= HS_NUM_MAPPED_IRQS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
desc = irq_to_desc(irq);
|
||||||
hs_mapped_irq[irq].sock = sp;
|
hs_mapped_irq[irq].sock = sp;
|
||||||
/* insert ourselves as the irq controller */
|
/* insert ourselves as the irq controller */
|
||||||
hs_mapped_irq[irq].old_handler = irq_desc[irq].chip;
|
hs_mapped_irq[irq].old_handler = desc->chip;
|
||||||
irq_desc[irq].chip = &hd64465_ss_irq_type;
|
desc->chip = &hd64465_ss_irq_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -250,13 +253,16 @@ static void hs_map_irq(hs_socket_t *sp, unsigned int irq)
|
|||||||
*/
|
*/
|
||||||
static void hs_unmap_irq(hs_socket_t *sp, unsigned int irq)
|
static void hs_unmap_irq(hs_socket_t *sp, unsigned int irq)
|
||||||
{
|
{
|
||||||
|
struct irq_desc *desc;
|
||||||
|
|
||||||
DPRINTK("hs_unmap_irq(sock=%d irq=%d)\n", sp->number, irq);
|
DPRINTK("hs_unmap_irq(sock=%d irq=%d)\n", sp->number, irq);
|
||||||
|
|
||||||
if (irq >= HS_NUM_MAPPED_IRQS)
|
if (irq >= HS_NUM_MAPPED_IRQS)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
desc = irq_to_desc(irq);
|
||||||
/* restore the original irq controller */
|
/* restore the original irq controller */
|
||||||
irq_desc[irq].chip = hs_mapped_irq[irq].old_handler;
|
desc->chip = hs_mapped_irq[irq].old_handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*============================================================*/
|
/*============================================================*/
|
||||||
|
@@ -639,7 +639,7 @@ static int __devinit vrc4171_card_setup(char *options)
|
|||||||
int irq;
|
int irq;
|
||||||
options += 4;
|
options += 4;
|
||||||
irq = simple_strtoul(options, &options, 0);
|
irq = simple_strtoul(options, &options, 0);
|
||||||
if (irq >= 0 && irq < NR_IRQS)
|
if (irq >= 0 && irq < nr_irqs)
|
||||||
vrc4171_irq = irq;
|
vrc4171_irq = irq;
|
||||||
|
|
||||||
if (*options != ',')
|
if (*options != ',')
|
||||||
|
@@ -360,7 +360,7 @@ static int __devinit rtc_probe(struct platform_device *pdev)
|
|||||||
spin_unlock_irq(&rtc_lock);
|
spin_unlock_irq(&rtc_lock);
|
||||||
|
|
||||||
aie_irq = platform_get_irq(pdev, 0);
|
aie_irq = platform_get_irq(pdev, 0);
|
||||||
if (aie_irq < 0 || aie_irq >= NR_IRQS) {
|
if (aie_irq < 0 || aie_irq >= nr_irqs) {
|
||||||
retval = -EBUSY;
|
retval = -EBUSY;
|
||||||
goto err_device_unregister;
|
goto err_device_unregister;
|
||||||
}
|
}
|
||||||
@@ -371,7 +371,7 @@ static int __devinit rtc_probe(struct platform_device *pdev)
|
|||||||
goto err_device_unregister;
|
goto err_device_unregister;
|
||||||
|
|
||||||
pie_irq = platform_get_irq(pdev, 1);
|
pie_irq = platform_get_irq(pdev, 1);
|
||||||
if (pie_irq < 0 || pie_irq >= NR_IRQS)
|
if (pie_irq < 0 || pie_irq >= nr_irqs)
|
||||||
goto err_free_irq;
|
goto err_free_irq;
|
||||||
|
|
||||||
retval = request_irq(pie_irq, rtclong1_interrupt, IRQF_DISABLED,
|
retval = request_irq(pie_irq, rtclong1_interrupt, IRQF_DISABLED,
|
||||||
|
@@ -337,7 +337,7 @@ CMD_INC_RESID(struct scsi_cmnd *cmd, int inc)
|
|||||||
#else
|
#else
|
||||||
#define IRQ_MIN 9
|
#define IRQ_MIN 9
|
||||||
#if defined(__PPC)
|
#if defined(__PPC)
|
||||||
#define IRQ_MAX (NR_IRQS-1)
|
#define IRQ_MAX (nr_irqs-1)
|
||||||
#else
|
#else
|
||||||
#define IRQ_MAX 12
|
#define IRQ_MAX 12
|
||||||
#endif
|
#endif
|
||||||
|
@@ -2108,7 +2108,7 @@ struct scsi_qla_host;
|
|||||||
|
|
||||||
struct qla_msix_entry {
|
struct qla_msix_entry {
|
||||||
int have_irq;
|
int have_irq;
|
||||||
uint16_t msix_vector;
|
uint32_t msix_vector;
|
||||||
uint16_t msix_entry;
|
uint16_t msix_entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -66,7 +66,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct m68k_serial m68k_soft[NR_PORTS];
|
static struct m68k_serial m68k_soft[NR_PORTS];
|
||||||
struct m68k_serial *IRQ_ports[NR_IRQS];
|
|
||||||
|
|
||||||
static unsigned int uart_irqs[NR_PORTS] = UART_IRQ_DEFNS;
|
static unsigned int uart_irqs[NR_PORTS] = UART_IRQ_DEFNS;
|
||||||
|
|
||||||
@@ -375,15 +374,11 @@ clear_and_return:
|
|||||||
*/
|
*/
|
||||||
irqreturn_t rs_interrupt(int irq, void *dev_id)
|
irqreturn_t rs_interrupt(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct m68k_serial * info;
|
struct m68k_serial *info = dev_id;
|
||||||
m68328_uart *uart;
|
m68328_uart *uart;
|
||||||
unsigned short rx;
|
unsigned short rx;
|
||||||
unsigned short tx;
|
unsigned short tx;
|
||||||
|
|
||||||
info = IRQ_ports[irq];
|
|
||||||
if(!info)
|
|
||||||
return IRQ_NONE;
|
|
||||||
|
|
||||||
uart = &uart_addr[info->line];
|
uart = &uart_addr[info->line];
|
||||||
rx = uart->urx.w;
|
rx = uart->urx.w;
|
||||||
|
|
||||||
@@ -1383,8 +1378,6 @@ rs68328_init(void)
|
|||||||
info->port, info->irq);
|
info->port, info->irq);
|
||||||
printk(" is a builtin MC68328 UART\n");
|
printk(" is a builtin MC68328 UART\n");
|
||||||
|
|
||||||
IRQ_ports[info->irq] = info; /* waste of space */
|
|
||||||
|
|
||||||
#ifdef CONFIG_M68VZ328
|
#ifdef CONFIG_M68VZ328
|
||||||
if (i > 0 )
|
if (i > 0 )
|
||||||
PJSEL &= 0xCF; /* PSW enable second port output */
|
PJSEL &= 0xCF; /* PSW enable second port output */
|
||||||
@@ -1393,7 +1386,7 @@ rs68328_init(void)
|
|||||||
if (request_irq(uart_irqs[i],
|
if (request_irq(uart_irqs[i],
|
||||||
rs_interrupt,
|
rs_interrupt,
|
||||||
IRQF_DISABLED,
|
IRQF_DISABLED,
|
||||||
"M68328_UART", NULL))
|
"M68328_UART", info))
|
||||||
panic("Unable to attach 68328 serial interrupt\n");
|
panic("Unable to attach 68328 serial interrupt\n");
|
||||||
}
|
}
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
|
@@ -156,11 +156,15 @@ struct uart_8250_port {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct irq_info {
|
struct irq_info {
|
||||||
spinlock_t lock;
|
struct hlist_node node;
|
||||||
|
int irq;
|
||||||
|
spinlock_t lock; /* Protects list not the hash */
|
||||||
struct list_head *head;
|
struct list_head *head;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct irq_info irq_lists[NR_IRQS];
|
#define NR_IRQ_HASH 32 /* Can be adjusted later */
|
||||||
|
static struct hlist_head irq_lists[NR_IRQ_HASH];
|
||||||
|
static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Here we define the default xmit fifo size used for each type of UART.
|
* Here we define the default xmit fifo size used for each type of UART.
|
||||||
@@ -1545,15 +1549,43 @@ static void serial_do_unlink(struct irq_info *i, struct uart_8250_port *up)
|
|||||||
BUG_ON(i->head != &up->list);
|
BUG_ON(i->head != &up->list);
|
||||||
i->head = NULL;
|
i->head = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irq(&i->lock);
|
spin_unlock_irq(&i->lock);
|
||||||
|
/* List empty so throw away the hash node */
|
||||||
|
if (i->head == NULL) {
|
||||||
|
hlist_del(&i->node);
|
||||||
|
kfree(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serial_link_irq_chain(struct uart_8250_port *up)
|
static int serial_link_irq_chain(struct uart_8250_port *up)
|
||||||
{
|
{
|
||||||
struct irq_info *i = irq_lists + up->port.irq;
|
struct hlist_head *h;
|
||||||
|
struct hlist_node *n;
|
||||||
|
struct irq_info *i;
|
||||||
int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
|
int ret, irq_flags = up->port.flags & UPF_SHARE_IRQ ? IRQF_SHARED : 0;
|
||||||
|
|
||||||
|
mutex_lock(&hash_mutex);
|
||||||
|
|
||||||
|
h = &irq_lists[up->port.irq % NR_IRQ_HASH];
|
||||||
|
|
||||||
|
hlist_for_each(n, h) {
|
||||||
|
i = hlist_entry(n, struct irq_info, node);
|
||||||
|
if (i->irq == up->port.irq)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == NULL) {
|
||||||
|
i = kzalloc(sizeof(struct irq_info), GFP_KERNEL);
|
||||||
|
if (i == NULL) {
|
||||||
|
mutex_unlock(&hash_mutex);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
spin_lock_init(&i->lock);
|
||||||
|
i->irq = up->port.irq;
|
||||||
|
hlist_add_head(&i->node, h);
|
||||||
|
}
|
||||||
|
mutex_unlock(&hash_mutex);
|
||||||
|
|
||||||
spin_lock_irq(&i->lock);
|
spin_lock_irq(&i->lock);
|
||||||
|
|
||||||
if (i->head) {
|
if (i->head) {
|
||||||
@@ -1577,14 +1609,28 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
|
|||||||
|
|
||||||
static void serial_unlink_irq_chain(struct uart_8250_port *up)
|
static void serial_unlink_irq_chain(struct uart_8250_port *up)
|
||||||
{
|
{
|
||||||
struct irq_info *i = irq_lists + up->port.irq;
|
struct irq_info *i;
|
||||||
|
struct hlist_node *n;
|
||||||
|
struct hlist_head *h;
|
||||||
|
|
||||||
|
mutex_lock(&hash_mutex);
|
||||||
|
|
||||||
|
h = &irq_lists[up->port.irq % NR_IRQ_HASH];
|
||||||
|
|
||||||
|
hlist_for_each(n, h) {
|
||||||
|
i = hlist_entry(n, struct irq_info, node);
|
||||||
|
if (i->irq == up->port.irq)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
BUG_ON(n == NULL);
|
||||||
BUG_ON(i->head == NULL);
|
BUG_ON(i->head == NULL);
|
||||||
|
|
||||||
if (list_empty(i->head))
|
if (list_empty(i->head))
|
||||||
free_irq(up->port.irq, i);
|
free_irq(up->port.irq, i);
|
||||||
|
|
||||||
serial_do_unlink(i, up);
|
serial_do_unlink(i, up);
|
||||||
|
mutex_unlock(&hash_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Base timer interval for polling */
|
/* Base timer interval for polling */
|
||||||
@@ -2447,7 +2493,7 @@ static void serial8250_config_port(struct uart_port *port, int flags)
|
|||||||
static int
|
static int
|
||||||
serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
|
serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||||
{
|
{
|
||||||
if (ser->irq >= NR_IRQS || ser->irq < 0 ||
|
if (ser->irq >= nr_irqs || ser->irq < 0 ||
|
||||||
ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
|
ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
|
||||||
ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
|
ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
|
||||||
ser->type == PORT_STARTECH)
|
ser->type == PORT_STARTECH)
|
||||||
@@ -2967,7 +3013,7 @@ EXPORT_SYMBOL(serial8250_unregister_port);
|
|||||||
|
|
||||||
static int __init serial8250_init(void)
|
static int __init serial8250_init(void)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret;
|
||||||
|
|
||||||
if (nr_uarts > UART_NR)
|
if (nr_uarts > UART_NR)
|
||||||
nr_uarts = UART_NR;
|
nr_uarts = UART_NR;
|
||||||
@@ -2976,9 +3022,6 @@ static int __init serial8250_init(void)
|
|||||||
"%d ports, IRQ sharing %sabled\n", nr_uarts,
|
"%d ports, IRQ sharing %sabled\n", nr_uarts,
|
||||||
share_irqs ? "en" : "dis");
|
share_irqs ? "en" : "dis");
|
||||||
|
|
||||||
for (i = 0; i < NR_IRQS; i++)
|
|
||||||
spin_lock_init(&irq_lists[i].lock);
|
|
||||||
|
|
||||||
#ifdef CONFIG_SPARC
|
#ifdef CONFIG_SPARC
|
||||||
ret = sunserial_register_minors(&serial8250_reg, UART_NR);
|
ret = sunserial_register_minors(&serial8250_reg, UART_NR);
|
||||||
#else
|
#else
|
||||||
@@ -3006,15 +3049,15 @@ static int __init serial8250_init(void)
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
platform_device_del(serial8250_isa_devs);
|
platform_device_del(serial8250_isa_devs);
|
||||||
put_dev:
|
put_dev:
|
||||||
platform_device_put(serial8250_isa_devs);
|
platform_device_put(serial8250_isa_devs);
|
||||||
unreg_uart_drv:
|
unreg_uart_drv:
|
||||||
#ifdef CONFIG_SPARC
|
#ifdef CONFIG_SPARC
|
||||||
sunserial_unregister_minors(&serial8250_reg, UART_NR);
|
sunserial_unregister_minors(&serial8250_reg, UART_NR);
|
||||||
#else
|
#else
|
||||||
uart_unregister_driver(&serial8250_reg);
|
uart_unregister_driver(&serial8250_reg);
|
||||||
#endif
|
#endif
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -512,7 +512,7 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
|
if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
if (ser->irq < 0 || ser->irq >= NR_IRQS)
|
if (ser->irq < 0 || ser->irq >= nr_irqs)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
if (ser->baud_base < 9600)
|
if (ser->baud_base < 9600)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@@ -572,7 +572,7 @@ static int pl010_verify_port(struct uart_port *port, struct serial_struct *ser)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
|
if (ser->type != PORT_UNKNOWN && ser->type != PORT_AMBA)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
if (ser->irq < 0 || ser->irq >= NR_IRQS)
|
if (ser->irq < 0 || ser->irq >= nr_irqs)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
if (ser->baud_base < 9600)
|
if (ser->baud_base < 9600)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@@ -623,7 +623,7 @@ static int cpm_uart_verify_port(struct uart_port *port,
|
|||||||
|
|
||||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
|
if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
if (ser->irq < 0 || ser->irq >= NR_IRQS)
|
if (ser->irq < 0 || ser->irq >= nr_irqs)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
if (ser->baud_base < 9600)
|
if (ser->baud_base < 9600)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@@ -922,7 +922,7 @@ static void m32r_sio_config_port(struct uart_port *port, int flags)
|
|||||||
static int
|
static int
|
||||||
m32r_sio_verify_port(struct uart_port *port, struct serial_struct *ser)
|
m32r_sio_verify_port(struct uart_port *port, struct serial_struct *ser)
|
||||||
{
|
{
|
||||||
if (ser->irq >= NR_IRQS || ser->irq < 0 ||
|
if (ser->irq >= nr_irqs || ser->irq < 0 ||
|
||||||
ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
|
ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
|
||||||
ser->type >= ARRAY_SIZE(uart_config))
|
ser->type >= ARRAY_SIZE(uart_config))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -1162,7 +1162,7 @@ static int __init m32r_sio_init(void)
|
|||||||
|
|
||||||
printk(KERN_INFO "Serial: M32R SIO driver\n");
|
printk(KERN_INFO "Serial: M32R SIO driver\n");
|
||||||
|
|
||||||
for (i = 0; i < NR_IRQS; i++)
|
for (i = 0; i < nr_irqs; i++)
|
||||||
spin_lock_init(&irq_lists[i].lock);
|
spin_lock_init(&irq_lists[i].lock);
|
||||||
|
|
||||||
ret = uart_register_driver(&m32r_sio_reg);
|
ret = uart_register_driver(&m32r_sio_reg);
|
||||||
|
@@ -741,7 +741,7 @@ static int uart_set_info(struct uart_state *state,
|
|||||||
if (port->ops->verify_port)
|
if (port->ops->verify_port)
|
||||||
retval = port->ops->verify_port(port, &new_serial);
|
retval = port->ops->verify_port(port, &new_serial);
|
||||||
|
|
||||||
if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) ||
|
if ((new_serial.irq >= nr_irqs) || (new_serial.irq < 0) ||
|
||||||
(new_serial.baud_base < 9600))
|
(new_serial.baud_base < 9600))
|
||||||
retval = -EINVAL;
|
retval = -EINVAL;
|
||||||
|
|
||||||
|
@@ -460,7 +460,7 @@ static int lh7a40xuart_verify_port (struct uart_port* port,
|
|||||||
|
|
||||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_LH7A40X)
|
if (ser->type != PORT_UNKNOWN && ser->type != PORT_LH7A40X)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
if (ser->irq < 0 || ser->irq >= NR_IRQS)
|
if (ser->irq < 0 || ser->irq >= nr_irqs)
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
if (ser->baud_base < 9600) /* *** FIXME: is this true? */
|
if (ser->baud_base < 9600) /* *** FIXME: is this true? */
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@@ -1149,7 +1149,7 @@ static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
|
|||||||
{
|
{
|
||||||
struct sci_port *s = &sci_ports[port->line];
|
struct sci_port *s = &sci_ports[port->line];
|
||||||
|
|
||||||
if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > NR_IRQS)
|
if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (ser->baud_base < 2400)
|
if (ser->baud_base < 2400)
|
||||||
/* No paper tape reader for Mitch.. */
|
/* No paper tape reader for Mitch.. */
|
||||||
|
@@ -1066,7 +1066,7 @@ static int qe_uart_verify_port(struct uart_port *port,
|
|||||||
if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
|
if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (ser->irq < 0 || ser->irq >= NR_IRQS)
|
if (ser->irq < 0 || ser->irq >= nr_irqs)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (ser->baud_base < 9600)
|
if (ser->baud_base < 9600)
|
||||||
|
@@ -125,7 +125,7 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
|
|||||||
|
|
||||||
BUG_ON(irq == -1);
|
BUG_ON(irq == -1);
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
irq_desc[irq].affinity = cpumask_of_cpu(cpu);
|
irq_to_desc(irq)->affinity = cpumask_of_cpu(cpu);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__clear_bit(chn, cpu_evtchn_mask[cpu_evtchn[chn]]);
|
__clear_bit(chn, cpu_evtchn_mask[cpu_evtchn[chn]]);
|
||||||
@@ -137,10 +137,12 @@ static void bind_evtchn_to_cpu(unsigned int chn, unsigned int cpu)
|
|||||||
static void init_evtchn_cpu_bindings(void)
|
static void init_evtchn_cpu_bindings(void)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
struct irq_desc *desc;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* By default all event channels notify CPU#0. */
|
/* By default all event channels notify CPU#0. */
|
||||||
for (i = 0; i < NR_IRQS; i++)
|
for_each_irq_desc(i, desc)
|
||||||
irq_desc[i].affinity = cpumask_of_cpu(0);
|
desc->affinity = cpumask_of_cpu(0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
|
memset(cpu_evtchn, 0, sizeof(cpu_evtchn));
|
||||||
@@ -229,12 +231,12 @@ static int find_unbound_irq(void)
|
|||||||
int irq;
|
int irq;
|
||||||
|
|
||||||
/* Only allocate from dynirq range */
|
/* Only allocate from dynirq range */
|
||||||
for (irq = 0; irq < NR_IRQS; irq++)
|
for_each_irq_nr(irq)
|
||||||
if (irq_bindcount[irq] == 0)
|
if (irq_bindcount[irq] == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
return irq;
|
return irq;
|
||||||
}
|
}
|
||||||
@@ -790,7 +792,7 @@ void xen_irq_resume(void)
|
|||||||
mask_evtchn(evtchn);
|
mask_evtchn(evtchn);
|
||||||
|
|
||||||
/* No IRQ <-> event-channel mappings. */
|
/* No IRQ <-> event-channel mappings. */
|
||||||
for (irq = 0; irq < NR_IRQS; irq++)
|
for_each_irq_nr(irq)
|
||||||
irq_info[irq].evtchn = 0; /* zap event-channel binding */
|
irq_info[irq].evtchn = 0; /* zap event-channel binding */
|
||||||
|
|
||||||
for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
|
for (evtchn = 0; evtchn < NR_EVENT_CHANNELS; evtchn++)
|
||||||
@@ -822,7 +824,7 @@ void __init xen_init_IRQ(void)
|
|||||||
mask_evtchn(i);
|
mask_evtchn(i);
|
||||||
|
|
||||||
/* Dynamic IRQ space is currently unbound. Zero the refcnts. */
|
/* Dynamic IRQ space is currently unbound. Zero the refcnts. */
|
||||||
for (i = 0; i < NR_IRQS; i++)
|
for_each_irq_nr(i)
|
||||||
irq_bindcount[i] = 0;
|
irq_bindcount[i] = 0;
|
||||||
|
|
||||||
irq_ctx_init(smp_processor_id());
|
irq_ctx_init(smp_processor_id());
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/mmzone.h>
|
#include <linux/mmzone.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/swap.h>
|
#include <linux/swap.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
@@ -521,17 +522,13 @@ static const struct file_operations proc_vmalloc_operations = {
|
|||||||
|
|
||||||
static int show_stat(struct seq_file *p, void *v)
|
static int show_stat(struct seq_file *p, void *v)
|
||||||
{
|
{
|
||||||
int i;
|
int i, j;
|
||||||
unsigned long jif;
|
unsigned long jif;
|
||||||
cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
|
cputime64_t user, nice, system, idle, iowait, irq, softirq, steal;
|
||||||
cputime64_t guest;
|
cputime64_t guest;
|
||||||
u64 sum = 0;
|
u64 sum = 0;
|
||||||
struct timespec boottime;
|
struct timespec boottime;
|
||||||
unsigned int *per_irq_sum;
|
unsigned int per_irq_sum;
|
||||||
|
|
||||||
per_irq_sum = kzalloc(sizeof(unsigned int)*NR_IRQS, GFP_KERNEL);
|
|
||||||
if (!per_irq_sum)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
user = nice = system = idle = iowait =
|
user = nice = system = idle = iowait =
|
||||||
irq = softirq = steal = cputime64_zero;
|
irq = softirq = steal = cputime64_zero;
|
||||||
@@ -540,8 +537,6 @@ static int show_stat(struct seq_file *p, void *v)
|
|||||||
jif = boottime.tv_sec;
|
jif = boottime.tv_sec;
|
||||||
|
|
||||||
for_each_possible_cpu(i) {
|
for_each_possible_cpu(i) {
|
||||||
int j;
|
|
||||||
|
|
||||||
user = cputime64_add(user, kstat_cpu(i).cpustat.user);
|
user = cputime64_add(user, kstat_cpu(i).cpustat.user);
|
||||||
nice = cputime64_add(nice, kstat_cpu(i).cpustat.nice);
|
nice = cputime64_add(nice, kstat_cpu(i).cpustat.nice);
|
||||||
system = cputime64_add(system, kstat_cpu(i).cpustat.system);
|
system = cputime64_add(system, kstat_cpu(i).cpustat.system);
|
||||||
@@ -551,11 +546,10 @@ static int show_stat(struct seq_file *p, void *v)
|
|||||||
softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
|
softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq);
|
||||||
steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal);
|
steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal);
|
||||||
guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest);
|
guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest);
|
||||||
for (j = 0; j < NR_IRQS; j++) {
|
|
||||||
unsigned int temp = kstat_cpu(i).irqs[j];
|
for_each_irq_nr(j)
|
||||||
sum += temp;
|
sum += kstat_irqs_cpu(j, i);
|
||||||
per_irq_sum[j] += temp;
|
|
||||||
}
|
|
||||||
sum += arch_irq_stat_cpu(i);
|
sum += arch_irq_stat_cpu(i);
|
||||||
}
|
}
|
||||||
sum += arch_irq_stat();
|
sum += arch_irq_stat();
|
||||||
@@ -597,8 +591,15 @@ static int show_stat(struct seq_file *p, void *v)
|
|||||||
}
|
}
|
||||||
seq_printf(p, "intr %llu", (unsigned long long)sum);
|
seq_printf(p, "intr %llu", (unsigned long long)sum);
|
||||||
|
|
||||||
for (i = 0; i < NR_IRQS; i++)
|
/* sum again ? it could be updated? */
|
||||||
seq_printf(p, " %u", per_irq_sum[i]);
|
for_each_irq_nr(j) {
|
||||||
|
per_irq_sum = 0;
|
||||||
|
|
||||||
|
for_each_possible_cpu(i)
|
||||||
|
per_irq_sum += kstat_irqs_cpu(j, i);
|
||||||
|
|
||||||
|
seq_printf(p, " %u", per_irq_sum);
|
||||||
|
}
|
||||||
|
|
||||||
seq_printf(p,
|
seq_printf(p,
|
||||||
"\nctxt %llu\n"
|
"\nctxt %llu\n"
|
||||||
@@ -612,7 +613,6 @@ static int show_stat(struct seq_file *p, void *v)
|
|||||||
nr_running(),
|
nr_running(),
|
||||||
nr_iowait());
|
nr_iowait());
|
||||||
|
|
||||||
kfree(per_irq_sum);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,15 +651,14 @@ static const struct file_operations proc_stat_operations = {
|
|||||||
*/
|
*/
|
||||||
static void *int_seq_start(struct seq_file *f, loff_t *pos)
|
static void *int_seq_start(struct seq_file *f, loff_t *pos)
|
||||||
{
|
{
|
||||||
return (*pos <= NR_IRQS) ? pos : NULL;
|
return (*pos <= nr_irqs) ? pos : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void *int_seq_next(struct seq_file *f, void *v, loff_t *pos)
|
static void *int_seq_next(struct seq_file *f, void *v, loff_t *pos)
|
||||||
{
|
{
|
||||||
(*pos)++;
|
(*pos)++;
|
||||||
if (*pos > NR_IRQS)
|
return (*pos <= nr_irqs) ? pos : NULL;
|
||||||
return NULL;
|
|
||||||
return pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void int_seq_stop(struct seq_file *f, void *v)
|
static void int_seq_stop(struct seq_file *f, void *v)
|
||||||
@@ -667,7 +666,6 @@ static void int_seq_stop(struct seq_file *f, void *v)
|
|||||||
/* Nothing to do */
|
/* Nothing to do */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const struct seq_operations int_seq_ops = {
|
static const struct seq_operations int_seq_ops = {
|
||||||
.start = int_seq_start,
|
.start = int_seq_start,
|
||||||
.next = int_seq_next,
|
.next = int_seq_next,
|
||||||
|
@@ -40,8 +40,6 @@ extern void generic_apic_probe(void);
|
|||||||
extern unsigned int apic_verbosity;
|
extern unsigned int apic_verbosity;
|
||||||
extern int local_apic_timer_c2_ok;
|
extern int local_apic_timer_c2_ok;
|
||||||
|
|
||||||
extern int ioapic_force;
|
|
||||||
|
|
||||||
extern int disable_apic;
|
extern int disable_apic;
|
||||||
/*
|
/*
|
||||||
* Basic functions accessing APICs.
|
* Basic functions accessing APICs.
|
||||||
@@ -100,6 +98,20 @@ extern void check_x2apic(void);
|
|||||||
extern void enable_x2apic(void);
|
extern void enable_x2apic(void);
|
||||||
extern void enable_IR_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)
|
||||||
|
{
|
||||||
|
int msr, msr2;
|
||||||
|
|
||||||
|
if (!cpu_has_x2apic)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
rdmsr(MSR_IA32_APICBASE, msr, msr2);
|
||||||
|
if (msr & X2APIC_ENABLE)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define x2apic_enabled() 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct apic_ops {
|
struct apic_ops {
|
||||||
|
@@ -9,22 +9,17 @@ static inline int apic_id_registered(void)
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Round robin the irqs amoung the online cpus */
|
|
||||||
static inline cpumask_t target_cpus(void)
|
static inline cpumask_t target_cpus(void)
|
||||||
{
|
{
|
||||||
static unsigned long cpu = NR_CPUS;
|
#ifdef CONFIG_SMP
|
||||||
do {
|
return cpu_online_map;
|
||||||
if (cpu >= NR_CPUS)
|
#else
|
||||||
cpu = first_cpu(cpu_online_map);
|
return cpumask_of_cpu(0);
|
||||||
else
|
#endif
|
||||||
cpu = next_cpu(cpu, cpu_online_map);
|
|
||||||
} while (cpu >= NR_CPUS);
|
|
||||||
return cpumask_of_cpu(cpu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef APIC_DEST_LOGICAL
|
#undef APIC_DEST_LOGICAL
|
||||||
#define APIC_DEST_LOGICAL 0
|
#define APIC_DEST_LOGICAL 0
|
||||||
#define TARGET_CPUS (target_cpus())
|
|
||||||
#define APIC_DFR_VALUE (APIC_DFR_FLAT)
|
#define APIC_DFR_VALUE (APIC_DFR_FLAT)
|
||||||
#define INT_DELIVERY_MODE (dest_Fixed)
|
#define INT_DELIVERY_MODE (dest_Fixed)
|
||||||
#define INT_DEST_MODE (0) /* phys delivery to target proc */
|
#define INT_DEST_MODE (0) /* phys delivery to target proc */
|
||||||
|
@@ -94,4 +94,17 @@ extern void efi_reserve_early(void);
|
|||||||
extern void efi_call_phys_prelog(void);
|
extern void efi_call_phys_prelog(void);
|
||||||
extern void efi_call_phys_epilog(void);
|
extern void efi_call_phys_epilog(void);
|
||||||
|
|
||||||
|
#ifndef CONFIG_EFI
|
||||||
|
/*
|
||||||
|
* IF EFI is not configured, have the EFI calls return -ENOSYS.
|
||||||
|
*/
|
||||||
|
#define efi_call0(_f) (-ENOSYS)
|
||||||
|
#define efi_call1(_f, _a1) (-ENOSYS)
|
||||||
|
#define efi_call2(_f, _a1, _a2) (-ENOSYS)
|
||||||
|
#define efi_call3(_f, _a1, _a2, _a3) (-ENOSYS)
|
||||||
|
#define efi_call4(_f, _a1, _a2, _a3, _a4) (-ENOSYS)
|
||||||
|
#define efi_call5(_f, _a1, _a2, _a3, _a4, _a5) (-ENOSYS)
|
||||||
|
#define efi_call6(_f, _a1, _a2, _a3, _a4, _a5, _a6) (-ENOSYS)
|
||||||
|
#endif /* CONFIG_EFI */
|
||||||
|
|
||||||
#endif /* ASM_X86__EFI_H */
|
#endif /* ASM_X86__EFI_H */
|
||||||
|
@@ -17,7 +17,6 @@ static inline cpumask_t target_cpus(void)
|
|||||||
return cpumask_of_cpu(smp_processor_id());
|
return cpumask_of_cpu(smp_processor_id());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#define TARGET_CPUS (target_cpus())
|
|
||||||
|
|
||||||
#if defined CONFIG_ES7000_CLUSTERED_APIC
|
#if defined CONFIG_ES7000_CLUSTERED_APIC
|
||||||
#define APIC_DFR_VALUE (APIC_DFR_CLUSTER)
|
#define APIC_DFR_VALUE (APIC_DFR_CLUSTER)
|
||||||
@@ -81,7 +80,7 @@ static inline void setup_apic_routing(void)
|
|||||||
int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id());
|
int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id());
|
||||||
printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n",
|
printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n",
|
||||||
(apic_version[apic] == 0x14) ?
|
(apic_version[apic] == 0x14) ?
|
||||||
"Physical Cluster" : "Logical Cluster", nr_ioapics, cpus_addr(TARGET_CPUS)[0]);
|
"Physical Cluster" : "Logical Cluster", nr_ioapics, cpus_addr(target_cpus())[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int multi_timer_check(int apic, int irq)
|
static inline int multi_timer_check(int apic, int irq)
|
||||||
|
@@ -57,6 +57,7 @@ struct genapic {
|
|||||||
unsigned (*get_apic_id)(unsigned long x);
|
unsigned (*get_apic_id)(unsigned long x);
|
||||||
unsigned long apic_id_mask;
|
unsigned long apic_id_mask;
|
||||||
unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask);
|
unsigned int (*cpu_mask_to_apicid)(cpumask_t cpumask);
|
||||||
|
cpumask_t (*vector_allocation_domain)(int cpu);
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
/* ipi */
|
/* ipi */
|
||||||
@@ -104,6 +105,7 @@ struct genapic {
|
|||||||
APICFUNC(get_apic_id) \
|
APICFUNC(get_apic_id) \
|
||||||
.apic_id_mask = APIC_ID_MASK, \
|
.apic_id_mask = APIC_ID_MASK, \
|
||||||
APICFUNC(cpu_mask_to_apicid) \
|
APICFUNC(cpu_mask_to_apicid) \
|
||||||
|
APICFUNC(vector_allocation_domain) \
|
||||||
APICFUNC(acpi_madt_oem_check) \
|
APICFUNC(acpi_madt_oem_check) \
|
||||||
IPIFUNC(send_IPI_mask) \
|
IPIFUNC(send_IPI_mask) \
|
||||||
IPIFUNC(send_IPI_allbutself) \
|
IPIFUNC(send_IPI_allbutself) \
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
#ifndef ASM_X86__HPET_H
|
#ifndef ASM_X86__HPET_H
|
||||||
#define ASM_X86__HPET_H
|
#define ASM_X86__HPET_H
|
||||||
|
|
||||||
|
#include <linux/msi.h>
|
||||||
|
|
||||||
#ifdef CONFIG_HPET_TIMER
|
#ifdef CONFIG_HPET_TIMER
|
||||||
|
|
||||||
#define HPET_MMAP_SIZE 1024
|
#define HPET_MMAP_SIZE 1024
|
||||||
@@ -10,6 +12,11 @@
|
|||||||
#define HPET_CFG 0x010
|
#define HPET_CFG 0x010
|
||||||
#define HPET_STATUS 0x020
|
#define HPET_STATUS 0x020
|
||||||
#define HPET_COUNTER 0x0f0
|
#define HPET_COUNTER 0x0f0
|
||||||
|
|
||||||
|
#define HPET_Tn_CFG(n) (0x100 + 0x20 * n)
|
||||||
|
#define HPET_Tn_CMP(n) (0x108 + 0x20 * n)
|
||||||
|
#define HPET_Tn_ROUTE(n) (0x110 + 0x20 * n)
|
||||||
|
|
||||||
#define HPET_T0_CFG 0x100
|
#define HPET_T0_CFG 0x100
|
||||||
#define HPET_T0_CMP 0x108
|
#define HPET_T0_CMP 0x108
|
||||||
#define HPET_T0_ROUTE 0x110
|
#define HPET_T0_ROUTE 0x110
|
||||||
@@ -65,6 +72,20 @@ extern void hpet_disable(void);
|
|||||||
extern unsigned long hpet_readl(unsigned long a);
|
extern unsigned long hpet_readl(unsigned long a);
|
||||||
extern void force_hpet_resume(void);
|
extern void force_hpet_resume(void);
|
||||||
|
|
||||||
|
extern void hpet_msi_unmask(unsigned int irq);
|
||||||
|
extern void hpet_msi_mask(unsigned int irq);
|
||||||
|
extern void hpet_msi_write(unsigned int irq, struct msi_msg *msg);
|
||||||
|
extern void hpet_msi_read(unsigned int irq, struct msi_msg *msg);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PCI_MSI
|
||||||
|
extern int arch_setup_hpet_msi(unsigned int irq);
|
||||||
|
#else
|
||||||
|
static inline int arch_setup_hpet_msi(unsigned int irq)
|
||||||
|
{
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_HPET_EMULATE_RTC
|
#ifdef CONFIG_HPET_EMULATE_RTC
|
||||||
|
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
|
@@ -96,13 +96,8 @@ extern asmlinkage void qic_call_function_interrupt(void);
|
|||||||
|
|
||||||
/* SMP */
|
/* SMP */
|
||||||
extern void smp_apic_timer_interrupt(struct pt_regs *);
|
extern void smp_apic_timer_interrupt(struct pt_regs *);
|
||||||
#ifdef CONFIG_X86_32
|
|
||||||
extern void smp_spurious_interrupt(struct pt_regs *);
|
extern void smp_spurious_interrupt(struct pt_regs *);
|
||||||
extern void smp_error_interrupt(struct pt_regs *);
|
extern void smp_error_interrupt(struct pt_regs *);
|
||||||
#else
|
|
||||||
extern asmlinkage void smp_spurious_interrupt(void);
|
|
||||||
extern asmlinkage void smp_error_interrupt(void);
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_X86_SMP
|
#ifdef CONFIG_X86_SMP
|
||||||
extern void smp_reschedule_interrupt(struct pt_regs *);
|
extern void smp_reschedule_interrupt(struct pt_regs *);
|
||||||
extern void smp_call_function_interrupt(struct pt_regs *);
|
extern void smp_call_function_interrupt(struct pt_regs *);
|
||||||
@@ -115,13 +110,13 @@ extern asmlinkage void smp_invalidate_interrupt(struct pt_regs *);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
extern void (*const interrupt[NR_IRQS])(void);
|
extern void (*const interrupt[NR_VECTORS])(void);
|
||||||
#else
|
|
||||||
typedef int vector_irq_t[NR_VECTORS];
|
|
||||||
DECLARE_PER_CPU(vector_irq_t, vector_irq);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_X86_64)
|
typedef int vector_irq_t[NR_VECTORS];
|
||||||
|
DECLARE_PER_CPU(vector_irq_t, vector_irq);
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_IO_APIC
|
||||||
extern void lock_vector_lock(void);
|
extern void lock_vector_lock(void);
|
||||||
extern void unlock_vector_lock(void);
|
extern void unlock_vector_lock(void);
|
||||||
extern void __setup_vector_irq(int cpu);
|
extern void __setup_vector_irq(int cpu);
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <asm/mpspec.h>
|
#include <asm/mpspec.h>
|
||||||
#include <asm/apicdef.h>
|
#include <asm/apicdef.h>
|
||||||
|
#include <asm/irq_vectors.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Intel IO-APIC support for SMP and UP systems.
|
* Intel IO-APIC support for SMP and UP systems.
|
||||||
@@ -87,24 +88,8 @@ struct IO_APIC_route_entry {
|
|||||||
mask : 1, /* 0: enabled, 1: disabled */
|
mask : 1, /* 0: enabled, 1: disabled */
|
||||||
__reserved_2 : 15;
|
__reserved_2 : 15;
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
__u32 __reserved_1 : 24,
|
|
||||||
physical_dest : 4,
|
|
||||||
__reserved_2 : 4;
|
|
||||||
} physical;
|
|
||||||
|
|
||||||
struct {
|
|
||||||
__u32 __reserved_1 : 24,
|
|
||||||
logical_dest : 8;
|
|
||||||
} logical;
|
|
||||||
} dest;
|
|
||||||
#else
|
|
||||||
__u32 __reserved_3 : 24,
|
__u32 __reserved_3 : 24,
|
||||||
dest : 8;
|
dest : 8;
|
||||||
#endif
|
|
||||||
|
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct IR_IO_APIC_route_entry {
|
struct IR_IO_APIC_route_entry {
|
||||||
@@ -203,10 +188,17 @@ extern void restore_IO_APIC_setup(void);
|
|||||||
extern void reinit_intr_remapped_IO_APIC(int);
|
extern void reinit_intr_remapped_IO_APIC(int);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern int probe_nr_irqs(void);
|
||||||
|
|
||||||
#else /* !CONFIG_X86_IO_APIC */
|
#else /* !CONFIG_X86_IO_APIC */
|
||||||
#define io_apic_assign_pci_irqs 0
|
#define io_apic_assign_pci_irqs 0
|
||||||
static const int timer_through_8259 = 0;
|
static const int timer_through_8259 = 0;
|
||||||
static inline void ioapic_init_mappings(void) { }
|
static inline void ioapic_init_mappings(void) { }
|
||||||
|
|
||||||
|
static inline int probe_nr_irqs(void)
|
||||||
|
{
|
||||||
|
return NR_IRQS;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* ASM_X86__IO_APIC_H */
|
#endif /* ASM_X86__IO_APIC_H */
|
||||||
|
@@ -19,19 +19,14 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Reserve the lowest usable priority level 0x20 - 0x2f for triggering
|
* Reserve the lowest usable priority level 0x20 - 0x2f for triggering
|
||||||
* cleanup after irq migration on 64 bit.
|
* cleanup after irq migration.
|
||||||
*/
|
*/
|
||||||
#define IRQ_MOVE_CLEANUP_VECTOR FIRST_EXTERNAL_VECTOR
|
#define IRQ_MOVE_CLEANUP_VECTOR FIRST_EXTERNAL_VECTOR
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Vectors 0x20-0x2f are used for ISA interrupts on 32 bit.
|
* Vectors 0x30-0x3f are used for ISA interrupts.
|
||||||
* Vectors 0x30-0x3f are used for ISA interrupts on 64 bit.
|
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_X86_32
|
|
||||||
#define IRQ0_VECTOR (FIRST_EXTERNAL_VECTOR)
|
|
||||||
#else
|
|
||||||
#define IRQ0_VECTOR (FIRST_EXTERNAL_VECTOR + 0x10)
|
#define IRQ0_VECTOR (FIRST_EXTERNAL_VECTOR + 0x10)
|
||||||
#endif
|
|
||||||
#define IRQ1_VECTOR (IRQ0_VECTOR + 1)
|
#define IRQ1_VECTOR (IRQ0_VECTOR + 1)
|
||||||
#define IRQ2_VECTOR (IRQ0_VECTOR + 2)
|
#define IRQ2_VECTOR (IRQ0_VECTOR + 2)
|
||||||
#define IRQ3_VECTOR (IRQ0_VECTOR + 3)
|
#define IRQ3_VECTOR (IRQ0_VECTOR + 3)
|
||||||
@@ -96,11 +91,7 @@
|
|||||||
* start at 0x31(0x41) to spread out vectors evenly between priority
|
* start at 0x31(0x41) to spread out vectors evenly between priority
|
||||||
* levels. (0x80 is the syscall vector)
|
* levels. (0x80 is the syscall vector)
|
||||||
*/
|
*/
|
||||||
#ifdef CONFIG_X86_32
|
#define FIRST_DEVICE_VECTOR (IRQ15_VECTOR + 2)
|
||||||
# define FIRST_DEVICE_VECTOR 0x31
|
|
||||||
#else
|
|
||||||
# define FIRST_DEVICE_VECTOR (IRQ15_VECTOR + 2)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define NR_VECTORS 256
|
#define NR_VECTORS 256
|
||||||
|
|
||||||
@@ -116,7 +107,6 @@
|
|||||||
# else
|
# else
|
||||||
# define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS))
|
# define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS))
|
||||||
# endif
|
# endif
|
||||||
# define NR_IRQ_VECTORS NR_IRQS
|
|
||||||
|
|
||||||
#elif !defined(CONFIG_X86_VOYAGER)
|
#elif !defined(CONFIG_X86_VOYAGER)
|
||||||
|
|
||||||
@@ -124,23 +114,15 @@
|
|||||||
|
|
||||||
# define NR_IRQS 224
|
# define NR_IRQS 224
|
||||||
|
|
||||||
# if (224 >= 32 * NR_CPUS)
|
|
||||||
# define NR_IRQ_VECTORS NR_IRQS
|
|
||||||
# else
|
|
||||||
# define NR_IRQ_VECTORS (32 * NR_CPUS)
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# else /* IO_APIC || PARAVIRT */
|
# else /* IO_APIC || PARAVIRT */
|
||||||
|
|
||||||
# define NR_IRQS 16
|
# define NR_IRQS 16
|
||||||
# define NR_IRQ_VECTORS NR_IRQS
|
|
||||||
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#else /* !VISWS && !VOYAGER */
|
#else /* !VISWS && !VOYAGER */
|
||||||
|
|
||||||
# define NR_IRQS 224
|
# define NR_IRQS 224
|
||||||
# define NR_IRQ_VECTORS NR_IRQS
|
|
||||||
|
|
||||||
#endif /* VISWS */
|
#endif /* VISWS */
|
||||||
|
|
||||||
|
@@ -14,6 +14,7 @@ BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR)
|
|||||||
BUILD_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
|
BUILD_INTERRUPT(invalidate_interrupt,INVALIDATE_TLB_VECTOR)
|
||||||
BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
|
BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR)
|
||||||
BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR)
|
BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR)
|
||||||
|
BUILD_INTERRUPT(irq_move_cleanup_interrupt,IRQ_MOVE_CLEANUP_VECTOR)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -85,6 +85,20 @@ static inline int apicid_to_node(int logical_apicid)
|
|||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline cpumask_t vector_allocation_domain(int cpu)
|
||||||
|
{
|
||||||
|
/* Careful. Some cpus do not strictly honor the set of cpus
|
||||||
|
* specified in the interrupt destination when using lowest
|
||||||
|
* priority interrupt delivery mode.
|
||||||
|
*
|
||||||
|
* In particular there was a hyperthreading cpu observed to
|
||||||
|
* deliver interrupts to the wrong hyperthread when only one
|
||||||
|
* hyperthread was specified in the interrupt desitination.
|
||||||
|
*/
|
||||||
|
cpumask_t domain = { { [0] = APIC_ALL_CPUS, } };
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
|
static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
|
||||||
@@ -138,6 +152,5 @@ static inline int check_phys_apicid_present(int boot_cpu_physical_apicid)
|
|||||||
static inline void enable_apic_mode(void)
|
static inline void enable_apic_mode(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_X86_LOCAL_APIC */
|
#endif /* CONFIG_X86_LOCAL_APIC */
|
||||||
#endif /* ASM_X86__MACH_DEFAULT__MACH_APIC_H */
|
#endif /* ASM_X86__MACH_DEFAULT__MACH_APIC_H */
|
||||||
|
@@ -1,14 +0,0 @@
|
|||||||
#ifndef ASM_X86__MACH_GENERIC__IRQ_VECTORS_LIMITS_H
|
|
||||||
#define ASM_X86__MACH_GENERIC__IRQ_VECTORS_LIMITS_H
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For Summit or generic (i.e. installer) kernels, we have lots of I/O APICs,
|
|
||||||
* even with uni-proc kernels, so use a big array.
|
|
||||||
*
|
|
||||||
* This value should be the same in both the generic and summit subarches.
|
|
||||||
* Change one, change 'em both.
|
|
||||||
*/
|
|
||||||
#define NR_IRQS 224
|
|
||||||
#define NR_IRQ_VECTORS 1024
|
|
||||||
|
|
||||||
#endif /* ASM_X86__MACH_GENERIC__IRQ_VECTORS_LIMITS_H */
|
|
@@ -24,6 +24,7 @@
|
|||||||
#define check_phys_apicid_present (genapic->check_phys_apicid_present)
|
#define check_phys_apicid_present (genapic->check_phys_apicid_present)
|
||||||
#define check_apicid_used (genapic->check_apicid_used)
|
#define check_apicid_used (genapic->check_apicid_used)
|
||||||
#define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid)
|
#define cpu_mask_to_apicid (genapic->cpu_mask_to_apicid)
|
||||||
|
#define vector_allocation_domain (genapic->vector_allocation_domain)
|
||||||
#define enable_apic_mode (genapic->enable_apic_mode)
|
#define enable_apic_mode (genapic->enable_apic_mode)
|
||||||
#define phys_pkg_id (genapic->phys_pkg_id)
|
#define phys_pkg_id (genapic->phys_pkg_id)
|
||||||
|
|
||||||
|
@@ -12,8 +12,6 @@ static inline cpumask_t target_cpus(void)
|
|||||||
return CPU_MASK_ALL;
|
return CPU_MASK_ALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TARGET_CPUS (target_cpus())
|
|
||||||
|
|
||||||
#define NO_BALANCE_IRQ (1)
|
#define NO_BALANCE_IRQ (1)
|
||||||
#define esr_disable (1)
|
#define esr_disable (1)
|
||||||
|
|
||||||
|
@@ -22,7 +22,6 @@ static inline cpumask_t target_cpus(void)
|
|||||||
*/
|
*/
|
||||||
return cpumask_of_cpu(0);
|
return cpumask_of_cpu(0);
|
||||||
}
|
}
|
||||||
#define TARGET_CPUS (target_cpus())
|
|
||||||
|
|
||||||
#define INT_DELIVERY_MODE (dest_LowestPrio)
|
#define INT_DELIVERY_MODE (dest_LowestPrio)
|
||||||
#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */
|
#define INT_DEST_MODE 1 /* logical delivery broadcast to all procs */
|
||||||
|
@@ -1,14 +0,0 @@
|
|||||||
#ifndef _ASM_IRQ_VECTORS_LIMITS_H
|
|
||||||
#define _ASM_IRQ_VECTORS_LIMITS_H
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For Summit or generic (i.e. installer) kernels, we have lots of I/O APICs,
|
|
||||||
* even with uni-proc kernels, so use a big array.
|
|
||||||
*
|
|
||||||
* This value should be the same in both the generic and summit subarches.
|
|
||||||
* Change one, change 'em both.
|
|
||||||
*/
|
|
||||||
#define NR_IRQS 224
|
|
||||||
#define NR_IRQ_VECTORS 1024
|
|
||||||
|
|
||||||
#endif /* _ASM_IRQ_VECTORS_LIMITS_H */
|
|
@@ -2,9 +2,7 @@
|
|||||||
#define ASM_X86__UV__BIOS_H
|
#define ASM_X86__UV__BIOS_H
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* BIOS layer definitions.
|
* UV BIOS layer definitions.
|
||||||
*
|
|
||||||
* Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved.
|
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -19,11 +17,43 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved.
|
||||||
|
* Copyright (c) Russ Anderson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/rtc.h>
|
#include <linux/rtc.h>
|
||||||
|
|
||||||
#define BIOS_FREQ_BASE 0x01000001
|
/*
|
||||||
|
* Values for the BIOS calls. It is passed as the first * argument in the
|
||||||
|
* BIOS call. Passing any other value in the first argument will result
|
||||||
|
* in a BIOS_STATUS_UNIMPLEMENTED return status.
|
||||||
|
*/
|
||||||
|
enum uv_bios_cmd {
|
||||||
|
UV_BIOS_COMMON,
|
||||||
|
UV_BIOS_GET_SN_INFO,
|
||||||
|
UV_BIOS_FREQ_BASE
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Status values returned from a BIOS call.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
BIOS_STATUS_SUCCESS = 0,
|
||||||
|
BIOS_STATUS_UNIMPLEMENTED = -ENOSYS,
|
||||||
|
BIOS_STATUS_EINVAL = -EINVAL,
|
||||||
|
BIOS_STATUS_UNAVAIL = -EBUSY
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The UV system table describes specific firmware
|
||||||
|
* capabilities available to the Linux kernel at runtime.
|
||||||
|
*/
|
||||||
|
struct uv_systab {
|
||||||
|
char signature[4]; /* must be "UVST" */
|
||||||
|
u32 revision; /* distinguish different firmware revs */
|
||||||
|
u64 function; /* BIOS runtime callback function ptr */
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
BIOS_FREQ_BASE_PLATFORM = 0,
|
BIOS_FREQ_BASE_PLATFORM = 0,
|
||||||
@@ -31,38 +61,34 @@ enum {
|
|||||||
BIOS_FREQ_BASE_REALTIME_CLOCK = 2
|
BIOS_FREQ_BASE_REALTIME_CLOCK = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
# define BIOS_CALL(result, a0, a1, a2, a3, a4, a5, a6, a7) \
|
union partition_info_u {
|
||||||
do { \
|
u64 val;
|
||||||
/* XXX - the real call goes here */ \
|
struct {
|
||||||
result.status = BIOS_STATUS_UNIMPLEMENTED; \
|
u64 hub_version : 8,
|
||||||
isrv.v0 = 0; \
|
partition_id : 16,
|
||||||
isrv.v1 = 0; \
|
coherence_id : 16,
|
||||||
} while (0)
|
region_size : 24;
|
||||||
|
};
|
||||||
enum {
|
|
||||||
BIOS_STATUS_SUCCESS = 0,
|
|
||||||
BIOS_STATUS_UNIMPLEMENTED = -1,
|
|
||||||
BIOS_STATUS_EINVAL = -2,
|
|
||||||
BIOS_STATUS_ERROR = -3
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct uv_bios_retval {
|
/*
|
||||||
/*
|
* bios calls have 6 parameters
|
||||||
* A zero status value indicates call completed without error.
|
*/
|
||||||
* A negative status value indicates reason of call failure.
|
extern s64 uv_bios_call(enum uv_bios_cmd, u64, u64, u64, u64, u64);
|
||||||
* A positive status value indicates success but an
|
extern s64 uv_bios_call_irqsave(enum uv_bios_cmd, u64, u64, u64, u64, u64);
|
||||||
* informational value should be printed (e.g., "reboot for
|
extern s64 uv_bios_call_reentrant(enum uv_bios_cmd, u64, u64, u64, u64, u64);
|
||||||
* change to take effect").
|
|
||||||
*/
|
|
||||||
s64 status;
|
|
||||||
u64 v0;
|
|
||||||
u64 v1;
|
|
||||||
u64 v2;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern long
|
extern s64 uv_bios_get_sn_info(int, int *, long *, long *, long *);
|
||||||
x86_bios_freq_base(unsigned long which, unsigned long *ticks_per_second,
|
extern s64 uv_bios_freq_base(u64, u64 *);
|
||||||
unsigned long *drift_info);
|
|
||||||
extern const char *x86_bios_strerror(long status);
|
extern void uv_bios_init(void);
|
||||||
|
|
||||||
|
extern int uv_type;
|
||||||
|
extern long sn_partition_id;
|
||||||
|
extern long uv_coherency_id;
|
||||||
|
extern long uv_region_size;
|
||||||
|
#define partition_coherence_id() (uv_coherency_id)
|
||||||
|
|
||||||
|
extern struct kobject *sgi_uv_kobj; /* /sys/firmware/sgi_uv */
|
||||||
|
|
||||||
#endif /* ASM_X86__UV__BIOS_H */
|
#endif /* ASM_X86__UV__BIOS_H */
|
||||||
|
36
include/asm-x86/uv/uv_irq.h
Normal file
36
include/asm-x86/uv/uv_irq.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* SGI UV IRQ definitions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ASM_X86__UV__UV_IRQ_H
|
||||||
|
#define ASM_X86__UV__UV_IRQ_H
|
||||||
|
|
||||||
|
/* If a generic version of this structure gets defined, eliminate this one. */
|
||||||
|
struct uv_IO_APIC_route_entry {
|
||||||
|
__u64 vector : 8,
|
||||||
|
delivery_mode : 3,
|
||||||
|
dest_mode : 1,
|
||||||
|
delivery_status : 1,
|
||||||
|
polarity : 1,
|
||||||
|
__reserved_1 : 1,
|
||||||
|
trigger : 1,
|
||||||
|
mask : 1,
|
||||||
|
__reserved_2 : 15,
|
||||||
|
dest : 32;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct irq_chip uv_irq_chip;
|
||||||
|
|
||||||
|
extern int arch_enable_uv_irq(char *, unsigned int, int, int, unsigned long);
|
||||||
|
extern void arch_disable_uv_irq(int, unsigned long);
|
||||||
|
|
||||||
|
extern int uv_setup_irq(char *, int, int, unsigned long);
|
||||||
|
extern void uv_teardown_irq(unsigned int, int, unsigned long);
|
||||||
|
|
||||||
|
#endif /* ASM_X86__UV__UV_IRQ_H */
|
@@ -45,7 +45,6 @@ extern struct list_head dmar_drhd_units;
|
|||||||
list_for_each_entry(drhd, &dmar_drhd_units, list)
|
list_for_each_entry(drhd, &dmar_drhd_units, list)
|
||||||
|
|
||||||
extern int dmar_table_init(void);
|
extern int dmar_table_init(void);
|
||||||
extern int early_dmar_detect(void);
|
|
||||||
extern int dmar_dev_scope_init(void);
|
extern int dmar_dev_scope_init(void);
|
||||||
|
|
||||||
/* Intel IOMMU detection */
|
/* Intel IOMMU detection */
|
||||||
|
@@ -208,6 +208,9 @@ typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_siz
|
|||||||
#define EFI_GLOBAL_VARIABLE_GUID \
|
#define EFI_GLOBAL_VARIABLE_GUID \
|
||||||
EFI_GUID( 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c )
|
EFI_GUID( 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c )
|
||||||
|
|
||||||
|
#define UV_SYSTEM_TABLE_GUID \
|
||||||
|
EFI_GUID( 0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93 )
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
efi_guid_t guid;
|
efi_guid_t guid;
|
||||||
unsigned long table;
|
unsigned long table;
|
||||||
@@ -255,6 +258,7 @@ extern struct efi {
|
|||||||
unsigned long boot_info; /* boot info table */
|
unsigned long boot_info; /* boot info table */
|
||||||
unsigned long hcdp; /* HCDP table */
|
unsigned long hcdp; /* HCDP table */
|
||||||
unsigned long uga; /* UGA table */
|
unsigned long uga; /* UGA table */
|
||||||
|
unsigned long uv_systab; /* UV system table */
|
||||||
efi_get_time_t *get_time;
|
efi_get_time_t *get_time;
|
||||||
efi_set_time_t *set_time;
|
efi_set_time_t *set_time;
|
||||||
efi_get_wakeup_time_t *get_wakeup_time;
|
efi_get_wakeup_time_t *get_wakeup_time;
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#include <linux/preempt.h>
|
#include <linux/preempt.h>
|
||||||
#include <linux/cpumask.h>
|
#include <linux/cpumask.h>
|
||||||
#include <linux/irqreturn.h>
|
#include <linux/irqreturn.h>
|
||||||
|
#include <linux/irqnr.h>
|
||||||
#include <linux/hardirq.h>
|
#include <linux/hardirq.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/irqflags.h>
|
#include <linux/irqflags.h>
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/cpumask.h>
|
#include <linux/cpumask.h>
|
||||||
#include <linux/irqreturn.h>
|
#include <linux/irqreturn.h>
|
||||||
|
#include <linux/irqnr.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
|
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
@@ -152,6 +153,7 @@ struct irq_chip {
|
|||||||
* @name: flow handler name for /proc/interrupts output
|
* @name: flow handler name for /proc/interrupts output
|
||||||
*/
|
*/
|
||||||
struct irq_desc {
|
struct irq_desc {
|
||||||
|
unsigned int irq;
|
||||||
irq_flow_handler_t handle_irq;
|
irq_flow_handler_t handle_irq;
|
||||||
struct irq_chip *chip;
|
struct irq_chip *chip;
|
||||||
struct msi_desc *msi_desc;
|
struct msi_desc *msi_desc;
|
||||||
@@ -170,7 +172,7 @@ struct irq_desc {
|
|||||||
cpumask_t affinity;
|
cpumask_t affinity;
|
||||||
unsigned int cpu;
|
unsigned int cpu;
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
|
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
||||||
cpumask_t pending_mask;
|
cpumask_t pending_mask;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
@@ -179,8 +181,14 @@ struct irq_desc {
|
|||||||
const char *name;
|
const char *name;
|
||||||
} ____cacheline_internodealigned_in_smp;
|
} ____cacheline_internodealigned_in_smp;
|
||||||
|
|
||||||
|
|
||||||
extern struct irq_desc irq_desc[NR_IRQS];
|
extern struct irq_desc irq_desc[NR_IRQS];
|
||||||
|
|
||||||
|
static inline struct irq_desc *irq_to_desc(unsigned int irq)
|
||||||
|
{
|
||||||
|
return (irq < nr_irqs) ? irq_desc + irq : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Migration helpers for obsolete names, they will go away:
|
* Migration helpers for obsolete names, they will go away:
|
||||||
*/
|
*/
|
||||||
@@ -198,19 +206,15 @@ extern int setup_irq(unsigned int irq, struct irqaction *new);
|
|||||||
|
|
||||||
#ifdef CONFIG_GENERIC_HARDIRQS
|
#ifdef CONFIG_GENERIC_HARDIRQS
|
||||||
|
|
||||||
#ifndef handle_dynamic_tick
|
|
||||||
# define handle_dynamic_tick(a) do { } while (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
|
|
||||||
#if defined(CONFIG_GENERIC_PENDING_IRQ) || defined(CONFIG_IRQBALANCE)
|
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
||||||
|
|
||||||
void set_pending_irq(unsigned int irq, cpumask_t mask);
|
void set_pending_irq(unsigned int irq, cpumask_t mask);
|
||||||
void move_native_irq(int irq);
|
void move_native_irq(int irq);
|
||||||
void move_masked_irq(int irq);
|
void move_masked_irq(int irq);
|
||||||
|
|
||||||
#else /* CONFIG_GENERIC_PENDING_IRQ || CONFIG_IRQBALANCE */
|
#else /* CONFIG_GENERIC_PENDING_IRQ */
|
||||||
|
|
||||||
static inline void move_irq(int irq)
|
static inline void move_irq(int irq)
|
||||||
{
|
{
|
||||||
@@ -237,19 +241,14 @@ static inline void set_pending_irq(unsigned int irq, cpumask_t mask)
|
|||||||
|
|
||||||
#endif /* CONFIG_SMP */
|
#endif /* CONFIG_SMP */
|
||||||
|
|
||||||
#ifdef CONFIG_IRQBALANCE
|
|
||||||
extern void set_balance_irq_affinity(unsigned int irq, cpumask_t mask);
|
|
||||||
#else
|
|
||||||
static inline void set_balance_irq_affinity(unsigned int irq, cpumask_t mask)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern int no_irq_affinity;
|
extern int no_irq_affinity;
|
||||||
|
|
||||||
static inline int irq_balancing_disabled(unsigned int irq)
|
static inline int irq_balancing_disabled(unsigned int irq)
|
||||||
{
|
{
|
||||||
return irq_desc[irq].status & IRQ_NO_BALANCING_MASK;
|
struct irq_desc *desc;
|
||||||
|
|
||||||
|
desc = irq_to_desc(irq);
|
||||||
|
return desc->status & IRQ_NO_BALANCING_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle irq action chains: */
|
/* Handle irq action chains: */
|
||||||
@@ -279,10 +278,8 @@ extern unsigned int __do_IRQ(unsigned int irq);
|
|||||||
* irqchip-style controller then we call the ->handle_irq() handler,
|
* irqchip-style controller then we call the ->handle_irq() handler,
|
||||||
* and it calls __do_IRQ() if it's attached to an irqtype-style controller.
|
* and it calls __do_IRQ() if it's attached to an irqtype-style controller.
|
||||||
*/
|
*/
|
||||||
static inline void generic_handle_irq(unsigned int irq)
|
static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *desc)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc = irq_desc + irq;
|
|
||||||
|
|
||||||
#ifdef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
|
#ifdef CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ
|
||||||
desc->handle_irq(irq, desc);
|
desc->handle_irq(irq, desc);
|
||||||
#else
|
#else
|
||||||
@@ -293,6 +290,11 @@ static inline void generic_handle_irq(unsigned int irq)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void generic_handle_irq(unsigned int irq)
|
||||||
|
{
|
||||||
|
generic_handle_irq_desc(irq, irq_to_desc(irq));
|
||||||
|
}
|
||||||
|
|
||||||
/* Handling of unhandled and spurious interrupts: */
|
/* Handling of unhandled and spurious interrupts: */
|
||||||
extern void note_interrupt(unsigned int irq, struct irq_desc *desc,
|
extern void note_interrupt(unsigned int irq, struct irq_desc *desc,
|
||||||
int action_ret);
|
int action_ret);
|
||||||
@@ -325,7 +327,10 @@ __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
|
|||||||
static inline void __set_irq_handler_unlocked(int irq,
|
static inline void __set_irq_handler_unlocked(int irq,
|
||||||
irq_flow_handler_t handler)
|
irq_flow_handler_t handler)
|
||||||
{
|
{
|
||||||
irq_desc[irq].handle_irq = handler;
|
struct irq_desc *desc;
|
||||||
|
|
||||||
|
desc = irq_to_desc(irq);
|
||||||
|
desc->handle_irq = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -353,13 +358,14 @@ 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 int create_irq(void);
|
extern int create_irq(void);
|
||||||
extern void destroy_irq(unsigned int irq);
|
extern void destroy_irq(unsigned int irq);
|
||||||
|
|
||||||
/* Test to see if a driver has successfully requested an irq */
|
/* Test to see if a driver has successfully requested an irq */
|
||||||
static inline int irq_has_action(unsigned int irq)
|
static inline int irq_has_action(unsigned int irq)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc = irq_desc + irq;
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
return desc->action != NULL;
|
return desc->action != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,10 +380,10 @@ extern int set_irq_chip_data(unsigned int irq, void *data);
|
|||||||
extern int set_irq_type(unsigned int irq, unsigned int type);
|
extern int set_irq_type(unsigned int irq, unsigned int type);
|
||||||
extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);
|
extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);
|
||||||
|
|
||||||
#define get_irq_chip(irq) (irq_desc[irq].chip)
|
#define get_irq_chip(irq) (irq_to_desc(irq)->chip)
|
||||||
#define get_irq_chip_data(irq) (irq_desc[irq].chip_data)
|
#define get_irq_chip_data(irq) (irq_to_desc(irq)->chip_data)
|
||||||
#define get_irq_data(irq) (irq_desc[irq].handler_data)
|
#define get_irq_data(irq) (irq_to_desc(irq)->handler_data)
|
||||||
#define get_irq_msi(irq) (irq_desc[irq].msi_desc)
|
#define get_irq_msi(irq) (irq_to_desc(irq)->msi_desc)
|
||||||
|
|
||||||
#endif /* CONFIG_GENERIC_HARDIRQS */
|
#endif /* CONFIG_GENERIC_HARDIRQS */
|
||||||
|
|
||||||
|
24
include/linux/irqnr.h
Normal file
24
include/linux/irqnr.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#ifndef _LINUX_IRQNR_H
|
||||||
|
#define _LINUX_IRQNR_H
|
||||||
|
|
||||||
|
#ifndef CONFIG_GENERIC_HARDIRQS
|
||||||
|
#include <asm/irq.h>
|
||||||
|
# define nr_irqs NR_IRQS
|
||||||
|
|
||||||
|
# define for_each_irq_desc(irq, desc) \
|
||||||
|
for (irq = 0; irq < nr_irqs; irq++)
|
||||||
|
#else
|
||||||
|
extern int nr_irqs;
|
||||||
|
|
||||||
|
# define for_each_irq_desc(irq, desc) \
|
||||||
|
for (irq = 0, desc = irq_desc; irq < nr_irqs; irq++, desc++)
|
||||||
|
|
||||||
|
# define for_each_irq_desc_reverse(irq, desc) \
|
||||||
|
for (irq = nr_irqs -1, desc = irq_desc + (nr_irqs -1 ); \
|
||||||
|
irq > 0; irq--, desc--)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define for_each_irq_nr(irq) \
|
||||||
|
for (irq = 0; irq < nr_irqs; irq++)
|
||||||
|
|
||||||
|
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user