]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
patches for 4.4
authorSasha Levin <sashal@kernel.org>
Thu, 20 Dec 2018 02:32:11 +0000 (21:32 -0500)
committerSasha Levin <sashal@kernel.org>
Thu, 20 Dec 2018 02:32:11 +0000 (21:32 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.4/alsa-isa-wavefront-prevent-some-out-of-bound-writes.patch [new file with mode: 0644]
queue-4.4/rtc-snvs-add-a-missing-write-sync.patch [new file with mode: 0644]
queue-4.4/rtc-snvs-add-timeouts-to-avoid-kernel-lockups.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/alsa-isa-wavefront-prevent-some-out-of-bound-writes.patch b/queue-4.4/alsa-isa-wavefront-prevent-some-out-of-bound-writes.patch
new file mode 100644 (file)
index 0000000..a7d5821
--- /dev/null
@@ -0,0 +1,54 @@
+From e89a8453f199b9b6a6fb2c2b62c9d8272b0a1ef1 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Wed, 4 May 2016 09:27:37 +0300
+Subject: ALSA: isa/wavefront: prevent some out of bound writes
+
+[ Upstream commit 84d7a4470dbac0dd9389050100b54a1625d04264 ]
+
+"header->number" can be up to USHRT_MAX and it comes from the ioctl so
+it needs to be capped.
+
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/isa/wavefront/wavefront_synth.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
+index 69f76ff5693d..718d5e3b7806 100644
+--- a/sound/isa/wavefront/wavefront_synth.c
++++ b/sound/isa/wavefront/wavefront_synth.c
+@@ -785,6 +785,9 @@ wavefront_send_patch (snd_wavefront_t *dev, wavefront_patch_info *header)
+       DPRINT (WF_DEBUG_LOAD_PATCH, "downloading patch %d\n",
+                                     header->number);
++      if (header->number >= ARRAY_SIZE(dev->patch_status))
++              return -EINVAL;
++
+       dev->patch_status[header->number] |= WF_SLOT_FILLED;
+       bptr = buf;
+@@ -809,6 +812,9 @@ wavefront_send_program (snd_wavefront_t *dev, wavefront_patch_info *header)
+       DPRINT (WF_DEBUG_LOAD_PATCH, "downloading program %d\n",
+               header->number);
++      if (header->number >= ARRAY_SIZE(dev->prog_status))
++              return -EINVAL;
++
+       dev->prog_status[header->number] = WF_SLOT_USED;
+       /* XXX need to zero existing SLOT_USED bit for program_status[i]
+@@ -898,6 +904,9 @@ wavefront_send_sample (snd_wavefront_t *dev,
+               header->number = x;
+       }
++      if (header->number >= WF_MAX_SAMPLE)
++              return -EINVAL;
++
+       if (header->size) {
+               /* XXX it's a debatable point whether or not RDONLY semantics
+-- 
+2.19.1
+
diff --git a/queue-4.4/rtc-snvs-add-a-missing-write-sync.patch b/queue-4.4/rtc-snvs-add-a-missing-write-sync.patch
new file mode 100644 (file)
index 0000000..11dbb7d
--- /dev/null
@@ -0,0 +1,33 @@
+From b98bc40758126e47e8cceaebeeac1440cdcb6a5c Mon Sep 17 00:00:00 2001
+From: Guy Shapiro <guy.shapiro@mobi-wize.com>
+Date: Sun, 29 Jan 2017 11:57:19 +0200
+Subject: rtc: snvs: add a missing write sync
+
+[ Upstream commit 7bb633b1a9812a6b9f3e49d0cf17f60a633914e5 ]
+
+The clear of the LPTA_EN flag should be synced before writing to the
+alarm register. Omitting this synchronization creates a race when
+trying to change existing alarm.
+
+Signed-off-by: Guy Shapiro <guy.shapiro@mobi-wize.com>
+Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/rtc/rtc-snvs.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
+index a161fbf6f172..af131682dbc9 100644
+--- a/drivers/rtc/rtc-snvs.c
++++ b/drivers/rtc/rtc-snvs.c
+@@ -187,6 +187,7 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+       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);
+       regmap_write(data->regmap, data->offset + SNVS_LPTAR, time);
+       /* Clear alarm interrupt status bit */
+-- 
+2.19.1
+
diff --git a/queue-4.4/rtc-snvs-add-timeouts-to-avoid-kernel-lockups.patch b/queue-4.4/rtc-snvs-add-timeouts-to-avoid-kernel-lockups.patch
new file mode 100644 (file)
index 0000000..a180960
--- /dev/null
@@ -0,0 +1,196 @@
+From 2fbbefa0946826044f2d15feab38cc426afdcbc3 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 af131682dbc9..63ad5b543f14 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 316bcc7b0f7e315f77bfd6a1d67465879ad38f76..6abc42ec8e973bc8514583ba3d792a8f63412ff0 100644 (file)
@@ -35,3 +35,6 @@ arm-8814-1-mm-improve-fix-arm-v7_dma_inv_range-unali.patch
 cifs-in-kconfig-config_cifs_posix-needs-depends-on-l.patch
 i2c-axxia-properly-handle-master-timeout.patch
 i2c-scmi-fix-probe-error-on-devices-with-an-empty-sm.patch
+rtc-snvs-add-a-missing-write-sync.patch
+rtc-snvs-add-timeouts-to-avoid-kernel-lockups.patch
+alsa-isa-wavefront-prevent-some-out-of-bound-writes.patch