aboutsummaryrefslogtreecommitdiffstats
path: root/features/rt/u64_stats-Disable-preemption-on-32bit-UP-SMP-with-RT.patch
diff options
context:
space:
mode:
Diffstat (limited to 'features/rt/u64_stats-Disable-preemption-on-32bit-UP-SMP-with-RT.patch')
-rw-r--r--features/rt/u64_stats-Disable-preemption-on-32bit-UP-SMP-with-RT.patch151
1 files changed, 151 insertions, 0 deletions
diff --git a/features/rt/u64_stats-Disable-preemption-on-32bit-UP-SMP-with-RT.patch b/features/rt/u64_stats-Disable-preemption-on-32bit-UP-SMP-with-RT.patch
new file mode 100644
index 00000000..af52aa75
--- /dev/null
+++ b/features/rt/u64_stats-Disable-preemption-on-32bit-UP-SMP-with-RT.patch
@@ -0,0 +1,151 @@
+From f134d18cc24a5f4bbd6fa3b658749d22a00136c6 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Mon, 17 Aug 2020 12:28:10 +0200
+Subject: [PATCH 088/191] u64_stats: Disable preemption on 32bit-UP/SMP with RT
+ during updates
+
+On RT the seqcount_t is required even on UP because the softirq can be
+preempted. The IRQ handler is threaded so it is also preemptible.
+
+Disable preemption on 32bit-RT during value updates. There is no need to
+disable interrupts on RT because the handler is run threaded. Therefore
+disabling preemption is enough to guarantee that the update is not
+interruped.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/u64_stats_sync.h | 42 ++++++++++++++++++++++------------
+ 1 file changed, 28 insertions(+), 14 deletions(-)
+
+diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h
+index e81856c0ba13..66eb968a09d4 100644
+--- a/include/linux/u64_stats_sync.h
++++ b/include/linux/u64_stats_sync.h
+@@ -66,7 +66,7 @@
+ #include <linux/seqlock.h>
+
+ struct u64_stats_sync {
+-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
++#if BITS_PER_LONG==32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+ seqcount_t seq;
+ #endif
+ };
+@@ -115,7 +115,7 @@ static inline void u64_stats_inc(u64_stats_t *p)
+ }
+ #endif
+
+-#if BITS_PER_LONG == 32 && defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+ #define u64_stats_init(syncp) seqcount_init(&(syncp)->seq)
+ #else
+ static inline void u64_stats_init(struct u64_stats_sync *syncp)
+@@ -125,15 +125,19 @@ static inline void u64_stats_init(struct u64_stats_sync *syncp)
+
+ static inline void u64_stats_update_begin(struct u64_stats_sync *syncp)
+ {
+-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
++ if (IS_ENABLED(CONFIG_PREEMPT_RT))
++ preempt_disable();
+ write_seqcount_begin(&syncp->seq);
+ #endif
+ }
+
+ static inline void u64_stats_update_end(struct u64_stats_sync *syncp)
+ {
+-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+ write_seqcount_end(&syncp->seq);
++ if (IS_ENABLED(CONFIG_PREEMPT_RT))
++ preempt_enable();
+ #endif
+ }
+
+@@ -142,8 +146,11 @@ u64_stats_update_begin_irqsave(struct u64_stats_sync *syncp)
+ {
+ unsigned long flags = 0;
+
+-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
+- local_irq_save(flags);
++#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
++ if (IS_ENABLED(CONFIG_PREEMPT_RT))
++ preempt_disable();
++ else
++ local_irq_save(flags);
+ write_seqcount_begin(&syncp->seq);
+ #endif
+ return flags;
+@@ -153,15 +160,18 @@ static inline void
+ u64_stats_update_end_irqrestore(struct u64_stats_sync *syncp,
+ unsigned long flags)
+ {
+-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+ write_seqcount_end(&syncp->seq);
+- local_irq_restore(flags);
++ if (IS_ENABLED(CONFIG_PREEMPT_RT))
++ preempt_enable();
++ else
++ local_irq_restore(flags);
+ #endif
+ }
+
+ static inline unsigned int __u64_stats_fetch_begin(const struct u64_stats_sync *syncp)
+ {
+-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+ return read_seqcount_begin(&syncp->seq);
+ #else
+ return 0;
+@@ -170,7 +180,7 @@ static inline unsigned int __u64_stats_fetch_begin(const struct u64_stats_sync *
+
+ static inline unsigned int u64_stats_fetch_begin(const struct u64_stats_sync *syncp)
+ {
+-#if BITS_PER_LONG==32 && !defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (!defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_RT))
+ preempt_disable();
+ #endif
+ return __u64_stats_fetch_begin(syncp);
+@@ -179,7 +189,7 @@ static inline unsigned int u64_stats_fetch_begin(const struct u64_stats_sync *sy
+ static inline bool __u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
+ unsigned int start)
+ {
+-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+ return read_seqcount_retry(&syncp->seq, start);
+ #else
+ return false;
+@@ -189,7 +199,7 @@ static inline bool __u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
+ static inline bool u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
+ unsigned int start)
+ {
+-#if BITS_PER_LONG==32 && !defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (!defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_RT))
+ preempt_enable();
+ #endif
+ return __u64_stats_fetch_retry(syncp, start);
+@@ -203,7 +213,9 @@ static inline bool u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
+ */
+ static inline unsigned int u64_stats_fetch_begin_irq(const struct u64_stats_sync *syncp)
+ {
+-#if BITS_PER_LONG==32 && !defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && defined(CONFIG_PREEMPT_RT)
++ preempt_disable();
++#elif BITS_PER_LONG == 32 && !defined(CONFIG_SMP)
+ local_irq_disable();
+ #endif
+ return __u64_stats_fetch_begin(syncp);
+@@ -212,7 +224,9 @@ static inline unsigned int u64_stats_fetch_begin_irq(const struct u64_stats_sync
+ static inline bool u64_stats_fetch_retry_irq(const struct u64_stats_sync *syncp,
+ unsigned int start)
+ {
+-#if BITS_PER_LONG==32 && !defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && defined(CONFIG_PREEMPT_RT)
++ preempt_enable();
++#elif BITS_PER_LONG == 32 && !defined(CONFIG_SMP)
+ local_irq_enable();
+ #endif
+ return __u64_stats_fetch_retry(syncp, start);
+--
+2.19.1
+