x86, UV: add uv_setup_irq() and uv_teardown_irq() functions, v3
Provide a means for UV interrupt MMRs to be setup with the message to be sent when an MSI is raised. Signed-off-by: Dean Nelson <dcn@sgi.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
5f79f2f2ad
commit
4173a0e737
|
@ -108,7 +108,7 @@ obj-$(CONFIG_MICROCODE) += microcode.o
|
||||||
# 64 bit specific files
|
# 64 bit specific files
|
||||||
ifeq ($(CONFIG_X86_64),y)
|
ifeq ($(CONFIG_X86_64),y)
|
||||||
obj-y += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o
|
obj-y += genapic_64.o genapic_flat_64.o genx2apic_uv_x.o tlb_uv.o
|
||||||
obj-y += bios_uv.o
|
obj-y += bios_uv.o uv_irq.o
|
||||||
obj-y += genx2apic_cluster.o
|
obj-y += genx2apic_cluster.o
|
||||||
obj-y += genx2apic_phys.o
|
obj-y += genx2apic_phys.o
|
||||||
obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o
|
obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o
|
||||||
|
|
|
@ -58,6 +58,8 @@
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
#include <asm/irq_remapping.h>
|
#include <asm/irq_remapping.h>
|
||||||
#include <asm/hpet.h>
|
#include <asm/hpet.h>
|
||||||
|
#include <asm/uv/uv_hub.h>
|
||||||
|
#include <asm/uv/uv_irq.h>
|
||||||
|
|
||||||
#include <mach_ipi.h>
|
#include <mach_ipi.h>
|
||||||
#include <mach_apic.h>
|
#include <mach_apic.h>
|
||||||
|
@ -3692,6 +3694,72 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_HT_IRQ */
|
#endif /* CONFIG_HT_IRQ */
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86_64
|
||||||
|
/*
|
||||||
|
* Re-target the irq to the specified CPU and enable the specified MMR located
|
||||||
|
* on the specified blade to allow the sending of MSIs to the specified CPU.
|
||||||
|
*/
|
||||||
|
int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
|
||||||
|
unsigned long mmr_offset)
|
||||||
|
{
|
||||||
|
const cpumask_t *eligible_cpu = get_cpu_mask(cpu);
|
||||||
|
struct irq_cfg *cfg;
|
||||||
|
int mmr_pnode;
|
||||||
|
unsigned long mmr_value;
|
||||||
|
struct uv_IO_APIC_route_entry *entry;
|
||||||
|
unsigned long flags;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = assign_irq_vector(irq, *eligible_cpu);
|
||||||
|
if (err != 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&vector_lock, flags);
|
||||||
|
set_irq_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
|
||||||
|
irq_name);
|
||||||
|
spin_unlock_irqrestore(&vector_lock, flags);
|
||||||
|
|
||||||
|
cfg = irq_cfg(irq);
|
||||||
|
|
||||||
|
mmr_value = 0;
|
||||||
|
entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
|
||||||
|
BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
|
||||||
|
|
||||||
|
entry->vector = cfg->vector;
|
||||||
|
entry->delivery_mode = INT_DELIVERY_MODE;
|
||||||
|
entry->dest_mode = INT_DEST_MODE;
|
||||||
|
entry->polarity = 0;
|
||||||
|
entry->trigger = 0;
|
||||||
|
entry->mask = 0;
|
||||||
|
entry->dest = cpu_mask_to_apicid(*eligible_cpu);
|
||||||
|
|
||||||
|
mmr_pnode = uv_blade_to_pnode(mmr_blade);
|
||||||
|
uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
|
||||||
|
|
||||||
|
return irq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable the specified MMR located on the specified blade so that MSIs are
|
||||||
|
* longer allowed to be sent.
|
||||||
|
*/
|
||||||
|
void arch_disable_uv_irq(int mmr_blade, unsigned long mmr_offset)
|
||||||
|
{
|
||||||
|
unsigned long mmr_value;
|
||||||
|
struct uv_IO_APIC_route_entry *entry;
|
||||||
|
int mmr_pnode;
|
||||||
|
|
||||||
|
mmr_value = 0;
|
||||||
|
entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
|
||||||
|
BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
|
||||||
|
|
||||||
|
entry->mask = 1;
|
||||||
|
|
||||||
|
mmr_pnode = uv_blade_to_pnode(mmr_blade);
|
||||||
|
uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_X86_64 */
|
||||||
|
|
||||||
int __init io_apic_get_redir_entries (int ioapic)
|
int __init io_apic_get_redir_entries (int ioapic)
|
||||||
{
|
{
|
||||||
union IO_APIC_reg_01 reg_01;
|
union IO_APIC_reg_01 reg_01;
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* SGI UV IRQ functions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/irq.h>
|
||||||
|
#include <asm/uv/uv_irq.h>
|
||||||
|
|
||||||
|
static void uv_noop(unsigned int irq)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int uv_noop_ret(unsigned int irq)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uv_ack_apic(unsigned int irq)
|
||||||
|
{
|
||||||
|
ack_APIC_irq();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct irq_chip uv_irq_chip = {
|
||||||
|
.name = "UV-CORE",
|
||||||
|
.startup = uv_noop_ret,
|
||||||
|
.shutdown = uv_noop,
|
||||||
|
.enable = uv_noop,
|
||||||
|
.disable = uv_noop,
|
||||||
|
.ack = uv_noop,
|
||||||
|
.mask = uv_noop,
|
||||||
|
.unmask = uv_noop,
|
||||||
|
.eoi = uv_ack_apic,
|
||||||
|
.end = uv_noop,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up a mapping of an available irq and vector, and enable the specified
|
||||||
|
* MMR that defines the MSI that is to be sent to the specified CPU when an
|
||||||
|
* interrupt is raised.
|
||||||
|
*/
|
||||||
|
int uv_setup_irq(char *irq_name, int cpu, int mmr_blade,
|
||||||
|
unsigned long mmr_offset)
|
||||||
|
{
|
||||||
|
int irq;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
irq = create_irq();
|
||||||
|
if (irq <= 0)
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
ret = arch_enable_uv_irq(irq_name, irq, cpu, mmr_blade, mmr_offset);
|
||||||
|
if (ret != irq)
|
||||||
|
destroy_irq(irq);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(uv_setup_irq);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tear down a mapping of an irq and vector, and disable the specified MMR that
|
||||||
|
* defined the MSI that was to be sent to the specified CPU when an interrupt
|
||||||
|
* was raised.
|
||||||
|
*
|
||||||
|
* Set mmr_blade and mmr_offset to what was passed in on uv_setup_irq().
|
||||||
|
*/
|
||||||
|
void uv_teardown_irq(unsigned int irq, int mmr_blade, unsigned long mmr_offset)
|
||||||
|
{
|
||||||
|
arch_disable_uv_irq(mmr_blade, mmr_offset);
|
||||||
|
destroy_irq(irq);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(uv_teardown_irq);
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* SGI UV IRQ definitions
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ASM_X86__UV__UV_IRQ_H
|
||||||
|
#define ASM_X86__UV__UV_IRQ_H
|
||||||
|
|
||||||
|
/* If a generic version of this structure gets defined, eliminate this one. */
|
||||||
|
struct uv_IO_APIC_route_entry {
|
||||||
|
__u64 vector : 8,
|
||||||
|
delivery_mode : 3,
|
||||||
|
dest_mode : 1,
|
||||||
|
delivery_status : 1,
|
||||||
|
polarity : 1,
|
||||||
|
__reserved_1 : 1,
|
||||||
|
trigger : 1,
|
||||||
|
mask : 1,
|
||||||
|
__reserved_2 : 15,
|
||||||
|
dest : 32;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct irq_chip uv_irq_chip;
|
||||||
|
|
||||||
|
extern int arch_enable_uv_irq(char *, unsigned int, int, int, unsigned long);
|
||||||
|
extern void arch_disable_uv_irq(int, unsigned long);
|
||||||
|
|
||||||
|
extern int uv_setup_irq(char *, int, int, unsigned long);
|
||||||
|
extern void uv_teardown_irq(unsigned int, int, unsigned long);
|
||||||
|
|
||||||
|
#endif /* ASM_X86__UV__UV_IRQ_H */
|
Loading…
Reference in New Issue