From: Greg Kroah-Hartman Date: Mon, 17 Jun 2019 09:29:42 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v5.1.11~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4edac94b6be5cc150b1b64c1a17c42ec0140606c;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches added patches: ras-cec-convert-the-timer-callback-to-a-workqueue.patch ras-cec-fix-binary-search-function.patch timekeeping-repair-ktime_get_coarse-granularity.patch --- diff --git a/queue-4.19/ras-cec-convert-the-timer-callback-to-a-workqueue.patch b/queue-4.19/ras-cec-convert-the-timer-callback-to-a-workqueue.patch new file mode 100644 index 00000000000..259ba9e44b6 --- /dev/null +++ b/queue-4.19/ras-cec-convert-the-timer-callback-to-a-workqueue.patch @@ -0,0 +1,142 @@ +From 0ade0b6240c4853cf9725924c46c10f4251639d7 Mon Sep 17 00:00:00 2001 +From: Cong Wang +Date: Tue, 16 Apr 2019 14:33:51 -0700 +Subject: RAS/CEC: Convert the timer callback to a workqueue + +From: Cong Wang + +commit 0ade0b6240c4853cf9725924c46c10f4251639d7 upstream. + +cec_timer_fn() is a timer callback which reads ce_arr.array[] and +updates its decay values. However, it runs in interrupt context and the +mutex protection the CEC uses for that array, is inadequate. Convert the +used timer to a workqueue to keep the tasks the CEC performs preemptible +and thus low-prio. + + [ bp: Rewrite commit message. + s/timer/decay/gi to make it agnostic as to what facility is used. ] + +Fixes: 011d82611172 ("RAS: Add a Corrected Errors Collector") +Signed-off-by: Cong Wang +Signed-off-by: Borislav Petkov +Cc: Thomas Gleixner +Cc: Tony Luck +Cc: linux-edac +Cc: +Link: https://lkml.kernel.org/r/20190416213351.28999-2-xiyou.wangcong@gmail.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ras/cec.c | 46 ++++++++++++++++++++++------------------------ + 1 file changed, 22 insertions(+), 24 deletions(-) + +--- a/drivers/ras/cec.c ++++ b/drivers/ras/cec.c +@@ -2,6 +2,7 @@ + #include + #include + #include ++#include + + #include + +@@ -123,16 +124,12 @@ static u64 dfs_pfn; + /* Amount of errors after which we offline */ + static unsigned int count_threshold = COUNT_MASK; + +-/* +- * The timer "decays" element count each timer_interval which is 24hrs by +- * default. +- */ +- +-#define CEC_TIMER_DEFAULT_INTERVAL 24 * 60 * 60 /* 24 hrs */ +-#define CEC_TIMER_MIN_INTERVAL 1 * 60 * 60 /* 1h */ +-#define CEC_TIMER_MAX_INTERVAL 30 * 24 * 60 * 60 /* one month */ +-static struct timer_list cec_timer; +-static u64 timer_interval = CEC_TIMER_DEFAULT_INTERVAL; ++/* Each element "decays" each decay_interval which is 24hrs by default. */ ++#define CEC_DECAY_DEFAULT_INTERVAL 24 * 60 * 60 /* 24 hrs */ ++#define CEC_DECAY_MIN_INTERVAL 1 * 60 * 60 /* 1h */ ++#define CEC_DECAY_MAX_INTERVAL 30 * 24 * 60 * 60 /* one month */ ++static struct delayed_work cec_work; ++static u64 decay_interval = CEC_DECAY_DEFAULT_INTERVAL; + + /* + * Decrement decay value. We're using DECAY_BITS bits to denote decay of an +@@ -160,20 +157,21 @@ static void do_spring_cleaning(struct ce + /* + * @interval in seconds + */ +-static void cec_mod_timer(struct timer_list *t, unsigned long interval) ++static void cec_mod_work(unsigned long interval) + { + unsigned long iv; + +- iv = interval * HZ + jiffies; +- +- mod_timer(t, round_jiffies(iv)); ++ iv = interval * HZ; ++ mod_delayed_work(system_wq, &cec_work, round_jiffies(iv)); + } + +-static void cec_timer_fn(struct timer_list *unused) ++static void cec_work_fn(struct work_struct *work) + { ++ mutex_lock(&ce_mutex); + do_spring_cleaning(&ce_arr); ++ mutex_unlock(&ce_mutex); + +- cec_mod_timer(&cec_timer, timer_interval); ++ cec_mod_work(decay_interval); + } + + /* +@@ -374,15 +372,15 @@ static int decay_interval_set(void *data + { + *(u64 *)data = val; + +- if (val < CEC_TIMER_MIN_INTERVAL) ++ if (val < CEC_DECAY_MIN_INTERVAL) + return -EINVAL; + +- if (val > CEC_TIMER_MAX_INTERVAL) ++ if (val > CEC_DECAY_MAX_INTERVAL) + return -EINVAL; + +- timer_interval = val; ++ decay_interval = val; + +- cec_mod_timer(&cec_timer, timer_interval); ++ cec_mod_work(decay_interval); + return 0; + } + DEFINE_DEBUGFS_ATTRIBUTE(decay_interval_ops, u64_get, decay_interval_set, "%lld\n"); +@@ -426,7 +424,7 @@ static int array_dump(struct seq_file *m + + seq_printf(m, "Flags: 0x%x\n", ca->flags); + +- seq_printf(m, "Timer interval: %lld seconds\n", timer_interval); ++ seq_printf(m, "Decay interval: %lld seconds\n", decay_interval); + seq_printf(m, "Decays: %lld\n", ca->decays_done); + + seq_printf(m, "Action threshold: %d\n", count_threshold); +@@ -472,7 +470,7 @@ static int __init create_debugfs_nodes(v + } + + decay = debugfs_create_file("decay_interval", S_IRUSR | S_IWUSR, d, +- &timer_interval, &decay_interval_ops); ++ &decay_interval, &decay_interval_ops); + if (!decay) { + pr_warn("Error creating decay_interval debugfs node!\n"); + goto err; +@@ -508,8 +506,8 @@ void __init cec_init(void) + if (create_debugfs_nodes()) + return; + +- timer_setup(&cec_timer, cec_timer_fn, 0); +- cec_mod_timer(&cec_timer, CEC_TIMER_DEFAULT_INTERVAL); ++ INIT_DELAYED_WORK(&cec_work, cec_work_fn); ++ schedule_delayed_work(&cec_work, CEC_DECAY_DEFAULT_INTERVAL); + + pr_info("Correctable Errors collector initialized.\n"); + } diff --git a/queue-4.19/ras-cec-fix-binary-search-function.patch b/queue-4.19/ras-cec-fix-binary-search-function.patch new file mode 100644 index 00000000000..2c4e4170d56 --- /dev/null +++ b/queue-4.19/ras-cec-fix-binary-search-function.patch @@ -0,0 +1,91 @@ +From f3c74b38a55aefe1004200d15a83f109b510068c Mon Sep 17 00:00:00 2001 +From: Borislav Petkov +Date: Sat, 20 Apr 2019 13:27:51 +0200 +Subject: RAS/CEC: Fix binary search function + +From: Borislav Petkov + +commit f3c74b38a55aefe1004200d15a83f109b510068c upstream. + +Switch to using Donald Knuth's binary search algorithm (The Art of +Computer Programming, vol. 3, section 6.2.1). This should've been done +from the very beginning but the author must've been smoking something +very potent at the time. + +The problem with the current one was that it would return the wrong +element index in certain situations: + + https://lkml.kernel.org/r/CAM_iQpVd02zkVJ846cj-Fg1yUNuz6tY5q1Vpj4LrXmE06dPYYg@mail.gmail.com + +and the noodling code after the loop was fishy at best. + +So switch to using Knuth's binary search. The final result is much +cleaner and straightforward. + +Fixes: 011d82611172 ("RAS: Add a Corrected Errors Collector") +Reported-by: Cong Wang +Signed-off-by: Borislav Petkov +Cc: Tony Luck +Cc: linux-edac +Cc: +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/ras/cec.c | 34 ++++++++++++++++++++-------------- + 1 file changed, 20 insertions(+), 14 deletions(-) + +--- a/drivers/ras/cec.c ++++ b/drivers/ras/cec.c +@@ -181,32 +181,38 @@ static void cec_work_fn(struct work_stru + */ + static int __find_elem(struct ce_array *ca, u64 pfn, unsigned int *to) + { ++ int min = 0, max = ca->n - 1; + u64 this_pfn; +- int min = 0, max = ca->n; + +- while (min < max) { +- int tmp = (max + min) >> 1; ++ while (min <= max) { ++ int i = (min + max) >> 1; + +- this_pfn = PFN(ca->array[tmp]); ++ this_pfn = PFN(ca->array[i]); + + if (this_pfn < pfn) +- min = tmp + 1; ++ min = i + 1; + else if (this_pfn > pfn) +- max = tmp; +- else { +- min = tmp; +- break; ++ max = i - 1; ++ else if (this_pfn == pfn) { ++ if (to) ++ *to = i; ++ ++ return i; + } + } + ++ /* ++ * When the loop terminates without finding @pfn, min has the index of ++ * the element slot where the new @pfn should be inserted. The loop ++ * terminates when min > max, which means the min index points to the ++ * bigger element while the max index to the smaller element, in-between ++ * which the new @pfn belongs to. ++ * ++ * For more details, see exercise 1, Section 6.2.1 in TAOCP, vol. 3. ++ */ + if (to) + *to = min; + +- this_pfn = PFN(ca->array[min]); +- +- if (this_pfn == pfn) +- return min; +- + return -ENOKEY; + } + diff --git a/queue-4.19/series b/queue-4.19/series index 7f7fafc86b6..c3dbd53da2a 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -63,3 +63,6 @@ usb-usb-storage-add-new-id-to-ums-realtek.patch usb-serial-pl2303-add-allied-telesis-vt-kit3.patch usb-serial-option-add-support-for-simcom-sim7500-sim7600-rndis-mode.patch usb-serial-option-add-telit-0x1260-and-0x1261-compositions.patch +timekeeping-repair-ktime_get_coarse-granularity.patch +ras-cec-convert-the-timer-callback-to-a-workqueue.patch +ras-cec-fix-binary-search-function.patch diff --git a/queue-4.19/timekeeping-repair-ktime_get_coarse-granularity.patch b/queue-4.19/timekeeping-repair-ktime_get_coarse-granularity.patch new file mode 100644 index 00000000000..1851f7fcd1b --- /dev/null +++ b/queue-4.19/timekeeping-repair-ktime_get_coarse-granularity.patch @@ -0,0 +1,60 @@ +From e3ff9c3678b4d80e22d2557b68726174578eaf52 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Thu, 13 Jun 2019 21:40:45 +0200 +Subject: timekeeping: Repair ktime_get_coarse*() granularity + +From: Thomas Gleixner + +commit e3ff9c3678b4d80e22d2557b68726174578eaf52 upstream. + +Jason reported that the coarse ktime based time getters advance only once +per second and not once per tick as advertised. + +The code reads only the monotonic base time, which advances once per +second. The nanoseconds are accumulated on every tick in xtime_nsec up to +a second and the regular time getters take this nanoseconds offset into +account, but the ktime_get_coarse*() implementation fails to do so. + +Add the accumulated xtime_nsec value to the monotonic base time to get the +proper per tick advancing coarse tinme. + +Fixes: b9ff604cff11 ("timekeeping: Add ktime_get_coarse_with_offset") +Reported-by: Jason A. Donenfeld +Signed-off-by: Thomas Gleixner +Tested-by: Jason A. Donenfeld +Cc: Arnd Bergmann +Cc: Peter Zijlstra +Cc: Clemens Ladisch +Cc: Sultan Alsawaf +Cc: Waiman Long +Cc: stable@vger.kernel.org +Link: https://lkml.kernel.org/r/alpine.DEB.2.21.1906132136280.1791@nanos.tec.linutronix.de +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/time/timekeeping.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/kernel/time/timekeeping.c ++++ b/kernel/time/timekeeping.c +@@ -812,17 +812,18 @@ ktime_t ktime_get_coarse_with_offset(enu + struct timekeeper *tk = &tk_core.timekeeper; + unsigned int seq; + ktime_t base, *offset = offsets[offs]; ++ u64 nsecs; + + WARN_ON(timekeeping_suspended); + + do { + seq = read_seqcount_begin(&tk_core.seq); + base = ktime_add(tk->tkr_mono.base, *offset); ++ nsecs = tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift; + + } while (read_seqcount_retry(&tk_core.seq, seq)); + +- return base; +- ++ return base + nsecs; + } + EXPORT_SYMBOL_GPL(ktime_get_coarse_with_offset); +