From d253e17308216e5032c615e679c0c68843300a3c Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sat, 9 Mar 2024 21:31:48 -0500 Subject: [PATCH] Fixes for 5.15 Signed-off-by: Sasha Levin --- ...dd-fixed_rate-quirk-for-jbl-quantum6.patch | 37 ++ ...dd-new-quirk-fixed_rate-for-jbl-quan.patch | 282 ++++++++++++++ ...-usb-audio-add-quirk-for-rode-nt-usb.patch | 55 +++ ...-audio-add-quirk-for-tascam-model-12.patch | 105 ++++++ ...lways-initialize-fixed_rate-in-snd_u.patch | 62 ++++ ...pply-mutex-around-snd_usb_endpoint_s.patch | 61 +++ ...dio-avoid-superfluous-endpoint-setup.patch | 108 ++++++ ...clear-fixed-clock-rate-at-closing-ep.patch | 56 +++ ...orrect-the-return-code-from-snd_usb_.patch | 38 ++ ...ix-microphone-sound-on-nexigo-webcam.patch | 143 ++++++++ ...ix-wrong-kfree-issue-in-snd_usb_endp.patch | 39 ++ ...udio-properly-refcounting-clock-rate.patch | 74 ++++ ...efcount-multiple-accesses-on-the-sin.patch | 284 ++++++++++++++ ...a-usb-audio-sort-quirk-table-entries.patch | 106 ++++++ ...plit-endpoint-setups-for-hw_params-a.patch | 346 ++++++++++++++++++ ...fix-uninitialized-variable-usage-in-.patch | 59 +++ ...increase-frame-larger-than-for-all-d.patch | 70 ++++ ...d-display-move-calcs-folder-into-dml.patch | 212 +++++++++++ ...re-arrange-fpu-code-structure-for-dc.patch | 137 +++++++ ...-remove-dml-makefile-duplicate-lines.patch | 51 +++ ...t-expose-the-api-used-internally-onl.patch | 115 ++++++ ...m-amdgpu-reset-ih-overflow_clear-bit.patch | 170 +++++++++ ...-in-comment-s-sub-theads-sub-threads.patch | 33 ++ ...ombie-kill-the-no-longer-necessary-s.patch | 65 ++++ ...stat-move-thread_group_cputime_adjus.patch | 81 ++++ ...the-signal_struct-sig-local-variable.patch | 93 +++++ ...hread_group_cputime_adjusted-outside.patch | 111 ++++++ .../getrusage-use-__for_each_thread.patch | 43 +++ ...g-stats_lock-rather-than-lock_task_s.patch | 92 +++++ ...er-vf-in-netvsc_probe-if-net_device_.patch | 184 ++++++++++ ...tif_is_bond_master-instead-of-open-c.patch | 38 ++ ...-.ltext-and-.ltext.-to-text_sections.patch | 55 +++ ...post-include-.text.-in-text_sections.patch | 53 +++ ...er-add-goto_chain_index-for-ct-entry.patch | 95 +++++ ...ardware-offload-check-for-post-ct-en.patch | 68 ++++ ...ting-comment-for-nfsd4_release_locko.patch | 73 ++++ ...-take-fi_lock-in-nfsd_break_deleg_cb.patch | 97 +++++ queue-5.15/nfsd-fix-release_lockowner.patch | 149 ++++++++ ...sd-modernize-nfsd4_release_lockowner.patch | 86 +++++ ...s_running-for-wchan-in-proc-pid-stat.patch | 52 +++ ...read-write-callbacks-into-regmap_con.patch | 300 +++++++++++++++ ...define-reg_update_bits-for-no-bus-co.patch | 65 ++++ ...-map_hugetlb-failure-on-64k-page-siz.patch | 61 +++ .../selftests-mm-switch-to-bash-from-sh.patch | 58 +++ ...ts-mptcp-decrease-bw-in-simult-flows.patch | 53 +++ ...-simult-flows-fix-some-subtest-names.patch | 42 +++ ...simult-flows-format-subtests-results.patch | 68 ++++ ...ix-io-data-corruption-in-batched-ope.patch | 88 +++++ ...ake-accessing-revision-id-interface-.patch | 157 ++++++++ ...revent-infinite-while-loop-in-port-s.patch | 76 ++++ ...-use-a-separate-regmap-for-each-port.patch | 243 ++++++++++++ ...se-regmap-methods-for-spi-batch-oper.patch | 93 +++++ queue-5.15/series | 55 +++ .../um-fix-adding-no-pie-for-clang.patch | 68 ++++ ...-babble-and-buffer-overrun-events-pr.patch | 57 +++ ...c-td-properly-when-there-was-a-trans.patch | 186 ++++++++++ 56 files changed, 5748 insertions(+) create mode 100644 queue-5.15/alsa-usb-audio-add-fixed_rate-quirk-for-jbl-quantum6.patch create mode 100644 queue-5.15/alsa-usb-audio-add-new-quirk-fixed_rate-for-jbl-quan.patch create mode 100644 queue-5.15/alsa-usb-audio-add-quirk-for-rode-nt-usb.patch create mode 100644 queue-5.15/alsa-usb-audio-add-quirk-for-tascam-model-12.patch create mode 100644 queue-5.15/alsa-usb-audio-always-initialize-fixed_rate-in-snd_u.patch create mode 100644 queue-5.15/alsa-usb-audio-apply-mutex-around-snd_usb_endpoint_s.patch create mode 100644 queue-5.15/alsa-usb-audio-avoid-superfluous-endpoint-setup.patch create mode 100644 queue-5.15/alsa-usb-audio-clear-fixed-clock-rate-at-closing-ep.patch create mode 100644 queue-5.15/alsa-usb-audio-correct-the-return-code-from-snd_usb_.patch create mode 100644 queue-5.15/alsa-usb-audio-fix-microphone-sound-on-nexigo-webcam.patch create mode 100644 queue-5.15/alsa-usb-audio-fix-wrong-kfree-issue-in-snd_usb_endp.patch create mode 100644 queue-5.15/alsa-usb-audio-properly-refcounting-clock-rate.patch create mode 100644 queue-5.15/alsa-usb-audio-refcount-multiple-accesses-on-the-sin.patch create mode 100644 queue-5.15/alsa-usb-audio-sort-quirk-table-entries.patch create mode 100644 queue-5.15/alsa-usb-audio-split-endpoint-setups-for-hw_params-a.patch create mode 100644 queue-5.15/drm-amd-display-fix-uninitialized-variable-usage-in-.patch create mode 100644 queue-5.15/drm-amd-display-increase-frame-larger-than-for-all-d.patch create mode 100644 queue-5.15/drm-amd-display-move-calcs-folder-into-dml.patch create mode 100644 queue-5.15/drm-amd-display-re-arrange-fpu-code-structure-for-dc.patch create mode 100644 queue-5.15/drm-amd-display-remove-dml-makefile-duplicate-lines.patch create mode 100644 queue-5.15/drm-amd-pm-do-not-expose-the-api-used-internally-onl.patch create mode 100644 queue-5.15/drm-amdgpu-reset-ih-overflow_clear-bit.patch create mode 100644 queue-5.15/exit-fix-typo-in-comment-s-sub-theads-sub-threads.patch create mode 100644 queue-5.15/exit-wait_task_zombie-kill-the-no-longer-necessary-s.patch create mode 100644 queue-5.15/fs-proc-do_task_stat-move-thread_group_cputime_adjus.patch create mode 100644 queue-5.15/getrusage-add-the-signal_struct-sig-local-variable.patch create mode 100644 queue-5.15/getrusage-move-thread_group_cputime_adjusted-outside.patch create mode 100644 queue-5.15/getrusage-use-__for_each_thread.patch create mode 100644 queue-5.15/getrusage-use-sig-stats_lock-rather-than-lock_task_s.patch create mode 100644 queue-5.15/hv_netvsc-register-vf-in-netvsc_probe-if-net_device_.patch create mode 100644 queue-5.15/hv_netvsc-use-netif_is_bond_master-instead-of-open-c.patch create mode 100644 queue-5.15/modpost-add-.ltext-and-.ltext.-to-text_sections.patch create mode 100644 queue-5.15/modpost-include-.text.-in-text_sections.patch create mode 100644 queue-5.15/nfp-flower-add-goto_chain_index-for-ct-entry.patch create mode 100644 queue-5.15/nfp-flower-add-hardware-offload-check-for-post-ct-en.patch create mode 100644 queue-5.15/nfsd-add-documenting-comment-for-nfsd4_release_locko.patch create mode 100644 queue-5.15/nfsd-don-t-take-fi_lock-in-nfsd_break_deleg_cb.patch create mode 100644 queue-5.15/nfsd-fix-release_lockowner.patch create mode 100644 queue-5.15/nfsd-modernize-nfsd4_release_lockowner.patch create mode 100644 queue-5.15/proc-use-task_is_running-for-wchan-in-proc-pid-stat.patch create mode 100644 queue-5.15/regmap-add-bulk-read-write-callbacks-into-regmap_con.patch create mode 100644 queue-5.15/regmap-allow-to-define-reg_update_bits-for-no-bus-co.patch create mode 100644 queue-5.15/selftests-mm-fix-map_hugetlb-failure-on-64k-page-siz.patch create mode 100644 queue-5.15/selftests-mm-switch-to-bash-from-sh.patch create mode 100644 queue-5.15/selftests-mptcp-decrease-bw-in-simult-flows.patch create mode 100644 queue-5.15/selftests-mptcp-simult-flows-fix-some-subtest-names.patch create mode 100644 queue-5.15/selftests-mptcp-simult-flows-format-subtests-results.patch create mode 100644 queue-5.15/serial-max310x-fix-io-data-corruption-in-batched-ope.patch create mode 100644 queue-5.15/serial-max310x-make-accessing-revision-id-interface-.patch create mode 100644 queue-5.15/serial-max310x-prevent-infinite-while-loop-in-port-s.patch create mode 100644 queue-5.15/serial-max310x-use-a-separate-regmap-for-each-port.patch create mode 100644 queue-5.15/serial-max310x-use-regmap-methods-for-spi-batch-oper.patch create mode 100644 queue-5.15/um-fix-adding-no-pie-for-clang.patch create mode 100644 queue-5.15/xhci-handle-isoc-babble-and-buffer-overrun-events-pr.patch create mode 100644 queue-5.15/xhci-process-isoc-td-properly-when-there-was-a-trans.patch 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 index 00000000000..4ab89a1df9d --- /dev/null +++ b/queue-5.15/alsa-usb-audio-add-fixed_rate-quirk-for-jbl-quantum6.patch @@ -0,0 +1,37 @@ +From 3cfa0f1d5a58f8dbbd7dfecb5ab621a62176a76e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 18 Jan 2023 17:59:47 +0100 +Subject: ALSA: usb-audio: Add FIXED_RATE quirk for JBL Quantum610 Wireless + +From: Takashi Iwai + +[ 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 +Stable-dep-of: 668abe6dc7b6 ("ALSA: usb-audio: Sort quirk table entries") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..ca7660e951c --- /dev/null +++ b/queue-5.15/alsa-usb-audio-add-new-quirk-fixed_rate-for-jbl-quan.patch @@ -0,0 +1,282 @@ +From 19d22139cc93bac97a5622ba1ab02ba345723d1f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20221215153037.1163786-1-perex@perex.cz +Signed-off-by: Takashi Iwai +Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..5a3118886ef --- /dev/null +++ b/queue-5.15/alsa-usb-audio-add-quirk-for-rode-nt-usb.patch @@ -0,0 +1,55 @@ +From 3e3ebc8ac5c58c699a72c93087ca5550b9d4f64d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: +Link: https://lore.kernel.org/r/20240124151524.23314-1-sean@mess.org +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..a58154fcf77 --- /dev/null +++ b/queue-5.15/alsa-usb-audio-add-quirk-for-tascam-model-12.patch @@ -0,0 +1,105 @@ +From 0aec1a0b154daba5a66d3f310f4c1d75cb63fe95 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 29 Nov 2022 13:00:59 +0000 +Subject: ALSA: usb-audio: Add quirk for Tascam Model 12 + +From: John Keeping + +[ 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 +Link: https://lore.kernel.org/r/20221129130100.1257904-1-john@metanate.com +Signed-off-by: Takashi Iwai +Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f9c11f922f6 --- /dev/null +++ b/queue-5.15/alsa-usb-audio-always-initialize-fixed_rate-in-snd_u.patch @@ -0,0 +1,62 @@ +From 3b4ebf37bf47cb2aa1f562fc2fe1c777c4111011 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: +Signed-off-by: Jaroslav Kysela +Link: https://lore.kernel.org/r/20230109141133.335543-1-perex@perex.cz +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..1bcb9cc4b22 --- /dev/null +++ b/queue-5.15/alsa-usb-audio-apply-mutex-around-snd_usb_endpoint_s.patch @@ -0,0 +1,61 @@ +From e2e430d64853facb3c48bc3da2e42af6150d0859 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Oct 2022 12:42:10 +0200 +Subject: ALSA: usb-audio: Apply mutex around snd_usb_endpoint_set_params() + +From: Takashi Iwai + +[ 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 +Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..25b5646f448 --- /dev/null +++ b/queue-5.15/alsa-usb-audio-avoid-superfluous-endpoint-setup.patch @@ -0,0 +1,108 @@ +From 8171e13b9cf1455b6516fa0a820830a439f2f7de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 9 Oct 2022 12:42:12 +0200 +Subject: ALSA: usb-audio: Avoid superfluous endpoint setup + +From: Takashi Iwai + +[ 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 +Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..6a6fbc5535d --- /dev/null +++ b/queue-5.15/alsa-usb-audio-clear-fixed-clock-rate-at-closing-ep.patch @@ -0,0 +1,56 @@ +From a0573be416ef827a9a82df1737196e584fd0af79 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Sep 2022 12:04:21 +0200 +Subject: ALSA: usb-audio: Clear fixed clock rate at closing EP + +From: Takashi Iwai + +[ 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 +Tested-by: Jason A. Donenfeld +Cc: +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 +Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..11321436729 --- /dev/null +++ b/queue-5.15/alsa-usb-audio-correct-the-return-code-from-snd_usb_.patch @@ -0,0 +1,38 @@ +From 2447216d3956accd7b3fb5f1d85afe5e88c0d08d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..ca645dc4342 --- /dev/null +++ b/queue-5.15/alsa-usb-audio-fix-microphone-sound-on-nexigo-webcam.patch @@ -0,0 +1,143 @@ +From 286d9d3541f3c2fc1c6baea3fd2c0d9ac0682ff2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Oct 2023 17:53:30 +0200 +Subject: ALSA: usb-audio: Fix microphone sound on Nexigo webcam. + +From: Christos Skevis + +[ 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 +Link: https://lore.kernel.org/r/20231006155330.399393-1-xristos.thes@gmail.com +Signed-off-by: Takashi Iwai +Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..3ac89d2ec7d --- /dev/null +++ b/queue-5.15/alsa-usb-audio-fix-wrong-kfree-issue-in-snd_usb_endp.patch @@ -0,0 +1,39 @@ +From e6c903d9f2cf00516280b571ba2b22d0b540663b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://lore.kernel.org/r/20220518021617.10114-1-wanjiabing@vivo.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..5c9da827fee --- /dev/null +++ b/queue-5.15/alsa-usb-audio-properly-refcounting-clock-rate.patch @@ -0,0 +1,74 @@ +From dc04dbbb44380b1d0bbb4b7fdc37377bd6bc131a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 20 Sep 2022 20:11:26 +0200 +Subject: ALSA: usb-audio: Properly refcounting clock rate + +From: Takashi Iwai + +[ 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 +Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..a34097726f0 --- /dev/null +++ b/queue-5.15/alsa-usb-audio-refcount-multiple-accesses-on-the-sin.patch @@ -0,0 +1,284 @@ +From 381513d78b7f803d2c58afc5a811b170164aa306 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 16 May 2022 12:48:07 +0200 +Subject: ALSA: usb-audio: Refcount multiple accesses on the single clock + +From: Takashi Iwai + +[ 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 +Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..2ab014103a1 --- /dev/null +++ b/queue-5.15/alsa-usb-audio-sort-quirk-table-entries.patch @@ -0,0 +1,106 @@ +From 0cc136667611ed6f7e9384dd5d91769ad6274024 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jan 2024 16:53:07 +0100 +Subject: ALSA: usb-audio: Sort quirk table entries + +From: Takashi Iwai + +[ 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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f64008d2f18 --- /dev/null +++ b/queue-5.15/alsa-usb-audio-split-endpoint-setups-for-hw_params-a.patch @@ -0,0 +1,346 @@ +From a8873d01d3e4f3256e67dd4a4eb2154d79887ba8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +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 +Stable-dep-of: 7822baa844a8 ("ALSA: usb-audio: add quirk for RODE NT-USB+") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..6faf1da9dac --- /dev/null +++ b/queue-5.15/drm-amd-display-fix-uninitialized-variable-usage-in-.patch @@ -0,0 +1,59 @@ +From de06547bbc90d0ebe9974e01e21be87a2353d668 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Jun Lei +Cc: Wayne Lin +Cc: Aurabindo Pillai +Cc: Rodrigo Siqueira +Cc: Hamza Mahfooz +Signed-off-by: Srinivasan Shanmugam +Reviewed-by: Rodrigo Siqueira +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..6c42416caac --- /dev/null +++ b/queue-5.15/drm-amd-display-increase-frame-larger-than-for-all-d.patch @@ -0,0 +1,70 @@ +From f0655a1f9d346930de4e9eb75a4c35aa899822ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..0d62ebb80a0 --- /dev/null +++ b/queue-5.15/drm-amd-display-move-calcs-folder-into-dml.patch @@ -0,0 +1,212 @@ +From d6dbb4a02f573b89d693ba7bc36177368945966e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Jan 2022 18:33:36 -0300 +Subject: drm/amd/display: move calcs folder into DML + +From: Isabella Basso + +[ 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 +Signed-off-by: Isabella Basso +Signed-off-by: Alex Deucher +Stable-dep-of: e63e35f0164c ("drm/amd/display: Increase frame-larger-than for all display_mode_vba files") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e14723869d5 --- /dev/null +++ b/queue-5.15/drm-amd-display-re-arrange-fpu-code-structure-for-dc.patch @@ -0,0 +1,137 @@ +From 57a0e2cfa570639b0b7321a13ac862fe7ff924eb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Oct 2021 22:36:10 +0800 +Subject: drm/amd/display: Re-arrange FPU code structure for dcn2x + +From: Qingqing Zhuo + +[ 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 +Acked-by: Solomon Chiu +Signed-off-by: Qingqing Zhuo +Signed-off-by: Alex Deucher +Stable-dep-of: e63e35f0164c ("drm/amd/display: Increase frame-larger-than for all display_mode_vba files") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..6b89227ec84 --- /dev/null +++ b/queue-5.15/drm-amd-display-remove-dml-makefile-duplicate-lines.patch @@ -0,0 +1,51 @@ +From d2fdf0e7949723bdfa6f2a14c6f0279a151da3d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: André Almeida +Reviewed-by: Harry Wentland +Signed-off-by: Alex Deucher +Stable-dep-of: e63e35f0164c ("drm/amd/display: Increase frame-larger-than for all display_mode_vba files") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..c1a0c808875 --- /dev/null +++ b/queue-5.15/drm-amd-pm-do-not-expose-the-api-used-internally-onl.patch @@ -0,0 +1,115 @@ +From 1567677ccdbdee35bf1e395b2a3a2a125528c30f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ Upstream commit 28a31774b050261371953401e8072ae15200c91e ] + +Move it to kv_dpm.c instead. + +Signed-off-by: Evan Quan +Reviewed-by: Lijo Lazar +Signed-off-by: Alex Deucher +Stable-dep-of: 733025626866 ("drm/amdgpu: Reset IH OVERFLOW_CLEAR bit") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..867bae130f9 --- /dev/null +++ b/queue-5.15/drm-amdgpu-reset-ih-overflow_clear-bit.patch @@ -0,0 +1,170 @@ +From 4e02f3eb93bde1f67d25d4d602037c8e9b53088f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ Upstream commit 7330256268664ea0a7dd5b07a3fed363093477dd ] + +Allows us to detect subsequent IH ring buffer overflows as well. + +Cc: Joshua Ashton +Cc: Alex Deucher +Cc: Christian König +Cc: stable@vger.kernel.org +Signed-off-by: Friedrich Vock +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..860268e76d2 --- /dev/null +++ b/queue-5.15/exit-fix-typo-in-comment-s-sub-theads-sub-threads.patch @@ -0,0 +1,33 @@ +From 1f617efca64c4777c0f63bbf6af189268de89058 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Aug 2022 10:43:42 +0200 +Subject: exit: Fix typo in comment: s/sub-theads/sub-threads + +From: Ingo Molnar + +[ Upstream commit dcca34754a3f5290406403b8066e3b15dda9f4bf ] + +Cc: linux-kernel@vger.kernel.org +Signed-off-by: Ingo Molnar +Stable-dep-of: c1be35a16b2f ("exit: wait_task_zombie: kill the no longer necessary spin_lock_irq(siglock)") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..b45c19ad5ff --- /dev/null +++ b/queue-5.15/exit-wait_task_zombie-kill-the-no-longer-necessary-s.patch @@ -0,0 +1,65 @@ +From 604746c31bdbf34966405f2a75644d27728068e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ Upstream commit c1be35a16b2f1fe21f4f26f9de030ad6eaaf6a25 ] + +After the recent changes nobody use siglock to read the values protected +by stats_lock, we can kill spin_lock_irq(¤t->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 +Signed-off-by: Dylan Hatch +Cc: Eric W. Biederman +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + 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(¤t->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(¤t->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 index 00000000000..ad5ba13e4dc --- /dev/null +++ b/queue-5.15/fs-proc-do_task_stat-move-thread_group_cputime_adjus.patch @@ -0,0 +1,81 @@ +From cc18e4bb6fc0ae25fa50c522f394b08170d857cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Dylan Hatch +Cc: Eric W. Biederman +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..93b9ca4d6a1 --- /dev/null +++ b/queue-5.15/getrusage-add-the-signal_struct-sig-local-variable.patch @@ -0,0 +1,93 @@ +From 829845be724c1424c9a6dc1791fc0029c8656b7b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 9 Sep 2023 19:25:54 +0200 +Subject: getrusage: add the "signal_struct *sig" local variable + +From: Oleg Nesterov + +[ Upstream commit c7ac8231ace9b07306d0299969e42073b189c70a ] + +No functional changes, cleanup/preparation. + +Link: https://lkml.kernel.org/r/20230909172554.GA20441@redhat.com +Signed-off-by: Oleg Nesterov +Cc: Eric W. Biederman +Signed-off-by: Andrew Morton +Stable-dep-of: daa694e41375 ("getrusage: move thread_group_cputime_adjusted() outside of lock_task_sighand()") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..8b4f71da567 --- /dev/null +++ b/queue-5.15/getrusage-move-thread_group_cputime_adjusted-outside.patch @@ -0,0 +1,111 @@ +From 51666a3a9c78ae153e07c1e62dd7acf605c487e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Jan 2024 16:50:50 +0100 +Subject: getrusage: move thread_group_cputime_adjusted() outside of + lock_task_sighand() + +From: Oleg Nesterov + +[ 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 +Reported-by: Dylan Hatch +Tested-by: Dylan Hatch +Cc: Eric W. Biederman +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..1399ef5ac5c --- /dev/null +++ b/queue-5.15/getrusage-use-__for_each_thread.patch @@ -0,0 +1,43 @@ +From 3b997873493d24e618f98d7546099ce96ca6e1de Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 9 Sep 2023 19:26:29 +0200 +Subject: getrusage: use __for_each_thread() + +From: Oleg Nesterov + +[ 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 +Cc: Eric W. Biederman +Signed-off-by: Andrew Morton +Stable-dep-of: f7ec1cd5cc7e ("getrusage: use sig->stats_lock rather than lock_task_sighand()") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..7bf20d198cf --- /dev/null +++ b/queue-5.15/getrusage-use-sig-stats_lock-rather-than-lock_task_s.patch @@ -0,0 +1,92 @@ +From 59a147da2ba7e91424c1ec97c53ca0773968f60c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Jan 2024 16:50:53 +0100 +Subject: getrusage: use sig->stats_lock rather than lock_task_sighand() + +From: Oleg Nesterov + +[ 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 +Reported-by: Dylan Hatch +Tested-by: Dylan Hatch +Cc: Eric W. Biederman +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..2dc6edd6e59 --- /dev/null +++ b/queue-5.15/hv_netvsc-register-vf-in-netvsc_probe-if-net_device_.patch @@ -0,0 +1,184 @@ +From 7a45ba5acfa54a330c3ea6aa99ff13b8e0840b63 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Shradha Gupta +Reviewed-by: Haiyang Zhang +Reviewed-by: Dexuan Cui +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..640c274ed90 --- /dev/null +++ b/queue-5.15/hv_netvsc-use-netif_is_bond_master-instead-of-open-c.patch @@ -0,0 +1,38 @@ +From 6f6fdc40a52b38dea903af25b0b238d803c1b0b3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 10 Oct 2021 13:03:28 +0900 +Subject: hv_netvsc: use netif_is_bond_master() instead of open code + +From: Juhee Kang + +[ 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 +Signed-off-by: David S. Miller +Stable-dep-of: 9cae43da9867 ("hv_netvsc: Register VF in netvsc_probe if NET_DEVICE_REGISTER missed") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..b8f7f40a1ad --- /dev/null +++ b/queue-5.15/modpost-add-.ltext-and-.ltext.-to-text_sections.patch @@ -0,0 +1,55 @@ +From e4a13ccef32375884dd266b8ba59d697f359bb84 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jan 2024 15:59:55 -0700 +Subject: modpost: Add '.ltext' and '.ltext.*' to TEXT_SECTIONS + +From: Nathan Chancellor + +[ 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 +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f933bae248e --- /dev/null +++ b/queue-5.15/modpost-include-.text.-in-text_sections.patch @@ -0,0 +1,53 @@ +From dc17488354b9dd27b5d2edcd64fc12d0a97281c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Dec 2022 11:35:29 -0700 +Subject: modpost: Include '.text.*' in TEXT_SECTIONS + +From: Nathan Chancellor + +[ 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.' 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 +Reviewed-and-tested-by: Alexander Lobakin +Reviewed-by: Sami Tolvanen +Tested-by: Vincent Donnefort +Signed-off-by: Nathan Chancellor +Signed-off-by: Masahiro Yamada +Stable-dep-of: 397586506c3d ("modpost: Add '.ltext' and '.ltext.*' to TEXT_SECTIONS") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..73aa4a9a13f --- /dev/null +++ b/queue-5.15/nfp-flower-add-goto_chain_index-for-ct-entry.patch @@ -0,0 +1,95 @@ +From 87339f9f7477eafd7071f0e7d0bf7799f7771198 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Mar 2023 08:36:08 +0200 +Subject: nfp: flower: add goto_chain_index for ct entry + +From: Wentao Jia + +[ 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 +Acked-by: Simon Horman +Signed-off-by: Louis Peens +Signed-off-by: Jakub Kicinski +Stable-dep-of: cefa98e806fd ("nfp: flower: add hardware offload check for post ct entry") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..762bc7e6936 --- /dev/null +++ b/queue-5.15/nfp-flower-add-hardware-offload-check-for-post-ct-en.patch @@ -0,0 +1,68 @@ +From cc07175827fb87e021328f091ed1855f180535be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Jan 2024 17:19:08 +0200 +Subject: nfp: flower: add hardware offload check for post ct entry + +From: Hui Zhou + +[ 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 +Signed-off-by: Louis Peens +Link: https://lore.kernel.org/r/20240124151909.31603-2-louis.peens@corigine.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + .../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 index 00000000000..ed1d05ae542 --- /dev/null +++ b/queue-5.15/nfsd-add-documenting-comment-for-nfsd4_release_locko.patch @@ -0,0 +1,73 @@ +From e1b27bbfe2fce3942ff80b3eb6458c53b7b628d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 22 May 2022 12:34:38 -0400 +Subject: NFSD: Add documenting comment for nfsd4_release_lockowner() + +From: Chuck Lever + +[ Upstream commit 043862b09cc00273e35e6c3a6389957953a34207 ] + +And return explicit nfserr values that match what is documented in the +new comment / API contract. + +Signed-off-by: Chuck Lever +Stable-dep-of: edcf9725150e ("nfsd: fix RELEASE_LOCKOWNER") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..865ad5a0656 --- /dev/null +++ b/queue-5.15/nfsd-don-t-take-fi_lock-in-nfsd_break_deleg_cb.patch @@ -0,0 +1,97 @@ +From 717ab4f6347df5c3588c0e63148f784d76ec369c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Feb 2024 13:22:39 +1100 +Subject: nfsd: don't take fi_lock in nfsd_break_deleg_cb() + +From: NeilBrown + +[ 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 +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..90a1edf918b --- /dev/null +++ b/queue-5.15/nfsd-fix-release_lockowner.patch @@ -0,0 +1,149 @@ +From ac6bed871ef46355b3aff79f487d6b7da525587d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Jan 2024 14:58:16 +1100 +Subject: nfsd: fix RELEASE_LOCKOWNER + +From: NeilBrown + +[ 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 +Reviewed-by: Jeff Layton +Cc: stable@vger.kernel.org # v6.2+ +Signed-off-by: Chuck Lever +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..c43e384f4aa --- /dev/null +++ b/queue-5.15/nfsd-modernize-nfsd4_release_lockowner.patch @@ -0,0 +1,86 @@ +From 6b245dd6dcc09fc719185689ac9fcc0bb9cd7cf0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 22 May 2022 12:07:18 -0400 +Subject: NFSD: Modernize nfsd4_release_lockowner() + +From: Chuck Lever + +[ 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 +Stable-dep-of: edcf9725150e ("nfsd: fix RELEASE_LOCKOWNER") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..343a2680d4b --- /dev/null +++ b/queue-5.15/proc-use-task_is_running-for-wchan-in-proc-pid-stat.patch @@ -0,0 +1,52 @@ +From 728a74ca4341c638246c15669c4dd072f8d188ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Sep 2021 15:02:15 -0700 +Subject: proc: Use task_is_running() for wchan in /proc/$pid/stat + +From: Kees Cook + +[ 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 +Signed-off-by: Peter Zijlstra (Intel) +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 +--- + 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 index 00000000000..391484cab64 --- /dev/null +++ b/queue-5.15/regmap-add-bulk-read-write-callbacks-into-regmap_con.patch @@ -0,0 +1,300 @@ +From 429c0a2bac690d3da2e39334ea535171395f78c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 30 Apr 2022 04:51:44 +0200 +Subject: regmap: Add bulk read/write callbacks into regmap_config + +From: Marek Vasut + +[ 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 +Cc: Jagan Teki +Cc: Mark Brown +Cc: Maxime Ripard +Cc: Robert Foss +Cc: Sam Ravnborg +Cc: Thomas Zimmermann +To: dri-devel@lists.freedesktop.org +Link: https://lore.kernel.org/r/20220430025145.640305-1-marex@denx.de +Signed-off-by: Mark Brown +Stable-dep-of: 3f42b142ea11 ("serial: max310x: fix IO data corruption in batched operations") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..6027f343785 --- /dev/null +++ b/queue-5.15/regmap-allow-to-define-reg_update_bits-for-no-bus-co.patch @@ -0,0 +1,65 @@ +From ee7b09e81c31d12393c05bbca1614c40c55ffba7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Nov 2021 16:00:40 +0100 +Subject: regmap: allow to define reg_update_bits for no bus configuration + +From: Ansuel Smith + +[ 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 +Link: https://lore.kernel.org/r/20211104150040.1260-1-ansuelsmth@gmail.com +Signed-off-by: Mark Brown +Stable-dep-of: 3f42b142ea11 ("serial: max310x: fix IO data corruption in batched operations") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..a3f00596183 --- /dev/null +++ b/queue-5.15/selftests-mm-fix-map_hugetlb-failure-on-64k-page-siz.patch @@ -0,0 +1,61 @@ +From 64813105ad49bec8e82a522e5a390997590d4827 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jan 2024 06:14:29 -0700 +Subject: selftests: mm: fix map_hugetlb failure on 64K page size systems + +From: Nico Pache + +[ 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 +Cc: Donet Tom +Cc: Shuah Khan +Cc: Christophe Leroy +Cc: Michael Ellerman +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + 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 + #include + #include ++#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 index 00000000000..4f2d25de536 --- /dev/null +++ b/queue-5.15/selftests-mm-switch-to-bash-from-sh.patch @@ -0,0 +1,58 @@ +From 40233cc35dca5c9cb8b4d25ac9c76750dc7ea9d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Jan 2024 14:04:54 +0500 +Subject: selftests/mm: switch to bash from sh + +From: Muhammad Usama Anjum + +[ 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 +Cc: Muhammad Usama Anjum +Cc: Shuah Khan +Cc: David Laight +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..7a5c1d036f3 --- /dev/null +++ b/queue-5.15/selftests-mptcp-decrease-bw-in-simult-flows.patch @@ -0,0 +1,53 @@ +From 4932a188b9e196bd115dffbb465723c9f1effcb4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Jan 2024 22:49:51 +0100 +Subject: selftests: mptcp: decrease BW in simult flows + +From: Matthieu Baerts (NGI0) + +[ 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 +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://lore.kernel.org/r/20240131-upstream-net-20240131-mptcp-ci-issues-v1-6-4c1c11e571ff@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f528c956af0 --- /dev/null +++ b/queue-5.15/selftests-mptcp-simult-flows-fix-some-subtest-names.patch @@ -0,0 +1,42 @@ +From 19c8b4907ef37163bc6be6633152beb25cb163c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Feb 2024 19:25:37 +0100 +Subject: selftests: mptcp: simult flows: fix some subtest names + +From: Matthieu Baerts (NGI0) + +[ 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 +Signed-off-by: Matthieu Baerts (NGI0) +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e05fcd3973b --- /dev/null +++ b/queue-5.15/selftests-mptcp-simult-flows-format-subtests-results.patch @@ -0,0 +1,68 @@ +From f007bec4e943548bed9e5612ce2f65241ab5ef4e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 17 Jul 2023 15:21:31 +0200 +Subject: selftests: mptcp: simult flows: format subtests results in TAP + +From: Matthieu Baerts + +[ 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 +Signed-off-by: Matthieu Baerts +Signed-off-by: David S. Miller +Stable-dep-of: 5e2f3c65af47 ("selftests: mptcp: decrease BW in simult flows") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..c83b78dbc89 --- /dev/null +++ b/queue-5.15/serial-max310x-fix-io-data-corruption-in-batched-ope.patch @@ -0,0 +1,88 @@ +From e300bac8e8b8e957e832da6456e15c16b5667396 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Jan Kundrát +Link: https://lore.kernel.org/r/79db8e82aadb0e174bc82b9996423c3503c8fb37.1680732084.git.jan.kundrat@cesnet.cz +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..a8366f865c4 --- /dev/null +++ b/queue-5.15/serial-max310x-make-accessing-revision-id-interface-.patch @@ -0,0 +1,157 @@ +From 78877e904e73cf50a5427d1860bf84375e2418c5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jun 2022 17:46:58 +0300 +Subject: serial: max310x: make accessing revision id interface-agnostic + +From: Cosmin Tanislav + +[ 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 +Signed-off-by: Cosmin Tanislav +Link: https://lore.kernel.org/r/20220605144659.4169853-4-demonsingur@gmail.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 3f42b142ea11 ("serial: max310x: fix IO data corruption in batched operations") +Signed-off-by: Sasha Levin +--- + 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, ®cfg); + } + +- 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 index 00000000000..d99f3c849c3 --- /dev/null +++ b/queue-5.15/serial-max310x-prevent-infinite-while-loop-in-port-s.patch @@ -0,0 +1,76 @@ +From 18117fc8643b81228a8f8e31fa6277405ba2a304 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 16 Jan 2024 16:30:01 -0500 +Subject: serial: max310x: prevent infinite while() loop in port startup + +From: Hugo Villeneuve + +[ 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 +Link: https://lore.kernel.org/r/20240116213001.3691629-5-hugo@hugovil.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..4fbe828f143 --- /dev/null +++ b/queue-5.15/serial-max310x-use-a-separate-regmap-for-each-port.patch @@ -0,0 +1,243 @@ +From 588bdbe11d4a276b793694c820d2b280a60e303d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jun 2022 17:46:57 +0300 +Subject: serial: max310x: use a separate regmap for each port + +From: Cosmin Tanislav + +[ 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 +Signed-off-by: Cosmin Tanislav +Link: https://lore.kernel.org/r/20220605144659.4169853-3-demonsingur@gmail.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: b35f8dbbce81 ("serial: max310x: prevent infinite while() loop in port startup") +Signed-off-by: Sasha Levin +--- + 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, ®cfg); ++ 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, ®cfg); ++ } + +- 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 index 00000000000..d0617829961 --- /dev/null +++ b/queue-5.15/serial-max310x-use-regmap-methods-for-spi-batch-oper.patch @@ -0,0 +1,93 @@ +From 7e3713d23a7abeac205e4deef6996ae5493868b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jun 2022 17:46:56 +0300 +Subject: serial: max310x: use regmap methods for SPI batch operations + +From: Cosmin Tanislav + +[ 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 +Signed-off-by: Cosmin Tanislav +Link: https://lore.kernel.org/r/20220605144659.4169853-2-demonsingur@gmail.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: b35f8dbbce81 ("serial: max310x: prevent infinite while() loop in port startup") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.15/series b/queue-5.15/series index 9f3a73e7333..b61fb8827ef 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -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 index 00000000000..ea92616dfa6 --- /dev/null +++ b/queue-5.15/um-fix-adding-no-pie-for-clang.patch @@ -0,0 +1,68 @@ +From 0332f68bfb32f980bd2385d853d957c2f9e41460 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Jan 2024 15:59:54 -0700 +Subject: um: Fix adding '-no-pie' for clang + +From: Nathan Chancellor + +[ 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 +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..3c5db6d7ba0 --- /dev/null +++ b/queue-5.15/xhci-handle-isoc-babble-and-buffer-overrun-events-pr.patch @@ -0,0 +1,57 @@ +From f458703f4997eb9faaf82dbc3e12d1c30ce4972b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Jan 2024 17:27:37 +0200 +Subject: xhci: handle isoc Babble and Buffer Overrun events properly + +From: Michal Pecio + +[ 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 +Cc: stable@vger.kernel.org +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20240125152737.2983959-5-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..488c483123c --- /dev/null +++ b/queue-5.15/xhci-process-isoc-td-properly-when-there-was-a-trans.patch @@ -0,0 +1,186 @@ +From 841aebf8e465f96009879c7c54fdf43c61625875 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Closes: https://lore.kernel.org/linux-usb/20240112235205.1259f60c@foxbook/ +Tested-by: Michał Pecio +Cc: stable@vger.kernel.org +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20240125152737.2983959-4-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 + -- 2.47.2