Skip to content

Commit

Permalink
Merge branch 'x86/irq' into x86/devel
Browse files Browse the repository at this point in the history
Conflicts:

	arch/x86/kernel/i8259.c
	arch/x86/kernel/irqinit_64.c

Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Ingo Molnar committed Jul 8, 2008
2 parents 58cf352 + cbd6712 commit 1b8ba39
Show file tree
Hide file tree
Showing 27 changed files with 1,253 additions and 850 deletions.
2 changes: 0 additions & 2 deletions arch/x86/kernel/acpi/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -514,8 +514,6 @@ int acpi_register_gsi(u32 gsi, int triggering, int polarity)
* Make sure all (legacy) PCI IRQs are set as level-triggered.
*/
if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
extern void eisa_set_level_irq(unsigned int irq);

if (triggering == ACPI_LEVEL_SENSITIVE)
eisa_set_level_irq(gsi);
}
Expand Down
18 changes: 11 additions & 7 deletions arch/x86/kernel/apic_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ static int local_apic_timer_disabled;
int local_apic_timer_c2_ok;
EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);

int first_system_vector = 0xfe;

char system_vectors[NR_VECTORS] = { [0 ... NR_VECTORS-1] = SYS_VECTOR_FREE};

/*
* Debug level, exported for io_apic.c
*/
Expand Down Expand Up @@ -1351,13 +1355,13 @@ void __init smp_intr_init(void)
* The reschedule interrupt is a CPU-to-CPU reschedule-helper
* IPI, driven by wakeup.
*/
set_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);

/* IPI for invalidation */
set_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);
alloc_intr_gate(INVALIDATE_TLB_VECTOR, invalidate_interrupt);

/* IPI for generic function call */
set_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
}
#endif

Expand All @@ -1370,15 +1374,15 @@ void __init apic_intr_init(void)
smp_intr_init();
#endif
/* self generated IPI for local APIC timer */
set_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);

/* IPI vectors for APIC spurious and error interrupts */
set_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);

/* thermal monitor LVT interrupt */
#ifdef CONFIG_X86_MCE_P4THERMAL
set_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
#endif
}

Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/entry_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
#include <asm/percpu.h>
#include <asm/dwarf2.h>
#include <asm/processor-flags.h>
#include "irq_vectors.h"
#include <asm/irq_vectors.h>

/*
* We use macros for low-level operations which need to be overridden
Expand Down
141 changes: 98 additions & 43 deletions arch/x86/kernel/genx2apic_uv_x.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* SGI UV APIC functions (note: not an Intel compatible APIC)
*
* Copyright (C) 2007 Silicon Graphics, Inc. All rights reserved.
* Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved.
*/

#include <linux/threads.h>
Expand Down Expand Up @@ -55,37 +55,37 @@ static cpumask_t uv_vector_allocation_domain(int cpu)
int uv_wakeup_secondary(int phys_apicid, unsigned int start_rip)
{
unsigned long val;
int nasid;
int pnode;

nasid = uv_apicid_to_nasid(phys_apicid);
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) |
APIC_DM_INIT;
uv_write_global_mmr64(nasid, UVH_IPI_INT, val);
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) |
APIC_DM_STARTUP;
uv_write_global_mmr64(nasid, UVH_IPI_INT, val);
uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
return 0;
}

static void uv_send_IPI_one(int cpu, int vector)
{
unsigned long val, apicid, lapicid;
int nasid;
int pnode;

apicid = per_cpu(x86_cpu_to_apicid, cpu); /* ZZZ - cache node-local ? */
lapicid = apicid & 0x3f; /* ZZZ macro needed */
nasid = uv_apicid_to_nasid(apicid);
pnode = uv_apicid_to_pnode(apicid);
val =
(1UL << UVH_IPI_INT_SEND_SHFT) | (lapicid <<
UVH_IPI_INT_APIC_ID_SHFT) |
(vector << UVH_IPI_INT_VECTOR_SHFT);
uv_write_global_mmr64(nasid, UVH_IPI_INT, val);
uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
}

