Skip to content

Commit

Permalink
genirq: Add a new function to get IPI reverse mapping
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Qais Yousef authored and Thomas Gleixner committed Feb 25, 2016
1 parent d17bf24 commit f9bce79
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/linux/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -942,5 +942,6 @@ static inline u32 irq_reg_readl(struct irq_chip_generic *gc,

/* Contrary to Linux irqs, for hardware irqs the irq number 0 is valid */
#define INVALID_HWIRQ (~0UL)
irq_hw_number_t ipi_get_hwirq(unsigned int irq, unsigned int cpu);

#endif /* _LINUX_IRQ_H */
34 changes: 34 additions & 0 deletions kernel/irq/ipi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

0 comments on commit f9bce79

Please sign in to comment.