]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 9 May 2022 09:55:25 +0000 (11:55 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 9 May 2022 09:55:25 +0000 (11:55 +0200)
added patches:
asoc-da7219-fix-change-notifications-for-tone-generator-frequency.patch
genirq-synchronize-interrupt-thread-startup.patch

queue-5.15/asoc-da7219-fix-change-notifications-for-tone-generator-frequency.patch [new file with mode: 0644]
queue-5.15/genirq-synchronize-interrupt-thread-startup.patch [new file with mode: 0644]
queue-5.15/series

diff --git a/queue-5.15/asoc-da7219-fix-change-notifications-for-tone-generator-frequency.patch b/queue-5.15/asoc-da7219-fix-change-notifications-for-tone-generator-frequency.patch
new file mode 100644 (file)
index 0000000..6a51a39
--- /dev/null
@@ -0,0 +1,58 @@
+From 08ef48404965cfef99343d6bbbcf75b88c74aa0e Mon Sep 17 00:00:00 2001
+From: Mark Brown <broonie@kernel.org>
+Date: Wed, 20 Apr 2022 14:34:37 +0100
+Subject: ASoC: da7219: Fix change notifications for tone generator frequency
+
+From: Mark Brown <broonie@kernel.org>
+
+commit 08ef48404965cfef99343d6bbbcf75b88c74aa0e upstream.
+
+The tone generator frequency control just returns 0 on successful write,
+not a boolean value indicating if there was a change or not.  Compare
+what was written with the value that was there previously so that
+notifications are generated appropriately when the value changes.
+
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Reviewed-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20220420133437.569229-1-broonie@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/soc/codecs/da7219.c |   14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+--- a/sound/soc/codecs/da7219.c
++++ b/sound/soc/codecs/da7219.c
+@@ -446,7 +446,7 @@ static int da7219_tonegen_freq_put(struc
+       struct soc_mixer_control *mixer_ctrl =
+               (struct soc_mixer_control *) kcontrol->private_value;
+       unsigned int reg = mixer_ctrl->reg;
+-      __le16 val;
++      __le16 val_new, val_old;
+       int ret;
+       /*
+@@ -454,13 +454,19 @@ static int da7219_tonegen_freq_put(struc
+        * Therefore we need to convert to little endian here to align with
+        * HW registers.
+        */
+-      val = cpu_to_le16(ucontrol->value.integer.value[0]);
++      val_new = cpu_to_le16(ucontrol->value.integer.value[0]);
+       mutex_lock(&da7219->ctrl_lock);
+-      ret = regmap_raw_write(da7219->regmap, reg, &val, sizeof(val));
++      ret = regmap_raw_read(da7219->regmap, reg, &val_old, sizeof(val_old));
++      if (ret == 0 && (val_old != val_new))
++              ret = regmap_raw_write(da7219->regmap, reg,
++                              &val_new, sizeof(val_new));
+       mutex_unlock(&da7219->ctrl_lock);
+-      return ret;
++      if (ret < 0)
++              return ret;
++
++      return val_old != val_new;
+ }
diff --git a/queue-5.15/genirq-synchronize-interrupt-thread-startup.patch b/queue-5.15/genirq-synchronize-interrupt-thread-startup.patch
new file mode 100644 (file)
index 0000000..8a755bc
--- /dev/null
@@ -0,0 +1,173 @@
+From 8707898e22fd665bc1d7b18b809be4b56ce25bdd Mon Sep 17 00:00:00 2001
+From: Thomas Pfaff <tpfaff@pcs.com>
+Date: Mon, 2 May 2022 13:28:29 +0200
+Subject: genirq: Synchronize interrupt thread startup
+
+From: Thomas Pfaff <tpfaff@pcs.com>
+
+commit 8707898e22fd665bc1d7b18b809be4b56ce25bdd upstream.
+
+A kernel hang can be observed when running setserial in a loop on a kernel
+with force threaded interrupts. The sequence of events is:
+
+   setserial
+     open("/dev/ttyXXX")
+       request_irq()
+     do_stuff()
+      -> serial interrupt
+         -> wake(irq_thread)
+             desc->threads_active++;
+     close()
+       free_irq()
+         kthread_stop(irq_thread)
+     synchronize_irq() <- hangs because desc->threads_active != 0
+
+The thread is created in request_irq() and woken up, but does not get on a
+CPU to reach the actual thread function, which would handle the pending
+wake-up. kthread_stop() sets the should stop condition which makes the
+thread immediately exit, which in turn leaves the stale threads_active
+count around.
+
+This problem was introduced with commit 519cc8652b3a, which addressed a
+interrupt sharing issue in the PCIe code.
+
+Before that commit free_irq() invoked synchronize_irq(), which waits for
+the hard interrupt handler and also for associated threads to complete.
+
+To address the PCIe issue synchronize_irq() was replaced with
+__synchronize_hardirq(), which only waits for the hard interrupt handler to
+complete, but not for threaded handlers.
+
+This was done under the assumption, that the interrupt thread already
+reached the thread function and waits for a wake-up, which is guaranteed to
+be handled before acting on the stop condition. The problematic case, that
+the thread would not reach the thread function, was obviously overlooked.
+
+Make sure that the interrupt thread is really started and reaches
+thread_fn() before returning from __setup_irq().
+
+This utilizes the existing wait queue in the interrupt descriptor. The
+wait queue is unused for non-shared interrupts. For shared interrupts the
+usage might cause a spurious wake-up of a waiter in synchronize_irq() or the
+completion of a threaded handler might cause a spurious wake-up of the
+waiter for the ready flag. Both are harmless and have no functional impact.
+
+[ tglx: Amended changelog ]
+
+Fixes: 519cc8652b3a ("genirq: Synchronize only with single thread on free_irq()")
+Signed-off-by: Thomas Pfaff <tpfaff@pcs.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Marc Zyngier <maz@kernel.org>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/552fe7b4-9224-b183-bb87-a8f36d335690@pcs.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/irq/internals.h |    2 ++
+ kernel/irq/irqdesc.c   |    2 ++
+ kernel/irq/manage.c    |   39 +++++++++++++++++++++++++++++----------
+ 3 files changed, 33 insertions(+), 10 deletions(-)
+
+--- a/kernel/irq/internals.h
++++ b/kernel/irq/internals.h
+@@ -29,12 +29,14 @@ extern struct irqaction chained_action;
+  * IRQTF_WARNED    - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed
+  * IRQTF_AFFINITY  - irq thread is requested to adjust affinity
+  * IRQTF_FORCED_THREAD  - irq action is force threaded
++ * IRQTF_READY     - signals that irq thread is ready
+  */
+ enum {
+       IRQTF_RUNTHREAD,
+       IRQTF_WARNED,
+       IRQTF_AFFINITY,
+       IRQTF_FORCED_THREAD,
++      IRQTF_READY,
+ };
+ /*
+--- a/kernel/irq/irqdesc.c
++++ b/kernel/irq/irqdesc.c
+@@ -407,6 +407,7 @@ static struct irq_desc *alloc_desc(int i
+       lockdep_set_class(&desc->lock, &irq_desc_lock_class);
+       mutex_init(&desc->request_mutex);
+       init_rcu_head(&desc->rcu);
++      init_waitqueue_head(&desc->wait_for_threads);
+       desc_set_defaults(irq, desc, node, affinity, owner);
+       irqd_set(&desc->irq_data, flags);
+@@ -575,6 +576,7 @@ int __init early_irq_init(void)
+               raw_spin_lock_init(&desc[i].lock);
+               lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
+               mutex_init(&desc[i].request_mutex);
++              init_waitqueue_head(&desc[i].wait_for_threads);
+               desc_set_defaults(i, &desc[i], node, NULL, NULL);
+       }
+       return arch_early_irq_init();
+--- a/kernel/irq/manage.c
++++ b/kernel/irq/manage.c
+@@ -1249,6 +1249,31 @@ static void irq_wake_secondary(struct ir
+ }
+ /*
++ * Internal function to notify that a interrupt thread is ready.
++ */
++static void irq_thread_set_ready(struct irq_desc *desc,
++                               struct irqaction *action)
++{
++      set_bit(IRQTF_READY, &action->thread_flags);
++      wake_up(&desc->wait_for_threads);
++}
++
++/*
++ * Internal function to wake up a interrupt thread and wait until it is
++ * ready.
++ */
++static void wake_up_and_wait_for_irq_thread_ready(struct irq_desc *desc,
++                                                struct irqaction *action)
++{
++      if (!action || !action->thread)
++              return;
++
++      wake_up_process(action->thread);
++      wait_event(desc->wait_for_threads,
++                 test_bit(IRQTF_READY, &action->thread_flags));
++}
++
++/*
+  * Interrupt handler thread
+  */
+ static int irq_thread(void *data)
+@@ -1259,6 +1284,8 @@ static int irq_thread(void *data)
+       irqreturn_t (*handler_fn)(struct irq_desc *desc,
+                       struct irqaction *action);
++      irq_thread_set_ready(desc, action);
++
+       if (force_irqthreads() && test_bit(IRQTF_FORCED_THREAD,
+                                          &action->thread_flags))
+               handler_fn = irq_forced_thread_fn;
+@@ -1683,8 +1710,6 @@ __setup_irq(unsigned int irq, struct irq
+       }
+       if (!shared) {
+-              init_waitqueue_head(&desc->wait_for_threads);
+-
+               /* Setup the type (level, edge polarity) if configured: */
+               if (new->flags & IRQF_TRIGGER_MASK) {
+                       ret = __irq_set_trigger(desc,
+@@ -1780,14 +1805,8 @@ __setup_irq(unsigned int irq, struct irq
+       irq_setup_timings(desc, new);
+-      /*
+-       * Strictly no need to wake it up, but hung_task complains
+-       * when no hard interrupt wakes the thread up.
+-       */
+-      if (new->thread)
+-              wake_up_process(new->thread);
+-      if (new->secondary)
+-              wake_up_process(new->secondary->thread);
++      wake_up_and_wait_for_irq_thread_ready(desc, new);
++      wake_up_and_wait_for_irq_thread_ready(desc, new->secondary);
+       register_irq_proc(irq, desc);
+       new->dir = NULL;
index d22481fcc0cfdb4ec23a19fdae3704b3fca72196..2dfa56d87bbab9e41c06570fd552d7614d574356 100644 (file)
@@ -20,4 +20,6 @@ firewire-fix-potential-uaf-in-outbound_phy_packet_callback.patch
 firewire-remove-check-of-list-iterator-against-head-past-the-loop-body.patch
 firewire-core-extend-card-lock-in-fw_core_handle_bus_reset.patch
 net-stmmac-disable-split-header-sph-for-intel-platforms.patch
+genirq-synchronize-interrupt-thread-startup.patch
+asoc-da7219-fix-change-notifications-for-tone-generator-frequency.patch
 btrfs-do-not-bug_on-on-failure-to-update-inode-when-setting-xattr.patch