]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/blob - rt-patches/0056-genirq-Do-not-invoke-the-affinity-callback-via-a-wor.patch
WAR:media:i2c:ov5693: add flip and mirror setting
[hercules2020/nv-tegra/linux-4.4.git] / rt-patches / 0056-genirq-Do-not-invoke-the-affinity-callback-via-a-wor.patch
1 From f2026ab95a3cee03145a08474c3feec39cbaad22 Mon Sep 17 00:00:00 2001
2 From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
3 Date: Wed, 21 Aug 2013 17:48:46 +0200
4 Subject: [PATCH 056/365] genirq: Do not invoke the affinity callback via a
5  workqueue on RT
6
7 Joe Korty reported, that __irq_set_affinity_locked() schedules a
8 workqueue while holding a rawlock which results in a might_sleep()
9 warning.
10 This patch moves the invokation into a process context so that we only
11 wakeup() a process while holding the lock.
12
13 Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
14 ---
15  include/linux/interrupt.h |  1 +
16  kernel/irq/manage.c       | 79 +++++++++++++++++++++++++++++++++++++++++++++--
17  2 files changed, 77 insertions(+), 3 deletions(-)
18
19 diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
20 index 48407e6..248380d 100644
21 --- a/include/linux/interrupt.h
22 +++ b/include/linux/interrupt.h
23 @@ -217,6 +217,7 @@ struct irq_affinity_notify {
24         unsigned int irq;
25         struct kref kref;
26         struct work_struct work;
27 +       struct list_head list;
28         void (*notify)(struct irq_affinity_notify *, const cpumask_t *mask);
29         void (*release)(struct kref *ref);
30  };
31 diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
32 index 8ca0dcd..8842388 100644
33 --- a/kernel/irq/manage.c
34 +++ b/kernel/irq/manage.c
35 @@ -183,6 +183,62 @@ static inline void
36  irq_get_pending(struct cpumask *mask, struct irq_desc *desc) { }
37  #endif
38  
39 +#ifdef CONFIG_PREEMPT_RT_FULL
40 +static void _irq_affinity_notify(struct irq_affinity_notify *notify);
41 +static struct task_struct *set_affinity_helper;
42 +static LIST_HEAD(affinity_list);
43 +static DEFINE_RAW_SPINLOCK(affinity_list_lock);
44 +
45 +static int set_affinity_thread(void *unused)
46 +{
47 +       while (1) {
48 +               struct irq_affinity_notify *notify;
49 +               int empty;
50 +
51 +               set_current_state(TASK_INTERRUPTIBLE);
52 +
53 +               raw_spin_lock_irq(&affinity_list_lock);
54 +               empty = list_empty(&affinity_list);
55 +               raw_spin_unlock_irq(&affinity_list_lock);
56 +
57 +               if (empty)
58 +                       schedule();
59 +               if (kthread_should_stop())
60 +                       break;
61 +               set_current_state(TASK_RUNNING);
62 +try_next:
63 +               notify = NULL;
64 +
65 +               raw_spin_lock_irq(&affinity_list_lock);
66 +               if (!list_empty(&affinity_list)) {
67 +                       notify = list_first_entry(&affinity_list,
68 +                                       struct irq_affinity_notify, list);
69 +                       list_del_init(&notify->list);
70 +               }
71 +               raw_spin_unlock_irq(&affinity_list_lock);
72 +
73 +               if (!notify)
74 +                       continue;
75 +               _irq_affinity_notify(notify);
76 +               goto try_next;
77 +       }
78 +       return 0;
79 +}
80 +
81 +static void init_helper_thread(void)
82 +{
83 +       if (set_affinity_helper)
84 +               return;
85 +       set_affinity_helper = kthread_run(set_affinity_thread, NULL,
86 +                       "affinity-cb");
87 +       WARN_ON(IS_ERR(set_affinity_helper));
88 +}
89 +#else
90 +
91 +static inline void init_helper_thread(void) { }
92 +
93 +#endif
94 +
95  int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask,
96                         bool force)
97  {
98 @@ -222,7 +278,17 @@ int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask,
99  
100         if (desc->affinity_notify) {
101                 kref_get(&desc->affinity_notify->kref);
102 +
103 +#ifdef CONFIG_PREEMPT_RT_FULL
104 +               raw_spin_lock(&affinity_list_lock);
105 +               if (list_empty(&desc->affinity_notify->list))
106 +                       list_add_tail(&affinity_list,
107 +                                       &desc->affinity_notify->list);
108 +               raw_spin_unlock(&affinity_list_lock);
109 +               wake_up_process(set_affinity_helper);
110 +#else
111                 schedule_work(&desc->affinity_notify->work);
112 +#endif
113         }
114         irqd_set(data, IRQD_AFFINITY_SET);
115  
116 @@ -260,10 +326,8 @@ int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m)
117  }
118  EXPORT_SYMBOL_GPL(irq_set_affinity_hint);
119  
120 -static void irq_affinity_notify(struct work_struct *work)
121 +static void _irq_affinity_notify(struct irq_affinity_notify *notify)
122  {
123 -       struct irq_affinity_notify *notify =
124 -               container_of(work, struct irq_affinity_notify, work);
125         struct irq_desc *desc = irq_to_desc(notify->irq);
126         cpumask_var_t cpumask;
127         unsigned long flags;
128 @@ -285,6 +349,13 @@ out:
129         kref_put(&notify->kref, notify->release);
130  }
131  
132 +static void irq_affinity_notify(struct work_struct *work)
133 +{
134 +       struct irq_affinity_notify *notify =
135 +               container_of(work, struct irq_affinity_notify, work);
136 +       _irq_affinity_notify(notify);
137 +}
138 +
139  /**
140   *     irq_set_affinity_notifier - control notification of IRQ affinity changes
141   *     @irq:           Interrupt for which to enable/disable notification
142 @@ -314,6 +385,8 @@ irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify)
143                 notify->irq = irq;
144                 kref_init(&notify->kref);
145                 INIT_WORK(&notify->work, irq_affinity_notify);
146 +               INIT_LIST_HEAD(&notify->list);
147 +               init_helper_thread();
148         }
149  
150         raw_spin_lock_irqsave(&desc->lock, flags);
151 -- 
152 2.7.4
153