]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/5.1.12/ras-cec-convert-the-timer-callback-to-a-workqueue.patch
move all the pending queues back to their "real" places
[thirdparty/kernel/stable-queue.git] / releases / 5.1.12 / ras-cec-convert-the-timer-callback-to-a-workqueue.patch
1 From 0ade0b6240c4853cf9725924c46c10f4251639d7 Mon Sep 17 00:00:00 2001
2 From: Cong Wang <xiyou.wangcong@gmail.com>
3 Date: Tue, 16 Apr 2019 14:33:51 -0700
4 Subject: RAS/CEC: Convert the timer callback to a workqueue
5
6 From: Cong Wang <xiyou.wangcong@gmail.com>
7
8 commit 0ade0b6240c4853cf9725924c46c10f4251639d7 upstream.
9
10 cec_timer_fn() is a timer callback which reads ce_arr.array[] and
11 updates its decay values. However, it runs in interrupt context and the
12 mutex protection the CEC uses for that array, is inadequate. Convert the
13 used timer to a workqueue to keep the tasks the CEC performs preemptible
14 and thus low-prio.
15
16 [ bp: Rewrite commit message.
17 s/timer/decay/gi to make it agnostic as to what facility is used. ]
18
19 Fixes: 011d82611172 ("RAS: Add a Corrected Errors Collector")
20 Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
21 Signed-off-by: Borislav Petkov <bp@suse.de>
22 Cc: Thomas Gleixner <tglx@linutronix.de>
23 Cc: Tony Luck <tony.luck@intel.com>
24 Cc: linux-edac <linux-edac@vger.kernel.org>
25 Cc: <stable@vger.kernel.org>
26 Link: https://lkml.kernel.org/r/20190416213351.28999-2-xiyou.wangcong@gmail.com
27 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
28
29 ---
30 drivers/ras/cec.c | 46 ++++++++++++++++++++++------------------------
31 1 file changed, 22 insertions(+), 24 deletions(-)
32
33 --- a/drivers/ras/cec.c
34 +++ b/drivers/ras/cec.c
35 @@ -2,6 +2,7 @@
36 #include <linux/mm.h>
37 #include <linux/gfp.h>
38 #include <linux/kernel.h>
39 +#include <linux/workqueue.h>
40
41 #include <asm/mce.h>
42
43 @@ -123,16 +124,12 @@ static u64 dfs_pfn;
44 /* Amount of errors after which we offline */
45 static unsigned int count_threshold = COUNT_MASK;
46
47 -/*
48 - * The timer "decays" element count each timer_interval which is 24hrs by
49 - * default.
50 - */
51 -
52 -#define CEC_TIMER_DEFAULT_INTERVAL 24 * 60 * 60 /* 24 hrs */
53 -#define CEC_TIMER_MIN_INTERVAL 1 * 60 * 60 /* 1h */
54 -#define CEC_TIMER_MAX_INTERVAL 30 * 24 * 60 * 60 /* one month */
55 -static struct timer_list cec_timer;
56 -static u64 timer_interval = CEC_TIMER_DEFAULT_INTERVAL;
57 +/* Each element "decays" each decay_interval which is 24hrs by default. */
58 +#define CEC_DECAY_DEFAULT_INTERVAL 24 * 60 * 60 /* 24 hrs */
59 +#define CEC_DECAY_MIN_INTERVAL 1 * 60 * 60 /* 1h */
60 +#define CEC_DECAY_MAX_INTERVAL 30 * 24 * 60 * 60 /* one month */
61 +static struct delayed_work cec_work;
62 +static u64 decay_interval = CEC_DECAY_DEFAULT_INTERVAL;
63
64 /*
65 * Decrement decay value. We're using DECAY_BITS bits to denote decay of an
66 @@ -160,20 +157,21 @@ static void do_spring_cleaning(struct ce
67 /*
68 * @interval in seconds
69 */
70 -static void cec_mod_timer(struct timer_list *t, unsigned long interval)
71 +static void cec_mod_work(unsigned long interval)
72 {
73 unsigned long iv;
74
75 - iv = interval * HZ + jiffies;
76 -
77 - mod_timer(t, round_jiffies(iv));
78 + iv = interval * HZ;
79 + mod_delayed_work(system_wq, &cec_work, round_jiffies(iv));
80 }
81
82 -static void cec_timer_fn(struct timer_list *unused)
83 +static void cec_work_fn(struct work_struct *work)
84 {
85 + mutex_lock(&ce_mutex);
86 do_spring_cleaning(&ce_arr);
87 + mutex_unlock(&ce_mutex);
88
89 - cec_mod_timer(&cec_timer, timer_interval);
90 + cec_mod_work(decay_interval);
91 }
92
93 /*
94 @@ -374,15 +372,15 @@ static int decay_interval_set(void *data
95 {
96 *(u64 *)data = val;
97
98 - if (val < CEC_TIMER_MIN_INTERVAL)
99 + if (val < CEC_DECAY_MIN_INTERVAL)
100 return -EINVAL;
101
102 - if (val > CEC_TIMER_MAX_INTERVAL)
103 + if (val > CEC_DECAY_MAX_INTERVAL)
104 return -EINVAL;
105
106 - timer_interval = val;
107 + decay_interval = val;
108
109 - cec_mod_timer(&cec_timer, timer_interval);
110 + cec_mod_work(decay_interval);
111 return 0;
112 }
113 DEFINE_DEBUGFS_ATTRIBUTE(decay_interval_ops, u64_get, decay_interval_set, "%lld\n");
114 @@ -426,7 +424,7 @@ static int array_dump(struct seq_file *m
115
116 seq_printf(m, "Flags: 0x%x\n", ca->flags);
117
118 - seq_printf(m, "Timer interval: %lld seconds\n", timer_interval);
119 + seq_printf(m, "Decay interval: %lld seconds\n", decay_interval);
120 seq_printf(m, "Decays: %lld\n", ca->decays_done);
121
122 seq_printf(m, "Action threshold: %d\n", count_threshold);
123 @@ -472,7 +470,7 @@ static int __init create_debugfs_nodes(v
124 }
125
126 decay = debugfs_create_file("decay_interval", S_IRUSR | S_IWUSR, d,
127 - &timer_interval, &decay_interval_ops);
128 + &decay_interval, &decay_interval_ops);
129 if (!decay) {
130 pr_warn("Error creating decay_interval debugfs node!\n");
131 goto err;
132 @@ -508,8 +506,8 @@ void __init cec_init(void)
133 if (create_debugfs_nodes())
134 return;
135
136 - timer_setup(&cec_timer, cec_timer_fn, 0);
137 - cec_mod_timer(&cec_timer, CEC_TIMER_DEFAULT_INTERVAL);
138 + INIT_DELAYED_WORK(&cec_work, cec_work_fn);
139 + schedule_delayed_work(&cec_work, CEC_DECAY_DEFAULT_INTERVAL);
140
141 pr_info("Correctable Errors collector initialized.\n");
142 }