diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-26 14:39:20 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-26 14:39:20 -0800 |
commit | dec0029a59779d8279dde663ef8abe9824ee5773 (patch) | |
tree | f4958e8af2877fc5227f688727d22ce9ebf38939 | |
parent | 02fc87b117a9b9ec325089d098fce86ed11966bd (diff) | |
parent | 75f1133873d6a1276d3c19918b7c94975840f990 (diff) | |
download | lwn-dec0029a59779d8279dde663ef8abe9824ee5773.tar.gz lwn-dec0029a59779d8279dde663ef8abe9824ee5773.zip |
Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq fixes from Thomas Glexiner:
- unbreak the irq trigger type check for legacy platforms
- a handful fixes for ARM GIC v3/4 interrupt controllers
- a few trivial fixes all over the place
* 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
genirq/matrix: Make - vs ?: Precedence explicit
irqchip/imgpdc: Use resource_size function on resource object
irqchip/qcom: Fix u32 comparison with value less than zero
irqchip/exiu: Fix return value check in exiu_init()
irqchip/gic-v3-its: Remove artificial dependency on PCI
irqchip/gic-v4: Add forward definition of struct irq_domain_ops
irqchip/gic-v3: pr_err() strings should end with newlines
irqchip/s3c24xx: pr_err() strings should end with newlines
irqchip/gic-v3: Fix ppi-partitions lookup
irqchip/gic-v4: Clear IRQ_DISABLE_UNLAZY again if mapping fails
genirq: Track whether the trigger type has been set
-rw-r--r-- | drivers/irqchip/Kconfig | 7 | ||||
-rw-r--r-- | drivers/irqchip/Makefile | 3 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 11 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v4.c | 7 | ||||
-rw-r--r-- | drivers/irqchip/irq-imgpdc.c | 2 | ||||
-rw-r--r-- | drivers/irqchip/irq-s3c24xx.c | 4 | ||||
-rw-r--r-- | drivers/irqchip/irq-sni-exiu.c | 4 | ||||
-rw-r--r-- | drivers/irqchip/qcom-irq-combiner.c | 2 | ||||
-rw-r--r-- | include/linux/irq.h | 11 | ||||
-rw-r--r-- | include/linux/irqchip/arm-gic-v4.h | 1 | ||||
-rw-r--r-- | kernel/irq/manage.c | 13 | ||||
-rw-r--r-- | kernel/irq/matrix.c | 2 |
12 files changed, 52 insertions, 15 deletions
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 53380bd72ea4..c70476b34a53 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -41,8 +41,15 @@ config ARM_GIC_V3 config ARM_GIC_V3_ITS bool + select GENERIC_MSI_IRQ_DOMAIN + default ARM_GIC_V3 + +config ARM_GIC_V3_ITS_PCI + bool + depends on ARM_GIC_V3_ITS depends on PCI depends on PCI_MSI + default ARM_GIC_V3_ITS config ARM_NVIC bool diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index dae7282bfdef..d2df34a54d38 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -30,7 +30,8 @@ obj-$(CONFIG_ARM_GIC_PM) += irq-gic-pm.o obj-$(CONFIG_ARCH_REALVIEW) += irq-gic-realview.o obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o -obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-pci-msi.o irq-gic-v3-its-platform-msi.o irq-gic-v4.o +obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-platform-msi.o irq-gic-v4.o +obj-$(CONFIG_ARM_GIC_V3_ITS_PCI) += irq-gic-v3-its-pci-msi.o obj-$(CONFIG_PARTITION_PERCPU) += irq-partition-percpu.o obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o obj-$(CONFIG_ARM_NVIC) += irq-nvic.o diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 17221143f505..b56c3e23f0af 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -1103,18 +1103,18 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node) int nr_parts; struct partition_affinity *parts; - parts_node = of_find_node_by_name(gic_node, "ppi-partitions"); + parts_node = of_get_child_by_name(gic_node, "ppi-partitions"); if (!parts_node) return; nr_parts = of_get_child_count(parts_node); if (!nr_parts) - return; + goto out_put_node; parts = kzalloc(sizeof(*parts) * nr_parts, GFP_KERNEL); if (WARN_ON(!parts)) - return; + goto out_put_node; for_each_child_of_node(parts_node, child_part) { struct partition_affinity *part; @@ -1181,6 +1181,9 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node) gic_data.ppi_descs[i] = desc; } + +out_put_node: + of_node_put(parts_node); } static void __init gic_of_setup_kvm_info(struct device_node *node) @@ -1523,7 +1526,7 @@ gic_acpi_init(struct acpi_subtable_header *header, const unsigned long end) err = gic_validate_dist_version(acpi_data.dist_base); if (err) { - pr_err("No distributor detected at @%p, giving up", + pr_err("No distributor detected at @%p, giving up\n", acpi_data.dist_base); goto out_dist_unmap; } diff --git a/drivers/irqchip/irq-gic-v4.c b/drivers/irqchip/irq-gic-v4.c index cd0bcc3b7e33..dba9d67cb9c1 100644 --- a/drivers/irqchip/irq-gic-v4.c +++ b/drivers/irqchip/irq-gic-v4.c @@ -177,6 +177,7 @@ int its_map_vlpi(int irq, struct its_vlpi_map *map) .map = map, }, }; + int ret; /* * The host will never see that interrupt firing again, so it @@ -184,7 +185,11 @@ int its_map_vlpi(int irq, struct its_vlpi_map *map) */ irq_set_status_flags(irq, IRQ_DISABLE_UNLAZY); - return irq_set_vcpu_affinity(irq, &info); + ret = irq_set_vcpu_affinity(irq, &info); + if (ret) + irq_clear_status_flags(irq, IRQ_DISABLE_UNLAZY); + + return ret; } int its_get_vlpi(int irq, struct its_vlpi_map *map) diff --git a/drivers/irqchip/irq-imgpdc.c b/drivers/irqchip/irq-imgpdc.c index 1f59998e03f8..e80263e16c4c 100644 --- a/drivers/irqchip/irq-imgpdc.c +++ b/drivers/irqchip/irq-imgpdc.c @@ -325,7 +325,7 @@ static int pdc_intc_probe(struct platform_device *pdev) /* Ioremap the registers */ priv->pdc_base = devm_ioremap(&pdev->dev, res_regs->start, - res_regs->end - res_regs->start); + resource_size(res_regs)); if (!priv->pdc_base) return -EIO; diff --git a/drivers/irqchip/irq-s3c24xx.c b/drivers/irqchip/irq-s3c24xx.c index c25ce5af091a..ec0e6a8cdb75 100644 --- a/drivers/irqchip/irq-s3c24xx.c +++ b/drivers/irqchip/irq-s3c24xx.c @@ -156,7 +156,7 @@ static int s3c_irq_type(struct irq_data *data, unsigned int type) irq_set_handler(data->irq, handle_level_irq); break; default: - pr_err("No such irq type %d", type); + pr_err("No such irq type %d\n", type); return -EINVAL; } @@ -204,7 +204,7 @@ static int s3c_irqext_type_set(void __iomem *gpcon_reg, break; default: - pr_err("No such irq type %d", type); + pr_err("No such irq type %d\n", type); return -EINVAL; } diff --git a/drivers/irqchip/irq-sni-exiu.c b/drivers/irqchip/irq-sni-exiu.c index 1b6e2f7c59af..1927b2f36ff6 100644 --- a/drivers/irqchip/irq-sni-exiu.c +++ b/drivers/irqchip/irq-sni-exiu.c @@ -196,8 +196,8 @@ static int __init exiu_init(struct device_node *node, } data->base = of_iomap(node, 0); - if (IS_ERR(data->base)) { - err = PTR_ERR(data->base); + if (!data->base) { + err = -ENODEV; goto out_free; } diff --git a/drivers/irqchip/qcom-irq-combiner.c b/drivers/irqchip/qcom-irq-combiner.c index 6aa3ea479214..f31265937439 100644 --- a/drivers/irqchip/qcom-irq-combiner.c +++ b/drivers/irqchip/qcom-irq-combiner.c @@ -238,7 +238,7 @@ static int __init combiner_probe(struct platform_device *pdev) { struct combiner *combiner; size_t alloc_sz; - u32 nregs; + int nregs; int err; nregs = count_registers(pdev); diff --git a/include/linux/irq.h b/include/linux/irq.h index b01d06db9101..e140f69163b6 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -211,6 +211,7 @@ struct irq_data { * IRQD_MANAGED_SHUTDOWN - Interrupt was shutdown due to empty affinity * mask. Applies only to affinity managed irqs. * IRQD_SINGLE_TARGET - IRQ allows only a single affinity target + * IRQD_DEFAULT_TRIGGER_SET - Expected trigger already been set */ enum { IRQD_TRIGGER_MASK = 0xf, @@ -231,6 +232,7 @@ enum { IRQD_IRQ_STARTED = (1 << 22), IRQD_MANAGED_SHUTDOWN = (1 << 23), IRQD_SINGLE_TARGET = (1 << 24), + IRQD_DEFAULT_TRIGGER_SET = (1 << 25), }; #define __irqd_to_state(d) ACCESS_PRIVATE((d)->common, state_use_accessors) @@ -260,18 +262,25 @@ static inline void irqd_mark_affinity_was_set(struct irq_data *d) __irqd_to_state(d) |= IRQD_AFFINITY_SET; } +static inline bool irqd_trigger_type_was_set(struct irq_data *d) +{ + return __irqd_to_state(d) & IRQD_DEFAULT_TRIGGER_SET; +} + static inline u32 irqd_get_trigger_type(struct irq_data *d) { return __irqd_to_state(d) & IRQD_TRIGGER_MASK; } /* - * Must only be called inside irq_chip.irq_set_type() functions. + * Must only be called inside irq_chip.irq_set_type() functions or + * from the DT/ACPI setup code. */ static inline void irqd_set_trigger_type(struct irq_data *d, u32 type) { __irqd_to_state(d) &= ~IRQD_TRIGGER_MASK; __irqd_to_state(d) |= type & IRQD_TRIGGER_MASK; + __irqd_to_state(d) |= IRQD_DEFAULT_TRIGGER_SET; } static inline bool irqd_is_level_type(struct irq_data *d) diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h index 447da8ca2156..fa683ea5c769 100644 --- a/include/linux/irqchip/arm-gic-v4.h +++ b/include/linux/irqchip/arm-gic-v4.h @@ -109,6 +109,7 @@ int its_get_vlpi(int irq, struct its_vlpi_map *map); int its_unmap_vlpi(int irq); int its_prop_update_vlpi(int irq, u8 config, bool inv); +struct irq_domain_ops; int its_init_v4(struct irq_domain *domain, const struct irq_domain_ops *ops); #endif diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 2ff1c0c82fc9..0f922729bab9 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -1246,7 +1246,18 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) * set the trigger type must match. Also all must * agree on ONESHOT. */ - unsigned int oldtype = irqd_get_trigger_type(&desc->irq_data); + unsigned int oldtype; + + /* + * If nobody did set the configuration before, inherit + * the one provided by the requester. + */ + if (irqd_trigger_type_was_set(&desc->irq_data)) { + oldtype = irqd_get_trigger_type(&desc->irq_data); + } else { + oldtype = new->flags & IRQF_TRIGGER_MASK; + irqd_set_trigger_type(&desc->irq_data, oldtype); + } if (!((old->flags & new->flags) & IRQF_SHARED) || (oldtype != (new->flags & IRQF_TRIGGER_MASK)) || diff --git a/kernel/irq/matrix.c b/kernel/irq/matrix.c index a3cbbc8191c5..7df2480005f8 100644 --- a/kernel/irq/matrix.c +++ b/kernel/irq/matrix.c @@ -384,7 +384,7 @@ unsigned int irq_matrix_available(struct irq_matrix *m, bool cpudown) { struct cpumap *cm = this_cpu_ptr(m->maps); - return m->global_available - cpudown ? cm->available : 0; + return (m->global_available - cpudown) ? cm->available : 0; } /** |