aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq')
-rw-r--r--kernel/irq/chip.c31
-rw-r--r--kernel/irq/irqdomain.c4
-rw-r--r--kernel/irq/manage.c46
-rw-r--r--kernel/irq/proc.c2
-rw-r--r--kernel/irq/resend.c8
-rw-r--r--kernel/irq/spurious.c7
6 files changed, 80 insertions, 18 deletions
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 57d86d07221e..cbd97ce0b000 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -90,27 +90,41 @@ int irq_set_handler_data(unsigned int irq, void *data)
90EXPORT_SYMBOL(irq_set_handler_data); 90EXPORT_SYMBOL(irq_set_handler_data);
91 91
92/** 92/**
93 * irq_set_msi_desc - set MSI descriptor data for an irq 93 * irq_set_msi_desc_off - set MSI descriptor data for an irq at offset
94 * @irq: Interrupt number 94 * @irq_base: Interrupt number base
95 * @entry: Pointer to MSI descriptor data 95 * @irq_offset: Interrupt number offset
96 * @entry: Pointer to MSI descriptor data
96 * 97 *
97 * Set the MSI descriptor entry for an irq 98 * Set the MSI descriptor entry for an irq at offset
98 */ 99 */
99int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry) 100int irq_set_msi_desc_off(unsigned int irq_base, unsigned int irq_offset,
101 struct msi_desc *entry)
100{ 102{
101 unsigned long flags; 103 unsigned long flags;
102 struct irq_desc *desc = irq_get_desc_lock(irq, &flags, IRQ_GET_DESC_CHECK_GLOBAL); 104 struct irq_desc *desc = irq_get_desc_lock(irq_base + irq_offset, &flags, IRQ_GET_DESC_CHECK_GLOBAL);
103 105
104 if (!desc) 106 if (!desc)
105 return -EINVAL; 107 return -EINVAL;
106 desc->irq_data.msi_desc = entry; 108 desc->irq_data.msi_desc = entry;
107 if (entry) 109 if (entry && !irq_offset)
108 entry->irq = irq; 110 entry->irq = irq_base;
109 irq_put_desc_unlock(desc, flags); 111 irq_put_desc_unlock(desc, flags);
110 return 0; 112 return 0;
111} 113}
112 114
113/** 115/**
116 * irq_set_msi_desc - set MSI descriptor data for an irq
117 * @irq: Interrupt number
118 * @entry: Pointer to MSI descriptor data
119 *
120 * Set the MSI descriptor entry for an irq
121 */
122int irq_set_msi_desc(unsigned int irq, struct msi_desc *entry)
123{
124 return irq_set_msi_desc_off(irq, 0, entry);
125}
126
127/**
114 * irq_set_chip_data - set irq chip data for an irq 128 * irq_set_chip_data - set irq chip data for an irq
115 * @irq: Interrupt number 129 * @irq: Interrupt number
116 * @data: Pointer to chip specific data 130 * @data: Pointer to chip specific data
@@ -272,6 +286,7 @@ void handle_nested_irq(unsigned int irq)
272 286
273 raw_spin_lock_irq(&desc->lock); 287 raw_spin_lock_irq(&desc->lock);
274 288
289 desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
275 kstat_incr_irqs_this_cpu(irq, desc); 290 kstat_incr_irqs_this_cpu(irq, desc);
276 291
277 action = desc->action; 292 action = desc->action;
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 4e69e24d3d7d..96f3a1d9c379 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -177,8 +177,8 @@ struct irq_domain *irq_domain_add_simple(struct device_node *of_node,
177 irq_base = irq_alloc_descs(first_irq, first_irq, size, 177 irq_base = irq_alloc_descs(first_irq, first_irq, size,
178 of_node_to_nid(of_node)); 178 of_node_to_nid(of_node));
179 if (irq_base < 0) { 179 if (irq_base < 0) {
180 WARN(1, "Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n", 180 pr_info("Cannot allocate irq_descs @ IRQ%d, assuming pre-allocated\n",
181 first_irq); 181 first_irq);
182 irq_base = first_irq; 182 irq_base = first_irq;
183 } 183 }
184 } else 184 } else
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 4c69326aa773..fa17855ca65a 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -16,6 +16,7 @@
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/sched.h> 18#include <linux/sched.h>
19#include <linux/sched/rt.h>
19#include <linux/task_work.h> 20#include <linux/task_work.h>
20 21
21#include "internals.h" 22#include "internals.h"
@@ -616,6 +617,22 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
616 return ret; 617 return ret;
617} 618}
618 619
620#ifdef CONFIG_HARDIRQS_SW_RESEND
621int irq_set_parent(int irq, int parent_irq)
622{
623 unsigned long flags;
624 struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);
625
626 if (!desc)
627 return -EINVAL;
628
629 desc->parent_irq = parent_irq;
630
631 irq_put_desc_unlock(desc, flags);
632 return 0;
633}
634#endif
635
619/* 636/*
620 * Default primary interrupt handler for threaded interrupts. Is 637 * Default primary interrupt handler for threaded interrupts. Is
621 * assigned as primary handler when request_threaded_irq is called 638 * assigned as primary handler when request_threaded_irq is called
@@ -716,6 +733,7 @@ static void
716irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) 733irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
717{ 734{
718 cpumask_var_t mask; 735 cpumask_var_t mask;
736 bool valid = true;
719 737
720 if (!test_and_clear_bit(IRQTF_AFFINITY, &action->thread_flags)) 738 if (!test_and_clear_bit(IRQTF_AFFINITY, &action->thread_flags))
721 return; 739 return;
@@ -730,10 +748,18 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
730 } 748 }
731 749
732 raw_spin_lock_irq(&desc->lock); 750 raw_spin_lock_irq(&desc->lock);
733 cpumask_copy(mask, desc->irq_data.affinity); 751 /*
752 * This code is triggered unconditionally. Check the affinity
753 * mask pointer. For CPU_MASK_OFFSTACK=n this is optimized out.
754 */
755 if (desc->irq_data.affinity)
756 cpumask_copy(mask, desc->irq_data.affinity);
757 else
758 valid = false;
734 raw_spin_unlock_irq(&desc->lock); 759 raw_spin_unlock_irq(&desc->lock);
735 760
736 set_cpus_allowed_ptr(current, mask); 761 if (valid)
762 set_cpus_allowed_ptr(current, mask);
737 free_cpumask_var(mask); 763 free_cpumask_var(mask);
738} 764}
739#else 765#else
@@ -793,7 +819,7 @@ static void irq_thread_dtor(struct callback_head *unused)
793 action = kthread_data(tsk); 819 action = kthread_data(tsk);
794 820
795 pr_err("exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n", 821 pr_err("exiting task \"%s\" (%d) is an active IRQ thread (irq %d)\n",
796 tsk->comm ? tsk->comm : "", tsk->pid, action->irq); 822 tsk->comm, tsk->pid, action->irq);
797 823
798 824
799 desc = irq_to_desc(action->irq); 825 desc = irq_to_desc(action->irq);
@@ -833,6 +859,8 @@ static int irq_thread(void *data)
833 init_task_work(&on_exit_work, irq_thread_dtor); 859 init_task_work(&on_exit_work, irq_thread_dtor);
834 task_work_add(current, &on_exit_work, false); 860 task_work_add(current, &on_exit_work, false);
835 861
862 irq_thread_check_affinity(desc, action);
863
836 while (!irq_wait_for_interrupt(action)) { 864 while (!irq_wait_for_interrupt(action)) {
837 irqreturn_t action_ret; 865 irqreturn_t action_ret;
838 866
@@ -936,6 +964,16 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
936 */ 964 */
937 get_task_struct(t); 965 get_task_struct(t);
938 new->thread = t; 966 new->thread = t;
967 /*
968 * Tell the thread to set its affinity. This is
969 * important for shared interrupt handlers as we do
970 * not invoke setup_affinity() for the secondary
971 * handlers as everything is already set up. Even for
972 * interrupts marked with IRQF_NO_BALANCE this is
973 * correct as we want the thread to move to the cpu(s)
974 * on which the requesting code placed the interrupt.
975 */
976 set_bit(IRQTF_AFFINITY, &new->thread_flags);
939 } 977 }
940 978
941 if (!alloc_cpumask_var(&mask, GFP_KERNEL)) { 979 if (!alloc_cpumask_var(&mask, GFP_KERNEL)) {
@@ -1487,6 +1525,7 @@ void enable_percpu_irq(unsigned int irq, unsigned int type)
1487out: 1525out:
1488 irq_put_desc_unlock(desc, flags); 1526 irq_put_desc_unlock(desc, flags);
1489} 1527}
1528EXPORT_SYMBOL_GPL(enable_percpu_irq);
1490 1529
1491void disable_percpu_irq(unsigned int irq) 1530void disable_percpu_irq(unsigned int irq)
1492{ 1531{
@@ -1500,6 +1539,7 @@ void disable_percpu_irq(unsigned int irq)
1500 irq_percpu_disable(desc, cpu); 1539 irq_percpu_disable(desc, cpu);
1501 irq_put_desc_unlock(desc, flags); 1540 irq_put_desc_unlock(desc, flags);
1502} 1541}
1542EXPORT_SYMBOL_GPL(disable_percpu_irq);
1503 1543
1504/* 1544/*
1505 * Internal function to unregister a percpu irqaction. 1545 * Internal function to unregister a percpu irqaction.
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index 4bd4faa6323a..397db02209ed 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -76,7 +76,7 @@ static int irq_affinity_list_proc_show(struct seq_file *m, void *v)
76static ssize_t write_irq_affinity(int type, struct file *file, 76static ssize_t write_irq_affinity(int type, struct file *file,
77 const char __user *buffer, size_t count, loff_t *pos) 77 const char __user *buffer, size_t count, loff_t *pos)
78{ 78{
79 unsigned int irq = (int)(long)PDE(file->f_path.dentry->d_inode)->data; 79 unsigned int irq = (int)(long)PDE(file_inode(file))->data;
80 cpumask_var_t new_value; 80 cpumask_var_t new_value;
81 int err; 81 int err;
82 82
diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c
index 6454db7b6a4d..9065107f083e 100644
--- a/kernel/irq/resend.c
+++ b/kernel/irq/resend.c
@@ -74,6 +74,14 @@ void check_irq_resend(struct irq_desc *desc, unsigned int irq)
74 if (!desc->irq_data.chip->irq_retrigger || 74 if (!desc->irq_data.chip->irq_retrigger ||
75 !desc->irq_data.chip->irq_retrigger(&desc->irq_data)) { 75 !desc->irq_data.chip->irq_retrigger(&desc->irq_data)) {
76#ifdef CONFIG_HARDIRQS_SW_RESEND 76#ifdef CONFIG_HARDIRQS_SW_RESEND
77 /*
78 * If the interrupt has a parent irq and runs
79 * in the thread context of the parent irq,
80 * retrigger the parent.
81 */
82 if (desc->parent_irq &&
83 irq_settings_is_nested_thread(desc))
84 irq = desc->parent_irq;
77 /* Set it pending and activate the softirq: */ 85 /* Set it pending and activate the softirq: */
78 set_bit(irq, irqs_resend); 86 set_bit(irq, irqs_resend);
79 tasklet_schedule(&resend_tasklet); 87 tasklet_schedule(&resend_tasklet);
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index 611cd6003c45..7b5f012bde9d 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -80,13 +80,11 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force)
80 80
81 /* 81 /*
82 * All handlers must agree on IRQF_SHARED, so we test just the 82 * All handlers must agree on IRQF_SHARED, so we test just the
83 * first. Check for action->next as well. 83 * first.
84 */ 84 */
85 action = desc->action; 85 action = desc->action;
86 if (!action || !(action->flags & IRQF_SHARED) || 86 if (!action || !(action->flags & IRQF_SHARED) ||
87 (action->flags & __IRQF_TIMER) || 87 (action->flags & __IRQF_TIMER))
88 (action->handler(irq, action->dev_id) == IRQ_HANDLED) ||
89 !action->next)
90 goto out; 88 goto out;
91 89
92 /* Already running on another processor */ 90 /* Already running on another processor */
@@ -104,6 +102,7 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force)
104 do { 102 do {
105 if (handle_irq_event(desc) == IRQ_HANDLED) 103 if (handle_irq_event(desc) == IRQ_HANDLED)
106 ret = IRQ_HANDLED; 104 ret = IRQ_HANDLED;
105 /* Make sure that there is still a valid action */
107 action = desc->action; 106 action = desc->action;
108 } while ((desc->istate & IRQS_PENDING) && action); 107 } while ((desc->istate & IRQS_PENDING) && action);
109 desc->istate &= ~IRQS_POLL_INPROGRESS; 108 desc->istate &= ~IRQS_POLL_INPROGRESS;