Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq updates from Thomas Gleixner: "This update delivers: - Yet another interrupt chip diver (LPC32xx) - Core functions to handle partitioned per-cpu interrupts - Enhancements to the IPI core - Proper handling of irq type configuration - A large set of ARM GIC enhancements - The usual pile of small fixes, cleanups and enhancements" * 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (31 commits) irqchip/bcm2836: Use a more generic memory barrier call irqchip/bcm2836: Fix compiler warning on 64-bit build irqchip/bcm2836: Drop smp_set_ops on arm64 builds irqchip/gic: Add helper functions for GIC setup and teardown irqchip/gic: Store GIC configuration parameters irqchip/gic: Pass GIC pointer to save/restore functions irqchip/gic: Return an error if GIC initialisation fails irqchip/gic: Remove static irq_chip definition for eoimode1 irqchip/gic: Don't initialise chip if mapping IO space fails irqchip/gic: WARN if setting the interrupt type for a PPI fails irqchip/gic: Don't unnecessarily write the IRQ configuration irqchip: Mask the non-type/sense bits when translating an IRQ genirq: Ensure IRQ descriptor is valid when setting-up the IRQ irqchip/gic-v3: Configure all interrupts as non-secure Group-1 irqchip/gic-v2m: Add workaround for Broadcom NS2 GICv2m erratum irqchip/irq-alpine-msi: Don't use <asm-generic/msi.h> irqchip/mbigen: Checking for IS_ERR() instead of NULL irqchip/gic-v3: Remove inexistant register definition irqchip/gicv3-its: Don't allow devices whose ID is outside range irqchip: Add LPC32xx interrupt controller driver ...
This commit is contained in:
@@ -19,9 +19,9 @@
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
unsigned int nr_irqs, offset;
|
||||
@@ -30,18 +30,18 @@ unsigned int irq_reserve_ipi(struct irq_domain *domain,
|
||||
|
||||
if (!domain ||!irq_domain_is_ipi(domain)) {
|
||||
pr_warn("Reservation on a non IPI domain\n");
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!cpumask_subset(dest, cpu_possible_mask)) {
|
||||
pr_warn("Reservation is not in possible_cpu_mask\n");
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nr_irqs = cpumask_weight(dest);
|
||||
if (!nr_irqs) {
|
||||
pr_warn("Reservation for empty destination mask\n");
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (irq_domain_is_ipi_single(domain)) {
|
||||
@@ -72,14 +72,14 @@ unsigned int irq_reserve_ipi(struct irq_domain *domain,
|
||||
next = cpumask_next(next, dest);
|
||||
if (next < nr_cpu_ids) {
|
||||
pr_warn("Destination mask has holes\n");
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
virq = irq_domain_alloc_descs(-1, nr_irqs, 0, NUMA_NO_NODE);
|
||||
if (virq <= 0) {
|
||||
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,
|
||||
@@ -100,17 +100,20 @@ unsigned int irq_reserve_ipi(struct irq_domain *domain,
|
||||
|
||||
free_descs:
|
||||
irq_free_descs(virq, nr_irqs);
|
||||
return 0;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/**
|
||||
* irq_destroy_ipi() - unreserve an IPI that was previously allocated
|
||||
* @irq: linux irq number to be destroyed
|
||||
* @dest: cpumask of cpus which should have the IPI removed
|
||||
*
|
||||
* Return the IPIs allocated with irq_reserve_ipi() to the system destroying
|
||||
* all virqs associated with them.
|
||||
* The IPIs allocated with irq_reserve_ipi() are retuerned to the system
|
||||
* destroying all virqs associated with them.
|
||||
*
|
||||
* Return 0 on success or error code on failure.
|
||||
*/
|
||||
void irq_destroy_ipi(unsigned int irq)
|
||||
int irq_destroy_ipi(unsigned int irq, const struct cpumask *dest)
|
||||
{
|
||||
struct irq_data *data = irq_get_irq_data(irq);
|
||||
struct cpumask *ipimask = data ? irq_data_get_affinity_mask(data) : NULL;
|
||||
@@ -118,7 +121,7 @@ void irq_destroy_ipi(unsigned int irq)
|
||||
unsigned int nr_irqs;
|
||||
|
||||
if (!irq || !data || !ipimask)
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
domain = data->domain;
|
||||
if (WARN_ON(domain == NULL))
|
||||
@@ -126,15 +129,25 @@ void irq_destroy_ipi(unsigned int irq)
|
||||
|
||||
if (!irq_domain_is_ipi(domain)) {
|
||||
pr_warn("Trying to destroy a non IPI domain!\n");
|
||||
return;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (irq_domain_is_ipi_per_cpu(domain))
|
||||
nr_irqs = cpumask_weight(ipimask);
|
||||
else
|
||||
if (WARN_ON(!cpumask_subset(dest, ipimask)))
|
||||
/*
|
||||
* Must be destroying a subset of CPUs to which this IPI
|
||||
* was set up to target
|
||||
*/
|
||||
return -EINVAL;
|
||||
|
||||
if (irq_domain_is_ipi_per_cpu(domain)) {
|
||||
irq = irq + cpumask_first(dest) - data->common->ipi_offset;
|
||||
nr_irqs = cpumask_weight(dest);
|
||||
} else {
|
||||
nr_irqs = 1;
|
||||
}
|
||||
|
||||
irq_domain_free_irqs(irq, nr_irqs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -595,7 +595,8 @@ void __irq_put_desc_unlock(struct irq_desc *desc, unsigned long flags, bool bus)
|
||||
chip_bus_sync_unlock(desc);
|
||||
}
|
||||
|
||||
int irq_set_percpu_devid(unsigned int irq)
|
||||
int irq_set_percpu_devid_partition(unsigned int irq,
|
||||
const struct cpumask *affinity)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
|
||||
@@ -610,10 +611,33 @@ int irq_set_percpu_devid(unsigned int irq)
|
||||
if (!desc->percpu_enabled)
|
||||
return -ENOMEM;
|
||||
|
||||
if (affinity)
|
||||
desc->percpu_affinity = affinity;
|
||||
else
|
||||
desc->percpu_affinity = cpu_possible_mask;
|
||||
|
||||
irq_set_percpu_devid_flags(irq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int irq_set_percpu_devid(unsigned int irq)
|
||||
{
|
||||
return irq_set_percpu_devid_partition(irq, NULL);
|
||||
}
|
||||
|
||||
int irq_get_percpu_devid_partition(unsigned int irq, struct cpumask *affinity)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
|
||||
if (!desc || !desc->percpu_enabled)
|
||||
return -EINVAL;
|
||||
|
||||
if (affinity)
|
||||
cpumask_copy(affinity, desc->percpu_affinity);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kstat_incr_irq_this_cpu(unsigned int irq)
|
||||
{
|
||||
kstat_incr_irqs_this_cpu(irq_to_desc(irq));
|
||||
|
||||
@@ -243,14 +243,15 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node,
|
||||
EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
|
||||
|
||||
/**
|
||||
* irq_find_matching_fwnode() - Locates a domain for a given fwnode
|
||||
* @fwnode: FW descriptor of the interrupt controller
|
||||
* irq_find_matching_fwspec() - Locates a domain for a given fwspec
|
||||
* @fwspec: FW specifier for an interrupt
|
||||
* @bus_token: domain-specific data
|
||||
*/
|
||||
struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
|
||||
struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec,
|
||||
enum irq_domain_bus_token bus_token)
|
||||
{
|
||||
struct irq_domain *h, *found = NULL;
|
||||
struct fwnode_handle *fwnode = fwspec->fwnode;
|
||||
int rc;
|
||||
|
||||
/* We might want to match the legacy controller last since
|
||||
@@ -264,7 +265,9 @@ struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
|
||||
*/
|
||||
mutex_lock(&irq_domain_mutex);
|
||||
list_for_each_entry(h, &irq_domain_list, link) {
|
||||
if (h->ops->match)
|
||||
if (h->ops->select && fwspec->param_count)
|
||||
rc = h->ops->select(h, fwspec, bus_token);
|
||||
else if (h->ops->match)
|
||||
rc = h->ops->match(h, to_of_node(fwnode), bus_token);
|
||||
else
|
||||
rc = ((fwnode != NULL) && (h->fwnode == fwnode) &&
|
||||
@@ -279,7 +282,7 @@ struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode,
|
||||
mutex_unlock(&irq_domain_mutex);
|
||||
return found;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(irq_find_matching_fwnode);
|
||||
EXPORT_SYMBOL_GPL(irq_find_matching_fwspec);
|
||||
|
||||
/**
|
||||
* irq_set_default_host() - Set a "default" irq domain
|
||||
@@ -574,11 +577,9 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
|
||||
int virq;
|
||||
|
||||
if (fwspec->fwnode) {
|
||||
domain = irq_find_matching_fwnode(fwspec->fwnode,
|
||||
DOMAIN_BUS_WIRED);
|
||||
domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_WIRED);
|
||||
if (!domain)
|
||||
domain = irq_find_matching_fwnode(fwspec->fwnode,
|
||||
DOMAIN_BUS_ANY);
|
||||
domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_ANY);
|
||||
} else {
|
||||
domain = irq_default_domain;
|
||||
}
|
||||
|
||||
@@ -1407,7 +1407,7 @@ int setup_irq(unsigned int irq, struct irqaction *act)
|
||||
int retval;
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
|
||||
if (WARN_ON(irq_settings_is_per_cpu_devid(desc)))
|
||||
if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
|
||||
return -EINVAL;
|
||||
chip_bus_lock(desc);
|
||||
retval = __setup_irq(irq, desc, act);
|
||||
|
||||
Reference in New Issue
Block a user