--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
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
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+
--- /dev/null
+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
+