diff options
Diffstat (limited to 'arch/powerpc/sysdev/xics/icp-native.c')
| -rw-r--r-- | arch/powerpc/sysdev/xics/icp-native.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c index 1f15ad43614..de8d9483bbe 100644 --- a/arch/powerpc/sysdev/xics/icp-native.c +++ b/arch/powerpc/sysdev/xics/icp-native.c @@ -17,6 +17,7 @@ #include <linux/cpu.h> #include <linux/of.h> #include <linux/spinlock.h> +#include <linux/module.h> #include <asm/prom.h> #include <asm/io.h> @@ -24,6 +25,8 @@ #include <asm/irq.h> #include <asm/errno.h> #include <asm/xics.h> +#include <asm/kvm_ppc.h> +#include <asm/dbell.h> struct icp_ipl { union { @@ -49,6 +52,12 @@ static struct icp_ipl __iomem *icp_native_regs[NR_CPUS]; static inline unsigned int icp_native_get_xirr(void) { int cpu = smp_processor_id(); + unsigned int xirr; + + /* Handled an interrupt latched by KVM */ + xirr = kvmppc_get_xics_latch(); + if (xirr) + return xirr; return in_be32(&icp_native_regs[cpu]->xirr.word); } @@ -79,7 +88,7 @@ static void icp_native_set_cpu_priority(unsigned char cppr) iosync(); } -static void icp_native_eoi(struct irq_data *d) +void icp_native_eoi(struct irq_data *d) { unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d); @@ -117,7 +126,7 @@ static unsigned int icp_native_get_irq(void) if (vec == XICS_IRQ_SPURIOUS) return NO_IRQ; - irq = irq_radix_revmap_lookup(xics_host, vec); + irq = irq_find_mapping(xics_host, vec); if (likely(irq != NO_IRQ)) { xics_push_cppr(vec); return irq; @@ -136,13 +145,27 @@ static unsigned int icp_native_get_irq(void) static void icp_native_cause_ipi(int cpu, unsigned long data) { + kvmppc_set_host_ipi(cpu, 1); +#ifdef CONFIG_PPC_DOORBELL + if (cpu_has_feature(CPU_FTR_DBELL) && + (cpumask_test_cpu(cpu, cpu_sibling_mask(smp_processor_id())))) + doorbell_cause_ipi(cpu, data); + else +#endif + icp_native_set_qirr(cpu, IPI_PRIORITY); +} + +void xics_wake_cpu(int cpu) +{ icp_native_set_qirr(cpu, IPI_PRIORITY); } +EXPORT_SYMBOL_GPL(xics_wake_cpu); static irqreturn_t icp_native_ipi_action(int irq, void *dev_id) { int cpu = smp_processor_id(); + kvmppc_set_host_ipi(cpu, 0); icp_native_set_qirr(cpu, 0xff); return smp_ipi_demux(); @@ -185,6 +208,7 @@ static int __init icp_native_map_one_cpu(int hw_id, unsigned long addr, } icp_native_regs[cpu] = ioremap(addr, size); + kvmppc_set_xics_phys(cpu, addr); if (!icp_native_regs[cpu]) { pr_warning("icp_native: Failed ioremap for CPU %d, " "interrupt server #0x%x, addr %#lx\n", @@ -199,7 +223,7 @@ static int __init icp_native_init_one_node(struct device_node *np, unsigned int *indx) { unsigned int ilen; - const u32 *ireg; + const __be32 *ireg; int i; int reg_tuple_size; int num_servers = 0; @@ -247,7 +271,7 @@ static int __init icp_native_init_one_node(struct device_node *np, return -1; } - if (icp_native_map_one_cpu(*indx, r.start, r.end - r.start)) + if (icp_native_map_one_cpu(*indx, r.start, resource_size(&r))) return -1; (*indx)++; @@ -267,7 +291,7 @@ static const struct icp_ops icp_native_ops = { #endif }; -int icp_native_init(void) +int __init icp_native_init(void) { struct device_node *np; u32 indx = 0; |
