aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq
diff options
context:
space:
mode:
authorQais Yousef <qais.yousef@imgtec.com>2015-12-08 13:20:20 +0000
committerThomas Gleixner <tglx@linutronix.de>2016-02-25 10:56:56 +0100
commitf9bce791ae2a1a10a965b30427f5507c1a77669f (patch)
tree73095b50502e126c58b16a05cfba733fee8648df /kernel/irq
parentgenirq: Add a new generic IPI reservation code to irq core (diff)
downloadlinux-dev-f9bce791ae2a1a10a965b30427f5507c1a77669f.tar.xz
linux-dev-f9bce791ae2a1a10a965b30427f5507c1a77669f.zip
genirq: Add a new function to get IPI reverse mapping
When dealing with coprocessors we need to find out the actual hwirqs values to pass on to the firmware so that it knows what it needs to use to receive IPIs from and send IPIs to Linux cpus. [ tglx: Fixed the single hwirq IPI case. The hardware irq number does not change due to the cpu number ] Signed-off-by: Qais Yousef <qais.yousef@imgtec.com> Cc: <jason@lakedaemon.net> Cc: <marc.zyngier@arm.com> Cc: <jiang.liu@linux.intel.com> Cc: <ralf@linux-mips.org> Cc: <linux-mips@linux-mips.org> Cc: <lisa.parratt@imgtec.com> Cc: Qais Yousef <qsyousef@gmail.com> Link: http://lkml.kernel.org/r/1449580830-23652-10-git-send-email-qais.yousef@imgtec.com Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/irq')
-rw-r--r--kernel/irq/ipi.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/kernel/irq/ipi.c b/kernel/irq/ipi.c
index 340af273429c..6f34f2930bc0 100644
--- a/kernel/irq/ipi.c
+++ b/kernel/irq/ipi.c
@@ -135,3 +135,37 @@ void irq_destroy_ipi(unsigned int irq)
irq_domain_free_irqs(irq, nr_irqs);
}
+
+/**
+ * ipi_get_hwirq - Get the hwirq associated with an IPI to a cpu
+ * @irq: linux irq number
+ * @cpu: the target cpu
+ *
+ * When dealing with coprocessors IPI, we need to inform the coprocessor of
+ * the hwirq it needs to use to receive and send IPIs.
+ *
+ * Returns hwirq value on success and INVALID_HWIRQ on failure.
+ */
+irq_hw_number_t ipi_get_hwirq(unsigned int irq, unsigned int cpu)
+{
+ struct irq_data *data = irq_get_irq_data(irq);
+ struct cpumask *ipimask = data ? irq_data_get_affinity_mask(data) : NULL;
+
+ if (!data || !ipimask || cpu > nr_cpu_ids)
+ return INVALID_HWIRQ;
+
+ if (!cpumask_test_cpu(cpu, ipimask))
+ return INVALID_HWIRQ;
+
+ /*
+ * Get the real hardware irq number if the underlying implementation
+ * uses a seperate irq per cpu. If the underlying implementation uses
+ * a single hardware irq for all cpus then the IPI send mechanism
+ * needs to take care of this.
+ */
+ if (irq_domain_is_ipi_per_cpu(data->domain))
+ data = irq_get_irq_data(irq + cpu - data->common->ipi_offset);
+
+ return data ? irqd_to_hwirq(data) : INVALID_HWIRQ;
+}
+EXPORT_SYMBOL_GPL(ipi_get_hwirq);