]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.15
authorSasha Levin <sashal@kernel.org>
Sun, 10 Mar 2024 02:31:48 +0000 (21:31 -0500)
committerSasha Levin <sashal@kernel.org>
Sun, 10 Mar 2024 02:31:48 +0000 (21:31 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
56 files changed:
queue-5.15/alsa-usb-audio-add-fixed_rate-quirk-for-jbl-quantum6.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-add-new-quirk-fixed_rate-for-jbl-quan.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-add-quirk-for-rode-nt-usb.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-add-quirk-for-tascam-model-12.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-always-initialize-fixed_rate-in-snd_u.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-apply-mutex-around-snd_usb_endpoint_s.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-avoid-superfluous-endpoint-setup.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-clear-fixed-clock-rate-at-closing-ep.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-correct-the-return-code-from-snd_usb_.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-fix-microphone-sound-on-nexigo-webcam.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-fix-wrong-kfree-issue-in-snd_usb_endp.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-properly-refcounting-clock-rate.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-refcount-multiple-accesses-on-the-sin.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-sort-quirk-table-entries.patch [new file with mode: 0644]
queue-5.15/alsa-usb-audio-split-endpoint-setups-for-hw_params-a.patch [new file with mode: 0644]
queue-5.15/drm-amd-display-fix-uninitialized-variable-usage-in-.patch [new file with mode: 0644]
queue-5.15/drm-amd-display-increase-frame-larger-than-for-all-d.patch [new file with mode: 0644]
queue-5.15/drm-amd-display-move-calcs-folder-into-dml.patch [new file with mode: 0644]
queue-5.15/drm-amd-display-re-arrange-fpu-code-structure-for-dc.patch [new file with mode: 0644]
queue-5.15/drm-amd-display-remove-dml-makefile-duplicate-lines.patch [new file with mode: 0644]
queue-5.15/drm-amd-pm-do-not-expose-the-api-used-internally-onl.patch [new file with mode: 0644]
queue-5.15/drm-amdgpu-reset-ih-overflow_clear-bit.patch [new file with mode: 0644]
queue-5.15/exit-fix-typo-in-comment-s-sub-theads-sub-threads.patch [new file with mode: 0644]
queue-5.15/exit-wait_task_zombie-kill-the-no-longer-necessary-s.patch [new file with mode: 0644]
queue-5.15/fs-proc-do_task_stat-move-thread_group_cputime_adjus.patch [new file with mode: 0644]
queue-5.15/getrusage-add-the-signal_struct-sig-local-variable.patch [new file with mode: 0644]
queue-5.15/getrusage-move-thread_group_cputime_adjusted-outside.patch [new file with mode: 0644]
queue-5.15/getrusage-use-__for_each_thread.patch [new file with mode: 0644]
queue-5.15/getrusage-use-sig-stats_lock-rather-than-lock_task_s.patch [new file with mode: 0644]
queue-5.15/hv_netvsc-register-vf-in-netvsc_probe-if-net_device_.patch [new file with mode: 0644]
queue-5.15/hv_netvsc-use-netif_is_bond_master-instead-of-open-c.patch [new file with mode: 0644]
queue-5.15/modpost-add-.ltext-and-.ltext.-to-text_sections.patch [new file with mode: 0644]
queue-5.15/modpost-include-.text.-in-text_sections.patch [new file with mode: 0644]
queue-5.15/nfp-flower-add-goto_chain_index-for-ct-entry.patch [new file with mode: 0644]
queue-5.15/nfp-flower-add-hardware-offload-check-for-post-ct-en.patch [new file with mode: 0644]
queue-5.15/nfsd-add-documenting-comment-for-nfsd4_release_locko.patch [new file with mode: 0644]
queue-5.15/nfsd-don-t-take-fi_lock-in-nfsd_break_deleg_cb.patch [new file with mode: 0644]
queue-5.15/nfsd-fix-release_lockowner.patch [new file with mode: 0644]
queue-5.15/nfsd-modernize-nfsd4_release_lockowner.patch [new file with mode: 0644]
queue-5.15/proc-use-task_is_running-for-wchan-in-proc-pid-stat.patch [new file with mode: 0644]
queue-5.15/regmap-add-bulk-read-write-callbacks-into-regmap_con.patch [new file with mode: 0644]
queue-5.15/regmap-allow-to-define-reg_update_bits-for-no-bus-co.patch [new file with mode: 0644]
queue-5.15/selftests-mm-fix-map_hugetlb-failure-on-64k-page-siz.patch [new file with mode: 0644]
queue-5.15/selftests-mm-switch-to-bash-from-sh.patch [new file with mode: 0644]
queue-5.15/selftests-mptcp-decrease-bw-in-simult-flows.patch [new file with mode: 0644]
queue-5.15/selftests-mptcp-simult-flows-fix-some-subtest-names.patch [new file with mode: 0644]
queue-5.15/selftests-mptcp-simult-flows-format-subtests-results.patch [new file with mode: 0644]
queue-5.15/serial-max310x-fix-io-data-corruption-in-batched-ope.patch [new file with mode: 0644]
queue-5.15/serial-max310x-make-accessing-revision-id-interface-.patch [new file with mode: 0644]
queue-5.15/serial-max310x-prevent-infinite-while-loop-in-port-s.patch [new file with mode: 0644]
queue-5.15/serial-max310x-use-a-separate-regmap-for-each-port.patch [new file with mode: 0644]
queue-5.15/serial-max310x-use-regmap-methods-for-spi-batch-oper.patch [new file with mode: 0644]
queue-5.15/series
queue-5.15/um-fix-adding-no-pie-for-clang.patch [new file with mode: 0644]
queue-5.15/xhci-handle-isoc-babble-and-buffer-overrun-events-pr.patch [new file with mode: 0644]
queue-5.15/xhci-process-isoc-td-properly-when-there-was-a-trans.patch [new file with mode: 0644]

diff --git a/queue-5.15/alsa-usb-audio-add-fixed_rate-quirk-for-jbl-quantum6.patch b/queue-5.15/alsa-usb-audio-add-fixed_rate-quirk-for-jbl-quantum6.patch
new file mode 100644 (file)
index 0000000..4ab89a1
--- /dev/null
@@ -0,0 +1,37 @@
+From 3cfa0f1d5a58f8dbbd7dfecb5ab621a62176a76e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 18 Jan 2023 17:59:47 +0100
+Subject: ALSA: usb-audio: Add FIXED_RATE quirk for JBL Quantum610 Wireless
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit dfd5fe19db7dc7006642f8109ee8965e5d031897 ]
+
+JBL Quantum610 Wireless (0ecb:205c) requires the same workaround that
+was used for JBL Quantum810 for limiting the sample rate.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=216798
+Link: https://lore.kernel.org/r/20230118165947.22317-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 668abe6dc7b6 ("ALSA: usb-audio: Sort quirk table entries")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index 6cd7f77779159..3073570beb3e2 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1896,6 +1896,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+                  QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+       DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */
+                  QUIRK_FLAG_IFACE_SKIP_CLOSE),
++      DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */
++                 QUIRK_FLAG_FIXED_RATE),
+       DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */
+                  QUIRK_FLAG_FIXED_RATE),
+       DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */
+-- 
+2.43.0
+
diff --git a/queue-5.15/alsa-usb-audio-add-new-quirk-fixed_rate-for-jbl-quan.patch b/queue-5.15/alsa-usb-audio-add-new-quirk-fixed_rate-for-jbl-quan.patch
new file mode 100644 (file)
index 0000000..ca7660e
--- /dev/null
@@ -0,0 +1,282 @@
+From 19d22139cc93bac97a5622ba1ab02ba345723d1f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Dec 2022 16:30:37 +0100
+Subject: ALSA: usb-audio: Add new quirk FIXED_RATE for JBL Quantum810 Wireless
+
+From: Jaroslav Kysela <perex@perex.cz>
+
+[ Upstream commit fd28941cff1cd9d8ffa59fe11eb64148e09b6ed6 ]
+
+It seems that the firmware is broken and does not accept
+the UAC_EP_CS_ATTR_SAMPLE_RATE URB. There is only one rate (48000Hz)
+available in the descriptors for the output endpoint.
+
+Create a new quirk QUIRK_FLAG_FIXED_RATE to skip the rate setup
+when only one rate is available (fixed).
+
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=216798
+Signed-off-by: Jaroslav Kysela <perex@perex.cz>
+Link: https://lore.kernel.org/r/20221215153037.1163786-1-perex@perex.cz
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/card.h     |  1 +
+ sound/usb/endpoint.c | 16 ++++++++++------
+ sound/usb/endpoint.h |  3 ++-
+ sound/usb/implicit.c |  6 +++++-
+ sound/usb/implicit.h |  2 +-
+ sound/usb/pcm.c      | 36 +++++++++++++++++++++++++++++++++---
+ sound/usb/pcm.h      |  2 ++
+ sound/usb/quirks.c   |  2 ++
+ sound/usb/usbaudio.h |  4 ++++
+ 9 files changed, 60 insertions(+), 12 deletions(-)
+
+diff --git a/sound/usb/card.h b/sound/usb/card.h
+index 40061550105ac..6ec95b2edf863 100644
+--- a/sound/usb/card.h
++++ b/sound/usb/card.h
+@@ -131,6 +131,7 @@ struct snd_usb_endpoint {
+       bool lowlatency_playback;       /* low-latency playback mode */
+       bool need_setup;                /* (re-)need for hw_params? */
+       bool need_prepare;              /* (re-)need for prepare? */
++      bool fixed_rate;                /* skip rate setup */
+       /* for hw constraints */
+       const struct audioformat *cur_audiofmt;
+diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
+index aca9ebfec22c8..26af199f3836e 100644
+--- a/sound/usb/endpoint.c
++++ b/sound/usb/endpoint.c
+@@ -774,7 +774,8 @@ struct snd_usb_endpoint *
+ snd_usb_endpoint_open(struct snd_usb_audio *chip,
+                     const struct audioformat *fp,
+                     const struct snd_pcm_hw_params *params,
+-                    bool is_sync_ep)
++                    bool is_sync_ep,
++                    bool fixed_rate)
+ {
+       struct snd_usb_endpoint *ep;
+       int ep_num = is_sync_ep ? fp->sync_ep : fp->endpoint;
+@@ -830,6 +831,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
+               ep->implicit_fb_sync = fp->implicit_fb;
+               ep->need_setup = true;
+               ep->need_prepare = true;
++              ep->fixed_rate = fixed_rate;
+               usb_audio_dbg(chip, "  channels=%d, rate=%d, format=%s, period_bytes=%d, periods=%d, implicit_fb=%d\n",
+                             ep->cur_channels, ep->cur_rate,
+@@ -1414,11 +1416,13 @@ static int init_sample_rate(struct snd_usb_audio *chip,
+       if (clock && !clock->need_setup)
+               return 0;
+-      err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate);
+-      if (err < 0) {
+-              if (clock)
+-                      clock->rate = 0; /* reset rate */
+-              return err;
++      if (!ep->fixed_rate) {
++              err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate);
++              if (err < 0) {
++                      if (clock)
++                              clock->rate = 0; /* reset rate */
++                      return err;
++              }
+       }
+       if (clock)
+diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
+index b972f7899d57e..c09f68ce08b18 100644
+--- a/sound/usb/endpoint.h
++++ b/sound/usb/endpoint.h
+@@ -14,7 +14,8 @@ struct snd_usb_endpoint *
+ snd_usb_endpoint_open(struct snd_usb_audio *chip,
+                     const struct audioformat *fp,
+                     const struct snd_pcm_hw_params *params,
+-                    bool is_sync_ep);
++                    bool is_sync_ep,
++                    bool fixed_rate);
+ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
+                           struct snd_usb_endpoint *ep);
+ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
+diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c
+index f3e8484b3d9cb..41ac7185b42b6 100644
+--- a/sound/usb/implicit.c
++++ b/sound/usb/implicit.c
+@@ -15,6 +15,7 @@
+ #include "usbaudio.h"
+ #include "card.h"
+ #include "helper.h"
++#include "pcm.h"
+ #include "implicit.h"
+ enum {
+@@ -455,7 +456,8 @@ const struct audioformat *
+ snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
+                                    const struct audioformat *target,
+                                    const struct snd_pcm_hw_params *params,
+-                                   int stream)
++                                   int stream,
++                                   bool *fixed_rate)
+ {
+       struct snd_usb_substream *subs;
+       const struct audioformat *fp, *sync_fmt = NULL;
+@@ -483,6 +485,8 @@ snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
+               }
+       }
++      if (fixed_rate)
++              *fixed_rate = snd_usb_pcm_has_fixed_rate(subs);
+       return sync_fmt;
+ }
+diff --git a/sound/usb/implicit.h b/sound/usb/implicit.h
+index ccb415a0ea860..7f1577b6c4d38 100644
+--- a/sound/usb/implicit.h
++++ b/sound/usb/implicit.h
+@@ -9,6 +9,6 @@ const struct audioformat *
+ snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
+                                    const struct audioformat *target,
+                                    const struct snd_pcm_hw_params *params,
+-                                   int stream);
++                                   int stream, bool *fixed_rate);
+ #endif /* __USBAUDIO_IMPLICIT_H */
+diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
+index 7f09191c83d0e..962a6e1bc70c8 100644
+--- a/sound/usb/pcm.c
++++ b/sound/usb/pcm.c
+@@ -157,6 +157,31 @@ find_substream_format(struct snd_usb_substream *subs,
+                          true, subs);
+ }
++bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *subs)
++{
++      const struct audioformat *fp;
++      struct snd_usb_audio *chip = subs->stream->chip;
++      int rate = -1;
++
++      if (!(chip->quirk_flags & QUIRK_FLAG_FIXED_RATE))
++              return false;
++      list_for_each_entry(fp, &subs->fmt_list, list) {
++              if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
++                      return false;
++              if (fp->nr_rates < 1)
++                      continue;
++              if (fp->nr_rates > 1)
++                      return false;
++              if (rate < 0) {
++                      rate = fp->rate_table[0];
++                      continue;
++              }
++              if (rate != fp->rate_table[0])
++                      return false;
++      }
++      return true;
++}
++
+ static int init_pitch_v1(struct snd_usb_audio *chip, int ep)
+ {
+       struct usb_device *dev = chip->dev;
+@@ -450,12 +475,14 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+       struct snd_usb_audio *chip = subs->stream->chip;
+       const struct audioformat *fmt;
+       const struct audioformat *sync_fmt;
++      bool fixed_rate, sync_fixed_rate;
+       int ret;
+       ret = snd_media_start_pipeline(subs);
+       if (ret)
+               return ret;
++      fixed_rate = snd_usb_pcm_has_fixed_rate(subs);
+       fmt = find_substream_format(subs, hw_params);
+       if (!fmt) {
+               usb_audio_dbg(chip,
+@@ -469,7 +496,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+       if (fmt->implicit_fb) {
+               sync_fmt = snd_usb_find_implicit_fb_sync_format(chip, fmt,
+                                                               hw_params,
+-                                                              !substream->stream);
++                                                              !substream->stream,
++                                                              &sync_fixed_rate);
+               if (!sync_fmt) {
+                       usb_audio_dbg(chip,
+                                     "cannot find sync format: ep=0x%x, iface=%d:%d, format=%s, rate=%d, channels=%d\n",
+@@ -482,6 +510,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+               }
+       } else {
+               sync_fmt = fmt;
++              sync_fixed_rate = fixed_rate;
+       }
+       ret = snd_usb_lock_shutdown(chip);
+@@ -501,7 +530,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+               close_endpoints(chip, subs);
+       }
+-      subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false);
++      subs->data_endpoint = snd_usb_endpoint_open(chip, fmt, hw_params, false, fixed_rate);
+       if (!subs->data_endpoint) {
+               ret = -EINVAL;
+               goto unlock;
+@@ -510,7 +539,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+       if (fmt->sync_ep) {
+               subs->sync_endpoint = snd_usb_endpoint_open(chip, sync_fmt,
+                                                           hw_params,
+-                                                          fmt == sync_fmt);
++                                                          fmt == sync_fmt,
++                                                          sync_fixed_rate);
+               if (!subs->sync_endpoint) {
+                       ret = -EINVAL;
+                       goto unlock;
+diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h
+index 493a4e34d78dc..388fe2ba346d6 100644
+--- a/sound/usb/pcm.h
++++ b/sound/usb/pcm.h
+@@ -6,6 +6,8 @@ void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream);
+ int snd_usb_pcm_suspend(struct snd_usb_stream *as);
+ int snd_usb_pcm_resume(struct snd_usb_stream *as);
++bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *as);
++
+ int snd_usb_init_pitch(struct snd_usb_audio *chip,
+                      const struct audioformat *fmt);
+ void snd_usb_preallocate_buffer(struct snd_usb_substream *subs);
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index b9c0affb79b10..a765da40eb27d 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1896,6 +1896,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+                  QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+       DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */
+                  QUIRK_FLAG_IFACE_SKIP_CLOSE),
++      DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */
++                 QUIRK_FLAG_FIXED_RATE),
+       /* Vendor matches */
+       VENDOR_FLG(0x045e, /* MS Lifecam */
+diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
+index 2aba508a48312..f5a8dca66457f 100644
+--- a/sound/usb/usbaudio.h
++++ b/sound/usb/usbaudio.h
+@@ -175,6 +175,9 @@ extern bool snd_usb_skip_validation;
+  * QUIRK_FLAG_FORCE_IFACE_RESET
+  *  Force an interface reset whenever stopping & restarting a stream
+  *  (e.g. after xrun)
++ * QUIRK_FLAG_FIXED_RATE
++ *  Do not set PCM rate (frequency) when only one rate is available
++ *  for the given endpoint.
+  */
+ #define QUIRK_FLAG_GET_SAMPLE_RATE    (1U << 0)
+@@ -198,5 +201,6 @@ extern bool snd_usb_skip_validation;
+ #define QUIRK_FLAG_SKIP_IMPLICIT_FB   (1U << 18)
+ #define QUIRK_FLAG_IFACE_SKIP_CLOSE   (1U << 19)
+ #define QUIRK_FLAG_FORCE_IFACE_RESET  (1U << 20)
++#define QUIRK_FLAG_FIXED_RATE         (1U << 21)
+ #endif /* __USBAUDIO_H */
+-- 
+2.43.0
+
diff --git a/queue-5.15/alsa-usb-audio-add-quirk-for-rode-nt-usb.patch b/queue-5.15/alsa-usb-audio-add-quirk-for-rode-nt-usb.patch
new file mode 100644 (file)
index 0000000..5a31188
--- /dev/null
@@ -0,0 +1,55 @@
+From 3e3ebc8ac5c58c699a72c93087ca5550b9d4f64d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jan 2024 15:15:24 +0000
+Subject: ALSA: usb-audio: add quirk for RODE NT-USB+
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Sean Young <sean@mess.org>
+
+[ Upstream commit 7822baa844a87cbb93308c1032c3d47d4079bb8a ]
+
+The RODE NT-USB+ is marketed as a professional usb microphone, however the
+usb audio interface is a mess:
+
+[    1.130977] usb 1-5: new full-speed USB device number 2 using xhci_hcd
+[    1.503906] usb 1-5: config 1 has an invalid interface number: 5 but max is 4
+[    1.503912] usb 1-5: config 1 has no interface number 4
+[    1.519689] usb 1-5: New USB device found, idVendor=19f7, idProduct=0035, bcdDevice= 1.09
+[    1.519695] usb 1-5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
+[    1.519697] usb 1-5: Product: RØDE NT-USB+
+[    1.519699] usb 1-5: Manufacturer: RØDE
+[    1.519700] usb 1-5: SerialNumber: 1D773A1A
+[    8.327495] usb 1-5: 1:1: cannot get freq at ep 0x82
+[    8.344500] usb 1-5: 1:2: cannot get freq at ep 0x82
+[    8.365499] usb 1-5: 2:1: cannot get freq at ep 0x2
+
+Add QUIRK_FLAG_GET_SAMPLE_RATE to work around the broken sample rate get.
+I have asked Rode support to fix it, but they show no interest.
+
+Signed-off-by: Sean Young <sean@mess.org>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20240124151524.23314-1-sean@mess.org
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index 39313db7aed3f..6cd7f77779159 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1900,6 +1900,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+                  QUIRK_FLAG_FIXED_RATE),
+       DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
++      DEVICE_FLG(0x19f7, 0x0035, /* RODE NT-USB+ */
++                 QUIRK_FLAG_GET_SAMPLE_RATE),
+       /* Vendor matches */
+       VENDOR_FLG(0x045e, /* MS Lifecam */
+-- 
+2.43.0
+
diff --git a/queue-5.15/alsa-usb-audio-add-quirk-for-tascam-model-12.patch b/queue-5.15/alsa-usb-audio-add-quirk-for-tascam-model-12.patch
new file mode 100644 (file)
index 0000000..a58154f
--- /dev/null
@@ -0,0 +1,105 @@
+From 0aec1a0b154daba5a66d3f310f4c1d75cb63fe95 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 29 Nov 2022 13:00:59 +0000
+Subject: ALSA: usb-audio: Add quirk for Tascam Model 12
+
+From: John Keeping <john@metanate.com>
+
+[ Upstream commit 67df411db3f0209e4bb5227d4dd9d41b21368b9d ]
+
+Tascam's Model 12 is a mixer which can also operate as a USB audio
+interface.  The audio interface uses explicit feedback but it seems that
+it does not correctly handle missing isochronous frames.
+
+When injecting an xrun (or doing anything else that pauses the playback
+stream) the feedback rate climbs (for example, at 44,100Hz nominal, I
+see a stable rate around 44,099 but xrun injection sees this peak at
+around 44,135 in most cases) and glitches are heard in the audio stream
+for several seconds - this is significantly worse than the single glitch
+expected for an underrun.
+
+While the stream does normally recover and the feedback rate returns to
+a stable value, I have seen some occurrences where this does not happen
+and the rate continues to increase while no audio is heard from the
+output.  I have not found a solid reproduction for this.
+
+This misbehaviour can be avoided by totally resetting the stream state
+by switching the interface to alt 0 and back before restarting the
+playback stream.
+
+Add a new quirk flag which forces the endpoint and interface to be
+reconfigured whenever the stream is stopped, and use this for the Tascam
+Model 12.
+
+Separate interfaces are used for the playback and capture endpoints, so
+resetting the playback interface here will not affect the capture stream
+if it is running.  While there are two endpoints on the interface,
+these are the OUT data endpoint and the IN explicit feedback endpoint
+corresponding to it and these are always stopped and started together.
+
+Signed-off-by: John Keeping <john@metanate.com>
+Link: https://lore.kernel.org/r/20221129130100.1257904-1-john@metanate.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/endpoint.c | 7 +++++++
+ sound/usb/quirks.c   | 2 ++
+ sound/usb/usbaudio.h | 4 ++++
+ 3 files changed, 13 insertions(+)
+
+diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
+index cf48d7ccc496e..aca9ebfec22c8 100644
+--- a/sound/usb/endpoint.c
++++ b/sound/usb/endpoint.c
+@@ -1674,6 +1674,13 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, bool keep_pending)
+               stop_urbs(ep, false, keep_pending);
+               if (ep->clock_ref)
+                       atomic_dec(&ep->clock_ref->locked);
++
++              if (ep->chip->quirk_flags & QUIRK_FLAG_FORCE_IFACE_RESET &&
++                  usb_pipeout(ep->pipe)) {
++                      ep->need_prepare = true;
++                      if (ep->iface_ref)
++                              ep->iface_ref->need_setup = true;
++              }
+       }
+ }
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index 03b6a07a2ea05..b9c0affb79b10 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1786,6 +1786,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+       DEVICE_FLG(0x0644, 0x804a, /* TEAC UD-301 */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
+                  QUIRK_FLAG_IFACE_DELAY),
++      DEVICE_FLG(0x0644, 0x805f, /* TEAC Model 12 */
++                 QUIRK_FLAG_FORCE_IFACE_RESET),
+       DEVICE_FLG(0x06f8, 0xb000, /* Hercules DJ Console (Windows Edition) */
+                  QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x06f8, 0xd002, /* Hercules DJ Console (Macintosh Edition) */
+diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
+index e97141ef730ad..2aba508a48312 100644
+--- a/sound/usb/usbaudio.h
++++ b/sound/usb/usbaudio.h
+@@ -172,6 +172,9 @@ extern bool snd_usb_skip_validation;
+  *  Don't apply implicit feedback sync mode
+  * QUIRK_FLAG_IFACE_SKIP_CLOSE
+  *  Don't closed interface during setting sample rate
++ * QUIRK_FLAG_FORCE_IFACE_RESET
++ *  Force an interface reset whenever stopping & restarting a stream
++ *  (e.g. after xrun)
+  */
+ #define QUIRK_FLAG_GET_SAMPLE_RATE    (1U << 0)
+@@ -194,5 +197,6 @@ extern bool snd_usb_skip_validation;
+ #define QUIRK_FLAG_GENERIC_IMPLICIT_FB        (1U << 17)
+ #define QUIRK_FLAG_SKIP_IMPLICIT_FB   (1U << 18)
+ #define QUIRK_FLAG_IFACE_SKIP_CLOSE   (1U << 19)
++#define QUIRK_FLAG_FORCE_IFACE_RESET  (1U << 20)
+ #endif /* __USBAUDIO_H */
+-- 
+2.43.0
+
diff --git a/queue-5.15/alsa-usb-audio-always-initialize-fixed_rate-in-snd_u.patch b/queue-5.15/alsa-usb-audio-always-initialize-fixed_rate-in-snd_u.patch
new file mode 100644 (file)
index 0000000..f9c11f9
--- /dev/null
@@ -0,0 +1,62 @@
+From 3b4ebf37bf47cb2aa1f562fc2fe1c777c4111011 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Jan 2023 15:11:33 +0100
+Subject: ALSA: usb-audio: Always initialize fixed_rate in
+ snd_usb_find_implicit_fb_sync_format()
+
+From: Jaroslav Kysela <perex@perex.cz>
+
+[ Upstream commit 291e9da91403e0e628d7692b5ed505100e7b7706 ]
+
+Handle the fallback code path, too.
+
+Fixes: fd28941cff1c ("ALSA: usb-audio: Add new quirk FIXED_RATE for JBL Quantum810 Wireless")
+BugLink: https://lore.kernel.org/alsa-devel/Y7frf3N%2FxzvESEsN@kili/
+Reported-by: Dan Carpenter <error27@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Jaroslav Kysela <perex@perex.cz>
+Link: https://lore.kernel.org/r/20230109141133.335543-1-perex@perex.cz
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/implicit.c | 3 ++-
+ sound/usb/pcm.c      | 2 ++
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c
+index 41ac7185b42b6..4727043fd7458 100644
+--- a/sound/usb/implicit.c
++++ b/sound/usb/implicit.c
+@@ -471,7 +471,7 @@ snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
+       subs = find_matching_substream(chip, stream, target->sync_ep,
+                                      target->fmt_type);
+       if (!subs)
+-              return sync_fmt;
++              goto end;
+       high_score = 0;
+       list_for_each_entry(fp, &subs->fmt_list, list) {
+@@ -485,6 +485,7 @@ snd_usb_find_implicit_fb_sync_format(struct snd_usb_audio *chip,
+               }
+       }
++ end:
+       if (fixed_rate)
+               *fixed_rate = snd_usb_pcm_has_fixed_rate(subs);
+       return sync_fmt;
+diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
+index 962a6e1bc70c8..580e2649641e4 100644
+--- a/sound/usb/pcm.c
++++ b/sound/usb/pcm.c
+@@ -163,6 +163,8 @@ bool snd_usb_pcm_has_fixed_rate(struct snd_usb_substream *subs)
+       struct snd_usb_audio *chip = subs->stream->chip;
+       int rate = -1;
++      if (!subs)
++              return false;
+       if (!(chip->quirk_flags & QUIRK_FLAG_FIXED_RATE))
+               return false;
+       list_for_each_entry(fp, &subs->fmt_list, list) {
+-- 
+2.43.0
+
diff --git a/queue-5.15/alsa-usb-audio-apply-mutex-around-snd_usb_endpoint_s.patch b/queue-5.15/alsa-usb-audio-apply-mutex-around-snd_usb_endpoint_s.patch
new file mode 100644 (file)
index 0000000..1bcb9cc
--- /dev/null
@@ -0,0 +1,61 @@
+From e2e430d64853facb3c48bc3da2e42af6150d0859 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Oct 2022 12:42:10 +0200
+Subject: ALSA: usb-audio: Apply mutex around snd_usb_endpoint_set_params()
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit a74f8d0aa902ca494676b79226e0b5a1747b81d4 ]
+
+The protection with chip->mutex was lost after splitting
+snd_usb_endpoint_set_params() and snd_usb_endpoint_prepare().
+Apply the same mutex again to the former function.
+
+Fixes: 2be79d586454 ("ALSA: usb-audio: Split endpoint setups for hw_params and prepare (take#2)")
+Link: https://lore.kernel.org/r/20221009104212.18877-3-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/endpoint.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
+index 2d3f814d067b5..486ef6b022552 100644
+--- a/sound/usb/endpoint.c
++++ b/sound/usb/endpoint.c
+@@ -1339,10 +1339,11 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
+       const struct audioformat *fmt = ep->cur_audiofmt;
+       int err;
++      mutex_lock(&chip->mutex);
+       /* release old buffers, if any */
+       err = release_urbs(ep, false);
+       if (err < 0)
+-              return err;
++              goto unlock;
+       ep->datainterval = fmt->datainterval;
+       ep->maxpacksize = fmt->maxpacksize;
+@@ -1380,13 +1381,16 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
+       usb_audio_dbg(chip, "Set up %d URBS, ret=%d\n", ep->nurbs, err);
+       if (err < 0)
+-              return err;
++              goto unlock;
+       /* some unit conversions in runtime */
+       ep->maxframesize = ep->maxpacksize / ep->cur_frame_bytes;
+       ep->curframesize = ep->curpacksize / ep->cur_frame_bytes;
+-      return update_clock_ref_rate(chip, ep);
++      err = update_clock_ref_rate(chip, ep);
++ unlock:
++      mutex_unlock(&chip->mutex);
++      return err;
+ }
+ static int init_sample_rate(struct snd_usb_audio *chip,
+-- 
+2.43.0
+
diff --git a/queue-5.15/alsa-usb-audio-avoid-superfluous-endpoint-setup.patch b/queue-5.15/alsa-usb-audio-avoid-superfluous-endpoint-setup.patch
new file mode 100644 (file)
index 0000000..25b5646
--- /dev/null
@@ -0,0 +1,108 @@
+From 8171e13b9cf1455b6516fa0a820830a439f2f7de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Oct 2022 12:42:12 +0200
+Subject: ALSA: usb-audio: Avoid superfluous endpoint setup
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 1045f5f1ff0751423aeb65648e5e1abd7a7a8672 ]
+
+After splitting to snd_usb_endpoint_set_params() and *_prepare(), the
+skip of each function should be checked with different flags, while we
+still use ep->need_setup as the single one.  Introduce
+ep->need_prepare for indicating the need of prepare, and also add the
+missing check of ep->need_setup at the set_params.
+
+Fixes: 2be79d586454 ("ALSA: usb-audio: Split endpoint setups for hw_params and prepare (take#2)")
+Link: https://lore.kernel.org/r/20221009104212.18877-5-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/card.h     |  3 ++-
+ sound/usb/endpoint.c | 17 ++++++++++++-----
+ 2 files changed, 14 insertions(+), 6 deletions(-)
+
+diff --git a/sound/usb/card.h b/sound/usb/card.h
+index ca75f2206170f..40061550105ac 100644
+--- a/sound/usb/card.h
++++ b/sound/usb/card.h
+@@ -129,7 +129,8 @@ struct snd_usb_endpoint {
+                                          in a stream */
+       bool implicit_fb_sync;          /* syncs with implicit feedback */
+       bool lowlatency_playback;       /* low-latency playback mode */
+-      bool need_setup;                /* (re-)need for configure? */
++      bool need_setup;                /* (re-)need for hw_params? */
++      bool need_prepare;              /* (re-)need for prepare? */
+       /* for hw constraints */
+       const struct audioformat *cur_audiofmt;
+diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
+index 80ead3db4d1c7..cf48d7ccc496e 100644
+--- a/sound/usb/endpoint.c
++++ b/sound/usb/endpoint.c
+@@ -829,6 +829,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
+               ep->implicit_fb_sync = fp->implicit_fb;
+               ep->need_setup = true;
++              ep->need_prepare = true;
+               usb_audio_dbg(chip, "  channels=%d, rate=%d, format=%s, period_bytes=%d, periods=%d, implicit_fb=%d\n",
+                             ep->cur_channels, ep->cur_rate,
+@@ -954,7 +955,7 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
+ /* Prepare for suspening EP, called from the main suspend handler */
+ void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep)
+ {
+-      ep->need_setup = true;
++      ep->need_prepare = true;
+       if (ep->iface_ref)
+               ep->iface_ref->need_setup = true;
+       if (ep->clock_ref)
+@@ -1337,9 +1338,12 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
+                               struct snd_usb_endpoint *ep)
+ {
+       const struct audioformat *fmt = ep->cur_audiofmt;
+-      int err;
++      int err = 0;
+       mutex_lock(&chip->mutex);
++      if (!ep->need_setup)
++              goto unlock;
++
+       /* release old buffers, if any */
+       err = release_urbs(ep, false);
+       if (err < 0)
+@@ -1388,8 +1392,11 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
+       ep->curframesize = ep->curpacksize / ep->cur_frame_bytes;
+       err = update_clock_ref_rate(chip, ep);
+-      if (err >= 0)
++      if (err >= 0) {
++              ep->need_setup = false;
+               err = 0;
++      }
++
+  unlock:
+       mutex_unlock(&chip->mutex);
+       return err;
+@@ -1439,7 +1446,7 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
+       mutex_lock(&chip->mutex);
+       if (WARN_ON(!ep->iface_ref))
+               goto unlock;
+-      if (!ep->need_setup)
++      if (!ep->need_prepare)
+               goto unlock;
+       /* If the interface has been already set up, just set EP parameters */
+@@ -1493,7 +1500,7 @@ int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
+       ep->iface_ref->need_setup = false;
+  done:
+-      ep->need_setup = false;
++      ep->need_prepare = false;
+       err = 1;
+ unlock:
+-- 
+2.43.0
+
diff --git a/queue-5.15/alsa-usb-audio-clear-fixed-clock-rate-at-closing-ep.patch b/queue-5.15/alsa-usb-audio-clear-fixed-clock-rate-at-closing-ep.patch
new file mode 100644 (file)
index 0000000..6a6fbc5
--- /dev/null
@@ -0,0 +1,56 @@
+From a0573be416ef827a9a82df1737196e584fd0af79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Sep 2022 12:04:21 +0200
+Subject: ALSA: usb-audio: Clear fixed clock rate at closing EP
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 809f44a0cc5ad4b1209467a6287f8ac0eb49d393 ]
+
+The recent commit c11117b634f4 ("ALSA: usb-audio: Refcount multiple
+accesses on the single clock") tries to manage the clock rate shared
+by several endpoints.  This was intended for avoiding the unmatched
+rate by a different endpoint, but unfortunately, it introduced a
+regression for PulseAudio and pipewire, too; those applications try to
+probe the multiple possible rates (44.1k and 48kHz) and setting up the
+normal rate fails but only the last rate is applied.
+
+The cause is that the last sample rate is still left to the clock
+reference even after closing the endpoint, and this value is still
+used at the next open.  It happens only when applications set up via
+PCM prepare but don't start/stop the stream; the rate is reset when
+the stream is stopped, but it's not cleared at close.
+
+This patch addresses the issue above, simply by clearing the rate set
+in the clock reference at the last close of each endpoint.
+
+Fixes: c11117b634f4 ("ALSA: usb-audio: Refcount multiple accesses on the single clock")
+Reported-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Tested-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/all/YxXIWv8dYmg1tnXP@zx2c4.com/
+Link: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/2620
+Link: https://lore.kernel.org/r/20220907100421.6443-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/endpoint.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
+index 803053d4c9dbc..13c0264881499 100644
+--- a/sound/usb/endpoint.c
++++ b/sound/usb/endpoint.c
+@@ -932,6 +932,8 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
+               endpoint_set_interface(chip, ep, false);
+       if (!--ep->opened) {
++              if (ep->clock_ref && !atomic_read(&ep->clock_ref->locked))
++                      ep->clock_ref->rate = 0;
+               ep->iface = 0;
+               ep->altsetting = 0;
+               ep->cur_audiofmt = NULL;
+-- 
+2.43.0
+
diff --git a/queue-5.15/alsa-usb-audio-correct-the-return-code-from-snd_usb_.patch b/queue-5.15/alsa-usb-audio-correct-the-return-code-from-snd_usb_.patch
new file mode 100644 (file)
index 0000000..1132143
--- /dev/null
@@ -0,0 +1,38 @@
+From 2447216d3956accd7b3fb5f1d85afe5e88c0d08d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Oct 2022 12:42:11 +0200
+Subject: ALSA: usb-audio: Correct the return code from
+ snd_usb_endpoint_set_params()
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 9355b60e401d825590d37f04ea873c58efe9b7bf ]
+
+snd_usb_endpoint_set_params() should return zero for a success, but
+currently it returns the sample rate.  Correct it.
+
+Fixes: 2be79d586454 ("ALSA: usb-audio: Split endpoint setups for hw_params and prepare (take#2)")
+Link: https://lore.kernel.org/r/20221009104212.18877-4-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/endpoint.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
+index 486ef6b022552..80ead3db4d1c7 100644
+--- a/sound/usb/endpoint.c
++++ b/sound/usb/endpoint.c
+@@ -1388,6 +1388,8 @@ int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
+       ep->curframesize = ep->curpacksize / ep->cur_frame_bytes;
+       err = update_clock_ref_rate(chip, ep);
++      if (err >= 0)
++              err = 0;
+  unlock:
+       mutex_unlock(&chip->mutex);
+       return err;
+-- 
+2.43.0
+
diff --git a/queue-5.15/alsa-usb-audio-fix-microphone-sound-on-nexigo-webcam.patch b/queue-5.15/alsa-usb-audio-fix-microphone-sound-on-nexigo-webcam.patch
new file mode 100644 (file)
index 0000000..ca645dc
--- /dev/null
@@ -0,0 +1,143 @@
+From 286d9d3541f3c2fc1c6baea3fd2c0d9ac0682ff2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Oct 2023 17:53:30 +0200
+Subject: ALSA: usb-audio: Fix microphone sound on Nexigo webcam.
+
+From: Christos Skevis <xristos.thes@gmail.com>
+
+[ Upstream commit 4a63e68a295187ae3c1cb3fa0c583c96a959714f ]
+
+I own an external usb Webcam, model NexiGo N930AF, which had low mic volume and
+inconsistent sound quality. Video works as expected.
+
+(snip)
+[  +0.047857] usb 5-1: new high-speed USB device number 2 using xhci_hcd
+[  +0.003406] usb 5-1: New USB device found, idVendor=1bcf, idProduct=2283, bcdDevice=12.17
+[  +0.000007] usb 5-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
+[  +0.000004] usb 5-1: Product: NexiGo N930AF FHD Webcam
+[  +0.000003] usb 5-1: Manufacturer: SHENZHEN AONI ELECTRONIC CO., LTD
+[  +0.000004] usb 5-1: SerialNumber: 20201217011
+[  +0.003900] usb 5-1: Found UVC 1.00 device NexiGo N930AF FHD Webcam (1bcf:2283)
+[  +0.025726] usb 5-1: 3:1: cannot get usb sound sample rate freq at ep 0x86
+[  +0.071482] usb 5-1: 3:2: cannot get usb sound sample rate freq at ep 0x86
+[  +0.004679] usb 5-1: 3:3: cannot get usb sound sample rate freq at ep 0x86
+[  +0.051607] usb 5-1: Warning! Unlikely big volume range (=4096), cval->res is probably wrong.
+[  +0.000005] usb 5-1: [7] FU [Mic Capture Volume] ch = 1, val = 0/4096/1
+
+Set up quirk cval->res to 16 for 256 levels,
+Set GET_SAMPLE_RATE quirk flag to stop trying to get the sample rate.
+Confirmed that happened anyway later due to the backoff mechanism, after 3 failures
+
+All audio stream on device interfaces share the same values,
+apart from wMaxPacketSize and tSamFreq :
+
+(snip)
+Interface Descriptor:
+      bLength                 9
+      bDescriptorType         4
+      bInterfaceNumber        3
+      bAlternateSetting       3
+      bNumEndpoints           1
+      bInterfaceClass         1 Audio
+      bInterfaceSubClass      2 Streaming
+      bInterfaceProtocol      0
+      iInterface              0
+      AudioStreaming Interface Descriptor:
+        bLength                 7
+        bDescriptorType        36
+        bDescriptorSubtype      1 (AS_GENERAL)
+        bTerminalLink           8
+        bDelay                  1 frames
+        wFormatTag         0x0001 PCM
+      AudioStreaming Interface Descriptor:
+        bLength                11
+        bDescriptorType        36
+        bDescriptorSubtype      2 (FORMAT_TYPE)
+        bFormatType             1 (FORMAT_TYPE_I)
+        bNrChannels             1
+        bSubframeSize           2
+        bBitResolution         16
+        bSamFreqType            1 Discrete
+        tSamFreq[ 0]        44100
+      Endpoint Descriptor:
+        bLength                 9
+        bDescriptorType         5
+        bEndpointAddress     0x86  EP 6 IN
+        bmAttributes            5
+          Transfer Type            Isochronous
+          Synch Type               Asynchronous
+          Usage Type               Data
+        wMaxPacketSize     0x005c  1x 92 bytes
+        bInterval               4
+        bRefresh                0
+        bSynchAddress           0
+        AudioStreaming Endpoint Descriptor:
+          bLength                 7
+          bDescriptorType        37
+          bDescriptorSubtype      1 (EP_GENERAL)
+          bmAttributes         0x01
+            Sampling Frequency
+          bLockDelayUnits         0 Undefined
+          wLockDelay         0x0000
+(snip)
+
+Based on the usb data about manufacturer, SPCA2281B3 is the most likely controller IC
+Manufacturer does not provide link for datasheet nor detailed specs.
+No way to confirm if the firmware supports any other way of getting the sample rate.
+
+Testing patch provides consistent good sound recording quality and volume range.
+
+(snip)
+[  +0.045764] usb 5-1: new high-speed USB device number 2 using xhci_hcd
+[  +0.106290] usb 5-1: New USB device found, idVendor=1bcf, idProduct=2283, bcdDevice=12.17
+[  +0.000006] usb 5-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
+[  +0.000004] usb 5-1: Product: NexiGo N930AF FHD Webcam
+[  +0.000003] usb 5-1: Manufacturer: SHENZHEN AONI ELECTRONIC CO., LTD
+[  +0.000004] usb 5-1: SerialNumber: 20201217011
+[  +0.043700] usb 5-1: set resolution quirk: cval->res = 16
+[  +0.002585] usb 5-1: Found UVC 1.00 device NexiGo N930AF FHD Webcam (1bcf:2283)
+
+Signed-off-by: Christos Skevis <xristos.thes@gmail.com>
+Link: https://lore.kernel.org/r/20231006155330.399393-1-xristos.thes@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/mixer.c  | 7 +++++++
+ sound/usb/quirks.c | 2 ++
+ 2 files changed, 9 insertions(+)
+
+diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
+index 567514832b0df..d818eee53c90a 100644
+--- a/sound/usb/mixer.c
++++ b/sound/usb/mixer.c
+@@ -1205,6 +1205,13 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval,
+                       cval->res = 16;
+               }
+               break;
++      case USB_ID(0x1bcf, 0x2283): /* NexiGo N930AF FHD Webcam */
++              if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
++                      usb_audio_info(chip,
++                              "set resolution quirk: cval->res = 16\n");
++                      cval->res = 16;
++              }
++              break;
+       }
+ }
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index a765da40eb27d..39313db7aed3f 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1898,6 +1898,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+                  QUIRK_FLAG_IFACE_SKIP_CLOSE),
+       DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */
+                  QUIRK_FLAG_FIXED_RATE),
++      DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */
++                 QUIRK_FLAG_GET_SAMPLE_RATE),
+       /* Vendor matches */
+       VENDOR_FLG(0x045e, /* MS Lifecam */
+-- 
+2.43.0
+
diff --git a/queue-5.15/alsa-usb-audio-fix-wrong-kfree-issue-in-snd_usb_endp.patch b/queue-5.15/alsa-usb-audio-fix-wrong-kfree-issue-in-snd_usb_endp.patch
new file mode 100644 (file)
index 0000000..3ac89d2
--- /dev/null
@@ -0,0 +1,39 @@
+From e6c903d9f2cf00516280b571ba2b22d0b540663b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 18 May 2022 10:16:16 +0800
+Subject: ALSA: usb-audio: Fix wrong kfree issue in snd_usb_endpoint_free_all
+
+From: Wan Jiabing <wanjiabing@vivo.com>
+
+[ Upstream commit 03a8b0df757f1beb21ba1626e23ca7412e48b525 ]
+
+Fix following coccicheck error:
+./sound/usb/endpoint.c:1671:8-10: ERROR: reference preceded by free on line 1671.
+
+Here should be 'cp' rather than 'ip'.
+
+Fixes: c11117b634f4 ("ALSA: usb-audio: Refcount multiple accesses on the single clock")
+Signed-off-by: Wan Jiabing <wanjiabing@vivo.com>
+Link: https://lore.kernel.org/r/20220518021617.10114-1-wanjiabing@vivo.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/endpoint.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
+index 26af199f3836e..8188113ca83f2 100644
+--- a/sound/usb/endpoint.c
++++ b/sound/usb/endpoint.c
+@@ -1720,7 +1720,7 @@ void snd_usb_endpoint_free_all(struct snd_usb_audio *chip)
+               kfree(ip);
+       list_for_each_entry_safe(cp, cn, &chip->clock_ref_list, list)
+-              kfree(ip);
++              kfree(cp);
+ }
+ /*
+-- 
+2.43.0
+
diff --git a/queue-5.15/alsa-usb-audio-properly-refcounting-clock-rate.patch b/queue-5.15/alsa-usb-audio-properly-refcounting-clock-rate.patch
new file mode 100644 (file)
index 0000000..5c9da82
--- /dev/null
@@ -0,0 +1,74 @@
+From dc04dbbb44380b1d0bbb4b7fdc37377bd6bc131a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Sep 2022 20:11:26 +0200
+Subject: ALSA: usb-audio: Properly refcounting clock rate
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 9a737e7f8b371e97eb649904276407cee2c9cf30 ]
+
+We fixed the bug introduced by the patch for managing the shared
+clocks at the commit 809f44a0cc5a ("ALSA: usb-audio: Clear fixed clock
+rate at closing EP"), but it was merely a workaround.  By this change,
+the clock reference rate is cleared at each EP close, hence the still
+remaining EP may need a re-setup of rate unnecessarily.
+
+This patch introduces the proper refcounting for the clock reference
+object so that the clock setup is done only when needed.
+
+Fixes: 809f44a0cc5a ("ALSA: usb-audio: Clear fixed clock rate at closing EP")
+Fixes: c11117b634f4 ("ALSA: usb-audio: Refcount multiple accesses on the single clock")
+Link: https://lore.kernel.org/r/20220920181126.4912-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/endpoint.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
+index 32a9e016665c8..2d3f814d067b5 100644
+--- a/sound/usb/endpoint.c
++++ b/sound/usb/endpoint.c
+@@ -39,6 +39,7 @@ struct snd_usb_iface_ref {
+ struct snd_usb_clock_ref {
+       unsigned char clock;
+       atomic_t locked;
++      int opened;
+       int rate;
+       bool need_setup;
+       struct list_head list;
+@@ -810,6 +811,7 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
+                               ep = NULL;
+                               goto unlock;
+                       }
++                      ep->clock_ref->opened++;
+               }
+               ep->cur_audiofmt = fp;
+@@ -934,8 +936,10 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
+               endpoint_set_interface(chip, ep, false);
+       if (!--ep->opened) {
+-              if (ep->clock_ref && !atomic_read(&ep->clock_ref->locked))
+-                      ep->clock_ref->rate = 0;
++              if (ep->clock_ref) {
++                      if (!--ep->clock_ref->opened)
++                              ep->clock_ref->rate = 0;
++              }
+               ep->iface = 0;
+               ep->altsetting = 0;
+               ep->cur_audiofmt = NULL;
+@@ -1656,8 +1660,7 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, bool keep_pending)
+                       WRITE_ONCE(ep->sync_source->sync_sink, NULL);
+               stop_urbs(ep, false, keep_pending);
+               if (ep->clock_ref)
+-                      if (!atomic_dec_return(&ep->clock_ref->locked))
+-                              ep->clock_ref->rate = 0;
++                      atomic_dec(&ep->clock_ref->locked);
+       }
+ }
+-- 
+2.43.0
+
diff --git a/queue-5.15/alsa-usb-audio-refcount-multiple-accesses-on-the-sin.patch b/queue-5.15/alsa-usb-audio-refcount-multiple-accesses-on-the-sin.patch
new file mode 100644 (file)
index 0000000..a340977
--- /dev/null
@@ -0,0 +1,284 @@
+From 381513d78b7f803d2c58afc5a811b170164aa306 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 16 May 2022 12:48:07 +0200
+Subject: ALSA: usb-audio: Refcount multiple accesses on the single clock
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit c11117b634f4f832c4420d3cf41c44227f140ce1 ]
+
+When a clock source is connected to multiple nodes / endpoints, the
+current USB-audio driver tries to set up at each time one of them is
+configured.  Although it reads the current rate and updates only if it
+differs, some devices seem unhappy with this behavior and spew the
+errors when reading/updating the rate unnecessarily.
+
+This patch tries to reduce the redundant clock setup by introducing a
+refcount for each clock source.  When the stream is actually running,
+a clock rate is "locked", and it bypasses the clock and/or refuse to
+change any longer.
+
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=215934
+Link: https://lore.kernel.org/r/20220516104807.16482-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/card.c     |  1 +
+ sound/usb/card.h     |  3 +-
+ sound/usb/endpoint.c | 90 +++++++++++++++++++++++++++++++++++++++-----
+ sound/usb/usbaudio.h |  1 +
+ 4 files changed, 85 insertions(+), 10 deletions(-)
+
+diff --git a/sound/usb/card.c b/sound/usb/card.c
+index 550c6a72fb5bc..bebd42413fadb 100644
+--- a/sound/usb/card.c
++++ b/sound/usb/card.c
+@@ -643,6 +643,7 @@ static int snd_usb_audio_create(struct usb_interface *intf,
+       INIT_LIST_HEAD(&chip->pcm_list);
+       INIT_LIST_HEAD(&chip->ep_list);
+       INIT_LIST_HEAD(&chip->iface_ref_list);
++      INIT_LIST_HEAD(&chip->clock_ref_list);
+       INIT_LIST_HEAD(&chip->midi_list);
+       INIT_LIST_HEAD(&chip->mixer_list);
+diff --git a/sound/usb/card.h b/sound/usb/card.h
+index 87f042d06ce08..ca75f2206170f 100644
+--- a/sound/usb/card.h
++++ b/sound/usb/card.h
+@@ -44,6 +44,7 @@ struct audioformat {
+ struct snd_usb_substream;
+ struct snd_usb_iface_ref;
++struct snd_usb_clock_ref;
+ struct snd_usb_endpoint;
+ struct snd_usb_power_domain;
+@@ -62,6 +63,7 @@ struct snd_urb_ctx {
+ struct snd_usb_endpoint {
+       struct snd_usb_audio *chip;
+       struct snd_usb_iface_ref *iface_ref;
++      struct snd_usb_clock_ref *clock_ref;
+       int opened;             /* open refcount; protect with chip->mutex */
+       atomic_t running;       /* running status */
+@@ -138,7 +140,6 @@ struct snd_usb_endpoint {
+       unsigned int cur_period_frames;
+       unsigned int cur_period_bytes;
+       unsigned int cur_buffer_periods;
+-      unsigned char cur_clock;
+       spinlock_t lock;
+       struct list_head list;
+diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
+index 6c7d842d04965..803053d4c9dbc 100644
+--- a/sound/usb/endpoint.c
++++ b/sound/usb/endpoint.c
+@@ -35,6 +35,14 @@ struct snd_usb_iface_ref {
+       struct list_head list;
+ };
++/* clock refcounting */
++struct snd_usb_clock_ref {
++      unsigned char clock;
++      atomic_t locked;
++      int rate;
++      struct list_head list;
++};
++
+ /*
+  * snd_usb_endpoint is a model that abstracts everything related to an
+  * USB endpoint and its streaming.
+@@ -598,6 +606,25 @@ iface_ref_find(struct snd_usb_audio *chip, int iface)
+       return ip;
+ }
++/* Similarly, a refcount object for clock */
++static struct snd_usb_clock_ref *
++clock_ref_find(struct snd_usb_audio *chip, int clock)
++{
++      struct snd_usb_clock_ref *ref;
++
++      list_for_each_entry(ref, &chip->clock_ref_list, list)
++              if (ref->clock == clock)
++                      return ref;
++
++      ref = kzalloc(sizeof(*ref), GFP_KERNEL);
++      if (!ref)
++              return NULL;
++      ref->clock = clock;
++      atomic_set(&ref->locked, 0);
++      list_add_tail(&ref->list, &chip->clock_ref_list);
++      return ref;
++}
++
+ /*
+  * Get the existing endpoint object corresponding EP
+  * Returns NULL if not present.
+@@ -775,6 +802,14 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
+                       goto unlock;
+               }
++              if (fp->protocol != UAC_VERSION_1) {
++                      ep->clock_ref = clock_ref_find(chip, fp->clock);
++                      if (!ep->clock_ref) {
++                              ep = NULL;
++                              goto unlock;
++                      }
++              }
++
+               ep->cur_audiofmt = fp;
+               ep->cur_channels = fp->channels;
+               ep->cur_rate = params_rate(params);
+@@ -784,7 +819,6 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
+               ep->cur_period_frames = params_period_size(params);
+               ep->cur_period_bytes = ep->cur_period_frames * ep->cur_frame_bytes;
+               ep->cur_buffer_periods = params_periods(params);
+-              ep->cur_clock = fp->clock;
+               if (ep->type == SND_USB_ENDPOINT_TYPE_SYNC)
+                       endpoint_set_syncinterval(chip, ep);
+@@ -902,8 +936,8 @@ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
+               ep->altsetting = 0;
+               ep->cur_audiofmt = NULL;
+               ep->cur_rate = 0;
+-              ep->cur_clock = 0;
+               ep->iface_ref = NULL;
++              ep->clock_ref = NULL;
+               usb_audio_dbg(chip, "EP 0x%x closed\n", ep->ep_num);
+       }
+       mutex_unlock(&chip->mutex);
+@@ -915,6 +949,8 @@ void snd_usb_endpoint_suspend(struct snd_usb_endpoint *ep)
+       ep->need_setup = true;
+       if (ep->iface_ref)
+               ep->iface_ref->need_setup = true;
++      if (ep->clock_ref)
++              ep->clock_ref->rate = 0;
+ }
+ /*
+@@ -1321,6 +1357,33 @@ static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
+       return 0;
+ }
++static int init_sample_rate(struct snd_usb_audio *chip,
++                          struct snd_usb_endpoint *ep)
++{
++      struct snd_usb_clock_ref *clock = ep->clock_ref;
++      int err;
++
++      if (clock) {
++              if (atomic_read(&clock->locked))
++                      return 0;
++              if (clock->rate == ep->cur_rate)
++                      return 0;
++              if (clock->rate && clock->rate != ep->cur_rate) {
++                      usb_audio_dbg(chip, "Mismatched sample rate %d vs %d for EP 0x%x\n",
++                                    clock->rate, ep->cur_rate, ep->ep_num);
++                      return -EINVAL;
++              }
++      }
++
++      err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, ep->cur_rate);
++      if (err < 0)
++              return err;
++
++      if (clock)
++              clock->rate = ep->cur_rate;
++      return 0;
++}
++
+ /*
+  * snd_usb_endpoint_configure: Configure the endpoint
+  *
+@@ -1350,8 +1413,7 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
+                * to update at each EP configuration
+                */
+               if (ep->cur_audiofmt->protocol == UAC_VERSION_1) {
+-                      err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt,
+-                                                     ep->cur_rate);
++                      err = init_sample_rate(chip, ep);
+                       if (err < 0)
+                               goto unlock;
+               }
+@@ -1381,7 +1443,7 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
+       if (err < 0)
+               goto unlock;
+-      err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, ep->cur_rate);
++      err = init_sample_rate(chip, ep);
+       if (err < 0)
+               goto unlock;
+@@ -1414,15 +1476,15 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
+ /* get the current rate set to the given clock by any endpoint */
+ int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock)
+ {
+-      struct snd_usb_endpoint *ep;
++      struct snd_usb_clock_ref *ref;
+       int rate = 0;
+       if (!clock)
+               return 0;
+       mutex_lock(&chip->mutex);
+-      list_for_each_entry(ep, &chip->ep_list, list) {
+-              if (ep->cur_clock == clock && ep->cur_rate) {
+-                      rate = ep->cur_rate;
++      list_for_each_entry(ref, &chip->clock_ref_list, list) {
++              if (ref->clock == clock) {
++                      rate = ref->rate;
+                       break;
+               }
+       }
+@@ -1463,6 +1525,9 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
+       if (atomic_inc_return(&ep->running) != 1)
+               return 0;
++      if (ep->clock_ref)
++              atomic_inc(&ep->clock_ref->locked);
++
+       ep->active_mask = 0;
+       ep->unlink_mask = 0;
+       ep->phase = 0;
+@@ -1572,6 +1637,9 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep, bool keep_pending)
+               if (ep->sync_source)
+                       WRITE_ONCE(ep->sync_source->sync_sink, NULL);
+               stop_urbs(ep, false, keep_pending);
++              if (ep->clock_ref)
++                      if (!atomic_dec_return(&ep->clock_ref->locked))
++                              ep->clock_ref->rate = 0;
+       }
+ }
+@@ -1598,12 +1666,16 @@ void snd_usb_endpoint_free_all(struct snd_usb_audio *chip)
+ {
+       struct snd_usb_endpoint *ep, *en;
+       struct snd_usb_iface_ref *ip, *in;
++      struct snd_usb_clock_ref *cp, *cn;
+       list_for_each_entry_safe(ep, en, &chip->ep_list, list)
+               kfree(ep);
+       list_for_each_entry_safe(ip, in, &chip->iface_ref_list, list)
+               kfree(ip);
++
++      list_for_each_entry_safe(cp, cn, &chip->clock_ref_list, list)
++              kfree(ip);
+ }
+ /*
+diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
+index ec06f441e890f..e97141ef730ad 100644
+--- a/sound/usb/usbaudio.h
++++ b/sound/usb/usbaudio.h
+@@ -46,6 +46,7 @@ struct snd_usb_audio {
+       struct list_head pcm_list;      /* list of pcm streams */
+       struct list_head ep_list;       /* list of audio-related endpoints */
+       struct list_head iface_ref_list; /* list of interface refcounts */
++      struct list_head clock_ref_list; /* list of clock refcounts */
+       int pcm_devs;
+       struct list_head midi_list;     /* list of midi interfaces */
+-- 
+2.43.0
+
diff --git a/queue-5.15/alsa-usb-audio-sort-quirk-table-entries.patch b/queue-5.15/alsa-usb-audio-sort-quirk-table-entries.patch
new file mode 100644 (file)
index 0000000..2ab0141
--- /dev/null
@@ -0,0 +1,106 @@
+From 0cc136667611ed6f7e9384dd5d91769ad6274024 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jan 2024 16:53:07 +0100
+Subject: ALSA: usb-audio: Sort quirk table entries
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 668abe6dc7b61941fa5c724c06797efb0b87f070 ]
+
+The quirk table entries should be put in the USB ID order, but some
+entries have been put in random places.  Re-sort them.
+
+Fixes: bf990c102319 ("ALSA: usb-audio: add quirk to fix Hamedal C20 disconnect issue")
+Fixes: fd28941cff1c ("ALSA: usb-audio: Add new quirk FIXED_RATE for JBL Quantum810 Wireless")
+Fixes: dfd5fe19db7d ("ALSA: usb-audio: Add FIXED_RATE quirk for JBL Quantum610 Wireless")
+Fixes: 4a63e68a2951 ("ALSA: usb-audio: Fix microphone sound on Nexigo webcam.")
+Fixes: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+")
+Fixes: 4fb7c24f69c4 ("ALSA: usb-audio: Add quirk for Fiero SC-01")
+Fixes: 2307a0e1ca0b ("ALSA: usb-audio: Add quirk for Fiero SC-01 (fw v1.0.0)")
+Link: https://lore.kernel.org/r/20240124155307.16996-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/quirks.c | 36 ++++++++++++++++++------------------
+ 1 file changed, 18 insertions(+), 18 deletions(-)
+
+diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
+index 3073570beb3e2..1226ce5d5a304 100644
+--- a/sound/usb/quirks.c
++++ b/sound/usb/quirks.c
+@@ -1765,6 +1765,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x04e8, 0xa051, /* Samsung USBC Headset (AKG) */
+                  QUIRK_FLAG_SKIP_CLOCK_SELECTOR | QUIRK_FLAG_CTL_MSG_DELAY_5M),
++      DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */
++                 QUIRK_FLAG_IFACE_SKIP_CLOSE),
+       DEVICE_FLG(0x054c, 0x0b8c, /* Sony WALKMAN NW-A45 DAC */
+                  QUIRK_FLAG_SET_IFACE_FIRST),
+       DEVICE_FLG(0x0556, 0x0014, /* Phoenix Audio TMX320VC */
+@@ -1808,8 +1810,14 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M),
+       DEVICE_FLG(0x0b0e, 0x0349, /* Jabra 550a */
+                  QUIRK_FLAG_CTL_MSG_DELAY_1M),
++      DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */
++                 QUIRK_FLAG_FIXED_RATE),
++      DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */
++                 QUIRK_FLAG_FIXED_RATE),
+       DEVICE_FLG(0x0fd9, 0x0008, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
++      DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */
++                 QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x1397, 0x0507, /* Behringer UMC202HD */
+@@ -1840,6 +1848,10 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+       DEVICE_FLG(0x1901, 0x0191, /* GE B850V3 CP2114 audio interface */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
++      DEVICE_FLG(0x19f7, 0x0035, /* RODE NT-USB+ */
++                 QUIRK_FLAG_GET_SAMPLE_RATE),
++      DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */
++                 QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */
+                  QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x2040, 0x7201, /* Hauppauge HVR-950Q-MXL */
+@@ -1878,6 +1890,12 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+                  QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */
+                  QUIRK_FLAG_GET_SAMPLE_RATE),
++      DEVICE_FLG(0x2b53, 0x0023, /* Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */
++                 QUIRK_FLAG_GENERIC_IMPLICIT_FB),
++      DEVICE_FLG(0x2b53, 0x0024, /* Fiero SC-01 (firmware v1.0.0 @ 96 kHz) */
++                 QUIRK_FLAG_GENERIC_IMPLICIT_FB),
++      DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */
++                 QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+       DEVICE_FLG(0x30be, 0x0101, /* Schiit Hel */
+                  QUIRK_FLAG_IGNORE_CTL_ERROR),
+       DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */
+@@ -1886,24 +1904,6 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
+                  QUIRK_FLAG_ALIGN_TRANSFER),
+       DEVICE_FLG(0x534d, 0x2109, /* MacroSilicon MS2109 */
+                  QUIRK_FLAG_ALIGN_TRANSFER),
+-      DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */
+-                 QUIRK_FLAG_GET_SAMPLE_RATE),
+-      DEVICE_FLG(0x2b53, 0x0023, /* Fiero SC-01 (firmware v1.0.0 @ 48 kHz) */
+-                 QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+-      DEVICE_FLG(0x2b53, 0x0024, /* Fiero SC-01 (firmware v1.0.0 @ 96 kHz) */
+-                 QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+-      DEVICE_FLG(0x2b53, 0x0031, /* Fiero SC-01 (firmware v1.1.0) */
+-                 QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+-      DEVICE_FLG(0x0525, 0xa4ad, /* Hamedal C20 usb camero */
+-                 QUIRK_FLAG_IFACE_SKIP_CLOSE),
+-      DEVICE_FLG(0x0ecb, 0x205c, /* JBL Quantum610 Wireless */
+-                 QUIRK_FLAG_FIXED_RATE),
+-      DEVICE_FLG(0x0ecb, 0x2069, /* JBL Quantum810 Wireless */
+-                 QUIRK_FLAG_FIXED_RATE),
+-      DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */
+-                 QUIRK_FLAG_GET_SAMPLE_RATE),
+-      DEVICE_FLG(0x19f7, 0x0035, /* RODE NT-USB+ */
+-                 QUIRK_FLAG_GET_SAMPLE_RATE),
+       /* Vendor matches */
+       VENDOR_FLG(0x045e, /* MS Lifecam */
+-- 
+2.43.0
+
diff --git a/queue-5.15/alsa-usb-audio-split-endpoint-setups-for-hw_params-a.patch b/queue-5.15/alsa-usb-audio-split-endpoint-setups-for-hw_params-a.patch
new file mode 100644 (file)
index 0000000..f64008d
--- /dev/null
@@ -0,0 +1,346 @@
+From a8873d01d3e4f3256e67dd4a4eb2154d79887ba8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Sep 2022 20:11:06 +0200
+Subject: ALSA: usb-audio: Split endpoint setups for hw_params and prepare
+ (take#2)
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 2be79d58645465351af5320eb14c70a94724c5ef ]
+
+This is a second attempt to fix the bug appearing on Android with the
+recent kernel; the first try was ff878b408a03 and reverted at commit
+79764ec772bc.
+
+The details taken from the v1 patch:
+
+One of the former changes for the endpoint management was the more
+consistent setup of endpoints at hw_params.
+snd_usb_endpoint_configure() is a single function that does the full
+setup, and it's called from both PCM hw_params and prepare callbacks.
+Although the EP setup at the prepare phase is usually skipped (by
+checking need_setup flag), it may be still effective in some cases
+like suspend/resume that requires the interface setup again.
+
+As it's a full and single setup, the invocation of
+snd_usb_endpoint_configure() includes not only the USB interface setup
+but also the buffer release and allocation.  OTOH, doing the buffer
+release and re-allocation at PCM prepare phase is rather superfluous,
+and better to be done only in the hw_params phase.
+
+For those optimizations, this patch splits the endpoint setup to two
+phases: snd_usb_endpoint_set_params() and snd_usb_endpoint_prepare(),
+to be called from hw_params and from prepare, respectively.
+
+Note that this patch changes the driver operation slightly,
+effectively moving the USB interface setup again to PCM prepare stage
+instead of hw_params stage, while the buffer allocation and such
+initializations are still done at hw_params stage.
+
+And, the change of the USB interface setup timing (moving to prepare)
+gave an interesting "fix", too: it was reported that the recent
+kernels caused silent output at the beginning on playbacks on some
+devices on Android, and this change casually fixed the regression.
+It seems that those devices are picky about the sample rate change (or
+the interface change?), and don't follow the too immediate rate
+changes.
+
+Meanwhile, Android operates the PCM in the following order:
+- open, then hw_params with the possibly highest sample rate
+- close without prepare
+- re-open, hw_params with the normal sample rate
+- prepare, and start streaming
+This procedure ended up the hw_params twice with different rates, and
+because the recent kernel did set up the sample rate twice one and
+after, it screwed up the device.  OTOH, the earlier kernels didn't set
+up the USB interface at hw_params, hence this problem didn't appear.
+
+Now, with this patch, the USB interface setup is again back to the
+prepare phase, and it works around the problem automagically.
+Although we should address the sample rate problem in a more solid
+way in future, let's keep things working as before for now.
+
+***
+
+What's new in the take#2 patch:
+- The regression caused by the v1 patch (bko#216500) was due to the
+  missing check of need_setup flag at hw_params.  Now the check is
+  added, and the snd_usb_endpoint_set_params() call is skipped when
+  the running EP is re-opened.
+
+- There was another bug in v1 where the clock reference rate wasn't
+  updated at hw_params phase, which may lead to a lack of the proper
+  hw constraints when an application doesn't issue the prepare but
+  only the hw_params call.  This patch fixes it as well by tracking
+  the clock rate change in the prepare callback with a new flag
+  "need_update" for the clock reference object, just like others.
+
+- The configure_endpoints() are simplified and folded back into
+  snd_usb_pcm_prepare().
+
+Fixes: bf6313a0ff76 ("ALSA: usb-audio: Refactor endpoint management")
+Fixes: ff878b408a03 ("ALSA: usb-audio: Split endpoint setups for hw_params and prepare")
+Reported-by: chihhao chen <chihhao.chen@mediatek.com>
+Link: https://lore.kernel.org/r/87e6d6ae69d68dc588ac9acc8c0f24d6188375c3.camel@mediatek.com
+Link: https://lore.kernel.org/r/20220901124136.4984-1-tiwai@suse.de
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=216500
+Link: https://lore.kernel.org/r/20220920181106.4894-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/endpoint.c | 76 +++++++++++++++++++++++++++-----------------
+ sound/usb/endpoint.h |  6 ++--
+ sound/usb/pcm.c      | 51 ++++++++++++-----------------
+ 3 files changed, 70 insertions(+), 63 deletions(-)
+
+diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
+index 13c0264881499..32a9e016665c8 100644
+--- a/sound/usb/endpoint.c
++++ b/sound/usb/endpoint.c
+@@ -40,6 +40,7 @@ struct snd_usb_clock_ref {
+       unsigned char clock;
+       atomic_t locked;
+       int rate;
++      bool need_setup;
+       struct list_head list;
+ };
+@@ -765,7 +766,8 @@ bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,
+  * The endpoint needs to be closed via snd_usb_endpoint_close() later.
+  *
+  * Note that this function doesn't configure the endpoint.  The substream
+- * needs to set it up later via snd_usb_endpoint_configure().
++ * needs to set it up later via snd_usb_endpoint_set_params() and
++ * snd_usb_endpoint_prepare().
+  */
+ struct snd_usb_endpoint *
+ snd_usb_endpoint_open(struct snd_usb_audio *chip,
+@@ -1296,15 +1298,39 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep)
+       return -ENOMEM;
+ }
++/* update the rate of the referred clock; return the actual rate */
++static int update_clock_ref_rate(struct snd_usb_audio *chip,
++                               struct snd_usb_endpoint *ep)
++{
++      struct snd_usb_clock_ref *clock = ep->clock_ref;
++      int rate = ep->cur_rate;
++
++      if (!clock || clock->rate == rate)
++              return rate;
++      if (clock->rate) {
++              if (atomic_read(&clock->locked))
++                      return clock->rate;
++              if (clock->rate != rate) {
++                      usb_audio_err(chip, "Mismatched sample rate %d vs %d for EP 0x%x\n",
++                                    clock->rate, rate, ep->ep_num);
++                      return clock->rate;
++              }
++      }
++      clock->rate = rate;
++      clock->need_setup = true;
++      return rate;
++}
++
+ /*
+  * snd_usb_endpoint_set_params: configure an snd_usb_endpoint
+  *
++ * It's called either from hw_params callback.
+  * Determine the number of URBs to be used on this endpoint.
+  * An endpoint must be configured before it can be started.
+  * An endpoint that is already running can not be reconfigured.
+  */
+-static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
+-                                     struct snd_usb_endpoint *ep)
++int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
++                              struct snd_usb_endpoint *ep)
+ {
+       const struct audioformat *fmt = ep->cur_audiofmt;
+       int err;
+@@ -1356,49 +1382,46 @@ static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
+       ep->maxframesize = ep->maxpacksize / ep->cur_frame_bytes;
+       ep->curframesize = ep->curpacksize / ep->cur_frame_bytes;
+-      return 0;
++      return update_clock_ref_rate(chip, ep);
+ }
+ static int init_sample_rate(struct snd_usb_audio *chip,
+                           struct snd_usb_endpoint *ep)
+ {
+       struct snd_usb_clock_ref *clock = ep->clock_ref;
+-      int err;
++      int rate, err;
+-      if (clock) {
+-              if (atomic_read(&clock->locked))
+-                      return 0;
+-              if (clock->rate == ep->cur_rate)
+-                      return 0;
+-              if (clock->rate && clock->rate != ep->cur_rate) {
+-                      usb_audio_dbg(chip, "Mismatched sample rate %d vs %d for EP 0x%x\n",
+-                                    clock->rate, ep->cur_rate, ep->ep_num);
+-                      return -EINVAL;
+-              }
+-      }
++      rate = update_clock_ref_rate(chip, ep);
++      if (rate < 0)
++              return rate;
++      if (clock && !clock->need_setup)
++              return 0;
+-      err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, ep->cur_rate);
+-      if (err < 0)
++      err = snd_usb_init_sample_rate(chip, ep->cur_audiofmt, rate);
++      if (err < 0) {
++              if (clock)
++                      clock->rate = 0; /* reset rate */
+               return err;
++      }
+       if (clock)
+-              clock->rate = ep->cur_rate;
++              clock->need_setup = false;
+       return 0;
+ }
+ /*
+- * snd_usb_endpoint_configure: Configure the endpoint
++ * snd_usb_endpoint_prepare: Prepare the endpoint
+  *
+  * This function sets up the EP to be fully usable state.
+- * It's called either from hw_params or prepare callback.
++ * It's called either from prepare callback.
+  * The function checks need_setup flag, and performs nothing unless needed,
+  * so it's safe to call this multiple times.
+  *
+  * This returns zero if unchanged, 1 if the configuration has changed,
+  * or a negative error code.
+  */
+-int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
+-                             struct snd_usb_endpoint *ep)
++int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
++                           struct snd_usb_endpoint *ep)
+ {
+       bool iface_first;
+       int err = 0;
+@@ -1419,9 +1442,6 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
+                       if (err < 0)
+                               goto unlock;
+               }
+-              err = snd_usb_endpoint_set_params(chip, ep);
+-              if (err < 0)
+-                      goto unlock;
+               goto done;
+       }
+@@ -1449,10 +1469,6 @@ int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
+       if (err < 0)
+               goto unlock;
+-      err = snd_usb_endpoint_set_params(chip, ep);
+-      if (err < 0)
+-              goto unlock;
+-
+       err = snd_usb_select_mode_quirk(chip, ep->cur_audiofmt);
+       if (err < 0)
+               goto unlock;
+diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
+index daa7ba063d858..b972f7899d57e 100644
+--- a/sound/usb/endpoint.h
++++ b/sound/usb/endpoint.h
+@@ -17,8 +17,10 @@ snd_usb_endpoint_open(struct snd_usb_audio *chip,
+                     bool is_sync_ep);
+ void snd_usb_endpoint_close(struct snd_usb_audio *chip,
+                           struct snd_usb_endpoint *ep);
+-int snd_usb_endpoint_configure(struct snd_usb_audio *chip,
+-                             struct snd_usb_endpoint *ep);
++int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
++                              struct snd_usb_endpoint *ep);
++int snd_usb_endpoint_prepare(struct snd_usb_audio *chip,
++                           struct snd_usb_endpoint *ep);
+ int snd_usb_endpoint_get_clock_rate(struct snd_usb_audio *chip, int clock);
+ bool snd_usb_endpoint_compatible(struct snd_usb_audio *chip,
+diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
+index de0964dbf7a91..7f09191c83d0e 100644
+--- a/sound/usb/pcm.c
++++ b/sound/usb/pcm.c
+@@ -433,35 +433,6 @@ static void close_endpoints(struct snd_usb_audio *chip,
+       }
+ }
+-static int configure_endpoints(struct snd_usb_audio *chip,
+-                             struct snd_usb_substream *subs)
+-{
+-      int err;
+-
+-      if (subs->data_endpoint->need_setup) {
+-              /* stop any running stream beforehand */
+-              if (stop_endpoints(subs, false))
+-                      sync_pending_stops(subs);
+-              if (subs->sync_endpoint) {
+-                      err = snd_usb_endpoint_configure(chip, subs->sync_endpoint);
+-                      if (err < 0)
+-                              return err;
+-              }
+-              err = snd_usb_endpoint_configure(chip, subs->data_endpoint);
+-              if (err < 0)
+-                      return err;
+-              snd_usb_set_format_quirk(subs, subs->cur_audiofmt);
+-      } else {
+-              if (subs->sync_endpoint) {
+-                      err = snd_usb_endpoint_configure(chip, subs->sync_endpoint);
+-                      if (err < 0)
+-                              return err;
+-              }
+-      }
+-
+-      return 0;
+-}
+-
+ /*
+  * hw_params callback
+  *
+@@ -553,7 +524,16 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+       subs->cur_audiofmt = fmt;
+       mutex_unlock(&chip->mutex);
+-      ret = configure_endpoints(chip, subs);
++      if (!subs->data_endpoint->need_setup)
++              goto unlock;
++
++      if (subs->sync_endpoint) {
++              ret = snd_usb_endpoint_set_params(chip, subs->sync_endpoint);
++              if (ret < 0)
++                      goto unlock;
++      }
++
++      ret = snd_usb_endpoint_set_params(chip, subs->data_endpoint);
+  unlock:
+       if (ret < 0)
+@@ -636,9 +616,18 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
+               goto unlock;
+       }
+-      ret = configure_endpoints(chip, subs);
++      if (subs->sync_endpoint) {
++              ret = snd_usb_endpoint_prepare(chip, subs->sync_endpoint);
++              if (ret < 0)
++                      goto unlock;
++      }
++
++      ret = snd_usb_endpoint_prepare(chip, subs->data_endpoint);
+       if (ret < 0)
+               goto unlock;
++      else if (ret > 0)
++              snd_usb_set_format_quirk(subs, subs->cur_audiofmt);
++      ret = 0;
+       /* reset the pointer */
+       subs->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size);
+-- 
+2.43.0
+
diff --git a/queue-5.15/drm-amd-display-fix-uninitialized-variable-usage-in-.patch b/queue-5.15/drm-amd-display-fix-uninitialized-variable-usage-in-.patch
new file mode 100644 (file)
index 0000000..6faf1da
--- /dev/null
@@ -0,0 +1,59 @@
+From de06547bbc90d0ebe9974e01e21be87a2353d668 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Jan 2024 08:41:52 +0530
+Subject: drm/amd/display: Fix uninitialized variable usage in core_link_
+ 'read_dpcd() & write_dpcd()' functions
+
+From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+
+[ Upstream commit a58371d632ebab9ea63f10893a6b6731196b6f8d ]
+
+The 'status' variable in 'core_link_read_dpcd()' &
+'core_link_write_dpcd()' was uninitialized.
+
+Thus, initializing 'status' variable to 'DC_ERROR_UNEXPECTED' by default.
+
+Fixes the below:
+drivers/gpu/drm/amd/amdgpu/../display/dc/link/protocols/link_dpcd.c:226 core_link_read_dpcd() error: uninitialized symbol 'status'.
+drivers/gpu/drm/amd/amdgpu/../display/dc/link/protocols/link_dpcd.c:248 core_link_write_dpcd() error: uninitialized symbol 'status'.
+
+Cc: stable@vger.kernel.org
+Cc: Jerry Zuo <jerry.zuo@amd.com>
+Cc: Jun Lei <Jun.Lei@amd.com>
+Cc: Wayne Lin <Wayne.Lin@amd.com>
+Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
+Cc: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Cc: Hamza Mahfooz <hamza.mahfooz@amd.com>
+Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
+Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c
+index 72970e49800a6..3978cd5ea08a7 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dpcd.c
+@@ -199,7 +199,7 @@ enum dc_status core_link_read_dpcd(
+       uint32_t extended_size;
+       /* size of the remaining partitioned address space */
+       uint32_t size_left_to_read;
+-      enum dc_status status;
++      enum dc_status status = DC_ERROR_UNEXPECTED;
+       /* size of the next partition to be read from */
+       uint32_t partition_size;
+       uint32_t data_index = 0;
+@@ -228,7 +228,7 @@ enum dc_status core_link_write_dpcd(
+ {
+       uint32_t partition_size;
+       uint32_t data_index = 0;
+-      enum dc_status status;
++      enum dc_status status = DC_ERROR_UNEXPECTED;
+       while (size) {
+               partition_size = dpcd_get_next_partition_size(address, size);
+-- 
+2.43.0
+
diff --git a/queue-5.15/drm-amd-display-increase-frame-larger-than-for-all-d.patch b/queue-5.15/drm-amd-display-increase-frame-larger-than-for-all-d.patch
new file mode 100644 (file)
index 0000000..6c42416
--- /dev/null
@@ -0,0 +1,70 @@
+From f0655a1f9d346930de4e9eb75a4c35aa899822ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Feb 2024 14:54:05 -0700
+Subject: drm/amd/display: Increase frame-larger-than for all display_mode_vba
+ files
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+[ Upstream commit e63e35f0164c43fbc1adb481d6604f253b9f9667 ]
+
+After a recent change in LLVM, allmodconfig (which has CONFIG_KCSAN=y
+and CONFIG_WERROR=y enabled) has a few new instances of
+-Wframe-larger-than for the mode support and system configuration
+functions:
+
+  drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn20/display_mode_vba_20v2.c:3393:6: error: stack frame size (2144) exceeds limit (2048) in 'dml20v2_ModeSupportAndSystemConfigurationFull' [-Werror,-Wframe-larger-than]
+   3393 | void dml20v2_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib)
+        |      ^
+  1 error generated.
+
+  drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn21/display_mode_vba_21.c:3520:6: error: stack frame size (2192) exceeds limit (2048) in 'dml21_ModeSupportAndSystemConfigurationFull' [-Werror,-Wframe-larger-than]
+   3520 | void dml21_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib)
+        |      ^
+  1 error generated.
+
+  drivers/gpu/drm/amd/amdgpu/../display/dc/dml/dcn20/display_mode_vba_20.c:3286:6: error: stack frame size (2128) exceeds limit (2048) in 'dml20_ModeSupportAndSystemConfigurationFull' [-Werror,-Wframe-larger-than]
+   3286 | void dml20_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_lib)
+        |      ^
+  1 error generated.
+
+Without the sanitizers enabled, there are no warnings.
+
+This was the catalyst for commit 6740ec97bcdb ("drm/amd/display:
+Increase frame warning limit with KASAN or KCSAN in dml2") and that same
+change was made to dml in commit 5b750b22530f ("drm/amd/display:
+Increase frame warning limit with KASAN or KCSAN in dml") but the
+frame_warn_flag variable was not applied to all files. Do so now to
+clear up the warnings and make all these files consistent.
+
+Cc: stable@vger.kernel.org
+Closes: https://github.com/ClangBuiltLinux/linux/issue/1990
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dml/Makefile | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile
+index 93cc3086783fa..96e70832c7423 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/Makefile
++++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile
+@@ -59,11 +59,11 @@ CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
+ ifdef CONFIG_DRM_AMD_DC_DCN
+ CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/dcn20_fpu.o := $(dml_ccflags)
+-CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags)
++CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags) $(frame_warn_flag)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20.o := $(dml_ccflags)
+-CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_ccflags)
++CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_ccflags) $(frame_warn_flag)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20v2.o := $(dml_ccflags)
+-CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_mode_vba_21.o := $(dml_ccflags)
++CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_mode_vba_21.o := $(dml_ccflags) $(frame_warn_flag)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_rq_dlg_calc_21.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) $(frame_warn_flag)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags)
+-- 
+2.43.0
+
diff --git a/queue-5.15/drm-amd-display-move-calcs-folder-into-dml.patch b/queue-5.15/drm-amd-display-move-calcs-folder-into-dml.patch
new file mode 100644 (file)
index 0000000..0d62ebb
--- /dev/null
@@ -0,0 +1,212 @@
+From d6dbb4a02f573b89d693ba7bc36177368945966e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Jan 2022 18:33:36 -0300
+Subject: drm/amd/display: move calcs folder into DML
+
+From: Isabella Basso <isabbasso@riseup.net>
+
+[ Upstream commit 552b7cb0eed12c184b3bdfcc262e96a954a2bc86 ]
+
+The calcs folder has FPU code on it, which should be isolated inside the
+DML folder as per https://patchwork.freedesktop.org/series/93042/.
+
+This commit aims single-handedly to correct the location of such FPU
+code and does not refactor any functions.
+
+Changes since v2:
+- Corrected problems to compile when DCN was disabled.
+
+Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Signed-off-by: Isabella Basso <isabbasso@riseup.net>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: e63e35f0164c ("drm/amd/display: Increase frame-larger-than for all display_mode_vba files")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/Makefile       |  4 +-
+ drivers/gpu/drm/amd/display/dc/calcs/Makefile | 68 -------------------
+ drivers/gpu/drm/amd/display/dc/dml/Makefile   | 10 ++-
+ .../amd/display/dc/{ => dml}/calcs/bw_fixed.c |  0
+ .../display/dc/{ => dml}/calcs/calcs_logger.h |  0
+ .../display/dc/{ => dml}/calcs/custom_float.c |  0
+ .../display/dc/{ => dml}/calcs/dce_calcs.c    |  0
+ .../dc/{ => dml}/calcs/dcn_calc_auto.c        |  0
+ .../dc/{ => dml}/calcs/dcn_calc_auto.h        |  0
+ .../dc/{ => dml}/calcs/dcn_calc_math.c        |  0
+ .../display/dc/{ => dml}/calcs/dcn_calcs.c    |  0
+ 11 files changed, 11 insertions(+), 71 deletions(-)
+ delete mode 100644 drivers/gpu/drm/amd/display/dc/calcs/Makefile
+ rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/bw_fixed.c (100%)
+ rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/calcs_logger.h (100%)
+ rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/custom_float.c (100%)
+ rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/dce_calcs.c (100%)
+ rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/dcn_calc_auto.c (100%)
+ rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/dcn_calc_auto.h (100%)
+ rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/dcn_calc_math.c (100%)
+ rename drivers/gpu/drm/amd/display/dc/{ => dml}/calcs/dcn_calcs.c (100%)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile
+index 943fcb164876c..d82574f379119 100644
+--- a/drivers/gpu/drm/amd/display/dc/Makefile
++++ b/drivers/gpu/drm/amd/display/dc/Makefile
+@@ -23,12 +23,12 @@
+ # Makefile for Display Core (dc) component.
+ #
+-DC_LIBS = basics bios calcs clk_mgr dce gpio irq virtual
++DC_LIBS = basics bios clk_mgr dce dml gpio irq virtual
+ ifdef CONFIG_DRM_AMD_DC_DCN
+ DC_LIBS += dcn20
+ DC_LIBS += dsc
+-DC_LIBS += dcn10 dml
++DC_LIBS += dcn10
+ DC_LIBS += dcn21
+ DC_LIBS += dcn30
+ DC_LIBS += dcn301
+diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile
+deleted file mode 100644
+index f3c00f479e1cb..0000000000000
+--- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile
++++ /dev/null
+@@ -1,68 +0,0 @@
+-#
+-# Copyright 2017 Advanced Micro Devices, Inc.
+-# Copyright 2019 Raptor Engineering, LLC
+-#
+-# Permission is hereby granted, free of charge, to any person obtaining a
+-# copy of this software and associated documentation files (the "Software"),
+-# to deal in the Software without restriction, including without limitation
+-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-# and/or sell copies of the Software, and to permit persons to whom the
+-# Software is furnished to do so, subject to the following conditions:
+-#
+-# The above copyright notice and this permission notice shall be included in
+-# all copies or substantial portions of the Software.
+-#
+-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+-# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+-# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+-# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+-# OTHER DEALINGS IN THE SOFTWARE.
+-#
+-#
+-# Makefile for the 'calcs' sub-component of DAL.
+-# It calculates Bandwidth and Watermarks values for HW programming
+-#
+-
+-ifdef CONFIG_X86
+-calcs_ccflags := -mhard-float -msse
+-endif
+-
+-ifdef CONFIG_PPC64
+-calcs_ccflags := -mhard-float -maltivec
+-endif
+-
+-ifdef CONFIG_CC_IS_GCC
+-ifeq ($(call cc-ifversion, -lt, 0701, y), y)
+-IS_OLD_GCC = 1
+-endif
+-endif
+-
+-ifdef CONFIG_X86
+-ifdef IS_OLD_GCC
+-# Stack alignment mismatch, proceed with caution.
+-# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
+-# (8B stack alignment).
+-calcs_ccflags += -mpreferred-stack-boundary=4
+-else
+-calcs_ccflags += -msse2
+-endif
+-endif
+-
+-CFLAGS_$(AMDDALPATH)/dc/calcs/dcn_calcs.o := $(calcs_ccflags)
+-CFLAGS_$(AMDDALPATH)/dc/calcs/dcn_calc_auto.o := $(calcs_ccflags)
+-CFLAGS_$(AMDDALPATH)/dc/calcs/dcn_calc_math.o := $(calcs_ccflags) -Wno-tautological-compare
+-CFLAGS_REMOVE_$(AMDDALPATH)/dc/calcs/dcn_calcs.o := $(calcs_rcflags)
+-CFLAGS_REMOVE_$(AMDDALPATH)/dc/calcs/dcn_calc_auto.o := $(calcs_rcflags)
+-CFLAGS_REMOVE_$(AMDDALPATH)/dc/calcs/dcn_calc_math.o := $(calcs_rcflags)
+-
+-BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o
+-
+-ifdef CONFIG_DRM_AMD_DC_DCN
+-BW_CALCS += dcn_calcs.o dcn_calc_math.o dcn_calc_auto.o
+-endif
+-
+-AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS))
+-
+-AMD_DISPLAY_FILES += $(AMD_DAL_BW_CALCS)
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile
+index e7bb69ec99b66..c97fdfc36d0fd 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/Makefile
++++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile
+@@ -72,6 +72,9 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(fram
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
++CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calcs.o := $(dml_ccflags)
++CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_auto.o := $(dml_ccflags)
++CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_math.o := $(dml_ccflags) -Wno-tautological-compare
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags)
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn2x/dcn2x.o := $(dml_rcflags)
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_rcflags)
+@@ -91,10 +94,14 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/display_rq_dlg_helpers.o := $(dml_ccflags)
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_rcflags)
+ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_rq_dlg_helpers.o := $(dml_rcflags)
++CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/calcs/dcn_calcs.o := $(dml_rcflags)
++CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_auto.o := $(dml_rcflags)
++CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_math.o := $(dml_rcflags)
+-DML = display_mode_lib.o display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o \
++DML = calcs/dce_calcs.o calcs/custom_float.o calcs/bw_fixed.o
+ ifdef CONFIG_DRM_AMD_DC_DCN
++DML += display_mode_lib.o display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o
+ DML += dcn20/dcn20_fpu.o
+ DML += display_mode_vba.o dcn20/display_rq_dlg_calc_20.o dcn20/display_mode_vba_20.o
+ DML += dcn20/display_rq_dlg_calc_20v2.o dcn20/display_mode_vba_20v2.o
+@@ -102,6 +109,7 @@ DML += dcn21/display_rq_dlg_calc_21.o dcn21/display_mode_vba_21.o
+ DML += dcn30/display_mode_vba_30.o dcn30/display_rq_dlg_calc_30.o
+ DML += dcn31/display_mode_vba_31.o dcn31/display_rq_dlg_calc_31.o
+ DML += dsc/rc_calc_fpu.o
++DML += calcs/dcn_calcs.o calcs/dcn_calc_math.o calcs/dcn_calc_auto.o
+ endif
+ AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML))
+diff --git a/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c
+similarity index 100%
+rename from drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c
+rename to drivers/gpu/drm/amd/display/dc/dml/calcs/bw_fixed.c
+diff --git a/drivers/gpu/drm/amd/display/dc/calcs/calcs_logger.h b/drivers/gpu/drm/amd/display/dc/dml/calcs/calcs_logger.h
+similarity index 100%
+rename from drivers/gpu/drm/amd/display/dc/calcs/calcs_logger.h
+rename to drivers/gpu/drm/amd/display/dc/dml/calcs/calcs_logger.h
+diff --git a/drivers/gpu/drm/amd/display/dc/calcs/custom_float.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/custom_float.c
+similarity index 100%
+rename from drivers/gpu/drm/amd/display/dc/calcs/custom_float.c
+rename to drivers/gpu/drm/amd/display/dc/dml/calcs/custom_float.c
+diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c
+similarity index 100%
+rename from drivers/gpu/drm/amd/display/dc/calcs/dce_calcs.c
+rename to drivers/gpu/drm/amd/display/dc/dml/calcs/dce_calcs.c
+diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_auto.c
+similarity index 100%
+rename from drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.c
+rename to drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_auto.c
+diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.h b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_auto.h
+similarity index 100%
+rename from drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_auto.h
+rename to drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_auto.h
+diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_math.c
+similarity index 100%
+rename from drivers/gpu/drm/amd/display/dc/calcs/dcn_calc_math.c
+rename to drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calc_math.c
+diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c
+similarity index 100%
+rename from drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c
+rename to drivers/gpu/drm/amd/display/dc/dml/calcs/dcn_calcs.c
+-- 
+2.43.0
+
diff --git a/queue-5.15/drm-amd-display-re-arrange-fpu-code-structure-for-dc.patch b/queue-5.15/drm-amd-display-re-arrange-fpu-code-structure-for-dc.patch
new file mode 100644 (file)
index 0000000..e147238
--- /dev/null
@@ -0,0 +1,137 @@
+From 57a0e2cfa570639b0b7321a13ac862fe7ff924eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Oct 2021 22:36:10 +0800
+Subject: drm/amd/display: Re-arrange FPU code structure for dcn2x
+
+From: Qingqing Zhuo <qingqing.zhuo@amd.com>
+
+[ Upstream commit ee37341199c61558b73113659695c90bf4736eb2 ]
+
+[Why]
+Current FPU code for DCN2x is located under dml/dcn2x.
+This is not aligned with DC's general source tree
+structure.
+
+[How]
+Move FPU code for DCN2x to dml/dcn20.
+
+Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Acked-by: Solomon Chiu <solomon.chiu@amd.com>
+Signed-off-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: e63e35f0164c ("drm/amd/display: Increase frame-larger-than for all display_mode_vba files")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c              | 2 +-
+ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c       | 2 +-
+ drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c       | 2 +-
+ drivers/gpu/drm/amd/display/dc/dml/Makefile                 | 4 ++--
+ .../amd/display/dc/dml/{dcn2x/dcn2x.c => dcn20/dcn20_fpu.c} | 2 +-
+ .../amd/display/dc/dml/{dcn2x/dcn2x.h => dcn20/dcn20_fpu.h} | 6 +++---
+ 6 files changed, 9 insertions(+), 9 deletions(-)
+ rename drivers/gpu/drm/amd/display/dc/dml/{dcn2x/dcn2x.c => dcn20/dcn20_fpu.c} (99%)
+ rename drivers/gpu/drm/amd/display/dc/dml/{dcn2x/dcn2x.h => dcn20/dcn20_fpu.h} (94%)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
+index b1bf80da3a55f..ab0c6d1910382 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
+@@ -52,7 +52,7 @@ static DEFINE_PER_CPU(int, fpu_recursion_depth);
+  * This function tells if the code is already under FPU protection or not. A
+  * function that works as an API for a set of FPU operations can use this
+  * function for checking if the caller invoked it after DC_FP_START(). For
+- * example, take a look at dcn2x.c file.
++ * example, take a look at dcn20_fpu.c file.
+  */
+ inline void dc_assert_fp_enabled(void)
+ {
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+index ede11eb120d4f..04b370e7e732e 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+@@ -35,7 +35,7 @@
+ #include "include/irq_service_interface.h"
+ #include "dcn20/dcn20_resource.h"
+-#include "dml/dcn2x/dcn2x.h"
++#include "dml/dcn20/dcn20_fpu.h"
+ #include "dcn10/dcn10_hubp.h"
+ #include "dcn10/dcn10_ipp.h"
+diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+index 5b8274b8c3845..7c5c1414b7a1c 100644
+--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
++++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+@@ -35,7 +35,7 @@
+ #include "include/irq_service_interface.h"
+ #include "dcn20/dcn20_resource.h"
+-#include "dml/dcn2x/dcn2x.h"
++#include "dml/dcn20/dcn20_fpu.h"
+ #include "clk_mgr.h"
+ #include "dcn10/dcn10_hubp.h"
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile
+index 9009b92490f34..e7bb69ec99b66 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/Makefile
++++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile
+@@ -58,7 +58,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
+ ifdef CONFIG_DRM_AMD_DC_DCN
+ CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_ccflags)
+-CFLAGS_$(AMDDALPATH)/dc/dml/dcn2x/dcn2x.o := $(dml_ccflags)
++CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/dcn20_fpu.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20.o := $(dml_ccflags)
+@@ -95,8 +95,8 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_rq_dlg_helpers.o := $(dml_rcflags)
+ DML = display_mode_lib.o display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o \
+ ifdef CONFIG_DRM_AMD_DC_DCN
++DML += dcn20/dcn20_fpu.o
+ DML += display_mode_vba.o dcn20/display_rq_dlg_calc_20.o dcn20/display_mode_vba_20.o
+-DML += dcn2x/dcn2x.o
+ DML += dcn20/display_rq_dlg_calc_20v2.o dcn20/display_mode_vba_20v2.o
+ DML += dcn21/display_rq_dlg_calc_21.o dcn21/display_mode_vba_21.o
+ DML += dcn30/display_mode_vba_30.o dcn30/display_rq_dlg_calc_30.o
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.c b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
+similarity index 99%
+rename from drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.c
+rename to drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
+index c58522436291a..d590dc9173637 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c
+@@ -26,7 +26,7 @@
+ #include "resource.h"
+-#include "dcn2x.h"
++#include "dcn20_fpu.h"
+ /**
+  * DOC: DCN2x FPU manipulation Overview
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.h b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
+similarity index 94%
+rename from drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.h
+rename to drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
+index 331547ba07132..36f26126d574b 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn2x/dcn2x.h
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.h
+@@ -24,11 +24,11 @@
+  *
+  */
+-#ifndef __DCN2X_H__
+-#define __DCN2X_H__
++#ifndef __DCN20_FPU_H__
++#define __DCN20_FPU_H__
+ void dcn20_populate_dml_writeback_from_context(struct dc *dc,
+                                              struct resource_context *res_ctx,
+                                              display_e2e_pipe_params_st *pipes);
+-#endif /* __DCN2X_H__ */
++#endif /* __DCN20_FPU_H__ */
+-- 
+2.43.0
+
diff --git a/queue-5.15/drm-amd-display-remove-dml-makefile-duplicate-lines.patch b/queue-5.15/drm-amd-display-remove-dml-makefile-duplicate-lines.patch
new file mode 100644 (file)
index 0000000..6b89227
--- /dev/null
@@ -0,0 +1,51 @@
+From d2fdf0e7949723bdfa6f2a14c6f0279a151da3d2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Aug 2022 09:04:06 -0300
+Subject: drm/amd/display: remove DML Makefile duplicate lines
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Magali Lemes <magalilemes00@gmail.com>
+
+[ Upstream commit 41ead3e0cdc03d64b7da2dcb1fd70ebb7164228b ]
+
+There are two identical CFLAGS entries for "display_mode_vba_20.o", so
+remove one of them. Also, as there's already an entry for
+"display_mode_lib.o" CFLAGS, regardless of CONFIG_DRM_AMD_DC_DCN being
+defined or not, remove the one entry between CONFIG_DRM_AMD_DC_DCN ifdef
+guards.
+
+Signed-off-by: Magali Lemes <magalilemes00@gmail.com>
+Reviewed-by: André Almeida <andrealmeid@igalia.com>
+Reviewed-by: Harry Wentland <harry.wentland@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: e63e35f0164c ("drm/amd/display: Increase frame-larger-than for all display_mode_vba files")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile
+index c97fdfc36d0fd..93cc3086783fa 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/Makefile
++++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile
+@@ -60,7 +60,6 @@ ifdef CONFIG_DRM_AMD_DC_DCN
+ CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/dcn20_fpu.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags)
+-CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20v2.o := $(dml_ccflags)
+@@ -71,7 +70,6 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(frame_warn_flag)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_ccflags)
+-CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calcs.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_auto.o := $(dml_ccflags)
+ CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_math.o := $(dml_ccflags) -Wno-tautological-compare
+-- 
+2.43.0
+
diff --git a/queue-5.15/drm-amd-pm-do-not-expose-the-api-used-internally-onl.patch b/queue-5.15/drm-amd-pm-do-not-expose-the-api-used-internally-onl.patch
new file mode 100644 (file)
index 0000000..c1a0c80
--- /dev/null
@@ -0,0 +1,115 @@
+From 1567677ccdbdee35bf1e395b2a3a2a125528c30f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 Nov 2021 14:29:00 +0800
+Subject: drm/amd/pm: do not expose the API used internally only in kv_dpm.c
+
+From: Evan Quan <evan.quan@amd.com>
+
+[ Upstream commit 28a31774b050261371953401e8072ae15200c91e ]
+
+Move it to kv_dpm.c instead.
+
+Signed-off-by: Evan Quan <evan.quan@amd.com>
+Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: 733025626866 ("drm/amdgpu: Reset IH OVERFLOW_CLEAR bit")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/pm/amdgpu_dpm.c       | 23 ---------------------
+ drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h   |  2 --
+ drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c | 25 ++++++++++++++++++++++-
+ 3 files changed, 24 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
+index a68496b3f9296..197ea6e263878 100644
+--- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
++++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c
+@@ -188,29 +188,6 @@ u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev)
+       return vrefresh;
+ }
+-bool amdgpu_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor)
+-{
+-      switch (sensor) {
+-      case THERMAL_TYPE_RV6XX:
+-      case THERMAL_TYPE_RV770:
+-      case THERMAL_TYPE_EVERGREEN:
+-      case THERMAL_TYPE_SUMO:
+-      case THERMAL_TYPE_NI:
+-      case THERMAL_TYPE_SI:
+-      case THERMAL_TYPE_CI:
+-      case THERMAL_TYPE_KV:
+-              return true;
+-      case THERMAL_TYPE_ADT7473_WITH_INTERNAL:
+-      case THERMAL_TYPE_EMC2103_WITH_INTERNAL:
+-              return false; /* need special handling */
+-      case THERMAL_TYPE_NONE:
+-      case THERMAL_TYPE_EXTERNAL:
+-      case THERMAL_TYPE_EXTERNAL_GPIO:
+-      default:
+-              return false;
+-      }
+-}
+-
+ union power_info {
+       struct _ATOM_POWERPLAY_INFO info;
+       struct _ATOM_POWERPLAY_INFO_V2 info_2;
+diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
+index 16e3f72d31b9f..a3f6caaec88c7 100644
+--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
++++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
+@@ -501,8 +501,6 @@ void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev);
+ int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor,
+                          void *data, uint32_t *size);
+-bool amdgpu_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor);
+-
+ int amdgpu_get_platform_caps(struct amdgpu_device *adev);
+ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev);
+diff --git a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c
+index 309c9f0b8f83a..b56854c03ead6 100644
+--- a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c
++++ b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c
+@@ -1256,6 +1256,29 @@ static void kv_dpm_enable_bapm(void *handle, bool enable)
+       }
+ }
++static bool kv_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor)
++{
++      switch (sensor) {
++      case THERMAL_TYPE_RV6XX:
++      case THERMAL_TYPE_RV770:
++      case THERMAL_TYPE_EVERGREEN:
++      case THERMAL_TYPE_SUMO:
++      case THERMAL_TYPE_NI:
++      case THERMAL_TYPE_SI:
++      case THERMAL_TYPE_CI:
++      case THERMAL_TYPE_KV:
++              return true;
++      case THERMAL_TYPE_ADT7473_WITH_INTERNAL:
++      case THERMAL_TYPE_EMC2103_WITH_INTERNAL:
++              return false; /* need special handling */
++      case THERMAL_TYPE_NONE:
++      case THERMAL_TYPE_EXTERNAL:
++      case THERMAL_TYPE_EXTERNAL_GPIO:
++      default:
++              return false;
++      }
++}
++
+ static int kv_dpm_enable(struct amdgpu_device *adev)
+ {
+       struct kv_power_info *pi = kv_get_pi(adev);
+@@ -1352,7 +1375,7 @@ static int kv_dpm_enable(struct amdgpu_device *adev)
+       }
+       if (adev->irq.installed &&
+-          amdgpu_is_internal_thermal_sensor(adev->pm.int_thermal_type)) {
++          kv_is_internal_thermal_sensor(adev->pm.int_thermal_type)) {
+               ret = kv_set_thermal_temperature_range(adev, KV_TEMP_RANGE_MIN, KV_TEMP_RANGE_MAX);
+               if (ret) {
+                       DRM_ERROR("kv_set_thermal_temperature_range failed\n");
+-- 
+2.43.0
+
diff --git a/queue-5.15/drm-amdgpu-reset-ih-overflow_clear-bit.patch b/queue-5.15/drm-amdgpu-reset-ih-overflow_clear-bit.patch
new file mode 100644 (file)
index 0000000..867bae1
--- /dev/null
@@ -0,0 +1,170 @@
+From 4e02f3eb93bde1f67d25d4d602037c8e9b53088f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Jan 2024 12:52:03 +0100
+Subject: drm/amdgpu: Reset IH OVERFLOW_CLEAR bit
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Friedrich Vock <friedrich.vock@gmx.de>
+
+[ Upstream commit 7330256268664ea0a7dd5b07a3fed363093477dd ]
+
+Allows us to detect subsequent IH ring buffer overflows as well.
+
+Cc: Joshua Ashton <joshua@froggi.es>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: Christian König <christian.koenig@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Friedrich Vock <friedrich.vock@gmx.de>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/cik_ih.c     | 6 ++++++
+ drivers/gpu/drm/amd/amdgpu/cz_ih.c      | 5 +++++
+ drivers/gpu/drm/amd/amdgpu/iceland_ih.c | 5 +++++
+ drivers/gpu/drm/amd/amdgpu/navi10_ih.c  | 6 ++++++
+ drivers/gpu/drm/amd/amdgpu/si_ih.c      | 6 ++++++
+ drivers/gpu/drm/amd/amdgpu/tonga_ih.c   | 6 ++++++
+ drivers/gpu/drm/amd/amdgpu/vega10_ih.c  | 6 ++++++
+ drivers/gpu/drm/amd/amdgpu/vega20_ih.c  | 6 ++++++
+ 8 files changed, 46 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/cik_ih.c b/drivers/gpu/drm/amd/amdgpu/cik_ih.c
+index df385ffc97683..6578ca1b90afa 100644
+--- a/drivers/gpu/drm/amd/amdgpu/cik_ih.c
++++ b/drivers/gpu/drm/amd/amdgpu/cik_ih.c
+@@ -204,6 +204,12 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev,
+               tmp = RREG32(mmIH_RB_CNTL);
+               tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK;
+               WREG32(mmIH_RB_CNTL, tmp);
++
++              /* Unset the CLEAR_OVERFLOW bit immediately so new overflows
++               * can be detected.
++               */
++              tmp &= ~IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK;
++              WREG32(mmIH_RB_CNTL, tmp);
+       }
+       return (wptr & ih->ptr_mask);
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ih.c b/drivers/gpu/drm/amd/amdgpu/cz_ih.c
+index b8c47e0cf37ad..c19681492efa7 100644
+--- a/drivers/gpu/drm/amd/amdgpu/cz_ih.c
++++ b/drivers/gpu/drm/amd/amdgpu/cz_ih.c
+@@ -216,6 +216,11 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev,
+       tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
+       WREG32(mmIH_RB_CNTL, tmp);
++      /* Unset the CLEAR_OVERFLOW bit immediately so new overflows
++       * can be detected.
++       */
++      tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
++      WREG32(mmIH_RB_CNTL, tmp);
+ out:
+       return (wptr & ih->ptr_mask);
+diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
+index ddfe4eaeea05e..77aacc242d439 100644
+--- a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
++++ b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c
+@@ -215,6 +215,11 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev,
+       tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
+       WREG32(mmIH_RB_CNTL, tmp);
++      /* Unset the CLEAR_OVERFLOW bit immediately so new overflows
++       * can be detected.
++       */
++      tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
++      WREG32(mmIH_RB_CNTL, tmp);
+ out:
+       return (wptr & ih->ptr_mask);
+diff --git a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
+index 5300116228013..6aa1884147c4c 100644
+--- a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
++++ b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c
+@@ -447,6 +447,12 @@ static u32 navi10_ih_get_wptr(struct amdgpu_device *adev,
+       tmp = RREG32_NO_KIQ(ih_regs->ih_rb_cntl);
+       tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
+       WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp);
++
++      /* Unset the CLEAR_OVERFLOW bit immediately so new overflows
++       * can be detected.
++       */
++      tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
++      WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp);
+ out:
+       return (wptr & ih->ptr_mask);
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/si_ih.c b/drivers/gpu/drm/amd/amdgpu/si_ih.c
+index 9a24f17a57502..cada9f300a7f5 100644
+--- a/drivers/gpu/drm/amd/amdgpu/si_ih.c
++++ b/drivers/gpu/drm/amd/amdgpu/si_ih.c
+@@ -119,6 +119,12 @@ static u32 si_ih_get_wptr(struct amdgpu_device *adev,
+               tmp = RREG32(IH_RB_CNTL);
+               tmp |= IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK;
+               WREG32(IH_RB_CNTL, tmp);
++
++              /* Unset the CLEAR_OVERFLOW bit immediately so new overflows
++               * can be detected.
++               */
++              tmp &= ~IH_RB_CNTL__WPTR_OVERFLOW_CLEAR_MASK;
++              WREG32(IH_RB_CNTL, tmp);
+       }
+       return (wptr & ih->ptr_mask);
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
+index b08905d1c00f0..07a5d95be07f5 100644
+--- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
++++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c
+@@ -219,6 +219,12 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev,
+       tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
+       WREG32(mmIH_RB_CNTL, tmp);
++      /* Unset the CLEAR_OVERFLOW bit immediately so new overflows
++       * can be detected.
++       */
++      tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
++      WREG32(mmIH_RB_CNTL, tmp);
++
+ out:
+       return (wptr & ih->ptr_mask);
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
+index 73728fa859970..e0524197f1b3d 100644
+--- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
++++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c
+@@ -371,6 +371,12 @@ static u32 vega10_ih_get_wptr(struct amdgpu_device *adev,
+       tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
+       WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp);
++      /* Unset the CLEAR_OVERFLOW bit immediately so new overflows
++       * can be detected.
++       */
++      tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
++      WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp);
++
+ out:
+       return (wptr & ih->ptr_mask);
+ }
+diff --git a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c
+index ac34af4cb178c..87edd1908e8b9 100644
+--- a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c
++++ b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c
+@@ -422,6 +422,12 @@ static u32 vega20_ih_get_wptr(struct amdgpu_device *adev,
+       tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 1);
+       WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp);
++      /* Unset the CLEAR_OVERFLOW bit immediately so new overflows
++       * can be detected.
++       */
++      tmp = REG_SET_FIELD(tmp, IH_RB_CNTL, WPTR_OVERFLOW_CLEAR, 0);
++      WREG32_NO_KIQ(ih_regs->ih_rb_cntl, tmp);
++
+ out:
+       return (wptr & ih->ptr_mask);
+ }
+-- 
+2.43.0
+
diff --git a/queue-5.15/exit-fix-typo-in-comment-s-sub-theads-sub-threads.patch b/queue-5.15/exit-fix-typo-in-comment-s-sub-theads-sub-threads.patch
new file mode 100644 (file)
index 0000000..860268e
--- /dev/null
@@ -0,0 +1,33 @@
+From 1f617efca64c4777c0f63bbf6af189268de89058 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Aug 2022 10:43:42 +0200
+Subject: exit: Fix typo in comment: s/sub-theads/sub-threads
+
+From: Ingo Molnar <mingo@kernel.org>
+
+[ Upstream commit dcca34754a3f5290406403b8066e3b15dda9f4bf ]
+
+Cc: linux-kernel@vger.kernel.org
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Stable-dep-of: c1be35a16b2f ("exit: wait_task_zombie: kill the no longer necessary spin_lock_irq(siglock)")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/exit.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/exit.c b/kernel/exit.c
+index 80efdfda6662b..e982111c489a9 100644
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -1119,7 +1119,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
+                * p->signal fields because the whole thread group is dead
+                * and nobody can change them.
+                *
+-               * psig->stats_lock also protects us from our sub-theads
++               * psig->stats_lock also protects us from our sub-threads
+                * which can reap other children at the same time. Until
+                * we change k_getrusage()-like users to rely on this lock
+                * we have to take ->siglock as well.
+-- 
+2.43.0
+
diff --git a/queue-5.15/exit-wait_task_zombie-kill-the-no-longer-necessary-s.patch b/queue-5.15/exit-wait_task_zombie-kill-the-no-longer-necessary-s.patch
new file mode 100644 (file)
index 0000000..b45c19a
--- /dev/null
@@ -0,0 +1,65 @@
+From 604746c31bdbf34966405f2a75644d27728068e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Jan 2024 16:34:00 +0100
+Subject: exit: wait_task_zombie: kill the no longer necessary
+ spin_lock_irq(siglock)
+
+From: Oleg Nesterov <oleg@redhat.com>
+
+[ Upstream commit c1be35a16b2f1fe21f4f26f9de030ad6eaaf6a25 ]
+
+After the recent changes nobody use siglock to read the values protected
+by stats_lock, we can kill spin_lock_irq(&current->sighand->siglock) and
+update the comment.
+
+With this patch only __exit_signal() and thread_group_start_cputime() take
+stats_lock under siglock.
+
+Link: https://lkml.kernel.org/r/20240123153359.GA21866@redhat.com
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
+Cc: Eric W. Biederman <ebiederm@xmission.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/exit.c | 10 +++-------
+ 1 file changed, 3 insertions(+), 7 deletions(-)
+
+diff --git a/kernel/exit.c b/kernel/exit.c
+index e982111c489a9..85baaa31b2997 100644
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -1120,17 +1120,14 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
+                * and nobody can change them.
+                *
+                * psig->stats_lock also protects us from our sub-threads
+-               * which can reap other children at the same time. Until
+-               * we change k_getrusage()-like users to rely on this lock
+-               * we have to take ->siglock as well.
++               * which can reap other children at the same time.
+                *
+                * We use thread_group_cputime_adjusted() to get times for
+                * the thread group, which consolidates times for all threads
+                * in the group including the group leader.
+                */
+               thread_group_cputime_adjusted(p, &tgutime, &tgstime);
+-              spin_lock_irq(&current->sighand->siglock);
+-              write_seqlock(&psig->stats_lock);
++              write_seqlock_irq(&psig->stats_lock);
+               psig->cutime += tgutime + sig->cutime;
+               psig->cstime += tgstime + sig->cstime;
+               psig->cgtime += task_gtime(p) + sig->gtime + sig->cgtime;
+@@ -1153,8 +1150,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
+                       psig->cmaxrss = maxrss;
+               task_io_accounting_add(&psig->ioac, &p->ioac);
+               task_io_accounting_add(&psig->ioac, &sig->ioac);
+-              write_sequnlock(&psig->stats_lock);
+-              spin_unlock_irq(&current->sighand->siglock);
++              write_sequnlock_irq(&psig->stats_lock);
+       }
+       if (wo->wo_rusage)
+-- 
+2.43.0
+
diff --git a/queue-5.15/fs-proc-do_task_stat-move-thread_group_cputime_adjus.patch b/queue-5.15/fs-proc-do_task_stat-move-thread_group_cputime_adjus.patch
new file mode 100644 (file)
index 0000000..ad5ba13
--- /dev/null
@@ -0,0 +1,81 @@
+From cc18e4bb6fc0ae25fa50c522f394b08170d857cd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Jan 2024 16:33:55 +0100
+Subject: fs/proc: do_task_stat: move thread_group_cputime_adjusted() outside
+ of lock_task_sighand()
+
+From: Oleg Nesterov <oleg@redhat.com>
+
+[ Upstream commit 60f92acb60a989b14e4b744501a0df0f82ef30a3 ]
+
+Patch series "fs/proc: do_task_stat: use sig->stats_".
+
+do_task_stat() has the same problem as getrusage() had before "getrusage:
+use sig->stats_lock rather than lock_task_sighand()": a hard lockup.  If
+NR_CPUS threads call lock_task_sighand() at the same time and the process
+has NR_THREADS, spin_lock_irq will spin with irqs disabled O(NR_CPUS *
+NR_THREADS) time.
+
+This patch (of 3):
+
+thread_group_cputime() does its own locking, we can safely shift
+thread_group_cputime_adjusted() which does another for_each_thread loop
+outside of ->siglock protected section.
+
+Not only this removes for_each_thread() from the critical section with
+irqs disabled, this removes another case when stats_lock is taken with
+siglock held.  We want to remove this dependency, then we can change the
+users of stats_lock to not disable irqs.
+
+Link: https://lkml.kernel.org/r/20240123153313.GA21832@redhat.com
+Link: https://lkml.kernel.org/r/20240123153355.GA21854@redhat.com
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Signed-off-by: Dylan Hatch <dylanbhatch@google.com>
+Cc: Eric W. Biederman <ebiederm@xmission.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/proc/array.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/fs/proc/array.c b/fs/proc/array.c
+index 77cf4187adecc..c925287a4dc4b 100644
+--- a/fs/proc/array.c
++++ b/fs/proc/array.c
+@@ -495,7 +495,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
+       sigemptyset(&sigign);
+       sigemptyset(&sigcatch);
+-      cutime = cstime = utime = stime = 0;
++      cutime = cstime = 0;
+       cgtime = gtime = 0;
+       if (lock_task_sighand(task, &flags)) {
+@@ -529,7 +529,6 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
+                       min_flt += sig->min_flt;
+                       maj_flt += sig->maj_flt;
+-                      thread_group_cputime_adjusted(task, &utime, &stime);
+                       gtime += sig->gtime;
+               }
+@@ -542,10 +541,13 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
+       if (permitted && (!whole || num_threads < 2))
+               wchan = !task_is_running(task);
+-      if (!whole) {
++
++      if (whole) {
++              thread_group_cputime_adjusted(task, &utime, &stime);
++      } else {
++              task_cputime_adjusted(task, &utime, &stime);
+               min_flt = task->min_flt;
+               maj_flt = task->maj_flt;
+-              task_cputime_adjusted(task, &utime, &stime);
+               gtime = task_gtime(task);
+       }
+-- 
+2.43.0
+
diff --git a/queue-5.15/getrusage-add-the-signal_struct-sig-local-variable.patch b/queue-5.15/getrusage-add-the-signal_struct-sig-local-variable.patch
new file mode 100644 (file)
index 0000000..93b9ca4
--- /dev/null
@@ -0,0 +1,93 @@
+From 829845be724c1424c9a6dc1791fc0029c8656b7b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 9 Sep 2023 19:25:54 +0200
+Subject: getrusage: add the "signal_struct *sig" local variable
+
+From: Oleg Nesterov <oleg@redhat.com>
+
+[ Upstream commit c7ac8231ace9b07306d0299969e42073b189c70a ]
+
+No functional changes, cleanup/preparation.
+
+Link: https://lkml.kernel.org/r/20230909172554.GA20441@redhat.com
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Cc: Eric W. Biederman <ebiederm@xmission.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: daa694e41375 ("getrusage: move thread_group_cputime_adjusted() outside of lock_task_sighand()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sys.c | 37 +++++++++++++++++++------------------
+ 1 file changed, 19 insertions(+), 18 deletions(-)
+
+diff --git a/kernel/sys.c b/kernel/sys.c
+index 2efab44746356..0298992c1eb9b 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -1764,6 +1764,7 @@ void getrusage(struct task_struct *p, int who, struct rusage *r)
+       unsigned long flags;
+       u64 tgutime, tgstime, utime, stime;
+       unsigned long maxrss = 0;
++      struct signal_struct *sig = p->signal;
+       memset((char *)r, 0, sizeof (*r));
+       utime = stime = 0;
+@@ -1771,7 +1772,7 @@ void getrusage(struct task_struct *p, int who, struct rusage *r)
+       if (who == RUSAGE_THREAD) {
+               task_cputime_adjusted(current, &utime, &stime);
+               accumulate_thread_rusage(p, r);
+-              maxrss = p->signal->maxrss;
++              maxrss = sig->maxrss;
+               goto out;
+       }
+@@ -1781,15 +1782,15 @@ void getrusage(struct task_struct *p, int who, struct rusage *r)
+       switch (who) {
+       case RUSAGE_BOTH:
+       case RUSAGE_CHILDREN:
+-              utime = p->signal->cutime;
+-              stime = p->signal->cstime;
+-              r->ru_nvcsw = p->signal->cnvcsw;
+-              r->ru_nivcsw = p->signal->cnivcsw;
+-              r->ru_minflt = p->signal->cmin_flt;
+-              r->ru_majflt = p->signal->cmaj_flt;
+-              r->ru_inblock = p->signal->cinblock;
+-              r->ru_oublock = p->signal->coublock;
+-              maxrss = p->signal->cmaxrss;
++              utime = sig->cutime;
++              stime = sig->cstime;
++              r->ru_nvcsw = sig->cnvcsw;
++              r->ru_nivcsw = sig->cnivcsw;
++              r->ru_minflt = sig->cmin_flt;
++              r->ru_majflt = sig->cmaj_flt;
++              r->ru_inblock = sig->cinblock;
++              r->ru_oublock = sig->coublock;
++              maxrss = sig->cmaxrss;
+               if (who == RUSAGE_CHILDREN)
+                       break;
+@@ -1799,14 +1800,14 @@ void getrusage(struct task_struct *p, int who, struct rusage *r)
+               thread_group_cputime_adjusted(p, &tgutime, &tgstime);
+               utime += tgutime;
+               stime += tgstime;
+-              r->ru_nvcsw += p->signal->nvcsw;
+-              r->ru_nivcsw += p->signal->nivcsw;
+-              r->ru_minflt += p->signal->min_flt;
+-              r->ru_majflt += p->signal->maj_flt;
+-              r->ru_inblock += p->signal->inblock;
+-              r->ru_oublock += p->signal->oublock;
+-              if (maxrss < p->signal->maxrss)
+-                      maxrss = p->signal->maxrss;
++              r->ru_nvcsw += sig->nvcsw;
++              r->ru_nivcsw += sig->nivcsw;
++              r->ru_minflt += sig->min_flt;
++              r->ru_majflt += sig->maj_flt;
++              r->ru_inblock += sig->inblock;
++              r->ru_oublock += sig->oublock;
++              if (maxrss < sig->maxrss)
++                      maxrss = sig->maxrss;
+               t = p;
+               do {
+                       accumulate_thread_rusage(t, r);
+-- 
+2.43.0
+
diff --git a/queue-5.15/getrusage-move-thread_group_cputime_adjusted-outside.patch b/queue-5.15/getrusage-move-thread_group_cputime_adjusted-outside.patch
new file mode 100644 (file)
index 0000000..8b4f71d
--- /dev/null
@@ -0,0 +1,111 @@
+From 51666a3a9c78ae153e07c1e62dd7acf605c487e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jan 2024 16:50:50 +0100
+Subject: getrusage: move thread_group_cputime_adjusted() outside of
+ lock_task_sighand()
+
+From: Oleg Nesterov <oleg@redhat.com>
+
+[ Upstream commit daa694e4137571b4ebec330f9a9b4d54aa8b8089 ]
+
+Patch series "getrusage: use sig->stats_lock", v2.
+
+This patch (of 2):
+
+thread_group_cputime() does its own locking, we can safely shift
+thread_group_cputime_adjusted() which does another for_each_thread loop
+outside of ->siglock protected section.
+
+This is also preparation for the next patch which changes getrusage() to
+use stats_lock instead of siglock, thread_group_cputime() takes the same
+lock.  With the current implementation recursive read_seqbegin_or_lock()
+is fine, thread_group_cputime() can't enter the slow mode if the caller
+holds stats_lock, yet this looks more safe and better performance-wise.
+
+Link: https://lkml.kernel.org/r/20240122155023.GA26169@redhat.com
+Link: https://lkml.kernel.org/r/20240122155050.GA26205@redhat.com
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Reported-by: Dylan Hatch <dylanbhatch@google.com>
+Tested-by: Dylan Hatch <dylanbhatch@google.com>
+Cc: Eric W. Biederman <ebiederm@xmission.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sys.c | 34 +++++++++++++++++++---------------
+ 1 file changed, 19 insertions(+), 15 deletions(-)
+
+diff --git a/kernel/sys.c b/kernel/sys.c
+index 0298992c1eb9b..25f0c0697356b 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -1763,17 +1763,19 @@ void getrusage(struct task_struct *p, int who, struct rusage *r)
+       struct task_struct *t;
+       unsigned long flags;
+       u64 tgutime, tgstime, utime, stime;
+-      unsigned long maxrss = 0;
++      unsigned long maxrss;
++      struct mm_struct *mm;
+       struct signal_struct *sig = p->signal;
+-      memset((char *)r, 0, sizeof (*r));
++      memset(r, 0, sizeof(*r));
+       utime = stime = 0;
++      maxrss = 0;
+       if (who == RUSAGE_THREAD) {
+               task_cputime_adjusted(current, &utime, &stime);
+               accumulate_thread_rusage(p, r);
+               maxrss = sig->maxrss;
+-              goto out;
++              goto out_thread;
+       }
+       if (!lock_task_sighand(p, &flags))
+@@ -1797,9 +1799,6 @@ void getrusage(struct task_struct *p, int who, struct rusage *r)
+               fallthrough;
+       case RUSAGE_SELF:
+-              thread_group_cputime_adjusted(p, &tgutime, &tgstime);
+-              utime += tgutime;
+-              stime += tgstime;
+               r->ru_nvcsw += sig->nvcsw;
+               r->ru_nivcsw += sig->nivcsw;
+               r->ru_minflt += sig->min_flt;
+@@ -1819,19 +1818,24 @@ void getrusage(struct task_struct *p, int who, struct rusage *r)
+       }
+       unlock_task_sighand(p, &flags);
+-out:
+-      r->ru_utime = ns_to_kernel_old_timeval(utime);
+-      r->ru_stime = ns_to_kernel_old_timeval(stime);
++      if (who == RUSAGE_CHILDREN)
++              goto out_children;
+-      if (who != RUSAGE_CHILDREN) {
+-              struct mm_struct *mm = get_task_mm(p);
++      thread_group_cputime_adjusted(p, &tgutime, &tgstime);
++      utime += tgutime;
++      stime += tgstime;
+-              if (mm) {
+-                      setmax_mm_hiwater_rss(&maxrss, mm);
+-                      mmput(mm);
+-              }
++out_thread:
++      mm = get_task_mm(p);
++      if (mm) {
++              setmax_mm_hiwater_rss(&maxrss, mm);
++              mmput(mm);
+       }
++
++out_children:
+       r->ru_maxrss = maxrss * (PAGE_SIZE / 1024); /* convert pages to KBs */
++      r->ru_utime = ns_to_kernel_old_timeval(utime);
++      r->ru_stime = ns_to_kernel_old_timeval(stime);
+ }
+ SYSCALL_DEFINE2(getrusage, int, who, struct rusage __user *, ru)
+-- 
+2.43.0
+
diff --git a/queue-5.15/getrusage-use-__for_each_thread.patch b/queue-5.15/getrusage-use-__for_each_thread.patch
new file mode 100644 (file)
index 0000000..1399ef5
--- /dev/null
@@ -0,0 +1,43 @@
+From 3b997873493d24e618f98d7546099ce96ca6e1de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 9 Sep 2023 19:26:29 +0200
+Subject: getrusage: use __for_each_thread()
+
+From: Oleg Nesterov <oleg@redhat.com>
+
+[ Upstream commit 13b7bc60b5353371460a203df6c38ccd38ad7a3a ]
+
+do/while_each_thread should be avoided when possible.
+
+Plus this change allows to avoid lock_task_sighand(), we can use rcu
+and/or sig->stats_lock instead.
+
+Link: https://lkml.kernel.org/r/20230909172629.GA20454@redhat.com
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Cc: Eric W. Biederman <ebiederm@xmission.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Stable-dep-of: f7ec1cd5cc7e ("getrusage: use sig->stats_lock rather than lock_task_sighand()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sys.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/kernel/sys.c b/kernel/sys.c
+index 25f0c0697356b..85f358a5d5eb5 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -1807,10 +1807,8 @@ void getrusage(struct task_struct *p, int who, struct rusage *r)
+               r->ru_oublock += sig->oublock;
+               if (maxrss < sig->maxrss)
+                       maxrss = sig->maxrss;
+-              t = p;
+-              do {
++              __for_each_thread(sig, t)
+                       accumulate_thread_rusage(t, r);
+-              } while_each_thread(p, t);
+               break;
+       default:
+-- 
+2.43.0
+
diff --git a/queue-5.15/getrusage-use-sig-stats_lock-rather-than-lock_task_s.patch b/queue-5.15/getrusage-use-sig-stats_lock-rather-than-lock_task_s.patch
new file mode 100644 (file)
index 0000000..7bf20d1
--- /dev/null
@@ -0,0 +1,92 @@
+From 59a147da2ba7e91424c1ec97c53ca0773968f60c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jan 2024 16:50:53 +0100
+Subject: getrusage: use sig->stats_lock rather than lock_task_sighand()
+
+From: Oleg Nesterov <oleg@redhat.com>
+
+[ Upstream commit f7ec1cd5cc7ef3ad964b677ba82b8b77f1c93009 ]
+
+lock_task_sighand() can trigger a hard lockup. If NR_CPUS threads call
+getrusage() at the same time and the process has NR_THREADS, spin_lock_irq
+will spin with irqs disabled O(NR_CPUS * NR_THREADS) time.
+
+Change getrusage() to use sig->stats_lock, it was specifically designed
+for this type of use. This way it runs lockless in the likely case.
+
+TODO:
+       - Change do_task_stat() to use sig->stats_lock too, then we can
+         remove spin_lock_irq(siglock) in wait_task_zombie().
+
+       - Turn sig->stats_lock into seqcount_rwlock_t, this way the
+         readers in the slow mode won't exclude each other. See
+         https://lore.kernel.org/all/20230913154907.GA26210@redhat.com/
+
+       - stats_lock has to disable irqs because ->siglock can be taken
+         in irq context, it would be very nice to change __exit_signal()
+         to avoid the siglock->stats_lock dependency.
+
+Link: https://lkml.kernel.org/r/20240122155053.GA26214@redhat.com
+Signed-off-by: Oleg Nesterov <oleg@redhat.com>
+Reported-by: Dylan Hatch <dylanbhatch@google.com>
+Tested-by: Dylan Hatch <dylanbhatch@google.com>
+Cc: Eric W. Biederman <ebiederm@xmission.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sys.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/sys.c b/kernel/sys.c
+index 85f358a5d5eb5..2cfb829864c63 100644
+--- a/kernel/sys.c
++++ b/kernel/sys.c
+@@ -1766,7 +1766,9 @@ void getrusage(struct task_struct *p, int who, struct rusage *r)
+       unsigned long maxrss;
+       struct mm_struct *mm;
+       struct signal_struct *sig = p->signal;
++      unsigned int seq = 0;
++retry:
+       memset(r, 0, sizeof(*r));
+       utime = stime = 0;
+       maxrss = 0;
+@@ -1778,8 +1780,7 @@ void getrusage(struct task_struct *p, int who, struct rusage *r)
+               goto out_thread;
+       }
+-      if (!lock_task_sighand(p, &flags))
+-              return;
++      flags = read_seqbegin_or_lock_irqsave(&sig->stats_lock, &seq);
+       switch (who) {
+       case RUSAGE_BOTH:
+@@ -1807,14 +1808,23 @@ void getrusage(struct task_struct *p, int who, struct rusage *r)
+               r->ru_oublock += sig->oublock;
+               if (maxrss < sig->maxrss)
+                       maxrss = sig->maxrss;
++
++              rcu_read_lock();
+               __for_each_thread(sig, t)
+                       accumulate_thread_rusage(t, r);
++              rcu_read_unlock();
++
+               break;
+       default:
+               BUG();
+       }
+-      unlock_task_sighand(p, &flags);
++
++      if (need_seqretry(&sig->stats_lock, seq)) {
++              seq = 1;
++              goto retry;
++      }
++      done_seqretry_irqrestore(&sig->stats_lock, seq, flags);
+       if (who == RUSAGE_CHILDREN)
+               goto out_children;
+-- 
+2.43.0
+
diff --git a/queue-5.15/hv_netvsc-register-vf-in-netvsc_probe-if-net_device_.patch b/queue-5.15/hv_netvsc-register-vf-in-netvsc_probe-if-net_device_.patch
new file mode 100644 (file)
index 0000000..2dc6edd
--- /dev/null
@@ -0,0 +1,184 @@
+From 7a45ba5acfa54a330c3ea6aa99ff13b8e0840b63 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Feb 2024 20:40:38 -0800
+Subject: hv_netvsc: Register VF in netvsc_probe if NET_DEVICE_REGISTER missed
+
+From: Shradha Gupta <shradhagupta@linux.microsoft.com>
+
+[ Upstream commit 9cae43da9867412f8bd09aee5c8a8dc5e8dc3dc2 ]
+
+If hv_netvsc driver is unloaded and reloaded, the NET_DEVICE_REGISTER
+handler cannot perform VF register successfully as the register call
+is received before netvsc_probe is finished. This is because we
+register register_netdevice_notifier() very early( even before
+vmbus_driver_register()).
+To fix this, we try to register each such matching VF( if it is visible
+as a netdevice) at the end of netvsc_probe.
+
+Cc: stable@vger.kernel.org
+Fixes: 85520856466e ("hv_netvsc: Fix race of register_netdevice_notifier and VF register")
+Suggested-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: Shradha Gupta <shradhagupta@linux.microsoft.com>
+Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/hyperv/netvsc_drv.c | 82 +++++++++++++++++++++++++--------
+ 1 file changed, 62 insertions(+), 20 deletions(-)
+
+diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
+index a7d1304466880..804c11cbccff6 100644
+--- a/drivers/net/hyperv/netvsc_drv.c
++++ b/drivers/net/hyperv/netvsc_drv.c
+@@ -42,6 +42,10 @@
+ #define LINKCHANGE_INT (2 * HZ)
+ #define VF_TAKEOVER_INT (HZ / 10)
++/* Macros to define the context of vf registration */
++#define VF_REG_IN_PROBE               1
++#define VF_REG_IN_NOTIFIER    2
++
+ static unsigned int ring_size __ro_after_init = 128;
+ module_param(ring_size, uint, 0444);
+ MODULE_PARM_DESC(ring_size, "Ring buffer size (# of 4K pages)");
+@@ -2204,7 +2208,7 @@ static rx_handler_result_t netvsc_vf_handle_frame(struct sk_buff **pskb)
+ }
+ static int netvsc_vf_join(struct net_device *vf_netdev,
+-                        struct net_device *ndev)
++                        struct net_device *ndev, int context)
+ {
+       struct net_device_context *ndev_ctx = netdev_priv(ndev);
+       int ret;
+@@ -2227,7 +2231,11 @@ static int netvsc_vf_join(struct net_device *vf_netdev,
+               goto upper_link_failed;
+       }
+-      schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
++      /* If this registration is called from probe context vf_takeover
++       * is taken care of later in probe itself.
++       */
++      if (context == VF_REG_IN_NOTIFIER)
++              schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
+       call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
+@@ -2365,7 +2373,7 @@ static int netvsc_prepare_bonding(struct net_device *vf_netdev)
+       return NOTIFY_DONE;
+ }
+-static int netvsc_register_vf(struct net_device *vf_netdev)
++static int netvsc_register_vf(struct net_device *vf_netdev, int context)
+ {
+       struct net_device_context *net_device_ctx;
+       struct netvsc_device *netvsc_dev;
+@@ -2405,7 +2413,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
+       netdev_info(ndev, "VF registering: %s\n", vf_netdev->name);
+-      if (netvsc_vf_join(vf_netdev, ndev) != 0)
++      if (netvsc_vf_join(vf_netdev, ndev, context) != 0)
+               return NOTIFY_DONE;
+       dev_hold(vf_netdev);
+@@ -2503,10 +2511,31 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev)
+       return NOTIFY_OK;
+ }
++static int check_dev_is_matching_vf(struct net_device *event_ndev)
++{
++      /* Skip NetVSC interfaces */
++      if (event_ndev->netdev_ops == &device_ops)
++              return -ENODEV;
++
++      /* Avoid non-Ethernet type devices */
++      if (event_ndev->type != ARPHRD_ETHER)
++              return -ENODEV;
++
++      /* Avoid Vlan dev with same MAC registering as VF */
++      if (is_vlan_dev(event_ndev))
++              return -ENODEV;
++
++      /* Avoid Bonding master dev with same MAC registering as VF */
++      if (netif_is_bond_master(event_ndev))
++              return -ENODEV;
++
++      return 0;
++}
++
+ static int netvsc_probe(struct hv_device *dev,
+                       const struct hv_vmbus_device_id *dev_id)
+ {
+-      struct net_device *net = NULL;
++      struct net_device *net = NULL, *vf_netdev;
+       struct net_device_context *net_device_ctx;
+       struct netvsc_device_info *device_info = NULL;
+       struct netvsc_device *nvdev;
+@@ -2614,6 +2643,30 @@ static int netvsc_probe(struct hv_device *dev,
+       }
+       list_add(&net_device_ctx->list, &netvsc_dev_list);
++
++      /* When the hv_netvsc driver is unloaded and reloaded, the
++       * NET_DEVICE_REGISTER for the vf device is replayed before probe
++       * is complete. This is because register_netdevice_notifier() gets
++       * registered before vmbus_driver_register() so that callback func
++       * is set before probe and we don't miss events like NETDEV_POST_INIT
++       * So, in this section we try to register the matching vf device that
++       * is present as a netdevice, knowing that its register call is not
++       * processed in the netvsc_netdev_notifier(as probing is progress and
++       * get_netvsc_byslot fails).
++       */
++      for_each_netdev(dev_net(net), vf_netdev) {
++              ret = check_dev_is_matching_vf(vf_netdev);
++              if (ret != 0)
++                      continue;
++
++              if (net != get_netvsc_byslot(vf_netdev))
++                      continue;
++
++              netvsc_prepare_bonding(vf_netdev);
++              netvsc_register_vf(vf_netdev, VF_REG_IN_PROBE);
++              __netvsc_vf_setup(net, vf_netdev);
++              break;
++      }
+       rtnl_unlock();
+       netvsc_devinfo_put(device_info);
+@@ -2770,28 +2823,17 @@ static int netvsc_netdev_event(struct notifier_block *this,
+                              unsigned long event, void *ptr)
+ {
+       struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
++      int ret = 0;
+-      /* Skip our own events */
+-      if (event_dev->netdev_ops == &device_ops)
+-              return NOTIFY_DONE;
+-
+-      /* Avoid non-Ethernet type devices */
+-      if (event_dev->type != ARPHRD_ETHER)
+-              return NOTIFY_DONE;
+-
+-      /* Avoid Vlan dev with same MAC registering as VF */
+-      if (is_vlan_dev(event_dev))
+-              return NOTIFY_DONE;
+-
+-      /* Avoid Bonding master dev with same MAC registering as VF */
+-      if (netif_is_bond_master(event_dev))
++      ret = check_dev_is_matching_vf(event_dev);
++      if (ret != 0)
+               return NOTIFY_DONE;
+       switch (event) {
+       case NETDEV_POST_INIT:
+               return netvsc_prepare_bonding(event_dev);
+       case NETDEV_REGISTER:
+-              return netvsc_register_vf(event_dev);
++              return netvsc_register_vf(event_dev, VF_REG_IN_NOTIFIER);
+       case NETDEV_UNREGISTER:
+               return netvsc_unregister_vf(event_dev);
+       case NETDEV_UP:
+-- 
+2.43.0
+
diff --git a/queue-5.15/hv_netvsc-use-netif_is_bond_master-instead-of-open-c.patch b/queue-5.15/hv_netvsc-use-netif_is_bond_master-instead-of-open-c.patch
new file mode 100644 (file)
index 0000000..640c274
--- /dev/null
@@ -0,0 +1,38 @@
+From 6f6fdc40a52b38dea903af25b0b238d803c1b0b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 10 Oct 2021 13:03:28 +0900
+Subject: hv_netvsc: use netif_is_bond_master() instead of open code
+
+From: Juhee Kang <claudiajkang@gmail.com>
+
+[ Upstream commit c60882a4566a0a62dc3a40c85131103aad83dcb3 ]
+
+Use netif_is_bond_master() function instead of open code, which is
+((event_dev->priv_flags & IFF_BONDING) && (event_dev->flags & IFF_MASTER)).
+This patch doesn't change logic.
+
+Signed-off-by: Juhee Kang <claudiajkang@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 9cae43da9867 ("hv_netvsc: Register VF in netvsc_probe if NET_DEVICE_REGISTER missed")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/hyperv/netvsc_drv.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
+index 25b65450cbb99..a7d1304466880 100644
+--- a/drivers/net/hyperv/netvsc_drv.c
++++ b/drivers/net/hyperv/netvsc_drv.c
+@@ -2784,8 +2784,7 @@ static int netvsc_netdev_event(struct notifier_block *this,
+               return NOTIFY_DONE;
+       /* Avoid Bonding master dev with same MAC registering as VF */
+-      if ((event_dev->priv_flags & IFF_BONDING) &&
+-          (event_dev->flags & IFF_MASTER))
++      if (netif_is_bond_master(event_dev))
+               return NOTIFY_DONE;
+       switch (event) {
+-- 
+2.43.0
+
diff --git a/queue-5.15/modpost-add-.ltext-and-.ltext.-to-text_sections.patch b/queue-5.15/modpost-add-.ltext-and-.ltext.-to-text_sections.patch
new file mode 100644 (file)
index 0000000..b8f7f40
--- /dev/null
@@ -0,0 +1,55 @@
+From e4a13ccef32375884dd266b8ba59d697f359bb84 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Jan 2024 15:59:55 -0700
+Subject: modpost: Add '.ltext' and '.ltext.*' to TEXT_SECTIONS
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+[ Upstream commit 397586506c3da005b9333ce5947ad01e8018a3be ]
+
+After the linked LLVM change, building ARCH=um defconfig results in a
+segmentation fault in modpost. Prior to commit a23e7584ecf3 ("modpost:
+unify 'sym' and 'to' in default_mismatch_handler()"), there was a
+warning:
+
+  WARNING: modpost: vmlinux.o(__ex_table+0x88): Section mismatch in reference to the .ltext:(unknown)
+  WARNING: modpost: The relocation at __ex_table+0x88 references
+  section ".ltext" which is not in the list of
+  authorized sections.  If you're adding a new section
+  and/or if this reference is valid, add ".ltext" to the
+  list of authorized sections to jump to on fault.
+  This can be achieved by adding ".ltext" to
+  OTHER_TEXT_SECTIONS in scripts/mod/modpost.c.
+
+The linked LLVM change moves global objects to the '.ltext' (and
+'.ltext.*' with '-ffunction-sections') sections with '-mcmodel=large',
+which ARCH=um uses. These sections should be handled just as '.text'
+and '.text.*' are, so add them to TEXT_SECTIONS.
+
+Cc: stable@vger.kernel.org
+Closes: https://github.com/ClangBuiltLinux/linux/issues/1981
+Link: https://github.com/llvm/llvm-project/commit/4bf8a688956a759b7b6b8d94f42d25c13c7af130
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ scripts/mod/modpost.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
+index 43bacdee5cc5d..201ac1bf5030d 100644
+--- a/scripts/mod/modpost.c
++++ b/scripts/mod/modpost.c
+@@ -937,7 +937,8 @@ static void check_section(const char *modname, struct elf_info *elf,
+ #define DATA_SECTIONS ".data", ".data.rel"
+ #define TEXT_SECTIONS ".text", ".text.*", ".sched.text", \
+-              ".kprobes.text", ".cpuidle.text", ".noinstr.text"
++              ".kprobes.text", ".cpuidle.text", ".noinstr.text", \
++              ".ltext", ".ltext.*"
+ #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
+               ".fixup", ".entry.text", ".exception.text", \
+               ".coldtext", ".softirqentry.text"
+-- 
+2.43.0
+
diff --git a/queue-5.15/modpost-include-.text.-in-text_sections.patch b/queue-5.15/modpost-include-.text.-in-text_sections.patch
new file mode 100644 (file)
index 0000000..f933bae
--- /dev/null
@@ -0,0 +1,53 @@
+From dc17488354b9dd27b5d2edcd64fc12d0a97281c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Dec 2022 11:35:29 -0700
+Subject: modpost: Include '.text.*' in TEXT_SECTIONS
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+[ Upstream commit 19331e84c3873256537d446afec1f6c507f8c4ef ]
+
+Commit 6c730bfc894f ("modpost: handle -ffunction-sections") added
+".text.*" to the OTHER_TEXT_SECTIONS macro to fix certain section
+mismatch warnings. Unfortunately, this makes it impossible for modpost
+to warn about section mismatches with LTO, which implies
+'-ffunction-sections', as all functions are put in their own
+'.text.<func_name>' sections, which may still reference functions in
+sections they are not supposed to, such as __init.
+
+Fix this by moving ".text.*" into TEXT_SECTIONS, so that configurations
+with '-ffunction-sections' will see warnings about mismatched sections.
+
+Link: https://lore.kernel.org/Y39kI3MOtVI5BAnV@google.com/
+Reported-by: Vincent Donnefort <vdonnefort@google.com>
+Reviewed-and-tested-by: Alexander Lobakin <alexandr.lobakin@intel.com>
+Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
+Tested-by: Vincent Donnefort <vdonnefort@google.com>
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Stable-dep-of: 397586506c3d ("modpost: Add '.ltext' and '.ltext.*' to TEXT_SECTIONS")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ scripts/mod/modpost.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
+index c6e655e0ed988..43bacdee5cc5d 100644
+--- a/scripts/mod/modpost.c
++++ b/scripts/mod/modpost.c
+@@ -936,10 +936,10 @@ static void check_section(const char *modname, struct elf_info *elf,
+ #define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS
+ #define DATA_SECTIONS ".data", ".data.rel"
+-#define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \
++#define TEXT_SECTIONS ".text", ".text.*", ".sched.text", \
+               ".kprobes.text", ".cpuidle.text", ".noinstr.text"
+ #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
+-              ".fixup", ".entry.text", ".exception.text", ".text.*", \
++              ".fixup", ".entry.text", ".exception.text", \
+               ".coldtext", ".softirqentry.text"
+ #define INIT_SECTIONS      ".init.*"
+-- 
+2.43.0
+
diff --git a/queue-5.15/nfp-flower-add-goto_chain_index-for-ct-entry.patch b/queue-5.15/nfp-flower-add-goto_chain_index-for-ct-entry.patch
new file mode 100644 (file)
index 0000000..73aa4a9
--- /dev/null
@@ -0,0 +1,95 @@
+From 87339f9f7477eafd7071f0e7d0bf7799f7771198 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Mar 2023 08:36:08 +0200
+Subject: nfp: flower: add goto_chain_index for ct entry
+
+From: Wentao Jia <wentao.jia@corigine.com>
+
+[ Upstream commit 3e44d19934b92398785b3ffc2353b9eba264140e ]
+
+The chain_index has different means in pre ct entry and post ct entry.
+In pre ct entry, it means chain index, but in post ct entry, it means
+goto chain index, it is confused.
+
+chain_index and goto_chain_index may be present in one flow rule, It
+cannot be distinguished by one field chain_index, both chain_index
+and goto_chain_index are required in the follow-up patch to support
+multiple ct zones
+
+Another field goto_chain_index is added to record the goto chain index.
+If no goto action in post ct entry, goto_chain_index is 0.
+
+Signed-off-by: Wentao Jia <wentao.jia@corigine.com>
+Acked-by: Simon Horman <simon.horman@corigine.com>
+Signed-off-by: Louis Peens <louis.peens@corigine.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: cefa98e806fd ("nfp: flower: add hardware offload check for post ct entry")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/netronome/nfp/flower/conntrack.c | 8 ++++++--
+ drivers/net/ethernet/netronome/nfp/flower/conntrack.h | 2 ++
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/netronome/nfp/flower/conntrack.c b/drivers/net/ethernet/netronome/nfp/flower/conntrack.c
+index fc17e9b11d19d..0a5592b12e2d1 100644
+--- a/drivers/net/ethernet/netronome/nfp/flower/conntrack.c
++++ b/drivers/net/ethernet/netronome/nfp/flower/conntrack.c
+@@ -1004,7 +1004,7 @@ static int nfp_ct_do_tc_merge(struct nfp_fl_ct_zone_entry *zt,
+       /* Checks that the chain_index of the filter matches the
+        * chain_index of the GOTO action.
+        */
+-      if (post_ct_entry->chain_index != pre_ct_entry->chain_index)
++      if (post_ct_entry->chain_index != pre_ct_entry->goto_chain_index)
+               return -EINVAL;
+       err = nfp_ct_merge_check(post_ct_entry, pre_ct_entry);
+@@ -1450,7 +1450,8 @@ int nfp_fl_ct_handle_pre_ct(struct nfp_flower_priv *priv,
+       if (IS_ERR(ct_entry))
+               return PTR_ERR(ct_entry);
+       ct_entry->type = CT_TYPE_PRE_CT;
+-      ct_entry->chain_index = ct_goto->chain_index;
++      ct_entry->chain_index = flow->common.chain_index;
++      ct_entry->goto_chain_index = ct_goto->chain_index;
+       list_add(&ct_entry->list_node, &zt->pre_ct_list);
+       zt->pre_ct_count++;
+@@ -1473,6 +1474,7 @@ int nfp_fl_ct_handle_post_ct(struct nfp_flower_priv *priv,
+       struct nfp_fl_ct_zone_entry *zt;
+       bool wildcarded = false;
+       struct flow_match_ct ct;
++      struct flow_action_entry *ct_goto;
+       flow_rule_match_ct(rule, &ct);
+       if (!ct.mask->ct_zone) {
+@@ -1497,6 +1499,8 @@ int nfp_fl_ct_handle_post_ct(struct nfp_flower_priv *priv,
+       ct_entry->type = CT_TYPE_POST_CT;
+       ct_entry->chain_index = flow->common.chain_index;
++      ct_goto = get_flow_act(flow->rule, FLOW_ACTION_GOTO);
++      ct_entry->goto_chain_index = ct_goto ? ct_goto->chain_index : 0;
+       list_add(&ct_entry->list_node, &zt->post_ct_list);
+       zt->post_ct_count++;
+diff --git a/drivers/net/ethernet/netronome/nfp/flower/conntrack.h b/drivers/net/ethernet/netronome/nfp/flower/conntrack.h
+index beb6cceff9d8e..47607cd8a716d 100644
+--- a/drivers/net/ethernet/netronome/nfp/flower/conntrack.h
++++ b/drivers/net/ethernet/netronome/nfp/flower/conntrack.h
+@@ -108,6 +108,7 @@ enum nfp_nfp_layer_name {
+  * @cookie:   Flow cookie, same as original TC flow, used as key
+  * @list_node:        Used by the list
+  * @chain_index:      Chain index of the original flow
++ * @goto_chain_index: goto chain index of the flow
+  * @netdev:   netdev structure.
+  * @type:     Type of pre-entry from enum ct_entry_type
+  * @zt:               Reference to the zone table this belongs to
+@@ -120,6 +121,7 @@ struct nfp_fl_ct_flow_entry {
+       unsigned long cookie;
+       struct list_head list_node;
+       u32 chain_index;
++      u32 goto_chain_index;
+       enum ct_entry_type type;
+       struct net_device *netdev;
+       struct nfp_fl_ct_zone_entry *zt;
+-- 
+2.43.0
+
diff --git a/queue-5.15/nfp-flower-add-hardware-offload-check-for-post-ct-en.patch b/queue-5.15/nfp-flower-add-hardware-offload-check-for-post-ct-en.patch
new file mode 100644 (file)
index 0000000..762bc7e
--- /dev/null
@@ -0,0 +1,68 @@
+From cc07175827fb87e021328f091ed1855f180535be Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Jan 2024 17:19:08 +0200
+Subject: nfp: flower: add hardware offload check for post ct entry
+
+From: Hui Zhou <hui.zhou@corigine.com>
+
+[ Upstream commit cefa98e806fd4e2a5e2047457a11ae5f17b8f621 ]
+
+The nfp offload flow pay will not allocate a mask id when the out port
+is openvswitch internal port. This is because these flows are used to
+configure the pre_tun table and are never actually send to the firmware
+as an add-flow message. When a tc rule which action contains ct and
+the post ct entry's out port is openvswitch internal port, the merge
+offload flow pay with the wrong mask id of 0 will be send to the
+firmware. Actually, the nfp can not support hardware offload for this
+situation, so return EOPNOTSUPP.
+
+Fixes: bd0fe7f96a3c ("nfp: flower-ct: add zone table entry when handling pre/post_ct flows")
+CC: stable@vger.kernel.org # 5.14+
+Signed-off-by: Hui Zhou <hui.zhou@corigine.com>
+Signed-off-by: Louis Peens <louis.peens@corigine.com>
+Link: https://lore.kernel.org/r/20240124151909.31603-2-louis.peens@corigine.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/netronome/nfp/flower/conntrack.c | 22 ++++++++++++++++++-
+ 1 file changed, 21 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/netronome/nfp/flower/conntrack.c b/drivers/net/ethernet/netronome/nfp/flower/conntrack.c
+index 0a5592b12e2d1..03a2dbcfbe566 100644
+--- a/drivers/net/ethernet/netronome/nfp/flower/conntrack.c
++++ b/drivers/net/ethernet/netronome/nfp/flower/conntrack.c
+@@ -1471,10 +1471,30 @@ int nfp_fl_ct_handle_post_ct(struct nfp_flower_priv *priv,
+ {
+       struct flow_rule *rule = flow_cls_offload_flow_rule(flow);
+       struct nfp_fl_ct_flow_entry *ct_entry;
++      struct flow_action_entry *ct_goto;
+       struct nfp_fl_ct_zone_entry *zt;
++      struct flow_action_entry *act;
+       bool wildcarded = false;
+       struct flow_match_ct ct;
+-      struct flow_action_entry *ct_goto;
++      int i;
++
++      flow_action_for_each(i, act, &rule->action) {
++              switch (act->id) {
++              case FLOW_ACTION_REDIRECT:
++              case FLOW_ACTION_REDIRECT_INGRESS:
++              case FLOW_ACTION_MIRRED:
++              case FLOW_ACTION_MIRRED_INGRESS:
++                      if (act->dev->rtnl_link_ops &&
++                          !strcmp(act->dev->rtnl_link_ops->kind, "openvswitch")) {
++                              NL_SET_ERR_MSG_MOD(extack,
++                                                 "unsupported offload: out port is openvswitch internal port");
++                              return -EOPNOTSUPP;
++                      }
++                      break;
++              default:
++                      break;
++              }
++      }
+       flow_rule_match_ct(rule, &ct);
+       if (!ct.mask->ct_zone) {
+-- 
+2.43.0
+
diff --git a/queue-5.15/nfsd-add-documenting-comment-for-nfsd4_release_locko.patch b/queue-5.15/nfsd-add-documenting-comment-for-nfsd4_release_locko.patch
new file mode 100644 (file)
index 0000000..ed1d05a
--- /dev/null
@@ -0,0 +1,73 @@
+From e1b27bbfe2fce3942ff80b3eb6458c53b7b628d2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 May 2022 12:34:38 -0400
+Subject: NFSD: Add documenting comment for nfsd4_release_lockowner()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 043862b09cc00273e35e6c3a6389957953a34207 ]
+
+And return explicit nfserr values that match what is documented in the
+new comment / API contract.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Stable-dep-of: edcf9725150e ("nfsd: fix RELEASE_LOCKOWNER")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/nfs4state.c | 23 ++++++++++++++++++++---
+ 1 file changed, 20 insertions(+), 3 deletions(-)
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 798063b9b96fd..f8533299db1c5 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -7284,6 +7284,23 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
+       return status;
+ }
++/**
++ * nfsd4_release_lockowner - process NFSv4.0 RELEASE_LOCKOWNER operations
++ * @rqstp: RPC transaction
++ * @cstate: NFSv4 COMPOUND state
++ * @u: RELEASE_LOCKOWNER arguments
++ *
++ * The lockowner's so_count is bumped when a lock record is added
++ * or when copying a conflicting lock. The latter case is brief,
++ * but can lead to fleeting false positives when looking for
++ * locks-in-use.
++ *
++ * Return values:
++ *   %nfs_ok: lockowner released or not found
++ *   %nfserr_locks_held: lockowner still in use
++ *   %nfserr_stale_clientid: clientid no longer active
++ *   %nfserr_expired: clientid not recognized
++ */
+ __be32
+ nfsd4_release_lockowner(struct svc_rqst *rqstp,
+                       struct nfsd4_compound_state *cstate,
+@@ -7310,7 +7327,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
+       lo = find_lockowner_str_locked(clp, &rlockowner->rl_owner);
+       if (!lo) {
+               spin_unlock(&clp->cl_lock);
+-              return status;
++              return nfs_ok;
+       }
+       if (atomic_read(&lo->lo_owner.so_count) != 2) {
+               spin_unlock(&clp->cl_lock);
+@@ -7326,11 +7343,11 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
+               put_ol_stateid_locked(stp, &reaplist);
+       }
+       spin_unlock(&clp->cl_lock);
++
+       free_ol_stateid_reaplist(&reaplist);
+       remove_blocked_locks(lo);
+       nfs4_put_stateowner(&lo->lo_owner);
+-
+-      return status;
++      return nfs_ok;
+ }
+ static inline struct nfs4_client_reclaim *
+-- 
+2.43.0
+
diff --git a/queue-5.15/nfsd-don-t-take-fi_lock-in-nfsd_break_deleg_cb.patch b/queue-5.15/nfsd-don-t-take-fi_lock-in-nfsd_break_deleg_cb.patch
new file mode 100644 (file)
index 0000000..865ad5a
--- /dev/null
@@ -0,0 +1,97 @@
+From 717ab4f6347df5c3588c0e63148f784d76ec369c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Feb 2024 13:22:39 +1100
+Subject: nfsd: don't take fi_lock in nfsd_break_deleg_cb()
+
+From: NeilBrown <neilb@suse.de>
+
+[ Upstream commit 5ea9a7c5fe4149f165f0e3b624fe08df02b6c301 ]
+
+A recent change to check_for_locks() changed it to take ->flc_lock while
+holding ->fi_lock.  This creates a lock inversion (reported by lockdep)
+because there is a case where ->fi_lock is taken while holding
+->flc_lock.
+
+->flc_lock is held across ->fl_lmops callbacks, and
+nfsd_break_deleg_cb() is one of those and does take ->fi_lock.  However
+it doesn't need to.
+
+Prior to v4.17-rc1~110^2~22 ("nfsd: create a separate lease for each
+delegation") nfsd_break_deleg_cb() would walk the ->fi_delegations list
+and so needed the lock.  Since then it doesn't walk the list and doesn't
+need the lock.
+
+Two actions are performed under the lock.  One is to call
+nfsd_break_one_deleg which calls nfsd4_run_cb().  These doesn't act on
+the nfs4_file at all, so don't need the lock.
+
+The other is to set ->fi_had_conflict which is in the nfs4_file.
+This field is only ever set here (except when initialised to false)
+so there is no possible problem will multiple threads racing when
+setting it.
+
+The field is tested twice in nfs4_set_delegation().  The first test does
+not hold a lock and is documented as an opportunistic optimisation, so
+it doesn't impose any need to hold ->fi_lock while setting
+->fi_had_conflict.
+
+The second test in nfs4_set_delegation() *is* make under ->fi_lock, so
+removing the locking when ->fi_had_conflict is set could make a change.
+The change could only be interesting if ->fi_had_conflict tested as
+false even though nfsd_break_one_deleg() ran before ->fi_lock was
+unlocked.  i.e. while hash_delegation_locked() was running.
+As hash_delegation_lock() doesn't interact in any way with nfs4_run_cb()
+there can be no importance to this interaction.
+
+So this patch removes the locking from nfsd_break_one_deleg() and moves
+the final test on ->fi_had_conflict out of the locked region to make it
+clear that locking isn't important to the test.  It is still tested
+*after* vfs_setlease() has succeeded.  This might be significant and as
+vfs_setlease() takes ->flc_lock, and nfsd_break_one_deleg() is called
+under ->flc_lock this "after" is a true ordering provided by a spinlock.
+
+Fixes: edcf9725150e ("nfsd: fix RELEASE_LOCKOWNER")
+Signed-off-by: NeilBrown <neilb@suse.de>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/nfs4state.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 07ea358036293..316cb64e15e97 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -4703,10 +4703,8 @@ nfsd_break_deleg_cb(struct file_lock *fl)
+        */
+       fl->fl_break_time = 0;
+-      spin_lock(&fp->fi_lock);
+       fp->fi_had_conflict = true;
+       nfsd_break_one_deleg(dp);
+-      spin_unlock(&fp->fi_lock);
+       return ret;
+ }
+@@ -5195,12 +5193,13 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
+       if (status)
+               goto out_unlock;
++      status = -EAGAIN;
++      if (fp->fi_had_conflict)
++              goto out_unlock;
++
+       spin_lock(&state_lock);
+       spin_lock(&fp->fi_lock);
+-      if (fp->fi_had_conflict)
+-              status = -EAGAIN;
+-      else
+-              status = hash_delegation_locked(dp, fp);
++      status = hash_delegation_locked(dp, fp);
+       spin_unlock(&fp->fi_lock);
+       spin_unlock(&state_lock);
+-- 
+2.43.0
+
diff --git a/queue-5.15/nfsd-fix-release_lockowner.patch b/queue-5.15/nfsd-fix-release_lockowner.patch
new file mode 100644 (file)
index 0000000..90a1edf
--- /dev/null
@@ -0,0 +1,149 @@
+From ac6bed871ef46355b3aff79f487d6b7da525587d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jan 2024 14:58:16 +1100
+Subject: nfsd: fix RELEASE_LOCKOWNER
+
+From: NeilBrown <neilb@suse.de>
+
+[ Upstream commit edcf9725150e42beeca42d085149f4c88fa97afd ]
+
+The test on so_count in nfsd4_release_lockowner() is nonsense and
+harmful.  Revert to using check_for_locks(), changing that to not sleep.
+
+First: harmful.
+As is documented in the kdoc comment for nfsd4_release_lockowner(), the
+test on so_count can transiently return a false positive resulting in a
+return of NFS4ERR_LOCKS_HELD when in fact no locks are held.  This is
+clearly a protocol violation and with the Linux NFS client it can cause
+incorrect behaviour.
+
+If RELEASE_LOCKOWNER is sent while some other thread is still
+processing a LOCK request which failed because, at the time that request
+was received, the given owner held a conflicting lock, then the nfsd
+thread processing that LOCK request can hold a reference (conflock) to
+the lock owner that causes nfsd4_release_lockowner() to return an
+incorrect error.
+
+The Linux NFS client ignores that NFS4ERR_LOCKS_HELD error because it
+never sends NFS4_RELEASE_LOCKOWNER without first releasing any locks, so
+it knows that the error is impossible.  It assumes the lock owner was in
+fact released so it feels free to use the same lock owner identifier in
+some later locking request.
+
+When it does reuse a lock owner identifier for which a previous RELEASE
+failed, it will naturally use a lock_seqid of zero.  However the server,
+which didn't release the lock owner, will expect a larger lock_seqid and
+so will respond with NFS4ERR_BAD_SEQID.
+
+So clearly it is harmful to allow a false positive, which testing
+so_count allows.
+
+The test is nonsense because ... well... it doesn't mean anything.
+
+so_count is the sum of three different counts.
+1/ the set of states listed on so_stateids
+2/ the set of active vfs locks owned by any of those states
+3/ various transient counts such as for conflicting locks.
+
+When it is tested against '2' it is clear that one of these is the
+transient reference obtained by find_lockowner_str_locked().  It is not
+clear what the other one is expected to be.
+
+In practice, the count is often 2 because there is precisely one state
+on so_stateids.  If there were more, this would fail.
+
+In my testing I see two circumstances when RELEASE_LOCKOWNER is called.
+In one case, CLOSE is called before RELEASE_LOCKOWNER.  That results in
+all the lock states being removed, and so the lockowner being discarded
+(it is removed when there are no more references which usually happens
+when the lock state is discarded).  When nfsd4_release_lockowner() finds
+that the lock owner doesn't exist, it returns success.
+
+The other case shows an so_count of '2' and precisely one state listed
+in so_stateid.  It appears that the Linux client uses a separate lock
+owner for each file resulting in one lock state per lock owner, so this
+test on '2' is safe.  For another client it might not be safe.
+
+So this patch changes check_for_locks() to use the (newish)
+find_any_file_locked() so that it doesn't take a reference on the
+nfs4_file and so never calls nfsd_file_put(), and so never sleeps.  With
+this check is it safe to restore the use of check_for_locks() rather
+than testing so_count against the mysterious '2'.
+
+Fixes: ce3c4ad7f4ce ("NFSD: Fix possible sleep during nfsd4_release_lockowner()")
+Signed-off-by: NeilBrown <neilb@suse.de>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Cc: stable@vger.kernel.org # v6.2+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/nfs4state.c | 26 +++++++++++++++-----------
+ 1 file changed, 15 insertions(+), 11 deletions(-)
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index f8533299db1c5..07ea358036293 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -7257,14 +7257,16 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
+ {
+       struct file_lock *fl;
+       int status = false;
+-      struct nfsd_file *nf = find_any_file(fp);
++      struct nfsd_file *nf;
+       struct inode *inode;
+       struct file_lock_context *flctx;
++      spin_lock(&fp->fi_lock);
++      nf = find_any_file_locked(fp);
+       if (!nf) {
+               /* Any valid lock stateid should have some sort of access */
+               WARN_ON_ONCE(1);
+-              return status;
++              goto out;
+       }
+       inode = locks_inode(nf->nf_file);
+@@ -7280,7 +7282,8 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
+               }
+               spin_unlock(&flctx->flc_lock);
+       }
+-      nfsd_file_put(nf);
++out:
++      spin_unlock(&fp->fi_lock);
+       return status;
+ }
+@@ -7290,10 +7293,8 @@ check_for_locks(struct nfs4_file *fp, struct nfs4_lockowner *lowner)
+  * @cstate: NFSv4 COMPOUND state
+  * @u: RELEASE_LOCKOWNER arguments
+  *
+- * The lockowner's so_count is bumped when a lock record is added
+- * or when copying a conflicting lock. The latter case is brief,
+- * but can lead to fleeting false positives when looking for
+- * locks-in-use.
++ * Check if theree are any locks still held and if not - free the lockowner
++ * and any lock state that is owned.
+  *
+  * Return values:
+  *   %nfs_ok: lockowner released or not found
+@@ -7329,10 +7330,13 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
+               spin_unlock(&clp->cl_lock);
+               return nfs_ok;
+       }
+-      if (atomic_read(&lo->lo_owner.so_count) != 2) {
+-              spin_unlock(&clp->cl_lock);
+-              nfs4_put_stateowner(&lo->lo_owner);
+-              return nfserr_locks_held;
++
++      list_for_each_entry(stp, &lo->lo_owner.so_stateids, st_perstateowner) {
++              if (check_for_locks(stp->st_stid.sc_file, lo)) {
++                      spin_unlock(&clp->cl_lock);
++                      nfs4_put_stateowner(&lo->lo_owner);
++                      return nfserr_locks_held;
++              }
+       }
+       unhash_lockowner_locked(lo);
+       while (!list_empty(&lo->lo_owner.so_stateids)) {
+-- 
+2.43.0
+
diff --git a/queue-5.15/nfsd-modernize-nfsd4_release_lockowner.patch b/queue-5.15/nfsd-modernize-nfsd4_release_lockowner.patch
new file mode 100644 (file)
index 0000000..c43e384
--- /dev/null
@@ -0,0 +1,86 @@
+From 6b245dd6dcc09fc719185689ac9fcc0bb9cd7cf0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 22 May 2022 12:07:18 -0400
+Subject: NFSD: Modernize nfsd4_release_lockowner()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit bd8fdb6e545f950f4654a9a10d7e819ad48146e5 ]
+
+Refactor: Use existing helpers that other lock operations use. This
+change removes several automatic variables, so re-organize the
+variable declarations for readability.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Stable-dep-of: edcf9725150e ("nfsd: fix RELEASE_LOCKOWNER")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/nfs4state.c | 36 +++++++++++-------------------------
+ 1 file changed, 11 insertions(+), 25 deletions(-)
+
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 9b660491f3931..798063b9b96fd 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -7290,16 +7290,13 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
+                       union nfsd4_op_u *u)
+ {
+       struct nfsd4_release_lockowner *rlockowner = &u->release_lockowner;
++      struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
+       clientid_t *clid = &rlockowner->rl_clientid;
+-      struct nfs4_stateowner *sop;
+-      struct nfs4_lockowner *lo = NULL;
+       struct nfs4_ol_stateid *stp;
+-      struct xdr_netobj *owner = &rlockowner->rl_owner;
+-      unsigned int hashval = ownerstr_hashval(owner);
+-      __be32 status;
+-      struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
++      struct nfs4_lockowner *lo;
+       struct nfs4_client *clp;
+-      LIST_HEAD (reaplist);
++      LIST_HEAD(reaplist);
++      __be32 status;
+       dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
+               clid->cl_boot, clid->cl_id);
+@@ -7307,30 +7304,19 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
+       status = set_client(clid, cstate, nn);
+       if (status)
+               return status;
+-
+       clp = cstate->clp;
+-      /* Find the matching lock stateowner */
+-      spin_lock(&clp->cl_lock);
+-      list_for_each_entry(sop, &clp->cl_ownerstr_hashtbl[hashval],
+-                          so_strhash) {
+-              if (sop->so_is_open_owner || !same_owner_str(sop, owner))
+-                      continue;
+-
+-              if (atomic_read(&sop->so_count) != 1) {
+-                      spin_unlock(&clp->cl_lock);
+-                      return nfserr_locks_held;
+-              }
+-
+-              lo = lockowner(sop);
+-              nfs4_get_stateowner(sop);
+-              break;
+-      }
++      spin_lock(&clp->cl_lock);
++      lo = find_lockowner_str_locked(clp, &rlockowner->rl_owner);
+       if (!lo) {
+               spin_unlock(&clp->cl_lock);
+               return status;
+       }
+-
++      if (atomic_read(&lo->lo_owner.so_count) != 2) {
++              spin_unlock(&clp->cl_lock);
++              nfs4_put_stateowner(&lo->lo_owner);
++              return nfserr_locks_held;
++      }
+       unhash_lockowner_locked(lo);
+       while (!list_empty(&lo->lo_owner.so_stateids)) {
+               stp = list_first_entry(&lo->lo_owner.so_stateids,
+-- 
+2.43.0
+
diff --git a/queue-5.15/proc-use-task_is_running-for-wchan-in-proc-pid-stat.patch b/queue-5.15/proc-use-task_is_running-for-wchan-in-proc-pid-stat.patch
new file mode 100644 (file)
index 0000000..343a268
--- /dev/null
@@ -0,0 +1,52 @@
+From 728a74ca4341c638246c15669c4dd072f8d188ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Sep 2021 15:02:15 -0700
+Subject: proc: Use task_is_running() for wchan in /proc/$pid/stat
+
+From: Kees Cook <keescook@chromium.org>
+
+[ Upstream commit 4e046156792c26bef8a4e30be711777fc8578257 ]
+
+The implementations of get_wchan() can be expensive. The only information
+imparted here is whether or not a process is currently blocked in the
+scheduler (and even this doesn't need to be exact). Avoid doing the
+heavy lifting of stack walking and just report that information by using
+task_is_running().
+
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lkml.kernel.org/r/20211008111626.211281780@infradead.org
+Stable-dep-of: 60f92acb60a9 ("fs/proc: do_task_stat: move thread_group_cputime_adjusted() outside of lock_task_sighand()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/proc/array.c | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+diff --git a/fs/proc/array.c b/fs/proc/array.c
+index 49be8c8ef555e..77cf4187adecc 100644
+--- a/fs/proc/array.c
++++ b/fs/proc/array.c
+@@ -541,7 +541,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
+       }
+       if (permitted && (!whole || num_threads < 2))
+-              wchan = get_wchan(task);
++              wchan = !task_is_running(task);
+       if (!whole) {
+               min_flt = task->min_flt;
+               maj_flt = task->maj_flt;
+@@ -606,10 +606,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
+        *
+        * This works with older implementations of procps as well.
+        */
+-      if (wchan)
+-              seq_puts(m, " 1");
+-      else
+-              seq_puts(m, " 0");
++      seq_put_decimal_ull(m, " ", wchan);
+       seq_put_decimal_ull(m, " ", 0);
+       seq_put_decimal_ull(m, " ", 0);
+-- 
+2.43.0
+
diff --git a/queue-5.15/regmap-add-bulk-read-write-callbacks-into-regmap_con.patch b/queue-5.15/regmap-add-bulk-read-write-callbacks-into-regmap_con.patch
new file mode 100644 (file)
index 0000000..391484c
--- /dev/null
@@ -0,0 +1,300 @@
+From 429c0a2bac690d3da2e39334ea535171395f78c4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 30 Apr 2022 04:51:44 +0200
+Subject: regmap: Add bulk read/write callbacks into regmap_config
+
+From: Marek Vasut <marex@denx.de>
+
+[ Upstream commit d77e745613680c54708470402e2b623dcd769681 ]
+
+Currently the regmap_config structure only allows the user to implement
+single element register read/write using .reg_read/.reg_write callbacks.
+The regmap_bus already implements bulk counterparts of both, and is being
+misused as a workaround for the missing bulk read/write callbacks in
+regmap_config by a couple of drivers. To stop this misuse, add the bulk
+read/write callbacks to regmap_config and call them from the regmap core
+code.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Cc: Jagan Teki <jagan@amarulasolutions.com>
+Cc: Mark Brown <broonie@kernel.org>
+Cc: Maxime Ripard <maxime@cerno.tech>
+Cc: Robert Foss <robert.foss@linaro.org>
+Cc: Sam Ravnborg <sam@ravnborg.org>
+Cc: Thomas Zimmermann <tzimmermann@suse.de>
+To: dri-devel@lists.freedesktop.org
+Link: https://lore.kernel.org/r/20220430025145.640305-1-marex@denx.de
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 3f42b142ea11 ("serial: max310x: fix IO data corruption in batched operations")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/regmap/internal.h |  4 ++
+ drivers/base/regmap/regmap.c   | 76 ++++++++++++++++++----------------
+ include/linux/regmap.h         | 12 ++++++
+ 3 files changed, 56 insertions(+), 36 deletions(-)
+
+diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h
+index b1905916f7af8..93e028445dade 100644
+--- a/drivers/base/regmap/internal.h
++++ b/drivers/base/regmap/internal.h
+@@ -108,6 +108,10 @@ struct regmap {
+       int (*reg_write)(void *context, unsigned int reg, unsigned int val);
+       int (*reg_update_bits)(void *context, unsigned int reg,
+                              unsigned int mask, unsigned int val);
++      /* Bulk read/write */
++      int (*read)(void *context, const void *reg_buf, size_t reg_size,
++                  void *val_buf, size_t val_size);
++      int (*write)(void *context, const void *data, size_t count);
+       bool defer_caching;
+diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
+index ab924127e0aef..6adb345866610 100644
+--- a/drivers/base/regmap/regmap.c
++++ b/drivers/base/regmap/regmap.c
+@@ -835,12 +835,15 @@ struct regmap *__regmap_init(struct device *dev,
+               map->reg_stride_order = ilog2(map->reg_stride);
+       else
+               map->reg_stride_order = -1;
+-      map->use_single_read = config->use_single_read || !bus || !bus->read;
+-      map->use_single_write = config->use_single_write || !bus || !bus->write;
+-      map->can_multi_write = config->can_multi_write && bus && bus->write;
++      map->use_single_read = config->use_single_read || !(config->read || (bus && bus->read));
++      map->use_single_write = config->use_single_write || !(config->write || (bus && bus->write));
++      map->can_multi_write = config->can_multi_write && (config->write || (bus && bus->write));
+       if (bus) {
+               map->max_raw_read = bus->max_raw_read;
+               map->max_raw_write = bus->max_raw_write;
++      } else if (config->max_raw_read && config->max_raw_write) {
++              map->max_raw_read = config->max_raw_read;
++              map->max_raw_write = config->max_raw_write;
+       }
+       map->dev = dev;
+       map->bus = bus;
+@@ -874,7 +877,16 @@ struct regmap *__regmap_init(struct device *dev,
+               map->read_flag_mask = bus->read_flag_mask;
+       }
+-      if (!bus) {
++      if (config && config->read && config->write) {
++              map->reg_read  = _regmap_bus_read;
++
++              /* Bulk read/write */
++              map->read = config->read;
++              map->write = config->write;
++
++              reg_endian = REGMAP_ENDIAN_NATIVE;
++              val_endian = REGMAP_ENDIAN_NATIVE;
++      } else if (!bus) {
+               map->reg_read  = config->reg_read;
+               map->reg_write = config->reg_write;
+               map->reg_update_bits = config->reg_update_bits;
+@@ -891,10 +903,13 @@ struct regmap *__regmap_init(struct device *dev,
+       } else {
+               map->reg_read  = _regmap_bus_read;
+               map->reg_update_bits = bus->reg_update_bits;
+-      }
++              /* Bulk read/write */
++              map->read = bus->read;
++              map->write = bus->write;
+-      reg_endian = regmap_get_reg_endian(bus, config);
+-      val_endian = regmap_get_val_endian(dev, bus, config);
++              reg_endian = regmap_get_reg_endian(bus, config);
++              val_endian = regmap_get_val_endian(dev, bus, config);
++      }
+       switch (config->reg_bits + map->reg_shift) {
+       case 2:
+@@ -1668,8 +1683,6 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
+       size_t len;
+       int i;
+-      WARN_ON(!map->bus);
+-
+       /* Check for unwritable or noinc registers in range
+        * before we start
+        */
+@@ -1751,7 +1764,7 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
+               val = work_val;
+       }
+-      if (map->async && map->bus->async_write) {
++      if (map->async && map->bus && map->bus->async_write) {
+               struct regmap_async *async;
+               trace_regmap_async_write_start(map, reg, val_len);
+@@ -1819,10 +1832,10 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
+        * write.
+        */
+       if (val == work_val)
+-              ret = map->bus->write(map->bus_context, map->work_buf,
+-                                    map->format.reg_bytes +
+-                                    map->format.pad_bytes +
+-                                    val_len);
++              ret = map->write(map->bus_context, map->work_buf,
++                               map->format.reg_bytes +
++                               map->format.pad_bytes +
++                               val_len);
+       else if (map->bus->gather_write)
+               ret = map->bus->gather_write(map->bus_context, map->work_buf,
+                                            map->format.reg_bytes +
+@@ -1841,7 +1854,7 @@ static int _regmap_raw_write_impl(struct regmap *map, unsigned int reg,
+               memcpy(buf, map->work_buf, map->format.reg_bytes);
+               memcpy(buf + map->format.reg_bytes + map->format.pad_bytes,
+                      val, val_len);
+-              ret = map->bus->write(map->bus_context, buf, len);
++              ret = map->write(map->bus_context, buf, len);
+               kfree(buf);
+       } else if (ret != 0 && !map->cache_bypass && map->format.parse_val) {
+@@ -1898,7 +1911,7 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,
+       struct regmap_range_node *range;
+       struct regmap *map = context;
+-      WARN_ON(!map->bus || !map->format.format_write);
++      WARN_ON(!map->format.format_write);
+       range = _regmap_range_lookup(map, reg);
+       if (range) {
+@@ -1911,8 +1924,7 @@ static int _regmap_bus_formatted_write(void *context, unsigned int reg,
+       trace_regmap_hw_write_start(map, reg, 1);
+-      ret = map->bus->write(map->bus_context, map->work_buf,
+-                            map->format.buf_size);
++      ret = map->write(map->bus_context, map->work_buf, map->format.buf_size);
+       trace_regmap_hw_write_done(map, reg, 1);
+@@ -1932,7 +1944,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg,
+ {
+       struct regmap *map = context;
+-      WARN_ON(!map->bus || !map->format.format_val);
++      WARN_ON(!map->format.format_val);
+       map->format.format_val(map->work_buf + map->format.reg_bytes
+                              + map->format.pad_bytes, val, 0);
+@@ -1946,7 +1958,7 @@ static int _regmap_bus_raw_write(void *context, unsigned int reg,
+ static inline void *_regmap_map_get_context(struct regmap *map)
+ {
+-      return (map->bus) ? map : map->bus_context;
++      return (map->bus || (!map->bus && map->read)) ? map : map->bus_context;
+ }
+ int _regmap_write(struct regmap *map, unsigned int reg,
+@@ -2356,7 +2368,7 @@ static int _regmap_raw_multi_reg_write(struct regmap *map,
+       u8 = buf;
+       *u8 |= map->write_flag_mask;
+-      ret = map->bus->write(map->bus_context, buf, len);
++      ret = map->write(map->bus_context, buf, len);
+       kfree(buf);
+@@ -2662,9 +2674,7 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
+       struct regmap_range_node *range;
+       int ret;
+-      WARN_ON(!map->bus);
+-
+-      if (!map->bus || !map->bus->read)
++      if (!map->read)
+               return -EINVAL;
+       range = _regmap_range_lookup(map, reg);
+@@ -2680,9 +2690,9 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
+                                     map->read_flag_mask);
+       trace_regmap_hw_read_start(map, reg, val_len / map->format.val_bytes);
+-      ret = map->bus->read(map->bus_context, map->work_buf,
+-                           map->format.reg_bytes + map->format.pad_bytes,
+-                           val, val_len);
++      ret = map->read(map->bus_context, map->work_buf,
++                      map->format.reg_bytes + map->format.pad_bytes,
++                      val, val_len);
+       trace_regmap_hw_read_done(map, reg, val_len / map->format.val_bytes);
+@@ -2793,8 +2803,6 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
+       unsigned int v;
+       int ret, i;
+-      if (!map->bus)
+-              return -EINVAL;
+       if (val_len % map->format.val_bytes)
+               return -EINVAL;
+       if (!IS_ALIGNED(reg, map->reg_stride))
+@@ -2809,7 +2817,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
+               size_t chunk_count, chunk_bytes;
+               size_t chunk_regs = val_count;
+-              if (!map->bus->read) {
++              if (!map->read) {
+                       ret = -ENOTSUPP;
+                       goto out;
+               }
+@@ -2869,7 +2877,7 @@ EXPORT_SYMBOL_GPL(regmap_raw_read);
+  * @val: Pointer to data buffer
+  * @val_len: Length of output buffer in bytes.
+  *
+- * The regmap API usually assumes that bulk bus read operations will read a
++ * The regmap API usually assumes that bulk read operations will read a
+  * range of registers. Some devices have certain registers for which a read
+  * operation read will read from an internal FIFO.
+  *
+@@ -2887,10 +2895,6 @@ int regmap_noinc_read(struct regmap *map, unsigned int reg,
+       size_t read_len;
+       int ret;
+-      if (!map->bus)
+-              return -EINVAL;
+-      if (!map->bus->read)
+-              return -ENOTSUPP;
+       if (val_len % map->format.val_bytes)
+               return -EINVAL;
+       if (!IS_ALIGNED(reg, map->reg_stride))
+@@ -3004,7 +3008,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
+       if (val_count == 0)
+               return -EINVAL;
+-      if (map->bus && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
++      if (map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
+               ret = regmap_raw_read(map, reg, val, val_bytes * val_count);
+               if (ret != 0)
+                       return ret;
+diff --git a/include/linux/regmap.h b/include/linux/regmap.h
+index 22652e5fbc380..f74e543fadc07 100644
+--- a/include/linux/regmap.h
++++ b/include/linux/regmap.h
+@@ -295,6 +295,12 @@ typedef void (*regmap_unlock)(void *);
+  *                 if the function require special handling with lock and reg
+  *                 handling and the operation cannot be represented as a simple
+  *                 update_bits operation on a bus such as SPI, I2C, etc.
++ * @read: Optional callback that if filled will be used to perform all the
++ *        bulk reads from the registers. Data is returned in the buffer used
++ *        to transmit data.
++ * @write: Same as above for writing.
++ * @max_raw_read: Max raw read size that can be used on the device.
++ * @max_raw_write: Max raw write size that can be used on the device.
+  * @fast_io:    Register IO is fast. Use a spinlock instead of a mutex
+  *              to perform locking. This field is ignored if custom lock/unlock
+  *              functions are used (see fields lock/unlock of struct regmap_config).
+@@ -379,6 +385,12 @@ struct regmap_config {
+       int (*reg_write)(void *context, unsigned int reg, unsigned int val);
+       int (*reg_update_bits)(void *context, unsigned int reg,
+                              unsigned int mask, unsigned int val);
++      /* Bulk read/write */
++      int (*read)(void *context, const void *reg_buf, size_t reg_size,
++                  void *val_buf, size_t val_size);
++      int (*write)(void *context, const void *data, size_t count);
++      size_t max_raw_read;
++      size_t max_raw_write;
+       bool fast_io;
+-- 
+2.43.0
+
diff --git a/queue-5.15/regmap-allow-to-define-reg_update_bits-for-no-bus-co.patch b/queue-5.15/regmap-allow-to-define-reg_update_bits-for-no-bus-co.patch
new file mode 100644 (file)
index 0000000..6027f34
--- /dev/null
@@ -0,0 +1,65 @@
+From ee7b09e81c31d12393c05bbca1614c40c55ffba7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Nov 2021 16:00:40 +0100
+Subject: regmap: allow to define reg_update_bits for no bus configuration
+
+From: Ansuel Smith <ansuelsmth@gmail.com>
+
+[ Upstream commit 02d6fdecb9c38de19065f6bed8d5214556fd061d ]
+
+Some device requires a special handling for reg_update_bits and can't use
+the normal regmap read write logic. An example is when locking is
+handled by the device and rmw operations requires to do atomic operations.
+Allow to declare a dedicated function in regmap_config for
+reg_update_bits in no bus configuration.
+
+Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
+Link: https://lore.kernel.org/r/20211104150040.1260-1-ansuelsmth@gmail.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 3f42b142ea11 ("serial: max310x: fix IO data corruption in batched operations")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/base/regmap/regmap.c | 1 +
+ include/linux/regmap.h       | 7 +++++++
+ 2 files changed, 8 insertions(+)
+
+diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
+index 7621b54975b57..ab924127e0aef 100644
+--- a/drivers/base/regmap/regmap.c
++++ b/drivers/base/regmap/regmap.c
+@@ -877,6 +877,7 @@ struct regmap *__regmap_init(struct device *dev,
+       if (!bus) {
+               map->reg_read  = config->reg_read;
+               map->reg_write = config->reg_write;
++              map->reg_update_bits = config->reg_update_bits;
+               map->defer_caching = false;
+               goto skip_format_initialization;
+diff --git a/include/linux/regmap.h b/include/linux/regmap.h
+index e3c9a25a853a8..22652e5fbc380 100644
+--- a/include/linux/regmap.h
++++ b/include/linux/regmap.h
+@@ -290,6 +290,11 @@ typedef void (*regmap_unlock)(void *);
+  *              read operation on a bus such as SPI, I2C, etc. Most of the
+  *              devices do not need this.
+  * @reg_write:          Same as above for writing.
++ * @reg_update_bits: Optional callback that if filled will be used to perform
++ *                 all the update_bits(rmw) operation. Should only be provided
++ *                 if the function require special handling with lock and reg
++ *                 handling and the operation cannot be represented as a simple
++ *                 update_bits operation on a bus such as SPI, I2C, etc.
+  * @fast_io:    Register IO is fast. Use a spinlock instead of a mutex
+  *              to perform locking. This field is ignored if custom lock/unlock
+  *              functions are used (see fields lock/unlock of struct regmap_config).
+@@ -372,6 +377,8 @@ struct regmap_config {
+       int (*reg_read)(void *context, unsigned int reg, unsigned int *val);
+       int (*reg_write)(void *context, unsigned int reg, unsigned int val);
++      int (*reg_update_bits)(void *context, unsigned int reg,
++                             unsigned int mask, unsigned int val);
+       bool fast_io;
+-- 
+2.43.0
+
diff --git a/queue-5.15/selftests-mm-fix-map_hugetlb-failure-on-64k-page-siz.patch b/queue-5.15/selftests-mm-fix-map_hugetlb-failure-on-64k-page-siz.patch
new file mode 100644 (file)
index 0000000..a3f0059
--- /dev/null
@@ -0,0 +1,61 @@
+From 64813105ad49bec8e82a522e5a390997590d4827 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jan 2024 06:14:29 -0700
+Subject: selftests: mm: fix map_hugetlb failure on 64K page size systems
+
+From: Nico Pache <npache@redhat.com>
+
+[ Upstream commit 91b80cc5b39f00399e8e2d17527cad2c7fa535e2 ]
+
+On systems with 64k page size and 512M huge page sizes, the allocation and
+test succeeds but errors out at the munmap.  As the comment states, munmap
+will failure if its not HUGEPAGE aligned.  This is due to the length of
+the mapping being 1/2 the size of the hugepage causing the munmap to not
+be hugepage aligned.  Fix this by making the mapping length the full
+hugepage if the hugepage is larger than the length of the mapping.
+
+Link: https://lkml.kernel.org/r/20240119131429.172448-1-npache@redhat.com
+Signed-off-by: Nico Pache <npache@redhat.com>
+Cc: Donet Tom <donettom@linux.vnet.ibm.com>
+Cc: Shuah Khan <shuah@kernel.org>
+Cc: Christophe Leroy <christophe.leroy@c-s.fr>
+Cc: Michael Ellerman <mpe@ellerman.id.au>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/vm/map_hugetlb.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/tools/testing/selftests/vm/map_hugetlb.c b/tools/testing/selftests/vm/map_hugetlb.c
+index 312889edb84ab..c65c55b7a789f 100644
+--- a/tools/testing/selftests/vm/map_hugetlb.c
++++ b/tools/testing/selftests/vm/map_hugetlb.c
+@@ -15,6 +15,7 @@
+ #include <unistd.h>
+ #include <sys/mman.h>
+ #include <fcntl.h>
++#include "vm_util.h"
+ #define LENGTH (256UL*1024*1024)
+ #define PROTECTION (PROT_READ | PROT_WRITE)
+@@ -70,10 +71,16 @@ int main(int argc, char **argv)
+ {
+       void *addr;
+       int ret;
++      size_t hugepage_size;
+       size_t length = LENGTH;
+       int flags = FLAGS;
+       int shift = 0;
++      hugepage_size = default_huge_page_size();
++      /* munmap with fail if the length is not page aligned */
++      if (hugepage_size > length)
++              length = hugepage_size;
++
+       if (argc > 1)
+               length = atol(argv[1]) << 20;
+       if (argc > 2) {
+-- 
+2.43.0
+
diff --git a/queue-5.15/selftests-mm-switch-to-bash-from-sh.patch b/queue-5.15/selftests-mm-switch-to-bash-from-sh.patch
new file mode 100644 (file)
index 0000000..4f2d25d
--- /dev/null
@@ -0,0 +1,58 @@
+From 40233cc35dca5c9cb8b4d25ac9c76750dc7ea9d0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Jan 2024 14:04:54 +0500
+Subject: selftests/mm: switch to bash from sh
+
+From: Muhammad Usama Anjum <usama.anjum@collabora.com>
+
+[ Upstream commit bc29036e1da1cf66e5f8312649aeec2d51ea3d86 ]
+
+Running charge_reserved_hugetlb.sh generates errors if sh is set to
+dash:
+
+./charge_reserved_hugetlb.sh: 9: [[: not found
+./charge_reserved_hugetlb.sh: 19: [[: not found
+./charge_reserved_hugetlb.sh: 27: [[: not found
+./charge_reserved_hugetlb.sh: 37: [[: not found
+./charge_reserved_hugetlb.sh: 45: Syntax error: "(" unexpected
+
+Switch to using /bin/bash instead of /bin/sh.  Make the switch for
+write_hugetlb_memory.sh as well which is called from
+charge_reserved_hugetlb.sh.
+
+Link: https://lkml.kernel.org/r/20240116090455.3407378-1-usama.anjum@collabora.com
+Signed-off-by: Muhammad Usama Anjum <usama.anjum@collabora.com>
+Cc: Muhammad Usama Anjum <usama.anjum@collabora.com>
+Cc: Shuah Khan <shuah@kernel.org>
+Cc: David Laight <David.Laight@ACULAB.COM>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/vm/charge_reserved_hugetlb.sh | 2 +-
+ tools/testing/selftests/vm/write_hugetlb_memory.sh    | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
+index 0899019a7fcb4..e14bdd4455f2d 100644
+--- a/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
++++ b/tools/testing/selftests/vm/charge_reserved_hugetlb.sh
+@@ -1,4 +1,4 @@
+-#!/bin/sh
++#!/bin/bash
+ # SPDX-License-Identifier: GPL-2.0
+ # Kselftest framework requirement - SKIP code is 4.
+diff --git a/tools/testing/selftests/vm/write_hugetlb_memory.sh b/tools/testing/selftests/vm/write_hugetlb_memory.sh
+index 70a02301f4c27..3d2d2eb9d6fff 100644
+--- a/tools/testing/selftests/vm/write_hugetlb_memory.sh
++++ b/tools/testing/selftests/vm/write_hugetlb_memory.sh
+@@ -1,4 +1,4 @@
+-#!/bin/sh
++#!/bin/bash
+ # SPDX-License-Identifier: GPL-2.0
+ set -e
+-- 
+2.43.0
+
diff --git a/queue-5.15/selftests-mptcp-decrease-bw-in-simult-flows.patch b/queue-5.15/selftests-mptcp-decrease-bw-in-simult-flows.patch
new file mode 100644 (file)
index 0000000..7a5c1d0
--- /dev/null
@@ -0,0 +1,53 @@
+From 4932a188b9e196bd115dffbb465723c9f1effcb4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jan 2024 22:49:51 +0100
+Subject: selftests: mptcp: decrease BW in simult flows
+
+From: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+
+[ Upstream commit 5e2f3c65af47e527ccac54060cf909e3306652ff ]
+
+When running the simult_flow selftest in slow environments -- e.g. QEmu
+without KVM support --, the results can be unstable. This selftest
+checks if the aggregated bandwidth is (almost) fully used as expected.
+
+To help improving the stability while still keeping the same validation
+in place, the BW and the delay are reduced to lower the pressure on the
+CPU.
+
+Fixes: 1a418cb8e888 ("mptcp: simult flow self-tests")
+Fixes: 219d04992b68 ("mptcp: push pending frames when subflow has free space")
+Cc: stable@vger.kernel.org
+Suggested-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Link: https://lore.kernel.org/r/20240131-upstream-net-20240131-mptcp-ci-issues-v1-6-4c1c11e571ff@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/mptcp/simult_flows.sh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh
+index d41fcd9f4ba76..af5f4ae48f7ea 100755
+--- a/tools/testing/selftests/net/mptcp/simult_flows.sh
++++ b/tools/testing/selftests/net/mptcp/simult_flows.sh
+@@ -291,12 +291,12 @@ done
+ setup
+ run_test 10 10 0 0 "balanced bwidth"
+-run_test 10 10 1 50 "balanced bwidth with unbalanced delay"
++run_test 10 10 1 25 "balanced bwidth with unbalanced delay"
+ # we still need some additional infrastructure to pass the following test-cases
+-run_test 30 10 0 0 "unbalanced bwidth"
+-run_test 30 10 1 50 "unbalanced bwidth with unbalanced delay"
+-run_test 30 10 50 1 "unbalanced bwidth with opposed, unbalanced delay"
++run_test 10 3 0 0 "unbalanced bwidth"
++run_test 10 3 1 25 "unbalanced bwidth with unbalanced delay"
++run_test 10 3 25 1 "unbalanced bwidth with opposed, unbalanced delay"
+ mptcp_lib_result_print_all_tap
+ exit $ret
+-- 
+2.43.0
+
diff --git a/queue-5.15/selftests-mptcp-simult-flows-fix-some-subtest-names.patch b/queue-5.15/selftests-mptcp-simult-flows-fix-some-subtest-names.patch
new file mode 100644 (file)
index 0000000..f528c95
--- /dev/null
@@ -0,0 +1,42 @@
+From 19c8b4907ef37163bc6be6633152beb25cb163c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Feb 2024 19:25:37 +0100
+Subject: selftests: mptcp: simult flows: fix some subtest names
+
+From: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+
+[ Upstream commit 4d8e0dde0403b5a86aa83e243f020711a9c3e31f ]
+
+The selftest was correctly recording all the results, but the 'reverse
+direction' part was missing in the name when needed.
+
+It is important to have a unique (sub)test name in TAP, because some CI
+environments drop tests with duplicated name.
+
+Fixes: 675d99338e7a ("selftests: mptcp: simult flows: format subtests results in TAP")
+Cc: stable@vger.kernel.org
+Reviewed-by: Geliang Tang <geliang@kernel.org>
+Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/mptcp/simult_flows.sh | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh
+index af5f4ae48f7ea..aef9ce433b374 100755
+--- a/tools/testing/selftests/net/mptcp/simult_flows.sh
++++ b/tools/testing/selftests/net/mptcp/simult_flows.sh
+@@ -257,7 +257,8 @@ run_test()
+               [ $bail -eq 0 ] || exit $ret
+       fi
+-      printf "%-60s" "$msg - reverse direction"
++      msg+=" - reverse direction"
++      printf "%-60s" "${msg}"
+       do_transfer $large $small $time
+       lret=$?
+       mptcp_lib_result_code "${lret}" "${msg}"
+-- 
+2.43.0
+
diff --git a/queue-5.15/selftests-mptcp-simult-flows-format-subtests-results.patch b/queue-5.15/selftests-mptcp-simult-flows-format-subtests-results.patch
new file mode 100644 (file)
index 0000000..e05fcd3
--- /dev/null
@@ -0,0 +1,68 @@
+From f007bec4e943548bed9e5612ce2f65241ab5ef4e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Jul 2023 15:21:31 +0200
+Subject: selftests: mptcp: simult flows: format subtests results in TAP
+
+From: Matthieu Baerts <matthieu.baerts@tessares.net>
+
+[ Upstream commit 675d99338e7a6cd925d61d7dbf8c26612f7f08a9 ]
+
+The current selftests infrastructure formats the results in TAP 13. This
+version doesn't support subtests and only the end result of each
+selftest is taken into account. It means that a single issue in a
+subtest of a selftest containing multiple subtests forces the whole
+selftest to be marked as failed. It also means that subtests results are
+not tracked by CIs executing selftests.
+
+MPTCP selftests run hundreds of various subtests. It is then important
+to track each of them and not one result per selftest.
+
+It is particularly interesting to do that when validating stable kernels
+with the last version of the test suite: tests might fail because a
+feature is not supported but the test didn't skip that part. In this
+case, if subtests are not tracked, the whole selftest will be marked as
+failed making the other subtests useless because their results are
+ignored.
+
+This patch formats subtests results in TAP in simult_flows.sh selftest.
+
+Link: https://github.com/multipath-tcp/mptcp_net-next/issues/368
+Acked-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 5e2f3c65af47 ("selftests: mptcp: decrease BW in simult flows")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/mptcp/simult_flows.sh | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/tools/testing/selftests/net/mptcp/simult_flows.sh b/tools/testing/selftests/net/mptcp/simult_flows.sh
+index 752cef1688040..d41fcd9f4ba76 100755
+--- a/tools/testing/selftests/net/mptcp/simult_flows.sh
++++ b/tools/testing/selftests/net/mptcp/simult_flows.sh
+@@ -251,6 +251,7 @@ run_test()
+       printf "%-60s" "$msg"
+       do_transfer $small $large $time
+       lret=$?
++      mptcp_lib_result_code "${lret}" "${msg}"
+       if [ $lret -ne 0 ]; then
+               ret=$lret
+               [ $bail -eq 0 ] || exit $ret
+@@ -259,6 +260,7 @@ run_test()
+       printf "%-60s" "$msg - reverse direction"
+       do_transfer $large $small $time
+       lret=$?
++      mptcp_lib_result_code "${lret}" "${msg}"
+       if [ $lret -ne 0 ]; then
+               ret=$lret
+               [ $bail -eq 0 ] || exit $ret
+@@ -295,4 +297,6 @@ run_test 10 10 1 50 "balanced bwidth with unbalanced delay"
+ run_test 30 10 0 0 "unbalanced bwidth"
+ run_test 30 10 1 50 "unbalanced bwidth with unbalanced delay"
+ run_test 30 10 50 1 "unbalanced bwidth with opposed, unbalanced delay"
++
++mptcp_lib_result_print_all_tap
+ exit $ret
+-- 
+2.43.0
+
diff --git a/queue-5.15/serial-max310x-fix-io-data-corruption-in-batched-ope.patch b/queue-5.15/serial-max310x-fix-io-data-corruption-in-batched-ope.patch
new file mode 100644 (file)
index 0000000..c83b78d
--- /dev/null
@@ -0,0 +1,88 @@
+From e300bac8e8b8e957e832da6456e15c16b5667396 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 Apr 2023 22:14:23 +0200
+Subject: serial: max310x: fix IO data corruption in batched operations
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jan Kundrát <jan.kundrat@cesnet.cz>
+
+[ Upstream commit 3f42b142ea1171967e40e10e4b0241c0d6d28d41 ]
+
+After upgrading from 5.16 to 6.1, our board with a MAX14830 started
+producing lots of garbage data over UART. Bisection pointed out commit
+285e76fc049c as the culprit. That patch tried to replace hand-written
+code which I added in 2b4bac48c1084 ("serial: max310x: Use batched reads
+when reasonably safe") with the generic regmap infrastructure for
+batched operations.
+
+Unfortunately, the `regmap_raw_read` and `regmap_raw_write` which were
+used are actually functions which perform IO over *multiple* registers.
+That's not what is needed for accessing these Tx/Rx FIFOs; the
+appropriate functions are the `_noinc_` versions, not the `_raw_` ones.
+
+Fix this regression by using `regmap_noinc_read()` and
+`regmap_noinc_write()` along with the necessary `regmap_config` setup;
+with this patch in place, our board communicates happily again. Since
+our board uses SPI for talking to this chip, the I2C part is completely
+untested.
+
+Fixes: 285e76fc049c ("serial: max310x: use regmap methods for SPI batch operations")
+Cc: stable@vger.kernel.org
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: Jan Kundrát <jan.kundrat@cesnet.cz>
+Link: https://lore.kernel.org/r/79db8e82aadb0e174bc82b9996423c3503c8fb37.1680732084.git.jan.kundrat@cesnet.cz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/max310x.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
+index 4299211183a74..c122e7e90fc89 100644
+--- a/drivers/tty/serial/max310x.c
++++ b/drivers/tty/serial/max310x.c
+@@ -511,6 +511,11 @@ static bool max310x_reg_precious(struct device *dev, unsigned int reg)
+       return false;
+ }
++static bool max310x_reg_noinc(struct device *dev, unsigned int reg)
++{
++      return reg == MAX310X_RHR_REG;
++}
++
+ static int max310x_set_baud(struct uart_port *port, int baud)
+ {
+       unsigned int mode = 0, div = 0, frac = 0, c = 0, F = 0;
+@@ -645,14 +650,14 @@ static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int
+ {
+       struct max310x_one *one = to_max310x_port(port);
+-      regmap_raw_write(one->regmap, MAX310X_THR_REG, txbuf, len);
++      regmap_noinc_write(one->regmap, MAX310X_THR_REG, txbuf, len);
+ }
+ static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int len)
+ {
+       struct max310x_one *one = to_max310x_port(port);
+-      regmap_raw_read(one->regmap, MAX310X_RHR_REG, rxbuf, len);
++      regmap_noinc_read(one->regmap, MAX310X_RHR_REG, rxbuf, len);
+ }
+ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
+@@ -1481,6 +1486,10 @@ static struct regmap_config regcfg = {
+       .writeable_reg = max310x_reg_writeable,
+       .volatile_reg = max310x_reg_volatile,
+       .precious_reg = max310x_reg_precious,
++      .writeable_noinc_reg = max310x_reg_noinc,
++      .readable_noinc_reg = max310x_reg_noinc,
++      .max_raw_read = MAX310X_FIFO_SIZE,
++      .max_raw_write = MAX310X_FIFO_SIZE,
+ };
+ #ifdef CONFIG_SPI_MASTER
+-- 
+2.43.0
+
diff --git a/queue-5.15/serial-max310x-make-accessing-revision-id-interface-.patch b/queue-5.15/serial-max310x-make-accessing-revision-id-interface-.patch
new file mode 100644 (file)
index 0000000..a8366f8
--- /dev/null
@@ -0,0 +1,157 @@
+From 78877e904e73cf50a5427d1860bf84375e2418c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 5 Jun 2022 17:46:58 +0300
+Subject: serial: max310x: make accessing revision id interface-agnostic
+
+From: Cosmin Tanislav <cosmin.tanislav@analog.com>
+
+[ Upstream commit b3883ab5e95713e479f774ea68be275413e8e5b2 ]
+
+SPI can only use 5 address bits, since one bit is reserved for
+specifying R/W and 2 bits are used to specify the UART port.
+To access registers that have addresses past 0x1F, an extended
+register space can be enabled by writing to the GlobalCommand
+register (address 0x1F).
+
+I2C uses 8 address bits. The R/W bit is placed in the slave
+address, and so is the UART port. Because of this, registers
+that have addresses higher than 0x1F can be accessed normally.
+
+To access the RevID register, on SPI, 0xCE must be written to
+the 0x1F address to enable the extended register space, after
+which the RevID register is accessible at address 0x5. 0xCD
+must be written to the 0x1F address to disable the extended
+register space.
+
+On I2C, the RevID register is accessible at address 0x25.
+
+Create an interface config struct, and add a method for
+toggling the extended register space and a member for the RevId
+register address. Implement these for SPI.
+
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: Cosmin Tanislav <cosmin.tanislav@analog.com>
+Link: https://lore.kernel.org/r/20220605144659.4169853-4-demonsingur@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 3f42b142ea11 ("serial: max310x: fix IO data corruption in batched operations")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/max310x.c | 40 +++++++++++++++++++++++++++---------
+ 1 file changed, 30 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
+index 41251fdf7c845..4299211183a74 100644
+--- a/drivers/tty/serial/max310x.c
++++ b/drivers/tty/serial/max310x.c
+@@ -72,7 +72,7 @@
+ #define MAX310X_GLOBALCMD_REG         MAX310X_REG_1F /* Global Command (WO) */
+ /* Extended registers */
+-#define MAX310X_REVID_EXTREG          MAX310X_REG_05 /* Revision ID */
++#define MAX310X_SPI_REVID_EXTREG      MAX310X_REG_05 /* Revision ID */
+ /* IRQ register bits */
+ #define MAX310X_IRQ_LSR_BIT           (1 << 0) /* LSR interrupt */
+@@ -253,6 +253,12 @@
+ #define MAX14830_BRGCFG_CLKDIS_BIT    (1 << 6) /* Clock Disable */
+ #define MAX14830_REV_ID                       (0xb0)
++struct max310x_if_cfg {
++      int (*extended_reg_enable)(struct device *dev, bool enable);
++
++      unsigned int rev_id_reg;
++};
++
+ struct max310x_devtype {
+       char    name[9];
+       int     nr;
+@@ -275,6 +281,7 @@ struct max310x_one {
+ struct max310x_port {
+       const struct max310x_devtype *devtype;
++      const struct max310x_if_cfg *if_cfg;
+       struct regmap           *regmap;
+       struct clk              *clk;
+ #ifdef CONFIG_GPIOLIB
+@@ -364,13 +371,12 @@ static int max3109_detect(struct device *dev)
+       unsigned int val = 0;
+       int ret;
+-      ret = regmap_write(s->regmap, MAX310X_GLOBALCMD_REG,
+-                         MAX310X_EXTREG_ENBL);
++      ret = s->if_cfg->extended_reg_enable(dev, true);
+       if (ret)
+               return ret;
+-      regmap_read(s->regmap, MAX310X_REVID_EXTREG, &val);
+-      regmap_write(s->regmap, MAX310X_GLOBALCMD_REG, MAX310X_EXTREG_DSBL);
++      regmap_read(s->regmap, s->if_cfg->rev_id_reg, &val);
++      s->if_cfg->extended_reg_enable(dev, false);
+       if (((val & MAX310x_REV_MASK) != MAX3109_REV_ID)) {
+               dev_err(dev,
+                       "%s ID 0x%02x does not match\n", s->devtype->name, val);
+@@ -395,13 +401,12 @@ static int max14830_detect(struct device *dev)
+       unsigned int val = 0;
+       int ret;
+-      ret = regmap_write(s->regmap, MAX310X_GLOBALCMD_REG,
+-                         MAX310X_EXTREG_ENBL);
++      ret = s->if_cfg->extended_reg_enable(dev, true);
+       if (ret)
+               return ret;
+       
+-      regmap_read(s->regmap, MAX310X_REVID_EXTREG, &val);
+-      regmap_write(s->regmap, MAX310X_GLOBALCMD_REG, MAX310X_EXTREG_DSBL);
++      regmap_read(s->regmap, s->if_cfg->rev_id_reg, &val);
++      s->if_cfg->extended_reg_enable(dev, false);
+       if (((val & MAX310x_REV_MASK) != MAX14830_REV_ID)) {
+               dev_err(dev,
+                       "%s ID 0x%02x does not match\n", s->devtype->name, val);
+@@ -1250,6 +1255,7 @@ static int max310x_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+ #endif
+ static int max310x_probe(struct device *dev, const struct max310x_devtype *devtype,
++                       const struct max310x_if_cfg *if_cfg,
+                        struct regmap *regmaps[], int irq)
+ {
+       int i, ret, fmin, fmax, freq;
+@@ -1308,6 +1314,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
+       s->regmap = regmaps[0];
+       s->devtype = devtype;
++      s->if_cfg = if_cfg;
+       dev_set_drvdata(dev, s);
+       /* Check device to ensure we are talking to what we expect */
+@@ -1477,6 +1484,19 @@ static struct regmap_config regcfg = {
+ };
+ #ifdef CONFIG_SPI_MASTER
++static int max310x_spi_extended_reg_enable(struct device *dev, bool enable)
++{
++      struct max310x_port *s = dev_get_drvdata(dev);
++
++      return regmap_write(s->regmap, MAX310X_GLOBALCMD_REG,
++                          enable ? MAX310X_EXTREG_ENBL : MAX310X_EXTREG_DSBL);
++}
++
++static const struct max310x_if_cfg __maybe_unused max310x_spi_if_cfg = {
++      .extended_reg_enable = max310x_spi_extended_reg_enable,
++      .rev_id_reg = MAX310X_SPI_REVID_EXTREG,
++};
++
+ static int max310x_spi_probe(struct spi_device *spi)
+ {
+       const struct max310x_devtype *devtype;
+@@ -1503,7 +1523,7 @@ static int max310x_spi_probe(struct spi_device *spi)
+               regmaps[i] = devm_regmap_init_spi(spi, &regcfg);
+       }
+-      return max310x_probe(&spi->dev, devtype, regmaps, spi->irq);
++      return max310x_probe(&spi->dev, devtype, &max310x_spi_if_cfg, regmaps, spi->irq);
+ }
+ static int max310x_spi_remove(struct spi_device *spi)
+-- 
+2.43.0
+
diff --git a/queue-5.15/serial-max310x-prevent-infinite-while-loop-in-port-s.patch b/queue-5.15/serial-max310x-prevent-infinite-while-loop-in-port-s.patch
new file mode 100644 (file)
index 0000000..d99f3c8
--- /dev/null
@@ -0,0 +1,76 @@
+From 18117fc8643b81228a8f8e31fa6277405ba2a304 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Jan 2024 16:30:01 -0500
+Subject: serial: max310x: prevent infinite while() loop in port startup
+
+From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+
+[ Upstream commit b35f8dbbce818b02c730dc85133dc7754266e084 ]
+
+If there is a problem after resetting a port, the do/while() loop that
+checks the default value of DIVLSB register may run forever and spam the
+I2C bus.
+
+Add a delay before each read of DIVLSB, and a maximum number of tries to
+prevent that situation from happening.
+
+Also fail probe if port reset is unsuccessful.
+
+Fixes: 10d8b34a4217 ("serial: max310x: Driver rework")
+Cc: stable@vger.kernel.org
+Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+Link: https://lore.kernel.org/r/20240116213001.3691629-5-hugo@hugovil.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/max310x.c | 20 ++++++++++++++++++--
+ 1 file changed, 18 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
+index d61e8a6bc99dd..41251fdf7c845 100644
+--- a/drivers/tty/serial/max310x.c
++++ b/drivers/tty/serial/max310x.c
+@@ -235,6 +235,10 @@
+ #define MAX310x_REV_MASK              (0xf8)
+ #define MAX310X_WRITE_BIT             0x80
++/* Port startup definitions */
++#define MAX310X_PORT_STARTUP_WAIT_RETRIES     20 /* Number of retries */
++#define MAX310X_PORT_STARTUP_WAIT_DELAY_MS    10 /* Delay between retries */
++
+ /* Crystal-related definitions */
+ #define MAX310X_XTAL_WAIT_RETRIES     20 /* Number of retries */
+ #define MAX310X_XTAL_WAIT_DELAY_MS    10 /* Delay between retries */
+@@ -1312,6 +1316,9 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
+               goto out_clk;
+       for (i = 0; i < devtype->nr; i++) {
++              bool started = false;
++              unsigned int try = 0, val = 0;
++
+               /* Reset port */
+               regmap_write(regmaps[i], MAX310X_MODE2_REG,
+                            MAX310X_MODE2_RST_BIT);
+@@ -1320,8 +1327,17 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
+               /* Wait for port startup */
+               do {
+-                      regmap_read(regmaps[i], MAX310X_BRGDIVLSB_REG, &ret);
+-              } while (ret != 0x01);
++                      msleep(MAX310X_PORT_STARTUP_WAIT_DELAY_MS);
++                      regmap_read(regmaps[i], MAX310X_BRGDIVLSB_REG, &val);
++
++                      if (val == 0x01)
++                              started = true;
++              } while (!started && (++try < MAX310X_PORT_STARTUP_WAIT_RETRIES));
++
++              if (!started) {
++                      ret = dev_err_probe(dev, -EAGAIN, "port reset failed\n");
++                      goto out_uart;
++              }
+               regmap_write(regmaps[i], MAX310X_MODE1_REG, devtype->mode1);
+       }
+-- 
+2.43.0
+
diff --git a/queue-5.15/serial-max310x-use-a-separate-regmap-for-each-port.patch b/queue-5.15/serial-max310x-use-a-separate-regmap-for-each-port.patch
new file mode 100644 (file)
index 0000000..4fbe828
--- /dev/null
@@ -0,0 +1,243 @@
+From 588bdbe11d4a276b793694c820d2b280a60e303d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 5 Jun 2022 17:46:57 +0300
+Subject: serial: max310x: use a separate regmap for each port
+
+From: Cosmin Tanislav <cosmin.tanislav@analog.com>
+
+[ Upstream commit 6ef281daf020592c219fa91780abc381c6c20db5 ]
+
+The driver currently does manual register manipulation in
+multiple places to talk to a specific UART port.
+
+In order to talk to a specific UART port over SPI, the bits U1
+and U0 of the register address can be set, as explained in the
+Command byte configuration section of the datasheet.
+
+Make this more elegant by creating regmaps for each UART port
+and setting the read_flag_mask and write_flag_mask
+accordingly.
+
+All communcations regarding global registers are done on UART
+port 0, so replace the global regmap entirely with the port 0
+regmap.
+
+Also, remove the 0x1f masks from reg_writeable(), reg_volatile()
+and reg_precious() methods, since setting the U1 and U0 bits of
+the register address happens inside the regmap core now.
+
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: Cosmin Tanislav <cosmin.tanislav@analog.com>
+Link: https://lore.kernel.org/r/20220605144659.4169853-3-demonsingur@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: b35f8dbbce81 ("serial: max310x: prevent infinite while() loop in port startup")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/max310x.c | 68 +++++++++++++++++++-----------------
+ 1 file changed, 36 insertions(+), 32 deletions(-)
+
+diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
+index c9032e300a586..d61e8a6bc99dd 100644
+--- a/drivers/tty/serial/max310x.c
++++ b/drivers/tty/serial/max310x.c
+@@ -262,6 +262,7 @@ struct max310x_one {
+       struct work_struct      tx_work;
+       struct work_struct      md_work;
+       struct work_struct      rs_work;
++      struct regmap           *regmap;
+       u8 rx_buf[MAX310X_FIFO_SIZE];
+ };
+@@ -291,26 +292,26 @@ static DECLARE_BITMAP(max310x_lines, MAX310X_UART_NRMAX);
+ static u8 max310x_port_read(struct uart_port *port, u8 reg)
+ {
+-      struct max310x_port *s = dev_get_drvdata(port->dev);
++      struct max310x_one *one = to_max310x_port(port);
+       unsigned int val = 0;
+-      regmap_read(s->regmap, port->iobase + reg, &val);
++      regmap_read(one->regmap, reg, &val);
+       return val;
+ }
+ static void max310x_port_write(struct uart_port *port, u8 reg, u8 val)
+ {
+-      struct max310x_port *s = dev_get_drvdata(port->dev);
++      struct max310x_one *one = to_max310x_port(port);
+-      regmap_write(s->regmap, port->iobase + reg, val);
++      regmap_write(one->regmap, reg, val);
+ }
+ static void max310x_port_update(struct uart_port *port, u8 reg, u8 mask, u8 val)
+ {
+-      struct max310x_port *s = dev_get_drvdata(port->dev);
++      struct max310x_one *one = to_max310x_port(port);
+-      regmap_update_bits(s->regmap, port->iobase + reg, mask, val);
++      regmap_update_bits(one->regmap, reg, mask, val);
+ }
+ static int max3107_detect(struct device *dev)
+@@ -449,7 +450,7 @@ static const struct max310x_devtype max14830_devtype = {
+ static bool max310x_reg_writeable(struct device *dev, unsigned int reg)
+ {
+-      switch (reg & 0x1f) {
++      switch (reg) {
+       case MAX310X_IRQSTS_REG:
+       case MAX310X_LSR_IRQSTS_REG:
+       case MAX310X_SPCHR_IRQSTS_REG:
+@@ -466,7 +467,7 @@ static bool max310x_reg_writeable(struct device *dev, unsigned int reg)
+ static bool max310x_reg_volatile(struct device *dev, unsigned int reg)
+ {
+-      switch (reg & 0x1f) {
++      switch (reg) {
+       case MAX310X_RHR_REG:
+       case MAX310X_IRQSTS_REG:
+       case MAX310X_LSR_IRQSTS_REG:
+@@ -488,7 +489,7 @@ static bool max310x_reg_volatile(struct device *dev, unsigned int reg)
+ static bool max310x_reg_precious(struct device *dev, unsigned int reg)
+ {
+-      switch (reg & 0x1f) {
++      switch (reg) {
+       case MAX310X_RHR_REG:
+       case MAX310X_IRQSTS_REG:
+       case MAX310X_SPCHR_IRQSTS_REG:
+@@ -633,18 +634,16 @@ static s32 max310x_set_ref_clk(struct device *dev, struct max310x_port *s,
+ static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int len)
+ {
+-      struct max310x_port *s = dev_get_drvdata(port->dev);
+-      u8 reg = port->iobase + MAX310X_THR_REG;
++      struct max310x_one *one = to_max310x_port(port);
+-      regmap_raw_write(s->regmap, reg, txbuf, len);
++      regmap_raw_write(one->regmap, MAX310X_THR_REG, txbuf, len);
+ }
+ static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int len)
+ {
+-      struct max310x_port *s = dev_get_drvdata(port->dev);
+-      u8 reg = port->iobase + MAX310X_RHR_REG;
++      struct max310x_one *one = to_max310x_port(port);
+-      regmap_raw_read(s->regmap, reg, rxbuf, len);
++      regmap_raw_read(one->regmap, MAX310X_RHR_REG, rxbuf, len);
+ }
+ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
+@@ -1247,15 +1246,16 @@ static int max310x_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
+ #endif
+ static int max310x_probe(struct device *dev, const struct max310x_devtype *devtype,
+-                       struct regmap *regmap, int irq)
++                       struct regmap *regmaps[], int irq)
+ {
+       int i, ret, fmin, fmax, freq;
+       struct max310x_port *s;
+       s32 uartclk = 0;
+       bool xtal;
+-      if (IS_ERR(regmap))
+-              return PTR_ERR(regmap);
++      for (i = 0; i < devtype->nr; i++)
++              if (IS_ERR(regmaps[i]))
++                      return PTR_ERR(regmaps[i]);
+       /* Alloc port structure */
+       s = devm_kzalloc(dev, struct_size(s, p, devtype->nr), GFP_KERNEL);
+@@ -1302,7 +1302,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
+               goto out_clk;
+       }
+-      s->regmap = regmap;
++      s->regmap = regmaps[0];
+       s->devtype = devtype;
+       dev_set_drvdata(dev, s);
+@@ -1312,22 +1312,18 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
+               goto out_clk;
+       for (i = 0; i < devtype->nr; i++) {
+-              unsigned int offs = i << 5;
+-
+               /* Reset port */
+-              regmap_write(s->regmap, MAX310X_MODE2_REG + offs,
++              regmap_write(regmaps[i], MAX310X_MODE2_REG,
+                            MAX310X_MODE2_RST_BIT);
+               /* Clear port reset */
+-              regmap_write(s->regmap, MAX310X_MODE2_REG + offs, 0);
++              regmap_write(regmaps[i], MAX310X_MODE2_REG, 0);
+               /* Wait for port startup */
+               do {
+-                      regmap_read(s->regmap,
+-                                  MAX310X_BRGDIVLSB_REG + offs, &ret);
++                      regmap_read(regmaps[i], MAX310X_BRGDIVLSB_REG, &ret);
+               } while (ret != 0x01);
+-              regmap_write(s->regmap, MAX310X_MODE1_REG + offs,
+-                           devtype->mode1);
++              regmap_write(regmaps[i], MAX310X_MODE1_REG, devtype->mode1);
+       }
+       uartclk = max310x_set_ref_clk(dev, s, freq, xtal);
+@@ -1355,11 +1351,13 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
+               s->p[i].port.fifosize   = MAX310X_FIFO_SIZE;
+               s->p[i].port.flags      = UPF_FIXED_TYPE | UPF_LOW_LATENCY;
+               s->p[i].port.iotype     = UPIO_PORT;
+-              s->p[i].port.iobase     = i * 0x20;
++              s->p[i].port.iobase     = i;
+               s->p[i].port.membase    = (void __iomem *)~0;
+               s->p[i].port.uartclk    = uartclk;
+               s->p[i].port.rs485_config = max310x_rs485_config;
+               s->p[i].port.ops        = &max310x_ops;
++              s->p[i].regmap          = regmaps[i];
++
+               /* Disable all interrupts */
+               max310x_port_write(&s->p[i].port, MAX310X_IRQEN_REG, 0);
+               /* Clear IRQ status register */
+@@ -1456,6 +1454,7 @@ static struct regmap_config regcfg = {
+       .val_bits = 8,
+       .write_flag_mask = MAX310X_WRITE_BIT,
+       .cache_type = REGCACHE_RBTREE,
++      .max_register = MAX310X_REG_1F,
+       .writeable_reg = max310x_reg_writeable,
+       .volatile_reg = max310x_reg_volatile,
+       .precious_reg = max310x_reg_precious,
+@@ -1465,7 +1464,8 @@ static struct regmap_config regcfg = {
+ static int max310x_spi_probe(struct spi_device *spi)
+ {
+       const struct max310x_devtype *devtype;
+-      struct regmap *regmap;
++      struct regmap *regmaps[4];
++      unsigned int i;
+       int ret;
+       /* Setup SPI bus */
+@@ -1480,10 +1480,14 @@ static int max310x_spi_probe(struct spi_device *spi)
+       if (!devtype)
+               devtype = (struct max310x_devtype *)spi_get_device_id(spi)->driver_data;
+-      regcfg.max_register = devtype->nr * 0x20 - 1;
+-      regmap = devm_regmap_init_spi(spi, &regcfg);
++      for (i = 0; i < devtype->nr; i++) {
++              u8 port_mask = i * 0x20;
++              regcfg.read_flag_mask = port_mask;
++              regcfg.write_flag_mask = port_mask | MAX310X_WRITE_BIT;
++              regmaps[i] = devm_regmap_init_spi(spi, &regcfg);
++      }
+-      return max310x_probe(&spi->dev, devtype, regmap, spi->irq);
++      return max310x_probe(&spi->dev, devtype, regmaps, spi->irq);
+ }
+ static int max310x_spi_remove(struct spi_device *spi)
+-- 
+2.43.0
+
diff --git a/queue-5.15/serial-max310x-use-regmap-methods-for-spi-batch-oper.patch b/queue-5.15/serial-max310x-use-regmap-methods-for-spi-batch-oper.patch
new file mode 100644 (file)
index 0000000..d061782
--- /dev/null
@@ -0,0 +1,93 @@
+From 7e3713d23a7abeac205e4deef6996ae5493868b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 5 Jun 2022 17:46:56 +0300
+Subject: serial: max310x: use regmap methods for SPI batch operations
+
+From: Cosmin Tanislav <cosmin.tanislav@analog.com>
+
+[ Upstream commit 285e76fc049c4d32c772eea9460a7ef28a193802 ]
+
+The SPI batch read/write operations can be implemented as simple
+regmap raw read and write, which will also try to do a gather
+write just as it is done here.
+
+Use the regmap raw read and write methods.
+
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Signed-off-by: Cosmin Tanislav <cosmin.tanislav@analog.com>
+Link: https://lore.kernel.org/r/20220605144659.4169853-2-demonsingur@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: b35f8dbbce81 ("serial: max310x: prevent infinite while() loop in port startup")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/max310x.c | 36 ++++++++----------------------------
+ 1 file changed, 8 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c
+index 5dd73d1da1ecc..c9032e300a586 100644
+--- a/drivers/tty/serial/max310x.c
++++ b/drivers/tty/serial/max310x.c
+@@ -263,8 +263,6 @@ struct max310x_one {
+       struct work_struct      md_work;
+       struct work_struct      rs_work;
+-      u8 wr_header;
+-      u8 rd_header;
+       u8 rx_buf[MAX310X_FIFO_SIZE];
+ };
+ #define to_max310x_port(_port) \
+@@ -635,32 +633,18 @@ static s32 max310x_set_ref_clk(struct device *dev, struct max310x_port *s,
+ static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int len)
+ {
+-      struct max310x_one *one = to_max310x_port(port);
+-      struct spi_transfer xfer[] = {
+-              {
+-                      .tx_buf = &one->wr_header,
+-                      .len = sizeof(one->wr_header),
+-              }, {
+-                      .tx_buf = txbuf,
+-                      .len = len,
+-              }
+-      };
+-      spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer));
++      struct max310x_port *s = dev_get_drvdata(port->dev);
++      u8 reg = port->iobase + MAX310X_THR_REG;
++
++      regmap_raw_write(s->regmap, reg, txbuf, len);
+ }
+ static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int len)
+ {
+-      struct max310x_one *one = to_max310x_port(port);
+-      struct spi_transfer xfer[] = {
+-              {
+-                      .tx_buf = &one->rd_header,
+-                      .len = sizeof(one->rd_header),
+-              }, {
+-                      .rx_buf = rxbuf,
+-                      .len = len,
+-              }
+-      };
+-      spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer));
++      struct max310x_port *s = dev_get_drvdata(port->dev);
++      u8 reg = port->iobase + MAX310X_RHR_REG;
++
++      regmap_raw_read(s->regmap, reg, rxbuf, len);
+ }
+ static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
+@@ -1386,10 +1370,6 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
+               INIT_WORK(&s->p[i].md_work, max310x_md_proc);
+               /* Initialize queue for changing RS485 mode */
+               INIT_WORK(&s->p[i].rs_work, max310x_rs_proc);
+-              /* Initialize SPI-transfer buffers */
+-              s->p[i].wr_header = (s->p[i].port.iobase + MAX310X_THR_REG) |
+-                                  MAX310X_WRITE_BIT;
+-              s->p[i].rd_header = (s->p[i].port.iobase + MAX310X_RHR_REG);
+               /* Register port */
+               ret = uart_add_one_port(&max310x_uart, &s->p[i].port);
+-- 
+2.43.0
+
index 9f3a73e7333bbe7731e0e030a3aa46ec6efbc585..b61fb8827efc2efa38d9a24e52ac07a50bfe9f95 100644 (file)
@@ -26,3 +26,58 @@ netrom-fix-a-data-race-around-sysctl_netrom_transpor.patch-3139
 netrom-fix-a-data-race-around-sysctl_netrom_routing_.patch
 netrom-fix-a-data-race-around-sysctl_netrom_link_fai.patch
 netrom-fix-data-races-around-sysctl_net_busy_read.patch
+nfsd-modernize-nfsd4_release_lockowner.patch
+nfsd-add-documenting-comment-for-nfsd4_release_locko.patch
+nfsd-fix-release_lockowner.patch
+alsa-usb-audio-refcount-multiple-accesses-on-the-sin.patch
+alsa-usb-audio-clear-fixed-clock-rate-at-closing-ep.patch
+alsa-usb-audio-split-endpoint-setups-for-hw_params-a.patch
+alsa-usb-audio-properly-refcounting-clock-rate.patch
+alsa-usb-audio-apply-mutex-around-snd_usb_endpoint_s.patch
+alsa-usb-audio-correct-the-return-code-from-snd_usb_.patch
+alsa-usb-audio-avoid-superfluous-endpoint-setup.patch
+alsa-usb-audio-add-quirk-for-tascam-model-12.patch
+alsa-usb-audio-add-new-quirk-fixed_rate-for-jbl-quan.patch
+alsa-usb-audio-fix-microphone-sound-on-nexigo-webcam.patch
+alsa-usb-audio-add-quirk-for-rode-nt-usb.patch
+drm-amd-display-fix-uninitialized-variable-usage-in-.patch
+nfp-flower-add-goto_chain_index-for-ct-entry.patch
+nfp-flower-add-hardware-offload-check-for-post-ct-en.patch
+selftests-mm-switch-to-bash-from-sh.patch
+selftests-mm-fix-map_hugetlb-failure-on-64k-page-siz.patch
+um-fix-adding-no-pie-for-clang.patch
+modpost-include-.text.-in-text_sections.patch
+modpost-add-.ltext-and-.ltext.-to-text_sections.patch
+xhci-process-isoc-td-properly-when-there-was-a-trans.patch
+xhci-handle-isoc-babble-and-buffer-overrun-events-pr.patch
+serial-max310x-use-regmap-methods-for-spi-batch-oper.patch
+serial-max310x-use-a-separate-regmap-for-each-port.patch
+serial-max310x-prevent-infinite-while-loop-in-port-s.patch
+drm-amd-pm-do-not-expose-the-api-used-internally-onl.patch
+drm-amdgpu-reset-ih-overflow_clear-bit.patch
+selftests-mptcp-simult-flows-format-subtests-results.patch
+selftests-mptcp-decrease-bw-in-simult-flows.patch
+hv_netvsc-use-netif_is_bond_master-instead-of-open-c.patch
+hv_netvsc-register-vf-in-netvsc_probe-if-net_device_.patch
+drm-amd-display-re-arrange-fpu-code-structure-for-dc.patch
+drm-amd-display-move-calcs-folder-into-dml.patch
+drm-amd-display-remove-dml-makefile-duplicate-lines.patch
+drm-amd-display-increase-frame-larger-than-for-all-d.patch
+getrusage-add-the-signal_struct-sig-local-variable.patch
+getrusage-move-thread_group_cputime_adjusted-outside.patch
+getrusage-use-__for_each_thread.patch
+getrusage-use-sig-stats_lock-rather-than-lock_task_s.patch
+proc-use-task_is_running-for-wchan-in-proc-pid-stat.patch
+fs-proc-do_task_stat-move-thread_group_cputime_adjus.patch
+exit-fix-typo-in-comment-s-sub-theads-sub-threads.patch
+exit-wait_task_zombie-kill-the-no-longer-necessary-s.patch
+alsa-usb-audio-fix-wrong-kfree-issue-in-snd_usb_endp.patch
+alsa-usb-audio-always-initialize-fixed_rate-in-snd_u.patch
+selftests-mptcp-simult-flows-fix-some-subtest-names.patch
+alsa-usb-audio-add-fixed_rate-quirk-for-jbl-quantum6.patch
+alsa-usb-audio-sort-quirk-table-entries.patch
+regmap-allow-to-define-reg_update_bits-for-no-bus-co.patch
+regmap-add-bulk-read-write-callbacks-into-regmap_con.patch
+serial-max310x-make-accessing-revision-id-interface-.patch
+serial-max310x-fix-io-data-corruption-in-batched-ope.patch
+nfsd-don-t-take-fi_lock-in-nfsd_break_deleg_cb.patch
diff --git a/queue-5.15/um-fix-adding-no-pie-for-clang.patch b/queue-5.15/um-fix-adding-no-pie-for-clang.patch
new file mode 100644 (file)
index 0000000..ea92616
--- /dev/null
@@ -0,0 +1,68 @@
+From 0332f68bfb32f980bd2385d853d957c2f9e41460 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Jan 2024 15:59:54 -0700
+Subject: um: Fix adding '-no-pie' for clang
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+[ Upstream commit 846cfbeed09b45d985079a9173cf390cc053715b ]
+
+The kernel builds with -fno-PIE, so commit 883354afbc10 ("um: link
+vmlinux with -no-pie") added the compiler linker flag '-no-pie' via
+cc-option because '-no-pie' was only supported in GCC 6.1.0 and newer.
+
+While this works for GCC, this does not work for clang because cc-option
+uses '-c', which stops the pipeline right before linking, so '-no-pie'
+is unconsumed and clang warns, causing cc-option to fail just as it
+would if the option was entirely unsupported:
+
+  $ clang -Werror -no-pie -c -o /dev/null -x c /dev/null
+  clang-16: error: argument unused during compilation: '-no-pie' [-Werror,-Wunused-command-line-argument]
+
+A recent version of clang exposes this because it generates a relocation
+under '-mcmodel=large' that is not supported in PIE mode:
+
+  /usr/sbin/ld: init/main.o: relocation R_X86_64_32 against symbol `saved_command_line' can not be used when making a PIE object; recompile with -fPIE
+  /usr/sbin/ld: failed to set dynamic section sizes: bad value
+  clang: error: linker command failed with exit code 1 (use -v to see invocation)
+
+Remove the cc-option check altogether. It is wasteful to invoke the
+compiler to check for '-no-pie' because only one supported compiler
+version does not support it, GCC 5.x (as it is supported with the
+minimum version of clang and GCC 6.1.0+). Use a combination of the
+gcc-min-version macro and CONFIG_CC_IS_CLANG to unconditionally add
+'-no-pie' with CONFIG_LD_SCRIPT_DYN=y, so that it is enabled with all
+compilers that support this. Furthermore, using gcc-min-version can help
+turn this back into
+
+  LINK-$(CONFIG_LD_SCRIPT_DYN) += -no-pie
+
+when the minimum version of GCC is bumped past 6.1.0.
+
+Cc: stable@vger.kernel.org
+Closes: https://github.com/ClangBuiltLinux/linux/issues/1982
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/um/Makefile | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/arch/um/Makefile b/arch/um/Makefile
+index 3dbd0e3b660ea..778c50f273992 100644
+--- a/arch/um/Makefile
++++ b/arch/um/Makefile
+@@ -118,7 +118,9 @@ archprepare:
+       $(Q)$(MAKE) $(build)=$(HOST_DIR)/um include/generated/user_constants.h
+ LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static
+-LINK-$(CONFIG_LD_SCRIPT_DYN) += $(call cc-option, -no-pie)
++ifdef CONFIG_LD_SCRIPT_DYN
++LINK-$(call gcc-min-version, 60100)$(CONFIG_CC_IS_CLANG) += -no-pie
++endif
+ LINK-$(CONFIG_LD_SCRIPT_DYN_RPATH) += -Wl,-rpath,/lib
+ CFLAGS_NO_HARDENING := $(call cc-option, -fno-PIC,) $(call cc-option, -fno-pic,) \
+-- 
+2.43.0
+
diff --git a/queue-5.15/xhci-handle-isoc-babble-and-buffer-overrun-events-pr.patch b/queue-5.15/xhci-handle-isoc-babble-and-buffer-overrun-events-pr.patch
new file mode 100644 (file)
index 0000000..3c5db6d
--- /dev/null
@@ -0,0 +1,57 @@
+From f458703f4997eb9faaf82dbc3e12d1c30ce4972b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Jan 2024 17:27:37 +0200
+Subject: xhci: handle isoc Babble and Buffer Overrun events properly
+
+From: Michal Pecio <michal.pecio@gmail.com>
+
+[ Upstream commit 7c4650ded49e5b88929ecbbb631efb8b0838e811 ]
+
+xHCI 4.9 explicitly forbids assuming that the xHC has released its
+ownership of a multi-TRB TD when it reports an error on one of the
+early TRBs. Yet the driver makes such assumption and releases the TD,
+allowing the remaining TRBs to be freed or overwritten by new TDs.
+
+The xHC should also report completion of the final TRB due to its IOC
+flag being set by us, regardless of prior errors. This event cannot
+be recognized if the TD has already been freed earlier, resulting in
+"Transfer event TRB DMA ptr not part of current TD" error message.
+
+Fix this by reusing the logic for processing isoc Transaction Errors.
+This also handles hosts which fail to report the final completion.
+
+Fix transfer length reporting on Babble errors. They may be caused by
+device malfunction, no guarantee that the buffer has been filled.
+
+Signed-off-by: Michal Pecio <michal.pecio@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20240125152737.2983959-5-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-ring.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 7e88b65b694ad..31d355613933f 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -2446,9 +2446,13 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+       case COMP_BANDWIDTH_OVERRUN_ERROR:
+               frame->status = -ECOMM;
+               break;
+-      case COMP_ISOCH_BUFFER_OVERRUN:
+       case COMP_BABBLE_DETECTED_ERROR:
++              sum_trbs_for_length = true;
++              fallthrough;
++      case COMP_ISOCH_BUFFER_OVERRUN:
+               frame->status = -EOVERFLOW;
++              if (ep_trb != td->last_trb)
++                      td->error_mid_td = true;
+               break;
+       case COMP_INCOMPATIBLE_DEVICE_ERROR:
+       case COMP_STALL_ERROR:
+-- 
+2.43.0
+
diff --git a/queue-5.15/xhci-process-isoc-td-properly-when-there-was-a-trans.patch b/queue-5.15/xhci-process-isoc-td-properly-when-there-was-a-trans.patch
new file mode 100644 (file)
index 0000000..488c483
--- /dev/null
@@ -0,0 +1,186 @@
+From 841aebf8e465f96009879c7c54fdf43c61625875 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Jan 2024 17:27:36 +0200
+Subject: xhci: process isoc TD properly when there was a transaction error mid
+ TD.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+[ Upstream commit 5372c65e1311a16351ef03dd096ff576e6477674 ]
+
+The last TRB of a isoc TD might not trigger an event if there was
+an error event for a TRB mid TD. This is seen on a NEC Corporation
+uPD720200 USB 3.0 Host
+
+After an error mid a multi-TRB TD the xHC should according to xhci 4.9.1
+generate events for passed TRBs with IOC flag set if it proceeds to the
+next TD. This event is either a copy of the original error, or a
+"success" transfer event.
+
+If that event is missing then the driver and xHC host get out of sync as
+the driver is still expecting a transfer event for that first TD, while
+xHC host is already sending events for the next TD in the list.
+This leads to
+"Transfer event TRB DMA ptr not part of current TD" messages.
+
+As a solution we tag the isoc TDs that get error events mid TD.
+If an event doesn't match the first TD, then check if the tag is
+set, and event points to the next TD.
+In that case give back the fist TD and process the next TD normally
+
+Make sure TD status and transferred length stay valid in both cases
+with and without final TD completion event.
+
+Reported-by: Michał Pecio <michal.pecio@gmail.com>
+Closes: https://lore.kernel.org/linux-usb/20240112235205.1259f60c@foxbook/
+Tested-by: Michał Pecio <michal.pecio@gmail.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20240125152737.2983959-4-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/xhci-ring.c | 74 +++++++++++++++++++++++++++++-------
+ drivers/usb/host/xhci.h      |  1 +
+ 2 files changed, 61 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index aa12da0796d2d..7e88b65b694ad 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -2428,6 +2428,9 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+       /* handle completion code */
+       switch (trb_comp_code) {
+       case COMP_SUCCESS:
++              /* Don't overwrite status if TD had an error, see xHCI 4.9.1 */
++              if (td->error_mid_td)
++                      break;
+               if (remaining) {
+                       frame->status = short_framestatus;
+                       if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
+@@ -2453,8 +2456,9 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+               break;
+       case COMP_USB_TRANSACTION_ERROR:
+               frame->status = -EPROTO;
++              sum_trbs_for_length = true;
+               if (ep_trb != td->last_trb)
+-                      return 0;
++                      td->error_mid_td = true;
+               break;
+       case COMP_STOPPED:
+               sum_trbs_for_length = true;
+@@ -2474,6 +2478,9 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+               break;
+       }
++      if (td->urb_length_set)
++              goto finish_td;
++
+       if (sum_trbs_for_length)
+               frame->actual_length = sum_trb_lengths(xhci, ep->ring, ep_trb) +
+                       ep_trb_len - remaining;
+@@ -2482,6 +2489,14 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+       td->urb->actual_length += frame->actual_length;
++finish_td:
++      /* Don't give back TD yet if we encountered an error mid TD */
++      if (td->error_mid_td && ep_trb != td->last_trb) {
++              xhci_dbg(xhci, "Error mid isoc TD, wait for final completion event\n");
++              td->urb_length_set = true;
++              return 0;
++      }
++
+       return finish_td(xhci, ep, ep_ring, td, trb_comp_code);
+ }
+@@ -2866,17 +2881,51 @@ static int handle_tx_event(struct xhci_hcd *xhci,
+               }
+               if (!ep_seg) {
+-                      if (!ep->skip ||
+-                          !usb_endpoint_xfer_isoc(&td->urb->ep->desc)) {
+-                              /* Some host controllers give a spurious
+-                               * successful event after a short transfer.
+-                               * Ignore it.
+-                               */
+-                              if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) &&
+-                                              ep_ring->last_td_was_short) {
+-                                      ep_ring->last_td_was_short = false;
+-                                      goto cleanup;
++
++                      if (ep->skip && usb_endpoint_xfer_isoc(&td->urb->ep->desc)) {
++                              skip_isoc_td(xhci, td, ep, status);
++                              goto cleanup;
++                      }
++
++                      /*
++                       * Some hosts give a spurious success event after a short
++                       * transfer. Ignore it.
++                       */
++                      if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) &&
++                          ep_ring->last_td_was_short) {
++                              ep_ring->last_td_was_short = false;
++                              goto cleanup;
++                      }
++
++                      /*
++                       * xhci 4.10.2 states isoc endpoints should continue
++                       * processing the next TD if there was an error mid TD.
++                       * So host like NEC don't generate an event for the last
++                       * isoc TRB even if the IOC flag is set.
++                       * xhci 4.9.1 states that if there are errors in mult-TRB
++                       * TDs xHC should generate an error for that TRB, and if xHC
++                       * proceeds to the next TD it should genete an event for
++                       * any TRB with IOC flag on the way. Other host follow this.
++                       * So this event might be for the next TD.
++                       */
++                      if (td->error_mid_td &&
++                          !list_is_last(&td->td_list, &ep_ring->td_list)) {
++                              struct xhci_td *td_next = list_next_entry(td, td_list);
++
++                              ep_seg = trb_in_td(xhci, td_next->start_seg, td_next->first_trb,
++                                                 td_next->last_trb, ep_trb_dma, false);
++                              if (ep_seg) {
++                                      /* give back previous TD, start handling new */
++                                      xhci_dbg(xhci, "Missing TD completion event after mid TD error\n");
++                                      ep_ring->dequeue = td->last_trb;
++                                      ep_ring->deq_seg = td->last_trb_seg;
++                                      inc_deq(xhci, ep_ring);
++                                      xhci_td_cleanup(xhci, td, ep_ring, td->status);
++                                      td = td_next;
+                               }
++                      }
++
++                      if (!ep_seg) {
+                               /* HC is busted, give up! */
+                               xhci_err(xhci,
+                                       "ERROR Transfer event TRB DMA ptr not "
+@@ -2888,9 +2937,6 @@ static int handle_tx_event(struct xhci_hcd *xhci,
+                                         ep_trb_dma, true);
+                               return -ESHUTDOWN;
+                       }
+-
+-                      skip_isoc_td(xhci, td, ep, status);
+-                      goto cleanup;
+               }
+               if (trb_comp_code == COMP_SHORT_PACKET)
+                       ep_ring->last_td_was_short = true;
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index 8ae33db1e4bcc..0e46b9e45c20c 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1572,6 +1572,7 @@ struct xhci_td {
+       struct xhci_segment     *bounce_seg;
+       /* actual_length of the URB has already been set */
+       bool                    urb_length_set;
++      bool                    error_mid_td;
+       unsigned int            num_trbs;
+ };
+-- 
+2.43.0
+