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:
Ingo Molnar 2008-12-12 13:49:17 +01:00
commit 8299608f14
60 changed files with 1227 additions and 503 deletions

View File

@ -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"

View File

@ -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 */

View File

@ -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)
{ {

View File

@ -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;

View File

@ -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++;

View File

@ -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 */

View File

@ -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,
@ -105,16 +114,24 @@ struct genapic {
APICFUNC(get_apic_id) \ APICFUNC(get_apic_id) \
.apic_id_mask = APIC_ID_MASK, \ .apic_id_mask = APIC_ID_MASK, \
APICFUNC(cpu_mask_to_apicid) \ APICFUNC(cpu_mask_to_apicid) \
APICFUNC(vector_allocation_domain) \ APICFUNC(vector_allocation_domain) \
APICFUNC(acpi_madt_oem_check) \ APICFUNC(acpi_madt_oem_check) \
IPIFUNC(send_IPI_mask) \ IPIFUNC(send_IPI_mask) \
IPIFUNC(send_IPI_allbutself) \ IPIFUNC(send_IPI_allbutself) \
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

View File

@ -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;

View File

@ -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 */

View File

@ -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)

View File

@ -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.
* *

View File

@ -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 */

View File

@ -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)

View File

@ -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);

View 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 */

View File

@ -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 */

View File

@ -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;

View File

@ -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

View File

@ -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;
} }

View File

@ -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

View File

@ -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)
{ {

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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)
{ {
} }

View File

@ -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)

View File

@ -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();

View File

@ -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.
*/ */

View File

@ -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;

View File

@ -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 */

View File

@ -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)

View File

@ -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)
{ {

View File

@ -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);
} }

View File

@ -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)
{ {

View File

@ -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;
} }

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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());

View File

@ -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);

View File

@ -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

View File

@ -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>

View File

@ -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 */

View File

@ -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

View File

@ -28,7 +28,9 @@ struct cpu_usage_stat {
struct kernel_stat { struct kernel_stat {
struct cpu_usage_stat cpustat; struct cpu_usage_stat cpustat;
unsigned int irqs[NR_IRQS]; #ifndef CONFIG_SPARSE_IRQ
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

View File

@ -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);

View File

@ -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);

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);
}
} }

View File

@ -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;