Merge branch 'linus' into perfcounters/core-v2
Merge reason: we have gathered quite a few conflicts, need to merge upstream Conflicts: arch/powerpc/kernel/Makefile arch/x86/ia32/ia32entry.S arch/x86/include/asm/hardirq.h arch/x86/include/asm/unistd_32.h arch/x86/include/asm/unistd_64.h arch/x86/kernel/cpu/common.c arch/x86/kernel/irq.c arch/x86/kernel/syscall_table_32.S arch/x86/mm/iomap_32.c include/linux/sched.h kernel/Makefile Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@@ -47,6 +47,7 @@
|
||||
#include <asm/idle.h>
|
||||
#include <asm/mtrr.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/mce.h>
|
||||
|
||||
unsigned int num_processors;
|
||||
|
||||
@@ -811,7 +812,7 @@ void clear_local_APIC(void)
|
||||
u32 v;
|
||||
|
||||
/* APIC hasn't been mapped yet */
|
||||
if (!apic_phys)
|
||||
if (!x2apic && !apic_phys)
|
||||
return;
|
||||
|
||||
maxlvt = lapic_get_maxlvt();
|
||||
@@ -845,6 +846,14 @@ void clear_local_APIC(void)
|
||||
apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED);
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_X86_MCE_INTEL
|
||||
if (maxlvt >= 6) {
|
||||
v = apic_read(APIC_LVTCMCI);
|
||||
if (!(v & APIC_LVT_MASKED))
|
||||
apic_write(APIC_LVTCMCI, v | APIC_LVT_MASKED);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Clean APIC state for other OSs:
|
||||
*/
|
||||
@@ -1245,6 +1254,12 @@ void __cpuinit setup_local_APIC(void)
|
||||
apic_write(APIC_LVT1, value);
|
||||
|
||||
preempt_enable();
|
||||
|
||||
#ifdef CONFIG_X86_MCE_INTEL
|
||||
/* Recheck CMCI information after local APIC is up on CPU #0 */
|
||||
if (smp_processor_id() == 0)
|
||||
cmci_recheck();
|
||||
#endif
|
||||
}
|
||||
|
||||
void __cpuinit end_local_APIC_setup(void)
|
||||
@@ -1323,15 +1338,16 @@ void __init enable_IR_x2apic(void)
|
||||
return;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
mask_8259A();
|
||||
|
||||
ret = save_mask_IO_APIC_setup();
|
||||
ret = save_IO_APIC_setup();
|
||||
if (ret) {
|
||||
pr_info("Saving IO-APIC state failed: %d\n", ret);
|
||||
goto end;
|
||||
}
|
||||
|
||||
local_irq_save(flags);
|
||||
mask_IO_APIC_setup();
|
||||
mask_8259A();
|
||||
|
||||
ret = enable_intr_remapping(1);
|
||||
|
||||
if (ret && x2apic_preenabled) {
|
||||
@@ -1356,10 +1372,10 @@ end_restore:
|
||||
else
|
||||
reinit_intr_remapped_IO_APIC(x2apic_preenabled);
|
||||
|
||||
end:
|
||||
unmask_8259A();
|
||||
local_irq_restore(flags);
|
||||
|
||||
end:
|
||||
if (!ret) {
|
||||
if (!x2apic_preenabled)
|
||||
pr_info("Enabled x2apic and interrupt-remapping\n");
|
||||
@@ -1512,12 +1528,10 @@ void __init early_init_lapic_mapping(void)
|
||||
*/
|
||||
void __init init_apic_mappings(void)
|
||||
{
|
||||
#ifdef CONFIG_X86_X2APIC
|
||||
if (x2apic) {
|
||||
boot_cpu_physical_apicid = read_apic_id();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If no local APIC can be found then set up a fake all
|
||||
@@ -1961,12 +1975,9 @@ static int lapic_resume(struct sys_device *dev)
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
#ifdef CONFIG_X86_X2APIC
|
||||
if (x2apic)
|
||||
enable_x2apic();
|
||||
else
|
||||
#endif
|
||||
{
|
||||
else {
|
||||
/*
|
||||
* Make sure the APICBASE points to the right address
|
||||
*
|
||||
|
@@ -159,20 +159,6 @@ static int flat_apic_id_registered(void)
|
||||
return physid_isset(read_xapic_id(), phys_cpu_present_map);
|
||||
}
|
||||
|
||||
static unsigned int flat_cpu_mask_to_apicid(const struct cpumask *cpumask)
|
||||
{
|
||||
return cpumask_bits(cpumask)[0] & APIC_ALL_CPUS;
|
||||
}
|
||||
|
||||
static unsigned int flat_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
|
||||
const struct cpumask *andmask)
|
||||
{
|
||||
unsigned long mask1 = cpumask_bits(cpumask)[0] & APIC_ALL_CPUS;
|
||||
unsigned long mask2 = cpumask_bits(andmask)[0] & APIC_ALL_CPUS;
|
||||
|
||||
return mask1 & mask2;
|
||||
}
|
||||
|
||||
static int flat_phys_pkg_id(int initial_apic_id, int index_msb)
|
||||
{
|
||||
return hard_smp_processor_id() >> index_msb;
|
||||
@@ -213,8 +199,8 @@ struct apic apic_flat = {
|
||||
.set_apic_id = set_apic_id,
|
||||
.apic_id_mask = 0xFFu << 24,
|
||||
|
||||
.cpu_mask_to_apicid = flat_cpu_mask_to_apicid,
|
||||
.cpu_mask_to_apicid_and = flat_cpu_mask_to_apicid_and,
|
||||
.cpu_mask_to_apicid = default_cpu_mask_to_apicid,
|
||||
.cpu_mask_to_apicid_and = default_cpu_mask_to_apicid_and,
|
||||
|
||||
.send_IPI_mask = flat_send_IPI_mask,
|
||||
.send_IPI_mask_allbutself = flat_send_IPI_mask_allbutself,
|
||||
@@ -222,7 +208,6 @@ struct apic apic_flat = {
|
||||
.send_IPI_all = flat_send_IPI_all,
|
||||
.send_IPI_self = apic_send_IPI_self,
|
||||
|
||||
.wakeup_cpu = NULL,
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
.wait_for_init_deassert = NULL,
|
||||
@@ -373,7 +358,6 @@ struct apic apic_physflat = {
|
||||
.send_IPI_all = physflat_send_IPI_all,
|
||||
.send_IPI_self = apic_send_IPI_self,
|
||||
|
||||
.wakeup_cpu = NULL,
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
.wait_for_init_deassert = NULL,
|
||||
|
@@ -16,32 +16,31 @@
|
||||
#include <asm/apic.h>
|
||||
#include <asm/ipi.h>
|
||||
|
||||
static inline unsigned bigsmp_get_apic_id(unsigned long x)
|
||||
static unsigned bigsmp_get_apic_id(unsigned long x)
|
||||
{
|
||||
return (x >> 24) & 0xFF;
|
||||
}
|
||||
|
||||
static inline int bigsmp_apic_id_registered(void)
|
||||
static int bigsmp_apic_id_registered(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline const cpumask_t *bigsmp_target_cpus(void)
|
||||
static const struct cpumask *bigsmp_target_cpus(void)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
return &cpu_online_map;
|
||||
return cpu_online_mask;
|
||||
#else
|
||||
return &cpumask_of_cpu(0);
|
||||
return cpumask_of(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
bigsmp_check_apicid_used(physid_mask_t bitmap, int apicid)
|
||||
static unsigned long bigsmp_check_apicid_used(physid_mask_t bitmap, int apicid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline unsigned long bigsmp_check_apicid_present(int bit)
|
||||
static unsigned long bigsmp_check_apicid_present(int bit)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -64,7 +63,7 @@ static inline unsigned long calculate_ldr(int cpu)
|
||||
* an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
|
||||
* document number 292116). So here it goes...
|
||||
*/
|
||||
static inline void bigsmp_init_apic_ldr(void)
|
||||
static void bigsmp_init_apic_ldr(void)
|
||||
{
|
||||
unsigned long val;
|
||||
int cpu = smp_processor_id();
|
||||
@@ -74,19 +73,19 @@ static inline void bigsmp_init_apic_ldr(void)
|
||||
apic_write(APIC_LDR, val);
|
||||
}
|
||||
|
||||
static inline void bigsmp_setup_apic_routing(void)
|
||||
static void bigsmp_setup_apic_routing(void)
|
||||
{
|
||||
printk(KERN_INFO
|
||||
"Enabling APIC mode: Physflat. Using %d I/O APICs\n",
|
||||
nr_ioapics);
|
||||
}
|
||||
|
||||
static inline int bigsmp_apicid_to_node(int logical_apicid)
|
||||
static int bigsmp_apicid_to_node(int logical_apicid)
|
||||
{
|
||||
return apicid_2_node[hard_smp_processor_id()];
|
||||
}
|
||||
|
||||
static inline int bigsmp_cpu_present_to_apicid(int mps_cpu)
|
||||
static int bigsmp_cpu_present_to_apicid(int mps_cpu)
|
||||
{
|
||||
if (mps_cpu < nr_cpu_ids)
|
||||
return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu);
|
||||
@@ -94,7 +93,7 @@ static inline int bigsmp_cpu_present_to_apicid(int mps_cpu)
|
||||
return BAD_APICID;
|
||||
}
|
||||
|
||||
static inline physid_mask_t bigsmp_apicid_to_cpu_present(int phys_apicid)
|
||||
static physid_mask_t bigsmp_apicid_to_cpu_present(int phys_apicid)
|
||||
{
|
||||
return physid_mask_of_physid(phys_apicid);
|
||||
}
|
||||
@@ -107,29 +106,24 @@ static inline int bigsmp_cpu_to_logical_apicid(int cpu)
|
||||
return cpu_physical_id(cpu);
|
||||
}
|
||||
|
||||
static inline physid_mask_t bigsmp_ioapic_phys_id_map(physid_mask_t phys_map)
|
||||
static physid_mask_t bigsmp_ioapic_phys_id_map(physid_mask_t phys_map)
|
||||
{
|
||||
/* For clustered we don't have a good way to do this yet - hack */
|
||||
return physids_promote(0xFFL);
|
||||
}
|
||||
|
||||
static inline void bigsmp_setup_portio_remap(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int bigsmp_check_phys_apicid_present(int boot_cpu_physical_apicid)
|
||||
static int bigsmp_check_phys_apicid_present(int boot_cpu_physical_apicid)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* As we are using single CPU as destination, pick only one CPU here */
|
||||
static inline unsigned int bigsmp_cpu_mask_to_apicid(const cpumask_t *cpumask)
|
||||
static unsigned int bigsmp_cpu_mask_to_apicid(const struct cpumask *cpumask)
|
||||
{
|
||||
return bigsmp_cpu_to_logical_apicid(first_cpu(*cpumask));
|
||||
return bigsmp_cpu_to_logical_apicid(cpumask_first(cpumask));
|
||||
}
|
||||
|
||||
static inline unsigned int
|
||||
bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
|
||||
static unsigned int bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
|
||||
const struct cpumask *andmask)
|
||||
{
|
||||
int cpu;
|
||||
@@ -148,7 +142,7 @@ bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
|
||||
return BAD_APICID;
|
||||
}
|
||||
|
||||
static inline int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb)
|
||||
static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb)
|
||||
{
|
||||
return cpuid_apic >> index_msb;
|
||||
}
|
||||
@@ -158,12 +152,12 @@ static inline void bigsmp_send_IPI_mask(const struct cpumask *mask, int vector)
|
||||
default_send_IPI_mask_sequence_phys(mask, vector);
|
||||
}
|
||||
|
||||
static inline void bigsmp_send_IPI_allbutself(int vector)
|
||||
static void bigsmp_send_IPI_allbutself(int vector)
|
||||
{
|
||||
default_send_IPI_mask_allbutself_phys(cpu_online_mask, vector);
|
||||
}
|
||||
|
||||
static inline void bigsmp_send_IPI_all(int vector)
|
||||
static void bigsmp_send_IPI_all(int vector)
|
||||
{
|
||||
bigsmp_send_IPI_mask(cpu_online_mask, vector);
|
||||
}
|
||||
@@ -194,10 +188,10 @@ static const struct dmi_system_id bigsmp_dmi_table[] = {
|
||||
{ } /* NULL entry stops DMI scanning */
|
||||
};
|
||||
|
||||
static void bigsmp_vector_allocation_domain(int cpu, cpumask_t *retmask)
|
||||
static void bigsmp_vector_allocation_domain(int cpu, struct cpumask *retmask)
|
||||
{
|
||||
cpus_clear(*retmask);
|
||||
cpu_set(cpu, *retmask);
|
||||
cpumask_clear(retmask);
|
||||
cpumask_set_cpu(cpu, retmask);
|
||||
}
|
||||
|
||||
static int probe_bigsmp(void)
|
||||
@@ -256,7 +250,6 @@ struct apic apic_bigsmp = {
|
||||
.send_IPI_all = bigsmp_send_IPI_all,
|
||||
.send_IPI_self = default_send_IPI_self,
|
||||
|
||||
.wakeup_cpu = NULL,
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
|
||||
|
@@ -163,22 +163,17 @@ static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init es7000_update_apic(void)
|
||||
static int es7000_apic_is_cluster(void)
|
||||
{
|
||||
apic->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_apic_to_cluster();
|
||||
apic->wait_for_init_deassert = NULL;
|
||||
apic->wakeup_cpu = wakeup_secondary_cpu_via_mip;
|
||||
}
|
||||
(boot_cpu_data.x86_model >= 7 || boot_cpu_data.x86_model <= 11))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init setup_unisys(void)
|
||||
static void setup_unisys(void)
|
||||
{
|
||||
/*
|
||||
* Determine the generation of the ES7000 currently running.
|
||||
@@ -192,14 +187,12 @@ static void __init setup_unisys(void)
|
||||
else
|
||||
es7000_plat = ES7000_CLASSIC;
|
||||
ioapic_renumber_irq = es7000_rename_gsi;
|
||||
|
||||
x86_quirks->update_apic = es7000_update_apic;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the OEM Table:
|
||||
*/
|
||||
static int __init parse_unisys_oem(char *oemptr)
|
||||
static int parse_unisys_oem(char *oemptr)
|
||||
{
|
||||
int i;
|
||||
int success = 0;
|
||||
@@ -261,7 +254,7 @@ static int __init parse_unisys_oem(char *oemptr)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static int __init find_unisys_acpi_oem_table(unsigned long *oem_addr)
|
||||
static int find_unisys_acpi_oem_table(unsigned long *oem_addr)
|
||||
{
|
||||
struct acpi_table_header *header = NULL;
|
||||
struct es7000_oem_table *table;
|
||||
@@ -292,7 +285,7 @@ static int __init find_unisys_acpi_oem_table(unsigned long *oem_addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init unmap_unisys_acpi_oem_table(unsigned long oem_addr)
|
||||
static void unmap_unisys_acpi_oem_table(unsigned long oem_addr)
|
||||
{
|
||||
if (!oem_addr)
|
||||
return;
|
||||
@@ -310,8 +303,10 @@ static int es7000_check_dsdt(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int es7000_acpi_ret;
|
||||
|
||||
/* Hook from generic ACPI tables.c */
|
||||
static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
static int es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
{
|
||||
unsigned long oem_addr = 0;
|
||||
int check_dsdt;
|
||||
@@ -332,10 +327,26 @@ static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
*/
|
||||
unmap_unisys_acpi_oem_table(oem_addr);
|
||||
}
|
||||
return ret;
|
||||
|
||||
es7000_acpi_ret = ret;
|
||||
|
||||
return ret && !es7000_apic_is_cluster();
|
||||
}
|
||||
|
||||
static int es7000_acpi_madt_oem_check_cluster(char *oem_id, char *oem_table_id)
|
||||
{
|
||||
int ret = es7000_acpi_ret;
|
||||
|
||||
return ret && es7000_apic_is_cluster();
|
||||
}
|
||||
|
||||
#else /* !CONFIG_ACPI: */
|
||||
static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
static int es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int es7000_acpi_madt_oem_check_cluster(char *oem_id, char *oem_table_id)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -349,8 +360,7 @@ static void es7000_spin(int n)
|
||||
rep_nop();
|
||||
}
|
||||
|
||||
static int __init
|
||||
es7000_mip_write(struct mip_reg *mip_reg)
|
||||
static int es7000_mip_write(struct mip_reg *mip_reg)
|
||||
{
|
||||
int status = 0;
|
||||
int spin;
|
||||
@@ -383,7 +393,7 @@ es7000_mip_write(struct mip_reg *mip_reg)
|
||||
return status;
|
||||
}
|
||||
|
||||
static void __init es7000_enable_apic_mode(void)
|
||||
static void es7000_enable_apic_mode(void)
|
||||
{
|
||||
struct mip_reg es7000_mip_reg;
|
||||
int mip_status;
|
||||
@@ -400,7 +410,7 @@ static void __init es7000_enable_apic_mode(void)
|
||||
WARN(1, "Command failed, status = %x\n", mip_status);
|
||||
}
|
||||
|
||||
static void es7000_vector_allocation_domain(int cpu, cpumask_t *retmask)
|
||||
static void es7000_vector_allocation_domain(int cpu, struct cpumask *retmask)
|
||||
{
|
||||
/* Careful. Some cpus do not strictly honor the set of cpus
|
||||
* specified in the interrupt destination when using lowest
|
||||
@@ -410,17 +420,15 @@ static void es7000_vector_allocation_domain(int cpu, cpumask_t *retmask)
|
||||
* deliver interrupts to the wrong hyperthread when only one
|
||||
* hyperthread was specified in the interrupt desitination.
|
||||
*/
|
||||
*retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } };
|
||||
cpumask_clear(retmask);
|
||||
cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
|
||||
}
|
||||
|
||||
|
||||
static void es7000_wait_for_init_deassert(atomic_t *deassert)
|
||||
{
|
||||
#ifndef CONFIG_ES7000_CLUSTERED_APIC
|
||||
while (!atomic_read(deassert))
|
||||
cpu_relax();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
static unsigned int es7000_get_apic_id(unsigned long x)
|
||||
@@ -448,14 +456,14 @@ static int es7000_apic_id_registered(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const cpumask_t *target_cpus_cluster(void)
|
||||
static const struct cpumask *target_cpus_cluster(void)
|
||||
{
|
||||
return &CPU_MASK_ALL;
|
||||
return cpu_all_mask;
|
||||
}
|
||||
|
||||
static const cpumask_t *es7000_target_cpus(void)
|
||||
static const struct cpumask *es7000_target_cpus(void)
|
||||
{
|
||||
return &cpumask_of_cpu(smp_processor_id());
|
||||
return cpumask_of(smp_processor_id());
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
@@ -510,7 +518,7 @@ static void es7000_setup_apic_routing(void)
|
||||
"Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n",
|
||||
(apic_version[apic] == 0x14) ?
|
||||
"Physical Cluster" : "Logical Cluster",
|
||||
nr_ioapics, cpus_addr(*es7000_target_cpus())[0]);
|
||||
nr_ioapics, cpumask_bits(es7000_target_cpus())[0]);
|
||||
}
|
||||
|
||||
static int es7000_apicid_to_node(int logical_apicid)
|
||||
@@ -565,72 +573,24 @@ static int es7000_check_phys_apicid_present(int cpu_physical_apicid)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
es7000_cpu_mask_to_apicid_cluster(const struct cpumask *cpumask)
|
||||
static unsigned int es7000_cpu_mask_to_apicid(const struct cpumask *cpumask)
|
||||
{
|
||||
int cpus_found = 0;
|
||||
int num_bits_set;
|
||||
int apicid;
|
||||
int cpu;
|
||||
unsigned int round = 0;
|
||||
int cpu, uninitialized_var(apicid);
|
||||
|
||||
num_bits_set = cpumask_weight(cpumask);
|
||||
/* Return id to all */
|
||||
if (num_bits_set == nr_cpu_ids)
|
||||
return 0xFF;
|
||||
/*
|
||||
* 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():
|
||||
* The cpus in the mask must all be on the apic cluster.
|
||||
*/
|
||||
cpu = cpumask_first(cpumask);
|
||||
apicid = es7000_cpu_to_logical_apicid(cpu);
|
||||
for_each_cpu(cpu, cpumask) {
|
||||
int new_apicid = es7000_cpu_to_logical_apicid(cpu);
|
||||
|
||||
while (cpus_found < num_bits_set) {
|
||||
if (cpumask_test_cpu(cpu, cpumask)) {
|
||||
int new_apicid = es7000_cpu_to_logical_apicid(cpu);
|
||||
if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
|
||||
WARN(1, "Not a valid mask!");
|
||||
|
||||
if (APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
|
||||
WARN(1, "Not a valid mask!");
|
||||
|
||||
return 0xFF;
|
||||
}
|
||||
apicid = new_apicid;
|
||||
cpus_found++;
|
||||
return BAD_APICID;
|
||||
}
|
||||
cpu++;
|
||||
}
|
||||
return apicid;
|
||||
}
|
||||
|
||||
static unsigned int es7000_cpu_mask_to_apicid(const cpumask_t *cpumask)
|
||||
{
|
||||
int cpus_found = 0;
|
||||
int num_bits_set;
|
||||
int apicid;
|
||||
int cpu;
|
||||
|
||||
num_bits_set = cpus_weight(*cpumask);
|
||||
/* Return id to all */
|
||||
if (num_bits_set == nr_cpu_ids)
|
||||
return es7000_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 = es7000_cpu_to_logical_apicid(cpu);
|
||||
while (cpus_found < num_bits_set) {
|
||||
if (cpu_isset(cpu, *cpumask)) {
|
||||
int new_apicid = es7000_cpu_to_logical_apicid(cpu);
|
||||
|
||||
if (APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
|
||||
printk("%s: Not a valid mask!\n", __func__);
|
||||
|
||||
return es7000_cpu_to_logical_apicid(0);
|
||||
}
|
||||
apicid = new_apicid;
|
||||
cpus_found++;
|
||||
}
|
||||
cpu++;
|
||||
apicid = new_apicid;
|
||||
round++;
|
||||
}
|
||||
return apicid;
|
||||
}
|
||||
@@ -659,37 +619,103 @@ static int es7000_phys_pkg_id(int cpuid_apic, int index_msb)
|
||||
return cpuid_apic >> index_msb;
|
||||
}
|
||||
|
||||
void __init es7000_update_apic_to_cluster(void)
|
||||
{
|
||||
apic->target_cpus = target_cpus_cluster;
|
||||
apic->irq_delivery_mode = dest_LowestPrio;
|
||||
/* logical delivery broadcast to all procs: */
|
||||
apic->irq_dest_mode = 1;
|
||||
|
||||
apic->init_apic_ldr = es7000_init_apic_ldr_cluster;
|
||||
|
||||
apic->cpu_mask_to_apicid = es7000_cpu_mask_to_apicid_cluster;
|
||||
}
|
||||
|
||||
static int probe_es7000(void)
|
||||
{
|
||||
/* probed later in mptable/ACPI hooks */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __init int
|
||||
es7000_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
|
||||
static int es7000_mps_ret;
|
||||
static int es7000_mps_oem_check(struct mpc_table *mpc, char *oem,
|
||||
char *productid)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (mpc->oemptr) {
|
||||
struct mpc_oemtable *oem_table =
|
||||
(struct mpc_oemtable *)mpc->oemptr;
|
||||
|
||||
if (!strncmp(oem, "UNISYS", 6))
|
||||
return parse_unisys_oem((char *)oem_table);
|
||||
ret = parse_unisys_oem((char *)oem_table);
|
||||
}
|
||||
return 0;
|
||||
|
||||
es7000_mps_ret = ret;
|
||||
|
||||
return ret && !es7000_apic_is_cluster();
|
||||
}
|
||||
|
||||
static int es7000_mps_oem_check_cluster(struct mpc_table *mpc, char *oem,
|
||||
char *productid)
|
||||
{
|
||||
int ret = es7000_mps_ret;
|
||||
|
||||
return ret && es7000_apic_is_cluster();
|
||||
}
|
||||
|
||||
struct apic apic_es7000_cluster = {
|
||||
|
||||
.name = "es7000",
|
||||
.probe = probe_es7000,
|
||||
.acpi_madt_oem_check = es7000_acpi_madt_oem_check_cluster,
|
||||
.apic_id_registered = es7000_apic_id_registered,
|
||||
|
||||
.irq_delivery_mode = dest_LowestPrio,
|
||||
/* logical delivery broadcast to all procs: */
|
||||
.irq_dest_mode = 1,
|
||||
|
||||
.target_cpus = target_cpus_cluster,
|
||||
.disable_esr = 1,
|
||||
.dest_logical = 0,
|
||||
.check_apicid_used = es7000_check_apicid_used,
|
||||
.check_apicid_present = es7000_check_apicid_present,
|
||||
|
||||
.vector_allocation_domain = es7000_vector_allocation_domain,
|
||||
.init_apic_ldr = es7000_init_apic_ldr_cluster,
|
||||
|
||||
.ioapic_phys_id_map = es7000_ioapic_phys_id_map,
|
||||
.setup_apic_routing = es7000_setup_apic_routing,
|
||||
.multi_timer_check = NULL,
|
||||
.apicid_to_node = es7000_apicid_to_node,
|
||||
.cpu_to_logical_apicid = es7000_cpu_to_logical_apicid,
|
||||
.cpu_present_to_apicid = es7000_cpu_present_to_apicid,
|
||||
.apicid_to_cpu_present = es7000_apicid_to_cpu_present,
|
||||
.setup_portio_remap = NULL,
|
||||
.check_phys_apicid_present = es7000_check_phys_apicid_present,
|
||||
.enable_apic_mode = es7000_enable_apic_mode,
|
||||
.phys_pkg_id = es7000_phys_pkg_id,
|
||||
.mps_oem_check = es7000_mps_oem_check_cluster,
|
||||
|
||||
.get_apic_id = es7000_get_apic_id,
|
||||
.set_apic_id = NULL,
|
||||
.apic_id_mask = 0xFF << 24,
|
||||
|
||||
.cpu_mask_to_apicid = es7000_cpu_mask_to_apicid,
|
||||
.cpu_mask_to_apicid_and = es7000_cpu_mask_to_apicid_and,
|
||||
|
||||
.send_IPI_mask = es7000_send_IPI_mask,
|
||||
.send_IPI_mask_allbutself = NULL,
|
||||
.send_IPI_allbutself = es7000_send_IPI_allbutself,
|
||||
.send_IPI_all = es7000_send_IPI_all,
|
||||
.send_IPI_self = default_send_IPI_self,
|
||||
|
||||
.wakeup_secondary_cpu = wakeup_secondary_cpu_via_mip,
|
||||
|
||||
.trampoline_phys_low = 0x467,
|
||||
.trampoline_phys_high = 0x469,
|
||||
|
||||
.wait_for_init_deassert = NULL,
|
||||
|
||||
/* Nothing to do for most platforms, since cleared by the INIT cycle: */
|
||||
.smp_callin_clear_local_apic = NULL,
|
||||
.inquire_remote_apic = default_inquire_remote_apic,
|
||||
|
||||
.read = native_apic_mem_read,
|
||||
.write = native_apic_mem_write,
|
||||
.icr_read = native_apic_icr_read,
|
||||
.icr_write = native_apic_icr_write,
|
||||
.wait_icr_idle = native_apic_wait_icr_idle,
|
||||
.safe_wait_icr_idle = native_safe_apic_wait_icr_idle,
|
||||
};
|
||||
|
||||
struct apic apic_es7000 = {
|
||||
|
||||
@@ -737,8 +763,6 @@ struct apic apic_es7000 = {
|
||||
.send_IPI_all = es7000_send_IPI_all,
|
||||
.send_IPI_self = default_send_IPI_self,
|
||||
|
||||
.wakeup_cpu = NULL,
|
||||
|
||||
.trampoline_phys_low = 0x467,
|
||||
.trampoline_phys_high = 0x469,
|
||||
|
||||
|
@@ -389,6 +389,8 @@ struct io_apic {
|
||||
unsigned int index;
|
||||
unsigned int unused[3];
|
||||
unsigned int data;
|
||||
unsigned int unused2[11];
|
||||
unsigned int eoi;
|
||||
};
|
||||
|
||||
static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
|
||||
@@ -397,6 +399,12 @@ static __attribute_const__ struct io_apic __iomem *io_apic_base(int idx)
|
||||
+ (mp_ioapics[idx].apicaddr & ~PAGE_MASK);
|
||||
}
|
||||
|
||||
static inline void io_apic_eoi(unsigned int apic, unsigned int vector)
|
||||
{
|
||||
struct io_apic __iomem *io_apic = io_apic_base(apic);
|
||||
writel(vector, &io_apic->eoi);
|
||||
}
|
||||
|
||||
static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
|
||||
{
|
||||
struct io_apic __iomem *io_apic = io_apic_base(apic);
|
||||
@@ -546,16 +554,12 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq
|
||||
|
||||
apic = entry->apic;
|
||||
pin = entry->pin;
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
/*
|
||||
* With interrupt-remapping, destination information comes
|
||||
* from interrupt-remapping table entry.
|
||||
*/
|
||||
if (!irq_remapped(irq))
|
||||
io_apic_write(apic, 0x11 + pin*2, dest);
|
||||
#else
|
||||
io_apic_write(apic, 0x11 + pin*2, dest);
|
||||
#endif
|
||||
reg = io_apic_read(apic, 0x10 + pin*2);
|
||||
reg &= ~IO_APIC_REDIR_VECTOR_MASK;
|
||||
reg |= vector;
|
||||
@@ -588,10 +592,12 @@ set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
|
||||
if (assign_irq_vector(irq, cfg, mask))
|
||||
return BAD_APICID;
|
||||
|
||||
cpumask_and(desc->affinity, cfg->domain, mask);
|
||||
/* check that before desc->addinity get updated */
|
||||
set_extra_move_desc(desc, mask);
|
||||
|
||||
return apic->cpu_mask_to_apicid_and(desc->affinity, cpu_online_mask);
|
||||
cpumask_copy(desc->affinity, mask);
|
||||
|
||||
return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -849,9 +855,9 @@ __setup("pirq=", ioapic_pirq_setup);
|
||||
static struct IO_APIC_route_entry *early_ioapic_entries[MAX_IO_APICS];
|
||||
|
||||
/*
|
||||
* Saves and masks all the unmasked IO-APIC RTE's
|
||||
* Saves all the IO-APIC RTE's
|
||||
*/
|
||||
int save_mask_IO_APIC_setup(void)
|
||||
int save_IO_APIC_setup(void)
|
||||
{
|
||||
union IO_APIC_reg_01 reg_01;
|
||||
unsigned long flags;
|
||||
@@ -876,16 +882,9 @@ int save_mask_IO_APIC_setup(void)
|
||||
}
|
||||
|
||||
for (apic = 0; apic < nr_ioapics; apic++)
|
||||
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
|
||||
struct IO_APIC_route_entry entry;
|
||||
|
||||
entry = early_ioapic_entries[apic][pin] =
|
||||
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++)
|
||||
early_ioapic_entries[apic][pin] =
|
||||
ioapic_read_entry(apic, pin);
|
||||
if (!entry.mask) {
|
||||
entry.mask = 1;
|
||||
ioapic_write_entry(apic, pin, entry);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -898,6 +897,25 @@ nomem:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void mask_IO_APIC_setup(void)
|
||||
{
|
||||
int apic, pin;
|
||||
|
||||
for (apic = 0; apic < nr_ioapics; apic++) {
|
||||
if (!early_ioapic_entries[apic])
|
||||
break;
|
||||
for (pin = 0; pin < nr_ioapic_registers[apic]; pin++) {
|
||||
struct IO_APIC_route_entry entry;
|
||||
|
||||
entry = early_ioapic_entries[apic][pin];
|
||||
if (!entry.mask) {
|
||||
entry.mask = 1;
|
||||
ioapic_write_entry(apic, pin, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void restore_IO_APIC_setup(void)
|
||||
{
|
||||
int apic, pin;
|
||||
@@ -1411,9 +1429,7 @@ void __setup_vector_irq(int cpu)
|
||||
}
|
||||
|
||||
static struct irq_chip ioapic_chip;
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
static struct irq_chip ir_ioapic_chip;
|
||||
#endif
|
||||
|
||||
#define IOAPIC_AUTO -1
|
||||
#define IOAPIC_EDGE 0
|
||||
@@ -1452,7 +1468,6 @@ static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long t
|
||||
else
|
||||
desc->status &= ~IRQ_LEVEL;
|
||||
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
if (irq_remapped(irq)) {
|
||||
desc->status |= IRQ_MOVE_PCNTXT;
|
||||
if (trigger)
|
||||
@@ -1464,7 +1479,7 @@ static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long t
|
||||
handle_edge_irq, "edge");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
|
||||
trigger == IOAPIC_LEVEL)
|
||||
set_irq_chip_and_handler_name(irq, &ioapic_chip,
|
||||
@@ -1478,14 +1493,13 @@ static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long t
|
||||
int setup_ioapic_entry(int apic_id, int irq,
|
||||
struct IO_APIC_route_entry *entry,
|
||||
unsigned int destination, int trigger,
|
||||
int polarity, int vector)
|
||||
int polarity, int vector, int pin)
|
||||
{
|
||||
/*
|
||||
* add it to the IO-APIC irq-routing table:
|
||||
*/
|
||||
memset(entry,0,sizeof(*entry));
|
||||
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
if (intr_remapping_enabled) {
|
||||
struct intel_iommu *iommu = map_ioapic_to_ir(apic_id);
|
||||
struct irte irte;
|
||||
@@ -1504,7 +1518,14 @@ int setup_ioapic_entry(int apic_id, int irq,
|
||||
|
||||
irte.present = 1;
|
||||
irte.dst_mode = apic->irq_dest_mode;
|
||||
irte.trigger_mode = trigger;
|
||||
/*
|
||||
* Trigger mode in the IRTE will always be edge, and the
|
||||
* actual level or edge trigger will be setup in the IO-APIC
|
||||
* RTE. This will help simplify level triggered irq migration.
|
||||
* For more details, see the comments above explainig IO-APIC
|
||||
* irq migration in the presence of interrupt-remapping.
|
||||
*/
|
||||
irte.trigger_mode = 0;
|
||||
irte.dlvry_mode = apic->irq_delivery_mode;
|
||||
irte.vector = vector;
|
||||
irte.dest_id = IRTE_DEST(destination);
|
||||
@@ -1515,18 +1536,21 @@ int setup_ioapic_entry(int apic_id, int irq,
|
||||
ir_entry->zero = 0;
|
||||
ir_entry->format = 1;
|
||||
ir_entry->index = (index & 0x7fff);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* IO-APIC RTE will be configured with virtual vector.
|
||||
* irq handler will do the explicit EOI to the io-apic.
|
||||
*/
|
||||
ir_entry->vector = pin;
|
||||
} else {
|
||||
entry->delivery_mode = apic->irq_delivery_mode;
|
||||
entry->dest_mode = apic->irq_dest_mode;
|
||||
entry->dest = destination;
|
||||
entry->vector = vector;
|
||||
}
|
||||
|
||||
entry->mask = 0; /* enable IRQ */
|
||||
entry->trigger = trigger;
|
||||
entry->polarity = polarity;
|
||||
entry->vector = vector;
|
||||
|
||||
/* Mask level triggered irqs.
|
||||
* Use IRQ_DELAYED_DISABLE for edge triggered irqs.
|
||||
@@ -1561,7 +1585,7 @@ static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq
|
||||
|
||||
|
||||
if (setup_ioapic_entry(mp_ioapics[apic_id].apicid, irq, &entry,
|
||||
dest, trigger, polarity, cfg->vector)) {
|
||||
dest, trigger, polarity, cfg->vector, pin)) {
|
||||
printk("Failed to setup ioapic entry for ioapic %d, pin %d\n",
|
||||
mp_ioapics[apic_id].apicid, pin);
|
||||
__clear_irq_vector(irq, cfg);
|
||||
@@ -1642,10 +1666,8 @@ static void __init setup_timer_IRQ0_pin(unsigned int apic_id, unsigned int pin,
|
||||
{
|
||||
struct IO_APIC_route_entry entry;
|
||||
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
if (intr_remapping_enabled)
|
||||
return;
|
||||
#endif
|
||||
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
|
||||
@@ -2040,8 +2062,13 @@ void disable_IO_APIC(void)
|
||||
* If the i8259 is routed through an IOAPIC
|
||||
* Put that IOAPIC in virtual wire mode
|
||||
* so legacy interrupts can be delivered.
|
||||
*
|
||||
* With interrupt-remapping, for now we will use virtual wire A mode,
|
||||
* as virtual wire B is little complex (need to configure both
|
||||
* IOAPIC RTE aswell as interrupt-remapping table entry).
|
||||
* As this gets called during crash dump, keep this simple for now.
|
||||
*/
|
||||
if (ioapic_i8259.pin != -1) {
|
||||
if (ioapic_i8259.pin != -1 && !intr_remapping_enabled) {
|
||||
struct IO_APIC_route_entry entry;
|
||||
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
@@ -2061,7 +2088,10 @@ void disable_IO_APIC(void)
|
||||
ioapic_write_entry(ioapic_i8259.apic, ioapic_i8259.pin, entry);
|
||||
}
|
||||
|
||||
disconnect_bsp_APIC(ioapic_i8259.pin != -1);
|
||||
/*
|
||||
* Use virtual wire A mode when interrupt remapping is enabled.
|
||||
*/
|
||||
disconnect_bsp_APIC(!intr_remapping_enabled && ioapic_i8259.pin != -1);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
@@ -2303,37 +2333,24 @@ static int ioapic_retrigger_irq(unsigned int irq)
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
static void ir_irq_migration(struct work_struct *work);
|
||||
|
||||
static DECLARE_DELAYED_WORK(ir_migration_work, ir_irq_migration);
|
||||
|
||||
/*
|
||||
* Migrate the IO-APIC irq in the presence of intr-remapping.
|
||||
*
|
||||
* For edge triggered, irq migration is a simple atomic update(of vector
|
||||
* and cpu destination) of IRTE and flush the hardware cache.
|
||||
* For both level and edge triggered, irq migration is a simple atomic
|
||||
* update(of vector and cpu destination) of IRTE and flush the hardware cache.
|
||||
*
|
||||
* For level triggered, we need to modify the io-apic RTE aswell with the update
|
||||
* vector information, along with modifying IRTE with vector and destination.
|
||||
* So irq migration for level triggered is little bit more complex compared to
|
||||
* edge triggered migration. But the good news is, we use the same algorithm
|
||||
* for level triggered migration as we have today, only difference being,
|
||||
* we now initiate the irq migration from process context instead of the
|
||||
* interrupt context.
|
||||
*
|
||||
* In future, when we do a directed EOI (combined with cpu EOI broadcast
|
||||
* suppression) to the IO-APIC, level triggered irq migration will also be
|
||||
* as simple as edge triggered migration and we can do the irq migration
|
||||
* with a simple atomic update to IO-APIC RTE.
|
||||
* For level triggered, we eliminate the io-apic RTE modification (with the
|
||||
* updated vector information), by using a virtual vector (io-apic pin number).
|
||||
* Real vector that is used for interrupting cpu will be coming from
|
||||
* the interrupt-remapping table entry.
|
||||
*/
|
||||
static void
|
||||
migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
|
||||
{
|
||||
struct irq_cfg *cfg;
|
||||
struct irte irte;
|
||||
int modify_ioapic_rte;
|
||||
unsigned int dest;
|
||||
unsigned long flags;
|
||||
unsigned int irq;
|
||||
|
||||
if (!cpumask_intersects(mask, cpu_online_mask))
|
||||
@@ -2351,13 +2368,6 @@ migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
|
||||
|
||||
dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
|
||||
|
||||
modify_ioapic_rte = desc->status & IRQ_LEVEL;
|
||||
if (modify_ioapic_rte) {
|
||||
spin_lock_irqsave(&ioapic_lock, flags);
|
||||
__target_IO_APIC_irq(irq, dest, cfg);
|
||||
spin_unlock_irqrestore(&ioapic_lock, flags);
|
||||
}
|
||||
|
||||
irte.vector = cfg->vector;
|
||||
irte.dest_id = IRTE_DEST(dest);
|
||||
|
||||
@@ -2372,73 +2382,12 @@ migrate_ioapic_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
|
||||
cpumask_copy(desc->affinity, mask);
|
||||
}
|
||||
|
||||
static int migrate_irq_remapped_level_desc(struct irq_desc *desc)
|
||||
{
|
||||
int ret = -1;
|
||||
struct irq_cfg *cfg = desc->chip_data;
|
||||
|
||||
mask_IO_APIC_irq_desc(desc);
|
||||
|
||||
if (io_apic_level_ack_pending(cfg)) {
|
||||
/*
|
||||
* Interrupt in progress. Migrating irq now will change the
|
||||
* vector information in the IO-APIC RTE and that will confuse
|
||||
* the EOI broadcast performed by cpu.
|
||||
* So, delay the irq migration to the next instance.
|
||||
*/
|
||||
schedule_delayed_work(&ir_migration_work, 1);
|
||||
goto unmask;
|
||||
}
|
||||
|
||||
/* everthing is clear. we have right of way */
|
||||
migrate_ioapic_irq_desc(desc, desc->pending_mask);
|
||||
|
||||
ret = 0;
|
||||
desc->status &= ~IRQ_MOVE_PENDING;
|
||||
cpumask_clear(desc->pending_mask);
|
||||
|
||||
unmask:
|
||||
unmask_IO_APIC_irq_desc(desc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ir_irq_migration(struct work_struct *work)
|
||||
{
|
||||
unsigned int irq;
|
||||
struct irq_desc *desc;
|
||||
|
||||
for_each_irq_desc(irq, desc) {
|
||||
if (desc->status & IRQ_MOVE_PENDING) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&desc->lock, flags);
|
||||
if (!desc->chip->set_affinity ||
|
||||
!(desc->status & IRQ_MOVE_PENDING)) {
|
||||
desc->status &= ~IRQ_MOVE_PENDING;
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
desc->chip->set_affinity(irq, desc->pending_mask);
|
||||
spin_unlock_irqrestore(&desc->lock, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Migrates the IRQ destination in the process context.
|
||||
*/
|
||||
static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
|
||||
const struct cpumask *mask)
|
||||
{
|
||||
if (desc->status & IRQ_LEVEL) {
|
||||
desc->status |= IRQ_MOVE_PENDING;
|
||||
cpumask_copy(desc->pending_mask, mask);
|
||||
migrate_irq_remapped_level_desc(desc);
|
||||
return;
|
||||
}
|
||||
|
||||
migrate_ioapic_irq_desc(desc, mask);
|
||||
}
|
||||
static void set_ir_ioapic_affinity_irq(unsigned int irq,
|
||||
@@ -2448,6 +2397,11 @@ static void set_ir_ioapic_affinity_irq(unsigned int irq,
|
||||
|
||||
set_ir_ioapic_affinity_irq_desc(desc, mask);
|
||||
}
|
||||
#else
|
||||
static inline void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
|
||||
const struct cpumask *mask)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
asmlinkage void smp_irq_move_cleanup_interrupt(void)
|
||||
@@ -2461,6 +2415,7 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
|
||||
me = smp_processor_id();
|
||||
for (vector = FIRST_EXTERNAL_VECTOR; vector < NR_VECTORS; vector++) {
|
||||
unsigned int irq;
|
||||
unsigned int irr;
|
||||
struct irq_desc *desc;
|
||||
struct irq_cfg *cfg;
|
||||
irq = __get_cpu_var(vector_irq)[vector];
|
||||
@@ -2480,6 +2435,18 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
|
||||
if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
|
||||
goto unlock;
|
||||
|
||||
irr = apic_read(APIC_IRR + (vector / 32 * 0x10));
|
||||
/*
|
||||
* Check if the vector that needs to be cleanedup is
|
||||
* registered at the cpu's IRR. If so, then this is not
|
||||
* the best time to clean it up. Lets clean it up in the
|
||||
* next attempt by sending another IRQ_MOVE_CLEANUP_VECTOR
|
||||
* to myself.
|
||||
*/
|
||||
if (irr & (1 << (vector % 32))) {
|
||||
apic->send_IPI_self(IRQ_MOVE_CLEANUP_VECTOR);
|
||||
goto unlock;
|
||||
}
|
||||
__get_cpu_var(vector_irq)[vector] = -1;
|
||||
cfg->move_cleanup_count--;
|
||||
unlock:
|
||||
@@ -2529,9 +2496,44 @@ static inline void irq_complete_move(struct irq_desc **descp) {}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
static void __eoi_ioapic_irq(unsigned int irq, struct irq_cfg *cfg)
|
||||
{
|
||||
int apic, pin;
|
||||
struct irq_pin_list *entry;
|
||||
|
||||
entry = cfg->irq_2_pin;
|
||||
for (;;) {
|
||||
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
apic = entry->apic;
|
||||
pin = entry->pin;
|
||||
io_apic_eoi(apic, pin);
|
||||
entry = entry->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eoi_ioapic_irq(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_cfg *cfg;
|
||||
unsigned long flags;
|
||||
unsigned int irq;
|
||||
|
||||
irq = desc->irq;
|
||||
cfg = desc->chip_data;
|
||||
|
||||
spin_lock_irqsave(&ioapic_lock, flags);
|
||||
__eoi_ioapic_irq(irq, cfg);
|
||||
spin_unlock_irqrestore(&ioapic_lock, flags);
|
||||
}
|
||||
|
||||
static void ack_x2apic_level(unsigned int irq)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
ack_x2APIC_irq();
|
||||
eoi_ioapic_irq(desc);
|
||||
}
|
||||
|
||||
static void ack_x2apic_edge(unsigned int irq)
|
||||
@@ -2662,20 +2664,20 @@ static struct irq_chip ioapic_chip __read_mostly = {
|
||||
.retrigger = ioapic_retrigger_irq,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
static struct irq_chip ir_ioapic_chip __read_mostly = {
|
||||
.name = "IR-IO-APIC",
|
||||
.startup = startup_ioapic_irq,
|
||||
.mask = mask_IO_APIC_irq,
|
||||
.unmask = unmask_IO_APIC_irq,
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
.ack = ack_x2apic_edge,
|
||||
.eoi = ack_x2apic_level,
|
||||
#ifdef CONFIG_SMP
|
||||
.set_affinity = set_ir_ioapic_affinity_irq,
|
||||
#endif
|
||||
#endif
|
||||
.retrigger = ioapic_retrigger_irq,
|
||||
};
|
||||
#endif
|
||||
|
||||
static inline void init_IO_APIC_traps(void)
|
||||
{
|
||||
@@ -2901,10 +2903,8 @@ static inline void __init check_timer(void)
|
||||
* 8259A.
|
||||
*/
|
||||
if (pin1 == -1) {
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
if (intr_remapping_enabled)
|
||||
panic("BIOS bug: timer not connected to IO-APIC");
|
||||
#endif
|
||||
pin1 = pin2;
|
||||
apic1 = apic2;
|
||||
no_pin1 = 1;
|
||||
@@ -2940,10 +2940,8 @@ static inline void __init check_timer(void)
|
||||
clear_IO_APIC_pin(0, pin1);
|
||||
goto out;
|
||||
}
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
if (intr_remapping_enabled)
|
||||
panic("timer doesn't work through Interrupt-remapped IO-APIC");
|
||||
#endif
|
||||
local_irq_disable();
|
||||
clear_IO_APIC_pin(apic1, pin1);
|
||||
if (!no_pin1)
|
||||
@@ -3237,9 +3235,7 @@ void destroy_irq(unsigned int irq)
|
||||
if (desc)
|
||||
desc->chip_data = cfg;
|
||||
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
free_irte(irq);
|
||||
#endif
|
||||
spin_lock_irqsave(&vector_lock, flags);
|
||||
__clear_irq_vector(irq, cfg);
|
||||
spin_unlock_irqrestore(&vector_lock, flags);
|
||||
@@ -3265,7 +3261,6 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms
|
||||
|
||||
dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
|
||||
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
if (irq_remapped(irq)) {
|
||||
struct irte irte;
|
||||
int ir_index;
|
||||
@@ -3291,10 +3286,13 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms
|
||||
MSI_ADDR_IR_SHV |
|
||||
MSI_ADDR_IR_INDEX1(ir_index) |
|
||||
MSI_ADDR_IR_INDEX2(ir_index);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
msg->address_hi = MSI_ADDR_BASE_HI;
|
||||
} else {
|
||||
if (x2apic_enabled())
|
||||
msg->address_hi = MSI_ADDR_BASE_HI |
|
||||
MSI_ADDR_EXT_DEST_ID(dest);
|
||||
else
|
||||
msg->address_hi = MSI_ADDR_BASE_HI;
|
||||
|
||||
msg->address_lo =
|
||||
MSI_ADDR_BASE_LO |
|
||||
((apic->irq_dest_mode == 0) ?
|
||||
@@ -3394,14 +3392,15 @@ static struct irq_chip msi_chip = {
|
||||
.retrigger = ioapic_retrigger_irq,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
static struct irq_chip msi_ir_chip = {
|
||||
.name = "IR-PCI-MSI",
|
||||
.unmask = unmask_msi_irq,
|
||||
.mask = mask_msi_irq,
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
.ack = ack_x2apic_edge,
|
||||
#ifdef CONFIG_SMP
|
||||
.set_affinity = ir_set_msi_irq_affinity,
|
||||
#endif
|
||||
#endif
|
||||
.retrigger = ioapic_retrigger_irq,
|
||||
};
|
||||
@@ -3432,7 +3431,6 @@ static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
|
||||
}
|
||||
return index;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
|
||||
{
|
||||
@@ -3446,7 +3444,6 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
|
||||
set_irq_msi(irq, msidesc);
|
||||
write_msi_msg(irq, &msg);
|
||||
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
if (irq_remapped(irq)) {
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
/*
|
||||
@@ -3455,7 +3452,6 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
|
||||
desc->status |= IRQ_MOVE_PCNTXT;
|
||||
set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge");
|
||||
} else
|
||||
#endif
|
||||
set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
|
||||
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "irq %d for MSI/MSI-X\n", irq);
|
||||
@@ -3469,11 +3465,12 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
||||
int ret, sub_handle;
|
||||
struct msi_desc *msidesc;
|
||||
unsigned int irq_want;
|
||||
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
struct intel_iommu *iommu = 0;
|
||||
struct intel_iommu *iommu = NULL;
|
||||
int index = 0;
|
||||
#endif
|
||||
|
||||
/* x86 doesn't support multiple MSI yet */
|
||||
if (type == PCI_CAP_ID_MSI && nvec > 1)
|
||||
return 1;
|
||||
|
||||
irq_want = nr_irqs_gsi;
|
||||
sub_handle = 0;
|
||||
@@ -3482,7 +3479,6 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
||||
if (irq == 0)
|
||||
return -1;
|
||||
irq_want = irq + 1;
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
if (!intr_remapping_enabled)
|
||||
goto no_ir;
|
||||
|
||||
@@ -3510,7 +3506,6 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
||||
set_irte_irq(irq, iommu, index, sub_handle);
|
||||
}
|
||||
no_ir:
|
||||
#endif
|
||||
ret = setup_msi_irq(dev, msidesc, irq);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
@@ -3528,7 +3523,7 @@ void arch_teardown_msi_irq(unsigned int irq)
|
||||
destroy_irq(irq);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DMAR
|
||||
#if defined (CONFIG_DMAR) || defined (CONFIG_INTR_REMAP)
|
||||
#ifdef CONFIG_SMP
|
||||
static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
|
||||
{
|
||||
@@ -3609,7 +3604,7 @@ static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
|
||||
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
struct irq_chip hpet_msi_type = {
|
||||
static struct irq_chip hpet_msi_type = {
|
||||
.name = "HPET_MSI",
|
||||
.unmask = hpet_msi_unmask,
|
||||
.mask = hpet_msi_mask,
|
||||
@@ -4045,11 +4040,9 @@ void __init setup_ioapic_dest(void)
|
||||
else
|
||||
mask = apic->target_cpus();
|
||||
|
||||
#ifdef CONFIG_INTR_REMAP
|
||||
if (intr_remapping_enabled)
|
||||
set_ir_ioapic_affinity_irq_desc(desc, mask);
|
||||
else
|
||||
#endif
|
||||
set_ioapic_affinity_irq_desc(desc, mask);
|
||||
}
|
||||
|
||||
@@ -4142,9 +4135,12 @@ static int __init ioapic_insert_resources(void)
|
||||
struct resource *r = ioapic_resources;
|
||||
|
||||
if (!r) {
|
||||
printk(KERN_ERR
|
||||
"IO APIC resources could be not be allocated.\n");
|
||||
return -1;
|
||||
if (nr_ioapics > 0) {
|
||||
printk(KERN_ERR
|
||||
"IO APIC resources couldn't be allocated.\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_ioapics; i++) {
|
||||
|
@@ -39,7 +39,7 @@
|
||||
int unknown_nmi_panic;
|
||||
int nmi_watchdog_enabled;
|
||||
|
||||
static cpumask_t backtrace_mask = CPU_MASK_NONE;
|
||||
static cpumask_var_t backtrace_mask;
|
||||
|
||||
/* nmi_active:
|
||||
* >0: the lapic NMI watchdog is active, but can be disabled
|
||||
@@ -138,6 +138,7 @@ int __init check_nmi_watchdog(void)
|
||||
if (!prev_nmi_count)
|
||||
goto error;
|
||||
|
||||
alloc_cpumask_var(&backtrace_mask, GFP_KERNEL);
|
||||
printk(KERN_INFO "Testing NMI watchdog ... ");
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
@@ -413,14 +414,14 @@ nmi_watchdog_tick(struct pt_regs *regs, unsigned reason)
|
||||
touched = 1;
|
||||
}
|
||||
|
||||
if (cpu_isset(cpu, backtrace_mask)) {
|
||||
if (cpumask_test_cpu(cpu, backtrace_mask)) {
|
||||
static DEFINE_SPINLOCK(lock); /* Serialise the printks */
|
||||
|
||||
spin_lock(&lock);
|
||||
printk(KERN_WARNING "NMI backtrace for cpu %d\n", cpu);
|
||||
dump_stack();
|
||||
spin_unlock(&lock);
|
||||
cpu_clear(cpu, backtrace_mask);
|
||||
cpumask_clear_cpu(cpu, backtrace_mask);
|
||||
}
|
||||
|
||||
/* Could check oops_in_progress here too, but it's safer not to */
|
||||
@@ -554,10 +555,10 @@ void __trigger_all_cpu_backtrace(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
backtrace_mask = cpu_online_map;
|
||||
cpumask_copy(backtrace_mask, cpu_online_mask);
|
||||
/* Wait for up to 10 seconds for all CPUs to do the backtrace */
|
||||
for (i = 0; i < 10 * 1000; i++) {
|
||||
if (cpus_empty(backtrace_mask))
|
||||
if (cpumask_empty(backtrace_mask))
|
||||
break;
|
||||
mdelay(1);
|
||||
}
|
||||
|
@@ -69,7 +69,7 @@ struct mpc_trans {
|
||||
/* x86_quirks member */
|
||||
static int mpc_record;
|
||||
|
||||
static __cpuinitdata struct mpc_trans *translation_table[MAX_MPC_ENTRY];
|
||||
static struct mpc_trans *translation_table[MAX_MPC_ENTRY];
|
||||
|
||||
int mp_bus_id_to_node[MAX_MP_BUSSES];
|
||||
int mp_bus_id_to_local[MAX_MP_BUSSES];
|
||||
@@ -256,13 +256,6 @@ static int __init numaq_setup_ioapic_ids(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __init numaq_update_apic(void)
|
||||
{
|
||||
apic->wakeup_cpu = wakeup_secondary_cpu_via_nmi;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct x86_quirks numaq_x86_quirks __initdata = {
|
||||
.arch_pre_time_init = numaq_pre_time_init,
|
||||
.arch_time_init = NULL,
|
||||
@@ -278,7 +271,6 @@ static struct x86_quirks numaq_x86_quirks __initdata = {
|
||||
.mpc_oem_pci_bus = mpc_oem_pci_bus,
|
||||
.smp_read_mpc_oem = smp_read_mpc_oem,
|
||||
.setup_ioapic_ids = numaq_setup_ioapic_ids,
|
||||
.update_apic = numaq_update_apic,
|
||||
};
|
||||
|
||||
static __init void early_check_numaq(void)
|
||||
@@ -342,9 +334,9 @@ static inline void numaq_smp_callin_clear_local_apic(void)
|
||||
clear_local_APIC();
|
||||
}
|
||||
|
||||
static inline const cpumask_t *numaq_target_cpus(void)
|
||||
static inline const struct cpumask *numaq_target_cpus(void)
|
||||
{
|
||||
return &CPU_MASK_ALL;
|
||||
return cpu_all_mask;
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
@@ -435,7 +427,7 @@ static inline int numaq_check_phys_apicid_present(int boot_cpu_physical_apicid)
|
||||
* We use physical apicids here, not logical, so just return the default
|
||||
* physical broadcast to stop people from breaking us
|
||||
*/
|
||||
static inline unsigned int numaq_cpu_mask_to_apicid(const cpumask_t *cpumask)
|
||||
static unsigned int numaq_cpu_mask_to_apicid(const struct cpumask *cpumask)
|
||||
{
|
||||
return 0x0F;
|
||||
}
|
||||
@@ -470,7 +462,7 @@ static int probe_numaq(void)
|
||||
return found_numaq;
|
||||
}
|
||||
|
||||
static void numaq_vector_allocation_domain(int cpu, cpumask_t *retmask)
|
||||
static void numaq_vector_allocation_domain(int cpu, struct cpumask *retmask)
|
||||
{
|
||||
/* Careful. Some cpus do not strictly honor the set of cpus
|
||||
* specified in the interrupt destination when using lowest
|
||||
@@ -480,7 +472,8 @@ static void numaq_vector_allocation_domain(int cpu, cpumask_t *retmask)
|
||||
* deliver interrupts to the wrong hyperthread when only one
|
||||
* hyperthread was specified in the interrupt desitination.
|
||||
*/
|
||||
*retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } };
|
||||
cpumask_clear(retmask);
|
||||
cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
|
||||
}
|
||||
|
||||
static void numaq_setup_portio_remap(void)
|
||||
@@ -546,7 +539,7 @@ struct apic apic_numaq = {
|
||||
.send_IPI_all = numaq_send_IPI_all,
|
||||
.send_IPI_self = default_send_IPI_self,
|
||||
|
||||
.wakeup_cpu = NULL,
|
||||
.wakeup_secondary_cpu = wakeup_secondary_cpu_via_nmi,
|
||||
.trampoline_phys_low = NUMAQ_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = NUMAQ_TRAMPOLINE_PHYS_HIGH,
|
||||
|
||||
|
@@ -83,7 +83,8 @@ static void default_vector_allocation_domain(int cpu, struct cpumask *retmask)
|
||||
* deliver interrupts to the wrong hyperthread when only one
|
||||
* hyperthread was specified in the interrupt desitination.
|
||||
*/
|
||||
*retmask = (cpumask_t) { { [0] = APIC_ALL_CPUS } };
|
||||
cpumask_clear(retmask);
|
||||
cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
|
||||
}
|
||||
|
||||
/* should be called last. */
|
||||
@@ -138,7 +139,6 @@ struct apic apic_default = {
|
||||
.send_IPI_all = default_send_IPI_all,
|
||||
.send_IPI_self = default_send_IPI_self,
|
||||
|
||||
.wakeup_cpu = NULL,
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
|
||||
@@ -159,6 +159,7 @@ extern struct apic apic_numaq;
|
||||
extern struct apic apic_summit;
|
||||
extern struct apic apic_bigsmp;
|
||||
extern struct apic apic_es7000;
|
||||
extern struct apic apic_es7000_cluster;
|
||||
extern struct apic apic_default;
|
||||
|
||||
struct apic *apic = &apic_default;
|
||||
@@ -176,6 +177,7 @@ static struct apic *apic_probe[] __initdata = {
|
||||
#endif
|
||||
#ifdef CONFIG_X86_ES7000
|
||||
&apic_es7000,
|
||||
&apic_es7000_cluster,
|
||||
#endif
|
||||
&apic_default, /* must be last */
|
||||
NULL,
|
||||
@@ -197,9 +199,6 @@ static int __init parse_apic(char *arg)
|
||||
}
|
||||
}
|
||||
|
||||
if (x86_quirks->update_apic)
|
||||
x86_quirks->update_apic();
|
||||
|
||||
/* Parsed again by __setup for debug/verbose */
|
||||
return 0;
|
||||
}
|
||||
@@ -218,8 +217,6 @@ void __init generic_bigsmp_probe(void)
|
||||
if (!cmdline_apic && apic == &apic_default) {
|
||||
if (apic_bigsmp.probe()) {
|
||||
apic = &apic_bigsmp;
|
||||
if (x86_quirks->update_apic)
|
||||
x86_quirks->update_apic();
|
||||
printk(KERN_INFO "Overriding APIC driver with %s\n",
|
||||
apic->name);
|
||||
}
|
||||
@@ -240,9 +237,6 @@ void __init generic_apic_probe(void)
|
||||
/* Not visible without early console */
|
||||
if (!apic_probe[i])
|
||||
panic("Didn't find an APIC driver");
|
||||
|
||||
if (x86_quirks->update_apic)
|
||||
x86_quirks->update_apic();
|
||||
}
|
||||
printk(KERN_INFO "Using APIC driver %s\n", apic->name);
|
||||
}
|
||||
@@ -262,8 +256,6 @@ generic_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
|
||||
|
||||
if (!cmdline_apic) {
|
||||
apic = apic_probe[i];
|
||||
if (x86_quirks->update_apic)
|
||||
x86_quirks->update_apic();
|
||||
printk(KERN_INFO "Switched to APIC driver `%s'.\n",
|
||||
apic->name);
|
||||
}
|
||||
@@ -284,8 +276,6 @@ int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
|
||||
if (!cmdline_apic) {
|
||||
apic = apic_probe[i];
|
||||
if (x86_quirks->update_apic)
|
||||
x86_quirks->update_apic();
|
||||
printk(KERN_INFO "Switched to APIC driver `%s'.\n",
|
||||
apic->name);
|
||||
}
|
||||
|
@@ -69,8 +69,12 @@ void __init default_setup_apic_routing(void)
|
||||
printk(KERN_INFO "Setting APIC routing to %s\n", apic->name);
|
||||
}
|
||||
|
||||
if (x86_quirks->update_apic)
|
||||
x86_quirks->update_apic();
|
||||
/*
|
||||
* Now that apic routing model is selected, configure the
|
||||
* fault handling for intr remapping.
|
||||
*/
|
||||
if (intr_remapping_enabled)
|
||||
enable_drhd_fault_handling();
|
||||
}
|
||||
|
||||
/* Same for both flat and physical. */
|
||||
|
@@ -53,23 +53,19 @@ static unsigned summit_get_apic_id(unsigned long x)
|
||||
return (x >> 24) & 0xFF;
|
||||
}
|
||||
|
||||
static inline void summit_send_IPI_mask(const cpumask_t *mask, int vector)
|
||||
static inline void summit_send_IPI_mask(const struct cpumask *mask, int vector)
|
||||
{
|
||||
default_send_IPI_mask_sequence_logical(mask, vector);
|
||||
}
|
||||
|
||||
static void summit_send_IPI_allbutself(int vector)
|
||||
{
|
||||
cpumask_t mask = cpu_online_map;
|
||||
cpu_clear(smp_processor_id(), mask);
|
||||
|
||||
if (!cpus_empty(mask))
|
||||
summit_send_IPI_mask(&mask, vector);
|
||||
default_send_IPI_mask_allbutself_logical(cpu_online_mask, vector);
|
||||
}
|
||||
|
||||
static void summit_send_IPI_all(int vector)
|
||||
{
|
||||
summit_send_IPI_mask(&cpu_online_map, vector);
|
||||
summit_send_IPI_mask(cpu_online_mask, vector);
|
||||
}
|
||||
|
||||
#include <asm/tsc.h>
|
||||
@@ -77,9 +73,9 @@ static void summit_send_IPI_all(int vector)
|
||||
extern int use_cyclone;
|
||||
|
||||
#ifdef CONFIG_X86_SUMMIT_NUMA
|
||||
extern void setup_summit(void);
|
||||
static void setup_summit(void);
|
||||
#else
|
||||
#define setup_summit() {}
|
||||
static inline void setup_summit(void) {}
|
||||
#endif
|
||||
|
||||
static int summit_mps_oem_check(struct mpc_table *mpc, char *oem,
|
||||
@@ -186,13 +182,13 @@ static inline int is_WPEG(struct rio_detail *rio){
|
||||
|
||||
#define SUMMIT_APIC_DFR_VALUE (APIC_DFR_CLUSTER)
|
||||
|
||||
static const cpumask_t *summit_target_cpus(void)
|
||||
static const struct cpumask *summit_target_cpus(void)
|
||||
{
|
||||
/* CPU_MASK_ALL (0xff) has undefined behaviour with
|
||||
* dest_LowestPrio mode logical clustered apic interrupt routing
|
||||
* Just start on cpu 0. IRQ balancing will spread load
|
||||
*/
|
||||
return &cpumask_of_cpu(0);
|
||||
return cpumask_of(0);
|
||||
}
|
||||
|
||||
static unsigned long summit_check_apicid_used(physid_mask_t bitmap, int apicid)
|
||||
@@ -289,35 +285,23 @@ static int summit_check_phys_apicid_present(int boot_cpu_physical_apicid)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask)
|
||||
static unsigned int summit_cpu_mask_to_apicid(const struct cpumask *cpumask)
|
||||
{
|
||||
int cpus_found = 0;
|
||||
int num_bits_set;
|
||||
int apicid;
|
||||
int cpu;
|
||||
unsigned int round = 0;
|
||||
int cpu, apicid = 0;
|
||||
|
||||
num_bits_set = cpus_weight(*cpumask);
|
||||
if (num_bits_set >= nr_cpu_ids)
|
||||
return BAD_APICID;
|
||||
/*
|
||||
* The cpus in the mask must all be on the apic cluster.
|
||||
*/
|
||||
cpu = first_cpu(*cpumask);
|
||||
apicid = summit_cpu_to_logical_apicid(cpu);
|
||||
for_each_cpu(cpu, cpumask) {
|
||||
int new_apicid = summit_cpu_to_logical_apicid(cpu);
|
||||
|
||||
while (cpus_found < num_bits_set) {
|
||||
if (cpu_isset(cpu, *cpumask)) {
|
||||
int new_apicid = summit_cpu_to_logical_apicid(cpu);
|
||||
|
||||
if (APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
|
||||
printk("%s: Not a valid mask!\n", __func__);
|
||||
|
||||
return BAD_APICID;
|
||||
}
|
||||
apicid = apicid | new_apicid;
|
||||
cpus_found++;
|
||||
if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
|
||||
printk("%s: Not a valid mask!\n", __func__);
|
||||
return BAD_APICID;
|
||||
}
|
||||
cpu++;
|
||||
apicid |= new_apicid;
|
||||
round++;
|
||||
}
|
||||
return apicid;
|
||||
}
|
||||
@@ -358,7 +342,7 @@ static int probe_summit(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void summit_vector_allocation_domain(int cpu, cpumask_t *retmask)
|
||||
static void summit_vector_allocation_domain(int cpu, struct cpumask *retmask)
|
||||
{
|
||||
/* Careful. Some cpus do not strictly honor the set of cpus
|
||||
* specified in the interrupt destination when using lowest
|
||||
@@ -368,19 +352,20 @@ static void summit_vector_allocation_domain(int cpu, cpumask_t *retmask)
|
||||
* deliver interrupts to the wrong hyperthread when only one
|
||||
* hyperthread was specified in the interrupt desitination.
|
||||
*/
|
||||
*retmask = (cpumask_t){ { [0] = APIC_ALL_CPUS, } };
|
||||
cpumask_clear(retmask);
|
||||
cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_SUMMIT_NUMA
|
||||
static struct rio_table_hdr *rio_table_hdr __initdata;
|
||||
static struct scal_detail *scal_devs[MAX_NUMNODES] __initdata;
|
||||
static struct rio_detail *rio_devs[MAX_NUMNODES*4] __initdata;
|
||||
static struct rio_table_hdr *rio_table_hdr;
|
||||
static struct scal_detail *scal_devs[MAX_NUMNODES];
|
||||
static struct rio_detail *rio_devs[MAX_NUMNODES*4];
|
||||
|
||||
#ifndef CONFIG_X86_NUMAQ
|
||||
static int mp_bus_id_to_node[MAX_MP_BUSSES] __initdata;
|
||||
static int mp_bus_id_to_node[MAX_MP_BUSSES];
|
||||
#endif
|
||||
|
||||
static int __init setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
|
||||
static int setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
|
||||
{
|
||||
int twister = 0, node = 0;
|
||||
int i, bus, num_buses;
|
||||
@@ -442,7 +427,7 @@ static int __init setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
|
||||
return bus;
|
||||
}
|
||||
|
||||
static int __init build_detail_arrays(void)
|
||||
static int build_detail_arrays(void)
|
||||
{
|
||||
unsigned long ptr;
|
||||
int i, scal_detail_size, rio_detail_size;
|
||||
@@ -476,7 +461,7 @@ static int __init build_detail_arrays(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void __init setup_summit(void)
|
||||
void setup_summit(void)
|
||||
{
|
||||
unsigned long ptr;
|
||||
unsigned short offset;
|
||||
@@ -574,7 +559,6 @@ struct apic apic_summit = {
|
||||
.send_IPI_all = summit_send_IPI_all,
|
||||
.send_IPI_self = default_send_IPI_self,
|
||||
|
||||
.wakeup_cpu = NULL,
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
|
||||
|
@@ -57,6 +57,8 @@ static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector)
|
||||
unsigned long query_cpu;
|
||||
unsigned long flags;
|
||||
|
||||
x2apic_wrmsr_fence();
|
||||
|
||||
local_irq_save(flags);
|
||||
for_each_cpu(query_cpu, mask) {
|
||||
__x2apic_send_IPI_dest(
|
||||
@@ -73,6 +75,8 @@ static void
|
||||
unsigned long query_cpu;
|
||||
unsigned long flags;
|
||||
|
||||
x2apic_wrmsr_fence();
|
||||
|
||||
local_irq_save(flags);
|
||||
for_each_cpu(query_cpu, mask) {
|
||||
if (query_cpu == this_cpu)
|
||||
@@ -90,6 +94,8 @@ static void x2apic_send_IPI_allbutself(int vector)
|
||||
unsigned long query_cpu;
|
||||
unsigned long flags;
|
||||
|
||||
x2apic_wrmsr_fence();
|
||||
|
||||
local_irq_save(flags);
|
||||
for_each_online_cpu(query_cpu) {
|
||||
if (query_cpu == this_cpu)
|
||||
@@ -224,7 +230,6 @@ struct apic apic_x2apic_cluster = {
|
||||
.send_IPI_all = x2apic_send_IPI_all,
|
||||
.send_IPI_self = x2apic_send_IPI_self,
|
||||
|
||||
.wakeup_cpu = NULL,
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
.wait_for_init_deassert = NULL,
|
||||
|
@@ -58,6 +58,8 @@ static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector)
|
||||
unsigned long query_cpu;
|
||||
unsigned long flags;
|
||||
|
||||
x2apic_wrmsr_fence();
|
||||
|
||||
local_irq_save(flags);
|
||||
for_each_cpu(query_cpu, mask) {
|
||||
__x2apic_send_IPI_dest(per_cpu(x86_cpu_to_apicid, query_cpu),
|
||||
@@ -73,6 +75,8 @@ static void
|
||||
unsigned long query_cpu;
|
||||
unsigned long flags;
|
||||
|
||||
x2apic_wrmsr_fence();
|
||||
|
||||
local_irq_save(flags);
|
||||
for_each_cpu(query_cpu, mask) {
|
||||
if (query_cpu != this_cpu)
|
||||
@@ -89,6 +93,8 @@ static void x2apic_send_IPI_allbutself(int vector)
|
||||
unsigned long query_cpu;
|
||||
unsigned long flags;
|
||||
|
||||
x2apic_wrmsr_fence();
|
||||
|
||||
local_irq_save(flags);
|
||||
for_each_online_cpu(query_cpu) {
|
||||
if (query_cpu == this_cpu)
|
||||
@@ -213,7 +219,6 @@ struct apic apic_x2apic_phys = {
|
||||
.send_IPI_all = x2apic_send_IPI_all,
|
||||
.send_IPI_self = x2apic_send_IPI_self,
|
||||
|
||||
.wakeup_cpu = NULL,
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
.wait_for_init_deassert = NULL,
|
||||
|
@@ -7,28 +7,28 @@
|
||||
*
|
||||
* Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/threads.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/threads.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/ipi.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/uv/uv.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <asm/uv/uv_mmrs.h>
|
||||
#include <asm/uv/uv_hub.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/uv/bios.h>
|
||||
#include <asm/uv/uv.h>
|
||||
#include <asm/apic.h>
|
||||
#include <asm/ipi.h>
|
||||
#include <asm/smp.h>
|
||||
|
||||
DEFINE_PER_CPU(int, x2apic_extra_bits);
|
||||
|
||||
@@ -91,40 +91,39 @@ static void uv_vector_allocation_domain(int cpu, struct cpumask *retmask)
|
||||
cpumask_set_cpu(cpu, retmask);
|
||||
}
|
||||
|
||||
int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip)
|
||||
static int uv_wakeup_secondary(int phys_apicid, unsigned long start_rip)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
unsigned long val;
|
||||
int pnode;
|
||||
|
||||
pnode = uv_apicid_to_pnode(phys_apicid);
|
||||
val = (1UL << UVH_IPI_INT_SEND_SHFT) |
|
||||
(phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) |
|
||||
(((long)start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |
|
||||
((start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |
|
||||
APIC_DM_INIT;
|
||||
uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
|
||||
mdelay(10);
|
||||
|
||||
val = (1UL << UVH_IPI_INT_SEND_SHFT) |
|
||||
(phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) |
|
||||
(((long)start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |
|
||||
((start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |
|
||||
APIC_DM_STARTUP;
|
||||
uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
|
||||
|
||||
atomic_set(&init_deasserted, 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uv_send_IPI_one(int cpu, int vector)
|
||||
{
|
||||
unsigned long val, apicid;
|
||||
unsigned long apicid;
|
||||
int pnode;
|
||||
|
||||
apicid = per_cpu(x86_cpu_to_apicid, cpu);
|
||||
pnode = uv_apicid_to_pnode(apicid);
|
||||
|
||||
val = (1UL << UVH_IPI_INT_SEND_SHFT) |
|
||||
(apicid << UVH_IPI_INT_APIC_ID_SHFT) |
|
||||
(vector << UVH_IPI_INT_VECTOR_SHFT);
|
||||
|
||||
uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
|
||||
uv_hub_send_ipi(pnode, apicid, vector);
|
||||
}
|
||||
|
||||
static void uv_send_IPI_mask(const struct cpumask *mask, int vector)
|
||||
@@ -285,7 +284,7 @@ struct apic apic_x2apic_uv_x = {
|
||||
.send_IPI_all = uv_send_IPI_all,
|
||||
.send_IPI_self = uv_send_IPI_self,
|
||||
|
||||
.wakeup_cpu = NULL,
|
||||
.wakeup_secondary_cpu = uv_wakeup_secondary,
|
||||
.trampoline_phys_low = DEFAULT_TRAMPOLINE_PHYS_LOW,
|
||||
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
|
||||
.wait_for_init_deassert = NULL,
|
||||
@@ -365,7 +364,7 @@ static __init void map_high(char *id, unsigned long base, int shift,
|
||||
paddr = base << shift;
|
||||
bytes = (1UL << shift) * (max_pnode + 1);
|
||||
printk(KERN_INFO "UV: Map %s_HI 0x%lx - 0x%lx\n", id, paddr,
|
||||
paddr + bytes);
|
||||
paddr + bytes);
|
||||
if (map_type == map_uc)
|
||||
init_extra_mapping_uc(paddr, bytes);
|
||||
else
|
||||
@@ -528,7 +527,7 @@ late_initcall(uv_init_heartbeat);
|
||||
|
||||
/*
|
||||
* Called on each cpu to initialize the per_cpu UV data area.
|
||||
* ZZZ hotplug not supported yet
|
||||
* FIXME: hotplug not supported yet
|
||||
*/
|
||||
void __cpuinit uv_cpu_init(void)
|
||||
{
|
||||
|
Reference in New Issue
Block a user