]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
patches for 4.14
authorSasha Levin <sashal@kernel.org>
Thu, 20 Dec 2018 02:32:10 +0000 (21:32 -0500)
committerSasha Levin <sashal@kernel.org>
Thu, 20 Dec 2018 02:32:10 +0000 (21:32 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.14/bpf-arm-fix-emit_ldx_r-and-emit_mov_i-using-tmp_reg_.patch [new file with mode: 0644]
queue-4.14/rtc-snvs-add-timeouts-to-avoid-kernel-lockups.patch [new file with mode: 0644]
queue-4.14/series

diff --git a/queue-4.14/bpf-arm-fix-emit_ldx_r-and-emit_mov_i-using-tmp_reg_.patch b/queue-4.14/bpf-arm-fix-emit_ldx_r-and-emit_mov_i-using-tmp_reg_.patch
new file mode 100644 (file)
index 0000000..d5733c9
--- /dev/null
@@ -0,0 +1,34 @@
+From 7e98830889eee8b422b3eb88a46e8a092d983bff Mon Sep 17 00:00:00 2001
+From: Nicolas Schichan <nschichan@freebox.fr>
+Date: Wed, 19 Dec 2018 22:40:42 +0100
+Subject: bpf, arm: fix emit_ldx_r and emit_mov_i using TMP_REG_1
+
+emit_ldx_r() and emit_a32_mov_i() were both using TMP_REG_1 and
+clashing with each other. Using TMP_REG_2 in emit_ldx_r() fixes
+the issue.
+
+Fixes: ec19e02b343 ("ARM: net: bpf: fix LDX instructions")
+Cc: Russell King <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Nicolas Schichan <nschichan@freebox.fr>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/net/bpf_jit_32.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
+index ece2d1d43724..dafeb5f81353 100644
+--- a/arch/arm/net/bpf_jit_32.c
++++ b/arch/arm/net/bpf_jit_32.c
+@@ -915,7 +915,7 @@ static inline void emit_str_r(const u8 dst, const u8 src, bool dstk,
+ /* dst = *(size*)(src + off) */
+ static inline void emit_ldx_r(const u8 dst[], const u8 src, bool dstk,
+                             s32 off, struct jit_ctx *ctx, const u8 sz){
+-      const u8 *tmp = bpf2a32[TMP_REG_1];
++      const u8 *tmp = bpf2a32[TMP_REG_2];
+       const u8 *rd = dstk ? tmp : dst;
+       u8 rm = src;
+       s32 off_max;
+-- 
+2.19.1
+
diff --git a/queue-4.14/rtc-snvs-add-timeouts-to-avoid-kernel-lockups.patch b/queue-4.14/rtc-snvs-add-timeouts-to-avoid-kernel-lockups.patch
new file mode 100644 (file)
index 0000000..78a3fa2
--- /dev/null
@@ -0,0 +1,196 @@
+From a517c43ea4a02a338ab238b73aa90618d85976ff Mon Sep 17 00:00:00 2001
+From: Trent Piepho <tpiepho@impinj.com>
+Date: Wed, 16 May 2018 16:45:51 -0700
+Subject: rtc: snvs: Add timeouts to avoid kernel lockups
+
+[ Upstream commit cd7f3a249dbed2858e6c2f30e5be7f1f7a709ee2 ]
+
+In order to read correctly from asynchronously updated RTC registers,
+it's necessary to read repeatedly until their values do not change from
+read to read.  It's also necessary to wait for three RTC clock ticks for
+certain operations.  There are no timeouts in this code and these
+operations could possibly loop forever.
+
+To avoid kernel hangs, put in timeouts.
+
+The iMX7d can be configured to stop the SRTC on a tamper event, which
+will lockup the kernel inside this driver as described above.
+
+These hangs can happen when running under qemu, which doesn't emulate
+the SNVS RTC, though currently the driver will refuse to load on qemu
+due to a timeout in the driver probe method.
+
+It could also happen if the SRTC block where somehow placed into reset
+or the slow speed clock that drives the SRTC counter (but not the CPU)
+were to stop.
+
+The symptoms on a two core iMX7d are a work queue hang on
+rtc_timer_do_work(), which eventually blocks a systemd fsnotify
+operation that triggers a work queue flush, causing systemd to hang and
+thus causing all services that should be started by systemd, like a
+console getty, to fail to start or stop.
+
+Also optimize the wait code to wait less.  It only needs to wait for the
+clock to advance three ticks, not to see it change three times.
+
+Cc: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+Cc: Alessandro Zummo <a.zummo@towertech.it>
+Cc: Fabio Estevam <fabio.estevam@nxp.com>
+Cc: Shawn Guo <shawn.guo@linaro.org>
+Cc: Bryan O'Donoghue <pure.logic@nexus-software.ie>
+Signed-off-by: Trent Piepho <tpiepho@impinj.com>
+Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/rtc/rtc-snvs.c | 105 +++++++++++++++++++++++++++--------------
+ 1 file changed, 70 insertions(+), 35 deletions(-)
+
+diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
+index 9af591d5223c..71eee39520f0 100644
+--- a/drivers/rtc/rtc-snvs.c
++++ b/drivers/rtc/rtc-snvs.c
+@@ -47,49 +47,83 @@ struct snvs_rtc_data {
+       struct clk *clk;
+ };
++/* Read 64 bit timer register, which could be in inconsistent state */
++static u64 rtc_read_lpsrt(struct snvs_rtc_data *data)
++{
++      u32 msb, lsb;
++
++      regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &msb);
++      regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &lsb);
++      return (u64)msb << 32 | lsb;
++}
++
++/* Read the secure real time counter, taking care to deal with the cases of the
++ * counter updating while being read.
++ */
+ static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
+ {
+       u64 read1, read2;
+-      u32 val;
++      unsigned int timeout = 100;
++      /* As expected, the registers might update between the read of the LSB
++       * reg and the MSB reg.  It's also possible that one register might be
++       * in partially modified state as well.
++       */
++      read1 = rtc_read_lpsrt(data);
+       do {
+-              regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
+-              read1 = val;
+-              read1 <<= 32;
+-              regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
+-              read1 |= val;
+-
+-              regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
+-              read2 = val;
+-              read2 <<= 32;
+-              regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
+-              read2 |= val;
+-      } while (read1 != read2);
++              read2 = read1;
++              read1 = rtc_read_lpsrt(data);
++      } while (read1 != read2 && --timeout);
++      if (!timeout)
++              dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
+       /* Convert 47-bit counter to 32-bit raw second count */
+       return (u32) (read1 >> CNTR_TO_SECS_SH);
+ }
+-static void rtc_write_sync_lp(struct snvs_rtc_data *data)
++/* Just read the lsb from the counter, dealing with inconsistent state */
++static int rtc_read_lp_counter_lsb(struct snvs_rtc_data *data, u32 *lsb)
+ {
+-      u32 count1, count2, count3;
+-      int i;
+-
+-      /* Wait for 3 CKIL cycles */
+-      for (i = 0; i < 3; i++) {
+-              do {
+-                      regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
+-                      regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
+-              } while (count1 != count2);
+-
+-              /* Now wait until counter value changes */
+-              do {
+-                      do {
+-                              regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
+-                              regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count3);
+-                      } while (count2 != count3);
+-              } while (count3 == count1);
++      u32 count1, count2;
++      unsigned int timeout = 100;
++
++      regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
++      do {
++              count2 = count1;
++              regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
++      } while (count1 != count2 && --timeout);
++      if (!timeout) {
++              dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
++              return -ETIMEDOUT;
+       }
++
++      *lsb = count1;
++      return 0;
++}
++
++static int rtc_write_sync_lp(struct snvs_rtc_data *data)
++{
++      u32 count1, count2;
++      u32 elapsed;
++      unsigned int timeout = 1000;
++      int ret;
++
++      ret = rtc_read_lp_counter_lsb(data, &count1);
++      if (ret)
++              return ret;
++
++      /* Wait for 3 CKIL cycles, about 61.0-91.5 µs */
++      do {
++              ret = rtc_read_lp_counter_lsb(data, &count2);
++              if (ret)
++                      return ret;
++              elapsed = count2 - count1; /* wrap around _is_ handled! */
++      } while (elapsed < 3 && --timeout);
++      if (!timeout) {
++              dev_err(&data->rtc->dev, "Timeout waiting for LPSRT Counter to change\n");
++              return -ETIMEDOUT;
++      }
++      return 0;
+ }
+ static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
+@@ -173,9 +207,7 @@ static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
+                          (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN),
+                          enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0);
+-      rtc_write_sync_lp(data);
+-
+-      return 0;
++      return rtc_write_sync_lp(data);
+ }
+ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+@@ -183,11 +215,14 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+       struct snvs_rtc_data *data = dev_get_drvdata(dev);
+       struct rtc_time *alrm_tm = &alrm->time;
+       unsigned long time;
++      int ret;
+       rtc_tm_to_time(alrm_tm, &time);
+       regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);
+-      rtc_write_sync_lp(data);
++      ret = rtc_write_sync_lp(data);
++      if (ret)
++              return ret;
+       regmap_write(data->regmap, data->offset + SNVS_LPTAR, time);
+       /* Clear alarm interrupt status bit */
+-- 
+2.19.1
+
index 7fd34b9cac7c852f5512c7d7c93e38c4779d9d44..c7c7d3df2890ade7fc6c8c085c2d9e5b2328ab5c 100644 (file)
@@ -68,3 +68,5 @@ i2c-scmi-fix-probe-error-on-devices-with-an-empty-sm.patch
 i2c-uniphier-fix-violation-of-tlow-requirement-for-f.patch
 i2c-uniphier-f-fix-violation-of-tlow-requirement-for.patch
 nvmet-rdma-fix-response-use-after-free.patch
+rtc-snvs-add-timeouts-to-avoid-kernel-lockups.patch
+bpf-arm-fix-emit_ldx_r-and-emit_mov_i-using-tmp_reg_.patch