--- /dev/null
+From 8a354d8b6952e9b4949d0c0cd618abd764cc9f48 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Aug 2023 20:40:51 +0900
+Subject: ALSA: hda/realtek: Add quirk for HP Victus 16-d1xxx to enable mute
+ LED
+
+From: SungHwan Jung <onenowy@gmail.com>
+
+[ Upstream commit 93dc18e11b1ab2d485b69f91c973e6b83e47ebd0 ]
+
+This quirk enables mute LED on HP Victus 16-d1xxx (8A25) laptops, which
+use ALC245 codec.
+
+Signed-off-by: SungHwan Jung <onenowy@gmail.com>
+Link: https://lore.kernel.org/r/20230823114051.3921-1-onenowy@gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 41b07476da38 ("ALSA: hda/realtek - ALC287 Realtek I2S speaker platform support")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/patch_realtek.c | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index ccf99f881cc4f..00051c14e263a 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -4639,6 +4639,22 @@ static void alc236_fixup_hp_mute_led_coefbit2(struct hda_codec *codec,
+ }
+ }
+
++static void alc245_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
++ const struct hda_fixup *fix,
++ int action)
++{
++ struct alc_spec *spec = codec->spec;
++
++ if (action == HDA_FIXUP_ACT_PRE_PROBE) {
++ spec->mute_led_polarity = 0;
++ spec->mute_led_coef.idx = 0x0b;
++ spec->mute_led_coef.mask = 3 << 2;
++ spec->mute_led_coef.on = 2 << 2;
++ spec->mute_led_coef.off = 1 << 2;
++ snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
++ }
++}
++
+ /* turn on/off mic-mute LED per capture hook by coef bit */
+ static int coef_micmute_led_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+@@ -7293,6 +7309,7 @@ enum {
+ ALC236_FIXUP_DELL_DUAL_CODECS,
+ ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI,
+ ALC287_FIXUP_TAS2781_I2C,
++ ALC245_FIXUP_HP_MUTE_LED_COEFBIT,
+ };
+
+ /* A special fixup for Lenovo C940 and Yoga Duet 7;
+@@ -9377,6 +9394,10 @@ static const struct hda_fixup alc269_fixups[] = {
+ .chained = true,
+ .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
+ },
++ [ALC245_FIXUP_HP_MUTE_LED_COEFBIT] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = alc245_fixup_hp_mute_led_coefbit,
++ },
+ };
+
+ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -9650,6 +9671,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x89c6, "Zbook Fury 17 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x89ca, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+ SND_PCI_QUIRK(0x103c, 0x89d3, "HP EliteBook 645 G9 (MB 89D2)", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
++ SND_PCI_QUIRK(0x103c, 0x8a25, "HP Victus 16-d1xxx (MB 8A25)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
+ SND_PCI_QUIRK(0x103c, 0x8a78, "HP Dev One", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST),
+ SND_PCI_QUIRK(0x103c, 0x8aa0, "HP ProBook 440 G9 (MB 8A9E)", ALC236_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8aa3, "HP ProBook 450 G9 (MB 8AA1)", ALC236_FIXUP_HP_GPIO_LED),
+--
+2.40.1
+
--- /dev/null
+From eadc5fca3515ed944bad90e2403d0742ad11cf93 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Aug 2023 20:39:48 +0200
+Subject: ALSA: hda/realtek: Add quirk for mute LEDs on HP ENVY x360 15-eu0xxx
+
+From: Fabian Vogt <fabian@ritter-vogt.de>
+
+[ Upstream commit c99c26b16c1544534ebd6a5f27a034f3e44d2597 ]
+
+The LED for the mic mute button is controlled by GPIO2.
+The mute button LED is slightly more complex, it's controlled by two bits
+in coeff 0x0b.
+
+Signed-off-by: Fabian Vogt <fabian@ritter-vogt.de>
+Link: https://lore.kernel.org/r/2693091.mvXUDI8C0e@fabians-envy
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 41b07476da38 ("ALSA: hda/realtek - ALC287 Realtek I2S speaker platform support")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/patch_realtek.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 00051c14e263a..57bd11c6057d5 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -7310,6 +7310,7 @@ enum {
+ ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI,
+ ALC287_FIXUP_TAS2781_I2C,
+ ALC245_FIXUP_HP_MUTE_LED_COEFBIT,
++ ALC245_FIXUP_HP_X360_MUTE_LEDS,
+ };
+
+ /* A special fixup for Lenovo C940 and Yoga Duet 7;
+@@ -9398,6 +9399,12 @@ static const struct hda_fixup alc269_fixups[] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc245_fixup_hp_mute_led_coefbit,
+ },
++ [ALC245_FIXUP_HP_X360_MUTE_LEDS] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = alc245_fixup_hp_mute_led_coefbit,
++ .chained = true,
++ .chain_id = ALC245_FIXUP_HP_GPIO_LED
++ },
+ };
+
+ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -9640,6 +9647,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x8870, "HP ZBook Fury 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+ SND_PCI_QUIRK(0x103c, 0x8873, "HP ZBook Studio 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+ SND_PCI_QUIRK(0x103c, 0x887a, "HP Laptop 15s-eq2xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
++ SND_PCI_QUIRK(0x103c, 0x888a, "HP ENVY x360 Convertible 15-eu0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS),
+ SND_PCI_QUIRK(0x103c, 0x888d, "HP ZBook Power 15.6 inch G8 Mobile Workstation PC", ALC236_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8895, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_SPEAKERS_MICMUTE_LED),
+ SND_PCI_QUIRK(0x103c, 0x8896, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_MUTE_LED),
+--
+2.40.1
+
--- /dev/null
+From 96533eb59bc801c55a4a632c135e321c2134ca9e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Sep 2023 16:50:41 +0800
+Subject: ALSA: hda/realtek - ALC287 I2S speaker platform support
+
+From: Kailang Yang <kailang@realtek.com>
+
+[ Upstream commit e43252db7e207a2e194e6a4883a43a31a776a968 ]
+
+0x17 was only speaker pin, DAC assigned will be 0x03. Headphone
+assigned to 0x02.
+Playback via headphone will get EQ filter processing. So,it needs to
+swap DAC.
+
+Tested-by: Mark Pearson <mpearson@lenovo.com>
+Signed-off-by: Kailang Yang <kailang@realtek.com>
+Link: https://lore.kernel.org/r/4e4cfa1b3b4c46838aecafc6e8b6f876@realtek.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 41b07476da38 ("ALSA: hda/realtek - ALC287 Realtek I2S speaker platform support")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/patch_realtek.c | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 57bd11c6057d5..b040889b22880 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -7049,6 +7049,27 @@ static void alc295_fixup_dell_inspiron_top_speakers(struct hda_codec *codec,
+ }
+ }
+
++/* Forcibly assign NID 0x03 to HP while NID 0x02 to SPK */
++static void alc287_fixup_bind_dacs(struct hda_codec *codec,
++ const struct hda_fixup *fix, int action)
++{
++ struct alc_spec *spec = codec->spec;
++ static const hda_nid_t conn[] = { 0x02, 0x03 }; /* exclude 0x06 */
++ static const hda_nid_t preferred_pairs[] = {
++ 0x17, 0x02, 0x21, 0x03, 0
++ };
++
++ if (action != HDA_FIXUP_ACT_PRE_PROBE)
++ return;
++
++ snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
++ spec->gen.preferred_dacs = preferred_pairs;
++ spec->gen.auto_mute_via_amp = 1;
++ snd_hda_codec_write_cache(codec, 0x14, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
++ 0x0); /* Make sure 0x14 was disable */
++}
++
++
+ enum {
+ ALC269_FIXUP_GPIO2,
+ ALC269_FIXUP_SONY_VAIO,
+@@ -7311,6 +7332,7 @@ enum {
+ ALC287_FIXUP_TAS2781_I2C,
+ ALC245_FIXUP_HP_MUTE_LED_COEFBIT,
+ ALC245_FIXUP_HP_X360_MUTE_LEDS,
++ ALC287_FIXUP_THINKPAD_I2S_SPK,
+ };
+
+ /* A special fixup for Lenovo C940 and Yoga Duet 7;
+@@ -9405,6 +9427,10 @@ static const struct hda_fixup alc269_fixups[] = {
+ .chained = true,
+ .chain_id = ALC245_FIXUP_HP_GPIO_LED
+ },
++ [ALC287_FIXUP_THINKPAD_I2S_SPK] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = alc287_fixup_bind_dacs,
++ },
+ };
+
+ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -10537,6 +10563,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
+ {0x17, 0x90170111},
+ {0x19, 0x03a11030},
+ {0x21, 0x03211020}),
++ SND_HDA_PIN_QUIRK(0x10ec0287, 0x17aa, "Lenovo", ALC287_FIXUP_THINKPAD_I2S_SPK,
++ {0x17, 0x90170110},
++ {0x19, 0x03a11030},
++ {0x21, 0x03211020}),
+ SND_HDA_PIN_QUIRK(0x10ec0286, 0x1025, "Acer", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE,
+ {0x12, 0x90a60130},
+ {0x17, 0x90170110},
+--
+2.40.1
+
--- /dev/null
+From 097eb22c1cce349594a0c43edfd5dcd2af10813a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 19 Sep 2023 16:27:16 +0800
+Subject: ALSA: hda/realtek - ALC287 Realtek I2S speaker platform support
+
+From: Kailang Yang <kailang@realtek.com>
+
+[ Upstream commit 41b07476da38ac2878a14e5b8fe0312c41ea36e3 ]
+
+New platform SSID:0x231f.
+
+0x17 was only speaker pin, DAC assigned will be 0x03. Headphone
+assigned to 0x02.
+Playback via headphone will get EQ filter processing.
+So, it needs to swap DAC.
+
+Signed-off-by: Kailang Yang <kailang@realtek.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/8d63c6e360124e3ea2523753050e6f05@realtek.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/patch_realtek.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index b040889b22880..45fa102060cef 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -10567,6 +10567,10 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
+ {0x17, 0x90170110},
+ {0x19, 0x03a11030},
+ {0x21, 0x03211020}),
++ SND_HDA_PIN_QUIRK(0x10ec0287, 0x17aa, "Lenovo", ALC287_FIXUP_THINKPAD_I2S_SPK,
++ {0x17, 0x90170110}, /* 0x231f with RTK I2S AMP */
++ {0x19, 0x04a11040},
++ {0x21, 0x04211020}),
+ SND_HDA_PIN_QUIRK(0x10ec0286, 0x1025, "Acer", ALC286_FIXUP_ACER_AIO_MIC_NO_PRESENCE,
+ {0x12, 0x90a60130},
+ {0x17, 0x90170110},
+--
+2.40.1
+
--- /dev/null
+From 49ae5f8082daf33e220fd5c14df7c14565971741 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Aug 2023 16:58:35 +0800
+Subject: ALSA: hda/tas2781: Add tas2781 HDA driver
+
+From: Shenghao Ding <shenghao-ding@ti.com>
+
+[ Upstream commit 3babae915f4c15d76a5134e55806a1c1588e2865 ]
+
+Integrate tas2781 configs for Lenovo Laptops. All of the tas2781s in the
+laptop will be aggregated as one audio device. The code support realtek
+as the primary codec. Rename "struct cs35l41_dev_name" to
+"struct scodec_dev_name" for all other side codecs instead of the certain
+one.
+
+Signed-off-by: Shenghao Ding <shenghao-ding@ti.com>
+Link: https://lore.kernel.org/r/20230818085836.1442-1-shenghao-ding@ti.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Stable-dep-of: 41b07476da38 ("ALSA: hda/realtek - ALC287 Realtek I2S speaker platform support")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/patch_realtek.c | 88 +++++++++++++++++++++++++++++++++--
+ 1 file changed, 85 insertions(+), 3 deletions(-)
+
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 4a13747b2b0f3..ccf99f881cc4f 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -6721,7 +6721,7 @@ static void comp_generic_playback_hook(struct hda_pcm_stream *hinfo, struct hda_
+ }
+ }
+
+-struct cs35l41_dev_name {
++struct scodec_dev_name {
+ const char *bus;
+ const char *hid;
+ int index;
+@@ -6730,7 +6730,7 @@ struct cs35l41_dev_name {
+ /* match the device name in a slightly relaxed manner */
+ static int comp_match_cs35l41_dev_name(struct device *dev, void *data)
+ {
+- struct cs35l41_dev_name *p = data;
++ struct scodec_dev_name *p = data;
+ const char *d = dev_name(dev);
+ int n = strlen(p->bus);
+ char tmp[32];
+@@ -6746,12 +6746,32 @@ static int comp_match_cs35l41_dev_name(struct device *dev, void *data)
+ return !strcmp(d + n, tmp);
+ }
+
++static int comp_match_tas2781_dev_name(struct device *dev,
++ void *data)
++{
++ struct scodec_dev_name *p = data;
++ const char *d = dev_name(dev);
++ int n = strlen(p->bus);
++ char tmp[32];
++
++ /* check the bus name */
++ if (strncmp(d, p->bus, n))
++ return 0;
++ /* skip the bus number */
++ if (isdigit(d[n]))
++ n++;
++ /* the rest must be exact matching */
++ snprintf(tmp, sizeof(tmp), "-%s:00", p->hid);
++
++ return !strcmp(d + n, tmp);
++}
++
+ static void cs35l41_generic_fixup(struct hda_codec *cdc, int action, const char *bus,
+ const char *hid, int count)
+ {
+ struct device *dev = hda_codec_dev(cdc);
+ struct alc_spec *spec = cdc->spec;
+- struct cs35l41_dev_name *rec;
++ struct scodec_dev_name *rec;
+ int ret, i;
+
+ switch (action) {
+@@ -6779,6 +6799,41 @@ static void cs35l41_generic_fixup(struct hda_codec *cdc, int action, const char
+ }
+ }
+
++static void tas2781_generic_fixup(struct hda_codec *cdc, int action,
++ const char *bus, const char *hid)
++{
++ struct device *dev = hda_codec_dev(cdc);
++ struct alc_spec *spec = cdc->spec;
++ struct scodec_dev_name *rec;
++ int ret;
++
++ switch (action) {
++ case HDA_FIXUP_ACT_PRE_PROBE:
++ rec = devm_kmalloc(dev, sizeof(*rec), GFP_KERNEL);
++ if (!rec)
++ return;
++ rec->bus = bus;
++ rec->hid = hid;
++ rec->index = 0;
++ spec->comps[0].codec = cdc;
++ component_match_add(dev, &spec->match,
++ comp_match_tas2781_dev_name, rec);
++ ret = component_master_add_with_match(dev, &comp_master_ops,
++ spec->match);
++ if (ret)
++ codec_err(cdc,
++ "Fail to register component aggregator %d\n",
++ ret);
++ else
++ spec->gen.pcm_playback_hook =
++ comp_generic_playback_hook;
++ break;
++ case HDA_FIXUP_ACT_FREE:
++ component_master_del(dev, &comp_master_ops);
++ break;
++ }
++}
++
+ static void cs35l41_fixup_i2c_two(struct hda_codec *cdc, const struct hda_fixup *fix, int action)
+ {
+ cs35l41_generic_fixup(cdc, action, "i2c", "CSC3551", 2);
+@@ -6806,6 +6861,12 @@ static void alc287_fixup_legion_16ithg6_speakers(struct hda_codec *cdc, const st
+ cs35l41_generic_fixup(cdc, action, "i2c", "CLSA0101", 2);
+ }
+
++static void tas2781_fixup_i2c(struct hda_codec *cdc,
++ const struct hda_fixup *fix, int action)
++{
++ tas2781_generic_fixup(cdc, action, "i2c", "TIAS2781");
++}
++
+ /* for alc295_fixup_hp_top_speakers */
+ #include "hp_x360_helper.c"
+
+@@ -7231,6 +7292,7 @@ enum {
+ ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS,
+ ALC236_FIXUP_DELL_DUAL_CODECS,
+ ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI,
++ ALC287_FIXUP_TAS2781_I2C,
+ };
+
+ /* A special fixup for Lenovo C940 and Yoga Duet 7;
+@@ -9309,6 +9371,12 @@ static const struct hda_fixup alc269_fixups[] = {
+ .chained = true,
+ .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
+ },
++ [ALC287_FIXUP_TAS2781_I2C] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = tas2781_fixup_i2c,
++ .chained = true,
++ .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
++ },
+ };
+
+ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+@@ -9890,6 +9958,20 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
+ SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6),
+ SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
++ SND_PCI_QUIRK(0x17aa, 0x387d, "Yoga S780-16 pro Quad AAC", ALC287_FIXUP_TAS2781_I2C),
++ SND_PCI_QUIRK(0x17aa, 0x387e, "Yoga S780-16 pro Quad YC", ALC287_FIXUP_TAS2781_I2C),
++ SND_PCI_QUIRK(0x17aa, 0x3881, "YB9 dual powe mode2 YC", ALC287_FIXUP_TAS2781_I2C),
++ SND_PCI_QUIRK(0x17aa, 0x3884, "Y780 YG DUAL", ALC287_FIXUP_TAS2781_I2C),
++ SND_PCI_QUIRK(0x17aa, 0x3886, "Y780 VECO DUAL", ALC287_FIXUP_TAS2781_I2C),
++ SND_PCI_QUIRK(0x17aa, 0x38a7, "Y780P AMD YG dual", ALC287_FIXUP_TAS2781_I2C),
++ SND_PCI_QUIRK(0x17aa, 0x38a8, "Y780P AMD VECO dual", ALC287_FIXUP_TAS2781_I2C),
++ SND_PCI_QUIRK(0x17aa, 0x38ba, "Yoga S780-14.5 Air AMD quad YC", ALC287_FIXUP_TAS2781_I2C),
++ SND_PCI_QUIRK(0x17aa, 0x38bb, "Yoga S780-14.5 Air AMD quad AAC", ALC287_FIXUP_TAS2781_I2C),
++ SND_PCI_QUIRK(0x17aa, 0x38be, "Yoga S980-14.5 proX YC Dual", ALC287_FIXUP_TAS2781_I2C),
++ SND_PCI_QUIRK(0x17aa, 0x38bf, "Yoga S980-14.5 proX LX Dual", ALC287_FIXUP_TAS2781_I2C),
++ SND_PCI_QUIRK(0x17aa, 0x38c3, "Y980 DUAL", ALC287_FIXUP_TAS2781_I2C),
++ SND_PCI_QUIRK(0x17aa, 0x38cb, "Y790 YG DUAL", ALC287_FIXUP_TAS2781_I2C),
++ SND_PCI_QUIRK(0x17aa, 0x38cd, "Y790 VECO DUAL", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
+ SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
+ SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
+--
+2.40.1
+
--- /dev/null
+From 8057be5d7ac578722af942d2455258d2e2e07944 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Aug 2023 15:37:45 +0100
+Subject: arm64: add HWCAP for FEAT_HBC (hinted conditional branches)
+
+From: Joey Gouly <joey.gouly@arm.com>
+
+[ Upstream commit 7f86d128e437990fd08d9e66ae7c1571666cff8a ]
+
+Add a HWCAP for FEAT_HBC, so that userspace can make a decision on using
+this feature.
+
+Signed-off-by: Joey Gouly <joey.gouly@arm.com>
+Cc: Catalin Marinas <catalin.marinas@arm.com>
+Cc: Will Deacon <will@kernel.org>
+Link: https://lore.kernel.org/r/20230804143746.3900803-2-joey.gouly@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Stable-dep-of: 479965a2b7ec ("arm64: cpufeature: Fix CLRBHB and BC detection")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/hwcap.h | 1 +
+ arch/arm64/include/uapi/asm/hwcap.h | 1 +
+ arch/arm64/kernel/cpufeature.c | 3 ++-
+ arch/arm64/kernel/cpuinfo.c | 1 +
+ 4 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
+index 692b1ec663b27..521267478d187 100644
+--- a/arch/arm64/include/asm/hwcap.h
++++ b/arch/arm64/include/asm/hwcap.h
+@@ -138,6 +138,7 @@
+ #define KERNEL_HWCAP_SME_B16B16 __khwcap2_feature(SME_B16B16)
+ #define KERNEL_HWCAP_SME_F16F16 __khwcap2_feature(SME_F16F16)
+ #define KERNEL_HWCAP_MOPS __khwcap2_feature(MOPS)
++#define KERNEL_HWCAP_HBC __khwcap2_feature(HBC)
+
+ /*
+ * This yields a mask that user programs can use to figure out what
+diff --git a/arch/arm64/include/uapi/asm/hwcap.h b/arch/arm64/include/uapi/asm/hwcap.h
+index a2cac4305b1e0..53026f45a5092 100644
+--- a/arch/arm64/include/uapi/asm/hwcap.h
++++ b/arch/arm64/include/uapi/asm/hwcap.h
+@@ -103,5 +103,6 @@
+ #define HWCAP2_SME_B16B16 (1UL << 41)
+ #define HWCAP2_SME_F16F16 (1UL << 42)
+ #define HWCAP2_MOPS (1UL << 43)
++#define HWCAP2_HBC (1UL << 44)
+
+ #endif /* _UAPI__ASM_HWCAP_H */
+diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
+index f9d456fe132d8..ac764c1dac363 100644
+--- a/arch/arm64/kernel/cpufeature.c
++++ b/arch/arm64/kernel/cpufeature.c
+@@ -222,7 +222,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
+ static const struct arm64_ftr_bits ftr_id_aa64isar2[] = {
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_CSSC_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_RPRFM_SHIFT, 4, 0),
+- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_HIGHER_SAFE, ID_AA64ISAR2_EL1_BC_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, ID_AA64ISAR2_EL1_BC_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_MOPS_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH),
+ FTR_STRICT, FTR_EXACT, ID_AA64ISAR2_EL1_APA3_SHIFT, 4, 0),
+@@ -2844,6 +2844,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
+ HWCAP_CAP(ID_AA64ISAR2_EL1, RPRES, IMP, CAP_HWCAP, KERNEL_HWCAP_RPRES),
+ HWCAP_CAP(ID_AA64ISAR2_EL1, WFxT, IMP, CAP_HWCAP, KERNEL_HWCAP_WFXT),
+ HWCAP_CAP(ID_AA64ISAR2_EL1, MOPS, IMP, CAP_HWCAP, KERNEL_HWCAP_MOPS),
++ HWCAP_CAP(ID_AA64ISAR2_EL1, BC, IMP, CAP_HWCAP, KERNEL_HWCAP_HBC),
+ #ifdef CONFIG_ARM64_SME
+ HWCAP_CAP(ID_AA64PFR1_EL1, SME, IMP, CAP_HWCAP, KERNEL_HWCAP_SME),
+ HWCAP_CAP(ID_AA64SMFR0_EL1, FA64, IMP, CAP_HWCAP, KERNEL_HWCAP_SME_FA64),
+diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
+index 58622dc859177..98fda85005353 100644
+--- a/arch/arm64/kernel/cpuinfo.c
++++ b/arch/arm64/kernel/cpuinfo.c
+@@ -126,6 +126,7 @@ static const char *const hwcap_str[] = {
+ [KERNEL_HWCAP_SME_B16B16] = "smeb16b16",
+ [KERNEL_HWCAP_SME_F16F16] = "smef16f16",
+ [KERNEL_HWCAP_MOPS] = "mops",
++ [KERNEL_HWCAP_HBC] = "hbc",
+ };
+
+ #ifdef CONFIG_COMPAT
+--
+2.40.1
+
--- /dev/null
+From 8a5c763da5aa12beba942da05d306c48437f5812 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 14:34:29 +0100
+Subject: arm64: cpufeature: Fix CLRBHB and BC detection
+
+From: Kristina Martsenko <kristina.martsenko@arm.com>
+
+[ Upstream commit 479965a2b7ec481737df0cadf553331063b9c343 ]
+
+ClearBHB support is indicated by the CLRBHB field in ID_AA64ISAR2_EL1.
+Following some refactoring the kernel incorrectly checks the BC field
+instead. Fix the detection to use the right field.
+
+(Note: The original ClearBHB support had it as FTR_HIGHER_SAFE, but this
+patch uses FTR_LOWER_SAFE, which seems more correct.)
+
+Also fix the detection of BC (hinted conditional branches) to use
+FTR_LOWER_SAFE, so that it is not reported on mismatched systems.
+
+Fixes: 356137e68a9f ("arm64/sysreg: Make BHB clear feature defines match the architecture")
+Fixes: 8fcc8285c0e3 ("arm64/sysreg: Convert ID_AA64ISAR2_EL1 to automatic generation")
+Cc: stable@vger.kernel.org
+Signed-off-by: Kristina Martsenko <kristina.martsenko@arm.com>
+Reviewed-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/r/20230912133429.2606875-1-kristina.martsenko@arm.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/cpufeature.h | 2 +-
+ arch/arm64/kernel/cpufeature.c | 3 ++-
+ arch/arm64/tools/sysreg | 6 +++++-
+ 3 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
+index 96e50227f940e..5bba393760557 100644
+--- a/arch/arm64/include/asm/cpufeature.h
++++ b/arch/arm64/include/asm/cpufeature.h
+@@ -663,7 +663,7 @@ static inline bool supports_clearbhb(int scope)
+ isar2 = read_sanitised_ftr_reg(SYS_ID_AA64ISAR2_EL1);
+
+ return cpuid_feature_extract_unsigned_field(isar2,
+- ID_AA64ISAR2_EL1_BC_SHIFT);
++ ID_AA64ISAR2_EL1_CLRBHB_SHIFT);
+ }
+
+ const struct cpumask *system_32bit_el0_cpumask(void);
+diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
+index ac764c1dac363..2c0b8444fea67 100644
+--- a/arch/arm64/kernel/cpufeature.c
++++ b/arch/arm64/kernel/cpufeature.c
+@@ -222,7 +222,8 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
+ static const struct arm64_ftr_bits ftr_id_aa64isar2[] = {
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_CSSC_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_RPRFM_SHIFT, 4, 0),
+- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_HIGHER_SAFE, ID_AA64ISAR2_EL1_BC_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_CLRBHB_SHIFT, 4, 0),
++ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_BC_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_MOPS_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH),
+ FTR_STRICT, FTR_EXACT, ID_AA64ISAR2_EL1_APA3_SHIFT, 4, 0),
+diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
+index 65866bf819c33..ffc81afa6caca 100644
+--- a/arch/arm64/tools/sysreg
++++ b/arch/arm64/tools/sysreg
+@@ -1347,7 +1347,11 @@ UnsignedEnum 51:48 RPRFM
+ 0b0000 NI
+ 0b0001 IMP
+ EndEnum
+-Res0 47:28
++Res0 47:32
++UnsignedEnum 31:28 CLRBHB
++ 0b0000 NI
++ 0b0001 IMP
++EndEnum
+ UnsignedEnum 27:24 PAC_frac
+ 0b0000 NI
+ 0b0001 IMP
+--
+2.40.1
+
--- /dev/null
+From bbf28b5526628d8e025a8666998314d62f87b0e8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Sep 2023 20:32:24 +0530
+Subject: ASoC: soc-utils: Export snd_soc_dai_is_dummy() symbol
+
+From: Sameer Pujar <spujar@nvidia.com>
+
+[ Upstream commit f101583fa9f8c3f372d4feb61d67da0ccbf4d9a5 ]
+
+Export symbol snd_soc_dai_is_dummy() for usage outside core driver
+modules. This is required by Tegra ASoC machine driver.
+
+Signed-off-by: Sameer Pujar <spujar@nvidia.com>
+Link: https://lore.kernel.org/r/1694098945-32760-2-git-send-email-spujar@nvidia.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/soc-utils.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
+index 11607c5f5d5a8..9c746e4edef71 100644
+--- a/sound/soc/soc-utils.c
++++ b/sound/soc/soc-utils.c
+@@ -217,6 +217,7 @@ int snd_soc_dai_is_dummy(struct snd_soc_dai *dai)
+ return 1;
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(snd_soc_dai_is_dummy);
+
+ int snd_soc_component_is_dummy(struct snd_soc_component *component)
+ {
+--
+2.40.1
+
--- /dev/null
+From 37c0e1b564a800ace7afd64aa91ce9d910323b6b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 7 Sep 2023 20:32:25 +0530
+Subject: ASoC: tegra: Fix redundant PLLA and PLLA_OUT0 updates
+
+From: Sameer Pujar <spujar@nvidia.com>
+
+[ Upstream commit e765886249c533e1bb5cbc3cd741bad677417312 ]
+
+Tegra audio graph card has many DAI links which connects internal
+AHUB modules and external audio codecs. Since these are DPCM links,
+hw_params() call in the machine driver happens for each connected
+BE link and PLLA is updated every time. This is not really needed
+for all links as only I/O link DAIs derive respective clocks from
+PLLA_OUT0 and thus from PLLA. Hence add checks to limit the clock
+updates to DAIs over I/O links.
+
+This found to be fixing a DMIC clock discrepancy which is suspected
+to happen because of back to back quick PLLA and PLLA_OUT0 rate
+updates. This was observed on Jetson TX2 platform where DMIC clock
+ended up with unexpected value.
+
+Fixes: 202e2f774543 ("ASoC: tegra: Add audio graph based card driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sameer Pujar <spujar@nvidia.com>
+Link: https://lore.kernel.org/r/1694098945-32760-3-git-send-email-spujar@nvidia.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/tegra/tegra_audio_graph_card.c | 30 ++++++++++++++----------
+ 1 file changed, 17 insertions(+), 13 deletions(-)
+
+diff --git a/sound/soc/tegra/tegra_audio_graph_card.c b/sound/soc/tegra/tegra_audio_graph_card.c
+index 1f2c5018bf5ac..4737e776d3837 100644
+--- a/sound/soc/tegra/tegra_audio_graph_card.c
++++ b/sound/soc/tegra/tegra_audio_graph_card.c
+@@ -10,6 +10,7 @@
+ #include <linux/platform_device.h>
+ #include <sound/graph_card.h>
+ #include <sound/pcm_params.h>
++#include <sound/soc-dai.h>
+
+ #define MAX_PLLA_OUT0_DIV 128
+
+@@ -44,6 +45,21 @@ struct tegra_audio_cdata {
+ unsigned int plla_out0_rates[NUM_RATE_TYPE];
+ };
+
++static bool need_clk_update(struct snd_soc_dai *dai)
++{
++ if (snd_soc_dai_is_dummy(dai) ||
++ !dai->driver->ops ||
++ !dai->driver->name)
++ return false;
++
++ if (strstr(dai->driver->name, "I2S") ||
++ strstr(dai->driver->name, "DMIC") ||
++ strstr(dai->driver->name, "DSPK"))
++ return true;
++
++ return false;
++}
++
+ /* Setup PLL clock as per the given sample rate */
+ static int tegra_audio_graph_update_pll(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+@@ -140,19 +156,7 @@ static int tegra_audio_graph_hw_params(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+ int err;
+
+- /*
+- * This gets called for each DAI link (FE or BE) when DPCM is used.
+- * We may not want to update PLLA rate for each call. So PLLA update
+- * must be restricted to external I/O links (I2S, DMIC or DSPK) since
+- * they actually depend on it. I/O modules update their clocks in
+- * hw_param() of their respective component driver and PLLA rate
+- * update here helps them to derive appropriate rates.
+- *
+- * TODO: When more HW accelerators get added (like sample rate
+- * converter, volume gain controller etc., which don't really
+- * depend on PLLA) we need a better way to filter here.
+- */
+- if (cpu_dai->driver->ops && rtd->dai_link->no_pcm) {
++ if (need_clk_update(cpu_dai)) {
+ err = tegra_audio_graph_update_pll(substream, params);
+ if (err)
+ return err;
+--
+2.40.1
+
--- /dev/null
+From f803e78617823ec1d571f40a115fe9b1a054a0de Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Sep 2023 09:06:23 +0900
+Subject: ata: libata-scsi: Fix delayed scsi_rescan_device() execution
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+[ Upstream commit 8b4d9469d0b0e553208ee6f62f2807111fde18b9 ]
+
+Commit 6aa0365a3c85 ("ata: libata-scsi: Avoid deadlock on rescan after
+device resume") modified ata_scsi_dev_rescan() to check the scsi device
+"is_suspended" power field to ensure that the scsi device associated
+with an ATA device is fully resumed when scsi_rescan_device() is
+executed. However, this fix is problematic as:
+1) It relies on a PM internal field that should not be used without PM
+ device locking protection.
+2) The check for is_suspended and the call to scsi_rescan_device() are
+ not atomic and a suspend PM event may be triggered between them,
+ casuing scsi_rescan_device() to be called on a suspended device and
+ in that function blocking while holding the scsi device lock. This
+ would deadlock a following resume operation.
+These problems can trigger PM deadlocks on resume, especially with
+resume operations triggered quickly after or during suspend operations.
+E.g., a simple bash script like:
+
+for (( i=0; i<10; i++ )); do
+ echo "+2 > /sys/class/rtc/rtc0/wakealarm
+ echo mem > /sys/power/state
+done
+
+that triggers a resume 2 seconds after starting suspending a system can
+quickly lead to a PM deadlock preventing the system from correctly
+resuming.
+
+Fix this by replacing the check on is_suspended with a check on the
+return value given by scsi_rescan_device() as that function will fail if
+called against a suspended device. Also make sure rescan tasks already
+scheduled are first cancelled before suspending an ata port.
+
+Fixes: 6aa0365a3c85 ("ata: libata-scsi: Avoid deadlock on rescan after device resume")
+Cc: stable@vger.kernel.org
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: Hannes Reinecke <hare@suse.de>
+Reviewed-by: Niklas Cassel <niklas.cassel@wdc.com>
+Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/libata-core.c | 16 ++++++++++++++++
+ drivers/ata/libata-scsi.c | 33 +++++++++++++++------------------
+ 2 files changed, 31 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
+index 76bf185a73c65..6ae9cff6b50c5 100644
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -5245,11 +5245,27 @@ static const unsigned int ata_port_suspend_ehi = ATA_EHI_QUIET
+
+ static void ata_port_suspend(struct ata_port *ap, pm_message_t mesg)
+ {
++ /*
++ * We are about to suspend the port, so we do not care about
++ * scsi_rescan_device() calls scheduled by previous resume operations.
++ * The next resume will schedule the rescan again. So cancel any rescan
++ * that is not done yet.
++ */
++ cancel_delayed_work_sync(&ap->scsi_rescan_task);
++
+ ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, false);
+ }
+
+ static void ata_port_suspend_async(struct ata_port *ap, pm_message_t mesg)
+ {
++ /*
++ * We are about to suspend the port, so we do not care about
++ * scsi_rescan_device() calls scheduled by previous resume operations.
++ * The next resume will schedule the rescan again. So cancel any rescan
++ * that is not done yet.
++ */
++ cancel_delayed_work_sync(&ap->scsi_rescan_task);
++
+ ata_port_request_pm(ap, mesg, 0, ata_port_suspend_ehi, true);
+ }
+
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index 22d7c26297889..ed3146c460910 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -4900,7 +4900,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
+ struct ata_link *link;
+ struct ata_device *dev;
+ unsigned long flags;
+- bool delay_rescan = false;
++ int ret = 0;
+
+ mutex_lock(&ap->scsi_scan_mutex);
+ spin_lock_irqsave(ap->lock, flags);
+@@ -4909,37 +4909,34 @@ void ata_scsi_dev_rescan(struct work_struct *work)
+ ata_for_each_dev(dev, link, ENABLED) {
+ struct scsi_device *sdev = dev->sdev;
+
++ /*
++ * If the port was suspended before this was scheduled,
++ * bail out.
++ */
++ if (ap->pflags & ATA_PFLAG_SUSPENDED)
++ goto unlock;
++
+ if (!sdev)
+ continue;
+ if (scsi_device_get(sdev))
+ continue;
+
+- /*
+- * If the rescan work was scheduled because of a resume
+- * event, the port is already fully resumed, but the
+- * SCSI device may not yet be fully resumed. In such
+- * case, executing scsi_rescan_device() may cause a
+- * deadlock with the PM code on device_lock(). Prevent
+- * this by giving up and retrying rescan after a short
+- * delay.
+- */
+- delay_rescan = sdev->sdev_gendev.power.is_suspended;
+- if (delay_rescan) {
+- scsi_device_put(sdev);
+- break;
+- }
+-
+ spin_unlock_irqrestore(ap->lock, flags);
+- scsi_rescan_device(sdev);
++ ret = scsi_rescan_device(sdev);
+ scsi_device_put(sdev);
+ spin_lock_irqsave(ap->lock, flags);
++
++ if (ret)
++ goto unlock;
+ }
+ }
+
++unlock:
+ spin_unlock_irqrestore(ap->lock, flags);
+ mutex_unlock(&ap->scsi_scan_mutex);
+
+- if (delay_rescan)
++ /* Reschedule with a delay if scsi_rescan_device() returned an error */
++ if (ret)
+ schedule_delayed_work(&ap->scsi_rescan_task,
+ msecs_to_jiffies(5));
+ }
+--
+2.40.1
+
--- /dev/null
+From 4c332287a5cd2f41bffe3f092df54326d02a0a02 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 8 Sep 2023 15:31:39 -0400
+Subject: btrfs: don't clear uptodate on write errors
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit b595d25996329427b2c09d4b90395a165fb3ef8e ]
+
+We have been consistently seeing hangs with generic/648 in our subpage
+GitHub CI setup. This is a classic deadlock, we are calling
+btrfs_read_folio() on a folio, which requires holding the folio lock on
+the folio, and then finding a ordered extent that overlaps that range
+and calling btrfs_start_ordered_extent(), which then tries to write out
+the dirty page, which requires taking the folio lock and then we
+deadlock.
+
+The hang happens because we're writing to range [1271750656, 1271767040),
+page index [77621, 77622], and page 77621 is !Uptodate. It is also Dirty,
+so we call btrfs_read_folio() for 77621 and which does
+btrfs_lock_and_flush_ordered_range() for that range, and we find an ordered
+extent which is [1271644160, 1271746560), page index [77615, 77621].
+The page indexes overlap, but the actual bytes don't overlap. We're
+holding the page lock for 77621, then call
+btrfs_lock_and_flush_ordered_range() which tries to flush the dirty
+page, and tries to lock 77621 again and then we deadlock.
+
+The byte ranges do not overlap, but with subpage support if we clear
+uptodate on any portion of the page we mark the entire thing as not
+uptodate.
+
+We have been clearing page uptodate on write errors, but no other file
+system does this, and is in fact incorrect. This doesn't hurt us in the
+!subpage case because we can't end up with overlapped ranges that don't
+also overlap on the page.
+
+Fix this by not clearing uptodate when we have a write error. The only
+thing we should be doing in this case is setting the mapping error and
+carrying on. This makes it so we would no longer call
+btrfs_read_folio() on the page as it's uptodate and eliminates the
+deadlock.
+
+With this patch we're now able to make it through a full fstests run on
+our subpage blocksize VMs.
+
+Note for stable backports: this probably goes beyond 6.1 but the code
+has been cleaned up and clearing the uptodate bit must be verified on
+each version independently.
+
+CC: stable@vger.kernel.org # 6.1+
+Reviewed-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/extent_io.c | 9 +--------
+ fs/btrfs/inode.c | 4 ----
+ 2 files changed, 1 insertion(+), 12 deletions(-)
+
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index 009c322c5418d..d8461c9aa2445 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -533,10 +533,8 @@ static void end_bio_extent_writepage(struct btrfs_bio *bbio)
+ bvec->bv_offset, bvec->bv_len);
+
+ btrfs_finish_ordered_extent(bbio->ordered, page, start, len, !error);
+- if (error) {
+- btrfs_page_clear_uptodate(fs_info, page, start, len);
++ if (error)
+ mapping_set_error(page->mapping, error);
+- }
+ btrfs_page_clear_writeback(fs_info, page, start, len);
+ }
+
+@@ -1508,8 +1506,6 @@ static int __extent_writepage(struct page *page, struct btrfs_bio_ctrl *bio_ctrl
+ if (ret) {
+ btrfs_mark_ordered_io_finished(BTRFS_I(inode), page, page_start,
+ PAGE_SIZE, !ret);
+- btrfs_page_clear_uptodate(btrfs_sb(inode->i_sb), page,
+- page_start, PAGE_SIZE);
+ mapping_set_error(page->mapping, ret);
+ }
+ unlock_page(page);
+@@ -1676,8 +1672,6 @@ static void extent_buffer_write_end_io(struct btrfs_bio *bbio)
+ struct page *page = bvec->bv_page;
+ u32 len = bvec->bv_len;
+
+- if (!uptodate)
+- btrfs_page_clear_uptodate(fs_info, page, start, len);
+ btrfs_page_clear_writeback(fs_info, page, start, len);
+ bio_offset += len;
+ }
+@@ -2256,7 +2250,6 @@ int extent_write_locked_range(struct inode *inode, u64 start, u64 end,
+ if (ret) {
+ btrfs_mark_ordered_io_finished(BTRFS_I(inode), page,
+ cur, cur_len, !ret);
+- btrfs_page_clear_uptodate(fs_info, page, cur, cur_len);
+ mapping_set_error(page->mapping, ret);
+ }
+ btrfs_page_unlock_writer(fs_info, page, cur, cur_len);
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index b126394ca3dde..0f4498dfa30c9 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -1162,9 +1162,6 @@ static int submit_uncompressed_range(struct btrfs_inode *inode,
+ btrfs_mark_ordered_io_finished(inode, locked_page,
+ page_start, PAGE_SIZE,
+ !ret);
+- btrfs_page_clear_uptodate(inode->root->fs_info,
+- locked_page, page_start,
+- PAGE_SIZE);
+ mapping_set_error(locked_page->mapping, ret);
+ unlock_page(locked_page);
+ }
+@@ -2951,7 +2948,6 @@ static void btrfs_writepage_fixup_worker(struct btrfs_work *work)
+ mapping_set_error(page->mapping, ret);
+ btrfs_mark_ordered_io_finished(inode, page, page_start,
+ PAGE_SIZE, !ret);
+- btrfs_page_clear_uptodate(fs_info, page, page_start, PAGE_SIZE);
+ clear_page_dirty_for_io(page);
+ }
+ btrfs_page_clear_checked(fs_info, page, page_start, PAGE_SIZE);
+--
+2.40.1
+
--- /dev/null
+From c5b0c5a4299d91df651782d99eacf0465c9cf450 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Jun 2023 17:31:25 +0200
+Subject: btrfs: remove btrfs_writepage_endio_finish_ordered
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 6648cedd86135db197410e56b5372b2945f2b311 ]
+
+btrfs_writepage_endio_finish_ordered is a small wrapper around
+btrfs_mark_ordered_io_finished that just changs the argument passing
+slightly, and adds a tracepoint.
+
+Move the tracpoint to btrfs_mark_ordered_io_finished, which means
+it now also covers the error handling in btrfs_cleanup_ordered_extent
+and switch all callers to just call btrfs_mark_ordered_io_finished
+directly.
+
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: b595d2599632 ("btrfs: don't clear uptodate on write errors")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/btrfs_inode.h | 3 ---
+ fs/btrfs/extent_io.c | 17 ++++++++---------
+ fs/btrfs/inode.c | 9 ---------
+ fs/btrfs/ordered-data.c | 4 ++++
+ 4 files changed, 12 insertions(+), 21 deletions(-)
+
+diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
+index d47a927b3504d..90e60ad9db620 100644
+--- a/fs/btrfs/btrfs_inode.h
++++ b/fs/btrfs/btrfs_inode.h
+@@ -501,9 +501,6 @@ int btrfs_run_delalloc_range(struct btrfs_inode *inode, struct page *locked_page
+ u64 start, u64 end, int *page_started,
+ unsigned long *nr_written, struct writeback_control *wbc);
+ int btrfs_writepage_cow_fixup(struct page *page);
+-void btrfs_writepage_endio_finish_ordered(struct btrfs_inode *inode,
+- struct page *page, u64 start,
+- u64 end, bool uptodate);
+ int btrfs_encoded_io_compression_from_extent(struct btrfs_fs_info *fs_info,
+ int compress_type);
+ int btrfs_encoded_read_regular_fill_pages(struct btrfs_inode *inode,
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index 7cc0ed7532793..b051b6e52022c 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -504,17 +504,15 @@ void end_extent_writepage(struct page *page, int err, u64 start, u64 end)
+ struct btrfs_inode *inode;
+ const bool uptodate = (err == 0);
+ int ret = 0;
++ u32 len = end + 1 - start;
+
++ ASSERT(end + 1 - start <= U32_MAX);
+ ASSERT(page && page->mapping);
+ inode = BTRFS_I(page->mapping->host);
+- btrfs_writepage_endio_finish_ordered(inode, page, start, end, uptodate);
++ btrfs_mark_ordered_io_finished(inode, page, start, len, uptodate);
+
+ if (!uptodate) {
+ const struct btrfs_fs_info *fs_info = inode->root->fs_info;
+- u32 len;
+-
+- ASSERT(end + 1 - start <= U32_MAX);
+- len = end + 1 - start;
+
+ btrfs_page_clear_uptodate(fs_info, page, start, len);
+ ret = err < 0 ? err : -EIO;
+@@ -1382,6 +1380,7 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode,
+
+ bio_ctrl->end_io_func = end_bio_extent_writepage;
+ while (cur <= end) {
++ u32 len = end - cur + 1;
+ u64 disk_bytenr;
+ u64 em_end;
+ u64 dirty_range_start = cur;
+@@ -1389,8 +1388,8 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode,
+ u32 iosize;
+
+ if (cur >= i_size) {
+- btrfs_writepage_endio_finish_ordered(inode, page, cur,
+- end, true);
++ btrfs_mark_ordered_io_finished(inode, page, cur, len,
++ true);
+ /*
+ * This range is beyond i_size, thus we don't need to
+ * bother writing back.
+@@ -1399,7 +1398,7 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode,
+ * writeback the sectors with subpage dirty bits,
+ * causing writeback without ordered extent.
+ */
+- btrfs_page_clear_dirty(fs_info, page, cur, end + 1 - cur);
++ btrfs_page_clear_dirty(fs_info, page, cur, len);
+ break;
+ }
+
+@@ -1410,7 +1409,7 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode,
+ continue;
+ }
+
+- em = btrfs_get_extent(inode, NULL, 0, cur, end - cur + 1);
++ em = btrfs_get_extent(inode, NULL, 0, cur, len);
+ if (IS_ERR(em)) {
+ ret = PTR_ERR_OR_ZERO(em);
+ goto out_error;
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index d5c112f6091b1..e0bb4018ddb28 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -3391,15 +3391,6 @@ int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered)
+ return btrfs_finish_one_ordered(ordered);
+ }
+
+-void btrfs_writepage_endio_finish_ordered(struct btrfs_inode *inode,
+- struct page *page, u64 start,
+- u64 end, bool uptodate)
+-{
+- trace_btrfs_writepage_end_io_hook(inode, start, end, uptodate);
+-
+- btrfs_mark_ordered_io_finished(inode, page, start, end + 1 - start, uptodate);
+-}
+-
+ /*
+ * Verify the checksum for a single sector without any extra action that depend
+ * on the type of I/O.
+diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c
+index 5b1aac3fc8e4a..eea5215280dfe 100644
+--- a/fs/btrfs/ordered-data.c
++++ b/fs/btrfs/ordered-data.c
+@@ -410,6 +410,10 @@ void btrfs_mark_ordered_io_finished(struct btrfs_inode *inode,
+ unsigned long flags;
+ u64 cur = file_offset;
+
++ trace_btrfs_writepage_end_io_hook(inode, file_offset,
++ file_offset + num_bytes - 1,
++ uptodate);
++
+ spin_lock_irqsave(&tree->lock, flags);
+ while (cur < file_offset + num_bytes) {
+ u64 entry_end;
+--
+2.40.1
+
--- /dev/null
+From f5d4b635889de5aa70af38ef7158b770893c4dd3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Jun 2023 17:31:26 +0200
+Subject: btrfs: remove end_extent_writepage
+
+From: Christoph Hellwig <hch@lst.de>
+
+[ Upstream commit 9783e4deed7291996459858a1a16f41a8988dd60 ]
+
+end_extent_writepage is a small helper that combines a call to
+btrfs_mark_ordered_io_finished with conditional error-only calls to
+btrfs_page_clear_uptodate and mapping_set_error with a somewhat
+unfortunate calling convention that passes and inclusive end instead
+of the len expected by the underlying functions.
+
+Remove end_extent_writepage and open code it in the 4 callers. Out
+of those two already are error-only and thus don't need the extra
+conditional, and one already has the mapping_set_error, so a duplicate
+call can be avoided.
+
+Reviewed-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: b595d2599632 ("btrfs: don't clear uptodate on write errors")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/extent_io.c | 44 +++++++++++++++-----------------------------
+ fs/btrfs/extent_io.h | 2 --
+ fs/btrfs/inode.c | 42 ++++++++++++++++++++++--------------------
+ 3 files changed, 37 insertions(+), 51 deletions(-)
+
+diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
+index b051b6e52022c..009c322c5418d 100644
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -497,29 +497,6 @@ static void end_page_read(struct page *page, bool uptodate, u64 start, u32 len)
+ btrfs_subpage_end_reader(fs_info, page, start, len);
+ }
+
+-/* lots and lots of room for performance fixes in the end_bio funcs */
+-
+-void end_extent_writepage(struct page *page, int err, u64 start, u64 end)
+-{
+- struct btrfs_inode *inode;
+- const bool uptodate = (err == 0);
+- int ret = 0;
+- u32 len = end + 1 - start;
+-
+- ASSERT(end + 1 - start <= U32_MAX);
+- ASSERT(page && page->mapping);
+- inode = BTRFS_I(page->mapping->host);
+- btrfs_mark_ordered_io_finished(inode, page, start, len, uptodate);
+-
+- if (!uptodate) {
+- const struct btrfs_fs_info *fs_info = inode->root->fs_info;
+-
+- btrfs_page_clear_uptodate(fs_info, page, start, len);
+- ret = err < 0 ? err : -EIO;
+- mapping_set_error(page->mapping, ret);
+- }
+-}
+-
+ /*
+ * after a writepage IO is done, we need to:
+ * clear the uptodate bits on error
+@@ -1485,7 +1462,6 @@ static int __extent_writepage(struct page *page, struct btrfs_bio_ctrl *bio_ctrl
+ struct folio *folio = page_folio(page);
+ struct inode *inode = page->mapping->host;
+ const u64 page_start = page_offset(page);
+- const u64 page_end = page_start + PAGE_SIZE - 1;
+ int ret;
+ int nr = 0;
+ size_t pg_offset;
+@@ -1529,8 +1505,13 @@ static int __extent_writepage(struct page *page, struct btrfs_bio_ctrl *bio_ctrl
+ set_page_writeback(page);
+ end_page_writeback(page);
+ }
+- if (ret)
+- end_extent_writepage(page, ret, page_start, page_end);
++ if (ret) {
++ btrfs_mark_ordered_io_finished(BTRFS_I(inode), page, page_start,
++ PAGE_SIZE, !ret);
++ btrfs_page_clear_uptodate(btrfs_sb(inode->i_sb), page,
++ page_start, PAGE_SIZE);
++ mapping_set_error(page->mapping, ret);
++ }
+ unlock_page(page);
+ ASSERT(ret <= 0);
+ return ret;
+@@ -2248,6 +2229,7 @@ int extent_write_locked_range(struct inode *inode, u64 start, u64 end,
+
+ while (cur <= end) {
+ u64 cur_end = min(round_down(cur, PAGE_SIZE) + PAGE_SIZE - 1, end);
++ u32 cur_len = cur_end + 1 - cur;
+ struct page *page;
+ int nr = 0;
+
+@@ -2271,9 +2253,13 @@ int extent_write_locked_range(struct inode *inode, u64 start, u64 end,
+ set_page_writeback(page);
+ end_page_writeback(page);
+ }
+- if (ret)
+- end_extent_writepage(page, ret, cur, cur_end);
+- btrfs_page_unlock_writer(fs_info, page, cur, cur_end + 1 - cur);
++ if (ret) {
++ btrfs_mark_ordered_io_finished(BTRFS_I(inode), page,
++ cur, cur_len, !ret);
++ btrfs_page_clear_uptodate(fs_info, page, cur, cur_len);
++ mapping_set_error(page->mapping, ret);
++ }
++ btrfs_page_unlock_writer(fs_info, page, cur, cur_len);
+ if (ret < 0) {
+ found_error = true;
+ first_error = ret;
+diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h
+index f61b7896320a1..e7b293717dc14 100644
+--- a/fs/btrfs/extent_io.h
++++ b/fs/btrfs/extent_io.h
+@@ -284,8 +284,6 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans,
+
+ int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array);
+
+-void end_extent_writepage(struct page *page, int err, u64 start, u64 end);
+-
+ #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
+ bool find_lock_delalloc_range(struct inode *inode,
+ struct page *locked_page, u64 *start,
+diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
+index e0bb4018ddb28..b126394ca3dde 100644
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -423,11 +423,10 @@ static inline void btrfs_cleanup_ordered_extents(struct btrfs_inode *inode,
+
+ while (index <= end_index) {
+ /*
+- * For locked page, we will call end_extent_writepage() on it
+- * in run_delalloc_range() for the error handling. That
+- * end_extent_writepage() function will call
+- * btrfs_mark_ordered_io_finished() to clear page Ordered and
+- * run the ordered extent accounting.
++ * For locked page, we will call btrfs_mark_ordered_io_finished
++ * through btrfs_mark_ordered_io_finished() on it
++ * in run_delalloc_range() for the error handling, which will
++ * clear page Ordered and run the ordered extent accounting.
+ *
+ * Here we can't just clear the Ordered bit, or
+ * btrfs_mark_ordered_io_finished() would skip the accounting
+@@ -1157,11 +1156,16 @@ static int submit_uncompressed_range(struct btrfs_inode *inode,
+ btrfs_cleanup_ordered_extents(inode, locked_page, start, end - start + 1);
+ if (locked_page) {
+ const u64 page_start = page_offset(locked_page);
+- const u64 page_end = page_start + PAGE_SIZE - 1;
+
+ set_page_writeback(locked_page);
+ end_page_writeback(locked_page);
+- end_extent_writepage(locked_page, ret, page_start, page_end);
++ btrfs_mark_ordered_io_finished(inode, locked_page,
++ page_start, PAGE_SIZE,
++ !ret);
++ btrfs_page_clear_uptodate(inode->root->fs_info,
++ locked_page, page_start,
++ PAGE_SIZE);
++ mapping_set_error(locked_page->mapping, ret);
+ unlock_page(locked_page);
+ }
+ return ret;
+@@ -2840,23 +2844,19 @@ struct btrfs_writepage_fixup {
+
+ static void btrfs_writepage_fixup_worker(struct btrfs_work *work)
+ {
+- struct btrfs_writepage_fixup *fixup;
++ struct btrfs_writepage_fixup *fixup =
++ container_of(work, struct btrfs_writepage_fixup, work);
+ struct btrfs_ordered_extent *ordered;
+ struct extent_state *cached_state = NULL;
+ struct extent_changeset *data_reserved = NULL;
+- struct page *page;
+- struct btrfs_inode *inode;
+- u64 page_start;
+- u64 page_end;
++ struct page *page = fixup->page;
++ struct btrfs_inode *inode = fixup->inode;
++ struct btrfs_fs_info *fs_info = inode->root->fs_info;
++ u64 page_start = page_offset(page);
++ u64 page_end = page_offset(page) + PAGE_SIZE - 1;
+ int ret = 0;
+ bool free_delalloc_space = true;
+
+- fixup = container_of(work, struct btrfs_writepage_fixup, work);
+- page = fixup->page;
+- inode = fixup->inode;
+- page_start = page_offset(page);
+- page_end = page_offset(page) + PAGE_SIZE - 1;
+-
+ /*
+ * This is similar to page_mkwrite, we need to reserve the space before
+ * we take the page lock.
+@@ -2949,10 +2949,12 @@ static void btrfs_writepage_fixup_worker(struct btrfs_work *work)
+ * to reflect the errors and clean the page.
+ */
+ mapping_set_error(page->mapping, ret);
+- end_extent_writepage(page, ret, page_start, page_end);
++ btrfs_mark_ordered_io_finished(inode, page, page_start,
++ PAGE_SIZE, !ret);
++ btrfs_page_clear_uptodate(fs_info, page, page_start, PAGE_SIZE);
+ clear_page_dirty_for_io(page);
+ }
+- btrfs_page_clear_checked(inode->root->fs_info, page, page_start, PAGE_SIZE);
++ btrfs_page_clear_checked(fs_info, page, page_start, PAGE_SIZE);
+ unlock_page(page);
+ put_page(page);
+ kfree(fixup);
+--
+2.40.1
+
--- /dev/null
+From 264d5a8c32f6ed81eb35ccd399db0183fe0bb583 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Sep 2023 14:12:35 -0400
+Subject: maple_tree: add mas_is_active() to detect in-tree walks
+
+From: Liam R. Howlett <Liam.Howlett@oracle.com>
+
+[ Upstream commit 5c590804b6b0ff933ed4e5cee5d76de3a5048d9f ]
+
+Patch series "maple_tree: Fix mas_prev() state regression".
+
+Pedro Falcato retported an mprotect regression [1] which was bisected back
+to the iterator changes for maple tree. Root cause analysis showed the
+mas_prev() running off the end of the VMA space (previous from 0) followed
+by mas_find(), would skip the first value.
+
+This patchset introduces maple state underflow/overflow so the sequence of
+calls on the maple state will return what the user expects.
+
+Users who encounter this bug may see mprotect(), userfaultfd_register(),
+and mlock() fail on VMAs mapped with address 0.
+
+This patch (of 2):
+
+Instead of constantly checking each possibility of the maple state,
+create a fast path that will skip over checking unlikely states.
+
+Link: https://lkml.kernel.org/r/20230921181236.509072-1-Liam.Howlett@oracle.com
+Link: https://lkml.kernel.org/r/20230921181236.509072-2-Liam.Howlett@oracle.com
+Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
+Cc: Pedro Falcato <pedro.falcato@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/maple_tree.h | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/include/linux/maple_tree.h b/include/linux/maple_tree.h
+index 295548cca8b36..e1e5f38384b20 100644
+--- a/include/linux/maple_tree.h
++++ b/include/linux/maple_tree.h
+@@ -503,6 +503,15 @@ static inline bool mas_is_paused(const struct ma_state *mas)
+ return mas->node == MAS_PAUSE;
+ }
+
++/* Check if the mas is pointing to a node or not */
++static inline bool mas_is_active(struct ma_state *mas)
++{
++ if ((unsigned long)mas->node >= MAPLE_RESERVED_RANGE)
++ return true;
++
++ return false;
++}
++
+ /**
+ * mas_reset() - Reset a Maple Tree operation state.
+ * @mas: Maple Tree operation state.
+--
+2.40.1
+
--- /dev/null
+From 478a93d24919d2f0f0ea93ad83738bcd9e927670 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 16 Sep 2023 12:52:49 +0200
+Subject: mptcp: fix dangling connection hang-up
+
+From: Paolo Abeni <pabeni@redhat.com>
+
+[ Upstream commit 27e5ccc2d5a50ed61bb73153edb1066104b108b3 ]
+
+According to RFC 8684 section 3.3:
+
+ A connection is not closed unless [...] or an implementation-specific
+ connection-level send timeout.
+
+Currently the MPTCP protocol does not implement such timeout, and
+connection timing-out at the TCP-level never move to close state.
+
+Introduces a catch-up condition at subflow close time to move the
+MPTCP socket to close, too.
+
+That additionally allows removing similar existing inside the worker.
+
+Finally, allow some additional timeout for plain ESTABLISHED mptcp
+sockets, as the protocol allows creating new subflows even at that
+point and making the connection functional again.
+
+This issue is actually present since the beginning, but it is basically
+impossible to solve without a long chain of functional pre-requisites
+topped by commit bbd49d114d57 ("mptcp: consolidate transition to
+TCP_CLOSE in mptcp_do_fastclose()"). When backporting this current
+patch, please also backport this other commit as well.
+
+Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/430
+Fixes: e16163b6e2b7 ("mptcp: refactor shutdown and close")
+Cc: stable@vger.kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
+Reviewed-by: Mat Martineau <martineau@kernel.org>
+Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mptcp/protocol.c | 86 ++++++++++++++++++++++----------------------
+ net/mptcp/protocol.h | 22 ++++++++++++
+ net/mptcp/subflow.c | 1 +
+ 3 files changed, 65 insertions(+), 44 deletions(-)
+
+diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
+index 3c85b4c107b2a..3a08ad4ec5d2c 100644
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -894,6 +894,7 @@ static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk)
+ mptcp_subflow_ctx(ssk)->subflow_id = msk->subflow_id++;
+ mptcp_sockopt_sync_locked(msk, ssk);
+ mptcp_subflow_joined(msk, ssk);
++ mptcp_stop_tout_timer(sk);
+ return true;
+ }
+
+@@ -2357,18 +2358,14 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
+ bool dispose_it, need_push = false;
+
+ /* If the first subflow moved to a close state before accept, e.g. due
+- * to an incoming reset, mptcp either:
+- * - if either the subflow or the msk are dead, destroy the context
+- * (the subflow socket is deleted by inet_child_forget) and the msk
+- * - otherwise do nothing at the moment and take action at accept and/or
+- * listener shutdown - user-space must be able to accept() the closed
+- * socket.
++ * to an incoming reset or listener shutdown, the subflow socket is
++ * already deleted by inet_child_forget() and the mptcp socket can't
++ * survive too.
+ */
+- if (msk->in_accept_queue && msk->first == ssk) {
+- if (!sock_flag(sk, SOCK_DEAD) && !sock_flag(ssk, SOCK_DEAD))
+- return;
+-
++ if (msk->in_accept_queue && msk->first == ssk &&
++ (sock_flag(sk, SOCK_DEAD) || sock_flag(ssk, SOCK_DEAD))) {
+ /* ensure later check in mptcp_worker() will dispose the msk */
++ mptcp_set_close_tout(sk, tcp_jiffies32 - (TCP_TIMEWAIT_LEN + 1));
+ sock_set_flag(sk, SOCK_DEAD);
+ lock_sock_nested(ssk, SINGLE_DEPTH_NESTING);
+ mptcp_subflow_drop_ctx(ssk);
+@@ -2435,6 +2432,22 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
+
+ if (need_push)
+ __mptcp_push_pending(sk, 0);
++
++ /* Catch every 'all subflows closed' scenario, including peers silently
++ * closing them, e.g. due to timeout.
++ * For established sockets, allow an additional timeout before closing,
++ * as the protocol can still create more subflows.
++ */
++ if (list_is_singular(&msk->conn_list) && msk->first &&
++ inet_sk_state_load(msk->first) == TCP_CLOSE) {
++ if (sk->sk_state != TCP_ESTABLISHED ||
++ msk->in_accept_queue || sock_flag(sk, SOCK_DEAD)) {
++ inet_sk_state_store(sk, TCP_CLOSE);
++ mptcp_close_wake_up(sk);
++ } else {
++ mptcp_start_tout_timer(sk);
++ }
++ }
+ }
+
+ void mptcp_close_ssk(struct sock *sk, struct sock *ssk,
+@@ -2478,23 +2491,14 @@ static void __mptcp_close_subflow(struct sock *sk)
+
+ }
+
+-static bool mptcp_should_close(const struct sock *sk)
++static bool mptcp_close_tout_expired(const struct sock *sk)
+ {
+- s32 delta = tcp_jiffies32 - inet_csk(sk)->icsk_mtup.probe_timestamp;
+- struct mptcp_subflow_context *subflow;
+-
+- if (delta >= TCP_TIMEWAIT_LEN || mptcp_sk(sk)->in_accept_queue)
+- return true;
++ if (!inet_csk(sk)->icsk_mtup.probe_timestamp ||
++ sk->sk_state == TCP_CLOSE)
++ return false;
+
+- /* if all subflows are in closed status don't bother with additional
+- * timeout
+- */
+- mptcp_for_each_subflow(mptcp_sk(sk), subflow) {
+- if (inet_sk_state_load(mptcp_subflow_tcp_sock(subflow)) !=
+- TCP_CLOSE)
+- return false;
+- }
+- return true;
++ return time_after32(tcp_jiffies32,
++ inet_csk(sk)->icsk_mtup.probe_timestamp + TCP_TIMEWAIT_LEN);
+ }
+
+ static void mptcp_check_fastclose(struct mptcp_sock *msk)
+@@ -2619,15 +2623,16 @@ void mptcp_reset_tout_timer(struct mptcp_sock *msk, unsigned long fail_tout)
+ struct sock *sk = (struct sock *)msk;
+ unsigned long timeout, close_timeout;
+
+- if (!fail_tout && !sock_flag(sk, SOCK_DEAD))
++ if (!fail_tout && !inet_csk(sk)->icsk_mtup.probe_timestamp)
+ return;
+
+- close_timeout = inet_csk(sk)->icsk_mtup.probe_timestamp - tcp_jiffies32 + jiffies + TCP_TIMEWAIT_LEN;
++ close_timeout = inet_csk(sk)->icsk_mtup.probe_timestamp - tcp_jiffies32 + jiffies +
++ TCP_TIMEWAIT_LEN;
+
+ /* the close timeout takes precedence on the fail one, and here at least one of
+ * them is active
+ */
+- timeout = sock_flag(sk, SOCK_DEAD) ? close_timeout : fail_tout;
++ timeout = inet_csk(sk)->icsk_mtup.probe_timestamp ? close_timeout : fail_tout;
+
+ sk_reset_timer(sk, &sk->sk_timer, timeout);
+ }
+@@ -2646,8 +2651,6 @@ static void mptcp_mp_fail_no_response(struct mptcp_sock *msk)
+ mptcp_subflow_reset(ssk);
+ WRITE_ONCE(mptcp_subflow_ctx(ssk)->fail_tout, 0);
+ unlock_sock_fast(ssk, slow);
+-
+- mptcp_reset_tout_timer(msk, 0);
+ }
+
+ static void mptcp_do_fastclose(struct sock *sk)
+@@ -2684,18 +2687,14 @@ static void mptcp_worker(struct work_struct *work)
+ if (test_and_clear_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
+ __mptcp_close_subflow(sk);
+
+- /* There is no point in keeping around an orphaned sk timedout or
+- * closed, but we need the msk around to reply to incoming DATA_FIN,
+- * even if it is orphaned and in FIN_WAIT2 state
+- */
+- if (sock_flag(sk, SOCK_DEAD)) {
+- if (mptcp_should_close(sk))
+- mptcp_do_fastclose(sk);
++ if (mptcp_close_tout_expired(sk)) {
++ mptcp_do_fastclose(sk);
++ mptcp_close_wake_up(sk);
++ }
+
+- if (sk->sk_state == TCP_CLOSE) {
+- __mptcp_destroy_sock(sk);
+- goto unlock;
+- }
++ if (sock_flag(sk, SOCK_DEAD) && sk->sk_state == TCP_CLOSE) {
++ __mptcp_destroy_sock(sk);
++ goto unlock;
+ }
+
+ if (test_and_clear_bit(MPTCP_WORK_RTX, &msk->flags))
+@@ -2987,7 +2986,6 @@ bool __mptcp_close(struct sock *sk, long timeout)
+
+ cleanup:
+ /* orphan all the subflows */
+- inet_csk(sk)->icsk_mtup.probe_timestamp = tcp_jiffies32;
+ mptcp_for_each_subflow(msk, subflow) {
+ struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
+ bool slow = lock_sock_fast_nested(ssk);
+@@ -3024,7 +3022,7 @@ bool __mptcp_close(struct sock *sk, long timeout)
+ __mptcp_destroy_sock(sk);
+ do_cancel_work = true;
+ } else {
+- mptcp_reset_tout_timer(msk, 0);
++ mptcp_start_tout_timer(sk);
+ }
+
+ return do_cancel_work;
+@@ -3088,7 +3086,7 @@ static int mptcp_disconnect(struct sock *sk, int flags)
+ inet_sk_state_store(sk, TCP_CLOSE);
+
+ mptcp_stop_rtx_timer(sk);
+- sk_stop_timer(sk, &sk->sk_timer);
++ mptcp_stop_tout_timer(sk);
+
+ if (msk->token)
+ mptcp_event(MPTCP_EVENT_CLOSED, msk, NULL, GFP_KERNEL);
+diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
+index 4e31b5cf48299..0a2d9d3df522e 100644
+--- a/net/mptcp/protocol.h
++++ b/net/mptcp/protocol.h
+@@ -700,6 +700,28 @@ void mptcp_get_options(const struct sk_buff *skb,
+ void mptcp_finish_connect(struct sock *sk);
+ void __mptcp_set_connected(struct sock *sk);
+ void mptcp_reset_tout_timer(struct mptcp_sock *msk, unsigned long fail_tout);
++
++static inline void mptcp_stop_tout_timer(struct sock *sk)
++{
++ if (!inet_csk(sk)->icsk_mtup.probe_timestamp)
++ return;
++
++ sk_stop_timer(sk, &sk->sk_timer);
++ inet_csk(sk)->icsk_mtup.probe_timestamp = 0;
++}
++
++static inline void mptcp_set_close_tout(struct sock *sk, unsigned long tout)
++{
++ /* avoid 0 timestamp, as that means no close timeout */
++ inet_csk(sk)->icsk_mtup.probe_timestamp = tout ? : 1;
++}
++
++static inline void mptcp_start_tout_timer(struct sock *sk)
++{
++ mptcp_set_close_tout(sk, tcp_jiffies32);
++ mptcp_reset_tout_timer(mptcp_sk(sk), 0);
++}
++
+ static inline bool mptcp_is_fully_established(struct sock *sk)
+ {
+ return inet_sk_state_load(sk) == TCP_ESTABLISHED &&
+diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
+index 0506d33177f3d..40ac67b854074 100644
+--- a/net/mptcp/subflow.c
++++ b/net/mptcp/subflow.c
+@@ -1552,6 +1552,7 @@ int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_addr_info *loc,
+ mptcp_sock_graft(ssk, sk->sk_socket);
+ iput(SOCK_INODE(sf));
+ WRITE_ONCE(msk->allow_infinite_fallback, false);
++ mptcp_stop_tout_timer(sk);
+ return 0;
+
+ failed_unlink:
+--
+2.40.1
+
--- /dev/null
+From 93b36859e5aae1d636bcbf0dff13bf760a12593b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Aug 2023 17:57:27 +0200
+Subject: mptcp: Remove unnecessary test for __mptcp_init_sock()
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit e263691773cd67d7c824eeee8b802f50c6e0c118 ]
+
+__mptcp_init_sock() always returns 0 because mptcp_init_sock() used
+to return the value directly.
+
+But after commit 18b683bff89d ("mptcp: queue data for mptcp level
+retransmission"), __mptcp_init_sock() need not return value anymore.
+
+Let's remove the unnecessary test for __mptcp_init_sock() and make
+it return void.
+
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
+Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 27e5ccc2d5a5 ("mptcp: fix dangling connection hang-up")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mptcp/protocol.c | 9 ++-------
+ 1 file changed, 2 insertions(+), 7 deletions(-)
+
+diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
+index 6947b4b2519c9..0aae76f1465b8 100644
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -2710,7 +2710,7 @@ static void mptcp_worker(struct work_struct *work)
+ sock_put(sk);
+ }
+
+-static int __mptcp_init_sock(struct sock *sk)
++static void __mptcp_init_sock(struct sock *sk)
+ {
+ struct mptcp_sock *msk = mptcp_sk(sk);
+
+@@ -2737,8 +2737,6 @@ static int __mptcp_init_sock(struct sock *sk)
+ /* re-use the csk retrans timer for MPTCP-level retrans */
+ timer_setup(&msk->sk.icsk_retransmit_timer, mptcp_retransmit_timer, 0);
+ timer_setup(&sk->sk_timer, mptcp_timeout_timer, 0);
+-
+- return 0;
+ }
+
+ static void mptcp_ca_reset(struct sock *sk)
+@@ -2756,11 +2754,8 @@ static void mptcp_ca_reset(struct sock *sk)
+ static int mptcp_init_sock(struct sock *sk)
+ {
+ struct net *net = sock_net(sk);
+- int ret;
+
+- ret = __mptcp_init_sock(sk);
+- if (ret)
+- return ret;
++ __mptcp_init_sock(sk);
+
+ if (!mptcp_is_enabled(net))
+ return -ENOPROTOOPT;
+--
+2.40.1
+
--- /dev/null
+From c6282c64ad6465a60cbf840926c938dbf002db2f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 16 Sep 2023 12:52:48 +0200
+Subject: mptcp: rename timer related helper to less confusing names
+
+From: Paolo Abeni <pabeni@redhat.com>
+
+[ Upstream commit f6909dc1c1f4452879278128012da6c76bc186a5 ]
+
+The msk socket uses to different timeout to track close related
+events and retransmissions. The existing helpers do not indicate
+clearly which timer they actually touch, making the related code
+quite confusing.
+
+Change the existing helpers name to avoid such confusion. No
+functional change intended.
+
+This patch is linked to the next one ("mptcp: fix dangling connection
+hang-up"). The two patches are supposed to be backported together.
+
+Cc: stable@vger.kernel.org # v5.11+
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
+Reviewed-by: Mat Martineau <martineau@kernel.org>
+Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 27e5ccc2d5a5 ("mptcp: fix dangling connection hang-up")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mptcp/protocol.c | 42 +++++++++++++++++++++---------------------
+ net/mptcp/protocol.h | 2 +-
+ net/mptcp/subflow.c | 2 +-
+ 3 files changed, 23 insertions(+), 23 deletions(-)
+
+diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
+index 0aae76f1465b8..3c85b4c107b2a 100644
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -407,7 +407,7 @@ static bool __mptcp_move_skb(struct mptcp_sock *msk, struct sock *ssk,
+ return false;
+ }
+
+-static void mptcp_stop_timer(struct sock *sk)
++static void mptcp_stop_rtx_timer(struct sock *sk)
+ {
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+@@ -913,12 +913,12 @@ static void __mptcp_flush_join_list(struct sock *sk, struct list_head *join_list
+ }
+ }
+
+-static bool mptcp_timer_pending(struct sock *sk)
++static bool mptcp_rtx_timer_pending(struct sock *sk)
+ {
+ return timer_pending(&inet_csk(sk)->icsk_retransmit_timer);
+ }
+
+-static void mptcp_reset_timer(struct sock *sk)
++static void mptcp_reset_rtx_timer(struct sock *sk)
+ {
+ struct inet_connection_sock *icsk = inet_csk(sk);
+ unsigned long tout;
+@@ -1052,10 +1052,10 @@ static void __mptcp_clean_una(struct sock *sk)
+ out:
+ if (snd_una == READ_ONCE(msk->snd_nxt) &&
+ snd_una == READ_ONCE(msk->write_seq)) {
+- if (mptcp_timer_pending(sk) && !mptcp_data_fin_enabled(msk))
+- mptcp_stop_timer(sk);
++ if (mptcp_rtx_timer_pending(sk) && !mptcp_data_fin_enabled(msk))
++ mptcp_stop_rtx_timer(sk);
+ } else {
+- mptcp_reset_timer(sk);
++ mptcp_reset_rtx_timer(sk);
+ }
+ }
+
+@@ -1606,8 +1606,8 @@ void __mptcp_push_pending(struct sock *sk, unsigned int flags)
+
+ out:
+ /* ensure the rtx timer is running */
+- if (!mptcp_timer_pending(sk))
+- mptcp_reset_timer(sk);
++ if (!mptcp_rtx_timer_pending(sk))
++ mptcp_reset_rtx_timer(sk);
+ if (do_check_data_fin)
+ mptcp_check_send_data_fin(sk);
+ }
+@@ -1663,8 +1663,8 @@ static void __mptcp_subflow_push_pending(struct sock *sk, struct sock *ssk, bool
+ if (copied) {
+ tcp_push(ssk, 0, info.mss_now, tcp_sk(ssk)->nonagle,
+ info.size_goal);
+- if (!mptcp_timer_pending(sk))
+- mptcp_reset_timer(sk);
++ if (!mptcp_rtx_timer_pending(sk))
++ mptcp_reset_rtx_timer(sk);
+
+ if (msk->snd_data_fin_enable &&
+ msk->snd_nxt + 1 == msk->write_seq)
+@@ -2235,7 +2235,7 @@ static void mptcp_retransmit_timer(struct timer_list *t)
+ sock_put(sk);
+ }
+
+-static void mptcp_timeout_timer(struct timer_list *t)
++static void mptcp_tout_timer(struct timer_list *t)
+ {
+ struct sock *sk = from_timer(sk, t, sk_timer);
+
+@@ -2607,14 +2607,14 @@ static void __mptcp_retrans(struct sock *sk)
+ reset_timer:
+ mptcp_check_and_set_pending(sk);
+
+- if (!mptcp_timer_pending(sk))
+- mptcp_reset_timer(sk);
++ if (!mptcp_rtx_timer_pending(sk))
++ mptcp_reset_rtx_timer(sk);
+ }
+
+ /* schedule the timeout timer for the relevant event: either close timeout
+ * or mp_fail timeout. The close timeout takes precedence on the mp_fail one
+ */
+-void mptcp_reset_timeout(struct mptcp_sock *msk, unsigned long fail_tout)
++void mptcp_reset_tout_timer(struct mptcp_sock *msk, unsigned long fail_tout)
+ {
+ struct sock *sk = (struct sock *)msk;
+ unsigned long timeout, close_timeout;
+@@ -2647,7 +2647,7 @@ static void mptcp_mp_fail_no_response(struct mptcp_sock *msk)
+ WRITE_ONCE(mptcp_subflow_ctx(ssk)->fail_tout, 0);
+ unlock_sock_fast(ssk, slow);
+
+- mptcp_reset_timeout(msk, 0);
++ mptcp_reset_tout_timer(msk, 0);
+ }
+
+ static void mptcp_do_fastclose(struct sock *sk)
+@@ -2736,7 +2736,7 @@ static void __mptcp_init_sock(struct sock *sk)
+
+ /* re-use the csk retrans timer for MPTCP-level retrans */
+ timer_setup(&msk->sk.icsk_retransmit_timer, mptcp_retransmit_timer, 0);
+- timer_setup(&sk->sk_timer, mptcp_timeout_timer, 0);
++ timer_setup(&sk->sk_timer, mptcp_tout_timer, 0);
+ }
+
+ static void mptcp_ca_reset(struct sock *sk)
+@@ -2821,8 +2821,8 @@ void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how)
+ } else {
+ pr_debug("Sending DATA_FIN on subflow %p", ssk);
+ tcp_send_ack(ssk);
+- if (!mptcp_timer_pending(sk))
+- mptcp_reset_timer(sk);
++ if (!mptcp_rtx_timer_pending(sk))
++ mptcp_reset_rtx_timer(sk);
+ }
+ break;
+ }
+@@ -2905,7 +2905,7 @@ static void __mptcp_destroy_sock(struct sock *sk)
+
+ might_sleep();
+
+- mptcp_stop_timer(sk);
++ mptcp_stop_rtx_timer(sk);
+ sk_stop_timer(sk, &sk->sk_timer);
+ msk->pm.status = 0;
+
+@@ -3024,7 +3024,7 @@ bool __mptcp_close(struct sock *sk, long timeout)
+ __mptcp_destroy_sock(sk);
+ do_cancel_work = true;
+ } else {
+- mptcp_reset_timeout(msk, 0);
++ mptcp_reset_tout_timer(msk, 0);
+ }
+
+ return do_cancel_work;
+@@ -3087,7 +3087,7 @@ static int mptcp_disconnect(struct sock *sk, int flags)
+ mptcp_check_listen_stop(sk);
+ inet_sk_state_store(sk, TCP_CLOSE);
+
+- mptcp_stop_timer(sk);
++ mptcp_stop_rtx_timer(sk);
+ sk_stop_timer(sk, &sk->sk_timer);
+
+ if (msk->token)
+diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
+index ba2a873a4d2e6..4e31b5cf48299 100644
+--- a/net/mptcp/protocol.h
++++ b/net/mptcp/protocol.h
+@@ -699,7 +699,7 @@ void mptcp_get_options(const struct sk_buff *skb,
+
+ void mptcp_finish_connect(struct sock *sk);
+ void __mptcp_set_connected(struct sock *sk);
+-void mptcp_reset_timeout(struct mptcp_sock *msk, unsigned long fail_tout);
++void mptcp_reset_tout_timer(struct mptcp_sock *msk, unsigned long fail_tout);
+ static inline bool mptcp_is_fully_established(struct sock *sk)
+ {
+ return inet_sk_state_load(sk) == TCP_ESTABLISHED &&
+diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c
+index c7bd99b8e7b7a..0506d33177f3d 100644
+--- a/net/mptcp/subflow.c
++++ b/net/mptcp/subflow.c
+@@ -1226,7 +1226,7 @@ static void mptcp_subflow_fail(struct mptcp_sock *msk, struct sock *ssk)
+ WRITE_ONCE(subflow->fail_tout, fail_tout);
+ tcp_send_ack(ssk);
+
+- mptcp_reset_timeout(msk, subflow->fail_tout);
++ mptcp_reset_tout_timer(msk, subflow->fail_tout);
+ }
+
+ static bool subflow_check_data_avail(struct sock *ssk)
+--
+2.40.1
+
--- /dev/null
+From 6baea050e37d2c14a86c1f2715caa919b73e5352 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Aug 2023 08:30:41 -0700
+Subject: scsi: core: Improve type safety of scsi_rescan_device()
+
+From: Bart Van Assche <bvanassche@acm.org>
+
+[ Upstream commit 79519528a180c64a90863db2ce70887de6c49d16 ]
+
+Most callers of scsi_rescan_device() have the scsi_device pointer readily
+available. Pass a struct scsi_device pointer to scsi_rescan_device()
+instead of a struct device pointer. This change prevents that a pointer to
+another struct device would be passed accidentally to scsi_rescan_device().
+
+Remove the scsi_rescan_device() declaration from the scsi_priv.h header
+file since it duplicates the declaration in <scsi/scsi_host.h>.
+
+Reviewed-by: Hannes Reinecke <hare@suse.de>
+Reviewed-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
+Reviewed-by: John Garry <john.g.garry@oracle.com>
+Cc: Mike Christie <michael.christie@oracle.com>
+Cc: Ming Lei <ming.lei@redhat.com>
+Signed-off-by: Bart Van Assche <bvanassche@acm.org>
+Link: https://lore.kernel.org/r/20230822153043.4046244-1-bvanassche@acm.org
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Stable-dep-of: 8b4d9469d0b0 ("ata: libata-scsi: Fix delayed scsi_rescan_device() execution")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/libata-scsi.c | 2 +-
+ drivers/scsi/aacraid/commsup.c | 2 +-
+ drivers/scsi/mvumi.c | 2 +-
+ drivers/scsi/scsi_lib.c | 2 +-
+ drivers/scsi/scsi_priv.h | 1 -
+ drivers/scsi/scsi_scan.c | 4 ++--
+ drivers/scsi/scsi_sysfs.c | 4 ++--
+ drivers/scsi/smartpqi/smartpqi_init.c | 2 +-
+ drivers/scsi/storvsc_drv.c | 2 +-
+ drivers/scsi/virtio_scsi.c | 2 +-
+ include/scsi/scsi_host.h | 2 +-
+ 11 files changed, 12 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index 702812285d8f0..22d7c26297889 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -4930,7 +4930,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
+ }
+
+ spin_unlock_irqrestore(ap->lock, flags);
+- scsi_rescan_device(&(sdev->sdev_gendev));
++ scsi_rescan_device(sdev);
+ scsi_device_put(sdev);
+ spin_lock_irqsave(ap->lock, flags);
+ }
+diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
+index 3f062e4013ab6..013a9a334972e 100644
+--- a/drivers/scsi/aacraid/commsup.c
++++ b/drivers/scsi/aacraid/commsup.c
+@@ -1451,7 +1451,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
+ #endif
+ break;
+ }
+- scsi_rescan_device(&device->sdev_gendev);
++ scsi_rescan_device(device);
+ break;
+
+ default:
+diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c
+index 73aa7059b5569..6cfbac518085d 100644
+--- a/drivers/scsi/mvumi.c
++++ b/drivers/scsi/mvumi.c
+@@ -1500,7 +1500,7 @@ static void mvumi_rescan_devices(struct mvumi_hba *mhba, int id)
+
+ sdev = scsi_device_lookup(mhba->shost, 0, id, 0);
+ if (sdev) {
+- scsi_rescan_device(&sdev->sdev_gendev);
++ scsi_rescan_device(sdev);
+ scsi_device_put(sdev);
+ }
+ }
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index ad9afae49544a..ca5eb058d5c7e 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -2458,7 +2458,7 @@ static void scsi_evt_emit(struct scsi_device *sdev, struct scsi_event *evt)
+ envp[idx++] = "SDEV_MEDIA_CHANGE=1";
+ break;
+ case SDEV_EVT_INQUIRY_CHANGE_REPORTED:
+- scsi_rescan_device(&sdev->sdev_gendev);
++ scsi_rescan_device(sdev);
+ envp[idx++] = "SDEV_UA=INQUIRY_DATA_HAS_CHANGED";
+ break;
+ case SDEV_EVT_CAPACITY_CHANGE_REPORTED:
+diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
+index f42388ecb0248..65c993c979095 100644
+--- a/drivers/scsi/scsi_priv.h
++++ b/drivers/scsi/scsi_priv.h
+@@ -138,7 +138,6 @@ extern int scsi_complete_async_scans(void);
+ extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int,
+ unsigned int, u64, enum scsi_scan_mode);
+ extern void scsi_forget_host(struct Scsi_Host *);
+-extern void scsi_rescan_device(struct device *);
+
+ /* scsi_sysctl.c */
+ #ifdef CONFIG_SYSCTL
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 97669657a9976..eaa972bee6c00 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -1619,9 +1619,9 @@ int scsi_add_device(struct Scsi_Host *host, uint channel,
+ }
+ EXPORT_SYMBOL(scsi_add_device);
+
+-void scsi_rescan_device(struct device *dev)
++void scsi_rescan_device(struct scsi_device *sdev)
+ {
+- struct scsi_device *sdev = to_scsi_device(dev);
++ struct device *dev = &sdev->sdev_gendev;
+
+ device_lock(dev);
+
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index 60317676e45f1..24f6eefb68030 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -747,7 +747,7 @@ static ssize_t
+ store_rescan_field (struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+ {
+- scsi_rescan_device(dev);
++ scsi_rescan_device(to_scsi_device(dev));
+ return count;
+ }
+ static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
+@@ -840,7 +840,7 @@ store_state_field(struct device *dev, struct device_attribute *attr,
+ * waiting for pending I/O to finish.
+ */
+ blk_mq_run_hw_queues(sdev->request_queue, true);
+- scsi_rescan_device(dev);
++ scsi_rescan_device(sdev);
+ }
+
+ return ret == 0 ? count : -EINVAL;
+diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
+index 6aaaa7ebca377..ed694d9399648 100644
+--- a/drivers/scsi/smartpqi/smartpqi_init.c
++++ b/drivers/scsi/smartpqi/smartpqi_init.c
+@@ -2257,7 +2257,7 @@ static void pqi_update_device_list(struct pqi_ctrl_info *ctrl_info,
+ device->advertised_queue_depth = device->queue_depth;
+ scsi_change_queue_depth(device->sdev, device->advertised_queue_depth);
+ if (device->rescan) {
+- scsi_rescan_device(&device->sdev->sdev_gendev);
++ scsi_rescan_device(device->sdev);
+ device->rescan = false;
+ }
+ }
+diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
+index 047ffaf7d42a9..a80a9e27ff9ee 100644
+--- a/drivers/scsi/storvsc_drv.c
++++ b/drivers/scsi/storvsc_drv.c
+@@ -472,7 +472,7 @@ static void storvsc_device_scan(struct work_struct *work)
+ sdev = scsi_device_lookup(wrk->host, 0, wrk->tgt_id, wrk->lun);
+ if (!sdev)
+ goto done;
+- scsi_rescan_device(&sdev->sdev_gendev);
++ scsi_rescan_device(sdev);
+ scsi_device_put(sdev);
+
+ done:
+diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
+index bd5633667d015..9d1bdcdc13312 100644
+--- a/drivers/scsi/virtio_scsi.c
++++ b/drivers/scsi/virtio_scsi.c
+@@ -325,7 +325,7 @@ static void virtscsi_handle_param_change(struct virtio_scsi *vscsi,
+ /* Handle "Parameters changed", "Mode parameters changed", and
+ "Capacity data has changed". */
+ if (asc == 0x2a && (ascq == 0x00 || ascq == 0x01 || ascq == 0x09))
+- scsi_rescan_device(&sdev->sdev_gendev);
++ scsi_rescan_device(sdev);
+
+ scsi_device_put(sdev);
+ }
+diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
+index a2b8d30c4c803..49f768d0ff370 100644
+--- a/include/scsi/scsi_host.h
++++ b/include/scsi/scsi_host.h
+@@ -764,7 +764,7 @@ scsi_template_proc_dir(const struct scsi_host_template *sht);
+ #define scsi_template_proc_dir(sht) NULL
+ #endif
+ extern void scsi_scan_host(struct Scsi_Host *);
+-extern void scsi_rescan_device(struct device *);
++extern void scsi_rescan_device(struct scsi_device *);
+ extern void scsi_remove_host(struct Scsi_Host *);
+ extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *);
+ extern int scsi_host_busy(struct Scsi_Host *shost);
+--
+2.40.1
+
--- /dev/null
+From 0c62f5a5665b1cb55824c1cf96f44be41b1ba176 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 15:00:13 +0900
+Subject: scsi: Do not attempt to rescan suspended devices
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+[ Upstream commit ff48b37802e5c134e2dfc4d091f10b2eb5065a72 ]
+
+scsi_rescan_device() takes a scsi device lock before executing a device
+handler and device driver rescan methods. Waiting for the completion of
+any command issued to the device by these methods will thus be done with
+the device lock held. As a result, there is a risk of deadlocking within
+the power management code if scsi_rescan_device() is called to handle a
+device resume with the associated scsi device not yet resumed.
+
+Avoid such situation by checking that the target scsi device is in the
+running state, that is, fully capable of executing commands, before
+proceeding with the rescan and bailout returning -EWOULDBLOCK otherwise.
+With this error return, the caller can retry rescaning the device after
+a delay.
+
+The state check is done with the device lock held and is thus safe
+against incoming suspend power management operations.
+
+Fixes: 6aa0365a3c85 ("ata: libata-scsi: Avoid deadlock on rescan after device resume")
+Cc: stable@vger.kernel.org
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: Hannes Reinecke <hare@suse.de>
+Reviewed-by: Niklas Cassel <niklas.cassel@wdc.com>
+Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Stable-dep-of: 8b4d9469d0b0 ("ata: libata-scsi: Fix delayed scsi_rescan_device() execution")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/scsi_scan.c | 18 +++++++++++++++++-
+ include/scsi/scsi_host.h | 2 +-
+ 2 files changed, 18 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index eaa972bee6c00..902655d759476 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -1619,12 +1619,24 @@ int scsi_add_device(struct Scsi_Host *host, uint channel,
+ }
+ EXPORT_SYMBOL(scsi_add_device);
+
+-void scsi_rescan_device(struct scsi_device *sdev)
++int scsi_rescan_device(struct scsi_device *sdev)
+ {
+ struct device *dev = &sdev->sdev_gendev;
++ int ret = 0;
+
+ device_lock(dev);
+
++ /*
++ * Bail out if the device is not running. Otherwise, the rescan may
++ * block waiting for commands to be executed, with us holding the
++ * device lock. This can result in a potential deadlock in the power
++ * management core code when system resume is on-going.
++ */
++ if (sdev->sdev_state != SDEV_RUNNING) {
++ ret = -EWOULDBLOCK;
++ goto unlock;
++ }
++
+ scsi_attach_vpd(sdev);
+ scsi_cdl_check(sdev);
+
+@@ -1638,7 +1650,11 @@ void scsi_rescan_device(struct scsi_device *sdev)
+ drv->rescan(dev);
+ module_put(dev->driver->owner);
+ }
++
++unlock:
+ device_unlock(dev);
++
++ return ret;
+ }
+ EXPORT_SYMBOL(scsi_rescan_device);
+
+diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
+index 49f768d0ff370..4c2dc8150c6d7 100644
+--- a/include/scsi/scsi_host.h
++++ b/include/scsi/scsi_host.h
+@@ -764,7 +764,7 @@ scsi_template_proc_dir(const struct scsi_host_template *sht);
+ #define scsi_template_proc_dir(sht) NULL
+ #endif
+ extern void scsi_scan_host(struct Scsi_Host *);
+-extern void scsi_rescan_device(struct scsi_device *);
++extern int scsi_rescan_device(struct scsi_device *sdev);
+ extern void scsi_remove_host(struct Scsi_Host *);
+ extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *);
+ extern int scsi_host_busy(struct Scsi_Host *shost);
+--
+2.40.1
+
--- /dev/null
+alsa-hda-tas2781-add-tas2781-hda-driver.patch
+alsa-hda-realtek-add-quirk-for-hp-victus-16-d1xxx-to.patch
+alsa-hda-realtek-add-quirk-for-mute-leds-on-hp-envy-.patch
+alsa-hda-realtek-alc287-i2s-speaker-platform-support.patch
+alsa-hda-realtek-alc287-realtek-i2s-speaker-platform.patch
+asoc-soc-utils-export-snd_soc_dai_is_dummy-symbol.patch
+asoc-tegra-fix-redundant-plla-and-plla_out0-updates.patch
+maple_tree-add-mas_is_active-to-detect-in-tree-walks.patch
+mptcp-remove-unnecessary-test-for-__mptcp_init_sock.patch
+mptcp-rename-timer-related-helper-to-less-confusing-.patch
+mptcp-fix-dangling-connection-hang-up.patch
+scsi-core-improve-type-safety-of-scsi_rescan_device.patch
+scsi-do-not-attempt-to-rescan-suspended-devices.patch
+ata-libata-scsi-fix-delayed-scsi_rescan_device-execu.patch
+btrfs-remove-btrfs_writepage_endio_finish_ordered.patch
+btrfs-remove-end_extent_writepage.patch
+btrfs-don-t-clear-uptodate-on-write-errors.patch
+arm64-add-hwcap-for-feat_hbc-hinted-conditional-bran.patch
+arm64-cpufeature-fix-clrbhb-and-bc-detection.patch