diff options
-rw-r--r-- | arch/arm/mach-hisi/Kconfig | 1 | ||||
-rw-r--r-- | arch/metag/Kconfig | 1 | ||||
-rw-r--r-- | drivers/irqchip/Kconfig | 7 | ||||
-rw-r--r-- | drivers/irqchip/irq-armada-370-xp.c | 3 | ||||
-rw-r--r-- | drivers/irqchip/irq-bcm6345-l1.c | 3 | ||||
-rw-r--r-- | drivers/irqchip/irq-bcm7038-l1.c | 3 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3-its.c | 7 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic-v3.c | 3 | ||||
-rw-r--r-- | drivers/irqchip/irq-gic.c | 3 | ||||
-rw-r--r-- | drivers/irqchip/irq-hip04.c | 3 | ||||
-rw-r--r-- | drivers/irqchip/irq-metag-ext.c | 4 | ||||
-rw-r--r-- | drivers/irqchip/irq-mips-gic.c | 10 | ||||
-rw-r--r-- | drivers/irqchip/irq-xtensa-mx.c | 6 | ||||
-rw-r--r-- | include/linux/irq.h | 5 | ||||
-rw-r--r-- | kernel/irq/debugfs.c | 50 | ||||
-rw-r--r-- | kernel/irq/internals.h | 2 | ||||
-rw-r--r-- | kernel/irq/proc.c | 2 |
17 files changed, 104 insertions, 9 deletions
diff --git a/arch/arm/mach-hisi/Kconfig b/arch/arm/mach-hisi/Kconfig index a3b091a4d344..65a048fa08ec 100644 --- a/arch/arm/mach-hisi/Kconfig +++ b/arch/arm/mach-hisi/Kconfig @@ -39,6 +39,7 @@ config ARCH_HIP04 select HAVE_ARM_ARCH_TIMER select MCPM if SMP select MCPM_QUAD_CLUSTER if SMP + select GENERIC_IRQ_EFFECTIVE_AFF_MASK help Support for Hisilicon HiP04 SoC family diff --git a/arch/metag/Kconfig b/arch/metag/Kconfig index 5b7a45d99cfb..7d8b322e5101 100644 --- a/arch/metag/Kconfig +++ b/arch/metag/Kconfig @@ -26,6 +26,7 @@ config METAG select HAVE_SYSCALL_TRACEPOINTS select HAVE_UNDERSCORE_SYMBOL_PREFIX select IRQ_DOMAIN + select GENERIC_IRQ_EFFECTIVE_AFF_MASK select MODULES_USE_ELF_RELA select OF select OF_EARLY_FLATTREE diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index f1fd5f44d1d4..1139de9da21a 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -7,6 +7,7 @@ config ARM_GIC select IRQ_DOMAIN select IRQ_DOMAIN_HIERARCHY select MULTI_IRQ_HANDLER + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config ARM_GIC_PM bool @@ -34,6 +35,7 @@ config ARM_GIC_V3 select MULTI_IRQ_HANDLER select IRQ_DOMAIN_HIERARCHY select PARTITION_PERCPU + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config ARM_GIC_V3_ITS bool @@ -64,6 +66,7 @@ config ARMADA_370_XP_IRQ bool select GENERIC_IRQ_CHIP select PCI_MSI if PCI + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config ALPINE_MSI bool @@ -93,11 +96,13 @@ config BCM6345_L1_IRQ bool select GENERIC_IRQ_CHIP select IRQ_DOMAIN + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config BCM7038_L1_IRQ bool select GENERIC_IRQ_CHIP select IRQ_DOMAIN + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config BCM7120_L2_IRQ bool @@ -136,6 +141,7 @@ config IRQ_MIPS_CPU select GENERIC_IRQ_IPI if SYS_SUPPORTS_MULTITHREADING select IRQ_DOMAIN select IRQ_DOMAIN_HIERARCHY if GENERIC_IRQ_IPI + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config CLPS711X_IRQCHIP bool @@ -217,6 +223,7 @@ config VERSATILE_FPGA_IRQ_NR config XTENSA_MX bool select IRQ_DOMAIN + select GENERIC_IRQ_EFFECTIVE_AFF_MASK config XILINX_INTC bool diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index b207b2c3aa55..eb815676c088 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -330,6 +330,8 @@ static int armada_xp_set_affinity(struct irq_data *d, writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq)); raw_spin_unlock(&irq_controller_lock); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + return IRQ_SET_MASK_OK; } #endif @@ -363,6 +365,7 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h, } else { irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip, handle_level_irq); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq))); } irq_set_probe(virq); diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c index daa4ae89e466..43f8abe40878 100644 --- a/drivers/irqchip/irq-bcm6345-l1.c +++ b/drivers/irqchip/irq-bcm6345-l1.c @@ -231,6 +231,8 @@ static int bcm6345_l1_set_affinity(struct irq_data *d, } raw_spin_unlock_irqrestore(&intc->lock, flags); + irq_data_update_effective_affinity(d, cpumask_of(new_cpu)); + return IRQ_SET_MASK_OK_NOCOPY; } @@ -291,6 +293,7 @@ static int bcm6345_l1_map(struct irq_domain *d, unsigned int virq, irq_set_chip_and_handler(virq, &bcm6345_l1_irq_chip, handle_percpu_irq); irq_set_chip_data(virq, d->host_data); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq))); return 0; } diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c index c2662a1bfdd3..55cfb986225b 100644 --- a/drivers/irqchip/irq-bcm7038-l1.c +++ b/drivers/irqchip/irq-bcm7038-l1.c @@ -212,6 +212,8 @@ static int bcm7038_l1_set_affinity(struct irq_data *d, __bcm7038_l1_unmask(d, first_cpu); raw_spin_unlock_irqrestore(&intc->lock, flags); + irq_data_update_effective_affinity(d, cpumask_of(first_cpu)); + return 0; } @@ -299,6 +301,7 @@ static int bcm7038_l1_map(struct irq_domain *d, unsigned int virq, { irq_set_chip_and_handler(virq, &bcm7038_l1_irq_chip, handle_level_irq); irq_set_chip_data(virq, d->host_data); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq))); return 0; } diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 68932873eebc..22e228500357 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -649,6 +649,7 @@ static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val, target_col = &its_dev->its->collections[cpu]; its_send_movi(its_dev, target_col, id); its_dev->event_map.col_map[id] = cpu; + irq_data_update_effective_affinity(d, cpumask_of(cpu)); } return IRQ_SET_MASK_OK_DONE; @@ -1481,6 +1482,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq, &its_irq_chip, its_dev); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq + i))); pr_debug("ID:%d pID:%d vID:%d\n", (int)(hwirq - its_dev->event_map.lpi_base), (int) hwirq, virq + i); @@ -1495,13 +1497,16 @@ static void its_irq_domain_activate(struct irq_domain *domain, struct its_device *its_dev = irq_data_get_irq_chip_data(d); u32 event = its_get_event_id(d); const struct cpumask *cpu_mask = cpu_online_mask; + int cpu; /* get the cpu_mask of local node */ if (its_dev->its->numa_node >= 0) cpu_mask = cpumask_of_node(its_dev->its->numa_node); /* Bind the LPI to the first possible CPU */ - its_dev->event_map.col_map[event] = cpumask_first(cpu_mask); + cpu = cpumask_first(cpu_mask); + its_dev->event_map.col_map[event] = cpu; + irq_data_update_effective_affinity(d, cpumask_of(cpu)); /* Map the GIC IRQ and event to the device */ its_send_mapti(its_dev, d->hwirq, event); diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index dbffb7ab6203..511c290c4a26 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -670,6 +670,8 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, else gic_dist_wait_for_rwp(); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + return IRQ_SET_MASK_OK_DONE; } #else @@ -768,6 +770,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_domain_set_info(d, irq, hw, chip, d->host_data, handle_fasteoi_irq, NULL, NULL); irq_set_probe(irq); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); } /* LPIs */ if (hw >= 8192 && hw < GIC_ID_NR) { diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 1b1df4f770bd..20dd2ba3d603 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -344,6 +344,8 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, writel_relaxed(val | bit, reg); gic_unlock_irqrestore(flags); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + return IRQ_SET_MASK_OK_DONE; } #endif @@ -966,6 +968,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data, handle_fasteoi_irq, NULL, NULL); irq_set_probe(irq); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); } return 0; } diff --git a/drivers/irqchip/irq-hip04.c b/drivers/irqchip/irq-hip04.c index c1b4ee955dbe..5b4fd2f4e5f8 100644 --- a/drivers/irqchip/irq-hip04.c +++ b/drivers/irqchip/irq-hip04.c @@ -165,6 +165,8 @@ static int hip04_irq_set_affinity(struct irq_data *d, writel_relaxed(val | bit, reg); raw_spin_unlock(&irq_controller_lock); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + return IRQ_SET_MASK_OK; } #endif @@ -312,6 +314,7 @@ static int hip04_irq_domain_map(struct irq_domain *d, unsigned int irq, irq_set_chip_and_handler(irq, &hip04_irq_chip, handle_fasteoi_irq); irq_set_probe(irq); + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); } irq_set_chip_data(irq, d->host_data); return 0; diff --git a/drivers/irqchip/irq-metag-ext.c b/drivers/irqchip/irq-metag-ext.c index 0cdd923d1535..be7216bfb8dd 100644 --- a/drivers/irqchip/irq-metag-ext.c +++ b/drivers/irqchip/irq-metag-ext.c @@ -518,6 +518,8 @@ static int meta_intc_set_affinity(struct irq_data *data, metag_out32(TBI_TRIG_VEC(TBID_SIGNUM_TR2(thread)), vec_addr); + irq_data_update_effective_affinity(data, cpumask_of(cpu)); + return 0; } #else @@ -578,6 +580,8 @@ static int meta_intc_map(struct irq_domain *d, unsigned int irq, else irq_set_chip_and_handler(irq, &meta_intc_edge_chip, handle_edge_irq); + + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); return 0; } diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 6ab1d3afec02..6461380ff1a4 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -445,24 +445,27 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, unsigned int irq = GIC_HWIRQ_TO_SHARED(d->hwirq); cpumask_t tmp = CPU_MASK_NONE; unsigned long flags; - int i; + int i, cpu; cpumask_and(&tmp, cpumask, cpu_online_mask); if (cpumask_empty(&tmp)) return -EINVAL; + cpu = cpumask_first(&tmp); + /* Assumption : cpumask refers to a single CPU */ spin_lock_irqsave(&gic_lock, flags); /* Re-route this IRQ */ - gic_map_to_vpe(irq, mips_cm_vp_id(cpumask_first(&tmp))); + gic_map_to_vpe(irq, mips_cm_vp_id(cpu)); /* Update the pcpu_masks */ for (i = 0; i < min(gic_vpes, NR_CPUS); i++) clear_bit(irq, pcpu_masks[i].pcpu_mask); - set_bit(irq, pcpu_masks[cpumask_first(&tmp)].pcpu_mask); + set_bit(irq, pcpu_masks[cpu].pcpu_mask); cpumask_copy(irq_data_get_affinity_mask(d), cpumask); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); spin_unlock_irqrestore(&gic_lock, flags); return IRQ_SET_MASK_OK_NOCOPY; @@ -716,6 +719,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, if (err) return err; + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq))); return gic_shared_irq_domain_map(d, virq, hwirq, 0); } diff --git a/drivers/irqchip/irq-xtensa-mx.c b/drivers/irqchip/irq-xtensa-mx.c index 72a391e01011..a15a9510c904 100644 --- a/drivers/irqchip/irq-xtensa-mx.c +++ b/drivers/irqchip/irq-xtensa-mx.c @@ -32,6 +32,7 @@ static int xtensa_mx_irq_map(struct irq_domain *d, unsigned int irq, irq_set_status_flags(irq, IRQ_LEVEL); return 0; } + irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(irq))); return xtensa_irq_map(d, irq, hw); } @@ -121,9 +122,12 @@ static int xtensa_mx_irq_retrigger(struct irq_data *d) static int xtensa_mx_irq_set_affinity(struct irq_data *d, const struct cpumask *dest, bool force) { - unsigned mask = 1u << cpumask_any_and(dest, cpu_online_mask); + int cpu = cpumask_any_and(dest, cpu_online_mask); + unsigned mask = 1u << cpu; set_er(mask, MIROUT(d->hwirq - HW_IRQ_MX_BASE)); + irq_data_update_effective_affinity(d, cpumask_of(cpu)); + return 0; } diff --git a/include/linux/irq.h b/include/linux/irq.h index d4728bf6a537..b99a784635ff 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -783,7 +783,10 @@ static inline struct cpumask *irq_data_get_affinity_mask(struct irq_data *d) static inline struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d) { - return d->common->effective_affinity; + if (!cpumask_empty(d->common->effective_affinity)) + return d->common->effective_affinity; + + return d->common->affinity; } static inline void irq_data_update_effective_affinity(struct irq_data *d, const struct cpumask *m) diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c index 4d384edc0c64..c3fdb36dec30 100644 --- a/kernel/irq/debugfs.c +++ b/kernel/irq/debugfs.c @@ -5,6 +5,7 @@ */ #include <linux/irqdomain.h> #include <linux/irq.h> +#include <linux/uaccess.h> #include "internals.h" @@ -171,8 +172,55 @@ static int irq_debug_open(struct inode *inode, struct file *file) return single_open(file, irq_debug_show, inode->i_private); } +static ssize_t irq_debug_write(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct irq_desc *desc = file_inode(file)->i_private; + char buf[8] = { 0, }; + size_t size; + + size = min(sizeof(buf) - 1, count); + if (copy_from_user(buf, user_buf, size)) + return -EFAULT; + + if (!strncmp(buf, "trigger", size)) { + unsigned long flags; + int err; + + /* Try the HW interface first */ + err = irq_set_irqchip_state(irq_desc_get_irq(desc), + IRQCHIP_STATE_PENDING, true); + if (!err) + return count; + + /* + * Otherwise, try to inject via the resend interface, + * which may or may not succeed. + */ + chip_bus_lock(desc); + raw_spin_lock_irqsave(&desc->lock, flags); + + if (irq_settings_is_level(desc)) { + /* Can't do level, sorry */ + err = -EINVAL; + } else { + desc->istate |= IRQS_PENDING; + check_irq_resend(desc); + err = 0; + } + + raw_spin_unlock_irqrestore(&desc->lock, flags); + chip_bus_sync_unlock(desc); + + return err ? err : count; + } + + return count; +} + static const struct file_operations dfs_irq_ops = { .open = irq_debug_open, + .write = irq_debug_write, .read = seq_read, .llseek = seq_lseek, .release = single_release, @@ -186,7 +234,7 @@ void irq_add_debugfs_entry(unsigned int irq, struct irq_desc *desc) return; sprintf(name, "%d", irq); - desc->debugfs_file = debugfs_create_file(name, 0444, irq_dir, desc, + desc->debugfs_file = debugfs_create_file(name, 0644, irq_dir, desc, &dfs_irq_ops); } diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h index a2c48058354c..a4aa39009f0d 100644 --- a/kernel/irq/internals.h +++ b/kernel/irq/internals.h @@ -151,7 +151,7 @@ static inline void chip_bus_sync_unlock(struct irq_desc *desc) #define IRQ_GET_DESC_CHECK_PERCPU (_IRQ_DESC_CHECK | _IRQ_DESC_PERCPU) #define for_each_action_of_desc(desc, act) \ - for (act = desc->act; act; act = act->next) + for (act = desc->action; act; act = act->next) struct irq_desc * __irq_get_desc_lock(unsigned int irq, unsigned long *flags, bool bus, diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c index 7f9642a1e267..0534781724d0 100644 --- a/kernel/irq/proc.c +++ b/kernel/irq/proc.c @@ -61,7 +61,7 @@ static int show_irq_affinity(int type, struct seq_file *m) case EFFECTIVE: case EFFECTIVE_LIST: #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK - mask = desc->irq_common_data.effective_affinity; + mask = irq_data_get_effective_affinity_mask(&desc->irq_data); break; #else return -EINVAL; |