]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.1
authorSasha Levin <sashal@kernel.org>
Sun, 15 Jan 2023 23:58:56 +0000 (18:58 -0500)
committerSasha Levin <sashal@kernel.org>
Sun, 15 Jan 2023 23:58:56 +0000 (18:58 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
82 files changed:
queue-6.1/af_unix-selftest-fix-the-size-of-the-parameter-to-co.patch [new file with mode: 0644]
queue-6.1/alsa-usb-audio-fix-possible-null-pointer-dereference.patch [new file with mode: 0644]
queue-6.1/alsa-usb-audio-make-sure-to-stop-endpoints-before-cl.patch [new file with mode: 0644]
queue-6.1/alsa-usb-audio-relax-hw-constraints-for-implicit-fb-.patch [new file with mode: 0644]
queue-6.1/asoc-intel-fix-sof-nau8825-link-failure.patch [new file with mode: 0644]
queue-6.1/asoc-intel-sof-nau8825-fix-module-alias-overflow.patch [new file with mode: 0644]
queue-6.1/asoc-intel-sof_nau8825-support-rt1015p-speaker-ampli.patch [new file with mode: 0644]
queue-6.1/asoc-qcom-fix-building-apq8016-machine-driver-withou.patch [new file with mode: 0644]
queue-6.1/asoc-wm8904-fix-wrong-outputs-volume-after-power-rea.patch [new file with mode: 0644]
queue-6.1/blk-crypto-pass-a-gendisk-to-blk_crypto_sysfs_-un-re.patch [new file with mode: 0644]
queue-6.1/blk-mq-move-the-srcu_struct-used-for-quiescing-to-th.patch [new file with mode: 0644]
queue-6.1/block-drop-spurious-might_sleep-from-blk_put_queue.patch [new file with mode: 0644]
queue-6.1/block-factor-out-a-blk_debugfs_remove-helper.patch [new file with mode: 0644]
queue-6.1/block-fix-error-unwinding-in-blk_register_queue.patch [new file with mode: 0644]
queue-6.1/block-mark-blk_put_queue-as-potentially-blocking.patch [new file with mode: 0644]
queue-6.1/block-untangle-request_queue-refcounting-from-sysfs.patch [new file with mode: 0644]
queue-6.1/bnxt-make-sure-we-return-pages-to-the-pool.patch [new file with mode: 0644]
queue-6.1/drm-amdgpu-fix-potential-null-dereference.patch [new file with mode: 0644]
queue-6.1/drm-msm-dpu-fix-memory-leak-in-msm_mdss_parse_data_b.patch [new file with mode: 0644]
queue-6.1/drm-msm-dpu-fix-some-kernel-doc-comments.patch [new file with mode: 0644]
queue-6.1/drm-vmwgfx-refactor-resource-manager-s-hashtable-to-.patch [new file with mode: 0644]
queue-6.1/drm-vmwgfx-refactor-resource-validation-hashtable-to.patch [new file with mode: 0644]
queue-6.1/drm-vmwgfx-refactor-ttm-reference-object-hashtable-t.patch [new file with mode: 0644]
queue-6.1/drm-vmwgfx-remove-rcu-locks-from-user-resources.patch [new file with mode: 0644]
queue-6.1/drm-vmwgfx-remove-ttm-object-hashtable.patch [new file with mode: 0644]
queue-6.1/drm-vmwgfx-remove-vmwgfx_hashtab.patch [new file with mode: 0644]
queue-6.1/drm-vmwgfx-write-the-driver-id-registers.patch [new file with mode: 0644]
queue-6.1/efi-fix-null-deref-in-init-error-path.patch [new file with mode: 0644]
queue-6.1/gro-avoid-checking-for-a-failed-search.patch [new file with mode: 0644]
queue-6.1/gro-take-care-of-dodgy-packets.patch [new file with mode: 0644]
queue-6.1/hvc-xen-lock-console-list-traversal.patch [new file with mode: 0644]
queue-6.1/ice-add-check-for-kzalloc.patch [new file with mode: 0644]
queue-6.1/ice-fix-potential-memory-leak-in-ice_gnss_tty_write.patch [new file with mode: 0644]
queue-6.1/igc-fix-pps-delta-between-two-synchronized-end-point.patch [new file with mode: 0644]
queue-6.1/io_uring-lock-overflowing-for-iopoll.patch [new file with mode: 0644]
queue-6.1/io_uring-poll-attempt-request-issue-after-racy-poll-.patch [new file with mode: 0644]
queue-6.1/mtd-cfi-allow-building-spi-intel-standalone.patch [new file with mode: 0644]
queue-6.1/mtd-parsers-scpart-fix-__udivdi3-undefined-on-mips.patch [new file with mode: 0644]
queue-6.1/net-hns3-fix-wrong-use-of-rss-size-during-vf-rss-con.patch [new file with mode: 0644]
queue-6.1/net-lan966x-check-for-ptp-to-be-enabled-in-lan966x_p.patch [new file with mode: 0644]
queue-6.1/net-mlx5-check-attr-pointer-validity-before-derefere.patch [new file with mode: 0644]
queue-6.1/net-mlx5-fix-command-stats-access-after-free.patch [new file with mode: 0644]
queue-6.1/net-mlx5-fix-ptp-max-frequency-adjustment-range.patch [new file with mode: 0644]
queue-6.1/net-mlx5e-don-t-support-encap-rules-with-gbp-option.patch [new file with mode: 0644]
queue-6.1/net-mlx5e-fix-macsec-possible-null-dereference-when-.patch [new file with mode: 0644]
queue-6.1/net-mlx5e-fix-macsec-ssci-attribute-handling-in-offl.patch [new file with mode: 0644]
queue-6.1/net-mlx5e-ipoib-block-pkey-interfaces-with-less-rx-q.patch [new file with mode: 0644]
queue-6.1/net-mlx5e-ipoib-block-queue-count-configuration-when.patch [new file with mode: 0644]
queue-6.1/net-mlx5e-ipoib-fix-child-pkey-interface-stats-on-rx.patch [new file with mode: 0644]
queue-6.1/net-mlx5e-tc-keep-mod-hdr-actions-after-mod-hdr-allo.patch [new file with mode: 0644]
queue-6.1/net-mlx5e-verify-dev-is-present-for-fix-features-ndo.patch [new file with mode: 0644]
queue-6.1/net-sched-act_mpls-fix-warning-during-failed-attribu.patch [new file with mode: 0644]
queue-6.1/nfc-pn533-wait-for-out_urb-s-completion-in-pn533_usb.patch [new file with mode: 0644]
queue-6.1/nfsd-add-an-nfsd_file_fsync-tracepoint.patch [new file with mode: 0644]
queue-6.1/nfsd-add-an-nfsd_file_gc-flag-to-enable-nfsd_file-ga.patch [new file with mode: 0644]
queue-6.1/nfsd-fix-handling-of-cached-open-files-in-nfsd4_open.patch [new file with mode: 0644]
queue-6.1/nfsd-pass-the-target-nfsd_file-to-nfsd_commit.patch [new file with mode: 0644]
queue-6.1/nfsd-remove-the-pages_flushed-statistic-from-filecac.patch [new file with mode: 0644]
queue-6.1/nfsd-reorganize-filecache.c.patch [new file with mode: 0644]
queue-6.1/nfsd-revert-nfsd-nfsv4-close-should-release-an-nfsd_.patch [new file with mode: 0644]
queue-6.1/nfsd-rework-refcounting-in-filecache.patch [new file with mode: 0644]
queue-6.1/octeontx2-af-fix-lmac-config-in-cgx_lmac_rx_tx_enabl.patch [new file with mode: 0644]
queue-6.1/octeontx2-pf-fix-resource-leakage-in-vf-driver-unbin.patch [new file with mode: 0644]
queue-6.1/perf-build-properly-guard-libbpf-includes.patch [new file with mode: 0644]
queue-6.1/perf-kmem-support-field-node-in-evsel__process_alloc.patch [new file with mode: 0644]
queue-6.1/perf-kmem-support-legacy-tracepoints.patch [new file with mode: 0644]
queue-6.1/platform-surface-aggregator-add-missing-call-to-ssam.patch [new file with mode: 0644]
queue-6.1/platform-x86-amd-fix-refcount-leak-in-amd_pmc_probe.patch [new file with mode: 0644]
queue-6.1/regulator-da9211-use-irq-handler-when-ready.patch [new file with mode: 0644]
queue-6.1/revert-r8169-disable-detection-of-chip-version-36.patch [new file with mode: 0644]
queue-6.1/sched-core-fix-arch_scale_freq_tick-on-tickless-syst.patch [new file with mode: 0644]
queue-6.1/scsi-mpi3mr-refer-config_scsi_mpi3mr-in-makefile.patch [new file with mode: 0644]
queue-6.1/scsi-storvsc-fix-swiotlb-bounce-buffer-leak-in-confi.patch [new file with mode: 0644]
queue-6.1/scsi-ufs-core-wlun-suspend-ssu-enter-hibern8-fail-re.patch [new file with mode: 0644]
queue-6.1/selftests-net-l2_tos_ttl_inherit.sh-ensure-environme.patch [new file with mode: 0644]
queue-6.1/selftests-net-l2_tos_ttl_inherit.sh-run-tests-in-the.patch [new file with mode: 0644]
queue-6.1/selftests-net-l2_tos_ttl_inherit.sh-set-ipv6-address.patch [new file with mode: 0644]
queue-6.1/series
queue-6.1/stmmac-dwmac-mediatek-remove-the-dwmac_fix_mac_speed.patch [new file with mode: 0644]
queue-6.1/tipc-fix-unexpected-link-reset-due-to-discovery-mess.patch [new file with mode: 0644]
queue-6.1/tools-nolibc-fix-the-o_-fcntl-open-macro-definitions.patch [new file with mode: 0644]
queue-6.1/tools-nolibc-restore-mips-branch-ordering-in-the-_st.patch [new file with mode: 0644]

diff --git a/queue-6.1/af_unix-selftest-fix-the-size-of-the-parameter-to-co.patch b/queue-6.1/af_unix-selftest-fix-the-size-of-the-parameter-to-co.patch
new file mode 100644 (file)
index 0000000..71ffd2c
--- /dev/null
@@ -0,0 +1,58 @@
+From 9802dc7ce4d550936c03edeb0db440c1bfb8a961 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 7 Jan 2023 04:40:20 +0100
+Subject: af_unix: selftest: Fix the size of the parameter to connect()
+
+From: Mirsad Goran Todorovac <mirsad.todorovac@alu.unizg.hr>
+
+[ Upstream commit 7d6ceeb1875cc08dc3d1e558e191434d94840cd5 ]
+
+Adjust size parameter in connect() to match the type of the parameter, to
+fix "No such file or directory" error in selftests/net/af_unix/
+test_oob_unix.c:127.
+
+The existing code happens to work provided that the autogenerated pathname
+is shorter than sizeof (struct sockaddr), which is why it hasn't been
+noticed earlier.
+
+Visible from the trace excerpt:
+
+bind(3, {sa_family=AF_UNIX, sun_path="unix_oob_453059"}, 110) = 0
+clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7fa6a6577a10) = 453060
+[pid <child>] connect(6, {sa_family=AF_UNIX, sun_path="unix_oob_45305"}, 16) = -1 ENOENT (No such file or directory)
+
+BUG: The filename is trimmed to sizeof (struct sockaddr).
+
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: Eric Dumazet <edumazet@google.com>
+Cc: Jakub Kicinski <kuba@kernel.org>
+Cc: Paolo Abeni <pabeni@redhat.com>
+Cc: Shuah Khan <shuah@kernel.org>
+Cc: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
+Cc: Florian Westphal <fw@strlen.de>
+Reviewed-by: Florian Westphal <fw@strlen.de>
+Fixes: 314001f0bf92 ("af_unix: Add OOB support")
+Signed-off-by: Mirsad Goran Todorovac <mirsad.todorovac@alu.unizg.hr>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/af_unix/test_unix_oob.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/testing/selftests/net/af_unix/test_unix_oob.c b/tools/testing/selftests/net/af_unix/test_unix_oob.c
+index b57e91e1c3f2..532459a15067 100644
+--- a/tools/testing/selftests/net/af_unix/test_unix_oob.c
++++ b/tools/testing/selftests/net/af_unix/test_unix_oob.c
+@@ -124,7 +124,7 @@ void producer(struct sockaddr_un *consumer_addr)
+       wait_for_signal(pipefd[0]);
+       if (connect(cfd, (struct sockaddr *)consumer_addr,
+-                   sizeof(struct sockaddr)) != 0) {
++                   sizeof(*consumer_addr)) != 0) {
+               perror("Connect failed");
+               kill(0, SIGTERM);
+               exit(1);
+-- 
+2.35.1
+
diff --git a/queue-6.1/alsa-usb-audio-fix-possible-null-pointer-dereference.patch b/queue-6.1/alsa-usb-audio-fix-possible-null-pointer-dereference.patch
new file mode 100644 (file)
index 0000000..7c3fe91
--- /dev/null
@@ -0,0 +1,44 @@
+From c60d4354b6e26ceef976bd3769e84c49c7b8da46 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 13 Jan 2023 09:53:11 +0100
+Subject: ALSA: usb-audio: Fix possible NULL pointer dereference in
+ snd_usb_pcm_has_fixed_rate()
+
+From: Jaroslav Kysela <perex@perex.cz>
+
+[ Upstream commit 92a9c0ad86d47ff4cce899012e355c400f02cfb8 ]
+
+The subs function argument may be NULL, so do not use it before the NULL check.
+
+Fixes: 291e9da91403 ("ALSA: usb-audio: Always initialize fixed_rate in snd_usb_find_implicit_fb_sync_format()")
+Reported-by: coverity-bot <keescook@chromium.org>
+Link: https://lore.kernel.org/alsa-devel/202301121424.4A79A485@keescook/
+Signed-off-by: Jaroslav Kysela <perex@perex.cz>
+Link: https://lore.kernel.org/r/20230113085311.623325-1-perex@perex.cz
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/pcm.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
+index 29838000eee0..2c5765cbed2d 100644
+--- a/sound/usb/pcm.c
++++ b/sound/usb/pcm.c
+@@ -160,11 +160,12 @@ find_substream_format(struct snd_usb_substream *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;
++      struct snd_usb_audio *chip;
+       int rate = -1;
+       if (!subs)
+               return false;
++      chip = subs->stream->chip;
+       if (!(chip->quirk_flags & QUIRK_FLAG_FIXED_RATE))
+               return false;
+       list_for_each_entry(fp, &subs->fmt_list, list) {
+-- 
+2.35.1
+
diff --git a/queue-6.1/alsa-usb-audio-make-sure-to-stop-endpoints-before-cl.patch b/queue-6.1/alsa-usb-audio-make-sure-to-stop-endpoints-before-cl.patch
new file mode 100644 (file)
index 0000000..c2bf9bd
--- /dev/null
@@ -0,0 +1,45 @@
+From e8d205471cae10707410a4d306416a31ac1497d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Jan 2023 18:07:57 +0100
+Subject: ALSA: usb-audio: Make sure to stop endpoints before closing EPs
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 0599313e26666e79f6e7fe1450588431b8cb25d5 ]
+
+At the PCM hw params, we may re-configure the endpoints and it's done
+by a temporary EP close followed by re-open.  A potential problem
+there is that the EP might be already running internally at the PCM
+prepare stage; it's seen typically in the playback stream with the
+implicit feedback sync.  As this stream start isn't tracked by the
+core PCM layer, we'd need to stop it explicitly, and that's the
+missing piece.
+
+This patch adds the stop_endpoints() call at snd_usb_hw_params() to
+assure the stream stop before closing the EPs.
+
+Fixes: bf6313a0ff76 ("ALSA: usb-audio: Refactor endpoint management")
+Link: https://lore.kernel.org/r/4e509aea-e563-e592-e652-ba44af6733fe@veniogames.com
+Link: https://lore.kernel.org/r/20230102170759.29610-2-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/pcm.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
+index d2c652aa1385..535eb95bc9ee 100644
+--- a/sound/usb/pcm.c
++++ b/sound/usb/pcm.c
+@@ -527,6 +527,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+               if (snd_usb_endpoint_compatible(chip, subs->data_endpoint,
+                                               fmt, hw_params))
+                       goto unlock;
++              if (stop_endpoints(subs, false))
++                      sync_pending_stops(subs);
+               close_endpoints(chip, subs);
+       }
+-- 
+2.35.1
+
diff --git a/queue-6.1/alsa-usb-audio-relax-hw-constraints-for-implicit-fb-.patch b/queue-6.1/alsa-usb-audio-relax-hw-constraints-for-implicit-fb-.patch
new file mode 100644 (file)
index 0000000..e6bf104
--- /dev/null
@@ -0,0 +1,55 @@
+From 50ae6e718898d4d28086dc799abe0741bb634ccd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Jan 2023 18:07:58 +0100
+Subject: ALSA: usb-audio: Relax hw constraints for implicit fb sync
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit d463ac1acb454fafed58f695cb3067fbf489f3a0 ]
+
+The fix commit the commit e4ea77f8e53f ("ALSA: usb-audio: Always apply
+the hw constraints for implicit fb sync") tried to address the bug
+where an incorrect PCM parameter is chosen when two (implicit fb)
+streams are set up at the same time.  This change had, however, some
+side effect: once when the sync endpoint is chosen and set up, this
+restriction is applied at the next hw params unless it's freed via hw
+free explicitly.
+
+This patch is a workaround for the problem by relaxing the hw
+constraints a bit for the implicit fb sync.  We still keep applying
+the hw constraints for implicit fb sync, but only when the matching
+sync EP is being used by other streams.
+
+Fixes: e4ea77f8e53f ("ALSA: usb-audio: Always apply the hw constraints for implicit fb sync")
+Reported-by: Ruud van Asseldonk <ruud@veniogames.com>
+Link: https://lore.kernel.org/r/4e509aea-e563-e592-e652-ba44af6733fe@veniogames.com
+Link: https://lore.kernel.org/r/20230102170759.29610-3-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/usb/pcm.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
+index 535eb95bc9ee..29838000eee0 100644
+--- a/sound/usb/pcm.c
++++ b/sound/usb/pcm.c
+@@ -939,8 +939,13 @@ get_sync_ep_from_substream(struct snd_usb_substream *subs)
+                       continue;
+               /* for the implicit fb, check the sync ep as well */
+               ep = snd_usb_get_endpoint(chip, fp->sync_ep);
+-              if (ep && ep->cur_audiofmt)
+-                      return ep;
++              if (ep && ep->cur_audiofmt) {
++                      /* ditto, if the sync (data) ep is used by others,
++                       * this stream is restricted by the sync ep
++                       */
++                      if (ep != subs->sync_endpoint || ep->opened > 1)
++                              return ep;
++              }
+       }
+       return NULL;
+ }
+-- 
+2.35.1
+
diff --git a/queue-6.1/asoc-intel-fix-sof-nau8825-link-failure.patch b/queue-6.1/asoc-intel-fix-sof-nau8825-link-failure.patch
new file mode 100644 (file)
index 0000000..bd2e1d4
--- /dev/null
@@ -0,0 +1,40 @@
+From 53462d345b7d8dabe94ee7dc7702730518175b32 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Dec 2022 14:25:48 +0100
+Subject: ASoC: Intel: fix sof-nau8825 link failure
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit 63f3d99b7efe4c5404a9388c05780917099cecf4 ]
+
+The snd-soc-sof_nau8825.ko module fails to link unless the
+sof_realtek_common support is also enabled:
+
+ERROR: modpost: "sof_rt1015p_codec_conf" [sound/soc/intel/boards/snd-soc-sof_nau8825.ko] undefined!
+ERROR: modpost: "sof_rt1015p_dai_link" [sound/soc/intel/boards/snd-soc-sof_nau8825.ko] undefined!
+
+Fixes: 8d0872f6239f ("ASoC: Intel: add sof-nau8825 machine driver")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Link: https://lore.kernel.org/r/20221221132559.2402341-1-arnd@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
+index aa12d7e3dd2f..ca49cc49c378 100644
+--- a/sound/soc/intel/boards/Kconfig
++++ b/sound/soc/intel/boards/Kconfig
+@@ -558,6 +558,7 @@ config SND_SOC_INTEL_SOF_NAU8825_MACH
+       select SND_SOC_HDAC_HDMI
+       select SND_SOC_INTEL_HDA_DSP_COMMON
+       select SND_SOC_INTEL_SOF_MAXIM_COMMON
++      select SND_SOC_INTEL_SOF_REALTEK_COMMON
+       help
+          This adds support for ASoC machine driver for SOF platforms
+          with nau8825 codec.
+-- 
+2.35.1
+
diff --git a/queue-6.1/asoc-intel-sof-nau8825-fix-module-alias-overflow.patch b/queue-6.1/asoc-intel-sof-nau8825-fix-module-alias-overflow.patch
new file mode 100644 (file)
index 0000000..2671a9c
--- /dev/null
@@ -0,0 +1,119 @@
+From 81868dc7b6e837be9c3739f80b615864f8d11758 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Dec 2022 14:24:56 +0100
+Subject: ASoC: Intel: sof-nau8825: fix module alias overflow
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit 3e78986a840d59dd27e636eae3f52dc11125c835 ]
+
+The maximum name length for a platform_device_id entry is 20 characters
+including the trailing NUL byte. The sof_nau8825.c file exceeds that,
+which causes an obscure error message:
+
+sound/soc/intel/boards/snd-soc-sof_nau8825.mod.c:35:45: error: illegal character encoding in string literal [-Werror,-Winvalid-source-encoding]
+MODULE_ALIAS("platform:adl_max98373_nau8825<U+0018><AA>");
+                                                   ^~~~
+include/linux/module.h:168:49: note: expanded from macro 'MODULE_ALIAS'
+                                                ^~~~~~
+include/linux/module.h:165:56: note: expanded from macro 'MODULE_INFO'
+                                                       ^~~~
+include/linux/moduleparam.h:26:47: note: expanded from macro '__MODULE_INFO'
+                = __MODULE_INFO_PREFIX __stringify(tag) "=" info
+
+I could not figure out how to make the module handling robust enough
+to handle this better, but as a quick fix, using slightly shorter
+names that are still unique avoids the build issue.
+
+Fixes: 8d0872f6239f ("ASoC: Intel: add sof-nau8825 machine driver")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Link: https://lore.kernel.org/r/20221221132515.2363276-1-arnd@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/sof_nau8825.c              | 8 ++++----
+ sound/soc/intel/common/soc-acpi-intel-adl-match.c | 8 ++++----
+ 2 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/sound/soc/intel/boards/sof_nau8825.c b/sound/soc/intel/boards/sof_nau8825.c
+index 27880224359d..009a41fbefa1 100644
+--- a/sound/soc/intel/boards/sof_nau8825.c
++++ b/sound/soc/intel/boards/sof_nau8825.c
+@@ -618,7 +618,7 @@ static const struct platform_device_id board_ids[] = {
+       },
+       {
+-              .name = "adl_rt1019p_nau8825",
++              .name = "adl_rt1019p_8825",
+               .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
+                                       SOF_SPEAKER_AMP_PRESENT |
+                                       SOF_RT1019P_SPEAKER_AMP_PRESENT |
+@@ -626,7 +626,7 @@ static const struct platform_device_id board_ids[] = {
+                                       SOF_NAU8825_NUM_HDMIDEV(4)),
+       },
+       {
+-              .name = "adl_max98373_nau8825",
++              .name = "adl_max98373_8825",
+               .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
+                                       SOF_SPEAKER_AMP_PRESENT |
+                                       SOF_MAX98373_SPEAKER_AMP_PRESENT |
+@@ -637,7 +637,7 @@ static const struct platform_device_id board_ids[] = {
+       },
+       {
+               /* The limitation of length of char array, shorten the name */
+-              .name = "adl_mx98360a_nau8825",
++              .name = "adl_mx98360a_8825",
+               .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
+                                       SOF_SPEAKER_AMP_PRESENT |
+                                       SOF_MAX98360A_SPEAKER_AMP_PRESENT |
+@@ -648,7 +648,7 @@ static const struct platform_device_id board_ids[] = {
+       },
+       {
+-              .name = "adl_rt1015p_nau8825",
++              .name = "adl_rt1015p_8825",
+               .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
+                                       SOF_SPEAKER_AMP_PRESENT |
+                                       SOF_RT1015P_SPEAKER_AMP_PRESENT |
+diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
+index ce4d8ec86f2c..68b4fa352354 100644
+--- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c
++++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
+@@ -474,21 +474,21 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
+       },
+       {
+               .id = "10508825",
+-              .drv_name = "adl_rt1019p_nau8825",
++              .drv_name = "adl_rt1019p_8825",
+               .machine_quirk = snd_soc_acpi_codec_list,
+               .quirk_data = &adl_rt1019p_amp,
+               .sof_tplg_filename = "sof-adl-rt1019-nau8825.tplg",
+       },
+       {
+               .id = "10508825",
+-              .drv_name = "adl_max98373_nau8825",
++              .drv_name = "adl_max98373_8825",
+               .machine_quirk = snd_soc_acpi_codec_list,
+               .quirk_data = &adl_max98373_amp,
+               .sof_tplg_filename = "sof-adl-max98373-nau8825.tplg",
+       },
+       {
+               .id = "10508825",
+-              .drv_name = "adl_mx98360a_nau8825",
++              .drv_name = "adl_mx98360a_8825",
+               .machine_quirk = snd_soc_acpi_codec_list,
+               .quirk_data = &adl_max98360a_amp,
+               .sof_tplg_filename = "sof-adl-max98360a-nau8825.tplg",
+@@ -502,7 +502,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
+       },
+       {
+               .id = "10508825",
+-              .drv_name = "adl_rt1015p_nau8825",
++              .drv_name = "adl_rt1015p_8825",
+               .machine_quirk = snd_soc_acpi_codec_list,
+               .quirk_data = &adl_rt1015p_amp,
+               .sof_tplg_filename = "sof-adl-rt1015-nau8825.tplg",
+-- 
+2.35.1
+
diff --git a/queue-6.1/asoc-intel-sof_nau8825-support-rt1015p-speaker-ampli.patch b/queue-6.1/asoc-intel-sof_nau8825-support-rt1015p-speaker-ampli.patch
new file mode 100644 (file)
index 0000000..5b60d8b
--- /dev/null
@@ -0,0 +1,110 @@
+From e3ee72117d71e8c30a11c2d7d425dfbb22b10bd5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Nov 2022 17:19:19 -0600
+Subject: ASoC: Intel: sof_nau8825: support rt1015p speaker amplifier
+
+From: Brent Lu <brent.lu@intel.com>
+
+[ Upstream commit 13c459fa37c9f26e9bf884a832dd67598b5c4d3e ]
+
+Add rt1015p speaker amplifier support with a new board info
+'adl_rt1015p_nau8825' which supports NAU8825 on SSP0 and ALC1015Q on
+SSP1.
+
+Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Signed-off-by: Brent Lu <brent.lu@intel.com>
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Link: https://lore.kernel.org/r/20221117231919.112483-1-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 3e78986a840d ("ASoC: Intel: sof-nau8825: fix module alias overflow")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/boards/sof_nau8825.c             | 16 ++++++++++++++++
+ .../soc/intel/common/soc-acpi-intel-adl-match.c  | 12 ++++++++++++
+ 2 files changed, 28 insertions(+)
+
+diff --git a/sound/soc/intel/boards/sof_nau8825.c b/sound/soc/intel/boards/sof_nau8825.c
+index 5585c217f78d..27880224359d 100644
+--- a/sound/soc/intel/boards/sof_nau8825.c
++++ b/sound/soc/intel/boards/sof_nau8825.c
+@@ -47,6 +47,7 @@
+ #define SOF_RT1019P_SPEAKER_AMP_PRESENT       BIT(14)
+ #define SOF_MAX98373_SPEAKER_AMP_PRESENT      BIT(15)
+ #define SOF_MAX98360A_SPEAKER_AMP_PRESENT     BIT(16)
++#define SOF_RT1015P_SPEAKER_AMP_PRESENT       BIT(17)
+ static unsigned long sof_nau8825_quirk = SOF_NAU8825_SSP_CODEC(0);
+@@ -483,6 +484,8 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev,
+               } else if (sof_nau8825_quirk &
+                               SOF_MAX98360A_SPEAKER_AMP_PRESENT) {
+                       max_98360a_dai_link(&links[id]);
++              } else if (sof_nau8825_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT) {
++                      sof_rt1015p_dai_link(&links[id]);
+               } else {
+                       goto devm_err;
+               }
+@@ -576,6 +579,8 @@ static int sof_audio_probe(struct platform_device *pdev)
+       if (sof_nau8825_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT)
+               max_98373_set_codec_conf(&sof_audio_card_nau8825);
++      else if (sof_nau8825_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT)
++              sof_rt1015p_codec_conf(&sof_audio_card_nau8825);
+       if (sof_nau8825_quirk & SOF_SSP_BT_OFFLOAD_PRESENT)
+               sof_audio_card_nau8825.num_links++;
+@@ -642,6 +647,16 @@ static const struct platform_device_id board_ids[] = {
+                                       SOF_SSP_BT_OFFLOAD_PRESENT),
+       },
++      {
++              .name = "adl_rt1015p_nau8825",
++              .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) |
++                                      SOF_SPEAKER_AMP_PRESENT |
++                                      SOF_RT1015P_SPEAKER_AMP_PRESENT |
++                                      SOF_NAU8825_SSP_AMP(1) |
++                                      SOF_NAU8825_NUM_HDMIDEV(4) |
++                                      SOF_BT_OFFLOAD_SSP(2) |
++                                      SOF_SSP_BT_OFFLOAD_PRESENT),
++      },
+       { }
+ };
+ MODULE_DEVICE_TABLE(platform, board_ids);
+@@ -663,3 +678,4 @@ MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
+ MODULE_LICENSE("GPL");
+ MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
+ MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
++MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
+diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
+index 9990d5502d26..ce4d8ec86f2c 100644
+--- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c
++++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c
+@@ -430,6 +430,11 @@ static const struct snd_soc_acpi_codecs adl_rt5682_rt5682s_hp = {
+       .codecs = {"10EC5682", "RTL5682"},
+ };
++static const struct snd_soc_acpi_codecs adl_rt1015p_amp = {
++      .num_codecs = 1,
++      .codecs = {"RTL1015"}
++};
++
+ static const struct snd_soc_acpi_codecs adl_rt1019p_amp = {
+       .num_codecs = 1,
+       .codecs = {"RTL1019"}
+@@ -495,6 +500,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = {
+               .quirk_data = &adl_rt1019p_amp,
+               .sof_tplg_filename = "sof-adl-rt1019-rt5682.tplg",
+       },
++      {
++              .id = "10508825",
++              .drv_name = "adl_rt1015p_nau8825",
++              .machine_quirk = snd_soc_acpi_codec_list,
++              .quirk_data = &adl_rt1015p_amp,
++              .sof_tplg_filename = "sof-adl-rt1015-nau8825.tplg",
++      },
+       {
+               .id = "10508825",
+               .drv_name = "sof_nau8825",
+-- 
+2.35.1
+
diff --git a/queue-6.1/asoc-qcom-fix-building-apq8016-machine-driver-withou.patch b/queue-6.1/asoc-qcom-fix-building-apq8016-machine-driver-withou.patch
new file mode 100644 (file)
index 0000000..a941047
--- /dev/null
@@ -0,0 +1,486 @@
+From 0aff577b36aaac9c14b90d822d0fda26993b3d65 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 31 Dec 2022 12:55:06 +0100
+Subject: ASoC: qcom: Fix building APQ8016 machine driver without SOUNDWIRE
+
+From: Stephan Gerhold <stephan@gerhold.net>
+
+[ Upstream commit 0cbf1ecd8c4801ec7566231491f7ad9cec31098b ]
+
+Older Qualcomm platforms like APQ8016 do not have hardware support for
+SoundWire, so kernel configurations made specifically for those platforms
+will usually not have CONFIG_SOUNDWIRE enabled.
+
+Unfortunately commit 8d89cf6ff229 ("ASoC: qcom: cleanup and fix
+dependency of QCOM_COMMON") breaks those kernel configurations, because
+SOUNDWIRE is now a required dependency for SND_SOC_QCOM_COMMON (and in
+turn also SND_SOC_APQ8016_SBC). Trying to migrate such a kernel config
+silently disables SND_SOC_APQ8016_SBC and breaks audio functionality.
+
+The soundwire helpers in common.c are only used by two of the Qualcomm
+audio machine drivers, so building and requiring CONFIG_SOUNDWIRE for
+all platforms is unnecessary.
+
+There is no need to stuff all common code into a single module. Fix the
+issue by moving the soundwire helpers to a separate SND_SOC_QCOM_SDW
+module/option that is selected only by the machine drivers that make
+use of them. This also allows reverting the imply/depends changes from
+the previous fix because both SM8250 and SC8280XP already depend on
+SOUNDWIRE, so the soundwire helpers will be only built if SOUNDWIRE
+is really enabled.
+
+Cc: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+Fixes: 8d89cf6ff229 ("ASoC: qcom: cleanup and fix dependency of QCOM_COMMON")
+Signed-off-by: Stephan Gerhold <stephan@gerhold.net>
+Link: https://lore.kernel.org/r/20221231115506.82991-1-stephan@gerhold.net
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/qcom/Kconfig    |  21 ++++---
+ sound/soc/qcom/Makefile   |   2 +
+ sound/soc/qcom/common.c   | 114 -----------------------------------
+ sound/soc/qcom/common.h   |  10 ----
+ sound/soc/qcom/sc8280xp.c |   1 +
+ sound/soc/qcom/sdw.c      | 123 ++++++++++++++++++++++++++++++++++++++
+ sound/soc/qcom/sdw.h      |  18 ++++++
+ sound/soc/qcom/sm8250.c   |   1 +
+ 8 files changed, 157 insertions(+), 133 deletions(-)
+ create mode 100644 sound/soc/qcom/sdw.c
+ create mode 100644 sound/soc/qcom/sdw.h
+
+diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig
+index 96a6d4731e6f..e7b00d1d9e99 100644
+--- a/sound/soc/qcom/Kconfig
++++ b/sound/soc/qcom/Kconfig
+@@ -2,7 +2,6 @@
+ menuconfig SND_SOC_QCOM
+       tristate "ASoC support for QCOM platforms"
+       depends on ARCH_QCOM || COMPILE_TEST
+-      imply SND_SOC_QCOM_COMMON
+       help
+         Say Y or M if you want to add support to use audio devices
+         in Qualcomm Technologies SOC-based platforms.
+@@ -60,14 +59,16 @@ config SND_SOC_STORM
+ config SND_SOC_APQ8016_SBC
+       tristate "SoC Audio support for APQ8016 SBC platforms"
+       select SND_SOC_LPASS_APQ8016
+-      depends on SND_SOC_QCOM_COMMON
++      select SND_SOC_QCOM_COMMON
+       help
+         Support for Qualcomm Technologies LPASS audio block in
+         APQ8016 SOC-based systems.
+         Say Y if you want to use audio devices on MI2S.
+ config SND_SOC_QCOM_COMMON
+-      depends on SOUNDWIRE
++      tristate
++
++config SND_SOC_QCOM_SDW
+       tristate
+ config SND_SOC_QDSP6_COMMON
+@@ -144,7 +145,7 @@ config SND_SOC_MSM8996
+       depends on QCOM_APR
+       depends on COMMON_CLK
+       select SND_SOC_QDSP6
+-      depends on SND_SOC_QCOM_COMMON
++      select SND_SOC_QCOM_COMMON
+       help
+         Support for Qualcomm Technologies LPASS audio block in
+         APQ8096 SoC-based systems.
+@@ -155,7 +156,7 @@ config SND_SOC_SDM845
+       depends on QCOM_APR && I2C && SOUNDWIRE
+       depends on COMMON_CLK
+       select SND_SOC_QDSP6
+-      depends on SND_SOC_QCOM_COMMON
++      select SND_SOC_QCOM_COMMON
+       select SND_SOC_RT5663
+       select SND_SOC_MAX98927
+       imply SND_SOC_CROS_EC_CODEC
+@@ -169,7 +170,8 @@ config SND_SOC_SM8250
+       depends on QCOM_APR && SOUNDWIRE
+       depends on COMMON_CLK
+       select SND_SOC_QDSP6
+-      depends on SND_SOC_QCOM_COMMON
++      select SND_SOC_QCOM_COMMON
++      select SND_SOC_QCOM_SDW
+       help
+         To add support for audio on Qualcomm Technologies Inc.
+         SM8250 SoC-based systems.
+@@ -180,7 +182,8 @@ config SND_SOC_SC8280XP
+       depends on QCOM_APR && SOUNDWIRE
+       depends on COMMON_CLK
+       select SND_SOC_QDSP6
+-      depends on SND_SOC_QCOM_COMMON
++      select SND_SOC_QCOM_COMMON
++      select SND_SOC_QCOM_SDW
+       help
+         To add support for audio on Qualcomm Technologies Inc.
+         SC8280XP SoC-based systems.
+@@ -190,7 +193,7 @@ config SND_SOC_SC7180
+       tristate "SoC Machine driver for SC7180 boards"
+       depends on I2C && GPIOLIB
+       depends on SOUNDWIRE || SOUNDWIRE=n
+-      depends on SND_SOC_QCOM_COMMON
++      select SND_SOC_QCOM_COMMON
+       select SND_SOC_LPASS_SC7180
+       select SND_SOC_MAX98357A
+       select SND_SOC_RT5682_I2C
+@@ -204,7 +207,7 @@ config SND_SOC_SC7180
+ config SND_SOC_SC7280
+       tristate "SoC Machine driver for SC7280 boards"
+       depends on I2C && SOUNDWIRE
+-      depends on SND_SOC_QCOM_COMMON
++      select SND_SOC_QCOM_COMMON
+       select SND_SOC_LPASS_SC7280
+       select SND_SOC_MAX98357A
+       select SND_SOC_WCD938X_SDW
+diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile
+index 8b97172cf990..254350d9dc06 100644
+--- a/sound/soc/qcom/Makefile
++++ b/sound/soc/qcom/Makefile
+@@ -28,6 +28,7 @@ snd-soc-sdm845-objs := sdm845.o
+ snd-soc-sm8250-objs := sm8250.o
+ snd-soc-sc8280xp-objs := sc8280xp.o
+ snd-soc-qcom-common-objs := common.o
++snd-soc-qcom-sdw-objs := sdw.o
+ obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o
+ obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o
+@@ -38,6 +39,7 @@ obj-$(CONFIG_SND_SOC_SC8280XP) += snd-soc-sc8280xp.o
+ obj-$(CONFIG_SND_SOC_SDM845) += snd-soc-sdm845.o
+ obj-$(CONFIG_SND_SOC_SM8250) += snd-soc-sm8250.o
+ obj-$(CONFIG_SND_SOC_QCOM_COMMON) += snd-soc-qcom-common.o
++obj-$(CONFIG_SND_SOC_QCOM_SDW) += snd-soc-qcom-sdw.o
+ #DSP lib
+ obj-$(CONFIG_SND_SOC_QDSP6) += qdsp6/
+diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c
+index 49c74c1662a3..96fe80241fb4 100644
+--- a/sound/soc/qcom/common.c
++++ b/sound/soc/qcom/common.c
+@@ -180,120 +180,6 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
+ }
+ EXPORT_SYMBOL_GPL(qcom_snd_parse_of);
+-int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
+-                       struct sdw_stream_runtime *sruntime,
+-                       bool *stream_prepared)
+-{
+-      struct snd_soc_pcm_runtime *rtd = substream->private_data;
+-      struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+-      int ret;
+-
+-      if (!sruntime)
+-              return 0;
+-
+-      switch (cpu_dai->id) {
+-      case WSA_CODEC_DMA_RX_0:
+-      case WSA_CODEC_DMA_RX_1:
+-      case RX_CODEC_DMA_RX_0:
+-      case RX_CODEC_DMA_RX_1:
+-      case TX_CODEC_DMA_TX_0:
+-      case TX_CODEC_DMA_TX_1:
+-      case TX_CODEC_DMA_TX_2:
+-      case TX_CODEC_DMA_TX_3:
+-              break;
+-      default:
+-              return 0;
+-      }
+-
+-      if (*stream_prepared) {
+-              sdw_disable_stream(sruntime);
+-              sdw_deprepare_stream(sruntime);
+-              *stream_prepared = false;
+-      }
+-
+-      ret = sdw_prepare_stream(sruntime);
+-      if (ret)
+-              return ret;
+-
+-      /**
+-       * NOTE: there is a strict hw requirement about the ordering of port
+-       * enables and actual WSA881x PA enable. PA enable should only happen
+-       * after soundwire ports are enabled if not DC on the line is
+-       * accumulated resulting in Click/Pop Noise
+-       * PA enable/mute are handled as part of codec DAPM and digital mute.
+-       */
+-
+-      ret = sdw_enable_stream(sruntime);
+-      if (ret) {
+-              sdw_deprepare_stream(sruntime);
+-              return ret;
+-      }
+-      *stream_prepared  = true;
+-
+-      return ret;
+-}
+-EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare);
+-
+-int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
+-                         struct snd_pcm_hw_params *params,
+-                         struct sdw_stream_runtime **psruntime)
+-{
+-      struct snd_soc_pcm_runtime *rtd = substream->private_data;
+-      struct snd_soc_dai *codec_dai;
+-      struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+-      struct sdw_stream_runtime *sruntime;
+-      int i;
+-
+-      switch (cpu_dai->id) {
+-      case WSA_CODEC_DMA_RX_0:
+-      case RX_CODEC_DMA_RX_0:
+-      case RX_CODEC_DMA_RX_1:
+-      case TX_CODEC_DMA_TX_0:
+-      case TX_CODEC_DMA_TX_1:
+-      case TX_CODEC_DMA_TX_2:
+-      case TX_CODEC_DMA_TX_3:
+-              for_each_rtd_codec_dais(rtd, i, codec_dai) {
+-                      sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
+-                      if (sruntime != ERR_PTR(-ENOTSUPP))
+-                              *psruntime = sruntime;
+-              }
+-              break;
+-      }
+-
+-      return 0;
+-
+-}
+-EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params);
+-
+-int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
+-                       struct sdw_stream_runtime *sruntime, bool *stream_prepared)
+-{
+-      struct snd_soc_pcm_runtime *rtd = substream->private_data;
+-      struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+-
+-      switch (cpu_dai->id) {
+-      case WSA_CODEC_DMA_RX_0:
+-      case WSA_CODEC_DMA_RX_1:
+-      case RX_CODEC_DMA_RX_0:
+-      case RX_CODEC_DMA_RX_1:
+-      case TX_CODEC_DMA_TX_0:
+-      case TX_CODEC_DMA_TX_1:
+-      case TX_CODEC_DMA_TX_2:
+-      case TX_CODEC_DMA_TX_3:
+-              if (sruntime && *stream_prepared) {
+-                      sdw_disable_stream(sruntime);
+-                      sdw_deprepare_stream(sruntime);
+-                      *stream_prepared = false;
+-              }
+-              break;
+-      default:
+-              break;
+-      }
+-
+-      return 0;
+-}
+-EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free);
+-
+ int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
+                           struct snd_soc_jack *jack, bool *jack_setup)
+ {
+diff --git a/sound/soc/qcom/common.h b/sound/soc/qcom/common.h
+index 3ef5bb6d12df..d7f80ee5ae26 100644
+--- a/sound/soc/qcom/common.h
++++ b/sound/soc/qcom/common.h
+@@ -5,19 +5,9 @@
+ #define __QCOM_SND_COMMON_H__
+ #include <sound/soc.h>
+-#include <linux/soundwire/sdw.h>
+ int qcom_snd_parse_of(struct snd_soc_card *card);
+ int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd,
+                           struct snd_soc_jack *jack, bool *jack_setup);
+-int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
+-                       struct sdw_stream_runtime *runtime,
+-                       bool *stream_prepared);
+-int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
+-                         struct snd_pcm_hw_params *params,
+-                         struct sdw_stream_runtime **psruntime);
+-int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
+-                       struct sdw_stream_runtime *sruntime,
+-                       bool *stream_prepared);
+ #endif
+diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c
+index ade44ad7c585..14d9fea33d16 100644
+--- a/sound/soc/qcom/sc8280xp.c
++++ b/sound/soc/qcom/sc8280xp.c
+@@ -12,6 +12,7 @@
+ #include <linux/input-event-codes.h>
+ #include "qdsp6/q6afe.h"
+ #include "common.h"
++#include "sdw.h"
+ #define DRIVER_NAME           "sc8280xp"
+diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c
+new file mode 100644
+index 000000000000..10249519a39e
+--- /dev/null
++++ b/sound/soc/qcom/sdw.c
+@@ -0,0 +1,123 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2018, Linaro Limited.
++// Copyright (c) 2018, The Linux Foundation. All rights reserved.
++
++#include <linux/module.h>
++#include <sound/soc.h>
++#include "qdsp6/q6afe.h"
++#include "sdw.h"
++
++int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
++                       struct sdw_stream_runtime *sruntime,
++                       bool *stream_prepared)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
++      int ret;
++
++      if (!sruntime)
++              return 0;
++
++      switch (cpu_dai->id) {
++      case WSA_CODEC_DMA_RX_0:
++      case WSA_CODEC_DMA_RX_1:
++      case RX_CODEC_DMA_RX_0:
++      case RX_CODEC_DMA_RX_1:
++      case TX_CODEC_DMA_TX_0:
++      case TX_CODEC_DMA_TX_1:
++      case TX_CODEC_DMA_TX_2:
++      case TX_CODEC_DMA_TX_3:
++              break;
++      default:
++              return 0;
++      }
++
++      if (*stream_prepared) {
++              sdw_disable_stream(sruntime);
++              sdw_deprepare_stream(sruntime);
++              *stream_prepared = false;
++      }
++
++      ret = sdw_prepare_stream(sruntime);
++      if (ret)
++              return ret;
++
++      /**
++       * NOTE: there is a strict hw requirement about the ordering of port
++       * enables and actual WSA881x PA enable. PA enable should only happen
++       * after soundwire ports are enabled if not DC on the line is
++       * accumulated resulting in Click/Pop Noise
++       * PA enable/mute are handled as part of codec DAPM and digital mute.
++       */
++
++      ret = sdw_enable_stream(sruntime);
++      if (ret) {
++              sdw_deprepare_stream(sruntime);
++              return ret;
++      }
++      *stream_prepared  = true;
++
++      return ret;
++}
++EXPORT_SYMBOL_GPL(qcom_snd_sdw_prepare);
++
++int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
++                         struct snd_pcm_hw_params *params,
++                         struct sdw_stream_runtime **psruntime)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_dai *codec_dai;
++      struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
++      struct sdw_stream_runtime *sruntime;
++      int i;
++
++      switch (cpu_dai->id) {
++      case WSA_CODEC_DMA_RX_0:
++      case RX_CODEC_DMA_RX_0:
++      case RX_CODEC_DMA_RX_1:
++      case TX_CODEC_DMA_TX_0:
++      case TX_CODEC_DMA_TX_1:
++      case TX_CODEC_DMA_TX_2:
++      case TX_CODEC_DMA_TX_3:
++              for_each_rtd_codec_dais(rtd, i, codec_dai) {
++                      sruntime = snd_soc_dai_get_stream(codec_dai, substream->stream);
++                      if (sruntime != ERR_PTR(-ENOTSUPP))
++                              *psruntime = sruntime;
++              }
++              break;
++      }
++
++      return 0;
++
++}
++EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params);
++
++int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
++                       struct sdw_stream_runtime *sruntime, bool *stream_prepared)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
++
++      switch (cpu_dai->id) {
++      case WSA_CODEC_DMA_RX_0:
++      case WSA_CODEC_DMA_RX_1:
++      case RX_CODEC_DMA_RX_0:
++      case RX_CODEC_DMA_RX_1:
++      case TX_CODEC_DMA_TX_0:
++      case TX_CODEC_DMA_TX_1:
++      case TX_CODEC_DMA_TX_2:
++      case TX_CODEC_DMA_TX_3:
++              if (sruntime && *stream_prepared) {
++                      sdw_disable_stream(sruntime);
++                      sdw_deprepare_stream(sruntime);
++                      *stream_prepared = false;
++              }
++              break;
++      default:
++              break;
++      }
++
++      return 0;
++}
++EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_free);
++MODULE_LICENSE("GPL v2");
+diff --git a/sound/soc/qcom/sdw.h b/sound/soc/qcom/sdw.h
+new file mode 100644
+index 000000000000..d74cbb84da13
+--- /dev/null
++++ b/sound/soc/qcom/sdw.h
+@@ -0,0 +1,18 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++// Copyright (c) 2018, The Linux Foundation. All rights reserved.
++
++#ifndef __QCOM_SND_SDW_H__
++#define __QCOM_SND_SDW_H__
++
++#include <linux/soundwire/sdw.h>
++
++int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream,
++                       struct sdw_stream_runtime *runtime,
++                       bool *stream_prepared);
++int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream,
++                         struct snd_pcm_hw_params *params,
++                         struct sdw_stream_runtime **psruntime);
++int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream,
++                       struct sdw_stream_runtime *sruntime,
++                       bool *stream_prepared);
++#endif
+diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c
+index 8dbe9ef41b1c..9626a9ef78c2 100644
+--- a/sound/soc/qcom/sm8250.c
++++ b/sound/soc/qcom/sm8250.c
+@@ -12,6 +12,7 @@
+ #include <linux/input-event-codes.h>
+ #include "qdsp6/q6afe.h"
+ #include "common.h"
++#include "sdw.h"
+ #define DRIVER_NAME           "sm8250"
+ #define MI2S_BCLK_RATE                1536000
+-- 
+2.35.1
+
diff --git a/queue-6.1/asoc-wm8904-fix-wrong-outputs-volume-after-power-rea.patch b/queue-6.1/asoc-wm8904-fix-wrong-outputs-volume-after-power-rea.patch
new file mode 100644 (file)
index 0000000..711972e
--- /dev/null
@@ -0,0 +1,69 @@
+From 74bc053eac1426389fb579efd7f2b0910f306f08 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 23 Dec 2022 09:02:47 +0100
+Subject: ASoC: wm8904: fix wrong outputs volume after power reactivation
+
+From: Emanuele Ghidoli <emanuele.ghidoli@toradex.com>
+
+[ Upstream commit 472a6309c6467af89dbf660a8310369cc9cb041f ]
+
+Restore volume after charge pump and PGA activation to ensure
+that volume settings are correctly applied when re-enabling codec
+from SND_SOC_BIAS_OFF state.
+CLASS_W, CHARGE_PUMP and POWER_MANAGEMENT_2 register configuration
+affect how the volume register are applied and must be configured first.
+
+Fixes: a91eb199e4dc ("ASoC: Initial WM8904 CODEC driver")
+Link: https://lore.kernel.org/all/c7864c35-738c-a867-a6a6-ddf9f98df7e7@gmail.com/
+Signed-off-by: Emanuele Ghidoli <emanuele.ghidoli@toradex.com>
+Signed-off-by: Francesco Dolcini <francesco.dolcini@toradex.com>
+Acked-by: Charles Keepax <ckeepax@opensource.cirrus.com>
+Link: https://lore.kernel.org/r/20221223080247.7258-1-francesco@dolcini.it
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/codecs/wm8904.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
+index ca6a01a230af..791d8738d1c0 100644
+--- a/sound/soc/codecs/wm8904.c
++++ b/sound/soc/codecs/wm8904.c
+@@ -697,6 +697,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
+       int dcs_mask;
+       int dcs_l, dcs_r;
+       int dcs_l_reg, dcs_r_reg;
++      int an_out_reg;
+       int timeout;
+       int pwr_reg;
+@@ -712,6 +713,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
+               dcs_mask = WM8904_DCS_ENA_CHAN_0 | WM8904_DCS_ENA_CHAN_1;
+               dcs_r_reg = WM8904_DC_SERVO_8;
+               dcs_l_reg = WM8904_DC_SERVO_9;
++              an_out_reg = WM8904_ANALOGUE_OUT1_LEFT;
+               dcs_l = 0;
+               dcs_r = 1;
+               break;
+@@ -720,6 +722,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
+               dcs_mask = WM8904_DCS_ENA_CHAN_2 | WM8904_DCS_ENA_CHAN_3;
+               dcs_r_reg = WM8904_DC_SERVO_6;
+               dcs_l_reg = WM8904_DC_SERVO_7;
++              an_out_reg = WM8904_ANALOGUE_OUT2_LEFT;
+               dcs_l = 2;
+               dcs_r = 3;
+               break;
+@@ -792,6 +795,10 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
+               snd_soc_component_update_bits(component, reg,
+                                   WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP,
+                                   WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP);
++
++              /* Update volume, requires PGA to be powered */
++              val = snd_soc_component_read(component, an_out_reg);
++              snd_soc_component_write(component, an_out_reg, val);
+               break;
+       case SND_SOC_DAPM_POST_PMU:
+-- 
+2.35.1
+
diff --git a/queue-6.1/blk-crypto-pass-a-gendisk-to-blk_crypto_sysfs_-un-re.patch b/queue-6.1/blk-crypto-pass-a-gendisk-to-blk_crypto_sysfs_-un-re.patch
new file mode 100644 (file)
index 0000000..fd7fe45
--- /dev/null
@@ -0,0 +1,109 @@
+From 01ffed5915ac9f8a369fd9cfacb27a20bdddafc6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Nov 2022 05:26:33 +0100
+Subject: blk-crypto: pass a gendisk to blk_crypto_sysfs_{,un}register
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 450deb93df7d457cdd93594a1987f9650c749b96 ]
+
+Prepare for changes to the block layer sysfs handling by passing the
+readily available gendisk to blk_crypto_sysfs_{,un}register.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Eric Biggers <ebiggers@google.com>
+Link: https://lore.kernel.org/r/20221114042637.1009333-2-hch@lst.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Stable-dep-of: 49e4d04f0486 ("block: Drop spurious might_sleep() from blk_put_queue()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-crypto-internal.h | 10 ++++++----
+ block/blk-crypto-sysfs.c    |  7 ++++---
+ block/blk-sysfs.c           |  4 ++--
+ 3 files changed, 12 insertions(+), 9 deletions(-)
+
+diff --git a/block/blk-crypto-internal.h b/block/blk-crypto-internal.h
+index e6818ffaddbf..b8a00847171f 100644
+--- a/block/blk-crypto-internal.h
++++ b/block/blk-crypto-internal.h
+@@ -21,9 +21,9 @@ extern const struct blk_crypto_mode blk_crypto_modes[];
+ #ifdef CONFIG_BLK_INLINE_ENCRYPTION
+-int blk_crypto_sysfs_register(struct request_queue *q);
++int blk_crypto_sysfs_register(struct gendisk *disk);
+-void blk_crypto_sysfs_unregister(struct request_queue *q);
++void blk_crypto_sysfs_unregister(struct gendisk *disk);
+ void bio_crypt_dun_increment(u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE],
+                            unsigned int inc);
+@@ -67,12 +67,14 @@ static inline bool blk_crypto_rq_is_encrypted(struct request *rq)
+ #else /* CONFIG_BLK_INLINE_ENCRYPTION */
+-static inline int blk_crypto_sysfs_register(struct request_queue *q)
++static inline int blk_crypto_sysfs_register(struct gendisk *disk)
+ {
+       return 0;
+ }
+-static inline void blk_crypto_sysfs_unregister(struct request_queue *q) { }
++static inline void blk_crypto_sysfs_unregister(struct gendisk *disk)
++{
++}
+ static inline bool bio_crypt_rq_ctx_compatible(struct request *rq,
+                                              struct bio *bio)
+diff --git a/block/blk-crypto-sysfs.c b/block/blk-crypto-sysfs.c
+index fd93bd2f33b7..e05f145cd797 100644
+--- a/block/blk-crypto-sysfs.c
++++ b/block/blk-crypto-sysfs.c
+@@ -126,8 +126,9 @@ static struct kobj_type blk_crypto_ktype = {
+  * If the request_queue has a blk_crypto_profile, create the "crypto"
+  * subdirectory in sysfs (/sys/block/$disk/queue/crypto/).
+  */
+-int blk_crypto_sysfs_register(struct request_queue *q)
++int blk_crypto_sysfs_register(struct gendisk *disk)
+ {
++      struct request_queue *q = disk->queue;
+       struct blk_crypto_kobj *obj;
+       int err;
+@@ -149,9 +150,9 @@ int blk_crypto_sysfs_register(struct request_queue *q)
+       return 0;
+ }
+-void blk_crypto_sysfs_unregister(struct request_queue *q)
++void blk_crypto_sysfs_unregister(struct gendisk *disk)
+ {
+-      kobject_put(q->crypto_kobject);
++      kobject_put(disk->queue->crypto_kobject);
+ }
+ static int __init blk_crypto_sysfs_init(void)
+diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
+index e7871665825a..2b1cf0b2a5c7 100644
+--- a/block/blk-sysfs.c
++++ b/block/blk-sysfs.c
+@@ -833,7 +833,7 @@ int blk_register_queue(struct gendisk *disk)
+                       goto put_dev;
+       }
+-      ret = blk_crypto_sysfs_register(q);
++      ret = blk_crypto_sysfs_register(disk);
+       if (ret)
+               goto put_dev;
+@@ -910,7 +910,7 @@ void blk_unregister_queue(struct gendisk *disk)
+        */
+       if (queue_is_mq(q))
+               blk_mq_sysfs_unregister(disk);
+-      blk_crypto_sysfs_unregister(q);
++      blk_crypto_sysfs_unregister(disk);
+       mutex_lock(&q->sysfs_lock);
+       elv_unregister_queue(q);
+-- 
+2.35.1
+
diff --git a/queue-6.1/blk-mq-move-the-srcu_struct-used-for-quiescing-to-th.patch b/queue-6.1/blk-mq-move-the-srcu_struct-used-for-quiescing-to-th.patch
new file mode 100644 (file)
index 0000000..37bf58b
--- /dev/null
@@ -0,0 +1,358 @@
+From bd9c3b70ef2f102bb8f8fdc9f9965b8078e21b8a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Nov 2022 16:00:47 +0100
+Subject: blk-mq: move the srcu_struct used for quiescing to the tagset
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 80bd4a7aab4c9ce59bf5e35fdf52aa23d8a3c9f5 ]
+
+All I/O submissions have fairly similar latencies, and a tagset-wide
+quiesce is a fairly common operation.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Keith Busch <kbusch@kernel.org>
+Reviewed-by: Ming Lei <ming.lei@redhat.com>
+Reviewed-by: Chao Leng <lengchao@huawei.com>
+Reviewed-by: Sagi Grimberg <sagi@grimberg.me>
+Reviewed-by: Hannes Reinecke <hare@suse.de>
+Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
+Link: https://lore.kernel.org/r/20221101150050.3510-12-hch@lst.de
+[axboe: fix whitespace]
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Stable-dep-of: 49e4d04f0486 ("block: Drop spurious might_sleep() from blk_put_queue()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-core.c       | 27 +++++----------------------
+ block/blk-mq.c         | 33 +++++++++++++++++++++++++--------
+ block/blk-mq.h         | 14 +++++++-------
+ block/blk-sysfs.c      |  9 ++-------
+ block/blk.h            |  9 +--------
+ block/genhd.c          |  2 +-
+ include/linux/blk-mq.h |  4 ++++
+ include/linux/blkdev.h |  9 ---------
+ 8 files changed, 45 insertions(+), 62 deletions(-)
+
+diff --git a/block/blk-core.c b/block/blk-core.c
+index 5487912befe8..9d6a947024ea 100644
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -65,7 +65,6 @@ DEFINE_IDA(blk_queue_ida);
+  * For queue allocation
+  */
+ struct kmem_cache *blk_requestq_cachep;
+-struct kmem_cache *blk_requestq_srcu_cachep;
+ /*
+  * Controlling structure to kblockd
+@@ -373,26 +372,20 @@ static void blk_timeout_work(struct work_struct *work)
+ {
+ }
+-struct request_queue *blk_alloc_queue(int node_id, bool alloc_srcu)
++struct request_queue *blk_alloc_queue(int node_id)
+ {
+       struct request_queue *q;
+-      q = kmem_cache_alloc_node(blk_get_queue_kmem_cache(alloc_srcu),
+-                      GFP_KERNEL | __GFP_ZERO, node_id);
++      q = kmem_cache_alloc_node(blk_requestq_cachep, GFP_KERNEL | __GFP_ZERO,
++                                node_id);
+       if (!q)
+               return NULL;
+-      if (alloc_srcu) {
+-              blk_queue_flag_set(QUEUE_FLAG_HAS_SRCU, q);
+-              if (init_srcu_struct(q->srcu) != 0)
+-                      goto fail_q;
+-      }
+-
+       q->last_merge = NULL;
+       q->id = ida_alloc(&blk_queue_ida, GFP_KERNEL);
+       if (q->id < 0)
+-              goto fail_srcu;
++              goto fail_q;
+       q->stats = blk_alloc_queue_stats();
+       if (!q->stats)
+@@ -434,11 +427,8 @@ struct request_queue *blk_alloc_queue(int node_id, bool alloc_srcu)
+       blk_free_queue_stats(q->stats);
+ fail_id:
+       ida_free(&blk_queue_ida, q->id);
+-fail_srcu:
+-      if (alloc_srcu)
+-              cleanup_srcu_struct(q->srcu);
+ fail_q:
+-      kmem_cache_free(blk_get_queue_kmem_cache(alloc_srcu), q);
++      kmem_cache_free(blk_requestq_cachep, q);
+       return NULL;
+ }
+@@ -1183,9 +1173,6 @@ int __init blk_dev_init(void)
+                       sizeof_field(struct request, cmd_flags));
+       BUILD_BUG_ON(REQ_OP_BITS + REQ_FLAG_BITS > 8 *
+                       sizeof_field(struct bio, bi_opf));
+-      BUILD_BUG_ON(ALIGN(offsetof(struct request_queue, srcu),
+-                         __alignof__(struct request_queue)) !=
+-                   sizeof(struct request_queue));
+       /* used for unplugging and affects IO latency/throughput - HIGHPRI */
+       kblockd_workqueue = alloc_workqueue("kblockd",
+@@ -1196,10 +1183,6 @@ int __init blk_dev_init(void)
+       blk_requestq_cachep = kmem_cache_create("request_queue",
+                       sizeof(struct request_queue), 0, SLAB_PANIC, NULL);
+-      blk_requestq_srcu_cachep = kmem_cache_create("request_queue_srcu",
+-                      sizeof(struct request_queue) +
+-                      sizeof(struct srcu_struct), 0, SLAB_PANIC, NULL);
+-
+       blk_debugfs_root = debugfs_create_dir("block", NULL);
+       return 0;
+diff --git a/block/blk-mq.c b/block/blk-mq.c
+index 0b855e033a83..a23026099284 100644
+--- a/block/blk-mq.c
++++ b/block/blk-mq.c
+@@ -261,8 +261,8 @@ EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue_nowait);
+  */
+ void blk_mq_wait_quiesce_done(struct request_queue *q)
+ {
+-      if (blk_queue_has_srcu(q))
+-              synchronize_srcu(q->srcu);
++      if (q->tag_set->flags & BLK_MQ_F_BLOCKING)
++              synchronize_srcu(q->tag_set->srcu);
+       else
+               synchronize_rcu();
+ }
+@@ -4007,7 +4007,7 @@ static struct request_queue *blk_mq_init_queue_data(struct blk_mq_tag_set *set,
+       struct request_queue *q;
+       int ret;
+-      q = blk_alloc_queue(set->numa_node, set->flags & BLK_MQ_F_BLOCKING);
++      q = blk_alloc_queue(set->numa_node);
+       if (!q)
+               return ERR_PTR(-ENOMEM);
+       q->queuedata = queuedata;
+@@ -4179,9 +4179,6 @@ static void blk_mq_update_poll_flag(struct request_queue *q)
+ int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
+               struct request_queue *q)
+ {
+-      WARN_ON_ONCE(blk_queue_has_srcu(q) !=
+-                      !!(set->flags & BLK_MQ_F_BLOCKING));
+-
+       /* mark the queue as mq asap */
+       q->mq_ops = set->ops;
+@@ -4438,8 +4435,18 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
+       if (set->nr_maps == 1 && set->nr_hw_queues > nr_cpu_ids)
+               set->nr_hw_queues = nr_cpu_ids;
+-      if (blk_mq_alloc_tag_set_tags(set, set->nr_hw_queues) < 0)
+-              return -ENOMEM;
++      if (set->flags & BLK_MQ_F_BLOCKING) {
++              set->srcu = kmalloc(sizeof(*set->srcu), GFP_KERNEL);
++              if (!set->srcu)
++                      return -ENOMEM;
++              ret = init_srcu_struct(set->srcu);
++              if (ret)
++                      goto out_free_srcu;
++      }
++
++      ret = blk_mq_alloc_tag_set_tags(set, set->nr_hw_queues);
++      if (ret)
++              goto out_cleanup_srcu;
+       ret = -ENOMEM;
+       for (i = 0; i < set->nr_maps; i++) {
+@@ -4469,6 +4476,12 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
+       }
+       kfree(set->tags);
+       set->tags = NULL;
++out_cleanup_srcu:
++      if (set->flags & BLK_MQ_F_BLOCKING)
++              cleanup_srcu_struct(set->srcu);
++out_free_srcu:
++      if (set->flags & BLK_MQ_F_BLOCKING)
++              kfree(set->srcu);
+       return ret;
+ }
+ EXPORT_SYMBOL(blk_mq_alloc_tag_set);
+@@ -4508,6 +4521,10 @@ void blk_mq_free_tag_set(struct blk_mq_tag_set *set)
+       kfree(set->tags);
+       set->tags = NULL;
++      if (set->flags & BLK_MQ_F_BLOCKING) {
++              cleanup_srcu_struct(set->srcu);
++              kfree(set->srcu);
++      }
+ }
+ EXPORT_SYMBOL(blk_mq_free_tag_set);
+diff --git a/block/blk-mq.h b/block/blk-mq.h
+index 0b2870839cdd..ef59fee62780 100644
+--- a/block/blk-mq.h
++++ b/block/blk-mq.h
+@@ -377,17 +377,17 @@ static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx,
+ /* run the code block in @dispatch_ops with rcu/srcu read lock held */
+ #define __blk_mq_run_dispatch_ops(q, check_sleep, dispatch_ops)       \
+ do {                                                          \
+-      if (!blk_queue_has_srcu(q)) {                           \
+-              rcu_read_lock();                                \
+-              (dispatch_ops);                                 \
+-              rcu_read_unlock();                              \
+-      } else {                                                \
++      if ((q)->tag_set->flags & BLK_MQ_F_BLOCKING) {          \
+               int srcu_idx;                                   \
+                                                               \
+               might_sleep_if(check_sleep);                    \
+-              srcu_idx = srcu_read_lock((q)->srcu);           \
++              srcu_idx = srcu_read_lock((q)->tag_set->srcu);  \
+               (dispatch_ops);                                 \
+-              srcu_read_unlock((q)->srcu, srcu_idx);          \
++              srcu_read_unlock((q)->tag_set->srcu, srcu_idx); \
++      } else {                                                \
++              rcu_read_lock();                                \
++              (dispatch_ops);                                 \
++              rcu_read_unlock();                              \
+       }                                                       \
+ } while (0)
+diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
+index e71b3b43927c..e7871665825a 100644
+--- a/block/blk-sysfs.c
++++ b/block/blk-sysfs.c
+@@ -739,10 +739,8 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
+ static void blk_free_queue_rcu(struct rcu_head *rcu_head)
+ {
+-      struct request_queue *q = container_of(rcu_head, struct request_queue,
+-                                             rcu_head);
+-
+-      kmem_cache_free(blk_get_queue_kmem_cache(blk_queue_has_srcu(q)), q);
++      kmem_cache_free(blk_requestq_cachep,
++                      container_of(rcu_head, struct request_queue, rcu_head));
+ }
+ /**
+@@ -779,9 +777,6 @@ static void blk_release_queue(struct kobject *kobj)
+       if (queue_is_mq(q))
+               blk_mq_release(q);
+-      if (blk_queue_has_srcu(q))
+-              cleanup_srcu_struct(q->srcu);
+-
+       ida_free(&blk_queue_ida, q->id);
+       call_rcu(&q->rcu_head, blk_free_queue_rcu);
+ }
+diff --git a/block/blk.h b/block/blk.h
+index 8b75a95b28d6..0661fa4b3a4d 100644
+--- a/block/blk.h
++++ b/block/blk.h
+@@ -27,7 +27,6 @@ struct blk_flush_queue {
+ };
+ extern struct kmem_cache *blk_requestq_cachep;
+-extern struct kmem_cache *blk_requestq_srcu_cachep;
+ extern struct kobj_type blk_queue_ktype;
+ extern struct ida blk_queue_ida;
+@@ -428,13 +427,7 @@ int bio_add_hw_page(struct request_queue *q, struct bio *bio,
+               struct page *page, unsigned int len, unsigned int offset,
+               unsigned int max_sectors, bool *same_page);
+-static inline struct kmem_cache *blk_get_queue_kmem_cache(bool srcu)
+-{
+-      if (srcu)
+-              return blk_requestq_srcu_cachep;
+-      return blk_requestq_cachep;
+-}
+-struct request_queue *blk_alloc_queue(int node_id, bool alloc_srcu);
++struct request_queue *blk_alloc_queue(int node_id);
+ int disk_scan_partitions(struct gendisk *disk, fmode_t mode, void *owner);
+diff --git a/block/genhd.c b/block/genhd.c
+index c4765681a8b4..f4f3f3b55634 100644
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -1417,7 +1417,7 @@ struct gendisk *__blk_alloc_disk(int node, struct lock_class_key *lkclass)
+       struct request_queue *q;
+       struct gendisk *disk;
+-      q = blk_alloc_queue(node, false);
++      q = blk_alloc_queue(node);
+       if (!q)
+               return NULL;
+diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
+index d6119c5d1069..2952c28410e3 100644
+--- a/include/linux/blk-mq.h
++++ b/include/linux/blk-mq.h
+@@ -7,6 +7,7 @@
+ #include <linux/lockdep.h>
+ #include <linux/scatterlist.h>
+ #include <linux/prefetch.h>
++#include <linux/srcu.h>
+ struct blk_mq_tags;
+ struct blk_flush_queue;
+@@ -501,6 +502,8 @@ enum hctx_type {
+  * @tag_list_lock: Serializes tag_list accesses.
+  * @tag_list:    List of the request queues that use this tag set. See also
+  *               request_queue.tag_set_list.
++ * @srcu:        Use as lock when type of the request queue is blocking
++ *               (BLK_MQ_F_BLOCKING).
+  */
+ struct blk_mq_tag_set {
+       struct blk_mq_queue_map map[HCTX_MAX_TYPES];
+@@ -521,6 +524,7 @@ struct blk_mq_tag_set {
+       struct mutex            tag_list_lock;
+       struct list_head        tag_list;
++      struct srcu_struct      *srcu;
+ };
+ /**
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 891f8cbcd043..36c286d22fb2 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -22,7 +22,6 @@
+ #include <linux/blkzoned.h>
+ #include <linux/sched.h>
+ #include <linux/sbitmap.h>
+-#include <linux/srcu.h>
+ #include <linux/uuid.h>
+ #include <linux/xarray.h>
+@@ -544,18 +543,11 @@ struct request_queue {
+       struct mutex            debugfs_mutex;
+       bool                    mq_sysfs_init_done;
+-
+-      /**
+-       * @srcu: Sleepable RCU. Use as lock when type of the request queue
+-       * is blocking (BLK_MQ_F_BLOCKING). Must be the last member
+-       */
+-      struct srcu_struct      srcu[];
+ };
+ /* Keep blk_queue_flag_name[] in sync with the definitions below */
+ #define QUEUE_FLAG_STOPPED    0       /* queue is stopped */
+ #define QUEUE_FLAG_DYING      1       /* queue being torn down */
+-#define QUEUE_FLAG_HAS_SRCU   2       /* SRCU is allocated */
+ #define QUEUE_FLAG_NOMERGES     3     /* disable merge attempts */
+ #define QUEUE_FLAG_SAME_COMP  4       /* complete on same CPU-group */
+ #define QUEUE_FLAG_FAIL_IO    5       /* fake timeout */
+@@ -591,7 +583,6 @@ bool blk_queue_flag_test_and_set(unsigned int flag, struct request_queue *q);
+ #define blk_queue_stopped(q)  test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags)
+ #define blk_queue_dying(q)    test_bit(QUEUE_FLAG_DYING, &(q)->queue_flags)
+-#define blk_queue_has_srcu(q) test_bit(QUEUE_FLAG_HAS_SRCU, &(q)->queue_flags)
+ #define blk_queue_init_done(q)        test_bit(QUEUE_FLAG_INIT_DONE, &(q)->queue_flags)
+ #define blk_queue_nomerges(q) test_bit(QUEUE_FLAG_NOMERGES, &(q)->queue_flags)
+ #define blk_queue_noxmerges(q)        \
+-- 
+2.35.1
+
diff --git a/queue-6.1/block-drop-spurious-might_sleep-from-blk_put_queue.patch b/queue-6.1/block-drop-spurious-might_sleep-from-blk_put_queue.patch
new file mode 100644 (file)
index 0000000..78c39bc
--- /dev/null
@@ -0,0 +1,62 @@
+From dd1460786ec68b9d790823779b75d4ec8e8a118a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Jan 2023 10:34:10 -1000
+Subject: block: Drop spurious might_sleep() from blk_put_queue()
+
+From: Tejun Heo <tj@kernel.org>
+
+[ Upstream commit 49e4d04f0486117ac57a97890eb1db6d52bf82b3 ]
+
+Dan reports the following smatch detected the following:
+
+  block/blk-cgroup.c:1863 blkcg_schedule_throttle() warn: sleeping in atomic context
+
+caused by blkcg_schedule_throttle() calling blk_put_queue() in an
+non-sleepable context.
+
+blk_put_queue() acquired might_sleep() in 63f93fd6fa57 ("block: mark
+blk_put_queue as potentially blocking") which transferred the might_sleep()
+from blk_free_queue().
+
+blk_free_queue() acquired might_sleep() in e8c7d14ac6c3 ("block: revert back
+to synchronous request_queue removal") while turning request_queue removal
+synchronous. However, this isn't necessary as nothing in the free path
+actually requires sleeping.
+
+It's pretty unusual to require a sleeping context in a put operation and
+it's not needed in the first place. Let's drop it.
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: Dan Carpenter <error27@gmail.com>
+Link: https://lkml.kernel.org/r/Y7g3L6fntnTtOm63@kili
+Cc: Christoph Hellwig <hch@lst.de>
+Cc: Luis Chamberlain <mcgrof@kernel.org>
+Fixes: e8c7d14ac6c3 ("block: revert back to synchronous request_queue removal") # v5.9+
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/Y7iFwjN+XzWvLv3y@slm.duckdns.org
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-core.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/block/blk-core.c b/block/blk-core.c
+index 815ffce6b988..f5ae527fb0c3 100644
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -282,12 +282,9 @@ static void blk_free_queue(struct request_queue *q)
+  *
+  * Decrements the refcount of the request_queue and free it when the refcount
+  * reaches 0.
+- *
+- * Context: Can sleep.
+  */
+ void blk_put_queue(struct request_queue *q)
+ {
+-      might_sleep();
+       if (refcount_dec_and_test(&q->refs))
+               blk_free_queue(q);
+ }
+-- 
+2.35.1
+
diff --git a/queue-6.1/block-factor-out-a-blk_debugfs_remove-helper.patch b/queue-6.1/block-factor-out-a-blk_debugfs_remove-helper.patch
new file mode 100644 (file)
index 0000000..9a5dc1c
--- /dev/null
@@ -0,0 +1,61 @@
+From a470755911a1d91ec554013211b835d0032051ab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Nov 2022 05:26:34 +0100
+Subject: block: factor out a blk_debugfs_remove helper
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 6fc75f309d291d328b4ea2f91bef0ff56e4bc7c2 ]
+
+Split the debugfs removal from blk_unregister_queue into a helper so that
+the it can be reused for blk_register_queue error handling.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/20221114042637.1009333-3-hch@lst.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Stable-dep-of: 49e4d04f0486 ("block: Drop spurious might_sleep() from blk_put_queue()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-sysfs.c | 21 ++++++++++++++-------
+ 1 file changed, 14 insertions(+), 7 deletions(-)
+
+diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
+index 2b1cf0b2a5c7..3d6951a0b4e7 100644
+--- a/block/blk-sysfs.c
++++ b/block/blk-sysfs.c
+@@ -797,6 +797,19 @@ struct kobj_type blk_queue_ktype = {
+       .release        = blk_release_queue,
+ };
++static void blk_debugfs_remove(struct gendisk *disk)
++{
++      struct request_queue *q = disk->queue;
++
++      mutex_lock(&q->debugfs_mutex);
++      blk_trace_shutdown(q);
++      debugfs_remove_recursive(q->debugfs_dir);
++      q->debugfs_dir = NULL;
++      q->sched_debugfs_dir = NULL;
++      q->rqos_debugfs_dir = NULL;
++      mutex_unlock(&q->debugfs_mutex);
++}
++
+ /**
+  * blk_register_queue - register a block layer queue with sysfs
+  * @disk: Disk of which the request queue should be registered with sysfs.
+@@ -922,11 +935,5 @@ void blk_unregister_queue(struct gendisk *disk)
+       kobject_del(&q->kobj);
+       mutex_unlock(&q->sysfs_dir_lock);
+-      mutex_lock(&q->debugfs_mutex);
+-      blk_trace_shutdown(q);
+-      debugfs_remove_recursive(q->debugfs_dir);
+-      q->debugfs_dir = NULL;
+-      q->sched_debugfs_dir = NULL;
+-      q->rqos_debugfs_dir = NULL;
+-      mutex_unlock(&q->debugfs_mutex);
++      blk_debugfs_remove(disk);
+ }
+-- 
+2.35.1
+
diff --git a/queue-6.1/block-fix-error-unwinding-in-blk_register_queue.patch b/queue-6.1/block-fix-error-unwinding-in-blk_register_queue.patch
new file mode 100644 (file)
index 0000000..f5d83fa
--- /dev/null
@@ -0,0 +1,101 @@
+From 92de18c2eb61fd698c0eb9163a508e1be7e7aea3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Nov 2022 05:26:35 +0100
+Subject: block: fix error unwinding in blk_register_queue
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 40602997be26887bdfa3d58659c3acb4579099e9 ]
+
+blk_register_queue fails to handle errors from blk_mq_sysfs_register,
+leaks various resources on errors and accidentally sets queue refs percpu
+refcount to percpu mode on kobject_add failure.  Fix all that by
+properly unwinding on errors.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/20221114042637.1009333-4-hch@lst.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Stable-dep-of: 49e4d04f0486 ("block: Drop spurious might_sleep() from blk_put_queue()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-sysfs.c | 28 ++++++++++++++++------------
+ 1 file changed, 16 insertions(+), 12 deletions(-)
+
+diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
+index 3d6951a0b4e7..1631ba2f7259 100644
+--- a/block/blk-sysfs.c
++++ b/block/blk-sysfs.c
+@@ -820,13 +820,15 @@ int blk_register_queue(struct gendisk *disk)
+       int ret;
+       mutex_lock(&q->sysfs_dir_lock);
+-
+       ret = kobject_add(&q->kobj, &disk_to_dev(disk)->kobj, "queue");
+       if (ret < 0)
+-              goto unlock;
++              goto out_unlock_dir;
+-      if (queue_is_mq(q))
+-              blk_mq_sysfs_register(disk);
++      if (queue_is_mq(q)) {
++              ret = blk_mq_sysfs_register(disk);
++              if (ret)
++                      goto out_del_queue_kobj;
++      }
+       mutex_lock(&q->sysfs_lock);
+       mutex_lock(&q->debugfs_mutex);
+@@ -838,17 +840,17 @@ int blk_register_queue(struct gendisk *disk)
+       ret = disk_register_independent_access_ranges(disk);
+       if (ret)
+-              goto put_dev;
++              goto out_debugfs_remove;
+       if (q->elevator) {
+               ret = elv_register_queue(q, false);
+               if (ret)
+-                      goto put_dev;
++                      goto out_unregister_ia_ranges;
+       }
+       ret = blk_crypto_sysfs_register(disk);
+       if (ret)
+-              goto put_dev;
++              goto out_elv_unregister;
+       blk_queue_flag_set(QUEUE_FLAG_REGISTERED, q);
+       wbt_enable_default(q);
+@@ -859,8 +861,6 @@ int blk_register_queue(struct gendisk *disk)
+       if (q->elevator)
+               kobject_uevent(&q->elevator->kobj, KOBJ_ADD);
+       mutex_unlock(&q->sysfs_lock);
+-
+-unlock:
+       mutex_unlock(&q->sysfs_dir_lock);
+       /*
+@@ -879,13 +879,17 @@ int blk_register_queue(struct gendisk *disk)
+       return ret;
+-put_dev:
++out_elv_unregister:
+       elv_unregister_queue(q);
++out_unregister_ia_ranges:
+       disk_unregister_independent_access_ranges(disk);
++out_debugfs_remove:
++      blk_debugfs_remove(disk);
+       mutex_unlock(&q->sysfs_lock);
+-      mutex_unlock(&q->sysfs_dir_lock);
++out_del_queue_kobj:
+       kobject_del(&q->kobj);
+-
++out_unlock_dir:
++      mutex_unlock(&q->sysfs_dir_lock);
+       return ret;
+ }
+-- 
+2.35.1
+
diff --git a/queue-6.1/block-mark-blk_put_queue-as-potentially-blocking.patch b/queue-6.1/block-mark-blk_put_queue-as-potentially-blocking.patch
new file mode 100644 (file)
index 0000000..6957d4a
--- /dev/null
@@ -0,0 +1,52 @@
+From 1ec7de36d3a9c53347ce5a07ffdfabc14ebed66b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Nov 2022 05:26:37 +0100
+Subject: block: mark blk_put_queue as potentially blocking
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 63f93fd6fa5717769a78d6d7bea6f7f9a1ccca8e ]
+
+We can't just say that the last reference release may block, as any
+reference dropped could be the last one.  So move the might_sleep() from
+blk_free_queue to blk_put_queue and update the documentation.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/20221114042637.1009333-6-hch@lst.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Stable-dep-of: 49e4d04f0486 ("block: Drop spurious might_sleep() from blk_put_queue()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-core.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/block/blk-core.c b/block/blk-core.c
+index 7de1bb16e9a7..815ffce6b988 100644
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -260,8 +260,6 @@ static void blk_free_queue_rcu(struct rcu_head *rcu_head)
+ static void blk_free_queue(struct request_queue *q)
+ {
+-      might_sleep();
+-
+       percpu_ref_exit(&q->q_usage_counter);
+       if (q->poll_stat)
+@@ -285,11 +283,11 @@ static void blk_free_queue(struct request_queue *q)
+  * Decrements the refcount of the request_queue and free it when the refcount
+  * reaches 0.
+  *
+- * Context: Any context, but the last reference must not be dropped from
+- *          atomic context.
++ * Context: Can sleep.
+  */
+ void blk_put_queue(struct request_queue *q)
+ {
++      might_sleep();
+       if (refcount_dec_and_test(&q->refs))
+               blk_free_queue(q);
+ }
+-- 
+2.35.1
+
diff --git a/queue-6.1/block-untangle-request_queue-refcounting-from-sysfs.patch b/queue-6.1/block-untangle-request_queue-refcounting-from-sysfs.patch
new file mode 100644 (file)
index 0000000..082e6f6
--- /dev/null
@@ -0,0 +1,400 @@
+From 8f978e86b17108d8f596f9b036e512b38e67a1de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Nov 2022 05:26:36 +0100
+Subject: block: untangle request_queue refcounting from sysfs
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 2bd85221a625b316114bafaab527770b607095d3 ]
+
+The kobject embedded into the request_queue is used for the queue
+directory in sysfs, but that is a child of the gendisks directory and is
+intimately tied to it.  Move this kobject to the gendisk and use a
+refcount_t in the request_queue for the actual request_queue refcounting
+that is completely unrelated to the device model.
+
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/20221114042637.1009333-5-hch@lst.de
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Stable-dep-of: 49e4d04f0486 ("block: Drop spurious might_sleep() from blk_put_queue()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ block/blk-core.c         | 42 ++++++++++++++++----
+ block/blk-crypto-sysfs.c |  4 +-
+ block/blk-ia-ranges.c    |  3 +-
+ block/blk-sysfs.c        | 86 +++++++++++-----------------------------
+ block/blk.h              |  4 --
+ block/bsg.c              | 11 +++--
+ block/elevator.c         |  2 +-
+ include/linux/blkdev.h   |  6 +--
+ 8 files changed, 71 insertions(+), 87 deletions(-)
+
+diff --git a/block/blk-core.c b/block/blk-core.c
+index 9d6a947024ea..7de1bb16e9a7 100644
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -59,12 +59,12 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(block_split);
+ EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug);
+ EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_insert);
+-DEFINE_IDA(blk_queue_ida);
++static DEFINE_IDA(blk_queue_ida);
+ /*
+  * For queue allocation
+  */
+-struct kmem_cache *blk_requestq_cachep;
++static struct kmem_cache *blk_requestq_cachep;
+ /*
+  * Controlling structure to kblockd
+@@ -252,19 +252,46 @@ void blk_clear_pm_only(struct request_queue *q)
+ }
+ EXPORT_SYMBOL_GPL(blk_clear_pm_only);
++static void blk_free_queue_rcu(struct rcu_head *rcu_head)
++{
++      kmem_cache_free(blk_requestq_cachep,
++                      container_of(rcu_head, struct request_queue, rcu_head));
++}
++
++static void blk_free_queue(struct request_queue *q)
++{
++      might_sleep();
++
++      percpu_ref_exit(&q->q_usage_counter);
++
++      if (q->poll_stat)
++              blk_stat_remove_callback(q, q->poll_cb);
++      blk_stat_free_callback(q->poll_cb);
++
++      blk_free_queue_stats(q->stats);
++      kfree(q->poll_stat);
++
++      if (queue_is_mq(q))
++              blk_mq_release(q);
++
++      ida_free(&blk_queue_ida, q->id);
++      call_rcu(&q->rcu_head, blk_free_queue_rcu);
++}
++
+ /**
+  * blk_put_queue - decrement the request_queue refcount
+  * @q: the request_queue structure to decrement the refcount for
+  *
+- * Decrements the refcount of the request_queue kobject. When this reaches 0
+- * we'll have blk_release_queue() called.
++ * Decrements the refcount of the request_queue and free it when the refcount
++ * reaches 0.
+  *
+  * Context: Any context, but the last reference must not be dropped from
+  *          atomic context.
+  */
+ void blk_put_queue(struct request_queue *q)
+ {
+-      kobject_put(&q->kobj);
++      if (refcount_dec_and_test(&q->refs))
++              blk_free_queue(q);
+ }
+ EXPORT_SYMBOL(blk_put_queue);
+@@ -399,8 +426,7 @@ struct request_queue *blk_alloc_queue(int node_id)
+       INIT_WORK(&q->timeout_work, blk_timeout_work);
+       INIT_LIST_HEAD(&q->icq_list);
+-      kobject_init(&q->kobj, &blk_queue_ktype);
+-
++      refcount_set(&q->refs, 1);
+       mutex_init(&q->debugfs_mutex);
+       mutex_init(&q->sysfs_lock);
+       mutex_init(&q->sysfs_dir_lock);
+@@ -444,7 +470,7 @@ bool blk_get_queue(struct request_queue *q)
+ {
+       if (unlikely(blk_queue_dying(q)))
+               return false;
+-      kobject_get(&q->kobj);
++      refcount_inc(&q->refs);
+       return true;
+ }
+ EXPORT_SYMBOL(blk_get_queue);
+diff --git a/block/blk-crypto-sysfs.c b/block/blk-crypto-sysfs.c
+index e05f145cd797..55268edc0625 100644
+--- a/block/blk-crypto-sysfs.c
++++ b/block/blk-crypto-sysfs.c
+@@ -140,8 +140,8 @@ int blk_crypto_sysfs_register(struct gendisk *disk)
+               return -ENOMEM;
+       obj->profile = q->crypto_profile;
+-      err = kobject_init_and_add(&obj->kobj, &blk_crypto_ktype, &q->kobj,
+-                                 "crypto");
++      err = kobject_init_and_add(&obj->kobj, &blk_crypto_ktype,
++                                 &disk->queue_kobj, "crypto");
+       if (err) {
+               kobject_put(&obj->kobj);
+               return err;
+diff --git a/block/blk-ia-ranges.c b/block/blk-ia-ranges.c
+index 2bd1d311033b..2141931ddd37 100644
+--- a/block/blk-ia-ranges.c
++++ b/block/blk-ia-ranges.c
+@@ -123,7 +123,8 @@ int disk_register_independent_access_ranges(struct gendisk *disk)
+        */
+       WARN_ON(iars->sysfs_registered);
+       ret = kobject_init_and_add(&iars->kobj, &blk_ia_ranges_ktype,
+-                                 &q->kobj, "%s", "independent_access_ranges");
++                                 &disk->queue_kobj, "%s",
++                                 "independent_access_ranges");
+       if (ret) {
+               disk->ia_ranges = NULL;
+               kobject_put(&iars->kobj);
+diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
+index 1631ba2f7259..35e854bb6e0c 100644
+--- a/block/blk-sysfs.c
++++ b/block/blk-sysfs.c
+@@ -680,8 +680,8 @@ static struct attribute *queue_attrs[] = {
+ static umode_t queue_attr_visible(struct kobject *kobj, struct attribute *attr,
+                               int n)
+ {
+-      struct request_queue *q =
+-              container_of(kobj, struct request_queue, kobj);
++      struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj);
++      struct request_queue *q = disk->queue;
+       if (attr == &queue_io_timeout_entry.attr &&
+               (!q->mq_ops || !q->mq_ops->timeout))
+@@ -707,8 +707,8 @@ static ssize_t
+ queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
+ {
+       struct queue_sysfs_entry *entry = to_queue(attr);
+-      struct request_queue *q =
+-              container_of(kobj, struct request_queue, kobj);
++      struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj);
++      struct request_queue *q = disk->queue;
+       ssize_t res;
+       if (!entry->show)
+@@ -724,63 +724,19 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
+                   const char *page, size_t length)
+ {
+       struct queue_sysfs_entry *entry = to_queue(attr);
+-      struct request_queue *q;
++      struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj);
++      struct request_queue *q = disk->queue;
+       ssize_t res;
+       if (!entry->store)
+               return -EIO;
+-      q = container_of(kobj, struct request_queue, kobj);
+       mutex_lock(&q->sysfs_lock);
+       res = entry->store(q, page, length);
+       mutex_unlock(&q->sysfs_lock);
+       return res;
+ }
+-static void blk_free_queue_rcu(struct rcu_head *rcu_head)
+-{
+-      kmem_cache_free(blk_requestq_cachep,
+-                      container_of(rcu_head, struct request_queue, rcu_head));
+-}
+-
+-/**
+- * blk_release_queue - releases all allocated resources of the request_queue
+- * @kobj: pointer to a kobject, whose container is a request_queue
+- *
+- * This function releases all allocated resources of the request queue.
+- *
+- * The struct request_queue refcount is incremented with blk_get_queue() and
+- * decremented with blk_put_queue(). Once the refcount reaches 0 this function
+- * is called.
+- *
+- * Drivers exist which depend on the release of the request_queue to be
+- * synchronous, it should not be deferred.
+- *
+- * Context: can sleep
+- */
+-static void blk_release_queue(struct kobject *kobj)
+-{
+-      struct request_queue *q =
+-              container_of(kobj, struct request_queue, kobj);
+-
+-      might_sleep();
+-
+-      percpu_ref_exit(&q->q_usage_counter);
+-
+-      if (q->poll_stat)
+-              blk_stat_remove_callback(q, q->poll_cb);
+-      blk_stat_free_callback(q->poll_cb);
+-
+-      blk_free_queue_stats(q->stats);
+-      kfree(q->poll_stat);
+-
+-      if (queue_is_mq(q))
+-              blk_mq_release(q);
+-
+-      ida_free(&blk_queue_ida, q->id);
+-      call_rcu(&q->rcu_head, blk_free_queue_rcu);
+-}
+-
+ static const struct sysfs_ops queue_sysfs_ops = {
+       .show   = queue_attr_show,
+       .store  = queue_attr_store,
+@@ -791,10 +747,15 @@ static const struct attribute_group *blk_queue_attr_groups[] = {
+       NULL
+ };
+-struct kobj_type blk_queue_ktype = {
++static void blk_queue_release(struct kobject *kobj)
++{
++      /* nothing to do here, all data is associated with the parent gendisk */
++}
++
++static struct kobj_type blk_queue_ktype = {
+       .default_groups = blk_queue_attr_groups,
+       .sysfs_ops      = &queue_sysfs_ops,
+-      .release        = blk_release_queue,
++      .release        = blk_queue_release,
+ };
+ static void blk_debugfs_remove(struct gendisk *disk)
+@@ -820,20 +781,20 @@ int blk_register_queue(struct gendisk *disk)
+       int ret;
+       mutex_lock(&q->sysfs_dir_lock);
+-      ret = kobject_add(&q->kobj, &disk_to_dev(disk)->kobj, "queue");
++      kobject_init(&disk->queue_kobj, &blk_queue_ktype);
++      ret = kobject_add(&disk->queue_kobj, &disk_to_dev(disk)->kobj, "queue");
+       if (ret < 0)
+-              goto out_unlock_dir;
++              goto out_put_queue_kobj;
+       if (queue_is_mq(q)) {
+               ret = blk_mq_sysfs_register(disk);
+               if (ret)
+-                      goto out_del_queue_kobj;
++                      goto out_put_queue_kobj;
+       }
+       mutex_lock(&q->sysfs_lock);
+       mutex_lock(&q->debugfs_mutex);
+-      q->debugfs_dir = debugfs_create_dir(kobject_name(q->kobj.parent),
+-                                          blk_debugfs_root);
++      q->debugfs_dir = debugfs_create_dir(disk->disk_name, blk_debugfs_root);
+       if (queue_is_mq(q))
+               blk_mq_debugfs_register(q);
+       mutex_unlock(&q->debugfs_mutex);
+@@ -857,7 +818,7 @@ int blk_register_queue(struct gendisk *disk)
+       blk_throtl_register(disk);
+       /* Now everything is ready and send out KOBJ_ADD uevent */
+-      kobject_uevent(&q->kobj, KOBJ_ADD);
++      kobject_uevent(&disk->queue_kobj, KOBJ_ADD);
+       if (q->elevator)
+               kobject_uevent(&q->elevator->kobj, KOBJ_ADD);
+       mutex_unlock(&q->sysfs_lock);
+@@ -886,9 +847,8 @@ int blk_register_queue(struct gendisk *disk)
+ out_debugfs_remove:
+       blk_debugfs_remove(disk);
+       mutex_unlock(&q->sysfs_lock);
+-out_del_queue_kobj:
+-      kobject_del(&q->kobj);
+-out_unlock_dir:
++out_put_queue_kobj:
++      kobject_put(&disk->queue_kobj);
+       mutex_unlock(&q->sysfs_dir_lock);
+       return ret;
+ }
+@@ -935,8 +895,8 @@ void blk_unregister_queue(struct gendisk *disk)
+       mutex_unlock(&q->sysfs_lock);
+       /* Now that we've deleted all child objects, we can delete the queue. */
+-      kobject_uevent(&q->kobj, KOBJ_REMOVE);
+-      kobject_del(&q->kobj);
++      kobject_uevent(&disk->queue_kobj, KOBJ_REMOVE);
++      kobject_del(&disk->queue_kobj);
+       mutex_unlock(&q->sysfs_dir_lock);
+       blk_debugfs_remove(disk);
+diff --git a/block/blk.h b/block/blk.h
+index 0661fa4b3a4d..6fe583dd6e3b 100644
+--- a/block/blk.h
++++ b/block/blk.h
+@@ -26,10 +26,6 @@ struct blk_flush_queue {
+       spinlock_t              mq_flush_lock;
+ };
+-extern struct kmem_cache *blk_requestq_cachep;
+-extern struct kobj_type blk_queue_ktype;
+-extern struct ida blk_queue_ida;
+-
+ bool is_flush_rq(struct request *req);
+ struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,
+diff --git a/block/bsg.c b/block/bsg.c
+index 2ab1351eb082..8eba57b9bb46 100644
+--- a/block/bsg.c
++++ b/block/bsg.c
+@@ -175,8 +175,10 @@ static void bsg_device_release(struct device *dev)
+ void bsg_unregister_queue(struct bsg_device *bd)
+ {
+-      if (bd->queue->kobj.sd)
+-              sysfs_remove_link(&bd->queue->kobj, "bsg");
++      struct gendisk *disk = bd->queue->disk;
++
++      if (disk && disk->queue_kobj.sd)
++              sysfs_remove_link(&disk->queue_kobj, "bsg");
+       cdev_device_del(&bd->cdev, &bd->device);
+       put_device(&bd->device);
+ }
+@@ -216,8 +218,9 @@ struct bsg_device *bsg_register_queue(struct request_queue *q,
+       if (ret)
+               goto out_put_device;
+-      if (q->kobj.sd) {
+-              ret = sysfs_create_link(&q->kobj, &bd->device.kobj, "bsg");
++      if (q->disk && q->disk->queue_kobj.sd) {
++              ret = sysfs_create_link(&q->disk->queue_kobj, &bd->device.kobj,
++                                      "bsg");
+               if (ret)
+                       goto out_device_del;
+       }
+diff --git a/block/elevator.c b/block/elevator.c
+index bd71f0fc4e4b..ac096f494911 100644
+--- a/block/elevator.c
++++ b/block/elevator.c
+@@ -499,7 +499,7 @@ int elv_register_queue(struct request_queue *q, bool uevent)
+       lockdep_assert_held(&q->sysfs_lock);
+-      error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched");
++      error = kobject_add(&e->kobj, &q->disk->queue_kobj, "iosched");
+       if (!error) {
+               struct elv_fs_entry *attr = e->type->elevator_attrs;
+               if (attr) {
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 36c286d22fb2..17dc59c5aa90 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -155,6 +155,7 @@ struct gendisk {
+       unsigned open_partitions;       /* number of open partitions */
+       struct backing_dev_info *bdi;
++      struct kobject queue_kobj;      /* the queue/ directory */
+       struct kobject *slave_dir;
+ #ifdef CONFIG_BLOCK_HOLDER_DEPRECATED
+       struct list_head slave_bdevs;
+@@ -437,10 +438,7 @@ struct request_queue {
+       struct gendisk          *disk;
+-      /*
+-       * queue kobject
+-       */
+-      struct kobject kobj;
++      refcount_t              refs;
+       /*
+        * mq queue kobject
+-- 
+2.35.1
+
diff --git a/queue-6.1/bnxt-make-sure-we-return-pages-to-the-pool.patch b/queue-6.1/bnxt-make-sure-we-return-pages-to-the-pool.patch
new file mode 100644 (file)
index 0000000..b732a09
--- /dev/null
@@ -0,0 +1,52 @@
+From 55174d10e4cfab4b9ed03b61aef0d9f127b45a3a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Jan 2023 20:25:47 -0800
+Subject: bnxt: make sure we return pages to the pool
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit 97f5e03a4a27d27ee4fed0cdb1658c81cf2784db ]
+
+Before the commit under Fixes the page would have been released
+from the pool before the napi_alloc_skb() call, so normal page
+freeing was fine (released page == no longer in the pool).
+
+After the change we just mark the page for recycling so it's still
+in the pool if the skb alloc fails, we need to recycle.
+
+Same commit added the same bug in the new bnxt_rx_multi_page_skb().
+
+Fixes: 1dc4c557bfed ("bnxt: adding bnxt_xdp_build_skb to build skb from multibuffer xdp_buff")
+Reviewed-by: Andy Gospodarek <gospo@broadcom.com>
+Link: https://lore.kernel.org/r/20230111042547.987749-1-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index f5a8bae8d79a..edca16b5f9e3 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -990,7 +990,7 @@ static struct sk_buff *bnxt_rx_multi_page_skb(struct bnxt *bp,
+                            DMA_ATTR_WEAK_ORDERING);
+       skb = build_skb(page_address(page), PAGE_SIZE);
+       if (!skb) {
+-              __free_page(page);
++              page_pool_recycle_direct(rxr->page_pool, page);
+               return NULL;
+       }
+       skb_mark_for_recycle(skb);
+@@ -1028,7 +1028,7 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp,
+       skb = napi_alloc_skb(&rxr->bnapi->napi, payload);
+       if (!skb) {
+-              __free_page(page);
++              page_pool_recycle_direct(rxr->page_pool, page);
+               return NULL;
+       }
+-- 
+2.35.1
+
diff --git a/queue-6.1/drm-amdgpu-fix-potential-null-dereference.patch b/queue-6.1/drm-amdgpu-fix-potential-null-dereference.patch
new file mode 100644 (file)
index 0000000..73aa60a
--- /dev/null
@@ -0,0 +1,48 @@
+From 1cbce5ec8e6ce678d060ef683b45499b2972704b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Jan 2023 17:09:02 -0500
+Subject: drm/amdgpu: Fix potential NULL dereference
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Luben Tuikov <luben.tuikov@amd.com>
+
+[ Upstream commit 0be7ed8e7eb15282b5d0f6fdfea884db594ea9bf ]
+
+Fix potential NULL dereference, in the case when "man", the resource manager
+might be NULL, when/if we print debug information.
+
+Cc: Alex Deucher <Alexander.Deucher@amd.com>
+Cc: Christian König <christian.koenig@amd.com>
+Cc: AMD Graphics <amd-gfx@lists.freedesktop.org>
+Cc: Dan Carpenter <error27@gmail.com>
+Cc: kernel test robot <lkp@intel.com>
+Fixes: 7554886daa31ea ("drm/amdgpu: Fix size validation for non-exclusive domains (v4)")
+Signed-off-by: Luben Tuikov <luben.tuikov@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+index 3be3cba3a16d..cfd78c4a45ba 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+@@ -468,8 +468,9 @@ static bool amdgpu_bo_validate_size(struct amdgpu_device *adev,
+       return true;
+ fail:
+-      DRM_DEBUG("BO size %lu > total memory in domain: %llu\n", size,
+-                man->size);
++      if (man)
++              DRM_DEBUG("BO size %lu > total memory in domain: %llu\n", size,
++                        man->size);
+       return false;
+ }
+-- 
+2.35.1
+
diff --git a/queue-6.1/drm-msm-dpu-fix-memory-leak-in-msm_mdss_parse_data_b.patch b/queue-6.1/drm-msm-dpu-fix-memory-leak-in-msm_mdss_parse_data_b.patch
new file mode 100644 (file)
index 0000000..301beda
--- /dev/null
@@ -0,0 +1,52 @@
+From 3c3debecffc9122efce64174d9841f64bb7aeb25 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Dec 2022 10:59:22 +0400
+Subject: drm/msm/dpu: Fix memory leak in msm_mdss_parse_data_bus_icc_path
+
+From: Miaoqian Lin <linmq006@gmail.com>
+
+[ Upstream commit 45dac1352b55b1d8cb17f218936b2bc2bc1fb4ee ]
+
+of_icc_get() alloc resources for path1, we should release it when not
+need anymore. Early return when IS_ERR_OR_NULL(path0) may leak path1.
+Defer getting path1 to fix this.
+
+Fixes: b9364eed9232 ("drm/msm/dpu: Move min BW request and full BW disable back to mdss")
+Signed-off-by: Miaoqian Lin <linmq006@gmail.com>
+Reviewed-by: Douglas Anderson <dianders@chromium.org>
+Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Patchwork: https://patchwork.freedesktop.org/patch/514264/
+Link: https://lore.kernel.org/r/20221207065922.2086368-1-linmq006@gmail.com
+Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/msm_mdss.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
+index e13c5c12b775..3b8d6991b04e 100644
+--- a/drivers/gpu/drm/msm/msm_mdss.c
++++ b/drivers/gpu/drm/msm/msm_mdss.c
+@@ -46,15 +46,17 @@ struct msm_mdss {
+ static int msm_mdss_parse_data_bus_icc_path(struct device *dev,
+                                           struct msm_mdss *msm_mdss)
+ {
+-      struct icc_path *path0 = of_icc_get(dev, "mdp0-mem");
+-      struct icc_path *path1 = of_icc_get(dev, "mdp1-mem");
++      struct icc_path *path0;
++      struct icc_path *path1;
++      path0 = of_icc_get(dev, "mdp0-mem");
+       if (IS_ERR_OR_NULL(path0))
+               return PTR_ERR_OR_ZERO(path0);
+       msm_mdss->path[0] = path0;
+       msm_mdss->num_paths = 1;
++      path1 = of_icc_get(dev, "mdp1-mem");
+       if (!IS_ERR_OR_NULL(path1)) {
+               msm_mdss->path[1] = path1;
+               msm_mdss->num_paths++;
+-- 
+2.35.1
+
diff --git a/queue-6.1/drm-msm-dpu-fix-some-kernel-doc-comments.patch b/queue-6.1/drm-msm-dpu-fix-some-kernel-doc-comments.patch
new file mode 100644 (file)
index 0000000..b09ff2e
--- /dev/null
@@ -0,0 +1,54 @@
+From d9af0a8f4b170f972d9240218e251b2760a86a9d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Nov 2022 09:49:02 +0800
+Subject: drm/msm/dpu: Fix some kernel-doc comments
+
+From: Yang Li <yang.lee@linux.alibaba.com>
+
+[ Upstream commit 1bdeb321d1f856346fe0078af09c9e7ffbd2ca7a ]
+
+Make the description of @init to @p in dpu_encoder_phys_wb_init()
+and remove @wb_roi in dpu_encoder_phys_wb_setup_fb() to clear the below
+warnings:
+
+drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c:139: warning: Excess function parameter 'wb_roi' description in 'dpu_encoder_phys_wb_setup_fb'
+drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c:699: warning: Function parameter or member 'p' not described in 'dpu_encoder_phys_wb_init'
+drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c:699: warning: Excess function parameter 'init' description in 'dpu_encoder_phys_wb_init'
+
+Link: https://bugzilla.openanolis.cn/show_bug.cgi?id=3067
+Reported-by: Abaci Robot <abaci@linux.alibaba.com>
+Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
+Fixes: d7d0e73f7de3 ("drm/msm/dpu: introduce the dpu_encoder_phys_* for writeback")
+Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Patchwork: https://patchwork.freedesktop.org/patch/511605/
+Link: https://lore.kernel.org/r/20221115014902.45240-1-yang.lee@linux.alibaba.com
+Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+index 7cbcef6efe17..62f6ff6abf41 100644
+--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
++++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+@@ -132,7 +132,6 @@ static void dpu_encoder_phys_wb_set_qos(struct dpu_encoder_phys *phys_enc)
+  * dpu_encoder_phys_wb_setup_fb - setup output framebuffer
+  * @phys_enc: Pointer to physical encoder
+  * @fb:               Pointer to output framebuffer
+- * @wb_roi:   Pointer to output region of interest
+  */
+ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc,
+               struct drm_framebuffer *fb)
+@@ -692,7 +691,7 @@ static void dpu_encoder_phys_wb_init_ops(struct dpu_encoder_phys_ops *ops)
+ /**
+  * dpu_encoder_phys_wb_init - initialize writeback encoder
+- * @init:     Pointer to init info structure with initialization params
++ * @p:        Pointer to init info structure with initialization params
+  */
+ struct dpu_encoder_phys *dpu_encoder_phys_wb_init(
+               struct dpu_enc_phys_init_params *p)
+-- 
+2.35.1
+
diff --git a/queue-6.1/drm-vmwgfx-refactor-resource-manager-s-hashtable-to-.patch b/queue-6.1/drm-vmwgfx-refactor-resource-manager-s-hashtable-to-.patch
new file mode 100644 (file)
index 0000000..0544db1
--- /dev/null
@@ -0,0 +1,203 @@
+From 9ee285c12d8374ed6c57615766c1e1b4ddf8152f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Oct 2022 00:02:22 -0400
+Subject: drm/vmwgfx: Refactor resource manager's hashtable to use
+ linux/hashtable implementation.
+
+From: Maaz Mombasawala <mombasawalam@vmware.com>
+
+[ Upstream commit 43531dc661b7fb6be249c023bf25847b38215545 ]
+
+Vmwgfx's hashtab implementation needs to be replaced with linux/hashtable
+to reduce maintenance burden.
+Refactor cmdbuf resource manager to use linux/hashtable.h implementation
+as part of this effort.
+
+Signed-off-by: Maaz Mombasawala <mombasawalam@vmware.com>
+Reviewed-by: Zack Rusin <zackr@vmware.com>
+Reviewed-by: Martin Krastev <krastevm@vmware.com>
+Signed-off-by: Zack Rusin <zackr@vmware.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20221022040236.616490-4-zack@kde.org
+Stable-dep-of: a309c7194e8a ("drm/vmwgfx: Remove rcu locks from user resources")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c | 62 +++++++++-------------
+ 1 file changed, 26 insertions(+), 36 deletions(-)
+
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
+index 82ef58ccdd42..142aef686fcd 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0 OR MIT
+ /**************************************************************************
+  *
+- * Copyright 2014-2015 VMware, Inc., Palo Alto, CA., USA
++ * Copyright 2014-2022 VMware, Inc., Palo Alto, CA., USA
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a
+  * copy of this software and associated documentation files (the
+@@ -28,6 +28,8 @@
+ #include "vmwgfx_drv.h"
+ #include "vmwgfx_resource_priv.h"
++#include <linux/hashtable.h>
++
+ #define VMW_CMDBUF_RES_MAN_HT_ORDER 12
+ /**
+@@ -59,7 +61,7 @@ struct vmw_cmdbuf_res {
+  * @resources and @list are protected by the cmdbuf mutex for now.
+  */
+ struct vmw_cmdbuf_res_manager {
+-      struct vmwgfx_open_hash resources;
++      DECLARE_HASHTABLE(resources, VMW_CMDBUF_RES_MAN_HT_ORDER);
+       struct list_head list;
+       struct vmw_private *dev_priv;
+ };
+@@ -82,14 +84,13 @@ vmw_cmdbuf_res_lookup(struct vmw_cmdbuf_res_manager *man,
+                     u32 user_key)
+ {
+       struct vmwgfx_hash_item *hash;
+-      int ret;
+       unsigned long key = user_key | (res_type << 24);
+-      ret = vmwgfx_ht_find_item(&man->resources, key, &hash);
+-      if (unlikely(ret != 0))
+-              return ERR_PTR(ret);
+-
+-      return drm_hash_entry(hash, struct vmw_cmdbuf_res, hash)->res;
++      hash_for_each_possible_rcu(man->resources, hash, head, key) {
++              if (hash->key == key)
++                      return drm_hash_entry(hash, struct vmw_cmdbuf_res, hash)->res;
++      }
++      return ERR_PTR(-EINVAL);
+ }
+ /**
+@@ -105,7 +106,7 @@ static void vmw_cmdbuf_res_free(struct vmw_cmdbuf_res_manager *man,
+                               struct vmw_cmdbuf_res *entry)
+ {
+       list_del(&entry->head);
+-      WARN_ON(vmwgfx_ht_remove_item(&man->resources, &entry->hash));
++      hash_del_rcu(&entry->hash.head);
+       vmw_resource_unreference(&entry->res);
+       kfree(entry);
+ }
+@@ -159,7 +160,6 @@ void vmw_cmdbuf_res_commit(struct list_head *list)
+ void vmw_cmdbuf_res_revert(struct list_head *list)
+ {
+       struct vmw_cmdbuf_res *entry, *next;
+-      int ret;
+       list_for_each_entry_safe(entry, next, list, head) {
+               switch (entry->state) {
+@@ -167,8 +167,8 @@ void vmw_cmdbuf_res_revert(struct list_head *list)
+                       vmw_cmdbuf_res_free(entry->man, entry);
+                       break;
+               case VMW_CMDBUF_RES_DEL:
+-                      ret = vmwgfx_ht_insert_item(&entry->man->resources, &entry->hash);
+-                      BUG_ON(ret);
++                      hash_add_rcu(entry->man->resources, &entry->hash.head,
++                                              entry->hash.key);
+                       list_move_tail(&entry->head, &entry->man->list);
+                       entry->state = VMW_CMDBUF_RES_COMMITTED;
+                       break;
+@@ -199,26 +199,20 @@ int vmw_cmdbuf_res_add(struct vmw_cmdbuf_res_manager *man,
+                      struct list_head *list)
+ {
+       struct vmw_cmdbuf_res *cres;
+-      int ret;
+       cres = kzalloc(sizeof(*cres), GFP_KERNEL);
+       if (unlikely(!cres))
+               return -ENOMEM;
+       cres->hash.key = user_key | (res_type << 24);
+-      ret = vmwgfx_ht_insert_item(&man->resources, &cres->hash);
+-      if (unlikely(ret != 0)) {
+-              kfree(cres);
+-              goto out_invalid_key;
+-      }
++      hash_add_rcu(man->resources, &cres->hash.head, cres->hash.key);
+       cres->state = VMW_CMDBUF_RES_ADD;
+       cres->res = vmw_resource_reference(res);
+       cres->man = man;
+       list_add_tail(&cres->head, list);
+-out_invalid_key:
+-      return ret;
++      return 0;
+ }
+ /**
+@@ -243,24 +237,26 @@ int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man,
+                         struct list_head *list,
+                         struct vmw_resource **res_p)
+ {
+-      struct vmw_cmdbuf_res *entry;
++      struct vmw_cmdbuf_res *entry = NULL;
+       struct vmwgfx_hash_item *hash;
+-      int ret;
++      unsigned long key = user_key | (res_type << 24);
+-      ret = vmwgfx_ht_find_item(&man->resources, user_key | (res_type << 24),
+-                             &hash);
+-      if (likely(ret != 0))
++      hash_for_each_possible_rcu(man->resources, hash, head, key) {
++              if (hash->key == key) {
++                      entry = drm_hash_entry(hash, struct vmw_cmdbuf_res, hash);
++                      break;
++              }
++      }
++      if (unlikely(!entry))
+               return -EINVAL;
+-      entry = drm_hash_entry(hash, struct vmw_cmdbuf_res, hash);
+-
+       switch (entry->state) {
+       case VMW_CMDBUF_RES_ADD:
+               vmw_cmdbuf_res_free(man, entry);
+               *res_p = NULL;
+               break;
+       case VMW_CMDBUF_RES_COMMITTED:
+-              (void) vmwgfx_ht_remove_item(&man->resources, &entry->hash);
++              hash_del_rcu(&entry->hash.head);
+               list_del(&entry->head);
+               entry->state = VMW_CMDBUF_RES_DEL;
+               list_add_tail(&entry->head, list);
+@@ -287,7 +283,6 @@ struct vmw_cmdbuf_res_manager *
+ vmw_cmdbuf_res_man_create(struct vmw_private *dev_priv)
+ {
+       struct vmw_cmdbuf_res_manager *man;
+-      int ret;
+       man = kzalloc(sizeof(*man), GFP_KERNEL);
+       if (!man)
+@@ -295,12 +290,8 @@ vmw_cmdbuf_res_man_create(struct vmw_private *dev_priv)
+       man->dev_priv = dev_priv;
+       INIT_LIST_HEAD(&man->list);
+-      ret = vmwgfx_ht_create(&man->resources, VMW_CMDBUF_RES_MAN_HT_ORDER);
+-      if (ret == 0)
+-              return man;
+-
+-      kfree(man);
+-      return ERR_PTR(ret);
++      hash_init(man->resources);
++      return man;
+ }
+ /**
+@@ -320,7 +311,6 @@ void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man)
+       list_for_each_entry_safe(entry, next, &man->list, head)
+               vmw_cmdbuf_res_free(man, entry);
+-      vmwgfx_ht_remove(&man->resources);
+       kfree(man);
+ }
+-- 
+2.35.1
+
diff --git a/queue-6.1/drm-vmwgfx-refactor-resource-validation-hashtable-to.patch b/queue-6.1/drm-vmwgfx-refactor-resource-validation-hashtable-to.patch
new file mode 100644 (file)
index 0000000..9d764a8
--- /dev/null
@@ -0,0 +1,382 @@
+From d8260b86aa4503b7be4800e358ea5bf589b71e52 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Oct 2022 00:02:24 -0400
+Subject: drm/vmwgfx: Refactor resource validation hashtable to use
+ linux/hashtable implementation.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Maaz Mombasawala <mombasawalam@vmware.com>
+
+[ Upstream commit 9e931f2e09701e25744f3d186a4ba13b5342b136 ]
+
+Vmwgfx's hashtab implementation needs to be replaced with linux/hashtable
+to reduce maintenence burden.
+As part of this effort, refactor the res_ht hashtable used for resource
+validation during execbuf execution to use linux/hashtable implementation.
+This also refactors vmw_validation_context to use vmw_sw_context as the
+container for the hashtable, whereas before it used a vmwgfx_open_hash
+directly. This makes vmw_validation_context less generic, but there is
+no functional change since res_ht is the only instance where validation
+context used a hashtable in vmwgfx driver.
+
+Signed-off-by: Maaz Mombasawala <mombasawalam@vmware.com>
+Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
+Signed-off-by: Zack Rusin <zackr@vmware.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20221022040236.616490-6-zack@kde.org
+Stable-dep-of: a309c7194e8a ("drm/vmwgfx: Remove rcu locks from user resources")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c        | 24 ++++++++--
+ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h        |  5 +-
+ drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c    | 14 ++----
+ drivers/gpu/drm/vmwgfx/vmwgfx_validation.c | 55 +++++++++++-----------
+ drivers/gpu/drm/vmwgfx/vmwgfx_validation.h | 26 +++-------
+ 5 files changed, 58 insertions(+), 66 deletions(-)
+
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+index 13b90273eb77..8d77e79bd904 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+@@ -830,6 +830,22 @@ static void vmw_write_driver_id(struct vmw_private *dev)
+       }
+ }
++static void vmw_sw_context_init(struct vmw_private *dev_priv)
++{
++      struct vmw_sw_context *sw_context = &dev_priv->ctx;
++
++      hash_init(sw_context->res_ht);
++}
++
++static void vmw_sw_context_fini(struct vmw_private *dev_priv)
++{
++      struct vmw_sw_context *sw_context = &dev_priv->ctx;
++
++      vfree(sw_context->cmd_bounce);
++      if (sw_context->staged_bindings)
++              vmw_binding_state_free(sw_context->staged_bindings);
++}
++
+ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
+ {
+       int ret;
+@@ -839,6 +855,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
+       dev_priv->drm.dev_private = dev_priv;
++      vmw_sw_context_init(dev_priv);
++
+       mutex_init(&dev_priv->cmdbuf_mutex);
+       mutex_init(&dev_priv->binding_mutex);
+       spin_lock_init(&dev_priv->resource_lock);
+@@ -1168,9 +1186,7 @@ static void vmw_driver_unload(struct drm_device *dev)
+       unregister_pm_notifier(&dev_priv->pm_nb);
+-      if (dev_priv->ctx.res_ht_initialized)
+-              vmwgfx_ht_remove(&dev_priv->ctx.res_ht);
+-      vfree(dev_priv->ctx.cmd_bounce);
++      vmw_sw_context_fini(dev_priv);
+       if (dev_priv->enable_fb) {
+               vmw_fb_off(dev_priv);
+               vmw_fb_close(dev_priv);
+@@ -1198,8 +1214,6 @@ static void vmw_driver_unload(struct drm_device *dev)
+               vmw_irq_uninstall(&dev_priv->drm);
+       ttm_object_device_release(&dev_priv->tdev);
+-      if (dev_priv->ctx.staged_bindings)
+-              vmw_binding_state_free(dev_priv->ctx.staged_bindings);
+       for (i = vmw_res_context; i < vmw_res_max; ++i)
+               idr_destroy(&dev_priv->res_idr[i]);
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+index 09e2d738aa87..d87aeedb78d0 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+@@ -30,6 +30,7 @@
+ #include <linux/suspend.h>
+ #include <linux/sync_file.h>
++#include <linux/hashtable.h>
+ #include <drm/drm_auth.h>
+ #include <drm/drm_device.h>
+@@ -93,6 +94,7 @@
+ #define VMW_RES_STREAM ttm_driver_type2
+ #define VMW_RES_FENCE ttm_driver_type3
+ #define VMW_RES_SHADER ttm_driver_type4
++#define VMW_RES_HT_ORDER 12
+ #define MKSSTAT_CAPACITY_LOG2 5U
+ #define MKSSTAT_CAPACITY (1U << MKSSTAT_CAPACITY_LOG2)
+@@ -425,8 +427,7 @@ struct vmw_ctx_validation_info;
+  * @ctx: The validation context
+  */
+ struct vmw_sw_context{
+-      struct vmwgfx_open_hash res_ht;
+-      bool res_ht_initialized;
++      DECLARE_HASHTABLE(res_ht, VMW_RES_HT_ORDER);
+       bool kernel;
+       struct vmw_fpriv *fp;
+       struct drm_file *filp;
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+index f085dbd4736d..c943ab801ca7 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0 OR MIT
+ /**************************************************************************
+  *
+- * Copyright 2009 - 2015 VMware, Inc., Palo Alto, CA., USA
++ * Copyright 2009 - 2022 VMware, Inc., Palo Alto, CA., USA
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a
+  * copy of this software and associated documentation files (the
+@@ -25,6 +25,7 @@
+  *
+  **************************************************************************/
+ #include <linux/sync_file.h>
++#include <linux/hashtable.h>
+ #include "vmwgfx_drv.h"
+ #include "vmwgfx_reg.h"
+@@ -34,7 +35,6 @@
+ #include "vmwgfx_binding.h"
+ #include "vmwgfx_mksstat.h"
+-#define VMW_RES_HT_ORDER 12
+ /*
+  * Helper macro to get dx_ctx_node if available otherwise print an error
+@@ -4101,7 +4101,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
+       int ret;
+       int32_t out_fence_fd = -1;
+       struct sync_file *sync_file = NULL;
+-      DECLARE_VAL_CONTEXT(val_ctx, &sw_context->res_ht, 1);
++      DECLARE_VAL_CONTEXT(val_ctx, sw_context, 1);
+       if (flags & DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD) {
+               out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
+@@ -4164,14 +4164,6 @@ int vmw_execbuf_process(struct drm_file *file_priv,
+       if (sw_context->staged_bindings)
+               vmw_binding_state_reset(sw_context->staged_bindings);
+-      if (!sw_context->res_ht_initialized) {
+-              ret = vmwgfx_ht_create(&sw_context->res_ht, VMW_RES_HT_ORDER);
+-              if (unlikely(ret != 0))
+-                      goto out_unlock;
+-
+-              sw_context->res_ht_initialized = true;
+-      }
+-
+       INIT_LIST_HEAD(&sw_context->staged_cmd_res);
+       sw_context->ctx = &val_ctx;
+       ret = vmw_execbuf_tie_context(dev_priv, sw_context, dx_context_handle);
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c
+index f46891012be3..f5c4a40fb16d 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c
+@@ -1,7 +1,7 @@
+ // SPDX-License-Identifier: GPL-2.0 OR MIT
+ /**************************************************************************
+  *
+- * Copyright © 2018 VMware, Inc., Palo Alto, CA., USA
++ * Copyright © 2018 - 2022 VMware, Inc., Palo Alto, CA., USA
+  * All Rights Reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a
+@@ -180,11 +180,16 @@ vmw_validation_find_bo_dup(struct vmw_validation_context *ctx,
+       if (!ctx->merge_dups)
+               return NULL;
+-      if (ctx->ht) {
++      if (ctx->sw_context) {
+               struct vmwgfx_hash_item *hash;
++              unsigned long key = (unsigned long) vbo;
+-              if (!vmwgfx_ht_find_item(ctx->ht, (unsigned long) vbo, &hash))
+-                      bo_node = container_of(hash, typeof(*bo_node), hash);
++              hash_for_each_possible_rcu(ctx->sw_context->res_ht, hash, head, key) {
++                      if (hash->key == key) {
++                              bo_node = container_of(hash, typeof(*bo_node), hash);
++                              break;
++                      }
++              }
+       } else {
+               struct  vmw_validation_bo_node *entry;
+@@ -217,11 +222,16 @@ vmw_validation_find_res_dup(struct vmw_validation_context *ctx,
+       if (!ctx->merge_dups)
+               return NULL;
+-      if (ctx->ht) {
++      if (ctx->sw_context) {
+               struct vmwgfx_hash_item *hash;
++              unsigned long key = (unsigned long) res;
+-              if (!vmwgfx_ht_find_item(ctx->ht, (unsigned long) res, &hash))
+-                      res_node = container_of(hash, typeof(*res_node), hash);
++              hash_for_each_possible_rcu(ctx->sw_context->res_ht, hash, head, key) {
++                      if (hash->key == key) {
++                              res_node = container_of(hash, typeof(*res_node), hash);
++                              break;
++                      }
++              }
+       } else {
+               struct  vmw_validation_res_node *entry;
+@@ -269,20 +279,15 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx,
+               }
+       } else {
+               struct ttm_validate_buffer *val_buf;
+-              int ret;
+               bo_node = vmw_validation_mem_alloc(ctx, sizeof(*bo_node));
+               if (!bo_node)
+                       return -ENOMEM;
+-              if (ctx->ht) {
++              if (ctx->sw_context) {
+                       bo_node->hash.key = (unsigned long) vbo;
+-                      ret = vmwgfx_ht_insert_item(ctx->ht, &bo_node->hash);
+-                      if (ret) {
+-                              DRM_ERROR("Failed to initialize a buffer "
+-                                        "validation entry.\n");
+-                              return ret;
+-                      }
++                      hash_add_rcu(ctx->sw_context->res_ht, &bo_node->hash.head,
++                              bo_node->hash.key);
+               }
+               val_buf = &bo_node->base;
+               val_buf->bo = ttm_bo_get_unless_zero(&vbo->base);
+@@ -316,7 +321,6 @@ int vmw_validation_add_resource(struct vmw_validation_context *ctx,
+                               bool *first_usage)
+ {
+       struct vmw_validation_res_node *node;
+-      int ret;
+       node = vmw_validation_find_res_dup(ctx, res);
+       if (node) {
+@@ -330,14 +334,9 @@ int vmw_validation_add_resource(struct vmw_validation_context *ctx,
+               return -ENOMEM;
+       }
+-      if (ctx->ht) {
++      if (ctx->sw_context) {
+               node->hash.key = (unsigned long) res;
+-              ret = vmwgfx_ht_insert_item(ctx->ht, &node->hash);
+-              if (ret) {
+-                      DRM_ERROR("Failed to initialize a resource validation "
+-                                "entry.\n");
+-                      return ret;
+-              }
++              hash_add_rcu(ctx->sw_context->res_ht, &node->hash.head, node->hash.key);
+       }
+       node->res = vmw_resource_reference_unless_doomed(res);
+       if (!node->res)
+@@ -681,19 +680,19 @@ void vmw_validation_drop_ht(struct vmw_validation_context *ctx)
+       struct vmw_validation_bo_node *entry;
+       struct vmw_validation_res_node *val;
+-      if (!ctx->ht)
++      if (!ctx->sw_context)
+               return;
+       list_for_each_entry(entry, &ctx->bo_list, base.head)
+-              (void) vmwgfx_ht_remove_item(ctx->ht, &entry->hash);
++              hash_del_rcu(&entry->hash.head);
+       list_for_each_entry(val, &ctx->resource_list, head)
+-              (void) vmwgfx_ht_remove_item(ctx->ht, &val->hash);
++              hash_del_rcu(&val->hash.head);
+       list_for_each_entry(val, &ctx->resource_ctx_list, head)
+-              (void) vmwgfx_ht_remove_item(ctx->ht, &val->hash);
++              hash_del_rcu(&entry->hash.head);
+-      ctx->ht = NULL;
++      ctx->sw_context = NULL;
+ }
+ /**
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h
+index f21df053882b..ab9ec226f433 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h
+@@ -1,7 +1,7 @@
+ /* SPDX-License-Identifier: GPL-2.0 OR MIT */
+ /**************************************************************************
+  *
+- * Copyright © 2018 VMware, Inc., Palo Alto, CA., USA
++ * Copyright © 2018 - 2022 VMware, Inc., Palo Alto, CA., USA
+  * All Rights Reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a
+@@ -29,12 +29,11 @@
+ #define _VMWGFX_VALIDATION_H_
+ #include <linux/list.h>
++#include <linux/hashtable.h>
+ #include <linux/ww_mutex.h>
+ #include <drm/ttm/ttm_execbuf_util.h>
+-#include "vmwgfx_hashtab.h"
+-
+ #define VMW_RES_DIRTY_NONE 0
+ #define VMW_RES_DIRTY_SET BIT(0)
+ #define VMW_RES_DIRTY_CLEAR BIT(1)
+@@ -59,7 +58,7 @@
+  * @total_mem: Amount of reserved memory.
+  */
+ struct vmw_validation_context {
+-      struct vmwgfx_open_hash *ht;
++      struct vmw_sw_context *sw_context;
+       struct list_head resource_list;
+       struct list_head resource_ctx_list;
+       struct list_head bo_list;
+@@ -82,16 +81,16 @@ struct vmw_fence_obj;
+ /**
+  * DECLARE_VAL_CONTEXT - Declare a validation context with initialization
+  * @_name: The name of the variable
+- * @_ht: The hash table used to find dups or NULL if none
++ * @_sw_context: Contains the hash table used to find dups or NULL if none
+  * @_merge_dups: Whether to merge duplicate buffer object- or resource
+  * entries. If set to true, ideally a hash table pointer should be supplied
+  * as well unless the number of resources and buffer objects per validation
+  * is known to be very small
+  */
+ #endif
+-#define DECLARE_VAL_CONTEXT(_name, _ht, _merge_dups)                  \
++#define DECLARE_VAL_CONTEXT(_name, _sw_context, _merge_dups)          \
+       struct vmw_validation_context _name =                           \
+-      { .ht = _ht,                                                    \
++      { .sw_context = _sw_context,                                    \
+         .resource_list = LIST_HEAD_INIT((_name).resource_list),       \
+         .resource_ctx_list = LIST_HEAD_INIT((_name).resource_ctx_list), \
+         .bo_list = LIST_HEAD_INIT((_name).bo_list),                   \
+@@ -114,19 +113,6 @@ vmw_validation_has_bos(struct vmw_validation_context *ctx)
+       return !list_empty(&ctx->bo_list);
+ }
+-/**
+- * vmw_validation_set_ht - Register a hash table for duplicate finding
+- * @ctx: The validation context
+- * @ht: Pointer to a hash table to use for duplicate finding
+- * This function is intended to be used if the hash table wasn't
+- * available at validation context declaration time
+- */
+-static inline void vmw_validation_set_ht(struct vmw_validation_context *ctx,
+-                                       struct vmwgfx_open_hash *ht)
+-{
+-      ctx->ht = ht;
+-}
+-
+ /**
+  * vmw_validation_bo_reserve - Reserve buffer objects registered with a
+  * validation context
+-- 
+2.35.1
+
diff --git a/queue-6.1/drm-vmwgfx-refactor-ttm-reference-object-hashtable-t.patch b/queue-6.1/drm-vmwgfx-refactor-ttm-reference-object-hashtable-t.patch
new file mode 100644 (file)
index 0000000..5e77a3e
--- /dev/null
@@ -0,0 +1,324 @@
+From 59ec46a84315d9b16c024bb045be0e48785c49b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Oct 2022 00:02:29 -0400
+Subject: drm/vmwgfx: Refactor ttm reference object hashtable to use
+ linux/hashtable.
+
+From: Maaz Mombasawala <mombasawalam@vmware.com>
+
+[ Upstream commit 76a9e07f270cf5fb556ac237dbf11f5dacd61fef ]
+
+This is part of an effort to move from the vmwgfx_open_hash hashtable to
+linux/hashtable implementation.
+Refactor the ref_hash hashtable, used for fast lookup of reference objects
+associated with a ttm file.
+This also exposed a problem related to inconsistently using 32-bit and
+64-bit keys with this hashtable. The hash function used changes depending
+on the size of the type, and results are not consistent across numbers,
+for example, hash_32(329) = 329, but hash_long(329) = 328. This would
+cause the lookup to fail for objects already in the hashtable, since keys
+of different sizes were being passed during adding and lookup. This was
+not an issue before because vmwgfx_open_hash always used hash_long.
+Fix this by always using 64-bit keys for this hashtable, which means that
+hash_long is always used.
+
+Signed-off-by: Maaz Mombasawala <mombasawalam@vmware.com>
+Reviewed-by: Zack Rusin <zackr@vmware.com>
+Signed-off-by: Zack Rusin <zackr@vmware.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20221022040236.616490-11-zack@kde.org
+Stable-dep-of: a309c7194e8a ("drm/vmwgfx: Remove rcu locks from user resources")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/vmwgfx/ttm_object.c | 91 ++++++++++++++++-------------
+ drivers/gpu/drm/vmwgfx/ttm_object.h | 12 ++--
+ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c |  2 +-
+ 3 files changed, 56 insertions(+), 49 deletions(-)
+
+diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.c b/drivers/gpu/drm/vmwgfx/ttm_object.c
+index 9546b121bc22..c07b81fbc495 100644
+--- a/drivers/gpu/drm/vmwgfx/ttm_object.c
++++ b/drivers/gpu/drm/vmwgfx/ttm_object.c
+@@ -52,9 +52,12 @@
+ #include <linux/slab.h>
+ #include <linux/atomic.h>
+ #include <linux/module.h>
++#include <linux/hashtable.h>
+ MODULE_IMPORT_NS(DMA_BUF);
++#define VMW_TTM_OBJECT_REF_HT_ORDER 10
++
+ /**
+  * struct ttm_object_file
+  *
+@@ -75,7 +78,7 @@ struct ttm_object_file {
+       struct ttm_object_device *tdev;
+       spinlock_t lock;
+       struct list_head ref_list;
+-      struct vmwgfx_open_hash ref_hash;
++      DECLARE_HASHTABLE(ref_hash, VMW_TTM_OBJECT_REF_HT_ORDER);
+       struct kref refcount;
+ };
+@@ -136,6 +139,36 @@ ttm_object_file_ref(struct ttm_object_file *tfile)
+       return tfile;
+ }
++static int ttm_tfile_find_ref_rcu(struct ttm_object_file *tfile,
++                                uint64_t key,
++                                struct vmwgfx_hash_item **p_hash)
++{
++      struct vmwgfx_hash_item *hash;
++
++      hash_for_each_possible_rcu(tfile->ref_hash, hash, head, key) {
++              if (hash->key == key) {
++                      *p_hash = hash;
++                      return 0;
++              }
++      }
++      return -EINVAL;
++}
++
++static int ttm_tfile_find_ref(struct ttm_object_file *tfile,
++                            uint64_t key,
++                            struct vmwgfx_hash_item **p_hash)
++{
++      struct vmwgfx_hash_item *hash;
++
++      hash_for_each_possible(tfile->ref_hash, hash, head, key) {
++              if (hash->key == key) {
++                      *p_hash = hash;
++                      return 0;
++              }
++      }
++      return -EINVAL;
++}
++
+ static void ttm_object_file_destroy(struct kref *kref)
+ {
+       struct ttm_object_file *tfile =
+@@ -238,14 +271,13 @@ void ttm_base_object_unref(struct ttm_base_object **p_base)
+  * Return: A pointer to the object if successful or NULL otherwise.
+  */
+ struct ttm_base_object *
+-ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key)
++ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key)
+ {
+       struct vmwgfx_hash_item *hash;
+-      struct vmwgfx_open_hash *ht = &tfile->ref_hash;
+       int ret;
+       rcu_read_lock();
+-      ret = vmwgfx_ht_find_item_rcu(ht, key, &hash);
++      ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);
+       if (ret) {
+               rcu_read_unlock();
+               return NULL;
+@@ -257,15 +289,14 @@ ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key)
+ EXPORT_SYMBOL(ttm_base_object_noref_lookup);
+ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
+-                                             uint32_t key)
++                                             uint64_t key)
+ {
+       struct ttm_base_object *base = NULL;
+       struct vmwgfx_hash_item *hash;
+-      struct vmwgfx_open_hash *ht = &tfile->ref_hash;
+       int ret;
+       rcu_read_lock();
+-      ret = vmwgfx_ht_find_item_rcu(ht, key, &hash);
++      ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);
+       if (likely(ret == 0)) {
+               base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
+@@ -278,7 +309,7 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
+ }
+ struct ttm_base_object *
+-ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key)
++ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint64_t key)
+ {
+       struct ttm_base_object *base;
+@@ -297,7 +328,6 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
+                      bool *existed,
+                      bool require_existed)
+ {
+-      struct vmwgfx_open_hash *ht = &tfile->ref_hash;
+       struct ttm_ref_object *ref;
+       struct vmwgfx_hash_item *hash;
+       int ret = -EINVAL;
+@@ -310,7 +340,7 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
+       while (ret == -EINVAL) {
+               rcu_read_lock();
+-              ret = vmwgfx_ht_find_item_rcu(ht, base->handle, &hash);
++              ret = ttm_tfile_find_ref_rcu(tfile, base->handle, &hash);
+               if (ret == 0) {
+                       ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
+@@ -335,21 +365,14 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
+               kref_init(&ref->kref);
+               spin_lock(&tfile->lock);
+-              ret = vmwgfx_ht_insert_item_rcu(ht, &ref->hash);
+-
+-              if (likely(ret == 0)) {
+-                      list_add_tail(&ref->head, &tfile->ref_list);
+-                      kref_get(&base->refcount);
+-                      spin_unlock(&tfile->lock);
+-                      if (existed != NULL)
+-                              *existed = false;
+-                      break;
+-              }
++              hash_add_rcu(tfile->ref_hash, &ref->hash.head, ref->hash.key);
++              ret = 0;
++              list_add_tail(&ref->head, &tfile->ref_list);
++              kref_get(&base->refcount);
+               spin_unlock(&tfile->lock);
+-              BUG_ON(ret != -EINVAL);
+-
+-              kfree(ref);
++              if (existed != NULL)
++                      *existed = false;
+       }
+       return ret;
+@@ -361,10 +384,8 @@ ttm_ref_object_release(struct kref *kref)
+       struct ttm_ref_object *ref =
+           container_of(kref, struct ttm_ref_object, kref);
+       struct ttm_object_file *tfile = ref->tfile;
+-      struct vmwgfx_open_hash *ht;
+-      ht = &tfile->ref_hash;
+-      (void)vmwgfx_ht_remove_item_rcu(ht, &ref->hash);
++      hash_del_rcu(&ref->hash.head);
+       list_del(&ref->head);
+       spin_unlock(&tfile->lock);
+@@ -376,13 +397,12 @@ ttm_ref_object_release(struct kref *kref)
+ int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
+                             unsigned long key)
+ {
+-      struct vmwgfx_open_hash *ht = &tfile->ref_hash;
+       struct ttm_ref_object *ref;
+       struct vmwgfx_hash_item *hash;
+       int ret;
+       spin_lock(&tfile->lock);
+-      ret = vmwgfx_ht_find_item(ht, key, &hash);
++      ret = ttm_tfile_find_ref(tfile, key, &hash);
+       if (unlikely(ret != 0)) {
+               spin_unlock(&tfile->lock);
+               return -EINVAL;
+@@ -414,16 +434,13 @@ void ttm_object_file_release(struct ttm_object_file **p_tfile)
+       }
+       spin_unlock(&tfile->lock);
+-      vmwgfx_ht_remove(&tfile->ref_hash);
+       ttm_object_file_unref(&tfile);
+ }
+-struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
+-                                           unsigned int hash_order)
++struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev)
+ {
+       struct ttm_object_file *tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
+-      int ret;
+       if (unlikely(tfile == NULL))
+               return NULL;
+@@ -433,17 +450,9 @@ struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
+       kref_init(&tfile->refcount);
+       INIT_LIST_HEAD(&tfile->ref_list);
+-      ret = vmwgfx_ht_create(&tfile->ref_hash, hash_order);
+-      if (ret)
+-              goto out_err;
++      hash_init(tfile->ref_hash);
+       return tfile;
+-out_err:
+-      vmwgfx_ht_remove(&tfile->ref_hash);
+-
+-      kfree(tfile);
+-
+-      return NULL;
+ }
+ struct ttm_object_device *
+diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.h b/drivers/gpu/drm/vmwgfx/ttm_object.h
+index 6870f951b677..67f30d589e27 100644
+--- a/drivers/gpu/drm/vmwgfx/ttm_object.h
++++ b/drivers/gpu/drm/vmwgfx/ttm_object.h
+@@ -104,7 +104,7 @@ struct ttm_base_object {
+       struct ttm_object_file *tfile;
+       struct kref refcount;
+       void (*refcount_release) (struct ttm_base_object **base);
+-      u32 handle;
++      u64 handle;
+       enum ttm_object_type object_type;
+       u32 shareable;
+ };
+@@ -164,7 +164,7 @@ extern int ttm_base_object_init(struct ttm_object_file *tfile,
+  */
+ extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file
+-                                                    *tfile, uint32_t key);
++                                                    *tfile, uint64_t key);
+ /**
+  * ttm_base_object_lookup_for_ref
+@@ -178,7 +178,7 @@ extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file
+  */
+ extern struct ttm_base_object *
+-ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key);
++ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint64_t key);
+ /**
+  * ttm_base_object_unref
+@@ -237,14 +237,12 @@ extern int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
+  * ttm_object_file_init - initialize a struct ttm_object file
+  *
+  * @tdev: A struct ttm_object device this file is initialized on.
+- * @hash_order: Order of the hash table used to hold the reference objects.
+  *
+  * This is typically called by the file_ops::open function.
+  */
+ extern struct ttm_object_file *ttm_object_file_init(struct ttm_object_device
+-                                                  *tdev,
+-                                                  unsigned int hash_order);
++                                                  *tdev);
+ /**
+  * ttm_object_file_release - release data held by a ttm_object_file
+@@ -312,7 +310,7 @@ extern int ttm_prime_handle_to_fd(struct ttm_object_file *tfile,
+       kfree_rcu(__obj, __prime.base.rhead)
+ struct ttm_base_object *
+-ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key);
++ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key);
+ /**
+  * ttm_base_object_noref_release - release a base object pointer looked up
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+index 8d77e79bd904..b909a3ce9af3 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+@@ -1242,7 +1242,7 @@ static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv)
+       if (unlikely(!vmw_fp))
+               return ret;
+-      vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev, 10);
++      vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev);
+       if (unlikely(vmw_fp->tfile == NULL))
+               goto out_no_tfile;
+-- 
+2.35.1
+
diff --git a/queue-6.1/drm-vmwgfx-remove-rcu-locks-from-user-resources.patch b/queue-6.1/drm-vmwgfx-remove-rcu-locks-from-user-resources.patch
new file mode 100644 (file)
index 0000000..70632d6
--- /dev/null
@@ -0,0 +1,592 @@
+From aeb4b588ab7935d6cb5910b0577f687b1c64b859 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Dec 2022 12:29:07 -0500
+Subject: drm/vmwgfx: Remove rcu locks from user resources
+
+From: Zack Rusin <zackr@vmware.com>
+
+[ Upstream commit a309c7194e8a2f8bd4539b9449917913f6c2cd50 ]
+
+User resource lookups used rcu to avoid two extra atomics. Unfortunately
+the rcu paths were buggy and it was easy to make the driver crash by
+submitting command buffers from two different threads. Because the
+lookups never show up in performance profiles replace them with a
+regular spin lock which fixes the races in accesses to those shared
+resources.
+
+Fixes kernel oops'es in IGT's vmwgfx execution_buffer stress test and
+seen crashes with apps using shared resources.
+
+Fixes: e14c02e6b699 ("drm/vmwgfx: Look up objects without taking a reference")
+Signed-off-by: Zack Rusin <zackr@vmware.com>
+Reviewed-by: Martin Krastev <krastevm@vmware.com>
+Reviewed-by: Maaz Mombasawala <mombasawalam@vmware.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20221207172907.959037-1-zack@kde.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/vmwgfx/ttm_object.c      |  41 +-----
+ drivers/gpu/drm/vmwgfx/ttm_object.h      |  14 --
+ drivers/gpu/drm/vmwgfx/vmwgfx_bo.c       |  38 -----
+ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h      |  18 +--
+ drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c  | 176 +++++++++++------------
+ drivers/gpu/drm/vmwgfx/vmwgfx_resource.c |  33 -----
+ 6 files changed, 87 insertions(+), 233 deletions(-)
+
+diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.c b/drivers/gpu/drm/vmwgfx/ttm_object.c
+index 932b125ebf3d..ddf8373c1d77 100644
+--- a/drivers/gpu/drm/vmwgfx/ttm_object.c
++++ b/drivers/gpu/drm/vmwgfx/ttm_object.c
+@@ -254,40 +254,6 @@ void ttm_base_object_unref(struct ttm_base_object **p_base)
+       kref_put(&base->refcount, ttm_release_base);
+ }
+-/**
+- * ttm_base_object_noref_lookup - look up a base object without reference
+- * @tfile: The struct ttm_object_file the object is registered with.
+- * @key: The object handle.
+- *
+- * This function looks up a ttm base object and returns a pointer to it
+- * without refcounting the pointer. The returned pointer is only valid
+- * until ttm_base_object_noref_release() is called, and the object
+- * pointed to by the returned pointer may be doomed. Any persistent usage
+- * of the object requires a refcount to be taken using kref_get_unless_zero().
+- * Iff this function returns successfully it needs to be paired with
+- * ttm_base_object_noref_release() and no sleeping- or scheduling functions
+- * may be called inbetween these function callse.
+- *
+- * Return: A pointer to the object if successful or NULL otherwise.
+- */
+-struct ttm_base_object *
+-ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key)
+-{
+-      struct vmwgfx_hash_item *hash;
+-      int ret;
+-
+-      rcu_read_lock();
+-      ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);
+-      if (ret) {
+-              rcu_read_unlock();
+-              return NULL;
+-      }
+-
+-      __release(RCU);
+-      return hlist_entry(hash, struct ttm_ref_object, hash)->obj;
+-}
+-EXPORT_SYMBOL(ttm_base_object_noref_lookup);
+-
+ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
+                                              uint64_t key)
+ {
+@@ -295,15 +261,16 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
+       struct vmwgfx_hash_item *hash;
+       int ret;
+-      rcu_read_lock();
+-      ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);
++      spin_lock(&tfile->lock);
++      ret = ttm_tfile_find_ref(tfile, key, &hash);
+       if (likely(ret == 0)) {
+               base = hlist_entry(hash, struct ttm_ref_object, hash)->obj;
+               if (!kref_get_unless_zero(&base->refcount))
+                       base = NULL;
+       }
+-      rcu_read_unlock();
++      spin_unlock(&tfile->lock);
++
+       return base;
+ }
+diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.h b/drivers/gpu/drm/vmwgfx/ttm_object.h
+index f0ebbe340ad6..8098a3846bae 100644
+--- a/drivers/gpu/drm/vmwgfx/ttm_object.h
++++ b/drivers/gpu/drm/vmwgfx/ttm_object.h
+@@ -307,18 +307,4 @@ extern int ttm_prime_handle_to_fd(struct ttm_object_file *tfile,
+ #define ttm_prime_object_kfree(__obj, __prime)                \
+       kfree_rcu(__obj, __prime.base.rhead)
+-struct ttm_base_object *
+-ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key);
+-
+-/**
+- * ttm_base_object_noref_release - release a base object pointer looked up
+- * without reference
+- *
+- * Releases a base object pointer looked up with ttm_base_object_noref_lookup().
+- */
+-static inline void ttm_base_object_noref_release(void)
+-{
+-      __acquire(RCU);
+-      rcu_read_unlock();
+-}
+ #endif
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+index 822251aaab0a..973a0a52462e 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+@@ -715,44 +715,6 @@ int vmw_user_bo_lookup(struct drm_file *filp,
+       return 0;
+ }
+-/**
+- * vmw_user_bo_noref_lookup - Look up a vmw user buffer object without reference
+- * @filp: The TTM object file the handle is registered with.
+- * @handle: The user buffer object handle.
+- *
+- * This function looks up a struct vmw_bo and returns a pointer to the
+- * struct vmw_buffer_object it derives from without refcounting the pointer.
+- * The returned pointer is only valid until vmw_user_bo_noref_release() is
+- * called, and the object pointed to by the returned pointer may be doomed.
+- * Any persistent usage of the object requires a refcount to be taken using
+- * ttm_bo_reference_unless_doomed(). Iff this function returns successfully it
+- * needs to be paired with vmw_user_bo_noref_release() and no sleeping-
+- * or scheduling functions may be called in between these function calls.
+- *
+- * Return: A struct vmw_buffer_object pointer if successful or negative
+- * error pointer on failure.
+- */
+-struct vmw_buffer_object *
+-vmw_user_bo_noref_lookup(struct drm_file *filp, u32 handle)
+-{
+-      struct vmw_buffer_object *vmw_bo;
+-      struct ttm_buffer_object *bo;
+-      struct drm_gem_object *gobj = drm_gem_object_lookup(filp, handle);
+-
+-      if (!gobj) {
+-              DRM_ERROR("Invalid buffer object handle 0x%08lx.\n",
+-                        (unsigned long)handle);
+-              return ERR_PTR(-ESRCH);
+-      }
+-      vmw_bo = gem_to_vmw_bo(gobj);
+-      bo = ttm_bo_get_unless_zero(&vmw_bo->base);
+-      vmw_bo = vmw_buffer_object(bo);
+-      drm_gem_object_put(gobj);
+-
+-      return vmw_bo;
+-}
+-
+-
+ /**
+  * vmw_bo_fence_single - Utility function to fence a single TTM buffer
+  *                       object without unreserving it.
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+index 7c45c3de0dcf..0bc1ebc43002 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+@@ -826,12 +826,7 @@ extern int vmw_user_resource_lookup_handle(
+       uint32_t handle,
+       const struct vmw_user_resource_conv *converter,
+       struct vmw_resource **p_res);
+-extern struct vmw_resource *
+-vmw_user_resource_noref_lookup_handle(struct vmw_private *dev_priv,
+-                                    struct ttm_object_file *tfile,
+-                                    uint32_t handle,
+-                                    const struct vmw_user_resource_conv *
+-                                    converter);
++
+ extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
+                                 struct drm_file *file_priv);
+ extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
+@@ -870,15 +865,6 @@ static inline bool vmw_resource_mob_attached(const struct vmw_resource *res)
+       return !RB_EMPTY_NODE(&res->mob_node);
+ }
+-/**
+- * vmw_user_resource_noref_release - release a user resource pointer looked up
+- * without reference
+- */
+-static inline void vmw_user_resource_noref_release(void)
+-{
+-      ttm_base_object_noref_release();
+-}
+-
+ /**
+  * Buffer object helper functions - vmwgfx_bo.c
+  */
+@@ -930,8 +916,6 @@ extern void vmw_bo_unmap(struct vmw_buffer_object *vbo);
+ extern void vmw_bo_move_notify(struct ttm_buffer_object *bo,
+                              struct ttm_resource *mem);
+ extern void vmw_bo_swap_notify(struct ttm_buffer_object *bo);
+-extern struct vmw_buffer_object *
+-vmw_user_bo_noref_lookup(struct drm_file *filp, u32 handle);
+ /**
+  * vmw_bo_adjust_prio - Adjust the buffer object eviction priority
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+index c943ab801ca7..70cfed4fdba0 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+@@ -290,20 +290,26 @@ static void vmw_execbuf_rcache_update(struct vmw_res_cache_entry *rcache,
+       rcache->valid_handle = 0;
+ }
++enum vmw_val_add_flags {
++      vmw_val_add_flag_none  =      0,
++      vmw_val_add_flag_noctx = 1 << 0,
++};
++
+ /**
+- * vmw_execbuf_res_noref_val_add - Add a resource described by an unreferenced
+- * rcu-protected pointer to the validation list.
++ * vmw_execbuf_res_val_add - Add a resource to the validation list.
+  *
+  * @sw_context: Pointer to the software context.
+  * @res: Unreferenced rcu-protected pointer to the resource.
+  * @dirty: Whether to change dirty status.
++ * @flags: specifies whether to use the context or not
+  *
+  * Returns: 0 on success. Negative error code on failure. Typical error codes
+  * are %-EINVAL on inconsistency and %-ESRCH if the resource was doomed.
+  */
+-static int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context,
+-                                       struct vmw_resource *res,
+-                                       u32 dirty)
++static int vmw_execbuf_res_val_add(struct vmw_sw_context *sw_context,
++                                 struct vmw_resource *res,
++                                 u32 dirty,
++                                 u32 flags)
+ {
+       struct vmw_private *dev_priv = res->dev_priv;
+       int ret;
+@@ -318,24 +324,30 @@ static int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context,
+               if (dirty)
+                       vmw_validation_res_set_dirty(sw_context->ctx,
+                                                    rcache->private, dirty);
+-              vmw_user_resource_noref_release();
+               return 0;
+       }
+-      priv_size = vmw_execbuf_res_size(dev_priv, res_type);
+-      ret = vmw_validation_add_resource(sw_context->ctx, res, priv_size,
+-                                        dirty, (void **)&ctx_info,
+-                                        &first_usage);
+-      vmw_user_resource_noref_release();
+-      if (ret)
+-              return ret;
++      if ((flags & vmw_val_add_flag_noctx) != 0) {
++              ret = vmw_validation_add_resource(sw_context->ctx, res, 0, dirty,
++                                                (void **)&ctx_info, NULL);
++              if (ret)
++                      return ret;
+-      if (priv_size && first_usage) {
+-              ret = vmw_cmd_ctx_first_setup(dev_priv, sw_context, res,
+-                                            ctx_info);
+-              if (ret) {
+-                      VMW_DEBUG_USER("Failed first usage context setup.\n");
++      } else {
++              priv_size = vmw_execbuf_res_size(dev_priv, res_type);
++              ret = vmw_validation_add_resource(sw_context->ctx, res, priv_size,
++                                                dirty, (void **)&ctx_info,
++                                                &first_usage);
++              if (ret)
+                       return ret;
++
++              if (priv_size && first_usage) {
++                      ret = vmw_cmd_ctx_first_setup(dev_priv, sw_context, res,
++                                                    ctx_info);
++                      if (ret) {
++                              VMW_DEBUG_USER("Failed first usage context setup.\n");
++                              return ret;
++                      }
+               }
+       }
+@@ -343,43 +355,6 @@ static int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context,
+       return 0;
+ }
+-/**
+- * vmw_execbuf_res_noctx_val_add - Add a non-context resource to the resource
+- * validation list if it's not already on it
+- *
+- * @sw_context: Pointer to the software context.
+- * @res: Pointer to the resource.
+- * @dirty: Whether to change dirty status.
+- *
+- * Returns: Zero on success. Negative error code on failure.
+- */
+-static int vmw_execbuf_res_noctx_val_add(struct vmw_sw_context *sw_context,
+-                                       struct vmw_resource *res,
+-                                       u32 dirty)
+-{
+-      struct vmw_res_cache_entry *rcache;
+-      enum vmw_res_type res_type = vmw_res_type(res);
+-      void *ptr;
+-      int ret;
+-
+-      rcache = &sw_context->res_cache[res_type];
+-      if (likely(rcache->valid && rcache->res == res)) {
+-              if (dirty)
+-                      vmw_validation_res_set_dirty(sw_context->ctx,
+-                                                   rcache->private, dirty);
+-              return 0;
+-      }
+-
+-      ret = vmw_validation_add_resource(sw_context->ctx, res, 0, dirty,
+-                                        &ptr, NULL);
+-      if (ret)
+-              return ret;
+-
+-      vmw_execbuf_rcache_update(rcache, res, ptr);
+-
+-      return 0;
+-}
+-
+ /**
+  * vmw_view_res_val_add - Add a view and the surface it's pointing to to the
+  * validation list
+@@ -398,13 +373,13 @@ static int vmw_view_res_val_add(struct vmw_sw_context *sw_context,
+        * First add the resource the view is pointing to, otherwise it may be
+        * swapped out when the view is validated.
+        */
+-      ret = vmw_execbuf_res_noctx_val_add(sw_context, vmw_view_srf(view),
+-                                          vmw_view_dirtying(view));
++      ret = vmw_execbuf_res_val_add(sw_context, vmw_view_srf(view),
++                                    vmw_view_dirtying(view), vmw_val_add_flag_noctx);
+       if (ret)
+               return ret;
+-      return vmw_execbuf_res_noctx_val_add(sw_context, view,
+-                                           VMW_RES_DIRTY_NONE);
++      return vmw_execbuf_res_val_add(sw_context, view, VMW_RES_DIRTY_NONE,
++                                     vmw_val_add_flag_noctx);
+ }
+ /**
+@@ -475,8 +450,9 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv,
+                       if (IS_ERR(res))
+                               continue;
+-                      ret = vmw_execbuf_res_noctx_val_add(sw_context, res,
+-                                                          VMW_RES_DIRTY_SET);
++                      ret = vmw_execbuf_res_val_add(sw_context, res,
++                                                    VMW_RES_DIRTY_SET,
++                                                    vmw_val_add_flag_noctx);
+                       if (unlikely(ret != 0))
+                               return ret;
+               }
+@@ -490,9 +466,9 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv,
+               if (vmw_res_type(entry->res) == vmw_res_view)
+                       ret = vmw_view_res_val_add(sw_context, entry->res);
+               else
+-                      ret = vmw_execbuf_res_noctx_val_add
+-                              (sw_context, entry->res,
+-                               vmw_binding_dirtying(entry->bt));
++                      ret = vmw_execbuf_res_val_add(sw_context, entry->res,
++                                                    vmw_binding_dirtying(entry->bt),
++                                                    vmw_val_add_flag_noctx);
+               if (unlikely(ret != 0))
+                       break;
+       }
+@@ -658,7 +634,8 @@ vmw_cmd_res_check(struct vmw_private *dev_priv,
+ {
+       struct vmw_res_cache_entry *rcache = &sw_context->res_cache[res_type];
+       struct vmw_resource *res;
+-      int ret;
++      int ret = 0;
++      bool needs_unref = false;
+       if (p_res)
+               *p_res = NULL;
+@@ -683,17 +660,18 @@ vmw_cmd_res_check(struct vmw_private *dev_priv,
+               if (ret)
+                       return ret;
+-              res = vmw_user_resource_noref_lookup_handle
+-                      (dev_priv, sw_context->fp->tfile, *id_loc, converter);
+-              if (IS_ERR(res)) {
++              ret = vmw_user_resource_lookup_handle
++                      (dev_priv, sw_context->fp->tfile, *id_loc, converter, &res);
++              if (ret != 0) {
+                       VMW_DEBUG_USER("Could not find/use resource 0x%08x.\n",
+                                      (unsigned int) *id_loc);
+-                      return PTR_ERR(res);
++                      return ret;
+               }
++              needs_unref = true;
+-              ret = vmw_execbuf_res_noref_val_add(sw_context, res, dirty);
++              ret = vmw_execbuf_res_val_add(sw_context, res, dirty, vmw_val_add_flag_none);
+               if (unlikely(ret != 0))
+-                      return ret;
++                      goto res_check_done;
+               if (rcache->valid && rcache->res == res) {
+                       rcache->valid_handle = true;
+@@ -708,7 +686,11 @@ vmw_cmd_res_check(struct vmw_private *dev_priv,
+       if (p_res)
+               *p_res = res;
+-      return 0;
++res_check_done:
++      if (needs_unref)
++              vmw_resource_unreference(&res);
++
++      return ret;
+ }
+ /**
+@@ -1171,9 +1153,9 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
+       int ret;
+       vmw_validation_preload_bo(sw_context->ctx);
+-      vmw_bo = vmw_user_bo_noref_lookup(sw_context->filp, handle);
+-      if (IS_ERR(vmw_bo)) {
+-              VMW_DEBUG_USER("Could not find or use MOB buffer.\n");
++      ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo);
++      if (ret != 0) {
++              drm_dbg(&dev_priv->drm, "Could not find or use MOB buffer.\n");
+               return PTR_ERR(vmw_bo);
+       }
+       ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false);
+@@ -1225,9 +1207,9 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
+       int ret;
+       vmw_validation_preload_bo(sw_context->ctx);
+-      vmw_bo = vmw_user_bo_noref_lookup(sw_context->filp, handle);
+-      if (IS_ERR(vmw_bo)) {
+-              VMW_DEBUG_USER("Could not find or use GMR region.\n");
++      ret = vmw_user_bo_lookup(sw_context->filp, handle, &vmw_bo);
++      if (ret != 0) {
++              drm_dbg(&dev_priv->drm, "Could not find or use GMR region.\n");
+               return PTR_ERR(vmw_bo);
+       }
+       ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false);
+@@ -2025,8 +2007,9 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
+               res = vmw_shader_lookup(vmw_context_res_man(ctx),
+                                       cmd->body.shid, cmd->body.type);
+               if (!IS_ERR(res)) {
+-                      ret = vmw_execbuf_res_noctx_val_add(sw_context, res,
+-                                                          VMW_RES_DIRTY_NONE);
++                      ret = vmw_execbuf_res_val_add(sw_context, res,
++                                                    VMW_RES_DIRTY_NONE,
++                                                    vmw_val_add_flag_noctx);
+                       if (unlikely(ret != 0))
+                               return ret;
+@@ -2273,8 +2256,9 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv,
+                       return PTR_ERR(res);
+               }
+-              ret = vmw_execbuf_res_noctx_val_add(sw_context, res,
+-                                                  VMW_RES_DIRTY_NONE);
++              ret = vmw_execbuf_res_val_add(sw_context, res,
++                                            VMW_RES_DIRTY_NONE,
++                                            vmw_val_add_flag_noctx);
+               if (ret)
+                       return ret;
+       }
+@@ -2777,8 +2761,8 @@ static int vmw_cmd_dx_bind_shader(struct vmw_private *dev_priv,
+               return PTR_ERR(res);
+       }
+-      ret = vmw_execbuf_res_noctx_val_add(sw_context, res,
+-                                          VMW_RES_DIRTY_NONE);
++      ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_NONE,
++                                    vmw_val_add_flag_noctx);
+       if (ret) {
+               VMW_DEBUG_USER("Error creating resource validation node.\n");
+               return ret;
+@@ -3098,8 +3082,8 @@ static int vmw_cmd_dx_bind_streamoutput(struct vmw_private *dev_priv,
+       vmw_dx_streamoutput_set_size(res, cmd->body.sizeInBytes);
+-      ret = vmw_execbuf_res_noctx_val_add(sw_context, res,
+-                                          VMW_RES_DIRTY_NONE);
++      ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_NONE,
++                                    vmw_val_add_flag_noctx);
+       if (ret) {
+               DRM_ERROR("Error creating resource validation node.\n");
+               return ret;
+@@ -3148,8 +3132,8 @@ static int vmw_cmd_dx_set_streamoutput(struct vmw_private *dev_priv,
+               return 0;
+       }
+-      ret = vmw_execbuf_res_noctx_val_add(sw_context, res,
+-                                          VMW_RES_DIRTY_NONE);
++      ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_NONE,
++                                    vmw_val_add_flag_noctx);
+       if (ret) {
+               DRM_ERROR("Error creating resource validation node.\n");
+               return ret;
+@@ -4067,22 +4051,26 @@ static int vmw_execbuf_tie_context(struct vmw_private *dev_priv,
+       if (ret)
+               return ret;
+-      res = vmw_user_resource_noref_lookup_handle
++      ret = vmw_user_resource_lookup_handle
+               (dev_priv, sw_context->fp->tfile, handle,
+-               user_context_converter);
+-      if (IS_ERR(res)) {
++               user_context_converter, &res);
++      if (ret != 0) {
+               VMW_DEBUG_USER("Could not find or user DX context 0x%08x.\n",
+                              (unsigned int) handle);
+-              return PTR_ERR(res);
++              return ret;
+       }
+-      ret = vmw_execbuf_res_noref_val_add(sw_context, res, VMW_RES_DIRTY_SET);
+-      if (unlikely(ret != 0))
++      ret = vmw_execbuf_res_val_add(sw_context, res, VMW_RES_DIRTY_SET,
++                                    vmw_val_add_flag_none);
++      if (unlikely(ret != 0)) {
++              vmw_resource_unreference(&res);
+               return ret;
++      }
+       sw_context->dx_ctx_node = vmw_execbuf_info_from_res(sw_context, res);
+       sw_context->man = vmw_context_res_man(res);
++      vmw_resource_unreference(&res);
+       return 0;
+ }
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+index f66caa540e14..c7d645e5ec7b 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+@@ -281,39 +281,6 @@ int vmw_user_resource_lookup_handle(struct vmw_private *dev_priv,
+       return ret;
+ }
+-/**
+- * vmw_user_resource_noref_lookup_handle - lookup a struct resource from a
+- * TTM user-space handle and perform basic type checks
+- *
+- * @dev_priv:     Pointer to a device private struct
+- * @tfile:        Pointer to a struct ttm_object_file identifying the caller
+- * @handle:       The TTM user-space handle
+- * @converter:    Pointer to an object describing the resource type
+- *
+- * If the handle can't be found or is associated with an incorrect resource
+- * type, -EINVAL will be returned.
+- */
+-struct vmw_resource *
+-vmw_user_resource_noref_lookup_handle(struct vmw_private *dev_priv,
+-                                    struct ttm_object_file *tfile,
+-                                    uint32_t handle,
+-                                    const struct vmw_user_resource_conv
+-                                    *converter)
+-{
+-      struct ttm_base_object *base;
+-
+-      base = ttm_base_object_noref_lookup(tfile, handle);
+-      if (!base)
+-              return ERR_PTR(-ESRCH);
+-
+-      if (unlikely(ttm_base_object_type(base) != converter->object_type)) {
+-              ttm_base_object_noref_release();
+-              return ERR_PTR(-EINVAL);
+-      }
+-
+-      return converter->base_obj_to_res(base);
+-}
+-
+ /*
+  * Helper function that looks either a surface or bo.
+  *
+-- 
+2.35.1
+
diff --git a/queue-6.1/drm-vmwgfx-remove-ttm-object-hashtable.patch b/queue-6.1/drm-vmwgfx-remove-ttm-object-hashtable.patch
new file mode 100644 (file)
index 0000000..ca0c4af
--- /dev/null
@@ -0,0 +1,161 @@
+From eac299d4a11e8351038ab2f59aede53d4c8f52fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Oct 2022 00:02:23 -0400
+Subject: drm/vmwgfx: Remove ttm object hashtable
+
+From: Maaz Mombasawala <mombasawalam@vmware.com>
+
+[ Upstream commit 931e09d8d5b4aa19bdae0234f2727049f1cd13d9 ]
+
+The object_hash hashtable for ttm objects is not being used.
+Remove it and perform refactoring in ttm_object init function.
+
+Signed-off-by: Maaz Mombasawala <mombasawalam@vmware.com>
+Reviewed-by: Zack Rusin <zackr@vmware.com>
+Reviewed-by: Martin Krastev <krastevm@vmware.com>
+Signed-off-by: Zack Rusin <zackr@vmware.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20221022040236.616490-5-zack@kde.org
+Stable-dep-of: a309c7194e8a ("drm/vmwgfx: Remove rcu locks from user resources")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/vmwgfx/ttm_object.c | 24 ++++++------------------
+ drivers/gpu/drm/vmwgfx/ttm_object.h |  6 ++----
+ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c |  2 +-
+ 3 files changed, 9 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.c b/drivers/gpu/drm/vmwgfx/ttm_object.c
+index 26a55fef1ab5..9546b121bc22 100644
+--- a/drivers/gpu/drm/vmwgfx/ttm_object.c
++++ b/drivers/gpu/drm/vmwgfx/ttm_object.c
+@@ -1,7 +1,7 @@
+ /* SPDX-License-Identifier: GPL-2.0 OR MIT */
+ /**************************************************************************
+  *
+- * Copyright (c) 2009-2013 VMware, Inc., Palo Alto, CA., USA
++ * Copyright (c) 2009-2022 VMware, Inc., Palo Alto, CA., USA
+  * All Rights Reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a
+@@ -44,13 +44,14 @@
+ #define pr_fmt(fmt) "[TTM] " fmt
++#include "ttm_object.h"
++#include "vmwgfx_drv.h"
++
+ #include <linux/list.h>
+ #include <linux/spinlock.h>
+ #include <linux/slab.h>
+ #include <linux/atomic.h>
+ #include <linux/module.h>
+-#include "ttm_object.h"
+-#include "vmwgfx_drv.h"
+ MODULE_IMPORT_NS(DMA_BUF);
+@@ -81,9 +82,7 @@ struct ttm_object_file {
+ /*
+  * struct ttm_object_device
+  *
+- * @object_lock: lock that protects the object_hash hash table.
+- *
+- * @object_hash: hash table for fast lookup of object global names.
++ * @object_lock: lock that protects idr.
+  *
+  * @object_count: Per device object count.
+  *
+@@ -92,7 +91,6 @@ struct ttm_object_file {
+ struct ttm_object_device {
+       spinlock_t object_lock;
+-      struct vmwgfx_open_hash object_hash;
+       atomic_t object_count;
+       struct dma_buf_ops ops;
+       void (*dmabuf_release)(struct dma_buf *dma_buf);
+@@ -449,20 +447,15 @@ struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
+ }
+ struct ttm_object_device *
+-ttm_object_device_init(unsigned int hash_order,
+-                     const struct dma_buf_ops *ops)
++ttm_object_device_init(const struct dma_buf_ops *ops)
+ {
+       struct ttm_object_device *tdev = kmalloc(sizeof(*tdev), GFP_KERNEL);
+-      int ret;
+       if (unlikely(tdev == NULL))
+               return NULL;
+       spin_lock_init(&tdev->object_lock);
+       atomic_set(&tdev->object_count, 0);
+-      ret = vmwgfx_ht_create(&tdev->object_hash, hash_order);
+-      if (ret != 0)
+-              goto out_no_object_hash;
+       /*
+        * Our base is at VMWGFX_NUM_MOB + 1 because we want to create
+@@ -477,10 +470,6 @@ ttm_object_device_init(unsigned int hash_order,
+       tdev->dmabuf_release = tdev->ops.release;
+       tdev->ops.release = ttm_prime_dmabuf_release;
+       return tdev;
+-
+-out_no_object_hash:
+-      kfree(tdev);
+-      return NULL;
+ }
+ void ttm_object_device_release(struct ttm_object_device **p_tdev)
+@@ -491,7 +480,6 @@ void ttm_object_device_release(struct ttm_object_device **p_tdev)
+       WARN_ON_ONCE(!idr_is_empty(&tdev->idr));
+       idr_destroy(&tdev->idr);
+-      vmwgfx_ht_remove(&tdev->object_hash);
+       kfree(tdev);
+ }
+diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.h b/drivers/gpu/drm/vmwgfx/ttm_object.h
+index 1a2fa0f83f5f..6870f951b677 100644
+--- a/drivers/gpu/drm/vmwgfx/ttm_object.h
++++ b/drivers/gpu/drm/vmwgfx/ttm_object.h
+@@ -1,6 +1,6 @@
+ /**************************************************************************
+  *
+- * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
++ * Copyright (c) 2006-2022 VMware, Inc., Palo Alto, CA., USA
+  * All Rights Reserved.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a
+@@ -262,7 +262,6 @@ extern void ttm_object_file_release(struct ttm_object_file **p_tfile);
+ /**
+  * ttm_object device init - initialize a struct ttm_object_device
+  *
+- * @hash_order: Order of hash table used to hash the base objects.
+  * @ops: DMA buf ops for prime objects of this device.
+  *
+  * This function is typically called on device initialization to prepare
+@@ -270,8 +269,7 @@ extern void ttm_object_file_release(struct ttm_object_file **p_tfile);
+  */
+ extern struct ttm_object_device *
+-ttm_object_device_init(unsigned int hash_order,
+-                     const struct dma_buf_ops *ops);
++ttm_object_device_init(const struct dma_buf_ops *ops);
+ /**
+  * ttm_object_device_release - release data held by a ttm_object_device
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+index 45028e25d490..13b90273eb77 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+@@ -994,7 +994,7 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
+               goto out_err0;
+       }
+-      dev_priv->tdev = ttm_object_device_init(12, &vmw_prime_dmabuf_ops);
++      dev_priv->tdev = ttm_object_device_init(&vmw_prime_dmabuf_ops);
+       if (unlikely(dev_priv->tdev == NULL)) {
+               drm_err(&dev_priv->drm,
+-- 
+2.35.1
+
diff --git a/queue-6.1/drm-vmwgfx-remove-vmwgfx_hashtab.patch b/queue-6.1/drm-vmwgfx-remove-vmwgfx_hashtab.patch
new file mode 100644 (file)
index 0000000..784edf6
--- /dev/null
@@ -0,0 +1,462 @@
+From f6bd263170131cfd1f3975110aaef11f994a9e13 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Oct 2022 00:02:30 -0400
+Subject: drm/vmwgfx: Remove vmwgfx_hashtab
+
+From: Maaz Mombasawala <mombasawalam@vmware.com>
+
+[ Upstream commit 9da30cdd6a318595199319708c143ae318f804ef ]
+
+The vmwgfx driver has migrated from using the hashtable in vmwgfx_hashtab
+to the linux/hashtable implementation. Remove the vmwgfx_hashtab from the
+driver.
+
+Signed-off-by: Maaz Mombasawala <mombasawalam@vmware.com>
+Reviewed-by: Martin Krastev <krastevm@vmware.com>
+Reviewed-by: Zack Rusin <zackr@vmware.com>
+Signed-off-by: Zack Rusin <zackr@vmware.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20221022040236.616490-12-zack@kde.org
+Stable-dep-of: a309c7194e8a ("drm/vmwgfx: Remove rcu locks from user resources")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/gpu/todo.rst                 |  11 --
+ drivers/gpu/drm/vmwgfx/Makefile            |   2 +-
+ drivers/gpu/drm/vmwgfx/ttm_object.c        |   8 +-
+ drivers/gpu/drm/vmwgfx/ttm_object.h        |   2 -
+ drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c |   4 +-
+ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h        |   6 +-
+ drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c    | 199 ---------------------
+ drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h    |  83 ---------
+ 8 files changed, 12 insertions(+), 303 deletions(-)
+ delete mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c
+ delete mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h
+
+diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
+index 393d218e4a0c..b2c6aaf1edf2 100644
+--- a/Documentation/gpu/todo.rst
++++ b/Documentation/gpu/todo.rst
+@@ -651,17 +651,6 @@ See drivers/gpu/drm/amd/display/TODO for tasks.
+ Contact: Harry Wentland, Alex Deucher
+-vmwgfx: Replace hashtable with Linux' implementation
+-----------------------------------------------------
+-
+-The vmwgfx driver uses its own hashtable implementation. Replace the
+-code with Linux' implementation and update the callers. It's mostly a
+-refactoring task, but the interfaces are different.
+-
+-Contact: Zack Rusin, Thomas Zimmermann <tzimmermann@suse.de>
+-
+-Level: Intermediate
+-
+ Bootsplash
+ ==========
+diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile
+index eee73b9aa404..68e350f410ad 100644
+--- a/drivers/gpu/drm/vmwgfx/Makefile
++++ b/drivers/gpu/drm/vmwgfx/Makefile
+@@ -1,5 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0
+-vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_hashtab.o vmwgfx_kms.o vmwgfx_drv.o \
++vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
+           vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_ttm_buffer.o \
+           vmwgfx_cmd.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
+           vmwgfx_overlay.o vmwgfx_gmrid_manager.o vmwgfx_fence.o \
+diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.c b/drivers/gpu/drm/vmwgfx/ttm_object.c
+index c07b81fbc495..932b125ebf3d 100644
+--- a/drivers/gpu/drm/vmwgfx/ttm_object.c
++++ b/drivers/gpu/drm/vmwgfx/ttm_object.c
+@@ -284,7 +284,7 @@ ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key)
+       }
+       __release(RCU);
+-      return drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
++      return hlist_entry(hash, struct ttm_ref_object, hash)->obj;
+ }
+ EXPORT_SYMBOL(ttm_base_object_noref_lookup);
+@@ -299,7 +299,7 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
+       ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);
+       if (likely(ret == 0)) {
+-              base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
++              base = hlist_entry(hash, struct ttm_ref_object, hash)->obj;
+               if (!kref_get_unless_zero(&base->refcount))
+                       base = NULL;
+       }
+@@ -343,7 +343,7 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
+               ret = ttm_tfile_find_ref_rcu(tfile, base->handle, &hash);
+               if (ret == 0) {
+-                      ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
++                      ref = hlist_entry(hash, struct ttm_ref_object, hash);
+                       if (kref_get_unless_zero(&ref->kref)) {
+                               rcu_read_unlock();
+                               break;
+@@ -407,7 +407,7 @@ int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
+               spin_unlock(&tfile->lock);
+               return -EINVAL;
+       }
+-      ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
++      ref = hlist_entry(hash, struct ttm_ref_object, hash);
+       kref_put(&ref->kref, ttm_ref_object_release);
+       spin_unlock(&tfile->lock);
+       return 0;
+diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.h b/drivers/gpu/drm/vmwgfx/ttm_object.h
+index 67f30d589e27..f0ebbe340ad6 100644
+--- a/drivers/gpu/drm/vmwgfx/ttm_object.h
++++ b/drivers/gpu/drm/vmwgfx/ttm_object.h
+@@ -42,8 +42,6 @@
+ #include <linux/list.h>
+ #include <linux/rcupdate.h>
+-#include "vmwgfx_hashtab.h"
+-
+ /**
+  * enum ttm_object_type
+  *
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
+index 142aef686fcd..47bc0b411055 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
+@@ -88,7 +88,7 @@ vmw_cmdbuf_res_lookup(struct vmw_cmdbuf_res_manager *man,
+       hash_for_each_possible_rcu(man->resources, hash, head, key) {
+               if (hash->key == key)
+-                      return drm_hash_entry(hash, struct vmw_cmdbuf_res, hash)->res;
++                      return hlist_entry(hash, struct vmw_cmdbuf_res, hash)->res;
+       }
+       return ERR_PTR(-EINVAL);
+ }
+@@ -243,7 +243,7 @@ int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man,
+       hash_for_each_possible_rcu(man->resources, hash, head, key) {
+               if (hash->key == key) {
+-                      entry = drm_hash_entry(hash, struct vmw_cmdbuf_res, hash);
++                      entry = hlist_entry(hash, struct vmw_cmdbuf_res, hash);
+                       break;
+               }
+       }
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+index d87aeedb78d0..7c45c3de0dcf 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+@@ -43,7 +43,6 @@
+ #include "ttm_object.h"
+ #include "vmwgfx_fence.h"
+-#include "vmwgfx_hashtab.h"
+ #include "vmwgfx_reg.h"
+ #include "vmwgfx_validation.h"
+@@ -104,6 +103,11 @@ struct vmw_fpriv {
+       bool gb_aware; /* user-space is guest-backed aware */
+ };
++struct vmwgfx_hash_item {
++      struct hlist_node head;
++      unsigned long key;
++};
++
+ /**
+  * struct vmw_buffer_object - TTM buffer object with vmwgfx additions
+  * @base: The TTM buffer object
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c b/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c
+deleted file mode 100644
+index 06aebc12774e..000000000000
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c
++++ /dev/null
+@@ -1,199 +0,0 @@
+-/*
+- * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
+- * All Rights Reserved.
+- *
+- * 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, sub license, 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 (including the
+- * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+- */
+-
+-/*
+- * Simple open hash tab implementation.
+- *
+- * Authors:
+- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+- */
+-
+-#include <linux/export.h>
+-#include <linux/hash.h>
+-#include <linux/mm.h>
+-#include <linux/rculist.h>
+-#include <linux/slab.h>
+-#include <linux/vmalloc.h>
+-
+-#include <drm/drm_print.h>
+-
+-#include "vmwgfx_hashtab.h"
+-
+-int vmwgfx_ht_create(struct vmwgfx_open_hash *ht, unsigned int order)
+-{
+-      unsigned int size = 1 << order;
+-
+-      ht->order = order;
+-      ht->table = NULL;
+-      if (size <= PAGE_SIZE / sizeof(*ht->table))
+-              ht->table = kcalloc(size, sizeof(*ht->table), GFP_KERNEL);
+-      else
+-              ht->table = vzalloc(array_size(size, sizeof(*ht->table)));
+-      if (!ht->table) {
+-              DRM_ERROR("Out of memory for hash table\n");
+-              return -ENOMEM;
+-      }
+-      return 0;
+-}
+-
+-void vmwgfx_ht_verbose_list(struct vmwgfx_open_hash *ht, unsigned long key)
+-{
+-      struct vmwgfx_hash_item *entry;
+-      struct hlist_head *h_list;
+-      unsigned int hashed_key;
+-      int count = 0;
+-
+-      hashed_key = hash_long(key, ht->order);
+-      DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
+-      h_list = &ht->table[hashed_key];
+-      hlist_for_each_entry(entry, h_list, head)
+-              DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
+-}
+-
+-static struct hlist_node *vmwgfx_ht_find_key(struct vmwgfx_open_hash *ht, unsigned long key)
+-{
+-      struct vmwgfx_hash_item *entry;
+-      struct hlist_head *h_list;
+-      unsigned int hashed_key;
+-
+-      hashed_key = hash_long(key, ht->order);
+-      h_list = &ht->table[hashed_key];
+-      hlist_for_each_entry(entry, h_list, head) {
+-              if (entry->key == key)
+-                      return &entry->head;
+-              if (entry->key > key)
+-                      break;
+-      }
+-      return NULL;
+-}
+-
+-static struct hlist_node *vmwgfx_ht_find_key_rcu(struct vmwgfx_open_hash *ht, unsigned long key)
+-{
+-      struct vmwgfx_hash_item *entry;
+-      struct hlist_head *h_list;
+-      unsigned int hashed_key;
+-
+-      hashed_key = hash_long(key, ht->order);
+-      h_list = &ht->table[hashed_key];
+-      hlist_for_each_entry_rcu(entry, h_list, head) {
+-              if (entry->key == key)
+-                      return &entry->head;
+-              if (entry->key > key)
+-                      break;
+-      }
+-      return NULL;
+-}
+-
+-int vmwgfx_ht_insert_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item)
+-{
+-      struct vmwgfx_hash_item *entry;
+-      struct hlist_head *h_list;
+-      struct hlist_node *parent;
+-      unsigned int hashed_key;
+-      unsigned long key = item->key;
+-
+-      hashed_key = hash_long(key, ht->order);
+-      h_list = &ht->table[hashed_key];
+-      parent = NULL;
+-      hlist_for_each_entry(entry, h_list, head) {
+-              if (entry->key == key)
+-                      return -EINVAL;
+-              if (entry->key > key)
+-                      break;
+-              parent = &entry->head;
+-      }
+-      if (parent)
+-              hlist_add_behind_rcu(&item->head, parent);
+-      else
+-              hlist_add_head_rcu(&item->head, h_list);
+-      return 0;
+-}
+-
+-/*
+- * Just insert an item and return any "bits" bit key that hasn't been
+- * used before.
+- */
+-int vmwgfx_ht_just_insert_please(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item,
+-                               unsigned long seed, int bits, int shift,
+-                               unsigned long add)
+-{
+-      int ret;
+-      unsigned long mask = (1UL << bits) - 1;
+-      unsigned long first, unshifted_key;
+-
+-      unshifted_key = hash_long(seed, bits);
+-      first = unshifted_key;
+-      do {
+-              item->key = (unshifted_key << shift) + add;
+-              ret = vmwgfx_ht_insert_item(ht, item);
+-              if (ret)
+-                      unshifted_key = (unshifted_key + 1) & mask;
+-      } while (ret && (unshifted_key != first));
+-
+-      if (ret) {
+-              DRM_ERROR("Available key bit space exhausted\n");
+-              return -EINVAL;
+-      }
+-      return 0;
+-}
+-
+-int vmwgfx_ht_find_item(struct vmwgfx_open_hash *ht, unsigned long key,
+-                      struct vmwgfx_hash_item **item)
+-{
+-      struct hlist_node *list;
+-
+-      list = vmwgfx_ht_find_key_rcu(ht, key);
+-      if (!list)
+-              return -EINVAL;
+-
+-      *item = hlist_entry(list, struct vmwgfx_hash_item, head);
+-      return 0;
+-}
+-
+-int vmwgfx_ht_remove_key(struct vmwgfx_open_hash *ht, unsigned long key)
+-{
+-      struct hlist_node *list;
+-
+-      list = vmwgfx_ht_find_key(ht, key);
+-      if (list) {
+-              hlist_del_init_rcu(list);
+-              return 0;
+-      }
+-      return -EINVAL;
+-}
+-
+-int vmwgfx_ht_remove_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item)
+-{
+-      hlist_del_init_rcu(&item->head);
+-      return 0;
+-}
+-
+-void vmwgfx_ht_remove(struct vmwgfx_open_hash *ht)
+-{
+-      if (ht->table) {
+-              kvfree(ht->table);
+-              ht->table = NULL;
+-      }
+-}
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h b/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h
+deleted file mode 100644
+index a9ce12922e21..000000000000
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h
++++ /dev/null
+@@ -1,83 +0,0 @@
+-/*
+- * Copyright 2006 Tungsten Graphics, Inc., Bismack, ND. USA.
+- * All Rights Reserved.
+- *
+- * 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, sub license, 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 (including the
+- * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
+- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
+- */
+-
+-/*
+- * Simple open hash tab implementation.
+- *
+- * Authors:
+- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
+- */
+-
+-/*
+- * TODO: Replace this hashtable with Linux' generic implementation
+- *       from <linux/hashtable.h>.
+- */
+-
+-#ifndef VMWGFX_HASHTAB_H
+-#define VMWGFX_HASHTAB_H
+-
+-#include <linux/list.h>
+-
+-#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
+-
+-struct vmwgfx_hash_item {
+-      struct hlist_node head;
+-      unsigned long key;
+-};
+-
+-struct vmwgfx_open_hash {
+-      struct hlist_head *table;
+-      u8 order;
+-};
+-
+-int vmwgfx_ht_create(struct vmwgfx_open_hash *ht, unsigned int order);
+-int vmwgfx_ht_insert_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item);
+-int vmwgfx_ht_just_insert_please(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item,
+-                               unsigned long seed, int bits, int shift,
+-                               unsigned long add);
+-int vmwgfx_ht_find_item(struct vmwgfx_open_hash *ht, unsigned long key,
+-                      struct vmwgfx_hash_item **item);
+-
+-void vmwgfx_ht_verbose_list(struct vmwgfx_open_hash *ht, unsigned long key);
+-int vmwgfx_ht_remove_key(struct vmwgfx_open_hash *ht, unsigned long key);
+-int vmwgfx_ht_remove_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item);
+-void vmwgfx_ht_remove(struct vmwgfx_open_hash *ht);
+-
+-/*
+- * RCU-safe interface
+- *
+- * The user of this API needs to make sure that two or more instances of the
+- * hash table manipulation functions are never run simultaneously.
+- * The lookup function vmwgfx_ht_find_item_rcu may, however, run simultaneously
+- * with any of the manipulation functions as long as it's called from within
+- * an RCU read-locked section.
+- */
+-#define vmwgfx_ht_insert_item_rcu vmwgfx_ht_insert_item
+-#define vmwgfx_ht_just_insert_please_rcu vmwgfx_ht_just_insert_please
+-#define vmwgfx_ht_remove_key_rcu vmwgfx_ht_remove_key
+-#define vmwgfx_ht_remove_item_rcu vmwgfx_ht_remove_item
+-#define vmwgfx_ht_find_item_rcu vmwgfx_ht_find_item
+-
+-#endif
+-- 
+2.35.1
+
diff --git a/queue-6.1/drm-vmwgfx-write-the-driver-id-registers.patch b/queue-6.1/drm-vmwgfx-write-the-driver-id-registers.patch
new file mode 100644 (file)
index 0000000..a7d4881
--- /dev/null
@@ -0,0 +1,102 @@
+From 23aba1879cd219c74ce29ae37061f04faeeb71f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Oct 2022 00:02:20 -0400
+Subject: drm/vmwgfx: Write the driver id registers
+
+From: Zack Rusin <zackr@vmware.com>
+
+[ Upstream commit 7f4c33778686cc2d34cb4ef65b4265eea874c159 ]
+
+Driver id registers are a new mechanism in the svga device to hint to the
+device which driver is running. This should not change device behavior
+in any way, but might be convenient to work-around specific bugs
+in guest drivers.
+
+Signed-off-by: Zack Rusin <zackr@vmware.com>
+Reviewed-by: Martin Krastev <krastevm@vmware.com>
+Reviewed-by: Maaz Mombasawala <mombasawalam@vmware.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20221022040236.616490-2-zack@kde.org
+Stable-dep-of: a309c7194e8a ("drm/vmwgfx: Remove rcu locks from user resources")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 43 +++++++++++++++++++++++------
+ 1 file changed, 34 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+index d7bd5eb1d3ac..45028e25d490 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+@@ -25,10 +25,13 @@
+  *
+  **************************************************************************/
+-#include <linux/dma-mapping.h>
+-#include <linux/module.h>
+-#include <linux/pci.h>
+-#include <linux/cc_platform.h>
++
++#include "vmwgfx_drv.h"
++
++#include "vmwgfx_devcaps.h"
++#include "vmwgfx_mksstat.h"
++#include "vmwgfx_binding.h"
++#include "ttm_object.h"
+ #include <drm/drm_aperture.h>
+ #include <drm/drm_drv.h>
+@@ -41,11 +44,11 @@
+ #include <drm/ttm/ttm_placement.h>
+ #include <generated/utsrelease.h>
+-#include "ttm_object.h"
+-#include "vmwgfx_binding.h"
+-#include "vmwgfx_devcaps.h"
+-#include "vmwgfx_drv.h"
+-#include "vmwgfx_mksstat.h"
++#include <linux/cc_platform.h>
++#include <linux/dma-mapping.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/version.h>
+ #define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices"
+@@ -806,6 +809,27 @@ static int vmw_detect_version(struct vmw_private *dev)
+       return 0;
+ }
++static void vmw_write_driver_id(struct vmw_private *dev)
++{
++      if ((dev->capabilities2 & SVGA_CAP2_DX2) != 0) {
++              vmw_write(dev,  SVGA_REG_GUEST_DRIVER_ID,
++                        SVGA_REG_GUEST_DRIVER_ID_LINUX);
++
++              vmw_write(dev, SVGA_REG_GUEST_DRIVER_VERSION1,
++                        LINUX_VERSION_MAJOR << 24 |
++                        LINUX_VERSION_PATCHLEVEL << 16 |
++                        LINUX_VERSION_SUBLEVEL);
++              vmw_write(dev, SVGA_REG_GUEST_DRIVER_VERSION2,
++                        VMWGFX_DRIVER_MAJOR << 24 |
++                        VMWGFX_DRIVER_MINOR << 16 |
++                        VMWGFX_DRIVER_PATCHLEVEL);
++              vmw_write(dev, SVGA_REG_GUEST_DRIVER_VERSION3, 0);
++
++              vmw_write(dev, SVGA_REG_GUEST_DRIVER_ID,
++                        SVGA_REG_GUEST_DRIVER_ID_SUBMIT);
++      }
++}
++
+ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
+ {
+       int ret;
+@@ -1091,6 +1115,7 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
+       vmw_host_printf("vmwgfx: Module Version: %d.%d.%d (kernel: %s)",
+                       VMWGFX_DRIVER_MAJOR, VMWGFX_DRIVER_MINOR,
+                       VMWGFX_DRIVER_PATCHLEVEL, UTS_RELEASE);
++      vmw_write_driver_id(dev_priv);
+       if (dev_priv->enable_fb) {
+               vmw_fifo_resource_inc(dev_priv);
+-- 
+2.35.1
+
diff --git a/queue-6.1/efi-fix-null-deref-in-init-error-path.patch b/queue-6.1/efi-fix-null-deref-in-init-error-path.patch
new file mode 100644 (file)
index 0000000..0dfe0e8
--- /dev/null
@@ -0,0 +1,56 @@
+From a6e2734462af8ae6eed1702d1482cf017d3d3153 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Dec 2022 10:10:04 +0100
+Subject: efi: fix NULL-deref in init error path
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+[ Upstream commit 703c13fe3c9af557d312f5895ed6a5fda2711104 ]
+
+In cases where runtime services are not supported or have been disabled,
+the runtime services workqueue will never have been allocated.
+
+Do not try to destroy the workqueue unconditionally in the unlikely
+event that EFI initialisation fails to avoid dereferencing a NULL
+pointer.
+
+Fixes: 98086df8b70c ("efi: add missed destroy_workqueue when efisubsys_init fails")
+Cc: stable@vger.kernel.org
+Cc: Li Heng <liheng40@huawei.com>
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/efi/efi.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
+index f12cc29bd4b8..033aac6be7da 100644
+--- a/drivers/firmware/efi/efi.c
++++ b/drivers/firmware/efi/efi.c
+@@ -374,8 +374,8 @@ static int __init efisubsys_init(void)
+       efi_kobj = kobject_create_and_add("efi", firmware_kobj);
+       if (!efi_kobj) {
+               pr_err("efi: Firmware registration failed.\n");
+-              destroy_workqueue(efi_rts_wq);
+-              return -ENOMEM;
++              error = -ENOMEM;
++              goto err_destroy_wq;
+       }
+       if (efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE |
+@@ -423,7 +423,10 @@ static int __init efisubsys_init(void)
+               generic_ops_unregister();
+ err_put:
+       kobject_put(efi_kobj);
+-      destroy_workqueue(efi_rts_wq);
++err_destroy_wq:
++      if (efi_rts_wq)
++              destroy_workqueue(efi_rts_wq);
++
+       return error;
+ }
+-- 
+2.35.1
+
diff --git a/queue-6.1/gro-avoid-checking-for-a-failed-search.patch b/queue-6.1/gro-avoid-checking-for-a-failed-search.patch
new file mode 100644 (file)
index 0000000..295ecb3
--- /dev/null
@@ -0,0 +1,112 @@
+From b41d00312d790b327a2d71ce796ee84ba56140be Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Nov 2022 13:33:28 +0100
+Subject: gro: avoid checking for a failed search
+
+From: Richard Gobert <richardbgobert@gmail.com>
+
+[ Upstream commit e081ecf084d31809242fb0b9f35484d5fb3a161a ]
+
+After searching for a protocol handler in dev_gro_receive, checking for
+failure is redundant. Skip the failure code after finding the
+corresponding handler.
+
+Suggested-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: Richard Gobert <richardbgobert@gmail.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://lore.kernel.org/r/20221108123320.GA59373@debian
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: 7871f54e3dee ("gro: take care of DODGY packets")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/gro.c | 70 +++++++++++++++++++++++++-------------------------
+ 1 file changed, 35 insertions(+), 35 deletions(-)
+
+diff --git a/net/core/gro.c b/net/core/gro.c
+index bc9451743307..8e0fe85a647d 100644
+--- a/net/core/gro.c
++++ b/net/core/gro.c
+@@ -489,45 +489,45 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
+       rcu_read_lock();
+       list_for_each_entry_rcu(ptype, head, list) {
+-              if (ptype->type != type || !ptype->callbacks.gro_receive)
+-                      continue;
+-
+-              skb_set_network_header(skb, skb_gro_offset(skb));
+-              skb_reset_mac_len(skb);
+-              BUILD_BUG_ON(sizeof_field(struct napi_gro_cb, zeroed) != sizeof(u32));
+-              BUILD_BUG_ON(!IS_ALIGNED(offsetof(struct napi_gro_cb, zeroed),
+-                                       sizeof(u32))); /* Avoid slow unaligned acc */
+-              *(u32 *)&NAPI_GRO_CB(skb)->zeroed = 0;
+-              NAPI_GRO_CB(skb)->flush = skb_has_frag_list(skb);
+-              NAPI_GRO_CB(skb)->is_atomic = 1;
+-              NAPI_GRO_CB(skb)->count = 1;
+-              if (unlikely(skb_is_gso(skb))) {
+-                      NAPI_GRO_CB(skb)->count = skb_shinfo(skb)->gso_segs;
+-                      /* Only support TCP at the moment. */
+-                      if (!skb_is_gso_tcp(skb))
+-                              NAPI_GRO_CB(skb)->flush = 1;
+-              }
+-
+-              /* Setup for GRO checksum validation */
+-              switch (skb->ip_summed) {
+-              case CHECKSUM_COMPLETE:
+-                      NAPI_GRO_CB(skb)->csum = skb->csum;
+-                      NAPI_GRO_CB(skb)->csum_valid = 1;
+-                      break;
+-              case CHECKSUM_UNNECESSARY:
+-                      NAPI_GRO_CB(skb)->csum_cnt = skb->csum_level + 1;
+-                      break;
+-              }
++              if (ptype->type == type && ptype->callbacks.gro_receive)
++                      goto found_ptype;
++      }
++      rcu_read_unlock();
++      goto normal;
++
++found_ptype:
++      skb_set_network_header(skb, skb_gro_offset(skb));
++      skb_reset_mac_len(skb);
++      BUILD_BUG_ON(sizeof_field(struct napi_gro_cb, zeroed) != sizeof(u32));
++      BUILD_BUG_ON(!IS_ALIGNED(offsetof(struct napi_gro_cb, zeroed),
++                                      sizeof(u32))); /* Avoid slow unaligned acc */
++      *(u32 *)&NAPI_GRO_CB(skb)->zeroed = 0;
++      NAPI_GRO_CB(skb)->flush = skb_has_frag_list(skb);
++      NAPI_GRO_CB(skb)->is_atomic = 1;
++      NAPI_GRO_CB(skb)->count = 1;
++      if (unlikely(skb_is_gso(skb))) {
++              NAPI_GRO_CB(skb)->count = skb_shinfo(skb)->gso_segs;
++              /* Only support TCP at the moment. */
++              if (!skb_is_gso_tcp(skb))
++                      NAPI_GRO_CB(skb)->flush = 1;
++      }
+-              pp = INDIRECT_CALL_INET(ptype->callbacks.gro_receive,
+-                                      ipv6_gro_receive, inet_gro_receive,
+-                                      &gro_list->list, skb);
++      /* Setup for GRO checksum validation */
++      switch (skb->ip_summed) {
++      case CHECKSUM_COMPLETE:
++              NAPI_GRO_CB(skb)->csum = skb->csum;
++              NAPI_GRO_CB(skb)->csum_valid = 1;
++              break;
++      case CHECKSUM_UNNECESSARY:
++              NAPI_GRO_CB(skb)->csum_cnt = skb->csum_level + 1;
+               break;
+       }
+-      rcu_read_unlock();
+-      if (&ptype->list == head)
+-              goto normal;
++      pp = INDIRECT_CALL_INET(ptype->callbacks.gro_receive,
++                              ipv6_gro_receive, inet_gro_receive,
++                              &gro_list->list, skb);
++
++      rcu_read_unlock();
+       if (PTR_ERR(pp) == -EINPROGRESS) {
+               ret = GRO_CONSUMED;
+-- 
+2.35.1
+
diff --git a/queue-6.1/gro-take-care-of-dodgy-packets.patch b/queue-6.1/gro-take-care-of-dodgy-packets.patch
new file mode 100644 (file)
index 0000000..671cc47
--- /dev/null
@@ -0,0 +1,48 @@
+From 90252422f92611d0d16b429c93ce953d16eb1a14 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Jan 2023 14:25:23 +0000
+Subject: gro: take care of DODGY packets
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 7871f54e3deed68a27111dda162c4fe9b9c65f8f ]
+
+Jaroslav reported a recent throughput regression with virtio_net
+caused by blamed commit.
+
+It is unclear if DODGY GSO packets coming from user space
+can be accepted by GRO engine in the future with minimal
+changes, and if there is any expected gain from it.
+
+In the meantime, make sure to detect and flush DODGY packets.
+
+Fixes: 5eddb24901ee ("gro: add support of (hw)gro packets to gro stack")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reported-and-bisected-by: Jaroslav Pulchart <jaroslav.pulchart@gooddata.com>
+Cc: Coco Li <lixiaoyan@google.com>
+Cc: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/gro.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/net/core/gro.c b/net/core/gro.c
+index 8e0fe85a647d..1b4abfb9a7a1 100644
+--- a/net/core/gro.c
++++ b/net/core/gro.c
+@@ -507,8 +507,9 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
+       NAPI_GRO_CB(skb)->count = 1;
+       if (unlikely(skb_is_gso(skb))) {
+               NAPI_GRO_CB(skb)->count = skb_shinfo(skb)->gso_segs;
+-              /* Only support TCP at the moment. */
+-              if (!skb_is_gso_tcp(skb))
++              /* Only support TCP and non DODGY users. */
++              if (!skb_is_gso_tcp(skb) ||
++                  (skb_shinfo(skb)->gso_type & SKB_GSO_DODGY))
+                       NAPI_GRO_CB(skb)->flush = 1;
+       }
+-- 
+2.35.1
+
diff --git a/queue-6.1/hvc-xen-lock-console-list-traversal.patch b/queue-6.1/hvc-xen-lock-console-list-traversal.patch
new file mode 100644 (file)
index 0000000..d3cf7f2
--- /dev/null
@@ -0,0 +1,186 @@
+From 33680937a9219ca16440e284d4c99dcbd1a6f80f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Nov 2022 17:36:02 +0100
+Subject: hvc/xen: lock console list traversal
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Roger Pau Monne <roger.pau@citrix.com>
+
+[ Upstream commit c0dccad87cf68fc6012aec7567e354353097ec1a ]
+
+The currently lockless access to the xen console list in
+vtermno_to_xencons() is incorrect, as additions and removals from the
+list can happen anytime, and as such the traversal of the list to get
+the private console data for a given termno needs to happen with the
+lock held.  Note users that modify the list already do so with the
+lock taken.
+
+Adjust current lock takers to use the _irq{save,restore} helpers,
+since the context in which vtermno_to_xencons() is called can have
+interrupts disabled.  Use the _irq{save,restore} set of helpers to
+switch the current callers to disable interrupts in the locked region.
+I haven't checked if existing users could instead use the _irq
+variant, as I think it's safer to use _irq{save,restore} upfront.
+
+While there switch from using list_for_each_entry_safe to
+list_for_each_entry: the current entry cursor won't be removed as
+part of the code in the loop body, so using the _safe variant is
+pointless.
+
+Fixes: 02e19f9c7cac ('hvc_xen: implement multiconsole support')
+Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
+Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
+Link: https://lore.kernel.org/r/20221130163611.14686-1-roger.pau@citrix.com
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/hvc/hvc_xen.c | 46 ++++++++++++++++++++++++---------------
+ 1 file changed, 29 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
+index 7c23112dc923..37809c6c027f 100644
+--- a/drivers/tty/hvc/hvc_xen.c
++++ b/drivers/tty/hvc/hvc_xen.c
+@@ -52,17 +52,22 @@ static DEFINE_SPINLOCK(xencons_lock);
+ static struct xencons_info *vtermno_to_xencons(int vtermno)
+ {
+-      struct xencons_info *entry, *n, *ret = NULL;
++      struct xencons_info *entry, *ret = NULL;
++      unsigned long flags;
+-      if (list_empty(&xenconsoles))
+-                      return NULL;
++      spin_lock_irqsave(&xencons_lock, flags);
++      if (list_empty(&xenconsoles)) {
++              spin_unlock_irqrestore(&xencons_lock, flags);
++              return NULL;
++      }
+-      list_for_each_entry_safe(entry, n, &xenconsoles, list) {
++      list_for_each_entry(entry, &xenconsoles, list) {
+               if (entry->vtermno == vtermno) {
+                       ret  = entry;
+                       break;
+               }
+       }
++      spin_unlock_irqrestore(&xencons_lock, flags);
+       return ret;
+ }
+@@ -223,7 +228,7 @@ static int xen_hvm_console_init(void)
+ {
+       int r;
+       uint64_t v = 0;
+-      unsigned long gfn;
++      unsigned long gfn, flags;
+       struct xencons_info *info;
+       if (!xen_hvm_domain())
+@@ -258,9 +263,9 @@ static int xen_hvm_console_init(void)
+               goto err;
+       info->vtermno = HVC_COOKIE;
+-      spin_lock(&xencons_lock);
++      spin_lock_irqsave(&xencons_lock, flags);
+       list_add_tail(&info->list, &xenconsoles);
+-      spin_unlock(&xencons_lock);
++      spin_unlock_irqrestore(&xencons_lock, flags);
+       return 0;
+ err:
+@@ -283,6 +288,7 @@ static int xencons_info_pv_init(struct xencons_info *info, int vtermno)
+ static int xen_pv_console_init(void)
+ {
+       struct xencons_info *info;
++      unsigned long flags;
+       if (!xen_pv_domain())
+               return -ENODEV;
+@@ -299,9 +305,9 @@ static int xen_pv_console_init(void)
+               /* already configured */
+               return 0;
+       }
+-      spin_lock(&xencons_lock);
++      spin_lock_irqsave(&xencons_lock, flags);
+       xencons_info_pv_init(info, HVC_COOKIE);
+-      spin_unlock(&xencons_lock);
++      spin_unlock_irqrestore(&xencons_lock, flags);
+       return 0;
+ }
+@@ -309,6 +315,7 @@ static int xen_pv_console_init(void)
+ static int xen_initial_domain_console_init(void)
+ {
+       struct xencons_info *info;
++      unsigned long flags;
+       if (!xen_initial_domain())
+               return -ENODEV;
+@@ -323,9 +330,9 @@ static int xen_initial_domain_console_init(void)
+       info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false);
+       info->vtermno = HVC_COOKIE;
+-      spin_lock(&xencons_lock);
++      spin_lock_irqsave(&xencons_lock, flags);
+       list_add_tail(&info->list, &xenconsoles);
+-      spin_unlock(&xencons_lock);
++      spin_unlock_irqrestore(&xencons_lock, flags);
+       return 0;
+ }
+@@ -380,10 +387,12 @@ static void xencons_free(struct xencons_info *info)
+ static int xen_console_remove(struct xencons_info *info)
+ {
++      unsigned long flags;
++
+       xencons_disconnect_backend(info);
+-      spin_lock(&xencons_lock);
++      spin_lock_irqsave(&xencons_lock, flags);
+       list_del(&info->list);
+-      spin_unlock(&xencons_lock);
++      spin_unlock_irqrestore(&xencons_lock, flags);
+       if (info->xbdev != NULL)
+               xencons_free(info);
+       else {
+@@ -464,6 +473,7 @@ static int xencons_probe(struct xenbus_device *dev,
+ {
+       int ret, devid;
+       struct xencons_info *info;
++      unsigned long flags;
+       devid = dev->nodename[strlen(dev->nodename) - 1] - '0';
+       if (devid == 0)
+@@ -482,9 +492,9 @@ static int xencons_probe(struct xenbus_device *dev,
+       ret = xencons_connect_backend(dev, info);
+       if (ret < 0)
+               goto error;
+-      spin_lock(&xencons_lock);
++      spin_lock_irqsave(&xencons_lock, flags);
+       list_add_tail(&info->list, &xenconsoles);
+-      spin_unlock(&xencons_lock);
++      spin_unlock_irqrestore(&xencons_lock, flags);
+       return 0;
+@@ -584,10 +594,12 @@ static int __init xen_hvc_init(void)
+       info->hvc = hvc_alloc(HVC_COOKIE, info->irq, ops, 256);
+       if (IS_ERR(info->hvc)) {
++              unsigned long flags;
++
+               r = PTR_ERR(info->hvc);
+-              spin_lock(&xencons_lock);
++              spin_lock_irqsave(&xencons_lock, flags);
+               list_del(&info->list);
+-              spin_unlock(&xencons_lock);
++              spin_unlock_irqrestore(&xencons_lock, flags);
+               if (info->irq)
+                       unbind_from_irqhandler(info->irq, NULL);
+               kfree(info);
+-- 
+2.35.1
+
diff --git a/queue-6.1/ice-add-check-for-kzalloc.patch b/queue-6.1/ice-add-check-for-kzalloc.patch
new file mode 100644 (file)
index 0000000..ca2cdaa
--- /dev/null
@@ -0,0 +1,73 @@
+From 24a5e5dd1d4d6350cf8c1d5d4501eabce0f73607 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 21:35:52 +0800
+Subject: ice: Add check for kzalloc
+
+From: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+
+[ Upstream commit 40543b3d9d2c13227ecd3aa90a713c201d1d7f09 ]
+
+Add the check for the return value of kzalloc in order to avoid
+NULL pointer dereference.
+Moreover, use the goto-label to share the clean code.
+
+Fixes: d6b98c8d242a ("ice: add write functionality for GNSS TTY")
+Signed-off-by: Jiasheng Jiang <jiasheng@iscas.ac.cn>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Tested-by: Gurucharan G <gurucharanx.g@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_gnss.c | 23 ++++++++++++++---------
+ 1 file changed, 14 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_gnss.c b/drivers/net/ethernet/intel/ice/ice_gnss.c
+index a1915551c69a..43e199b5b513 100644
+--- a/drivers/net/ethernet/intel/ice/ice_gnss.c
++++ b/drivers/net/ethernet/intel/ice/ice_gnss.c
+@@ -461,6 +461,9 @@ static struct tty_driver *ice_gnss_create_tty_driver(struct ice_pf *pf)
+       for (i = 0; i < ICE_GNSS_TTY_MINOR_DEVICES; i++) {
+               pf->gnss_tty_port[i] = kzalloc(sizeof(*pf->gnss_tty_port[i]),
+                                              GFP_KERNEL);
++              if (!pf->gnss_tty_port[i])
++                      goto err_out;
++
+               pf->gnss_serial[i] = NULL;
+               tty_port_init(pf->gnss_tty_port[i]);
+@@ -470,21 +473,23 @@ static struct tty_driver *ice_gnss_create_tty_driver(struct ice_pf *pf)
+       err = tty_register_driver(tty_driver);
+       if (err) {
+               dev_err(dev, "Failed to register TTY driver err=%d\n", err);
+-
+-              for (i = 0; i < ICE_GNSS_TTY_MINOR_DEVICES; i++) {
+-                      tty_port_destroy(pf->gnss_tty_port[i]);
+-                      kfree(pf->gnss_tty_port[i]);
+-              }
+-              kfree(ttydrv_name);
+-              tty_driver_kref_put(pf->ice_gnss_tty_driver);
+-
+-              return NULL;
++              goto err_out;
+       }
+       for (i = 0; i < ICE_GNSS_TTY_MINOR_DEVICES; i++)
+               dev_info(dev, "%s%d registered\n", ttydrv_name, i);
+       return tty_driver;
++
++err_out:
++      while (i--) {
++              tty_port_destroy(pf->gnss_tty_port[i]);
++              kfree(pf->gnss_tty_port[i]);
++      }
++      kfree(ttydrv_name);
++      tty_driver_kref_put(pf->ice_gnss_tty_driver);
++
++      return NULL;
+ }
+ /**
+-- 
+2.35.1
+
diff --git a/queue-6.1/ice-fix-potential-memory-leak-in-ice_gnss_tty_write.patch b/queue-6.1/ice-fix-potential-memory-leak-in-ice_gnss_tty_write.patch
new file mode 100644 (file)
index 0000000..9d312b2
--- /dev/null
@@ -0,0 +1,39 @@
+From dd52bce5069fb1f62a55aa0d491e163da7fa0b36 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Dec 2022 08:55:02 +0000
+Subject: ice: Fix potential memory leak in ice_gnss_tty_write()
+
+From: Yuan Can <yuancan@huawei.com>
+
+[ Upstream commit f58985620f55580a07d40062c4115d8c9cf6ae27 ]
+
+The ice_gnss_tty_write() return directly if the write_buf alloc failed,
+leaking the cmd_buf.
+
+Fix by free cmd_buf if write_buf alloc failed.
+
+Fixes: d6b98c8d242a ("ice: add write functionality for GNSS TTY")
+Signed-off-by: Yuan Can <yuancan@huawei.com>
+Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
+Tested-by: Gurucharan G <gurucharanx.g@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_gnss.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_gnss.c b/drivers/net/ethernet/intel/ice/ice_gnss.c
+index b5a7f246d230..a1915551c69a 100644
+--- a/drivers/net/ethernet/intel/ice/ice_gnss.c
++++ b/drivers/net/ethernet/intel/ice/ice_gnss.c
+@@ -363,6 +363,7 @@ ice_gnss_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
+       /* Send the data out to a hardware port */
+       write_buf = kzalloc(sizeof(*write_buf), GFP_KERNEL);
+       if (!write_buf) {
++              kfree(cmd_buf);
+               err = -ENOMEM;
+               goto exit;
+       }
+-- 
+2.35.1
+
diff --git a/queue-6.1/igc-fix-pps-delta-between-two-synchronized-end-point.patch b/queue-6.1/igc-fix-pps-delta-between-two-synchronized-end-point.patch
new file mode 100644 (file)
index 0000000..1a58526
--- /dev/null
@@ -0,0 +1,97 @@
+From e73c9beaf1edc3c92314c2a51b3470607c31f7a4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Dec 2022 16:10:38 +0800
+Subject: igc: Fix PPS delta between two synchronized end-points
+
+From: Christopher S Hall <christopher.s.hall@intel.com>
+
+[ Upstream commit 5e91c72e560cc85f7163bbe3d14197268de31383 ]
+
+This patch fix the pulse per second output delta between
+two synchronized end-points.
+
+Based on Intel Discrete I225 Software User Manual Section
+4.2.15 TimeSync Auxiliary Control Register, ST0[Bit 4] and
+ST1[Bit 7] must be set to ensure that clock output will be
+toggles based on frequency value defined. This is to ensure
+that output of the PPS is aligned with the clock.
+
+How to test:
+
+1) Running time synchronization on both end points.
+Ex: ptp4l --step_threshold=1 -m -f gPTP.cfg -i <interface name>
+
+2) Configure PPS output using below command for both end-points
+Ex: SDP0 on I225 REV4 SKU variant
+
+./testptp -d /dev/ptp0 -L 0,2
+./testptp -d /dev/ptp0 -p 1000000000
+
+3) Measure the output using analyzer for both end-points
+
+Fixes: 87938851b6ef ("igc: enable auxiliary PHC functions for the i225")
+Signed-off-by: Christopher S Hall <christopher.s.hall@intel.com>
+Signed-off-by: Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@intel.com>
+Acked-by: Sasha Neftin <sasha.neftin@intel.com>
+Tested-by: Naama Meir <naamax.meir@linux.intel.com>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/igc/igc_defines.h |  2 ++
+ drivers/net/ethernet/intel/igc/igc_ptp.c     | 10 ++++++----
+ 2 files changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
+index 4ad35fbdc02e..dbfa4b9dee06 100644
+--- a/drivers/net/ethernet/intel/igc/igc_defines.h
++++ b/drivers/net/ethernet/intel/igc/igc_defines.h
+@@ -466,7 +466,9 @@
+ #define IGC_TSAUXC_EN_TT0     BIT(0)  /* Enable target time 0. */
+ #define IGC_TSAUXC_EN_TT1     BIT(1)  /* Enable target time 1. */
+ #define IGC_TSAUXC_EN_CLK0    BIT(2)  /* Enable Configurable Frequency Clock 0. */
++#define IGC_TSAUXC_ST0                BIT(4)  /* Start Clock 0 Toggle on Target Time 0. */
+ #define IGC_TSAUXC_EN_CLK1    BIT(5)  /* Enable Configurable Frequency Clock 1. */
++#define IGC_TSAUXC_ST1                BIT(7)  /* Start Clock 1 Toggle on Target Time 1. */
+ #define IGC_TSAUXC_EN_TS0     BIT(8)  /* Enable hardware timestamp 0. */
+ #define IGC_TSAUXC_AUTT0      BIT(9)  /* Auxiliary Timestamp Taken. */
+ #define IGC_TSAUXC_EN_TS1     BIT(10) /* Enable hardware timestamp 0. */
+diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c
+index 8dbb9f903ca7..c34734d432e0 100644
+--- a/drivers/net/ethernet/intel/igc/igc_ptp.c
++++ b/drivers/net/ethernet/intel/igc/igc_ptp.c
+@@ -322,7 +322,7 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp,
+               ts = ns_to_timespec64(ns);
+               if (rq->perout.index == 1) {
+                       if (use_freq) {
+-                              tsauxc_mask = IGC_TSAUXC_EN_CLK1;
++                              tsauxc_mask = IGC_TSAUXC_EN_CLK1 | IGC_TSAUXC_ST1;
+                               tsim_mask = 0;
+                       } else {
+                               tsauxc_mask = IGC_TSAUXC_EN_TT1;
+@@ -333,7 +333,7 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp,
+                       freqout = IGC_FREQOUT1;
+               } else {
+                       if (use_freq) {
+-                              tsauxc_mask = IGC_TSAUXC_EN_CLK0;
++                              tsauxc_mask = IGC_TSAUXC_EN_CLK0 | IGC_TSAUXC_ST0;
+                               tsim_mask = 0;
+                       } else {
+                               tsauxc_mask = IGC_TSAUXC_EN_TT0;
+@@ -347,10 +347,12 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp,
+               tsauxc = rd32(IGC_TSAUXC);
+               tsim = rd32(IGC_TSIM);
+               if (rq->perout.index == 1) {
+-                      tsauxc &= ~(IGC_TSAUXC_EN_TT1 | IGC_TSAUXC_EN_CLK1);
++                      tsauxc &= ~(IGC_TSAUXC_EN_TT1 | IGC_TSAUXC_EN_CLK1 |
++                                  IGC_TSAUXC_ST1);
+                       tsim &= ~IGC_TSICR_TT1;
+               } else {
+-                      tsauxc &= ~(IGC_TSAUXC_EN_TT0 | IGC_TSAUXC_EN_CLK0);
++                      tsauxc &= ~(IGC_TSAUXC_EN_TT0 | IGC_TSAUXC_EN_CLK0 |
++                                  IGC_TSAUXC_ST0);
+                       tsim &= ~IGC_TSICR_TT0;
+               }
+               if (on) {
+-- 
+2.35.1
+
diff --git a/queue-6.1/io_uring-lock-overflowing-for-iopoll.patch b/queue-6.1/io_uring-lock-overflowing-for-iopoll.patch
new file mode 100644 (file)
index 0000000..60d3776
--- /dev/null
@@ -0,0 +1,63 @@
+From ee2f4cf9c7408e0ce398eee696ac256a30437f83 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 14 Jan 2023 08:41:33 -0700
+Subject: io_uring: lock overflowing for IOPOLL
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+commit 544d163d659d45a206d8929370d5a2984e546cb7 upstream.
+
+syzbot reports an issue with overflow filling for IOPOLL:
+
+WARNING: CPU: 0 PID: 28 at io_uring/io_uring.c:734 io_cqring_event_overflow+0x1c0/0x230 io_uring/io_uring.c:734
+CPU: 0 PID: 28 Comm: kworker/u4:1 Not tainted 6.2.0-rc3-syzkaller-16369-g358a161a6a9e #0
+Workqueue: events_unbound io_ring_exit_work
+Call trace:
+ io_cqring_event_overflow+0x1c0/0x230 io_uring/io_uring.c:734
+ io_req_cqe_overflow+0x5c/0x70 io_uring/io_uring.c:773
+ io_fill_cqe_req io_uring/io_uring.h:168 [inline]
+ io_do_iopoll+0x474/0x62c io_uring/rw.c:1065
+ io_iopoll_try_reap_events+0x6c/0x108 io_uring/io_uring.c:1513
+ io_uring_try_cancel_requests+0x13c/0x258 io_uring/io_uring.c:3056
+ io_ring_exit_work+0xec/0x390 io_uring/io_uring.c:2869
+ process_one_work+0x2d8/0x504 kernel/workqueue.c:2289
+ worker_thread+0x340/0x610 kernel/workqueue.c:2436
+ kthread+0x12c/0x158 kernel/kthread.c:376
+ ret_from_fork+0x10/0x20 arch/arm64/kernel/entry.S:863
+
+There is no real problem for normal IOPOLL as flush is also called with
+uring_lock taken, but it's getting more complicated for IOPOLL|SQPOLL,
+for which __io_cqring_overflow_flush() happens from the CQ waiting path.
+
+Reported-and-tested-by: syzbot+6805087452d72929404e@syzkaller.appspotmail.com
+Cc: stable@vger.kernel.org # 5.10+
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ io_uring/rw.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/io_uring/rw.c b/io_uring/rw.c
+index bb47cc4da713..6223472095d2 100644
+--- a/io_uring/rw.c
++++ b/io_uring/rw.c
+@@ -1055,7 +1055,11 @@ int io_do_iopoll(struct io_ring_ctx *ctx, bool force_nonspin)
+                       continue;
+               req->cqe.flags = io_put_kbuf(req, 0);
+-              __io_fill_cqe_req(req->ctx, req);
++              if (unlikely(!__io_fill_cqe_req(ctx, req))) {
++                      spin_lock(&ctx->completion_lock);
++                      io_req_cqe_overflow(req);
++                      spin_unlock(&ctx->completion_lock);
++              }
+       }
+       if (unlikely(!nr_events))
+-- 
+2.35.1
+
diff --git a/queue-6.1/io_uring-poll-attempt-request-issue-after-racy-poll-.patch b/queue-6.1/io_uring-poll-attempt-request-issue-after-racy-poll-.patch
new file mode 100644 (file)
index 0000000..e7356e2
--- /dev/null
@@ -0,0 +1,119 @@
+From bb806bb3dd58be279a43ca8ac204d653a022067b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 14 Jan 2023 08:46:14 -0700
+Subject: io_uring/poll: attempt request issue after racy poll wakeup
+
+From: Jens Axboe <axboe@kernel.dk>
+
+commit 6e5aedb9324aab1c14a23fae3d8eeb64a679c20e upstream.
+
+If we have multiple requests waiting on the same target poll waitqueue,
+then it's quite possible to get a request triggered and get disappointed
+in not being able to make any progress with it. If we race in doing so,
+we'll potentially leave the poll request on the internal tables, but
+removed from the waitqueue. That means that any subsequent trigger of
+the poll waitqueue will not kick that request into action, causing an
+application to potentially wait for completion of a request that will
+never happen.
+
+Fix this by adding a new poll return state, IOU_POLL_REISSUE. Rather
+than have complicated logic for how to re-arm a given type of request,
+just punt it for a reissue.
+
+While in there, move the 'ret' variable to the only section where it
+gets used. This avoids confusion the scope of it.
+
+Cc: stable@vger.kernel.org
+Fixes: eb0089d629ba ("io_uring: single shot poll removal optimisation")
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ io_uring/poll.c | 33 ++++++++++++++++++++++-----------
+ 1 file changed, 22 insertions(+), 11 deletions(-)
+
+diff --git a/io_uring/poll.c b/io_uring/poll.c
+index df42fd8a6ab0..f2f9f174fc62 100644
+--- a/io_uring/poll.c
++++ b/io_uring/poll.c
+@@ -223,22 +223,23 @@ enum {
+       IOU_POLL_DONE = 0,
+       IOU_POLL_NO_ACTION = 1,
+       IOU_POLL_REMOVE_POLL_USE_RES = 2,
++      IOU_POLL_REISSUE = 3,
+ };
+ /*
+  * All poll tw should go through this. Checks for poll events, manages
+  * references, does rewait, etc.
+  *
+- * Returns a negative error on failure. IOU_POLL_NO_ACTION when no action require,
+- * which is either spurious wakeup or multishot CQE is served.
+- * IOU_POLL_DONE when it's done with the request, then the mask is stored in req->cqe.res.
+- * IOU_POLL_REMOVE_POLL_USE_RES indicates to remove multishot poll and that the result
+- * is stored in req->cqe.
++ * Returns a negative error on failure. IOU_POLL_NO_ACTION when no action
++ * require, which is either spurious wakeup or multishot CQE is served.
++ * IOU_POLL_DONE when it's done with the request, then the mask is stored in
++ * req->cqe.res. IOU_POLL_REMOVE_POLL_USE_RES indicates to remove multishot
++ * poll and that the result is stored in req->cqe.
+  */
+ static int io_poll_check_events(struct io_kiocb *req, bool *locked)
+ {
+       struct io_ring_ctx *ctx = req->ctx;
+-      int v, ret;
++      int v;
+       /* req->task == current here, checking PF_EXITING is safe */
+       if (unlikely(req->task->flags & PF_EXITING))
+@@ -274,10 +275,15 @@ static int io_poll_check_events(struct io_kiocb *req, bool *locked)
+               if (!req->cqe.res) {
+                       struct poll_table_struct pt = { ._key = req->apoll_events };
+                       req->cqe.res = vfs_poll(req->file, &pt) & req->apoll_events;
++                      /*
++                       * We got woken with a mask, but someone else got to
++                       * it first. The above vfs_poll() doesn't add us back
++                       * to the waitqueue, so if we get nothing back, we
++                       * should be safe and attempt a reissue.
++                       */
++                      if (unlikely(!req->cqe.res))
++                              return IOU_POLL_REISSUE;
+               }
+-
+-              if ((unlikely(!req->cqe.res)))
+-                      continue;
+               if (req->apoll_events & EPOLLONESHOT)
+                       return IOU_POLL_DONE;
+               if (io_is_uring_fops(req->file))
+@@ -294,7 +300,7 @@ static int io_poll_check_events(struct io_kiocb *req, bool *locked)
+                               return IOU_POLL_REMOVE_POLL_USE_RES;
+                       }
+               } else {
+-                      ret = io_poll_issue(req, locked);
++                      int ret = io_poll_issue(req, locked);
+                       if (ret == IOU_STOP_MULTISHOT)
+                               return IOU_POLL_REMOVE_POLL_USE_RES;
+                       if (ret < 0)
+@@ -325,6 +331,11 @@ static void io_poll_task_func(struct io_kiocb *req, bool *locked)
+       if (ret == IOU_POLL_DONE) {
+               struct io_poll *poll = io_kiocb_to_cmd(req, struct io_poll);
+               req->cqe.res = mangle_poll(req->cqe.res & poll->events);
++      } else if (ret == IOU_POLL_REISSUE) {
++              io_poll_remove_entries(req);
++              io_poll_tw_hash_eject(req, locked);
++              io_req_task_submit(req, locked);
++              return;
+       } else if (ret != IOU_POLL_REMOVE_POLL_USE_RES) {
+               req->cqe.res = ret;
+               req_set_fail(req);
+@@ -350,7 +361,7 @@ static void io_apoll_task_func(struct io_kiocb *req, bool *locked)
+       if (ret == IOU_POLL_REMOVE_POLL_USE_RES)
+               io_req_complete_post(req);
+-      else if (ret == IOU_POLL_DONE)
++      else if (ret == IOU_POLL_DONE || ret == IOU_POLL_REISSUE)
+               io_req_task_submit(req, locked);
+       else
+               io_req_complete_failed(req, ret);
+-- 
+2.35.1
+
diff --git a/queue-6.1/mtd-cfi-allow-building-spi-intel-standalone.patch b/queue-6.1/mtd-cfi-allow-building-spi-intel-standalone.patch
new file mode 100644 (file)
index 0000000..1b55564
--- /dev/null
@@ -0,0 +1,61 @@
+From 81dc790606ab425ed9d6da7a15c9625bd6ce672e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Dec 2022 15:13:34 +0100
+Subject: mtd: cfi: allow building spi-intel standalone
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit d19ab1f785d0b6b9f709799f0938658903821ba1 ]
+
+When MTD or MTD_CFI_GEOMETRY is disabled, the spi-intel driver
+fails to build, as it includes the shared CFI header:
+
+include/linux/mtd/cfi.h:62:2: error: #warning No CONFIG_MTD_CFI_Ix selected. No NOR chip support can work. [-Werror=cpp]
+   62 | #warning No CONFIG_MTD_CFI_Ix selected. No NOR chip support can work.
+
+linux/mtd/spi-nor.h does not actually need to include cfi.h, so
+remove the inclusion here to fix the warning. This uncovers a
+missing #include in spi-nor/core.c so add that there to
+prevent a different build issue.
+
+Fixes: e23e5a05d1fd ("mtd: spi-nor: intel-spi: Convert to SPI MEM")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
+Reviewed-by: Tokunori Ikegami <ikegami.t@gmail.com>
+Acked-by: Pratyush Yadav <pratyush@kernel.org>
+Reviewed-by: Tudor Ambarus <tudor.ambarus@linaro.org>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/linux-mtd/20221220141352.1486360-1-arnd@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mtd/spi-nor/core.c  | 1 +
+ include/linux/mtd/spi-nor.h | 1 -
+ 2 files changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
+index 2e0655c0b606..5dbf52aa0355 100644
+--- a/drivers/mtd/spi-nor/core.c
++++ b/drivers/mtd/spi-nor/core.c
+@@ -10,6 +10,7 @@
+ #include <linux/err.h>
+ #include <linux/errno.h>
+ #include <linux/module.h>
++#include <linux/delay.h>
+ #include <linux/device.h>
+ #include <linux/mutex.h>
+ #include <linux/math64.h>
+diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
+index 42218a1164f6..f92bf7f7a754 100644
+--- a/include/linux/mtd/spi-nor.h
++++ b/include/linux/mtd/spi-nor.h
+@@ -7,7 +7,6 @@
+ #define __LINUX_MTD_SPI_NOR_H
+ #include <linux/bitops.h>
+-#include <linux/mtd/cfi.h>
+ #include <linux/mtd/mtd.h>
+ #include <linux/spi/spi-mem.h>
+-- 
+2.35.1
+
diff --git a/queue-6.1/mtd-parsers-scpart-fix-__udivdi3-undefined-on-mips.patch b/queue-6.1/mtd-parsers-scpart-fix-__udivdi3-undefined-on-mips.patch
new file mode 100644 (file)
index 0000000..cf24276
--- /dev/null
@@ -0,0 +1,47 @@
+From f616855d80955160feda5827347906585782f1ec Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 23:28:29 +0300
+Subject: mtd: parsers: scpart: fix __udivdi3 undefined on mips
+
+From: Mikhail Zhilkin <csharper2005@gmail.com>
+
+[ Upstream commit 105c14b84d93168431abba5d55e6c26fa4b65abb ]
+
+This fixes the following compile error on mips architecture with clang
+version 16.0.0 reported by the 0-DAY CI Kernel Test Service:
+   ld.lld: error: undefined symbol: __udivdi3
+   referenced by scpart.c
+   mtd/parsers/scpart.o:(scpart_parse) in archive drivers/built-in.a
+
+As a workaround this makes 'offs' a 32-bit type. This is enough, because
+the mtd containing partition table practically does not exceed 1 MB. We
+can revert this when the [Link] has been resolved.
+
+Link: https://github.com/ClangBuiltLinux/linux/issues/1635
+Fixes: 9b78ef0c7997 ("mtd: parsers: add support for Sercomm partitions")
+Reported-by: kernel test robot <lkp@intel.com>
+Suggested-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Mikhail Zhilkin <csharper2005@gmail.com>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/linux-mtd/805fe58e-690f-6a3f-5ebf-2f6f6e6e4599@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mtd/parsers/scpart.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/parsers/scpart.c b/drivers/mtd/parsers/scpart.c
+index 02601bb33de4..6e5e11c37078 100644
+--- a/drivers/mtd/parsers/scpart.c
++++ b/drivers/mtd/parsers/scpart.c
+@@ -50,7 +50,7 @@ static int scpart_scan_partmap(struct mtd_info *master, loff_t partmap_offs,
+       int cnt = 0;
+       int res = 0;
+       int res2;
+-      loff_t offs;
++      uint32_t offs;
+       size_t retlen;
+       struct sc_part_desc *pdesc = NULL;
+       struct sc_part_desc *tmpdesc;
+-- 
+2.35.1
+
diff --git a/queue-6.1/net-hns3-fix-wrong-use-of-rss-size-during-vf-rss-con.patch b/queue-6.1/net-hns3-fix-wrong-use-of-rss-size-during-vf-rss-con.patch
new file mode 100644 (file)
index 0000000..ccf73b3
--- /dev/null
@@ -0,0 +1,42 @@
+From 1c4670326a50afc69e989d8dedfcbf8ae642dad2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Jan 2023 19:53:59 +0800
+Subject: net: hns3: fix wrong use of rss size during VF rss config
+
+From: Jie Wang <wangjie125@huawei.com>
+
+[ Upstream commit ae9f29fdfd827ad06c1ae8155c042245a9d00757 ]
+
+Currently, it used old rss size to get current tc mode. As a result, the
+rss size is updated, but the tc mode is still configured based on the old
+rss size.
+
+So this patch fixes it by using the new rss size in both process.
+
+Fixes: 93969dc14fcd ("net: hns3: refactor VF rss init APIs with new common rss init APIs")
+Signed-off-by: Jie Wang <wangjie125@huawei.com>
+Signed-off-by: Hao Lan <lanhao@huawei.com>
+Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
+Link: https://lore.kernel.org/r/20230110115359.10163-1-lanhao@huawei.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+index 081bd2c3f289..e84e5be8e59e 100644
+--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+@@ -3130,7 +3130,7 @@ static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num,
+       hclgevf_update_rss_size(handle, new_tqps_num);
+-      hclge_comm_get_rss_tc_info(cur_rss_size, hdev->hw_tc_map,
++      hclge_comm_get_rss_tc_info(kinfo->rss_size, hdev->hw_tc_map,
+                                  tc_offset, tc_valid, tc_size);
+       ret = hclge_comm_set_rss_tc_mode(&hdev->hw.hw, tc_offset,
+                                        tc_valid, tc_size);
+-- 
+2.35.1
+
diff --git a/queue-6.1/net-lan966x-check-for-ptp-to-be-enabled-in-lan966x_p.patch b/queue-6.1/net-lan966x-check-for-ptp-to-be-enabled-in-lan966x_p.patch
new file mode 100644 (file)
index 0000000..d7bbf7e
--- /dev/null
@@ -0,0 +1,42 @@
+From 0df047ca73826a8fb4b6a1130902297779947ea2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Jan 2023 16:32:23 +0100
+Subject: net: lan966x: check for ptp to be enabled in lan966x_ptp_deinit()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Clément Léger <clement.leger@bootlin.com>
+
+[ Upstream commit b0e380b5d4275299adf43e249f18309331b6f54f ]
+
+If ptp was not enabled due to missing IRQ for instance,
+lan966x_ptp_deinit() will dereference NULL pointers.
+
+Fixes: d096459494a8 ("net: lan966x: Add support for ptp clocks")
+Signed-off-by: Clément Léger <clement.leger@bootlin.com>
+Reviewed-by: Horatiu Vultur <horatiu.vultur@microchip.com>
+Reviewed-by: Jiri Pirko <jiri@nvidia.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c
+index e5a2bbe064f8..8e368318558a 100644
+--- a/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c
++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c
+@@ -853,6 +853,9 @@ void lan966x_ptp_deinit(struct lan966x *lan966x)
+       struct lan966x_port *port;
+       int i;
++      if (!lan966x->ptp)
++              return;
++
+       for (i = 0; i < lan966x->num_phys_ports; i++) {
+               port = lan966x->ports[i];
+               if (!port)
+-- 
+2.35.1
+
diff --git a/queue-6.1/net-mlx5-check-attr-pointer-validity-before-derefere.patch b/queue-6.1/net-mlx5-check-attr-pointer-validity-before-derefere.patch
new file mode 100644 (file)
index 0000000..7390393
--- /dev/null
@@ -0,0 +1,38 @@
+From 50d41e137410074b01a8dc5889cd677f14a273d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 16 Aug 2022 23:19:11 +0300
+Subject: net/mlx5: check attr pointer validity before dereferencing it
+
+From: Ariel Levkovich <lariel@nvidia.com>
+
+[ Upstream commit e0bf81bf0d3d4747c146e0bf44774d3d881d7137 ]
+
+Fix attr pointer validity checks after it was already
+dereferenced.
+
+Fixes: cb0d54cbf948 ("net/mlx5e: Fix wrong source vport matching on tunnel rule")
+Signed-off-by: Ariel Levkovich <lariel@nvidia.com>
+Reported-by: kernel test robot <lkp@intel.com>
+Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+index 8c6c9bcb3dc3..b4e263e8cfb8 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+@@ -142,7 +142,7 @@ mlx5_eswitch_set_rule_source_port(struct mlx5_eswitch *esw,
+               if (mlx5_esw_indir_table_decap_vport(attr))
+                       vport = mlx5_esw_indir_table_decap_vport(attr);
+-              if (attr && !attr->chain && esw_attr->int_port)
++              if (!attr->chain && esw_attr && esw_attr->int_port)
+                       metadata =
+                               mlx5e_tc_int_port_get_metadata_for_match(esw_attr->int_port);
+               else
+-- 
+2.35.1
+
diff --git a/queue-6.1/net-mlx5-fix-command-stats-access-after-free.patch b/queue-6.1/net-mlx5-fix-command-stats-access-after-free.patch
new file mode 100644 (file)
index 0000000..df3067e
--- /dev/null
@@ -0,0 +1,108 @@
+From 2f23e924c1b50459773895168ead4f44e591597a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 28 Nov 2022 19:05:47 +0200
+Subject: net/mlx5: Fix command stats access after free
+
+From: Moshe Shemesh <moshe@nvidia.com>
+
+[ Upstream commit da2e552b469a0cd130ff70a88ccc4139da428a65 ]
+
+Command may fail while driver is reloading and can't accept FW commands
+till command interface is reinitialized. Such command failure is being
+logged to command stats. This results in NULL pointer access as command
+stats structure is being freed and reallocated during mlx5 devlink
+reload (see kernel log below).
+
+Fix it by making command stats statically allocated on driver probe.
+
+Kernel log:
+[ 2394.808802] BUG: unable to handle kernel paging request at 000000000002a9c0
+[ 2394.810610] PGD 0 P4D 0
+[ 2394.811811] Oops: 0002 [#1] SMP NOPTI
+...
+[ 2394.815482] RIP: 0010:native_queued_spin_lock_slowpath+0x183/0x1d0
+...
+[ 2394.829505] Call Trace:
+[ 2394.830667]  _raw_spin_lock_irq+0x23/0x26
+[ 2394.831858]  cmd_status_err+0x55/0x110 [mlx5_core]
+[ 2394.833020]  mlx5_access_reg+0xe7/0x150 [mlx5_core]
+[ 2394.834175]  mlx5_query_port_ptys+0x78/0xa0 [mlx5_core]
+[ 2394.835337]  mlx5e_ethtool_get_link_ksettings+0x74/0x590 [mlx5_core]
+[ 2394.836454]  ? kmem_cache_alloc_trace+0x140/0x1c0
+[ 2394.837562]  __rh_call_get_link_ksettings+0x33/0x100
+[ 2394.838663]  ? __rtnl_unlock+0x25/0x50
+[ 2394.839755]  __ethtool_get_link_ksettings+0x72/0x150
+[ 2394.840862]  duplex_show+0x6e/0xc0
+[ 2394.841963]  dev_attr_show+0x1c/0x40
+[ 2394.843048]  sysfs_kf_seq_show+0x9b/0x100
+[ 2394.844123]  seq_read+0x153/0x410
+[ 2394.845187]  vfs_read+0x91/0x140
+[ 2394.846226]  ksys_read+0x4f/0xb0
+[ 2394.847234]  do_syscall_64+0x5b/0x1a0
+[ 2394.848228]  entry_SYSCALL_64_after_hwframe+0x65/0xca
+
+Fixes: 34f46ae0d4b3 ("net/mlx5: Add command failures data to debugfs")
+Signed-off-by: Moshe Shemesh <moshe@nvidia.com>
+Reviewed-by: Shay Drory <shayd@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 13 ++-----------
+ include/linux/mlx5/driver.h                   |  2 +-
+ 2 files changed, 3 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+index e7a894ba5c3e..723891eb86ee 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+@@ -2177,15 +2177,9 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
+               return -EINVAL;
+       }
+-      cmd->stats = kvcalloc(MLX5_CMD_OP_MAX, sizeof(*cmd->stats), GFP_KERNEL);
+-      if (!cmd->stats)
+-              return -ENOMEM;
+-
+       cmd->pool = dma_pool_create("mlx5_cmd", mlx5_core_dma_dev(dev), size, align, 0);
+-      if (!cmd->pool) {
+-              err = -ENOMEM;
+-              goto dma_pool_err;
+-      }
++      if (!cmd->pool)
++              return -ENOMEM;
+       err = alloc_cmd_page(dev, cmd);
+       if (err)
+@@ -2269,8 +2263,6 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
+ err_free_pool:
+       dma_pool_destroy(cmd->pool);
+-dma_pool_err:
+-      kvfree(cmd->stats);
+       return err;
+ }
+@@ -2283,7 +2275,6 @@ void mlx5_cmd_cleanup(struct mlx5_core_dev *dev)
+       destroy_msg_cache(dev);
+       free_cmd_page(dev, cmd);
+       dma_pool_destroy(cmd->pool);
+-      kvfree(cmd->stats);
+ }
+ void mlx5_cmd_set_state(struct mlx5_core_dev *dev,
+diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
+index 06cbad166225..ad55470a9fb9 100644
+--- a/include/linux/mlx5/driver.h
++++ b/include/linux/mlx5/driver.h
+@@ -315,7 +315,7 @@ struct mlx5_cmd {
+       struct mlx5_cmd_debug dbg;
+       struct cmd_msg_cache cache[MLX5_NUM_COMMAND_CACHES];
+       int checksum_disabled;
+-      struct mlx5_cmd_stats *stats;
++      struct mlx5_cmd_stats stats[MLX5_CMD_OP_MAX];
+ };
+ struct mlx5_cmd_mailbox {
+-- 
+2.35.1
+
diff --git a/queue-6.1/net-mlx5-fix-ptp-max-frequency-adjustment-range.patch b/queue-6.1/net-mlx5-fix-ptp-max-frequency-adjustment-range.patch
new file mode 100644 (file)
index 0000000..6e44dc0
--- /dev/null
@@ -0,0 +1,41 @@
+From d700758da58e3bfec03dccf8896f2cf0f15faa90 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Dec 2022 14:26:09 -0800
+Subject: net/mlx5: Fix ptp max frequency adjustment range
+
+From: Rahul Rameshbabu <rrameshbabu@nvidia.com>
+
+[ Upstream commit fe91d57277eef8bb4aca05acfa337b4a51d0bba4 ]
+
+.max_adj of ptp_clock_info acts as an absolute value for the amount in ppb
+that can be set for a single call of .adjfine. This means that a single
+call to .getfine cannot be greater than .max_adj or less than -(.max_adj).
+Provides correct value for max frequency adjustment value supported by
+devices.
+
+Fixes: 3d8c38af1493 ("net/mlx5e: Add PTP Hardware Clock (PHC) support")
+Signed-off-by: Rahul Rameshbabu <rrameshbabu@nvidia.com>
+Reviewed-by: Gal Pressman <gal@nvidia.com>
+Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+index d3a9ae80fd30..d7ddfc489536 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+@@ -691,7 +691,7 @@ static int mlx5_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
+ static const struct ptp_clock_info mlx5_ptp_clock_info = {
+       .owner          = THIS_MODULE,
+       .name           = "mlx5_ptp",
+-      .max_adj        = 100000000,
++      .max_adj        = 50000000,
+       .n_alarm        = 0,
+       .n_ext_ts       = 0,
+       .n_per_out      = 0,
+-- 
+2.35.1
+
diff --git a/queue-6.1/net-mlx5e-don-t-support-encap-rules-with-gbp-option.patch b/queue-6.1/net-mlx5e-don-t-support-encap-rules-with-gbp-option.patch
new file mode 100644 (file)
index 0000000..dfed24d
--- /dev/null
@@ -0,0 +1,40 @@
+From ffb487e4a5f85eb981b482d7f11660a9b1397a33 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 27 Dec 2022 04:54:09 +0200
+Subject: net/mlx5e: Don't support encap rules with gbp option
+
+From: Gavin Li <gavinl@nvidia.com>
+
+[ Upstream commit d515d63cae2cd186acf40deaa8ef33067bb7f637 ]
+
+Previously, encap rules with gbp option would be offloaded by mistake but
+driver does not support gbp option offload.
+
+To fix this issue, check if the encap rule has gbp option and don't
+offload the rule
+
+Fixes: d8f9dfae49ce ("net: sched: allow flower to match vxlan options")
+Signed-off-by: Gavin Li <gavinl@nvidia.com>
+Reviewed-by: Maor Dickman <maord@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c
+index fd07c4cbfd1d..1f62c702b625 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c
+@@ -88,6 +88,8 @@ static int mlx5e_gen_ip_tunnel_header_vxlan(char buf[],
+       struct udphdr *udp = (struct udphdr *)(buf);
+       struct vxlanhdr *vxh;
++      if (tun_key->tun_flags & TUNNEL_VXLAN_OPT)
++              return -EOPNOTSUPP;
+       vxh = (struct vxlanhdr *)((char *)udp + sizeof(struct udphdr));
+       *ip_proto = IPPROTO_UDP;
+-- 
+2.35.1
+
diff --git a/queue-6.1/net-mlx5e-fix-macsec-possible-null-dereference-when-.patch b/queue-6.1/net-mlx5e-fix-macsec-possible-null-dereference-when-.patch
new file mode 100644 (file)
index 0000000..b059e82
--- /dev/null
@@ -0,0 +1,57 @@
+From c999632c11f42ddd83b6b959a0f13ad6db2e780c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 11 Dec 2022 13:22:23 +0200
+Subject: net/mlx5e: Fix macsec possible null dereference when updating MAC
+ security entity (SecY)
+
+From: Emeel Hakim <ehakim@nvidia.com>
+
+[ Upstream commit 9828994ac492e8e7de47fe66097b7e665328f348 ]
+
+Upon updating MAC security entity (SecY) in hw offload path, the macsec
+security association (SA) initialization routine is called. In case of
+extended packet number (epn) is enabled the salt and ssci attributes are
+retrieved using the MACsec driver rx_sa context which is unavailable when
+updating a SecY property such as encoding-sa hence the null dereference.
+Fix by using the provided SA to set those attributes.
+
+Fixes: 4411a6c0abd3 ("net/mlx5e: Support MACsec offload extended packet number (EPN)")
+Signed-off-by: Emeel Hakim <ehakim@nvidia.com>
+Reviewed-by: Raed Salem <raeds@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/mellanox/mlx5/core/en_accel/macsec.c    | 9 ++-------
+ 1 file changed, 2 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
+index 7c0085ba2fc5..b92d541b5286 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
+@@ -359,7 +359,6 @@ static int mlx5e_macsec_init_sa(struct macsec_context *ctx,
+       struct mlx5_core_dev *mdev = priv->mdev;
+       struct mlx5_macsec_obj_attrs obj_attrs;
+       union mlx5e_macsec_rule *macsec_rule;
+-      struct macsec_key *key;
+       int err;
+       obj_attrs.next_pn = sa->next_pn;
+@@ -369,13 +368,9 @@ static int mlx5e_macsec_init_sa(struct macsec_context *ctx,
+       obj_attrs.aso_pdn = macsec->aso.pdn;
+       obj_attrs.epn_state = sa->epn_state;
+-      key = (is_tx) ? &ctx->sa.tx_sa->key : &ctx->sa.rx_sa->key;
+-
+       if (sa->epn_state.epn_enabled) {
+-              obj_attrs.ssci = (is_tx) ? cpu_to_be32((__force u32)ctx->sa.tx_sa->ssci) :
+-                                         cpu_to_be32((__force u32)ctx->sa.rx_sa->ssci);
+-
+-              memcpy(&obj_attrs.salt, &key->salt, sizeof(key->salt));
++              obj_attrs.ssci = cpu_to_be32((__force u32)sa->ssci);
++              memcpy(&obj_attrs.salt, &sa->salt, sizeof(sa->salt));
+       }
+       obj_attrs.replay_window = ctx->secy->replay_window;
+-- 
+2.35.1
+
diff --git a/queue-6.1/net-mlx5e-fix-macsec-ssci-attribute-handling-in-offl.patch b/queue-6.1/net-mlx5e-fix-macsec-ssci-attribute-handling-in-offl.patch
new file mode 100644 (file)
index 0000000..5db6940
--- /dev/null
@@ -0,0 +1,73 @@
+From e9e5408ad28662e95c11afb40269376f3542d623 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Dec 2022 16:34:13 +0200
+Subject: net/mlx5e: Fix macsec ssci attribute handling in offload path
+
+From: Emeel Hakim <ehakim@nvidia.com>
+
+[ Upstream commit f5e1ed04aa2ea665a796f0109091ca3f2b01024a ]
+
+Currently when macsec offload is set with extended packet number (epn)
+enabled, the driver wrongly deduce the short secure channel identifier
+(ssci) from the salt instead of the stand alone ssci attribute as it
+should, consequently creating a mismatch between the kernel and driver's
+ssci values.
+Fix by using the ssci value from the relevant attribute.
+
+Fixes: 4411a6c0abd3 ("net/mlx5e: Support MACsec offload extended packet number (EPN)")
+Signed-off-by: Emeel Hakim <ehakim@nvidia.com>
+Reviewed-by: Raed Salem <raeds@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/mellanox/mlx5/core/en_accel/macsec.c  | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
+index f900709639f6..7c0085ba2fc5 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
+@@ -62,6 +62,7 @@ struct mlx5e_macsec_sa {
+       u32 enc_key_id;
+       u32 next_pn;
+       sci_t sci;
++      ssci_t ssci;
+       salt_t salt;
+       struct rhash_head hash;
+@@ -499,10 +500,11 @@ mlx5e_macsec_get_macsec_device_context(const struct mlx5e_macsec *macsec,
+ }
+ static void update_macsec_epn(struct mlx5e_macsec_sa *sa, const struct macsec_key *key,
+-                            const pn_t *next_pn_halves)
++                            const pn_t *next_pn_halves, ssci_t ssci)
+ {
+       struct mlx5e_macsec_epn_state *epn_state = &sa->epn_state;
++      sa->ssci = ssci;
+       sa->salt = key->salt;
+       epn_state->epn_enabled = 1;
+       epn_state->epn_msb = next_pn_halves->upper;
+@@ -550,7 +552,8 @@ static int mlx5e_macsec_add_txsa(struct macsec_context *ctx)
+       tx_sa->assoc_num = assoc_num;
+       if (secy->xpn)
+-              update_macsec_epn(tx_sa, &ctx_tx_sa->key, &ctx_tx_sa->next_pn_halves);
++              update_macsec_epn(tx_sa, &ctx_tx_sa->key, &ctx_tx_sa->next_pn_halves,
++                                ctx_tx_sa->ssci);
+       err = mlx5_create_encryption_key(mdev, ctx->sa.key, secy->key_len,
+                                        MLX5_ACCEL_OBJ_MACSEC_KEY,
+@@ -945,7 +948,8 @@ static int mlx5e_macsec_add_rxsa(struct macsec_context *ctx)
+       rx_sa->fs_id = rx_sc->sc_xarray_element->fs_id;
+       if (ctx->secy->xpn)
+-              update_macsec_epn(rx_sa, &ctx_rx_sa->key, &ctx_rx_sa->next_pn_halves);
++              update_macsec_epn(rx_sa, &ctx_rx_sa->key, &ctx_rx_sa->next_pn_halves,
++                                ctx_rx_sa->ssci);
+       err = mlx5_create_encryption_key(mdev, ctx->sa.key, ctx->secy->key_len,
+                                        MLX5_ACCEL_OBJ_MACSEC_KEY,
+-- 
+2.35.1
+
diff --git a/queue-6.1/net-mlx5e-ipoib-block-pkey-interfaces-with-less-rx-q.patch b/queue-6.1/net-mlx5e-ipoib-block-pkey-interfaces-with-less-rx-q.patch
new file mode 100644 (file)
index 0000000..651b23f
--- /dev/null
@@ -0,0 +1,55 @@
+From a757108b4054a61a454edfe05143d23eaccd3fa0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Nov 2022 17:51:19 +0200
+Subject: net/mlx5e: IPoIB, Block PKEY interfaces with less rx queues than
+ parent
+
+From: Dragos Tatulea <dtatulea@nvidia.com>
+
+[ Upstream commit 31c70bfe58ef09fe36327ddcced9143a16e9e83d ]
+
+A user is able to configure an arbitrary number of rx queues when
+creating an interface via netlink. This doesn't work for child PKEY
+interfaces because the child interface uses the parent receive channels.
+
+Although the child shares the parent's receive channels, the number of
+rx queues is important for the channel_stats array: the parent's rx
+channel index is used to access the child's channel_stats. So the array
+has to be at least as large as the parent's rx queue size for the
+counting to work correctly and to prevent out of bound accesses.
+
+This patch checks for the mentioned scenario and returns an error when
+trying to create the interface. The error is propagated to the user.
+
+Fixes: be98737a4faa ("net/mlx5e: Use dynamic per-channel allocations in stats")
+Signed-off-by: Dragos Tatulea <dtatulea@nvidia.com>
+Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c   | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c
+index 3d31c59e69d4..0cf4eaf852d2 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c
+@@ -168,6 +168,15 @@ static int mlx5i_pkey_dev_init(struct net_device *dev)
+               return -EINVAL;
+       }
++      if (dev->num_rx_queues < parent_dev->real_num_rx_queues) {
++              mlx5_core_warn(priv->mdev,
++                             "failed to create child device with rx queues [%d] less than parent's [%d]\n",
++                             dev->num_rx_queues,
++                             parent_dev->real_num_rx_queues);
++              mlx5i_parent_put(dev);
++              return -EINVAL;
++      }
++
+       /* Get QPN to netdevice hash table from parent */
+       parent_ipriv = netdev_priv(parent_dev);
+       ipriv->qpn_htbl = parent_ipriv->qpn_htbl;
+-- 
+2.35.1
+
diff --git a/queue-6.1/net-mlx5e-ipoib-block-queue-count-configuration-when.patch b/queue-6.1/net-mlx5e-ipoib-block-queue-count-configuration-when.patch
new file mode 100644 (file)
index 0000000..3488437
--- /dev/null
@@ -0,0 +1,184 @@
+From d8cc574f5a33a0981598acd3457d25998fc94ec4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Dec 2022 13:02:38 +0200
+Subject: net/mlx5e: IPoIB, Block queue count configuration when sub interfaces
+ are present
+
+From: Dragos Tatulea <dtatulea@nvidia.com>
+
+[ Upstream commit 806a8df7126a8c05d60411eeb81057c2a8bbe7a7 ]
+
+PKEY sub interfaces share the receive queues with the parent interface.
+While setting the sub interface queue count is not supported, it is
+currently possible to change the number of queues of the parent interface.
+Thus we can end up with inconsistent queue sizes between the parent and its
+sub interfaces.
+
+This change disallows setting the queue count on the parent interface when
+sub interfaces are present.
+
+This is achieved by introducing an explicit reference to the parent netdev
+in the mlx5i_priv of the child interface. An additional counter is also
+required on the parent side to detect when sub interfaces are attached and
+for proper cleanup.
+
+The rtnl lock is taken during the ethtool op and the sub interface
+ndo_init/uninit ops. There is no race here around counting the sub
+interfaces, reading the sub interfaces and setting the number of
+channels. The ASSERT_RTNL was added to document that.
+
+Fixes: be98737a4faa ("net/mlx5e: Use dynamic per-channel allocations in stats")
+Signed-off-by: Dragos Tatulea <dtatulea@nvidia.com>
+Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../mellanox/mlx5/core/ipoib/ethtool.c        | 16 +++++++-
+ .../ethernet/mellanox/mlx5/core/ipoib/ipoib.c | 38 +++++++++++++++++++
+ .../ethernet/mellanox/mlx5/core/ipoib/ipoib.h |  6 +++
+ .../mellanox/mlx5/core/ipoib/ipoib_vlan.c     |  9 ++---
+ 4 files changed, 62 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
+index c247cca154e9..eff92dc0927c 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
+@@ -90,9 +90,21 @@ static void mlx5i_get_ringparam(struct net_device *dev,
+ static int mlx5i_set_channels(struct net_device *dev,
+                             struct ethtool_channels *ch)
+ {
+-      struct mlx5e_priv *priv = mlx5i_epriv(dev);
++      struct mlx5i_priv *ipriv = netdev_priv(dev);
++      struct mlx5e_priv *epriv = mlx5i_epriv(dev);
++
++      /* rtnl lock protects from race between this ethtool op and sub
++       * interface ndo_init/uninit.
++       */
++      ASSERT_RTNL();
++      if (ipriv->num_sub_interfaces > 0) {
++              mlx5_core_warn(epriv->mdev,
++                             "can't change number of channels for interfaces with sub interfaces (%u)\n",
++                             ipriv->num_sub_interfaces);
++              return -EINVAL;
++      }
+-      return mlx5e_ethtool_set_channels(priv, ch);
++      return mlx5e_ethtool_set_channels(epriv, ch);
+ }
+ static void mlx5i_get_channels(struct net_device *dev,
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
+index 84f5352b0ce1..038ae0fcf9d4 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
+@@ -160,6 +160,44 @@ void mlx5i_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
+       stats->tx_dropped = sstats->tx_queue_dropped;
+ }
++struct net_device *mlx5i_parent_get(struct net_device *netdev)
++{
++      struct mlx5e_priv *priv = mlx5i_epriv(netdev);
++      struct mlx5i_priv *ipriv, *parent_ipriv;
++      struct net_device *parent_dev;
++      int parent_ifindex;
++
++      ipriv = priv->ppriv;
++
++      parent_ifindex = netdev->netdev_ops->ndo_get_iflink(netdev);
++      parent_dev = dev_get_by_index(dev_net(netdev), parent_ifindex);
++      if (!parent_dev)
++              return NULL;
++
++      parent_ipriv = netdev_priv(parent_dev);
++
++      ASSERT_RTNL();
++      parent_ipriv->num_sub_interfaces++;
++
++      ipriv->parent_dev = parent_dev;
++
++      return parent_dev;
++}
++
++void mlx5i_parent_put(struct net_device *netdev)
++{
++      struct mlx5e_priv *priv = mlx5i_epriv(netdev);
++      struct mlx5i_priv *ipriv, *parent_ipriv;
++
++      ipriv = priv->ppriv;
++      parent_ipriv = netdev_priv(ipriv->parent_dev);
++
++      ASSERT_RTNL();
++      parent_ipriv->num_sub_interfaces--;
++
++      dev_put(ipriv->parent_dev);
++}
++
+ int mlx5i_init_underlay_qp(struct mlx5e_priv *priv)
+ {
+       struct mlx5_core_dev *mdev = priv->mdev;
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h
+index 99d46fda9f82..f3f2af972020 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h
++++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.h
+@@ -54,9 +54,11 @@ struct mlx5i_priv {
+       struct rdma_netdev rn; /* keep this first */
+       u32 qpn;
+       bool   sub_interface;
++      u32    num_sub_interfaces;
+       u32    qkey;
+       u16    pkey_index;
+       struct mlx5i_pkey_qpn_ht *qpn_htbl;
++      struct net_device *parent_dev;
+       char  *mlx5e_priv[];
+ };
+@@ -117,5 +119,9 @@ void mlx5i_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb,
+                  struct mlx5_av *av, u32 dqpn, u32 dqkey, bool xmit_more);
+ void mlx5i_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats);
++/* Reference management for child to parent interfaces. */
++struct net_device *mlx5i_parent_get(struct net_device *netdev);
++void mlx5i_parent_put(struct net_device *netdev);
++
+ #endif /* CONFIG_MLX5_CORE_IPOIB */
+ #endif /* __MLX5E_IPOB_H__ */
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c
+index 0227a521d301..3d31c59e69d4 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib_vlan.c
+@@ -158,21 +158,19 @@ static int mlx5i_pkey_dev_init(struct net_device *dev)
+       struct mlx5e_priv *priv = mlx5i_epriv(dev);
+       struct mlx5i_priv *ipriv, *parent_ipriv;
+       struct net_device *parent_dev;
+-      int parent_ifindex;
+       ipriv = priv->ppriv;
+-      /* Get QPN to netdevice hash table from parent */
+-      parent_ifindex = dev->netdev_ops->ndo_get_iflink(dev);
+-      parent_dev = dev_get_by_index(dev_net(dev), parent_ifindex);
++      /* Link to parent */
++      parent_dev = mlx5i_parent_get(dev);
+       if (!parent_dev) {
+               mlx5_core_warn(priv->mdev, "failed to get parent device\n");
+               return -EINVAL;
+       }
++      /* Get QPN to netdevice hash table from parent */
+       parent_ipriv = netdev_priv(parent_dev);
+       ipriv->qpn_htbl = parent_ipriv->qpn_htbl;
+-      dev_put(parent_dev);
+       return mlx5i_dev_init(dev);
+ }
+@@ -184,6 +182,7 @@ static int mlx5i_pkey_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+ static void mlx5i_pkey_dev_cleanup(struct net_device *netdev)
+ {
++      mlx5i_parent_put(netdev);
+       return mlx5i_dev_cleanup(netdev);
+ }
+-- 
+2.35.1
+
diff --git a/queue-6.1/net-mlx5e-ipoib-fix-child-pkey-interface-stats-on-rx.patch b/queue-6.1/net-mlx5e-ipoib-fix-child-pkey-interface-stats-on-rx.patch
new file mode 100644 (file)
index 0000000..9977e20
--- /dev/null
@@ -0,0 +1,43 @@
+From 0699ee36c1f630d0a65f367338d5f767a7c80d5d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Nov 2022 16:59:13 +0200
+Subject: net/mlx5e: IPoIB, Fix child PKEY interface stats on rx path
+
+From: Dragos Tatulea <dtatulea@nvidia.com>
+
+[ Upstream commit b5e23931c45a2f99f60a2f2b98a9e4d5a62a5b13 ]
+
+The current code always does the accounting using the
+stats from the parent interface (linked in the rq). This
+doesn't work when there are child interfaces configured.
+
+Fix this behavior by always using the stats from the child
+interface priv. This will also work for parent only
+interfaces: the child (netdev) and parent netdev (rq->netdev)
+will point to the same thing.
+
+Fixes: be98737a4faa ("net/mlx5e: Use dynamic per-channel allocations in stats")
+Signed-off-by: Dragos Tatulea <dtatulea@nvidia.com>
+Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_rx.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+index a61a43fc8d5c..56d1bd22c7c6 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
+@@ -2300,7 +2300,7 @@ static inline void mlx5i_complete_rx_cqe(struct mlx5e_rq *rq,
+       priv = mlx5i_epriv(netdev);
+       tstamp = &priv->tstamp;
+-      stats = rq->stats;
++      stats = &priv->channel_stats[rq->ix]->rq;
+       flags_rqpn = be32_to_cpu(cqe->flags_rqpn);
+       g = (flags_rqpn >> 28) & 3;
+-- 
+2.35.1
+
diff --git a/queue-6.1/net-mlx5e-tc-keep-mod-hdr-actions-after-mod-hdr-allo.patch b/queue-6.1/net-mlx5e-tc-keep-mod-hdr-actions-after-mod-hdr-allo.patch
new file mode 100644 (file)
index 0000000..a03a64a
--- /dev/null
@@ -0,0 +1,56 @@
+From e4b6b2764e8ce47f9bd2ca5f93422f583db65cff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Aug 2022 00:32:30 +0300
+Subject: net/mlx5e: TC, Keep mod hdr actions after mod hdr alloc
+
+From: Ariel Levkovich <lariel@nvidia.com>
+
+[ Upstream commit 5e72f3f1c558019082cfeedeed73748f35d780c6 ]
+
+When offloading TC NIC rule which has mod_hdr action, the
+mod_hdr actions list is freed upon mod_hdr allocation.
+
+In the new format of handling multi table actions and CT in
+particular, the mod_hdr actions list is still relevant when
+setting the pre and post rules and therefore, freeing the list
+may cause adding rules which don't set the FTE_ID.
+
+Therefore, the mod_hdr actions list needs to be kept for the
+pre/post flows as well and should be left for these handler to
+be freed.
+
+Fixes: 8300f225268b ("net/mlx5e: Create new flow attr for multi table actions")
+Signed-off-by: Ariel Levkovich <lariel@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+index bd9936af4582..4c313b7424bf 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+@@ -1283,7 +1283,6 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
+               err = mlx5e_attach_mod_hdr(priv, flow, parse_attr);
+-              mlx5e_mod_hdr_dealloc(&parse_attr->mod_hdr_acts);
+               if (err)
+                       return err;
+       }
+@@ -1341,8 +1340,10 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
+       }
+       mutex_unlock(&tc->t_lock);
+-      if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
++      if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
++              mlx5e_mod_hdr_dealloc(&attr->parse_attr->mod_hdr_acts);
+               mlx5e_detach_mod_hdr(priv, flow);
++      }
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT)
+               mlx5_fc_destroy(priv->mdev, attr->counter);
+-- 
+2.35.1
+
diff --git a/queue-6.1/net-mlx5e-verify-dev-is-present-for-fix-features-ndo.patch b/queue-6.1/net-mlx5e-verify-dev-is-present-for-fix-features-ndo.patch
new file mode 100644 (file)
index 0000000..b75e4e3
--- /dev/null
@@ -0,0 +1,40 @@
+From 34336c2631eae8dd5e5da6c79415a2407be73a3e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 4 Jan 2023 11:16:21 +0200
+Subject: net/mlx5e: Verify dev is present for fix features ndo
+
+From: Roy Novich <royno@nvidia.com>
+
+[ Upstream commit ab4b01bfdaa69492fb36484026b0a0f0af02d75a ]
+
+The native NIC port net device instance is being used as Uplink
+representor.  While changing profiles private resources are not
+available, fix features ndo does not check if the netdev is present.
+Add driver protection to verify private resources are ready.
+
+Fixes: 7a9fb35e8c3a ("net/mlx5e: Do not reload ethernet ports when changing eswitch mode")
+Signed-off-by: Roy Novich <royno@nvidia.com>
+Reviewed-by: Roi Dayan <roid@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+index 951ede433813..4dc149ef618c 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+@@ -4071,6 +4071,9 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
+       struct mlx5e_vlan_table *vlan;
+       struct mlx5e_params *params;
++      if (!netif_device_present(netdev))
++              return features;
++
+       vlan = mlx5e_fs_get_vlan(priv->fs);
+       mutex_lock(&priv->state_lock);
+       params = &priv->channels.params;
+-- 
+2.35.1
+
diff --git a/queue-6.1/net-sched-act_mpls-fix-warning-during-failed-attribu.patch b/queue-6.1/net-sched-act_mpls-fix-warning-during-failed-attribu.patch
new file mode 100644 (file)
index 0000000..5aee194
--- /dev/null
@@ -0,0 +1,109 @@
+From 40ac2ed5a74f9c9ca81864219a301e344149acae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 7 Jan 2023 19:10:04 +0200
+Subject: net/sched: act_mpls: Fix warning during failed attribute validation
+
+From: Ido Schimmel <idosch@nvidia.com>
+
+[ Upstream commit 9e17f99220d111ea031b44153fdfe364b0024ff2 ]
+
+The 'TCA_MPLS_LABEL' attribute is of 'NLA_U32' type, but has a
+validation type of 'NLA_VALIDATE_FUNCTION'. This is an invalid
+combination according to the comment above 'struct nla_policy':
+
+"
+Meaning of `validate' field, use via NLA_POLICY_VALIDATE_FN:
+   NLA_BINARY           Validation function called for the attribute.
+   All other            Unused - but note that it's a union
+"
+
+This can trigger the warning [1] in nla_get_range_unsigned() when
+validation of the attribute fails. Despite being of 'NLA_U32' type, the
+associated 'min'/'max' fields in the policy are negative as they are
+aliased by the 'validate' field.
+
+Fix by changing the attribute type to 'NLA_BINARY' which is consistent
+with the above comment and all other users of NLA_POLICY_VALIDATE_FN().
+As a result, move the length validation to the validation function.
+
+No regressions in MPLS tests:
+
+ # ./tdc.py -f tc-tests/actions/mpls.json
+ [...]
+ # echo $?
+ 0
+
+[1]
+WARNING: CPU: 0 PID: 17743 at lib/nlattr.c:118
+nla_get_range_unsigned+0x1d8/0x1e0 lib/nlattr.c:117
+Modules linked in:
+CPU: 0 PID: 17743 Comm: syz-executor.0 Not tainted 6.1.0-rc8 #3
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS
+rel-1.13.0-48-gd9c812dda519-prebuilt.qemu.org 04/01/2014
+RIP: 0010:nla_get_range_unsigned+0x1d8/0x1e0 lib/nlattr.c:117
+[...]
+Call Trace:
+ <TASK>
+ __netlink_policy_dump_write_attr+0x23d/0x990 net/netlink/policy.c:310
+ netlink_policy_dump_write_attr+0x22/0x30 net/netlink/policy.c:411
+ netlink_ack_tlv_fill net/netlink/af_netlink.c:2454 [inline]
+ netlink_ack+0x546/0x760 net/netlink/af_netlink.c:2506
+ netlink_rcv_skb+0x1b7/0x240 net/netlink/af_netlink.c:2546
+ rtnetlink_rcv+0x18/0x20 net/core/rtnetlink.c:6109
+ netlink_unicast_kernel net/netlink/af_netlink.c:1319 [inline]
+ netlink_unicast+0x5e9/0x6b0 net/netlink/af_netlink.c:1345
+ netlink_sendmsg+0x739/0x860 net/netlink/af_netlink.c:1921
+ sock_sendmsg_nosec net/socket.c:714 [inline]
+ sock_sendmsg net/socket.c:734 [inline]
+ ____sys_sendmsg+0x38f/0x500 net/socket.c:2482
+ ___sys_sendmsg net/socket.c:2536 [inline]
+ __sys_sendmsg+0x197/0x230 net/socket.c:2565
+ __do_sys_sendmsg net/socket.c:2574 [inline]
+ __se_sys_sendmsg net/socket.c:2572 [inline]
+ __x64_sys_sendmsg+0x42/0x50 net/socket.c:2572
+ do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+ do_syscall_64+0x2b/0x70 arch/x86/entry/common.c:80
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+
+Link: https://lore.kernel.org/netdev/CAO4mrfdmjvRUNbDyP0R03_DrD_eFCLCguz6OxZ2TYRSv0K9gxA@mail.gmail.com/
+Fixes: 2a2ea50870ba ("net: sched: add mpls manipulation actions to TC")
+Reported-by: Wei Chen <harperchen1110@gmail.com>
+Tested-by: Wei Chen <harperchen1110@gmail.com>
+Signed-off-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
+Link: https://lore.kernel.org/r/20230107171004.608436-1-idosch@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/act_mpls.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/act_mpls.c b/net/sched/act_mpls.c
+index 8ad25cc8ccd5..ea5959094adb 100644
+--- a/net/sched/act_mpls.c
++++ b/net/sched/act_mpls.c
+@@ -132,6 +132,11 @@ static int valid_label(const struct nlattr *attr,
+ {
+       const u32 *label = nla_data(attr);
++      if (nla_len(attr) != sizeof(*label)) {
++              NL_SET_ERR_MSG_MOD(extack, "Invalid MPLS label length");
++              return -EINVAL;
++      }
++
+       if (*label & ~MPLS_LABEL_MASK || *label == MPLS_LABEL_IMPLNULL) {
+               NL_SET_ERR_MSG_MOD(extack, "MPLS label out of range");
+               return -EINVAL;
+@@ -143,7 +148,8 @@ static int valid_label(const struct nlattr *attr,
+ static const struct nla_policy mpls_policy[TCA_MPLS_MAX + 1] = {
+       [TCA_MPLS_PARMS]        = NLA_POLICY_EXACT_LEN(sizeof(struct tc_mpls)),
+       [TCA_MPLS_PROTO]        = { .type = NLA_U16 },
+-      [TCA_MPLS_LABEL]        = NLA_POLICY_VALIDATE_FN(NLA_U32, valid_label),
++      [TCA_MPLS_LABEL]        = NLA_POLICY_VALIDATE_FN(NLA_BINARY,
++                                                       valid_label),
+       [TCA_MPLS_TC]           = NLA_POLICY_RANGE(NLA_U8, 0, 7),
+       [TCA_MPLS_TTL]          = NLA_POLICY_MIN(NLA_U8, 1),
+       [TCA_MPLS_BOS]          = NLA_POLICY_RANGE(NLA_U8, 0, 1),
+-- 
+2.35.1
+
diff --git a/queue-6.1/nfc-pn533-wait-for-out_urb-s-completion-in-pn533_usb.patch b/queue-6.1/nfc-pn533-wait-for-out_urb-s-completion-in-pn533_usb.patch
new file mode 100644 (file)
index 0000000..c5fc6b3
--- /dev/null
@@ -0,0 +1,129 @@
+From d7e7d0b2c6d89d76f8fc1e8416e4f811f125108a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Jan 2023 17:23:44 +0900
+Subject: nfc: pn533: Wait for out_urb's completion in pn533_usb_send_frame()
+
+From: Minsuk Kang <linuxlovemin@yonsei.ac.kr>
+
+[ Upstream commit 9dab880d675b9d0dd56c6428e4e8352a3339371d ]
+
+Fix a use-after-free that occurs in hcd when in_urb sent from
+pn533_usb_send_frame() is completed earlier than out_urb. Its callback
+frees the skb data in pn533_send_async_complete() that is used as a
+transfer buffer of out_urb. Wait before sending in_urb until the
+callback of out_urb is called. To modify the callback of out_urb alone,
+separate the complete function of out_urb and ack_urb.
+
+Found by a modified version of syzkaller.
+
+BUG: KASAN: use-after-free in dummy_timer
+Call Trace:
+ memcpy (mm/kasan/shadow.c:65)
+ dummy_perform_transfer (drivers/usb/gadget/udc/dummy_hcd.c:1352)
+ transfer (drivers/usb/gadget/udc/dummy_hcd.c:1453)
+ dummy_timer (drivers/usb/gadget/udc/dummy_hcd.c:1972)
+ arch_static_branch (arch/x86/include/asm/jump_label.h:27)
+ static_key_false (include/linux/jump_label.h:207)
+ timer_expire_exit (include/trace/events/timer.h:127)
+ call_timer_fn (kernel/time/timer.c:1475)
+ expire_timers (kernel/time/timer.c:1519)
+ __run_timers (kernel/time/timer.c:1790)
+ run_timer_softirq (kernel/time/timer.c:1803)
+
+Fixes: c46ee38620a2 ("NFC: pn533: add NXP pn533 nfc device driver")
+Signed-off-by: Minsuk Kang <linuxlovemin@yonsei.ac.kr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nfc/pn533/usb.c | 44 ++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 41 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c
+index 6f71ac72012e..ed9c5e2cf3ad 100644
+--- a/drivers/nfc/pn533/usb.c
++++ b/drivers/nfc/pn533/usb.c
+@@ -153,10 +153,17 @@ static int pn533_usb_send_ack(struct pn533 *dev, gfp_t flags)
+       return usb_submit_urb(phy->ack_urb, flags);
+ }
++struct pn533_out_arg {
++      struct pn533_usb_phy *phy;
++      struct completion done;
++};
++
+ static int pn533_usb_send_frame(struct pn533 *dev,
+                               struct sk_buff *out)
+ {
+       struct pn533_usb_phy *phy = dev->phy;
++      struct pn533_out_arg arg;
++      void *cntx;
+       int rc;
+       if (phy->priv == NULL)
+@@ -168,10 +175,17 @@ static int pn533_usb_send_frame(struct pn533 *dev,
+       print_hex_dump_debug("PN533 TX: ", DUMP_PREFIX_NONE, 16, 1,
+                            out->data, out->len, false);
++      init_completion(&arg.done);
++      cntx = phy->out_urb->context;
++      phy->out_urb->context = &arg;
++
+       rc = usb_submit_urb(phy->out_urb, GFP_KERNEL);
+       if (rc)
+               return rc;
++      wait_for_completion(&arg.done);
++      phy->out_urb->context = cntx;
++
+       if (dev->protocol_type == PN533_PROTO_REQ_RESP) {
+               /* request for response for sent packet directly */
+               rc = pn533_submit_urb_for_response(phy, GFP_KERNEL);
+@@ -408,7 +422,31 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy)
+       return arg.rc;
+ }
+-static void pn533_send_complete(struct urb *urb)
++static void pn533_out_complete(struct urb *urb)
++{
++      struct pn533_out_arg *arg = urb->context;
++      struct pn533_usb_phy *phy = arg->phy;
++
++      switch (urb->status) {
++      case 0:
++              break; /* success */
++      case -ECONNRESET:
++      case -ENOENT:
++              dev_dbg(&phy->udev->dev,
++                      "The urb has been stopped (status %d)\n",
++                      urb->status);
++              break;
++      case -ESHUTDOWN:
++      default:
++              nfc_err(&phy->udev->dev,
++                      "Urb failure (status %d)\n",
++                      urb->status);
++      }
++
++      complete(&arg->done);
++}
++
++static void pn533_ack_complete(struct urb *urb)
+ {
+       struct pn533_usb_phy *phy = urb->context;
+@@ -496,10 +534,10 @@ static int pn533_usb_probe(struct usb_interface *interface,
+       usb_fill_bulk_urb(phy->out_urb, phy->udev,
+                         usb_sndbulkpipe(phy->udev, out_endpoint),
+-                        NULL, 0, pn533_send_complete, phy);
++                        NULL, 0, pn533_out_complete, phy);
+       usb_fill_bulk_urb(phy->ack_urb, phy->udev,
+                         usb_sndbulkpipe(phy->udev, out_endpoint),
+-                        NULL, 0, pn533_send_complete, phy);
++                        NULL, 0, pn533_ack_complete, phy);
+       switch (id->driver_info) {
+       case PN533_DEVICE_STD:
+-- 
+2.35.1
+
diff --git a/queue-6.1/nfsd-add-an-nfsd_file_fsync-tracepoint.patch b/queue-6.1/nfsd-add-an-nfsd_file_fsync-tracepoint.patch
new file mode 100644 (file)
index 0000000..b1bf574
--- /dev/null
@@ -0,0 +1,93 @@
+From 057411ae5088b443b23ee7e733e72f442f4ddbc5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 3 Nov 2022 16:22:48 -0400
+Subject: NFSD: Add an nfsd_file_fsync tracepoint
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit d7064eaf688cfe454c50db9f59298463d80d403c ]
+
+Add a tracepoint to capture the number of filecache-triggered fsync
+calls and which files needed it. Also, record when an fsync triggers
+a write verifier reset.
+
+Examples:
+
+<...>-97    [007]   262.505611: nfsd_file_free:       inode=0xffff888171e08140 ref=0 flags=GC may=WRITE nf_file=0xffff8881373d2400
+<...>-97    [007]   262.505612: nfsd_file_fsync:      inode=0xffff888171e08140 ref=0 flags=GC may=WRITE nf_file=0xffff8881373d2400 ret=0
+<...>-97    [007]   262.505623: nfsd_file_free:       inode=0xffff888171e08dc0 ref=0 flags=GC may=WRITE nf_file=0xffff8881373d1e00
+<...>-97    [007]   262.505624: nfsd_file_fsync:      inode=0xffff888171e08dc0 ref=0 flags=GC may=WRITE nf_file=0xffff8881373d1e00 ret=0
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Stable-dep-of: 0b3a551fa58b ("nfsd: fix handling of cached open files in nfsd4_open codepath")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/filecache.c |  5 ++++-
+ fs/nfsd/trace.h     | 31 +++++++++++++++++++++++++++++++
+ 2 files changed, 35 insertions(+), 1 deletion(-)
+
+diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c
+index f54dd6695741..7c673f98f95c 100644
+--- a/fs/nfsd/filecache.c
++++ b/fs/nfsd/filecache.c
+@@ -314,10 +314,13 @@ static void
+ nfsd_file_fsync(struct nfsd_file *nf)
+ {
+       struct file *file = nf->nf_file;
++      int ret;
+       if (!file || !(file->f_mode & FMODE_WRITE))
+               return;
+-      if (vfs_fsync(file, 1) != 0)
++      ret = vfs_fsync(file, 1);
++      trace_nfsd_file_fsync(nf, ret);
++      if (ret)
+               nfsd_reset_write_verifier(net_generic(nf->nf_net, nfsd_net_id));
+ }
+diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h
+index 55e9e19cb1ec..08e2738adf8f 100644
+--- a/fs/nfsd/trace.h
++++ b/fs/nfsd/trace.h
+@@ -1182,6 +1182,37 @@ DEFINE_EVENT(nfsd_file_lruwalk_class, name,                             \
+ DEFINE_NFSD_FILE_LRUWALK_EVENT(nfsd_file_gc_removed);
+ DEFINE_NFSD_FILE_LRUWALK_EVENT(nfsd_file_shrinker_removed);
++TRACE_EVENT(nfsd_file_fsync,
++      TP_PROTO(
++              const struct nfsd_file *nf,
++              int ret
++      ),
++      TP_ARGS(nf, ret),
++      TP_STRUCT__entry(
++              __field(void *, nf_inode)
++              __field(int, nf_ref)
++              __field(int, ret)
++              __field(unsigned long, nf_flags)
++              __field(unsigned char, nf_may)
++              __field(struct file *, nf_file)
++      ),
++      TP_fast_assign(
++              __entry->nf_inode = nf->nf_inode;
++              __entry->nf_ref = refcount_read(&nf->nf_ref);
++              __entry->ret = ret;
++              __entry->nf_flags = nf->nf_flags;
++              __entry->nf_may = nf->nf_may;
++              __entry->nf_file = nf->nf_file;
++      ),
++      TP_printk("inode=%p ref=%d flags=%s may=%s nf_file=%p ret=%d",
++              __entry->nf_inode,
++              __entry->nf_ref,
++              show_nf_flags(__entry->nf_flags),
++              show_nfsd_may_flags(__entry->nf_may),
++              __entry->nf_file, __entry->ret
++      )
++);
++
+ #include "cache.h"
+ TRACE_DEFINE_ENUM(RC_DROPIT);
+-- 
+2.35.1
+
diff --git a/queue-6.1/nfsd-add-an-nfsd_file_gc-flag-to-enable-nfsd_file-ga.patch b/queue-6.1/nfsd-add-an-nfsd_file_gc-flag-to-enable-nfsd_file-ga.patch
new file mode 100644 (file)
index 0000000..8630d4b
--- /dev/null
@@ -0,0 +1,266 @@
+From 20252f33a1fbc03d9d8df264788f541c0246b424 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Oct 2022 10:46:51 -0400
+Subject: NFSD: Add an NFSD_FILE_GC flag to enable nfsd_file garbage collection
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 4d1ea8455716ca070e3cd85767e6f6a562a58b1b ]
+
+NFSv4 operations manage the lifetime of nfsd_file items they use by
+means of NFSv4 OPEN and CLOSE. Hence there's no need for them to be
+garbage collected.
+
+Introduce a mechanism to enable garbage collection for nfsd_file
+items used only by NFSv2/3 callers.
+
+Note that the change in nfsd_file_put() ensures that both CLOSE and
+DELEGRETURN will actually close out and free an nfsd_file on last
+reference of a non-garbage-collected file.
+
+Link: https://bugzilla.linux-nfs.org/show_bug.cgi?id=394
+Suggested-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Tested-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: NeilBrown <neilb@suse.de>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Stable-dep-of: 0b3a551fa58b ("nfsd: fix handling of cached open files in nfsd4_open codepath")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/filecache.c | 63 +++++++++++++++++++++++++++++++++++++++------
+ fs/nfsd/filecache.h |  3 +++
+ fs/nfsd/nfs3proc.c  |  4 +--
+ fs/nfsd/trace.h     |  3 ++-
+ fs/nfsd/vfs.c       |  4 +--
+ 5 files changed, 64 insertions(+), 13 deletions(-)
+
+diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c
+index babea79d3f6f..cee44405cf7d 100644
+--- a/fs/nfsd/filecache.c
++++ b/fs/nfsd/filecache.c
+@@ -63,6 +63,7 @@ struct nfsd_file_lookup_key {
+       struct net                      *net;
+       const struct cred               *cred;
+       unsigned char                   need;
++      bool                            gc;
+       enum nfsd_file_lookup_type      type;
+ };
+@@ -162,6 +163,8 @@ static int nfsd_file_obj_cmpfn(struct rhashtable_compare_arg *arg,
+                       return 1;
+               if (!nfsd_match_cred(nf->nf_cred, key->cred))
+                       return 1;
++              if (!!test_bit(NFSD_FILE_GC, &nf->nf_flags) != key->gc)
++                      return 1;
+               if (test_bit(NFSD_FILE_HASHED, &nf->nf_flags) == 0)
+                       return 1;
+               break;
+@@ -297,6 +300,8 @@ nfsd_file_alloc(struct nfsd_file_lookup_key *key, unsigned int may)
+               nf->nf_flags = 0;
+               __set_bit(NFSD_FILE_HASHED, &nf->nf_flags);
+               __set_bit(NFSD_FILE_PENDING, &nf->nf_flags);
++              if (key->gc)
++                      __set_bit(NFSD_FILE_GC, &nf->nf_flags);
+               nf->nf_inode = key->inode;
+               /* nf_ref is pre-incremented for hash table */
+               refcount_set(&nf->nf_ref, 2);
+@@ -428,16 +433,27 @@ nfsd_file_put_noref(struct nfsd_file *nf)
+       }
+ }
++static void
++nfsd_file_unhash_and_put(struct nfsd_file *nf)
++{
++      if (nfsd_file_unhash(nf))
++              nfsd_file_put_noref(nf);
++}
++
+ void
+ nfsd_file_put(struct nfsd_file *nf)
+ {
+       might_sleep();
+-      nfsd_file_lru_add(nf);
+-      if (test_bit(NFSD_FILE_HASHED, &nf->nf_flags) == 0) {
++      if (test_bit(NFSD_FILE_GC, &nf->nf_flags))
++              nfsd_file_lru_add(nf);
++      else if (refcount_read(&nf->nf_ref) == 2)
++              nfsd_file_unhash_and_put(nf);
++
++      if (!test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) {
+               nfsd_file_flush(nf);
+               nfsd_file_put_noref(nf);
+-      } else if (nf->nf_file) {
++      } else if (nf->nf_file && test_bit(NFSD_FILE_GC, &nf->nf_flags)) {
+               nfsd_file_put_noref(nf);
+               nfsd_file_schedule_laundrette();
+       } else
+@@ -1016,12 +1032,14 @@ nfsd_file_is_cached(struct inode *inode)
+ static __be32
+ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
+-                   unsigned int may_flags, struct nfsd_file **pnf, bool open)
++                   unsigned int may_flags, struct nfsd_file **pnf,
++                   bool open, bool want_gc)
+ {
+       struct nfsd_file_lookup_key key = {
+               .type   = NFSD_FILE_KEY_FULL,
+               .need   = may_flags & NFSD_FILE_MAY_MASK,
+               .net    = SVC_NET(rqstp),
++              .gc     = want_gc,
+       };
+       bool open_retry = true;
+       struct nfsd_file *nf;
+@@ -1117,14 +1135,35 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
+        * then unhash.
+        */
+       if (status != nfs_ok || key.inode->i_nlink == 0)
+-              if (nfsd_file_unhash(nf))
+-                      nfsd_file_put_noref(nf);
++              nfsd_file_unhash_and_put(nf);
+       clear_bit_unlock(NFSD_FILE_PENDING, &nf->nf_flags);
+       smp_mb__after_atomic();
+       wake_up_bit(&nf->nf_flags, NFSD_FILE_PENDING);
+       goto out;
+ }
++/**
++ * nfsd_file_acquire_gc - Get a struct nfsd_file with an open file
++ * @rqstp: the RPC transaction being executed
++ * @fhp: the NFS filehandle of the file to be opened
++ * @may_flags: NFSD_MAY_ settings for the file
++ * @pnf: OUT: new or found "struct nfsd_file" object
++ *
++ * The nfsd_file object returned by this API is reference-counted
++ * and garbage-collected. The object is retained for a few
++ * seconds after the final nfsd_file_put() in case the caller
++ * wants to re-use it.
++ *
++ * Returns nfs_ok and sets @pnf on success; otherwise an nfsstat in
++ * network byte order is returned.
++ */
++__be32
++nfsd_file_acquire_gc(struct svc_rqst *rqstp, struct svc_fh *fhp,
++                   unsigned int may_flags, struct nfsd_file **pnf)
++{
++      return nfsd_file_do_acquire(rqstp, fhp, may_flags, pnf, true, true);
++}
++
+ /**
+  * nfsd_file_acquire - Get a struct nfsd_file with an open file
+  * @rqstp: the RPC transaction being executed
+@@ -1132,6 +1171,10 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
+  * @may_flags: NFSD_MAY_ settings for the file
+  * @pnf: OUT: new or found "struct nfsd_file" object
+  *
++ * The nfsd_file_object returned by this API is reference-counted
++ * but not garbage-collected. The object is unhashed after the
++ * final nfsd_file_put().
++ *
+  * Returns nfs_ok and sets @pnf on success; otherwise an nfsstat in
+  * network byte order is returned.
+  */
+@@ -1139,7 +1182,7 @@ __be32
+ nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
+                 unsigned int may_flags, struct nfsd_file **pnf)
+ {
+-      return nfsd_file_do_acquire(rqstp, fhp, may_flags, pnf, true);
++      return nfsd_file_do_acquire(rqstp, fhp, may_flags, pnf, true, false);
+ }
+ /**
+@@ -1149,6 +1192,10 @@ nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
+  * @may_flags: NFSD_MAY_ settings for the file
+  * @pnf: OUT: new or found "struct nfsd_file" object
+  *
++ * The nfsd_file_object returned by this API is reference-counted
++ * but not garbage-collected. The object is released immediately
++ * one RCU grace period after the final nfsd_file_put().
++ *
+  * Returns nfs_ok and sets @pnf on success; otherwise an nfsstat in
+  * network byte order is returned.
+  */
+@@ -1156,7 +1203,7 @@ __be32
+ nfsd_file_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
+                unsigned int may_flags, struct nfsd_file **pnf)
+ {
+-      return nfsd_file_do_acquire(rqstp, fhp, may_flags, pnf, false);
++      return nfsd_file_do_acquire(rqstp, fhp, may_flags, pnf, false, false);
+ }
+ /*
+diff --git a/fs/nfsd/filecache.h b/fs/nfsd/filecache.h
+index 6b012ea4bd9d..b7efb2c3ddb1 100644
+--- a/fs/nfsd/filecache.h
++++ b/fs/nfsd/filecache.h
+@@ -38,6 +38,7 @@ struct nfsd_file {
+ #define NFSD_FILE_HASHED      (0)
+ #define NFSD_FILE_PENDING     (1)
+ #define NFSD_FILE_REFERENCED  (2)
++#define NFSD_FILE_GC          (3)
+       unsigned long           nf_flags;
+       struct inode            *nf_inode;      /* don't deref */
+       refcount_t              nf_ref;
+@@ -55,6 +56,8 @@ void nfsd_file_put(struct nfsd_file *nf);
+ struct nfsd_file *nfsd_file_get(struct nfsd_file *nf);
+ void nfsd_file_close_inode_sync(struct inode *inode);
+ bool nfsd_file_is_cached(struct inode *inode);
++__be32 nfsd_file_acquire_gc(struct svc_rqst *rqstp, struct svc_fh *fhp,
++                unsigned int may_flags, struct nfsd_file **nfp);
+ __be32 nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
+                 unsigned int may_flags, struct nfsd_file **nfp);
+ __be32 nfsd_file_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
+diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
+index ff2920546333..d01b29aba662 100644
+--- a/fs/nfsd/nfs3proc.c
++++ b/fs/nfsd/nfs3proc.c
+@@ -772,8 +772,8 @@ nfsd3_proc_commit(struct svc_rqst *rqstp)
+                               (unsigned long long) argp->offset);
+       fh_copy(&resp->fh, &argp->fh);
+-      resp->status = nfsd_file_acquire(rqstp, &resp->fh, NFSD_MAY_WRITE |
+-                                       NFSD_MAY_NOT_BREAK_LEASE, &nf);
++      resp->status = nfsd_file_acquire_gc(rqstp, &resp->fh, NFSD_MAY_WRITE |
++                                          NFSD_MAY_NOT_BREAK_LEASE, &nf);
+       if (resp->status)
+               goto out;
+       resp->status = nfsd_commit(rqstp, &resp->fh, nf, argp->offset,
+diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h
+index d4b6839bb459..3fcfeb7b560f 100644
+--- a/fs/nfsd/trace.h
++++ b/fs/nfsd/trace.h
+@@ -817,7 +817,8 @@ DEFINE_CLID_EVENT(confirmed_r);
+       __print_flags(val, "|",                                         \
+               { 1 << NFSD_FILE_HASHED,        "HASHED" },             \
+               { 1 << NFSD_FILE_PENDING,       "PENDING" },            \
+-              { 1 << NFSD_FILE_REFERENCED,    "REFERENCED"})
++              { 1 << NFSD_FILE_REFERENCED,    "REFERENCED"},          \
++              { 1 << NFSD_FILE_GC,            "GC"})
+ DECLARE_EVENT_CLASS(nfsd_file_class,
+       TP_PROTO(struct nfsd_file *nf),
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index f1919834a99d..2934ab1d9862 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1085,7 +1085,7 @@ __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
+       __be32 err;
+       trace_nfsd_read_start(rqstp, fhp, offset, *count);
+-      err = nfsd_file_acquire(rqstp, fhp, NFSD_MAY_READ, &nf);
++      err = nfsd_file_acquire_gc(rqstp, fhp, NFSD_MAY_READ, &nf);
+       if (err)
+               return err;
+@@ -1117,7 +1117,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
+       trace_nfsd_write_start(rqstp, fhp, offset, *cnt);
+-      err = nfsd_file_acquire(rqstp, fhp, NFSD_MAY_WRITE, &nf);
++      err = nfsd_file_acquire_gc(rqstp, fhp, NFSD_MAY_WRITE, &nf);
+       if (err)
+               goto out;
+-- 
+2.35.1
+
diff --git a/queue-6.1/nfsd-fix-handling-of-cached-open-files-in-nfsd4_open.patch b/queue-6.1/nfsd-fix-handling-of-cached-open-files-in-nfsd4_open.patch
new file mode 100644 (file)
index 0000000..eb1334c
--- /dev/null
@@ -0,0 +1,273 @@
+From 06edd77f710b4e2d4727422d8a698e26d48034fe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 5 Jan 2023 14:55:56 -0500
+Subject: nfsd: fix handling of cached open files in nfsd4_open codepath
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit 0b3a551fa58b4da941efeb209b3770868e2eddd7 ]
+
+Commit fb70bf124b05 ("NFSD: Instantiate a struct file when creating a
+regular NFSv4 file") added the ability to cache an open fd over a
+compound. There are a couple of problems with the way this currently
+works:
+
+It's racy, as a newly-created nfsd_file can end up with its PENDING bit
+cleared while the nf is hashed, and the nf_file pointer is still zeroed
+out. Other tasks can find it in this state and they expect to see a
+valid nf_file, and can oops if nf_file is NULL.
+
+Also, there is no guarantee that we'll end up creating a new nfsd_file
+if one is already in the hash. If an extant entry is in the hash with a
+valid nf_file, nfs4_get_vfs_file will clobber its nf_file pointer with
+the value of op_file and the old nf_file will leak.
+
+Fix both issues by making a new nfsd_file_acquirei_opened variant that
+takes an optional file pointer. If one is present when this is called,
+we'll take a new reference to it instead of trying to open the file. If
+the nfsd_file already has a valid nf_file, we'll just ignore the
+optional file and pass the nfsd_file back as-is.
+
+Also rework the tracepoints a bit to allow for an "opened" variant and
+don't try to avoid counting acquisitions in the case where we already
+have a cached open file.
+
+Fixes: fb70bf124b05 ("NFSD: Instantiate a struct file when creating a regular NFSv4 file")
+Cc: Trond Myklebust <trondmy@hammerspace.com>
+Reported-by: Stanislav Saner <ssaner@redhat.com>
+Reported-and-Tested-by: Ruben Vestergaard <rubenv@drcmr.dk>
+Reported-and-Tested-by: Torkil Svensgaard <torkil@drcmr.dk>
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/filecache.c | 40 ++++++++++++++++++----------------
+ fs/nfsd/filecache.h |  5 +++--
+ fs/nfsd/nfs4state.c | 16 ++++----------
+ fs/nfsd/trace.h     | 52 ++++++++++++---------------------------------
+ 4 files changed, 42 insertions(+), 71 deletions(-)
+
+diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c
+index 9bf78506d071..ea6fb0e6b165 100644
+--- a/fs/nfsd/filecache.c
++++ b/fs/nfsd/filecache.c
+@@ -1048,8 +1048,8 @@ nfsd_file_is_cached(struct inode *inode)
+ static __be32
+ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
+-                   unsigned int may_flags, struct nfsd_file **pnf,
+-                   bool open, bool want_gc)
++                   unsigned int may_flags, struct file *file,
++                   struct nfsd_file **pnf, bool want_gc)
+ {
+       struct nfsd_file_lookup_key key = {
+               .type   = NFSD_FILE_KEY_FULL,
+@@ -1124,8 +1124,7 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
+       status = nfserrno(nfsd_open_break_lease(file_inode(nf->nf_file), may_flags));
+ out:
+       if (status == nfs_ok) {
+-              if (open)
+-                      this_cpu_inc(nfsd_file_acquisitions);
++              this_cpu_inc(nfsd_file_acquisitions);
+               *pnf = nf;
+       } else {
+               if (refcount_dec_and_test(&nf->nf_ref))
+@@ -1135,20 +1134,23 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
+ out_status:
+       put_cred(key.cred);
+-      if (open)
+-              trace_nfsd_file_acquire(rqstp, key.inode, may_flags, nf, status);
++      trace_nfsd_file_acquire(rqstp, key.inode, may_flags, nf, status);
+       return status;
+ open_file:
+       trace_nfsd_file_alloc(nf);
+       nf->nf_mark = nfsd_file_mark_find_or_create(nf, key.inode);
+       if (nf->nf_mark) {
+-              if (open) {
++              if (file) {
++                      get_file(file);
++                      nf->nf_file = file;
++                      status = nfs_ok;
++                      trace_nfsd_file_opened(nf, status);
++              } else {
+                       status = nfsd_open_verified(rqstp, fhp, may_flags,
+                                                   &nf->nf_file);
+                       trace_nfsd_file_open(nf, status);
+-              } else
+-                      status = nfs_ok;
++              }
+       } else
+               status = nfserr_jukebox;
+       /*
+@@ -1184,7 +1186,7 @@ __be32
+ nfsd_file_acquire_gc(struct svc_rqst *rqstp, struct svc_fh *fhp,
+                    unsigned int may_flags, struct nfsd_file **pnf)
+ {
+-      return nfsd_file_do_acquire(rqstp, fhp, may_flags, pnf, true, true);
++      return nfsd_file_do_acquire(rqstp, fhp, may_flags, NULL, pnf, true);
+ }
+ /**
+@@ -1205,28 +1207,30 @@ __be32
+ nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
+                 unsigned int may_flags, struct nfsd_file **pnf)
+ {
+-      return nfsd_file_do_acquire(rqstp, fhp, may_flags, pnf, true, false);
++      return nfsd_file_do_acquire(rqstp, fhp, may_flags, NULL, pnf, false);
+ }
+ /**
+- * nfsd_file_create - Get a struct nfsd_file, do not open
++ * nfsd_file_acquire_opened - Get a struct nfsd_file using existing open file
+  * @rqstp: the RPC transaction being executed
+  * @fhp: the NFS filehandle of the file just created
+  * @may_flags: NFSD_MAY_ settings for the file
++ * @file: cached, already-open file (may be NULL)
+  * @pnf: OUT: new or found "struct nfsd_file" object
+  *
+- * The nfsd_file_object returned by this API is reference-counted
+- * but not garbage-collected. The object is released immediately
+- * one RCU grace period after the final nfsd_file_put().
++ * Acquire a nfsd_file object that is not GC'ed. If one doesn't already exist,
++ * and @file is non-NULL, use it to instantiate a new nfsd_file instead of
++ * opening a new one.
+  *
+  * Returns nfs_ok and sets @pnf on success; otherwise an nfsstat in
+  * network byte order is returned.
+  */
+ __be32
+-nfsd_file_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
+-               unsigned int may_flags, struct nfsd_file **pnf)
++nfsd_file_acquire_opened(struct svc_rqst *rqstp, struct svc_fh *fhp,
++                       unsigned int may_flags, struct file *file,
++                       struct nfsd_file **pnf)
+ {
+-      return nfsd_file_do_acquire(rqstp, fhp, may_flags, pnf, false, false);
++      return nfsd_file_do_acquire(rqstp, fhp, may_flags, file, pnf, false);
+ }
+ /*
+diff --git a/fs/nfsd/filecache.h b/fs/nfsd/filecache.h
+index b7efb2c3ddb1..41516a4263ea 100644
+--- a/fs/nfsd/filecache.h
++++ b/fs/nfsd/filecache.h
+@@ -60,7 +60,8 @@ __be32 nfsd_file_acquire_gc(struct svc_rqst *rqstp, struct svc_fh *fhp,
+                 unsigned int may_flags, struct nfsd_file **nfp);
+ __be32 nfsd_file_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
+                 unsigned int may_flags, struct nfsd_file **nfp);
+-__be32 nfsd_file_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
+-                unsigned int may_flags, struct nfsd_file **nfp);
++__be32 nfsd_file_acquire_opened(struct svc_rqst *rqstp, struct svc_fh *fhp,
++                unsigned int may_flags, struct file *file,
++                struct nfsd_file **nfp);
+ int nfsd_file_cache_stats_show(struct seq_file *m, void *v);
+ #endif /* _FS_NFSD_FILECACHE_H */
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 16c3e991ddcc..2247d107da90 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -5211,18 +5211,10 @@ static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp,
+       if (!fp->fi_fds[oflag]) {
+               spin_unlock(&fp->fi_lock);
+-              if (!open->op_filp) {
+-                      status = nfsd_file_acquire(rqstp, cur_fh, access, &nf);
+-                      if (status != nfs_ok)
+-                              goto out_put_access;
+-              } else {
+-                      status = nfsd_file_create(rqstp, cur_fh, access, &nf);
+-                      if (status != nfs_ok)
+-                              goto out_put_access;
+-                      nf->nf_file = open->op_filp;
+-                      open->op_filp = NULL;
+-                      trace_nfsd_file_create(rqstp, access, nf);
+-              }
++              status = nfsd_file_acquire_opened(rqstp, cur_fh, access,
++                                                open->op_filp, &nf);
++              if (status != nfs_ok)
++                      goto out_put_access;
+               spin_lock(&fp->fi_lock);
+               if (!fp->fi_fds[oflag]) {
+diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h
+index 4feeaed32541..4eb4e1039c7f 100644
+--- a/fs/nfsd/trace.h
++++ b/fs/nfsd/trace.h
+@@ -922,43 +922,6 @@ TRACE_EVENT(nfsd_file_acquire,
+       )
+ );
+-TRACE_EVENT(nfsd_file_create,
+-      TP_PROTO(
+-              const struct svc_rqst *rqstp,
+-              unsigned int may_flags,
+-              const struct nfsd_file *nf
+-      ),
+-
+-      TP_ARGS(rqstp, may_flags, nf),
+-
+-      TP_STRUCT__entry(
+-              __field(const void *, nf_inode)
+-              __field(const void *, nf_file)
+-              __field(unsigned long, may_flags)
+-              __field(unsigned long, nf_flags)
+-              __field(unsigned long, nf_may)
+-              __field(unsigned int, nf_ref)
+-              __field(u32, xid)
+-      ),
+-
+-      TP_fast_assign(
+-              __entry->nf_inode = nf->nf_inode;
+-              __entry->nf_file = nf->nf_file;
+-              __entry->may_flags = may_flags;
+-              __entry->nf_flags = nf->nf_flags;
+-              __entry->nf_may = nf->nf_may;
+-              __entry->nf_ref = refcount_read(&nf->nf_ref);
+-              __entry->xid = be32_to_cpu(rqstp->rq_xid);
+-      ),
+-
+-      TP_printk("xid=0x%x inode=%p may_flags=%s ref=%u nf_flags=%s nf_may=%s nf_file=%p",
+-              __entry->xid, __entry->nf_inode,
+-              show_nfsd_may_flags(__entry->may_flags),
+-              __entry->nf_ref, show_nf_flags(__entry->nf_flags),
+-              show_nfsd_may_flags(__entry->nf_may), __entry->nf_file
+-      )
+-);
+-
+ TRACE_EVENT(nfsd_file_insert_err,
+       TP_PROTO(
+               const struct svc_rqst *rqstp,
+@@ -1020,8 +983,8 @@ TRACE_EVENT(nfsd_file_cons_err,
+       )
+ );
+-TRACE_EVENT(nfsd_file_open,
+-      TP_PROTO(struct nfsd_file *nf, __be32 status),
++DECLARE_EVENT_CLASS(nfsd_file_open_class,
++      TP_PROTO(const struct nfsd_file *nf, __be32 status),
+       TP_ARGS(nf, status),
+       TP_STRUCT__entry(
+               __field(void *, nf_inode)       /* cannot be dereferenced */
+@@ -1045,6 +1008,17 @@ TRACE_EVENT(nfsd_file_open,
+               __entry->nf_file)
+ )
++#define DEFINE_NFSD_FILE_OPEN_EVENT(name)                                     \
++DEFINE_EVENT(nfsd_file_open_class, name,                                      \
++      TP_PROTO(                                                       \
++              const struct nfsd_file *nf,                             \
++              __be32 status                                           \
++      ),                                                              \
++      TP_ARGS(nf, status))
++
++DEFINE_NFSD_FILE_OPEN_EVENT(nfsd_file_open);
++DEFINE_NFSD_FILE_OPEN_EVENT(nfsd_file_opened);
++
+ TRACE_EVENT(nfsd_file_is_cached,
+       TP_PROTO(
+               const struct inode *inode,
+-- 
+2.35.1
+
diff --git a/queue-6.1/nfsd-pass-the-target-nfsd_file-to-nfsd_commit.patch b/queue-6.1/nfsd-pass-the-target-nfsd_file-to-nfsd_commit.patch
new file mode 100644 (file)
index 0000000..426611f
--- /dev/null
@@ -0,0 +1,153 @@
+From 631c0a99c74f4d87bddfe2f0aa79ce12653e8323 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Oct 2022 10:46:38 -0400
+Subject: NFSD: Pass the target nfsd_file to nfsd_commit()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit c252849082ff525af18b4f253b3c9ece94e951ed ]
+
+In a moment I'm going to introduce separate nfsd_file types, one of
+which is garbage-collected; the other, not. The garbage-collected
+variety is to be used by NFSv2 and v3, and the non-garbage-collected
+variety is to be used by NFSv4.
+
+nfsd_commit() is invoked by both NFSv3 and NFSv4 consumers. We want
+nfsd_commit() to find and use the correct variety of cached
+nfsd_file object for the NFS version that is in use.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Tested-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: NeilBrown <neilb@suse.de>
+Stable-dep-of: 0b3a551fa58b ("nfsd: fix handling of cached open files in nfsd4_open codepath")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/nfs3proc.c | 10 +++++++++-
+ fs/nfsd/nfs4proc.c | 11 ++++++++++-
+ fs/nfsd/vfs.c      | 15 ++++-----------
+ fs/nfsd/vfs.h      |  3 ++-
+ 4 files changed, 25 insertions(+), 14 deletions(-)
+
+diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
+index 923d9a80df92..ff2920546333 100644
+--- a/fs/nfsd/nfs3proc.c
++++ b/fs/nfsd/nfs3proc.c
+@@ -13,6 +13,7 @@
+ #include "cache.h"
+ #include "xdr3.h"
+ #include "vfs.h"
++#include "filecache.h"
+ #define NFSDDBG_FACILITY              NFSDDBG_PROC
+@@ -763,6 +764,7 @@ nfsd3_proc_commit(struct svc_rqst *rqstp)
+ {
+       struct nfsd3_commitargs *argp = rqstp->rq_argp;
+       struct nfsd3_commitres *resp = rqstp->rq_resp;
++      struct nfsd_file *nf;
+       dprintk("nfsd: COMMIT(3)   %s %u@%Lu\n",
+                               SVCFH_fmt(&argp->fh),
+@@ -770,8 +772,14 @@ nfsd3_proc_commit(struct svc_rqst *rqstp)
+                               (unsigned long long) argp->offset);
+       fh_copy(&resp->fh, &argp->fh);
+-      resp->status = nfsd_commit(rqstp, &resp->fh, argp->offset,
++      resp->status = nfsd_file_acquire(rqstp, &resp->fh, NFSD_MAY_WRITE |
++                                       NFSD_MAY_NOT_BREAK_LEASE, &nf);
++      if (resp->status)
++              goto out;
++      resp->status = nfsd_commit(rqstp, &resp->fh, nf, argp->offset,
+                                  argp->count, resp->verf);
++      nfsd_file_put(nf);
++out:
+       return rpc_success;
+ }
+diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
+index c7329523a10f..30a08ec31a70 100644
+--- a/fs/nfsd/nfs4proc.c
++++ b/fs/nfsd/nfs4proc.c
+@@ -731,10 +731,19 @@ nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+            union nfsd4_op_u *u)
+ {
+       struct nfsd4_commit *commit = &u->commit;
++      struct nfsd_file *nf;
++      __be32 status;
+-      return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
++      status = nfsd_file_acquire(rqstp, &cstate->current_fh, NFSD_MAY_WRITE |
++                                 NFSD_MAY_NOT_BREAK_LEASE, &nf);
++      if (status != nfs_ok)
++              return status;
++
++      status = nfsd_commit(rqstp, &cstate->current_fh, nf, commit->co_offset,
+                            commit->co_count,
+                            (__be32 *)commit->co_verf.data);
++      nfsd_file_put(nf);
++      return status;
+ }
+ static __be32
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 849a720ab43f..f1919834a99d 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -1133,6 +1133,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
+  * nfsd_commit - Commit pending writes to stable storage
+  * @rqstp: RPC request being processed
+  * @fhp: NFS filehandle
++ * @nf: target file
+  * @offset: raw offset from beginning of file
+  * @count: raw count of bytes to sync
+  * @verf: filled in with the server's current write verifier
+@@ -1149,19 +1150,13 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
+  *   An nfsstat value in network byte order.
+  */
+ __be32
+-nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, u64 offset,
+-          u32 count, __be32 *verf)
++nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf,
++          u64 offset, u32 count, __be32 *verf)
+ {
++      __be32                  err = nfs_ok;
+       u64                     maxbytes;
+       loff_t                  start, end;
+       struct nfsd_net         *nn;
+-      struct nfsd_file        *nf;
+-      __be32                  err;
+-
+-      err = nfsd_file_acquire(rqstp, fhp,
+-                      NFSD_MAY_WRITE|NFSD_MAY_NOT_BREAK_LEASE, &nf);
+-      if (err)
+-              goto out;
+       /*
+        * Convert the client-provided (offset, count) range to a
+@@ -1202,8 +1197,6 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, u64 offset,
+       } else
+               nfsd_copy_write_verifier(verf, nn);
+-      nfsd_file_put(nf);
+-out:
+       return err;
+ }
+diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
+index 120521bc7b24..9744b041105b 100644
+--- a/fs/nfsd/vfs.h
++++ b/fs/nfsd/vfs.h
+@@ -88,7 +88,8 @@ __be32               nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *);
+ __be32                nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
+                               struct svc_fh *resfhp, struct nfsd_attrs *iap);
+ __be32                nfsd_commit(struct svc_rqst *rqst, struct svc_fh *fhp,
+-                              u64 offset, u32 count, __be32 *verf);
++                              struct nfsd_file *nf, u64 offset, u32 count,
++                              __be32 *verf);
+ #ifdef CONFIG_NFSD_V4
+ __be32                nfsd_getxattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
+                           char *name, void **bufp, int *lenp);
+-- 
+2.35.1
+
diff --git a/queue-6.1/nfsd-remove-the-pages_flushed-statistic-from-filecac.patch b/queue-6.1/nfsd-remove-the-pages_flushed-statistic-from-filecac.patch
new file mode 100644 (file)
index 0000000..f5b7843
--- /dev/null
@@ -0,0 +1,76 @@
+From 959abbdc7fadfe08b0c7c1ce8e2d0344016986f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Nov 2022 14:44:47 -0400
+Subject: nfsd: remove the pages_flushed statistic from filecache
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit 1f696e230ea5198e393368b319eb55651828d687 ]
+
+We're counting mapping->nrpages, but not all of those are necessarily
+dirty. We don't really have a simple way to count just the dirty pages,
+so just remove this stat since it's not accurate.
+
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Stable-dep-of: 0b3a551fa58b ("nfsd: fix handling of cached open files in nfsd4_open codepath")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/filecache.c | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c
+index cee44405cf7d..28fff3672df9 100644
+--- a/fs/nfsd/filecache.c
++++ b/fs/nfsd/filecache.c
+@@ -33,7 +33,6 @@ static DEFINE_PER_CPU(unsigned long, nfsd_file_cache_hits);
+ static DEFINE_PER_CPU(unsigned long, nfsd_file_acquisitions);
+ static DEFINE_PER_CPU(unsigned long, nfsd_file_releases);
+ static DEFINE_PER_CPU(unsigned long, nfsd_file_total_age);
+-static DEFINE_PER_CPU(unsigned long, nfsd_file_pages_flushed);
+ static DEFINE_PER_CPU(unsigned long, nfsd_file_evictions);
+ struct nfsd_fcache_disposal {
+@@ -371,7 +370,6 @@ nfsd_file_flush(struct nfsd_file *nf)
+       if (!file || !(file->f_mode & FMODE_WRITE))
+               return;
+-      this_cpu_add(nfsd_file_pages_flushed, file->f_mapping->nrpages);
+       if (vfs_fsync(file, 1) != 0)
+               nfsd_reset_write_verifier(net_generic(nf->nf_net, nfsd_net_id));
+ }
+@@ -998,7 +996,6 @@ nfsd_file_cache_shutdown(void)
+               per_cpu(nfsd_file_acquisitions, i) = 0;
+               per_cpu(nfsd_file_releases, i) = 0;
+               per_cpu(nfsd_file_total_age, i) = 0;
+-              per_cpu(nfsd_file_pages_flushed, i) = 0;
+               per_cpu(nfsd_file_evictions, i) = 0;
+       }
+ }
+@@ -1213,7 +1210,7 @@ nfsd_file_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
+  */
+ int nfsd_file_cache_stats_show(struct seq_file *m, void *v)
+ {
+-      unsigned long releases = 0, pages_flushed = 0, evictions = 0;
++      unsigned long releases = 0, evictions = 0;
+       unsigned long hits = 0, acquisitions = 0;
+       unsigned int i, count = 0, buckets = 0;
+       unsigned long lru = 0, total_age = 0;
+@@ -1241,7 +1238,6 @@ int nfsd_file_cache_stats_show(struct seq_file *m, void *v)
+               releases += per_cpu(nfsd_file_releases, i);
+               total_age += per_cpu(nfsd_file_total_age, i);
+               evictions += per_cpu(nfsd_file_evictions, i);
+-              pages_flushed += per_cpu(nfsd_file_pages_flushed, i);
+       }
+       seq_printf(m, "total entries: %u\n", count);
+@@ -1255,6 +1251,5 @@ int nfsd_file_cache_stats_show(struct seq_file *m, void *v)
+               seq_printf(m, "mean age (ms): %ld\n", total_age / releases);
+       else
+               seq_printf(m, "mean age (ms): -\n");
+-      seq_printf(m, "pages flushed: %lu\n", pages_flushed);
+       return 0;
+ }
+-- 
+2.35.1
+
diff --git a/queue-6.1/nfsd-reorganize-filecache.c.patch b/queue-6.1/nfsd-reorganize-filecache.c.patch
new file mode 100644 (file)
index 0000000..09ea3ea
--- /dev/null
@@ -0,0 +1,240 @@
+From de76c3bb47aa0615447be482132f7cf8ede2c34e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Nov 2022 14:44:48 -0400
+Subject: nfsd: reorganize filecache.c
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit 8214118589881b2d390284410c5ff275e7a5e03c ]
+
+In a coming patch, we're going to rework how the filecache refcounting
+works. Move some code around in the function to reduce the churn in the
+later patches, and rename some of the functions with (hopefully) clearer
+names: nfsd_file_flush becomes nfsd_file_fsync, and
+nfsd_file_unhash_and_dispose is renamed to nfsd_file_unhash_and_queue.
+
+Also, the nfsd_file_put_final tracepoint is renamed to nfsd_file_free,
+to better match the name of the function from which it's called.
+
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: NeilBrown <neilb@suse.de>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Stable-dep-of: 0b3a551fa58b ("nfsd: fix handling of cached open files in nfsd4_open codepath")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/filecache.c | 111 ++++++++++++++++++++++----------------------
+ fs/nfsd/trace.h     |   4 +-
+ 2 files changed, 58 insertions(+), 57 deletions(-)
+
+diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c
+index 28fff3672df9..f54dd6695741 100644
+--- a/fs/nfsd/filecache.c
++++ b/fs/nfsd/filecache.c
+@@ -310,16 +310,59 @@ nfsd_file_alloc(struct nfsd_file_lookup_key *key, unsigned int may)
+       return nf;
+ }
++static void
++nfsd_file_fsync(struct nfsd_file *nf)
++{
++      struct file *file = nf->nf_file;
++
++      if (!file || !(file->f_mode & FMODE_WRITE))
++              return;
++      if (vfs_fsync(file, 1) != 0)
++              nfsd_reset_write_verifier(net_generic(nf->nf_net, nfsd_net_id));
++}
++
++static int
++nfsd_file_check_write_error(struct nfsd_file *nf)
++{
++      struct file *file = nf->nf_file;
++
++      if (!file || !(file->f_mode & FMODE_WRITE))
++              return 0;
++      return filemap_check_wb_err(file->f_mapping, READ_ONCE(file->f_wb_err));
++}
++
++static void
++nfsd_file_hash_remove(struct nfsd_file *nf)
++{
++      trace_nfsd_file_unhash(nf);
++
++      if (nfsd_file_check_write_error(nf))
++              nfsd_reset_write_verifier(net_generic(nf->nf_net, nfsd_net_id));
++      rhashtable_remove_fast(&nfsd_file_rhash_tbl, &nf->nf_rhash,
++                             nfsd_file_rhash_params);
++}
++
++static bool
++nfsd_file_unhash(struct nfsd_file *nf)
++{
++      if (test_and_clear_bit(NFSD_FILE_HASHED, &nf->nf_flags)) {
++              nfsd_file_hash_remove(nf);
++              return true;
++      }
++      return false;
++}
++
+ static bool
+ nfsd_file_free(struct nfsd_file *nf)
+ {
+       s64 age = ktime_to_ms(ktime_sub(ktime_get(), nf->nf_birthtime));
+       bool flush = false;
++      trace_nfsd_file_free(nf);
++
+       this_cpu_inc(nfsd_file_releases);
+       this_cpu_add(nfsd_file_total_age, age);
+-      trace_nfsd_file_put_final(nf);
+       if (nf->nf_mark)
+               nfsd_file_mark_put(nf->nf_mark);
+       if (nf->nf_file) {
+@@ -353,27 +396,6 @@ nfsd_file_check_writeback(struct nfsd_file *nf)
+               mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK);
+ }
+-static int
+-nfsd_file_check_write_error(struct nfsd_file *nf)
+-{
+-      struct file *file = nf->nf_file;
+-
+-      if (!file || !(file->f_mode & FMODE_WRITE))
+-              return 0;
+-      return filemap_check_wb_err(file->f_mapping, READ_ONCE(file->f_wb_err));
+-}
+-
+-static void
+-nfsd_file_flush(struct nfsd_file *nf)
+-{
+-      struct file *file = nf->nf_file;
+-
+-      if (!file || !(file->f_mode & FMODE_WRITE))
+-              return;
+-      if (vfs_fsync(file, 1) != 0)
+-              nfsd_reset_write_verifier(net_generic(nf->nf_net, nfsd_net_id));
+-}
+-
+ static void nfsd_file_lru_add(struct nfsd_file *nf)
+ {
+       set_bit(NFSD_FILE_REFERENCED, &nf->nf_flags);
+@@ -387,31 +409,18 @@ static void nfsd_file_lru_remove(struct nfsd_file *nf)
+               trace_nfsd_file_lru_del(nf);
+ }
+-static void
+-nfsd_file_hash_remove(struct nfsd_file *nf)
+-{
+-      trace_nfsd_file_unhash(nf);
+-
+-      if (nfsd_file_check_write_error(nf))
+-              nfsd_reset_write_verifier(net_generic(nf->nf_net, nfsd_net_id));
+-      rhashtable_remove_fast(&nfsd_file_rhash_tbl, &nf->nf_rhash,
+-                             nfsd_file_rhash_params);
+-}
+-
+-static bool
+-nfsd_file_unhash(struct nfsd_file *nf)
++struct nfsd_file *
++nfsd_file_get(struct nfsd_file *nf)
+ {
+-      if (test_and_clear_bit(NFSD_FILE_HASHED, &nf->nf_flags)) {
+-              nfsd_file_hash_remove(nf);
+-              return true;
+-      }
+-      return false;
++      if (likely(refcount_inc_not_zero(&nf->nf_ref)))
++              return nf;
++      return NULL;
+ }
+ static void
+-nfsd_file_unhash_and_dispose(struct nfsd_file *nf, struct list_head *dispose)
++nfsd_file_unhash_and_queue(struct nfsd_file *nf, struct list_head *dispose)
+ {
+-      trace_nfsd_file_unhash_and_dispose(nf);
++      trace_nfsd_file_unhash_and_queue(nf);
+       if (nfsd_file_unhash(nf)) {
+               /* caller must call nfsd_file_dispose_list() later */
+               nfsd_file_lru_remove(nf);
+@@ -449,7 +458,7 @@ nfsd_file_put(struct nfsd_file *nf)
+               nfsd_file_unhash_and_put(nf);
+       if (!test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) {
+-              nfsd_file_flush(nf);
++              nfsd_file_fsync(nf);
+               nfsd_file_put_noref(nf);
+       } else if (nf->nf_file && test_bit(NFSD_FILE_GC, &nf->nf_flags)) {
+               nfsd_file_put_noref(nf);
+@@ -458,14 +467,6 @@ nfsd_file_put(struct nfsd_file *nf)
+               nfsd_file_put_noref(nf);
+ }
+-struct nfsd_file *
+-nfsd_file_get(struct nfsd_file *nf)
+-{
+-      if (likely(refcount_inc_not_zero(&nf->nf_ref)))
+-              return nf;
+-      return NULL;
+-}
+-
+ static void
+ nfsd_file_dispose_list(struct list_head *dispose)
+ {
+@@ -474,7 +475,7 @@ nfsd_file_dispose_list(struct list_head *dispose)
+       while(!list_empty(dispose)) {
+               nf = list_first_entry(dispose, struct nfsd_file, nf_lru);
+               list_del_init(&nf->nf_lru);
+-              nfsd_file_flush(nf);
++              nfsd_file_fsync(nf);
+               nfsd_file_put_noref(nf);
+       }
+ }
+@@ -488,7 +489,7 @@ nfsd_file_dispose_list_sync(struct list_head *dispose)
+       while(!list_empty(dispose)) {
+               nf = list_first_entry(dispose, struct nfsd_file, nf_lru);
+               list_del_init(&nf->nf_lru);
+-              nfsd_file_flush(nf);
++              nfsd_file_fsync(nf);
+               if (!refcount_dec_and_test(&nf->nf_ref))
+                       continue;
+               if (nfsd_file_free(nf))
+@@ -688,7 +689,7 @@ __nfsd_file_close_inode(struct inode *inode, struct list_head *dispose)
+                                      nfsd_file_rhash_params);
+               if (!nf)
+                       break;
+-              nfsd_file_unhash_and_dispose(nf, dispose);
++              nfsd_file_unhash_and_queue(nf, dispose);
+               count++;
+       } while (1);
+       rcu_read_unlock();
+@@ -890,7 +891,7 @@ __nfsd_file_cache_purge(struct net *net)
+               nf = rhashtable_walk_next(&iter);
+               while (!IS_ERR_OR_NULL(nf)) {
+                       if (!net || nf->nf_net == net)
+-                              nfsd_file_unhash_and_dispose(nf, &dispose);
++                              nfsd_file_unhash_and_queue(nf, &dispose);
+                       nf = rhashtable_walk_next(&iter);
+               }
+diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h
+index 3fcfeb7b560f..55e9e19cb1ec 100644
+--- a/fs/nfsd/trace.h
++++ b/fs/nfsd/trace.h
+@@ -850,10 +850,10 @@ DEFINE_EVENT(nfsd_file_class, name, \
+       TP_PROTO(struct nfsd_file *nf), \
+       TP_ARGS(nf))
+-DEFINE_NFSD_FILE_EVENT(nfsd_file_put_final);
++DEFINE_NFSD_FILE_EVENT(nfsd_file_free);
+ DEFINE_NFSD_FILE_EVENT(nfsd_file_unhash);
+ DEFINE_NFSD_FILE_EVENT(nfsd_file_put);
+-DEFINE_NFSD_FILE_EVENT(nfsd_file_unhash_and_dispose);
++DEFINE_NFSD_FILE_EVENT(nfsd_file_unhash_and_queue);
+ TRACE_EVENT(nfsd_file_alloc,
+       TP_PROTO(
+-- 
+2.35.1
+
diff --git a/queue-6.1/nfsd-revert-nfsd-nfsv4-close-should-release-an-nfsd_.patch b/queue-6.1/nfsd-revert-nfsd-nfsv4-close-should-release-an-nfsd_.patch
new file mode 100644 (file)
index 0000000..577852d
--- /dev/null
@@ -0,0 +1,96 @@
+From 16d066330e4495eae9987ba3becf18a876f562ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 Oct 2022 10:46:44 -0400
+Subject: NFSD: Revert "NFSD: NFSv4 CLOSE should release an nfsd_file
+ immediately"
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit dcf3f80965ca787c70def402cdf1553c93c75529 ]
+
+This reverts commit 5e138c4a750dc140d881dab4a8804b094bbc08d2.
+
+That commit attempted to make files available to other users as soon
+as all NFSv4 clients were done with them, rather than waiting until
+the filecache LRU had garbage collected them.
+
+It gets the reference counting wrong, for one thing.
+
+But it also misses that DELEGRETURN should release a file in the
+same fashion. In fact, any nfsd_file_put() on an file held open
+by an NFSv4 client needs potentially to release the file
+immediately...
+
+Clear the way for implementing that idea.
+
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: NeilBrown <neilb@suse.de>
+Stable-dep-of: 0b3a551fa58b ("nfsd: fix handling of cached open files in nfsd4_open codepath")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/filecache.c | 18 ------------------
+ fs/nfsd/filecache.h |  1 -
+ fs/nfsd/nfs4state.c |  4 ++--
+ 3 files changed, 2 insertions(+), 21 deletions(-)
+
+diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c
+index ec3fceb92236..babea79d3f6f 100644
+--- a/fs/nfsd/filecache.c
++++ b/fs/nfsd/filecache.c
+@@ -444,24 +444,6 @@ nfsd_file_put(struct nfsd_file *nf)
+               nfsd_file_put_noref(nf);
+ }
+-/**
+- * nfsd_file_close - Close an nfsd_file
+- * @nf: nfsd_file to close
+- *
+- * If this is the final reference for @nf, free it immediately.
+- * This reflects an on-the-wire CLOSE or DELEGRETURN into the
+- * VFS and exported filesystem.
+- */
+-void nfsd_file_close(struct nfsd_file *nf)
+-{
+-      nfsd_file_put(nf);
+-      if (refcount_dec_if_one(&nf->nf_ref)) {
+-              nfsd_file_unhash(nf);
+-              nfsd_file_lru_remove(nf);
+-              nfsd_file_free(nf);
+-      }
+-}
+-
+ struct nfsd_file *
+ nfsd_file_get(struct nfsd_file *nf)
+ {
+diff --git a/fs/nfsd/filecache.h b/fs/nfsd/filecache.h
+index 357832bac736..6b012ea4bd9d 100644
+--- a/fs/nfsd/filecache.h
++++ b/fs/nfsd/filecache.h
+@@ -52,7 +52,6 @@ void nfsd_file_cache_shutdown(void);
+ int nfsd_file_cache_start_net(struct net *net);
+ void nfsd_file_cache_shutdown_net(struct net *net);
+ void nfsd_file_put(struct nfsd_file *nf);
+-void nfsd_file_close(struct nfsd_file *nf);
+ struct nfsd_file *nfsd_file_get(struct nfsd_file *nf);
+ void nfsd_file_close_inode_sync(struct inode *inode);
+ bool nfsd_file_is_cached(struct inode *inode);
+diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
+index 52b5552d0d70..16c3e991ddcc 100644
+--- a/fs/nfsd/nfs4state.c
++++ b/fs/nfsd/nfs4state.c
+@@ -842,9 +842,9 @@ static void __nfs4_file_put_access(struct nfs4_file *fp, int oflag)
+                       swap(f2, fp->fi_fds[O_RDWR]);
+               spin_unlock(&fp->fi_lock);
+               if (f1)
+-                      nfsd_file_close(f1);
++                      nfsd_file_put(f1);
+               if (f2)
+-                      nfsd_file_close(f2);
++                      nfsd_file_put(f2);
+       }
+ }
+-- 
+2.35.1
+
diff --git a/queue-6.1/nfsd-rework-refcounting-in-filecache.patch b/queue-6.1/nfsd-rework-refcounting-in-filecache.patch
new file mode 100644 (file)
index 0000000..d11fcdb
--- /dev/null
@@ -0,0 +1,669 @@
+From f46c734da1a479098262420090554e3bdfaa78bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 11 Dec 2022 06:19:33 -0500
+Subject: nfsd: rework refcounting in filecache
+
+From: Jeff Layton <jlayton@kernel.org>
+
+[ Upstream commit ac3a2585f018f10039b4a856dcb122da88c1c1c9 ]
+
+The filecache refcounting is a bit non-standard for something searchable
+by RCU, in that we maintain a sentinel reference while it's hashed. This
+in turn requires that we have to do things differently in the "put"
+depending on whether its hashed, which we believe to have led to races.
+
+There are other problems in here too. nfsd_file_close_inode_sync can end
+up freeing an nfsd_file while there are still outstanding references to
+it, and there are a number of subtle ToC/ToU races.
+
+Rework the code so that the refcount is what drives the lifecycle. When
+the refcount goes to zero, then unhash and rcu free the object. A task
+searching for a nfsd_file is allowed to bump its refcount, but only if
+it's not already 0. Ensure that we don't make any other changes to it
+until a reference is held.
+
+With this change, the LRU carries a reference. Take special care to deal
+with it when removing an entry from the list, and ensure that we only
+repurpose the nf_lru list_head when the refcount is 0 to ensure
+exclusive access to it.
+
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Stable-dep-of: 0b3a551fa58b ("nfsd: fix handling of cached open files in nfsd4_open codepath")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/nfsd/filecache.c | 318 +++++++++++++++++++++++---------------------
+ fs/nfsd/trace.h     |  51 +++----
+ 2 files changed, 189 insertions(+), 180 deletions(-)
+
+diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c
+index 7c673f98f95c..9bf78506d071 100644
+--- a/fs/nfsd/filecache.c
++++ b/fs/nfsd/filecache.c
+@@ -302,8 +302,7 @@ nfsd_file_alloc(struct nfsd_file_lookup_key *key, unsigned int may)
+               if (key->gc)
+                       __set_bit(NFSD_FILE_GC, &nf->nf_flags);
+               nf->nf_inode = key->inode;
+-              /* nf_ref is pre-incremented for hash table */
+-              refcount_set(&nf->nf_ref, 2);
++              refcount_set(&nf->nf_ref, 1);
+               nf->nf_may = key->need;
+               nf->nf_mark = NULL;
+       }
+@@ -355,24 +354,35 @@ nfsd_file_unhash(struct nfsd_file *nf)
+       return false;
+ }
+-static bool
++static void
+ nfsd_file_free(struct nfsd_file *nf)
+ {
+       s64 age = ktime_to_ms(ktime_sub(ktime_get(), nf->nf_birthtime));
+-      bool flush = false;
+       trace_nfsd_file_free(nf);
+       this_cpu_inc(nfsd_file_releases);
+       this_cpu_add(nfsd_file_total_age, age);
++      nfsd_file_unhash(nf);
++
++      /*
++       * We call fsync here in order to catch writeback errors. It's not
++       * strictly required by the protocol, but an nfsd_file could get
++       * evicted from the cache before a COMMIT comes in. If another
++       * task were to open that file in the interim and scrape the error,
++       * then the client may never see it. By calling fsync here, we ensure
++       * that writeback happens before the entry is freed, and that any
++       * errors reported result in the write verifier changing.
++       */
++      nfsd_file_fsync(nf);
++
+       if (nf->nf_mark)
+               nfsd_file_mark_put(nf->nf_mark);
+       if (nf->nf_file) {
+               get_file(nf->nf_file);
+               filp_close(nf->nf_file, NULL);
+               fput(nf->nf_file);
+-              flush = true;
+       }
+       /*
+@@ -380,10 +390,9 @@ nfsd_file_free(struct nfsd_file *nf)
+        * WARN and leak it to preserve system stability.
+        */
+       if (WARN_ON_ONCE(!list_empty(&nf->nf_lru)))
+-              return flush;
++              return;
+       call_rcu(&nf->nf_rcu, nfsd_file_slab_free);
+-      return flush;
+ }
+ static bool
+@@ -399,17 +408,23 @@ nfsd_file_check_writeback(struct nfsd_file *nf)
+               mapping_tagged(mapping, PAGECACHE_TAG_WRITEBACK);
+ }
+-static void nfsd_file_lru_add(struct nfsd_file *nf)
++static bool nfsd_file_lru_add(struct nfsd_file *nf)
+ {
+       set_bit(NFSD_FILE_REFERENCED, &nf->nf_flags);
+-      if (list_lru_add(&nfsd_file_lru, &nf->nf_lru))
++      if (list_lru_add(&nfsd_file_lru, &nf->nf_lru)) {
+               trace_nfsd_file_lru_add(nf);
++              return true;
++      }
++      return false;
+ }
+-static void nfsd_file_lru_remove(struct nfsd_file *nf)
++static bool nfsd_file_lru_remove(struct nfsd_file *nf)
+ {
+-      if (list_lru_del(&nfsd_file_lru, &nf->nf_lru))
++      if (list_lru_del(&nfsd_file_lru, &nf->nf_lru)) {
+               trace_nfsd_file_lru_del(nf);
++              return true;
++      }
++      return false;
+ }
+ struct nfsd_file *
+@@ -420,86 +435,60 @@ nfsd_file_get(struct nfsd_file *nf)
+       return NULL;
+ }
+-static void
+-nfsd_file_unhash_and_queue(struct nfsd_file *nf, struct list_head *dispose)
+-{
+-      trace_nfsd_file_unhash_and_queue(nf);
+-      if (nfsd_file_unhash(nf)) {
+-              /* caller must call nfsd_file_dispose_list() later */
+-              nfsd_file_lru_remove(nf);
+-              list_add(&nf->nf_lru, dispose);
+-      }
+-}
+-
+-static void
+-nfsd_file_put_noref(struct nfsd_file *nf)
+-{
+-      trace_nfsd_file_put(nf);
+-
+-      if (refcount_dec_and_test(&nf->nf_ref)) {
+-              WARN_ON(test_bit(NFSD_FILE_HASHED, &nf->nf_flags));
+-              nfsd_file_lru_remove(nf);
+-              nfsd_file_free(nf);
+-      }
+-}
+-
+-static void
+-nfsd_file_unhash_and_put(struct nfsd_file *nf)
+-{
+-      if (nfsd_file_unhash(nf))
+-              nfsd_file_put_noref(nf);
+-}
+-
++/**
++ * nfsd_file_put - put the reference to a nfsd_file
++ * @nf: nfsd_file of which to put the reference
++ *
++ * Put a reference to a nfsd_file. In the non-GC case, we just put the
++ * reference immediately. In the GC case, if the reference would be
++ * the last one, the put it on the LRU instead to be cleaned up later.
++ */
+ void
+ nfsd_file_put(struct nfsd_file *nf)
+ {
+       might_sleep();
++      trace_nfsd_file_put(nf);
+-      if (test_bit(NFSD_FILE_GC, &nf->nf_flags))
+-              nfsd_file_lru_add(nf);
+-      else if (refcount_read(&nf->nf_ref) == 2)
+-              nfsd_file_unhash_and_put(nf);
+-
+-      if (!test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) {
+-              nfsd_file_fsync(nf);
+-              nfsd_file_put_noref(nf);
+-      } else if (nf->nf_file && test_bit(NFSD_FILE_GC, &nf->nf_flags)) {
+-              nfsd_file_put_noref(nf);
+-              nfsd_file_schedule_laundrette();
+-      } else
+-              nfsd_file_put_noref(nf);
+-}
+-
+-static void
+-nfsd_file_dispose_list(struct list_head *dispose)
+-{
+-      struct nfsd_file *nf;
++      if (test_bit(NFSD_FILE_GC, &nf->nf_flags) &&
++          test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) {
++              /*
++               * If this is the last reference (nf_ref == 1), then try to
++               * transfer it to the LRU.
++               */
++              if (refcount_dec_not_one(&nf->nf_ref))
++                      return;
++
++              /* Try to add it to the LRU.  If that fails, decrement. */
++              if (nfsd_file_lru_add(nf)) {
++                      /* If it's still hashed, we're done */
++                      if (test_bit(NFSD_FILE_HASHED, &nf->nf_flags)) {
++                              nfsd_file_schedule_laundrette();
++                              return;
++                      }
+-      while(!list_empty(dispose)) {
+-              nf = list_first_entry(dispose, struct nfsd_file, nf_lru);
+-              list_del_init(&nf->nf_lru);
+-              nfsd_file_fsync(nf);
+-              nfsd_file_put_noref(nf);
++                      /*
++                       * We're racing with unhashing, so try to remove it from
++                       * the LRU. If removal fails, then someone else already
++                       * has our reference.
++                       */
++                      if (!nfsd_file_lru_remove(nf))
++                              return;
++              }
+       }
++      if (refcount_dec_and_test(&nf->nf_ref))
++              nfsd_file_free(nf);
+ }
+ static void
+-nfsd_file_dispose_list_sync(struct list_head *dispose)
++nfsd_file_dispose_list(struct list_head *dispose)
+ {
+-      bool flush = false;
+       struct nfsd_file *nf;
+-      while(!list_empty(dispose)) {
++      while (!list_empty(dispose)) {
+               nf = list_first_entry(dispose, struct nfsd_file, nf_lru);
+               list_del_init(&nf->nf_lru);
+-              nfsd_file_fsync(nf);
+-              if (!refcount_dec_and_test(&nf->nf_ref))
+-                      continue;
+-              if (nfsd_file_free(nf))
+-                      flush = true;
++              nfsd_file_free(nf);
+       }
+-      if (flush)
+-              flush_delayed_fput();
+ }
+ static void
+@@ -569,21 +558,8 @@ nfsd_file_lru_cb(struct list_head *item, struct list_lru_one *lru,
+       struct list_head *head = arg;
+       struct nfsd_file *nf = list_entry(item, struct nfsd_file, nf_lru);
+-      /*
+-       * Do a lockless refcount check. The hashtable holds one reference, so
+-       * we look to see if anything else has a reference, or if any have
+-       * been put since the shrinker last ran. Those don't get unhashed and
+-       * released.
+-       *
+-       * Note that in the put path, we set the flag and then decrement the
+-       * counter. Here we check the counter and then test and clear the flag.
+-       * That order is deliberate to ensure that we can do this locklessly.
+-       */
+-      if (refcount_read(&nf->nf_ref) > 1) {
+-              list_lru_isolate(lru, &nf->nf_lru);
+-              trace_nfsd_file_gc_in_use(nf);
+-              return LRU_REMOVED;
+-      }
++      /* We should only be dealing with GC entries here */
++      WARN_ON_ONCE(!test_bit(NFSD_FILE_GC, &nf->nf_flags));
+       /*
+        * Don't throw out files that are still undergoing I/O or
+@@ -594,40 +570,30 @@ nfsd_file_lru_cb(struct list_head *item, struct list_lru_one *lru,
+               return LRU_SKIP;
+       }
++      /* If it was recently added to the list, skip it */
+       if (test_and_clear_bit(NFSD_FILE_REFERENCED, &nf->nf_flags)) {
+               trace_nfsd_file_gc_referenced(nf);
+               return LRU_ROTATE;
+       }
+-      if (!test_and_clear_bit(NFSD_FILE_HASHED, &nf->nf_flags)) {
+-              trace_nfsd_file_gc_hashed(nf);
+-              return LRU_SKIP;
++      /*
++       * Put the reference held on behalf of the LRU. If it wasn't the last
++       * one, then just remove it from the LRU and ignore it.
++       */
++      if (!refcount_dec_and_test(&nf->nf_ref)) {
++              trace_nfsd_file_gc_in_use(nf);
++              list_lru_isolate(lru, &nf->nf_lru);
++              return LRU_REMOVED;
+       }
++      /* Refcount went to zero. Unhash it and queue it to the dispose list */
++      nfsd_file_unhash(nf);
+       list_lru_isolate_move(lru, &nf->nf_lru, head);
+       this_cpu_inc(nfsd_file_evictions);
+       trace_nfsd_file_gc_disposed(nf);
+       return LRU_REMOVED;
+ }
+-/*
+- * Unhash items on @dispose immediately, then queue them on the
+- * disposal workqueue to finish releasing them in the background.
+- *
+- * cel: Note that between the time list_lru_shrink_walk runs and
+- * now, these items are in the hash table but marked unhashed.
+- * Why release these outside of lru_cb ? There's no lock ordering
+- * problem since lru_cb currently takes no lock.
+- */
+-static void nfsd_file_gc_dispose_list(struct list_head *dispose)
+-{
+-      struct nfsd_file *nf;
+-
+-      list_for_each_entry(nf, dispose, nf_lru)
+-              nfsd_file_hash_remove(nf);
+-      nfsd_file_dispose_list_delayed(dispose);
+-}
+-
+ static void
+ nfsd_file_gc(void)
+ {
+@@ -637,7 +603,7 @@ nfsd_file_gc(void)
+       ret = list_lru_walk(&nfsd_file_lru, nfsd_file_lru_cb,
+                           &dispose, list_lru_count(&nfsd_file_lru));
+       trace_nfsd_file_gc_removed(ret, list_lru_count(&nfsd_file_lru));
+-      nfsd_file_gc_dispose_list(&dispose);
++      nfsd_file_dispose_list_delayed(&dispose);
+ }
+ static void
+@@ -662,7 +628,7 @@ nfsd_file_lru_scan(struct shrinker *s, struct shrink_control *sc)
+       ret = list_lru_shrink_walk(&nfsd_file_lru, sc,
+                                  nfsd_file_lru_cb, &dispose);
+       trace_nfsd_file_shrinker_removed(ret, list_lru_count(&nfsd_file_lru));
+-      nfsd_file_gc_dispose_list(&dispose);
++      nfsd_file_dispose_list_delayed(&dispose);
+       return ret;
+ }
+@@ -672,72 +638,111 @@ static struct shrinker  nfsd_file_shrinker = {
+       .seeks = 1,
+ };
+-/*
+- * Find all cache items across all net namespaces that match @inode and
+- * move them to @dispose. The lookup is atomic wrt nfsd_file_acquire().
++/**
++ * nfsd_file_queue_for_close: try to close out any open nfsd_files for an inode
++ * @inode:   inode on which to close out nfsd_files
++ * @dispose: list on which to gather nfsd_files to close out
++ *
++ * An nfsd_file represents a struct file being held open on behalf of nfsd. An
++ * open file however can block other activity (such as leases), or cause
++ * undesirable behavior (e.g. spurious silly-renames when reexporting NFS).
++ *
++ * This function is intended to find open nfsd_files when this sort of
++ * conflicting access occurs and then attempt to close those files out.
++ *
++ * Populates the dispose list with entries that have already had their
++ * refcounts go to zero. The actual free of an nfsd_file can be expensive,
++ * so we leave it up to the caller whether it wants to wait or not.
+  */
+-static unsigned int
+-__nfsd_file_close_inode(struct inode *inode, struct list_head *dispose)
++static void
++nfsd_file_queue_for_close(struct inode *inode, struct list_head *dispose)
+ {
+       struct nfsd_file_lookup_key key = {
+               .type   = NFSD_FILE_KEY_INODE,
+               .inode  = inode,
+       };
+-      unsigned int count = 0;
+       struct nfsd_file *nf;
+       rcu_read_lock();
+       do {
++              int decrement = 1;
++
+               nf = rhashtable_lookup(&nfsd_file_rhash_tbl, &key,
+                                      nfsd_file_rhash_params);
+               if (!nf)
+                       break;
+-              nfsd_file_unhash_and_queue(nf, dispose);
+-              count++;
++
++              /* If we raced with someone else unhashing, ignore it */
++              if (!nfsd_file_unhash(nf))
++                      continue;
++
++              /* If we can't get a reference, ignore it */
++              if (!nfsd_file_get(nf))
++                      continue;
++
++              /* Extra decrement if we remove from the LRU */
++              if (nfsd_file_lru_remove(nf))
++                      ++decrement;
++
++              /* If refcount goes to 0, then put on the dispose list */
++              if (refcount_sub_and_test(decrement, &nf->nf_ref)) {
++                      list_add(&nf->nf_lru, dispose);
++                      trace_nfsd_file_closing(nf);
++              }
+       } while (1);
+       rcu_read_unlock();
+-      return count;
+ }
+ /**
+- * nfsd_file_close_inode_sync - attempt to forcibly close a nfsd_file
++ * nfsd_file_close_inode - attempt a delayed close of a nfsd_file
+  * @inode: inode of the file to attempt to remove
+  *
+- * Unhash and put, then flush and fput all cache items associated with @inode.
++ * Close out any open nfsd_files that can be reaped for @inode. The
++ * actual freeing is deferred to the dispose_list_delayed infrastructure.
++ *
++ * This is used by the fsnotify callbacks and setlease notifier.
+  */
+-void
+-nfsd_file_close_inode_sync(struct inode *inode)
++static void
++nfsd_file_close_inode(struct inode *inode)
+ {
+       LIST_HEAD(dispose);
+-      unsigned int count;
+-      count = __nfsd_file_close_inode(inode, &dispose);
+-      trace_nfsd_file_close_inode_sync(inode, count);
+-      nfsd_file_dispose_list_sync(&dispose);
++      nfsd_file_queue_for_close(inode, &dispose);
++      nfsd_file_dispose_list_delayed(&dispose);
+ }
+ /**
+- * nfsd_file_close_inode - attempt a delayed close of a nfsd_file
++ * nfsd_file_close_inode_sync - attempt to forcibly close a nfsd_file
+  * @inode: inode of the file to attempt to remove
+  *
+- * Unhash and put all cache item associated with @inode.
++ * Close out any open nfsd_files that can be reaped for @inode. The
++ * nfsd_files are closed out synchronously.
++ *
++ * This is called from nfsd_rename and nfsd_unlink to avoid silly-renames
++ * when reexporting NFS.
+  */
+-static void
+-nfsd_file_close_inode(struct inode *inode)
++void
++nfsd_file_close_inode_sync(struct inode *inode)
+ {
++      struct nfsd_file *nf;
+       LIST_HEAD(dispose);
+-      unsigned int count;
+-      count = __nfsd_file_close_inode(inode, &dispose);
+-      trace_nfsd_file_close_inode(inode, count);
+-      nfsd_file_dispose_list_delayed(&dispose);
++      trace_nfsd_file_close(inode);
++
++      nfsd_file_queue_for_close(inode, &dispose);
++      while (!list_empty(&dispose)) {
++              nf = list_first_entry(&dispose, struct nfsd_file, nf_lru);
++              list_del_init(&nf->nf_lru);
++              nfsd_file_free(nf);
++      }
++      flush_delayed_fput();
+ }
+ /**
+  * nfsd_file_delayed_close - close unused nfsd_files
+  * @work: dummy
+  *
+- * Walk the LRU list and close any entries that have not been used since
++ * Walk the LRU list and destroy any entries that have not been used since
+  * the last scan.
+  */
+ static void
+@@ -759,7 +764,7 @@ nfsd_file_lease_notifier_call(struct notifier_block *nb, unsigned long arg,
+       /* Only close files for F_SETLEASE leases */
+       if (fl->fl_flags & FL_LEASE)
+-              nfsd_file_close_inode_sync(file_inode(fl->fl_file));
++              nfsd_file_close_inode(file_inode(fl->fl_file));
+       return 0;
+ }
+@@ -880,6 +885,13 @@ nfsd_file_cache_init(void)
+       goto out;
+ }
++/**
++ * __nfsd_file_cache_purge: clean out the cache for shutdown
++ * @net: net-namespace to shut down the cache (may be NULL)
++ *
++ * Walk the nfsd_file cache and close out any that match @net. If @net is NULL,
++ * then close out everything. Called when an nfsd instance is being shut down.
++ */
+ static void
+ __nfsd_file_cache_purge(struct net *net)
+ {
+@@ -893,8 +905,11 @@ __nfsd_file_cache_purge(struct net *net)
+               nf = rhashtable_walk_next(&iter);
+               while (!IS_ERR_OR_NULL(nf)) {
+-                      if (!net || nf->nf_net == net)
+-                              nfsd_file_unhash_and_queue(nf, &dispose);
++                      if (!net || nf->nf_net == net) {
++                              nfsd_file_unhash(nf);
++                              nfsd_file_lru_remove(nf);
++                              list_add(&nf->nf_lru, &dispose);
++                      }
+                       nf = rhashtable_walk_next(&iter);
+               }
+@@ -1061,8 +1076,12 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
+       if (nf)
+               nf = nfsd_file_get(nf);
+       rcu_read_unlock();
+-      if (nf)
++
++      if (nf) {
++              if (nfsd_file_lru_remove(nf))
++                      WARN_ON_ONCE(refcount_dec_and_test(&nf->nf_ref));
+               goto wait_for_construction;
++      }
+       nf = nfsd_file_alloc(&key, may_flags);
+       if (!nf) {
+@@ -1095,11 +1114,11 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
+                       goto out;
+               }
+               open_retry = false;
+-              nfsd_file_put_noref(nf);
++              if (refcount_dec_and_test(&nf->nf_ref))
++                      nfsd_file_free(nf);
+               goto retry;
+       }
+-      nfsd_file_lru_remove(nf);
+       this_cpu_inc(nfsd_file_cache_hits);
+       status = nfserrno(nfsd_open_break_lease(file_inode(nf->nf_file), may_flags));
+@@ -1109,7 +1128,8 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
+                       this_cpu_inc(nfsd_file_acquisitions);
+               *pnf = nf;
+       } else {
+-              nfsd_file_put(nf);
++              if (refcount_dec_and_test(&nf->nf_ref))
++                      nfsd_file_free(nf);
+               nf = NULL;
+       }
+@@ -1135,8 +1155,10 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct svc_fh *fhp,
+        * If construction failed, or we raced with a call to unlink()
+        * then unhash.
+        */
+-      if (status != nfs_ok || key.inode->i_nlink == 0)
+-              nfsd_file_unhash_and_put(nf);
++      if (status == nfs_ok && key.inode->i_nlink == 0)
++              status = nfserr_jukebox;
++      if (status != nfs_ok)
++              nfsd_file_unhash(nf);
+       clear_bit_unlock(NFSD_FILE_PENDING, &nf->nf_flags);
+       smp_mb__after_atomic();
+       wake_up_bit(&nf->nf_flags, NFSD_FILE_PENDING);
+diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h
+index 08e2738adf8f..4feeaed32541 100644
+--- a/fs/nfsd/trace.h
++++ b/fs/nfsd/trace.h
+@@ -817,8 +817,8 @@ DEFINE_CLID_EVENT(confirmed_r);
+       __print_flags(val, "|",                                         \
+               { 1 << NFSD_FILE_HASHED,        "HASHED" },             \
+               { 1 << NFSD_FILE_PENDING,       "PENDING" },            \
+-              { 1 << NFSD_FILE_REFERENCED,    "REFERENCED"},          \
+-              { 1 << NFSD_FILE_GC,            "GC"})
++              { 1 << NFSD_FILE_REFERENCED,    "REFERENCED" },         \
++              { 1 << NFSD_FILE_GC,            "GC" })
+ DECLARE_EVENT_CLASS(nfsd_file_class,
+       TP_PROTO(struct nfsd_file *nf),
+@@ -853,6 +853,7 @@ DEFINE_EVENT(nfsd_file_class, name, \
+ DEFINE_NFSD_FILE_EVENT(nfsd_file_free);
+ DEFINE_NFSD_FILE_EVENT(nfsd_file_unhash);
+ DEFINE_NFSD_FILE_EVENT(nfsd_file_put);
++DEFINE_NFSD_FILE_EVENT(nfsd_file_closing);
+ DEFINE_NFSD_FILE_EVENT(nfsd_file_unhash_and_queue);
+ TRACE_EVENT(nfsd_file_alloc,
+@@ -1044,35 +1045,6 @@ TRACE_EVENT(nfsd_file_open,
+               __entry->nf_file)
+ )
+-DECLARE_EVENT_CLASS(nfsd_file_search_class,
+-      TP_PROTO(
+-              const struct inode *inode,
+-              unsigned int count
+-      ),
+-      TP_ARGS(inode, count),
+-      TP_STRUCT__entry(
+-              __field(const struct inode *, inode)
+-              __field(unsigned int, count)
+-      ),
+-      TP_fast_assign(
+-              __entry->inode = inode;
+-              __entry->count = count;
+-      ),
+-      TP_printk("inode=%p count=%u",
+-              __entry->inode, __entry->count)
+-);
+-
+-#define DEFINE_NFSD_FILE_SEARCH_EVENT(name)                           \
+-DEFINE_EVENT(nfsd_file_search_class, name,                            \
+-      TP_PROTO(                                                       \
+-              const struct inode *inode,                              \
+-              unsigned int count                                      \
+-      ),                                                              \
+-      TP_ARGS(inode, count))
+-
+-DEFINE_NFSD_FILE_SEARCH_EVENT(nfsd_file_close_inode_sync);
+-DEFINE_NFSD_FILE_SEARCH_EVENT(nfsd_file_close_inode);
+-
+ TRACE_EVENT(nfsd_file_is_cached,
+       TP_PROTO(
+               const struct inode *inode,
+@@ -1150,7 +1122,6 @@ DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_lru_del_disposed);
+ DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_in_use);
+ DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_writeback);
+ DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_referenced);
+-DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_hashed);
+ DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_disposed);
+ DECLARE_EVENT_CLASS(nfsd_file_lruwalk_class,
+@@ -1182,6 +1153,22 @@ DEFINE_EVENT(nfsd_file_lruwalk_class, name,                             \
+ DEFINE_NFSD_FILE_LRUWALK_EVENT(nfsd_file_gc_removed);
+ DEFINE_NFSD_FILE_LRUWALK_EVENT(nfsd_file_shrinker_removed);
++TRACE_EVENT(nfsd_file_close,
++      TP_PROTO(
++              const struct inode *inode
++      ),
++      TP_ARGS(inode),
++      TP_STRUCT__entry(
++              __field(const void *, inode)
++      ),
++      TP_fast_assign(
++              __entry->inode = inode;
++      ),
++      TP_printk("inode=%p",
++              __entry->inode
++      )
++);
++
+ TRACE_EVENT(nfsd_file_fsync,
+       TP_PROTO(
+               const struct nfsd_file *nf,
+-- 
+2.35.1
+
diff --git a/queue-6.1/octeontx2-af-fix-lmac-config-in-cgx_lmac_rx_tx_enabl.patch b/queue-6.1/octeontx2-af-fix-lmac-config-in-cgx_lmac_rx_tx_enabl.patch
new file mode 100644 (file)
index 0000000..6f28fba
--- /dev/null
@@ -0,0 +1,57 @@
+From 09b1f72b3a42358b7b4dd63ae385a407e81df45e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 5 Jan 2023 21:31:07 +0530
+Subject: octeontx2-af: Fix LMAC config in cgx_lmac_rx_tx_enable
+
+From: Angela Czubak <aczubak@marvell.com>
+
+[ Upstream commit b4e9b8763e417db31c7088103cc557d55cb7a8f5 ]
+
+PF netdev can request AF to enable or disable reception and transmission
+on assigned CGX::LMAC. The current code instead of disabling or enabling
+'reception and transmission' also disables/enable the LMAC. This patch
+fixes this issue.
+
+Fixes: 1435f66a28b4 ("octeontx2-af: CGX Rx/Tx enable/disable mbox handlers")
+Signed-off-by: Angela Czubak <aczubak@marvell.com>
+Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
+Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
+Link: https://lore.kernel.org/r/20230105160107.17638-1-hkelam@marvell.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 4 ++--
+ drivers/net/ethernet/marvell/octeontx2/af/cgx.h | 1 -
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+index c8724bfa86b0..8fdd3afe5998 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+@@ -768,9 +768,9 @@ int cgx_lmac_rx_tx_enable(void *cgxd, int lmac_id, bool enable)
+       cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_CFG);
+       if (enable)
+-              cfg |= CMR_EN | DATA_PKT_RX_EN | DATA_PKT_TX_EN;
++              cfg |= DATA_PKT_RX_EN | DATA_PKT_TX_EN;
+       else
+-              cfg &= ~(CMR_EN | DATA_PKT_RX_EN | DATA_PKT_TX_EN);
++              cfg &= ~(DATA_PKT_RX_EN | DATA_PKT_TX_EN);
+       cgx_write(cgx, lmac_id, CGXX_CMRX_CFG, cfg);
+       return 0;
+ }
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
+index 0b06788b8d80..04338db38671 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
+@@ -30,7 +30,6 @@
+ #define CMR_P2X_SEL_SHIFT             59ULL
+ #define CMR_P2X_SEL_NIX0              1ULL
+ #define CMR_P2X_SEL_NIX1              2ULL
+-#define CMR_EN                                BIT_ULL(55)
+ #define DATA_PKT_TX_EN                        BIT_ULL(53)
+ #define DATA_PKT_RX_EN                        BIT_ULL(54)
+ #define CGX_LMAC_TYPE_SHIFT           40
+-- 
+2.35.1
+
diff --git a/queue-6.1/octeontx2-pf-fix-resource-leakage-in-vf-driver-unbin.patch b/queue-6.1/octeontx2-pf-fix-resource-leakage-in-vf-driver-unbin.patch
new file mode 100644 (file)
index 0000000..99fb8b2
--- /dev/null
@@ -0,0 +1,39 @@
+From 27b67d97afcdc7fe75a0d18e9459882a1884427f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Jan 2023 11:43:25 +0530
+Subject: octeontx2-pf: Fix resource leakage in VF driver unbind
+
+From: Hariprasad Kelam <hkelam@marvell.com>
+
+[ Upstream commit 53da7aec32982f5ee775b69dce06d63992ce4af3 ]
+
+resources allocated like mcam entries to support the Ntuple feature
+and hash tables for the tc feature are not getting freed in driver
+unbind. This patch fixes the issue.
+
+Fixes: 2da489432747 ("octeontx2-pf: devlink params support to set mcam entry count")
+Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
+Signed-off-by: Sunil Kovvuri Goutham <sgoutham@marvell.com>
+Link: https://lore.kernel.org/r/20230109061325.21395-1-hkelam@marvell.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+index 86653bb8e403..7f8ffbf79cf7 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+@@ -758,6 +758,8 @@ static void otx2vf_remove(struct pci_dev *pdev)
+       if (vf->otx2_wq)
+               destroy_workqueue(vf->otx2_wq);
+       otx2_ptp_destroy(vf);
++      otx2_mcam_flow_del(vf);
++      otx2_shutdown_tc(vf);
+       otx2vf_disable_mbox_intr(vf);
+       otx2_detach_resources(&vf->mbox);
+       if (test_bit(CN10K_LMTST, &vf->hw.cap_flag))
+-- 
+2.35.1
+
diff --git a/queue-6.1/perf-build-properly-guard-libbpf-includes.patch b/queue-6.1/perf-build-properly-guard-libbpf-includes.patch
new file mode 100644 (file)
index 0000000..9c90a4f
--- /dev/null
@@ -0,0 +1,80 @@
+From 24152c02967581cc6178bd920b92684ca3c7139e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Jan 2023 07:13:19 -0800
+Subject: perf build: Properly guard libbpf includes
+
+From: Ian Rogers <irogers@google.com>
+
+[ Upstream commit d891f2b724b39a2a41e3ad7b57110193993242ff ]
+
+Including libbpf header files should be guarded by HAVE_LIBBPF_SUPPORT.
+In bpf_counter.h, move the skeleton utilities under HAVE_BPF_SKEL.
+
+Fixes: d6a735ef3277c45f ("perf bpf_counter: Move common functions to bpf_counter.h")
+Reported-by: Mike Leach <mike.leach@linaro.org>
+Signed-off-by: Ian Rogers <irogers@google.com>
+Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Tested-by: Jiri Olsa <jolsa@kernel.org>
+Tested-by: Mike Leach <mike.leach@linaro.org>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Link: http://lore.kernel.org/lkml/20230105172243.7238-1-mike.leach@linaro.org
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-trace.c    | 2 ++
+ tools/perf/util/bpf_counter.h | 6 ++++++
+ 2 files changed, 8 insertions(+)
+
+diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
+index 3dcf6aed1ef7..97b17f8941dc 100644
+--- a/tools/perf/builtin-trace.c
++++ b/tools/perf/builtin-trace.c
+@@ -17,7 +17,9 @@
+ #include "util/record.h"
+ #include <traceevent/event-parse.h>
+ #include <api/fs/tracing_path.h>
++#ifdef HAVE_LIBBPF_SUPPORT
+ #include <bpf/bpf.h>
++#endif
+ #include "util/bpf_map.h"
+ #include "util/rlimit.h"
+ #include "builtin.h"
+diff --git a/tools/perf/util/bpf_counter.h b/tools/perf/util/bpf_counter.h
+index 4dbf26408b69..c6d21c07b14c 100644
+--- a/tools/perf/util/bpf_counter.h
++++ b/tools/perf/util/bpf_counter.h
+@@ -4,9 +4,12 @@
+ #include <linux/list.h>
+ #include <sys/resource.h>
++
++#ifdef HAVE_LIBBPF_SUPPORT
+ #include <bpf/bpf.h>
+ #include <bpf/btf.h>
+ #include <bpf/libbpf.h>
++#endif
+ struct evsel;
+ struct target;
+@@ -87,6 +90,8 @@ static inline void set_max_rlimit(void)
+       setrlimit(RLIMIT_MEMLOCK, &rinf);
+ }
++#ifdef HAVE_BPF_SKEL
++
+ static inline __u32 bpf_link_get_id(int fd)
+ {
+       struct bpf_link_info link_info = { .id = 0, };
+@@ -127,5 +132,6 @@ static inline int bperf_trigger_reading(int prog_fd, int cpu)
+       return bpf_prog_test_run_opts(prog_fd, &opts);
+ }
++#endif /* HAVE_BPF_SKEL */
+ #endif /* __PERF_BPF_COUNTER_H */
+-- 
+2.35.1
+
diff --git a/queue-6.1/perf-kmem-support-field-node-in-evsel__process_alloc.patch b/queue-6.1/perf-kmem-support-field-node-in-evsel__process_alloc.patch
new file mode 100644 (file)
index 0000000..d50e6e3
--- /dev/null
@@ -0,0 +1,111 @@
+From bda77d3c3768476c268d00cb98e6349b5e4e38cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 8 Jan 2023 14:24:00 +0800
+Subject: perf kmem: Support field "node" in evsel__process_alloc_event()
+ coping with recent tracepoint restructuring
+
+From: Leo Yan <leo.yan@linaro.org>
+
+[ Upstream commit dce088ab0d51ae3b14fb2bd608e9c649aadfe5dc ]
+
+Commit 11e9734bcb6a7361 ("mm/slab_common: unify NUMA and UMA version of
+tracepoints") adds the field "node" into the tracepoints 'kmalloc' and
+'kmem_cache_alloc', so this patch modifies the event process function to
+support the field "node".
+
+If field "node" is detected by checking function evsel__field(), it
+stats the cross allocation.
+
+When the "node" value is NUMA_NO_NODE (-1), it means the memory can be
+allocated from any memory node, in this case, we don't account it as a
+cross allocation.
+
+Fixes: 11e9734bcb6a7361 ("mm/slab_common: unify NUMA and UMA version of tracepoints")
+Reported-by: Ravi Bangoria <ravi.bangoria@amd.com>
+Reviewed-by: James Clark <james.clark@arm.com>
+Signed-off-by: Leo Yan <leo.yan@linaro.org>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Hyeonggon Yoo <42.hyeyoo@gmail.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Link: https://lore.kernel.org/r/20230108062400.250690-2-leo.yan@linaro.org
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-kmem.c | 36 ++++++++++++++++++++++++------------
+ 1 file changed, 24 insertions(+), 12 deletions(-)
+
+diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
+index 63c759edb8bc..40dd52acc48a 100644
+--- a/tools/perf/builtin-kmem.c
++++ b/tools/perf/builtin-kmem.c
+@@ -26,6 +26,7 @@
+ #include "util/string2.h"
+ #include <linux/kernel.h>
++#include <linux/numa.h>
+ #include <linux/rbtree.h>
+ #include <linux/string.h>
+ #include <linux/zalloc.h>
+@@ -184,22 +185,33 @@ static int evsel__process_alloc_event(struct evsel *evsel, struct perf_sample *s
+       total_allocated += bytes_alloc;
+       nr_allocs++;
+-      return 0;
+-}
+-static int evsel__process_alloc_node_event(struct evsel *evsel, struct perf_sample *sample)
+-{
+-      int ret = evsel__process_alloc_event(evsel, sample);
++      /*
++       * Commit 11e9734bcb6a ("mm/slab_common: unify NUMA and UMA
++       * version of tracepoints") adds the field "node" into the
++       * tracepoints 'kmalloc' and 'kmem_cache_alloc'.
++       *
++       * The legacy tracepoints 'kmalloc_node' and 'kmem_cache_alloc_node'
++       * also contain the field "node".
++       *
++       * If the tracepoint contains the field "node" the tool stats the
++       * cross allocation.
++       */
++      if (evsel__field(evsel, "node")) {
++              int node1, node2;
+-      if (!ret) {
+-              int node1 = cpu__get_node((struct perf_cpu){.cpu = sample->cpu}),
+-                  node2 = evsel__intval(evsel, sample, "node");
++              node1 = cpu__get_node((struct perf_cpu){.cpu = sample->cpu});
++              node2 = evsel__intval(evsel, sample, "node");
+-              if (node1 != node2)
++              /*
++               * If the field "node" is NUMA_NO_NODE (-1), we don't take it
++               * as a cross allocation.
++               */
++              if ((node2 != NUMA_NO_NODE) && (node1 != node2))
+                       nr_cross_allocs++;
+       }
+-      return ret;
++      return 0;
+ }
+ static int ptr_cmp(void *, void *);
+@@ -1368,8 +1380,8 @@ static int __cmd_kmem(struct perf_session *session)
+               /* slab allocator */
+               { "kmem:kmalloc",               evsel__process_alloc_event, },
+               { "kmem:kmem_cache_alloc",      evsel__process_alloc_event, },
+-              { "kmem:kmalloc_node",          evsel__process_alloc_node_event, },
+-              { "kmem:kmem_cache_alloc_node", evsel__process_alloc_node_event, },
++              { "kmem:kmalloc_node",          evsel__process_alloc_event, },
++              { "kmem:kmem_cache_alloc_node", evsel__process_alloc_event, },
+               { "kmem:kfree",                 evsel__process_free_event, },
+               { "kmem:kmem_cache_free",       evsel__process_free_event, },
+               /* page allocator */
+-- 
+2.35.1
+
diff --git a/queue-6.1/perf-kmem-support-legacy-tracepoints.patch b/queue-6.1/perf-kmem-support-legacy-tracepoints.patch
new file mode 100644 (file)
index 0000000..4955b8d
--- /dev/null
@@ -0,0 +1,106 @@
+From 2204e7dd6595ecb466904fd55d84dd54ffa61787 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 8 Jan 2023 14:23:59 +0800
+Subject: perf kmem: Support legacy tracepoints
+
+From: Leo Yan <leo.yan@linaro.org>
+
+[ Upstream commit b3719108ae60169eda5c941ca5e1be1faa371c57 ]
+
+Commit 11e9734bcb6a7361 ("mm/slab_common: unify NUMA and UMA version of
+tracepoints") removed tracepoints 'kmalloc_node' and
+'kmem_cache_alloc_node', we need to consider the tool should be backward
+compatible.
+
+If it detect the tracepoint "kmem:kmalloc_node", this patch enables the
+legacy tracepoints, otherwise, it will ignore them.
+
+Fixes: 11e9734bcb6a7361 ("mm/slab_common: unify NUMA and UMA version of tracepoints")
+Reported-by: Ravi Bangoria <ravi.bangoria@amd.com>
+Reviewed-by: James Clark <james.clark@arm.com>
+Signed-off-by: Leo Yan <leo.yan@linaro.org>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Hyeonggon Yoo <42.hyeyoo@gmail.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Vlastimil Babka <vbabka@suse.cz>
+Link: https://lore.kernel.org/r/20230108062400.250690-1-leo.yan@linaro.org
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/builtin-kmem.c | 29 ++++++++++++++++++++++++++---
+ 1 file changed, 26 insertions(+), 3 deletions(-)
+
+diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
+index ebfab2ca1702..63c759edb8bc 100644
+--- a/tools/perf/builtin-kmem.c
++++ b/tools/perf/builtin-kmem.c
+@@ -1823,6 +1823,19 @@ static int parse_line_opt(const struct option *opt __maybe_unused,
+       return 0;
+ }
++static bool slab_legacy_tp_is_exposed(void)
++{
++      /*
++       * The tracepoints "kmem:kmalloc_node" and
++       * "kmem:kmem_cache_alloc_node" have been removed on the latest
++       * kernel, if the tracepoint "kmem:kmalloc_node" is existed it
++       * means the tool is running on an old kernel, we need to
++       * rollback to support these legacy tracepoints.
++       */
++      return IS_ERR(trace_event__tp_format("kmem", "kmalloc_node")) ?
++              false : true;
++}
++
+ static int __cmd_record(int argc, const char **argv)
+ {
+       const char * const record_args[] = {
+@@ -1830,22 +1843,28 @@ static int __cmd_record(int argc, const char **argv)
+       };
+       const char * const slab_events[] = {
+       "-e", "kmem:kmalloc",
+-      "-e", "kmem:kmalloc_node",
+       "-e", "kmem:kfree",
+       "-e", "kmem:kmem_cache_alloc",
+-      "-e", "kmem:kmem_cache_alloc_node",
+       "-e", "kmem:kmem_cache_free",
+       };
++      const char * const slab_legacy_events[] = {
++      "-e", "kmem:kmalloc_node",
++      "-e", "kmem:kmem_cache_alloc_node",
++      };
+       const char * const page_events[] = {
+       "-e", "kmem:mm_page_alloc",
+       "-e", "kmem:mm_page_free",
+       };
+       unsigned int rec_argc, i, j;
+       const char **rec_argv;
++      unsigned int slab_legacy_tp_exposed = slab_legacy_tp_is_exposed();
+       rec_argc = ARRAY_SIZE(record_args) + argc - 1;
+-      if (kmem_slab)
++      if (kmem_slab) {
+               rec_argc += ARRAY_SIZE(slab_events);
++              if (slab_legacy_tp_exposed)
++                      rec_argc += ARRAY_SIZE(slab_legacy_events);
++      }
+       if (kmem_page)
+               rec_argc += ARRAY_SIZE(page_events) + 1; /* for -g */
+@@ -1860,6 +1879,10 @@ static int __cmd_record(int argc, const char **argv)
+       if (kmem_slab) {
+               for (j = 0; j < ARRAY_SIZE(slab_events); j++, i++)
+                       rec_argv[i] = strdup(slab_events[j]);
++              if (slab_legacy_tp_exposed) {
++                      for (j = 0; j < ARRAY_SIZE(slab_legacy_events); j++, i++)
++                              rec_argv[i] = strdup(slab_legacy_events[j]);
++              }
+       }
+       if (kmem_page) {
+               rec_argv[i++] = strdup("-g");
+-- 
+2.35.1
+
diff --git a/queue-6.1/platform-surface-aggregator-add-missing-call-to-ssam.patch b/queue-6.1/platform-surface-aggregator-add-missing-call-to-ssam.patch
new file mode 100644 (file)
index 0000000..9d27593
--- /dev/null
@@ -0,0 +1,43 @@
+From d5eb3d2b510ca09d450bfa8310a08f782c2cd0ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Dec 2022 18:56:07 +0100
+Subject: platform/surface: aggregator: Add missing call to
+ ssam_request_sync_free()
+
+From: Maximilian Luz <luzmaximilian@gmail.com>
+
+[ Upstream commit c965daac370f08a9b71d573a71d13cda76f2a884 ]
+
+Although rare, ssam_request_sync_init() can fail. In that case, the
+request should be freed via ssam_request_sync_free(). Currently it is
+leaked instead. Fix this.
+
+Fixes: c167b9c7e3d6 ("platform/surface: Add Surface Aggregator subsystem")
+Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
+Link: https://lore.kernel.org/r/20221220175608.1436273-1-luzmaximilian@gmail.com
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/surface/aggregator/controller.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
+index 43e765199137..c6537a1b3a2e 100644
+--- a/drivers/platform/surface/aggregator/controller.c
++++ b/drivers/platform/surface/aggregator/controller.c
+@@ -1700,8 +1700,10 @@ int ssam_request_sync(struct ssam_controller *ctrl,
+               return status;
+       status = ssam_request_sync_init(rqst, spec->flags);
+-      if (status)
++      if (status) {
++              ssam_request_sync_free(rqst);
+               return status;
++      }
+       ssam_request_sync_set_resp(rqst, rsp);
+-- 
+2.35.1
+
diff --git a/queue-6.1/platform-x86-amd-fix-refcount-leak-in-amd_pmc_probe.patch b/queue-6.1/platform-x86-amd-fix-refcount-leak-in-amd_pmc_probe.patch
new file mode 100644 (file)
index 0000000..3c08903
--- /dev/null
@@ -0,0 +1,40 @@
+From a2c8df242de4bc49b27ab6650daa5bc6f9013c3f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Dec 2022 11:25:33 +0400
+Subject: platform/x86/amd: Fix refcount leak in amd_pmc_probe
+
+From: Miaoqian Lin <linmq006@gmail.com>
+
+[ Upstream commit ccb32e2be14271a60e9ba89c6d5660cc9998773c ]
+
+pci_get_domain_bus_and_slot() takes reference, the caller should release
+the reference by calling pci_dev_put() after use. Call pci_dev_put() in
+the error path to fix this.
+
+Fixes: 3d7d407dfb05 ("platform/x86: amd-pmc: Add support for AMD Spill to DRAM STB feature")
+Signed-off-by: Miaoqian Lin <linmq006@gmail.com>
+Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+Link: https://lore.kernel.org/r/20221229072534.1381432-1-linmq006@gmail.com
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/amd/pmc.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/platform/x86/amd/pmc.c b/drivers/platform/x86/amd/pmc.c
+index 439d282aafd1..8d924986381b 100644
+--- a/drivers/platform/x86/amd/pmc.c
++++ b/drivers/platform/x86/amd/pmc.c
+@@ -932,7 +932,7 @@ static int amd_pmc_probe(struct platform_device *pdev)
+       if (enable_stb && (dev->cpu_id == AMD_CPU_ID_YC || dev->cpu_id == AMD_CPU_ID_CB)) {
+               err = amd_pmc_s2d_init(dev);
+               if (err)
+-                      return err;
++                      goto err_pci_dev_put;
+       }
+       platform_set_drvdata(pdev, dev);
+-- 
+2.35.1
+
diff --git a/queue-6.1/regulator-da9211-use-irq-handler-when-ready.patch b/queue-6.1/regulator-da9211-use-irq-handler-when-ready.patch
new file mode 100644 (file)
index 0000000..26174a8
--- /dev/null
@@ -0,0 +1,66 @@
+From c9e45fbf36a9ab6af1a28ec6699638c51f64d104 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Nov 2022 22:06:02 +0100
+Subject: regulator: da9211: Use irq handler when ready
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+[ Upstream commit 02228f6aa6a64d588bc31e3267d05ff184d772eb ]
+
+If the system does not come from reset (like when it is kexec()), the
+regulator might have an IRQ waiting for us.
+
+If we enable the IRQ handler before its structures are ready, we crash.
+
+This patch fixes:
+
+[    1.141839] Unable to handle kernel read from unreadable memory at virtual address 0000000000000078
+[    1.316096] Call trace:
+[    1.316101]  blocking_notifier_call_chain+0x20/0xa8
+[    1.322757] cpu cpu0: dummy supplies not allowed for exclusive requests
+[    1.327823]  regulator_notifier_call_chain+0x1c/0x2c
+[    1.327825]  da9211_irq_handler+0x68/0xf8
+[    1.327829]  irq_thread+0x11c/0x234
+[    1.327833]  kthread+0x13c/0x154
+
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Reviewed-by: Adam Ward <DLG-Adam.Ward.opensource@dm.renesas.com>
+Link: https://lore.kernel.org/r/20221124-da9211-v2-0-1779e3c5d491@chromium.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/regulator/da9211-regulator.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c
+index e01b32d1fa17..00828f5baa97 100644
+--- a/drivers/regulator/da9211-regulator.c
++++ b/drivers/regulator/da9211-regulator.c
+@@ -498,6 +498,12 @@ static int da9211_i2c_probe(struct i2c_client *i2c)
+       chip->chip_irq = i2c->irq;
++      ret = da9211_regulator_init(chip);
++      if (ret < 0) {
++              dev_err(chip->dev, "Failed to initialize regulator: %d\n", ret);
++              return ret;
++      }
++
+       if (chip->chip_irq != 0) {
+               ret = devm_request_threaded_irq(chip->dev, chip->chip_irq, NULL,
+                                       da9211_irq_handler,
+@@ -512,11 +518,6 @@ static int da9211_i2c_probe(struct i2c_client *i2c)
+               dev_warn(chip->dev, "No IRQ configured\n");
+       }
+-      ret = da9211_regulator_init(chip);
+-
+-      if (ret < 0)
+-              dev_err(chip->dev, "Failed to initialize regulator: %d\n", ret);
+-
+       return ret;
+ }
+-- 
+2.35.1
+
diff --git a/queue-6.1/revert-r8169-disable-detection-of-chip-version-36.patch b/queue-6.1/revert-r8169-disable-detection-of-chip-version-36.patch
new file mode 100644 (file)
index 0000000..f2d41fd
--- /dev/null
@@ -0,0 +1,43 @@
+From 21155065d6a30fab6afe3dad66dc920880d8bb66 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 8 Jan 2023 20:37:53 +0100
+Subject: Revert "r8169: disable detection of chip version 36"
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit 2ea26b4de6f42b74a5f1701de41efa6bc9f12666 ]
+
+This reverts commit 42666b2c452ce87894786aae05e3fad3cfc6cb59.
+
+This chip version seems to be very rare, but it exits in consumer
+devices, see linked report.
+
+Link: https://stackoverflow.com/questions/75049473/cant-setup-a-wired-network-in-archlinux-fresh-install
+Fixes: 42666b2c452c ("r8169: disable detection of chip version 36")
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://lore.kernel.org/r/42e9674c-d5d0-a65a-f578-e5c74f244739@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index a73d061d9fcb..fe8dc8e0522b 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -1996,10 +1996,7 @@ static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii)
+               /* 8168F family. */
+               { 0x7c8, 0x488, RTL_GIGA_MAC_VER_38 },
+-              /* It seems this chip version never made it to
+-               * the wild. Let's disable detection.
+-               * { 0x7cf, 0x481,      RTL_GIGA_MAC_VER_36 },
+-               */
++              { 0x7cf, 0x481, RTL_GIGA_MAC_VER_36 },
+               { 0x7cf, 0x480, RTL_GIGA_MAC_VER_35 },
+               /* 8168E family. */
+-- 
+2.35.1
+
diff --git a/queue-6.1/sched-core-fix-arch_scale_freq_tick-on-tickless-syst.patch b/queue-6.1/sched-core-fix-arch_scale_freq_tick-on-tickless-syst.patch
new file mode 100644 (file)
index 0000000..95ecdb9
--- /dev/null
@@ -0,0 +1,56 @@
+From 6abbcb374d5cc479423241ca6f867fe11d806c41 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Nov 2022 14:51:21 +0200
+Subject: sched/core: Fix arch_scale_freq_tick() on tickless systems
+
+From: Yair Podemsky <ypodemsk@redhat.com>
+
+[ Upstream commit 7fb3ff22ad8772bbf0e3ce1ef3eb7b09f431807f ]
+
+In order for the scheduler to be frequency invariant we measure the
+ratio between the maximum CPU frequency and the actual CPU frequency.
+
+During long tickless periods of time the calculations that keep track
+of that might overflow, in the function scale_freq_tick():
+
+  if (check_shl_overflow(acnt, 2*SCHED_CAPACITY_SHIFT, &acnt))
+          goto error;
+
+eventually forcing the kernel to disable the feature for all CPUs,
+and show the warning message:
+
+   "Scheduler frequency invariance went wobbly, disabling!".
+
+Let's avoid that by limiting the frequency invariant calculations
+to CPUs with regular tick.
+
+Fixes: e2b0d619b400 ("x86, sched: check for counters overflow in frequency invariant accounting")
+Suggested-by: "Peter Zijlstra (Intel)" <peterz@infradead.org>
+Signed-off-by: Yair Podemsky <ypodemsk@redhat.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Reviewed-by: Valentin Schneider <vschneid@redhat.com>
+Acked-by: Giovanni Gherdovich <ggherdovich@suse.cz>
+Link: https://lore.kernel.org/r/20221130125121.34407-1-ypodemsk@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/sched/core.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index 981e41cc4121..172ec79b66f6 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -5498,7 +5498,9 @@ void scheduler_tick(void)
+       unsigned long thermal_pressure;
+       u64 resched_latency;
+-      arch_scale_freq_tick();
++      if (housekeeping_cpu(cpu, HK_TYPE_TICK))
++              arch_scale_freq_tick();
++
+       sched_clock_tick();
+       rq_lock(rq, &rf);
+-- 
+2.35.1
+
diff --git a/queue-6.1/scsi-mpi3mr-refer-config_scsi_mpi3mr-in-makefile.patch b/queue-6.1/scsi-mpi3mr-refer-config_scsi_mpi3mr-in-makefile.patch
new file mode 100644 (file)
index 0000000..94e711f
--- /dev/null
@@ -0,0 +1,44 @@
+From 3153380ff980cb26ef68601ae93d1a9e069dd30c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Dec 2022 11:36:59 +0900
+Subject: scsi: mpi3mr: Refer CONFIG_SCSI_MPI3MR in Makefile
+
+From: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
+
+[ Upstream commit f0a43ba6c66cc0688e2748d986a1459fdd3442ef ]
+
+When Kconfig item CONFIG_SCSI_MPI3MR was introduced for mpi3mr driver, the
+Makefile of the driver was not modified to refer the Kconfig item.
+
+As a result, mpi3mr.ko is built regardless of the Kconfig item value y or
+m. Also, if 'make localmodconfig' can not find the Kconfig item in the
+Makefile, then it does not generate CONFIG_SCSI_MPI3MR=m even when
+mpi3mr.ko is loaded on the system.
+
+Refer to the Kconfig item to avoid the issues.
+
+Fixes: c4f7ac64616e ("scsi: mpi3mr: Add mpi30 Rev-R headers and Kconfig")
+Signed-off-by: Shin'ichiro Kawasaki <shinichiro.kawasaki@wdc.com>
+Link: https://lore.kernel.org/r/20221207023659.2411785-1-shinichiro.kawasaki@wdc.com
+Reviewed-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
+Acked-by: Sathya Prakash Veerichetty <sathya.prakash@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/mpi3mr/Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/mpi3mr/Makefile b/drivers/scsi/mpi3mr/Makefile
+index ef86ca46646b..3bf8cf34e1c3 100644
+--- a/drivers/scsi/mpi3mr/Makefile
++++ b/drivers/scsi/mpi3mr/Makefile
+@@ -1,5 +1,5 @@
+ # mpi3mr makefile
+-obj-m += mpi3mr.o
++obj-$(CONFIG_SCSI_MPI3MR) += mpi3mr.o
+ mpi3mr-y +=  mpi3mr_os.o     \
+               mpi3mr_fw.o \
+               mpi3mr_app.o \
+-- 
+2.35.1
+
diff --git a/queue-6.1/scsi-storvsc-fix-swiotlb-bounce-buffer-leak-in-confi.patch b/queue-6.1/scsi-storvsc-fix-swiotlb-bounce-buffer-leak-in-confi.patch
new file mode 100644 (file)
index 0000000..42547b4
--- /dev/null
@@ -0,0 +1,51 @@
+From 4332ec1394ed16170d756433aa7867f97709eb08 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 4 Dec 2022 11:52:44 -0800
+Subject: scsi: storvsc: Fix swiotlb bounce buffer leak in confidential VM
+
+From: Michael Kelley <mikelley@microsoft.com>
+
+[ Upstream commit 67ff3d0a49f3d445c3922e30a54e03c161da561e ]
+
+storvsc_queuecommand() maps the scatter/gather list using scsi_dma_map(),
+which in a confidential VM allocates swiotlb bounce buffers. If the I/O
+submission fails in storvsc_do_io(), the I/O is typically retried by higher
+level code, but the bounce buffer memory is never freed.  The mostly like
+cause of I/O submission failure is a full VMBus channel ring buffer, which
+is not uncommon under high I/O loads.  Eventually enough bounce buffer
+memory leaks that the confidential VM can't do any I/O. The same problem
+can arise in a non-confidential VM with kernel boot parameter
+swiotlb=force.
+
+Fix this by doing scsi_dma_unmap() in the case of an I/O submission
+error, which frees the bounce buffer memory.
+
+Fixes: 743b237c3a7b ("scsi: storvsc: Add Isolation VM support for storvsc driver")
+Signed-off-by: Michael Kelley <mikelley@microsoft.com>
+Link: https://lore.kernel.org/r/1670183564-76254-1-git-send-email-mikelley@microsoft.com
+Tested-by: Dexuan Cui <decui@microsoft.com>
+Reviewed-by: Dexuan Cui <decui@microsoft.com>
+Reviewed-by: Tianyu Lan <Tianyu.Lan@microsoft.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/storvsc_drv.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
+index 3c5b7e4227b2..55d6fb452680 100644
+--- a/drivers/scsi/storvsc_drv.c
++++ b/drivers/scsi/storvsc_drv.c
+@@ -1823,6 +1823,9 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
+       ret = storvsc_do_io(dev, cmd_request, get_cpu());
+       put_cpu();
++      if (ret)
++              scsi_dma_unmap(scmnd);
++
+       if (ret == -EAGAIN) {
+               /* no more space */
+               ret = SCSI_MLQUEUE_DEVICE_BUSY;
+-- 
+2.35.1
+
diff --git a/queue-6.1/scsi-ufs-core-wlun-suspend-ssu-enter-hibern8-fail-re.patch b/queue-6.1/scsi-ufs-core-wlun-suspend-ssu-enter-hibern8-fail-re.patch
new file mode 100644 (file)
index 0000000..adeb805
--- /dev/null
@@ -0,0 +1,79 @@
+From 0cceeb7e85a809b6d3410ce006510967ea81f084 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Dec 2022 15:25:20 +0800
+Subject: scsi: ufs: core: WLUN suspend SSU/enter hibern8 fail recovery
+
+From: Peter Wang <peter.wang@mediatek.com>
+
+[ Upstream commit 1a5665fc8d7a000671ebd3fe69c6f9acf1e0dcd9 ]
+
+When SSU/enter hibern8 fail in WLUN suspend flow, trigger the error handler
+and return busy to break the suspend.  Otherwise the consumer will get
+stuck in runtime suspend status.
+
+Fixes: b294ff3e3449 ("scsi: ufs: core: Enable power management for wlun")
+Signed-off-by: Peter Wang <peter.wang@mediatek.com>
+Link: https://lore.kernel.org/r/20221208072520.26210-1-peter.wang@mediatek.com
+Reviewed-by: Stanley Chu <stanley.chu@mediatek.com>
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ufs/core/ufshcd.c | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
+index d1db6be80156..b048357d21e3 100644
+--- a/drivers/ufs/core/ufshcd.c
++++ b/drivers/ufs/core/ufshcd.c
+@@ -6094,6 +6094,14 @@ void ufshcd_schedule_eh_work(struct ufs_hba *hba)
+       }
+ }
++static void ufshcd_force_error_recovery(struct ufs_hba *hba)
++{
++      spin_lock_irq(hba->host->host_lock);
++      hba->force_reset = true;
++      ufshcd_schedule_eh_work(hba);
++      spin_unlock_irq(hba->host->host_lock);
++}
++
+ static void ufshcd_clk_scaling_allow(struct ufs_hba *hba, bool allow)
+ {
+       down_write(&hba->clk_scaling_lock);
+@@ -9066,6 +9074,15 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
+               if (!hba->dev_info.b_rpm_dev_flush_capable) {
+                       ret = ufshcd_set_dev_pwr_mode(hba, req_dev_pwr_mode);
++                      if (ret && pm_op != UFS_SHUTDOWN_PM) {
++                              /*
++                               * If return err in suspend flow, IO will hang.
++                               * Trigger error handler and break suspend for
++                               * error recovery.
++                               */
++                              ufshcd_force_error_recovery(hba);
++                              ret = -EBUSY;
++                      }
+                       if (ret)
+                               goto enable_scaling;
+               }
+@@ -9077,6 +9094,15 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
+        */
+       check_for_bkops = !ufshcd_is_ufs_dev_deepsleep(hba);
+       ret = ufshcd_link_state_transition(hba, req_link_state, check_for_bkops);
++      if (ret && pm_op != UFS_SHUTDOWN_PM) {
++              /*
++               * If return err in suspend flow, IO will hang.
++               * Trigger error handler and break suspend for
++               * error recovery.
++               */
++              ufshcd_force_error_recovery(hba);
++              ret = -EBUSY;
++      }
+       if (ret)
+               goto set_dev_active;
+-- 
+2.35.1
+
diff --git a/queue-6.1/selftests-net-l2_tos_ttl_inherit.sh-ensure-environme.patch b/queue-6.1/selftests-net-l2_tos_ttl_inherit.sh-ensure-environme.patch
new file mode 100644 (file)
index 0000000..c55f33d
--- /dev/null
@@ -0,0 +1,113 @@
+From 7e16342d79be2cf3c16266bc8ca1670575626cd4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 8 Jan 2023 16:45:50 +0100
+Subject: selftests/net: l2_tos_ttl_inherit.sh: Ensure environment cleanup on
+ failure.
+
+From: Guillaume Nault <gnault@redhat.com>
+
+[ Upstream commit d68ff8ad3351b8fc8d6f14b9a4f5cc8ba3e8bd13 ]
+
+Use 'set -e' and an exit handler to stop the script if a command fails
+and ensure the test environment is cleaned up in any case. Also, handle
+the case where the script is interrupted by SIGINT.
+
+The only command that's expected to fail is 'wait $ping_pid', since
+it's killed by the script. Handle this case with '|| true' to make it
+play well with 'set -e'.
+
+Finally, return the Kselftest SKIP code (4) when the script breaks
+because of an environment problem or a command line failure. The 0 and
+1 return codes should now reliably indicate that all tests have been
+run (0: all tests run and passed, 1: all tests run but at least one
+failed, 4: test script didn't run completely).
+
+Fixes: b690842d12fd ("selftests/net: test l2 tunnel TOS/TTL inheriting")
+Reported-by: Mirsad Goran Todorovac <mirsad.todorovac@alu.unizg.hr>
+Tested-by: Mirsad Goran Todorovac <mirsad.todorovac@alu.unizg.hr>
+Signed-off-by: Guillaume Nault <gnault@redhat.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/net/l2_tos_ttl_inherit.sh       | 40 +++++++++++++++++--
+ 1 file changed, 36 insertions(+), 4 deletions(-)
+
+diff --git a/tools/testing/selftests/net/l2_tos_ttl_inherit.sh b/tools/testing/selftests/net/l2_tos_ttl_inherit.sh
+index cf56680d598f..f11756e7df2f 100755
+--- a/tools/testing/selftests/net/l2_tos_ttl_inherit.sh
++++ b/tools/testing/selftests/net/l2_tos_ttl_inherit.sh
+@@ -12,13 +12,16 @@
+ # In addition this script also checks if forcing a specific field in the
+ # outer header is working.
++# Return 4 by default (Kselftest SKIP code)
++ERR=4
++
+ if [ "$(id -u)" != "0" ]; then
+       echo "Please run as root."
+-      exit 0
++      exit $ERR
+ fi
+ if ! which tcpdump > /dev/null 2>&1; then
+       echo "No tcpdump found. Required for this test."
+-      exit 0
++      exit $ERR
+ fi
+ expected_tos="0x00"
+@@ -340,7 +343,7 @@ verify() {
+               fi
+       fi
+       kill -9 $ping_pid
+-      wait $ping_pid 2>/dev/null
++      wait $ping_pid 2>/dev/null || true
+       result="FAIL"
+       if [ "$outer" = "4" ]; then
+               captured_ttl="$(get_field "ttl" "$out")"
+@@ -380,6 +383,31 @@ cleanup() {
+       ip netns del "${NS1}" 2>/dev/null
+ }
++exit_handler() {
++      # Don't exit immediately if one of the intermediate commands fails.
++      # We might be called at the end of the script, when the network
++      # namespaces have already been deleted. So cleanup() may fail, but we
++      # still need to run until 'exit $ERR' or the script won't return the
++      # correct error code.
++      set +e
++
++      cleanup
++
++      exit $ERR
++}
++
++# Restore the default SIGINT handler (just in case) and exit.
++# The exit handler will take care of cleaning everything up.
++interrupted() {
++      trap - INT
++
++      exit $ERR
++}
++
++set -e
++trap exit_handler EXIT
++trap interrupted INT
++
+ printf "┌────────┬───────┬───────┬──────────────┬"
+ printf "──────────────┬───────┬────────┐\n"
+ for type in gre vxlan geneve; do
+@@ -409,6 +437,10 @@ done
+ printf "└────────┴───────┴───────┴──────────────┴"
+ printf "──────────────┴───────┴────────┘\n"
++# All tests done.
++# Set ERR appropriately: it will be returned by the exit handler.
+ if $failed; then
+-      exit 1
++      ERR=1
++else
++      ERR=0
+ fi
+-- 
+2.35.1
+
diff --git a/queue-6.1/selftests-net-l2_tos_ttl_inherit.sh-run-tests-in-the.patch b/queue-6.1/selftests-net-l2_tos_ttl_inherit.sh-run-tests-in-the.patch
new file mode 100644 (file)
index 0000000..07d21d2
--- /dev/null
@@ -0,0 +1,309 @@
+From 89dc77464444ff55b9bf378460a272ade4285b0c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 8 Jan 2023 16:45:46 +0100
+Subject: selftests/net: l2_tos_ttl_inherit.sh: Run tests in their own netns.
+
+From: Guillaume Nault <gnault@redhat.com>
+
+[ Upstream commit c53cb00f7983a5474f2d36967f84908b85af9159 ]
+
+This selftest currently runs half in the current namespace and half in
+a netns of its own. Therefore, the test can fail if the current
+namespace is already configured with incompatible parameters (for
+example if it already has a veth0 interface).
+
+Adapt the script to put both ends of the veth pair in their own netns.
+Now veth0 is created in NS0 instead of the current namespace, while
+veth1 is set up in NS1 (instead of the 'testing' netns).
+
+The user visible netns names are randomised to minimise the risk of
+conflicts with already existing namespaces. The cleanup() function
+doesn't need to remove the virtual interface anymore: deleting NS0 and
+NS1 automatically removes the virtual interfaces they contained.
+
+We can remove $ns, which was only used to run ip commands in the
+'testing' netns (let's use the builtin "-netns" option instead).
+However, we still need a similar functionality as ping and tcpdump
+now need to run in NS0. So we now have $RUN_NS0 for that.
+
+Fixes: b690842d12fd ("selftests/net: test l2 tunnel TOS/TTL inheriting")
+Reported-by: Mirsad Goran Todorovac <mirsad.todorovac@alu.unizg.hr>
+Tested-by: Mirsad Goran Todorovac <mirsad.todorovac@alu.unizg.hr>
+Signed-off-by: Guillaume Nault <gnault@redhat.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../selftests/net/l2_tos_ttl_inherit.sh       | 162 ++++++++++--------
+ 1 file changed, 93 insertions(+), 69 deletions(-)
+
+diff --git a/tools/testing/selftests/net/l2_tos_ttl_inherit.sh b/tools/testing/selftests/net/l2_tos_ttl_inherit.sh
+index e2574b08eabc..cf56680d598f 100755
+--- a/tools/testing/selftests/net/l2_tos_ttl_inherit.sh
++++ b/tools/testing/selftests/net/l2_tos_ttl_inherit.sh
+@@ -25,6 +25,11 @@ expected_tos="0x00"
+ expected_ttl="0"
+ failed=false
++readonly NS0=$(mktemp -u ns0-XXXXXXXX)
++readonly NS1=$(mktemp -u ns1-XXXXXXXX)
++
++RUN_NS0="ip netns exec ${NS0}"
++
+ get_random_tos() {
+       # Get a random hex tos value between 0x00 and 0xfc, a multiple of 4
+       echo "0x$(tr -dc '0-9a-f' < /dev/urandom | head -c 1)\
+@@ -61,7 +66,6 @@ setup() {
+       local vlan="$5"
+       local test_tos="0x00"
+       local test_ttl="0"
+-      local ns="ip netns exec testing"
+       # We don't want a test-tos of 0x00,
+       # because this is the value that we get when no tos is set.
+@@ -94,14 +98,15 @@ setup() {
+       printf "│%7s │%6s │%6s │%13s │%13s │%6s │" \
+       "$type" "$outer" "$inner" "$tos" "$ttl" "$vlan"
+-      # Create 'testing' netns, veth pair and connect main ns with testing ns
+-      ip netns add testing
+-      ip link add type veth
+-      ip link set veth1 netns testing
+-      ip link set veth0 up
+-      $ns ip link set veth1 up
+-      ip addr flush dev veth0
+-      $ns ip addr flush dev veth1
++      # Create netns NS0 and NS1 and connect them with a veth pair
++      ip netns add "${NS0}"
++      ip netns add "${NS1}"
++      ip link add name veth0 netns "${NS0}" type veth \
++              peer name veth1 netns "${NS1}"
++      ip -netns "${NS0}" link set dev veth0 up
++      ip -netns "${NS1}" link set dev veth1 up
++      ip -netns "${NS0}" address flush dev veth0
++      ip -netns "${NS1}" address flush dev veth1
+       local local_addr1=""
+       local local_addr2=""
+@@ -127,51 +132,59 @@ setup() {
+               if [ "$type" = "gre" ]; then
+                       type="gretap"
+               fi
+-              ip addr add 198.18.0.1/24 dev veth0
+-              $ns ip addr add 198.18.0.2/24 dev veth1
+-              ip link add name tep0 type $type $local_addr1 remote \
+-              198.18.0.2 tos $test_tos ttl $test_ttl $vxlan $geneve
+-              $ns ip link add name tep1 type $type $local_addr2 remote \
+-              198.18.0.1 tos $test_tos ttl $test_ttl $vxlan $geneve
++              ip -netns "${NS0}" address add 198.18.0.1/24 dev veth0
++              ip -netns "${NS1}" address add 198.18.0.2/24 dev veth1
++              ip -netns "${NS0}" link add name tep0 type $type $local_addr1 \
++                      remote 198.18.0.2 tos $test_tos ttl $test_ttl         \
++                      $vxlan $geneve
++              ip -netns "${NS1}" link add name tep1 type $type $local_addr2 \
++                      remote 198.18.0.1 tos $test_tos ttl $test_ttl         \
++                      $vxlan $geneve
+       elif [ "$outer" = "6" ]; then
+               if [ "$type" = "gre" ]; then
+                       type="ip6gretap"
+               fi
+-              ip addr add fdd1:ced0:5d88:3fce::1/64 dev veth0 nodad
+-              $ns ip addr add fdd1:ced0:5d88:3fce::2/64 dev veth1 nodad
+-              ip link add name tep0 type $type $local_addr1 \
+-              remote fdd1:ced0:5d88:3fce::2 tos $test_tos ttl $test_ttl \
+-              $vxlan $geneve
+-              $ns ip link add name tep1 type $type $local_addr2 \
+-              remote fdd1:ced0:5d88:3fce::1 tos $test_tos ttl $test_ttl \
+-              $vxlan $geneve
++              ip -netns "${NS0}" address add fdd1:ced0:5d88:3fce::1/64 \
++                      dev veth0 nodad
++              ip -netns "${NS1}" address add fdd1:ced0:5d88:3fce::2/64 \
++                      dev veth1 nodad
++              ip -netns "${NS0}" link add name tep0 type $type $local_addr1 \
++                      remote fdd1:ced0:5d88:3fce::2 tos $test_tos           \
++                      ttl $test_ttl $vxlan $geneve
++              ip -netns "${NS1}" link add name tep1 type $type $local_addr2 \
++                      remote fdd1:ced0:5d88:3fce::1 tos $test_tos           \
++                      ttl $test_ttl $vxlan $geneve
+       fi
+       # Bring L2-tunnel link up and create VLAN on top
+-      ip link set tep0 up
+-      $ns ip link set tep1 up
+-      ip addr flush dev tep0
+-      $ns ip addr flush dev tep1
++      ip -netns "${NS0}" link set tep0 up
++      ip -netns "${NS1}" link set tep1 up
++      ip -netns "${NS0}" address flush dev tep0
++      ip -netns "${NS1}" address flush dev tep1
+       local parent
+       if $vlan; then
+               parent="vlan99-"
+-              ip link add link tep0 name ${parent}0 type vlan id 99
+-              $ns ip link add link tep1 name ${parent}1 type vlan id 99
+-              ip link set ${parent}0 up
+-              $ns ip link set ${parent}1 up
+-              ip addr flush dev ${parent}0
+-              $ns ip addr flush dev ${parent}1
++              ip -netns "${NS0}" link add link tep0 name ${parent}0 \
++                      type vlan id 99
++              ip -netns "${NS1}" link add link tep1 name ${parent}1 \
++                      type vlan id 99
++              ip -netns "${NS0}" link set dev ${parent}0 up
++              ip -netns "${NS1}" link set dev ${parent}1 up
++              ip -netns "${NS0}" address flush dev ${parent}0
++              ip -netns "${NS1}" address flush dev ${parent}1
+       else
+               parent="tep"
+       fi
+       # Assign inner IPv4/IPv6 addresses
+       if [ "$inner" = "4" ] || [ "$inner" = "other" ]; then
+-              ip addr add 198.19.0.1/24 brd + dev ${parent}0
+-              $ns ip addr add 198.19.0.2/24 brd + dev ${parent}1
++              ip -netns "${NS0}" address add 198.19.0.1/24 brd + dev ${parent}0
++              ip -netns "${NS1}" address add 198.19.0.2/24 brd + dev ${parent}1
+       elif [ "$inner" = "6" ]; then
+-              ip addr add fdd4:96cf:4eae:443b::1/64 dev ${parent}0 nodad
+-              $ns ip addr add fdd4:96cf:4eae:443b::2/64 dev ${parent}1 nodad
++              ip -netns "${NS0}" address add fdd4:96cf:4eae:443b::1/64 \
++                      dev ${parent}0 nodad
++              ip -netns "${NS1}" address add fdd4:96cf:4eae:443b::2/64 \
++                      dev ${parent}1 nodad
+       fi
+ }
+@@ -192,10 +205,10 @@ verify() {
+               ping_dst="198.19.0.3" # Generates ARPs which are not IPv4/IPv6
+       fi
+       if [ "$tos_ttl" = "inherit" ]; then
+-              ping -i 0.1 $ping_dst -Q "$expected_tos" -t "$expected_ttl" \
+-              2>/dev/null 1>&2 & ping_pid="$!"
++              ${RUN_NS0} ping -i 0.1 $ping_dst -Q "$expected_tos"          \
++                       -t "$expected_ttl" 2>/dev/null 1>&2 & ping_pid="$!"
+       else
+-              ping -i 0.1 $ping_dst 2>/dev/null 1>&2 & ping_pid="$!"
++              ${RUN_NS0} ping -i 0.1 $ping_dst 2>/dev/null 1>&2 & ping_pid="$!"
+       fi
+       local tunnel_type_offset tunnel_type_proto req_proto_offset req_offset
+       if [ "$type" = "gre" ]; then
+@@ -216,10 +229,12 @@ verify() {
+                               req_proto_offset="$((req_proto_offset + 4))"
+                               req_offset="$((req_offset + 4))"
+                       fi
+-                      out="$(tcpdump --immediate-mode -p -c 1 -v -i veth0 -n \
+-                      ip[$tunnel_type_offset] = $tunnel_type_proto and \
+-                      ip[$req_proto_offset] = 0x01 and \
+-                      ip[$req_offset] = 0x08 2>/dev/null | head -n 1)"
++                      out="$(${RUN_NS0} tcpdump --immediate-mode -p -c 1 -v \
++                              -i veth0 -n                                   \
++                              ip[$tunnel_type_offset] = $tunnel_type_proto and \
++                              ip[$req_proto_offset] = 0x01 and              \
++                              ip[$req_offset] = 0x08 2>/dev/null            \
++                              | head -n 1)"
+               elif [ "$inner" = "6" ]; then
+                       req_proto_offset="44"
+                       req_offset="78"
+@@ -231,10 +246,12 @@ verify() {
+                               req_proto_offset="$((req_proto_offset + 4))"
+                               req_offset="$((req_offset + 4))"
+                       fi
+-                      out="$(tcpdump --immediate-mode -p -c 1 -v -i veth0 -n \
+-                      ip[$tunnel_type_offset] = $tunnel_type_proto and \
+-                      ip[$req_proto_offset] = 0x3a and \
+-                      ip[$req_offset] = 0x80 2>/dev/null | head -n 1)"
++                      out="$(${RUN_NS0} tcpdump --immediate-mode -p -c 1 -v \
++                              -i veth0 -n                                   \
++                              ip[$tunnel_type_offset] = $tunnel_type_proto and \
++                              ip[$req_proto_offset] = 0x3a and              \
++                              ip[$req_offset] = 0x80 2>/dev/null            \
++                              | head -n 1)"
+               elif [ "$inner" = "other" ]; then
+                       req_proto_offset="36"
+                       req_offset="45"
+@@ -250,11 +267,13 @@ verify() {
+                               expected_tos="0x00"
+                               expected_ttl="64"
+                       fi
+-                      out="$(tcpdump --immediate-mode -p -c 1 -v -i veth0 -n \
+-                      ip[$tunnel_type_offset] = $tunnel_type_proto and \
+-                      ip[$req_proto_offset] = 0x08 and \
+-                      ip[$((req_proto_offset + 1))] = 0x06 and \
+-                      ip[$req_offset] = 0x01 2>/dev/null | head -n 1)"
++                      out="$(${RUN_NS0} tcpdump --immediate-mode -p -c 1 -v \
++                              -i veth0 -n                                   \
++                              ip[$tunnel_type_offset] = $tunnel_type_proto and \
++                              ip[$req_proto_offset] = 0x08 and              \
++                              ip[$((req_proto_offset + 1))] = 0x06 and      \
++                              ip[$req_offset] = 0x01 2>/dev/null            \
++                              | head -n 1)"
+               fi
+       elif [ "$outer" = "6" ]; then
+               if [ "$type" = "gre" ]; then
+@@ -273,10 +292,12 @@ verify() {
+                               req_proto_offset="$((req_proto_offset + 4))"
+                               req_offset="$((req_offset + 4))"
+                       fi
+-                      out="$(tcpdump --immediate-mode -p -c 1 -v -i veth0 -n \
+-                      ip6[$tunnel_type_offset] = $tunnel_type_proto and \
+-                      ip6[$req_proto_offset] = 0x01 and \
+-                      ip6[$req_offset] = 0x08 2>/dev/null | head -n 1)"
++                      out="$(${RUN_NS0} tcpdump --immediate-mode -p -c 1 -v \
++                              -i veth0 -n                                   \
++                              ip6[$tunnel_type_offset] = $tunnel_type_proto and \
++                              ip6[$req_proto_offset] = 0x01 and             \
++                              ip6[$req_offset] = 0x08 2>/dev/null           \
++                              | head -n 1)"
+               elif [ "$inner" = "6" ]; then
+                       local req_proto_offset="72"
+                       local req_offset="106"
+@@ -288,10 +309,12 @@ verify() {
+                               req_proto_offset="$((req_proto_offset + 4))"
+                               req_offset="$((req_offset + 4))"
+                       fi
+-                      out="$(tcpdump --immediate-mode -p -c 1 -v -i veth0 -n \
+-                      ip6[$tunnel_type_offset] = $tunnel_type_proto and \
+-                      ip6[$req_proto_offset] = 0x3a and \
+-                      ip6[$req_offset] = 0x80 2>/dev/null | head -n 1)"
++                      out="$(${RUN_NS0} tcpdump --immediate-mode -p -c 1 -v \
++                              -i veth0 -n                                   \
++                              ip6[$tunnel_type_offset] = $tunnel_type_proto and \
++                              ip6[$req_proto_offset] = 0x3a and             \
++                              ip6[$req_offset] = 0x80 2>/dev/null           \
++                              | head -n 1)"
+               elif [ "$inner" = "other" ]; then
+                       local req_proto_offset="64"
+                       local req_offset="73"
+@@ -307,11 +330,13 @@ verify() {
+                               expected_tos="0x00"
+                               expected_ttl="64"
+                       fi
+-                      out="$(tcpdump --immediate-mode -p -c 1 -v -i veth0 -n \
+-                      ip6[$tunnel_type_offset] = $tunnel_type_proto and \
+-                      ip6[$req_proto_offset] = 0x08 and \
+-                      ip6[$((req_proto_offset + 1))] = 0x06 and \
+-                      ip6[$req_offset] = 0x01 2>/dev/null | head -n 1)"
++                      out="$(${RUN_NS0} tcpdump --immediate-mode -p -c 1 -v \
++                              -i veth0 -n                                   \
++                              ip6[$tunnel_type_offset] = $tunnel_type_proto and \
++                              ip6[$req_proto_offset] = 0x08 and             \
++                              ip6[$((req_proto_offset + 1))] = 0x06 and     \
++                              ip6[$req_offset] = 0x01 2>/dev/null           \
++                              | head -n 1)"
+               fi
+       fi
+       kill -9 $ping_pid
+@@ -351,9 +376,8 @@ verify() {
+ }
+ cleanup() {
+-      ip link del veth0 2>/dev/null
+-      ip netns del testing 2>/dev/null
+-      ip link del tep0 2>/dev/null
++      ip netns del "${NS0}" 2>/dev/null
++      ip netns del "${NS1}" 2>/dev/null
+ }
+ printf "┌────────┬───────┬───────┬──────────────┬"
+-- 
+2.35.1
+
diff --git a/queue-6.1/selftests-net-l2_tos_ttl_inherit.sh-set-ipv6-address.patch b/queue-6.1/selftests-net-l2_tos_ttl_inherit.sh-set-ipv6-address.patch
new file mode 100644 (file)
index 0000000..7303f94
--- /dev/null
@@ -0,0 +1,52 @@
+From 7ab6b7c24ac07a7eb678ee0571c84a73c46f9b27 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 8 Jan 2023 16:45:41 +0100
+Subject: selftests/net: l2_tos_ttl_inherit.sh: Set IPv6 addresses with
+ "nodad".
+
+From: Guillaume Nault <gnault@redhat.com>
+
+[ Upstream commit e59370b2e96eb8e7e057a2a16e999ff385a3f2fb ]
+
+The ping command can run before DAD completes. In that case, ping may
+fail and break the selftest.
+
+We don't need DAD here since we're working on isolated device pairs.
+
+Fixes: b690842d12fd ("selftests/net: test l2 tunnel TOS/TTL inheriting")
+Signed-off-by: Guillaume Nault <gnault@redhat.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/net/l2_tos_ttl_inherit.sh | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/tools/testing/selftests/net/l2_tos_ttl_inherit.sh b/tools/testing/selftests/net/l2_tos_ttl_inherit.sh
+index dca1e6f777a8..e2574b08eabc 100755
+--- a/tools/testing/selftests/net/l2_tos_ttl_inherit.sh
++++ b/tools/testing/selftests/net/l2_tos_ttl_inherit.sh
+@@ -137,8 +137,8 @@ setup() {
+               if [ "$type" = "gre" ]; then
+                       type="ip6gretap"
+               fi
+-              ip addr add fdd1:ced0:5d88:3fce::1/64 dev veth0
+-              $ns ip addr add fdd1:ced0:5d88:3fce::2/64 dev veth1
++              ip addr add fdd1:ced0:5d88:3fce::1/64 dev veth0 nodad
++              $ns ip addr add fdd1:ced0:5d88:3fce::2/64 dev veth1 nodad
+               ip link add name tep0 type $type $local_addr1 \
+               remote fdd1:ced0:5d88:3fce::2 tos $test_tos ttl $test_ttl \
+               $vxlan $geneve
+@@ -170,8 +170,8 @@ setup() {
+               ip addr add 198.19.0.1/24 brd + dev ${parent}0
+               $ns ip addr add 198.19.0.2/24 brd + dev ${parent}1
+       elif [ "$inner" = "6" ]; then
+-              ip addr add fdd4:96cf:4eae:443b::1/64 dev ${parent}0
+-              $ns ip addr add fdd4:96cf:4eae:443b::2/64 dev ${parent}1
++              ip addr add fdd4:96cf:4eae:443b::1/64 dev ${parent}0 nodad
++              $ns ip addr add fdd4:96cf:4eae:443b::2/64 dev ${parent}1 nodad
+       fi
+ }
+-- 
+2.35.1
+
index bdd578303bf6ca3da38773d9d1e601fc3023f98e..25f18e5969fb0668e97945a163dde499c5bc3618 100644 (file)
@@ -94,3 +94,84 @@ edac-device-fix-period-calculation-in-edac_device_reset_delay_period.patch
 x86-pat-fix-pat_x_mtrr_type-for-mtrr-disabled-case.patch
 x86-resctrl-fix-task-closid-rmid-update-race.patch
 x86-resctrl-fix-event-counts-regression-in-reused-rmids.patch
+regulator-da9211-use-irq-handler-when-ready.patch
+scsi-storvsc-fix-swiotlb-bounce-buffer-leak-in-confi.patch
+scsi-mpi3mr-refer-config_scsi_mpi3mr-in-makefile.patch
+scsi-ufs-core-wlun-suspend-ssu-enter-hibern8-fail-re.patch
+asoc-intel-fix-sof-nau8825-link-failure.patch
+asoc-intel-sof_nau8825-support-rt1015p-speaker-ampli.patch
+asoc-intel-sof-nau8825-fix-module-alias-overflow.patch
+drm-msm-dpu-fix-some-kernel-doc-comments.patch
+drm-msm-dpu-fix-memory-leak-in-msm_mdss_parse_data_b.patch
+asoc-wm8904-fix-wrong-outputs-volume-after-power-rea.patch
+mtd-parsers-scpart-fix-__udivdi3-undefined-on-mips.patch
+mtd-cfi-allow-building-spi-intel-standalone.patch
+alsa-usb-audio-make-sure-to-stop-endpoints-before-cl.patch
+alsa-usb-audio-relax-hw-constraints-for-implicit-fb-.patch
+stmmac-dwmac-mediatek-remove-the-dwmac_fix_mac_speed.patch
+tipc-fix-unexpected-link-reset-due-to-discovery-mess.patch
+nfsd-pass-the-target-nfsd_file-to-nfsd_commit.patch
+nfsd-revert-nfsd-nfsv4-close-should-release-an-nfsd_.patch
+nfsd-add-an-nfsd_file_gc-flag-to-enable-nfsd_file-ga.patch
+nfsd-remove-the-pages_flushed-statistic-from-filecac.patch
+nfsd-reorganize-filecache.c.patch
+nfsd-add-an-nfsd_file_fsync-tracepoint.patch
+nfsd-rework-refcounting-in-filecache.patch
+nfsd-fix-handling-of-cached-open-files-in-nfsd4_open.patch
+octeontx2-af-fix-lmac-config-in-cgx_lmac_rx_tx_enabl.patch
+sched-core-fix-arch_scale_freq_tick-on-tickless-syst.patch
+blk-mq-move-the-srcu_struct-used-for-quiescing-to-th.patch
+blk-crypto-pass-a-gendisk-to-blk_crypto_sysfs_-un-re.patch
+block-factor-out-a-blk_debugfs_remove-helper.patch
+block-fix-error-unwinding-in-blk_register_queue.patch
+block-untangle-request_queue-refcounting-from-sysfs.patch
+block-mark-blk_put_queue-as-potentially-blocking.patch
+block-drop-spurious-might_sleep-from-blk_put_queue.patch
+hvc-xen-lock-console-list-traversal.patch
+nfc-pn533-wait-for-out_urb-s-completion-in-pn533_usb.patch
+gro-avoid-checking-for-a-failed-search.patch
+gro-take-care-of-dodgy-packets.patch
+af_unix-selftest-fix-the-size-of-the-parameter-to-co.patch
+asoc-qcom-fix-building-apq8016-machine-driver-withou.patch
+tools-nolibc-restore-mips-branch-ordering-in-the-_st.patch
+tools-nolibc-fix-the-o_-fcntl-open-macro-definitions.patch
+drm-amdgpu-fix-potential-null-dereference.patch
+ice-fix-potential-memory-leak-in-ice_gnss_tty_write.patch
+ice-add-check-for-kzalloc.patch
+drm-vmwgfx-write-the-driver-id-registers.patch
+drm-vmwgfx-refactor-resource-manager-s-hashtable-to-.patch
+drm-vmwgfx-remove-ttm-object-hashtable.patch
+drm-vmwgfx-refactor-resource-validation-hashtable-to.patch
+drm-vmwgfx-refactor-ttm-reference-object-hashtable-t.patch
+drm-vmwgfx-remove-vmwgfx_hashtab.patch
+drm-vmwgfx-remove-rcu-locks-from-user-resources.patch
+net-sched-act_mpls-fix-warning-during-failed-attribu.patch
+revert-r8169-disable-detection-of-chip-version-36.patch
+net-mlx5-check-attr-pointer-validity-before-derefere.patch
+net-mlx5e-tc-keep-mod-hdr-actions-after-mod-hdr-allo.patch
+net-mlx5-fix-command-stats-access-after-free.patch
+net-mlx5e-verify-dev-is-present-for-fix-features-ndo.patch
+net-mlx5e-ipoib-block-queue-count-configuration-when.patch
+net-mlx5e-ipoib-block-pkey-interfaces-with-less-rx-q.patch
+net-mlx5e-ipoib-fix-child-pkey-interface-stats-on-rx.patch
+net-mlx5-fix-ptp-max-frequency-adjustment-range.patch
+net-mlx5e-don-t-support-encap-rules-with-gbp-option.patch
+net-mlx5e-fix-macsec-ssci-attribute-handling-in-offl.patch
+net-mlx5e-fix-macsec-possible-null-dereference-when-.patch
+selftests-net-l2_tos_ttl_inherit.sh-set-ipv6-address.patch
+selftests-net-l2_tos_ttl_inherit.sh-run-tests-in-the.patch
+selftests-net-l2_tos_ttl_inherit.sh-ensure-environme.patch
+octeontx2-pf-fix-resource-leakage-in-vf-driver-unbin.patch
+perf-build-properly-guard-libbpf-includes.patch
+perf-kmem-support-legacy-tracepoints.patch
+perf-kmem-support-field-node-in-evsel__process_alloc.patch
+igc-fix-pps-delta-between-two-synchronized-end-point.patch
+net-lan966x-check-for-ptp-to-be-enabled-in-lan966x_p.patch
+net-hns3-fix-wrong-use-of-rss-size-during-vf-rss-con.patch
+bnxt-make-sure-we-return-pages-to-the-pool.patch
+platform-surface-aggregator-add-missing-call-to-ssam.patch
+platform-x86-amd-fix-refcount-leak-in-amd_pmc_probe.patch
+alsa-usb-audio-fix-possible-null-pointer-dereference.patch
+efi-fix-null-deref-in-init-error-path.patch
+io_uring-lock-overflowing-for-iopoll.patch
+io_uring-poll-attempt-request-issue-after-racy-poll-.patch
diff --git a/queue-6.1/stmmac-dwmac-mediatek-remove-the-dwmac_fix_mac_speed.patch b/queue-6.1/stmmac-dwmac-mediatek-remove-the-dwmac_fix_mac_speed.patch
new file mode 100644 (file)
index 0000000..17f8d8b
--- /dev/null
@@ -0,0 +1,81 @@
+From 80b2eb9b85e87fb17187dbef32e5f4c9144cce97 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 5 Jan 2023 09:07:11 +0800
+Subject: stmmac: dwmac-mediatek: remove the dwmac_fix_mac_speed
+
+From: Biao Huang <biao.huang@mediatek.com>
+
+[ Upstream commit c26de7507d1f5ffa5daf6a4980ef7896889691a9 ]
+
+In current driver, MAC will always enable 2ns delay in RGMII mode,
+but that's not the correct usage.
+
+Remove the dwmac_fix_mac_speed() in driver, and recommend "rgmii-id"
+for phy-mode in device tree.
+
+Fixes: f2d356a6ab71 ("stmmac: dwmac-mediatek: add support for mt8195")
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Biao Huang <biao.huang@mediatek.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/stmicro/stmmac/dwmac-mediatek.c  | 26 -------------------
+ 1 file changed, 26 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
+index d42e1afb6521..2f7d8e4561d9 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-mediatek.c
+@@ -90,7 +90,6 @@ struct mediatek_dwmac_plat_data {
+ struct mediatek_dwmac_variant {
+       int (*dwmac_set_phy_interface)(struct mediatek_dwmac_plat_data *plat);
+       int (*dwmac_set_delay)(struct mediatek_dwmac_plat_data *plat);
+-      void (*dwmac_fix_mac_speed)(void *priv, unsigned int speed);
+       /* clock ids to be requested */
+       const char * const *clk_list;
+@@ -443,32 +442,9 @@ static int mt8195_set_delay(struct mediatek_dwmac_plat_data *plat)
+       return 0;
+ }
+-static void mt8195_fix_mac_speed(void *priv, unsigned int speed)
+-{
+-      struct mediatek_dwmac_plat_data *priv_plat = priv;
+-
+-      if ((phy_interface_mode_is_rgmii(priv_plat->phy_mode))) {
+-              /* prefer 2ns fixed delay which is controlled by TXC_PHASE_CTRL,
+-               * when link speed is 1Gbps with RGMII interface,
+-               * Fall back to delay macro circuit for 10/100Mbps link speed.
+-               */
+-              if (speed == SPEED_1000)
+-                      regmap_update_bits(priv_plat->peri_regmap,
+-                                         MT8195_PERI_ETH_CTRL0,
+-                                         MT8195_RGMII_TXC_PHASE_CTRL |
+-                                         MT8195_DLY_GTXC_ENABLE |
+-                                         MT8195_DLY_GTXC_INV |
+-                                         MT8195_DLY_GTXC_STAGES,
+-                                         MT8195_RGMII_TXC_PHASE_CTRL);
+-              else
+-                      mt8195_set_delay(priv_plat);
+-      }
+-}
+-
+ static const struct mediatek_dwmac_variant mt8195_gmac_variant = {
+       .dwmac_set_phy_interface = mt8195_set_interface,
+       .dwmac_set_delay = mt8195_set_delay,
+-      .dwmac_fix_mac_speed = mt8195_fix_mac_speed,
+       .clk_list = mt8195_dwmac_clk_l,
+       .num_clks = ARRAY_SIZE(mt8195_dwmac_clk_l),
+       .dma_bit_mask = 35,
+@@ -619,8 +595,6 @@ static int mediatek_dwmac_common_data(struct platform_device *pdev,
+       plat->bsp_priv = priv_plat;
+       plat->init = mediatek_dwmac_init;
+       plat->clks_config = mediatek_dwmac_clks_config;
+-      if (priv_plat->variant->dwmac_fix_mac_speed)
+-              plat->fix_mac_speed = priv_plat->variant->dwmac_fix_mac_speed;
+       plat->safety_feat_cfg = devm_kzalloc(&pdev->dev,
+                                            sizeof(*plat->safety_feat_cfg),
+-- 
+2.35.1
+
diff --git a/queue-6.1/tipc-fix-unexpected-link-reset-due-to-discovery-mess.patch b/queue-6.1/tipc-fix-unexpected-link-reset-due-to-discovery-mess.patch
new file mode 100644 (file)
index 0000000..4c9f577
--- /dev/null
@@ -0,0 +1,111 @@
+From 1b2f3c186114c3012e40a60fe45d11eec9d19ddf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 5 Jan 2023 06:02:51 +0000
+Subject: tipc: fix unexpected link reset due to discovery messages
+
+From: Tung Nguyen <tung.q.nguyen@dektech.com.au>
+
+[ Upstream commit c244c092f1ed2acfb5af3d3da81e22367d3dd733 ]
+
+This unexpected behavior is observed:
+
+node 1                    | node 2
+------                    | ------
+link is established       | link is established
+reboot                    | link is reset
+up                        | send discovery message
+receive discovery message |
+link is established       | link is established
+send discovery message    |
+                          | receive discovery message
+                          | link is reset (unexpected)
+                          | send reset message
+link is reset             |
+
+It is due to delayed re-discovery as described in function
+tipc_node_check_dest(): "this link endpoint has already reset
+and re-established contact with the peer, before receiving a
+discovery message from that node."
+
+However, commit 598411d70f85 has changed the condition for calling
+tipc_node_link_down() which was the acceptance of new media address.
+
+This commit fixes this by restoring the old and correct behavior.
+
+Fixes: 598411d70f85 ("tipc: make resetting of links non-atomic")
+Acked-by: Jon Maloy <jmaloy@redhat.com>
+Signed-off-by: Tung Nguyen <tung.q.nguyen@dektech.com.au>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tipc/node.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/net/tipc/node.c b/net/tipc/node.c
+index 49ddc484c4fe..5e000fde8067 100644
+--- a/net/tipc/node.c
++++ b/net/tipc/node.c
+@@ -1179,8 +1179,9 @@ void tipc_node_check_dest(struct net *net, u32 addr,
+       bool addr_match = false;
+       bool sign_match = false;
+       bool link_up = false;
++      bool link_is_reset = false;
+       bool accept_addr = false;
+-      bool reset = true;
++      bool reset = false;
+       char *if_name;
+       unsigned long intv;
+       u16 session;
+@@ -1200,14 +1201,14 @@ void tipc_node_check_dest(struct net *net, u32 addr,
+       /* Prepare to validate requesting node's signature and media address */
+       l = le->link;
+       link_up = l && tipc_link_is_up(l);
++      link_is_reset = l && tipc_link_is_reset(l);
+       addr_match = l && !memcmp(&le->maddr, maddr, sizeof(*maddr));
+       sign_match = (signature == n->signature);
+       /* These three flags give us eight permutations: */
+       if (sign_match && addr_match && link_up) {
+-              /* All is fine. Do nothing. */
+-              reset = false;
++              /* All is fine. Ignore requests. */
+               /* Peer node is not a container/local namespace */
+               if (!n->peer_hash_mix)
+                       n->peer_hash_mix = hash_mixes;
+@@ -1232,6 +1233,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
+                */
+               accept_addr = true;
+               *respond = true;
++              reset = true;
+       } else if (!sign_match && addr_match && link_up) {
+               /* Peer node rebooted. Two possibilities:
+                *  - Delayed re-discovery; this link endpoint has already
+@@ -1263,6 +1265,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
+               n->signature = signature;
+               accept_addr = true;
+               *respond = true;
++              reset = true;
+       }
+       if (!accept_addr)
+@@ -1291,6 +1294,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
+               tipc_link_fsm_evt(l, LINK_RESET_EVT);
+               if (n->state == NODE_FAILINGOVER)
+                       tipc_link_fsm_evt(l, LINK_FAILOVER_BEGIN_EVT);
++              link_is_reset = tipc_link_is_reset(l);
+               le->link = l;
+               n->link_cnt++;
+               tipc_node_calculate_timer(n, l);
+@@ -1303,7 +1307,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
+       memcpy(&le->maddr, maddr, sizeof(*maddr));
+ exit:
+       tipc_node_write_unlock(n);
+-      if (reset && l && !tipc_link_is_reset(l))
++      if (reset && !link_is_reset)
+               tipc_node_link_down(n, b->identity, false);
+       tipc_node_put(n);
+ }
+-- 
+2.35.1
+
diff --git a/queue-6.1/tools-nolibc-fix-the-o_-fcntl-open-macro-definitions.patch b/queue-6.1/tools-nolibc-fix-the-o_-fcntl-open-macro-definitions.patch
new file mode 100644 (file)
index 0000000..ae07360
--- /dev/null
@@ -0,0 +1,49 @@
+From cba524cff2d1415bdaa95a9a066b456c33304375 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Jan 2023 08:54:42 +0100
+Subject: tools/nolibc: fix the O_* fcntl/open macro definitions for riscv
+
+From: Willy Tarreau <w@1wt.eu>
+
+[ Upstream commit 00b18da4089330196906b9fe075c581c17eb726c ]
+
+When RISCV port was imported in 5.2, the O_* macros were taken with
+their octal value and written as-is in hex, resulting in the getdents64()
+to fail in nolibc-test.
+
+Fixes: 582e84f7b779 ("tool headers nolibc: add RISCV support") #5.2
+Signed-off-by: Willy Tarreau <w@1wt.eu>
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/include/nolibc/arch-riscv.h | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/tools/include/nolibc/arch-riscv.h b/tools/include/nolibc/arch-riscv.h
+index ba04771cb3a3..a3bdd9803f8c 100644
+--- a/tools/include/nolibc/arch-riscv.h
++++ b/tools/include/nolibc/arch-riscv.h
+@@ -11,13 +11,13 @@
+ #define O_RDONLY            0
+ #define O_WRONLY            1
+ #define O_RDWR              2
+-#define O_CREAT         0x100
+-#define O_EXCL          0x200
+-#define O_NOCTTY        0x400
+-#define O_TRUNC        0x1000
+-#define O_APPEND       0x2000
+-#define O_NONBLOCK     0x4000
+-#define O_DIRECTORY  0x200000
++#define O_CREAT          0x40
++#define O_EXCL           0x80
++#define O_NOCTTY        0x100
++#define O_TRUNC         0x200
++#define O_APPEND        0x400
++#define O_NONBLOCK      0x800
++#define O_DIRECTORY   0x10000
+ struct sys_stat_struct {
+       unsigned long   st_dev;         /* Device.  */
+-- 
+2.35.1
+
diff --git a/queue-6.1/tools-nolibc-restore-mips-branch-ordering-in-the-_st.patch b/queue-6.1/tools-nolibc-restore-mips-branch-ordering-in-the-_st.patch
new file mode 100644 (file)
index 0000000..582ae00
--- /dev/null
@@ -0,0 +1,80 @@
+From 74c6ada39b016d83095dea69585ec5455f9e9fff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 Jan 2023 08:54:39 +0100
+Subject: tools/nolibc: restore mips branch ordering in the _start block
+
+From: Willy Tarreau <w@1wt.eu>
+
+[ Upstream commit 184177c3d6e023da934761e198c281344d7dd65b ]
+
+Depending on the compiler used and the optimization options, the sbrk()
+test was crashing, both on real hardware (mips-24kc) and in qemu. One
+such example is kernel.org toolchain in version 11.3 optimizing at -Os.
+
+Inspecting the sys_brk() call shows the following code:
+
+  0040047c <sys_brk>:
+    40047c:       24020fcd        li      v0,4045
+    400480:       27bdffe0        addiu   sp,sp,-32
+    400484:       0000000c        syscall
+    400488:       27bd0020        addiu   sp,sp,32
+    40048c:       10e00001        beqz    a3,400494 <sys_brk+0x18>
+    400490:       00021023        negu    v0,v0
+    400494:       03e00008        jr      ra
+
+It is obviously wrong, the "negu" instruction is placed in beqz's
+delayed slot, and worse, there's no nop nor instruction after the
+return, so the next function's first instruction (addiu sip,sip,-32)
+will also be executed as part of the delayed slot that follows the
+return.
+
+This is caused by the ".set noreorder" directive in the _start block,
+that applies to the whole program. The compiler emits code without the
+delayed slots and relies on the compiler to swap instructions when this
+option is not set. Removing the option would require to change the
+startup code in a way that wouldn't make it look like the resulting
+code, which would not be easy to debug. Instead let's just save the
+default ordering before changing it, and restore it at the end of the
+_start block. Now the code is correct:
+
+  0040047c <sys_brk>:
+    40047c:       24020fcd        li      v0,4045
+    400480:       27bdffe0        addiu   sp,sp,-32
+    400484:       0000000c        syscall
+    400488:       10e00002        beqz    a3,400494 <sys_brk+0x18>
+    40048c:       27bd0020        addiu   sp,sp,32
+    400490:       00021023        negu    v0,v0
+    400494:       03e00008        jr      ra
+    400498:       00000000        nop
+
+Fixes: 66b6f755ad45 ("rcutorture: Import a copy of nolibc") #5.0
+Signed-off-by: Willy Tarreau <w@1wt.eu>
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/include/nolibc/arch-mips.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h
+index 5fc5b8029bff..7380093ba9e7 100644
+--- a/tools/include/nolibc/arch-mips.h
++++ b/tools/include/nolibc/arch-mips.h
+@@ -192,6 +192,7 @@ struct sys_stat_struct {
+ __asm__ (".section .text\n"
+     ".weak __start\n"
+     ".set nomips16\n"
++    ".set push\n"
+     ".set    noreorder\n"
+     ".option pic0\n"
+     ".ent __start\n"
+@@ -210,6 +211,7 @@ __asm__ (".section .text\n"
+     "li $v0, 4001\n"              // NR_exit == 4001
+     "syscall\n"
+     ".end __start\n"
++    ".set pop\n"
+     "");
+ #endif // _NOLIBC_ARCH_MIPS_H
+-- 
+2.35.1
+