static void uv_send_IPI_mask(cpumask_t mask, int vector)
Expand Down Expand Up @@ -159,39 +159,81 @@ struct genapic apic_x2apic_uv_x = {
.phys_pkg_id = phys_pkg_id, /* Fixme ZZZ */
};

static __cpuinit void set_x2apic_extra_bits(int nasid)
static __cpuinit void set_x2apic_extra_bits(int pnode)
{
__get_cpu_var(x2apic_extra_bits) = ((nasid >> 1) << 6);
__get_cpu_var(x2apic_extra_bits) = (pnode << 6);
}

/*
* Called on boot cpu.
*/
static __init int boot_pnode_to_blade(int pnode)
{
int blade;

for (blade = 0; blade < uv_num_possible_blades(); blade++)
if (pnode == uv_blade_info[blade].pnode)
return blade;
BUG();
}

struct redir_addr {
unsigned long redirect;
unsigned long alias;
};

#define DEST_SHIFT UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_SHFT

static __initdata struct redir_addr redir_addrs[] = {
{UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR, UVH_SI_ALIAS0_OVERLAY_CONFIG},
{UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR, UVH_SI_ALIAS1_OVERLAY_CONFIG},
{UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR, UVH_SI_ALIAS2_OVERLAY_CONFIG},
};

static __init void get_lowmem_redirect(unsigned long *base, unsigned long *size)
{
union uvh_si_alias0_overlay_config_u alias;
union uvh_rh_gam_alias210_redirect_config_2_mmr_u redirect;
int i;

for (i = 0; i < ARRAY_SIZE(redir_addrs); i++) {
alias.v = uv_read_local_mmr(redir_addrs[i].alias);
if (alias.s.base == 0) {
*size = (1UL << alias.s.m_alias);
redirect.v = uv_read_local_mmr(redir_addrs[i].redirect);
*base = (unsigned long)redirect.s.dest_base << DEST_SHIFT;
return;
}
}
BUG();
}

static __init void uv_system_init(void)
{
union uvh_si_addr_map_config_u m_n_config;
int bytes, nid, cpu, lcpu, nasid, last_nasid, blade;
unsigned long mmr_base;
union uvh_node_id_u node_id;
unsigned long gnode_upper, lowmem_redir_base, lowmem_redir_size;
int bytes, nid, cpu, lcpu, pnode, blade, i, j, m_val, n_val;
unsigned long mmr_base, present;

m_n_config.v = uv_read_local_mmr(UVH_SI_ADDR_MAP_CONFIG);
m_val = m_n_config.s.m_skt;
n_val = m_n_config.s.n_skt;
mmr_base =
uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) &
~UV_MMR_ENABLE;
printk(KERN_DEBUG "UV: global MMR base 0x%lx\n", mmr_base);

last_nasid = -1;
for_each_possible_cpu(cpu) {
nid = cpu_to_node(cpu);
nasid = uv_apicid_to_nasid(per_cpu(x86_cpu_to_apicid, cpu));
if (nasid != last_nasid)
uv_possible_blades++;
last_nasid = nasid;
}
for(i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++)
uv_possible_blades +=
hweight64(uv_read_local_mmr( UVH_NODE_PRESENT_TABLE + i * 8));
printk(KERN_DEBUG "UV: Found %d blades\n", uv_num_possible_blades());

bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
uv_blade_info = alloc_bootmem_pages(bytes);

get_lowmem_redirect(&lowmem_redir_base, &lowmem_redir_size);

bytes = sizeof(uv_node_to_blade[0]) * num_possible_nodes();
uv_node_to_blade = alloc_bootmem_pages(bytes);
memset(uv_node_to_blade, 255, bytes);
Expand All @@ -200,43 +242,56 @@ static __init void uv_system_init(void)
uv_cpu_to_blade = alloc_bootmem_pages(bytes);
memset(uv_cpu_to_blade, 255, bytes);

