--- /dev/null
+From 744a11abc56405c5a106e63da30a941b6d27f737 Mon Sep 17 00:00:00 2001
+From: bo liu <bo.liu@senarytech.com>
+Date: Tue, 29 Dec 2020 11:52:26 +0800
+Subject: ALSA: hda/conexant: add a new hda codec CX11970
+
+From: bo liu <bo.liu@senarytech.com>
+
+commit 744a11abc56405c5a106e63da30a941b6d27f737 upstream.
+
+The current kernel does not support the cx11970 codec chip.
+Add a codec configuration item to kernel.
+
+[ Minor coding style fix by tiwai ]
+
+Signed-off-by: bo liu <bo.liu@senarytech.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20201229035226.62120-1-bo.liu@senarytech.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/pci/hda/patch_conexant.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/pci/hda/patch_conexant.c
++++ b/sound/pci/hda/patch_conexant.c
+@@ -1070,6 +1070,7 @@ static int patch_conexant_auto(struct hd
+ static const struct hda_device_id snd_hda_id_conexant[] = {
+ HDA_CODEC_ENTRY(0x14f11f86, "CX8070", patch_conexant_auto),
+ HDA_CODEC_ENTRY(0x14f12008, "CX8200", patch_conexant_auto),
++ HDA_CODEC_ENTRY(0x14f120d0, "CX11970", patch_conexant_auto),
+ HDA_CODEC_ENTRY(0x14f15045, "CX20549 (Venice)", patch_conexant_auto),
+ HDA_CODEC_ENTRY(0x14f15047, "CX20551 (Waikiki)", patch_conexant_auto),
+ HDA_CODEC_ENTRY(0x14f15051, "CX20561 (Hermosa)", patch_conexant_auto),
--- /dev/null
+From 484229585a5e91eeb00ee10e05d5204e1ca6c481 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Manuel=20Jim=C3=A9nez?= <mjbfm99@me.com>
+Date: Tue, 29 Dec 2020 15:38:56 +0100
+Subject: ALSA: hda/realtek: Add mute LED quirk for more HP laptops
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Manuel Jiménez <mjbfm99@me.com>
+
+commit 484229585a5e91eeb00ee10e05d5204e1ca6c481 upstream.
+
+HP Pavilion 13-bb0000 (SSID 103c:87c8) needs the same
+quirk as other models with ALC287.
+
+Signed-off-by: Manuel Jiménez <mjbfm99@me.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/X+s/gKNydVrI6nLj@HP-Pavilion-13
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/pci/hda/patch_realtek.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -7969,6 +7969,7 @@ static const struct snd_pci_quirk alc269
+ SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED),
+ SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED),
+ SND_PCI_QUIRK(0x103c, 0x877d, "HP", ALC236_FIXUP_HP_MUTE_LED),
++ SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
--- /dev/null
+From ce2e79b223867b9e586021b55dee7035517a236b Mon Sep 17 00:00:00 2001
+From: PeiSen Hou <pshou@realtek.com>
+Date: Thu, 31 Dec 2020 11:57:28 +0100
+Subject: ALSA: hda/realtek: Add two "Intel Reference board" SSID in the ALC256.
+
+From: PeiSen Hou <pshou@realtek.com>
+
+commit ce2e79b223867b9e586021b55dee7035517a236b upstream.
+
+Add two "Intel Reference boad" SSID in the alc256.
+Enable "power saving mode" and Enable "headset jack mode".
+
+Signed-off-by: PeiSen Hou <pshou@realtek.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/5978d2267f034c28973d117925ec9c63@realtek.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/pci/hda/patch_realtek.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -8028,6 +8028,8 @@ static const struct snd_pci_quirk alc269
+ SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
+ SND_PCI_QUIRK(0x10ec, 0x10f2, "Intel Reference board", ALC700_FIXUP_INTEL_REFERENCE),
+ SND_PCI_QUIRK(0x10ec, 0x1230, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
++ SND_PCI_QUIRK(0x10ec, 0x1252, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
++ SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
+ SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE),
+ SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
+ SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
--- /dev/null
+From a598098cc9737f612dbab52294433fc26c51cc9b Mon Sep 17 00:00:00 2001
+From: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Date: Wed, 30 Dec 2020 20:56:35 +0800
+Subject: ALSA: hda/realtek: Enable mute and micmute LED on HP EliteBook 850 G7
+
+From: Kai-Heng Feng <kai.heng.feng@canonical.com>
+
+commit a598098cc9737f612dbab52294433fc26c51cc9b upstream.
+
+HP EliteBook 850 G7 uses the same GPIO pins as ALC285_FIXUP_HP_GPIO_LED
+to enable mute and micmute LED. So apply the quirk to enable the LEDs.
+
+Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20201230125636.45028-1-kai.heng.feng@canonical.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/pci/hda/patch_realtek.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -7964,6 +7964,7 @@ static const struct snd_pci_quirk alc269
+ SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+ SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+ SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED),
++ SND_PCI_QUIRK(0x103c, 0x8724, "HP EliteBook 850 G7", ALC285_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8729, "HP", ALC285_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+ SND_PCI_QUIRK(0x103c, 0x8760, "HP", ALC285_FIXUP_HP_MUTE_LED),
--- /dev/null
+From f86de9b1c0663b0a3ca2dcddec9aa910ff0fbf2c Mon Sep 17 00:00:00 2001
+From: Kailang Yang <kailang@realtek.com>
+Date: Fri, 23 Oct 2020 14:46:47 +0800
+Subject: ALSA: hda/realtek - Fix speaker volume control on Lenovo C940
+
+From: Kailang Yang <kailang@realtek.com>
+
+commit f86de9b1c0663b0a3ca2dcddec9aa910ff0fbf2c upstream.
+
+Cannot adjust speaker's volume on Lenovo C940.
+Applying the alc298_fixup_speaker_volume function can fix the issue.
+
+[ Additional note: C940 has I2S amp for the speaker and this needs the
+ same initialization as Dell machines.
+ The patch was slightly modified so that the quirk entry is moved
+ next to the corresponding Dell quirk entry. -- tiwai ]
+
+Signed-off-by: Kailang Yang <kailang@realtek.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/ea25b4e5c468491aa2e9d6cb1f2fced3@realtek.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/pci/hda/patch_realtek.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -6289,6 +6289,7 @@ enum {
+ ALC221_FIXUP_HP_FRONT_MIC,
+ ALC292_FIXUP_TPT460,
+ ALC298_FIXUP_SPK_VOLUME,
++ ALC298_FIXUP_LENOVO_SPK_VOLUME,
+ ALC256_FIXUP_DELL_INSPIRON_7559_SUBWOOFER,
+ ALC269_FIXUP_ATIV_BOOK_8,
+ ALC221_FIXUP_HP_MIC_NO_PRESENCE,
+@@ -7119,6 +7120,10 @@ static const struct hda_fixup alc269_fix
+ .chained = true,
+ .chain_id = ALC298_FIXUP_DELL_AIO_MIC_NO_PRESENCE,
+ },
++ [ALC298_FIXUP_LENOVO_SPK_VOLUME] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = alc298_fixup_speaker_volume,
++ },
+ [ALC295_FIXUP_DISABLE_DAC3] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc295_fixup_disable_dac3,
+@@ -8126,6 +8131,7 @@ static const struct snd_pci_quirk alc269
+ SND_PCI_QUIRK(0x17aa, 0x3151, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x17aa, 0x3176, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
++ SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME),
+ SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
+ SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
+ SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
--- /dev/null
+From 4bfd6247fa9164c8e193a55ef9c0ea3ee22f82d8 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Mon, 4 Jan 2021 16:30:46 +0100
+Subject: ALSA: hda/via: Fix runtime PM for Clevo W35xSS
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit 4bfd6247fa9164c8e193a55ef9c0ea3ee22f82d8 upstream.
+
+Clevo W35xSS_370SS with VIA codec has had the runtime PM problem that
+looses the power state of some nodes after the runtime resume. This
+was worked around by disabling the default runtime PM via a denylist
+entry. Since 5.10.x made the runtime PM applied (casually) even
+though it's disabled in the denylist, this problem was revisited. The
+result was that disabling power_save_node feature suffices for the
+runtime PM problem.
+
+This patch implements the disablement of power_save_node feature in
+VIA codec for the device. It also drops the former denylist entry,
+too, as the runtime PM should work in the codec side properly now.
+
+Fixes: b529ef2464ad ("ALSA: hda: Add Clevo W35xSS_370SS to the power_save blacklist")
+Reported-by: Christian Labisch <clnetbox@gmail.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20210104153046.19993-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/pci/hda/hda_intel.c | 2 --
+ sound/pci/hda/patch_via.c | 13 +++++++++++++
+ 2 files changed, 13 insertions(+), 2 deletions(-)
+
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -2220,8 +2220,6 @@ static const struct snd_pci_quirk power_
+ SND_PCI_QUIRK(0x1849, 0x7662, "Asrock H81M-HDS", 0),
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
+ SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0),
+- /* https://bugzilla.redhat.com/show_bug.cgi?id=1581607 */
+- SND_PCI_QUIRK(0x1558, 0x3501, "Clevo W35xSS_370SS", 0),
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
+ SND_PCI_QUIRK(0x1558, 0x6504, "Clevo W65_67SB", 0),
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
+--- a/sound/pci/hda/patch_via.c
++++ b/sound/pci/hda/patch_via.c
+@@ -1002,6 +1002,7 @@ static const struct hda_verb vt1802_init
+ enum {
+ VIA_FIXUP_INTMIC_BOOST,
+ VIA_FIXUP_ASUS_G75,
++ VIA_FIXUP_POWER_SAVE,
+ };
+
+ static void via_fixup_intmic_boost(struct hda_codec *codec,
+@@ -1011,6 +1012,13 @@ static void via_fixup_intmic_boost(struc
+ override_mic_boost(codec, 0x30, 0, 2, 40);
+ }
+
++static void via_fixup_power_save(struct hda_codec *codec,
++ const struct hda_fixup *fix, int action)
++{
++ if (action == HDA_FIXUP_ACT_PRE_PROBE)
++ codec->power_save_node = 0;
++}
++
+ static const struct hda_fixup via_fixups[] = {
+ [VIA_FIXUP_INTMIC_BOOST] = {
+ .type = HDA_FIXUP_FUNC,
+@@ -1025,11 +1033,16 @@ static const struct hda_fixup via_fixups
+ { }
+ }
+ },
++ [VIA_FIXUP_POWER_SAVE] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = via_fixup_power_save,
++ },
+ };
+
+ static const struct snd_pci_quirk vt2002p_fixups[] = {
+ SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
+ SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
++ SND_PCI_QUIRK(0x1558, 0x3501, "Clevo W35xSS_370SS", VIA_FIXUP_POWER_SAVE),
+ {}
+ };
+
--- /dev/null
+From c06ccf3ebb7503706ea49fd248e709287ef385a3 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Wed, 23 Dec 2020 18:45:57 +0100
+Subject: ALSA: usb-audio: Fix UBSAN warnings for MIDI jacks
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit c06ccf3ebb7503706ea49fd248e709287ef385a3 upstream.
+
+The calculation of in_cables and out_cables bitmaps are done with the
+bit shift by the value from the descriptor, which is an arbitrary
+value, and can lead to UBSAN shift-out-of-bounds warnings.
+
+Fix it by filtering the bad descriptor values with the check of the
+upper bound 0x10 (the cable bitmaps are 16 bits).
+
+Reported-by: syzbot+92e45ae45543f89e8c88@syzkaller.appspotmail.com
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20201223174557.10249-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/usb/midi.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/sound/usb/midi.c
++++ b/sound/usb/midi.c
+@@ -1889,6 +1889,8 @@ static int snd_usbmidi_get_ms_info(struc
+ ms_ep = find_usb_ms_endpoint_descriptor(hostep);
+ if (!ms_ep)
+ continue;
++ if (ms_ep->bNumEmbMIDIJack > 0x10)
++ continue;
+ if (usb_endpoint_dir_out(ep)) {
+ if (endpoints[epidx].out_ep) {
+ if (++epidx >= MIDI_MAX_ENDPOINTS) {
+@@ -2141,6 +2143,8 @@ static int snd_usbmidi_detect_roland(str
+ cs_desc[1] == USB_DT_CS_INTERFACE &&
+ cs_desc[2] == 0xf1 &&
+ cs_desc[3] == 0x02) {
++ if (cs_desc[4] > 0x10 || cs_desc[5] > 0x10)
++ continue;
+ endpoint->in_cables = (1 << cs_desc[4]) - 1;
+ endpoint->out_cables = (1 << cs_desc[5]) - 1;
+ return snd_usbmidi_detect_endpoints(umidi, endpoint, 1);
--- /dev/null
+From 311bea3cb9ee20ef150ca76fc60a592bf6b159f5 Mon Sep 17 00:00:00 2001
+From: Nick Desaulniers <ndesaulniers@google.com>
+Date: Thu, 17 Dec 2020 16:24:32 -0800
+Subject: arm64: link with -z norelro for LLD or aarch64-elf
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Nick Desaulniers <ndesaulniers@google.com>
+
+commit 311bea3cb9ee20ef150ca76fc60a592bf6b159f5 upstream.
+
+With GNU binutils 2.35+, linking with BFD produces warnings for vmlinux:
+aarch64-linux-gnu-ld: warning: -z norelro ignored
+
+BFD can produce this warning when the target emulation mode does not
+support RELRO program headers, and -z relro or -z norelro is passed.
+
+Alan Modra clarifies:
+ The default linker emulation for an aarch64-linux ld.bfd is
+ -maarch64linux, the default for an aarch64-elf linker is
+ -maarch64elf. They are not equivalent. If you choose -maarch64elf
+ you get an emulation that doesn't support -z relro.
+
+The ARCH=arm64 kernel prefers -maarch64elf, but may fall back to
+-maarch64linux based on the toolchain configuration.
+
+LLD will always create RELRO program header regardless of target
+emulation.
+
+To avoid the above warning when linking with BFD, pass -z norelro only
+when linking with LLD or with -maarch64linux.
+
+Fixes: 3b92fa7485eb ("arm64: link with -z norelro regardless of CONFIG_RELOCATABLE")
+Fixes: 3bbd3db86470 ("arm64: relocatable: fix inconsistencies in linker script and options")
+Cc: <stable@vger.kernel.org> # 5.0.x-
+Reported-by: kernelci.org bot <bot@kernelci.org>
+Reported-by: Quentin Perret <qperret@google.com>
+Signed-off-by: Nick Desaulniers <ndesaulniers@google.com>
+Reviewed-by: Nathan Chancellor <natechancellor@gmail.com>
+Acked-by: Ard Biesheuvel <ardb@kernel.org>
+Cc: Alan Modra <amodra@gmail.com>
+Cc: Fāng-ruì Sòng <maskray@google.com>
+Link: https://lore.kernel.org/r/20201218002432.788499-1-ndesaulniers@google.com
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/Makefile | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+--- a/arch/arm64/Makefile
++++ b/arch/arm64/Makefile
+@@ -10,7 +10,7 @@
+ #
+ # Copyright (C) 1995-2001 by Russell King
+
+-LDFLAGS_vmlinux :=--no-undefined -X -z norelro
++LDFLAGS_vmlinux :=--no-undefined -X
+
+ ifeq ($(CONFIG_RELOCATABLE), y)
+ # Pass --no-apply-dynamic-relocs to restore pre-binutils-2.27 behaviour
+@@ -110,16 +110,20 @@ KBUILD_CPPFLAGS += -mbig-endian
+ CHECKFLAGS += -D__AARCH64EB__
+ # Prefer the baremetal ELF build target, but not all toolchains include
+ # it so fall back to the standard linux version if needed.
+-KBUILD_LDFLAGS += -EB $(call ld-option, -maarch64elfb, -maarch64linuxb)
++KBUILD_LDFLAGS += -EB $(call ld-option, -maarch64elfb, -maarch64linuxb -z norelro)
+ UTS_MACHINE := aarch64_be
+ else
+ KBUILD_CPPFLAGS += -mlittle-endian
+ CHECKFLAGS += -D__AARCH64EL__
+ # Same as above, prefer ELF but fall back to linux target if needed.
+-KBUILD_LDFLAGS += -EL $(call ld-option, -maarch64elf, -maarch64linux)
++KBUILD_LDFLAGS += -EL $(call ld-option, -maarch64elf, -maarch64linux -z norelro)
+ UTS_MACHINE := aarch64
+ endif
+
++ifeq ($(CONFIG_LD_IS_LLD), y)
++KBUILD_LDFLAGS += -z norelro
++endif
++
+ CHECKFLAGS += -D__aarch64__
+
+ ifeq ($(CONFIG_DYNAMIC_FTRACE_WITH_REGS),y)
--- /dev/null
+From 1dfc0686c29a9bbd3a446a29f9ccde3dec3bc75a Mon Sep 17 00:00:00 2001
+From: Coly Li <colyli@suse.de>
+Date: Mon, 4 Jan 2021 15:41:20 +0800
+Subject: bcache: check unsupported feature sets for bcache register
+
+From: Coly Li <colyli@suse.de>
+
+commit 1dfc0686c29a9bbd3a446a29f9ccde3dec3bc75a upstream.
+
+This patch adds the check for features which is incompatible for
+current supported feature sets.
+
+Now if the bcache device created by bcache-tools has features that
+current kernel doesn't support, read_super() will fail with error
+messoage. E.g. if an unsupported incompatible feature detected,
+bcache register will fail with dmesg "bcache: register_bcache() error :
+Unsupported incompatible feature found".
+
+Fixes: d721a43ff69c ("bcache: increase super block version for cache device and backing device")
+Fixes: ffa470327572 ("bcache: add bucket_size_hi into struct cache_sb_disk for large bucket")
+Signed-off-by: Coly Li <colyli@suse.de>
+Cc: stable@vger.kernel.org # 5.9+
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/bcache/features.h | 15 +++++++++++++++
+ drivers/md/bcache/super.c | 14 ++++++++++++++
+ 2 files changed, 29 insertions(+)
+
+--- a/drivers/md/bcache/features.h
++++ b/drivers/md/bcache/features.h
+@@ -79,6 +79,21 @@ static inline void bch_clear_feature_##n
+
+ BCH_FEATURE_INCOMPAT_FUNCS(large_bucket, LARGE_BUCKET);
+
++static inline bool bch_has_unknown_compat_features(struct cache_sb *sb)
++{
++ return ((sb->feature_compat & ~BCH_FEATURE_COMPAT_SUPP) != 0);
++}
++
++static inline bool bch_has_unknown_ro_compat_features(struct cache_sb *sb)
++{
++ return ((sb->feature_ro_compat & ~BCH_FEATURE_RO_COMPAT_SUPP) != 0);
++}
++
++static inline bool bch_has_unknown_incompat_features(struct cache_sb *sb)
++{
++ return ((sb->feature_incompat & ~BCH_FEATURE_INCOMPAT_SUPP) != 0);
++}
++
+ int bch_print_cache_set_feature_compat(struct cache_set *c, char *buf, int size);
+ int bch_print_cache_set_feature_ro_compat(struct cache_set *c, char *buf, int size);
+ int bch_print_cache_set_feature_incompat(struct cache_set *c, char *buf, int size);
+--- a/drivers/md/bcache/super.c
++++ b/drivers/md/bcache/super.c
+@@ -228,6 +228,20 @@ static const char *read_super(struct cac
+ sb->feature_compat = le64_to_cpu(s->feature_compat);
+ sb->feature_incompat = le64_to_cpu(s->feature_incompat);
+ sb->feature_ro_compat = le64_to_cpu(s->feature_ro_compat);
++
++ /* Check incompatible features */
++ err = "Unsupported compatible feature found";
++ if (bch_has_unknown_compat_features(sb))
++ goto err;
++
++ err = "Unsupported read-only compatible feature found";
++ if (bch_has_unknown_ro_compat_features(sb))
++ goto err;
++
++ err = "Unsupported incompatible feature found";
++ if (bch_has_unknown_incompat_features(sb))
++ goto err;
++
+ err = read_super_common(sb, bdev, s);
+ if (err)
+ goto err;
--- /dev/null
+From f7b4943dea48a572ad751ce1f18a245d43debe7e Mon Sep 17 00:00:00 2001
+From: Coly Li <colyli@suse.de>
+Date: Mon, 4 Jan 2021 15:41:19 +0800
+Subject: bcache: fix typo from SUUP to SUPP in features.h
+
+From: Coly Li <colyli@suse.de>
+
+commit f7b4943dea48a572ad751ce1f18a245d43debe7e upstream.
+
+This patch fixes the following typos,
+from BCH_FEATURE_COMPAT_SUUP to BCH_FEATURE_COMPAT_SUPP
+from BCH_FEATURE_INCOMPAT_SUUP to BCH_FEATURE_INCOMPAT_SUPP
+from BCH_FEATURE_INCOMPAT_SUUP to BCH_FEATURE_RO_COMPAT_SUPP
+
+Fixes: d721a43ff69c ("bcache: increase super block version for cache device and backing device")
+Fixes: ffa470327572 ("bcache: add bucket_size_hi into struct cache_sb_disk for large bucket")
+Signed-off-by: Coly Li <colyli@suse.de>
+Cc: stable@vger.kernel.org # 5.9+
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/bcache/features.h | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/md/bcache/features.h
++++ b/drivers/md/bcache/features.h
+@@ -15,9 +15,9 @@
+ /* Incompat feature set */
+ #define BCH_FEATURE_INCOMPAT_LARGE_BUCKET 0x0001 /* 32bit bucket size */
+
+-#define BCH_FEATURE_COMPAT_SUUP 0
+-#define BCH_FEATURE_RO_COMPAT_SUUP 0
+-#define BCH_FEATURE_INCOMPAT_SUUP BCH_FEATURE_INCOMPAT_LARGE_BUCKET
++#define BCH_FEATURE_COMPAT_SUPP 0
++#define BCH_FEATURE_RO_COMPAT_SUPP 0
++#define BCH_FEATURE_INCOMPAT_SUPP BCH_FEATURE_INCOMPAT_LARGE_BUCKET
+
+ #define BCH_HAS_COMPAT_FEATURE(sb, mask) \
+ ((sb)->feature_compat & (mask))
--- /dev/null
+From b16671e8f493e3df40b1fb0dff4078f391c5099a Mon Sep 17 00:00:00 2001
+From: Coly Li <colyli@suse.de>
+Date: Mon, 4 Jan 2021 15:41:21 +0800
+Subject: bcache: introduce BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE for large bucket
+
+From: Coly Li <colyli@suse.de>
+
+commit b16671e8f493e3df40b1fb0dff4078f391c5099a upstream.
+
+When large bucket feature was added, BCH_FEATURE_INCOMPAT_LARGE_BUCKET
+was introduced into the incompat feature set. It used bucket_size_hi
+(which was added at the tail of struct cache_sb_disk) to extend current
+16bit bucket size to 32bit with existing bucket_size in struct
+cache_sb_disk.
+
+This is not a good idea, there are two obvious problems,
+- Bucket size is always value power of 2, if store log2(bucket size) in
+ existing bucket_size of struct cache_sb_disk, it is unnecessary to add
+ bucket_size_hi.
+- Macro csum_set() assumes d[SB_JOURNAL_BUCKETS] is the last member in
+ struct cache_sb_disk, bucket_size_hi was added after d[] which makes
+ csum_set calculate an unexpected super block checksum.
+
+To fix the above problems, this patch introduces a new incompat feature
+bit BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE, when this bit is set, it
+means bucket_size in struct cache_sb_disk stores the order of power-of-2
+bucket size value. When user specifies a bucket size larger than 32768
+sectors, BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE will be set to
+incompat feature set, and bucket_size stores log2(bucket size) more
+than store the real bucket size value.
+
+The obsoleted BCH_FEATURE_INCOMPAT_LARGE_BUCKET won't be used anymore,
+it is renamed to BCH_FEATURE_INCOMPAT_OBSO_LARGE_BUCKET and still only
+recognized by kernel driver for legacy compatible purpose. The previous
+bucket_size_hi is renmaed to obso_bucket_size_hi in struct cache_sb_disk
+and not used in bcache-tools anymore.
+
+For cache device created with BCH_FEATURE_INCOMPAT_LARGE_BUCKET feature,
+bcache-tools and kernel driver still recognize the feature string and
+display it as "obso_large_bucket".
+
+With this change, the unnecessary extra space extend of bcache on-disk
+super block can be avoided, and csum_set() may generate expected check
+sum as well.
+
+Fixes: ffa470327572 ("bcache: add bucket_size_hi into struct cache_sb_disk for large bucket")
+Signed-off-by: Coly Li <colyli@suse.de>
+Cc: stable@vger.kernel.org # 5.9+
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/bcache/features.c | 2 +-
+ drivers/md/bcache/features.h | 11 ++++++++---
+ drivers/md/bcache/super.c | 22 +++++++++++++++++++---
+ include/uapi/linux/bcache.h | 2 +-
+ 4 files changed, 29 insertions(+), 8 deletions(-)
+
+--- a/drivers/md/bcache/features.c
++++ b/drivers/md/bcache/features.c
+@@ -17,7 +17,7 @@ struct feature {
+ };
+
+ static struct feature feature_list[] = {
+- {BCH_FEATURE_INCOMPAT, BCH_FEATURE_INCOMPAT_LARGE_BUCKET,
++ {BCH_FEATURE_INCOMPAT, BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE,
+ "large_bucket"},
+ {0, 0, 0 },
+ };
+--- a/drivers/md/bcache/features.h
++++ b/drivers/md/bcache/features.h
+@@ -13,11 +13,15 @@
+
+ /* Feature set definition */
+ /* Incompat feature set */
+-#define BCH_FEATURE_INCOMPAT_LARGE_BUCKET 0x0001 /* 32bit bucket size */
++/* 32bit bucket size, obsoleted */
++#define BCH_FEATURE_INCOMPAT_OBSO_LARGE_BUCKET 0x0001
++/* real bucket size is (1 << bucket_size) */
++#define BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE 0x0002
+
+ #define BCH_FEATURE_COMPAT_SUPP 0
+ #define BCH_FEATURE_RO_COMPAT_SUPP 0
+-#define BCH_FEATURE_INCOMPAT_SUPP BCH_FEATURE_INCOMPAT_LARGE_BUCKET
++#define BCH_FEATURE_INCOMPAT_SUPP (BCH_FEATURE_INCOMPAT_OBSO_LARGE_BUCKET| \
++ BCH_FEATURE_INCOMPAT_LOG_LARGE_BUCKET_SIZE)
+
+ #define BCH_HAS_COMPAT_FEATURE(sb, mask) \
+ ((sb)->feature_compat & (mask))
+@@ -77,7 +81,8 @@ static inline void bch_clear_feature_##n
+ ~BCH##_FEATURE_INCOMPAT_##flagname; \
+ }
+
+-BCH_FEATURE_INCOMPAT_FUNCS(large_bucket, LARGE_BUCKET);
++BCH_FEATURE_INCOMPAT_FUNCS(obso_large_bucket, OBSO_LARGE_BUCKET);
++BCH_FEATURE_INCOMPAT_FUNCS(large_bucket, LOG_LARGE_BUCKET_SIZE);
+
+ static inline bool bch_has_unknown_compat_features(struct cache_sb *sb)
+ {
+--- a/drivers/md/bcache/super.c
++++ b/drivers/md/bcache/super.c
+@@ -64,9 +64,25 @@ static unsigned int get_bucket_size(stru
+ {
+ unsigned int bucket_size = le16_to_cpu(s->bucket_size);
+
+- if (sb->version >= BCACHE_SB_VERSION_CDEV_WITH_FEATURES &&
+- bch_has_feature_large_bucket(sb))
+- bucket_size |= le16_to_cpu(s->bucket_size_hi) << 16;
++ if (sb->version >= BCACHE_SB_VERSION_CDEV_WITH_FEATURES) {
++ if (bch_has_feature_large_bucket(sb)) {
++ unsigned int max, order;
++
++ max = sizeof(unsigned int) * BITS_PER_BYTE - 1;
++ order = le16_to_cpu(s->bucket_size);
++ /*
++ * bcache tool will make sure the overflow won't
++ * happen, an error message here is enough.
++ */
++ if (order > max)
++ pr_err("Bucket size (1 << %u) overflows\n",
++ order);
++ bucket_size = 1 << order;
++ } else if (bch_has_feature_obso_large_bucket(sb)) {
++ bucket_size +=
++ le16_to_cpu(s->obso_bucket_size_hi) << 16;
++ }
++ }
+
+ return bucket_size;
+ }
+--- a/include/uapi/linux/bcache.h
++++ b/include/uapi/linux/bcache.h
+@@ -213,7 +213,7 @@ struct cache_sb_disk {
+ __le16 keys;
+ };
+ __le64 d[SB_JOURNAL_BUCKETS]; /* journal buckets */
+- __le16 bucket_size_hi;
++ __le16 obso_bucket_size_hi; /* obsoleted */
+ };
+
+ /*
--- /dev/null
+From d16baa3f1453c14d680c5fee01cd122a22d0e0ce Mon Sep 17 00:00:00 2001
+From: Tejun Heo <tj@kernel.org>
+Date: Tue, 5 Jan 2021 12:37:23 -0500
+Subject: blk-iocost: fix NULL iocg deref from racing against initialization
+
+From: Tejun Heo <tj@kernel.org>
+
+commit d16baa3f1453c14d680c5fee01cd122a22d0e0ce upstream.
+
+When initializing iocost for a queue, its rqos should be registered before
+the blkcg policy is activated to allow policy data initiailization to lookup
+the associated ioc. This unfortunately means that the rqos methods can be
+called on bios before iocgs are attached to all existing blkgs.
+
+While the race is theoretically possible on ioc_rqos_throttle(), it mostly
+happened in ioc_rqos_merge() due to the difference in how they lookup ioc.
+The former determines it from the passed in @rqos and then bails before
+dereferencing iocg if the looked up ioc is disabled, which most likely is
+the case if initialization is still in progress. The latter looked up ioc by
+dereferencing the possibly NULL iocg making it a lot more prone to actually
+triggering the bug.
+
+* Make ioc_rqos_merge() use the same method as ioc_rqos_throttle() to look
+ up ioc for consistency.
+
+* Make ioc_rqos_throttle() and ioc_rqos_merge() test for NULL iocg before
+ dereferencing it.
+
+* Explain the danger of NULL iocgs in blk_iocost_init().
+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reported-by: Jonathan Lemon <bsd@fb.com>
+Cc: stable@vger.kernel.org # v5.4+
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ block/blk-iocost.c | 16 +++++++++++-----
+ 1 file changed, 11 insertions(+), 5 deletions(-)
+
+--- a/block/blk-iocost.c
++++ b/block/blk-iocost.c
+@@ -2525,8 +2525,8 @@ static void ioc_rqos_throttle(struct rq_
+ bool use_debt, ioc_locked;
+ unsigned long flags;
+
+- /* bypass IOs if disabled or for root cgroup */
+- if (!ioc->enabled || !iocg->level)
++ /* bypass IOs if disabled, still initializing, or for root cgroup */
++ if (!ioc->enabled || !iocg || !iocg->level)
+ return;
+
+ /* calculate the absolute vtime cost */
+@@ -2653,14 +2653,14 @@ static void ioc_rqos_merge(struct rq_qos
+ struct bio *bio)
+ {
+ struct ioc_gq *iocg = blkg_to_iocg(bio->bi_blkg);
+- struct ioc *ioc = iocg->ioc;
++ struct ioc *ioc = rqos_to_ioc(rqos);
+ sector_t bio_end = bio_end_sector(bio);
+ struct ioc_now now;
+ u64 vtime, abs_cost, cost;
+ unsigned long flags;
+
+- /* bypass if disabled or for root cgroup */
+- if (!ioc->enabled || !iocg->level)
++ /* bypass if disabled, still initializing, or for root cgroup */
++ if (!ioc->enabled || !iocg || !iocg->level)
+ return;
+
+ abs_cost = calc_vtime_cost(bio, iocg, true);
+@@ -2837,6 +2837,12 @@ static int blk_iocost_init(struct reques
+ ioc_refresh_params(ioc, true);
+ spin_unlock_irq(&ioc->lock);
+
++ /*
++ * rqos must be added before activation to allow iocg_pd_init() to
++ * lookup the ioc from q. This means that the rqos methods may get
++ * called before policy activation completion, can't assume that the
++ * target bio has an iocg associated and need to test for NULL iocg.
++ */
+ rq_qos_add(q, rqos);
+ ret = blkcg_activate_policy(q, &blkcg_policy_iocost);
+ if (ret) {
--- /dev/null
+From ae5e070eaca9dbebde3459dd8f4c2756f8c097d0 Mon Sep 17 00:00:00 2001
+From: Qu Wenruo <wqu@suse.com>
+Date: Fri, 4 Dec 2020 09:24:47 +0800
+Subject: btrfs: qgroup: don't try to wait flushing if we're already holding a transaction
+
+From: Qu Wenruo <wqu@suse.com>
+
+commit ae5e070eaca9dbebde3459dd8f4c2756f8c097d0 upstream.
+
+There is a chance of racing for qgroup flushing which may lead to
+deadlock:
+
+ Thread A | Thread B
+ (not holding trans handle) | (holding a trans handle)
+--------------------------------+--------------------------------
+__btrfs_qgroup_reserve_meta() | __btrfs_qgroup_reserve_meta()
+|- try_flush_qgroup() | |- try_flush_qgroup()
+ |- QGROUP_FLUSHING bit set | |
+ | | |- test_and_set_bit()
+ | | |- wait_event()
+ |- btrfs_join_transaction() |
+ |- btrfs_commit_transaction()|
+
+ !!! DEAD LOCK !!!
+
+Since thread A wants to commit transaction, but thread B is holding a
+transaction handle, blocking the commit.
+At the same time, thread B is waiting for thread A to finish its commit.
+
+This is just a hot fix, and would lead to more EDQUOT when we're near
+the qgroup limit.
+
+The proper fix would be to make all metadata/data reservations happen
+without holding a transaction handle.
+
+CC: stable@vger.kernel.org # 5.9+
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/qgroup.c | 30 ++++++++++++++++++++----------
+ 1 file changed, 20 insertions(+), 10 deletions(-)
+
+--- a/fs/btrfs/qgroup.c
++++ b/fs/btrfs/qgroup.c
+@@ -3565,16 +3565,6 @@ static int try_flush_qgroup(struct btrfs
+ bool can_commit = true;
+
+ /*
+- * We don't want to run flush again and again, so if there is a running
+- * one, we won't try to start a new flush, but exit directly.
+- */
+- if (test_and_set_bit(BTRFS_ROOT_QGROUP_FLUSHING, &root->state)) {
+- wait_event(root->qgroup_flush_wait,
+- !test_bit(BTRFS_ROOT_QGROUP_FLUSHING, &root->state));
+- return 0;
+- }
+-
+- /*
+ * If current process holds a transaction, we shouldn't flush, as we
+ * assume all space reservation happens before a transaction handle is
+ * held.
+@@ -3588,6 +3578,26 @@ static int try_flush_qgroup(struct btrfs
+ current->journal_info != BTRFS_SEND_TRANS_STUB)
+ can_commit = false;
+
++ /*
++ * We don't want to run flush again and again, so if there is a running
++ * one, we won't try to start a new flush, but exit directly.
++ */
++ if (test_and_set_bit(BTRFS_ROOT_QGROUP_FLUSHING, &root->state)) {
++ /*
++ * We are already holding a transaction, thus we can block other
++ * threads from flushing. So exit right now. This increases
++ * the chance of EDQUOT for heavy load and near limit cases.
++ * But we can argue that if we're already near limit, EDQUOT is
++ * unavoidable anyway.
++ */
++ if (!can_commit)
++ return 0;
++
++ wait_event(root->qgroup_flush_wait,
++ !test_bit(BTRFS_ROOT_QGROUP_FLUSHING, &root->state));
++ return 0;
++ }
++
+ ret = btrfs_start_delalloc_snapshot(root);
+ if (ret < 0)
+ goto out;
--- /dev/null
+From 0b3f407e6728d990ae1630a02c7b952c21c288d3 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Thu, 10 Dec 2020 12:09:02 +0000
+Subject: btrfs: send: fix wrong file path when there is an inode with a pending rmdir
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 0b3f407e6728d990ae1630a02c7b952c21c288d3 upstream.
+
+When doing an incremental send, if we have a new inode that happens to
+have the same number that an old directory inode had in the base snapshot
+and that old directory has a pending rmdir operation, we end up computing
+a wrong path for the new inode, causing the receiver to fail.
+
+Example reproducer:
+
+ $ cat test-send-rmdir.sh
+ #!/bin/bash
+
+ DEV=/dev/sdi
+ MNT=/mnt/sdi
+
+ mkfs.btrfs -f $DEV >/dev/null
+ mount $DEV $MNT
+
+ mkdir $MNT/dir
+ touch $MNT/dir/file1
+ touch $MNT/dir/file2
+ touch $MNT/dir/file3
+
+ # Filesystem looks like:
+ #
+ # . (ino 256)
+ # |----- dir/ (ino 257)
+ # |----- file1 (ino 258)
+ # |----- file2 (ino 259)
+ # |----- file3 (ino 260)
+ #
+
+ btrfs subvolume snapshot -r $MNT $MNT/snap1
+ btrfs send -f /tmp/snap1.send $MNT/snap1
+
+ # Now remove our directory and all its files.
+ rm -fr $MNT/dir
+
+ # Unmount the filesystem and mount it again. This is to ensure that
+ # the next inode that is created ends up with the same inode number
+ # that our directory "dir" had, 257, which is the first free "objectid"
+ # available after mounting again the filesystem.
+ umount $MNT
+ mount $DEV $MNT
+
+ # Now create a new file (it could be a directory as well).
+ touch $MNT/newfile
+
+ # Filesystem now looks like:
+ #
+ # . (ino 256)
+ # |----- newfile (ino 257)
+ #
+
+ btrfs subvolume snapshot -r $MNT $MNT/snap2
+ btrfs send -f /tmp/snap2.send -p $MNT/snap1 $MNT/snap2
+
+ # Now unmount the filesystem, create a new one, mount it and try to apply
+ # both send streams to recreate both snapshots.
+ umount $DEV
+
+ mkfs.btrfs -f $DEV >/dev/null
+
+ mount $DEV $MNT
+
+ btrfs receive -f /tmp/snap1.send $MNT
+ btrfs receive -f /tmp/snap2.send $MNT
+
+ umount $MNT
+
+When running the test, the receive operation for the incremental stream
+fails:
+
+ $ ./test-send-rmdir.sh
+ Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap1'
+ At subvol /mnt/sdi/snap1
+ Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap2'
+ At subvol /mnt/sdi/snap2
+ At subvol snap1
+ At snapshot snap2
+ ERROR: chown o257-9-0 failed: No such file or directory
+
+So fix this by tracking directories that have a pending rmdir by inode
+number and generation number, instead of only inode number.
+
+A test case for fstests follows soon.
+
+Reported-by: Massimo B. <massimo.b@gmx.net>
+Tested-by: Massimo B. <massimo.b@gmx.net>
+Link: https://lore.kernel.org/linux-btrfs/6ae34776e85912960a253a8327068a892998e685.camel@gmx.net/
+CC: stable@vger.kernel.org # 4.19+
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/send.c | 49 +++++++++++++++++++++++++++++++------------------
+ 1 file changed, 31 insertions(+), 18 deletions(-)
+
+--- a/fs/btrfs/send.c
++++ b/fs/btrfs/send.c
+@@ -236,6 +236,7 @@ struct waiting_dir_move {
+ * after this directory is moved, we can try to rmdir the ino rmdir_ino.
+ */
+ u64 rmdir_ino;
++ u64 rmdir_gen;
+ bool orphanized;
+ };
+
+@@ -316,7 +317,7 @@ static int is_waiting_for_move(struct se
+ static struct waiting_dir_move *
+ get_waiting_dir_move(struct send_ctx *sctx, u64 ino);
+
+-static int is_waiting_for_rm(struct send_ctx *sctx, u64 dir_ino);
++static int is_waiting_for_rm(struct send_ctx *sctx, u64 dir_ino, u64 gen);
+
+ static int need_send_hole(struct send_ctx *sctx)
+ {
+@@ -2299,7 +2300,7 @@ static int get_cur_path(struct send_ctx
+
+ fs_path_reset(name);
+
+- if (is_waiting_for_rm(sctx, ino)) {
++ if (is_waiting_for_rm(sctx, ino, gen)) {
+ ret = gen_unique_name(sctx, ino, gen, name);
+ if (ret < 0)
+ goto out;
+@@ -2858,8 +2859,8 @@ out:
+ return ret;
+ }
+
+-static struct orphan_dir_info *
+-add_orphan_dir_info(struct send_ctx *sctx, u64 dir_ino)
++static struct orphan_dir_info *add_orphan_dir_info(struct send_ctx *sctx,
++ u64 dir_ino, u64 dir_gen)
+ {
+ struct rb_node **p = &sctx->orphan_dirs.rb_node;
+ struct rb_node *parent = NULL;
+@@ -2868,20 +2869,23 @@ add_orphan_dir_info(struct send_ctx *sct
+ while (*p) {
+ parent = *p;
+ entry = rb_entry(parent, struct orphan_dir_info, node);
+- if (dir_ino < entry->ino) {
++ if (dir_ino < entry->ino)
+ p = &(*p)->rb_left;
+- } else if (dir_ino > entry->ino) {
++ else if (dir_ino > entry->ino)
+ p = &(*p)->rb_right;
+- } else {
++ else if (dir_gen < entry->gen)
++ p = &(*p)->rb_left;
++ else if (dir_gen > entry->gen)
++ p = &(*p)->rb_right;
++ else
+ return entry;
+- }
+ }
+
+ odi = kmalloc(sizeof(*odi), GFP_KERNEL);
+ if (!odi)
+ return ERR_PTR(-ENOMEM);
+ odi->ino = dir_ino;
+- odi->gen = 0;
++ odi->gen = dir_gen;
+ odi->last_dir_index_offset = 0;
+
+ rb_link_node(&odi->node, parent, p);
+@@ -2889,8 +2893,8 @@ add_orphan_dir_info(struct send_ctx *sct
+ return odi;
+ }
+
+-static struct orphan_dir_info *
+-get_orphan_dir_info(struct send_ctx *sctx, u64 dir_ino)
++static struct orphan_dir_info *get_orphan_dir_info(struct send_ctx *sctx,
++ u64 dir_ino, u64 gen)
+ {
+ struct rb_node *n = sctx->orphan_dirs.rb_node;
+ struct orphan_dir_info *entry;
+@@ -2901,15 +2905,19 @@ get_orphan_dir_info(struct send_ctx *sct
+ n = n->rb_left;
+ else if (dir_ino > entry->ino)
+ n = n->rb_right;
++ else if (gen < entry->gen)
++ n = n->rb_left;
++ else if (gen > entry->gen)
++ n = n->rb_right;
+ else
+ return entry;
+ }
+ return NULL;
+ }
+
+-static int is_waiting_for_rm(struct send_ctx *sctx, u64 dir_ino)
++static int is_waiting_for_rm(struct send_ctx *sctx, u64 dir_ino, u64 gen)
+ {
+- struct orphan_dir_info *odi = get_orphan_dir_info(sctx, dir_ino);
++ struct orphan_dir_info *odi = get_orphan_dir_info(sctx, dir_ino, gen);
+
+ return odi != NULL;
+ }
+@@ -2954,7 +2962,7 @@ static int can_rmdir(struct send_ctx *sc
+ key.type = BTRFS_DIR_INDEX_KEY;
+ key.offset = 0;
+
+- odi = get_orphan_dir_info(sctx, dir);
++ odi = get_orphan_dir_info(sctx, dir, dir_gen);
+ if (odi)
+ key.offset = odi->last_dir_index_offset;
+
+@@ -2985,7 +2993,7 @@ static int can_rmdir(struct send_ctx *sc
+
+ dm = get_waiting_dir_move(sctx, loc.objectid);
+ if (dm) {
+- odi = add_orphan_dir_info(sctx, dir);
++ odi = add_orphan_dir_info(sctx, dir, dir_gen);
+ if (IS_ERR(odi)) {
+ ret = PTR_ERR(odi);
+ goto out;
+@@ -2993,12 +3001,13 @@ static int can_rmdir(struct send_ctx *sc
+ odi->gen = dir_gen;
+ odi->last_dir_index_offset = found_key.offset;
+ dm->rmdir_ino = dir;
++ dm->rmdir_gen = dir_gen;
+ ret = 0;
+ goto out;
+ }
+
+ if (loc.objectid > send_progress) {
+- odi = add_orphan_dir_info(sctx, dir);
++ odi = add_orphan_dir_info(sctx, dir, dir_gen);
+ if (IS_ERR(odi)) {
+ ret = PTR_ERR(odi);
+ goto out;
+@@ -3038,6 +3047,7 @@ static int add_waiting_dir_move(struct s
+ return -ENOMEM;
+ dm->ino = ino;
+ dm->rmdir_ino = 0;
++ dm->rmdir_gen = 0;
+ dm->orphanized = orphanized;
+
+ while (*p) {
+@@ -3183,7 +3193,7 @@ static int path_loop(struct send_ctx *sc
+ while (ino != BTRFS_FIRST_FREE_OBJECTID) {
+ fs_path_reset(name);
+
+- if (is_waiting_for_rm(sctx, ino))
++ if (is_waiting_for_rm(sctx, ino, gen))
+ break;
+ if (is_waiting_for_move(sctx, ino)) {
+ if (*ancestor_ino == 0)
+@@ -3223,6 +3233,7 @@ static int apply_dir_move(struct send_ct
+ u64 parent_ino, parent_gen;
+ struct waiting_dir_move *dm = NULL;
+ u64 rmdir_ino = 0;
++ u64 rmdir_gen;
+ u64 ancestor;
+ bool is_orphan;
+ int ret;
+@@ -3237,6 +3248,7 @@ static int apply_dir_move(struct send_ct
+ dm = get_waiting_dir_move(sctx, pm->ino);
+ ASSERT(dm);
+ rmdir_ino = dm->rmdir_ino;
++ rmdir_gen = dm->rmdir_gen;
+ is_orphan = dm->orphanized;
+ free_waiting_dir_move(sctx, dm);
+
+@@ -3273,6 +3285,7 @@ static int apply_dir_move(struct send_ct
+ dm = get_waiting_dir_move(sctx, pm->ino);
+ ASSERT(dm);
+ dm->rmdir_ino = rmdir_ino;
++ dm->rmdir_gen = rmdir_gen;
+ }
+ goto out;
+ }
+@@ -3291,7 +3304,7 @@ static int apply_dir_move(struct send_ct
+ struct orphan_dir_info *odi;
+ u64 gen;
+
+- odi = get_orphan_dir_info(sctx, rmdir_ino);
++ odi = get_orphan_dir_info(sctx, rmdir_ino, rmdir_gen);
+ if (!odi) {
+ /* already deleted */
+ goto finish;
--- /dev/null
+From 05cd84691eafcd7959a1e120d5e72c0dd98c5d91 Mon Sep 17 00:00:00 2001
+From: Charan Teja Reddy <charante@codeaurora.org>
+Date: Tue, 5 Jan 2021 20:06:39 +0530
+Subject: dmabuf: fix use-after-free of dmabuf's file->f_inode
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Charan Teja Reddy <charante@codeaurora.org>
+
+commit 05cd84691eafcd7959a1e120d5e72c0dd98c5d91 upstream.
+
+It is observed 'use-after-free' on the dmabuf's file->f_inode with the
+race between closing the dmabuf file and reading the dmabuf's debug
+info.
+
+Consider the below scenario where P1 is closing the dma_buf file
+and P2 is reading the dma_buf's debug info in the system:
+
+P1 P2
+ dma_buf_debug_show()
+dma_buf_put()
+ __fput()
+ file->f_op->release()
+ dput()
+ ....
+ dentry_unlink_inode()
+ iput(dentry->d_inode)
+ (where the inode is freed)
+ mutex_lock(&db_list.lock)
+ read 'dma_buf->file->f_inode'
+ (the same inode is freed by P1)
+ mutex_unlock(&db_list.lock)
+ dentry->d_op->d_release()-->
+ dma_buf_release()
+ .....
+ mutex_lock(&db_list.lock)
+ removes the dmabuf from the list
+ mutex_unlock(&db_list.lock)
+
+In the above scenario, when dma_buf_put() is called on a dma_buf, it
+first frees the dma_buf's file->f_inode(=dentry->d_inode) and then
+removes this dma_buf from the system db_list. In between P2 traversing
+the db_list tries to access this dma_buf's file->f_inode that was freed
+by P1 which is a use-after-free case.
+
+Since, __fput() calls f_op->release first and then later calls the
+d_op->d_release, move the dma_buf's db_list removal from d_release() to
+f_op->release(). This ensures that dma_buf's file->f_inode is not
+accessed after it is released.
+
+Cc: <stable@vger.kernel.org> # 5.4.x-
+Fixes: 4ab59c3c638c ("dma-buf: Move dma_buf_release() from fops to dentry_ops")
+Acked-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Charan Teja Reddy <charante@codeaurora.org>
+Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/1609857399-31549-1-git-send-email-charante@codeaurora.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/dma-buf/dma-buf.c | 21 +++++++++++++++++----
+ 1 file changed, 17 insertions(+), 4 deletions(-)
+
+--- a/drivers/dma-buf/dma-buf.c
++++ b/drivers/dma-buf/dma-buf.c
+@@ -76,10 +76,6 @@ static void dma_buf_release(struct dentr
+
+ dmabuf->ops->release(dmabuf);
+
+- mutex_lock(&db_list.lock);
+- list_del(&dmabuf->list_node);
+- mutex_unlock(&db_list.lock);
+-
+ if (dmabuf->resv == (struct dma_resv *)&dmabuf[1])
+ dma_resv_fini(dmabuf->resv);
+
+@@ -88,6 +84,22 @@ static void dma_buf_release(struct dentr
+ kfree(dmabuf);
+ }
+
++static int dma_buf_file_release(struct inode *inode, struct file *file)
++{
++ struct dma_buf *dmabuf;
++
++ if (!is_dma_buf_file(file))
++ return -EINVAL;
++
++ dmabuf = file->private_data;
++
++ mutex_lock(&db_list.lock);
++ list_del(&dmabuf->list_node);
++ mutex_unlock(&db_list.lock);
++
++ return 0;
++}
++
+ static const struct dentry_operations dma_buf_dentry_ops = {
+ .d_dname = dmabuffs_dname,
+ .d_release = dma_buf_release,
+@@ -413,6 +425,7 @@ static void dma_buf_show_fdinfo(struct s
+ }
+
+ static const struct file_operations dma_buf_fops = {
++ .release = dma_buf_file_release,
+ .mmap = dma_buf_mmap_internal,
+ .llseek = dma_buf_llseek,
+ .poll = dma_buf_poll,
--- /dev/null
+From 641382e9b44fba81a0778e1914ee35b8471121f9 Mon Sep 17 00:00:00 2001
+From: Matthew Auld <matthew.auld@intel.com>
+Date: Thu, 24 Dec 2020 15:13:58 +0000
+Subject: drm/i915: clear the gpu reloc batch
+
+From: Matthew Auld <matthew.auld@intel.com>
+
+commit 641382e9b44fba81a0778e1914ee35b8471121f9 upstream.
+
+The reloc batch is short lived but can exist in the user visible ppGTT,
+and since it's backed by an internal object, which lacks page clearing,
+we should take care to clear it upfront.
+
+Signed-off-by: Matthew Auld <matthew.auld@intel.com>
+Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Link: https://patchwork.freedesktop.org/patch/msgid/20201224151358.401345-2-matthew.auld@intel.com
+Cc: stable@vger.kernel.org
+(cherry picked from commit 26ebc511e799f621357982ccc37a7987a56a00f4)
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
++++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+@@ -1046,7 +1046,7 @@ static void reloc_gpu_flush(struct i915_
+ GEM_BUG_ON(cache->rq_size >= obj->base.size / sizeof(u32));
+ cache->rq_cmd[cache->rq_size] = MI_BATCH_BUFFER_END;
+
+- __i915_gem_object_flush_map(obj, 0, sizeof(u32) * (cache->rq_size + 1));
++ i915_gem_object_flush_map(obj);
+ i915_gem_object_unpin_map(obj);
+
+ intel_gt_chipset_flush(cache->rq->engine->gt);
+@@ -1296,6 +1296,8 @@ static int __reloc_gpu_alloc(struct i915
+ goto err_pool;
+ }
+
++ memset32(cmd, 0, pool->obj->base.size / sizeof(u32));
++
+ batch = i915_vma_instance(pool->obj, vma->vm, NULL);
+ if (IS_ERR(batch)) {
+ err = PTR_ERR(batch);
--- /dev/null
+From 75353bcd2184010f08a3ed2f0da019bd9d604e1e Mon Sep 17 00:00:00 2001
+From: Matthew Auld <matthew.auld@intel.com>
+Date: Thu, 24 Dec 2020 15:13:57 +0000
+Subject: drm/i915: clear the shadow batch
+
+From: Matthew Auld <matthew.auld@intel.com>
+
+commit 75353bcd2184010f08a3ed2f0da019bd9d604e1e upstream.
+
+The shadow batch is an internal object, which doesn't have any page
+clearing, and since the batch_len can be smaller than the object, we
+should take care to clear it.
+
+Testcase: igt/gen9_exec_parse/shadow-peek
+Fixes: 4f7af1948abc ("drm/i915: Support ro ppgtt mapped cmdparser shadow buffers")
+Signed-off-by: Matthew Auld <matthew.auld@intel.com>
+Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Link: https://patchwork.freedesktop.org/patch/msgid/20201224151358.401345-1-matthew.auld@intel.com
+Cc: stable@vger.kernel.org
+(cherry picked from commit eeb52ee6c4a429ec301faf1dc48988744960786e)
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/i915_cmd_parser.c | 27 +++++++++------------------
+ 1 file changed, 9 insertions(+), 18 deletions(-)
+
+--- a/drivers/gpu/drm/i915/i915_cmd_parser.c
++++ b/drivers/gpu/drm/i915/i915_cmd_parser.c
+@@ -1166,7 +1166,7 @@ static u32 *copy_batch(struct drm_i915_g
+ }
+ }
+ if (IS_ERR(src)) {
+- unsigned long x, n;
++ unsigned long x, n, remain;
+ void *ptr;
+
+ /*
+@@ -1177,14 +1177,15 @@ static u32 *copy_batch(struct drm_i915_g
+ * We don't care about copying too much here as we only
+ * validate up to the end of the batch.
+ */
++ remain = length;
+ if (!(dst_obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ))
+- length = round_up(length,
++ remain = round_up(remain,
+ boot_cpu_data.x86_clflush_size);
+
+ ptr = dst;
+ x = offset_in_page(offset);
+- for (n = offset >> PAGE_SHIFT; length; n++) {
+- int len = min(length, PAGE_SIZE - x);
++ for (n = offset >> PAGE_SHIFT; remain; n++) {
++ int len = min(remain, PAGE_SIZE - x);
+
+ src = kmap_atomic(i915_gem_object_get_page(src_obj, n));
+ if (needs_clflush)
+@@ -1193,13 +1194,15 @@ static u32 *copy_batch(struct drm_i915_g
+ kunmap_atomic(src);
+
+ ptr += len;
+- length -= len;
++ remain -= len;
+ x = 0;
+ }
+ }
+
+ i915_gem_object_unpin_pages(src_obj);
+
++ memset32(dst + length, 0, (dst_obj->base.size - length) / sizeof(u32));
++
+ /* dst_obj is returned with vmap pinned */
+ return dst;
+ }
+@@ -1392,11 +1395,6 @@ static unsigned long *alloc_whitelist(u3
+
+ #define LENGTH_BIAS 2
+
+-static bool shadow_needs_clflush(struct drm_i915_gem_object *obj)
+-{
+- return !(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE);
+-}
+-
+ /**
+ * intel_engine_cmd_parser() - parse a batch buffer for privilege violations
+ * @engine: the engine on which the batch is to execute
+@@ -1539,16 +1537,9 @@ int intel_engine_cmd_parser(struct intel
+ ret = 0; /* allow execution */
+ }
+ }
+-
+- if (shadow_needs_clflush(shadow->obj))
+- drm_clflush_virt_range(batch_end, 8);
+ }
+
+- if (shadow_needs_clflush(shadow->obj)) {
+- void *ptr = page_mask_bits(shadow->obj->mm.mapping);
+-
+- drm_clflush_virt_range(ptr, (void *)(cmd + 1) - ptr);
+- }
++ i915_gem_object_flush_map(shadow->obj);
+
+ if (!IS_ERR_OR_NULL(jump_whitelist))
+ kfree(jump_whitelist);
--- /dev/null
+From 84e261553e6f919bf0b4d65244599ab2b41f1da5 Mon Sep 17 00:00:00 2001
+From: David Arcari <darcari@redhat.com>
+Date: Thu, 7 Jan 2021 09:47:07 -0500
+Subject: hwmon: (amd_energy) fix allocation of hwmon_channel_info config
+
+From: David Arcari <darcari@redhat.com>
+
+commit 84e261553e6f919bf0b4d65244599ab2b41f1da5 upstream.
+
+hwmon, specifically hwmon_num_channel_attrs, expects the config
+array in the hwmon_channel_info structure to be terminated by
+a zero entry. amd_energy does not honor this convention. As
+result, a KASAN warning is possible. Fix this by adding an
+additional entry and setting it to zero.
+
+Fixes: 8abee9566b7e ("hwmon: Add amd_energy driver to report energy counters")
+
+Signed-off-by: David Arcari <darcari@redhat.com>
+Cc: Naveen Krishna Chatradhi <nchatrad@amd.com>
+Cc: Jean Delvare <jdelvare@suse.com>
+Cc: Guenter Roeck <linux@roeck-us.net>
+Cc: linux-kernel@vger.kernel.org
+Cc: stable@vger.kernel.org
+Signed-off-by: David Arcari <darcari@redhat.com>
+Acked-by: Naveen Krishna Chatradhi <nchatrad@amd.com>
+Link: https://lore.kernel.org/r/20210107144707.6927-1-darcari@redhat.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hwmon/amd_energy.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/hwmon/amd_energy.c
++++ b/drivers/hwmon/amd_energy.c
+@@ -222,7 +222,7 @@ static int amd_create_sensor(struct devi
+ */
+ cpus = num_present_cpus() / num_siblings;
+
+- s_config = devm_kcalloc(dev, cpus + sockets,
++ s_config = devm_kcalloc(dev, cpus + sockets + 1,
+ sizeof(u32), GFP_KERNEL);
+ if (!s_config)
+ return -ENOMEM;
+@@ -254,6 +254,7 @@ static int amd_create_sensor(struct devi
+ scnprintf(label_l[i], 10, "Esocket%u", (i - cpus));
+ }
+
++ s_config[i] = 0;
+ return 0;
+ }
+
--- /dev/null
+From 9ad9f45b3b91162b33abfe175ae75ab65718dbf5 Mon Sep 17 00:00:00 2001
+From: Liu Yi L <yi.l.liu@intel.com>
+Date: Thu, 7 Jan 2021 00:03:55 +0800
+Subject: iommu/vt-d: Move intel_iommu info from struct intel_svm to struct intel_svm_dev
+
+From: Liu Yi L <yi.l.liu@intel.com>
+
+commit 9ad9f45b3b91162b33abfe175ae75ab65718dbf5 upstream.
+
+'struct intel_svm' is shared by all devices bound to a give process,
+but records only a single pointer to a 'struct intel_iommu'. Consequently,
+cache invalidations may only be applied to a single DMAR unit, and are
+erroneously skipped for the other devices.
+
+In preparation for fixing this, rework the structures so that the iommu
+pointer resides in 'struct intel_svm_dev', allowing 'struct intel_svm'
+to track them in its device list.
+
+Fixes: 1c4f88b7f1f9 ("iommu/vt-d: Shared virtual address in scalable mode")
+Cc: Lu Baolu <baolu.lu@linux.intel.com>
+Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
+Cc: Raj Ashok <ashok.raj@intel.com>
+Cc: David Woodhouse <dwmw2@infradead.org>
+Reported-by: Guo Kaijie <Kaijie.Guo@intel.com>
+Reported-by: Xin Zeng <xin.zeng@intel.com>
+Signed-off-by: Guo Kaijie <Kaijie.Guo@intel.com>
+Signed-off-by: Xin Zeng <xin.zeng@intel.com>
+Signed-off-by: Liu Yi L <yi.l.liu@intel.com>
+Tested-by: Guo Kaijie <Kaijie.Guo@intel.com>
+Cc: stable@vger.kernel.org # v5.0+
+Acked-by: Lu Baolu <baolu.lu@linux.intel.com>
+Link: https://lore.kernel.org/r/1609949037-25291-2-git-send-email-yi.l.liu@intel.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iommu/intel/svm.c | 9 +++++----
+ include/linux/intel-iommu.h | 2 +-
+ 2 files changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/iommu/intel/svm.c
++++ b/drivers/iommu/intel/svm.c
+@@ -142,7 +142,7 @@ static void intel_flush_svm_range_dev (s
+ }
+ desc.qw2 = 0;
+ desc.qw3 = 0;
+- qi_submit_sync(svm->iommu, &desc, 1, 0);
++ qi_submit_sync(sdev->iommu, &desc, 1, 0);
+
+ if (sdev->dev_iotlb) {
+ desc.qw0 = QI_DEV_EIOTLB_PASID(svm->pasid) |
+@@ -166,7 +166,7 @@ static void intel_flush_svm_range_dev (s
+ }
+ desc.qw2 = 0;
+ desc.qw3 = 0;
+- qi_submit_sync(svm->iommu, &desc, 1, 0);
++ qi_submit_sync(sdev->iommu, &desc, 1, 0);
+ }
+ }
+
+@@ -211,7 +211,7 @@ static void intel_mm_release(struct mmu_
+ */
+ rcu_read_lock();
+ list_for_each_entry_rcu(sdev, &svm->devs, list)
+- intel_pasid_tear_down_entry(svm->iommu, sdev->dev,
++ intel_pasid_tear_down_entry(sdev->iommu, sdev->dev,
+ svm->pasid, true);
+ rcu_read_unlock();
+
+@@ -363,6 +363,7 @@ int intel_svm_bind_gpasid(struct iommu_d
+ }
+ sdev->dev = dev;
+ sdev->sid = PCI_DEVID(info->bus, info->devfn);
++ sdev->iommu = iommu;
+
+ /* Only count users if device has aux domains */
+ if (iommu_dev_feature_enabled(dev, IOMMU_DEV_FEAT_AUX))
+@@ -546,6 +547,7 @@ intel_svm_bind_mm(struct device *dev, un
+ goto out;
+ }
+ sdev->dev = dev;
++ sdev->iommu = iommu;
+
+ ret = intel_iommu_enable_pasid(iommu, dev);
+ if (ret) {
+@@ -575,7 +577,6 @@ intel_svm_bind_mm(struct device *dev, un
+ kfree(sdev);
+ goto out;
+ }
+- svm->iommu = iommu;
+
+ if (pasid_max > intel_pasid_max_id)
+ pasid_max = intel_pasid_max_id;
+--- a/include/linux/intel-iommu.h
++++ b/include/linux/intel-iommu.h
+@@ -758,6 +758,7 @@ struct intel_svm_dev {
+ struct list_head list;
+ struct rcu_head rcu;
+ struct device *dev;
++ struct intel_iommu *iommu;
+ struct svm_dev_ops *ops;
+ struct iommu_sva sva;
+ u32 pasid;
+@@ -771,7 +772,6 @@ struct intel_svm {
+ struct mmu_notifier notifier;
+ struct mm_struct *mm;
+
+- struct intel_iommu *iommu;
+ unsigned int flags;
+ u32 pasid;
+ int gpasid; /* In case that guest PASID is different from host PASID */
--- /dev/null
+From 88bf56d04bc3564542049ec4ec168a8b60d0b48c Mon Sep 17 00:00:00 2001
+From: Lai Jiangshan <laijs@linux.alibaba.com>
+Date: Thu, 17 Dec 2020 23:41:18 +0800
+Subject: kvm: check tlbs_dirty directly
+
+From: Lai Jiangshan <laijs@linux.alibaba.com>
+
+commit 88bf56d04bc3564542049ec4ec168a8b60d0b48c upstream.
+
+In kvm_mmu_notifier_invalidate_range_start(), tlbs_dirty is used as:
+ need_tlb_flush |= kvm->tlbs_dirty;
+with need_tlb_flush's type being int and tlbs_dirty's type being long.
+
+It means that tlbs_dirty is always used as int and the higher 32 bits
+is useless. We need to check tlbs_dirty in a correct way and this
+change checks it directly without propagating it to need_tlb_flush.
+
+Note: it's _extremely_ unlikely this neglecting of higher 32 bits can
+cause problems in practice. It would require encountering tlbs_dirty
+on a 4 billion count boundary, and KVM would need to be using shadow
+paging or be running a nested guest.
+
+Cc: stable@vger.kernel.org
+Fixes: a4ee1ca4a36e ("KVM: MMU: delay flush all tlbs on sync_page path")
+Signed-off-by: Lai Jiangshan <laijs@linux.alibaba.com>
+Message-Id: <20201217154118.16497-1-jiangshanlai@gmail.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ virt/kvm/kvm_main.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/virt/kvm/kvm_main.c
++++ b/virt/kvm/kvm_main.c
+@@ -482,9 +482,8 @@ static int kvm_mmu_notifier_invalidate_r
+ kvm->mmu_notifier_count++;
+ need_tlb_flush = kvm_unmap_hva_range(kvm, range->start, range->end,
+ range->flags);
+- need_tlb_flush |= kvm->tlbs_dirty;
+ /* we've to flush the tlb before the pages can be freed */
+- if (need_tlb_flush)
++ if (need_tlb_flush || kvm->tlbs_dirty)
+ kvm_flush_remote_tlbs(kvm);
+
+ spin_unlock(&kvm->mmu_lock);
--- /dev/null
+From a889ea54b3daa63ee1463dc19ed699407d61458b Mon Sep 17 00:00:00 2001
+From: Ben Gardon <bgardon@google.com>
+Date: Wed, 6 Jan 2021 16:19:34 -0800
+Subject: KVM: x86/mmu: Ensure TDP MMU roots are freed after yield
+
+From: Ben Gardon <bgardon@google.com>
+
+commit a889ea54b3daa63ee1463dc19ed699407d61458b upstream.
+
+Many TDP MMU functions which need to perform some action on all TDP MMU
+roots hold a reference on that root so that they can safely drop the MMU
+lock in order to yield to other threads. However, when releasing the
+reference on the root, there is a bug: the root will not be freed even
+if its reference count (root_count) is reduced to 0.
+
+To simplify acquiring and releasing references on TDP MMU root pages, and
+to ensure that these roots are properly freed, move the get/put operations
+into another TDP MMU root iterator macro.
+
+Moving the get/put operations into an iterator macro also helps
+simplify control flow when a root does need to be freed. Note that using
+the list_for_each_entry_safe macro would not have been appropriate in
+this situation because it could keep a pointer to the next root across
+an MMU lock release + reacquire, during which time that root could be
+freed.
+
+Reported-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
+Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
+Fixes: faaf05b00aec ("kvm: x86/mmu: Support zapping SPTEs in the TDP MMU")
+Fixes: 063afacd8730 ("kvm: x86/mmu: Support invalidate range MMU notifier for TDP MMU")
+Fixes: a6a0b05da9f3 ("kvm: x86/mmu: Support dirty logging for the TDP MMU")
+Fixes: 14881998566d ("kvm: x86/mmu: Support disabling dirty logging for the tdp MMU")
+Signed-off-by: Ben Gardon <bgardon@google.com>
+Message-Id: <20210107001935.3732070-1-bgardon@google.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kvm/mmu/tdp_mmu.c | 104 ++++++++++++++++++++-------------------------
+ 1 file changed, 48 insertions(+), 56 deletions(-)
+
+--- a/arch/x86/kvm/mmu/tdp_mmu.c
++++ b/arch/x86/kvm/mmu/tdp_mmu.c
+@@ -42,7 +42,48 @@ void kvm_mmu_uninit_tdp_mmu(struct kvm *
+ WARN_ON(!list_empty(&kvm->arch.tdp_mmu_roots));
+ }
+
+-#define for_each_tdp_mmu_root(_kvm, _root) \
++static void tdp_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *root)
++{
++ if (kvm_mmu_put_root(kvm, root))
++ kvm_tdp_mmu_free_root(kvm, root);
++}
++
++static inline bool tdp_mmu_next_root_valid(struct kvm *kvm,
++ struct kvm_mmu_page *root)
++{
++ lockdep_assert_held(&kvm->mmu_lock);
++
++ if (list_entry_is_head(root, &kvm->arch.tdp_mmu_roots, link))
++ return false;
++
++ kvm_mmu_get_root(kvm, root);
++ return true;
++
++}
++
++static inline struct kvm_mmu_page *tdp_mmu_next_root(struct kvm *kvm,
++ struct kvm_mmu_page *root)
++{
++ struct kvm_mmu_page *next_root;
++
++ next_root = list_next_entry(root, link);
++ tdp_mmu_put_root(kvm, root);
++ return next_root;
++}
++
++/*
++ * Note: this iterator gets and puts references to the roots it iterates over.
++ * This makes it safe to release the MMU lock and yield within the loop, but
++ * if exiting the loop early, the caller must drop the reference to the most
++ * recent root. (Unless keeping a live reference is desirable.)
++ */
++#define for_each_tdp_mmu_root_yield_safe(_kvm, _root) \
++ for (_root = list_first_entry(&_kvm->arch.tdp_mmu_roots, \
++ typeof(*_root), link); \
++ tdp_mmu_next_root_valid(_kvm, _root); \
++ _root = tdp_mmu_next_root(_kvm, _root))
++
++#define for_each_tdp_mmu_root(_kvm, _root) \
+ list_for_each_entry(_root, &_kvm->arch.tdp_mmu_roots, link)
+
+ bool is_tdp_mmu_root(struct kvm *kvm, hpa_t hpa)
+@@ -439,18 +480,9 @@ bool kvm_tdp_mmu_zap_gfn_range(struct kv
+ struct kvm_mmu_page *root;
+ bool flush = false;
+
+- for_each_tdp_mmu_root(kvm, root) {
+- /*
+- * Take a reference on the root so that it cannot be freed if
+- * this thread releases the MMU lock and yields in this loop.
+- */
+- kvm_mmu_get_root(kvm, root);
+-
++ for_each_tdp_mmu_root_yield_safe(kvm, root)
+ flush |= zap_gfn_range(kvm, root, start, end, true);
+
+- kvm_mmu_put_root(kvm, root);
+- }
+-
+ return flush;
+ }
+
+@@ -609,13 +641,7 @@ static int kvm_tdp_mmu_handle_hva_range(
+ int ret = 0;
+ int as_id;
+
+- for_each_tdp_mmu_root(kvm, root) {
+- /*
+- * Take a reference on the root so that it cannot be freed if
+- * this thread releases the MMU lock and yields in this loop.
+- */
+- kvm_mmu_get_root(kvm, root);
+-
++ for_each_tdp_mmu_root_yield_safe(kvm, root) {
+ as_id = kvm_mmu_page_as_id(root);
+ slots = __kvm_memslots(kvm, as_id);
+ kvm_for_each_memslot(memslot, slots) {
+@@ -637,8 +663,6 @@ static int kvm_tdp_mmu_handle_hva_range(
+ ret |= handler(kvm, memslot, root, gfn_start,
+ gfn_end, data);
+ }
+-
+- kvm_mmu_put_root(kvm, root);
+ }
+
+ return ret;
+@@ -826,21 +850,13 @@ bool kvm_tdp_mmu_wrprot_slot(struct kvm
+ int root_as_id;
+ bool spte_set = false;
+
+- for_each_tdp_mmu_root(kvm, root) {
++ for_each_tdp_mmu_root_yield_safe(kvm, root) {
+ root_as_id = kvm_mmu_page_as_id(root);
+ if (root_as_id != slot->as_id)
+ continue;
+
+- /*
+- * Take a reference on the root so that it cannot be freed if
+- * this thread releases the MMU lock and yields in this loop.
+- */
+- kvm_mmu_get_root(kvm, root);
+-
+ spte_set |= wrprot_gfn_range(kvm, root, slot->base_gfn,
+ slot->base_gfn + slot->npages, min_level);
+-
+- kvm_mmu_put_root(kvm, root);
+ }
+
+ return spte_set;
+@@ -894,21 +910,13 @@ bool kvm_tdp_mmu_clear_dirty_slot(struct
+ int root_as_id;
+ bool spte_set = false;
+
+- for_each_tdp_mmu_root(kvm, root) {
++ for_each_tdp_mmu_root_yield_safe(kvm, root) {
+ root_as_id = kvm_mmu_page_as_id(root);
+ if (root_as_id != slot->as_id)
+ continue;
+
+- /*
+- * Take a reference on the root so that it cannot be freed if
+- * this thread releases the MMU lock and yields in this loop.
+- */
+- kvm_mmu_get_root(kvm, root);
+-
+ spte_set |= clear_dirty_gfn_range(kvm, root, slot->base_gfn,
+ slot->base_gfn + slot->npages);
+-
+- kvm_mmu_put_root(kvm, root);
+ }
+
+ return spte_set;
+@@ -1017,21 +1025,13 @@ bool kvm_tdp_mmu_slot_set_dirty(struct k
+ int root_as_id;
+ bool spte_set = false;
+
+- for_each_tdp_mmu_root(kvm, root) {
++ for_each_tdp_mmu_root_yield_safe(kvm, root) {
+ root_as_id = kvm_mmu_page_as_id(root);
+ if (root_as_id != slot->as_id)
+ continue;
+
+- /*
+- * Take a reference on the root so that it cannot be freed if
+- * this thread releases the MMU lock and yields in this loop.
+- */
+- kvm_mmu_get_root(kvm, root);
+-
+ spte_set |= set_dirty_gfn_range(kvm, root, slot->base_gfn,
+ slot->base_gfn + slot->npages);
+-
+- kvm_mmu_put_root(kvm, root);
+ }
+ return spte_set;
+ }
+@@ -1077,21 +1077,13 @@ void kvm_tdp_mmu_zap_collapsible_sptes(s
+ struct kvm_mmu_page *root;
+ int root_as_id;
+
+- for_each_tdp_mmu_root(kvm, root) {
++ for_each_tdp_mmu_root_yield_safe(kvm, root) {
+ root_as_id = kvm_mmu_page_as_id(root);
+ if (root_as_id != slot->as_id)
+ continue;
+
+- /*
+- * Take a reference on the root so that it cannot be freed if
+- * this thread releases the MMU lock and yields in this loop.
+- */
+- kvm_mmu_get_root(kvm, root);
+-
+ zap_collapsible_spte_range(kvm, root, slot->base_gfn,
+ slot->base_gfn + slot->npages);
+-
+- kvm_mmu_put_root(kvm, root);
+ }
+ }
+
--- /dev/null
+From 39b4d43e6003cee51cd119596d3c33d0449eb44c Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Thu, 17 Dec 2020 16:31:37 -0800
+Subject: KVM: x86/mmu: Get root level from walkers when retrieving MMIO SPTE
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 39b4d43e6003cee51cd119596d3c33d0449eb44c upstream.
+
+Get the so called "root" level from the low level shadow page table
+walkers instead of manually attempting to calculate it higher up the
+stack, e.g. in get_mmio_spte(). When KVM is using PAE shadow paging,
+the starting level of the walk, from the callers perspective, is not
+the CR3 root but rather the PDPTR "root". Checking for reserved bits
+from the CR3 root causes get_mmio_spte() to consume uninitialized stack
+data due to indexing into sptes[] for a level that was not filled by
+get_walk(). This can result in false positives and/or negatives
+depending on what garbage happens to be on the stack.
+
+Opportunistically nuke a few extra newlines.
+
+Fixes: 95fb5b0258b7 ("kvm: x86/mmu: Support MMIO in the TDP MMU")
+Reported-by: Richard Herbert <rherbert@sympatico.ca>
+Cc: Ben Gardon <bgardon@google.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20201218003139.2167891-3-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kvm/mmu/mmu.c | 15 ++++++---------
+ arch/x86/kvm/mmu/tdp_mmu.c | 5 ++++-
+ arch/x86/kvm/mmu/tdp_mmu.h | 4 +++-
+ 3 files changed, 13 insertions(+), 11 deletions(-)
+
+--- a/arch/x86/kvm/mmu/mmu.c
++++ b/arch/x86/kvm/mmu/mmu.c
+@@ -3485,16 +3485,16 @@ static bool mmio_info_in_cache(struct kv
+ * Return the level of the lowest level SPTE added to sptes.
+ * That SPTE may be non-present.
+ */
+-static int get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes)
++static int get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes, int *root_level)
+ {
+ struct kvm_shadow_walk_iterator iterator;
+ int leaf = -1;
+ u64 spte;
+
+-
+ walk_shadow_page_lockless_begin(vcpu);
+
+- for (shadow_walk_init(&iterator, vcpu, addr);
++ for (shadow_walk_init(&iterator, vcpu, addr),
++ *root_level = iterator.level;
+ shadow_walk_okay(&iterator);
+ __shadow_walk_next(&iterator, spte)) {
+ leaf = iterator.level;
+@@ -3504,7 +3504,6 @@ static int get_walk(struct kvm_vcpu *vcp
+
+ if (!is_shadow_present_pte(spte))
+ break;
+-
+ }
+
+ walk_shadow_page_lockless_end(vcpu);
+@@ -3517,9 +3516,7 @@ static bool get_mmio_spte(struct kvm_vcp
+ {
+ u64 sptes[PT64_ROOT_MAX_LEVEL];
+ struct rsvd_bits_validate *rsvd_check;
+- int root = vcpu->arch.mmu->shadow_root_level;
+- int leaf;
+- int level;
++ int root, leaf, level;
+ bool reserved = false;
+
+ if (!VALID_PAGE(vcpu->arch.mmu->root_hpa)) {
+@@ -3528,9 +3525,9 @@ static bool get_mmio_spte(struct kvm_vcp
+ }
+
+ if (is_tdp_mmu_root(vcpu->kvm, vcpu->arch.mmu->root_hpa))
+- leaf = kvm_tdp_mmu_get_walk(vcpu, addr, sptes);
++ leaf = kvm_tdp_mmu_get_walk(vcpu, addr, sptes, &root);
+ else
+- leaf = get_walk(vcpu, addr, sptes);
++ leaf = get_walk(vcpu, addr, sptes, &root);
+
+ if (unlikely(leaf < 0)) {
+ *sptep = 0ull;
+--- a/arch/x86/kvm/mmu/tdp_mmu.c
++++ b/arch/x86/kvm/mmu/tdp_mmu.c
+@@ -1148,13 +1148,16 @@ bool kvm_tdp_mmu_write_protect_gfn(struc
+ * Return the level of the lowest level SPTE added to sptes.
+ * That SPTE may be non-present.
+ */
+-int kvm_tdp_mmu_get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes)
++int kvm_tdp_mmu_get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes,
++ int *root_level)
+ {
+ struct tdp_iter iter;
+ struct kvm_mmu *mmu = vcpu->arch.mmu;
+ gfn_t gfn = addr >> PAGE_SHIFT;
+ int leaf = -1;
+
++ *root_level = vcpu->arch.mmu->shadow_root_level;
++
+ tdp_mmu_for_each_pte(iter, mmu, gfn, gfn + 1) {
+ leaf = iter.level;
+ sptes[leaf - 1] = iter.old_spte;
+--- a/arch/x86/kvm/mmu/tdp_mmu.h
++++ b/arch/x86/kvm/mmu/tdp_mmu.h
+@@ -44,5 +44,7 @@ void kvm_tdp_mmu_zap_collapsible_sptes(s
+ bool kvm_tdp_mmu_write_protect_gfn(struct kvm *kvm,
+ struct kvm_memory_slot *slot, gfn_t gfn);
+
+-int kvm_tdp_mmu_get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes);
++int kvm_tdp_mmu_get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes,
++ int *root_level);
++
+ #endif /* __KVM_X86_MMU_TDP_MMU_H */
--- /dev/null
+From 2aa078932ff6c66bf10cc5b3144440dbfa7d813d Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+Date: Thu, 17 Dec 2020 16:31:36 -0800
+Subject: KVM: x86/mmu: Use -1 to flag an undefined spte in get_mmio_spte()
+
+From: Sean Christopherson <seanjc@google.com>
+
+commit 2aa078932ff6c66bf10cc5b3144440dbfa7d813d upstream.
+
+Return -1 from the get_walk() helpers if the shadow walk doesn't fill at
+least one spte, which can theoretically happen if the walk hits a
+not-present PDPTR. Returning the root level in such a case will cause
+get_mmio_spte() to return garbage (uninitialized stack data). In
+practice, such a scenario should be impossible as KVM shouldn't get a
+reserved-bit page fault with a not-present PDPTR.
+
+Note, using mmu->root_level in get_walk() is wrong for other reasons,
+too, but that's now a moot point.
+
+Fixes: 95fb5b0258b7 ("kvm: x86/mmu: Support MMIO in the TDP MMU")
+Cc: Ben Gardon <bgardon@google.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20201218003139.2167891-2-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kvm/mmu/mmu.c | 7 ++++++-
+ arch/x86/kvm/mmu/tdp_mmu.c | 2 +-
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/kvm/mmu/mmu.c
++++ b/arch/x86/kvm/mmu/mmu.c
+@@ -3488,7 +3488,7 @@ static bool mmio_info_in_cache(struct kv
+ static int get_walk(struct kvm_vcpu *vcpu, u64 addr, u64 *sptes)
+ {
+ struct kvm_shadow_walk_iterator iterator;
+- int leaf = vcpu->arch.mmu->root_level;
++ int leaf = -1;
+ u64 spte;
+
+
+@@ -3532,6 +3532,11 @@ static bool get_mmio_spte(struct kvm_vcp
+ else
+ leaf = get_walk(vcpu, addr, sptes);
+
++ if (unlikely(leaf < 0)) {
++ *sptep = 0ull;
++ return reserved;
++ }
++
+ rsvd_check = &vcpu->arch.mmu->shadow_zero_check;
+
+ for (level = root; level >= leaf; level--) {
+--- a/arch/x86/kvm/mmu/tdp_mmu.c
++++ b/arch/x86/kvm/mmu/tdp_mmu.c
+@@ -1152,8 +1152,8 @@ int kvm_tdp_mmu_get_walk(struct kvm_vcpu
+ {
+ struct tdp_iter iter;
+ struct kvm_mmu *mmu = vcpu->arch.mmu;
+- int leaf = vcpu->arch.mmu->shadow_root_level;
+ gfn_t gfn = addr >> PAGE_SHIFT;
++ int leaf = -1;
+
+ tdp_mmu_for_each_pte(iter, mmu, gfn, gfn + 1) {
+ leaf = iter.level;
--- /dev/null
+From c2407cf7d22d0c0d94cf20342b3b8f06f1d904e7 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Tue, 5 Jan 2021 11:33:00 -0800
+Subject: mm: make wait_on_page_writeback() wait for multiple pending writebacks
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit c2407cf7d22d0c0d94cf20342b3b8f06f1d904e7 upstream.
+
+Ever since commit 2a9127fcf229 ("mm: rewrite wait_on_page_bit_common()
+logic") we've had some very occasional reports of BUG_ON(PageWriteback)
+in write_cache_pages(), which we thought we already fixed in commit
+073861ed77b6 ("mm: fix VM_BUG_ON(PageTail) and BUG_ON(PageWriteback)").
+
+But syzbot just reported another one, even with that commit in place.
+
+And it turns out that there's a simpler way to trigger the BUG_ON() than
+the one Hugh found with page re-use. It all boils down to the fact that
+the page writeback is ostensibly serialized by the page lock, but that
+isn't actually really true.
+
+Yes, the people _setting_ writeback all do so under the page lock, but
+the actual clearing of the bit - and waking up any waiters - happens
+without any page lock.
+
+This gives us this fairly simple race condition:
+
+ CPU1 = end previous writeback
+ CPU2 = start new writeback under page lock
+ CPU3 = write_cache_pages()
+
+ CPU1 CPU2 CPU3
+ ---- ---- ----
+
+ end_page_writeback()
+ test_clear_page_writeback(page)
+ ... delayed...
+
+ lock_page();
+ set_page_writeback()
+ unlock_page()
+
+ lock_page()
+ wait_on_page_writeback();
+
+ wake_up_page(page, PG_writeback);
+ .. wakes up CPU3 ..
+
+ BUG_ON(PageWriteback(page));
+
+where the BUG_ON() happens because we woke up the PG_writeback bit
+becasue of the _previous_ writeback, but a new one had already been
+started because the clearing of the bit wasn't actually atomic wrt the
+actual wakeup or serialized by the page lock.
+
+The reason this didn't use to happen was that the old logic in waiting
+on a page bit would just loop if it ever saw the bit set again.
+
+The nice proper fix would probably be to get rid of the whole "wait for
+writeback to clear, and then set it" logic in the writeback path, and
+replace it with an atomic "wait-to-set" (ie the same as we have for page
+locking: we set the page lock bit with a single "lock_page()", not with
+"wait for lock bit to clear and then set it").
+
+However, out current model for writeback is that the waiting for the
+writeback bit is done by the generic VFS code (ie write_cache_pages()),
+but the actual setting of the writeback bit is done much later by the
+filesystem ".writepages()" function.
+
+IOW, to make the writeback bit have that same kind of "wait-to-set"
+behavior as we have for page locking, we'd have to change our roughly
+~50 different writeback functions. Painful.
+
+Instead, just make "wait_on_page_writeback()" loop on the very unlikely
+situation that the PG_writeback bit is still set, basically re-instating
+the old behavior. This is very non-optimal in case of contention, but
+since we only ever set the bit under the page lock, that situation is
+controlled.
+
+Reported-by: syzbot+2fc0712f8f8b8b8fa0ef@syzkaller.appspotmail.com
+Fixes: 2a9127fcf229 ("mm: rewrite wait_on_page_bit_common() logic")
+Acked-by: Hugh Dickins <hughd@google.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Matthew Wilcox <willy@infradead.org>
+Cc: stable@kernel.org
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ mm/page-writeback.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/mm/page-writeback.c
++++ b/mm/page-writeback.c
+@@ -2826,7 +2826,7 @@ EXPORT_SYMBOL(__test_set_page_writeback)
+ */
+ void wait_on_page_writeback(struct page *page)
+ {
+- if (PageWriteback(page)) {
++ while (PageWriteback(page)) {
+ trace_wait_on_page_writeback(page, page_mapping(page));
+ wait_on_page_bit(page, PG_writeback);
+ }
--- /dev/null
+From 47f4469970d8861bc06d2d4d45ac8200ff07c693 Mon Sep 17 00:00:00 2001
+From: Bard Liao <yung-chuan.liao@linux.intel.com>
+Date: Tue, 5 Jan 2021 17:11:45 +0800
+Subject: Revert "device property: Keep secondary firmware node secondary by type"
+
+From: Bard Liao <yung-chuan.liao@linux.intel.com>
+
+commit 47f4469970d8861bc06d2d4d45ac8200ff07c693 upstream.
+
+While commit d5dcce0c414f ("device property: Keep secondary firmware
+node secondary by type") describes everything correct in its commit
+message, the change it made does the opposite and original commit
+c15e1bdda436 ("device property: Fix the secondary firmware node handling
+in set_primary_fwnode()") was fully correct.
+
+Revert the former one here and improve documentation in the next patch.
+
+Fixes: d5dcce0c414f ("device property: Keep secondary firmware node secondary by type")
+Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Cc: 5.10+ <stable@vger.kernel.org> # 5.10+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/base/core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/base/core.c
++++ b/drivers/base/core.c
+@@ -4278,7 +4278,7 @@ void set_primary_fwnode(struct device *d
+ if (fwnode_is_primary(fn)) {
+ dev->fwnode = fn->secondary;
+ if (!(parent && fn == parent->fwnode))
+- fn->secondary = ERR_PTR(-ENODEV);
++ fn->secondary = NULL;
+ } else {
+ dev->fwnode = NULL;
+ }
usb-cdc-acm-blacklist-another-ir-droid-device.patch
usb-cdc-wdm-fix-use-after-free-in-service_outstanding_interrupt.patch
usb-typec-intel_pmc_mux-configure-hpd-first-for-hpd-irq-request.patch
+usb-dwc3-meson-g12a-disable-clk-on-error-handling-path-in-probe.patch
+usb-dwc3-gadget-restart-dwc3-gadget-when-enabling-pullup.patch
+usb-dwc3-gadget-clear-wait-flag-on-dequeue.patch
+usb-dwc3-ulpi-use-vstsdone-to-detect-phy-regs-access-completion.patch
+usb-dwc3-ulpi-replace-cpu-based-busyloop-with-protocol-based-one.patch
+usb-dwc3-ulpi-fix-usb2.0-hs-fs-ls-phy-suspend-regression.patch
+usb-chipidea-ci_hdrc_imx-add-missing-put_device-call-in-usbmisc_get_init_data.patch
+usb-xhci-fix-u1-u2-handling-for-hardware-with-xhci_intel_host-quirk-set.patch
+usb-usbip-vhci_hcd-protect-shift-size.patch
+usb-uas-add-pny-usb-portable-ssd-to-unusual_uas.patch
+usb-serial-iuu_phoenix-fix-dma-from-stack.patch
+usb-serial-option-add-longsung-m5710-module-support.patch
+usb-serial-option-add-quectel-em160r-gl.patch
+usb-yurex-fix-control-urb-timeout-handling.patch
+usb-usblp-fix-dma-to-stack.patch
+alsa-usb-audio-fix-ubsan-warnings-for-midi-jacks.patch
+usb-gadget-select-config_crc32.patch
+usb-gadget-dummy-hcd-fix-shift-out-of-bounds-bug.patch
+usb-gadget-f_uac2-reset-wmaxpacketsize.patch
+usb-gadget-function-printer-fix-a-memory-leak-for-interface-descriptor.patch
+usb-gadget-u_ether-fix-mtu-size-mismatch-with-rx-packet-size.patch
+usb-gadget-legacy-fix-return-error-code-in-acm_ms_bind.patch
+usb-gadget-fix-spinlock-lockup-on-usb_function_deactivate.patch
+usb-gadget-configfs-preserve-function-ordering-after-bind-failure.patch
+usb-gadget-configfs-fix-use-after-free-issue-with-udc_name.patch
+usb-serial-keyspan_pda-remove-unused-variable.patch
+hwmon-amd_energy-fix-allocation-of-hwmon_channel_info-config.patch
+mm-make-wait_on_page_writeback-wait-for-multiple-pending-writebacks.patch
+x86-mm-fix-leak-of-pmd-ptlock.patch
+kvm-x86-mmu-use-1-to-flag-an-undefined-spte-in-get_mmio_spte.patch
+kvm-x86-mmu-get-root-level-from-walkers-when-retrieving-mmio-spte.patch
+kvm-check-tlbs_dirty-directly.patch
+kvm-x86-mmu-ensure-tdp-mmu-roots-are-freed-after-yield.patch
+x86-resctrl-use-an-ipi-instead-of-task_work_add-to-update-pqr_assoc-msr.patch
+x86-resctrl-don-t-move-a-task-to-the-same-resource-group.patch
+blk-iocost-fix-null-iocg-deref-from-racing-against-initialization.patch
+alsa-hda-via-fix-runtime-pm-for-clevo-w35xss.patch
+alsa-hda-conexant-add-a-new-hda-codec-cx11970.patch
+alsa-hda-realtek-fix-speaker-volume-control-on-lenovo-c940.patch
+alsa-hda-realtek-add-mute-led-quirk-for-more-hp-laptops.patch
+alsa-hda-realtek-enable-mute-and-micmute-led-on-hp-elitebook-850-g7.patch
+alsa-hda-realtek-add-two-intel-reference-board-ssid-in-the-alc256.patch
+iommu-vt-d-move-intel_iommu-info-from-struct-intel_svm-to-struct-intel_svm_dev.patch
+btrfs-qgroup-don-t-try-to-wait-flushing-if-we-re-already-holding-a-transaction.patch
+btrfs-send-fix-wrong-file-path-when-there-is-an-inode-with-a-pending-rmdir.patch
+revert-device-property-keep-secondary-firmware-node-secondary-by-type.patch
+dmabuf-fix-use-after-free-of-dmabuf-s-file-f_inode.patch
+arm64-link-with-z-norelro-for-lld-or-aarch64-elf.patch
+drm-i915-clear-the-shadow-batch.patch
+drm-i915-clear-the-gpu-reloc-batch.patch
+bcache-fix-typo-from-suup-to-supp-in-features.h.patch
+bcache-check-unsupported-feature-sets-for-bcache-register.patch
+bcache-introduce-bch_feature_incompat_log_large_bucket_size-for-large-bucket.patch
--- /dev/null
+From 83a43ff80a566de8718dfc6565545a0080ec1fb5 Mon Sep 17 00:00:00 2001
+From: Yu Kuai <yukuai3@huawei.com>
+Date: Tue, 17 Nov 2020 09:14:30 +0800
+Subject: usb: chipidea: ci_hdrc_imx: add missing put_device() call in usbmisc_get_init_data()
+
+From: Yu Kuai <yukuai3@huawei.com>
+
+commit 83a43ff80a566de8718dfc6565545a0080ec1fb5 upstream.
+
+if of_find_device_by_node() succeed, usbmisc_get_init_data() doesn't have
+a corresponding put_device(). Thus add put_device() to fix the exception
+handling for this function implementation.
+
+Fixes: ef12da914ed6 ("usb: chipidea: imx: properly check for usbmisc")
+Signed-off-by: Yu Kuai <yukuai3@huawei.com>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20201117011430.642589-1-yukuai3@huawei.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/chipidea/ci_hdrc_imx.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/chipidea/ci_hdrc_imx.c
++++ b/drivers/usb/chipidea/ci_hdrc_imx.c
+@@ -139,9 +139,13 @@ static struct imx_usbmisc_data *usbmisc_
+ misc_pdev = of_find_device_by_node(args.np);
+ of_node_put(args.np);
+
+- if (!misc_pdev || !platform_get_drvdata(misc_pdev))
++ if (!misc_pdev)
+ return ERR_PTR(-EPROBE_DEFER);
+
++ if (!platform_get_drvdata(misc_pdev)) {
++ put_device(&misc_pdev->dev);
++ return ERR_PTR(-EPROBE_DEFER);
++ }
+ data->dev = &misc_pdev->dev;
+
+ /*
--- /dev/null
+From a5c7682aaaa10e42928d73de1c9e1e02d2b14c2e Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Mon, 4 Jan 2021 22:42:39 -0800
+Subject: usb: dwc3: gadget: Clear wait flag on dequeue
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit a5c7682aaaa10e42928d73de1c9e1e02d2b14c2e upstream.
+
+If an active transfer is dequeued, then the endpoint is freed to start a
+new transfer. Make sure to clear the endpoint's transfer wait flag for
+this case.
+
+Fixes: e0d19563eb6c ("usb: dwc3: gadget: Wait for transfer completion")
+Cc: stable@vger.kernel.org
+Acked-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://lore.kernel.org/r/b81cd5b5281cfbfdadb002c4bcf5c9be7c017cfd.1609828485.git.Thinh.Nguyen@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/gadget.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1763,6 +1763,8 @@ static int dwc3_gadget_ep_dequeue(struct
+ list_for_each_entry_safe(r, t, &dep->started_list, list)
+ dwc3_gadget_move_cancelled_request(r);
+
++ dep->flags &= ~DWC3_EP_WAIT_TRANSFER_COMPLETE;
++
+ goto out;
+ }
+ }
--- /dev/null
+From a1383b3537a7bea1c213baa7878ccc4ecf4413b5 Mon Sep 17 00:00:00 2001
+From: Wesley Cheng <wcheng@codeaurora.org>
+Date: Tue, 29 Dec 2020 15:00:37 -0800
+Subject: usb: dwc3: gadget: Restart DWC3 gadget when enabling pullup
+
+From: Wesley Cheng <wcheng@codeaurora.org>
+
+commit a1383b3537a7bea1c213baa7878ccc4ecf4413b5 upstream.
+
+usb_gadget_deactivate/usb_gadget_activate does not execute the UDC start
+operation, which may leave EP0 disabled and event IRQs disabled when
+re-activating the function. Move the enabling/disabling of USB EP0 and
+device event IRQs to be performed in the pullup routine.
+
+Fixes: ae7e86108b12 ("usb: dwc3: Stop active transfers before halting the controller")
+Tested-by: Michael Tretter <m.tretter@pengutronix.de>
+Cc: stable <stable@vger.kernel.org>
+Reported-by: Michael Tretter <m.tretter@pengutronix.de>
+Signed-off-by: Wesley Cheng <wcheng@codeaurora.org>
+Link: https://lore.kernel.org/r/1609282837-21666-1-git-send-email-wcheng@codeaurora.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/gadget.c | 14 +++-----------
+ 1 file changed, 3 insertions(+), 11 deletions(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -2083,6 +2083,7 @@ static int dwc3_gadget_run_stop(struct d
+
+ static void dwc3_gadget_disable_irq(struct dwc3 *dwc);
+ static void __dwc3_gadget_stop(struct dwc3 *dwc);
++static int __dwc3_gadget_start(struct dwc3 *dwc);
+
+ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
+ {
+@@ -2145,6 +2146,8 @@ static int dwc3_gadget_pullup(struct usb
+ dwc->ev_buf->lpos = (dwc->ev_buf->lpos + count) %
+ dwc->ev_buf->length;
+ }
++ } else {
++ __dwc3_gadget_start(dwc);
+ }
+
+ ret = dwc3_gadget_run_stop(dwc, is_on, false);
+@@ -2319,10 +2322,6 @@ static int dwc3_gadget_start(struct usb_
+ }
+
+ dwc->gadget_driver = driver;
+-
+- if (pm_runtime_active(dwc->dev))
+- __dwc3_gadget_start(dwc);
+-
+ spin_unlock_irqrestore(&dwc->lock, flags);
+
+ return 0;
+@@ -2348,13 +2347,6 @@ static int dwc3_gadget_stop(struct usb_g
+ unsigned long flags;
+
+ spin_lock_irqsave(&dwc->lock, flags);
+-
+- if (pm_runtime_suspended(dwc->dev))
+- goto out;
+-
+- __dwc3_gadget_stop(dwc);
+-
+-out:
+ dwc->gadget_driver = NULL;
+ spin_unlock_irqrestore(&dwc->lock, flags);
+
--- /dev/null
+From a5ada3dfe6a20f41f91448b9034a1ef8da3dc87d Mon Sep 17 00:00:00 2001
+From: Zheng Zengkai <zhengzengkai@huawei.com>
+Date: Tue, 15 Dec 2020 10:54:59 +0800
+Subject: usb: dwc3: meson-g12a: disable clk on error handling path in probe
+
+From: Zheng Zengkai <zhengzengkai@huawei.com>
+
+commit a5ada3dfe6a20f41f91448b9034a1ef8da3dc87d upstream.
+
+dwc3_meson_g12a_probe() does not invoke clk_bulk_disable_unprepare()
+on one error handling path. This patch fixes that.
+
+Fixes: 347052e3bf1b ("usb: dwc3: meson-g12a: fix USB2 PHY initialization on G12A and A1 SoCs")
+Reported-by: Hulk Robot <hulkci@huawei.com>
+Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
+Cc: stable <stable@vger.kernel.org>
+Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+Link: https://lore.kernel.org/r/20201215025459.91794-1-zhengzengkai@huawei.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/dwc3-meson-g12a.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/dwc3/dwc3-meson-g12a.c
++++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
+@@ -754,7 +754,7 @@ static int dwc3_meson_g12a_probe(struct
+
+ ret = priv->drvdata->setup_regmaps(priv, base);
+ if (ret)
+- return ret;
++ goto err_disable_clks;
+
+ if (priv->vbus) {
+ ret = regulator_enable(priv->vbus);
--- /dev/null
+From e5f4ca3fce90a37b23a77bfcc86800d484a80514 Mon Sep 17 00:00:00 2001
+From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
+Date: Thu, 10 Dec 2020 11:50:08 +0300
+Subject: usb: dwc3: ulpi: Fix USB2.0 HS/FS/LS PHY suspend regression
+
+From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
+
+commit e5f4ca3fce90a37b23a77bfcc86800d484a80514 upstream.
+
+First of all the commit e0082698b689 ("usb: dwc3: ulpi: conditionally
+resume ULPI PHY") introduced the Suspend USB2.0 HS/FS/LS PHY regression,
+as by design of the fix any attempt to read/write from/to the PHY control
+registers will completely disable the PHY suspension, which consequently
+will increase the USB bus power consumption. Secondly the fix won't work
+well for the very first attempt of the ULPI PHY control registers IO,
+because after disabling the USB2.0 PHY suspension functionality it will
+still take some time for the bus to resume from the sleep state if one has
+been reached before it. So the very first PHY register read/write
+operation will take more time than the busy-loop provides and the IO
+timeout error might be returned anyway.
+
+Here we suggest to fix the denoted problems in the following way. First of
+all let's not disable the Suspend USB2.0 HS/FS/LS PHY functionality so to
+make the controller and the USB2.0 bus more power efficient. Secondly
+instead of that we'll extend the PHY IO op wait procedure with 1 - 1.2 ms
+sleep if the PHY suspension is enabled (1ms should be enough as by LPM
+specification it is at most how long it takes for the USB2.0 bus to resume
+from L1 (Sleep) state). Finally in case if the USB2.0 PHY suspension
+functionality has been disabled on the DWC USB3 controller setup procedure
+we'll compensate the USB bus resume process latency by extending the
+busy-loop attempts counter.
+
+Fixes: e0082698b689 ("usb: dwc3: ulpi: conditionally resume ULPI PHY")
+Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
+Link: https://lore.kernel.org/r/20201210085008.13264-4-Sergey.Semin@baikalelectronics.ru
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/ulpi.c | 18 +++++-------------
+ 1 file changed, 5 insertions(+), 13 deletions(-)
+
+--- a/drivers/usb/dwc3/ulpi.c
++++ b/drivers/usb/dwc3/ulpi.c
+@@ -24,7 +24,7 @@
+ static int dwc3_ulpi_busyloop(struct dwc3 *dwc, u8 addr, bool read)
+ {
+ unsigned long ns = 5L * DWC3_ULPI_BASE_DELAY;
+- unsigned int count = 1000;
++ unsigned int count = 10000;
+ u32 reg;
+
+ if (addr >= ULPI_EXT_VENDOR_SPECIFIC)
+@@ -33,6 +33,10 @@ static int dwc3_ulpi_busyloop(struct dwc
+ if (read)
+ ns += DWC3_ULPI_BASE_DELAY;
+
++ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
++ if (reg & DWC3_GUSB2PHYCFG_SUSPHY)
++ usleep_range(1000, 1200);
++
+ while (count--) {
+ ndelay(ns);
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0));
+@@ -50,12 +54,6 @@ static int dwc3_ulpi_read(struct device
+ u32 reg;
+ int ret;
+
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+- if (reg & DWC3_GUSB2PHYCFG_SUSPHY) {
+- reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+- }
+-
+ reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
+
+@@ -73,12 +71,6 @@ static int dwc3_ulpi_write(struct device
+ struct dwc3 *dwc = dev_get_drvdata(dev);
+ u32 reg;
+
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+- if (reg & DWC3_GUSB2PHYCFG_SUSPHY) {
+- reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+- }
+-
+ reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
+ reg |= DWC3_GUSB2PHYACC_WRITE | val;
+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
--- /dev/null
+From fca3f138105727c3a22edda32d02f91ce1bf11c9 Mon Sep 17 00:00:00 2001
+From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
+Date: Thu, 10 Dec 2020 11:50:07 +0300
+Subject: usb: dwc3: ulpi: Replace CPU-based busyloop with Protocol-based one
+
+From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
+
+commit fca3f138105727c3a22edda32d02f91ce1bf11c9 upstream.
+
+Originally the procedure of the ULPI transaction finish detection has been
+developed as a simple busy-loop with just decrementing counter and no
+delays. It's wrong since on different systems the loop will take a
+different time to complete. So if the system bus and CPU are fast enough
+to overtake the ULPI bus and the companion PHY reaction, then we'll get to
+take a false timeout error. Fix this by converting the busy-loop procedure
+to take the standard bus speed, address value and the registers access
+mode into account for the busy-loop delay calculation.
+
+Here is the way the fix works. It's known that the ULPI bus is clocked
+with 60MHz signal. In accordance with [1] the ULPI bus protocol is created
+so to spend 5 and 6 clock periods for immediate register write and read
+operations respectively, and 6 and 7 clock periods - for the extended
+register writes and reads. Based on that we can easily pre-calculate the
+time which will be needed for the controller to perform a requested IO
+operation. Note we'll still preserve the attempts counter in case if the
+DWC USB3 controller has got some internals delays.
+
+[1] UTMI+ Low Pin Interface (ULPI) Specification, Revision 1.1,
+ October 20, 2004, pp. 30 - 36.
+
+Fixes: 88bc9d194ff6 ("usb: dwc3: add ULPI interface support")
+Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
+Link: https://lore.kernel.org/r/20201210085008.13264-3-Sergey.Semin@baikalelectronics.ru
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/ulpi.c | 18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/dwc3/ulpi.c
++++ b/drivers/usb/dwc3/ulpi.c
+@@ -7,6 +7,8 @@
+ * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+ */
+
++#include <linux/delay.h>
++#include <linux/time64.h>
+ #include <linux/ulpi/regs.h>
+
+ #include "core.h"
+@@ -17,12 +19,22 @@
+ DWC3_GUSB2PHYACC_ADDR(ULPI_ACCESS_EXTENDED) | \
+ DWC3_GUSB2PHYACC_EXTEND_ADDR(a) : DWC3_GUSB2PHYACC_ADDR(a))
+
+-static int dwc3_ulpi_busyloop(struct dwc3 *dwc)
++#define DWC3_ULPI_BASE_DELAY DIV_ROUND_UP(NSEC_PER_SEC, 60000000L)
++
++static int dwc3_ulpi_busyloop(struct dwc3 *dwc, u8 addr, bool read)
+ {
++ unsigned long ns = 5L * DWC3_ULPI_BASE_DELAY;
+ unsigned int count = 1000;
+ u32 reg;
+
++ if (addr >= ULPI_EXT_VENDOR_SPECIFIC)
++ ns += DWC3_ULPI_BASE_DELAY;
++
++ if (read)
++ ns += DWC3_ULPI_BASE_DELAY;
++
+ while (count--) {
++ ndelay(ns);
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0));
+ if (reg & DWC3_GUSB2PHYACC_DONE)
+ return 0;
+@@ -47,7 +59,7 @@ static int dwc3_ulpi_read(struct device
+ reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
+
+- ret = dwc3_ulpi_busyloop(dwc);
++ ret = dwc3_ulpi_busyloop(dwc, addr, true);
+ if (ret)
+ return ret;
+
+@@ -71,7 +83,7 @@ static int dwc3_ulpi_write(struct device
+ reg |= DWC3_GUSB2PHYACC_WRITE | val;
+ dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
+
+- return dwc3_ulpi_busyloop(dwc);
++ return dwc3_ulpi_busyloop(dwc, addr, false);
+ }
+
+ static const struct ulpi_ops dwc3_ulpi_ops = {
--- /dev/null
+From ce722da66d3e9384aa2de9d33d584ee154e5e157 Mon Sep 17 00:00:00 2001
+From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
+Date: Thu, 10 Dec 2020 11:50:06 +0300
+Subject: usb: dwc3: ulpi: Use VStsDone to detect PHY regs access completion
+
+From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
+
+commit ce722da66d3e9384aa2de9d33d584ee154e5e157 upstream.
+
+In accordance with [1] the DWC_usb3 core sets the GUSB2PHYACCn.VStsDone
+bit when the PHY vendor control access is done and clears it when the
+application initiates a new transaction. The doc doesn't say anything
+about the GUSB2PHYACCn.VStsBsy flag serving for the same purpose. Moreover
+we've discovered that the VStsBsy flag can be cleared before the VStsDone
+bit. So using the former as a signal of the PHY control registers
+completion might be dangerous. Let's have the VStsDone flag utilized
+instead then.
+
+[1] Synopsys DesignWare Cores SuperSpeed USB 3.0 xHCI Host Controller
+ Databook, 2.70a, December 2013, p.388
+
+Fixes: 88bc9d194ff6 ("usb: dwc3: add ULPI interface support")
+Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
+Link: https://lore.kernel.org/r/20201210085008.13264-2-Sergey.Semin@baikalelectronics.ru
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/core.h | 1 +
+ drivers/usb/dwc3/ulpi.c | 2 +-
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/dwc3/core.h
++++ b/drivers/usb/dwc3/core.h
+@@ -285,6 +285,7 @@
+
+ /* Global USB2 PHY Vendor Control Register */
+ #define DWC3_GUSB2PHYACC_NEWREGREQ BIT(25)
++#define DWC3_GUSB2PHYACC_DONE BIT(24)
+ #define DWC3_GUSB2PHYACC_BUSY BIT(23)
+ #define DWC3_GUSB2PHYACC_WRITE BIT(22)
+ #define DWC3_GUSB2PHYACC_ADDR(n) (n << 16)
+--- a/drivers/usb/dwc3/ulpi.c
++++ b/drivers/usb/dwc3/ulpi.c
+@@ -24,7 +24,7 @@ static int dwc3_ulpi_busyloop(struct dwc
+
+ while (count--) {
+ reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0));
+- if (!(reg & DWC3_GUSB2PHYACC_BUSY))
++ if (reg & DWC3_GUSB2PHYACC_DONE)
+ return 0;
+ cpu_relax();
+ }
--- /dev/null
+From 64e6bbfff52db4bf6785fab9cffab850b2de6870 Mon Sep 17 00:00:00 2001
+From: Eddie Hung <eddie.hung@mediatek.com>
+Date: Tue, 29 Dec 2020 18:53:35 +0800
+Subject: usb: gadget: configfs: Fix use-after-free issue with udc_name
+
+From: Eddie Hung <eddie.hung@mediatek.com>
+
+commit 64e6bbfff52db4bf6785fab9cffab850b2de6870 upstream.
+
+There is a use-after-free issue, if access udc_name
+in function gadget_dev_desc_UDC_store after another context
+free udc_name in function unregister_gadget.
+
+Context 1:
+gadget_dev_desc_UDC_store()->unregister_gadget()->
+free udc_name->set udc_name to NULL
+
+Context 2:
+gadget_dev_desc_UDC_show()-> access udc_name
+
+Call trace:
+dump_backtrace+0x0/0x340
+show_stack+0x14/0x1c
+dump_stack+0xe4/0x134
+print_address_description+0x78/0x478
+__kasan_report+0x270/0x2ec
+kasan_report+0x10/0x18
+__asan_report_load1_noabort+0x18/0x20
+string+0xf4/0x138
+vsnprintf+0x428/0x14d0
+sprintf+0xe4/0x12c
+gadget_dev_desc_UDC_show+0x54/0x64
+configfs_read_file+0x210/0x3a0
+__vfs_read+0xf0/0x49c
+vfs_read+0x130/0x2b4
+SyS_read+0x114/0x208
+el0_svc_naked+0x34/0x38
+
+Add mutex_lock to protect this kind of scenario.
+
+Signed-off-by: Eddie Hung <eddie.hung@mediatek.com>
+Signed-off-by: Macpaul Lin <macpaul.lin@mediatek.com>
+Reviewed-by: Peter Chen <peter.chen@nxp.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/1609239215-21819-1-git-send-email-macpaul.lin@mediatek.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/configfs.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/gadget/configfs.c
++++ b/drivers/usb/gadget/configfs.c
+@@ -221,9 +221,16 @@ static ssize_t gadget_dev_desc_bcdUSB_st
+
+ static ssize_t gadget_dev_desc_UDC_show(struct config_item *item, char *page)
+ {
+- char *udc_name = to_gadget_info(item)->composite.gadget_driver.udc_name;
++ struct gadget_info *gi = to_gadget_info(item);
++ char *udc_name;
++ int ret;
+
+- return sprintf(page, "%s\n", udc_name ?: "");
++ mutex_lock(&gi->lock);
++ udc_name = gi->composite.gadget_driver.udc_name;
++ ret = sprintf(page, "%s\n", udc_name ?: "");
++ mutex_unlock(&gi->lock);
++
++ return ret;
+ }
+
+ static int unregister_gadget(struct gadget_info *gi)
--- /dev/null
+From 6cd0fe91387917be48e91385a572a69dfac2f3f7 Mon Sep 17 00:00:00 2001
+From: Chandana Kishori Chiluveru <cchiluve@codeaurora.org>
+Date: Tue, 29 Dec 2020 14:44:43 -0800
+Subject: usb: gadget: configfs: Preserve function ordering after bind failure
+
+From: Chandana Kishori Chiluveru <cchiluve@codeaurora.org>
+
+commit 6cd0fe91387917be48e91385a572a69dfac2f3f7 upstream.
+
+When binding the ConfigFS gadget to a UDC, the functions in each
+configuration are added in list order. However, if usb_add_function()
+fails, the failed function is put back on its configuration's
+func_list and purge_configs_funcs() is called to further clean up.
+
+purge_configs_funcs() iterates over the configurations and functions
+in forward order, calling unbind() on each of the previously added
+functions. But after doing so, each function gets moved to the
+tail of the configuration's func_list. This results in reshuffling
+the original order of the functions within a configuration such
+that the failed function now appears first even though it may have
+originally appeared in the middle or even end of the list. At this
+point if the ConfigFS gadget is attempted to re-bind to the UDC,
+the functions will be added in a different order than intended,
+with the only recourse being to remove and relink the functions all
+over again.
+
+An example of this as follows:
+
+ln -s functions/mass_storage.0 configs/c.1
+ln -s functions/ncm.0 configs/c.1
+ln -s functions/ffs.adb configs/c.1 # oops, forgot to start adbd
+echo "<udc device>" > UDC # fails
+start adbd
+echo "<udc device>" > UDC # now succeeds, but...
+ # bind order is
+ # "ADB", mass_storage, ncm
+
+[30133.118289] configfs-gadget gadget: adding 'Mass Storage Function'/ffffff810af87200 to config 'c'/ffffff817d6a2520
+[30133.119875] configfs-gadget gadget: adding 'cdc_network'/ffffff80f48d1a00 to config 'c'/ffffff817d6a2520
+[30133.119974] using random self ethernet address
+[30133.120002] using random host ethernet address
+[30133.139604] usb0: HOST MAC 3e:27:46:ba:3e:26
+[30133.140015] usb0: MAC 6e:28:7e:42:66:6a
+[30133.140062] configfs-gadget gadget: adding 'Function FS Gadget'/ffffff80f3868438 to config 'c'/ffffff817d6a2520
+[30133.140081] configfs-gadget gadget: adding 'Function FS Gadget'/ffffff80f3868438 --> -19
+[30133.140098] configfs-gadget gadget: unbind function 'Mass Storage Function'/ffffff810af87200
+[30133.140119] configfs-gadget gadget: unbind function 'cdc_network'/ffffff80f48d1a00
+[30133.173201] configfs-gadget a600000.dwc3: failed to start g1: -19
+[30136.661933] init: starting service 'adbd'...
+[30136.700126] read descriptors
+[30136.700413] read strings
+[30138.574484] configfs-gadget gadget: adding 'Function FS Gadget'/ffffff80f3868438 to config 'c'/ffffff817d6a2520
+[30138.575497] configfs-gadget gadget: adding 'Mass Storage Function'/ffffff810af87200 to config 'c'/ffffff817d6a2520
+[30138.575554] configfs-gadget gadget: adding 'cdc_network'/ffffff80f48d1a00 to config 'c'/ffffff817d6a2520
+[30138.575631] using random self ethernet address
+[30138.575660] using random host ethernet address
+[30138.595338] usb0: HOST MAC 2e:cf:43:cd:ca:c8
+[30138.597160] usb0: MAC 6a:f0:9f:ee:82:a0
+[30138.791490] configfs-gadget gadget: super-speed config #1: c
+
+Fix this by reversing the iteration order of the functions in
+purge_config_funcs() when unbinding them, and adding them back to
+the config's func_list at the head instead of the tail. This
+ensures that we unbind and unwind back to the original list order.
+
+Fixes: 88af8bbe4ef7 ("usb: gadget: the start of the configfs interface")
+Signed-off-by: Chandana Kishori Chiluveru <cchiluve@codeaurora.org>
+Signed-off-by: Jack Pham <jackp@codeaurora.org>
+Reviewed-by: Peter Chen <peter.chen@nxp.com>
+Link: https://lore.kernel.org/r/20201229224443.31623-1-jackp@codeaurora.org
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/configfs.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/gadget/configfs.c
++++ b/drivers/usb/gadget/configfs.c
+@@ -1248,9 +1248,9 @@ static void purge_configs_funcs(struct g
+
+ cfg = container_of(c, struct config_usb_cfg, c);
+
+- list_for_each_entry_safe(f, tmp, &c->functions, list) {
++ list_for_each_entry_safe_reverse(f, tmp, &c->functions, list) {
+
+- list_move_tail(&f->list, &cfg->func_list);
++ list_move(&f->list, &cfg->func_list);
+ if (f->unbind) {
+ dev_dbg(&gi->cdev.gadget->dev,
+ "unbind function '%s'/%p\n",
--- /dev/null
+From c318840fb2a42ce25febc95c4c19357acf1ae5ca Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Wed, 30 Dec 2020 11:20:44 -0500
+Subject: USB: Gadget: dummy-hcd: Fix shift-out-of-bounds bug
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+commit c318840fb2a42ce25febc95c4c19357acf1ae5ca upstream.
+
+The dummy-hcd driver was written under the assumption that all the
+parameters in URBs sent to its root hub would be valid. With URBs
+sent from userspace via usbfs, that assumption can be violated.
+
+In particular, the driver doesn't fully check the port-feature values
+stored in the wValue entry of Clear-Port-Feature and Set-Port-Feature
+requests. Values that are too large can cause the driver to perform
+an invalid left shift of more than 32 bits. Ironically, two of those
+left shifts are unnecessary, because they implement Set-Port-Feature
+requests that hubs are not required to support, according to section
+11.24.2.13 of the USB-2.0 spec.
+
+This patch adds the appropriate checks for the port feature selector
+values and removes the unnecessary feature settings. It also rejects
+requests to set the TEST feature or to set or clear the INDICATOR and
+C_OVERCURRENT features, as none of these are relevant to dummy-hcd's
+root-hub emulation.
+
+CC: <stable@vger.kernel.org>
+Reported-and-tested-by: syzbot+5925509f78293baa7331@syzkaller.appspotmail.com
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Link: https://lore.kernel.org/r/20201230162044.GA727759@rowland.harvard.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/udc/dummy_hcd.c | 35 +++++++++++++++++++++++------------
+ 1 file changed, 23 insertions(+), 12 deletions(-)
+
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -2114,9 +2114,21 @@ static int dummy_hub_control(
+ dum_hcd->port_status &= ~USB_PORT_STAT_POWER;
+ set_link_state(dum_hcd);
+ break;
+- default:
++ case USB_PORT_FEAT_ENABLE:
++ case USB_PORT_FEAT_C_ENABLE:
++ case USB_PORT_FEAT_C_SUSPEND:
++ /* Not allowed for USB-3 */
++ if (hcd->speed == HCD_USB3)
++ goto error;
++ fallthrough;
++ case USB_PORT_FEAT_C_CONNECTION:
++ case USB_PORT_FEAT_C_RESET:
+ dum_hcd->port_status &= ~(1 << wValue);
+ set_link_state(dum_hcd);
++ break;
++ default:
++ /* Disallow INDICATOR and C_OVER_CURRENT */
++ goto error;
+ }
+ break;
+ case GetHubDescriptor:
+@@ -2277,18 +2289,17 @@ static int dummy_hub_control(
+ */
+ dum_hcd->re_timeout = jiffies + msecs_to_jiffies(50);
+ fallthrough;
++ case USB_PORT_FEAT_C_CONNECTION:
++ case USB_PORT_FEAT_C_RESET:
++ case USB_PORT_FEAT_C_ENABLE:
++ case USB_PORT_FEAT_C_SUSPEND:
++ /* Not allowed for USB-3, and ignored for USB-2 */
++ if (hcd->speed == HCD_USB3)
++ goto error;
++ break;
+ default:
+- if (hcd->speed == HCD_USB3) {
+- if ((dum_hcd->port_status &
+- USB_SS_PORT_STAT_POWER) != 0) {
+- dum_hcd->port_status |= (1 << wValue);
+- }
+- } else
+- if ((dum_hcd->port_status &
+- USB_PORT_STAT_POWER) != 0) {
+- dum_hcd->port_status |= (1 << wValue);
+- }
+- set_link_state(dum_hcd);
++ /* Disallow TEST, INDICATOR, and C_OVER_CURRENT */
++ goto error;
+ }
+ break;
+ case GetPortErrorCount:
--- /dev/null
+From 9389044f27081d6ec77730c36d5bf9a1288bcda2 Mon Sep 17 00:00:00 2001
+From: Jerome Brunet <jbrunet@baylibre.com>
+Date: Mon, 21 Dec 2020 18:35:28 +0100
+Subject: usb: gadget: f_uac2: reset wMaxPacketSize
+
+From: Jerome Brunet <jbrunet@baylibre.com>
+
+commit 9389044f27081d6ec77730c36d5bf9a1288bcda2 upstream.
+
+With commit 913e4a90b6f9 ("usb: gadget: f_uac2: finalize wMaxPacketSize according to bandwidth")
+wMaxPacketSize is computed dynamically but the value is never reset.
+
+Because of this, the actual maximum packet size can only decrease each time
+the audio gadget is instantiated.
+
+Reset the endpoint maximum packet size and mark wMaxPacketSize as dynamic
+to solve the problem.
+
+Fixes: 913e4a90b6f9 ("usb: gadget: f_uac2: finalize wMaxPacketSize according to bandwidth")
+Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20201221173531.215169-2-jbrunet@baylibre.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/function/f_uac2.c | 69 +++++++++++++++++++++++++++--------
+ 1 file changed, 55 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/gadget/function/f_uac2.c
++++ b/drivers/usb/gadget/function/f_uac2.c
+@@ -271,7 +271,7 @@ static struct usb_endpoint_descriptor fs
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+- .wMaxPacketSize = cpu_to_le16(1023),
++ /* .wMaxPacketSize = DYNAMIC */
+ .bInterval = 1,
+ };
+
+@@ -280,7 +280,7 @@ static struct usb_endpoint_descriptor hs
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+- .wMaxPacketSize = cpu_to_le16(1024),
++ /* .wMaxPacketSize = DYNAMIC */
+ .bInterval = 4,
+ };
+
+@@ -348,7 +348,7 @@ static struct usb_endpoint_descriptor fs
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+- .wMaxPacketSize = cpu_to_le16(1023),
++ /* .wMaxPacketSize = DYNAMIC */
+ .bInterval = 1,
+ };
+
+@@ -357,7 +357,7 @@ static struct usb_endpoint_descriptor hs
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
+- .wMaxPacketSize = cpu_to_le16(1024),
++ /* .wMaxPacketSize = DYNAMIC */
+ .bInterval = 4,
+ };
+
+@@ -444,12 +444,28 @@ struct cntrl_range_lay3 {
+ __le32 dRES;
+ } __packed;
+
+-static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
++static int set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
+ struct usb_endpoint_descriptor *ep_desc,
+- unsigned int factor, bool is_playback)
++ enum usb_device_speed speed, bool is_playback)
+ {
+ int chmask, srate, ssize;
+- u16 max_packet_size;
++ u16 max_size_bw, max_size_ep;
++ unsigned int factor;
++
++ switch (speed) {
++ case USB_SPEED_FULL:
++ max_size_ep = 1023;
++ factor = 1000;
++ break;
++
++ case USB_SPEED_HIGH:
++ max_size_ep = 1024;
++ factor = 8000;
++ break;
++
++ default:
++ return -EINVAL;
++ }
+
+ if (is_playback) {
+ chmask = uac2_opts->p_chmask;
+@@ -461,10 +477,12 @@ static void set_ep_max_packet_size(const
+ ssize = uac2_opts->c_ssize;
+ }
+
+- max_packet_size = num_channels(chmask) * ssize *
++ max_size_bw = num_channels(chmask) * ssize *
+ DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1)));
+- ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_packet_size,
+- le16_to_cpu(ep_desc->wMaxPacketSize)));
++ ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_size_bw,
++ max_size_ep));
++
++ return 0;
+ }
+
+ /* Use macro to overcome line length limitation */
+@@ -670,10 +688,33 @@ afunc_bind(struct usb_configuration *cfg
+ }
+
+ /* Calculate wMaxPacketSize according to audio bandwidth */
+- set_ep_max_packet_size(uac2_opts, &fs_epin_desc, 1000, true);
+- set_ep_max_packet_size(uac2_opts, &fs_epout_desc, 1000, false);
+- set_ep_max_packet_size(uac2_opts, &hs_epin_desc, 8000, true);
+- set_ep_max_packet_size(uac2_opts, &hs_epout_desc, 8000, false);
++ ret = set_ep_max_packet_size(uac2_opts, &fs_epin_desc, USB_SPEED_FULL,
++ true);
++ if (ret < 0) {
++ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
++ return ret;
++ }
++
++ ret = set_ep_max_packet_size(uac2_opts, &fs_epout_desc, USB_SPEED_FULL,
++ false);
++ if (ret < 0) {
++ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
++ return ret;
++ }
++
++ ret = set_ep_max_packet_size(uac2_opts, &hs_epin_desc, USB_SPEED_HIGH,
++ true);
++ if (ret < 0) {
++ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
++ return ret;
++ }
++
++ ret = set_ep_max_packet_size(uac2_opts, &hs_epout_desc, USB_SPEED_HIGH,
++ false);
++ if (ret < 0) {
++ dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
++ return ret;
++ }
+
+ if (EPOUT_EN(uac2_opts)) {
+ agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc);
--- /dev/null
+From 5cc35c224a80aa5a5a539510ef049faf0d6ed181 Mon Sep 17 00:00:00 2001
+From: Sriharsha Allenki <sallenki@codeaurora.org>
+Date: Wed, 2 Dec 2020 18:32:20 +0530
+Subject: usb: gadget: Fix spinlock lockup on usb_function_deactivate
+
+From: Sriharsha Allenki <sallenki@codeaurora.org>
+
+commit 5cc35c224a80aa5a5a539510ef049faf0d6ed181 upstream.
+
+There is a spinlock lockup as part of composite_disconnect
+when it tries to acquire cdev->lock as part of usb_gadget_deactivate.
+This is because the usb_gadget_deactivate is called from
+usb_function_deactivate with the same spinlock held.
+
+This would result in the below call stack and leads to stall.
+
+rcu: INFO: rcu_preempt detected stalls on CPUs/tasks:
+rcu: 3-...0: (1 GPs behind) idle=162/1/0x4000000000000000
+softirq=10819/10819 fqs=2356
+ (detected by 2, t=5252 jiffies, g=20129, q=3770)
+ Task dump for CPU 3:
+ task:uvc-gadget_wlhe state:R running task stack: 0 pid: 674 ppid:
+ 636 flags:0x00000202
+ Call trace:
+ __switch_to+0xc0/0x170
+ _raw_spin_lock_irqsave+0x84/0xb0
+ composite_disconnect+0x28/0x78
+ configfs_composite_disconnect+0x68/0x70
+ usb_gadget_disconnect+0x10c/0x128
+ usb_gadget_deactivate+0xd4/0x108
+ usb_function_deactivate+0x6c/0x80
+ uvc_function_disconnect+0x20/0x58
+ uvc_v4l2_release+0x30/0x88
+ v4l2_release+0xbc/0xf0
+ __fput+0x7c/0x230
+ ____fput+0x14/0x20
+ task_work_run+0x88/0x140
+ do_notify_resume+0x240/0x6f0
+ work_pending+0x8/0x200
+
+Fix this by doing an unlock on cdev->lock before the usb_gadget_deactivate
+call from usb_function_deactivate.
+
+The same lockup can happen in the usb_gadget_activate path. Fix that path
+as well.
+
+Reported-by: Peter Chen <peter.chen@nxp.com>
+Link: https://lore.kernel.org/linux-usb/20201102094936.GA29581@b29397-desktop/
+Tested-by: Peter Chen <peter.chen@nxp.com>
+Signed-off-by: Sriharsha Allenki <sallenki@codeaurora.org>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20201202130220.24926-1-sallenki@codeaurora.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/composite.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/gadget/composite.c
++++ b/drivers/usb/gadget/composite.c
+@@ -392,8 +392,11 @@ int usb_function_deactivate(struct usb_f
+
+ spin_lock_irqsave(&cdev->lock, flags);
+
+- if (cdev->deactivations == 0)
++ if (cdev->deactivations == 0) {
++ spin_unlock_irqrestore(&cdev->lock, flags);
+ status = usb_gadget_deactivate(cdev->gadget);
++ spin_lock_irqsave(&cdev->lock, flags);
++ }
+ if (status == 0)
+ cdev->deactivations++;
+
+@@ -424,8 +427,11 @@ int usb_function_activate(struct usb_fun
+ status = -EINVAL;
+ else {
+ cdev->deactivations--;
+- if (cdev->deactivations == 0)
++ if (cdev->deactivations == 0) {
++ spin_unlock_irqrestore(&cdev->lock, flags);
+ status = usb_gadget_activate(cdev->gadget);
++ spin_lock_irqsave(&cdev->lock, flags);
++ }
+ }
+
+ spin_unlock_irqrestore(&cdev->lock, flags);
--- /dev/null
+From 2cc332e4ee4febcbb685e2962ad323fe4b3b750a Mon Sep 17 00:00:00 2001
+From: Zqiang <qiang.zhang@windriver.com>
+Date: Thu, 10 Dec 2020 10:01:48 +0800
+Subject: usb: gadget: function: printer: Fix a memory leak for interface descriptor
+
+From: Zqiang <qiang.zhang@windriver.com>
+
+commit 2cc332e4ee4febcbb685e2962ad323fe4b3b750a upstream.
+
+When printer driver is loaded, the printer_func_bind function is called, in
+this function, the interface descriptor be allocated memory, if after that,
+the error occurred, the interface descriptor memory need to be free.
+
+Reviewed-by: Peter Chen <peter.chen@nxp.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Zqiang <qiang.zhang@windriver.com>
+Link: https://lore.kernel.org/r/20201210020148.6691-1-qiang.zhang@windriver.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/function/f_printer.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/gadget/function/f_printer.c
++++ b/drivers/usb/gadget/function/f_printer.c
+@@ -1162,6 +1162,7 @@ fail_tx_reqs:
+ printer_req_free(dev->in_ep, req);
+ }
+
++ usb_free_all_descriptors(f);
+ return ret;
+
+ }
--- /dev/null
+From c91d3a6bcaa031f551ba29a496a8027b31289464 Mon Sep 17 00:00:00 2001
+From: Yang Yingliang <yangyingliang@huawei.com>
+Date: Tue, 17 Nov 2020 17:29:55 +0800
+Subject: USB: gadget: legacy: fix return error code in acm_ms_bind()
+
+From: Yang Yingliang <yangyingliang@huawei.com>
+
+commit c91d3a6bcaa031f551ba29a496a8027b31289464 upstream.
+
+If usb_otg_descriptor_alloc() failed, it need return ENOMEM.
+
+Fixes: 578aa8a2b12c ("usb: gadget: acm_ms: allocate and init otg descriptor by otg capabilities")
+Reported-by: Hulk Robot <hulkci@huawei.com>
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20201117092955.4102785-1-yangyingliang@huawei.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/legacy/acm_ms.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/legacy/acm_ms.c
++++ b/drivers/usb/gadget/legacy/acm_ms.c
+@@ -200,8 +200,10 @@ static int acm_ms_bind(struct usb_compos
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+- if (!usb_desc)
++ if (!usb_desc) {
++ status = -ENOMEM;
+ goto fail_string_ids;
++ }
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
--- /dev/null
+From d7889c2020e08caab0d7e36e947f642d91015bd0 Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Sun, 3 Jan 2021 22:42:17 +0100
+Subject: usb: gadget: select CONFIG_CRC32
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+commit d7889c2020e08caab0d7e36e947f642d91015bd0 upstream.
+
+Without crc32 support, this driver fails to link:
+
+arm-linux-gnueabi-ld: drivers/usb/gadget/function/f_eem.o: in function `eem_unwrap':
+f_eem.c:(.text+0x11cc): undefined reference to `crc32_le'
+arm-linux-gnueabi-ld: drivers/usb/gadget/function/f_ncm.o:f_ncm.c:(.text+0x1e40):
+more undefined references to `crc32_le' follow
+
+Fixes: 6d3865f9d41f ("usb: gadget: NCM: Add transmit multi-frame.")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20210103214224.1996535-1-arnd@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/Kconfig | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/gadget/Kconfig
++++ b/drivers/usb/gadget/Kconfig
+@@ -265,6 +265,7 @@ config USB_CONFIGFS_NCM
+ depends on NET
+ select USB_U_ETHER
+ select USB_F_NCM
++ select CRC32
+ help
+ NCM is an advanced protocol for Ethernet encapsulation, allows
+ grouping of several ethernet frames into one USB transfer and
+@@ -314,6 +315,7 @@ config USB_CONFIGFS_EEM
+ depends on NET
+ select USB_U_ETHER
+ select USB_F_EEM
++ select CRC32
+ help
+ CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM
+ and therefore can be supported by more hardware. Technically ECM and
--- /dev/null
+From 0a88fa221ce911c331bf700d2214c5b2f77414d3 Mon Sep 17 00:00:00 2001
+From: Manish Narani <manish.narani@xilinx.com>
+Date: Tue, 17 Nov 2020 12:43:35 +0530
+Subject: usb: gadget: u_ether: Fix MTU size mismatch with RX packet size
+
+From: Manish Narani <manish.narani@xilinx.com>
+
+commit 0a88fa221ce911c331bf700d2214c5b2f77414d3 upstream.
+
+Fix the MTU size issue with RX packet size as the host sends the packet
+with extra bytes containing ethernet header. This causes failure when
+user sets the MTU size to the maximum i.e. 15412. In this case the
+ethernet packet received will be of length 15412 plus the ethernet header
+length. This patch fixes the issue where there is a check that RX packet
+length must not be more than max packet length.
+
+Fixes: bba787a860fa ("usb: gadget: ether: Allow jumbo frames")
+Signed-off-by: Manish Narani <manish.narani@xilinx.com>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/1605597215-122027-1-git-send-email-manish.narani@xilinx.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/function/u_ether.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/gadget/function/u_ether.c
++++ b/drivers/usb/gadget/function/u_ether.c
+@@ -45,9 +45,10 @@
+ #define UETH__VERSION "29-May-2008"
+
+ /* Experiments show that both Linux and Windows hosts allow up to 16k
+- * frame sizes. Set the max size to 15k+52 to prevent allocating 32k
++ * frame sizes. Set the max MTU size to 15k+52 to prevent allocating 32k
+ * blocks and still have efficient handling. */
+-#define GETHER_MAX_ETH_FRAME_LEN 15412
++#define GETHER_MAX_MTU_SIZE 15412
++#define GETHER_MAX_ETH_FRAME_LEN (GETHER_MAX_MTU_SIZE + ETH_HLEN)
+
+ struct eth_dev {
+ /* lock is held while accessing port_usb
+@@ -786,7 +787,7 @@ struct eth_dev *gether_setup_name(struct
+
+ /* MTU range: 14 - 15412 */
+ net->min_mtu = ETH_HLEN;
+- net->max_mtu = GETHER_MAX_ETH_FRAME_LEN;
++ net->max_mtu = GETHER_MAX_MTU_SIZE;
+
+ dev->gadget = g;
+ SET_NETDEV_DEV(net, &g->dev);
+@@ -848,7 +849,7 @@ struct net_device *gether_setup_name_def
+
+ /* MTU range: 14 - 15412 */
+ net->min_mtu = ETH_HLEN;
+- net->max_mtu = GETHER_MAX_ETH_FRAME_LEN;
++ net->max_mtu = GETHER_MAX_MTU_SIZE;
+
+ return net;
+ }
--- /dev/null
+From 54d0a3ab80f49f19ee916def62fe067596833403 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 4 Jan 2021 15:50:07 +0100
+Subject: USB: serial: iuu_phoenix: fix DMA from stack
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 54d0a3ab80f49f19ee916def62fe067596833403 upstream.
+
+Stack-allocated buffers cannot be used for DMA (on all architectures) so
+allocate the flush command buffer using kmalloc().
+
+Fixes: 60a8fc017103 ("USB: add iuu_phoenix driver")
+Cc: stable <stable@vger.kernel.org> # 2.6.25
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/iuu_phoenix.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/serial/iuu_phoenix.c
++++ b/drivers/usb/serial/iuu_phoenix.c
+@@ -532,23 +532,29 @@ static int iuu_uart_flush(struct usb_ser
+ struct device *dev = &port->dev;
+ int i;
+ int status;
+- u8 rxcmd = IUU_UART_RX;
++ u8 *rxcmd;
+ struct iuu_private *priv = usb_get_serial_port_data(port);
+
+ if (iuu_led(port, 0xF000, 0, 0, 0xFF) < 0)
+ return -EIO;
+
++ rxcmd = kmalloc(1, GFP_KERNEL);
++ if (!rxcmd)
++ return -ENOMEM;
++
++ rxcmd[0] = IUU_UART_RX;
++
+ for (i = 0; i < 2; i++) {
+- status = bulk_immediate(port, &rxcmd, 1);
++ status = bulk_immediate(port, rxcmd, 1);
+ if (status != IUU_OPERATION_OK) {
+ dev_dbg(dev, "%s - uart_flush_write error\n", __func__);
+- return status;
++ goto out_free;
+ }
+
+ status = read_immediate(port, &priv->len, 1);
+ if (status != IUU_OPERATION_OK) {
+ dev_dbg(dev, "%s - uart_flush_read error\n", __func__);
+- return status;
++ goto out_free;
+ }
+
+ if (priv->len > 0) {
+@@ -556,12 +562,16 @@ static int iuu_uart_flush(struct usb_ser
+ status = read_immediate(port, priv->buf, priv->len);
+ if (status != IUU_OPERATION_OK) {
+ dev_dbg(dev, "%s - uart_flush_read error\n", __func__);
+- return status;
++ goto out_free;
+ }
+ }
+ }
+ dev_dbg(dev, "%s - uart_flush_read OK!\n", __func__);
+ iuu_led(port, 0, 0xF000, 0, 0xFF);
++
++out_free:
++ kfree(rxcmd);
++
+ return status;
+ }
+
--- /dev/null
+From 62218024401fac7dd7c7a6e74b566164d515d922 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Fri, 8 Jan 2021 15:55:28 +0100
+Subject: USB: serial: keyspan_pda: remove unused variable
+
+From: Johan Hovold <johan@kernel.org>
+
+Remove an unused variable which was mistakingly left by commit
+37faf5061541 ("USB: serial: keyspan_pda: fix write-wakeup
+use-after-free") and only removed by a later change.
+
+This is needed to suppress a W=1 warning about the unused variable in
+the stable trees that the build bots triggers.
+
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/serial/keyspan_pda.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/usb/serial/keyspan_pda.c
++++ b/drivers/usb/serial/keyspan_pda.c
+@@ -555,10 +555,8 @@ exit:
+ static void keyspan_pda_write_bulk_callback(struct urb *urb)
+ {
+ struct usb_serial_port *port = urb->context;
+- struct keyspan_pda_private *priv;
+
+ set_bit(0, &port->write_urbs_free);
+- priv = usb_get_serial_port_data(port);
+
+ /* queue up a wakeup at scheduler time */
+ usb_serial_port_softint(port);
--- /dev/null
+From 0e2d6795e8dbe91c2f5473564c6b25d11df3778b Mon Sep 17 00:00:00 2001
+From: Daniel Palmer <daniel@0x0f.com>
+Date: Sun, 27 Dec 2020 12:17:16 +0900
+Subject: USB: serial: option: add LongSung M5710 module support
+
+From: Daniel Palmer <daniel@0x0f.com>
+
+commit 0e2d6795e8dbe91c2f5473564c6b25d11df3778b upstream.
+
+Add a device-id entry for the LongSung M5710 module.
+
+T: Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=480 MxCh= 0
+D: Ver= 2.00 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs= 1
+P: Vendor=2df3 ProdID=9d03 Rev= 1.00
+S: Manufacturer=Marvell
+S: Product=Mobile Composite Device Bus
+S: SerialNumber=<snip>
+C:* #Ifs= 5 Cfg#= 1 Atr=c0 MxPwr=500mA
+A: FirstIf#= 0 IfCount= 2 Cls=e0(wlcon) Sub=01 Prot=03
+I:* If#= 0 Alt= 0 #EPs= 1 Cls=e0(wlcon) Sub=01 Prot=03 Driver=rndis_host
+E: Ad=87(I) Atr=03(Int.) MxPS= 64 Ivl=4096ms
+I:* If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=rndis_host
+E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=0c(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
+E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=0b(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
+E: Ad=89(I) Atr=03(Int.) MxPS= 64 Ivl=4096ms
+E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=0f(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+I:* If#= 5 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option
+E: Ad=88(I) Atr=03(Int.) MxPS= 64 Ivl=4096ms
+E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+E: Ad=0a(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
+
+Signed-off-by: Daniel Palmer <daniel@0x0f.com>
+https://lore.kernel.org/r/20201227031716.1343300-1-daniel@0x0f.com
+[ johan: drop id defines, only bind to vendor class ]
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/option.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -2057,6 +2057,7 @@ static const struct usb_device_id option
+ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff), /* Fibocom NL678 series */
+ .driver_info = RSVD(6) },
+ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */
++ { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */
+ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */
+ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */
+ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */
--- /dev/null
+From d6c1ddd938d84a1adef7e19e8efc10e1b4df5034 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bjorn@mork.no>
+Date: Wed, 30 Dec 2020 16:25:34 +0100
+Subject: USB: serial: option: add Quectel EM160R-GL
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Bjørn Mork <bjorn@mork.no>
+
+commit d6c1ddd938d84a1adef7e19e8efc10e1b4df5034 upstream.
+
+New modem using ff/ff/30 for QCDM, ff/00/00 for AT and NMEA,
+and ff/ff/ff for RMNET/QMI.
+
+T: Bus=02 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=5000 MxCh= 0
+D: Ver= 3.20 Cls=ef(misc ) Sub=02 Prot=01 MxPS= 9 #Cfgs= 1
+P: Vendor=2c7c ProdID=0620 Rev= 4.09
+S: Manufacturer=Quectel
+S: Product=EM160R-GL
+S: SerialNumber=e31cedc1
+C:* #Ifs= 5 Cfg#= 1 Atr=a0 MxPwr=896mA
+I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=(none)
+E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
+E: Ad=01(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
+I:* If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)
+E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
+E: Ad=82(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
+E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
+I:* If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)
+E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
+E: Ad=84(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
+E: Ad=03(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
+I:* If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=(none)
+E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
+E: Ad=86(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
+E: Ad=04(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
+I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
+E: Ad=88(I) Atr=03(Int.) MxPS= 8 Ivl=32ms
+E: Ad=8e(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms
+E: Ad=0f(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Bjørn Mork <bjorn@mork.no>
+[ johan: add model comment ]
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/serial/option.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -1117,6 +1117,8 @@ static const struct usb_device_id option
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0xff, 0xff),
+ .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0, 0) },
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, 0x0620, 0xff, 0xff, 0x30) }, /* EM160R-GL */
++ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, 0x0620, 0xff, 0, 0) },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x30) },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0, 0) },
+ { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x10),
--- /dev/null
+From 96ebc9c871d8a28fb22aa758dd9188a4732df482 Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Mon, 4 Jan 2021 20:07:15 -0800
+Subject: usb: uas: Add PNY USB Portable SSD to unusual_uas
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit 96ebc9c871d8a28fb22aa758dd9188a4732df482 upstream.
+
+Here's another variant PNY Pro Elite USB 3.1 Gen 2 portable SSD that
+hangs and doesn't respond to ATA_1x pass-through commands. If it doesn't
+support these commands, it should respond properly to the host. Add it
+to the unusual uas list to be able to move forward with other
+operations.
+
+Cc: stable@vger.kernel.org
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Acked-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://lore.kernel.org/r/2edc7af892d0913bf06f5b35e49ec463f03d5ed8.1609819418.git.Thinh.Nguyen@synopsys.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/storage/unusual_uas.h | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/usb/storage/unusual_uas.h
++++ b/drivers/usb/storage/unusual_uas.h
+@@ -91,6 +91,13 @@ UNUSUAL_DEV(0x152d, 0x0578, 0x0000, 0x99
+ US_FL_BROKEN_FUA),
+
+ /* Reported-by: Thinh Nguyen <thinhn@synopsys.com> */
++UNUSUAL_DEV(0x154b, 0xf00b, 0x0000, 0x9999,
++ "PNY",
++ "Pro Elite SSD",
++ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++ US_FL_NO_ATA_1X),
++
++/* Reported-by: Thinh Nguyen <thinhn@synopsys.com> */
+ UNUSUAL_DEV(0x154b, 0xf00d, 0x0000, 0x9999,
+ "PNY",
+ "Pro Elite SSD",
--- /dev/null
+From 718bf42b119de652ebcc93655a1f33a9c0d04b3c Mon Sep 17 00:00:00 2001
+From: Randy Dunlap <rdunlap@infradead.org>
+Date: Mon, 28 Dec 2020 23:13:09 -0800
+Subject: usb: usbip: vhci_hcd: protect shift size
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+commit 718bf42b119de652ebcc93655a1f33a9c0d04b3c upstream.
+
+Fix shift out-of-bounds in vhci_hcd.c:
+
+ UBSAN: shift-out-of-bounds in ../drivers/usb/usbip/vhci_hcd.c:399:41
+ shift exponent 768 is too large for 32-bit type 'int'
+
+Fixes: 03cd00d538a6 ("usbip: vhci-hcd: Set the vhci structure up to work")
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Reported-by: syzbot+297d20e437b79283bf6d@syzkaller.appspotmail.com
+Cc: Yuyang Du <yuyang.du@intel.com>
+Cc: Shuah Khan <shuahkh@osg.samsung.com>
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: linux-usb@vger.kernel.org
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20201229071309.18418-1-rdunlap@infradead.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/usbip/vhci_hcd.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/usbip/vhci_hcd.c
++++ b/drivers/usb/usbip/vhci_hcd.c
+@@ -396,6 +396,8 @@ static int vhci_hub_control(struct usb_h
+ default:
+ usbip_dbg_vhci_rh(" ClearPortFeature: default %x\n",
+ wValue);
++ if (wValue >= 32)
++ goto error;
+ vhci_hcd->port_status[rhport] &= ~(1 << wValue);
+ break;
+ }
--- /dev/null
+From 020a1f453449294926ca548d8d5ca970926e8dfd Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 4 Jan 2021 15:53:02 +0100
+Subject: USB: usblp: fix DMA to stack
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 020a1f453449294926ca548d8d5ca970926e8dfd upstream.
+
+Stack-allocated buffers cannot be used for DMA (on all architectures).
+
+Replace the HP-channel macro with a helper function that allocates a
+dedicated transfer buffer so that it can continue to be used with
+arguments from the stack.
+
+Note that the buffer is cleared on allocation as usblp_ctrl_msg()
+returns success also on short transfers (the buffer is only used for
+debugging).
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://lore.kernel.org/r/20210104145302.2087-1-johan@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/usblp.c | 21 +++++++++++++++++++--
+ 1 file changed, 19 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/class/usblp.c
++++ b/drivers/usb/class/usblp.c
+@@ -274,8 +274,25 @@ static int usblp_ctrl_msg(struct usblp *
+ #define usblp_reset(usblp)\
+ usblp_ctrl_msg(usblp, USBLP_REQ_RESET, USB_TYPE_CLASS, USB_DIR_OUT, USB_RECIP_OTHER, 0, NULL, 0)
+
+-#define usblp_hp_channel_change_request(usblp, channel, buffer) \
+- usblp_ctrl_msg(usblp, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST, USB_TYPE_VENDOR, USB_DIR_IN, USB_RECIP_INTERFACE, channel, buffer, 1)
++static int usblp_hp_channel_change_request(struct usblp *usblp, int channel, u8 *new_channel)
++{
++ u8 *buf;
++ int ret;
++
++ buf = kzalloc(1, GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ ret = usblp_ctrl_msg(usblp, USBLP_REQ_HP_CHANNEL_CHANGE_REQUEST,
++ USB_TYPE_VENDOR, USB_DIR_IN, USB_RECIP_INTERFACE,
++ channel, buf, 1);
++ if (ret == 0)
++ *new_channel = buf[0];
++
++ kfree(buf);
++
++ return ret;
++}
+
+ /*
+ * See the description for usblp_select_alts() below for the usage
--- /dev/null
+From 5d5323a6f3625f101dbfa94ba3ef7706cce38760 Mon Sep 17 00:00:00 2001
+From: Michael Grzeschik <m.grzeschik@pengutronix.de>
+Date: Tue, 15 Dec 2020 20:31:47 +0100
+Subject: USB: xhci: fix U1/U2 handling for hardware with XHCI_INTEL_HOST quirk set
+
+From: Michael Grzeschik <m.grzeschik@pengutronix.de>
+
+commit 5d5323a6f3625f101dbfa94ba3ef7706cce38760 upstream.
+
+The commit 0472bf06c6fd ("xhci: Prevent U1/U2 link pm states if exit
+latency is too long") was constraining the xhci code not to allow U1/U2
+sleep states if the latency to wake up from the U-states reached the
+service interval of an periodic endpoint. This fix was not taking into
+account that in case the quirk XHCI_INTEL_HOST is set, the wakeup time
+will be calculated and configured differently.
+
+It checks for u1_params.mel/u2_params.mel as a limit. But the code could
+decide to write another MEL into the hardware. This leads to broken
+cases where not enough bandwidth is available for other devices:
+
+usb 1-2: can't set config #1, error -28
+
+This patch is fixing that case by checking for timeout_ns after the
+wakeup time was calculated depending on the quirks.
+
+Fixes: 0472bf06c6fd ("xhci: Prevent U1/U2 link pm states if exit latency is too long")
+Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20201215193147.11738-1-m.grzeschik@pengutronix.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci.c | 24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -4646,19 +4646,19 @@ static u16 xhci_calculate_u1_timeout(str
+ {
+ unsigned long long timeout_ns;
+
++ if (xhci->quirks & XHCI_INTEL_HOST)
++ timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc);
++ else
++ timeout_ns = udev->u1_params.sel;
++
+ /* Prevent U1 if service interval is shorter than U1 exit latency */
+ if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) {
+- if (xhci_service_interval_to_ns(desc) <= udev->u1_params.mel) {
++ if (xhci_service_interval_to_ns(desc) <= timeout_ns) {
+ dev_dbg(&udev->dev, "Disable U1, ESIT shorter than exit latency\n");
+ return USB3_LPM_DISABLED;
+ }
+ }
+
+- if (xhci->quirks & XHCI_INTEL_HOST)
+- timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc);
+- else
+- timeout_ns = udev->u1_params.sel;
+-
+ /* The U1 timeout is encoded in 1us intervals.
+ * Don't return a timeout of zero, because that's USB3_LPM_DISABLED.
+ */
+@@ -4710,19 +4710,19 @@ static u16 xhci_calculate_u2_timeout(str
+ {
+ unsigned long long timeout_ns;
+
++ if (xhci->quirks & XHCI_INTEL_HOST)
++ timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc);
++ else
++ timeout_ns = udev->u2_params.sel;
++
+ /* Prevent U2 if service interval is shorter than U2 exit latency */
+ if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) {
+- if (xhci_service_interval_to_ns(desc) <= udev->u2_params.mel) {
++ if (xhci_service_interval_to_ns(desc) <= timeout_ns) {
+ dev_dbg(&udev->dev, "Disable U2, ESIT shorter than exit latency\n");
+ return USB3_LPM_DISABLED;
+ }
+ }
+
+- if (xhci->quirks & XHCI_INTEL_HOST)
+- timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc);
+- else
+- timeout_ns = udev->u2_params.sel;
+-
+ /* The U2 timeout is encoded in 256us intervals */
+ timeout_ns = DIV_ROUND_UP_ULL(timeout_ns, 256 * 1000);
+ /* If the necessary timeout value is bigger than what we can set in the
--- /dev/null
+From 372c93131998c0622304bed118322d2a04489e63 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan@kernel.org>
+Date: Mon, 14 Dec 2020 11:30:53 +0100
+Subject: USB: yurex: fix control-URB timeout handling
+
+From: Johan Hovold <johan@kernel.org>
+
+commit 372c93131998c0622304bed118322d2a04489e63 upstream.
+
+Make sure to always cancel the control URB in write() so that it can be
+reused after a timeout or spurious CMD_ACK.
+
+Currently any further write requests after a timeout would fail after
+triggering a WARN() in usb_submit_urb() when attempting to submit the
+already active URB.
+
+Reported-by: syzbot+e87ebe0f7913f71f2ea5@syzkaller.appspotmail.com
+Fixes: 6bc235a2e24a ("USB: add driver for Meywa-Denki & Kayac YUREX")
+Cc: stable <stable@vger.kernel.org> # 2.6.37
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/misc/yurex.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/usb/misc/yurex.c
++++ b/drivers/usb/misc/yurex.c
+@@ -495,6 +495,9 @@ static ssize_t yurex_write(struct file *
+ timeout = schedule_timeout(YUREX_WRITE_TIMEOUT);
+ finish_wait(&dev->waitq, &wait);
+
++ /* make sure URB is idle after timeout or (spurious) CMD_ACK */
++ usb_kill_urb(dev->cntl_urb);
++
+ mutex_unlock(&dev->io_mutex);
+
+ if (retval < 0) {
--- /dev/null
+From d1c5246e08eb64991001d97a3bd119c93edbc79a Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Wed, 2 Dec 2020 22:28:12 -0800
+Subject: x86/mm: Fix leak of pmd ptlock
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+commit d1c5246e08eb64991001d97a3bd119c93edbc79a upstream.
+
+Commit
+
+ 28ee90fe6048 ("x86/mm: implement free pmd/pte page interfaces")
+
+introduced a new location where a pmd was released, but neglected to
+run the pmd page destructor. In fact, this happened previously for a
+different pmd release path and was fixed by commit:
+
+ c283610e44ec ("x86, mm: do not leak page->ptl for pmd page tables").
+
+This issue was hidden until recently because the failure mode is silent,
+but commit:
+
+ b2b29d6d0119 ("mm: account PMD tables like PTE tables")
+
+turns the failure mode into this signature:
+
+ BUG: Bad page state in process lt-pmem-ns pfn:15943d
+ page:000000007262ed7b refcount:0 mapcount:-1024 mapping:0000000000000000 index:0x0 pfn:0x15943d
+ flags: 0xaffff800000000()
+ raw: 00affff800000000 dead000000000100 0000000000000000 0000000000000000
+ raw: 0000000000000000 ffff913a029bcc08 00000000fffffbff 0000000000000000
+ page dumped because: nonzero mapcount
+ [..]
+ dump_stack+0x8b/0xb0
+ bad_page.cold+0x63/0x94
+ free_pcp_prepare+0x224/0x270
+ free_unref_page+0x18/0xd0
+ pud_free_pmd_page+0x146/0x160
+ ioremap_pud_range+0xe3/0x350
+ ioremap_page_range+0x108/0x160
+ __ioremap_caller.constprop.0+0x174/0x2b0
+ ? memremap+0x7a/0x110
+ memremap+0x7a/0x110
+ devm_memremap+0x53/0xa0
+ pmem_attach_disk+0x4ed/0x530 [nd_pmem]
+ ? __devm_release_region+0x52/0x80
+ nvdimm_bus_probe+0x85/0x210 [libnvdimm]
+
+Given this is a repeat occurrence it seemed prudent to look for other
+places where this destructor might be missing and whether a better
+helper is needed. try_to_free_pmd_page() looks like a candidate, but
+testing with setting up and tearing down pmd mappings via the dax unit
+tests is thus far not triggering the failure.
+
+As for a better helper pmd_free() is close, but it is a messy fit
+due to requiring an @mm arg. Also, ___pmd_free_tlb() wants to call
+paravirt_tlb_remove_table() instead of free_page(), so open-coded
+pgtable_pmd_page_dtor() seems the best way forward for now.
+
+Debugged together with Matthew Wilcox <willy@infradead.org>.
+
+Fixes: 28ee90fe6048 ("x86/mm: implement free pmd/pte page interfaces")
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Tested-by: Yi Zhang <yi.zhang@redhat.com>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Cc: <stable@vger.kernel.org>
+Link: https://lkml.kernel.org/r/160697689204.605323.17629854984697045602.stgit@dwillia2-desk3.amr.corp.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/mm/pgtable.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/x86/mm/pgtable.c
++++ b/arch/x86/mm/pgtable.c
+@@ -829,6 +829,8 @@ int pud_free_pmd_page(pud_t *pud, unsign
+ }
+
+ free_page((unsigned long)pmd_sv);
++
++ pgtable_pmd_page_dtor(virt_to_page(pmd));
+ free_page((unsigned long)pmd);
+
+ return 1;
--- /dev/null
+From a0195f314a25582b38993bf30db11c300f4f4611 Mon Sep 17 00:00:00 2001
+From: Fenghua Yu <fenghua.yu@intel.com>
+Date: Thu, 17 Dec 2020 14:31:19 -0800
+Subject: x86/resctrl: Don't move a task to the same resource group
+
+From: Fenghua Yu <fenghua.yu@intel.com>
+
+commit a0195f314a25582b38993bf30db11c300f4f4611 upstream.
+
+Shakeel Butt reported in [1] that a user can request a task to be moved
+to a resource group even if the task is already in the group. It just
+wastes time to do the move operation which could be costly to send IPI
+to a different CPU.
+
+Add a sanity check to ensure that the move operation only happens when
+the task is not already in the resource group.
+
+[1] https://lore.kernel.org/lkml/CALvZod7E9zzHwenzf7objzGKsdBmVwTgEJ0nPgs0LUFU3SN5Pw@mail.gmail.com/
+
+Fixes: e02737d5b826 ("x86/intel_rdt: Add tasks files")
+Reported-by: Shakeel Butt <shakeelb@google.com>
+Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
+Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Reviewed-by: Tony Luck <tony.luck@intel.com>
+Cc: stable@vger.kernel.org
+Link: https://lkml.kernel.org/r/962ede65d8e95be793cb61102cca37f7bb018e66.1608243147.git.reinette.chatre@intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kernel/cpu/resctrl/rdtgroup.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
++++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+@@ -546,6 +546,13 @@ static void update_task_closid_rmid(stru
+ static int __rdtgroup_move_task(struct task_struct *tsk,
+ struct rdtgroup *rdtgrp)
+ {
++ /* If the task is already in rdtgrp, no need to move the task. */
++ if ((rdtgrp->type == RDTCTRL_GROUP && tsk->closid == rdtgrp->closid &&
++ tsk->rmid == rdtgrp->mon.rmid) ||
++ (rdtgrp->type == RDTMON_GROUP && tsk->rmid == rdtgrp->mon.rmid &&
++ tsk->closid == rdtgrp->mon.parent->closid))
++ return 0;
++
+ /*
+ * Set the task's closid/rmid before the PQR_ASSOC MSR can be
+ * updated by them.
--- /dev/null
+From ae28d1aae48a1258bd09a6f707ebb4231d79a761 Mon Sep 17 00:00:00 2001
+From: Fenghua Yu <fenghua.yu@intel.com>
+Date: Thu, 17 Dec 2020 14:31:18 -0800
+Subject: x86/resctrl: Use an IPI instead of task_work_add() to update PQR_ASSOC MSR
+
+From: Fenghua Yu <fenghua.yu@intel.com>
+
+commit ae28d1aae48a1258bd09a6f707ebb4231d79a761 upstream.
+
+Currently, when moving a task to a resource group the PQR_ASSOC MSR is
+updated with the new closid and rmid in an added task callback. If the
+task is running, the work is run as soon as possible. If the task is not
+running, the work is executed later in the kernel exit path when the
+kernel returns to the task again.
+
+Updating the PQR_ASSOC MSR as soon as possible on the CPU a moved task
+is running is the right thing to do. Queueing work for a task that is
+not running is unnecessary (the PQR_ASSOC MSR is already updated when
+the task is scheduled in) and causing system resource waste with the way
+in which it is implemented: Work to update the PQR_ASSOC register is
+queued every time the user writes a task id to the "tasks" file, even if
+the task already belongs to the resource group.
+
+This could result in multiple pending work items associated with a
+single task even if they are all identical and even though only a single
+update with most recent values is needed. Specifically, even if a task
+is moved between different resource groups while it is sleeping then it
+is only the last move that is relevant but yet a work item is queued
+during each move.
+
+This unnecessary queueing of work items could result in significant
+system resource waste, especially on tasks sleeping for a long time.
+For example, as demonstrated by Shakeel Butt in [1] writing the same
+task id to the "tasks" file can quickly consume significant memory. The
+same problem (wasted system resources) occurs when moving a task between
+different resource groups.
+
+As pointed out by Valentin Schneider in [2] there is an additional issue
+with the way in which the queueing of work is done in that the task_struct
+update is currently done after the work is queued, resulting in a race with
+the register update possibly done before the data needed by the update is
+available.
+
+To solve these issues, update the PQR_ASSOC MSR in a synchronous way
+right after the new closid and rmid are ready during the task movement,
+only if the task is running. If a moved task is not running nothing
+is done since the PQR_ASSOC MSR will be updated next time the task is
+scheduled. This is the same way used to update the register when tasks
+are moved as part of resource group removal.
+
+[1] https://lore.kernel.org/lkml/CALvZod7E9zzHwenzf7objzGKsdBmVwTgEJ0nPgs0LUFU3SN5Pw@mail.gmail.com/
+[2] https://lore.kernel.org/lkml/20201123022433.17905-1-valentin.schneider@arm.com
+
+ [ bp: Massage commit message and drop the two update_task_closid_rmid()
+ variants. ]
+
+Fixes: e02737d5b826 ("x86/intel_rdt: Add tasks files")
+Reported-by: Shakeel Butt <shakeelb@google.com>
+Reported-by: Valentin Schneider <valentin.schneider@arm.com>
+Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
+Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Reviewed-by: Tony Luck <tony.luck@intel.com>
+Reviewed-by: James Morse <james.morse@arm.com>
+Reviewed-by: Valentin Schneider <valentin.schneider@arm.com>
+Cc: stable@vger.kernel.org
+Link: https://lkml.kernel.org/r/17aa2fb38fc12ce7bb710106b3e7c7b45acb9e94.1608243147.git.reinette.chatre@intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kernel/cpu/resctrl/rdtgroup.c | 112 ++++++++++++---------------------
+ 1 file changed, 43 insertions(+), 69 deletions(-)
+
+--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
++++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+@@ -525,89 +525,63 @@ static void rdtgroup_remove(struct rdtgr
+ kfree(rdtgrp);
+ }
+
+-struct task_move_callback {
+- struct callback_head work;
+- struct rdtgroup *rdtgrp;
+-};
+-
+-static void move_myself(struct callback_head *head)
++static void _update_task_closid_rmid(void *task)
+ {
+- struct task_move_callback *callback;
+- struct rdtgroup *rdtgrp;
+-
+- callback = container_of(head, struct task_move_callback, work);
+- rdtgrp = callback->rdtgrp;
+-
+ /*
+- * If resource group was deleted before this task work callback
+- * was invoked, then assign the task to root group and free the
+- * resource group.
++ * If the task is still current on this CPU, update PQR_ASSOC MSR.
++ * Otherwise, the MSR is updated when the task is scheduled in.
+ */
+- if (atomic_dec_and_test(&rdtgrp->waitcount) &&
+- (rdtgrp->flags & RDT_DELETED)) {
+- current->closid = 0;
+- current->rmid = 0;
+- rdtgroup_remove(rdtgrp);
+- }
+-
+- if (unlikely(current->flags & PF_EXITING))
+- goto out;
+-
+- preempt_disable();
+- /* update PQR_ASSOC MSR to make resource group go into effect */
+- resctrl_sched_in();
+- preempt_enable();
++ if (task == current)
++ resctrl_sched_in();
++}
+
+-out:
+- kfree(callback);
++static void update_task_closid_rmid(struct task_struct *t)
++{
++ if (IS_ENABLED(CONFIG_SMP) && task_curr(t))
++ smp_call_function_single(task_cpu(t), _update_task_closid_rmid, t, 1);
++ else
++ _update_task_closid_rmid(t);
+ }
+
+ static int __rdtgroup_move_task(struct task_struct *tsk,
+ struct rdtgroup *rdtgrp)
+ {
+- struct task_move_callback *callback;
+- int ret;
+-
+- callback = kzalloc(sizeof(*callback), GFP_KERNEL);
+- if (!callback)
+- return -ENOMEM;
+- callback->work.func = move_myself;
+- callback->rdtgrp = rdtgrp;
+-
+ /*
+- * Take a refcount, so rdtgrp cannot be freed before the
+- * callback has been invoked.
++ * Set the task's closid/rmid before the PQR_ASSOC MSR can be
++ * updated by them.
++ *
++ * For ctrl_mon groups, move both closid and rmid.
++ * For monitor groups, can move the tasks only from
++ * their parent CTRL group.
+ */
+- atomic_inc(&rdtgrp->waitcount);
+- ret = task_work_add(tsk, &callback->work, TWA_RESUME);
+- if (ret) {
+- /*
+- * Task is exiting. Drop the refcount and free the callback.
+- * No need to check the refcount as the group cannot be
+- * deleted before the write function unlocks rdtgroup_mutex.
+- */
+- atomic_dec(&rdtgrp->waitcount);
+- kfree(callback);
+- rdt_last_cmd_puts("Task exited\n");
+- } else {
+- /*
+- * For ctrl_mon groups move both closid and rmid.
+- * For monitor groups, can move the tasks only from
+- * their parent CTRL group.
+- */
+- if (rdtgrp->type == RDTCTRL_GROUP) {
+- tsk->closid = rdtgrp->closid;
++
++ if (rdtgrp->type == RDTCTRL_GROUP) {
++ tsk->closid = rdtgrp->closid;
++ tsk->rmid = rdtgrp->mon.rmid;
++ } else if (rdtgrp->type == RDTMON_GROUP) {
++ if (rdtgrp->mon.parent->closid == tsk->closid) {
+ tsk->rmid = rdtgrp->mon.rmid;
+- } else if (rdtgrp->type == RDTMON_GROUP) {
+- if (rdtgrp->mon.parent->closid == tsk->closid) {
+- tsk->rmid = rdtgrp->mon.rmid;
+- } else {
+- rdt_last_cmd_puts("Can't move task to different control group\n");
+- ret = -EINVAL;
+- }
++ } else {
++ rdt_last_cmd_puts("Can't move task to different control group\n");
++ return -EINVAL;
+ }
+ }
+- return ret;
++
++ /*
++ * Ensure the task's closid and rmid are written before determining if
++ * the task is current that will decide if it will be interrupted.
++ */
++ barrier();
++
++ /*
++ * By now, the task's closid and rmid are set. If the task is current
++ * on a CPU, the PQR_ASSOC MSR needs to be updated to make the resource
++ * group go into effect. If the task is not current, the MSR will be
++ * updated when the task is scheduled in.
++ */
++ update_task_closid_rmid(tsk);
++
++ return 0;
+ }
+
+ static bool is_closid_match(struct task_struct *t, struct rdtgroup *r)