From: Sasha Levin Date: Sat, 14 Jan 2023 14:23:27 +0000 (-0500) Subject: Fixes for 4.19 X-Git-Tag: v4.14.303~63^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3aff4aa526e9287b5c490be5373894490251ed6a;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 4.19 Signed-off-by: Sasha Levin --- diff --git a/queue-4.19/add-acer-aspire-ethos-8951g-model-quirk.patch b/queue-4.19/add-acer-aspire-ethos-8951g-model-quirk.patch new file mode 100644 index 00000000000..211e231c0f5 --- /dev/null +++ b/queue-4.19/add-acer-aspire-ethos-8951g-model-quirk.patch @@ -0,0 +1,160 @@ +From 838fb58f173edcce0d175049aac2bb54ac4c481f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 6 Sep 2019 11:33:43 +0200 +Subject: Add Acer Aspire Ethos 8951G model quirk + +From: Sergey Bostandzhyan + +[ Upstream commit 00066e9733f629e536f6b7957de2ce11a85fe15a ] + +This notebook has 6 built in speakers for 5.1 surround support, however +only two got autodetected and have also not been assigned correctly. + +This patch enables all speakers and also fixes muting when headphones are +plugged in. + +The speaker layout is as follows: + +pin 0x15 Front Left / Front Right +pin 0x18 Front Center / Subwoofer +pin 0x1b Rear Left / Rear Right (Surround) + +The quirk will be enabled automatically on this hardware, but can also be +activated manually via the model=aspire-ethos module parameter. + +Caveat: pin 0x1b is shared between headphones jack and surround speakers. +When headphones are plugged in, the surround speakers get muted +automatically by the hardware, however all other speakers remain +unmuted. Currently it's not possible to make use of the generic automute +function in the driver, because such shared pins are not supported. + +If we would change the pin settings to identify the pin as headphones, +the surround channel and thus the ability to select 5.1 profiles would +get lost. + +This quirk solves the above problem by monitoring jack state of 0x1b and +by connecting/disconnecting all remaining speaker pins when something +gets plugged in or unplugged from the headphones jack port. + +Signed-off-by: Sergey Bostandzhyan +Link: https://lore.kernel.org/r/20190906093343.GA7640@xn--80adja5bqm.su +Signed-off-by: Takashi Iwai +Stable-dep-of: 4bf5bf54476d ("ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB") +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 71 +++++++++++++++++++++++++++++++++++ + 1 file changed, 71 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 9670db6ad1e1..fe17fb8d7f67 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -8510,6 +8510,45 @@ static void alc662_fixup_usi_headset_mic(struct hda_codec *codec, + } + } + ++static void alc662_aspire_ethos_mute_speakers(struct hda_codec *codec, ++ struct hda_jack_callback *cb) ++{ ++ /* surround speakers at 0x1b already get muted automatically when ++ * headphones are plugged in, but we have to mute/unmute the remaining ++ * channels manually: ++ * 0x15 - front left/front right ++ * 0x18 - front center/ LFE ++ */ ++ if (snd_hda_jack_detect_state(codec, 0x1b) == HDA_JACK_PRESENT) { ++ snd_hda_set_pin_ctl_cache(codec, 0x15, 0); ++ snd_hda_set_pin_ctl_cache(codec, 0x18, 0); ++ } else { ++ snd_hda_set_pin_ctl_cache(codec, 0x15, PIN_OUT); ++ snd_hda_set_pin_ctl_cache(codec, 0x18, PIN_OUT); ++ } ++} ++ ++static void alc662_fixup_aspire_ethos_hp(struct hda_codec *codec, ++ const struct hda_fixup *fix, int action) ++{ ++ /* Pin 0x1b: shared headphones jack and surround speakers */ ++ if (!is_jack_detectable(codec, 0x1b)) ++ return; ++ ++ switch (action) { ++ case HDA_FIXUP_ACT_PRE_PROBE: ++ snd_hda_jack_detect_enable_callback(codec, 0x1b, ++ alc662_aspire_ethos_mute_speakers); ++ break; ++ case HDA_FIXUP_ACT_INIT: ++ /* Make sure to start in a correct state, i.e. if ++ * headphones have been plugged in before powering up the system ++ */ ++ alc662_aspire_ethos_mute_speakers(codec, NULL); ++ break; ++ } ++} ++ + static struct coef_fw alc668_coefs[] = { + WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0), + WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80), +@@ -8581,6 +8620,9 @@ enum { + ALC662_FIXUP_USI_FUNC, + ALC662_FIXUP_USI_HEADSET_MODE, + ALC662_FIXUP_LENOVO_MULTI_CODECS, ++ ALC669_FIXUP_ACER_ASPIRE_ETHOS, ++ ALC669_FIXUP_ACER_ASPIRE_ETHOS_SUBWOOFER, ++ ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET, + }; + + static const struct hda_fixup alc662_fixups[] = { +@@ -8907,6 +8949,33 @@ static const struct hda_fixup alc662_fixups[] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc233_alc662_fixup_lenovo_dual_codecs, + }, ++ [ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc662_fixup_aspire_ethos_hp, ++ }, ++ [ALC669_FIXUP_ACER_ASPIRE_ETHOS_SUBWOOFER] = { ++ .type = HDA_FIXUP_VERBS, ++ /* subwoofer needs an extra GPIO setting to become audible */ ++ .v.verbs = (const struct hda_verb[]) { ++ {0x01, AC_VERB_SET_GPIO_MASK, 0x02}, ++ {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02}, ++ {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET ++ }, ++ [ALC669_FIXUP_ACER_ASPIRE_ETHOS] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x15, 0x92130110 }, /* front speakers */ ++ { 0x18, 0x99130111 }, /* center/subwoofer */ ++ { 0x1b, 0x11130012 }, /* surround plus jack for HP */ ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC669_FIXUP_ACER_ASPIRE_ETHOS_SUBWOOFER ++ }, + }; + + static const struct snd_pci_quirk alc662_fixup_tbl[] = { +@@ -8952,6 +9021,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68), + SND_PCI_QUIRK(0x1b0a, 0x01b8, "ACER Veriton", ALC662_FIXUP_ACER_VERITON), + SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T), ++ SND_PCI_QUIRK(0x1025, 0x0566, "Acer Aspire Ethos 8951G", ALC669_FIXUP_ACER_ASPIRE_ETHOS), + + #if 0 + /* Below is a quirk table taken from the old code. +@@ -9044,6 +9114,7 @@ static const struct hda_model_fixup alc662_fixup_models[] = { + {.id = ALC892_FIXUP_ASROCK_MOBO, .name = "asrock-mobo"}, + {.id = ALC662_FIXUP_USI_HEADSET_MODE, .name = "usi-headset"}, + {.id = ALC662_FIXUP_LENOVO_MULTI_CODECS, .name = "dual-codecs"}, ++ {.id = ALC669_FIXUP_ACER_ASPIRE_ETHOS, .name = "aspire-ethos"}, + {} + }; + +-- +2.35.1 + diff --git a/queue-4.19/alsa-hda-hdmi-fix-failures-at-pcm-open-on-intel-icl-.patch b/queue-4.19/alsa-hda-hdmi-fix-failures-at-pcm-open-on-intel-icl-.patch new file mode 100644 index 00000000000..31ec5a7b958 --- /dev/null +++ b/queue-4.19/alsa-hda-hdmi-fix-failures-at-pcm-open-on-intel-icl-.patch @@ -0,0 +1,105 @@ +From 4a121175adb0c0db346f02cc9eb534800b95feee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 3 Jul 2020 18:38:17 +0300 +Subject: ALSA: hda/hdmi: fix failures at PCM open on Intel ICL and later + +From: Kai Vehmanen + +[ Upstream commit 56275036d8185f92eceac7479d48b858ee3dab84 ] + +When HDMI PCM devices are opened in a specific order, with at least one +HDMI/DP receiver connected, ALSA PCM open fails to -EBUSY on the +connected monitor, on recent Intel platforms (ICL/JSL and newer). While +this is not a typical sequence, at least Pulseaudio does this every time +when it is started, to discover the available PCMs. + +The rootcause is an invalid assumption in hdmi_add_pin(), where the +total number of converters is assumed to be known at the time the +function is called. On older Intel platforms this held true, but after +ICL/JSL, the order how pins and converters are in the subnode list as +returned by snd_hda_get_sub_nodes(), was changed. As a result, +information for some converters was not stored to per_pin->mux_nids. +And this means some pins cannot be connected to all converters, and +application instead gets -EBUSY instead at open. + +The assumption that converters are always before pins in the subnode +list, is not really a valid one. Fix the problem in hdmi_parse_codec() +by introducing separate loops for discovering converters and pins. + +BugLink: https://github.com/thesofproject/linux/issues/1978 +BugLink: https://github.com/thesofproject/linux/issues/2216 +BugLink: https://github.com/thesofproject/linux/issues/2217 +Reviewed-by: Ranjani Sridharan +Reviewed-by: Pierre-Louis Bossart +Signed-off-by: Kai Vehmanen +Link: https://lore.kernel.org/r/20200703153818.2808592-1-kai.vehmanen@linux.intel.com +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_hdmi.c | 36 +++++++++++++++++++++++------------- + 1 file changed, 23 insertions(+), 13 deletions(-) + +diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c +index cbd5118570fd..be9f1c4295cd 100644 +--- a/sound/pci/hda/patch_hdmi.c ++++ b/sound/pci/hda/patch_hdmi.c +@@ -1804,33 +1804,43 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) + + static int hdmi_parse_codec(struct hda_codec *codec) + { +- hda_nid_t nid; ++ hda_nid_t start_nid; ++ unsigned int caps; + int i, nodes; + +- nodes = snd_hda_get_sub_nodes(codec, codec->core.afg, &nid); +- if (!nid || nodes < 0) { ++ nodes = snd_hda_get_sub_nodes(codec, codec->core.afg, &start_nid); ++ if (!start_nid || nodes < 0) { + codec_warn(codec, "HDMI: failed to get afg sub nodes\n"); + return -EINVAL; + } + +- for (i = 0; i < nodes; i++, nid++) { +- unsigned int caps; +- unsigned int type; ++ /* ++ * hdmi_add_pin() assumes total amount of converters to ++ * be known, so first discover all converters ++ */ ++ for (i = 0; i < nodes; i++) { ++ hda_nid_t nid = start_nid + i; + + caps = get_wcaps(codec, nid); +- type = get_wcaps_type(caps); + + if (!(caps & AC_WCAP_DIGITAL)) + continue; + +- switch (type) { +- case AC_WID_AUD_OUT: ++ if (get_wcaps_type(caps) == AC_WID_AUD_OUT) + hdmi_add_cvt(codec, nid); +- break; +- case AC_WID_PIN: ++ } ++ ++ /* discover audio pins */ ++ for (i = 0; i < nodes; i++) { ++ hda_nid_t nid = start_nid + i; ++ ++ caps = get_wcaps(codec, nid); ++ ++ if (!(caps & AC_WCAP_DIGITAL)) ++ continue; ++ ++ if (get_wcaps_type(caps) == AC_WID_PIN) + hdmi_add_pin(codec, nid); +- break; +- } + } + + return 0; +-- +2.35.1 + diff --git a/queue-4.19/alsa-hda-realtek-add-headset-mic-support-for-lenovo-.patch b/queue-4.19/alsa-hda-realtek-add-headset-mic-support-for-lenovo-.patch new file mode 100644 index 00000000000..be2be4196a8 --- /dev/null +++ b/queue-4.19/alsa-hda-realtek-add-headset-mic-support-for-lenovo-.patch @@ -0,0 +1,98 @@ +From 0b4eb46f4710900534f2ed59e104c46e6d7d07d2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 23 Nov 2021 16:32:44 +0800 +Subject: ALSA: hda/realtek - Add headset Mic support for Lenovo ALC897 + platform + +From: Kailang Yang + +[ Upstream commit d7f32791a9fcf0dae8b073cdea9b79e29098c5f4 ] + +Lenovo ALC897 platform had headset Mic. +This patch enable supported headset Mic. + +Signed-off-by: Kailang Yang +Cc: +Link: https://lore.kernel.org/r/baab2c2536cb4cc18677a862c6f6d840@realtek.com +Signed-off-by: Takashi Iwai +Stable-dep-of: 4bf5bf54476d ("ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB") +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 40 +++++++++++++++++++++++++++++++++++ + 1 file changed, 40 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 566d5ea74c62..f0cf3e23d355 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -8572,6 +8572,27 @@ static void alc671_fixup_hp_headset_mic2(struct hda_codec *codec, + } + } + ++static void alc897_hp_automute_hook(struct hda_codec *codec, ++ struct hda_jack_callback *jack) ++{ ++ struct alc_spec *spec = codec->spec; ++ int vref; ++ ++ snd_hda_gen_hp_automute(codec, jack); ++ vref = spec->gen.hp_jack_present ? (PIN_HP | AC_PINCTL_VREF_100) : PIN_HP; ++ snd_hda_codec_write(codec, 0x1b, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, ++ vref); ++} ++ ++static void alc897_fixup_lenovo_headset_mic(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->gen.hp_automute_hook = alc897_hp_automute_hook; ++ } ++} ++ + static const struct coef_fw alc668_coefs[] = { + WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0), + WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80), +@@ -8652,6 +8673,8 @@ enum { + ALC668_FIXUP_ASUS_NO_HEADSET_MIC, + ALC668_FIXUP_HEADSET_MIC, + ALC668_FIXUP_MIC_DET_COEF, ++ ALC897_FIXUP_LENOVO_HEADSET_MIC, ++ ALC897_FIXUP_HEADSET_MIC_PIN, + }; + + static const struct hda_fixup alc662_fixups[] = { +@@ -9051,6 +9074,19 @@ static const struct hda_fixup alc662_fixups[] = { + {} + }, + }, ++ [ALC897_FIXUP_LENOVO_HEADSET_MIC] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc897_fixup_lenovo_headset_mic, ++ }, ++ [ALC897_FIXUP_HEADSET_MIC_PIN] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x1a, 0x03a11050 }, ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MIC ++ }, + }; + + static const struct snd_pci_quirk alc662_fixup_tbl[] = { +@@ -9094,6 +9130,10 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x14cd, 0x5003, "USI", ALC662_FIXUP_USI_HEADSET_MODE), + SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC662_FIXUP_LENOVO_MULTI_CODECS), ++ SND_PCI_QUIRK(0x17aa, 0x32ca, "Lenovo ThinkCentre M80", ALC897_FIXUP_HEADSET_MIC_PIN), ++ SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN), ++ SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN), ++ SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN), + SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO), +-- +2.35.1 + diff --git a/queue-4.19/alsa-hda-realtek-add-headset-mic-supported-for-hp-cp.patch b/queue-4.19/alsa-hda-realtek-add-headset-mic-supported-for-hp-cp.patch new file mode 100644 index 00000000000..3a3a0c33e65 --- /dev/null +++ b/queue-4.19/alsa-hda-realtek-add-headset-mic-supported-for-hp-cp.patch @@ -0,0 +1,99 @@ +From 50f5ff94cf283068f9d643d3276c129b3d60faf5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Jan 2020 14:04:01 +0800 +Subject: ALSA: hda/realtek - Add Headset Mic supported for HP cPC + +From: Kailang Yang + +[ Upstream commit 5af29028fd6db9438b5584ab7179710a0a22569d ] + +HP ALC671 need to support Headset Mic. + +Signed-off-by: Kailang Yang +Link: https://lore.kernel.org/r/06a9d2b176e14706976d6584cbe2d92a@realtek.com +Signed-off-by: Takashi Iwai +Stable-dep-of: 4bf5bf54476d ("ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB") +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 44 +++++++++++++++++++++++++++++++++++ + 1 file changed, 44 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 3abe30eec49a..375493d3807f 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -8549,6 +8549,29 @@ static void alc662_fixup_aspire_ethos_hp(struct hda_codec *codec, + } + } + ++static void alc671_fixup_hp_headset_mic2(struct hda_codec *codec, ++ const struct hda_fixup *fix, int action) ++{ ++ struct alc_spec *spec = codec->spec; ++ ++ static const struct hda_pintbl pincfgs[] = { ++ { 0x19, 0x02a11040 }, /* use as headset mic, with its own jack detect */ ++ { 0x1b, 0x0181304f }, ++ { } ++ }; ++ ++ switch (action) { ++ case HDA_FIXUP_ACT_PRE_PROBE: ++ spec->gen.mixer_nid = 0; ++ spec->parse_flags |= HDA_PINCFG_HEADSET_MIC; ++ snd_hda_apply_pincfgs(codec, pincfgs); ++ break; ++ case HDA_FIXUP_ACT_INIT: ++ alc_write_coef_idx(codec, 0x19, 0xa054); ++ break; ++ } ++} ++ + static const struct coef_fw alc668_coefs[] = { + WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0), + WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80), +@@ -8623,6 +8646,7 @@ enum { + ALC669_FIXUP_ACER_ASPIRE_ETHOS, + ALC669_FIXUP_ACER_ASPIRE_ETHOS_SUBWOOFER, + ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET, ++ ALC671_FIXUP_HP_HEADSET_MIC2, + }; + + static const struct hda_fixup alc662_fixups[] = { +@@ -8976,6 +9000,10 @@ static const struct hda_fixup alc662_fixups[] = { + .chained = true, + .chain_id = ALC669_FIXUP_ACER_ASPIRE_ETHOS_SUBWOOFER + }, ++ [ALC671_FIXUP_HP_HEADSET_MIC2] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc671_fixup_hp_headset_mic2, ++ }, + }; + + static const struct snd_pci_quirk alc662_fixup_tbl[] = { +@@ -9157,6 +9185,22 @@ static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = { + {0x12, 0x90a60130}, + {0x14, 0x90170110}, + {0x15, 0x0321101f}), ++ SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2, ++ {0x14, 0x01014010}, ++ {0x17, 0x90170150}, ++ {0x1b, 0x01813030}, ++ {0x21, 0x02211020}), ++ SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2, ++ {0x14, 0x01014010}, ++ {0x18, 0x01a19040}, ++ {0x1b, 0x01813030}, ++ {0x21, 0x02211020}), ++ SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2, ++ {0x14, 0x01014020}, ++ {0x17, 0x90170110}, ++ {0x18, 0x01a19050}, ++ {0x1b, 0x01813040}, ++ {0x21, 0x02211030}), + {} + }; + +-- +2.35.1 + diff --git a/queue-4.19/alsa-hda-realtek-add-quirk-for-lenovo-tianyi510pro-1.patch b/queue-4.19/alsa-hda-realtek-add-quirk-for-lenovo-tianyi510pro-1.patch new file mode 100644 index 00000000000..1d97ab999b1 --- /dev/null +++ b/queue-4.19/alsa-hda-realtek-add-quirk-for-lenovo-tianyi510pro-1.patch @@ -0,0 +1,84 @@ +From e71b599471f13a7c22ef65751c1c1257486ea353 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Dec 2022 21:32:18 +0800 +Subject: ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB + +From: Edward Pacman + +[ Upstream commit 4bf5bf54476dffe60e6b6d8d539f67309ff599e2 ] + +Lenovo TianYi510Pro-14IOB (17aa:3742) +require quirk for enabling headset-mic + +Signed-off-by: Edward Pacman +Cc: +Link: https://bugzilla.kernel.org/show_bug.cgi?id=216756 +Link: https://lore.kernel.org/r/20221207133218.18989-1-edward@edward-p.xyz +Signed-off-by: Takashi Iwai +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 0a2cf8ca2812..ed14772a8e6e 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -8593,6 +8593,17 @@ static void alc897_fixup_lenovo_headset_mic(struct hda_codec *codec, + } + } + ++static void alc897_fixup_lenovo_headset_mode(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->parse_flags |= HDA_PINCFG_HEADSET_MIC; ++ spec->gen.hp_automute_hook = alc897_hp_automute_hook; ++ } ++} ++ + static const struct coef_fw alc668_coefs[] = { + WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0), + WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80), +@@ -8676,6 +8687,8 @@ enum { + ALC897_FIXUP_LENOVO_HEADSET_MIC, + ALC897_FIXUP_HEADSET_MIC_PIN, + ALC897_FIXUP_HP_HSMIC_VERB, ++ ALC897_FIXUP_LENOVO_HEADSET_MODE, ++ ALC897_FIXUP_HEADSET_MIC_PIN2, + }; + + static const struct hda_fixup alc662_fixups[] = { +@@ -9095,6 +9108,19 @@ static const struct hda_fixup alc662_fixups[] = { + { } + }, + }, ++ [ALC897_FIXUP_LENOVO_HEADSET_MODE] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc897_fixup_lenovo_headset_mode, ++ }, ++ [ALC897_FIXUP_HEADSET_MIC_PIN2] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x1a, 0x01a11140 }, /* use as headset mic, without its own jack detect */ ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MODE ++ }, + }; + + static const struct snd_pci_quirk alc662_fixup_tbl[] = { +@@ -9143,6 +9169,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x17aa, 0x32cb, "Lenovo ThinkCentre M70", ALC897_FIXUP_HEADSET_MIC_PIN), + SND_PCI_QUIRK(0x17aa, 0x32cf, "Lenovo ThinkCentre M950", ALC897_FIXUP_HEADSET_MIC_PIN), + SND_PCI_QUIRK(0x17aa, 0x32f7, "Lenovo ThinkCentre M90", ALC897_FIXUP_HEADSET_MIC_PIN), ++ SND_PCI_QUIRK(0x17aa, 0x3742, "Lenovo TianYi510Pro-14IOB", ALC897_FIXUP_HEADSET_MIC_PIN2), + SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x1849, 0x5892, "ASRock B150M", ALC892_FIXUP_ASROCK_MOBO), +-- +2.35.1 + diff --git a/queue-4.19/alsa-hda-realtek-alc897-headset-mic-no-sound.patch b/queue-4.19/alsa-hda-realtek-alc897-headset-mic-no-sound.patch new file mode 100644 index 00000000000..13e47ca5f9e --- /dev/null +++ b/queue-4.19/alsa-hda-realtek-alc897-headset-mic-no-sound.patch @@ -0,0 +1,60 @@ +From 4d69f320a26a6c6e4fc4e91f5507c3eaa012d96e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Jun 2022 14:57:19 +0800 +Subject: ALSA: hda/realtek - ALC897 headset MIC no sound + +From: Kailang Yang + +[ Upstream commit fe6900bd8156467365bd5b976df64928fdebfeb0 ] + +There is not have Headset Mic verb table in BIOS default. +So, it will have recording issue from headset MIC. +Add the verb table value without jack detect. It will turn on Headset Mic. + +Signed-off-by: Kailang Yang +Cc: +Link: https://lore.kernel.org/r/719133a27d8844a890002cb817001dfa@realtek.com +Signed-off-by: Takashi Iwai +Stable-dep-of: 4bf5bf54476d ("ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB") +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index f0cf3e23d355..0a2cf8ca2812 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -8675,6 +8675,7 @@ enum { + ALC668_FIXUP_MIC_DET_COEF, + ALC897_FIXUP_LENOVO_HEADSET_MIC, + ALC897_FIXUP_HEADSET_MIC_PIN, ++ ALC897_FIXUP_HP_HSMIC_VERB, + }; + + static const struct hda_fixup alc662_fixups[] = { +@@ -9087,6 +9088,13 @@ static const struct hda_fixup alc662_fixups[] = { + .chained = true, + .chain_id = ALC897_FIXUP_LENOVO_HEADSET_MIC + }, ++ [ALC897_FIXUP_HP_HSMIC_VERB] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */ ++ { } ++ }, ++ }, + }; + + static const struct snd_pci_quirk alc662_fixup_tbl[] = { +@@ -9111,6 +9119,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), ++ SND_PCI_QUIRK(0x103c, 0x8719, "HP", ALC897_FIXUP_HP_HSMIC_VERB), + SND_PCI_QUIRK(0x103c, 0x873e, "HP", ALC671_FIXUP_HP_HEADSET_MIC2), + SND_PCI_QUIRK(0x1043, 0x1080, "Asus UX501VW", ALC668_FIXUP_HEADSET_MODE), + SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_ASUS_Nx50), +-- +2.35.1 + diff --git a/queue-4.19/alsa-hda-realtek-enable-headset-mic-of-acer-x2660g-w.patch b/queue-4.19/alsa-hda-realtek-enable-headset-mic-of-acer-x2660g-w.patch new file mode 100644 index 00000000000..05ce66f0d02 --- /dev/null +++ b/queue-4.19/alsa-hda-realtek-enable-headset-mic-of-acer-x2660g-w.patch @@ -0,0 +1,61 @@ +From 2dc43622b34ae832e20e81b6dc53aedbaffb8e9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2020 16:28:07 +0800 +Subject: ALSA: hda/realtek - Enable headset mic of Acer X2660G with ALC662 + +From: Jian-Hong Pan + +[ Upstream commit d858c706bdca97698752bd26b60c21ec07ef04f2 ] + +The Acer desktop X2660G with ALC662 can't detect the headset microphone +until ALC662_FIXUP_ACER_X2660G_HEADSET_MODE quirk applied. + +Signed-off-by: Jian-Hong Pan +Cc: +Link: https://lore.kernel.org/r/20200317082806.73194-2-jian-hong@endlessm.com +Signed-off-by: Takashi Iwai +Stable-dep-of: 4bf5bf54476d ("ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB") +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 375493d3807f..024a7e473e11 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -8647,6 +8647,7 @@ enum { + ALC669_FIXUP_ACER_ASPIRE_ETHOS_SUBWOOFER, + ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET, + ALC671_FIXUP_HP_HEADSET_MIC2, ++ ALC662_FIXUP_ACER_X2660G_HEADSET_MODE, + }; + + static const struct hda_fixup alc662_fixups[] = { +@@ -9004,6 +9005,15 @@ static const struct hda_fixup alc662_fixups[] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc671_fixup_hp_headset_mic2, + }, ++ [ALC662_FIXUP_ACER_X2660G_HEADSET_MODE] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x1a, 0x02a1113c }, /* use as headset mic, without its own jack detect */ ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC662_FIXUP_USI_FUNC ++ }, + }; + + static const struct snd_pci_quirk alc662_fixup_tbl[] = { +@@ -9015,6 +9025,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), + SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC), + SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), ++ SND_PCI_QUIRK(0x1025, 0x124e, "Acer 2660G", ALC662_FIXUP_ACER_X2660G_HEADSET_MODE), + SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x05fe, "Dell XPS 15", ALC668_FIXUP_DELL_XPS13), +-- +2.35.1 + diff --git a/queue-4.19/alsa-hda-realtek-enable-the-headset-of-acer-n50-600-.patch b/queue-4.19/alsa-hda-realtek-enable-the-headset-of-acer-n50-600-.patch new file mode 100644 index 00000000000..ced04629676 --- /dev/null +++ b/queue-4.19/alsa-hda-realtek-enable-the-headset-of-acer-n50-600-.patch @@ -0,0 +1,62 @@ +From 2e7fe866347afee7c46766e1e47df33430caaf65 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 17 Mar 2020 16:28:09 +0800 +Subject: ALSA: hda/realtek - Enable the headset of Acer N50-600 with ALC662 + +From: Jian-Hong Pan + +[ Upstream commit a124458a127ccd7629e20cd7bae3e1f758ed32aa ] + +A headset on the desktop like Acer N50-600 does not work, until quirk +ALC662_FIXUP_ACER_NITRO_HEADSET_MODE is applied. + +Signed-off-by: Jian-Hong Pan +Cc: +Link: https://lore.kernel.org/r/20200317082806.73194-3-jian-hong@endlessm.com +Signed-off-by: Takashi Iwai +Stable-dep-of: 4bf5bf54476d ("ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB") +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index 024a7e473e11..bb0917b9e68f 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -8648,6 +8648,7 @@ enum { + ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET, + ALC671_FIXUP_HP_HEADSET_MIC2, + ALC662_FIXUP_ACER_X2660G_HEADSET_MODE, ++ ALC662_FIXUP_ACER_NITRO_HEADSET_MODE, + }; + + static const struct hda_fixup alc662_fixups[] = { +@@ -9014,6 +9015,16 @@ static const struct hda_fixup alc662_fixups[] = { + .chained = true, + .chain_id = ALC662_FIXUP_USI_FUNC + }, ++ [ALC662_FIXUP_ACER_NITRO_HEADSET_MODE] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x1a, 0x01a11140 }, /* use as headset mic, without its own jack detect */ ++ { 0x1b, 0x0221144f }, ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC662_FIXUP_USI_FUNC ++ }, + }; + + static const struct snd_pci_quirk alc662_fixup_tbl[] = { +@@ -9025,6 +9036,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC), + SND_PCI_QUIRK(0x1025, 0x034a, "Gateway LT27", ALC662_FIXUP_INV_DMIC), + SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), ++ SND_PCI_QUIRK(0x1025, 0x123c, "Acer Nitro N50-600", ALC662_FIXUP_ACER_NITRO_HEADSET_MODE), + SND_PCI_QUIRK(0x1025, 0x124e, "Acer 2660G", ALC662_FIXUP_ACER_X2660G_HEADSET_MODE), + SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), +-- +2.35.1 + diff --git a/queue-4.19/alsa-hda-realtek-fix-the-mic-type-detection-issue-fo.patch b/queue-4.19/alsa-hda-realtek-fix-the-mic-type-detection-issue-fo.patch new file mode 100644 index 00000000000..7cbce125d78 --- /dev/null +++ b/queue-4.19/alsa-hda-realtek-fix-the-mic-type-detection-issue-fo.patch @@ -0,0 +1,88 @@ +From da632ed5ac77ffb74fa8511c3e07f25b133224da Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 12 Oct 2021 19:47:48 +0800 +Subject: ALSA: hda/realtek: Fix the mic type detection issue for ASUS G551JW + +From: Hui Wang + +[ Upstream commit a3fd1a986e499a06ac5ef95c3a39aa4611e7444c ] + +We need to define the codec pin 0x1b to be the mic, but somehow +the mic doesn't support hot plugging detection, and Windows also has +this issue, so we set it to phantom headset-mic. + +Also the determine_headset_type() often returns the omtp type by a +mistake when we plug a ctia headset, this makes the mic can't record +sound at all. Because most of the headset are ctia type nowadays and +some machines have the fixed ctia type audio jack, it is possible this +machine has the fixed ctia jack too. Here we set this mic jack to +fixed ctia type, this could avoid the mic type detection mistake and +make the ctia headset work stable. + +BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=214537 +Reported-and-tested-by: msd +Cc: +Signed-off-by: Hui Wang +Link: https://lore.kernel.org/r/20211012114748.5238-1-hui.wang@canonical.com +Signed-off-by: Takashi Iwai +Stable-dep-of: 4bf5bf54476d ("ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB") +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index a3cc5cc0d668..566d5ea74c62 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -8649,6 +8649,9 @@ enum { + ALC671_FIXUP_HP_HEADSET_MIC2, + ALC662_FIXUP_ACER_X2660G_HEADSET_MODE, + ALC662_FIXUP_ACER_NITRO_HEADSET_MODE, ++ ALC668_FIXUP_ASUS_NO_HEADSET_MIC, ++ ALC668_FIXUP_HEADSET_MIC, ++ ALC668_FIXUP_MIC_DET_COEF, + }; + + static const struct hda_fixup alc662_fixups[] = { +@@ -9025,6 +9028,29 @@ static const struct hda_fixup alc662_fixups[] = { + .chained = true, + .chain_id = ALC662_FIXUP_USI_FUNC + }, ++ [ALC668_FIXUP_ASUS_NO_HEADSET_MIC] = { ++ .type = HDA_FIXUP_PINS, ++ .v.pins = (const struct hda_pintbl[]) { ++ { 0x1b, 0x04a1112c }, ++ { } ++ }, ++ .chained = true, ++ .chain_id = ALC668_FIXUP_HEADSET_MIC ++ }, ++ [ALC668_FIXUP_HEADSET_MIC] = { ++ .type = HDA_FIXUP_FUNC, ++ .v.func = alc269_fixup_headset_mic, ++ .chained = true, ++ .chain_id = ALC668_FIXUP_MIC_DET_COEF ++ }, ++ [ALC668_FIXUP_MIC_DET_COEF] = { ++ .type = HDA_FIXUP_VERBS, ++ .v.verbs = (const struct hda_verb[]) { ++ { 0x20, AC_VERB_SET_COEF_INDEX, 0x15 }, ++ { 0x20, AC_VERB_SET_PROC_COEF, 0x0d60 }, ++ {} ++ }, ++ }, + }; + + static const struct snd_pci_quirk alc662_fixup_tbl[] = { +@@ -9059,6 +9085,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x1043, 0x15a7, "ASUS UX51VZH", ALC662_FIXUP_BASS_16), + SND_PCI_QUIRK(0x1043, 0x177d, "ASUS N551", ALC668_FIXUP_ASUS_Nx51), + SND_PCI_QUIRK(0x1043, 0x17bd, "ASUS N751", ALC668_FIXUP_ASUS_Nx51), ++ SND_PCI_QUIRK(0x1043, 0x185d, "ASUS G551JW", ALC668_FIXUP_ASUS_NO_HEADSET_MIC), + SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71SL", ALC662_FIXUP_ASUS_MODE8), + SND_PCI_QUIRK(0x1043, 0x1b73, "ASUS N55SF", ALC662_FIXUP_BASS_16), + SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_BASS_MODE4_CHMAP), +-- +2.35.1 + diff --git a/queue-4.19/alsa-hda-realtek-more-constifications.patch b/queue-4.19/alsa-hda-realtek-more-constifications.patch new file mode 100644 index 00000000000..61181e8bbae --- /dev/null +++ b/queue-4.19/alsa-hda-realtek-more-constifications.patch @@ -0,0 +1,480 @@ +From 6e631f1d938fd402205892d0be1a0319a7593335 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 5 Jan 2020 15:47:18 +0100 +Subject: ALSA: hda/realtek - More constifications + +From: Takashi Iwai + +[ Upstream commit 6b0f95c49d890440c01a759c767dfe40e2acdbf2 ] + +Apply const prefix to each coef table array. + +Just for minor optimization and no functional changes. + +Link: https://lore.kernel.org/r/20200105144823.29547-4-tiwai@suse.de +Signed-off-by: Takashi Iwai +Stable-dep-of: 4bf5bf54476d ("ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB") +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 118 +++++++++++++++++----------------- + 1 file changed, 59 insertions(+), 59 deletions(-) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index fe17fb8d7f67..3abe30eec49a 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -956,7 +956,7 @@ struct alc_codec_rename_pci_table { + const char *name; + }; + +-static struct alc_codec_rename_table rename_tbl[] = { ++static const struct alc_codec_rename_table rename_tbl[] = { + { 0x10ec0221, 0xf00f, 0x1003, "ALC231" }, + { 0x10ec0269, 0xfff0, 0x3010, "ALC277" }, + { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" }, +@@ -977,7 +977,7 @@ static struct alc_codec_rename_table rename_tbl[] = { + { } /* terminator */ + }; + +-static struct alc_codec_rename_pci_table rename_pci_tbl[] = { ++static const struct alc_codec_rename_pci_table rename_pci_tbl[] = { + { 0x10ec0280, 0x1028, 0, "ALC3220" }, + { 0x10ec0282, 0x1028, 0, "ALC3221" }, + { 0x10ec0283, 0x1028, 0, "ALC3223" }, +@@ -3115,7 +3115,7 @@ static void alc269_shutup(struct hda_codec *codec) + alc_shutup_pins(codec); + } + +-static struct coef_fw alc282_coefs[] = { ++static const struct coef_fw alc282_coefs[] = { + WRITE_COEF(0x03, 0x0002), /* Power Down Control */ + UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */ + WRITE_COEF(0x07, 0x0200), /* DMIC control */ +@@ -3227,7 +3227,7 @@ static void alc282_shutup(struct hda_codec *codec) + alc_write_coef_idx(codec, 0x78, coef78); + } + +-static struct coef_fw alc283_coefs[] = { ++static const struct coef_fw alc283_coefs[] = { + WRITE_COEF(0x03, 0x0002), /* Power Down Control */ + UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */ + WRITE_COEF(0x07, 0x0200), /* DMIC control */ +@@ -4234,7 +4234,7 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec, + } + } + +-static struct coef_fw alc225_pre_hsmode[] = { ++static const struct coef_fw alc225_pre_hsmode[] = { + UPDATE_COEF(0x4a, 1<<8, 0), + UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), + UPDATE_COEF(0x63, 3<<14, 3<<14), +@@ -4247,7 +4247,7 @@ static struct coef_fw alc225_pre_hsmode[] = { + + static void alc_headset_mode_unplugged(struct hda_codec *codec) + { +- static struct coef_fw coef0255[] = { ++ static const struct coef_fw coef0255[] = { + WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */ + WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */ + UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/ +@@ -4255,7 +4255,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) + WRITE_COEFEX(0x57, 0x03, 0x8aa6), /* Direct Drive HP Amp control */ + {} + }; +- static struct coef_fw coef0256[] = { ++ static const struct coef_fw coef0256[] = { + WRITE_COEF(0x1b, 0x0c4b), /* LDO and MISC control */ + WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */ + WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */ +@@ -4263,7 +4263,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) + UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/ + {} + }; +- static struct coef_fw coef0233[] = { ++ static const struct coef_fw coef0233[] = { + WRITE_COEF(0x1b, 0x0c0b), + WRITE_COEF(0x45, 0xc429), + UPDATE_COEF(0x35, 0x4000, 0), +@@ -4273,7 +4273,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) + WRITE_COEF(0x32, 0x42a3), + {} + }; +- static struct coef_fw coef0288[] = { ++ static const struct coef_fw coef0288[] = { + UPDATE_COEF(0x4f, 0xfcc0, 0xc400), + UPDATE_COEF(0x50, 0x2000, 0x2000), + UPDATE_COEF(0x56, 0x0006, 0x0006), +@@ -4281,18 +4281,18 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) + UPDATE_COEF(0x67, 0x2000, 0), + {} + }; +- static struct coef_fw coef0298[] = { ++ static const struct coef_fw coef0298[] = { + UPDATE_COEF(0x19, 0x1300, 0x0300), + {} + }; +- static struct coef_fw coef0292[] = { ++ static const struct coef_fw coef0292[] = { + WRITE_COEF(0x76, 0x000e), + WRITE_COEF(0x6c, 0x2400), + WRITE_COEF(0x18, 0x7308), + WRITE_COEF(0x6b, 0xc429), + {} + }; +- static struct coef_fw coef0293[] = { ++ static const struct coef_fw coef0293[] = { + UPDATE_COEF(0x10, 7<<8, 6<<8), /* SET Line1 JD to 0 */ + UPDATE_COEFEX(0x57, 0x05, 1<<15|1<<13, 0x0), /* SET charge pump by verb */ + UPDATE_COEFEX(0x57, 0x03, 1<<10, 1<<10), /* SET EN_OSW to 1 */ +@@ -4301,16 +4301,16 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) + UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */ + {} + }; +- static struct coef_fw coef0668[] = { ++ static const struct coef_fw coef0668[] = { + WRITE_COEF(0x15, 0x0d40), + WRITE_COEF(0xb7, 0x802b), + {} + }; +- static struct coef_fw coef0225[] = { ++ static const struct coef_fw coef0225[] = { + UPDATE_COEF(0x63, 3<<14, 0), + {} + }; +- static struct coef_fw coef0274[] = { ++ static const struct coef_fw coef0274[] = { + UPDATE_COEF(0x4a, 0x0100, 0), + UPDATE_COEFEX(0x57, 0x05, 0x4000, 0), + UPDATE_COEF(0x6b, 0xf000, 0x5000), +@@ -4375,25 +4375,25 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) + static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, + hda_nid_t mic_pin) + { +- static struct coef_fw coef0255[] = { ++ static const struct coef_fw coef0255[] = { + WRITE_COEFEX(0x57, 0x03, 0x8aa6), + WRITE_COEF(0x06, 0x6100), /* Set MIC2 Vref gate to normal */ + {} + }; +- static struct coef_fw coef0256[] = { ++ static const struct coef_fw coef0256[] = { + UPDATE_COEFEX(0x57, 0x05, 1<<14, 1<<14), /* Direct Drive HP Amp control(Set to verb control)*/ + WRITE_COEFEX(0x57, 0x03, 0x09a3), + WRITE_COEF(0x06, 0x6100), /* Set MIC2 Vref gate to normal */ + {} + }; +- static struct coef_fw coef0233[] = { ++ static const struct coef_fw coef0233[] = { + UPDATE_COEF(0x35, 0, 1<<14), + WRITE_COEF(0x06, 0x2100), + WRITE_COEF(0x1a, 0x0021), + WRITE_COEF(0x26, 0x008c), + {} + }; +- static struct coef_fw coef0288[] = { ++ static const struct coef_fw coef0288[] = { + UPDATE_COEF(0x4f, 0x00c0, 0), + UPDATE_COEF(0x50, 0x2000, 0), + UPDATE_COEF(0x56, 0x0006, 0), +@@ -4402,30 +4402,30 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, + UPDATE_COEF(0x67, 0x2000, 0x2000), + {} + }; +- static struct coef_fw coef0292[] = { ++ static const struct coef_fw coef0292[] = { + WRITE_COEF(0x19, 0xa208), + WRITE_COEF(0x2e, 0xacf0), + {} + }; +- static struct coef_fw coef0293[] = { ++ static const struct coef_fw coef0293[] = { + UPDATE_COEFEX(0x57, 0x05, 0, 1<<15|1<<13), /* SET charge pump by verb */ + UPDATE_COEFEX(0x57, 0x03, 1<<10, 0), /* SET EN_OSW to 0 */ + UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */ + {} + }; +- static struct coef_fw coef0688[] = { ++ static const struct coef_fw coef0688[] = { + WRITE_COEF(0xb7, 0x802b), + WRITE_COEF(0xb5, 0x1040), + UPDATE_COEF(0xc3, 0, 1<<12), + {} + }; +- static struct coef_fw coef0225[] = { ++ static const struct coef_fw coef0225[] = { + UPDATE_COEFEX(0x57, 0x05, 1<<14, 1<<14), + UPDATE_COEF(0x4a, 3<<4, 2<<4), + UPDATE_COEF(0x63, 3<<14, 0), + {} + }; +- static struct coef_fw coef0274[] = { ++ static const struct coef_fw coef0274[] = { + UPDATE_COEFEX(0x57, 0x05, 0x4000, 0x4000), + UPDATE_COEF(0x4a, 0x0010, 0), + UPDATE_COEF(0x6b, 0xf000, 0), +@@ -4511,7 +4511,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, + + static void alc_headset_mode_default(struct hda_codec *codec) + { +- static struct coef_fw coef0225[] = { ++ static const struct coef_fw coef0225[] = { + UPDATE_COEF(0x45, 0x3f<<10, 0x30<<10), + UPDATE_COEF(0x45, 0x3f<<10, 0x31<<10), + UPDATE_COEF(0x49, 3<<8, 0<<8), +@@ -4520,14 +4520,14 @@ static void alc_headset_mode_default(struct hda_codec *codec) + UPDATE_COEF(0x67, 0xf000, 0x3000), + {} + }; +- static struct coef_fw coef0255[] = { ++ static const struct coef_fw coef0255[] = { + WRITE_COEF(0x45, 0xc089), + WRITE_COEF(0x45, 0xc489), + WRITE_COEFEX(0x57, 0x03, 0x8ea6), + WRITE_COEF(0x49, 0x0049), + {} + }; +- static struct coef_fw coef0256[] = { ++ static const struct coef_fw coef0256[] = { + WRITE_COEF(0x45, 0xc489), + WRITE_COEFEX(0x57, 0x03, 0x0da3), + WRITE_COEF(0x49, 0x0049), +@@ -4535,12 +4535,12 @@ static void alc_headset_mode_default(struct hda_codec *codec) + WRITE_COEF(0x06, 0x6100), + {} + }; +- static struct coef_fw coef0233[] = { ++ static const struct coef_fw coef0233[] = { + WRITE_COEF(0x06, 0x2100), + WRITE_COEF(0x32, 0x4ea3), + {} + }; +- static struct coef_fw coef0288[] = { ++ static const struct coef_fw coef0288[] = { + UPDATE_COEF(0x4f, 0xfcc0, 0xc400), /* Set to TRS type */ + UPDATE_COEF(0x50, 0x2000, 0x2000), + UPDATE_COEF(0x56, 0x0006, 0x0006), +@@ -4548,26 +4548,26 @@ static void alc_headset_mode_default(struct hda_codec *codec) + UPDATE_COEF(0x67, 0x2000, 0), + {} + }; +- static struct coef_fw coef0292[] = { ++ static const struct coef_fw coef0292[] = { + WRITE_COEF(0x76, 0x000e), + WRITE_COEF(0x6c, 0x2400), + WRITE_COEF(0x6b, 0xc429), + WRITE_COEF(0x18, 0x7308), + {} + }; +- static struct coef_fw coef0293[] = { ++ static const struct coef_fw coef0293[] = { + UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */ + WRITE_COEF(0x45, 0xC429), /* Set to TRS type */ + UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */ + {} + }; +- static struct coef_fw coef0688[] = { ++ static const struct coef_fw coef0688[] = { + WRITE_COEF(0x11, 0x0041), + WRITE_COEF(0x15, 0x0d40), + WRITE_COEF(0xb7, 0x802b), + {} + }; +- static struct coef_fw coef0274[] = { ++ static const struct coef_fw coef0274[] = { + WRITE_COEF(0x45, 0x4289), + UPDATE_COEF(0x4a, 0x0010, 0x0010), + UPDATE_COEF(0x6b, 0x0f00, 0), +@@ -4630,53 +4630,53 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) + { + int val; + +- static struct coef_fw coef0255[] = { ++ static const struct coef_fw coef0255[] = { + WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */ + WRITE_COEF(0x1b, 0x0c2b), + WRITE_COEFEX(0x57, 0x03, 0x8ea6), + {} + }; +- static struct coef_fw coef0256[] = { ++ static const struct coef_fw coef0256[] = { + WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */ + WRITE_COEF(0x1b, 0x0e6b), + {} + }; +- static struct coef_fw coef0233[] = { ++ static const struct coef_fw coef0233[] = { + WRITE_COEF(0x45, 0xd429), + WRITE_COEF(0x1b, 0x0c2b), + WRITE_COEF(0x32, 0x4ea3), + {} + }; +- static struct coef_fw coef0288[] = { ++ static const struct coef_fw coef0288[] = { + UPDATE_COEF(0x50, 0x2000, 0x2000), + UPDATE_COEF(0x56, 0x0006, 0x0006), + UPDATE_COEF(0x66, 0x0008, 0), + UPDATE_COEF(0x67, 0x2000, 0), + {} + }; +- static struct coef_fw coef0292[] = { ++ static const struct coef_fw coef0292[] = { + WRITE_COEF(0x6b, 0xd429), + WRITE_COEF(0x76, 0x0008), + WRITE_COEF(0x18, 0x7388), + {} + }; +- static struct coef_fw coef0293[] = { ++ static const struct coef_fw coef0293[] = { + WRITE_COEF(0x45, 0xd429), /* Set to ctia type */ + UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */ + {} + }; +- static struct coef_fw coef0688[] = { ++ static const struct coef_fw coef0688[] = { + WRITE_COEF(0x11, 0x0001), + WRITE_COEF(0x15, 0x0d60), + WRITE_COEF(0xc3, 0x0000), + {} + }; +- static struct coef_fw coef0225_1[] = { ++ static const struct coef_fw coef0225_1[] = { + UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10), + UPDATE_COEF(0x63, 3<<14, 2<<14), + {} + }; +- static struct coef_fw coef0225_2[] = { ++ static const struct coef_fw coef0225_2[] = { + UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10), + UPDATE_COEF(0x63, 3<<14, 1<<14), + {} +@@ -4748,48 +4748,48 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) + /* Nokia type */ + static void alc_headset_mode_omtp(struct hda_codec *codec) + { +- static struct coef_fw coef0255[] = { ++ static const struct coef_fw coef0255[] = { + WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */ + WRITE_COEF(0x1b, 0x0c2b), + WRITE_COEFEX(0x57, 0x03, 0x8ea6), + {} + }; +- static struct coef_fw coef0256[] = { ++ static const struct coef_fw coef0256[] = { + WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */ + WRITE_COEF(0x1b, 0x0e6b), + {} + }; +- static struct coef_fw coef0233[] = { ++ static const struct coef_fw coef0233[] = { + WRITE_COEF(0x45, 0xe429), + WRITE_COEF(0x1b, 0x0c2b), + WRITE_COEF(0x32, 0x4ea3), + {} + }; +- static struct coef_fw coef0288[] = { ++ static const struct coef_fw coef0288[] = { + UPDATE_COEF(0x50, 0x2000, 0x2000), + UPDATE_COEF(0x56, 0x0006, 0x0006), + UPDATE_COEF(0x66, 0x0008, 0), + UPDATE_COEF(0x67, 0x2000, 0), + {} + }; +- static struct coef_fw coef0292[] = { ++ static const struct coef_fw coef0292[] = { + WRITE_COEF(0x6b, 0xe429), + WRITE_COEF(0x76, 0x0008), + WRITE_COEF(0x18, 0x7388), + {} + }; +- static struct coef_fw coef0293[] = { ++ static const struct coef_fw coef0293[] = { + WRITE_COEF(0x45, 0xe429), /* Set to omtp type */ + UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */ + {} + }; +- static struct coef_fw coef0688[] = { ++ static const struct coef_fw coef0688[] = { + WRITE_COEF(0x11, 0x0001), + WRITE_COEF(0x15, 0x0d50), + WRITE_COEF(0xc3, 0x0000), + {} + }; +- static struct coef_fw coef0225[] = { ++ static const struct coef_fw coef0225[] = { + UPDATE_COEF(0x45, 0x3f<<10, 0x39<<10), + UPDATE_COEF(0x63, 3<<14, 2<<14), + {} +@@ -4849,17 +4849,17 @@ static void alc_determine_headset_type(struct hda_codec *codec) + int val; + bool is_ctia = false; + struct alc_spec *spec = codec->spec; +- static struct coef_fw coef0255[] = { ++ static const struct coef_fw coef0255[] = { + WRITE_COEF(0x45, 0xd089), /* combo jack auto switch control(Check type)*/ + WRITE_COEF(0x49, 0x0149), /* combo jack auto switch control(Vref + conteol) */ + {} + }; +- static struct coef_fw coef0288[] = { ++ static const struct coef_fw coef0288[] = { + UPDATE_COEF(0x4f, 0xfcc0, 0xd400), /* Check Type */ + {} + }; +- static struct coef_fw coef0298[] = { ++ static const struct coef_fw coef0298[] = { + UPDATE_COEF(0x50, 0x2000, 0x2000), + UPDATE_COEF(0x56, 0x0006, 0x0006), + UPDATE_COEF(0x66, 0x0008, 0), +@@ -4867,19 +4867,19 @@ static void alc_determine_headset_type(struct hda_codec *codec) + UPDATE_COEF(0x19, 0x1300, 0x1300), + {} + }; +- static struct coef_fw coef0293[] = { ++ static const struct coef_fw coef0293[] = { + UPDATE_COEF(0x4a, 0x000f, 0x0008), /* Combo Jack auto detect */ + WRITE_COEF(0x45, 0xD429), /* Set to ctia type */ + {} + }; +- static struct coef_fw coef0688[] = { ++ static const struct coef_fw coef0688[] = { + WRITE_COEF(0x11, 0x0001), + WRITE_COEF(0xb7, 0x802b), + WRITE_COEF(0x15, 0x0d60), + WRITE_COEF(0xc3, 0x0c00), + {} + }; +- static struct coef_fw coef0274[] = { ++ static const struct coef_fw coef0274[] = { + UPDATE_COEF(0x4a, 0x0010, 0), + UPDATE_COEF(0x4a, 0x8000, 0), + WRITE_COEF(0x45, 0xd289), +@@ -5164,7 +5164,7 @@ static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec, + static void alc255_set_default_jack_type(struct hda_codec *codec) + { + /* Set to iphone type */ +- static struct coef_fw alc255fw[] = { ++ static const struct coef_fw alc255fw[] = { + WRITE_COEF(0x1b, 0x880b), + WRITE_COEF(0x45, 0xd089), + WRITE_COEF(0x1b, 0x080b), +@@ -5172,7 +5172,7 @@ static void alc255_set_default_jack_type(struct hda_codec *codec) + WRITE_COEF(0x1b, 0x0c0b), + {} + }; +- static struct coef_fw alc256fw[] = { ++ static const struct coef_fw alc256fw[] = { + WRITE_COEF(0x1b, 0x884b), + WRITE_COEF(0x45, 0xd089), + WRITE_COEF(0x1b, 0x084b), +@@ -8549,7 +8549,7 @@ static void alc662_fixup_aspire_ethos_hp(struct hda_codec *codec, + } + } + +-static struct coef_fw alc668_coefs[] = { ++static const struct coef_fw alc668_coefs[] = { + WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03, 0x0), + WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06, 0x0), WRITE_COEF(0x07, 0x0f80), + WRITE_COEF(0x08, 0x0031), WRITE_COEF(0x0a, 0x0060), WRITE_COEF(0x0b, 0x0), +-- +2.35.1 + diff --git a/queue-4.19/alsa-hda-realtek-the-front-mic-on-a-hp-machine-doesn.patch b/queue-4.19/alsa-hda-realtek-the-front-mic-on-a-hp-machine-doesn.patch new file mode 100644 index 00000000000..a364d267a96 --- /dev/null +++ b/queue-4.19/alsa-hda-realtek-the-front-mic-on-a-hp-machine-doesn.patch @@ -0,0 +1,39 @@ +From 3f997afe6915a117e99439677f69fdf9c66d1780 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 8 Oct 2020 18:56:44 +0800 +Subject: ALSA: hda/realtek - The front Mic on a HP machine doesn't work + +From: Jeremy Szu + +[ Upstream commit 148ebf548a1af366fc797fcc7d03f0bb92b12a79 ] + +On a HP ZCentral, the front Mic could not be detected. + +The codec of the HP ZCentrol is alc671 and it needs to override the pin +configuration to enable the headset mic. + +Signed-off-by: Jeremy Szu +Cc: +Link: https://lore.kernel.org/r/20201008105645.65505-1-jeremy.szu@canonical.com +Signed-off-by: Takashi Iwai +Stable-dep-of: 4bf5bf54476d ("ALSA: hda/realtek: Add quirk for Lenovo TianYi510Pro-14IOB") +Signed-off-by: Sasha Levin +--- + sound/pci/hda/patch_realtek.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index bb0917b9e68f..a3cc5cc0d668 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -9049,6 +9049,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { + SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x069f, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), ++ SND_PCI_QUIRK(0x103c, 0x873e, "HP", ALC671_FIXUP_HP_HEADSET_MIC2), + SND_PCI_QUIRK(0x1043, 0x1080, "Asus UX501VW", ALC668_FIXUP_HEADSET_MODE), + SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_ASUS_Nx50), + SND_PCI_QUIRK(0x1043, 0x13df, "Asus N550JX", ALC662_FIXUP_BASS_1A), +-- +2.35.1 + diff --git a/queue-4.19/ext4-add-new-pending-reservation-mechanism.patch b/queue-4.19/ext4-add-new-pending-reservation-mechanism.patch new file mode 100644 index 00000000000..62f87604292 --- /dev/null +++ b/queue-4.19/ext4-add-new-pending-reservation-mechanism.patch @@ -0,0 +1,351 @@ +From 1e4d3f9286661240c542984257d065efdcc3afed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Oct 2018 14:17:41 -0400 +Subject: ext4: add new pending reservation mechanism + +From: Eric Whitney + +[ Upstream commit 1dc0aa46e74a3366e12f426b7caaca477853e9c3 ] + +Add new pending reservation mechanism to help manage reserved cluster +accounting. Its primary function is to avoid the need to read extents +from the disk when invalidating pages as a result of a truncate, punch +hole, or collapse range operation. + +Signed-off-by: Eric Whitney +Signed-off-by: Theodore Ts'o +Stable-dep-of: 131294c35ed6 ("ext4: fix delayed allocation bug in ext4_clu_mapped for bigalloc + inline") +Signed-off-by: Sasha Levin +--- + fs/ext4/ext4.h | 3 + + fs/ext4/extents_status.c | 187 +++++++++++++++++++++++++++++++++++++++ + fs/ext4/extents_status.h | 51 +++++++++++ + fs/ext4/super.c | 8 ++ + 4 files changed, 249 insertions(+) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 24bbfbf9a5aa..e914a0df209f 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -1041,6 +1041,9 @@ struct ext4_inode_info { + ext4_lblk_t i_da_metadata_calc_last_lblock; + int i_da_metadata_calc_len; + ++ /* pending cluster reservations for bigalloc file systems */ ++ struct ext4_pending_tree i_pending_tree; ++ + /* on-disk additional length */ + __u16 i_extra_isize; + +diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c +index e7503a3a3299..90e473084fd4 100644 +--- a/fs/ext4/extents_status.c ++++ b/fs/ext4/extents_status.c +@@ -142,6 +142,7 @@ + */ + + static struct kmem_cache *ext4_es_cachep; ++static struct kmem_cache *ext4_pending_cachep; + + static int __es_insert_extent(struct inode *inode, struct extent_status *newes); + static int __es_remove_extent(struct inode *inode, ext4_lblk_t lblk, +@@ -1363,3 +1364,189 @@ static int es_reclaim_extents(struct ext4_inode_info *ei, int *nr_to_scan) + ei->i_es_tree.cache_es = NULL; + return nr_shrunk; + } ++ ++#ifdef ES_DEBUG__ ++static void ext4_print_pending_tree(struct inode *inode) ++{ ++ struct ext4_pending_tree *tree; ++ struct rb_node *node; ++ struct pending_reservation *pr; ++ ++ printk(KERN_DEBUG "pending reservations for inode %lu:", inode->i_ino); ++ tree = &EXT4_I(inode)->i_pending_tree; ++ node = rb_first(&tree->root); ++ while (node) { ++ pr = rb_entry(node, struct pending_reservation, rb_node); ++ printk(KERN_DEBUG " %u", pr->lclu); ++ node = rb_next(node); ++ } ++ printk(KERN_DEBUG "\n"); ++} ++#else ++#define ext4_print_pending_tree(inode) ++#endif ++ ++int __init ext4_init_pending(void) ++{ ++ ext4_pending_cachep = kmem_cache_create("ext4_pending_reservation", ++ sizeof(struct pending_reservation), ++ 0, (SLAB_RECLAIM_ACCOUNT), NULL); ++ if (ext4_pending_cachep == NULL) ++ return -ENOMEM; ++ return 0; ++} ++ ++void ext4_exit_pending(void) ++{ ++ kmem_cache_destroy(ext4_pending_cachep); ++} ++ ++void ext4_init_pending_tree(struct ext4_pending_tree *tree) ++{ ++ tree->root = RB_ROOT; ++} ++ ++/* ++ * __get_pending - retrieve a pointer to a pending reservation ++ * ++ * @inode - file containing the pending cluster reservation ++ * @lclu - logical cluster of interest ++ * ++ * Returns a pointer to a pending reservation if it's a member of ++ * the set, and NULL if not. Must be called holding i_es_lock. ++ */ ++static struct pending_reservation *__get_pending(struct inode *inode, ++ ext4_lblk_t lclu) ++{ ++ struct ext4_pending_tree *tree; ++ struct rb_node *node; ++ struct pending_reservation *pr = NULL; ++ ++ tree = &EXT4_I(inode)->i_pending_tree; ++ node = (&tree->root)->rb_node; ++ ++ while (node) { ++ pr = rb_entry(node, struct pending_reservation, rb_node); ++ if (lclu < pr->lclu) ++ node = node->rb_left; ++ else if (lclu > pr->lclu) ++ node = node->rb_right; ++ else if (lclu == pr->lclu) ++ return pr; ++ } ++ return NULL; ++} ++ ++/* ++ * __insert_pending - adds a pending cluster reservation to the set of ++ * pending reservations ++ * ++ * @inode - file containing the cluster ++ * @lblk - logical block in the cluster to be added ++ * ++ * Returns 0 on successful insertion and -ENOMEM on failure. If the ++ * pending reservation is already in the set, returns successfully. ++ */ ++static int __insert_pending(struct inode *inode, ext4_lblk_t lblk) ++{ ++ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); ++ struct ext4_pending_tree *tree = &EXT4_I(inode)->i_pending_tree; ++ struct rb_node **p = &tree->root.rb_node; ++ struct rb_node *parent = NULL; ++ struct pending_reservation *pr; ++ ext4_lblk_t lclu; ++ int ret = 0; ++ ++ lclu = EXT4_B2C(sbi, lblk); ++ /* search to find parent for insertion */ ++ while (*p) { ++ parent = *p; ++ pr = rb_entry(parent, struct pending_reservation, rb_node); ++ ++ if (lclu < pr->lclu) { ++ p = &(*p)->rb_left; ++ } else if (lclu > pr->lclu) { ++ p = &(*p)->rb_right; ++ } else { ++ /* pending reservation already inserted */ ++ goto out; ++ } ++ } ++ ++ pr = kmem_cache_alloc(ext4_pending_cachep, GFP_ATOMIC); ++ if (pr == NULL) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ pr->lclu = lclu; ++ ++ rb_link_node(&pr->rb_node, parent, p); ++ rb_insert_color(&pr->rb_node, &tree->root); ++ ++out: ++ return ret; ++} ++ ++/* ++ * __remove_pending - removes a pending cluster reservation from the set ++ * of pending reservations ++ * ++ * @inode - file containing the cluster ++ * @lblk - logical block in the pending cluster reservation to be removed ++ * ++ * Returns successfully if pending reservation is not a member of the set. ++ */ ++static void __remove_pending(struct inode *inode, ext4_lblk_t lblk) ++{ ++ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); ++ struct pending_reservation *pr; ++ struct ext4_pending_tree *tree; ++ ++ pr = __get_pending(inode, EXT4_B2C(sbi, lblk)); ++ if (pr != NULL) { ++ tree = &EXT4_I(inode)->i_pending_tree; ++ rb_erase(&pr->rb_node, &tree->root); ++ kmem_cache_free(ext4_pending_cachep, pr); ++ } ++} ++ ++/* ++ * ext4_remove_pending - removes a pending cluster reservation from the set ++ * of pending reservations ++ * ++ * @inode - file containing the cluster ++ * @lblk - logical block in the pending cluster reservation to be removed ++ * ++ * Locking for external use of __remove_pending. ++ */ ++void ext4_remove_pending(struct inode *inode, ext4_lblk_t lblk) ++{ ++ struct ext4_inode_info *ei = EXT4_I(inode); ++ ++ write_lock(&ei->i_es_lock); ++ __remove_pending(inode, lblk); ++ write_unlock(&ei->i_es_lock); ++} ++ ++/* ++ * ext4_is_pending - determine whether a cluster has a pending reservation ++ * on it ++ * ++ * @inode - file containing the cluster ++ * @lblk - logical block in the cluster ++ * ++ * Returns true if there's a pending reservation for the cluster in the ++ * set of pending reservations, and false if not. ++ */ ++bool ext4_is_pending(struct inode *inode, ext4_lblk_t lblk) ++{ ++ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); ++ struct ext4_inode_info *ei = EXT4_I(inode); ++ bool ret; ++ ++ read_lock(&ei->i_es_lock); ++ ret = (bool)(__get_pending(inode, EXT4_B2C(sbi, lblk)) != NULL); ++ read_unlock(&ei->i_es_lock); ++ ++ return ret; ++} +diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h +index df9628c3ec3b..379b7171c67c 100644 +--- a/fs/ext4/extents_status.h ++++ b/fs/ext4/extents_status.h +@@ -78,6 +78,51 @@ struct ext4_es_stats { + struct percpu_counter es_stats_shk_cnt; + }; + ++/* ++ * Pending cluster reservations for bigalloc file systems ++ * ++ * A cluster with a pending reservation is a logical cluster shared by at ++ * least one extent in the extents status tree with delayed and unwritten ++ * status and at least one other written or unwritten extent. The ++ * reservation is said to be pending because a cluster reservation would ++ * have to be taken in the event all blocks in the cluster shared with ++ * written or unwritten extents were deleted while the delayed and ++ * unwritten blocks remained. ++ * ++ * The set of pending cluster reservations is an auxiliary data structure ++ * used with the extents status tree to implement reserved cluster/block ++ * accounting for bigalloc file systems. The set is kept in memory and ++ * records all pending cluster reservations. ++ * ++ * Its primary function is to avoid the need to read extents from the ++ * disk when invalidating pages as a result of a truncate, punch hole, or ++ * collapse range operation. Page invalidation requires a decrease in the ++ * reserved cluster count if it results in the removal of all delayed ++ * and unwritten extents (blocks) from a cluster that is not shared with a ++ * written or unwritten extent, and no decrease otherwise. Determining ++ * whether the cluster is shared can be done by searching for a pending ++ * reservation on it. ++ * ++ * Secondarily, it provides a potentially faster method for determining ++ * whether the reserved cluster count should be increased when a physical ++ * cluster is deallocated as a result of a truncate, punch hole, or ++ * collapse range operation. The necessary information is also present ++ * in the extents status tree, but might be more rapidly accessed in ++ * the pending reservation set in many cases due to smaller size. ++ * ++ * The pending cluster reservation set is implemented as a red-black tree ++ * with the goal of minimizing per page search time overhead. ++ */ ++ ++struct pending_reservation { ++ struct rb_node rb_node; ++ ext4_lblk_t lclu; ++}; ++ ++struct ext4_pending_tree { ++ struct rb_root root; ++}; ++ + extern int __init ext4_init_es(void); + extern void ext4_exit_es(void); + extern void ext4_es_init_tree(struct ext4_es_tree *tree); +@@ -182,4 +227,10 @@ extern void ext4_es_unregister_shrinker(struct ext4_sb_info *sbi); + + extern int ext4_seq_es_shrinker_info_show(struct seq_file *seq, void *v); + ++extern int __init ext4_init_pending(void); ++extern void ext4_exit_pending(void); ++extern void ext4_init_pending_tree(struct ext4_pending_tree *tree); ++extern void ext4_remove_pending(struct inode *inode, ext4_lblk_t lblk); ++extern bool ext4_is_pending(struct inode *inode, ext4_lblk_t lblk); ++ + #endif /* _EXT4_EXTENTS_STATUS_H */ +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index e54a5be15636..73a431b6e720 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -1095,6 +1095,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) + ei->i_da_metadata_calc_len = 0; + ei->i_da_metadata_calc_last_lblock = 0; + spin_lock_init(&(ei->i_block_reservation_lock)); ++ ext4_init_pending_tree(&ei->i_pending_tree); + #ifdef CONFIG_QUOTA + ei->i_reserved_quota = 0; + memset(&ei->i_dquot, 0, sizeof(ei->i_dquot)); +@@ -6189,6 +6190,10 @@ static int __init ext4_init_fs(void) + if (err) + return err; + ++ err = ext4_init_pending(); ++ if (err) ++ goto out6; ++ + err = ext4_init_pageio(); + if (err) + goto out5; +@@ -6227,6 +6232,8 @@ static int __init ext4_init_fs(void) + out4: + ext4_exit_pageio(); + out5: ++ ext4_exit_pending(); ++out6: + ext4_exit_es(); + + return err; +@@ -6244,6 +6251,7 @@ static void __exit ext4_exit_fs(void) + ext4_exit_system_zone(); + ext4_exit_pageio(); + ext4_exit_es(); ++ ext4_exit_pending(); + } + + MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others"); +-- +2.35.1 + diff --git a/queue-4.19/ext4-fix-bug_on-in-__es_tree_search-caused-by-bad-qu.patch b/queue-4.19/ext4-fix-bug_on-in-__es_tree_search-caused-by-bad-qu.patch new file mode 100644 index 00000000000..0f854c5362a --- /dev/null +++ b/queue-4.19/ext4-fix-bug_on-in-__es_tree_search-caused-by-bad-qu.patch @@ -0,0 +1,114 @@ +From ca803d95c0c2b5366c817f7a9a5f8f3b01913c35 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Oct 2022 12:23:07 +0800 +Subject: ext4: fix bug_on in __es_tree_search caused by bad quota inode + +From: Baokun Li + +[ Upstream commit d323877484765aaacbb2769b06e355c2041ed115 ] + +We got a issue as fllows: +================================================================== + kernel BUG at fs/ext4/extents_status.c:202! + invalid opcode: 0000 [#1] PREEMPT SMP + CPU: 1 PID: 810 Comm: mount Not tainted 6.1.0-rc1-next-g9631525255e3 #352 + RIP: 0010:__es_tree_search.isra.0+0xb8/0xe0 + RSP: 0018:ffffc90001227900 EFLAGS: 00010202 + RAX: 0000000000000000 RBX: 0000000077512a0f RCX: 0000000000000000 + RDX: 0000000000000002 RSI: 0000000000002a10 RDI: ffff8881004cd0c8 + RBP: ffff888177512ac8 R08: 47ffffffffffffff R09: 0000000000000001 + R10: 0000000000000001 R11: 00000000000679af R12: 0000000000002a10 + R13: ffff888177512d88 R14: 0000000077512a10 R15: 0000000000000000 + FS: 00007f4bd76dbc40(0000)GS:ffff88842fd00000(0000)knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00005653bf993cf8 CR3: 000000017bfdf000 CR4: 00000000000006e0 + DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 + DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 + Call Trace: + + ext4_es_cache_extent+0xe2/0x210 + ext4_cache_extents+0xd2/0x110 + ext4_find_extent+0x5d5/0x8c0 + ext4_ext_map_blocks+0x9c/0x1d30 + ext4_map_blocks+0x431/0xa50 + ext4_getblk+0x82/0x340 + ext4_bread+0x14/0x110 + ext4_quota_read+0xf0/0x180 + v2_read_header+0x24/0x90 + v2_check_quota_file+0x2f/0xa0 + dquot_load_quota_sb+0x26c/0x760 + dquot_load_quota_inode+0xa5/0x190 + ext4_enable_quotas+0x14c/0x300 + __ext4_fill_super+0x31cc/0x32c0 + ext4_fill_super+0x115/0x2d0 + get_tree_bdev+0x1d2/0x360 + ext4_get_tree+0x19/0x30 + vfs_get_tree+0x26/0xe0 + path_mount+0x81d/0xfc0 + do_mount+0x8d/0xc0 + __x64_sys_mount+0xc0/0x160 + do_syscall_64+0x35/0x80 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + +================================================================== + +Above issue may happen as follows: +------------------------------------- +ext4_fill_super + ext4_orphan_cleanup + ext4_enable_quotas + ext4_quota_enable + ext4_iget --> get error inode <5> + ext4_ext_check_inode --> Wrong imode makes it escape inspection + make_bad_inode(inode) --> EXT4_BOOT_LOADER_INO set imode + dquot_load_quota_inode + vfs_setup_quota_inode --> check pass + dquot_load_quota_sb + v2_check_quota_file + v2_read_header + ext4_quota_read + ext4_bread + ext4_getblk + ext4_map_blocks + ext4_ext_map_blocks + ext4_find_extent + ext4_cache_extents + ext4_es_cache_extent + __es_tree_search.isra.0 + ext4_es_end --> Wrong extents trigger BUG_ON + +In the above issue, s_usr_quota_inum is set to 5, but inode<5> contains +incorrect imode and disordered extents. Because 5 is EXT4_BOOT_LOADER_INO, +the ext4_ext_check_inode check in the ext4_iget function can be bypassed, +finally, the extents that are not checked trigger the BUG_ON in the +__es_tree_search function. To solve this issue, check whether the inode is +bad_inode in vfs_setup_quota_inode(). + +Signed-off-by: Baokun Li +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Jason Yan +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20221026042310.3839669-2-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Sasha Levin +--- + fs/quota/dquot.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c +index a1d2aed0d833..770a2b143485 100644 +--- a/fs/quota/dquot.c ++++ b/fs/quota/dquot.c +@@ -2303,6 +2303,8 @@ static int vfs_setup_quota_inode(struct inode *inode, int type) + struct super_block *sb = inode->i_sb; + struct quota_info *dqopt = sb_dqopt(sb); + ++ if (is_bad_inode(inode)) ++ return -EUCLEAN; + if (!S_ISREG(inode->i_mode)) + return -EACCES; + if (IS_RDONLY(inode)) +-- +2.35.1 + diff --git a/queue-4.19/ext4-fix-delayed-allocation-bug-in-ext4_clu_mapped-f.patch b/queue-4.19/ext4-fix-delayed-allocation-bug-in-ext4_clu_mapped-f.patch new file mode 100644 index 00000000000..d25b03f57b4 --- /dev/null +++ b/queue-4.19/ext4-fix-delayed-allocation-bug-in-ext4_clu_mapped-f.patch @@ -0,0 +1,63 @@ +From 70a393283f87ce85b538285dfd5b6449d01eae6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 10:22:07 -0500 +Subject: ext4: fix delayed allocation bug in ext4_clu_mapped for bigalloc + + inline + +From: Eric Whitney + +[ Upstream commit 131294c35ed6f777bd4e79d42af13b5c41bf2775 ] + +When converting files with inline data to extents, delayed allocations +made on a file system created with both the bigalloc and inline options +can result in invalid extent status cache content, incorrect reserved +cluster counts, kernel memory leaks, and potential kernel panics. + +With bigalloc, the code that determines whether a block must be +delayed allocated searches the extent tree to see if that block maps +to a previously allocated cluster. If not, the block is delayed +allocated, and otherwise, it isn't. However, if the inline option is +also used, and if the file containing the block is marked as able to +store data inline, there isn't a valid extent tree associated with +the file. The current code in ext4_clu_mapped() calls +ext4_find_extent() to search the non-existent tree for a previously +allocated cluster anyway, which typically finds nothing, as desired. +However, a side effect of the search can be to cache invalid content +from the non-existent tree (garbage) in the extent status tree, +including bogus entries in the pending reservation tree. + +To fix this, avoid searching the extent tree when allocating blocks +for bigalloc + inline files that are being converted from inline to +extent mapped. + +Signed-off-by: Eric Whitney +Link: https://lore.kernel.org/r/20221117152207.2424-1-enwlinux@gmail.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Sasha Levin +--- + fs/ext4/extents.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 0bb772cd7f88..1ad4c8eb82c1 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -5984,6 +5984,14 @@ int ext4_clu_mapped(struct inode *inode, ext4_lblk_t lclu) + struct ext4_extent *extent; + ext4_lblk_t first_lblk, first_lclu, last_lclu; + ++ /* ++ * if data can be stored inline, the logical cluster isn't ++ * mapped - no physical clusters have been allocated, and the ++ * file has no extents ++ */ ++ if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA)) ++ return 0; ++ + /* search for the extent closest to the first block in the cluster */ + path = ext4_find_extent(inode, EXT4_C2B(sbi, lclu), NULL, 0); + if (IS_ERR(path)) { +-- +2.35.1 + diff --git a/queue-4.19/ext4-fix-reserved-cluster-accounting-at-delayed-writ.patch b/queue-4.19/ext4-fix-reserved-cluster-accounting-at-delayed-writ.patch new file mode 100644 index 00000000000..0ce3ee9271f --- /dev/null +++ b/queue-4.19/ext4-fix-reserved-cluster-accounting-at-delayed-writ.patch @@ -0,0 +1,367 @@ +From fa738f0cc8380c18b39d69f0af4eecae95cf174a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Oct 2018 14:19:37 -0400 +Subject: ext4: fix reserved cluster accounting at delayed write time + +From: Eric Whitney + +[ Upstream commit 0b02f4c0d6d9e2c611dfbdd4317193e9dca740e6 ] + +The code in ext4_da_map_blocks sometimes reserves space for more +delayed allocated clusters than it should, resulting in premature +ENOSPC, exceeded quota, and inaccurate free space reporting. + +Fix this by checking for written and unwritten blocks shared in the +same cluster with the newly delayed allocated block. A cluster +reservation should not be made for a cluster for which physical space +has already been allocated. + +Signed-off-by: Eric Whitney +Signed-off-by: Theodore Ts'o +Stable-dep-of: 131294c35ed6 ("ext4: fix delayed allocation bug in ext4_clu_mapped for bigalloc + inline") +Signed-off-by: Sasha Levin +--- + fs/ext4/ext4.h | 1 + + fs/ext4/extents.c | 79 +++++++++++++++++++++++++++++++++++++ + fs/ext4/extents_status.c | 53 +++++++++++++++++++++++++ + fs/ext4/extents_status.h | 12 ++++++ + fs/ext4/inode.c | 79 ++++++++++++++++++++++++++++--------- + include/trace/events/ext4.h | 35 ++++++++++++++++ + 6 files changed, 241 insertions(+), 18 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index e914a0df209f..d8068c0e547d 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -3241,6 +3241,7 @@ extern int ext4_swap_extents(handle_t *handle, struct inode *inode1, + struct inode *inode2, ext4_lblk_t lblk1, + ext4_lblk_t lblk2, ext4_lblk_t count, + int mark_unwritten,int *err); ++extern int ext4_clu_mapped(struct inode *inode, ext4_lblk_t lclu); + + /* move_extent.c */ + extern void ext4_double_down_write_data_sem(struct inode *first, +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index c5c8326f5c25..0bb772cd7f88 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -5963,3 +5963,82 @@ ext4_swap_extents(handle_t *handle, struct inode *inode1, + } + return replaced_count; + } ++ ++/* ++ * ext4_clu_mapped - determine whether any block in a logical cluster has ++ * been mapped to a physical cluster ++ * ++ * @inode - file containing the logical cluster ++ * @lclu - logical cluster of interest ++ * ++ * Returns 1 if any block in the logical cluster is mapped, signifying ++ * that a physical cluster has been allocated for it. Otherwise, ++ * returns 0. Can also return negative error codes. Derived from ++ * ext4_ext_map_blocks(). ++ */ ++int ext4_clu_mapped(struct inode *inode, ext4_lblk_t lclu) ++{ ++ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); ++ struct ext4_ext_path *path; ++ int depth, mapped = 0, err = 0; ++ struct ext4_extent *extent; ++ ext4_lblk_t first_lblk, first_lclu, last_lclu; ++ ++ /* search for the extent closest to the first block in the cluster */ ++ path = ext4_find_extent(inode, EXT4_C2B(sbi, lclu), NULL, 0); ++ if (IS_ERR(path)) { ++ err = PTR_ERR(path); ++ path = NULL; ++ goto out; ++ } ++ ++ depth = ext_depth(inode); ++ ++ /* ++ * A consistent leaf must not be empty. This situation is possible, ++ * though, _during_ tree modification, and it's why an assert can't ++ * be put in ext4_find_extent(). ++ */ ++ if (unlikely(path[depth].p_ext == NULL && depth != 0)) { ++ EXT4_ERROR_INODE(inode, ++ "bad extent address - lblock: %lu, depth: %d, pblock: %lld", ++ (unsigned long) EXT4_C2B(sbi, lclu), ++ depth, path[depth].p_block); ++ err = -EFSCORRUPTED; ++ goto out; ++ } ++ ++ extent = path[depth].p_ext; ++ ++ /* can't be mapped if the extent tree is empty */ ++ if (extent == NULL) ++ goto out; ++ ++ first_lblk = le32_to_cpu(extent->ee_block); ++ first_lclu = EXT4_B2C(sbi, first_lblk); ++ ++ /* ++ * Three possible outcomes at this point - found extent spanning ++ * the target cluster, to the left of the target cluster, or to the ++ * right of the target cluster. The first two cases are handled here. ++ * The last case indicates the target cluster is not mapped. ++ */ ++ if (lclu >= first_lclu) { ++ last_lclu = EXT4_B2C(sbi, first_lblk + ++ ext4_ext_get_actual_len(extent) - 1); ++ if (lclu <= last_lclu) { ++ mapped = 1; ++ } else { ++ first_lblk = ext4_ext_next_allocated_block(path); ++ first_lclu = EXT4_B2C(sbi, first_lblk); ++ if (lclu == first_lclu) ++ mapped = 1; ++ } ++ } ++ ++out: ++ ext4_ext_drop_refs(path); ++ kfree(path); ++ ++ return err ? err : mapped; ++} +diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c +index 90e473084fd4..441ee2e747d3 100644 +--- a/fs/ext4/extents_status.c ++++ b/fs/ext4/extents_status.c +@@ -1550,3 +1550,56 @@ bool ext4_is_pending(struct inode *inode, ext4_lblk_t lblk) + + return ret; + } ++ ++/* ++ * ext4_es_insert_delayed_block - adds a delayed block to the extents status ++ * tree, adding a pending reservation where ++ * needed ++ * ++ * @inode - file containing the newly added block ++ * @lblk - logical block to be added ++ * @allocated - indicates whether a physical cluster has been allocated for ++ * the logical cluster that contains the block ++ * ++ * Returns 0 on success, negative error code on failure. ++ */ ++int ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk, ++ bool allocated) ++{ ++ struct extent_status newes; ++ int err = 0; ++ ++ es_debug("add [%u/1) delayed to extent status tree of inode %lu\n", ++ lblk, inode->i_ino); ++ ++ newes.es_lblk = lblk; ++ newes.es_len = 1; ++ ext4_es_store_pblock_status(&newes, ~0, EXTENT_STATUS_DELAYED); ++ trace_ext4_es_insert_delayed_block(inode, &newes, allocated); ++ ++ ext4_es_insert_extent_check(inode, &newes); ++ ++ write_lock(&EXT4_I(inode)->i_es_lock); ++ ++ err = __es_remove_extent(inode, lblk, lblk); ++ if (err != 0) ++ goto error; ++retry: ++ err = __es_insert_extent(inode, &newes); ++ if (err == -ENOMEM && __es_shrink(EXT4_SB(inode->i_sb), ++ 128, EXT4_I(inode))) ++ goto retry; ++ if (err != 0) ++ goto error; ++ ++ if (allocated) ++ __insert_pending(inode, lblk); ++ ++error: ++ write_unlock(&EXT4_I(inode)->i_es_lock); ++ ++ ext4_es_print_tree(inode); ++ ext4_print_pending_tree(inode); ++ ++ return err; ++} +diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h +index 379b7171c67c..9d3c676ec623 100644 +--- a/fs/ext4/extents_status.h ++++ b/fs/ext4/extents_status.h +@@ -178,6 +178,16 @@ static inline int ext4_es_is_hole(struct extent_status *es) + return (ext4_es_type(es) & EXTENT_STATUS_HOLE) != 0; + } + ++static inline int ext4_es_is_mapped(struct extent_status *es) ++{ ++ return (ext4_es_is_written(es) || ext4_es_is_unwritten(es)); ++} ++ ++static inline int ext4_es_is_delonly(struct extent_status *es) ++{ ++ return (ext4_es_is_delayed(es) && !ext4_es_is_unwritten(es)); ++} ++ + static inline void ext4_es_set_referenced(struct extent_status *es) + { + es->es_pblk |= ((ext4_fsblk_t)EXTENT_STATUS_REFERENCED) << ES_SHIFT; +@@ -232,5 +242,7 @@ extern void ext4_exit_pending(void); + extern void ext4_init_pending_tree(struct ext4_pending_tree *tree); + extern void ext4_remove_pending(struct inode *inode, ext4_lblk_t lblk); + extern bool ext4_is_pending(struct inode *inode, ext4_lblk_t lblk); ++extern int ext4_es_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk, ++ bool allocated); + + #endif /* _EXT4_EXTENTS_STATUS_H */ +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index cba27ba41834..17d120ac2010 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -1823,6 +1823,65 @@ static int ext4_bh_delay_or_unwritten(handle_t *handle, struct buffer_head *bh) + return (buffer_delay(bh) || buffer_unwritten(bh)) && buffer_dirty(bh); + } + ++/* ++ * ext4_insert_delayed_block - adds a delayed block to the extents status ++ * tree, incrementing the reserved cluster/block ++ * count or making a pending reservation ++ * where needed ++ * ++ * @inode - file containing the newly added block ++ * @lblk - logical block to be added ++ * ++ * Returns 0 on success, negative error code on failure. ++ */ ++static int ext4_insert_delayed_block(struct inode *inode, ext4_lblk_t lblk) ++{ ++ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); ++ int ret; ++ bool allocated = false; ++ ++ /* ++ * If the cluster containing lblk is shared with a delayed, ++ * written, or unwritten extent in a bigalloc file system, it's ++ * already been accounted for and does not need to be reserved. ++ * A pending reservation must be made for the cluster if it's ++ * shared with a written or unwritten extent and doesn't already ++ * have one. Written and unwritten extents can be purged from the ++ * extents status tree if the system is under memory pressure, so ++ * it's necessary to examine the extent tree if a search of the ++ * extents status tree doesn't get a match. ++ */ ++ if (sbi->s_cluster_ratio == 1) { ++ ret = ext4_da_reserve_space(inode); ++ if (ret != 0) /* ENOSPC */ ++ goto errout; ++ } else { /* bigalloc */ ++ if (!ext4_es_scan_clu(inode, &ext4_es_is_delonly, lblk)) { ++ if (!ext4_es_scan_clu(inode, ++ &ext4_es_is_mapped, lblk)) { ++ ret = ext4_clu_mapped(inode, ++ EXT4_B2C(sbi, lblk)); ++ if (ret < 0) ++ goto errout; ++ if (ret == 0) { ++ ret = ext4_da_reserve_space(inode); ++ if (ret != 0) /* ENOSPC */ ++ goto errout; ++ } else { ++ allocated = true; ++ } ++ } else { ++ allocated = true; ++ } ++ } ++ } ++ ++ ret = ext4_es_insert_delayed_block(inode, lblk, allocated); ++ ++errout: ++ return ret; ++} ++ + /* + * This function is grabs code from the very beginning of + * ext4_map_blocks, but assumes that the caller is from delayed write +@@ -1907,25 +1966,9 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock, + * XXX: __block_prepare_write() unmaps passed block, + * is it OK? + */ +- /* +- * If the block was allocated from previously allocated cluster, +- * then we don't need to reserve it again. However we still need +- * to reserve metadata for every block we're going to write. +- */ +- if (EXT4_SB(inode->i_sb)->s_cluster_ratio == 1 || +- !ext4_es_scan_clu(inode, +- &ext4_es_is_delayed, map->m_lblk)) { +- ret = ext4_da_reserve_space(inode); +- if (ret) { +- /* not enough space to reserve */ +- retval = ret; +- goto out_unlock; +- } +- } + +- ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len, +- ~0, EXTENT_STATUS_DELAYED); +- if (ret) { ++ ret = ext4_insert_delayed_block(inode, map->m_lblk); ++ if (ret != 0) { + retval = ret; + goto out_unlock; + } +diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h +index 388dc3666cc7..20c9b8e77a57 100644 +--- a/include/trace/events/ext4.h ++++ b/include/trace/events/ext4.h +@@ -2532,6 +2532,41 @@ TRACE_EVENT(ext4_es_shrink, + __entry->scan_time, __entry->nr_skipped, __entry->retried) + ); + ++TRACE_EVENT(ext4_es_insert_delayed_block, ++ TP_PROTO(struct inode *inode, struct extent_status *es, ++ bool allocated), ++ ++ TP_ARGS(inode, es, allocated), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( ino_t, ino ) ++ __field( ext4_lblk_t, lblk ) ++ __field( ext4_lblk_t, len ) ++ __field( ext4_fsblk_t, pblk ) ++ __field( char, status ) ++ __field( bool, allocated ) ++ ), ++ ++ TP_fast_assign( ++ __entry->dev = inode->i_sb->s_dev; ++ __entry->ino = inode->i_ino; ++ __entry->lblk = es->es_lblk; ++ __entry->len = es->es_len; ++ __entry->pblk = ext4_es_pblock(es); ++ __entry->status = ext4_es_status(es); ++ __entry->allocated = allocated; ++ ), ++ ++ TP_printk("dev %d,%d ino %lu es [%u/%u) mapped %llu status %s " ++ "allocated %d", ++ MAJOR(__entry->dev), MINOR(__entry->dev), ++ (unsigned long) __entry->ino, ++ __entry->lblk, __entry->len, ++ __entry->pblk, show_extent_status(__entry->status), ++ __entry->allocated) ++); ++ + /* fsmap traces */ + DECLARE_EVENT_CLASS(ext4_fsmap_class, + TP_PROTO(struct super_block *sb, u32 keydev, u32 agno, u64 bno, u64 len, +-- +2.35.1 + diff --git a/queue-4.19/ext4-fix-uninititialized-value-in-ext4_evict_inode.patch b/queue-4.19/ext4-fix-uninititialized-value-in-ext4_evict_inode.patch new file mode 100644 index 00000000000..96ee18a0045 --- /dev/null +++ b/queue-4.19/ext4-fix-uninititialized-value-in-ext4_evict_inode.patch @@ -0,0 +1,97 @@ +From d18baeee2b2eb18b38f13f083db0772fb783788f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 15:36:03 +0800 +Subject: ext4: fix uninititialized value in 'ext4_evict_inode' + +From: Ye Bin + +[ Upstream commit 7ea71af94eaaaf6d9aed24bc94a05b977a741cb9 ] + +Syzbot found the following issue: +===================================================== +BUG: KMSAN: uninit-value in ext4_evict_inode+0xdd/0x26b0 fs/ext4/inode.c:180 + ext4_evict_inode+0xdd/0x26b0 fs/ext4/inode.c:180 + evict+0x365/0x9a0 fs/inode.c:664 + iput_final fs/inode.c:1747 [inline] + iput+0x985/0xdd0 fs/inode.c:1773 + __ext4_new_inode+0xe54/0x7ec0 fs/ext4/ialloc.c:1361 + ext4_mknod+0x376/0x840 fs/ext4/namei.c:2844 + vfs_mknod+0x79d/0x830 fs/namei.c:3914 + do_mknodat+0x47d/0xaa0 + __do_sys_mknodat fs/namei.c:3992 [inline] + __se_sys_mknodat fs/namei.c:3989 [inline] + __ia32_sys_mknodat+0xeb/0x150 fs/namei.c:3989 + do_syscall_32_irqs_on arch/x86/entry/common.c:112 [inline] + __do_fast_syscall_32+0xa2/0x100 arch/x86/entry/common.c:178 + do_fast_syscall_32+0x33/0x70 arch/x86/entry/common.c:203 + do_SYSENTER_32+0x1b/0x20 arch/x86/entry/common.c:246 + entry_SYSENTER_compat_after_hwframe+0x70/0x82 + +Uninit was created at: + __alloc_pages+0x9f1/0xe80 mm/page_alloc.c:5578 + alloc_pages+0xaae/0xd80 mm/mempolicy.c:2285 + alloc_slab_page mm/slub.c:1794 [inline] + allocate_slab+0x1b5/0x1010 mm/slub.c:1939 + new_slab mm/slub.c:1992 [inline] + ___slab_alloc+0x10c3/0x2d60 mm/slub.c:3180 + __slab_alloc mm/slub.c:3279 [inline] + slab_alloc_node mm/slub.c:3364 [inline] + slab_alloc mm/slub.c:3406 [inline] + __kmem_cache_alloc_lru mm/slub.c:3413 [inline] + kmem_cache_alloc_lru+0x6f3/0xb30 mm/slub.c:3429 + alloc_inode_sb include/linux/fs.h:3117 [inline] + ext4_alloc_inode+0x5f/0x860 fs/ext4/super.c:1321 + alloc_inode+0x83/0x440 fs/inode.c:259 + new_inode_pseudo fs/inode.c:1018 [inline] + new_inode+0x3b/0x430 fs/inode.c:1046 + __ext4_new_inode+0x2a7/0x7ec0 fs/ext4/ialloc.c:959 + ext4_mkdir+0x4d5/0x1560 fs/ext4/namei.c:2992 + vfs_mkdir+0x62a/0x870 fs/namei.c:4035 + do_mkdirat+0x466/0x7b0 fs/namei.c:4060 + __do_sys_mkdirat fs/namei.c:4075 [inline] + __se_sys_mkdirat fs/namei.c:4073 [inline] + __ia32_sys_mkdirat+0xc4/0x120 fs/namei.c:4073 + do_syscall_32_irqs_on arch/x86/entry/common.c:112 [inline] + __do_fast_syscall_32+0xa2/0x100 arch/x86/entry/common.c:178 + do_fast_syscall_32+0x33/0x70 arch/x86/entry/common.c:203 + do_SYSENTER_32+0x1b/0x20 arch/x86/entry/common.c:246 + entry_SYSENTER_compat_after_hwframe+0x70/0x82 + +CPU: 1 PID: 4625 Comm: syz-executor.2 Not tainted 6.1.0-rc4-syzkaller-62821-gcb231e2f67ec #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 +===================================================== + +Now, 'ext4_alloc_inode()' didn't init 'ei->i_flags'. If new inode failed +before set 'ei->i_flags' in '__ext4_new_inode()', then do 'iput()'. As after +6bc0d63dad7f commit will access 'ei->i_flags' in 'ext4_evict_inode()' which +will lead to access uninit-value. +To solve above issue just init 'ei->i_flags' in 'ext4_alloc_inode()'. + +Reported-by: syzbot+57b25da729eb0b88177d@syzkaller.appspotmail.com +Signed-off-by: Ye Bin +Fixes: 6bc0d63dad7f ("ext4: remove EA inode entry from mbcache on inode eviction") +Reviewed-by: Jan Kara +Reviewed-by: Eric Biggers +Link: https://lore.kernel.org/r/20221117073603.2598882-1-yebin@huaweicloud.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Sasha Levin +--- + fs/ext4/super.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 85703a3e69e5..e54a5be15636 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -1081,6 +1081,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) + return NULL; + + inode_set_iversion(&ei->vfs_inode, 1); ++ ei->i_flags = 0; + spin_lock_init(&ei->i_raw_lock); + INIT_LIST_HEAD(&ei->i_prealloc_list); + spin_lock_init(&ei->i_prealloc_lock); +-- +2.35.1 + diff --git a/queue-4.19/ext4-fix-use-after-free-in-ext4_orphan_cleanup.patch b/queue-4.19/ext4-fix-use-after-free-in-ext4_orphan_cleanup.patch new file mode 100644 index 00000000000..fce189ac617 --- /dev/null +++ b/queue-4.19/ext4-fix-use-after-free-in-ext4_orphan_cleanup.patch @@ -0,0 +1,80 @@ +From c38979a0ed86a39afa58548afc86881d6960ab57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 16:06:33 +0800 +Subject: ext4: fix use-after-free in ext4_orphan_cleanup + +From: Baokun Li + +[ Upstream commit a71248b1accb2b42e4980afef4fa4a27fa0e36f5 ] + +I caught a issue as follows: +================================================================== + BUG: KASAN: use-after-free in __list_add_valid+0x28/0x1a0 + Read of size 8 at addr ffff88814b13f378 by task mount/710 + + CPU: 1 PID: 710 Comm: mount Not tainted 6.1.0-rc3-next #370 + Call Trace: + + dump_stack_lvl+0x73/0x9f + print_report+0x25d/0x759 + kasan_report+0xc0/0x120 + __asan_load8+0x99/0x140 + __list_add_valid+0x28/0x1a0 + ext4_orphan_cleanup+0x564/0x9d0 [ext4] + __ext4_fill_super+0x48e2/0x5300 [ext4] + ext4_fill_super+0x19f/0x3a0 [ext4] + get_tree_bdev+0x27b/0x450 + ext4_get_tree+0x19/0x30 [ext4] + vfs_get_tree+0x49/0x150 + path_mount+0xaae/0x1350 + do_mount+0xe2/0x110 + __x64_sys_mount+0xf0/0x190 + do_syscall_64+0x35/0x80 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + + [...] +================================================================== + +Above issue may happen as follows: +------------------------------------- +ext4_fill_super + ext4_orphan_cleanup + --- loop1: assume last_orphan is 12 --- + list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan) + ext4_truncate --> return 0 + ext4_inode_attach_jinode --> return -ENOMEM + iput(inode) --> free inode<12> + --- loop2: last_orphan is still 12 --- + list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan); + // use inode<12> and trigger UAF + +To solve this issue, we need to propagate the return value of +ext4_inode_attach_jinode() appropriately. + +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20221102080633.1630225-1-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Sasha Levin +--- + fs/ext4/inode.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 16d2b88bc66d..3c7bbdaa425a 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4568,7 +4568,8 @@ int ext4_truncate(struct inode *inode) + + /* If we zero-out tail of the page, we have to create jinode for jbd2 */ + if (inode->i_size & (inode->i_sb->s_blocksize - 1)) { +- if (ext4_inode_attach_jinode(inode) < 0) ++ err = ext4_inode_attach_jinode(inode); ++ if (err) + goto out_trace; + } + +-- +2.35.1 + diff --git a/queue-4.19/ext4-generalize-extents-status-tree-search-functions.patch b/queue-4.19/ext4-generalize-extents-status-tree-search-functions.patch new file mode 100644 index 00000000000..58193a94791 --- /dev/null +++ b/queue-4.19/ext4-generalize-extents-status-tree-search-functions.patch @@ -0,0 +1,457 @@ +From 24d8fd52d6535265069404abafc1d2223c93db9c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 1 Oct 2018 14:10:39 -0400 +Subject: ext4: generalize extents status tree search functions + +From: Eric Whitney + +[ Upstream commit ad431025aecda85d3ebef5e4a3aca5c1c681d0c7 ] + +Ext4 contains a few functions that are used to search for delayed +extents or blocks in the extents status tree. Rather than duplicate +code to add new functions to search for extents with different status +values, such as written or a combination of delayed and unwritten, +generalize the existing code to search for caller-specified extents +status values. Also, move this code into extents_status.c where it +is better associated with the data structures it operates upon, and +where it can be more readily used to implement new extents status tree +functions that might want a broader scope for i_es_lock. + +Three missing static specifiers in RFC version of patch reported and +fixed by Fengguang Wu . + +Signed-off-by: Eric Whitney +Signed-off-by: Theodore Ts'o +Stable-dep-of: 131294c35ed6 ("ext4: fix delayed allocation bug in ext4_clu_mapped for bigalloc + inline") +Signed-off-by: Sasha Levin +--- + fs/ext4/ext4.h | 4 - + fs/ext4/extents.c | 52 +++---------- + fs/ext4/extents_status.c | 149 +++++++++++++++++++++++++++++++----- + fs/ext4/extents_status.h | 13 +++- + fs/ext4/inode.c | 17 ++-- + include/trace/events/ext4.h | 4 +- + 6 files changed, 165 insertions(+), 74 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index e58b162ad5d6..24bbfbf9a5aa 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -3228,10 +3228,6 @@ extern struct ext4_ext_path *ext4_find_extent(struct inode *, ext4_lblk_t, + int flags); + extern void ext4_ext_drop_refs(struct ext4_ext_path *); + extern int ext4_ext_check_inode(struct inode *inode); +-extern int ext4_find_delalloc_range(struct inode *inode, +- ext4_lblk_t lblk_start, +- ext4_lblk_t lblk_end); +-extern int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk); + extern ext4_lblk_t ext4_ext_next_allocated_block(struct ext4_ext_path *path); + extern int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + __u64 start, __u64 len); +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 6c492fca60c4..c5c8326f5c25 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -2381,8 +2381,8 @@ ext4_ext_put_gap_in_cache(struct inode *inode, ext4_lblk_t hole_start, + { + struct extent_status es; + +- ext4_es_find_delayed_extent_range(inode, hole_start, +- hole_start + hole_len - 1, &es); ++ ext4_es_find_extent_range(inode, &ext4_es_is_delayed, hole_start, ++ hole_start + hole_len - 1, &es); + if (es.es_len) { + /* There's delayed extent containing lblock? */ + if (es.es_lblk <= hole_start) +@@ -3852,39 +3852,6 @@ static int check_eofblocks_fl(handle_t *handle, struct inode *inode, + return ext4_mark_inode_dirty(handle, inode); + } + +-/** +- * ext4_find_delalloc_range: find delayed allocated block in the given range. +- * +- * Return 1 if there is a delalloc block in the range, otherwise 0. +- */ +-int ext4_find_delalloc_range(struct inode *inode, +- ext4_lblk_t lblk_start, +- ext4_lblk_t lblk_end) +-{ +- struct extent_status es; +- +- ext4_es_find_delayed_extent_range(inode, lblk_start, lblk_end, &es); +- if (es.es_len == 0) +- return 0; /* there is no delay extent in this tree */ +- else if (es.es_lblk <= lblk_start && +- lblk_start < es.es_lblk + es.es_len) +- return 1; +- else if (lblk_start <= es.es_lblk && es.es_lblk <= lblk_end) +- return 1; +- else +- return 0; +-} +- +-int ext4_find_delalloc_cluster(struct inode *inode, ext4_lblk_t lblk) +-{ +- struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); +- ext4_lblk_t lblk_start, lblk_end; +- lblk_start = EXT4_LBLK_CMASK(sbi, lblk); +- lblk_end = lblk_start + sbi->s_cluster_ratio - 1; +- +- return ext4_find_delalloc_range(inode, lblk_start, lblk_end); +-} +- + /** + * Determines how many complete clusters (out of those specified by the 'map') + * are under delalloc and were reserved quota for. +@@ -3943,7 +3910,8 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start, + lblk_from = EXT4_LBLK_CMASK(sbi, lblk_start); + lblk_to = lblk_from + c_offset - 1; + +- if (ext4_find_delalloc_range(inode, lblk_from, lblk_to)) ++ if (ext4_es_scan_range(inode, &ext4_es_is_delayed, lblk_from, ++ lblk_to)) + allocated_clusters--; + } + +@@ -3953,7 +3921,8 @@ get_reserved_cluster_alloc(struct inode *inode, ext4_lblk_t lblk_start, + lblk_from = lblk_start + num_blks; + lblk_to = lblk_from + (sbi->s_cluster_ratio - c_offset) - 1; + +- if (ext4_find_delalloc_range(inode, lblk_from, lblk_to)) ++ if (ext4_es_scan_range(inode, &ext4_es_is_delayed, lblk_from, ++ lblk_to)) + allocated_clusters--; + } + +@@ -5108,8 +5077,10 @@ static int ext4_find_delayed_extent(struct inode *inode, + ext4_lblk_t block, next_del; + + if (newes->es_pblk == 0) { +- ext4_es_find_delayed_extent_range(inode, newes->es_lblk, +- newes->es_lblk + newes->es_len - 1, &es); ++ ext4_es_find_extent_range(inode, &ext4_es_is_delayed, ++ newes->es_lblk, ++ newes->es_lblk + newes->es_len - 1, ++ &es); + + /* + * No extent in extent-tree contains block @newes->es_pblk, +@@ -5130,7 +5101,8 @@ static int ext4_find_delayed_extent(struct inode *inode, + } + + block = newes->es_lblk + newes->es_len; +- ext4_es_find_delayed_extent_range(inode, block, EXT_MAX_BLOCKS, &es); ++ ext4_es_find_extent_range(inode, &ext4_es_is_delayed, block, ++ EXT_MAX_BLOCKS, &es); + if (es.es_len == 0) + next_del = EXT_MAX_BLOCKS; + else +diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c +index 027c3e1b9f61..e7503a3a3299 100644 +--- a/fs/ext4/extents_status.c ++++ b/fs/ext4/extents_status.c +@@ -233,30 +233,38 @@ static struct extent_status *__es_tree_search(struct rb_root *root, + } + + /* +- * ext4_es_find_delayed_extent_range: find the 1st delayed extent covering +- * @es->lblk if it exists, otherwise, the next extent after @es->lblk. ++ * ext4_es_find_extent_range - find extent with specified status within block ++ * range or next extent following block range in ++ * extents status tree + * +- * @inode: the inode which owns delayed extents +- * @lblk: the offset where we start to search +- * @end: the offset where we stop to search +- * @es: delayed extent that we found ++ * @inode - file containing the range ++ * @matching_fn - pointer to function that matches extents with desired status ++ * @lblk - logical block defining start of range ++ * @end - logical block defining end of range ++ * @es - extent found, if any ++ * ++ * Find the first extent within the block range specified by @lblk and @end ++ * in the extents status tree that satisfies @matching_fn. If a match ++ * is found, it's returned in @es. If not, and a matching extent is found ++ * beyond the block range, it's returned in @es. If no match is found, an ++ * extent is returned in @es whose es_lblk, es_len, and es_pblk components ++ * are 0. + */ +-void ext4_es_find_delayed_extent_range(struct inode *inode, +- ext4_lblk_t lblk, ext4_lblk_t end, +- struct extent_status *es) ++static void __es_find_extent_range(struct inode *inode, ++ int (*matching_fn)(struct extent_status *es), ++ ext4_lblk_t lblk, ext4_lblk_t end, ++ struct extent_status *es) + { + struct ext4_es_tree *tree = NULL; + struct extent_status *es1 = NULL; + struct rb_node *node; + +- BUG_ON(es == NULL); +- BUG_ON(end < lblk); +- trace_ext4_es_find_delayed_extent_range_enter(inode, lblk); ++ WARN_ON(es == NULL); ++ WARN_ON(end < lblk); + +- read_lock(&EXT4_I(inode)->i_es_lock); + tree = &EXT4_I(inode)->i_es_tree; + +- /* find extent in cache firstly */ ++ /* see if the extent has been cached */ + es->es_lblk = es->es_len = es->es_pblk = 0; + if (tree->cache_es) { + es1 = tree->cache_es; +@@ -271,28 +279,133 @@ void ext4_es_find_delayed_extent_range(struct inode *inode, + es1 = __es_tree_search(&tree->root, lblk); + + out: +- if (es1 && !ext4_es_is_delayed(es1)) { ++ if (es1 && !matching_fn(es1)) { + while ((node = rb_next(&es1->rb_node)) != NULL) { + es1 = rb_entry(node, struct extent_status, rb_node); + if (es1->es_lblk > end) { + es1 = NULL; + break; + } +- if (ext4_es_is_delayed(es1)) ++ if (matching_fn(es1)) + break; + } + } + +- if (es1 && ext4_es_is_delayed(es1)) { ++ if (es1 && matching_fn(es1)) { + tree->cache_es = es1; + es->es_lblk = es1->es_lblk; + es->es_len = es1->es_len; + es->es_pblk = es1->es_pblk; + } + ++} ++ ++/* ++ * Locking for __es_find_extent_range() for external use ++ */ ++void ext4_es_find_extent_range(struct inode *inode, ++ int (*matching_fn)(struct extent_status *es), ++ ext4_lblk_t lblk, ext4_lblk_t end, ++ struct extent_status *es) ++{ ++ trace_ext4_es_find_extent_range_enter(inode, lblk); ++ ++ read_lock(&EXT4_I(inode)->i_es_lock); ++ __es_find_extent_range(inode, matching_fn, lblk, end, es); ++ read_unlock(&EXT4_I(inode)->i_es_lock); ++ ++ trace_ext4_es_find_extent_range_exit(inode, es); ++} ++ ++/* ++ * __es_scan_range - search block range for block with specified status ++ * in extents status tree ++ * ++ * @inode - file containing the range ++ * @matching_fn - pointer to function that matches extents with desired status ++ * @lblk - logical block defining start of range ++ * @end - logical block defining end of range ++ * ++ * Returns true if at least one block in the specified block range satisfies ++ * the criterion specified by @matching_fn, and false if not. If at least ++ * one extent has the specified status, then there is at least one block ++ * in the cluster with that status. Should only be called by code that has ++ * taken i_es_lock. ++ */ ++static bool __es_scan_range(struct inode *inode, ++ int (*matching_fn)(struct extent_status *es), ++ ext4_lblk_t start, ext4_lblk_t end) ++{ ++ struct extent_status es; ++ ++ __es_find_extent_range(inode, matching_fn, start, end, &es); ++ if (es.es_len == 0) ++ return false; /* no matching extent in the tree */ ++ else if (es.es_lblk <= start && ++ start < es.es_lblk + es.es_len) ++ return true; ++ else if (start <= es.es_lblk && es.es_lblk <= end) ++ return true; ++ else ++ return false; ++} ++/* ++ * Locking for __es_scan_range() for external use ++ */ ++bool ext4_es_scan_range(struct inode *inode, ++ int (*matching_fn)(struct extent_status *es), ++ ext4_lblk_t lblk, ext4_lblk_t end) ++{ ++ bool ret; ++ ++ read_lock(&EXT4_I(inode)->i_es_lock); ++ ret = __es_scan_range(inode, matching_fn, lblk, end); ++ read_unlock(&EXT4_I(inode)->i_es_lock); ++ ++ return ret; ++} ++ ++/* ++ * __es_scan_clu - search cluster for block with specified status in ++ * extents status tree ++ * ++ * @inode - file containing the cluster ++ * @matching_fn - pointer to function that matches extents with desired status ++ * @lblk - logical block in cluster to be searched ++ * ++ * Returns true if at least one extent in the cluster containing @lblk ++ * satisfies the criterion specified by @matching_fn, and false if not. If at ++ * least one extent has the specified status, then there is at least one block ++ * in the cluster with that status. Should only be called by code that has ++ * taken i_es_lock. ++ */ ++static bool __es_scan_clu(struct inode *inode, ++ int (*matching_fn)(struct extent_status *es), ++ ext4_lblk_t lblk) ++{ ++ struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); ++ ext4_lblk_t lblk_start, lblk_end; ++ ++ lblk_start = EXT4_LBLK_CMASK(sbi, lblk); ++ lblk_end = lblk_start + sbi->s_cluster_ratio - 1; ++ ++ return __es_scan_range(inode, matching_fn, lblk_start, lblk_end); ++} ++ ++/* ++ * Locking for __es_scan_clu() for external use ++ */ ++bool ext4_es_scan_clu(struct inode *inode, ++ int (*matching_fn)(struct extent_status *es), ++ ext4_lblk_t lblk) ++{ ++ bool ret; ++ ++ read_lock(&EXT4_I(inode)->i_es_lock); ++ ret = __es_scan_clu(inode, matching_fn, lblk); + read_unlock(&EXT4_I(inode)->i_es_lock); + +- trace_ext4_es_find_delayed_extent_range_exit(inode, es); ++ return ret; + } + + static void ext4_es_list_add(struct inode *inode) +diff --git a/fs/ext4/extents_status.h b/fs/ext4/extents_status.h +index 8efdeb903d6b..df9628c3ec3b 100644 +--- a/fs/ext4/extents_status.h ++++ b/fs/ext4/extents_status.h +@@ -90,11 +90,18 @@ extern void ext4_es_cache_extent(struct inode *inode, ext4_lblk_t lblk, + unsigned int status); + extern int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk, + ext4_lblk_t len); +-extern void ext4_es_find_delayed_extent_range(struct inode *inode, +- ext4_lblk_t lblk, ext4_lblk_t end, +- struct extent_status *es); ++extern void ext4_es_find_extent_range(struct inode *inode, ++ int (*match_fn)(struct extent_status *es), ++ ext4_lblk_t lblk, ext4_lblk_t end, ++ struct extent_status *es); + extern int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk, + struct extent_status *es); ++extern bool ext4_es_scan_range(struct inode *inode, ++ int (*matching_fn)(struct extent_status *es), ++ ext4_lblk_t lblk, ext4_lblk_t end); ++extern bool ext4_es_scan_clu(struct inode *inode, ++ int (*matching_fn)(struct extent_status *es), ++ ext4_lblk_t lblk); + + static inline unsigned int ext4_es_status(struct extent_status *es) + { +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 3c7bbdaa425a..cba27ba41834 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -600,8 +600,8 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, + EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; + if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && + !(status & EXTENT_STATUS_WRITTEN) && +- ext4_find_delalloc_range(inode, map->m_lblk, +- map->m_lblk + map->m_len - 1)) ++ ext4_es_scan_range(inode, &ext4_es_is_delayed, map->m_lblk, ++ map->m_lblk + map->m_len - 1)) + status |= EXTENT_STATUS_DELAYED; + ret = ext4_es_insert_extent(inode, map->m_lblk, + map->m_len, map->m_pblk, status); +@@ -724,8 +724,8 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, + EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN; + if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) && + !(status & EXTENT_STATUS_WRITTEN) && +- ext4_find_delalloc_range(inode, map->m_lblk, +- map->m_lblk + map->m_len - 1)) ++ ext4_es_scan_range(inode, &ext4_es_is_delayed, map->m_lblk, ++ map->m_lblk + map->m_len - 1)) + status |= EXTENT_STATUS_DELAYED; + ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len, + map->m_pblk, status); +@@ -1717,7 +1717,7 @@ static void ext4_da_page_release_reservation(struct page *page, + lblk = (page->index << (PAGE_SHIFT - inode->i_blkbits)) + + ((num_clusters - 1) << sbi->s_cluster_bits); + if (sbi->s_cluster_ratio == 1 || +- !ext4_find_delalloc_cluster(inode, lblk)) ++ !ext4_es_scan_clu(inode, &ext4_es_is_delayed, lblk)) + ext4_da_release_space(inode, 1); + + num_clusters--; +@@ -1902,6 +1902,7 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock, + add_delayed: + if (retval == 0) { + int ret; ++ + /* + * XXX: __block_prepare_write() unmaps passed block, + * is it OK? +@@ -1912,7 +1913,8 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock, + * to reserve metadata for every block we're going to write. + */ + if (EXT4_SB(inode->i_sb)->s_cluster_ratio == 1 || +- !ext4_find_delalloc_cluster(inode, map->m_lblk)) { ++ !ext4_es_scan_clu(inode, ++ &ext4_es_is_delayed, map->m_lblk)) { + ret = ext4_da_reserve_space(inode); + if (ret) { + /* not enough space to reserve */ +@@ -3519,7 +3521,8 @@ static int ext4_iomap_begin(struct inode *inode, loff_t offset, loff_t length, + ext4_lblk_t end = map.m_lblk + map.m_len - 1; + struct extent_status es; + +- ext4_es_find_delayed_extent_range(inode, map.m_lblk, end, &es); ++ ext4_es_find_extent_range(inode, &ext4_es_is_delayed, ++ map.m_lblk, end, &es); + + if (!es.es_len || es.es_lblk > end) { + /* entire range is a hole */ +diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h +index 0dfb174f707e..388dc3666cc7 100644 +--- a/include/trace/events/ext4.h ++++ b/include/trace/events/ext4.h +@@ -2290,7 +2290,7 @@ TRACE_EVENT(ext4_es_remove_extent, + __entry->lblk, __entry->len) + ); + +-TRACE_EVENT(ext4_es_find_delayed_extent_range_enter, ++TRACE_EVENT(ext4_es_find_extent_range_enter, + TP_PROTO(struct inode *inode, ext4_lblk_t lblk), + + TP_ARGS(inode, lblk), +@@ -2312,7 +2312,7 @@ TRACE_EVENT(ext4_es_find_delayed_extent_range_enter, + (unsigned long) __entry->ino, __entry->lblk) + ); + +-TRACE_EVENT(ext4_es_find_delayed_extent_range_exit, ++TRACE_EVENT(ext4_es_find_extent_range_exit, + TP_PROTO(struct inode *inode, struct extent_status *es), + + TP_ARGS(inode, es), +-- +2.35.1 + diff --git a/queue-4.19/ext4-lost-matching-pair-of-trace-in-ext4_truncate.patch b/queue-4.19/ext4-lost-matching-pair-of-trace-in-ext4_truncate.patch new file mode 100644 index 00000000000..29b0621891a --- /dev/null +++ b/queue-4.19/ext4-lost-matching-pair-of-trace-in-ext4_truncate.patch @@ -0,0 +1,79 @@ +From 2c7d9deb7582867fbf82542db6612c226b15af2f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 1 Jul 2020 16:30:27 +0800 +Subject: ext4: lost matching-pair of trace in ext4_truncate + +From: zhengliang + +[ Upstream commit 9a5d265fed014115f35e598022c956e5d2fb863e ] + +It should call trace exit in all return path for ext4_truncate. + +Signed-off-by: zhengliang +Reviewed-by: Andreas Dilger +Reviewed-by: Ritesh Harjani +Link: https://lore.kernel.org/r/20200701083027.45996-1-zhengliang6@huawei.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: a71248b1accb ("ext4: fix use-after-free in ext4_orphan_cleanup") +Signed-off-by: Sasha Levin +--- + fs/ext4/inode.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index b322658ceff1..16d2b88bc66d 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4551,7 +4551,7 @@ int ext4_truncate(struct inode *inode) + trace_ext4_truncate_enter(inode); + + if (!ext4_can_truncate(inode)) +- return 0; ++ goto out_trace; + + ext4_clear_inode_flag(inode, EXT4_INODE_EOFBLOCKS); + +@@ -4562,16 +4562,14 @@ int ext4_truncate(struct inode *inode) + int has_inline = 1; + + err = ext4_inline_data_truncate(inode, &has_inline); +- if (err) +- return err; +- if (has_inline) +- return 0; ++ if (err || has_inline) ++ goto out_trace; + } + + /* If we zero-out tail of the page, we have to create jinode for jbd2 */ + if (inode->i_size & (inode->i_sb->s_blocksize - 1)) { + if (ext4_inode_attach_jinode(inode) < 0) +- return 0; ++ goto out_trace; + } + + if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) +@@ -4580,8 +4578,10 @@ int ext4_truncate(struct inode *inode) + credits = ext4_blocks_for_truncate(inode); + + handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits); +- if (IS_ERR(handle)) +- return PTR_ERR(handle); ++ if (IS_ERR(handle)) { ++ err = PTR_ERR(handle); ++ goto out_trace; ++ } + + if (inode->i_size & (inode->i_sb->s_blocksize - 1)) + ext4_block_truncate_page(handle, mapping, inode->i_size); +@@ -4630,6 +4630,7 @@ int ext4_truncate(struct inode *inode) + ext4_mark_inode_dirty(handle, inode); + ext4_journal_stop(handle); + ++out_trace: + trace_ext4_truncate_exit(inode); + return err; + } +-- +2.35.1 + diff --git a/queue-4.19/kest.pl-fix-grub2-menu-handling-for-rebooting.patch b/queue-4.19/kest.pl-fix-grub2-menu-handling-for-rebooting.patch new file mode 100644 index 00000000000..3149f972fb8 --- /dev/null +++ b/queue-4.19/kest.pl-fix-grub2-menu-handling-for-rebooting.patch @@ -0,0 +1,128 @@ +From 2ef6249539ff0a94c778486d5043123e550d7c07 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 30 Nov 2022 17:54:34 -0500 +Subject: kest.pl: Fix grub2 menu handling for rebooting + +From: Steven Rostedt + +[ Upstream commit 26df05a8c1420ad3de314fdd407e7fc2058cc7aa ] + +grub2 has submenus where to use grub-reboot, it requires: + + grub-reboot X>Y + +where X is the main index and Y is the submenu. Thus if you have: + +menuentry 'Debian GNU/Linux' --class debian --class gnu-linux ... + [...] +} +submenu 'Advanced options for Debian GNU/Linux' $menuentry_id_option ... + menuentry 'Debian GNU/Linux, with Linux 6.0.0-4-amd64' --class debian --class gnu-linux ... + [...] + } + menuentry 'Debian GNU/Linux, with Linux 6.0.0-4-amd64 (recovery mode)' --class debian --class gnu-linux ... + [...] + } + menuentry 'Debian GNU/Linux, with Linux test' --class debian --class gnu-linux ... + [...] + } + +And wanted to boot to the "Linux test" kernel, you need to run: + + # grub-reboot 1>2 + +As 1 is the second top menu (the submenu) and 2 is the third of the sub +menu entries. + +Have the grub.cfg parsing for grub2 handle such cases. + +Cc: stable@vger.kernel.org +Fixes: a15ba91361d46 ("ktest: Add support for grub2") +Reviewed-by: John 'Warthog9' Hawley (VMware) +Signed-off-by: Steven Rostedt +Signed-off-by: Sasha Levin +--- + tools/testing/ktest/ktest.pl | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl +index 689fa4fd3d76..a0b53309c5d8 100755 +--- a/tools/testing/ktest/ktest.pl ++++ b/tools/testing/ktest/ktest.pl +@@ -1860,7 +1860,7 @@ sub run_scp_mod { + + sub _get_grub_index { + +- my ($command, $target, $skip) = @_; ++ my ($command, $target, $skip, $submenu) = @_; + + return if (defined($grub_number) && defined($last_grub_menu) && + $last_grub_menu eq $grub_menu && defined($last_machine) && +@@ -1877,11 +1877,16 @@ sub _get_grub_index { + + my $found = 0; + ++ my $submenu_number = 0; ++ + while () { + if (/$target/) { + $grub_number++; + $found = 1; + last; ++ } elsif (defined($submenu) && /$submenu/) { ++ $submenu_number++; ++ $grub_number = -1; + } elsif (/$skip/) { + $grub_number++; + } +@@ -1890,6 +1895,9 @@ sub _get_grub_index { + + dodie "Could not find '$grub_menu' through $command on $machine" + if (!$found); ++ if ($submenu_number > 0) { ++ $grub_number = "$submenu_number>$grub_number"; ++ } + doprint "$grub_number\n"; + $last_grub_menu = $grub_menu; + $last_machine = $machine; +@@ -1936,6 +1944,7 @@ sub get_grub_index { + my $command; + my $target; + my $skip; ++ my $submenu; + my $grub_menu_qt; + + if ($reboot_type !~ /^grub/) { +@@ -1950,8 +1959,9 @@ sub get_grub_index { + $skip = '^\s*title\s'; + } elsif ($reboot_type eq "grub2") { + $command = "cat $grub_file"; +- $target = '^menuentry.*' . $grub_menu_qt; +- $skip = '^menuentry\s|^submenu\s'; ++ $target = '^\s*menuentry.*' . $grub_menu_qt; ++ $skip = '^\s*menuentry'; ++ $submenu = '^\s*submenu\s'; + } elsif ($reboot_type eq "grub2bls") { + $command = $grub_bls_get; + $target = '^title=.*' . $grub_menu_qt; +@@ -1960,7 +1970,7 @@ sub get_grub_index { + return; + } + +- _get_grub_index($command, $target, $skip); ++ _get_grub_index($command, $target, $skip, $submenu); + } + + sub wait_for_input +@@ -2024,7 +2034,7 @@ sub reboot_to { + if ($reboot_type eq "grub") { + run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'"; + } elsif (($reboot_type eq "grub2") or ($reboot_type eq "grub2bls")) { +- run_ssh "$grub_reboot $grub_number"; ++ run_ssh "$grub_reboot \"'$grub_number'\""; + } elsif ($reboot_type eq "syslinux") { + run_ssh "$syslinux --once \\\"$syslinux_label\\\" $syslinux_path"; + } elsif (defined $reboot_script) { +-- +2.35.1 + diff --git a/queue-4.19/ktest-add-support-for-meta-characters-in-grub_menu.patch b/queue-4.19/ktest-add-support-for-meta-characters-in-grub_menu.patch new file mode 100644 index 00000000000..079423565f4 --- /dev/null +++ b/queue-4.19/ktest-add-support-for-meta-characters-in-grub_menu.patch @@ -0,0 +1,58 @@ +From 00893dd3710e13e7ecf9a3110d31d6deb4d51674 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 17 Apr 2019 19:58:23 -0400 +Subject: ktest: Add support for meta characters in GRUB_MENU + +From: Masayoshi Mizuma + +[ Upstream commit 68911069f509ba3bf0f513d9af00309e07932906 ] + +ktest fails if meta characters are in GRUB_MENU, for example +GRUB_MENU = 'Fedora (test)' + +The failure happens because the meta characters are not escaped, +so the menu doesn't match in any entries in GRUB_FILE. + +Use quotemeta() to escape the meta characters. + +Link: http://lkml.kernel.org/r/20190417235823.18176-1-msys.mizuma@gmail.com + +Signed-off-by: Masayoshi Mizuma +Signed-off-by: Steven Rostedt (VMware) +Stable-dep-of: 26df05a8c142 ("kest.pl: Fix grub2 menu handling for rebooting") +Signed-off-by: Sasha Levin +--- + tools/testing/ktest/ktest.pl | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl +index 92663d123be1..635121ecf543 100755 +--- a/tools/testing/ktest/ktest.pl ++++ b/tools/testing/ktest/ktest.pl +@@ -1866,9 +1866,10 @@ sub get_grub2_index { + or dodie "unable to get $grub_file"; + + my $found = 0; ++ my $grub_menu_qt = quotemeta($grub_menu); + + while () { +- if (/^menuentry.*$grub_menu/) { ++ if (/^menuentry.*$grub_menu_qt/) { + $grub_number++; + $found = 1; + last; +@@ -1909,9 +1910,10 @@ sub get_grub_index { + or dodie "unable to get menu.lst"; + + my $found = 0; ++ my $grub_menu_qt = quotemeta($grub_menu); + + while () { +- if (/^\s*title\s+$grub_menu\s*$/) { ++ if (/^\s*title\s+$grub_menu_qt\s*$/) { + $grub_number++; + $found = 1; + last; +-- +2.35.1 + diff --git a/queue-4.19/ktest-cleanup-get_grub_index.patch b/queue-4.19/ktest-cleanup-get_grub_index.patch new file mode 100644 index 00000000000..ede373676ea --- /dev/null +++ b/queue-4.19/ktest-cleanup-get_grub_index.patch @@ -0,0 +1,92 @@ +From f056a77a93c17e5c10f6b6bb3401470ef2a4b78b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 May 2019 17:36:43 -0400 +Subject: ktest: cleanup get_grub_index + +From: Masayoshi Mizuma + +[ Upstream commit 38891392916c42d4ba46f474d553c76d1ed329ca ] + +Cleanup get_grub_index(). + +Link: http://lkml.kernel.org/r/20190509213647.6276-3-msys.mizuma@gmail.com + +Signed-off-by: Masayoshi Mizuma +Signed-off-by: Steven Rostedt (VMware) +Stable-dep-of: 26df05a8c142 ("kest.pl: Fix grub2 menu handling for rebooting") +Signed-off-by: Sasha Levin +--- + tools/testing/ktest/ktest.pl | 50 ++++++++++++------------------------ + 1 file changed, 17 insertions(+), 33 deletions(-) + +diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl +index 5fa60b3c564f..a1067469ba0e 100755 +--- a/tools/testing/ktest/ktest.pl ++++ b/tools/testing/ktest/ktest.pl +@@ -1925,46 +1925,30 @@ sub get_grub2_index { + + sub get_grub_index { + +- if ($reboot_type eq "grub2") { +- get_grub2_index; +- return; +- } ++ my $command; ++ my $target; ++ my $skip; ++ my $grub_menu_qt; + +- if ($reboot_type ne "grub") { ++ if ($reboot_type !~ /^grub/) { + return; + } +- return if (defined($grub_number) && defined($last_grub_menu) && +- $last_grub_menu eq $grub_menu && defined($last_machine) && +- $last_machine eq $machine); +- +- doprint "Find grub menu ... "; +- $grub_number = -1; + +- my $ssh_grub = $ssh_exec; +- $ssh_grub =~ s,\$SSH_COMMAND,cat /boot/grub/menu.lst,g; +- +- open(IN, "$ssh_grub |") +- or dodie "unable to get menu.lst"; ++ $grub_menu_qt = quotemeta($grub_menu); + +- my $found = 0; +- my $grub_menu_qt = quotemeta($grub_menu); +- +- while () { +- if (/^\s*title\s+$grub_menu_qt\s*$/) { +- $grub_number++; +- $found = 1; +- last; +- } elsif (/^\s*title\s/) { +- $grub_number++; +- } ++ if ($reboot_type eq "grub") { ++ $command = "cat /boot/grub/menu.lst"; ++ $target = '^\s*title\s+' . $grub_menu_qt . '\s*$'; ++ $skip = '^\s*title\s'; ++ } elsif ($reboot_type eq "grub2") { ++ $command = "cat $grub_file"; ++ $target = '^menuentry.*' . $grub_menu_qt; ++ $skip = '^menuentry\s|^submenu\s'; ++ } else { ++ return; + } +- close(IN); + +- dodie "Could not find '$grub_menu' in /boot/grub/menu on $machine" +- if (!$found); +- doprint "$grub_number\n"; +- $last_grub_menu = $grub_menu; +- $last_machine = $machine; ++ _get_grub_index($command, $target, $skip); + } + + sub wait_for_input +-- +2.35.1 + diff --git a/queue-4.19/ktest-introduce-_get_grub_index.patch b/queue-4.19/ktest-introduce-_get_grub_index.patch new file mode 100644 index 00000000000..1bc1650aef0 --- /dev/null +++ b/queue-4.19/ktest-introduce-_get_grub_index.patch @@ -0,0 +1,73 @@ +From 0ccee5cb4ab817d238b06632a8af2443c69f02b8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 May 2019 17:36:42 -0400 +Subject: ktest: introduce _get_grub_index + +From: Masayoshi Mizuma + +[ Upstream commit f824b6866835bc5051c44ffd289134974f214e98 ] + +Introduce _get_grub_index() to deal with Boot Loader +Specification (BLS) and cleanup. + +Link: http://lkml.kernel.org/r/20190509213647.6276-2-msys.mizuma@gmail.com + +Signed-off-by: Masayoshi Mizuma +Signed-off-by: Steven Rostedt (VMware) +Stable-dep-of: 26df05a8c142 ("kest.pl: Fix grub2 menu handling for rebooting") +Signed-off-by: Sasha Levin +--- + tools/testing/ktest/ktest.pl | 37 ++++++++++++++++++++++++++++++++++++ + 1 file changed, 37 insertions(+) + +diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl +index 635121ecf543..5fa60b3c564f 100755 +--- a/tools/testing/ktest/ktest.pl ++++ b/tools/testing/ktest/ktest.pl +@@ -1850,6 +1850,43 @@ sub run_scp_mod { + return run_scp($src, $dst, $cp_scp); + } + ++sub _get_grub_index { ++ ++ my ($command, $target, $skip) = @_; ++ ++ return if (defined($grub_number) && defined($last_grub_menu) && ++ $last_grub_menu eq $grub_menu && defined($last_machine) && ++ $last_machine eq $machine); ++ ++ doprint "Find $reboot_type menu ... "; ++ $grub_number = -1; ++ ++ my $ssh_grub = $ssh_exec; ++ $ssh_grub =~ s,\$SSH_COMMAND,$command,g; ++ ++ open(IN, "$ssh_grub |") ++ or dodie "unable to execute $command"; ++ ++ my $found = 0; ++ ++ while () { ++ if (/$target/) { ++ $grub_number++; ++ $found = 1; ++ last; ++ } elsif (/$skip/) { ++ $grub_number++; ++ } ++ } ++ close(IN); ++ ++ dodie "Could not find '$grub_menu' through $command on $machine" ++ if (!$found); ++ doprint "$grub_number\n"; ++ $last_grub_menu = $grub_menu; ++ $last_machine = $machine; ++} ++ + sub get_grub2_index { + + return if (defined($grub_number) && defined($last_grub_menu) && +-- +2.35.1 + diff --git a/queue-4.19/ktest-introduce-grub2bls-reboot_type-option.patch b/queue-4.19/ktest-introduce-grub2bls-reboot_type-option.patch new file mode 100644 index 00000000000..c083352d8ee --- /dev/null +++ b/queue-4.19/ktest-introduce-grub2bls-reboot_type-option.patch @@ -0,0 +1,115 @@ +From 895503847551777f218c09eee0fe4c35c07bb2cd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 9 May 2019 17:36:44 -0400 +Subject: ktest: introduce grub2bls REBOOT_TYPE option + +From: Masayoshi Mizuma + +[ Upstream commit ac2466456eaa0ff9b8cf647c4c52832024bc929f ] + +Fedora 30 introduces Boot Loader Specification (BLS), +it changes around grub entry configuration. + +kernel entries aren't in grub.cfg. We can get the entries +by "grubby --info=ALL" command. + +Introduce grub2bls as REBOOT_TYPE option for BLS. + +Link: http://lkml.kernel.org/r/20190509213647.6276-4-msys.mizuma@gmail.com + +Signed-off-by: Masayoshi Mizuma +Signed-off-by: Steven Rostedt (VMware) +Stable-dep-of: 26df05a8c142 ("kest.pl: Fix grub2 menu handling for rebooting") +Signed-off-by: Sasha Levin +--- + tools/testing/ktest/ktest.pl | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl +index a1067469ba0e..76468e2d619f 100755 +--- a/tools/testing/ktest/ktest.pl ++++ b/tools/testing/ktest/ktest.pl +@@ -63,6 +63,7 @@ my %default = ( + "STOP_TEST_AFTER" => 600, + "MAX_MONITOR_WAIT" => 1800, + "GRUB_REBOOT" => "grub2-reboot", ++ "GRUB_BLS_GET" => "grubby --info=ALL", + "SYSLINUX" => "extlinux", + "SYSLINUX_PATH" => "/boot/extlinux", + "CONNECT_TIMEOUT" => 25, +@@ -123,6 +124,7 @@ my $last_grub_menu; + my $grub_file; + my $grub_number; + my $grub_reboot; ++my $grub_bls_get; + my $syslinux; + my $syslinux_path; + my $syslinux_label; +@@ -292,6 +294,7 @@ my %option_map = ( + "GRUB_MENU" => \$grub_menu, + "GRUB_FILE" => \$grub_file, + "GRUB_REBOOT" => \$grub_reboot, ++ "GRUB_BLS_GET" => \$grub_bls_get, + "SYSLINUX" => \$syslinux, + "SYSLINUX_PATH" => \$syslinux_path, + "SYSLINUX_LABEL" => \$syslinux_label, +@@ -437,7 +440,7 @@ EOF + ; + $config_help{"REBOOT_TYPE"} = << "EOF" + Way to reboot the box to the test kernel. +- Only valid options so far are "grub", "grub2", "syslinux", and "script". ++ Only valid options so far are "grub", "grub2", "grub2bls", "syslinux", and "script". + + If you specify grub, it will assume grub version 1 + and will search in /boot/grub/menu.lst for the title \$GRUB_MENU +@@ -451,6 +454,8 @@ $config_help{"REBOOT_TYPE"} = << "EOF" + If you specify grub2, then you also need to specify both \$GRUB_MENU + and \$GRUB_FILE. + ++ If you specify grub2bls, then you also need to specify \$GRUB_MENU. ++ + If you specify syslinux, then you may use SYSLINUX to define the syslinux + command (defaults to extlinux), and SYSLINUX_PATH to specify the path to + the syslinux install (defaults to /boot/extlinux). But you have to specify +@@ -476,6 +481,9 @@ $config_help{"GRUB_MENU"} = << "EOF" + menu must be a non-nested menu. Add the quotes used in the menu + to guarantee your selection, as the first menuentry with the content + of \$GRUB_MENU that is found will be used. ++ ++ For grub2bls, \$GRUB_MENU is searched on the result of \$GRUB_BLS_GET ++ command for the lines that begin with "title". + EOF + ; + $config_help{"GRUB_FILE"} = << "EOF" +@@ -692,7 +700,7 @@ sub get_mandatory_configs { + } + } + +- if ($rtype eq "grub") { ++ if (($rtype eq "grub") or ($rtype eq "grub2bls")) { + get_mandatory_config("GRUB_MENU"); + } + +@@ -1944,6 +1952,10 @@ sub get_grub_index { + $command = "cat $grub_file"; + $target = '^menuentry.*' . $grub_menu_qt; + $skip = '^menuentry\s|^submenu\s'; ++ } elsif ($reboot_type eq "grub2bls") { ++ $command = $grub_bls_get; ++ $target = '^title=.*' . $grub_menu_qt; ++ $skip = '^title='; + } else { + return; + } +@@ -4307,7 +4319,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) { + + if (!$buildonly) { + $target = "$ssh_user\@$machine"; +- if ($reboot_type eq "grub") { ++ if (($reboot_type eq "grub") or ($reboot_type eq "grub2bls")) { + dodie "GRUB_MENU not defined" if (!defined($grub_menu)); + } elsif ($reboot_type eq "grub2") { + dodie "GRUB_MENU not defined" if (!defined($grub_menu)); +-- +2.35.1 + diff --git a/queue-4.19/ktest.pl-fix-incorrect-reboot-for-grub2bls.patch b/queue-4.19/ktest.pl-fix-incorrect-reboot-for-grub2bls.patch new file mode 100644 index 00000000000..eab0e466183 --- /dev/null +++ b/queue-4.19/ktest.pl-fix-incorrect-reboot-for-grub2bls.patch @@ -0,0 +1,51 @@ +From 37af8e738417415b592907ed48bebb0b975af426 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Nov 2020 18:12:43 -0800 +Subject: ktest.pl: Fix incorrect reboot for grub2bls + +From: Libo Chen + +[ Upstream commit 271e0c9dce1b02a825b3cc1a7aa1fab7c381d44b ] + +This issue was first noticed when I was testing different kernels on +Oracle Linux 8 which as Fedora 30+ adopts BLS as default. Even though a +kernel entry was added successfully and the index of that kernel entry was +retrieved correctly, ktest still wouldn't reboot the system into +user-specified kernel. + +The bug was spotted in subroutine reboot_to where the if-statement never +checks for REBOOT_TYPE "grub2bls", therefore the desired entry will not be +set for the next boot. + +Add a check for "grub2bls" so that $grub_reboot $grub_number can +be run before a reboot if REBOOT_TYPE is "grub2bls" then we can boot to +the correct kernel. + +Link: https://lkml.kernel.org/r/20201121021243.1532477-1-libo.chen@oracle.com + +Cc: stable@vger.kernel.org +Fixes: ac2466456eaa ("ktest: introduce grub2bls REBOOT_TYPE option") +Signed-off-by: Libo Chen +Signed-off-by: Steven Rostedt (VMware) +Stable-dep-of: 26df05a8c142 ("kest.pl: Fix grub2 menu handling for rebooting") +Signed-off-by: Sasha Levin +--- + tools/testing/ktest/ktest.pl | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl +index 76468e2d619f..689fa4fd3d76 100755 +--- a/tools/testing/ktest/ktest.pl ++++ b/tools/testing/ktest/ktest.pl +@@ -2023,7 +2023,7 @@ sub reboot_to { + + if ($reboot_type eq "grub") { + run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'"; +- } elsif ($reboot_type eq "grub2") { ++ } elsif (($reboot_type eq "grub2") or ($reboot_type eq "grub2bls")) { + run_ssh "$grub_reboot $grub_number"; + } elsif ($reboot_type eq "syslinux") { + run_ssh "$syslinux --once \\\"$syslinux_label\\\" $syslinux_path"; +-- +2.35.1 + diff --git a/queue-4.19/quota-factor-out-setup-of-quota-inode.patch b/queue-4.19/quota-factor-out-setup-of-quota-inode.patch new file mode 100644 index 00000000000..38bc6c15786 --- /dev/null +++ b/queue-4.19/quota-factor-out-setup-of-quota-inode.patch @@ -0,0 +1,192 @@ +From a99d6a0b738922dd1fcb3cf8a5d6378ec49b7a02 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Nov 2019 17:45:31 +0100 +Subject: quota: Factor out setup of quota inode + +From: Jan Kara + +[ Upstream commit c7d3d28360fdb3ed3a5aa0bab19315e0fdc994a1 ] + +Factor out setting up of quota inode and eventual error cleanup from +vfs_load_quota_inode(). This will simplify situation for filesystems +that don't have any quota inodes. + +Signed-off-by: Jan Kara +Stable-dep-of: d32387748476 ("ext4: fix bug_on in __es_tree_search caused by bad quota inode") +Signed-off-by: Sasha Levin +--- + fs/quota/dquot.c | 108 ++++++++++++++++++++++++--------------- + include/linux/quotaops.h | 2 + + 2 files changed, 69 insertions(+), 41 deletions(-) + +diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c +index ddb379abd919..a1d2aed0d833 100644 +--- a/fs/quota/dquot.c ++++ b/fs/quota/dquot.c +@@ -2298,28 +2298,60 @@ EXPORT_SYMBOL(dquot_quota_off); + * Turn quotas on on a device + */ + +-/* +- * Helper function to turn quotas on when we already have the inode of +- * quota file and no quota information is loaded. +- */ +-static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, ++static int vfs_setup_quota_inode(struct inode *inode, int type) ++{ ++ struct super_block *sb = inode->i_sb; ++ struct quota_info *dqopt = sb_dqopt(sb); ++ ++ if (!S_ISREG(inode->i_mode)) ++ return -EACCES; ++ if (IS_RDONLY(inode)) ++ return -EROFS; ++ if (sb_has_quota_loaded(sb, type)) ++ return -EBUSY; ++ ++ dqopt->files[type] = igrab(inode); ++ if (!dqopt->files[type]) ++ return -EIO; ++ if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { ++ /* We don't want quota and atime on quota files (deadlocks ++ * possible) Also nobody should write to the file - we use ++ * special IO operations which ignore the immutable bit. */ ++ inode_lock(inode); ++ inode->i_flags |= S_NOQUOTA; ++ inode_unlock(inode); ++ /* ++ * When S_NOQUOTA is set, remove dquot references as no more ++ * references can be added ++ */ ++ __dquot_drop(inode); ++ } ++ return 0; ++} ++ ++static void vfs_cleanup_quota_inode(struct super_block *sb, int type) ++{ ++ struct quota_info *dqopt = sb_dqopt(sb); ++ struct inode *inode = dqopt->files[type]; ++ ++ if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { ++ inode_lock(inode); ++ inode->i_flags &= ~S_NOQUOTA; ++ inode_unlock(inode); ++ } ++ dqopt->files[type] = NULL; ++ iput(inode); ++} ++ ++int dquot_load_quota_sb(struct super_block *sb, int type, int format_id, + unsigned int flags) + { + struct quota_format_type *fmt = find_quota_format(format_id); +- struct super_block *sb = inode->i_sb; + struct quota_info *dqopt = sb_dqopt(sb); + int error; + + if (!fmt) + return -ESRCH; +- if (!S_ISREG(inode->i_mode)) { +- error = -EACCES; +- goto out_fmt; +- } +- if (IS_RDONLY(inode)) { +- error = -EROFS; +- goto out_fmt; +- } + if (!sb->s_op->quota_write || !sb->s_op->quota_read || + (type == PRJQUOTA && sb->dq_op->get_projid == NULL)) { + error = -EINVAL; +@@ -2351,27 +2383,9 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, + invalidate_bdev(sb->s_bdev); + } + +- if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { +- /* We don't want quota and atime on quota files (deadlocks +- * possible) Also nobody should write to the file - we use +- * special IO operations which ignore the immutable bit. */ +- inode_lock(inode); +- inode->i_flags |= S_NOQUOTA; +- inode_unlock(inode); +- /* +- * When S_NOQUOTA is set, remove dquot references as no more +- * references can be added +- */ +- __dquot_drop(inode); +- } +- +- error = -EIO; +- dqopt->files[type] = igrab(inode); +- if (!dqopt->files[type]) +- goto out_file_flags; + error = -EINVAL; + if (!fmt->qf_ops->check_quota_file(sb, type)) +- goto out_file_init; ++ goto out_fmt; + + dqopt->ops[type] = fmt->qf_ops; + dqopt->info[type].dqi_format = fmt; +@@ -2379,7 +2393,7 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, + INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list); + error = dqopt->ops[type]->read_file_info(sb, type); + if (error < 0) +- goto out_file_init; ++ goto out_fmt; + if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) { + spin_lock(&dq_data_lock); + dqopt->info[type].dqi_flags |= DQF_SYS_FILE; +@@ -2394,18 +2408,30 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, + dquot_disable(sb, type, flags); + + return error; +-out_file_init: +- dqopt->files[type] = NULL; +- iput(inode); +-out_file_flags: +- inode_lock(inode); +- inode->i_flags &= ~S_NOQUOTA; +- inode_unlock(inode); + out_fmt: + put_quota_format(fmt); + + return error; + } ++EXPORT_SYMBOL(dquot_load_quota_sb); ++ ++/* ++ * Helper function to turn quotas on when we already have the inode of ++ * quota file and no quota information is loaded. ++ */ ++static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, ++ unsigned int flags) ++{ ++ int err; ++ ++ err = vfs_setup_quota_inode(inode, type); ++ if (err < 0) ++ return err; ++ err = dquot_load_quota_sb(inode->i_sb, type, format_id, flags); ++ if (err < 0) ++ vfs_cleanup_quota_inode(inode->i_sb, type); ++ return err; ++} + + /* Reenable quotas on remount RW */ + int dquot_resume(struct super_block *sb, int type) +diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h +index 91e0b7624053..ec10897f7f60 100644 +--- a/include/linux/quotaops.h ++++ b/include/linux/quotaops.h +@@ -99,6 +99,8 @@ int dquot_file_open(struct inode *inode, struct file *file); + + int dquot_enable(struct inode *inode, int type, int format_id, + unsigned int flags); ++int dquot_load_quota_sb(struct super_block *sb, int type, int format_id, ++ unsigned int flags); + int dquot_quota_on(struct super_block *sb, int type, int format_id, + const struct path *path); + int dquot_quota_on_mount(struct super_block *sb, char *qf_name, +-- +2.35.1 + diff --git a/queue-4.19/series b/queue-4.19/series index 616ba7d1c50..22fff145982 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -468,3 +468,31 @@ perf-auxtrace-fix-address-filter-duplicate-symbol-selection.patch s390-percpu-add-read_once-to-arch_this_cpu_to_op_simple.patch net-ulp-prevent-ulp-without-clone-op-from-entering-the-listen-status.patch alsa-pcm-move-rwsem-lock-inside-snd_ctl_elem_read-to-prevent-uaf.patch +wifi-wilc1000-sdio-fix-module-autoloading.patch +alsa-hda-hdmi-fix-failures-at-pcm-open-on-intel-icl-.patch +add-acer-aspire-ethos-8951g-model-quirk.patch +alsa-hda-realtek-more-constifications.patch +alsa-hda-realtek-add-headset-mic-supported-for-hp-cp.patch +alsa-hda-realtek-enable-headset-mic-of-acer-x2660g-w.patch +alsa-hda-realtek-enable-the-headset-of-acer-n50-600-.patch +alsa-hda-realtek-the-front-mic-on-a-hp-machine-doesn.patch +alsa-hda-realtek-fix-the-mic-type-detection-issue-fo.patch +alsa-hda-realtek-add-headset-mic-support-for-lenovo-.patch +alsa-hda-realtek-alc897-headset-mic-no-sound.patch +alsa-hda-realtek-add-quirk-for-lenovo-tianyi510pro-1.patch +ktest-add-support-for-meta-characters-in-grub_menu.patch +ktest-introduce-_get_grub_index.patch +ktest-cleanup-get_grub_index.patch +ktest-introduce-grub2bls-reboot_type-option.patch +ktest.pl-fix-incorrect-reboot-for-grub2bls.patch +kest.pl-fix-grub2-menu-handling-for-rebooting.patch +usb-ulpi-defer-ulpi_register-on-ulpi_read_id-timeout.patch +quota-factor-out-setup-of-quota-inode.patch +ext4-fix-bug_on-in-__es_tree_search-caused-by-bad-qu.patch +ext4-lost-matching-pair-of-trace-in-ext4_truncate.patch +ext4-fix-use-after-free-in-ext4_orphan_cleanup.patch +ext4-fix-uninititialized-value-in-ext4_evict_inode.patch +ext4-generalize-extents-status-tree-search-functions.patch +ext4-add-new-pending-reservation-mechanism.patch +ext4-fix-reserved-cluster-accounting-at-delayed-writ.patch +ext4-fix-delayed-allocation-bug-in-ext4_clu_mapped-f.patch diff --git a/queue-4.19/usb-ulpi-defer-ulpi_register-on-ulpi_read_id-timeout.patch b/queue-4.19/usb-ulpi-defer-ulpi_register-on-ulpi_read_id-timeout.patch new file mode 100644 index 00000000000..214ccfc2e97 --- /dev/null +++ b/queue-4.19/usb-ulpi-defer-ulpi_register-on-ulpi_read_id-timeout.patch @@ -0,0 +1,49 @@ +From 85a42569f5edafb3142250de260797938db4f826 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Dec 2022 21:15:26 +0100 +Subject: usb: ulpi: defer ulpi_register on ulpi_read_id timeout + +From: Ferry Toth + +[ Upstream commit 8a7b31d545d3a15f0e6f5984ae16f0ca4fd76aac ] + +Since commit 0f0101719138 ("usb: dwc3: Don't switch OTG -> peripheral +if extcon is present") Dual Role support on Intel Merrifield platform +broke due to rearranging the call to dwc3_get_extcon(). + +It appears to be caused by ulpi_read_id() on the first test write failing +with -ETIMEDOUT. Currently ulpi_read_id() expects to discover the phy via +DT when the test write fails and returns 0 in that case, even if DT does not +provide the phy. As a result usb probe completes without phy. + +Make ulpi_read_id() return -ETIMEDOUT to its user if the first test write +fails. The user should then handle it appropriately. A follow up patch +will make dwc3_core_init() set -EPROBE_DEFER in this case and bail out. + +Fixes: ef6a7bcfb01c ("usb: ulpi: Support device discovery via DT") +Cc: stable@vger.kernel.org +Acked-by: Heikki Krogerus +Signed-off-by: Ferry Toth +Link: https://lore.kernel.org/r/20221205201527.13525-2-ftoth@exalondelft.nl +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/common/ulpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c +index c42c152bbc33..94700c1d2f6e 100644 +--- a/drivers/usb/common/ulpi.c ++++ b/drivers/usb/common/ulpi.c +@@ -207,7 +207,7 @@ static int ulpi_read_id(struct ulpi *ulpi) + /* Test the interface */ + ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa); + if (ret < 0) +- goto err; ++ return ret; + + ret = ulpi_read(ulpi, ULPI_SCRATCH); + if (ret < 0) +-- +2.35.1 + diff --git a/queue-4.19/wifi-wilc1000-sdio-fix-module-autoloading.patch b/queue-4.19/wifi-wilc1000-sdio-fix-module-autoloading.patch new file mode 100644 index 00000000000..d8450f348fe --- /dev/null +++ b/queue-4.19/wifi-wilc1000-sdio-fix-module-autoloading.patch @@ -0,0 +1,36 @@ +From 3f6ef7bc16eca5d3b22f708134e5dfe0a440a6b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Oct 2022 19:12:21 +0200 +Subject: wifi: wilc1000: sdio: fix module autoloading + +From: Michael Walle + +[ Upstream commit 57d545b5a3d6ce3a8fb6b093f02bfcbb908973f3 ] + +There are no SDIO module aliases included in the driver, therefore, +module autoloading isn't working. Add the proper MODULE_DEVICE_TABLE(). + +Cc: stable@vger.kernel.org +Signed-off-by: Michael Walle +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221027171221.491937-1-michael@walle.cc +Signed-off-by: Sasha Levin +--- + drivers/staging/wilc1000/wilc_sdio.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c +index e52c3bdeaf04..b4d456f3fb1b 100644 +--- a/drivers/staging/wilc1000/wilc_sdio.c ++++ b/drivers/staging/wilc1000/wilc_sdio.c +@@ -18,6 +18,7 @@ static const struct sdio_device_id wilc_sdio_ids[] = { + { SDIO_DEVICE(SDIO_VENDOR_ID_WILC, SDIO_DEVICE_ID_WILC) }, + { }, + }; ++MODULE_DEVICE_TABLE(sdio, wilc_sdio_ids); + + #define WILC_SDIO_BLOCK_SIZE 512 + +-- +2.35.1 +