last_nasid = -1;
blade = -1;
lcpu = -1;
for_each_possible_cpu(cpu) {
nid = cpu_to_node(cpu);
nasid = uv_apicid_to_nasid(per_cpu(x86_cpu_to_apicid, cpu));
if (nasid != last_nasid) {
blade++;
lcpu = -1;
uv_blade_info[blade].nr_posible_cpus = 0;
blade = 0;
for (i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++) {
present = uv_read_local_mmr(UVH_NODE_PRESENT_TABLE + i * 8);
for (j = 0; j < 64; j++) {
if (!test_bit(j, &present))
continue;
uv_blade_info[blade].pnode = (i * 64 + j);
uv_blade_info[blade].nr_possible_cpus = 0;
uv_blade_info[blade].nr_online_cpus = 0;
blade++;
}
last_nasid = nasid;
lcpu++;
}

uv_cpu_hub_info(cpu)->m_val = m_n_config.s.m_skt;
uv_cpu_hub_info(cpu)->n_val = m_n_config.s.n_skt;
node_id.v = uv_read_local_mmr(UVH_NODE_ID);
gnode_upper = (((unsigned long)node_id.s.node_id) &
~((1 << n_val) - 1)) << m_val;

for_each_present_cpu(cpu) {
nid = cpu_to_node(cpu);
pnode = uv_apicid_to_pnode(per_cpu(x86_cpu_to_apicid, cpu));
blade = boot_pnode_to_blade(pnode);
lcpu = uv_blade_info[blade].nr_possible_cpus;
uv_blade_info[blade].nr_possible_cpus++;

uv_cpu_hub_info(cpu)->lowmem_remap_base = lowmem_redir_base;
uv_cpu_hub_info(cpu)->lowmem_remap_top =
lowmem_redir_base + lowmem_redir_size;
uv_cpu_hub_info(cpu)->m_val = m_val;
uv_cpu_hub_info(cpu)->n_val = m_val;
uv_cpu_hub_info(cpu)->numa_blade_id = blade;
uv_cpu_hub_info(cpu)->blade_processor_id = lcpu;
uv_cpu_hub_info(cpu)->local_nasid = nasid;
uv_cpu_hub_info(cpu)->gnode_upper =
nasid & ~((1 << uv_hub_info->n_val) - 1);
uv_cpu_hub_info(cpu)->pnode = pnode;
uv_cpu_hub_info(cpu)->pnode_mask = (1 << n_val) - 1;
uv_cpu_hub_info(cpu)->gpa_mask = (1 << (m_val + n_val)) - 1;
uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper;
uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base;
uv_cpu_hub_info(cpu)->coherency_domain_number = 0;/* ZZZ */
uv_blade_info[blade].nasid = nasid;
uv_blade_info[blade].nr_posible_cpus++;
uv_node_to_blade[nid] = blade;
uv_cpu_to_blade[cpu] = blade;

printk(KERN_DEBUG "UV cpu %d, apicid 0x%x, nasid %d, nid %d\n",
cpu, per_cpu(x86_cpu_to_apicid, cpu), nasid, nid);
printk(KERN_DEBUG "UV lcpu %d, blade %d\n", lcpu, blade);
printk(KERN_DEBUG "UV cpu %d, apicid 0x%x, pnode %d, nid %d, "
"lcpu %d, blade %d\n",
cpu, per_cpu(x86_cpu_to_apicid, cpu), pnode, nid,
lcpu, blade);
}
}

/*
* Called on each cpu to initialize the per_cpu UV data area.
* ZZZ hotplug not supported yet
*/
void __cpuinit uv_cpu_init(void)
{
Expand All @@ -246,5 +301,5 @@ void __cpuinit uv_cpu_init(void)
uv_blade_info[uv_numa_blade_id()].nr_online_cpus++;

if (get_uv_system_type() == UV_NON_UNIQUE_APIC)
set_x2apic_extra_bits(uv_hub_info->local_nasid);
set_x2apic_extra_bits(uv_hub_info->pnode);
}
22 changes: 8 additions & 14 deletions arch/x86/kernel/i8259.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,34 +297,28 @@ void init_8259A(int auto_eoi)
* outb_pic - this has to work on a wide range of PC hardware.
*/
outb_pic(0x11, PIC_MASTER_CMD); /* ICW1: select 8259A-1 init */
#ifndef CONFIG_X86_64
outb_pic(0x20 + 0, PIC_MASTER_IMR); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
outb_pic(1U << PIC_CASCADE_IR, PIC_MASTER_IMR); /* 8259A-1 (the master) has a slave on IR2 */
#else /* CONFIG_X86_64 */
/* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 */

/* ICW2: 8259A-1 IR0-7 mapped to 0x30-0x37 on x86-64,
to 0x20-0x27 on i386 */
outb_pic(IRQ0_VECTOR, PIC_MASTER_IMR);

/* 8259A-1 (the master) has a slave on IR2 */
outb_pic(0x04, PIC_MASTER_IMR);
#endif /* CONFIG_X86_64 */
outb_pic(1U << PIC_CASCADE_IR, PIC_MASTER_IMR);

if (auto_eoi) /* master does Auto EOI */
outb_pic(MASTER_ICW4_DEFAULT | PIC_ICW4_AEOI, PIC_MASTER_IMR);
else /* master expects normal EOI */
outb_pic(MASTER_ICW4_DEFAULT, PIC_MASTER_IMR);

outb_pic(0x11, PIC_SLAVE_CMD); /* ICW1: select 8259A-2 init */
#ifndef CONFIG_X86_64
outb_pic(0x20 + 8, PIC_SLAVE_IMR); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
outb_pic(PIC_CASCADE_IR, PIC_SLAVE_IMR); /* 8259A-2 is a slave on master's IR2 */
outb_pic(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR); /* (slave's support for AEOI in flat mode is to be investigated) */
#else /* CONFIG_X86_64 */
/* ICW2: 8259A-2 IR0-7 mapped to 0x38-0x3f */

/* ICW2: 8259A-2 IR0-7 mapped to IRQ8_VECTOR */
outb_pic(IRQ8_VECTOR, PIC_SLAVE_IMR);
/* 8259A-2 is a slave on master's IR2 */
outb_pic(PIC_CASCADE_IR, PIC_SLAVE_IMR);
/* (slave's support for AEOI in flat mode is to be investigated) */
outb_pic(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR);

#endif /* CONFIG_X86_64 */
if (auto_eoi)
/*
* In AEOI mode we just have to mask the interrupt
Expand Down
4 changes: 2 additions & 2 deletions arch/x86/kernel/io_apic_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -1174,7 +1174,7 @@ static int __assign_irq_vector(int irq)
offset = current_offset;
next:
vector += 8;
if (vector >= FIRST_SYSTEM_VECTOR) {
if (vector >= first_system_vector) {
offset = (offset + 1) % 8;
vector = FIRST_DEVICE_VECTOR + offset;
}
Expand Down Expand Up @@ -2280,7 +2280,7 @@ void __init setup_IO_APIC(void)
int i;

/* Reserve all the system vectors. */
for (i = FIRST_SYSTEM_VECTOR; i < NR_VECTORS; i++)
for (i = first_system_vector; i < NR_VECTORS; i++)
set_bit(i, used_vectors);

enable_IO_APIC();
Expand Down
6 changes: 5 additions & 1 deletion arch/x86/kernel/io_apic_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ static struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = {

static int assign_irq_vector(int irq, cpumask_t mask);

int first_system_vector = 0xfe;

char system_vectors[NR_VECTORS] = { [0 ... NR_VECTORS-1] = SYS_VECTOR_FREE};

#define __apicdebuginit __init

int sis_apic_bug; /* not actually supported, dummy for compile */
Expand Down Expand Up @@ -737,7 +741,7 @@ static int __assign_irq_vector(int irq, cpumask_t mask)
offset = current_offset;
next:
vector += 8;
if (vector >= FIRST_SYSTEM_VECTOR) {
if (vector >= first_system_vector) {
/* If we run out of vectors on large boxen, must share them. */
offset = (offset + 1) % 8;
vector = FIRST_DEVICE_VECTOR + offset;
Expand Down
Loading

0 comments on commit 1b8ba39

Please sign in to comment.