aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/manage.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq/manage.c')
-rw-r--r--kernel/irq/manage.c132
1 files changed, 107 insertions, 25 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 481a13c43b17..2486a4c1a710 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -32,24 +32,10 @@ static int __init setup_forced_irqthreads(char *arg)
32early_param("threadirqs", setup_forced_irqthreads); 32early_param("threadirqs", setup_forced_irqthreads);
33#endif 33#endif
34 34
35/** 35static void __synchronize_hardirq(struct irq_desc *desc)
36 * synchronize_irq - wait for pending IRQ handlers (on other CPUs)
37 * @irq: interrupt number to wait for
38 *
39 * This function waits for any pending IRQ handlers for this interrupt
40 * to complete before returning. If you use this function while
41 * holding a resource the IRQ handler may need you will deadlock.
42 *
43 * This function may be called - with care - from IRQ context.
44 */
45void synchronize_irq(unsigned int irq)
46{ 36{
47 struct irq_desc *desc = irq_to_desc(irq);
48 bool inprogress; 37 bool inprogress;
49 38
50 if (!desc)
51 return;
52
53 do { 39 do {
54 unsigned long flags; 40 unsigned long flags;
55 41
@@ -67,12 +53,56 @@ void synchronize_irq(unsigned int irq)
67 53
68 /* Oops, that failed? */ 54 /* Oops, that failed? */
69 } while (inprogress); 55 } while (inprogress);
56}
70 57
71 /* 58/**
72 * We made sure that no hardirq handler is running. Now verify 59 * synchronize_hardirq - wait for pending hard IRQ handlers (on other CPUs)
73 * that no threaded handlers are active. 60 * @irq: interrupt number to wait for
74 */ 61 *
75 wait_event(desc->wait_for_threads, !atomic_read(&desc->threads_active)); 62 * This function waits for any pending hard IRQ handlers for this
63 * interrupt to complete before returning. If you use this
64 * function while holding a resource the IRQ handler may need you
65 * will deadlock. It does not take associated threaded handlers
66 * into account.
67 *
68 * Do not use this for shutdown scenarios where you must be sure
69 * that all parts (hardirq and threaded handler) have completed.
70 *
71 * This function may be called - with care - from IRQ context.
72 */
73void synchronize_hardirq(unsigned int irq)
74{
75 struct irq_desc *desc = irq_to_desc(irq);
76
77 if (desc)
78 __synchronize_hardirq(desc);
79}
80EXPORT_SYMBOL(synchronize_hardirq);
81
82/**
83 * synchronize_irq - wait for pending IRQ handlers (on other CPUs)
84 * @irq: interrupt number to wait for
85 *
86 * This function waits for any pending IRQ handlers for this interrupt
87 * to complete before returning. If you use this function while
88 * holding a resource the IRQ handler may need you will deadlock.
89 *
90 * This function may be called - with care - from IRQ context.
91 */
92void synchronize_irq(unsigned int irq)
93{
94 struct irq_desc *desc = irq_to_desc(irq);
95
96 if (desc) {
97 __synchronize_hardirq(desc);
98 /*
99 * We made sure that no hardirq handler is
100 * running. Now verify that no threaded handlers are
101 * active.
102 */
103 wait_event(desc->wait_for_threads,
104 !atomic_read(&desc->threads_active));
105 }
76} 106}
77EXPORT_SYMBOL(synchronize_irq); 107EXPORT_SYMBOL(synchronize_irq);
78 108
@@ -718,7 +748,7 @@ again:
718 748
719 if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) && 749 if (!desc->threads_oneshot && !irqd_irq_disabled(&desc->irq_data) &&
720 irqd_irq_masked(&desc->irq_data)) 750 irqd_irq_masked(&desc->irq_data))
721 unmask_irq(desc); 751 unmask_threaded_irq(desc);
722 752
723out_unlock: 753out_unlock:
724 raw_spin_unlock_irq(&desc->lock); 754 raw_spin_unlock_irq(&desc->lock);
@@ -727,7 +757,7 @@ out_unlock:
727 757
728#ifdef CONFIG_SMP 758#ifdef CONFIG_SMP
729/* 759/*
730 * Check whether we need to chasnge the affinity of the interrupt thread. 760 * Check whether we need to change the affinity of the interrupt thread.
731 */ 761 */
732static void 762static void
733irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) 763irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
@@ -802,8 +832,7 @@ static irqreturn_t irq_thread_fn(struct irq_desc *desc,
802 832
803static void wake_threads_waitq(struct irq_desc *desc) 833static void wake_threads_waitq(struct irq_desc *desc)
804{ 834{
805 if (atomic_dec_and_test(&desc->threads_active) && 835 if (atomic_dec_and_test(&desc->threads_active))
806 waitqueue_active(&desc->wait_for_threads))
807 wake_up(&desc->wait_for_threads); 836 wake_up(&desc->wait_for_threads);
808} 837}
809 838
@@ -881,6 +910,33 @@ static int irq_thread(void *data)
881 return 0; 910 return 0;
882} 911}
883 912
913/**
914 * irq_wake_thread - wake the irq thread for the action identified by dev_id
915 * @irq: Interrupt line
916 * @dev_id: Device identity for which the thread should be woken
917 *
918 */
919void irq_wake_thread(unsigned int irq, void *dev_id)
920{
921 struct irq_desc *desc = irq_to_desc(irq);
922 struct irqaction *action;
923 unsigned long flags;
924
925 if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
926 return;
927
928 raw_spin_lock_irqsave(&desc->lock, flags);
929 for (action = desc->action; action; action = action->next) {
930 if (action->dev_id == dev_id) {
931 if (action->thread)
932 __irq_wake_thread(desc, action);
933 break;
934 }
935 }
936 raw_spin_unlock_irqrestore(&desc->lock, flags);
937}
938EXPORT_SYMBOL_GPL(irq_wake_thread);
939
884static void irq_setup_forced_threading(struct irqaction *new) 940static void irq_setup_forced_threading(struct irqaction *new)
885{ 941{
886 if (!force_irqthreads) 942 if (!force_irqthreads)
@@ -897,6 +953,23 @@ static void irq_setup_forced_threading(struct irqaction *new)
897 } 953 }
898} 954}
899 955
956static int irq_request_resources(struct irq_desc *desc)
957{
958 struct irq_data *d = &desc->irq_data;
959 struct irq_chip *c = d->chip;
960
961 return c->irq_request_resources ? c->irq_request_resources(d) : 0;
962}
963
964static void irq_release_resources(struct irq_desc *desc)
965{
966 struct irq_data *d = &desc->irq_data;
967 struct irq_chip *c = d->chip;
968
969 if (c->irq_release_resources)
970 c->irq_release_resources(d);
971}
972
900/* 973/*
901 * Internal function to register an irqaction - typically used to 974 * Internal function to register an irqaction - typically used to
902 * allocate special interrupts that are part of the architecture. 975 * allocate special interrupts that are part of the architecture.
@@ -1092,6 +1165,13 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
1092 } 1165 }
1093 1166
1094 if (!shared) { 1167 if (!shared) {
1168 ret = irq_request_resources(desc);
1169 if (ret) {
1170 pr_err("Failed to request resources for %s (irq %d) on irqchip %s\n",
1171 new->name, irq, desc->irq_data.chip->name);
1172 goto out_mask;
1173 }
1174
1095 init_waitqueue_head(&desc->wait_for_threads); 1175 init_waitqueue_head(&desc->wait_for_threads);
1096 1176
1097 /* Setup the type (level, edge polarity) if configured: */ 1177 /* Setup the type (level, edge polarity) if configured: */
@@ -1262,8 +1342,10 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
1262 *action_ptr = action->next; 1342 *action_ptr = action->next;
1263 1343
1264 /* If this was the last handler, shut down the IRQ line: */ 1344 /* If this was the last handler, shut down the IRQ line: */
1265 if (!desc->action) 1345 if (!desc->action) {
1266 irq_shutdown(desc); 1346 irq_shutdown(desc);
1347 irq_release_resources(desc);
1348 }
1267 1349
1268#ifdef CONFIG_SMP 1350#ifdef CONFIG_SMP
1269 /* make sure affinity_hint is cleaned up */ 1351 /* make sure affinity_hint is cleaned up */