Merge branches 'irq/sparseirq', 'x86/quirks' and 'x86/reboot' into cpus4096
We merge the irq/sparseirq, x86/quirks and x86/reboot trees into the cpus4096 tree because the io-apic changes in the sparseirq change conflict with the cpumask changes in the cpumask tree, and we want to resolve those.
This commit is contained in:
commit
8299608f14
@ -241,6 +241,16 @@ config X86_HAS_BOOT_CPU_ID
|
|||||||
def_bool y
|
def_bool y
|
||||||
depends on X86_VOYAGER
|
depends on X86_VOYAGER
|
||||||
|
|
||||||
|
config SPARSE_IRQ
|
||||||
|
bool "Support sparse irq numbering"
|
||||||
|
depends on (PCI_MSI || HT_IRQ) && SMP
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
This enables support for sparse irq, esp for msi/msi-x. You may need
|
||||||
|
if you have lots of cards supports msi-x installed.
|
||||||
|
|
||||||
|
If you don't know what to do here, say Y.
|
||||||
|
|
||||||
config X86_FIND_SMP_CONFIG
|
config X86_FIND_SMP_CONFIG
|
||||||
def_bool y
|
def_bool y
|
||||||
depends on X86_MPPARSE || X86_VOYAGER
|
depends on X86_MPPARSE || X86_VOYAGER
|
||||||
@ -468,10 +478,6 @@ config X86_CYCLONE_TIMER
|
|||||||
def_bool y
|
def_bool y
|
||||||
depends on X86_GENERICARCH
|
depends on X86_GENERICARCH
|
||||||
|
|
||||||
config ES7000_CLUSTERED_APIC
|
|
||||||
def_bool y
|
|
||||||
depends on SMP && X86_ES7000 && MPENTIUMIII
|
|
||||||
|
|
||||||
source "arch/x86/Kconfig.cpu"
|
source "arch/x86/Kconfig.cpu"
|
||||||
|
|
||||||
config HPET_TIMER
|
config HPET_TIMER
|
||||||
@ -1635,13 +1641,6 @@ config APM_ALLOW_INTS
|
|||||||
many of the newer IBM Thinkpads. If you experience hangs when you
|
many of the newer IBM Thinkpads. If you experience hangs when you
|
||||||
suspend, try setting this to Y. Otherwise, say N.
|
suspend, try setting this to Y. Otherwise, say N.
|
||||||
|
|
||||||
config APM_REAL_MODE_POWER_OFF
|
|
||||||
bool "Use real mode APM BIOS call to power off"
|
|
||||||
help
|
|
||||||
Use real mode APM BIOS calls to switch off the computer. This is
|
|
||||||
a work-around for a number of buggy BIOSes. Switch this option on if
|
|
||||||
your computer crashes instead of powering off properly.
|
|
||||||
|
|
||||||
endif # APM
|
endif # APM
|
||||||
|
|
||||||
source "arch/x86/kernel/cpu/cpufreq/Kconfig"
|
source "arch/x86/kernel/cpu/cpufreq/Kconfig"
|
||||||
|
@ -193,6 +193,7 @@ extern u8 setup_APIC_eilvt_ibs(u8 vector, u8 msg_type, u8 mask);
|
|||||||
static inline void lapic_shutdown(void) { }
|
static inline void lapic_shutdown(void) { }
|
||||||
#define local_apic_timer_c2_ok 1
|
#define local_apic_timer_c2_ok 1
|
||||||
static inline void init_apic_mappings(void) { }
|
static inline void init_apic_mappings(void) { }
|
||||||
|
static inline void disable_local_APIC(void) { }
|
||||||
|
|
||||||
#endif /* !CONFIG_X86_LOCAL_APIC */
|
#endif /* !CONFIG_X86_LOCAL_APIC */
|
||||||
|
|
||||||
|
@ -24,8 +24,6 @@ static inline cpumask_t target_cpus(void)
|
|||||||
#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 */
|
||||||
#define NO_BALANCE_IRQ (0)
|
#define NO_BALANCE_IRQ (0)
|
||||||
#define WAKE_SECONDARY_VIA_INIT
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,9 @@ enum reboot_type {
|
|||||||
BOOT_BIOS = 'b',
|
BOOT_BIOS = 'b',
|
||||||
#endif
|
#endif
|
||||||
BOOT_ACPI = 'a',
|
BOOT_ACPI = 'a',
|
||||||
BOOT_EFI = 'e'
|
BOOT_EFI = 'e',
|
||||||
|
BOOT_CF9 = 'p',
|
||||||
|
BOOT_CF9_COND = 'q',
|
||||||
};
|
};
|
||||||
|
|
||||||
extern enum reboot_type reboot_type;
|
extern enum reboot_type reboot_type;
|
||||||
|
@ -9,31 +9,27 @@ static inline int apic_id_registered(void)
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline cpumask_t target_cpus(void)
|
static inline cpumask_t target_cpus_cluster(void)
|
||||||
{
|
{
|
||||||
#if defined CONFIG_ES7000_CLUSTERED_APIC
|
|
||||||
return CPU_MASK_ALL;
|
return CPU_MASK_ALL;
|
||||||
#else
|
|
||||||
return cpumask_of_cpu(smp_processor_id());
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined CONFIG_ES7000_CLUSTERED_APIC
|
static inline cpumask_t target_cpus(void)
|
||||||
#define APIC_DFR_VALUE (APIC_DFR_CLUSTER)
|
{
|
||||||
#define INT_DELIVERY_MODE (dest_LowestPrio)
|
return cpumask_of_cpu(smp_processor_id());
|
||||||
#define INT_DEST_MODE (1) /* logical delivery broadcast to all procs */
|
}
|
||||||
#define NO_BALANCE_IRQ (1)
|
|
||||||
#undef WAKE_SECONDARY_VIA_INIT
|
#define APIC_DFR_VALUE_CLUSTER (APIC_DFR_CLUSTER)
|
||||||
#define WAKE_SECONDARY_VIA_MIP
|
#define INT_DELIVERY_MODE_CLUSTER (dest_LowestPrio)
|
||||||
#else
|
#define INT_DEST_MODE_CLUSTER (1) /* logical delivery broadcast to all procs */
|
||||||
|
#define NO_BALANCE_IRQ_CLUSTER (1)
|
||||||
|
|
||||||
#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 procs */
|
#define INT_DEST_MODE (0) /* phys delivery to target procs */
|
||||||
#define NO_BALANCE_IRQ (0)
|
#define NO_BALANCE_IRQ (0)
|
||||||
#undef APIC_DEST_LOGICAL
|
#undef APIC_DEST_LOGICAL
|
||||||
#define APIC_DEST_LOGICAL 0x0
|
#define APIC_DEST_LOGICAL 0x0
|
||||||
#define WAKE_SECONDARY_VIA_INIT
|
|
||||||
#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)
|
||||||
{
|
{
|
||||||
@ -60,6 +56,16 @@ static inline unsigned long calculate_ldr(int cpu)
|
|||||||
* an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
|
* an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
|
||||||
* document number 292116). So here it goes...
|
* document number 292116). So here it goes...
|
||||||
*/
|
*/
|
||||||
|
static inline void init_apic_ldr_cluster(void)
|
||||||
|
{
|
||||||
|
unsigned long val;
|
||||||
|
int cpu = smp_processor_id();
|
||||||
|
|
||||||
|
apic_write(APIC_DFR, APIC_DFR_VALUE_CLUSTER);
|
||||||
|
val = calculate_ldr(cpu);
|
||||||
|
apic_write(APIC_LDR, val);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void init_apic_ldr(void)
|
static inline void init_apic_ldr(void)
|
||||||
{
|
{
|
||||||
unsigned long val;
|
unsigned long val;
|
||||||
@ -70,10 +76,6 @@ static inline void init_apic_ldr(void)
|
|||||||
apic_write(APIC_LDR, val);
|
apic_write(APIC_LDR, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_X86_GENERICARCH
|
|
||||||
extern void enable_apic_mode(void);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern int apic_version [MAX_APICS];
|
extern int apic_version [MAX_APICS];
|
||||||
static inline void setup_apic_routing(void)
|
static inline void setup_apic_routing(void)
|
||||||
{
|
{
|
||||||
@ -144,7 +146,7 @@ static inline int check_phys_apicid_present(int cpu_physical_apicid)
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
|
static inline unsigned int cpu_mask_to_apicid_cluster(cpumask_t cpumask)
|
||||||
{
|
{
|
||||||
int num_bits_set;
|
int num_bits_set;
|
||||||
int cpus_found = 0;
|
int cpus_found = 0;
|
||||||
@ -154,11 +156,7 @@ static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
|
|||||||
num_bits_set = cpus_weight(cpumask);
|
num_bits_set = cpus_weight(cpumask);
|
||||||
/* Return id to all */
|
/* Return id to all */
|
||||||
if (num_bits_set == NR_CPUS)
|
if (num_bits_set == NR_CPUS)
|
||||||
#if defined CONFIG_ES7000_CLUSTERED_APIC
|
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
#else
|
|
||||||
return cpu_to_logical_apicid(0);
|
|
||||||
#endif
|
|
||||||
/*
|
/*
|
||||||
* The cpus in the mask must all be on the apic cluster. If are not
|
* The cpus in the mask must all be on the apic cluster. If are not
|
||||||
* on the same apicid cluster return default value of TARGET_CPUS.
|
* on the same apicid cluster return default value of TARGET_CPUS.
|
||||||
@ -171,11 +169,40 @@ static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
|
|||||||
if (apicid_cluster(apicid) !=
|
if (apicid_cluster(apicid) !=
|
||||||
apicid_cluster(new_apicid)){
|
apicid_cluster(new_apicid)){
|
||||||
printk ("%s: Not a valid mask!\n", __func__);
|
printk ("%s: Not a valid mask!\n", __func__);
|
||||||
#if defined CONFIG_ES7000_CLUSTERED_APIC
|
|
||||||
return 0xFF;
|
return 0xFF;
|
||||||
#else
|
}
|
||||||
|
apicid = new_apicid;
|
||||||
|
cpus_found++;
|
||||||
|
}
|
||||||
|
cpu++;
|
||||||
|
}
|
||||||
|
return apicid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int cpu_mask_to_apicid(cpumask_t cpumask)
|
||||||
|
{
|
||||||
|
int num_bits_set;
|
||||||
|
int cpus_found = 0;
|
||||||
|
int cpu;
|
||||||
|
int apicid;
|
||||||
|
|
||||||
|
num_bits_set = cpus_weight(cpumask);
|
||||||
|
/* Return id to all */
|
||||||
|
if (num_bits_set == NR_CPUS)
|
||||||
|
return cpu_to_logical_apicid(0);
|
||||||
|
/*
|
||||||
|
* The cpus in the mask must all be on the apic cluster. If are not
|
||||||
|
* on the same apicid cluster return default value of TARGET_CPUS.
|
||||||
|
*/
|
||||||
|
cpu = first_cpu(cpumask);
|
||||||
|
apicid = cpu_to_logical_apicid(cpu);
|
||||||
|
while (cpus_found < num_bits_set) {
|
||||||
|
if (cpu_isset(cpu, cpumask)) {
|
||||||
|
int new_apicid = cpu_to_logical_apicid(cpu);
|
||||||
|
if (apicid_cluster(apicid) !=
|
||||||
|
apicid_cluster(new_apicid)){
|
||||||
|
printk ("%s: Not a valid mask!\n", __func__);
|
||||||
return cpu_to_logical_apicid(0);
|
return cpu_to_logical_apicid(0);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
apicid = new_apicid;
|
apicid = new_apicid;
|
||||||
cpus_found++;
|
cpus_found++;
|
||||||
|
@ -1,36 +1,12 @@
|
|||||||
#ifndef __ASM_ES7000_WAKECPU_H
|
#ifndef __ASM_ES7000_WAKECPU_H
|
||||||
#define __ASM_ES7000_WAKECPU_H
|
#define __ASM_ES7000_WAKECPU_H
|
||||||
|
|
||||||
/*
|
#define TRAMPOLINE_PHYS_LOW 0x467
|
||||||
* This file copes with machines that wakeup secondary CPUs by the
|
#define TRAMPOLINE_PHYS_HIGH 0x469
|
||||||
* INIT, INIT, STARTUP sequence.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef CONFIG_ES7000_CLUSTERED_APIC
|
|
||||||
#define WAKE_SECONDARY_VIA_MIP
|
|
||||||
#else
|
|
||||||
#define WAKE_SECONDARY_VIA_INIT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WAKE_SECONDARY_VIA_MIP
|
|
||||||
extern int es7000_start_cpu(int cpu, unsigned long eip);
|
|
||||||
static inline int
|
|
||||||
wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
|
|
||||||
{
|
|
||||||
int boot_error = 0;
|
|
||||||
boot_error = es7000_start_cpu(phys_apicid, start_eip);
|
|
||||||
return boot_error;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TRAMPOLINE_LOW phys_to_virt(0x467)
|
|
||||||
#define TRAMPOLINE_HIGH phys_to_virt(0x469)
|
|
||||||
|
|
||||||
#define boot_cpu_apicid boot_cpu_physical_apicid
|
|
||||||
|
|
||||||
static inline void wait_for_init_deassert(atomic_t *deassert)
|
static inline void wait_for_init_deassert(atomic_t *deassert)
|
||||||
{
|
{
|
||||||
#ifdef WAKE_SECONDARY_VIA_INIT
|
#ifndef CONFIG_ES7000_CLUSTERED_APIC
|
||||||
while (!atomic_read(deassert))
|
while (!atomic_read(deassert))
|
||||||
cpu_relax();
|
cpu_relax();
|
||||||
#endif
|
#endif
|
||||||
@ -50,9 +26,12 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#define inquire_remote_apic(apicid) do { \
|
extern void __inquire_remote_apic(int apicid);
|
||||||
if (apic_verbosity >= APIC_DEBUG) \
|
|
||||||
__inquire_remote_apic(apicid); \
|
static inline void inquire_remote_apic(int apicid)
|
||||||
} while (0)
|
{
|
||||||
|
if (apic_verbosity >= APIC_DEBUG)
|
||||||
|
__inquire_remote_apic(apicid);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __ASM_MACH_WAKECPU_H */
|
#endif /* __ASM_MACH_WAKECPU_H */
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define _ASM_X86_GENAPIC_32_H
|
#define _ASM_X86_GENAPIC_32_H
|
||||||
|
|
||||||
#include <asm/mpspec.h>
|
#include <asm/mpspec.h>
|
||||||
|
#include <asm/atomic.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generic APIC driver interface.
|
* Generic APIC driver interface.
|
||||||
@ -65,6 +66,14 @@ struct genapic {
|
|||||||
void (*send_IPI_allbutself)(int vector);
|
void (*send_IPI_allbutself)(int vector);
|
||||||
void (*send_IPI_all)(int vector);
|
void (*send_IPI_all)(int vector);
|
||||||
#endif
|
#endif
|
||||||
|
int (*wakeup_cpu)(int apicid, unsigned long start_eip);
|
||||||
|
int trampoline_phys_low;
|
||||||
|
int trampoline_phys_high;
|
||||||
|
void (*wait_for_init_deassert)(atomic_t *deassert);
|
||||||
|
void (*smp_callin_clear_local_apic)(void);
|
||||||
|
void (*store_NMI_vector)(unsigned short *high, unsigned short *low);
|
||||||
|
void (*restore_NMI_vector)(unsigned short *high, unsigned short *low);
|
||||||
|
void (*inquire_remote_apic)(int apicid);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define APICFUNC(x) .x = x,
|
#define APICFUNC(x) .x = x,
|
||||||
@ -112,9 +121,17 @@ struct genapic {
|
|||||||
IPIFUNC(send_IPI_all) \
|
IPIFUNC(send_IPI_all) \
|
||||||
APICFUNC(enable_apic_mode) \
|
APICFUNC(enable_apic_mode) \
|
||||||
APICFUNC(phys_pkg_id) \
|
APICFUNC(phys_pkg_id) \
|
||||||
|
.trampoline_phys_low = TRAMPOLINE_PHYS_LOW, \
|
||||||
|
.trampoline_phys_high = TRAMPOLINE_PHYS_HIGH, \
|
||||||
|
APICFUNC(wait_for_init_deassert) \
|
||||||
|
APICFUNC(smp_callin_clear_local_apic) \
|
||||||
|
APICFUNC(store_NMI_vector) \
|
||||||
|
APICFUNC(restore_NMI_vector) \
|
||||||
|
APICFUNC(inquire_remote_apic) \
|
||||||
}
|
}
|
||||||
|
|
||||||
extern struct genapic *genapic;
|
extern struct genapic *genapic;
|
||||||
|
extern void es7000_update_genapic_to_cluster(void);
|
||||||
|
|
||||||
enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC};
|
enum uv_system_type {UV_NONE, UV_LEGACY_APIC, UV_X2APIC, UV_NON_UNIQUE_APIC};
|
||||||
#define get_uv_system_type() UV_NONE
|
#define get_uv_system_type() UV_NONE
|
||||||
|
@ -32,6 +32,8 @@ struct genapic {
|
|||||||
unsigned int (*get_apic_id)(unsigned long x);
|
unsigned int (*get_apic_id)(unsigned long x);
|
||||||
unsigned long (*set_apic_id)(unsigned int id);
|
unsigned long (*set_apic_id)(unsigned int id);
|
||||||
unsigned long apic_id_mask;
|
unsigned long apic_id_mask;
|
||||||
|
/* wakeup_secondary_cpu */
|
||||||
|
int (*wakeup_cpu)(int apicid, unsigned long start_eip);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct genapic *genapic;
|
extern struct genapic *genapic;
|
||||||
|
@ -188,17 +188,14 @@ 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);
|
extern void probe_nr_irqs_gsi(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)
|
static inline void probe_nr_irqs_gsi(void) { }
|
||||||
{
|
|
||||||
return NR_IRQS;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _ASM_X86_IO_APIC_H */
|
#endif /* _ASM_X86_IO_APIC_H */
|
||||||
|
@ -101,12 +101,23 @@
|
|||||||
#define LAST_VM86_IRQ 15
|
#define LAST_VM86_IRQ 15
|
||||||
#define invalid_vm86_irq(irq) ((irq) < 3 || (irq) > 15)
|
#define invalid_vm86_irq(irq) ((irq) < 3 || (irq) > 15)
|
||||||
|
|
||||||
|
#define NR_IRQS_LEGACY 16
|
||||||
|
|
||||||
#if defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_VOYAGER)
|
#if defined(CONFIG_X86_IO_APIC) && !defined(CONFIG_X86_VOYAGER)
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPARSE_IRQ
|
||||||
# if NR_CPUS < MAX_IO_APICS
|
# if NR_CPUS < MAX_IO_APICS
|
||||||
# define NR_IRQS (NR_VECTORS + (32 * NR_CPUS))
|
# define NR_IRQS (NR_VECTORS + (32 * NR_CPUS))
|
||||||
# else
|
# else
|
||||||
# define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS))
|
# define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS))
|
||||||
# endif
|
# endif
|
||||||
|
#else
|
||||||
|
# if (8 * NR_CPUS) > (32 * MAX_IO_APICS)
|
||||||
|
# define NR_IRQS (NR_VECTORS + (8 * NR_CPUS))
|
||||||
|
# else
|
||||||
|
# define NR_IRQS (NR_VECTORS + (32 * MAX_IO_APICS))
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#elif defined(CONFIG_X86_VOYAGER)
|
#elif defined(CONFIG_X86_VOYAGER)
|
||||||
|
|
||||||
|
@ -32,11 +32,13 @@ static inline cpumask_t target_cpus(void)
|
|||||||
#define vector_allocation_domain (genapic->vector_allocation_domain)
|
#define vector_allocation_domain (genapic->vector_allocation_domain)
|
||||||
#define read_apic_id() (GET_APIC_ID(apic_read(APIC_ID)))
|
#define read_apic_id() (GET_APIC_ID(apic_read(APIC_ID)))
|
||||||
#define send_IPI_self (genapic->send_IPI_self)
|
#define send_IPI_self (genapic->send_IPI_self)
|
||||||
|
#define wakeup_secondary_cpu (genapic->wakeup_cpu)
|
||||||
extern void setup_apic_routing(void);
|
extern void setup_apic_routing(void);
|
||||||
#else
|
#else
|
||||||
#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 */
|
||||||
#define TARGET_CPUS (target_cpus())
|
#define TARGET_CPUS (target_cpus())
|
||||||
|
#define wakeup_secondary_cpu wakeup_secondary_cpu_via_init
|
||||||
/*
|
/*
|
||||||
* Set up the logical destination ID.
|
* Set up the logical destination ID.
|
||||||
*
|
*
|
||||||
|
@ -1,17 +1,8 @@
|
|||||||
#ifndef _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H
|
#ifndef _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H
|
||||||
#define _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H
|
#define _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H
|
||||||
|
|
||||||
/*
|
#define TRAMPOLINE_PHYS_LOW (0x467)
|
||||||
* This file copes with machines that wakeup secondary CPUs by the
|
#define TRAMPOLINE_PHYS_HIGH (0x469)
|
||||||
* INIT, INIT, STARTUP sequence.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define WAKE_SECONDARY_VIA_INIT
|
|
||||||
|
|
||||||
#define TRAMPOLINE_LOW phys_to_virt(0x467)
|
|
||||||
#define TRAMPOLINE_HIGH phys_to_virt(0x469)
|
|
||||||
|
|
||||||
#define boot_cpu_apicid boot_cpu_physical_apicid
|
|
||||||
|
|
||||||
static inline void wait_for_init_deassert(atomic_t *deassert)
|
static inline void wait_for_init_deassert(atomic_t *deassert)
|
||||||
{
|
{
|
||||||
@ -33,9 +24,12 @@ static inline void restore_NMI_vector(unsigned short *high, unsigned short *low)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#define inquire_remote_apic(apicid) do { \
|
extern void __inquire_remote_apic(int apicid);
|
||||||
if (apic_verbosity >= APIC_DEBUG) \
|
|
||||||
__inquire_remote_apic(apicid); \
|
static inline void inquire_remote_apic(int apicid)
|
||||||
} while (0)
|
{
|
||||||
|
if (apic_verbosity >= APIC_DEBUG)
|
||||||
|
__inquire_remote_apic(apicid);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H */
|
#endif /* _ASM_X86_MACH_DEFAULT_MACH_WAKECPU_H */
|
||||||
|
@ -13,9 +13,11 @@ static inline void smpboot_setup_warm_reset_vector(unsigned long start_eip)
|
|||||||
CMOS_WRITE(0xa, 0xf);
|
CMOS_WRITE(0xa, 0xf);
|
||||||
local_flush_tlb();
|
local_flush_tlb();
|
||||||
pr_debug("1.\n");
|
pr_debug("1.\n");
|
||||||
*((volatile unsigned short *) TRAMPOLINE_HIGH) = start_eip >> 4;
|
*((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) =
|
||||||
|
start_eip >> 4;
|
||||||
pr_debug("2.\n");
|
pr_debug("2.\n");
|
||||||
*((volatile unsigned short *) TRAMPOLINE_LOW) = start_eip & 0xf;
|
*((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) =
|
||||||
|
start_eip & 0xf;
|
||||||
pr_debug("3.\n");
|
pr_debug("3.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +34,7 @@ static inline void smpboot_restore_warm_reset_vector(void)
|
|||||||
*/
|
*/
|
||||||
CMOS_WRITE(0, 0xf);
|
CMOS_WRITE(0, 0xf);
|
||||||
|
|
||||||
*((volatile long *) phys_to_virt(0x467)) = 0;
|
*((volatile long *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __init smpboot_setup_io_apic(void)
|
static inline void __init smpboot_setup_io_apic(void)
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#define vector_allocation_domain (genapic->vector_allocation_domain)
|
#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)
|
||||||
|
#define wakeup_secondary_cpu (genapic->wakeup_cpu)
|
||||||
|
|
||||||
extern void generic_bigsmp_probe(void);
|
extern void generic_bigsmp_probe(void);
|
||||||
|
|
||||||
|
12
arch/x86/include/asm/mach-generic/mach_wakecpu.h
Normal file
12
arch/x86/include/asm/mach-generic/mach_wakecpu.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H
|
||||||
|
#define _ASM_X86_MACH_GENERIC_MACH_WAKECPU_H
|
||||||
|
|
||||||
|
#define TRAMPOLINE_PHYS_LOW (genapic->trampoline_phys_low)
|
||||||
|
#define TRAMPOLINE_PHYS_HIGH (genapic->trampoline_phys_high)
|
||||||
|
#define wait_for_init_deassert (genapic->wait_for_init_deassert)
|
||||||
|
#define smp_callin_clear_local_apic (genapic->smp_callin_clear_local_apic)
|
||||||
|
#define store_NMI_vector (genapic->store_NMI_vector)
|
||||||
|
#define restore_NMI_vector (genapic->restore_NMI_vector)
|
||||||
|
#define inquire_remote_apic (genapic->inquire_remote_apic)
|
||||||
|
|
||||||
|
#endif /* _ASM_X86_MACH_GENERIC_MACH_APIC_H */
|
@ -3,12 +3,8 @@
|
|||||||
|
|
||||||
/* This file copes with machines that wakeup secondary CPUs by NMIs */
|
/* This file copes with machines that wakeup secondary CPUs by NMIs */
|
||||||
|
|
||||||
#define WAKE_SECONDARY_VIA_NMI
|
#define TRAMPOLINE_PHYS_LOW (0x8)
|
||||||
|
#define TRAMPOLINE_PHYS_HIGH (0xa)
|
||||||
#define TRAMPOLINE_LOW phys_to_virt(0x8)
|
|
||||||
#define TRAMPOLINE_HIGH phys_to_virt(0xa)
|
|
||||||
|
|
||||||
#define boot_cpu_apicid boot_cpu_logical_apicid
|
|
||||||
|
|
||||||
/* We don't do anything here because we use NMI's to boot instead */
|
/* We don't do anything here because we use NMI's to boot instead */
|
||||||
static inline void wait_for_init_deassert(atomic_t *deassert)
|
static inline void wait_for_init_deassert(atomic_t *deassert)
|
||||||
@ -27,17 +23,23 @@ static inline void smp_callin_clear_local_apic(void)
|
|||||||
static inline void store_NMI_vector(unsigned short *high, unsigned short *low)
|
static inline void store_NMI_vector(unsigned short *high, unsigned short *low)
|
||||||
{
|
{
|
||||||
printk("Storing NMI vector\n");
|
printk("Storing NMI vector\n");
|
||||||
*high = *((volatile unsigned short *) TRAMPOLINE_HIGH);
|
*high =
|
||||||
*low = *((volatile unsigned short *) TRAMPOLINE_LOW);
|
*((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH));
|
||||||
|
*low =
|
||||||
|
*((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void restore_NMI_vector(unsigned short *high, unsigned short *low)
|
static inline void restore_NMI_vector(unsigned short *high, unsigned short *low)
|
||||||
{
|
{
|
||||||
printk("Restoring NMI vector\n");
|
printk("Restoring NMI vector\n");
|
||||||
*((volatile unsigned short *) TRAMPOLINE_HIGH) = *high;
|
*((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_HIGH)) =
|
||||||
*((volatile unsigned short *) TRAMPOLINE_LOW) = *low;
|
*high;
|
||||||
|
*((volatile unsigned short *)phys_to_virt(TRAMPOLINE_PHYS_LOW)) =
|
||||||
|
*low;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define inquire_remote_apic(apicid) {}
|
static inline void inquire_remote_apic(int apicid)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __ASM_NUMAQ_WAKECPU_H */
|
#endif /* __ASM_NUMAQ_WAKECPU_H */
|
||||||
|
@ -16,6 +16,8 @@ static inline void visws_early_detect(void) { }
|
|||||||
static inline int is_visws_box(void) { return 0; }
|
static inline int is_visws_box(void) { return 0; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern int wakeup_secondary_cpu_via_nmi(int apicid, unsigned long start_eip);
|
||||||
|
extern int wakeup_secondary_cpu_via_init(int apicid, unsigned long start_eip);
|
||||||
/*
|
/*
|
||||||
* Any setup quirks to be performed?
|
* Any setup quirks to be performed?
|
||||||
*/
|
*/
|
||||||
@ -39,6 +41,7 @@ struct x86_quirks {
|
|||||||
void (*smp_read_mpc_oem)(struct mp_config_oemtable *oemtable,
|
void (*smp_read_mpc_oem)(struct mp_config_oemtable *oemtable,
|
||||||
unsigned short oemsize);
|
unsigned short oemsize);
|
||||||
int (*setup_ioapic_ids)(void);
|
int (*setup_ioapic_ids)(void);
|
||||||
|
int (*update_genapic)(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct x86_quirks *x86_quirks;
|
extern struct x86_quirks *x86_quirks;
|
||||||
|
@ -314,6 +314,8 @@ extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
|
|||||||
|
|
||||||
void default_idle(void);
|
void default_idle(void);
|
||||||
|
|
||||||
|
void stop_this_cpu(void *dummy);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force strict CPU ordering.
|
* Force strict CPU ordering.
|
||||||
* And yes, this is required on UP too when we're talking
|
* And yes, this is required on UP too when we're talking
|
||||||
|
@ -1360,6 +1360,17 @@ static void __init acpi_process_madt(void)
|
|||||||
disable_acpi();
|
disable_acpi();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ACPI supports both logical (e.g. Hyper-Threading) and physical
|
||||||
|
* processors, where MPS only supports physical.
|
||||||
|
*/
|
||||||
|
if (acpi_lapic && acpi_ioapic)
|
||||||
|
printk(KERN_INFO "Using ACPI (MADT) for SMP configuration "
|
||||||
|
"information\n");
|
||||||
|
else if (acpi_lapic)
|
||||||
|
printk(KERN_INFO "Using ACPI for processor (LAPIC) "
|
||||||
|
"configuration information\n");
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -391,11 +391,7 @@ static int power_off;
|
|||||||
#else
|
#else
|
||||||
static int power_off = 1;
|
static int power_off = 1;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_APM_REAL_MODE_POWER_OFF
|
|
||||||
static int realmode_power_off = 1;
|
|
||||||
#else
|
|
||||||
static int realmode_power_off;
|
static int realmode_power_off;
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_APM_ALLOW_INTS
|
#ifdef CONFIG_APM_ALLOW_INTS
|
||||||
static int allow_ints = 1;
|
static int allow_ints = 1;
|
||||||
#else
|
#else
|
||||||
|
@ -38,8 +38,11 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/nmi.h>
|
#include <asm/nmi.h>
|
||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
|
#include <asm/atomic.h>
|
||||||
#include <asm/apicdef.h>
|
#include <asm/apicdef.h>
|
||||||
#include <mach_mpparse.h>
|
#include <mach_mpparse.h>
|
||||||
|
#include <asm/genapic.h>
|
||||||
|
#include <asm/setup.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ES7000 chipsets
|
* ES7000 chipsets
|
||||||
@ -161,6 +164,43 @@ es7000_rename_gsi(int ioapic, int gsi)
|
|||||||
return gsi;
|
return gsi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
|
||||||
|
{
|
||||||
|
unsigned long vect = 0, psaival = 0;
|
||||||
|
|
||||||
|
if (psai == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
vect = ((unsigned long)__pa(eip)/0x1000) << 16;
|
||||||
|
psaival = (0x1000000 | vect | cpu);
|
||||||
|
|
||||||
|
while (*psai & 0x1000000)
|
||||||
|
;
|
||||||
|
|
||||||
|
*psai = psaival;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void noop_wait_for_deassert(atomic_t *deassert_not_used)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init es7000_update_genapic(void)
|
||||||
|
{
|
||||||
|
genapic->wakeup_cpu = wakeup_secondary_cpu_via_mip;
|
||||||
|
|
||||||
|
/* MPENTIUMIII */
|
||||||
|
if (boot_cpu_data.x86 == 6 &&
|
||||||
|
(boot_cpu_data.x86_model >= 7 || boot_cpu_data.x86_model <= 11)) {
|
||||||
|
es7000_update_genapic_to_cluster();
|
||||||
|
genapic->wait_for_init_deassert = noop_wait_for_deassert;
|
||||||
|
genapic->wakeup_cpu = wakeup_secondary_cpu_via_mip;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void __init
|
void __init
|
||||||
setup_unisys(void)
|
setup_unisys(void)
|
||||||
{
|
{
|
||||||
@ -176,6 +216,8 @@ setup_unisys(void)
|
|||||||
else
|
else
|
||||||
es7000_plat = ES7000_CLASSIC;
|
es7000_plat = ES7000_CLASSIC;
|
||||||
ioapic_renumber_irq = es7000_rename_gsi;
|
ioapic_renumber_irq = es7000_rename_gsi;
|
||||||
|
|
||||||
|
x86_quirks->update_genapic = es7000_update_genapic;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -317,26 +359,6 @@ es7000_mip_write(struct mip_reg *mip_reg)
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
es7000_start_cpu(int cpu, unsigned long eip)
|
|
||||||
{
|
|
||||||
unsigned long vect = 0, psaival = 0;
|
|
||||||
|
|
||||||
if (psai == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
vect = ((unsigned long)__pa(eip)/0x1000) << 16;
|
|
||||||
psaival = (0x1000000 | vect | cpu);
|
|
||||||
|
|
||||||
while (*psai & 0x1000000)
|
|
||||||
;
|
|
||||||
|
|
||||||
*psai = psaival;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void __init
|
void __init
|
||||||
es7000_sw_apic(void)
|
es7000_sw_apic(void)
|
||||||
{
|
{
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <asm/smp.h>
|
#include <asm/smp.h>
|
||||||
#include <asm/ipi.h>
|
#include <asm/ipi.h>
|
||||||
#include <asm/genapic.h>
|
#include <asm/genapic.h>
|
||||||
|
#include <asm/setup.h>
|
||||||
|
|
||||||
extern struct genapic apic_flat;
|
extern struct genapic apic_flat;
|
||||||
extern struct genapic apic_physflat;
|
extern struct genapic apic_physflat;
|
||||||
@ -53,6 +54,9 @@ void __init setup_apic_routing(void)
|
|||||||
genapic = &apic_physflat;
|
genapic = &apic_physflat;
|
||||||
printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
|
printk(KERN_INFO "Setting APIC routing to %s\n", genapic->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (x86_quirks->update_genapic)
|
||||||
|
x86_quirks->update_genapic();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Same for both flat and physical. */
|
/* Same for both flat and physical. */
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -118,6 +118,9 @@ int show_interrupts(struct seq_file *p, void *v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
desc = irq_to_desc(i);
|
desc = irq_to_desc(i);
|
||||||
|
if (!desc)
|
||||||
|
return 0;
|
||||||
|
|
||||||
spin_lock_irqsave(&desc->lock, flags);
|
spin_lock_irqsave(&desc->lock, flags);
|
||||||
#ifndef CONFIG_SMP
|
#ifndef CONFIG_SMP
|
||||||
any_count = kstat_irqs(i);
|
any_count = kstat_irqs(i);
|
||||||
|
@ -242,6 +242,8 @@ void fixup_irqs(cpumask_t map)
|
|||||||
for_each_irq_desc(irq, desc) {
|
for_each_irq_desc(irq, desc) {
|
||||||
cpumask_t mask;
|
cpumask_t mask;
|
||||||
|
|
||||||
|
if (!desc)
|
||||||
|
continue;
|
||||||
if (irq == 2)
|
if (irq == 2)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -94,6 +94,8 @@ void fixup_irqs(cpumask_t map)
|
|||||||
int break_affinity = 0;
|
int break_affinity = 0;
|
||||||
int set_affinity = 1;
|
int set_affinity = 1;
|
||||||
|
|
||||||
|
if (!desc)
|
||||||
|
continue;
|
||||||
if (irq == 2)
|
if (irq == 2)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -68,8 +68,7 @@ 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 < NR_IRQS_LEGACY; i++) {
|
||||||
/* first time call this irq_desc */
|
|
||||||
struct irq_desc *desc = irq_to_desc(i);
|
struct irq_desc *desc = irq_to_desc(i);
|
||||||
|
|
||||||
desc->status = IRQ_DISABLED;
|
desc->status = IRQ_DISABLED;
|
||||||
|
@ -142,8 +142,7 @@ void __init init_ISA_irqs(void)
|
|||||||
init_bsp_APIC();
|
init_bsp_APIC();
|
||||||
init_8259A(0);
|
init_8259A(0);
|
||||||
|
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < NR_IRQS_LEGACY; i++) {
|
||||||
/* first time call this irq_desc */
|
|
||||||
struct irq_desc *desc = irq_to_desc(i);
|
struct irq_desc *desc = irq_to_desc(i);
|
||||||
|
|
||||||
desc->status = IRQ_DISABLED;
|
desc->status = IRQ_DISABLED;
|
||||||
|
@ -586,26 +586,23 @@ static void __init __get_smp_config(unsigned int early)
|
|||||||
{
|
{
|
||||||
struct intel_mp_floating *mpf = mpf_found;
|
struct intel_mp_floating *mpf = mpf_found;
|
||||||
|
|
||||||
|
if (!mpf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (acpi_lapic && early)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MPS doesn't support hyperthreading, aka only have
|
||||||
|
* thread 0 apic id in MPS table
|
||||||
|
*/
|
||||||
|
if (acpi_lapic && acpi_ioapic)
|
||||||
|
return;
|
||||||
|
|
||||||
if (x86_quirks->mach_get_smp_config) {
|
if (x86_quirks->mach_get_smp_config) {
|
||||||
if (x86_quirks->mach_get_smp_config(early))
|
if (x86_quirks->mach_get_smp_config(early))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (acpi_lapic && early)
|
|
||||||
return;
|
|
||||||
/*
|
|
||||||
* ACPI supports both logical (e.g. Hyper-Threading) and physical
|
|
||||||
* processors, where MPS only supports physical.
|
|
||||||
*/
|
|
||||||
if (acpi_lapic && acpi_ioapic) {
|
|
||||||
printk(KERN_INFO "Using ACPI (MADT) for SMP configuration "
|
|
||||||
"information\n");
|
|
||||||
return;
|
|
||||||
} else if (acpi_lapic)
|
|
||||||
printk(KERN_INFO "Using ACPI for processor (LAPIC) "
|
|
||||||
"configuration information\n");
|
|
||||||
|
|
||||||
if (!mpf)
|
|
||||||
return;
|
|
||||||
|
|
||||||
printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
|
printk(KERN_INFO "Intel MultiProcessor Specification v1.%d\n",
|
||||||
mpf->mpf_specification);
|
mpf->mpf_specification);
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
#include <asm/numaq.h>
|
#include <asm/numaq.h>
|
||||||
#include <asm/topology.h>
|
#include <asm/topology.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/mpspec.h>
|
#include <asm/genapic.h>
|
||||||
#include <asm/e820.h>
|
#include <asm/e820.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
|
|
||||||
@ -235,6 +235,13 @@ static int __init numaq_setup_ioapic_ids(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __init numaq_update_genapic(void)
|
||||||
|
{
|
||||||
|
genapic->wakeup_cpu = wakeup_secondary_cpu_via_nmi;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct x86_quirks numaq_x86_quirks __initdata = {
|
static struct x86_quirks numaq_x86_quirks __initdata = {
|
||||||
.arch_pre_time_init = numaq_pre_time_init,
|
.arch_pre_time_init = numaq_pre_time_init,
|
||||||
.arch_time_init = NULL,
|
.arch_time_init = NULL,
|
||||||
@ -250,6 +257,7 @@ static struct x86_quirks numaq_x86_quirks __initdata = {
|
|||||||
.mpc_oem_pci_bus = mpc_oem_pci_bus,
|
.mpc_oem_pci_bus = mpc_oem_pci_bus,
|
||||||
.smp_read_mpc_oem = smp_read_mpc_oem,
|
.smp_read_mpc_oem = smp_read_mpc_oem,
|
||||||
.setup_ioapic_ids = numaq_setup_ioapic_ids,
|
.setup_ioapic_ids = numaq_setup_ioapic_ids,
|
||||||
|
.update_genapic = numaq_update_genapic,
|
||||||
};
|
};
|
||||||
|
|
||||||
void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
|
void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <linux/clockchips.h>
|
#include <linux/clockchips.h>
|
||||||
#include <linux/ftrace.h>
|
#include <linux/ftrace.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
#include <asm/apic.h>
|
||||||
|
|
||||||
unsigned long idle_halt;
|
unsigned long idle_halt;
|
||||||
EXPORT_SYMBOL(idle_halt);
|
EXPORT_SYMBOL(idle_halt);
|
||||||
@ -127,6 +128,21 @@ void default_idle(void)
|
|||||||
EXPORT_SYMBOL(default_idle);
|
EXPORT_SYMBOL(default_idle);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void stop_this_cpu(void *dummy)
|
||||||
|
{
|
||||||
|
local_irq_disable();
|
||||||
|
/*
|
||||||
|
* Remove this CPU:
|
||||||
|
*/
|
||||||
|
cpu_clear(smp_processor_id(), cpu_online_map);
|
||||||
|
disable_local_APIC();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (hlt_works(smp_processor_id()))
|
||||||
|
halt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void do_nothing(void *unused)
|
static void do_nothing(void *unused)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,10 @@ int reboot_force;
|
|||||||
static int reboot_cpu = -1;
|
static int reboot_cpu = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old]
|
/* This is set by the PCI code if either type 1 or type 2 PCI is detected */
|
||||||
|
bool port_cf9_safe = false;
|
||||||
|
|
||||||
|
/* reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci]
|
||||||
warm Don't set the cold reboot flag
|
warm Don't set the cold reboot flag
|
||||||
cold Set the cold reboot flag
|
cold Set the cold reboot flag
|
||||||
bios Reboot by jumping through the BIOS (only for X86_32)
|
bios Reboot by jumping through the BIOS (only for X86_32)
|
||||||
@ -45,6 +48,7 @@ static int reboot_cpu = -1;
|
|||||||
kbd Use the keyboard controller. cold reset (default)
|
kbd Use the keyboard controller. cold reset (default)
|
||||||
acpi Use the RESET_REG in the FADT
|
acpi Use the RESET_REG in the FADT
|
||||||
efi Use efi reset_system runtime service
|
efi Use efi reset_system runtime service
|
||||||
|
pci Use the so-called "PCI reset register", CF9
|
||||||
force Avoid anything that could hang.
|
force Avoid anything that could hang.
|
||||||
*/
|
*/
|
||||||
static int __init reboot_setup(char *str)
|
static int __init reboot_setup(char *str)
|
||||||
@ -79,6 +83,7 @@ static int __init reboot_setup(char *str)
|
|||||||
case 'k':
|
case 'k':
|
||||||
case 't':
|
case 't':
|
||||||
case 'e':
|
case 'e':
|
||||||
|
case 'p':
|
||||||
reboot_type = *str;
|
reboot_type = *str;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -404,12 +409,27 @@ static void native_machine_emergency_restart(void)
|
|||||||
reboot_type = BOOT_KBD;
|
reboot_type = BOOT_KBD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case BOOT_EFI:
|
case BOOT_EFI:
|
||||||
if (efi_enabled)
|
if (efi_enabled)
|
||||||
efi.reset_system(reboot_mode ? EFI_RESET_WARM : EFI_RESET_COLD,
|
efi.reset_system(reboot_mode ?
|
||||||
|
EFI_RESET_WARM :
|
||||||
|
EFI_RESET_COLD,
|
||||||
EFI_SUCCESS, 0, NULL);
|
EFI_SUCCESS, 0, NULL);
|
||||||
|
reboot_type = BOOT_KBD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BOOT_CF9:
|
||||||
|
port_cf9_safe = true;
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case BOOT_CF9_COND:
|
||||||
|
if (port_cf9_safe) {
|
||||||
|
u8 cf9 = inb(0xcf9) & ~6;
|
||||||
|
outb(cf9|2, 0xcf9); /* Request hard reset */
|
||||||
|
udelay(50);
|
||||||
|
outb(cf9|6, 0xcf9); /* Actually do the reset */
|
||||||
|
udelay(50);
|
||||||
|
}
|
||||||
reboot_type = BOOT_KBD;
|
reboot_type = BOOT_KBD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -470,6 +490,11 @@ static void native_machine_restart(char *__unused)
|
|||||||
|
|
||||||
static void native_machine_halt(void)
|
static void native_machine_halt(void)
|
||||||
{
|
{
|
||||||
|
/* stop other cpus and apics */
|
||||||
|
machine_shutdown();
|
||||||
|
|
||||||
|
/* stop this cpu */
|
||||||
|
stop_this_cpu(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void native_machine_power_off(void)
|
static void native_machine_power_off(void)
|
||||||
|
@ -583,7 +583,20 @@ static int __init setup_elfcorehdr(char *arg)
|
|||||||
early_param("elfcorehdr", setup_elfcorehdr);
|
early_param("elfcorehdr", setup_elfcorehdr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct x86_quirks default_x86_quirks __initdata;
|
static int __init default_update_genapic(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_X86_SMP
|
||||||
|
# if defined(CONFIG_X86_GENERICARCH) || defined(CONFIG_X86_64)
|
||||||
|
genapic->wakeup_cpu = wakeup_secondary_cpu_via_init;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct x86_quirks default_x86_quirks __initdata = {
|
||||||
|
.update_genapic = default_update_genapic,
|
||||||
|
};
|
||||||
|
|
||||||
struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;
|
struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;
|
||||||
|
|
||||||
@ -1082,7 +1095,7 @@ void __init setup_arch(char **cmdline_p)
|
|||||||
ioapic_init_mappings();
|
ioapic_init_mappings();
|
||||||
|
|
||||||
/* need to wait for io_apic is mapped */
|
/* need to wait for io_apic is mapped */
|
||||||
nr_irqs = probe_nr_irqs();
|
probe_nr_irqs_gsi();
|
||||||
|
|
||||||
kvm_guest_init();
|
kvm_guest_init();
|
||||||
|
|
||||||
|
@ -140,19 +140,6 @@ void native_send_call_func_ipi(cpumask_t mask)
|
|||||||
send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
|
send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stop_this_cpu(void *dummy)
|
|
||||||
{
|
|
||||||
local_irq_disable();
|
|
||||||
/*
|
|
||||||
* Remove this CPU:
|
|
||||||
*/
|
|
||||||
cpu_clear(smp_processor_id(), cpu_online_map);
|
|
||||||
disable_local_APIC();
|
|
||||||
if (hlt_works(smp_processor_id()))
|
|
||||||
for (;;) halt();
|
|
||||||
for (;;);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* this function calls the 'stop' function on all other CPUs in the system.
|
* this function calls the 'stop' function on all other CPUs in the system.
|
||||||
*/
|
*/
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
#include <asm/mtrr.h>
|
#include <asm/mtrr.h>
|
||||||
#include <asm/vmi.h>
|
#include <asm/vmi.h>
|
||||||
#include <asm/genapic.h>
|
#include <asm/genapic.h>
|
||||||
|
#include <asm/setup.h>
|
||||||
#include <linux/mc146818rtc.h>
|
#include <linux/mc146818rtc.h>
|
||||||
|
|
||||||
#include <mach_apic.h>
|
#include <mach_apic.h>
|
||||||
@ -536,7 +537,7 @@ static void impress_friends(void)
|
|||||||
pr_debug("Before bogocount - setting activated=1.\n");
|
pr_debug("Before bogocount - setting activated=1.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void __inquire_remote_apic(int apicid)
|
void __inquire_remote_apic(int apicid)
|
||||||
{
|
{
|
||||||
unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
|
unsigned i, regs[] = { APIC_ID >> 4, APIC_LVR >> 4, APIC_SPIV >> 4 };
|
||||||
char *names[] = { "ID", "VERSION", "SPIV" };
|
char *names[] = { "ID", "VERSION", "SPIV" };
|
||||||
@ -575,14 +576,13 @@ static inline void __inquire_remote_apic(int apicid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WAKE_SECONDARY_VIA_NMI
|
|
||||||
/*
|
/*
|
||||||
* Poke the other CPU in the eye via NMI to wake it up. Remember that the normal
|
* Poke the other CPU in the eye via NMI to wake it up. Remember that the normal
|
||||||
* INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
|
* INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
|
||||||
* won't ... remember to clear down the APIC, etc later.
|
* won't ... remember to clear down the APIC, etc later.
|
||||||
*/
|
*/
|
||||||
static int __devinit
|
int __devinit
|
||||||
wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
|
wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip)
|
||||||
{
|
{
|
||||||
unsigned long send_status, accept_status = 0;
|
unsigned long send_status, accept_status = 0;
|
||||||
int maxlvt;
|
int maxlvt;
|
||||||
@ -599,7 +599,7 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
|
|||||||
* Give the other CPU some time to accept the IPI.
|
* Give the other CPU some time to accept the IPI.
|
||||||
*/
|
*/
|
||||||
udelay(200);
|
udelay(200);
|
||||||
if (APIC_INTEGRATED(apic_version[phys_apicid])) {
|
if (APIC_INTEGRATED(apic_version[boot_cpu_physical_apicid])) {
|
||||||
maxlvt = lapic_get_maxlvt();
|
maxlvt = lapic_get_maxlvt();
|
||||||
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
|
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
|
||||||
apic_write(APIC_ESR, 0);
|
apic_write(APIC_ESR, 0);
|
||||||
@ -614,11 +614,9 @@ wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
|
|||||||
|
|
||||||
return (send_status | accept_status);
|
return (send_status | accept_status);
|
||||||
}
|
}
|
||||||
#endif /* WAKE_SECONDARY_VIA_NMI */
|
|
||||||
|
|
||||||
#ifdef WAKE_SECONDARY_VIA_INIT
|
int __devinit
|
||||||
static int __devinit
|
wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
|
||||||
wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
|
|
||||||
{
|
{
|
||||||
unsigned long send_status, accept_status = 0;
|
unsigned long send_status, accept_status = 0;
|
||||||
int maxlvt, num_starts, j;
|
int maxlvt, num_starts, j;
|
||||||
@ -737,7 +735,6 @@ wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
|
|||||||
|
|
||||||
return (send_status | accept_status);
|
return (send_status | accept_status);
|
||||||
}
|
}
|
||||||
#endif /* WAKE_SECONDARY_VIA_INIT */
|
|
||||||
|
|
||||||
struct create_idle {
|
struct create_idle {
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <asm/bigsmp/apic.h>
|
#include <asm/bigsmp/apic.h>
|
||||||
#include <asm/bigsmp/ipi.h>
|
#include <asm/bigsmp/ipi.h>
|
||||||
#include <asm/mach-default/mach_mpparse.h>
|
#include <asm/mach-default/mach_mpparse.h>
|
||||||
|
#include <asm/mach-default/mach_wakecpu.h>
|
||||||
|
|
||||||
static int dmi_bigsmp; /* can be set by dmi scanners */
|
static int dmi_bigsmp; /* can be set by dmi scanners */
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <asm/mach-default/mach_apic.h>
|
#include <asm/mach-default/mach_apic.h>
|
||||||
#include <asm/mach-default/mach_ipi.h>
|
#include <asm/mach-default/mach_ipi.h>
|
||||||
#include <asm/mach-default/mach_mpparse.h>
|
#include <asm/mach-default/mach_mpparse.h>
|
||||||
|
#include <asm/mach-default/mach_wakecpu.h>
|
||||||
|
|
||||||
/* should be called last. */
|
/* should be called last. */
|
||||||
static int probe_default(void)
|
static int probe_default(void)
|
||||||
|
@ -16,7 +16,19 @@
|
|||||||
#include <asm/es7000/apic.h>
|
#include <asm/es7000/apic.h>
|
||||||
#include <asm/es7000/ipi.h>
|
#include <asm/es7000/ipi.h>
|
||||||
#include <asm/es7000/mpparse.h>
|
#include <asm/es7000/mpparse.h>
|
||||||
#include <asm/es7000/wakecpu.h>
|
#include <asm/mach-default/mach_wakecpu.h>
|
||||||
|
|
||||||
|
void __init es7000_update_genapic_to_cluster(void)
|
||||||
|
{
|
||||||
|
genapic->target_cpus = target_cpus_cluster;
|
||||||
|
genapic->int_delivery_mode = INT_DELIVERY_MODE_CLUSTER;
|
||||||
|
genapic->int_dest_mode = INT_DEST_MODE_CLUSTER;
|
||||||
|
genapic->no_balance_irq = NO_BALANCE_IRQ_CLUSTER;
|
||||||
|
|
||||||
|
genapic->init_apic_ldr = init_apic_ldr_cluster;
|
||||||
|
|
||||||
|
genapic->cpu_mask_to_apicid = cpu_mask_to_apicid_cluster;
|
||||||
|
}
|
||||||
|
|
||||||
static int probe_es7000(void)
|
static int probe_es7000(void)
|
||||||
{
|
{
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <asm/mpspec.h>
|
#include <asm/mpspec.h>
|
||||||
#include <asm/apicdef.h>
|
#include <asm/apicdef.h>
|
||||||
#include <asm/genapic.h>
|
#include <asm/genapic.h>
|
||||||
|
#include <asm/setup.h>
|
||||||
|
|
||||||
extern struct genapic apic_numaq;
|
extern struct genapic apic_numaq;
|
||||||
extern struct genapic apic_summit;
|
extern struct genapic apic_summit;
|
||||||
@ -57,6 +58,9 @@ static int __init parse_apic(char *arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (x86_quirks->update_genapic)
|
||||||
|
x86_quirks->update_genapic();
|
||||||
|
|
||||||
/* Parsed again by __setup for debug/verbose */
|
/* Parsed again by __setup for debug/verbose */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -72,12 +76,15 @@ void __init generic_bigsmp_probe(void)
|
|||||||
* - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
|
* - we find more than 8 CPUs in acpi LAPIC listing with xAPIC support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!cmdline_apic && genapic == &apic_default)
|
if (!cmdline_apic && genapic == &apic_default) {
|
||||||
if (apic_bigsmp.probe()) {
|
if (apic_bigsmp.probe()) {
|
||||||
genapic = &apic_bigsmp;
|
genapic = &apic_bigsmp;
|
||||||
|
if (x86_quirks->update_genapic)
|
||||||
|
x86_quirks->update_genapic();
|
||||||
printk(KERN_INFO "Overriding APIC driver with %s\n",
|
printk(KERN_INFO "Overriding APIC driver with %s\n",
|
||||||
genapic->name);
|
genapic->name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +101,9 @@ void __init generic_apic_probe(void)
|
|||||||
/* Not visible without early console */
|
/* Not visible without early console */
|
||||||
if (!apic_probe[i])
|
if (!apic_probe[i])
|
||||||
panic("Didn't find an APIC driver");
|
panic("Didn't find an APIC driver");
|
||||||
|
|
||||||
|
if (x86_quirks->update_genapic)
|
||||||
|
x86_quirks->update_genapic();
|
||||||
}
|
}
|
||||||
printk(KERN_INFO "Using APIC driver %s\n", genapic->name);
|
printk(KERN_INFO "Using APIC driver %s\n", genapic->name);
|
||||||
}
|
}
|
||||||
@ -108,6 +118,8 @@ int __init mps_oem_check(struct mp_config_table *mpc, char *oem,
|
|||||||
if (apic_probe[i]->mps_oem_check(mpc, oem, productid)) {
|
if (apic_probe[i]->mps_oem_check(mpc, oem, productid)) {
|
||||||
if (!cmdline_apic) {
|
if (!cmdline_apic) {
|
||||||
genapic = apic_probe[i];
|
genapic = apic_probe[i];
|
||||||
|
if (x86_quirks->update_genapic)
|
||||||
|
x86_quirks->update_genapic();
|
||||||
printk(KERN_INFO "Switched to APIC driver `%s'.\n",
|
printk(KERN_INFO "Switched to APIC driver `%s'.\n",
|
||||||
genapic->name);
|
genapic->name);
|
||||||
}
|
}
|
||||||
@ -124,6 +136,8 @@ int __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
|||||||
if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
|
if (apic_probe[i]->acpi_madt_oem_check(oem_id, oem_table_id)) {
|
||||||
if (!cmdline_apic) {
|
if (!cmdline_apic) {
|
||||||
genapic = apic_probe[i];
|
genapic = apic_probe[i];
|
||||||
|
if (x86_quirks->update_genapic)
|
||||||
|
x86_quirks->update_genapic();
|
||||||
printk(KERN_INFO "Switched to APIC driver `%s'.\n",
|
printk(KERN_INFO "Switched to APIC driver `%s'.\n",
|
||||||
genapic->name);
|
genapic->name);
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <asm/summit/apic.h>
|
#include <asm/summit/apic.h>
|
||||||
#include <asm/summit/ipi.h>
|
#include <asm/summit/ipi.h>
|
||||||
#include <asm/summit/mpparse.h>
|
#include <asm/summit/mpparse.h>
|
||||||
|
#include <asm/mach-default/mach_wakecpu.h>
|
||||||
|
|
||||||
static int probe_summit(void)
|
static int probe_summit(void)
|
||||||
{
|
{
|
||||||
|
@ -173,7 +173,7 @@ static int pci_conf2_write(unsigned int seg, unsigned int bus,
|
|||||||
|
|
||||||
#undef PCI_CONF2_ADDRESS
|
#undef PCI_CONF2_ADDRESS
|
||||||
|
|
||||||
static struct pci_raw_ops pci_direct_conf2 = {
|
struct pci_raw_ops pci_direct_conf2 = {
|
||||||
.read = pci_conf2_read,
|
.read = pci_conf2_read,
|
||||||
.write = pci_conf2_write,
|
.write = pci_conf2_write,
|
||||||
};
|
};
|
||||||
@ -289,6 +289,7 @@ int __init pci_direct_probe(void)
|
|||||||
|
|
||||||
if (pci_check_type1()) {
|
if (pci_check_type1()) {
|
||||||
raw_pci_ops = &pci_direct_conf1;
|
raw_pci_ops = &pci_direct_conf1;
|
||||||
|
port_cf9_safe = true;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
release_resource(region);
|
release_resource(region);
|
||||||
@ -305,6 +306,7 @@ int __init pci_direct_probe(void)
|
|||||||
|
|
||||||
if (pci_check_type2()) {
|
if (pci_check_type2()) {
|
||||||
raw_pci_ops = &pci_direct_conf2;
|
raw_pci_ops = &pci_direct_conf2;
|
||||||
|
port_cf9_safe = true;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,6 +96,7 @@ extern struct pci_raw_ops *raw_pci_ops;
|
|||||||
extern struct pci_raw_ops *raw_pci_ext_ops;
|
extern struct pci_raw_ops *raw_pci_ext_ops;
|
||||||
|
|
||||||
extern struct pci_raw_ops pci_direct_conf1;
|
extern struct pci_raw_ops pci_direct_conf1;
|
||||||
|
extern bool port_cf9_safe;
|
||||||
|
|
||||||
/* arch_initcall level */
|
/* arch_initcall level */
|
||||||
extern int pci_direct_probe(void);
|
extern int pci_direct_probe(void);
|
||||||
|
@ -558,23 +558,9 @@ struct timer_rand_state {
|
|||||||
unsigned dont_count_entropy:1;
|
unsigned dont_count_entropy:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct timer_rand_state *irq_timer_state[NR_IRQS];
|
#ifndef CONFIG_SPARSE_IRQ
|
||||||
|
struct timer_rand_state *irq_timer_state[NR_IRQS];
|
||||||
static struct timer_rand_state *get_timer_rand_state(unsigned int irq)
|
#endif
|
||||||
{
|
|
||||||
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;
|
static struct timer_rand_state input_timer_state;
|
||||||
|
|
||||||
@ -933,8 +919,10 @@ void rand_initialize_irq(int irq)
|
|||||||
{
|
{
|
||||||
struct timer_rand_state *state;
|
struct timer_rand_state *state;
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPARSE_IRQ
|
||||||
if (irq >= nr_irqs)
|
if (irq >= nr_irqs)
|
||||||
return;
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
state = get_timer_rand_state(irq);
|
state = get_timer_rand_state(irq);
|
||||||
|
|
||||||
|
@ -19,17 +19,75 @@ struct irq_2_iommu {
|
|||||||
u8 irte_mask;
|
u8 irte_mask;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct irq_2_iommu irq_2_iommuX[NR_IRQS];
|
#ifdef CONFIG_SPARSE_IRQ
|
||||||
|
static struct irq_2_iommu *get_one_free_irq_2_iommu(int cpu)
|
||||||
|
{
|
||||||
|
struct irq_2_iommu *iommu;
|
||||||
|
int node;
|
||||||
|
|
||||||
|
node = cpu_to_node(cpu);
|
||||||
|
|
||||||
|
iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node);
|
||||||
|
printk(KERN_DEBUG "alloc irq_2_iommu on cpu %d node %d\n", cpu, node);
|
||||||
|
|
||||||
|
return iommu;
|
||||||
|
}
|
||||||
|
|
||||||
static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
|
static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
|
||||||
{
|
{
|
||||||
return (irq < nr_irqs) ? irq_2_iommuX + irq : NULL;
|
struct irq_desc *desc;
|
||||||
|
|
||||||
|
desc = irq_to_desc(irq);
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(!desc))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return desc->irq_2_iommu;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu)
|
||||||
|
{
|
||||||
|
struct irq_desc *desc;
|
||||||
|
struct irq_2_iommu *irq_iommu;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* alloc irq desc if not allocated already.
|
||||||
|
*/
|
||||||
|
desc = irq_to_desc_alloc_cpu(irq, cpu);
|
||||||
|
if (!desc) {
|
||||||
|
printk(KERN_INFO "can not get irq_desc for %d\n", irq);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
irq_iommu = desc->irq_2_iommu;
|
||||||
|
|
||||||
|
if (!irq_iommu)
|
||||||
|
desc->irq_2_iommu = get_one_free_irq_2_iommu(cpu);
|
||||||
|
|
||||||
|
return desc->irq_2_iommu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
|
||||||
|
{
|
||||||
|
return irq_2_iommu_alloc_cpu(irq, boot_cpu_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* !CONFIG_SPARSE_IRQ */
|
||||||
|
|
||||||
|
static struct irq_2_iommu irq_2_iommuX[NR_IRQS];
|
||||||
|
|
||||||
|
static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
|
||||||
|
{
|
||||||
|
if (irq < nr_irqs)
|
||||||
|
return &irq_2_iommuX[irq];
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
|
static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq)
|
||||||
{
|
{
|
||||||
return irq_2_iommu(irq);
|
return irq_2_iommu(irq);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(irq_2_ir_lock);
|
static DEFINE_SPINLOCK(irq_2_ir_lock);
|
||||||
|
|
||||||
@ -86,9 +144,11 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
|
|||||||
if (!count)
|
if (!count)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPARSE_IRQ
|
||||||
/* protect irq_2_iommu_alloc later */
|
/* protect irq_2_iommu_alloc later */
|
||||||
if (irq >= nr_irqs)
|
if (irq >= nr_irqs)
|
||||||
return -1;
|
return -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* start the IRTE search from index 0.
|
* start the IRTE search from index 0.
|
||||||
@ -130,6 +190,12 @@ int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
|
|||||||
table->base[i].present = 1;
|
table->base[i].present = 1;
|
||||||
|
|
||||||
irq_iommu = irq_2_iommu_alloc(irq);
|
irq_iommu = irq_2_iommu_alloc(irq);
|
||||||
|
if (!irq_iommu) {
|
||||||
|
spin_unlock(&irq_2_ir_lock);
|
||||||
|
printk(KERN_ERR "can't allocate irq_2_iommu\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
irq_iommu->iommu = iommu;
|
irq_iommu->iommu = iommu;
|
||||||
irq_iommu->irte_index = index;
|
irq_iommu->irte_index = index;
|
||||||
irq_iommu->sub_handle = 0;
|
irq_iommu->sub_handle = 0;
|
||||||
@ -177,6 +243,12 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
|
|||||||
|
|
||||||
irq_iommu = irq_2_iommu_alloc(irq);
|
irq_iommu = irq_2_iommu_alloc(irq);
|
||||||
|
|
||||||
|
if (!irq_iommu) {
|
||||||
|
spin_unlock(&irq_2_ir_lock);
|
||||||
|
printk(KERN_ERR "can't allocate irq_2_iommu\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
irq_iommu->iommu = iommu;
|
irq_iommu->iommu = iommu;
|
||||||
irq_iommu->irte_index = index;
|
irq_iommu->irte_index = index;
|
||||||
irq_iommu->sub_handle = subhandle;
|
irq_iommu->sub_handle = subhandle;
|
||||||
|
@ -103,11 +103,11 @@ static void msix_set_enable(struct pci_dev *dev, int enable)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void msix_flush_writes(unsigned int irq)
|
static void msix_flush_writes(struct irq_desc *desc)
|
||||||
{
|
{
|
||||||
struct msi_desc *entry;
|
struct msi_desc *entry;
|
||||||
|
|
||||||
entry = get_irq_msi(irq);
|
entry = get_irq_desc_msi(desc);
|
||||||
BUG_ON(!entry || !entry->dev);
|
BUG_ON(!entry || !entry->dev);
|
||||||
switch (entry->msi_attrib.type) {
|
switch (entry->msi_attrib.type) {
|
||||||
case PCI_CAP_ID_MSI:
|
case PCI_CAP_ID_MSI:
|
||||||
@ -135,11 +135,11 @@ static void msix_flush_writes(unsigned int irq)
|
|||||||
* Returns 1 if it succeeded in masking the interrupt and 0 if the device
|
* Returns 1 if it succeeded in masking the interrupt and 0 if the device
|
||||||
* doesn't support MSI masking.
|
* doesn't support MSI masking.
|
||||||
*/
|
*/
|
||||||
static int msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag)
|
static int msi_set_mask_bits(struct irq_desc *desc, u32 mask, u32 flag)
|
||||||
{
|
{
|
||||||
struct msi_desc *entry;
|
struct msi_desc *entry;
|
||||||
|
|
||||||
entry = get_irq_msi(irq);
|
entry = get_irq_desc_msi(desc);
|
||||||
BUG_ON(!entry || !entry->dev);
|
BUG_ON(!entry || !entry->dev);
|
||||||
switch (entry->msi_attrib.type) {
|
switch (entry->msi_attrib.type) {
|
||||||
case PCI_CAP_ID_MSI:
|
case PCI_CAP_ID_MSI:
|
||||||
@ -172,9 +172,9 @@ static int msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_msi_msg(unsigned int irq, struct msi_msg *msg)
|
void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
|
||||||
{
|
{
|
||||||
struct msi_desc *entry = get_irq_msi(irq);
|
struct msi_desc *entry = get_irq_desc_msi(desc);
|
||||||
switch(entry->msi_attrib.type) {
|
switch(entry->msi_attrib.type) {
|
||||||
case PCI_CAP_ID_MSI:
|
case PCI_CAP_ID_MSI:
|
||||||
{
|
{
|
||||||
@ -211,9 +211,16 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_msi_msg(unsigned int irq, struct msi_msg *msg)
|
void read_msi_msg(unsigned int irq, struct msi_msg *msg)
|
||||||
{
|
{
|
||||||
struct msi_desc *entry = get_irq_msi(irq);
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
|
|
||||||
|
read_msi_msg_desc(desc, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
|
||||||
|
{
|
||||||
|
struct msi_desc *entry = get_irq_desc_msi(desc);
|
||||||
switch (entry->msi_attrib.type) {
|
switch (entry->msi_attrib.type) {
|
||||||
case PCI_CAP_ID_MSI:
|
case PCI_CAP_ID_MSI:
|
||||||
{
|
{
|
||||||
@ -252,21 +259,31 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg)
|
|||||||
entry->msg = *msg;
|
entry->msg = *msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_msi_msg(unsigned int irq, struct msi_msg *msg)
|
||||||
|
{
|
||||||
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
|
|
||||||
|
write_msi_msg_desc(desc, msg);
|
||||||
|
}
|
||||||
|
|
||||||
void mask_msi_irq(unsigned int irq)
|
void mask_msi_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
msi_set_mask_bits(irq, 1, 1);
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
msix_flush_writes(irq);
|
|
||||||
|
msi_set_mask_bits(desc, 1, 1);
|
||||||
|
msix_flush_writes(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unmask_msi_irq(unsigned int irq)
|
void unmask_msi_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
msi_set_mask_bits(irq, 1, 0);
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
msix_flush_writes(irq);
|
|
||||||
|
msi_set_mask_bits(desc, 1, 0);
|
||||||
|
msix_flush_writes(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int msi_free_irqs(struct pci_dev* dev);
|
static int msi_free_irqs(struct pci_dev* dev);
|
||||||
|
|
||||||
|
|
||||||
static struct msi_desc* alloc_msi_entry(void)
|
static struct msi_desc* alloc_msi_entry(void)
|
||||||
{
|
{
|
||||||
struct msi_desc *entry;
|
struct msi_desc *entry;
|
||||||
@ -303,9 +320,11 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
|
|||||||
pci_intx_for_msi(dev, 0);
|
pci_intx_for_msi(dev, 0);
|
||||||
msi_set_enable(dev, 0);
|
msi_set_enable(dev, 0);
|
||||||
write_msi_msg(dev->irq, &entry->msg);
|
write_msi_msg(dev->irq, &entry->msg);
|
||||||
if (entry->msi_attrib.maskbit)
|
if (entry->msi_attrib.maskbit) {
|
||||||
msi_set_mask_bits(dev->irq, entry->msi_attrib.maskbits_mask,
|
struct irq_desc *desc = irq_to_desc(dev->irq);
|
||||||
|
msi_set_mask_bits(desc, entry->msi_attrib.maskbits_mask,
|
||||||
entry->msi_attrib.masked);
|
entry->msi_attrib.masked);
|
||||||
|
}
|
||||||
|
|
||||||
pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
|
pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
|
||||||
control &= ~PCI_MSI_FLAGS_QSIZE;
|
control &= ~PCI_MSI_FLAGS_QSIZE;
|
||||||
@ -327,8 +346,9 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
|
|||||||
msix_set_enable(dev, 0);
|
msix_set_enable(dev, 0);
|
||||||
|
|
||||||
list_for_each_entry(entry, &dev->msi_list, list) {
|
list_for_each_entry(entry, &dev->msi_list, list) {
|
||||||
|
struct irq_desc *desc = irq_to_desc(entry->irq);
|
||||||
write_msi_msg(entry->irq, &entry->msg);
|
write_msi_msg(entry->irq, &entry->msg);
|
||||||
msi_set_mask_bits(entry->irq, 1, entry->msi_attrib.masked);
|
msi_set_mask_bits(desc, 1, entry->msi_attrib.masked);
|
||||||
}
|
}
|
||||||
|
|
||||||
BUG_ON(list_empty(&dev->msi_list));
|
BUG_ON(list_empty(&dev->msi_list));
|
||||||
@ -596,7 +616,8 @@ void pci_msi_shutdown(struct pci_dev* dev)
|
|||||||
/* Return the the pci reset with msi irqs unmasked */
|
/* Return the the pci reset with msi irqs unmasked */
|
||||||
if (entry->msi_attrib.maskbit) {
|
if (entry->msi_attrib.maskbit) {
|
||||||
u32 mask = entry->msi_attrib.maskbits_mask;
|
u32 mask = entry->msi_attrib.maskbits_mask;
|
||||||
msi_set_mask_bits(dev->irq, mask, ~mask);
|
struct irq_desc *desc = irq_to_desc(dev->irq);
|
||||||
|
msi_set_mask_bits(desc, mask, ~mask);
|
||||||
}
|
}
|
||||||
if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI)
|
if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI)
|
||||||
return;
|
return;
|
||||||
|
@ -141,8 +141,12 @@ static void init_evtchn_cpu_bindings(void)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* By default all event channels notify CPU#0. */
|
/* By default all event channels notify CPU#0. */
|
||||||
for_each_irq_desc(i, desc)
|
for_each_irq_desc(i, desc) {
|
||||||
|
if (!desc)
|
||||||
|
continue;
|
||||||
|
|
||||||
desc->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));
|
||||||
@ -231,7 +235,7 @@ static int find_unbound_irq(void)
|
|||||||
int irq;
|
int irq;
|
||||||
|
|
||||||
/* Only allocate from dynirq range */
|
/* Only allocate from dynirq range */
|
||||||
for_each_irq_nr(irq)
|
for (irq = 0; irq < nr_irqs; irq++)
|
||||||
if (irq_bindcount[irq] == 0)
|
if (irq_bindcount[irq] == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -792,7 +796,7 @@ void xen_irq_resume(void)
|
|||||||
mask_evtchn(evtchn);
|
mask_evtchn(evtchn);
|
||||||
|
|
||||||
/* No IRQ <-> event-channel mappings. */
|
/* No IRQ <-> event-channel mappings. */
|
||||||
for_each_irq_nr(irq)
|
for (irq = 0; irq < nr_irqs; 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++)
|
||||||
@ -824,7 +828,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_each_irq_nr(i)
|
for (i = 0; i < nr_irqs; i++)
|
||||||
irq_bindcount[i] = 0;
|
irq_bindcount[i] = 0;
|
||||||
|
|
||||||
irq_ctx_init(smp_processor_id());
|
irq_ctx_init(smp_processor_id());
|
||||||
|
@ -27,6 +27,7 @@ static int show_stat(struct seq_file *p, void *v)
|
|||||||
u64 sum = 0;
|
u64 sum = 0;
|
||||||
struct timespec boottime;
|
struct timespec boottime;
|
||||||
unsigned int per_irq_sum;
|
unsigned int per_irq_sum;
|
||||||
|
struct irq_desc *desc;
|
||||||
|
|
||||||
user = nice = system = idle = iowait =
|
user = nice = system = idle = iowait =
|
||||||
irq = softirq = steal = cputime64_zero;
|
irq = softirq = steal = cputime64_zero;
|
||||||
@ -44,10 +45,14 @@ 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_each_irq_nr(j) {
|
||||||
for_each_irq_nr(j)
|
#ifdef CONFIG_SPARSE_IRQ
|
||||||
|
desc = irq_to_desc(j);
|
||||||
|
if (!desc)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
sum += kstat_irqs_cpu(j, i);
|
sum += kstat_irqs_cpu(j, i);
|
||||||
|
}
|
||||||
sum += arch_irq_stat_cpu(i);
|
sum += arch_irq_stat_cpu(i);
|
||||||
}
|
}
|
||||||
sum += arch_irq_stat();
|
sum += arch_irq_stat();
|
||||||
@ -92,7 +97,13 @@ static int show_stat(struct seq_file *p, void *v)
|
|||||||
/* sum again ? it could be updated? */
|
/* sum again ? it could be updated? */
|
||||||
for_each_irq_nr(j) {
|
for_each_irq_nr(j) {
|
||||||
per_irq_sum = 0;
|
per_irq_sum = 0;
|
||||||
|
#ifdef CONFIG_SPARSE_IRQ
|
||||||
|
desc = irq_to_desc(j);
|
||||||
|
if (!desc) {
|
||||||
|
seq_printf(p, " %u", per_irq_sum);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
for_each_possible_cpu(i)
|
for_each_possible_cpu(i)
|
||||||
per_irq_sum += kstat_irqs_cpu(j, i);
|
per_irq_sum += kstat_irqs_cpu(j, i);
|
||||||
|
|
||||||
|
@ -313,6 +313,7 @@ unifdef-y += ptrace.h
|
|||||||
unifdef-y += qnx4_fs.h
|
unifdef-y += qnx4_fs.h
|
||||||
unifdef-y += quota.h
|
unifdef-y += quota.h
|
||||||
unifdef-y += random.h
|
unifdef-y += random.h
|
||||||
|
unifdef-y += irqnr.h
|
||||||
unifdef-y += reboot.h
|
unifdef-y += reboot.h
|
||||||
unifdef-y += reiserfs_fs.h
|
unifdef-y += reiserfs_fs.h
|
||||||
unifdef-y += reiserfs_xattr.h
|
unifdef-y += reiserfs_xattr.h
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#include <linux/irqflags.h>
|
#include <linux/irqflags.h>
|
||||||
#include <linux/smp.h>
|
#include <linux/smp.h>
|
||||||
#include <linux/percpu.h>
|
#include <linux/percpu.h>
|
||||||
|
#include <linux/irqnr.h>
|
||||||
|
|
||||||
#include <asm/atomic.h>
|
#include <asm/atomic.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
@ -129,6 +129,8 @@ struct irq_chip {
|
|||||||
const char *typename;
|
const char *typename;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct timer_rand_state;
|
||||||
|
struct irq_2_iommu;
|
||||||
/**
|
/**
|
||||||
* struct irq_desc - interrupt descriptor
|
* struct irq_desc - interrupt descriptor
|
||||||
* @irq: interrupt number for this descriptor
|
* @irq: interrupt number for this descriptor
|
||||||
@ -154,6 +156,13 @@ struct irq_chip {
|
|||||||
*/
|
*/
|
||||||
struct irq_desc {
|
struct irq_desc {
|
||||||
unsigned int irq;
|
unsigned int irq;
|
||||||
|
#ifdef CONFIG_SPARSE_IRQ
|
||||||
|
struct timer_rand_state *timer_rand_state;
|
||||||
|
unsigned int *kstat_irqs;
|
||||||
|
# ifdef CONFIG_INTR_REMAP
|
||||||
|
struct irq_2_iommu *irq_2_iommu;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
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;
|
||||||
@ -181,13 +190,42 @@ struct irq_desc {
|
|||||||
const char *name;
|
const char *name;
|
||||||
} ____cacheline_internodealigned_in_smp;
|
} ____cacheline_internodealigned_in_smp;
|
||||||
|
|
||||||
|
extern void early_irq_init(void);
|
||||||
|
extern void arch_early_irq_init(void);
|
||||||
|
extern void arch_init_chip_data(struct irq_desc *desc, int cpu);
|
||||||
|
extern void arch_init_copy_chip_data(struct irq_desc *old_desc,
|
||||||
|
struct irq_desc *desc, int cpu);
|
||||||
|
extern void arch_free_chip_data(struct irq_desc *old_desc, struct irq_desc *desc);
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPARSE_IRQ
|
||||||
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)
|
static inline struct irq_desc *irq_to_desc(unsigned int irq)
|
||||||
{
|
{
|
||||||
return (irq < nr_irqs) ? irq_desc + irq : NULL;
|
return (irq < NR_IRQS) ? irq_desc + irq : NULL;
|
||||||
}
|
}
|
||||||
|
static inline struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
|
||||||
|
{
|
||||||
|
return irq_to_desc(irq);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
extern struct irq_desc *irq_to_desc(unsigned int irq);
|
||||||
|
extern struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu);
|
||||||
|
extern struct irq_desc *move_irq_desc(struct irq_desc *old_desc, int cpu);
|
||||||
|
|
||||||
|
# define for_each_irq_desc(irq, desc) \
|
||||||
|
for (irq = 0, desc = irq_to_desc(irq); irq < nr_irqs; irq++, desc = irq_to_desc(irq))
|
||||||
|
# define for_each_irq_desc_reverse(irq, desc) \
|
||||||
|
for (irq = nr_irqs - 1, desc = irq_to_desc(irq); irq >= 0; irq--, desc = irq_to_desc(irq))
|
||||||
|
|
||||||
|
#define kstat_irqs_this_cpu(DESC) \
|
||||||
|
((DESC)->kstat_irqs[smp_processor_id()])
|
||||||
|
#define kstat_incr_irqs_this_cpu(irqno, DESC) \
|
||||||
|
((DESC)->kstat_irqs[smp_processor_id()]++)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Migration helpers for obsolete names, they will go away:
|
* Migration helpers for obsolete names, they will go away:
|
||||||
@ -380,6 +418,11 @@ extern int set_irq_msi(unsigned int irq, struct msi_desc *entry);
|
|||||||
#define get_irq_data(irq) (irq_to_desc(irq)->handler_data)
|
#define get_irq_data(irq) (irq_to_desc(irq)->handler_data)
|
||||||
#define get_irq_msi(irq) (irq_to_desc(irq)->msi_desc)
|
#define get_irq_msi(irq) (irq_to_desc(irq)->msi_desc)
|
||||||
|
|
||||||
|
#define get_irq_desc_chip(desc) ((desc)->chip)
|
||||||
|
#define get_irq_desc_chip_data(desc) ((desc)->chip_data)
|
||||||
|
#define get_irq_desc_data(desc) ((desc)->handler_data)
|
||||||
|
#define get_irq_desc_msi(desc) ((desc)->msi_desc)
|
||||||
|
|
||||||
#endif /* CONFIG_GENERIC_HARDIRQS */
|
#endif /* CONFIG_GENERIC_HARDIRQS */
|
||||||
|
|
||||||
#endif /* !CONFIG_S390 */
|
#endif /* !CONFIG_S390 */
|
||||||
|
@ -1,24 +1,38 @@
|
|||||||
#ifndef _LINUX_IRQNR_H
|
#ifndef _LINUX_IRQNR_H
|
||||||
#define _LINUX_IRQNR_H
|
#define _LINUX_IRQNR_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic irq_desc iterators:
|
||||||
|
*/
|
||||||
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
#ifndef CONFIG_GENERIC_HARDIRQS
|
#ifndef CONFIG_GENERIC_HARDIRQS
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
# define nr_irqs NR_IRQS
|
# define nr_irqs NR_IRQS
|
||||||
|
|
||||||
# define for_each_irq_desc(irq, desc) \
|
# define for_each_irq_desc(irq, desc) \
|
||||||
for (irq = 0; irq < nr_irqs; irq++)
|
for (irq = 0; irq < nr_irqs; irq++)
|
||||||
|
|
||||||
|
# define for_each_irq_desc_reverse(irq, desc) \
|
||||||
|
for (irq = nr_irqs - 1; irq >= 0; irq--)
|
||||||
#else
|
#else
|
||||||
|
|
||||||
extern int nr_irqs;
|
extern int nr_irqs;
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPARSE_IRQ
|
||||||
|
|
||||||
|
struct irq_desc;
|
||||||
# define for_each_irq_desc(irq, desc) \
|
# define for_each_irq_desc(irq, desc) \
|
||||||
for (irq = 0, desc = irq_desc; irq < nr_irqs; irq++, desc++)
|
for (irq = 0, desc = irq_desc; irq < nr_irqs; irq++, desc++)
|
||||||
|
|
||||||
# define for_each_irq_desc_reverse(irq, desc) \
|
# define for_each_irq_desc_reverse(irq, desc) \
|
||||||
for (irq = nr_irqs - 1, desc = irq_desc + (nr_irqs - 1); \
|
for (irq = nr_irqs - 1, desc = irq_desc + (nr_irqs - 1); \
|
||||||
irq >= 0; irq--, desc--)
|
irq >= 0; irq--, desc--)
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#define for_each_irq_nr(irq) \
|
#define for_each_irq_nr(irq) \
|
||||||
for (irq = 0; irq < nr_irqs; irq++)
|
for (irq = 0; irq < nr_irqs; irq++)
|
||||||
|
|
||||||
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,7 +28,9 @@ struct cpu_usage_stat {
|
|||||||
|
|
||||||
struct kernel_stat {
|
struct kernel_stat {
|
||||||
struct cpu_usage_stat cpustat;
|
struct cpu_usage_stat cpustat;
|
||||||
|
#ifndef CONFIG_SPARSE_IRQ
|
||||||
unsigned int irqs[NR_IRQS];
|
unsigned int irqs[NR_IRQS];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_PER_CPU(struct kernel_stat, kstat);
|
DECLARE_PER_CPU(struct kernel_stat, kstat);
|
||||||
@ -39,6 +41,10 @@ DECLARE_PER_CPU(struct kernel_stat, kstat);
|
|||||||
|
|
||||||
extern unsigned long long nr_context_switches(void);
|
extern unsigned long long nr_context_switches(void);
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPARSE_IRQ
|
||||||
|
#define kstat_irqs_this_cpu(irq) \
|
||||||
|
(kstat_this_cpu.irqs[irq])
|
||||||
|
|
||||||
struct irq_desc;
|
struct irq_desc;
|
||||||
|
|
||||||
static inline void kstat_incr_irqs_this_cpu(unsigned int irq,
|
static inline void kstat_incr_irqs_this_cpu(unsigned int irq,
|
||||||
@ -46,11 +52,17 @@ static inline void kstat_incr_irqs_this_cpu(unsigned int irq,
|
|||||||
{
|
{
|
||||||
kstat_this_cpu.irqs[irq]++;
|
kstat_this_cpu.irqs[irq]++;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPARSE_IRQ
|
||||||
static inline unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
|
static inline unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
|
||||||
{
|
{
|
||||||
return kstat_cpu(cpu).irqs[irq];
|
return kstat_cpu(cpu).irqs[irq];
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
extern unsigned int kstat_irqs_cpu(unsigned int irq, int cpu);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Number of interrupts per specific IRQ source, since bootup
|
* Number of interrupts per specific IRQ source, since bootup
|
||||||
|
@ -10,8 +10,11 @@ struct msi_msg {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Helper functions */
|
/* Helper functions */
|
||||||
|
struct irq_desc;
|
||||||
extern void mask_msi_irq(unsigned int irq);
|
extern void mask_msi_irq(unsigned int irq);
|
||||||
extern void unmask_msi_irq(unsigned int irq);
|
extern void unmask_msi_irq(unsigned int irq);
|
||||||
|
extern void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
|
||||||
|
extern void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
|
||||||
extern void read_msi_msg(unsigned int irq, struct msi_msg *msg);
|
extern void read_msi_msg(unsigned int irq, struct msi_msg *msg);
|
||||||
extern void write_msi_msg(unsigned int irq, struct msi_msg *msg);
|
extern void write_msi_msg(unsigned int irq, struct msi_msg *msg);
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#define _LINUX_RANDOM_H
|
#define _LINUX_RANDOM_H
|
||||||
|
|
||||||
#include <linux/ioctl.h>
|
#include <linux/ioctl.h>
|
||||||
|
#include <linux/irqnr.h>
|
||||||
|
|
||||||
/* ioctl()'s for the random number generator */
|
/* ioctl()'s for the random number generator */
|
||||||
|
|
||||||
@ -44,6 +45,56 @@ struct rand_pool_info {
|
|||||||
|
|
||||||
extern void rand_initialize_irq(int irq);
|
extern void rand_initialize_irq(int irq);
|
||||||
|
|
||||||
|
struct timer_rand_state;
|
||||||
|
#ifndef CONFIG_SPARSE_IRQ
|
||||||
|
|
||||||
|
extern struct timer_rand_state *irq_timer_state[];
|
||||||
|
|
||||||
|
static inline struct timer_rand_state *get_timer_rand_state(unsigned int irq)
|
||||||
|
{
|
||||||
|
if (irq >= nr_irqs)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return irq_timer_state[irq];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_timer_rand_state(unsigned int irq, struct timer_rand_state *state)
|
||||||
|
{
|
||||||
|
if (irq >= nr_irqs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
irq_timer_state[irq] = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <linux/irq.h>
|
||||||
|
static inline struct timer_rand_state *get_timer_rand_state(unsigned int irq)
|
||||||
|
{
|
||||||
|
struct irq_desc *desc;
|
||||||
|
|
||||||
|
desc = irq_to_desc(irq);
|
||||||
|
|
||||||
|
if (!desc)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return desc->timer_rand_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_timer_rand_state(unsigned int irq, struct timer_rand_state *state)
|
||||||
|
{
|
||||||
|
struct irq_desc *desc;
|
||||||
|
|
||||||
|
desc = irq_to_desc(irq);
|
||||||
|
|
||||||
|
if (!desc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
desc->timer_rand_state = state;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
extern void add_input_randomness(unsigned int type, unsigned int code,
|
extern void add_input_randomness(unsigned int type, unsigned int code,
|
||||||
unsigned int value);
|
unsigned int value);
|
||||||
extern void add_interrupt_randomness(int irq);
|
extern void add_interrupt_randomness(int irq);
|
||||||
|
11
init/main.c
11
init/main.c
@ -540,6 +540,15 @@ void __init __weak thread_info_cache_init(void)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __init __weak arch_early_irq_init(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init __weak early_irq_init(void)
|
||||||
|
{
|
||||||
|
arch_early_irq_init();
|
||||||
|
}
|
||||||
|
|
||||||
asmlinkage void __init start_kernel(void)
|
asmlinkage void __init start_kernel(void)
|
||||||
{
|
{
|
||||||
char * command_line;
|
char * command_line;
|
||||||
@ -604,6 +613,8 @@ asmlinkage void __init start_kernel(void)
|
|||||||
sort_main_extable();
|
sort_main_extable();
|
||||||
trap_init();
|
trap_init();
|
||||||
rcu_init();
|
rcu_init();
|
||||||
|
/* init some links before init_ISA_irqs() */
|
||||||
|
early_irq_init();
|
||||||
init_IRQ();
|
init_IRQ();
|
||||||
pidhash_init();
|
pidhash_init();
|
||||||
init_timers();
|
init_timers();
|
||||||
|
@ -40,6 +40,9 @@ unsigned long probe_irq_on(void)
|
|||||||
* flush such a longstanding irq before considering it as spurious.
|
* flush such a longstanding irq before considering it as spurious.
|
||||||
*/
|
*/
|
||||||
for_each_irq_desc_reverse(i, desc) {
|
for_each_irq_desc_reverse(i, desc) {
|
||||||
|
if (!desc)
|
||||||
|
continue;
|
||||||
|
|
||||||
spin_lock_irq(&desc->lock);
|
spin_lock_irq(&desc->lock);
|
||||||
if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
|
if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
|
||||||
/*
|
/*
|
||||||
@ -68,6 +71,9 @@ unsigned long probe_irq_on(void)
|
|||||||
* happened in the previous stage, it may have masked itself)
|
* happened in the previous stage, it may have masked itself)
|
||||||
*/
|
*/
|
||||||
for_each_irq_desc_reverse(i, desc) {
|
for_each_irq_desc_reverse(i, desc) {
|
||||||
|
if (!desc)
|
||||||
|
continue;
|
||||||
|
|
||||||
spin_lock_irq(&desc->lock);
|
spin_lock_irq(&desc->lock);
|
||||||
if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
|
if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
|
||||||
desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
|
desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
|
||||||
@ -86,6 +92,9 @@ unsigned long probe_irq_on(void)
|
|||||||
* Now filter out any obviously spurious interrupts
|
* Now filter out any obviously spurious interrupts
|
||||||
*/
|
*/
|
||||||
for_each_irq_desc(i, desc) {
|
for_each_irq_desc(i, desc) {
|
||||||
|
if (!desc)
|
||||||
|
continue;
|
||||||
|
|
||||||
spin_lock_irq(&desc->lock);
|
spin_lock_irq(&desc->lock);
|
||||||
status = desc->status;
|
status = desc->status;
|
||||||
|
|
||||||
@ -124,6 +133,9 @@ unsigned int probe_irq_mask(unsigned long val)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for_each_irq_desc(i, desc) {
|
for_each_irq_desc(i, desc) {
|
||||||
|
if (!desc)
|
||||||
|
continue;
|
||||||
|
|
||||||
spin_lock_irq(&desc->lock);
|
spin_lock_irq(&desc->lock);
|
||||||
status = desc->status;
|
status = desc->status;
|
||||||
|
|
||||||
@ -166,6 +178,9 @@ int probe_irq_off(unsigned long val)
|
|||||||
unsigned int status;
|
unsigned int status;
|
||||||
|
|
||||||
for_each_irq_desc(i, desc) {
|
for_each_irq_desc(i, desc) {
|
||||||
|
if (!desc)
|
||||||
|
continue;
|
||||||
|
|
||||||
spin_lock_irq(&desc->lock);
|
spin_lock_irq(&desc->lock);
|
||||||
status = desc->status;
|
status = desc->status;
|
||||||
|
|
||||||
|
@ -24,9 +24,10 @@
|
|||||||
*/
|
*/
|
||||||
void dynamic_irq_init(unsigned int irq)
|
void dynamic_irq_init(unsigned int irq)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc = irq_to_desc(irq);
|
struct irq_desc *desc;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
desc = irq_to_desc(irq);
|
||||||
if (!desc) {
|
if (!desc) {
|
||||||
WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
|
WARN(1, KERN_ERR "Trying to initialize invalid IRQ%d\n", irq);
|
||||||
return;
|
return;
|
||||||
|
@ -15,9 +15,16 @@
|
|||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/kernel_stat.h>
|
#include <linux/kernel_stat.h>
|
||||||
|
#include <linux/rculist.h>
|
||||||
|
#include <linux/hash.h>
|
||||||
|
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lockdep: we want to handle all irq_desc locks as a single lock-class:
|
||||||
|
*/
|
||||||
|
static struct lock_class_key irq_desc_lock_class;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* handle_bad_irq - handle spurious and unhandled irqs
|
* handle_bad_irq - handle spurious and unhandled irqs
|
||||||
* @irq: the interrupt number
|
* @irq: the interrupt number
|
||||||
@ -49,6 +56,155 @@ void handle_bad_irq(unsigned int irq, struct irq_desc *desc)
|
|||||||
int nr_irqs = NR_IRQS;
|
int nr_irqs = NR_IRQS;
|
||||||
EXPORT_SYMBOL_GPL(nr_irqs);
|
EXPORT_SYMBOL_GPL(nr_irqs);
|
||||||
|
|
||||||
|
void __init __attribute__((weak)) arch_early_irq_init(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SPARSE_IRQ
|
||||||
|
static struct irq_desc irq_desc_init = {
|
||||||
|
.irq = -1,
|
||||||
|
.status = IRQ_DISABLED,
|
||||||
|
.chip = &no_irq_chip,
|
||||||
|
.handle_irq = handle_bad_irq,
|
||||||
|
.depth = 1,
|
||||||
|
.lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
.affinity = CPU_MASK_ALL
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static void init_kstat_irqs(struct irq_desc *desc, int cpu, int nr)
|
||||||
|
{
|
||||||
|
unsigned long bytes;
|
||||||
|
char *ptr;
|
||||||
|
int node;
|
||||||
|
|
||||||
|
/* Compute how many bytes we need per irq and allocate them */
|
||||||
|
bytes = nr * sizeof(unsigned int);
|
||||||
|
|
||||||
|
node = cpu_to_node(cpu);
|
||||||
|
ptr = kzalloc_node(bytes, GFP_ATOMIC, node);
|
||||||
|
printk(KERN_DEBUG " alloc kstat_irqs on cpu %d node %d\n", cpu, node);
|
||||||
|
|
||||||
|
if (ptr)
|
||||||
|
desc->kstat_irqs = (unsigned int *)ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__((weak)) arch_init_chip_data(struct irq_desc *desc, int cpu)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_one_irq_desc(int irq, struct irq_desc *desc, int cpu)
|
||||||
|
{
|
||||||
|
memcpy(desc, &irq_desc_init, sizeof(struct irq_desc));
|
||||||
|
desc->irq = irq;
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
desc->cpu = cpu;
|
||||||
|
#endif
|
||||||
|
lockdep_set_class(&desc->lock, &irq_desc_lock_class);
|
||||||
|
init_kstat_irqs(desc, cpu, nr_cpu_ids);
|
||||||
|
if (!desc->kstat_irqs) {
|
||||||
|
printk(KERN_ERR "can not alloc kstat_irqs\n");
|
||||||
|
BUG_ON(1);
|
||||||
|
}
|
||||||
|
arch_init_chip_data(desc, cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Protect the sparse_irqs:
|
||||||
|
*/
|
||||||
|
static DEFINE_SPINLOCK(sparse_irq_lock);
|
||||||
|
|
||||||
|
struct irq_desc *irq_desc_ptrs[NR_IRQS] __read_mostly;
|
||||||
|
|
||||||
|
static struct irq_desc irq_desc_legacy[NR_IRQS_LEGACY] __cacheline_aligned_in_smp = {
|
||||||
|
[0 ... NR_IRQS_LEGACY-1] = {
|
||||||
|
.irq = -1,
|
||||||
|
.status = IRQ_DISABLED,
|
||||||
|
.chip = &no_irq_chip,
|
||||||
|
.handle_irq = handle_bad_irq,
|
||||||
|
.depth = 1,
|
||||||
|
.lock = __SPIN_LOCK_UNLOCKED(irq_desc_init.lock),
|
||||||
|
#ifdef CONFIG_SMP
|
||||||
|
.affinity = CPU_MASK_ALL
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FIXME: use bootmem alloc ...*/
|
||||||
|
static unsigned int kstat_irqs_legacy[NR_IRQS_LEGACY][NR_CPUS];
|
||||||
|
|
||||||
|
void __init early_irq_init(void)
|
||||||
|
{
|
||||||
|
struct irq_desc *desc;
|
||||||
|
int legacy_count;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
desc = irq_desc_legacy;
|
||||||
|
legacy_count = ARRAY_SIZE(irq_desc_legacy);
|
||||||
|
|
||||||
|
for (i = 0; i < legacy_count; i++) {
|
||||||
|
desc[i].irq = i;
|
||||||
|
desc[i].kstat_irqs = kstat_irqs_legacy[i];
|
||||||
|
|
||||||
|
irq_desc_ptrs[i] = desc + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = legacy_count; i < NR_IRQS; i++)
|
||||||
|
irq_desc_ptrs[i] = NULL;
|
||||||
|
|
||||||
|
arch_early_irq_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct irq_desc *irq_to_desc(unsigned int irq)
|
||||||
|
{
|
||||||
|
return (irq < NR_IRQS) ? irq_desc_ptrs[irq] : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct irq_desc *irq_to_desc_alloc_cpu(unsigned int irq, int cpu)
|
||||||
|
{
|
||||||
|
struct irq_desc *desc;
|
||||||
|
unsigned long flags;
|
||||||
|
int node;
|
||||||
|
|
||||||
|
if (irq >= NR_IRQS) {
|
||||||
|
printk(KERN_WARNING "irq >= NR_IRQS in irq_to_desc_alloc: %d %d\n",
|
||||||
|
irq, NR_IRQS);
|
||||||
|
WARN_ON(1);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc = irq_desc_ptrs[irq];
|
||||||
|
if (desc)
|
||||||
|
return desc;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&sparse_irq_lock, flags);
|
||||||
|
|
||||||
|
/* We have to check it to avoid races with another CPU */
|
||||||
|
desc = irq_desc_ptrs[irq];
|
||||||
|
if (desc)
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
|
node = cpu_to_node(cpu);
|
||||||
|
desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
|
||||||
|
printk(KERN_DEBUG " alloc irq_desc for %d on cpu %d node %d\n",
|
||||||
|
irq, cpu, node);
|
||||||
|
if (!desc) {
|
||||||
|
printk(KERN_ERR "can not alloc irq_desc\n");
|
||||||
|
BUG_ON(1);
|
||||||
|
}
|
||||||
|
init_one_irq_desc(irq, desc, cpu);
|
||||||
|
|
||||||
|
irq_desc_ptrs[irq] = desc;
|
||||||
|
|
||||||
|
out_unlock:
|
||||||
|
spin_unlock_irqrestore(&sparse_irq_lock, flags);
|
||||||
|
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
|
struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
|
||||||
[0 ... NR_IRQS-1] = {
|
[0 ... NR_IRQS-1] = {
|
||||||
.status = IRQ_DISABLED,
|
.status = IRQ_DISABLED,
|
||||||
@ -62,6 +218,8 @@ struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* What should we do if we get a hw irq event on an illegal vector?
|
* What should we do if we get a hw irq event on an illegal vector?
|
||||||
* Each architecture has to answer this themself.
|
* Each architecture has to answer this themself.
|
||||||
@ -261,17 +419,28 @@ unsigned int __do_IRQ(unsigned int irq)
|
|||||||
|
|
||||||
|
|
||||||
#ifdef CONFIG_TRACE_IRQFLAGS
|
#ifdef CONFIG_TRACE_IRQFLAGS
|
||||||
/*
|
|
||||||
* lockdep: we want to handle all irq_desc locks as a single lock-class:
|
|
||||||
*/
|
|
||||||
static struct lock_class_key irq_desc_lock_class;
|
|
||||||
|
|
||||||
void early_init_irq_lock_class(void)
|
void early_init_irq_lock_class(void)
|
||||||
{
|
{
|
||||||
|
#ifndef CONFIG_SPARSE_IRQ
|
||||||
struct irq_desc *desc;
|
struct irq_desc *desc;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for_each_irq_desc(i, desc)
|
for_each_irq_desc(i, desc) {
|
||||||
|
if (!desc)
|
||||||
|
continue;
|
||||||
|
|
||||||
lockdep_set_class(&desc->lock, &irq_desc_lock_class);
|
lockdep_set_class(&desc->lock, &irq_desc_lock_class);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_SPARSE_IRQ
|
||||||
|
unsigned int kstat_irqs_cpu(unsigned int irq, int cpu)
|
||||||
|
{
|
||||||
|
struct irq_desc *desc = irq_to_desc(irq);
|
||||||
|
return desc->kstat_irqs[cpu];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
EXPORT_SYMBOL(kstat_irqs_cpu);
|
||||||
|
|
||||||
|
@ -243,7 +243,11 @@ void init_irq_proc(void)
|
|||||||
/*
|
/*
|
||||||
* Create entries for all existing IRQs.
|
* Create entries for all existing IRQs.
|
||||||
*/
|
*/
|
||||||
for_each_irq_desc(irq, desc)
|
for_each_irq_desc(irq, desc) {
|
||||||
|
if (!desc)
|
||||||
|
continue;
|
||||||
|
|
||||||
register_irq_proc(irq, desc);
|
register_irq_proc(irq, desc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +91,9 @@ static int misrouted_irq(int irq)
|
|||||||
int i, ok = 0;
|
int i, ok = 0;
|
||||||
|
|
||||||
for_each_irq_desc(i, desc) {
|
for_each_irq_desc(i, desc) {
|
||||||
|
if (!desc)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (!i)
|
if (!i)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -112,6 +115,8 @@ static void poll_spurious_irqs(unsigned long dummy)
|
|||||||
for_each_irq_desc(i, desc) {
|
for_each_irq_desc(i, desc) {
|
||||||
unsigned int status;
|
unsigned int status;
|
||||||
|
|
||||||
|
if (!desc)
|
||||||
|
continue;
|
||||||
if (!i)
|
if (!i)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user