Commit 7cec18a3 authored by Matt Redfearn's avatar Matt Redfearn Committed by Thomas Gleixner

genirq: Add error code reporting to irq_{reserve,destroy}_ipi

Make these functions return appropriate error codes when something goes
wrong.

Previously irq_destroy_ipi returned void making it impossible to notify
the caller if the request could not be fulfilled. Patch 1 in the series
added another condition in which this could fail in addition to the
existing ones. irq_reserve_ipi returned an unsigned int meaning it could
only return 0 on failure and give the caller no indication as to why the
request failed.

As time goes on there are likely to be further conditions added in which
these functions can fail. These APIs and the IPI IRQ domain are new in
4.6 and the number of existing call sites are low, changing the API now
has little impact on the code, while making it easier for these
functions to grow over time.
Signed-off-by: default avatarMatt Redfearn <matt.redfearn@imgtec.com>
Cc: linux-mips@linux-mips.org
Cc: jason@lakedaemon.net
Cc: marc.zyngier@arm.com
Cc: ralf@linux-mips.org
Cc: Qais Yousef <qsyousef@gmail.com>
Cc: lisa.parratt@imgtec.com
Cc: jiang.liu@linux.intel.com
Link: http://lkml.kernel.org/r/1461568464-31701-2-git-send-email-matt.redfearn@imgtec.comSigned-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 01292cea
...@@ -346,9 +346,8 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr, ...@@ -346,9 +346,8 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr,
irq_hw_number_t *out_hwirq, unsigned int *out_type); irq_hw_number_t *out_hwirq, unsigned int *out_type);
/* IPI functions */ /* IPI functions */
unsigned int irq_reserve_ipi(struct irq_domain *domain, int irq_reserve_ipi(struct irq_domain *domain, const struct cpumask *dest);
const struct cpumask *dest); int irq_destroy_ipi(unsigned int irq, const struct cpumask *dest);
void irq_destroy_ipi(unsigned int irq, const struct cpumask *dest);
/* V2 interfaces to support hierarchy IRQ domains. */ /* V2 interfaces to support hierarchy IRQ domains. */
extern struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain, extern struct irq_data *irq_domain_get_irq_data(struct irq_domain *domain,
......
...@@ -19,9 +19,9 @@ ...@@ -19,9 +19,9 @@
* *
* Allocate a virq that can be used to send IPI to any CPU in dest mask. * Allocate a virq that can be used to send IPI to any CPU in dest mask.
* *
* On success it'll return linux irq number and 0 on failure * On success it'll return linux irq number and error code on failure
*/ */
unsigned int irq_reserve_ipi(struct irq_domain *domain, int irq_reserve_ipi(struct irq_domain *domain,
const struct cpumask *dest) const struct cpumask *dest)
{ {
unsigned int nr_irqs, offset; unsigned int nr_irqs, offset;
...@@ -30,18 +30,18 @@ unsigned int irq_reserve_ipi(struct irq_domain *domain, ...@@ -30,18 +30,18 @@ unsigned int irq_reserve_ipi(struct irq_domain *domain,
if (!domain ||!irq_domain_is_ipi(domain)) { if (!domain ||!irq_domain_is_ipi(domain)) {
pr_warn("Reservation on a non IPI domain\n"); pr_warn("Reservation on a non IPI domain\n");
return 0; return -EINVAL;
} }
if (!cpumask_subset(dest, cpu_possible_mask)) { if (!cpumask_subset(dest, cpu_possible_mask)) {
pr_warn("Reservation is not in possible_cpu_mask\n"); pr_warn("Reservation is not in possible_cpu_mask\n");
return 0; return -EINVAL;
} }
nr_irqs = cpumask_weight(dest); nr_irqs = cpumask_weight(dest);
if (!nr_irqs) { if (!nr_irqs) {
pr_warn("Reservation for empty destination mask\n"); pr_warn("Reservation for empty destination mask\n");
return 0; return -EINVAL;
} }
if (irq_domain_is_ipi_single(domain)) { if (irq_domain_is_ipi_single(domain)) {
...@@ -72,14 +72,14 @@ unsigned int irq_reserve_ipi(struct irq_domain *domain, ...@@ -72,14 +72,14 @@ unsigned int irq_reserve_ipi(struct irq_domain *domain,
next = cpumask_next(next, dest); next = cpumask_next(next, dest);
if (next < nr_cpu_ids) { if (next < nr_cpu_ids) {
pr_warn("Destination mask has holes\n"); pr_warn("Destination mask has holes\n");
return 0; return -EINVAL;
} }
} }
virq = irq_domain_alloc_descs(-1, nr_irqs, 0, NUMA_NO_NODE); virq = irq_domain_alloc_descs(-1, nr_irqs, 0, NUMA_NO_NODE);
if (virq <= 0) { if (virq <= 0) {
pr_warn("Can't reserve IPI, failed to alloc descs\n"); pr_warn("Can't reserve IPI, failed to alloc descs\n");
return 0; return -ENOMEM;
} }
virq = __irq_domain_alloc_irqs(domain, virq, nr_irqs, NUMA_NO_NODE, virq = __irq_domain_alloc_irqs(domain, virq, nr_irqs, NUMA_NO_NODE,
...@@ -100,7 +100,7 @@ unsigned int irq_reserve_ipi(struct irq_domain *domain, ...@@ -100,7 +100,7 @@ unsigned int irq_reserve_ipi(struct irq_domain *domain,
free_descs: free_descs:
irq_free_descs(virq, nr_irqs); irq_free_descs(virq, nr_irqs);
return 0; return -EBUSY;
} }
/** /**
...@@ -108,10 +108,12 @@ unsigned int irq_reserve_ipi(struct irq_domain *domain, ...@@ -108,10 +108,12 @@ unsigned int irq_reserve_ipi(struct irq_domain *domain,
* @irq: linux irq number to be destroyed * @irq: linux irq number to be destroyed
* @dest: cpumask of cpus which should have the IPI removed * @dest: cpumask of cpus which should have the IPI removed
* *
* Return the IPIs allocated with irq_reserve_ipi() to the system destroying * The IPIs allocated with irq_reserve_ipi() are retuerned to the system
* all virqs associated with them. * destroying all virqs associated with them.
*
* Return 0 on success or error code on failure.
*/ */
void irq_destroy_ipi(unsigned int irq, const struct cpumask *dest) int irq_destroy_ipi(unsigned int irq, const struct cpumask *dest)
{ {
struct irq_data *data = irq_get_irq_data(irq); struct irq_data *data = irq_get_irq_data(irq);
struct cpumask *ipimask = data ? irq_data_get_affinity_mask(data) : NULL; struct cpumask *ipimask = data ? irq_data_get_affinity_mask(data) : NULL;
...@@ -119,7 +121,7 @@ void irq_destroy_ipi(unsigned int irq, const struct cpumask *dest) ...@@ -119,7 +121,7 @@ void irq_destroy_ipi(unsigned int irq, const struct cpumask *dest)
unsigned int nr_irqs; unsigned int nr_irqs;
if (!irq || !data || !ipimask) if (!irq || !data || !ipimask)
return; return -EINVAL;
domain = data->domain; domain = data->domain;
if (WARN_ON(domain == NULL)) if (WARN_ON(domain == NULL))
...@@ -127,7 +129,7 @@ void irq_destroy_ipi(unsigned int irq, const struct cpumask *dest) ...@@ -127,7 +129,7 @@ void irq_destroy_ipi(unsigned int irq, const struct cpumask *dest)
if (!irq_domain_is_ipi(domain)) { if (!irq_domain_is_ipi(domain)) {
pr_warn("Trying to destroy a non IPI domain!\n"); pr_warn("Trying to destroy a non IPI domain!\n");
return; return -EINVAL;
} }
if (WARN_ON(!cpumask_subset(dest, ipimask))) if (WARN_ON(!cpumask_subset(dest, ipimask)))
...@@ -135,7 +137,7 @@ void irq_destroy_ipi(unsigned int irq, const struct cpumask *dest) ...@@ -135,7 +137,7 @@ void irq_destroy_ipi(unsigned int irq, const struct cpumask *dest)
* Must be destroying a subset of CPUs to which this IPI * Must be destroying a subset of CPUs to which this IPI
* was set up to target * was set up to target
*/ */
return; return -EINVAL;
if (irq_domain_is_ipi_per_cpu(domain)) { if (irq_domain_is_ipi_per_cpu(domain)) {
irq = irq + cpumask_first(dest) - data->common->ipi_offset; irq = irq + cpumask_first(dest) - data->common->ipi_offset;
...@@ -145,6 +147,7 @@ void irq_destroy_ipi(unsigned int irq, const struct cpumask *dest) ...@@ -145,6 +147,7 @@ void irq_destroy_ipi(unsigned int irq, const struct cpumask *dest)
} }
irq_domain_free_irqs(irq, nr_irqs); irq_domain_free_irqs(irq, nr_irqs);
return 0;
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment