--- /dev/null
+From 3b1ff57e24a7bcd2e2a8426dd2013a80d1fa96eb Mon Sep 17 00:00:00 2001
+From: Kai Vehmanen <kai.vehmanen@linux.intel.com>
+Date: Fri, 8 Dec 2023 15:21:26 +0200
+Subject: ALSA: hda/hdmi: add force-connect quirk for NUC5CPYB
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kai Vehmanen <kai.vehmanen@linux.intel.com>
+
+commit 3b1ff57e24a7bcd2e2a8426dd2013a80d1fa96eb upstream.
+
+Add one more older NUC model that requires quirk to force all pins to be
+connected. The display codec pins are not registered properly without
+the force-connect quirk. The codec will report only one pin as having
+external connectivity, but i915 finds all three connectors on the
+system, so the two drivers are not in sync.
+
+Issue found with DRM igt-gpu-tools test kms_hdmi_inject@inject-audio.
+
+Link: https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/issues/3
+Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Cc: Jani Saarinen <jani.saarinen@intel.com>
+Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20231208132127.2438067-2-kai.vehmanen@linux.intel.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/hda/patch_hdmi.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/pci/hda/patch_hdmi.c
++++ b/sound/pci/hda/patch_hdmi.c
+@@ -1994,6 +1994,7 @@ static const struct snd_pci_quirk force_
+ SND_PCI_QUIRK(0x103c, 0x8711, "HP", 1),
+ SND_PCI_QUIRK(0x103c, 0x8715, "HP", 1),
+ SND_PCI_QUIRK(0x1462, 0xec94, "MS-7C94", 1),
++ SND_PCI_QUIRK(0x8086, 0x2060, "Intel NUC5CPYB", 1),
+ SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", 1),
+ {}
+ };
--- /dev/null
+From 924f5ca2975b2993ee81a7ecc3c809943a70f334 Mon Sep 17 00:00:00 2001
+From: Kai Vehmanen <kai.vehmanen@linux.intel.com>
+Date: Fri, 8 Dec 2023 15:21:27 +0200
+Subject: ALSA: hda/hdmi: add force-connect quirks for ASUSTeK Z170 variants
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Kai Vehmanen <kai.vehmanen@linux.intel.com>
+
+commit 924f5ca2975b2993ee81a7ecc3c809943a70f334 upstream.
+
+On ASUSTeK Z170M PLUS and Z170 PRO GAMING systems, the display codec
+pins are not registered properly without the force-connect quirk. The
+codec will report only one pin as having external connectivity, but i915
+finds all three connectors on the system, so the two drivers are not
+in sync.
+
+Issue found with DRM igt-gpu-tools test kms_hdmi_inject@inject-audio.
+
+Link: https://gitlab.freedesktop.org/drm/intel/-/issues/9801
+Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Cc: Jani Saarinen <jani.saarinen@intel.com>
+Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20231208132127.2438067-3-kai.vehmanen@linux.intel.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/hda/patch_hdmi.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/pci/hda/patch_hdmi.c
++++ b/sound/pci/hda/patch_hdmi.c
+@@ -1993,6 +1993,8 @@ static const struct snd_pci_quirk force_
+ SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1),
+ SND_PCI_QUIRK(0x103c, 0x8711, "HP", 1),
+ SND_PCI_QUIRK(0x103c, 0x8715, "HP", 1),
++ SND_PCI_QUIRK(0x1043, 0x86ae, "ASUS", 1), /* Z170 PRO */
++ SND_PCI_QUIRK(0x1043, 0x86c7, "ASUS", 1), /* Z170M PLUS */
+ SND_PCI_QUIRK(0x1462, 0xec94, "MS-7C94", 1),
+ SND_PCI_QUIRK(0x8086, 0x2060, "Intel NUC5CPYB", 1),
+ SND_PCI_QUIRK(0x8086, 0x2081, "Intel NUC 10", 1),
--- /dev/null
+From 9b726bf6ae11add6a7a52883a21f90ff9cbca916 Mon Sep 17 00:00:00 2001
+From: Hartmut Knaack <knaack.h@gmx.de>
+Date: Sat, 9 Dec 2023 15:47:07 +0100
+Subject: ALSA: hda/realtek: Apply mute LED quirk for HP15-db
+
+From: Hartmut Knaack <knaack.h@gmx.de>
+
+commit 9b726bf6ae11add6a7a52883a21f90ff9cbca916 upstream.
+
+The HP laptop 15-db0403ng uses the ALC236 codec and controls the mute
+LED using COEF 0x07 index 1.
+Sound card subsystem: Hewlett-Packard Company Device [103c:84ae]
+
+Use the existing quirk for this model.
+
+Signed-off-by: Hartmut Knaack <knaack.h@gmx.de>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/e61815d0-f1c7-b164-e49d-6ca84771476a@gmx.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/hda/patch_realtek.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -9705,6 +9705,7 @@ static const struct snd_pci_quirk alc269
+ SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+ SND_PCI_QUIRK(0x103c, 0x841c, "HP Pavilion 15-CK0xx", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+ SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
++ SND_PCI_QUIRK(0x103c, 0x84ae, "HP 15-db0403ng", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
+ SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN),
+ SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+ SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360),
--- /dev/null
+From 6c6fa2641402e8e753262fb61ed9a15a7cb225ad Mon Sep 17 00:00:00 2001
+From: Gergo Koteles <soyer@irl.hu>
+Date: Thu, 14 Dec 2023 00:28:16 +0100
+Subject: ALSA: hda/tas2781: call cleanup functions only once
+
+From: Gergo Koteles <soyer@irl.hu>
+
+commit 6c6fa2641402e8e753262fb61ed9a15a7cb225ad upstream.
+
+If the module can load the RCA but not the firmware binary, it will call
+the cleanup functions. Then unloading the module causes general
+protection fault due to double free.
+
+Do not call the cleanup functions in tasdev_fw_ready.
+
+general protection fault, probably for non-canonical address
+0x6f2b8a2bff4c8fec: 0000 [#1] PREEMPT SMP NOPTI
+Call Trace:
+ <TASK>
+ ? die_addr+0x36/0x90
+ ? exc_general_protection+0x1c5/0x430
+ ? asm_exc_general_protection+0x26/0x30
+ ? tasdevice_config_info_remove+0x6d/0xd0 [snd_soc_tas2781_fmwlib]
+ tas2781_hda_unbind+0xaa/0x100 [snd_hda_scodec_tas2781_i2c]
+ component_unbind+0x2e/0x50
+ component_unbind_all+0x92/0xa0
+ component_del+0xa8/0x140
+ tas2781_hda_remove.isra.0+0x32/0x60 [snd_hda_scodec_tas2781_i2c]
+ i2c_device_remove+0x26/0xb0
+
+Fixes: 5be27f1e3ec9 ("ALSA: hda/tas2781: Add tas2781 HDA driver")
+CC: stable@vger.kernel.org
+Signed-off-by: Gergo Koteles <soyer@irl.hu>
+Link: https://lore.kernel.org/r/1a0885c424bb21172702d254655882b59ef6477a.1702510018.git.soyer@irl.hu
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/hda/tas2781_hda_i2c.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c
+index d3dafc9d150b..c8ee5f809c38 100644
+--- a/sound/pci/hda/tas2781_hda_i2c.c
++++ b/sound/pci/hda/tas2781_hda_i2c.c
+@@ -550,11 +550,6 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
+ tas2781_save_calibration(tas_priv);
+
+ out:
+- if (tas_priv->fw_state == TASDEVICE_DSP_FW_FAIL) {
+- /*If DSP FW fail, kcontrol won't be created */
+- tasdevice_config_info_remove(tas_priv);
+- tasdevice_dsp_remove(tas_priv);
+- }
+ mutex_unlock(&tas_priv->codec_lock);
+ if (fmw)
+ release_firmware(fmw);
+--
+2.43.0
+
--- /dev/null
+From 33071422714a4c9587753b0ccc130ca59323bf42 Mon Sep 17 00:00:00 2001
+From: Gergo Koteles <soyer@irl.hu>
+Date: Mon, 11 Dec 2023 00:37:33 +0100
+Subject: ALSA: hda/tas2781: handle missing EFI calibration data
+
+From: Gergo Koteles <soyer@irl.hu>
+
+commit 33071422714a4c9587753b0ccc130ca59323bf42 upstream.
+
+The code does not properly check whether the calibration variable is
+available in the EFI. If it is not available, it causes a NULL pointer
+dereference.
+
+Check the return value of the first get_variable call also.
+
+BUG: kernel NULL pointer dereference, address: 0000000000000000
+Call Trace:
+ <TASK>
+ ? __die+0x23/0x70
+ ? page_fault_oops+0x171/0x4e0
+ ? srso_alias_return_thunk+0x5/0x7f
+ ? schedule+0x5e/0xd0
+ ? exc_page_fault+0x7f/0x180
+ ? asm_exc_page_fault+0x26/0x30
+ ? crc32_body+0x2c/0x120
+ ? tas2781_save_calibration+0xe4/0x220 [snd_hda_scodec_tas2781_i2c]
+ tasdev_fw_ready+0x1af/0x280 [snd_hda_scodec_tas2781_i2c]
+ request_firmware_work_func+0x59/0xa0
+
+Fixes: 5be27f1e3ec9 ("ALSA: hda/tas2781: Add tas2781 HDA driver")
+CC: stable@vger.kernel.org
+Signed-off-by: Gergo Koteles <soyer@irl.hu>
+Link: https://lore.kernel.org/r/f1f6583bda918f78556f67d522ca7b3b91cebbd5.1702251102.git.soyer@irl.hu
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/hda/tas2781_hda_i2c.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/sound/pci/hda/tas2781_hda_i2c.c
++++ b/sound/pci/hda/tas2781_hda_i2c.c
+@@ -455,9 +455,9 @@ static int tas2781_save_calibration(stru
+ status = efi.get_variable(efi_name, &efi_guid, &attr,
+ &tas_priv->cali_data.total_sz,
+ tas_priv->cali_data.data);
+- if (status != EFI_SUCCESS)
+- return -EINVAL;
+ }
++ if (status != EFI_SUCCESS)
++ return -EINVAL;
+
+ tmp_val = (unsigned int *)tas_priv->cali_data.data;
+
--- /dev/null
+From 75a25d31b80770485641ad2789a854955f5c1e40 Mon Sep 17 00:00:00 2001
+From: Gergo Koteles <soyer@irl.hu>
+Date: Sat, 9 Dec 2023 22:18:29 +0100
+Subject: ALSA: hda/tas2781: leave hda_component in usable state
+
+From: Gergo Koteles <soyer@irl.hu>
+
+commit 75a25d31b80770485641ad2789a854955f5c1e40 upstream.
+
+Unloading then loading the module causes a NULL ponter dereference.
+
+The hda_unbind zeroes the hda_component, later the hda_bind tries
+to dereference the codec field.
+
+The hda_component is only initialized once by tas2781_generic_fixup.
+
+Set only previously modified fields to NULL.
+
+BUG: kernel NULL pointer dereference, address: 0000000000000322
+Call Trace:
+ <TASK>
+ ? __die+0x23/0x70
+ ? page_fault_oops+0x171/0x4e0
+ ? exc_page_fault+0x7f/0x180
+ ? asm_exc_page_fault+0x26/0x30
+ ? tas2781_hda_bind+0x59/0x140 [snd_hda_scodec_tas2781_i2c]
+ component_bind_all+0xf3/0x240
+ try_to_bring_up_aggregate_device+0x1c3/0x270
+ __component_add+0xbc/0x1a0
+ tas2781_hda_i2c_probe+0x289/0x3a0 [snd_hda_scodec_tas2781_i2c]
+ i2c_device_probe+0x136/0x2e0
+
+Fixes: 5be27f1e3ec9 ("ALSA: hda/tas2781: Add tas2781 HDA driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Gergo Koteles <soyer@irl.hu>
+Link: https://lore.kernel.org/r/8b8ed2bd5f75fbb32e354a3226c2f966fa85b46b.1702156522.git.soyer@irl.hu
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/hda/tas2781_hda_i2c.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c
+index fb802802939e..b42837105c22 100644
+--- a/sound/pci/hda/tas2781_hda_i2c.c
++++ b/sound/pci/hda/tas2781_hda_i2c.c
+@@ -612,9 +612,13 @@ static void tas2781_hda_unbind(struct device *dev,
+ {
+ struct tasdevice_priv *tas_priv = dev_get_drvdata(dev);
+ struct hda_component *comps = master_data;
++ comps = &comps[tas_priv->index];
+
+- if (comps[tas_priv->index].dev == dev)
+- memset(&comps[tas_priv->index], 0, sizeof(*comps));
++ if (comps->dev == dev) {
++ comps->dev = NULL;
++ memset(comps->name, 0, sizeof(comps->name));
++ comps->playback_hook = NULL;
++ }
+
+ tasdevice_config_info_remove(tas_priv);
+ tasdevice_dsp_remove(tas_priv);
+--
+2.43.0
+
--- /dev/null
+From 315deab289924c83ab1ded50022e8db95d6e428b Mon Sep 17 00:00:00 2001
+From: Gergo Koteles <soyer@irl.hu>
+Date: Thu, 14 Dec 2023 00:49:20 +0100
+Subject: ALSA: hda/tas2781: reset the amp before component_add
+
+From: Gergo Koteles <soyer@irl.hu>
+
+commit 315deab289924c83ab1ded50022e8db95d6e428b upstream.
+
+Calling component_add starts loading the firmware, the callback function
+writes the program to the amplifiers. If the module resets the
+amplifiers after component_add, it happens that one of the amplifiers
+does not work because the reset and program writing are interleaving.
+
+Call tas2781_reset before component_add to ensure reliable
+initialization.
+
+Fixes: 5be27f1e3ec9 ("ALSA: hda/tas2781: Add tas2781 HDA driver")
+CC: stable@vger.kernel.org
+Signed-off-by: Gergo Koteles <soyer@irl.hu>
+Link: https://lore.kernel.org/r/4d23bf58558e23ee8097de01f70f1eb8d9de2d15.1702511246.git.soyer@irl.hu
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ sound/pci/hda/tas2781_hda_i2c.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c
+index c8ee5f809c38..63a90c7e8976 100644
+--- a/sound/pci/hda/tas2781_hda_i2c.c
++++ b/sound/pci/hda/tas2781_hda_i2c.c
+@@ -674,14 +674,14 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt)
+
+ pm_runtime_put_autosuspend(tas_priv->dev);
+
++ tas2781_reset(tas_priv);
++
+ ret = component_add(tas_priv->dev, &tas2781_hda_comp_ops);
+ if (ret) {
+ dev_err(tas_priv->dev, "Register component failed: %d\n", ret);
+ pm_runtime_disable(tas_priv->dev);
+- goto err;
+ }
+
+- tas2781_reset(tas_priv);
+ err:
+ if (ret)
+ tas2781_hda_remove(&clt->dev);
+--
+2.43.0
+
--- /dev/null
+From ae1914174a63a558113e80d24ccac2773f9f7b2b Mon Sep 17 00:00:00 2001
+From: Jens Axboe <axboe@kernel.dk>
+Date: Fri, 15 Dec 2023 13:40:57 -0700
+Subject: cred: get rid of CONFIG_DEBUG_CREDENTIALS
+
+From: Jens Axboe <axboe@kernel.dk>
+
+commit ae1914174a63a558113e80d24ccac2773f9f7b2b upstream.
+
+This code is rarely (never?) enabled by distros, and it hasn't caught
+anything in decades. Let's kill off this legacy debug code.
+
+Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/powerpc/configs/skiroot_defconfig | 1
+ arch/s390/configs/debug_defconfig | 1
+ fs/nfsd/auth.c | 4
+ fs/nfsd/nfssvc.c | 1
+ fs/nfsd/vfs.c | 9 -
+ fs/open.c | 3
+ include/linux/cred.h | 50 ------
+ kernel/cred.c | 232 ++----------------------------
+ kernel/exit.c | 3
+ lib/Kconfig.debug | 15 -
+ net/sunrpc/auth.c | 3
+ security/selinux/hooks.c | 6
+ tools/objtool/noreturns.h | 1
+ tools/testing/selftests/bpf/config.x86_64 | 1
+ tools/testing/selftests/hid/config.common | 1
+ 15 files changed, 18 insertions(+), 313 deletions(-)
+
+--- a/arch/powerpc/configs/skiroot_defconfig
++++ b/arch/powerpc/configs/skiroot_defconfig
+@@ -301,7 +301,6 @@ CONFIG_WQ_WATCHDOG=y
+ CONFIG_DEBUG_SG=y
+ CONFIG_DEBUG_NOTIFIERS=y
+ CONFIG_BUG_ON_DATA_CORRUPTION=y
+-CONFIG_DEBUG_CREDENTIALS=y
+ # CONFIG_FTRACE is not set
+ CONFIG_XMON=y
+ # CONFIG_RUNTIME_TESTING_MENU is not set
+--- a/arch/s390/configs/debug_defconfig
++++ b/arch/s390/configs/debug_defconfig
+@@ -834,7 +834,6 @@ CONFIG_DEBUG_IRQFLAGS=y
+ CONFIG_DEBUG_LIST=y
+ CONFIG_DEBUG_SG=y
+ CONFIG_DEBUG_NOTIFIERS=y
+-CONFIG_DEBUG_CREDENTIALS=y
+ CONFIG_RCU_TORTURE_TEST=m
+ CONFIG_RCU_REF_SCALE_TEST=m
+ CONFIG_RCU_CPU_STALL_TIMEOUT=300
+--- a/fs/nfsd/auth.c
++++ b/fs/nfsd/auth.c
+@@ -26,8 +26,6 @@ int nfsd_setuser(struct svc_rqst *rqstp,
+ int i;
+ int flags = nfsexp_flags(rqstp, exp);
+
+- validate_process_creds();
+-
+ /* discard any old override before preparing the new set */
+ revert_creds(get_cred(current_real_cred()));
+ new = prepare_creds();
+@@ -81,10 +79,8 @@ int nfsd_setuser(struct svc_rqst *rqstp,
+ else
+ new->cap_effective = cap_raise_nfsd_set(new->cap_effective,
+ new->cap_permitted);
+- validate_process_creds();
+ put_cred(override_creds(new));
+ put_cred(new);
+- validate_process_creds();
+ return 0;
+
+ oom:
+--- a/fs/nfsd/nfssvc.c
++++ b/fs/nfsd/nfssvc.c
+@@ -962,7 +962,6 @@ nfsd(void *vrqstp)
+ rqstp->rq_server->sv_maxconn = nn->max_connections;
+
+ svc_recv(rqstp);
+- validate_process_creds();
+ }
+
+ atomic_dec(&nfsdstats.th_cnt);
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -884,7 +884,6 @@ nfsd_open(struct svc_rqst *rqstp, struct
+ int host_err;
+ bool retried = false;
+
+- validate_process_creds();
+ /*
+ * If we get here, then the client has already done an "open",
+ * and (hopefully) checked permission - so allow OWNER_OVERRIDE
+@@ -909,7 +908,6 @@ retry:
+ }
+ err = nfserrno(host_err);
+ }
+- validate_process_creds();
+ return err;
+ }
+
+@@ -926,12 +924,7 @@ int
+ nfsd_open_verified(struct svc_rqst *rqstp, struct svc_fh *fhp, int may_flags,
+ struct file **filp)
+ {
+- int err;
+-
+- validate_process_creds();
+- err = __nfsd_open(rqstp, fhp, S_IFREG, may_flags, filp);
+- validate_process_creds();
+- return err;
++ return __nfsd_open(rqstp, fhp, S_IFREG, may_flags, filp);
+ }
+
+ /*
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -1069,8 +1069,6 @@ struct file *dentry_open(const struct pa
+ int error;
+ struct file *f;
+
+- validate_creds(cred);
+-
+ /* We must always pass in a valid mount pointer. */
+ BUG_ON(!path->mnt);
+
+@@ -1109,7 +1107,6 @@ struct file *dentry_create(const struct
+ struct file *f;
+ int error;
+
+- validate_creds(cred);
+ f = alloc_empty_file(flags, cred);
+ if (IS_ERR(f))
+ return f;
+--- a/include/linux/cred.h
++++ b/include/linux/cred.h
+@@ -109,13 +109,6 @@ static inline int groups_search(const st
+ */
+ struct cred {
+ atomic_long_t usage;
+-#ifdef CONFIG_DEBUG_CREDENTIALS
+- atomic_t subscribers; /* number of processes subscribed */
+- void *put_addr;
+- unsigned magic;
+-#define CRED_MAGIC 0x43736564
+-#define CRED_MAGIC_DEAD 0x44656144
+-#endif
+ kuid_t uid; /* real UID of the task */
+ kgid_t gid; /* real GID of the task */
+ kuid_t suid; /* saved UID of the task */
+@@ -171,46 +164,6 @@ extern int cred_fscmp(const struct cred
+ extern void __init cred_init(void);
+ extern int set_cred_ucounts(struct cred *);
+
+-/*
+- * check for validity of credentials
+- */
+-#ifdef CONFIG_DEBUG_CREDENTIALS
+-extern void __noreturn __invalid_creds(const struct cred *, const char *, unsigned);
+-extern void __validate_process_creds(struct task_struct *,
+- const char *, unsigned);
+-
+-extern bool creds_are_invalid(const struct cred *cred);
+-
+-static inline void __validate_creds(const struct cred *cred,
+- const char *file, unsigned line)
+-{
+- if (unlikely(creds_are_invalid(cred)))
+- __invalid_creds(cred, file, line);
+-}
+-
+-#define validate_creds(cred) \
+-do { \
+- __validate_creds((cred), __FILE__, __LINE__); \
+-} while(0)
+-
+-#define validate_process_creds() \
+-do { \
+- __validate_process_creds(current, __FILE__, __LINE__); \
+-} while(0)
+-
+-extern void validate_creds_for_do_exit(struct task_struct *);
+-#else
+-static inline void validate_creds(const struct cred *cred)
+-{
+-}
+-static inline void validate_creds_for_do_exit(struct task_struct *tsk)
+-{
+-}
+-static inline void validate_process_creds(void)
+-{
+-}
+-#endif
+-
+ static inline bool cap_ambient_invariant_ok(const struct cred *cred)
+ {
+ return cap_issubset(cred->cap_ambient,
+@@ -249,7 +202,6 @@ static inline const struct cred *get_cre
+ struct cred *nonconst_cred = (struct cred *) cred;
+ if (!cred)
+ return cred;
+- validate_creds(cred);
+ nonconst_cred->non_rcu = 0;
+ return get_new_cred(nonconst_cred);
+ }
+@@ -261,7 +213,6 @@ static inline const struct cred *get_cre
+ return NULL;
+ if (!atomic_long_inc_not_zero(&nonconst_cred->usage))
+ return NULL;
+- validate_creds(cred);
+ nonconst_cred->non_rcu = 0;
+ return cred;
+ }
+@@ -282,7 +233,6 @@ static inline void put_cred(const struct
+ struct cred *cred = (struct cred *) _cred;
+
+ if (cred) {
+- validate_creds(cred);
+ if (atomic_long_dec_and_test(&(cred)->usage))
+ __put_cred(cred);
+ }
+--- a/kernel/cred.c
++++ b/kernel/cred.c
+@@ -43,10 +43,6 @@ static struct group_info init_groups = {
+ */
+ struct cred init_cred = {
+ .usage = ATOMIC_INIT(4),
+-#ifdef CONFIG_DEBUG_CREDENTIALS
+- .subscribers = ATOMIC_INIT(2),
+- .magic = CRED_MAGIC,
+-#endif
+ .uid = GLOBAL_ROOT_UID,
+ .gid = GLOBAL_ROOT_GID,
+ .suid = GLOBAL_ROOT_UID,
+@@ -66,31 +62,6 @@ struct cred init_cred = {
+ .ucounts = &init_ucounts,
+ };
+
+-static inline void set_cred_subscribers(struct cred *cred, int n)
+-{
+-#ifdef CONFIG_DEBUG_CREDENTIALS
+- atomic_set(&cred->subscribers, n);
+-#endif
+-}
+-
+-static inline int read_cred_subscribers(const struct cred *cred)
+-{
+-#ifdef CONFIG_DEBUG_CREDENTIALS
+- return atomic_read(&cred->subscribers);
+-#else
+- return 0;
+-#endif
+-}
+-
+-static inline void alter_cred_subscribers(const struct cred *_cred, int n)
+-{
+-#ifdef CONFIG_DEBUG_CREDENTIALS
+- struct cred *cred = (struct cred *) _cred;
+-
+- atomic_add(n, &cred->subscribers);
+-#endif
+-}
+-
+ /*
+ * The RCU callback to actually dispose of a set of credentials
+ */
+@@ -100,20 +71,9 @@ static void put_cred_rcu(struct rcu_head
+
+ kdebug("put_cred_rcu(%p)", cred);
+
+-#ifdef CONFIG_DEBUG_CREDENTIALS
+- if (cred->magic != CRED_MAGIC_DEAD ||
+- atomic_long_read(&cred->usage) != 0 ||
+- read_cred_subscribers(cred) != 0)
+- panic("CRED: put_cred_rcu() sees %p with"
+- " mag %x, put %p, usage %ld, subscr %d\n",
+- cred, cred->magic, cred->put_addr,
+- atomic_long_read(&cred->usage),
+- read_cred_subscribers(cred));
+-#else
+ if (atomic_long_read(&cred->usage) != 0)
+ panic("CRED: put_cred_rcu() sees %p with usage %ld\n",
+ cred, atomic_long_read(&cred->usage));
+-#endif
+
+ security_cred_free(cred);
+ key_put(cred->session_keyring);
+@@ -137,16 +97,10 @@ static void put_cred_rcu(struct rcu_head
+ */
+ void __put_cred(struct cred *cred)
+ {
+- kdebug("__put_cred(%p{%ld,%d})", cred,
+- atomic_long_read(&cred->usage),
+- read_cred_subscribers(cred));
++ kdebug("__put_cred(%p{%ld})", cred,
++ atomic_long_read(&cred->usage));
+
+ BUG_ON(atomic_long_read(&cred->usage) != 0);
+-#ifdef CONFIG_DEBUG_CREDENTIALS
+- BUG_ON(read_cred_subscribers(cred) != 0);
+- cred->magic = CRED_MAGIC_DEAD;
+- cred->put_addr = __builtin_return_address(0);
+-#endif
+ BUG_ON(cred == current->cred);
+ BUG_ON(cred == current->real_cred);
+
+@@ -164,20 +118,15 @@ void exit_creds(struct task_struct *tsk)
+ {
+ struct cred *cred;
+
+- kdebug("exit_creds(%u,%p,%p,{%ld,%d})", tsk->pid, tsk->real_cred, tsk->cred,
+- atomic_long_read(&tsk->cred->usage),
+- read_cred_subscribers(tsk->cred));
++ kdebug("exit_creds(%u,%p,%p,{%ld})", tsk->pid, tsk->real_cred, tsk->cred,
++ atomic_long_read(&tsk->cred->usage));
+
+ cred = (struct cred *) tsk->real_cred;
+ tsk->real_cred = NULL;
+- validate_creds(cred);
+- alter_cred_subscribers(cred, -1);
+ put_cred(cred);
+
+ cred = (struct cred *) tsk->cred;
+ tsk->cred = NULL;
+- validate_creds(cred);
+- alter_cred_subscribers(cred, -1);
+ put_cred(cred);
+
+ #ifdef CONFIG_KEYS_REQUEST_CACHE
+@@ -225,9 +174,6 @@ struct cred *cred_alloc_blank(void)
+ return NULL;
+
+ atomic_long_set(&new->usage, 1);
+-#ifdef CONFIG_DEBUG_CREDENTIALS
+- new->magic = CRED_MAGIC;
+-#endif
+ if (security_cred_alloc_blank(new, GFP_KERNEL_ACCOUNT) < 0)
+ goto error;
+
+@@ -258,8 +204,6 @@ struct cred *prepare_creds(void)
+ const struct cred *old;
+ struct cred *new;
+
+- validate_process_creds();
+-
+ new = kmem_cache_alloc(cred_jar, GFP_KERNEL);
+ if (!new)
+ return NULL;
+@@ -271,7 +215,6 @@ struct cred *prepare_creds(void)
+
+ new->non_rcu = 0;
+ atomic_long_set(&new->usage, 1);
+- set_cred_subscribers(new, 0);
+ get_group_info(new->group_info);
+ get_uid(new->user);
+ get_user_ns(new->user_ns);
+@@ -294,7 +237,6 @@ struct cred *prepare_creds(void)
+ if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0)
+ goto error;
+
+- validate_creds(new);
+ return new;
+
+ error:
+@@ -357,10 +299,8 @@ int copy_creds(struct task_struct *p, un
+ ) {
+ p->real_cred = get_cred(p->cred);
+ get_cred(p->cred);
+- alter_cred_subscribers(p->cred, 2);
+- kdebug("share_creds(%p{%ld,%d})",
+- p->cred, atomic_long_read(&p->cred->usage),
+- read_cred_subscribers(p->cred));
++ kdebug("share_creds(%p{%ld})",
++ p->cred, atomic_long_read(&p->cred->usage));
+ inc_rlimit_ucounts(task_ucounts(p), UCOUNT_RLIMIT_NPROC, 1);
+ return 0;
+ }
+@@ -399,8 +339,6 @@ int copy_creds(struct task_struct *p, un
+
+ p->cred = p->real_cred = get_cred(new);
+ inc_rlimit_ucounts(task_ucounts(p), UCOUNT_RLIMIT_NPROC, 1);
+- alter_cred_subscribers(new, 2);
+- validate_creds(new);
+ return 0;
+
+ error_put:
+@@ -452,16 +390,10 @@ int commit_creds(struct cred *new)
+ struct task_struct *task = current;
+ const struct cred *old = task->real_cred;
+
+- kdebug("commit_creds(%p{%ld,%d})", new,
+- atomic_long_read(&new->usage),
+- read_cred_subscribers(new));
++ kdebug("commit_creds(%p{%ld})", new,
++ atomic_long_read(&new->usage));
+
+ BUG_ON(task->cred != old);
+-#ifdef CONFIG_DEBUG_CREDENTIALS
+- BUG_ON(read_cred_subscribers(old) < 2);
+- validate_creds(old);
+- validate_creds(new);
+-#endif
+ BUG_ON(atomic_long_read(&new->usage) < 1);
+
+ get_cred(new); /* we will require a ref for the subj creds too */
+@@ -497,14 +429,12 @@ int commit_creds(struct cred *new)
+ * RLIMIT_NPROC limits on user->processes have already been checked
+ * in set_user().
+ */
+- alter_cred_subscribers(new, 2);
+ if (new->user != old->user || new->user_ns != old->user_ns)
+ inc_rlimit_ucounts(new->ucounts, UCOUNT_RLIMIT_NPROC, 1);
+ rcu_assign_pointer(task->real_cred, new);
+ rcu_assign_pointer(task->cred, new);
+ if (new->user != old->user || new->user_ns != old->user_ns)
+ dec_rlimit_ucounts(old->ucounts, UCOUNT_RLIMIT_NPROC, 1);
+- alter_cred_subscribers(old, -2);
+
+ /* send notifications */
+ if (!uid_eq(new->uid, old->uid) ||
+@@ -535,13 +465,9 @@ EXPORT_SYMBOL(commit_creds);
+ */
+ void abort_creds(struct cred *new)
+ {
+- kdebug("abort_creds(%p{%ld,%d})", new,
+- atomic_long_read(&new->usage),
+- read_cred_subscribers(new));
++ kdebug("abort_creds(%p{%ld})", new,
++ atomic_long_read(&new->usage));
+
+-#ifdef CONFIG_DEBUG_CREDENTIALS
+- BUG_ON(read_cred_subscribers(new) != 0);
+-#endif
+ BUG_ON(atomic_long_read(&new->usage) < 1);
+ put_cred(new);
+ }
+@@ -558,12 +484,8 @@ const struct cred *override_creds(const
+ {
+ const struct cred *old = current->cred;
+
+- kdebug("override_creds(%p{%ld,%d})", new,
+- atomic_long_read(&new->usage),
+- read_cred_subscribers(new));
+-
+- validate_creds(old);
+- validate_creds(new);
++ kdebug("override_creds(%p{%ld})", new,
++ atomic_long_read(&new->usage));
+
+ /*
+ * NOTE! This uses 'get_new_cred()' rather than 'get_cred()'.
+@@ -572,18 +494,12 @@ const struct cred *override_creds(const
+ * we are only installing the cred into the thread-synchronous
+ * '->cred' pointer, not the '->real_cred' pointer that is
+ * visible to other threads under RCU.
+- *
+- * Also note that we did validate_creds() manually, not depending
+- * on the validation in 'get_cred()'.
+ */
+ get_new_cred((struct cred *)new);
+- alter_cred_subscribers(new, 1);
+ rcu_assign_pointer(current->cred, new);
+- alter_cred_subscribers(old, -1);
+
+- kdebug("override_creds() = %p{%ld,%d}", old,
+- atomic_long_read(&old->usage),
+- read_cred_subscribers(old));
++ kdebug("override_creds() = %p{%ld}", old,
++ atomic_long_read(&old->usage));
+ return old;
+ }
+ EXPORT_SYMBOL(override_creds);
+@@ -599,15 +515,10 @@ void revert_creds(const struct cred *old
+ {
+ const struct cred *override = current->cred;
+
+- kdebug("revert_creds(%p{%ld,%d})", old,
+- atomic_long_read(&old->usage),
+- read_cred_subscribers(old));
+-
+- validate_creds(old);
+- validate_creds(override);
+- alter_cred_subscribers(old, 1);
++ kdebug("revert_creds(%p{%ld})", old,
++ atomic_long_read(&old->usage));
++
+ rcu_assign_pointer(current->cred, old);
+- alter_cred_subscribers(override, -1);
+ put_cred(override);
+ }
+ EXPORT_SYMBOL(revert_creds);
+@@ -727,12 +638,10 @@ struct cred *prepare_kernel_cred(struct
+ kdebug("prepare_kernel_cred() alloc %p", new);
+
+ old = get_task_cred(daemon);
+- validate_creds(old);
+
+ *new = *old;
+ new->non_rcu = 0;
+ atomic_long_set(&new->usage, 1);
+- set_cred_subscribers(new, 0);
+ get_uid(new->user);
+ get_user_ns(new->user_ns);
+ get_group_info(new->group_info);
+@@ -756,7 +665,6 @@ struct cred *prepare_kernel_cred(struct
+ goto error;
+
+ put_cred(old);
+- validate_creds(new);
+ return new;
+
+ error:
+@@ -821,109 +729,3 @@ int set_create_files_as(struct cred *new
+ return security_kernel_create_files_as(new, inode);
+ }
+ EXPORT_SYMBOL(set_create_files_as);
+-
+-#ifdef CONFIG_DEBUG_CREDENTIALS
+-
+-bool creds_are_invalid(const struct cred *cred)
+-{
+- if (cred->magic != CRED_MAGIC)
+- return true;
+- return false;
+-}
+-EXPORT_SYMBOL(creds_are_invalid);
+-
+-/*
+- * dump invalid credentials
+- */
+-static void dump_invalid_creds(const struct cred *cred, const char *label,
+- const struct task_struct *tsk)
+-{
+- pr_err("%s credentials: %p %s%s%s\n",
+- label, cred,
+- cred == &init_cred ? "[init]" : "",
+- cred == tsk->real_cred ? "[real]" : "",
+- cred == tsk->cred ? "[eff]" : "");
+- pr_err("->magic=%x, put_addr=%p\n",
+- cred->magic, cred->put_addr);
+- pr_err("->usage=%ld, subscr=%d\n",
+- atomic_long_read(&cred->usage),
+- read_cred_subscribers(cred));
+- pr_err("->*uid = { %d,%d,%d,%d }\n",
+- from_kuid_munged(&init_user_ns, cred->uid),
+- from_kuid_munged(&init_user_ns, cred->euid),
+- from_kuid_munged(&init_user_ns, cred->suid),
+- from_kuid_munged(&init_user_ns, cred->fsuid));
+- pr_err("->*gid = { %d,%d,%d,%d }\n",
+- from_kgid_munged(&init_user_ns, cred->gid),
+- from_kgid_munged(&init_user_ns, cred->egid),
+- from_kgid_munged(&init_user_ns, cred->sgid),
+- from_kgid_munged(&init_user_ns, cred->fsgid));
+-#ifdef CONFIG_SECURITY
+- pr_err("->security is %p\n", cred->security);
+- if ((unsigned long) cred->security >= PAGE_SIZE &&
+- (((unsigned long) cred->security & 0xffffff00) !=
+- (POISON_FREE << 24 | POISON_FREE << 16 | POISON_FREE << 8)))
+- pr_err("->security {%x, %x}\n",
+- ((u32*)cred->security)[0],
+- ((u32*)cred->security)[1]);
+-#endif
+-}
+-
+-/*
+- * report use of invalid credentials
+- */
+-void __noreturn __invalid_creds(const struct cred *cred, const char *file, unsigned line)
+-{
+- pr_err("Invalid credentials\n");
+- pr_err("At %s:%u\n", file, line);
+- dump_invalid_creds(cred, "Specified", current);
+- BUG();
+-}
+-EXPORT_SYMBOL(__invalid_creds);
+-
+-/*
+- * check the credentials on a process
+- */
+-void __validate_process_creds(struct task_struct *tsk,
+- const char *file, unsigned line)
+-{
+- if (tsk->cred == tsk->real_cred) {
+- if (unlikely(read_cred_subscribers(tsk->cred) < 2 ||
+- creds_are_invalid(tsk->cred)))
+- goto invalid_creds;
+- } else {
+- if (unlikely(read_cred_subscribers(tsk->real_cred) < 1 ||
+- read_cred_subscribers(tsk->cred) < 1 ||
+- creds_are_invalid(tsk->real_cred) ||
+- creds_are_invalid(tsk->cred)))
+- goto invalid_creds;
+- }
+- return;
+-
+-invalid_creds:
+- pr_err("Invalid process credentials\n");
+- pr_err("At %s:%u\n", file, line);
+-
+- dump_invalid_creds(tsk->real_cred, "Real", tsk);
+- if (tsk->cred != tsk->real_cred)
+- dump_invalid_creds(tsk->cred, "Effective", tsk);
+- else
+- pr_err("Effective creds == Real creds\n");
+- BUG();
+-}
+-EXPORT_SYMBOL(__validate_process_creds);
+-
+-/*
+- * check creds for do_exit()
+- */
+-void validate_creds_for_do_exit(struct task_struct *tsk)
+-{
+- kdebug("validate_creds_for_do_exit(%p,%p{%ld,%d})",
+- tsk->real_cred, tsk->cred,
+- atomic_long_read(&tsk->cred->usage),
+- read_cred_subscribers(tsk->cred));
+-
+- __validate_process_creds(tsk, __FILE__, __LINE__);
+-}
+-
+-#endif /* CONFIG_DEBUG_CREDENTIALS */
+--- a/kernel/exit.c
++++ b/kernel/exit.c
+@@ -824,8 +824,6 @@ void __noreturn do_exit(long code)
+ ptrace_event(PTRACE_EVENT_EXIT, code);
+ user_events_exit(tsk);
+
+- validate_creds_for_do_exit(tsk);
+-
+ io_uring_files_cancel();
+ exit_signals(tsk); /* sets PF_EXITING */
+
+@@ -912,7 +910,6 @@ void __noreturn do_exit(long code)
+ if (tsk->task_frag.page)
+ put_page(tsk->task_frag.page);
+
+- validate_creds_for_do_exit(tsk);
+ exit_task_stack_account(tsk);
+
+ check_stack_usage();
+--- a/lib/Kconfig.debug
++++ b/lib/Kconfig.debug
+@@ -1730,21 +1730,6 @@ config DEBUG_MAPLE_TREE
+
+ endmenu
+
+-config DEBUG_CREDENTIALS
+- bool "Debug credential management"
+- depends on DEBUG_KERNEL
+- help
+- Enable this to turn on some debug checking for credential
+- management. The additional code keeps track of the number of
+- pointers from task_structs to any given cred struct, and checks to
+- see that this number never exceeds the usage count of the cred
+- struct.
+-
+- Furthermore, if SELinux is enabled, this also checks that the
+- security pointer in the cred struct is never seen to be invalid.
+-
+- If unsure, say N.
+-
+ source "kernel/rcu/Kconfig.debug"
+
+ config DEBUG_WQ_FORCE_RR_CPU
+--- a/net/sunrpc/auth.c
++++ b/net/sunrpc/auth.c
+@@ -40,9 +40,6 @@ static unsigned long number_cred_unused;
+
+ static struct cred machine_cred = {
+ .usage = ATOMIC_INIT(1),
+-#ifdef CONFIG_DEBUG_CREDENTIALS
+- .magic = CRED_MAGIC,
+-#endif
+ };
+
+ /*
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -1660,8 +1660,6 @@ static int inode_has_perm(const struct c
+ struct inode_security_struct *isec;
+ u32 sid;
+
+- validate_creds(cred);
+-
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
+@@ -3056,8 +3054,6 @@ static int selinux_inode_follow_link(str
+ struct inode_security_struct *isec;
+ u32 sid;
+
+- validate_creds(cred);
+-
+ ad.type = LSM_AUDIT_DATA_DENTRY;
+ ad.u.dentry = dentry;
+ sid = cred_sid(cred);
+@@ -3101,8 +3097,6 @@ static int selinux_inode_permission(stru
+ if (!mask)
+ return 0;
+
+- validate_creds(cred);
+-
+ if (unlikely(IS_PRIVATE(inode)))
+ return 0;
+
+--- a/tools/objtool/noreturns.h
++++ b/tools/objtool/noreturns.h
+@@ -6,7 +6,6 @@
+ *
+ * Yes, this is unfortunate. A better solution is in the works.
+ */
+-NORETURN(__invalid_creds)
+ NORETURN(__kunit_abort)
+ NORETURN(__module_put_and_kthread_exit)
+ NORETURN(__reiserfs_panic)
+--- a/tools/testing/selftests/bpf/config.x86_64
++++ b/tools/testing/selftests/bpf/config.x86_64
+@@ -50,7 +50,6 @@ CONFIG_CRYPTO_SEQIV=y
+ CONFIG_CRYPTO_XXHASH=y
+ CONFIG_DCB=y
+ CONFIG_DEBUG_ATOMIC_SLEEP=y
+-CONFIG_DEBUG_CREDENTIALS=y
+ CONFIG_DEBUG_INFO_BTF=y
+ CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
+ CONFIG_DEBUG_MEMORY_INIT=y
+--- a/tools/testing/selftests/hid/config.common
++++ b/tools/testing/selftests/hid/config.common
+@@ -46,7 +46,6 @@ CONFIG_CRYPTO_SEQIV=y
+ CONFIG_CRYPTO_XXHASH=y
+ CONFIG_DCB=y
+ CONFIG_DEBUG_ATOMIC_SLEEP=y
+-CONFIG_DEBUG_CREDENTIALS=y
+ CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
+ CONFIG_DEBUG_MEMORY_INIT=y
+ CONFIG_DEFAULT_FQ_CODEL=y
--- /dev/null
+From f8fa5d76925991976b3e7076f9d1052515ec1fca Mon Sep 17 00:00:00 2001
+From: Jens Axboe <axboe@kernel.dk>
+Date: Fri, 15 Dec 2023 13:24:10 -0700
+Subject: cred: switch to using atomic_long_t
+
+From: Jens Axboe <axboe@kernel.dk>
+
+commit f8fa5d76925991976b3e7076f9d1052515ec1fca upstream.
+
+There are multiple ways to grab references to credentials, and the only
+protection we have against overflowing it is the memory required to do
+so.
+
+With memory sizes only moving in one direction, let's bump the reference
+count to 64-bit and move it outside the realm of feasibly overflowing.
+
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/cred.h | 8 +++---
+ kernel/cred.c | 64 +++++++++++++++++++++++++--------------------------
+ 2 files changed, 36 insertions(+), 36 deletions(-)
+
+--- a/include/linux/cred.h
++++ b/include/linux/cred.h
+@@ -108,7 +108,7 @@ static inline int groups_search(const st
+ * same context as task->real_cred.
+ */
+ struct cred {
+- atomic_t usage;
++ atomic_long_t usage;
+ #ifdef CONFIG_DEBUG_CREDENTIALS
+ atomic_t subscribers; /* number of processes subscribed */
+ void *put_addr;
+@@ -227,7 +227,7 @@ static inline bool cap_ambient_invariant
+ */
+ static inline struct cred *get_new_cred(struct cred *cred)
+ {
+- atomic_inc(&cred->usage);
++ atomic_long_inc(&cred->usage);
+ return cred;
+ }
+
+@@ -259,7 +259,7 @@ static inline const struct cred *get_cre
+ struct cred *nonconst_cred = (struct cred *) cred;
+ if (!cred)
+ return NULL;
+- if (!atomic_inc_not_zero(&nonconst_cred->usage))
++ if (!atomic_long_inc_not_zero(&nonconst_cred->usage))
+ return NULL;
+ validate_creds(cred);
+ nonconst_cred->non_rcu = 0;
+@@ -283,7 +283,7 @@ static inline void put_cred(const struct
+
+ if (cred) {
+ validate_creds(cred);
+- if (atomic_dec_and_test(&(cred)->usage))
++ if (atomic_long_dec_and_test(&(cred)->usage))
+ __put_cred(cred);
+ }
+ }
+--- a/kernel/cred.c
++++ b/kernel/cred.c
+@@ -102,17 +102,17 @@ static void put_cred_rcu(struct rcu_head
+
+ #ifdef CONFIG_DEBUG_CREDENTIALS
+ if (cred->magic != CRED_MAGIC_DEAD ||
+- atomic_read(&cred->usage) != 0 ||
++ atomic_long_read(&cred->usage) != 0 ||
+ read_cred_subscribers(cred) != 0)
+ panic("CRED: put_cred_rcu() sees %p with"
+- " mag %x, put %p, usage %d, subscr %d\n",
++ " mag %x, put %p, usage %ld, subscr %d\n",
+ cred, cred->magic, cred->put_addr,
+- atomic_read(&cred->usage),
++ atomic_long_read(&cred->usage),
+ read_cred_subscribers(cred));
+ #else
+- if (atomic_read(&cred->usage) != 0)
+- panic("CRED: put_cred_rcu() sees %p with usage %d\n",
+- cred, atomic_read(&cred->usage));
++ if (atomic_long_read(&cred->usage) != 0)
++ panic("CRED: put_cred_rcu() sees %p with usage %ld\n",
++ cred, atomic_long_read(&cred->usage));
+ #endif
+
+ security_cred_free(cred);
+@@ -137,11 +137,11 @@ static void put_cred_rcu(struct rcu_head
+ */
+ void __put_cred(struct cred *cred)
+ {
+- kdebug("__put_cred(%p{%d,%d})", cred,
+- atomic_read(&cred->usage),
++ kdebug("__put_cred(%p{%ld,%d})", cred,
++ atomic_long_read(&cred->usage),
+ read_cred_subscribers(cred));
+
+- BUG_ON(atomic_read(&cred->usage) != 0);
++ BUG_ON(atomic_long_read(&cred->usage) != 0);
+ #ifdef CONFIG_DEBUG_CREDENTIALS
+ BUG_ON(read_cred_subscribers(cred) != 0);
+ cred->magic = CRED_MAGIC_DEAD;
+@@ -164,8 +164,8 @@ void exit_creds(struct task_struct *tsk)
+ {
+ struct cred *cred;
+
+- kdebug("exit_creds(%u,%p,%p,{%d,%d})", tsk->pid, tsk->real_cred, tsk->cred,
+- atomic_read(&tsk->cred->usage),
++ kdebug("exit_creds(%u,%p,%p,{%ld,%d})", tsk->pid, tsk->real_cred, tsk->cred,
++ atomic_long_read(&tsk->cred->usage),
+ read_cred_subscribers(tsk->cred));
+
+ cred = (struct cred *) tsk->real_cred;
+@@ -224,7 +224,7 @@ struct cred *cred_alloc_blank(void)
+ if (!new)
+ return NULL;
+
+- atomic_set(&new->usage, 1);
++ atomic_long_set(&new->usage, 1);
+ #ifdef CONFIG_DEBUG_CREDENTIALS
+ new->magic = CRED_MAGIC;
+ #endif
+@@ -270,7 +270,7 @@ struct cred *prepare_creds(void)
+ memcpy(new, old, sizeof(struct cred));
+
+ new->non_rcu = 0;
+- atomic_set(&new->usage, 1);
++ atomic_long_set(&new->usage, 1);
+ set_cred_subscribers(new, 0);
+ get_group_info(new->group_info);
+ get_uid(new->user);
+@@ -358,8 +358,8 @@ int copy_creds(struct task_struct *p, un
+ p->real_cred = get_cred(p->cred);
+ get_cred(p->cred);
+ alter_cred_subscribers(p->cred, 2);
+- kdebug("share_creds(%p{%d,%d})",
+- p->cred, atomic_read(&p->cred->usage),
++ kdebug("share_creds(%p{%ld,%d})",
++ p->cred, atomic_long_read(&p->cred->usage),
+ read_cred_subscribers(p->cred));
+ inc_rlimit_ucounts(task_ucounts(p), UCOUNT_RLIMIT_NPROC, 1);
+ return 0;
+@@ -452,8 +452,8 @@ int commit_creds(struct cred *new)
+ struct task_struct *task = current;
+ const struct cred *old = task->real_cred;
+
+- kdebug("commit_creds(%p{%d,%d})", new,
+- atomic_read(&new->usage),
++ kdebug("commit_creds(%p{%ld,%d})", new,
++ atomic_long_read(&new->usage),
+ read_cred_subscribers(new));
+
+ BUG_ON(task->cred != old);
+@@ -462,7 +462,7 @@ int commit_creds(struct cred *new)
+ validate_creds(old);
+ validate_creds(new);
+ #endif
+- BUG_ON(atomic_read(&new->usage) < 1);
++ BUG_ON(atomic_long_read(&new->usage) < 1);
+
+ get_cred(new); /* we will require a ref for the subj creds too */
+
+@@ -535,14 +535,14 @@ EXPORT_SYMBOL(commit_creds);
+ */
+ void abort_creds(struct cred *new)
+ {
+- kdebug("abort_creds(%p{%d,%d})", new,
+- atomic_read(&new->usage),
++ kdebug("abort_creds(%p{%ld,%d})", new,
++ atomic_long_read(&new->usage),
+ read_cred_subscribers(new));
+
+ #ifdef CONFIG_DEBUG_CREDENTIALS
+ BUG_ON(read_cred_subscribers(new) != 0);
+ #endif
+- BUG_ON(atomic_read(&new->usage) < 1);
++ BUG_ON(atomic_long_read(&new->usage) < 1);
+ put_cred(new);
+ }
+ EXPORT_SYMBOL(abort_creds);
+@@ -558,8 +558,8 @@ const struct cred *override_creds(const
+ {
+ const struct cred *old = current->cred;
+
+- kdebug("override_creds(%p{%d,%d})", new,
+- atomic_read(&new->usage),
++ kdebug("override_creds(%p{%ld,%d})", new,
++ atomic_long_read(&new->usage),
+ read_cred_subscribers(new));
+
+ validate_creds(old);
+@@ -581,8 +581,8 @@ const struct cred *override_creds(const
+ rcu_assign_pointer(current->cred, new);
+ alter_cred_subscribers(old, -1);
+
+- kdebug("override_creds() = %p{%d,%d}", old,
+- atomic_read(&old->usage),
++ kdebug("override_creds() = %p{%ld,%d}", old,
++ atomic_long_read(&old->usage),
+ read_cred_subscribers(old));
+ return old;
+ }
+@@ -599,8 +599,8 @@ void revert_creds(const struct cred *old
+ {
+ const struct cred *override = current->cred;
+
+- kdebug("revert_creds(%p{%d,%d})", old,
+- atomic_read(&old->usage),
++ kdebug("revert_creds(%p{%ld,%d})", old,
++ atomic_long_read(&old->usage),
+ read_cred_subscribers(old));
+
+ validate_creds(old);
+@@ -731,7 +731,7 @@ struct cred *prepare_kernel_cred(struct
+
+ *new = *old;
+ new->non_rcu = 0;
+- atomic_set(&new->usage, 1);
++ atomic_long_set(&new->usage, 1);
+ set_cred_subscribers(new, 0);
+ get_uid(new->user);
+ get_user_ns(new->user_ns);
+@@ -845,8 +845,8 @@ static void dump_invalid_creds(const str
+ cred == tsk->cred ? "[eff]" : "");
+ pr_err("->magic=%x, put_addr=%p\n",
+ cred->magic, cred->put_addr);
+- pr_err("->usage=%d, subscr=%d\n",
+- atomic_read(&cred->usage),
++ pr_err("->usage=%ld, subscr=%d\n",
++ atomic_long_read(&cred->usage),
+ read_cred_subscribers(cred));
+ pr_err("->*uid = { %d,%d,%d,%d }\n",
+ from_kuid_munged(&init_user_ns, cred->uid),
+@@ -918,9 +918,9 @@ EXPORT_SYMBOL(__validate_process_creds);
+ */
+ void validate_creds_for_do_exit(struct task_struct *tsk)
+ {
+- kdebug("validate_creds_for_do_exit(%p,%p{%d,%d})",
++ kdebug("validate_creds_for_do_exit(%p,%p{%ld,%d})",
+ tsk->real_cred, tsk->cred,
+- atomic_read(&tsk->cred->usage),
++ atomic_long_read(&tsk->cred->usage),
+ read_cred_subscribers(tsk->cred));
+
+ __validate_process_creds(tsk, __FILE__, __LINE__);
--- /dev/null
+From 7f8ed28d1401320bcb02dda81b3c23ab2dc5a6d8 Mon Sep 17 00:00:00 2001
+From: Hangyu Hua <hbh25y@gmail.com>
+Date: Thu, 16 Nov 2023 15:57:26 +0800
+Subject: fuse: dax: set fc->dax to NULL in fuse_dax_conn_free()
+
+From: Hangyu Hua <hbh25y@gmail.com>
+
+commit 7f8ed28d1401320bcb02dda81b3c23ab2dc5a6d8 upstream.
+
+fuse_dax_conn_free() will be called when fuse_fill_super_common() fails
+after fuse_dax_conn_alloc(). Then deactivate_locked_super() in
+virtio_fs_get_tree() will call virtio_kill_sb() to release the discarded
+superblock. This will call fuse_dax_conn_free() again in fuse_conn_put(),
+resulting in a possible double free.
+
+Fixes: 1dd539577c42 ("virtiofs: add a mount option to enable dax")
+Signed-off-by: Hangyu Hua <hbh25y@gmail.com>
+Acked-by: Vivek Goyal <vgoyal@redhat.com>
+Reviewed-by: Jingbo Xu <jefflexu@linux.alibaba.com>
+Cc: <stable@vger.kernel.org> # v5.10
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fuse/dax.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/fuse/dax.c
++++ b/fs/fuse/dax.c
+@@ -1222,6 +1222,7 @@ void fuse_dax_conn_free(struct fuse_conn
+ if (fc->dax) {
+ fuse_free_dax_mem_ranges(&fc->dax->free_ranges);
+ kfree(fc->dax);
++ fc->dax = NULL;
+ }
+ }
+
--- /dev/null
+From 3f29f1c336c0e8a4bec52f1e5217f88835553e5b Mon Sep 17 00:00:00 2001
+From: Amir Goldstein <amir73il@gmail.com>
+Date: Sun, 3 Dec 2023 09:42:33 +0200
+Subject: fuse: disable FOPEN_PARALLEL_DIRECT_WRITES with FUSE_DIRECT_IO_ALLOW_MMAP
+
+From: Amir Goldstein <amir73il@gmail.com>
+
+commit 3f29f1c336c0e8a4bec52f1e5217f88835553e5b upstream.
+
+The new fuse init flag FUSE_DIRECT_IO_ALLOW_MMAP breaks assumptions made by
+FOPEN_PARALLEL_DIRECT_WRITES and causes test generic/095 to hit
+BUG_ON(fi->writectr < 0) assertions in fuse_set_nowrite():
+
+generic/095 5s ...
+ kernel BUG at fs/fuse/dir.c:1756!
+...
+ ? fuse_set_nowrite+0x3d/0xdd
+ ? do_raw_spin_unlock+0x88/0x8f
+ ? _raw_spin_unlock+0x2d/0x43
+ ? fuse_range_is_writeback+0x71/0x84
+ fuse_sync_writes+0xf/0x19
+ fuse_direct_io+0x167/0x5bd
+ fuse_direct_write_iter+0xf0/0x146
+
+Auto disable FOPEN_PARALLEL_DIRECT_WRITES when server negotiated
+FUSE_DIRECT_IO_ALLOW_MMAP.
+
+Fixes: e78662e818f9 ("fuse: add a new fuse init flag to relax restrictions in no cache mode")
+Cc: <stable@vger.kernel.org> # v6.6
+Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fuse/file.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/fs/fuse/file.c b/fs/fuse/file.c
+index 89e870d1a526..a660f1f21540 100644
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -1574,6 +1574,7 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
+ ssize_t res;
+ bool exclusive_lock =
+ !(ff->open_flags & FOPEN_PARALLEL_DIRECT_WRITES) ||
++ get_fuse_conn(inode)->direct_io_allow_mmap ||
+ iocb->ki_flags & IOCB_APPEND ||
+ fuse_direct_write_extending_i_size(iocb, from);
+
+@@ -1581,6 +1582,7 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
+ * Take exclusive lock if
+ * - Parallel direct writes are disabled - a user space decision
+ * - Parallel direct writes are enabled and i_size is being extended.
++ * - Shared mmap on direct_io file is supported (FUSE_DIRECT_IO_ALLOW_MMAP).
+ * This might not be needed at all, but needs further investigation.
+ */
+ if (exclusive_lock)
+--
+2.43.0
+
--- /dev/null
+From c55e0a55b165202f18cbc4a20650d2e1becd5507 Mon Sep 17 00:00:00 2001
+From: Tyler Fanelli <tfanelli@redhat.com>
+Date: Tue, 19 Sep 2023 22:40:00 -0400
+Subject: fuse: Rename DIRECT_IO_RELAX to DIRECT_IO_ALLOW_MMAP
+
+From: Tyler Fanelli <tfanelli@redhat.com>
+
+commit c55e0a55b165202f18cbc4a20650d2e1becd5507 upstream.
+
+Although DIRECT_IO_RELAX's initial usage is to allow shared mmap, its
+description indicates a purpose of reducing memory footprint. This
+may imply that it could be further used to relax other DIRECT_IO
+operations in the future.
+
+Replace it with a flag DIRECT_IO_ALLOW_MMAP which does only one thing,
+allow shared mmap of DIRECT_IO files while still bypassing the cache
+on regular reads and writes.
+
+[Miklos] Also Keep DIRECT_IO_RELAX definition for backward compatibility.
+
+Signed-off-by: Tyler Fanelli <tfanelli@redhat.com>
+Fixes: e78662e818f9 ("fuse: add a new fuse init flag to relax restrictions in no cache mode")
+Cc: <stable@vger.kernel.org> # v6.6
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fuse/file.c | 6 +++---
+ fs/fuse/fuse_i.h | 4 ++--
+ fs/fuse/inode.c | 6 +++---
+ include/uapi/linux/fuse.h | 10 ++++++----
+ 4 files changed, 14 insertions(+), 12 deletions(-)
+
+--- a/fs/fuse/file.c
++++ b/fs/fuse/file.c
+@@ -1448,7 +1448,7 @@ ssize_t fuse_direct_io(struct fuse_io_pr
+ if (!ia)
+ return -ENOMEM;
+
+- if (fopen_direct_io && fc->direct_io_relax) {
++ if (fopen_direct_io && fc->direct_io_allow_mmap) {
+ res = filemap_write_and_wait_range(mapping, pos, pos + count - 1);
+ if (res) {
+ fuse_io_free(ia);
+@@ -2466,9 +2466,9 @@ static int fuse_file_mmap(struct file *f
+
+ if (ff->open_flags & FOPEN_DIRECT_IO) {
+ /* Can't provide the coherency needed for MAP_SHARED
+- * if FUSE_DIRECT_IO_RELAX isn't set.
++ * if FUSE_DIRECT_IO_ALLOW_MMAP isn't set.
+ */
+- if ((vma->vm_flags & VM_MAYSHARE) && !fc->direct_io_relax)
++ if ((vma->vm_flags & VM_MAYSHARE) && !fc->direct_io_allow_mmap)
+ return -ENODEV;
+
+ invalidate_inode_pages2(file->f_mapping);
+--- a/fs/fuse/fuse_i.h
++++ b/fs/fuse/fuse_i.h
+@@ -797,8 +797,8 @@ struct fuse_conn {
+ /* Is tmpfile not implemented by fs? */
+ unsigned int no_tmpfile:1;
+
+- /* relax restrictions in FOPEN_DIRECT_IO mode */
+- unsigned int direct_io_relax:1;
++ /* Relax restrictions to allow shared mmap in FOPEN_DIRECT_IO mode */
++ unsigned int direct_io_allow_mmap:1;
+
+ /* Is statx not implemented by fs? */
+ unsigned int no_statx:1;
+--- a/fs/fuse/inode.c
++++ b/fs/fuse/inode.c
+@@ -1232,8 +1232,8 @@ static void process_init_reply(struct fu
+ fc->init_security = 1;
+ if (flags & FUSE_CREATE_SUPP_GROUP)
+ fc->create_supp_group = 1;
+- if (flags & FUSE_DIRECT_IO_RELAX)
+- fc->direct_io_relax = 1;
++ if (flags & FUSE_DIRECT_IO_ALLOW_MMAP)
++ fc->direct_io_allow_mmap = 1;
+ } else {
+ ra_pages = fc->max_read / PAGE_SIZE;
+ fc->no_lock = 1;
+@@ -1280,7 +1280,7 @@ void fuse_send_init(struct fuse_mount *f
+ FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA |
+ FUSE_HANDLE_KILLPRIV_V2 | FUSE_SETXATTR_EXT | FUSE_INIT_EXT |
+ FUSE_SECURITY_CTX | FUSE_CREATE_SUPP_GROUP |
+- FUSE_HAS_EXPIRE_ONLY | FUSE_DIRECT_IO_RELAX;
++ FUSE_HAS_EXPIRE_ONLY | FUSE_DIRECT_IO_ALLOW_MMAP;
+ #ifdef CONFIG_FUSE_DAX
+ if (fm->fc->dax)
+ flags |= FUSE_MAP_ALIGNMENT;
+--- a/include/uapi/linux/fuse.h
++++ b/include/uapi/linux/fuse.h
+@@ -209,7 +209,7 @@
+ * - add FUSE_HAS_EXPIRE_ONLY
+ *
+ * 7.39
+- * - add FUSE_DIRECT_IO_RELAX
++ * - add FUSE_DIRECT_IO_ALLOW_MMAP
+ * - add FUSE_STATX and related structures
+ */
+
+@@ -409,8 +409,7 @@ struct fuse_file_lock {
+ * FUSE_CREATE_SUPP_GROUP: add supplementary group info to create, mkdir,
+ * symlink and mknod (single group that matches parent)
+ * FUSE_HAS_EXPIRE_ONLY: kernel supports expiry-only entry invalidation
+- * FUSE_DIRECT_IO_RELAX: relax restrictions in FOPEN_DIRECT_IO mode, for now
+- * allow shared mmap
++ * FUSE_DIRECT_IO_ALLOW_MMAP: allow shared mmap in FOPEN_DIRECT_IO mode.
+ */
+ #define FUSE_ASYNC_READ (1 << 0)
+ #define FUSE_POSIX_LOCKS (1 << 1)
+@@ -449,7 +448,10 @@ struct fuse_file_lock {
+ #define FUSE_HAS_INODE_DAX (1ULL << 33)
+ #define FUSE_CREATE_SUPP_GROUP (1ULL << 34)
+ #define FUSE_HAS_EXPIRE_ONLY (1ULL << 35)
+-#define FUSE_DIRECT_IO_RELAX (1ULL << 36)
++#define FUSE_DIRECT_IO_ALLOW_MMAP (1ULL << 36)
++
++/* Obsolete alias for FUSE_DIRECT_IO_ALLOW_MMAP */
++#define FUSE_DIRECT_IO_RELAX FUSE_DIRECT_IO_ALLOW_MMAP
+
+ /**
+ * CUSE INIT request/reply flags
--- /dev/null
+From c4d361f66ac91db8fc65061a9671682f61f4ca9d Mon Sep 17 00:00:00 2001
+From: Krister Johansen <kjlx@templeofstupid.com>
+Date: Fri, 3 Nov 2023 10:39:47 -0700
+Subject: fuse: share lookup state between submount and its parent
+
+From: Krister Johansen <kjlx@templeofstupid.com>
+
+commit c4d361f66ac91db8fc65061a9671682f61f4ca9d upstream.
+
+Fuse submounts do not perform a lookup for the nodeid that they inherit
+from their parent. Instead, the code decrements the nlookup on the
+submount's fuse_inode when it is instantiated, and no forget is
+performed when a submount root is evicted.
+
+Trouble arises when the submount's parent is evicted despite the
+submount itself being in use. In this author's case, the submount was
+in a container and deatched from the initial mount namespace via a
+MNT_DEATCH operation. When memory pressure triggered the shrinker, the
+inode from the parent was evicted, which triggered enough forgets to
+render the submount's nodeid invalid.
+
+Since submounts should still function, even if their parent goes away,
+solve this problem by sharing refcounted state between the parent and
+its submount. When all of the references on this shared state reach
+zero, it's safe to forget the final lookup of the fuse nodeid.
+
+Signed-off-by: Krister Johansen <kjlx@templeofstupid.com>
+Cc: stable@vger.kernel.org
+Fixes: 1866d779d5d2 ("fuse: Allow fuse_fill_super_common() for submounts")
+Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/fuse/fuse_i.h | 15 +++++++++++
+ fs/fuse/inode.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
+ 2 files changed, 87 insertions(+), 3 deletions(-)
+
+--- a/fs/fuse/fuse_i.h
++++ b/fs/fuse/fuse_i.h
+@@ -63,6 +63,19 @@ struct fuse_forget_link {
+ struct fuse_forget_link *next;
+ };
+
++/* Submount lookup tracking */
++struct fuse_submount_lookup {
++ /** Refcount */
++ refcount_t count;
++
++ /** Unique ID, which identifies the inode between userspace
++ * and kernel */
++ u64 nodeid;
++
++ /** The request used for sending the FORGET message */
++ struct fuse_forget_link *forget;
++};
++
+ /** FUSE inode */
+ struct fuse_inode {
+ /** Inode data */
+@@ -158,6 +171,8 @@ struct fuse_inode {
+ */
+ struct fuse_inode_dax *dax;
+ #endif
++ /** Submount specific lookup tracking */
++ struct fuse_submount_lookup *submount_lookup;
+ };
+
+ /** FUSE inode state bits */
+--- a/fs/fuse/inode.c
++++ b/fs/fuse/inode.c
+@@ -68,6 +68,24 @@ struct fuse_forget_link *fuse_alloc_forg
+ return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL_ACCOUNT);
+ }
+
++static struct fuse_submount_lookup *fuse_alloc_submount_lookup(void)
++{
++ struct fuse_submount_lookup *sl;
++
++ sl = kzalloc(sizeof(struct fuse_submount_lookup), GFP_KERNEL_ACCOUNT);
++ if (!sl)
++ return NULL;
++ sl->forget = fuse_alloc_forget();
++ if (!sl->forget)
++ goto out_free;
++
++ return sl;
++
++out_free:
++ kfree(sl);
++ return NULL;
++}
++
+ static struct inode *fuse_alloc_inode(struct super_block *sb)
+ {
+ struct fuse_inode *fi;
+@@ -83,6 +101,7 @@ static struct inode *fuse_alloc_inode(st
+ fi->attr_version = 0;
+ fi->orig_ino = 0;
+ fi->state = 0;
++ fi->submount_lookup = NULL;
+ mutex_init(&fi->mutex);
+ spin_lock_init(&fi->lock);
+ fi->forget = fuse_alloc_forget();
+@@ -113,6 +132,17 @@ static void fuse_free_inode(struct inode
+ kmem_cache_free(fuse_inode_cachep, fi);
+ }
+
++static void fuse_cleanup_submount_lookup(struct fuse_conn *fc,
++ struct fuse_submount_lookup *sl)
++{
++ if (!refcount_dec_and_test(&sl->count))
++ return;
++
++ fuse_queue_forget(fc, sl->forget, sl->nodeid, 1);
++ sl->forget = NULL;
++ kfree(sl);
++}
++
+ static void fuse_evict_inode(struct inode *inode)
+ {
+ struct fuse_inode *fi = get_fuse_inode(inode);
+@@ -132,6 +162,11 @@ static void fuse_evict_inode(struct inod
+ fi->nlookup);
+ fi->forget = NULL;
+ }
++
++ if (fi->submount_lookup) {
++ fuse_cleanup_submount_lookup(fc, fi->submount_lookup);
++ fi->submount_lookup = NULL;
++ }
+ }
+ if (S_ISREG(inode->i_mode) && !fuse_is_bad(inode)) {
+ WARN_ON(!list_empty(&fi->write_files));
+@@ -332,6 +367,13 @@ void fuse_change_attributes(struct inode
+ fuse_dax_dontcache(inode, attr->flags);
+ }
+
++static void fuse_init_submount_lookup(struct fuse_submount_lookup *sl,
++ u64 nodeid)
++{
++ sl->nodeid = nodeid;
++ refcount_set(&sl->count, 1);
++}
++
+ static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr,
+ struct fuse_conn *fc)
+ {
+@@ -395,12 +437,22 @@ struct inode *fuse_iget(struct super_blo
+ */
+ if (fc->auto_submounts && (attr->flags & FUSE_ATTR_SUBMOUNT) &&
+ S_ISDIR(attr->mode)) {
++ struct fuse_inode *fi;
++
+ inode = new_inode(sb);
+ if (!inode)
+ return NULL;
+
+ fuse_init_inode(inode, attr, fc);
+- get_fuse_inode(inode)->nodeid = nodeid;
++ fi = get_fuse_inode(inode);
++ fi->nodeid = nodeid;
++ fi->submount_lookup = fuse_alloc_submount_lookup();
++ if (!fi->submount_lookup) {
++ iput(inode);
++ return NULL;
++ }
++ /* Sets nlookup = 1 on fi->submount_lookup->nlookup */
++ fuse_init_submount_lookup(fi->submount_lookup, nodeid);
+ inode->i_flags |= S_AUTOMOUNT;
+ goto done;
+ }
+@@ -423,11 +475,11 @@ retry:
+ iput(inode);
+ goto retry;
+ }
+-done:
+ fi = get_fuse_inode(inode);
+ spin_lock(&fi->lock);
+ fi->nlookup++;
+ spin_unlock(&fi->lock);
++done:
+ fuse_change_attributes(inode, attr, NULL, attr_valid, attr_version);
+
+ return inode;
+@@ -1465,6 +1517,8 @@ static int fuse_fill_super_submount(stru
+ struct super_block *parent_sb = parent_fi->inode.i_sb;
+ struct fuse_attr root_attr;
+ struct inode *root;
++ struct fuse_submount_lookup *sl;
++ struct fuse_inode *fi;
+
+ fuse_sb_defaults(sb);
+ fm->sb = sb;
+@@ -1487,12 +1541,27 @@ static int fuse_fill_super_submount(stru
+ * its nlookup should not be incremented. fuse_iget() does
+ * that, though, so undo it here.
+ */
+- get_fuse_inode(root)->nlookup--;
++ fi = get_fuse_inode(root);
++ fi->nlookup--;
++
+ sb->s_d_op = &fuse_dentry_operations;
+ sb->s_root = d_make_root(root);
+ if (!sb->s_root)
+ return -ENOMEM;
+
++ /*
++ * Grab the parent's submount_lookup pointer and take a
++ * reference on the shared nlookup from the parent. This is to
++ * prevent the last forget for this nodeid from getting
++ * triggered until all users have finished with it.
++ */
++ sl = parent_fi->submount_lookup;
++ WARN_ON(!sl);
++ if (sl) {
++ refcount_inc(&sl->count);
++ fi->submount_lookup = sl;
++ }
++
+ return 0;
+ }
+
--- /dev/null
+From 31e52523267faab5ed8569b9d5c22c9a2283872f Mon Sep 17 00:00:00 2001
+From: Sebastian Parschauer <s.parschauer@gmx.de>
+Date: Mon, 27 Nov 2023 23:49:37 +0100
+Subject: HID: Add quirk for Labtec/ODDOR/aikeec handbrake
+
+From: Sebastian Parschauer <s.parschauer@gmx.de>
+
+commit 31e52523267faab5ed8569b9d5c22c9a2283872f upstream.
+
+This device needs ALWAYS_POLL quirk, otherwise it keeps reconnecting
+indefinitely. It is a handbrake for sim racing detected as joystick.
+Reported and tested by GitHub user N0th1ngM4tt3rs.
+
+Link: https://github.com/sriemer/fix-linux-mouse issue 22
+Signed-off-by: Sebastian Parschauer <s.parschauer@gmx.de>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-ids.h | 1 +
+ drivers/hid/hid-quirks.c | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -744,6 +744,7 @@
+
+ #define USB_VENDOR_ID_LABTEC 0x1020
+ #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD 0x0006
++#define USB_DEVICE_ID_LABTEC_ODDOR_HANDBRAKE 0x8888
+
+ #define USB_VENDOR_ID_LCPOWER 0x1241
+ #define USB_DEVICE_ID_LCPOWER_LC1000 0xf767
+--- a/drivers/hid/hid-quirks.c
++++ b/drivers/hid/hid-quirks.c
+@@ -120,6 +120,7 @@ static const struct hid_device_id hid_qu
+ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M406XE), HID_QUIRK_MULTI_INPUT },
+ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2), HID_QUIRK_MULTI_INPUT },
+ { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_T609A), HID_QUIRK_MULTI_INPUT },
++ { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_ODDOR_HANDBRAKE), HID_QUIRK_ALWAYS_POLL },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E), HID_QUIRK_ALWAYS_POLL },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D), HID_QUIRK_ALWAYS_POLL },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019), HID_QUIRK_ALWAYS_POLL },
--- /dev/null
+From a9f68ffe1170ca4bc17ab29067d806a354a026e0 Mon Sep 17 00:00:00 2001
+From: Mario Limonciello <mario.limonciello@amd.com>
+Date: Sat, 2 Dec 2023 21:24:30 -0600
+Subject: HID: i2c-hid: Add IDEA5002 to i2c_hid_acpi_blacklist[]
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+commit a9f68ffe1170ca4bc17ab29067d806a354a026e0 upstream.
+
+Users have reported problems with recent Lenovo laptops that contain
+an IDEA5002 I2C HID device. Reports include fans turning on and
+running even at idle and spurious wakeups from suspend.
+
+Presumably in the Windows ecosystem there is an application that
+uses the HID device. Maybe that puts it into a lower power state so
+it doesn't cause spurious events.
+
+This device doesn't serve any functional purpose in Linux as nothing
+interacts with it so blacklist it from being probed. This will
+prevent the GPIO driver from setting up the GPIO and the spurious
+interrupts and wake events will not occur.
+
+Cc: stable@vger.kernel.org # 6.1
+Reported-and-tested-by: Marcus Aram <marcus+oss@oxar.nl>
+Reported-and-tested-by: Mark Herbert <mark.herbert42@gmail.com>
+Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/2812
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/i2c-hid/i2c-hid-acpi.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/hid/i2c-hid/i2c-hid-acpi.c
++++ b/drivers/hid/i2c-hid/i2c-hid-acpi.c
+@@ -40,6 +40,11 @@ static const struct acpi_device_id i2c_h
+ * ICN8505 controller, has a _CID of PNP0C50 but is not HID compatible.
+ */
+ { "CHPN0001" },
++ /*
++ * The IDEA5002 ACPI device causes high interrupt usage and spurious
++ * wakeups from suspend.
++ */
++ { "IDEA5002" },
+ { }
+ };
+
--- /dev/null
+From 1ba0e9d69b2000e95267c888cbfa91d823388d47 Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Thu, 14 Dec 2023 21:34:08 +0000
+Subject: io_uring/cmd: fix breakage in SOCKET_URING_OP_SIOC* implementation
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 1ba0e9d69b2000e95267c888cbfa91d823388d47 upstream.
+
+ In 8e9fad0e70b7 "io_uring: Add io_uring command support for sockets"
+you've got an include of asm-generic/ioctls.h done in io_uring/uring_cmd.c.
+That had been done for the sake of this chunk -
++ ret = prot->ioctl(sk, SIOCINQ, &arg);
++ if (ret)
++ return ret;
++ return arg;
++ case SOCKET_URING_OP_SIOCOUTQ:
++ ret = prot->ioctl(sk, SIOCOUTQ, &arg);
+
+SIOC{IN,OUT}Q are defined to symbols (FIONREAD and TIOCOUTQ) that come from
+ioctls.h, all right, but the values vary by the architecture.
+
+FIONREAD is
+ 0x467F on mips
+ 0x4004667F on alpha, powerpc and sparc
+ 0x8004667F on sh and xtensa
+ 0x541B everywhere else
+TIOCOUTQ is
+ 0x7472 on mips
+ 0x40047473 on alpha, powerpc and sparc
+ 0x80047473 on sh and xtensa
+ 0x5411 everywhere else
+
+->ioctl() expects the same values it would've gotten from userland; all
+places where we compare with SIOC{IN,OUT}Q are using asm/ioctls.h, so
+they pick the correct values. io_uring_cmd_sock(), OTOH, ends up
+passing the default ones.
+
+Fixes: 8e9fad0e70b7 ("io_uring: Add io_uring command support for sockets")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Link: https://lore.kernel.org/r/20231214213408.GT1674809@ZenIV
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ io_uring/uring_cmd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c
+index acbc2924ecd2..7d3ef62e620a 100644
+--- a/io_uring/uring_cmd.c
++++ b/io_uring/uring_cmd.c
+@@ -7,7 +7,7 @@
+ #include <linux/nospec.h>
+
+ #include <uapi/linux/io_uring.h>
+-#include <uapi/asm-generic/ioctls.h>
++#include <asm/ioctls.h>
+
+ #include "io_uring.h"
+ #include "rsrc.h"
+--
+2.43.0
+
--- /dev/null
+From 13736654481198e519059d4a2e2e3b20fa9fdb3e Mon Sep 17 00:00:00 2001
+From: Namjae Jeon <linkinjeon@kernel.org>
+Date: Wed, 6 Dec 2023 08:23:49 +0900
+Subject: ksmbd: fix wrong name of SMB2_CREATE_ALLOCATION_SIZE
+
+From: Namjae Jeon <linkinjeon@kernel.org>
+
+commit 13736654481198e519059d4a2e2e3b20fa9fdb3e upstream.
+
+MS confirm that "AISi" name of SMB2_CREATE_ALLOCATION_SIZE in MS-SMB2
+specification is a typo. cifs/ksmbd have been using this wrong name from
+MS-SMB2. It should be "AlSi". Also It will cause problem when running
+smb2.create.open test in smbtorture against ksmbd.
+
+Cc: stable@vger.kernel.org
+Fixes: 12197a7fdda9 ("Clarify SMB2/SMB3 create context and add missing ones")
+Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
+Reviewed-by: Paulo Alcantara (SUSE) <pc@manguebit.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/smb/common/smb2pdu.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/smb/common/smb2pdu.h
++++ b/fs/smb/common/smb2pdu.h
+@@ -1120,7 +1120,7 @@ struct smb2_change_notify_rsp {
+ #define SMB2_CREATE_SD_BUFFER "SecD" /* security descriptor */
+ #define SMB2_CREATE_DURABLE_HANDLE_REQUEST "DHnQ"
+ #define SMB2_CREATE_DURABLE_HANDLE_RECONNECT "DHnC"
+-#define SMB2_CREATE_ALLOCATION_SIZE "AISi"
++#define SMB2_CREATE_ALLOCATION_SIZE "AlSi"
+ #define SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST "MxAc"
+ #define SMB2_CREATE_TIMEWARP_REQUEST "TWrp"
+ #define SMB2_CREATE_QUERY_ON_DISK_ID "QFid"
--- /dev/null
+From 718ab8226636a1a3a7d281f5d6a7ad7c925efe5a Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan+linaro@kernel.org>
+Date: Tue, 28 Nov 2023 09:15:07 +0100
+Subject: PCI/ASPM: Add pci_enable_link_state_locked()
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+commit 718ab8226636a1a3a7d281f5d6a7ad7c925efe5a upstream.
+
+Add pci_enable_link_state_locked() for enabling link states that can be
+used in contexts where a pci_bus_sem read lock is already held (e.g. from
+pci_walk_bus()).
+
+This helper will be used to fix a couple of potential deadlocks where
+the current helper is called with the lock already held, hence the CC
+stable tag.
+
+Fixes: f492edb40b54 ("PCI: vmd: Add quirk to configure PCIe ASPM and LTR")
+Link: https://lore.kernel.org/r/20231128081512.19387-2-johan+linaro@kernel.org
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+[bhelgaas: include helper name in subject, commit log]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Cc: <stable@vger.kernel.org> # 6.3
+Cc: Michael Bottini <michael.a.bottini@linux.intel.com>
+Cc: David E. Box <david.e.box@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/pcie/aspm.c | 53 ++++++++++++++++++++++++++++++++++++------------
+ include/linux/pci.h | 3 ++
+ 2 files changed, 43 insertions(+), 13 deletions(-)
+
+--- a/drivers/pci/pcie/aspm.c
++++ b/drivers/pci/pcie/aspm.c
+@@ -1102,17 +1102,7 @@ int pci_disable_link_state(struct pci_de
+ }
+ EXPORT_SYMBOL(pci_disable_link_state);
+
+-/**
+- * pci_enable_link_state - Clear and set the default device link state so that
+- * the link may be allowed to enter the specified states. Note that if the
+- * BIOS didn't grant ASPM control to the OS, this does nothing because we can't
+- * touch the LNKCTL register. Also note that this does not enable states
+- * disabled by pci_disable_link_state(). Return 0 or a negative errno.
+- *
+- * @pdev: PCI device
+- * @state: Mask of ASPM link states to enable
+- */
+-int pci_enable_link_state(struct pci_dev *pdev, int state)
++static int __pci_enable_link_state(struct pci_dev *pdev, int state, bool locked)
+ {
+ struct pcie_link_state *link = pcie_aspm_get_link(pdev);
+
+@@ -1129,7 +1119,8 @@ int pci_enable_link_state(struct pci_dev
+ return -EPERM;
+ }
+
+- down_read(&pci_bus_sem);
++ if (!locked)
++ down_read(&pci_bus_sem);
+ mutex_lock(&aspm_lock);
+ link->aspm_default = 0;
+ if (state & PCIE_LINK_STATE_L0S)
+@@ -1150,12 +1141,48 @@ int pci_enable_link_state(struct pci_dev
+ link->clkpm_default = (state & PCIE_LINK_STATE_CLKPM) ? 1 : 0;
+ pcie_set_clkpm(link, policy_to_clkpm_state(link));
+ mutex_unlock(&aspm_lock);
+- up_read(&pci_bus_sem);
++ if (!locked)
++ up_read(&pci_bus_sem);
+
+ return 0;
+ }
++
++/**
++ * pci_enable_link_state - Clear and set the default device link state so that
++ * the link may be allowed to enter the specified states. Note that if the
++ * BIOS didn't grant ASPM control to the OS, this does nothing because we can't
++ * touch the LNKCTL register. Also note that this does not enable states
++ * disabled by pci_disable_link_state(). Return 0 or a negative errno.
++ *
++ * @pdev: PCI device
++ * @state: Mask of ASPM link states to enable
++ */
++int pci_enable_link_state(struct pci_dev *pdev, int state)
++{
++ return __pci_enable_link_state(pdev, state, false);
++}
+ EXPORT_SYMBOL(pci_enable_link_state);
+
++/**
++ * pci_enable_link_state_locked - Clear and set the default device link state
++ * so that the link may be allowed to enter the specified states. Note that if
++ * the BIOS didn't grant ASPM control to the OS, this does nothing because we
++ * can't touch the LNKCTL register. Also note that this does not enable states
++ * disabled by pci_disable_link_state(). Return 0 or a negative errno.
++ *
++ * @pdev: PCI device
++ * @state: Mask of ASPM link states to enable
++ *
++ * Context: Caller holds pci_bus_sem read lock.
++ */
++int pci_enable_link_state_locked(struct pci_dev *pdev, int state)
++{
++ lockdep_assert_held_read(&pci_bus_sem);
++
++ return __pci_enable_link_state(pdev, state, true);
++}
++EXPORT_SYMBOL(pci_enable_link_state_locked);
++
+ static int pcie_aspm_set_policy(const char *val,
+ const struct kernel_param *kp)
+ {
+--- a/include/linux/pci.h
++++ b/include/linux/pci.h
+@@ -1803,6 +1803,7 @@ extern bool pcie_ports_native;
+ int pci_disable_link_state(struct pci_dev *pdev, int state);
+ int pci_disable_link_state_locked(struct pci_dev *pdev, int state);
+ int pci_enable_link_state(struct pci_dev *pdev, int state);
++int pci_enable_link_state_locked(struct pci_dev *pdev, int state);
+ void pcie_no_aspm(void);
+ bool pcie_aspm_support_enabled(void);
+ bool pcie_aspm_enabled(struct pci_dev *pdev);
+@@ -1813,6 +1814,8 @@ static inline int pci_disable_link_state
+ { return 0; }
+ static inline int pci_enable_link_state(struct pci_dev *pdev, int state)
+ { return 0; }
++static inline int pci_enable_link_state_locked(struct pci_dev *pdev, int state)
++{ return 0; }
+ static inline void pcie_no_aspm(void) { }
+ static inline bool pcie_aspm_support_enabled(void) { return false; }
+ static inline bool pcie_aspm_enabled(struct pci_dev *pdev) { return false; }
--- /dev/null
+From ef61a0405742a9f7f6051bc6fd2f017d87d07911 Mon Sep 17 00:00:00 2001
+From: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Date: Fri, 1 Dec 2023 11:50:28 +0000
+Subject: PCI: loongson: Limit MRRS to 256
+
+From: Jiaxun Yang <jiaxun.yang@flygoat.com>
+
+commit ef61a0405742a9f7f6051bc6fd2f017d87d07911 upstream.
+
+This is a partial revert of 8b3517f88ff2 ("PCI: loongson: Prevent LS7A MRRS
+increases") for MIPS-based Loongson.
+
+Some MIPS Loongson systems don't support arbitrary Max_Read_Request_Size
+(MRRS) settings. 8b3517f88ff2 ("PCI: loongson: Prevent LS7A MRRS
+increases") worked around that by (1) assuming that firmware configured
+MRRS to the maximum supported value and (2) preventing the PCI core from
+increasing MRRS.
+
+Unfortunately, some firmware doesn't set that maximum MRRS correctly, which
+results in devices not being initialized correctly. One symptom, from the
+Debian report below, is this:
+
+ ata4.00: exception Emask 0x0 SAct 0x20000000 SErr 0x0 action 0x6 frozen
+ ata4.00: failed command: WRITE FPDMA QUEUED
+ ata4.00: cmd 61/20:e8:00:f0:e1/00:00:00:00:00/40 tag 29 ncq dma 16384 out
+ res 40/00:00:00:00:00/00:00:00:00:00/00 Emask 0x4 (timeout)
+ ata4.00: status: { DRDY }
+ ata4: hard resetting link
+
+Limit MRRS to 256 because MIPS Loongson with higher MRRS support is
+considered rare.
+
+This must be done at device enablement stage because the MRRS setting may
+get lost if PCI_COMMAND_MASTER on the parent bridge is cleared, and we are
+only sure parent bridge is enabled at this point.
+
+Fixes: 8b3517f88ff2 ("PCI: loongson: Prevent LS7A MRRS increases")
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217680
+Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1035587
+Link: https://lore.kernel.org/r/20231201115028.84351-1-jiaxun.yang@flygoat.com
+Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Huacai Chen <chenhuacai@loongson.cn>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/pci-loongson.c | 46 ++++++++++++++++++++++++++++++----
+ 1 file changed, 41 insertions(+), 5 deletions(-)
+
+--- a/drivers/pci/controller/pci-loongson.c
++++ b/drivers/pci/controller/pci-loongson.c
+@@ -80,13 +80,49 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LO
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LOONGSON,
+ DEV_LS7A_LPC, system_bus_quirk);
+
++/*
++ * Some Loongson PCIe ports have hardware limitations on their Maximum Read
++ * Request Size. They can't handle anything larger than this. Sane
++ * firmware will set proper MRRS at boot, so we only need no_inc_mrrs for
++ * bridges. However, some MIPS Loongson firmware doesn't set MRRS properly,
++ * so we have to enforce maximum safe MRRS, which is 256 bytes.
++ */
++#ifdef CONFIG_MIPS
++static void loongson_set_min_mrrs_quirk(struct pci_dev *pdev)
++{
++ struct pci_bus *bus = pdev->bus;
++ struct pci_dev *bridge;
++ static const struct pci_device_id bridge_devids[] = {
++ { PCI_VDEVICE(LOONGSON, DEV_LS2K_PCIE_PORT0) },
++ { PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT0) },
++ { PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT1) },
++ { PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT2) },
++ { PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT3) },
++ { PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT4) },
++ { PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT5) },
++ { PCI_VDEVICE(LOONGSON, DEV_LS7A_PCIE_PORT6) },
++ { 0, },
++ };
++
++ /* look for the matching bridge */
++ while (!pci_is_root_bus(bus)) {
++ bridge = bus->self;
++ bus = bus->parent;
++
++ if (pci_match_id(bridge_devids, bridge)) {
++ if (pcie_get_readrq(pdev) > 256) {
++ pci_info(pdev, "limiting MRRS to 256\n");
++ pcie_set_readrq(pdev, 256);
++ }
++ break;
++ }
++ }
++}
++DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, loongson_set_min_mrrs_quirk);
++#endif
++
+ static void loongson_mrrs_quirk(struct pci_dev *pdev)
+ {
+- /*
+- * Some Loongson PCIe ports have h/w limitations of maximum read
+- * request size. They can't handle anything larger than this. So
+- * force this limit on any devices attached under these ports.
+- */
+ struct pci_host_bridge *bridge = pci_find_host_bridge(pdev->bus);
+
+ bridge->no_inc_mrrs = 1;
--- /dev/null
+From 49de0dc87965079a8e2803ee4b39f9d946259423 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan+linaro@kernel.org>
+Date: Tue, 28 Nov 2023 09:15:08 +0100
+Subject: PCI: vmd: Fix potential deadlock when enabling ASPM
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+commit 49de0dc87965079a8e2803ee4b39f9d946259423 upstream.
+
+The vmd_pm_enable_quirk() helper is called from pci_walk_bus() during
+probe to enable ASPM for controllers with VMD_FEAT_BIOS_PM_QUIRK set.
+
+Since pci_walk_bus() already holds a pci_bus_sem read lock, use
+pci_enable_link_state_locked() to enable link states in order to avoid a
+potential deadlock (e.g. in case someone takes a write lock before
+reacquiring the read lock).
+
+Fixes: f492edb40b54 ("PCI: vmd: Add quirk to configure PCIe ASPM and LTR")
+Link: https://lore.kernel.org/r/20231128081512.19387-3-johan+linaro@kernel.org
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+[bhelgaas: add "potential" in subject since the deadlock has only been
+reported by lockdep, include helper name in commit log]
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Cc: <stable@vger.kernel.org> # 6.3
+Cc: Michael Bottini <michael.a.bottini@linux.intel.com>
+Cc: David E. Box <david.e.box@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/controller/vmd.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/pci/controller/vmd.c b/drivers/pci/controller/vmd.c
+index 94ba61fe1c44..0452cbc362ee 100644
+--- a/drivers/pci/controller/vmd.c
++++ b/drivers/pci/controller/vmd.c
+@@ -751,7 +751,7 @@ static int vmd_pm_enable_quirk(struct pci_dev *pdev, void *userdata)
+ if (!(features & VMD_FEAT_BIOS_PM_QUIRK))
+ return 0;
+
+- pci_enable_link_state(pdev, PCIE_LINK_STATE_ALL);
++ pci_enable_link_state_locked(pdev, PCIE_LINK_STATE_ALL);
+
+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_LTR);
+ if (!pos)
+--
+2.43.0
+
--- /dev/null
+From 5df12742b7e3aae2594a30a9d14d5d6e9e7699f4 Mon Sep 17 00:00:00 2001
+From: Bjorn Helgaas <bhelgaas@google.com>
+Date: Thu, 14 Dec 2023 09:08:56 -0600
+Subject: Revert "PCI: acpiphp: Reassign resources on bridge if necessary"
+
+From: Bjorn Helgaas <bhelgaas@google.com>
+
+commit 5df12742b7e3aae2594a30a9d14d5d6e9e7699f4 upstream.
+
+This reverts commit 40613da52b13fb21c5566f10b287e0ca8c12c4e9 and the
+subsequent fix to it:
+
+ cc22522fd55e ("PCI: acpiphp: Use pci_assign_unassigned_bridge_resources() only for non-root bus")
+
+40613da52b13 fixed a problem where hot-adding a device with large BARs
+failed if the bridge windows programmed by firmware were not large enough.
+
+cc22522fd55e ("PCI: acpiphp: Use pci_assign_unassigned_bridge_resources()
+only for non-root bus") fixed a problem with 40613da52b13: an ACPI hot-add
+of a device on a PCI root bus (common in the virt world) or firmware
+sending ACPI Bus Check to non-existent Root Ports (e.g., on Dell Inspiron
+7352/0W6WV0) caused a NULL pointer dereference and suspend/resume hangs.
+
+Unfortunately the combination of 40613da52b13 and cc22522fd55e caused other
+problems:
+
+ - Fiona reported that hot-add of SCSI disks in QEMU virtual machine fails
+ sometimes.
+
+ - Dongli reported a similar problem with hot-add of SCSI disks.
+
+ - Jonathan reported a console freeze during boot on bare metal due to an
+ error in radeon GPU initialization.
+
+Revert both patches to avoid adding these problems. This means we will
+again see the problems with hot-adding devices with large BARs and the NULL
+pointer dereferences and suspend/resume issues that 40613da52b13 and
+cc22522fd55e were intended to fix.
+
+Fixes: 40613da52b13 ("PCI: acpiphp: Reassign resources on bridge if necessary")
+Fixes: cc22522fd55e ("PCI: acpiphp: Use pci_assign_unassigned_bridge_resources() only for non-root bus")
+Reported-by: Fiona Ebner <f.ebner@proxmox.com>
+Closes: https://lore.kernel.org/r/9eb669c0-d8f2-431d-a700-6da13053ae54@proxmox.com
+Reported-by: Dongli Zhang <dongli.zhang@oracle.com>
+Closes: https://lore.kernel.org/r/3c4a446a-b167-11b8-f36f-d3c1b49b42e9@oracle.com
+Reported-by: Jonathan Woithe <jwoithe@just42.net>
+Closes: https://lore.kernel.org/r/ZXpaNCLiDM+Kv38H@marvin.atrad.com.au
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Michael S. Tsirkin <mst@redhat.com>
+Acked-by: Igor Mammedov <imammedo@redhat.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/hotplug/acpiphp_glue.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+--- a/drivers/pci/hotplug/acpiphp_glue.c
++++ b/drivers/pci/hotplug/acpiphp_glue.c
+@@ -512,15 +512,12 @@ static void enable_slot(struct acpiphp_s
+ if (pass && dev->subordinate) {
+ check_hotplug_bridge(slot, dev);
+ pcibios_resource_survey_bus(dev->subordinate);
+- if (pci_is_root_bus(bus))
+- __pci_bus_size_bridges(dev->subordinate, &add_list);
++ __pci_bus_size_bridges(dev->subordinate,
++ &add_list);
+ }
+ }
+ }
+- if (pci_is_root_bus(bus))
+- __pci_bus_assign_resources(bus, &add_list, NULL);
+- else
+- pci_assign_unassigned_bridge_resources(bus->self);
++ __pci_bus_assign_resources(bus, &add_list, NULL);
+ }
+
+ acpiphp_sanitize_bus(bus);
net-stmmac-handle-disabled-mdio-busses-from-devicetr.patch
appletalk-fix-use-after-free-in-atalk_ioctl.patch
net-atlantic-fix-double-free-in-ring-reinit-logic.patch
+cred-switch-to-using-atomic_long_t.patch
+cred-get-rid-of-config_debug_credentials.patch
+hid-i2c-hid-add-idea5002-to-i2c_hid_acpi_blacklist.patch
+hid-add-quirk-for-labtec-oddor-aikeec-handbrake.patch
+fuse-rename-direct_io_relax-to-direct_io_allow_mmap.patch
+fuse-share-lookup-state-between-submount-and-its-parent.patch
+fuse-disable-fopen_parallel_direct_writes-with-fuse_direct_io_allow_mmap.patch
+fuse-dax-set-fc-dax-to-null-in-fuse_dax_conn_free.patch
+io_uring-cmd-fix-breakage-in-socket_uring_op_sioc-implementation.patch
+alsa-hda-hdmi-add-force-connect-quirk-for-nuc5cpyb.patch
+alsa-hda-hdmi-add-force-connect-quirks-for-asustek-z170-variants.patch
+alsa-hda-realtek-apply-mute-led-quirk-for-hp15-db.patch
+alsa-hda-tas2781-leave-hda_component-in-usable-state.patch
+alsa-hda-tas2781-handle-missing-efi-calibration-data.patch
+alsa-hda-tas2781-call-cleanup-functions-only-once.patch
+alsa-hda-tas2781-reset-the-amp-before-component_add.patch
+revert-pci-acpiphp-reassign-resources-on-bridge-if-necessary.patch
+pci-loongson-limit-mrrs-to-256.patch
+pci-aspm-add-pci_enable_link_state_locked.patch
+ksmbd-fix-wrong-name-of-smb2_create_allocation_size.patch
+pci-vmd-fix-potential-deadlock-when-enabling-aspm.patch